@strapi/typescript-utils 0.0.0-next.f8af92b375dc730ba47ed2117f25df893aae696c → 0.0.0-next.f93d6eabe52aa7681655cfa08eedbc3708dbb90d

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/LICENSE CHANGED
@@ -2,7 +2,21 @@ Copyright (c) 2015-present Strapi Solutions SAS
2
2
 
3
3
  Portions of the Strapi software are licensed as follows:
4
4
 
5
- * All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
5
+ * All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined below.
6
+
7
+ Enterprise License
8
+
9
+ If you or the company you represent has entered into a written agreement referencing the Enterprise Edition of the Strapi source code available at
10
+ https://github.com/strapi/strapi, then such agreement applies to your use of the Enterprise Edition of the Strapi Software. If you or the company you
11
+ represent is using the Enterprise Edition of the Strapi Software in connection with a subscription to our cloud offering, then the agreement you have
12
+ agreed to with respect to our cloud offering and the licenses included in such agreement apply to your use of the Enterprise Edition of the Strapi Software.
13
+ Otherwise, the Strapi Enterprise Software License Agreement (found here https://strapi.io/enterprise-terms) applies to your use of the Enterprise Edition of the Strapi Software.
14
+
15
+ BY ACCESSING OR USING THE ENTERPRISE EDITION OF THE STRAPI SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE RELEVANT REFERENCED AGREEMENT.
16
+ IF YOU ARE NOT AUTHORIZED TO ACCEPT THESE TERMS ON BEHALF OF THE COMPANY YOU REPRESENT OR IF YOU DO NOT AGREE TO ALL OF THE RELEVANT TERMS AND CONDITIONS REFERENCED AND YOU
17
+ HAVE NOT OTHERWISE EXECUTED A WRITTEN AGREEMENT WITH STRAPI, YOU ARE NOT AUTHORIZED TO ACCESS OR USE OR ALLOW ANY USER TO ACCESS OR USE ANY PART OF
18
+ THE ENTERPRISE EDITION OF THE STRAPI SOFTWARE. YOUR ACCESS RIGHTS ARE CONDITIONAL ON YOUR CONSENT TO THE RELEVANT REFERENCED TERMS TO THE EXCLUSION OF ALL OTHER TERMS;
19
+ IF THE RELEVANT REFERENCED TERMS ARE CONSIDERED AN OFFER BY YOU, ACCEPTANCE IS EXPRESSLY LIMITED TO THE RELEVANT REFERENCED TERMS.
6
20
 
7
21
  * All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
8
22
 
@@ -18,5 +32,6 @@ furnished to do so, subject to the following conditions:
18
32
  The above copyright notice and this permission notice shall be included in all
19
33
  copies or substantial portions of the Software.
20
34
 
21
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -48,7 +48,7 @@ describe('Attributes', () => {
48
48
 
49
49
  expect(prop.type.types).toHaveLength(1);
50
50
  expect(prop.type.types[0].kind).toBe(ts.SyntaxKind.TypeReference);
51
- expect(prop.type.types[0].typeName.escapedText).toBe('Attribute.String');
51
+ expect(prop.type.types[0].typeName.escapedText).toBe('Schema.Attribute.String');
52
52
  expect(prop.type.types[0].typeArguments).toBeUndefined();
53
53
  });
54
54
 
@@ -60,10 +60,11 @@ describe('Attributes', () => {
60
60
 
61
61
  expect(prop.type.types).toHaveLength(1);
62
62
  expect(prop.type.types[0].kind).toBe(ts.SyntaxKind.TypeReference);
63
- expect(prop.type.types[0].typeName.escapedText).toBe('Attribute.Component');
64
- expect(prop.type.types[0].typeArguments).toHaveLength(1);
63
+ expect(prop.type.types[0].typeName.escapedText).toBe('Schema.Attribute.Component');
64
+ expect(prop.type.types[0].typeArguments).toHaveLength(2);
65
65
  expect(prop.type.types[0].typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
66
66
  expect(prop.type.types[0].typeArguments[0].text).toBe('default.comp');
67
+ expect(prop.type.types[0].typeArguments[1].kind).toBe(ts.SyntaxKind.FalseKeyword);
67
68
  });
68
69
 
69
70
  test('Attribute with type argument and options', () => {
@@ -82,14 +83,14 @@ describe('Attributes', () => {
82
83
  const [attributeType, requiredOptionType] = prop.type.types;
83
84
 
84
85
  expect(attributeType.kind).toBe(ts.SyntaxKind.TypeReference);
85
- expect(attributeType.typeName.escapedText).toBe('Attribute.Enumeration');
86
+ expect(attributeType.typeName.escapedText).toBe('Schema.Attribute.Enumeration');
86
87
  expect(attributeType.typeArguments).toHaveLength(1);
87
88
  expect(attributeType.typeArguments[0].kind).toBe(ts.SyntaxKind.TupleType);
88
89
  expect(attributeType.typeArguments[0].elements[0].text).toBe('a');
89
90
  expect(attributeType.typeArguments[0].elements[1].text).toBe('b');
90
91
 
91
92
  expect(requiredOptionType.kind).toBe(ts.SyntaxKind.TypeReference);
92
- expect(requiredOptionType.typeName.escapedText).toBe('Attribute.DefaultTo');
93
+ expect(requiredOptionType.typeName.escapedText).toBe('Schema.Attribute.DefaultTo');
93
94
  expect(requiredOptionType.typeArguments).toHaveLength(1);
94
95
  expect(requiredOptionType.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
95
96
  expect(requiredOptionType.typeArguments[0].text).toBe('b');
@@ -108,22 +109,22 @@ describe('Attributes', () => {
108
109
  });
109
110
 
110
111
  test.each([
111
- ['string', 'Attribute.String'],
112
- ['text', 'Attribute.Text'],
113
- ['richtext', 'Attribute.RichText'],
114
- ['password', 'Attribute.Password'],
115
- ['email', 'Attribute.Email'],
116
- ['date', 'Attribute.Date'],
117
- ['time', 'Attribute.Time'],
118
- ['datetime', 'Attribute.DateTime'],
119
- ['timestamp', 'Attribute.Timestamp'],
120
- ['integer', 'Attribute.Integer'],
121
- ['biginteger', 'Attribute.BigInteger'],
122
- ['float', 'Attribute.Float'],
123
- ['decimal', 'Attribute.Decimal'],
124
- ['boolean', 'Attribute.Boolean'],
125
- ['json', 'Attribute.JSON'],
126
- ['media', 'Attribute.Media'],
112
+ ['string', 'Schema.Attribute.String'],
113
+ ['text', 'Schema.Attribute.Text'],
114
+ ['richtext', 'Schema.Attribute.RichText'],
115
+ ['password', 'Schema.Attribute.Password'],
116
+ ['email', 'Schema.Attribute.Email'],
117
+ ['date', 'Schema.Attribute.Date'],
118
+ ['time', 'Schema.Attribute.Time'],
119
+ ['datetime', 'Schema.Attribute.DateTime'],
120
+ ['timestamp', 'Schema.Attribute.Timestamp'],
121
+ ['integer', 'Schema.Attribute.Integer'],
122
+ ['biginteger', 'Schema.Attribute.BigInteger'],
123
+ ['float', 'Schema.Attribute.Float'],
124
+ ['decimal', 'Schema.Attribute.Decimal'],
125
+ ['boolean', 'Schema.Attribute.Boolean'],
126
+ ['json', 'Schema.Attribute.JSON'],
127
+ ['media', 'Schema.Attribute.Media'],
127
128
  ])('Basic %p attribute should map to a %p type', (type, expectedType) => {
128
129
  const typeNode = getAttributeType('foo', { type });
129
130
 
@@ -134,7 +135,7 @@ describe('Attributes', () => {
134
135
  expect(typeNode.typeArguments).toBeUndefined();
135
136
 
136
137
  expect(consoleWarnMock).not.toHaveBeenCalled();
137
- expect(addImport).toHaveBeenCalledWith('Attribute');
138
+ expect(addImport).toHaveBeenCalledWith('Schema');
138
139
  });
139
140
 
140
141
  describe('Complex types (with generic type parameters)', () => {
@@ -145,15 +146,81 @@ describe('Attributes', () => {
145
146
  expect(typeNode.typeName.escapedText).toBe(typeName);
146
147
 
147
148
  expect(consoleWarnMock).not.toHaveBeenCalled();
148
- expect(addImport).toHaveBeenCalledWith('Attribute');
149
+ expect(addImport).toHaveBeenCalledWith('Schema');
149
150
  };
150
151
 
152
+ describe('Media', () => {
153
+ test('Media with multiple and with no allowedTypes', () => {
154
+ const attribute = { type: 'media', multiple: true };
155
+ const typeNode = getAttributeType('foo', attribute);
156
+
157
+ defaultAssertions(typeNode, 'Schema.Attribute.Media');
158
+
159
+ expect(typeNode.typeArguments).toHaveLength(2);
160
+
161
+ expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.UndefinedKeyword);
162
+
163
+ expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.TrueKeyword);
164
+ });
165
+
166
+ test('Media without multiple with allowedTypes', () => {
167
+ const attribute = { type: 'media', allowedTypes: ['images', 'videos'] };
168
+ const typeNode = getAttributeType('foo', attribute);
169
+
170
+ defaultAssertions(typeNode, 'Schema.Attribute.Media');
171
+
172
+ expect(typeNode.typeArguments).toHaveLength(1);
173
+
174
+ expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.UnionType);
175
+
176
+ const unionTypes = typeNode.typeArguments[0].types;
177
+
178
+ attribute.allowedTypes.forEach((value, index) => {
179
+ const element = unionTypes[index];
180
+
181
+ expect(element.kind).toBe(ts.SyntaxKind.StringLiteral);
182
+ expect(element.text).toBe(value);
183
+ });
184
+ });
185
+
186
+ test('Media with multiple and with allowedTypes', () => {
187
+ const attribute = { type: 'media', multiple: true, allowedTypes: ['images', 'videos'] };
188
+ const typeNode = getAttributeType('foo', attribute);
189
+
190
+ defaultAssertions(typeNode, 'Schema.Attribute.Media');
191
+
192
+ expect(typeNode.typeArguments).toHaveLength(2);
193
+
194
+ expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.UnionType);
195
+
196
+ const unionTypes = typeNode.typeArguments[0].types;
197
+
198
+ attribute.allowedTypes.forEach((value, index) => {
199
+ const element = unionTypes[index];
200
+
201
+ expect(element.kind).toBe(ts.SyntaxKind.StringLiteral);
202
+ expect(element.text).toBe(value);
203
+ });
204
+
205
+ expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.TrueKeyword);
206
+ });
207
+
208
+ test('Media without multiple and with no allowedTypes', () => {
209
+ const attribute = { type: 'media' };
210
+ const typeNode = getAttributeType('foo', attribute);
211
+
212
+ defaultAssertions(typeNode, 'Schema.Attribute.Media');
213
+
214
+ expect(typeNode.typeArguments).toBeUndefined();
215
+ });
216
+ });
217
+
151
218
  describe('Enumeration', () => {
152
219
  test('Enumeration with an enum property', () => {
153
220
  const attribute = { type: 'enumeration', enum: ['a', 'b', 'c'] };
154
221
  const typeNode = getAttributeType('foo', attribute);
155
222
 
156
- defaultAssertions(typeNode, 'Attribute.Enumeration');
223
+ defaultAssertions(typeNode, 'Schema.Attribute.Enumeration');
157
224
 
158
225
  expect(typeNode.typeArguments).toHaveLength(1);
159
226
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.TupleType);
@@ -174,7 +241,7 @@ describe('Attributes', () => {
174
241
  const attribute = { type: 'uid' };
175
242
  const typeNode = getAttributeType('foo', attribute);
176
243
 
177
- defaultAssertions(typeNode, 'Attribute.UID');
244
+ defaultAssertions(typeNode, 'Schema.Attribute.UID');
178
245
 
179
246
  expect(typeNode.typeArguments).toBeUndefined();
180
247
  });
@@ -183,30 +250,26 @@ describe('Attributes', () => {
183
250
  const attribute = { type: 'uid', targetField: 'bar' };
184
251
  const typeNode = getAttributeType('foo', attribute, 'api::bar.bar');
185
252
 
186
- defaultAssertions(typeNode, 'Attribute.UID');
253
+ defaultAssertions(typeNode, 'Schema.Attribute.UID');
187
254
 
188
255
  expect(typeNode.typeArguments).not.toBeUndefined();
189
- expect(typeNode.typeArguments).toHaveLength(2);
256
+ expect(typeNode.typeArguments).toHaveLength(1);
190
257
 
191
258
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
192
- expect(typeNode.typeArguments[0].text).toBe('api::bar.bar');
193
-
194
- expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.StringLiteral);
195
- expect(typeNode.typeArguments[1].text).toBe('bar');
259
+ expect(typeNode.typeArguments[0].text).toBe('bar');
196
260
  });
197
261
 
198
262
  test('UID with partial options and no target field', () => {
199
263
  const attribute = { type: 'uid', options: { separator: '_' } };
200
- const typeNode = getAttributeType('foo', attribute);
264
+ const typeNode = getAttributeType('foo', attribute, 'api::foo.foo');
201
265
 
202
- defaultAssertions(typeNode, 'Attribute.UID');
266
+ defaultAssertions(typeNode, 'Schema.Attribute.UID');
203
267
 
204
- expect(typeNode.typeArguments).toHaveLength(3);
268
+ expect(typeNode.typeArguments).toHaveLength(2);
205
269
 
206
270
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.UndefinedKeyword);
207
- expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.UndefinedKeyword);
208
271
 
209
- const optionsLiteralNode = typeNode.typeArguments[2];
272
+ const optionsLiteralNode = typeNode.typeArguments[1];
210
273
 
211
274
  expect(optionsLiteralNode.kind).toBe(ts.SyntaxKind.TypeLiteral);
212
275
  expect(optionsLiteralNode.members).toHaveLength(1);
@@ -224,17 +287,14 @@ describe('Attributes', () => {
224
287
  const attribute = { type: 'uid', options: { separator: '_' }, targetField: 'bar' };
225
288
  const typeNode = getAttributeType('foo', attribute, 'api::bar.bar');
226
289
 
227
- defaultAssertions(typeNode, 'Attribute.UID');
290
+ defaultAssertions(typeNode, 'Schema.Attribute.UID');
228
291
 
229
- expect(typeNode.typeArguments).toHaveLength(3);
292
+ expect(typeNode.typeArguments).toHaveLength(2);
230
293
 
231
294
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
232
- expect(typeNode.typeArguments[0].text).toBe('api::bar.bar');
233
-
234
- expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.StringLiteral);
235
- expect(typeNode.typeArguments[1].text).toBe('bar');
295
+ expect(typeNode.typeArguments[0].text).toBe('bar');
236
296
 
237
- const optionsLiteralNode = typeNode.typeArguments[2];
297
+ const optionsLiteralNode = typeNode.typeArguments[1];
238
298
 
239
299
  expect(optionsLiteralNode.kind).toBe(ts.SyntaxKind.TypeLiteral);
240
300
  expect(optionsLiteralNode.members).toHaveLength(1);
@@ -254,33 +314,27 @@ describe('Attributes', () => {
254
314
  const attribute = { type: 'relation', relation: 'oneToOne', target: 'api::bar.bar' };
255
315
  const typeNode = getAttributeType('foo', attribute, 'api::foo.foo');
256
316
 
257
- defaultAssertions(typeNode, 'Attribute.Relation');
317
+ defaultAssertions(typeNode, 'Schema.Attribute.Relation');
258
318
 
259
- expect(typeNode.typeArguments).toHaveLength(3);
319
+ expect(typeNode.typeArguments).toHaveLength(2);
260
320
 
261
321
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
262
- expect(typeNode.typeArguments[0].text).toBe('api::foo.foo');
322
+ expect(typeNode.typeArguments[0].text).toBe('oneToOne');
263
323
 
264
324
  expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.StringLiteral);
265
- expect(typeNode.typeArguments[1].text).toBe('oneToOne');
266
-
267
- expect(typeNode.typeArguments[2].kind).toBe(ts.SyntaxKind.StringLiteral);
268
- expect(typeNode.typeArguments[2].text).toBe('api::bar.bar');
325
+ expect(typeNode.typeArguments[1].text).toBe('api::bar.bar');
269
326
  });
270
327
 
271
328
  test('Polymorphic relation', () => {
272
329
  const attribute = { type: 'relation', relation: 'morphMany' };
273
330
  const typeNode = getAttributeType('foo', attribute, 'api::foo.foo');
274
331
 
275
- defaultAssertions(typeNode, 'Attribute.Relation');
332
+ defaultAssertions(typeNode, 'Schema.Attribute.Relation');
276
333
 
277
- expect(typeNode.typeArguments).toHaveLength(2);
334
+ expect(typeNode.typeArguments).toHaveLength(1);
278
335
 
279
336
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
280
- expect(typeNode.typeArguments[0].text).toBe('api::foo.foo');
281
-
282
- expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.StringLiteral);
283
- expect(typeNode.typeArguments[1].text).toBe('morphMany');
337
+ expect(typeNode.typeArguments[0].text).toBe('morphMany');
284
338
  });
285
339
  });
286
340
 
@@ -289,7 +343,7 @@ describe('Attributes', () => {
289
343
  const attribute = { type: 'component', component: 'default.comp', repeatable: true };
290
344
  const typeNode = getAttributeType('foo', attribute);
291
345
 
292
- defaultAssertions(typeNode, 'Attribute.Component');
346
+ defaultAssertions(typeNode, 'Schema.Attribute.Component');
293
347
 
294
348
  expect(typeNode.typeArguments).toHaveLength(2);
295
349
 
@@ -303,12 +357,14 @@ describe('Attributes', () => {
303
357
  const attribute = { type: 'component', component: 'default.comp' };
304
358
  const typeNode = getAttributeType('foo', attribute);
305
359
 
306
- defaultAssertions(typeNode, 'Attribute.Component');
360
+ defaultAssertions(typeNode, 'Schema.Attribute.Component');
307
361
 
308
- expect(typeNode.typeArguments).toHaveLength(1);
362
+ expect(typeNode.typeArguments).toHaveLength(2);
309
363
 
310
364
  expect(typeNode.typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
311
365
  expect(typeNode.typeArguments[0].text).toBe('default.comp');
366
+
367
+ expect(typeNode.typeArguments[1].kind).toBe(ts.SyntaxKind.FalseKeyword);
312
368
  });
313
369
  });
314
370
 
@@ -317,7 +373,7 @@ describe('Attributes', () => {
317
373
  const attribute = { type: 'dynamiczone', components: ['default.comp1', 'default.comp2'] };
318
374
  const typeNode = getAttributeType('foo', attribute);
319
375
 
320
- defaultAssertions(typeNode, 'Attribute.DynamicZone');
376
+ defaultAssertions(typeNode, 'Schema.Attribute.DynamicZone');
321
377
 
322
378
  expect(typeNode.typeArguments).toHaveLength(1);
323
379
 
@@ -359,7 +415,7 @@ describe('Attributes', () => {
359
415
 
360
416
  expect(modifiers).toHaveLength(1);
361
417
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
362
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.Required');
418
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.Required');
363
419
  });
364
420
  });
365
421
 
@@ -384,7 +440,7 @@ describe('Attributes', () => {
384
440
 
385
441
  expect(modifiers).toHaveLength(1);
386
442
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
387
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.Private');
443
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.Private');
388
444
  });
389
445
  });
390
446
 
@@ -409,7 +465,7 @@ describe('Attributes', () => {
409
465
 
410
466
  expect(modifiers).toHaveLength(1);
411
467
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
412
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.Unique');
468
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.Unique');
413
469
  });
414
470
  });
415
471
 
@@ -434,7 +490,7 @@ describe('Attributes', () => {
434
490
 
435
491
  expect(modifiers).toHaveLength(1);
436
492
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
437
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.Configurable');
493
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.Configurable');
438
494
  });
439
495
  });
440
496
 
@@ -455,7 +511,7 @@ describe('Attributes', () => {
455
511
 
456
512
  expect(modifiers).toHaveLength(1);
457
513
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
458
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.CustomField');
514
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.CustomField');
459
515
  expect(modifiers[0].typeArguments).toHaveLength(1);
460
516
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
461
517
  expect(modifiers[0].typeArguments[0].text).toBe('plugin::color-picker.color');
@@ -473,7 +529,7 @@ describe('Attributes', () => {
473
529
 
474
530
  expect(modifiers).toHaveLength(1);
475
531
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
476
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.CustomField');
532
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.CustomField');
477
533
  expect(modifiers[0].typeArguments).toHaveLength(2);
478
534
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.StringLiteral);
479
535
  expect(modifiers[0].typeArguments[0].text).toBe('plugin::color-picker.color');
@@ -507,7 +563,7 @@ describe('Attributes', () => {
507
563
 
508
564
  expect(modifiers).toHaveLength(1);
509
565
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
510
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetPluginOptions');
566
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetPluginOptions');
511
567
  expect(modifiers[0].typeArguments).toHaveLength(1);
512
568
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TypeLiteral);
513
569
  expect(modifiers[0].typeArguments[0].members).toHaveLength(1);
@@ -546,7 +602,7 @@ describe('Attributes', () => {
546
602
  expect(modifiers).toHaveLength(1);
547
603
 
548
604
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
549
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMax');
605
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMax');
550
606
 
551
607
  const [setMinMax] = modifiers;
552
608
  const { typeArguments } = setMinMax;
@@ -578,7 +634,7 @@ describe('Attributes', () => {
578
634
  expect(modifiers).toHaveLength(1);
579
635
 
580
636
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
581
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMax');
637
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMax');
582
638
 
583
639
  const [setMinMax] = modifiers;
584
640
  const { typeArguments } = setMinMax;
@@ -610,7 +666,7 @@ describe('Attributes', () => {
610
666
  expect(modifiers).toHaveLength(1);
611
667
 
612
668
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
613
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMax');
669
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMax');
614
670
 
615
671
  const [setMinMax] = modifiers;
616
672
  const { typeArguments } = setMinMax;
@@ -624,18 +680,18 @@ describe('Attributes', () => {
624
680
  expect(definition.kind).toBe(ts.SyntaxKind.TypeLiteral);
625
681
  expect(definition.members).toHaveLength(2);
626
682
 
627
- const [min, max] = definition.members;
628
-
629
- expect(min.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
630
- expect(min.name.escapedText).toBe('min');
631
- expect(min.type.kind).toBe(ts.SyntaxKind.NumericLiteral);
632
- expect(min.type.text).toBe('4');
683
+ const [max, min] = definition.members;
633
684
 
634
685
  expect(max.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
635
686
  expect(max.name.escapedText).toBe('max');
636
687
  expect(max.type.kind).toBe(ts.SyntaxKind.NumericLiteral);
637
688
  expect(max.type.text).toBe('12');
638
689
 
690
+ expect(min.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
691
+ expect(min.name.escapedText).toBe('min');
692
+ expect(min.type.kind).toBe(ts.SyntaxKind.NumericLiteral);
693
+ expect(min.type.text).toBe('4');
694
+
639
695
  // Check for number keyword on the second typeArgument
640
696
  expect(typeofMinMax.kind).toBe(ts.SyntaxKind.NumberKeyword);
641
697
  });
@@ -647,7 +703,7 @@ describe('Attributes', () => {
647
703
  expect(modifiers).toHaveLength(1);
648
704
 
649
705
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
650
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMax');
706
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMax');
651
707
 
652
708
  const [setMinMax] = modifiers;
653
709
  const { typeArguments } = setMinMax;
@@ -679,7 +735,7 @@ describe('Attributes', () => {
679
735
  expect(modifiers).toHaveLength(1);
680
736
 
681
737
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
682
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMax');
738
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMax');
683
739
 
684
740
  const [setMinMax] = modifiers;
685
741
  const { typeArguments } = setMinMax;
@@ -720,7 +776,7 @@ describe('Attributes', () => {
720
776
  expect(modifiers).toHaveLength(1);
721
777
 
722
778
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
723
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMaxLength');
779
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMaxLength');
724
780
 
725
781
  expect(modifiers[0].typeArguments).toHaveLength(1);
726
782
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TypeLiteral);
@@ -744,7 +800,7 @@ describe('Attributes', () => {
744
800
  expect(modifiers).toHaveLength(1);
745
801
 
746
802
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
747
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMaxLength');
803
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMaxLength');
748
804
 
749
805
  expect(modifiers[0].typeArguments).toHaveLength(1);
750
806
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TypeLiteral);
@@ -768,30 +824,25 @@ describe('Attributes', () => {
768
824
  expect(modifiers).toHaveLength(1);
769
825
 
770
826
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
771
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.SetMinMaxLength');
827
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.SetMinMaxLength');
772
828
 
773
829
  expect(modifiers[0].typeArguments).toHaveLength(1);
774
830
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TypeLiteral);
775
831
  expect(modifiers[0].typeArguments[0].members).toHaveLength(2);
776
832
 
777
- // Min
778
- expect(modifiers[0].typeArguments[0].members[0].kind).toBe(
779
- ts.SyntaxKind.PropertyDeclaration
780
- );
781
- expect(modifiers[0].typeArguments[0].members[0].name.escapedText).toBe('minLength');
782
- expect(modifiers[0].typeArguments[0].members[0].type.kind).toBe(
783
- ts.SyntaxKind.NumericLiteral
784
- );
785
- expect(modifiers[0].typeArguments[0].members[0].type.text).toBe('4');
833
+ const [maxLength, minLength] = modifiers[0].typeArguments[0].members;
786
834
 
787
- expect(modifiers[0].typeArguments[0].members[1].kind).toBe(
788
- ts.SyntaxKind.PropertyDeclaration
789
- );
790
- expect(modifiers[0].typeArguments[0].members[1].name.escapedText).toBe('maxLength');
791
- expect(modifiers[0].typeArguments[0].members[1].type.kind).toBe(
792
- ts.SyntaxKind.NumericLiteral
793
- );
794
- expect(modifiers[0].typeArguments[0].members[1].type.text).toBe('12');
835
+ // Max
836
+ expect(maxLength.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
837
+ expect(maxLength.name.escapedText).toBe('maxLength');
838
+ expect(maxLength.type.kind).toBe(ts.SyntaxKind.NumericLiteral);
839
+ expect(maxLength.type.text).toBe('12');
840
+
841
+ // Min
842
+ expect(minLength.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
843
+ expect(minLength.name.escapedText).toBe('minLength');
844
+ expect(minLength.type.kind).toBe(ts.SyntaxKind.NumericLiteral);
845
+ expect(minLength.type.text).toBe('4');
795
846
  });
796
847
  });
797
848
 
@@ -810,7 +861,7 @@ describe('Attributes', () => {
810
861
  expect(modifiers).toHaveLength(1);
811
862
 
812
863
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
813
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.DefaultTo');
864
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.DefaultTo');
814
865
 
815
866
  expect(modifiers[0].typeArguments).toHaveLength(1);
816
867
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TrueKeyword);
@@ -823,7 +874,7 @@ describe('Attributes', () => {
823
874
  expect(modifiers).toHaveLength(1);
824
875
 
825
876
  expect(modifiers[0].kind).toBe(ts.SyntaxKind.TypeReference);
826
- expect(modifiers[0].typeName.escapedText).toBe('Attribute.DefaultTo');
877
+ expect(modifiers[0].typeName.escapedText).toBe('Schema.Attribute.DefaultTo');
827
878
 
828
879
  expect(modifiers[0].typeArguments).toHaveLength(1);
829
880
  expect(modifiers[0].typeArguments[0].kind).toBe(ts.SyntaxKind.TypeLiteral);
@@ -836,6 +887,16 @@ describe('Attributes', () => {
836
887
  ts.SyntaxKind.TrueKeyword
837
888
  );
838
889
  });
890
+
891
+ test('Default: <function>', () => {
892
+ const anyFunction = jest.fn();
893
+ const attribute = { default: anyFunction };
894
+
895
+ const modifiers = getAttributeModifiers(attribute);
896
+
897
+ // The default modifier shouldn't be processed when encountering a function
898
+ expect(modifiers).toHaveLength(0);
899
+ });
839
900
  });
840
901
  });
841
902
  });
@@ -120,9 +120,9 @@ describe('Utils', () => {
120
120
 
121
121
  describe('Get Schema Extends Type Name', () => {
122
122
  test.each([
123
- [{ modelType: 'component', kind: null }, 'Schema.Component'],
124
- [{ modelType: 'contentType', kind: 'singleType' }, 'Schema.SingleType'],
125
- [{ modelType: 'contentType', kind: 'collectionType' }, 'Schema.CollectionType'],
123
+ [{ modelType: 'component', kind: null }, 'Struct.ComponentSchema'],
124
+ [{ modelType: 'contentType', kind: 'singleType' }, 'Struct.SingleTypeSchema'],
125
+ [{ modelType: 'contentType', kind: 'collectionType' }, 'Struct.CollectionTypeSchema'],
126
126
  [{ modelType: 'invalidType', kind: 'foo' }, null],
127
127
  ])("Expect %p to generate %p as the base type for a schema's interface", (schema, expected) => {
128
128
  expect(getSchemaExtendsTypeName(schema)).toBe(expected);
@@ -247,13 +247,13 @@ describe('Utils', () => {
247
247
  expect(objectNode.members).toHaveLength(2);
248
248
 
249
249
  expect(objectNode.members[0].kind).toBe(ts.SyntaxKind.PropertyDeclaration);
250
- expect(objectNode.members[0].name.escapedText).toBe('foo');
251
- expect(objectNode.members[0].type.kind).toBe(ts.SyntaxKind.StringLiteral);
252
- expect(objectNode.members[0].type.text).toBe('bar');
250
+ expect(objectNode.members[0].name.escapedText).toBe('bar');
251
+ expect(objectNode.members[0].type.kind).toBe(ts.SyntaxKind.TrueKeyword);
253
252
 
254
253
  expect(objectNode.members[1].kind).toBe(ts.SyntaxKind.PropertyDeclaration);
255
- expect(objectNode.members[1].name.escapedText).toBe('bar');
256
- expect(objectNode.members[1].type.kind).toBe(ts.SyntaxKind.TrueKeyword);
254
+ expect(objectNode.members[1].name.escapedText).toBe('foo');
255
+ expect(objectNode.members[1].type.kind).toBe(ts.SyntaxKind.StringLiteral);
256
+ expect(objectNode.members[1].type.text).toBe('bar');
257
257
  });
258
258
 
259
259
  test('Object', () => {
@@ -262,20 +262,20 @@ describe('Utils', () => {
262
262
  expect(node.kind).toBe(ts.SyntaxKind.TypeLiteral);
263
263
  expect(node.members).toHaveLength(2);
264
264
 
265
- const [firstMember, secondMember] = node.members;
265
+ const [barMember, fooMember] = node.members;
266
266
 
267
- expect(firstMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
268
- expect(firstMember.name.escapedText).toBe('foo');
269
- expect(firstMember.type.kind).toBe(ts.SyntaxKind.TupleType);
270
- expect(firstMember.type.elements).toHaveLength(3);
271
- expect(firstMember.type.elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
272
- expect(firstMember.type.elements[1].kind).toBe(ts.SyntaxKind.TrueKeyword);
273
- expect(firstMember.type.elements[2].kind).toBe(ts.SyntaxKind.FirstLiteralToken);
267
+ expect(barMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
268
+ expect(barMember.name.escapedText).toBe('bar');
269
+ expect(barMember.type.kind).toBe(ts.SyntaxKind.LiteralType);
270
+ expect(barMember.type.literal).toBe(ts.SyntaxKind.NullKeyword);
274
271
 
275
- expect(secondMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
276
- expect(secondMember.name.escapedText).toBe('bar');
277
- expect(secondMember.type.kind).toBe(ts.SyntaxKind.LiteralType);
278
- expect(secondMember.type.literal).toBe(ts.SyntaxKind.NullKeyword);
272
+ expect(fooMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
273
+ expect(fooMember.name.escapedText).toBe('foo');
274
+ expect(fooMember.type.kind).toBe(ts.SyntaxKind.TupleType);
275
+ expect(fooMember.type.elements).toHaveLength(3);
276
+ expect(fooMember.type.elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
277
+ expect(fooMember.type.elements[1].kind).toBe(ts.SyntaxKind.TrueKeyword);
278
+ expect(fooMember.type.elements[2].kind).toBe(ts.SyntaxKind.FirstLiteralToken);
279
279
  });
280
280
 
281
281
  test('Object with complex keys', () => {
@@ -284,19 +284,19 @@ describe('Utils', () => {
284
284
  expect(node.kind).toBe(ts.SyntaxKind.TypeLiteral);
285
285
  expect(node.members).toHaveLength(2);
286
286
 
287
- const [firstMember, secondMember] = node.members;
287
+ const [fooBar, fooDashBar] = node.members;
288
288
 
289
- expect(firstMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
290
- expect(firstMember.name.kind).toBe(ts.SyntaxKind.StringLiteral);
291
- expect(firstMember.name.text).toBe('foo-bar');
292
- expect(firstMember.type.kind).toBe(ts.SyntaxKind.StringLiteral);
293
- expect(firstMember.type.text).toBe('foobar');
289
+ expect(fooBar.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
290
+ expect(fooBar.name.kind).toBe(ts.SyntaxKind.Identifier);
291
+ expect(fooBar.name.escapedText).toBe('foo');
292
+ expect(fooBar.type.kind).toBe(ts.SyntaxKind.StringLiteral);
293
+ expect(fooBar.type.text).toBe('bar');
294
294
 
295
- expect(secondMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
296
- expect(secondMember.name.kind).toBe(ts.SyntaxKind.Identifier);
297
- expect(secondMember.name.escapedText).toBe('foo');
298
- expect(secondMember.type.kind).toBe(ts.SyntaxKind.StringLiteral);
299
- expect(secondMember.type.text).toBe('bar');
295
+ expect(fooDashBar.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
296
+ expect(fooDashBar.name.kind).toBe(ts.SyntaxKind.StringLiteral);
297
+ expect(fooDashBar.name.text).toBe('foo-bar');
298
+ expect(fooDashBar.type.kind).toBe(ts.SyntaxKind.StringLiteral);
299
+ expect(fooDashBar.type.text).toBe('foobar');
300
300
  });
301
301
 
302
302
  test('Invalid data type supplied (function)', () => {
@@ -18,9 +18,9 @@ module.exports = {
18
18
  },
19
19
 
20
20
  generateImportDefinition() {
21
- const formattedImports = imports.map((key) =>
22
- factory.createImportSpecifier(false, undefined, factory.createIdentifier(key))
23
- );
21
+ const formattedImports = imports
22
+ .sort()
23
+ .map((key) => factory.createImportSpecifier(false, undefined, factory.createIdentifier(key)));
24
24
 
25
25
  return [
26
26
  factory.createImportDeclaration(
@@ -28,8 +28,8 @@ const getAttributeType = (attributeName, attribute, uid) => {
28
28
 
29
29
  const [attributeType, typeParams] = mappers[attribute.type]({ uid, attribute, attributeName });
30
30
 
31
- // Make sure the attribute namespace is imported
32
- addImport(NAMESPACES.attribute);
31
+ // Make sure the schema namespace is imported
32
+ addImport(NAMESPACES.Schema);
33
33
 
34
34
  return getTypeNode(attributeType, typeParams);
35
35
  };
@@ -151,8 +151,8 @@ const getAttributeModifiers = (attribute) => {
151
151
  );
152
152
  }
153
153
 
154
- // Default
155
- if (!_.isNil(attribute.default)) {
154
+ // Default (ignore if default is a function)
155
+ if (!_.isNil(attribute.default) && !_.isFunction(attribute.default)) {
156
156
  const defaultLiteral = toTypeLiteral(attribute.default);
157
157
 
158
158
  modifiers.push(
@@ -195,6 +195,4 @@ const attributeToPropertySignature = (schema, attributeName, attribute) => {
195
195
 
196
196
  module.exports = attributeToPropertySignature;
197
197
 
198
- module.exports.mappers = mappers;
199
- module.exports.getAttributeType = getAttributeType;
200
- module.exports.getAttributeModifiers = getAttributeModifiers;
198
+ Object.assign(module.exports, { mappers, getAttributeModifiers, getAttributeType });
@@ -47,7 +47,7 @@ module.exports = {
47
47
  decimal() {
48
48
  return [withAttributeNamespace('Decimal')];
49
49
  },
50
- uid({ attribute, uid }) {
50
+ uid({ attribute }) {
51
51
  const { targetField, options } = attribute;
52
52
 
53
53
  // If there are no params to compute, then return the attribute type alone
@@ -58,18 +58,15 @@ module.exports = {
58
58
  const params = [];
59
59
 
60
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)];
61
+ // otherwise, put `undefined` keyword type node as placeholder
62
+ const targetFieldParam = _.isUndefined(targetField)
63
+ ? factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
64
+ : factory.createStringLiteral(targetField);
68
65
 
69
- params.push(...targetFieldParams);
66
+ params.push(targetFieldParam);
70
67
 
71
68
  // If the options property is defined, transform it to
72
- // a type literral node and add it to the params list
69
+ // a type literal node and add it to the params list
73
70
  if (_.isObject(options)) {
74
71
  params.push(toTypeLiteral(options));
75
72
  }
@@ -90,28 +87,39 @@ module.exports = {
90
87
  blocks() {
91
88
  return [withAttributeNamespace('Blocks')];
92
89
  },
93
- media() {
94
- return [withAttributeNamespace('Media')];
90
+ media({ attribute }) {
91
+ const { allowedTypes, multiple } = attribute;
92
+
93
+ const params = [];
94
+
95
+ const typesParam = allowedTypes
96
+ ? factory.createUnionTypeNode(
97
+ allowedTypes.map((allowedType) => factory.createStringLiteral(allowedType))
98
+ )
99
+ : factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword);
100
+
101
+ if (allowedTypes || multiple) {
102
+ params.push(typesParam);
103
+ }
104
+
105
+ if (multiple) {
106
+ params.push(factory.createTrue());
107
+ }
108
+
109
+ return [withAttributeNamespace('Media'), params];
95
110
  },
96
- relation({ uid, attribute }) {
111
+ relation({ attribute }) {
97
112
  const { relation, target } = attribute;
98
113
 
99
114
  const isMorphRelation = relation.toLowerCase().includes('morph');
100
115
 
101
116
  if (isMorphRelation) {
102
- return [
103
- withAttributeNamespace('Relation'),
104
- [factory.createStringLiteral(uid, true), factory.createStringLiteral(relation, true)],
105
- ];
117
+ return [withAttributeNamespace('Relation'), [factory.createStringLiteral(relation, true)]];
106
118
  }
107
119
 
108
120
  return [
109
121
  withAttributeNamespace('Relation'),
110
- [
111
- factory.createStringLiteral(uid, true),
112
- factory.createStringLiteral(relation, true),
113
- factory.createStringLiteral(target, true),
114
- ],
122
+ [factory.createStringLiteral(relation, true), factory.createStringLiteral(target, true)],
115
123
  ];
116
124
  },
117
125
  component({ attribute }) {
@@ -120,6 +128,8 @@ module.exports = {
120
128
 
121
129
  if (attribute.repeatable) {
122
130
  params.push(factory.createTrue());
131
+ } else {
132
+ params.push(factory.createFalse());
123
133
  }
124
134
 
125
135
  return [withAttributeNamespace('Component'), params];
@@ -22,9 +22,11 @@ const { addImport } = require('../imports');
22
22
  const generateAttributePropertySignature = (schema) => {
23
23
  const { attributes } = schema;
24
24
 
25
- const properties = Object.entries(attributes).map(([attributeName, attribute]) => {
26
- return attributeToPropertySignature(schema, attributeName, attribute);
27
- });
25
+ const properties = Object.entries(attributes)
26
+ .sort((a, b) => a[0].localeCompare(b[0]))
27
+ .map(([attributeName, attribute]) => {
28
+ return attributeToPropertySignature(schema, attributeName, attribute);
29
+ });
28
30
 
29
31
  return factory.createPropertySignature(
30
32
  undefined,
@@ -56,8 +58,8 @@ const generateSchemaDefinition = (schema) => {
56
58
  const interfaceName = getSchemaInterfaceName(uid);
57
59
  const parentType = getSchemaExtendsTypeName(schema);
58
60
 
59
- // Make sure the Schema namespace is imported
60
- addImport(NAMESPACES.schema);
61
+ // Make sure the Struct namespace is imported
62
+ addImport(NAMESPACES.Struct);
61
63
 
62
64
  // Properties whose values can be mapped to a literal type expression
63
65
  const literalPropertiesDefinitions = ['collectionName', 'info', 'options', 'pluginOptions']
@@ -18,8 +18,8 @@ const {
18
18
  } = require('lodash/fp');
19
19
 
20
20
  const NAMESPACES = {
21
- schema: 'Schema',
22
- attribute: 'Attribute',
21
+ Struct: 'Struct',
22
+ Schema: 'Schema',
23
23
  };
24
24
 
25
25
  /**
@@ -50,7 +50,7 @@ const getSchemaModelType = (schema) => {
50
50
  * Get the parent type name to extend based on the schema's nature
51
51
  *
52
52
  * @param {object} schema
53
- * @returns {string}
53
+ * @returns {string|null}
54
54
  */
55
55
  const getSchemaExtendsTypeName = (schema) => {
56
56
  const base = getSchemaModelType(schema);
@@ -59,7 +59,7 @@ const getSchemaExtendsTypeName = (schema) => {
59
59
  return null;
60
60
  }
61
61
 
62
- return `${NAMESPACES.schema}.${upperFirst(base)}`;
62
+ return `${NAMESPACES.Struct}.${upperFirst(base)}Schema`;
63
63
  };
64
64
 
65
65
  /**
@@ -111,7 +111,7 @@ const toTypeLiteral = (data) => {
111
111
  throw new Error(`Cannot convert to object literal. Unknown type "${typeof data}"`);
112
112
  }
113
113
 
114
- const entries = Object.entries(data);
114
+ const entries = Object.entries(data).sort((a, b) => a[0].localeCompare(b[0]));
115
115
 
116
116
  const props = entries.reduce((acc, [key, value]) => {
117
117
  // Handle keys such as content-type-builder & co.
@@ -145,12 +145,12 @@ const getDefinitionAttributesCount = (definition) => {
145
145
  };
146
146
 
147
147
  /**
148
- * Add the attribute namespace before the typename
148
+ * Add the Schema.Attribute namespace before the typename
149
149
  *
150
150
  * @param {string} typeName
151
151
  * @returns {string}
152
152
  */
153
- const withAttributeNamespace = (typeName) => `${NAMESPACES.attribute}.${typeName}`;
153
+ const withAttributeNamespace = (typeName) => `${NAMESPACES.Schema}.Attribute.${typeName}`;
154
154
 
155
155
  /**
156
156
  * Add the schema namespace before the typename
@@ -1,10 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  const { factory } = require('typescript');
4
+ const { pipe, values, sortBy, map } = require('lodash/fp');
4
5
 
5
6
  const { models } = require('../common');
6
7
  const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils');
7
8
 
9
+ const NO_COMPONENT_PLACEHOLDER_COMMENT = `/*
10
+ * The app doesn't have any components yet.
11
+ */
12
+ `;
13
+
8
14
  /**
9
15
  * Generate type definitions for Strapi Components
10
16
  *
@@ -18,10 +24,20 @@ const generateComponentsDefinitions = async (options = {}) => {
18
24
 
19
25
  const { components } = strapi;
20
26
 
21
- const componentsDefinitions = Object.values(components).map((contentType) => ({
22
- uid: contentType.uid,
23
- definition: models.schema.generateSchemaDefinition(contentType),
24
- }));
27
+ const componentsDefinitions = pipe(
28
+ values,
29
+ sortBy('uid'),
30
+ map((component) => ({
31
+ uid: component.uid,
32
+ definition: models.schema.generateSchemaDefinition(component),
33
+ }))
34
+ )(components);
35
+
36
+ options.logger.debug(`Found ${componentsDefinitions.length} components.`);
37
+
38
+ if (componentsDefinitions.length === 0) {
39
+ return { output: NO_COMPONENT_PLACEHOLDER_COMMENT, stats: {} };
40
+ }
25
41
 
26
42
  const formattedSchemasDefinitions = componentsDefinitions.reduce((acc, def) => {
27
43
  acc.push(
@@ -46,7 +62,7 @@ const generateComponentsDefinitions = async (options = {}) => {
46
62
  ...formattedSchemasDefinitions,
47
63
 
48
64
  // Global
49
- generateSharedExtensionDefinition('Components', componentsDefinitions),
65
+ generateSharedExtensionDefinition('ComponentSchemas', componentsDefinitions),
50
66
  ];
51
67
 
52
68
  const output = emitDefinitions(allDefinitions);
@@ -1,10 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  const { factory } = require('typescript');
4
+ const { values, pipe, map, sortBy } = require('lodash/fp');
4
5
 
5
6
  const { models } = require('../common');
6
7
  const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils');
7
8
 
9
+ const NO_CONTENT_TYPE_PLACEHOLDER_COMMENT = `/*
10
+ * The app doesn't have any content-types yet.
11
+ */
12
+ `;
13
+
8
14
  /**
9
15
  * Generate type definitions for Strapi Content-Types
10
16
  *
@@ -18,10 +24,20 @@ const generateContentTypesDefinitions = async (options = {}) => {
18
24
 
19
25
  const { contentTypes } = strapi;
20
26
 
21
- const contentTypesDefinitions = Object.values(contentTypes).map((contentType) => ({
22
- uid: contentType.uid,
23
- definition: models.schema.generateSchemaDefinition(contentType),
24
- }));
27
+ const contentTypesDefinitions = pipe(
28
+ values,
29
+ sortBy('uid'),
30
+ map((contentType) => ({
31
+ uid: contentType.uid,
32
+ definition: models.schema.generateSchemaDefinition(contentType),
33
+ }))
34
+ )(contentTypes);
35
+
36
+ options.logger.debug(`Found ${contentTypesDefinitions.length} content-types.`);
37
+
38
+ if (contentTypesDefinitions.length === 0) {
39
+ return { output: NO_CONTENT_TYPE_PLACEHOLDER_COMMENT, stats: {} };
40
+ }
25
41
 
26
42
  const formattedSchemasDefinitions = contentTypesDefinitions.reduce((acc, def) => {
27
43
  acc.push(
@@ -46,7 +62,7 @@ const generateContentTypesDefinitions = async (options = {}) => {
46
62
  ...formattedSchemasDefinitions,
47
63
 
48
64
  // Global
49
- generateSharedExtensionDefinition('ContentTypes', contentTypesDefinitions),
65
+ generateSharedExtensionDefinition('ContentTypeSchemas', contentTypesDefinitions),
50
66
  ];
51
67
 
52
68
  const output = emitDefinitions(allDefinitions);
@@ -100,7 +100,7 @@ const generate = async (config = {}) => {
100
100
 
101
101
  try {
102
102
  const outPath = await saveDefinitionToFileSystem(registryPwd, filename, report.output);
103
- const relativeOutPath = path.relative(__dirname, outPath);
103
+ const relativeOutPath = path.relative(process.cwd(), outPath);
104
104
 
105
105
  artifactFsTimer.end();
106
106
 
@@ -3,12 +3,14 @@
3
3
  const path = require('path');
4
4
  const assert = require('assert');
5
5
  const ts = require('typescript');
6
- const prettier = require('prettier');
7
6
  const fse = require('fs-extra');
8
7
  const chalk = require('chalk');
9
8
 
10
9
  const { factory } = ts;
11
10
 
11
+ const MODULE_DECLARATION = '@strapi/strapi';
12
+ const PUBLIC_NAMESPACE = 'Public';
13
+
12
14
  /**
13
15
  * Aggregate the given TypeScript nodes into a single string
14
16
  *
@@ -58,6 +60,9 @@ const saveDefinitionToFileSystem = async (dir, file, content) => {
58
60
  * @returns {Promise<string>}
59
61
  */
60
62
  const format = async (content) => {
63
+ // eslint-disable-next-line node/no-unsupported-features/es-syntax
64
+ const prettier = await import('prettier'); // ESM-only
65
+
61
66
  const configFile = await prettier.resolveConfigFile();
62
67
  const config = configFile
63
68
  ? await prettier.resolveConfig(configFile)
@@ -92,11 +97,11 @@ const generateSharedExtensionDefinition = (registry, definitions) => {
92
97
 
93
98
  return factory.createModuleDeclaration(
94
99
  [factory.createModifier(ts.SyntaxKind.DeclareKeyword)],
95
- factory.createStringLiteral('@strapi/types', true),
100
+ factory.createStringLiteral(MODULE_DECLARATION, true),
96
101
  factory.createModuleBlock([
97
102
  factory.createModuleDeclaration(
98
103
  [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
99
- factory.createIdentifier('Shared'),
104
+ factory.createIdentifier(PUBLIC_NAMESPACE),
100
105
  factory.createModuleBlock(
101
106
  properties.length > 0
102
107
  ? [
package/lib/index.js CHANGED
@@ -2,15 +2,12 @@
2
2
 
3
3
  const compile = require('./compile');
4
4
  const compilers = require('./compilers');
5
- const admin = require('./admin');
6
5
  const utils = require('./utils');
7
6
  const generators = require('./generators');
8
7
 
9
8
  module.exports = {
10
9
  compile,
11
10
  compilers,
12
- admin,
13
11
  generators,
14
-
15
12
  ...utils,
16
13
  };
@@ -7,6 +7,7 @@ const reportDiagnostics = require('./report-diagnostics');
7
7
  const resolveConfigOptions = require('./resolve-config-options');
8
8
  const formatHost = require('./format-host');
9
9
  const resolveOutDir = require('./resolve-outdir');
10
+ const resolveOutDirSync = require('./resolve-outdir-sync');
10
11
 
11
12
  module.exports = {
12
13
  isUsingTypeScript,
@@ -16,4 +17,5 @@ module.exports = {
16
17
  resolveConfigOptions,
17
18
  formatHost,
18
19
  resolveOutDir,
20
+ resolveOutDirSync,
19
21
  };
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const resolveConfigOptions = require('./resolve-config-options');
5
+ const isUsingTypescriptSync = require('./is-using-typescript-sync');
6
+
7
+ const DEFAULT_TS_CONFIG_FILENAME = 'tsconfig.json';
8
+ /**
9
+ * Gets the outDir value from config file (tsconfig)
10
+ * @param {string} dir
11
+ * @param {string | undefined} configFilename
12
+ * @returns {string | undefined}
13
+ */
14
+ module.exports = (dir, configFilename = DEFAULT_TS_CONFIG_FILENAME) => {
15
+ return isUsingTypescriptSync(dir)
16
+ ? resolveConfigOptions(path.join(dir, configFilename)).options.outDir
17
+ : undefined;
18
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/typescript-utils",
3
- "version": "0.0.0-next.f8af92b375dc730ba47ed2117f25df893aae696c",
3
+ "version": "0.0.0-next.f93d6eabe52aa7681655cfa08eedbc3708dbb90d",
4
4
  "description": "Typescript support for Strapi",
5
5
  "keywords": [
6
6
  "strapi",
@@ -36,15 +36,17 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "chalk": "4.1.2",
39
- "cli-table3": "0.6.2",
40
- "fs-extra": "10.0.0",
39
+ "cli-table3": "0.6.5",
40
+ "fs-extra": "11.2.0",
41
41
  "lodash": "4.17.21",
42
- "prettier": "2.8.4",
43
- "typescript": "5.2.2"
42
+ "prettier": "3.3.3",
43
+ "typescript": "5.4.4"
44
+ },
45
+ "devDependencies": {
46
+ "@types/fs-extra": "11.0.4"
44
47
  },
45
48
  "engines": {
46
- "node": ">=18.0.0 <=20.x.x",
49
+ "node": ">=18.0.0 <=22.x.x",
47
50
  "npm": ">=6.0.0"
48
- },
49
- "gitHead": "f8af92b375dc730ba47ed2117f25df893aae696c"
51
+ }
50
52
  }
@@ -11,6 +11,7 @@
11
11
  "skipLibCheck": true,
12
12
  "forceConsistentCasingInFileNames": true,
13
13
 
14
+ "tsBuildInfoFile": "./.tsbuildinfo",
14
15
  "incremental": true,
15
16
  "esModuleInterop": true,
16
17
  "resolveJsonModule": true,
@@ -1,23 +0,0 @@
1
- 'use strict';
2
-
3
- const path = require('path');
4
- const fs = require('fs-extra');
5
- const adminTsConfig = require('../../tsconfigs/admin.json');
6
-
7
- module.exports = async (dest) => {
8
- const tsConfig = {
9
- ...adminTsConfig,
10
- include: ['../../../src/admin/*', '../../../src/**/**/admin/src/*'],
11
- exclude: ['node_modules', '**/*.test.js', '*.js'],
12
- };
13
-
14
- const filePath = path.join(dest, 'admin', 'src', 'tsconfig.json');
15
-
16
- try {
17
- await fs.ensureFile(filePath);
18
-
19
- await fs.writeJSON(filePath, tsConfig, { spaces: 2 });
20
- } catch (err) {
21
- console.log(err);
22
- }
23
- };
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- const createTSConfigFile = require('./create-tsconfig-file');
4
-
5
- module.exports = { createTSConfigFile };