@angeloashmore/prismic-cli-poc 0.0.0-canary.1143872

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 (139) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +98 -0
  3. package/dist/index.mjs +2508 -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 +222 -0
  8. package/src/custom-type-add-field-color.ts +205 -0
  9. package/src/custom-type-add-field-date.ts +208 -0
  10. package/src/custom-type-add-field-embed.ts +205 -0
  11. package/src/custom-type-add-field-geo-point.ts +202 -0
  12. package/src/custom-type-add-field-group.ts +179 -0
  13. package/src/custom-type-add-field-image.ts +205 -0
  14. package/src/custom-type-add-field-key-text.ts +205 -0
  15. package/src/custom-type-add-field-link.ts +228 -0
  16. package/src/custom-type-add-field-number.ts +237 -0
  17. package/src/custom-type-add-field-rich-text.ts +229 -0
  18. package/src/custom-type-add-field-select.ts +211 -0
  19. package/src/custom-type-add-field-timestamp.ts +208 -0
  20. package/src/custom-type-add-field-uid.ts +188 -0
  21. package/src/custom-type-add-field.ts +116 -0
  22. package/src/custom-type-connect-slice.ts +214 -0
  23. package/src/custom-type-create.ts +112 -0
  24. package/src/custom-type-disconnect-slice.ts +171 -0
  25. package/src/custom-type-list.ts +110 -0
  26. package/src/custom-type-remove-field.ts +171 -0
  27. package/src/custom-type-remove.ts +138 -0
  28. package/src/custom-type-set-name.ts +138 -0
  29. package/src/custom-type-view.ts +118 -0
  30. package/src/custom-type.ts +85 -0
  31. package/src/docs-fetch.ts +146 -0
  32. package/src/docs-list.ts +131 -0
  33. package/src/docs.ts +54 -0
  34. package/src/index.ts +132 -0
  35. package/src/init.ts +64 -0
  36. package/src/lib/auth.ts +83 -0
  37. package/src/lib/config.ts +111 -0
  38. package/src/lib/custom-types-api.ts +438 -0
  39. package/src/lib/field-path.ts +81 -0
  40. package/src/lib/file.ts +49 -0
  41. package/src/lib/framework.ts +143 -0
  42. package/src/lib/json.ts +3 -0
  43. package/src/lib/request.ts +116 -0
  44. package/src/lib/slice.ts +115 -0
  45. package/src/lib/string.ts +6 -0
  46. package/src/lib/url.ts +25 -0
  47. package/src/locale-add.ts +116 -0
  48. package/src/locale-list.ts +107 -0
  49. package/src/locale-remove.ts +88 -0
  50. package/src/locale-set-default.ts +131 -0
  51. package/src/locale.ts +60 -0
  52. package/src/login.ts +152 -0
  53. package/src/logout.ts +36 -0
  54. package/src/page-type-add-field-boolean.ts +238 -0
  55. package/src/page-type-add-field-color.ts +224 -0
  56. package/src/page-type-add-field-date.ts +227 -0
  57. package/src/page-type-add-field-embed.ts +224 -0
  58. package/src/page-type-add-field-geo-point.ts +221 -0
  59. package/src/page-type-add-field-group.ts +198 -0
  60. package/src/page-type-add-field-image.ts +224 -0
  61. package/src/page-type-add-field-key-text.ts +224 -0
  62. package/src/page-type-add-field-link.ts +247 -0
  63. package/src/page-type-add-field-number.ts +256 -0
  64. package/src/page-type-add-field-rich-text.ts +248 -0
  65. package/src/page-type-add-field-select.ts +230 -0
  66. package/src/page-type-add-field-timestamp.ts +227 -0
  67. package/src/page-type-add-field-uid.ts +207 -0
  68. package/src/page-type-add-field.ts +116 -0
  69. package/src/page-type-connect-slice.ts +214 -0
  70. package/src/page-type-create.ts +161 -0
  71. package/src/page-type-disconnect-slice.ts +171 -0
  72. package/src/page-type-list.ts +109 -0
  73. package/src/page-type-remove-field.ts +171 -0
  74. package/src/page-type-remove.ts +138 -0
  75. package/src/page-type-set-name.ts +138 -0
  76. package/src/page-type-set-repeatable.ts +147 -0
  77. package/src/page-type-view.ts +118 -0
  78. package/src/page-type.ts +90 -0
  79. package/src/preview-add.ts +126 -0
  80. package/src/preview-get-simulator.ts +104 -0
  81. package/src/preview-list.ts +106 -0
  82. package/src/preview-remove-simulator.ts +80 -0
  83. package/src/preview-remove.ts +109 -0
  84. package/src/preview-set-name.ts +137 -0
  85. package/src/preview-set-simulator.ts +116 -0
  86. package/src/preview.ts +75 -0
  87. package/src/pull.ts +242 -0
  88. package/src/push.ts +405 -0
  89. package/src/repo-create.ts +195 -0
  90. package/src/repo-get-access.ts +86 -0
  91. package/src/repo-list.ts +100 -0
  92. package/src/repo-set-access.ts +100 -0
  93. package/src/repo-set-name.ts +102 -0
  94. package/src/repo-view.ts +113 -0
  95. package/src/repo.ts +70 -0
  96. package/src/slice-add-field-boolean.ts +240 -0
  97. package/src/slice-add-field-color.ts +226 -0
  98. package/src/slice-add-field-date.ts +226 -0
  99. package/src/slice-add-field-embed.ts +226 -0
  100. package/src/slice-add-field-geo-point.ts +223 -0
  101. package/src/slice-add-field-group.ts +191 -0
  102. package/src/slice-add-field-image.ts +223 -0
  103. package/src/slice-add-field-key-text.ts +226 -0
  104. package/src/slice-add-field-link.ts +245 -0
  105. package/src/slice-add-field-number.ts +226 -0
  106. package/src/slice-add-field-rich-text.ts +250 -0
  107. package/src/slice-add-field-select.ts +232 -0
  108. package/src/slice-add-field-timestamp.ts +226 -0
  109. package/src/slice-add-field.ts +111 -0
  110. package/src/slice-add-variation.ts +139 -0
  111. package/src/slice-create.ts +203 -0
  112. package/src/slice-list-variations.ts +67 -0
  113. package/src/slice-list.ts +88 -0
  114. package/src/slice-remove-field.ts +122 -0
  115. package/src/slice-remove-variation.ts +112 -0
  116. package/src/slice-remove.ts +91 -0
  117. package/src/slice-rename.ts +122 -0
  118. package/src/slice-set-screenshot.ts +235 -0
  119. package/src/slice-view.ts +80 -0
  120. package/src/slice.ts +95 -0
  121. package/src/status.ts +873 -0
  122. package/src/token-create.ts +203 -0
  123. package/src/token-delete.ts +182 -0
  124. package/src/token-list.ts +223 -0
  125. package/src/token-set-name.ts +193 -0
  126. package/src/token.ts +60 -0
  127. package/src/webhook-add-header.ts +118 -0
  128. package/src/webhook-create.ts +152 -0
  129. package/src/webhook-disable.ts +109 -0
  130. package/src/webhook-enable.ts +132 -0
  131. package/src/webhook-list.ts +93 -0
  132. package/src/webhook-remove-header.ts +117 -0
  133. package/src/webhook-remove.ts +106 -0
  134. package/src/webhook-set-triggers.ts +148 -0
  135. package/src/webhook-status.ts +90 -0
  136. package/src/webhook-test.ts +106 -0
  137. package/src/webhook-view.ts +147 -0
  138. package/src/webhook.ts +95 -0
  139. package/src/whoami.ts +62 -0
@@ -0,0 +1,110 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { parseArgs } from "node:util";
3
+ import * as v from "valibot";
4
+
5
+ import { findUpward } from "./lib/file";
6
+
7
+ const HELP = `
8
+ List all custom types in a Prismic project.
9
+
10
+ USAGE
11
+ prismic custom-type list [flags]
12
+
13
+ FLAGS
14
+ --json Output as JSON
15
+ -h, --help Show help for command
16
+
17
+ EXAMPLES
18
+ prismic custom-type list
19
+ prismic custom-type list --json
20
+ `.trim();
21
+
22
+ const CustomTypeSchema = v.object({
23
+ id: v.string(),
24
+ label: v.string(),
25
+ repeatable: v.boolean(),
26
+ status: v.boolean(),
27
+ format: v.optional(v.string()),
28
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
29
+ });
30
+
31
+ export async function customTypeList(): Promise<void> {
32
+ const {
33
+ values: { help, json },
34
+ } = parseArgs({
35
+ args: process.argv.slice(4), // skip: node, script, "custom-type", "list"
36
+ options: {
37
+ json: { type: "boolean" },
38
+ help: { type: "boolean", short: "h" },
39
+ },
40
+ allowPositionals: true,
41
+ });
42
+
43
+ if (help) {
44
+ console.info(HELP);
45
+ return;
46
+ }
47
+
48
+ const projectRoot = await findUpward("package.json");
49
+ if (!projectRoot) {
50
+ console.error("Could not find project root (no package.json found)");
51
+ process.exitCode = 1;
52
+ return;
53
+ }
54
+
55
+ const customTypesDirectory = new URL("customtypes/", projectRoot);
56
+
57
+ let entries: string[];
58
+ try {
59
+ entries = (await readdir(customTypesDirectory, {
60
+ withFileTypes: false,
61
+ })) as unknown as string[];
62
+ } catch {
63
+ if (json) {
64
+ console.info(JSON.stringify([]));
65
+ } else {
66
+ console.info("No custom types found.");
67
+ }
68
+ return;
69
+ }
70
+
71
+ const customTypes: { id: string; label: string; repeatable: boolean }[] = [];
72
+
73
+ for (const entry of entries) {
74
+ const modelPath = new URL(`${entry}/index.json`, customTypesDirectory);
75
+ try {
76
+ const contents = await readFile(modelPath, "utf8");
77
+ const parsed = JSON.parse(contents);
78
+ const result = v.safeParse(CustomTypeSchema, parsed);
79
+ // Custom types have format !== "page" (either "custom" or undefined)
80
+ if (result.success && result.output.format !== "page") {
81
+ customTypes.push({
82
+ id: result.output.id,
83
+ label: result.output.label,
84
+ repeatable: result.output.repeatable,
85
+ });
86
+ }
87
+ } catch {
88
+ // Skip directories without valid index.json
89
+ }
90
+ }
91
+
92
+ if (customTypes.length === 0) {
93
+ if (json) {
94
+ console.info(JSON.stringify([]));
95
+ } else {
96
+ console.info("No custom types found.");
97
+ }
98
+ return;
99
+ }
100
+
101
+ if (json) {
102
+ console.info(JSON.stringify(customTypes, null, 2));
103
+ } else {
104
+ console.info("ID\tLABEL\tTYPE");
105
+ for (const customType of customTypes) {
106
+ const typeLabel = customType.repeatable ? "repeatable" : "singleton";
107
+ console.info(`${customType.id}\t${customType.label}\t${typeLabel}`);
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,171 @@
1
+ import type { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { 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 { findUpward } from "./lib/file";
9
+ import { stringify } from "./lib/json";
10
+
11
+ const HELP = `
12
+ Remove a field from a custom type.
13
+
14
+ USAGE
15
+ prismic custom-type remove-field <type-id> <field-id> [flags]
16
+
17
+ ARGUMENTS
18
+ type-id Custom type identifier (required)
19
+ field-id Field identifier (required)
20
+
21
+ FLAGS
22
+ --tab string Specific tab (searches all tabs if not specified)
23
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
24
+ -h, --help Show help for command
25
+
26
+ EXAMPLES
27
+ prismic custom-type remove-field settings title
28
+ prismic custom-type remove-field settings description --tab "Content"
29
+ `.trim();
30
+
31
+ const CustomTypeSchema = v.object({
32
+ id: v.string(),
33
+ label: v.string(),
34
+ repeatable: v.boolean(),
35
+ status: v.boolean(),
36
+ format: v.optional(v.string()),
37
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
38
+ });
39
+
40
+ export async function customTypeRemoveField(): Promise<void> {
41
+ const {
42
+ values: { help, tab, types },
43
+ positionals: [typeId, fieldId],
44
+ } = parseArgs({
45
+ args: process.argv.slice(4), // skip: node, script, "custom-type", "remove-field"
46
+ options: {
47
+ tab: { type: "string" },
48
+ types: { type: "string" },
49
+ help: { type: "boolean", short: "h" },
50
+ },
51
+ allowPositionals: true,
52
+ });
53
+
54
+ if (help) {
55
+ console.info(HELP);
56
+ return;
57
+ }
58
+
59
+ if (!typeId) {
60
+ console.error("Missing required argument: type-id\n");
61
+ console.error("Usage: prismic custom-type remove-field <type-id> <field-id>");
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+
66
+ if (!fieldId) {
67
+ console.error("Missing required argument: field-id\n");
68
+ console.error("Usage: prismic custom-type remove-field <type-id> <field-id>");
69
+ process.exitCode = 1;
70
+ return;
71
+ }
72
+
73
+ const projectRoot = await findUpward("package.json");
74
+ if (!projectRoot) {
75
+ console.error("Could not find project root (no package.json found)");
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+
80
+ const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
81
+
82
+ // Read and parse the model
83
+ let model: CustomType;
84
+ try {
85
+ const contents = await readFile(modelPath, "utf8");
86
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
87
+ if (!result.success) {
88
+ console.error(`Invalid custom type model: ${modelPath.href}`);
89
+ process.exitCode = 1;
90
+ return;
91
+ }
92
+ model = result.output as CustomType;
93
+ } catch (error) {
94
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
95
+ console.error(`Custom type not found: ${typeId}\n`);
96
+ console.error(`Create it first with: prismic custom-type create ${typeId}`);
97
+ process.exitCode = 1;
98
+ return;
99
+ }
100
+ if (error instanceof Error) {
101
+ console.error(`Failed to read custom type: ${error.message}`);
102
+ } else {
103
+ console.error("Failed to read custom type");
104
+ }
105
+ process.exitCode = 1;
106
+ return;
107
+ }
108
+
109
+ // Check if this is actually a custom type (not a page type)
110
+ if (model.format === "page") {
111
+ console.error(`"${typeId}" is not a custom type (format: page)`);
112
+ process.exitCode = 1;
113
+ return;
114
+ }
115
+
116
+ // Find and remove the field
117
+ let foundTab: string | undefined;
118
+
119
+ if (tab) {
120
+ // Look in specific tab
121
+ if (!model.json[tab]) {
122
+ console.error(`Tab "${tab}" not found in custom type "${typeId}"`);
123
+ console.error(`Available tabs: ${Object.keys(model.json).join(", ")}`);
124
+ process.exitCode = 1;
125
+ return;
126
+ }
127
+ if (!(fieldId in model.json[tab])) {
128
+ console.error(`Field "${fieldId}" not found in tab "${tab}"`);
129
+ process.exitCode = 1;
130
+ return;
131
+ }
132
+ delete model.json[tab][fieldId];
133
+ foundTab = tab;
134
+ } else {
135
+ // Search all tabs
136
+ for (const [tabName, tabFields] of Object.entries(model.json)) {
137
+ if (fieldId in tabFields) {
138
+ delete tabFields[fieldId];
139
+ foundTab = tabName;
140
+ break;
141
+ }
142
+ }
143
+ if (!foundTab) {
144
+ console.error(`Field "${fieldId}" not found in any tab of custom type "${typeId}"`);
145
+ process.exitCode = 1;
146
+ return;
147
+ }
148
+ }
149
+
150
+ // Write updated model
151
+ try {
152
+ await writeFile(modelPath, stringify(model));
153
+ } catch (error) {
154
+ if (error instanceof Error) {
155
+ console.error(`Failed to update custom type: ${error.message}`);
156
+ } else {
157
+ console.error("Failed to update custom type");
158
+ }
159
+ process.exitCode = 1;
160
+ return;
161
+ }
162
+
163
+ console.info(`Removed field "${fieldId}" from tab "${foundTab}" in custom type "${typeId}"`);
164
+
165
+ try {
166
+ await buildTypes({ output: types });
167
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
168
+ } catch (error) {
169
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
170
+ }
171
+ }
@@ -0,0 +1,138 @@
1
+ import type { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { readFile, rm } 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 { findUpward } from "./lib/file";
9
+
10
+ const HELP = `
11
+ Remove a custom type from the project.
12
+
13
+ USAGE
14
+ prismic custom-type remove <type-id> [flags]
15
+
16
+ ARGUMENTS
17
+ type-id Custom type identifier (required)
18
+
19
+ FLAGS
20
+ -y Confirm removal
21
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
22
+ -h, --help Show help for command
23
+
24
+ EXAMPLES
25
+ prismic custom-type remove settings
26
+ prismic custom-type remove settings -y
27
+ `.trim();
28
+
29
+ const CustomTypeSchema = v.object({
30
+ id: v.string(),
31
+ label: v.string(),
32
+ repeatable: v.boolean(),
33
+ status: v.boolean(),
34
+ format: v.optional(v.string()),
35
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
36
+ });
37
+
38
+ export async function customTypeRemove(): Promise<void> {
39
+ const {
40
+ values: { help, y, types },
41
+ positionals: [typeId],
42
+ } = parseArgs({
43
+ args: process.argv.slice(4), // skip: node, script, "custom-type", "remove"
44
+ options: {
45
+ y: { type: "boolean", short: "y" },
46
+ types: { type: "string" },
47
+ help: { type: "boolean", short: "h" },
48
+ },
49
+ allowPositionals: true,
50
+ });
51
+
52
+ if (help) {
53
+ console.info(HELP);
54
+ return;
55
+ }
56
+
57
+ if (!typeId) {
58
+ console.error("Missing required argument: type-id\n");
59
+ console.error("Usage: prismic custom-type remove <type-id>");
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+
64
+ const projectRoot = await findUpward("package.json");
65
+ if (!projectRoot) {
66
+ console.error("Could not find project root (no package.json found)");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+
71
+ const typeDirectory = new URL(`customtypes/${typeId}/`, projectRoot);
72
+ const modelPath = new URL("index.json", typeDirectory);
73
+
74
+ // Verify the custom type exists and is actually a custom type
75
+ let model: CustomType;
76
+ try {
77
+ const contents = await readFile(modelPath, "utf8");
78
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
79
+ if (!result.success) {
80
+ console.error(`Invalid custom type model: ${modelPath.href}`);
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ model = result.output as CustomType;
85
+ } catch (error) {
86
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
87
+ console.error(`Custom type not found: ${typeId}`);
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+ if (error instanceof Error) {
92
+ console.error(`Failed to read custom type: ${error.message}`);
93
+ } else {
94
+ console.error("Failed to read custom type");
95
+ }
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+
100
+ // Check if this is actually a custom type (not a page type)
101
+ if (model.format === "page") {
102
+ console.error(`"${typeId}" is not a custom type (format: page)`);
103
+ process.exitCode = 1;
104
+ return;
105
+ }
106
+
107
+ // Require -y flag to confirm deletion
108
+ if (!y) {
109
+ console.error(
110
+ `Refusing to remove custom type "${typeId}" (this will delete the entire directory).`,
111
+ );
112
+ console.error("Re-run with -y to confirm.");
113
+ process.exitCode = 1;
114
+ return;
115
+ }
116
+
117
+ // Delete the custom type directory
118
+ try {
119
+ await rm(typeDirectory, { recursive: true });
120
+ } catch (error) {
121
+ if (error instanceof Error) {
122
+ console.error(`Failed to remove custom type: ${error.message}`);
123
+ } else {
124
+ console.error("Failed to remove custom type");
125
+ }
126
+ process.exitCode = 1;
127
+ return;
128
+ }
129
+
130
+ console.info(`Removed custom type "${typeId}"`);
131
+
132
+ try {
133
+ await buildTypes({ output: types });
134
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
135
+ } catch (error) {
136
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
137
+ }
138
+ }
@@ -0,0 +1,138 @@
1
+ import type { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { 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 { findUpward } from "./lib/file";
9
+ import { stringify } from "./lib/json";
10
+
11
+ const HELP = `
12
+ Change a custom type's display name (label).
13
+
14
+ USAGE
15
+ prismic custom-type set-name <type-id> <new-name> [flags]
16
+
17
+ ARGUMENTS
18
+ type-id Custom type identifier (required)
19
+ new-name New display name (required)
20
+
21
+ FLAGS
22
+ --types string Output file for generated types (default: "prismicio-types.d.ts")
23
+ -h, --help Show help for command
24
+
25
+ EXAMPLES
26
+ prismic custom-type set-name settings "Site Settings"
27
+ prismic custom-type set-name menu "Navigation Menu"
28
+ `.trim();
29
+
30
+ const CustomTypeSchema = v.object({
31
+ id: v.string(),
32
+ label: v.string(),
33
+ repeatable: v.boolean(),
34
+ status: v.boolean(),
35
+ format: v.optional(v.string()),
36
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
37
+ });
38
+
39
+ export async function customTypeSetName(): Promise<void> {
40
+ const {
41
+ values: { help, types },
42
+ positionals: [typeId, newName],
43
+ } = parseArgs({
44
+ args: process.argv.slice(4), // skip: node, script, "custom-type", "set-name"
45
+ options: {
46
+ types: { type: "string" },
47
+ help: { type: "boolean", short: "h" },
48
+ },
49
+ allowPositionals: true,
50
+ });
51
+
52
+ if (help) {
53
+ console.info(HELP);
54
+ return;
55
+ }
56
+
57
+ if (!typeId) {
58
+ console.error("Missing required argument: type-id\n");
59
+ console.error("Usage: prismic custom-type set-name <type-id> <new-name>");
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+
64
+ if (!newName) {
65
+ console.error("Missing required argument: new-name\n");
66
+ console.error("Usage: prismic custom-type set-name <type-id> <new-name>");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+
71
+ const projectRoot = await findUpward("package.json");
72
+ if (!projectRoot) {
73
+ console.error("Could not find project root (no package.json found)");
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+
78
+ const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
79
+
80
+ // Read and parse the model
81
+ let model: CustomType;
82
+ try {
83
+ const contents = await readFile(modelPath, "utf8");
84
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
85
+ if (!result.success) {
86
+ console.error(`Invalid custom type model: ${modelPath.href}`);
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+ model = result.output as CustomType;
91
+ } catch (error) {
92
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
93
+ console.error(`Custom type not found: ${typeId}\n`);
94
+ console.error(`Create it first with: prismic custom-type create ${typeId}`);
95
+ process.exitCode = 1;
96
+ return;
97
+ }
98
+ if (error instanceof Error) {
99
+ console.error(`Failed to read custom type: ${error.message}`);
100
+ } else {
101
+ console.error("Failed to read custom type");
102
+ }
103
+ process.exitCode = 1;
104
+ return;
105
+ }
106
+
107
+ // Check if this is actually a custom type (not a page type)
108
+ if (model.format === "page") {
109
+ console.error(`"${typeId}" is not a custom type (format: page)`);
110
+ process.exitCode = 1;
111
+ return;
112
+ }
113
+
114
+ // Update the model
115
+ model.label = newName;
116
+
117
+ // Write updated model
118
+ try {
119
+ await writeFile(modelPath, stringify(model));
120
+ } catch (error) {
121
+ if (error instanceof Error) {
122
+ console.error(`Failed to update custom type: ${error.message}`);
123
+ } else {
124
+ console.error("Failed to update custom type");
125
+ }
126
+ process.exitCode = 1;
127
+ return;
128
+ }
129
+
130
+ console.info(`Renamed custom type "${typeId}" to "${newName}"`);
131
+
132
+ try {
133
+ await buildTypes({ output: types });
134
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
135
+ } catch (error) {
136
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
137
+ }
138
+ }
@@ -0,0 +1,118 @@
1
+ import type { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { readFile } from "node:fs/promises";
4
+ import { parseArgs } from "node:util";
5
+ import * as v from "valibot";
6
+
7
+ import { findUpward } from "./lib/file";
8
+
9
+ const HELP = `
10
+ View details of a specific custom type.
11
+
12
+ USAGE
13
+ prismic custom-type view <type-id> [flags]
14
+
15
+ ARGUMENTS
16
+ type-id Custom type identifier (required)
17
+
18
+ FLAGS
19
+ --json Output as JSON
20
+ -h, --help Show help for command
21
+
22
+ EXAMPLES
23
+ prismic custom-type view settings
24
+ prismic custom-type view settings --json
25
+ `.trim();
26
+
27
+ const CustomTypeSchema = v.object({
28
+ id: v.string(),
29
+ label: v.string(),
30
+ repeatable: v.boolean(),
31
+ status: v.boolean(),
32
+ format: v.optional(v.string()),
33
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
34
+ });
35
+
36
+ export async function customTypeView(): Promise<void> {
37
+ const {
38
+ values: { help, json },
39
+ positionals: [typeId],
40
+ } = parseArgs({
41
+ args: process.argv.slice(4), // skip: node, script, "custom-type", "view"
42
+ options: {
43
+ json: { 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 (!typeId) {
55
+ console.error("Missing required argument: type-id\n");
56
+ console.error("Usage: prismic custom-type view <type-id>");
57
+ process.exitCode = 1;
58
+ return;
59
+ }
60
+
61
+ const projectRoot = await findUpward("package.json");
62
+ if (!projectRoot) {
63
+ console.error("Could not find project root (no package.json found)");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
69
+
70
+ let model: CustomType;
71
+ try {
72
+ const contents = await readFile(modelPath, "utf8");
73
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
74
+ if (!result.success) {
75
+ console.error(`Invalid custom type model: ${modelPath.href}`);
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ model = result.output as CustomType;
80
+ } catch (error) {
81
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
82
+ console.error(`Custom type not found: ${typeId}\n`);
83
+ console.error(`Create it first with: prismic custom-type create ${typeId}`);
84
+ process.exitCode = 1;
85
+ return;
86
+ }
87
+ if (error instanceof Error) {
88
+ console.error(`Failed to read custom type: ${error.message}`);
89
+ } else {
90
+ console.error("Failed to read custom type");
91
+ }
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+
96
+ // Check if this is actually a custom type (not a page type)
97
+ if (model.format === "page") {
98
+ console.error(`"${typeId}" is not a custom type (format: page)`);
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+
103
+ if (json) {
104
+ console.info(JSON.stringify(model, null, 2));
105
+ return;
106
+ }
107
+
108
+ console.info(`ID: ${model.id}`);
109
+ console.info(`Label: ${model.label}`);
110
+ console.info(`Repeatable: ${model.repeatable}`);
111
+
112
+ const tabs = Object.entries(model.json);
113
+ console.info(`\nTabs (${tabs.length}):`);
114
+ for (const [tabName, tabFields] of tabs) {
115
+ const fieldCount = Object.keys(tabFields).length;
116
+ console.info(` - ${tabName}: ${fieldCount} fields`);
117
+ }
118
+ }