@runtime-env/vite-plugin 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -18,15 +18,15 @@ Before using the plugin, ensure you have the following prerequisites in your pro
18
18
  {
19
19
  "type": "object",
20
20
  "properties": {
21
- "API_URL": { "type": "string" }
21
+ "VITE_API_URL": { "type": "string" }
22
22
  },
23
- "required": ["API_URL"]
23
+ "required": ["VITE_API_URL"]
24
24
  }
25
25
  ```
26
26
  2. **Provide local environment variables**
27
27
  Create a `.env` (or `.env.local`, `.env.development`, etc.) file to provide values for development:
28
28
  ```env
29
- API_URL=http://localhost:3000
29
+ VITE_API_URL=http://localhost:3000
30
30
  ```
31
31
  3. **Load the runtime environment**
32
32
  Add a `<script>` tag to your `index.html` **before** your main entry point to load the generated environment variables:
@@ -55,14 +55,14 @@ export default defineConfig({
55
55
 
56
56
  ```ts
57
57
  // Variables are available globally
58
- const apiUrl = runtimeEnv.API_URL;
58
+ const apiUrl = runtimeEnv.VITE_API_URL;
59
59
  ```
60
60
 
61
61
  **In `index.html` (Template Interpolation):**
62
62
 
63
63
  ```html
64
64
  <!-- Use lodash-style templates -->
65
- <script src="https://maps.googleapis.com/maps/api/js?key=<%= runtimeEnv.GOOGLE_MAPS_API_KEY %>"></script>
65
+ <script src="https://maps.googleapis.com/maps/api/js?key=<%= runtimeEnv.VITE_GOOGLE_MAPS_API_KEY %>"></script>
66
66
  ```
67
67
 
68
68
  That's it! The plugin automatically handles the following:
package/dist/build.js CHANGED
@@ -1,27 +1,29 @@
1
- import { isTypeScriptProject, runRuntimeEnvCommand, logError, hasRuntimeEnvScript, } from "./utils.js";
1
+ import { isTypeScriptProject, runRuntimeEnvCommand, validateSchema, logError, hasRuntimeEnvScript, } from "./utils.js";
2
2
  export function buildPlugin() {
3
3
  let config;
4
4
  return {
5
5
  name: "runtime-env-build",
6
+ apply: "build",
6
7
  configResolved(resolvedConfig) {
7
8
  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
- }
9
+ const validation = validateSchema(config.root, config.envPrefix);
10
+ if (!validation.success) {
11
+ logError(config.logger, "Schema validation failed", validation.message);
12
+ process.exit(1);
13
+ }
14
+ if (isTypeScriptProject(config.root)) {
15
+ const result = runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
16
+ if (!result.success) {
17
+ logError(config.logger, "Failed to generate runtime-env.d.ts", result.stderr || result.stdout);
18
+ process.exit(1);
15
19
  }
16
20
  }
17
21
  },
18
22
  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);
24
- }
23
+ if (!hasRuntimeEnvScript(html, config.base)) {
24
+ logError(config.logger, `index.html is missing <script src="${config.base === "/" ? "" : config.base}/runtime-env.js"></script>. ` +
25
+ "This script tag is mandatory for @runtime-env/vite-plugin to function correctly in production.");
26
+ process.exit(1);
25
27
  }
26
28
  },
27
29
  };
package/dist/dev.js CHANGED
@@ -1,23 +1,22 @@
1
1
  import { resolve } from "path";
2
2
  import { writeFileSync, readFileSync, rmSync, existsSync } from "fs";
3
- import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, clearLastError, hasRuntimeEnvScript, } from "./utils.js";
3
+ import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, validateSchema, logError, clearLastError, hasRuntimeEnvScript, } from "./utils.js";
4
4
  const schemaFile = ".runtimeenvschema.json";
5
5
  export function devPlugin() {
6
6
  return {
7
7
  name: "runtime-env-dev",
8
+ apply(config, { command, mode }) {
9
+ return command === "serve" && mode !== "test";
10
+ },
8
11
  configureServer(server) {
9
- if (server.config.mode === "test")
10
- return;
11
12
  const envDir = server.config.envDir || server.config.root;
12
13
  const envFiles = getViteEnvFiles(server.config.mode, envDir);
13
14
  const watchFiles = [resolve(server.config.root, schemaFile), ...envFiles];
14
15
  let hadError = false;
15
16
  function run() {
16
- const devOutputDir = getTempDir("dev");
17
- const devOutputPath = resolve(devOutputDir, "runtime-env.js");
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);
17
+ const validation = validateSchema(server.config.root, server.config.envPrefix);
18
+ if (!validation.success) {
19
+ logError(server.config.logger, "Schema validation failed", validation.message, server);
21
20
  hadError = true;
22
21
  return;
23
22
  }
@@ -29,6 +28,14 @@ export function devPlugin() {
29
28
  return;
30
29
  }
31
30
  }
31
+ const devOutputDir = getTempDir("dev");
32
+ const devOutputPath = resolve(devOutputDir, "runtime-env.js");
33
+ const jsResult = runRuntimeEnvCommand("gen-js", devOutputPath, envFiles);
34
+ if (!jsResult.success) {
35
+ logError(server.config.logger, "Failed to generate runtime-env.js", jsResult.stderr || jsResult.stdout, server);
36
+ hadError = true;
37
+ return;
38
+ }
32
39
  if (hadError) {
33
40
  clearLastError();
34
41
  server.ws.send({ type: "full-reload" });
@@ -59,7 +66,7 @@ export function devPlugin() {
59
66
  });
60
67
  },
61
68
  transformIndexHtml(html, ctx) {
62
- if (ctx.server && ctx.server.config.command === "serve") {
69
+ if (ctx.server) {
63
70
  const envDir = ctx.server.config.envDir || ctx.server.config.root;
64
71
  const envFiles = getViteEnvFiles(ctx.server.config.mode, envDir);
65
72
  if (!hasRuntimeEnvScript(html, ctx.server.config.base)) {
package/dist/preview.js CHANGED
@@ -1,9 +1,15 @@
1
1
  import { resolve } from "path";
2
2
  import { readFileSync, writeFileSync, existsSync, rmSync } from "fs";
3
- import { runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, } from "./utils.js";
3
+ import { runRuntimeEnvCommand, getTempDir, getViteEnvFiles, validateSchema, logError, } from "./utils.js";
4
4
  export function previewPlugin() {
5
5
  return {
6
6
  name: "runtime-env-preview",
7
+ apply(config, { command }) {
8
+ // preview command also uses 'serve' but it's often better to just let it be
9
+ // and rely on the hook itself if we don't have a specific command.
10
+ // However, to be consistent with others:
11
+ return command === "serve";
12
+ },
7
13
  configurePreviewServer(server) {
8
14
  server.middlewares.use((req, res, next) => {
9
15
  const base = server.config.base || "/";
@@ -21,6 +27,12 @@ export function previewPlugin() {
21
27
  const envFiles = getViteEnvFiles(server.config.mode, envDir);
22
28
  // Serve runtime-env.js
23
29
  if (path === "/runtime-env.js") {
30
+ const validation = validateSchema(server.config.root, server.config.envPrefix);
31
+ if (!validation.success) {
32
+ logError(server.config.logger, "Schema validation failed", validation.message);
33
+ next();
34
+ return;
35
+ }
24
36
  const tmpDir = getTempDir("preview-gen-js");
25
37
  const tmpPath = resolve(tmpDir, "runtime-env.js");
26
38
  try {
@@ -43,6 +55,10 @@ export function previewPlugin() {
43
55
  }
44
56
  // Intercept index.html
45
57
  if (path === "/" || path === "/index.html") {
58
+ const validation = validateSchema(server.config.root, server.config.envPrefix);
59
+ if (!validation.success) {
60
+ logError(server.config.logger, "Schema validation failed", validation.message);
61
+ }
46
62
  const outDir = server.config.build.outDir || "dist";
47
63
  const distIndexHtml = resolve(server.config.root, outDir, "index.html");
48
64
  if (existsSync(distIndexHtml)) {
package/dist/utils.d.ts CHANGED
@@ -5,6 +5,10 @@ import type { Logger, ViteDevServer } from "vite";
5
5
  */
6
6
  export declare function clearLastError(): void;
7
7
  export declare function logError(logger: Logger | undefined, message: string, error?: any, server?: ViteDevServer): void;
8
+ export declare function validateSchema(root: string, envPrefix?: string | string[]): {
9
+ success: boolean;
10
+ message?: string;
11
+ };
8
12
  export declare function isTypeScriptProject(root: string): boolean;
9
13
  export declare function getViteEnvFiles(mode: string, envDir: string): string[];
10
14
  export declare function getRuntimeEnvCommandLineArgs(command: string, outputFile: string, envFiles?: string[], inputFile?: string): string[];
package/dist/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync } from "fs";
1
+ import { existsSync, mkdirSync, readFileSync } from "fs";
2
2
  import { resolve } from "path";
3
3
  import { spawnSync } from "child_process";
4
4
  import { createRequire } from "module";
@@ -50,6 +50,35 @@ export function logError(logger, message, error, server) {
50
50
  });
51
51
  }
52
52
  }
53
+ export function validateSchema(root, envPrefix = "VITE_") {
54
+ const schemaPath = resolve(root, schemaFile);
55
+ if (!existsSync(schemaPath)) {
56
+ return { success: true };
57
+ }
58
+ try {
59
+ const schemaContent = readFileSync(schemaPath, "utf-8");
60
+ const schema = JSON.parse(schemaContent);
61
+ if (schema.type !== "object" || !schema.properties) {
62
+ return { success: true }; // Let the CLI handle invalid schema format
63
+ }
64
+ const keys = Object.keys(schema.properties);
65
+ const prefixes = Array.isArray(envPrefix) ? envPrefix : [envPrefix];
66
+ const invalidKeys = keys.filter((key) => !prefixes.some((prefix) => key.startsWith(prefix)));
67
+ if (invalidKeys.length > 0) {
68
+ return {
69
+ success: false,
70
+ message: `The following keys in ${schemaFile} do not match any of the allowed env prefixes (${prefixes.join(", ")}): ${invalidKeys.join(", ")}`,
71
+ };
72
+ }
73
+ }
74
+ catch (error) {
75
+ return {
76
+ success: false,
77
+ message: `Failed to parse ${schemaFile}: ${error instanceof Error ? error.message : String(error)}`,
78
+ };
79
+ }
80
+ return { success: true };
81
+ }
53
82
  export function isTypeScriptProject(root) {
54
83
  return existsSync(resolve(root, "tsconfig.json"));
55
84
  }
package/dist/vitest.js CHANGED
@@ -1,54 +1,60 @@
1
1
  import { resolve } from "path";
2
2
  import { rmSync } from "fs";
3
- import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, logError, } from "./utils.js";
3
+ import { isTypeScriptProject, runRuntimeEnvCommand, getTempDir, getViteEnvFiles, validateSchema, logError, } from "./utils.js";
4
4
  export function vitestPlugin() {
5
5
  return {
6
6
  name: "runtime-env-vitest",
7
- config(config, configEnv) {
8
- if (config.mode === "test" || configEnv.mode === "test") {
9
- // Generate runtime-env.js for Vitest runtime access
10
- const vitestOutputDir = getTempDir("vitest");
11
- const vitestOutputPath = resolve(vitestOutputDir, "runtime-env.js");
12
- // Automatically inject setupFiles for Vitest
13
- const vitestConfig = config.test || {};
14
- const setupFiles = vitestConfig.setupFiles || [];
15
- if (Array.isArray(setupFiles)) {
7
+ apply(_config, { mode }) {
8
+ return mode === "test";
9
+ },
10
+ config(config) {
11
+ // Generate runtime-env.js for Vitest runtime access
12
+ const vitestOutputDir = getTempDir("vitest");
13
+ const vitestOutputPath = resolve(vitestOutputDir, "runtime-env.js");
14
+ // Automatically inject setupFiles for Vitest
15
+ const vitestConfig = config.test || {};
16
+ const setupFiles = vitestConfig.setupFiles || [];
17
+ if (Array.isArray(setupFiles)) {
18
+ if (!setupFiles.includes(vitestOutputPath)) {
16
19
  setupFiles.push(vitestOutputPath);
17
20
  }
18
- else {
19
- vitestConfig.setupFiles = [setupFiles, vitestOutputPath];
20
- }
21
- config.test = {
22
- ...vitestConfig,
23
- setupFiles,
24
- };
25
21
  }
22
+ else {
23
+ vitestConfig.setupFiles = [setupFiles, vitestOutputPath];
24
+ }
25
+ config.test = {
26
+ ...vitestConfig,
27
+ setupFiles,
28
+ };
26
29
  },
27
30
  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);
31
+ const root = config.root || process.cwd();
32
+ const validation = validateSchema(root, config.envPrefix);
33
+ if (!validation.success) {
34
+ logError(config.logger, "Schema validation failed", validation.message);
35
+ process.exit(1);
36
+ }
37
+ // Generate runtime-env.d.ts for Vitest type checking
38
+ if (isTypeScriptProject(root)) {
39
+ const result = runRuntimeEnvCommand("gen-ts", "src/runtime-env.d.ts");
47
40
  if (!result.success) {
48
- logError(config.logger, "Failed to generate runtime-env.js", result.stderr || result.stdout);
41
+ logError(config.logger, "Failed to generate runtime-env.d.ts", result.stderr || result.stdout);
49
42
  process.exit(1);
50
43
  }
51
44
  }
45
+ const envDir = config.envDir || root;
46
+ const envFiles = getViteEnvFiles(config.mode, envDir);
47
+ // Generate runtime-env.js for Vitest runtime access
48
+ const vitestOutputDir = getTempDir("vitest");
49
+ const vitestOutputPath = resolve(vitestOutputDir, "runtime-env.js");
50
+ // Ensure directory is clean
51
+ rmSync(vitestOutputDir, { recursive: true, force: true });
52
+ getTempDir("vitest"); // Re-create it clean
53
+ const result = runRuntimeEnvCommand("gen-js", vitestOutputPath, envFiles);
54
+ if (!result.success) {
55
+ logError(config.logger, "Failed to generate runtime-env.js", result.stderr || result.stdout);
56
+ process.exit(1);
57
+ }
52
58
  },
53
59
  };
54
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtime-env/vite-plugin",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Opinionated Vite plugin for runtime-env",
5
5
  "license": "MIT",
6
6
  "author": "Ernest",
@@ -34,14 +34,20 @@
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
37
  "peerDependencies": {
39
38
  "@runtime-env/cli": "*",
40
- "vite": "*"
39
+ "vite": "*",
40
+ "vitest": "*"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "vitest": {
44
+ "optional": true
45
+ }
41
46
  },
42
47
  "devDependencies": {
43
- "@runtime-env/cli": "^1.0.0",
44
- "vite": "7.3.0"
48
+ "@runtime-env/cli": "^1.0.1",
49
+ "vite": "^7.3.1",
50
+ "vitest": "^4.0.18"
45
51
  },
46
52
  "type": "module"
47
53
  }