@prisma/orm-family-sql 8.0.0-rc.17-dev.6 → 8.0.0-rc.17-dev.7

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 (68) hide show
  1. package/dist/attribute-specs-15pm1Qvk.d.mts +106 -0
  2. package/dist/attribute-specs-15pm1Qvk.d.mts.map +1 -0
  3. package/dist/{authoring-type-constructors-0Iv2zdwS-CcpLSwei.mjs → authoring-type-constructors-0Iv2zdwS-hVVlzpLW.mjs} +2 -2
  4. package/dist/{authoring-type-constructors-0Iv2zdwS-CcpLSwei.mjs.map → authoring-type-constructors-0Iv2zdwS-hVVlzpLW.mjs.map} +1 -1
  5. package/dist/{contract-builder-DEtvdts6.mjs → contract-builder-BSipKPrc.mjs} +3 -3
  6. package/dist/{contract-builder-DEtvdts6.mjs.map → contract-builder-BSipKPrc.mjs.map} +1 -1
  7. package/dist/contract-prisma7__provider.mjs +2 -2
  8. package/dist/contract-psl.d.mts +2 -2
  9. package/dist/contract-psl.d.mts.map +1 -1
  10. package/dist/contract-psl.mjs +1 -1
  11. package/dist/contract-psl__attribute-specs.d.mts +2 -86
  12. package/dist/contract-psl__attribute-specs.mjs +1 -1
  13. package/dist/contract-psl__provider.mjs +1 -1
  14. package/dist/contract-psl__provider.mjs.map +1 -1
  15. package/dist/contract-ts.mjs +1 -1
  16. package/dist/contract-ts__contract-builder.mjs +1 -1
  17. package/dist/contract.d.mts +2 -2
  18. package/dist/contract.mjs +2 -2
  19. package/dist/contract__sql-expression.d.mts +2 -2
  20. package/dist/contract__sql-expression.mjs +2 -2
  21. package/dist/{control-BK2oKZmT.d.mts → control-3kVclzEh.d.mts} +20 -19
  22. package/dist/control-3kVclzEh.d.mts.map +1 -0
  23. package/dist/{control-4kwMnHYO.mjs → control-CXHnIBSV.mjs} +5 -5
  24. package/dist/{control-4kwMnHYO.mjs.map → control-CXHnIBSV.mjs.map} +1 -1
  25. package/dist/family.d.mts +5 -5
  26. package/dist/family.mjs +3 -3
  27. package/dist/family__control.d.mts +1 -1
  28. package/dist/family__control.mjs +2 -2
  29. package/dist/family__diff.mjs +1 -1
  30. package/dist/family__pack.d.mts +1 -1
  31. package/dist/family__pack.mjs +2 -2
  32. package/dist/family__psl-build.d.mts +2 -2
  33. package/dist/family__psl-build.mjs +1 -1
  34. package/dist/family__psl-infer.d.mts +1 -1
  35. package/dist/{interpreter-DlG-2o64-CDb20sM1.mjs → interpreter-BTM9k0wn-DPrWFd6h.mjs} +54 -26
  36. package/dist/interpreter-BTM9k0wn-DPrWFd6h.mjs.map +1 -0
  37. package/dist/{pack-D3L1b4Ag.d.mts → pack-g2rKoDhU.d.mts} +19 -18
  38. package/dist/pack-g2rKoDhU.d.mts.map +1 -0
  39. package/dist/{psl-build-C_n5uPZH.d.mts → psl-build-TrbDSGOA.d.mts} +2 -2
  40. package/dist/psl-build-TrbDSGOA.d.mts.map +1 -0
  41. package/dist/{psl-build-DTE03hcr.mjs → psl-build-vdqjrTx6.mjs} +7 -4
  42. package/dist/psl-build-vdqjrTx6.mjs.map +1 -0
  43. package/dist/{psl-column-resolution-CNtNJ7g7-DOrhyw4S.d.mts → psl-column-resolution-Dm5LhN9b-Bz-Ax2iC.d.mts} +2 -2
  44. package/dist/psl-column-resolution-Dm5LhN9b-Bz-Ax2iC.d.mts.map +1 -0
  45. package/dist/{psl-field-resolution-BW0ZuqBd--WxiBxb0.mjs → psl-field-resolution-CAJsUfST-BYuz5Nqh.mjs} +306 -284
  46. package/dist/psl-field-resolution-CAJsUfST-BYuz5Nqh.mjs.map +1 -0
  47. package/dist/{psl-infer-DsHE9xAU.d.mts → psl-infer-Dp_NzWE0.d.mts} +2 -2
  48. package/dist/{psl-infer-DsHE9xAU.d.mts.map → psl-infer-Dp_NzWE0.d.mts.map} +1 -1
  49. package/dist/{schema-verify-DIfHSB4I-k8l0LZZB.mjs → schema-verify-DIfHSB4I-CcxNNnKO.mjs} +2 -2
  50. package/dist/{schema-verify-DIfHSB4I-k8l0LZZB.mjs.map → schema-verify-DIfHSB4I-CcxNNnKO.mjs.map} +1 -1
  51. package/dist/{sql-expression-DE_MTt3T.d.mts → sql-expression-DWyTh9M1.d.mts} +10 -3
  52. package/dist/sql-expression-DWyTh9M1.d.mts.map +1 -0
  53. package/dist/{sql-expression-D7GsLgDM.mjs → sql-expression-Dek0jx_g.mjs} +17 -4
  54. package/dist/sql-expression-Dek0jx_g.mjs.map +1 -0
  55. package/dist/{type-map-3w0ieDAb-DiMpKEc2.d.mts → type-map-BMCZ_fb9-BTmWHQ-J.d.mts} +6 -3
  56. package/dist/type-map-BMCZ_fb9-BTmWHQ-J.d.mts.map +1 -0
  57. package/package.json +18 -18
  58. package/dist/contract-psl__attribute-specs.d.mts.map +0 -1
  59. package/dist/control-BK2oKZmT.d.mts.map +0 -1
  60. package/dist/interpreter-DlG-2o64-CDb20sM1.mjs.map +0 -1
  61. package/dist/pack-D3L1b4Ag.d.mts.map +0 -1
  62. package/dist/psl-build-C_n5uPZH.d.mts.map +0 -1
  63. package/dist/psl-build-DTE03hcr.mjs.map +0 -1
  64. package/dist/psl-column-resolution-CNtNJ7g7-DOrhyw4S.d.mts.map +0 -1
  65. package/dist/psl-field-resolution-BW0ZuqBd--WxiBxb0.mjs.map +0 -1
  66. package/dist/sql-expression-D7GsLgDM.mjs.map +0 -1
  67. package/dist/sql-expression-DE_MTt3T.d.mts.map +0 -1
  68. package/dist/type-map-3w0ieDAb-DiMpKEc2.d.mts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { s as sqlTextFromCanonical, t as SQL_EXPRESSION_DATA_TYPE_ID } from "./sql-expression-D7GsLgDM.mjs";
1
+ import { c as sqlTextFromCanonical, t as SQL_EXPRESSION_DATA_TYPE_ID } from "./sql-expression-Dek0jx_g.mjs";
2
2
  import { n as checkSqlDefaultText, o as reservedSqlDefaultText } from "./validators-CIfn8ezs.mjs";
3
3
  import { a as storedAsListColumn, i as isValueObjectMember } from "./derived-checks-CfXjGvNH-CrXoMrPU.mjs";
4
4
  import { structuredError } from "@prisma/orm-framework/utils/structured-error";
@@ -7,13 +7,13 @@ import { admittedForms, castTypedValue, describeExpected, describeRefusal, descr
7
7
  import { canonicalFormOf, codecForRef } from "@prisma/orm-framework/components/codec";
8
8
  import { blindCast } from "@prisma/orm-framework/utils/casts";
9
9
  import { InternalError, isInternalError } from "@prisma/orm-framework/utils/internal-error";
10
- import { ArrayLiteralAst, FunctionCallAst, IdentifierAst } from "@prisma/orm-framework/psl-parser/syntax";
10
+ import { FunctionCallAst } from "@prisma/orm-framework/psl-parser/syntax";
11
11
  import { assertDefined, invariant } from "@prisma/orm-framework/utils/assertions";
12
12
  import { describeTaggedLiteralFailure } from "@prisma/orm-framework/components/control";
13
13
  import { notOk, ok } from "@prisma/orm-framework/utils/result";
14
- import { bool, diagnosticSource, entityRef, fieldAttribute, fieldRef, funcCall, identifier, interpretAttribute, leafDiagnostic, list, modelAttribute, nodePslSpan, numLiteral, oneOf, optional, record, referencedFieldRef, str, taggedLiteral, typeReferenceNode } from "@prisma/orm-framework/psl-parser";
14
+ import { bool, dataTypeValue, diagnosticSource, entityRef, fieldAttribute, fieldRef, funcCall, identifier, interpretAttribute, leafDiagnostic, list, mapArg, modelAttribute, nodePslSpan, numLiteral, oneOf, optional, record, referencedFieldRef, str, taggedLiteral, typeReferenceNode, writtenList, writtenScalar } from "@prisma/orm-framework/psl-parser";
15
15
  import { instantiatePslFieldPreset, isBareTypeConstructor, mapPslHelperArgs, reportPresetNotCalled, reportTypeConstructorNotCalled } from "@prisma/orm-framework/psl-parser/interpret";
16
- //#region ../../../2-sql/2-authoring/contract-psl/dist/psl-field-resolution-BW0ZuqBd.mjs
16
+ //#region ../../../2-sql/2-authoring/contract-psl/dist/psl-field-resolution-CAJsUfST.mjs
17
17
  function storageName(symbol, physicalNames) {
18
18
  const name = physicalNames.get(symbol);
19
19
  assertDefined(name, "Physical names are populated for every model and field before lowering");
@@ -146,7 +146,10 @@ function storedValueReader(input) {
146
146
  */
147
147
  function readStoredValue(input) {
148
148
  const reading = storedValueReader(input).read(input.value, void 0);
149
- return reading.ok ? reading : storedRefusalDiagnostic(reading.refusal, `Field "${input.fieldPath}"`);
149
+ return reading.ok ? reading : {
150
+ ok: false,
151
+ ...storedRefusalMessage(reading.refusal, `Field "${input.fieldPath}"`)
152
+ };
150
153
  }
151
154
  /**
152
155
  * Read one `@default(...)` value for a column, refusing in parts so each contract source words its
@@ -258,13 +261,23 @@ function rewriteOf(refusal, written, dataTypes) {
258
261
  const refused = refusal.elementIndex === void 0 || written.kind !== "list" ? written : written.elements[refusal.elementIndex];
259
262
  return refused === void 0 || refused.kind === "list" ? void 0 : exactRewrite(dataTypes, refusal.receivingType, refused);
260
263
  }
261
- /** {@link readDataTypeDefault} worded as a PSL diagnostic's code and message. */
264
+ /**
265
+ * {@link readDataTypeDefault} worded as a PSL diagnostic's code, message and span: a cast-rule
266
+ * refusal at the written value, or the element of a written list it is about; a refusal only
267
+ * defaults have at the `@default` attribute.
268
+ */
262
269
  function lowerDataTypeDefault(input) {
263
270
  const read = readDataTypeDefault(input);
264
- return read.ok ? read : refusalDiagnostic(atSourceElement(read.refusal, input.sourceElementIndexes), `Field "${input.fieldPath}"`, input.dataTypes, guidanceFor(read, input.written, input.dataTypes));
271
+ if (read.ok) return read;
272
+ const refusal = atSourceElement(read.refusal, input.sourceElementIndexes);
273
+ return {
274
+ ok: false,
275
+ ...refusalMessage(refusal, `Field "${input.fieldPath}"`, input.dataTypes, guidanceFor(read, input.written, input.dataTypes)),
276
+ span: refusalSpan(refusal, input.spans, input.fieldPath)
277
+ };
265
278
  }
266
279
  /**
267
- * Reads one number literal written in a contract source outside a default, such as an enum member's value, from its source text for a codec, as {@link lowerDataTypeDefault} reads a default: the number's entry gives it a data type, the codec's data type takes it directly or through a cast, and the codec checks it. A refusal is worded for `subject`.
280
+ * Reads one number literal written in a contract source outside a default, such as an enum member's value, from its source text for a codec, as {@link lowerDataTypeDefault} reads a default: the number's entry gives it a data type, the codec's data type takes it directly or through a cast, and the codec checks it. A refusal is worded for `subject`, and the caller reports it at its own span.
268
281
  */
269
282
  function readWrittenNumberForCodec(input) {
270
283
  const written = {
@@ -279,7 +292,10 @@ function readWrittenNumberForCodec(input) {
279
292
  dataTypes: input.dataTypes,
280
293
  fieldPath: input.subject
281
294
  });
282
- return read.ok ? read : refusalDiagnostic(read.refusal, input.subject, input.dataTypes, guidanceFor(read, written, input.dataTypes));
295
+ return read.ok ? read : {
296
+ ok: false,
297
+ ...refusalMessage(read.refusal, input.subject, input.dataTypes, guidanceFor(read, written, input.dataTypes))
298
+ };
283
299
  }
284
300
  /** What a refusal of `written` tells the author to write instead. */
285
301
  function guidanceFor(failure, written, dataTypes) {
@@ -296,61 +312,58 @@ function atSourceElement(refusal, sourceElementIndexes) {
296
312
  elementIndex
297
313
  };
298
314
  }
299
- function codecRefusalDiagnostic(refusal, subject) {
315
+ function codecRefusalMessage(refusal, subject) {
300
316
  return {
301
- ok: false,
302
317
  code: PSL_INVALID_DEFAULT_LITERAL,
303
- message: `${location(subject, refusal.elementIndex)}: ${refusal.message}`,
304
- place: { kind: "attribute" }
318
+ message: `${location(subject, refusal.elementIndex)}: ${refusal.message}`
305
319
  };
306
320
  }
307
- function storedRefusalDiagnostic(refusal, subject) {
308
- if (refusal.kind === "refused-by-codec") return codecRefusalDiagnostic(refusal, subject);
321
+ function storedRefusalMessage(refusal, subject) {
322
+ if (refusal.kind === "refused-by-codec") return codecRefusalMessage(refusal, subject);
309
323
  return {
310
- ok: false,
311
324
  code: "PSL_INVALID_LITERAL",
312
- message: `${location(subject, refusal.elementIndex)}: ${refusal.message}`,
313
- place: { kind: "attribute" }
325
+ message: `${location(subject, refusal.elementIndex)}: ${refusal.message}`
314
326
  };
315
327
  }
316
- /** A refusal worded as a PSL diagnostic's code, message and place; `guidance` says what to write instead. */
317
- function refusalDiagnostic(refusal, subject, dataTypes, guidance) {
328
+ /** A refusal worded as a PSL diagnostic's code and message; `guidance` says what to write instead. */
329
+ function refusalMessage(refusal, subject, dataTypes, guidance) {
318
330
  const where = location(subject, refusal.elementIndex);
319
- const atWrittenValue = {
320
- kind: "written-value",
321
- elementIndex: refusal.elementIndex
322
- };
323
331
  switch (refusal.kind) {
324
332
  case "not-a-list": return {
325
- ok: false,
326
333
  code: PSL_DEFAULT_LIST_EXPECTED,
327
- message: `${where}: this column holds a list, so its default is a list literal, as in [1, 2]`,
328
- place: { kind: "attribute" }
334
+ message: `${where}: this column holds a list, so its default is a list literal, as in [1, 2]`
329
335
  };
330
- case "refused-by-codec": return codecRefusalDiagnostic(refusal, subject);
336
+ case "refused-by-codec": return codecRefusalMessage(refusal, subject);
331
337
  case "no-list-cast": return {
332
- ok: false,
333
338
  code: PSL_VALUE_TYPE_INCOMPATIBLE,
334
- message: `${where}: ${describeExpected(guidance.forms)}; got a list`,
335
- place: atWrittenValue
339
+ message: `${where}: ${describeExpected(guidance.forms)}; got a list`
336
340
  };
337
341
  case "no-element-cast": return {
338
- ok: false,
339
342
  code: PSL_VALUE_TYPE_INCOMPATIBLE,
340
- message: `${where}: ${describeRefusedValueType(refusal, dataTypes, guidance)}`,
341
- place: atWrittenValue
343
+ message: `${where}: ${describeRefusedValueType(refusal, dataTypes, guidance)}`
342
344
  };
343
345
  default: {
344
346
  const { code, message } = describeRefusal(refusal, dataTypes, guidance);
345
347
  return {
346
- ok: false,
347
348
  code,
348
- message: `${where}: ${message}`,
349
- place: atWrittenValue
349
+ message: `${where}: ${message}`
350
350
  };
351
351
  }
352
352
  }
353
353
  }
354
+ function refusalSpan(refusal, spans, fieldPath) {
355
+ switch (refusal.kind) {
356
+ case "not-a-list":
357
+ case "refused-by-codec": return spans.attribute;
358
+ default: return writtenValueSpan(spans, refusal.elementIndex, fieldPath);
359
+ }
360
+ }
361
+ function writtenValueSpan(spans, elementIndex, fieldPath) {
362
+ if (elementIndex === void 0) return spans.value;
363
+ const span = spans.elements[elementIndex];
364
+ if (span === void 0) throw new InternalError(`Field "${fieldPath}": a refused @default list element ${elementIndex + 1} has no written span.`);
365
+ return span;
366
+ }
354
367
  function formatSupportedFunctionList(registry) {
355
368
  const signatures = Array.from(registry.entries()).sort(([a], [b]) => a.localeCompare(b)).flatMap(([functionName, entry]) => {
356
369
  const usageSignatures = entry.usageSignatures?.filter((signature) => signature.length > 0);
@@ -457,16 +470,25 @@ const mapFieldSpec = fieldAttribute("map", {
457
470
  });
458
471
  function nullLiteral() {
459
472
  const nullIdentifier = identifier("null", { documentation: "A null list element or nullable scalar default." });
460
- return {
473
+ return mapArg({
461
474
  kind: "null",
462
475
  label: "null",
463
476
  parse: (arg, ctx) => {
464
477
  const result = nullIdentifier.parse(arg, ctx);
465
478
  return result.ok ? ok(null) : result;
466
479
  }
467
- };
480
+ }, (_null, arg, ctx) => ({
481
+ kind: "null",
482
+ span: nodePslSpan(arg.syntax, ctx.sources)
483
+ }));
484
+ }
485
+ function defaultFunctionArm(name, signature) {
486
+ return mapArg(funcCall(name, signature), (call) => ({
487
+ kind: "default-function",
488
+ call
489
+ }));
468
490
  }
469
- function scalarDefaultArms(isList, dataTypes, registries) {
491
+ function scalarDefaultArms(isList, dataTypes, defaultFunctionRegistry) {
470
492
  const tagArms = (admits) => {
471
493
  const tagsByDocumentation = /* @__PURE__ */ new Map();
472
494
  for (const [dataType, entry] of Object.entries(dataTypes.entries)) {
@@ -475,20 +497,20 @@ function scalarDefaultArms(isList, dataTypes, registries) {
475
497
  if (tags === void 0) tagsByDocumentation.set(entry.documentation, [entry.written.tag]);
476
498
  else tags.push(entry.written.tag);
477
499
  }
478
- return [...tagsByDocumentation].map(([documentation, tags]) => taggedLiteral(tags, { documentation }));
500
+ return [...tagsByDocumentation].map(([documentation, tags]) => writtenScalar(taggedLiteral(tags, { documentation })));
479
501
  };
480
502
  const anyTag = () => tagArms(() => true);
481
- const literal = () => oneOf(str(), numLiteral(), bool(), nullLiteral(), ...tagArms((dataType) => dataType !== SQL_EXPRESSION_DATA_TYPE_ID));
482
- const listArm = () => list(literal(), { label: `list of (${literal().label})` });
483
- const funcArms = [...registries.defaultFunctionRegistry.entries()].map(([name, entry]) => funcCall(name, blindCast(entry.signature)));
503
+ const literal = () => oneOf(writtenScalar(str()), writtenScalar(numLiteral()), writtenScalar(bool()), nullLiteral(), ...tagArms((dataType) => dataType !== SQL_EXPRESSION_DATA_TYPE_ID));
504
+ const listArm = () => writtenList(literal());
505
+ const funcArms = [...defaultFunctionRegistry.entries()].map(([name, entry]) => defaultFunctionArm(name, blindCast(entry.signature)));
484
506
  return isList ? [
485
507
  listArm(),
486
508
  ...funcArms,
487
509
  ...anyTag()
488
510
  ] : [
489
- str(),
490
- numLiteral(),
491
- bool(),
511
+ writtenScalar(str()),
512
+ writtenScalar(numLiteral()),
513
+ writtenScalar(bool()),
492
514
  nullLiteral(),
493
515
  ...funcArms,
494
516
  ...anyTag(),
@@ -531,8 +553,14 @@ function enumMemberNames(ctx) {
531
553
  function enumDefaultArms(members, enumName, isList) {
532
554
  const [first, ...rest] = members;
533
555
  if (first === void 0) return [noEnumMember()];
534
- const member = (name) => identifier(name, { documentation: `The \`${name}\` member of enum \`${enumName}\`.` });
535
- if (isList) return [list(oneOf(member(first), ...rest.map(member), nullLiteral()))];
556
+ const member = (name) => mapArg(identifier(name, { documentation: `The \`${name}\` member of enum \`${enumName}\`.` }), (parsed) => ({
557
+ kind: "member",
558
+ name: parsed
559
+ }));
560
+ if (isList) return [mapArg(list(oneOf(member(first), ...rest.map(member), nullLiteral())), (elements) => ({
561
+ kind: "member-list",
562
+ elements
563
+ }))];
536
564
  return [member(first), ...rest.map(member)];
537
565
  }
538
566
  function defaultFieldSpec(ctx) {
@@ -541,7 +569,7 @@ function defaultFieldSpec(ctx) {
541
569
  documentation: "Supplies a default value when this field is omitted from a mutation.",
542
570
  positional: [{
543
571
  key: "value",
544
- type: defaultValueArm(members === void 0 ? scalarDefaultArms(ctx.field.list, ctx.dataTypes, ctx.controlMutationDefaults) : enumDefaultArms(members, ctx.field.typeName, ctx.field.list), ctx.controlMutationDefaults.defaultFunctionRegistry),
572
+ type: defaultValueArm(members === void 0 ? scalarDefaultArms(ctx.field.list, ctx.dataTypes, ctx.defaultFunctionRegistry) : enumDefaultArms(members, ctx.field.typeName, ctx.field.list), ctx.defaultFunctionRegistry),
545
573
  documentation: "A literal, enum member, or registered default function compatible with this field."
546
574
  }]
547
575
  });
@@ -616,55 +644,57 @@ const uniqueModelSpec = modelAttribute("unique", {
616
644
  const PSL_INDEX_FIELDS_XOR_EXPRESSION = "PSL_INDEX_FIELDS_XOR_EXPRESSION";
617
645
  const PSL_INDEX_EXPRESSION_REQUIRES_NAME = "PSL_INDEX_EXPRESSION_REQUIRES_NAME";
618
646
  const PSL_INDEX_NAME_XOR_MAP = "PSL_INDEX_NAME_XOR_MAP";
619
- const indexModelSpec = modelAttribute("index", {
620
- documentation: "Declares a database index over fields or a SQL expression, optionally restricted by a predicate.",
621
- positional: [{
622
- key: "fields",
623
- type: optional(list(fieldRef(), {
624
- allowEmpty: false,
625
- unique: true
626
- })),
627
- documentation: "The ordered list of distinct indexed fields. Mutually exclusive with `expression`."
628
- }],
629
- named: {
630
- expression: {
631
- type: optional(str()),
632
- documentation: "The SQL index expression. Requires `name` or `map` and cannot be combined with a fields list."
633
- },
634
- where: {
635
- type: optional(str()),
636
- documentation: "The SQL predicate restricting rows included in a partial index."
637
- },
638
- unique: {
639
- type: optional(bool()),
640
- documentation: "Whether the index enforces uniqueness."
641
- },
642
- name: {
643
- type: optional(str()),
644
- documentation: "The index name. Mutually exclusive with `map`."
645
- },
646
- map: {
647
- type: optional(str()),
648
- documentation: "The database index name. Mutually exclusive with `name`."
649
- },
650
- type: {
651
- type: optional(str()),
652
- documentation: "The target-specific index access method."
647
+ function indexModelSpec(ctx) {
648
+ return modelAttribute("index", {
649
+ documentation: "Declares a database index over fields or a SQL expression, optionally restricted by a predicate.",
650
+ positional: [{
651
+ key: "fields",
652
+ type: optional(list(fieldRef(), {
653
+ allowEmpty: false,
654
+ unique: true
655
+ })),
656
+ documentation: "The ordered list of distinct indexed fields. Mutually exclusive with `expression`."
657
+ }],
658
+ named: {
659
+ expression: {
660
+ type: optional(dataTypeValue(SQL_EXPRESSION_DATA_TYPE_ID, ctx.dataTypes)),
661
+ documentation: "The SQL index expression. Requires `name` or `map` and cannot be combined with a fields list."
662
+ },
663
+ where: {
664
+ type: optional(dataTypeValue(SQL_EXPRESSION_DATA_TYPE_ID, ctx.dataTypes)),
665
+ documentation: "The SQL predicate restricting rows included in a partial index."
666
+ },
667
+ unique: {
668
+ type: optional(bool()),
669
+ documentation: "Whether the index enforces uniqueness."
670
+ },
671
+ name: {
672
+ type: optional(str()),
673
+ documentation: "The index name. Mutually exclusive with `map`."
674
+ },
675
+ map: {
676
+ type: optional(str()),
677
+ documentation: "The database index name. Mutually exclusive with `name`."
678
+ },
679
+ type: {
680
+ type: optional(str()),
681
+ documentation: "The target-specific index access method."
682
+ },
683
+ options: {
684
+ type: optional(record(str())),
685
+ documentation: "Target-specific index options. Requires an explicit `type`."
686
+ }
653
687
  },
654
- options: {
655
- type: optional(record(str())),
656
- documentation: "Target-specific index options. Requires an explicit `type`."
688
+ refine: (value, ctx, attributeNode) => {
689
+ const diagnostics = [];
690
+ if (value.fields === void 0 === (value.expression === void 0)) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` requires exactly one of a fields list or an `expression` argument", PSL_INDEX_FIELDS_XOR_EXPRESSION));
691
+ if (value.expression !== void 0 && value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` with an `expression` argument requires a `name` or `map` argument (a default name cannot be derived from an expression)", PSL_INDEX_EXPRESSION_REQUIRES_NAME));
692
+ if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` takes at most one of `name` and `map`", PSL_INDEX_NAME_XOR_MAP));
693
+ if (value.options !== void 0 && value.type === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` options argument requires a type argument"));
694
+ return diagnostics;
657
695
  }
658
- },
659
- refine: (value, ctx, attributeNode) => {
660
- const diagnostics = [];
661
- if (value.fields === void 0 === (value.expression === void 0)) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` requires exactly one of a fields list or an `expression` argument", PSL_INDEX_FIELDS_XOR_EXPRESSION));
662
- if (value.expression !== void 0 && value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` with an `expression` argument requires a `name` or `map` argument (a default name cannot be derived from an expression)", PSL_INDEX_EXPRESSION_REQUIRES_NAME));
663
- if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` takes at most one of `name` and `map`", PSL_INDEX_NAME_XOR_MAP));
664
- if (value.options !== void 0 && value.type === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` options argument requires a type argument"));
665
- return diagnostics;
666
- }
667
- });
696
+ });
697
+ }
668
698
  const PSL_CHECK_REQUIRES_NAME_OR_MAP = "PSL_CHECK_REQUIRES_NAME_OR_MAP";
669
699
  const PSL_CHECK_NAME_XOR_MAP = "PSL_CHECK_NAME_XOR_MAP";
670
700
  const PSL_CHECK_EXPRESSION_EMPTY = "PSL_CHECK_EXPRESSION_EMPTY";
@@ -676,30 +706,32 @@ const PSL_CHECK_EXPRESSION_EMPTY = "PSL_CHECK_EXPRESSION_EMPTY";
676
706
  * declaration, which a single attribute's `refine` cannot see.
677
707
  */
678
708
  const PSL_CHECK_ON_STI_VARIANT = "PSL_CHECK_ON_STI_VARIANT";
679
- const checkModelSpec = modelAttribute("check", {
680
- documentation: "Declares a named database CHECK constraint on this table.",
681
- named: {
682
- expression: {
683
- type: str(),
684
- documentation: "The nonempty SQL predicate checked for each row."
685
- },
686
- name: {
687
- type: optional(str()),
688
- documentation: "The constraint name. Exactly one of `name` and `map` is required."
709
+ function checkModelSpec(ctx) {
710
+ return modelAttribute("check", {
711
+ documentation: "Declares a named database CHECK constraint on this table.",
712
+ named: {
713
+ expression: {
714
+ type: dataTypeValue(SQL_EXPRESSION_DATA_TYPE_ID, ctx.dataTypes),
715
+ documentation: "The nonempty SQL predicate checked for each row."
716
+ },
717
+ name: {
718
+ type: optional(str()),
719
+ documentation: "The constraint name. Exactly one of `name` and `map` is required."
720
+ },
721
+ map: {
722
+ type: optional(str()),
723
+ documentation: "The database constraint name. Exactly one of `name` and `map` is required."
724
+ }
689
725
  },
690
- map: {
691
- type: optional(str()),
692
- documentation: "The database constraint name. Exactly one of `name` and `map` is required."
726
+ refine: (value, ctx, attributeNode) => {
727
+ const diagnostics = [];
728
+ if (sqlTextFromCanonical(value.expression.value).trim().length === 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` expression must not be empty — an empty predicate is not a constraint", PSL_CHECK_EXPRESSION_EMPTY));
729
+ if (value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` requires a `name` or `map` argument (a default name cannot be derived — a check has no column tuple to name itself after)", PSL_CHECK_REQUIRES_NAME_OR_MAP));
730
+ if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` takes at most one of `name` and `map`", PSL_CHECK_NAME_XOR_MAP));
731
+ return diagnostics;
693
732
  }
694
- },
695
- refine: (value, ctx, attributeNode) => {
696
- const diagnostics = [];
697
- if (value.expression.trim().length === 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` expression must not be empty — an empty predicate is not a constraint", PSL_CHECK_EXPRESSION_EMPTY));
698
- if (value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` requires a `name` or `map` argument (a default name cannot be derived — a check has no column tuple to name itself after)", PSL_CHECK_REQUIRES_NAME_OR_MAP));
699
- if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` takes at most one of `name` and `map`", PSL_CHECK_NAME_XOR_MAP));
700
- return diagnostics;
701
- }
702
- });
733
+ });
734
+ }
703
735
  const controlModelSpec = modelAttribute("control", {
704
736
  documentation: "Sets how schema management treats this model’s storage.",
705
737
  positional: [{
@@ -789,6 +821,14 @@ const relationFieldSpec = fieldAttribute("relation", {
789
821
  },
790
822
  refine: relationInvariants
791
823
  });
824
+ function modelSpecContext(input) {
825
+ return {
826
+ symbols: input.symbols,
827
+ model: input.model,
828
+ defaultFunctionRegistry: input.defaultFunctionRegistry,
829
+ dataTypes: input.dataTypes
830
+ };
831
+ }
792
832
  function fieldSpecContext(input) {
793
833
  const node = typeReferenceNode(input.field);
794
834
  return {
@@ -796,27 +836,28 @@ function fieldSpecContext(input) {
796
836
  model: input.model,
797
837
  field: input.field,
798
838
  typeResolution: node === void 0 ? void 0 : input.binder.symbolForNode(node),
799
- controlMutationDefaults: input.controlMutationDefaults,
839
+ defaultFunctionRegistry: input.defaultFunctionRegistry,
800
840
  dataTypes: input.dataTypes
801
841
  };
802
842
  }
843
+ /** Every entry is a factory over the spec context, whether or not its spec reads it. ADR 249. */
803
844
  const sqlAttributeSpecs = {
804
845
  model: {
805
- map: () => mapModelSpec,
806
- id: () => idModelSpec,
807
- unique: () => uniqueModelSpec,
808
- index: () => indexModelSpec,
809
- check: () => checkModelSpec,
810
- control: () => controlModelSpec,
811
- discriminator: () => discriminatorModelSpec,
812
- base: baseModelSpec
846
+ map: (_ctx) => mapModelSpec,
847
+ id: (_ctx) => idModelSpec,
848
+ unique: (_ctx) => uniqueModelSpec,
849
+ index: indexModelSpec,
850
+ check: checkModelSpec,
851
+ control: (_ctx) => controlModelSpec,
852
+ discriminator: (_ctx) => discriminatorModelSpec,
853
+ base: (_ctx) => baseModelSpec()
813
854
  },
814
855
  field: {
815
- map: () => mapFieldSpec,
816
- id: () => idFieldSpec,
817
- unique: () => uniqueFieldSpec,
818
- noCheck: () => noCheckFieldSpec,
819
- relation: () => relationFieldSpec,
856
+ map: (_ctx) => mapFieldSpec,
857
+ id: (_ctx) => idFieldSpec,
858
+ unique: (_ctx) => uniqueFieldSpec,
859
+ noCheck: (_ctx) => noCheckFieldSpec,
860
+ relation: (_ctx) => relationFieldSpec,
820
861
  default: defaultFieldSpec
821
862
  }
822
863
  };
@@ -1289,30 +1330,23 @@ const TAGGED_LITERAL_CANONICALIZATION_CODES = {
1289
1330
  nul: "PSL_TAGGED_LITERAL_NUL",
1290
1331
  "too-large": "PSL_TAGGED_LITERAL_TOO_LARGE"
1291
1332
  };
1292
- function defaultValueExpression(node) {
1293
- return [...node.argList()?.args() ?? []].find((arg) => arg.colon() === void 0)?.value();
1294
- }
1295
- function listElements(expression) {
1296
- const list = expression === void 0 ? void 0 : ArrayLiteralAst.cast(expression.syntax);
1297
- return list === void 0 ? [] : [...list.elements()];
1298
- }
1333
+ /**
1334
+ * Refuses a `null` element in the list default of a field whose list elements are not nullable,
1335
+ * at the first `null`. Returns whether it refused.
1336
+ */
1299
1337
  function rejectStrictListNullDefault(input) {
1300
1338
  if (input.field.elementOptional) return false;
1301
- for (const arg of input.node.argList()?.args() ?? []) {
1302
- const expression = arg.value();
1303
- const list = expression ? ArrayLiteralAst.cast(expression.syntax) : void 0;
1304
- for (const element of list?.elements() ?? []) {
1305
- const identifier = IdentifierAst.cast(element.syntax);
1306
- if (identifier?.token()?.text !== "null") continue;
1307
- input.diagnostics.push({
1308
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1309
- message: `Field "${input.modelName}.${input.field.name}" has strict list elements and cannot use null in a literal list default. Make the element type nullable or remove null from the default.`,
1310
- ...diagnosticSource(input.sources, identifier.syntax).at()
1311
- });
1312
- return true;
1313
- }
1314
- }
1315
- return false;
1339
+ const nullElement = input.elements.find(isParsedNullLiteral);
1340
+ if (nullElement === void 0) return false;
1341
+ input.diagnostics.push({
1342
+ code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1343
+ message: `Field "${input.modelName}.${input.field.name}" has strict list elements and cannot use null in a literal list default. Make the element type nullable or remove null from the default.`,
1344
+ ...input.source.at(nullElement.span)
1345
+ });
1346
+ return true;
1347
+ }
1348
+ function isParsedNullLiteral(element) {
1349
+ return element.kind === "null";
1316
1350
  }
1317
1351
  function lowerDefaultForField(input) {
1318
1352
  const node = getAttribute(input.field.attributes, "default")?.node;
@@ -1323,7 +1357,7 @@ function lowerDefaultForField(input) {
1323
1357
  model: input.model,
1324
1358
  field: input.field,
1325
1359
  binder: input.binder,
1326
- controlMutationDefaults: { defaultFunctionRegistry: input.defaultFunctionRegistry },
1360
+ defaultFunctionRegistry: input.defaultFunctionRegistry,
1327
1361
  dataTypes: input.dataTypes
1328
1362
  }));
1329
1363
  const interpreted = interpretFieldAttribute({
@@ -1338,11 +1372,8 @@ function lowerDefaultForField(input) {
1338
1372
  });
1339
1373
  if (interpreted === void 0) return {};
1340
1374
  const value = interpreted.value;
1341
- if (Array.isArray(value) && value.includes(null) && rejectStrictListNullDefault({
1342
- ...input,
1343
- node
1344
- })) return {};
1345
- if (value === null) {
1375
+ const attributeSpan = nodePslSpan(node.syntax, input.sources);
1376
+ if (value.kind === "null") {
1346
1377
  if (!input.field.optional) {
1347
1378
  input.diagnostics.push({
1348
1379
  code: "PSL_INVALID_DEFAULT_APPLICABILITY",
@@ -1357,17 +1388,16 @@ function lowerDefaultForField(input) {
1357
1388
  canonical: true
1358
1389
  } };
1359
1390
  }
1360
- const valueExpression = defaultValueExpression(node);
1361
- const refusalLocation = (place) => {
1362
- if (place.kind === "attribute") return source.at();
1363
- const expression = place.elementIndex === void 0 ? valueExpression : listElements(valueExpression)[place.elementIndex];
1364
- if (expression === void 0) throw new InternalError(`Field "${input.modelName}.${input.fieldName}": the refused @default value has no written expression.`);
1365
- return diagnosticSource(input.sources, expression.syntax).at();
1366
- };
1391
+ if (value.kind === "list" && rejectStrictListNullDefault({
1392
+ ...input,
1393
+ elements: value.elements,
1394
+ source
1395
+ })) return {};
1367
1396
  const readsListElements = (written) => input.isListColumn || input.field.list && written.kind === "list";
1368
- const readAsLiteral = (written, sourceElementIndexes) => {
1397
+ const readAsLiteral = (written, spans, sourceElementIndexes) => {
1369
1398
  const lowered = lowerDataTypeDefault({
1370
1399
  written,
1400
+ spans,
1371
1401
  sourceElementIndexes,
1372
1402
  isList: readsListElements(written),
1373
1403
  column: input.columnDescriptor,
@@ -1379,15 +1409,15 @@ function lowerDefaultForField(input) {
1379
1409
  input.diagnostics.push({
1380
1410
  code: lowered.code,
1381
1411
  message: lowered.message,
1382
- ...refusalLocation(lowered.place)
1412
+ ...source.at(lowered.span)
1383
1413
  });
1384
1414
  return {};
1385
1415
  }
1386
1416
  let restoredValue = lowered.value;
1387
- if (Array.isArray(value) && value.includes(null) && Array.isArray(lowered.value)) {
1417
+ if (value.kind === "list" && value.elements.some(isParsedNullLiteral) && Array.isArray(lowered.value)) {
1388
1418
  let index = 0;
1389
1419
  const nonNullValues = lowered.value;
1390
- restoredValue = value.map((element) => element === null ? null : nonNullValues[index++] ?? null);
1420
+ restoredValue = value.elements.map((element) => element.kind === "null" ? null : nonNullValues[index++] ?? null);
1391
1421
  }
1392
1422
  if (input.valueObjectDefault !== void 0) {
1393
1423
  const { document, stored } = valueObjectDefaultDocument({
@@ -1424,33 +1454,13 @@ function lowerDefaultForField(input) {
1424
1454
  canonical: true
1425
1455
  } };
1426
1456
  };
1427
- const writtenScalar = (element) => {
1428
- if (typeof element === "string") return {
1429
- kind: "string",
1430
- text: element
1431
- };
1432
- if (typeof element === "boolean") return {
1433
- kind: "boolean",
1434
- value: element
1435
- };
1436
- if ("text" in element) return {
1437
- kind: "number",
1438
- text: element.text
1439
- };
1440
- const { canonicalization } = element;
1441
- if (!canonicalization.ok) {
1442
- input.diagnostics.push({
1443
- code: TAGGED_LITERAL_CANONICALIZATION_CODES[canonicalization.reason],
1444
- message: describeTaggedLiteralFailure(canonicalization.reason),
1445
- ...source.at(element.span)
1446
- });
1447
- return { ok: false };
1448
- }
1449
- return {
1450
- kind: "tag",
1451
- tag: element.tag,
1452
- text: canonicalization.text
1453
- };
1457
+ const canonicalized = (scalar) => {
1458
+ if (scalar.written !== void 0) return scalar.written;
1459
+ input.diagnostics.push({
1460
+ code: TAGGED_LITERAL_CANONICALIZATION_CODES[scalar.reason],
1461
+ message: describeTaggedLiteralFailure(scalar.reason),
1462
+ ...source.at(scalar.span)
1463
+ });
1454
1464
  };
1455
1465
  const sqlExpressionDefault = (text, span) => {
1456
1466
  const reserved = reservedSqlDefaultText(text);
@@ -1468,100 +1478,101 @@ function lowerDefaultForField(input) {
1468
1478
  expression: text
1469
1479
  } };
1470
1480
  };
1481
+ if (value.kind === "member" || value.kind === "member-list") return {};
1471
1482
  if (input.columnDescriptor.valueSet !== void 0) {
1472
- if (typeof value === "string") return { defaultValue: {
1473
- kind: "literal",
1474
- value
1475
- } };
1476
- if (Array.isArray(value)) {
1477
- const members = value.filter((element) => element === null || typeof element === "string");
1478
- if (members.length === value.length) return { defaultValue: {
1483
+ const memberName = (element) => element.kind === "scalar" && element.written?.kind === "string" ? element.written.text : void 0;
1484
+ if (value.kind === "scalar") {
1485
+ const member = memberName(value);
1486
+ if (member !== void 0) return { defaultValue: {
1487
+ kind: "literal",
1488
+ value: member
1489
+ } };
1490
+ }
1491
+ if (value.kind === "list") {
1492
+ const members = value.elements.map((element) => element.kind === "null" ? null : memberName(element));
1493
+ if (members.every((member) => member !== void 0)) return { defaultValue: {
1479
1494
  kind: "literal",
1480
1495
  value: members
1481
1496
  } };
1482
1497
  }
1483
1498
  }
1484
- if (Array.isArray(value)) {
1499
+ if (value.kind === "list") {
1485
1500
  const elements = [];
1486
1501
  const sourceElementIndexes = [];
1487
- for (const [sourceIndex, element] of value.entries()) {
1488
- if (element === null) continue;
1489
- const written = writtenScalar(element);
1490
- if ("ok" in written) return {};
1502
+ for (const [sourceIndex, element] of value.elements.entries()) {
1503
+ if (element.kind === "null") continue;
1504
+ const written = canonicalized(element);
1505
+ if (written === void 0) return {};
1491
1506
  elements.push(written);
1492
1507
  sourceElementIndexes.push(sourceIndex);
1493
1508
  }
1494
1509
  return readAsLiteral({
1495
1510
  kind: "list",
1496
1511
  elements
1512
+ }, {
1513
+ attribute: attributeSpan,
1514
+ value: value.span,
1515
+ elements: value.elements.map((element) => element.span)
1497
1516
  }, sourceElementIndexes);
1498
1517
  }
1499
- if (typeof value === "string") return readAsLiteral({
1500
- kind: "string",
1501
- text: value
1502
- });
1503
- if (typeof value === "boolean") return readAsLiteral({
1504
- kind: "boolean",
1505
- value
1506
- });
1507
- if ("text" in value) return readAsLiteral({
1508
- kind: "number",
1509
- text: value.text
1510
- });
1511
- if ("tag" in value) {
1512
- const written = writtenScalar(value);
1513
- if ("ok" in written) return {};
1518
+ if (value.kind === "scalar") {
1519
+ const written = canonicalized(value);
1520
+ if (written === void 0) return {};
1521
+ const spans = {
1522
+ attribute: attributeSpan,
1523
+ value: value.span,
1524
+ elements: []
1525
+ };
1526
+ if (written.kind !== "tag") return readAsLiteral(written, spans);
1514
1527
  const read = readWrittenValue(input.dataTypes, written);
1515
1528
  if (read.ok && read.value.type === SQL_EXPRESSION_DATA_TYPE_ID) return sqlExpressionDefault(sqlTextFromCanonical(read.value.value), value.span);
1516
- return readAsLiteral(written);
1529
+ return readAsLiteral(written, spans);
1517
1530
  }
1518
- if (typeof value === "object") {
1519
- const context = {
1520
- sourceId: input.sources.sourceFileFor(node.syntax).filename,
1521
- modelName: input.modelName,
1522
- fieldName: input.fieldName,
1523
- columnCodecId: input.columnDescriptor.codecId
1524
- };
1525
- const lowered = lowerDefaultFunctionWithRegistry({
1526
- call: value,
1527
- registry: input.defaultFunctionRegistry,
1528
- context,
1529
- source
1531
+ const { call } = value;
1532
+ const context = {
1533
+ sourceId: input.sources.sourceFileFor(node.syntax).filename,
1534
+ modelName: input.modelName,
1535
+ fieldName: input.fieldName,
1536
+ columnCodecId: input.columnDescriptor.codecId
1537
+ };
1538
+ const lowered = lowerDefaultFunctionWithRegistry({
1539
+ call,
1540
+ registry: input.defaultFunctionRegistry,
1541
+ context,
1542
+ source
1543
+ });
1544
+ if (!lowered.ok) {
1545
+ if (lowered.kind === "owned") input.diagnostics.push(lowered.diagnostic);
1546
+ else input.diagnostics.pushExternal(lowered.diagnostic);
1547
+ return {};
1548
+ }
1549
+ if (lowered.value.kind === "storage") return { defaultValue: lowered.value.defaultValue };
1550
+ const generatorDescriptor = input.generatorDescriptorById.get(lowered.value.generated.id);
1551
+ if (!generatorDescriptor) {
1552
+ input.diagnostics.push({
1553
+ code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1554
+ message: `Default generator "${lowered.value.generated.id}" is not available in the composed mutation default registry.`,
1555
+ ...source.at(call.span)
1530
1556
  });
1531
- if (!lowered.ok) {
1532
- if (lowered.kind === "owned") input.diagnostics.push(lowered.diagnostic);
1533
- else input.diagnostics.pushExternal(lowered.diagnostic);
1534
- return {};
1535
- }
1536
- if (lowered.value.kind === "storage") return { defaultValue: lowered.value.defaultValue };
1537
- const generatorDescriptor = input.generatorDescriptorById.get(lowered.value.generated.id);
1538
- if (!generatorDescriptor) {
1539
- input.diagnostics.push({
1540
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1541
- message: `Default generator "${lowered.value.generated.id}" is not available in the composed mutation default registry.`,
1542
- ...source.at(value.span)
1543
- });
1544
- return {};
1545
- }
1546
- if (generatorDescriptor.applicableCodecIds === void 0) {
1547
- input.diagnostics.push({
1548
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1549
- message: `Default generator "${generatorDescriptor.id}" is not applicable to "@default(...)" lowering. Use the corresponding field preset (e.g. \`temporal.${generatorDescriptor.id === "timestampNow" ? "updatedAt" : generatorDescriptor.id}()\`) instead.`,
1550
- ...source.at(value.span)
1551
- });
1552
- return {};
1553
- }
1554
- if (!generatorDescriptor.applicableCodecIds.includes(input.columnDescriptor.codecId)) {
1555
- input.diagnostics.push({
1556
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1557
- message: `Default generator "${generatorDescriptor.id}" is not applicable to "${input.modelName}.${input.fieldName}" with codecId "${input.columnDescriptor.codecId}".`,
1558
- ...source.at(value.span)
1559
- });
1560
- return {};
1561
- }
1562
- return { executionDefaults: { onCreate: lowered.value.generated } };
1557
+ return {};
1563
1558
  }
1564
- return {};
1559
+ if (generatorDescriptor.applicableCodecIds === void 0) {
1560
+ input.diagnostics.push({
1561
+ code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1562
+ message: `Default generator "${generatorDescriptor.id}" is not applicable to "@default(...)" lowering. Use the corresponding field preset (e.g. \`temporal.${generatorDescriptor.id === "timestampNow" ? "updatedAt" : generatorDescriptor.id}()\`) instead.`,
1563
+ ...source.at(call.span)
1564
+ });
1565
+ return {};
1566
+ }
1567
+ if (!generatorDescriptor.applicableCodecIds.includes(input.columnDescriptor.codecId)) {
1568
+ input.diagnostics.push({
1569
+ code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1570
+ message: `Default generator "${generatorDescriptor.id}" is not applicable to "${input.modelName}.${input.fieldName}" with codecId "${input.columnDescriptor.codecId}".`,
1571
+ ...source.at(call.span)
1572
+ });
1573
+ return {};
1574
+ }
1575
+ return { executionDefaults: { onCreate: lowered.value.generated } };
1565
1576
  }
1566
1577
  function lowerEnumDefaultForField(input) {
1567
1578
  const { field, model, enumHandle, diagnostics } = input;
@@ -1575,7 +1586,7 @@ function lowerEnumDefaultForField(input) {
1575
1586
  model,
1576
1587
  field,
1577
1588
  binder: input.binder,
1578
- controlMutationDefaults: { defaultFunctionRegistry: input.defaultFunctionRegistry },
1589
+ defaultFunctionRegistry: input.defaultFunctionRegistry,
1579
1590
  dataTypes: input.dataTypes
1580
1591
  })),
1581
1592
  symbols: input.symbolTable,
@@ -1587,18 +1598,19 @@ function lowerEnumDefaultForField(input) {
1587
1598
  });
1588
1599
  if (interpreted === void 0) return {};
1589
1600
  const member = interpreted.value;
1590
- if (Array.isArray(member)) {
1591
- if (member.includes(null) && rejectStrictListNullDefault({
1601
+ if (member.kind === "member-list") {
1602
+ if (rejectStrictListNullDefault({
1592
1603
  ...input,
1593
- node
1604
+ elements: member.elements,
1605
+ source: diagnosticSource(input.sources, node.syntax)
1594
1606
  })) return {};
1595
1607
  return { defaultValue: {
1596
1608
  kind: "literal",
1597
- value: blindCast(member.map((entry) => entry === null ? null : enumHandle.enumMembers.find((candidate) => candidate.name === entry)?.value))
1609
+ value: blindCast(member.elements.map((entry) => entry.kind === "null" ? null : enumHandle.enumMembers.find((candidate) => candidate.name === entry.name)?.value))
1598
1610
  } };
1599
1611
  }
1600
- invariant(typeof member === "string", "the enum @default grammar admits only member identifiers, so the parsed value is a string");
1601
- const match = enumHandle.enumMembers.find((m) => m.name === member);
1612
+ invariant(member.kind === "member", "the enum @default grammar admits only member identifiers");
1613
+ const match = enumHandle.enumMembers.find((m) => m.name === member.name);
1602
1614
  if (!match) return {};
1603
1615
  return { defaultValue: {
1604
1616
  kind: "literal",
@@ -1651,7 +1663,7 @@ function extractFieldConstraintNames(input) {
1651
1663
  const idName = idNode === void 0 ? void 0 : interpretFieldAttribute({
1652
1664
  node: idNode,
1653
1665
  symbols: input.symbolTable,
1654
- spec: sqlAttributeSpecs.field.id(),
1666
+ spec: sqlAttributeSpecs.field.id(input.specContext),
1655
1667
  model: input.model,
1656
1668
  field: input.field,
1657
1669
  sources: input.sources,
@@ -1666,7 +1678,7 @@ function extractFieldConstraintNames(input) {
1666
1678
  uniqueName: uniqueNode === void 0 ? void 0 : interpretFieldAttribute({
1667
1679
  node: uniqueNode,
1668
1680
  symbols: input.symbolTable,
1669
- spec: sqlAttributeSpecs.field.unique(),
1681
+ spec: sqlAttributeSpecs.field.unique(input.specContext),
1670
1682
  model: input.model,
1671
1683
  field: input.field,
1672
1684
  sources: input.sources,
@@ -1687,7 +1699,7 @@ function lowerNoCheckForField(input) {
1687
1699
  if (node === void 0) return void 0;
1688
1700
  const interpreted = interpretFieldAttribute({
1689
1701
  node,
1690
- spec: sqlAttributeSpecs.field.noCheck(),
1702
+ spec: sqlAttributeSpecs.field.noCheck(input.specContext),
1691
1703
  symbols: input.symbolTable,
1692
1704
  model: input.model,
1693
1705
  field: input.field,
@@ -1877,10 +1889,19 @@ function collectResolvedFields(input) {
1877
1889
  continue;
1878
1890
  }
1879
1891
  const mappedColumnName = storageName(field, input.physicalNames);
1892
+ const specContext = fieldSpecContext({
1893
+ symbols: symbolTable,
1894
+ model,
1895
+ field,
1896
+ binder,
1897
+ defaultFunctionRegistry,
1898
+ dataTypes
1899
+ });
1880
1900
  const { idAttribute, uniqueAttribute, idName, uniqueName } = extractFieldConstraintNames({
1881
1901
  symbolTable: input.symbolTable,
1882
1902
  model,
1883
1903
  field,
1904
+ specContext,
1884
1905
  sources: input.sources,
1885
1906
  binder: input.binder,
1886
1907
  diagnostics
@@ -1916,6 +1937,7 @@ function collectResolvedFields(input) {
1916
1937
  symbolTable: input.symbolTable,
1917
1938
  model,
1918
1939
  field,
1940
+ specContext,
1919
1941
  sources: input.sources,
1920
1942
  binder: input.binder,
1921
1943
  isListColumn,
@@ -1944,6 +1966,6 @@ function collectResolvedFields(input) {
1944
1966
  return resolvedFields;
1945
1967
  }
1946
1968
  //#endregion
1947
- export { toNamedTypeFieldDescriptor as S, readDataTypeDefault as _, describeUnsupportedSqlAttribute as a, sqlAttributeSpecs as b, getAuthoringEntity as c, instantiatePslTypeConstructor as d, interpretFieldAttribute as f, modelCoordinateKey as g, modelAttributeSpecsFrom as h, contractError as i, getNamedArgument as l, mapFieldNamesToColumns as m, bareTypeConstructorOf as n, formatDbAttributeMigrationMessage as o, interpretModelAttribute as p, collectResolvedFields as r, getAttribute as s, PSL_CHECK_ON_STI_VARIANT as t, instantiateFieldTypeConstructor as u, readWrittenNumberForCodec as v, storageName as x, resolveFieldTypeDescriptor as y };
1969
+ export { storageName as C, sqlAttributeSpecs as S, modelCoordinateKey as _, describeUnsupportedSqlAttribute as a, readWrittenNumberForCodec as b, getAttribute as c, instantiateFieldTypeConstructor as d, instantiatePslTypeConstructor as f, modelAttributeSpecsFrom as g, mapFieldNamesToColumns as h, contractError as i, getAuthoringEntity as l, interpretModelAttribute as m, bareTypeConstructorOf as n, fieldSpecContext as o, interpretFieldAttribute as p, collectResolvedFields as r, formatDbAttributeMigrationMessage as s, PSL_CHECK_ON_STI_VARIANT as t, getNamedArgument as u, modelSpecContext as v, toNamedTypeFieldDescriptor as w, resolveFieldTypeDescriptor as x, readDataTypeDefault as y };
1948
1970
 
1949
- //# sourceMappingURL=psl-field-resolution-BW0ZuqBd--WxiBxb0.mjs.map
1971
+ //# sourceMappingURL=psl-field-resolution-CAJsUfST-BYuz5Nqh.mjs.map