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
15 changes: 15 additions & 0 deletions .changeset/20595-driver-turso-provenance-anchors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@objectstack/driver-turso': patch
---

Provenance comments in `@objectstack/driver-turso` cite the commits that decided them, not tracker numbers that no longer resolve

Clause-②: no

Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub.
Each one now cites the commit in this repository's history that made the decision it describes. Some
of these docblocks sit on exported members, so the reworded text appears in the published `index.d.ts`
/ `index.d.mts`, and the comments esbuild keeps appear in the JavaScript output (`index.js` /
`index.mjs`); the sourcemaps do not change.

Comment only: no export, type, error code, status, message text or runtime behaviour changes.
6 changes: 3 additions & 3 deletions packages/drivers/driver-turso/src/remote-transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1642,7 +1642,7 @@ export class RemoteTransport {
}

/**
* [#14428] A miss answers `null` — the arm `IDataDriver.update()` declares
* [commit ca3fd4b1a] A miss answers `null` — the arm `IDataDriver.update()` declares
* (#13878), and the answer this driver's LOCAL face (`SqlDriver.update`,
* through `TursoDriver.update`'s `super` branch) has always given.
*
Expand Down Expand Up @@ -2598,7 +2598,7 @@ export class RemoteTransport {
*
* Both transports round-trip every `VALUE_ROUNDTRIP_CASES` value faithfully
* (`turso-value-roundtrip-conformance.test.ts`, both halves). They arrive
* there by different routes: #12380 made the local `Field.json` codec
* there by different routes: commit 4045b954d made the local `Field.json` codec
* injective, so the NUMERIC-affinity column is only ever handed an encoded
* form it has nothing to convert; this transport's own `serializeValue` /
* `mapRows` reach the same answer over a column where no conversion was
Expand All @@ -2609,7 +2609,7 @@ export class RemoteTransport {
* and a TEXT cell here, and `find()` answers `123` on both. That is the
* #11535 class in its quiet phase — two paths agreeing on every visible
* answer while standing on different ground. PR #12585's ablation is the
* loud phase: restoring the pre-#12380 SQLite `json` branch broke the two
* loud phase: restoring the SQLite `json` branch from before commit 4045b954d broke the two
* transports by DIFFERENT counts, diverging on `s_0123`, because only the
* local column had NUMERIC affinity to destroy a bare `'0123'` with.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.

/**
* [#16711] `TursoDriver.initObjects` — the override that shadowed a base-class
* [commit 7862fb711] `TursoDriver.initObjects` — the override that shadowed a base-class
* fix in a separately published package for five weeks.
*
* ## The defect this pins, which no gate scoped to `sql-driver.ts` could see
Expand All @@ -14,7 +14,7 @@
* - #4311 declared `tenancy` on `SqlDriver.initObjects` in August. From
* outside this package that fix did not exist: a fresh literal carrying
* `tenancy` was still TS2353 here, for five weeks, and nothing was red.
* - #16570's `indexes` fix would have escaped by the identical route.
* - Commit b72226f48's `indexes` fix would have escaped by the identical route.
*
* ⭐ And the type face was the ONLY thing refusing them. The remote arm below
* forwards the whole object through as `schema`
Expand Down Expand Up @@ -69,7 +69,7 @@ describe('TursoDriver.initObjects declares every key SqlDriver.initObjects does
const driver = await remoteDriver();
const T = 'os16711_turso_all';

// Fresh literal in argument position. Before #16711 this did not compile:
// Fresh literal in argument position. Before commit 7862fb711 this did not compile:
// `tenancy`, `indexes` and `lifecycle` were all TS2353 against this
// override's own narrower literal, while the base declared the first two.
await driver.initObjects([
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('TursoDriver.initObjects declares every key SqlDriver.initObjects does
});

/**
* ⭐ THE NEGATIVE CONTROL (#16711 验收口径 item 4). Each `@ts-expect-error` IS
* ⭐ THE NEGATIVE CONTROL (验收口径 item 4 of the card commit 7862fb711 closed). Each `@ts-expect-error` IS
* the assertion: `tsc` fails the file with TS2578 the moment the key starts
* being accepted, which is precisely what a relaxation to `any` or an index
* signature would do. Compile-time only, deliberately never called.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// #15267 — the `IDataDriver` doors `TursoDriver` OVERRIDES publish their
// declared return type, not `any`.
//
// The same shape #14438 fixed on this class's `update()` override, and for the
// The same shape commit 2200f8ec8 fixed on this class's `update()` override, and for the
// same reason it had to be fixed here rather than inherited: `TursoDriver`
// overrides `findOne`, `create`, `bulkCreate` and `execute` with its own
// explicit `Promise<any>` on each, so this package's published `.d.ts`
Expand Down Expand Up @@ -58,7 +58,7 @@
// `@objectstack/driver-sql` narrowing does not reach a consumer holding a
// `TursoDriver`.
//
// [#17690] Three more overridden doors join the driver half — `find`,
// [commit be5c60291] Three more overridden doors join the driver half — `find`,
// `upsert` and `bulkUpdate` — plus (at the time) `RemoteTransport.beginTransaction`,
// which lived in this package and in this same tsc program. All four nested their
// `any` inside a wider type (`Promise<any[]>`, `Promise<Record<string, any>>`,
Expand Down Expand Up @@ -114,7 +114,7 @@ type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B
type Resolved<F> = F extends (...args: never[]) => PromiseLike<infer R> ? R : never;

/**
* [#17690] `IsAny<T>` answers about T ITSELF, which is honestly `false` for
* [commit be5c60291] `IsAny<T>` answers about T ITSELF, which is honestly `false` for
* `any[]` and for `Record<string, any>` — and those are exactly the two shapes
* every door on this card had regressed to. Used as the "is not `any`" half of
* a nested-`any` door it is a PHANTOM CHECK: it evaluates, it is green, and it
Expand All @@ -139,7 +139,7 @@ type Resolved<F> = F extends (...args: never[]) => PromiseLike<infer R> ? R : ne
* `Record<string, unknown>[]` / `Record<string, unknown>` / `unknown` answer
* `false`.
*
* [#17970] Answering `boolean` is the ONE failure mode this detector has to
* [commit 47e6601c5] Answering `boolean` is the ONE failure mode this detector has to
* stay out of, and staying out of it takes TWO guards, because `T` can reach a
* distributive conditional for two unrelated reasons. Every leg below is
* spelled `const x: ContainsAny<Door> = false`, and `false` is ASSIGNABLE to
Expand Down Expand Up @@ -184,7 +184,7 @@ type ContainsAnyPerMember<T> = IsAny<T> extends true
: false;

/**
* [#17970] The collapse. `ContainsAnyPerMember<T>` is distributive, so on a
* [commit 47e6601c5] The collapse. `ContainsAnyPerMember<T>` is distributive, so on a
* union door it answers a UNION of per-member verdicts; this reports `false`
* only when that union is exactly `false`, turning any `boolean` into `true`.
*/
Expand All @@ -198,7 +198,7 @@ type ContractExecute = Resolved<IDataDriver['execute']>;
// `aggregate` is OPTIONAL on the contract (`aggregate?`), so its function type
// is read through `NonNullable` — the door is the member, not its presence.
type ContractAggregate = Resolved<NonNullable<IDataDriver['aggregate']>>;
// [#17690]
// [commit be5c60291]
type ContractFind = Resolved<IDataDriver['find']>;
type ContractUpsert = Resolved<IDataDriver['upsert']>;
type ContractBulkUpdate = Resolved<IDataDriver['bulkUpdate']>;
Expand Down Expand Up @@ -346,7 +346,7 @@ describe('TursoDriver declared return types on the doors it overrides (#15267)',
expect(result === null ? 'absent' : result.name).toBe('before');
});

// [#17690] The three further overridden doors, plus the transaction door.
// [commit be5c60291] The three further overridden doors, plus the transaction door.
// [#18063] That fourth slot moved from `RemoteTransport.beginTransaction` —
// deleted with the rest of that transport's decorative transaction members —
// to `TursoDriver.beginTransaction`, which this card made assertable. Both
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
* The shape was character-identical across every override, so narrowing a subset
* would read to the next person as a *verdict* on the rest. That is not
* hypothetical: #6075 (PR #6210) narrowed `count`'s `query` and deliberately left
* hypothetical: commit d367f03d6 (PR #6210) narrowed `count`'s `query` and deliberately left
* its `options`, and #6212 batch B did the same on `aggregate` — each leaving a
* comment saying so. This file is the pin for the sweep that closed all of them
* together, so no half-narrowed state exists to be misread.
Expand Down Expand Up @@ -63,8 +63,8 @@ import type { DriverOptions } from '@objectstack/spec/data';
type IsAny<T> = 0 extends 1 & T ? true : false;

/**
* [#17879] MEASURED — `Door<T>` below asks `IsAny`, which is a PHANTOM half
* against a NESTED regression, and swapping in `ContainsAny` (#17876) does
* [commit eb9334915] MEASURED — `Door<T>` below asks `IsAny`, which is a PHANTOM half
* against a NESTED regression, and swapping in `ContainsAny` (commit be5c60291) does
* NOT close it. Measured on the `find` row, on disk:
*
* every one of the 17 doors resolves to `DriverOptions | undefined`
Expand All @@ -76,7 +76,7 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
* `ContainsAny` distributes over the `| undefined` every optional parameter
* carries, so the regressed door answers `boolean`, and `boolean extends true`
* is `false` — the detector reads it as "no `any` here". No swap was made;
* the two measured repairs are in the #17879 report.
* the two measured repairs are in commit eb9334915's message.
*/

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
//
// #14438 — `TursoDriver.update()`'s declared return type is the contract's, not
// Commit 2200f8ec8 — `TursoDriver.update()`'s declared return type is the contract's, not
// `any`, and it carries the not-found arm.
//
// `TursoDriver` does not merely inherit `SqlDriver.update()` — it OVERRIDES it
// (a local branch that forwards to `super.update`, a remote branch that passes
// `RemoteTransport.update()`'s result through the generic `formatRemoteRow`),
// and the override was written out with its own explicit `Promise<any>`. Both
// branches already carried the honest type: `SqlDriver.update()` is narrowed
// by #14438 and `RemoteTransport.update()` declared
// `Promise<Record<string, unknown> | null>` with #14428. The override's
// by commit 2200f8ec8 and `RemoteTransport.update()` declared
// `Promise<Record<string, unknown> | null>` with commit ca3fd4b1a. The override's
// annotation was the one place the family's honest type was re-erased, so
// this package's published `.d.ts` re-declared the door as `any` on its own —
// which is why "TursoDriver inherits the fix" would have been wrong, and why
Expand All @@ -34,7 +34,7 @@
// errors are the consumer sites the narrowing was written to surface.
//
// The runtime case below drives the LOCAL face (`:memory:`); the remote face's
// `null` on a miss is pinned by the `RemoteTransport` suites (#14428).
// `null` on a miss is pinned by the `RemoteTransport` suites (commit ca3fd4b1a).

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import type { IDataDriver } from '@objectstack/spec/contracts';
Expand All @@ -44,8 +44,8 @@ import { TursoDriver } from './turso-driver.js';
type IsAny<T> = 0 extends 1 & T ? true : false;

/**
* [#17879] MEASURED — `tursoUpdateIsAny` below is a PHANTOM half against a
* NESTED regression, and `ContainsAny` (#17876) does NOT close it. On disk,
* [commit eb9334915] MEASURED — `tursoUpdateIsAny` below is a PHANTOM half against a
* NESTED regression, and `ContainsAny` (commit be5c60291) does NOT close it. On disk,
* reverting only this override:
*
* door resolves to `Record<string, unknown> | null`
Expand All @@ -56,7 +56,7 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
*
* `ContainsAny` distributes over the not-found arm, so the regressed door
* answers `boolean`, which `= false` accepts. No swap was made; the two
* measured repairs are in the #17879 report.
* measured repairs are in commit eb9334915's message.
*/
/** Exact (mutual, non-`any`) type equality. */
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
Expand Down
20 changes: 10 additions & 10 deletions packages/drivers/driver-turso/src/turso-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2128,14 +2128,14 @@ export class TursoDriver extends SqlDriver {
// [#6402] Every `options` parameter in this file is a {@link DriverOptions},
// matching `SqlDriver` / `IDataDriver` — the two faces of one driver may not
// declare one argument two ways. This was the last `any` axis left in the
// overrides: #5181 (PR #6076), #6075 (PR #6210) and #6212 each narrowed
// overrides: #5181 (commit 6513c1749), commit d367f03d6 (PR #6210) and #6212 each narrowed
// `query`, and each deliberately left `options` alone because it is a
// SEPARATE axis whose shape was verbatim-identical across all 17 overrides —
// narrowing one would have read as a verdict on the other sixteen. #6402
// closed all 17 in one sweep, so there is no half-narrowed state to
// interpret. Keep it that way: a new override here declares `DriverOptions`.

// [#17690] The return is the contract's own type, and this override needs it
// [commit be5c60291] The return is the contract's own type, and this override needs it
// declared HERE: an override re-declares the door in this package's own
// `.d.ts`, so the `@objectstack/driver-sql` narrowing does not reach a
// consumer holding a `TursoDriver` — measured twice already (#15280 for
Expand Down Expand Up @@ -2729,7 +2729,7 @@ export class TursoDriver extends SqlDriver {
// already do: `RemoteTransport.create()` answers `Record<string, unknown>`
// through the generic `formatRemoteRow`, and the local branch forwards to
// `super.create` (narrowed alongside). Same shape the `update()` override
// above took with #14438.
// above took with commit 2200f8ec8.
override async create(object: string, data: Record<string, any>, options?: DriverOptions): Promise<Record<string, unknown>> {
this.assertRemoteTransactionUnsupported(options, 'create');
if (this.isRemote) {
Expand All @@ -2752,9 +2752,9 @@ export class TursoDriver extends SqlDriver {
return super.create(object, data, options);
}

// [#14438] The override declares the contract's type, as both of its branches
// [commit 2200f8ec8] The override declares the contract's type, as both of its branches
// already do: `super.update` (driver-sql) and `RemoteTransport.update()`
// (#14428) both answer `Record<string, unknown> | null`, and `formatRemoteRow`
// (commit ca3fd4b1a) both answer `Record<string, unknown> | null`, and `formatRemoteRow`
// is a generic pass-through. The explicit `Promise<any>` here was the one
// place this package's own `.d.ts` re-erased the door.
override async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions): Promise<Record<string, unknown> | null> {
Expand All @@ -2773,7 +2773,7 @@ export class TursoDriver extends SqlDriver {
return super.update(object, id, data, options);
}

// [#17690] The return is the contract's own type, and this override needs it
// [commit be5c60291] The return is the contract's own type, and this override needs it
// declared HERE: an override re-declares the door in this package's own
// `.d.ts`, so the `@objectstack/driver-sql` narrowing does not reach a
// consumer holding a `TursoDriver` — measured twice already (#15280 for
Expand Down Expand Up @@ -3441,7 +3441,7 @@ export class TursoDriver extends SqlDriver {
return super.bulkCreate(object, data, options);
}

// [#17690] The return is the contract's own type, and this override needs it
// [commit be5c60291] The return is the contract's own type, and this override needs it
// declared HERE: an override re-declares the door in this package's own
// `.d.ts`, so the `@objectstack/driver-sql` narrowing does not reach a
// consumer holding a `TursoDriver` — measured twice already (#15280 for
Expand Down Expand Up @@ -3546,7 +3546,7 @@ export class TursoDriver extends SqlDriver {
// have been a lie on the remote arm. The `any` masked that real LSP
// violation, and closing it meant widening `SqlDriver`'s narrowing (measured
// at the time: +14 further consumer sites across the driver packages) or
// restructuring the remote handle — both above an annotation swap (#17690).
// restructuring the remote handle — both above an annotation swap (commit be5c60291).
//
// What dissolved it is that the remote arm no longer returns anything.
// [#18616] made it REFUSE, and `refuseRemoteTransaction` returns `never`, so
Expand Down Expand Up @@ -3686,12 +3686,12 @@ export class TursoDriver extends SqlDriver {
*
* In local / replica modes the existing Knex-based path remains in effect.
*
* ⛔ #16711 — this parameter type must declare every key `SqlDriver.initObjects`
* ⛔ Commit 7862fb711 — this parameter type must declare every key `SqlDriver.initObjects`
* declares, and `scripts/check-object-def-param-keys.mjs` fails the build if it
* stops doing so. An `override` does NOT inherit the base's parameter type, so
* this literal is what every caller of `@objectstack/driver-turso` sees: while
* it read `{ name; fields? }`, #4311's `tenancy` fix sat on the base for five
* weeks and was invisible from outside `@objectstack/driver-sql`, and #16570's
* weeks and was invisible from outside `@objectstack/driver-sql`, and commit b72226f48's
* `indexes` fix would have escaped the same way. The escape is silent because
* TypeScript's excess-property check fires on a FRESH object literal only — and
* the remote arm below forwards the WHOLE object as `schema`, so the runtime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
* given the remote transport NUMERIC affinity — `json` contains none of
* SQLite's affinity markers (`INT`, `CHAR`/`CLOB`/`TEXT`, `BLOB`,
* `REAL`/`FLOA`/`DOUB`) — i.e. the measured `'0123'` → `123` exposure that
* #12380 had to defeat on the local half, imported into the half that never had
* commit 4045b954d had to defeat on the local half, imported into the half that never had
* it.
*
* ## The instrument is AFFINITY-LEVEL, and that is a requirement, not a taste
Expand All @@ -66,7 +66,7 @@
*
* Only what NEW columns are declared as. A column created before this change
* keeps its `json` declaration, keeps NUMERIC affinity, and keeps being
* defended by #12380's injective codec — `SqlDriver.buildRebuiltColumn` still
* defended by commit 4045b954d's injective codec — `SqlDriver.buildRebuiltColumn` still
* re-declares an introspected `json` column as `json`, so not even a drift
* rebuild converts one. Nothing on the read path consults the physical type
* (`isJsonField` answers from metadata), so decoding is identical either way.
Expand All @@ -81,7 +81,7 @@
*
* @see https://github.com/objectstack-ai/objectstack/issues/12738 (this inversion)
* @see https://github.com/objectstack-ai/objectstack/issues/12586 (the pin this replaces)
* @see https://github.com/objectstack-ai/objectstack/issues/12380 (the injective local codec)
* @see commit 4045b954d (the injective local codec)
* @see https://github.com/objectstack-ai/objectstack/issues/11535 (the class)
*/

Expand Down Expand Up @@ -256,7 +256,7 @@ describe('[#12738] driver-turso — the two transports declare ONE physical colu
// ⛔ This is the assertion that would go red if anyone converged these two
// onto `json` instead. It is stated as the RAW-SQL truth on purpose: it
// asks what the COLUMN does, bypassing the driver codec whose job is to
// make the column's answer not matter. #12380's codec still runs and is
// make the column's answer not matter. Commit 4045b954d's codec still runs and is
// still required — for LEGACY columns, which keep their `json` declaration
// and therefore keep NUMERIC affinity.
expect(
Expand Down
Loading
Loading