@aws-amplify/data-schema 1.5.0 → 1.6.0
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 +21 -0
- package/dist/cjs/CustomOperation.js.map +1 -1
- package/dist/cjs/Handler.js +20 -1
- package/dist/cjs/Handler.js.map +1 -1
- package/dist/cjs/SchemaProcessor.js +54 -11
- package/dist/cjs/SchemaProcessor.js.map +1 -1
- package/dist/cjs/runtime/internals/operations/subscription.js +11 -3
- package/dist/cjs/runtime/internals/operations/subscription.js.map +1 -1
- package/dist/esm/ClientSchema/Core/ClientCustomOperations.d.ts +2 -2
- package/dist/esm/CustomOperation.d.ts +16 -4
- package/dist/esm/CustomOperation.mjs +21 -1
- package/dist/esm/CustomOperation.mjs.map +1 -1
- package/dist/esm/Handler.d.ts +57 -9
- package/dist/esm/Handler.mjs +20 -1
- package/dist/esm/Handler.mjs.map +1 -1
- package/dist/esm/SchemaProcessor.mjs +54 -12
- package/dist/esm/SchemaProcessor.mjs.map +1 -1
- package/dist/esm/runtime/internals/operations/subscription.mjs +12 -4
- package/dist/esm/runtime/internals/operations/subscription.mjs.map +1 -1
- package/dist/meta/cjs.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/ClientSchema/Core/ClientCustomOperations.ts +32 -3
- package/src/CustomOperation.ts +68 -5
- package/src/Handler.ts +92 -21
- package/src/SchemaProcessor.ts +73 -23
- package/src/runtime/internals/operations/subscription.ts +18 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.js","sources":["../../../../../src/runtime/internals/operations/subscription.ts"],"sourcesContent":["\"use strict\";\n// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.subscriptionFactory = void 0;\nconst rxjs_1 = require(\"rxjs\");\nconst APIClient_1 = require(\"../APIClient\");\nfunction subscriptionFactory(client, modelIntrospection, model, operation, getInternals) {\n const { name } = model;\n const subscription = (args) => {\n const query = (0, APIClient_1.generateGraphQLDocument)(modelIntrospection, name, operation, args);\n const variables = (0, APIClient_1.buildGraphQLVariables)(model, operation, args, modelIntrospection);\n const auth = (0, APIClient_1.authModeParams)(client, getInternals, args);\n const headers = (0, APIClient_1.getCustomHeaders)(client, getInternals, args?.headers);\n const observable = client.graphql({\n ...auth,\n query,\n variables,\n }, headers);\n return observable.pipe((0, rxjs_1.map)((value) => {\n const [key] = Object.keys(value.data);\n
|
|
1
|
+
{"version":3,"file":"subscription.js","sources":["../../../../../src/runtime/internals/operations/subscription.ts"],"sourcesContent":["\"use strict\";\n// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.subscriptionFactory = void 0;\nconst rxjs_1 = require(\"rxjs\");\nconst APIClient_1 = require(\"../APIClient\");\nfunction subscriptionFactory(client, modelIntrospection, model, operation, getInternals) {\n const { name } = model;\n const subscription = (args) => {\n const query = (0, APIClient_1.generateGraphQLDocument)(modelIntrospection, name, operation, args);\n const variables = (0, APIClient_1.buildGraphQLVariables)(model, operation, args, modelIntrospection);\n const auth = (0, APIClient_1.authModeParams)(client, getInternals, args);\n const headers = (0, APIClient_1.getCustomHeaders)(client, getInternals, args?.headers);\n const observable = client.graphql({\n ...auth,\n query,\n variables,\n }, headers);\n return observable.pipe((0, rxjs_1.map)((value) => {\n const [key] = Object.keys(value.data);\n const data = value.data[key];\n const flattenedResult = (0, APIClient_1.flattenItems)(modelIntrospection, name, data);\n if (flattenedResult === null) {\n return null;\n }\n else if (args?.selectionSet) {\n return flattenedResult;\n }\n else {\n const [initialized] = (0, APIClient_1.initializeModel)(client, name, [flattenedResult], modelIntrospection, auth.authMode, auth.authToken);\n return initialized;\n }\n }));\n };\n return subscription;\n}\nexports.subscriptionFactory = subscriptionFactory;\n"],"names":[],"mappings":";;AACA;AACA;AACA,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9D,OAAO,CAAC,mBAAmB,GAAG,KAAK,CAAC,CAAC;AACrC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAC5C,SAAS,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE;AACzF,IAAI,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;AAC3B,IAAI,MAAM,YAAY,GAAG,CAAC,IAAI,KAAK;AACnC,QAAQ,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,uBAAuB,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAC1G,QAAQ,MAAM,SAAS,GAAG,IAAI,WAAW,CAAC,qBAAqB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;AAC7G,QAAQ,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;AACjF,QAAQ,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,gBAAgB,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC/F,QAAQ,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC;AAC1C,YAAY,GAAG,IAAI;AACnB,YAAY,KAAK;AACjB,YAAY,SAAS;AACrB,SAAS,EAAE,OAAO,CAAC,CAAC;AACpB,QAAQ,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK;AAC1D,YAAY,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAClD,YAAY,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,YAAY,MAAM,eAAe,GAAG,IAAI,WAAW,CAAC,YAAY,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAClG,YAAY,IAAI,eAAe,KAAK,IAAI,EAAE;AAC1C,gBAAgB,OAAO,IAAI,CAAC;AAC5B,aAAa;AACb,iBAAiB,IAAI,IAAI,EAAE,YAAY,EAAE;AACzC,gBAAgB,OAAO,eAAe,CAAC;AACvC,aAAa;AACb,iBAAiB;AACjB,gBAAgB,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AAC3J,gBAAgB,OAAO,WAAW,CAAC;AACnC,aAAa;AACb,SAAS,CAAC,CAAC,CAAC;AACZ,KAAK,CAAC;AACN,IAAI,OAAO,YAAY,CAAC;AACxB,CAAC;AACD,OAAO,CAAC,mBAAmB,GAAG,mBAAmB;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CustomOperationParamShape } from '../../CustomOperation';
|
|
1
|
+
import type { CustomOperationParamShape, UltimateFunctionHandlerAsyncType } from '../../CustomOperation';
|
|
2
2
|
import type { BaseModelField } from '../../ModelField';
|
|
3
3
|
import type { RefType } from '../../RefType';
|
|
4
4
|
import type { ResolveFieldRequirements } from '../../MappedTypes/ResolveFieldProperties';
|
|
@@ -27,7 +27,7 @@ export interface ClientCustomOperation<RefBag extends Record<any, any>, Op exten
|
|
|
27
27
|
* }
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
functionHandler: AppSyncResolverHandler<CustomOpArguments<Op>, LambdaReturnType<CustomOpReturnType<Op, RefBag>>>;
|
|
30
|
+
functionHandler: AppSyncResolverHandler<CustomOpArguments<Op>, Op['handlers'] extends UltimateFunctionHandlerAsyncType ? void : LambdaReturnType<CustomOpReturnType<Op, RefBag>>>;
|
|
31
31
|
/**
|
|
32
32
|
* The `context.arguments` type for lambda function implementations.
|
|
33
33
|
*
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SetTypeSubArg } from '@aws-amplify/data-schema-types';
|
|
2
2
|
import { Brand } from './util';
|
|
3
|
-
import { InternalField, type BaseModelField } from './ModelField';
|
|
3
|
+
import { InternalField, ModelField, type BaseModelField } from './ModelField';
|
|
4
4
|
import { AllowModifierForCustomOperation, Authorization } from './Authorization';
|
|
5
5
|
import { RefType, InternalRef } from './RefType';
|
|
6
6
|
import { EnumType } from './EnumType';
|
|
7
7
|
import { CustomType } from './CustomType';
|
|
8
|
-
import type { CustomHandler, FunctionHandler, HandlerType as Handler } from './Handler';
|
|
8
|
+
import type { AsyncFunctionHandler, CustomHandler, FunctionHandler, HandlerType as Handler } from './Handler';
|
|
9
9
|
import { AiModel, InferenceConfiguration } from './ai/ModelType';
|
|
10
10
|
declare const queryBrand = "queryCustomOperation";
|
|
11
11
|
declare const mutationBrand = "mutationCustomOperation";
|
|
@@ -18,7 +18,13 @@ type InternalSubscriptionSource = InternalRef;
|
|
|
18
18
|
type CustomReturnType = RefType<any> | CustomType<any>;
|
|
19
19
|
type InternalCustomArguments = Record<string, InternalField>;
|
|
20
20
|
type InternalCustomReturnType = InternalRef;
|
|
21
|
-
type HandlerInputType = FunctionHandler[] | CustomHandler[] | Handler;
|
|
21
|
+
type HandlerInputType = FunctionHandler[] | CustomHandler[] | AsyncFunctionHandler[] | HeterogeneousFunctionHandlerWithLastAsync | HeterogeneousFunctionHandlerType | Handler;
|
|
22
|
+
type HeterogeneousFunctionHandlerType = (FunctionHandler | AsyncFunctionHandler)[];
|
|
23
|
+
type HeterogeneousFunctionHandlerWithLastAsync = [
|
|
24
|
+
...HeterogeneousFunctionHandlerType,
|
|
25
|
+
AsyncFunctionHandler
|
|
26
|
+
];
|
|
27
|
+
export type UltimateFunctionHandlerAsyncType = AsyncFunctionHandler | AsyncFunctionHandler[] | HeterogeneousFunctionHandlerWithLastAsync;
|
|
22
28
|
export declare const CustomOperationNames: readonly ["Query", "Mutation", "Subscription", "Generation"];
|
|
23
29
|
type CustomOperationName = (typeof CustomOperationNames)[number];
|
|
24
30
|
type CustomData = {
|
|
@@ -49,7 +55,7 @@ export type CustomOperation<T extends CustomOperationParamShape, K extends keyof
|
|
|
49
55
|
arguments<Arguments extends CustomArguments>(args: Arguments): CustomOperation<SetTypeSubArg<T, 'arguments', Arguments>, K | 'arguments', B>;
|
|
50
56
|
returns<ReturnType extends CustomReturnType>(returnType: ReturnType): CustomOperation<SetTypeSubArg<T, 'returnType', ReturnType>, K | 'returns', B>;
|
|
51
57
|
authorization<AuthRuleType extends Authorization<any, any, any>>(callback: (allow: AllowModifierForCustomOperation) => AuthRuleType | AuthRuleType[]): CustomOperation<SetTypeSubArg<T, 'authorization', AuthRuleType[]>, K | 'authorization', B>;
|
|
52
|
-
handler<H extends HandlerInputType>(handlers: H): CustomOperation<T, K | 'handler', B>;
|
|
58
|
+
handler<H extends HandlerInputType>(handlers: H): [H] extends [UltimateFunctionHandlerAsyncType] ? CustomOperation<AsyncFunctionCustomOperation<T>, K | 'handler' | 'returns', B> : CustomOperation<T, K | 'handler', B>;
|
|
53
59
|
for<Source extends SubscriptionSource>(source: Source | Source[]): CustomOperation<T['typeName'] extends 'Subscription' ? SetTypeSubArg<T, 'returnType', Source extends SubscriptionSource[] ? Source[number] : Source> : T, K | 'for', B>;
|
|
54
60
|
}, K> & Brand<B>;
|
|
55
61
|
/**
|
|
@@ -129,6 +135,12 @@ export declare function subscription(): CustomOperation<{
|
|
|
129
135
|
typeName: 'Subscription';
|
|
130
136
|
handlers: null;
|
|
131
137
|
}, 'returns', typeof subscriptionBrand>;
|
|
138
|
+
type AsyncFunctionCustomOperation<T extends CustomOperationParamShape> = SetTypeSubArg<SetTypeSubArg<T, 'returnType', EventInvocationResponseCustomType>, 'handlers', AsyncFunctionHandler>;
|
|
139
|
+
type EventInvocationResponseCustomType = CustomType<{
|
|
140
|
+
fields: {
|
|
141
|
+
success: ModelField<boolean, 'required', undefined>;
|
|
142
|
+
};
|
|
143
|
+
}>;
|
|
132
144
|
export interface GenerationInput {
|
|
133
145
|
aiModel: AiModel;
|
|
134
146
|
systemPrompt: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { brand } from './util/Brand.mjs';
|
|
1
|
+
import { brand, brandSymbol } from './util/Brand.mjs';
|
|
2
2
|
import { allowForCustomOperations } from './Authorization.mjs';
|
|
3
3
|
|
|
4
4
|
const queryBrand = 'queryCustomOperation';
|
|
@@ -42,6 +42,9 @@ function _custom(typeName, brand, input) {
|
|
|
42
42
|
data.handlers = Array.isArray(handlers)
|
|
43
43
|
? handlers
|
|
44
44
|
: [handlers];
|
|
45
|
+
if (lastHandlerIsAsyncFunction(handlers)) {
|
|
46
|
+
data.returnType = eventInvocationResponse;
|
|
47
|
+
}
|
|
45
48
|
return this;
|
|
46
49
|
},
|
|
47
50
|
for(source) {
|
|
@@ -106,6 +109,23 @@ function mutation() {
|
|
|
106
109
|
function subscription() {
|
|
107
110
|
return _custom('Subscription', subscriptionBrand);
|
|
108
111
|
}
|
|
112
|
+
const eventInvocationResponse = {
|
|
113
|
+
data: {
|
|
114
|
+
type: 'ref',
|
|
115
|
+
link: 'EventInvocationResponse',
|
|
116
|
+
valueRequired: false,
|
|
117
|
+
array: false,
|
|
118
|
+
arrayRequired: false,
|
|
119
|
+
mutationOperations: [],
|
|
120
|
+
authorization: [],
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
function lastHandlerIsAsyncFunction(handlers) {
|
|
124
|
+
const lastHandlerBrandSymbol = Array.isArray(handlers)
|
|
125
|
+
? handlers[handlers.length - 1][brandSymbol]
|
|
126
|
+
: handlers[brandSymbol];
|
|
127
|
+
return lastHandlerBrandSymbol === 'asyncFunctionHandler';
|
|
128
|
+
}
|
|
109
129
|
/**
|
|
110
130
|
* @experimental
|
|
111
131
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomOperation.mjs","sources":["../../src/CustomOperation.ts"],"sourcesContent":["import { brand } from './util';\nimport { allowForCustomOperations, } from './Authorization';\nconst queryBrand = 'queryCustomOperation';\nconst mutationBrand = 'mutationCustomOperation';\nconst subscriptionBrand = 'subscriptionCustomOperation';\nconst generationBrand = 'generationCustomOperation';\nexport const CustomOperationNames = [\n 'Query',\n 'Mutation',\n 'Subscription',\n 'Generation',\n];\nfunction brandedBuilder(builder, brandValue) {\n return { ...builder, ...brand(brandValue) };\n}\nfunction _custom(typeName, brand, input) {\n const data = {\n arguments: {},\n returnType: null,\n authorization: [],\n typeName: typeName,\n handlers: null,\n subscriptionSource: [],\n input,\n };\n const builder = brandedBuilder({\n arguments(args) {\n data.arguments = args;\n return this;\n },\n returns(returnType) {\n data.returnType = returnType;\n return this;\n },\n authorization(callback) {\n const rules = callback(allowForCustomOperations);\n data.authorization = Array.isArray(rules) ? rules : [rules];\n return this;\n },\n handler(handlers) {\n data.handlers = Array.isArray(handlers)\n ? handlers\n : [handlers];\n return this;\n },\n for(source) {\n data.subscriptionSource = Array.isArray(source) ? source : [source];\n return this;\n },\n }, brand);\n return { ...builder, data };\n}\n/**\n * Use a custom query to define an API request that will retrieve backend data.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @example\n * const schema = a.schema({\n * echo: a\n * .query()\n * .arguments({ content: a.string() })\n * .returns(a.ref('EchoResponse'))\n * .authorization(allow => [allow.publicApiKey()])\n * // 3. set the function has the handler\n * .handler(a.handler.function(echoHandler)),\n *\n * EchoResponse: a.customType({\n * content: a.string(),\n * executionDuration: a.float()\n * }),\n * });\n * @returns a custom query\n */\nexport function query() {\n return _custom('Query', queryBrand);\n}\n/**\n * Use a custom mutation to define an API request that will modify backend data or trigger a subscription event.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @example\n * likePost: a\n * .mutation()\n * .arguments({ postId: a.string() })\n * .returns(a.ref('Post'))\n * .authorization(allow => [allow.publicApiKey()])\n * .handler(a.handler.function(echoHandler))\n * @returns a custom mutation\n */\nexport function mutation() {\n return _custom('Mutation', mutationBrand);\n}\n/**\n * Define a custom subscription to receive an event when a mutation is triggered\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-subscription/}\n * @example\n * // Subscribe to incoming messages\n * receive: a.subscription()\n * // subscribes to the 'publish' mutation\n * .for(a.ref('publish'))\n * // subscription handler to set custom filters\n * .handler(a.handler.custom({entry: './receive.js'}))\n * // authorization rules as to who can subscribe to the data\n * .authorization(allow => [allow.publicApiKey()]),\n * @returns a custom subscription\n */\nexport function subscription() {\n return _custom('Subscription', subscriptionBrand);\n}\n/**\n * @experimental\n *\n * Define an AI generation route for single request-response interaction with specified AI model.\n * @example\n * makeRecipe: a.generation({\n * aiModel: { resourcePath },\n * systemPrompt: 'Please make a recipe from the provided ingredients',\n * })\n * .arguments({ ingredients: a.string().array() })\n * .returns(a.ref(\"Recipe\"))\n * @returns a generation route definition\n */\nexport function generation(input) {\n return _custom('Generation', generationBrand, input);\n}\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"CustomOperation.mjs","sources":["../../src/CustomOperation.ts"],"sourcesContent":["import { brand } from './util';\nimport { allowForCustomOperations, } from './Authorization';\nimport { brandSymbol } from './util/Brand';\nconst queryBrand = 'queryCustomOperation';\nconst mutationBrand = 'mutationCustomOperation';\nconst subscriptionBrand = 'subscriptionCustomOperation';\nconst generationBrand = 'generationCustomOperation';\nexport const CustomOperationNames = [\n 'Query',\n 'Mutation',\n 'Subscription',\n 'Generation',\n];\nfunction brandedBuilder(builder, brandValue) {\n return { ...builder, ...brand(brandValue) };\n}\nfunction _custom(typeName, brand, input) {\n const data = {\n arguments: {},\n returnType: null,\n authorization: [],\n typeName: typeName,\n handlers: null,\n subscriptionSource: [],\n input,\n };\n const builder = brandedBuilder({\n arguments(args) {\n data.arguments = args;\n return this;\n },\n returns(returnType) {\n data.returnType = returnType;\n return this;\n },\n authorization(callback) {\n const rules = callback(allowForCustomOperations);\n data.authorization = Array.isArray(rules) ? rules : [rules];\n return this;\n },\n handler(handlers) {\n data.handlers = Array.isArray(handlers)\n ? handlers\n : [handlers];\n if (lastHandlerIsAsyncFunction(handlers)) {\n data.returnType = eventInvocationResponse;\n }\n return this;\n },\n for(source) {\n data.subscriptionSource = Array.isArray(source) ? source : [source];\n return this;\n },\n }, brand);\n return { ...builder, data };\n}\n/**\n * Use a custom query to define an API request that will retrieve backend data.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @example\n * const schema = a.schema({\n * echo: a\n * .query()\n * .arguments({ content: a.string() })\n * .returns(a.ref('EchoResponse'))\n * .authorization(allow => [allow.publicApiKey()])\n * // 3. set the function has the handler\n * .handler(a.handler.function(echoHandler)),\n *\n * EchoResponse: a.customType({\n * content: a.string(),\n * executionDuration: a.float()\n * }),\n * });\n * @returns a custom query\n */\nexport function query() {\n return _custom('Query', queryBrand);\n}\n/**\n * Use a custom mutation to define an API request that will modify backend data or trigger a subscription event.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @example\n * likePost: a\n * .mutation()\n * .arguments({ postId: a.string() })\n * .returns(a.ref('Post'))\n * .authorization(allow => [allow.publicApiKey()])\n * .handler(a.handler.function(echoHandler))\n * @returns a custom mutation\n */\nexport function mutation() {\n return _custom('Mutation', mutationBrand);\n}\n/**\n * Define a custom subscription to receive an event when a mutation is triggered\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-subscription/}\n * @example\n * // Subscribe to incoming messages\n * receive: a.subscription()\n * // subscribes to the 'publish' mutation\n * .for(a.ref('publish'))\n * // subscription handler to set custom filters\n * .handler(a.handler.custom({entry: './receive.js'}))\n * // authorization rules as to who can subscribe to the data\n * .authorization(allow => [allow.publicApiKey()]),\n * @returns a custom subscription\n */\nexport function subscription() {\n return _custom('Subscription', subscriptionBrand);\n}\nconst eventInvocationResponse = {\n data: {\n type: 'ref',\n link: 'EventInvocationResponse',\n valueRequired: false,\n array: false,\n arrayRequired: false,\n mutationOperations: [],\n authorization: [],\n },\n};\nfunction lastHandlerIsAsyncFunction(handlers) {\n const lastHandlerBrandSymbol = Array.isArray(handlers)\n ? handlers[handlers.length - 1][brandSymbol]\n : handlers[brandSymbol];\n return lastHandlerBrandSymbol === 'asyncFunctionHandler';\n}\n/**\n * @experimental\n *\n * Define an AI generation route for single request-response interaction with specified AI model.\n * @example\n * makeRecipe: a.generation({\n * aiModel: { resourcePath },\n * systemPrompt: 'Please make a recipe from the provided ingredients',\n * })\n * .arguments({ ingredients: a.string().array() })\n * .returns(a.ref(\"Recipe\"))\n * @returns a generation route definition\n */\nexport function generation(input) {\n return _custom('Generation', generationBrand, input);\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/Handler.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { DefineFunction } from '@aws-amplify/data-schema-types';
|
|
2
|
-
import {
|
|
2
|
+
import type { brandSymbol } from './util/Brand.js';
|
|
3
3
|
import { RefType } from './RefType';
|
|
4
|
-
export type HandlerType = InlineSqlHandler | SqlReferenceHandler | CustomHandler | FunctionHandler;
|
|
4
|
+
export type HandlerType = InlineSqlHandler | SqlReferenceHandler | CustomHandler | FunctionHandler | AsyncFunctionHandler;
|
|
5
5
|
declare const dataSymbol: unique symbol;
|
|
6
|
-
type AllHandlers = InlineSqlHandler | SqlReferenceHandler | CustomHandler | FunctionHandler;
|
|
6
|
+
type AllHandlers = InlineSqlHandler | SqlReferenceHandler | CustomHandler | FunctionHandler | AsyncFunctionHandler;
|
|
7
7
|
export declare function getHandlerData<H extends AllHandlers>(handler: H): H[typeof dataSymbol];
|
|
8
8
|
declare const inlineSqlBrand = "inlineSql";
|
|
9
9
|
export type InlineSqlHandler = {
|
|
10
10
|
[dataSymbol]: string;
|
|
11
|
-
|
|
11
|
+
[brandSymbol]: typeof inlineSqlBrand;
|
|
12
|
+
};
|
|
12
13
|
declare function inlineSql(sql: string): InlineSqlHandler;
|
|
13
14
|
declare const sqlReferenceBrand = "sqlReference";
|
|
14
15
|
export type SqlReferenceHandlerData = {
|
|
@@ -17,7 +18,8 @@ export type SqlReferenceHandlerData = {
|
|
|
17
18
|
};
|
|
18
19
|
export type SqlReferenceHandler = {
|
|
19
20
|
[dataSymbol]: SqlReferenceHandlerData;
|
|
20
|
-
|
|
21
|
+
[brandSymbol]: typeof sqlReferenceBrand;
|
|
22
|
+
};
|
|
21
23
|
declare function sqlReference(sqlFilePath: string): SqlReferenceHandler;
|
|
22
24
|
type CustomHandlerInput = {
|
|
23
25
|
/**
|
|
@@ -40,7 +42,8 @@ export type CustomHandlerData = CustomHandlerInput & {
|
|
|
40
42
|
declare const customHandlerBrand = "customHandler";
|
|
41
43
|
export type CustomHandler = {
|
|
42
44
|
[dataSymbol]: CustomHandlerData;
|
|
43
|
-
|
|
45
|
+
[brandSymbol]: typeof customHandlerBrand;
|
|
46
|
+
};
|
|
44
47
|
/**
|
|
45
48
|
* Use a custom JavaScript resolver to handle a query, mutation, or subscription.
|
|
46
49
|
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/#step-2---configure-custom-business-logic-handler-code}
|
|
@@ -69,11 +72,56 @@ export type CustomHandler = {
|
|
|
69
72
|
* });
|
|
70
73
|
*/
|
|
71
74
|
declare function custom(customHandler: CustomHandlerInput): CustomHandler;
|
|
72
|
-
export type
|
|
75
|
+
export type FunctionHandlerInput = DefineFunction | string;
|
|
76
|
+
export type FunctionHandlerData = {
|
|
77
|
+
handler: FunctionHandlerInput;
|
|
78
|
+
invocationType: 'RequestResponse' | 'Event';
|
|
79
|
+
};
|
|
73
80
|
declare const functionHandlerBrand = "functionHandler";
|
|
74
81
|
export type FunctionHandler = {
|
|
75
82
|
[dataSymbol]: FunctionHandlerData;
|
|
76
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Use `async()` to have this function handler invoked asynchronously.
|
|
85
|
+
* If an `async()` function is only handler or the final handler in a pipeline, the return type of this
|
|
86
|
+
* custom query / mutation is `{ success: boolean }`.
|
|
87
|
+
* @example
|
|
88
|
+
* import {
|
|
89
|
+
* type ClientSchema,
|
|
90
|
+
* a,
|
|
91
|
+
* defineData,
|
|
92
|
+
* defineFunction // 1.Import "defineFunction" to create new functions
|
|
93
|
+
* } from '@aws-amplify/backend';
|
|
94
|
+
*
|
|
95
|
+
* // 2. define a function
|
|
96
|
+
* const echoHandler = defineFunction({
|
|
97
|
+
* entry: './echo-handler/handler.ts'
|
|
98
|
+
* })
|
|
99
|
+
*
|
|
100
|
+
* const schema = a.schema({
|
|
101
|
+
* EchoResponse: a.customType({
|
|
102
|
+
* content: a.string(),
|
|
103
|
+
* executionDuration: a.float()
|
|
104
|
+
* }),
|
|
105
|
+
*
|
|
106
|
+
* echo: a
|
|
107
|
+
* .query()
|
|
108
|
+
* .arguments({ content: a.string() })
|
|
109
|
+
* .returns(a.ref('EchoResponse'))
|
|
110
|
+
* .authorization(allow => [allow.publicApiKey()])
|
|
111
|
+
* // 3. set the function has the handler
|
|
112
|
+
* .handler(a.handler.function(echoHandler).async())
|
|
113
|
+
*
|
|
114
|
+
* @see {@link https://docs.amplify.aws/react/build-a-backend/data/INSERT_PATH_WHEN_READY}
|
|
115
|
+
* @returns A function handler for query / mutation that is asynchronously invoked.
|
|
116
|
+
*/
|
|
117
|
+
async(): AsyncFunctionHandler;
|
|
118
|
+
[brandSymbol]: typeof functionHandlerBrand;
|
|
119
|
+
};
|
|
120
|
+
declare const asyncFunctionHandlerBrand = "asyncFunctionHandler";
|
|
121
|
+
export type AsyncFunctionHandler = {
|
|
122
|
+
[dataSymbol]: FunctionHandlerData;
|
|
123
|
+
[brandSymbol]: typeof asyncFunctionHandlerBrand;
|
|
124
|
+
};
|
|
77
125
|
/**
|
|
78
126
|
* Use a function created via `defineFunction` to handle the custom query/mutation/subscription. In your function handler,
|
|
79
127
|
* you can use the `Schema["YOUR_QUERY_OR_MUTATION_NAME"]["functionHandler"]` utility type to type the handler function.
|
|
@@ -109,7 +157,7 @@ export type FunctionHandler = {
|
|
|
109
157
|
* in a corresponding value into the `functionMap` property of defineData.
|
|
110
158
|
* @returns A handler for the query / mutation / subscription
|
|
111
159
|
*/
|
|
112
|
-
declare function fcn(fn:
|
|
160
|
+
declare function fcn(fn: FunctionHandlerInput): FunctionHandler;
|
|
113
161
|
export declare const handler: {
|
|
114
162
|
inlineSql: typeof inlineSql;
|
|
115
163
|
sqlReference: typeof sqlReference;
|
package/dist/esm/Handler.mjs
CHANGED
|
@@ -60,6 +60,7 @@ function custom(customHandler) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
const functionHandlerBrand = 'functionHandler';
|
|
63
|
+
const asyncFunctionHandlerBrand = 'asyncFunctionHandler';
|
|
63
64
|
/**
|
|
64
65
|
* Use a function created via `defineFunction` to handle the custom query/mutation/subscription. In your function handler,
|
|
65
66
|
* you can use the `Schema["YOUR_QUERY_OR_MUTATION_NAME"]["functionHandler"]` utility type to type the handler function.
|
|
@@ -96,7 +97,25 @@ const functionHandlerBrand = 'functionHandler';
|
|
|
96
97
|
* @returns A handler for the query / mutation / subscription
|
|
97
98
|
*/
|
|
98
99
|
function fcn(fn) {
|
|
99
|
-
return {
|
|
100
|
+
return {
|
|
101
|
+
[dataSymbol]: {
|
|
102
|
+
handler: fn,
|
|
103
|
+
invocationType: 'RequestResponse',
|
|
104
|
+
},
|
|
105
|
+
async() {
|
|
106
|
+
return _async(this);
|
|
107
|
+
},
|
|
108
|
+
...buildHandler(functionHandlerBrand),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function _async(fnHandler) {
|
|
112
|
+
return {
|
|
113
|
+
[dataSymbol]: {
|
|
114
|
+
handler: fnHandler[dataSymbol].handler,
|
|
115
|
+
invocationType: 'Event',
|
|
116
|
+
},
|
|
117
|
+
...buildHandler(asyncFunctionHandlerBrand),
|
|
118
|
+
};
|
|
100
119
|
}
|
|
101
120
|
//#endregion
|
|
102
121
|
const handler = {
|
package/dist/esm/Handler.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Handler.mjs","sources":["../../src/Handler.ts"],"sourcesContent":["import { brand } from './util';\nconst dataSymbol = Symbol('Data');\nfunction buildHandler(brandName) {\n return brand(brandName);\n}\nexport function getHandlerData(handler) {\n return handler[dataSymbol];\n}\n//#region handler.inlineSql\nconst inlineSqlBrand = 'inlineSql';\nfunction inlineSql(sql) {\n return { [dataSymbol]: sql, ...buildHandler(inlineSqlBrand) };\n}\n//#endregion\n//#region handler.sqlReference\nconst sqlReferenceBrand = 'sqlReference';\nfunction sqlReference(sqlFilePath) {\n // used to determine caller directory in order to resolve relative path downstream\n const stack = new Error().stack;\n return {\n [dataSymbol]: { stack, entry: sqlFilePath },\n ...buildHandler(sqlReferenceBrand),\n };\n}\nconst customHandlerBrand = 'customHandler';\n/**\n * Use a custom JavaScript resolver to handle a query, mutation, or subscription.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/#step-2---configure-custom-business-logic-handler-code}\n * @param customHandler `{ entry: \"path-to-javascript-resolver-file.js\", dataSource: \"Data Source name added via \"backend.data.add*DataSoruce(...)\"}`\n * @returns A JavaScript resolver attached to the query, mutation, or subscription.\n * @example\n * const schema = a.schema({\n * Post: a.model({\n * content: a.string(),\n * likes: a.integer()\n * .authorization(allow => [allow.authenticated().to(['read'])])\n * }).authorization(allow => [\n * allow.owner(),\n * allow.authenticated().to(['read'])\n * ]),\n *\n * likePost: a\n * .mutation()\n * .arguments({ postId: a.id() })\n * .returns(a.ref('Post'))\n * .authorization(allow => [allow.authenticated()])\n * .handler(a.handler.custom({\n * dataSource: a.ref('Post'),\n * entry: './increment-like.js'\n * }))\n * });\n */\nfunction custom(customHandler) {\n // used to determine caller directory in order to resolve relative path downstream\n const stack = new Error().stack;\n return {\n [dataSymbol]: { ...customHandler, stack },\n ...buildHandler(customHandlerBrand),\n };\n}\nconst functionHandlerBrand = 'functionHandler';\n/**\n * Use a function created via `defineFunction` to handle the custom query/mutation/subscription. In your function handler,\n * you can use the `Schema[\"YOUR_QUERY_OR_MUTATION_NAME\"][\"functionHandler\"]` utility type to type the handler function.\n * @example\n * import {\n * type ClientSchema,\n * a,\n * defineData,\n * defineFunction // 1.Import \"defineFunction\" to create new functions\n * } from '@aws-amplify/backend';\n *\n * // 2. define a function\n * const echoHandler = defineFunction({\n * entry: './echo-handler/handler.ts'\n * })\n *\n * const schema = a.schema({\n * EchoResponse: a.customType({\n * content: a.string(),\n * executionDuration: a.float()\n * }),\n *\n * echo: a\n * .query()\n * .arguments({ content: a.string() })\n * .returns(a.ref('EchoResponse'))\n * .authorization(allow => [allow.publicApiKey()])\n * // 3. set the function has the handler\n * .handler(a.handler.function(echoHandler))\n * });\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @param fn A function created via `defineFunction`. Alternatively, you can pass in a \"string\" of the function name and pass\n * in a corresponding value into the `functionMap` property of defineData.\n * @returns A handler for the query / mutation / subscription\n */\nfunction fcn(fn) {\n return {
|
|
1
|
+
{"version":3,"file":"Handler.mjs","sources":["../../src/Handler.ts"],"sourcesContent":["import { brand } from './util';\nconst dataSymbol = Symbol('Data');\nfunction buildHandler(brandName) {\n return brand(brandName);\n}\nexport function getHandlerData(handler) {\n return handler[dataSymbol];\n}\n//#region handler.inlineSql\nconst inlineSqlBrand = 'inlineSql';\nfunction inlineSql(sql) {\n return { [dataSymbol]: sql, ...buildHandler(inlineSqlBrand) };\n}\n//#endregion\n//#region handler.sqlReference\nconst sqlReferenceBrand = 'sqlReference';\nfunction sqlReference(sqlFilePath) {\n // used to determine caller directory in order to resolve relative path downstream\n const stack = new Error().stack;\n return {\n [dataSymbol]: { stack, entry: sqlFilePath },\n ...buildHandler(sqlReferenceBrand),\n };\n}\nconst customHandlerBrand = 'customHandler';\n/**\n * Use a custom JavaScript resolver to handle a query, mutation, or subscription.\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/#step-2---configure-custom-business-logic-handler-code}\n * @param customHandler `{ entry: \"path-to-javascript-resolver-file.js\", dataSource: \"Data Source name added via \"backend.data.add*DataSoruce(...)\"}`\n * @returns A JavaScript resolver attached to the query, mutation, or subscription.\n * @example\n * const schema = a.schema({\n * Post: a.model({\n * content: a.string(),\n * likes: a.integer()\n * .authorization(allow => [allow.authenticated().to(['read'])])\n * }).authorization(allow => [\n * allow.owner(),\n * allow.authenticated().to(['read'])\n * ]),\n *\n * likePost: a\n * .mutation()\n * .arguments({ postId: a.id() })\n * .returns(a.ref('Post'))\n * .authorization(allow => [allow.authenticated()])\n * .handler(a.handler.custom({\n * dataSource: a.ref('Post'),\n * entry: './increment-like.js'\n * }))\n * });\n */\nfunction custom(customHandler) {\n // used to determine caller directory in order to resolve relative path downstream\n const stack = new Error().stack;\n return {\n [dataSymbol]: { ...customHandler, stack },\n ...buildHandler(customHandlerBrand),\n };\n}\nconst functionHandlerBrand = 'functionHandler';\nconst asyncFunctionHandlerBrand = 'asyncFunctionHandler';\n/**\n * Use a function created via `defineFunction` to handle the custom query/mutation/subscription. In your function handler,\n * you can use the `Schema[\"YOUR_QUERY_OR_MUTATION_NAME\"][\"functionHandler\"]` utility type to type the handler function.\n * @example\n * import {\n * type ClientSchema,\n * a,\n * defineData,\n * defineFunction // 1.Import \"defineFunction\" to create new functions\n * } from '@aws-amplify/backend';\n *\n * // 2. define a function\n * const echoHandler = defineFunction({\n * entry: './echo-handler/handler.ts'\n * })\n *\n * const schema = a.schema({\n * EchoResponse: a.customType({\n * content: a.string(),\n * executionDuration: a.float()\n * }),\n *\n * echo: a\n * .query()\n * .arguments({ content: a.string() })\n * .returns(a.ref('EchoResponse'))\n * .authorization(allow => [allow.publicApiKey()])\n * // 3. set the function has the handler\n * .handler(a.handler.function(echoHandler))\n * });\n * @see {@link https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/}\n * @param fn A function created via `defineFunction`. Alternatively, you can pass in a \"string\" of the function name and pass\n * in a corresponding value into the `functionMap` property of defineData.\n * @returns A handler for the query / mutation / subscription\n */\nfunction fcn(fn) {\n return {\n [dataSymbol]: {\n handler: fn,\n invocationType: 'RequestResponse',\n },\n async() {\n return _async(this);\n },\n ...buildHandler(functionHandlerBrand),\n };\n}\nfunction _async(fnHandler) {\n return {\n [dataSymbol]: {\n handler: fnHandler[dataSymbol].handler,\n invocationType: 'Event',\n },\n ...buildHandler(asyncFunctionHandlerBrand),\n };\n}\n//#endregion\nexport const handler = {\n inlineSql,\n sqlReference,\n custom,\n function: fcn,\n};\n"],"names":[],"mappings":";;AACA,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAClC,SAAS,YAAY,CAAC,SAAS,EAAE;AACjC,IAAI,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AACM,SAAS,cAAc,CAAC,OAAO,EAAE;AACxC,IAAI,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/B,CAAC;AACD;AACA,MAAM,cAAc,GAAG,WAAW,CAAC;AACnC,SAAS,SAAS,CAAC,GAAG,EAAE;AACxB,IAAI,OAAO,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;AAClE,CAAC;AACD;AACA;AACA,MAAM,iBAAiB,GAAG,cAAc,CAAC;AACzC,SAAS,YAAY,CAAC,WAAW,EAAE;AACnC;AACA,IAAI,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACpC,IAAI,OAAO;AACX,QAAQ,CAAC,UAAU,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE;AACnD,QAAQ,GAAG,YAAY,CAAC,iBAAiB,CAAC;AAC1C,KAAK,CAAC;AACN,CAAC;AACD,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,MAAM,CAAC,aAAa,EAAE;AAC/B;AACA,IAAI,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACpC,IAAI,OAAO;AACX,QAAQ,CAAC,UAAU,GAAG,EAAE,GAAG,aAAa,EAAE,KAAK,EAAE;AACjD,QAAQ,GAAG,YAAY,CAAC,kBAAkB,CAAC;AAC3C,KAAK,CAAC;AACN,CAAC;AACD,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AAC/C,MAAM,yBAAyB,GAAG,sBAAsB,CAAC;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,GAAG,CAAC,EAAE,EAAE;AACjB,IAAI,OAAO;AACX,QAAQ,CAAC,UAAU,GAAG;AACtB,YAAY,OAAO,EAAE,EAAE;AACvB,YAAY,cAAc,EAAE,iBAAiB;AAC7C,SAAS;AACT,QAAQ,KAAK,GAAG;AAChB,YAAY,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AAChC,SAAS;AACT,QAAQ,GAAG,YAAY,CAAC,oBAAoB,CAAC;AAC7C,KAAK,CAAC;AACN,CAAC;AACD,SAAS,MAAM,CAAC,SAAS,EAAE;AAC3B,IAAI,OAAO;AACX,QAAQ,CAAC,UAAU,GAAG;AACtB,YAAY,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO;AAClD,YAAY,cAAc,EAAE,OAAO;AACnC,SAAS;AACT,QAAQ,GAAG,YAAY,CAAC,yBAAyB,CAAC;AAClD,KAAK,CAAC;AACN,CAAC;AACD;AACY,MAAC,OAAO,GAAG;AACvB,IAAI,SAAS;AACb,IAAI,YAAY;AAChB,IAAI,MAAM;AACV,IAAI,QAAQ,EAAE,GAAG;AACjB;;;;"}
|
|
@@ -2,7 +2,7 @@ import { ModelFieldType, string } from './ModelField.mjs';
|
|
|
2
2
|
import { ModelRelationshipTypes } from './ModelRelationalField.mjs';
|
|
3
3
|
import { accessData, accessSchemaData } from './Authorization.mjs';
|
|
4
4
|
import { CustomOperationNames } from './CustomOperation.mjs';
|
|
5
|
-
import { getBrand } from './util/Brand.mjs';
|
|
5
|
+
import { getBrand, brandSymbol } from './util/Brand.mjs';
|
|
6
6
|
import { getHandlerData } from './Handler.mjs';
|
|
7
7
|
import * as os from 'os';
|
|
8
8
|
import * as path from 'path';
|
|
@@ -149,19 +149,23 @@ function transformFunctionHandler(handlers, functionFieldName) {
|
|
|
149
149
|
const lambdaFunctionDefinition = {};
|
|
150
150
|
handlers.forEach((handler, idx) => {
|
|
151
151
|
const handlerData = getHandlerData(handler);
|
|
152
|
-
if (typeof handlerData === 'string') {
|
|
153
|
-
gqlHandlerContent += `@function(name: "${handlerData}") `;
|
|
152
|
+
if (typeof handlerData.handler === 'string') {
|
|
153
|
+
gqlHandlerContent += `@function(name: "${handlerData.handler}") `;
|
|
154
154
|
}
|
|
155
|
-
else if (typeof handlerData.getInstance === 'function') {
|
|
155
|
+
else if (typeof handlerData.handler.getInstance === 'function') {
|
|
156
156
|
const fnName = `Fn${capitalize(functionFieldName)}${idx === 0 ? '' : `${idx + 1}`}`;
|
|
157
|
-
lambdaFunctionDefinition[fnName] = handlerData;
|
|
158
|
-
|
|
157
|
+
lambdaFunctionDefinition[fnName] = handlerData.handler;
|
|
158
|
+
const invocationTypeArg = handlerData.invocationType === 'Event' ? ', invocationType: Event)' : ')';
|
|
159
|
+
gqlHandlerContent += `@function(name: "${fnName}"${invocationTypeArg} `;
|
|
159
160
|
}
|
|
160
161
|
else {
|
|
161
162
|
throw new Error(`Invalid value specified for ${functionFieldName} handler.function(). Expected: defineFunction or string.`);
|
|
162
163
|
}
|
|
163
164
|
});
|
|
164
|
-
return {
|
|
165
|
+
return {
|
|
166
|
+
gqlHandlerContent,
|
|
167
|
+
lambdaFunctionDefinition,
|
|
168
|
+
};
|
|
165
169
|
}
|
|
166
170
|
function customOperationToGql(typeName, typeDef, authorization, isCustom = false, databaseType, getRefType) {
|
|
167
171
|
const { arguments: fieldArgs, typeName: opType, returnType, handlers, subscriptionSource, } = typeDef.data;
|
|
@@ -814,6 +818,18 @@ const schemaPreprocessor = (schema) => {
|
|
|
814
818
|
? 'dynamodb'
|
|
815
819
|
: 'sql';
|
|
816
820
|
const staticSchema = databaseType === 'sql';
|
|
821
|
+
// If the schema contains a custom operation with an async lambda handler,
|
|
822
|
+
// we need to add the EventInvocationResponse custom type to the schema.
|
|
823
|
+
// This is done here so that:
|
|
824
|
+
// - it only happens once per schema
|
|
825
|
+
// - downstream validation based on `getRefTypeForSchema` finds the EventInvocationResponse type
|
|
826
|
+
const containsAsyncLambdaCustomOperation = Object.entries(schema.data.types).find(([_, typeDef]) => {
|
|
827
|
+
return isCustomOperation(typeDef)
|
|
828
|
+
&& finalHandlerIsAsyncFunctionHandler(typeDef.data.handlers);
|
|
829
|
+
});
|
|
830
|
+
if (containsAsyncLambdaCustomOperation) {
|
|
831
|
+
schema.data.types['EventInvocationResponse'] = eventInvocationResponseCustomType;
|
|
832
|
+
}
|
|
817
833
|
const topLevelTypes = sortTopLevelTypes(Object.entries(schema.data.types));
|
|
818
834
|
const { schemaAuth, functionSchemaAccess } = extractFunctionSchemaAccess(schema.data.authorization);
|
|
819
835
|
const getRefType = getRefTypeForSchema(schema);
|
|
@@ -976,14 +992,22 @@ function validateCustomOperations(typeDef, typeName, authRules, getRefType) {
|
|
|
976
992
|
configuredHandlers.add(getBrand(handler));
|
|
977
993
|
}
|
|
978
994
|
if (configuredHandlers.size > 1) {
|
|
979
|
-
|
|
980
|
-
|
|
995
|
+
configuredHandlers.delete('asyncFunctionHandler');
|
|
996
|
+
configuredHandlers.delete('functionHandler');
|
|
997
|
+
if (configuredHandlers.size > 0) {
|
|
998
|
+
const configuredHandlersStr = JSON.stringify(Array.from(configuredHandlers));
|
|
999
|
+
throw new Error(`Field handlers must be of the same type. ${typeName} has been configured with ${configuredHandlersStr}`);
|
|
1000
|
+
}
|
|
981
1001
|
}
|
|
982
1002
|
}
|
|
983
1003
|
if (typeDef.data.returnType === null &&
|
|
984
1004
|
(opType === 'Query' || opType === 'Mutation' || opType === 'Generation')) {
|
|
985
|
-
|
|
986
|
-
|
|
1005
|
+
// TODO: There should be a more elegant and readable way to handle this check.
|
|
1006
|
+
// Maybe it's not even necessary anymore since we're the setting returnType in the handler() method.
|
|
1007
|
+
if (!handlers || handlers.length === 0 || handlers[handlers.length - 1][brandSymbol] !== 'asyncFunctionHandler') {
|
|
1008
|
+
const typeDescription = opType === 'Generation' ? 'Generation Route' : `Custom ${opType}`;
|
|
1009
|
+
throw new Error(`Invalid ${typeDescription} definition. A ${typeDescription} must include a return type. ${typeName} has no return type specified.`);
|
|
1010
|
+
}
|
|
987
1011
|
}
|
|
988
1012
|
if (opType !== 'Subscription' && subscriptionSource.length > 0) {
|
|
989
1013
|
throw new Error(`The .for() modifier function can only be used with a custom subscription. ${typeName} is not a custom subscription.`);
|
|
@@ -1038,7 +1062,10 @@ const isCustomHandler = (handler) => {
|
|
|
1038
1062
|
return Array.isArray(handler) && getBrand(handler[0]) === 'customHandler';
|
|
1039
1063
|
};
|
|
1040
1064
|
const isFunctionHandler = (handler) => {
|
|
1041
|
-
return Array.isArray(handler) && getBrand(handler[0])
|
|
1065
|
+
return Array.isArray(handler) && ['functionHandler', 'asyncFunctionHandler'].includes(getBrand(handler[0]));
|
|
1066
|
+
};
|
|
1067
|
+
const finalHandlerIsAsyncFunctionHandler = (handler) => {
|
|
1068
|
+
return Array.isArray(handler) && getBrand(handler[handler.length - 1]) === 'asyncFunctionHandler';
|
|
1042
1069
|
};
|
|
1043
1070
|
const normalizeDataSourceName = (dataSource) => {
|
|
1044
1071
|
// default data source
|
|
@@ -1092,6 +1119,21 @@ const handleCustom = (handlers, opType, typeName) => {
|
|
|
1092
1119
|
};
|
|
1093
1120
|
return jsFn;
|
|
1094
1121
|
};
|
|
1122
|
+
const eventInvocationResponseCustomType = {
|
|
1123
|
+
data: {
|
|
1124
|
+
fields: {
|
|
1125
|
+
success: {
|
|
1126
|
+
data: {
|
|
1127
|
+
fieldType: ModelFieldType.Boolean,
|
|
1128
|
+
required: true,
|
|
1129
|
+
array: false,
|
|
1130
|
+
arrayRequired: false,
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
type: 'customType'
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1095
1137
|
function transformCustomOperations(typeDef, typeName, authRules, databaseType, getRefType) {
|
|
1096
1138
|
const { typeName: opType, handlers } = typeDef.data;
|
|
1097
1139
|
let jsFunctionForField = undefined;
|