@prisma-next/adapter-sqlite 0.13.0-dev.3 → 0.13.0-dev.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter-DCwhDr2I.mjs → adapter-C1w7dvmO.mjs} +122 -78
- package/dist/adapter-C1w7dvmO.mjs.map +1 -0
- package/dist/adapter-CPydDe3Y.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/control.d.mts +25 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +4 -4
- package/dist/control.mjs.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +23 -23
- package/src/core/adapter.ts +6 -3
- package/src/core/codec-lookup.ts +21 -0
- package/src/core/control-adapter.ts +177 -4
- package/src/core/control-codecs.ts +25 -0
- package/src/core/marker-ledger.ts +2 -18
- package/src/exports/control.ts +3 -3
- package/dist/adapter-DCwhDr2I.mjs.map +0 -1
- package/src/core/ddl-renderer.ts +0 -123
package/dist/control.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.mjs","names":[],"sources":["../src/core/control-mutation-defaults.ts","../src/exports/control.ts"],"sourcesContent":["import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';\nimport { timestampNowControlDescriptor } from '@prisma-next/family-sql/control';\nimport type {\n ControlMutationDefaultEntry,\n MutationDefaultGeneratorDescriptor,\n} from '@prisma-next/framework-components/control';\nimport {\n builtinGeneratorRegistryMetadata,\n resolveBuiltinGeneratedColumnDescriptor,\n} from '@prisma-next/ids';\nimport type {\n DefaultFunctionLoweringContext,\n DefaultFunctionLoweringHandler,\n} from '@prisma-next/sql-contract-psl';\nimport {\n SQLITE_BIGINT_CODEC_ID,\n SQLITE_BLOB_CODEC_ID,\n SQLITE_DATETIME_CODEC_ID,\n SQLITE_INTEGER_CODEC_ID,\n SQLITE_JSON_CODEC_ID,\n SQLITE_REAL_CODEC_ID,\n SQLITE_TEXT_CODEC_ID,\n} from '@prisma-next/target-sqlite/codec-ids';\n\ntype LoweredDefaultResult = ReturnType<DefaultFunctionLoweringHandler>;\ntype ParsedDefaultFunctionCall = Parameters<DefaultFunctionLoweringHandler>[0]['call'];\n\nfunction invalidArgumentDiagnostic(input: {\n readonly context: DefaultFunctionLoweringContext;\n readonly span: ParsedDefaultFunctionCall['span'];\n readonly message: string;\n}): LoweredDefaultResult {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT',\n message: input.message,\n sourceId: input.context.sourceId,\n span: input.span,\n },\n };\n}\n\nfunction executionGenerator(\n id: ExecutionMutationDefaultValue['id'],\n params?: Record<string, unknown>,\n): LoweredDefaultResult {\n return {\n ok: true,\n value: {\n kind: 'execution',\n generated: {\n kind: 'generator',\n id,\n ...(params ? { params } : {}),\n },\n },\n };\n}\n\nfunction expectNoArgs(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n readonly usage: string;\n}): LoweredDefaultResult | undefined {\n if (input.call.args.length === 0) {\n return undefined;\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: `Default function \"${input.call.name}\" does not accept arguments. Use ${input.usage}.`,\n });\n}\n\nfunction parseIntegerArgument(raw: string): number | undefined {\n const trimmed = raw.trim();\n if (!/^-?\\d+$/.test(trimmed)) {\n return undefined;\n }\n const value = Number(trimmed);\n if (!Number.isInteger(value)) {\n return undefined;\n }\n return value;\n}\n\nfunction parseStringLiteral(raw: string): string | undefined {\n const match = raw.trim().match(/^(['\"])(.*)\\1$/s);\n if (!match) {\n return undefined;\n }\n return match[2] ?? '';\n}\n\nfunction lowerAutoincrement(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`autoincrement()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'autoincrement()',\n },\n },\n };\n}\n\nfunction lowerNow(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`now()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'now()',\n },\n },\n };\n}\n\nfunction lowerUuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('uuidv4');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"uuid\" accepts at most one version argument: `uuid()`, `uuid(4)`, or `uuid(7)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 4) {\n return executionGenerator('uuidv4');\n }\n if (version === 7) {\n return executionGenerator('uuidv7');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message:\n 'Default function \"uuid\" supports only `uuid()`, `uuid(4)`, or `uuid(7)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerCuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_UNKNOWN_DEFAULT_FUNCTION',\n message:\n 'Default function \"cuid()\" is not supported in SQL PSL provider v1. Use `cuid(2)` instead.',\n sourceId: input.context.sourceId,\n span: input.call.span,\n },\n };\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: 'Default function \"cuid\" accepts exactly one version argument: `cuid(2)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 2) {\n return executionGenerator('cuid2');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"cuid\" supports only `cuid(2)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerUlid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`ulid()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return executionGenerator('ulid');\n}\n\nfunction lowerNanoid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('nanoid');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"nanoid\" accepts at most one size argument: `nanoid()` or `nanoid(<2-255>)`.',\n });\n }\n const size = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (size !== undefined && size >= 2 && size <= 255) {\n return executionGenerator('nanoid', { size });\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"nanoid\" size argument must be an integer between 2 and 255.',\n });\n}\n\n/**\n * SQLite spellings that all denote the same wall-clock-now value. Anything\n * matching this set when passed through `dbgenerated(\"...\")` is rewritten\n * to the canonical `now()` form before entering the contract — symmetric\n * with `parseSqliteDefault` on the introspection side, so the verifier\n * compares canonical-vs-canonical and a contract using\n * `dbgenerated(\"CURRENT_TIMESTAMP\")` doesn't drift against the schema it\n * just produced.\n */\nconst NOW_SYNONYMS = new Set(['current_timestamp', \"datetime('now')\", 'datetime(\"now\")', 'now()']);\n\nfunction lowerDbgenerated(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"dbgenerated\" requires exactly one string argument: `dbgenerated(\"...\")`.',\n });\n }\n const rawExpression = parseStringLiteral(input.call.args[0]?.raw ?? '');\n if (rawExpression === undefined) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument must be a string literal.',\n });\n }\n const trimmed = rawExpression.trim();\n if (trimmed.length === 0) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument cannot be empty.',\n });\n }\n const expression = NOW_SYNONYMS.has(trimmed.toLowerCase()) ? 'now()' : trimmed;\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression,\n },\n },\n };\n}\n\nconst sqliteDefaultFunctionRegistryEntries = [\n ['autoincrement', { lower: lowerAutoincrement, usageSignatures: ['autoincrement()'] }],\n ['now', { lower: lowerNow, usageSignatures: ['now()'] }],\n ['uuid', { lower: lowerUuid, usageSignatures: ['uuid()', 'uuid(4)', 'uuid(7)'] }],\n ['cuid', { lower: lowerCuid, usageSignatures: ['cuid(2)'] }],\n ['ulid', { lower: lowerUlid, usageSignatures: ['ulid()'] }],\n ['nanoid', { lower: lowerNanoid, usageSignatures: ['nanoid()', 'nanoid(<2-255>)'] }],\n ['dbgenerated', { lower: lowerDbgenerated, usageSignatures: ['dbgenerated(\"...\")'] }],\n] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;\n\nconst sqliteScalarTypeDescriptors = new Map<string, string>([\n ['String', SQLITE_TEXT_CODEC_ID],\n ['Int', SQLITE_INTEGER_CODEC_ID],\n ['BigInt', SQLITE_BIGINT_CODEC_ID],\n ['Float', SQLITE_REAL_CODEC_ID],\n ['Decimal', SQLITE_TEXT_CODEC_ID],\n ['DateTime', SQLITE_DATETIME_CODEC_ID],\n ['Json', SQLITE_JSON_CODEC_ID],\n ['Bytes', SQLITE_BLOB_CODEC_ID],\n]);\n\nexport function createSqliteDefaultFunctionRegistry(): ReadonlyMap<\n string,\n ControlMutationDefaultEntry\n> {\n return new Map(sqliteDefaultFunctionRegistryEntries);\n}\n\nexport function createSqliteMutationDefaultGeneratorDescriptors(): readonly MutationDefaultGeneratorDescriptor[] {\n return [\n ...builtinGeneratorRegistryMetadata.map(\n ({ id, applicableCodecIds }): MutationDefaultGeneratorDescriptor => ({\n id,\n applicableCodecIds,\n resolveGeneratedColumnDescriptor: ({ generated }) => {\n if (generated.kind !== 'generator' || generated.id !== id) {\n return undefined;\n }\n const descriptor = resolveBuiltinGeneratedColumnDescriptor({\n id,\n ...(generated.params ? { params: generated.params } : {}),\n });\n return {\n codecId: descriptor.type.codecId,\n nativeType: descriptor.type.nativeType,\n ...(descriptor.type.typeRef ? { typeRef: descriptor.type.typeRef } : {}),\n ...(descriptor.typeParams ? { typeParams: descriptor.typeParams } : {}),\n };\n },\n }),\n ),\n timestampNowControlDescriptor(),\n ];\n}\n\nexport function createSqliteScalarTypeDescriptors(): ReadonlyMap<string, string> {\n return new Map(sqliteScalarTypeDescriptors);\n}\n","import type { SqlControlAdapterDescriptor } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { SqliteControlAdapter } from '../core/control-adapter';\nimport {\n createSqliteDefaultFunctionRegistry,\n createSqliteMutationDefaultGeneratorDescriptors,\n createSqliteScalarTypeDescriptors,\n} from '../core/control-mutation-defaults';\nimport { sqliteAdapterDescriptorMeta } from '../core/descriptor-meta';\n\nconst sqliteAdapterDescriptor: SqlControlAdapterDescriptor<'sqlite'> = {\n ...sqliteAdapterDescriptorMeta,\n scalarTypeDescriptors: createSqliteScalarTypeDescriptors(),\n controlMutationDefaults: {\n defaultFunctionRegistry: createSqliteDefaultFunctionRegistry(),\n generatorDescriptors: createSqliteMutationDefaultGeneratorDescriptors(),\n },\n create(): SqlControlAdapter<'sqlite'> {\n return new SqliteControlAdapter();\n },\n};\n\nexport default sqliteAdapterDescriptor;\n\n// `parseSqliteDefault`, `normalizeSqliteNativeType`, `quoteIdentifier`,\n// `escapeLiteral`, and `SqlEscapeError` live target-side (one-way\n// `adapter → target` edge, matching Postgres). Re-exported from the\n// adapter so consumers — both internal and downstream — see the same\n// adapter-shaped surface across SQL targets.\nexport { parseSqliteDefault } from '@prisma-next/target-sqlite/default-normalizer';\nexport { normalizeSqliteNativeType } from '@prisma-next/target-sqlite/native-type-normalizer';\nexport {\n escapeLiteral,\n quoteIdentifier,\n SqlEscapeError,\n} from '@prisma-next/target-sqlite/sql-utils';\n\n// `SqlControlAdapterDescriptor` is declared in two places in the codebase\n// (`family-sql/control-adapter` and `family-sql/migrations/types`); the\n// migrations-side declaration narrows `create()`'s return type to the base\n// `ControlAdapterInstance`, hiding `introspect`/`readMarker`. Until that's\n// reconciled upstream, downstream consumers (e2e harness, integration\n// tests) need direct access to the concrete class. Mirrors how Postgres'\n// own package tests import `PostgresControlAdapter` directly.\nexport { SqliteControlAdapter } from '../core/control-adapter';\n"],"mappings":";;;;;;;;;AA2BA,SAAS,0BAA0B,OAIV;CACvB,OAAO;EACL,IAAI;EACJ,YAAY;GACV,MAAM;GACN,SAAS,MAAM;GACf,UAAU,MAAM,QAAQ;GACxB,MAAM,MAAM;EACd;CACF;AACF;AAEA,SAAS,mBACP,IACA,QACsB;CACtB,OAAO;EACL,IAAI;EACJ,OAAO;GACL,MAAM;GACN,WAAW;IACT,MAAM;IACN;IACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;GAC7B;EACF;CACF;AACF;AAEA,SAAS,aAAa,OAIe;CACnC,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B;CAEF,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,SAAS,qBAAqB,MAAM,KAAK,KAAK,mCAAmC,MAAM,MAAM;CAC/F,CAAC;AACH;AAEA,SAAS,qBAAqB,KAAiC;CAC7D,MAAM,UAAU,IAAI,KAAK;CACzB,IAAI,CAAC,UAAU,KAAK,OAAO,GACzB;CAEF,MAAM,QAAQ,OAAO,OAAO;CAC5B,IAAI,CAAC,OAAO,UAAU,KAAK,GACzB;CAEF,OAAO;AACT;AAEA,SAAS,mBAAmB,KAAiC;CAC3D,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,MAAM,iBAAiB;CAChD,IAAI,CAAC,OACH;CAEF,OAAO,MAAM,MAAM;AACrB;AAEA,SAAS,mBAAmB,OAGH;CACvB,MAAM,cAAc,aAAa;EAC/B,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,OAAO;CACT,CAAC;CACD,IAAI,aACF,OAAO;CAET,OAAO;EACL,IAAI;EACJ,OAAO;GACL,MAAM;GACN,cAAc;IACZ,MAAM;IACN,YAAY;GACd;EACF;CACF;AACF;AAEA,SAAS,SAAS,OAGO;CACvB,MAAM,cAAc,aAAa;EAC/B,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,OAAO;CACT,CAAC;CACD,IAAI,aACF,OAAO;CAET,OAAO;EACL,IAAI;EACJ,OAAO;GACL,MAAM;GACN,cAAc;IACZ,MAAM;IACN,YAAY;GACd;EACF;CACF;AACF;AAEA,SAAS,UAAU,OAGM;CACvB,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,mBAAmB,QAAQ;CAEpC,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,SACE;CACJ,CAAC;CAEH,MAAM,UAAU,qBAAqB,MAAM,KAAK,KAAK,EAAE,EAAE,OAAO,EAAE;CAClE,IAAI,YAAY,GACd,OAAO,mBAAmB,QAAQ;CAEpC,IAAI,YAAY,GACd,OAAO,mBAAmB,QAAQ;CAEpC,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE,QAAQ,MAAM,KAAK;EAC7C,SACE;CACJ,CAAC;AACH;AAEA,SAAS,UAAU,OAGM;CACvB,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO;EACL,IAAI;EACJ,YAAY;GACV,MAAM;GACN,SACE;GACF,UAAU,MAAM,QAAQ;GACxB,MAAM,MAAM,KAAK;EACnB;CACF;CAEF,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,SAAS;CACX,CAAC;CAGH,IADgB,qBAAqB,MAAM,KAAK,KAAK,EAAE,EAAE,OAAO,EACtD,MAAM,GACd,OAAO,mBAAmB,OAAO;CAEnC,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE,QAAQ,MAAM,KAAK;EAC7C,SAAS;CACX,CAAC;AACH;AAEA,SAAS,UAAU,OAGM;CACvB,MAAM,cAAc,aAAa;EAC/B,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,OAAO;CACT,CAAC;CACD,IAAI,aACF,OAAO;CAET,OAAO,mBAAmB,MAAM;AAClC;AAEA,SAAS,YAAY,OAGI;CACvB,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,mBAAmB,QAAQ;CAEpC,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,SACE;CACJ,CAAC;CAEH,MAAM,OAAO,qBAAqB,MAAM,KAAK,KAAK,EAAE,EAAE,OAAO,EAAE;CAC/D,IAAI,SAAS,KAAA,KAAa,QAAQ,KAAK,QAAQ,KAC7C,OAAO,mBAAmB,UAAU,EAAE,KAAK,CAAC;CAE9C,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE,QAAQ,MAAM,KAAK;EAC7C,SAAS;CACX,CAAC;AACH;;;;;;;;;;AAWA,MAAM,eAAe,IAAI,IAAI;CAAC;CAAqB;CAAmB;CAAmB;AAAO,CAAC;AAEjG,SAAS,iBAAiB,OAGD;CACvB,IAAI,MAAM,KAAK,KAAK,WAAW,GAC7B,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,SACE;CACJ,CAAC;CAEH,MAAM,gBAAgB,mBAAmB,MAAM,KAAK,KAAK,EAAE,EAAE,OAAO,EAAE;CACtE,IAAI,kBAAkB,KAAA,GACpB,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE,QAAQ,MAAM,KAAK;EAC7C,SAAS;CACX,CAAC;CAEH,MAAM,UAAU,cAAc,KAAK;CACnC,IAAI,QAAQ,WAAW,GACrB,OAAO,0BAA0B;EAC/B,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE,QAAQ,MAAM,KAAK;EAC7C,SAAS;CACX,CAAC;CAGH,OAAO;EACL,IAAI;EACJ,OAAO;GACL,MAAM;GACN,cAAc;IACZ,MAAM;IACN,YAPa,aAAa,IAAI,QAAQ,YAAY,CAAC,IAAI,UAAU;GAQnE;EACF;CACF;AACF;AAEA,MAAM,uCAAuC;CAC3C,CAAC,iBAAiB;EAAE,OAAO;EAAoB,iBAAiB,CAAC,iBAAiB;CAAE,CAAC;CACrF,CAAC,OAAO;EAAE,OAAO;EAAU,iBAAiB,CAAC,OAAO;CAAE,CAAC;CACvD,CAAC,QAAQ;EAAE,OAAO;EAAW,iBAAiB;GAAC;GAAU;GAAW;EAAS;CAAE,CAAC;CAChF,CAAC,QAAQ;EAAE,OAAO;EAAW,iBAAiB,CAAC,SAAS;CAAE,CAAC;CAC3D,CAAC,QAAQ;EAAE,OAAO;EAAW,iBAAiB,CAAC,QAAQ;CAAE,CAAC;CAC1D,CAAC,UAAU;EAAE,OAAO;EAAa,iBAAiB,CAAC,YAAY,iBAAiB;CAAE,CAAC;CACnF,CAAC,eAAe;EAAE,OAAO;EAAkB,iBAAiB,CAAC,sBAAoB;CAAE,CAAC;AACtF;AAEA,MAAM,8BAA8B,IAAI,IAAoB;CAC1D,CAAC,UAAU,oBAAoB;CAC/B,CAAC,OAAO,uBAAuB;CAC/B,CAAC,UAAU,sBAAsB;CACjC,CAAC,SAAS,oBAAoB;CAC9B,CAAC,WAAW,oBAAoB;CAChC,CAAC,YAAY,wBAAwB;CACrC,CAAC,QAAQ,oBAAoB;CAC7B,CAAC,SAAS,oBAAoB;AAChC,CAAC;AAED,SAAgB,sCAGd;CACA,OAAO,IAAI,IAAI,oCAAoC;AACrD;AAEA,SAAgB,kDAAiG;CAC/G,OAAO,CACL,GAAG,iCAAiC,KACjC,EAAE,IAAI,0BAA8D;EACnE;EACA;EACA,mCAAmC,EAAE,gBAAgB;GACnD,IAAI,UAAU,SAAS,eAAe,UAAU,OAAO,IACrD;GAEF,MAAM,aAAa,wCAAwC;IACzD;IACA,GAAI,UAAU,SAAS,EAAE,QAAQ,UAAU,OAAO,IAAI,CAAC;GACzD,CAAC;GACD,OAAO;IACL,SAAS,WAAW,KAAK;IACzB,YAAY,WAAW,KAAK;IAC5B,GAAI,WAAW,KAAK,UAAU,EAAE,SAAS,WAAW,KAAK,QAAQ,IAAI,CAAC;IACtE,GAAI,WAAW,aAAa,EAAE,YAAY,WAAW,WAAW,IAAI,CAAC;GACvE;EACF;CACF,EACF,GACA,8BAA8B,CAChC;AACF;AAEA,SAAgB,oCAAiE;CAC/E,OAAO,IAAI,IAAI,2BAA2B;AAC5C;;;AC3VA,MAAM,0BAAiE;CACrE,GAAG;CACH,uBAAuB,kCAAkC;CACzD,yBAAyB;EACvB,yBAAyB,oCAAoC;EAC7D,sBAAsB,gDAAgD;CACxE;CACA,SAAsC;EACpC,OAAO,IAAI,qBAAqB;CAClC;AACF"}
|
|
1
|
+
{"version":3,"file":"control.mjs","names":[],"sources":["../src/core/control-mutation-defaults.ts","../src/exports/control.ts"],"sourcesContent":["import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';\nimport { timestampNowControlDescriptor } from '@prisma-next/family-sql/control';\nimport type {\n ControlMutationDefaultEntry,\n MutationDefaultGeneratorDescriptor,\n} from '@prisma-next/framework-components/control';\nimport {\n builtinGeneratorRegistryMetadata,\n resolveBuiltinGeneratedColumnDescriptor,\n} from '@prisma-next/ids';\nimport type {\n DefaultFunctionLoweringContext,\n DefaultFunctionLoweringHandler,\n} from '@prisma-next/sql-contract-psl';\nimport {\n SQLITE_BIGINT_CODEC_ID,\n SQLITE_BLOB_CODEC_ID,\n SQLITE_DATETIME_CODEC_ID,\n SQLITE_INTEGER_CODEC_ID,\n SQLITE_JSON_CODEC_ID,\n SQLITE_REAL_CODEC_ID,\n SQLITE_TEXT_CODEC_ID,\n} from '@prisma-next/target-sqlite/codec-ids';\n\ntype LoweredDefaultResult = ReturnType<DefaultFunctionLoweringHandler>;\ntype ParsedDefaultFunctionCall = Parameters<DefaultFunctionLoweringHandler>[0]['call'];\n\nfunction invalidArgumentDiagnostic(input: {\n readonly context: DefaultFunctionLoweringContext;\n readonly span: ParsedDefaultFunctionCall['span'];\n readonly message: string;\n}): LoweredDefaultResult {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT',\n message: input.message,\n sourceId: input.context.sourceId,\n span: input.span,\n },\n };\n}\n\nfunction executionGenerator(\n id: ExecutionMutationDefaultValue['id'],\n params?: Record<string, unknown>,\n): LoweredDefaultResult {\n return {\n ok: true,\n value: {\n kind: 'execution',\n generated: {\n kind: 'generator',\n id,\n ...(params ? { params } : {}),\n },\n },\n };\n}\n\nfunction expectNoArgs(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n readonly usage: string;\n}): LoweredDefaultResult | undefined {\n if (input.call.args.length === 0) {\n return undefined;\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: `Default function \"${input.call.name}\" does not accept arguments. Use ${input.usage}.`,\n });\n}\n\nfunction parseIntegerArgument(raw: string): number | undefined {\n const trimmed = raw.trim();\n if (!/^-?\\d+$/.test(trimmed)) {\n return undefined;\n }\n const value = Number(trimmed);\n if (!Number.isInteger(value)) {\n return undefined;\n }\n return value;\n}\n\nfunction parseStringLiteral(raw: string): string | undefined {\n const match = raw.trim().match(/^(['\"])(.*)\\1$/s);\n if (!match) {\n return undefined;\n }\n return match[2] ?? '';\n}\n\nfunction lowerAutoincrement(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`autoincrement()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'autoincrement()',\n },\n },\n };\n}\n\nfunction lowerNow(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`now()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'now()',\n },\n },\n };\n}\n\nfunction lowerUuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('uuidv4');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"uuid\" accepts at most one version argument: `uuid()`, `uuid(4)`, or `uuid(7)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 4) {\n return executionGenerator('uuidv4');\n }\n if (version === 7) {\n return executionGenerator('uuidv7');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message:\n 'Default function \"uuid\" supports only `uuid()`, `uuid(4)`, or `uuid(7)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerCuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_UNKNOWN_DEFAULT_FUNCTION',\n message:\n 'Default function \"cuid()\" is not supported in SQL PSL provider v1. Use `cuid(2)` instead.',\n sourceId: input.context.sourceId,\n span: input.call.span,\n },\n };\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: 'Default function \"cuid\" accepts exactly one version argument: `cuid(2)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 2) {\n return executionGenerator('cuid2');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"cuid\" supports only `cuid(2)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerUlid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`ulid()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return executionGenerator('ulid');\n}\n\nfunction lowerNanoid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('nanoid');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"nanoid\" accepts at most one size argument: `nanoid()` or `nanoid(<2-255>)`.',\n });\n }\n const size = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (size !== undefined && size >= 2 && size <= 255) {\n return executionGenerator('nanoid', { size });\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"nanoid\" size argument must be an integer between 2 and 255.',\n });\n}\n\n/**\n * SQLite spellings that all denote the same wall-clock-now value. Anything\n * matching this set when passed through `dbgenerated(\"...\")` is rewritten\n * to the canonical `now()` form before entering the contract — symmetric\n * with `parseSqliteDefault` on the introspection side, so the verifier\n * compares canonical-vs-canonical and a contract using\n * `dbgenerated(\"CURRENT_TIMESTAMP\")` doesn't drift against the schema it\n * just produced.\n */\nconst NOW_SYNONYMS = new Set(['current_timestamp', \"datetime('now')\", 'datetime(\"now\")', 'now()']);\n\nfunction lowerDbgenerated(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"dbgenerated\" requires exactly one string argument: `dbgenerated(\"...\")`.',\n });\n }\n const rawExpression = parseStringLiteral(input.call.args[0]?.raw ?? '');\n if (rawExpression === undefined) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument must be a string literal.',\n });\n }\n const trimmed = rawExpression.trim();\n if (trimmed.length === 0) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument cannot be empty.',\n });\n }\n const expression = NOW_SYNONYMS.has(trimmed.toLowerCase()) ? 'now()' : trimmed;\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression,\n },\n },\n };\n}\n\nconst sqliteDefaultFunctionRegistryEntries = [\n ['autoincrement', { lower: lowerAutoincrement, usageSignatures: ['autoincrement()'] }],\n ['now', { lower: lowerNow, usageSignatures: ['now()'] }],\n ['uuid', { lower: lowerUuid, usageSignatures: ['uuid()', 'uuid(4)', 'uuid(7)'] }],\n ['cuid', { lower: lowerCuid, usageSignatures: ['cuid(2)'] }],\n ['ulid', { lower: lowerUlid, usageSignatures: ['ulid()'] }],\n ['nanoid', { lower: lowerNanoid, usageSignatures: ['nanoid()', 'nanoid(<2-255>)'] }],\n ['dbgenerated', { lower: lowerDbgenerated, usageSignatures: ['dbgenerated(\"...\")'] }],\n] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;\n\nconst sqliteScalarTypeDescriptors = new Map<string, string>([\n ['String', SQLITE_TEXT_CODEC_ID],\n ['Int', SQLITE_INTEGER_CODEC_ID],\n ['BigInt', SQLITE_BIGINT_CODEC_ID],\n ['Float', SQLITE_REAL_CODEC_ID],\n ['Decimal', SQLITE_TEXT_CODEC_ID],\n ['DateTime', SQLITE_DATETIME_CODEC_ID],\n ['Json', SQLITE_JSON_CODEC_ID],\n ['Bytes', SQLITE_BLOB_CODEC_ID],\n]);\n\nexport function createSqliteDefaultFunctionRegistry(): ReadonlyMap<\n string,\n ControlMutationDefaultEntry\n> {\n return new Map(sqliteDefaultFunctionRegistryEntries);\n}\n\nexport function createSqliteMutationDefaultGeneratorDescriptors(): readonly MutationDefaultGeneratorDescriptor[] {\n return [\n ...builtinGeneratorRegistryMetadata.map(\n ({ id, applicableCodecIds }): MutationDefaultGeneratorDescriptor => ({\n id,\n applicableCodecIds,\n resolveGeneratedColumnDescriptor: ({ generated }) => {\n if (generated.kind !== 'generator' || generated.id !== id) {\n return undefined;\n }\n const descriptor = resolveBuiltinGeneratedColumnDescriptor({\n id,\n ...(generated.params ? { params: generated.params } : {}),\n });\n return {\n codecId: descriptor.type.codecId,\n nativeType: descriptor.type.nativeType,\n ...(descriptor.type.typeRef ? { typeRef: descriptor.type.typeRef } : {}),\n ...(descriptor.typeParams ? { typeParams: descriptor.typeParams } : {}),\n };\n },\n }),\n ),\n timestampNowControlDescriptor(),\n ];\n}\n\nexport function createSqliteScalarTypeDescriptors(): ReadonlyMap<string, string> {\n return new Map(sqliteScalarTypeDescriptors);\n}\n","import type { SqlControlAdapterDescriptor } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { SqliteControlAdapter } from '../core/control-adapter';\nimport {\n createSqliteDefaultFunctionRegistry,\n createSqliteMutationDefaultGeneratorDescriptors,\n createSqliteScalarTypeDescriptors,\n} from '../core/control-mutation-defaults';\nimport { sqliteAdapterDescriptorMeta } from '../core/descriptor-meta';\n\nconst sqliteAdapterDescriptor: SqlControlAdapterDescriptor<'sqlite'> = {\n ...sqliteAdapterDescriptorMeta,\n scalarTypeDescriptors: createSqliteScalarTypeDescriptors(),\n controlMutationDefaults: {\n defaultFunctionRegistry: createSqliteDefaultFunctionRegistry(),\n generatorDescriptors: createSqliteMutationDefaultGeneratorDescriptors(),\n },\n create(stack): SqlControlAdapter<'sqlite'> {\n return new SqliteControlAdapter(stack.codecLookup);\n },\n};\n\nexport default sqliteAdapterDescriptor;\n\n// `parseSqliteDefault`, `normalizeSqliteNativeType`, `quoteIdentifier`,\n// `escapeLiteral`, and `SqlEscapeError` live target-side (one-way\n// `adapter → target` edge, matching Postgres). Re-exported from the\n// adapter so consumers — both internal and downstream — see the same\n// adapter-shaped surface across SQL targets.\nexport { parseSqliteDefault } from '@prisma-next/target-sqlite/default-normalizer';\nexport { normalizeSqliteNativeType } from '@prisma-next/target-sqlite/native-type-normalizer';\nexport {\n escapeLiteral,\n quoteIdentifier,\n SqlEscapeError,\n} from '@prisma-next/target-sqlite/sql-utils';\nexport { createSqliteBuiltinCodecLookup } from '../core/codec-lookup';\n// `SqlControlAdapterDescriptor` is declared in two places in the codebase\n// (`family-sql/control-adapter` and `family-sql/migrations/types`); the\n// migrations-side declaration narrows `create()`'s return type to the base\n// `ControlAdapterInstance`, hiding `introspect`/`readMarker`. Until that's\n// reconciled upstream, downstream consumers (e2e harness, integration\n// tests) need direct access to the concrete class. Mirrors how Postgres'\n// own package tests import `PostgresControlAdapter` directly.\nexport { SqliteControlAdapter } from '../core/control-adapter';\n"],"mappings":"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"}
|
package/dist/runtime.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as sqliteRawCodecInferer, t as createSqliteAdapter } from "./adapter-
|
|
1
|
+
import { n as sqliteRawCodecInferer, t as createSqliteAdapter } from "./adapter-C1w7dvmO.mjs";
|
|
2
2
|
import { t as sqliteAdapterDescriptorMeta } from "./descriptor-meta-Du5OgSxS.mjs";
|
|
3
3
|
import { sqliteCodecRegistry } from "@prisma-next/target-sqlite/codecs";
|
|
4
4
|
import { builtinGeneratorIds } from "@prisma-next/ids";
|
package/package.json
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/adapter-sqlite",
|
|
3
|
-
"version": "0.13.0-dev.
|
|
3
|
+
"version": "0.13.0-dev.30",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@prisma-next/cli": "0.13.0-dev.
|
|
9
|
-
"@prisma-next/contract": "0.13.0-dev.
|
|
10
|
-
"@prisma-next/contract-authoring": "0.13.0-dev.
|
|
11
|
-
"@prisma-next/errors": "0.13.0-dev.
|
|
12
|
-
"@prisma-next/framework-components": "0.13.0-dev.
|
|
13
|
-
"@prisma-next/family-sql": "0.13.0-dev.
|
|
14
|
-
"@prisma-next/ids": "0.13.0-dev.
|
|
15
|
-
"@prisma-next/sql-contract": "0.13.0-dev.
|
|
16
|
-
"@prisma-next/sql-contract-psl": "0.13.0-dev.
|
|
17
|
-
"@prisma-next/sql-contract-ts": "0.13.0-dev.
|
|
18
|
-
"@prisma-next/sql-operations": "0.13.0-dev.
|
|
19
|
-
"@prisma-next/sql-relational-core": "0.13.0-dev.
|
|
20
|
-
"@prisma-next/sql-runtime": "0.13.0-dev.
|
|
21
|
-
"@prisma-next/sql-schema-ir": "0.13.0-dev.
|
|
22
|
-
"@prisma-next/target-sqlite": "0.13.0-dev.
|
|
23
|
-
"@prisma-next/utils": "0.13.0-dev.
|
|
8
|
+
"@prisma-next/cli": "0.13.0-dev.30",
|
|
9
|
+
"@prisma-next/contract": "0.13.0-dev.30",
|
|
10
|
+
"@prisma-next/contract-authoring": "0.13.0-dev.30",
|
|
11
|
+
"@prisma-next/errors": "0.13.0-dev.30",
|
|
12
|
+
"@prisma-next/framework-components": "0.13.0-dev.30",
|
|
13
|
+
"@prisma-next/family-sql": "0.13.0-dev.30",
|
|
14
|
+
"@prisma-next/ids": "0.13.0-dev.30",
|
|
15
|
+
"@prisma-next/sql-contract": "0.13.0-dev.30",
|
|
16
|
+
"@prisma-next/sql-contract-psl": "0.13.0-dev.30",
|
|
17
|
+
"@prisma-next/sql-contract-ts": "0.13.0-dev.30",
|
|
18
|
+
"@prisma-next/sql-operations": "0.13.0-dev.30",
|
|
19
|
+
"@prisma-next/sql-relational-core": "0.13.0-dev.30",
|
|
20
|
+
"@prisma-next/sql-runtime": "0.13.0-dev.30",
|
|
21
|
+
"@prisma-next/sql-schema-ir": "0.13.0-dev.30",
|
|
22
|
+
"@prisma-next/target-sqlite": "0.13.0-dev.30",
|
|
23
|
+
"@prisma-next/utils": "0.13.0-dev.30",
|
|
24
24
|
"arktype": "^2.2.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@prisma-next/driver-sqlite": "0.13.0-dev.
|
|
28
|
-
"@prisma-next/migration-tools": "0.13.0-dev.
|
|
29
|
-
"@prisma-next/test-utils": "0.13.0-dev.
|
|
30
|
-
"@prisma-next/tsconfig": "0.13.0-dev.
|
|
31
|
-
"@prisma-next/tsdown": "0.13.0-dev.
|
|
27
|
+
"@prisma-next/driver-sqlite": "0.13.0-dev.30",
|
|
28
|
+
"@prisma-next/migration-tools": "0.13.0-dev.30",
|
|
29
|
+
"@prisma-next/test-utils": "0.13.0-dev.30",
|
|
30
|
+
"@prisma-next/tsconfig": "0.13.0-dev.30",
|
|
31
|
+
"@prisma-next/tsdown": "0.13.0-dev.30",
|
|
32
32
|
"pathe": "^2.0.3",
|
|
33
33
|
"tsdown": "0.22.1",
|
|
34
34
|
"typescript": "5.9.3",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"build": "tsdown",
|
|
68
68
|
"test": "vitest run",
|
|
69
69
|
"test:coverage": "vitest run --coverage",
|
|
70
|
-
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
70
|
+
"typecheck": "tsc --project tsconfig.json --noEmit && tsc --project tsconfig.test.json --noEmit",
|
|
71
71
|
"lint": "biome check . --error-on-warnings",
|
|
72
72
|
"lint:fix": "biome check --write .",
|
|
73
73
|
"lint:fix:unsafe": "biome check --write --unsafe .",
|
package/src/core/adapter.ts
CHANGED
|
@@ -36,8 +36,8 @@ import { isDdlNode } from '@prisma-next/sql-relational-core/ast';
|
|
|
36
36
|
import type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';
|
|
37
37
|
import type { SqliteDdlNode } from '@prisma-next/target-sqlite/ddl';
|
|
38
38
|
import { escapeLiteral, quoteIdentifier } from '@prisma-next/target-sqlite/sql-utils';
|
|
39
|
+
import { createSqliteBuiltinCodecLookup } from './codec-lookup';
|
|
39
40
|
import { SqliteControlAdapter } from './control-adapter';
|
|
40
|
-
import { renderLoweredDdl } from './ddl-renderer';
|
|
41
41
|
import type { SqliteAdapterOptions, SqliteContract, SqliteLoweredStatement } from './types';
|
|
42
42
|
|
|
43
43
|
const defaultCapabilities = Object.freeze({
|
|
@@ -58,7 +58,8 @@ class SqliteAdapterImpl implements Adapter<AnyQueryAst, SqliteContract, SqliteLo
|
|
|
58
58
|
readonly profile: AdapterProfile<'sqlite'>;
|
|
59
59
|
|
|
60
60
|
constructor(options?: SqliteAdapterOptions) {
|
|
61
|
-
const
|
|
61
|
+
const codecLookup = createSqliteBuiltinCodecLookup();
|
|
62
|
+
const controlAdapter = new SqliteControlAdapter(codecLookup);
|
|
62
63
|
this.profile = Object.freeze({
|
|
63
64
|
id: options?.profileId ?? 'sqlite/default@1',
|
|
64
65
|
target: 'sqlite',
|
|
@@ -87,7 +88,9 @@ class SqliteAdapterImpl implements Adapter<AnyQueryAst, SqliteContract, SqliteLo
|
|
|
87
88
|
context: LowererContext<SqliteContract>,
|
|
88
89
|
): SqliteLoweredStatement {
|
|
89
90
|
if (isDdlNode(ast)) {
|
|
90
|
-
|
|
91
|
+
throw new Error(
|
|
92
|
+
'lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.',
|
|
93
|
+
);
|
|
91
94
|
}
|
|
92
95
|
return renderLoweredSql(ast, context.contract);
|
|
93
96
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CodecRegistry } from '@prisma-next/framework-components/codec';
|
|
2
|
+
import { extractCodecLookup } from '@prisma-next/framework-components/control';
|
|
3
|
+
import { sqliteCodecRegistry } from '@prisma-next/target-sqlite/codecs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build a {@link CodecRegistry} populated with the SQLite-builtin codec definitions only.
|
|
7
|
+
*
|
|
8
|
+
* Used by `createSqliteAdapter()` and `new SqliteControlAdapter()` when called without a
|
|
9
|
+
* stack-derived registry (e.g. from tests, or one-off scripts that don't compose a full stack).
|
|
10
|
+
*
|
|
11
|
+
* Extension codecs are intentionally NOT included: a bare adapter cannot see extensions.
|
|
12
|
+
* Stack-composed paths supply the broader, extension-inclusive registry at construction time.
|
|
13
|
+
*/
|
|
14
|
+
export function createSqliteBuiltinCodecLookup(): CodecRegistry {
|
|
15
|
+
return extractCodecLookup([
|
|
16
|
+
{
|
|
17
|
+
id: 'sqlite-builtin-codecs',
|
|
18
|
+
types: { codecTypes: { codecDescriptors: Array.from(sqliteCodecRegistry.values()) } },
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
@@ -2,15 +2,24 @@ import type { ContractMarkerRecord, LedgerEntryRecord } from '@prisma-next/contr
|
|
|
2
2
|
import { parseMarkerRowSafely, withMarkerReadErrorHandling } from '@prisma-next/errors/execution';
|
|
3
3
|
import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
|
|
4
4
|
import { parseContractMarkerRow } from '@prisma-next/family-sql/verify';
|
|
5
|
+
import type { CodecLookup, CodecRegistry } from '@prisma-next/framework-components/codec';
|
|
5
6
|
import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
|
|
6
7
|
import { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';
|
|
8
|
+
import { REFERENTIAL_ACTION_SQL } from '@prisma-next/sql-contract/referential-action-sql';
|
|
7
9
|
import type { SqlControlDriverInstance } from '@prisma-next/sql-contract/types';
|
|
8
10
|
import type {
|
|
9
11
|
AnyQueryAst,
|
|
12
|
+
CodecRef,
|
|
13
|
+
ContractCodecRegistry,
|
|
14
|
+
DdlColumn,
|
|
10
15
|
DdlNode,
|
|
16
|
+
DdlTableConstraint,
|
|
17
|
+
FunctionColumnDefault,
|
|
18
|
+
LiteralColumnDefault,
|
|
11
19
|
LoweredStatement,
|
|
12
20
|
LowererContext,
|
|
13
21
|
MarkerReadResult,
|
|
22
|
+
SqlExecuteRequest,
|
|
14
23
|
} from '@prisma-next/sql-relational-core/ast';
|
|
15
24
|
import { isDdlNode } from '@prisma-next/sql-relational-core/ast';
|
|
16
25
|
import type {
|
|
@@ -27,13 +36,14 @@ import {
|
|
|
27
36
|
buildControlTableBootstrapQueries,
|
|
28
37
|
buildSignMarkerBootstrapQueries,
|
|
29
38
|
} from '@prisma-next/target-sqlite/contract-free';
|
|
30
|
-
import type { SqliteDdlNode } from '@prisma-next/target-sqlite/ddl';
|
|
39
|
+
import type { SqliteCreateTable, SqliteDdlNode } from '@prisma-next/target-sqlite/ddl';
|
|
31
40
|
import { parseSqliteDefault } from '@prisma-next/target-sqlite/default-normalizer';
|
|
32
41
|
import { normalizeSqliteNativeType } from '@prisma-next/target-sqlite/native-type-normalizer';
|
|
42
|
+
import { escapeLiteral, quoteIdentifier } from '@prisma-next/target-sqlite/sql-utils';
|
|
33
43
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
34
44
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
35
45
|
import { renderLoweredSql } from './adapter';
|
|
36
|
-
import {
|
|
46
|
+
import { encodeControlQueryParams } from './control-codecs';
|
|
37
47
|
import { coerceLedgerAppliedAt, operationCountFromStored } from './ledger-decode';
|
|
38
48
|
import {
|
|
39
49
|
decodeSqliteMarkerRow,
|
|
@@ -106,6 +116,12 @@ export class SqliteControlAdapter implements SqlControlAdapter<'sqlite'> {
|
|
|
106
116
|
readonly familyId = 'sql' as const;
|
|
107
117
|
readonly targetId = 'sqlite' as const;
|
|
108
118
|
|
|
119
|
+
private readonly codecRegistry: CodecRegistry;
|
|
120
|
+
|
|
121
|
+
constructor(codecRegistry: CodecRegistry) {
|
|
122
|
+
this.codecRegistry = codecRegistry;
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
readonly normalizeDefault = parseSqliteDefault;
|
|
110
126
|
readonly normalizeNativeType = normalizeSqliteNativeType;
|
|
111
127
|
|
|
@@ -127,9 +143,43 @@ export class SqliteControlAdapter implements SqlControlAdapter<'sqlite'> {
|
|
|
127
143
|
*/
|
|
128
144
|
lower(ast: AnyQueryAst | SqliteDdlNode, context: LowererContext<unknown>): LoweredStatement {
|
|
129
145
|
if (isDdlNode(ast)) {
|
|
130
|
-
|
|
146
|
+
throw new Error(
|
|
147
|
+
'lower() cannot lower DDL: DDL default literals require inline codec encoding, which is async. Use lowerToExecuteRequest().',
|
|
148
|
+
);
|
|
131
149
|
}
|
|
132
|
-
return renderLoweredSql(
|
|
150
|
+
return renderLoweredSql(
|
|
151
|
+
ast,
|
|
152
|
+
blindCast<SqliteContract, 'caller must supply a matching SqliteContract'>(context.contract),
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Lower an AST all the way to a driver-ready statement. For DDL nodes,
|
|
158
|
+
* literal column defaults are formatted as inline SQL with SQLite-specific
|
|
159
|
+
* literal syntax (no cast suffix, boolean as 0/1, blob via X'hex'). For
|
|
160
|
+
* query ASTs, params are kept as `?` placeholders; wire values go in
|
|
161
|
+
* `params`. Does NOT call `this.lower()` — independent implementation.
|
|
162
|
+
*/
|
|
163
|
+
async lowerToExecuteRequest(
|
|
164
|
+
ast: AnyQueryAst | SqliteDdlNode,
|
|
165
|
+
context?: LowererContext<unknown>,
|
|
166
|
+
): Promise<SqlExecuteRequest> {
|
|
167
|
+
if (isDdlNode(ast)) {
|
|
168
|
+
return sqliteRenderDdlExecuteRequest(
|
|
169
|
+
blindCast<SqliteDdlNode, 'isDdlNode guard'>(ast),
|
|
170
|
+
this.codecRegistry,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
const contract = blindCast<SqliteContract, 'Caller must supply matching contract'>(
|
|
174
|
+
context?.contract,
|
|
175
|
+
);
|
|
176
|
+
const lowered = renderLoweredSql(ast, contract);
|
|
177
|
+
const codecRegistry = blindCast<
|
|
178
|
+
ContractCodecRegistry,
|
|
179
|
+
'framework CodecRegistry: its descriptors materialise SQL codecs; the framework Codec type erases to BaseCodec at this boundary'
|
|
180
|
+
>(this.codecRegistry);
|
|
181
|
+
const params = await encodeControlQueryParams(lowered, ast, codecRegistry);
|
|
182
|
+
return { sql: lowered.sql, params };
|
|
133
183
|
}
|
|
134
184
|
|
|
135
185
|
/**
|
|
@@ -582,3 +632,126 @@ function mapSqliteReferentialAction(rule: string): SqlReferentialAction | undefi
|
|
|
582
632
|
if (mapped === 'noAction') return undefined;
|
|
583
633
|
return mapped;
|
|
584
634
|
}
|
|
635
|
+
|
|
636
|
+
// ---------------------------------------------------------------------------
|
|
637
|
+
// sqliteRenderDdlExecuteRequest — independent DDL walker for lowerToExecuteRequest
|
|
638
|
+
// ---------------------------------------------------------------------------
|
|
639
|
+
|
|
640
|
+
function sqliteInlineLiteral(wire: unknown): string {
|
|
641
|
+
if (wire === null) return 'NULL';
|
|
642
|
+
if (typeof wire === 'boolean') return wire ? '1' : '0';
|
|
643
|
+
if (typeof wire === 'number') {
|
|
644
|
+
if (!Number.isFinite(wire)) {
|
|
645
|
+
throw new Error(
|
|
646
|
+
`sqliteRenderDdlExecuteRequest: non-finite number wire value ${String(wire)} cannot be emitted as a DEFAULT literal`,
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
return String(wire);
|
|
650
|
+
}
|
|
651
|
+
if (typeof wire === 'bigint') return String(wire);
|
|
652
|
+
if (wire instanceof Date) {
|
|
653
|
+
if (Number.isNaN(wire.getTime())) {
|
|
654
|
+
throw new Error(
|
|
655
|
+
'sqliteRenderDdlExecuteRequest: invalid Date value cannot be emitted as a DEFAULT literal',
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
return `'${escapeLiteral(wire.toISOString())}'`;
|
|
659
|
+
}
|
|
660
|
+
if (typeof wire === 'string') return `'${escapeLiteral(wire)}'`;
|
|
661
|
+
if (wire instanceof Uint8Array) {
|
|
662
|
+
const hex = Array.from(wire)
|
|
663
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
664
|
+
.join('');
|
|
665
|
+
return `X'${hex}'`;
|
|
666
|
+
}
|
|
667
|
+
if (typeof wire === 'object') return `'${escapeLiteral(JSON.stringify(wire))}'`;
|
|
668
|
+
throw new Error(`sqliteRenderDdlExecuteRequest: unexpected wire type "${typeof wire}"`);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
async function sqliteRenderDdlColumnDefault(
|
|
672
|
+
def: LiteralColumnDefault | FunctionColumnDefault,
|
|
673
|
+
codecLookup: CodecLookup,
|
|
674
|
+
codecRef: CodecRef | undefined,
|
|
675
|
+
): Promise<string> {
|
|
676
|
+
if (def.kind === 'function') {
|
|
677
|
+
if (def.expression === 'autoincrement()') return '';
|
|
678
|
+
// SQLite has no `now()` function; the contract canonicalizes
|
|
679
|
+
// `CURRENT_TIMESTAMP` / `datetime('now')` to `now()`, so map it back to a
|
|
680
|
+
// valid SQLite expression on the way out.
|
|
681
|
+
if (def.expression === 'now()') return "DEFAULT (datetime('now'))";
|
|
682
|
+
return `DEFAULT (${def.expression})`;
|
|
683
|
+
}
|
|
684
|
+
if (codecRef !== undefined) {
|
|
685
|
+
const codec = codecLookup.get(codecRef.codecId);
|
|
686
|
+
if (codec !== undefined) {
|
|
687
|
+
const wire = await codec.encode(def.value, {});
|
|
688
|
+
return `DEFAULT ${sqliteInlineLiteral(wire)}`;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
// Fallback: codec-less literal defaults follow RawSqlLiteral wire-scalar semantics.
|
|
692
|
+
return `DEFAULT ${sqliteInlineLiteral(def.value)}`;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
async function sqliteRenderDdlColumn(column: DdlColumn, codecLookup: CodecLookup): Promise<string> {
|
|
696
|
+
if (column.type.includes('AUTOINCREMENT')) {
|
|
697
|
+
return `${quoteIdentifier(column.name)} ${column.type}`;
|
|
698
|
+
}
|
|
699
|
+
const parts = [quoteIdentifier(column.name), column.type];
|
|
700
|
+
if (column.notNull) parts.push('NOT NULL');
|
|
701
|
+
if (column.primaryKey) parts.push('PRIMARY KEY');
|
|
702
|
+
if (column.default) {
|
|
703
|
+
const clause = await sqliteRenderDdlColumnDefault(column.default, codecLookup, column.codecRef);
|
|
704
|
+
if (clause.length > 0) parts.push(clause);
|
|
705
|
+
}
|
|
706
|
+
return parts.join(' ');
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function sqliteRenderDdlConstraint(constraint: DdlTableConstraint): string {
|
|
710
|
+
if (constraint.kind === 'primary-key') {
|
|
711
|
+
const cols = constraint.columns.map(quoteIdentifier).join(', ');
|
|
712
|
+
if (constraint.name !== undefined) {
|
|
713
|
+
return `CONSTRAINT ${quoteIdentifier(constraint.name)} PRIMARY KEY (${cols})`;
|
|
714
|
+
}
|
|
715
|
+
return `PRIMARY KEY (${cols})`;
|
|
716
|
+
}
|
|
717
|
+
if (constraint.kind === 'foreign-key') {
|
|
718
|
+
const cols = constraint.columns.map(quoteIdentifier).join(', ');
|
|
719
|
+
const refTable = constraint.refTable.split('.').map(quoteIdentifier).join('.');
|
|
720
|
+
const refCols = constraint.refColumns.map(quoteIdentifier).join(', ');
|
|
721
|
+
let sql = `FOREIGN KEY (${cols}) REFERENCES ${refTable} (${refCols})`;
|
|
722
|
+
if (constraint.onDelete !== undefined) {
|
|
723
|
+
sql += ` ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`;
|
|
724
|
+
}
|
|
725
|
+
if (constraint.onUpdate !== undefined) {
|
|
726
|
+
sql += ` ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`;
|
|
727
|
+
}
|
|
728
|
+
if (constraint.name !== undefined) {
|
|
729
|
+
sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
|
|
730
|
+
}
|
|
731
|
+
return sql;
|
|
732
|
+
}
|
|
733
|
+
const cols = constraint.columns.map(quoteIdentifier).join(', ');
|
|
734
|
+
if (constraint.name !== undefined) {
|
|
735
|
+
return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
|
|
736
|
+
}
|
|
737
|
+
return `UNIQUE (${cols})`;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
async function sqliteRenderDdlExecuteRequest(
|
|
741
|
+
ast: SqliteDdlNode,
|
|
742
|
+
codecLookup: CodecLookup,
|
|
743
|
+
): Promise<SqlExecuteRequest> {
|
|
744
|
+
const node = blindCast<SqliteCreateTable, 'SQLite DDL only has create-table'>(ast);
|
|
745
|
+
const ifNotExists = node.ifNotExists ? 'IF NOT EXISTS ' : '';
|
|
746
|
+
const tableRef = quoteIdentifier(node.table);
|
|
747
|
+
const columnDefs = await Promise.all(
|
|
748
|
+
node.columns.map((col) => sqliteRenderDdlColumn(col, codecLookup)),
|
|
749
|
+
);
|
|
750
|
+
const constraintDefs =
|
|
751
|
+
node.constraints !== undefined ? node.constraints.map(sqliteRenderDdlConstraint) : [];
|
|
752
|
+
const allDefs = [...columnDefs, ...constraintDefs].join(',\n ');
|
|
753
|
+
return {
|
|
754
|
+
sql: `CREATE TABLE ${ifNotExists}${tableRef} (\n ${allDefs}\n)`,
|
|
755
|
+
params: [],
|
|
756
|
+
};
|
|
757
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AnyQueryAst,
|
|
3
|
+
ContractCodecRegistry,
|
|
4
|
+
LoweredStatement,
|
|
5
|
+
} from '@prisma-next/sql-relational-core/ast';
|
|
6
|
+
import {
|
|
7
|
+
createAstCodecRegistry,
|
|
8
|
+
deriveParamMetadata,
|
|
9
|
+
encodeParamsWithMetadata,
|
|
10
|
+
} from '@prisma-next/sql-runtime';
|
|
11
|
+
import { sqliteCodecRegistry } from '@prisma-next/target-sqlite/codecs';
|
|
12
|
+
|
|
13
|
+
export const CONTROL_CODECS = createAstCodecRegistry(sqliteCodecRegistry);
|
|
14
|
+
|
|
15
|
+
export async function encodeControlQueryParams(
|
|
16
|
+
lowered: LoweredStatement,
|
|
17
|
+
ast: AnyQueryAst,
|
|
18
|
+
codecs: ContractCodecRegistry = CONTROL_CODECS,
|
|
19
|
+
): Promise<readonly unknown[]> {
|
|
20
|
+
const values = lowered.params.map((slot) => {
|
|
21
|
+
if (slot.kind === 'literal') return slot.value;
|
|
22
|
+
throw new Error(`control query lowered to a bind slot '${slot.name}', which is unsupported`);
|
|
23
|
+
});
|
|
24
|
+
return encodeParamsWithMetadata(values, deriveParamMetadata(ast), {}, codecs);
|
|
25
|
+
}
|
|
@@ -4,13 +4,7 @@ import {
|
|
|
4
4
|
type LoweredStatement,
|
|
5
5
|
RawExpr,
|
|
6
6
|
} from '@prisma-next/sql-relational-core/ast';
|
|
7
|
-
import {
|
|
8
|
-
createAstCodecRegistry,
|
|
9
|
-
deriveParamMetadata,
|
|
10
|
-
encodeParamsWithMetadata,
|
|
11
|
-
} from '@prisma-next/sql-runtime';
|
|
12
7
|
import { SQLITE_DATETIME_CODEC_ID } from '@prisma-next/target-sqlite/codec-ids';
|
|
13
|
-
import { sqliteCodecRegistry } from '@prisma-next/target-sqlite/codecs';
|
|
14
8
|
import {
|
|
15
9
|
datetime,
|
|
16
10
|
integer,
|
|
@@ -18,8 +12,7 @@ import {
|
|
|
18
12
|
sqliteTable,
|
|
19
13
|
text,
|
|
20
14
|
} from '@prisma-next/target-sqlite/contract-free';
|
|
21
|
-
|
|
22
|
-
const CONTROL_CODECS = createAstCodecRegistry(sqliteCodecRegistry);
|
|
15
|
+
import { encodeControlQueryParams } from './control-codecs';
|
|
23
16
|
|
|
24
17
|
export const marker = sqliteTable('_prisma_marker', {
|
|
25
18
|
space: text(),
|
|
@@ -91,16 +84,7 @@ export async function execute(
|
|
|
91
84
|
query: AnyQueryAst,
|
|
92
85
|
): Promise<readonly Record<string, unknown>[]> {
|
|
93
86
|
const lowered = lower(query);
|
|
94
|
-
const
|
|
95
|
-
if (slot.kind === 'literal') return slot.value;
|
|
96
|
-
throw new Error('SQLite control DML lowered to a bind parameter, which is unsupported');
|
|
97
|
-
});
|
|
98
|
-
const encoded = await encodeParamsWithMetadata(
|
|
99
|
-
values,
|
|
100
|
-
deriveParamMetadata(query),
|
|
101
|
-
{},
|
|
102
|
-
CONTROL_CODECS,
|
|
103
|
-
);
|
|
87
|
+
const encoded = await encodeControlQueryParams(lowered, query);
|
|
104
88
|
const result = await driver.query(lowered.sql, encoded);
|
|
105
89
|
return result.rows;
|
|
106
90
|
}
|
package/src/exports/control.ts
CHANGED
|
@@ -15,8 +15,8 @@ const sqliteAdapterDescriptor: SqlControlAdapterDescriptor<'sqlite'> = {
|
|
|
15
15
|
defaultFunctionRegistry: createSqliteDefaultFunctionRegistry(),
|
|
16
16
|
generatorDescriptors: createSqliteMutationDefaultGeneratorDescriptors(),
|
|
17
17
|
},
|
|
18
|
-
create(): SqlControlAdapter<'sqlite'> {
|
|
19
|
-
return new SqliteControlAdapter();
|
|
18
|
+
create(stack): SqlControlAdapter<'sqlite'> {
|
|
19
|
+
return new SqliteControlAdapter(stack.codecLookup);
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ export {
|
|
|
34
34
|
quoteIdentifier,
|
|
35
35
|
SqlEscapeError,
|
|
36
36
|
} from '@prisma-next/target-sqlite/sql-utils';
|
|
37
|
-
|
|
37
|
+
export { createSqliteBuiltinCodecLookup } from '../core/codec-lookup';
|
|
38
38
|
// `SqlControlAdapterDescriptor` is declared in two places in the codebase
|
|
39
39
|
// (`family-sql/control-adapter` and `family-sql/migrations/types`); the
|
|
40
40
|
// migrations-side declaration narrows `create()`'s return type to the base
|