Skip to content

Commit 491a87e

Browse files
angeloashmoreclaude
andcommitted
feat: inject the active environment via prismic/env/register
Add the `prismic/env/register` export, which sets the framework's public environment variable from the active environment at config-load time, and wire `gen setup` to import it in the framework config for Next.js, Nuxt, and SvelteKit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent bacccda commit 491a87e

11 files changed

Lines changed: 117 additions & 7 deletions

File tree

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "prismic",
3-
"version": "1.12.2",
3+
"version": "1.12.0",
44
"description": "Prismic's official command line tool",
55
"keywords": [
66
"prismic",
@@ -19,6 +19,10 @@
1919
"./dist"
2020
],
2121
"type": "module",
22+
"exports": {
23+
"./env/register": "./dist/env/register.mjs",
24+
"./package.json": "./package.json"
25+
},
2226
"publishConfig": {
2327
"access": "public"
2428
},

src/adapters/index.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import type { CustomType, SharedSlice } from "@prismicio/types-internal/lib/customtypes";
22

33
import { pascalCase } from "change-case";
4-
import { rm } from "node:fs/promises";
4+
import { readFile, rm, writeFile } from "node:fs/promises";
55
import { pathToFileURL } from "node:url";
66
import { generateTypes } from "prismic-ts-codegen";
77
import { glob } from "tinyglobby";
88

9-
import { readJsonFile, writeFileRecursive } from "../lib/file";
9+
import { findFirstFile, readJsonFile, writeFileRecursive } from "../lib/file";
1010
import { stringify } from "../lib/json";
1111
import { readPackageJson } from "../lib/packageJson";
1212
import { appendTrailingSlash } from "../lib/url";
@@ -206,3 +206,25 @@ export abstract class Adapter {
206206
return output;
207207
}
208208
}
209+
210+
export async function addEnvRegisterImport(configFilenames: string[]): Promise<void> {
211+
const projectRoot = await findProjectRoot();
212+
const configUrl = await findFirstFile(
213+
configFilenames.map((filename) => new URL(filename, projectRoot)),
214+
);
215+
if (!configUrl) return;
216+
217+
// The register module uses top-level await, so it can only be
218+
// imported from an ESM config file.
219+
let isEsm = configUrl.pathname.endsWith(".mjs") || configUrl.pathname.endsWith(".ts");
220+
if (!isEsm) {
221+
const packageJson = await readPackageJson();
222+
isEsm = packageJson.type === "module";
223+
}
224+
if (!isEsm) return;
225+
226+
const statement = 'import "prismic/env/register";';
227+
const contents = await readFile(configUrl, "utf8");
228+
if (contents.includes(statement)) return;
229+
await writeFile(configUrl, `${statement}\n\n${contents}`);
230+
}

src/adapters/nextjs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createRequire } from "node:module";
55
import { relative } from "node:path";
66
import { fileURLToPath } from "node:url";
77

8-
import { Adapter } from ".";
8+
import { Adapter, addEnvRegisterImport } from ".";
99
import { getHost, getToken } from "../auth";
1010
import { addPreview, getPreviews, getSimulatorUrl, setSimulatorUrl } from "../clients/core";
1111
import { exists, writeFileRecursive } from "../lib/file";
@@ -38,6 +38,7 @@ export class NextJsAdapter extends Adapter {
3838
await createPreviewRoute();
3939
await createExitPreviewRoute();
4040
await createRevalidateRoute();
41+
await addEnvRegisterImport(["next.config.mjs", "next.config.ts", "next.config.js"]);
4142
}
4243

4344
async onProjectInitialized(): Promise<void> {

src/adapters/nuxt.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { readFile, rm } from "node:fs/promises";
66
import { relative } from "node:path";
77
import { fileURLToPath } from "node:url";
88

9-
import { Adapter } from ".";
9+
import { Adapter, addEnvRegisterImport } from ".";
1010
import { getHost, getToken } from "../auth";
1111
import { addPreview, getPreviews, getSimulatorUrl, setSimulatorUrl } from "../clients/core";
1212
import { exists, writeFileRecursive } from "../lib/file";
@@ -31,6 +31,7 @@ export class NuxtAdapter extends Adapter {
3131
await createSliceSimulatorPage();
3232
await moveOrDeleteAppVue();
3333
await modifySliceLibraryPath(this);
34+
await addEnvRegisterImport(["nuxt.config.ts", "nuxt.config.js"]);
3435
}
3536

3637
async onProjectInitialized(): Promise<void> {

src/adapters/sveltekit.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { createRequire } from "node:module";
77
import { relative } from "node:path";
88
import { fileURLToPath } from "node:url";
99

10-
import { Adapter } from ".";
10+
import { Adapter, addEnvRegisterImport } from ".";
1111
import { getHost, getToken } from "../auth";
1212
import { addPreview, getPreviews, getSimulatorUrl, setSimulatorUrl } from "../clients/core";
1313
import { exists, writeFileRecursive } from "../lib/file";
@@ -42,6 +42,7 @@ export class SvelteKitAdapter extends Adapter {
4242
await createRootLayoutServerFile();
4343
await createRootLayoutFile();
4444
await modifyViteConfig();
45+
await addEnvRegisterImport(["vite.config.ts", "vite.config.js"]);
4546
}
4647

4748
async onProjectInitialized(): Promise<void> {

src/exports/env/register.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { getEnvironment } from "../../environments";
2+
3+
const environment = await getEnvironment();
4+
if (environment) {
5+
process.env.NEXT_PUBLIC_PRISMIC_ENVIRONMENT ??= environment;
6+
process.env.PUBLIC_PRISMIC_ENVIRONMENT ??= environment;
7+
process.env.NUXT_PUBLIC_PRISMIC_ENVIRONMENT ??= environment;
8+
}

src/lib/file.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ export async function exists(path: URL): Promise<boolean> {
4949
}
5050
}
5151

52+
export async function findFirstFile(candidates: URL[]): Promise<URL | undefined> {
53+
for (const candidate of candidates) {
54+
if (await exists(candidate)) return candidate;
55+
}
56+
}
57+
5258
export async function writeFileRecursive(
5359
path: URL,
5460
data: Parameters<typeof writeFile>[1],

src/lib/packageJson.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const PackageJsonSchema = z.object({
1212
devDependencies: z.optional(z.record(z.string(), z.string())),
1313
peerDependencies: z.optional(z.record(z.string(), z.string())),
1414
packageManager: z.optional(z.string()),
15+
type: z.optional(z.string()),
1516
});
1617
type PackageJson = z.infer<typeof PackageJsonSchema>;
1718

test/env-register.serial.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { mkdir, writeFile } from "node:fs/promises";
2+
import { fileURLToPath } from "node:url";
3+
import { vi } from "vitest";
4+
5+
import { it } from "./it";
6+
7+
const REGISTER = fileURLToPath(new URL("../dist/env/register.mjs", import.meta.url));
8+
9+
const ENV_VARS = [
10+
"NEXT_PUBLIC_PRISMIC_ENVIRONMENT",
11+
"PUBLIC_PRISMIC_ENVIRONMENT",
12+
"NUXT_PUBLIC_PRISMIC_ENVIRONMENT",
13+
] as const;
14+
15+
it("does not set env vars when no environment is configured", async ({ expect, home, project }) => {
16+
process.chdir(fileURLToPath(project));
17+
vi.stubEnv("PRISMIC_CONFIG_DIR", fileURLToPath(new URL(".config/prismic/", home)));
18+
vi.resetModules();
19+
await import(REGISTER);
20+
for (const key of ENV_VARS) expect(process.env[key]).toBeUndefined();
21+
});
22+
23+
it("sets env vars when an environment is configured", async ({ expect, home, project }) => {
24+
process.chdir(fileURLToPath(project));
25+
vi.stubEnv("PRISMIC_CONFIG_DIR", fileURLToPath(new URL(".config/prismic/", home)));
26+
await mkdir(new URL(".config/prismic/", home), { recursive: true });
27+
await writeFile(
28+
new URL(".config/prismic/environments.json", home),
29+
JSON.stringify({ [project.toString()]: "my-stage-env" }),
30+
);
31+
vi.resetModules();
32+
await import(REGISTER);
33+
for (const key of ENV_VARS) expect(process.env[key]).toBe("my-stage-env");
34+
});

test/gen-setup.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { mkdir, writeFile } from "node:fs/promises";
1+
import { mkdir, readFile, writeFile } from "node:fs/promises";
22

33
import { it } from "./it";
44

@@ -61,6 +61,37 @@ it("generates valid script tags for SvelteKit", { timeout: 30_000 }, async ({
6161
});
6262
});
6363

64+
it("adds the env register import to the framework config", { timeout: 30_000 }, async ({
65+
expect,
66+
project,
67+
prismic,
68+
}) => {
69+
const configPath = new URL("next.config.mjs", project);
70+
await writeFile(configPath, "export default {};\n");
71+
72+
const { exitCode } = await prismic("gen", ["setup", "--no-install"]);
73+
expect(exitCode).toBe(0);
74+
75+
const contents = await readFile(configPath, "utf8");
76+
expect(contents).toBe('import "prismic/env/register";\n\nexport default {};\n');
77+
});
78+
79+
it("skips the env register import for a CommonJS config", { timeout: 30_000 }, async ({
80+
expect,
81+
project,
82+
prismic,
83+
}) => {
84+
// The fixture's package.json has no "type": "module", so a .js config is CommonJS.
85+
const configPath = new URL("next.config.js", project);
86+
await writeFile(configPath, "module.exports = {};\n");
87+
88+
const { exitCode } = await prismic("gen", ["setup", "--no-install"]);
89+
expect(exitCode).toBe(0);
90+
91+
const contents = await readFile(configPath, "utf8");
92+
expect(contents).toBe("module.exports = {};\n");
93+
});
94+
6495
it("skips installation with --no-install", async ({ expect, project, prismic }) => {
6596
const { exitCode, stdout } = await prismic("gen", ["setup", "--no-install"]);
6697
expect(exitCode).toBe(0);

0 commit comments

Comments
 (0)