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,241 @@
1
+ import type { SharedSlice } from "@prismicio/types-internal/lib/customtypes";
2
+
3
+ import { loadFile } from "magicast";
4
+ import { mkdir, writeFile } from "node:fs/promises";
5
+ import { createRequire } from "node:module";
6
+
7
+ import type { Framework } from ".";
8
+
9
+ import { FrameworkAdapter } from ".";
10
+ import { exists } from "../lib/file";
11
+ import { getNpmPackageVersion } from "../lib/packageJson";
12
+ import { dedent } from "../lib/string";
13
+ import {
14
+ previewAPIRouteTemplate,
15
+ prismicIOFileTemplate,
16
+ rootLayoutTemplate,
17
+ sliceSimulatorPageTemplate,
18
+ sliceTemplate,
19
+ } from "./sveltekit.templates";
20
+
21
+ export class SvelteKitFramework extends FrameworkAdapter {
22
+ readonly id: Framework = "sveltekit";
23
+
24
+ async getDependencies(): Promise<Record<string, string>> {
25
+ return {
26
+ "@prismicio/client": `^${await getNpmPackageVersion("@prismicio/client")}`,
27
+ "@prismicio/svelte": `^${await getNpmPackageVersion("@prismicio/svelte")}`,
28
+ };
29
+ }
30
+
31
+ async initProject(): Promise<void> {
32
+ await super.initProject();
33
+
34
+ await this.#createPrismicIOFile();
35
+ await this.#createSliceSimulatorPage();
36
+ await this.#createPreviewRouteMatcher();
37
+ await this.#createPreviewAPIRoute();
38
+ await this.#createPreviewRouteDirectory();
39
+ await this.#createRootLayoutServerFile();
40
+ await this.#createRootLayoutFile();
41
+ await this.#modifyViteConfig();
42
+ }
43
+
44
+ async createSliceComponent(
45
+ model: SharedSlice,
46
+ sliceDirectory: URL,
47
+ ): Promise<{ componentPath: URL }> {
48
+ const componentPath = new URL("index.svelte", sliceDirectory);
49
+ const contents = sliceTemplate({
50
+ name: model.name,
51
+ typescript: await this.checkIsTypeScriptProject(),
52
+ version: await this.#getSvelteMajor(),
53
+ });
54
+ await writeFile(componentPath, contents);
55
+ return { componentPath };
56
+ }
57
+
58
+ getSliceImportPath(relativeDirectory: string): string {
59
+ return `./${relativeDirectory}/index.svelte`;
60
+ }
61
+
62
+ async getDefaultSliceLibraryPath(projectRoot: URL): Promise<URL> {
63
+ return new URL("src/lib/slices/", projectRoot);
64
+ }
65
+
66
+ async getClientFilePath(): Promise<string | null> {
67
+ return "src/lib/prismicio.ts";
68
+ }
69
+
70
+ async getSlicesDirectoryPath(): Promise<string> {
71
+ return "src/lib/slices/";
72
+ }
73
+
74
+ getSliceComponentExtensions(): string[] {
75
+ return [".svelte"];
76
+ }
77
+
78
+ async getRoutePath(route: string): Promise<{ path: string; extensions: string[] } | null> {
79
+ switch (route) {
80
+ case "/slice-simulator":
81
+ return { path: "src/routes/slice-simulator/+page", extensions: [".svelte"] };
82
+ case "/api/preview":
83
+ return { path: "src/routes/api/preview/+server", extensions: [".ts", ".js"] };
84
+ default:
85
+ return null;
86
+ }
87
+ }
88
+
89
+ async #createPrismicIOFile(): Promise<void> {
90
+ const extension = await this.getJsFileExtension();
91
+ const projectRoot = await this.getProjectRoot();
92
+ const filePath = new URL(`src/lib/prismicio.${extension}`, projectRoot);
93
+
94
+ if (await exists(filePath)) {
95
+ return;
96
+ }
97
+
98
+ const typescript = await this.checkIsTypeScriptProject();
99
+ const contents = prismicIOFileTemplate({ typescript });
100
+ await mkdir(new URL(".", filePath), { recursive: true });
101
+ await writeFile(filePath, contents);
102
+ }
103
+
104
+ async #createSliceSimulatorPage(): Promise<void> {
105
+ const projectRoot = await this.getProjectRoot();
106
+ const filePath = new URL("src/routes/slice-simulator/+page.svelte", projectRoot);
107
+
108
+ if (await exists(filePath)) {
109
+ return;
110
+ }
111
+
112
+ const contents = sliceSimulatorPageTemplate({
113
+ version: await this.#getSvelteMajor(),
114
+ });
115
+ await mkdir(new URL(".", filePath), { recursive: true });
116
+ await writeFile(filePath, contents);
117
+ }
118
+
119
+ async #createPreviewRouteMatcher(): Promise<void> {
120
+ const extension = await this.getJsFileExtension();
121
+ const projectRoot = await this.getProjectRoot();
122
+ const filePath = new URL(`src/params/preview.${extension}`, projectRoot);
123
+
124
+ if (await exists(filePath)) {
125
+ return;
126
+ }
127
+
128
+ const contents = dedent`
129
+ export function match(param) {
130
+ return param === 'preview';
131
+ }
132
+ `;
133
+ await mkdir(new URL(".", filePath), { recursive: true });
134
+ await writeFile(filePath, contents);
135
+ }
136
+
137
+ async #createPreviewAPIRoute(): Promise<void> {
138
+ const extension = await this.getJsFileExtension();
139
+ const projectRoot = await this.getProjectRoot();
140
+ const filePath = new URL(`src/routes/api/preview/+server.${extension}`, projectRoot);
141
+
142
+ if (await exists(filePath)) {
143
+ return;
144
+ }
145
+
146
+ const typescript = await this.checkIsTypeScriptProject();
147
+ const contents = previewAPIRouteTemplate({ typescript });
148
+ await mkdir(new URL(".", filePath), { recursive: true });
149
+ await writeFile(filePath, contents);
150
+ }
151
+
152
+ async #createPreviewRouteDirectory(): Promise<void> {
153
+ const projectRoot = await this.getProjectRoot();
154
+ const filePath = new URL("src/routes/[[preview=preview]]/README.md", projectRoot);
155
+
156
+ if (await exists(filePath)) {
157
+ return;
158
+ }
159
+
160
+ const contents = dedent`
161
+ This directory adds support for optional \`/preview\` routes. Do not remove this directory.
162
+
163
+ All routes within this directory will be served using the following URLs:
164
+
165
+ - \`/example-route\` (prerendered)
166
+ - \`/preview/example-route\` (server-rendered)
167
+
168
+ See <https://prismic.io/docs/svelte-preview> for more information.
169
+ `;
170
+ await mkdir(new URL(".", filePath), { recursive: true });
171
+ await writeFile(filePath, contents);
172
+ }
173
+
174
+ async #createRootLayoutServerFile(): Promise<void> {
175
+ const extension = await this.getJsFileExtension();
176
+ const projectRoot = await this.getProjectRoot();
177
+ const filePath = new URL(`src/routes/+layout.server.${extension}`, projectRoot);
178
+
179
+ if (await exists(filePath)) {
180
+ return;
181
+ }
182
+
183
+ const contents = dedent`
184
+ export const prerender = "auto";
185
+ `;
186
+ await mkdir(new URL(".", filePath), { recursive: true });
187
+ await writeFile(filePath, contents);
188
+ }
189
+
190
+ async #createRootLayoutFile(): Promise<void> {
191
+ const projectRoot = await this.getProjectRoot();
192
+ const filePath = new URL("src/routes/+layout.svelte", projectRoot);
193
+
194
+ if (await exists(filePath)) {
195
+ return;
196
+ }
197
+
198
+ const contents = rootLayoutTemplate({
199
+ version: await this.#getSvelteMajor(),
200
+ });
201
+ await mkdir(new URL(".", filePath), { recursive: true });
202
+ await writeFile(filePath, contents);
203
+ }
204
+
205
+ async #modifyViteConfig(): Promise<void> {
206
+ const projectRoot = await this.getProjectRoot();
207
+ let configUrl = new URL("vite.config.js", projectRoot);
208
+ if (!(await exists(configUrl))) {
209
+ configUrl = new URL("vite.config.ts", projectRoot);
210
+ }
211
+ if (!(await exists(configUrl))) {
212
+ return;
213
+ }
214
+
215
+ const filepath = configUrl.pathname;
216
+ const mod = await loadFile(filepath);
217
+ if (mod.exports.default.$type !== "function-call") {
218
+ return;
219
+ }
220
+
221
+ const config = mod.exports.default.$args[0];
222
+ config.server ??= {};
223
+ config.server.fs ??= {};
224
+ config.server.fs.allow ??= [];
225
+ if (!config.server.fs.allow.includes("./prismic.config.json")) {
226
+ config.server.fs.allow.push("./prismic.config.json");
227
+ }
228
+
229
+ const contents = mod.generate().code.replace(/\n\s*\n(?=\s*server:)/, "\n");
230
+ await writeFile(configUrl, contents);
231
+ }
232
+
233
+ async #getSvelteMajor(): Promise<number> {
234
+ const projectRoot = await this.getProjectRoot();
235
+ const require = createRequire(new URL("package.json", projectRoot));
236
+ const { version } = require("svelte/package.json");
237
+ const major = Number.parseInt(version.split(".")[0]);
238
+ if (Number.isNaN(major)) return Infinity;
239
+ return major;
240
+ }
241
+ }
package/src/index.ts ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ import packageJson from "../package.json" with { type: "json" };
6
+ import { codegen } from "./codegen";
7
+ import { customType } from "./custom-type";
8
+ import { docs } from "./docs";
9
+ import { initSegment, trackEnd, trackStart } from "./lib/segment";
10
+ import { captureError, setupSentry } from "./lib/sentry";
11
+ import { init } from "./init";
12
+ import { locale } from "./locale";
13
+ import { login } from "./login";
14
+ import { logout } from "./logout";
15
+ import { pageType } from "./page-type";
16
+ import { preview } from "./preview";
17
+ import { pull } from "./pull";
18
+ import { push } from "./push";
19
+ import { repo } from "./repo";
20
+ import { slice } from "./slice";
21
+ import { status } from "./status";
22
+ import { sync } from "./sync";
23
+ import { token } from "./token";
24
+ import { webhook } from "./webhook";
25
+ import { whoami } from "./whoami";
26
+
27
+ const HELP = `
28
+ Prismic CLI for managing repositories and configurations.
29
+
30
+ USAGE
31
+ prismic <command> [flags]
32
+
33
+ COMMANDS
34
+ init Initialize a Prismic project
35
+ sync Sync types and slices from Prismic
36
+ login Log in to Prismic
37
+ logout Log out of Prismic
38
+ whoami Show the currently logged in user
39
+ status Show the status of the current project
40
+ repo Manage Prismic repositories
41
+ locale Manage locales in a repository
42
+ page-type Manage page types in a repository
43
+ custom-type Manage custom types in a repository
44
+ slice Manage slices in a project
45
+ pull Pull types and slices from Prismic
46
+ push Push types and slices to Prismic
47
+ codegen Generate code from Prismic models
48
+ docs Fetch and list documentation from Prismic
49
+ preview Manage preview configurations
50
+ token Manage API tokens in a repository
51
+ webhook Manage webhooks in a repository
52
+
53
+ FLAGS
54
+ -v, --version Show CLI version
55
+ -h, --help Show help for command
56
+
57
+ LEARN MORE
58
+ Use \`prismic <command> --help\` for more information about a command.
59
+ `.trim();
60
+
61
+ const {
62
+ positionals,
63
+ values: { version },
64
+ } = parseArgs({
65
+ options: {
66
+ help: { type: "boolean", short: "h" },
67
+ version: { type: "boolean", short: "v" },
68
+ },
69
+ allowPositionals: true,
70
+ strict: false,
71
+ });
72
+
73
+ setupSentry();
74
+ await initSegment();
75
+
76
+ if (version) {
77
+ console.info(packageJson.version);
78
+ } else {
79
+ const command = positionals[0];
80
+
81
+ trackStart(command);
82
+
83
+ try {
84
+ switch (command) {
85
+ case "init":
86
+ await init();
87
+ break;
88
+ case "sync":
89
+ await sync();
90
+ break;
91
+ case "login":
92
+ await login();
93
+ break;
94
+ case "logout":
95
+ await logout();
96
+ break;
97
+ case "whoami":
98
+ await whoami();
99
+ break;
100
+ case "status":
101
+ await status();
102
+ break;
103
+ case "repo":
104
+ await repo();
105
+ break;
106
+ case "locale":
107
+ await locale();
108
+ break;
109
+ case "page-type":
110
+ await pageType();
111
+ break;
112
+ case "custom-type":
113
+ await customType();
114
+ break;
115
+ case "slice":
116
+ await slice();
117
+ break;
118
+ case "pull":
119
+ await pull();
120
+ break;
121
+ case "push":
122
+ await push();
123
+ break;
124
+ case "codegen":
125
+ await codegen();
126
+ break;
127
+ case "docs":
128
+ await docs();
129
+ break;
130
+ case "preview":
131
+ await preview();
132
+ break;
133
+ case "token":
134
+ await token();
135
+ break;
136
+ case "webhook":
137
+ await webhook();
138
+ break;
139
+ default: {
140
+ if (command) {
141
+ console.error(`Unknown command: ${command}`);
142
+ process.exitCode = 1;
143
+ }
144
+ console.info(HELP);
145
+ }
146
+ }
147
+
148
+ trackEnd(command, process.exitCode !== 1);
149
+ } catch (error) {
150
+ await captureError(error);
151
+ trackEnd(command, false, error);
152
+ process.exitCode = 1;
153
+ throw error;
154
+ }
155
+ }
package/src/init.ts ADDED
@@ -0,0 +1,173 @@
1
+ import { readFile, rm } from "node:fs/promises";
2
+ import { parseArgs } from "node:util";
3
+ import * as v from "valibot";
4
+
5
+ import { createLoginSession, isAuthenticated } from "./lib/auth";
6
+ import { openBrowser } from "./lib/browser";
7
+ import { createConfig, readConfig, UnknownProjectRoot } from "./lib/config";
8
+ import { findUpward } from "./lib/file";
9
+ import { getFramework } from "./framework";
10
+ import { request } from "./lib/request";
11
+ import { getUserServiceUrl } from "./lib/url";
12
+ import { syncCustomTypes, syncSlices } from "./sync";
13
+
14
+ const HELP = `
15
+ Initialize a Prismic project by creating a prismic.config.json file.
16
+
17
+ Detects the project framework, installs dependencies, and syncs models
18
+ from Prismic. If a slicemachine.config.json exists, it will be migrated.
19
+
20
+ USAGE
21
+ prismic init [flags]
22
+
23
+ FLAGS
24
+ -r, --repo string Repository name
25
+ -h, --help Show help for command
26
+
27
+ EXAMPLES
28
+ prismic init --repo my-repo
29
+
30
+ LEARN MORE
31
+ Use \`prismic <command> --help\` for more information about a command.
32
+ `.trim();
33
+
34
+ const ProfileSchema = v.object({
35
+ repositories: v.array(
36
+ v.object({
37
+ domain: v.string(),
38
+ name: v.optional(v.string()),
39
+ }),
40
+ ),
41
+ });
42
+
43
+ export async function init(): Promise<void> {
44
+ const { values } = parseArgs({
45
+ args: process.argv.slice(3),
46
+ options: {
47
+ help: { type: "boolean", short: "h" },
48
+ repo: { type: "string", short: "r" },
49
+ },
50
+ });
51
+
52
+ if (values.help) {
53
+ console.info(HELP);
54
+ return;
55
+ }
56
+
57
+ // Check for existing prismic.config.json
58
+ const existingConfig = await readConfig();
59
+ if (existingConfig.ok) {
60
+ console.error("A prismic.config.json file already exists.");
61
+ process.exitCode = 1;
62
+ return;
63
+ }
64
+
65
+ // Check for legacy slicemachine.config.json
66
+ const legacyConfigPath = await findUpward("slicemachine.config.json", {
67
+ stop: "package.json",
68
+ });
69
+ let legacyRepoName: string | undefined;
70
+ let legacyLibraries: string[] | undefined;
71
+
72
+ if (legacyConfigPath) {
73
+ try {
74
+ const contents = await readFile(legacyConfigPath, "utf8");
75
+ const legacyConfig = JSON.parse(contents);
76
+ legacyRepoName = legacyConfig.repositoryName;
77
+ legacyLibraries = legacyConfig.libraries;
78
+ } catch {
79
+ console.warn("Could not read slicemachine.config.json, ignoring.");
80
+ }
81
+ }
82
+
83
+ // Determine repo name: --repo flag > legacy config > error
84
+ const repo = values.repo ?? legacyRepoName;
85
+ if (!repo) {
86
+ console.error("Missing required flag: --repo");
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+
91
+ // Login if needed
92
+ if (!(await isAuthenticated())) {
93
+ console.info("Not logged in. Starting login...");
94
+ const { email } = await createLoginSession({
95
+ onReady: (url) => {
96
+ console.info("Opening browser to complete login...");
97
+ console.info(`If the browser doesn't open, visit: ${url}`);
98
+ openBrowser(url);
99
+ },
100
+ });
101
+ console.info(`Logged in as ${email}`);
102
+ }
103
+
104
+ // Validate repo membership
105
+ const profileUrl = new URL("profile", await getUserServiceUrl());
106
+ const profileResponse = await request(profileUrl, {
107
+ schema: ProfileSchema,
108
+ });
109
+ if (!profileResponse.ok) {
110
+ console.error("Failed to fetch user profile.");
111
+ process.exitCode = 1;
112
+ return;
113
+ }
114
+
115
+ const repoData = profileResponse.value.repositories.find(
116
+ (r) => r.domain === repo,
117
+ );
118
+ if (!repoData) {
119
+ console.error(
120
+ `Repository "${repo}" not found in your account. Check the name or create it with \`prismic repo create\`.`,
121
+ );
122
+ process.exitCode = 1;
123
+ return;
124
+ }
125
+
126
+ // Detect framework
127
+ const framework = await getFramework();
128
+ if (!framework) {
129
+ console.error(
130
+ "Could not detect a supported framework (Next.js, Nuxt, or SvelteKit).",
131
+ );
132
+ process.exitCode = 1;
133
+ return;
134
+ }
135
+
136
+ // Create prismic.config.json
137
+ const configData: { repositoryName: string; libraries?: string[] } = {
138
+ repositoryName: repo,
139
+ };
140
+ if (legacyLibraries?.length) {
141
+ configData.libraries = legacyLibraries;
142
+ }
143
+
144
+ const configResult = await createConfig(configData);
145
+ if (!configResult.ok) {
146
+ if (configResult.error instanceof UnknownProjectRoot) {
147
+ console.error(
148
+ "Could not find a package.json file. Run this command from a project directory.",
149
+ );
150
+ } else {
151
+ console.error("Failed to create config file.");
152
+ }
153
+ process.exitCode = 1;
154
+ return;
155
+ }
156
+
157
+ // Delete legacy config after new config is created
158
+ if (legacyConfigPath) {
159
+ await rm(legacyConfigPath);
160
+ console.info("Migrated slicemachine.config.json to prismic.config.json");
161
+ }
162
+
163
+ // Install dependencies and create framework files
164
+ await framework.initProject();
165
+
166
+ // Sync models from remote
167
+ await syncSlices(repo, framework);
168
+ await syncCustomTypes(repo, framework);
169
+
170
+ console.info(
171
+ `Initialized Prismic for repository "${repo}". Run \`npm install\` to install new dependencies.`,
172
+ );
173
+ }