ultraenv 1.0.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.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2058 -0
  3. package/bin/ultraenv.mjs +3 -0
  4. package/dist/chunk-2USZPWLZ.js +288 -0
  5. package/dist/chunk-3UV2QNJL.js +270 -0
  6. package/dist/chunk-3VYXPTYV.js +179 -0
  7. package/dist/chunk-4XUYMRK5.js +366 -0
  8. package/dist/chunk-5G2DU52U.js +189 -0
  9. package/dist/chunk-6KS56D6E.js +172 -0
  10. package/dist/chunk-AWN6ADV7.js +328 -0
  11. package/dist/chunk-CHVO6NWI.js +203 -0
  12. package/dist/chunk-CIFMBJ4H.js +3975 -0
  13. package/dist/chunk-GC7RXHLA.js +253 -0
  14. package/dist/chunk-HFXQGJY3.js +445 -0
  15. package/dist/chunk-IGFVP24Q.js +91 -0
  16. package/dist/chunk-IKPTKALB.js +78 -0
  17. package/dist/chunk-JB7RKV3C.js +66 -0
  18. package/dist/chunk-MNVFG7H4.js +611 -0
  19. package/dist/chunk-MSXMESFP.js +1910 -0
  20. package/dist/chunk-N5PAV4NM.js +127 -0
  21. package/dist/chunk-NBOABPHM.js +158 -0
  22. package/dist/chunk-OMAOROL4.js +49 -0
  23. package/dist/chunk-R7PZRSZ7.js +105 -0
  24. package/dist/chunk-TE7HPLA6.js +73 -0
  25. package/dist/chunk-TMT5KCO3.js +101 -0
  26. package/dist/chunk-UEWYFN6A.js +189 -0
  27. package/dist/chunk-WMHN5RW2.js +128 -0
  28. package/dist/chunk-XC65ORJ5.js +70 -0
  29. package/dist/chunk-YMMP4VQL.js +118 -0
  30. package/dist/chunk-YN2KGTCB.js +33 -0
  31. package/dist/chunk-YTICOB5M.js +65 -0
  32. package/dist/chunk-YVWLXFUT.js +107 -0
  33. package/dist/ci-check-sync-VBMSVWIV.js +48 -0
  34. package/dist/ci-scan-24MT5XGS.js +41 -0
  35. package/dist/ci-setup-C2NKEFRD.js +135 -0
  36. package/dist/ci-validate-7AW24LSQ.js +57 -0
  37. package/dist/cli/index.cjs +9217 -0
  38. package/dist/cli/index.d.cts +9 -0
  39. package/dist/cli/index.d.ts +9 -0
  40. package/dist/cli/index.js +339 -0
  41. package/dist/comparator-RDKX3OI7.js +13 -0
  42. package/dist/completion-MW35C2XO.js +168 -0
  43. package/dist/config-O5YRQP5Z.js +13 -0
  44. package/dist/debug-PTPXAF3K.js +131 -0
  45. package/dist/declaration-LEME4AFZ.js +10 -0
  46. package/dist/doctor-FZAUPKHS.js +129 -0
  47. package/dist/envs-compare-5K3HESX5.js +49 -0
  48. package/dist/envs-create-2XXHXMGA.js +58 -0
  49. package/dist/envs-list-NQM5252B.js +59 -0
  50. package/dist/envs-switch-6L2AQYID.js +50 -0
  51. package/dist/envs-validate-FL73Q76T.js +89 -0
  52. package/dist/fs-VH7ATUS3.js +31 -0
  53. package/dist/generator-LFZBMZZS.js +14 -0
  54. package/dist/git-BZS4DPAI.js +30 -0
  55. package/dist/help-3XJBXEHE.js +121 -0
  56. package/dist/index.cjs +12907 -0
  57. package/dist/index.d.cts +2562 -0
  58. package/dist/index.d.ts +2562 -0
  59. package/dist/index.js +3212 -0
  60. package/dist/init-Y7JQ2KYJ.js +146 -0
  61. package/dist/install-hook-SKXIV6NV.js +111 -0
  62. package/dist/json-schema-I26YNQBH.js +10 -0
  63. package/dist/key-manager-O3G55WPU.js +25 -0
  64. package/dist/middleware/express.cjs +103 -0
  65. package/dist/middleware/express.d.cts +115 -0
  66. package/dist/middleware/express.d.ts +115 -0
  67. package/dist/middleware/express.js +8 -0
  68. package/dist/middleware/fastify.cjs +91 -0
  69. package/dist/middleware/fastify.d.cts +111 -0
  70. package/dist/middleware/fastify.d.ts +111 -0
  71. package/dist/middleware/fastify.js +8 -0
  72. package/dist/module-IDIZPP4M.js +10 -0
  73. package/dist/protect-NCWPM6VC.js +161 -0
  74. package/dist/scan-TRLY36TT.js +58 -0
  75. package/dist/schema/index.cjs +4074 -0
  76. package/dist/schema/index.d.cts +1244 -0
  77. package/dist/schema/index.d.ts +1244 -0
  78. package/dist/schema/index.js +152 -0
  79. package/dist/sync-TMHMTLH2.js +186 -0
  80. package/dist/typegen-SQOSXBWM.js +80 -0
  81. package/dist/validate-IOAM5HWS.js +100 -0
  82. package/dist/vault-decrypt-U6HJZNBV.js +111 -0
  83. package/dist/vault-diff-B3ZOQTWI.js +132 -0
  84. package/dist/vault-encrypt-GUSLCSKS.js +112 -0
  85. package/dist/vault-init-GUBOTOUL.js +106 -0
  86. package/dist/vault-rekey-DAHT7JCN.js +132 -0
  87. package/dist/vault-status-GDLRU2OK.js +90 -0
  88. package/dist/vault-verify-CD76FJSF.js +102 -0
  89. package/package.json +106 -0
@@ -0,0 +1,146 @@
1
+ import {
2
+ confirm,
3
+ prompt
4
+ } from "./chunk-YTICOB5M.js";
5
+ import {
6
+ bold,
7
+ cyan,
8
+ green,
9
+ red
10
+ } from "./chunk-OMAOROL4.js";
11
+ import {
12
+ writeError,
13
+ writeLine
14
+ } from "./chunk-YN2KGTCB.js";
15
+ import {
16
+ exists,
17
+ writeFile
18
+ } from "./chunk-3VYXPTYV.js";
19
+ import {
20
+ DEFAULT_GITIGNORE_ENTRIES
21
+ } from "./chunk-XC65ORJ5.js";
22
+ import {
23
+ FileSystemError,
24
+ getErrorMessage
25
+ } from "./chunk-5G2DU52U.js";
26
+
27
+ // src/cli/commands/init.ts
28
+ import { resolve, join } from "path";
29
+ var DEFAULT_ENV_CONTENT = `# Environment Variables
30
+ # Created by ultraenv \u2014 https://github.com/Avinashvelu03/ultraenv
31
+
32
+ # App
33
+ NODE_ENV=development
34
+ APP_NAME=
35
+ APP_URL=http://localhost:3000
36
+
37
+ # Database
38
+ DATABASE_URL=
39
+ DATABASE_POOL_SIZE=10
40
+
41
+ # Server
42
+ PORT=3000
43
+ HOST=localhost
44
+
45
+ # Logging
46
+ LOG_LEVEL=info
47
+ `;
48
+ async function run(args, ctx) {
49
+ try {
50
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
51
+ const baseDir = resolve(cwd);
52
+ writeLine(bold("\u{1F680} ultraenv project initialization"));
53
+ writeLine("");
54
+ const configPath = join(baseDir, ".ultraenvrc.json");
55
+ const envPath = join(baseDir, ".env");
56
+ if (await exists(configPath) && !args.flags["--force"]) {
57
+ writeLine(cyan(" An ultraenv configuration already exists."));
58
+ const overwrite = await confirm(" Overwrite existing configuration?", false);
59
+ if (!overwrite) {
60
+ writeLine(green(" Initialization cancelled."));
61
+ return 0;
62
+ }
63
+ }
64
+ await prompt(" Project name", { default: baseDir.split("/").pop() ?? "my-project" });
65
+ const envDir = await prompt(" Environment directory", { default: "." });
66
+ writeLine("");
67
+ writeLine(cyan(" Creating configuration..."));
68
+ const configContent = JSON.stringify({
69
+ envDir,
70
+ expandVariables: true,
71
+ overrideProcessEnv: false,
72
+ mergeStrategy: "last-wins",
73
+ outputFormat: "terminal",
74
+ debug: false
75
+ }, null, 2) + "\n";
76
+ await writeFile(configPath, configContent);
77
+ writeLine(green(` \u2713 Created ${configPath}`));
78
+ if (!await exists(envPath)) {
79
+ writeLine(cyan(" Creating .env file..."));
80
+ await writeFile(envPath, DEFAULT_ENV_CONTENT);
81
+ writeLine(green(` \u2713 Created ${envPath}`));
82
+ } else {
83
+ writeLine(cyan(` .env already exists, skipping.`));
84
+ }
85
+ const examplePath = join(baseDir, ".env.example");
86
+ if (!await exists(examplePath)) {
87
+ const exampleContent = `# Environment Variables Template
88
+ # Auto-generated by ultraenv
89
+ # Copy this file to .env and fill in the values
90
+
91
+ # App
92
+ NODE_ENV=development
93
+ APP_NAME=<your-app-name>
94
+ APP_URL=http://localhost:3000
95
+
96
+ # Database
97
+ DATABASE_URL=<your-database-url>
98
+ DATABASE_POOL_SIZE=10
99
+
100
+ # Server
101
+ PORT=3000
102
+ HOST=localhost
103
+
104
+ # Logging
105
+ LOG_LEVEL=info
106
+ `;
107
+ await writeFile(examplePath, exampleContent);
108
+ writeLine(green(` \u2713 Created ${examplePath}`));
109
+ }
110
+ const gitignorePath = join(baseDir, ".gitignore");
111
+ if (await exists(gitignorePath)) {
112
+ const { readFile } = await import("./fs-VH7ATUS3.js");
113
+ const existingContent = await readFile(gitignorePath);
114
+ if (!existingContent.includes("# ultraenv")) {
115
+ const { appendFileSync } = await import("fs");
116
+ appendFileSync(gitignorePath, "\n" + DEFAULT_GITIGNORE_ENTRIES.join("\n") + "\n");
117
+ writeLine(green(" \u2713 Updated .gitignore"));
118
+ } else {
119
+ writeLine(cyan(" .gitignore already contains ultraenv entries"));
120
+ }
121
+ } else {
122
+ const gitignoreContent = DEFAULT_GITIGNORE_ENTRIES.join("\n") + "\n";
123
+ await writeFile(gitignorePath, gitignoreContent);
124
+ writeLine(green(" \u2713 Created .gitignore"));
125
+ }
126
+ writeLine("");
127
+ writeLine(green(bold(" \u2705 ultraenv initialized successfully!")));
128
+ writeLine("");
129
+ writeLine(cyan(" Next steps:"));
130
+ writeLine(` 1. Edit ${envPath} with your environment variables`);
131
+ writeLine(` 2. Edit ${configPath} to customize settings`);
132
+ writeLine(` 3. Run ${cyan("ultraenv validate")} to check your configuration`);
133
+ writeLine("");
134
+ return 0;
135
+ } catch (error) {
136
+ if (error instanceof FileSystemError) {
137
+ writeError(red(` Error: ${getErrorMessage(error)}`));
138
+ return 1;
139
+ }
140
+ writeError(red(` Error: ${error instanceof Error ? error.message : String(error)}`));
141
+ return 1;
142
+ }
143
+ }
144
+ export {
145
+ run
146
+ };
@@ -0,0 +1,111 @@
1
+ import {
2
+ isGitRepository
3
+ } from "./chunk-R7PZRSZ7.js";
4
+ import {
5
+ bold,
6
+ cyan,
7
+ green,
8
+ red,
9
+ yellow
10
+ } from "./chunk-OMAOROL4.js";
11
+ import {
12
+ writeError,
13
+ writeLine
14
+ } from "./chunk-YN2KGTCB.js";
15
+ import {
16
+ ensureDir,
17
+ exists,
18
+ writeFile
19
+ } from "./chunk-3VYXPTYV.js";
20
+ import "./chunk-5G2DU52U.js";
21
+
22
+ // src/cli/commands/install-hook.ts
23
+ import { resolve, join } from "path";
24
+ var HOOK_SCRIPT = `#!/bin/sh
25
+ # ultraenv pre-commit hook
26
+ # Validates environment, checks sync, and scans for secrets
27
+
28
+ echo "Running ultraenv pre-commit checks..."
29
+
30
+ # Check if ultraenv is available
31
+ if ! command -v ultraenv >/dev/null 2>&1; then
32
+ echo "Warning: ultraenv not found. Skipping pre-commit checks."
33
+ echo "Install with: npm install -g ultraenv"
34
+ exit 0
35
+ fi
36
+
37
+ # Validate environment
38
+ echo " \u2192 Validating environment..."
39
+ ultraenv ci validate --format json --strict
40
+ if [ $? -ne 0 ]; then
41
+ echo "\u2717 Environment validation failed"
42
+ exit 1
43
+ fi
44
+
45
+ # Check sync
46
+ echo " \u2192 Checking .env sync..."
47
+ ultraenv ci check-sync
48
+ if [ $? -ne 0 ]; then
49
+ echo "\u26A0 .env.example is out of sync (non-blocking)"
50
+ fi
51
+
52
+ # Scan for secrets
53
+ echo " \u2192 Scanning for secrets..."
54
+ ultraenv ci scan --format sarif --output .ultraenv-scan.sarif
55
+ if [ $? -ne 0 ]; then
56
+ echo "\u2717 Secret scan detected potential secrets!"
57
+ echo " Review the findings and remove any committed secrets."
58
+ exit 1
59
+ fi
60
+
61
+ echo "\u2713 All pre-commit checks passed"
62
+ exit 0
63
+ `;
64
+ async function run(args, ctx) {
65
+ try {
66
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
67
+ const baseDir = resolve(cwd);
68
+ const isGit = await isGitRepository(baseDir);
69
+ if (!isGit) {
70
+ writeError(red(" Not a git repository. Cannot install hooks."));
71
+ return 1;
72
+ }
73
+ const { getGitRoot } = await import("./git-BZS4DPAI.js");
74
+ const gitRoot = await getGitRoot(baseDir);
75
+ if (!gitRoot) {
76
+ writeError(red(" Could not determine git root."));
77
+ return 1;
78
+ }
79
+ const hooksDir = join(gitRoot, ".git", "hooks");
80
+ const hookPath = join(hooksDir, "pre-commit");
81
+ if (await exists(hookPath) && !args.flags["--force"]) {
82
+ writeLine(yellow(" A pre-commit hook already exists."));
83
+ writeLine(yellow(` Path: ${hookPath}`));
84
+ writeLine(yellow(" Use --force to overwrite."));
85
+ return 0;
86
+ }
87
+ await ensureDir(hooksDir);
88
+ await writeFile(hookPath, HOOK_SCRIPT);
89
+ const { chmodSync } = await import("fs");
90
+ chmodSync(hookPath, 493);
91
+ writeLine(green(bold(" \u2705 Pre-commit hook installed!")));
92
+ writeLine("");
93
+ writeLine(cyan(` Hook path: ${hookPath}`));
94
+ writeLine("");
95
+ writeLine(cyan(" The hook will run on every commit and:"));
96
+ writeLine(" \u2713 Validate environment variables");
97
+ writeLine(" \u2713 Check .env \u2194 .env.example sync");
98
+ writeLine(" \u2713 Scan for leaked secrets");
99
+ writeLine("");
100
+ writeLine(yellow(" Bypass with: git commit --no-verify"));
101
+ writeLine("");
102
+ return 0;
103
+ } catch (error) {
104
+ const msg = error instanceof Error ? error.message : String(error);
105
+ writeError(red(` Error: ${msg}`));
106
+ return 1;
107
+ }
108
+ }
109
+ export {
110
+ run
111
+ };
@@ -0,0 +1,10 @@
1
+ import {
2
+ generateJsonSchema,
3
+ generateJsonSchemaContent
4
+ } from "./chunk-6KS56D6E.js";
5
+ import "./chunk-3VYXPTYV.js";
6
+ import "./chunk-5G2DU52U.js";
7
+ export {
8
+ generateJsonSchema,
9
+ generateJsonSchemaContent
10
+ };
@@ -0,0 +1,25 @@
1
+ import {
2
+ deriveEnvironmentKey,
3
+ formatKey,
4
+ generateKeysFile,
5
+ generateMasterKey,
6
+ isValidKeyFormat,
7
+ maskKey,
8
+ parseKey,
9
+ parseKeysFile,
10
+ rotateKey
11
+ } from "./chunk-UEWYFN6A.js";
12
+ import "./chunk-2USZPWLZ.js";
13
+ import "./chunk-XC65ORJ5.js";
14
+ import "./chunk-5G2DU52U.js";
15
+ export {
16
+ deriveEnvironmentKey,
17
+ formatKey,
18
+ generateKeysFile,
19
+ generateMasterKey,
20
+ isValidKeyFormat,
21
+ maskKey,
22
+ parseKey,
23
+ parseKeysFile,
24
+ rotateKey
25
+ };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/middleware/express.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ healthCheckRoute: () => healthCheckRoute,
24
+ ultraenvMiddleware: () => ultraenvMiddleware
25
+ });
26
+ module.exports = __toCommonJS(express_exports);
27
+ function ultraenvMiddleware(options = {}) {
28
+ const {
29
+ exposePublic = true,
30
+ prefix = "PUBLIC_",
31
+ additionalPrefixes = [],
32
+ allowList = [],
33
+ denyList = [],
34
+ exposeNodeEnv = true,
35
+ source = process.env
36
+ } = options;
37
+ const allPrefixes = [prefix];
38
+ for (const p of additionalPrefixes) {
39
+ allPrefixes.push(p);
40
+ }
41
+ const allowSet = new Set(allowList.map((k) => k.toUpperCase()));
42
+ const denySet = new Set(denyList.map((k) => k.toUpperCase()));
43
+ const filteredEnv = buildFilteredEnv(
44
+ source,
45
+ allPrefixes,
46
+ allowSet,
47
+ denySet,
48
+ exposePublic,
49
+ exposeNodeEnv
50
+ );
51
+ return (_req, _res, next) => {
52
+ _req.env = filteredEnv;
53
+ next();
54
+ };
55
+ }
56
+ function buildFilteredEnv(source, prefixes, allowSet, denySet, exposePublic, exposeNodeEnv) {
57
+ if (!exposePublic) {
58
+ return {};
59
+ }
60
+ const env = {};
61
+ for (const [key, value] of Object.entries(source)) {
62
+ if (value === void 0 || value === "") continue;
63
+ const upperKey = key.toUpperCase();
64
+ if (denySet.has(upperKey)) continue;
65
+ if (allowSet.has(upperKey)) {
66
+ env[key] = value;
67
+ continue;
68
+ }
69
+ if (exposeNodeEnv && upperKey === "NODE_ENV") {
70
+ env[key] = value;
71
+ continue;
72
+ }
73
+ for (const p of prefixes) {
74
+ if (upperKey.startsWith(p.toUpperCase())) {
75
+ env[key] = value;
76
+ break;
77
+ }
78
+ }
79
+ }
80
+ return env;
81
+ }
82
+ function healthCheckRoute(options = {}) {
83
+ const { source = process.env, metadata = {} } = options;
84
+ return (_req, res) => {
85
+ const envKeys = Object.keys(source).filter(
86
+ (k) => source[k] !== void 0 && source[k] !== ""
87
+ );
88
+ const nodeEnv = source["NODE_ENV"] ?? "unknown";
89
+ const response = {
90
+ status: "ok",
91
+ loaded: envKeys.length,
92
+ environment: nodeEnv,
93
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
94
+ ...metadata
95
+ };
96
+ res.status(200).json(response);
97
+ };
98
+ }
99
+ // Annotate the CommonJS export names for ESM import in node:
100
+ 0 && (module.exports = {
101
+ healthCheckRoute,
102
+ ultraenvMiddleware
103
+ });
@@ -0,0 +1,115 @@
1
+ /** Minimal Express Request type */
2
+ interface UltraenvRequest {
3
+ [key: string]: unknown;
4
+ env?: UltraenvFilteredEnv;
5
+ }
6
+ /** Minimal Express Response type */
7
+ interface UltraenvResponse {
8
+ status(code: number): UltraenvResponse;
9
+ json(data: Record<string, unknown>): void;
10
+ }
11
+ /** Express NextFunction type */
12
+ type UltraenvNextFunction = (err?: Error) => void;
13
+ /** Options for the ultraenv Express middleware */
14
+ interface UltraenvMiddlewareOptions {
15
+ /**
16
+ * Whether to expose public env vars.
17
+ * When true, filters process.env by the specified prefix and attaches
18
+ * a filtered subset to req.env.
19
+ * Default: true
20
+ */
21
+ exposePublic?: boolean;
22
+ /**
23
+ * Prefix to filter public variables by.
24
+ * Only env vars starting with this prefix will be included in req.env.
25
+ * Default: 'PUBLIC_'
26
+ */
27
+ prefix?: string;
28
+ /**
29
+ * Additional prefixes to include in the filtered env.
30
+ * Useful for framework-specific prefixes (e.g., ['NEXT_PUBLIC_', 'VITE_']).
31
+ * Default: []
32
+ */
33
+ additionalPrefixes?: readonly string[];
34
+ /**
35
+ * Explicit list of env var names to always include.
36
+ * These are included regardless of prefix matching.
37
+ * Default: []
38
+ */
39
+ allowList?: readonly string[];
40
+ /**
41
+ * Explicit list of env var names to always exclude.
42
+ * Even if they match the prefix, they will be excluded.
43
+ * Default: []
44
+ */
45
+ denyList?: readonly string[];
46
+ /**
47
+ * Whether to also set NODE_ENV on req.env.
48
+ * Default: true
49
+ */
50
+ exposeNodeEnv?: boolean;
51
+ /**
52
+ * Custom source for environment variables.
53
+ * Defaults to process.env if not provided.
54
+ */
55
+ source?: Record<string, string | undefined>;
56
+ }
57
+ /** The filtered env object attached to req.env */
58
+ interface UltraenvFilteredEnv {
59
+ /** The filtered environment variables */
60
+ [key: string]: string;
61
+ }
62
+ /**
63
+ * Create an Express/Connect middleware that filters environment variables
64
+ * by prefix and attaches them to `req.env`.
65
+ *
66
+ * Only env vars matching the specified prefix(es) are included,
67
+ * preventing accidental exposure of secrets to client-side code.
68
+ *
69
+ * @param options - Middleware configuration options
70
+ * @returns Express middleware function
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * import express from 'express';
75
+ * import { ultraenvMiddleware } from 'ultraenv/middleware';
76
+ *
77
+ * const app = express();
78
+ * app.use(ultraenvMiddleware({
79
+ * exposePublic: true,
80
+ * prefix: 'PUBLIC_',
81
+ * additionalPrefixes: ['NEXT_PUBLIC_', 'VITE_'],
82
+ * }));
83
+ *
84
+ * // Now in routes:
85
+ * app.get('/api/config', (req, res) => {
86
+ * res.json({
87
+ * apiUrl: req.env?.PUBLIC_API_URL,
88
+ * siteUrl: req.env?.PUBLIC_SITE_URL,
89
+ * });
90
+ * });
91
+ * ```
92
+ */
93
+ declare function ultraenvMiddleware(options?: UltraenvMiddlewareOptions): (req: UltraenvRequest, res: UltraenvResponse, next: UltraenvNextFunction) => void;
94
+ /**
95
+ * Create a health check route handler that returns env health status.
96
+ * Does NOT expose secret values — only counts and metadata.
97
+ *
98
+ * @param options - Health check options
99
+ * @returns Express route handler
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import { healthCheckRoute } from 'ultraenv/middleware';
104
+ * app.get('/health/env', healthCheckRoute());
105
+ * // Response: { status: 'ok', loaded: 38, environment: 'production', timestamp: '...' }
106
+ * ```
107
+ */
108
+ declare function healthCheckRoute(options?: {
109
+ /** Custom env source. Defaults to process.env */
110
+ source?: Record<string, string | undefined>;
111
+ /** Additional metadata to include */
112
+ metadata?: Record<string, string | number | boolean>;
113
+ }): (req: UltraenvRequest, res: UltraenvResponse) => void;
114
+
115
+ export { type UltraenvFilteredEnv, type UltraenvMiddlewareOptions, type UltraenvNextFunction, type UltraenvRequest, type UltraenvResponse, healthCheckRoute, ultraenvMiddleware };
@@ -0,0 +1,115 @@
1
+ /** Minimal Express Request type */
2
+ interface UltraenvRequest {
3
+ [key: string]: unknown;
4
+ env?: UltraenvFilteredEnv;
5
+ }
6
+ /** Minimal Express Response type */
7
+ interface UltraenvResponse {
8
+ status(code: number): UltraenvResponse;
9
+ json(data: Record<string, unknown>): void;
10
+ }
11
+ /** Express NextFunction type */
12
+ type UltraenvNextFunction = (err?: Error) => void;
13
+ /** Options for the ultraenv Express middleware */
14
+ interface UltraenvMiddlewareOptions {
15
+ /**
16
+ * Whether to expose public env vars.
17
+ * When true, filters process.env by the specified prefix and attaches
18
+ * a filtered subset to req.env.
19
+ * Default: true
20
+ */
21
+ exposePublic?: boolean;
22
+ /**
23
+ * Prefix to filter public variables by.
24
+ * Only env vars starting with this prefix will be included in req.env.
25
+ * Default: 'PUBLIC_'
26
+ */
27
+ prefix?: string;
28
+ /**
29
+ * Additional prefixes to include in the filtered env.
30
+ * Useful for framework-specific prefixes (e.g., ['NEXT_PUBLIC_', 'VITE_']).
31
+ * Default: []
32
+ */
33
+ additionalPrefixes?: readonly string[];
34
+ /**
35
+ * Explicit list of env var names to always include.
36
+ * These are included regardless of prefix matching.
37
+ * Default: []
38
+ */
39
+ allowList?: readonly string[];
40
+ /**
41
+ * Explicit list of env var names to always exclude.
42
+ * Even if they match the prefix, they will be excluded.
43
+ * Default: []
44
+ */
45
+ denyList?: readonly string[];
46
+ /**
47
+ * Whether to also set NODE_ENV on req.env.
48
+ * Default: true
49
+ */
50
+ exposeNodeEnv?: boolean;
51
+ /**
52
+ * Custom source for environment variables.
53
+ * Defaults to process.env if not provided.
54
+ */
55
+ source?: Record<string, string | undefined>;
56
+ }
57
+ /** The filtered env object attached to req.env */
58
+ interface UltraenvFilteredEnv {
59
+ /** The filtered environment variables */
60
+ [key: string]: string;
61
+ }
62
+ /**
63
+ * Create an Express/Connect middleware that filters environment variables
64
+ * by prefix and attaches them to `req.env`.
65
+ *
66
+ * Only env vars matching the specified prefix(es) are included,
67
+ * preventing accidental exposure of secrets to client-side code.
68
+ *
69
+ * @param options - Middleware configuration options
70
+ * @returns Express middleware function
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * import express from 'express';
75
+ * import { ultraenvMiddleware } from 'ultraenv/middleware';
76
+ *
77
+ * const app = express();
78
+ * app.use(ultraenvMiddleware({
79
+ * exposePublic: true,
80
+ * prefix: 'PUBLIC_',
81
+ * additionalPrefixes: ['NEXT_PUBLIC_', 'VITE_'],
82
+ * }));
83
+ *
84
+ * // Now in routes:
85
+ * app.get('/api/config', (req, res) => {
86
+ * res.json({
87
+ * apiUrl: req.env?.PUBLIC_API_URL,
88
+ * siteUrl: req.env?.PUBLIC_SITE_URL,
89
+ * });
90
+ * });
91
+ * ```
92
+ */
93
+ declare function ultraenvMiddleware(options?: UltraenvMiddlewareOptions): (req: UltraenvRequest, res: UltraenvResponse, next: UltraenvNextFunction) => void;
94
+ /**
95
+ * Create a health check route handler that returns env health status.
96
+ * Does NOT expose secret values — only counts and metadata.
97
+ *
98
+ * @param options - Health check options
99
+ * @returns Express route handler
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import { healthCheckRoute } from 'ultraenv/middleware';
104
+ * app.get('/health/env', healthCheckRoute());
105
+ * // Response: { status: 'ok', loaded: 38, environment: 'production', timestamp: '...' }
106
+ * ```
107
+ */
108
+ declare function healthCheckRoute(options?: {
109
+ /** Custom env source. Defaults to process.env */
110
+ source?: Record<string, string | undefined>;
111
+ /** Additional metadata to include */
112
+ metadata?: Record<string, string | number | boolean>;
113
+ }): (req: UltraenvRequest, res: UltraenvResponse) => void;
114
+
115
+ export { type UltraenvFilteredEnv, type UltraenvMiddlewareOptions, type UltraenvNextFunction, type UltraenvRequest, type UltraenvResponse, healthCheckRoute, ultraenvMiddleware };
@@ -0,0 +1,8 @@
1
+ import {
2
+ healthCheckRoute,
3
+ ultraenvMiddleware
4
+ } from "../chunk-IKPTKALB.js";
5
+ export {
6
+ healthCheckRoute,
7
+ ultraenvMiddleware
8
+ };