prismic 1.1.0 → 1.2.0

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 (48) hide show
  1. package/dist/{builders-hKD4IrLX-ClhMQQkN.mjs → builders-hKD4IrLX-BrpqCAS2.mjs} +1 -1
  2. package/dist/index.mjs +115 -101
  3. package/dist/nextjs-HiDO_p-p.mjs +318 -0
  4. package/dist/nuxt-CDrqbn0o.mjs +59 -0
  5. package/dist/string-BUjs_2AH.mjs +7 -0
  6. package/dist/{sveltekit-BMDXAfYz.mjs → sveltekit-Qx8xJZOd.mjs} +45 -35
  7. package/package.json +1 -1
  8. package/src/adapters/index.ts +177 -0
  9. package/src/{frameworks → adapters}/nextjs.templates.ts +102 -102
  10. package/src/adapters/nextjs.ts +211 -0
  11. package/src/adapters/nuxt.ts +232 -0
  12. package/src/adapters/sveltekit.ts +226 -0
  13. package/src/clients/core.ts +104 -0
  14. package/src/clients/wroom.ts +111 -0
  15. package/src/commands/init.ts +57 -69
  16. package/src/commands/login.ts +12 -29
  17. package/src/commands/logout.ts +8 -28
  18. package/src/commands/preview-add.ts +57 -0
  19. package/src/commands/preview-list.ts +54 -0
  20. package/src/commands/preview-remove.ts +51 -0
  21. package/src/commands/preview-set-simulator.ts +60 -0
  22. package/src/commands/preview.ts +28 -0
  23. package/src/commands/sync.ts +49 -87
  24. package/src/commands/webhook-create.ts +89 -0
  25. package/src/commands/webhook-disable.ts +60 -0
  26. package/src/commands/webhook-enable.ts +60 -0
  27. package/src/commands/webhook-list.ts +43 -0
  28. package/src/commands/webhook-remove.ts +52 -0
  29. package/src/commands/webhook-set-triggers.ts +93 -0
  30. package/src/commands/webhook-view.ts +65 -0
  31. package/src/commands/webhook.ts +43 -0
  32. package/src/commands/whoami.ts +7 -28
  33. package/src/config.ts +2 -11
  34. package/src/index.ts +122 -105
  35. package/src/lib/command.ts +188 -0
  36. package/src/lib/file.ts +13 -1
  37. package/src/lib/packageJson.ts +70 -1
  38. package/src/lib/segment.ts +26 -30
  39. package/src/project.ts +54 -0
  40. package/dist/frameworks-DtGBrEuY.mjs +0 -17
  41. package/dist/nextjs-2qjzSaQI.mjs +0 -312
  42. package/dist/nuxt-DKsgbqpV.mjs +0 -59
  43. package/src/frameworks/index.ts +0 -398
  44. package/src/frameworks/nextjs.ts +0 -211
  45. package/src/frameworks/nuxt.ts +0 -252
  46. package/src/frameworks/sveltekit.ts +0 -234
  47. /package/src/{frameworks → adapters}/nuxt.templates.ts +0 -0
  48. /package/src/{frameworks → adapters}/sveltekit.templates.ts +0 -0
@@ -0,0 +1,104 @@
1
+ import * as z from "zod/mini";
2
+
3
+ import { request } from "../lib/request";
4
+
5
+ const PreviewSchema = z.object({
6
+ id: z.string(),
7
+ label: z.string(),
8
+ url: z.string(),
9
+ });
10
+
11
+ const GetPreviewsResponseSchema = z.object({
12
+ results: z.array(PreviewSchema),
13
+ });
14
+
15
+ export type Preview = z.infer<typeof PreviewSchema>;
16
+
17
+ export async function getPreviews(config: {
18
+ repo: string;
19
+ token: string | undefined;
20
+ host: string;
21
+ }): Promise<Preview[]> {
22
+ const { repo, token, host } = config;
23
+ const url = new URL(
24
+ "core/repository/preview_configs",
25
+ getCoreBaseUrl(repo, host),
26
+ );
27
+ const response = await request(url, {
28
+ credentials: { "prismic-auth": token },
29
+ schema: GetPreviewsResponseSchema,
30
+ });
31
+ return response.results;
32
+ }
33
+
34
+ export async function addPreview(
35
+ previewConfig: {
36
+ name: string;
37
+ websiteURL: string;
38
+ resolverPath: string | undefined;
39
+ },
40
+ config: { repo: string; token: string | undefined; host: string },
41
+ ): Promise<void> {
42
+ const { repo, token, host } = config;
43
+ const url = new URL("previews/new", getCoreBaseUrl(repo, host));
44
+ await request(url, {
45
+ method: "POST",
46
+ body: {
47
+ name: previewConfig.name,
48
+ websiteURL: previewConfig.websiteURL,
49
+ resolverPath: previewConfig.resolverPath,
50
+ },
51
+ credentials: { "prismic-auth": token },
52
+ });
53
+ }
54
+
55
+ export async function removePreview(
56
+ id: string,
57
+ config: { repo: string; token: string | undefined; host: string },
58
+ ): Promise<void> {
59
+ const { repo, token, host } = config;
60
+ const url = new URL(
61
+ `previews/delete/${id}`,
62
+ getCoreBaseUrl(repo, host),
63
+ );
64
+ await request(url, {
65
+ method: "POST",
66
+ body: {},
67
+ credentials: { "prismic-auth": token },
68
+ });
69
+ }
70
+
71
+ const RepositoryResponseSchema = z.object({
72
+ simulator_url: z.optional(z.string()),
73
+ });
74
+
75
+ export async function getSimulatorUrl(config: {
76
+ repo: string;
77
+ token: string | undefined;
78
+ host: string;
79
+ }): Promise<string | undefined> {
80
+ const { repo, token, host } = config;
81
+ const url = new URL("core/repository", getCoreBaseUrl(repo, host));
82
+ const response = await request(url, {
83
+ credentials: { "prismic-auth": token },
84
+ schema: RepositoryResponseSchema,
85
+ });
86
+ return response.simulator_url;
87
+ }
88
+
89
+ export async function setSimulatorUrl(
90
+ simulatorUrl: string,
91
+ config: { repo: string; token: string | undefined; host: string },
92
+ ): Promise<void> {
93
+ const { repo, token, host } = config;
94
+ const url = new URL("core/repository", getCoreBaseUrl(repo, host));
95
+ await request(url, {
96
+ method: "PATCH",
97
+ body: { simulator_url: simulatorUrl },
98
+ credentials: { "prismic-auth": token },
99
+ });
100
+ }
101
+
102
+ function getCoreBaseUrl(repo: string, host: string): URL {
103
+ return new URL(`https://${repo}.${host}/`);
104
+ }
@@ -0,0 +1,111 @@
1
+ import * as z from "zod/mini";
2
+
3
+ import { request } from "../lib/request";
4
+
5
+ const WebhookTriggersSchema = z.object({
6
+ documentsPublished: z.boolean(),
7
+ documentsUnpublished: z.boolean(),
8
+ releasesCreated: z.boolean(),
9
+ releasesUpdated: z.boolean(),
10
+ tagsCreated: z.boolean(),
11
+ tagsDeleted: z.boolean(),
12
+ });
13
+
14
+ export const WEBHOOK_TRIGGERS = Object.keys(WebhookTriggersSchema.shape);
15
+
16
+ const WebhookSchema = z.object({
17
+ config: z.extend(WebhookTriggersSchema, {
18
+ _id: z.string(),
19
+ url: z.string(),
20
+ active: z.boolean(),
21
+ name: z.nullable(z.string()),
22
+ secret: z.nullable(z.string()),
23
+ headers: z.record(z.string(), z.string()),
24
+ }),
25
+ });
26
+ type Webhook = z.infer<typeof WebhookSchema>;
27
+
28
+ export async function getWebhooks(config: {
29
+ repo: string;
30
+ token: string | undefined;
31
+ host: string;
32
+ }): Promise<Webhook[]> {
33
+ const { repo, token, host } = config;
34
+ const wroomUrl = getWroomUrl(repo, host);
35
+ const url = new URL("app/settings/webhooks", wroomUrl);
36
+ const response = await request(url, {
37
+ credentials: { "prismic-auth": token },
38
+ schema: z.array(WebhookSchema),
39
+ });
40
+ return response;
41
+ }
42
+
43
+ export async function createWebhook(
44
+ webhookConfig: Omit<Webhook["config"], "_id" | "active" | "headers">,
45
+ config: { repo: string; token: string | undefined; host: string },
46
+ ): Promise<void> {
47
+ const { repo, token, host } = config;
48
+ const wroomUrl = getWroomUrl(repo, host);
49
+ const url = new URL(`app/settings/webhooks/create`, wroomUrl);
50
+ const body = new FormData();
51
+ body.set("url", webhookConfig.url);
52
+ body.set("name", webhookConfig.name ?? "");
53
+ body.set("secret", webhookConfig.secret ?? "");
54
+ body.set("headers", JSON.stringify({}));
55
+ body.set("active", "on");
56
+ body.set("documentsPublished", webhookConfig.documentsPublished.toString());
57
+ body.set("documentsUnpublished", webhookConfig.documentsUnpublished.toString());
58
+ body.set("releasesCreated", webhookConfig.releasesCreated.toString());
59
+ body.set("releasesUpdated", webhookConfig.releasesUpdated.toString());
60
+ body.set("tagsCreated", webhookConfig.tagsCreated.toString());
61
+ body.set("tagsDeleted", webhookConfig.tagsDeleted.toString());
62
+ await request(url, {
63
+ method: "POST",
64
+ body,
65
+ credentials: { "prismic-auth": token },
66
+ });
67
+ }
68
+
69
+ export async function updateWebhook(
70
+ id: string,
71
+ webhookConfig: Omit<Webhook["config"], "_id">,
72
+ config: { repo: string; token: string | undefined; host: string },
73
+ ): Promise<void> {
74
+ const { repo, token, host } = config;
75
+ const wroomUrl = getWroomUrl(repo, host);
76
+ const url = new URL(`app/settings/webhooks/${id}`, wroomUrl);
77
+ const body = new FormData();
78
+ body.set("url", webhookConfig.url);
79
+ body.set("name", webhookConfig.name ?? "");
80
+ body.set("secret", webhookConfig.secret ?? "");
81
+ body.set("headers", JSON.stringify(webhookConfig.headers ?? {}));
82
+ body.set("active", webhookConfig.active ? "on" : "off");
83
+ body.set("documentsPublished", webhookConfig.documentsPublished.toString());
84
+ body.set("documentsUnpublished", webhookConfig.documentsUnpublished.toString());
85
+ body.set("releasesCreated", webhookConfig.releasesCreated.toString());
86
+ body.set("releasesUpdated", webhookConfig.releasesUpdated.toString());
87
+ body.set("tagsCreated", webhookConfig.tagsCreated.toString());
88
+ body.set("tagsDeleted", webhookConfig.tagsDeleted.toString());
89
+ await request(url, {
90
+ method: "POST",
91
+ body,
92
+ credentials: { "prismic-auth": token },
93
+ });
94
+ }
95
+
96
+ export async function deleteWebhook(
97
+ id: string,
98
+ config: { repo: string; token: string | undefined; host: string },
99
+ ): Promise<void> {
100
+ const { repo, token, host } = config;
101
+ const wroomUrl = getWroomUrl(repo, host);
102
+ const url = new URL(`app/settings/webhooks/${id}/delete`, wroomUrl);
103
+ await request(url, {
104
+ method: "POST",
105
+ credentials: { "prismic-auth": token },
106
+ });
107
+ }
108
+
109
+ function getWroomUrl(repo: string, host: string): URL {
110
+ return new URL(`https://${repo}.${host}/`);
111
+ }
@@ -1,66 +1,58 @@
1
- import { parseArgs } from "node:util";
2
-
3
1
  import type { Profile } from "../clients/user";
4
2
 
3
+ import { getAdapter } from "../adapters";
5
4
  import { createLoginSession, getHost, getToken } from "../auth";
6
5
  import { getProfile } from "../clients/user";
7
6
  import {
8
7
  createConfig,
9
8
  deleteLegacySliceMachineConfig,
10
9
  InvalidLegacySliceMachineConfig,
10
+ MissingPrismicConfig,
11
11
  readConfig,
12
12
  readLegacySliceMachineConfig,
13
13
  UnknownProjectRoot,
14
14
  } from "../config";
15
- import { getFramework } from "../frameworks";
16
15
  import { openBrowser } from "../lib/browser";
17
16
  import { generateAndWriteTypes } from "../lib/codegen";
17
+ import { CommandError, createCommand, type CommandConfig } from "../lib/command";
18
+ import { installDependencies } from "../lib/packageJson";
18
19
  import { ForbiddenRequestError, UnauthorizedRequestError } from "../lib/request";
20
+ import { findProjectRoot } from "../project";
19
21
  import { syncCustomTypes, syncSlices } from "./sync";
20
22
 
21
- const HELP = `
22
- Initialize a Prismic project by creating a prismic.config.json file.
23
-
24
- Detects the project framework, installs dependencies, and syncs models
25
- from Prismic. If a slicemachine.config.json exists, it will be migrated.
26
-
27
- USAGE
28
- prismic init [flags]
29
-
30
- FLAGS
31
- -r, --repo string Repository name
32
- --no-browser Skip opening the browser automatically during login
33
- -h, --help Show help for command
34
-
35
- EXAMPLES
36
- prismic init --repo my-repo
37
-
38
- LEARN MORE
39
- Use \`prismic <command> --help\` for more information about a command.
40
- `.trim();
41
-
42
- export async function init(): Promise<void> {
43
- const { values } = parseArgs({
44
- args: process.argv.slice(3),
45
- options: {
46
- help: { type: "boolean", short: "h" },
47
- repo: { type: "string", short: "r" },
48
- "no-browser": { type: "boolean" },
23
+ const config = {
24
+ name: "prismic init",
25
+ description: `
26
+ Initialize a Prismic project by creating a prismic.config.json file.
27
+
28
+ Detects the project framework, installs dependencies, and syncs models
29
+ from Prismic. If a slicemachine.config.json exists, it will be migrated.
30
+ `,
31
+ options: {
32
+ repo: { type: "string", short: "r", description: "Repository name" },
33
+ "no-browser": {
34
+ type: "boolean",
35
+ description: "Skip opening the browser automatically during login",
49
36
  },
50
- });
37
+ },
38
+ } satisfies CommandConfig;
51
39
 
52
- if (values.help) {
53
- console.info(HELP);
54
- return;
55
- }
40
+ export default createCommand(config, async ({ values }) => {
41
+ const { repo: explicitRepo, "no-browser": noBrowser } = values;
56
42
 
57
43
  // Check for existing prismic.config.json
58
44
  try {
59
45
  await readConfig();
60
- console.error("A prismic.config.json file exists. This project is already initialized.");
61
- process.exitCode = 1;
62
- return;
63
- } catch {}
46
+ throw new CommandError(
47
+ "A prismic.config.json file exists. This project is already initialized.",
48
+ );
49
+ } catch (error) {
50
+ if (error instanceof MissingPrismicConfig) {
51
+ // No config found — proceed with initialization.
52
+ } else {
53
+ throw error;
54
+ }
55
+ }
64
56
 
65
57
  // Load legacy slicemachine.config.json
66
58
  let legacySliceMachineConfig;
@@ -72,11 +64,9 @@ export async function init(): Promise<void> {
72
64
  }
73
65
  }
74
66
 
75
- const repo = values.repo ?? legacySliceMachineConfig?.repositoryName;
67
+ const repo = explicitRepo ?? legacySliceMachineConfig?.repositoryName;
76
68
  if (!repo) {
77
- console.error("Missing required flag: --repo");
78
- process.exitCode = 1;
79
- return;
69
+ throw new CommandError("Missing required flag: --repo");
80
70
  }
81
71
 
82
72
  // Validate repo membership
@@ -90,7 +80,7 @@ export async function init(): Promise<void> {
90
80
  console.info("Not logged in. Starting login...");
91
81
  const { email } = await createLoginSession({
92
82
  onReady: (url) => {
93
- if (values["no-browser"]) {
83
+ if (noBrowser) {
94
84
  console.info(`Open this URL to log in: ${url}`);
95
85
  } else {
96
86
  console.info("Opening browser to complete login...");
@@ -109,19 +99,12 @@ export async function init(): Promise<void> {
109
99
 
110
100
  const repoMeta = profile.repositories.find((repository) => repository.domain === repo);
111
101
  if (!repoMeta) {
112
- console.error(
102
+ throw new CommandError(
113
103
  `Repository "${repo}" not found in your account. Check the name or request access to the repository.`,
114
104
  );
115
- process.exitCode = 1;
116
- return;
117
105
  }
118
106
 
119
- const framework = await getFramework();
120
- if (!framework) {
121
- console.error("No supported framework found (Next.js, Nuxt, or SvelteKit required)");
122
- process.exitCode = 1;
123
- return;
124
- }
107
+ const adapter = await getAdapter();
125
108
 
126
109
  // Create prismic.config.json
127
110
  try {
@@ -131,14 +114,11 @@ export async function init(): Promise<void> {
131
114
  });
132
115
  } catch (error) {
133
116
  if (error instanceof UnknownProjectRoot) {
134
- console.error(
117
+ throw new CommandError(
135
118
  "Could not find a package.json file. Run this command from a project directory.",
136
119
  );
137
- } else {
138
- console.error("Failed to create config file.");
139
120
  }
140
- process.exitCode = 1;
141
- return;
121
+ throw new CommandError("Failed to create prismic.config.json.");
142
122
  }
143
123
 
144
124
  if (legacySliceMachineConfig) {
@@ -149,23 +129,31 @@ export async function init(): Promise<void> {
149
129
  }
150
130
 
151
131
  // Install dependencies and create framework files
152
- await framework.initProject();
132
+ await adapter.initProject();
133
+
134
+ // Run package manager install
135
+ try {
136
+ console.info("Installing dependencies...");
137
+ await installDependencies();
138
+ } catch {
139
+ console.warn(
140
+ "Could not install dependencies automatically. Please install them manually (i.e. `npm install`).",
141
+ );
142
+ }
153
143
 
154
144
  // Sync models from remote
155
- await syncSlices(repo, framework);
156
- await syncCustomTypes(repo, framework);
145
+ await syncSlices(repo, adapter);
146
+ await syncCustomTypes(repo, adapter);
157
147
 
158
148
  // Generate TypeScript types from synced models
159
- const slices = await framework.getSlices();
160
- const customTypes = await framework.getCustomTypes();
161
- const projectRoot = await framework.getProjectRoot();
149
+ const slices = await adapter.getSlices();
150
+ const customTypes = await adapter.getCustomTypes();
151
+ const projectRoot = await findProjectRoot();
162
152
  await generateAndWriteTypes({
163
153
  customTypes: customTypes.map((customType) => customType.model),
164
154
  slices: slices.map((slice) => slice.model),
165
155
  projectRoot,
166
156
  });
167
157
 
168
- console.info(
169
- `Initialized Prismic for repository "${repo}". Run \`npm install\` to install new dependencies.`,
170
- );
171
- }
158
+ console.info(`\nInitialized Prismic for repository "${repo}".`);
159
+ });
@@ -1,39 +1,22 @@
1
1
  import { exec } from "node:child_process";
2
- import { parseArgs } from "node:util";
3
2
 
4
3
  import { createLoginSession } from "../auth";
4
+ import { createCommand, type CommandConfig } from "../lib/command";
5
5
 
6
- const HELP = `
7
- Log in to Prismic via browser.
6
+ const config = {
7
+ name: "prismic login",
8
+ description: "Log in to Prismic via browser.",
9
+ options: {
10
+ "no-browser": { type: "boolean", description: "Skip opening the browser automatically" },
11
+ },
12
+ } satisfies CommandConfig;
8
13
 
9
- USAGE
10
- prismic login [flags]
11
-
12
- FLAGS
13
- --no-browser Skip opening the browser automatically
14
- -h, --help Show help for command
15
-
16
- LEARN MORE
17
- Use \`prismic <command> --help\` for more information about a command.
18
- `.trim();
19
-
20
- export async function login(): Promise<void> {
21
- const { values } = parseArgs({
22
- args: process.argv.slice(3),
23
- options: {
24
- help: { type: "boolean", short: "h" },
25
- "no-browser": { type: "boolean" },
26
- },
27
- });
28
-
29
- if (values.help) {
30
- console.info(HELP);
31
- return;
32
- }
14
+ export default createCommand(config, async ({ values }) => {
15
+ const { "no-browser": noBrowser } = values;
33
16
 
34
17
  const { email } = await createLoginSession({
35
18
  onReady: (url) => {
36
- if (values["no-browser"]) {
19
+ if (noBrowser) {
37
20
  console.info(`Open this URL to log in: ${url}`);
38
21
  } else {
39
22
  console.info("Opening browser to complete login...");
@@ -44,7 +27,7 @@ export async function login(): Promise<void> {
44
27
  });
45
28
 
46
29
  console.info(`Logged in to Prismic as ${email}`);
47
- }
30
+ });
48
31
 
49
32
  function openBrowser(url: URL): void {
50
33
  const cmd =
@@ -1,36 +1,16 @@
1
- import { parseArgs } from "node:util";
2
-
3
1
  import { logout as baseLogout } from "../auth";
2
+ import { CommandError, createCommand, type CommandConfig } from "../lib/command";
4
3
 
5
- const HELP = `
6
- Log out of Prismic.
7
-
8
- USAGE
9
- prismic logout [flags]
10
-
11
- FLAGS
12
- -h, --help Show help for command
13
-
14
- LEARN MORE
15
- Use \`prismic <command> --help\` for more information about a command.
16
- `.trim();
17
-
18
- export async function logout(): Promise<void> {
19
- const { values } = parseArgs({
20
- args: process.argv.slice(3),
21
- options: { help: { type: "boolean", short: "h" } },
22
- });
23
-
24
- if (values.help) {
25
- console.info(HELP);
26
- return;
27
- }
4
+ const config = {
5
+ name: "prismic logout",
6
+ description: "Log out of Prismic.",
7
+ } satisfies CommandConfig;
28
8
 
9
+ export default createCommand(config, async () => {
29
10
  const ok = await baseLogout();
30
11
  if (ok) {
31
12
  console.info("Logged out of Prismic");
32
13
  } else {
33
- console.error("Logout failed. You can log out manually by deleting the file.");
34
- process.exitCode = 1;
14
+ throw new CommandError("Logout failed. You can log out manually by deleting the file.");
35
15
  }
36
- }
16
+ });
@@ -0,0 +1,57 @@
1
+ import { getHost, getToken } from "../auth";
2
+ import { addPreview } from "../clients/core";
3
+ import { CommandError, createCommand, type CommandConfig } from "../lib/command";
4
+ import { UnknownRequestError } from "../lib/request";
5
+ import { getRepositoryName } from "../project";
6
+
7
+ const config = {
8
+ name: "prismic preview add",
9
+ description: `
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
+ positionals: {
16
+ url: { description: "Preview URL (e.g. https://example.com/api/preview)" },
17
+ },
18
+ options: {
19
+ name: { type: "string", short: "n", description: "Display name (defaults to hostname)" },
20
+ repo: { type: "string", short: "r", description: "Repository domain" },
21
+ },
22
+ } satisfies CommandConfig;
23
+
24
+ export default createCommand(config, async ({ positionals, values }) => {
25
+ const [previewUrl] = positionals;
26
+ const { repo = await getRepositoryName(), name } = values;
27
+
28
+ if (!previewUrl) {
29
+ throw new CommandError("Missing required argument: <url>");
30
+ }
31
+
32
+ let parsed: URL;
33
+ try {
34
+ parsed = new URL(previewUrl);
35
+ } catch {
36
+ throw new CommandError(`Invalid URL: ${previewUrl}`);
37
+ }
38
+
39
+ const displayName = name || parsed.hostname;
40
+ const websiteURL = `${parsed.protocol}//${parsed.host}`;
41
+ const resolverPath = parsed.pathname === "/" ? undefined : parsed.pathname;
42
+
43
+ const token = await getToken();
44
+ const host = await getHost();
45
+
46
+ try {
47
+ await addPreview({ name: displayName, websiteURL, resolverPath }, { repo, token, host });
48
+ } catch (error) {
49
+ if (error instanceof UnknownRequestError) {
50
+ const message = await error.text();
51
+ throw new CommandError(`Failed to add preview: ${message}`);
52
+ }
53
+ throw error;
54
+ }
55
+
56
+ console.info(`Preview added: ${previewUrl}`);
57
+ });
@@ -0,0 +1,54 @@
1
+ import { getHost, getToken } from "../auth";
2
+ import { getPreviews, getSimulatorUrl } from "../clients/core";
3
+ import { createCommand, type CommandConfig } from "../lib/command";
4
+ import { stringify } from "../lib/json";
5
+ import { getRepositoryName } from "../project";
6
+
7
+ const config = {
8
+ name: "prismic preview list",
9
+ description: `
10
+ List all preview configurations in a Prismic repository.
11
+
12
+ By default, this command reads the repository from prismic.config.json at the
13
+ project root.
14
+ `,
15
+ options: {
16
+ json: { type: "boolean", description: "Output as JSON" },
17
+ repo: { type: "string", short: "r", description: "Repository domain" },
18
+ },
19
+ } satisfies CommandConfig;
20
+
21
+ export default createCommand(config, async ({ values }) => {
22
+ const { repo = await getRepositoryName(), json } = values;
23
+
24
+ const token = await getToken();
25
+ const host = await getHost();
26
+
27
+ const [previews, simulatorUrl] = await Promise.all([
28
+ getPreviews({ repo, token, host }),
29
+ getSimulatorUrl({ repo, token, host }),
30
+ ]);
31
+
32
+ if (json) {
33
+ console.info(
34
+ stringify({
35
+ previews,
36
+ simulatorUrl: simulatorUrl ?? null,
37
+ }),
38
+ );
39
+ return;
40
+ }
41
+
42
+ if (previews.length === 0 && !simulatorUrl) {
43
+ console.info("No preview configurations found.");
44
+ return;
45
+ }
46
+
47
+ for (const preview of previews) {
48
+ console.info(`${preview.url} ${preview.label}`);
49
+ }
50
+
51
+ if (simulatorUrl) {
52
+ console.info(`\nSimulator: ${simulatorUrl}`);
53
+ }
54
+ });
@@ -0,0 +1,51 @@
1
+ import { getHost, getToken } from "../auth";
2
+ import { getPreviews, removePreview } from "../clients/core";
3
+ import { CommandError, createCommand, type CommandConfig } from "../lib/command";
4
+ import { UnknownRequestError } from "../lib/request";
5
+ import { getRepositoryName } from "../project";
6
+
7
+ const config = {
8
+ name: "prismic preview remove",
9
+ description: `
10
+ Remove a preview configuration from a Prismic repository.
11
+
12
+ By default, this command reads the repository from prismic.config.json at the
13
+ project root.
14
+ `,
15
+ positionals: {
16
+ url: { description: "Preview URL to remove" },
17
+ },
18
+ options: {
19
+ repo: { type: "string", short: "r", description: "Repository domain" },
20
+ },
21
+ } satisfies CommandConfig;
22
+
23
+ export default createCommand(config, async ({ positionals, values }) => {
24
+ const [previewUrl] = positionals;
25
+ const { repo = await getRepositoryName() } = values;
26
+
27
+ if (!previewUrl) {
28
+ throw new CommandError("Missing required argument: <url>");
29
+ }
30
+
31
+ const token = await getToken();
32
+ const host = await getHost();
33
+
34
+ const previews = await getPreviews({ repo, token, host });
35
+ const preview = previews.find((p) => p.url === previewUrl);
36
+ if (!preview) {
37
+ throw new CommandError(`Preview not found: ${previewUrl}`);
38
+ }
39
+
40
+ try {
41
+ await removePreview(preview.id, { repo, token, host });
42
+ } catch (error) {
43
+ if (error instanceof UnknownRequestError) {
44
+ const message = await error.text();
45
+ throw new CommandError(`Failed to remove preview: ${message}`);
46
+ }
47
+ throw error;
48
+ }
49
+
50
+ console.info(`Preview removed: ${previewUrl}`);
51
+ });