@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,144 @@
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 page type from the project.
12
+
13
+ USAGE
14
+ prismic page-type remove <type-id> [flags]
15
+
16
+ ARGUMENTS
17
+ type-id Page type identifier (required)
18
+
19
+ Types are generated by default after changes. Use --no-types to skip.
20
+
21
+ FLAGS
22
+ -y Confirm removal
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 page-type remove homepage
29
+ prismic page-type remove homepage -y
30
+ `.trim();
31
+
32
+ const CustomTypeSchema = v.object({
33
+ id: v.string(),
34
+ label: v.string(),
35
+ repeatable: v.boolean(),
36
+ status: v.boolean(),
37
+ format: v.optional(v.string()),
38
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
39
+ });
40
+
41
+ export async function pageTypeRemove(): Promise<void> {
42
+ const {
43
+ values: { help, y, types, "no-types": noTypes },
44
+ positionals: [typeId],
45
+ } = parseArgs({
46
+ args: process.argv.slice(4), // skip: node, script, "page-type", "remove"
47
+ options: {
48
+ y: { type: "boolean", short: "y" },
49
+ types: { type: "string" },
50
+ "no-types": { type: "boolean" },
51
+ help: { type: "boolean", short: "h" },
52
+ },
53
+ allowPositionals: true,
54
+ });
55
+
56
+ if (help) {
57
+ console.info(HELP);
58
+ return;
59
+ }
60
+
61
+ if (!typeId) {
62
+ console.error("Missing required argument: type-id\n");
63
+ console.error("Usage: prismic page-type remove <type-id>");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ const projectRoot = await findUpward("package.json");
69
+ if (!projectRoot) {
70
+ console.error("Could not find project root (no package.json found)");
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+
75
+ const typeDirectory = new URL(`customtypes/${typeId}/`, projectRoot);
76
+ const modelPath = new URL("index.json", typeDirectory);
77
+
78
+ // Verify the page type exists and is actually a page type
79
+ let model: CustomType;
80
+ try {
81
+ const contents = await readFile(modelPath, "utf8");
82
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
83
+ if (!result.success) {
84
+ console.error(`Invalid page type model: ${modelPath.href}`);
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ model = result.output as CustomType;
89
+ } catch (error) {
90
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
91
+ console.error(`Page type not found: ${typeId}`);
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ if (error instanceof Error) {
96
+ console.error(`Failed to read page type: ${error.message}`);
97
+ } else {
98
+ console.error("Failed to read page type");
99
+ }
100
+ process.exitCode = 1;
101
+ return;
102
+ }
103
+
104
+ // Check if this is actually a page type
105
+ if (model.format !== "page") {
106
+ console.error(`"${typeId}" is not a page type (format: ${model.format ?? "custom"})`);
107
+ process.exitCode = 1;
108
+ return;
109
+ }
110
+
111
+ // Require -y flag to confirm deletion
112
+ if (!y) {
113
+ console.error(
114
+ `Refusing to remove page type "${typeId}" (this will delete the entire directory).`,
115
+ );
116
+ console.error("Re-run with -y to confirm.");
117
+ process.exitCode = 1;
118
+ return;
119
+ }
120
+
121
+ // Delete the page type directory
122
+ try {
123
+ await rm(typeDirectory, { recursive: true });
124
+ } catch (error) {
125
+ if (error instanceof Error) {
126
+ console.error(`Failed to remove page type: ${error.message}`);
127
+ } else {
128
+ console.error("Failed to remove page type");
129
+ }
130
+ process.exitCode = 1;
131
+ return;
132
+ }
133
+
134
+ console.info(`Removed page type "${typeId}"`);
135
+
136
+ if (!noTypes) {
137
+ try {
138
+ await buildTypes({ output: types });
139
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
140
+ } catch (error) {
141
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,144 @@
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 page type's display name (label).
13
+
14
+ USAGE
15
+ prismic page-type set-name <type-id> <new-name> [flags]
16
+
17
+ ARGUMENTS
18
+ type-id Page type identifier (required)
19
+ new-name New display name (required)
20
+
21
+ Types are generated by default after changes. Use --no-types to skip.
22
+
23
+ FLAGS
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
+ EXAMPLES
29
+ prismic page-type set-name homepage "Home Page"
30
+ prismic page-type set-name blog_post "Blog Post"
31
+ `.trim();
32
+
33
+ const CustomTypeSchema = v.object({
34
+ id: v.string(),
35
+ label: v.string(),
36
+ repeatable: v.boolean(),
37
+ status: v.boolean(),
38
+ format: v.optional(v.string()),
39
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
40
+ });
41
+
42
+ export async function pageTypeSetName(): Promise<void> {
43
+ const {
44
+ values: { help, types, "no-types": noTypes },
45
+ positionals: [typeId, newName],
46
+ } = parseArgs({
47
+ args: process.argv.slice(4), // skip: node, script, "page-type", "set-name"
48
+ options: {
49
+ types: { type: "string" },
50
+ "no-types": { type: "boolean" },
51
+ help: { type: "boolean", short: "h" },
52
+ },
53
+ allowPositionals: true,
54
+ });
55
+
56
+ if (help) {
57
+ console.info(HELP);
58
+ return;
59
+ }
60
+
61
+ if (!typeId) {
62
+ console.error("Missing required argument: type-id\n");
63
+ console.error("Usage: prismic page-type set-name <type-id> <new-name>");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ if (!newName) {
69
+ console.error("Missing required argument: new-name\n");
70
+ console.error("Usage: prismic page-type set-name <type-id> <new-name>");
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+
75
+ const projectRoot = await findUpward("package.json");
76
+ if (!projectRoot) {
77
+ console.error("Could not find project root (no package.json found)");
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+
82
+ const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
83
+
84
+ // Read and parse the model
85
+ let model: CustomType;
86
+ try {
87
+ const contents = await readFile(modelPath, "utf8");
88
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
89
+ if (!result.success) {
90
+ console.error(`Invalid page type model: ${modelPath.href}`);
91
+ process.exitCode = 1;
92
+ return;
93
+ }
94
+ model = result.output as CustomType;
95
+ } catch (error) {
96
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
97
+ console.error(`Page type not found: ${typeId}\n`);
98
+ console.error(`Create it first with: prismic page-type create ${typeId}`);
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+ if (error instanceof Error) {
103
+ console.error(`Failed to read page type: ${error.message}`);
104
+ } else {
105
+ console.error("Failed to read page type");
106
+ }
107
+ process.exitCode = 1;
108
+ return;
109
+ }
110
+
111
+ // Check if this is actually a page type
112
+ if (model.format !== "page") {
113
+ console.error(`"${typeId}" is not a page type (format: ${model.format ?? "custom"})`);
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+
118
+ // Update the model
119
+ model.label = newName;
120
+
121
+ // Write updated model
122
+ try {
123
+ await writeFile(modelPath, stringify(model));
124
+ } catch (error) {
125
+ if (error instanceof Error) {
126
+ console.error(`Failed to update page type: ${error.message}`);
127
+ } else {
128
+ console.error("Failed to update page type");
129
+ }
130
+ process.exitCode = 1;
131
+ return;
132
+ }
133
+
134
+ console.info(`Renamed page type "${typeId}" to "${newName}"`);
135
+
136
+ if (!noTypes) {
137
+ try {
138
+ await buildTypes({ output: types });
139
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
140
+ } catch (error) {
141
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,153 @@
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
+ Set whether a page type is repeatable.
13
+
14
+ USAGE
15
+ prismic page-type set-repeatable <type-id> <true|false> [flags]
16
+
17
+ ARGUMENTS
18
+ type-id Page type identifier (required)
19
+ true|false Repeatable value (required)
20
+
21
+ Types are generated by default after changes. Use --no-types to skip.
22
+
23
+ FLAGS
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
+ EXAMPLES
29
+ prismic page-type set-repeatable homepage true
30
+ prismic page-type set-repeatable settings false
31
+ `.trim();
32
+
33
+ const CustomTypeSchema = v.object({
34
+ id: v.string(),
35
+ label: v.string(),
36
+ repeatable: v.boolean(),
37
+ status: v.boolean(),
38
+ format: v.optional(v.string()),
39
+ json: v.record(v.string(), v.record(v.string(), v.unknown())),
40
+ });
41
+
42
+ export async function pageTypeSetRepeatable(): Promise<void> {
43
+ const {
44
+ values: { help, types, "no-types": noTypes },
45
+ positionals: [typeId, repeatableValue],
46
+ } = parseArgs({
47
+ args: process.argv.slice(4), // skip: node, script, "page-type", "set-repeatable"
48
+ options: {
49
+ types: { type: "string" },
50
+ "no-types": { type: "boolean" },
51
+ help: { type: "boolean", short: "h" },
52
+ },
53
+ allowPositionals: true,
54
+ });
55
+
56
+ if (help) {
57
+ console.info(HELP);
58
+ return;
59
+ }
60
+
61
+ if (!typeId) {
62
+ console.error("Missing required argument: type-id\n");
63
+ console.error("Usage: prismic page-type set-repeatable <type-id> <true|false>");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ if (!repeatableValue) {
69
+ console.error("Missing required argument: true|false\n");
70
+ console.error("Usage: prismic page-type set-repeatable <type-id> <true|false>");
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+
75
+ if (repeatableValue !== "true" && repeatableValue !== "false") {
76
+ console.error(`Invalid value: "${repeatableValue}". Must be "true" or "false".`);
77
+ process.exitCode = 1;
78
+ return;
79
+ }
80
+
81
+ const repeatable = repeatableValue === "true";
82
+
83
+ const projectRoot = await findUpward("package.json");
84
+ if (!projectRoot) {
85
+ console.error("Could not find project root (no package.json found)");
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+
90
+ const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
91
+
92
+ // Read and parse the model
93
+ let model: CustomType;
94
+ try {
95
+ const contents = await readFile(modelPath, "utf8");
96
+ const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
97
+ if (!result.success) {
98
+ console.error(`Invalid page type model: ${modelPath.href}`);
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+ model = result.output as CustomType;
103
+ } catch (error) {
104
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
105
+ console.error(`Page type not found: ${typeId}\n`);
106
+ console.error(`Create it first with: prismic page-type create ${typeId}`);
107
+ process.exitCode = 1;
108
+ return;
109
+ }
110
+ if (error instanceof Error) {
111
+ console.error(`Failed to read page type: ${error.message}`);
112
+ } else {
113
+ console.error("Failed to read page type");
114
+ }
115
+ process.exitCode = 1;
116
+ return;
117
+ }
118
+
119
+ // Check if this is actually a page type
120
+ if (model.format !== "page") {
121
+ console.error(`"${typeId}" is not a page type (format: ${model.format ?? "custom"})`);
122
+ process.exitCode = 1;
123
+ return;
124
+ }
125
+
126
+ // Update the model
127
+ model.repeatable = repeatable;
128
+
129
+ // Write updated model
130
+ try {
131
+ await writeFile(modelPath, stringify(model));
132
+ } catch (error) {
133
+ if (error instanceof Error) {
134
+ console.error(`Failed to update page type: ${error.message}`);
135
+ } else {
136
+ console.error("Failed to update page type");
137
+ }
138
+ process.exitCode = 1;
139
+ return;
140
+ }
141
+
142
+ const typeLabel = repeatable ? "repeatable" : "singleton";
143
+ console.info(`Set page type "${typeId}" to ${typeLabel}`);
144
+
145
+ if (!noTypes) {
146
+ try {
147
+ await buildTypes({ output: types });
148
+ console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
149
+ } catch (error) {
150
+ console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
151
+ }
152
+ }
153
+ }
@@ -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 page type.
11
+
12
+ USAGE
13
+ prismic page-type view <type-id> [flags]
14
+
15
+ ARGUMENTS
16
+ type-id Page type identifier (required)
17
+
18
+ FLAGS
19
+ --json Output as JSON
20
+ -h, --help Show help for command
21
+
22
+ EXAMPLES
23
+ prismic page-type view homepage
24
+ prismic page-type view homepage --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 pageTypeView(): Promise<void> {
37
+ const {
38
+ values: { help, json },
39
+ positionals: [typeId],
40
+ } = parseArgs({
41
+ args: process.argv.slice(4), // skip: node, script, "page-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 page-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 page 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(`Page type not found: ${typeId}\n`);
83
+ console.error(`Create it first with: prismic page-type create ${typeId}`);
84
+ process.exitCode = 1;
85
+ return;
86
+ }
87
+ if (error instanceof Error) {
88
+ console.error(`Failed to read page type: ${error.message}`);
89
+ } else {
90
+ console.error("Failed to read page type");
91
+ }
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+
96
+ // Check if this is actually a page type
97
+ if (model.format !== "page") {
98
+ console.error(`"${typeId}" is not a page type (format: ${model.format ?? "custom"})`);
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
+ }
@@ -0,0 +1,90 @@
1
+ import { parseArgs } from "node:util";
2
+
3
+ import { pageTypeAddField } from "./page-type-add-field";
4
+ import { pageTypeConnectSlice } from "./page-type-connect-slice";
5
+ import { pageTypeCreate } from "./page-type-create";
6
+ import { pageTypeDisconnectSlice } from "./page-type-disconnect-slice";
7
+ import { pageTypeList } from "./page-type-list";
8
+ import { pageTypeRemove } from "./page-type-remove";
9
+ import { pageTypeRemoveField } from "./page-type-remove-field";
10
+ import { pageTypeSetName } from "./page-type-set-name";
11
+ import { pageTypeSetRepeatable } from "./page-type-set-repeatable";
12
+ import { pageTypeView } from "./page-type-view";
13
+
14
+ const HELP = `
15
+ Manage page types in a Prismic repository.
16
+
17
+ USAGE
18
+ prismic page-type <command> [flags]
19
+
20
+ COMMANDS
21
+ create Create a new page type
22
+ list List all page types
23
+ view View details of a page type
24
+ remove Remove a page type
25
+ set-name Change a page type's display name
26
+ set-repeatable Set whether a page type is repeatable
27
+ add-field Add a field to a page type
28
+ remove-field Remove a field from a page type
29
+ connect-slice Connect a shared slice to a page type
30
+ disconnect-slice Disconnect a shared slice from a page type
31
+
32
+ FLAGS
33
+ -h, --help Show help for command
34
+
35
+ LEARN MORE
36
+ Use \`prismic page-type <command> --help\` for more information about a command.
37
+ `.trim();
38
+
39
+ export async function pageType(): Promise<void> {
40
+ const {
41
+ positionals: [subcommand],
42
+ } = parseArgs({
43
+ args: process.argv.slice(3), // skip: node, script, "page-type"
44
+ options: {
45
+ help: { type: "boolean", short: "h" },
46
+ },
47
+ allowPositionals: true,
48
+ strict: false,
49
+ });
50
+
51
+ switch (subcommand) {
52
+ case "create":
53
+ await pageTypeCreate();
54
+ break;
55
+ case "list":
56
+ await pageTypeList();
57
+ break;
58
+ case "view":
59
+ await pageTypeView();
60
+ break;
61
+ case "remove":
62
+ await pageTypeRemove();
63
+ break;
64
+ case "set-name":
65
+ await pageTypeSetName();
66
+ break;
67
+ case "set-repeatable":
68
+ await pageTypeSetRepeatable();
69
+ break;
70
+ case "add-field":
71
+ await pageTypeAddField();
72
+ break;
73
+ case "remove-field":
74
+ await pageTypeRemoveField();
75
+ break;
76
+ case "connect-slice":
77
+ await pageTypeConnectSlice();
78
+ break;
79
+ case "disconnect-slice":
80
+ await pageTypeDisconnectSlice();
81
+ break;
82
+ default: {
83
+ if (subcommand) {
84
+ console.error(`Unknown page-type subcommand: ${subcommand}\n`);
85
+ process.exitCode = 1;
86
+ }
87
+ console.info(HELP);
88
+ }
89
+ }
90
+ }