@prisma-next/sql-contract-psl 0.12.0-dev.3 → 0.12.0-dev.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-QE6eZZof.mjs → interpreter-B75uZQde.mjs} +78 -10
- package/dist/interpreter-B75uZQde.mjs.map +1 -0
- package/dist/provider.d.mts +2 -0
- package/dist/provider.d.mts.map +1 -1
- package/dist/provider.mjs +3 -2
- package/dist/provider.mjs.map +1 -1
- package/package.json +12 -12
- package/src/interpreter.ts +30 -9
- package/src/provider.ts +6 -1
- package/src/psl-attribute-parsing.ts +66 -0
- package/dist/interpreter-QE6eZZof.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ This keeps core/CLI source-agnostic while giving PSL-first SQL users a one-line
|
|
|
14
14
|
## Responsibilities
|
|
15
15
|
|
|
16
16
|
- Interpret `ParsePslDocumentResult` into SQL `Contract`
|
|
17
|
-
- Interpret generic PSL attributes into SQL contract semantics (`@id`, `@unique`, `@default`, `@relation`, `@map`, `@@map`)
|
|
17
|
+
- Interpret generic PSL attributes into SQL contract semantics (`@id`, `@unique`, `@default`, `@relation`, `@map`, `@@map`, `@@control`)
|
|
18
18
|
- Interpret SQL timestamp semantics: `DateTime @default(now())` (or the equivalent `temporal.createdAt()` field-preset call) as a storage default, and `temporal.updatedAt()` as an execution mutation default
|
|
19
19
|
- Lower shared constructor expressions in both `types {}` blocks and inline field positions (for example `ShortName = sql.String(length: 35)` and `embedding pgvector.Vector(length: 1536)?`)
|
|
20
20
|
- Lower supported default functions through composed registry inputs
|
|
@@ -71,12 +71,20 @@ Supported timestamp authoring surface:
|
|
|
71
71
|
- The Prisma-flavored `@updatedAt` attribute is not supported; references produce `PSL_UNSUPPORTED_FIELD_ATTRIBUTE` with a migration hint pointing at `temporal.updatedAt()`. The hint is suppressed when the field already declares any `temporal.*` preset.
|
|
72
72
|
- `@createdAt` is not supported as a PSL alias.
|
|
73
73
|
|
|
74
|
+
Model-level control policy:
|
|
75
|
+
|
|
76
|
+
- `@@control(<policy>)` lowers to the storage table's `control` field. The argument is one positional lowercase literal: `managed`, `tolerated`, `external`, or `observed`. Omit `@@control` to leave per-table control unset (the framework default applies at runtime).
|
|
77
|
+
|
|
78
|
+
Contract-level default (specifier options bag):
|
|
79
|
+
|
|
80
|
+
- `defaultControlPolicy` on `prismaContract(...)` sets `Contract.defaultControlPolicy` at load time when the interpreted contract does not already define one (source wins when both are present).
|
|
81
|
+
|
|
74
82
|
## Public API
|
|
75
83
|
|
|
76
84
|
- `@prisma-next/sql-contract-psl`
|
|
77
85
|
- `interpretPslDocumentToSqlContract({ document, target, scalarTypeDescriptors, authoringContributions?, controlMutationDefaults?, composedExtensionPacks? })`
|
|
78
86
|
- `@prisma-next/sql-contract-psl/provider`
|
|
79
|
-
- `prismaContract(schemaPath, { output?, target, scalarTypeDescriptors, authoringContributions?, controlMutationDefaults?, composedExtensionPacks? })`
|
|
87
|
+
- `prismaContract(schemaPath, { output?, target, defaultControlPolicy?, scalarTypeDescriptors, authoringContributions?, controlMutationDefaults?, composedExtensionPacks? })`
|
|
80
88
|
- Provider input is fully preassembled by composition layers (for example `@prisma-next/family-sql/control` helpers).
|
|
81
89
|
|
|
82
90
|
## Dependencies
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Contract } from "@prisma-next/contract/types";
|
|
2
2
|
import { AuthoringContributions } from "@prisma-next/framework-components/authoring";
|
|
3
|
-
import { Namespace } from "@prisma-next/framework-components/ir";
|
|
4
3
|
import { SqlNamespaceTablesInput } from "@prisma-next/sql-contract/types";
|
|
5
4
|
import { Result } from "@prisma-next/utils/result";
|
|
6
5
|
import { ParsePslDocumentResult } from "@prisma-next/psl-parser";
|
|
7
6
|
import { ControlMutationDefaults, ControlMutationDefaults as ControlMutationDefaults$1, DefaultFunctionLoweringContext, DefaultFunctionLoweringHandler, DefaultFunctionRegistry, DefaultFunctionRegistryEntry, MutationDefaultGeneratorDescriptor } from "@prisma-next/framework-components/control";
|
|
8
7
|
import { ContractSourceDiagnostics } from "@prisma-next/config/config-types";
|
|
9
8
|
import { ExtensionPackRef, TargetPackRef } from "@prisma-next/framework-components/components";
|
|
9
|
+
import { Namespace } from "@prisma-next/framework-components/ir";
|
|
10
10
|
|
|
11
11
|
//#region src/psl-column-resolution.d.ts
|
|
12
12
|
type ColumnDescriptor = {
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/psl-column-resolution.ts","../src/interpreter.ts"],"mappings":";;;;;;;;;;;KAyCY,gBAAA;EAAA,SACD,OAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,GAAa,MAAM;AAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/psl-column-resolution.ts","../src/interpreter.ts"],"mappings":";;;;;;;;;;;KAyCY,gBAAA;EAAA,SACD,OAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,GAAa,MAAM;AAAA;;;UC+Cb,sCAAA;EAAA,SACN,QAAA,EAAU,sBAAA;EAAA,SACV,MAAA,EAAQ,aAAA;EAAA,SACR,qBAAA,EAAuB,WAAA,SAAoB,gBAAA;EAAA,SAC3C,sBAAA;EAAA,SACA,yBAAA,YAAqC,gBAAA;EAAA,SACrC,uBAAA,GAA0B,yBAAA;EAAA,SAC1B,sBAAA,GAAyB,sBAAA;EDtDzB;;;AAAmB;;;;AC+C9B;;ED/CW,SCgEA,eAAA,IAAmB,KAAA,EAAO,uBAAA,KAA4B,SAAA;AAAA;AAAA,iBA4zCjD,iCAAA,CACd,KAAA,EAAO,sCAAA,GACN,MAAA,CAAO,QAAA,EAAU,yBAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as interpretPslDocumentToSqlContract } from "./interpreter-
|
|
1
|
+
import { t as interpretPslDocumentToSqlContract } from "./interpreter-B75uZQde.mjs";
|
|
2
2
|
export { interpretPslDocumentToSqlContract };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { crossRef } from "@prisma-next/contract/types";
|
|
2
2
|
import { hasRegisteredFieldNamespace, instantiateAuthoringEntityType, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma-next/framework-components/authoring";
|
|
3
|
-
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
4
3
|
import { isPostgresEnumStorageEntry } from "@prisma-next/sql-contract/types";
|
|
5
4
|
import { buildSqlContractFromDefinition } from "@prisma-next/sql-contract-ts/contract-builder";
|
|
6
5
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
@@ -279,6 +278,56 @@ function findDuplicateFieldName(fieldNames) {
|
|
|
279
278
|
seen.add(name);
|
|
280
279
|
}
|
|
281
280
|
}
|
|
281
|
+
const CONTROL_POLICY_LITERAL_SET = new Set([
|
|
282
|
+
"managed",
|
|
283
|
+
"tolerated",
|
|
284
|
+
"external",
|
|
285
|
+
"observed"
|
|
286
|
+
]);
|
|
287
|
+
function isControlPolicyLiteral(value) {
|
|
288
|
+
return CONTROL_POLICY_LITERAL_SET.has(value);
|
|
289
|
+
}
|
|
290
|
+
function parseControlPolicyAttribute(input) {
|
|
291
|
+
if (input.attribute.args.filter((arg) => arg.kind === "named").length > 0) {
|
|
292
|
+
input.diagnostics.push({
|
|
293
|
+
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
294
|
+
message: "`@@control` does not accept named arguments; pass the policy positionally as `@@control(external)`.",
|
|
295
|
+
sourceId: input.sourceId,
|
|
296
|
+
span: input.attribute.span
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const positionalArgs = getPositionalArguments(input.attribute);
|
|
301
|
+
if (positionalArgs.length === 0) {
|
|
302
|
+
input.diagnostics.push({
|
|
303
|
+
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
304
|
+
message: "`@@control` requires exactly one positional argument: `managed`, `tolerated`, `external`, or `observed`.",
|
|
305
|
+
sourceId: input.sourceId,
|
|
306
|
+
span: input.attribute.span
|
|
307
|
+
});
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (positionalArgs.length > 1) {
|
|
311
|
+
input.diagnostics.push({
|
|
312
|
+
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
313
|
+
message: `\`@@control\` accepts exactly one positional argument; got ${positionalArgs.length}.`,
|
|
314
|
+
sourceId: input.sourceId,
|
|
315
|
+
span: input.attribute.span
|
|
316
|
+
});
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const token = unquoteStringLiteral(positionalArgs[0] ?? "").trim();
|
|
320
|
+
if (!isControlPolicyLiteral(token)) {
|
|
321
|
+
input.diagnostics.push({
|
|
322
|
+
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
323
|
+
message: `\`@@control\` argument \`${token}\` is not a known policy. Allowed: \`managed\`, \`tolerated\`, \`external\`, \`observed\`.`,
|
|
324
|
+
sourceId: input.sourceId,
|
|
325
|
+
span: input.attribute.span
|
|
326
|
+
});
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
return token;
|
|
330
|
+
}
|
|
282
331
|
function mapFieldNamesToColumns(input) {
|
|
283
332
|
const columns = [];
|
|
284
333
|
for (const fieldName of input.fieldNames) {
|
|
@@ -1852,9 +1901,6 @@ const UNSPECIFIED_PSL_NAMESPACE_NAME = "__unspecified__";
|
|
|
1852
1901
|
* slot empty (which means the late-bound default at the `StorageTable`
|
|
1853
1902
|
* layer; emitted JSON omits the field).
|
|
1854
1903
|
*/
|
|
1855
|
-
function defaultSqlNamespaceIdForTarget(targetId) {
|
|
1856
|
-
return targetId === "postgres" ? "public" : UNBOUND_NAMESPACE_ID;
|
|
1857
|
-
}
|
|
1858
1904
|
function resolveNamespaceIdForSqlTarget(input) {
|
|
1859
1905
|
if (input.targetId !== "postgres") return;
|
|
1860
1906
|
if (input.bucketName === UNSPECIFIED_PSL_NAMESPACE_NAME) return "public";
|
|
@@ -2132,6 +2178,8 @@ function buildModelNodeFromPsl(input) {
|
|
|
2132
2178
|
} : void 0;
|
|
2133
2179
|
const hasInlinePrimaryKey = primaryKey !== void 0;
|
|
2134
2180
|
let blockPrimaryKeyDeclared = false;
|
|
2181
|
+
let controlPolicyDeclared = false;
|
|
2182
|
+
let controlPolicy;
|
|
2135
2183
|
const resultBackrelationCandidates = [];
|
|
2136
2184
|
for (const field of model.fields) {
|
|
2137
2185
|
if (!field.list || !input.modelNames.has(field.typeName)) continue;
|
|
@@ -2198,6 +2246,25 @@ function buildModelNodeFromPsl(input) {
|
|
|
2198
2246
|
for (const modelAttribute of model.attributes) {
|
|
2199
2247
|
if (modelAttribute.name === "map") continue;
|
|
2200
2248
|
if (modelAttribute.name === "discriminator" || modelAttribute.name === "base") continue;
|
|
2249
|
+
if (modelAttribute.name === "control") {
|
|
2250
|
+
if (controlPolicyDeclared) {
|
|
2251
|
+
diagnostics.push({
|
|
2252
|
+
code: "PSL_DUPLICATE_ATTRIBUTE",
|
|
2253
|
+
message: `\`@@control\` declared more than once on model "${model.name}".`,
|
|
2254
|
+
sourceId,
|
|
2255
|
+
span: modelAttribute.span
|
|
2256
|
+
});
|
|
2257
|
+
continue;
|
|
2258
|
+
}
|
|
2259
|
+
controlPolicyDeclared = true;
|
|
2260
|
+
const parsed = parseControlPolicyAttribute({
|
|
2261
|
+
attribute: modelAttribute,
|
|
2262
|
+
sourceId,
|
|
2263
|
+
diagnostics
|
|
2264
|
+
});
|
|
2265
|
+
if (parsed !== void 0) controlPolicy = parsed;
|
|
2266
|
+
continue;
|
|
2267
|
+
}
|
|
2201
2268
|
const attributeLabel = `Model "${model.name}" @@${modelAttribute.name}`;
|
|
2202
2269
|
if (modelAttribute.name === "id") {
|
|
2203
2270
|
if (blockPrimaryKeyDeclared) {
|
|
@@ -2520,7 +2587,8 @@ function buildModelNodeFromPsl(input) {
|
|
|
2520
2587
|
...ifDefined("id", primaryKey),
|
|
2521
2588
|
...uniqueConstraints.length > 0 ? { uniques: uniqueConstraints } : {},
|
|
2522
2589
|
...indexNodes.length > 0 ? { indexes: indexNodes } : {},
|
|
2523
|
-
...foreignKeyNodes.length > 0 ? { foreignKeys: foreignKeyNodes } : {}
|
|
2590
|
+
...foreignKeyNodes.length > 0 ? { foreignKeys: foreignKeyNodes } : {},
|
|
2591
|
+
...ifDefined("control", controlPolicy)
|
|
2524
2592
|
},
|
|
2525
2593
|
fkRelationMetadata: resultFkRelationMetadata,
|
|
2526
2594
|
backrelationCandidates: resultBackrelationCandidates,
|
|
@@ -2688,7 +2756,7 @@ function collectPolymorphismDeclarations(models, sourceId, diagnostics) {
|
|
|
2688
2756
|
baseDeclarations
|
|
2689
2757
|
};
|
|
2690
2758
|
}
|
|
2691
|
-
function resolvePolymorphism(models, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds,
|
|
2759
|
+
function resolvePolymorphism(models, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds, defaultNamespaceId, sourceId, diagnostics) {
|
|
2692
2760
|
let patched = models;
|
|
2693
2761
|
for (const [modelName, decl] of discriminatorDeclarations) {
|
|
2694
2762
|
if (baseDeclarations.has(modelName)) {
|
|
@@ -2775,7 +2843,7 @@ function resolvePolymorphism(models, discriminatorDeclarations, baseDeclarations
|
|
|
2775
2843
|
...patched,
|
|
2776
2844
|
[variantName]: {
|
|
2777
2845
|
...variantModel,
|
|
2778
|
-
base: crossRef(baseDecl.baseName, modelNamespaceIds.get(baseDecl.baseName) ??
|
|
2846
|
+
base: crossRef(baseDecl.baseName, modelNamespaceIds.get(baseDecl.baseName) ?? defaultNamespaceId),
|
|
2779
2847
|
...resolvedTable ? { storage: {
|
|
2780
2848
|
...variantModel.storage,
|
|
2781
2849
|
table: resolvedTable
|
|
@@ -2963,7 +3031,7 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
2963
3031
|
}
|
|
2964
3032
|
let patchedModels = patchModelDomainFields(modelsForPatch, modelResolvedFields);
|
|
2965
3033
|
const polyDiagnostics = [];
|
|
2966
|
-
patchedModels = resolvePolymorphism(patchedModels, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds, input.target.
|
|
3034
|
+
patchedModels = resolvePolymorphism(patchedModels, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds, input.target.defaultNamespaceId, sourceId, polyDiagnostics);
|
|
2967
3035
|
if (polyDiagnostics.length > 0) return notOk({
|
|
2968
3036
|
summary: "PSL to SQL contract interpretation failed",
|
|
2969
3037
|
diagnostics: polyDiagnostics
|
|
@@ -2976,11 +3044,11 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
2976
3044
|
domain: { namespaces: Object.fromEntries(Object.entries(contract.domain.namespaces).map(([namespaceId, namespaceSlice]) => [namespaceId, {
|
|
2977
3045
|
models: Object.fromEntries(Object.entries(namespaceSlice.models).map(([modelName, model]) => [modelName, patchedModels[modelName] ?? model])),
|
|
2978
3046
|
...namespaceSlice.valueObjects !== void 0 ? { valueObjects: namespaceSlice.valueObjects } : {},
|
|
2979
|
-
...namespaceId ===
|
|
3047
|
+
...namespaceId === input.target.defaultNamespaceId && Object.keys(valueObjects).length > 0 ? { valueObjects } : {}
|
|
2980
3048
|
}])) }
|
|
2981
3049
|
});
|
|
2982
3050
|
}
|
|
2983
3051
|
//#endregion
|
|
2984
3052
|
export { interpretPslDocumentToSqlContract as t };
|
|
2985
3053
|
|
|
2986
|
-
//# sourceMappingURL=interpreter-
|
|
3054
|
+
//# sourceMappingURL=interpreter-B75uZQde.mjs.map
|