@aws-amplify/data-schema 1.10.2 → 1.11.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/SchemaProcessor.js +40 -5
- package/dist/cjs/SchemaProcessor.js.map +1 -1
- package/dist/esm/ModelType.d.ts +3 -3
- package/dist/esm/SchemaProcessor.mjs +40 -5
- package/dist/esm/SchemaProcessor.mjs.map +1 -1
- package/dist/meta/cjs.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/ModelType.ts +2 -7
- package/src/SchemaProcessor.ts +55 -1
package/dist/esm/ModelType.d.ts
CHANGED
|
@@ -51,8 +51,8 @@ export type ModelTypeParamShape = {
|
|
|
51
51
|
* indicator string, and resolve its corresponding type later in
|
|
52
52
|
* packages/data-schema/src/runtime/client/index.ts
|
|
53
53
|
*/
|
|
54
|
-
export type ExtractSecondaryIndexIRFields<T extends ModelTypeParamShape
|
|
55
|
-
[FieldProp in keyof T['fields'] as T['fields'][FieldProp] extends BaseModelField<infer R> ? NonNullable<R> extends string | number ?
|
|
54
|
+
export type ExtractSecondaryIndexIRFields<T extends ModelTypeParamShape> = {
|
|
55
|
+
[FieldProp in keyof T['fields'] as T['fields'][FieldProp] extends BaseModelField<infer R> ? NonNullable<R> extends string | number ? FieldProp : never : T['fields'][FieldProp] extends EnumType | RefType<RefTypeParamShape, any, any> ? FieldProp : never]: T['fields'][FieldProp] extends BaseModelField<infer R> ? R : T['fields'][FieldProp] extends EnumType<infer values> ? values[number] : T['fields'][FieldProp] extends RefType<infer R, any, any> ? `${deferredRefResolvingPrefix}${R['link']}` : never;
|
|
56
56
|
};
|
|
57
57
|
export type AddRelationshipFieldsToModelTypeFields<Model, RelationshipFields extends Record<string, ModelRelationshipField<ModelRelationshipFieldParamShape, string, any, any>>> = Model extends ModelType<infer ModelParam extends ModelTypeParamShape, infer HiddenKeys> ? ModelType<SetTypeSubArg<ModelParam, 'fields', ModelParam['fields'] & RelationshipFields>, HiddenKeys> : never;
|
|
58
58
|
export type BaseModelType<T extends ModelTypeParamShape = ModelTypeParamShape> = ModelType<T, UsableModelTypeKey>;
|
|
@@ -65,7 +65,7 @@ export type UsableModelTypeKey = methodKeyOf<ModelType>;
|
|
|
65
65
|
*/
|
|
66
66
|
export type ModelType<T extends ModelTypeParamShape = ModelTypeParamShape, UsedMethod extends UsableModelTypeKey = never> = Omit<{
|
|
67
67
|
[brandSymbol]: typeof brandName;
|
|
68
|
-
identifier<PrimaryIndexFields = ExtractSecondaryIndexIRFields<T
|
|
68
|
+
identifier<PrimaryIndexFields = ExtractSecondaryIndexIRFields<T>, PrimaryIndexPool extends string = keyof PrimaryIndexFields & string, const ID extends ReadonlyArray<PrimaryIndexPool> = readonly [], const PrimaryIndexIR extends PrimaryIndexIrShape = PrimaryIndexFieldsToIR<ID, PrimaryIndexFields>>(identifier: ID): ModelType<SetTypeSubArg<T, 'identifier', PrimaryIndexIR>, UsedMethod | 'identifier'>;
|
|
69
69
|
secondaryIndexes<const SecondaryIndexFields = ExtractSecondaryIndexIRFields<T>, const SecondaryIndexPKPool extends string = keyof SecondaryIndexFields & string, const Indexes extends readonly ModelIndexType<string, string, unknown, readonly [], any>[] = readonly [], const IndexesIR extends readonly any[] = SecondaryIndexToIR<Indexes, SecondaryIndexFields>>(callback: (index: <PK extends SecondaryIndexPKPool>(pk: PK) => ModelIndexType<SecondaryIndexPKPool, PK, ReadonlyArray<Exclude<SecondaryIndexPKPool, PK>>>) => Indexes): ModelType<SetTypeSubArg<T, 'secondaryIndexes', IndexesIR>, UsedMethod | 'secondaryIndexes'>;
|
|
70
70
|
disableOperations<const Ops extends ReadonlyArray<DisableOperationsOptions>>(ops: Ops): ModelType<SetTypeSubArg<T, 'disabledOperations', Ops>, UsedMethod | 'disableOperations'>;
|
|
71
71
|
authorization<AuthRuleType extends Authorization<any, any, any>>(callback: (allow: Omit<AllowModifier, 'resource'>) => AuthRuleType | AuthRuleType[]): ModelType<SetTypeSubArg<T, 'authorization', AuthRuleType[]>, UsedMethod | 'authorization'>;
|
|
@@ -64,6 +64,9 @@ function isScalarField(field) {
|
|
|
64
64
|
function isRefField(field) {
|
|
65
65
|
return isRefFieldDef(field?.data);
|
|
66
66
|
}
|
|
67
|
+
function canGenerateFieldType(fieldType) {
|
|
68
|
+
return fieldType === 'Int';
|
|
69
|
+
}
|
|
67
70
|
function scalarFieldToGql(fieldDef, identifier, secondaryIndexes = []) {
|
|
68
71
|
const { fieldType, required, array, arrayRequired, default: _default, } = fieldDef;
|
|
69
72
|
let field = fieldType;
|
|
@@ -81,6 +84,9 @@ function scalarFieldToGql(fieldDef, identifier, secondaryIndexes = []) {
|
|
|
81
84
|
for (const index of secondaryIndexes) {
|
|
82
85
|
field += ` ${index}`;
|
|
83
86
|
}
|
|
87
|
+
if (_default === __generated) {
|
|
88
|
+
field += ` @default`;
|
|
89
|
+
}
|
|
84
90
|
return field;
|
|
85
91
|
}
|
|
86
92
|
if (required === true) {
|
|
@@ -609,12 +615,40 @@ function processFieldLevelAuthRules(fields, authFields) {
|
|
|
609
615
|
}
|
|
610
616
|
return fieldLevelAuthRules;
|
|
611
617
|
}
|
|
612
|
-
function
|
|
618
|
+
function validateDBGeneration(fields, databaseEngine) {
|
|
619
|
+
for (const [fieldName, fieldDef] of Object.entries(fields)) {
|
|
620
|
+
const _default = fieldDef.data?.default;
|
|
621
|
+
const fieldType = fieldDef.data?.fieldType;
|
|
622
|
+
const isGenerated = _default === __generated;
|
|
623
|
+
if (isGenerated && databaseEngine !== 'postgresql') {
|
|
624
|
+
throw new Error(`Invalid field definition for ${fieldName}. DB-generated fields are only supported with PostgreSQL data sources.`);
|
|
625
|
+
}
|
|
626
|
+
if (isGenerated && !canGenerateFieldType(fieldType)) {
|
|
627
|
+
throw new Error(`Incompatible field type. Field type ${fieldType} in field ${fieldName} cannot be configured as a DB-generated field.`);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function validateNullableIdentifiers(fields, identifier) {
|
|
632
|
+
for (const [fieldName, fieldDef] of Object.entries(fields)) {
|
|
633
|
+
const fieldType = fieldDef.data?.fieldType;
|
|
634
|
+
const required = fieldDef.data?.required;
|
|
635
|
+
const _default = fieldDef.data?.default;
|
|
636
|
+
const isGenerated = _default === __generated;
|
|
637
|
+
if (identifier !== undefined && identifier.includes(fieldName)) {
|
|
638
|
+
if (!required && fieldType !== 'ID' && !isGenerated) {
|
|
639
|
+
throw new Error(`Invalid identifier definition. Field ${fieldName} cannot be used in the identifier. Identifiers must reference required or DB-generated fields)`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
function processFields(typeName, fields, impliedFields, fieldLevelAuthRules, identifier, partitionKey, secondaryIndexes = {}, databaseEngine = 'dynamodb') {
|
|
613
645
|
const gqlFields = [];
|
|
614
646
|
// stores nested, field-level type definitions (custom types and enums)
|
|
615
647
|
// the need to be hoisted to top-level schema types and processed accordingly
|
|
616
648
|
const implicitTypes = [];
|
|
617
649
|
validateImpliedFields(fields, impliedFields);
|
|
650
|
+
validateDBGeneration(fields, databaseEngine);
|
|
651
|
+
validateNullableIdentifiers(fields, identifier);
|
|
618
652
|
for (const [fieldName, fieldDef] of Object.entries(fields)) {
|
|
619
653
|
const fieldAuth = fieldLevelAuthRules[fieldName]
|
|
620
654
|
? ` ${fieldLevelAuthRules[fieldName]}`
|
|
@@ -829,7 +863,8 @@ const schemaPreprocessor = (schema) => {
|
|
|
829
863
|
const jsFunctions = [];
|
|
830
864
|
const lambdaFunctions = {};
|
|
831
865
|
const customSqlDataSourceStrategies = [];
|
|
832
|
-
const
|
|
866
|
+
const databaseEngine = schema.data.configuration.database.engine;
|
|
867
|
+
const databaseType = databaseEngine === 'dynamodb'
|
|
833
868
|
? 'dynamodb'
|
|
834
869
|
: 'sql';
|
|
835
870
|
const staticSchema = databaseType === 'sql';
|
|
@@ -872,7 +907,7 @@ const schemaPreprocessor = (schema) => {
|
|
|
872
907
|
}
|
|
873
908
|
const authFields = {};
|
|
874
909
|
const fieldLevelAuthRules = processFieldLevelAuthRules(fieldAuthApplicableFields, authFields);
|
|
875
|
-
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules);
|
|
910
|
+
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules, undefined, undefined, undefined, databaseEngine);
|
|
876
911
|
topLevelTypes.push(...implicitTypes);
|
|
877
912
|
const joined = gqlFields.join('\n ');
|
|
878
913
|
const model = `type ${typeName} ${customAuth}\n{\n ${joined}\n}`;
|
|
@@ -929,7 +964,7 @@ const schemaPreprocessor = (schema) => {
|
|
|
929
964
|
const { authString, authFields } = calculateAuth(mostRelevantAuthRules);
|
|
930
965
|
const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields);
|
|
931
966
|
validateStaticFields(fields, authFields);
|
|
932
|
-
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules, identifier, partitionKey);
|
|
967
|
+
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules, identifier, partitionKey, undefined, databaseEngine);
|
|
933
968
|
topLevelTypes.push(...implicitTypes);
|
|
934
969
|
const joined = gqlFields.join('\n ');
|
|
935
970
|
const refersToString = typeDef.data.originalName
|
|
@@ -963,7 +998,7 @@ const schemaPreprocessor = (schema) => {
|
|
|
963
998
|
};
|
|
964
999
|
validateRelationships(typeName, fields, getInternalModel);
|
|
965
1000
|
const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields);
|
|
966
|
-
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules, identifier, partitionKey, transformedSecondaryIndexes);
|
|
1001
|
+
const { gqlFields, implicitTypes } = processFields(typeName, fields, authFields, fieldLevelAuthRules, identifier, partitionKey, transformedSecondaryIndexes, databaseEngine);
|
|
967
1002
|
topLevelTypes.push(...implicitTypes);
|
|
968
1003
|
const joined = gqlFields.join('\n ');
|
|
969
1004
|
const modelAttrs = modelAttributesFromDisabledOps(typeDef.data.disabledOperations);
|