@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 +5 -5
- package/dist/build.js +16 -14
- package/dist/dev.js +16 -9
- package/dist/preview.js +17 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +30 -1
- package/dist/vitest.js +43 -37
- package/package.json +11 -5
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
|
-
"
|
|
21
|
+
"VITE_API_URL": { "type": "string" }
|
|
22
22
|
},
|
|
23
|
-
"required": ["
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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 (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
44
|
-
"vite": "7.3.
|
|
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
|
}
|