@angeloashmore/prismic-cli-poc 0.0.0-canary.2ff9563 → 0.0.0-canary.d96e685

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angeloashmore/prismic-cli-poc",
3
- "version": "0.0.0-canary.2ff9563",
3
+ "version": "0.0.0-canary.d96e685",
4
4
  "description": "A proof-of-concept developer CLI for Prismic.",
5
5
  "keywords": [
6
6
  "prismic",
package/src/index.ts CHANGED
@@ -11,7 +11,6 @@ import { pageType } from "./page-type";
11
11
  import { preview } from "./preview";
12
12
  import { repo } from "./repo";
13
13
  import { slice } from "./slice";
14
- import { sync } from "./sync";
15
14
  import { token } from "./token";
16
15
  import { webhook } from "./webhook";
17
16
  import { whoami } from "./whoami";
@@ -32,7 +31,6 @@ COMMANDS
32
31
  page-type Manage page types in a repository
33
32
  custom-type Manage custom types in a repository
34
33
  slice Manage slices in a project
35
- sync Sync types and slices from Prismic
36
34
  preview Manage preview configurations
37
35
  token Manage API tokens in a repository
38
36
  webhook Manage webhooks in a repository
@@ -78,9 +76,6 @@ switch (positionals[0]) {
78
76
  case "slice":
79
77
  await slice();
80
78
  break;
81
- case "sync":
82
- await sync();
83
- break;
84
79
  case "preview":
85
80
  await preview();
86
81
  break;
package/src/sync.ts DELETED
@@ -1,309 +0,0 @@
1
- import type { CustomType, SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
-
3
- import { mkdir, writeFile } from "node:fs/promises";
4
- import { parseArgs } from "node:util";
5
- import * as v from "valibot";
6
-
7
- import { isAuthenticated, readHost, readToken } from "./lib/auth";
8
- import { safeGetRepositoryFromConfig } from "./lib/config";
9
- import { findUpward } from "./lib/file";
10
- import { stringify } from "./lib/json";
11
- import { getSlicesDirectory, pascalCase, SharedSliceSchema } from "./lib/slice";
12
-
13
- const HELP = `
14
- Sync custom types and slices from Prismic to local files.
15
-
16
- By default, this command reads the repository from prismic.config.json at the
17
- project root.
18
-
19
- USAGE
20
- prismic sync [flags]
21
-
22
- FLAGS
23
- -r, --repo string Repository domain
24
- --dry-run Show what would be synced without writing files
25
- --types-only Only sync custom types
26
- --slices-only Only sync slices
27
- --json Output as JSON
28
- -h, --help Show help for command
29
-
30
- EXAMPLES
31
- prismic sync
32
- prismic sync --repo my-repo
33
- prismic sync --dry-run
34
- prismic sync --types-only
35
- `.trim();
36
-
37
- const CustomTypeSchema = v.object({
38
- id: v.string(),
39
- label: v.optional(v.string()),
40
- repeatable: v.boolean(),
41
- status: v.boolean(),
42
- format: v.optional(v.string()),
43
- json: v.record(v.string(), v.unknown()),
44
- });
45
-
46
- export async function sync(): Promise<void> {
47
- const {
48
- values: { help, repo = await safeGetRepositoryFromConfig(), "dry-run": dryRun, "types-only": typesOnly, "slices-only": slicesOnly, json },
49
- } = parseArgs({
50
- args: process.argv.slice(3), // skip: node, script, "sync"
51
- options: {
52
- repo: { type: "string", short: "r" },
53
- "dry-run": { type: "boolean" },
54
- "types-only": { type: "boolean" },
55
- "slices-only": { type: "boolean" },
56
- json: { type: "boolean" },
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(`Syncing 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 ? fetchRemoteCustomTypes(repo) : Promise.resolve({ ok: true, value: [] } as const),
90
- shouldFetchSlices ? fetchRemoteSlices(repo) : Promise.resolve({ ok: true, value: [] } as const),
91
- ]);
92
-
93
- if (!customTypesResult.ok) {
94
- console.error(`Failed to fetch custom types: ${customTypesResult.error}`);
95
- process.exitCode = 1;
96
- return;
97
- }
98
-
99
- if (!slicesResult.ok) {
100
- console.error(`Failed to fetch slices: ${slicesResult.error}`);
101
- process.exitCode = 1;
102
- return;
103
- }
104
-
105
- const customTypes = customTypesResult.value;
106
- const slices = slicesResult.value;
107
-
108
- if (!json) {
109
- if (shouldFetchTypes) {
110
- console.info(`Fetching custom types... ${customTypes.length} types`);
111
- }
112
- if (shouldFetchSlices) {
113
- console.info(`Fetching slices... ${slices.length} slices`);
114
- }
115
- }
116
-
117
- // Dry run - just show what would be synced
118
- if (dryRun) {
119
- if (json) {
120
- console.info(stringify({ customTypes, slices }));
121
- } else {
122
- console.info("");
123
- if (shouldFetchTypes && customTypes.length > 0) {
124
- console.info("Would write custom types:");
125
- for (const ct of customTypes) {
126
- console.info(` customtypes/${ct.id}/index.json`);
127
- }
128
- }
129
- if (shouldFetchSlices && slices.length > 0) {
130
- const slicesDir = await getSlicesDirectory();
131
- const relativeSlicesDir = getRelativePath(slicesDir);
132
- console.info("Would write slices:");
133
- for (const slice of slices) {
134
- console.info(` ${relativeSlicesDir}${pascalCase(slice.name)}/model.json`);
135
- }
136
- }
137
- console.info(`\nDry run complete: ${customTypes.length} custom types, ${slices.length} slices`);
138
- }
139
- return;
140
- }
141
-
142
- // Find project root
143
- const projectRoot = await findUpward("package.json");
144
- if (!projectRoot) {
145
- console.error("Could not find project root (no package.json found)");
146
- process.exitCode = 1;
147
- return;
148
- }
149
- const projectDir = new URL(".", projectRoot);
150
-
151
- const writtenTypes: string[] = [];
152
- const writtenSlices: string[] = [];
153
-
154
- // Write custom types
155
- if (shouldFetchTypes && customTypes.length > 0) {
156
- if (!json) {
157
- console.info("\nWriting custom types:");
158
- }
159
- const customTypesDir = new URL("customtypes/", projectDir);
160
-
161
- for (const ct of customTypes) {
162
- const typeDir = new URL(`${ct.id}/`, customTypesDir);
163
- const modelPath = new URL("index.json", typeDir);
164
-
165
- try {
166
- await mkdir(typeDir, { recursive: true });
167
- await writeFile(modelPath, stringify(ct));
168
- const relativePath = `customtypes/${ct.id}/index.json`;
169
- writtenTypes.push(relativePath);
170
- if (!json) {
171
- console.info(` ${relativePath}`);
172
- }
173
- } catch (error) {
174
- console.error(`Failed to write custom type ${ct.id}: ${error instanceof Error ? error.message : error}`);
175
- process.exitCode = 1;
176
- return;
177
- }
178
- }
179
- }
180
-
181
- // Write slices
182
- if (shouldFetchSlices && slices.length > 0) {
183
- if (!json) {
184
- console.info("\nWriting slices:");
185
- }
186
- const slicesDir = await getSlicesDirectory();
187
-
188
- for (const slice of slices) {
189
- const sliceDir = new URL(`${pascalCase(slice.name)}/`, slicesDir);
190
- const modelPath = new URL("model.json", sliceDir);
191
-
192
- try {
193
- await mkdir(sliceDir, { recursive: true });
194
- await writeFile(modelPath, stringify(slice));
195
- const relativePath = `${getRelativePath(slicesDir)}${pascalCase(slice.name)}/model.json`;
196
- writtenSlices.push(relativePath);
197
- if (!json) {
198
- console.info(` ${relativePath}`);
199
- }
200
- } catch (error) {
201
- console.error(`Failed to write slice ${slice.name}: ${error instanceof Error ? error.message : error}`);
202
- process.exitCode = 1;
203
- return;
204
- }
205
- }
206
- }
207
-
208
- // Output summary
209
- if (json) {
210
- console.info(stringify({ writtenTypes, writtenSlices }));
211
- } else {
212
- console.info(`\nSync complete: ${writtenTypes.length} custom types, ${writtenSlices.length} slices`);
213
- }
214
- }
215
-
216
- async function getCustomTypesApiUrl(): Promise<URL> {
217
- const host = await readHost();
218
- host.hostname = `customtypes.${host.hostname}`;
219
- return host;
220
- }
221
-
222
- type FetchResult<T> = { ok: true; value: T } | { ok: false; error: string };
223
-
224
- async function fetchRemoteCustomTypes(repo: string): Promise<FetchResult<CustomType[]>> {
225
- const token = await readToken();
226
- if (!token) {
227
- return { ok: false, error: "Not authenticated" };
228
- }
229
-
230
- const baseUrl = await getCustomTypesApiUrl();
231
- const url = new URL("customtypes", baseUrl);
232
-
233
- try {
234
- const response = await fetch(url, {
235
- headers: {
236
- Authorization: `Bearer ${token}`,
237
- repository: repo,
238
- },
239
- });
240
-
241
- if (!response.ok) {
242
- if (response.status === 401) {
243
- return { ok: false, error: "Unauthorized. Your session may have expired. Run `prismic login` again." };
244
- }
245
- if (response.status === 403) {
246
- return { ok: false, error: `Access denied. You may not have access to repository "${repo}".` };
247
- }
248
- return { ok: false, error: `API error: ${response.status} ${response.statusText}` };
249
- }
250
-
251
- const data = await response.json();
252
- const result = v.safeParse(v.array(CustomTypeSchema), data);
253
- if (!result.success) {
254
- return { ok: false, error: "Invalid response from Custom Types API" };
255
- }
256
-
257
- return { ok: true, value: result.output as CustomType[] };
258
- } catch (error) {
259
- return { ok: false, error: `Network error: ${error instanceof Error ? error.message : error}` };
260
- }
261
- }
262
-
263
- async function fetchRemoteSlices(repo: string): Promise<FetchResult<SharedSlice[]>> {
264
- const token = await readToken();
265
- if (!token) {
266
- return { ok: false, error: "Not authenticated" };
267
- }
268
-
269
- const baseUrl = await getCustomTypesApiUrl();
270
- const url = new URL("slices", baseUrl);
271
-
272
- try {
273
- const response = await fetch(url, {
274
- headers: {
275
- Authorization: `Bearer ${token}`,
276
- repository: repo,
277
- },
278
- });
279
-
280
- if (!response.ok) {
281
- if (response.status === 401) {
282
- return { ok: false, error: "Unauthorized. Your session may have expired. Run `prismic login` again." };
283
- }
284
- if (response.status === 403) {
285
- return { ok: false, error: `Access denied. You may not have access to repository "${repo}".` };
286
- }
287
- return { ok: false, error: `API error: ${response.status} ${response.statusText}` };
288
- }
289
-
290
- const data = await response.json();
291
- const result = v.safeParse(v.array(SharedSliceSchema), data);
292
- if (!result.success) {
293
- return { ok: false, error: "Invalid response from Custom Types API" };
294
- }
295
-
296
- return { ok: true, value: result.output as SharedSlice[] };
297
- } catch (error) {
298
- return { ok: false, error: `Network error: ${error instanceof Error ? error.message : error}` };
299
- }
300
- }
301
-
302
- function getRelativePath(url: URL): string {
303
- const cwd = process.cwd();
304
- const path = url.pathname;
305
- if (path.startsWith(cwd)) {
306
- return path.slice(cwd.length + 1);
307
- }
308
- return path;
309
- }