prismic 0.0.0-pr.28.59bf330

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.
Files changed (158) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +69 -0
  3. package/dist/builders-hKD4IrLX-DsO7BUQw.mjs +97 -0
  4. package/dist/dist-B11B2hHn.mjs +1 -0
  5. package/dist/dist-DT8CtumB.mjs +1 -0
  6. package/dist/framework-CfjEoVk0.mjs +17 -0
  7. package/dist/index.mjs +2537 -0
  8. package/dist/nextjs-9z7YrSnS.mjs +312 -0
  9. package/dist/nuxt-KoJ61G2q.mjs +59 -0
  10. package/dist/sveltekit-DjXKCG78.mjs +226 -0
  11. package/package.json +58 -0
  12. package/src/codegen-types.ts +82 -0
  13. package/src/codegen.ts +45 -0
  14. package/src/custom-type-add-field-boolean.ts +185 -0
  15. package/src/custom-type-add-field-color.ts +168 -0
  16. package/src/custom-type-add-field-date.ts +171 -0
  17. package/src/custom-type-add-field-embed.ts +168 -0
  18. package/src/custom-type-add-field-geo-point.ts +165 -0
  19. package/src/custom-type-add-field-group.ts +142 -0
  20. package/src/custom-type-add-field-image.ts +168 -0
  21. package/src/custom-type-add-field-key-text.ts +168 -0
  22. package/src/custom-type-add-field-link.ts +191 -0
  23. package/src/custom-type-add-field-number.ts +200 -0
  24. package/src/custom-type-add-field-rich-text.ts +192 -0
  25. package/src/custom-type-add-field-select.ts +174 -0
  26. package/src/custom-type-add-field-timestamp.ts +171 -0
  27. package/src/custom-type-add-field-uid.ts +151 -0
  28. package/src/custom-type-add-field.ts +116 -0
  29. package/src/custom-type-connect-slice.ts +178 -0
  30. package/src/custom-type-create.ts +98 -0
  31. package/src/custom-type-disconnect-slice.ts +134 -0
  32. package/src/custom-type-list.ts +110 -0
  33. package/src/custom-type-remove-field.ts +135 -0
  34. package/src/custom-type-remove.ts +103 -0
  35. package/src/custom-type-set-name.ts +102 -0
  36. package/src/custom-type-view.ts +118 -0
  37. package/src/custom-type.ts +85 -0
  38. package/src/docs-fetch.ts +146 -0
  39. package/src/docs-list.ts +131 -0
  40. package/src/docs.ts +54 -0
  41. package/src/env.d.ts +12 -0
  42. package/src/framework/index.ts +399 -0
  43. package/src/framework/nextjs.templates.ts +426 -0
  44. package/src/framework/nextjs.ts +216 -0
  45. package/src/framework/nuxt.templates.ts +74 -0
  46. package/src/framework/nuxt.ts +250 -0
  47. package/src/framework/sveltekit.templates.ts +278 -0
  48. package/src/framework/sveltekit.ts +241 -0
  49. package/src/index.ts +155 -0
  50. package/src/init.ts +173 -0
  51. package/src/lib/auth.ts +200 -0
  52. package/src/lib/browser.ts +11 -0
  53. package/src/lib/config.ts +111 -0
  54. package/src/lib/custom-types-api.ts +385 -0
  55. package/src/lib/field-path.ts +81 -0
  56. package/src/lib/file.ts +49 -0
  57. package/src/lib/json.ts +3 -0
  58. package/src/lib/packageJson.ts +35 -0
  59. package/src/lib/profile.ts +39 -0
  60. package/src/lib/request.ts +116 -0
  61. package/src/lib/segment.ts +145 -0
  62. package/src/lib/sentry.ts +63 -0
  63. package/src/lib/string.ts +10 -0
  64. package/src/lib/url.ts +31 -0
  65. package/src/locale-add.ts +116 -0
  66. package/src/locale-list.ts +107 -0
  67. package/src/locale-remove.ts +88 -0
  68. package/src/locale-set-default.ts +131 -0
  69. package/src/locale.ts +60 -0
  70. package/src/login.ts +45 -0
  71. package/src/logout.ts +36 -0
  72. package/src/page-type-add-field-boolean.ts +179 -0
  73. package/src/page-type-add-field-color.ts +165 -0
  74. package/src/page-type-add-field-date.ts +168 -0
  75. package/src/page-type-add-field-embed.ts +165 -0
  76. package/src/page-type-add-field-geo-point.ts +162 -0
  77. package/src/page-type-add-field-group.ts +139 -0
  78. package/src/page-type-add-field-image.ts +165 -0
  79. package/src/page-type-add-field-key-text.ts +165 -0
  80. package/src/page-type-add-field-link.ts +188 -0
  81. package/src/page-type-add-field-number.ts +197 -0
  82. package/src/page-type-add-field-rich-text.ts +189 -0
  83. package/src/page-type-add-field-select.ts +171 -0
  84. package/src/page-type-add-field-timestamp.ts +168 -0
  85. package/src/page-type-add-field-uid.ts +148 -0
  86. package/src/page-type-add-field.ts +116 -0
  87. package/src/page-type-connect-slice.ts +178 -0
  88. package/src/page-type-create.ts +128 -0
  89. package/src/page-type-disconnect-slice.ts +134 -0
  90. package/src/page-type-list.ts +109 -0
  91. package/src/page-type-remove-field.ts +135 -0
  92. package/src/page-type-remove.ts +103 -0
  93. package/src/page-type-set-name.ts +102 -0
  94. package/src/page-type-set-repeatable.ts +111 -0
  95. package/src/page-type-view.ts +118 -0
  96. package/src/page-type.ts +90 -0
  97. package/src/preview-add.ts +126 -0
  98. package/src/preview-get-simulator.ts +104 -0
  99. package/src/preview-list.ts +106 -0
  100. package/src/preview-remove-simulator.ts +80 -0
  101. package/src/preview-remove.ts +109 -0
  102. package/src/preview-set-name.ts +137 -0
  103. package/src/preview-set-simulator.ts +116 -0
  104. package/src/preview.ts +75 -0
  105. package/src/pull.ts +236 -0
  106. package/src/push.ts +409 -0
  107. package/src/repo-create.ts +175 -0
  108. package/src/repo-get-access.ts +86 -0
  109. package/src/repo-list.ts +100 -0
  110. package/src/repo-set-access.ts +100 -0
  111. package/src/repo-set-name.ts +102 -0
  112. package/src/repo-view.ts +113 -0
  113. package/src/repo.ts +70 -0
  114. package/src/slice-add-field-boolean.ts +219 -0
  115. package/src/slice-add-field-color.ts +205 -0
  116. package/src/slice-add-field-date.ts +205 -0
  117. package/src/slice-add-field-embed.ts +205 -0
  118. package/src/slice-add-field-geo-point.ts +202 -0
  119. package/src/slice-add-field-group.ts +170 -0
  120. package/src/slice-add-field-image.ts +202 -0
  121. package/src/slice-add-field-key-text.ts +205 -0
  122. package/src/slice-add-field-link.ts +224 -0
  123. package/src/slice-add-field-number.ts +205 -0
  124. package/src/slice-add-field-rich-text.ts +229 -0
  125. package/src/slice-add-field-select.ts +211 -0
  126. package/src/slice-add-field-timestamp.ts +205 -0
  127. package/src/slice-add-field.ts +111 -0
  128. package/src/slice-add-variation.ts +142 -0
  129. package/src/slice-create.ts +164 -0
  130. package/src/slice-list-variations.ts +71 -0
  131. package/src/slice-list.ts +60 -0
  132. package/src/slice-remove-field.ts +125 -0
  133. package/src/slice-remove-variation.ts +113 -0
  134. package/src/slice-remove.ts +92 -0
  135. package/src/slice-rename.ts +104 -0
  136. package/src/slice-set-screenshot.ts +239 -0
  137. package/src/slice-view.ts +83 -0
  138. package/src/slice.ts +95 -0
  139. package/src/status.ts +834 -0
  140. package/src/sync.ts +259 -0
  141. package/src/token-create.ts +203 -0
  142. package/src/token-delete.ts +182 -0
  143. package/src/token-list.ts +223 -0
  144. package/src/token-set-name.ts +193 -0
  145. package/src/token.ts +60 -0
  146. package/src/webhook-add-header.ts +118 -0
  147. package/src/webhook-create.ts +152 -0
  148. package/src/webhook-disable.ts +109 -0
  149. package/src/webhook-enable.ts +132 -0
  150. package/src/webhook-list.ts +93 -0
  151. package/src/webhook-remove-header.ts +117 -0
  152. package/src/webhook-remove.ts +106 -0
  153. package/src/webhook-set-triggers.ts +148 -0
  154. package/src/webhook-status.ts +90 -0
  155. package/src/webhook-test.ts +106 -0
  156. package/src/webhook-view.ts +147 -0
  157. package/src/webhook.ts +95 -0
  158. package/src/whoami.ts +62 -0
package/src/repo.ts ADDED
@@ -0,0 +1,70 @@
1
+ import { parseArgs } from "node:util";
2
+
3
+ import { repoCreate } from "./repo-create";
4
+ import { repoGetAccess } from "./repo-get-access";
5
+ import { repoList } from "./repo-list";
6
+ import { repoSetAccess } from "./repo-set-access";
7
+ import { repoSetName } from "./repo-set-name";
8
+ import { repoView } from "./repo-view";
9
+
10
+ const HELP = `
11
+ Manage Prismic repositories.
12
+
13
+ USAGE
14
+ prismic repo <command> [flags]
15
+
16
+ COMMANDS
17
+ create Create a new Prismic repository
18
+ list List all repositories
19
+ view View repository details
20
+ get-access Get Content API access level
21
+ set-access Set Content API access level
22
+ set-name Set repository display name
23
+
24
+ FLAGS
25
+ -h, --help Show help for command
26
+
27
+ LEARN MORE
28
+ Use \`prismic repo <command> --help\` for more information about a command.
29
+ `.trim();
30
+
31
+ export async function repo(): Promise<void> {
32
+ const {
33
+ positionals: [subcommand],
34
+ } = parseArgs({
35
+ args: process.argv.slice(3), // skip: node, script, "repo"
36
+ options: {
37
+ help: { type: "boolean", short: "h" },
38
+ },
39
+ allowPositionals: true,
40
+ strict: false,
41
+ });
42
+
43
+ switch (subcommand) {
44
+ case "create":
45
+ await repoCreate();
46
+ break;
47
+ case "list":
48
+ await repoList();
49
+ break;
50
+ case "view":
51
+ await repoView();
52
+ break;
53
+ case "get-access":
54
+ await repoGetAccess();
55
+ break;
56
+ case "set-access":
57
+ await repoSetAccess();
58
+ break;
59
+ case "set-name":
60
+ await repoSetName();
61
+ break;
62
+ default: {
63
+ if (subcommand) {
64
+ console.error(`Unknown repo subcommand: ${subcommand}\n`);
65
+ process.exitCode = 1;
66
+ }
67
+ console.info(HELP);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,219 @@
1
+ import type { BooleanField, SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ import { buildTypes } from "./codegen-types";
6
+ import { findGroupInVariation, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
7
+ import { getDocsPath, getWriteComponentsAnchor, requireFramework } from "./framework";
8
+ import { humanReadable } from "./lib/string";
9
+
10
+ const HELP = `
11
+ Add a boolean (toggle) field to an existing slice.
12
+
13
+ USAGE
14
+ prismic slice add-field boolean <slice-id> <field-id> [flags]
15
+
16
+ ARGUMENTS
17
+ slice-id Slice identifier (required)
18
+ field-id Field identifier (required)
19
+
20
+ FLAGS
21
+ -v, --variation string Target variation (default: first variation)
22
+ -l, --label string Display label for the field (inferred from field-id if omitted)
23
+ --default Set default value to true
24
+ --true-label string Label shown when toggle is on
25
+ --false-label string Label shown when toggle is off
26
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
27
+ -h, --help Show help for command
28
+
29
+ EXAMPLES
30
+ prismic slice add-field boolean my_slice featured
31
+ prismic slice add-field boolean hero show_overlay --default
32
+ prismic slice add-field boolean product available --true-label "In Stock" --false-label "Out of Stock"
33
+ `.trim();
34
+
35
+
36
+
37
+ export async function sliceAddFieldBoolean(): Promise<void> {
38
+ const {
39
+ values: {
40
+ help,
41
+ variation,
42
+ label,
43
+ default: defaultValue,
44
+ "true-label": trueLabel,
45
+ "false-label": falseLabel,
46
+ types,
47
+ },
48
+ positionals: [sliceId, fieldId],
49
+ } = parseArgs({
50
+ args: process.argv.slice(5), // skip: node, script, "slice", "add-field", "boolean"
51
+ options: {
52
+ variation: { type: "string", short: "v" },
53
+ label: { type: "string", short: "l" },
54
+ default: { type: "boolean" },
55
+ "true-label": { type: "string" },
56
+ "false-label": { type: "string" },
57
+ types: { type: "string" },
58
+ help: { type: "boolean", short: "h" },
59
+ },
60
+ allowPositionals: true,
61
+ });
62
+
63
+ if (help) {
64
+ console.info(HELP);
65
+ return;
66
+ }
67
+
68
+ if (!sliceId) {
69
+ console.error("Missing required argument: slice-id\n");
70
+ console.error("Usage: prismic slice add-field boolean <slice-id> <field-id>");
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+
75
+ if (!fieldId) {
76
+ console.error("Missing required argument: field-id\n");
77
+ console.error("Usage: prismic slice add-field boolean <slice-id> <field-id>");
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+
82
+ // Parse and validate field path
83
+ const fieldPath = parseFieldPath(fieldId);
84
+ const pathValidation = validateNestedFieldPath(fieldPath);
85
+ if (!pathValidation.ok) {
86
+ console.error(pathValidation.error);
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+
91
+ // Find the slice model
92
+ const framework = await requireFramework();
93
+ if (!framework) return;
94
+
95
+ let model: SharedSlice;
96
+ try {
97
+ model = await framework.readSlice(sliceId);
98
+ } catch {
99
+ console.error(`Slice not found: ${sliceId}\n\nCreate it first with: prismic slice create ${sliceId}`);
100
+ process.exitCode = 1;
101
+ return;
102
+ }
103
+
104
+ // Check for variations
105
+ if (model.variations.length === 0) {
106
+ console.error(`Slice "${sliceId}" has no variations.\n`);
107
+ console.error("Add a variation first before adding fields.");
108
+ process.exitCode = 1;
109
+ return;
110
+ }
111
+
112
+ // Find target variation
113
+ const targetVariation = variation
114
+ ? model.variations.find((v) => v.id === variation)
115
+ : model.variations[0];
116
+
117
+ if (!targetVariation) {
118
+ console.error(`Variation "${variation}" not found in slice "${sliceId}"\n`);
119
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
120
+ process.exitCode = 1;
121
+ return;
122
+ }
123
+
124
+ // Initialize primary if it doesn't exist
125
+ if (!targetVariation.primary) {
126
+ targetVariation.primary = {};
127
+ }
128
+
129
+ // Build field definition
130
+ const fieldDefinition: BooleanField = {
131
+ type: "Boolean",
132
+ config: {
133
+ label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
134
+ ...(defaultValue && { default_value: true }),
135
+ ...(trueLabel && { placeholder_true: trueLabel }),
136
+ ...(falseLabel && { placeholder_false: falseLabel }),
137
+ },
138
+ };
139
+
140
+ // Add field to variation (with nested field support)
141
+ if (fieldPath.type === "nested") {
142
+ const groupResult = findGroupInVariation(targetVariation.primary, fieldPath.groupId, targetVariation.id);
143
+ if (!groupResult.ok) {
144
+ console.error(groupResult.error);
145
+ process.exitCode = 1;
146
+ return;
147
+ }
148
+ // Check if nested field already exists
149
+ if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
150
+ console.error(
151
+ `Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`,
152
+ );
153
+ process.exitCode = 1;
154
+ return;
155
+ }
156
+ groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
157
+ } else {
158
+ // Check if field already exists in any variation (at top level or in groups)
159
+ for (const v of model.variations) {
160
+ if (v.primary?.[fieldId]) {
161
+ console.error(`Field "${fieldId}" already exists in variation "${v.id}"`);
162
+ process.exitCode = 1;
163
+ return;
164
+ }
165
+ // Also check inside groups
166
+ for (const [groupFieldId, groupField] of Object.entries(v.primary ?? {})) {
167
+ if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
168
+ console.error(
169
+ `Field "${fieldId}" already exists in group "${groupFieldId}" in variation "${v.id}"`,
170
+ );
171
+ process.exitCode = 1;
172
+ return;
173
+ }
174
+ }
175
+ }
176
+ targetVariation.primary[fieldId] = fieldDefinition;
177
+ }
178
+
179
+ // Write updated model
180
+ try {
181
+ await framework.updateSlice(model);
182
+ } catch (error) {
183
+ if (error instanceof Error) {
184
+ console.error(`Failed to update slice: ${error.message}`);
185
+ } else {
186
+ console.error("Failed to update slice");
187
+ }
188
+ process.exitCode = 1;
189
+ return;
190
+ }
191
+
192
+ if (fieldPath.type === "nested") {
193
+ console.info(
194
+ `Added field "${fieldPath.nestedFieldId}" (Boolean) to group "${fieldPath.groupId}" in ${sliceId}`,
195
+ );
196
+ } else {
197
+ console.info(
198
+ `Added field "${fieldId}" (Boolean) to "${targetVariation.id}" variation in ${sliceId}`,
199
+ );
200
+ }
201
+
202
+ try {
203
+ await buildTypes({ output: types });
204
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
205
+ } catch (error) {
206
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
207
+ }
208
+
209
+ console.info();
210
+ console.info("Next: Add more fields with `prismic slice add-field`");
211
+
212
+ if (framework) {
213
+ const docsPath = getDocsPath(framework.id);
214
+ const anchor = getWriteComponentsAnchor(framework.id);
215
+ console.info(
216
+ ` Run \`prismic docs fetch ${docsPath}${anchor}\` to learn how to implement the slice's component`,
217
+ );
218
+ }
219
+ }
@@ -0,0 +1,205 @@
1
+ import type { Color, SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ import { buildTypes } from "./codegen-types";
6
+ import { findGroupInVariation, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
7
+ import { getDocsPath, getWriteComponentsAnchor, requireFramework } from "./framework";
8
+ import { humanReadable } from "./lib/string";
9
+
10
+ const HELP = `
11
+ Add a color picker field to an existing slice.
12
+
13
+ USAGE
14
+ prismic slice add-field color <slice-id> <field-id> [flags]
15
+
16
+ ARGUMENTS
17
+ slice-id Slice identifier (required)
18
+ field-id Field identifier (required)
19
+
20
+ FLAGS
21
+ -v, --variation string Target variation (default: first variation)
22
+ -l, --label string Display label for the field (inferred from field-id if omitted)
23
+ -p, --placeholder string Placeholder text
24
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
25
+ -h, --help Show help for command
26
+
27
+ EXAMPLES
28
+ prismic slice add-field color my_slice background_color
29
+ prismic slice add-field color hero accent --label "Accent Color"
30
+ prismic slice add-field color banner theme_color --variation "dark"
31
+ `.trim();
32
+
33
+
34
+
35
+ export async function sliceAddFieldColor(): Promise<void> {
36
+ const {
37
+ values: { help, variation, label, placeholder, types },
38
+ positionals: [sliceId, fieldId],
39
+ } = parseArgs({
40
+ args: process.argv.slice(5), // skip: node, script, "slice", "add-field", "color"
41
+ options: {
42
+ variation: { type: "string", short: "v" },
43
+ label: { type: "string", short: "l" },
44
+ placeholder: { type: "string", short: "p" },
45
+ types: { type: "string" },
46
+ help: { type: "boolean", short: "h" },
47
+ },
48
+ allowPositionals: true,
49
+ });
50
+
51
+ if (help) {
52
+ console.info(HELP);
53
+ return;
54
+ }
55
+
56
+ if (!sliceId) {
57
+ console.error("Missing required argument: slice-id\n");
58
+ console.error("Usage: prismic slice add-field color <slice-id> <field-id>");
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+
63
+ if (!fieldId) {
64
+ console.error("Missing required argument: field-id\n");
65
+ console.error("Usage: prismic slice add-field color <slice-id> <field-id>");
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+
70
+ // Parse and validate field path
71
+ const fieldPath = parseFieldPath(fieldId);
72
+ const pathValidation = validateNestedFieldPath(fieldPath);
73
+ if (!pathValidation.ok) {
74
+ console.error(pathValidation.error);
75
+ process.exitCode = 1;
76
+ return;
77
+ }
78
+
79
+ // Find the slice model
80
+ const framework = await requireFramework();
81
+ if (!framework) return;
82
+
83
+ let model: SharedSlice;
84
+ try {
85
+ model = await framework.readSlice(sliceId);
86
+ } catch {
87
+ console.error(`Slice not found: ${sliceId}\n\nCreate it first with: prismic slice create ${sliceId}`);
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+
92
+ // Check for variations
93
+ if (model.variations.length === 0) {
94
+ console.error(`Slice "${sliceId}" has no variations.\n`);
95
+ console.error("Add a variation first before adding fields.");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+
100
+ // Find target variation
101
+ const targetVariation = variation
102
+ ? model.variations.find((v) => v.id === variation)
103
+ : model.variations[0];
104
+
105
+ if (!targetVariation) {
106
+ console.error(`Variation "${variation}" not found in slice "${sliceId}"\n`);
107
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
108
+ process.exitCode = 1;
109
+ return;
110
+ }
111
+
112
+ // Initialize primary if it doesn't exist
113
+ if (!targetVariation.primary) {
114
+ targetVariation.primary = {};
115
+ }
116
+
117
+ // Build field definition
118
+ const fieldDefinition: Color = {
119
+ type: "Color",
120
+ config: {
121
+ label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
122
+ ...(placeholder && { placeholder }),
123
+ },
124
+ };
125
+
126
+ // Add field to variation (with nested field support)
127
+ if (fieldPath.type === "nested") {
128
+ const groupResult = findGroupInVariation(targetVariation.primary, fieldPath.groupId, targetVariation.id);
129
+ if (!groupResult.ok) {
130
+ console.error(groupResult.error);
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+ // Check if nested field already exists
135
+ if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
136
+ console.error(
137
+ `Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`,
138
+ );
139
+ process.exitCode = 1;
140
+ return;
141
+ }
142
+ groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
143
+ } else {
144
+ // Check if field already exists in any variation (at top level or in groups)
145
+ for (const v of model.variations) {
146
+ if (v.primary?.[fieldId]) {
147
+ console.error(`Field "${fieldId}" already exists in variation "${v.id}"`);
148
+ process.exitCode = 1;
149
+ return;
150
+ }
151
+ // Also check inside groups
152
+ for (const [groupFieldId, groupField] of Object.entries(v.primary ?? {})) {
153
+ if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
154
+ console.error(
155
+ `Field "${fieldId}" already exists in group "${groupFieldId}" in variation "${v.id}"`,
156
+ );
157
+ process.exitCode = 1;
158
+ return;
159
+ }
160
+ }
161
+ }
162
+ targetVariation.primary[fieldId] = fieldDefinition;
163
+ }
164
+
165
+ // Write updated model
166
+ try {
167
+ await framework.updateSlice(model);
168
+ } catch (error) {
169
+ if (error instanceof Error) {
170
+ console.error(`Failed to update slice: ${error.message}`);
171
+ } else {
172
+ console.error("Failed to update slice");
173
+ }
174
+ process.exitCode = 1;
175
+ return;
176
+ }
177
+
178
+ if (fieldPath.type === "nested") {
179
+ console.info(
180
+ `Added field "${fieldPath.nestedFieldId}" (Color) to group "${fieldPath.groupId}" in ${sliceId}`,
181
+ );
182
+ } else {
183
+ console.info(
184
+ `Added field "${fieldId}" (Color) to "${targetVariation.id}" variation in ${sliceId}`,
185
+ );
186
+ }
187
+
188
+ try {
189
+ await buildTypes({ output: types });
190
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
191
+ } catch (error) {
192
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
193
+ }
194
+
195
+ console.info();
196
+ console.info("Next: Add more fields with `prismic slice add-field`");
197
+
198
+ if (framework) {
199
+ const docsPath = getDocsPath(framework.id);
200
+ const anchor = getWriteComponentsAnchor(framework.id);
201
+ console.info(
202
+ ` Run \`prismic docs fetch ${docsPath}${anchor}\` to learn how to implement the slice's component`,
203
+ );
204
+ }
205
+ }
@@ -0,0 +1,205 @@
1
+ import type { Date as DateField, SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ import { buildTypes } from "./codegen-types";
6
+ import { findGroupInVariation, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
7
+ import { getDocsPath, getWriteComponentsAnchor, requireFramework } from "./framework";
8
+ import { humanReadable } from "./lib/string";
9
+
10
+ const HELP = `
11
+ Add a date picker field to an existing slice.
12
+
13
+ USAGE
14
+ prismic slice add-field date <slice-id> <field-id> [flags]
15
+
16
+ ARGUMENTS
17
+ slice-id Slice identifier (required)
18
+ field-id Field identifier (required)
19
+
20
+ FLAGS
21
+ -v, --variation string Target variation (default: first variation)
22
+ -l, --label string Display label for the field (inferred from field-id if omitted)
23
+ -p, --placeholder string Placeholder text
24
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
25
+ -h, --help Show help for command
26
+
27
+ EXAMPLES
28
+ prismic slice add-field date my_slice publish_date
29
+ prismic slice add-field date event start_date --label "Start Date"
30
+ prismic slice add-field date promo end_date --variation "countdown"
31
+ `.trim();
32
+
33
+
34
+
35
+ export async function sliceAddFieldDate(): Promise<void> {
36
+ const {
37
+ values: { help, variation, label, placeholder, types },
38
+ positionals: [sliceId, fieldId],
39
+ } = parseArgs({
40
+ args: process.argv.slice(5), // skip: node, script, "slice", "add-field", "date"
41
+ options: {
42
+ variation: { type: "string", short: "v" },
43
+ label: { type: "string", short: "l" },
44
+ placeholder: { type: "string", short: "p" },
45
+ types: { type: "string" },
46
+ help: { type: "boolean", short: "h" },
47
+ },
48
+ allowPositionals: true,
49
+ });
50
+
51
+ if (help) {
52
+ console.info(HELP);
53
+ return;
54
+ }
55
+
56
+ if (!sliceId) {
57
+ console.error("Missing required argument: slice-id\n");
58
+ console.error("Usage: prismic slice add-field date <slice-id> <field-id>");
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+
63
+ if (!fieldId) {
64
+ console.error("Missing required argument: field-id\n");
65
+ console.error("Usage: prismic slice add-field date <slice-id> <field-id>");
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+
70
+ // Parse and validate field path
71
+ const fieldPath = parseFieldPath(fieldId);
72
+ const pathValidation = validateNestedFieldPath(fieldPath);
73
+ if (!pathValidation.ok) {
74
+ console.error(pathValidation.error);
75
+ process.exitCode = 1;
76
+ return;
77
+ }
78
+
79
+ // Find the slice model
80
+ const framework = await requireFramework();
81
+ if (!framework) return;
82
+
83
+ let model: SharedSlice;
84
+ try {
85
+ model = await framework.readSlice(sliceId);
86
+ } catch {
87
+ console.error(`Slice not found: ${sliceId}\n\nCreate it first with: prismic slice create ${sliceId}`);
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+
92
+ // Check for variations
93
+ if (model.variations.length === 0) {
94
+ console.error(`Slice "${sliceId}" has no variations.\n`);
95
+ console.error("Add a variation first before adding fields.");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+
100
+ // Find target variation
101
+ const targetVariation = variation
102
+ ? model.variations.find((v) => v.id === variation)
103
+ : model.variations[0];
104
+
105
+ if (!targetVariation) {
106
+ console.error(`Variation "${variation}" not found in slice "${sliceId}"\n`);
107
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
108
+ process.exitCode = 1;
109
+ return;
110
+ }
111
+
112
+ // Initialize primary if it doesn't exist
113
+ if (!targetVariation.primary) {
114
+ targetVariation.primary = {};
115
+ }
116
+
117
+ // Build field definition
118
+ const fieldDefinition: DateField = {
119
+ type: "Date",
120
+ config: {
121
+ label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
122
+ ...(placeholder && { placeholder }),
123
+ },
124
+ };
125
+
126
+ // Add field to variation (with nested field support)
127
+ if (fieldPath.type === "nested") {
128
+ const groupResult = findGroupInVariation(targetVariation.primary, fieldPath.groupId, targetVariation.id);
129
+ if (!groupResult.ok) {
130
+ console.error(groupResult.error);
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+ // Check if nested field already exists
135
+ if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
136
+ console.error(
137
+ `Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`,
138
+ );
139
+ process.exitCode = 1;
140
+ return;
141
+ }
142
+ groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
143
+ } else {
144
+ // Check if field already exists in any variation (at top level or in groups)
145
+ for (const v of model.variations) {
146
+ if (v.primary?.[fieldId]) {
147
+ console.error(`Field "${fieldId}" already exists in variation "${v.id}"`);
148
+ process.exitCode = 1;
149
+ return;
150
+ }
151
+ // Also check inside groups
152
+ for (const [groupFieldId, groupField] of Object.entries(v.primary ?? {})) {
153
+ if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
154
+ console.error(
155
+ `Field "${fieldId}" already exists in group "${groupFieldId}" in variation "${v.id}"`,
156
+ );
157
+ process.exitCode = 1;
158
+ return;
159
+ }
160
+ }
161
+ }
162
+ targetVariation.primary[fieldId] = fieldDefinition;
163
+ }
164
+
165
+ // Write updated model
166
+ try {
167
+ await framework.updateSlice(model);
168
+ } catch (error) {
169
+ if (error instanceof Error) {
170
+ console.error(`Failed to update slice: ${error.message}`);
171
+ } else {
172
+ console.error("Failed to update slice");
173
+ }
174
+ process.exitCode = 1;
175
+ return;
176
+ }
177
+
178
+ if (fieldPath.type === "nested") {
179
+ console.info(
180
+ `Added field "${fieldPath.nestedFieldId}" (Date) to group "${fieldPath.groupId}" in ${sliceId}`,
181
+ );
182
+ } else {
183
+ console.info(
184
+ `Added field "${fieldId}" (Date) to "${targetVariation.id}" variation in ${sliceId}`,
185
+ );
186
+ }
187
+
188
+ try {
189
+ await buildTypes({ output: types });
190
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
191
+ } catch (error) {
192
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
193
+ }
194
+
195
+ console.info();
196
+ console.info("Next: Add more fields with `prismic slice add-field`");
197
+
198
+ if (framework) {
199
+ const docsPath = getDocsPath(framework.id);
200
+ const anchor = getWriteComponentsAnchor(framework.id);
201
+ console.info(
202
+ ` Run \`prismic docs fetch ${docsPath}${anchor}\` to learn how to implement the slice's component`,
203
+ );
204
+ }
205
+ }