prismic-ts-codegen 0.0.2

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/dist/index.js ADDED
@@ -0,0 +1,937 @@
1
+ import { Project } from 'ts-morph';
2
+ import { stripIndent } from 'common-tags';
3
+ import { pascalCase as pascalCase$1, pascalCaseTransformMerge } from 'pascal-case';
4
+
5
+ const BLANK_LINE_IDENTIFIER = "// ___BLANK_LINE_TO_BE_REPLACED___";
6
+ const NON_EDITABLE_FILE_HEADER = stripIndent`
7
+ // Code generated by prismic-ts-codegen. DO NOT EDIT.
8
+ ${BLANK_LINE_IDENTIFIER}
9
+ `;
10
+ const CUSTOM_TYPES_DOCUMENTATION_URL = "https://prismic.io/docs/core-concepts/custom-types";
11
+ const SHARED_SLICES_DOCUMENTATION_URL = "https://prismic.io/docs/core-concepts/reusing-slices";
12
+ const FIELD_DOCUMENTATION_URLS = {
13
+ UID: "https://prismic.io/docs/core-concepts/uid",
14
+ Boolean: "https://prismic.io/docs/core-concepts/boolean",
15
+ Color: "https://prismic.io/docs/core-concepts/color",
16
+ Date: "https://prismic.io/docs/core-concepts/date",
17
+ Timestamp: "https://prismic.io/docs/core-concepts/timestamp",
18
+ Number: "https://prismic.io/docs/core-concepts/number",
19
+ Text: "https://prismic.io/docs/core-concepts/key-text",
20
+ Select: "https://prismic.io/docs/core-concepts/select",
21
+ StructuredText: "https://prismic.io/docs/core-concepts/rich-text-title",
22
+ Image: "https://prismic.io/docs/core-concepts/image",
23
+ Link: "https://prismic.io/docs/core-concepts/link-content-relationship",
24
+ Embed: "https://prismic.io/docs/core-concepts/embed",
25
+ GeoPoint: "https://prismic.io/docs/core-concepts/geopoint",
26
+ Group: "https://prismic.io/docs/core-concepts/group",
27
+ IntegrationFields: "https://prismic.io/docs/core-concepts/integration-fields",
28
+ Slices: "https://prismic.io/docs/core-concepts/slices"
29
+ };
30
+
31
+ const CustomTypeModelFieldType = {
32
+ Boolean: "Boolean",
33
+ Color: "Color",
34
+ Date: "Date",
35
+ Embed: "Embed",
36
+ GeoPoint: "GeoPoint",
37
+ Group: "Group",
38
+ Image: "Image",
39
+ IntegrationFields: "IntegrationFields",
40
+ Link: "Link",
41
+ Number: "Number",
42
+ Select: "Select",
43
+ Slices: "Slices",
44
+ StructuredText: "StructuredText",
45
+ Text: "Text",
46
+ Timestamp: "Timestamp",
47
+ UID: "UID"
48
+ };
49
+ const CustomTypeModelLinkSelectType = {
50
+ Document: "document",
51
+ Media: "media"
52
+ };
53
+ const CustomTypeModelSliceType = {
54
+ Slice: "Slice",
55
+ SharedSlice: "SharedSlice"
56
+ };
57
+
58
+ const isCustomTypeModelField = (model) => {
59
+ return typeof model === "object" && model !== null && "type" in model && "config" in model;
60
+ };
61
+
62
+ const isCustomTypeModelSlice = (model) => {
63
+ return typeof model === "object" && model !== null && "non-repeat" in model && "repeat" in model;
64
+ };
65
+
66
+ const isSharedSliceModel = (model) => {
67
+ return typeof model === "object" && model !== null && "variations" in model;
68
+ };
69
+
70
+ const getAPIIDPath = (config) => {
71
+ return config.path.map((element, i) => {
72
+ if (isCustomTypeModelField(element.model) && (element.model.type === CustomTypeModelFieldType.Group || element.model.type === CustomTypeModelFieldType.Slices)) {
73
+ return `${element.id}[]`;
74
+ } else {
75
+ if (element.id === "items") {
76
+ const previousElement = config.path[i - 1];
77
+ if (isCustomTypeModelSlice(previousElement.model) || isSharedSliceModel(previousElement.model)) {
78
+ return `${element.id}[]`;
79
+ }
80
+ }
81
+ return element.id;
82
+ }
83
+ }).join(".");
84
+ };
85
+
86
+ const getFieldDocumentationURL = (config) => {
87
+ return FIELD_DOCUMENTATION_URLS[config.model.type];
88
+ };
89
+
90
+ const isCustomTypeModel = (model) => {
91
+ return typeof model === "object" && model !== null && "json" in model;
92
+ };
93
+
94
+ const getHumanReadableModelName = (config) => {
95
+ if (isCustomTypeModel(config.model)) {
96
+ return config.model.label;
97
+ } else if (isSharedSliceModel(config.model)) {
98
+ return config.model.name;
99
+ } else if (isCustomTypeModelField(config.model) && "label" in config.model.config) {
100
+ return config.model.config.label;
101
+ } else if (isCustomTypeModelSlice(config.model)) {
102
+ return config.model.fieldset;
103
+ } else {
104
+ return `Slice Zone (\`${config.id}\`)`;
105
+ }
106
+ };
107
+
108
+ const getHumanReadableFieldPath = (config) => {
109
+ return config.path.map((element) => {
110
+ if (element.label) {
111
+ return element.label;
112
+ } else if (element.model) {
113
+ return getHumanReadableModelName({
114
+ id: element.id,
115
+ model: element.model
116
+ });
117
+ } else {
118
+ return element.id;
119
+ }
120
+ }).join(" \u2192 ");
121
+ };
122
+
123
+ const getHumanReadableFieldType = (config) => {
124
+ switch (config.model.type) {
125
+ case "StructuredText": {
126
+ const isTitleField = "single" in config.model.config && config.model.config.single.split(",").every((blockType) => /heading/.test(blockType));
127
+ return isTitleField ? "Title" : "Rich Text";
128
+ }
129
+ case "IntegrationFields": {
130
+ return `Integration Fields (Catalog: \`${config.model.config.catalog}\`)`;
131
+ }
132
+ case "Link": {
133
+ switch (config.model.config.select) {
134
+ case CustomTypeModelLinkSelectType.Document: {
135
+ return "Content Relationship";
136
+ }
137
+ case CustomTypeModelLinkSelectType.Media: {
138
+ return "Link to Media";
139
+ }
140
+ default: {
141
+ return "Link";
142
+ }
143
+ }
144
+ }
145
+ case "Slices": {
146
+ return "Slice Zone";
147
+ }
148
+ default: {
149
+ return config.model.type;
150
+ }
151
+ }
152
+ };
153
+
154
+ const writeFieldDocsDescription = (config) => {
155
+ if (config.description) {
156
+ config.writer.writeLine(config.description);
157
+ }
158
+ config.writer.blankLineIfLastNot();
159
+ if (config.fieldType) {
160
+ config.writer.writeLine(`- **Field Type**: ${config.fieldType}`);
161
+ }
162
+ if (config.placeholder) {
163
+ config.writer.writeLine(`- **Placeholder**: ${config.placeholder}`);
164
+ }
165
+ if (config.defaultValue !== void 0) {
166
+ const stringifiedDefaultValue = typeof config.defaultValue === "boolean" ? `${config.defaultValue}` : config.defaultValue;
167
+ config.writer.writeLine(`- **Default Value**: ${stringifiedDefaultValue}`);
168
+ }
169
+ if (config.apiIDPath) {
170
+ config.writer.writeLine(`- **API ID Path**: ${config.apiIDPath}`);
171
+ }
172
+ if (config.documentationURL) {
173
+ config.writer.writeLine(`- **Documentation**: ${config.documentationURL}`);
174
+ }
175
+ };
176
+
177
+ const buildFieldDocs = (config) => {
178
+ return [
179
+ {
180
+ description: (writer) => {
181
+ const name = getHumanReadableModelName({
182
+ id: config.id,
183
+ model: config.model
184
+ });
185
+ const humanReadablePath = getHumanReadableFieldPath({
186
+ path: config.path
187
+ });
188
+ const fieldType = getHumanReadableFieldType({
189
+ model: config.model
190
+ });
191
+ const placeholder = "placeholder" in config.model.config && config.model.config.placeholder ? config.model.config.placeholder : `*None*`;
192
+ const defaultValue = "default_value" in config.model.config ? config.model.config.default_value : void 0;
193
+ const apiIDPath = getAPIIDPath({
194
+ path: [...config.path, { id: config.id, model: config.model }]
195
+ });
196
+ writeFieldDocsDescription({
197
+ writer,
198
+ description: `${name} field in *${humanReadablePath}*`,
199
+ fieldType,
200
+ placeholder,
201
+ defaultValue,
202
+ apiIDPath,
203
+ documentationURL: getFieldDocumentationURL({ model: config.model })
204
+ });
205
+ }
206
+ }
207
+ ];
208
+ };
209
+
210
+ const pascalCase = (input) => pascalCase$1(input, {
211
+ transform: pascalCaseTransformMerge
212
+ });
213
+
214
+ const buildSharedSliceInterfaceName = (config) => {
215
+ return pascalCase(`${config.id} Slice`);
216
+ };
217
+
218
+ const addInterfacePropertyFromField = (config) => {
219
+ switch (config.model.type) {
220
+ case "UID": {
221
+ break;
222
+ }
223
+ case "Boolean": {
224
+ config.interface.addProperty({
225
+ name: config.id,
226
+ type: "prismicT.BooleanField",
227
+ docs: buildFieldDocs({
228
+ id: config.id,
229
+ model: config.model,
230
+ path: config.path
231
+ })
232
+ });
233
+ break;
234
+ }
235
+ case "Color": {
236
+ config.interface.addProperty({
237
+ name: config.id,
238
+ type: "prismicT.ColorField",
239
+ docs: buildFieldDocs({
240
+ id: config.id,
241
+ model: config.model,
242
+ path: config.path
243
+ })
244
+ });
245
+ break;
246
+ }
247
+ case "Date": {
248
+ config.interface.addProperty({
249
+ name: config.id,
250
+ type: "prismicT.DateField",
251
+ docs: buildFieldDocs({
252
+ id: config.id,
253
+ model: config.model,
254
+ path: config.path
255
+ })
256
+ });
257
+ break;
258
+ }
259
+ case "Embed": {
260
+ const providerTypes = [];
261
+ if (config.fieldConfigs.embed?.providerTypes) {
262
+ for (const providerType in config.fieldConfigs.embed?.providerTypes) {
263
+ const configuredProviderType = config.fieldConfigs.embed?.providerTypes[providerType];
264
+ providerTypes.push(`({ provider_name: "${providerType}" } & ${configuredProviderType})`);
265
+ }
266
+ }
267
+ config.interface.addProperty({
268
+ name: config.id,
269
+ type: providerTypes.length > 0 ? `prismicT.EmbedField<prismicT.AnyOEmbed & prismicT.OEmbedExtra & (${providerTypes.join(" | ")})>` : "prismicT.EmbedField",
270
+ docs: buildFieldDocs({
271
+ id: config.id,
272
+ model: config.model,
273
+ path: config.path
274
+ })
275
+ });
276
+ break;
277
+ }
278
+ case "GeoPoint": {
279
+ config.interface.addProperty({
280
+ name: config.id,
281
+ type: "prismicT.GeoPointField",
282
+ docs: buildFieldDocs({
283
+ id: config.id,
284
+ model: config.model,
285
+ path: config.path
286
+ })
287
+ });
288
+ break;
289
+ }
290
+ case "Image": {
291
+ if (config.model.config.thumbnails.length > 0) {
292
+ const thumbnailNames = config.model.config.thumbnails.map((thumbnail) => `"${thumbnail.name}"`).join(" | ");
293
+ config.interface.addProperty({
294
+ name: config.id,
295
+ type: `prismicT.ImageField<${thumbnailNames}>`,
296
+ docs: buildFieldDocs({
297
+ id: config.id,
298
+ model: config.model,
299
+ path: config.path
300
+ })
301
+ });
302
+ } else {
303
+ config.interface.addProperty({
304
+ name: config.id,
305
+ type: "prismicT.ImageField<null>",
306
+ docs: buildFieldDocs({
307
+ id: config.id,
308
+ model: config.model,
309
+ path: config.path
310
+ })
311
+ });
312
+ }
313
+ break;
314
+ }
315
+ case "IntegrationFields": {
316
+ const catalogType = config.fieldConfigs.integrationFields?.catalogTypes?.[config.model.config.catalog];
317
+ config.interface.addProperty({
318
+ name: config.id,
319
+ type: catalogType ? `prismicT.IntegrationFields<${catalogType}>` : "prismicT.IntegrationFields",
320
+ docs: buildFieldDocs({
321
+ id: config.id,
322
+ model: config.model,
323
+ path: config.path
324
+ })
325
+ });
326
+ break;
327
+ }
328
+ case "Link": {
329
+ switch (config.model.config.select) {
330
+ case CustomTypeModelLinkSelectType.Document: {
331
+ config.interface.addProperty({
332
+ name: config.id,
333
+ type: config.model.config.customtypes && config.model.config.customtypes.length > 0 ? `prismicT.RelationField<${config.model.config.customtypes.map((type) => `"${type}"`).join(" | ")}>` : "prismicT.RelationField",
334
+ docs: buildFieldDocs({
335
+ id: config.id,
336
+ model: config.model,
337
+ path: config.path
338
+ })
339
+ });
340
+ break;
341
+ }
342
+ case CustomTypeModelLinkSelectType.Media: {
343
+ config.interface.addProperty({
344
+ name: config.id,
345
+ type: "prismicT.LinkToMediaField",
346
+ docs: buildFieldDocs({
347
+ id: config.id,
348
+ model: config.model,
349
+ path: config.path
350
+ })
351
+ });
352
+ break;
353
+ }
354
+ default: {
355
+ config.interface.addProperty({
356
+ name: config.id,
357
+ type: "prismicT.LinkField",
358
+ docs: buildFieldDocs({
359
+ id: config.id,
360
+ model: config.model,
361
+ path: config.path
362
+ })
363
+ });
364
+ }
365
+ }
366
+ break;
367
+ }
368
+ case "Number": {
369
+ config.interface.addProperty({
370
+ name: config.id,
371
+ type: "prismicT.NumberField",
372
+ docs: buildFieldDocs({
373
+ id: config.id,
374
+ model: config.model,
375
+ path: config.path
376
+ })
377
+ });
378
+ break;
379
+ }
380
+ case "StructuredText": {
381
+ const isTitleField = "single" in config.model.config && config.model.config.single.split(",").every((blockType) => /heading/.test(blockType));
382
+ if (isTitleField) {
383
+ config.interface.addProperty({
384
+ name: config.id,
385
+ type: "prismicT.TitleField",
386
+ docs: buildFieldDocs({
387
+ id: config.id,
388
+ model: config.model,
389
+ path: config.path
390
+ })
391
+ });
392
+ } else {
393
+ config.interface.addProperty({
394
+ name: config.id,
395
+ type: "prismicT.RichTextField",
396
+ docs: buildFieldDocs({
397
+ id: config.id,
398
+ model: config.model,
399
+ path: config.path
400
+ })
401
+ });
402
+ }
403
+ break;
404
+ }
405
+ case "Select": {
406
+ const options = config.model.config.options.map((option) => `"${option}"`).join(" | ");
407
+ const hasDefault = Boolean(config.model.config.default_value);
408
+ if (hasDefault) {
409
+ config.interface.addProperty({
410
+ name: config.id,
411
+ type: `prismicT.SelectField<${options}, "filled">`,
412
+ docs: buildFieldDocs({
413
+ id: config.id,
414
+ model: config.model,
415
+ path: config.path
416
+ })
417
+ });
418
+ } else {
419
+ config.interface.addProperty({
420
+ name: config.id,
421
+ type: `prismicT.SelectField<${options}>`,
422
+ docs: buildFieldDocs({
423
+ id: config.id,
424
+ model: config.model,
425
+ path: config.path
426
+ })
427
+ });
428
+ }
429
+ break;
430
+ }
431
+ case "Text": {
432
+ config.interface.addProperty({
433
+ name: config.id,
434
+ type: "prismicT.KeyTextField",
435
+ docs: buildFieldDocs({
436
+ id: config.id,
437
+ model: config.model,
438
+ path: config.path
439
+ })
440
+ });
441
+ break;
442
+ }
443
+ case "Timestamp": {
444
+ config.interface.addProperty({
445
+ name: config.id,
446
+ type: "prismicT.TimestampField",
447
+ docs: buildFieldDocs({
448
+ id: config.id,
449
+ model: config.model,
450
+ path: config.path
451
+ })
452
+ });
453
+ break;
454
+ }
455
+ case "Group": {
456
+ const itemInterface = config.sourceFile.addInterface({
457
+ name: pascalCase(`${config.path[0].id} Document Data ${config.id} Item`),
458
+ docs: [
459
+ {
460
+ description: (writer) => {
461
+ const humanReadablePath = getHumanReadableFieldPath({
462
+ path: [
463
+ ...config.path,
464
+ {
465
+ id: config.id,
466
+ model: config.model
467
+ }
468
+ ]
469
+ });
470
+ writer.writeLine(`Item in ${humanReadablePath}`);
471
+ }
472
+ }
473
+ ]
474
+ });
475
+ addInterfacePropertiesForFields({
476
+ interface: itemInterface,
477
+ sourceFile: config.sourceFile,
478
+ fields: config.model.config.fields,
479
+ path: [
480
+ ...config.path,
481
+ {
482
+ id: config.id,
483
+ model: config.model
484
+ }
485
+ ],
486
+ fieldConfigs: config.fieldConfigs
487
+ });
488
+ config.interface.addProperty({
489
+ name: config.id,
490
+ type: `prismicT.GroupField<Simplify<${itemInterface.getName()}>>`,
491
+ docs: buildFieldDocs({
492
+ id: config.id,
493
+ model: config.model,
494
+ path: config.path
495
+ })
496
+ });
497
+ break;
498
+ }
499
+ case "Slices": {
500
+ const choiceInterfaceNames = [];
501
+ for (const choiceId in config.model.config.choices) {
502
+ const choice = config.model.config.choices[choiceId];
503
+ if (choice.type === CustomTypeModelSliceType.SharedSlice) {
504
+ choiceInterfaceNames.push(buildSharedSliceInterfaceName({ id: choiceId }));
505
+ } else if (choice.type === CustomTypeModelSliceType.Slice) {
506
+ let primaryInterface;
507
+ if (Object.keys(choice["non-repeat"]).length > 0) {
508
+ primaryInterface = config.sourceFile.addInterface({
509
+ name: pascalCase(`${config.path[0].id} Document Data ${config.id} ${choiceId} Slice Primary`),
510
+ docs: [
511
+ {
512
+ description: (writer) => {
513
+ const humanReadablePath = getHumanReadableFieldPath({
514
+ path: [
515
+ ...config.path,
516
+ {
517
+ id: config.id,
518
+ model: config.model
519
+ },
520
+ {
521
+ id: choiceId,
522
+ model: choice
523
+ },
524
+ {
525
+ id: "primary",
526
+ label: "Primary"
527
+ }
528
+ ]
529
+ });
530
+ writer.writeLine(`Primary content in ${humanReadablePath}`);
531
+ }
532
+ }
533
+ ]
534
+ });
535
+ addInterfacePropertiesForFields({
536
+ interface: primaryInterface,
537
+ sourceFile: config.sourceFile,
538
+ fields: choice["non-repeat"],
539
+ path: [
540
+ ...config.path,
541
+ {
542
+ id: config.id,
543
+ model: config.model
544
+ },
545
+ {
546
+ id: choiceId,
547
+ model: choice
548
+ },
549
+ {
550
+ id: "primary",
551
+ label: "Primary"
552
+ }
553
+ ],
554
+ fieldConfigs: config.fieldConfigs
555
+ });
556
+ }
557
+ let itemInterface;
558
+ if (Object.keys(choice.repeat).length > 0) {
559
+ itemInterface = config.sourceFile.addInterface({
560
+ name: pascalCase(`${config.path[0].id} Document Data ${config.id} ${choiceId} Slice Item`),
561
+ docs: [
562
+ {
563
+ description: (writer) => {
564
+ const humanReadablePath = getHumanReadableFieldPath({
565
+ path: [
566
+ ...config.path,
567
+ {
568
+ id: config.id,
569
+ model: config.model
570
+ },
571
+ {
572
+ id: choiceId,
573
+ model: choice
574
+ },
575
+ {
576
+ id: "items",
577
+ label: "Items"
578
+ }
579
+ ]
580
+ });
581
+ writer.writeLine(`Item in ${humanReadablePath}`);
582
+ }
583
+ }
584
+ ]
585
+ });
586
+ addInterfacePropertiesForFields({
587
+ interface: itemInterface,
588
+ sourceFile: config.sourceFile,
589
+ fields: choice.repeat,
590
+ path: [
591
+ ...config.path,
592
+ {
593
+ id: config.id,
594
+ model: config.model
595
+ },
596
+ {
597
+ id: choiceId,
598
+ model: choice
599
+ },
600
+ {
601
+ id: "items",
602
+ label: "Items"
603
+ }
604
+ ],
605
+ fieldConfigs: config.fieldConfigs
606
+ });
607
+ }
608
+ const sliceType = config.sourceFile.addTypeAlias({
609
+ name: pascalCase(`${config.path[0].id} Document Data ${config.id} ${choiceId} Slice`),
610
+ type: `prismicT.Slice<"${choiceId}", ${primaryInterface ? `Simplify<${primaryInterface.getName()}>` : "Record<string, never>"}, ${itemInterface ? `Simplify<${itemInterface.getName()}>` : "never"}>`
611
+ });
612
+ choiceInterfaceNames.push(sliceType.getName());
613
+ }
614
+ }
615
+ const slicesType = config.sourceFile.addTypeAlias({
616
+ name: pascalCase(`${config.path[0].id} Document Data ${config.id} Slice`),
617
+ type: choiceInterfaceNames.length > 0 ? choiceInterfaceNames.join(" | ") : "never",
618
+ docs: [
619
+ {
620
+ description: (writer) => {
621
+ const humanReadablePath = getHumanReadableFieldPath({
622
+ path: [
623
+ ...config.path,
624
+ {
625
+ id: config.id,
626
+ model: config.model
627
+ }
628
+ ]
629
+ });
630
+ writer.writeLine(`Slice for *${humanReadablePath}*`);
631
+ }
632
+ }
633
+ ]
634
+ });
635
+ config.interface.addProperty({
636
+ name: config.id,
637
+ type: `prismicT.SliceZone<${slicesType.getName()}>`,
638
+ docs: buildFieldDocs({
639
+ id: config.id,
640
+ model: config.model,
641
+ path: config.path
642
+ })
643
+ });
644
+ break;
645
+ }
646
+ default: {
647
+ config.interface.addProperty({
648
+ name: config.id,
649
+ type: "unknown",
650
+ docs: buildFieldDocs({
651
+ id: config.id,
652
+ model: config.model,
653
+ path: config.path
654
+ })
655
+ });
656
+ }
657
+ }
658
+ };
659
+ const addInterfacePropertiesForFields = (config) => {
660
+ for (const name in config.fields) {
661
+ addInterfacePropertyFromField({
662
+ ...config,
663
+ id: name,
664
+ model: config.fields[name]
665
+ });
666
+ }
667
+ };
668
+
669
+ const collectCustomTypeFields = (model) => {
670
+ return Object.assign({}, ...Object.values(model.json));
671
+ };
672
+ const addTypeAliasForCustomType = ({
673
+ model,
674
+ sourceFile,
675
+ localeIDs,
676
+ fieldConfigs
677
+ }) => {
678
+ const { uid: uidField, ...fields } = collectCustomTypeFields(model);
679
+ const hasDataFields = Object.keys(fields).length > 0;
680
+ const hasUIDField = Boolean(uidField);
681
+ let dataInterface;
682
+ if (hasDataFields) {
683
+ dataInterface = sourceFile.addInterface({
684
+ name: pascalCase(`${model.id} Document Data`),
685
+ docs: [
686
+ {
687
+ description: `Content for ${model.label} documents`
688
+ }
689
+ ]
690
+ });
691
+ addInterfacePropertiesForFields({
692
+ fields,
693
+ interface: dataInterface,
694
+ sourceFile,
695
+ path: [
696
+ {
697
+ id: model.id,
698
+ model
699
+ }
700
+ ],
701
+ fieldConfigs
702
+ });
703
+ } else {
704
+ dataInterface = sourceFile.addTypeAlias({
705
+ name: pascalCase(`${model.id} Document Data`),
706
+ type: `Record<string, never>`,
707
+ docs: [
708
+ {
709
+ description: `Content for ${model.label} documents`
710
+ }
711
+ ]
712
+ });
713
+ }
714
+ return sourceFile.addTypeAlias({
715
+ name: pascalCase(`${model.id} Document`),
716
+ typeParameters: [
717
+ {
718
+ name: "Lang",
719
+ constraint: "string",
720
+ default: localeIDs.length > 0 ? localeIDs.map((localeID) => `"${localeID}"`).join(" | ") : "string"
721
+ }
722
+ ],
723
+ type: hasUIDField ? `prismicT.PrismicDocumentWithUID<Simplify<${dataInterface.getName()}>, "${model.id}", Lang>` : `prismicT.PrismicDocumentWithoutUID<Simplify<${dataInterface.getName()}>, "${model.id}", Lang>`,
724
+ docs: [
725
+ {
726
+ description: (writer) => {
727
+ writer.writeLine(`${model.label} document from Prismic`);
728
+ writer.blankLine();
729
+ writer.writeLine(`- **API ID**: \`${model.id}\``);
730
+ writer.writeLine(`- **Repeatable**: \`${model.repeatable}\``);
731
+ writer.writeLine(`- **Documentation**: ${CUSTOM_TYPES_DOCUMENTATION_URL}`);
732
+ },
733
+ tags: [
734
+ {
735
+ tagName: "typeParam",
736
+ text: "Lang - Language API ID of the document."
737
+ }
738
+ ]
739
+ }
740
+ ],
741
+ isExported: true
742
+ });
743
+ };
744
+
745
+ const addTypeAliasForSharedSlice = (config) => {
746
+ const variationTypeNames = [];
747
+ for (const variation of config.model.variations) {
748
+ let primaryInterface;
749
+ if (Object.keys(variation.primary).length > 0) {
750
+ primaryInterface = config.sourceFile.addInterface({
751
+ name: pascalCase(`${buildSharedSliceInterfaceName({ id: config.model.id })} ${variation.id} Primary`),
752
+ docs: [
753
+ {
754
+ description: (writer) => {
755
+ const humanReadablePath = getHumanReadableFieldPath({
756
+ path: [
757
+ {
758
+ id: config.model.id,
759
+ model: config.model
760
+ },
761
+ {
762
+ id: "primary",
763
+ label: "Primary"
764
+ }
765
+ ]
766
+ });
767
+ writer.writeLine(`Primary content in ${humanReadablePath}`);
768
+ }
769
+ }
770
+ ]
771
+ });
772
+ addInterfacePropertiesForFields({
773
+ interface: primaryInterface,
774
+ sourceFile: config.sourceFile,
775
+ fields: variation.primary,
776
+ path: [
777
+ {
778
+ id: config.model.id,
779
+ model: config.model
780
+ },
781
+ {
782
+ id: "primary",
783
+ label: "Primary"
784
+ }
785
+ ],
786
+ fieldConfigs: config.fieldConfigs
787
+ });
788
+ }
789
+ let itemInterface;
790
+ if (Object.keys(variation.items).length > 0) {
791
+ itemInterface = config.sourceFile.addInterface({
792
+ name: pascalCase(`${buildSharedSliceInterfaceName({ id: config.model.id })} ${variation.id} Item`),
793
+ docs: [
794
+ {
795
+ description: (writer) => {
796
+ const humanReadablePath = getHumanReadableFieldPath({
797
+ path: [
798
+ {
799
+ id: config.model.id,
800
+ model: config.model
801
+ },
802
+ {
803
+ id: "items",
804
+ label: "Items"
805
+ }
806
+ ]
807
+ });
808
+ writer.writeLine(`Item in ${humanReadablePath}`);
809
+ }
810
+ }
811
+ ]
812
+ });
813
+ addInterfacePropertiesForFields({
814
+ interface: itemInterface,
815
+ sourceFile: config.sourceFile,
816
+ fields: variation.items,
817
+ path: [
818
+ {
819
+ id: config.model.id,
820
+ model: config.model
821
+ },
822
+ {
823
+ id: "items",
824
+ label: "Items"
825
+ }
826
+ ],
827
+ fieldConfigs: config.fieldConfigs
828
+ });
829
+ }
830
+ const variationType = config.sourceFile.addTypeAlias({
831
+ name: pascalCase(`${buildSharedSliceInterfaceName({
832
+ id: config.model.id
833
+ })} ${variation.id}`),
834
+ type: `prismicT.SharedSliceVariation<"${variation.id}", ${primaryInterface ? `Simplify<${primaryInterface.getName()}>` : "Record<string, never>"}, ${itemInterface ? `Simplify<${itemInterface.getName()}>` : "never"}>`,
835
+ docs: [
836
+ {
837
+ description: (writer) => {
838
+ writer.writeLine(`${variation.name} variation for ${config.model.name} Slice`);
839
+ writer.blankLine();
840
+ writer.writeLine(`- **API ID**: \`${variation.id}\``);
841
+ writer.writeLine(`- **Description**: \`${variation.description}\``);
842
+ writer.writeLine(`- **Documentation**: ${SHARED_SLICES_DOCUMENTATION_URL}`);
843
+ }
844
+ }
845
+ ]
846
+ });
847
+ variationTypeNames.push(variationType.getName());
848
+ }
849
+ const variationsType = config.sourceFile.addTypeAlias({
850
+ name: pascalCase(`${config.model.id} Slice Variation`),
851
+ type: variationTypeNames.length > 0 ? variationTypeNames.join(" | ") : "never",
852
+ docs: [
853
+ {
854
+ description: (writer) => {
855
+ const humanReadablePath = getHumanReadableFieldPath({
856
+ path: [
857
+ {
858
+ id: config.model.id,
859
+ model: config.model
860
+ }
861
+ ]
862
+ });
863
+ writer.writeLine(`Slice variation for *${humanReadablePath}*`);
864
+ }
865
+ }
866
+ ]
867
+ });
868
+ return config.sourceFile.addTypeAlias({
869
+ name: pascalCase(buildSharedSliceInterfaceName({
870
+ id: config.model.id
871
+ })),
872
+ type: `prismicT.SharedSlice<"${config.model.id}", ${variationsType.getName()}>`,
873
+ docs: [
874
+ {
875
+ description: (writer) => {
876
+ writer.writeLine(`${config.model.name} Shared Slice`);
877
+ writer.blankLine();
878
+ writer.writeLine(`- **API ID**: \`${config.model.id}\``);
879
+ writer.writeLine(`- **Description**: \`${config.model.description}\``);
880
+ writer.writeLine(`- **Documentation**: ${SHARED_SLICES_DOCUMENTATION_URL}`);
881
+ }
882
+ }
883
+ ],
884
+ isExported: true
885
+ });
886
+ };
887
+
888
+ const getSourceFileText = (sourceFile) => {
889
+ const text = sourceFile.print().replace(new RegExp(BLANK_LINE_IDENTIFIER, "g"), "");
890
+ return text;
891
+ };
892
+
893
+ const generateTypes = (config = {}) => {
894
+ const project = new Project({
895
+ useInMemoryFileSystem: true
896
+ });
897
+ const sourceFile = project.createSourceFile("types.d.ts");
898
+ sourceFile.addImportDeclaration({
899
+ moduleSpecifier: "@prismicio/types",
900
+ namespaceImport: "prismicT",
901
+ isTypeOnly: true,
902
+ leadingTrivia: NON_EDITABLE_FILE_HEADER
903
+ });
904
+ sourceFile.addStatements(BLANK_LINE_IDENTIFIER);
905
+ sourceFile.addTypeAlias({
906
+ name: "Simplify",
907
+ typeParameters: [
908
+ {
909
+ name: "T"
910
+ }
911
+ ],
912
+ type: `{ [KeyType in keyof T]: T[KeyType] }`
913
+ });
914
+ if (config.customTypeModels) {
915
+ for (const model of config.customTypeModels) {
916
+ addTypeAliasForCustomType({
917
+ model,
918
+ sourceFile,
919
+ localeIDs: config.localeIDs || [],
920
+ fieldConfigs: config.fieldConfigs || {}
921
+ });
922
+ }
923
+ }
924
+ if (config.sharedSliceModels) {
925
+ for (const model of config.sharedSliceModels) {
926
+ addTypeAliasForSharedSlice({
927
+ model,
928
+ sourceFile,
929
+ fieldConfigs: config.fieldConfigs || {}
930
+ });
931
+ }
932
+ }
933
+ return getSourceFileText(sourceFile);
934
+ };
935
+
936
+ export { generateTypes };
937
+ //# sourceMappingURL=index.js.map