@prisma-next/sql-contract-ts 0.3.0-dev.134 → 0.3.0-dev.135

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.
@@ -0,0 +1,139 @@
1
+ import type {
2
+ AuthoringFieldNamespace,
3
+ AuthoringFieldPresetDescriptor,
4
+ AuthoringTypeNamespace,
5
+ } from '@prisma-next/contract/framework-components';
6
+ import {
7
+ instantiateAuthoringTypeConstructor,
8
+ isAuthoringFieldPresetDescriptor,
9
+ isAuthoringTypeConstructorDescriptor,
10
+ validateAuthoringHelperArguments,
11
+ } from '@prisma-next/contract/framework-components';
12
+ import type { StorageTypeInstance } from '@prisma-next/sql-contract/types';
13
+
14
+ export type RuntimeNamedConstraintSpec = {
15
+ readonly name?: string;
16
+ };
17
+
18
+ export function isNamedConstraintOptionsLike(value: unknown): value is RuntimeNamedConstraintSpec {
19
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
20
+ return false;
21
+ }
22
+
23
+ const keys = Object.keys(value as Record<string, unknown>);
24
+ if (keys.some((key) => key !== 'name')) {
25
+ return false;
26
+ }
27
+
28
+ const name = (value as { readonly name?: unknown }).name;
29
+ return name === undefined || typeof name === 'string';
30
+ }
31
+
32
+ const blockedSegments = new Set(['__proto__', 'constructor', 'prototype']);
33
+
34
+ function assertSafeHelperKey(key: string, path: readonly string[]): void {
35
+ if (blockedSegments.has(key)) {
36
+ throw new Error(
37
+ `Invalid authoring helper "${[...path, key].join('.')}". Helper path segments must not use "${key}".`,
38
+ );
39
+ }
40
+ }
41
+
42
+ export function createTypeHelpersFromNamespace(
43
+ namespace: AuthoringTypeNamespace,
44
+ path: readonly string[] = [],
45
+ ): Record<string, unknown> {
46
+ const helpers: Record<string, unknown> = {};
47
+
48
+ for (const [key, value] of Object.entries(namespace)) {
49
+ assertSafeHelperKey(key, path);
50
+ const currentPath = [...path, key];
51
+
52
+ if (isAuthoringTypeConstructorDescriptor(value)) {
53
+ const helperPath = currentPath.join('.');
54
+ helpers[key] = (...args: readonly unknown[]) => {
55
+ validateAuthoringHelperArguments(helperPath, value.args, args);
56
+ return instantiateAuthoringTypeConstructor(value, args) as StorageTypeInstance;
57
+ };
58
+ continue;
59
+ }
60
+
61
+ helpers[key] = createTypeHelpersFromNamespace(value as AuthoringTypeNamespace, currentPath);
62
+ }
63
+
64
+ return helpers;
65
+ }
66
+
67
+ export function createFieldPresetHelper<Result>(options: {
68
+ readonly helperPath: string;
69
+ readonly descriptor: AuthoringFieldPresetDescriptor;
70
+ readonly build: (options: {
71
+ readonly args: readonly unknown[];
72
+ readonly namedConstraintOptions?: RuntimeNamedConstraintSpec;
73
+ }) => Result;
74
+ }): (...rawArgs: readonly unknown[]) => Result {
75
+ return (...rawArgs: readonly unknown[]) => {
76
+ const acceptsNamedConstraintOptions =
77
+ options.descriptor.output.id === true || options.descriptor.output.unique === true;
78
+ const declaredArguments = options.descriptor.args ?? [];
79
+
80
+ if (acceptsNamedConstraintOptions && rawArgs.length > declaredArguments.length + 1) {
81
+ throw new Error(
82
+ `${options.helperPath} expects at most ${declaredArguments.length + 1} argument(s), received ${rawArgs.length}`,
83
+ );
84
+ }
85
+
86
+ let args = rawArgs;
87
+ let namedConstraintOptions: RuntimeNamedConstraintSpec | undefined;
88
+
89
+ if (acceptsNamedConstraintOptions && rawArgs.length === declaredArguments.length + 1) {
90
+ const maybeNamedConstraintOptions = rawArgs.at(-1);
91
+ if (!isNamedConstraintOptionsLike(maybeNamedConstraintOptions)) {
92
+ throw new Error(
93
+ `${options.helperPath} accepts an optional trailing { name?: string } constraint options object`,
94
+ );
95
+ }
96
+ namedConstraintOptions = maybeNamedConstraintOptions;
97
+ args = rawArgs.slice(0, -1);
98
+ }
99
+
100
+ validateAuthoringHelperArguments(options.helperPath, options.descriptor.args, args);
101
+
102
+ return options.build({
103
+ args,
104
+ ...(namedConstraintOptions ? { namedConstraintOptions } : {}),
105
+ });
106
+ };
107
+ }
108
+
109
+ export function createFieldHelpersFromNamespace(
110
+ namespace: AuthoringFieldNamespace,
111
+ createLeafHelper: (options: {
112
+ readonly helperPath: string;
113
+ readonly descriptor: AuthoringFieldPresetDescriptor;
114
+ }) => (...rawArgs: readonly unknown[]) => unknown,
115
+ path: readonly string[] = [],
116
+ ): Record<string, unknown> {
117
+ const helpers: Record<string, unknown> = {};
118
+
119
+ for (const [key, value] of Object.entries(namespace)) {
120
+ assertSafeHelperKey(key, path);
121
+ const currentPath = [...path, key];
122
+
123
+ if (isAuthoringFieldPresetDescriptor(value)) {
124
+ helpers[key] = createLeafHelper({
125
+ helperPath: currentPath.join('.'),
126
+ descriptor: value,
127
+ });
128
+ continue;
129
+ }
130
+
131
+ helpers[key] = createFieldHelpersFromNamespace(
132
+ value as AuthoringFieldNamespace,
133
+ createLeafHelper,
134
+ currentPath,
135
+ );
136
+ }
137
+
138
+ return helpers;
139
+ }
@@ -0,0 +1,168 @@
1
+ import type {
2
+ AuthoringArgumentDescriptor,
3
+ AuthoringFieldPresetDescriptor,
4
+ } from '@prisma-next/contract/framework-components';
5
+ import type { ScalarFieldBuilder, ScalarFieldState } from './staged-contract-dsl';
6
+
7
+ export type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (
8
+ value: infer I,
9
+ ) => void
10
+ ? I
11
+ : never;
12
+
13
+ export type NamedConstraintSpec<Name extends string | undefined = string | undefined> = {
14
+ readonly name?: Name;
15
+ };
16
+
17
+ export type NamedConstraintState<
18
+ Enabled extends boolean,
19
+ Name extends string | undefined = undefined,
20
+ > = Enabled extends true ? NamedConstraintSpec<Name> : undefined;
21
+
22
+ export type OptionalObjectArgumentKeys<
23
+ Properties extends Record<string, AuthoringArgumentDescriptor>,
24
+ > = {
25
+ readonly [K in keyof Properties]: Properties[K] extends { readonly optional: true } ? K : never;
26
+ }[keyof Properties];
27
+
28
+ export type ObjectArgumentType<Properties extends Record<string, AuthoringArgumentDescriptor>> = {
29
+ readonly [K in Exclude<
30
+ keyof Properties,
31
+ OptionalObjectArgumentKeys<Properties>
32
+ >]: ArgTypeFromDescriptor<Properties[K]>;
33
+ } & {
34
+ readonly [K in OptionalObjectArgumentKeys<Properties>]?: ArgTypeFromDescriptor<Properties[K]>;
35
+ };
36
+
37
+ export type ArgTypeFromDescriptor<Arg extends AuthoringArgumentDescriptor> = Arg extends {
38
+ readonly kind: 'string';
39
+ }
40
+ ? string
41
+ : Arg extends { readonly kind: 'number' }
42
+ ? number
43
+ : Arg extends { readonly kind: 'stringArray' }
44
+ ? readonly string[]
45
+ : Arg extends {
46
+ readonly kind: 'object';
47
+ readonly properties: infer Properties extends Record<
48
+ string,
49
+ AuthoringArgumentDescriptor
50
+ >;
51
+ }
52
+ ? ObjectArgumentType<Properties>
53
+ : never;
54
+
55
+ export type TupleFromArgumentDescriptors<Args extends readonly AuthoringArgumentDescriptor[]> = {
56
+ readonly [K in keyof Args]: Args[K] extends AuthoringArgumentDescriptor
57
+ ? ArgTypeFromDescriptor<Args[K]>
58
+ : never;
59
+ };
60
+
61
+ export type SupportsNamedConstraintOptions<Descriptor extends AuthoringFieldPresetDescriptor> =
62
+ Descriptor['output'] extends { readonly id: true }
63
+ ? true
64
+ : Descriptor['output'] extends { readonly unique: true }
65
+ ? true
66
+ : false;
67
+
68
+ export type ResolveTemplateValue<Template, Args extends readonly unknown[]> = Template extends {
69
+ readonly kind: 'arg';
70
+ readonly index: infer Index extends number;
71
+ readonly path?: infer Path extends readonly string[] | undefined;
72
+ readonly default?: infer Default;
73
+ }
74
+ ? ResolveTemplateArgValue<Args[Index], Path, Default, Args>
75
+ : Template extends readonly unknown[]
76
+ ? { readonly [K in keyof Template]: ResolveTemplateValue<Template[K], Args> }
77
+ : Template extends Record<string, unknown>
78
+ ? { readonly [K in keyof Template]: ResolveTemplateValue<Template[K], Args> }
79
+ : Template;
80
+
81
+ type ResolveTemplatePathValue<
82
+ Value,
83
+ Path extends readonly string[] | undefined,
84
+ > = Path extends readonly [infer Segment extends string, ...infer Rest extends readonly string[]]
85
+ ? Segment extends keyof NonNullable<Value>
86
+ ? ResolveTemplatePathValue<NonNullable<Value>[Segment], Rest>
87
+ : never
88
+ : Value;
89
+
90
+ type ResolveTemplateDefaultValue<
91
+ Value,
92
+ Default,
93
+ Args extends readonly unknown[],
94
+ > = Default extends undefined
95
+ ? Value
96
+ : [Value] extends [never]
97
+ ? ResolveTemplateValue<Default, Args>
98
+ : undefined extends Value
99
+ ? Exclude<Value, undefined> | ResolveTemplateValue<Default, Args>
100
+ : Value;
101
+
102
+ type ResolveTemplateArgValue<
103
+ Value,
104
+ Path extends readonly string[] | undefined,
105
+ Default,
106
+ Args extends readonly unknown[],
107
+ > = ResolveTemplateDefaultValue<ResolveTemplatePathValue<Value, Path>, Default, Args>;
108
+
109
+ export type FieldBuilderFromPresetDescriptor<
110
+ Descriptor extends AuthoringFieldPresetDescriptor,
111
+ Args extends readonly unknown[] = readonly [],
112
+ ConstraintName extends string | undefined = undefined,
113
+ > = ScalarFieldBuilder<
114
+ ScalarFieldState<
115
+ ResolveTemplateValue<Descriptor['output']['codecId'], Args> extends string
116
+ ? ResolveTemplateValue<Descriptor['output']['codecId'], Args>
117
+ : string,
118
+ undefined,
119
+ ResolveTemplateValue<Descriptor['output']['nullable'], Args> extends true ? true : false,
120
+ undefined,
121
+ NamedConstraintState<
122
+ ResolveTemplateValue<Descriptor['output']['id'], Args> extends true ? true : false,
123
+ ConstraintName
124
+ >,
125
+ NamedConstraintState<
126
+ ResolveTemplateValue<Descriptor['output']['unique'], Args> extends true ? true : false,
127
+ ConstraintName
128
+ >
129
+ >
130
+ >;
131
+
132
+ export type FieldHelperFunctionWithoutNamedConstraint<
133
+ Descriptor extends AuthoringFieldPresetDescriptor,
134
+ > = Descriptor extends {
135
+ readonly args: infer Args extends readonly AuthoringArgumentDescriptor[];
136
+ }
137
+ ? <const Params extends TupleFromArgumentDescriptors<Args>>(
138
+ ...args: Params
139
+ ) => FieldBuilderFromPresetDescriptor<Descriptor, Params>
140
+ : () => FieldBuilderFromPresetDescriptor<Descriptor, readonly []>;
141
+
142
+ export type FieldHelperFunctionWithNamedConstraint<
143
+ Descriptor extends AuthoringFieldPresetDescriptor,
144
+ > = Descriptor extends {
145
+ readonly args: infer Args extends readonly AuthoringArgumentDescriptor[];
146
+ }
147
+ ? <
148
+ const Params extends TupleFromArgumentDescriptors<Args>,
149
+ const Name extends string | undefined = undefined,
150
+ >(
151
+ ...args: [...params: Params, options?: NamedConstraintSpec<Name>]
152
+ ) => FieldBuilderFromPresetDescriptor<Descriptor, Params, Name>
153
+ : <const Name extends string | undefined = undefined>(
154
+ options?: NamedConstraintSpec<Name>,
155
+ ) => FieldBuilderFromPresetDescriptor<Descriptor, readonly [], Name>;
156
+
157
+ export type FieldHelperFunction<Descriptor extends AuthoringFieldPresetDescriptor> =
158
+ SupportsNamedConstraintOptions<Descriptor> extends true
159
+ ? FieldHelperFunctionWithNamedConstraint<Descriptor>
160
+ : FieldHelperFunctionWithoutNamedConstraint<Descriptor>;
161
+
162
+ export type FieldHelpersFromNamespace<Namespace> = {
163
+ readonly [K in keyof Namespace]: Namespace[K] extends AuthoringFieldPresetDescriptor
164
+ ? FieldHelperFunction<Namespace[K]>
165
+ : Namespace[K] extends Record<string, unknown>
166
+ ? FieldHelpersFromNamespace<Namespace[K]>
167
+ : never;
168
+ };
@@ -0,0 +1,254 @@
1
+ import type {
2
+ AuthoringArgumentDescriptor,
3
+ AuthoringFieldNamespace,
4
+ AuthoringTypeConstructorDescriptor,
5
+ AuthoringTypeNamespace,
6
+ ExtensionPackRef,
7
+ FamilyPackRef,
8
+ TargetPackRef,
9
+ } from '@prisma-next/contract/framework-components';
10
+ import {
11
+ isAuthoringFieldPresetDescriptor,
12
+ isAuthoringTypeConstructorDescriptor,
13
+ } from '@prisma-next/contract/framework-components';
14
+ import {
15
+ createFieldHelpersFromNamespace,
16
+ createFieldPresetHelper,
17
+ createTypeHelpersFromNamespace,
18
+ } from './authoring-helper-runtime';
19
+ import type {
20
+ FieldHelpersFromNamespace,
21
+ ResolveTemplateValue,
22
+ TupleFromArgumentDescriptors,
23
+ UnionToIntersection,
24
+ } from './authoring-type-utils';
25
+ import { buildFieldPreset, field, model, rel } from './staged-contract-dsl';
26
+
27
+ type ExtractTypeNamespaceFromPack<Pack> = Pack extends {
28
+ readonly authoring?: { readonly type?: infer Namespace extends AuthoringTypeNamespace };
29
+ }
30
+ ? Namespace
31
+ : Record<never, never>;
32
+
33
+ type ExtractFieldNamespaceFromPack<Pack> = Pack extends {
34
+ readonly authoring?: { readonly field?: infer Namespace extends AuthoringFieldNamespace };
35
+ }
36
+ ? Namespace
37
+ : Record<never, never>;
38
+
39
+ type MergeExtensionTypeNamespaces<ExtensionPacks> =
40
+ ExtensionPacks extends Record<string, unknown>
41
+ ? keyof ExtensionPacks extends never
42
+ ? Record<never, never>
43
+ : UnionToIntersection<
44
+ {
45
+ [K in keyof ExtensionPacks]: ExtractTypeNamespaceFromPack<ExtensionPacks[K]>;
46
+ }[keyof ExtensionPacks]
47
+ >
48
+ : Record<never, never>;
49
+
50
+ type MergeExtensionFieldNamespaces<ExtensionPacks> =
51
+ ExtensionPacks extends Record<string, unknown>
52
+ ? keyof ExtensionPacks extends never
53
+ ? Record<never, never>
54
+ : UnionToIntersection<
55
+ {
56
+ [K in keyof ExtensionPacks]: ExtractFieldNamespaceFromPack<ExtensionPacks[K]>;
57
+ }[keyof ExtensionPacks]
58
+ >
59
+ : Record<never, never>;
60
+
61
+ type StorageTypeFromDescriptor<
62
+ Descriptor extends AuthoringTypeConstructorDescriptor,
63
+ Args extends readonly unknown[],
64
+ > = {
65
+ readonly codecId: ResolveTemplateValue<Descriptor['output']['codecId'], Args>;
66
+ readonly nativeType: ResolveTemplateValue<Descriptor['output']['nativeType'], Args>;
67
+ } & (Descriptor['output'] extends {
68
+ readonly typeParams: infer TypeParams extends Record<string, unknown>;
69
+ }
70
+ ? {
71
+ readonly typeParams: ResolveTemplateValue<TypeParams, Args>;
72
+ }
73
+ : Record<never, never>);
74
+
75
+ type TypeHelperFunction<Descriptor extends AuthoringTypeConstructorDescriptor> =
76
+ Descriptor extends { readonly args: infer Args extends readonly AuthoringArgumentDescriptor[] }
77
+ ? <const Params extends TupleFromArgumentDescriptors<Args>>(
78
+ ...args: Params
79
+ ) => StorageTypeFromDescriptor<Descriptor, Params>
80
+ : () => StorageTypeFromDescriptor<Descriptor, readonly []>;
81
+
82
+ type TypeHelpersFromNamespace<Namespace> = {
83
+ readonly [K in keyof Namespace]: Namespace[K] extends AuthoringTypeConstructorDescriptor
84
+ ? TypeHelperFunction<Namespace[K]>
85
+ : Namespace[K] extends Record<string, unknown>
86
+ ? TypeHelpersFromNamespace<Namespace[K]>
87
+ : never;
88
+ };
89
+
90
+ type CoreFieldHelpers = Pick<typeof field, 'column' | 'generated' | 'namedType'>;
91
+
92
+ export type ComposedAuthoringHelpers<
93
+ Family extends FamilyPackRef<string>,
94
+ Target extends TargetPackRef<'sql', string>,
95
+ ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined,
96
+ > = {
97
+ readonly field: CoreFieldHelpers &
98
+ FieldHelpersFromNamespace<
99
+ ExtractFieldNamespaceFromPack<Family> &
100
+ ExtractFieldNamespaceFromPack<Target> &
101
+ MergeExtensionFieldNamespaces<ExtensionPacks>
102
+ >;
103
+ readonly model: typeof model;
104
+ readonly rel: typeof rel;
105
+ readonly type: TypeHelpersFromNamespace<
106
+ ExtractTypeNamespaceFromPack<Family> &
107
+ ExtractTypeNamespaceFromPack<Target> &
108
+ MergeExtensionTypeNamespaces<ExtensionPacks>
109
+ >;
110
+ };
111
+
112
+ function extractTypeNamespace<Pack>(pack: Pack): ExtractTypeNamespaceFromPack<Pack> {
113
+ return ((pack as { readonly authoring?: { readonly type?: unknown } }).authoring?.type ??
114
+ {}) as ExtractTypeNamespaceFromPack<Pack>;
115
+ }
116
+
117
+ function extractFieldNamespace<Pack>(pack: Pack): ExtractFieldNamespaceFromPack<Pack> {
118
+ return ((pack as { readonly authoring?: { readonly field?: unknown } }).authoring?.field ??
119
+ {}) as ExtractFieldNamespaceFromPack<Pack>;
120
+ }
121
+
122
+ function mergeHelperNamespaces(
123
+ target: Record<string, unknown>,
124
+ source: Record<string, unknown>,
125
+ path: readonly string[],
126
+ leafGuard: (value: unknown) => boolean,
127
+ label: string,
128
+ ): void {
129
+ const assertSafePath = (currentPath: readonly string[]) => {
130
+ const blockedSegment = currentPath.find(
131
+ (segment) => segment === '__proto__' || segment === 'constructor' || segment === 'prototype',
132
+ );
133
+ if (blockedSegment) {
134
+ throw new Error(
135
+ `Invalid authoring ${label} helper "${currentPath.join('.')}". Helper path segments must not use "${blockedSegment}".`,
136
+ );
137
+ }
138
+ };
139
+
140
+ for (const [key, sourceValue] of Object.entries(source)) {
141
+ const currentPath = [...path, key];
142
+ assertSafePath(currentPath);
143
+ const hasExistingValue = Object.hasOwn(target, key);
144
+ const existingValue = hasExistingValue ? target[key] : undefined;
145
+
146
+ if (!hasExistingValue) {
147
+ target[key] = sourceValue;
148
+ continue;
149
+ }
150
+
151
+ const existingIsLeaf = leafGuard(existingValue);
152
+ const sourceIsLeaf = leafGuard(sourceValue);
153
+
154
+ if (existingIsLeaf || sourceIsLeaf) {
155
+ throw new Error(
156
+ `Duplicate authoring ${label} helper "${currentPath.join('.')}". Helper names must be unique across composed packs.`,
157
+ );
158
+ }
159
+
160
+ mergeHelperNamespaces(
161
+ existingValue as Record<string, unknown>,
162
+ sourceValue as Record<string, unknown>,
163
+ currentPath,
164
+ leafGuard,
165
+ label,
166
+ );
167
+ }
168
+ }
169
+
170
+ type AuthoringComponent = {
171
+ readonly authoring?: { readonly type?: unknown; readonly field?: unknown };
172
+ };
173
+
174
+ function composeTypeNamespace(components: readonly AuthoringComponent[]): AuthoringTypeNamespace {
175
+ const merged: Record<string, unknown> = {};
176
+ for (const component of components) {
177
+ const ns = extractTypeNamespace(component);
178
+ if (Object.keys(ns).length > 0) {
179
+ mergeHelperNamespaces(merged, ns, [], isAuthoringTypeConstructorDescriptor, 'type');
180
+ }
181
+ }
182
+ return merged as AuthoringTypeNamespace;
183
+ }
184
+
185
+ function composeFieldNamespace(components: readonly AuthoringComponent[]): AuthoringFieldNamespace {
186
+ const merged: Record<string, unknown> = {};
187
+ for (const component of components) {
188
+ const ns = extractFieldNamespace(component);
189
+ if (Object.keys(ns).length > 0) {
190
+ mergeHelperNamespaces(merged, ns, [], isAuthoringFieldPresetDescriptor, 'field');
191
+ }
192
+ }
193
+ return merged as AuthoringFieldNamespace;
194
+ }
195
+
196
+ function createComposedFieldHelpers(
197
+ components: readonly AuthoringComponent[],
198
+ ): CoreFieldHelpers & Record<string, unknown> {
199
+ const helperNamespace = createFieldHelpersFromNamespace(
200
+ composeFieldNamespace(components),
201
+ ({ helperPath, descriptor }) =>
202
+ createFieldPresetHelper({
203
+ helperPath,
204
+ descriptor,
205
+ build: ({ args, namedConstraintOptions }) =>
206
+ buildFieldPreset(descriptor, args, namedConstraintOptions),
207
+ }),
208
+ );
209
+ const coreFieldHelpers = {
210
+ column: field.column,
211
+ generated: field.generated,
212
+ namedType: field.namedType,
213
+ } satisfies CoreFieldHelpers;
214
+
215
+ const coreHelperNames = new Set(Object.keys(coreFieldHelpers));
216
+ for (const helperName of Object.keys(helperNamespace)) {
217
+ if (coreHelperNames.has(helperName)) {
218
+ throw new Error(
219
+ `Duplicate authoring field helper "${helperName}". Core field helpers reserve that name.`,
220
+ );
221
+ }
222
+ }
223
+
224
+ return {
225
+ ...coreFieldHelpers,
226
+ ...helperNamespace,
227
+ };
228
+ }
229
+
230
+ export function createComposedAuthoringHelpers<
231
+ Family extends FamilyPackRef<string>,
232
+ Target extends TargetPackRef<'sql', string>,
233
+ ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined,
234
+ >(options: {
235
+ readonly family: Family;
236
+ readonly target: Target;
237
+ readonly extensionPacks?: ExtensionPacks;
238
+ }): ComposedAuthoringHelpers<Family, Target, ExtensionPacks> {
239
+ const extensionValues: readonly ExtensionPackRef<'sql', string>[] = Object.values(
240
+ (options.extensionPacks ?? {}) as Record<string, ExtensionPackRef<'sql', string>>,
241
+ );
242
+ const components: readonly AuthoringComponent[] = [
243
+ options.family,
244
+ options.target,
245
+ ...extensionValues,
246
+ ];
247
+
248
+ return {
249
+ field: createComposedFieldHelpers(components),
250
+ model,
251
+ rel,
252
+ type: createTypeHelpersFromNamespace(composeTypeNamespace(components)),
253
+ } as ComposedAuthoringHelpers<Family, Target, ExtensionPacks>;
254
+ }