@prismicio/cli 0.0.1

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 (84) hide show
  1. package/bin/prismic.js +47 -0
  2. package/dist/_node_modules/meow/build/dependencies.js +9040 -0
  3. package/dist/_node_modules/meow/build/dependencies.js.map +1 -0
  4. package/dist/_node_modules/meow/build/index.js +80 -0
  5. package/dist/_node_modules/meow/build/index.js.map +1 -0
  6. package/dist/_node_modules/meow/build/options.js +86 -0
  7. package/dist/_node_modules/meow/build/options.js.map +1 -0
  8. package/dist/_node_modules/meow/build/parser.js +61 -0
  9. package/dist/_node_modules/meow/build/parser.js.map +1 -0
  10. package/dist/_node_modules/meow/build/utils.js +8 -0
  11. package/dist/_node_modules/meow/build/utils.js.map +1 -0
  12. package/dist/_node_modules/meow/build/validate.js +102 -0
  13. package/dist/_node_modules/meow/build/validate.js.map +1 -0
  14. package/dist/cli.d.ts +12 -0
  15. package/dist/cli.js +147 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/commands/init.d.ts +7 -0
  18. package/dist/commands/init.js +34 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/sync.d.ts +6 -0
  21. package/dist/commands/sync.js +32 -0
  22. package/dist/commands/sync.js.map +1 -0
  23. package/dist/core/auth.d.ts +2 -0
  24. package/dist/core/auth.js +72 -0
  25. package/dist/core/auth.js.map +1 -0
  26. package/dist/core/customType.d.ts +6 -0
  27. package/dist/core/customType.js +43 -0
  28. package/dist/core/customType.js.map +1 -0
  29. package/dist/core/framework.d.ts +41 -0
  30. package/dist/core/framework.js +128 -0
  31. package/dist/core/framework.js.map +1 -0
  32. package/dist/core/project.d.ts +19 -0
  33. package/dist/core/project.js +92 -0
  34. package/dist/core/project.js.map +1 -0
  35. package/dist/core/repository.d.ts +6 -0
  36. package/dist/core/repository.js +33 -0
  37. package/dist/core/repository.js.map +1 -0
  38. package/dist/core/slices.d.ts +6 -0
  39. package/dist/core/slices.js +47 -0
  40. package/dist/core/slices.js.map +1 -0
  41. package/dist/core/version.d.ts +15 -0
  42. package/dist/core/version.js +27 -0
  43. package/dist/core/version.js.map +1 -0
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +5 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/packages/cli/package.json.js +63 -0
  48. package/dist/packages/cli/package.json.js.map +1 -0
  49. package/dist/utils/error.d.ts +8 -0
  50. package/dist/utils/error.js +18 -0
  51. package/dist/utils/error.js.map +1 -0
  52. package/dist/utils/listr.d.ts +5 -0
  53. package/dist/utils/listr.js +12 -0
  54. package/dist/utils/listr.js.map +1 -0
  55. package/dist/utils/output.d.ts +3 -0
  56. package/dist/utils/output.js +34 -0
  57. package/dist/utils/output.js.map +1 -0
  58. package/dist/utils/package.d.ts +10 -0
  59. package/dist/utils/package.js +20 -0
  60. package/dist/utils/package.js.map +1 -0
  61. package/dist/utils/sentry.d.ts +10 -0
  62. package/dist/utils/sentry.js +62 -0
  63. package/dist/utils/sentry.js.map +1 -0
  64. package/dist/utils/telemetry.d.ts +14 -0
  65. package/dist/utils/telemetry.js +42 -0
  66. package/dist/utils/telemetry.js.map +1 -0
  67. package/package.json +84 -0
  68. package/src/cli.ts +186 -0
  69. package/src/commands/init.ts +68 -0
  70. package/src/commands/sync.ts +58 -0
  71. package/src/core/auth.ts +98 -0
  72. package/src/core/customType.ts +64 -0
  73. package/src/core/framework.ts +180 -0
  74. package/src/core/project.ts +148 -0
  75. package/src/core/repository.ts +51 -0
  76. package/src/core/slices.ts +67 -0
  77. package/src/core/version.ts +50 -0
  78. package/src/index.ts +1 -0
  79. package/src/utils/error.ts +40 -0
  80. package/src/utils/listr.ts +13 -0
  81. package/src/utils/output.ts +45 -0
  82. package/src/utils/package.ts +29 -0
  83. package/src/utils/sentry.ts +104 -0
  84. package/src/utils/telemetry.ts +70 -0
package/src/cli.ts ADDED
@@ -0,0 +1,186 @@
1
+ import { createPrismicManager } from "@prismicio/manager";
2
+ import meow from "meow";
3
+ import * as z from "zod";
4
+
5
+ import { name as pkgName, version as pkgVersion } from "../package.json";
6
+
7
+ import { init } from "./commands/init";
8
+ import { sync } from "./commands/sync";
9
+ import { FRAMEWORK_PLUGINS } from "./core/framework";
10
+ import { handleSilentError } from "./utils/error";
11
+ import { displayError, displayHeader } from "./utils/output";
12
+ import { setupSentry, trackSentryError } from "./utils/sentry";
13
+ import { initTelemetry, trackErrorTelemetry } from "./utils/telemetry";
14
+
15
+ const cli = meow(
16
+ `
17
+ DOCUMENTATION
18
+ https://prismic.io/docs
19
+
20
+ VERSION
21
+ ${pkgName}@${pkgVersion}
22
+
23
+ USAGE
24
+ $ npx prismic@latest init --repository <repository-id>
25
+ $ npx prismic@latest sync
26
+
27
+ OPTIONS
28
+ --repository, -r Specify a Prismic repository to use when initializing a project
29
+
30
+ --help, -h Display CLI help
31
+ --version, -v Display CLI version
32
+ `,
33
+ {
34
+ importMeta: import.meta,
35
+ flags: {
36
+ repository: {
37
+ type: "string",
38
+ shortFlag: "r",
39
+ },
40
+ help: {
41
+ type: "boolean",
42
+ shortFlag: "h",
43
+ default: false,
44
+ },
45
+ version: {
46
+ type: "boolean",
47
+ shortFlag: "v",
48
+ default: false,
49
+ },
50
+ },
51
+ description: false,
52
+ autoHelp: false,
53
+ autoVersion: false,
54
+ allowUnknownFlags: false,
55
+ },
56
+ );
57
+
58
+ export const CLIArgs = z.discriminatedUnion("commandType", [
59
+ z.object({
60
+ commandType: z.literal("init"),
61
+ help: z.boolean().optional(),
62
+ version: z.boolean().optional(),
63
+ repository: z
64
+ .string()
65
+ .min(1, "Repository name is required to initialize a project"),
66
+ }),
67
+ z.object({
68
+ commandType: z.literal("sync"),
69
+ help: z.boolean().optional(),
70
+ version: z.boolean().optional(),
71
+ }),
72
+ ]);
73
+
74
+ export async function run(): Promise<void> {
75
+ // Display header immediately so user sees something is happening
76
+ displayHeader();
77
+
78
+ // Setup Sentry as early as possible to track ALL errors
79
+ setupSentry();
80
+
81
+ // Handle help flag (exit early, no telemetry needed)
82
+ if (cli.flags.help) {
83
+ cli.showHelp(0);
84
+ process.exit(0);
85
+ }
86
+
87
+ // Handle version flag (exit early, no telemetry needed)
88
+ if (cli.flags.version) {
89
+ console.info(`${pkgName}@${pkgVersion}`);
90
+ process.exit(0);
91
+ }
92
+
93
+ // Validate CLI arguments first (before any operations that might fail)
94
+ const cliArgs = CLIArgs.safeParse({
95
+ ...cli.flags,
96
+ commandType: cli.input[0],
97
+ });
98
+
99
+ // Invalid arguments - track with Sentry even though it's a user error
100
+ if (!cliArgs.success) {
101
+ const error = new Error(cliArgs.error.message);
102
+ displayError(error);
103
+ await trackSentryError(error);
104
+ process.exit(1);
105
+ }
106
+
107
+ // Too many arguments - track with Sentry
108
+ if (cli.input.length > 1) {
109
+ const error = new Error("Too many arguments. Expected 'init' or 'sync'.");
110
+ displayError(error);
111
+ await trackSentryError(error);
112
+ process.exit(1);
113
+ }
114
+
115
+ // Create manager - wrap in try-catch to track failures
116
+ let manager;
117
+ try {
118
+ manager = createPrismicManager({
119
+ cwd: process.cwd(),
120
+ nativePlugins: FRAMEWORK_PLUGINS,
121
+ });
122
+ } catch (error) {
123
+ // Manager creation failed - track with Sentry (telemetry not available yet)
124
+ displayError(error);
125
+ await trackSentryError(error);
126
+ process.exit(1);
127
+ }
128
+
129
+ const commandType = cliArgs.data.commandType;
130
+ const repositoryName =
131
+ commandType === "init" ? cliArgs.data.repository : undefined;
132
+
133
+ // Initialize telemetry as early as possible (after manager creation)
134
+ // Track initialization failures with Sentry
135
+ try {
136
+ await initTelemetry({
137
+ manager,
138
+ commandType,
139
+ repositoryName,
140
+ });
141
+ } catch (telemetryError) {
142
+ // Telemetry initialization failed - track with Sentry but continue execution
143
+ // This prevents telemetry issues from breaking the CLI
144
+ await trackSentryError(telemetryError);
145
+ handleSilentError(telemetryError, "Telemetry initialization error");
146
+ }
147
+
148
+ // Execute command - all errors here will be tracked
149
+ try {
150
+ if (commandType === "init") {
151
+ await init({
152
+ manager,
153
+ repositoryName: cliArgs.data.repository,
154
+ });
155
+ process.exit(0);
156
+ }
157
+
158
+ if (commandType === "sync") {
159
+ await sync({ manager });
160
+ process.exit(0);
161
+ }
162
+
163
+ throw new Error("Unknown command type.");
164
+ } catch (error) {
165
+ displayError(error);
166
+
167
+ // Always track with Sentry first (most reliable)
168
+ await trackSentryError(error);
169
+
170
+ // Try to track with telemetry if it was initialized
171
+ // If telemetry wasn't initialized or tracking fails, Sentry already has it
172
+ try {
173
+ await trackErrorTelemetry({
174
+ manager,
175
+ error,
176
+ commandType,
177
+ });
178
+ } catch (telemetryError) {
179
+ handleSilentError(telemetryError, "Telemetry tracking error");
180
+ }
181
+
182
+ process.exit(1);
183
+ }
184
+ }
185
+
186
+ void run();
@@ -0,0 +1,68 @@
1
+ import type { PrismicManager } from "@prismicio/manager";
2
+
3
+ import { version as pkgVersion } from "../../package.json";
4
+ import { login } from "../core/auth";
5
+ import { saveCustomTypes } from "../core/customType";
6
+ import { initFramework } from "../core/framework";
7
+ import {
8
+ createPrismicConfig,
9
+ detectProjectContext,
10
+ detectProjectState,
11
+ } from "../core/project";
12
+ import { validateRepository } from "../core/repository";
13
+ import { saveSlices } from "../core/slices";
14
+ import { checkCLIVersion } from "../core/version";
15
+ import { displaySuccess } from "../utils/output";
16
+
17
+ type InitArgs = {
18
+ manager: PrismicManager;
19
+ repositoryName: string;
20
+ };
21
+
22
+ export async function init(args: InitArgs): Promise<void> {
23
+ const { manager, repositoryName } = args;
24
+
25
+ // Authentication - Also updates Sentry context
26
+ await login(manager);
27
+
28
+ // Ensure the project is not already initialized
29
+ await detectProjectState({ manager, commandType: "init" });
30
+
31
+ // Ensure the repository exists and the user has write access
32
+ await validateRepository({ manager, repository: repositoryName });
33
+
34
+ // Get project framework and package manager - Also updates Sentry context
35
+ const projectContext = await detectProjectContext(manager);
36
+
37
+ // Check CLI version - Voluntarily late so Sentry context is updated
38
+ await checkCLIVersion({ manager, currentVersion: pkgVersion });
39
+
40
+ // Create Prismic configuration file
41
+ await createPrismicConfig({ manager, projectContext, repositoryName });
42
+
43
+ // Initialize the plugin system
44
+ await manager.plugins.initPlugins();
45
+
46
+ // Initialize the framework specific dependencies and files
47
+ await initFramework({ manager, projectContext });
48
+
49
+ // Save Prismic slices locally
50
+ await saveSlices({ manager });
51
+
52
+ // Save Prismic custom types locally
53
+ await saveCustomTypes({ manager });
54
+
55
+ // Track the end of the init command
56
+ await manager.telemetry.track({
57
+ event: "prismic-cli:end",
58
+ commandType: "init",
59
+ repository: repositoryName,
60
+ fullCommand: process.argv.join(" "),
61
+ success: true,
62
+ });
63
+
64
+ displaySuccess(
65
+ "Project initialized successfully!",
66
+ "You're all set to start building with Prismic.",
67
+ );
68
+ }
@@ -0,0 +1,58 @@
1
+ import type { PrismicManager } from "@prismicio/manager";
2
+
3
+ import { version as pkgVersion } from "../../package.json";
4
+ import { login } from "../core/auth";
5
+ import { saveCustomTypes } from "../core/customType";
6
+ import { detectProjectContext, detectProjectState } from "../core/project";
7
+ import { validateRepository } from "../core/repository";
8
+ import { saveSlices } from "../core/slices";
9
+ import { checkCLIVersion } from "../core/version";
10
+ import { displaySuccess } from "../utils/output";
11
+
12
+ type SyncArgs = {
13
+ manager: PrismicManager;
14
+ };
15
+
16
+ export async function sync(args: SyncArgs): Promise<void> {
17
+ const { manager } = args;
18
+
19
+ // Authentication - Also updates Sentry context
20
+ await login(manager);
21
+
22
+ // Ensure the project is already initialized
23
+ await detectProjectState({ manager, commandType: "sync" });
24
+
25
+ // Get repository from Prismic config file
26
+ const repositoryName = await manager.project.getRepositoryName();
27
+
28
+ // Ensure the repository exists and the user has write access
29
+ await validateRepository({ manager, repository: repositoryName });
30
+
31
+ // Ensure validity of the framework and package manager - Also updates Sentry context
32
+ await detectProjectContext(manager);
33
+
34
+ // Check CLI version - Voluntarily late so Sentry context is updated
35
+ await checkCLIVersion({ manager, currentVersion: pkgVersion });
36
+
37
+ // Initialize the plugin system
38
+ await manager.plugins.initPlugins();
39
+
40
+ // Save Prismic slices locally
41
+ await saveSlices({ manager });
42
+
43
+ // Save Prismic custom types locally
44
+ await saveCustomTypes({ manager });
45
+
46
+ await manager.telemetry.track({
47
+ event: "prismic-cli:end",
48
+ commandType: "sync",
49
+ repository: repositoryName,
50
+ fullCommand: process.argv.join(" "),
51
+ success: true,
52
+ });
53
+
54
+ displaySuccess(
55
+ "Sync completed successfully!",
56
+ "Your local types are up to date.",
57
+ );
58
+ }
@@ -0,0 +1,98 @@
1
+ import type { PrismicManager } from "@prismicio/manager";
2
+ import chalk from "chalk";
3
+ import open from "open";
4
+
5
+ import { listr, listrRun } from "../utils/listr";
6
+ import { updateSentryContext } from "../utils/sentry";
7
+
8
+ export async function login(manager: PrismicManager): Promise<void> {
9
+ return listrRun([
10
+ {
11
+ title: "Logging in to Prismic...",
12
+ task: async (_, parentTask) => {
13
+ const isLoggedIn = await manager.user.checkIsLoggedIn();
14
+
15
+ if (!isLoggedIn) {
16
+ parentTask.title = getLoggingInTitle(
17
+ chalk.cyan("Press any key to open the browser to login..."),
18
+ );
19
+ await pressKeyToLogin();
20
+ await waitingForLogin(manager, ({ url }) => {
21
+ parentTask.title = getLoggingInTitle(
22
+ chalk.cyan("Opening browser, waiting for you to login..."),
23
+ chalk.yellow(
24
+ "If your browser did not open automatically, please use the url below:",
25
+ ),
26
+ url,
27
+ );
28
+ });
29
+ }
30
+
31
+ parentTask.title = `Logged in`;
32
+
33
+ return listr(
34
+ [
35
+ {
36
+ title: "Fetching user profile...",
37
+ task: async (_, task) => {
38
+ const userProfile = await manager.user.getProfile();
39
+
40
+ // Identify the user for Amplitude
41
+ await manager.telemetry.identify(userProfile);
42
+
43
+ // Update Sentry context for the current user
44
+ updateSentryContext({ userProfile });
45
+
46
+ parentTask.title = `Logged in as ${chalk.cyan(
47
+ userProfile?.email,
48
+ )}`;
49
+ task.title = "Fetched user profile";
50
+ },
51
+ },
52
+ ],
53
+ { concurrent: true },
54
+ );
55
+ },
56
+ },
57
+ ]);
58
+ }
59
+
60
+ function getLoggingInTitle(subtitle?: string, ...extra: string[]): string {
61
+ return `Logging in to Prismic...
62
+
63
+ ███████████████████████████████████████████████████████████████████████████
64
+
65
+ ${subtitle ? `* * ${subtitle}` : ""}
66
+ ${extra.length ? `\n${extra.map((line) => ` ${line}`).join("\n")}\n` : ""}
67
+ ███████████████████████████████████████████████████████████████████████████
68
+ `;
69
+ }
70
+
71
+ async function pressKeyToLogin(): Promise<void> {
72
+ await new Promise((resolve) => {
73
+ const initialRawMode = !!process.stdin.isRaw;
74
+ process.stdin.setRawMode?.(true);
75
+ process.stdin.resume();
76
+ process.stdin.once("data", (data: Buffer) => {
77
+ process.stdin.setRawMode?.(initialRawMode);
78
+ process.stdin.pause();
79
+ resolve(data.toString("utf-8"));
80
+ });
81
+ });
82
+ }
83
+
84
+ async function waitingForLogin(
85
+ manager: PrismicManager,
86
+ onListenCallback?: (
87
+ sessionInfo: Awaited<ReturnType<typeof manager.user.getLoginSessionInfo>>,
88
+ ) => void,
89
+ ): Promise<void> {
90
+ const sessionInfo = await manager.user.getLoginSessionInfo();
91
+ await manager.user.nodeLoginSession({
92
+ port: sessionInfo.port,
93
+ onListenCallback() {
94
+ open(sessionInfo.url);
95
+ onListenCallback?.(sessionInfo);
96
+ },
97
+ });
98
+ }
@@ -0,0 +1,64 @@
1
+ import type { PrismicManager } from "@prismicio/manager";
2
+
3
+ import { listrRun } from "../utils/listr";
4
+
5
+ type SaveCustomTypesArgs = {
6
+ manager: PrismicManager;
7
+ };
8
+
9
+ export async function saveCustomTypes(
10
+ args: SaveCustomTypesArgs,
11
+ ): Promise<void> {
12
+ const { manager } = args;
13
+
14
+ await listrRun([
15
+ {
16
+ title: "Fetching Prismic custom types...",
17
+ task: async (_, parentTask) => {
18
+ const customTypes = await manager.customTypes.fetchRemoteCustomTypes();
19
+
20
+ parentTask.title = "Saving Prismic custom types changes...";
21
+
22
+ const localCustomTypes = await manager.customTypes.readAllCustomTypes();
23
+
24
+ // Handle custom types update
25
+ for (const remoteCustomType of customTypes) {
26
+ const existsLocally = localCustomTypes.models.some(
27
+ (local) => local.model.id === remoteCustomType.id,
28
+ );
29
+ if (existsLocally) {
30
+ await manager.customTypes.updateCustomType({
31
+ model: remoteCustomType,
32
+ });
33
+ }
34
+ }
35
+
36
+ // Handle custom types deletion
37
+ for (const localCustomType of localCustomTypes.models) {
38
+ const existsRemotely = customTypes.some(
39
+ (remote) => remote.id === localCustomType.model.id,
40
+ );
41
+ if (!existsRemotely) {
42
+ await manager.customTypes.deleteCustomType({
43
+ id: localCustomType.model.id,
44
+ });
45
+ }
46
+ }
47
+
48
+ // Handle custom types creation
49
+ for (const remoteCustomType of customTypes) {
50
+ const existsLocally = localCustomTypes.models.some(
51
+ (local) => local.model.id === remoteCustomType.id,
52
+ );
53
+ if (!existsLocally) {
54
+ await manager.customTypes.createCustomType({
55
+ model: remoteCustomType,
56
+ });
57
+ }
58
+ }
59
+
60
+ parentTask.title = "Prismic custom types changes saved";
61
+ },
62
+ },
63
+ ]);
64
+ }
@@ -0,0 +1,180 @@
1
+ import { readFile, readdir, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+
4
+ import adapterNextPlugin from "@prismicio/adapter-next";
5
+ import adapterNuxtPlugin from "@prismicio/adapter-nuxt";
6
+ import adapterNuxt2Plugin from "@prismicio/adapter-nuxt2";
7
+ import adapterSveltekitPlugin from "@prismicio/adapter-sveltekit";
8
+ import { type PrismicManager } from "@prismicio/manager";
9
+ import semver from "semver";
10
+
11
+ import { listrRun } from "../utils/listr";
12
+
13
+ import { type ProjectContext } from "./project";
14
+
15
+ export type Framework = {
16
+ /**
17
+ * Framework's human readable name.
18
+ */
19
+ name: string;
20
+
21
+ /**
22
+ * Framework 's id sent to Segment from Slice Machine
23
+ */
24
+ telemetryID: "next" | "nuxt-2" | "nuxt" | "sveltekit-1" | "sveltekit-2";
25
+
26
+ /**
27
+ * Package name of the adapter responsible for this framework
28
+ */
29
+ adapterName: string;
30
+
31
+ /**
32
+ * A package name/semver range map defining framework compatibility
33
+ * requirements.
34
+ *
35
+ * Project should match all entries to be considered compatible.
36
+ */
37
+ compatibility: Record<string, string>;
38
+ };
39
+
40
+ /**
41
+ * Frameworks we support, orders shouldn't matter much but is respected (the
42
+ * higher it is the more priority it has in case multiple matches)
43
+ */
44
+ export const FRAMEWORKS: Record<string, Framework> = {
45
+ "nuxt-2": {
46
+ name: "Nuxt 2",
47
+ telemetryID: "nuxt-2",
48
+ adapterName: "@prismicio/adapter-nuxt2",
49
+ compatibility: {
50
+ nuxt: "^2.0.0",
51
+ },
52
+ },
53
+ nuxt: {
54
+ name: "Nuxt",
55
+ telemetryID: "nuxt",
56
+ adapterName: "@prismicio/adapter-nuxt",
57
+ compatibility: {
58
+ nuxt: "^3.0.0 || ^4.0.0",
59
+ },
60
+ },
61
+ next: {
62
+ name: "Next.js",
63
+ telemetryID: "next",
64
+ adapterName: "@prismicio/adapter-next",
65
+ compatibility: {
66
+ next: "^11 || ^12 || ^13 || ^14 || ^15 || ^16.0.0-beta.0",
67
+ },
68
+ },
69
+ "sveltekit-1": {
70
+ name: "SvelteKit",
71
+ telemetryID: "sveltekit-1",
72
+ adapterName: "@prismicio/adapter-sveltekit",
73
+ compatibility: {
74
+ "@sveltejs/kit": "^1.0.0",
75
+ },
76
+ },
77
+ "sveltekit-2": {
78
+ name: "SvelteKit",
79
+ telemetryID: "sveltekit-2",
80
+ adapterName: "@prismicio/adapter-sveltekit",
81
+ compatibility: {
82
+ "@sveltejs/kit": "^2.0.0",
83
+ },
84
+ },
85
+ } as const;
86
+
87
+ export const detectFramework = async (cwd: string): Promise<Framework> => {
88
+ const path = join(cwd, "package.json");
89
+
90
+ let allDependencies: Record<string, string>;
91
+ try {
92
+ const pkg = JSON.parse(await readFile(path, "utf-8"));
93
+
94
+ allDependencies = {
95
+ ...pkg.dependencies,
96
+ ...pkg.devDependencies,
97
+ };
98
+ } catch (error) {
99
+ throw new Error(
100
+ `Failed to read project's \`package.json\` at \`${path}\``,
101
+ { cause: error },
102
+ );
103
+ }
104
+
105
+ const framework = Object.values(FRAMEWORKS).find((framework) => {
106
+ return Object.entries(framework.compatibility).every(([pkg, range]) => {
107
+ if (pkg in allDependencies) {
108
+ try {
109
+ // Determine lowest version possibly in use
110
+ const minimumVersion = semver.minVersion(allDependencies[pkg]);
111
+
112
+ return semver.satisfies(minimumVersion!, range);
113
+ } catch {
114
+ // We assume unconventional tags, `latest`, `beta`, `dev` matches the framework
115
+ return true;
116
+ }
117
+ }
118
+
119
+ return false;
120
+ });
121
+ });
122
+
123
+ if (!framework) {
124
+ throw new Error("No framework compatible with Prismic was found.");
125
+ }
126
+
127
+ return framework;
128
+ };
129
+
130
+ type InitFrameworkArgs = {
131
+ manager: PrismicManager;
132
+ projectContext: ProjectContext;
133
+ };
134
+
135
+ export async function initFramework(args: InitFrameworkArgs): Promise<void> {
136
+ const { manager, projectContext } = args;
137
+ const { framework } = projectContext;
138
+
139
+ await listrRun([
140
+ {
141
+ title: `Initializing project for ${framework.name}...`,
142
+ task: async (_, parentTask) => {
143
+ const updateOutput = (data: Buffer | string | null) => {
144
+ if (data instanceof Buffer) {
145
+ parentTask.output = data.toString();
146
+ } else if (typeof data === "string") {
147
+ parentTask.output = data;
148
+ }
149
+ };
150
+ await manager.project.initProject({
151
+ log: updateOutput,
152
+ });
153
+
154
+ // TODO: Export simulator management out of adapter and remove this code
155
+ const projectRoot = await manager.project.getRoot();
156
+ const entries = await readdir(projectRoot, {
157
+ recursive: true,
158
+ withFileTypes: true,
159
+ });
160
+ for (const entry of entries) {
161
+ if (entry.isDirectory() && entry.name === "slice-simulator") {
162
+ await rm(join(entry.path, entry.name), {
163
+ recursive: true,
164
+ force: true,
165
+ });
166
+ }
167
+ }
168
+
169
+ parentTask.title = `Updated project for ${framework.name}`;
170
+ },
171
+ },
172
+ ]);
173
+ }
174
+
175
+ export const FRAMEWORK_PLUGINS = {
176
+ "@prismicio/adapter-next": adapterNextPlugin,
177
+ "@prismicio/adapter-nuxt": adapterNuxtPlugin,
178
+ "@prismicio/adapter-nuxt2": adapterNuxt2Plugin,
179
+ "@prismicio/adapter-sveltekit": adapterSveltekitPlugin,
180
+ };