UNPKG

@aws-amplify/appsync-modelgen-plugin

Version:
798 lines 54.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppSyncModelDartVisitor = void 0; const appsync_visitor_1 = require("./appsync-visitor"); const dart_declaration_block_1 = require("../languages/dart-declaration-block"); const process_connections_1 = require("../utils/process-connections"); const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common"); const process_auth_1 = require("../utils/process-auth"); const warn_1 = require("../utils/warn"); const dart_config_1 = require("../configs/dart-config"); const generateLicense_1 = require("../utils/generateLicense"); const scalars_1 = require("../scalars"); const change_case_1 = require("change-case"); class AppSyncModelDartVisitor extends appsync_visitor_1.AppSyncModelVisitor { constructor(schema, rawConfig, additionalConfig, defaultScalars = scalars_1.DART_SCALAR_MAP) { super(schema, rawConfig, additionalConfig, defaultScalars); } generate() { const shouldUseModelNameFieldInHasManyAndBelongsTo = true; const shouldImputeKeyForUniDirectionalHasMany = false; this.processDirectives(shouldUseModelNameFieldInHasManyAndBelongsTo, shouldImputeKeyForUniDirectionalHasMany); this.validateReservedKeywords(); if (this._parsedConfig.generate === appsync_visitor_1.CodeGenGenerateEnum.loader) { return this.generateClassLoader(); } else if (this.selectedTypeIsEnum()) { return this.generateEnums(); } else if (this.selectedTypeIsNonModel()) { return this.generateNonModelClasses(); } return this.generateModelClasses(); } validateReservedKeywords() { Object.entries({ ...this.models, ...this.nonModels }).forEach(([name, obj]) => { if (dart_config_1.DART_RESERVED_KEYWORDS.includes(name)) { throw new Error(`Type name '${name}' is a reserved word in dart. Please use a non-reserved name instead.`); } obj.fields.forEach(field => { const fieldName = this.getFieldName(field); if (dart_config_1.DART_RESERVED_KEYWORDS.includes(fieldName)) { throw new Error(`Field name '${fieldName}' in type '${name}' is a reserved word in dart. Please use a non-reserved name instead.`); } }); }); Object.entries(this.enums).forEach(([name, enumVal]) => { if (dart_config_1.DART_RESERVED_KEYWORDS.includes(name)) { throw new Error(`Enum name '${name}' is a reserved word in dart. Please use a non-reserved name instead.`); } Object.values(enumVal.values).forEach(val => { if (dart_config_1.DART_RESERVED_KEYWORDS.includes(val)) { throw new Error(`Enum value '${val}' in enum '${name}' is a reserved word in dart. Please use a non-reserved name instead.`); } }); }); } generateClassLoader() { const result = []; const modelNames = Object.keys(this.modelMap).sort(); const nonModelNames = Object.keys(this.nonModelMap).sort(); const exportClasses = [...modelNames, ...Object.keys(this.enumMap), ...Object.keys(this.nonModelMap)].sort(); const license = (0, generateLicense_1.generateLicense)(); result.push(license); result.push(dart_config_1.CUSTOM_LINTS_MESSAGE); result.push(dart_config_1.IGNORE_FOR_FILE); const flutterDatastorePackage = dart_config_1.FLUTTER_AMPLIFY_CORE_IMPORT; const packageImports = [...modelNames, ...nonModelNames]; const packageExports = [...exportClasses]; const classDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock() .asKind('class') .withName(dart_config_1.LOADER_CLASS_NAME) .implements([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelProviderInterface}`]) .addClassMember('version', 'String', `"${this.computeVersion()}"`, undefined, ['override']) .addClassMember('modelSchemas', `List<${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelSchema}>`, `[${modelNames.map(m => `${m}.schema`).join(', ')}]`, undefined, ['override']) .addClassMember('customTypeSchemas', `List<${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelSchema}>`, `[${nonModelNames.map(nm => `${nm}.schema`).join(', ')}]`, undefined, ['override']) .addClassMember('_instance', dart_config_1.LOADER_CLASS_NAME, `${dart_config_1.LOADER_CLASS_NAME}()`, { static: true, final: true }) .addClassMethod('get instance', dart_config_1.LOADER_CLASS_NAME, [], ' => _instance;', { isBlock: false, isGetter: true, static: true }); if (modelNames.length) { const getModelTypeImplStr = [ 'switch(modelName) {', ...modelNames.map(modelName => [(0, visitor_plugin_common_1.indent)(`case "${modelName}":`), (0, visitor_plugin_common_1.indent)(`return ${modelName}.classType;`, 2)].join('\n')), (0, visitor_plugin_common_1.indent)('default:'), (0, visitor_plugin_common_1.indent)('throw Exception("Failed to find model in model provider for model name: " + modelName);', 2), '}', ].join('\n'); classDeclarationBlock.addClassMethod('getModelTypeByModelName', `${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelType}`, [{ type: 'String', name: 'modelName' }], getModelTypeImplStr); } const processedPackageImports = packageImports.map(p => `import '${p}.dart';`); processedPackageImports.unshift(`import '${flutterDatastorePackage}.dart' as ${dart_config_1.AMPLIFY_CORE_PREFIX};`); result.push(processedPackageImports.join('\n')); result.push(packageExports.map(p => `export '${p}.dart';`).join('\n')); result.push(classDeclarationBlock.string); result.push(dart_config_1.MODEL_FILED_VALUE_CLASS); return result.join('\n\n'); } generateEnums() { const result = []; const license = (0, generateLicense_1.generateLicense)(); result.push(license); result.push(dart_config_1.CUSTOM_LINTS_MESSAGE); result.push(dart_config_1.IGNORE_FOR_FILE); Object.entries(this.getSelectedEnums()).forEach(([name, enumVal]) => { const body = Object.values(enumVal.values).join(',\n'); result.push([`enum ${(0, change_case_1.pascalCase)(name)} {`, (0, visitor_plugin_common_1.indentMultiline)(body), '}'].join('\n')); }); return result.join('\n\n'); } generateModelClasses() { const result = []; const license = (0, generateLicense_1.generateLicense)(); result.push(license); result.push(dart_config_1.CUSTOM_LINTS_MESSAGE); result.push(dart_config_1.IGNORE_FOR_FILE); const packageImports = this.generatePackageHeader(); result.push(packageImports); Object.entries(this.getSelectedModels()).forEach(([name, model]) => { const modelDeclaration = this.generateModelClass(model); const modelType = this.generateModelType(model); result.push(modelDeclaration); result.push(modelType); if (this.isCustomPKEnabled()) { const modelIdentifier = this.generateModelIdentifierClass(model); result.push(modelIdentifier); } }); return result.join('\n\n'); } generateNonModelClasses() { const result = []; const license = (0, generateLicense_1.generateLicense)(); result.push(license); result.push(dart_config_1.CUSTOM_LINTS_MESSAGE); result.push(dart_config_1.IGNORE_FOR_FILE); const packageImports = this.generatePackageHeader(); result.push(packageImports); Object.entries(this.getSelectedNonModels()).forEach(([name, model]) => { const modelDeclaration = this.generateNonModelClass(model); result.push(modelDeclaration); }); return result.join('\n\n'); } generatePackageHeader() { let usingCollection = false; Object.entries({ ...this.getSelectedModels(), ...this.getSelectedNonModels() }).forEach(([name, model]) => { model.fields.forEach(f => { if (f.isList) { usingCollection = true; } }); }); const flutterDatastorePackage = dart_config_1.FLUTTER_AMPLIFY_CORE_IMPORT; const packagesImports = [usingCollection ? dart_config_1.COLLECTION_PACKAGE : '', `${dart_config_1.LOADER_CLASS_NAME}.dart`] .filter(f => f) .map(pckg => `import '${pckg}';`); packagesImports.push(`import '${flutterDatastorePackage}.dart' as ${dart_config_1.AMPLIFY_CORE_PREFIX};`); return packagesImports.sort().join('\n') + '\n'; } generateModelClass(model) { const classDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock() .asKind('class') .withName(this.getModelName(model)) .extends([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.Model}`]) .withComment(`This is an auto generated class representing the ${model.name} type in your schema.`); classDeclarationBlock.addClassMember('classType', '', `const _${this.getModelName(model)}ModelType()`, { static: true, const: true }); model.fields.forEach(field => { this.generateModelField(field, '', classDeclarationBlock); }); classDeclarationBlock.addClassMethod('getInstanceType', '', [], ' => classType;', { isBlock: false }, ['override']); this.generateGetters(model, classDeclarationBlock); this.generateConstructor(model, classDeclarationBlock); this.generateEqualsMethodAndOperator(model, classDeclarationBlock); this.generateHashCodeMethod(model, classDeclarationBlock); this.generateToStringMethod(model, classDeclarationBlock); this.generateCopyWithMethod(model, classDeclarationBlock); this.generateCopyWithModelFieldValuesMethod(model, classDeclarationBlock); this.generateSerializationMethod(model, classDeclarationBlock); this.generateModelSchema(model, classDeclarationBlock); return classDeclarationBlock.string; } generateNonModelClass(model) { const includeIdGetter = false; const classDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock() .asKind('class') .withName(this.getModelName(model)) .withComment(`This is an auto generated class representing the ${model.name} type in your schema.`); model.fields.forEach(field => { this.generateModelField(field, '', classDeclarationBlock); }); this.generateGetters(model, classDeclarationBlock, includeIdGetter); this.generateConstructor(model, classDeclarationBlock); this.generateEqualsMethodAndOperator(model, classDeclarationBlock); this.generateHashCodeMethod(model, classDeclarationBlock); this.generateToStringMethod(model, classDeclarationBlock); this.generateCopyWithMethod(model, classDeclarationBlock); this.generateCopyWithModelFieldValuesMethod(model, classDeclarationBlock); this.generateSerializationMethod(model, classDeclarationBlock); this.generateNonModelSchema(model, classDeclarationBlock); return classDeclarationBlock.string; } generateModelType(model) { const modelName = this.getModelName(model); const classDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock() .asKind('class') .withName(`_${modelName}ModelType`) .extends([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelType}<${modelName}>`]); classDeclarationBlock.addClassMethod(`_${modelName}ModelType`, '', [], ';', { const: true, isBlock: false }); classDeclarationBlock.addClassMethod('fromJson', modelName, [{ name: 'jsonData', type: 'Map<String, dynamic>' }], `return ${modelName}.fromJson(jsonData);`, undefined, ['override']); classDeclarationBlock.addClassMethod('modelName', 'String', [], `return '${modelName}';`, undefined, ['override']); return classDeclarationBlock.string; } generateModelIdentifierClass(model) { const identifierFields = this.getModelIdentifierFields(model); const modelName = this.getModelName(model); const classDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock() .asKind('class') .withName(`${modelName}ModelIdentifier`) .implements([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelIdentifier}<${modelName}>`]) .withComment(['This is an auto generated class representing the model identifier', `of [${modelName}] in your schema.`].join('\n')); identifierFields.forEach(field => { classDeclarationBlock.addClassMember(field.name, this.getNativeType(field), '', { final: true }); }); const constructorArgs = `{\n${(0, visitor_plugin_common_1.indentMultiline)(identifierFields.map(field => `required this.${field.name}`).join(',\n'))}}`; classDeclarationBlock.addClassMethod(`${modelName}ModelIdentifier`, '', [{ name: constructorArgs }], ';', { const: true, isBlock: false }, undefined, [ `Create an instance of ${modelName}ModelIdentifier using [${identifierFields[0].name}] the primary key.`, identifierFields.length > 1 ? `And ${identifierFields .slice(1) .map(field => `[${field.name}]`) .join(', ')} the sort key${identifierFields.length == 2 ? '' : 's'}.` : undefined, ] .filter(comment => comment) .join('\n')); classDeclarationBlock.addClassMethod('serializeAsMap', 'Map<String, dynamic>', [], [' => (<String, dynamic>{', (0, visitor_plugin_common_1.indentMultiline)(identifierFields.map(field => `'${field.name}': ${field.name}`).join(',\n')), '});'].join('\n'), { isBlock: false }, ['override']); classDeclarationBlock.addClassMethod('serializeAsList', 'List<Map<String, dynamic>>', [], [ ' => serializeAsMap()', (0, visitor_plugin_common_1.indent)('.entries'), (0, visitor_plugin_common_1.indent)('.map((entry) => (<String, dynamic>{ entry.key: entry.value }))'), (0, visitor_plugin_common_1.indent)('.toList();'), ].join('\n'), { isBlock: false }, ['override']); classDeclarationBlock.addClassMethod('serializeAsString', 'String', undefined, " => serializeAsMap().values.join('#');", { isBlock: false, }, ['override']); classDeclarationBlock.addClassMethod('toString', 'String', undefined, ` => '${modelName}ModelIdentifier(${identifierFields.map(field => `${field.name}: $${field.name}`).join(', ')})';`, { isBlock: false }, ['override']); const equalOperatorImpl = [ 'if (identical(this, other)) {', (0, visitor_plugin_common_1.indent)('return true;'), '}\n', `return other is ${modelName}ModelIdentifier &&`, (0, visitor_plugin_common_1.indentMultiline)(`${identifierFields.map(field => `${field.name} == other.${field.name}`).join(' &&\n')};`), ].join('\n'); classDeclarationBlock.addClassMethod('operator ==', 'bool', [{ name: 'Object other' }], equalOperatorImpl, undefined, ['override']); classDeclarationBlock.addClassMethod('get hashCode', 'int', undefined, ` =>\n${(0, visitor_plugin_common_1.indentMultiline)(identifierFields.map(field => `${field.name}.hashCode`).join(' ^\n'))};`, { isBlock: false, isGetter: true }, ['override']); return classDeclarationBlock.string; } generateModelField(field, value, classDeclarationBlock) { const fieldType = this.getNativeType(field); const fieldName = this.getFieldName(field); if (fieldName !== 'id') { classDeclarationBlock.addClassMember(`_${fieldName}`, `${fieldType}?`, value, { final: true }); } else { classDeclarationBlock.addClassMember(fieldName, fieldType, value, { final: true }); } } generateGetters(model, declarationBlock, includeIdGetter = true) { if (includeIdGetter) { if (this.isCustomPKEnabled()) { const identifierFields = this.getModelIdentifierFields(model); const isCustomPK = identifierFields[0].name !== 'id'; const getIdImpl = isCustomPK ? ' => modelIdentifier.serializeAsString();' : ' => id;'; declarationBlock.addClassMethod('getId', 'String', [], getIdImpl, { isBlock: false }, [ "Deprecated('[getId] is being deprecated in favor of custom primary key feature. Use getter [modelIdentifier] to get model identifier.')", 'override', ]); } else { declarationBlock.addClassMethod('getId', 'String', [], 'return id;', {}, ['override']); } } let forceCastException = `throw ${dart_config_1.DART_AMPLIFY_CORE_TYPES.AmplifyCodeGenModelException}( ${dart_config_1.DART_AMPLIFY_CORE_TYPES.AmplifyExceptionMessages}.codeGenRequiredFieldForceCastExceptionMessage, recoverySuggestion: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.AmplifyExceptionMessages}.codeGenRequiredFieldForceCastRecoverySuggestion, underlyingException: e.toString() );`; if (includeIdGetter && this.isCustomPKEnabled()) { this.generateModelIdentifierGetter(model, declarationBlock, forceCastException); } model.fields.forEach(field => { const fieldName = this.getFieldName(field); const fieldType = this.getNativeType(field); const returnType = this.isFieldRequired(field) ? fieldType : `${fieldType}?`; const getterImpl = this.isFieldRequired(field) ? [`try {`, (0, visitor_plugin_common_1.indent)(`return _${fieldName}!;`), '} catch(e) {', (0, visitor_plugin_common_1.indent)(forceCastException), '}'].join('\n') : `return _${fieldName};`; if (fieldName !== 'id') { declarationBlock.addClassMethod(`get ${fieldName}`, returnType, undefined, getterImpl, { isGetter: true, isBlock: true }); } }); } generateModelIdentifierGetter(model, declarationBlock, forceCastException) { const identifierFields = this.getModelIdentifierFields(model); const modelName = this.getModelName(model); const isSingleManagedIDField = identifierFields.length === 1 && identifierFields[0].name === 'id'; const getterImpl = [ isSingleManagedIDField ? undefined : 'try {', (0, visitor_plugin_common_1.indent)(`return ${modelName}ModelIdentifier(`), (0, visitor_plugin_common_1.indentMultiline)(identifierFields .map(field => { const isManagedIdField = field.name === 'id'; return (0, visitor_plugin_common_1.indent)(`${field.name}: ${isManagedIdField ? '' : '_'}${field.name}${isManagedIdField ? '' : '!'}`); }) .join(',\n')), (0, visitor_plugin_common_1.indent)(');'), isSingleManagedIDField ? undefined : '} catch(e) {', isSingleManagedIDField ? undefined : (0, visitor_plugin_common_1.indent)(forceCastException), isSingleManagedIDField ? undefined : '}', ] .filter(line => line) .join('\n'); declarationBlock.addClassMethod(`get modelIdentifier`, `${modelName}ModelIdentifier`, undefined, getterImpl, { isGetter: true, isBlock: true, }); } generateConstructor(model, declarationBlock) { const args = `{${model.fields .map(f => `${this.isFieldRequired(f) ? 'required ' : ''}${this.getFieldName(f) === 'id' ? 'this.' : ''}${this.getFieldName(f)}`) .join(', ')}}`; const internalFields = model.fields.filter(f => this.getFieldName(f) !== 'id'); const internalImpl = internalFields.length ? `: ${internalFields.map(f => `_${this.getFieldName(f)} = ${this.getFieldName(f)}`).join(', ')};` : ';'; declarationBlock.addClassMethod(`${this.getModelName(model)}._internal`, '', [{ name: args }], internalImpl, { const: true, isBlock: false, }); const writableFields = this.getWritableFields(model); const returnParamStr = writableFields .map(field => { const fieldName = this.getFieldName(field); if (fieldName === 'id') { return `id: id == null ? ${dart_config_1.DART_AMPLIFY_CORE_TYPES.UUID}.getUUID() : id`; } else if (field.isList) { return `${fieldName}: ${fieldName} != null ? ${this.getNativeType(field)}.unmodifiable(${fieldName}) : ${fieldName}`; } else { return `${fieldName}: ${fieldName}`; } }) .join(',\n'); const factoryImpl = [`return ${this.getModelName(model)}._internal(`, (0, visitor_plugin_common_1.indentMultiline)(`${returnParamStr});`)].join('\n'); const factoryParam = `{${writableFields .map(f => { if (this.getFieldName(f) === 'id' || !this.isFieldRequired(f)) { return `${this.getNativeType(f)}? ${this.getFieldName(f)}`; } return `required ${this.getNativeType(f)} ${this.getFieldName(f)}`; }) .join(', ')}}`; declarationBlock.addClassMethod(this.getModelName(model), 'factory', [{ name: factoryParam }], factoryImpl); } generateEqualsMethodAndOperator(model, declarationBlock) { declarationBlock.addClassMethod('equals', 'bool', [{ name: 'other', type: 'Object' }], 'return this == other;'); const equalImpl = [ 'if (identical(other, this)) return true;', `return other is ${this.getModelName(model)} &&`, (0, visitor_plugin_common_1.indentMultiline)(`${this.getWritableFields(model) .map(f => { const fieldName = `${f.name !== 'id' ? '_' : ''}${this.getFieldName(f)}`; return f.isList ? `DeepCollectionEquality().equals(${fieldName}, other.${fieldName})` : `${fieldName} == other.${fieldName}`; }) .join(' &&\n')};`), ].join('\n'); declarationBlock.addClassMethod('operator ==', 'bool', [{ name: 'other', type: 'Object' }], equalImpl, undefined, ['override']); } generateHashCodeMethod(model, declarationBlock) { declarationBlock.addClassMethod(`get hashCode`, `int`, undefined, ' => toString().hashCode;', { isGetter: true, isBlock: false }, [ 'override', ]); } generateToStringMethod(model, declarationBlock) { const fields = this.getNonConnectedField(model); declarationBlock.addClassMethod('toString', 'String', [], [ 'var buffer = new StringBuffer();', '', `buffer.write("${this.getModelName(model)} {");`, ...fields.map((field, index) => { const fieldDelimiter = ', '; const varName = this.getFieldName(field); const fieldName = `${field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`; let toStringVal = ''; if (this.isEnumType(field)) { if (field.isList) { toStringVal = `(${fieldName} != null ? ${fieldName}!.map((e) => ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumToString}(e)).toString() : "null")`; } else { toStringVal = `(${fieldName} != null ? ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumToString}(${fieldName})! : "null")`; } } else { const fieldNativeType = this.getNativeType(field); switch (fieldNativeType) { case 'String': toStringVal = `"$${fieldName}"`; break; case this.scalars['AWSDate']: case this.scalars['AWSTime']: case this.scalars['AWSDateTime']: toStringVal = `(${fieldName} != null ? ${fieldName}!.format() : "null")`; break; default: toStringVal = `(${fieldName} != null ? ${fieldName}!.toString() : "null")`; } } if (index !== fields.length - 1) { return `buffer.write("${varName}=" + ${toStringVal} + "${fieldDelimiter}");`; } return `buffer.write("${varName}=" + ${toStringVal});`; }), `buffer.write("}");`, '', 'return buffer.toString();', ].join('\n'), undefined, ['override']); } generateCopyWithMethod(model, declarationBlock) { const writableFields = this.getWritableFields(model, this.isCustomPKEnabled()); const copyParam = `{${writableFields.map(f => `${this.getNativeType(f)}? ${this.getFieldName(f)}`).join(', ')}}`; declarationBlock.addClassMethod('copyWith', this.getModelName(model), writableFields.length ? [{ name: copyParam }] : undefined, [ `return ${this.getModelName(model)}${this.config.isTimestampFieldsAdded ? '._internal' : ''}(`, (0, visitor_plugin_common_1.indentMultiline)(`${this.getWritableFields(model) .map(field => { const fieldName = this.getFieldName(field); return `${fieldName}: ${writableFields.findIndex(field => field.name === fieldName) > -1 ? `${fieldName} ?? this.` : ''}${fieldName}`; }) .join(',\n')});`), ].join('\n')); } generateCopyWithModelFieldValuesMethod(model, declarationBlock) { const writableFields = this.getWritableFields(model, this.isCustomPKEnabled()); const copyParameters = writableFields.map(field => `ModelFieldValue<${this.getNativeType(field)}${field.isNullable ? '?' : ''}>? ${this.getFieldName(field)}`); const copyParameterStr = `{\n${(0, visitor_plugin_common_1.indentMultiline)(copyParameters.join(',\n'))}\n}`; declarationBlock.addClassMethod('copyWithModelFieldValues', this.getModelName(model), writableFields.length ? [{ name: copyParameterStr }] : undefined, [ `return ${this.getModelName(model)}${this.config.isTimestampFieldsAdded ? '._internal' : ''}(`, (0, visitor_plugin_common_1.indentMultiline)(`${this.getWritableFields(model, false) .map(field => { const fieldName = this.getFieldName(field); return `${fieldName}: ${writableFields.findIndex(field => field.name === fieldName) > -1 ? `${fieldName} == null ? this.${fieldName} : ${fieldName}.value` : `${fieldName}`}`; }) .join(',\n')}`), ');', ].join('\n')); } generateSerializationMethod(model, declarationBlock) { const serializationImpl = `\n: ${(0, visitor_plugin_common_1.indentMultiline)(model.fields .map(field => { const varName = this.getFieldName(field); const fieldName = `${field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`; if (this.isModelType(field)) { if (field.isList) { return [ `${fieldName} = json['${varName}'] is Map`, (0, visitor_plugin_common_1.indent)(`? (json['${varName}']['items'] is List`), (0, visitor_plugin_common_1.indent)(`? (json['${varName}']['items'] as List)`, 2), (0, visitor_plugin_common_1.indent)(`.where((e) => e != null)`, 4), (0, visitor_plugin_common_1.indent)(`.map((e) => ${this.getNativeType({ ...field, isList: false })}.fromJson(new Map<String, dynamic>.from(e)))`, 4), (0, visitor_plugin_common_1.indent)(`.toList()`, 4), (0, visitor_plugin_common_1.indent)(`: null)`, 2), (0, visitor_plugin_common_1.indent)(`: (json['${varName}'] is List`), (0, visitor_plugin_common_1.indent)(`? (json['${varName}'] as List)`, 2), (0, visitor_plugin_common_1.indent)(`.where((e) => e?['serializedData'] != null)`, 4), (0, visitor_plugin_common_1.indent)(`.map((e) => ${this.getNativeType({ ...field, isList: false })}.fromJson(new Map<String, dynamic>.from(e?['serializedData'])))`, 4), (0, visitor_plugin_common_1.indent)(`.toList()`, 4), (0, visitor_plugin_common_1.indent)(`: null)`, 2), ] .filter(e => e !== undefined) .join('\n'); } return [ `${fieldName} = json['${varName}'] != null`, (0, visitor_plugin_common_1.indent)(`? json['${varName}']['serializedData'] != null`), (0, visitor_plugin_common_1.indent)(`? ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']['serializedData']))`, 2), (0, visitor_plugin_common_1.indent)(`: ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']))`, 2), (0, visitor_plugin_common_1.indent)(`: null`), ].join('\n'); } if (this.isEnumType(field)) { if (field.isList) { return [ `${fieldName} = json['${varName}'] is List`, (0, visitor_plugin_common_1.indent)(`? (json['${varName}'] as List)`), (0, visitor_plugin_common_1.indent)(`.map((e) => ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumFromString}<${field.type}>(e, ${field.type}.values)!)`, 2), (0, visitor_plugin_common_1.indent)(`.toList()`, 2), (0, visitor_plugin_common_1.indent)(`: null`), ].join('\n'); } return `${fieldName} = ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumFromString}<${field.type}>(json['${varName}'], ${field.type}.values)`; } if (this.isNonModelType(field)) { if (field.isList) { return [ `${fieldName} = json['${varName}'] is List`, (0, visitor_plugin_common_1.indent)(`? (json['${varName}'] as List)`), (0, visitor_plugin_common_1.indent)(`.where((e) => e != null)`, 2), (0, visitor_plugin_common_1.indent)(`.map((e) => ${this.getNativeType({ ...field, isList: false })}.fromJson(new Map<String, dynamic>.from(${this.isNonModelType(field) ? "e['serializedData'] ?? e" : 'e'})))`, 2), (0, visitor_plugin_common_1.indent)(`.toList()`, 2), (0, visitor_plugin_common_1.indent)(`: null`), ] .filter(e => e !== undefined) .join('\n'); } return [ `${fieldName} = json['${varName}'] != null`, (0, visitor_plugin_common_1.indent)(`? json['${varName}']['serializedData'] != null`, 2), (0, visitor_plugin_common_1.indent)(`? ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']['serializedData']))`, 4), (0, visitor_plugin_common_1.indent)(`: ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']))`, 4), (0, visitor_plugin_common_1.indent)(`: null`), ].join('\n'); } const fieldNativeType = this.getNativeType({ ...field, isList: false }); switch (fieldNativeType) { case this.scalars['AWSDate']: case this.scalars['AWSTime']: case this.scalars['AWSDateTime']: return field.isList ? `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('List')})?.map((e) => ${fieldNativeType}.fromString(e)).toList()` : `${fieldName} = json['${varName}'] != null ? ${fieldNativeType}.fromString(json['${varName}']) : null`; case this.scalars['AWSTimestamp']: return field.isList ? `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('List')})?.map((e) => ${fieldNativeType}.fromSeconds(e)).toList()` : `${fieldName} = json['${varName}'] != null ? ${fieldNativeType}.fromSeconds(json['${varName}']) : null`; case this.scalars['Int']: return field.isList ? `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('List')})?.map((e) => (e as num).toInt()).toList()` : `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('num')})?.toInt()`; case this.scalars['Float']: return field.isList ? `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('List')})?.map((e) => (e as num).toDouble()).toList()` : `${fieldName} = (json['${varName}'] as ${this.getNullableTypeStr('num')})?.toDouble()`; default: return field.isList ? `${fieldName} = json['${varName}']?.cast<${this.getNativeType({ ...field, isList: false })}>()` : `${fieldName} = json['${varName}']`; } }) .join(',\n')).trim()};`; declarationBlock.addClassMethod(`${this.getModelName(model)}.fromJson`, ``, [{ name: 'json', type: 'Map<String, dynamic>' }], (0, visitor_plugin_common_1.indentMultiline)(serializationImpl), { isBlock: false }); const toJsonFields = model.fields .map(field => { const varName = this.getFieldName(field); const fieldName = `${field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`; if (this.isModelType(field) || this.isNonModelType(field)) { if (field.isList) { const modelName = this.getNativeType({ ...field, isList: false }); return `'${varName}': ${fieldName}?.map((${modelName}? e) => e?.toJson()).toList()`; } return `'${varName}': ${fieldName}?.toJson()`; } if (this.isEnumType(field)) { if (field.isList) { return `'${varName}': ${fieldName}?.map((e) => ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumToString}(e)).toList()`; } return `'${varName}': ${dart_config_1.DART_AMPLIFY_CORE_TYPES.enumToString}(${fieldName})`; } const fieldNativeType = this.getNativeType({ ...field, isList: false }); switch (fieldNativeType) { case this.scalars['AWSDate']: case this.scalars['AWSTime']: case this.scalars['AWSDateTime']: return field.isList ? `'${varName}': ${fieldName}?.map((e) => e.format()).toList()` : `'${varName}': ${fieldName}?.format()`; case this.scalars['AWSTimestamp']: return field.isList ? `'${varName}': ${fieldName}?.map((e) => e.toSeconds()).toList()` : `'${varName}': ${fieldName}?.toSeconds()`; default: return `'${varName}': ${fieldName}`; } }) .join(', '); const deserializationImpl = [' => {', (0, visitor_plugin_common_1.indentMultiline)(toJsonFields), '};'].join('\n'); declarationBlock.addClassMethod('toJson', 'Map<String, dynamic>', [], deserializationImpl, { isBlock: false }); const toMapFields = model.fields .map(field => { const varName = this.getFieldName(field); const fieldName = `${field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`; return `'${varName}': ${fieldName}`; }) .join(',\n'); const toMapImpl = [' => {', (0, visitor_plugin_common_1.indentMultiline)(toMapFields), '};'].join('\n'); declarationBlock.addClassMethod('toMap', 'Map<String, Object?>', [], toMapImpl, { isBlock: false }); } generateModelSchema(model, classDeclarationBlock) { const modelName = model.name; const schemaDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock(); if (this.isCustomPKEnabled()) { schemaDeclarationBlock.addClassMember('MODEL_IDENTIFIER', `${dart_config_1.DART_AMPLIFY_CORE_TYPES.QueryModelIdentifier}<${modelName}ModelIdentifier>`, `${dart_config_1.DART_AMPLIFY_CORE_TYPES.QueryModelIdentifier}<${modelName}ModelIdentifier>()`, { static: true, final: true }); } this.getWritableFields(model).forEach(field => { this.generateQueryField(model, field, schemaDeclarationBlock); }); this.generateSchemaField(model, schemaDeclarationBlock); classDeclarationBlock.addBlock(schemaDeclarationBlock); } generateNonModelSchema(model, classDeclarationBlock) { const isNonModel = true; const schemaDeclarationBlock = new dart_declaration_block_1.DartDeclarationBlock(); this.generateSchemaField(model, schemaDeclarationBlock, isNonModel); classDeclarationBlock.addBlock(schemaDeclarationBlock); } generateQueryField(model, field, declarationBlock) { const fieldName = this.getFieldName(field); const queryFieldName = this.getQueryFieldName(field); let value = `${dart_config_1.DART_AMPLIFY_CORE_TYPES.QueryField}(fieldName: "${fieldName}")`; if (this.isModelType(field)) { const modelName = this.getNativeType({ ...field, isList: false }); value = [ `${dart_config_1.DART_AMPLIFY_CORE_TYPES.QueryField}(`, (0, visitor_plugin_common_1.indent)(`fieldName: "${fieldName}",`), (0, visitor_plugin_common_1.indent)(`fieldType: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldType}(${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}.model, ofModelName: '${modelName}'))`), ].join('\n'); } declarationBlock.addClassMember(queryFieldName, `${dart_config_1.DART_AMPLIFY_CORE_TYPES.QueryField}`, value, { static: true, final: true, inferType: true, }); } getQueryFieldName(field) { return this.getFieldName(field).toUpperCase(); } generateSchemaField(model, declarationBlock, isNonModel = false) { const schema = [ `${dart_config_1.DART_AMPLIFY_CORE_TYPES.Model}.defineSchema(define: (${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelSchemaDefinition} modelSchemaDefinition) {`, (0, visitor_plugin_common_1.indentMultiline)([ `modelSchemaDefinition.name = "${this.getModelName(model)}";\nmodelSchemaDefinition.pluralName = "${this.pluralizeModelName(model)}";`, this.generateAuthRules(model), this.generateIndexes(model), isNonModel ? this.generateNonModelAddFields(model) : this.generateAddFields(model), ] .filter(f => f) .join('\n\n')), '})', ].join('\n'); declarationBlock.addClassMember('schema', '', schema, { static: true, var: true, inferType: true }); } generateAuthRules(model) { const authDirectives = model.directives.filter(d => d.name === 'auth'); if (authDirectives.length) { const rules = []; authDirectives.forEach(directive => { var _a; (_a = directive.arguments) === null || _a === void 0 ? void 0 : _a.rules.forEach(rule => { var _a; const authRule = []; const authStrategy = `authStrategy: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.AuthStrategy}.${rule.allow.toUpperCase()}`; switch (rule.allow) { case process_auth_1.AuthStrategy.owner: authRule.push(authStrategy); authRule.push(`ownerField: "${rule.ownerField}"`); authRule.push(`identityClaim: "${rule.identityClaim}"`); break; case process_auth_1.AuthStrategy.private: case process_auth_1.AuthStrategy.public: authRule.push(authStrategy); break; case process_auth_1.AuthStrategy.groups: authRule.push(authStrategy); authRule.push(`groupClaim: "${rule.groupClaim}"`); if (rule.groups) { authRule.push(`groups: [ ${(_a = rule.groups) === null || _a === void 0 ? void 0 : _a.map(group => `"${group}"`).join(', ')} ]`); } else { authRule.push(`groupsField: "${rule.groupField}"`); } break; default: (0, warn_1.printWarning)(`Model has auth with authStrategy ${rule.allow} of which is not yet supported`); return ''; } if (rule.provider) { authRule.push(`provider: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.AuthRuleProvider}.${rule.provider.toUpperCase()}`); } authRule.push([ 'operations: const [', (0, visitor_plugin_common_1.indentMultiline)(rule.operations.map(op => `${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelOperation}.${op.toUpperCase()}`).join(',\n')), ']', ].join('\n')); rules.push(`${dart_config_1.DART_AMPLIFY_CORE_TYPES.AuthRule}(\n${(0, visitor_plugin_common_1.indentMultiline)(authRule.join(',\n'))})`); }); }); if (rules.length) { return ['modelSchemaDefinition.authRules = [', (0, visitor_plugin_common_1.indentMultiline)(rules.join(',\n')), '];'].join('\n'); } } return ''; } generateIndexes(model) { const indexes = model.directives .filter(directive => directive.name === 'key') .map(directive => { const name = directive.arguments.name ? `"${directive.arguments.name}"` : 'null'; const fields = directive.arguments.fields.map((field) => `"${field}"`).join(', '); return `${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelIndex}(fields: const [${fields}], name: ${name})`; }); if (indexes.length) { return ['modelSchemaDefinition.indexes = [', (0, visitor_plugin_common_1.indentMultiline)(indexes.join(',\n')), '];'].join('\n'); } return ''; } generateAddFields(model) { if (model.fields.length) { const fieldsToAdd = []; model.fields.forEach(field => { const fieldName = this.getFieldName(field); const modelName = this.getModelName(model); const queryFieldName = this.getQueryFieldName(field); let fieldParam = ''; if (fieldName === 'id') { fieldsToAdd.push(`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldDefinition}.id()`); } else if (field.connectionInfo) { const connectedModelName = this.getNativeType({ ...field, isList: false }); switch (field.connectionInfo.kind) { case process_connections_1.CodeGenConnectionType.HAS_ONE: { let associatedString = `associatedKey: ${connectedModelName}.${this.getQueryFieldName(field.connectionInfo.associatedWith)}`; if (field.connectionInfo.associatedWithNativeReferences) { associatedString = `associatedKey: ${connectedModelName}.${this.getQueryFieldName(field.connectionInfo.associatedWithNativeReferences)}`; } fieldParam = [ `key: ${modelName}.${queryFieldName}`, `isRequired: ${!field.isNullable}`, `ofModelName: '${connectedModelName}'`, associatedString, ].join(',\n'); fieldsToAdd.push([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldDefinition}.hasOne(`, (0, visitor_plugin_common_1.indentMultiline)(fieldParam), ')'].join('\n')); break; } case process_connections_1.CodeGenConnectionType.HAS_MANY: { let associatedString = `associatedKey: ${connectedModelName}.${this.getQueryFieldName(field.connectionInfo.associatedWith)}`; if (field.connectionInfo.associatedWithNativeReferences) { associatedString = `associatedKey: ${connectedModelName}.${this.getQueryFieldName(field.connectionInfo.associatedWithNativeReferences)}`; } fieldParam = [ `key: ${modelName}.${queryFieldName}`, `isRequired: ${!field.isNullable}`, `ofModelName: '${connectedModelName}'`, associatedString, ].join(',\n'); fieldsToAdd.push([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldDefinition}.hasMany(`, (0, visitor_plugin_common_1.indentMultiline)(fieldParam), ')'].join('\n')); break; } case process_connections_1.CodeGenConnectionType.BELONGS_TO: fieldParam = [ `key: ${modelName}.${queryFieldName}`, `isRequired: ${!field.isNullable}`, this.isCustomPKEnabled() ? `targetNames: [${field.connectionInfo.targetNames.map(target => `'${target}'`).join(', ')}]` : `targetName: '${field.connectionInfo.targetName}'`, `ofModelName: '${connectedModelName}'`, ].join(',\n'); fieldsToAdd.push([`${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldDefinition}.belongsTo(`, (0, visitor_plugin_common_1.indentMultiline)(fieldParam), ')'].join('\n')); break; } } else { const ofType = this.getOfType(field); let ofTypeStr; if (field.isList) { if (ofType === '.embedded') { ofTypeStr = `ofType: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldType}(${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}.embeddedCollection, ofCustomTypeName: '${field.type}')`; } else { ofTypeStr = `ofType: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldType}(${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}.collection, ofModelName: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}${ofType}.name)`; } } else if (ofType === '.embedded') { ofTypeStr = `ofType: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldType}(${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}${ofType}, ofCustomTypeName: '${field.type}')`; } else { ofTypeStr = `ofType: ${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldType}(${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldTypeEnum}${ofType})`; } fieldParam = [ ...(ofType === '.embedded' || field.isReadOnly ? [`fieldName: '${fieldName}'`] : [`key: ${modelName}.${queryFieldName}`]), `isRequired: ${this.isFieldRequired(field)}`, field.isList ? 'isArray: true' : '', field.isReadOnly ? 'isReadOnly: true' : '', ofTypeStr, ] .filter(f => f) .join(',\n'); fieldsToAdd.push([ `${dart_config_1.DART_AMPLIFY_CORE_TYPES.ModelFieldDefinition}.${ofType === '.embedded' ? 'embedded' : field.isReadOnly ? 'nonQueryField' : 'field'}(`, (0, visitor_plugin_common_1.indentMultiline)(fieldParam), '