UNPKG

graphql-codegen-flutter-freezed

Version:

A stand-alone package to generate Freezed models from GraphQL schema based on the flutter-freezed plugin for GraphQL Code Generator

129 lines (128 loc) 4.58 kB
import { indent } from '@graphql-codegen/visitor-plugin-common'; import { Kind } from 'graphql'; import { camelCase, pascalCase } from 'change-case-all'; import { FreezedParameterBlock } from './parameter-block'; import { FreezedConfigValue, getCustomDecorators, transformCustomDecorators } from '../utils'; export class FreezedFactoryBlock { _config; _node; /** document the constructor */ _comment = ''; /** a list of decorators to copy paste to the generator */ _decorators = []; /** the key of the original type name */ _key; /** the name of the class */ _name; /** the namedConstructor is used for GraphQL Union types or if mergeInput is true */ _namedConstructor; /** a list of interfaces to implements */ // _implements: string[] = []; /** a list of class to mixin with */ // _mixins: string[] = []; /** the parameters of this factory constructor */ // TODO: handle other parameter types like positional parameters later. // TODO: sticking to named parameters because GraphQL is a typed language _parameters = []; /** the shape is the content of the block */ _shape; /** the block is the final structure that is generated */ _block; _freezedConfigValue; constructor(_config, _node) { this._config = _config; this._node = _node; this._config = _config; this._node = _node; this._freezedConfigValue = new FreezedConfigValue(_config, _node.name.value); } init() { /* setDecorators(), setName() and setType() will be called when the factory is retrieved from the repository */ this.setComment().setParameters().setShape().setBlock(); return this; } setComment() { const comment = this._node.description?.value; if (comment && comment !== null && comment !== '') { this._comment = indent(`/// ${comment} \n`); } return this; } setDecorators(appliesOn, nodeName) { this._decorators = [ ...transformCustomDecorators(getCustomDecorators(this._config, appliesOn.split(','), nodeName), this._node), ]; return this; } setKey(key) { this._key = pascalCase(key); return this; } setName(name) { this._name = pascalCase(name); return this; } setNamedConstructor(namedConstructor) { if (namedConstructor) { this._namedConstructor = camelCase(namedConstructor); } return this; } setParameters() { const appliesOn = this._namedConstructor ? ['union_factory_parameter'] : ['class_factory_parameter']; if (this._node.kind !== Kind.UNION_TYPE_DEFINITION && this._node.kind !== Kind.ENUM_TYPE_DEFINITION) { this._parameters = this._node?.fields?.map((field) => new FreezedParameterBlock(this._config, appliesOn, this._node, field).init()) ?? []; } return this; } setShape() { this._shape = this._parameters.map(p => p.toString()).join(''); return this; } setBlock() { let block = ''; //append comment block += this._comment; // append the decorators block += this._decorators.map(d => indent(`${d}\n`)).join(''); block += indent(''); // decide if to use const or not if (this._freezedConfigValue.get('immutable')) { block += 'const '; } // append the factory keyword and the name block += `factory ${this._name}`; // append .namedConstructor is not null if (this._namedConstructor && this._namedConstructor !== '') { block += `.${this._namedConstructor}`; } // append the parenthesis for the constructor and braces for the named parameters block += '({\n'; //append the shape block += this._shape; // close the constructor and assign the key block += indent(`}) = `); // but first decide whether prefix the key with an underscore if (!this._namedConstructor) { block += '_'; } // finally, append the key block += `${this._key};\n`; // store it in the shape this._block = block; return this; } /** returns the block */ toString() { if (!this._block) { throw new Error('FreezedFactoryBlock: setShape must be called before calling toString()'); } return this._block; } }