@arki/env 0.0.6 → 0.0.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"define-env.d.ts","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC,qGAAqG;AACrG,KAAK,gBAAgB,GAAG,UAAU,CAChC,WAAW,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAClE,CAAC,CAAC,CAAC,CAAC;AAkBL;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EAC9D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EAC9D,KAAK,CAAC,OAAO,SAAS,MAAM,GAAG,EAAE,EACjC,KAAK,CAAC,QAAQ,SAAS,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,EAC1D,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,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,CAwDxE"}
1
+ {"version":3,"file":"define-env.d.ts","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC,qGAAqG;AACrG,KAAK,gBAAgB,GAAG,UAAU,CAChC,WAAW,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAClE,CAAC,CAAC,CAAC,CAAC;AAkBL;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EAC9D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EAC9D,KAAK,CAAC,OAAO,SAAS,MAAM,GAAG,EAAE,EACjC,KAAK,CAAC,QAAQ,SAAS,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,EAC1D,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,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,CAkExE"}
@@ -1,4 +1,5 @@
1
1
  import { createEnv } from '@t3-oss/env-core';
2
+ import { lazyObject } from '@arki/ts';
2
3
  /**
3
4
  * Fold validation issues into a human-legible, log-pipeline-safe string. The t3-oss default handler
4
5
  * logs `issues` as a raw object, which platforms like Coolify collapse to `[Object]` — so the var
@@ -25,52 +26,62 @@ function formatIssues(name, issues) {
25
26
  * server key collapse to a type-level `ErrorMessage`, so the prefix must stay a literal.
26
27
  */
27
28
  export function defineEnv(config) {
28
- const skipValidation = config.options?.skipValidation ?? (!!process.env.CI || process.env.NODE_ENV !== 'development');
29
- // Use the caller's explicit runtimeEnv when supplied (Vite client vars via import.meta.env, or
30
- // fallback aliases). Otherwise auto-build from every declared key (server + client + shared);
31
- // createEnv tolerates keys absent from process.env (they parse as undefined → optional/default).
32
- let runtimeEnv;
33
- if (config.runtimeEnv) {
34
- runtimeEnv = config.runtimeEnv;
35
- }
36
- else {
37
- runtimeEnv = {};
38
- for (const key of Object.keys(config.server)) {
39
- runtimeEnv[key] = process.env[key];
29
+ // LAZY by design: reading `process.env` and running validation are deferred
30
+ // to the FIRST property access, not the module import. Declaring an env is
31
+ // therefore observationally free — an app's declaration graph (features,
32
+ // adapters, `dot explain`, docs tooling) imports from a bare checkout with
33
+ // zero environment, and validation fires exactly when a value is actually
34
+ // consumed (boot, a request, a job). This is the same import/observe split
35
+ // drizzle tables have: define everywhere, observe only at use.
36
+ const build = () => {
37
+ const skipValidation = config.options?.skipValidation ?? (!!process.env.CI || process.env.NODE_ENV !== 'development');
38
+ // Use the caller's explicit runtimeEnv when supplied (Vite client vars via import.meta.env, or
39
+ // fallback aliases). Otherwise auto-build from every declared key (server + client + shared);
40
+ // createEnv tolerates keys absent from process.env (they parse as undefined → optional/default).
41
+ let runtimeEnv;
42
+ if (config.runtimeEnv) {
43
+ runtimeEnv = config.runtimeEnv;
40
44
  }
41
- for (const key of Object.keys(config.client ?? {})) {
42
- runtimeEnv[key] = process.env[key];
45
+ else {
46
+ runtimeEnv = {};
47
+ for (const key of Object.keys(config.server)) {
48
+ runtimeEnv[key] = process.env[key];
49
+ }
50
+ for (const key of Object.keys(config.client ?? {})) {
51
+ runtimeEnv[key] = process.env[key];
52
+ }
53
+ for (const key of Object.keys(config.shared ?? {})) {
54
+ runtimeEnv[key] = process.env[key];
55
+ }
43
56
  }
44
- for (const key of Object.keys(config.shared ?? {})) {
45
- runtimeEnv[key] = process.env[key];
46
- }
47
- }
48
- const onValidationError = config.options?.onValidationError ??
49
- ((issues) => {
50
- const message = formatIssues(config.name, issues);
51
- console.error(message);
52
- throw new Error(message);
53
- });
54
- // `createEnv`'s `server`/`client` params are conditional on `clientPrefix` being a *concrete*
55
- // string literal; inside a generic wrapper `TPrefix` is abstract, so the body cannot be verified
56
- // for all prefixes and the call argument must be asserted once. The PUBLIC contract stays exact:
57
- // the explicit return type above reconstructs `createEnv`'s own result from the generics, and the
58
- // caller's `server`/`client`/`extends` are fully type-checked against `TServer`/`TClient`/`TExtends`
59
- // at the call site. This is the only seam where types are asserted — value types are never widened.
60
- const options = {
61
- shared: config.shared ?? {},
62
- extends: config.extends,
63
- server: config.server,
64
- client: config.client ?? {},
65
- clientPrefix: config.clientPrefix ?? '',
66
- runtimeEnv,
67
- skipValidation,
68
- // Default ON: in containerized deploys an unset var is baked as "" (e.g. Docker `ENV X=${X}`
69
- // with no build arg), not left absent. Treating "" as undefined lets `.default()`/`.optional()`
70
- // apply as intended instead of failing format checks like `z.url()` on an empty string.
71
- emptyStringAsUndefined: config.options?.emptyStringAsUndefined ?? true,
72
- onValidationError,
57
+ const onValidationError = config.options?.onValidationError ??
58
+ ((issues) => {
59
+ const message = formatIssues(config.name, issues);
60
+ console.error(message);
61
+ throw new Error(message);
62
+ });
63
+ // `createEnv`'s `server`/`client` params are conditional on `clientPrefix` being a *concrete*
64
+ // string literal; inside a generic wrapper `TPrefix` is abstract, so the body cannot be verified
65
+ // for all prefixes and the call argument must be asserted once. The PUBLIC contract stays exact:
66
+ // the explicit return type above reconstructs `createEnv`'s own result from the generics, and the
67
+ // caller's `server`/`client`/`extends` are fully type-checked against `TServer`/`TClient`/`TExtends`
68
+ // at the call site. This is the only seam where types are asserted — value types are never widened.
69
+ const options = {
70
+ shared: config.shared ?? {},
71
+ extends: config.extends,
72
+ server: config.server,
73
+ client: config.client ?? {},
74
+ clientPrefix: config.clientPrefix ?? '',
75
+ runtimeEnv,
76
+ skipValidation,
77
+ // Default ON: in containerized deploys an unset var is baked as "" (e.g. Docker `ENV X=${X}`
78
+ // with no build arg), not left absent. Treating "" as undefined lets `.default()`/`.optional()`
79
+ // apply as intended instead of failing format checks like `z.url()` on an empty string.
80
+ emptyStringAsUndefined: config.options?.emptyStringAsUndefined ?? true,
81
+ onValidationError,
82
+ };
83
+ return createEnv(options);
73
84
  };
74
- return createEnv(options);
85
+ return lazyObject(build);
75
86
  }
76
87
  //# sourceMappingURL=define-env.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define-env.js","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define-env.js","sourceRoot":"","sources":["../../src/core/define-env.ts"],"names":[],"mappings":"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"}
package/dist/dot.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * DOT adapter for `@arki/env`.
3
3
  *
4
- * Wraps `defineEnv()` as a DOT pip so a DOT app can validate its
5
- * environment alongside any other services. The pip is sync (env
4
+ * Wraps `defineEnv()` as a DOT plugin so a DOT app can validate its
5
+ * environment alongside any other services. The plugin is sync (env
6
6
  * validation is sync), so the `boot` hook returns the validated env
7
7
  * object synchronously through the standard provides channel.
8
8
  *
@@ -33,7 +33,7 @@
33
33
  * this adapter without `@arki/dot` installed will fail at module load —
34
34
  * that is intentional: the adapter only makes sense in a DOT app.
35
35
  */
36
- import { type EmptyShape, type Pip } from '@arki/dot/pip';
36
+ import { type EmptyShape, type Plugin } from '@arki/dot/plugin';
37
37
  import type { ZodType } from 'zod';
38
38
  /**
39
39
  * Options for the env DOT adapter.
@@ -42,7 +42,7 @@ import type { ZodType } from 'zod';
42
42
  * resulting `app.services.env` is typed from this.
43
43
  */
44
44
  export type EnvDotOptions<TSchema extends Record<string, ZodType>> = {
45
- /** Zod schemas for each env var the pip validates. */
45
+ /** Zod schemas for each env var the plugin validates. */
46
46
  readonly schema: TSchema;
47
47
  /**
48
48
  * Forwarded to `defineEnv`. If `true`, the validator is skipped
@@ -58,10 +58,10 @@ export type EnvServices<TSchema extends Record<string, ZodType>> = {
58
58
  };
59
59
  };
60
60
  /**
61
- * Build a DOT pip that validates and publishes a typed `env` service.
61
+ * Build a DOT plugin that validates and publishes a typed `env` service.
62
62
  *
63
63
  * @param options - Schema + optional config.
64
- * @returns A pip that publishes `services.env`.
64
+ * @returns A plugin that publishes `services.env`.
65
65
  */
66
- export declare function env<TSchema extends Record<string, ZodType>>(options: EnvDotOptions<TSchema>): Pip<EmptyShape, EnvServices<TSchema>>;
66
+ export declare function env<TSchema extends Record<string, ZodType>>(options: EnvDotOptions<TSchema>): Plugin<EmptyShape, EnvServices<TSchema>>;
67
67
  //# sourceMappingURL=dot.d.ts.map
package/dist/dot.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAO,KAAK,UAAU,EAAE,KAAK,GAAG,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACnE,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACjE,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;KAAE,CAAC;CAClG,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,GAC9B,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAuBvC"}
1
+ {"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAU,KAAK,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACnE,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACjE,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;KAAE,CAAC;CAClG,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,GAC9B,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAuB1C"}
package/dist/dot.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * DOT adapter for `@arki/env`.
3
3
  *
4
- * Wraps `defineEnv()` as a DOT pip so a DOT app can validate its
5
- * environment alongside any other services. The pip is sync (env
4
+ * Wraps `defineEnv()` as a DOT plugin so a DOT app can validate its
5
+ * environment alongside any other services. The plugin is sync (env
6
6
  * validation is sync), so the `boot` hook returns the validated env
7
7
  * object synchronously through the standard provides channel.
8
8
  *
@@ -33,16 +33,16 @@
33
33
  * this adapter without `@arki/dot` installed will fail at module load —
34
34
  * that is intentional: the adapter only makes sense in a DOT app.
35
35
  */
36
- import { pip } from '@arki/dot/pip';
36
+ import { plugin } from '@arki/dot/plugin';
37
37
  import { defineEnv } from './core/define-env.js';
38
38
  /**
39
- * Build a DOT pip that validates and publishes a typed `env` service.
39
+ * Build a DOT plugin that validates and publishes a typed `env` service.
40
40
  *
41
41
  * @param options - Schema + optional config.
42
- * @returns A pip that publishes `services.env`.
42
+ * @returns A plugin that publishes `services.env`.
43
43
  */
44
44
  export function env(options) {
45
- return pip({
45
+ return plugin({
46
46
  name: 'env',
47
47
  version: '0.1.0',
48
48
  configure(ctx) {
package/dist/dot.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dot.js","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,GAAG,EAA6B,MAAM,eAAe,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAwBjD;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CACjB,OAA+B;IAE/B,OAAO,GAAG,CAAC;QACT,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;QAChB,SAAS,CAAC,GAAG;YACX,GAAG,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,IAAI;YACF,MAAM,SAAS,GAAG,SAAS,CAAC;gBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EACL,OAAO,CAAC,cAAc,KAAK,SAAS;oBAClC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE;oBAC5C,CAAC,CAAC,SAAS;aAChB,CAAC,CAAC;YACH,oEAAoE;YACpE,kEAAkE;YAClE,8DAA8D;YAC9D,0DAA0D;YAC1D,MAAM,SAAS,GAAG,SAAmD,CAAC;YACtE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"dot.js","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,MAAM,EAAgC,MAAM,kBAAkB,CAAC;AAGxE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAwBjD;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CACjB,OAA+B;IAE/B,OAAO,MAAM,CAAC;QACZ,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;QAChB,SAAS,CAAC,GAAG;YACX,GAAG,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,IAAI;YACF,MAAM,SAAS,GAAG,SAAS,CAAC;gBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EACL,OAAO,CAAC,cAAc,KAAK,SAAS;oBAClC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE;oBAC5C,CAAC,CAAC,SAAS;aAChB,CAAC,CAAC;YACH,oEAAoE;YACpE,kEAAkE;YAClE,8DAA8D;YAC9D,0DAA0D;YAC1D,MAAM,SAAS,GAAG,SAAmD,CAAC;YACtE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arki/env",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Type-safe environment variable parsing for ARKI — defineEnv() built on @t3-oss/env-core with Zod contracts for common variable shapes.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -58,11 +58,12 @@
58
58
  "package.json"
59
59
  ],
60
60
  "dependencies": {
61
+ "@arki/ts": "0.0.3",
61
62
  "@t3-oss/env-core": "^0.13.10",
62
63
  "zod": "4.3.5"
63
64
  },
64
65
  "peerDependencies": {
65
- "@arki/dot": "^0.3.0"
66
+ "@arki/dot": "^0.4.0"
66
67
  },
67
68
  "peerDependenciesMeta": {
68
69
  "@arki/dot": {
@@ -1,5 +1,6 @@
1
1
  import { createEnv } from '@t3-oss/env-core';
2
2
  import type { CreateEnv, DefaultCombinedSchema } from '@t3-oss/env-core';
3
+ import { lazyObject } from '@arki/ts';
3
4
  import type { ZodType } from 'zod';
4
5
 
5
6
  /** The issue shape t3-oss hands to `onValidationError`, derived so it stays in sync with the lib. */
@@ -76,59 +77,69 @@ export function defineEnv<
76
77
  onValidationError?: (issues: ValidationIssues) => never;
77
78
  };
78
79
  }): CreateEnv<DefaultCombinedSchema<TServer, TClient, TShared>, TExtends> {
79
- const skipValidation =
80
- config.options?.skipValidation ?? (!!process.env.CI || process.env.NODE_ENV !== 'development');
80
+ type Result = CreateEnv<DefaultCombinedSchema<TServer, TClient, TShared>, TExtends>;
81
81
 
82
- // Use the caller's explicit runtimeEnv when supplied (Vite client vars via import.meta.env, or
83
- // fallback aliases). Otherwise auto-build from every declared key (server + client + shared);
84
- // createEnv tolerates keys absent from process.env (they parse as undefined → optional/default).
85
- let runtimeEnv: Record<string, string | boolean | number | undefined>;
86
- if (config.runtimeEnv) {
87
- runtimeEnv = config.runtimeEnv;
88
- } else {
89
- runtimeEnv = {};
90
- for (const key of Object.keys(config.server)) {
91
- runtimeEnv[key] = process.env[key];
92
- }
93
- for (const key of Object.keys(config.client ?? {})) {
94
- runtimeEnv[key] = process.env[key];
95
- }
96
- for (const key of Object.keys(config.shared ?? {})) {
97
- runtimeEnv[key] = process.env[key];
82
+ // LAZY by design: reading `process.env` and running validation are deferred
83
+ // to the FIRST property access, not the module import. Declaring an env is
84
+ // therefore observationally free — an app's declaration graph (features,
85
+ // adapters, `dot explain`, docs tooling) imports from a bare checkout with
86
+ // zero environment, and validation fires exactly when a value is actually
87
+ // consumed (boot, a request, a job). This is the same import/observe split
88
+ // drizzle tables have: define everywhere, observe only at use.
89
+ const build = (): Result => {
90
+ const skipValidation =
91
+ config.options?.skipValidation ?? (!!process.env.CI || process.env.NODE_ENV !== 'development');
92
+
93
+ // Use the caller's explicit runtimeEnv when supplied (Vite client vars via import.meta.env, or
94
+ // fallback aliases). Otherwise auto-build from every declared key (server + client + shared);
95
+ // createEnv tolerates keys absent from process.env (they parse as undefined → optional/default).
96
+ let runtimeEnv: Record<string, string | boolean | number | undefined>;
97
+ if (config.runtimeEnv) {
98
+ runtimeEnv = config.runtimeEnv;
99
+ } else {
100
+ runtimeEnv = {};
101
+ for (const key of Object.keys(config.server)) {
102
+ runtimeEnv[key] = process.env[key];
103
+ }
104
+ for (const key of Object.keys(config.client ?? {})) {
105
+ runtimeEnv[key] = process.env[key];
106
+ }
107
+ for (const key of Object.keys(config.shared ?? {})) {
108
+ runtimeEnv[key] = process.env[key];
109
+ }
98
110
  }
99
- }
100
111
 
101
- const onValidationError =
102
- config.options?.onValidationError ??
103
- ((issues: ValidationIssues): never => {
104
- const message = formatIssues(config.name, issues);
105
- console.error(message);
106
- throw new Error(message);
107
- });
112
+ const onValidationError =
113
+ config.options?.onValidationError ??
114
+ ((issues: ValidationIssues): never => {
115
+ const message = formatIssues(config.name, issues);
116
+ console.error(message);
117
+ throw new Error(message);
118
+ });
108
119
 
109
- // `createEnv`'s `server`/`client` params are conditional on `clientPrefix` being a *concrete*
110
- // string literal; inside a generic wrapper `TPrefix` is abstract, so the body cannot be verified
111
- // for all prefixes and the call argument must be asserted once. The PUBLIC contract stays exact:
112
- // the explicit return type above reconstructs `createEnv`'s own result from the generics, and the
113
- // caller's `server`/`client`/`extends` are fully type-checked against `TServer`/`TClient`/`TExtends`
114
- // at the call site. This is the only seam where types are asserted — value types are never widened.
115
- const options = {
116
- shared: config.shared ?? {},
117
- extends: config.extends,
118
- server: config.server,
119
- client: config.client ?? {},
120
- clientPrefix: config.clientPrefix ?? '',
121
- runtimeEnv,
122
- skipValidation,
123
- // Default ON: in containerized deploys an unset var is baked as "" (e.g. Docker `ENV X=${X}`
124
- // with no build arg), not left absent. Treating "" as undefined lets `.default()`/`.optional()`
125
- // apply as intended instead of failing format checks like `z.url()` on an empty string.
126
- emptyStringAsUndefined: config.options?.emptyStringAsUndefined ?? true,
127
- onValidationError,
128
- } satisfies Record<string, unknown>;
120
+ // `createEnv`'s `server`/`client` params are conditional on `clientPrefix` being a *concrete*
121
+ // string literal; inside a generic wrapper `TPrefix` is abstract, so the body cannot be verified
122
+ // for all prefixes and the call argument must be asserted once. The PUBLIC contract stays exact:
123
+ // the explicit return type above reconstructs `createEnv`'s own result from the generics, and the
124
+ // caller's `server`/`client`/`extends` are fully type-checked against `TServer`/`TClient`/`TExtends`
125
+ // at the call site. This is the only seam where types are asserted — value types are never widened.
126
+ const options = {
127
+ shared: config.shared ?? {},
128
+ extends: config.extends,
129
+ server: config.server,
130
+ client: config.client ?? {},
131
+ clientPrefix: config.clientPrefix ?? '',
132
+ runtimeEnv,
133
+ skipValidation,
134
+ // Default ON: in containerized deploys an unset var is baked as "" (e.g. Docker `ENV X=${X}`
135
+ // with no build arg), not left absent. Treating "" as undefined lets `.default()`/`.optional()`
136
+ // apply as intended instead of failing format checks like `z.url()` on an empty string.
137
+ emptyStringAsUndefined: config.options?.emptyStringAsUndefined ?? true,
138
+ onValidationError,
139
+ } satisfies Record<string, unknown>;
140
+
141
+ return createEnv(options as Parameters<typeof createEnv>[0]) as Result;
142
+ };
129
143
 
130
- return createEnv(options as Parameters<typeof createEnv>[0]) as CreateEnv<
131
- DefaultCombinedSchema<TServer, TClient, TShared>,
132
- TExtends
133
- >;
144
+ return lazyObject(build);
134
145
  }
package/src/dot.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * DOT adapter for `@arki/env`.
3
3
  *
4
- * Wraps `defineEnv()` as a DOT pip so a DOT app can validate its
5
- * environment alongside any other services. The pip is sync (env
4
+ * Wraps `defineEnv()` as a DOT plugin so a DOT app can validate its
5
+ * environment alongside any other services. The plugin is sync (env
6
6
  * validation is sync), so the `boot` hook returns the validated env
7
7
  * object synchronously through the standard provides channel.
8
8
  *
@@ -34,7 +34,7 @@
34
34
  * that is intentional: the adapter only makes sense in a DOT app.
35
35
  */
36
36
 
37
- import { pip, type EmptyShape, type Pip } from '@arki/dot/pip';
37
+ import { plugin, type EmptyShape, type Plugin } from '@arki/dot/plugin';
38
38
  import type { ZodType } from 'zod';
39
39
 
40
40
  import { defineEnv } from './core/define-env.js';
@@ -46,7 +46,7 @@ import { defineEnv } from './core/define-env.js';
46
46
  * resulting `app.services.env` is typed from this.
47
47
  */
48
48
  export type EnvDotOptions<TSchema extends Record<string, ZodType>> = {
49
- /** Zod schemas for each env var the pip validates. */
49
+ /** Zod schemas for each env var the plugin validates. */
50
50
  readonly schema: TSchema;
51
51
  /**
52
52
  * Forwarded to `defineEnv`. If `true`, the validator is skipped
@@ -62,15 +62,15 @@ export type EnvServices<TSchema extends Record<string, ZodType>> = {
62
62
  };
63
63
 
64
64
  /**
65
- * Build a DOT pip that validates and publishes a typed `env` service.
65
+ * Build a DOT plugin that validates and publishes a typed `env` service.
66
66
  *
67
67
  * @param options - Schema + optional config.
68
- * @returns A pip that publishes `services.env`.
68
+ * @returns A plugin that publishes `services.env`.
69
69
  */
70
70
  export function env<TSchema extends Record<string, ZodType>>(
71
71
  options: EnvDotOptions<TSchema>,
72
- ): Pip<EmptyShape, EnvServices<TSchema>> {
73
- return pip({
72
+ ): Plugin<EmptyShape, EnvServices<TSchema>> {
73
+ return plugin({
74
74
  name: 'env',
75
75
  version: '0.1.0',
76
76
  configure(ctx) {