feat(8.0): id-normalization (#18) + aggregation min/max delete-safety + RC-safe release
- id-normalization (#18): `brain.newId()` (UUID v7) + v7 default ids; non-UUID string ids are transparently normalized to a stable UUID v5 on creation AND every lookup — get/update/remove, relate(from,to), related, find({connected}), getMany, removeMany, the transact op-handler, and db.with() overlays — with the caller's original key preserved under `_originalId`. The engine only ever sees a UUID; real UUIDs pass through untouched. universal/uuid.ts gains v5/v7/isUUID + BRAINY_ID_NAMESPACE; new utils/idNormalization.ts (coerceNewEntityId / resolveEntityId). - aggregation min/max delete-safety: `queryAggregate` no longer leaves a stale min/max after deleting the current extreme — min/max now track a value multiset and recompute in-memory (no entity scan; that scan was the prior delete-then-hang a consumer reported). Other metrics were already exact across deletes. Regression test proves resolve-after-delete + correct new min/max. - release.sh RC-safe: explicit version arg, prerelease detection (npm `--tag rc` + GitHub `--prerelease`), full `test:ci` gate (unit + integration), current-branch push, npm-access verification after publish. - native-engine references point at `@soulcraft/cor` (8.0's partner) in user-facing strings/docs. Unit 1461/0 · integration 599/0 · tsc clean.
This commit is contained in:
parent
606445cd61
commit
d02e522a3e
14 changed files with 943 additions and 100 deletions
|
|
@ -27,8 +27,18 @@ for arg in "$@"; do
|
|||
esac
|
||||
done
|
||||
|
||||
# An explicit version (e.g. "8.0.0-rc.1") may be passed in place of patch/minor/major.
|
||||
EXPLICIT_VERSION=""
|
||||
if [[ "$RELEASE_TYPE" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
|
||||
EXPLICIT_VERSION="$RELEASE_TYPE"
|
||||
fi
|
||||
|
||||
# Release on whatever branch we're on — RC lines live on feature branches, not main.
|
||||
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||
|
||||
echo -e "${BLUE}🚀 Brainy Release Script${NC}"
|
||||
echo -e "${BLUE}Release type: ${RELEASE_TYPE}${NC}\n"
|
||||
echo -e "${BLUE}Release type: ${RELEASE_TYPE}${NC}"
|
||||
echo -e "${BLUE}Branch: ${CURRENT_BRANCH}${NC}\n"
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo -e "${YELLOW}⚠️ DRY RUN MODE - No changes will be made${NC}\n"
|
||||
|
|
@ -57,7 +67,8 @@ echo -e "${GREEN}✅ Build successful${NC}\n"
|
|||
if [ "$SKIP_TESTS" = false ]; then
|
||||
echo -e "${BLUE}3️⃣ Running tests...${NC}"
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
npm test
|
||||
# Full CI gate: unit + integration (test:ci = test:ci-unit && test:ci-integration).
|
||||
npm run test:ci
|
||||
fi
|
||||
echo -e "${GREEN}✅ Tests passed${NC}\n"
|
||||
else
|
||||
|
|
@ -74,24 +85,41 @@ MAJOR="${VERSION_PARTS[0]}"
|
|||
MINOR="${VERSION_PARTS[1]}"
|
||||
PATCH="${VERSION_PARTS[2]}"
|
||||
|
||||
case $RELEASE_TYPE in
|
||||
major)
|
||||
NEW_VERSION="$((MAJOR + 1)).0.0"
|
||||
;;
|
||||
minor)
|
||||
NEW_VERSION="${MAJOR}.$((MINOR + 1)).0"
|
||||
;;
|
||||
patch)
|
||||
NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ Invalid release type: ${RELEASE_TYPE}${NC}"
|
||||
echo "Usage: ./scripts/release.sh [patch|minor|major] [--dry-run]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if [ -n "$EXPLICIT_VERSION" ]; then
|
||||
NEW_VERSION="$EXPLICIT_VERSION"
|
||||
else
|
||||
case $RELEASE_TYPE in
|
||||
major)
|
||||
NEW_VERSION="$((MAJOR + 1)).0.0"
|
||||
;;
|
||||
minor)
|
||||
NEW_VERSION="${MAJOR}.$((MINOR + 1)).0"
|
||||
;;
|
||||
patch)
|
||||
NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ Invalid release type: ${RELEASE_TYPE}${NC}"
|
||||
echo "Usage: ./scripts/release.sh [patch|minor|major|<explicit-version>] [--dry-run]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}New version: ${NEW_VERSION}${NC}\n"
|
||||
# A version with a hyphen (e.g. 8.0.0-rc.1) is a prerelease: publish under the 'rc'
|
||||
# dist-tag (NOT 'latest') and mark the GitHub release as a prerelease.
|
||||
PRERELEASE=false
|
||||
NPM_TAG="latest"
|
||||
if [[ "$NEW_VERSION" == *"-"* ]]; then
|
||||
PRERELEASE=true
|
||||
NPM_TAG="rc"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}New version: ${NEW_VERSION}${NC}"
|
||||
if [ "$PRERELEASE" = true ]; then
|
||||
echo -e "${YELLOW}⚠️ Prerelease → npm dist-tag '${NPM_TAG}', GitHub prerelease${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo -e "${YELLOW}DRY RUN: Would release version ${NEW_VERSION}${NC}"
|
||||
|
|
@ -149,17 +177,23 @@ echo -e "${GREEN}✅ Tag created${NC}\n"
|
|||
|
||||
# Step 9: Push to GitHub
|
||||
echo -e "${BLUE}8️⃣ Pushing to GitHub...${NC}"
|
||||
git push --follow-tags origin main
|
||||
git push --follow-tags origin "$CURRENT_BRANCH"
|
||||
echo -e "${GREEN}✅ Pushed to GitHub${NC}\n"
|
||||
|
||||
# Step 10: Publish to npm
|
||||
echo -e "${BLUE}9️⃣ Publishing to npm...${NC}"
|
||||
npm publish
|
||||
echo -e "${BLUE}9️⃣ Publishing to npm (dist-tag: ${NPM_TAG})...${NC}"
|
||||
npm publish --tag "$NPM_TAG"
|
||||
# Brainy is the only PUBLIC @soulcraft package — verify visibility after every publish.
|
||||
npm access get status @soulcraft/brainy || true
|
||||
echo -e "${GREEN}✅ Published to npm${NC}\n"
|
||||
|
||||
# Step 11: Create GitHub release
|
||||
echo -e "${BLUE}🔟 Creating GitHub release...${NC}"
|
||||
gh release create "v${NEW_VERSION}" --generate-notes
|
||||
if [ "$PRERELEASE" = true ]; then
|
||||
gh release create "v${NEW_VERSION}" --generate-notes --prerelease
|
||||
else
|
||||
gh release create "v${NEW_VERSION}" --generate-notes
|
||||
fi
|
||||
echo -e "${GREEN}✅ GitHub release created${NC}\n"
|
||||
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue