@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.
- package/LICENSE +202 -0
- package/README.md +98 -0
- package/dist/index.mjs +2508 -0
- package/package.json +53 -0
- package/src/codegen-types.ts +82 -0
- package/src/codegen.ts +45 -0
- package/src/custom-type-add-field-boolean.ts +222 -0
- package/src/custom-type-add-field-color.ts +205 -0
- package/src/custom-type-add-field-date.ts +208 -0
- package/src/custom-type-add-field-embed.ts +205 -0
- package/src/custom-type-add-field-geo-point.ts +202 -0
- package/src/custom-type-add-field-group.ts +179 -0
- package/src/custom-type-add-field-image.ts +205 -0
- package/src/custom-type-add-field-key-text.ts +205 -0
- package/src/custom-type-add-field-link.ts +228 -0
- package/src/custom-type-add-field-number.ts +237 -0
- package/src/custom-type-add-field-rich-text.ts +229 -0
- package/src/custom-type-add-field-select.ts +211 -0
- package/src/custom-type-add-field-timestamp.ts +208 -0
- package/src/custom-type-add-field-uid.ts +188 -0
- package/src/custom-type-add-field.ts +116 -0
- package/src/custom-type-connect-slice.ts +214 -0
- package/src/custom-type-create.ts +112 -0
- package/src/custom-type-disconnect-slice.ts +171 -0
- package/src/custom-type-list.ts +110 -0
- package/src/custom-type-remove-field.ts +171 -0
- package/src/custom-type-remove.ts +138 -0
- package/src/custom-type-set-name.ts +138 -0
- package/src/custom-type-view.ts +118 -0
- package/src/custom-type.ts +85 -0
- package/src/docs-fetch.ts +146 -0
- package/src/docs-list.ts +131 -0
- package/src/docs.ts +54 -0
- package/src/index.ts +132 -0
- package/src/init.ts +64 -0
- package/src/lib/auth.ts +83 -0
- package/src/lib/config.ts +111 -0
- package/src/lib/custom-types-api.ts +438 -0
- package/src/lib/field-path.ts +81 -0
- package/src/lib/file.ts +49 -0
- package/src/lib/framework.ts +143 -0
- package/src/lib/json.ts +3 -0
- package/src/lib/request.ts +116 -0
- package/src/lib/slice.ts +115 -0
- package/src/lib/string.ts +6 -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 +152 -0
- package/src/logout.ts +36 -0
- package/src/page-type-add-field-boolean.ts +238 -0
- package/src/page-type-add-field-color.ts +224 -0
- package/src/page-type-add-field-date.ts +227 -0
- package/src/page-type-add-field-embed.ts +224 -0
- package/src/page-type-add-field-geo-point.ts +221 -0
- package/src/page-type-add-field-group.ts +198 -0
- package/src/page-type-add-field-image.ts +224 -0
- package/src/page-type-add-field-key-text.ts +224 -0
- package/src/page-type-add-field-link.ts +247 -0
- package/src/page-type-add-field-number.ts +256 -0
- package/src/page-type-add-field-rich-text.ts +248 -0
- package/src/page-type-add-field-select.ts +230 -0
- package/src/page-type-add-field-timestamp.ts +227 -0
- package/src/page-type-add-field-uid.ts +207 -0
- package/src/page-type-add-field.ts +116 -0
- package/src/page-type-connect-slice.ts +214 -0
- package/src/page-type-create.ts +161 -0
- package/src/page-type-disconnect-slice.ts +171 -0
- package/src/page-type-list.ts +109 -0
- package/src/page-type-remove-field.ts +171 -0
- package/src/page-type-remove.ts +138 -0
- package/src/page-type-set-name.ts +138 -0
- package/src/page-type-set-repeatable.ts +147 -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-get-simulator.ts +104 -0
- package/src/preview-list.ts +106 -0
- package/src/preview-remove-simulator.ts +80 -0
- package/src/preview-remove.ts +109 -0
- package/src/preview-set-name.ts +137 -0
- package/src/preview-set-simulator.ts +116 -0
- package/src/preview.ts +75 -0
- package/src/pull.ts +242 -0
- package/src/push.ts +405 -0
- package/src/repo-create.ts +195 -0
- package/src/repo-get-access.ts +86 -0
- package/src/repo-list.ts +100 -0
- package/src/repo-set-access.ts +100 -0
- package/src/repo-set-name.ts +102 -0
- package/src/repo-view.ts +113 -0
- package/src/repo.ts +70 -0
- package/src/slice-add-field-boolean.ts +240 -0
- package/src/slice-add-field-color.ts +226 -0
- package/src/slice-add-field-date.ts +226 -0
- package/src/slice-add-field-embed.ts +226 -0
- package/src/slice-add-field-geo-point.ts +223 -0
- package/src/slice-add-field-group.ts +191 -0
- package/src/slice-add-field-image.ts +223 -0
- package/src/slice-add-field-key-text.ts +226 -0
- package/src/slice-add-field-link.ts +245 -0
- package/src/slice-add-field-number.ts +226 -0
- package/src/slice-add-field-rich-text.ts +250 -0
- package/src/slice-add-field-select.ts +232 -0
- package/src/slice-add-field-timestamp.ts +226 -0
- package/src/slice-add-field.ts +111 -0
- package/src/slice-add-variation.ts +139 -0
- package/src/slice-create.ts +203 -0
- package/src/slice-list-variations.ts +67 -0
- package/src/slice-list.ts +88 -0
- package/src/slice-remove-field.ts +122 -0
- package/src/slice-remove-variation.ts +112 -0
- package/src/slice-remove.ts +91 -0
- package/src/slice-rename.ts +122 -0
- package/src/slice-set-screenshot.ts +235 -0
- package/src/slice-view.ts +80 -0
- package/src/slice.ts +95 -0
- package/src/status.ts +873 -0
- package/src/token-create.ts +203 -0
- package/src/token-delete.ts +182 -0
- package/src/token-list.ts +223 -0
- package/src/token-set-name.ts +193 -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,109 @@
|
|
|
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
|
+
import { getPreviews } from "./preview-list";
|
|
9
|
+
|
|
10
|
+
const HELP = `
|
|
11
|
+
Remove a preview configuration from 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 remove <url> [flags]
|
|
18
|
+
|
|
19
|
+
ARGUMENTS
|
|
20
|
+
<url> Preview URL to remove
|
|
21
|
+
|
|
22
|
+
FLAGS
|
|
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 previewRemove(): Promise<void> {
|
|
31
|
+
const {
|
|
32
|
+
values: { help, repo = await safeGetRepositoryFromConfig() },
|
|
33
|
+
positionals: [previewUrl],
|
|
34
|
+
} = parseArgs({
|
|
35
|
+
args: process.argv.slice(4), // skip: node, script, "preview", "remove"
|
|
36
|
+
options: {
|
|
37
|
+
repo: { type: "string", short: "r" },
|
|
38
|
+
help: { type: "boolean", short: "h" },
|
|
39
|
+
},
|
|
40
|
+
allowPositionals: true,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (help) {
|
|
44
|
+
console.info(HELP);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!previewUrl) {
|
|
49
|
+
console.error("Missing required argument: <url>");
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!repo) {
|
|
55
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const authenticated = await isAuthenticated();
|
|
61
|
+
if (!authenticated) {
|
|
62
|
+
handleUnauthenticated();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const previewsResponse = await getPreviews(repo);
|
|
67
|
+
if (!previewsResponse.ok) {
|
|
68
|
+
if (previewsResponse.error instanceof ForbiddenRequestError) {
|
|
69
|
+
handleUnauthenticated();
|
|
70
|
+
} else {
|
|
71
|
+
console.error(`Failed to fetch previews: ${stringify(previewsResponse.value)}`);
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const preview = previewsResponse.value.results.find((p) => p.url === previewUrl);
|
|
78
|
+
if (!preview) {
|
|
79
|
+
console.error(`Preview not found: ${previewUrl}`);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const response = await removePreview(repo, preview.id);
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
if (response.error instanceof ForbiddenRequestError) {
|
|
87
|
+
handleUnauthenticated();
|
|
88
|
+
} else {
|
|
89
|
+
console.error(`Failed to remove preview: ${stringify(response.value)}`);
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.info(`Preview removed: ${previewUrl}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function removePreview(repo: string, id: string) {
|
|
99
|
+
const url = new URL(`/previews/delete/${id}`, await getRepoUrl(repo));
|
|
100
|
+
return await request(url, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
body: {},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function handleUnauthenticated() {
|
|
107
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
import { parsePreviewUrl } from "./preview-add";
|
|
9
|
+
import { getPreviews } from "./preview-list";
|
|
10
|
+
|
|
11
|
+
const HELP = `
|
|
12
|
+
Update the name of a preview configuration.
|
|
13
|
+
|
|
14
|
+
By default, this command reads the repository from prismic.config.json at the
|
|
15
|
+
project root.
|
|
16
|
+
|
|
17
|
+
USAGE
|
|
18
|
+
prismic preview set-name <url> <name> [flags]
|
|
19
|
+
|
|
20
|
+
ARGUMENTS
|
|
21
|
+
<url> Preview URL to update
|
|
22
|
+
<name> New display name
|
|
23
|
+
|
|
24
|
+
FLAGS
|
|
25
|
+
-r, --repo string Repository domain
|
|
26
|
+
-h, --help Show help for command
|
|
27
|
+
|
|
28
|
+
LEARN MORE
|
|
29
|
+
Use \`prismic <command> <subcommand> --help\` for more information about a command.
|
|
30
|
+
`.trim();
|
|
31
|
+
|
|
32
|
+
export async function previewSetName(): Promise<void> {
|
|
33
|
+
const {
|
|
34
|
+
values: { help, repo = await safeGetRepositoryFromConfig() },
|
|
35
|
+
positionals: [previewUrl, name],
|
|
36
|
+
} = parseArgs({
|
|
37
|
+
args: process.argv.slice(4), // skip: node, script, "preview", "set-name"
|
|
38
|
+
options: {
|
|
39
|
+
repo: { type: "string", short: "r" },
|
|
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 (!previewUrl) {
|
|
51
|
+
console.error("Missing required argument: <url>");
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!name) {
|
|
57
|
+
console.error("Missing required argument: <name>");
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!repo) {
|
|
63
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const authenticated = await isAuthenticated();
|
|
69
|
+
if (!authenticated) {
|
|
70
|
+
handleUnauthenticated();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const parsed = parsePreviewUrl(previewUrl);
|
|
75
|
+
if (!parsed) {
|
|
76
|
+
console.error(`Invalid URL: ${previewUrl}`);
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const previewsResponse = await getPreviews(repo);
|
|
82
|
+
if (!previewsResponse.ok) {
|
|
83
|
+
if (previewsResponse.error instanceof ForbiddenRequestError) {
|
|
84
|
+
handleUnauthenticated();
|
|
85
|
+
} else {
|
|
86
|
+
console.error(`Failed to fetch previews: ${stringify(previewsResponse.value)}`);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const preview = previewsResponse.value.results.find((p) => p.url === previewUrl);
|
|
93
|
+
if (!preview) {
|
|
94
|
+
console.error(`Preview not found: ${previewUrl}`);
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const response = await updatePreview(repo, preview.id, {
|
|
100
|
+
name,
|
|
101
|
+
websiteURL: parsed.websiteURL,
|
|
102
|
+
resolverPath: parsed.resolverPath,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
if (response.error instanceof ForbiddenRequestError) {
|
|
107
|
+
handleUnauthenticated();
|
|
108
|
+
} else {
|
|
109
|
+
console.error(`Failed to update preview: ${stringify(response.value)}`);
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.info(`Preview updated: ${previewUrl}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function updatePreview(
|
|
119
|
+
repo: string,
|
|
120
|
+
id: string,
|
|
121
|
+
config: { name: string; websiteURL: string; resolverPath: string | undefined },
|
|
122
|
+
) {
|
|
123
|
+
const url = new URL(`/previews/save/${id}`, await getRepoUrl(repo));
|
|
124
|
+
return await request(url, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
body: {
|
|
127
|
+
name: config.name,
|
|
128
|
+
websiteURL: config.websiteURL,
|
|
129
|
+
resolverPath: config.resolverPath,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function handleUnauthenticated() {
|
|
135
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
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
|
+
Set the slice simulator URL for a Prismic repository.
|
|
11
|
+
|
|
12
|
+
If the URL pathname does not end with /slice-simulator, it is appended
|
|
13
|
+
automatically.
|
|
14
|
+
|
|
15
|
+
By default, this command reads the repository from prismic.config.json at the
|
|
16
|
+
project root.
|
|
17
|
+
|
|
18
|
+
USAGE
|
|
19
|
+
prismic preview set-simulator <url> [flags]
|
|
20
|
+
|
|
21
|
+
ARGUMENTS
|
|
22
|
+
<url> Simulator URL (e.g. https://example.com/slice-simulator)
|
|
23
|
+
|
|
24
|
+
FLAGS
|
|
25
|
+
-r, --repo string Repository domain
|
|
26
|
+
-h, --help Show help for command
|
|
27
|
+
|
|
28
|
+
EXAMPLES
|
|
29
|
+
prismic preview set-simulator https://my-site.com
|
|
30
|
+
prismic preview set-simulator http://localhost:3000/slice-simulator
|
|
31
|
+
|
|
32
|
+
LEARN MORE
|
|
33
|
+
Use \`prismic <command> <subcommand> --help\` for more information about a command.
|
|
34
|
+
`.trim();
|
|
35
|
+
|
|
36
|
+
export async function previewSetSimulator(): Promise<void> {
|
|
37
|
+
const {
|
|
38
|
+
values: { help, repo = await safeGetRepositoryFromConfig() },
|
|
39
|
+
positionals: [urlArg],
|
|
40
|
+
} = parseArgs({
|
|
41
|
+
args: process.argv.slice(4), // skip: node, script, "preview", "set-simulator"
|
|
42
|
+
options: {
|
|
43
|
+
repo: { type: "string", short: "r" },
|
|
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 (!urlArg) {
|
|
55
|
+
console.error("Missing required argument: <url>");
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!repo) {
|
|
61
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const authenticated = await isAuthenticated();
|
|
67
|
+
if (!authenticated) {
|
|
68
|
+
handleUnauthenticated();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const simulatorUrl = normalizeSimulatorUrl(urlArg);
|
|
73
|
+
if (!simulatorUrl) {
|
|
74
|
+
console.error(`Invalid URL: ${urlArg}`);
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const response = await setSimulatorUrl(repo, simulatorUrl);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
if (response.error instanceof ForbiddenRequestError) {
|
|
82
|
+
handleUnauthenticated();
|
|
83
|
+
} else {
|
|
84
|
+
console.error(`Failed to set simulator URL: ${stringify(response.value)}`);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.info(`Simulator URL set: ${simulatorUrl}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function normalizeSimulatorUrl(url: string): string | undefined {
|
|
94
|
+
try {
|
|
95
|
+
const parsed = new URL(url);
|
|
96
|
+
if (!parsed.pathname.endsWith("/slice-simulator")) {
|
|
97
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "") + "/slice-simulator";
|
|
98
|
+
}
|
|
99
|
+
return parsed.toString();
|
|
100
|
+
} catch {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function setSimulatorUrl(repo: string, simulatorUrl: string) {
|
|
106
|
+
const url = new URL("/core/repository", await getRepoUrl(repo));
|
|
107
|
+
return await request(url, {
|
|
108
|
+
method: "PATCH",
|
|
109
|
+
body: { simulator_url: simulatorUrl },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function handleUnauthenticated() {
|
|
114
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
}
|
package/src/preview.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
|
|
3
|
+
import { previewAdd } from "./preview-add";
|
|
4
|
+
import { previewGetSimulator } from "./preview-get-simulator";
|
|
5
|
+
import { previewList } from "./preview-list";
|
|
6
|
+
import { previewRemove } from "./preview-remove";
|
|
7
|
+
import { previewRemoveSimulator } from "./preview-remove-simulator";
|
|
8
|
+
import { previewSetName } from "./preview-set-name";
|
|
9
|
+
import { previewSetSimulator } from "./preview-set-simulator";
|
|
10
|
+
|
|
11
|
+
const HELP = `
|
|
12
|
+
Manage preview configurations in a Prismic repository.
|
|
13
|
+
|
|
14
|
+
USAGE
|
|
15
|
+
prismic preview <command> [flags]
|
|
16
|
+
|
|
17
|
+
COMMANDS
|
|
18
|
+
add Add a preview configuration
|
|
19
|
+
list List preview configurations
|
|
20
|
+
remove Remove a preview configuration
|
|
21
|
+
set-name Update a preview's name
|
|
22
|
+
set-simulator Set the slice simulator URL
|
|
23
|
+
get-simulator Show the slice simulator URL
|
|
24
|
+
remove-simulator Remove the slice simulator URL
|
|
25
|
+
|
|
26
|
+
FLAGS
|
|
27
|
+
-h, --help Show help for command
|
|
28
|
+
|
|
29
|
+
LEARN MORE
|
|
30
|
+
Use \`prismic preview <command> --help\` for more information about a command.
|
|
31
|
+
`.trim();
|
|
32
|
+
|
|
33
|
+
export async function preview(): Promise<void> {
|
|
34
|
+
const {
|
|
35
|
+
positionals: [subcommand],
|
|
36
|
+
} = parseArgs({
|
|
37
|
+
args: process.argv.slice(3), // skip: node, script, "preview"
|
|
38
|
+
options: {
|
|
39
|
+
help: { type: "boolean", short: "h" },
|
|
40
|
+
},
|
|
41
|
+
allowPositionals: true,
|
|
42
|
+
strict: false,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
switch (subcommand) {
|
|
46
|
+
case "add":
|
|
47
|
+
await previewAdd();
|
|
48
|
+
break;
|
|
49
|
+
case "list":
|
|
50
|
+
await previewList();
|
|
51
|
+
break;
|
|
52
|
+
case "remove":
|
|
53
|
+
await previewRemove();
|
|
54
|
+
break;
|
|
55
|
+
case "set-name":
|
|
56
|
+
await previewSetName();
|
|
57
|
+
break;
|
|
58
|
+
case "set-simulator":
|
|
59
|
+
await previewSetSimulator();
|
|
60
|
+
break;
|
|
61
|
+
case "get-simulator":
|
|
62
|
+
await previewGetSimulator();
|
|
63
|
+
break;
|
|
64
|
+
case "remove-simulator":
|
|
65
|
+
await previewRemoveSimulator();
|
|
66
|
+
break;
|
|
67
|
+
default: {
|
|
68
|
+
if (subcommand) {
|
|
69
|
+
console.error(`Unknown preview subcommand: ${subcommand}\n`);
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
}
|
|
72
|
+
console.info(HELP);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/pull.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
|
|
4
|
+
import { buildTypes } from "./codegen-types";
|
|
5
|
+
import { isAuthenticated } from "./lib/auth";
|
|
6
|
+
import { safeGetRepositoryFromConfig } from "./lib/config";
|
|
7
|
+
import { fetchRemoteCustomTypes, fetchRemoteSlices } from "./lib/custom-types-api";
|
|
8
|
+
import { findUpward } from "./lib/file";
|
|
9
|
+
import { stringify } from "./lib/json";
|
|
10
|
+
import { getSlicesDirectory, pascalCase } from "./lib/slice";
|
|
11
|
+
|
|
12
|
+
const HELP = `
|
|
13
|
+
Pull custom types and slices from Prismic to local files.
|
|
14
|
+
|
|
15
|
+
By default, this command reads the repository from prismic.config.json at the
|
|
16
|
+
project root.
|
|
17
|
+
|
|
18
|
+
USAGE
|
|
19
|
+
prismic pull [flags]
|
|
20
|
+
|
|
21
|
+
FLAGS
|
|
22
|
+
-r, --repo string Repository domain
|
|
23
|
+
--dry-run Show what would be pulled without writing files
|
|
24
|
+
--types-only Only pull custom types
|
|
25
|
+
--slices-only Only pull slices
|
|
26
|
+
--json Output as JSON
|
|
27
|
+
--types string Output file for generated types (default: "prismicio-types.d.ts")
|
|
28
|
+
-h, --help Show help for command
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
prismic pull
|
|
32
|
+
prismic pull --repo my-repo
|
|
33
|
+
prismic pull --dry-run
|
|
34
|
+
prismic pull --types-only
|
|
35
|
+
`.trim();
|
|
36
|
+
|
|
37
|
+
export async function pull(): Promise<void> {
|
|
38
|
+
const {
|
|
39
|
+
values: {
|
|
40
|
+
help,
|
|
41
|
+
repo = await safeGetRepositoryFromConfig(),
|
|
42
|
+
"dry-run": dryRun,
|
|
43
|
+
"types-only": typesOnly,
|
|
44
|
+
"slices-only": slicesOnly,
|
|
45
|
+
json,
|
|
46
|
+
types,
|
|
47
|
+
},
|
|
48
|
+
} = parseArgs({
|
|
49
|
+
args: process.argv.slice(3), // skip: node, script, "pull"
|
|
50
|
+
options: {
|
|
51
|
+
repo: { type: "string", short: "r" },
|
|
52
|
+
"dry-run": { type: "boolean" },
|
|
53
|
+
"types-only": { type: "boolean" },
|
|
54
|
+
"slices-only": { type: "boolean" },
|
|
55
|
+
json: { type: "boolean" },
|
|
56
|
+
types: { type: "string" },
|
|
57
|
+
help: { type: "boolean", short: "h" },
|
|
58
|
+
},
|
|
59
|
+
allowPositionals: false,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (help) {
|
|
63
|
+
console.info(HELP);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!repo) {
|
|
68
|
+
console.error("Missing prismic.config.json or --repo option");
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Check authentication
|
|
74
|
+
if (!(await isAuthenticated())) {
|
|
75
|
+
console.error("Not logged in. Run `prismic login` first.");
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!json) {
|
|
81
|
+
console.info(`Pulling from repository: ${repo}\n`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Fetch remote data in parallel
|
|
85
|
+
const shouldFetchTypes = !slicesOnly;
|
|
86
|
+
const shouldFetchSlices = !typesOnly;
|
|
87
|
+
|
|
88
|
+
const [customTypesResult, slicesResult] = await Promise.all([
|
|
89
|
+
shouldFetchTypes
|
|
90
|
+
? fetchRemoteCustomTypes(repo)
|
|
91
|
+
: Promise.resolve({ ok: true, value: [] } as const),
|
|
92
|
+
shouldFetchSlices ? fetchRemoteSlices(repo) : Promise.resolve({ ok: true, value: [] } as const),
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
if (!customTypesResult.ok) {
|
|
96
|
+
console.error(`Failed to fetch custom types: ${customTypesResult.error}`);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!slicesResult.ok) {
|
|
102
|
+
console.error(`Failed to fetch slices: ${slicesResult.error}`);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const customTypes = customTypesResult.value;
|
|
108
|
+
const slices = slicesResult.value;
|
|
109
|
+
|
|
110
|
+
if (!json) {
|
|
111
|
+
if (shouldFetchTypes) {
|
|
112
|
+
console.info(`Fetching custom types... ${customTypes.length} types`);
|
|
113
|
+
}
|
|
114
|
+
if (shouldFetchSlices) {
|
|
115
|
+
console.info(`Fetching slices... ${slices.length} slices`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Dry run - just show what would be pulled
|
|
120
|
+
if (dryRun) {
|
|
121
|
+
if (json) {
|
|
122
|
+
console.info(stringify({ customTypes, slices }));
|
|
123
|
+
} else {
|
|
124
|
+
console.info("");
|
|
125
|
+
if (shouldFetchTypes && customTypes.length > 0) {
|
|
126
|
+
console.info("Would write custom types:");
|
|
127
|
+
for (const ct of customTypes) {
|
|
128
|
+
console.info(` customtypes/${ct.id}/index.json`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (shouldFetchSlices && slices.length > 0) {
|
|
132
|
+
const slicesDir = await getSlicesDirectory();
|
|
133
|
+
const relativeSlicesDir = getRelativePath(slicesDir);
|
|
134
|
+
console.info("Would write slices:");
|
|
135
|
+
for (const slice of slices) {
|
|
136
|
+
console.info(` ${relativeSlicesDir}${pascalCase(slice.name)}/model.json`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
console.info(
|
|
140
|
+
`\nDry run complete: ${customTypes.length} custom types, ${slices.length} slices`,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Find project root
|
|
147
|
+
const projectRoot = await findUpward("package.json");
|
|
148
|
+
if (!projectRoot) {
|
|
149
|
+
console.error("Could not find project root (no package.json found)");
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const projectDir = new URL(".", projectRoot);
|
|
154
|
+
|
|
155
|
+
const writtenTypes: string[] = [];
|
|
156
|
+
const writtenSlices: string[] = [];
|
|
157
|
+
|
|
158
|
+
// Write custom types
|
|
159
|
+
if (shouldFetchTypes && customTypes.length > 0) {
|
|
160
|
+
if (!json) {
|
|
161
|
+
console.info("\nWriting custom types:");
|
|
162
|
+
}
|
|
163
|
+
const customTypesDir = new URL("customtypes/", projectDir);
|
|
164
|
+
|
|
165
|
+
for (const ct of customTypes) {
|
|
166
|
+
const typeDir = new URL(`${ct.id}/`, customTypesDir);
|
|
167
|
+
const modelPath = new URL("index.json", typeDir);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await mkdir(typeDir, { recursive: true });
|
|
171
|
+
await writeFile(modelPath, stringify(ct));
|
|
172
|
+
const relativePath = `customtypes/${ct.id}/index.json`;
|
|
173
|
+
writtenTypes.push(relativePath);
|
|
174
|
+
if (!json) {
|
|
175
|
+
console.info(` ${relativePath}`);
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error(
|
|
179
|
+
`Failed to write custom type ${ct.id}: ${error instanceof Error ? error.message : error}`,
|
|
180
|
+
);
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Write slices
|
|
188
|
+
if (shouldFetchSlices && slices.length > 0) {
|
|
189
|
+
if (!json) {
|
|
190
|
+
console.info("\nWriting slices:");
|
|
191
|
+
}
|
|
192
|
+
const slicesDir = await getSlicesDirectory();
|
|
193
|
+
|
|
194
|
+
for (const slice of slices) {
|
|
195
|
+
const sliceDir = new URL(`${pascalCase(slice.name)}/`, slicesDir);
|
|
196
|
+
const modelPath = new URL("model.json", sliceDir);
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
await mkdir(sliceDir, { recursive: true });
|
|
200
|
+
await writeFile(modelPath, stringify(slice));
|
|
201
|
+
const relativePath = `${getRelativePath(slicesDir)}${pascalCase(slice.name)}/model.json`;
|
|
202
|
+
writtenSlices.push(relativePath);
|
|
203
|
+
if (!json) {
|
|
204
|
+
console.info(` ${relativePath}`);
|
|
205
|
+
}
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error(
|
|
208
|
+
`Failed to write slice ${slice.name}: ${error instanceof Error ? error.message : error}`,
|
|
209
|
+
);
|
|
210
|
+
process.exitCode = 1;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Output summary
|
|
217
|
+
if (json) {
|
|
218
|
+
console.info(stringify({ writtenTypes, writtenSlices }));
|
|
219
|
+
} else {
|
|
220
|
+
console.info(
|
|
221
|
+
`\nPull complete: ${writtenTypes.length} custom types, ${writtenSlices.length} slices`,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!json) {
|
|
226
|
+
try {
|
|
227
|
+
await buildTypes({ output: types });
|
|
228
|
+
console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function getRelativePath(url: URL): string {
|
|
236
|
+
const cwd = process.cwd();
|
|
237
|
+
const path = url.pathname;
|
|
238
|
+
if (path.startsWith(cwd)) {
|
|
239
|
+
return path.slice(cwd.length + 1);
|
|
240
|
+
}
|
|
241
|
+
return path;
|
|
242
|
+
}
|