@runtime-env/vite-plugin 0.0.0 → 0.1.0

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/dist/build.js CHANGED
@@ -1,11 +1,26 @@
1
- import { isTypeScriptProject, runRuntimeEnvCommand } from "./utils.js";
1
+ import { isTypeScriptProject, runRuntimeEnvCommand, logError, hasRuntimeEnvScript, } from "./utils.js";
2
2
  export function buildPlugin() {
3
+ let config;
3
4
  return {
4
5
  name: "runtime-env-build",
5
- config(config, configEnv) {
6
- if (configEnv.command === "build") {
7
- if (isTypeScriptProject(config.root || process.cwd())) {
8
- runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
6
+ configResolved(resolvedConfig) {
7
+ config = resolvedConfig;
8
+ if (config.command === "build") {
9
+ if (isTypeScriptProject(config.root)) {
10
+ const result = runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
11
+ if (!result.success) {
12
+ logError(config.logger, "Failed to generate runtime-env.d.ts", result.stderr || result.stdout);
13
+ process.exit(1);
14
+ }
15
+ }
16
+ }
17
+ },
18
+ transformIndexHtml(html) {
19
+ if (config && config.command === "build") {
20
+ if (!hasRuntimeEnvScript(html, config.base)) {
21
+ logError(config.logger, `index.html is missing <script src="${config.base === "/" ? "" : config.base}/runtime-env.js"></script>. ` +
22
+ "This script tag is mandatory for @runtime-env/vite-plugin to function correctly in production.");
23
+ process.exit(1);
9
24
  }
10
25
  }
11
26
  },
package/dist/dev.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { resolve } from "path";
2
2
  import { writeFileSync, readFileSync, rmSync, existsSync } from "fs";
3
- import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, } from "./utils.js";
3
+ import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, clearLastError, hasRuntimeEnvScript, } from "./utils.js";
4
4
  const schemaFile = ".runtimeenvschema.json";
5
5
  export function devPlugin() {
6
6
  return {
@@ -10,13 +10,29 @@ export function devPlugin() {
10
10
  return;
11
11
  const envDir = server.config.envDir || server.config.root;
12
12
  const envFiles = getViteEnvFiles(server.config.mode, envDir);
13
- const watchFiles = [schemaFile, ...envFiles];
13
+ const watchFiles = [resolve(server.config.root, schemaFile), ...envFiles];
14
+ let hadError = false;
14
15
  function run() {
15
16
  const devOutputDir = getTempDir("dev");
16
17
  const devOutputPath = resolve(devOutputDir, "runtime-env.js");
17
- runRuntimeEnvCommand("gen-js", devOutputPath, envFiles);
18
+ const jsResult = runRuntimeEnvCommand("gen-js", devOutputPath, envFiles);
19
+ if (!jsResult.success) {
20
+ logError(server.config.logger, "Failed to generate runtime-env.js", jsResult.stderr || jsResult.stdout, server);
21
+ hadError = true;
22
+ return;
23
+ }
18
24
  if (isTypeScriptProject(server.config.root)) {
19
- runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
25
+ const tsResult = runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
26
+ if (!tsResult.success) {
27
+ logError(server.config.logger, "Failed to generate runtime-env.d.ts", tsResult.stderr || tsResult.stdout, server);
28
+ hadError = true;
29
+ return;
30
+ }
31
+ }
32
+ if (hadError) {
33
+ clearLastError();
34
+ server.ws.send({ type: "full-reload" });
35
+ hadError = false;
20
36
  }
21
37
  }
22
38
  run();
@@ -46,11 +62,19 @@ export function devPlugin() {
46
62
  if (ctx.server && ctx.server.config.command === "serve") {
47
63
  const envDir = ctx.server.config.envDir || ctx.server.config.root;
48
64
  const envFiles = getViteEnvFiles(ctx.server.config.mode, envDir);
65
+ if (!hasRuntimeEnvScript(html, ctx.server.config.base)) {
66
+ logError(ctx.server.config.logger, `index.html is missing <script src="${ctx.server.config.base === "/" ? "" : ctx.server.config.base}/runtime-env.js"></script>. ` +
67
+ "Runtime values will not be available. Please add the script tag.", undefined, ctx.server);
68
+ }
49
69
  const tmpDir = getTempDir("dev-interpolate");
50
70
  try {
51
71
  const htmlFile = resolve(tmpDir, "index.html");
52
72
  writeFileSync(htmlFile, html, "utf8");
53
- runRuntimeEnvCommand("interpolate", htmlFile, envFiles, htmlFile);
73
+ const result = runRuntimeEnvCommand("interpolate", htmlFile, envFiles, htmlFile);
74
+ if (!result.success) {
75
+ logError(ctx.server.config.logger, "Failed to interpolate index.html", result.stderr || result.stdout, ctx.server);
76
+ return html;
77
+ }
54
78
  html = readFileSync(htmlFile, "utf8");
55
79
  return html;
56
80
  }
package/dist/preview.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { resolve } from "path";
2
2
  import { readFileSync, writeFileSync, existsSync, rmSync } from "fs";
3
- import { runRuntimeEnvCommand, getTempDir, getViteEnvFiles } from "./utils.js";
3
+ import { runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, } from "./utils.js";
4
4
  export function previewPlugin() {
5
5
  return {
6
6
  name: "runtime-env-preview",
@@ -24,7 +24,12 @@ export function previewPlugin() {
24
24
  const tmpDir = getTempDir("preview-gen-js");
25
25
  const tmpPath = resolve(tmpDir, "runtime-env.js");
26
26
  try {
27
- runRuntimeEnvCommand("gen-js", tmpPath, envFiles);
27
+ const result = runRuntimeEnvCommand("gen-js", tmpPath, envFiles);
28
+ if (!result.success) {
29
+ logError(server.config.logger, "Failed to generate runtime-env.js", result.stderr || result.stdout);
30
+ next();
31
+ return;
32
+ }
28
33
  if (existsSync(tmpPath)) {
29
34
  const content = readFileSync(tmpPath, "utf8");
30
35
  res.setHeader("Content-Type", "application/javascript");
@@ -46,7 +51,13 @@ export function previewPlugin() {
46
51
  const tmpHtmlPath = resolve(tmpDir, "index.html");
47
52
  const originalHtml = readFileSync(distIndexHtml, "utf8");
48
53
  writeFileSync(tmpHtmlPath, originalHtml, "utf8");
49
- runRuntimeEnvCommand("interpolate", tmpHtmlPath, envFiles, tmpHtmlPath);
54
+ const result = runRuntimeEnvCommand("interpolate", tmpHtmlPath, envFiles, tmpHtmlPath);
55
+ if (!result.success) {
56
+ logError(server.config.logger, "Failed to interpolate index.html", result.stderr || result.stdout);
57
+ res.setHeader("Content-Type", "text/html");
58
+ res.end(originalHtml);
59
+ return;
60
+ }
50
61
  const interpolatedHtml = readFileSync(tmpHtmlPath, "utf8");
51
62
  res.setHeader("Content-Type", "text/html");
52
63
  res.end(interpolatedHtml);
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,17 @@
1
+ import type { Logger, ViteDevServer } from "vite";
2
+ /**
3
+ * Clears the last error message to allow it to be logged again.
4
+ * This should be called when the plugin recovers from an error state.
5
+ */
6
+ export declare function clearLastError(): void;
7
+ export declare function logError(logger: Logger | undefined, message: string, error?: any, server?: ViteDevServer): void;
1
8
  export declare function isTypeScriptProject(root: string): boolean;
2
9
  export declare function getViteEnvFiles(mode: string, envDir: string): string[];
3
10
  export declare function getRuntimeEnvCommandLineArgs(command: string, outputFile: string, envFiles?: string[], inputFile?: string): string[];
4
- export declare function runRuntimeEnvCommand(command: string, outputFile: string, envFiles?: string[], inputFile?: string): void;
11
+ export declare function runRuntimeEnvCommand(command: string, outputFile: string, envFiles?: string[], inputFile?: string): {
12
+ success: boolean;
13
+ stdout: string;
14
+ stderr: string;
15
+ };
5
16
  export declare function getTempDir(subDir: string): string;
17
+ export declare function hasRuntimeEnvScript(html: string, base: string): boolean;
package/dist/utils.js CHANGED
@@ -5,6 +5,51 @@ import { createRequire } from "module";
5
5
  const require = createRequire(import.meta.url);
6
6
  const schemaFile = ".runtimeenvschema.json";
7
7
  const globalVariableName = "runtimeEnv";
8
+ let lastErrorMessage = null;
9
+ /**
10
+ * Clears the last error message to allow it to be logged again.
11
+ * This should be called when the plugin recovers from an error state.
12
+ */
13
+ export function clearLastError() {
14
+ lastErrorMessage = null;
15
+ }
16
+ export function logError(logger, message, error, server) {
17
+ const prefix = "[@runtime-env/vite-plugin]";
18
+ const fullMessage = `${prefix} ${message}`;
19
+ const errorDetails = error
20
+ ? typeof error === "string"
21
+ ? error
22
+ : error instanceof Error
23
+ ? error.message
24
+ : JSON.stringify(error)
25
+ : "";
26
+ const completeErrorMessage = errorDetails
27
+ ? `${fullMessage}\n${errorDetails}`
28
+ : fullMessage;
29
+ if (completeErrorMessage !== lastErrorMessage) {
30
+ if (!logger) {
31
+ console.error(fullMessage);
32
+ if (error)
33
+ console.error(errorDetails);
34
+ }
35
+ else {
36
+ logger.error(fullMessage, { timestamp: true });
37
+ if (error) {
38
+ logger.error(errorDetails, { timestamp: true });
39
+ }
40
+ }
41
+ lastErrorMessage = completeErrorMessage;
42
+ }
43
+ if (server) {
44
+ server.ws.send({
45
+ type: "error",
46
+ err: {
47
+ message: completeErrorMessage,
48
+ stack: "",
49
+ },
50
+ });
51
+ }
52
+ }
8
53
  export function isTypeScriptProject(root) {
9
54
  return existsSync(resolve(root, "tsconfig.json"));
10
55
  }
@@ -45,7 +90,12 @@ export function runRuntimeEnvCommand(command, outputFile, envFiles = [], inputFi
45
90
  // Fallback to local node_modules/.bin if require.resolve fails (e.g. during development or in some monorepo setups)
46
91
  cliPath = resolve("node_modules", ".bin", "runtime-env");
47
92
  }
48
- spawnSync("node", [cliPath, ...args]);
93
+ const result = spawnSync("node", [cliPath, ...args], { encoding: "utf8" });
94
+ return {
95
+ success: result.status === 0,
96
+ stdout: result.stdout,
97
+ stderr: result.stderr,
98
+ };
49
99
  }
50
100
  export function getTempDir(subDir) {
51
101
  const root = process.cwd();
@@ -53,3 +103,22 @@ export function getTempDir(subDir) {
53
103
  mkdirSync(tempDir, { recursive: true });
54
104
  return tempDir;
55
105
  }
106
+ export function hasRuntimeEnvScript(html, base) {
107
+ // Normalize base: ensure it starts with / and doesn't end with / (unless it's just /)
108
+ const normalizedBase = base.startsWith("/") ? base : `/${base}`;
109
+ const finalBase = normalizedBase.endsWith("/") && normalizedBase.length > 1
110
+ ? normalizedBase.slice(0, -1)
111
+ : normalizedBase;
112
+ const expectedSrc = `${finalBase === "/" ? "" : finalBase}/runtime-env.js`;
113
+ // Regex to find script tag with src matching runtime-env.js
114
+ // It accounts for varying whitespace, attribute order, and quote types.
115
+ const scriptRegex = /<script\b[^>]*?\bsrc\s*=\s*(['"])([^'"]*\/runtime-env\.js)\1[^>]*?>\s*<\/script>/gi;
116
+ let match;
117
+ while ((match = scriptRegex.exec(html)) !== null) {
118
+ const src = match[2];
119
+ if (src === expectedSrc || src === "/runtime-env.js") {
120
+ return true;
121
+ }
122
+ }
123
+ return false;
124
+ }
package/dist/vitest.js CHANGED
@@ -1,25 +1,14 @@
1
1
  import { resolve } from "path";
2
2
  import { rmSync } from "fs";
3
- import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, } from "./utils.js";
3
+ import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, } from "./utils.js";
4
4
  export function vitestPlugin() {
5
5
  return {
6
6
  name: "runtime-env-vitest",
7
7
  config(config, configEnv) {
8
- if (config.mode === "test") {
9
- const root = config.root || process.cwd();
10
- // Generate runtime-env.d.ts for Vitest type checking
11
- if (isTypeScriptProject(root)) {
12
- runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
13
- }
14
- const envDir = config.envDir || root;
15
- const envFiles = getViteEnvFiles(config.mode, envDir);
8
+ if (config.mode === "test" || configEnv.mode === "test") {
16
9
  // Generate runtime-env.js for Vitest runtime access
17
10
  const vitestOutputDir = getTempDir("vitest");
18
11
  const vitestOutputPath = resolve(vitestOutputDir, "runtime-env.js");
19
- // Ensure directory is clean
20
- rmSync(vitestOutputDir, { recursive: true, force: true });
21
- getTempDir("vitest"); // Re-create it clean
22
- runRuntimeEnvCommand("gen-js", vitestOutputPath, envFiles);
23
12
  // Automatically inject setupFiles for Vitest
24
13
  const vitestConfig = config.test || {};
25
14
  const setupFiles = vitestConfig.setupFiles || [];
@@ -35,5 +24,31 @@ export function vitestPlugin() {
35
24
  };
36
25
  }
37
26
  },
27
+ configResolved(config) {
28
+ if (config.mode === "test") {
29
+ const root = config.root || process.cwd();
30
+ // Generate runtime-env.d.ts for Vitest type checking
31
+ if (isTypeScriptProject(root)) {
32
+ const result = runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
33
+ if (!result.success) {
34
+ logError(config.logger, "Failed to generate runtime-env.d.ts", result.stderr || result.stdout);
35
+ process.exit(1);
36
+ }
37
+ }
38
+ const envDir = config.envDir || root;
39
+ const envFiles = getViteEnvFiles(config.mode, envDir);
40
+ // Generate runtime-env.js for Vitest runtime access
41
+ const vitestOutputDir = getTempDir("vitest");
42
+ const vitestOutputPath = resolve(vitestOutputDir, "runtime-env.js");
43
+ // Ensure directory is clean
44
+ rmSync(vitestOutputDir, { recursive: true, force: true });
45
+ getTempDir("vitest"); // Re-create it clean
46
+ const result = runRuntimeEnvCommand("gen-js", vitestOutputPath, envFiles);
47
+ if (!result.success) {
48
+ logError(config.logger, "Failed to generate runtime-env.js", result.stderr || result.stdout);
49
+ process.exit(1);
50
+ }
51
+ }
52
+ },
38
53
  };
39
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtime-env/vite-plugin",
3
- "version": "0.0.0",
3
+ "version": "0.1.0",
4
4
  "description": "Opinionated Vite plugin for runtime-env",
5
5
  "license": "MIT",
6
6
  "author": "Ernest",
@@ -34,10 +34,13 @@
34
34
  "url": "https://github.com/runtime-env/runtime-env/issues"
35
35
  },
36
36
  "homepage": "https://github.com/runtime-env/runtime-env#readme",
37
- "dependencies": {
38
- "@runtime-env/cli": "^0.7.8"
37
+ "dependencies": {},
38
+ "peerDependencies": {
39
+ "@runtime-env/cli": "*",
40
+ "vite": "*"
39
41
  },
40
42
  "devDependencies": {
43
+ "@runtime-env/cli": "^1.0.0",
41
44
  "vite": "7.3.0"
42
45
  },
43
46
  "type": "module"