@aws-amplify/data-schema 0.13.3 → 0.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@aws-amplify/data-schema/internals",
3
+ "types": "../lib-esm/src/internals/index.d.ts",
4
+ "main": "../lib-esm/src/internals/index.js",
5
+ "sideEffects": false
6
+ }
@@ -1,15 +1,18 @@
1
- import { SetTypeSubArg, Brand } from '@aws-amplify/data-schema-types';
1
+ import { SetTypeSubArg } from '@aws-amplify/data-schema-types';
2
+ import { Brand } from './util';
2
3
  import { ModelField, InternalField } from './ModelField';
3
4
  import { Authorization } from './Authorization';
4
5
  import { RefType, InternalRef } from './RefType';
5
6
  import { EnumType, EnumTypeParamShape } from './EnumType';
6
7
  import { CustomType } from './CustomType';
8
+ import { Handler } from './Handler';
7
9
  type CustomArguments = Record<string, ModelField<any, any> | EnumType<EnumTypeParamShape>>;
8
10
  type CustomReturnType = RefType<any> | CustomType<any>;
9
11
  type CustomFunctionRefType = string;
10
12
  type InternalCustomArguments = Record<string, InternalField>;
11
13
  type InternalCustomReturnType = InternalRef;
12
14
  declare const brandName = "customOperation";
15
+ type HandlerInputType = Handler | Handler[];
13
16
  export declare const CustomOperationNames: readonly ["Query", "Mutation", "Subscription"];
14
17
  type CustomOperationName = (typeof CustomOperationNames)[number];
15
18
  type CustomData = {
@@ -18,6 +21,7 @@ type CustomData = {
18
21
  functionRef: string | null;
19
22
  authorization: Authorization<any, any, any>[];
20
23
  typeName: CustomOperationName;
24
+ handlers: Handler[] | null;
21
25
  };
22
26
  type InternalCustomData = CustomData & {
23
27
  arguments: InternalCustomArguments;
@@ -31,13 +35,15 @@ export type CustomOperationParamShape = {
31
35
  functionRef: string | null;
32
36
  authorization: Authorization<any, any, any>[];
33
37
  typeName: CustomOperationName;
38
+ handlers: Handler[] | null;
34
39
  };
35
40
  export type CustomOperation<T extends CustomOperationParamShape, K extends keyof CustomOperation<T> = never> = Omit<{
36
41
  arguments<Arguments extends CustomArguments>(args: Arguments): CustomOperation<SetTypeSubArg<T, 'arguments', Arguments>, K | 'arguments'>;
37
42
  returns<ReturnType extends CustomReturnType>(returnType: ReturnType): CustomOperation<SetTypeSubArg<T, 'returnType', ReturnType>, K | 'returns'>;
38
43
  function<FunctionRef extends CustomFunctionRefType>(functionRefOrName: FunctionRef): CustomOperation<SetTypeSubArg<T, 'functionRef', FunctionRef>, K | 'function'>;
39
44
  authorization<AuthRuleType extends Authorization<any, any, any>>(rules: AuthRuleType[]): CustomOperation<SetTypeSubArg<T, 'authorization', AuthRuleType[]>, K | 'authorization'>;
40
- }, K> & Brand<object, typeof brandName>;
45
+ handler(handlers: HandlerInputType): CustomOperation<SetTypeSubArg<T, 'handlers', Handler[]>, K | 'handler'>;
46
+ }, K> & Brand<typeof brandName>;
41
47
  /**
42
48
  * Internal representation of Custom Type that exposes the `data` property.
43
49
  * Used at buildtime.
@@ -51,6 +57,7 @@ export declare function query(): CustomOperation<{
51
57
  functionRef: null;
52
58
  authorization: [];
53
59
  typeName: 'Query';
60
+ handlers: null;
54
61
  }>;
55
62
  export declare function mutation(): CustomOperation<{
56
63
  arguments: CustomArguments;
@@ -58,6 +65,7 @@ export declare function mutation(): CustomOperation<{
58
65
  functionRef: null;
59
66
  authorization: [];
60
67
  typeName: 'Mutation';
68
+ handlers: null;
61
69
  }>;
62
70
  export declare function subscription(): CustomOperation<{
63
71
  arguments: CustomArguments;
@@ -65,5 +73,6 @@ export declare function subscription(): CustomOperation<{
65
73
  functionRef: null;
66
74
  authorization: [];
67
75
  typeName: 'Subscription';
76
+ handlers: null;
68
77
  }>;
69
78
  export {};
@@ -17,6 +17,7 @@ function _custom(typeName) {
17
17
  functionRef: null,
18
18
  authorization: [],
19
19
  typeName: typeName,
20
+ handlers: null,
20
21
  };
21
22
  const builder = brandedBuilder({
22
23
  arguments(args) {
@@ -35,6 +36,10 @@ function _custom(typeName) {
35
36
  data.authorization = rules;
36
37
  return this;
37
38
  },
39
+ handler(handlers) {
40
+ data.handlers = Array.isArray(handlers) ? handlers : [handlers];
41
+ return this;
42
+ },
38
43
  });
39
44
  return { ...builder, data };
40
45
  }
@@ -1,4 +1,4 @@
1
- import { Brand } from '@aws-amplify/data-schema-types';
1
+ import { Brand } from './util';
2
2
  import { ModelField, InternalField, ModelFieldTypeParamOuter } from './ModelField';
3
3
  /**
4
4
  * Custom Types
@@ -19,7 +19,7 @@ type InternalCustomTypeData = CustomTypeData & {
19
19
  export type CustomTypeParamShape = {
20
20
  fields: CustomTypeFields;
21
21
  };
22
- export type CustomType<T extends CustomTypeParamShape> = Brand<T, 'customType'>;
22
+ export type CustomType<T extends CustomTypeParamShape> = T & Brand<'customType'>;
23
23
  /**
24
24
  * Internal representation of CustomType that exposes the `data` property.
25
25
  * Used at buildtime.
@@ -1,9 +1,9 @@
1
- import { Brand } from '@aws-amplify/data-schema-types';
1
+ import { Brand } from './util';
2
2
  export type EnumTypeParamShape = {
3
3
  type: 'enum';
4
4
  values: readonly string[];
5
5
  };
6
- export type EnumType<T extends EnumTypeParamShape> = Brand<T, 'enum'>;
6
+ export type EnumType<T extends EnumTypeParamShape> = T & Brand<'enum'>;
7
7
  type EnumTypeArgFactory<Values extends readonly string[]> = {
8
8
  type: 'enum';
9
9
  values: Values;
@@ -0,0 +1,26 @@
1
+ import { Brand } from './util';
2
+ declare const brandName = "Handler";
3
+ export type Handler = Brand<typeof brandName>;
4
+ type InlineSqlResult = {
5
+ sql: string;
6
+ } & Handler;
7
+ declare function inlineSql(sql: string): InlineSqlResult;
8
+ type SqlReferenceResult = {
9
+ sqlReference: string;
10
+ } & Handler;
11
+ declare function sqlReference(sqlReference: string): SqlReferenceResult;
12
+ type CustomResult = {
13
+ custom: string;
14
+ } & Handler;
15
+ declare function custom(file: string): CustomResult;
16
+ type FunctionResult = {
17
+ function: (...args: any[]) => any;
18
+ } & Handler;
19
+ declare function fcn(fcn: (...args: any[]) => any): FunctionResult;
20
+ export declare const handler: {
21
+ inlineSql: typeof inlineSql;
22
+ sqlReference: typeof sqlReference;
23
+ custom: typeof custom;
24
+ function: typeof fcn;
25
+ };
26
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const util_1 = require("./util");
5
+ const brandName = 'Handler';
6
+ function buildHandler() {
7
+ return (0, util_1.brand)(brandName);
8
+ }
9
+ function inlineSql(sql) {
10
+ return { sql, ...buildHandler() };
11
+ }
12
+ function sqlReference(sqlReference) {
13
+ return { sqlReference, ...buildHandler() };
14
+ }
15
+ function custom(file) {
16
+ return { custom: file, ...buildHandler() };
17
+ }
18
+ function fcn(fcn) {
19
+ return { function: fcn, ...buildHandler() };
20
+ }
21
+ exports.handler = {
22
+ inlineSql,
23
+ sqlReference,
24
+ custom,
25
+ function: fcn,
26
+ };
@@ -15,7 +15,7 @@ export type ExtractNonModelTypes<Schema> = ResolveNonModelFields<ResolveNonModel
15
15
  */
16
16
  type ExtractImplicitNonModelTypes<Schema, ResolvedModels = ModelTypes<SchemaTypes<Schema>>> = UnionToIntersection<{
17
17
  [Model in keyof ResolvedModels]: {
18
- [Field in keyof ResolvedModels[Model] as ResolvedModels[Model][Field] extends EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape> ? `${Capitalize<Field & string>}` : never]: ResolvedModels[Model][Field];
18
+ [Field in keyof ResolvedModels[Model] as ResolvedModels[Model][Field] extends EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape> ? `${Capitalize<Model & string>}${Capitalize<Field & string>}` : never]: ResolvedModels[Model][Field];
19
19
  };
20
20
  }[keyof ResolvedModels]>;
21
21
  type ResolveNonModelTypes<Schema, Extracted, ResolvedSchema = SchemaTypes<Schema> & Extracted> = {
@@ -26,7 +26,7 @@ export type ModelTypes<Schema> = {
26
26
  export type FieldTypes<T> = {
27
27
  [ModelProp in keyof T]: {
28
28
  [FieldProp in keyof T[ModelProp]]: T[ModelProp][FieldProp] extends RefType<infer R extends RefTypeParamShape, any, any> ? R['required'] extends true ? T[ModelProp][FieldProp] : T[ModelProp][FieldProp] | null : T[ModelProp][FieldProp] extends EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape> ? RefType<{
29
- link: Capitalize<FieldProp & string>;
29
+ link: `${Capitalize<ModelProp & string>}${Capitalize<FieldProp & string>}`;
30
30
  type: 'ref';
31
31
  required: false;
32
32
  authorization: [];
@@ -1,4 +1,4 @@
1
- import { Brand } from '@aws-amplify/data-schema-types';
1
+ import { Brand } from './util';
2
2
  import { Authorization } from './Authorization';
3
3
  /**
4
4
  * Used to "attach" auth types to ModelField without exposing them on the builder.
@@ -73,7 +73,7 @@ export type ModelField<T extends ModelFieldTypeParamOuter, K extends keyof Model
73
73
  authorization<AuthRuleType extends Authorization<any, any, any>>(rules: AuthRuleType[]): ModelField<T, K | 'authorization', AuthRuleType>;
74
74
  }, K> & {
75
75
  [__auth]?: Auth;
76
- } & Brand<object, typeof brandName>;
76
+ } & Brand<typeof brandName>;
77
77
  /**
78
78
  * Internal representation of Model Field that exposes the `data` property.
79
79
  * Used at buildtime.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ipAddress = exports.url = exports.phone = exports.json = exports.email = exports.timestamp = exports.datetime = exports.time = exports.date = exports.boolean = exports.float = exports.integer = exports.string = exports.id = exports.ModelFieldDataType = exports.ModelFieldType = exports.__auth = void 0;
4
+ const util_1 = require("./util");
4
5
  /**
5
6
  * Used to "attach" auth types to ModelField without exposing them on the builder.
6
7
  */
@@ -81,6 +82,7 @@ function _field(fieldType) {
81
82
  _meta.lastInvokedMethod = 'authorization';
82
83
  return this;
83
84
  },
85
+ ...(0, util_1.brand)(brandName),
84
86
  };
85
87
  // this double cast gives us a Subtyping Constraint i.e., hides `data` from the public API,
86
88
  // but makes it available internally when needed
@@ -1,5 +1,5 @@
1
- import type { Brand } from '@aws-amplify/data-schema-types';
2
- declare const brand = "modelIndexType";
1
+ import { Brand } from './util';
2
+ declare const brandName = "modelIndexType";
3
3
  export type ModelIndexData = {
4
4
  partitionKey: string;
5
5
  sortKeys: readonly unknown[];
@@ -13,6 +13,6 @@ export type ModelIndexType<ModelFieldKeys extends string, PK, SK = readonly [],
13
13
  sortKeys<FieldKeys extends ModelFieldKeys = ModelFieldKeys, const SK extends ReadonlyArray<Exclude<FieldKeys, PK>> = readonly []>(sortKeys: SK): ModelIndexType<FieldKeys, PK, SK, QueryField, K | 'sortKeys'>;
14
14
  name(name: string): ModelIndexType<ModelFieldKeys, PK, SK, QueryField, K | 'name'>;
15
15
  queryField<QF extends string = never, MF extends ModelFieldKeys = ModelFieldKeys>(field: QF): ModelIndexType<MF, PK, SK, QF, K | 'queryField'>;
16
- }, K> & Brand<object, typeof brand>;
16
+ }, K> & Brand<typeof brandName>;
17
17
  export declare function modelIndex<ModelFieldKeys extends string, PK extends ModelFieldKeys, SK = readonly [], QueryField = never>(partitionKeyFieldName: PK): ModelIndexType<ModelFieldKeys, PK, SK, QueryField, never>;
18
18
  export {};
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.modelIndex = void 0;
4
- const brand = 'modelIndexType';
4
+ const util_1 = require("./util");
5
+ const brandName = 'modelIndexType';
5
6
  function _modelIndex(partitionKeyFieldName) {
6
7
  const data = {
7
8
  partitionKey: partitionKeyFieldName,
@@ -22,6 +23,7 @@ function _modelIndex(partitionKeyFieldName) {
22
23
  data.queryField = field;
23
24
  return this;
24
25
  },
26
+ ...(0, util_1.brand)(brandName),
25
27
  };
26
28
  return { ...builder, data };
27
29
  }
@@ -1,4 +1,5 @@
1
- import { SetTypeSubArg, Brand } from '@aws-amplify/data-schema-types';
1
+ import { SetTypeSubArg } from '@aws-amplify/data-schema-types';
2
+ import { Brand } from './util';
2
3
  import { Authorization } from './Authorization';
3
4
  /**
4
5
  * Used to "attach" auth types to ModelField without exposing them on the builder.
@@ -60,7 +61,7 @@ type ModelRelationalFieldFunctions<T extends ModelRelationalFieldParamShape, RM
60
61
  };
61
62
  export type ModelRelationalField<T extends ModelRelationalFieldParamShape, RM extends string | symbol, K extends keyof ModelRelationalField<T, RM> = never, Auth = undefined> = Omit<ModelRelationalFieldFunctions<T, RM, K>, K> & {
62
63
  [__auth]?: Auth;
63
- } & Brand<object, typeof brandName>;
64
+ } & Brand<typeof brandName>;
64
65
  /**
65
66
  * Internal representation of Model Field that exposes the `data` property.
66
67
  * Used at buildtime.
@@ -3,14 +3,43 @@ import { type ModelType, type ModelTypeParamShape, type InternalModel, SchemaMod
3
3
  import type { EnumType, EnumTypeParamShape } from './EnumType';
4
4
  import type { CustomType, CustomTypeParamShape } from './CustomType';
5
5
  import type { CustomOperation, CustomOperationParamShape, InternalCustom } from './CustomOperation';
6
- export { __auth } from './ModelField';
7
6
  import { Authorization } from './Authorization';
8
7
  type SchemaContent = ModelType<ModelTypeParamShape, any> | CustomType<CustomTypeParamShape> | EnumType<EnumTypeParamShape> | CustomOperation<CustomOperationParamShape, any>;
9
8
  type ModelSchemaContents = Record<string, SchemaContent>;
10
9
  type InternalSchemaModels = Record<string, InternalModel | EnumType<any> | CustomType<any> | InternalCustom>;
10
+ /**
11
+ * Importing the full objects from @aws-amplify/plugin-types
12
+ * more than doubles dev env runtime. This type replacement
13
+ * will contain the content for config without the negative
14
+ * side-effects. We may need to re-approach if customers interact
15
+ * with these programmatically to avoid forcing narrowing.
16
+ */
17
+ type BackendSecret = {
18
+ resolve: (scope: any, backendIdentifier: any) => any;
19
+ resolvePath: (backendIdentifier: any) => any;
20
+ };
21
+ export type DatasourceEngine = 'mysql' | 'postgresql' | 'dynamodb';
22
+ type DatasourceConfig<DE extends DatasourceEngine> = DE extends 'dynamodb' ? {
23
+ engine: DE;
24
+ } : {
25
+ engine: DE;
26
+ hostname: BackendSecret;
27
+ username: BackendSecret;
28
+ password: BackendSecret;
29
+ port: BackendSecret;
30
+ databaseName: BackendSecret;
31
+ vpcConfig?: Record<string, never>;
32
+ };
33
+ export type SchemaConfig<DE extends DatasourceEngine, DC extends DatasourceConfig<DE>> = {
34
+ database: DC;
35
+ };
11
36
  export type ModelSchemaParamShape = {
12
37
  types: ModelSchemaContents;
13
38
  authorization: Authorization<any, any, any>[];
39
+ configuration: SchemaConfig<any, any>;
40
+ };
41
+ export type SQLModelSchemaParamShape = ModelSchemaParamShape & {
42
+ setSqlStatementFolderPath?: string;
14
43
  };
15
44
  export type InternalSchema = {
16
45
  data: {
@@ -27,6 +56,9 @@ export type ModelSchema<T extends ModelSchemaParamShape, UsedMethods extends 'au
27
56
  };
28
57
  transform: () => DerivedApiDefinition;
29
58
  };
59
+ export type SqlModelSchema<T extends SQLModelSchemaParamShape, UsedMethods extends 'authorization' | 'setSqlStatementFolderPath' = never> = ModelSchema<T, Exclude<UsedMethods, 'setSqlStatementFolderPath'>> & Omit<{
60
+ setSqlStatementFolderPath: (path: string) => SqlModelSchema<T, UsedMethods | 'setSqlStatementFolderPath'>;
61
+ }, UsedMethods>;
30
62
  /**
31
63
  * Amplify API Next Model Schema shape
32
64
  */
@@ -37,6 +69,15 @@ export type ModelSchemaType = ModelSchema<ModelSchemaParamShape>;
37
69
  * @returns true if the given value is a ModelSchema
38
70
  */
39
71
  export declare const isModelSchema: (schema: string | ModelSchemaType) => schema is ModelSchemaType;
72
+ type SchemaReturnType<DE extends DatasourceEngine, Types extends ModelSchemaContents> = DE extends 'dynamodb' ? ModelSchema<{
73
+ types: Types;
74
+ authorization: [];
75
+ configuration: any;
76
+ }> : SqlModelSchema<{
77
+ types: Types;
78
+ authorization: [];
79
+ configuration: any;
80
+ }>;
40
81
  /**
41
82
  * The API and data model definition for Amplify Data. Pass in `{ <NAME>: a.model(...) }` to create a database table
42
83
  * and exposes CRUDL operations via an API.
@@ -44,7 +85,19 @@ export declare const isModelSchema: (schema: string | ModelSchemaType) => schema
44
85
  * @returns An API and data model definition to be deployed with Amplify (Gen 2) experience (`processSchema(...)`)
45
86
  * or with the Amplify Data CDK construct (`@aws-amplify/data-construct`)
46
87
  */
47
- export declare function schema<Types extends ModelSchemaContents>(types: Types): ModelSchema<{
88
+ export declare const schema: <Types extends ModelSchemaContents>(types: Types) => ModelSchema<{
48
89
  types: Types;
49
90
  authorization: [];
50
- }>;
91
+ configuration: any;
92
+ }, never>;
93
+ /**
94
+ * Configure wraps schema definition with non-default config to allow usecases other than
95
+ * the default DynamoDB use-case.
96
+ *
97
+ * @param config The SchemaConfig augments the schema with content like the database type
98
+ * @returns
99
+ */
100
+ export declare function configure<DE extends DatasourceEngine>(config: SchemaConfig<DE, DatasourceConfig<DE>>): {
101
+ schema: <Types extends ModelSchemaContents>(types: Types) => SchemaReturnType<DE, Types>;
102
+ };
103
+ export {};
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.schema = exports.isModelSchema = exports.__auth = void 0;
3
+ exports.configure = exports.schema = exports.isModelSchema = void 0;
4
4
  const ModelType_1 = require("./ModelType");
5
- var ModelField_1 = require("./ModelField");
6
- Object.defineProperty(exports, "__auth", { enumerable: true, get: function () { return ModelField_1.__auth; } });
7
5
  const SchemaProcessor_1 = require("./SchemaProcessor");
8
6
  /**
9
7
  * Filter the schema types down to only include the ModelTypes as SchemaModelType
@@ -31,22 +29,41 @@ const isModelSchema = (schema) => {
31
29
  return typeof schema === 'object' && schema.data !== undefined;
32
30
  };
33
31
  exports.isModelSchema = isModelSchema;
34
- function _schema(types) {
35
- const data = { types, authorization: [] };
36
- const models = filterSchemaModelTypes(data.types);
37
- const transform = () => {
38
- const internalSchema = { data };
39
- return (0, SchemaProcessor_1.processSchema)({ schema: internalSchema });
32
+ function _sqlSchemaExtension(schema) {
33
+ return {
34
+ ...schema,
35
+ setSqlStatementFolderPath(path) {
36
+ this.data.setSqlStatementFolderPath = path;
37
+ const { setSqlStatementFolderPath: _, ...rest } = this;
38
+ return rest;
39
+ },
40
40
  };
41
- const authorization = (rules) => {
42
- data.authorization = rules;
43
- return { data, transform, models };
41
+ }
42
+ function _baseSchema(types, config) {
43
+ const data = {
44
+ types,
45
+ authorization: [],
46
+ configuration: config,
44
47
  };
45
48
  return {
46
49
  data,
47
- transform,
48
- authorization,
49
- models,
50
+ transform() {
51
+ const internalSchema = { data };
52
+ return (0, SchemaProcessor_1.processSchema)({ schema: internalSchema });
53
+ },
54
+ authorization(rules) {
55
+ this.data.authorization = rules;
56
+ const { authorization: _, ...rest } = this;
57
+ return rest;
58
+ },
59
+ models: filterSchemaModelTypes(data.types),
60
+ };
61
+ }
62
+ function bindConfigToSchema(config) {
63
+ return (types) => {
64
+ return (config.database.engine === 'dynamodb'
65
+ ? _baseSchema(types, config)
66
+ : _sqlSchemaExtension(_baseSchema(types, config)));
50
67
  };
51
68
  }
52
69
  /**
@@ -56,7 +73,17 @@ function _schema(types) {
56
73
  * @returns An API and data model definition to be deployed with Amplify (Gen 2) experience (`processSchema(...)`)
57
74
  * or with the Amplify Data CDK construct (`@aws-amplify/data-construct`)
58
75
  */
59
- function schema(types) {
60
- return _schema(types);
76
+ exports.schema = bindConfigToSchema({ database: { engine: 'dynamodb' } });
77
+ /**
78
+ * Configure wraps schema definition with non-default config to allow usecases other than
79
+ * the default DynamoDB use-case.
80
+ *
81
+ * @param config The SchemaConfig augments the schema with content like the database type
82
+ * @returns
83
+ */
84
+ function configure(config) {
85
+ return {
86
+ schema: bindConfigToSchema(config),
87
+ };
61
88
  }
62
- exports.schema = schema;
89
+ exports.configure = configure;
@@ -1,4 +1,5 @@
1
- import type { Brand, SetTypeSubArg, SecondaryIndexIrShape } from '@aws-amplify/data-schema-types';
1
+ import type { SetTypeSubArg, SecondaryIndexIrShape } from '@aws-amplify/data-schema-types';
2
+ import { Brand } from './util';
2
3
  import { ModelField, InternalField } from './ModelField';
3
4
  import type { ModelRelationalField, InternalRelationalField } from './ModelRelationalField';
4
5
  import { Authorization } from './Authorization';
@@ -7,7 +8,7 @@ import { EnumType, EnumTypeParamShape } from './EnumType';
7
8
  import { CustomType, CustomTypeParamShape } from './CustomType';
8
9
  import { ModelIndexType, InternalModelIndexType } from './ModelIndex';
9
10
  import { SecondaryIndexToIR } from './MappedTypes/MapSecondaryIndexes';
10
- declare const brand = "modelType";
11
+ declare const brandName = "modelType";
11
12
  type ModelFields = Record<string, ModelField<any, any, any> | ModelRelationalField<any, string, any, any> | RefType<any, any, any> | EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape>>;
12
13
  type InternalModelFields = Record<string, InternalField | InternalRelationalField>;
13
14
  type ModelData = {
@@ -44,7 +45,7 @@ export type ModelType<T extends ModelTypeParamShape, K extends keyof ModelType<T
44
45
  identifier<ID extends IdentifierType<T> = []>(identifier: ID): ModelType<SetTypeSubArg<T, 'identifier', ID>, K | 'identifier'>;
45
46
  secondaryIndexes<const Indexes extends readonly ModelIndexType<SecondaryIndexFields<ExtractType<T>>, SecondaryIndexFields<ExtractType<T>>, unknown, never, any>[] = readonly [], const IndexesIR extends readonly any[] = SecondaryIndexToIR<Indexes, ExtractType<T>>>(indexes: Indexes): ModelType<SetTypeSubArg<T, 'secondaryIndexes', IndexesIR>, K | 'secondaryIndexes'>;
46
47
  authorization<AuthRuleType extends Authorization<any, any, any>>(rules: AuthRuleType[]): ModelType<SetTypeSubArg<T, 'authorization', AuthRuleType[]>, K | 'authorization'>;
47
- }, K> & Brand<object, typeof brand>;
48
+ }, K> & Brand<typeof brandName>;
48
49
  /**
49
50
  * External representation of Model Type that exposes the `addRelationships` modifier.
50
51
  * Used on the complete schema object.
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.model = exports.isSchemaModelType = void 0;
4
- const brand = 'modelType';
4
+ const util_1 = require("./util");
5
+ const brandName = 'modelType';
5
6
  function _model(fields) {
6
7
  const data = {
7
8
  fields,
@@ -22,6 +23,7 @@ function _model(fields) {
22
23
  data.authorization = rules;
23
24
  return this;
24
25
  },
26
+ ...(0, util_1.brand)(brandName),
25
27
  };
26
28
  return {
27
29
  ...builder,
@@ -1,4 +1,5 @@
1
- import { SetTypeSubArg, Brand } from '@aws-amplify/data-schema-types';
1
+ import { SetTypeSubArg } from '@aws-amplify/data-schema-types';
2
+ import { Brand } from './util';
2
3
  import { Authorization } from './Authorization';
3
4
  import { __auth } from './ModelField';
4
5
  declare const brandName = "ref";
@@ -26,7 +27,7 @@ export type RefType<T extends RefTypeParamShape, K extends keyof RefType<T> = ne
26
27
  authorization<AuthRuleType extends Authorization<any, any, any>>(rules: AuthRuleType[]): RefType<T, K | 'authorization', AuthRuleType>;
27
28
  }, K> & {
28
29
  [__auth]?: Auth;
29
- } & Brand<object, typeof brandName>;
30
+ } & Brand<typeof brandName>;
30
31
  /**
31
32
  * Internal representation of Ref that exposes the `data` property.
32
33
  * Used at buildtime.
@@ -123,8 +123,8 @@ function refFieldToGql(fieldDef) {
123
123
  // }
124
124
  return field;
125
125
  }
126
- function customOperationToGql(typeName, typeDef) {
127
- const { arguments: fieldArgs, returnType, authorization, functionRef, } = typeDef.data;
126
+ function customOperationToGql(typeName, typeDef, authorization) {
127
+ const { arguments: fieldArgs, returnType, functionRef } = typeDef.data;
128
128
  let callSignature = typeName;
129
129
  const implicitModels = [];
130
130
  const { authString } = calculateAuth(authorization);
@@ -143,7 +143,7 @@ function customOperationToGql(typeName, typeDef) {
143
143
  throw new Error(`Unrecognized return type on ${typeName}`);
144
144
  }
145
145
  if (Object.keys(fieldArgs).length > 0) {
146
- const { gqlFields, models } = processFields(fieldArgs, {});
146
+ const { gqlFields, models } = processFields(typeName, fieldArgs, {});
147
147
  callSignature += `(${gqlFields.join(', ')})`;
148
148
  implicitModels.push(...models);
149
149
  }
@@ -434,7 +434,7 @@ function processFieldLevelAuthRules(fields, authFields) {
434
434
  }
435
435
  return fieldLevelAuthRules;
436
436
  }
437
- function processFields(fields, fieldLevelAuthRules, identifier, partitionKey, secondaryIndexes = {}) {
437
+ function processFields(typeName, fields, fieldLevelAuthRules, identifier, partitionKey, secondaryIndexes = {}) {
438
438
  const gqlFields = [];
439
439
  const models = [];
440
440
  for (const [fieldName, fieldDef] of Object.entries(fields)) {
@@ -452,12 +452,16 @@ function processFields(fields, fieldLevelAuthRules, identifier, partitionKey, se
452
452
  gqlFields.push(`${fieldName}: ${refFieldToGql(fieldDef.data)}${fieldAuth}`);
453
453
  }
454
454
  else if (isEnumType(fieldDef)) {
455
- const enumName = capitalize(fieldName);
455
+ // The inline enum type name should be `<TypeName><FieldName>` to avoid
456
+ // enum type name conflicts
457
+ const enumName = `${capitalize(typeName)}${capitalize(fieldName)}`;
456
458
  models.push([enumName, fieldDef]);
457
459
  gqlFields.push(`${fieldName}: ${enumName}`);
458
460
  }
459
461
  else if (isCustomType(fieldDef)) {
460
- const customTypeName = capitalize(fieldName);
462
+ // The inline CustomType name should be `<TypeName><FieldName>` to avoid
463
+ // CustomType name conflicts
464
+ const customTypeName = `${capitalize(typeName)}${capitalize(fieldName)}`;
461
465
  models.push([customTypeName, fieldDef]);
462
466
  gqlFields.push(`${fieldName}: ${customTypeName}`);
463
467
  }
@@ -520,8 +524,14 @@ const schemaPreprocessor = (schema) => {
520
524
  const fkFields = allImpliedFKs(schema);
521
525
  const topLevelTypes = Object.entries(schema.data.types);
522
526
  for (const [typeName, typeDef] of topLevelTypes) {
527
+ const mostRelevantAuthRules = typeDef.data?.authorization?.length > 0
528
+ ? typeDef.data.authorization
529
+ : schema.data.authorization;
523
530
  if (!isInternalModel(typeDef)) {
524
531
  if (isEnumType(typeDef)) {
532
+ if (typeDef.values.some((value) => /\s/.test(value))) {
533
+ throw new Error(`Values of the enum type ${typeName} should not contain any whitespace.`);
534
+ }
525
535
  const enumType = `enum ${typeName} {\n ${typeDef.values.join('\n ')}\n}`;
526
536
  gqlModels.push(enumType);
527
537
  }
@@ -530,7 +540,7 @@ const schemaPreprocessor = (schema) => {
530
540
  const authString = '';
531
541
  const authFields = {};
532
542
  const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields);
533
- const { gqlFields, models } = processFields(fields, fieldLevelAuthRules);
543
+ const { gqlFields, models } = processFields(typeName, fields, fieldLevelAuthRules);
534
544
  topLevelTypes.push(...models);
535
545
  const joined = gqlFields.join('\n ');
536
546
  const model = `type ${typeName} ${authString}\n{\n ${joined}\n}`;
@@ -538,7 +548,15 @@ const schemaPreprocessor = (schema) => {
538
548
  }
539
549
  else if (isCustomOperation(typeDef)) {
540
550
  const { typeName: opType } = typeDef.data;
541
- const { gqlField, models } = customOperationToGql(typeName, typeDef);
551
+ if ((mostRelevantAuthRules.length > 0 && !typeDef.data.functionRef) ||
552
+ (typeDef.data.functionRef && mostRelevantAuthRules.length < 1)) {
553
+ // Deploying a custom operation with auth and no handler reference OR
554
+ // with a handler reference but not auth
555
+ // causes the CFN stack to reach an unrecoverable state. Ideally, this should be fixed
556
+ // in the CDK construct, but we're catching it early here as a stopgap
557
+ throw new Error(`Custom operation ${typeName} requires both an authorization rule and a handler reference`);
558
+ }
559
+ const { gqlField, models } = customOperationToGql(typeName, typeDef, mostRelevantAuthRules);
542
560
  topLevelTypes.push(...models);
543
561
  switch (opType) {
544
562
  case 'Query':
@@ -560,15 +578,12 @@ const schemaPreprocessor = (schema) => {
560
578
  const identifier = typeDef.data.identifier;
561
579
  const [partitionKey] = identifier;
562
580
  const transformedSecondaryIndexes = transformedSecondaryIndexesForModel(typeDef.data.secondaryIndexes);
563
- const mostRelevantAuthRules = typeDef.data.authorization.length > 0
564
- ? typeDef.data.authorization
565
- : schema.data.authorization;
566
581
  const { authString, authFields } = calculateAuth(mostRelevantAuthRules);
567
582
  if (authString == '') {
568
583
  throw new Error(`Model \`${typeName}\` is missing authorization rules. Add global rules to the schema or ensure every model has its own rules.`);
569
584
  }
570
585
  const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields);
571
- const { gqlFields, models } = processFields({
586
+ const { gqlFields, models } = processFields(typeName, {
572
587
  // ID fields are not merged outside `mergeFieldObjects` to skip
573
588
  // validation, because the `identifer()` method doesn't specify or
574
589
  // care what the underlying field type is. We should always just defer
@@ -8,4 +8,5 @@ import { allow } from './Authorization';
8
8
  import { customType } from './CustomType';
9
9
  import { enumType } from './EnumType';
10
10
  import { query, mutation, subscription } from './CustomOperation';
11
- export { schema, model, modelIndex as index, ref, customType, enumType as enum, query, mutation, subscription, hasOne, hasMany, belongsTo, manyToMany, allow, id, string, integer, float, boolean, date, time, datetime, timestamp, email, json, phone, url, ipAddress, };
11
+ import { handler } from './Handler';
12
+ export { schema, model, modelIndex as index, ref, customType, enumType as enum, query, mutation, subscription, hasOne, hasMany, belongsTo, manyToMany, allow, id, string, integer, float, boolean, date, time, datetime, timestamp, email, json, phone, url, ipAddress, handler, };