@prisma-next/sql-contract-psl 0.3.0-dev.147 → 0.3.0-dev.163

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.
@@ -1,4 +1,4 @@
1
- import { instantiateAuthoringTypeConstructor, isAuthoringTypeConstructorDescriptor } from "@prisma-next/framework-components/authoring";
1
+ import { instantiateAuthoringTypeConstructor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma-next/framework-components/authoring";
2
2
  import { buildSqlContractFromDefinition } from "@prisma-next/sql-contract-ts/contract-builder";
3
3
  import { ifDefined } from "@prisma-next/utils/defined";
4
4
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -324,6 +324,284 @@ function lowerDefaultFunctionWithRegistry(input) {
324
324
  };
325
325
  }
326
326
 
327
+ //#endregion
328
+ //#region src/psl-authoring-arguments.ts
329
+ const INVALID_AUTHORING_ARGUMENT = Symbol("invalidAuthoringArgument");
330
+ function isIdentifierStartCharacter(character) {
331
+ return character !== void 0 && /[A-Za-z_$]/.test(character);
332
+ }
333
+ function isIdentifierCharacter(character) {
334
+ return character !== void 0 && /[A-Za-z0-9_$]/.test(character);
335
+ }
336
+ function parseJsLikeLiteral(value) {
337
+ let index = 0;
338
+ function skipWhitespace() {
339
+ while (/\s/.test(value[index] ?? "")) index += 1;
340
+ }
341
+ function parseIdentifier() {
342
+ const first = value[index];
343
+ if (!isIdentifierStartCharacter(first)) return INVALID_AUTHORING_ARGUMENT;
344
+ let end = index + 1;
345
+ while (isIdentifierCharacter(value[end])) end += 1;
346
+ const identifier = value.slice(index, end);
347
+ index = end;
348
+ return identifier;
349
+ }
350
+ function parseString() {
351
+ const quote = value[index];
352
+ if (quote !== "\"" && quote !== "'") return INVALID_AUTHORING_ARGUMENT;
353
+ index += 1;
354
+ let result = "";
355
+ while (index < value.length) {
356
+ const character = value[index];
357
+ index += 1;
358
+ if (character === void 0) return INVALID_AUTHORING_ARGUMENT;
359
+ if (character === quote) return result;
360
+ if (character !== "\\") {
361
+ result += character;
362
+ continue;
363
+ }
364
+ const escaped = value[index];
365
+ index += 1;
366
+ if (escaped === void 0) return INVALID_AUTHORING_ARGUMENT;
367
+ switch (escaped) {
368
+ case "'":
369
+ case "\"":
370
+ case "\\":
371
+ case "/":
372
+ result += escaped;
373
+ break;
374
+ case "b":
375
+ result += "\b";
376
+ break;
377
+ case "f":
378
+ result += "\f";
379
+ break;
380
+ case "n":
381
+ result += "\n";
382
+ break;
383
+ case "r":
384
+ result += "\r";
385
+ break;
386
+ case "t":
387
+ result += " ";
388
+ break;
389
+ case "u": {
390
+ const hex = value.slice(index, index + 4);
391
+ if (!/^[0-9A-Fa-f]{4}$/.test(hex)) return INVALID_AUTHORING_ARGUMENT;
392
+ result += String.fromCharCode(Number.parseInt(hex, 16));
393
+ index += 4;
394
+ break;
395
+ }
396
+ default: return INVALID_AUTHORING_ARGUMENT;
397
+ }
398
+ }
399
+ return INVALID_AUTHORING_ARGUMENT;
400
+ }
401
+ function parseNumber() {
402
+ const raw = value.slice(index).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/)?.[0];
403
+ if (!raw) return INVALID_AUTHORING_ARGUMENT;
404
+ const parsed$1 = Number(raw);
405
+ if (!Number.isFinite(parsed$1)) return INVALID_AUTHORING_ARGUMENT;
406
+ index += raw.length;
407
+ return parsed$1;
408
+ }
409
+ function parseArray() {
410
+ if (value[index] !== "[") return INVALID_AUTHORING_ARGUMENT;
411
+ index += 1;
412
+ const result = [];
413
+ skipWhitespace();
414
+ if (value[index] === "]") {
415
+ index += 1;
416
+ return result;
417
+ }
418
+ while (index < value.length) {
419
+ const entry = parseValue();
420
+ if (entry === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
421
+ result.push(entry);
422
+ skipWhitespace();
423
+ if (value[index] === ",") {
424
+ index += 1;
425
+ skipWhitespace();
426
+ continue;
427
+ }
428
+ if (value[index] === "]") {
429
+ index += 1;
430
+ return result;
431
+ }
432
+ return INVALID_AUTHORING_ARGUMENT;
433
+ }
434
+ return INVALID_AUTHORING_ARGUMENT;
435
+ }
436
+ function parseObject() {
437
+ if (value[index] !== "{") return INVALID_AUTHORING_ARGUMENT;
438
+ index += 1;
439
+ const result = {};
440
+ skipWhitespace();
441
+ if (value[index] === "}") {
442
+ index += 1;
443
+ return result;
444
+ }
445
+ while (index < value.length) {
446
+ skipWhitespace();
447
+ const key = value[index] === "\"" || value[index] === "'" ? parseString() : parseIdentifier();
448
+ if (key === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
449
+ skipWhitespace();
450
+ if (value[index] !== ":") return INVALID_AUTHORING_ARGUMENT;
451
+ index += 1;
452
+ const entry = parseValue();
453
+ if (entry === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
454
+ result[key] = entry;
455
+ skipWhitespace();
456
+ if (value[index] === ",") {
457
+ index += 1;
458
+ skipWhitespace();
459
+ continue;
460
+ }
461
+ if (value[index] === "}") {
462
+ index += 1;
463
+ return result;
464
+ }
465
+ return INVALID_AUTHORING_ARGUMENT;
466
+ }
467
+ return INVALID_AUTHORING_ARGUMENT;
468
+ }
469
+ function parseValue() {
470
+ skipWhitespace();
471
+ const character = value[index];
472
+ if (character === "{") return parseObject();
473
+ if (character === "[") return parseArray();
474
+ if (character === "\"" || character === "'") return parseString();
475
+ if (character === "-" || /\d/.test(character ?? "")) return parseNumber();
476
+ const identifier = parseIdentifier();
477
+ if (identifier === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
478
+ if (identifier === "true") return true;
479
+ if (identifier === "false") return false;
480
+ if (identifier === "null") return null;
481
+ return INVALID_AUTHORING_ARGUMENT;
482
+ }
483
+ skipWhitespace();
484
+ const parsed = parseValue();
485
+ if (parsed === INVALID_AUTHORING_ARGUMENT) return parsed;
486
+ skipWhitespace();
487
+ return index === value.length ? parsed : INVALID_AUTHORING_ARGUMENT;
488
+ }
489
+ function parseStringArrayLiteral(value) {
490
+ const parsed = parseJsLikeLiteral(value);
491
+ if (parsed === INVALID_AUTHORING_ARGUMENT || !Array.isArray(parsed)) return INVALID_AUTHORING_ARGUMENT;
492
+ if (!parsed.every((item) => typeof item === "string")) return INVALID_AUTHORING_ARGUMENT;
493
+ return parsed;
494
+ }
495
+ function isPlainObject(value) {
496
+ return typeof value === "object" && value !== null && !Array.isArray(value);
497
+ }
498
+ function parsePslObjectLiteral(value) {
499
+ const trimmed = value.trim();
500
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return INVALID_AUTHORING_ARGUMENT;
501
+ let parsed;
502
+ try {
503
+ parsed = JSON.parse(trimmed);
504
+ } catch {
505
+ parsed = parseJsLikeLiteral(trimmed);
506
+ if (parsed === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
507
+ }
508
+ if (!isPlainObject(parsed)) return INVALID_AUTHORING_ARGUMENT;
509
+ return parsed;
510
+ }
511
+ function parsePslAuthoringArgumentValue(descriptor, rawValue) {
512
+ switch (descriptor.kind) {
513
+ case "string": return unquoteStringLiteral(rawValue);
514
+ case "number": {
515
+ const parsed = Number(unquoteStringLiteral(rawValue));
516
+ return Number.isNaN(parsed) ? INVALID_AUTHORING_ARGUMENT : parsed;
517
+ }
518
+ case "stringArray": return parseStringArrayLiteral(rawValue);
519
+ case "object": return parsePslObjectLiteral(rawValue);
520
+ default: return INVALID_AUTHORING_ARGUMENT;
521
+ }
522
+ }
523
+ function pushInvalidPslHelperArgument(input) {
524
+ input.diagnostics.push({
525
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
526
+ message: `${input.entityLabel} ${input.helperLabel} ${input.message}`,
527
+ sourceId: input.sourceId,
528
+ span: input.span
529
+ });
530
+ }
531
+ function mapPslHelperArgs(input) {
532
+ const mappedArgs = input.descriptors.map(() => void 0);
533
+ const positionalArgs = input.args.filter((arg) => arg.kind === "positional");
534
+ const namedArgs = input.args.filter((arg) => arg.kind === "named");
535
+ if (positionalArgs.length > input.descriptors.length) return pushInvalidPslHelperArgument({
536
+ diagnostics: input.diagnostics,
537
+ sourceId: input.sourceId,
538
+ span: input.span,
539
+ entityLabel: input.entityLabel,
540
+ helperLabel: input.helperLabel,
541
+ message: `accepts at most ${input.descriptors.length} argument(s), received ${positionalArgs.length}.`
542
+ });
543
+ for (const [index, argument] of positionalArgs.entries()) {
544
+ const descriptor = input.descriptors[index];
545
+ if (!descriptor) return pushInvalidPslHelperArgument({
546
+ diagnostics: input.diagnostics,
547
+ sourceId: input.sourceId,
548
+ span: argument.span,
549
+ entityLabel: input.entityLabel,
550
+ helperLabel: input.helperLabel,
551
+ message: `does not define positional argument #${index + 1}.`
552
+ });
553
+ const value = parsePslAuthoringArgumentValue(descriptor, argument.value);
554
+ if (value === INVALID_AUTHORING_ARGUMENT) return pushInvalidPslHelperArgument({
555
+ diagnostics: input.diagnostics,
556
+ sourceId: input.sourceId,
557
+ span: argument.span,
558
+ entityLabel: input.entityLabel,
559
+ helperLabel: input.helperLabel,
560
+ message: `cannot parse argument #${index + 1} for descriptor kind "${descriptor.kind}".`
561
+ });
562
+ mappedArgs[index] = value;
563
+ }
564
+ for (const argument of namedArgs) {
565
+ const descriptorIndex = input.descriptors.findIndex((descriptor$1) => descriptor$1.name === argument.name);
566
+ if (descriptorIndex < 0) return pushInvalidPslHelperArgument({
567
+ diagnostics: input.diagnostics,
568
+ sourceId: input.sourceId,
569
+ span: argument.span,
570
+ entityLabel: input.entityLabel,
571
+ helperLabel: input.helperLabel,
572
+ message: `received unknown named argument "${argument.name}".`
573
+ });
574
+ if (mappedArgs[descriptorIndex] !== void 0) return pushInvalidPslHelperArgument({
575
+ diagnostics: input.diagnostics,
576
+ sourceId: input.sourceId,
577
+ span: argument.span,
578
+ entityLabel: input.entityLabel,
579
+ helperLabel: input.helperLabel,
580
+ message: `received duplicate value for argument "${argument.name}".`
581
+ });
582
+ const descriptor = input.descriptors[descriptorIndex];
583
+ if (!descriptor) return pushInvalidPslHelperArgument({
584
+ diagnostics: input.diagnostics,
585
+ sourceId: input.sourceId,
586
+ span: argument.span,
587
+ entityLabel: input.entityLabel,
588
+ helperLabel: input.helperLabel,
589
+ message: `does not define named argument "${argument.name}".`
590
+ });
591
+ const value = parsePslAuthoringArgumentValue(descriptor, argument.value);
592
+ if (value === INVALID_AUTHORING_ARGUMENT) return pushInvalidPslHelperArgument({
593
+ diagnostics: input.diagnostics,
594
+ sourceId: input.sourceId,
595
+ span: argument.span,
596
+ entityLabel: input.entityLabel,
597
+ helperLabel: input.helperLabel,
598
+ message: `cannot parse named argument "${argument.name}" for descriptor kind "${descriptor.kind}".`
599
+ });
600
+ mappedArgs[descriptorIndex] = value;
601
+ }
602
+ return mappedArgs;
603
+ }
604
+
327
605
  //#endregion
328
606
  //#region src/psl-column-resolution.ts
329
607
  function toNamedTypeFieldDescriptor(typeRef, descriptor) {
@@ -341,6 +619,147 @@ function getAuthoringTypeConstructor(contributions, path) {
341
619
  }
342
620
  return isAuthoringTypeConstructorDescriptor(current) ? current : void 0;
343
621
  }
622
+ /**
623
+ * Returns the namespace prefix of `attributeName` if it references an
624
+ * unrecognized extension namespace, otherwise `undefined`. A namespace is
625
+ * considered recognized when it is:
626
+ *
627
+ * - `db` (native-type spec, always allowed),
628
+ * - the active family id (e.g. `sql`),
629
+ * - the active target id (e.g. `postgres`),
630
+ * - present in `composedExtensions`.
631
+ *
632
+ * Family/target namespaces are exempted so that e.g. `@sql.foo` surfaces as
633
+ * PSL_UNSUPPORTED_*_ATTRIBUTE (the attribute isn't defined) rather than
634
+ * PSL_EXTENSION_NAMESPACE_NOT_COMPOSED (the namespace is already composed).
635
+ */
636
+ function checkUncomposedNamespace(attributeName, composedExtensions, context) {
637
+ const dotIndex = attributeName.indexOf(".");
638
+ if (dotIndex <= 0 || dotIndex === attributeName.length - 1) return;
639
+ const namespace = attributeName.slice(0, dotIndex);
640
+ if (namespace === "db" || namespace === context?.familyId || namespace === context?.targetId || composedExtensions.has(namespace)) return;
641
+ return namespace;
642
+ }
643
+ /**
644
+ * Pushes the canonical `PSL_EXTENSION_NAMESPACE_NOT_COMPOSED` diagnostic for a
645
+ * subject (attribute, model attribute, or type constructor) that references an
646
+ * extension namespace which is not composed in the current contract.
647
+ *
648
+ * The `data` payload carries the missing namespace so machine consumers
649
+ * (agents, IDE extensions, CLI auto-fix) don't have to parse the prose.
650
+ */
651
+ function reportUncomposedNamespace(input) {
652
+ input.diagnostics.push({
653
+ code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
654
+ message: `${input.subjectLabel} uses unrecognized namespace "${input.namespace}". Add extension pack "${input.namespace}" to extensionPacks in prisma-next.config.ts.`,
655
+ sourceId: input.sourceId,
656
+ span: input.span,
657
+ data: {
658
+ namespace: input.namespace,
659
+ suggestedPack: input.namespace
660
+ }
661
+ });
662
+ }
663
+ function instantiatePslTypeConstructor(input) {
664
+ const helperPath = input.call.path.join(".");
665
+ const args = mapPslHelperArgs({
666
+ args: input.call.args,
667
+ descriptors: input.descriptor.args ?? [],
668
+ helperLabel: `constructor "${helperPath}"`,
669
+ span: input.call.span,
670
+ diagnostics: input.diagnostics,
671
+ sourceId: input.sourceId,
672
+ entityLabel: input.entityLabel
673
+ });
674
+ if (!args) return;
675
+ try {
676
+ validateAuthoringHelperArguments(helperPath, input.descriptor.args, args);
677
+ return instantiateAuthoringTypeConstructor(input.descriptor, args);
678
+ } catch (error) {
679
+ const message = error instanceof Error ? error.message : String(error);
680
+ input.diagnostics.push({
681
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
682
+ message: `${input.entityLabel} constructor "${helperPath}" ${message}`,
683
+ sourceId: input.sourceId,
684
+ span: input.call.span
685
+ });
686
+ return;
687
+ }
688
+ }
689
+ function pushUnsupportedTypeConstructorDiagnostic(input) {
690
+ input.diagnostics.push({
691
+ code: input.code,
692
+ message: input.message,
693
+ sourceId: input.sourceId,
694
+ span: input.span
695
+ });
696
+ }
697
+ function resolvePslTypeConstructorDescriptor(input) {
698
+ const descriptor = getAuthoringTypeConstructor(input.authoringContributions, input.call.path);
699
+ if (descriptor) return descriptor;
700
+ const namespace = input.call.path.length > 1 ? input.call.path[0] : void 0;
701
+ if (namespace && namespace !== "db" && namespace !== input.familyId && namespace !== input.targetId && !input.composedExtensions.has(namespace)) {
702
+ reportUncomposedNamespace({
703
+ subjectLabel: `Type constructor "${input.call.path.join(".")}"`,
704
+ namespace,
705
+ sourceId: input.sourceId,
706
+ span: input.call.span,
707
+ diagnostics: input.diagnostics
708
+ });
709
+ return;
710
+ }
711
+ return pushUnsupportedTypeConstructorDiagnostic({
712
+ diagnostics: input.diagnostics,
713
+ sourceId: input.sourceId,
714
+ span: input.call.span,
715
+ code: input.unsupportedCode,
716
+ message: input.unsupportedMessage
717
+ });
718
+ }
719
+ function resolveFieldTypeDescriptor(input) {
720
+ if (input.field.typeConstructor) {
721
+ const helperPath = input.field.typeConstructor.path.join(".");
722
+ const descriptor$1 = resolvePslTypeConstructorDescriptor({
723
+ call: input.field.typeConstructor,
724
+ authoringContributions: input.authoringContributions,
725
+ composedExtensions: input.composedExtensions,
726
+ familyId: input.familyId,
727
+ targetId: input.targetId,
728
+ diagnostics: input.diagnostics,
729
+ sourceId: input.sourceId,
730
+ unsupportedCode: "PSL_UNSUPPORTED_FIELD_TYPE",
731
+ unsupportedMessage: `${input.entityLabel} type constructor "${helperPath}" is not supported in SQL PSL provider v1`
732
+ });
733
+ if (!descriptor$1) return {
734
+ ok: false,
735
+ alreadyReported: true
736
+ };
737
+ const instantiated = instantiatePslTypeConstructor({
738
+ call: input.field.typeConstructor,
739
+ descriptor: descriptor$1,
740
+ diagnostics: input.diagnostics,
741
+ sourceId: input.sourceId,
742
+ entityLabel: input.entityLabel
743
+ });
744
+ if (!instantiated) return {
745
+ ok: false,
746
+ alreadyReported: true
747
+ };
748
+ return {
749
+ ok: true,
750
+ descriptor: instantiated
751
+ };
752
+ }
753
+ const descriptor = resolveColumnDescriptor(input.field, input.enumTypeDescriptors, input.namedTypeDescriptors, input.scalarTypeDescriptors);
754
+ if (!descriptor) return {
755
+ ok: false,
756
+ alreadyReported: false
757
+ };
758
+ return {
759
+ ok: true,
760
+ descriptor
761
+ };
762
+ }
344
763
  const NATIVE_TYPE_SPECS = {
345
764
  "db.VarChar": {
346
765
  args: "optionalLength",
@@ -492,32 +911,6 @@ function resolveDbNativeTypeAttribute(input) {
492
911
  }
493
912
  }
494
913
  }
495
- function parsePgvectorLength(input) {
496
- const namedLength = getNamedArgument(input.attribute, "length");
497
- const namedDim = getNamedArgument(input.attribute, "dim");
498
- const positional = getPositionalArgument(input.attribute);
499
- const raw = namedLength ?? namedDim ?? positional;
500
- if (!raw) {
501
- input.diagnostics.push({
502
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
503
- message: "@pgvector.column requires length/dim argument",
504
- sourceId: input.sourceId,
505
- span: input.attribute.span
506
- });
507
- return;
508
- }
509
- const parsed = Number(unquoteStringLiteral(raw));
510
- if (!Number.isInteger(parsed) || parsed < 1) {
511
- input.diagnostics.push({
512
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
513
- message: "@pgvector.column length/dim must be a positive integer",
514
- sourceId: input.sourceId,
515
- span: input.attribute.span
516
- });
517
- return;
518
- }
519
- return parsed;
520
- }
521
914
  function parseDefaultLiteralValue(expression) {
522
915
  const trimmed = expression.trim();
523
916
  if (trimmed === "true" || trimmed === "false") return {
@@ -612,49 +1005,99 @@ function resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptor
612
1005
 
613
1006
  //#endregion
614
1007
  //#region src/psl-field-resolution.ts
615
- function collectResolvedFields(model, mapping, enumTypeDescriptors, namedTypeDescriptors, namedTypeBaseTypes, modelNames, compositeTypeNames, composedExtensions, authoringContributions, defaultFunctionRegistry, generatorDescriptorById, diagnostics, sourceId, scalarTypeDescriptors) {
1008
+ const BUILTIN_FIELD_ATTRIBUTE_NAMES = new Set([
1009
+ "id",
1010
+ "unique",
1011
+ "default",
1012
+ "relation",
1013
+ "map"
1014
+ ]);
1015
+ function validateFieldAttributes(input) {
1016
+ for (const attribute of input.field.attributes) {
1017
+ if (BUILTIN_FIELD_ATTRIBUTE_NAMES.has(attribute.name)) continue;
1018
+ const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1019
+ familyId: input.familyId,
1020
+ targetId: input.targetId
1021
+ });
1022
+ if (uncomposedNamespace) {
1023
+ reportUncomposedNamespace({
1024
+ subjectLabel: `Attribute "@${attribute.name}"`,
1025
+ namespace: uncomposedNamespace,
1026
+ sourceId: input.sourceId,
1027
+ span: attribute.span,
1028
+ diagnostics: input.diagnostics
1029
+ });
1030
+ continue;
1031
+ }
1032
+ input.diagnostics.push({
1033
+ code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
1034
+ message: `Field "${input.model.name}.${input.field.name}" uses unsupported attribute "@${attribute.name}"`,
1035
+ sourceId: input.sourceId,
1036
+ span: attribute.span
1037
+ });
1038
+ }
1039
+ }
1040
+ function extractFieldConstraintNames(input) {
1041
+ const idAttribute = getAttribute(input.field.attributes, "id");
1042
+ const uniqueAttribute = getAttribute(input.field.attributes, "unique");
1043
+ return {
1044
+ idAttribute,
1045
+ uniqueAttribute,
1046
+ idName: parseConstraintMapArgument({
1047
+ attribute: idAttribute,
1048
+ sourceId: input.sourceId,
1049
+ diagnostics: input.diagnostics,
1050
+ entityLabel: `Field "${input.model.name}.${input.field.name}" @id`,
1051
+ span: input.field.span,
1052
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT"
1053
+ }),
1054
+ uniqueName: parseConstraintMapArgument({
1055
+ attribute: uniqueAttribute,
1056
+ sourceId: input.sourceId,
1057
+ diagnostics: input.diagnostics,
1058
+ entityLabel: `Field "${input.model.name}.${input.field.name}" @unique`,
1059
+ span: input.field.span,
1060
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT"
1061
+ })
1062
+ };
1063
+ }
1064
+ function collectResolvedFields(input) {
1065
+ const { model, mapping, enumTypeDescriptors, namedTypeDescriptors, modelNames, compositeTypeNames, composedExtensions, authoringContributions, familyId, targetId, defaultFunctionRegistry, generatorDescriptorById, diagnostics, sourceId, scalarTypeDescriptors } = input;
616
1066
  const resolvedFields = [];
617
- const pgvectorVectorConstructor = getAuthoringTypeConstructor(authoringContributions, ["pgvector", "vector"]);
618
1067
  for (const field of model.fields) {
619
1068
  if (field.list && modelNames.has(field.typeName)) continue;
620
- for (const attribute of field.attributes) {
621
- if (attribute.name === "id" || attribute.name === "unique" || attribute.name === "default" || attribute.name === "relation" || attribute.name === "map" || attribute.name === "pgvector.column") continue;
622
- if (attribute.name.startsWith("pgvector.") && !composedExtensions.has("pgvector")) {
623
- diagnostics.push({
624
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
625
- message: `Attribute "@${attribute.name}" uses unrecognized namespace "pgvector". Add extension pack "pgvector" to extensionPacks in prisma-next.config.ts.`,
626
- sourceId,
627
- span: attribute.span
628
- });
629
- continue;
630
- }
631
- diagnostics.push({
632
- code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
633
- message: `Field "${model.name}.${field.name}" uses unsupported attribute "@${attribute.name}"`,
634
- sourceId,
635
- span: attribute.span
636
- });
637
- }
1069
+ validateFieldAttributes({
1070
+ model,
1071
+ field,
1072
+ composedExtensions,
1073
+ diagnostics,
1074
+ sourceId,
1075
+ familyId,
1076
+ targetId
1077
+ });
638
1078
  if (getAttribute(field.attributes, "relation") && modelNames.has(field.typeName)) continue;
639
1079
  const isValueObjectField = compositeTypeNames.has(field.typeName);
640
1080
  const isListField = field.list;
641
- const pgvectorOnJsonField = getAttribute(field.attributes, "pgvector.column");
642
- if (pgvectorOnJsonField && (isValueObjectField || isListField)) {
643
- diagnostics.push({
644
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
645
- message: `Field "${model.name}.${field.name}" uses @pgvector.column on a JSON-backed field (${isValueObjectField ? "value object" : "list"}). @pgvector.column is only supported on scalar Bytes fields.`,
646
- sourceId,
647
- span: pgvectorOnJsonField.span
648
- });
649
- continue;
650
- }
651
1081
  let descriptor;
652
1082
  let scalarCodecId;
1083
+ const resolveInput = {
1084
+ field,
1085
+ enumTypeDescriptors,
1086
+ namedTypeDescriptors,
1087
+ scalarTypeDescriptors,
1088
+ authoringContributions,
1089
+ composedExtensions,
1090
+ familyId,
1091
+ targetId,
1092
+ diagnostics,
1093
+ sourceId,
1094
+ entityLabel: `Field "${model.name}.${field.name}"`
1095
+ };
653
1096
  if (isValueObjectField) descriptor = scalarTypeDescriptors.get("Json");
654
1097
  else if (isListField) {
655
- const originalDescriptor = resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors);
656
- if (!originalDescriptor) {
657
- diagnostics.push({
1098
+ const resolved = resolveFieldTypeDescriptor(resolveInput);
1099
+ if (!resolved.ok) {
1100
+ if (!resolved.alreadyReported) diagnostics.push({
658
1101
  code: "PSL_UNSUPPORTED_FIELD_TYPE",
659
1102
  message: `Field "${model.name}.${field.name}" type "${field.typeName}" is not supported in SQL PSL provider v1`,
660
1103
  sourceId,
@@ -662,45 +1105,22 @@ function collectResolvedFields(model, mapping, enumTypeDescriptors, namedTypeDes
662
1105
  });
663
1106
  continue;
664
1107
  }
665
- scalarCodecId = originalDescriptor.codecId;
1108
+ scalarCodecId = resolved.descriptor.codecId;
666
1109
  descriptor = scalarTypeDescriptors.get("Json");
667
1110
  } else {
668
- descriptor = resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors);
669
- const pgvectorColumnAttribute = getAttribute(field.attributes, "pgvector.column");
670
- if (pgvectorColumnAttribute) if (!composedExtensions.has("pgvector")) diagnostics.push({
671
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
672
- message: "Attribute \"@pgvector.column\" uses unrecognized namespace \"pgvector\". Add extension pack \"pgvector\" to extensionPacks in prisma-next.config.ts.",
673
- sourceId,
674
- span: pgvectorColumnAttribute.span
675
- });
676
- else if (!(field.typeName === "Bytes" || namedTypeBaseTypes.get(field.typeRef ?? field.typeName) === "Bytes")) diagnostics.push({
677
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
678
- message: `Field "${model.name}.${field.name}" uses @pgvector.column on unsupported base type "${field.typeName}"`,
679
- sourceId,
680
- span: pgvectorColumnAttribute.span
681
- });
682
- else {
683
- const length = parsePgvectorLength({
684
- attribute: pgvectorColumnAttribute,
685
- diagnostics,
686
- sourceId
1111
+ const resolved = resolveFieldTypeDescriptor(resolveInput);
1112
+ if (!resolved.ok) {
1113
+ if (!resolved.alreadyReported) diagnostics.push({
1114
+ code: "PSL_UNSUPPORTED_FIELD_TYPE",
1115
+ message: `Field "${model.name}.${field.name}" type "${field.typeName}" is not supported in SQL PSL provider v1`,
1116
+ sourceId,
1117
+ span: field.span
687
1118
  });
688
- if (length !== void 0) descriptor = pgvectorVectorConstructor ? instantiateAuthoringTypeConstructor(pgvectorVectorConstructor, [length]) : {
689
- codecId: "pg/vector@1",
690
- nativeType: "vector",
691
- typeParams: { length }
692
- };
1119
+ continue;
693
1120
  }
1121
+ descriptor = resolved.descriptor;
694
1122
  }
695
- if (!descriptor) {
696
- diagnostics.push({
697
- code: "PSL_UNSUPPORTED_FIELD_TYPE",
698
- message: `Field "${model.name}.${field.name}" type "${field.typeName}" is not supported in SQL PSL provider v1`,
699
- sourceId,
700
- span: field.span
701
- });
702
- continue;
703
- }
1123
+ if (!descriptor) continue;
704
1124
  const defaultAttribute = getAttribute(field.attributes, "default");
705
1125
  const loweredDefault = defaultAttribute ? lowerDefaultForField({
706
1126
  modelName: model.name,
@@ -727,23 +1147,11 @@ function collectResolvedFields(model, mapping, enumTypeDescriptors, namedTypeDes
727
1147
  if (generatedDescriptor) descriptor = generatedDescriptor;
728
1148
  }
729
1149
  const mappedColumnName = mapping.fieldColumns.get(field.name) ?? field.name;
730
- const idAttribute = getAttribute(field.attributes, "id");
731
- const uniqueAttribute = getAttribute(field.attributes, "unique");
732
- const idName = parseConstraintMapArgument({
733
- attribute: idAttribute,
734
- sourceId,
735
- diagnostics,
736
- entityLabel: `Field "${model.name}.${field.name}" @id`,
737
- span: field.span,
738
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT"
739
- });
740
- const uniqueName = parseConstraintMapArgument({
741
- attribute: uniqueAttribute,
1150
+ const { idAttribute, uniqueAttribute, idName, uniqueName } = extractFieldConstraintNames({
1151
+ model,
1152
+ field,
742
1153
  sourceId,
743
- diagnostics,
744
- entityLabel: `Field "${model.name}.${field.name}" @unique`,
745
- span: field.span,
746
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT"
1154
+ diagnostics
747
1155
  });
748
1156
  resolvedFields.push({
749
1157
  field,
@@ -1008,12 +1416,17 @@ function validateNavigationListFieldAttributes(input) {
1008
1416
  let valid = true;
1009
1417
  for (const attribute of input.field.attributes) {
1010
1418
  if (attribute.name === "relation") continue;
1011
- if (attribute.name.startsWith("pgvector.") && !input.composedExtensions.has("pgvector")) {
1012
- input.diagnostics.push({
1013
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
1014
- message: `Attribute "@${attribute.name}" uses unrecognized namespace "pgvector". Add extension pack "pgvector" to extensionPacks in prisma-next.config.ts.`,
1419
+ const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1420
+ familyId: input.familyId,
1421
+ targetId: input.targetId
1422
+ });
1423
+ if (uncomposedNamespace) {
1424
+ reportUncomposedNamespace({
1425
+ subjectLabel: `Attribute "@${attribute.name}"`,
1426
+ namespace: uncomposedNamespace,
1015
1427
  sourceId: input.sourceId,
1016
- span: attribute.span
1428
+ span: attribute.span,
1429
+ diagnostics: input.diagnostics
1017
1430
  });
1018
1431
  valid = false;
1019
1432
  continue;
@@ -1042,8 +1455,18 @@ function buildComposedExtensionPackRefs(target, extensionIds, extensionPackRefs
1042
1455
  version: "0.0.1"
1043
1456
  }]));
1044
1457
  }
1045
- function hasSameSpan(a, b) {
1046
- return a.start.offset === b.start.offset && a.end.offset === b.end.offset && a.start.line === b.start.line && a.end.line === b.end.line;
1458
+ function diagnosticDedupKey(diagnostic) {
1459
+ const span = diagnostic.span;
1460
+ const spanKey = span ? `${span.start.offset}:${span.end.offset}:${span.start.line}:${span.end.line}` : "";
1461
+ return `${diagnostic.code}\u0000${diagnostic.sourceId}\u0000${spanKey}\u0000${diagnostic.message}`;
1462
+ }
1463
+ function dedupeDiagnostics(diagnostics) {
1464
+ const seen = /* @__PURE__ */ new Map();
1465
+ for (const diagnostic of diagnostics) {
1466
+ const key = diagnosticDedupKey(diagnostic);
1467
+ if (!seen.has(key)) seen.set(key, diagnostic);
1468
+ }
1469
+ return [...seen.values()];
1047
1470
  }
1048
1471
  function compareStrings(left, right) {
1049
1472
  if (left < right) return -1;
@@ -1092,85 +1515,126 @@ function processEnumDeclarations(input) {
1092
1515
  enumTypeDescriptors
1093
1516
  };
1094
1517
  }
1518
+ function validateNamedTypeAttributes(input) {
1519
+ const [dbNativeTypeAttribute, ...extraDbNativeTypeAttributes] = input.allowDbNativeType ? input.declaration.attributes.filter((attribute) => attribute.name.startsWith("db.")) : [];
1520
+ let hasUnsupportedNamedTypeAttribute = false;
1521
+ for (const extra of extraDbNativeTypeAttributes) {
1522
+ input.diagnostics.push({
1523
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
1524
+ message: `Named type "${input.declaration.name}" can declare at most one @db.* attribute`,
1525
+ sourceId: input.sourceId,
1526
+ span: extra.span
1527
+ });
1528
+ hasUnsupportedNamedTypeAttribute = true;
1529
+ }
1530
+ for (const attribute of input.declaration.attributes) {
1531
+ if (input.allowDbNativeType && attribute.name.startsWith("db.")) continue;
1532
+ const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1533
+ familyId: input.familyId,
1534
+ targetId: input.targetId
1535
+ });
1536
+ if (uncomposedNamespace) {
1537
+ reportUncomposedNamespace({
1538
+ subjectLabel: `Attribute "@${attribute.name}"`,
1539
+ namespace: uncomposedNamespace,
1540
+ sourceId: input.sourceId,
1541
+ span: attribute.span,
1542
+ diagnostics: input.diagnostics
1543
+ });
1544
+ hasUnsupportedNamedTypeAttribute = true;
1545
+ continue;
1546
+ }
1547
+ input.diagnostics.push({
1548
+ code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
1549
+ message: `Named type "${input.declaration.name}" uses unsupported attribute "${attribute.name}"`,
1550
+ sourceId: input.sourceId,
1551
+ span: attribute.span
1552
+ });
1553
+ hasUnsupportedNamedTypeAttribute = true;
1554
+ }
1555
+ return {
1556
+ dbNativeTypeAttribute,
1557
+ hasUnsupportedNamedTypeAttribute
1558
+ };
1559
+ }
1095
1560
  function resolveNamedTypeDeclarations(input) {
1096
1561
  const storageTypes = {};
1097
1562
  const namedTypeDescriptors = /* @__PURE__ */ new Map();
1098
- const namedTypeBaseTypes = /* @__PURE__ */ new Map();
1099
1563
  for (const declaration of input.declarations) {
1100
- const baseDescriptor = input.enumTypeDescriptors.get(declaration.baseType) ?? input.scalarTypeDescriptors.get(declaration.baseType);
1101
- if (!baseDescriptor) {
1102
- input.diagnostics.push({
1103
- code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1104
- message: `Named type "${declaration.name}" references unsupported base type "${declaration.baseType}"`,
1564
+ if (declaration.typeConstructor) {
1565
+ const { hasUnsupportedNamedTypeAttribute: hasUnsupportedNamedTypeAttribute$1 } = validateNamedTypeAttributes({
1566
+ declaration,
1105
1567
  sourceId: input.sourceId,
1106
- span: declaration.span
1568
+ diagnostics: input.diagnostics,
1569
+ composedExtensions: input.composedExtensions,
1570
+ allowDbNativeType: false,
1571
+ familyId: input.familyId,
1572
+ targetId: input.targetId
1107
1573
  });
1108
- continue;
1109
- }
1110
- namedTypeBaseTypes.set(declaration.name, declaration.baseType);
1111
- const pgvectorAttribute = getAttribute(declaration.attributes, "pgvector.column");
1112
- const dbNativeTypeAttribute = declaration.attributes.find((attribute) => attribute.name.startsWith("db."));
1113
- const unsupportedNamedTypeAttribute = declaration.attributes.find((attribute) => attribute.name !== "pgvector.column" && !attribute.name.startsWith("db."));
1114
- if (unsupportedNamedTypeAttribute) {
1115
- input.diagnostics.push({
1116
- code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
1117
- message: `Named type "${declaration.name}" uses unsupported attribute "${unsupportedNamedTypeAttribute.name}"`,
1574
+ if (hasUnsupportedNamedTypeAttribute$1) continue;
1575
+ const helperPath = declaration.typeConstructor.path.join(".");
1576
+ const typeConstructor = resolvePslTypeConstructorDescriptor({
1577
+ call: declaration.typeConstructor,
1578
+ authoringContributions: input.authoringContributions,
1579
+ composedExtensions: input.composedExtensions,
1580
+ familyId: input.familyId,
1581
+ targetId: input.targetId,
1582
+ diagnostics: input.diagnostics,
1583
+ sourceId: input.sourceId,
1584
+ unsupportedCode: "PSL_UNSUPPORTED_NAMED_TYPE_CONSTRUCTOR",
1585
+ unsupportedMessage: `Named type "${declaration.name}" references unsupported constructor "${helperPath}"`
1586
+ });
1587
+ if (!typeConstructor) continue;
1588
+ const storageType = instantiatePslTypeConstructor({
1589
+ call: declaration.typeConstructor,
1590
+ descriptor: typeConstructor,
1591
+ diagnostics: input.diagnostics,
1118
1592
  sourceId: input.sourceId,
1119
- span: unsupportedNamedTypeAttribute.span
1593
+ entityLabel: `Named type "${declaration.name}"`
1120
1594
  });
1595
+ if (!storageType) continue;
1596
+ namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, storageType));
1597
+ storageTypes[declaration.name] = {
1598
+ codecId: storageType.codecId,
1599
+ nativeType: storageType.nativeType,
1600
+ typeParams: storageType.typeParams ?? {}
1601
+ };
1121
1602
  continue;
1122
1603
  }
1123
- if (pgvectorAttribute && dbNativeTypeAttribute) {
1604
+ if (declaration.baseType === void 0) {
1124
1605
  input.diagnostics.push({
1125
- code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
1126
- message: `Named type "${declaration.name}" cannot combine @pgvector.column with @${dbNativeTypeAttribute.name}.`,
1606
+ code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1607
+ message: `Named type "${declaration.name}" must declare a base type or constructor`,
1127
1608
  sourceId: input.sourceId,
1128
- span: dbNativeTypeAttribute.span
1609
+ span: declaration.span
1129
1610
  });
1130
1611
  continue;
1131
1612
  }
1132
- if (pgvectorAttribute) {
1133
- if (!input.composedExtensions.has("pgvector")) {
1134
- input.diagnostics.push({
1135
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
1136
- message: "Attribute \"@pgvector.column\" uses unrecognized namespace \"pgvector\". Add extension pack \"pgvector\" to extensionPacks in prisma-next.config.ts.",
1137
- sourceId: input.sourceId,
1138
- span: pgvectorAttribute.span
1139
- });
1140
- continue;
1141
- }
1142
- if (declaration.baseType !== "Bytes") {
1143
- input.diagnostics.push({
1144
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
1145
- message: `Named type "${declaration.name}" uses @pgvector.column on unsupported base type "${declaration.baseType}"`,
1146
- sourceId: input.sourceId,
1147
- span: pgvectorAttribute.span
1148
- });
1149
- continue;
1150
- }
1151
- const length = parsePgvectorLength({
1152
- attribute: pgvectorAttribute,
1153
- diagnostics: input.diagnostics,
1154
- sourceId: input.sourceId
1613
+ const { baseType } = declaration;
1614
+ const baseDescriptor = input.enumTypeDescriptors.get(baseType) ?? input.scalarTypeDescriptors.get(baseType);
1615
+ if (!baseDescriptor) {
1616
+ input.diagnostics.push({
1617
+ code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1618
+ message: `Named type "${declaration.name}" references unsupported base type "${baseType}"`,
1619
+ sourceId: input.sourceId,
1620
+ span: declaration.span
1155
1621
  });
1156
- if (length === void 0) continue;
1157
- const pgvectorStorageType = input.pgvectorVectorConstructor ? instantiateAuthoringTypeConstructor(input.pgvectorVectorConstructor, [length]) : {
1158
- codecId: "pg/vector@1",
1159
- nativeType: "vector",
1160
- typeParams: { length }
1161
- };
1162
- namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, pgvectorStorageType));
1163
- storageTypes[declaration.name] = {
1164
- codecId: pgvectorStorageType.codecId,
1165
- nativeType: pgvectorStorageType.nativeType,
1166
- typeParams: pgvectorStorageType.typeParams ?? { length }
1167
- };
1168
1622
  continue;
1169
1623
  }
1624
+ const { dbNativeTypeAttribute, hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
1625
+ declaration,
1626
+ sourceId: input.sourceId,
1627
+ diagnostics: input.diagnostics,
1628
+ composedExtensions: input.composedExtensions,
1629
+ allowDbNativeType: true,
1630
+ familyId: input.familyId,
1631
+ targetId: input.targetId
1632
+ });
1633
+ if (hasUnsupportedNamedTypeAttribute) continue;
1170
1634
  if (dbNativeTypeAttribute) {
1171
1635
  const descriptor$1 = resolveDbNativeTypeAttribute({
1172
1636
  attribute: dbNativeTypeAttribute,
1173
- baseType: declaration.baseType,
1637
+ baseType,
1174
1638
  baseDescriptor,
1175
1639
  diagnostics: input.diagnostics,
1176
1640
  sourceId: input.sourceId,
@@ -1195,14 +1659,29 @@ function resolveNamedTypeDeclarations(input) {
1195
1659
  }
1196
1660
  return {
1197
1661
  storageTypes,
1198
- namedTypeDescriptors,
1199
- namedTypeBaseTypes
1662
+ namedTypeDescriptors
1200
1663
  };
1201
1664
  }
1202
1665
  function buildModelNodeFromPsl(input) {
1203
1666
  const { model, mapping, sourceId, diagnostics } = input;
1204
1667
  const tableName = mapping.tableName;
1205
- const resolvedFields = collectResolvedFields(model, mapping, input.enumTypeDescriptors, input.namedTypeDescriptors, input.namedTypeBaseTypes, input.modelNames, input.compositeTypeNames, input.composedExtensions, input.authoringContributions, input.defaultFunctionRegistry, input.generatorDescriptorById, diagnostics, sourceId, input.scalarTypeDescriptors);
1668
+ const resolvedFields = collectResolvedFields({
1669
+ model,
1670
+ mapping,
1671
+ enumTypeDescriptors: input.enumTypeDescriptors,
1672
+ namedTypeDescriptors: input.namedTypeDescriptors,
1673
+ modelNames: input.modelNames,
1674
+ compositeTypeNames: input.compositeTypeNames,
1675
+ composedExtensions: input.composedExtensions,
1676
+ authoringContributions: input.authoringContributions,
1677
+ familyId: input.familyId,
1678
+ targetId: input.targetId,
1679
+ defaultFunctionRegistry: input.defaultFunctionRegistry,
1680
+ generatorDescriptorById: input.generatorDescriptorById,
1681
+ diagnostics,
1682
+ sourceId,
1683
+ scalarTypeDescriptors: input.scalarTypeDescriptors
1684
+ });
1206
1685
  const primaryKeyFields = resolvedFields.filter((field) => field.isId);
1207
1686
  const primaryKeyColumns = primaryKeyFields.map((field) => field.columnName);
1208
1687
  const primaryKeyName = primaryKeyFields.length === 1 ? primaryKeyFields[0]?.idName : void 0;
@@ -1221,7 +1700,9 @@ function buildModelNodeFromPsl(input) {
1221
1700
  field,
1222
1701
  sourceId,
1223
1702
  composedExtensions: input.composedExtensions,
1224
- diagnostics
1703
+ diagnostics,
1704
+ familyId: input.familyId,
1705
+ targetId: input.targetId
1225
1706
  });
1226
1707
  const relationAttribute = getAttribute(field.attributes, "relation");
1227
1708
  let relationName;
@@ -1313,12 +1794,17 @@ function buildModelNodeFromPsl(input) {
1313
1794
  });
1314
1795
  continue;
1315
1796
  }
1316
- if (modelAttribute.name.startsWith("pgvector.") && !input.composedExtensions.has("pgvector")) {
1317
- diagnostics.push({
1318
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
1319
- message: `Attribute "@@${modelAttribute.name}" uses unrecognized namespace "pgvector". Add extension pack "pgvector" to extensionPacks in prisma-next.config.ts.`,
1797
+ const uncomposedNamespace = checkUncomposedNamespace(modelAttribute.name, input.composedExtensions, {
1798
+ familyId: input.familyId,
1799
+ targetId: input.targetId
1800
+ });
1801
+ if (uncomposedNamespace) {
1802
+ reportUncomposedNamespace({
1803
+ subjectLabel: `Attribute "@@${modelAttribute.name}"`,
1804
+ namespace: uncomposedNamespace,
1320
1805
  sourceId,
1321
- span: modelAttribute.span
1806
+ span: modelAttribute.span,
1807
+ diagnostics
1322
1808
  });
1323
1809
  continue;
1324
1810
  }
@@ -1462,7 +1948,8 @@ function buildModelNodeFromPsl(input) {
1462
1948
  resolvedFields
1463
1949
  };
1464
1950
  }
1465
- function buildValueObjects(compositeTypes, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors, diagnostics, sourceId) {
1951
+ function buildValueObjects(input) {
1952
+ const { compositeTypes, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors, composedExtensions, familyId, targetId, authoringContributions, diagnostics, sourceId } = input;
1466
1953
  const valueObjects = {};
1467
1954
  const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
1468
1955
  for (const compositeType of compositeTypes) {
@@ -1482,9 +1969,21 @@ function buildValueObjects(compositeTypes, enumTypeDescriptors, namedTypeDescrip
1482
1969
  } : result;
1483
1970
  continue;
1484
1971
  }
1485
- const descriptor = resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors);
1486
- if (!descriptor) {
1487
- diagnostics.push({
1972
+ const resolved = resolveFieldTypeDescriptor({
1973
+ field,
1974
+ enumTypeDescriptors,
1975
+ namedTypeDescriptors,
1976
+ scalarTypeDescriptors,
1977
+ authoringContributions,
1978
+ composedExtensions,
1979
+ familyId,
1980
+ targetId,
1981
+ diagnostics,
1982
+ sourceId,
1983
+ entityLabel: `Field "${compositeType.name}.${field.name}"`
1984
+ });
1985
+ if (!resolved.ok) {
1986
+ if (!resolved.alreadyReported) diagnostics.push({
1488
1987
  code: "PSL_UNSUPPORTED_FIELD_TYPE",
1489
1988
  message: `Field "${compositeType.name}.${field.name}" type "${field.typeName}" is not supported`,
1490
1989
  sourceId,
@@ -1492,13 +1991,17 @@ function buildValueObjects(compositeTypes, enumTypeDescriptors, namedTypeDescrip
1492
1991
  });
1493
1992
  continue;
1494
1993
  }
1495
- fields[field.name] = {
1994
+ const scalarField = {
1496
1995
  nullable: field.optional,
1497
1996
  type: {
1498
1997
  kind: "scalar",
1499
- codecId: descriptor.codecId
1998
+ codecId: resolved.descriptor.codecId
1500
1999
  }
1501
2000
  };
2001
+ fields[field.name] = field.list ? {
2002
+ ...scalarField,
2003
+ many: true
2004
+ } : scalarField;
1502
2005
  }
1503
2006
  valueObjects[compositeType.name] = { fields };
1504
2007
  }
@@ -1744,7 +2247,9 @@ function interpretPslDocumentToSqlContract(input) {
1744
2247
  enumTypeDescriptors: enumResult.enumTypeDescriptors,
1745
2248
  scalarTypeDescriptors: input.scalarTypeDescriptors,
1746
2249
  composedExtensions,
1747
- pgvectorVectorConstructor: getAuthoringTypeConstructor(input.authoringContributions, ["pgvector", "vector"]),
2250
+ familyId: input.target.familyId,
2251
+ targetId: input.target.targetId,
2252
+ authoringContributions: input.authoringContributions,
1748
2253
  diagnostics
1749
2254
  });
1750
2255
  const storageTypes = {
@@ -1767,8 +2272,9 @@ function interpretPslDocumentToSqlContract(input) {
1767
2272
  compositeTypeNames,
1768
2273
  enumTypeDescriptors: enumResult.enumTypeDescriptors,
1769
2274
  namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
1770
- namedTypeBaseTypes: namedTypeResult.namedTypeBaseTypes,
1771
2275
  composedExtensions,
2276
+ familyId: input.target.familyId,
2277
+ targetId: input.target.targetId,
1772
2278
  authoringContributions: input.authoringContributions,
1773
2279
  defaultFunctionRegistry,
1774
2280
  generatorDescriptorById,
@@ -1790,9 +2296,21 @@ function interpretPslDocumentToSqlContract(input) {
1790
2296
  sourceId
1791
2297
  });
1792
2298
  const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(models, sourceId, diagnostics);
2299
+ const valueObjects = buildValueObjects({
2300
+ compositeTypes,
2301
+ enumTypeDescriptors: enumResult.enumTypeDescriptors,
2302
+ namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
2303
+ scalarTypeDescriptors: input.scalarTypeDescriptors,
2304
+ composedExtensions,
2305
+ familyId: input.target.familyId,
2306
+ targetId: input.target.targetId,
2307
+ authoringContributions: input.authoringContributions,
2308
+ diagnostics,
2309
+ sourceId
2310
+ });
1793
2311
  if (diagnostics.length > 0) return notOk({
1794
2312
  summary: "PSL to SQL contract interpretation failed",
1795
- diagnostics: diagnostics.filter((diagnostic, index, allDiagnostics) => allDiagnostics.findIndex((candidate) => candidate.code === diagnostic.code && candidate.message === diagnostic.message && candidate.sourceId === diagnostic.sourceId && (candidate.span && diagnostic.span && hasSameSpan(candidate.span, diagnostic.span) || !candidate.span && !diagnostic.span)) === index)
2313
+ diagnostics: dedupeDiagnostics(diagnostics)
1796
2314
  });
1797
2315
  const contract = buildSqlContractFromDefinition({
1798
2316
  target: input.target,
@@ -1803,7 +2321,6 @@ function interpretPslDocumentToSqlContract(input) {
1803
2321
  ...modelRelations.has(model.modelName) ? { relations: [...modelRelations.get(model.modelName) ?? []].sort((left, right) => compareStrings(left.fieldName, right.fieldName)) } : {}
1804
2322
  }))
1805
2323
  });
1806
- const valueObjects = buildValueObjects(compositeTypes, enumResult.enumTypeDescriptors, namedTypeResult.namedTypeDescriptors, input.scalarTypeDescriptors, diagnostics, sourceId);
1807
2324
  let patchedModels = patchModelDomainFields(contract.models, modelResolvedFields);
1808
2325
  const polyDiagnostics = [];
1809
2326
  patchedModels = resolvePolymorphism(patchedModels, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, sourceId, polyDiagnostics);
@@ -1823,4 +2340,4 @@ function interpretPslDocumentToSqlContract(input) {
1823
2340
 
1824
2341
  //#endregion
1825
2342
  export { interpretPslDocumentToSqlContract as t };
1826
- //# sourceMappingURL=interpreter-qjtea3zY.mjs.map
2343
+ //# sourceMappingURL=interpreter-iFCRN9nb.mjs.map