@stratal/framework 0.0.22 → 0.0.24

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.
Files changed (44) hide show
  1. package/dist/access-control/index.d.mts +3 -3
  2. package/dist/access-control/index.d.mts.map +1 -1
  3. package/dist/access-control/index.mjs +3 -3
  4. package/dist/access-control/index.mjs.map +1 -1
  5. package/dist/{access.service-DWRsDLJq.mjs → access.service-BmDhE-re.mjs} +3 -3
  6. package/dist/{access.service-DWRsDLJq.mjs.map → access.service-BmDhE-re.mjs.map} +1 -1
  7. package/dist/auth/index.d.mts +22 -20
  8. package/dist/auth/index.d.mts.map +1 -1
  9. package/dist/auth/index.mjs +22 -20
  10. package/dist/auth/index.mjs.map +1 -1
  11. package/dist/{auth-context-CObJcW0t.mjs → auth-context-C8NBfiMa.mjs} +3 -3
  12. package/dist/{auth-context-CObJcW0t.mjs.map → auth-context-C8NBfiMa.mjs.map} +1 -1
  13. package/dist/{auth-context-D70ktWUf.d.mts → auth-context-CGVbiSX3.d.mts} +1 -1
  14. package/dist/auth-context-CGVbiSX3.d.mts.map +1 -0
  15. package/dist/context/index.d.mts +1 -1
  16. package/dist/context/index.d.mts.map +1 -1
  17. package/dist/context/index.mjs +2 -2
  18. package/dist/database/index.d.mts +2 -2
  19. package/dist/database/index.mjs +35 -3
  20. package/dist/database/index.mjs.map +1 -1
  21. package/dist/{decorate-7CAoTBu4.mjs → decorate-B7nr7eBl.mjs} +1 -1
  22. package/dist/{decorateParam-C_dJ_dIO.mjs → decorateParam-DwV9LSPl.mjs} +2 -2
  23. package/dist/{decorateParam-C_dJ_dIO.mjs.map → decorateParam-DwV9LSPl.mjs.map} +1 -1
  24. package/dist/{errors-MCyrn_V2.mjs → errors-BvJSaUTW.mjs} +1 -1
  25. package/dist/{errors-MCyrn_V2.mjs.map → errors-BvJSaUTW.mjs.map} +1 -1
  26. package/dist/factory/index.d.mts +1 -1
  27. package/dist/factory/index.d.mts.map +1 -1
  28. package/dist/factory/index.mjs.map +1 -1
  29. package/dist/guards/index.d.mts.map +1 -1
  30. package/dist/guards/index.mjs +4 -4
  31. package/dist/guards/index.mjs.map +1 -1
  32. package/dist/{index-DJ_DCIul.d.mts → index-jILx9QXw.d.mts} +3 -3
  33. package/dist/index-jILx9QXw.d.mts.map +1 -0
  34. package/dist/index.d.mts +2 -2
  35. package/dist/{insufficient-permissions.error-GwrkWnEM.mjs → insufficient-permissions.error-DeEyZRgy.mjs} +1 -1
  36. package/dist/{insufficient-permissions.error-GwrkWnEM.mjs.map → insufficient-permissions.error-DeEyZRgy.mjs.map} +1 -1
  37. package/dist/{types-4uX3XKRM.d.mts → types-CWZ9q74G.d.mts} +1 -1
  38. package/dist/types-CWZ9q74G.d.mts.map +1 -0
  39. package/dist/{types-tu9pTehB.d.mts → types-DabF8LGz.d.mts} +1 -1
  40. package/dist/{types-tu9pTehB.d.mts.map → types-DabF8LGz.d.mts.map} +1 -1
  41. package/package.json +22 -22
  42. package/dist/auth-context-D70ktWUf.d.mts.map +0 -1
  43. package/dist/index-DJ_DCIul.d.mts.map +0 -1
  44. package/dist/types-4uX3XKRM.d.mts.map +0 -1
@@ -1,3 +1,3 @@
1
- import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, o as InternalDatabaseEventContext, r as InferAnySchema, s as StratalDatabase, t as ConnectionName } from "../types-4uX3XKRM.mjs";
2
- import { A as DatabaseModule, C as UniqueConstraintError, D as connectionSymbol, E as DATABASE_TOKENS, O as DatabaseService, S as fromZenStackError, T as InjectDB, _ as EventPhase, a as DbPushCommand, b as ModelName, c as ZenStackCommand, d as EventEmitterPluginOptions, f as ErrorHandlerPlugin, g as DatabaseOperation, h as DatabaseEvents, i as MigrateDeployCommand, j as DatabaseModuleConfig, k as DatabaseConnectionConfig, l as SchemaSwitcher, m as DatabaseEventName, n as MigrateResetCommand, o as DbPullCommand, p as databaseMessages, r as MigrateDevCommand, s as DbGenerateCommand, t as MigrateStatusCommand, u as EventEmitterPlugin, v as GetData, w as RecordNotFoundError, x as ParseEvent, y as GetResult } from "../index-DJ_DCIul.mjs";
1
+ import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, o as InternalDatabaseEventContext, r as InferAnySchema, s as StratalDatabase, t as ConnectionName } from "../types-CWZ9q74G.mjs";
2
+ import { A as DatabaseModule, C as UniqueConstraintError, D as connectionSymbol, E as DATABASE_TOKENS, O as DatabaseService, S as fromZenStackError, T as InjectDB, _ as EventPhase, a as DbPushCommand, b as ModelName, c as ZenStackCommand, d as EventEmitterPluginOptions, f as ErrorHandlerPlugin, g as DatabaseOperation, h as DatabaseEvents, i as MigrateDeployCommand, j as DatabaseModuleConfig, k as DatabaseConnectionConfig, l as SchemaSwitcher, m as DatabaseEventName, n as MigrateResetCommand, o as DbPullCommand, p as databaseMessages, r as MigrateDevCommand, s as DbGenerateCommand, t as MigrateStatusCommand, u as EventEmitterPlugin, v as GetData, w as RecordNotFoundError, x as ParseEvent, y as GetResult } from "../index-jILx9QXw.mjs";
3
3
  export { ConnectionName, DATABASE_TOKENS, DatabaseConnectionConfig, DatabaseEventName, DatabaseEvents, DatabaseModule, DatabaseModuleConfig, DatabaseOperation, DatabaseService, DbGenerateCommand, DbPullCommand, DbPushCommand, DefaultConnectionName, ErrorHandlerPlugin, EventEmitterPlugin, EventEmitterPluginOptions, EventPhase, GetData, GetResult, InferAnySchema, InferConnectionExtensions, InferConnectionSchema, InjectDB, InternalDatabaseEventContext, MigrateDeployCommand, MigrateDevCommand, MigrateResetCommand, MigrateStatusCommand, ModelName, ParseEvent, RecordNotFoundError, SchemaSwitcher, StratalDatabase, UniqueConstraintError, ZenStackCommand, connectionSymbol, databaseMessages, fromZenStackError };
@@ -1,10 +1,11 @@
1
- import { t as __decorate } from "../decorate-7CAoTBu4.mjs";
1
+ import { t as __decorate } from "../decorate-B7nr7eBl.mjs";
2
2
  import { DI_TOKENS, Transient, inject, lazy } from "stratal/di";
3
3
  import { Module } from "stratal/module";
4
4
  import { DatabaseError, HttpException } from "stratal/errors";
5
5
  import { I18nModule } from "stratal/i18n";
6
6
  import { Command } from "stratal/quarry";
7
7
  import { ORMError, ORMErrorReason, ZenStackClient } from "@zenstackhq/orm";
8
+ import { AsyncLocalStorage } from "node:async_hooks";
8
9
  import { withZodI18n, z } from "stratal/validation";
9
10
  //#region src/database/commands/zenstack.command.ts
10
11
  /**
@@ -276,12 +277,42 @@ z.object({
276
277
  const names = config.connections.map((c) => c.name);
277
278
  return new Set(names).size === names.length;
278
279
  }, withZodI18n("database.duplicateConnections")).refine((config) => config.connections.some((c) => c.name === config.default), withZodI18n("database.defaultConnectionNotFound"));
280
+ /**
281
+ * Wrap a ZenStack client so `$transaction` is reentrant: when a transaction is
282
+ * already open on this connection (tracked per-connection via
283
+ * {@link AsyncLocalStorage}), nested calls run within the active transaction's
284
+ * client instead of opening a new one. ZenStack only reuses a connection when
285
+ * `$transaction` is called on a transaction client; callers holding the base
286
+ * client (e.g. the better-auth adapter, which since better-auth 1.6.11 nests
287
+ * transactions to atomically consume verification rows) would otherwise open a
288
+ * fresh transaction. On a small pool (e.g. a Hyperdrive-fronted `max: 1` pg
289
+ * pool) that inner transaction blocks forever waiting for the connection the
290
+ * outer one holds — a deadlock surfacing as a backend stuck `idle in
291
+ * transaction`. Reusing the active client is also the correct semantics: nested
292
+ * transactions form a single atomic unit.
293
+ *
294
+ * ZenStackClient's constructor returns a Proxy (for dynamic model accessors), so
295
+ * a subclass method override is shadowed — hence the proxy wrapper here.
296
+ */
297
+ function makeReentrantTransaction(client, activeTransaction) {
298
+ return new Proxy(client, { get(target, prop, receiver) {
299
+ if (prop !== "$transaction") return Reflect.get(target, prop, receiver);
300
+ const transaction = Reflect.get(target, prop);
301
+ return (input, options) => {
302
+ const active = activeTransaction.getStore();
303
+ if (active) return typeof input === "function" ? input(active) : active.$transaction(input, options);
304
+ if (typeof input !== "function") return transaction.call(target, input, options);
305
+ return transaction.call(target, (tx) => activeTransaction.run(tx, () => input(tx)), options);
306
+ };
307
+ } });
308
+ }
279
309
  function createDatabaseService(conn, eventRegistry) {
280
310
  const plugins = [
281
311
  new ErrorHandlerPlugin(),
282
312
  new EventEmitterPlugin({ eventRegistry }),
283
313
  ...conn.plugins ?? []
284
314
  ];
315
+ const activeTransaction = new AsyncLocalStorage();
285
316
  let DatabaseClient = class DatabaseClient extends ZenStackClient {
286
317
  constructor() {
287
318
  const dialect = conn.dialect();
@@ -290,6 +321,7 @@ function createDatabaseService(conn, eventRegistry) {
290
321
  plugins,
291
322
  computedFields: conn.computedFields
292
323
  });
324
+ return makeReentrantTransaction(this, activeTransaction);
293
325
  }
294
326
  };
295
327
  DatabaseClient = __decorate([Transient()], DatabaseClient);
@@ -336,9 +368,9 @@ let DatabaseModule = _DatabaseModule = class DatabaseModule {
336
368
  }]
337
369
  };
338
370
  }
339
- onInitialize(context) {
371
+ async onInitialize(context) {
340
372
  const config = context.container.resolve(DATABASE_TOKENS.Options);
341
- const eventRegistry = context.container.resolve(DI_TOKENS.EventRegistry);
373
+ const eventRegistry = (await context.container.resolve(DI_TOKENS.LazyModuleLoader).load(() => import("stratal/events").then((m) => m.EventsModule))).get(DI_TOKENS.EventRegistry);
342
374
  for (const conn of config.connections) {
343
375
  const Service = createDatabaseService(conn, eventRegistry);
344
376
  context.container.register(connectionSymbol(conn.name), lazy(() => Service));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/database/commands/zenstack.command.ts","../../src/database/commands/db-generate.command.ts","../../src/database/commands/db-pull.command.ts","../../src/database/commands/db-push.command.ts","../../src/database/commands/migrate-deploy.command.ts","../../src/database/commands/migrate-dev.command.ts","../../src/database/commands/migrate-reset.command.ts","../../src/database/commands/migrate-status.command.ts","../../src/database/errors/record-not-found.error.ts","../../src/database/errors/unique-constraint.error.ts","../../src/database/errors/from-zenstack-error.ts","../../src/database/plugins/error-handler.plugin.ts","../../src/database/plugins/event-emitter.plugin.ts","../../src/database/plugins/schema-switcher.ts","../../src/database/database.helpers.ts","../../src/database/database.tokens.ts","../../src/database/i18n/en.ts","../../src/database/database.module.ts","../../src/database/decorators/inject-db.decorator.ts"],"sourcesContent":["import { Command } from 'stratal/quarry'\n\n/**\n * Base command for ZenStack CLI wrappers.\n * Uses execFileSync with array arguments to prevent shell injection.\n */\nexport abstract class ZenStackCommand extends Command {\n protected async zenstack(args: string[]): Promise<number> {\n // Dynamic import — node:child_process is only available in the Quarry CLI (Node) context\n const { execFileSync } = await import('node:child_process')\n\n try {\n const output = execFileSync('npx', ['zenstack', ...args], {\n encoding: 'utf-8',\n stdio: 'pipe',\n })\n if (output) this.info(output.trim())\n return 0\n } catch (err) {\n const error = err as { stderr?: string; stdout?: string; status?: number }\n if (error.stderr) this.error(error.stderr.trim())\n if (error.stdout) this.info(error.stdout.trim())\n return error.status ?? 1\n }\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbGenerateCommand extends ZenStackCommand {\n static command = 'db:generate {--schema= : Path to schema file} {--watch : Enable watch mode}'\n static description = 'Generate ZenStack ORM client'\n\n async handle(): Promise<number> {\n const args = ['generate']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('watch')) args.push('--watch')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPullCommand extends ZenStackCommand {\n static command = 'db:pull {--schema= : Path to schema file}'\n static description = 'Introspect database and generate schema'\n\n async handle(): Promise<number> {\n const args = ['db', 'pull']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPushCommand extends ZenStackCommand {\n static command = 'db:push {--schema= : Path to schema file} {--accept-data-loss : Accept data loss} {--force-reset : Force reset database}'\n static description = 'Push database schema changes'\n\n async handle(): Promise<number> {\n const args = ['db', 'push']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('accept-data-loss')) args.push('--accept-data-loss')\n if (this.boolean('force-reset')) args.push('--force-reset')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDeployCommand extends ZenStackCommand {\n static command = 'migrate:deploy {--schema= : Path to schema file}'\n static description = 'Deploy pending migrations'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'deploy']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDevCommand extends ZenStackCommand {\n static command = 'migrate:dev {--schema= : Path to schema file} {--name= : Migration name} {--create-only : Create without applying}'\n static description = 'Create and apply migration'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'dev']\n const schema = this.string('schema')\n const name = this.string('name')\n\n if (schema) args.push('--schema', schema)\n if (name) args.push('--name', name)\n if (this.boolean('create-only')) args.push('--create-only')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateResetCommand extends ZenStackCommand {\n static command = 'migrate:reset {--schema= : Path to schema file} {--force : Skip confirmation} {--skip-seed : Skip seeding}'\n static description = 'Reset database'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'reset']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('force')) args.push('--force')\n if (this.boolean('skip-seed')) args.push('--skip-seed')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateStatusCommand extends ZenStackCommand {\n static command = 'migrate:status {--schema= : Path to schema file}'\n static description = 'Check migration status'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'status']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class RecordNotFoundError extends HttpException {\n constructor(public readonly details?: string, cause?: unknown) {\n super(404, 'Record not found', cause)\n }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class UniqueConstraintError extends HttpException {\n constructor(public readonly fields?: string[], cause?: unknown) {\n super(409, 'Record already exists', cause)\n }\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { type ApplicationError, DatabaseError } from 'stratal/errors';\nimport { RecordNotFoundError } from './record-not-found.error';\nimport { UniqueConstraintError } from './unique-constraint.error';\n\nexport function fromZenStackError(error: unknown): ApplicationError {\n if (error instanceof ORMError) {\n switch (error.reason) {\n case ORMErrorReason.NOT_FOUND:\n return new RecordNotFoundError(error.model, error)\n case ORMErrorReason.DB_QUERY_ERROR:\n return parseDatabaseError(error)\n case ORMErrorReason.INVALID_INPUT:\n return new DatabaseError('Invalid database query', error)\n case ORMErrorReason.CONFIG_ERROR:\n return new DatabaseError('Database configuration error', error)\n case ORMErrorReason.NOT_SUPPORTED:\n return new DatabaseError('Operation not supported', error)\n case ORMErrorReason.INTERNAL_ERROR:\n return new DatabaseError('Database internal error', error)\n default:\n return new DatabaseError('Database error', error)\n }\n }\n return new DatabaseError('Database error', error)\n}\n\nfunction parseDatabaseError(error: ORMError): ApplicationError {\n const dbErrorCode = error.dbErrorCode as string | undefined\n if (dbErrorCode) {\n if (dbErrorCode === '23505') return new UniqueConstraintError([error.model ?? 'unknown'], error)\n if (dbErrorCode === '23503') return new DatabaseError('Foreign key constraint violation', error)\n if (dbErrorCode === '23502') return new DatabaseError('Required field is missing', error)\n if (dbErrorCode === '23514') return new DatabaseError('Database constraint violated', error)\n if (dbErrorCode === '42P01') return new DatabaseError('Table does not exist', error)\n if (dbErrorCode === '42703') return new DatabaseError('Column does not exist', error)\n if (dbErrorCode.startsWith('42')) return new DatabaseError('Database syntax or access error', error)\n if (dbErrorCode.startsWith('08')) return new DatabaseError('Database connection failed', error)\n if (dbErrorCode === '57014') return new DatabaseError('Database query timeout', error)\n if (dbErrorCode.startsWith('40')) return new DatabaseError('Transaction conflict or deadlock', error)\n if (dbErrorCode === '53300') return new DatabaseError('Too many database connections', error)\n }\n return new DatabaseError('Database error', error)\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport { fromZenStackError } from '../errors'\n\n/**\n * ZenStack runtime plugin that transforms ORM errors into ApplicationError instances.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [new ErrorHandlerPlugin()]\n * })\n * ```\n */\nexport class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'error-handler'\n\n onQuery = async ({ args, proceed }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n try {\n return await proceed(args)\n } catch (error) {\n throw fromZenStackError(error)\n }\n }\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport type { EventName, IEventRegistry } from 'stratal/events'\n\nexport interface EventEmitterPluginOptions {\n eventRegistry: IEventRegistry\n}\n\n/**\n * ZenStack runtime plugin that emits before/after events for database operations.\n *\n * Emits events in the format:\n * - `before.{Model}.{operation}` - Before the database operation\n * - `after.{Model}.{operation}` - After the database operation\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new EventEmitterPlugin({\n * eventRegistry,\n * })\n * ]\n * })\n * ```\n */\nexport class EventEmitterPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'event-emitter'\n\n constructor(private options: EventEmitterPluginOptions) { }\n\n onQuery = async ({ model, operation, args, proceed }: {\n model: string\n operation: string\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n const { eventRegistry } = this.options\n const eventBase = `${model}.${operation}`\n\n // Emit BEFORE event\n await eventRegistry.emit(`before.${eventBase}` as EventName, {\n data: args,\n })\n\n // Execute the actual database operation\n const result = await proceed(args)\n\n // Emit AFTER event\n await eventRegistry.emit(`after.${eventBase}` as EventName, {\n data: args,\n result,\n })\n\n return result\n }\n}\n","interface SwitchableClient {\n $schema: { provider: { defaultSchema: string } } & Record<string, unknown>\n schema: unknown\n}\n\n/**\n * Switches the active schema on a ZenStack/Kysely database client by mutating\n * `$schema.provider.defaultSchema`. This causes ZenStack's QueryNameMapper to\n * generate fully-qualified table references (e.g. `\"tenant_123\".\"User\"`).\n *\n * Must be called BEFORE any queries are made on the client.\n *\n * Note: The ZenStack RuntimePlugin `onQuery` hook fires after table names are\n * already resolved, so a plugin-based approach cannot set the schema prefix.\n * Direct client mutation is the only supported method.\n */\nexport class SchemaSwitcher {\n static apply<T>(client: T, schemaName: string): T {\n const c = client as unknown as SwitchableClient\n const switched = {\n ...c.$schema,\n provider: { ...c.$schema.provider, defaultSchema: schemaName },\n }\n c.$schema = switched\n c.schema = switched\n return client\n }\n}\n","import { ZenStackClient, type AnyPlugin } from '@zenstackhq/orm'\nimport { Transient } from 'stratal/di'\nimport type { IEventRegistry } from 'stratal/events'\nimport { withZodI18n, z } from 'stratal/validation'\nimport type { DatabaseConnectionConfig } from './database.module'\nimport { ErrorHandlerPlugin, EventEmitterPlugin } from './plugins'\n\nconst databaseConnectionSchema = z.object({\n name: z.string().min(1, withZodI18n('database.connectionNameRequired')),\n schema: z.object({}).loose(),\n dialect: z.function(),\n plugins: z.array(z.object({}).loose()).optional(),\n computedFields: z.object({}).loose().optional(),\n})\n\nexport const databaseModuleConfigSchema = z.object({\n default: z.string().min(1, withZodI18n('database.defaultConnectionRequired')),\n connections: z.array(databaseConnectionSchema).min(1, withZodI18n('database.connectionRequired')),\n}).refine(\n (config) => {\n const names = config.connections.map(c => c.name)\n return new Set(names).size === names.length\n },\n withZodI18n('database.duplicateConnections')\n).refine(\n (config) => config.connections.some(c => c.name === config.default),\n withZodI18n('database.defaultConnectionNotFound')\n)\n\nexport function createDatabaseService(\n conn: DatabaseConnectionConfig,\n eventRegistry: IEventRegistry,\n): new () => InstanceType<typeof ZenStackClient> {\n const plugins: AnyPlugin[] = [\n new ErrorHandlerPlugin(),\n new EventEmitterPlugin({\n eventRegistry,\n }),\n ...(conn.plugins ?? []),\n ]\n\n @Transient()\n class DatabaseClient extends ZenStackClient<typeof conn.schema> {\n constructor() {\n const dialect = conn.dialect()\n // ZenStack 3+ requires `computedFields` whenever the schema declares any\n // `@computed` fields, so pass them through when the consumer provides them.\n super(conn.schema, {\n dialect,\n plugins,\n // @ts-expect-error - ZenStack 3+ requires `computedFields` whenever the schema declares any `@computed` fields, so pass them through when the consumer provides them.\n computedFields: conn.computedFields\n })\n }\n }\n\n return DatabaseClient\n}\n","export const DATABASE_TOKENS = {\n Options: Symbol.for('stratal:database:options'),\n Services: Symbol.for('stratal:database:services'),\n} as const\n\nimport type { ConnectionName } from './types'\n\nexport function connectionSymbol(name: ConnectionName): symbol {\n return Symbol.for(`stratal:database:connection:${name}`)\n}\n","export const databaseMessages = {\n en: {\n connectionNameRequired: 'Connection name is required',\n defaultConnectionRequired: 'Default connection name is required',\n connectionRequired: 'At least one connection is required',\n duplicateConnections: 'Duplicate connection names found',\n defaultConnectionNotFound: 'Default connection not found in connections',\n },\n} as const\n\ndeclare module 'stratal/i18n' {\n interface AppMessageNamespaces {\n database: typeof databaseMessages['en']\n }\n}\n","import type { AnyPlugin, ClientOptions, ComputedFieldsOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { DI_TOKENS, lazy } from 'stratal/di';\nimport type { IEventRegistry } from 'stratal/events';\nimport { I18nModule } from 'stratal/i18n';\nimport {\n Module,\n type AsyncModuleOptions,\n type DynamicModule,\n type ModuleContext,\n type OnInitialize,\n type OnShutdown,\n} from 'stratal/module';\nimport { DbGenerateCommand } from './commands/db-generate.command';\nimport { DbPullCommand } from './commands/db-pull.command';\nimport { DbPushCommand } from './commands/db-push.command';\nimport { MigrateDeployCommand } from './commands/migrate-deploy.command';\nimport { MigrateDevCommand } from './commands/migrate-dev.command';\nimport { MigrateResetCommand } from './commands/migrate-reset.command';\nimport { MigrateStatusCommand } from './commands/migrate-status.command';\nimport { createDatabaseService } from './database.helpers';\nimport { connectionSymbol, DATABASE_TOKENS } from './database.tokens';\nimport { databaseMessages } from './i18n';\nimport type { ConnectionName, DefaultConnectionName } from './types';\n\nexport interface DatabaseConnectionConfig<\n Schema extends SchemaDef = SchemaDef,\n Name extends ConnectionName = ConnectionName,\n> {\n name: Name\n schema: Schema\n dialect: () => ClientOptions<SchemaDef>['dialect']\n plugins?: AnyPlugin[]\n /**\n * Schema-level @computed field implementations. Required when the schema\n * declares any `@computed` fields. Keyed by uncapitalized model name; values\n * map field name to a Kysely-expression compute callback.\n */\n computedFields?: ComputedFieldsOptions<Schema>\n}\n\nexport interface DatabaseModuleConfig {\n default: DefaultConnectionName\n connections: DatabaseConnectionConfig[]\n}\n\n@Module({\n imports: [\n I18nModule.registerMessages({ en: { database: databaseMessages.en } }),\n ],\n providers: [\n DbGenerateCommand,\n DbPushCommand,\n DbPullCommand,\n MigrateDevCommand,\n MigrateDeployCommand,\n MigrateStatusCommand,\n MigrateResetCommand,\n ],\n})\nexport class DatabaseModule implements OnInitialize, OnShutdown {\n static forRoot(config: DatabaseModuleConfig): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n { provide: DATABASE_TOKENS.Options, useValue: config as unknown as object },\n ],\n }\n }\n\n static forRootAsync(options: AsyncModuleOptions<DatabaseModuleConfig>): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n {\n provide: DATABASE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n onInitialize(context: ModuleContext): void {\n const config = context.container.resolve<DatabaseModuleConfig>(DATABASE_TOKENS.Options)\n const eventRegistry = context.container.resolve<IEventRegistry>(DI_TOKENS.EventRegistry)\n for (const conn of config.connections) {\n const Service = createDatabaseService(conn, eventRegistry);\n\n context.container.register(connectionSymbol(conn.name), lazy(() => Service))\n }\n\n context.container.registerExisting(DI_TOKENS.Database, connectionSymbol(config.default))\n\n context.logger.info('DatabaseModule initialized')\n }\n\n onShutdown(context: ModuleContext): void {\n context.logger.info('DatabaseModule shutdown')\n }\n}\n","import { inject } from 'stratal/di'\nimport type { ConnectionName } from '../types'\nimport { connectionSymbol } from '../database.tokens'\n\nexport function InjectDB(name: ConnectionName): ParameterDecorator {\n return inject(connectionSymbol(name))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/database/commands/zenstack.command.ts","../../src/database/commands/db-generate.command.ts","../../src/database/commands/db-pull.command.ts","../../src/database/commands/db-push.command.ts","../../src/database/commands/migrate-deploy.command.ts","../../src/database/commands/migrate-dev.command.ts","../../src/database/commands/migrate-reset.command.ts","../../src/database/commands/migrate-status.command.ts","../../src/database/errors/record-not-found.error.ts","../../src/database/errors/unique-constraint.error.ts","../../src/database/errors/from-zenstack-error.ts","../../src/database/plugins/error-handler.plugin.ts","../../src/database/plugins/event-emitter.plugin.ts","../../src/database/plugins/schema-switcher.ts","../../src/database/database.helpers.ts","../../src/database/database.tokens.ts","../../src/database/i18n/en.ts","../../src/database/database.module.ts","../../src/database/decorators/inject-db.decorator.ts"],"sourcesContent":["import { Command } from 'stratal/quarry'\n\n/**\n * Base command for ZenStack CLI wrappers.\n * Uses execFileSync with array arguments to prevent shell injection.\n */\nexport abstract class ZenStackCommand extends Command {\n protected async zenstack(args: string[]): Promise<number> {\n // Dynamic import — node:child_process is only available in the Quarry CLI (Node) context\n const { execFileSync } = await import('node:child_process')\n\n try {\n const output = execFileSync('npx', ['zenstack', ...args], {\n encoding: 'utf-8',\n stdio: 'pipe',\n })\n if (output) this.info(output.trim())\n return 0\n } catch (err) {\n const error = err as { stderr?: string; stdout?: string; status?: number }\n if (error.stderr) this.error(error.stderr.trim())\n if (error.stdout) this.info(error.stdout.trim())\n return error.status ?? 1\n }\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbGenerateCommand extends ZenStackCommand {\n static command = 'db:generate {--schema= : Path to schema file} {--watch : Enable watch mode}'\n static description = 'Generate ZenStack ORM client'\n\n async handle(): Promise<number> {\n const args = ['generate']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('watch')) args.push('--watch')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPullCommand extends ZenStackCommand {\n static command = 'db:pull {--schema= : Path to schema file}'\n static description = 'Introspect database and generate schema'\n\n async handle(): Promise<number> {\n const args = ['db', 'pull']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPushCommand extends ZenStackCommand {\n static command = 'db:push {--schema= : Path to schema file} {--accept-data-loss : Accept data loss} {--force-reset : Force reset database}'\n static description = 'Push database schema changes'\n\n async handle(): Promise<number> {\n const args = ['db', 'push']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('accept-data-loss')) args.push('--accept-data-loss')\n if (this.boolean('force-reset')) args.push('--force-reset')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDeployCommand extends ZenStackCommand {\n static command = 'migrate:deploy {--schema= : Path to schema file}'\n static description = 'Deploy pending migrations'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'deploy']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDevCommand extends ZenStackCommand {\n static command = 'migrate:dev {--schema= : Path to schema file} {--name= : Migration name} {--create-only : Create without applying}'\n static description = 'Create and apply migration'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'dev']\n const schema = this.string('schema')\n const name = this.string('name')\n\n if (schema) args.push('--schema', schema)\n if (name) args.push('--name', name)\n if (this.boolean('create-only')) args.push('--create-only')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateResetCommand extends ZenStackCommand {\n static command = 'migrate:reset {--schema= : Path to schema file} {--force : Skip confirmation} {--skip-seed : Skip seeding}'\n static description = 'Reset database'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'reset']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('force')) args.push('--force')\n if (this.boolean('skip-seed')) args.push('--skip-seed')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateStatusCommand extends ZenStackCommand {\n static command = 'migrate:status {--schema= : Path to schema file}'\n static description = 'Check migration status'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'status']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class RecordNotFoundError extends HttpException {\n constructor(public readonly details?: string, cause?: unknown) {\n super(404, 'Record not found', cause)\n }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class UniqueConstraintError extends HttpException {\n constructor(public readonly fields?: string[], cause?: unknown) {\n super(409, 'Record already exists', cause)\n }\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { type ApplicationError, DatabaseError } from 'stratal/errors';\nimport { RecordNotFoundError } from './record-not-found.error';\nimport { UniqueConstraintError } from './unique-constraint.error';\n\nexport function fromZenStackError(error: unknown): ApplicationError {\n if (error instanceof ORMError) {\n switch (error.reason) {\n case ORMErrorReason.NOT_FOUND:\n return new RecordNotFoundError(error.model, error)\n case ORMErrorReason.DB_QUERY_ERROR:\n return parseDatabaseError(error)\n case ORMErrorReason.INVALID_INPUT:\n return new DatabaseError('Invalid database query', error)\n case ORMErrorReason.CONFIG_ERROR:\n return new DatabaseError('Database configuration error', error)\n case ORMErrorReason.NOT_SUPPORTED:\n return new DatabaseError('Operation not supported', error)\n case ORMErrorReason.INTERNAL_ERROR:\n return new DatabaseError('Database internal error', error)\n default:\n return new DatabaseError('Database error', error)\n }\n }\n return new DatabaseError('Database error', error)\n}\n\nfunction parseDatabaseError(error: ORMError): ApplicationError {\n const dbErrorCode = error.dbErrorCode as string | undefined\n if (dbErrorCode) {\n if (dbErrorCode === '23505') return new UniqueConstraintError([error.model ?? 'unknown'], error)\n if (dbErrorCode === '23503') return new DatabaseError('Foreign key constraint violation', error)\n if (dbErrorCode === '23502') return new DatabaseError('Required field is missing', error)\n if (dbErrorCode === '23514') return new DatabaseError('Database constraint violated', error)\n if (dbErrorCode === '42P01') return new DatabaseError('Table does not exist', error)\n if (dbErrorCode === '42703') return new DatabaseError('Column does not exist', error)\n if (dbErrorCode.startsWith('42')) return new DatabaseError('Database syntax or access error', error)\n if (dbErrorCode.startsWith('08')) return new DatabaseError('Database connection failed', error)\n if (dbErrorCode === '57014') return new DatabaseError('Database query timeout', error)\n if (dbErrorCode.startsWith('40')) return new DatabaseError('Transaction conflict or deadlock', error)\n if (dbErrorCode === '53300') return new DatabaseError('Too many database connections', error)\n }\n return new DatabaseError('Database error', error)\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport { fromZenStackError } from '../errors'\n\n/**\n * ZenStack runtime plugin that transforms ORM errors into ApplicationError instances.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [new ErrorHandlerPlugin()]\n * })\n * ```\n */\nexport class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'error-handler'\n\n onQuery = async ({ args, proceed }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n try {\n return await proceed(args)\n } catch (error) {\n throw fromZenStackError(error)\n }\n }\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport type { EventName, IEventRegistry } from 'stratal/events'\n\nexport interface EventEmitterPluginOptions {\n eventRegistry: IEventRegistry\n}\n\n/**\n * ZenStack runtime plugin that emits before/after events for database operations.\n *\n * Emits events in the format:\n * - `before.{Model}.{operation}` - Before the database operation\n * - `after.{Model}.{operation}` - After the database operation\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new EventEmitterPlugin({\n * eventRegistry,\n * })\n * ]\n * })\n * ```\n */\nexport class EventEmitterPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'event-emitter'\n\n constructor(private options: EventEmitterPluginOptions) { }\n\n onQuery = async ({ model, operation, args, proceed }: {\n model: string\n operation: string\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n const { eventRegistry } = this.options\n const eventBase = `${model}.${operation}`\n\n // Emit BEFORE event\n await eventRegistry.emit(`before.${eventBase}` as EventName, {\n data: args,\n })\n\n // Execute the actual database operation\n const result = await proceed(args)\n\n // Emit AFTER event\n await eventRegistry.emit(`after.${eventBase}` as EventName, {\n data: args,\n result,\n })\n\n return result\n }\n}\n","interface SwitchableClient {\n $schema: { provider: { defaultSchema: string } } & Record<string, unknown>\n schema: unknown\n}\n\n/**\n * Switches the active schema on a ZenStack/Kysely database client by mutating\n * `$schema.provider.defaultSchema`. This causes ZenStack's QueryNameMapper to\n * generate fully-qualified table references (e.g. `\"tenant_123\".\"User\"`).\n *\n * Must be called BEFORE any queries are made on the client.\n *\n * Note: The ZenStack RuntimePlugin `onQuery` hook fires after table names are\n * already resolved, so a plugin-based approach cannot set the schema prefix.\n * Direct client mutation is the only supported method.\n */\nexport class SchemaSwitcher {\n static apply<T>(client: T, schemaName: string): T {\n const c = client as unknown as SwitchableClient\n const switched = {\n ...c.$schema,\n provider: { ...c.$schema.provider, defaultSchema: schemaName },\n }\n c.$schema = switched\n c.schema = switched\n return client\n }\n}\n","import { ZenStackClient, type AnyPlugin } from '@zenstackhq/orm';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { Transient } from 'stratal/di';\nimport type { IEventRegistry } from 'stratal/events';\nimport { withZodI18n, z } from 'stratal/validation';\nimport type { DatabaseConnectionConfig } from './database.module';\nimport { ErrorHandlerPlugin, EventEmitterPlugin } from './plugins';\n\nconst databaseConnectionSchema = z.object({\n name: z.string().min(1, withZodI18n('database.connectionNameRequired')),\n schema: z.object({}).loose(),\n dialect: z.function(),\n plugins: z.array(z.object({}).loose()).optional(),\n computedFields: z.object({}).loose().optional(),\n})\n\nexport const databaseModuleConfigSchema = z.object({\n default: z.string().min(1, withZodI18n('database.defaultConnectionRequired')),\n connections: z.array(databaseConnectionSchema).min(1, withZodI18n('database.connectionRequired')),\n}).refine(\n (config) => {\n const names = config.connections.map(c => c.name)\n return new Set(names).size === names.length\n },\n withZodI18n('database.duplicateConnections')\n).refine(\n (config) => config.connections.some(c => c.name === config.default),\n withZodI18n('database.defaultConnectionNotFound')\n)\n\ntype ZenStackClientInstance = InstanceType<typeof ZenStackClient>\n\n/**\n * Wrap a ZenStack client so `$transaction` is reentrant: when a transaction is\n * already open on this connection (tracked per-connection via\n * {@link AsyncLocalStorage}), nested calls run within the active transaction's\n * client instead of opening a new one. ZenStack only reuses a connection when\n * `$transaction` is called on a transaction client; callers holding the base\n * client (e.g. the better-auth adapter, which since better-auth 1.6.11 nests\n * transactions to atomically consume verification rows) would otherwise open a\n * fresh transaction. On a small pool (e.g. a Hyperdrive-fronted `max: 1` pg\n * pool) that inner transaction blocks forever waiting for the connection the\n * outer one holds — a deadlock surfacing as a backend stuck `idle in\n * transaction`. Reusing the active client is also the correct semantics: nested\n * transactions form a single atomic unit.\n *\n * ZenStackClient's constructor returns a Proxy (for dynamic model accessors), so\n * a subclass method override is shadowed — hence the proxy wrapper here.\n */\nfunction makeReentrantTransaction<T extends object>(\n client: T,\n activeTransaction: AsyncLocalStorage<ZenStackClientInstance>,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop !== '$transaction') {\n // Forward the receiver so getters/methods resolve `this` against the\n // proxy (correct for layered proxies / accessor properties).\n return Reflect.get(target, prop, receiver)\n }\n // Read the original `$transaction` off the target WITHOUT the receiver — a\n // receiver of the proxy would re-enter this trap and recurse infinitely.\n const transaction = Reflect.get(target, prop) as (\n input: unknown,\n options?: unknown,\n ) => unknown\n return (input: unknown, options?: unknown) => {\n const active = activeTransaction.getStore()\n if (active) {\n return typeof input === 'function'\n ? (input as (tx: ZenStackClientInstance) => unknown)(active)\n : (active.$transaction as (i: unknown, o?: unknown) => unknown)(input, options)\n }\n if (typeof input !== 'function') {\n return transaction.call(target, input, options)\n }\n return transaction.call(\n target,\n (tx: ZenStackClientInstance) =>\n activeTransaction.run(tx, () => (input as (t: ZenStackClientInstance) => unknown)(tx)),\n options,\n )\n }\n },\n })\n}\n\nexport function createDatabaseService(\n conn: DatabaseConnectionConfig,\n eventRegistry: IEventRegistry,\n): new () => InstanceType<typeof ZenStackClient> {\n const plugins: AnyPlugin[] = [\n new ErrorHandlerPlugin(),\n new EventEmitterPlugin({\n eventRegistry,\n }),\n ...(conn.plugins ?? []),\n ]\n\n // Tracks the in-flight interactive transaction client for this connection so\n // nested `$transaction` calls reuse it instead of acquiring a second\n // connection. ZenStack's own reuse only triggers when `$transaction` is\n // invoked on a transaction client; callers that hold the base client (e.g.\n // the better-auth adapter, which since better-auth 1.6.11 nests transactions\n // to atomically consume verification rows) instead open a fresh transaction.\n // On a small pool (e.g. a Hyperdrive-fronted `max: 1` pg pool) the inner\n // transaction then blocks forever waiting for the connection the outer one\n // holds — a deadlock that surfaces as a Postgres backend stuck `idle in\n // transaction`. Reusing the active client makes nested transactions share the\n // single connection, which is also the correct semantics (one atomic unit).\n const activeTransaction = new AsyncLocalStorage<InstanceType<typeof ZenStackClient>>()\n\n @Transient()\n class DatabaseClient extends ZenStackClient<typeof conn.schema> {\n constructor() {\n const dialect = conn.dialect()\n // ZenStack 3+ requires `computedFields` whenever the schema declares any\n // `@computed` fields, so pass them through when the consumer provides them.\n super(conn.schema, {\n dialect,\n plugins,\n // @ts-expect-error - ZenStack 3+ requires `computedFields` whenever the schema declares any `@computed` fields, so pass them through when the consumer provides them.\n computedFields: conn.computedFields\n })\n // ZenStackClient's constructor returns a Proxy (for dynamic model\n // accessors), so subclass method overrides are shadowed. Wrap it in a\n // proxy that makes `$transaction` reentrant. Returning from the\n // constructor replaces the instance DI receives.\n return makeReentrantTransaction(this as InstanceType<typeof ZenStackClient>, activeTransaction)\n }\n }\n\n return DatabaseClient\n}\n","export const DATABASE_TOKENS = {\n Options: Symbol.for('stratal:database:options'),\n Services: Symbol.for('stratal:database:services'),\n} as const\n\nimport type { ConnectionName } from './types'\n\nexport function connectionSymbol(name: ConnectionName): symbol {\n return Symbol.for(`stratal:database:connection:${name}`)\n}\n","export const databaseMessages = {\n en: {\n connectionNameRequired: 'Connection name is required',\n defaultConnectionRequired: 'Default connection name is required',\n connectionRequired: 'At least one connection is required',\n duplicateConnections: 'Duplicate connection names found',\n defaultConnectionNotFound: 'Default connection not found in connections',\n },\n} as const\n\ndeclare module 'stratal/i18n' {\n interface AppMessageNamespaces {\n database: typeof databaseMessages['en']\n }\n}\n","import type { AnyPlugin, ClientOptions, ComputedFieldsOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { DI_TOKENS, lazy } from 'stratal/di';\nimport type { IEventRegistry } from 'stratal/events';\nimport { I18nModule } from 'stratal/i18n';\nimport {\n Module,\n type AsyncModuleOptions,\n type DynamicModule,\n type LazyModuleLoader,\n type ModuleContext,\n type OnInitialize,\n type OnShutdown,\n} from 'stratal/module';\nimport { DbGenerateCommand } from './commands/db-generate.command';\nimport { DbPullCommand } from './commands/db-pull.command';\nimport { DbPushCommand } from './commands/db-push.command';\nimport { MigrateDeployCommand } from './commands/migrate-deploy.command';\nimport { MigrateDevCommand } from './commands/migrate-dev.command';\nimport { MigrateResetCommand } from './commands/migrate-reset.command';\nimport { MigrateStatusCommand } from './commands/migrate-status.command';\nimport { createDatabaseService } from './database.helpers';\nimport { connectionSymbol, DATABASE_TOKENS } from './database.tokens';\nimport { databaseMessages } from './i18n';\nimport type { ConnectionName, DefaultConnectionName } from './types';\n\nexport interface DatabaseConnectionConfig<\n Schema extends SchemaDef = SchemaDef,\n Name extends ConnectionName = ConnectionName,\n> {\n name: Name\n schema: Schema\n dialect: () => ClientOptions<SchemaDef>['dialect']\n plugins?: AnyPlugin[]\n /**\n * Schema-level @computed field implementations. Required when the schema\n * declares any `@computed` fields. Keyed by uncapitalized model name; values\n * map field name to a Kysely-expression compute callback.\n */\n computedFields?: ComputedFieldsOptions<Schema>\n}\n\nexport interface DatabaseModuleConfig {\n default: DefaultConnectionName\n connections: DatabaseConnectionConfig[]\n}\n\n@Module({\n imports: [\n I18nModule.registerMessages({ en: { database: databaseMessages.en } }),\n ],\n providers: [\n DbGenerateCommand,\n DbPushCommand,\n DbPullCommand,\n MigrateDevCommand,\n MigrateDeployCommand,\n MigrateStatusCommand,\n MigrateResetCommand,\n ],\n})\nexport class DatabaseModule implements OnInitialize, OnShutdown {\n static forRoot(config: DatabaseModuleConfig): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n { provide: DATABASE_TOKENS.Options, useValue: config as unknown as object },\n ],\n }\n }\n\n static forRootAsync(options: AsyncModuleOptions<DatabaseModuleConfig>): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n {\n provide: DATABASE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n async onInitialize(context: ModuleContext): Promise<void> {\n const config = context.container.resolve<DatabaseModuleConfig>(DATABASE_TOKENS.Options)\n // EventRegistry is loaded on demand — pull in EventsModule via the loader.\n const loader = context.container.resolve<LazyModuleLoader>(DI_TOKENS.LazyModuleLoader)\n const eventsRef = await loader.load(() => import('stratal/events').then((m) => m.EventsModule))\n const eventRegistry = eventsRef.get<IEventRegistry>(DI_TOKENS.EventRegistry)\n for (const conn of config.connections) {\n const Service = createDatabaseService(conn, eventRegistry);\n\n context.container.register(connectionSymbol(conn.name), lazy(() => Service))\n }\n\n context.container.registerExisting(DI_TOKENS.Database, connectionSymbol(config.default))\n\n context.logger.info('DatabaseModule initialized')\n }\n\n onShutdown(context: ModuleContext): void {\n context.logger.info('DatabaseModule shutdown')\n }\n}\n","import { inject } from 'stratal/di'\nimport type { ConnectionName } from '../types'\nimport { connectionSymbol } from '../database.tokens'\n\nexport function InjectDB(name: ConnectionName): ParameterDecorator {\n return inject(connectionSymbol(name))\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.129.0/helpers/decorate.js
1
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -6,7 +6,7 @@ const AC_TOKENS = {
6
6
  Options: Symbol.for("stratal:ac:options")
7
7
  };
8
8
  //#endregion
9
- //#region \0@oxc-project+runtime@0.129.0/helpers/decorateParam.js
9
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/decorateParam.js
10
10
  function __decorateParam(paramIndex, decorator) {
11
11
  return function(target, key) {
12
12
  decorator(target, key, paramIndex);
@@ -15,4 +15,4 @@ function __decorateParam(paramIndex, decorator) {
15
15
  //#endregion
16
16
  export { AC_TOKENS as n, __decorateParam as t };
17
17
 
18
- //# sourceMappingURL=decorateParam-C_dJ_dIO.mjs.map
18
+ //# sourceMappingURL=decorateParam-DwV9LSPl.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorateParam-C_dJ_dIO.mjs","names":[],"sources":["../src/access-control/tokens.ts"],"sourcesContent":["export const AC_TOKENS = {\n /** Request-scoped access service */\n AccessService: Symbol.for('stratal:ac:service'),\n /** Access control module options (ac, roles) */\n Options: Symbol.for('stratal:ac:options'),\n} as const\n"],"mappings":";AAAA,MAAa,YAAY;;CAEvB,eAAe,OAAO,IAAI,qBAAqB;;CAE/C,SAAS,OAAO,IAAI,qBAAqB;CAC1C"}
1
+ {"version":3,"file":"decorateParam-DwV9LSPl.mjs","names":[],"sources":["../src/access-control/tokens.ts"],"sourcesContent":["export const AC_TOKENS = {\n /** Request-scoped access service */\n AccessService: Symbol.for('stratal:ac:service'),\n /** Access control module options (ac, roles) */\n Options: Symbol.for('stratal:ac:options'),\n} as const\n"],"mappings":";AAAA,MAAa,YAAY;;CAEvB,eAAe,OAAO,IAAI,oBAAoB;;CAE9C,SAAS,OAAO,IAAI,oBAAoB;AAC1C"}
@@ -15,4 +15,4 @@ var UserNotAuthorizedError = class extends HttpException {
15
15
  //#endregion
16
16
  export { UserNotAuthenticatedError as n, UserNotAuthorizedError as t };
17
17
 
18
- //# sourceMappingURL=errors-MCyrn_V2.mjs.map
18
+ //# sourceMappingURL=errors-BvJSaUTW.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors-MCyrn_V2.mjs","names":[],"sources":["../src/context/errors/user-not-authenticated.error.ts","../src/context/errors/user-not-authorized.error.ts"],"sourcesContent":["import { HttpException } from 'stratal/errors'\n\nexport class UserNotAuthenticatedError extends HttpException {\n constructor() { super(401, 'User is not authenticated') }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class UserNotAuthorizedError extends HttpException {\n constructor() { super(403, 'Unauthorized') }\n}\n"],"mappings":";;AAEA,IAAa,4BAAb,cAA+C,cAAc;CAC3D,cAAc;EAAE,MAAM,KAAK,4BAA4B;;;;;ACDzD,IAAa,yBAAb,cAA4C,cAAc;CACxD,cAAc;EAAE,MAAM,KAAK,eAAe"}
1
+ {"version":3,"file":"errors-BvJSaUTW.mjs","names":[],"sources":["../src/context/errors/user-not-authenticated.error.ts","../src/context/errors/user-not-authorized.error.ts"],"sourcesContent":["import { HttpException } from 'stratal/errors'\n\nexport class UserNotAuthenticatedError extends HttpException {\n constructor() { super(401, 'User is not authenticated') }\n}\n","import { HttpException } from 'stratal/errors'\n\nexport class UserNotAuthorizedError extends HttpException {\n constructor() { super(403, 'Unauthorized') }\n}\n"],"mappings":";;AAEA,IAAa,4BAAb,cAA+C,cAAc;CAC3D,cAAc;EAAE,MAAM,KAAK,2BAA2B;CAAE;AAC1D;;;ACFA,IAAa,yBAAb,cAA4C,cAAc;CACxD,cAAc;EAAE,MAAM,KAAK,cAAc;CAAE;AAC7C"}
@@ -1,4 +1,4 @@
1
- import { O as DatabaseService } from "../index-DJ_DCIul.mjs";
1
+ import { O as DatabaseService } from "../index-jILx9QXw.mjs";
2
2
  import { Faker } from "@faker-js/faker";
3
3
 
4
4
  //#region src/factory/factory.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/factory/factory.ts","../../src/factory/sequence.ts"],"mappings":";;;;;;AAuCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAAsB,OAAA;EAAA,mBACD,KAAA,EAAO,KAAA;EAAA,mBACP,KAAA;EAAA,mBACA,UAAA,CAAA,GAAc,YAAA;EAAA,QAEzB,MAAA;EAAA,QACA,MAAA;EAER,KAAA,CAAM,QAAA,GAAW,KAAA,EAAO,YAAA,KAAiB,OAAA,CAAQ,YAAA;EAMjD,KAAA,CAAM,CAAA;EAMN,IAAA,CAAA,GAAQ,YAAA;EAQR,QAAA,CAAS,KAAA,YAAiB,YAAA;EAKpB,MAAA,CAAO,EAAA,EAAI,eAAA,GAAkB,OAAA,CAAQ,MAAA;EAMrC,UAAA,CAAW,EAAA,EAAI,eAAA,EAAiB,KAAA,YAAiB,OAAA;IAAU,KAAA;EAAA;EAM3D,mBAAA,CAAoB,EAAA,EAAI,eAAA,EAAiB,KAAA,YAAiB,OAAA,CAAQ,MAAA;EAAA,UAM9D,KAAA,CAAA;AAAA;;;;;;;AAnDZ;;;;;;;;;;;;;;;;;;;;;;;;;cCVa,QAAA;EAAA,iBAGkB,SAAA;EAAA,QAFrB,OAAA;cAEqB,SAAA,KAAa,CAAA,aAAc,CAAA;EAExD,IAAA,CAAA,GAAQ,CAAA;EAQR,IAAA,CAAA,GAAQ,CAAA;EAQR,KAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/factory/factory.ts","../../src/factory/sequence.ts"],"mappings":";;;;;;AAuCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAAsB,OAAA;EAAA,mBACD,KAAA,EAAO,KAAA;EAAA,mBACP,KAAA;EAAA,mBACA,UAAA,IAAc,YAAA;EAAA,QAEzB,MAAA;EAAA,QACA,MAAA;EAER,KAAA,CAAM,QAAA,GAAW,KAAA,EAAO,YAAA,KAAiB,OAAA,CAAQ,YAAA;EAMjD,KAAA,CAAM,CAAA;EAMN,IAAA,IAAQ,YAAA;EAQR,QAAA,CAAS,KAAA,YAAiB,YAAA;EAKpB,MAAA,CAAO,EAAA,EAAI,eAAA,GAAkB,OAAA,CAAQ,MAAA;EAMrC,UAAA,CAAW,EAAA,EAAI,eAAA,EAAiB,KAAA,YAAiB,OAAA;IAAU,KAAA;EAAA;EAM3D,mBAAA,CAAoB,EAAA,EAAI,eAAA,EAAiB,KAAA,YAAiB,OAAA,CAAQ,MAAA;EAAA,UAM9D,KAAA;AAAA;;;;;;;AAnDZ;;;;;;;;;;;;;;;;;;;;;;;;;cCVa,QAAA;EAAA,iBAGkB,SAAA;EAAA,QAFrB,OAAA;cAEqB,SAAA,KAAa,CAAA,aAAc,CAAA;EAExD,IAAA,IAAQ,CAAA;EAQR,IAAA,IAAQ,CAAA;EAQR,KAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/factory/factory.ts","../../src/factory/sequence.ts"],"sourcesContent":["import { faker, type Faker } from '@faker-js/faker'\nimport type { DatabaseService } from '../database'\n\n/**\n * Factory\n *\n * Abstract base class for creating test data.\n * Integrates with Faker.js for data generation.\n *\n * @example Define a factory\n * ```typescript\n * import { Factory } from '@stratal/framework/factory'\n * import type { User, UserCreateInput } from '@your-app/db'\n *\n * export class UserFactory extends Factory<User, UserCreateInput> {\n * protected model = 'user'\n *\n * protected definition(): UserCreateInput {\n * return {\n * email: this.faker.internet.email(),\n * firstName: this.faker.person.firstName(),\n * lastName: this.faker.person.lastName(),\n * emailVerified: true,\n * }\n * }\n *\n * admin() {\n * return this.state(attrs => ({ ...attrs, role: 'admin' }))\n * }\n * }\n * ```\n *\n * @example Usage\n * ```typescript\n * const user = await new UserFactory().create(ctx.db)\n * const admin = await new UserFactory().admin().create(ctx.db)\n * const users = await new UserFactory().count(10).createManyAndReturn(ctx.db)\n * ```\n */\nexport abstract class Factory<TModel, TCreateInput> {\n protected readonly faker: Faker = faker\n protected abstract model: string\n protected abstract definition(): TCreateInput\n\n private states: ((attrs: TCreateInput) => Partial<TCreateInput>)[] = []\n private _count = 1\n\n state(modifier: (attrs: TCreateInput) => Partial<TCreateInput>): this {\n const clone = this.clone()\n clone.states.push(modifier)\n return clone\n }\n\n count(n: number): this {\n const clone = this.clone()\n clone._count = n\n return clone\n }\n\n make(): TCreateInput {\n let attrs = this.definition()\n for (const modifier of this.states) {\n attrs = { ...attrs, ...modifier(attrs) }\n }\n return attrs\n }\n\n makeMany(count?: number): TCreateInput[] {\n const n = count ?? this._count\n return Array.from({ length: n }, () => this.make())\n }\n\n async create(db: DatabaseService): Promise<TModel> {\n const data = this.make()\n const model = (db as unknown as Record<string, { create: (args: { data: TCreateInput }) => Promise<TModel> }>)[this.model]\n return model.create({ data })\n }\n\n async createMany(db: DatabaseService, count?: number): Promise<{ count: number }> {\n const data = this.makeMany(count)\n const model = (db as unknown as Record<string, { createMany: (args: { data: TCreateInput[] }) => Promise<{ count: number }> }>)[this.model]\n return model.createMany({ data })\n }\n\n async createManyAndReturn(db: DatabaseService, count?: number): Promise<TModel[]> {\n const data = this.makeMany(count)\n const model = (db as unknown as Record<string, { createManyAndReturn: (args: { data: TCreateInput[] }) => Promise<TModel[]> }>)[this.model]\n return model.createManyAndReturn({ data })\n }\n\n protected clone(): this {\n const FactoryClass = this.constructor as new () => this\n const clone = new FactoryClass()\n clone.states = [...this.states]\n clone._count = this._count\n return clone\n }\n}\n","/**\n * Sequence\n *\n * Auto-incrementing sequence generator for creating unique values.\n *\n * @example Basic usage\n * ```typescript\n * const emailSeq = new Sequence((n) => `user${n}@example.com`)\n *\n * emailSeq.next() // 'user1@example.com'\n * emailSeq.next() // 'user2@example.com'\n * emailSeq.reset()\n * emailSeq.next() // 'user1@example.com'\n * ```\n *\n * @example With factory\n * ```typescript\n * const orderSeq = new Sequence((n) => `ORD-${String(n).padStart(6, '0')}`)\n *\n * export class OrderFactory extends Factory<Order, OrderCreateInput> {\n * protected definition() {\n * return {\n * orderNumber: orderSeq.next(),\n * // ...\n * }\n * }\n * }\n * ```\n */\nexport class Sequence<T = number> {\n private current = 0\n\n constructor(private readonly generator?: (n: number) => T) {}\n\n next(): T {\n this.current++\n if (this.generator) {\n return this.generator(this.current)\n }\n return this.current as T\n }\n\n peek(): T {\n const value = this.current + 1\n if (this.generator) {\n return this.generator(value)\n }\n return value as T\n }\n\n reset(): void {\n this.current = 0\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAsB,UAAtB,MAAoD;CAClD,QAAkC;CAIlC,SAAqE,EAAE;CACvE,SAAiB;CAEjB,MAAM,UAAgE;EACpE,MAAM,QAAQ,KAAK,OAAO;EAC1B,MAAM,OAAO,KAAK,SAAS;EAC3B,OAAO;;CAGT,MAAM,GAAiB;EACrB,MAAM,QAAQ,KAAK,OAAO;EAC1B,MAAM,SAAS;EACf,OAAO;;CAGT,OAAqB;EACnB,IAAI,QAAQ,KAAK,YAAY;EAC7B,KAAK,MAAM,YAAY,KAAK,QAC1B,QAAQ;GAAE,GAAG;GAAO,GAAG,SAAS,MAAM;GAAE;EAE1C,OAAO;;CAGT,SAAS,OAAgC;EACvC,MAAM,IAAI,SAAS,KAAK;EACxB,OAAO,MAAM,KAAK,EAAE,QAAQ,GAAG,QAAQ,KAAK,MAAM,CAAC;;CAGrD,MAAM,OAAO,IAAsC;EACjD,MAAM,OAAO,KAAK,MAAM;EAExB,OADe,GAAgG,KAAK,OACvG,OAAO,EAAE,MAAM,CAAC;;CAG/B,MAAM,WAAW,IAAqB,OAA4C;EAChF,MAAM,OAAO,KAAK,SAAS,MAAM;EAEjC,OADe,GAAiH,KAAK,OACxH,WAAW,EAAE,MAAM,CAAC;;CAGnC,MAAM,oBAAoB,IAAqB,OAAmC;EAChF,MAAM,OAAO,KAAK,SAAS,MAAM;EAEjC,OADe,GAAiH,KAAK,OACxH,oBAAoB,EAAE,MAAM,CAAC;;CAG5C,QAAwB;EACtB,MAAM,eAAe,KAAK;EAC1B,MAAM,QAAQ,IAAI,cAAc;EAChC,MAAM,SAAS,CAAC,GAAG,KAAK,OAAO;EAC/B,MAAM,SAAS,KAAK;EACpB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClEX,IAAa,WAAb,MAAkC;CAGH;CAF7B,UAAkB;CAElB,YAAY,WAA+C;EAA9B,KAAA,YAAA;;CAE7B,OAAU;EACR,KAAK;EACL,IAAI,KAAK,WACP,OAAO,KAAK,UAAU,KAAK,QAAQ;EAErC,OAAO,KAAK;;CAGd,OAAU;EACR,MAAM,QAAQ,KAAK,UAAU;EAC7B,IAAI,KAAK,WACP,OAAO,KAAK,UAAU,MAAM;EAE9B,OAAO;;CAGT,QAAc;EACZ,KAAK,UAAU"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/factory/factory.ts","../../src/factory/sequence.ts"],"sourcesContent":["import { faker, type Faker } from '@faker-js/faker'\nimport type { DatabaseService } from '../database'\n\n/**\n * Factory\n *\n * Abstract base class for creating test data.\n * Integrates with Faker.js for data generation.\n *\n * @example Define a factory\n * ```typescript\n * import { Factory } from '@stratal/framework/factory'\n * import type { User, UserCreateInput } from '@your-app/db'\n *\n * export class UserFactory extends Factory<User, UserCreateInput> {\n * protected model = 'user'\n *\n * protected definition(): UserCreateInput {\n * return {\n * email: this.faker.internet.email(),\n * firstName: this.faker.person.firstName(),\n * lastName: this.faker.person.lastName(),\n * emailVerified: true,\n * }\n * }\n *\n * admin() {\n * return this.state(attrs => ({ ...attrs, role: 'admin' }))\n * }\n * }\n * ```\n *\n * @example Usage\n * ```typescript\n * const user = await new UserFactory().create(ctx.db)\n * const admin = await new UserFactory().admin().create(ctx.db)\n * const users = await new UserFactory().count(10).createManyAndReturn(ctx.db)\n * ```\n */\nexport abstract class Factory<TModel, TCreateInput> {\n protected readonly faker: Faker = faker\n protected abstract model: string\n protected abstract definition(): TCreateInput\n\n private states: ((attrs: TCreateInput) => Partial<TCreateInput>)[] = []\n private _count = 1\n\n state(modifier: (attrs: TCreateInput) => Partial<TCreateInput>): this {\n const clone = this.clone()\n clone.states.push(modifier)\n return clone\n }\n\n count(n: number): this {\n const clone = this.clone()\n clone._count = n\n return clone\n }\n\n make(): TCreateInput {\n let attrs = this.definition()\n for (const modifier of this.states) {\n attrs = { ...attrs, ...modifier(attrs) }\n }\n return attrs\n }\n\n makeMany(count?: number): TCreateInput[] {\n const n = count ?? this._count\n return Array.from({ length: n }, () => this.make())\n }\n\n async create(db: DatabaseService): Promise<TModel> {\n const data = this.make()\n const model = (db as unknown as Record<string, { create: (args: { data: TCreateInput }) => Promise<TModel> }>)[this.model]\n return model.create({ data })\n }\n\n async createMany(db: DatabaseService, count?: number): Promise<{ count: number }> {\n const data = this.makeMany(count)\n const model = (db as unknown as Record<string, { createMany: (args: { data: TCreateInput[] }) => Promise<{ count: number }> }>)[this.model]\n return model.createMany({ data })\n }\n\n async createManyAndReturn(db: DatabaseService, count?: number): Promise<TModel[]> {\n const data = this.makeMany(count)\n const model = (db as unknown as Record<string, { createManyAndReturn: (args: { data: TCreateInput[] }) => Promise<TModel[]> }>)[this.model]\n return model.createManyAndReturn({ data })\n }\n\n protected clone(): this {\n const FactoryClass = this.constructor as new () => this\n const clone = new FactoryClass()\n clone.states = [...this.states]\n clone._count = this._count\n return clone\n }\n}\n","/**\n * Sequence\n *\n * Auto-incrementing sequence generator for creating unique values.\n *\n * @example Basic usage\n * ```typescript\n * const emailSeq = new Sequence((n) => `user${n}@example.com`)\n *\n * emailSeq.next() // 'user1@example.com'\n * emailSeq.next() // 'user2@example.com'\n * emailSeq.reset()\n * emailSeq.next() // 'user1@example.com'\n * ```\n *\n * @example With factory\n * ```typescript\n * const orderSeq = new Sequence((n) => `ORD-${String(n).padStart(6, '0')}`)\n *\n * export class OrderFactory extends Factory<Order, OrderCreateInput> {\n * protected definition() {\n * return {\n * orderNumber: orderSeq.next(),\n * // ...\n * }\n * }\n * }\n * ```\n */\nexport class Sequence<T = number> {\n private current = 0\n\n constructor(private readonly generator?: (n: number) => T) {}\n\n next(): T {\n this.current++\n if (this.generator) {\n return this.generator(this.current)\n }\n return this.current as T\n }\n\n peek(): T {\n const value = this.current + 1\n if (this.generator) {\n return this.generator(value)\n }\n return value as T\n }\n\n reset(): void {\n this.current = 0\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAsB,UAAtB,MAAoD;CAClD,QAAkC;CAIlC,SAAqE,CAAC;CACtE,SAAiB;CAEjB,MAAM,UAAgE;EACpE,MAAM,QAAQ,KAAK,MAAM;EACzB,MAAM,OAAO,KAAK,QAAQ;EAC1B,OAAO;CACT;CAEA,MAAM,GAAiB;EACrB,MAAM,QAAQ,KAAK,MAAM;EACzB,MAAM,SAAS;EACf,OAAO;CACT;CAEA,OAAqB;EACnB,IAAI,QAAQ,KAAK,WAAW;EAC5B,KAAK,MAAM,YAAY,KAAK,QAC1B,QAAQ;GAAE,GAAG;GAAO,GAAG,SAAS,KAAK;EAAE;EAEzC,OAAO;CACT;CAEA,SAAS,OAAgC;EACvC,MAAM,IAAI,SAAS,KAAK;EACxB,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,KAAK,KAAK,CAAC;CACpD;CAEA,MAAM,OAAO,IAAsC;EACjD,MAAM,OAAO,KAAK,KAAK;EAEvB,OADe,GAAgG,KAAK,OACvG,OAAO,EAAE,KAAK,CAAC;CAC9B;CAEA,MAAM,WAAW,IAAqB,OAA4C;EAChF,MAAM,OAAO,KAAK,SAAS,KAAK;EAEhC,OADe,GAAiH,KAAK,OACxH,WAAW,EAAE,KAAK,CAAC;CAClC;CAEA,MAAM,oBAAoB,IAAqB,OAAmC;EAChF,MAAM,OAAO,KAAK,SAAS,KAAK;EAEhC,OADe,GAAiH,KAAK,OACxH,oBAAoB,EAAE,KAAK,CAAC;CAC3C;CAEA,QAAwB;EACtB,MAAM,eAAe,KAAK;EAC1B,MAAM,QAAQ,IAAI,aAAa;EAC/B,MAAM,SAAS,CAAC,GAAG,KAAK,MAAM;EAC9B,MAAM,SAAS,KAAK;EACpB,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpEA,IAAa,WAAb,MAAkC;CAGH;CAF7B,UAAkB;CAElB,YAAY,WAA+C;EAA9B,KAAA,YAAA;CAA+B;CAE5D,OAAU;EACR,KAAK;EACL,IAAI,KAAK,WACP,OAAO,KAAK,UAAU,KAAK,OAAO;EAEpC,OAAO,KAAK;CACd;CAEA,OAAU;EACR,MAAM,QAAQ,KAAK,UAAU;EAC7B,IAAI,KAAK,WACP,OAAO,KAAK,UAAU,KAAK;EAE7B,OAAO;CACT;CAEA,QAAc;EACZ,KAAK,UAAU;CACjB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/auth.guard.ts"],"mappings":";;;;;AAqDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,SAAA,CAAU,OAAA,GAAU,kBAAA,GAAmB,YAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/auth.guard.ts"],"mappings":";;;;;AAqDA;;;;;;;;AAAiE;;;;;;;;;;;;;;;;;;;;;iBAAjD,SAAA,CAAU,OAAA,GAAU,kBAAA,GAAmB,YAAU"}
@@ -1,7 +1,7 @@
1
- import { n as AC_TOKENS, t as __decorateParam } from "../decorateParam-C_dJ_dIO.mjs";
2
- import { t as __decorate } from "../decorate-7CAoTBu4.mjs";
3
- import { n as UserNotAuthenticatedError } from "../errors-MCyrn_V2.mjs";
4
- import { t as InsufficientPermissionsError } from "../insufficient-permissions.error-GwrkWnEM.mjs";
1
+ import { n as AC_TOKENS, t as __decorateParam } from "../decorateParam-DwV9LSPl.mjs";
2
+ import { t as __decorate } from "../decorate-B7nr7eBl.mjs";
3
+ import { n as UserNotAuthenticatedError } from "../errors-BvJSaUTW.mjs";
4
+ import { t as InsufficientPermissionsError } from "../insufficient-permissions.error-DeEyZRgy.mjs";
5
5
  import { DI_TOKENS, Transient, inject } from "stratal/di";
6
6
  import { LOGGER_TOKENS } from "stratal/logger";
7
7
  import { GUARD_METADATA_KEY, GuardExecutionService, UseGuards, getControllerGuards, getMethodGuards } from "stratal/guards";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/guards/auth.guard.ts"],"sourcesContent":["import { DI_TOKENS, inject, Transient } from 'stratal/di'\nimport type { AuthGuardOptions, CanActivate, GuardClass } from 'stratal/guards'\nimport { LOGGER_TOKENS, type LoggerService } from 'stratal/logger'\nimport type { RouterContext } from 'stratal/router'\nimport { InsufficientPermissionsError } from '../access-control/errors/insufficient-permissions.error'\nimport type { AccessService } from '../access-control/services/access.service'\nimport { AC_TOKENS } from '../access-control/tokens'\nimport type { AuthContext } from '../context/auth-context'\nimport { UserNotAuthenticatedError } from '../context/errors'\n\nfunction parsePermissions(raw: string | string[]): Record<string, string[]> {\n const list = Array.isArray(raw) ? raw : [raw]\n return list.reduce<Record<string, string[]>>((acc, perm) => {\n const colon = perm.indexOf(':')\n const resource = colon === -1 ? perm : perm.slice(0, colon)\n const action = colon === -1 ? '*' : perm.slice(colon + 1)\n ;(acc[resource] ??= []).push(action)\n return acc\n }, {})\n}\n\n\n/**\n * AuthGuard Factory\n *\n * Creates a guard class that enforces authentication and optional authorization.\n *\n * **Authentication (no permissions):**\n * - Checks if user is authenticated via AuthContext.isAuthenticated()\n * - Throws UserNotAuthenticatedError (401) if not authenticated\n *\n * **Authorization (with permissions):**\n * - First verifies authentication\n * - Then checks permissions via AccessService (reads from AuthContext — no DB hit)\n * - Throws InsufficientPermissionsError (403) if unauthorized\n *\n * @param options - Configuration options\n * @param options.permissions - Required permissions keyed by resource\n * @returns Guard class for use with @UseGuards decorator\n *\n * @example Authentication only\n * ```typescript\n * @UseGuards(AuthGuard())\n * export class ProfileController { }\n * ```\n *\n * @example Authentication with permissions\n * ```typescript\n * @UseGuards(AuthGuard({ permissions: 'posts:update' }))\n * @UseGuards(AuthGuard({ permissions: ['posts:update', 'posts:delete'] }))\n * export class PostsController { }\n * ```\n */\nexport function AuthGuard(options?: AuthGuardOptions): GuardClass {\n const rawPermissions = options?.permissions\n const permissions = rawPermissions ? parsePermissions(rawPermissions) : undefined\n\n @Transient()\n class ConfiguredAuthGuard implements CanActivate {\n constructor(\n @inject(DI_TOKENS.AuthContext) private readonly authContext: AuthContext,\n @inject(LOGGER_TOKENS.LoggerService) private readonly logger: LoggerService,\n @inject(AC_TOKENS.AccessService, { isOptional: true }) private readonly accessService?: AccessService\n ) { }\n\n async canActivate(_context: RouterContext): Promise<boolean> {\n if (!this.authContext.isAuthenticated()) {\n this.logger.debug('Auth guard: User not authenticated')\n throw new UserNotAuthenticatedError()\n }\n\n if (!permissions || Object.keys(permissions).length === 0) {\n this.logger.debug('Auth guard: Authentication passed (no permissions required)')\n return true\n }\n\n const userId = this.authContext.getUserId()\n if (!userId) {\n this.logger.debug('Auth guard: No user ID in context')\n throw new InsufficientPermissionsError(rawPermissions!)\n }\n\n if (this.accessService) {\n const allowed = await this.accessService.hasPermission(userId, permissions)\n\n this.logger.debug('Auth guard: Authorization check', {\n userId,\n permissions,\n allowed,\n })\n\n if (!allowed) {\n throw new InsufficientPermissionsError(rawPermissions!, userId)\n }\n }\n\n return true\n }\n }\n\n return ConfiguredAuthGuard\n}\n"],"mappings":";;;;;;;;AAUA,SAAS,iBAAiB,KAAkD;CAE1E,QADa,MAAM,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI,EACjC,QAAkC,KAAK,SAAS;EAC1D,MAAM,QAAQ,KAAK,QAAQ,IAAI;EAC/B,MAAM,WAAW,UAAU,KAAK,OAAO,KAAK,MAAM,GAAG,MAAM;EAC3D,MAAM,SAAS,UAAU,KAAK,MAAM,KAAK,MAAM,QAAQ,EAAE;EACxD,CAAC,IAAI,cAAc,EAAE,EAAE,KAAK,OAAO;EACpC,OAAO;IACN,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCR,SAAgB,UAAU,SAAwC;CAChE,MAAM,iBAAiB,SAAS;CAChC,MAAM,cAAc,iBAAiB,iBAAiB,eAAe,GAAG,KAAA;CAExE,IAAA,sBAAA,MACM,oBAA2C;EAEG;EACM;EACkB;EAH1E,YACE,aACA,QACA,eACA;GAHgD,KAAA,cAAA;GACM,KAAA,SAAA;GACkB,KAAA,gBAAA;;EAG1E,MAAM,YAAY,UAA2C;GAC3D,IAAI,CAAC,KAAK,YAAY,iBAAiB,EAAE;IACvC,KAAK,OAAO,MAAM,qCAAqC;IACvD,MAAM,IAAI,2BAA2B;;GAGvC,IAAI,CAAC,eAAe,OAAO,KAAK,YAAY,CAAC,WAAW,GAAG;IACzD,KAAK,OAAO,MAAM,8DAA8D;IAChF,OAAO;;GAGT,MAAM,SAAS,KAAK,YAAY,WAAW;GAC3C,IAAI,CAAC,QAAQ;IACX,KAAK,OAAO,MAAM,oCAAoC;IACtD,MAAM,IAAI,6BAA6B,eAAgB;;GAGzD,IAAI,KAAK,eAAe;IACtB,MAAM,UAAU,MAAM,KAAK,cAAc,cAAc,QAAQ,YAAY;IAE3E,KAAK,OAAO,MAAM,mCAAmC;KACnD;KACA;KACA;KACD,CAAC;IAEF,IAAI,CAAC,SACH,MAAM,IAAI,6BAA6B,gBAAiB,OAAO;;GAInE,OAAO;;;;EAvCV,WAAW;qBAGP,OAAO,UAAU,YAAY,CAAA;qBAC7B,OAAO,cAAc,cAAc,CAAA;qBACnC,OAAO,UAAU,eAAe,EAAE,YAAY,MAAM,CAAC,CAAA;;CAsC1D,OAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/guards/auth.guard.ts"],"sourcesContent":["import { DI_TOKENS, inject, Transient } from 'stratal/di'\nimport type { AuthGuardOptions, CanActivate, GuardClass } from 'stratal/guards'\nimport { LOGGER_TOKENS, type LoggerService } from 'stratal/logger'\nimport type { RouterContext } from 'stratal/router'\nimport { InsufficientPermissionsError } from '../access-control/errors/insufficient-permissions.error'\nimport type { AccessService } from '../access-control/services/access.service'\nimport { AC_TOKENS } from '../access-control/tokens'\nimport type { AuthContext } from '../context/auth-context'\nimport { UserNotAuthenticatedError } from '../context/errors'\n\nfunction parsePermissions(raw: string | string[]): Record<string, string[]> {\n const list = Array.isArray(raw) ? raw : [raw]\n return list.reduce<Record<string, string[]>>((acc, perm) => {\n const colon = perm.indexOf(':')\n const resource = colon === -1 ? perm : perm.slice(0, colon)\n const action = colon === -1 ? '*' : perm.slice(colon + 1)\n ;(acc[resource] ??= []).push(action)\n return acc\n }, {})\n}\n\n\n/**\n * AuthGuard Factory\n *\n * Creates a guard class that enforces authentication and optional authorization.\n *\n * **Authentication (no permissions):**\n * - Checks if user is authenticated via AuthContext.isAuthenticated()\n * - Throws UserNotAuthenticatedError (401) if not authenticated\n *\n * **Authorization (with permissions):**\n * - First verifies authentication\n * - Then checks permissions via AccessService (reads from AuthContext — no DB hit)\n * - Throws InsufficientPermissionsError (403) if unauthorized\n *\n * @param options - Configuration options\n * @param options.permissions - Required permissions keyed by resource\n * @returns Guard class for use with @UseGuards decorator\n *\n * @example Authentication only\n * ```typescript\n * @UseGuards(AuthGuard())\n * export class ProfileController { }\n * ```\n *\n * @example Authentication with permissions\n * ```typescript\n * @UseGuards(AuthGuard({ permissions: 'posts:update' }))\n * @UseGuards(AuthGuard({ permissions: ['posts:update', 'posts:delete'] }))\n * export class PostsController { }\n * ```\n */\nexport function AuthGuard(options?: AuthGuardOptions): GuardClass {\n const rawPermissions = options?.permissions\n const permissions = rawPermissions ? parsePermissions(rawPermissions) : undefined\n\n @Transient()\n class ConfiguredAuthGuard implements CanActivate {\n constructor(\n @inject(DI_TOKENS.AuthContext) private readonly authContext: AuthContext,\n @inject(LOGGER_TOKENS.LoggerService) private readonly logger: LoggerService,\n @inject(AC_TOKENS.AccessService, { isOptional: true }) private readonly accessService?: AccessService\n ) { }\n\n async canActivate(_context: RouterContext): Promise<boolean> {\n if (!this.authContext.isAuthenticated()) {\n this.logger.debug('Auth guard: User not authenticated')\n throw new UserNotAuthenticatedError()\n }\n\n if (!permissions || Object.keys(permissions).length === 0) {\n this.logger.debug('Auth guard: Authentication passed (no permissions required)')\n return true\n }\n\n const userId = this.authContext.getUserId()\n if (!userId) {\n this.logger.debug('Auth guard: No user ID in context')\n throw new InsufficientPermissionsError(rawPermissions!)\n }\n\n if (this.accessService) {\n const allowed = await this.accessService.hasPermission(userId, permissions)\n\n this.logger.debug('Auth guard: Authorization check', {\n userId,\n permissions,\n allowed,\n })\n\n if (!allowed) {\n throw new InsufficientPermissionsError(rawPermissions!, userId)\n }\n }\n\n return true\n }\n }\n\n return ConfiguredAuthGuard\n}\n"],"mappings":";;;;;;;;AAUA,SAAS,iBAAiB,KAAkD;CAE1E,QADa,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG,GAChC,QAAkC,KAAK,SAAS;EAC1D,MAAM,QAAQ,KAAK,QAAQ,GAAG;EAC9B,MAAM,WAAW,UAAU,KAAK,OAAO,KAAK,MAAM,GAAG,KAAK;EAC1D,MAAM,SAAS,UAAU,KAAK,MAAM,KAAK,MAAM,QAAQ,CAAC;EACvD,CAAC,IAAI,cAAc,CAAC,GAAG,KAAK,MAAM;EACnC,OAAO;CACT,GAAG,CAAC,CAAC;AACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,UAAU,SAAwC;CAChE,MAAM,iBAAiB,SAAS;CAChC,MAAM,cAAc,iBAAiB,iBAAiB,cAAc,IAAI,KAAA;CAExE,IAAA,sBAAA,MACM,oBAA2C;EAEG;EACM;EACkB;EAH1E,YACE,aACA,QACA,eACA;GAHgD,KAAA,cAAA;GACM,KAAA,SAAA;GACkB,KAAA,gBAAA;EACtE;EAEJ,MAAM,YAAY,UAA2C;GAC3D,IAAI,CAAC,KAAK,YAAY,gBAAgB,GAAG;IACvC,KAAK,OAAO,MAAM,oCAAoC;IACtD,MAAM,IAAI,0BAA0B;GACtC;GAEA,IAAI,CAAC,eAAe,OAAO,KAAK,WAAW,EAAE,WAAW,GAAG;IACzD,KAAK,OAAO,MAAM,6DAA6D;IAC/E,OAAO;GACT;GAEA,MAAM,SAAS,KAAK,YAAY,UAAU;GAC1C,IAAI,CAAC,QAAQ;IACX,KAAK,OAAO,MAAM,mCAAmC;IACrD,MAAM,IAAI,6BAA6B,cAAe;GACxD;GAEA,IAAI,KAAK,eAAe;IACtB,MAAM,UAAU,MAAM,KAAK,cAAc,cAAc,QAAQ,WAAW;IAE1E,KAAK,OAAO,MAAM,mCAAmC;KACnD;KACA;KACA;IACF,CAAC;IAED,IAAI,CAAC,SACH,MAAM,IAAI,6BAA6B,gBAAiB,MAAM;GAElE;GAEA,OAAO;EACT;CACF;;EAzCC,UAAU;qBAGN,OAAO,UAAU,WAAW,CAAA;qBAC5B,OAAO,cAAc,aAAa,CAAA;qBAClC,OAAO,UAAU,eAAe,EAAE,YAAY,KAAK,CAAC,CAAA;;CAsCzD,OAAO;AACT"}
@@ -1,4 +1,4 @@
1
- import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, r as InferAnySchema, t as ConnectionName } from "./types-4uX3XKRM.mjs";
1
+ import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, r as InferAnySchema, t as ConnectionName } from "./types-CWZ9q74G.mjs";
2
2
  import { AsyncModuleOptions, DynamicModule, ModuleContext, OnInitialize, OnShutdown } from "stratal/module";
3
3
  import { ApplicationError, HttpException } from "stratal/errors";
4
4
  import { Command } from "stratal/quarry";
@@ -27,7 +27,7 @@ interface DatabaseModuleConfig {
27
27
  declare class DatabaseModule implements OnInitialize, OnShutdown {
28
28
  static forRoot(config: DatabaseModuleConfig): DynamicModule;
29
29
  static forRootAsync(options: AsyncModuleOptions<DatabaseModuleConfig>): DynamicModule;
30
- onInitialize(context: ModuleContext): void;
30
+ onInitialize(context: ModuleContext): Promise<void>;
31
31
  onShutdown(context: ModuleContext): void;
32
32
  }
33
33
  //#endregion
@@ -363,4 +363,4 @@ declare class MigrateStatusCommand extends ZenStackCommand {
363
363
  }
364
364
  //#endregion
365
365
  export { DatabaseModule as A, UniqueConstraintError as C, connectionSymbol as D, DATABASE_TOKENS as E, DatabaseService as O, fromZenStackError as S, InjectDB as T, EventPhase as _, DbPushCommand as a, ModelName as b, ZenStackCommand as c, EventEmitterPluginOptions as d, ErrorHandlerPlugin as f, DatabaseOperation as g, DatabaseEvents as h, MigrateDeployCommand as i, DatabaseModuleConfig as j, DatabaseConnectionConfig as k, SchemaSwitcher as l, DatabaseEventName as m, MigrateResetCommand as n, DbPullCommand as o, databaseMessages as p, MigrateDevCommand as r, DbGenerateCommand as s, MigrateStatusCommand as t, EventEmitterPlugin as u, GetData as v, RecordNotFoundError as w, ParseEvent as x, GetResult as y };
366
- //# sourceMappingURL=index-DJ_DCIul.d.mts.map
366
+ //# sourceMappingURL=index-jILx9QXw.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-jILx9QXw.d.mts","names":[],"sources":["../src/database/database.module.ts","../src/database/database.service.ts","../src/database/database.tokens.ts","../src/database/decorators/inject-db.decorator.ts","../src/database/errors/record-not-found.error.ts","../src/database/errors/unique-constraint.error.ts","../src/database/errors/from-zenstack-error.ts","../src/database/event-types.ts","../src/database/i18n/en.ts","../src/database/plugins/error-handler.plugin.ts","../src/database/plugins/event-emitter.plugin.ts","../src/database/plugins/schema-switcher.ts","../src/database/commands/zenstack.command.ts","../src/database/commands/db-generate.command.ts","../src/database/commands/db-pull.command.ts","../src/database/commands/db-push.command.ts","../src/database/commands/migrate-deploy.command.ts","../src/database/commands/migrate-dev.command.ts","../src/database/commands/migrate-reset.command.ts","../src/database/commands/migrate-status.command.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, r as InferAnySchema, s as StratalDatabase, t as ConnectionName } from "./types-4uX3XKRM.mjs";
1
+ import { a as InferConnectionSchema, i as InferConnectionExtensions, n as DefaultConnectionName, r as InferAnySchema, s as StratalDatabase, t as ConnectionName } from "./types-CWZ9q74G.mjs";
2
2
  import { CustomEventRegistry, EventName } from "stratal/events";
3
- export { type ConnectionName, type CustomEventRegistry, type DefaultConnectionName, type EventName, type InferAnySchema, type InferConnectionExtensions, type InferConnectionSchema, type StratalDatabase };
3
+ export type { ConnectionName, CustomEventRegistry, DefaultConnectionName, EventName, InferAnySchema, InferConnectionExtensions, InferConnectionSchema, StratalDatabase };
@@ -13,4 +13,4 @@ var InsufficientPermissionsError = class extends HttpException {
13
13
  //#endregion
14
14
  export { InsufficientPermissionsError as t };
15
15
 
16
- //# sourceMappingURL=insufficient-permissions.error-GwrkWnEM.mjs.map
16
+ //# sourceMappingURL=insufficient-permissions.error-DeEyZRgy.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"insufficient-permissions.error-GwrkWnEM.mjs","names":[],"sources":["../src/access-control/errors/insufficient-permissions.error.ts"],"sourcesContent":["import { HttpException } from 'stratal/errors'\n\nexport class InsufficientPermissionsError extends HttpException {\n public readonly requiredPermissions: string\n public readonly userId?: string\n\n constructor(requiredPermissions: string | string[], userId?: string) {\n const summary = Array.isArray(requiredPermissions) ? requiredPermissions.join(', ') : requiredPermissions\n super(403, 'Insufficient permissions')\n this.requiredPermissions = summary\n this.userId = userId\n }\n}\n"],"mappings":";;AAEA,IAAa,+BAAb,cAAkD,cAAc;CAC9D;CACA;CAEA,YAAY,qBAAwC,QAAiB;EACnE,MAAM,UAAU,MAAM,QAAQ,oBAAoB,GAAG,oBAAoB,KAAK,KAAK,GAAG;EACtF,MAAM,KAAK,2BAA2B;EACtC,KAAK,sBAAsB;EAC3B,KAAK,SAAS"}
1
+ {"version":3,"file":"insufficient-permissions.error-DeEyZRgy.mjs","names":[],"sources":["../src/access-control/errors/insufficient-permissions.error.ts"],"sourcesContent":["import { HttpException } from 'stratal/errors'\n\nexport class InsufficientPermissionsError extends HttpException {\n public readonly requiredPermissions: string\n public readonly userId?: string\n\n constructor(requiredPermissions: string | string[], userId?: string) {\n const summary = Array.isArray(requiredPermissions) ? requiredPermissions.join(', ') : requiredPermissions\n super(403, 'Insufficient permissions')\n this.requiredPermissions = summary\n this.userId = userId\n }\n}\n"],"mappings":";;AAEA,IAAa,+BAAb,cAAkD,cAAc;CAC9D;CACA;CAEA,YAAY,qBAAwC,QAAiB;EACnE,MAAM,UAAU,MAAM,QAAQ,mBAAmB,IAAI,oBAAoB,KAAK,IAAI,IAAI;EACtF,MAAM,KAAK,0BAA0B;EACrC,KAAK,sBAAsB;EAC3B,KAAK,SAAS;CAChB;AACF"}
@@ -89,4 +89,4 @@ interface InternalDatabaseEventContext {
89
89
  }
90
90
  //#endregion
91
91
  export { InferConnectionSchema as a, InferConnectionExtensions as i, DefaultConnectionName as n, InternalDatabaseEventContext as o, InferAnySchema as r, StratalDatabase as s, ConnectionName as t };
92
- //# sourceMappingURL=types-4uX3XKRM.d.mts.map
92
+ //# sourceMappingURL=types-CWZ9q74G.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CWZ9q74G.d.mts","names":[],"sources":["../src/database/types.ts"],"mappings":";;;;;;AA+BA;;;;AAAgC;AAAG;;;;;;;;;;;;;AAIiC;AAAA;;;;;;;UAJnD,eAAA;;KAGZ,sBAAA,MACH,CAAA,SAAU,aAAa,0CAA0C,CAAA;;KAG9D,0BAAA,MACH,CAAA,SAAU,aAAa,0CAA0C,CAAA;AAAC;AAAA,KAG/D,mBAAA,MACH,CAAA,SAAU,aAAa,0CAA0C,CAAA;;KAG9D,YAAA,8BACH,OAAA;EAEM,YAAA,EAAc,sBAAA,CAAuB,CAAA,IAAK,YAAA,CAAa,IAAA;EACvD,gBAAA,EAAkB,0BAAA,CAA2B,CAAA,IAAK,YAAA,CAAa,IAAA;EAC/D,SAAA,EAAW,mBAAA,CAAoB,CAAA,IAAK,YAAA,CAAa,IAAA;AAAA;EAEjD,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;;KAGpC,yBAAA,qBACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,eAAgB,CAAA,GACd,CAAA,CAAE,CAAA,sBACA,YAAA,CAAa,CAAA,CAAE,CAAA;EACb,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;EAC1C,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;EAC1C,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;;KAGpC,qBAAA,qBACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,eAAgB,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,SAAA,GAAY,CAAA,CAAE,CAAA,IAAK,SAAA,GAAY,SAAA,GAChE,SAAA;;KAGM,cAAA,GACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,OAAQ,CAAA,UAAW,SAAA,GAAY,CAAA,OAAQ,CAAA,IAAK,SAAA,GAC5C,SAAA;;KAGM,cAAA,GACV,eAAA;EAA0B,OAAA;AAAA,UAChB,CAAA,0BAA2B,OAAA,OAAc,CAAA;;KAIzC,qBAAA,GACV,eAAe;EAAW,iBAAA;AAAA,IAA8C,CAAA;;;;;UAMzD,4BAAA;EACf,IAAA;EACA,MAAM;AAAA"}
@@ -8,4 +8,4 @@ interface AccessControlOptions<TStatements extends Statements = Statements, TRol
8
8
  }
9
9
  //#endregion
10
10
  export { RolePermissions as n, AccessControlOptions as t };
11
- //# sourceMappingURL=types-tu9pTehB.d.mts.map
11
+ //# sourceMappingURL=types-DabF8LGz.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-tu9pTehB.d.mts","names":[],"sources":["../src/access-control/types.ts"],"mappings":";;;KAEY,eAAA,qBAAoC,UAAA,kBAClC,WAAA,aAAwB,WAAA,CAAY,CAAA;AAAA,UAGjC,oBAAA,qBAAyC,UAAA,GAAa,UAAA,iBAA2B,MAAA,SAAe,eAAA,CAAgB,WAAA,KAAgB,MAAA,SAAe,eAAA,CAAgB,WAAA;EAC9K,EAAA,EAAI,aAAA;EACJ,KAAA,gBAAqB,MAAA,GAAS,IAAA;AAAA"}
1
+ {"version":3,"file":"types-DabF8LGz.d.mts","names":[],"sources":["../src/access-control/types.ts"],"mappings":";;;KAEY,eAAA,qBAAoC,UAAA,kBAClC,WAAA,aAAwB,WAAA,CAAY,CAAA;AAAA,UAGjC,oBAAA,qBAAyC,UAAA,GAAa,UAAA,iBAA2B,MAAA,SAAe,eAAA,CAAgB,WAAA,KAAgB,MAAA,SAAe,eAAA,CAAgB,WAAA;EAC9K,EAAA,EAAI,aAAA;EACJ,KAAA,gBAAqB,MAAA,GAAS,IAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratal/framework",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Temitayo Fadojutimi",
@@ -57,10 +57,10 @@
57
57
  "generate": "zenstack generate --schema=test/schema.zmodel -o test/zenstack",
58
58
  "generate:types": "wrangler types -c test/wrangler.jsonc",
59
59
  "pretest": "npx dotenv -- yarn generate && yarn generate:types",
60
- "test": "vitest run",
61
- "test:watch": "vitest",
62
- "test:e2e": "vitest run --project e2e",
63
- "test:coverage": "vitest run --coverage",
60
+ "test": "npx dotenv -- vitest run",
61
+ "test:watch": "npx dotenv -- vitest",
62
+ "test:e2e": "npx dotenv -- vitest run --project e2e",
63
+ "test:coverage": "npx dotenv -- vitest run --coverage",
64
64
  "test:db": "docker compose -f test/docker-compose.yml up -d",
65
65
  "typecheck": "yarn tsc --noEmit",
66
66
  "lint": "npx oxlint .",
@@ -77,29 +77,29 @@
77
77
  "@zenstackhq/schema": ">=3.6",
78
78
  "better-auth": ">=1.6",
79
79
  "pg": "^8.0.0",
80
- "stratal": "^0.0.22"
80
+ "stratal": "^0.0.24"
81
81
  },
82
82
  "devDependencies": {
83
- "@better-auth/core": "^1.6.11",
84
- "@cloudflare/vitest-pool-workers": "^0.16.3",
85
- "@cloudflare/workers-types": "4.20260510.1",
83
+ "@better-auth/core": "^1.6.14",
84
+ "@cloudflare/vitest-pool-workers": "^0.16.12",
85
+ "@cloudflare/workers-types": "4.20260603.1",
86
86
  "@stratal/testing": "workspace:^",
87
- "@types/node": "^25.6.2",
87
+ "@types/node": "^25.9.1",
88
88
  "@types/pg": "^8.20.0",
89
- "@vitest/coverage-istanbul": "~4.1.5",
90
- "@vitest/runner": "~4.1.5",
91
- "@vitest/snapshot": "~4.1.5",
92
- "@zenstackhq/better-auth": "^3.6.4",
93
- "@zenstackhq/cli": "^3.6.4",
94
- "@zenstackhq/orm": "^3.6.4",
95
- "@zenstackhq/schema": "^3.6.4",
96
- "better-auth": "^1.6.11",
89
+ "@vitest/coverage-istanbul": "~4.1.8",
90
+ "@vitest/runner": "~4.1.8",
91
+ "@vitest/snapshot": "~4.1.8",
92
+ "@zenstackhq/better-auth": "^3.7.2",
93
+ "@zenstackhq/cli": "^3.7.2",
94
+ "@zenstackhq/orm": "^3.7.2",
95
+ "@zenstackhq/schema": "^3.7.2",
96
+ "better-auth": "^1.6.14",
97
97
  "dotenv-cli": "^11.0.0",
98
- "pg": "^8.20.0",
98
+ "pg": "^8.21.0",
99
99
  "stratal": "workspace:*",
100
- "tsdown": "^0.22.0",
100
+ "tsdown": "^0.22.1",
101
101
  "typescript": "^6.0.3",
102
- "vitest": "~4.1.5",
103
- "wrangler": "^4.90.0"
102
+ "vitest": "~4.1.8",
103
+ "wrangler": "^4.97.0"
104
104
  }
105
105
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-context-D70ktWUf.d.mts","names":[],"sources":["../src/context/auth-context.ts"],"mappings":";;;;;AA8BA;;;;;AAEA;;;;;AAIA;;;;;;;;;;;UANiB,QAAA,SAAiB,QAAA;AAAA,UAEjB,QAAA;EACf,IAAA,EAAM,QAAA;AAAA;AAAA,cAIK,WAAA;EAAA,UACD,IAAA,GAAO,QAAA;EAqBF;;;;EAff,cAAA,CAAe,IAAA,EAAM,QAAA;EAsDrB;;;;EA9CA,OAAA,CAAA,GAAW,QAAA;EAuEK;;;EAhEhB,WAAA,CAAA,GAAe,QAAA;;;;;EAWf,SAAA,CAAA;;;;;EAQA,aAAA,CAAA;;;;EAOA,WAAA,CAAA,GAAe,QAAA;;;;;;;EAaf,OAAA,CAAA;;;;;EAQA,QAAA,CAAA;;;;EASA,eAAA,CAAA;;;;;EAQA,gBAAA,CAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DJ_DCIul.d.mts","names":[],"sources":["../src/database/database.module.ts","../src/database/database.service.ts","../src/database/database.tokens.ts","../src/database/decorators/inject-db.decorator.ts","../src/database/errors/record-not-found.error.ts","../src/database/errors/unique-constraint.error.ts","../src/database/errors/from-zenstack-error.ts","../src/database/event-types.ts","../src/database/i18n/en.ts","../src/database/plugins/error-handler.plugin.ts","../src/database/plugins/event-emitter.plugin.ts","../src/database/plugins/schema-switcher.ts","../src/database/commands/zenstack.command.ts","../src/database/commands/db-generate.command.ts","../src/database/commands/db-pull.command.ts","../src/database/commands/db-push.command.ts","../src/database/commands/migrate-deploy.command.ts","../src/database/commands/migrate-dev.command.ts","../src/database/commands/migrate-reset.command.ts","../src/database/commands/migrate-status.command.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-4uX3XKRM.d.mts","names":[],"sources":["../src/database/types.ts"],"mappings":";;;;;;AA+BA;;;;;AAAmC;;;;;;;;;;;;;;AAIiC;;;;;;;UAJnD,eAAA;;KAGZ,sBAAA,MACH,CAAA,SAAU,aAAA,0CAAuD,CAAA;;KAG9D,0BAAA,MACH,CAAA,SAAU,aAAA,0CAAuD,CAAA;;KAG9D,mBAAA,MACH,CAAA,SAAU,aAAA,0CAAuD,CAAA;;KAG9D,YAAA,8BACH,OAAA;EAEM,YAAA,EAAc,sBAAA,CAAuB,CAAA,IAAK,YAAA,CAAa,IAAA;EACvD,gBAAA,EAAkB,0BAAA,CAA2B,CAAA,IAAK,YAAA,CAAa,IAAA;EAC/D,SAAA,EAAW,mBAAA,CAAoB,CAAA,IAAK,YAAA,CAAa,IAAA;AAAA;EAEjD,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;;KAGpC,yBAAA,qBACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,eAAgB,CAAA,GACd,CAAA,CAAE,CAAA,sBACA,YAAA,CAAa,CAAA,CAAE,CAAA;EACb,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;EAC1C,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;EAC1C,YAAA;EAAkB,gBAAA;EAAsB,SAAA;AAAA;;KAGpC,qBAAA,qBACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,eAAgB,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,SAAA,GAAY,CAAA,CAAE,CAAA,IAAK,SAAA,GAAY,SAAA,GAChE,SAAA;;KAGM,cAAA,GACV,eAAA;EAA0B,OAAA;AAAA,IACtB,CAAA,OAAQ,CAAA,UAAW,SAAA,GAAY,CAAA,OAAQ,CAAA,IAAK,SAAA,GAC5C,SAAA;;KAGM,cAAA,GACV,eAAA;EAA0B,OAAA;AAAA,UAChB,CAAA,0BAA2B,OAAA,OAAc,CAAA;;KAIzC,qBAAA,GACV,eAAA;EAA0B,iBAAA;AAAA,IAA8C,CAAA;;;;;UAMzD,4BAAA;EACf,IAAA;EACA,MAAA;AAAA"}