@angeloashmore/prismic-cli-poc 0.0.0-canary.2ff9563
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +98 -0
- package/dist/index.mjs +1996 -0
- package/package.json +52 -0
- package/src/custom-type-add-field-boolean.ts +171 -0
- package/src/custom-type-add-field-color.ts +158 -0
- package/src/custom-type-add-field-date.ts +161 -0
- package/src/custom-type-add-field-embed.ts +158 -0
- package/src/custom-type-add-field-geo-point.ts +155 -0
- package/src/custom-type-add-field-image.ts +158 -0
- package/src/custom-type-add-field-key-text.ts +158 -0
- package/src/custom-type-add-field-link.ts +180 -0
- package/src/custom-type-add-field-number.ts +190 -0
- package/src/custom-type-add-field-rich-text.ts +181 -0
- package/src/custom-type-add-field-select.ts +164 -0
- package/src/custom-type-add-field-timestamp.ts +161 -0
- package/src/custom-type-add-field-uid.ts +158 -0
- package/src/custom-type-add-field.ts +111 -0
- package/src/custom-type-connect-slice.ts +221 -0
- package/src/custom-type-create.ts +92 -0
- package/src/custom-type-disconnect-slice.ts +179 -0
- package/src/custom-type-list.ts +110 -0
- package/src/custom-type-remove-field.ts +161 -0
- package/src/custom-type-remove.ts +126 -0
- package/src/custom-type-set-name.ts +128 -0
- package/src/custom-type-view.ts +118 -0
- package/src/custom-type.ts +85 -0
- package/src/index.ts +100 -0
- package/src/init.ts +62 -0
- package/src/lib/auth.ts +60 -0
- package/src/lib/config.ts +111 -0
- package/src/lib/file.ts +49 -0
- package/src/lib/json.ts +3 -0
- package/src/lib/request.ts +116 -0
- package/src/lib/slice.ts +112 -0
- package/src/lib/url.ts +25 -0
- package/src/locale-add.ts +116 -0
- package/src/locale-list.ts +107 -0
- package/src/locale-remove.ts +88 -0
- package/src/locale-set-default.ts +131 -0
- package/src/locale.ts +60 -0
- package/src/login.ts +143 -0
- package/src/logout.ts +36 -0
- package/src/page-type-add-field-boolean.ts +171 -0
- package/src/page-type-add-field-color.ts +158 -0
- package/src/page-type-add-field-date.ts +161 -0
- package/src/page-type-add-field-embed.ts +158 -0
- package/src/page-type-add-field-geo-point.ts +155 -0
- package/src/page-type-add-field-image.ts +158 -0
- package/src/page-type-add-field-key-text.ts +158 -0
- package/src/page-type-add-field-link.ts +180 -0
- package/src/page-type-add-field-number.ts +190 -0
- package/src/page-type-add-field-rich-text.ts +181 -0
- package/src/page-type-add-field-select.ts +164 -0
- package/src/page-type-add-field-timestamp.ts +161 -0
- package/src/page-type-add-field-uid.ts +158 -0
- package/src/page-type-add-field.ts +111 -0
- package/src/page-type-connect-slice.ts +221 -0
- package/src/page-type-create.ts +93 -0
- package/src/page-type-disconnect-slice.ts +179 -0
- package/src/page-type-list.ts +109 -0
- package/src/page-type-remove-field.ts +161 -0
- package/src/page-type-remove.ts +126 -0
- package/src/page-type-set-name.ts +128 -0
- package/src/page-type-set-repeatable.ts +137 -0
- package/src/page-type-view.ts +118 -0
- package/src/page-type.ts +90 -0
- package/src/preview-add.ts +126 -0
- package/src/preview-list.ts +106 -0
- package/src/preview-remove.ts +109 -0
- package/src/preview-set-name.ts +137 -0
- package/src/preview.ts +60 -0
- package/src/repo-create.ts +136 -0
- package/src/repo-list.ts +100 -0
- package/src/repo-set-name.ts +102 -0
- package/src/repo-view.ts +113 -0
- package/src/repo.ts +60 -0
- package/src/slice-add-field-boolean.ts +150 -0
- package/src/slice-add-field-color.ts +137 -0
- package/src/slice-add-field-date.ts +137 -0
- package/src/slice-add-field-embed.ts +137 -0
- package/src/slice-add-field-geo-point.ts +134 -0
- package/src/slice-add-field-image.ts +134 -0
- package/src/slice-add-field-key-text.ts +137 -0
- package/src/slice-add-field-link.ts +155 -0
- package/src/slice-add-field-number.ts +137 -0
- package/src/slice-add-field-rich-text.ts +160 -0
- package/src/slice-add-field-select.ts +143 -0
- package/src/slice-add-field-timestamp.ts +137 -0
- package/src/slice-add-field.ts +106 -0
- package/src/slice-add-variation.ts +137 -0
- package/src/slice-create.ts +129 -0
- package/src/slice-list-variations.ts +67 -0
- package/src/slice-list.ts +88 -0
- package/src/slice-remove-field.ts +117 -0
- package/src/slice-remove-variation.ts +108 -0
- package/src/slice-remove.ts +81 -0
- package/src/slice-rename.ts +112 -0
- package/src/slice-view.ts +77 -0
- package/src/slice.ts +90 -0
- package/src/sync.ts +309 -0
- package/src/token-create.ts +185 -0
- package/src/token-delete.ts +161 -0
- package/src/token-list.ts +212 -0
- package/src/token-set-name.ts +165 -0
- package/src/token.ts +60 -0
- package/src/webhook-add-header.ts +118 -0
- package/src/webhook-create.ts +152 -0
- package/src/webhook-disable.ts +109 -0
- package/src/webhook-enable.ts +132 -0
- package/src/webhook-list.ts +93 -0
- package/src/webhook-remove-header.ts +117 -0
- package/src/webhook-remove.ts +106 -0
- package/src/webhook-set-triggers.ts +148 -0
- package/src/webhook-status.ts +90 -0
- package/src/webhook-test.ts +106 -0
- package/src/webhook-view.ts +147 -0
- package/src/webhook.ts +95 -0
- package/src/whoami.ts +62 -0
|
@@ -0,0 +1,128 @@
|
|
|
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 { findUpward } from "./lib/file";
|
|
8
|
+
import { stringify } from "./lib/json";
|
|
9
|
+
|
|
10
|
+
const HELP = `
|
|
11
|
+
Change a page type's display name (label).
|
|
12
|
+
|
|
13
|
+
USAGE
|
|
14
|
+
prismic page-type set-name <type-id> <new-name> [flags]
|
|
15
|
+
|
|
16
|
+
ARGUMENTS
|
|
17
|
+
type-id Page type identifier (required)
|
|
18
|
+
new-name New display name (required)
|
|
19
|
+
|
|
20
|
+
FLAGS
|
|
21
|
+
-h, --help Show help for command
|
|
22
|
+
|
|
23
|
+
EXAMPLES
|
|
24
|
+
prismic page-type set-name homepage "Home Page"
|
|
25
|
+
prismic page-type set-name blog_post "Blog Post"
|
|
26
|
+
`.trim();
|
|
27
|
+
|
|
28
|
+
const CustomTypeSchema = v.object({
|
|
29
|
+
id: v.string(),
|
|
30
|
+
label: v.string(),
|
|
31
|
+
repeatable: v.boolean(),
|
|
32
|
+
status: v.boolean(),
|
|
33
|
+
format: v.optional(v.string()),
|
|
34
|
+
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export async function pageTypeSetName(): Promise<void> {
|
|
38
|
+
const {
|
|
39
|
+
values: { help },
|
|
40
|
+
positionals: [typeId, newName],
|
|
41
|
+
} = parseArgs({
|
|
42
|
+
args: process.argv.slice(4), // skip: node, script, "page-type", "set-name"
|
|
43
|
+
options: {
|
|
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 set-name <type-id> <new-name>");
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!newName) {
|
|
62
|
+
console.error("Missing required argument: new-name\n");
|
|
63
|
+
console.error("Usage: prismic page-type set-name <type-id> <new-name>");
|
|
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 modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
|
|
76
|
+
|
|
77
|
+
// Read and parse the model
|
|
78
|
+
let model: CustomType;
|
|
79
|
+
try {
|
|
80
|
+
const contents = await readFile(modelPath, "utf8");
|
|
81
|
+
const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
console.error(`Invalid page type model: ${modelPath.href}`);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
model = result.output as CustomType;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
90
|
+
console.error(`Page type not found: ${typeId}\n`);
|
|
91
|
+
console.error(`Create it first with: prismic page-type create ${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
|
+
// Update the model
|
|
112
|
+
model.label = newName;
|
|
113
|
+
|
|
114
|
+
// Write updated model
|
|
115
|
+
try {
|
|
116
|
+
await writeFile(modelPath, stringify(model));
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (error instanceof Error) {
|
|
119
|
+
console.error(`Failed to update page type: ${error.message}`);
|
|
120
|
+
} else {
|
|
121
|
+
console.error("Failed to update page type");
|
|
122
|
+
}
|
|
123
|
+
process.exitCode = 1;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.info(`Renamed page type "${typeId}" to "${newName}"`);
|
|
128
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
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 { findUpward } from "./lib/file";
|
|
8
|
+
import { stringify } from "./lib/json";
|
|
9
|
+
|
|
10
|
+
const HELP = `
|
|
11
|
+
Set whether a page type is repeatable.
|
|
12
|
+
|
|
13
|
+
USAGE
|
|
14
|
+
prismic page-type set-repeatable <type-id> <true|false> [flags]
|
|
15
|
+
|
|
16
|
+
ARGUMENTS
|
|
17
|
+
type-id Page type identifier (required)
|
|
18
|
+
true|false Repeatable value (required)
|
|
19
|
+
|
|
20
|
+
FLAGS
|
|
21
|
+
-h, --help Show help for command
|
|
22
|
+
|
|
23
|
+
EXAMPLES
|
|
24
|
+
prismic page-type set-repeatable homepage true
|
|
25
|
+
prismic page-type set-repeatable settings false
|
|
26
|
+
`.trim();
|
|
27
|
+
|
|
28
|
+
const CustomTypeSchema = v.object({
|
|
29
|
+
id: v.string(),
|
|
30
|
+
label: v.string(),
|
|
31
|
+
repeatable: v.boolean(),
|
|
32
|
+
status: v.boolean(),
|
|
33
|
+
format: v.optional(v.string()),
|
|
34
|
+
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export async function pageTypeSetRepeatable(): Promise<void> {
|
|
38
|
+
const {
|
|
39
|
+
values: { help },
|
|
40
|
+
positionals: [typeId, repeatableValue],
|
|
41
|
+
} = parseArgs({
|
|
42
|
+
args: process.argv.slice(4), // skip: node, script, "page-type", "set-repeatable"
|
|
43
|
+
options: {
|
|
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 set-repeatable <type-id> <true|false>");
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!repeatableValue) {
|
|
62
|
+
console.error("Missing required argument: true|false\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 !== "true" && repeatableValue !== "false") {
|
|
69
|
+
console.error(`Invalid value: "${repeatableValue}". Must be "true" or "false".`);
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const repeatable = repeatableValue === "true";
|
|
75
|
+
|
|
76
|
+
const projectRoot = await findUpward("package.json");
|
|
77
|
+
if (!projectRoot) {
|
|
78
|
+
console.error("Could not find project root (no package.json found)");
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
|
|
84
|
+
|
|
85
|
+
// Read and parse the model
|
|
86
|
+
let model: CustomType;
|
|
87
|
+
try {
|
|
88
|
+
const contents = await readFile(modelPath, "utf8");
|
|
89
|
+
const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
console.error(`Invalid page type model: ${modelPath.href}`);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
model = result.output as CustomType;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
98
|
+
console.error(`Page type not found: ${typeId}\n`);
|
|
99
|
+
console.error(`Create it first with: prismic page-type create ${typeId}`);
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (error instanceof Error) {
|
|
104
|
+
console.error(`Failed to read page type: ${error.message}`);
|
|
105
|
+
} else {
|
|
106
|
+
console.error("Failed to read page type");
|
|
107
|
+
}
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Check if this is actually a page type
|
|
113
|
+
if (model.format !== "page") {
|
|
114
|
+
console.error(`"${typeId}" is not a page type (format: ${model.format ?? "custom"})`);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Update the model
|
|
120
|
+
model.repeatable = repeatable;
|
|
121
|
+
|
|
122
|
+
// Write updated model
|
|
123
|
+
try {
|
|
124
|
+
await writeFile(modelPath, stringify(model));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (error instanceof Error) {
|
|
127
|
+
console.error(`Failed to update page type: ${error.message}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.error("Failed to update page type");
|
|
130
|
+
}
|
|
131
|
+
process.exitCode = 1;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const typeLabel = repeatable ? "repeatable" : "singleton";
|
|
136
|
+
console.info(`Set page type "${typeId}" to ${typeLabel}`);
|
|
137
|
+
}
|
|
@@ -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
|
+
}
|
package/src/page-type.ts
ADDED
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
|
|
3
|
+
import { isAuthenticated } from "./lib/auth";
|
|
4
|
+
import { safeGetRepositoryFromConfig } from "./lib/config";
|
|
5
|
+
import { stringify } from "./lib/json";
|
|
6
|
+
import { ForbiddenRequestError, request } from "./lib/request";
|
|
7
|
+
import { getRepoUrl } from "./lib/url";
|
|
8
|
+
|
|
9
|
+
const HELP = `
|
|
10
|
+
Add a preview configuration to a Prismic repository.
|
|
11
|
+
|
|
12
|
+
By default, this command reads the repository from prismic.config.json at the
|
|
13
|
+
project root.
|
|
14
|
+
|
|
15
|
+
USAGE
|
|
16
|
+
prismic preview add <url> [flags]
|
|
17
|
+
|
|
18
|
+
ARGUMENTS
|
|
19
|
+
<url> Preview URL (e.g. https://example.com/api/preview)
|
|
20
|
+
|
|
21
|
+
FLAGS
|
|
22
|
+
-n, --name string Display name (defaults to hostname)
|
|
23
|
+
-r, --repo string Repository domain
|
|
24
|
+
-h, --help Show help for command
|
|
25
|
+
|
|
26
|
+
LEARN MORE
|
|
27
|
+
Use \`prismic <command> <subcommand> --help\` for more information about a command.
|
|
28
|
+
`.trim();
|
|
29
|
+
|
|
30
|
+
export async function previewAdd(): Promise<void> {
|
|
31
|
+
const {
|
|
32
|
+
values: { help, name, repo = await safeGetRepositoryFromConfig() },
|
|
33
|
+
positionals: [previewUrl],
|
|
34
|
+
} = parseArgs({
|
|
35
|
+
args: process.argv.slice(4), // skip: node, script, "preview", "add"
|
|
36
|
+
options: {
|
|
37
|
+
name: { type: "string", short: "n" },
|
|
38
|
+
repo: { type: "string", short: "r" },
|
|
39
|
+
help: { type: "boolean", short: "h" },
|
|
40
|
+
},
|
|
41
|
+
allowPositionals: true,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (help) {
|
|
45
|
+
console.info(HELP);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!previewUrl) {
|
|
50
|
+
console.error("Missing required argument: <url>");
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!repo) {
|
|
56
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const authenticated = await isAuthenticated();
|
|
62
|
+
if (!authenticated) {
|
|
63
|
+
handleUnauthenticated();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const parsed = parsePreviewUrl(previewUrl);
|
|
68
|
+
if (!parsed) {
|
|
69
|
+
console.error(`Invalid URL: ${previewUrl}`);
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const displayName = name || parsed.hostname;
|
|
75
|
+
|
|
76
|
+
const response = await addPreview(repo, {
|
|
77
|
+
name: displayName,
|
|
78
|
+
websiteURL: parsed.websiteURL,
|
|
79
|
+
resolverPath: parsed.resolverPath,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
if (response.error instanceof ForbiddenRequestError) {
|
|
84
|
+
handleUnauthenticated();
|
|
85
|
+
} else {
|
|
86
|
+
console.error(`Failed to add preview: ${stringify(response.value)}`);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.info(`Preview added: ${previewUrl}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function parsePreviewUrl(
|
|
96
|
+
url: string,
|
|
97
|
+
): { websiteURL: string; resolverPath: string | undefined; hostname: string } | undefined {
|
|
98
|
+
try {
|
|
99
|
+
const parsed = new URL(url);
|
|
100
|
+
const websiteURL = `${parsed.protocol}//${parsed.host}`;
|
|
101
|
+
const resolverPath = parsed.pathname === "/" ? undefined : parsed.pathname;
|
|
102
|
+
return { websiteURL, resolverPath, hostname: parsed.hostname };
|
|
103
|
+
} catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function addPreview(
|
|
109
|
+
repo: string,
|
|
110
|
+
config: { name: string; websiteURL: string; resolverPath: string | undefined },
|
|
111
|
+
) {
|
|
112
|
+
const url = new URL("/previews/new", await getRepoUrl(repo));
|
|
113
|
+
return await request(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
body: {
|
|
116
|
+
name: config.name,
|
|
117
|
+
websiteURL: config.websiteURL,
|
|
118
|
+
resolverPath: config.resolverPath,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function handleUnauthenticated() {
|
|
124
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
|
|
4
|
+
import { isAuthenticated } from "./lib/auth";
|
|
5
|
+
import { safeGetRepositoryFromConfig } from "./lib/config";
|
|
6
|
+
import { stringify } from "./lib/json";
|
|
7
|
+
import { ForbiddenRequestError, type ParsedRequestResponse, request } from "./lib/request";
|
|
8
|
+
import { getRepoUrl } from "./lib/url";
|
|
9
|
+
|
|
10
|
+
const HELP = `
|
|
11
|
+
List all preview configurations in a Prismic repository.
|
|
12
|
+
|
|
13
|
+
By default, this command reads the repository from prismic.config.json at the
|
|
14
|
+
project root.
|
|
15
|
+
|
|
16
|
+
USAGE
|
|
17
|
+
prismic preview list [flags]
|
|
18
|
+
|
|
19
|
+
FLAGS
|
|
20
|
+
--json Output as JSON
|
|
21
|
+
-r, --repo string Repository domain
|
|
22
|
+
-h, --help Show help for command
|
|
23
|
+
|
|
24
|
+
LEARN MORE
|
|
25
|
+
Use \`prismic <command> <subcommand> --help\` for more information about a command.
|
|
26
|
+
`.trim();
|
|
27
|
+
|
|
28
|
+
export async function previewList(): Promise<void> {
|
|
29
|
+
const {
|
|
30
|
+
values: { help, repo = await safeGetRepositoryFromConfig(), json },
|
|
31
|
+
} = parseArgs({
|
|
32
|
+
args: process.argv.slice(4), // skip: node, script, "preview", "list"
|
|
33
|
+
options: {
|
|
34
|
+
json: { type: "boolean" },
|
|
35
|
+
repo: { type: "string", short: "r" },
|
|
36
|
+
help: { type: "boolean", short: "h" },
|
|
37
|
+
},
|
|
38
|
+
allowPositionals: false,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (help) {
|
|
42
|
+
console.info(HELP);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!repo) {
|
|
47
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const authenticated = await isAuthenticated();
|
|
53
|
+
if (!authenticated) {
|
|
54
|
+
handleUnauthenticated();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const response = await getPreviews(repo);
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
if (response.error instanceof ForbiddenRequestError) {
|
|
61
|
+
handleUnauthenticated();
|
|
62
|
+
} else if (v.isValiError(response.error)) {
|
|
63
|
+
console.error(
|
|
64
|
+
`Failed to list previews: Invalid response: ${stringify(response.error.issues)}`,
|
|
65
|
+
);
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
} else {
|
|
68
|
+
console.error(`Failed to list previews: ${stringify(response.value)}`);
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const previews = response.value.results;
|
|
75
|
+
if (json) {
|
|
76
|
+
console.info(stringify(previews));
|
|
77
|
+
} else {
|
|
78
|
+
for (const preview of previews) {
|
|
79
|
+
console.info(`${preview.url} ${preview.label}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const PreviewSchema = v.object({
|
|
85
|
+
id: v.string(),
|
|
86
|
+
label: v.string(),
|
|
87
|
+
url: v.string(),
|
|
88
|
+
});
|
|
89
|
+
export type Preview = v.InferOutput<typeof PreviewSchema>;
|
|
90
|
+
|
|
91
|
+
const GetPreviewsResponseSchema = v.object({
|
|
92
|
+
results: v.array(PreviewSchema),
|
|
93
|
+
});
|
|
94
|
+
type GetPreviewsResponse = v.InferOutput<typeof GetPreviewsResponseSchema>;
|
|
95
|
+
|
|
96
|
+
export async function getPreviews(
|
|
97
|
+
repo: string,
|
|
98
|
+
): Promise<ParsedRequestResponse<GetPreviewsResponse>> {
|
|
99
|
+
const url = new URL("/core/repository/preview_configs", await getRepoUrl(repo));
|
|
100
|
+
return await request(url, { schema: GetPreviewsResponseSchema });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function handleUnauthenticated() {
|
|
104
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
}
|