@graphql-codegen/flutter-freezed
Version:
GraphQL Code Generator plugin to generate Freezed models from your GraphQL schema
92 lines (91 loc) • 4.4 kB
JavaScript
import { snakeCase } from 'change-case-all';
import { Kind } from 'graphql';
import { Config } from '../config/config-value.js';
import { TypeName } from '../config/pattern.js';
import { dartCasing, escapeDartKeyword, isDartKeyword, nodeIsObjectType } from '../utils.js';
import { ClassBlock } from './class-block.js';
import { EnumBlock } from './enum-block.js';
import { FactoryBlock } from './factory-block.js';
export class Block {
}
Block.buildImportStatements = (fileName) => {
if (fileName.length < 1) {
throw new Error('fileName is required and must not be empty');
}
const segments = fileName.split('/');
const target = segments[segments.length - 1];
const expectedFileName = snakeCase(target.replace(/\.dart/g, ''));
return [
`import 'package:freezed_annotation/freezed_annotation.dart';\n`,
`import 'package:flutter/foundation.dart';\n\n`,
`part '${expectedFileName}.freezed.dart';\n`,
`part '${expectedFileName}.g.dart';\n\n`,
].join('');
};
/**
* Transforms the AST nodes into Freezed classes/models
* @param config The plugin configuration object
* @param node the AST node passed by the schema visitor
* @param nodeRepository A map that stores the name of the Graphql Type as the key and it AST node as the value. Used to build FactoryBlocks from placeholders for mergedInputs and Union Types
* @returns a string output of a `FreezedDeclarationBlock` which represents a Freezed class/model in Dart
*/
Block.build = (config, node, nodeRepository) => {
// ignore these...
const typeName = TypeName.fromString(node.name.value);
if (['Query', 'Mutation', 'Subscription', ...Config.ignoreTypes(config, typeName)].includes(typeName.value)) {
return '';
}
// registers all the ObjectTypes
if (nodeIsObjectType(node)) {
nodeRepository.register(node);
}
return node.kind === Kind.ENUM_TYPE_DEFINITION
? EnumBlock.build(config, node)
: ClassBlock.build(config, node);
};
Block.buildComment = (node) => {
var _a;
const comment = (_a = node === null || node === void 0 ? void 0 : node.description) === null || _a === void 0 ? void 0 : _a.value;
return comment && (comment === null || comment === void 0 ? void 0 : comment.length) > 0
? `${comment
.trim()
.split(/\n/gm)
.map(c => `/// ${c.trim().replace(/^#/, '')}\n`)
.join('')}`
: '';
};
Block.buildBlockName = (config, blockAppliesOn, identifier, typeName, fieldName, blockCasing) => {
identifier = dartCasing(identifier, blockCasing);
if (isDartKeyword(identifier)) {
return escapeDartKeyword(config, blockAppliesOn, identifier, typeName, fieldName);
}
return identifier;
};
Block.tokens = {
defaultFactory: '==>default_factory==>',
unionFactory: '==>union_factory==>',
mergedFactory: '==>merged_factory==>',
fromJsonToJson: '==>from_json_to_json==>',
};
Block.regexpForToken = (tokenName) => {
return RegExp(`${Block.tokens[tokenName]}.+\n`, 'gm');
};
Block.replaceTokens = (config, nodeRepository, generatedBlocks) => generatedBlocks
.map(block => {
block = Block.replaceDefaultFactoryToken(block, config, nodeRepository);
block = Block.replaceNamedFactoryToken(block, config, nodeRepository, 'unionFactory');
block = Block.replaceNamedFactoryToken(block, config, nodeRepository, 'mergedFactory');
// TODO: one more for parameter fromJson and toJson tokens inside @JsonKey
return block;
})
.join('');
Block.replaceDefaultFactoryToken = (block, config, nodeRepository) => block.replace(Block.regexpForToken('defaultFactory'), token => {
const pattern = token.replace(Block.tokens.defaultFactory, '').trim();
const [className, blockAppliesOn] = pattern.split('==>');
return FactoryBlock.deserializeFactory(config, nodeRepository, blockAppliesOn.split(','), TypeName.fromString(className));
});
Block.replaceNamedFactoryToken = (block, config, nodeRepository, blockType) => block.replace(Block.regexpForToken(blockType), token => {
const pattern = token.replace(Block.tokens[blockType], '').trim();
const [className, factoryName, blockAppliesOn] = pattern.split('==>');
return FactoryBlock.deserializeNamedFactory(config, nodeRepository, blockAppliesOn.split(','), TypeName.fromString(className), TypeName.fromString(factoryName));
});