@g14o/env-core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,13 +21,13 @@ import { createEnv } from "@g14o/env-core";
21
21
  import * as z from "zod";
22
22
 
23
23
  export const env = createEnv({
24
- clientPrefix: "NEXT_PUBLIC_",
24
+ clientPrefix: "PUBLIC_",
25
25
  server: {
26
26
  DATABASE_URL: z.url(),
27
27
  OPEN_AI_API_KEY: z.string().min(1),
28
28
  },
29
29
  client: {
30
- NEXT_PUBLIC_API_URL: z.url(),
30
+ PUBLIC_API_URL: z.url(),
31
31
  },
32
32
  runtimeEnv: process.env,
33
33
  emptyStringAsUndefined: true,
@@ -34,35 +34,143 @@ declare namespace StandardSchemaV1 {
34
34
  }
35
35
  //#endregion
36
36
  //#region src/types.d.ts
37
+ /**
38
+ * Record mapping environment variable names to
39
+ * [Standard Schema v1](https://standardschema.dev) validators (Zod, Valibot, ArkType, and others).
40
+ *
41
+ * Used for both `server` and `client` shapes in {@link CreateEnvOptions}.
42
+ */
37
43
  type SchemaShape = Record<string, StandardSchemaV1>;
44
+ /**
45
+ * Raw value that may appear in a runtime environment source before schema validation.
46
+ *
47
+ * Values from `process.env` and bundler-inlined mappings are always strings at runtime;
48
+ * schemas coerce them to the declared output types.
49
+ */
38
50
  type RuntimeEnvValue = string | number | boolean | undefined | null;
51
+ /**
52
+ * Loose record passed as `runtimeEnv`.
53
+ *
54
+ * Extra keys are allowed; only keys declared in `server` and `client` shapes are picked
55
+ * and validated.
56
+ */
39
57
  type RuntimeEnvInput = Record<string, RuntimeEnvValue>;
58
+ /**
59
+ * Flattens intersection types into a single object type for readable IDE hovers.
60
+ *
61
+ * @typeParam T - Object type to simplify.
62
+ */
40
63
  type Simplify<T> = { [K in keyof T]: T[K] } & {};
64
+ /**
65
+ * Extracts the output type from a single Standard Schema validator.
66
+ *
67
+ * @typeParam TSchema - A Standard Schema v1 validator.
68
+ */
41
69
  type InferSchemaOutput<TSchema extends StandardSchemaV1> = TSchema extends StandardSchemaV1<unknown, infer TOutput> ? TOutput : never;
70
+ /**
71
+ * Maps a {@link SchemaShape} to an object of inferred output types.
72
+ *
73
+ * @typeParam TShape - Server or client schema shape.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import type { InferShapeOutput, SchemaShape } from "@g14o/env-core";
78
+ * import * as z from "zod";
79
+ *
80
+ * const shape = {
81
+ * DATABASE_URL: z.url(),
82
+ * PORT: z.coerce.number(),
83
+ * } satisfies SchemaShape;
84
+ *
85
+ * type Env = InferShapeOutput<typeof shape>;
86
+ * // { DATABASE_URL: string; PORT: number }
87
+ * ```
88
+ */
42
89
  type InferShapeOutput<TShape extends SchemaShape> = Simplify<{ [K in keyof TShape]: InferSchemaOutput<TShape[K]> }>;
90
+ /** @internal Resolves whether a client key matches the required prefix. */
43
91
  type ClientKeyWithPrefix<TPrefix extends string, TKey extends PropertyKey> = TKey extends `${TPrefix}${string}` ? TKey : never;
92
+ /**
93
+ * Subset of a client shape containing only keys that start with `clientPrefix`.
94
+ *
95
+ * @typeParam TPrefix - Required prefix (e.g. `"NEXT_PUBLIC_"`).
96
+ * @typeParam TClient - Client schema shape before prefix filtering.
97
+ */
44
98
  type PrefixedClientShape<TPrefix extends string, TClient extends SchemaShape> = Simplify<{ [K in keyof TClient as ClientKeyWithPrefix<TPrefix, K>]: TClient[K] }>;
99
+ /**
100
+ * Client keys that do not start with the required `clientPrefix`.
101
+ *
102
+ * When this type is not `never`, {@link AssertValidClientPrefix} produces a compile-time error.
103
+ *
104
+ * @typeParam TPrefix - Required prefix (e.g. `"NEXT_PUBLIC_"`).
105
+ * @typeParam TClient - Client schema shape to check.
106
+ */
45
107
  type InvalidClientKeys<TPrefix extends string, TClient extends SchemaShape> = Exclude<keyof TClient, `${TPrefix}${string}`>;
108
+ /**
109
+ * Compile-time check that every `client` key uses `clientPrefix`.
110
+ *
111
+ * Intersected into {@link CreateEnvOptions} on `createEnv` calls. When invalid keys exist,
112
+ * TypeScript reports an error on the call site (not a runtime throw).
113
+ *
114
+ * @typeParam TPrefix - Required prefix when `clientPrefix` is set.
115
+ * @typeParam TClient - Client schema shape to validate.
116
+ */
46
117
  type AssertValidClientPrefix<TPrefix extends string | undefined, TClient extends SchemaShape | undefined> = TPrefix extends string ? TClient extends SchemaShape ? InvalidClientKeys<TPrefix, TClient> extends never ? unknown : `Client environment variable(s) must start with "${TPrefix}": ${InvalidClientKeys<TPrefix, TClient> & string}` : unknown : unknown;
118
+ /**
119
+ * @internal Effective client shape after applying an optional `clientPrefix`.
120
+ */
47
121
  type ResolveClientShape<TPrefix extends string | undefined, TClient extends SchemaShape | undefined> = TClient extends SchemaShape ? TPrefix extends string ? PrefixedClientShape<TPrefix, TClient> : TClient : Record<string, never>;
122
+ /** @internal Extracts keys from an optional schema shape, or `never` when undefined. */
48
123
  type ShapeKeys<TShape extends SchemaShape | undefined> = TShape extends SchemaShape ? keyof TShape : never;
124
+ /**
125
+ * Explicit per-key runtime mapping required by `runtimeEnvStrict`.
126
+ *
127
+ * Must include every key from `server` and `client` shapes. Used by bundlers that only
128
+ * inline env vars you reference explicitly.
129
+ *
130
+ * @typeParam TServer - Server schema shape.
131
+ * @typeParam TClient - Client schema shape.
132
+ */
49
133
  type StrictRuntimeEnv<TServer extends SchemaShape | undefined, TClient extends SchemaShape | undefined> = Simplify<{ [K in ShapeKeys<TServer> | ShapeKeys<TClient>]: RuntimeEnvValue }>;
134
+ /** @internal Union requiring exactly one of two option groups (XOR). */
50
135
  type MutuallyExclusive<A extends Record<string, unknown>, B extends Record<string, unknown>> = (A & { [K in keyof B]?: never }) | (B & { [K in keyof A]?: never });
136
+ /** @internal Enforces that `runtimeEnv` and `runtimeEnvStrict` cannot both be set. */
51
137
  type RuntimeEnvSource<TServer extends SchemaShape | undefined, TClient extends SchemaShape | undefined> = MutuallyExclusive<{
52
- runtimeEnv: RuntimeEnvInput;
138
+ /** Loose record to read values from (e.g. `process.env`). Extra keys are allowed. */runtimeEnv: RuntimeEnvInput;
53
139
  }, {
54
- runtimeEnvStrict: StrictRuntimeEnv<TServer, TClient>;
140
+ /** Explicit per-key mapping; mutually exclusive with `runtimeEnv`. */runtimeEnvStrict: StrictRuntimeEnv<TServer, TClient>;
55
141
  }>;
142
+ /**
143
+ * Merges `server` and `client` schema shapes for output type inference.
144
+ *
145
+ * @typeParam TServer - Server schema shape.
146
+ * @typeParam TClient - Client schema shape.
147
+ */
56
148
  type MergeEnvShapes<TServer extends SchemaShape | undefined, TClient extends SchemaShape | undefined> = (TServer extends SchemaShape ? TServer : Record<string, never>) & (TClient extends SchemaShape ? TClient : Record<string, never>);
149
+ /**
150
+ * Options passed to `createEnv`. Server and client shapes are validated separately;
151
+ * runtime values come from exactly one of `runtimeEnv` or `runtimeEnvStrict`.
152
+ *
153
+ * @typeParam TServer - Server-only schema shape.
154
+ * @typeParam TClient - Client-safe schema shape.
155
+ * @typeParam TPrefix - Required prefix for all `client` keys when `clientPrefix` is set.
156
+ */
57
157
  type CreateEnvOptions<TServer extends SchemaShape | undefined = undefined, TClient extends SchemaShape | undefined = undefined, TPrefix extends string | undefined = undefined> = {
58
- server?: TServer;
59
- client?: TClient;
60
- clientPrefix?: TPrefix;
61
- emptyStringAsUndefined?: boolean;
62
- isServer?: boolean;
63
- onInvalidAccess?: OnInvalidAccessHandler; /** @internal */
158
+ /** Server-only variables; validated only when `isServer` is true. */server?: TServer; /** Variables safe on the client; always validated unless `skipValidation`. */
159
+ client?: TClient; /** Prefix every `client` key must use (enforced at compile time and runtime). */
160
+ clientPrefix?: TPrefix; /** Treat `""` as `undefined` before validation. Default `false`. */
161
+ emptyStringAsUndefined?: boolean; /** Override server detection. Default: no `window` on `globalThis`. */
162
+ isServer?: boolean; /** Called before throwing when a non-client key is read on the client. */
163
+ onInvalidAccess?: OnInvalidAccessHandler; /** @internal Skip schema validation and return picked runtime values only. */
64
164
  skipValidation?: boolean;
65
165
  } & RuntimeEnvSource<TServer, TClient>;
166
+ /**
167
+ * Readonly, inferred environment object returned by `createEnv`.
168
+ *
169
+ * Output types are derived from {@link MergeEnvShapes} via {@link InferShapeOutput}.
170
+ *
171
+ * @typeParam TServer - Server schema shape.
172
+ * @typeParam TClient - Client schema shape.
173
+ */
66
174
  type CreateEnvOutput<TServer extends SchemaShape | undefined, TClient extends SchemaShape | undefined> = Readonly<InferShapeOutput<MergeEnvShapes<TServer, TClient>>>;
67
175
  //#endregion
68
176
  //#region src/create-env.d.ts
@@ -106,7 +214,7 @@ type CreateEnvOutput<TServer extends SchemaShape | undefined, TClient extends Sc
106
214
  * PUBLIC_API_URL: z.url(),
107
215
  * PUBLIC_APP_NAME: z.string().min(1),
108
216
  * },
109
- * runtimeEnvStrict: runtimeEnvStrict(),
217
+ * runtimeEnv: process.env,
110
218
  * emptyStringAsUndefined: true,
111
219
  * });
112
220
  * ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@g14o/env-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Framework-agnostic, typesafe environment variables via Standard Schema (Zod, Valibot, ArkType).",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -47,10 +47,21 @@
47
47
  "zod": "^4.0.0",
48
48
  "@workspace/typescript-config": "0.0.0"
49
49
  },
50
+ "main": "./dist/index.mjs",
51
+ "module": "./dist/index.mjs",
52
+ "types": "./dist/index.d.mts",
50
53
  "exports": {
51
54
  ".": {
52
- "types": "./dist/index.d.ts",
53
- "import": "./dist/index.js"
55
+ "dev-source": "./src/index.ts",
56
+ "types": "./dist/index.d.mts",
57
+ "default": "./dist/index.mjs"
58
+ }
59
+ },
60
+ "typesVersions": {
61
+ "*": {
62
+ "*": [
63
+ "./dist/index.d.mts"
64
+ ]
54
65
  }
55
66
  },
56
67
  "publishConfig": {
File without changes