@arki/env 0.0.9 → 0.2.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/CHANGELOG.md +196 -0
- package/README.md +231 -62
- package/dist/api.json +597 -0
- package/dist/core/define-env.d.ts +29 -4
- package/dist/core/define-env.d.ts.map +1 -1
- package/dist/core/define-env.js +85 -15
- package/dist/core/define-env.js.map +1 -1
- package/dist/core/describe.d.ts +29 -0
- package/dist/core/describe.d.ts.map +1 -0
- package/dist/core/describe.js +25 -0
- package/dist/core/describe.js.map +1 -0
- package/dist/core/errors.d.ts +10 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +13 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +7 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/secret.d.ts +56 -0
- package/dist/core/secret.d.ts.map +1 -0
- package/dist/core/secret.js +85 -0
- package/dist/core/secret.js.map +1 -0
- package/dist/errors.json +128 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/node/codec.d.ts +63 -0
- package/dist/node/codec.d.ts.map +1 -0
- package/dist/node/codec.js +182 -0
- package/dist/node/codec.js.map +1 -0
- package/dist/node/edit.d.ts +112 -0
- package/dist/node/edit.d.ts.map +1 -0
- package/dist/node/edit.js +268 -0
- package/dist/node/edit.js.map +1 -0
- package/dist/node/errors.d.ts +119 -0
- package/dist/node/errors.d.ts.map +1 -0
- package/dist/node/errors.js +144 -0
- package/dist/node/errors.js.map +1 -0
- package/dist/node/files.d.ts +9 -0
- package/dist/node/files.d.ts.map +1 -0
- package/dist/node/files.js +35 -0
- package/dist/node/files.js.map +1 -0
- package/dist/node/index.d.ts +20 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +13 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/key-schemas.d.ts +25 -0
- package/dist/node/key-schemas.d.ts.map +1 -0
- package/dist/node/key-schemas.js +38 -0
- package/dist/node/key-schemas.js.map +1 -0
- package/dist/node/keys.d.ts +54 -0
- package/dist/node/keys.d.ts.map +1 -0
- package/dist/node/keys.js +76 -0
- package/dist/node/keys.js.map +1 -0
- package/dist/node/load.d.ts +103 -0
- package/dist/node/load.d.ts.map +1 -0
- package/dist/node/load.js +306 -0
- package/dist/node/load.js.map +1 -0
- package/dist/node/operation-telemetry.d.ts +3 -0
- package/dist/node/operation-telemetry.d.ts.map +1 -0
- package/dist/node/operation-telemetry.js +53 -0
- package/dist/node/operation-telemetry.js.map +1 -0
- package/dist/node/references.d.ts +16 -0
- package/dist/node/references.d.ts.map +1 -0
- package/dist/node/references.js +72 -0
- package/dist/node/references.js.map +1 -0
- package/dist/node/register.d.ts +2 -0
- package/dist/node/register.d.ts.map +1 -0
- package/dist/node/register.js +19 -0
- package/dist/node/register.js.map +1 -0
- package/dist/{contracts → presets}/common.d.ts +1 -1
- package/dist/presets/common.d.ts.map +1 -0
- package/dist/{contracts → presets}/common.js +4 -8
- package/dist/presets/common.js.map +1 -0
- package/dist/{contracts → presets}/index.d.ts +5 -5
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +15 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/{contracts → presets}/parsing.d.ts +2 -2
- package/dist/presets/parsing.d.ts.map +1 -0
- package/dist/{contracts → presets}/parsing.js +13 -5
- package/dist/presets/parsing.js.map +1 -0
- package/dist/{contracts → presets}/urls.d.ts +1 -1
- package/dist/presets/urls.d.ts.map +1 -0
- package/dist/{contracts → presets}/urls.js +1 -1
- package/dist/presets/urls.js.map +1 -0
- package/docs/agent-guide.md +121 -0
- package/docs/upgrades/0.0.11-to-0.1.0.md +62 -0
- package/docs/upgrades/0.1.0-to-0.2.0.md +73 -0
- package/docs/upgrades/typed-node-outcomes.md +13 -0
- package/llms.txt +30 -0
- package/package.json +27 -20
- package/src/core/define-env.ts +101 -20
- package/src/core/describe.ts +52 -0
- package/src/core/errors.ts +14 -0
- package/src/core/index.ts +7 -2
- package/src/core/secret.ts +127 -0
- package/src/index.ts +3 -2
- package/src/node/codec.ts +220 -0
- package/src/node/edit.ts +279 -0
- package/src/node/errors.ts +147 -0
- package/src/node/files.ts +41 -0
- package/src/node/index.ts +48 -0
- package/src/node/key-schemas.ts +44 -0
- package/src/node/keys.ts +93 -0
- package/src/node/load.ts +386 -0
- package/src/node/operation-telemetry.ts +56 -0
- package/src/node/references.ts +90 -0
- package/src/node/register.ts +18 -0
- package/src/{contracts → presets}/common.ts +4 -8
- package/src/presets/index.ts +18 -0
- package/src/{contracts → presets}/parsing.ts +12 -5
- package/src/{contracts → presets}/urls.ts +1 -1
- package/dist/contracts/common.d.ts.map +0 -1
- package/dist/contracts/common.js.map +0 -1
- package/dist/contracts/index.d.ts.map +0 -1
- package/dist/contracts/index.js +0 -14
- package/dist/contracts/index.js.map +0 -1
- package/dist/contracts/parsing.d.ts.map +0 -1
- package/dist/contracts/parsing.js.map +0 -1
- package/dist/contracts/urls.d.ts.map +0 -1
- package/dist/contracts/urls.js.map +0 -1
- package/dist/dot.d.ts +0 -67
- package/dist/dot.d.ts.map +0 -1
- package/dist/dot.js +0 -65
- package/dist/dot.js.map +0 -1
- package/src/contracts/index.ts +0 -17
- package/src/dot.ts +0 -94
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
import type { CreateEnv, DefaultCombinedSchema } from '@t3-oss/env-core';
|
|
2
|
-
import type { ZodType } from 'zod';
|
|
3
2
|
import { createEnv } from '@t3-oss/env-core';
|
|
3
|
+
import type { StandardSchemaV1 } from '@arki/schema';
|
|
4
|
+
/**
|
|
5
|
+
* The process environment, or `undefined` on engines with no `process` (Hermes, browsers, Deno without
|
|
6
|
+
* Node compat). Reads through `globalThis` so a missing global is not a ReferenceError. Called only when
|
|
7
|
+
* the env is first read, never at import.
|
|
8
|
+
*/
|
|
9
|
+
export declare function processEnv(): Record<string, string | undefined> | undefined;
|
|
10
|
+
/** The prefix of a value encrypted in a dotenvx-format env file (`@arki/env/node`). */
|
|
11
|
+
export declare const ENCRYPTED_PREFIX = "encrypted:";
|
|
4
12
|
/** The issue shape t3-oss hands to `onValidationError`, derived so it stays in sync with the lib. */
|
|
5
13
|
type ValidationIssues = Parameters<NonNullable<Parameters<typeof createEnv>[0]['onValidationError']>>[0];
|
|
14
|
+
/**
|
|
15
|
+
* Fold validation issues into a human-legible, log-pipeline-safe string. The t3-oss default handler
|
|
16
|
+
* logs `issues` as a raw object, which platforms like Coolify collapse to `[Object]` — so the var
|
|
17
|
+
* that actually failed never reaches the logs. A flat ` path: message` list survives transport.
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatIssues(name: string | undefined, issues: ValidationIssues): string;
|
|
6
20
|
/**
|
|
7
21
|
* Thin, type-preserving wrapper over `@t3-oss/env-core`'s `createEnv`. Generic over the server,
|
|
8
22
|
* client, shared and composed schemas so the parsed env keeps its exact inferred types — the wrapper
|
|
9
|
-
* adds the ARKI defaults (auto `runtimeEnv`,
|
|
10
|
-
* handler) without widening any value to `unknown`.
|
|
23
|
+
* adds the ARKI defaults (auto `runtimeEnv`, validation on in every environment, a legible labelled
|
|
24
|
+
* error handler) without widening any value to `unknown`.
|
|
25
|
+
*
|
|
26
|
+
* Every schema is a Standard Schema (Zod, Valibot, ArkType, or a hand-written `~standard` object); each
|
|
27
|
+
* value's type is the schema's OUTPUT, so defaults and coercions in the caller's schemas still apply.
|
|
28
|
+
* Validation is synchronous: a schema whose `validate` returns a Promise or throws makes the first read
|
|
29
|
+
* throw `UnexpectedFailure` with the canonical schema failure, never a validation error.
|
|
11
30
|
*
|
|
12
31
|
* `TPrefix` is kept as a string-literal generic on purpose: `createEnv` uses it to enforce that
|
|
13
32
|
* client keys (and only client keys) carry the prefix. Widening it to `string` would make every
|
|
14
33
|
* server key collapse to a type-level `ErrorMessage`, so the prefix must stay a literal.
|
|
15
34
|
*/
|
|
16
|
-
export declare function defineEnv<TServer extends Record<string,
|
|
35
|
+
export declare function defineEnv<TServer extends Record<string, StandardSchemaV1>, TClient extends Record<string, StandardSchemaV1> = NonNullable<unknown>, TShared extends Record<string, StandardSchemaV1> = NonNullable<unknown>, const TPrefix extends string = '', const TExtends extends Record<string, unknown>[] = []>(config: {
|
|
17
36
|
/**
|
|
18
37
|
* Label shown in validation-error logs, e.g. `'@acme/backend'`. Without it a misconfigured
|
|
19
38
|
* deploy logs a bare "Invalid environment variables" with no hint which env failed — exactly the
|
|
@@ -40,6 +59,12 @@ export declare function defineEnv<TServer extends Record<string, ZodType>, TClie
|
|
|
40
59
|
*/
|
|
41
60
|
runtimeEnv?: Record<string, string | boolean | number | undefined>;
|
|
42
61
|
options?: {
|
|
62
|
+
/**
|
|
63
|
+
* `true` skips schema validation: values pass through raw. Default: validate on the first read,
|
|
64
|
+
* in every environment, unless the process sets `SKIP_ENV_VALIDATION=1` (exactly `1`). That
|
|
65
|
+
* variable is the only implicit opt-out, meant for Docker build stages that prerender without
|
|
66
|
+
* secrets. `CI`, lint and `NODE_ENV` never skip.
|
|
67
|
+
*/
|
|
43
68
|
skipValidation?: boolean;
|
|
44
69
|
/**
|
|
45
70
|
* Treat empty-string env values as `undefined` so defaults apply (e.g. `PORT=` in `.env`, or a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-env.d.ts","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"define-env.d.ts","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAOrD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAI3E;AAED,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAK7C,qGAAqG;AACrG,KAAK,gBAAgB,GAAG,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzG;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAOvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAChD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EACvE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EACvE,KAAK,CAAC,OAAO,SAAS,MAAM,GAAG,EAAE,EACjC,KAAK,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,EACrD,MAAM,EAAE;IACR;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qFAAqF;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IACnE,OAAO,CAAC,EAAE;QACR;;;;;WAKG;QACH,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB;;;;WAIG;QACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,KAAK,CAAC;KACzD,CAAC;CACH,GAAG,SAAS,CAAC,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CA6FxE"}
|
package/dist/core/define-env.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import { createEnv } from '@t3-oss/env-core';
|
|
2
|
+
import { InvalidInput, orThrow, UnexpectedFailure } from '@arki/failure';
|
|
3
|
+
import { parse, pathOf } from '@arki/schema';
|
|
4
|
+
import { registerEnvDescription } from './describe.js';
|
|
5
|
+
import { InvalidEnvironment } from './errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* The process environment, or `undefined` on engines with no `process` (Hermes, browsers, Deno without
|
|
8
|
+
* Node compat). Reads through `globalThis` so a missing global is not a ReferenceError. Called only when
|
|
9
|
+
* the env is first read, never at import.
|
|
10
|
+
*/
|
|
11
|
+
export function processEnv() {
|
|
12
|
+
// Typed as optional on purpose: the Node typings say `process` always exists, Hermes says otherwise.
|
|
13
|
+
const scope = globalThis;
|
|
14
|
+
return scope.process?.env;
|
|
15
|
+
}
|
|
16
|
+
/** The prefix of a value encrypted in a dotenvx-format env file (`@arki/env/node`). */
|
|
17
|
+
export const ENCRYPTED_PREFIX = 'encrypted:';
|
|
18
|
+
const STILL_ENCRYPTED_MESSAGE = 'still encrypted: start the process with `dot env run -- <cmd>`, or import `@arki/env/node/register` first';
|
|
2
19
|
/**
|
|
3
20
|
* Fold validation issues into a human-legible, log-pipeline-safe string. The t3-oss default handler
|
|
4
21
|
* logs `issues` as a raw object, which platforms like Coolify collapse to `[Object]` — so the var
|
|
5
22
|
* that actually failed never reaches the logs. A flat ` path: message` list survives transport.
|
|
6
23
|
*/
|
|
7
|
-
function formatIssues(name, issues) {
|
|
24
|
+
export function formatIssues(name, issues) {
|
|
8
25
|
const label = name ? `[${name}] ` : '';
|
|
9
26
|
const lines = issues.map(issue => {
|
|
10
|
-
const path = (issue.
|
|
11
|
-
.map(seg => (typeof seg === 'object' && seg !== null && 'key' in seg ? String(seg.key) : String(seg)))
|
|
12
|
-
.join('.');
|
|
27
|
+
const path = pathOf(issue).map(String).join('.');
|
|
13
28
|
return ` ${path || '(root)'}: ${issue.message}`;
|
|
14
29
|
});
|
|
15
30
|
return `❌ ${label}Invalid environment variables:\n${lines.join('\n')}`;
|
|
@@ -17,8 +32,13 @@ function formatIssues(name, issues) {
|
|
|
17
32
|
/**
|
|
18
33
|
* Thin, type-preserving wrapper over `@t3-oss/env-core`'s `createEnv`. Generic over the server,
|
|
19
34
|
* client, shared and composed schemas so the parsed env keeps its exact inferred types — the wrapper
|
|
20
|
-
* adds the ARKI defaults (auto `runtimeEnv`,
|
|
21
|
-
* handler) without widening any value to `unknown`.
|
|
35
|
+
* adds the ARKI defaults (auto `runtimeEnv`, validation on in every environment, a legible labelled
|
|
36
|
+
* error handler) without widening any value to `unknown`.
|
|
37
|
+
*
|
|
38
|
+
* Every schema is a Standard Schema (Zod, Valibot, ArkType, or a hand-written `~standard` object); each
|
|
39
|
+
* value's type is the schema's OUTPUT, so defaults and coercions in the caller's schemas still apply.
|
|
40
|
+
* Validation is synchronous: a schema whose `validate` returns a Promise or throws makes the first read
|
|
41
|
+
* throw `UnexpectedFailure` with the canonical schema failure, never a validation error.
|
|
22
42
|
*
|
|
23
43
|
* `TPrefix` is kept as a string-literal generic on purpose: `createEnv` uses it to enforce that
|
|
24
44
|
* client keys (and only client keys) carry the prefix. Widening it to `string` would make every
|
|
@@ -33,7 +53,11 @@ export function defineEnv(config) {
|
|
|
33
53
|
// consumed (boot, a request, a job). This is the same import/observe split
|
|
34
54
|
// drizzle tables have: define everywhere, observe only at use.
|
|
35
55
|
const build = () => {
|
|
36
|
-
|
|
56
|
+
// Validate everywhere the app runs, production included. The only implicit opt-out is the
|
|
57
|
+
// purpose-named SKIP_ENV_VALIDATION=1 (Docker build stages without secrets). Ambient variables
|
|
58
|
+
// like CI or the npm script name must never turn validation off: that would boot production on
|
|
59
|
+
// an unchecked config.
|
|
60
|
+
const skipValidation = config.options?.skipValidation ?? processEnv()?.SKIP_ENV_VALIDATION === '1';
|
|
37
61
|
// Use the caller's explicit runtimeEnv when supplied (Vite client vars via import.meta.env, or
|
|
38
62
|
// fallback aliases). Otherwise auto-build from every declared key (server + client + shared);
|
|
39
63
|
// createEnv tolerates keys absent from process.env (they parse as undefined → optional/default).
|
|
@@ -43,22 +67,34 @@ export function defineEnv(config) {
|
|
|
43
67
|
}
|
|
44
68
|
else {
|
|
45
69
|
runtimeEnv = {};
|
|
70
|
+
const source = processEnv();
|
|
46
71
|
for (const key of Object.keys(config.server)) {
|
|
47
|
-
runtimeEnv[key] =
|
|
72
|
+
runtimeEnv[key] = source?.[key];
|
|
48
73
|
}
|
|
49
74
|
for (const key of Object.keys(config.client ?? {})) {
|
|
50
|
-
runtimeEnv[key] =
|
|
75
|
+
runtimeEnv[key] = source?.[key];
|
|
51
76
|
}
|
|
52
77
|
for (const key of Object.keys(config.shared ?? {})) {
|
|
53
|
-
runtimeEnv[key] =
|
|
78
|
+
runtimeEnv[key] = source?.[key];
|
|
54
79
|
}
|
|
55
80
|
}
|
|
56
81
|
const onValidationError = config.options?.onValidationError ??
|
|
57
82
|
((issues) => {
|
|
58
83
|
const message = formatIssues(config.name, issues);
|
|
59
84
|
console.error(message);
|
|
60
|
-
|
|
85
|
+
// A configuration fault at boot: a typed failure, so a catcher can match on the code.
|
|
86
|
+
throw new UnexpectedFailure(InvalidEnvironment({ report: message }));
|
|
61
87
|
});
|
|
88
|
+
// A value that is still `encrypted:` means the env files were not loaded (Bun auto-loads them
|
|
89
|
+
// as they are, ciphertext included). A string schema would accept it, so refuse it here, by name.
|
|
90
|
+
if (!skipValidation) {
|
|
91
|
+
const stillEncrypted = Object.keys(runtimeEnv).filter(key => {
|
|
92
|
+
const value = runtimeEnv[key];
|
|
93
|
+
return typeof value === 'string' && value.startsWith(ENCRYPTED_PREFIX);
|
|
94
|
+
});
|
|
95
|
+
if (stillEncrypted.length > 0)
|
|
96
|
+
onValidationError(stillEncrypted.map(key => ({ message: STILL_ENCRYPTED_MESSAGE, path: [key] })));
|
|
97
|
+
}
|
|
62
98
|
// `createEnv`'s `server`/`client` params are conditional on `clientPrefix` being a *concrete*
|
|
63
99
|
// string literal; inside a generic wrapper `TPrefix` is abstract, so the body cannot be verified
|
|
64
100
|
// for all prefixes and the call argument must be asserted once. The PUBLIC contract stays exact:
|
|
@@ -66,10 +102,10 @@ export function defineEnv(config) {
|
|
|
66
102
|
// caller's `server`/`client`/`extends` are fully type-checked against `TServer`/`TClient`/`TExtends`
|
|
67
103
|
// at the call site. This is the only seam where types are asserted — value types are never widened.
|
|
68
104
|
const options = {
|
|
69
|
-
shared: config.shared
|
|
105
|
+
shared: syncSchemas(config.shared),
|
|
70
106
|
extends: config.extends,
|
|
71
|
-
server: config.server,
|
|
72
|
-
client: config.client
|
|
107
|
+
server: syncSchemas(config.server),
|
|
108
|
+
client: syncSchemas(config.client),
|
|
73
109
|
clientPrefix: config.clientPrefix ?? '',
|
|
74
110
|
runtimeEnv,
|
|
75
111
|
skipValidation,
|
|
@@ -85,7 +121,41 @@ export function defineEnv(config) {
|
|
|
85
121
|
const isPrivate = skipValidation ? config.runtimeEnv === undefined : isServer();
|
|
86
122
|
return { env, isPrivate };
|
|
87
123
|
};
|
|
88
|
-
|
|
124
|
+
const env = lazyEnv(build);
|
|
125
|
+
registerEnvDescription(env, {
|
|
126
|
+
...(config.name === undefined ? {} : { name: config.name }),
|
|
127
|
+
server: config.server,
|
|
128
|
+
...(config.client === undefined ? {} : { client: config.client }),
|
|
129
|
+
...(config.shared === undefined ? {} : { shared: config.shared }),
|
|
130
|
+
...(config.extends === undefined ? {} : { extends: config.extends }),
|
|
131
|
+
});
|
|
132
|
+
return env;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The caller's schemas, each run through `parse` before t3 sees it. t3 would let a throwing validator's
|
|
136
|
+
* raw error escape and report an async one with its own error (leaving a rejection unhandled). Here both
|
|
137
|
+
* fail as `UnexpectedFailure` (canonical validator defect with its private cause, or async mismatch), and bad values still reach t3 as issues.
|
|
138
|
+
*/
|
|
139
|
+
function syncSchemas(schemas) {
|
|
140
|
+
const wrapped = {};
|
|
141
|
+
for (const [key, schema] of Object.entries(schemas ?? {}))
|
|
142
|
+
wrapped[key] = syncSchema(schema);
|
|
143
|
+
return wrapped;
|
|
144
|
+
}
|
|
145
|
+
/** Same `version`, `vendor` and `types` as `schema`; only `validate` changes. */
|
|
146
|
+
function syncSchema(schema) {
|
|
147
|
+
return {
|
|
148
|
+
'~standard': {
|
|
149
|
+
...schema['~standard'],
|
|
150
|
+
validate: value => {
|
|
151
|
+
const result = parse(schema, value);
|
|
152
|
+
if (InvalidInput.is(result))
|
|
153
|
+
return { issues: result.data.issues };
|
|
154
|
+
// env-core expects validator defects to throw; bridge that foreign contract explicitly.
|
|
155
|
+
return { value: orThrow(result) };
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
89
159
|
}
|
|
90
160
|
/**
|
|
91
161
|
* Reads an env takes through the lazy view before it copies the values for fast reads. A copy costs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-env.js","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"define-env.js","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `describeEnv(env)`: the keys an env built by `defineEnv` declares, which of them are `secret()`,
|
|
3
|
+
* and where they live. It reads the declaration only, never a value, so tools (`dot env check`) can
|
|
4
|
+
* use it on a bare checkout.
|
|
5
|
+
*/
|
|
6
|
+
import type { StandardSchemaV1 } from '@arki/schema';
|
|
7
|
+
/** One declared key. */
|
|
8
|
+
export type EnvKeyDescription = {
|
|
9
|
+
readonly key: string;
|
|
10
|
+
/** Declared with `secret()`: must never be plaintext in a tracked file. */
|
|
11
|
+
readonly secret: boolean;
|
|
12
|
+
readonly scope: 'server' | 'client' | 'shared';
|
|
13
|
+
};
|
|
14
|
+
/** What an env declares, its `extends` included. */
|
|
15
|
+
export type EnvDescription = {
|
|
16
|
+
readonly name?: string;
|
|
17
|
+
readonly keys: readonly EnvKeyDescription[];
|
|
18
|
+
};
|
|
19
|
+
/** The description of an env built by `defineEnv`, or `undefined` for any other object. */
|
|
20
|
+
export declare function describeEnv(env: object): EnvDescription | undefined;
|
|
21
|
+
/** Called by `defineEnv` once per env. Later scopes and the env's own keys win over `extends`. */
|
|
22
|
+
export declare function registerEnvDescription(env: object, declaration: {
|
|
23
|
+
readonly name?: string;
|
|
24
|
+
readonly server: Record<string, StandardSchemaV1>;
|
|
25
|
+
readonly client?: Record<string, StandardSchemaV1>;
|
|
26
|
+
readonly shared?: Record<string, StandardSchemaV1>;
|
|
27
|
+
readonly extends?: readonly object[];
|
|
28
|
+
}): void;
|
|
29
|
+
//# sourceMappingURL=describe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/core/describe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIrD,wBAAwB;AACxB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAChD,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAAE,CAAC;AAIrG,2FAA2F;AAC3F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEnE;AAED,kGAAkG;AAClG,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE;IACX,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GACA,IAAI,CAcN"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { isSecretSchema } from './secret.js';
|
|
2
|
+
const descriptions = new WeakMap();
|
|
3
|
+
/** The description of an env built by `defineEnv`, or `undefined` for any other object. */
|
|
4
|
+
export function describeEnv(env) {
|
|
5
|
+
return descriptions.get(env);
|
|
6
|
+
}
|
|
7
|
+
/** Called by `defineEnv` once per env. Later scopes and the env's own keys win over `extends`. */
|
|
8
|
+
export function registerEnvDescription(env, declaration) {
|
|
9
|
+
const keys = new Map();
|
|
10
|
+
for (const base of declaration.extends ?? []) {
|
|
11
|
+
for (const key of describeEnv(base)?.keys ?? [])
|
|
12
|
+
keys.set(key.key, key);
|
|
13
|
+
}
|
|
14
|
+
const scopes = [
|
|
15
|
+
['shared', declaration.shared],
|
|
16
|
+
['client', declaration.client],
|
|
17
|
+
['server', declaration.server],
|
|
18
|
+
];
|
|
19
|
+
for (const [scope, schemas] of scopes) {
|
|
20
|
+
for (const [key, schema] of Object.entries(schemas ?? {}))
|
|
21
|
+
keys.set(key, { key, secret: isSecretSchema(schema), scope });
|
|
22
|
+
}
|
|
23
|
+
descriptions.set(env, declaration.name === undefined ? { keys: [...keys.values()] } : { name: declaration.name, keys: [...keys.values()] });
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=describe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/core/describe.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C,MAAM,YAAY,GAAG,IAAI,OAAO,EAA0B,CAAC;AAE3D,2FAA2F;AAC3F,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,sBAAsB,CACpC,GAAW,EACX,WAMC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAA6B,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAC7C,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,MAAM,GAAG;QACb,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;QAC9B,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;QAC9B,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;KACtB,CAAC;IACX,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,MAAM,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3H,CAAC;IACD,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAC9I,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The process environment does not match the schema, so the app must not boot.
|
|
2
|
+
* @fix Set or correct the variables listed in the report, then start the app again.
|
|
3
|
+
* @verify bun run test -- src/core/define-env.test.ts
|
|
4
|
+
*/
|
|
5
|
+
export declare const InvalidEnvironment: import("@arki/failure").FailureDefinition<"env.invalid_environment", import("@standard-schema/spec").StandardSchemaV1<{
|
|
6
|
+
report: string;
|
|
7
|
+
}, {
|
|
8
|
+
report: string;
|
|
9
|
+
}>>;
|
|
10
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;;GAK7B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineFailure } from '@arki/failure';
|
|
3
|
+
/** The process environment does not match the schema, so the app must not boot.
|
|
4
|
+
* @fix Set or correct the variables listed in the report, then start the app again.
|
|
5
|
+
* @verify bun run test -- src/core/define-env.test.ts
|
|
6
|
+
*/
|
|
7
|
+
export const InvalidEnvironment = /* @__PURE__ */ defineFailure('env.invalid_environment', {
|
|
8
|
+
status: 500,
|
|
9
|
+
data: z.object({ report: z.string() }),
|
|
10
|
+
message: data => data.report,
|
|
11
|
+
remediation: 'Set or correct the variables listed in the report, then start the app again.',
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC,aAAa,CAAC,yBAAyB,EAAE;IACzF,MAAM,EAAE,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACtC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM;IAC5B,WAAW,EAAE,8EAA8E;CAC5F,CAAC,CAAC"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
/** `defineEnv()` plus `secret()`, `reveal()` and `Redacted` for typed, lazily validated environments. */
|
|
2
|
+
export { defineEnv, formatIssues } from './define-env.js';
|
|
3
|
+
export { InvalidEnvironment } from './errors.js';
|
|
4
|
+
export { isSecretSchema, Redacted, reveal, secret, SECRET_SCHEMA } from './secret.js';
|
|
5
|
+
export { describeEnv } from './describe.js';
|
|
6
|
+
export type { EnvDescription, EnvKeyDescription } from './describe.js';
|
|
7
|
+
export { presets } from '../presets/index.js';
|
|
3
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
/** `defineEnv()` plus `secret()`, `reveal()` and `Redacted` for typed, lazily validated environments. */
|
|
2
|
+
export { defineEnv, formatIssues } from './define-env.js';
|
|
3
|
+
export { InvalidEnvironment } from './errors.js';
|
|
4
|
+
export { isSecretSchema, Redacted, reveal, secret, SECRET_SCHEMA } from './secret.js';
|
|
5
|
+
export { describeEnv } from './describe.js';
|
|
6
|
+
export { presets } from '../presets/index.js';
|
|
3
7
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets that cannot leak by accident.
|
|
3
|
+
*
|
|
4
|
+
* `secret(schema)` parses a variable as usual and wraps the result in a
|
|
5
|
+
* {@link Redacted}. Printing it, logging it, serialising it or putting it in a
|
|
6
|
+
* template string all show `[redacted]`. Reading the value takes a deliberate,
|
|
7
|
+
* greppable `reveal(env.KEY)` call at the one place that needs it.
|
|
8
|
+
*
|
|
9
|
+
* Redaction guards against accidents (a logged config object, an error
|
|
10
|
+
* message with the env in it). It is not encryption: code that calls
|
|
11
|
+
* `reveal` gets the plain value.
|
|
12
|
+
*/
|
|
13
|
+
import type { SchemaInput, SchemaOutput, StandardSchemaV1 } from '@arki/schema';
|
|
14
|
+
/** Node's `util.inspect` hook, so `console.log(env)` shows `[redacted]` too. */
|
|
15
|
+
declare const inspect: unique symbol;
|
|
16
|
+
/** A value that prints as `[redacted]`. Read it with {@link reveal}. */
|
|
17
|
+
export declare class Redacted<Value = string> {
|
|
18
|
+
#private;
|
|
19
|
+
constructor(value: Value);
|
|
20
|
+
toString(): string;
|
|
21
|
+
toJSON(): string;
|
|
22
|
+
[inspect](): string;
|
|
23
|
+
}
|
|
24
|
+
/** What {@link secret} returns: a Standard Schema whose output is redacted, with an `.optional()` variant. */
|
|
25
|
+
export type SecretSchema<Schema extends StandardSchemaV1> = StandardSchemaV1<SchemaInput<Schema>, Redacted<SchemaOutput<Schema>>> & {
|
|
26
|
+
readonly [SECRET_SCHEMA]: true;
|
|
27
|
+
/** Accepts a missing variable. `undefined` passes through as `undefined`, never redacted. */
|
|
28
|
+
optional(): StandardSchemaV1<SchemaInput<Schema> | undefined, Redacted<SchemaOutput<Schema>> | undefined> & {
|
|
29
|
+
readonly [SECRET_SCHEMA]: true;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/** Marks a schema built by {@link secret}, so `describeEnv` can tell secrets apart. */
|
|
33
|
+
export declare const SECRET_SCHEMA: unique symbol;
|
|
34
|
+
/** True for a schema built by {@link secret} (or its `.optional()`). */
|
|
35
|
+
export declare function isSecretSchema(schema: StandardSchemaV1): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Validate with `schema` (any Standard Schema), then wrap the value in a {@link Redacted}. For an
|
|
38
|
+
* optional secret, call `.optional()`: `secret(z.string()).optional()`. The inner result passes
|
|
39
|
+
* straight through: an async inner schema yields a promise, so `defineEnv`'s synchronous check
|
|
40
|
+
* fails with the same `UnexpectedFailure` it would give without `secret`, and a throwing validator
|
|
41
|
+
* still throws.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const env = defineEnv({ server: { STRIPE_KEY: secret(z.string().min(1)) } });
|
|
45
|
+
* console.log(env.STRIPE_KEY); // [redacted]
|
|
46
|
+
* stripe(reveal(env.STRIPE_KEY)); // the key
|
|
47
|
+
*/
|
|
48
|
+
export declare function secret<Schema extends StandardSchemaV1>(schema: Schema): SecretSchema<Schema>;
|
|
49
|
+
/**
|
|
50
|
+
* The plain value of a secret. Also takes the raw value, because when
|
|
51
|
+
* validation is skipped (`skipValidation`, or `CI` builds) schemas do not run
|
|
52
|
+
* and the variable is still a plain string.
|
|
53
|
+
*/
|
|
54
|
+
export declare function reveal<Value>(value: Redacted<Value> | Value): Value;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../src/core/secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKhF,gFAAgF;AAChF,QAAA,MAAM,OAAO,EAAE,OAAO,MAAiD,CAAC;AAKxE,wEAAwE;AACxE,qBAAa,QAAQ,CAAC,KAAK,GAAG,MAAM;;IAQlC,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,QAAQ,IAAI,MAAM,CAEjB;IAED,MAAM,IAAI,MAAM,CAEf;IAED,CAAC,OAAO,CAAC,IAAI,MAAM,CAElB;CACF;AAED,8GAA8G;AAC9G,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,gBAAgB,IAAI,gBAAgB,CAC1E,WAAW,CAAC,MAAM,CAAC,EACnB,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAC/B,GAAG;IACF,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,IAAI,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG;QAC1G,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,aAAa,EAAE,OAAO,MAAsC,CAAC;AAE1E,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEhE;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,MAAM,SAAS,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CA6B5F;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAEnE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** What a redacted value prints as, everywhere. */
|
|
2
|
+
const REDACTED_TEXT = '[redacted]';
|
|
3
|
+
/** Node's `util.inspect` hook, so `console.log(env)` shows `[redacted]` too. */
|
|
4
|
+
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
|
5
|
+
/** Reads the private value. Assigned in the class's static block, so only this module can read it. */
|
|
6
|
+
let read;
|
|
7
|
+
/** A value that prints as `[redacted]`. Read it with {@link reveal}. */
|
|
8
|
+
export class Redacted {
|
|
9
|
+
// A private field: invisible to JSON, `Object.keys`, spreading and `util.inspect`.
|
|
10
|
+
#value;
|
|
11
|
+
static {
|
|
12
|
+
read = redacted => redacted.#value;
|
|
13
|
+
}
|
|
14
|
+
constructor(value) {
|
|
15
|
+
this.#value = value;
|
|
16
|
+
}
|
|
17
|
+
toString() {
|
|
18
|
+
return REDACTED_TEXT;
|
|
19
|
+
}
|
|
20
|
+
toJSON() {
|
|
21
|
+
return REDACTED_TEXT;
|
|
22
|
+
}
|
|
23
|
+
[inspect]() {
|
|
24
|
+
return REDACTED_TEXT;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Marks a schema built by {@link secret}, so `describeEnv` can tell secrets apart. */
|
|
28
|
+
export const SECRET_SCHEMA = Symbol.for('arki.env.secret');
|
|
29
|
+
/** True for a schema built by {@link secret} (or its `.optional()`). */
|
|
30
|
+
export function isSecretSchema(schema) {
|
|
31
|
+
return SECRET_SCHEMA in schema;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What every issue of a rejected secret says. Vendors such as valibot put the received value in
|
|
35
|
+
* their messages (`Received "sk_live_…"`), and `defineEnv` logs and throws issues, so a secret's
|
|
36
|
+
* issues keep only their path.
|
|
37
|
+
*/
|
|
38
|
+
const HIDDEN_ISSUE_MESSAGE = 'Invalid secret (details hidden so the value cannot leak)';
|
|
39
|
+
/**
|
|
40
|
+
* Validate with `schema` (any Standard Schema), then wrap the value in a {@link Redacted}. For an
|
|
41
|
+
* optional secret, call `.optional()`: `secret(z.string()).optional()`. The inner result passes
|
|
42
|
+
* straight through: an async inner schema yields a promise, so `defineEnv`'s synchronous check
|
|
43
|
+
* fails with the same `UnexpectedFailure` it would give without `secret`, and a throwing validator
|
|
44
|
+
* still throws.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const env = defineEnv({ server: { STRIPE_KEY: secret(z.string().min(1)) } });
|
|
48
|
+
* console.log(env.STRIPE_KEY); // [redacted]
|
|
49
|
+
* stripe(reveal(env.STRIPE_KEY)); // the key
|
|
50
|
+
*/
|
|
51
|
+
export function secret(schema) {
|
|
52
|
+
const { version, vendor } = schema['~standard'];
|
|
53
|
+
const seal = (result) => result.issues === undefined
|
|
54
|
+
? { value: new Redacted(result.value) }
|
|
55
|
+
: {
|
|
56
|
+
issues: result.issues.map(issue => issue.path === undefined
|
|
57
|
+
? { message: HIDDEN_ISSUE_MESSAGE }
|
|
58
|
+
: { message: HIDDEN_ISSUE_MESSAGE, path: issue.path }),
|
|
59
|
+
};
|
|
60
|
+
const redact = (value) => {
|
|
61
|
+
const result = schema['~standard'].validate(value);
|
|
62
|
+
return result instanceof Promise ? result.then(seal) : seal(result);
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
[SECRET_SCHEMA]: true,
|
|
66
|
+
'~standard': { version, vendor, validate: redact },
|
|
67
|
+
optional: () => ({
|
|
68
|
+
[SECRET_SCHEMA]: true,
|
|
69
|
+
'~standard': {
|
|
70
|
+
version,
|
|
71
|
+
vendor,
|
|
72
|
+
validate: value => (value === undefined ? { value: undefined } : redact(value)),
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The plain value of a secret. Also takes the raw value, because when
|
|
79
|
+
* validation is skipped (`skipValidation`, or `CI` builds) schemas do not run
|
|
80
|
+
* and the variable is still a plain string.
|
|
81
|
+
*/
|
|
82
|
+
export function reveal(value) {
|
|
83
|
+
return value instanceof Redacted ? read(value) : value;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../../src/core/secret.ts"],"names":[],"mappings":"AAcA,mDAAmD;AACnD,MAAM,aAAa,GAAG,YAAY,CAAC;AAEnC,gFAAgF;AAChF,MAAM,OAAO,GAAkB,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAExE,sGAAsG;AACtG,IAAI,IAAiD,CAAC;AAEtD,wEAAwE;AACxE,MAAM,OAAO,QAAQ;IACnB,mFAAmF;IAC1E,MAAM,CAAQ;IAEvB;QACE,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;IACrC,CAAC;IAED,YAAY,KAAY;QACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM;QACJ,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,CAAC,OAAO,CAAC;QACP,OAAO,aAAa,CAAC;IACvB,CAAC;CACF;AAcD,uFAAuF;AACvF,MAAM,CAAC,MAAM,aAAa,GAAkB,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAE1E,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,aAAa,IAAI,MAAM,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,0DAA0D,CAAC;AAExF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAkC,MAAc;IACpE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IAEhD,MAAM,IAAI,GAAG,CAAC,MAAqD,EAAU,EAAE,CAC7E,MAAM,CAAC,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACvC,CAAC,CAAC;YACE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAChC,KAAK,CAAC,IAAI,KAAK,SAAS;gBACtB,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE;gBACnC,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CACxD;SACF,CAAC;IACR,MAAM,MAAM,GAAG,CAAC,KAAc,EAA4B,EAAE;QAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnD,OAAO,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC,CAAC;IACF,OAAO;QACL,CAAC,aAAa,CAAC,EAAE,IAAI;QACrB,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;QAClD,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACf,CAAC,aAAa,CAAC,EAAE,IAAI;YACrB,WAAW,EAAE;gBACX,OAAO;gBACP,MAAM;gBACN,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aAChF;SACF,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAQ,KAA8B;IAC1D,OAAO,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC"}
|