@aws-amplify/data-schema 1.3.10 → 1.4.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.
Files changed (102) hide show
  1. package/dist/cjs/ModelType.js +5 -0
  2. package/dist/cjs/ModelType.js.map +1 -1
  3. package/dist/cjs/SchemaProcessor.js +58 -1
  4. package/dist/cjs/SchemaProcessor.js.map +1 -1
  5. package/dist/cjs/runtime/addSchemaToClient.js +1 -0
  6. package/dist/cjs/runtime/addSchemaToClient.js.map +1 -1
  7. package/dist/cjs/runtime/addSchemaToClientWithInstance.js +1 -0
  8. package/dist/cjs/runtime/addSchemaToClientWithInstance.js.map +1 -1
  9. package/dist/cjs/runtime/internals/APIClient.js +63 -42
  10. package/dist/cjs/runtime/internals/APIClient.js.map +1 -1
  11. package/dist/cjs/runtime/internals/cancellation.js +48 -0
  12. package/dist/cjs/runtime/internals/cancellation.js.map +1 -0
  13. package/dist/cjs/runtime/internals/clientUtils.js +45 -3
  14. package/dist/cjs/runtime/internals/clientUtils.js.map +1 -1
  15. package/dist/cjs/runtime/internals/index.js +3 -1
  16. package/dist/cjs/runtime/internals/index.js.map +1 -1
  17. package/dist/cjs/runtime/internals/operations/custom.js +91 -85
  18. package/dist/cjs/runtime/internals/operations/custom.js.map +1 -1
  19. package/dist/cjs/runtime/internals/operations/get.js +71 -65
  20. package/dist/cjs/runtime/internals/operations/get.js.map +1 -1
  21. package/dist/cjs/runtime/internals/operations/indexQuery.js +66 -60
  22. package/dist/cjs/runtime/internals/operations/indexQuery.js.map +1 -1
  23. package/dist/cjs/runtime/internals/operations/list.js +90 -84
  24. package/dist/cjs/runtime/internals/operations/list.js.map +1 -1
  25. package/dist/cjs/runtime/internals/server/generateModelsProperty.js +3 -3
  26. package/dist/cjs/runtime/internals/server/generateModelsProperty.js.map +1 -1
  27. package/dist/cjs/runtime/internals/utils/clientProperties/generateModelsProperty.js +3 -3
  28. package/dist/cjs/runtime/internals/utils/clientProperties/generateModelsProperty.js.map +1 -1
  29. package/dist/cjs/runtime/utils/index.js +3 -1
  30. package/dist/cjs/runtime/utils/index.js.map +1 -1
  31. package/dist/cjs/runtime/utils/selfAwareAsync.js +40 -0
  32. package/dist/cjs/runtime/utils/selfAwareAsync.js.map +1 -0
  33. package/dist/esm/Authorization.d.ts +1 -1
  34. package/dist/esm/ClientSchema/Core/ClientModel.d.ts +20 -1
  35. package/dist/esm/ClientSchema/utilities/ResolveField.d.ts +5 -1
  36. package/dist/esm/ModelType.d.ts +6 -0
  37. package/dist/esm/ModelType.mjs +5 -0
  38. package/dist/esm/ModelType.mjs.map +1 -1
  39. package/dist/esm/SchemaProcessor.mjs +58 -1
  40. package/dist/esm/SchemaProcessor.mjs.map +1 -1
  41. package/dist/esm/runtime/addSchemaToClient.mjs +2 -0
  42. package/dist/esm/runtime/addSchemaToClient.mjs.map +1 -1
  43. package/dist/esm/runtime/addSchemaToClientWithInstance.mjs +2 -0
  44. package/dist/esm/runtime/addSchemaToClientWithInstance.mjs.map +1 -1
  45. package/dist/esm/runtime/bridge-types.d.ts +2 -2
  46. package/dist/esm/runtime/client/index.d.ts +6 -6
  47. package/dist/esm/runtime/internals/APIClient.d.ts +2 -2
  48. package/dist/esm/runtime/internals/APIClient.mjs +64 -42
  49. package/dist/esm/runtime/internals/APIClient.mjs.map +1 -1
  50. package/dist/esm/runtime/internals/cancellation.d.ts +10 -0
  51. package/dist/esm/runtime/internals/cancellation.mjs +44 -0
  52. package/dist/esm/runtime/internals/cancellation.mjs.map +1 -0
  53. package/dist/esm/runtime/internals/clientUtils.d.ts +78 -1
  54. package/dist/esm/runtime/internals/clientUtils.mjs +45 -3
  55. package/dist/esm/runtime/internals/clientUtils.mjs.map +1 -1
  56. package/dist/esm/runtime/internals/index.d.ts +1 -0
  57. package/dist/esm/runtime/internals/index.mjs +1 -0
  58. package/dist/esm/runtime/internals/index.mjs.map +1 -1
  59. package/dist/esm/runtime/internals/operations/custom.d.ts +1 -1
  60. package/dist/esm/runtime/internals/operations/custom.mjs +91 -85
  61. package/dist/esm/runtime/internals/operations/custom.mjs.map +1 -1
  62. package/dist/esm/runtime/internals/operations/get.d.ts +1 -1
  63. package/dist/esm/runtime/internals/operations/get.mjs +71 -65
  64. package/dist/esm/runtime/internals/operations/get.mjs.map +1 -1
  65. package/dist/esm/runtime/internals/operations/indexQuery.d.ts +1 -1
  66. package/dist/esm/runtime/internals/operations/indexQuery.mjs +66 -60
  67. package/dist/esm/runtime/internals/operations/indexQuery.mjs.map +1 -1
  68. package/dist/esm/runtime/internals/operations/list.d.ts +1 -1
  69. package/dist/esm/runtime/internals/operations/list.mjs +90 -84
  70. package/dist/esm/runtime/internals/operations/list.mjs.map +1 -1
  71. package/dist/esm/runtime/internals/server/generateModelsProperty.mjs +4 -4
  72. package/dist/esm/runtime/internals/server/generateModelsProperty.mjs.map +1 -1
  73. package/dist/esm/runtime/internals/utils/clientProperties/generateModelsProperty.mjs +4 -4
  74. package/dist/esm/runtime/internals/utils/clientProperties/generateModelsProperty.mjs.map +1 -1
  75. package/dist/esm/runtime/utils/index.d.ts +1 -0
  76. package/dist/esm/runtime/utils/index.mjs +1 -0
  77. package/dist/esm/runtime/utils/index.mjs.map +1 -1
  78. package/dist/esm/runtime/utils/selfAwareAsync.d.ts +19 -0
  79. package/dist/esm/runtime/utils/selfAwareAsync.mjs +37 -0
  80. package/dist/esm/runtime/utils/selfAwareAsync.mjs.map +1 -0
  81. package/dist/meta/cjs.tsbuildinfo +1 -1
  82. package/package.json +2 -2
  83. package/src/ClientSchema/Core/ClientModel.ts +29 -0
  84. package/src/ClientSchema/utilities/ResolveField.ts +26 -6
  85. package/src/ModelType.ts +31 -0
  86. package/src/SchemaProcessor.ts +77 -2
  87. package/src/runtime/addSchemaToClient.ts +2 -0
  88. package/src/runtime/addSchemaToClientWithInstance.ts +2 -0
  89. package/src/runtime/bridge-types.ts +2 -2
  90. package/src/runtime/client/index.ts +207 -184
  91. package/src/runtime/internals/APIClient.ts +67 -23
  92. package/src/runtime/internals/cancellation.ts +57 -0
  93. package/src/runtime/internals/clientUtils.ts +61 -1
  94. package/src/runtime/internals/index.ts +1 -0
  95. package/src/runtime/internals/operations/custom.ts +117 -109
  96. package/src/runtime/internals/operations/get.ts +111 -95
  97. package/src/runtime/internals/operations/indexQuery.ts +100 -94
  98. package/src/runtime/internals/operations/list.ts +132 -119
  99. package/src/runtime/internals/server/generateModelsProperty.ts +31 -28
  100. package/src/runtime/internals/utils/clientProperties/generateModelsProperty.ts +36 -33
  101. package/src/runtime/utils/index.ts +1 -0
  102. package/src/runtime/utils/selfAwareAsync.ts +39 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-amplify/data-schema",
3
- "version": "1.3.10",
3
+ "version": "1.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@
16
16
  "clean": "rimraf dist",
17
17
  "docs": "api-extractor run && api-documenter markdown --input-folder temp --output-folder docs",
18
18
  "docs:temp": "api-extractor run && api-documenter markdown --input-folder temp --output-folder temp/docs",
19
- "check:api": "rimraf temp && npm run docs:temp && node ../../scripts/shallow-dir-diff.js docs temp/docs",
19
+ "check:api": "rimraf temp && npm run docs:temp && tsx ../../scripts/shallow-dir-diff.ts docs temp/docs",
20
20
  "lint": "eslint .",
21
21
  "test": "jest"
22
22
  },
@@ -2,6 +2,7 @@ import type {
2
2
  deferredRefResolvingPrefix,
3
3
  ModelTypeParamShape,
4
4
  ModelDefaultIdentifier,
5
+ DisableOperationsOptions,
5
6
  } from '../../ModelType';
6
7
  import type { ClientSchemaProperty } from './ClientSchemaProperty';
7
8
  import type { Authorization, ImpliedAuthFields } from '../../Authorization';
@@ -49,9 +50,37 @@ export interface ClientModel<
49
50
  secondaryIndexes: IndexQueryMethodsFromIR<Bag, T['secondaryIndexes'], K>;
50
51
  __meta: {
51
52
  listOptionsPkParams: ListOptionsPkParams<Bag, T>;
53
+ disabledOperations: DisabledOpsToMap<T['disabledOperations']>;
52
54
  };
53
55
  }
54
56
 
57
+ /**
58
+ * Creates a map of disabled operations, expanding coarse-grained ops into fine-grained ones
59
+ * The map is used in runtime/client/index.ts to Omit any disabled ops from the data-client types
60
+ *
61
+ * @example
62
+ * a.model({...}).disableOperations(['update', 'subscriptions'])
63
+ * Returns
64
+ * {
65
+ * update: true;
66
+ * onCreate: true;
67
+ * onUpdate: true;
68
+ * onDelete: true;
69
+ * observeQuery: true;
70
+ * }
71
+ */
72
+ type DisabledOpsToMap<Ops extends ReadonlyArray<DisableOperationsOptions>> = {
73
+ [Op in Ops[number] as Op extends 'queries'
74
+ ? 'list' | 'get' | 'observeQuery'
75
+ : Op extends 'mutations'
76
+ ? 'create' | 'update' | 'delete'
77
+ : Op extends 'subscriptions'
78
+ ? 'onCreate' | 'onUpdate' | 'onDelete' | 'observeQuery'
79
+ : Op extends 'list'
80
+ ? 'list' | 'observeQuery'
81
+ : Op]: true;
82
+ };
83
+
55
84
  type ClientFields<
56
85
  Bag extends Record<string, unknown>,
57
86
  Metadata extends SchemaMetadata<any>,
@@ -51,15 +51,35 @@ export type ResolveIndividualField<Bag extends Record<string, any>, T> =
51
51
  ? values[number] | null
52
52
  : never;
53
53
 
54
+ /**
55
+ * Resolves to never if the related model has disabled list or get ops for hasOne/hasMany or belongsTo respectively
56
+ */
54
57
  type ResolveRelationship<
55
58
  Bag extends Record<string, any>,
56
59
  RelationshipShape extends ModelRelationalFieldParamShape,
57
- > = LazyLoader<
58
- RelationshipShape['valueRequired'] extends true
59
- ? Bag[RelationshipShape['relatedModel']]['type']
60
- : Bag[RelationshipShape['relatedModel']]['type'] | null,
61
- RelationshipShape['array']
62
- >;
60
+ > = DependentLazyLoaderOpIsAvailable<Bag, RelationshipShape> extends true
61
+ ? LazyLoader<
62
+ RelationshipShape['valueRequired'] extends true
63
+ ? Bag[RelationshipShape['relatedModel']]['type']
64
+ : Bag[RelationshipShape['relatedModel']]['type'] | null,
65
+ RelationshipShape['array']
66
+ >
67
+ : never
68
+ ;
69
+
70
+ type DependentLazyLoaderOpIsAvailable<
71
+ Bag extends Record<string, any>,
72
+ RelationshipShape extends ModelRelationalFieldParamShape,
73
+ > = RelationshipShape['relationshipType'] extends 'hasOne' | 'hasMany'
74
+ ? // hasOne and hasMany depend on `list`
75
+ 'list' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations']
76
+ ? false
77
+ : true
78
+ : // the relationship is a belongsTo, which depends on `get`
79
+ 'get' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations']
80
+ ? false
81
+ : true
82
+ ;
63
83
 
64
84
  type IsRequired<T> =
65
85
  T extends BaseModelField<infer FieldShape>
package/src/ModelType.ts CHANGED
@@ -43,11 +43,25 @@ type InternalModelFields = Record<
43
43
  InternalField | InternalRelationalField
44
44
  >;
45
45
 
46
+ export type DisableOperationsOptions =
47
+ | 'queries'
48
+ | 'mutations'
49
+ | 'subscriptions'
50
+ | 'list'
51
+ | 'get'
52
+ | 'create'
53
+ | 'update'
54
+ | 'delete'
55
+ | 'onCreate'
56
+ | 'onUpdate'
57
+ | 'onDelete';
58
+
46
59
  type ModelData = {
47
60
  fields: ModelFields;
48
61
  identifier: ReadonlyArray<string>;
49
62
  secondaryIndexes: ReadonlyArray<ModelIndexType<any, any, any, any, any>>;
50
63
  authorization: Authorization<any, any, any>[];
64
+ disabledOperations: ReadonlyArray<DisableOperationsOptions>;
51
65
  };
52
66
 
53
67
  type InternalModelData = ModelData & {
@@ -55,6 +69,7 @@ type InternalModelData = ModelData & {
55
69
  identifier: ReadonlyArray<string>;
56
70
  secondaryIndexes: ReadonlyArray<InternalModelIndexType>;
57
71
  authorization: Authorization<any, any, any>[];
72
+ disabledOperations: ReadonlyArray<DisableOperationsOptions>;
58
73
  originalName?: string;
59
74
  };
60
75
 
@@ -63,6 +78,7 @@ export type ModelTypeParamShape = {
63
78
  identifier: PrimaryIndexIrShape;
64
79
  secondaryIndexes: ReadonlyArray<SecondaryIndexIrShape>;
65
80
  authorization: Authorization<any, any, any>[];
81
+ disabledOperations: ReadonlyArray<DisableOperationsOptions>;
66
82
  };
67
83
 
68
84
  /**
@@ -250,6 +266,14 @@ export type ModelType<
250
266
  SetTypeSubArg<T, 'secondaryIndexes', IndexesIR>,
251
267
  UsedMethod | 'secondaryIndexes'
252
268
  >;
269
+ disableOperations<
270
+ const Ops extends ReadonlyArray<DisableOperationsOptions>,
271
+ >(
272
+ ops: Ops,
273
+ ): ModelType<
274
+ SetTypeSubArg<T, 'disabledOperations', Ops>,
275
+ UsedMethod | 'disableOperations'
276
+ >;
253
277
  authorization<AuthRuleType extends Authorization<any, any, any>>(
254
278
  callback: (
255
279
  allow: Omit<AllowModifier, 'resource'>,
@@ -302,6 +326,7 @@ function _model<T extends ModelTypeParamShape>(fields: T['fields']) {
302
326
  identifier: ['id'],
303
327
  secondaryIndexes: [],
304
328
  authorization: [],
329
+ disabledOperations: [],
305
330
  };
306
331
 
307
332
  const builder = {
@@ -315,6 +340,11 @@ function _model<T extends ModelTypeParamShape>(fields: T['fields']) {
315
340
 
316
341
  return this;
317
342
  },
343
+ disableOperations(ops) {
344
+ data.disabledOperations = ops;
345
+
346
+ return this;
347
+ },
318
348
  authorization(callback) {
319
349
  const { resource: _, ...rest } = allow;
320
350
  const rules = callback(rest);
@@ -375,6 +405,7 @@ export function model<T extends ModelFields>(
375
405
  identifier: ModelDefaultIdentifier;
376
406
  secondaryIndexes: [];
377
407
  authorization: [];
408
+ disabledOperations: [];
378
409
  }> {
379
410
  return _model(fields);
380
411
  }
@@ -10,7 +10,7 @@ import {
10
10
  ModelRelationshipTypes,
11
11
  type InternalRelationalField,
12
12
  } from './ModelRelationalField';
13
- import type { InternalModel } from './ModelType';
13
+ import type { InternalModel, DisableOperationsOptions } from './ModelType';
14
14
  import type { InternalModelIndexType } from './ModelIndex';
15
15
  import {
16
16
  type Authorization,
@@ -1455,7 +1455,13 @@ const schemaPreprocessor = (
1455
1455
 
1456
1456
  const joined = gqlFields.join('\n ');
1457
1457
 
1458
- const model = `type ${typeName} @model ${authString}\n{\n ${joined}\n}`;
1458
+ const modelAttrs = modelAttributesFromDisabledOps(
1459
+ typeDef.data.disabledOperations,
1460
+ );
1461
+
1462
+ const modelDirective = modelAttrs ? `@model(${modelAttrs})` : '@model';
1463
+
1464
+ const model = `type ${typeName} ${modelDirective} ${authString}\n{\n ${joined}\n}`;
1459
1465
  gqlModels.push(model);
1460
1466
  }
1461
1467
  }
@@ -2180,6 +2186,75 @@ function getModelRelationship(
2180
2186
  }
2181
2187
  }
2182
2188
 
2189
+ /**
2190
+ *
2191
+ * @param disabledOps
2192
+ * @returns sanitized string @model directive attribute; can be passed in as-is
2193
+ *
2194
+ * @example
2195
+ * ```ts
2196
+ * const disabledOps = ["subscriptions", "create"];
2197
+ * ```
2198
+ * returns
2199
+ * ```
2200
+ * subscriptions:null,mutations:{create:null}
2201
+ * ```
2202
+ */
2203
+ function modelAttributesFromDisabledOps(
2204
+ disabledOps: ReadonlyArray<DisableOperationsOptions>,
2205
+ ) {
2206
+ const fineCoarseMap: Record<string, string> = {
2207
+ onCreate: 'subscriptions',
2208
+ onUpdate: 'subscriptions',
2209
+ onDelete: 'subscriptions',
2210
+ create: 'mutations',
2211
+ update: 'mutations',
2212
+ delete: 'mutations',
2213
+ list: 'queries',
2214
+ get: 'queries',
2215
+ };
2216
+
2217
+ const coarseGrainedOps = ['queries', 'mutations', 'subscriptions'];
2218
+
2219
+ const coarseFirstSorted = disabledOps
2220
+ // disabledOps is readOnly; create a copy w/ slice
2221
+ .slice()
2222
+ .sort((a: DisableOperationsOptions, b: DisableOperationsOptions) => {
2223
+ if (coarseGrainedOps.includes(a) && !coarseGrainedOps.includes(b)) {
2224
+ return -1;
2225
+ }
2226
+
2227
+ if (!coarseGrainedOps.includes(a) && coarseGrainedOps.includes(b)) {
2228
+ return 1;
2229
+ }
2230
+
2231
+ return 0;
2232
+ });
2233
+
2234
+ const modelAttrs: Record<string, null | Record<string, null>> = {};
2235
+
2236
+ for (const op of coarseFirstSorted) {
2237
+ if (coarseGrainedOps.includes(op)) {
2238
+ modelAttrs[op] = null;
2239
+ continue;
2240
+ }
2241
+
2242
+ const coarseOp = fineCoarseMap[op];
2243
+
2244
+ if (modelAttrs[coarseOp] !== null) {
2245
+ modelAttrs[coarseOp] = modelAttrs[coarseOp] || {};
2246
+
2247
+ modelAttrs[coarseOp]![op] = null;
2248
+ }
2249
+ }
2250
+
2251
+ const modelAttrsStr = JSON.stringify(modelAttrs)
2252
+ .replace(/"/g, '') // remove quotes
2253
+ .slice(1, -1); // drop outer curlies {}
2254
+
2255
+ return modelAttrsStr;
2256
+ }
2257
+
2183
2258
  /**
2184
2259
  * Returns API definition from ModelSchema or string schema
2185
2260
  * @param arg - { schema }
@@ -8,6 +8,7 @@ import {
8
8
  generateCustomSubscriptionsProperty,
9
9
  generateEnumsProperty,
10
10
  generateModelsProperty,
11
+ upgradeClientCancellation,
11
12
  } from './internals';
12
13
  import {
13
14
  BaseClient,
@@ -20,6 +21,7 @@ export function addSchemaToClient<T extends Record<any, any> = never>(
20
21
  apiGraphqlConfig: GraphQLProviderConfig['GraphQL'],
21
22
  getInternals: ClientInternalsGetter,
22
23
  ): BaseClient & ClientExtensions<T> {
24
+ upgradeClientCancellation(client);
23
25
  (client as any).models = generateModelsProperty<T>(
24
26
  client as any,
25
27
  apiGraphqlConfig,
@@ -10,6 +10,7 @@ import {
10
10
  generateCustomQueriesProperty,
11
11
  generateCustomMutationsProperty,
12
12
  generateEnumsProperty,
13
+ upgradeClientCancellation,
13
14
  } from './internals';
14
15
  import { generateModelsProperty as generateModelsPropertyServer } from './internals/server';
15
16
  import { BaseClient, ClientInternalsGetter } from './bridge-types';
@@ -24,6 +25,7 @@ export function addSchemaToClientWithInstance<T extends Record<any, any>>(
24
25
  const apiGraphqlConfig = params.config?.API?.GraphQL;
25
26
 
26
27
  if (isApiGraphQLConfig(apiGraphqlConfig)) {
28
+ upgradeClientCancellation(client);
27
29
  (client as any).models = generateModelsPropertyServer<T>(
28
30
  client as any,
29
31
  params,
@@ -374,10 +374,10 @@ export type BaseSSRClient = {
374
374
  export type GraphQLMethod = (
375
375
  options: GraphQLOptions,
376
376
  additionalHeaders?: CustomHeaders | undefined,
377
- ) => GraphQLResult | GraphqlSubscriptionResult;
377
+ ) => Promise<GraphQLResult> | GraphqlSubscriptionResult;
378
378
 
379
379
  export type GraphQLMethodSSR = (
380
380
  contextSpec: AmplifyServer.ContextSpec,
381
381
  options: GraphQLOptions,
382
382
  additionalHeaders?: CustomHeaders | undefined,
383
- ) => GraphQLResult | GraphqlSubscriptionResult;
383
+ ) => Promise<GraphQLResult> | GraphqlSubscriptionResult;