UNPKG

@graphql-codegen/flutter-freezed

Version:

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

92 lines (91 loc) 4.4 kB
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)); });