@aws-amplify/data-schema
Advanced tools
Comparing version 0.13.3 to 0.13.4
@@ -18,3 +18,3 @@ import type { UnionToIntersection } from '@aws-amplify/data-schema-types'; | ||
[Model in keyof ResolvedModels]: { | ||
[Field in keyof ResolvedModels[Model] as ResolvedModels[Model][Field] extends EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape> ? `${Capitalize<Field & string>}` : never]: ResolvedModels[Model][Field]; | ||
[Field in keyof ResolvedModels[Model] as ResolvedModels[Model][Field] extends EnumType<EnumTypeParamShape> | CustomType<CustomTypeParamShape> ? `${Capitalize<Model & string>}${Capitalize<Field & string>}` : never]: ResolvedModels[Model][Field]; | ||
}; | ||
@@ -21,0 +21,0 @@ }[keyof ResolvedModels]>; |
@@ -29,3 +29,3 @@ import type { ModelType } from '../ModelType'; | ||
[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<{ | ||
link: Capitalize<FieldProp & string>; | ||
link: `${Capitalize<ModelProp & string>}${Capitalize<FieldProp & string>}`; | ||
type: 'ref'; | ||
@@ -32,0 +32,0 @@ required: false; |
@@ -6,3 +6,2 @@ import type { DerivedApiDefinition, SetTypeSubArg } from '@aws-amplify/data-schema-types'; | ||
import type { CustomOperation, CustomOperationParamShape, InternalCustom } from './CustomOperation'; | ||
export { __auth } from './ModelField'; | ||
import { Authorization } from './Authorization'; | ||
@@ -12,6 +11,36 @@ type SchemaContent = ModelType<ModelTypeParamShape, any> | CustomType<CustomTypeParamShape> | EnumType<EnumTypeParamShape> | CustomOperation<CustomOperationParamShape, any>; | ||
type InternalSchemaModels = Record<string, InternalModel | EnumType<any> | CustomType<any> | InternalCustom>; | ||
/** | ||
* Importing the full objects from @aws-amplify/plugin-types | ||
* more than doubles dev env runtime. This type replacement | ||
* will contain the content for config without the negative | ||
* side-effects. We may need to re-approach if customers interact | ||
* with these programmatically to avoid forcing narrowing. | ||
*/ | ||
type BackendSecret = { | ||
resolve: (scope: any, backendIdentifier: any) => any; | ||
resolvePath: (backendIdentifier: any) => any; | ||
}; | ||
export type DatasourceEngine = 'mysql' | 'postgresql' | 'dynamodb'; | ||
type DatasourceConfig<DE extends DatasourceEngine> = DE extends 'dynamodb' ? { | ||
engine: DE; | ||
} : { | ||
engine: DE; | ||
hostname: BackendSecret; | ||
username: BackendSecret; | ||
password: BackendSecret; | ||
port: BackendSecret; | ||
databaseName: BackendSecret; | ||
vpcConfig?: Record<string, never>; | ||
}; | ||
export type SchemaConfig<DE extends DatasourceEngine, DC extends DatasourceConfig<DE>> = { | ||
database: DC; | ||
}; | ||
export type ModelSchemaParamShape = { | ||
types: ModelSchemaContents; | ||
authorization: Authorization<any, any, any>[]; | ||
configuration: SchemaConfig<any, any>; | ||
}; | ||
export type SQLModelSchemaParamShape = ModelSchemaParamShape & { | ||
setSqlStatementFolderPath?: string; | ||
}; | ||
export type InternalSchema = { | ||
@@ -32,2 +61,5 @@ data: { | ||
}; | ||
export type SqlModelSchema<T extends SQLModelSchemaParamShape, UsedMethods extends 'authorization' | 'setSqlStatementFolderPath' = never> = ModelSchema<T, Exclude<UsedMethods, 'setSqlStatementFolderPath'>> & Omit<{ | ||
setSqlStatementFolderPath: (path: string) => SqlModelSchema<T, UsedMethods | 'setSqlStatementFolderPath'>; | ||
}, UsedMethods>; | ||
/** | ||
@@ -43,2 +75,11 @@ * Amplify API Next Model Schema shape | ||
export declare const isModelSchema: (schema: string | ModelSchemaType) => schema is ModelSchemaType; | ||
type SchemaReturnType<DE extends DatasourceEngine, Types extends ModelSchemaContents> = DE extends 'dynamodb' ? ModelSchema<{ | ||
types: Types; | ||
authorization: []; | ||
configuration: any; | ||
}> : SqlModelSchema<{ | ||
types: Types; | ||
authorization: []; | ||
configuration: any; | ||
}>; | ||
/** | ||
@@ -51,5 +92,17 @@ * The API and data model definition for Amplify Data. Pass in `{ <NAME>: a.model(...) }` to create a database table | ||
*/ | ||
export declare function schema<Types extends ModelSchemaContents>(types: Types): ModelSchema<{ | ||
export declare const schema: <Types extends ModelSchemaContents>(types: Types) => ModelSchema<{ | ||
types: Types; | ||
authorization: []; | ||
}>; | ||
configuration: any; | ||
}, never>; | ||
/** | ||
* Configure wraps schema definition with non-default config to allow usecases other than | ||
* the default DynamoDB use-case. | ||
* | ||
* @param config The SchemaConfig augments the schema with content like the database type | ||
* @returns | ||
*/ | ||
export declare function configure<DE extends DatasourceEngine>(config: SchemaConfig<DE, DatasourceConfig<DE>>): { | ||
schema: <Types extends ModelSchemaContents>(types: Types) => SchemaReturnType<DE, Types>; | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.schema = exports.isModelSchema = exports.__auth = void 0; | ||
exports.configure = exports.schema = exports.isModelSchema = void 0; | ||
const ModelType_1 = require("./ModelType"); | ||
var ModelField_1 = require("./ModelField"); | ||
Object.defineProperty(exports, "__auth", { enumerable: true, get: function () { return ModelField_1.__auth; } }); | ||
const SchemaProcessor_1 = require("./SchemaProcessor"); | ||
@@ -34,20 +32,39 @@ /** | ||
exports.isModelSchema = isModelSchema; | ||
function _schema(types) { | ||
const data = { types, authorization: [] }; | ||
const models = filterSchemaModelTypes(data.types); | ||
const transform = () => { | ||
const internalSchema = { data }; | ||
return (0, SchemaProcessor_1.processSchema)({ schema: internalSchema }); | ||
function _sqlSchemaExtension(schema) { | ||
return { | ||
...schema, | ||
setSqlStatementFolderPath(path) { | ||
this.data.setSqlStatementFolderPath = path; | ||
const { setSqlStatementFolderPath: _, ...rest } = this; | ||
return rest; | ||
}, | ||
}; | ||
const authorization = (rules) => { | ||
data.authorization = rules; | ||
return { data, transform, models }; | ||
} | ||
function _baseSchema(types, config) { | ||
const data = { | ||
types, | ||
authorization: [], | ||
configuration: config, | ||
}; | ||
return { | ||
data, | ||
transform, | ||
authorization, | ||
models, | ||
transform() { | ||
const internalSchema = { data }; | ||
return (0, SchemaProcessor_1.processSchema)({ schema: internalSchema }); | ||
}, | ||
authorization(rules) { | ||
this.data.authorization = rules; | ||
const { authorization: _, ...rest } = this; | ||
return rest; | ||
}, | ||
models: filterSchemaModelTypes(data.types), | ||
}; | ||
} | ||
function bindConfigToSchema(config) { | ||
return (types) => { | ||
return (config.database.engine === 'dynamodb' | ||
? _baseSchema(types, config) | ||
: _sqlSchemaExtension(_baseSchema(types, config))); | ||
}; | ||
} | ||
/** | ||
@@ -60,5 +77,15 @@ * The API and data model definition for Amplify Data. Pass in `{ <NAME>: a.model(...) }` to create a database table | ||
*/ | ||
function schema(types) { | ||
return _schema(types); | ||
exports.schema = bindConfigToSchema({ database: { engine: 'dynamodb' } }); | ||
/** | ||
* Configure wraps schema definition with non-default config to allow usecases other than | ||
* the default DynamoDB use-case. | ||
* | ||
* @param config The SchemaConfig augments the schema with content like the database type | ||
* @returns | ||
*/ | ||
function configure(config) { | ||
return { | ||
schema: bindConfigToSchema(config), | ||
}; | ||
} | ||
exports.schema = schema; | ||
exports.configure = configure; |
@@ -126,4 +126,4 @@ "use strict"; | ||
} | ||
function customOperationToGql(typeName, typeDef) { | ||
const { arguments: fieldArgs, returnType, authorization, functionRef, } = typeDef.data; | ||
function customOperationToGql(typeName, typeDef, authorization) { | ||
const { arguments: fieldArgs, returnType, functionRef } = typeDef.data; | ||
let callSignature = typeName; | ||
@@ -147,3 +147,3 @@ const implicitModels = []; | ||
if (Object.keys(fieldArgs).length > 0) { | ||
const { gqlFields, models } = processFields(fieldArgs, {}); | ||
const { gqlFields, models } = processFields(typeName, fieldArgs, {}); | ||
callSignature += `(${gqlFields.join(', ')})`; | ||
@@ -439,3 +439,3 @@ implicitModels.push(...models); | ||
} | ||
function processFields(fields, fieldLevelAuthRules, identifier, partitionKey, secondaryIndexes = {}) { | ||
function processFields(typeName, fields, fieldLevelAuthRules, identifier, partitionKey, secondaryIndexes = {}) { | ||
const gqlFields = []; | ||
@@ -458,3 +458,5 @@ const models = []; | ||
else if (isEnumType(fieldDef)) { | ||
const enumName = capitalize(fieldName); | ||
// The inline enum type name should be `<TypeName><FieldName>` to avoid | ||
// enum type name conflicts | ||
const enumName = `${capitalize(typeName)}${capitalize(fieldName)}`; | ||
models.push([enumName, fieldDef]); | ||
@@ -464,3 +466,5 @@ gqlFields.push(`${fieldName}: ${enumName}`); | ||
else if (isCustomType(fieldDef)) { | ||
const customTypeName = capitalize(fieldName); | ||
// The inline CustomType name should be `<TypeName><FieldName>` to avoid | ||
// CustomType name conflicts | ||
const customTypeName = `${capitalize(typeName)}${capitalize(fieldName)}`; | ||
models.push([customTypeName, fieldDef]); | ||
@@ -528,4 +532,10 @@ gqlFields.push(`${fieldName}: ${customTypeName}`); | ||
for (const [typeName, typeDef] of topLevelTypes) { | ||
const mostRelevantAuthRules = typeDef.data?.authorization?.length > 0 | ||
? typeDef.data.authorization | ||
: schema.data.authorization; | ||
if (!isInternalModel(typeDef)) { | ||
if (isEnumType(typeDef)) { | ||
if (typeDef.values.some((value) => /\s/.test(value))) { | ||
throw new Error(`Values of the enum type ${typeName} should not contain any whitespace.`); | ||
} | ||
const enumType = `enum ${typeName} {\n ${typeDef.values.join('\n ')}\n}`; | ||
@@ -539,3 +549,3 @@ gqlModels.push(enumType); | ||
const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields); | ||
const { gqlFields, models } = processFields(fields, fieldLevelAuthRules); | ||
const { gqlFields, models } = processFields(typeName, fields, fieldLevelAuthRules); | ||
topLevelTypes.push(...models); | ||
@@ -548,3 +558,11 @@ const joined = gqlFields.join('\n '); | ||
const { typeName: opType } = typeDef.data; | ||
const { gqlField, models } = customOperationToGql(typeName, typeDef); | ||
if ((mostRelevantAuthRules.length > 0 && !typeDef.data.functionRef) || | ||
(typeDef.data.functionRef && mostRelevantAuthRules.length < 1)) { | ||
// Deploying a custom operation with auth and no handler reference OR | ||
// with a handler reference but not auth | ||
// causes the CFN stack to reach an unrecoverable state. Ideally, this should be fixed | ||
// in the CDK construct, but we're catching it early here as a stopgap | ||
throw new Error(`Custom operation ${typeName} requires both an authorization rule and a handler reference`); | ||
} | ||
const { gqlField, models } = customOperationToGql(typeName, typeDef, mostRelevantAuthRules); | ||
topLevelTypes.push(...models); | ||
@@ -571,5 +589,2 @@ switch (opType) { | ||
const transformedSecondaryIndexes = transformedSecondaryIndexesForModel(typeDef.data.secondaryIndexes); | ||
const mostRelevantAuthRules = typeDef.data.authorization.length > 0 | ||
? typeDef.data.authorization | ||
: schema.data.authorization; | ||
const { authString, authFields } = calculateAuth(mostRelevantAuthRules); | ||
@@ -580,3 +595,3 @@ if (authString == '') { | ||
const fieldLevelAuthRules = processFieldLevelAuthRules(fields, authFields); | ||
const { gqlFields, models } = processFields({ | ||
const { gqlFields, models } = processFields(typeName, { | ||
// ID fields are not merged outside `mergeFieldObjects` to skip | ||
@@ -583,0 +598,0 @@ // validation, because the `identifer()` method doesn't specify or |
{ | ||
"name": "@aws-amplify/data-schema", | ||
"version": "0.13.3", | ||
"version": "0.13.4", | ||
"license": "Apache-2.0", | ||
@@ -17,2 +17,19 @@ "repository": { | ||
}, | ||
"exports": { | ||
".": { | ||
"types": "./lib-esm/index.d.ts", | ||
"import": "./lib-esm/index.js" | ||
}, | ||
"./internals": { | ||
"types": "./lib-esm/src/internals/index.d.ts", | ||
"import": "./lib-esm/src/internals/index.js" | ||
} | ||
}, | ||
"typesVersions": { | ||
">=5.0": { | ||
"internals": [ | ||
"./lib-esm/src/internals/index.d.ts" | ||
] | ||
} | ||
}, | ||
"dependencies": { | ||
@@ -34,2 +51,3 @@ "@aws-amplify/data-schema-types": "*" | ||
"lib-esm/**", | ||
"internals", | ||
"package.json", | ||
@@ -36,0 +54,0 @@ "README.md", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
221238
51
3003