diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 1b4a8280..b1c25f62 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,5 +1,6 @@ {"id":"effect-qb-dn3.1","title":"P0 migrate Effect dependencies and schema API surface","description":"Smallest coherent implementation slice. Align workspace/package dependencies to effect@4.0.0-beta.66 and matching v4 packages, remove @effect/experimental where replaced, and perform the mechanical Schema API migration called out in docs/effect-v4-opportunities.md without intentional behavior changes.","acceptance_criteria":"Effect package versions are aligned to the observed v4 beta line; v3 Schema call shapes listed in the opportunity doc are migrated; README/type-test examples are updated as needed; behavior tests covering risky runtime schema/json paths still pass; bun run test:types, bun test, and relevant tsgo checks are run or blockers documented.","notes":"Status: in_progress. Starting with repo inspection and focused regression/type coverage around current Schema API and JSON path inference before the mechanical v4 dependency/API migration.\nBaseline before migration: focused Bun behavior tests passed for runtime-value/json/table/executor; tsgo type-test project passed. Commands: bun --config ./bunfig.test.toml test test/internal/behavior/runtime-value.behavior.test.ts test/public/behavior/json.behavior.test.ts test/internal/behavior/table.test.ts test/public/behavior/executor.behavior.test.ts; bunx tsgo -p tsconfig.type-tests.json.\nImplemented and verified in the first migration slice. Dependencies aligned to effect@4.0.0-beta.66 and matching v4 driver/platform packages; removed @effect/experimental, @effect/sql, @effect/cli, and @effect/platform where v4 unstable exports replaced them; migrated mechanical Schema API changes and README/type examples. Checks passed: bunx tsgo -p tsconfig.type-tests.json; bun --config ./bunfig.test.toml test test/internal/behavior/runtime-value.behavior.test.ts test/public/behavior/json.behavior.test.ts test/internal/behavior/table.test.ts test/public/behavior/executor.behavior.test.ts test/public/behavior/mysql-errors.behavior.test.ts test/public/behavior/postgres-errors.behavior.test.ts; bun run test:types; bun run build; bun run test:pack; bun run test.","status":"closed","priority":0,"issue_type":"task","owner":"relsunkaev@outlook.com","created_at":"2026-05-13T02:18:18Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-05-13T02:41:33Z","started_at":"2026-05-13T02:20:14Z","closed_at":"2026-05-13T02:41:33Z","close_reason":"P0 dependency and mechanical Schema API migration implemented; full type, build, pack, focused behavior, and full Bun tests passed.","labels":["effect-v4","migration","schema"],"dependencies":[{"issue_id":"effect-qb-dn3.1","depends_on_id":"effect-qb-dn3","type":"parent-child","created_at":"2026-05-12T19:18:18Z","created_by":"Ramazan Elsunkaev","metadata":"{}"}],"dependency_count":0,"dependent_count":6,"comment_count":0} {"id":"effect-qb-dn3","title":"Effect v4 migration epic","description":"Parent epic for the Effect v4 migration work described in docs/effect-v4-opportunities.md. Scope includes dependency alignment, mechanical Schema API migration, VariantSchema replacement, v4 SQL core adoption, SqlSchema validation, optional v4 codecs, row decode error improvements, JSON schema inference review, and CLI/platform packaging.","acceptance_criteria":"All child beads map to docs/effect-v4-opportunities.md opportunities; every opportunity is implemented, explicitly deferred, or blocked with a concrete reason; relevant tests/type checks/lint checks pass; coherent increments are committed.","notes":"Source of truth: docs/effect-v4-opportunities.md checked against effect@4.0.0-beta.66. Assumption: this branch is the v4 line, so no Effect 3 compatibility shim is required unless a child bead discovers a concrete compatibility requirement.","status":"open","priority":0,"issue_type":"epic","owner":"relsunkaev@outlook.com","created_at":"2026-05-13T02:18:02Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-05-13T02:18:02Z","labels":["effect-v4","migration"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"id":"effect-qb-xzx","title":"Release v0.20.0","description":"Publish the verified Effect v4 beta.98 code as the next stable zerover release for effect-qb and effect-db, keeping Effect dependencies pinned to 4.0.0-beta.98 and promoting npm latest to 0.20.0.","acceptance_criteria":"Release notes cover the complete stable delta since v0.19.0; package and CLI versions are 0.20.0 while Effect dependencies remain 4.0.0-beta.98; build, unit, type, pack, and integration gates pass; v0.20.0 publishes both packages under latest with signed provenance; GitHub marks v0.20.0 as Latest; release evidence is recorded and the issue is closed.","status":"in_progress","priority":1,"issue_type":"task","assignee":"Ramazan Elsunkaev","owner":"relsunkaev@outlook.com","created_at":"2026-07-13T19:53:35Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-07-13T19:53:40Z","started_at":"2026-07-13T19:53:40Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"effect-qb-vt7","title":"Classify beta GitHub releases as prereleases","description":"The publish workflow maps prerelease versions to the npm beta dist-tag but unconditionally creates a normal GitHub release, causing beta versions to become Latest. Derive GitHub release classification from the same npm-tag decision and correct v4.0.0-beta.98 metadata.","acceptance_criteria":"Publish workflow passes prerelease=true and latest=false for hyphenated versions, stable versions remain latest releases, actionlint passes, and v4.0.0-beta.98 is shown as a GitHub prerelease rather than Latest.","status":"closed","priority":1,"issue_type":"bug","assignee":"Ramazan Elsunkaev","owner":"relsunkaev@outlook.com","created_at":"2026-07-13T19:47:12Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-07-13T19:50:37Z","started_at":"2026-07-13T19:47:17Z","closed_at":"2026-07-13T19:50:37Z","close_reason":"Publish workflow now classifies npm beta releases as GitHub prereleases and explicitly clears the make_latest pointer; actionlint passes; beta.92 and beta.98 metadata verified as prerelease with v0.17.0 restored as latest.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"effect-qb-lbx","title":"Release v4.0.0-beta.98","description":"Upgrade the Effect v4 dependency stack from beta.92 to beta.98, cut matching effect-qb and effect-db beta.98 packages, publish through the repository release workflows, and verify npm plus GitHub release state.","acceptance_criteria":"All Effect packages and peer dependencies resolve to 4.0.0-beta.98; build, unit, type, pack, and integration gates pass; v4.0.0-beta.98 is tagged and published for effect-qb/effect-db under the beta dist-tag; the GitHub release and publish workflow succeed.","status":"closed","priority":1,"issue_type":"task","assignee":"Ramazan Elsunkaev","owner":"relsunkaev@outlook.com","created_at":"2026-07-13T19:35:31Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-07-13T19:45:11Z","started_at":"2026-07-13T19:36:09Z","closed_at":"2026-07-13T19:45:11Z","close_reason":"Published effect-qb and effect-db 4.0.0-beta.98 via tag v4.0.0-beta.98; PR #6 and publish run 29279588367 succeeded; npm beta tags and signed provenance verified.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"effect-qb-bpa","title":"Release v4.0.0-beta.92","description":"Cut the requested v4.0.0-beta.92 release from main, including version bump, changelog, tag, publish workflow, and verification of npm/GitHub release state.","notes":"Release prep is complete at v4.0.0-beta.92. Release commit 46adff1 and tag v4.0.0-beta.92 were pushed to main. Local gates passed: bun run build; bun run test; bun run test:types; bun run test:pack; bunx npm pack --dry-run; bun run test:integration; bun run test:integration:datatypes. Plain 'bun test' still fails through known broad-runner/stale-test issue effect-qb-lnu and was not used as release proof. Publish workflow run 28472253061 failed at Publish querybuilder to npm with 404 Not Found for https://registry.npmjs.org/effect-qb; effect-qb@4.0.0-beta.92 and effect-db@4.0.0-beta.92 are not visible on npm, and the GitHub release was skipped.","status":"closed","priority":1,"issue_type":"task","assignee":"Ramazan Elsunkaev","owner":"relsunkaev@outlook.com","created_at":"2026-06-30T19:57:50Z","created_by":"Ramazan Elsunkaev","updated_at":"2026-07-13T18:44:26Z","started_at":"2026-06-30T19:58:19Z","closed_at":"2026-07-13T18:44:26Z","close_reason":"v4.0.0-beta.92 is published on npm for both packages, beta dist-tags point to beta.92, GitHub release exists, and repaired Publish runs 29275561438 and 29275567580 passed.","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/CHANGELOG.md b/CHANGELOG.md index b9b69e00..dac3ec0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,94 @@ All notable changes to this project are documented here. ## Unreleased +## 0.20.0 - 2026-07-13 + +### Breaking Changes + +- feat(querybuilder)!: remove renderer make casing option +- feat(querybuilder)!: require callback table options +- feat(querybuilder)!: add path-aware JSON traversal +- feat(querybuilder)!: remove JSON asText aliases +- feat(querybuilder)!: consolidate cast surface +- feat(querybuilder)!: separate standard and dialect type helpers +- feat(querybuilder)!: remove executor withSavepoint helper + +### Features + +- feat: validate effect-db sql rows with SqlSchema +- feat: preserve schema issues in row decode errors +- feat(querybuilder): add table option namespaces +- feat(querybuilder): consolidate dialect helper exports +- feat(querybuilder): support row-local check callbacks +- feat(querybuilder): type-check conflict arbiters +- feat(querybuilder): enforce datatype matrix coverage + +### Fixes + +- fix: preserve json path schema transforms +- fix(database): emit package declarations +- fix(querybuilder): allow schema-backed jsonb scalar casts +- fix(querybuilder): render portable mysql datatypes as executable SQL +- fix(querybuilder): stabilize curried Cast.to inference; bump tsgo +- fix(database): canonicalize int and dec/decimal postgres type aliases +- fix(database): treat explicit noAction referential actions as the default +- fix(ci): publish npm packages with trusted authentication +- fix(release): consume unreleased changelog entries +- fix(release): classify beta GitHub releases +- fix(release): select stable changelog boundary + +### Docs + +- docs: cover opt-in Effect v4 schema codecs +- docs: record schema model migration decision +- docs: remove broken database beta guidance +- docs: update jsonb readme examples +- docs(readme): clarify type and json examples +- docs(readme): document json paths and cast type safety +- docs(readme): document conflict target type safety +- docs(readme): restructure code examples for clarity +- docs(readme): rewrite casting example, showcase more query features +- docs(readme): sharpen example salience +- docs(readme): show scoped executor transactions +- docs(readme): update beta install command + +### Tests + +- test: repair stale suite for effect 4.0.0-beta.92 +- test(pack): use declared Effect peer version + +### CI + +- ci: add beta package deprecation path +- ci(release): publish querybuilder with bun + +### Chores + +- chore: migrate Effect dependency surface to v4 beta +- chore(release): prepare beta channel +- chore(release): v4.0.0-beta.66 +- chore(beads): close readme check callback task +- chore(beads): record JSON type-safety epic +- chore: track @typescript/native-preview via the beta tag +- chore(beads): track effect v4 merge +- chore(beads): track v4 beta release +- chore(release): v4.0.0-beta.67 +- chore(beads): record beta release publish blocker +- chore(effect): update beta dependencies to beta.92 +- chore(beads): track beta.92 release +- chore(release): v4.0.0-beta.92 +- chore(beads): record beta.92 publish blocker +- chore(beads): close beta.92 release +- chore(effect): update beta dependencies to beta.98 +- chore(release): v4.0.0-beta.98 +- chore(beads): close beta.98 release +- chore(beads): track v0.20.0 release + +### Other + +- bd init: initialize beads issue tracking +- Add datatype matrix coverage tests + ## 4.0.0-beta.98 - 2026-07-13 ### Fixes diff --git a/bun.lock b/bun.lock index e6b60c98..c7b5723d 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/database": { "name": "effect-db", - "version": "4.0.0-beta.98", + "version": "0.20.0", "bin": { "effectdb": "./dist/cli.js", }, @@ -37,7 +37,7 @@ }, "packages/querybuilder": { "name": "effect-qb", - "version": "4.0.0-beta.98", + "version": "0.20.0", "dependencies": { "pgsql-ast-parser": "^12.0.2", }, diff --git a/package.json b/package.json index 7107f536..37cf9900 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "effect-qb-workspace", - "version": "4.0.0-beta.98", + "version": "0.20.0", "type": "module", "workspaces": [ "packages/*" diff --git a/packages/database/package.json b/packages/database/package.json index f5d996e7..c9832eb4 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "effect-db", - "version": "4.0.0-beta.98", + "version": "0.20.0", "type": "module", "license": "MIT", "repository": { diff --git a/packages/database/src/cli.ts b/packages/database/src/cli.ts index 1ef7602c..8f369ee6 100644 --- a/packages/database/src/cli.ts +++ b/packages/database/src/cli.ts @@ -398,7 +398,7 @@ const root = Command.make("effectdb", {}, () => Effect.void).pipe( ) const cli = Command.run(root, { - version: "4.0.0-beta.98" + version: "0.20.0" }) cli.pipe( diff --git a/packages/querybuilder/package.json b/packages/querybuilder/package.json index c60e3b22..ab4b28e0 100644 --- a/packages/querybuilder/package.json +++ b/packages/querybuilder/package.json @@ -1,6 +1,6 @@ { "name": "effect-qb", - "version": "4.0.0-beta.98", + "version": "0.20.0", "type": "module", "license": "MIT", "repository": { diff --git a/scripts/release.ts b/scripts/release.ts index e435a40b..e512690e 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -154,8 +154,48 @@ const getLatestTag = async (): Promise => { return result.exitCode === 0 ? result.stdout.trim() : null } -const getLatestReleaseBoundary = async (): Promise => { - const latestTag = await getLatestTag() +const getReleaseTags = async (): Promise> => { + const result = await run([ + "git", + "tag", + "--merged", + "HEAD", + "--sort=-version:refname", + "--list", + "v[0-9]*" + ]) + + return result.stdout.split("\n").map((tag) => tag.trim()).filter(Boolean) +} + +export const selectReleaseTag = ( + tags: ReadonlyArray, + explicitVersion: string | null +): string | null => { + if (explicitVersion === null) { + return tags[0] ?? null + } + + const target = parseSemver(explicitVersion) + const parsedTags = tags.map((tag) => ({ tag, version: parseSemver(tag.slice(1)) })) + const latestStable = parsedTags.find(({ version }) => version.prerelease === null)?.tag ?? null + + if (target.prerelease === null) { + return latestStable + } + + return parsedTags.find(({ version }) => + version.prerelease !== null && + version.major === target.major && + version.minor === target.minor && + version.patch === target.patch + )?.tag ?? latestStable +} + +const getLatestReleaseBoundary = async (explicitVersion: Semver | null): Promise => { + const latestTag = explicitVersion === null + ? await getLatestTag() + : selectReleaseTag(await getReleaseTags(), formatSemver(explicitVersion)) if (latestTag) { const hashResult = await run(["git", "rev-list", "-n", "1", latestTag]) @@ -347,7 +387,8 @@ const main = async () => { const args = new Set(argv) const push = args.has("--push") const dryRun = args.has("--dry-run") - const explicitVersion = getArgValue(argv, "--version") + const explicitVersionValue = getArgValue(argv, "--version") + const explicitVersion = explicitVersionValue === null ? null : parseSemver(explicitVersionValue) const status = await run(["git", "status", "--short"]) if (status.stdout.trim()) { @@ -355,7 +396,7 @@ const main = async () => { } const packageVersion = await getPackageVersion() - const boundary = await getLatestReleaseBoundary() + const boundary = await getLatestReleaseBoundary(explicitVersion) const commits = await getCommits(boundary ? `${boundary.hash}..HEAD` : "HEAD") if (boundary && commits.length === 0) { @@ -366,7 +407,7 @@ const main = async () => { const bump = determineBump(commits, baseVersion.major) const nextVersion = explicitVersion === null ? bumpSemver(baseVersion, bump) - : parseSemver(explicitVersion) + : explicitVersion const changelogSection = renderChangelogSection(formatSemver(nextVersion), commits) console.log(`Release version: ${formatSemver(nextVersion)}`) diff --git a/test/internal/behavior/release-script.behavior.test.ts b/test/internal/behavior/release-script.behavior.test.ts index 217f08c2..cd2e6a33 100644 --- a/test/internal/behavior/release-script.behavior.test.ts +++ b/test/internal/behavior/release-script.behavior.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test" -import { insertChangelogSection } from "../../../scripts/release.ts" +import { insertChangelogSection, selectReleaseTag } from "../../../scripts/release.ts" test("release changelog consumes unreleased entries", () => { const existing = [ @@ -32,3 +32,23 @@ test("release changelog consumes unreleased entries", () => { "" ].join("\n")) }) + +test("stable releases use the latest stable tag as their boundary", () => { + expect(selectReleaseTag([ + "v4.0.0-beta.98", + "v4.0.0-beta.92", + "v0.19.0", + "v0.18.0" + ], "0.20.0")).toBe("v0.19.0") +}) + +test("prereleases continue their version line before falling back to stable", () => { + const tags = [ + "v4.0.0-beta.98", + "v4.0.0-beta.92", + "v0.19.0" + ] + + expect(selectReleaseTag(tags, "4.0.0-beta.99")).toBe("v4.0.0-beta.98") + expect(selectReleaseTag(tags, "0.20.0-beta.1")).toBe("v0.19.0") +})