@aws-amplify/data-schema 1.1.4 → 1.1.6
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/cjs/CustomOperation.js +46 -0
- package/dist/cjs/CustomOperation.js.map +1 -1
- package/dist/cjs/CustomType.js +32 -0
- package/dist/cjs/CustomType.js.map +1 -1
- package/dist/cjs/Handler.js +62 -0
- package/dist/cjs/Handler.js.map +1 -1
- package/dist/cjs/ModelRelationalField.js +82 -3
- package/dist/cjs/ModelRelationalField.js.map +1 -1
- package/dist/cjs/util/Brand.js +4 -4
- package/dist/cjs/util/Brand.js.map +1 -1
- package/dist/cjs/util/usedMethods.js +4 -0
- package/dist/cjs/util/usedMethods.js.map +1 -0
- package/dist/esm/CustomOperation.d.ts +49 -3
- package/dist/esm/CustomOperation.mjs +46 -0
- package/dist/esm/CustomOperation.mjs.map +1 -1
- package/dist/esm/CustomType.d.ts +35 -3
- package/dist/esm/CustomType.mjs +32 -0
- package/dist/esm/CustomType.mjs.map +1 -1
- package/dist/esm/EnumType.d.ts +7 -9
- package/dist/esm/Handler.d.ts +62 -0
- package/dist/esm/Handler.mjs +62 -0
- package/dist/esm/Handler.mjs.map +1 -1
- package/dist/esm/MappedTypes/CustomOperations.d.ts +3 -3
- package/dist/esm/MappedTypes/ExtractNonModelTypes.d.ts +4 -4
- package/dist/esm/MappedTypes/ResolveFieldProperties.d.ts +2 -2
- package/dist/esm/MappedTypes/ResolveSchema.d.ts +6 -6
- package/dist/esm/ModelField.d.ts +16 -13
- package/dist/esm/ModelRelationalField.d.ts +83 -4
- package/dist/esm/ModelRelationalField.mjs +82 -3
- package/dist/esm/ModelRelationalField.mjs.map +1 -1
- package/dist/esm/ModelSchema.d.ts +4 -4
- package/dist/esm/ModelType.d.ts +16 -12
- package/dist/esm/RefType.d.ts +1 -1
- package/dist/esm/util/Brand.d.ts +1 -2
- package/dist/esm/util/Brand.mjs +1 -1
- package/dist/esm/util/Brand.mjs.map +1 -1
- package/dist/esm/util/usedMethods.d.ts +4 -0
- package/dist/esm/util/usedMethods.mjs +2 -0
- package/dist/esm/util/usedMethods.mjs.map +1 -0
- package/dist/meta/cjs.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/CustomOperation.ts +49 -7
- package/src/CustomType.ts +36 -8
- package/src/EnumType.ts +16 -22
- package/src/Handler.ts +62 -0
- package/src/MappedTypes/CustomOperations.ts +4 -6
- package/src/MappedTypes/ExtractNonModelTypes.ts +39 -40
- package/src/MappedTypes/ResolveFieldProperties.ts +2 -2
- package/src/MappedTypes/ResolveSchema.ts +18 -21
- package/src/ModelField.ts +34 -19
- package/src/ModelRelationalField.ts +83 -4
- package/src/ModelSchema.ts +8 -12
- package/src/ModelType.ts +30 -34
- package/src/RefType.ts +1 -1
- package/src/SchemaProcessor.ts +21 -41
- package/src/util/Brand.ts +1 -1
- package/src/util/usedMethods.ts +5 -0
package/src/CustomOperation.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { SetTypeSubArg } from '@aws-amplify/data-schema-types';
|
|
2
2
|
import { Brand, brand } from './util';
|
|
3
|
-
|
|
4
|
-
import { ModelField, InternalField } from './ModelField';
|
|
3
|
+
import { InternalField, type BaseModelField } from './ModelField';
|
|
5
4
|
import {
|
|
6
5
|
AllowModifierForCustomOperation,
|
|
7
6
|
Authorization,
|
|
8
7
|
allowForCustomOperations,
|
|
9
8
|
} from './Authorization';
|
|
10
9
|
import { RefType, InternalRef } from './RefType';
|
|
11
|
-
import { EnumType
|
|
10
|
+
import { EnumType } from './EnumType';
|
|
12
11
|
import { CustomType } from './CustomType';
|
|
13
12
|
import type {
|
|
14
13
|
CustomHandler,
|
|
@@ -25,10 +24,7 @@ type CustomOperationBrand =
|
|
|
25
24
|
| typeof mutationBrand
|
|
26
25
|
| typeof subscriptionBrand;
|
|
27
26
|
|
|
28
|
-
type CustomArguments = Record<
|
|
29
|
-
string,
|
|
30
|
-
ModelField<any, any> | EnumType<EnumTypeParamShape>
|
|
31
|
-
>;
|
|
27
|
+
type CustomArguments = Record<string, BaseModelField | EnumType>;
|
|
32
28
|
|
|
33
29
|
type SubscriptionSource = RefType<any, any>;
|
|
34
30
|
type InternalSubscriptionSource = InternalRef;
|
|
@@ -202,6 +198,26 @@ export type QueryCustomOperation = CustomOperation<
|
|
|
202
198
|
typeof queryBrand
|
|
203
199
|
>;
|
|
204
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Use a custom query to define an API request that will retrieve backend data.
|
|
203
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}
|
|
204
|
+
* @example
|
|
205
|
+
* const schema = a.schema({
|
|
206
|
+
* echo: a
|
|
207
|
+
* .query()
|
|
208
|
+
* .arguments({ content: a.string() })
|
|
209
|
+
* .returns(a.ref('EchoResponse'))
|
|
210
|
+
* .authorization(allow => [allow.publicApiKey()])
|
|
211
|
+
* // 3. set the function has the handler
|
|
212
|
+
* .handler(a.handler.function(echoHandler)),
|
|
213
|
+
*
|
|
214
|
+
* EchoResponse: a.customType({
|
|
215
|
+
* content: a.string(),
|
|
216
|
+
* executionDuration: a.float()
|
|
217
|
+
* }),
|
|
218
|
+
* });
|
|
219
|
+
* @returns a custom query
|
|
220
|
+
*/
|
|
205
221
|
export function query(): CustomOperation<
|
|
206
222
|
{
|
|
207
223
|
arguments: null;
|
|
@@ -222,6 +238,18 @@ export type MutationCustomOperation = CustomOperation<
|
|
|
222
238
|
typeof mutationBrand
|
|
223
239
|
>;
|
|
224
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Use a custom mutation to define an API request that will modify backend data or trigger a subscription event.
|
|
243
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}
|
|
244
|
+
* @example
|
|
245
|
+
* likePost: a
|
|
246
|
+
* .mutation()
|
|
247
|
+
* .arguments({ postId: a.string() })
|
|
248
|
+
* .returns(a.ref('Post'))
|
|
249
|
+
* .authorization(allow => [allow.publicApiKey()])
|
|
250
|
+
* .handler(a.handler.function(echoHandler))
|
|
251
|
+
* @returns a custom mutation
|
|
252
|
+
*/
|
|
225
253
|
export function mutation(): CustomOperation<
|
|
226
254
|
{
|
|
227
255
|
arguments: null;
|
|
@@ -242,6 +270,20 @@ export type SubscriptionCustomOperation = CustomOperation<
|
|
|
242
270
|
typeof subscriptionBrand
|
|
243
271
|
>;
|
|
244
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Define a custom subscription to receive an event when a mutation is triggered
|
|
275
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-subscription/}
|
|
276
|
+
* @example
|
|
277
|
+
* // Subscribe to incoming messages
|
|
278
|
+
* receive: a.subscription()
|
|
279
|
+
* // subscribes to the 'publish' mutation
|
|
280
|
+
* .for(a.ref('publish'))
|
|
281
|
+
* // subscription handler to set custom filters
|
|
282
|
+
* .handler(a.handler.custom({entry: './receive.js'}))
|
|
283
|
+
* // authorization rules as to who can subscribe to the data
|
|
284
|
+
* .authorization(allow => [allow.publicApiKey()]),
|
|
285
|
+
* @returns a custom subscription
|
|
286
|
+
*/
|
|
245
287
|
export function subscription(): CustomOperation<
|
|
246
288
|
{
|
|
247
289
|
arguments: null;
|
package/src/CustomType.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { Brand } from './util';
|
|
2
|
-
import type {
|
|
3
|
-
ModelField,
|
|
4
|
-
InternalField,
|
|
5
|
-
ModelFieldTypeParamOuter,
|
|
6
|
-
} from './ModelField';
|
|
2
|
+
import type { InternalField, BaseModelField } from './ModelField';
|
|
7
3
|
import type { RefType } from './RefType';
|
|
8
|
-
import type { EnumType
|
|
4
|
+
import type { EnumType } from './EnumType';
|
|
9
5
|
|
|
10
6
|
/**
|
|
11
7
|
* Custom Types
|
|
@@ -19,9 +15,9 @@ export type CustomTypeAllowedModifiers = 'authorization' | 'array' | 'required';
|
|
|
19
15
|
|
|
20
16
|
type CustomTypeFields = Record<
|
|
21
17
|
string,
|
|
22
|
-
|
|
|
18
|
+
| BaseModelField
|
|
23
19
|
| RefType<any, any, any>
|
|
24
|
-
| EnumType
|
|
20
|
+
| EnumType
|
|
25
21
|
| CustomType<CustomTypeParamShape>
|
|
26
22
|
>;
|
|
27
23
|
|
|
@@ -60,6 +56,38 @@ function _customType<T extends CustomTypeParamShape>(fields: T['fields']) {
|
|
|
60
56
|
return { data } as InternalCustomType as CustomType<T>;
|
|
61
57
|
}
|
|
62
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Define a custom type. This type represents an inline, typed JSON object.
|
|
61
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/data-modeling/add-fields/#specify-a-custom-field-type}
|
|
62
|
+
* @param fields the fields to be added to the custom type
|
|
63
|
+
* @returns a custom type
|
|
64
|
+
* @example
|
|
65
|
+
* a.schema({
|
|
66
|
+
* Post: a.model({
|
|
67
|
+
* location: a.customType({
|
|
68
|
+
* lat: a.float(),
|
|
69
|
+
* long: a.float(),
|
|
70
|
+
* }),
|
|
71
|
+
* content: a.string(),
|
|
72
|
+
* }),
|
|
73
|
+
* });
|
|
74
|
+
* @example
|
|
75
|
+
* a.schema({
|
|
76
|
+
* Location: a.customType({
|
|
77
|
+
* lat: a.float(),
|
|
78
|
+
* long: a.float(),
|
|
79
|
+
* }),
|
|
80
|
+
*
|
|
81
|
+
* Post: a.model({
|
|
82
|
+
* location: a.ref('Location'),
|
|
83
|
+
* content: a.string(),
|
|
84
|
+
* }),
|
|
85
|
+
*
|
|
86
|
+
* User: a.model({
|
|
87
|
+
* lastKnownLocation: a.ref('Location'),
|
|
88
|
+
* }),
|
|
89
|
+
* });
|
|
90
|
+
*/
|
|
63
91
|
export function customType<T extends CustomTypeFields>(
|
|
64
92
|
fields: T,
|
|
65
93
|
): CustomType<{ fields: T }> {
|
package/src/EnumType.ts
CHANGED
|
@@ -1,36 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { brandSymbol } from './util/Brand.js';
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export type EnumTypeParamShape = {
|
|
9
|
-
type: 'enum';
|
|
10
|
-
values: readonly string[];
|
|
11
|
-
};
|
|
3
|
+
type EnumTypeParamShape<values extends readonly string[] = readonly string[]> =
|
|
4
|
+
{
|
|
5
|
+
type: 'enum';
|
|
6
|
+
values: values;
|
|
7
|
+
};
|
|
12
8
|
|
|
13
|
-
export
|
|
9
|
+
export interface EnumType<values extends readonly string[] = readonly string[]>
|
|
10
|
+
extends EnumTypeParamShape<values> {
|
|
11
|
+
[brandSymbol]: 'enum';
|
|
12
|
+
}
|
|
14
13
|
|
|
15
|
-
function _enum<
|
|
16
|
-
const data:
|
|
14
|
+
function _enum<values extends readonly string[]>(values: values) {
|
|
15
|
+
const data: EnumTypeParamShape = {
|
|
17
16
|
type: 'enum',
|
|
18
17
|
values,
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
return data as EnumType<
|
|
20
|
+
return data as EnumType<values>;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
type EnumTypeArgFactory<Values extends readonly string[]> = {
|
|
25
|
-
type: 'enum';
|
|
26
|
-
values: Values;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
23
|
/**
|
|
30
24
|
* this type param pattern allows us to infer literal type values from the array without using the `as const` suffix
|
|
31
25
|
*/
|
|
32
|
-
export function enumType<
|
|
33
|
-
values:
|
|
26
|
+
export function enumType<const values extends readonly string[]>(
|
|
27
|
+
values: values,
|
|
34
28
|
) {
|
|
35
|
-
return _enum
|
|
29
|
+
return _enum(values);
|
|
36
30
|
}
|
package/src/Handler.ts
CHANGED
|
@@ -92,6 +92,33 @@ export type CustomHandler = { [dataSymbol]: CustomHandlerData } & Brand<
|
|
|
92
92
|
typeof customHandlerBrand
|
|
93
93
|
>;
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Use a custom JavaScript resolver to handle a query, mutation, or subscription.
|
|
97
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/#step-2---configure-custom-business-logic-handler-code}
|
|
98
|
+
* @param customHandler `{ entry: "path-to-javascript-resolver-file.js", dataSource: "Data Source name added via "backend.data.add*DataSoruce(...)"}`
|
|
99
|
+
* @returns A JavaScript resolver attached to the query, mutation, or subscription.
|
|
100
|
+
* @example
|
|
101
|
+
* const schema = a.schema({
|
|
102
|
+
* Post: a.model({
|
|
103
|
+
* content: a.string(),
|
|
104
|
+
* likes: a.integer()
|
|
105
|
+
* .authorization(allow => [allow.authenticated().to(['read'])])
|
|
106
|
+
* }).authorization(allow => [
|
|
107
|
+
* allow.owner(),
|
|
108
|
+
* allow.authenticated().to(['read'])
|
|
109
|
+
* ]),
|
|
110
|
+
*
|
|
111
|
+
* likePost: a
|
|
112
|
+
* .mutation()
|
|
113
|
+
* .arguments({ postId: a.id() })
|
|
114
|
+
* .returns(a.ref('Post'))
|
|
115
|
+
* .authorization(allow => [allow.authenticated()])
|
|
116
|
+
* .handler(a.handler.custom({
|
|
117
|
+
* dataSource: a.ref('Post'),
|
|
118
|
+
* entry: './increment-like.js'
|
|
119
|
+
* }))
|
|
120
|
+
* });
|
|
121
|
+
*/
|
|
95
122
|
function custom(customHandler: CustomHandlerInput): CustomHandler {
|
|
96
123
|
// used to determine caller directory in order to resolve relative path downstream
|
|
97
124
|
const stack = new Error().stack;
|
|
@@ -113,6 +140,41 @@ export type FunctionHandler = {
|
|
|
113
140
|
[dataSymbol]: FunctionHandlerData;
|
|
114
141
|
} & Brand<typeof functionHandlerBrand>;
|
|
115
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Use a function created via `defineFunction` to handle the custom query/mutation/subscription. In your function handler,
|
|
145
|
+
* you can use the `Schema["YOUR_QUERY_OR_MUTATION_NAME"]["functionHandler"]` utility type to type the handler function.
|
|
146
|
+
* @example
|
|
147
|
+
* import {
|
|
148
|
+
* type ClientSchema,
|
|
149
|
+
* a,
|
|
150
|
+
* defineData,
|
|
151
|
+
* defineFunction // 1.Import "defineFunction" to create new functions
|
|
152
|
+
* } from '@aws-amplify/backend';
|
|
153
|
+
*
|
|
154
|
+
* // 2. define a function
|
|
155
|
+
* const echoHandler = defineFunction({
|
|
156
|
+
* entry: './echo-handler/handler.ts'
|
|
157
|
+
* })
|
|
158
|
+
*
|
|
159
|
+
* const schema = a.schema({
|
|
160
|
+
* EchoResponse: a.customType({
|
|
161
|
+
* content: a.string(),
|
|
162
|
+
* executionDuration: a.float()
|
|
163
|
+
* }),
|
|
164
|
+
*
|
|
165
|
+
* echo: a
|
|
166
|
+
* .query()
|
|
167
|
+
* .arguments({ content: a.string() })
|
|
168
|
+
* .returns(a.ref('EchoResponse'))
|
|
169
|
+
* .authorization(allow => [allow.publicApiKey()])
|
|
170
|
+
* // 3. set the function has the handler
|
|
171
|
+
* .handler(a.handler.function(echoHandler))
|
|
172
|
+
* });
|
|
173
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}
|
|
174
|
+
* @param fn A function created via `defineFunction`. Alternatively, you can pass in a "string" of the function name and pass
|
|
175
|
+
* in a corresponding value into the `functionMap` property of defineData.
|
|
176
|
+
* @returns A handler for the query / mutation / subscription
|
|
177
|
+
*/
|
|
116
178
|
function fcn(fn: FunctionHandlerData): FunctionHandler {
|
|
117
179
|
return { [dataSymbol]: fn, ...buildHandler(functionHandlerBrand) };
|
|
118
180
|
}
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
CustomOperation,
|
|
5
5
|
CustomOperationParamShape,
|
|
6
6
|
} from '../CustomOperation';
|
|
7
|
-
import type {
|
|
7
|
+
import type { BaseModelField } from '../ModelField';
|
|
8
8
|
import type { RefType, RefTypeParamShape } from '../RefType';
|
|
9
9
|
import type {
|
|
10
10
|
ResolveFieldRequirements,
|
|
@@ -66,10 +66,8 @@ export type CustomOpArguments<Shape extends CustomOperationParamShape> =
|
|
|
66
66
|
Shape['arguments'] extends null
|
|
67
67
|
? never
|
|
68
68
|
: ResolveFieldRequirements<{
|
|
69
|
-
[FieldName in keyof Shape['arguments']]: Shape['arguments'][FieldName] extends
|
|
70
|
-
infer R
|
|
71
|
-
any,
|
|
72
|
-
any
|
|
69
|
+
[FieldName in keyof Shape['arguments']]: Shape['arguments'][FieldName] extends BaseModelField<
|
|
70
|
+
infer R
|
|
73
71
|
>
|
|
74
72
|
? R
|
|
75
73
|
: never;
|
|
@@ -101,7 +99,7 @@ export type CustomOpReturnType<
|
|
|
101
99
|
NonModelTypes,
|
|
102
100
|
CustomOperations
|
|
103
101
|
>
|
|
104
|
-
: Shape['returnType'] extends
|
|
102
|
+
: Shape['returnType'] extends BaseModelField<infer R>
|
|
105
103
|
? R
|
|
106
104
|
: Shape['returnType'] extends CustomType<infer R>
|
|
107
105
|
?
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UnionToIntersection } from '@aws-amplify/data-schema-types';
|
|
2
2
|
import type { CustomType, CustomTypeParamShape } from '../CustomType';
|
|
3
|
-
import type { EnumType
|
|
3
|
+
import type { EnumType } from '../EnumType';
|
|
4
4
|
import type {
|
|
5
5
|
SchemaTypes,
|
|
6
6
|
ModelAndCustomTypes,
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
import type { ModelType, ModelTypeParamShape } from '../ModelType';
|
|
10
10
|
|
|
11
11
|
export type NonModelTypesShape = {
|
|
12
|
-
enums: Record<string,
|
|
12
|
+
enums: Record<string, any>;
|
|
13
13
|
customTypes: Record<string, any>;
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -51,43 +51,44 @@ export type ExtractNonModelTypes<Schema> = ResolveNonModelFields<
|
|
|
51
51
|
export type ExtractAndFlattenImplicitNonModelTypesFromFields<
|
|
52
52
|
ParentTypeName extends string,
|
|
53
53
|
Fields,
|
|
54
|
-
> =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
FieldProp & string
|
|
67
|
-
>}`]: Fields[FieldProp];
|
|
68
|
-
}
|
|
69
|
-
: // if the field is a CustomType
|
|
70
|
-
FieldType extends CustomType<
|
|
71
|
-
infer CustomTypeShape extends CustomTypeParamShape
|
|
72
|
-
>
|
|
73
|
-
? // recursively extract to the Nested CustomType, and return the
|
|
74
|
-
// merge of the current CustomType and the extracted (if any)
|
|
75
|
-
ExtractAndFlattenImplicitNonModelTypesFromFields<
|
|
76
|
-
`${ParentTypeName}${Capitalize<FieldProp & string>}`,
|
|
77
|
-
CustomTypeShape['fields']
|
|
78
|
-
> & {
|
|
54
|
+
> =
|
|
55
|
+
{
|
|
56
|
+
// loop through the fields - omit the field that's not a non-model type
|
|
57
|
+
[FieldProp in keyof Fields as Fields[FieldProp] extends
|
|
58
|
+
| EnumType
|
|
59
|
+
| CustomType<CustomTypeParamShape>
|
|
60
|
+
? FieldProp
|
|
61
|
+
: never]: (
|
|
62
|
+
x: NonNullable<Fields[FieldProp]> extends infer FieldType
|
|
63
|
+
? // if the filed is a enum extract it as is
|
|
64
|
+
FieldType extends EnumType
|
|
65
|
+
? {
|
|
79
66
|
[Key in `${ParentTypeName}${Capitalize<
|
|
80
67
|
FieldProp & string
|
|
81
68
|
>}`]: Fields[FieldProp];
|
|
82
69
|
}
|
|
83
|
-
:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
70
|
+
: // if the field is a CustomType
|
|
71
|
+
FieldType extends CustomType<
|
|
72
|
+
infer CustomTypeShape extends CustomTypeParamShape
|
|
73
|
+
>
|
|
74
|
+
? // recursively extract to the Nested CustomType, and return the
|
|
75
|
+
// merge of the current CustomType and the extracted (if any)
|
|
76
|
+
ExtractAndFlattenImplicitNonModelTypesFromFields<
|
|
77
|
+
`${ParentTypeName}${Capitalize<FieldProp & string>}`,
|
|
78
|
+
CustomTypeShape['fields']
|
|
79
|
+
> & {
|
|
80
|
+
[Key in `${ParentTypeName}${Capitalize<
|
|
81
|
+
FieldProp & string
|
|
82
|
+
>}`]: Fields[FieldProp];
|
|
83
|
+
}
|
|
84
|
+
: never
|
|
85
|
+
: never,
|
|
86
|
+
) => void;
|
|
87
|
+
} extends Record<string, infer Func>
|
|
88
|
+
? Func extends (x: infer P) => void
|
|
89
|
+
? P // extract the union of all types of the `x` param used above
|
|
90
|
+
: Record<never, never> // return an empty mapped object (nothing got extracted)
|
|
91
|
+
: Record<never, never>; // return an empty mapped object (nothing got extracted)
|
|
91
92
|
|
|
92
93
|
/**
|
|
93
94
|
* Pulls out implicit, i.e. field-level non-model types from `ModelType` and
|
|
@@ -129,12 +130,10 @@ type ResolveNonModelTypes<
|
|
|
129
130
|
ResolvedSchema = SchemaTypes<Schema> & Extracted,
|
|
130
131
|
> = {
|
|
131
132
|
enums: {
|
|
132
|
-
[Model in keyof ResolvedSchema as ResolvedSchema[Model] extends EnumType
|
|
133
|
+
[Model in keyof ResolvedSchema as ResolvedSchema[Model] extends EnumType
|
|
133
134
|
? Model
|
|
134
|
-
: never]: ResolvedSchema[Model] extends EnumType<
|
|
135
|
-
|
|
136
|
-
>
|
|
137
|
-
? R['values'][number]
|
|
135
|
+
: never]: ResolvedSchema[Model] extends EnumType<infer values>
|
|
136
|
+
? values[number]
|
|
138
137
|
: never;
|
|
139
138
|
};
|
|
140
139
|
customTypes: {
|
|
@@ -20,7 +20,7 @@ import type { RefType, RefTypeParamShape } from '../RefType';
|
|
|
20
20
|
import type { NonModelTypesShape } from './ExtractNonModelTypes';
|
|
21
21
|
|
|
22
22
|
import type { CustomType, CustomTypeParamShape } from '../CustomType';
|
|
23
|
-
import type { EnumType
|
|
23
|
+
import type { EnumType } from '../EnumType';
|
|
24
24
|
import type {
|
|
25
25
|
CustomOperation,
|
|
26
26
|
CustomOperationParamShape,
|
|
@@ -214,7 +214,7 @@ type Intersection<
|
|
|
214
214
|
// TODO: this should probably happen in InjectImplicitModelFields instead. Keeping here for now to reduce refactor
|
|
215
215
|
// blast radius
|
|
216
216
|
export type ModelImpliedAuthFields<Schema extends GenericModelSchema<any>> = {
|
|
217
|
-
[ModelKey in keyof Schema['data']['types'] as Schema['data']['types'][ModelKey] extends EnumType
|
|
217
|
+
[ModelKey in keyof Schema['data']['types'] as Schema['data']['types'][ModelKey] extends EnumType
|
|
218
218
|
? never
|
|
219
219
|
: Schema['data']['types'][ModelKey] extends CustomType<CustomTypeParamShape>
|
|
220
220
|
? never
|
|
@@ -5,9 +5,9 @@ import type {
|
|
|
5
5
|
ModelRelationshipTypes,
|
|
6
6
|
RelationTypeFunctionOmitMapping,
|
|
7
7
|
} from '../ModelRelationalField';
|
|
8
|
-
import type {
|
|
8
|
+
import type { BaseModelField } from '../ModelField';
|
|
9
9
|
import type { CustomType, CustomTypeParamShape } from '../CustomType';
|
|
10
|
-
import type { EnumType
|
|
10
|
+
import type { EnumType } from '../EnumType';
|
|
11
11
|
import type { RefType, RefTypeParamShape } from '../RefType';
|
|
12
12
|
import type {
|
|
13
13
|
CustomOperation,
|
|
@@ -17,9 +17,8 @@ import type {
|
|
|
17
17
|
export type ResolveSchema<Schema> = FieldTypes<ModelTypes<SchemaTypes<Schema>>>;
|
|
18
18
|
|
|
19
19
|
// TODO: find better name
|
|
20
|
-
export type SchemaTypes<T> =
|
|
21
|
-
? T['data']['types']
|
|
22
|
-
: never;
|
|
20
|
+
export type SchemaTypes<T> =
|
|
21
|
+
T extends GenericModelSchema<any> ? T['data']['types'] : never;
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* Resolves model types
|
|
@@ -30,7 +29,7 @@ export type SchemaTypes<T> = T extends GenericModelSchema<any>
|
|
|
30
29
|
*/
|
|
31
30
|
export type ModelTypes<Schema> = {
|
|
32
31
|
[Model in keyof Schema as Schema[Model] extends
|
|
33
|
-
| EnumType
|
|
32
|
+
| EnumType
|
|
34
33
|
| CustomType<CustomTypeParamShape>
|
|
35
34
|
| CustomOperation<CustomOperationParamShape, any>
|
|
36
35
|
? never
|
|
@@ -45,14 +44,16 @@ export type ModelTypes<Schema> = {
|
|
|
45
44
|
*/
|
|
46
45
|
export type ModelAndCustomTypes<Schema> = {
|
|
47
46
|
[Model in keyof Schema as Schema[Model] extends
|
|
48
|
-
| EnumType
|
|
47
|
+
| EnumType
|
|
49
48
|
| CustomOperation<CustomOperationParamShape, any>
|
|
50
49
|
? never
|
|
51
|
-
:
|
|
50
|
+
: // TODO: This should use BaseModel, but seems to only work because it relies on
|
|
51
|
+
// omitting extra methods
|
|
52
|
+
Model]: Schema[Model] extends
|
|
53
|
+
| ModelType<any, any>
|
|
54
|
+
| CustomType<CustomTypeParamShape>
|
|
52
55
|
? Schema[Model]
|
|
53
|
-
:
|
|
54
|
-
? Schema[Model]
|
|
55
|
-
: never;
|
|
56
|
+
: never;
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
/**
|
|
@@ -62,11 +63,9 @@ export type ModelAndCustomTypes<Schema> = {
|
|
|
62
63
|
*/
|
|
63
64
|
export type FieldTypes<T> = {
|
|
64
65
|
[ModelProp in keyof T]: {
|
|
65
|
-
[FieldProp in keyof T[ModelProp]]: T[ModelProp][FieldProp] extends
|
|
66
|
+
[FieldProp in keyof T[ModelProp]]: T[ModelProp][FieldProp] extends BaseModelField<
|
|
66
67
|
// Match the most common field type to improve resolving performance
|
|
67
|
-
infer R
|
|
68
|
-
any,
|
|
69
|
-
any
|
|
68
|
+
infer R
|
|
70
69
|
>
|
|
71
70
|
? R
|
|
72
71
|
: T[ModelProp][FieldProp] extends RefType<
|
|
@@ -80,7 +79,7 @@ export type FieldTypes<T> = {
|
|
|
80
79
|
: T[ModelProp][FieldProp] | null
|
|
81
80
|
: // replace non-model types with Ref
|
|
82
81
|
T[ModelProp][FieldProp] extends
|
|
83
|
-
| EnumType
|
|
82
|
+
| EnumType
|
|
84
83
|
| CustomType<CustomTypeParamShape>
|
|
85
84
|
? RefType<{
|
|
86
85
|
link: `${Capitalize<ModelProp & string>}${Capitalize<
|
|
@@ -114,10 +113,8 @@ export type FieldTypes<T> = {
|
|
|
114
113
|
*/
|
|
115
114
|
export type FieldTypesOfCustomType<T> = {
|
|
116
115
|
[CustomTypeName in keyof T]: {
|
|
117
|
-
[FieldProp in keyof T[CustomTypeName]]: T[CustomTypeName][FieldProp] extends
|
|
118
|
-
infer R
|
|
119
|
-
any,
|
|
120
|
-
any
|
|
116
|
+
[FieldProp in keyof T[CustomTypeName]]: T[CustomTypeName][FieldProp] extends BaseModelField<
|
|
117
|
+
infer R
|
|
121
118
|
>
|
|
122
119
|
? R
|
|
123
120
|
: T[CustomTypeName][FieldProp] extends RefType<
|
|
@@ -131,7 +128,7 @@ export type FieldTypesOfCustomType<T> = {
|
|
|
131
128
|
: T[CustomTypeName][FieldProp] | null
|
|
132
129
|
: // replace non-model types with Ref
|
|
133
130
|
T[CustomTypeName][FieldProp] extends
|
|
134
|
-
| EnumType
|
|
131
|
+
| EnumType
|
|
135
132
|
| CustomType<CustomTypeParamShape>
|
|
136
133
|
? RefType<{
|
|
137
134
|
link: `${Capitalize<CustomTypeName & string>}${Capitalize<
|
package/src/ModelField.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { brand } from './util';
|
|
2
2
|
import { AllowModifier, Authorization, allow } from './Authorization';
|
|
3
|
+
import type { methodKeyOf, satisfy } from './util/usedMethods.js';
|
|
4
|
+
import type { brandSymbol } from './util/Brand.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Used to "attach" auth types to ModelField without exposing them on the builder.
|
|
@@ -34,7 +36,7 @@ export enum ModelFieldDataType {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
type FieldMeta = {
|
|
37
|
-
lastInvokedMethod: null |
|
|
39
|
+
lastInvokedMethod: null | methodKeyOf<ModelField>;
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
type FieldData = {
|
|
@@ -67,56 +69,69 @@ export type ArrayField<T> = [T] extends [ModelFieldTypeParamInner]
|
|
|
67
69
|
? Array<T> | null // optional by default
|
|
68
70
|
: never;
|
|
69
71
|
|
|
72
|
+
export type BaseModelField<
|
|
73
|
+
T extends ModelFieldTypeParamOuter = ModelFieldTypeParamOuter,
|
|
74
|
+
> = ModelField<T, UsableModelFieldKey, any>;
|
|
75
|
+
|
|
76
|
+
export type UsableModelFieldKey = satisfy<
|
|
77
|
+
methodKeyOf<ModelField>,
|
|
78
|
+
'required' | 'default' | 'authorization'
|
|
79
|
+
>;
|
|
80
|
+
|
|
70
81
|
/**
|
|
71
82
|
* Public API for the chainable builder methods exposed by Model Field.
|
|
72
83
|
* The type is narrowing e.g., after calling .array() it will be omitted from intellisense suggestions
|
|
73
84
|
*
|
|
74
85
|
* @typeParam T - holds the JS data type of the field
|
|
75
|
-
* @typeParam
|
|
86
|
+
* @typeParam UsedMethod - union of strings representing already-invoked method names. Used to improve Intellisense
|
|
76
87
|
*/
|
|
77
88
|
export type ModelField<
|
|
78
|
-
T extends ModelFieldTypeParamOuter,
|
|
79
|
-
|
|
80
|
-
K extends keyof ModelField<T> = never,
|
|
89
|
+
T extends ModelFieldTypeParamOuter = ModelFieldTypeParamOuter,
|
|
90
|
+
UsedMethod extends UsableModelFieldKey = never,
|
|
81
91
|
Auth = undefined,
|
|
82
92
|
> = Omit<
|
|
83
93
|
{
|
|
94
|
+
// This is a lie. This property is never set at runtime. It's just used to smuggle auth types through.
|
|
95
|
+
[__auth]?: Auth;
|
|
96
|
+
[brandSymbol]: typeof brandName;
|
|
97
|
+
|
|
84
98
|
/**
|
|
85
99
|
* Marks a field as required.
|
|
86
100
|
*/
|
|
87
|
-
required(): ModelField<Required<T>,
|
|
101
|
+
required(): ModelField<Required<T>, UsedMethod | 'required'>;
|
|
88
102
|
// Exclude `optional` after calling array, because both the value and the array itself can be optional
|
|
89
103
|
/**
|
|
90
104
|
* Converts a field type definition to an array of the field type.
|
|
91
105
|
*/
|
|
92
|
-
array(): ModelField<ArrayField<T>, Exclude<
|
|
106
|
+
array(): ModelField<ArrayField<T>, Exclude<UsedMethod, 'required'>>;
|
|
93
107
|
// TODO: should be T, but .array breaks this constraint. Fix later
|
|
94
108
|
/**
|
|
95
109
|
* Sets a default value for the scalar type.
|
|
96
110
|
* @param value the default value
|
|
97
111
|
*/
|
|
98
|
-
default(
|
|
112
|
+
default(
|
|
113
|
+
value: ModelFieldTypeParamOuter,
|
|
114
|
+
): ModelField<T, UsedMethod | 'default'>;
|
|
99
115
|
/**
|
|
100
|
-
* Configures field-level authorization rules. Pass in an array of authorizations `(
|
|
116
|
+
* Configures field-level authorization rules. Pass in an array of authorizations `(allow => allow.____)` to mix and match
|
|
101
117
|
* multiple authorization rules for this field.
|
|
102
118
|
*/
|
|
103
119
|
authorization<AuthRuleType extends Authorization<any, any, any>>(
|
|
104
|
-
callback: (
|
|
105
|
-
|
|
120
|
+
callback: (
|
|
121
|
+
allow: Omit<AllowModifier, 'resource'>,
|
|
122
|
+
) => AuthRuleType | AuthRuleType[],
|
|
123
|
+
): ModelField<T, UsedMethod | 'authorization', AuthRuleType>;
|
|
106
124
|
},
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// This is a lie. This property is never set at runtime. It's just used to smuggle auth types through.
|
|
110
|
-
[__auth]?: Auth;
|
|
111
|
-
} & Brand<typeof brandName>;
|
|
125
|
+
UsedMethod
|
|
126
|
+
>;
|
|
112
127
|
|
|
113
128
|
/**
|
|
114
129
|
* Internal representation of Model Field that exposes the `data` property.
|
|
115
130
|
* Used at buildtime.
|
|
116
131
|
*/
|
|
117
|
-
export
|
|
132
|
+
export interface InternalField extends ModelField {
|
|
118
133
|
data: FieldData;
|
|
119
|
-
}
|
|
134
|
+
}
|
|
120
135
|
|
|
121
136
|
/**
|
|
122
137
|
* Model Field Implementation
|