prismic 0.0.0-pr.28.59bf330

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 (158) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +69 -0
  3. package/dist/builders-hKD4IrLX-DsO7BUQw.mjs +97 -0
  4. package/dist/dist-B11B2hHn.mjs +1 -0
  5. package/dist/dist-DT8CtumB.mjs +1 -0
  6. package/dist/framework-CfjEoVk0.mjs +17 -0
  7. package/dist/index.mjs +2537 -0
  8. package/dist/nextjs-9z7YrSnS.mjs +312 -0
  9. package/dist/nuxt-KoJ61G2q.mjs +59 -0
  10. package/dist/sveltekit-DjXKCG78.mjs +226 -0
  11. package/package.json +58 -0
  12. package/src/codegen-types.ts +82 -0
  13. package/src/codegen.ts +45 -0
  14. package/src/custom-type-add-field-boolean.ts +185 -0
  15. package/src/custom-type-add-field-color.ts +168 -0
  16. package/src/custom-type-add-field-date.ts +171 -0
  17. package/src/custom-type-add-field-embed.ts +168 -0
  18. package/src/custom-type-add-field-geo-point.ts +165 -0
  19. package/src/custom-type-add-field-group.ts +142 -0
  20. package/src/custom-type-add-field-image.ts +168 -0
  21. package/src/custom-type-add-field-key-text.ts +168 -0
  22. package/src/custom-type-add-field-link.ts +191 -0
  23. package/src/custom-type-add-field-number.ts +200 -0
  24. package/src/custom-type-add-field-rich-text.ts +192 -0
  25. package/src/custom-type-add-field-select.ts +174 -0
  26. package/src/custom-type-add-field-timestamp.ts +171 -0
  27. package/src/custom-type-add-field-uid.ts +151 -0
  28. package/src/custom-type-add-field.ts +116 -0
  29. package/src/custom-type-connect-slice.ts +178 -0
  30. package/src/custom-type-create.ts +98 -0
  31. package/src/custom-type-disconnect-slice.ts +134 -0
  32. package/src/custom-type-list.ts +110 -0
  33. package/src/custom-type-remove-field.ts +135 -0
  34. package/src/custom-type-remove.ts +103 -0
  35. package/src/custom-type-set-name.ts +102 -0
  36. package/src/custom-type-view.ts +118 -0
  37. package/src/custom-type.ts +85 -0
  38. package/src/docs-fetch.ts +146 -0
  39. package/src/docs-list.ts +131 -0
  40. package/src/docs.ts +54 -0
  41. package/src/env.d.ts +12 -0
  42. package/src/framework/index.ts +399 -0
  43. package/src/framework/nextjs.templates.ts +426 -0
  44. package/src/framework/nextjs.ts +216 -0
  45. package/src/framework/nuxt.templates.ts +74 -0
  46. package/src/framework/nuxt.ts +250 -0
  47. package/src/framework/sveltekit.templates.ts +278 -0
  48. package/src/framework/sveltekit.ts +241 -0
  49. package/src/index.ts +155 -0
  50. package/src/init.ts +173 -0
  51. package/src/lib/auth.ts +200 -0
  52. package/src/lib/browser.ts +11 -0
  53. package/src/lib/config.ts +111 -0
  54. package/src/lib/custom-types-api.ts +385 -0
  55. package/src/lib/field-path.ts +81 -0
  56. package/src/lib/file.ts +49 -0
  57. package/src/lib/json.ts +3 -0
  58. package/src/lib/packageJson.ts +35 -0
  59. package/src/lib/profile.ts +39 -0
  60. package/src/lib/request.ts +116 -0
  61. package/src/lib/segment.ts +145 -0
  62. package/src/lib/sentry.ts +63 -0
  63. package/src/lib/string.ts +10 -0
  64. package/src/lib/url.ts +31 -0
  65. package/src/locale-add.ts +116 -0
  66. package/src/locale-list.ts +107 -0
  67. package/src/locale-remove.ts +88 -0
  68. package/src/locale-set-default.ts +131 -0
  69. package/src/locale.ts +60 -0
  70. package/src/login.ts +45 -0
  71. package/src/logout.ts +36 -0
  72. package/src/page-type-add-field-boolean.ts +179 -0
  73. package/src/page-type-add-field-color.ts +165 -0
  74. package/src/page-type-add-field-date.ts +168 -0
  75. package/src/page-type-add-field-embed.ts +165 -0
  76. package/src/page-type-add-field-geo-point.ts +162 -0
  77. package/src/page-type-add-field-group.ts +139 -0
  78. package/src/page-type-add-field-image.ts +165 -0
  79. package/src/page-type-add-field-key-text.ts +165 -0
  80. package/src/page-type-add-field-link.ts +188 -0
  81. package/src/page-type-add-field-number.ts +197 -0
  82. package/src/page-type-add-field-rich-text.ts +189 -0
  83. package/src/page-type-add-field-select.ts +171 -0
  84. package/src/page-type-add-field-timestamp.ts +168 -0
  85. package/src/page-type-add-field-uid.ts +148 -0
  86. package/src/page-type-add-field.ts +116 -0
  87. package/src/page-type-connect-slice.ts +178 -0
  88. package/src/page-type-create.ts +128 -0
  89. package/src/page-type-disconnect-slice.ts +134 -0
  90. package/src/page-type-list.ts +109 -0
  91. package/src/page-type-remove-field.ts +135 -0
  92. package/src/page-type-remove.ts +103 -0
  93. package/src/page-type-set-name.ts +102 -0
  94. package/src/page-type-set-repeatable.ts +111 -0
  95. package/src/page-type-view.ts +118 -0
  96. package/src/page-type.ts +90 -0
  97. package/src/preview-add.ts +126 -0
  98. package/src/preview-get-simulator.ts +104 -0
  99. package/src/preview-list.ts +106 -0
  100. package/src/preview-remove-simulator.ts +80 -0
  101. package/src/preview-remove.ts +109 -0
  102. package/src/preview-set-name.ts +137 -0
  103. package/src/preview-set-simulator.ts +116 -0
  104. package/src/preview.ts +75 -0
  105. package/src/pull.ts +236 -0
  106. package/src/push.ts +409 -0
  107. package/src/repo-create.ts +175 -0
  108. package/src/repo-get-access.ts +86 -0
  109. package/src/repo-list.ts +100 -0
  110. package/src/repo-set-access.ts +100 -0
  111. package/src/repo-set-name.ts +102 -0
  112. package/src/repo-view.ts +113 -0
  113. package/src/repo.ts +70 -0
  114. package/src/slice-add-field-boolean.ts +219 -0
  115. package/src/slice-add-field-color.ts +205 -0
  116. package/src/slice-add-field-date.ts +205 -0
  117. package/src/slice-add-field-embed.ts +205 -0
  118. package/src/slice-add-field-geo-point.ts +202 -0
  119. package/src/slice-add-field-group.ts +170 -0
  120. package/src/slice-add-field-image.ts +202 -0
  121. package/src/slice-add-field-key-text.ts +205 -0
  122. package/src/slice-add-field-link.ts +224 -0
  123. package/src/slice-add-field-number.ts +205 -0
  124. package/src/slice-add-field-rich-text.ts +229 -0
  125. package/src/slice-add-field-select.ts +211 -0
  126. package/src/slice-add-field-timestamp.ts +205 -0
  127. package/src/slice-add-field.ts +111 -0
  128. package/src/slice-add-variation.ts +142 -0
  129. package/src/slice-create.ts +164 -0
  130. package/src/slice-list-variations.ts +71 -0
  131. package/src/slice-list.ts +60 -0
  132. package/src/slice-remove-field.ts +125 -0
  133. package/src/slice-remove-variation.ts +113 -0
  134. package/src/slice-remove.ts +92 -0
  135. package/src/slice-rename.ts +104 -0
  136. package/src/slice-set-screenshot.ts +239 -0
  137. package/src/slice-view.ts +83 -0
  138. package/src/slice.ts +95 -0
  139. package/src/status.ts +834 -0
  140. package/src/sync.ts +259 -0
  141. package/src/token-create.ts +203 -0
  142. package/src/token-delete.ts +182 -0
  143. package/src/token-list.ts +223 -0
  144. package/src/token-set-name.ts +193 -0
  145. package/src/token.ts +60 -0
  146. package/src/webhook-add-header.ts +118 -0
  147. package/src/webhook-create.ts +152 -0
  148. package/src/webhook-disable.ts +109 -0
  149. package/src/webhook-enable.ts +132 -0
  150. package/src/webhook-list.ts +93 -0
  151. package/src/webhook-remove-header.ts +117 -0
  152. package/src/webhook-remove.ts +106 -0
  153. package/src/webhook-set-triggers.ts +148 -0
  154. package/src/webhook-status.ts +90 -0
  155. package/src/webhook-test.ts +106 -0
  156. package/src/webhook-view.ts +147 -0
  157. package/src/webhook.ts +95 -0
  158. package/src/whoami.ts +62 -0
@@ -0,0 +1,223 @@
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 {
8
+ ForbiddenRequestError,
9
+ type ParsedRequestResponse,
10
+ request,
11
+ UnauthorizedRequestError,
12
+ } from "./lib/request";
13
+ import { getRepoUrl } from "./lib/url";
14
+
15
+ const HELP = `
16
+ List all API tokens for a Prismic repository.
17
+
18
+ By default, this command reads the repository from prismic.config.json at the
19
+ project root.
20
+
21
+ USAGE
22
+ prismic token list [flags]
23
+
24
+ FLAGS
25
+ --json Output as JSON
26
+ -r, --repo string Repository domain
27
+ -h, --help Show help for command
28
+
29
+ LEARN MORE
30
+ Use \`prismic token <command> --help\` for more information about a command.
31
+ `.trim();
32
+
33
+ export async function tokenList(): Promise<void> {
34
+ const {
35
+ values: { help, repo = await safeGetRepositoryFromConfig(), json },
36
+ } = parseArgs({
37
+ args: process.argv.slice(4), // skip: node, script, "token", "list"
38
+ options: {
39
+ json: { type: "boolean" },
40
+ repo: { type: "string", short: "r" },
41
+ help: { type: "boolean", short: "h" },
42
+ },
43
+ allowPositionals: false,
44
+ });
45
+
46
+ if (help) {
47
+ console.info(HELP);
48
+ return;
49
+ }
50
+
51
+ if (!repo) {
52
+ console.error("Missing prismic.config.json or --repo option");
53
+ process.exitCode = 1;
54
+ return;
55
+ }
56
+
57
+ const authenticated = await isAuthenticated();
58
+ if (!authenticated) {
59
+ handleUnauthenticated();
60
+ return;
61
+ }
62
+
63
+ const [accessResponse, writeResponse] = await Promise.all([
64
+ getAccessTokens(repo),
65
+ getWriteTokens(repo),
66
+ ]);
67
+
68
+ if (!accessResponse.ok) {
69
+ if (
70
+ accessResponse.error instanceof ForbiddenRequestError ||
71
+ accessResponse.error instanceof UnauthorizedRequestError
72
+ ) {
73
+ handleUnauthenticated();
74
+ } else if (v.isValiError(accessResponse.error)) {
75
+ console.error(
76
+ `Failed to list access tokens: Invalid response: ${stringify(accessResponse.error.issues)}`,
77
+ );
78
+ process.exitCode = 1;
79
+ } else {
80
+ console.error(`Failed to list access tokens: ${stringify(accessResponse.value)}`);
81
+ process.exitCode = 1;
82
+ }
83
+ return;
84
+ }
85
+
86
+ if (!writeResponse.ok) {
87
+ if (
88
+ writeResponse.error instanceof ForbiddenRequestError ||
89
+ writeResponse.error instanceof UnauthorizedRequestError
90
+ ) {
91
+ handleUnauthenticated();
92
+ } else if (v.isValiError(writeResponse.error)) {
93
+ console.error(
94
+ `Failed to list write tokens: Invalid response: ${stringify(writeResponse.error.issues)}`,
95
+ );
96
+ process.exitCode = 1;
97
+ } else {
98
+ console.error(`Failed to list write tokens: ${stringify(writeResponse.value)}`);
99
+ process.exitCode = 1;
100
+ }
101
+ return;
102
+ }
103
+
104
+ const accessTokens = accessResponse.value.flatMap((app: OAuthApp) =>
105
+ app.wroom_auths.map((auth: AccessToken) => ({
106
+ name: app.name,
107
+ appId: app.id,
108
+ authId: auth.id,
109
+ scope: auth.scope,
110
+ token: auth.token,
111
+ createdAt: auth.created_at.$date,
112
+ })),
113
+ );
114
+ const writeTokens = writeResponse.value.tokens;
115
+
116
+ if (json) {
117
+ console.info(stringify({ accessTokens, writeTokens }));
118
+ } else {
119
+ if (accessTokens.length > 0) {
120
+ console.info("ACCESS TOKENS");
121
+ for (const token of accessTokens) {
122
+ const truncated = truncateToken(token.token);
123
+ const date = formatDate(token.createdAt);
124
+ console.info(` ${token.name} ${token.scope} ${truncated} ${date}`);
125
+ }
126
+ } else {
127
+ console.info("ACCESS TOKENS (none)");
128
+ }
129
+
130
+ console.info("");
131
+
132
+ if (writeTokens.length > 0) {
133
+ console.info("WRITE TOKENS");
134
+ for (const token of writeTokens) {
135
+ const truncated = truncateToken(token.token);
136
+ const date = formatDate(token.timestamp);
137
+ console.info(` ${token.app_name} ${truncated} ${date}`);
138
+ }
139
+ } else {
140
+ console.info("WRITE TOKENS (none)");
141
+ }
142
+ }
143
+ }
144
+
145
+ // MongoDB date format: { "$date": milliseconds }
146
+ const MongoDBDateSchema = v.object({ $date: v.number() });
147
+ type MongoDBDate = v.InferOutput<typeof MongoDBDateSchema>;
148
+
149
+ // Access Token (from OAuth app's wroom_auths array)
150
+ export const AccessTokenSchema = v.object({
151
+ id: v.string(),
152
+ origin: v.string(),
153
+ domain: v.string(),
154
+ app: v.string(),
155
+ scope: v.string(),
156
+ expired_at: MongoDBDateSchema,
157
+ created_at: MongoDBDateSchema,
158
+ owner: v.nullable(v.string()),
159
+ token: v.string(),
160
+ });
161
+ export type AccessToken = v.InferOutput<typeof AccessTokenSchema>;
162
+
163
+ // OAuth App (container for access tokens)
164
+ export const OAuthAppSchema = v.object({
165
+ id: v.string(),
166
+ secret: v.string(),
167
+ name: v.string(),
168
+ owner: v.string(),
169
+ created_at: MongoDBDateSchema,
170
+ authorized_domains: v.array(v.string()),
171
+ wroom_auths: v.array(AccessTokenSchema),
172
+ });
173
+ export type OAuthApp = v.InferOutput<typeof OAuthAppSchema>;
174
+
175
+ // Write Token
176
+ export const WriteTokenSchema = v.object({
177
+ app_name: v.string(),
178
+ token: v.string(),
179
+ timestamp: v.number(),
180
+ });
181
+ export type WriteToken = v.InferOutput<typeof WriteTokenSchema>;
182
+
183
+ // Write Tokens List Response
184
+ const WriteTokensInfoSchema = v.object({
185
+ max_tokens: v.number(),
186
+ tokens: v.array(WriteTokenSchema),
187
+ });
188
+ type WriteTokensInfo = v.InferOutput<typeof WriteTokensInfoSchema>;
189
+
190
+ // Response schemas
191
+ const GetAccessTokensResponseSchema = v.array(OAuthAppSchema);
192
+ type GetAccessTokensResponse = v.InferOutput<typeof GetAccessTokensResponseSchema>;
193
+
194
+ export async function getAccessTokens(
195
+ repo: string,
196
+ ): Promise<ParsedRequestResponse<GetAccessTokensResponse>> {
197
+ const url = new URL("settings/security/contentapi", await getRepoUrl(repo));
198
+ return await request(url, { schema: GetAccessTokensResponseSchema });
199
+ }
200
+
201
+ export async function getWriteTokens(
202
+ repo: string,
203
+ ): Promise<ParsedRequestResponse<WriteTokensInfo>> {
204
+ const url = new URL("settings/security/customtypesapi", await getRepoUrl(repo));
205
+ return await request(url, { schema: WriteTokensInfoSchema });
206
+ }
207
+
208
+ function truncateToken(token: string): string {
209
+ if (token.length <= 12) return token;
210
+ return `${token.slice(0, 8)}...${token.slice(-4)}`;
211
+ }
212
+
213
+ function formatDate(timestamp: number | MongoDBDate): string {
214
+ // MongoDB dates are in milliseconds, plain numbers are in seconds
215
+ const ms = typeof timestamp === "number" ? timestamp * 1000 : timestamp.$date;
216
+ const date = new Date(ms);
217
+ return date.toISOString().split("T")[0];
218
+ }
219
+
220
+ function handleUnauthenticated(): void {
221
+ console.error("Not logged in. Run `prismic login` first.");
222
+ process.exitCode = 1;
223
+ }
@@ -0,0 +1,193 @@
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, request, UnauthorizedRequestError } from "./lib/request";
8
+ import { getRepoUrl } from "./lib/url";
9
+ import {
10
+ getAccessTokens,
11
+ getWriteTokens,
12
+ type OAuthApp,
13
+ OAuthAppSchema,
14
+ type WriteToken,
15
+ } from "./token-list";
16
+
17
+ const HELP = `
18
+ Set the name of a token in a Prismic repository.
19
+
20
+ Note: Only access tokens can be renamed. Write tokens cannot be renamed without
21
+ changing the token value.
22
+
23
+ By default, this command reads the repository from prismic.config.json at the
24
+ project root.
25
+
26
+ USAGE
27
+ prismic token set-name <token> <name> [flags]
28
+
29
+ ARGUMENTS
30
+ token The token value (or partial match)
31
+ name New name for the token
32
+
33
+ FLAGS
34
+ -r, --repo string Repository domain
35
+ -h, --help Show help for command
36
+
37
+ LEARN MORE
38
+ Use \`prismic token <command> --help\` for more information about a command.
39
+ `.trim();
40
+
41
+ export async function tokenSetName(): Promise<void> {
42
+ const {
43
+ values: { help, repo = await safeGetRepositoryFromConfig() },
44
+ positionals: [tokenValue, newName],
45
+ } = parseArgs({
46
+ args: process.argv.slice(4), // skip: node, script, "token", "set-name"
47
+ options: {
48
+ repo: { type: "string", short: "r" },
49
+ help: { type: "boolean", short: "h" },
50
+ },
51
+ allowPositionals: true,
52
+ });
53
+
54
+ if (help) {
55
+ console.info(HELP);
56
+ return;
57
+ }
58
+
59
+ if (!tokenValue) {
60
+ console.error("Missing required argument: token");
61
+ process.exitCode = 1;
62
+ return;
63
+ }
64
+
65
+ if (!newName) {
66
+ console.error("Missing required argument: name");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+
71
+ if (!repo) {
72
+ console.error("Missing prismic.config.json or --repo option");
73
+ process.exitCode = 1;
74
+ return;
75
+ }
76
+
77
+ const authenticated = await isAuthenticated();
78
+ if (!authenticated) {
79
+ handleUnauthenticated();
80
+ return;
81
+ }
82
+
83
+ // First, find the token in access tokens or write tokens
84
+ const [accessResponse, writeResponse] = await Promise.all([
85
+ getAccessTokens(repo),
86
+ getWriteTokens(repo),
87
+ ]);
88
+
89
+ if (!accessResponse.ok) {
90
+ if (
91
+ accessResponse.error instanceof ForbiddenRequestError ||
92
+ accessResponse.error instanceof UnauthorizedRequestError
93
+ ) {
94
+ handleUnauthenticated();
95
+ } else if (v.isValiError(accessResponse.error)) {
96
+ console.error(
97
+ `Failed to list access tokens: Invalid response: ${stringify(accessResponse.error.issues)}`,
98
+ );
99
+ process.exitCode = 1;
100
+ } else {
101
+ console.error(`Failed to list access tokens: ${stringify(accessResponse.value)}`);
102
+ process.exitCode = 1;
103
+ }
104
+ return;
105
+ }
106
+
107
+ if (!writeResponse.ok) {
108
+ if (
109
+ writeResponse.error instanceof ForbiddenRequestError ||
110
+ writeResponse.error instanceof UnauthorizedRequestError
111
+ ) {
112
+ handleUnauthenticated();
113
+ } else if (v.isValiError(writeResponse.error)) {
114
+ console.error(
115
+ `Failed to list write tokens: Invalid response: ${stringify(writeResponse.error.issues)}`,
116
+ );
117
+ process.exitCode = 1;
118
+ } else {
119
+ console.error(`Failed to list write tokens: ${stringify(writeResponse.value)}`);
120
+ process.exitCode = 1;
121
+ }
122
+ return;
123
+ }
124
+
125
+ // Find in access tokens
126
+ let foundApp: OAuthApp | undefined;
127
+ for (const app of accessResponse.value) {
128
+ for (const auth of app.wroom_auths) {
129
+ if (
130
+ auth.token === tokenValue ||
131
+ auth.token.startsWith(tokenValue) ||
132
+ auth.token.endsWith(tokenValue)
133
+ ) {
134
+ foundApp = app;
135
+ break;
136
+ }
137
+ }
138
+ if (foundApp) break;
139
+ }
140
+
141
+ if (foundApp) {
142
+ // Update OAuth app name
143
+ const url = new URL(`settings/security/oauthapp/${foundApp.id}`, await getRepoUrl(repo));
144
+ const response = await request(url, {
145
+ method: "POST",
146
+ body: { name: newName },
147
+ schema: OAuthAppSchema,
148
+ });
149
+
150
+ if (!response.ok) {
151
+ if (
152
+ response.error instanceof ForbiddenRequestError ||
153
+ response.error instanceof UnauthorizedRequestError
154
+ ) {
155
+ handleUnauthenticated();
156
+ } else if (v.isValiError(response.error)) {
157
+ console.error(
158
+ `Failed to rename token: Invalid response: ${stringify(response.error.issues)}`,
159
+ );
160
+ process.exitCode = 1;
161
+ } else {
162
+ console.error(`Failed to rename token: ${stringify(response.value)}`);
163
+ process.exitCode = 1;
164
+ }
165
+ return;
166
+ }
167
+
168
+ console.info(`Token renamed to: ${newName}`);
169
+ return;
170
+ }
171
+
172
+ // Check if it's a write token
173
+ const foundWriteToken = writeResponse.value.tokens.find(
174
+ (t: WriteToken) =>
175
+ t.token === tokenValue || t.token.startsWith(tokenValue) || t.token.endsWith(tokenValue),
176
+ );
177
+
178
+ if (foundWriteToken) {
179
+ console.error(
180
+ "Write tokens cannot be renamed. Delete and create a new token with the desired name.",
181
+ );
182
+ process.exitCode = 1;
183
+ return;
184
+ }
185
+
186
+ console.error(`Token not found: ${tokenValue}`);
187
+ process.exitCode = 1;
188
+ }
189
+
190
+ function handleUnauthenticated(): void {
191
+ console.error("Not logged in. Run `prismic login` first.");
192
+ process.exitCode = 1;
193
+ }
package/src/token.ts ADDED
@@ -0,0 +1,60 @@
1
+ import { parseArgs } from "node:util";
2
+
3
+ import { tokenCreate } from "./token-create";
4
+ import { tokenDelete } from "./token-delete";
5
+ import { tokenList } from "./token-list";
6
+ import { tokenSetName } from "./token-set-name";
7
+
8
+ const HELP = `
9
+ Manage API tokens for a Prismic repository.
10
+
11
+ USAGE
12
+ prismic token <command> [flags]
13
+
14
+ COMMANDS
15
+ list List all tokens
16
+ create Create a new token
17
+ set-name Set token name (access tokens only)
18
+ delete Delete a token
19
+
20
+ FLAGS
21
+ -h, --help Show help for command
22
+
23
+ LEARN MORE
24
+ Use \`prismic token <command> --help\` for more information about a command.
25
+ `.trim();
26
+
27
+ export async function token(): Promise<void> {
28
+ const {
29
+ positionals: [subcommand],
30
+ } = parseArgs({
31
+ args: process.argv.slice(3), // skip: node, script, "token"
32
+ options: {
33
+ help: { type: "boolean", short: "h" },
34
+ },
35
+ allowPositionals: true,
36
+ strict: false,
37
+ });
38
+
39
+ switch (subcommand) {
40
+ case "list":
41
+ await tokenList();
42
+ break;
43
+ case "create":
44
+ await tokenCreate();
45
+ break;
46
+ case "set-name":
47
+ await tokenSetName();
48
+ break;
49
+ case "delete":
50
+ await tokenDelete();
51
+ break;
52
+ default: {
53
+ if (subcommand) {
54
+ console.error(`Unknown token subcommand: ${subcommand}\n`);
55
+ process.exitCode = 1;
56
+ }
57
+ console.info(HELP);
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,118 @@
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 } from "./lib/request";
7
+ import { updateWebhook } from "./webhook-enable";
8
+ import { getWebhooks } from "./webhook-view";
9
+
10
+ const HELP = `
11
+ Add a custom HTTP header to a webhook.
12
+
13
+ By default, this command reads the repository from prismic.config.json at the
14
+ project root.
15
+
16
+ USAGE
17
+ prismic webhook add-header <url> <key> <value> [flags]
18
+
19
+ ARGUMENTS
20
+ <url> Webhook URL
21
+ <key> Header name
22
+ <value> Header value
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 webhookAddHeader(): Promise<void> {
33
+ const {
34
+ values: { help, repo = await safeGetRepositoryFromConfig() },
35
+ positionals: [webhookUrl, headerKey, headerValue],
36
+ } = parseArgs({
37
+ args: process.argv.slice(4), // skip: node, script, "webhook", "add-header"
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 (!webhookUrl) {
51
+ console.error("Missing required argument: <url>");
52
+ process.exitCode = 1;
53
+ return;
54
+ }
55
+
56
+ if (!headerKey) {
57
+ console.error("Missing required argument: <key>");
58
+ process.exitCode = 1;
59
+ return;
60
+ }
61
+
62
+ if (!headerValue) {
63
+ console.error("Missing required argument: <value>");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ if (!repo) {
69
+ console.error("Missing prismic.config.json or --repo option");
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+
74
+ const authenticated = await isAuthenticated();
75
+ if (!authenticated) {
76
+ handleUnauthenticated();
77
+ return;
78
+ }
79
+
80
+ const webhooksResponse = await getWebhooks(repo);
81
+ if (!webhooksResponse.ok) {
82
+ if (webhooksResponse.error instanceof ForbiddenRequestError) {
83
+ handleUnauthenticated();
84
+ } else {
85
+ console.error(`Failed to add header: ${stringify(webhooksResponse.value)}`);
86
+ process.exitCode = 1;
87
+ }
88
+ return;
89
+ }
90
+
91
+ const webhook = webhooksResponse.value.find((w) => w.config.url === webhookUrl);
92
+ if (!webhook) {
93
+ console.error(`Webhook not found: ${webhookUrl}`);
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+
98
+ const updatedConfig = structuredClone(webhook.config);
99
+ updatedConfig.headers[headerKey] = headerValue;
100
+
101
+ const response = await updateWebhook(repo, webhook.config._id, updatedConfig);
102
+ if (!response.ok) {
103
+ if (response.error instanceof ForbiddenRequestError) {
104
+ handleUnauthenticated();
105
+ } else {
106
+ console.error(`Failed to add header: ${stringify(response.value)}`);
107
+ process.exitCode = 1;
108
+ }
109
+ return;
110
+ }
111
+
112
+ console.info(`Header added: ${headerKey}`);
113
+ }
114
+
115
+ function handleUnauthenticated() {
116
+ console.error("Not logged in. Run `prismic login` first.");
117
+ process.exitCode = 1;
118
+ }