UNPKG

@graphql-codegen/flutter-freezed

Version:

GraphQL Code Generator plugin to generate Freezed models from your GraphQL schema

233 lines (232 loc) • 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FreezedDeclarationBlock = void 0; const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common"); const graphql_1 = require("graphql"); const change_case_all_1 = require("change-case-all"); const utils_js_1 = require("../utils.js"); const factory_block_js_1 = require("./factory-block.js"); class FreezedDeclarationBlock { constructor(_config, _freezedFactoryBlockRepository, _node) { this._config = _config; this._freezedFactoryBlockRepository = _freezedFactoryBlockRepository; this._node = _node; /** document the class */ this._comment = ''; /** a list of decorators to copy paste to the generator */ this._decorators = []; /** a list of default constructor and named Constructors used create a Freezed union/sealed class */ this._factoryBlocks = []; this._config = _config; this._freezedFactoryBlockRepository = _freezedFactoryBlockRepository; this._node = _node; this._freezedConfigValue = new utils_js_1.FreezedConfigValue(this._config, this._node.name.value); } init() { if (this._node.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION) { this.setDecorators().setName().setShape().setBlock(); return this; } this.setComment().setDecorators().setName().setFactoryBlocks().setShape().setBlock(); return this; } setComment() { var _a; const comment = (_a = this._node.description) === null || _a === void 0 ? void 0 : _a.value; if (comment && comment !== null && comment !== '') { this._comment = `/// ${comment} \n`; } return this; } getEnumComment(value) { var _a; const comment = (_a = value.description) === null || _a === void 0 ? void 0 : _a.value; if (comment && comment !== null && comment !== '') { return `/// ${comment} \n`; } return ''; } setDecorators() { var _a, _b; const name = this._node.name.value; // determine if should mark as deprecated const isDeprecated = (_b = (_a = this._config.typeSpecificFreezedConfig) === null || _a === void 0 ? void 0 : _a[name]) === null || _b === void 0 ? void 0 : _b.deprecated; this._decorators = this._node.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION ? [...(0, utils_js_1.transformCustomDecorators)((0, utils_js_1.getCustomDecorators)(this._config, ['enum'], name), this._node)] : [ this.getFreezedDecorator(), ...(0, utils_js_1.transformCustomDecorators)((0, utils_js_1.getCustomDecorators)(this._config, ['class'], name), this._node), ]; // @deprecated // if this._decorators doesn't include an @deprecated decorator but the field is marked as @deprecated... if (!this._decorators.includes('@deprecated') && isDeprecated) { this._decorators = [...this._decorators, '@deprecated\n']; } return this; } getFreezedDecorator() { const use_unfreezed = () => { if (!this._freezedConfigValue.get('immutable') || (this._node.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION && this._freezedConfigValue.get('mutableInputs'))) { return '@unfreezed\n'; } return use_Freezed_or_freezed(); }; const use_Freezed_or_freezed = () => { if (isCustomizedFreezed()) { const copyWith = this._freezedConfigValue.get('copyWith'); const equal = this._freezedConfigValue.get('equal'); const makeCollectionsUnmodifiable = this._freezedConfigValue.get('makeCollectionsUnmodifiable'); const unionKey = this._freezedConfigValue.get('unionKey'); const unionValueCase = this._freezedConfigValue.get('unionValueCase'); let atFreezed = '@Freezed(\n'; if (copyWith !== undefined) { atFreezed += (0, visitor_plugin_common_1.indent)(`copyWith: ${copyWith},\n`); } if (equal !== undefined) { atFreezed += (0, visitor_plugin_common_1.indent)(`equal: ${equal},\n`); } if (makeCollectionsUnmodifiable !== undefined) { atFreezed += (0, visitor_plugin_common_1.indent)(`makeCollectionsUnmodifiable: ${makeCollectionsUnmodifiable},\n`); } if (unionKey !== undefined) { atFreezed += (0, visitor_plugin_common_1.indent)(`unionKey: ${unionKey},\n`); } if (unionValueCase !== undefined) { atFreezed += (0, visitor_plugin_common_1.indent)(`unionValueCase: '${unionValueCase}',\n`); } atFreezed += ')\n'; return atFreezed; } // else fallback to the normal @freezed decorator return '@freezed\n'; }; const isCustomizedFreezed = () => { return (this._freezedConfigValue.get('copyWith') !== undefined || this._freezedConfigValue.get('equal') !== undefined || this._freezedConfigValue.get('makeCollectionsUnmodifiable') !== undefined || this._freezedConfigValue.get('unionKey') !== undefined || this._freezedConfigValue.get('unionValueCase') !== undefined); }; // this is the start of the pipeline of decisions to determine which Freezed decorator to use return use_unfreezed(); } setName() { this._name = (0, change_case_all_1.pascalCase)(this._node.name.value); return this; } setFactoryBlocks() { var _a, _b, _c, _d; if (this._node.kind === graphql_1.Kind.UNION_TYPE_DEFINITION) { this._factoryBlocks = (_b = (_a = this._node.types) === null || _a === void 0 ? void 0 : _a.map((_type) => new factory_block_js_1.FreezedFactoryBlock(this._config, this._node).init())) !== null && _b !== void 0 ? _b : []; } else if (this._node.kind !== graphql_1.Kind.ENUM_TYPE_DEFINITION) { /* for `ObjectTypeDefinitionNode` and `InputObjectTypeDefinitionNode` nodes, we use the `ShapeRepository` to register the `FreezedFactoryBlock` so that we can use it later when we are merging inputs or generating freezed union/sealed classes for GraphQL union types */ this._factoryBlocks = (_d = (_c = this._node.fields) === null || _c === void 0 ? void 0 : _c.map((_field) => this._freezedFactoryBlockRepository.register(this._node.name.value, new factory_block_js_1.FreezedFactoryBlock(this._config, this._node).init()))) !== null && _d !== void 0 ? _d : []; } return this; } setShape() { var _a, _b, _c; let shape = ''; // some helper variables const name = this._node.name.value; let namedConstructor; let factoryBlockKey; // handle enums differently if (this._node.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION) { this._shape = (_a = this._node.values) === null || _a === void 0 ? void 0 : _a.map((value) => { var _a; shape = (0, visitor_plugin_common_1.indent)(this.getEnumComment(value)); if ((_a = this._config.camelCasedEnums) !== null && _a !== void 0 ? _a : true) { shape += `@JsonKey(name: ${value.name.value}) ${value.name.value.toLowerCase()}`; } else { shape += value.name.value; } return `${shape}\n`; }).join(''); return this; } // append private empty constructor if (this._freezedConfigValue.get('privateEmptyConstructor')) { shape += (0, visitor_plugin_common_1.indent)(`const ${this._name}._();\n\n`); } // decide whether to append an empty Union constructor if (this._freezedConfigValue.get('defaultUnionConstructor') && this._node.kind === graphql_1.Kind.UNION_TYPE_DEFINITION) { shape += (0, visitor_plugin_common_1.indent)(`const factory ${this._name}() = _${this._name};\n\n`); } // append tokens which will be used to retrieve the factory blocks // from the FreezedFactoryBlockRepository if (this._node.kind === graphql_1.Kind.UNION_TYPE_DEFINITION) { (_c = (_b = this._node) === null || _b === void 0 ? void 0 : _b.types) === null || _c === void 0 ? void 0 : _c.forEach(type => { namedConstructor = type.name.value; factoryBlockKey = namedConstructor; shape += `==>factory==>${factoryBlockKey}==>${'union_factory'}==>${name}==>${namedConstructor}\n`; }); } else { factoryBlockKey = name; // replace token for the ObjectType & InputType to be replaced with the default Freezed constructor shape += `==>factory==>${factoryBlockKey}==>${'class_factory'}==>${name}\n`; const mergeInputs = this._freezedConfigValue.get('mergeInputs'); if (this._node.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION && mergeInputs) { // replace token for the InputTypes(a.k.a namedConstructors) as a union/sealed class mergeInputs.forEach(input => { const separator = input.includes('$') ? '$' : input.includes(name) ? name : '*'; namedConstructor = (0, change_case_all_1.camelCase)(input.split(separator).join('_')); factoryBlockKey = input.replace('$', name); shape += `==>factory==>${factoryBlockKey}==>${'merged_input_factory'}==>${name}==>${namedConstructor}\n`; }); } } this._shape = shape; return this; } /** * returns the string output of the block */ setBlock() { let block = ''; //append comment block += this._comment; // append the decorators block += this._decorators.join(''); // handle enums differently if (this._node.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION) { block += `enum ${this._name}{\n${this._shape}}\n\n`; this._block = block; return this; } // append start of class definition block += `class ${this._name} with _$${this._name} {\n`; // append the shape block += this._shape; // append fromJson if (this._freezedConfigValue.get('fromJsonToJson')) { block += (0, visitor_plugin_common_1.indent)(`factory ${this._name}.fromJson(Map<String, Object?> json) => _${this._name}FromJson(json);\n`); } //append end of class definition block += '}\n\n'; this._block = block; return this; } /** returns the block */ toString() { if (!this._block) { throw new Error('setShape must be called before calling toString()'); } return this._block; } } exports.FreezedDeclarationBlock = FreezedDeclarationBlock;