@graphql-codegen/flutter-freezed 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/config.js +2 -0
- package/cjs/freezed-declaration-blocks/class-block.js +221 -0
- package/cjs/freezed-declaration-blocks/factory-block.js +121 -0
- package/cjs/freezed-declaration-blocks/index.js +6 -0
- package/cjs/freezed-declaration-blocks/parameter-block.js +150 -0
- package/cjs/index.js +27 -0
- package/cjs/package.json +1 -0
- package/cjs/schema-visitor.js +15 -0
- package/cjs/utils.js +221 -0
- package/esm/config.js +1 -0
- package/esm/freezed-declaration-blocks/class-block.js +217 -0
- package/esm/freezed-declaration-blocks/factory-block.js +117 -0
- package/esm/freezed-declaration-blocks/index.js +3 -0
- package/esm/freezed-declaration-blocks/parameter-block.js +146 -0
- package/esm/index.js +23 -0
- package/esm/schema-visitor.js +11 -0
- package/esm/utils.js +209 -0
- package/package.json +46 -0
- package/typings/config.d.cts +453 -0
- package/typings/config.d.ts +453 -0
- package/typings/freezed-declaration-blocks/class-block.d.cts +36 -0
- package/typings/freezed-declaration-blocks/class-block.d.ts +36 -0
- package/typings/freezed-declaration-blocks/factory-block.d.cts +38 -0
- package/typings/freezed-declaration-blocks/factory-block.d.ts +38 -0
- package/typings/freezed-declaration-blocks/index.d.cts +3 -0
- package/typings/freezed-declaration-blocks/index.d.ts +3 -0
- package/typings/freezed-declaration-blocks/parameter-block.d.cts +45 -0
- package/typings/freezed-declaration-blocks/parameter-block.d.ts +45 -0
- package/typings/index.d.cts +3 -0
- package/typings/index.d.ts +3 -0
- package/typings/schema-visitor.d.cts +10 -0
- package/typings/schema-visitor.d.ts +10 -0
- package/typings/utils.d.cts +78 -0
- package/typings/utils.d.ts +78 -0
package/cjs/utils.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultFreezedConfig = exports.DefaultFreezedPluginConfig = exports.FreezedFactoryBlockRepository = exports.FreezedConfigValue = exports.addFreezedImportStatements = exports.transformCustomDecorators = exports.getCustomDecorators = exports.getFreezedConfigValue = exports.transformDefinition = void 0;
|
|
4
|
+
const index_js_1 = require("./freezed-declaration-blocks/index.js");
|
|
5
|
+
function transformDefinition(config, freezedFactoryBlockRepository, node) {
|
|
6
|
+
var _a;
|
|
7
|
+
// ignore these...
|
|
8
|
+
if (['Query', 'Mutation', 'Subscription', ...((_a = config === null || config === void 0 ? void 0 : config.ignoreTypes) !== null && _a !== void 0 ? _a : [])].includes(node.name.value)) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
return new index_js_1.FreezedDeclarationBlock(config, freezedFactoryBlockRepository, node).init();
|
|
12
|
+
}
|
|
13
|
+
exports.transformDefinition = transformDefinition;
|
|
14
|
+
/**
|
|
15
|
+
* returns the value of the FreezedConfig option
|
|
16
|
+
* for a specific type if given typeName
|
|
17
|
+
* or else fallback to the global FreezedConfig value
|
|
18
|
+
*/
|
|
19
|
+
function getFreezedConfigValue(option, config, typeName) {
|
|
20
|
+
var _a, _b, _c, _d, _e;
|
|
21
|
+
if (typeName) {
|
|
22
|
+
return (_d = (_c = (_b = (_a = config === null || config === void 0 ? void 0 : config.typeSpecificFreezedConfig) === null || _a === void 0 ? void 0 : _a[typeName]) === null || _b === void 0 ? void 0 : _b.config) === null || _c === void 0 ? void 0 : _c[option]) !== null && _d !== void 0 ? _d : getFreezedConfigValue(option, config);
|
|
23
|
+
}
|
|
24
|
+
return (_e = config === null || config === void 0 ? void 0 : config.globalFreezedConfig) === null || _e === void 0 ? void 0 : _e[option];
|
|
25
|
+
}
|
|
26
|
+
exports.getFreezedConfigValue = getFreezedConfigValue;
|
|
27
|
+
/**
|
|
28
|
+
* @description filters the customDirectives to return those that are applied on a list of blocks
|
|
29
|
+
*/
|
|
30
|
+
function getCustomDecorators(config, appliesOn, nodeName, fieldName) {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
32
|
+
const filteredCustomDecorators = {};
|
|
33
|
+
const globalCustomDecorators = (_b = (_a = config === null || config === void 0 ? void 0 : config.globalFreezedConfig) === null || _a === void 0 ? void 0 : _a.customDecorators) !== null && _b !== void 0 ? _b : {};
|
|
34
|
+
let customDecorators = { ...globalCustomDecorators };
|
|
35
|
+
if (nodeName) {
|
|
36
|
+
const typeConfig = (_c = config === null || config === void 0 ? void 0 : config.typeSpecificFreezedConfig) === null || _c === void 0 ? void 0 : _c[nodeName];
|
|
37
|
+
const typeSpecificCustomDecorators = (_e = (_d = typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.config) === null || _d === void 0 ? void 0 : _d.customDecorators) !== null && _e !== void 0 ? _e : {};
|
|
38
|
+
customDecorators = { ...customDecorators, ...typeSpecificCustomDecorators };
|
|
39
|
+
if (fieldName) {
|
|
40
|
+
const fieldSpecificCustomDecorators = (_h = (_g = (_f = typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.fields) === null || _f === void 0 ? void 0 : _f[fieldName]) === null || _g === void 0 ? void 0 : _g.customDecorators) !== null && _h !== void 0 ? _h : {};
|
|
41
|
+
customDecorators = { ...customDecorators, ...fieldSpecificCustomDecorators };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
Object.entries(customDecorators).forEach(([key, value]) => {
|
|
45
|
+
var _a;
|
|
46
|
+
return (_a = value === null || value === void 0 ? void 0 : value.applyOn) === null || _a === void 0 ? void 0 : _a.forEach(a => {
|
|
47
|
+
if (appliesOn.includes(a)) {
|
|
48
|
+
filteredCustomDecorators[key] = value;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return filteredCustomDecorators;
|
|
53
|
+
}
|
|
54
|
+
exports.getCustomDecorators = getCustomDecorators;
|
|
55
|
+
function transformCustomDecorators(customDecorators, node, field) {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
let result = [];
|
|
58
|
+
result = [
|
|
59
|
+
...result,
|
|
60
|
+
...((_a = node === null || node === void 0 ? void 0 : node.directives) !== null && _a !== void 0 ? _a : [])
|
|
61
|
+
.concat((_b = field === null || field === void 0 ? void 0 : field.directives) !== null && _b !== void 0 ? _b : [])
|
|
62
|
+
// extract only the directives whose names were specified as keys
|
|
63
|
+
// and have values that not undefined or null in the customDecorator record
|
|
64
|
+
.filter(d => {
|
|
65
|
+
var _a;
|
|
66
|
+
const key = d.name.value;
|
|
67
|
+
const value = (_a = customDecorators[key]) !== null && _a !== void 0 ? _a : customDecorators[`@${key}`];
|
|
68
|
+
if (value && value.mapsToFreezedAs !== 'custom') {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
})
|
|
73
|
+
// transform each directive to string
|
|
74
|
+
.map(d => directiveToString(d, customDecorators)),
|
|
75
|
+
];
|
|
76
|
+
// for decorators that mapsToFreezedAs === 'custom'
|
|
77
|
+
Object.entries(customDecorators).forEach(([key, value]) => {
|
|
78
|
+
if (value.mapsToFreezedAs === 'custom') {
|
|
79
|
+
const args = value === null || value === void 0 ? void 0 : value.arguments;
|
|
80
|
+
// if the custom directives have arguments,
|
|
81
|
+
if (args && args !== []) {
|
|
82
|
+
// join them with a comma in the parenthesis
|
|
83
|
+
result = [...result, `${key}(${args.join(', ')})`];
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// else return the customDecorator key just as it is
|
|
87
|
+
result = [...result, key];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
exports.transformCustomDecorators = transformCustomDecorators;
|
|
94
|
+
/**
|
|
95
|
+
* transforms the directive into a decorator array
|
|
96
|
+
* this decorator array might contain a `final` string which would be filtered out
|
|
97
|
+
* and used to mark the parameter block as final
|
|
98
|
+
*/
|
|
99
|
+
function directiveToString(directive, customDecorators) {
|
|
100
|
+
var _a, _b, _c, _d, _e;
|
|
101
|
+
const key = directive.name.value;
|
|
102
|
+
const value = customDecorators[key];
|
|
103
|
+
if (value.mapsToFreezedAs === 'directive') {
|
|
104
|
+
// get the directive's arguments
|
|
105
|
+
const directiveArgs = (_a = directive === null || directive === void 0 ? void 0 : directive.arguments) !== null && _a !== void 0 ? _a : [];
|
|
106
|
+
// extract the directive's argument using the template index: ["$0", "$1", ...]
|
|
107
|
+
// specified in the customDecorator.arguments array
|
|
108
|
+
const args = (_b = value === null || value === void 0 ? void 0 : value.arguments) === null || _b === void 0 ? void 0 : _b.filter(a => directiveArgs[argToInt(a)]).map(a => directiveArgs[argToInt(a)]).map(a => `${a.name}: ${a.value}`);
|
|
109
|
+
// if the args is not empty
|
|
110
|
+
if (args !== []) {
|
|
111
|
+
// returns "@directiveName(argName: argValue, argName: argValue ...)"
|
|
112
|
+
return `@${directive.name.value}(${args === null || args === void 0 ? void 0 : args.join(', ')})`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (value.mapsToFreezedAs === '@Default') {
|
|
116
|
+
const defaultValue = (_c = directive === null || directive === void 0 ? void 0 : directive.arguments) === null || _c === void 0 ? void 0 : _c[argToInt((_e = (_d = value === null || value === void 0 ? void 0 : value.arguments) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : '0')];
|
|
117
|
+
if (defaultValue) {
|
|
118
|
+
return `@Default(value: ${defaultValue})`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// returns either "@deprecated" || "final".
|
|
122
|
+
// `final` to be filtered from the decorators array when applying the decorators
|
|
123
|
+
return value.mapsToFreezedAs;
|
|
124
|
+
}
|
|
125
|
+
/** transforms string template: "$0" into an integer: 1 */
|
|
126
|
+
function argToInt(arg) {
|
|
127
|
+
var _a;
|
|
128
|
+
const parsedIndex = Number.parseInt((_a = arg.replace('$', '').trim()) !== null && _a !== void 0 ? _a : '0'); // '$1 => 1
|
|
129
|
+
return parsedIndex ? parsedIndex : 0;
|
|
130
|
+
}
|
|
131
|
+
/** returns freezed import statements */
|
|
132
|
+
function addFreezedImportStatements(fileName) {
|
|
133
|
+
return [
|
|
134
|
+
"import 'package:freezed_annotation/freezed_annotation.dart';\n",
|
|
135
|
+
"import 'package:flutter/foundation.dart';\n\n",
|
|
136
|
+
`part ${fileName}.dart;\n`,
|
|
137
|
+
`part '${fileName}.g.dart';\n\n`,
|
|
138
|
+
].join('');
|
|
139
|
+
}
|
|
140
|
+
exports.addFreezedImportStatements = addFreezedImportStatements;
|
|
141
|
+
/** a class variant of the getFreezedConfigValue helper function
|
|
142
|
+
*
|
|
143
|
+
* returns the value of the FreezedConfig option
|
|
144
|
+
* for a specific type if given typeName
|
|
145
|
+
* or else fallback to the global FreezedConfig value
|
|
146
|
+
*/
|
|
147
|
+
class FreezedConfigValue {
|
|
148
|
+
constructor(_config, _typeName) {
|
|
149
|
+
this._config = _config;
|
|
150
|
+
this._typeName = _typeName;
|
|
151
|
+
this._config = _config;
|
|
152
|
+
this._typeName = _typeName;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* returns the value of the FreezedConfig option
|
|
156
|
+
* for a specific type if given typeName
|
|
157
|
+
* or else fallback to the global FreezedConfig value
|
|
158
|
+
*/
|
|
159
|
+
get(option) {
|
|
160
|
+
return getFreezedConfigValue(option, this._config, this._typeName);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.FreezedConfigValue = FreezedConfigValue;
|
|
164
|
+
/**
|
|
165
|
+
* stores an instance of FreezedFactoryBlock using the node names as the key
|
|
166
|
+
* and returns that instance when replacing tokens
|
|
167
|
+
* */
|
|
168
|
+
class FreezedFactoryBlockRepository {
|
|
169
|
+
constructor() {
|
|
170
|
+
this._store = {};
|
|
171
|
+
}
|
|
172
|
+
register(key, value) {
|
|
173
|
+
this._store[key] = value;
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
retrieve(key, appliesOn, name, typeName) {
|
|
177
|
+
return this._store[key]
|
|
178
|
+
.setDecorators(appliesOn, key)
|
|
179
|
+
.setKey(key)
|
|
180
|
+
.setName(name)
|
|
181
|
+
.setNamedConstructor(typeName)
|
|
182
|
+
.init();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.FreezedFactoryBlockRepository = FreezedFactoryBlockRepository;
|
|
186
|
+
/** initializes a FreezedPluginConfig with the defaults values */
|
|
187
|
+
class DefaultFreezedPluginConfig {
|
|
188
|
+
constructor(config = {}) {
|
|
189
|
+
var _a, _b, _c, _d, _e, _f;
|
|
190
|
+
Object.assign(this, {
|
|
191
|
+
customScalars: (_a = config.customScalars) !== null && _a !== void 0 ? _a : {},
|
|
192
|
+
fileName: (_b = config.fileName) !== null && _b !== void 0 ? _b : 'app_models',
|
|
193
|
+
globalFreezedConfig: { ...new DefaultFreezedConfig(), ...((_c = config.globalFreezedConfig) !== null && _c !== void 0 ? _c : {}) },
|
|
194
|
+
typeSpecificFreezedConfig: (_d = config.typeSpecificFreezedConfig) !== null && _d !== void 0 ? _d : {},
|
|
195
|
+
ignoreTypes: (_e = config.ignoreTypes) !== null && _e !== void 0 ? _e : [],
|
|
196
|
+
lowercaseEnums: (_f = config.lowercaseEnums) !== null && _f !== void 0 ? _f : true,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.DefaultFreezedPluginConfig = DefaultFreezedPluginConfig;
|
|
201
|
+
/** initializes a FreezedConfig with the defaults values */
|
|
202
|
+
class DefaultFreezedConfig {
|
|
203
|
+
constructor() {
|
|
204
|
+
Object.assign(this, {
|
|
205
|
+
alwaysUseJsonKeyName: false,
|
|
206
|
+
copyWith: undefined,
|
|
207
|
+
customDecorators: {},
|
|
208
|
+
defaultUnionConstructor: true,
|
|
209
|
+
equal: undefined,
|
|
210
|
+
fromJsonToJson: true,
|
|
211
|
+
immutable: true,
|
|
212
|
+
makeCollectionsUnmodifiable: undefined,
|
|
213
|
+
mergeInputs: [],
|
|
214
|
+
mutableInputs: true,
|
|
215
|
+
privateEmptyConstructor: true,
|
|
216
|
+
unionKey: undefined,
|
|
217
|
+
unionValueCase: undefined,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.DefaultFreezedConfig = DefaultFreezedConfig;
|
package/esm/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { indent } from '@graphql-codegen/visitor-plugin-common';
|
|
2
|
+
import { Kind } from 'graphql';
|
|
3
|
+
import { camelCase, pascalCase } from 'change-case-all';
|
|
4
|
+
import { getCustomDecorators, transformCustomDecorators, FreezedConfigValue, } from '../utils.js';
|
|
5
|
+
import { FreezedFactoryBlock } from './factory-block.js';
|
|
6
|
+
export class FreezedDeclarationBlock {
|
|
7
|
+
constructor(_config, _freezedFactoryBlockRepository, _node) {
|
|
8
|
+
this._config = _config;
|
|
9
|
+
this._freezedFactoryBlockRepository = _freezedFactoryBlockRepository;
|
|
10
|
+
this._node = _node;
|
|
11
|
+
/** document the class */
|
|
12
|
+
this._comment = '';
|
|
13
|
+
/** a list of decorators to copy paste to the generator */
|
|
14
|
+
this._decorators = [];
|
|
15
|
+
/** a list of default constructor and named Constructors used create a Freezed union/sealed class */
|
|
16
|
+
this._factoryBlocks = [];
|
|
17
|
+
this._config = _config;
|
|
18
|
+
this._freezedFactoryBlockRepository = _freezedFactoryBlockRepository;
|
|
19
|
+
this._node = _node;
|
|
20
|
+
this._freezedConfigValue = new FreezedConfigValue(this._config, this._node.name.value);
|
|
21
|
+
}
|
|
22
|
+
init() {
|
|
23
|
+
if (this._node.kind === Kind.ENUM_TYPE_DEFINITION) {
|
|
24
|
+
this.setDecorators().setName().setShape().setBlock();
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
this.setComment().setDecorators().setName().setFactoryBlocks().setShape().setBlock();
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
setComment() {
|
|
31
|
+
var _a;
|
|
32
|
+
const comment = (_a = this._node.description) === null || _a === void 0 ? void 0 : _a.value;
|
|
33
|
+
if (comment && comment !== null && comment !== '') {
|
|
34
|
+
this._comment = `/// ${comment} \n`;
|
|
35
|
+
}
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
getEnumComment(value) {
|
|
39
|
+
var _a;
|
|
40
|
+
const comment = (_a = value.description) === null || _a === void 0 ? void 0 : _a.value;
|
|
41
|
+
if (comment && comment !== null && comment !== '') {
|
|
42
|
+
return `/// ${comment} \n`;
|
|
43
|
+
}
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
setDecorators() {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const name = this._node.name.value;
|
|
49
|
+
// determine if should mark as deprecated
|
|
50
|
+
const isDeprecated = (_b = (_a = this._config.typeSpecificFreezedConfig) === null || _a === void 0 ? void 0 : _a[name]) === null || _b === void 0 ? void 0 : _b.deprecated;
|
|
51
|
+
this._decorators =
|
|
52
|
+
this._node.kind === Kind.ENUM_TYPE_DEFINITION
|
|
53
|
+
? [...transformCustomDecorators(getCustomDecorators(this._config, ['enum'], name), this._node)]
|
|
54
|
+
: [
|
|
55
|
+
this.getFreezedDecorator(),
|
|
56
|
+
...transformCustomDecorators(getCustomDecorators(this._config, ['class'], name), this._node),
|
|
57
|
+
];
|
|
58
|
+
// @deprecated
|
|
59
|
+
// if this._decorators doesn't include an @deprecated decorator but the field is marked as @deprecated...
|
|
60
|
+
if (!this._decorators.includes('@deprecated') && isDeprecated) {
|
|
61
|
+
this._decorators = [...this._decorators, '@deprecated'];
|
|
62
|
+
}
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
getFreezedDecorator() {
|
|
66
|
+
const use_unfreezed = () => {
|
|
67
|
+
if (!this._freezedConfigValue.get('immutable') ||
|
|
68
|
+
(this._node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION && this._freezedConfigValue.get('mutableInputs'))) {
|
|
69
|
+
return '@unfreezed';
|
|
70
|
+
}
|
|
71
|
+
return use_Freezed_or_freezed();
|
|
72
|
+
};
|
|
73
|
+
const use_Freezed_or_freezed = () => {
|
|
74
|
+
// if any of these options is not null, use the @Freezed() decorator passing in that option
|
|
75
|
+
const [isCustomized, copyWith, equal, makeCollectionsUnmodifiable, unionKey, unionValueCase] = isCustomizedFreezed();
|
|
76
|
+
if (isCustomized) {
|
|
77
|
+
return `@Freezed(\n
|
|
78
|
+
${copyWith ? indent(`copyWith: ${copyWith},\n`) : ''}
|
|
79
|
+
${equal ? indent(`equal: ${equal},\n`) : ''}
|
|
80
|
+
${makeCollectionsUnmodifiable ? indent(`makeCollectionsUnmodifiable: ${makeCollectionsUnmodifiable},\n`) : ''}
|
|
81
|
+
${unionKey ? indent(`unionKey: ${unionKey},\n`) : ''}
|
|
82
|
+
${unionValueCase ? indent(`unionValueCase: ${unionValueCase},\n`) : ''}
|
|
83
|
+
)`;
|
|
84
|
+
}
|
|
85
|
+
// else fallback to the normal @freezed decorator
|
|
86
|
+
return '@freezed';
|
|
87
|
+
};
|
|
88
|
+
const isCustomizedFreezed = () => {
|
|
89
|
+
const copyWith = this._freezedConfigValue.get('copyWith');
|
|
90
|
+
const equal = this._freezedConfigValue.get('equal');
|
|
91
|
+
const makeCollectionsUnmodifiable = this._freezedConfigValue.get('makeCollectionsUnmodifiable');
|
|
92
|
+
const unionKey = this._freezedConfigValue.get('unionKey');
|
|
93
|
+
const unionValueCase = this._freezedConfigValue.get('unionValueCase');
|
|
94
|
+
const isCustomized = copyWith || equal || makeCollectionsUnmodifiable || unionKey || unionValueCase;
|
|
95
|
+
return [isCustomized, copyWith, equal, makeCollectionsUnmodifiable, unionKey, unionValueCase];
|
|
96
|
+
};
|
|
97
|
+
// this is the start of the pipeline of decisions to determine which Freezed decorator to use
|
|
98
|
+
return use_unfreezed();
|
|
99
|
+
}
|
|
100
|
+
setName() {
|
|
101
|
+
this._name = pascalCase(this._node.name.value);
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
setFactoryBlocks() {
|
|
105
|
+
var _a, _b, _c, _d;
|
|
106
|
+
if (this._node.kind === Kind.UNION_TYPE_DEFINITION) {
|
|
107
|
+
this._factoryBlocks =
|
|
108
|
+
(_b = (_a = this._node.types) === null || _a === void 0 ? void 0 : _a.map((_type) => new FreezedFactoryBlock(this._config, this._node).init())) !== null && _b !== void 0 ? _b : [];
|
|
109
|
+
}
|
|
110
|
+
else if (this._node.kind !== Kind.ENUM_TYPE_DEFINITION) {
|
|
111
|
+
/*
|
|
112
|
+
for `ObjectTypeDefinitionNode` and `InputObjectTypeDefinitionNode` nodes,
|
|
113
|
+
we use the `ShapeRepository`
|
|
114
|
+
to register the `FreezedFactoryBlock` so that we can use it later
|
|
115
|
+
when we are merging inputs or generating freezed union/sealed classes
|
|
116
|
+
for GraphQL union types
|
|
117
|
+
*/
|
|
118
|
+
this._factoryBlocks =
|
|
119
|
+
(_d = (_c = this._node.fields) === null || _c === void 0 ? void 0 : _c.map((_field) => this._freezedFactoryBlockRepository.register(this._node.name.value, new FreezedFactoryBlock(this._config, this._node).init()))) !== null && _d !== void 0 ? _d : [];
|
|
120
|
+
}
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
setShape() {
|
|
124
|
+
var _a, _b, _c;
|
|
125
|
+
let shape = '';
|
|
126
|
+
// some helper variables
|
|
127
|
+
const name = this._node.name.value;
|
|
128
|
+
let namedConstructor;
|
|
129
|
+
let factoryBlockKey;
|
|
130
|
+
// handle enums differently
|
|
131
|
+
if (this._node.kind === Kind.ENUM_TYPE_DEFINITION) {
|
|
132
|
+
this._shape = (_a = this._node.values) === null || _a === void 0 ? void 0 : _a.map((value) => {
|
|
133
|
+
var _a;
|
|
134
|
+
shape = indent(this.getEnumComment(value));
|
|
135
|
+
if ((_a = this._config.lowercaseEnums) !== null && _a !== void 0 ? _a : true) {
|
|
136
|
+
shape += `@JsonKey(name: ${value.name.value}) ${value.name.value.toLowerCase()}`;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
shape += value.name.value;
|
|
140
|
+
}
|
|
141
|
+
return `${shape}\n`;
|
|
142
|
+
}).join('');
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
// append private empty constructor
|
|
146
|
+
if (this._freezedConfigValue.get('privateEmptyConstructor')) {
|
|
147
|
+
shape += indent(`const ${this._name}._();\n\n`);
|
|
148
|
+
}
|
|
149
|
+
// decide whether to append an empty Union constructor
|
|
150
|
+
if (this._freezedConfigValue.get('defaultUnionConstructor') && this._node.kind === Kind.UNION_TYPE_DEFINITION) {
|
|
151
|
+
shape += indent(`const factory ${this._name}() = _${this._name};\n\n`);
|
|
152
|
+
}
|
|
153
|
+
// append tokens which will be used to retrieve the factory blocks
|
|
154
|
+
// from the FreezedFactoryBlockRepository
|
|
155
|
+
if (this._node.kind === Kind.UNION_TYPE_DEFINITION) {
|
|
156
|
+
(_c = (_b = this._node) === null || _b === void 0 ? void 0 : _b.types) === null || _c === void 0 ? void 0 : _c.forEach(type => {
|
|
157
|
+
namedConstructor = type.name.value;
|
|
158
|
+
factoryBlockKey = namedConstructor;
|
|
159
|
+
shape += `==>factory==>${factoryBlockKey}==>${'union_factory'}==>${name}==>${namedConstructor}\n`;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
factoryBlockKey = name;
|
|
164
|
+
// replace token for the ObjectType & InputType to be replaced with the default Freezed constructor
|
|
165
|
+
shape += `==>factory==>${factoryBlockKey}==>${'class_factory'}==>${name}\n`;
|
|
166
|
+
const mergeInputs = this._freezedConfigValue.get('mergeInputs');
|
|
167
|
+
if (this._node.kind === Kind.OBJECT_TYPE_DEFINITION && mergeInputs) {
|
|
168
|
+
// replace token for the InputTypes(a.k.a namedConstructors) as a union/sealed class
|
|
169
|
+
mergeInputs.forEach(input => {
|
|
170
|
+
namedConstructor = camelCase(input.split('$').join('_'));
|
|
171
|
+
factoryBlockKey = input.replace('$', name);
|
|
172
|
+
shape += `==>factory==>${factoryBlockKey}==>${'union_factory'}==>${name}==>${namedConstructor}\n`;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
this._shape = shape;
|
|
177
|
+
return this;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* returns the string output of the block
|
|
181
|
+
*/
|
|
182
|
+
setBlock() {
|
|
183
|
+
let block = '';
|
|
184
|
+
//append comment
|
|
185
|
+
block += this._comment;
|
|
186
|
+
// append the decorators
|
|
187
|
+
block += this._decorators.join('\n');
|
|
188
|
+
if (this._decorators !== []) {
|
|
189
|
+
block += '\n';
|
|
190
|
+
}
|
|
191
|
+
// handle enums differently
|
|
192
|
+
if (this._node.kind === Kind.ENUM_TYPE_DEFINITION) {
|
|
193
|
+
block += `enum ${this._name}{\n${this._shape}}\n\n`;
|
|
194
|
+
this._block = block;
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
// append start of class definition
|
|
198
|
+
block += `class ${this._name} with _$${this._name} {\n`;
|
|
199
|
+
// append the shape
|
|
200
|
+
block += this._shape;
|
|
201
|
+
// append fromJson
|
|
202
|
+
if (this._freezedConfigValue.get('fromJsonToJson')) {
|
|
203
|
+
block += indent(`factory ${this._name}.fromJson(Map<String, Object?> json) => _${this._name}FromJson(json);\n`);
|
|
204
|
+
}
|
|
205
|
+
//append end of class definition
|
|
206
|
+
block += '}\n\n';
|
|
207
|
+
this._block = block;
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
/** returns the block */
|
|
211
|
+
toString() {
|
|
212
|
+
if (!this._block) {
|
|
213
|
+
throw new Error('setShape must be called before calling toString()');
|
|
214
|
+
}
|
|
215
|
+
return this._block;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { indent } from '@graphql-codegen/visitor-plugin-common';
|
|
2
|
+
import { Kind } from 'graphql';
|
|
3
|
+
import { camelCase, pascalCase } from 'change-case-all';
|
|
4
|
+
import { FreezedParameterBlock } from './parameter-block.js';
|
|
5
|
+
import { FreezedConfigValue, getCustomDecorators, transformCustomDecorators } from '../utils.js';
|
|
6
|
+
export class FreezedFactoryBlock {
|
|
7
|
+
constructor(_config, _node) {
|
|
8
|
+
this._config = _config;
|
|
9
|
+
this._node = _node;
|
|
10
|
+
/** document the constructor */
|
|
11
|
+
this._comment = '';
|
|
12
|
+
/** a list of decorators to copy paste to the generator */
|
|
13
|
+
this._decorators = [];
|
|
14
|
+
/** a list of interfaces to implements */
|
|
15
|
+
// _implements: string[] = [];
|
|
16
|
+
/** a list of class to mixin with */
|
|
17
|
+
// _mixins: string[] = [];
|
|
18
|
+
/** the parameters of this factory constructor */
|
|
19
|
+
// TODO: handle other parameter types like positional parameters later.
|
|
20
|
+
// TODO: sticking to named parameters because GraphQL is a typed language
|
|
21
|
+
this._parameters = [];
|
|
22
|
+
this._config = _config;
|
|
23
|
+
this._node = _node;
|
|
24
|
+
this._freezedConfigValue = new FreezedConfigValue(_config, _node.name.value);
|
|
25
|
+
}
|
|
26
|
+
init() {
|
|
27
|
+
/*
|
|
28
|
+
setDecorators(), setName() and setType() will be called
|
|
29
|
+
when the factory is retrieved from the repository
|
|
30
|
+
*/
|
|
31
|
+
this.setComment().setParameters().setShape().setBlock();
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
setComment() {
|
|
35
|
+
var _a;
|
|
36
|
+
const comment = (_a = this._node.description) === null || _a === void 0 ? void 0 : _a.value;
|
|
37
|
+
if (comment && comment !== null && comment !== '') {
|
|
38
|
+
this._comment = indent(`/// ${comment} \n`);
|
|
39
|
+
}
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
setDecorators(appliesOn, nodeName) {
|
|
43
|
+
this._decorators = [
|
|
44
|
+
...transformCustomDecorators(getCustomDecorators(this._config, appliesOn.split(','), nodeName), this._node),
|
|
45
|
+
];
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
setKey(key) {
|
|
49
|
+
this._key = pascalCase(key);
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
setName(name) {
|
|
53
|
+
this._name = pascalCase(name);
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
setNamedConstructor(namedConstructor) {
|
|
57
|
+
if (namedConstructor) {
|
|
58
|
+
this._namedConstructor = camelCase(namedConstructor);
|
|
59
|
+
}
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
setParameters() {
|
|
63
|
+
var _a, _b, _c;
|
|
64
|
+
const appliesOn = this._namedConstructor
|
|
65
|
+
? ['union_factory_parameter']
|
|
66
|
+
: ['class_factory_parameter'];
|
|
67
|
+
if (this._node.kind !== Kind.UNION_TYPE_DEFINITION && this._node.kind !== Kind.ENUM_TYPE_DEFINITION) {
|
|
68
|
+
this._parameters =
|
|
69
|
+
(_c = (_b = (_a = this._node) === null || _a === void 0 ? void 0 : _a.fields) === null || _b === void 0 ? void 0 : _b.map((field) => new FreezedParameterBlock(this._config, appliesOn, this._node, field).init())) !== null && _c !== void 0 ? _c : [];
|
|
70
|
+
}
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
setShape() {
|
|
74
|
+
this._shape = this._parameters.map(p => p.toString()).join('');
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
setBlock() {
|
|
78
|
+
let block = '';
|
|
79
|
+
//append comment
|
|
80
|
+
block += this._comment;
|
|
81
|
+
// append the decorators
|
|
82
|
+
block += this._decorators.map(d => indent(`${d}\n`)).join('');
|
|
83
|
+
block += indent('');
|
|
84
|
+
// decide if to use const or not
|
|
85
|
+
if (this._freezedConfigValue.get('immutable')) {
|
|
86
|
+
block += 'const ';
|
|
87
|
+
}
|
|
88
|
+
// append the factory keyword and the name
|
|
89
|
+
block += `factory ${this._name}`;
|
|
90
|
+
// append .namedConstructor is not null
|
|
91
|
+
if (this._namedConstructor && this._namedConstructor !== '') {
|
|
92
|
+
block += `.${this._namedConstructor}`;
|
|
93
|
+
}
|
|
94
|
+
// append the parenthesis for the constructor and braces for the named parameters
|
|
95
|
+
block += '({\n';
|
|
96
|
+
//append the shape
|
|
97
|
+
block += this._shape;
|
|
98
|
+
// close the constructor and assign the key
|
|
99
|
+
block += indent(`}) = `);
|
|
100
|
+
// but first decide whether prefix the key with an underscore
|
|
101
|
+
if (!this._namedConstructor) {
|
|
102
|
+
block += '_';
|
|
103
|
+
}
|
|
104
|
+
// finally, append the key
|
|
105
|
+
block += `${this._key};\n`;
|
|
106
|
+
// store it in the shape
|
|
107
|
+
this._block = block;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/** returns the block */
|
|
111
|
+
toString() {
|
|
112
|
+
if (!this._block) {
|
|
113
|
+
throw new Error('FreezedFactoryBlock: setShape must be called before calling toString()');
|
|
114
|
+
}
|
|
115
|
+
return this._block;
|
|
116
|
+
}
|
|
117
|
+
}
|