Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ permissions:
contents: read

jobs:
package:
runs-on: ubuntu-latest
package-platform:
name: package (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout repository
uses: actions/checkout@v7
Expand All @@ -24,9 +29,30 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Format check
run: npm run fmt -- --check

- name: Run package gate
run: npm run check

- name: Upload implementation coverage
if: always()
uses: actions/upload-artifact@v7
with:
name: orm-coverage-${{ matrix.os }}
path: coverage
if-no-files-found: warn

package:
needs: package-platform
if: always()
runs-on: ubuntu-latest
steps:
- name: Require every platform package gate
env:
PACKAGE_RESULT: ${{ needs.package-platform.result }}
run: test "$PACKAGE_RESULT" = success

postgres-contract:
name: PostgreSQL ${{ matrix.postgres }}
runs-on: ubuntu-latest
Expand Down
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Changelog

## Unreleased

### Breaking

- Curate the root to 68 names and the tooling subpath to its single runDatabaseCli
bridge. Remove 54 named exports and sql.key. Replace direct client construction
with defineDatabase/open; use sql.identifier/literal/unsafe and defineQuery for
their canonical contracts. Every removed name has migration guidance in
docs/0.5.0-api.md. Retain all five export-map keys and optional PostgreSQL peers.

### Added

- Optional DatabaseAdapter.executeScript for complete migration scripts; custom
drivers without it keep the existing execute fallback. PostgreSQL and SQLite
implementations execute driver-owned scripts without splitting semicolons.
- Exact packed runtime/declaration checks, removed-import and private-path checks,
optional-peer isolation/minimum installs, and real-adapter value parity probes.

### Fixed

- SQLite migration execution no longer drops all statements after the first.
- PostgreSQL migration scripts no longer fail when the driver returns multiple
result sets.
- Failed SQLite rollback closes and quarantines the adapter, rolls back remaining
writes and releases shared-file ownership before a new connection recovers.
- PostgreSQL failed rollback/advisory unlock discards poisoned pooled connections
while preserving the primary operation error; failed statement deallocation
still releases and discards the owned client.
- Update compatible development tooling to audited versions and add TypeScript 6 compiler-API audits alongside the TypeScript 7 gate and pin
the matching coverage provider.

- Load CLI database entries through file URLs so Windows drive paths and reserved
URL characters in project directories remain filesystem paths.

- Transaction-owned migration plan/apply/resolve handles now reject use after
their transaction ends, before any SQL can run on a released connection.

### Remaining release gate

- PostgreSQL shadow reset/introspection/query description are incomplete in the
advertised generation/validation workflow (#55). No ORM 0.5.0 readiness or
publication claim is made until that real workflow is qualified.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ their scalar value. Writes return status by default. Ordinary promises are the
non-atomic coordination mechanism; use `db.transaction(...)` when operations
must be atomic. Nested transactions use savepoints, and a transaction client
throws after its callback completes. If rollback cleanup itself fails, the
original callback error remains the error surfaced to the caller.
original callback error remains the error surfaced to the caller. Failed
PostgreSQL cleanup discards the pooled connection; failed SQLite rollback
quarantines the adapter and closes its database. If physical close fails, explicit
close retries cleanup. Open a new SQLite adapter before retrying application work.

`escapeLikePattern()` escapes `\\`, `%`, and `_` for literal-text searches.
`like()` and `ilike()` bind the pattern and emit the matching `ESCAPE '\\'`
Expand All @@ -95,6 +98,11 @@ askr database migration plan
askr database migration apply --yes
```

The PostgreSQL generated-artifact workflow is a 0.5.0 release blocker tracked in
[#55](https://github.com/askrjs/askr-orm/issues/55): the shipped shadow reset,
introspection and description methods are incomplete. Ordinary runtime access
and application of an already bundled migration manifest are covered separately.

Generation replays checksummed, forward-only SQL against the shadow database
before accepting it. It writes migration SQL plus one committed
`database/generated.ts` artifact containing schema identity, migration
Expand All @@ -109,3 +117,10 @@ SQLite uses Node's synchronous `node:sqlite` API behind a re-entrant async
connection queue. Transactions and streams hold the connection; cancellation
is checked between streamed rows, but a synchronous statement already running
cannot be interrupted.

## 0.5.0 review

The [API decisions](docs/0.5.0-api.md) record every retained and removed name and
its migration. The [hardening report](docs/0.5.0-hardening.md) distinguishes
regression fixes, executed characterization and the remaining release blocker.
The package version remains 0.4.0 until the coordinated candidate is prepared.
13 changes: 11 additions & 2 deletions benchmarks/runtime.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { performance } from "node:perf_hooks";
import { createDatabaseClient, eq, table, text, uuid } from "../dist/index.js";
import { defineDatabase, eq, table, text, uuid } from "../dist/index.js";

const gate = process.argv.includes("--gate");
const iterations = 20_000;
Expand All @@ -23,7 +23,16 @@ const users = table("users", {
email: text().notNull(),
});
const adapter = new BenchmarkAdapter();
const db = createDatabaseClient({ users }, adapter);
const db = await defineDatabase({
tables: { users },
driver: {
dialect: "postgres",
open: async () => adapter,
shadow: async () => {
throw new Error("Benchmark does not use tooling.");
},
},
}).open();

async function measure(callback) {
const started = performance.now();
Expand Down
Loading
Loading