@prisma-next/psl-parser 0.14.0-dev.43 → 0.14.0-dev.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +80 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +278 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/attribute-spec/combinators/diagnostic.ts +15 -0
- package/src/attribute-spec/combinators/field-ref.ts +36 -0
- package/src/attribute-spec/combinators/identifier.ts +16 -0
- package/src/attribute-spec/combinators/list.ts +43 -0
- package/src/attribute-spec/combinators/one-of.ts +29 -0
- package/src/attribute-spec/combinators/str.ts +19 -0
- package/src/attribute-spec/field-attribute.ts +27 -0
- package/src/attribute-spec/interpret.ts +154 -0
- package/src/attribute-spec/optional.ts +8 -0
- package/src/attribute-spec/types.ts +72 -0
- package/src/exports/index.ts +24 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { $ as Range, H as SyntaxNode, T as ExpressionAst, b as FieldAttributeAst, c as DocumentAst, et as SourceFile, h as NamespaceDeclarationAst, l as FieldDeclarationAst, m as NamedTypeDeclarationAst, o as CompositeTypeDeclarationAst, p as ModelDeclarationAst, t as ParseDiagnostic, u as GenericBlockDeclarationAst, v as TypeAnnotationAst, x as ModelAttributeAst } from "./parse-BKN_-hW8.mjs";
|
|
2
2
|
import { PslAttribute, PslAttribute as PslAttribute$1, PslAttributeArgument, PslAttributeNamedArgument, PslAttributePositionalArgument, PslAttributeTarget, PslCompositeType, PslDefaultFunctionValue, PslDefaultLiteralValue, PslDefaultValue, PslDiagnostic, PslDiagnostic as PslDiagnostic$1, PslDiagnosticCode, PslDocumentAst, PslExtensionBlock, PslExtensionBlock as PslExtensionBlock$1, PslExtensionBlockAttribute, PslExtensionBlockAttributeArg, PslExtensionBlockParamBare, PslExtensionBlockParamList, PslExtensionBlockParamOption, PslExtensionBlockParamRef, PslExtensionBlockParamScalarValue, PslExtensionBlockParamValue, PslField, PslFieldAttribute, PslModel, PslModelAttribute, PslNamedTypeDeclaration, PslNamespace, PslPosition, PslSpan, PslSpan as PslSpan$1, PslTypeConstructorCall, PslTypesBlock, flatPslModels, namespacePslExtensionBlocks } from "@prisma-next/framework-components/psl-ast";
|
|
3
|
+
import { Result } from "@prisma-next/utils/result";
|
|
3
4
|
import { AuthoringPslBlockDescriptor, AuthoringPslBlockDescriptorNamespace } from "@prisma-next/framework-components/authoring";
|
|
5
|
+
import { Simplify, UnionToIntersection } from "@prisma-next/utils/types";
|
|
4
6
|
import { CodecLookup } from "@prisma-next/framework-components/codec";
|
|
5
7
|
|
|
6
8
|
//#region src/attribute-helpers.d.ts
|
|
@@ -128,6 +130,83 @@ interface SymbolTableResult {
|
|
|
128
130
|
*/
|
|
129
131
|
declare function buildSymbolTable(options: BuildSymbolTableOptions): SymbolTableResult;
|
|
130
132
|
//#endregion
|
|
133
|
+
//#region src/attribute-spec/types.d.ts
|
|
134
|
+
type AttributeLevel = 'field' | 'model' | 'block';
|
|
135
|
+
interface ArgType<T> {
|
|
136
|
+
readonly kind: string;
|
|
137
|
+
readonly label: string;
|
|
138
|
+
readonly _out?: T;
|
|
139
|
+
parse(arg: ExpressionAst, ctx: InterpretCtx): Result<T, readonly PslDiagnostic$1[]>;
|
|
140
|
+
}
|
|
141
|
+
interface InterpretCtx {
|
|
142
|
+
readonly level: AttributeLevel;
|
|
143
|
+
readonly sourceId: string;
|
|
144
|
+
readonly sourceFile: SourceFile;
|
|
145
|
+
readonly selfModel: ModelSymbol;
|
|
146
|
+
resolveReferencedModel(): ModelSymbol | undefined;
|
|
147
|
+
readonly field?: FieldSymbol;
|
|
148
|
+
}
|
|
149
|
+
interface OptionalArgType<T> extends ArgType<T> {
|
|
150
|
+
readonly optional: true;
|
|
151
|
+
readonly hasDefault: boolean;
|
|
152
|
+
readonly defaultValue?: T;
|
|
153
|
+
}
|
|
154
|
+
type Param<T> = ArgType<T>;
|
|
155
|
+
interface PositionalParam<T = unknown> {
|
|
156
|
+
readonly key: string;
|
|
157
|
+
readonly type: Param<T>;
|
|
158
|
+
}
|
|
159
|
+
interface AttributeSpec<Out> {
|
|
160
|
+
readonly level: AttributeLevel;
|
|
161
|
+
readonly name: string;
|
|
162
|
+
readonly positional: readonly PositionalParam[];
|
|
163
|
+
readonly named: Readonly<Record<string, Param<unknown>>>;
|
|
164
|
+
readonly refine?: (parsed: Out, ctx: InterpretCtx) => readonly PslDiagnostic$1[];
|
|
165
|
+
}
|
|
166
|
+
type OutOf<P> = P extends ArgType<infer T> ? T : never;
|
|
167
|
+
type NamedOut<N extends Record<string, Param<unknown>>> = Simplify<{ [K in keyof N as N[K] extends OptionalArgType<unknown> ? never : K]: OutOf<N[K]> } & { [K in keyof N as N[K] extends OptionalArgType<unknown> ? K : never]?: OutOf<N[K]> }>;
|
|
168
|
+
type PosEntryObject<E extends PositionalParam> = E['type'] extends OptionalArgType<unknown> ? { [K in E['key']]?: OutOf<E['type']> } : { [K in E['key']]: OutOf<E['type']> };
|
|
169
|
+
type PosOut<Pos extends readonly PositionalParam[]> = Simplify<UnionToIntersection<{ [I in keyof Pos]: PosEntryObject<Pos[I]> }[number]>>;
|
|
170
|
+
type AttributeOut<Pos extends readonly PositionalParam[], Named extends Record<string, Param<unknown>>> = Simplify<PosOut<Pos> & NamedOut<Named>>;
|
|
171
|
+
type InferAttr<S> = S extends AttributeSpec<infer Out> ? Out : never;
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/attribute-spec/combinators/field-ref.d.ts
|
|
174
|
+
type FieldRefScope = 'self' | 'referenced';
|
|
175
|
+
interface FieldRefArgType extends ArgType<string> {
|
|
176
|
+
readonly scope: FieldRefScope;
|
|
177
|
+
}
|
|
178
|
+
declare function fieldRef(scope: FieldRefScope): FieldRefArgType;
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/attribute-spec/combinators/identifier.d.ts
|
|
181
|
+
declare function identifier<const N extends string>(name: N): ArgType<N>;
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/attribute-spec/combinators/list.d.ts
|
|
184
|
+
interface ListOptions {
|
|
185
|
+
readonly nonEmpty?: boolean;
|
|
186
|
+
readonly unique?: boolean;
|
|
187
|
+
}
|
|
188
|
+
declare function list<T>(of: ArgType<T>, opts?: ListOptions): ArgType<T[]>;
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/attribute-spec/combinators/one-of.d.ts
|
|
191
|
+
declare function oneOf<Alts extends readonly [ArgType<unknown>, ...ArgType<unknown>[]]>(...alts: Alts): ArgType<OutOf<Alts[number]>>;
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/attribute-spec/combinators/str.d.ts
|
|
194
|
+
declare function str(): ArgType<string>;
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/attribute-spec/field-attribute.d.ts
|
|
197
|
+
interface FieldAttributeConfig<Pos extends readonly PositionalParam[], Named extends Record<string, Param<unknown>>> {
|
|
198
|
+
readonly positional?: Pos;
|
|
199
|
+
readonly named?: Named;
|
|
200
|
+
readonly refine?: (parsed: AttributeOut<Pos, Named>, ctx: InterpretCtx) => readonly PslDiagnostic$1[];
|
|
201
|
+
}
|
|
202
|
+
declare function fieldAttribute<const Pos extends readonly PositionalParam[] = readonly [], const Named extends Record<string, Param<unknown>> = Record<never, never>>(name: string, config: FieldAttributeConfig<Pos, Named>): AttributeSpec<AttributeOut<Pos, Named>>;
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/attribute-spec/interpret.d.ts
|
|
205
|
+
declare function interpretAttribute<Out>(attrNode: FieldAttributeAst | ModelAttributeAst, spec: AttributeSpec<Out>, ctx: InterpretCtx): Result<Out, readonly PslDiagnostic$1[]>;
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/attribute-spec/optional.d.ts
|
|
208
|
+
declare function optional<T>(type: ArgType<T>, ...rest: [defaultValue: T] | []): OptionalArgType<T>;
|
|
209
|
+
//#endregion
|
|
131
210
|
//#region src/extension-block.d.ts
|
|
132
211
|
declare function findBlockDescriptor(descriptors: AuthoringPslBlockDescriptorNamespace | undefined, keyword: string): AuthoringPslBlockDescriptor | undefined;
|
|
133
212
|
declare function validateExtensionBlockFromSymbol(input: {
|
|
@@ -139,5 +218,5 @@ declare function validateExtensionBlockFromSymbol(input: {
|
|
|
139
218
|
readonly codecLookup: CodecLookup;
|
|
140
219
|
}): readonly PslDiagnostic$1[];
|
|
141
220
|
//#endregion
|
|
142
|
-
export { type BlockSymbol, type BuildSymbolTableOptions, type CompositeTypeSymbol, type FieldSymbol, type ModelSymbol, type NamespaceSymbol, type PslAttribute, type PslAttributeArgument, type PslAttributeNamedArgument, type PslAttributePositionalArgument, type PslAttributeTarget, type PslCompositeType, type PslDefaultFunctionValue, type PslDefaultLiteralValue, type PslDefaultValue, type PslDiagnostic, type PslDiagnosticCode, type PslDocumentAst, type PslExtensionBlock, type PslExtensionBlockAttribute, type PslExtensionBlockAttributeArg, type PslExtensionBlockParamBare, type PslExtensionBlockParamList, type PslExtensionBlockParamOption, type PslExtensionBlockParamRef, type PslExtensionBlockParamScalarValue, type PslExtensionBlockParamValue, type PslField, type PslFieldAttribute, type PslModel, type PslModelAttribute, type PslNamedTypeDeclaration, type PslNamespace, type PslPosition, type PslSpan, type PslTypeConstructorCall, type PslTypesBlock, type ResolvedAttribute, type ResolvedAttributeArg, type ResolvedNamedTypeBinding, type ResolvedTypeConstructorCall, type ScalarSymbol, type SymbolTable, type SymbolTableResult, type TopLevelScope, type TypeAliasSymbol, buildSymbolTable, findBlockDescriptor, flatPslModels, getPositionalArgument, keywordPslSpan, namespacePslExtensionBlocks, nodePslSpan, parseQuotedStringLiteral, rangeToPslSpan, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, validateExtensionBlockFromSymbol };
|
|
221
|
+
export { type ArgType, type AttributeLevel, type AttributeOut, type AttributeSpec, type BlockSymbol, type BuildSymbolTableOptions, type CompositeTypeSymbol, type FieldRefArgType, type FieldRefScope, type FieldSymbol, type InferAttr, type InterpretCtx, type ListOptions, type ModelSymbol, type NamedOut, type NamespaceSymbol, type OptionalArgType, type OutOf, type Param, type PosOut, type PositionalParam, type PslAttribute, type PslAttributeArgument, type PslAttributeNamedArgument, type PslAttributePositionalArgument, type PslAttributeTarget, type PslCompositeType, type PslDefaultFunctionValue, type PslDefaultLiteralValue, type PslDefaultValue, type PslDiagnostic, type PslDiagnosticCode, type PslDocumentAst, type PslExtensionBlock, type PslExtensionBlockAttribute, type PslExtensionBlockAttributeArg, type PslExtensionBlockParamBare, type PslExtensionBlockParamList, type PslExtensionBlockParamOption, type PslExtensionBlockParamRef, type PslExtensionBlockParamScalarValue, type PslExtensionBlockParamValue, type PslField, type PslFieldAttribute, type PslModel, type PslModelAttribute, type PslNamedTypeDeclaration, type PslNamespace, type PslPosition, type PslSpan, type PslTypeConstructorCall, type PslTypesBlock, type ResolvedAttribute, type ResolvedAttributeArg, type ResolvedNamedTypeBinding, type ResolvedTypeConstructorCall, type ScalarSymbol, type SymbolTable, type SymbolTableResult, type TopLevelScope, type TypeAliasSymbol, buildSymbolTable, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, getPositionalArgument, identifier, interpretAttribute, keywordPslSpan, list, namespacePslExtensionBlocks, nodePslSpan, oneOf, optional, parseQuotedStringLiteral, rangeToPslSpan, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, str, validateExtensionBlockFromSymbol };
|
|
143
222
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/attribute-helpers.ts","../src/resolve.ts","../src/symbol-table.ts","../src/extension-block.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/attribute-helpers.ts","../src/resolve.ts","../src/symbol-table.ts","../src/attribute-spec/types.ts","../src/attribute-spec/combinators/field-ref.ts","../src/attribute-spec/combinators/identifier.ts","../src/attribute-spec/combinators/list.ts","../src/attribute-spec/combinators/one-of.ts","../src/attribute-spec/combinators/str.ts","../src/attribute-spec/field-attribute.ts","../src/attribute-spec/interpret.ts","../src/attribute-spec/optional.ts","../src/extension-block.ts"],"mappings":";;;;;;;;iBAEgB,qBAAA,CAAsB,SAAA,EAAW,cAAY,EAAE,KAAA;AAAA,iBAK/C,wBAAA,CAAyB,KAAa;;;UCMrC,oBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA;EAAA,SACA,UAAA,GAAa,aAAA;EAAA,SACb,IAAA,EAAM,SAAO;AAAA;AAAA,UAGP,iBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA,WAAe,oBAAA;EAAA,SACf,IAAA,EAAM,SAAO;AAAA;AAAA,UAGP,2BAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA,WAAe,oBAAA;EAAA,SACf,IAAA,EAAM,SAAO;AAAA;AAAA,iBAGR,qBAAA,CACd,SAAA,EAAW,iBAAA,GAAoB,iBAAA,EAC/B,UAAA,EAAY,UAAA,GACX,iBAAA;AAAA,iBAQa,sBAAA,CACd,UAAA,EAAY,QAAA,CAAS,iBAAA,GAAoB,iBAAA,GACzC,UAAA,EAAY,UAAA,YACF,iBAAA;AAAA,iBAII,2BAAA,CACd,UAAA,EAAY,iBAAA,cACZ,UAAA,EAAY,UAAA,GACX,2BAAA;AAAA,iBAuCa,WAAA,CAAY,IAAA,EAAM,UAAA,EAAY,UAAA,EAAY,UAAA,GAAa,SAAA;;iBAUvD,cAAA,CAAe,IAAA,EAAM,UAAA,EAAY,OAAA,UAAiB,UAAA,EAAY,UAAA,GAAa,SAAA;AAAA,iBAS3E,cAAA,CAAe,KAAA,EAAO,KAAA,EAAO,UAAA,EAAY,UAAA,GAAa,SAAA;;;UChFrD,WAAA;EAAA,SACN,QAAA,EAAU,aAAa;AAAA;AAAA,UAGjB,aAAA;EAAA,SACN,UAAA,EAAY,MAAA,SAAe,eAAA;EAAA,SAC3B,OAAA,EAAS,MAAA,SAAe,YAAA;EAAA,SACxB,WAAA,EAAa,MAAA,SAAe,eAAA;EAAA,SAC5B,MAAA,EAAQ,MAAA,SAAe,WAAA;EAAA,SACvB,MAAA,EAAQ,MAAA,SAAe,WAAA;EAAA,SACvB,cAAA,EAAgB,MAAA,SAAe,mBAAA;AAAA;AAAA,UAGzB,eAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,uBAAA;EAAA,SACN,IAAA,EAAM,SAAA;EAAA,SACN,MAAA,EAAQ,MAAA,SAAe,WAAA;EAAA,SACvB,cAAA,EAAgB,MAAA,SAAe,mBAAA;EAAA,SAC/B,MAAA,EAAQ,MAAA,SAAe,WAAA;AAAA;AAAA,UAGjB,WAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,mBAAA;EAAA,SACN,IAAA,EAAM,SAAA;EAAA,SACN,MAAA,EAAQ,MAAA,SAAe,WAAA;EAAA,SACvB,UAAA,WAAqB,iBAAA;AAAA;AAAA,UAGf,mBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,2BAAA;EAAA,SACN,IAAA,EAAM,SAAA;EAAA,SACN,MAAA,EAAQ,MAAA,SAAe,WAAA;EAAA,SACvB,UAAA,WAAqB,iBAAA;AAAA;AAAA,UAGf,WAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA,EAAM,0BAAA;EAAA,SACN,IAAA,EAAM,SAAA;EDnDA;EAAA,SCqDN,KAAA,EAAO,mBAAA;AAAA;AAAA,UAGD,wBAAA;EAAA,SACN,QAAA;EAAA,SACA,eAAA,GAAkB,2BAAA;EAAA,SAClB,aAAA;EAAA,SACA,UAAA,WAAqB,iBAAiB;AAAA;AAAA,UAGhC,YAAA,SAAqB,wBAAA;EAAA,SAC3B,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,uBAAA;EAAA,SACN,IAAA,EAAM,SAAA;AAAA;AAAA,UAGA,eAAA,SAAwB,wBAAA;EAAA,SAC9B,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,uBAAA;EAAA,SACN,IAAA,EAAM,SAAA;AAAA;AAAA,UAGA,WAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,mBAAA;EAAA,SACN,IAAA,EAAM,SAAA;EAAA,SACN,QAAA;EAAA,SACA,eAAA;EAAA,SACA,mBAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,eAAA,GAAkB,2BAAA;EAAA,SAClB,UAAA,WAAqB,iBAAA;EDtElB;EAAA,SCwEH,aAAA;AAAA;AAAA,UAGM,uBAAA;EAAA,SACN,QAAA,EAAU,WAAA;EAAA,SACV,UAAA,EAAY,UAAA;EAAA,SACZ,WAAA;EAAA,SACA,mBAAA,EAAqB,oCAAA;AAAA;AAAA,UAGf,iBAAA;EAAA,SACN,KAAA,EAAO,WAAA;EAAA,SACP,WAAA,WAAsB,eAAe;AAAA;ADlFnB;AAI7B;;;AAJ6B,iBCyFb,gBAAA,CAAiB,OAAA,EAAS,uBAAA,GAA0B,iBAAiB;;;KCjIzE,cAAA;AAAA,UAEK,OAAA;EAAA,SACN,IAAA;EAAA,SACA,KAAA;EAAA,SAEA,IAAA,GAAO,CAAA;EAChB,KAAA,CAAM,GAAA,EAAK,aAAA,EAAe,GAAA,EAAK,YAAA,GAAe,MAAA,CAAO,CAAA,WAAY,eAAA;AAAA;AAAA,UAGlD,YAAA;EAAA,SACN,KAAA,EAAO,cAAA;EAAA,SACP,QAAA;EAAA,SACA,UAAA,EAAY,UAAA;EAAA,SACZ,SAAA,EAAW,WAAA;EACpB,sBAAA,IAA0B,WAAA;EAAA,SACjB,KAAA,GAAQ,WAAA;AAAA;AAAA,UAGF,eAAA,YAA2B,OAAA,CAAQ,CAAA;EAAA,SAEzC,QAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA,GAAe,CAAA;AAAA;AAAA,KAGd,KAAA,MAAW,OAAO,CAAC,CAAA;AAAA,UAEd,eAAA;EAAA,SACN,GAAA;EAAA,SACA,IAAA,EAAM,KAAK,CAAC,CAAA;AAAA;AAAA,UAGN,aAAA;EAAA,SACN,KAAA,EAAO,cAAA;EAAA,SACP,IAAA;EAAA,SACA,UAAA,WAAqB,eAAA;EAAA,SACrB,KAAA,EAAO,QAAA,CAAS,MAAA,SAAe,KAAA;EAAA,SAC/B,MAAA,IAAU,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,YAAA,cAA0B,eAAA;AAAA;AAAA,KAGrD,KAAA,MAAW,CAAA,SAAU,OAAO,YAAY,CAAA;AAAA,KAExC,QAAA,WAAmB,MAAA,SAAe,KAAA,cAAmB,QAAA,eACjD,CAAA,IAAK,CAAA,CAAE,CAAA,UAAW,eAAA,oBAAmC,CAAA,GAAI,KAAA,CAAM,CAAA,CAAE,CAAA,qBACjE,CAAA,IAAK,CAAA,CAAE,CAAA,UAAW,eAAA,YAA2B,CAAA,YAAa,KAAA,CAAM,CAAA,CAAE,CAAA;AAAA,KAI7E,cAAA,WAAyB,eAAA,IAC5B,CAAA,iBAAkB,eAAA,oBACN,CAAA,WAAY,KAAA,CAAM,CAAA,sBAClB,CAAA,UAAW,KAAA,CAAM,CAAA;AAAA,KAEnB,MAAA,sBAA4B,eAAA,MAAqB,QAAA,CAC3D,mBAAA,eAAkC,GAAA,GAAM,cAAA,CAAe,GAAA,CAAI,CAAA;AAAA,KAGjD,YAAA,sBACW,eAAA,kBACP,MAAA,SAAe,KAAA,cAC3B,QAAA,CAAS,MAAA,CAAO,GAAA,IAAO,QAAA,CAAS,KAAA;AAAA,KAGxB,SAAA,MAAe,CAAA,SAAU,aAAa,cAAc,GAAA;;;KCjEpD,aAAA;AAAA,UAEK,eAAA,SAAwB,OAAO;EAAA,SACrC,KAAA,EAAO,aAAA;AAAA;AAAA,iBAGF,QAAA,CAAS,KAAA,EAAO,aAAA,GAAgB,eAAe;;;iBCN/C,UAAA,yBAAmC,IAAA,EAAM,CAAA,GAAI,OAAA,CAAQ,CAAA;;;UCApD,WAAA;EAAA,SACN,QAAA;EAAA,SACA,MAAM;AAAA;AAAA,iBAGD,IAAA,IAAQ,EAAA,EAAI,OAAA,CAAQ,CAAA,GAAI,IAAA,GAAO,WAAA,GAAc,OAAA,CAAQ,CAAA;;;iBCLrD,KAAA,wBAA6B,OAAA,cAAqB,OAAA,iBAC7D,IAAA,EAAM,IAAA,GACR,OAAA,CAAQ,KAAA,CAAM,IAAA;;;iBCFD,GAAA,IAAO,OAAO;;;UCHpB,oBAAA,sBACa,eAAA,kBACP,MAAA,SAAe,KAAA;EAAA,SAEpB,UAAA,GAAa,GAAA;EAAA,SACb,KAAA,GAAQ,KAAA;EAAA,SACR,MAAA,IACP,MAAA,EAAQ,YAAA,CAAa,GAAA,EAAK,KAAA,GAC1B,GAAA,EAAK,YAAA,cACO,eAAA;AAAA;AAAA,iBAGA,cAAA,4BACa,eAAA,sCACP,MAAA,SAAe,KAAA,aAAkB,MAAA,gBACrD,IAAA,UAAc,MAAA,EAAQ,oBAAA,CAAqB,GAAA,EAAK,KAAA,IAAS,aAAA,CAAc,YAAA,CAAa,GAAA,EAAK,KAAA;;;iBCT3E,kBAAA,MACd,QAAA,EAAU,iBAAA,GAAoB,iBAAA,EAC9B,IAAA,EAAM,aAAA,CAAc,GAAA,GACpB,GAAA,EAAK,YAAA,GACJ,MAAA,CAAO,GAAA,WAAc,eAAA;;;iBCXR,QAAA,IAAY,IAAA,EAAM,OAAA,CAAQ,CAAA,MAAO,IAAA,GAAO,YAAA,EAAc,CAAA,SAAU,eAAA,CAAgB,CAAA;;;iBCgBhF,mBAAA,CACd,WAAA,EAAa,oCAAA,cACb,OAAA,WACC,2BAA2B;AAAA,iBAcd,gCAAA,CAAiC,KAAA;EAAA,SACtC,KAAA,EAAO,WAAA;EAAA,SACP,UAAA,EAAY,2BAAA;EAAA,SACZ,WAAA,EAAa,WAAA;EAAA,SACb,UAAA,EAAY,UAAA;EAAA,SACZ,QAAA;EAAA,SACA,WAAA,EAAa,WAAA;AAAA,aACX,eAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { c as NamespaceDeclarationAst, i as GenericBlockDeclarationAst, k as printSyntax, l as TypesBlockAst, m as ArrayLiteralAst, o as ModelDeclarationAst, t as CompositeTypeDeclarationAst } from "./declarations-CPDuQm7x.mjs";
|
|
1
|
+
import { c as NamespaceDeclarationAst, i as GenericBlockDeclarationAst, k as printSyntax, l as TypesBlockAst, m as ArrayLiteralAst, o as ModelDeclarationAst, t as CompositeTypeDeclarationAst, w as IdentifierAst, x as StringLiteralExprAst } from "./declarations-CPDuQm7x.mjs";
|
|
2
2
|
import { UNSPECIFIED_PSL_NAMESPACE_ID, flatPslModels, makePslNamespace, makePslNamespaceEntries, namespacePslExtensionBlocks, validateExtensionBlock } from "@prisma-next/framework-components/psl-ast";
|
|
3
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
4
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
3
5
|
import { isAuthoringPslBlockDescriptor } from "@prisma-next/framework-components/authoring";
|
|
4
6
|
//#region src/attribute-helpers.ts
|
|
5
7
|
function getPositionalArgument(attribute, index = 0) {
|
|
@@ -11,63 +13,6 @@ function parseQuotedStringLiteral(value) {
|
|
|
11
13
|
return match[2] ?? "";
|
|
12
14
|
}
|
|
13
15
|
//#endregion
|
|
14
|
-
//#region src/extension-block.ts
|
|
15
|
-
function findBlockDescriptor(descriptors, keyword) {
|
|
16
|
-
if (descriptors === void 0) return void 0;
|
|
17
|
-
for (const value of Object.values(descriptors)) {
|
|
18
|
-
if (value === void 0) continue;
|
|
19
|
-
if (isAuthoringPslBlockDescriptor(value)) {
|
|
20
|
-
if (value.keyword === keyword) return value;
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
const nested = findBlockDescriptor(value, keyword);
|
|
24
|
-
if (nested !== void 0) return nested;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function validateExtensionBlockFromSymbol(input) {
|
|
28
|
-
const refCtx = buildRefResolutionContext(input.symbolTable, input.block);
|
|
29
|
-
return validateExtensionBlock(input.block.block, input.descriptor, input.sourceId, input.codecLookup, refCtx);
|
|
30
|
-
}
|
|
31
|
-
const ZERO_SPAN = {
|
|
32
|
-
start: {
|
|
33
|
-
offset: 0,
|
|
34
|
-
line: 1,
|
|
35
|
-
column: 1
|
|
36
|
-
},
|
|
37
|
-
end: {
|
|
38
|
-
offset: 0,
|
|
39
|
-
line: 1,
|
|
40
|
-
column: 1
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
function buildRefResolutionContext(symbolTable, block) {
|
|
44
|
-
const unspecifiedNamespace = makeNamespace(UNSPECIFIED_PSL_NAMESPACE_ID, Object.values(symbolTable.topLevel.models));
|
|
45
|
-
const allNamespaces = [unspecifiedNamespace, ...Object.values(symbolTable.topLevel.namespaces).map((namespace) => makeNamespace(namespace.name, Object.values(namespace.models)))];
|
|
46
|
-
const ownerNamespaceName = findOwnerNamespaceName(symbolTable, block);
|
|
47
|
-
return {
|
|
48
|
-
ownerNamespace: allNamespaces.find((namespace) => namespace.name === ownerNamespaceName) ?? unspecifiedNamespace,
|
|
49
|
-
allNamespaces
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function makeNamespace(name, models) {
|
|
53
|
-
return makePslNamespace({
|
|
54
|
-
kind: "namespace",
|
|
55
|
-
name,
|
|
56
|
-
entries: makePslNamespaceEntries(models.map((model) => ({
|
|
57
|
-
kind: "model",
|
|
58
|
-
name: model.name,
|
|
59
|
-
fields: [],
|
|
60
|
-
attributes: [],
|
|
61
|
-
span: ZERO_SPAN
|
|
62
|
-
})), [], []),
|
|
63
|
-
span: ZERO_SPAN
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
function findOwnerNamespaceName(symbolTable, block) {
|
|
67
|
-
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) if (Object.values(namespace.blocks).some((candidate) => candidate === block)) return namespace.name;
|
|
68
|
-
return UNSPECIFIED_PSL_NAMESPACE_ID;
|
|
69
|
-
}
|
|
70
|
-
//#endregion
|
|
71
16
|
//#region src/resolve.ts
|
|
72
17
|
function readResolvedAttribute(attribute, sourceFile) {
|
|
73
18
|
return {
|
|
@@ -143,6 +88,280 @@ function offsetToPslPosition(offset, sourceFile) {
|
|
|
143
88
|
};
|
|
144
89
|
}
|
|
145
90
|
//#endregion
|
|
91
|
+
//#region src/attribute-spec/combinators/diagnostic.ts
|
|
92
|
+
const ATTRIBUTE_DIAGNOSTIC_CODE = "PSL_INVALID_ATTRIBUTE_SYNTAX";
|
|
93
|
+
function leafDiagnostic(ctx, node, message) {
|
|
94
|
+
return {
|
|
95
|
+
code: ATTRIBUTE_DIAGNOSTIC_CODE,
|
|
96
|
+
message,
|
|
97
|
+
sourceId: ctx.sourceId,
|
|
98
|
+
span: nodePslSpan(node.syntax, ctx.sourceFile)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/attribute-spec/combinators/field-ref.ts
|
|
103
|
+
function fieldRef(scope) {
|
|
104
|
+
return {
|
|
105
|
+
kind: "fieldRef",
|
|
106
|
+
label: "field name",
|
|
107
|
+
scope,
|
|
108
|
+
parse: (arg, ctx) => {
|
|
109
|
+
if (!(arg instanceof IdentifierAst)) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
|
|
110
|
+
const name = arg.name();
|
|
111
|
+
if (name === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
|
|
112
|
+
const model = scope === "self" ? ctx.selfModel : ctx.resolveReferencedModel();
|
|
113
|
+
if (model !== void 0 && !Object.hasOwn(model.fields, name)) return notOk([leafDiagnostic(ctx, arg, `Field "${name}" does not exist on model "${model.name}"`)]);
|
|
114
|
+
return ok(name);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/attribute-spec/combinators/identifier.ts
|
|
120
|
+
function identifier(name) {
|
|
121
|
+
return {
|
|
122
|
+
kind: "identifier",
|
|
123
|
+
label: name,
|
|
124
|
+
parse: (arg, ctx) => {
|
|
125
|
+
if (arg instanceof IdentifierAst && arg.name() === name) return ok(name);
|
|
126
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${name}`)]);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/attribute-spec/combinators/list.ts
|
|
132
|
+
function list(of, opts) {
|
|
133
|
+
return {
|
|
134
|
+
kind: "list",
|
|
135
|
+
label: `${of.label}[]`,
|
|
136
|
+
parse: (arg, ctx) => {
|
|
137
|
+
if (!(arg instanceof ArrayLiteralAst)) return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
|
|
138
|
+
const diagnostics = [];
|
|
139
|
+
const parsed = [];
|
|
140
|
+
let count = 0;
|
|
141
|
+
for (const element of arg.elements()) {
|
|
142
|
+
count += 1;
|
|
143
|
+
const result = of.parse(element, ctx);
|
|
144
|
+
if (result.ok) parsed.push({
|
|
145
|
+
node: element,
|
|
146
|
+
value: result.value
|
|
147
|
+
});
|
|
148
|
+
else diagnostics.push(...result.failure);
|
|
149
|
+
}
|
|
150
|
+
if (opts?.nonEmpty === true && count === 0) diagnostics.push(leafDiagnostic(ctx, arg, "Expected a non-empty list"));
|
|
151
|
+
if (opts?.unique === true) {
|
|
152
|
+
const seen = /* @__PURE__ */ new Set();
|
|
153
|
+
for (const { node, value } of parsed) if (seen.has(value)) diagnostics.push(leafDiagnostic(ctx, node, "Duplicate list entry"));
|
|
154
|
+
else seen.add(value);
|
|
155
|
+
}
|
|
156
|
+
if (diagnostics.length > 0) return notOk(diagnostics);
|
|
157
|
+
return ok(parsed.map((entry) => entry.value));
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/attribute-spec/combinators/one-of.ts
|
|
163
|
+
function oneOf(...alts) {
|
|
164
|
+
const label = alts.map((alt) => alt.label).join(" | ");
|
|
165
|
+
return {
|
|
166
|
+
kind: "oneOf",
|
|
167
|
+
label,
|
|
168
|
+
parse: (arg, ctx) => {
|
|
169
|
+
for (const alt of alts) {
|
|
170
|
+
const result = alt.parse(arg, ctx);
|
|
171
|
+
if (result.ok) return ok(blindCast(result.value));
|
|
172
|
+
}
|
|
173
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/attribute-spec/combinators/str.ts
|
|
179
|
+
function str() {
|
|
180
|
+
return {
|
|
181
|
+
kind: "str",
|
|
182
|
+
label: "string",
|
|
183
|
+
parse: (arg, ctx) => {
|
|
184
|
+
if (arg instanceof StringLiteralExprAst) {
|
|
185
|
+
const value = arg.value();
|
|
186
|
+
if (value !== void 0) return ok(value);
|
|
187
|
+
}
|
|
188
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a string literal")]);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/attribute-spec/field-attribute.ts
|
|
194
|
+
function fieldAttribute(name, config) {
|
|
195
|
+
return {
|
|
196
|
+
level: "field",
|
|
197
|
+
name,
|
|
198
|
+
positional: config.positional ?? [],
|
|
199
|
+
named: config.named ?? {},
|
|
200
|
+
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/attribute-spec/interpret.ts
|
|
205
|
+
function interpretAttribute(attrNode, spec, ctx) {
|
|
206
|
+
const diagnostics = [];
|
|
207
|
+
const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sourceFile);
|
|
208
|
+
const output = {};
|
|
209
|
+
const seen = /* @__PURE__ */ new Set();
|
|
210
|
+
let positionalSlot = 0;
|
|
211
|
+
let reportedExcess = false;
|
|
212
|
+
for (const arg of attrNode.argList()?.args() ?? []) {
|
|
213
|
+
const name = arg.name()?.name();
|
|
214
|
+
let key;
|
|
215
|
+
let param;
|
|
216
|
+
if (name === void 0) {
|
|
217
|
+
const posParam = spec.positional[positionalSlot];
|
|
218
|
+
if (posParam === void 0) {
|
|
219
|
+
if (!reportedExcess) {
|
|
220
|
+
diagnostics.push(diagnostic(`Attribute "${spec.name}" received too many positional arguments`, ctx, attributeSpan));
|
|
221
|
+
reportedExcess = true;
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
positionalSlot += 1;
|
|
226
|
+
key = posParam.key;
|
|
227
|
+
param = posParam.type;
|
|
228
|
+
} else {
|
|
229
|
+
const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : void 0;
|
|
230
|
+
if (namedParam === void 0) {
|
|
231
|
+
diagnostics.push(diagnostic(`Attribute "${spec.name}" received unknown argument "${name}"`, ctx, nodePslSpan(arg.syntax, ctx.sourceFile)));
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
key = name;
|
|
235
|
+
param = namedParam;
|
|
236
|
+
}
|
|
237
|
+
if (seen.has(key)) {
|
|
238
|
+
diagnostics.push(diagnostic(`Attribute "${spec.name}" received duplicate argument "${key}"`, ctx, nodePslSpan(arg.syntax, ctx.sourceFile)));
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
seen.add(key);
|
|
242
|
+
const result = parseArgValue(arg, param, ctx, diagnostics);
|
|
243
|
+
if (result.ok) output[key] = result.value;
|
|
244
|
+
}
|
|
245
|
+
const finalized = /* @__PURE__ */ new Set();
|
|
246
|
+
const finalizeAbsentKey = (key, positionalParam, namedParam) => {
|
|
247
|
+
if (finalized.has(key) || seen.has(key)) return;
|
|
248
|
+
finalized.add(key);
|
|
249
|
+
const effective = namedParam ?? positionalParam;
|
|
250
|
+
if (effective === void 0) return;
|
|
251
|
+
if (isOptionalArgType(effective)) {
|
|
252
|
+
if (effective.hasDefault) output[key] = effective.defaultValue;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
diagnostics.push(diagnostic(`Attribute "${spec.name}" is missing required argument "${key}"`, ctx, attributeSpan));
|
|
256
|
+
};
|
|
257
|
+
for (const param of spec.positional) {
|
|
258
|
+
const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : void 0;
|
|
259
|
+
finalizeAbsentKey(param.key, param.type, namedParam);
|
|
260
|
+
}
|
|
261
|
+
for (const key of Object.keys(spec.named)) finalizeAbsentKey(key, void 0, spec.named[key]);
|
|
262
|
+
if (diagnostics.length > 0) return notOk(diagnostics);
|
|
263
|
+
const value = blindCast(output);
|
|
264
|
+
if (spec.refine !== void 0) {
|
|
265
|
+
const refineDiagnostics = spec.refine(value, ctx);
|
|
266
|
+
if (refineDiagnostics.length > 0) return notOk(refineDiagnostics);
|
|
267
|
+
}
|
|
268
|
+
return ok(value);
|
|
269
|
+
}
|
|
270
|
+
function parseArgValue(arg, argType, ctx, diagnostics) {
|
|
271
|
+
const value = arg.value();
|
|
272
|
+
if (value === void 0) {
|
|
273
|
+
const missing = diagnostic("Attribute argument is missing a value", ctx, nodePslSpan(arg.syntax, ctx.sourceFile));
|
|
274
|
+
diagnostics.push(missing);
|
|
275
|
+
return notOk([missing]);
|
|
276
|
+
}
|
|
277
|
+
const result = argType.parse(value, ctx);
|
|
278
|
+
if (!result.ok) for (const failure of result.failure) diagnostics.push(failure);
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
function isOptionalArgType(param) {
|
|
282
|
+
return "optional" in param && param.optional === true;
|
|
283
|
+
}
|
|
284
|
+
function diagnostic(message, ctx, span) {
|
|
285
|
+
return {
|
|
286
|
+
code: ATTRIBUTE_DIAGNOSTIC_CODE,
|
|
287
|
+
message,
|
|
288
|
+
sourceId: ctx.sourceId,
|
|
289
|
+
span
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/attribute-spec/optional.ts
|
|
294
|
+
function optional(type, ...rest) {
|
|
295
|
+
if (rest.length === 0) return {
|
|
296
|
+
...type,
|
|
297
|
+
optional: true,
|
|
298
|
+
hasDefault: false
|
|
299
|
+
};
|
|
300
|
+
return {
|
|
301
|
+
...type,
|
|
302
|
+
optional: true,
|
|
303
|
+
hasDefault: true,
|
|
304
|
+
defaultValue: rest[0]
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/extension-block.ts
|
|
309
|
+
function findBlockDescriptor(descriptors, keyword) {
|
|
310
|
+
if (descriptors === void 0) return void 0;
|
|
311
|
+
for (const value of Object.values(descriptors)) {
|
|
312
|
+
if (value === void 0) continue;
|
|
313
|
+
if (isAuthoringPslBlockDescriptor(value)) {
|
|
314
|
+
if (value.keyword === keyword) return value;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
const nested = findBlockDescriptor(value, keyword);
|
|
318
|
+
if (nested !== void 0) return nested;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function validateExtensionBlockFromSymbol(input) {
|
|
322
|
+
const refCtx = buildRefResolutionContext(input.symbolTable, input.block);
|
|
323
|
+
return validateExtensionBlock(input.block.block, input.descriptor, input.sourceId, input.codecLookup, refCtx);
|
|
324
|
+
}
|
|
325
|
+
const ZERO_SPAN = {
|
|
326
|
+
start: {
|
|
327
|
+
offset: 0,
|
|
328
|
+
line: 1,
|
|
329
|
+
column: 1
|
|
330
|
+
},
|
|
331
|
+
end: {
|
|
332
|
+
offset: 0,
|
|
333
|
+
line: 1,
|
|
334
|
+
column: 1
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
function buildRefResolutionContext(symbolTable, block) {
|
|
338
|
+
const unspecifiedNamespace = makeNamespace(UNSPECIFIED_PSL_NAMESPACE_ID, Object.values(symbolTable.topLevel.models));
|
|
339
|
+
const allNamespaces = [unspecifiedNamespace, ...Object.values(symbolTable.topLevel.namespaces).map((namespace) => makeNamespace(namespace.name, Object.values(namespace.models)))];
|
|
340
|
+
const ownerNamespaceName = findOwnerNamespaceName(symbolTable, block);
|
|
341
|
+
return {
|
|
342
|
+
ownerNamespace: allNamespaces.find((namespace) => namespace.name === ownerNamespaceName) ?? unspecifiedNamespace,
|
|
343
|
+
allNamespaces
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function makeNamespace(name, models) {
|
|
347
|
+
return makePslNamespace({
|
|
348
|
+
kind: "namespace",
|
|
349
|
+
name,
|
|
350
|
+
entries: makePslNamespaceEntries(models.map((model) => ({
|
|
351
|
+
kind: "model",
|
|
352
|
+
name: model.name,
|
|
353
|
+
fields: [],
|
|
354
|
+
attributes: [],
|
|
355
|
+
span: ZERO_SPAN
|
|
356
|
+
})), [], []),
|
|
357
|
+
span: ZERO_SPAN
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function findOwnerNamespaceName(symbolTable, block) {
|
|
361
|
+
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) if (Object.values(namespace.blocks).some((candidate) => candidate === block)) return namespace.name;
|
|
362
|
+
return UNSPECIFIED_PSL_NAMESPACE_ID;
|
|
363
|
+
}
|
|
364
|
+
//#endregion
|
|
146
365
|
//#region src/block-reconstruction.ts
|
|
147
366
|
/**
|
|
148
367
|
* Descriptor-free and unknown parameters become `value` stubs so validation can
|
|
@@ -481,6 +700,6 @@ function nodeRange(node, sourceFile) {
|
|
|
481
700
|
};
|
|
482
701
|
}
|
|
483
702
|
//#endregion
|
|
484
|
-
export { buildSymbolTable, findBlockDescriptor, flatPslModels, getPositionalArgument, keywordPslSpan, namespacePslExtensionBlocks, nodePslSpan, parseQuotedStringLiteral, rangeToPslSpan, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, validateExtensionBlockFromSymbol };
|
|
703
|
+
export { buildSymbolTable, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, getPositionalArgument, identifier, interpretAttribute, keywordPslSpan, list, namespacePslExtensionBlocks, nodePslSpan, oneOf, optional, parseQuotedStringLiteral, rangeToPslSpan, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, str, validateExtensionBlockFromSymbol };
|
|
485
704
|
|
|
486
705
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/attribute-helpers.ts","../src/extension-block.ts","../src/resolve.ts","../src/block-reconstruction.ts","../src/symbol-table.ts"],"sourcesContent":["import type { PslAttribute } from '@prisma-next/framework-components/psl-ast';\n\nexport function getPositionalArgument(attribute: PslAttribute, index = 0): string | undefined {\n const entries = attribute.args.filter((arg) => arg.kind === 'positional');\n return entries[index]?.value;\n}\n\nexport function parseQuotedStringLiteral(value: string): string | undefined {\n const trimmed = value.trim();\n const match = trimmed.match(/^(['\"])(.*)\\1$/);\n if (!match) return undefined;\n return match[2] ?? '';\n}\n","import {\n type AuthoringPslBlockDescriptor,\n type AuthoringPslBlockDescriptorNamespace,\n isAuthoringPslBlockDescriptor,\n} from '@prisma-next/framework-components/authoring';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport {\n makePslNamespace,\n makePslNamespaceEntries,\n type PslDiagnostic,\n type PslModel,\n type PslSpan,\n UNSPECIFIED_PSL_NAMESPACE_ID,\n validateExtensionBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { SourceFile } from './source-file';\nimport type { BlockSymbol, ModelSymbol, SymbolTable } from './symbol-table';\n\nexport function findBlockDescriptor(\n descriptors: AuthoringPslBlockDescriptorNamespace | undefined,\n keyword: string,\n): AuthoringPslBlockDescriptor | undefined {\n if (descriptors === undefined) return undefined;\n for (const value of Object.values(descriptors)) {\n if (value === undefined) continue;\n if (isAuthoringPslBlockDescriptor(value)) {\n if (value.keyword === keyword) return value;\n continue;\n }\n const nested = findBlockDescriptor(value, keyword);\n if (nested !== undefined) return nested;\n }\n return undefined;\n}\n\nexport function validateExtensionBlockFromSymbol(input: {\n readonly block: BlockSymbol;\n readonly descriptor: AuthoringPslBlockDescriptor;\n readonly symbolTable: SymbolTable;\n readonly sourceFile: SourceFile;\n readonly sourceId: string;\n readonly codecLookup: CodecLookup;\n}): readonly PslDiagnostic[] {\n const refCtx = buildRefResolutionContext(input.symbolTable, input.block);\n return validateExtensionBlock(\n input.block.block,\n input.descriptor,\n input.sourceId,\n input.codecLookup,\n refCtx,\n );\n}\n\nconst ZERO_SPAN: PslSpan = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: 0, line: 1, column: 1 },\n};\n\nfunction buildRefResolutionContext(\n symbolTable: SymbolTable,\n block: BlockSymbol,\n): {\n ownerNamespace: ReturnType<typeof makePslNamespace>;\n allNamespaces: readonly ReturnType<typeof makePslNamespace>[];\n} {\n const unspecifiedNamespace = makeNamespace(\n UNSPECIFIED_PSL_NAMESPACE_ID,\n Object.values(symbolTable.topLevel.models),\n );\n const namedNamespaces = Object.values(symbolTable.topLevel.namespaces).map((namespace) =>\n makeNamespace(namespace.name, Object.values(namespace.models)),\n );\n const allNamespaces = [unspecifiedNamespace, ...namedNamespaces];\n const ownerNamespaceName = findOwnerNamespaceName(symbolTable, block);\n const ownerNamespace =\n allNamespaces.find((namespace) => namespace.name === ownerNamespaceName) ??\n unspecifiedNamespace;\n return { ownerNamespace, allNamespaces };\n}\n\nfunction makeNamespace(\n name: string,\n models: readonly ModelSymbol[],\n): ReturnType<typeof makePslNamespace> {\n const modelStubs: PslModel[] = models.map((model) => ({\n kind: 'model',\n name: model.name,\n fields: [],\n attributes: [],\n span: ZERO_SPAN,\n }));\n return makePslNamespace({\n kind: 'namespace',\n name,\n entries: makePslNamespaceEntries(modelStubs, [], []),\n span: ZERO_SPAN,\n });\n}\n\nfunction findOwnerNamespaceName(symbolTable: SymbolTable, block: BlockSymbol): string {\n for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {\n if (Object.values(namespace.blocks).some((candidate) => candidate === block)) {\n return namespace.name;\n }\n }\n return UNSPECIFIED_PSL_NAMESPACE_ID;\n}\n","import type { PslSpan } from '@prisma-next/framework-components/psl-ast';\nimport type { Position, Range, SourceFile } from './source-file';\nimport type {\n AttributeArgListAst,\n FieldAttributeAst,\n ModelAttributeAst,\n} from './syntax/ast/attributes';\nimport type { ExpressionAst } from './syntax/ast/expressions';\nimport type { QualifiedNameAst } from './syntax/ast/qualified-name';\nimport type { TypeAnnotationAst } from './syntax/ast/type-annotation';\nimport { printSyntax } from './syntax/ast-helpers';\nimport type { SyntaxNode } from './syntax/red';\n\nexport interface ResolvedAttributeArg {\n readonly kind: 'positional' | 'named';\n readonly name?: string;\n readonly value: string;\n readonly expression?: ExpressionAst;\n readonly span: PslSpan;\n}\n\nexport interface ResolvedAttribute {\n readonly name: string;\n readonly args: readonly ResolvedAttributeArg[];\n readonly span: PslSpan;\n}\n\nexport interface ResolvedTypeConstructorCall {\n readonly path: readonly string[];\n readonly args: readonly ResolvedAttributeArg[];\n readonly span: PslSpan;\n}\n\nexport function readResolvedAttribute(\n attribute: FieldAttributeAst | ModelAttributeAst,\n sourceFile: SourceFile,\n): ResolvedAttribute {\n return {\n name: attributeName(attribute.name()),\n args: readResolvedArgList(attribute.argList(), sourceFile),\n span: nodePslSpan(attribute.syntax, sourceFile),\n };\n}\n\nexport function readResolvedAttributes(\n attributes: Iterable<FieldAttributeAst | ModelAttributeAst>,\n sourceFile: SourceFile,\n): readonly ResolvedAttribute[] {\n return Array.from(attributes, (attribute) => readResolvedAttribute(attribute, sourceFile));\n}\n\nexport function readResolvedConstructorCall(\n annotation: TypeAnnotationAst | undefined,\n sourceFile: SourceFile,\n): ResolvedTypeConstructorCall | undefined {\n const argList = annotation?.argList();\n if (annotation === undefined || argList === undefined) return undefined;\n return {\n path: annotation.name()?.path() ?? [],\n args: readResolvedArgList(argList, sourceFile),\n span: nodePslSpan(annotation.syntax, sourceFile),\n };\n}\n\nfunction readResolvedArgList(\n argList: AttributeArgListAst | undefined,\n sourceFile: SourceFile,\n): readonly ResolvedAttributeArg[] {\n if (argList === undefined) return [];\n const args: ResolvedAttributeArg[] = [];\n for (const arg of argList.args()) {\n const name = arg.name()?.name();\n const expression = arg.value();\n args.push({\n kind: name !== undefined ? 'named' : 'positional',\n ...(name !== undefined ? { name } : {}),\n value: renderExpression(expression),\n ...(expression !== undefined ? { expression } : {}),\n span: nodePslSpan(arg.syntax, sourceFile),\n });\n }\n return args;\n}\n\nfunction attributeName(name: QualifiedNameAst | undefined): string {\n return name?.path().join('.') ?? '';\n}\n\nfunction renderExpression(expression: ExpressionAst | undefined): string {\n if (expression === undefined) return '';\n return printSyntax(expression.syntax).trim();\n}\n\nexport function nodePslSpan(node: SyntaxNode, sourceFile: SourceFile): PslSpan {\n const start = node.offset;\n const end = start + node.green.textLength;\n return {\n start: offsetToPslPosition(start, sourceFile),\n end: offsetToPslPosition(end, sourceFile),\n };\n}\n\n/** Unsupported-top-level-block diagnostics are anchored to the keyword token. */\nexport function keywordPslSpan(node: SyntaxNode, keyword: string, sourceFile: SourceFile): PslSpan {\n const start = node.offset;\n const end = start + keyword.length;\n return {\n start: offsetToPslPosition(start, sourceFile),\n end: offsetToPslPosition(end, sourceFile),\n };\n}\n\nexport function rangeToPslSpan(range: Range, sourceFile: SourceFile): PslSpan {\n return {\n start: offsetToPslPosition(sourceFile.offsetAt(range.start), sourceFile),\n end: offsetToPslPosition(sourceFile.offsetAt(range.end), sourceFile),\n };\n}\n\nfunction offsetToPslPosition(offset: number, sourceFile: SourceFile): PslSpan['start'] {\n const position: Position = sourceFile.positionAt(offset);\n return { offset, line: position.line + 1, column: position.character + 1 };\n}\n","import type { AuthoringPslBlockDescriptor } from '@prisma-next/framework-components/authoring';\nimport type {\n PslBlockParam,\n PslExtensionBlock,\n PslExtensionBlockAttribute,\n PslExtensionBlockParamValue,\n PslSpan,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { ParseDiagnostic } from './parse';\nimport { nodePslSpan } from './resolve';\nimport type { SourceFile } from './source-file';\nimport type { GenericBlockDeclarationAst, KeyValuePairAst } from './syntax/ast/declarations';\nimport { ArrayLiteralAst, type ExpressionAst } from './syntax/ast/expressions';\nimport { printSyntax } from './syntax/ast-helpers';\n\n/**\n * Descriptor-free and unknown parameters become `value` stubs so validation can\n * report them via key-set comparison. Duplicate member names are first-wins.\n */\nexport function reconstructExtensionBlock(\n node: GenericBlockDeclarationAst,\n descriptor: AuthoringPslBlockDescriptor | undefined,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): PslExtensionBlock {\n const keyword = node.keyword()?.text ?? '';\n const blockName = node.name()?.name() ?? '';\n\n const blockAttributes: PslExtensionBlockAttribute[] = [];\n for (const attribute of node.attributes()) {\n const name = attribute.name()?.path().join('.') ?? '';\n const args = Array.from(attribute.argList()?.args() ?? [], (arg) => {\n const value = arg.value();\n return {\n kind: 'positional' as const,\n value: value === undefined ? '' : printSyntax(value.syntax).trim(),\n span: nodePslSpan(arg.syntax, sourceFile),\n };\n });\n blockAttributes.push({\n name,\n args,\n span: nodePslSpan(attribute.syntax, sourceFile),\n });\n }\n\n const parameters: Record<string, PslExtensionBlockParamValue> = {};\n for (const entry of node.entries()) {\n const key = entry.key()?.name();\n if (key === undefined) continue;\n const span = nodePslSpan(entry.syntax, sourceFile);\n if (Object.hasOwn(parameters, key)) {\n diagnostics.push({\n code: 'PSL_EXTENSION_DUPLICATE_PARAMETER',\n message: `Duplicate parameter \"${key}\" in \"${keyword}\" block \"${blockName}\"; first occurrence wins`,\n range: {\n start: sourceFile.positionAt(entry.syntax.offset),\n end: sourceFile.positionAt(entry.syntax.offset + entry.syntax.green.textLength),\n },\n });\n continue;\n }\n parameters[key] = reconstructParamValue(\n entry,\n descriptor?.parameters[key],\n span,\n sourceFile,\n diagnostics,\n );\n }\n\n return {\n kind: descriptor?.discriminator ?? keyword,\n name: blockName,\n parameters,\n blockAttributes,\n span: nodePslSpan(node.syntax, sourceFile),\n };\n}\n\nfunction reconstructParamValue(\n entry: KeyValuePairAst,\n param: PslBlockParam | undefined,\n span: PslSpan,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): PslExtensionBlockParamValue {\n const value = entry.value();\n if (value === undefined) {\n return { kind: 'bare', span };\n }\n return reconstructFromExpression(value, param, span, sourceFile, diagnostics);\n}\n\nfunction reconstructFromExpression(\n value: ExpressionAst,\n param: PslBlockParam | undefined,\n span: PslSpan,\n sourceFile: SourceFile,\n diagnostics?: ParseDiagnostic[],\n): PslExtensionBlockParamValue {\n const raw = printSyntax(value.syntax).trim();\n if (param?.kind === 'list') {\n const array = ArrayLiteralAst.cast(value.syntax);\n if (!array) {\n diagnostics?.push({\n code: 'PSL_EXTENSION_INVALID_VALUE',\n message: `List parameter expects an array literal, got ${raw}`,\n range: {\n start: sourceFile.positionAt(value.syntax.offset),\n end: sourceFile.positionAt(value.syntax.offset + value.syntax.green.textLength),\n },\n });\n return { kind: 'value', raw, span };\n }\n\n const items: PslExtensionBlockParamValue[] = [];\n for (const element of array.elements()) {\n items.push(\n reconstructFromExpression(\n element,\n param.of,\n nodePslSpan(element.syntax, sourceFile),\n sourceFile,\n diagnostics,\n ),\n );\n }\n return { kind: 'list', items, span };\n }\n switch (param?.kind) {\n case 'ref':\n return { kind: 'ref', identifier: raw, span };\n case 'option':\n return { kind: 'option', token: raw, span };\n default:\n return { kind: 'value', raw, span };\n }\n}\n","import type { AuthoringPslBlockDescriptorNamespace } from '@prisma-next/framework-components/authoring';\nimport type { PslExtensionBlock, PslSpan } from '@prisma-next/framework-components/psl-ast';\nimport { reconstructExtensionBlock } from './block-reconstruction';\nimport { findBlockDescriptor } from './extension-block';\nimport type { ParseDiagnostic } from './parse';\nimport {\n nodePslSpan,\n type ResolvedAttribute,\n type ResolvedTypeConstructorCall,\n readResolvedAttributes,\n readResolvedConstructorCall,\n} from './resolve';\nimport type { Range, SourceFile } from './source-file';\nimport {\n CompositeTypeDeclarationAst,\n type DocumentAst,\n type FieldDeclarationAst,\n GenericBlockDeclarationAst,\n ModelDeclarationAst,\n type NamedTypeDeclarationAst,\n NamespaceDeclarationAst,\n TypesBlockAst,\n} from './syntax/ast/declarations';\nimport type { IdentifierAst } from './syntax/ast/identifier';\nimport type { SyntaxNode } from './syntax/red';\n\nexport type {\n ResolvedAttribute,\n ResolvedAttributeArg,\n ResolvedTypeConstructorCall,\n} from './resolve';\n\nexport interface SymbolTable {\n readonly topLevel: TopLevelScope;\n}\n\nexport interface TopLevelScope {\n readonly namespaces: Record<string, NamespaceSymbol>;\n readonly scalars: Record<string, ScalarSymbol>;\n readonly typeAliases: Record<string, TypeAliasSymbol>;\n readonly blocks: Record<string, BlockSymbol>;\n readonly models: Record<string, ModelSymbol>;\n readonly compositeTypes: Record<string, CompositeTypeSymbol>;\n}\n\nexport interface NamespaceSymbol {\n readonly kind: 'namespace';\n readonly name: string;\n readonly node: NamespaceDeclarationAst;\n readonly span: PslSpan;\n readonly models: Record<string, ModelSymbol>;\n readonly compositeTypes: Record<string, CompositeTypeSymbol>;\n readonly blocks: Record<string, BlockSymbol>;\n}\n\nexport interface ModelSymbol {\n readonly kind: 'model';\n readonly name: string;\n readonly node: ModelDeclarationAst;\n readonly span: PslSpan;\n readonly fields: Record<string, FieldSymbol>;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface CompositeTypeSymbol {\n readonly kind: 'compositeType';\n readonly name: string;\n readonly node: CompositeTypeDeclarationAst;\n readonly span: PslSpan;\n readonly fields: Record<string, FieldSymbol>;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface BlockSymbol {\n readonly kind: 'block';\n readonly name: string;\n readonly keyword: string;\n readonly node: GenericBlockDeclarationAst;\n readonly span: PslSpan;\n /** Resolved once so consumers do not independently classify block parameters. */\n readonly block: PslExtensionBlock;\n}\n\nexport interface ResolvedNamedTypeBinding {\n readonly baseType?: string;\n readonly typeConstructor?: ResolvedTypeConstructorCall;\n readonly isConstructor: boolean;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface ScalarSymbol extends ResolvedNamedTypeBinding {\n readonly kind: 'scalar';\n readonly name: string;\n readonly node: NamedTypeDeclarationAst;\n readonly span: PslSpan;\n}\n\nexport interface TypeAliasSymbol extends ResolvedNamedTypeBinding {\n readonly kind: 'typeAlias';\n readonly name: string;\n readonly node: NamedTypeDeclarationAst;\n readonly span: PslSpan;\n}\n\nexport interface FieldSymbol {\n readonly kind: 'field';\n readonly name: string;\n readonly node: FieldDeclarationAst;\n readonly span: PslSpan;\n readonly typeName: string;\n readonly typeNamespaceId?: string;\n readonly typeContractSpaceId?: string;\n readonly optional: boolean;\n readonly list: boolean;\n readonly typeConstructor?: ResolvedTypeConstructorCall;\n readonly attributes: readonly ResolvedAttribute[];\n /** Prevents cascading unsupported-type diagnostics after invalid qualification. */\n readonly malformedType?: boolean;\n}\n\nexport interface BuildSymbolTableOptions {\n readonly document: DocumentAst;\n readonly sourceFile: SourceFile;\n readonly scalarTypes: readonly string[];\n readonly pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace;\n}\n\nexport interface SymbolTableResult {\n readonly table: SymbolTable;\n readonly diagnostics: readonly ParseDiagnostic[];\n}\n\n/**\n * Owns duplicate-declaration detection for all PSL scopes; downstream consumers\n * should consume first-wins symbols rather than re-emitting duplicate diagnostics.\n */\nexport function buildSymbolTable(options: BuildSymbolTableOptions): SymbolTableResult {\n const { document, sourceFile, scalarTypes, pslBlockDescriptors } = options;\n const diagnostics: ParseDiagnostic[] = [];\n const scalarSet = new Set(scalarTypes);\n\n const namespaces: Record<string, NamespaceSymbol> = {};\n const scalars: Record<string, ScalarSymbol> = {};\n const typeAliases: Record<string, TypeAliasSymbol> = {};\n const blocks: Record<string, BlockSymbol> = {};\n const models: Record<string, ModelSymbol> = {};\n const compositeTypes: Record<string, CompositeTypeSymbol> = {};\n const topLevelNames = new Set<string>();\n\n const claim = (taken: Set<string>, name: IdentifierAst | undefined): string | undefined => {\n const text = name?.name();\n if (text === undefined) return undefined;\n if (taken.has(text)) {\n const range = nameRange(name, sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${text}\"`,\n range,\n });\n }\n return undefined;\n }\n taken.add(text);\n return text;\n };\n\n for (const declaration of document.declarations()) {\n if (declaration instanceof ModelDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) models[name] = buildModel(name, declaration, sourceFile, diagnostics);\n } else if (declaration instanceof CompositeTypeDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n compositeTypes[name] = buildCompositeType(name, declaration, sourceFile, diagnostics);\n }\n } else if (declaration instanceof GenericBlockDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n blocks[name] = buildBlock(name, declaration, sourceFile, pslBlockDescriptors, diagnostics);\n }\n } else if (declaration instanceof NamespaceDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n namespaces[name] = buildNamespace(\n name,\n declaration,\n diagnostics,\n sourceFile,\n pslBlockDescriptors,\n );\n }\n } else if (declaration instanceof TypesBlockAst) {\n for (const binding of declaration.declarations()) {\n const name = claim(topLevelNames, binding.name());\n if (name === undefined) continue;\n const resolved = resolveNamedTypeBinding(binding, sourceFile);\n const span = nodePslSpan(binding.syntax, sourceFile);\n if (isScalarBinding(binding, scalarSet)) {\n scalars[name] = { kind: 'scalar', name, node: binding, span, ...resolved };\n } else {\n typeAliases[name] = { kind: 'typeAlias', name, node: binding, span, ...resolved };\n }\n }\n }\n }\n\n const table: SymbolTable = {\n topLevel: { namespaces, scalars, typeAliases, blocks, models, compositeTypes },\n };\n return { table, diagnostics };\n}\n\nfunction buildModel(\n name: string,\n node: ModelDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): ModelSymbol {\n return {\n kind: 'model',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n fields: buildFields(name, node.fields(), sourceFile, diagnostics),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction buildCompositeType(\n name: string,\n node: CompositeTypeDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): CompositeTypeSymbol {\n return {\n kind: 'compositeType',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n fields: buildFields(name, node.fields(), sourceFile, diagnostics),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction buildBlock(\n name: string,\n node: GenericBlockDeclarationAst,\n sourceFile: SourceFile,\n pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace,\n diagnostics: ParseDiagnostic[],\n): BlockSymbol {\n const keyword = node.keyword()?.text ?? '';\n const descriptor = findBlockDescriptor(pslBlockDescriptors, keyword);\n return {\n kind: 'block',\n name,\n keyword,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n block: reconstructExtensionBlock(node, descriptor, sourceFile, diagnostics),\n };\n}\n\nfunction buildNamespace(\n name: string,\n node: NamespaceDeclarationAst,\n diagnostics: ParseDiagnostic[],\n sourceFile: SourceFile,\n pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace,\n): NamespaceSymbol {\n const models: Record<string, ModelSymbol> = {};\n const compositeTypes: Record<string, CompositeTypeSymbol> = {};\n const blocks: Record<string, BlockSymbol> = {};\n const taken = new Set<string>();\n\n for (const member of node.declarations()) {\n const memberName = member.name()?.name();\n if (memberName === undefined) continue;\n if (taken.has(memberName)) {\n const range = nameRange(member.name(), sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${memberName}\"`,\n range,\n });\n }\n continue;\n }\n taken.add(memberName);\n if (member instanceof ModelDeclarationAst) {\n models[memberName] = buildModel(memberName, member, sourceFile, diagnostics);\n } else if (member instanceof CompositeTypeDeclarationAst) {\n compositeTypes[memberName] = buildCompositeType(memberName, member, sourceFile, diagnostics);\n } else if (member instanceof GenericBlockDeclarationAst) {\n blocks[memberName] = buildBlock(\n memberName,\n member,\n sourceFile,\n pslBlockDescriptors,\n diagnostics,\n );\n }\n }\n\n return {\n kind: 'namespace',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n models,\n compositeTypes,\n blocks,\n };\n}\n\nfunction buildFields(\n ownerName: string,\n fields: Iterable<FieldDeclarationAst>,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): Record<string, FieldSymbol> {\n const result: Record<string, FieldSymbol> = {};\n for (const field of fields) {\n const nameNode = field.name();\n const name = nameNode?.name();\n if (name === undefined) continue;\n if (Object.hasOwn(result, name)) {\n const range = nameRange(nameNode, sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${name}\"`,\n range,\n });\n }\n continue;\n }\n result[name] = buildField(ownerName, name, field, sourceFile, diagnostics);\n }\n return result;\n}\n\nfunction buildField(\n ownerName: string,\n name: string,\n node: FieldDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): FieldSymbol {\n const attributes = readResolvedAttributes(node.attributes(), sourceFile);\n const span = nodePslSpan(node.syntax, sourceFile);\n const annotation = node.typeAnnotation();\n const typeName = annotation?.name();\n\n if (typeName?.isOverQualified()) {\n const path = typeName.path();\n diagnostics.push({\n code: 'PSL_INVALID_QUALIFIED_TYPE',\n message: `Field \"${ownerName}.${name}\" has an invalid qualified type \"${path.join('.')}\"; use at most one namespace qualifier (e.g. \"ns.TypeName\")`,\n range: nodeRange(typeName.syntax, sourceFile),\n });\n return {\n kind: 'field',\n name,\n node,\n span,\n typeName: path[path.length - 1] ?? '',\n optional: false,\n list: false,\n malformedType: true,\n attributes,\n };\n }\n\n const typeConstructor = annotation?.isConstructor()\n ? readResolvedConstructorCall(annotation, sourceFile)\n : undefined;\n const typeNamespaceId = typeName?.namespace()?.name();\n const typeContractSpaceId = typeName?.space()?.name();\n\n return {\n kind: 'field',\n name,\n node,\n span,\n typeName: typeName?.identifier()?.name() ?? '',\n ...(typeNamespaceId !== undefined ? { typeNamespaceId } : {}),\n ...(typeContractSpaceId !== undefined ? { typeContractSpaceId } : {}),\n optional: annotation?.isOptional() ?? false,\n list: annotation?.isList() ?? false,\n ...(typeConstructor !== undefined ? { typeConstructor } : {}),\n attributes,\n };\n}\n\nfunction resolveNamedTypeBinding(\n node: NamedTypeDeclarationAst,\n sourceFile: SourceFile,\n): {\n baseType?: string;\n typeConstructor?: ResolvedTypeConstructorCall;\n isConstructor: boolean;\n attributes: readonly ResolvedAttribute[];\n} {\n const annotation = node.typeAnnotation();\n const isConstructor = annotation?.isConstructor() ?? false;\n const baseType = annotation?.name()?.identifier()?.name();\n const typeConstructor = readResolvedConstructorCall(annotation, sourceFile);\n return {\n isConstructor,\n ...(!isConstructor && baseType !== undefined ? { baseType } : {}),\n ...(typeConstructor !== undefined ? { typeConstructor } : {}),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction isScalarBinding(node: NamedTypeDeclarationAst, scalarTypes: Set<string>): boolean {\n const annotation = node.typeAnnotation();\n if (annotation === undefined || annotation.isConstructor()) return false;\n const base = annotation.name()?.identifier()?.name();\n return base !== undefined && scalarTypes.has(base);\n}\n\nfunction nameRange(name: IdentifierAst | undefined, sourceFile: SourceFile): Range | undefined {\n if (name === undefined) return undefined;\n for (const token of name.syntax.tokens()) {\n if (token.kind === 'Ident') {\n return {\n start: sourceFile.positionAt(token.offset),\n end: sourceFile.positionAt(token.offset + token.text.length),\n };\n }\n }\n return undefined;\n}\n\nfunction nodeRange(node: SyntaxNode, sourceFile: SourceFile): Range {\n const start = node.offset;\n const end = start + node.green.textLength;\n return {\n start: sourceFile.positionAt(start),\n end: sourceFile.positionAt(end),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/attribute-helpers.ts","../src/resolve.ts","../src/attribute-spec/combinators/diagnostic.ts","../src/attribute-spec/combinators/field-ref.ts","../src/attribute-spec/combinators/identifier.ts","../src/attribute-spec/combinators/list.ts","../src/attribute-spec/combinators/one-of.ts","../src/attribute-spec/combinators/str.ts","../src/attribute-spec/field-attribute.ts","../src/attribute-spec/interpret.ts","../src/attribute-spec/optional.ts","../src/extension-block.ts","../src/block-reconstruction.ts","../src/symbol-table.ts"],"sourcesContent":["import type { PslAttribute } from '@prisma-next/framework-components/psl-ast';\n\nexport function getPositionalArgument(attribute: PslAttribute, index = 0): string | undefined {\n const entries = attribute.args.filter((arg) => arg.kind === 'positional');\n return entries[index]?.value;\n}\n\nexport function parseQuotedStringLiteral(value: string): string | undefined {\n const trimmed = value.trim();\n const match = trimmed.match(/^(['\"])(.*)\\1$/);\n if (!match) return undefined;\n return match[2] ?? '';\n}\n","import type { PslSpan } from '@prisma-next/framework-components/psl-ast';\nimport type { Position, Range, SourceFile } from './source-file';\nimport type {\n AttributeArgListAst,\n FieldAttributeAst,\n ModelAttributeAst,\n} from './syntax/ast/attributes';\nimport type { ExpressionAst } from './syntax/ast/expressions';\nimport type { QualifiedNameAst } from './syntax/ast/qualified-name';\nimport type { TypeAnnotationAst } from './syntax/ast/type-annotation';\nimport { printSyntax } from './syntax/ast-helpers';\nimport type { SyntaxNode } from './syntax/red';\n\nexport interface ResolvedAttributeArg {\n readonly kind: 'positional' | 'named';\n readonly name?: string;\n readonly value: string;\n readonly expression?: ExpressionAst;\n readonly span: PslSpan;\n}\n\nexport interface ResolvedAttribute {\n readonly name: string;\n readonly args: readonly ResolvedAttributeArg[];\n readonly span: PslSpan;\n}\n\nexport interface ResolvedTypeConstructorCall {\n readonly path: readonly string[];\n readonly args: readonly ResolvedAttributeArg[];\n readonly span: PslSpan;\n}\n\nexport function readResolvedAttribute(\n attribute: FieldAttributeAst | ModelAttributeAst,\n sourceFile: SourceFile,\n): ResolvedAttribute {\n return {\n name: attributeName(attribute.name()),\n args: readResolvedArgList(attribute.argList(), sourceFile),\n span: nodePslSpan(attribute.syntax, sourceFile),\n };\n}\n\nexport function readResolvedAttributes(\n attributes: Iterable<FieldAttributeAst | ModelAttributeAst>,\n sourceFile: SourceFile,\n): readonly ResolvedAttribute[] {\n return Array.from(attributes, (attribute) => readResolvedAttribute(attribute, sourceFile));\n}\n\nexport function readResolvedConstructorCall(\n annotation: TypeAnnotationAst | undefined,\n sourceFile: SourceFile,\n): ResolvedTypeConstructorCall | undefined {\n const argList = annotation?.argList();\n if (annotation === undefined || argList === undefined) return undefined;\n return {\n path: annotation.name()?.path() ?? [],\n args: readResolvedArgList(argList, sourceFile),\n span: nodePslSpan(annotation.syntax, sourceFile),\n };\n}\n\nfunction readResolvedArgList(\n argList: AttributeArgListAst | undefined,\n sourceFile: SourceFile,\n): readonly ResolvedAttributeArg[] {\n if (argList === undefined) return [];\n const args: ResolvedAttributeArg[] = [];\n for (const arg of argList.args()) {\n const name = arg.name()?.name();\n const expression = arg.value();\n args.push({\n kind: name !== undefined ? 'named' : 'positional',\n ...(name !== undefined ? { name } : {}),\n value: renderExpression(expression),\n ...(expression !== undefined ? { expression } : {}),\n span: nodePslSpan(arg.syntax, sourceFile),\n });\n }\n return args;\n}\n\nfunction attributeName(name: QualifiedNameAst | undefined): string {\n return name?.path().join('.') ?? '';\n}\n\nfunction renderExpression(expression: ExpressionAst | undefined): string {\n if (expression === undefined) return '';\n return printSyntax(expression.syntax).trim();\n}\n\nexport function nodePslSpan(node: SyntaxNode, sourceFile: SourceFile): PslSpan {\n const start = node.offset;\n const end = start + node.green.textLength;\n return {\n start: offsetToPslPosition(start, sourceFile),\n end: offsetToPslPosition(end, sourceFile),\n };\n}\n\n/** Unsupported-top-level-block diagnostics are anchored to the keyword token. */\nexport function keywordPslSpan(node: SyntaxNode, keyword: string, sourceFile: SourceFile): PslSpan {\n const start = node.offset;\n const end = start + keyword.length;\n return {\n start: offsetToPslPosition(start, sourceFile),\n end: offsetToPslPosition(end, sourceFile),\n };\n}\n\nexport function rangeToPslSpan(range: Range, sourceFile: SourceFile): PslSpan {\n return {\n start: offsetToPslPosition(sourceFile.offsetAt(range.start), sourceFile),\n end: offsetToPslPosition(sourceFile.offsetAt(range.end), sourceFile),\n };\n}\n\nfunction offsetToPslPosition(offset: number, sourceFile: SourceFile): PslSpan['start'] {\n const position: Position = sourceFile.positionAt(offset);\n return { offset, line: position.line + 1, column: position.character + 1 };\n}\n","import type { PslDiagnostic, PslDiagnosticCode } from '@prisma-next/framework-components/psl-ast';\nimport { nodePslSpan } from '../../resolve';\nimport type { AstNode } from '../../syntax/ast-helpers';\nimport type { InterpretCtx } from '../types';\n\nexport const ATTRIBUTE_DIAGNOSTIC_CODE: PslDiagnosticCode = 'PSL_INVALID_ATTRIBUTE_SYNTAX';\n\nexport function leafDiagnostic(ctx: InterpretCtx, node: AstNode, message: string): PslDiagnostic {\n return {\n code: ATTRIBUTE_DIAGNOSTIC_CODE,\n message,\n sourceId: ctx.sourceId,\n span: nodePslSpan(node.syntax, ctx.sourceFile),\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { IdentifierAst } from '../../syntax/ast/identifier';\nimport type { ArgType } from '../types';\nimport { leafDiagnostic } from './diagnostic';\n\nexport type FieldRefScope = 'self' | 'referenced';\n\nexport interface FieldRefArgType extends ArgType<string> {\n readonly scope: FieldRefScope;\n}\n\nexport function fieldRef(scope: FieldRefScope): FieldRefArgType {\n return {\n kind: 'fieldRef',\n label: 'field name',\n scope,\n parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {\n if (!(arg instanceof IdentifierAst)) {\n return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);\n }\n const name = arg.name();\n if (name === undefined) {\n return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);\n }\n const model = scope === 'self' ? ctx.selfModel : ctx.resolveReferencedModel();\n // A referenced model in another space can't be resolved here (resolveReferencedModel returns undefined); skip the existence check — it runs where that model is known.\n if (model !== undefined && !Object.hasOwn(model.fields, name)) {\n return notOk([\n leafDiagnostic(ctx, arg, `Field \"${name}\" does not exist on model \"${model.name}\"`),\n ]);\n }\n return ok(name);\n },\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { IdentifierAst } from '../../syntax/ast/identifier';\nimport type { ArgType } from '../types';\nimport { leafDiagnostic } from './diagnostic';\n\nexport function identifier<const N extends string>(name: N): ArgType<N> {\n return {\n kind: 'identifier',\n label: name,\n parse: (arg, ctx): Result<N, readonly PslDiagnostic[]> => {\n if (arg instanceof IdentifierAst && arg.name() === name) return ok(name);\n return notOk([leafDiagnostic(ctx, arg, `Expected ${name}`)]);\n },\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { ArrayLiteralAst, type ExpressionAst } from '../../syntax/ast/expressions';\nimport type { ArgType } from '../types';\nimport { leafDiagnostic } from './diagnostic';\n\nexport interface ListOptions {\n readonly nonEmpty?: boolean;\n readonly unique?: boolean;\n}\n\nexport function list<T>(of: ArgType<T>, opts?: ListOptions): ArgType<T[]> {\n return {\n kind: 'list',\n label: `${of.label}[]`,\n parse: (arg, ctx): Result<T[], readonly PslDiagnostic[]> => {\n if (!(arg instanceof ArrayLiteralAst)) {\n return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);\n }\n const diagnostics: PslDiagnostic[] = [];\n const parsed: { node: ExpressionAst; value: T }[] = [];\n let count = 0;\n for (const element of arg.elements()) {\n count += 1;\n const result = of.parse(element, ctx);\n if (result.ok) parsed.push({ node: element, value: result.value });\n else diagnostics.push(...result.failure);\n }\n if (opts?.nonEmpty === true && count === 0) {\n diagnostics.push(leafDiagnostic(ctx, arg, 'Expected a non-empty list'));\n }\n if (opts?.unique === true) {\n const seen = new Set<T>();\n for (const { node, value } of parsed) {\n if (seen.has(value)) diagnostics.push(leafDiagnostic(ctx, node, 'Duplicate list entry'));\n else seen.add(value);\n }\n }\n if (diagnostics.length > 0) return notOk(diagnostics);\n return ok(parsed.map((entry) => entry.value));\n },\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport type { ArgType, OutOf } from '../types';\nimport { leafDiagnostic } from './diagnostic';\n\nexport function oneOf<Alts extends readonly [ArgType<unknown>, ...ArgType<unknown>[]]>(\n ...alts: Alts\n): ArgType<OutOf<Alts[number]>> {\n const label = alts.map((alt) => alt.label).join(' | ');\n return {\n kind: 'oneOf',\n label,\n parse: (arg, ctx): Result<OutOf<Alts[number]>, readonly PslDiagnostic[]> => {\n for (const alt of alts) {\n const result = alt.parse(arg, ctx);\n if (result.ok) {\n return ok(\n blindCast<\n OutOf<Alts[number]>,\n 'The matched value comes from an alternative whose output type is a member of the union, but iterating the tuple widens each element to ArgType<unknown>, erasing that relationship.'\n >(result.value),\n );\n }\n }\n return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);\n },\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { StringLiteralExprAst } from '../../syntax/ast/expressions';\nimport type { ArgType } from '../types';\nimport { leafDiagnostic } from './diagnostic';\n\nexport function str(): ArgType<string> {\n return {\n kind: 'str',\n label: 'string',\n parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {\n if (arg instanceof StringLiteralExprAst) {\n const value = arg.value();\n if (value !== undefined) return ok(value);\n }\n return notOk([leafDiagnostic(ctx, arg, 'Expected a string literal')]);\n },\n };\n}\n","import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';\nimport type { AttributeOut, AttributeSpec, InterpretCtx, Param, PositionalParam } from './types';\n\ninterface FieldAttributeConfig<\n Pos extends readonly PositionalParam[],\n Named extends Record<string, Param<unknown>>,\n> {\n readonly positional?: Pos;\n readonly named?: Named;\n readonly refine?: (\n parsed: AttributeOut<Pos, Named>,\n ctx: InterpretCtx,\n ) => readonly PslDiagnostic[];\n}\n\nexport function fieldAttribute<\n const Pos extends readonly PositionalParam[] = readonly [],\n const Named extends Record<string, Param<unknown>> = Record<never, never>,\n>(name: string, config: FieldAttributeConfig<Pos, Named>): AttributeSpec<AttributeOut<Pos, Named>> {\n return {\n level: 'field',\n name,\n positional: config.positional ?? [],\n named: config.named ?? {},\n ...(config.refine !== undefined ? { refine: config.refine } : {}),\n };\n}\n","import type { PslDiagnostic, PslSpan } from '@prisma-next/framework-components/psl-ast';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { nodePslSpan } from '../resolve';\nimport type { FieldAttributeAst, ModelAttributeAst } from '../syntax/ast/attributes';\nimport type { AttributeArgAst } from '../syntax/ast/expressions';\nimport { ATTRIBUTE_DIAGNOSTIC_CODE } from './combinators/diagnostic';\nimport type { ArgType, AttributeSpec, InterpretCtx, OptionalArgType, Param } from './types';\n\nexport function interpretAttribute<Out>(\n attrNode: FieldAttributeAst | ModelAttributeAst,\n spec: AttributeSpec<Out>,\n ctx: InterpretCtx,\n): Result<Out, readonly PslDiagnostic[]> {\n const diagnostics: PslDiagnostic[] = [];\n const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sourceFile);\n\n const output: Record<string, unknown> = {};\n const seen = new Set<string>();\n let positionalSlot = 0;\n let reportedExcess = false;\n\n for (const arg of attrNode.argList()?.args() ?? []) {\n const name = arg.name()?.name();\n\n let key: string;\n let param: Param<unknown>;\n if (name === undefined) {\n const posParam = spec.positional[positionalSlot];\n if (posParam === undefined) {\n if (!reportedExcess) {\n diagnostics.push(\n diagnostic(\n `Attribute \"${spec.name}\" received too many positional arguments`,\n ctx,\n attributeSpan,\n ),\n );\n reportedExcess = true;\n }\n continue;\n }\n positionalSlot += 1;\n key = posParam.key;\n param = posParam.type;\n } else {\n const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : undefined;\n if (namedParam === undefined) {\n diagnostics.push(\n diagnostic(\n `Attribute \"${spec.name}\" received unknown argument \"${name}\"`,\n ctx,\n nodePslSpan(arg.syntax, ctx.sourceFile),\n ),\n );\n continue;\n }\n key = name;\n param = namedParam;\n }\n\n if (seen.has(key)) {\n diagnostics.push(\n diagnostic(\n `Attribute \"${spec.name}\" received duplicate argument \"${key}\"`,\n ctx,\n nodePslSpan(arg.syntax, ctx.sourceFile),\n ),\n );\n continue;\n }\n seen.add(key);\n const result = parseArgValue(arg, param, ctx, diagnostics);\n if (result.ok) output[key] = result.value;\n }\n\n const finalized = new Set<string>();\n const finalizeAbsentKey = (\n key: string,\n positionalParam: Param<unknown> | undefined,\n namedParam: Param<unknown> | undefined,\n ): void => {\n if (finalized.has(key) || seen.has(key)) return;\n finalized.add(key);\n const effective = namedParam ?? positionalParam;\n if (effective === undefined) return;\n if (isOptionalArgType(effective)) {\n if (effective.hasDefault) output[key] = effective.defaultValue;\n return;\n }\n diagnostics.push(\n diagnostic(\n `Attribute \"${spec.name}\" is missing required argument \"${key}\"`,\n ctx,\n attributeSpan,\n ),\n );\n };\n\n for (const param of spec.positional) {\n const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : undefined;\n finalizeAbsentKey(param.key, param.type, namedParam);\n }\n for (const key of Object.keys(spec.named)) {\n finalizeAbsentKey(key, undefined, spec.named[key]);\n }\n\n if (diagnostics.length > 0) {\n return notOk<readonly PslDiagnostic[]>(diagnostics);\n }\n\n const value = blindCast<\n Out,\n 'The engine builds the output object structurally from the spec; TypeScript cannot relate the dynamically-keyed record to the spec-inferred output type.'\n >(output);\n if (spec.refine !== undefined) {\n const refineDiagnostics = spec.refine(value, ctx);\n if (refineDiagnostics.length > 0) {\n return notOk<readonly PslDiagnostic[]>(refineDiagnostics);\n }\n }\n return ok(value);\n}\n\nfunction parseArgValue(\n arg: AttributeArgAst,\n argType: ArgType<unknown>,\n ctx: InterpretCtx,\n diagnostics: PslDiagnostic[],\n): Result<unknown, readonly PslDiagnostic[]> {\n const value = arg.value();\n if (value === undefined) {\n const missing = diagnostic(\n 'Attribute argument is missing a value',\n ctx,\n nodePslSpan(arg.syntax, ctx.sourceFile),\n );\n diagnostics.push(missing);\n return notOk<readonly PslDiagnostic[]>([missing]);\n }\n const result = argType.parse(value, ctx);\n if (!result.ok) {\n for (const failure of result.failure) diagnostics.push(failure);\n }\n return result;\n}\n\nfunction isOptionalArgType(param: Param<unknown>): param is OptionalArgType<unknown> {\n return 'optional' in param && param.optional === true;\n}\n\nfunction diagnostic(message: string, ctx: InterpretCtx, span: PslSpan): PslDiagnostic {\n return { code: ATTRIBUTE_DIAGNOSTIC_CODE, message, sourceId: ctx.sourceId, span };\n}\n","import type { ArgType, OptionalArgType } from './types';\n\nexport function optional<T>(type: ArgType<T>, ...rest: [defaultValue: T] | []): OptionalArgType<T> {\n if (rest.length === 0) {\n return { ...type, optional: true, hasDefault: false };\n }\n return { ...type, optional: true, hasDefault: true, defaultValue: rest[0] };\n}\n","import {\n type AuthoringPslBlockDescriptor,\n type AuthoringPslBlockDescriptorNamespace,\n isAuthoringPslBlockDescriptor,\n} from '@prisma-next/framework-components/authoring';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport {\n makePslNamespace,\n makePslNamespaceEntries,\n type PslDiagnostic,\n type PslModel,\n type PslSpan,\n UNSPECIFIED_PSL_NAMESPACE_ID,\n validateExtensionBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { SourceFile } from './source-file';\nimport type { BlockSymbol, ModelSymbol, SymbolTable } from './symbol-table';\n\nexport function findBlockDescriptor(\n descriptors: AuthoringPslBlockDescriptorNamespace | undefined,\n keyword: string,\n): AuthoringPslBlockDescriptor | undefined {\n if (descriptors === undefined) return undefined;\n for (const value of Object.values(descriptors)) {\n if (value === undefined) continue;\n if (isAuthoringPslBlockDescriptor(value)) {\n if (value.keyword === keyword) return value;\n continue;\n }\n const nested = findBlockDescriptor(value, keyword);\n if (nested !== undefined) return nested;\n }\n return undefined;\n}\n\nexport function validateExtensionBlockFromSymbol(input: {\n readonly block: BlockSymbol;\n readonly descriptor: AuthoringPslBlockDescriptor;\n readonly symbolTable: SymbolTable;\n readonly sourceFile: SourceFile;\n readonly sourceId: string;\n readonly codecLookup: CodecLookup;\n}): readonly PslDiagnostic[] {\n const refCtx = buildRefResolutionContext(input.symbolTable, input.block);\n return validateExtensionBlock(\n input.block.block,\n input.descriptor,\n input.sourceId,\n input.codecLookup,\n refCtx,\n );\n}\n\nconst ZERO_SPAN: PslSpan = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: 0, line: 1, column: 1 },\n};\n\nfunction buildRefResolutionContext(\n symbolTable: SymbolTable,\n block: BlockSymbol,\n): {\n ownerNamespace: ReturnType<typeof makePslNamespace>;\n allNamespaces: readonly ReturnType<typeof makePslNamespace>[];\n} {\n const unspecifiedNamespace = makeNamespace(\n UNSPECIFIED_PSL_NAMESPACE_ID,\n Object.values(symbolTable.topLevel.models),\n );\n const namedNamespaces = Object.values(symbolTable.topLevel.namespaces).map((namespace) =>\n makeNamespace(namespace.name, Object.values(namespace.models)),\n );\n const allNamespaces = [unspecifiedNamespace, ...namedNamespaces];\n const ownerNamespaceName = findOwnerNamespaceName(symbolTable, block);\n const ownerNamespace =\n allNamespaces.find((namespace) => namespace.name === ownerNamespaceName) ??\n unspecifiedNamespace;\n return { ownerNamespace, allNamespaces };\n}\n\nfunction makeNamespace(\n name: string,\n models: readonly ModelSymbol[],\n): ReturnType<typeof makePslNamespace> {\n const modelStubs: PslModel[] = models.map((model) => ({\n kind: 'model',\n name: model.name,\n fields: [],\n attributes: [],\n span: ZERO_SPAN,\n }));\n return makePslNamespace({\n kind: 'namespace',\n name,\n entries: makePslNamespaceEntries(modelStubs, [], []),\n span: ZERO_SPAN,\n });\n}\n\nfunction findOwnerNamespaceName(symbolTable: SymbolTable, block: BlockSymbol): string {\n for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {\n if (Object.values(namespace.blocks).some((candidate) => candidate === block)) {\n return namespace.name;\n }\n }\n return UNSPECIFIED_PSL_NAMESPACE_ID;\n}\n","import type { AuthoringPslBlockDescriptor } from '@prisma-next/framework-components/authoring';\nimport type {\n PslBlockParam,\n PslExtensionBlock,\n PslExtensionBlockAttribute,\n PslExtensionBlockParamValue,\n PslSpan,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { ParseDiagnostic } from './parse';\nimport { nodePslSpan } from './resolve';\nimport type { SourceFile } from './source-file';\nimport type { GenericBlockDeclarationAst, KeyValuePairAst } from './syntax/ast/declarations';\nimport { ArrayLiteralAst, type ExpressionAst } from './syntax/ast/expressions';\nimport { printSyntax } from './syntax/ast-helpers';\n\n/**\n * Descriptor-free and unknown parameters become `value` stubs so validation can\n * report them via key-set comparison. Duplicate member names are first-wins.\n */\nexport function reconstructExtensionBlock(\n node: GenericBlockDeclarationAst,\n descriptor: AuthoringPslBlockDescriptor | undefined,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): PslExtensionBlock {\n const keyword = node.keyword()?.text ?? '';\n const blockName = node.name()?.name() ?? '';\n\n const blockAttributes: PslExtensionBlockAttribute[] = [];\n for (const attribute of node.attributes()) {\n const name = attribute.name()?.path().join('.') ?? '';\n const args = Array.from(attribute.argList()?.args() ?? [], (arg) => {\n const value = arg.value();\n return {\n kind: 'positional' as const,\n value: value === undefined ? '' : printSyntax(value.syntax).trim(),\n span: nodePslSpan(arg.syntax, sourceFile),\n };\n });\n blockAttributes.push({\n name,\n args,\n span: nodePslSpan(attribute.syntax, sourceFile),\n });\n }\n\n const parameters: Record<string, PslExtensionBlockParamValue> = {};\n for (const entry of node.entries()) {\n const key = entry.key()?.name();\n if (key === undefined) continue;\n const span = nodePslSpan(entry.syntax, sourceFile);\n if (Object.hasOwn(parameters, key)) {\n diagnostics.push({\n code: 'PSL_EXTENSION_DUPLICATE_PARAMETER',\n message: `Duplicate parameter \"${key}\" in \"${keyword}\" block \"${blockName}\"; first occurrence wins`,\n range: {\n start: sourceFile.positionAt(entry.syntax.offset),\n end: sourceFile.positionAt(entry.syntax.offset + entry.syntax.green.textLength),\n },\n });\n continue;\n }\n parameters[key] = reconstructParamValue(\n entry,\n descriptor?.parameters[key],\n span,\n sourceFile,\n diagnostics,\n );\n }\n\n return {\n kind: descriptor?.discriminator ?? keyword,\n name: blockName,\n parameters,\n blockAttributes,\n span: nodePslSpan(node.syntax, sourceFile),\n };\n}\n\nfunction reconstructParamValue(\n entry: KeyValuePairAst,\n param: PslBlockParam | undefined,\n span: PslSpan,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): PslExtensionBlockParamValue {\n const value = entry.value();\n if (value === undefined) {\n return { kind: 'bare', span };\n }\n return reconstructFromExpression(value, param, span, sourceFile, diagnostics);\n}\n\nfunction reconstructFromExpression(\n value: ExpressionAst,\n param: PslBlockParam | undefined,\n span: PslSpan,\n sourceFile: SourceFile,\n diagnostics?: ParseDiagnostic[],\n): PslExtensionBlockParamValue {\n const raw = printSyntax(value.syntax).trim();\n if (param?.kind === 'list') {\n const array = ArrayLiteralAst.cast(value.syntax);\n if (!array) {\n diagnostics?.push({\n code: 'PSL_EXTENSION_INVALID_VALUE',\n message: `List parameter expects an array literal, got ${raw}`,\n range: {\n start: sourceFile.positionAt(value.syntax.offset),\n end: sourceFile.positionAt(value.syntax.offset + value.syntax.green.textLength),\n },\n });\n return { kind: 'value', raw, span };\n }\n\n const items: PslExtensionBlockParamValue[] = [];\n for (const element of array.elements()) {\n items.push(\n reconstructFromExpression(\n element,\n param.of,\n nodePslSpan(element.syntax, sourceFile),\n sourceFile,\n diagnostics,\n ),\n );\n }\n return { kind: 'list', items, span };\n }\n switch (param?.kind) {\n case 'ref':\n return { kind: 'ref', identifier: raw, span };\n case 'option':\n return { kind: 'option', token: raw, span };\n default:\n return { kind: 'value', raw, span };\n }\n}\n","import type { AuthoringPslBlockDescriptorNamespace } from '@prisma-next/framework-components/authoring';\nimport type { PslExtensionBlock, PslSpan } from '@prisma-next/framework-components/psl-ast';\nimport { reconstructExtensionBlock } from './block-reconstruction';\nimport { findBlockDescriptor } from './extension-block';\nimport type { ParseDiagnostic } from './parse';\nimport {\n nodePslSpan,\n type ResolvedAttribute,\n type ResolvedTypeConstructorCall,\n readResolvedAttributes,\n readResolvedConstructorCall,\n} from './resolve';\nimport type { Range, SourceFile } from './source-file';\nimport {\n CompositeTypeDeclarationAst,\n type DocumentAst,\n type FieldDeclarationAst,\n GenericBlockDeclarationAst,\n ModelDeclarationAst,\n type NamedTypeDeclarationAst,\n NamespaceDeclarationAst,\n TypesBlockAst,\n} from './syntax/ast/declarations';\nimport type { IdentifierAst } from './syntax/ast/identifier';\nimport type { SyntaxNode } from './syntax/red';\n\nexport type {\n ResolvedAttribute,\n ResolvedAttributeArg,\n ResolvedTypeConstructorCall,\n} from './resolve';\n\nexport interface SymbolTable {\n readonly topLevel: TopLevelScope;\n}\n\nexport interface TopLevelScope {\n readonly namespaces: Record<string, NamespaceSymbol>;\n readonly scalars: Record<string, ScalarSymbol>;\n readonly typeAliases: Record<string, TypeAliasSymbol>;\n readonly blocks: Record<string, BlockSymbol>;\n readonly models: Record<string, ModelSymbol>;\n readonly compositeTypes: Record<string, CompositeTypeSymbol>;\n}\n\nexport interface NamespaceSymbol {\n readonly kind: 'namespace';\n readonly name: string;\n readonly node: NamespaceDeclarationAst;\n readonly span: PslSpan;\n readonly models: Record<string, ModelSymbol>;\n readonly compositeTypes: Record<string, CompositeTypeSymbol>;\n readonly blocks: Record<string, BlockSymbol>;\n}\n\nexport interface ModelSymbol {\n readonly kind: 'model';\n readonly name: string;\n readonly node: ModelDeclarationAst;\n readonly span: PslSpan;\n readonly fields: Record<string, FieldSymbol>;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface CompositeTypeSymbol {\n readonly kind: 'compositeType';\n readonly name: string;\n readonly node: CompositeTypeDeclarationAst;\n readonly span: PslSpan;\n readonly fields: Record<string, FieldSymbol>;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface BlockSymbol {\n readonly kind: 'block';\n readonly name: string;\n readonly keyword: string;\n readonly node: GenericBlockDeclarationAst;\n readonly span: PslSpan;\n /** Resolved once so consumers do not independently classify block parameters. */\n readonly block: PslExtensionBlock;\n}\n\nexport interface ResolvedNamedTypeBinding {\n readonly baseType?: string;\n readonly typeConstructor?: ResolvedTypeConstructorCall;\n readonly isConstructor: boolean;\n readonly attributes: readonly ResolvedAttribute[];\n}\n\nexport interface ScalarSymbol extends ResolvedNamedTypeBinding {\n readonly kind: 'scalar';\n readonly name: string;\n readonly node: NamedTypeDeclarationAst;\n readonly span: PslSpan;\n}\n\nexport interface TypeAliasSymbol extends ResolvedNamedTypeBinding {\n readonly kind: 'typeAlias';\n readonly name: string;\n readonly node: NamedTypeDeclarationAst;\n readonly span: PslSpan;\n}\n\nexport interface FieldSymbol {\n readonly kind: 'field';\n readonly name: string;\n readonly node: FieldDeclarationAst;\n readonly span: PslSpan;\n readonly typeName: string;\n readonly typeNamespaceId?: string;\n readonly typeContractSpaceId?: string;\n readonly optional: boolean;\n readonly list: boolean;\n readonly typeConstructor?: ResolvedTypeConstructorCall;\n readonly attributes: readonly ResolvedAttribute[];\n /** Prevents cascading unsupported-type diagnostics after invalid qualification. */\n readonly malformedType?: boolean;\n}\n\nexport interface BuildSymbolTableOptions {\n readonly document: DocumentAst;\n readonly sourceFile: SourceFile;\n readonly scalarTypes: readonly string[];\n readonly pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace;\n}\n\nexport interface SymbolTableResult {\n readonly table: SymbolTable;\n readonly diagnostics: readonly ParseDiagnostic[];\n}\n\n/**\n * Owns duplicate-declaration detection for all PSL scopes; downstream consumers\n * should consume first-wins symbols rather than re-emitting duplicate diagnostics.\n */\nexport function buildSymbolTable(options: BuildSymbolTableOptions): SymbolTableResult {\n const { document, sourceFile, scalarTypes, pslBlockDescriptors } = options;\n const diagnostics: ParseDiagnostic[] = [];\n const scalarSet = new Set(scalarTypes);\n\n const namespaces: Record<string, NamespaceSymbol> = {};\n const scalars: Record<string, ScalarSymbol> = {};\n const typeAliases: Record<string, TypeAliasSymbol> = {};\n const blocks: Record<string, BlockSymbol> = {};\n const models: Record<string, ModelSymbol> = {};\n const compositeTypes: Record<string, CompositeTypeSymbol> = {};\n const topLevelNames = new Set<string>();\n\n const claim = (taken: Set<string>, name: IdentifierAst | undefined): string | undefined => {\n const text = name?.name();\n if (text === undefined) return undefined;\n if (taken.has(text)) {\n const range = nameRange(name, sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${text}\"`,\n range,\n });\n }\n return undefined;\n }\n taken.add(text);\n return text;\n };\n\n for (const declaration of document.declarations()) {\n if (declaration instanceof ModelDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) models[name] = buildModel(name, declaration, sourceFile, diagnostics);\n } else if (declaration instanceof CompositeTypeDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n compositeTypes[name] = buildCompositeType(name, declaration, sourceFile, diagnostics);\n }\n } else if (declaration instanceof GenericBlockDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n blocks[name] = buildBlock(name, declaration, sourceFile, pslBlockDescriptors, diagnostics);\n }\n } else if (declaration instanceof NamespaceDeclarationAst) {\n const name = claim(topLevelNames, declaration.name());\n if (name !== undefined) {\n namespaces[name] = buildNamespace(\n name,\n declaration,\n diagnostics,\n sourceFile,\n pslBlockDescriptors,\n );\n }\n } else if (declaration instanceof TypesBlockAst) {\n for (const binding of declaration.declarations()) {\n const name = claim(topLevelNames, binding.name());\n if (name === undefined) continue;\n const resolved = resolveNamedTypeBinding(binding, sourceFile);\n const span = nodePslSpan(binding.syntax, sourceFile);\n if (isScalarBinding(binding, scalarSet)) {\n scalars[name] = { kind: 'scalar', name, node: binding, span, ...resolved };\n } else {\n typeAliases[name] = { kind: 'typeAlias', name, node: binding, span, ...resolved };\n }\n }\n }\n }\n\n const table: SymbolTable = {\n topLevel: { namespaces, scalars, typeAliases, blocks, models, compositeTypes },\n };\n return { table, diagnostics };\n}\n\nfunction buildModel(\n name: string,\n node: ModelDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): ModelSymbol {\n return {\n kind: 'model',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n fields: buildFields(name, node.fields(), sourceFile, diagnostics),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction buildCompositeType(\n name: string,\n node: CompositeTypeDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): CompositeTypeSymbol {\n return {\n kind: 'compositeType',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n fields: buildFields(name, node.fields(), sourceFile, diagnostics),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction buildBlock(\n name: string,\n node: GenericBlockDeclarationAst,\n sourceFile: SourceFile,\n pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace,\n diagnostics: ParseDiagnostic[],\n): BlockSymbol {\n const keyword = node.keyword()?.text ?? '';\n const descriptor = findBlockDescriptor(pslBlockDescriptors, keyword);\n return {\n kind: 'block',\n name,\n keyword,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n block: reconstructExtensionBlock(node, descriptor, sourceFile, diagnostics),\n };\n}\n\nfunction buildNamespace(\n name: string,\n node: NamespaceDeclarationAst,\n diagnostics: ParseDiagnostic[],\n sourceFile: SourceFile,\n pslBlockDescriptors: AuthoringPslBlockDescriptorNamespace,\n): NamespaceSymbol {\n const models: Record<string, ModelSymbol> = {};\n const compositeTypes: Record<string, CompositeTypeSymbol> = {};\n const blocks: Record<string, BlockSymbol> = {};\n const taken = new Set<string>();\n\n for (const member of node.declarations()) {\n const memberName = member.name()?.name();\n if (memberName === undefined) continue;\n if (taken.has(memberName)) {\n const range = nameRange(member.name(), sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${memberName}\"`,\n range,\n });\n }\n continue;\n }\n taken.add(memberName);\n if (member instanceof ModelDeclarationAst) {\n models[memberName] = buildModel(memberName, member, sourceFile, diagnostics);\n } else if (member instanceof CompositeTypeDeclarationAst) {\n compositeTypes[memberName] = buildCompositeType(memberName, member, sourceFile, diagnostics);\n } else if (member instanceof GenericBlockDeclarationAst) {\n blocks[memberName] = buildBlock(\n memberName,\n member,\n sourceFile,\n pslBlockDescriptors,\n diagnostics,\n );\n }\n }\n\n return {\n kind: 'namespace',\n name,\n node,\n span: nodePslSpan(node.syntax, sourceFile),\n models,\n compositeTypes,\n blocks,\n };\n}\n\nfunction buildFields(\n ownerName: string,\n fields: Iterable<FieldDeclarationAst>,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): Record<string, FieldSymbol> {\n const result: Record<string, FieldSymbol> = {};\n for (const field of fields) {\n const nameNode = field.name();\n const name = nameNode?.name();\n if (name === undefined) continue;\n if (Object.hasOwn(result, name)) {\n const range = nameRange(nameNode, sourceFile);\n if (range) {\n diagnostics.push({\n code: 'PSL_DUPLICATE_DECLARATION',\n message: `Duplicate declaration of \"${name}\"`,\n range,\n });\n }\n continue;\n }\n result[name] = buildField(ownerName, name, field, sourceFile, diagnostics);\n }\n return result;\n}\n\nfunction buildField(\n ownerName: string,\n name: string,\n node: FieldDeclarationAst,\n sourceFile: SourceFile,\n diagnostics: ParseDiagnostic[],\n): FieldSymbol {\n const attributes = readResolvedAttributes(node.attributes(), sourceFile);\n const span = nodePslSpan(node.syntax, sourceFile);\n const annotation = node.typeAnnotation();\n const typeName = annotation?.name();\n\n if (typeName?.isOverQualified()) {\n const path = typeName.path();\n diagnostics.push({\n code: 'PSL_INVALID_QUALIFIED_TYPE',\n message: `Field \"${ownerName}.${name}\" has an invalid qualified type \"${path.join('.')}\"; use at most one namespace qualifier (e.g. \"ns.TypeName\")`,\n range: nodeRange(typeName.syntax, sourceFile),\n });\n return {\n kind: 'field',\n name,\n node,\n span,\n typeName: path[path.length - 1] ?? '',\n optional: false,\n list: false,\n malformedType: true,\n attributes,\n };\n }\n\n const typeConstructor = annotation?.isConstructor()\n ? readResolvedConstructorCall(annotation, sourceFile)\n : undefined;\n const typeNamespaceId = typeName?.namespace()?.name();\n const typeContractSpaceId = typeName?.space()?.name();\n\n return {\n kind: 'field',\n name,\n node,\n span,\n typeName: typeName?.identifier()?.name() ?? '',\n ...(typeNamespaceId !== undefined ? { typeNamespaceId } : {}),\n ...(typeContractSpaceId !== undefined ? { typeContractSpaceId } : {}),\n optional: annotation?.isOptional() ?? false,\n list: annotation?.isList() ?? false,\n ...(typeConstructor !== undefined ? { typeConstructor } : {}),\n attributes,\n };\n}\n\nfunction resolveNamedTypeBinding(\n node: NamedTypeDeclarationAst,\n sourceFile: SourceFile,\n): {\n baseType?: string;\n typeConstructor?: ResolvedTypeConstructorCall;\n isConstructor: boolean;\n attributes: readonly ResolvedAttribute[];\n} {\n const annotation = node.typeAnnotation();\n const isConstructor = annotation?.isConstructor() ?? false;\n const baseType = annotation?.name()?.identifier()?.name();\n const typeConstructor = readResolvedConstructorCall(annotation, sourceFile);\n return {\n isConstructor,\n ...(!isConstructor && baseType !== undefined ? { baseType } : {}),\n ...(typeConstructor !== undefined ? { typeConstructor } : {}),\n attributes: readResolvedAttributes(node.attributes(), sourceFile),\n };\n}\n\nfunction isScalarBinding(node: NamedTypeDeclarationAst, scalarTypes: Set<string>): boolean {\n const annotation = node.typeAnnotation();\n if (annotation === undefined || annotation.isConstructor()) return false;\n const base = annotation.name()?.identifier()?.name();\n return base !== undefined && scalarTypes.has(base);\n}\n\nfunction nameRange(name: IdentifierAst | undefined, sourceFile: SourceFile): Range | undefined {\n if (name === undefined) return undefined;\n for (const token of name.syntax.tokens()) {\n if (token.kind === 'Ident') {\n return {\n start: sourceFile.positionAt(token.offset),\n end: sourceFile.positionAt(token.offset + token.text.length),\n };\n }\n }\n return undefined;\n}\n\nfunction nodeRange(node: SyntaxNode, sourceFile: SourceFile): Range {\n const start = node.offset;\n const end = start + node.green.textLength;\n return {\n start: sourceFile.positionAt(start),\n end: sourceFile.positionAt(end),\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/psl-parser",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.45",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Reusable parser for Prisma Schema Language (PSL)",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/framework-components": "0.14.0-dev.
|
|
10
|
-
"@prisma-next/utils": "0.14.0-dev.
|
|
9
|
+
"@prisma-next/framework-components": "0.14.0-dev.45",
|
|
10
|
+
"@prisma-next/utils": "0.14.0-dev.45"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@prisma-next/tsconfig": "0.14.0-dev.
|
|
14
|
-
"@prisma-next/tsdown": "0.14.0-dev.
|
|
13
|
+
"@prisma-next/tsconfig": "0.14.0-dev.45",
|
|
14
|
+
"@prisma-next/tsdown": "0.14.0-dev.45",
|
|
15
15
|
"tsdown": "0.22.1",
|
|
16
16
|
"typescript": "5.9.3",
|
|
17
17
|
"vitest": "4.1.8"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PslDiagnostic, PslDiagnosticCode } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { nodePslSpan } from '../../resolve';
|
|
3
|
+
import type { AstNode } from '../../syntax/ast-helpers';
|
|
4
|
+
import type { InterpretCtx } from '../types';
|
|
5
|
+
|
|
6
|
+
export const ATTRIBUTE_DIAGNOSTIC_CODE: PslDiagnosticCode = 'PSL_INVALID_ATTRIBUTE_SYNTAX';
|
|
7
|
+
|
|
8
|
+
export function leafDiagnostic(ctx: InterpretCtx, node: AstNode, message: string): PslDiagnostic {
|
|
9
|
+
return {
|
|
10
|
+
code: ATTRIBUTE_DIAGNOSTIC_CODE,
|
|
11
|
+
message,
|
|
12
|
+
sourceId: ctx.sourceId,
|
|
13
|
+
span: nodePslSpan(node.syntax, ctx.sourceFile),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { IdentifierAst } from '../../syntax/ast/identifier';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export type FieldRefScope = 'self' | 'referenced';
|
|
8
|
+
|
|
9
|
+
export interface FieldRefArgType extends ArgType<string> {
|
|
10
|
+
readonly scope: FieldRefScope;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function fieldRef(scope: FieldRefScope): FieldRefArgType {
|
|
14
|
+
return {
|
|
15
|
+
kind: 'fieldRef',
|
|
16
|
+
label: 'field name',
|
|
17
|
+
scope,
|
|
18
|
+
parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {
|
|
19
|
+
if (!(arg instanceof IdentifierAst)) {
|
|
20
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);
|
|
21
|
+
}
|
|
22
|
+
const name = arg.name();
|
|
23
|
+
if (name === undefined) {
|
|
24
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);
|
|
25
|
+
}
|
|
26
|
+
const model = scope === 'self' ? ctx.selfModel : ctx.resolveReferencedModel();
|
|
27
|
+
// A referenced model in another space can't be resolved here (resolveReferencedModel returns undefined); skip the existence check — it runs where that model is known.
|
|
28
|
+
if (model !== undefined && !Object.hasOwn(model.fields, name)) {
|
|
29
|
+
return notOk([
|
|
30
|
+
leafDiagnostic(ctx, arg, `Field "${name}" does not exist on model "${model.name}"`),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
return ok(name);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { IdentifierAst } from '../../syntax/ast/identifier';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function identifier<const N extends string>(name: N): ArgType<N> {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'identifier',
|
|
10
|
+
label: name,
|
|
11
|
+
parse: (arg, ctx): Result<N, readonly PslDiagnostic[]> => {
|
|
12
|
+
if (arg instanceof IdentifierAst && arg.name() === name) return ok(name);
|
|
13
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${name}`)]);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { ArrayLiteralAst, type ExpressionAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export interface ListOptions {
|
|
8
|
+
readonly nonEmpty?: boolean;
|
|
9
|
+
readonly unique?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function list<T>(of: ArgType<T>, opts?: ListOptions): ArgType<T[]> {
|
|
13
|
+
return {
|
|
14
|
+
kind: 'list',
|
|
15
|
+
label: `${of.label}[]`,
|
|
16
|
+
parse: (arg, ctx): Result<T[], readonly PslDiagnostic[]> => {
|
|
17
|
+
if (!(arg instanceof ArrayLiteralAst)) {
|
|
18
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
|
|
19
|
+
}
|
|
20
|
+
const diagnostics: PslDiagnostic[] = [];
|
|
21
|
+
const parsed: { node: ExpressionAst; value: T }[] = [];
|
|
22
|
+
let count = 0;
|
|
23
|
+
for (const element of arg.elements()) {
|
|
24
|
+
count += 1;
|
|
25
|
+
const result = of.parse(element, ctx);
|
|
26
|
+
if (result.ok) parsed.push({ node: element, value: result.value });
|
|
27
|
+
else diagnostics.push(...result.failure);
|
|
28
|
+
}
|
|
29
|
+
if (opts?.nonEmpty === true && count === 0) {
|
|
30
|
+
diagnostics.push(leafDiagnostic(ctx, arg, 'Expected a non-empty list'));
|
|
31
|
+
}
|
|
32
|
+
if (opts?.unique === true) {
|
|
33
|
+
const seen = new Set<T>();
|
|
34
|
+
for (const { node, value } of parsed) {
|
|
35
|
+
if (seen.has(value)) diagnostics.push(leafDiagnostic(ctx, node, 'Duplicate list entry'));
|
|
36
|
+
else seen.add(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (diagnostics.length > 0) return notOk(diagnostics);
|
|
40
|
+
return ok(parsed.map((entry) => entry.value));
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
3
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
4
|
+
import type { ArgType, OutOf } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function oneOf<Alts extends readonly [ArgType<unknown>, ...ArgType<unknown>[]]>(
|
|
8
|
+
...alts: Alts
|
|
9
|
+
): ArgType<OutOf<Alts[number]>> {
|
|
10
|
+
const label = alts.map((alt) => alt.label).join(' | ');
|
|
11
|
+
return {
|
|
12
|
+
kind: 'oneOf',
|
|
13
|
+
label,
|
|
14
|
+
parse: (arg, ctx): Result<OutOf<Alts[number]>, readonly PslDiagnostic[]> => {
|
|
15
|
+
for (const alt of alts) {
|
|
16
|
+
const result = alt.parse(arg, ctx);
|
|
17
|
+
if (result.ok) {
|
|
18
|
+
return ok(
|
|
19
|
+
blindCast<
|
|
20
|
+
OutOf<Alts[number]>,
|
|
21
|
+
'The matched value comes from an alternative whose output type is a member of the union, but iterating the tuple widens each element to ArgType<unknown>, erasing that relationship.'
|
|
22
|
+
>(result.value),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { StringLiteralExprAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function str(): ArgType<string> {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'str',
|
|
10
|
+
label: 'string',
|
|
11
|
+
parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {
|
|
12
|
+
if (arg instanceof StringLiteralExprAst) {
|
|
13
|
+
const value = arg.value();
|
|
14
|
+
if (value !== undefined) return ok(value);
|
|
15
|
+
}
|
|
16
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a string literal')]);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import type { AttributeOut, AttributeSpec, InterpretCtx, Param, PositionalParam } from './types';
|
|
3
|
+
|
|
4
|
+
interface FieldAttributeConfig<
|
|
5
|
+
Pos extends readonly PositionalParam[],
|
|
6
|
+
Named extends Record<string, Param<unknown>>,
|
|
7
|
+
> {
|
|
8
|
+
readonly positional?: Pos;
|
|
9
|
+
readonly named?: Named;
|
|
10
|
+
readonly refine?: (
|
|
11
|
+
parsed: AttributeOut<Pos, Named>,
|
|
12
|
+
ctx: InterpretCtx,
|
|
13
|
+
) => readonly PslDiagnostic[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function fieldAttribute<
|
|
17
|
+
const Pos extends readonly PositionalParam[] = readonly [],
|
|
18
|
+
const Named extends Record<string, Param<unknown>> = Record<never, never>,
|
|
19
|
+
>(name: string, config: FieldAttributeConfig<Pos, Named>): AttributeSpec<AttributeOut<Pos, Named>> {
|
|
20
|
+
return {
|
|
21
|
+
level: 'field',
|
|
22
|
+
name,
|
|
23
|
+
positional: config.positional ?? [],
|
|
24
|
+
named: config.named ?? {},
|
|
25
|
+
...(config.refine !== undefined ? { refine: config.refine } : {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { PslDiagnostic, PslSpan } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
3
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
4
|
+
import { nodePslSpan } from '../resolve';
|
|
5
|
+
import type { FieldAttributeAst, ModelAttributeAst } from '../syntax/ast/attributes';
|
|
6
|
+
import type { AttributeArgAst } from '../syntax/ast/expressions';
|
|
7
|
+
import { ATTRIBUTE_DIAGNOSTIC_CODE } from './combinators/diagnostic';
|
|
8
|
+
import type { ArgType, AttributeSpec, InterpretCtx, OptionalArgType, Param } from './types';
|
|
9
|
+
|
|
10
|
+
export function interpretAttribute<Out>(
|
|
11
|
+
attrNode: FieldAttributeAst | ModelAttributeAst,
|
|
12
|
+
spec: AttributeSpec<Out>,
|
|
13
|
+
ctx: InterpretCtx,
|
|
14
|
+
): Result<Out, readonly PslDiagnostic[]> {
|
|
15
|
+
const diagnostics: PslDiagnostic[] = [];
|
|
16
|
+
const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sourceFile);
|
|
17
|
+
|
|
18
|
+
const output: Record<string, unknown> = {};
|
|
19
|
+
const seen = new Set<string>();
|
|
20
|
+
let positionalSlot = 0;
|
|
21
|
+
let reportedExcess = false;
|
|
22
|
+
|
|
23
|
+
for (const arg of attrNode.argList()?.args() ?? []) {
|
|
24
|
+
const name = arg.name()?.name();
|
|
25
|
+
|
|
26
|
+
let key: string;
|
|
27
|
+
let param: Param<unknown>;
|
|
28
|
+
if (name === undefined) {
|
|
29
|
+
const posParam = spec.positional[positionalSlot];
|
|
30
|
+
if (posParam === undefined) {
|
|
31
|
+
if (!reportedExcess) {
|
|
32
|
+
diagnostics.push(
|
|
33
|
+
diagnostic(
|
|
34
|
+
`Attribute "${spec.name}" received too many positional arguments`,
|
|
35
|
+
ctx,
|
|
36
|
+
attributeSpan,
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
reportedExcess = true;
|
|
40
|
+
}
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
positionalSlot += 1;
|
|
44
|
+
key = posParam.key;
|
|
45
|
+
param = posParam.type;
|
|
46
|
+
} else {
|
|
47
|
+
const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : undefined;
|
|
48
|
+
if (namedParam === undefined) {
|
|
49
|
+
diagnostics.push(
|
|
50
|
+
diagnostic(
|
|
51
|
+
`Attribute "${spec.name}" received unknown argument "${name}"`,
|
|
52
|
+
ctx,
|
|
53
|
+
nodePslSpan(arg.syntax, ctx.sourceFile),
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
key = name;
|
|
59
|
+
param = namedParam;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (seen.has(key)) {
|
|
63
|
+
diagnostics.push(
|
|
64
|
+
diagnostic(
|
|
65
|
+
`Attribute "${spec.name}" received duplicate argument "${key}"`,
|
|
66
|
+
ctx,
|
|
67
|
+
nodePslSpan(arg.syntax, ctx.sourceFile),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
seen.add(key);
|
|
73
|
+
const result = parseArgValue(arg, param, ctx, diagnostics);
|
|
74
|
+
if (result.ok) output[key] = result.value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const finalized = new Set<string>();
|
|
78
|
+
const finalizeAbsentKey = (
|
|
79
|
+
key: string,
|
|
80
|
+
positionalParam: Param<unknown> | undefined,
|
|
81
|
+
namedParam: Param<unknown> | undefined,
|
|
82
|
+
): void => {
|
|
83
|
+
if (finalized.has(key) || seen.has(key)) return;
|
|
84
|
+
finalized.add(key);
|
|
85
|
+
const effective = namedParam ?? positionalParam;
|
|
86
|
+
if (effective === undefined) return;
|
|
87
|
+
if (isOptionalArgType(effective)) {
|
|
88
|
+
if (effective.hasDefault) output[key] = effective.defaultValue;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
diagnostics.push(
|
|
92
|
+
diagnostic(
|
|
93
|
+
`Attribute "${spec.name}" is missing required argument "${key}"`,
|
|
94
|
+
ctx,
|
|
95
|
+
attributeSpan,
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
for (const param of spec.positional) {
|
|
101
|
+
const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : undefined;
|
|
102
|
+
finalizeAbsentKey(param.key, param.type, namedParam);
|
|
103
|
+
}
|
|
104
|
+
for (const key of Object.keys(spec.named)) {
|
|
105
|
+
finalizeAbsentKey(key, undefined, spec.named[key]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (diagnostics.length > 0) {
|
|
109
|
+
return notOk<readonly PslDiagnostic[]>(diagnostics);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const value = blindCast<
|
|
113
|
+
Out,
|
|
114
|
+
'The engine builds the output object structurally from the spec; TypeScript cannot relate the dynamically-keyed record to the spec-inferred output type.'
|
|
115
|
+
>(output);
|
|
116
|
+
if (spec.refine !== undefined) {
|
|
117
|
+
const refineDiagnostics = spec.refine(value, ctx);
|
|
118
|
+
if (refineDiagnostics.length > 0) {
|
|
119
|
+
return notOk<readonly PslDiagnostic[]>(refineDiagnostics);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return ok(value);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function parseArgValue(
|
|
126
|
+
arg: AttributeArgAst,
|
|
127
|
+
argType: ArgType<unknown>,
|
|
128
|
+
ctx: InterpretCtx,
|
|
129
|
+
diagnostics: PslDiagnostic[],
|
|
130
|
+
): Result<unknown, readonly PslDiagnostic[]> {
|
|
131
|
+
const value = arg.value();
|
|
132
|
+
if (value === undefined) {
|
|
133
|
+
const missing = diagnostic(
|
|
134
|
+
'Attribute argument is missing a value',
|
|
135
|
+
ctx,
|
|
136
|
+
nodePslSpan(arg.syntax, ctx.sourceFile),
|
|
137
|
+
);
|
|
138
|
+
diagnostics.push(missing);
|
|
139
|
+
return notOk<readonly PslDiagnostic[]>([missing]);
|
|
140
|
+
}
|
|
141
|
+
const result = argType.parse(value, ctx);
|
|
142
|
+
if (!result.ok) {
|
|
143
|
+
for (const failure of result.failure) diagnostics.push(failure);
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function isOptionalArgType(param: Param<unknown>): param is OptionalArgType<unknown> {
|
|
149
|
+
return 'optional' in param && param.optional === true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function diagnostic(message: string, ctx: InterpretCtx, span: PslSpan): PslDiagnostic {
|
|
153
|
+
return { code: ATTRIBUTE_DIAGNOSTIC_CODE, message, sourceId: ctx.sourceId, span };
|
|
154
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ArgType, OptionalArgType } from './types';
|
|
2
|
+
|
|
3
|
+
export function optional<T>(type: ArgType<T>, ...rest: [defaultValue: T] | []): OptionalArgType<T> {
|
|
4
|
+
if (rest.length === 0) {
|
|
5
|
+
return { ...type, optional: true, hasDefault: false };
|
|
6
|
+
}
|
|
7
|
+
return { ...type, optional: true, hasDefault: true, defaultValue: rest[0] };
|
|
8
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import type { Result } from '@prisma-next/utils/result';
|
|
3
|
+
import type { Simplify, UnionToIntersection } from '@prisma-next/utils/types';
|
|
4
|
+
import type { SourceFile } from '../source-file';
|
|
5
|
+
import type { FieldSymbol, ModelSymbol } from '../symbol-table';
|
|
6
|
+
import type { ExpressionAst } from '../syntax/ast/expressions';
|
|
7
|
+
|
|
8
|
+
export type AttributeLevel = 'field' | 'model' | 'block';
|
|
9
|
+
|
|
10
|
+
export interface ArgType<T> {
|
|
11
|
+
readonly kind: string;
|
|
12
|
+
readonly label: string;
|
|
13
|
+
// phantom carrier for `T`; never read at runtime.
|
|
14
|
+
readonly _out?: T;
|
|
15
|
+
parse(arg: ExpressionAst, ctx: InterpretCtx): Result<T, readonly PslDiagnostic[]>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface InterpretCtx {
|
|
19
|
+
readonly level: AttributeLevel;
|
|
20
|
+
readonly sourceId: string;
|
|
21
|
+
readonly sourceFile: SourceFile;
|
|
22
|
+
readonly selfModel: ModelSymbol;
|
|
23
|
+
resolveReferencedModel(): ModelSymbol | undefined;
|
|
24
|
+
readonly field?: FieldSymbol;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface OptionalArgType<T> extends ArgType<T> {
|
|
28
|
+
// the engine detects optionality by checking for this marker (`'optional' in param`).
|
|
29
|
+
readonly optional: true;
|
|
30
|
+
readonly hasDefault: boolean;
|
|
31
|
+
readonly defaultValue?: T;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type Param<T> = ArgType<T>;
|
|
35
|
+
|
|
36
|
+
export interface PositionalParam<T = unknown> {
|
|
37
|
+
readonly key: string;
|
|
38
|
+
readonly type: Param<T>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AttributeSpec<Out> {
|
|
42
|
+
readonly level: AttributeLevel;
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly positional: readonly PositionalParam[];
|
|
45
|
+
readonly named: Readonly<Record<string, Param<unknown>>>;
|
|
46
|
+
readonly refine?: (parsed: Out, ctx: InterpretCtx) => readonly PslDiagnostic[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type OutOf<P> = P extends ArgType<infer T> ? T : never;
|
|
50
|
+
|
|
51
|
+
export type NamedOut<N extends Record<string, Param<unknown>>> = Simplify<
|
|
52
|
+
{ [K in keyof N as N[K] extends OptionalArgType<unknown> ? never : K]: OutOf<N[K]> } & {
|
|
53
|
+
[K in keyof N as N[K] extends OptionalArgType<unknown> ? K : never]?: OutOf<N[K]>;
|
|
54
|
+
}
|
|
55
|
+
>;
|
|
56
|
+
|
|
57
|
+
type PosEntryObject<E extends PositionalParam> =
|
|
58
|
+
E['type'] extends OptionalArgType<unknown>
|
|
59
|
+
? { [K in E['key']]?: OutOf<E['type']> }
|
|
60
|
+
: { [K in E['key']]: OutOf<E['type']> };
|
|
61
|
+
|
|
62
|
+
export type PosOut<Pos extends readonly PositionalParam[]> = Simplify<
|
|
63
|
+
UnionToIntersection<{ [I in keyof Pos]: PosEntryObject<Pos[I]> }[number]>
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export type AttributeOut<
|
|
67
|
+
Pos extends readonly PositionalParam[],
|
|
68
|
+
Named extends Record<string, Param<unknown>>,
|
|
69
|
+
> = Simplify<PosOut<Pos> & NamedOut<Named>>;
|
|
70
|
+
|
|
71
|
+
// `S` is unconstrained on purpose: `refine` makes `Out` contravariant, so a bound like `S extends AttributeSpec<unknown>` would reject every spec that uses `refine`.
|
|
72
|
+
export type InferAttr<S> = S extends AttributeSpec<infer Out> ? Out : never;
|
package/src/exports/index.ts
CHANGED
|
@@ -36,6 +36,30 @@ export {
|
|
|
36
36
|
namespacePslExtensionBlocks,
|
|
37
37
|
} from '@prisma-next/framework-components/psl-ast';
|
|
38
38
|
export { getPositionalArgument, parseQuotedStringLiteral } from '../attribute-helpers';
|
|
39
|
+
export type { FieldRefArgType, FieldRefScope } from '../attribute-spec/combinators/field-ref';
|
|
40
|
+
export { fieldRef } from '../attribute-spec/combinators/field-ref';
|
|
41
|
+
export { identifier } from '../attribute-spec/combinators/identifier';
|
|
42
|
+
export type { ListOptions } from '../attribute-spec/combinators/list';
|
|
43
|
+
export { list } from '../attribute-spec/combinators/list';
|
|
44
|
+
export { oneOf } from '../attribute-spec/combinators/one-of';
|
|
45
|
+
export { str } from '../attribute-spec/combinators/str';
|
|
46
|
+
export { fieldAttribute } from '../attribute-spec/field-attribute';
|
|
47
|
+
export { interpretAttribute } from '../attribute-spec/interpret';
|
|
48
|
+
export { optional } from '../attribute-spec/optional';
|
|
49
|
+
export type {
|
|
50
|
+
ArgType,
|
|
51
|
+
AttributeLevel,
|
|
52
|
+
AttributeOut,
|
|
53
|
+
AttributeSpec,
|
|
54
|
+
InferAttr,
|
|
55
|
+
InterpretCtx,
|
|
56
|
+
NamedOut,
|
|
57
|
+
OptionalArgType,
|
|
58
|
+
OutOf,
|
|
59
|
+
Param,
|
|
60
|
+
PositionalParam,
|
|
61
|
+
PosOut,
|
|
62
|
+
} from '../attribute-spec/types';
|
|
39
63
|
export { findBlockDescriptor, validateExtensionBlockFromSymbol } from '../extension-block';
|
|
40
64
|
export {
|
|
41
65
|
keywordPslSpan,
|