prismic-ts-codegen 0.0.2 → 0.0.5

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/src/cli/types.ts CHANGED
@@ -1,29 +1,159 @@
1
+ /**
2
+ * Configuration to control the generated types.
3
+ */
1
4
  export type Config = {
5
+ /**
6
+ * The name of the Prismic repository.
7
+ */
2
8
  repositoryName?: string;
9
+
10
+ /**
11
+ * The access token for the Prismic repository. If the repository is private
12
+ * and `locales.fetchFromRepository` is `true`, providing a token is required.
13
+ */
3
14
  accessToken?: string;
15
+
16
+ /**
17
+ * The Custom Types API token for the Prismic repository. If
18
+ * `models.fetchFromRepository` is `true`, providing a token is required.
19
+ */
4
20
  customTypesAPIToken?: string;
5
21
 
22
+ /**
23
+ * The file path where the generated types will be saved. This path is
24
+ * relative to where the command is called.
25
+ */
6
26
  output?: string;
7
27
 
28
+ /**
29
+ * Configuration for automatic `@prismicio/client` integration.
30
+ */
31
+ clientIntegration?: {
32
+ /**
33
+ * Determines if a `@prismicio/client` integration with automatic typing
34
+ * should be included in the output.
35
+ *
36
+ * If set to `true`, Prismic clients will automatically be typed with the
37
+ * generated Custom Types and Slices.
38
+ *
39
+ * **Note**: If your project queries content from multiple Prismic
40
+ * repositories, set `includeCreateClientInterface` to `false` and manually
41
+ * provide the generated `AllDocumentTypes` type to `@prismicio/client`'s
42
+ * `createClient()` function instead.
43
+ *
44
+ * @defaultValue `true`
45
+ */
46
+ includeCreateClientInterface?: boolean;
47
+ };
48
+
49
+ /**
50
+ * Configuration for languages for the Prismic repository.
51
+ *
52
+ * It can be configured by providing an array of locale IDs configured for the
53
+ * repository or an object with finer control.
54
+ *
55
+ * @example
56
+ *
57
+ * ```ts
58
+ * ["en-us", "fr-fr"];
59
+ * ```
60
+ *
61
+ * @example
62
+ *
63
+ * ```ts
64
+ * {
65
+ * "ids": ["en-us", "fr-fr"],
66
+ * "fetchFromRepository": true
67
+ * }
68
+ * ```
69
+ */
8
70
  locales?:
9
71
  | string[]
10
72
  | {
73
+ /**
74
+ * A list of locales configured for the Prismic repository. This is used
75
+ * to type a document's `lang` property.
76
+ *
77
+ * @example
78
+ *
79
+ * ```ts
80
+ * ["en-us", "fr-fr"];
81
+ * ```
82
+ */
11
83
  ids?: string[];
84
+
85
+ /**
86
+ * Determines if the Prismic repository's locales should be fetched from
87
+ * the repository's API.
88
+ */
12
89
  fetchFromRepository?: boolean;
13
90
  };
14
91
 
92
+ /**
93
+ * Configuration for Custom Type and Slice models for the Prismic repository.
94
+ *
95
+ * It can be configured by providing an array of file paths to Custom Type and
96
+ * Slice JSON models or an object with finer control.
97
+ */
15
98
  models?:
16
99
  | string[]
17
100
  | {
101
+ /**
102
+ * A list of file paths to Custom Type and Slice models. Globs are supported.
103
+ */
18
104
  files?: string[];
105
+
106
+ /**
107
+ * Determines if the Prismic repository's Custom Type and Slice models
108
+ * should be fetched from the repository's API.
109
+ *
110
+ * `customTypesAPIToken` must be provided if set to `true`.
111
+ */
19
112
  fetchFromRepository?: boolean;
20
113
  };
21
114
 
115
+ /**
116
+ * Configuration for types generated for fields.
117
+ */
22
118
  fields?: {
119
+ /**
120
+ * Configuration for Embed fields.
121
+ */
23
122
  embed?: {
123
+ /**
124
+ * An object mapping oEmbed providers to their type. The type should be
125
+ * provided as a string and is added directly into the generated types.
126
+ *
127
+ * @example
128
+ *
129
+ * ```ts
130
+ * {
131
+ * "YouTube": "import('./types').OEmbedYouTube"
132
+ * "Twitter": "import('./types').OEmbedTwitter"
133
+ * "Vimeo": "import('./types').OEmbedVimeo"
134
+ * }
135
+ * ```
136
+ */
24
137
  providerTypes?: Record<string, string>;
25
138
  };
139
+
140
+ /**
141
+ * Configuration for Integration Fields.
142
+ */
26
143
  integrationFields?: {
144
+ /**
145
+ * An object mapping catalog IDs to their type. The type should be
146
+ * provided as a string and is added directly into the generated types.
147
+ *
148
+ * @example
149
+ *
150
+ * ```ts
151
+ * {
152
+ * "shopify_products": "import('./types').IntegrationFieldShopifyProduct"
153
+ * "mux_videos": "import('./types').IntegrationFieldMuxVideo"
154
+ * }
155
+ * ```
156
+ */
27
157
  catalogTypes?: Record<string, string>;
28
158
  };
29
159
  };
@@ -1,4 +1,4 @@
1
- import { Project } from "ts-morph";
1
+ import { Project, ModuleDeclarationKind } from "ts-morph";
2
2
  import type { CustomTypeModel, SharedSliceModel } from "@prismicio/types";
3
3
 
4
4
  import { BLANK_LINE_IDENTIFIER, NON_EDITABLE_FILE_HEADER } from "./constants";
@@ -6,12 +6,16 @@ import { addTypeAliasForCustomType } from "./lib/addTypeAliasForCustomType";
6
6
  import { addTypeAliasForSharedSlice } from "./lib/addTypeAliasForSharedSlice";
7
7
  import { getSourceFileText } from "./lib/getSourceFileText";
8
8
  import { FieldConfigs } from "./types";
9
+ import { pascalCase } from "./lib/pascalCase";
9
10
 
10
11
  export type GenerateTypesConfig = {
11
12
  customTypeModels?: CustomTypeModel[];
12
13
  sharedSliceModels?: SharedSliceModel[];
13
14
  localeIDs?: string[];
14
15
  fieldConfigs?: FieldConfigs;
16
+ clientIntegration?: {
17
+ includeCreateClientInterface?: boolean;
18
+ };
15
19
  };
16
20
 
17
21
  export const generateTypes = (config: GenerateTypesConfig = {}) => {
@@ -49,6 +53,18 @@ export const generateTypes = (config: GenerateTypesConfig = {}) => {
49
53
  fieldConfigs: config.fieldConfigs || {},
50
54
  });
51
55
  }
56
+
57
+ if (config.customTypeModels.length > 0) {
58
+ sourceFile.addTypeAlias({
59
+ name: "AllDocumentTypes",
60
+ type: config.customTypeModels
61
+ .map((customTypeModel) =>
62
+ pascalCase(`${customTypeModel.id} Document`),
63
+ )
64
+ .join(" | "),
65
+ isExported: true,
66
+ });
67
+ }
52
68
  }
53
69
 
54
70
  if (config.sharedSliceModels) {
@@ -61,5 +77,42 @@ export const generateTypes = (config: GenerateTypesConfig = {}) => {
61
77
  }
62
78
  }
63
79
 
80
+ if (config.clientIntegration?.includeCreateClientInterface) {
81
+ sourceFile.addImportDeclaration({
82
+ moduleSpecifier: "@prismicio/client",
83
+ namespaceImport: "prismic",
84
+ isTypeOnly: true,
85
+ });
86
+
87
+ const clientModuleDeclaration = sourceFile.addModule({
88
+ name: '"@prismicio/client"',
89
+ hasDeclareKeyword: true,
90
+ declarationKind: ModuleDeclarationKind.Module,
91
+ });
92
+
93
+ clientModuleDeclaration.addInterface({
94
+ name: "CreateClient",
95
+ callSignatures: [
96
+ {
97
+ parameters: [
98
+ {
99
+ name: "repositoryNameOrEndpoint",
100
+ type: "string",
101
+ },
102
+ {
103
+ name: "options",
104
+ type: "prismic.ClientConfig",
105
+ hasQuestionToken: true,
106
+ },
107
+ ],
108
+ returnType:
109
+ (config.customTypeModels?.length || 0) > 0
110
+ ? "prismic.Client<AllDocumentTypes>"
111
+ : "prismic.Client",
112
+ },
113
+ ],
114
+ });
115
+ }
116
+
64
117
  return getSourceFileText(sourceFile);
65
118
  };
@@ -23,12 +23,13 @@ type AddInterfacePropertyFromFieldConfig = {
23
23
  sourceFile: SourceFile;
24
24
  path: [
25
25
  PathElement<CustomTypeModel | SharedSliceModel>,
26
- ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[]
26
+ ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[],
27
27
  ];
28
28
  fieldConfigs: FieldConfigs;
29
+ tabName?: string;
29
30
  };
30
31
 
31
- const addInterfacePropertyFromField = (
32
+ const addInterfacePropertyForField = (
32
33
  config: AddInterfacePropertyFromFieldConfig,
33
34
  ) => {
34
35
  switch (config.model.type) {
@@ -45,6 +46,7 @@ const addInterfacePropertyFromField = (
45
46
  id: config.id,
46
47
  model: config.model,
47
48
  path: config.path,
49
+ tabName: config.tabName,
48
50
  }),
49
51
  });
50
52
 
@@ -59,6 +61,7 @@ const addInterfacePropertyFromField = (
59
61
  id: config.id,
60
62
  model: config.model,
61
63
  path: config.path,
64
+ tabName: config.tabName,
62
65
  }),
63
66
  });
64
67
 
@@ -73,6 +76,7 @@ const addInterfacePropertyFromField = (
73
76
  id: config.id,
74
77
  model: config.model,
75
78
  path: config.path,
79
+ tabName: config.tabName,
76
80
  }),
77
81
  });
78
82
 
@@ -105,6 +109,7 @@ const addInterfacePropertyFromField = (
105
109
  id: config.id,
106
110
  model: config.model,
107
111
  path: config.path,
112
+ tabName: config.tabName,
108
113
  }),
109
114
  });
110
115
 
@@ -119,6 +124,7 @@ const addInterfacePropertyFromField = (
119
124
  id: config.id,
120
125
  model: config.model,
121
126
  path: config.path,
127
+ tabName: config.tabName,
122
128
  }),
123
129
  });
124
130
 
@@ -138,6 +144,7 @@ const addInterfacePropertyFromField = (
138
144
  id: config.id,
139
145
  model: config.model,
140
146
  path: config.path,
147
+ tabName: config.tabName,
141
148
  }),
142
149
  });
143
150
  } else {
@@ -148,6 +155,7 @@ const addInterfacePropertyFromField = (
148
155
  id: config.id,
149
156
  model: config.model,
150
157
  path: config.path,
158
+ tabName: config.tabName,
151
159
  }),
152
160
  });
153
161
  }
@@ -170,6 +178,7 @@ const addInterfacePropertyFromField = (
170
178
  id: config.id,
171
179
  model: config.model,
172
180
  path: config.path,
181
+ tabName: config.tabName,
173
182
  }),
174
183
  });
175
184
 
@@ -192,6 +201,7 @@ const addInterfacePropertyFromField = (
192
201
  id: config.id,
193
202
  model: config.model,
194
203
  path: config.path,
204
+ tabName: config.tabName,
195
205
  }),
196
206
  });
197
207
 
@@ -206,6 +216,7 @@ const addInterfacePropertyFromField = (
206
216
  id: config.id,
207
217
  model: config.model,
208
218
  path: config.path,
219
+ tabName: config.tabName,
209
220
  }),
210
221
  });
211
222
 
@@ -220,6 +231,7 @@ const addInterfacePropertyFromField = (
220
231
  id: config.id,
221
232
  model: config.model,
222
233
  path: config.path,
234
+ tabName: config.tabName,
223
235
  }),
224
236
  });
225
237
  }
@@ -236,6 +248,7 @@ const addInterfacePropertyFromField = (
236
248
  id: config.id,
237
249
  model: config.model,
238
250
  path: config.path,
251
+ tabName: config.tabName,
239
252
  }),
240
253
  });
241
254
 
@@ -257,6 +270,7 @@ const addInterfacePropertyFromField = (
257
270
  id: config.id,
258
271
  model: config.model,
259
272
  path: config.path,
273
+ tabName: config.tabName,
260
274
  }),
261
275
  });
262
276
  } else {
@@ -267,6 +281,7 @@ const addInterfacePropertyFromField = (
267
281
  id: config.id,
268
282
  model: config.model,
269
283
  path: config.path,
284
+ tabName: config.tabName,
270
285
  }),
271
286
  });
272
287
  }
@@ -288,6 +303,7 @@ const addInterfacePropertyFromField = (
288
303
  id: config.id,
289
304
  model: config.model,
290
305
  path: config.path,
306
+ tabName: config.tabName,
291
307
  }),
292
308
  });
293
309
  } else {
@@ -298,6 +314,7 @@ const addInterfacePropertyFromField = (
298
314
  id: config.id,
299
315
  model: config.model,
300
316
  path: config.path,
317
+ tabName: config.tabName,
301
318
  }),
302
319
  });
303
320
  }
@@ -313,6 +330,7 @@ const addInterfacePropertyFromField = (
313
330
  id: config.id,
314
331
  model: config.model,
315
332
  path: config.path,
333
+ tabName: config.tabName,
316
334
  }),
317
335
  });
318
336
 
@@ -327,6 +345,7 @@ const addInterfacePropertyFromField = (
327
345
  id: config.id,
328
346
  model: config.model,
329
347
  path: config.path,
348
+ tabName: config.tabName,
330
349
  }),
331
350
  });
332
351
 
@@ -355,6 +374,7 @@ const addInterfacePropertyFromField = (
355
374
  },
356
375
  },
357
376
  ],
377
+ isExported: true,
358
378
  });
359
379
  addInterfacePropertiesForFields({
360
380
  interface: itemInterface,
@@ -377,6 +397,7 @@ const addInterfacePropertyFromField = (
377
397
  id: config.id,
378
398
  model: config.model,
379
399
  path: config.path,
400
+ tabName: config.tabName,
380
401
  }),
381
402
  });
382
403
 
@@ -480,6 +501,7 @@ const addInterfacePropertyFromField = (
480
501
  },
481
502
  },
482
503
  ],
504
+ isExported: true,
483
505
  });
484
506
  addInterfacePropertiesForFields({
485
507
  interface: itemInterface,
@@ -515,6 +537,7 @@ const addInterfacePropertyFromField = (
515
537
  }, ${
516
538
  itemInterface ? `Simplify<${itemInterface.getName()}>` : "never"
517
539
  }>`,
540
+ isExported: true,
518
541
  });
519
542
 
520
543
  choiceInterfaceNames.push(sliceType.getName());
@@ -555,6 +578,7 @@ const addInterfacePropertyFromField = (
555
578
  id: config.id,
556
579
  model: config.model,
557
580
  path: config.path,
581
+ tabName: config.tabName,
558
582
  }),
559
583
  });
560
584
 
@@ -569,6 +593,7 @@ const addInterfacePropertyFromField = (
569
593
  id: config.id,
570
594
  model: config.model,
571
595
  path: config.path,
596
+ tabName: config.tabName,
572
597
  }),
573
598
  });
574
599
  }
@@ -580,16 +605,18 @@ type AddInterfacePropertiesForFieldsConfig = Omit<
580
605
  "id" | "model"
581
606
  > & {
582
607
  fields: Record<string, AddInterfacePropertyFromFieldConfig["model"]>;
608
+ tabName?: string;
583
609
  };
584
610
 
585
611
  export const addInterfacePropertiesForFields = (
586
612
  config: AddInterfacePropertiesForFieldsConfig,
587
613
  ) => {
588
614
  for (const name in config.fields) {
589
- addInterfacePropertyFromField({
615
+ addInterfacePropertyForField({
590
616
  ...config,
591
- id: name,
617
+ id: name.includes("-") ? `"${name}"` : name,
592
618
  model: config.fields[name],
619
+ tabName: config.tabName,
593
620
  });
594
621
  }
595
622
  };
@@ -43,18 +43,26 @@ export const addTypeAliasForCustomType = ({
43
43
  },
44
44
  ],
45
45
  });
46
- addInterfacePropertiesForFields({
47
- fields,
48
- interface: dataInterface,
49
- sourceFile: sourceFile,
50
- path: [
51
- {
52
- id: model.id,
53
- model: model,
54
- },
55
- ],
56
- fieldConfigs,
57
- });
46
+
47
+ for (const tabName in model.json) {
48
+ // This is destructured to ensure the UID field is
49
+ // ignored.
50
+ const { uid: _uidField, ...tabFields } = model.json[tabName];
51
+
52
+ addInterfacePropertiesForFields({
53
+ fields: tabFields,
54
+ interface: dataInterface,
55
+ sourceFile: sourceFile,
56
+ path: [
57
+ {
58
+ id: model.id,
59
+ model: model,
60
+ },
61
+ ],
62
+ fieldConfigs,
63
+ tabName,
64
+ });
65
+ }
58
66
  } else {
59
67
  dataInterface = sourceFile.addTypeAlias({
60
68
  name: pascalCase(`${model.id} Document Data`),
@@ -99,6 +99,7 @@ export const addTypeAliasForSharedSlice = (
99
99
  },
100
100
  },
101
101
  ],
102
+ isExported: true,
102
103
  });
103
104
  addInterfacePropertiesForFields({
104
105
  interface: itemInterface,
@@ -144,6 +145,7 @@ export const addTypeAliasForSharedSlice = (
144
145
  },
145
146
  },
146
147
  ],
148
+ isExported: true,
147
149
  });
148
150
 
149
151
  variationTypeNames.push(variationType.getName());
@@ -19,8 +19,9 @@ type BuildFieldDocsConfig = {
19
19
  model: CustomTypeModelField;
20
20
  path: [
21
21
  PathElement<CustomTypeModel | SharedSliceModel>,
22
- ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[]
22
+ ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[],
23
23
  ];
24
+ tabName?: string;
24
25
  };
25
26
 
26
27
  export const buildFieldDocs = (
@@ -63,6 +64,7 @@ export const buildFieldDocs = (
63
64
  placeholder,
64
65
  defaultValue,
65
66
  apiIDPath,
67
+ tabName: config.tabName,
66
68
  documentationURL: getFieldDocumentationURL({ model: config.model }),
67
69
  });
68
70
  },
@@ -14,7 +14,7 @@ import { isSharedSliceModel } from "./isSharedSliceModel";
14
14
  type GetAPIIDPathConfig = {
15
15
  path: [
16
16
  PathElement<CustomTypeModel | SharedSliceModel>,
17
- ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[]
17
+ ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[],
18
18
  ];
19
19
  };
20
20
 
@@ -11,7 +11,7 @@ import { getHumanReadableModelName } from "./getHumanReadableModelName";
11
11
  type GetHumanReadableFieldPathConfig = {
12
12
  path: [
13
13
  PathElement<CustomTypeModel | SharedSliceModel>,
14
- ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[]
14
+ ...PathElement<CustomTypeModelField | CustomTypeModelSlice>[],
15
15
  ];
16
16
  };
17
17
 
@@ -7,6 +7,7 @@ type BuildFieldDocsConfig = {
7
7
  defaultValue?: string | boolean;
8
8
  placeholder?: string;
9
9
  apiIDPath?: string;
10
+ tabName?: string;
10
11
  documentationURL?: string;
11
12
  };
12
13
 
@@ -40,6 +41,10 @@ export const writeFieldDocsDescription = (
40
41
  config.writer.writeLine(`- **API ID Path**: ${config.apiIDPath}`);
41
42
  }
42
43
 
44
+ if (config.tabName) {
45
+ config.writer.writeLine(`- **Tab**: ${config.tabName}`);
46
+ }
47
+
43
48
  if (config.documentationURL) {
44
49
  config.writer.writeLine(`- **Documentation**: ${config.documentationURL}`);
45
50
  }