@strapi/typescript-utils 4.3.3 → 4.3.6
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/lib/__tests__/generators/schemas/attributes.test.js +2 -2
- package/lib/__tests__/generators/schemas/global.test.js +1 -1
- package/lib/admin/create-tsconfig-file.js +1 -1
- package/lib/compilers/watch.js +4 -4
- package/lib/generators/schemas/attributes.js +26 -149
- package/lib/generators/schemas/global.js +21 -19
- package/lib/generators/schemas/imports.js +1 -1
- package/lib/generators/schemas/index.js +63 -63
- package/lib/generators/schemas/mappers.js +131 -0
- package/lib/generators/schemas/schema.js +32 -32
- package/lib/generators/schemas/utils.js +18 -18
- package/lib/utils/report-diagnostics.js +1 -1
- package/lib/utils/resolve-config-options.js +1 -1
- package/lib/utils/resolve-outdir.js +1 -0
- package/package.json +2 -2
|
@@ -23,11 +23,11 @@ describe('Attributes', () => {
|
|
|
23
23
|
const schema = { uid: 'api::foo.foo' };
|
|
24
24
|
const attributeName = 'foo';
|
|
25
25
|
|
|
26
|
-
const toPropertySignature = attribute => {
|
|
26
|
+
const toPropertySignature = (attribute) => {
|
|
27
27
|
return attributeToPropertySignature(schema, attributeName, attribute);
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const defaultAssertion = node => {
|
|
30
|
+
const defaultAssertion = (node) => {
|
|
31
31
|
expect(node.kind).toBe(ts.SyntaxKind.PropertySignature);
|
|
32
32
|
expect(node.name.escapedText).toBe(attributeName);
|
|
33
33
|
expect(node.type.kind).toBe(ts.SyntaxKind.IntersectionType);
|
|
@@ -17,7 +17,7 @@ describe('Global', () => {
|
|
|
17
17
|
jest.resetAllMocks();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
const assertGlobalNodeStructure = node => {
|
|
20
|
+
const assertGlobalNodeStructure = (node) => {
|
|
21
21
|
// "declare global"
|
|
22
22
|
expect(node.kind).toBe(ts.SyntaxKind.ModuleDeclaration);
|
|
23
23
|
expect(node.modifiers).toHaveLength(1);
|
package/lib/compilers/watch.js
CHANGED
|
@@ -10,7 +10,7 @@ const resolveConfigOptions = require('../utils/resolve-config-options');
|
|
|
10
10
|
* Prints a diagnostic every time the watch status changes.
|
|
11
11
|
* This is mainly for messages like "Starting compilation" or "Compilation completed".
|
|
12
12
|
*/
|
|
13
|
-
const reportWatchStatusChanged = diagnostic => {
|
|
13
|
+
const reportWatchStatusChanged = (diagnostic) => {
|
|
14
14
|
console.info(ts.formatDiagnostic(diagnostic, formatHost));
|
|
15
15
|
};
|
|
16
16
|
|
|
@@ -18,9 +18,9 @@ module.exports = {
|
|
|
18
18
|
run(configPath) {
|
|
19
19
|
const createProgram = ts.createSemanticDiagnosticsBuilderProgram;
|
|
20
20
|
|
|
21
|
-
const { fileNames, options, projectReferences, watchOptions } =
|
|
22
|
-
configPath
|
|
23
|
-
|
|
21
|
+
const { fileNames, options, projectReferences, watchOptions } =
|
|
22
|
+
resolveConfigOptions(configPath);
|
|
23
|
+
|
|
24
24
|
const host = ts.createWatchCompilerHost(
|
|
25
25
|
fileNames,
|
|
26
26
|
options,
|
|
@@ -1,38 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ts = require('typescript');
|
|
4
3
|
const { factory } = require('typescript');
|
|
5
4
|
const _ = require('lodash/fp');
|
|
6
5
|
|
|
7
6
|
const { addImport } = require('./imports');
|
|
8
7
|
const { getTypeNode, toTypeLiteral } = require('./utils');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Generate a property signature node for a given attribute
|
|
12
|
-
*
|
|
13
|
-
* @param {object} schema
|
|
14
|
-
* @param {string} attributeName
|
|
15
|
-
* @param {object} attribute
|
|
16
|
-
* @returns {object}
|
|
17
|
-
*/
|
|
18
|
-
const attributeToPropertySignature = (schema, attributeName, attribute) => {
|
|
19
|
-
const baseType = getAttributeType(attributeName, attribute, schema.uid);
|
|
20
|
-
|
|
21
|
-
if (baseType === null) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const modifiers = getAttributeModifiers(attribute);
|
|
26
|
-
|
|
27
|
-
const nodes = [baseType, ...modifiers];
|
|
28
|
-
|
|
29
|
-
return factory.createPropertySignature(
|
|
30
|
-
undefined,
|
|
31
|
-
factory.createIdentifier(attributeName),
|
|
32
|
-
undefined,
|
|
33
|
-
factory.createIntersectionTypeNode(nodes)
|
|
34
|
-
);
|
|
35
|
-
};
|
|
8
|
+
const mappers = require('./mappers');
|
|
36
9
|
|
|
37
10
|
/**
|
|
38
11
|
* Create the base type node for a given attribute
|
|
@@ -64,7 +37,7 @@ const getAttributeType = (attributeName, attribute, uid) => {
|
|
|
64
37
|
* @param {object} attribute
|
|
65
38
|
* @returns {object[]}
|
|
66
39
|
*/
|
|
67
|
-
const getAttributeModifiers = attribute => {
|
|
40
|
+
const getAttributeModifiers = (attribute) => {
|
|
68
41
|
const modifiers = [];
|
|
69
42
|
|
|
70
43
|
// Required
|
|
@@ -151,127 +124,31 @@ const getAttributeModifiers = attribute => {
|
|
|
151
124
|
return modifiers;
|
|
152
125
|
};
|
|
153
126
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
},
|
|
173
|
-
time() {
|
|
174
|
-
return ['TimeAttribute'];
|
|
175
|
-
},
|
|
176
|
-
datetime() {
|
|
177
|
-
return ['DateTimeAttribute'];
|
|
178
|
-
},
|
|
179
|
-
timestamp() {
|
|
180
|
-
return ['TimestampAttribute'];
|
|
181
|
-
},
|
|
182
|
-
integer() {
|
|
183
|
-
return ['IntegerAttribute'];
|
|
184
|
-
},
|
|
185
|
-
biginteger() {
|
|
186
|
-
return ['BigIntegerAttribute'];
|
|
187
|
-
},
|
|
188
|
-
float() {
|
|
189
|
-
return ['FloatAttribute'];
|
|
190
|
-
},
|
|
191
|
-
decimal() {
|
|
192
|
-
return ['DecimalAttribute'];
|
|
193
|
-
},
|
|
194
|
-
uid({ attribute, uid }) {
|
|
195
|
-
const { targetField, options } = attribute;
|
|
196
|
-
|
|
197
|
-
// If there are no params to compute, then return the attribute type alone
|
|
198
|
-
if (targetField === undefined && options === undefined) {
|
|
199
|
-
return ['UIDAttribute'];
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const params = [];
|
|
203
|
-
|
|
204
|
-
// If the targetField property is defined, then reference it,
|
|
205
|
-
// otherwise, put `undefined` keyword type nodes as placeholders
|
|
206
|
-
const targetFieldParams = _.isUndefined(targetField)
|
|
207
|
-
? [
|
|
208
|
-
factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
209
|
-
factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
210
|
-
]
|
|
211
|
-
: [factory.createStringLiteral(uid), factory.createStringLiteral(targetField)];
|
|
212
|
-
|
|
213
|
-
params.push(...targetFieldParams);
|
|
214
|
-
|
|
215
|
-
// If the options property is defined, transform it to
|
|
216
|
-
// a type literral node and add it to the params list
|
|
217
|
-
if (_.isObject(options)) {
|
|
218
|
-
params.push(toTypeLiteral(options));
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return ['UIDAttribute', params];
|
|
222
|
-
},
|
|
223
|
-
enumeration({ attribute }) {
|
|
224
|
-
const { enum: enumValues } = attribute;
|
|
225
|
-
|
|
226
|
-
return ['EnumerationAttribute', [toTypeLiteral(enumValues)]];
|
|
227
|
-
},
|
|
228
|
-
boolean() {
|
|
229
|
-
return ['BooleanAttribute'];
|
|
230
|
-
},
|
|
231
|
-
json() {
|
|
232
|
-
return ['JSONAttribute'];
|
|
233
|
-
},
|
|
234
|
-
media() {
|
|
235
|
-
return ['MediaAttribute'];
|
|
236
|
-
},
|
|
237
|
-
relation({ uid, attribute }) {
|
|
238
|
-
const { relation, target } = attribute;
|
|
239
|
-
|
|
240
|
-
const isMorphRelation = relation.toLowerCase().includes('morph');
|
|
241
|
-
|
|
242
|
-
if (isMorphRelation) {
|
|
243
|
-
return [
|
|
244
|
-
'RelationAttribute',
|
|
245
|
-
[factory.createStringLiteral(uid, true), factory.createStringLiteral(relation, true)],
|
|
246
|
-
];
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
return [
|
|
250
|
-
'RelationAttribute',
|
|
251
|
-
[
|
|
252
|
-
factory.createStringLiteral(uid, true),
|
|
253
|
-
factory.createStringLiteral(relation, true),
|
|
254
|
-
factory.createStringLiteral(target, true),
|
|
255
|
-
],
|
|
256
|
-
];
|
|
257
|
-
},
|
|
258
|
-
component({ attribute }) {
|
|
259
|
-
const target = attribute.component;
|
|
260
|
-
const params = [factory.createStringLiteral(target, true)];
|
|
261
|
-
|
|
262
|
-
if (attribute.repeatable) {
|
|
263
|
-
params.push(factory.createTrue());
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return ['ComponentAttribute', params];
|
|
267
|
-
},
|
|
268
|
-
dynamiczone({ attribute }) {
|
|
269
|
-
const componentsParam = factory.createTupleTypeNode(
|
|
270
|
-
attribute.components.map(component => factory.createStringLiteral(component))
|
|
271
|
-
);
|
|
127
|
+
/**
|
|
128
|
+
* Generate a property signature node for a given attribute
|
|
129
|
+
*
|
|
130
|
+
* @param {object} schema
|
|
131
|
+
* @param {string} attributeName
|
|
132
|
+
* @param {object} attribute
|
|
133
|
+
* @returns {object}
|
|
134
|
+
*/
|
|
135
|
+
const attributeToPropertySignature = (schema, attributeName, attribute) => {
|
|
136
|
+
const baseType = getAttributeType(attributeName, attribute, schema.uid);
|
|
137
|
+
|
|
138
|
+
if (baseType === null) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const modifiers = getAttributeModifiers(attribute);
|
|
143
|
+
|
|
144
|
+
const nodes = [baseType, ...modifiers];
|
|
272
145
|
|
|
273
|
-
|
|
274
|
-
|
|
146
|
+
return factory.createPropertySignature(
|
|
147
|
+
undefined,
|
|
148
|
+
factory.createIdentifier(attributeName),
|
|
149
|
+
undefined,
|
|
150
|
+
factory.createIntersectionTypeNode(nodes)
|
|
151
|
+
);
|
|
275
152
|
};
|
|
276
153
|
|
|
277
154
|
module.exports = attributeToPropertySignature;
|
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
/* eslint-disable no-bitwise */
|
|
4
|
+
|
|
3
5
|
const ts = require('typescript');
|
|
4
6
|
const { factory } = require('typescript');
|
|
5
7
|
|
|
6
8
|
const { getSchemaInterfaceName } = require('./utils');
|
|
7
9
|
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param {object} schemaDefinition
|
|
13
|
+
* @param {ts.InterfaceDeclaration} schemaDefinition.definition
|
|
14
|
+
* @param {object} schemaDefinition.schema
|
|
15
|
+
*/
|
|
16
|
+
const schemaDefinitionToPropertySignature = ({ schema }) => {
|
|
17
|
+
const { uid } = schema;
|
|
18
|
+
|
|
19
|
+
const interfaceTypeName = getSchemaInterfaceName(uid);
|
|
20
|
+
|
|
21
|
+
return factory.createPropertySignature(
|
|
22
|
+
undefined,
|
|
23
|
+
factory.createStringLiteral(uid, true),
|
|
24
|
+
undefined,
|
|
25
|
+
factory.createTypeReferenceNode(factory.createIdentifier(interfaceTypeName))
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
8
29
|
/**
|
|
9
30
|
* Generate the global module augmentation block
|
|
10
31
|
*
|
|
@@ -46,23 +67,4 @@ const generateGlobalDefinition = (schemasDefinitions = []) => {
|
|
|
46
67
|
);
|
|
47
68
|
};
|
|
48
69
|
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* @param {object} schemaDefinition
|
|
52
|
-
* @param {ts.InterfaceDeclaration} schemaDefinition.definition
|
|
53
|
-
* @param {object} schemaDefinition.schema
|
|
54
|
-
*/
|
|
55
|
-
const schemaDefinitionToPropertySignature = ({ schema }) => {
|
|
56
|
-
const { uid } = schema;
|
|
57
|
-
|
|
58
|
-
const interfaceTypeName = getSchemaInterfaceName(uid);
|
|
59
|
-
|
|
60
|
-
return factory.createPropertySignature(
|
|
61
|
-
undefined,
|
|
62
|
-
factory.createStringLiteral(uid, true),
|
|
63
|
-
undefined,
|
|
64
|
-
factory.createTypeReferenceNode(factory.createIdentifier(interfaceTypeName))
|
|
65
|
-
);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
70
|
module.exports = { generateGlobalDefinition };
|
|
@@ -23,67 +23,7 @@ const {
|
|
|
23
23
|
|
|
24
24
|
const DEFAULT_OUT_FILENAME = 'schemas.d.ts';
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
* Generate type definitions for Strapi schemas
|
|
28
|
-
*
|
|
29
|
-
* @param {object} options
|
|
30
|
-
* @param {Strapi} options.strapi
|
|
31
|
-
* @param {{ distDir: string; appDir: string; }} options.dirs
|
|
32
|
-
* @param {string} [options.outDir]
|
|
33
|
-
* @param {string} [options.file]
|
|
34
|
-
* @param {boolean} [options.verbose]
|
|
35
|
-
*/
|
|
36
|
-
const generateSchemasDefinitions = async (options = {}) => {
|
|
37
|
-
const {
|
|
38
|
-
strapi,
|
|
39
|
-
outDir = process.cwd(),
|
|
40
|
-
file = DEFAULT_OUT_FILENAME,
|
|
41
|
-
verbose = false,
|
|
42
|
-
silent = false,
|
|
43
|
-
} = options;
|
|
44
|
-
|
|
45
|
-
const schemas = getAllStrapiSchemas(strapi);
|
|
46
|
-
|
|
47
|
-
const schemasDefinitions = Object.values(schemas).map(schema => ({
|
|
48
|
-
schema,
|
|
49
|
-
definition: generateSchemaDefinition(schema),
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
const formattedSchemasDefinitions = schemasDefinitions.reduce((acc, def) => {
|
|
53
|
-
acc.push(
|
|
54
|
-
// Definition
|
|
55
|
-
def.definition,
|
|
56
|
-
|
|
57
|
-
// Add a newline between each interface declaration
|
|
58
|
-
factory.createIdentifier('\n')
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return acc;
|
|
62
|
-
}, []);
|
|
63
|
-
|
|
64
|
-
const allDefinitions = [
|
|
65
|
-
// Imports
|
|
66
|
-
generateImportDefinition(),
|
|
67
|
-
|
|
68
|
-
// Add a newline after the import statement
|
|
69
|
-
factory.createIdentifier('\n'),
|
|
70
|
-
|
|
71
|
-
// Schemas
|
|
72
|
-
...formattedSchemasDefinitions,
|
|
73
|
-
|
|
74
|
-
// Global
|
|
75
|
-
generateGlobalDefinition(schemasDefinitions),
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
const output = emitDefinitions(allDefinitions);
|
|
79
|
-
const formattedOutput = await format(output);
|
|
80
|
-
|
|
81
|
-
const definitionFilepath = await saveDefinitionToFileSystem(outDir, file, formattedOutput);
|
|
82
|
-
|
|
83
|
-
logDebugInformation(schemasDefinitions, { filepath: definitionFilepath, verbose, silent });
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const emitDefinitions = definitions => {
|
|
26
|
+
const emitDefinitions = (definitions) => {
|
|
87
27
|
const nodeArray = factory.createNodeArray(definitions);
|
|
88
28
|
|
|
89
29
|
const sourceFile = ts.createSourceFile(
|
|
@@ -114,7 +54,7 @@ const saveDefinitionToFileSystem = async (dir, file, content) => {
|
|
|
114
54
|
* @param {string} content
|
|
115
55
|
* @returns {Promise<string>}
|
|
116
56
|
*/
|
|
117
|
-
const format = async content => {
|
|
57
|
+
const format = async (content) => {
|
|
118
58
|
const configFile = await prettier.resolveConfigFile();
|
|
119
59
|
const config = configFile
|
|
120
60
|
? await prettier.resolveConfig(configFile)
|
|
@@ -144,7 +84,7 @@ const logDebugInformation = (definitions, options = {}) => {
|
|
|
144
84
|
colAligns: ['center', 'left', 'left', 'center'],
|
|
145
85
|
});
|
|
146
86
|
|
|
147
|
-
const sortedDefinitions = definitions.map(def => ({
|
|
87
|
+
const sortedDefinitions = definitions.map((def) => ({
|
|
148
88
|
...def,
|
|
149
89
|
attributesCount: getDefinitionAttributesCount(def.definition),
|
|
150
90
|
}));
|
|
@@ -182,4 +122,64 @@ const logDebugInformation = (definitions, options = {}) => {
|
|
|
182
122
|
}
|
|
183
123
|
};
|
|
184
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Generate type definitions for Strapi schemas
|
|
127
|
+
*
|
|
128
|
+
* @param {object} options
|
|
129
|
+
* @param {Strapi} options.strapi
|
|
130
|
+
* @param {{ distDir: string; appDir: string; }} options.dirs
|
|
131
|
+
* @param {string} [options.outDir]
|
|
132
|
+
* @param {string} [options.file]
|
|
133
|
+
* @param {boolean} [options.verbose]
|
|
134
|
+
*/
|
|
135
|
+
const generateSchemasDefinitions = async (options = {}) => {
|
|
136
|
+
const {
|
|
137
|
+
strapi,
|
|
138
|
+
outDir = process.cwd(),
|
|
139
|
+
file = DEFAULT_OUT_FILENAME,
|
|
140
|
+
verbose = false,
|
|
141
|
+
silent = false,
|
|
142
|
+
} = options;
|
|
143
|
+
|
|
144
|
+
const schemas = getAllStrapiSchemas(strapi);
|
|
145
|
+
|
|
146
|
+
const schemasDefinitions = Object.values(schemas).map((schema) => ({
|
|
147
|
+
schema,
|
|
148
|
+
definition: generateSchemaDefinition(schema),
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
const formattedSchemasDefinitions = schemasDefinitions.reduce((acc, def) => {
|
|
152
|
+
acc.push(
|
|
153
|
+
// Definition
|
|
154
|
+
def.definition,
|
|
155
|
+
|
|
156
|
+
// Add a newline between each interface declaration
|
|
157
|
+
factory.createIdentifier('\n')
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return acc;
|
|
161
|
+
}, []);
|
|
162
|
+
|
|
163
|
+
const allDefinitions = [
|
|
164
|
+
// Imports
|
|
165
|
+
generateImportDefinition(),
|
|
166
|
+
|
|
167
|
+
// Add a newline after the import statement
|
|
168
|
+
factory.createIdentifier('\n'),
|
|
169
|
+
|
|
170
|
+
// Schemas
|
|
171
|
+
...formattedSchemasDefinitions,
|
|
172
|
+
|
|
173
|
+
// Global
|
|
174
|
+
generateGlobalDefinition(schemasDefinitions),
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
const output = emitDefinitions(allDefinitions);
|
|
178
|
+
const formattedOutput = await format(output);
|
|
179
|
+
|
|
180
|
+
const definitionFilepath = await saveDefinitionToFileSystem(outDir, file, formattedOutput);
|
|
181
|
+
|
|
182
|
+
logDebugInformation(schemasDefinitions, { filepath: definitionFilepath, verbose, silent });
|
|
183
|
+
};
|
|
184
|
+
|
|
185
185
|
module.exports = generateSchemasDefinitions;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ts = require('typescript');
|
|
4
|
+
const _ = require('lodash/fp');
|
|
5
|
+
|
|
6
|
+
const { toTypeLiteral } = require('./utils');
|
|
7
|
+
|
|
8
|
+
const { factory } = ts;
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
string() {
|
|
12
|
+
return ['StringAttribute'];
|
|
13
|
+
},
|
|
14
|
+
text() {
|
|
15
|
+
return ['TextAttribute'];
|
|
16
|
+
},
|
|
17
|
+
richtext() {
|
|
18
|
+
return ['RichTextAttribute'];
|
|
19
|
+
},
|
|
20
|
+
password() {
|
|
21
|
+
return ['PasswordAttribute'];
|
|
22
|
+
},
|
|
23
|
+
email() {
|
|
24
|
+
return ['EmailAttribute'];
|
|
25
|
+
},
|
|
26
|
+
date() {
|
|
27
|
+
return ['DateAttribute'];
|
|
28
|
+
},
|
|
29
|
+
time() {
|
|
30
|
+
return ['TimeAttribute'];
|
|
31
|
+
},
|
|
32
|
+
datetime() {
|
|
33
|
+
return ['DateTimeAttribute'];
|
|
34
|
+
},
|
|
35
|
+
timestamp() {
|
|
36
|
+
return ['TimestampAttribute'];
|
|
37
|
+
},
|
|
38
|
+
integer() {
|
|
39
|
+
return ['IntegerAttribute'];
|
|
40
|
+
},
|
|
41
|
+
biginteger() {
|
|
42
|
+
return ['BigIntegerAttribute'];
|
|
43
|
+
},
|
|
44
|
+
float() {
|
|
45
|
+
return ['FloatAttribute'];
|
|
46
|
+
},
|
|
47
|
+
decimal() {
|
|
48
|
+
return ['DecimalAttribute'];
|
|
49
|
+
},
|
|
50
|
+
uid({ attribute, uid }) {
|
|
51
|
+
const { targetField, options } = attribute;
|
|
52
|
+
|
|
53
|
+
// If there are no params to compute, then return the attribute type alone
|
|
54
|
+
if (targetField === undefined && options === undefined) {
|
|
55
|
+
return ['UIDAttribute'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const params = [];
|
|
59
|
+
|
|
60
|
+
// If the targetField property is defined, then reference it,
|
|
61
|
+
// otherwise, put `undefined` keyword type nodes as placeholders
|
|
62
|
+
const targetFieldParams = _.isUndefined(targetField)
|
|
63
|
+
? [
|
|
64
|
+
factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
65
|
+
factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
66
|
+
]
|
|
67
|
+
: [factory.createStringLiteral(uid), factory.createStringLiteral(targetField)];
|
|
68
|
+
|
|
69
|
+
params.push(...targetFieldParams);
|
|
70
|
+
|
|
71
|
+
// If the options property is defined, transform it to
|
|
72
|
+
// a type literral node and add it to the params list
|
|
73
|
+
if (_.isObject(options)) {
|
|
74
|
+
params.push(toTypeLiteral(options));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return ['UIDAttribute', params];
|
|
78
|
+
},
|
|
79
|
+
enumeration({ attribute }) {
|
|
80
|
+
const { enum: enumValues } = attribute;
|
|
81
|
+
|
|
82
|
+
return ['EnumerationAttribute', [toTypeLiteral(enumValues)]];
|
|
83
|
+
},
|
|
84
|
+
boolean() {
|
|
85
|
+
return ['BooleanAttribute'];
|
|
86
|
+
},
|
|
87
|
+
json() {
|
|
88
|
+
return ['JSONAttribute'];
|
|
89
|
+
},
|
|
90
|
+
media() {
|
|
91
|
+
return ['MediaAttribute'];
|
|
92
|
+
},
|
|
93
|
+
relation({ uid, attribute }) {
|
|
94
|
+
const { relation, target } = attribute;
|
|
95
|
+
|
|
96
|
+
const isMorphRelation = relation.toLowerCase().includes('morph');
|
|
97
|
+
|
|
98
|
+
if (isMorphRelation) {
|
|
99
|
+
return [
|
|
100
|
+
'RelationAttribute',
|
|
101
|
+
[factory.createStringLiteral(uid, true), factory.createStringLiteral(relation, true)],
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return [
|
|
106
|
+
'RelationAttribute',
|
|
107
|
+
[
|
|
108
|
+
factory.createStringLiteral(uid, true),
|
|
109
|
+
factory.createStringLiteral(relation, true),
|
|
110
|
+
factory.createStringLiteral(target, true),
|
|
111
|
+
],
|
|
112
|
+
];
|
|
113
|
+
},
|
|
114
|
+
component({ attribute }) {
|
|
115
|
+
const target = attribute.component;
|
|
116
|
+
const params = [factory.createStringLiteral(target, true)];
|
|
117
|
+
|
|
118
|
+
if (attribute.repeatable) {
|
|
119
|
+
params.push(factory.createTrue());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return ['ComponentAttribute', params];
|
|
123
|
+
},
|
|
124
|
+
dynamiczone({ attribute }) {
|
|
125
|
+
const componentsParam = factory.createTupleTypeNode(
|
|
126
|
+
attribute.components.map((component) => factory.createStringLiteral(component))
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return ['DynamicZoneAttribute', [componentsParam]];
|
|
130
|
+
},
|
|
131
|
+
};
|
|
@@ -8,13 +8,43 @@ const { getSchemaExtendsTypeName, getSchemaInterfaceName, toTypeLiteral } = requ
|
|
|
8
8
|
const attributeToPropertySignature = require('./attributes');
|
|
9
9
|
const { addImport } = require('./imports');
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Generate a property signature for the schema's `attributes` field
|
|
13
|
+
*
|
|
14
|
+
* @param {object} schema
|
|
15
|
+
* @returns {ts.PropertySignature}
|
|
16
|
+
*/
|
|
17
|
+
const generateAttributePropertySignature = (schema) => {
|
|
18
|
+
const { attributes } = schema;
|
|
19
|
+
|
|
20
|
+
const properties = Object.entries(attributes).map(([attributeName, attribute]) => {
|
|
21
|
+
return attributeToPropertySignature(schema, attributeName, attribute);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return factory.createPropertySignature(
|
|
25
|
+
undefined,
|
|
26
|
+
factory.createIdentifier('attributes'),
|
|
27
|
+
undefined,
|
|
28
|
+
factory.createTypeLiteralNode(properties)
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const generatePropertyLiteralDefinitionFactory = (schema) => (key) => {
|
|
33
|
+
return factory.createPropertySignature(
|
|
34
|
+
undefined,
|
|
35
|
+
factory.createIdentifier(key),
|
|
36
|
+
undefined,
|
|
37
|
+
toTypeLiteral(schema[key])
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
11
41
|
/**
|
|
12
42
|
* Generate an interface declaration for a given schema
|
|
13
43
|
*
|
|
14
44
|
* @param {object} schema
|
|
15
45
|
* @returns {ts.InterfaceDeclaration}
|
|
16
46
|
*/
|
|
17
|
-
const generateSchemaDefinition = schema => {
|
|
47
|
+
const generateSchemaDefinition = (schema) => {
|
|
18
48
|
const { uid } = schema;
|
|
19
49
|
|
|
20
50
|
// Resolve the different interface names needed to declare the schema's interface
|
|
@@ -27,7 +57,7 @@ const generateSchemaDefinition = schema => {
|
|
|
27
57
|
// Properties whose values can be mapped to a literal type expression
|
|
28
58
|
const literalPropertiesDefinitions = ['info', 'options', 'pluginOptions']
|
|
29
59
|
// Ignore non-existent or empty declarations
|
|
30
|
-
.filter(key => !isEmpty(schema[key]))
|
|
60
|
+
.filter((key) => !isEmpty(schema[key]))
|
|
31
61
|
// Generate literal definition for each property
|
|
32
62
|
.map(generatePropertyLiteralDefinitionFactory(schema));
|
|
33
63
|
|
|
@@ -54,34 +84,4 @@ const generateSchemaDefinition = schema => {
|
|
|
54
84
|
return schemaType;
|
|
55
85
|
};
|
|
56
86
|
|
|
57
|
-
/**
|
|
58
|
-
* Generate a property signature for the schema's `attributes` field
|
|
59
|
-
*
|
|
60
|
-
* @param {object} schema
|
|
61
|
-
* @returns {ts.PropertySignature}
|
|
62
|
-
*/
|
|
63
|
-
const generateAttributePropertySignature = schema => {
|
|
64
|
-
const { attributes } = schema;
|
|
65
|
-
|
|
66
|
-
const properties = Object.entries(attributes).map(([attributeName, attribute]) => {
|
|
67
|
-
return attributeToPropertySignature(schema, attributeName, attribute);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return factory.createPropertySignature(
|
|
71
|
-
undefined,
|
|
72
|
-
factory.createIdentifier('attributes'),
|
|
73
|
-
undefined,
|
|
74
|
-
factory.createTypeLiteralNode(properties)
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const generatePropertyLiteralDefinitionFactory = schema => key => {
|
|
79
|
-
return factory.createPropertySignature(
|
|
80
|
-
undefined,
|
|
81
|
-
factory.createIdentifier(key),
|
|
82
|
-
undefined,
|
|
83
|
-
toTypeLiteral(schema[key])
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
87
|
module.exports = { generateSchemaDefinition };
|
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
* @param {Strapi} strapi
|
|
24
24
|
* @returns {object}
|
|
25
25
|
*/
|
|
26
|
-
const getAllStrapiSchemas = strapi => ({ ...strapi.contentTypes, ...strapi.components });
|
|
26
|
+
const getAllStrapiSchemas = (strapi) => ({ ...strapi.contentTypes, ...strapi.components });
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Extract a valid interface name from a schema uid
|
|
@@ -33,19 +33,7 @@ const getAllStrapiSchemas = strapi => ({ ...strapi.contentTypes, ...strapi.compo
|
|
|
33
33
|
*/
|
|
34
34
|
const getSchemaInterfaceName = pipe(replace(/(:.)/, ' '), camelCase, upperFirst);
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
* Get the parent type name to extend based on the schema's nature
|
|
38
|
-
*
|
|
39
|
-
* @param {object} schema
|
|
40
|
-
* @returns {string}
|
|
41
|
-
*/
|
|
42
|
-
const getSchemaExtendsTypeName = schema => {
|
|
43
|
-
const base = getSchemaModelType(schema);
|
|
44
|
-
|
|
45
|
-
return upperFirst(base) + 'Schema';
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const getSchemaModelType = schema => {
|
|
36
|
+
const getSchemaModelType = (schema) => {
|
|
49
37
|
const { modelType, kind } = schema;
|
|
50
38
|
|
|
51
39
|
// Components
|
|
@@ -54,13 +42,25 @@ const getSchemaModelType = schema => {
|
|
|
54
42
|
}
|
|
55
43
|
|
|
56
44
|
// Content-Types
|
|
57
|
-
|
|
45
|
+
if (modelType === 'contentType') {
|
|
58
46
|
return kind;
|
|
59
47
|
}
|
|
60
48
|
|
|
61
49
|
return null;
|
|
62
50
|
};
|
|
63
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Get the parent type name to extend based on the schema's nature
|
|
54
|
+
*
|
|
55
|
+
* @param {object} schema
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*/
|
|
58
|
+
const getSchemaExtendsTypeName = (schema) => {
|
|
59
|
+
const base = getSchemaModelType(schema);
|
|
60
|
+
|
|
61
|
+
return `${upperFirst(base)}Schema`;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
64
|
/**
|
|
65
65
|
* Get a type node based on a type and its params
|
|
66
66
|
*
|
|
@@ -77,7 +77,7 @@ const getTypeNode = (typeName, params = []) => {
|
|
|
77
77
|
* @param data
|
|
78
78
|
* @returns {ts.TypeNode}
|
|
79
79
|
*/
|
|
80
|
-
const toTypeLiteral = data => {
|
|
80
|
+
const toTypeLiteral = (data) => {
|
|
81
81
|
if (isUndefined(data)) {
|
|
82
82
|
return factory.createLiteralTypeNode(ts.SyntaxKind.UndefinedKeyword);
|
|
83
83
|
}
|
|
@@ -99,7 +99,7 @@ const toTypeLiteral = data => {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
if (isArray(data)) {
|
|
102
|
-
return factory.createTupleTypeNode(data.map(item => toTypeLiteral(item)));
|
|
102
|
+
return factory.createTupleTypeNode(data.map((item) => toTypeLiteral(item)));
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
if (isDate(data)) {
|
|
@@ -139,7 +139,7 @@ const toTypeLiteral = data => {
|
|
|
139
139
|
* @param {ts.TypeNode} definition
|
|
140
140
|
* @returns {number | null}
|
|
141
141
|
*/
|
|
142
|
-
const getDefinitionAttributesCount = definition => {
|
|
142
|
+
const getDefinitionAttributesCount = (definition) => {
|
|
143
143
|
const attributesNode = definition.members.find(propEq('name.escapedText', 'attributes'));
|
|
144
144
|
|
|
145
145
|
if (!attributesNode) {
|
|
@@ -8,7 +8,7 @@ const formatHost = require('./format-host');
|
|
|
8
8
|
* Report one or several diagnostic to the console
|
|
9
9
|
* @param {ts.Diagnostic[] | ts.Diagnostic} diagnostics
|
|
10
10
|
*/
|
|
11
|
-
module.exports = diagnostics => {
|
|
11
|
+
module.exports = (diagnostics) => {
|
|
12
12
|
const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(
|
|
13
13
|
Array.isArray(diagnostics) ? diagnostics : [diagnostics],
|
|
14
14
|
formatHost
|
|
@@ -4,7 +4,7 @@ const ts = require('typescript');
|
|
|
4
4
|
|
|
5
5
|
const logDiagnostics = require('./report-diagnostics');
|
|
6
6
|
|
|
7
|
-
module.exports = configPath => {
|
|
7
|
+
module.exports = (configPath) => {
|
|
8
8
|
// Parse the tsconfig.json file and resolve every file name & compiler options
|
|
9
9
|
const { errors, ...configOptions } = ts.getParsedCommandLineOfConfigFile(
|
|
10
10
|
configPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/typescript-utils",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.6",
|
|
4
4
|
"description": "Typescript support for Strapi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"node": ">=12.22.0 <=16.x.x",
|
|
36
36
|
"npm": ">=6.0.0"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "4c6e67c4934580ed051a2afb83e6fc8f64f3a5b5"
|
|
39
39
|
}
|