@graphql-codegen/flutter-freezed
Version:
GraphQL Code Generator plugin to generate Freezed models from your GraphQL schema
93 lines (92 loc) • 4.24 kB
JavaScript
import { Kind } from 'graphql';
import { indent } from '@graphql-codegen/visitor-plugin-common';
import { Config } from '../config/config-value.js';
import { TypeName } from '../config/pattern.js';
import { APPLIES_ON_CLASS } from '../config/plugin-config.js';
import { nodeIsObjectType, stringIsNotEmpty } from '../utils.js';
import { FactoryBlock } from './factory-block.js';
import { Block } from './index.js';
export class ClassBlock {
static build(config, node) {
const typeName = TypeName.fromString(node.name.value);
const _className = Block.buildBlockName(config, APPLIES_ON_CLASS, typeName.value, typeName, undefined, 'PascalCase');
let block = '';
// the comments should be on the factory block instead
// block += Block.buildComment(node);
block += this.buildDecorators(config, node);
block += this.buildHeader(config, typeName, _className);
block += this.buildBody(config, node);
block += this.buildFooter(_className);
return block;
}
}
ClassBlock.buildDecorators = (config, node) => {
const freezedDecorator = ClassBlock.buildFreezedDecorator(config, node);
// TODO: consider implementing custom decorators
return [freezedDecorator].join('');
};
ClassBlock.buildFreezedDecorator = (config, node) => {
// this is the start of the pipeline of decisions to determine which Freezed decorator to use
return ClassBlock.decorateAsFreezed(config, node);
};
ClassBlock.decorateAsFreezed = (config, node) => {
const typeName = TypeName.fromString(node.name.value);
const copyWith = Config.copyWith(config, typeName);
const equal = Config.equal(config, typeName);
const makeCollectionsUnmodifiable = Config.makeCollectionsUnmodifiable(config, typeName);
const unionKey = Config.unionKey();
const unionValueCase = Config.unionValueCase();
const body = [
copyWith !== undefined ? `copyWith: ${copyWith},\n` : undefined,
equal !== undefined ? `equal: ${equal},\n` : undefined,
makeCollectionsUnmodifiable !== undefined
? `makeCollectionsUnmodifiable: ${makeCollectionsUnmodifiable},\n`
: undefined,
unionKey !== undefined ? `unionKey: ${unionKey},\n` : undefined,
unionValueCase !== undefined ? `unionValueCase: '${unionValueCase}',\n` : undefined,
]
.filter(value => value !== undefined)
.map(value => indent(value))
.join('');
return stringIsNotEmpty(body)
? `@Freezed(\n${body})\n`
: ClassBlock.decorateAsUnfreezed(config, node);
};
ClassBlock.decorateAsUnfreezed = (config, node) => {
const typeName = TypeName.fromString(node.name.value);
const immutable = Config.immutable(config, typeName);
const mutableInputs = Config.mutableInputs(config, typeName);
const mutable = immutable !== true || (node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION && mutableInputs);
return mutable ? '@unfreezed\n' : '@freezed\n';
};
ClassBlock.buildHeader = (config, typeName, _className) => {
const privateEmptyConstructor = Config.privateEmptyConstructor(config, typeName)
? indent(`const ${_className}._();\n\n`)
: '';
return `class ${_className} with _$${_className} {\n${privateEmptyConstructor}`;
};
ClassBlock.buildBody = (config, node) => {
var _a;
const className = TypeName.fromString(node.name.value);
let body = '';
if (nodeIsObjectType(node)) {
body += FactoryBlock.serializeDefaultFactory(className);
}
else if (node.kind === Kind.UNION_TYPE_DEFINITION) {
body += ((_a = node.types) !== null && _a !== void 0 ? _a : [])
.map(value => {
const factoryName = TypeName.fromString(value.name.value);
return FactoryBlock.serializeUnionFactory(className, factoryName);
})
.join('');
}
body += Config.mergeTypes(config, className)
.map(factoryName => {
return FactoryBlock.serializeMergedFactory(className, factoryName);
})
.join('');
return body;
};
ClassBlock.buildFooter = (_className) => {
return indent(`factory ${_className}.fromJson(Map<String, dynamic> json) => _$${_className}FromJson(json);\n}\n\n`);
};