@angeloashmore/prismic-cli-poc 0.0.0-canary.1d36cd8

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 (131) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +98 -0
  3. package/dist/index.mjs +2548 -0
  4. package/package.json +53 -0
  5. package/src/codegen-types.ts +82 -0
  6. package/src/codegen.ts +45 -0
  7. package/src/custom-type-add-field-boolean.ts +192 -0
  8. package/src/custom-type-add-field-color.ts +177 -0
  9. package/src/custom-type-add-field-date.ts +180 -0
  10. package/src/custom-type-add-field-embed.ts +177 -0
  11. package/src/custom-type-add-field-geo-point.ts +174 -0
  12. package/src/custom-type-add-field-image.ts +177 -0
  13. package/src/custom-type-add-field-key-text.ts +177 -0
  14. package/src/custom-type-add-field-link.ts +201 -0
  15. package/src/custom-type-add-field-number.ts +209 -0
  16. package/src/custom-type-add-field-rich-text.ts +202 -0
  17. package/src/custom-type-add-field-select.ts +192 -0
  18. package/src/custom-type-add-field-timestamp.ts +180 -0
  19. package/src/custom-type-add-field-uid.ts +177 -0
  20. package/src/custom-type-add-field.ts +111 -0
  21. package/src/custom-type-connect-slice.ts +220 -0
  22. package/src/custom-type-create.ts +118 -0
  23. package/src/custom-type-disconnect-slice.ts +177 -0
  24. package/src/custom-type-list.ts +110 -0
  25. package/src/custom-type-remove-field.ts +177 -0
  26. package/src/custom-type-remove.ts +144 -0
  27. package/src/custom-type-set-name.ts +144 -0
  28. package/src/custom-type-view.ts +118 -0
  29. package/src/custom-type.ts +85 -0
  30. package/src/index.ts +127 -0
  31. package/src/init.ts +64 -0
  32. package/src/lib/auth.ts +83 -0
  33. package/src/lib/config.ts +111 -0
  34. package/src/lib/custom-types-api.ts +438 -0
  35. package/src/lib/file.ts +49 -0
  36. package/src/lib/framework.ts +143 -0
  37. package/src/lib/json.ts +3 -0
  38. package/src/lib/request.ts +116 -0
  39. package/src/lib/slice.ts +115 -0
  40. package/src/lib/string.ts +6 -0
  41. package/src/lib/url.ts +25 -0
  42. package/src/locale-add.ts +116 -0
  43. package/src/locale-list.ts +107 -0
  44. package/src/locale-remove.ts +88 -0
  45. package/src/locale-set-default.ts +131 -0
  46. package/src/locale.ts +60 -0
  47. package/src/login.ts +152 -0
  48. package/src/logout.ts +36 -0
  49. package/src/page-type-add-field-boolean.ts +192 -0
  50. package/src/page-type-add-field-color.ts +177 -0
  51. package/src/page-type-add-field-date.ts +180 -0
  52. package/src/page-type-add-field-embed.ts +177 -0
  53. package/src/page-type-add-field-geo-point.ts +174 -0
  54. package/src/page-type-add-field-image.ts +177 -0
  55. package/src/page-type-add-field-key-text.ts +177 -0
  56. package/src/page-type-add-field-link.ts +201 -0
  57. package/src/page-type-add-field-number.ts +209 -0
  58. package/src/page-type-add-field-rich-text.ts +202 -0
  59. package/src/page-type-add-field-select.ts +192 -0
  60. package/src/page-type-add-field-timestamp.ts +180 -0
  61. package/src/page-type-add-field-uid.ts +177 -0
  62. package/src/page-type-add-field.ts +111 -0
  63. package/src/page-type-connect-slice.ts +220 -0
  64. package/src/page-type-create.ts +142 -0
  65. package/src/page-type-disconnect-slice.ts +177 -0
  66. package/src/page-type-list.ts +109 -0
  67. package/src/page-type-remove-field.ts +177 -0
  68. package/src/page-type-remove.ts +144 -0
  69. package/src/page-type-set-name.ts +144 -0
  70. package/src/page-type-set-repeatable.ts +153 -0
  71. package/src/page-type-view.ts +118 -0
  72. package/src/page-type.ts +90 -0
  73. package/src/preview-add.ts +126 -0
  74. package/src/preview-get-simulator.ts +104 -0
  75. package/src/preview-list.ts +106 -0
  76. package/src/preview-remove-simulator.ts +80 -0
  77. package/src/preview-remove.ts +109 -0
  78. package/src/preview-set-name.ts +137 -0
  79. package/src/preview-set-simulator.ts +116 -0
  80. package/src/preview.ts +75 -0
  81. package/src/pull.ts +247 -0
  82. package/src/push.ts +405 -0
  83. package/src/repo-create.ts +136 -0
  84. package/src/repo-get-access.ts +86 -0
  85. package/src/repo-list.ts +100 -0
  86. package/src/repo-set-access.ts +100 -0
  87. package/src/repo-set-name.ts +102 -0
  88. package/src/repo-view.ts +113 -0
  89. package/src/repo.ts +70 -0
  90. package/src/slice-add-field-boolean.ts +173 -0
  91. package/src/slice-add-field-color.ts +158 -0
  92. package/src/slice-add-field-date.ts +158 -0
  93. package/src/slice-add-field-embed.ts +158 -0
  94. package/src/slice-add-field-geo-point.ts +155 -0
  95. package/src/slice-add-field-image.ts +155 -0
  96. package/src/slice-add-field-key-text.ts +158 -0
  97. package/src/slice-add-field-link.ts +178 -0
  98. package/src/slice-add-field-number.ts +158 -0
  99. package/src/slice-add-field-rich-text.ts +183 -0
  100. package/src/slice-add-field-select.ts +173 -0
  101. package/src/slice-add-field-timestamp.ts +158 -0
  102. package/src/slice-add-field.ts +106 -0
  103. package/src/slice-add-variation.ts +145 -0
  104. package/src/slice-create.ts +148 -0
  105. package/src/slice-list-variations.ts +67 -0
  106. package/src/slice-list.ts +88 -0
  107. package/src/slice-remove-field.ts +128 -0
  108. package/src/slice-remove-variation.ts +118 -0
  109. package/src/slice-remove.ts +97 -0
  110. package/src/slice-rename.ts +128 -0
  111. package/src/slice-view.ts +77 -0
  112. package/src/slice.ts +90 -0
  113. package/src/status.ts +733 -0
  114. package/src/token-create.ts +203 -0
  115. package/src/token-delete.ts +182 -0
  116. package/src/token-list.ts +223 -0
  117. package/src/token-set-name.ts +193 -0
  118. package/src/token.ts +60 -0
  119. package/src/webhook-add-header.ts +118 -0
  120. package/src/webhook-create.ts +152 -0
  121. package/src/webhook-disable.ts +109 -0
  122. package/src/webhook-enable.ts +132 -0
  123. package/src/webhook-list.ts +93 -0
  124. package/src/webhook-remove-header.ts +117 -0
  125. package/src/webhook-remove.ts +106 -0
  126. package/src/webhook-set-triggers.ts +148 -0
  127. package/src/webhook-status.ts +90 -0
  128. package/src/webhook-test.ts +106 -0
  129. package/src/webhook-view.ts +147 -0
  130. package/src/webhook.ts +95 -0
  131. package/src/whoami.ts +62 -0
@@ -0,0 +1,145 @@
1
+ import type { SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { writeFile } from "node:fs/promises";
4
+ import { parseArgs } from "node:util";
5
+
6
+ import { buildTypes } from "./codegen-types";
7
+ import { stringify } from "./lib/json";
8
+ import { findSliceModel, pascalCase } from "./lib/slice";
9
+
10
+ const HELP = `
11
+ Add a new variation to a slice.
12
+
13
+ USAGE
14
+ prismic slice add-variation <slice-id> <variation-id> [flags]
15
+
16
+ ARGUMENTS
17
+ slice-id Slice identifier (required)
18
+ variation-id New variation identifier (required)
19
+
20
+ Types are generated by default after changes. Use --no-types to skip.
21
+
22
+ FLAGS
23
+ --name string Display name for the variation
24
+ --copy-from string Copy fields from an existing variation
25
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
26
+ --no-types Skip type generation
27
+ -h, --help Show help for command
28
+
29
+ EXAMPLES
30
+ prismic slice add-variation MySlice withImage
31
+ prismic slice add-variation MySlice withImage --name "With Image"
32
+ prismic slice add-variation MySlice withImage --copy-from default
33
+ `.trim();
34
+
35
+ export async function sliceAddVariation(): Promise<void> {
36
+ const {
37
+ values: { help, name, "copy-from": copyFrom, types, "no-types": noTypes },
38
+ positionals: [sliceId, variationId],
39
+ } = parseArgs({
40
+ args: process.argv.slice(4), // skip: node, script, "slice", "add-variation"
41
+ options: {
42
+ name: { type: "string" },
43
+ "copy-from": { type: "string" },
44
+ types: { type: "string" },
45
+ "no-types": { type: "boolean" },
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-variation <slice-id> <variation-id>");
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+
63
+ if (!variationId) {
64
+ console.error("Missing required argument: variation-id\n");
65
+ console.error("Usage: prismic slice add-variation <slice-id> <variation-id>");
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+
70
+ const result = await findSliceModel(sliceId);
71
+ if (!result.ok) {
72
+ console.error(result.error);
73
+ process.exitCode = 1;
74
+ return;
75
+ }
76
+
77
+ const { model, modelPath } = result;
78
+
79
+ // Check if variation already exists
80
+ if (model.variations.some((v) => v.id === variationId)) {
81
+ console.error(`Variation "${variationId}" already exists in slice "${sliceId}"`);
82
+ process.exitCode = 1;
83
+ return;
84
+ }
85
+
86
+ // Build new variation
87
+ let newVariation: SharedSlice["variations"][number];
88
+
89
+ if (copyFrom) {
90
+ const sourceVariation = model.variations.find((v) => v.id === copyFrom);
91
+ if (!sourceVariation) {
92
+ console.error(`Source variation not found: ${copyFrom}`);
93
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+
98
+ newVariation = {
99
+ ...structuredClone(sourceVariation),
100
+ id: variationId,
101
+ name: name ?? pascalCase(variationId),
102
+ };
103
+ } else {
104
+ newVariation = {
105
+ id: variationId,
106
+ name: name ?? pascalCase(variationId),
107
+ description: variationId,
108
+ imageUrl: "",
109
+ docURL: "",
110
+ version: "initial",
111
+ primary: {},
112
+ items: {},
113
+ };
114
+ }
115
+
116
+ // Add variation to model
117
+ const updatedModel = {
118
+ ...model,
119
+ variations: [...model.variations, newVariation],
120
+ };
121
+
122
+ // Write updated model
123
+ try {
124
+ await writeFile(modelPath, stringify(updatedModel as SharedSlice));
125
+ } catch (error) {
126
+ if (error instanceof Error) {
127
+ console.error(`Failed to update slice: ${error.message}`);
128
+ } else {
129
+ console.error("Failed to update slice");
130
+ }
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+
135
+ console.info(`Added variation "${variationId}" to slice "${sliceId}"`);
136
+
137
+ if (!noTypes) {
138
+ try {
139
+ await buildTypes({ output: types });
140
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
141
+ } catch (error) {
142
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
143
+ }
144
+ }
145
+ }
@@ -0,0 +1,148 @@
1
+ import type { SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import { parseArgs } from "node:util";
5
+ import * as v from "valibot";
6
+
7
+ import { buildTypes } from "./codegen-types";
8
+ import { exists, findUpward } from "./lib/file";
9
+ import { stringify } from "./lib/json";
10
+
11
+ const HELP = `
12
+ Create a new slice in a Prismic project.
13
+
14
+ USAGE
15
+ prismic slice create <id> [flags]
16
+
17
+ ARGUMENTS
18
+ id Slice identifier (required)
19
+
20
+ Types are generated by default after changes. Use --no-types to skip.
21
+
22
+ FLAGS
23
+ -n, --name string Display name for the slice
24
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
25
+ --no-types Skip type generation
26
+ -h, --help Show help for command
27
+
28
+ LEARN MORE
29
+ Use \`prismic slice <command> --help\` for more information about a command.
30
+ `.trim();
31
+
32
+ export async function sliceCreate(): Promise<void> {
33
+ const {
34
+ values: { help, name, types, "no-types": noTypes },
35
+ positionals: [id],
36
+ } = parseArgs({
37
+ args: process.argv.slice(4), // skip: node, script, "slice", "create"
38
+ options: {
39
+ name: { type: "string", short: "n" },
40
+ types: { type: "string" },
41
+ "no-types": { type: "boolean" },
42
+ help: { type: "boolean", short: "h" },
43
+ },
44
+ allowPositionals: true,
45
+ });
46
+
47
+ if (help) {
48
+ console.info(HELP);
49
+ return;
50
+ }
51
+
52
+ if (!id) {
53
+ console.error("Missing required argument: id");
54
+ process.exitCode = 1;
55
+ return;
56
+ }
57
+
58
+ const model: SharedSlice = {
59
+ id,
60
+ type: "SharedSlice",
61
+ name: name ?? pascalCase(id),
62
+ description: "",
63
+ variations: [
64
+ {
65
+ id: "default",
66
+ name: "Default",
67
+ description: "Default",
68
+ imageUrl: "",
69
+ docURL: "",
70
+ version: "initial",
71
+ primary: {},
72
+ items: {},
73
+ },
74
+ ],
75
+ };
76
+
77
+ const slicesDirectory = await getSlicesDirectory();
78
+ const sliceDirectory = new URL(pascalCase(model.name) + "/", slicesDirectory);
79
+ const modelPath = new URL("model.json", sliceDirectory);
80
+
81
+ try {
82
+ await mkdir(new URL(".", modelPath), { recursive: true });
83
+ await writeFile(modelPath, stringify(model));
84
+ } catch (error) {
85
+ if (error instanceof Error) {
86
+ console.error(`Failed to create slice: ${error.message}`);
87
+ } else {
88
+ console.error(`Failed to create slice`);
89
+ }
90
+ process.exitCode = 1;
91
+ return;
92
+ }
93
+
94
+ console.info(`Created slice at ${modelPath.href}`);
95
+
96
+ if (!noTypes) {
97
+ try {
98
+ await buildTypes({ output: types });
99
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
100
+ } catch (error) {
101
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
102
+ }
103
+ }
104
+
105
+ console.info();
106
+ console.info("Next: Add fields with `prismic slice add-field`");
107
+ }
108
+
109
+ async function getSlicesDirectory(): Promise<URL> {
110
+ const framework = await detectFramework();
111
+ const projectRoot = await findUpward("package.json");
112
+ switch (framework) {
113
+ case "next": {
114
+ const hasSrcDir = await exists(new URL("src", projectRoot));
115
+ if (hasSrcDir) return new URL("src/slices/", projectRoot);
116
+ }
117
+ case "nuxt": {
118
+ const hasAppDir = await exists(new URL("app", projectRoot));
119
+ if (hasAppDir) return new URL("app/slices/", projectRoot);
120
+ }
121
+ case "sveltekit": {
122
+ return new URL("src/slices/", projectRoot);
123
+ }
124
+ }
125
+ return new URL("slices/", projectRoot);
126
+ }
127
+
128
+ const PackageJsonSchema = v.object({
129
+ dependencies: v.optional(v.record(v.string(), v.string())),
130
+ });
131
+
132
+ type Framework = "next" | "nuxt" | "sveltekit";
133
+
134
+ async function detectFramework(): Promise<Framework | undefined> {
135
+ const packageJsonPath = await findUpward("package.json");
136
+ if (!packageJsonPath) return;
137
+ try {
138
+ const contents = await readFile(packageJsonPath, "utf8");
139
+ const { dependencies = {} } = v.parse(PackageJsonSchema, JSON.parse(contents));
140
+ if ("next" in dependencies) return "next";
141
+ if ("nuxt" in dependencies) return "nuxt";
142
+ if ("@sveltejs/kit" in dependencies) return "sveltekit";
143
+ } catch {}
144
+ }
145
+
146
+ function pascalCase(input: string): string {
147
+ return input.toLowerCase().replace(/(^|[-_\s]+)(.)?/g, (_, __, c) => c?.toUpperCase() ?? "");
148
+ }
@@ -0,0 +1,67 @@
1
+ import { parseArgs } from "node:util";
2
+
3
+ import { findSliceModel } from "./lib/slice";
4
+
5
+ const HELP = `
6
+ List all variations for a slice.
7
+
8
+ USAGE
9
+ prismic slice list-variations <slice-id> [flags]
10
+
11
+ ARGUMENTS
12
+ slice-id Slice identifier (required)
13
+
14
+ FLAGS
15
+ --json Output as JSON
16
+ -h, --help Show help for command
17
+
18
+ EXAMPLES
19
+ prismic slice list-variations MySlice
20
+ prismic slice list-variations MySlice --json
21
+ `.trim();
22
+
23
+ export async function sliceListVariations(): Promise<void> {
24
+ const {
25
+ values: { help, json },
26
+ positionals: [sliceId],
27
+ } = parseArgs({
28
+ args: process.argv.slice(4), // skip: node, script, "slice", "list-variations"
29
+ options: {
30
+ json: { type: "boolean" },
31
+ help: { type: "boolean", short: "h" },
32
+ },
33
+ allowPositionals: true,
34
+ });
35
+
36
+ if (help) {
37
+ console.info(HELP);
38
+ return;
39
+ }
40
+
41
+ if (!sliceId) {
42
+ console.error("Missing required argument: slice-id\n");
43
+ console.error("Usage: prismic slice list-variations <slice-id>");
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+
48
+ const result = await findSliceModel(sliceId);
49
+ if (!result.ok) {
50
+ console.error(result.error);
51
+ process.exitCode = 1;
52
+ return;
53
+ }
54
+
55
+ const { model } = result;
56
+ const variations = model.variations.map((v) => ({ id: v.id, name: v.name }));
57
+
58
+ if (json) {
59
+ console.info(JSON.stringify(variations, null, 2));
60
+ return;
61
+ }
62
+
63
+ console.info("ID\tNAME");
64
+ for (const variation of variations) {
65
+ console.info(`${variation.id}\t${variation.name}`);
66
+ }
67
+ }
@@ -0,0 +1,88 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { parseArgs } from "node:util";
3
+ import * as v from "valibot";
4
+
5
+ import { getSlicesDirectory, SharedSliceSchema } from "./lib/slice";
6
+
7
+ const HELP = `
8
+ List all slices in a Prismic project.
9
+
10
+ USAGE
11
+ prismic slice list [flags]
12
+
13
+ FLAGS
14
+ --json Output as JSON
15
+ -h, --help Show help for command
16
+
17
+ EXAMPLES
18
+ prismic slice list
19
+ prismic slice list --json
20
+ `.trim();
21
+
22
+ export async function sliceList(): Promise<void> {
23
+ const {
24
+ values: { help, json },
25
+ } = parseArgs({
26
+ args: process.argv.slice(4), // skip: node, script, "slice", "list"
27
+ options: {
28
+ json: { type: "boolean" },
29
+ help: { type: "boolean", short: "h" },
30
+ },
31
+ allowPositionals: true,
32
+ });
33
+
34
+ if (help) {
35
+ console.info(HELP);
36
+ return;
37
+ }
38
+
39
+ const slicesDirectory = await getSlicesDirectory();
40
+
41
+ let entries: string[];
42
+ try {
43
+ entries = (await readdir(slicesDirectory, {
44
+ withFileTypes: false,
45
+ })) as unknown as string[];
46
+ } catch {
47
+ if (json) {
48
+ console.info(JSON.stringify([]));
49
+ } else {
50
+ console.info("No slices found.");
51
+ }
52
+ return;
53
+ }
54
+
55
+ const slices: { id: string; name: string }[] = [];
56
+
57
+ for (const entry of entries) {
58
+ const modelPath = new URL(`${entry}/model.json`, slicesDirectory);
59
+ try {
60
+ const contents = await readFile(modelPath, "utf8");
61
+ const parsed = JSON.parse(contents);
62
+ const result = v.safeParse(SharedSliceSchema, parsed);
63
+ if (result.success) {
64
+ slices.push({ id: result.output.id, name: result.output.name });
65
+ }
66
+ } catch {
67
+ // Skip directories without valid model.json
68
+ }
69
+ }
70
+
71
+ if (slices.length === 0) {
72
+ if (json) {
73
+ console.info(JSON.stringify([]));
74
+ } else {
75
+ console.info("No slices found.");
76
+ }
77
+ return;
78
+ }
79
+
80
+ if (json) {
81
+ console.info(JSON.stringify(slices, null, 2));
82
+ } else {
83
+ console.info("ID\tNAME");
84
+ for (const slice of slices) {
85
+ console.info(`${slice.id}\t${slice.name}`);
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,128 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { parseArgs } from "node:util";
3
+
4
+ import { buildTypes } from "./codegen-types";
5
+ import { stringify } from "./lib/json";
6
+ import { findSliceModel } from "./lib/slice";
7
+
8
+ const HELP = `
9
+ Remove a field from a slice variation.
10
+
11
+ USAGE
12
+ prismic slice remove-field <slice-id> <field-id> [flags]
13
+
14
+ ARGUMENTS
15
+ slice-id Slice identifier (required)
16
+ field-id Field identifier (required)
17
+
18
+ Types are generated by default after changes. Use --no-types to skip.
19
+
20
+ FLAGS
21
+ --variation string Target variation (default: "default")
22
+ --zone string Field zone: "primary" or "items" (default: "primary")
23
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
24
+ --no-types Skip type generation
25
+ -h, --help Show help for command
26
+
27
+ EXAMPLES
28
+ prismic slice remove-field MySlice title
29
+ prismic slice remove-field MySlice title --variation withImage
30
+ prismic slice remove-field MySlice item_title --zone items
31
+ `.trim();
32
+
33
+ export async function sliceRemoveField(): Promise<void> {
34
+ const {
35
+ values: { help, variation, zone, types, "no-types": noTypes },
36
+ positionals: [sliceId, fieldId],
37
+ } = parseArgs({
38
+ args: process.argv.slice(4), // skip: node, script, "slice", "remove-field"
39
+ options: {
40
+ variation: { type: "string", default: "default" },
41
+ zone: { type: "string", default: "primary" },
42
+ types: { type: "string" },
43
+ "no-types": { type: "boolean" },
44
+ help: { type: "boolean", short: "h" },
45
+ },
46
+ allowPositionals: true,
47
+ });
48
+
49
+ if (help) {
50
+ console.info(HELP);
51
+ return;
52
+ }
53
+
54
+ if (!sliceId) {
55
+ console.error("Missing required argument: slice-id\n");
56
+ console.error("Usage: prismic slice remove-field <slice-id> <field-id>");
57
+ process.exitCode = 1;
58
+ return;
59
+ }
60
+
61
+ if (!fieldId) {
62
+ console.error("Missing required argument: field-id\n");
63
+ console.error("Usage: prismic slice remove-field <slice-id> <field-id>");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ if (zone !== "primary" && zone !== "items") {
69
+ console.error(`Invalid zone: ${zone}. Must be "primary" or "items".`);
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+
74
+ const result = await findSliceModel(sliceId);
75
+ if (!result.ok) {
76
+ console.error(result.error);
77
+ process.exitCode = 1;
78
+ return;
79
+ }
80
+
81
+ const { model, modelPath } = result;
82
+
83
+ // Find the variation
84
+ const targetVariation = model.variations.find((v) => v.id === variation);
85
+ if (!targetVariation) {
86
+ console.error(`Variation not found: ${variation}`);
87
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+
92
+ // Check if field exists
93
+ const zoneFields = zone === "primary" ? targetVariation.primary : targetVariation.items;
94
+ if (!zoneFields || !(fieldId in zoneFields)) {
95
+ console.error(`Field "${fieldId}" not found in ${zone} zone of variation "${variation}"`);
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+
100
+ // Remove the field
101
+ delete zoneFields[fieldId];
102
+
103
+ // Write updated model
104
+ try {
105
+ await writeFile(modelPath, stringify(model));
106
+ } catch (error) {
107
+ if (error instanceof Error) {
108
+ console.error(`Failed to update slice: ${error.message}`);
109
+ } else {
110
+ console.error("Failed to update slice");
111
+ }
112
+ process.exitCode = 1;
113
+ return;
114
+ }
115
+
116
+ console.info(
117
+ `Removed field "${fieldId}" from ${zone} zone in variation "${variation}" of slice "${sliceId}"`,
118
+ );
119
+
120
+ if (!noTypes) {
121
+ try {
122
+ await buildTypes({ output: types });
123
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
124
+ } catch (error) {
125
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,118 @@
1
+ import type { SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { writeFile } from "node:fs/promises";
4
+ import { parseArgs } from "node:util";
5
+
6
+ import { buildTypes } from "./codegen-types";
7
+ import { stringify } from "./lib/json";
8
+ import { findSliceModel } from "./lib/slice";
9
+
10
+ const HELP = `
11
+ Remove a variation from a slice.
12
+
13
+ USAGE
14
+ prismic slice remove-variation <slice-id> <variation-id> [flags]
15
+
16
+ ARGUMENTS
17
+ slice-id Slice identifier (required)
18
+ variation-id Variation to remove (required)
19
+
20
+ Types are generated by default after changes. Use --no-types to skip.
21
+
22
+ FLAGS
23
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
24
+ --no-types Skip type generation
25
+ -h, --help Show help for command
26
+
27
+ EXAMPLES
28
+ prismic slice remove-variation MySlice withImage
29
+ `.trim();
30
+
31
+ export async function sliceRemoveVariation(): Promise<void> {
32
+ const {
33
+ values: { help, types, "no-types": noTypes },
34
+ positionals: [sliceId, variationId],
35
+ } = parseArgs({
36
+ args: process.argv.slice(4), // skip: node, script, "slice", "remove-variation"
37
+ options: {
38
+ types: { type: "string" },
39
+ "no-types": { type: "boolean" },
40
+ help: { type: "boolean", short: "h" },
41
+ },
42
+ allowPositionals: true,
43
+ });
44
+
45
+ if (help) {
46
+ console.info(HELP);
47
+ return;
48
+ }
49
+
50
+ if (!sliceId) {
51
+ console.error("Missing required argument: slice-id\n");
52
+ console.error("Usage: prismic slice remove-variation <slice-id> <variation-id>");
53
+ process.exitCode = 1;
54
+ return;
55
+ }
56
+
57
+ if (!variationId) {
58
+ console.error("Missing required argument: variation-id\n");
59
+ console.error("Usage: prismic slice remove-variation <slice-id> <variation-id>");
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+
64
+ const result = await findSliceModel(sliceId);
65
+ if (!result.ok) {
66
+ console.error(result.error);
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+
71
+ const { model, modelPath } = result;
72
+
73
+ // Check if variation exists
74
+ const variationExists = model.variations.some((v) => v.id === variationId);
75
+ if (!variationExists) {
76
+ console.error(`Variation not found: ${variationId}`);
77
+ console.error(`Available variations: ${model.variations.map((v) => v.id).join(", ")}`);
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+
82
+ // Prevent removing the last variation
83
+ if (model.variations.length === 1) {
84
+ console.error("Cannot remove the last variation from a slice.");
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+
89
+ // Remove the variation
90
+ const updatedModel = {
91
+ ...model,
92
+ variations: model.variations.filter((v) => v.id !== variationId),
93
+ };
94
+
95
+ // Write updated model
96
+ try {
97
+ await writeFile(modelPath, stringify(updatedModel as SharedSlice));
98
+ } catch (error) {
99
+ if (error instanceof Error) {
100
+ console.error(`Failed to update slice: ${error.message}`);
101
+ } else {
102
+ console.error("Failed to update slice");
103
+ }
104
+ process.exitCode = 1;
105
+ return;
106
+ }
107
+
108
+ console.info(`Removed variation "${variationId}" from slice "${sliceId}"`);
109
+
110
+ if (!noTypes) {
111
+ try {
112
+ await buildTypes({ output: types });
113
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
114
+ } catch (error) {
115
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
116
+ }
117
+ }
118
+ }