sqlstack 3.2.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/adapters/sqlite.d.ts.map +1 -1
- package/dist/cjs/adapters/sqlite.js +4 -1
- package/dist/cjs/adapters/sqlite.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/runtime.d.ts.map +1 -1
- package/dist/cjs/runtime.js +22 -19
- package/dist/cjs/runtime.js.map +1 -1
- package/dist/cjs/stack.d.ts +2 -0
- package/dist/cjs/stack.d.ts.map +1 -1
- package/dist/cjs/stack.js +40 -27
- package/dist/cjs/stack.js.map +1 -1
- package/dist/cjs/testing/builder.d.ts.map +1 -1
- package/dist/cjs/testing/builder.js +14 -5
- package/dist/cjs/testing/builder.js.map +1 -1
- package/dist/cjs/testing/fixture-provenance.d.ts +3 -0
- package/dist/cjs/testing/fixture-provenance.d.ts.map +1 -0
- package/dist/cjs/testing/fixture-provenance.js +21 -0
- package/dist/cjs/testing/fixture-provenance.js.map +1 -0
- package/dist/cjs/testing/index.d.ts +2 -0
- package/dist/cjs/testing/index.d.ts.map +1 -1
- package/dist/cjs/testing/index.js +5 -1
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/cjs/testing/postgres/database.d.ts +9 -1
- package/dist/cjs/testing/postgres/database.d.ts.map +1 -1
- package/dist/cjs/testing/postgres/database.js +17 -13
- package/dist/cjs/testing/postgres/database.js.map +1 -1
- package/dist/cjs/testing/resource.d.ts +76 -0
- package/dist/cjs/testing/resource.d.ts.map +1 -0
- package/dist/cjs/testing/resource.js +117 -0
- package/dist/cjs/testing/resource.js.map +1 -0
- package/dist/cjs/testing/sqlite/builder.d.ts.map +1 -1
- package/dist/cjs/testing/sqlite/builder.js +10 -2
- package/dist/cjs/testing/sqlite/builder.js.map +1 -1
- package/dist/cjs/testing/sqlite/database.d.ts +11 -1
- package/dist/cjs/testing/sqlite/database.d.ts.map +1 -1
- package/dist/cjs/testing/sqlite/database.js +32 -18
- package/dist/cjs/testing/sqlite/database.js.map +1 -1
- package/dist/cjs/transactions.d.ts +6 -0
- package/dist/cjs/transactions.d.ts.map +1 -1
- package/dist/cjs/transactions.js +9 -0
- package/dist/cjs/transactions.js.map +1 -1
- package/dist/esm/adapters/sqlite.js +4 -1
- package/dist/esm/adapters/sqlite.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/runtime.js +22 -19
- package/dist/esm/runtime.js.map +1 -1
- package/dist/esm/stack.js +40 -27
- package/dist/esm/stack.js.map +1 -1
- package/dist/esm/testing/builder.js +14 -5
- package/dist/esm/testing/builder.js.map +1 -1
- package/dist/esm/testing/fixture-provenance.js +15 -0
- package/dist/esm/testing/fixture-provenance.js.map +1 -0
- package/dist/esm/testing/index.js +1 -0
- package/dist/esm/testing/index.js.map +1 -1
- package/dist/esm/testing/postgres/database.js +17 -13
- package/dist/esm/testing/postgres/database.js.map +1 -1
- package/dist/esm/testing/resource.js +106 -0
- package/dist/esm/testing/resource.js.map +1 -0
- package/dist/esm/testing/sqlite/builder.js +10 -2
- package/dist/esm/testing/sqlite/builder.js.map +1 -1
- package/dist/esm/testing/sqlite/database.js +32 -18
- package/dist/esm/testing/sqlite/database.js.map +1 -1
- package/dist/esm/transactions.js +8 -0
- package/dist/esm/transactions.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../../src/testing/sqlite/database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../../src/testing/sqlite/database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE1H,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAwBD;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;AAC/C,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAElC,SAAS,cAAc,CAAC,SAAiB;IACvC,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,qBAAqB;QAAE,OAAO;IAClC,qBAAqB,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;QACxB,KAAK,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6EAA6E;AAC7E,SAAS,oBAAoB,CAAC,SAAiB;IAC7C,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,uEAAuE;IACvE,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAmB;IAEnB,IAAI,SAA6B,CAAC;IAClC,IAAI,QAAQ,GAAG,UAAU,CAAC;IAC1B,IAAI,UAAU,EAAE,CAAC;QACf,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACrE,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QACnD,cAAc,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,EAAY,CAAC;IACjB,IAAI,CAAC;QACH,EAAE,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC;gBAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YACxC,OAAO,OAAO,EAAE,CAAC;gBACf,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,wBAAwB,CAAC,wDAAwD,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9I,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,eAAe,CAAC,yDAAyD,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,IAAI,eAAe,CAAC,0CAA0C,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,OAAO,GAAsB,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClE,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,SAAS,CAAC;IACjC,IAAI,QAAmC,CAAC;IAExC,MAAM,MAAM,GAAuB;QACjC,MAAM,EAAE,QAAQ;QAChB,UAAU;QACV,OAAO;QACP,EAAE;QACF,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACvC,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,SAA6B,EAAE;YACtD,IAAI,QAAQ;gBAAE,MAAM,IAAI,eAAe,CAAC,yCAAyC,CAAC,CAAC;YACnF,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO;YACL,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,MAAM,KAAK,GAAmC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;gBACjE,IAAI,cAAc;oBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC3E,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,yBAAyB,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;YACvG,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;IACF,gBAAgB,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { createSqliteDb } from '../../adapters/sqlite';\nimport { SqlStackError } from '../../core/errors';\nimport type { Database } from '../../registry';\nimport { mintResourceId, registerResource, retireResource, runCleanupSteps, TestDatabaseDisposeError } from '../resource';\n\nexport class TestSqliteError extends SqlStackError {\n constructor(message: string) {\n super(message);\n this.name = 'TestSqliteError';\n }\n}\n\nexport interface TestSqliteDatabase {\n /** Engine discriminator for SQLStack-minted disposable test databases. */\n readonly engine: 'sqlite';\n /** Fresh per-allocation identifier; never reused within a process. */\n readonly resourceId: string;\n /** Explicit storage: an owned temporary file, or an isolated `:memory:` db. */\n readonly storage: 'memory' | 'file';\n /** The live sqlstack SQLite adapter, suitable for direct injection. */\n readonly db: Database;\n /** The underlying better-sqlite3 (or sqlite3) connection. */\n readonly conn: unknown;\n /** Absolute database path in file mode; undefined for :memory:. */\n readonly path?: string;\n query(sql: string, params?: readonly unknown[]): Promise<unknown>;\n /**\n * Close the connection and remove owned temporary files. Idempotent:\n * concurrent and repeated calls share one outcome. Every cleanup step is\n * attempted; failures are aggregated into a `TestDatabaseDisposeError`.\n */\n dispose(): Promise<void>;\n}\n\n/**\n * Temp directories for file-backed handles that were never disposed. Tests are\n * expected to call `dispose()`, but a failed assertion can skip it; this keeps\n * an abandoned directory from outliving the worker process.\n */\nconst abandonedDirectories = new Set<string>();\nlet exitCleanupRegistered = false;\n\nfunction trackDirectory(directory: string): void {\n abandonedDirectories.add(directory);\n if (exitCleanupRegistered) return;\n exitCleanupRegistered = true;\n process.once('exit', () => {\n for (const dir of abandonedDirectories) {\n try {\n fs.rmSync(dir, { recursive: true, force: true });\n } catch {\n /* best-effort cleanup */\n }\n }\n });\n}\n\n/** Remove exactly the SQLStack-owned temp directory; never a caller path. */\nfunction removeOwnedDirectory(directory: string): void {\n fs.rmSync(directory, { recursive: true, force: true });\n // Keep failed paths in the owned inventory for the exit cleanup retry.\n abandonedDirectories.delete(directory);\n}\n\nexport async function createDatabaseHandle(\n fileBacked: boolean\n): Promise<TestSqliteDatabase> {\n let directory: string | undefined;\n let filename = ':memory:';\n if (fileBacked) {\n directory = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlstack-test-'));\n filename = path.join(directory, 'database.sqlite');\n trackDirectory(directory);\n }\n\n let db: Database;\n try {\n db = await createSqliteDb(filename);\n } catch (err) {\n if (directory) {\n try { removeOwnedDirectory(directory); }\n catch (cleanup) {\n throw Object.assign(new TestDatabaseDisposeError('SQLite test allocation failed and owned cleanup failed', [err, cleanup]), { cause: err });\n }\n }\n const message = (err as Error).message;\n if (message.includes('No SQLite driver available')) {\n throw new TestSqliteError('testSqlite requires the optional peer \"better-sqlite3\".');\n }\n throw new TestSqliteError(`Failed to create SQLite test database: ${message}`);\n }\n\n const storage: 'memory' | 'file' = fileBacked ? 'file' : 'memory';\n const resourceId = mintResourceId('sqlite');\n const ownedDirectory = directory;\n let disposal: Promise<void> | undefined;\n\n const handle: TestSqliteDatabase = {\n engine: 'sqlite',\n resourceId,\n storage,\n db,\n conn: db.conn,\n path: fileBacked ? filename : undefined,\n async query(sql: string, params: readonly unknown[] = []) {\n if (disposal) throw new TestSqliteError('Test SQLite database has been disposed.');\n return db.query(sql, [...params]);\n },\n dispose() {\n if (!disposal) {\n retireResource(handle);\n const steps: (() => Promise<void> | void)[] = [() => db.close()];\n if (ownedDirectory) steps.push(() => removeOwnedDirectory(ownedDirectory));\n disposal = Promise.resolve().then(() => runCleanupSteps(`Test SQLite database (${storage})`, steps));\n }\n return disposal;\n },\n };\n registerResource(handle, { engine: 'sqlite', resourceId, storage });\n return handle;\n}\n"]}
|
package/dist/esm/transactions.js
CHANGED
|
@@ -230,6 +230,14 @@ export function currentTransaction(db) {
|
|
|
230
230
|
return undefined;
|
|
231
231
|
return new TransactionHandle(entry, state, false);
|
|
232
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Whether this async call carries any transaction records. This observation
|
|
235
|
+
* never resolves a database, opens a connection, or consults legacy defaults.
|
|
236
|
+
* It does not choose an owner: use currentTransactionFor(entry) for that.
|
|
237
|
+
*/
|
|
238
|
+
export function hasTransactionContext() {
|
|
239
|
+
return (getStore()?.txByDb.size ?? 0) > 0;
|
|
240
|
+
}
|
|
233
241
|
/** Active transaction handle for a concrete database entry, if any. */
|
|
234
242
|
export function currentTransactionFor(entry) {
|
|
235
243
|
const store = getStore();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/transactions.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Database, QueryResult } from './registry';\nimport { createPgDb, createMysqlDb } from './adapters';\nimport { RollbackTransactionError, SqlStackError } from './core/errors';\nimport type { DatabaseEntry } from './stack';\nimport { resolveExecution, legacyEntry } from './runtime';\n\nexport type TransactionOptions = {\n db?: string;\n lazy?: boolean;\n nested?: 'join';\n};\n\n// Keyed by concrete DatabaseEntry identity (owning stack + registration), so\n// two roots transacting on the same name (\"primary\") can never collide\n// (spec 16 §20, spec 17 §14).\ntype TxStore = {\n txByDb: Map<DatabaseEntry, TxState>;\n};\n\nconst als = new AsyncLocalStorage<TxStore>();\n\nfunction getStore(): TxStore | undefined {\n return als.getStore();\n}\n\nfunction getOrCreateStore(): { store: TxStore; isNew: boolean } {\n const existing = getStore();\n if (existing) return { store: existing, isNew: false };\n return { store: { txByDb: new Map() }, isNew: true };\n}\n\nfunction isRollbackTransactionError(err: unknown): err is RollbackTransactionError {\n return err instanceof RollbackTransactionError;\n}\n\nfunction unwrapRollbackCause(err: RollbackTransactionError): unknown {\n return typeof err.cause === 'undefined' ? err : err.cause;\n}\n\nexport class TransactionHandle {\n readonly entry: DatabaseEntry;\n #state: TxState;\n #owned: boolean;\n #finished = false;\n\n constructor(entry: DatabaseEntry, state: TxState, owned: boolean) {\n this.entry = entry;\n this.#state = state;\n this.#owned = owned;\n }\n\n get dbName(): string {\n return this.entry.name;\n }\n\n async ensureStarted() {\n await this.#state.ensureStarted();\n }\n\n rollbackOnly(errorToThrow?: unknown) {\n this.#state.rollbackOnly = true;\n if (typeof errorToThrow !== 'undefined') {\n this.#state.rollbackError = errorToThrow;\n }\n }\n\n async commit() {\n if (!this.#owned) return;\n await this.#state.commitIfStarted();\n }\n\n async rollback() {\n if (!this.#owned) return;\n await this.#state.rollbackIfStarted();\n }\n\n async release() {\n if (!this.#owned) return;\n await this.#state.release();\n }\n\n async finishOnSuccess() {\n if (!this.#owned || this.#finished) return;\n this.#finished = true;\n await this.#state.finishOnSuccess();\n }\n\n async finishOnError(err: unknown) {\n if (!this.#owned || this.#finished) return;\n this.#finished = true;\n await this.#state.finishOnError(err);\n }\n}\n\nclass TxState {\n readonly entry: DatabaseEntry;\n readonly db: Database;\n readonly options: Required<Pick<TransactionOptions, 'lazy'>> & Pick<TransactionOptions, 'nested'>;\n depth = 1;\n started = false;\n completed = false;\n rollbackOnly = false;\n rollbackError: unknown | undefined;\n\n private txDb: Database | undefined;\n private releaseFn: (() => Promise<void>) | undefined;\n\n constructor(entry: DatabaseEntry, options: TransactionOptions | undefined) {\n this.entry = entry;\n this.db = entry.db;\n this.options = {\n lazy: options?.lazy ?? true,\n nested: options?.nested ?? 'join',\n };\n }\n\n get activeDb(): Database {\n return this.txDb ?? this.db;\n }\n\n async ensureStarted() {\n if (this.started) return;\n\n const dialect = this.db.dialect ?? 'sqlite';\n if (dialect === 'postgres') {\n const pool: any = this.db.conn;\n if (!pool || typeof pool.connect !== 'function') {\n throw new SqlStackError('Postgres transactions require a pg Pool with .connect() as Database.conn');\n }\n const client = await pool.connect();\n this.txDb = createPgDb(client);\n this.releaseFn = async () => {\n if (typeof client.release === 'function') client.release();\n };\n await this.txDb.query('BEGIN', []);\n this.started = true;\n return;\n }\n\n if (dialect === 'mysql') {\n const pool: any = this.db.conn;\n if (!pool || typeof pool.getConnection !== 'function') {\n throw new SqlStackError('MySQL transactions require a mysql2 Pool with .getConnection() as Database.conn');\n }\n const conn = await pool.getConnection();\n this.txDb = createMysqlDb(conn);\n this.releaseFn = async () => {\n if (typeof conn.release === 'function') conn.release();\n };\n await this.txDb.query('START TRANSACTION', []);\n this.started = true;\n return;\n }\n\n // sqlite: existing connection is already bound\n await this.db.query('BEGIN', []);\n this.started = true;\n }\n\n async query(sql: string, params: unknown[]): Promise<QueryResult> {\n await this.ensureStarted();\n return await this.activeDb.query(sql, params);\n }\n\n async commitIfStarted() {\n if (this.completed) return;\n if (!this.started) {\n this.completed = true;\n return;\n }\n await this.activeDb.query('COMMIT', []);\n this.completed = true;\n }\n\n async rollbackIfStarted() {\n if (this.completed) return;\n if (!this.started) {\n this.completed = true;\n return;\n }\n await this.activeDb.query('ROLLBACK', []);\n this.completed = true;\n }\n\n async release() {\n try {\n if (this.releaseFn) await this.releaseFn();\n } finally {\n this.txDb = undefined;\n this.releaseFn = undefined;\n }\n }\n\n async finishOnSuccess() {\n try {\n if (this.rollbackOnly) {\n await this.rollbackIfStarted();\n if (typeof this.rollbackError !== 'undefined') throw this.rollbackError;\n throw new RollbackTransactionError();\n }\n await this.commitIfStarted();\n } finally {\n await this.release();\n }\n }\n\n async finishOnError(err: unknown) {\n try {\n await this.rollbackIfStarted();\n } finally {\n await this.release();\n }\n if (isRollbackTransactionError(err)) {\n throw unwrapRollbackCause(err);\n }\n throw err;\n }\n}\n\nfunction enterTx(entry: DatabaseEntry, options?: TransactionOptions): { handle: TransactionHandle; store: TxStore; isNewStore: boolean } {\n const { store, isNew } = getOrCreateStore();\n const existing = store.txByDb.get(entry);\n if (existing) {\n existing.depth++;\n return { handle: new TransactionHandle(entry, existing, false), store, isNewStore: isNew };\n }\n const state = new TxState(entry, options);\n store.txByDb.set(entry, state);\n return { handle: new TransactionHandle(entry, state, true), store, isNewStore: isNew };\n}\n\nasync function exitTx(entry: DatabaseEntry, store: TxStore) {\n const state = store.txByDb.get(entry);\n if (!state) return;\n state.depth = Math.max(0, state.depth - 1);\n if (state.depth === 0) {\n store.txByDb.delete(entry);\n }\n}\n\n/**\n * @deprecated Synchronous lookup against the legacy global registry only.\n * Under an active IoC root, use `currentTransactionFor(entry)` with an entry\n * from the root's SqlStack (`stack.getEntry(name)`).\n */\nexport function currentTransaction(db?: string): TransactionHandle | undefined {\n const store = getStore();\n if (!store) return undefined;\n const entry = legacyEntry(db);\n const state = store.txByDb.get(entry);\n if (!state) return undefined;\n return new TransactionHandle(entry, state, false);\n}\n\n/** Active transaction handle for a concrete database entry, if any. */\nexport function currentTransactionFor(entry: DatabaseEntry): TransactionHandle | undefined {\n const store = getStore();\n const state = store?.txByDb.get(entry);\n if (!state) return undefined;\n return new TransactionHandle(entry, state, false);\n}\n\nexport async function withTransaction<T>(fn: () => Promise<T>, options?: TransactionOptions): Promise<T> {\n const { entry } = await resolveExecution(options?.db);\n const { handle, store, isNewStore } = enterTx(entry, options);\n\n const run = async () => {\n try {\n const out = await fn();\n await handle.finishOnSuccess();\n return out;\n } catch (err) {\n await handle.finishOnError(err);\n throw err;\n } finally {\n await exitTx(entry, store);\n }\n };\n\n return isNewStore ? await als.run(store, run) : await run();\n}\n\nexport type TransactionDecorator = {\n (target: any, prop: string | symbol, desc: PropertyDescriptor): void;\n (options?: TransactionOptions): (target: any, prop: string | symbol, desc: PropertyDescriptor) => void;\n};\n\nexport const transaction: TransactionDecorator = function (...args: any[]) {\n // @transaction\n if (args.length === 3 && typeof args[2]?.value === 'function') {\n const [target, prop, desc] = args as [any, string | symbol, PropertyDescriptor];\n wrapMethod(target, prop, desc, undefined);\n return;\n }\n // @transaction() or @transaction({ ... })\n const options: TransactionOptions | undefined = args.length > 0 ? args[0] : undefined;\n return function (target: any, prop: string | symbol, desc: PropertyDescriptor) {\n wrapMethod(target, prop, desc, options);\n };\n} as any;\n\nfunction wrapMethod(_target: any, _prop: string | symbol, desc: PropertyDescriptor, options?: TransactionOptions) {\n const original = desc.value;\n desc.value = async function (...callArgs: any[]) {\n return await withTransaction(() => original.apply(this, callArgs), options);\n };\n}\n\nexport type ActiveTransaction = {\n query(sql: string, params: unknown[]): Promise<QueryResult>;\n};\n\nexport function getActiveTransaction(entry: DatabaseEntry): ActiveTransaction | undefined {\n const store = getStore();\n return store?.txByDb.get(entry);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/transactions.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Database, QueryResult } from './registry';\nimport { createPgDb, createMysqlDb } from './adapters';\nimport { RollbackTransactionError, SqlStackError } from './core/errors';\nimport type { DatabaseEntry } from './stack';\nimport { resolveExecution, legacyEntry } from './runtime';\n\nexport type TransactionOptions = {\n db?: string;\n lazy?: boolean;\n nested?: 'join';\n};\n\n// Keyed by concrete DatabaseEntry identity (owning stack + registration), so\n// two roots transacting on the same name (\"primary\") can never collide\n// (spec 16 §20, spec 17 §14).\ntype TxStore = {\n txByDb: Map<DatabaseEntry, TxState>;\n};\n\nconst als = new AsyncLocalStorage<TxStore>();\n\nfunction getStore(): TxStore | undefined {\n return als.getStore();\n}\n\nfunction getOrCreateStore(): { store: TxStore; isNew: boolean } {\n const existing = getStore();\n if (existing) return { store: existing, isNew: false };\n return { store: { txByDb: new Map() }, isNew: true };\n}\n\nfunction isRollbackTransactionError(err: unknown): err is RollbackTransactionError {\n return err instanceof RollbackTransactionError;\n}\n\nfunction unwrapRollbackCause(err: RollbackTransactionError): unknown {\n return typeof err.cause === 'undefined' ? err : err.cause;\n}\n\nexport class TransactionHandle {\n readonly entry: DatabaseEntry;\n #state: TxState;\n #owned: boolean;\n #finished = false;\n\n constructor(entry: DatabaseEntry, state: TxState, owned: boolean) {\n this.entry = entry;\n this.#state = state;\n this.#owned = owned;\n }\n\n get dbName(): string {\n return this.entry.name;\n }\n\n async ensureStarted() {\n await this.#state.ensureStarted();\n }\n\n rollbackOnly(errorToThrow?: unknown) {\n this.#state.rollbackOnly = true;\n if (typeof errorToThrow !== 'undefined') {\n this.#state.rollbackError = errorToThrow;\n }\n }\n\n async commit() {\n if (!this.#owned) return;\n await this.#state.commitIfStarted();\n }\n\n async rollback() {\n if (!this.#owned) return;\n await this.#state.rollbackIfStarted();\n }\n\n async release() {\n if (!this.#owned) return;\n await this.#state.release();\n }\n\n async finishOnSuccess() {\n if (!this.#owned || this.#finished) return;\n this.#finished = true;\n await this.#state.finishOnSuccess();\n }\n\n async finishOnError(err: unknown) {\n if (!this.#owned || this.#finished) return;\n this.#finished = true;\n await this.#state.finishOnError(err);\n }\n}\n\nclass TxState {\n readonly entry: DatabaseEntry;\n readonly db: Database;\n readonly options: Required<Pick<TransactionOptions, 'lazy'>> & Pick<TransactionOptions, 'nested'>;\n depth = 1;\n started = false;\n completed = false;\n rollbackOnly = false;\n rollbackError: unknown | undefined;\n\n private txDb: Database | undefined;\n private releaseFn: (() => Promise<void>) | undefined;\n\n constructor(entry: DatabaseEntry, options: TransactionOptions | undefined) {\n this.entry = entry;\n this.db = entry.db;\n this.options = {\n lazy: options?.lazy ?? true,\n nested: options?.nested ?? 'join',\n };\n }\n\n get activeDb(): Database {\n return this.txDb ?? this.db;\n }\n\n async ensureStarted() {\n if (this.started) return;\n\n const dialect = this.db.dialect ?? 'sqlite';\n if (dialect === 'postgres') {\n const pool: any = this.db.conn;\n if (!pool || typeof pool.connect !== 'function') {\n throw new SqlStackError('Postgres transactions require a pg Pool with .connect() as Database.conn');\n }\n const client = await pool.connect();\n this.txDb = createPgDb(client);\n this.releaseFn = async () => {\n if (typeof client.release === 'function') client.release();\n };\n await this.txDb.query('BEGIN', []);\n this.started = true;\n return;\n }\n\n if (dialect === 'mysql') {\n const pool: any = this.db.conn;\n if (!pool || typeof pool.getConnection !== 'function') {\n throw new SqlStackError('MySQL transactions require a mysql2 Pool with .getConnection() as Database.conn');\n }\n const conn = await pool.getConnection();\n this.txDb = createMysqlDb(conn);\n this.releaseFn = async () => {\n if (typeof conn.release === 'function') conn.release();\n };\n await this.txDb.query('START TRANSACTION', []);\n this.started = true;\n return;\n }\n\n // sqlite: existing connection is already bound\n await this.db.query('BEGIN', []);\n this.started = true;\n }\n\n async query(sql: string, params: unknown[]): Promise<QueryResult> {\n await this.ensureStarted();\n return await this.activeDb.query(sql, params);\n }\n\n async commitIfStarted() {\n if (this.completed) return;\n if (!this.started) {\n this.completed = true;\n return;\n }\n await this.activeDb.query('COMMIT', []);\n this.completed = true;\n }\n\n async rollbackIfStarted() {\n if (this.completed) return;\n if (!this.started) {\n this.completed = true;\n return;\n }\n await this.activeDb.query('ROLLBACK', []);\n this.completed = true;\n }\n\n async release() {\n try {\n if (this.releaseFn) await this.releaseFn();\n } finally {\n this.txDb = undefined;\n this.releaseFn = undefined;\n }\n }\n\n async finishOnSuccess() {\n try {\n if (this.rollbackOnly) {\n await this.rollbackIfStarted();\n if (typeof this.rollbackError !== 'undefined') throw this.rollbackError;\n throw new RollbackTransactionError();\n }\n await this.commitIfStarted();\n } finally {\n await this.release();\n }\n }\n\n async finishOnError(err: unknown) {\n try {\n await this.rollbackIfStarted();\n } finally {\n await this.release();\n }\n if (isRollbackTransactionError(err)) {\n throw unwrapRollbackCause(err);\n }\n throw err;\n }\n}\n\nfunction enterTx(entry: DatabaseEntry, options?: TransactionOptions): { handle: TransactionHandle; store: TxStore; isNewStore: boolean } {\n const { store, isNew } = getOrCreateStore();\n const existing = store.txByDb.get(entry);\n if (existing) {\n existing.depth++;\n return { handle: new TransactionHandle(entry, existing, false), store, isNewStore: isNew };\n }\n const state = new TxState(entry, options);\n store.txByDb.set(entry, state);\n return { handle: new TransactionHandle(entry, state, true), store, isNewStore: isNew };\n}\n\nasync function exitTx(entry: DatabaseEntry, store: TxStore) {\n const state = store.txByDb.get(entry);\n if (!state) return;\n state.depth = Math.max(0, state.depth - 1);\n if (state.depth === 0) {\n store.txByDb.delete(entry);\n }\n}\n\n/**\n * @deprecated Synchronous lookup against the legacy global registry only.\n * Under an active IoC root, use `currentTransactionFor(entry)` with an entry\n * from the root's SqlStack (`stack.getEntry(name)`).\n */\nexport function currentTransaction(db?: string): TransactionHandle | undefined {\n const store = getStore();\n if (!store) return undefined;\n const entry = legacyEntry(db);\n const state = store.txByDb.get(entry);\n if (!state) return undefined;\n return new TransactionHandle(entry, state, false);\n}\n\n/**\n * Whether this async call carries any transaction records. This observation\n * never resolves a database, opens a connection, or consults legacy defaults.\n * It does not choose an owner: use currentTransactionFor(entry) for that.\n */\nexport function hasTransactionContext(): boolean {\n return (getStore()?.txByDb.size ?? 0) > 0;\n}\n\n/** Active transaction handle for a concrete database entry, if any. */\nexport function currentTransactionFor(entry: DatabaseEntry): TransactionHandle | undefined {\n const store = getStore();\n const state = store?.txByDb.get(entry);\n if (!state) return undefined;\n return new TransactionHandle(entry, state, false);\n}\n\nexport async function withTransaction<T>(fn: () => Promise<T>, options?: TransactionOptions): Promise<T> {\n const { entry } = await resolveExecution(options?.db);\n const { handle, store, isNewStore } = enterTx(entry, options);\n\n const run = async () => {\n try {\n const out = await fn();\n await handle.finishOnSuccess();\n return out;\n } catch (err) {\n await handle.finishOnError(err);\n throw err;\n } finally {\n await exitTx(entry, store);\n }\n };\n\n return isNewStore ? await als.run(store, run) : await run();\n}\n\nexport type TransactionDecorator = {\n (target: any, prop: string | symbol, desc: PropertyDescriptor): void;\n (options?: TransactionOptions): (target: any, prop: string | symbol, desc: PropertyDescriptor) => void;\n};\n\nexport const transaction: TransactionDecorator = function (...args: any[]) {\n // @transaction\n if (args.length === 3 && typeof args[2]?.value === 'function') {\n const [target, prop, desc] = args as [any, string | symbol, PropertyDescriptor];\n wrapMethod(target, prop, desc, undefined);\n return;\n }\n // @transaction() or @transaction({ ... })\n const options: TransactionOptions | undefined = args.length > 0 ? args[0] : undefined;\n return function (target: any, prop: string | symbol, desc: PropertyDescriptor) {\n wrapMethod(target, prop, desc, options);\n };\n} as any;\n\nfunction wrapMethod(_target: any, _prop: string | symbol, desc: PropertyDescriptor, options?: TransactionOptions) {\n const original = desc.value;\n desc.value = async function (...callArgs: any[]) {\n return await withTransaction(() => original.apply(this, callArgs), options);\n };\n}\n\nexport type ActiveTransaction = {\n query(sql: string, params: unknown[]): Promise<QueryResult>;\n};\n\nexport function getActiveTransaction(entry: DatabaseEntry): ActiveTransaction | undefined {\n const store = getStore();\n return store?.txByDb.get(entry);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sqlstack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"db:logs:mysql": "docker logs -f sqlstack-mysql"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@noego/ioc": "^0.
|
|
74
|
+
"@noego/ioc": "^0.8.0",
|
|
75
75
|
"@types/jest": "^29.5.13",
|
|
76
76
|
"better-sqlite3": "^12.3.0",
|
|
77
77
|
"jest": "^29.7.0",
|
package/readme.md
CHANGED
|
@@ -47,6 +47,9 @@ npm install better-sqlite3 # SQLite
|
|
|
47
47
|
|
|
48
48
|
## Quick Start (5 minutes)
|
|
49
49
|
|
|
50
|
+
> **Standalone versus IoC applications:** The global `SqlStackDB` setup below is for execution without an active IoC context. Inside an active `@noego/ioc` root or child scope, queries and transactions use that root's registered `SqlStack` only. Register it during root composition with `registerSqlStack(container, config)` from `sqlstack/ioc`; a global default does not substitute for a missing root registration. Missing registration throws `SqlStackError`, and failures constructing a registered SqlStack propagate without falling back globally. Connect the returned `dispose()` function to application shutdown/test teardown to close SQLStack-owned adapters. Existing standalone execution without an active IoC context remains supported.
|
|
51
|
+
|
|
52
|
+
|
|
50
53
|
At a high level, you:
|
|
51
54
|
|
|
52
55
|
- Register one or more database connections with `SqlStackDB`.
|