celery-env 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # celery-env
2
+
3
+ <p align="center">
4
+ <img src="docs/assets/celery-mark.svg" alt="celery-env" width="96" height="96">
5
+ </p>
6
+
7
+ <p align="center">
8
+ <strong>Environment validation that compiles to tiny standalone JavaScript.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/celery-env"><img alt="npm" src="https://img.shields.io/npm/v/celery-env?color=0f766e"></a>
13
+ <a href="https://github.com/theaaravagarwal/celery-env/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/theaaravagarwal/celery-env/ci.yml?branch=main"></a>
14
+ <img alt="dependencies" src="https://img.shields.io/badge/dependencies-0-0f766e">
15
+ <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-black"></a>
16
+ </p>
17
+
18
+ Celery validates `process.env` with a schema you can read, then generates a
19
+ small validator you can ship without a runtime dependency. It is built for app
20
+ configuration: defaults, production-only secrets, typed output, good error
21
+ messages, and fast startup.
22
+
23
+ ## Install
24
+
25
+ ```sh
26
+ npm install -D celery-env
27
+ ```
28
+
29
+ Other package managers:
30
+
31
+ ```sh
32
+ pnpm add -D celery-env
33
+ yarn add -D celery-env
34
+ bun add -d celery-env
35
+ ```
36
+
37
+ ## 60-Second Setup
38
+
39
+ Create a schema:
40
+
41
+ ```js
42
+ // env.schema.mjs
43
+ import { bool, defineEnv, int, oneOf, str, url } from "celery-env";
44
+
45
+ export default defineEnv({
46
+ NODE_ENV: oneOf(["development", "test", "production"], { default: "development" }),
47
+ DATABASE_URL: url({ protocols: ["postgres"] }),
48
+ PORT: int({ default: 3000, min: 1, max: 65535 }),
49
+ DEBUG: bool({ default: false }),
50
+ SESSION_SECRET: str({
51
+ optional: true,
52
+ requiredWhen: (env) => env.NODE_ENV === "production"
53
+ })
54
+ });
55
+ ```
56
+
57
+ Generate the validator:
58
+
59
+ ```sh
60
+ npx celery-env generate \
61
+ --schema env.schema.mjs \
62
+ --out src/env.mjs \
63
+ --types src/env.d.ts \
64
+ --example .env.example \
65
+ --minify
66
+ ```
67
+
68
+ Use it at app startup:
69
+
70
+ ```js
71
+ // src/config.js
72
+ import { loadEnv } from "./env.mjs";
73
+
74
+ export const env = loadEnv(process.env);
75
+ ```
76
+
77
+ That is the main path: write `env.schema.mjs`, generate `src/env.mjs`, and use
78
+ the typed result everywhere else.
79
+
80
+ ## When To Use Celery
81
+
82
+ Use Celery when you want env validation to be:
83
+
84
+ - focused on app configuration instead of general object validation;
85
+ - generated once and cheap at startup;
86
+ - dependency-free in production;
87
+ - typed without hand-written config types;
88
+ - strict about missing production secrets without printing secret values.
89
+
90
+ If you already use Zod for forms, API payloads, or general data validation,
91
+ keep using it there. Celery is for the narrower `process.env` problem where
92
+ defaults, examples, generated files, and startup cost matter.
93
+
94
+ ## Why Use It
95
+
96
+ - **Generated validator**: no schema walk during app startup.
97
+ - **Zero runtime dependencies** in generated mode.
98
+ - **Small output**: the measured small generated validator is 526 gzip bytes.
99
+ - **Typed config** through generated `.d.ts` files or `InferEnv`.
100
+ - **Env-specific rules** like `devDefault`, `testDefault`, and `requiredWhen`.
101
+ - **Secret-safe errors** that do not print rejected secret values.
102
+ - **Runtime mode** available when you do not want a build step.
103
+
104
+ ## Runtime Mode
105
+
106
+ Generated mode is recommended for apps, but direct parsing is available:
107
+
108
+ ```js
109
+ import { defineEnv, int, parseEnv, str } from "celery-env";
110
+
111
+ const schema = defineEnv({
112
+ DATABASE_URL: str({ min: 1 }),
113
+ PORT: int({ default: 3000 })
114
+ });
115
+
116
+ export const env = parseEnv(schema, process.env);
117
+ ```
118
+
119
+ ## Benchmarks
120
+
121
+ Current report: Node v26.3.0, macOS arm64, Apple M3.
122
+
123
+ | Metric | Result |
124
+ | --- | ---: |
125
+ | Valid real-schema geometric mean | 1.50x over best external competitor |
126
+ | Real `process.env` geometric mean | 1.14x over best external competitor |
127
+ | Invalid real-schema geometric mean | 1.32x over best external competitor |
128
+ | Cold first validation | 2.42x faster than best external competitor |
129
+ | Generated validator size | 526 gzip bytes |
130
+ | Smallest external bundle gap | 2.15x smaller |
131
+
132
+ Competitors measured include Zod, Valibot, Envalid, Envsafe, env-var, T3 Env
133
+ Core, Valienv, env-schema, env-type-validator, safe-env-vars, and Convict where
134
+ the benchmark applies. The claim is specific to this env-validation corpus.
135
+
136
+ ## Documentation
137
+
138
+ - [Getting Started](docs/GETTING_STARTED.md)
139
+ - [Schema API](docs/SCHEMA.md)
140
+ - [CLI](docs/CLI.md)
141
+ - [TypeScript](docs/TYPESCRIPT.md)
142
+ - [Runtime Mode](docs/RUNTIME.md)
143
+ - [Comparison](docs/COMPARISON.md)
144
+ - [Troubleshooting](docs/TROUBLESHOOTING.md)
145
+ - [Benchmarks](docs/BENCHMARKS.md)
146
+ - [Migration Guide](docs/MIGRATION.md)
147
+ - [Security](SECURITY.md)
148
+
149
+ ## License
150
+
151
+ MIT
package/SECURITY.md ADDED
@@ -0,0 +1,75 @@
1
+ # Security
2
+
3
+ `celery-env` is designed to keep the published package small and auditable:
4
+
5
+ - The root package has zero runtime dependencies.
6
+ - The package has no consumer install hooks or pack hooks. Its only publish
7
+ lifecycle script is `prepublishOnly`, which runs the local verification gate.
8
+ - Runtime validation does not include rejected environment values in error messages.
9
+ - Generated validators escape schema keys and validate generated function names.
10
+ - Environment reads require own properties, so inherited object-prototype keys do
11
+ not masquerade as environment variables.
12
+ - Generated `requiredWhen` predicates receive an own-property environment facade
13
+ instead of the raw inherited object.
14
+ - `__proto__` schema keys are treated as data properties instead of prototype mutation.
15
+ - Publish validation uses `npm pack --ignore-scripts`; local hardening checks
16
+ reject consumer install hooks, pack hooks, and unexpected publish hooks.
17
+ - CLI generation refuses symlink outputs and only overwrites existing generated
18
+ files when `--force` is passed.
19
+
20
+ ## Audit Commands
21
+
22
+ Run the local hardening checks before publishing:
23
+
24
+ ```sh
25
+ npm run security:scan
26
+ ```
27
+
28
+ The root package intentionally has no lockfile because it has no dependencies.
29
+ `npm audit` requires a lockfile, so root-package supply-chain checks are covered
30
+ by `scripts/security-scan.mjs` and `scripts/validate-publish.mjs`.
31
+
32
+ CI runs the same root hardening scan on Node 18, 20, 22, and 26.
33
+
34
+ ## Hardening Findings
35
+
36
+ The dependency audit did not find known vulnerable packages. The hardening pass
37
+ did find code-level weakness classes before release, and they are now covered by
38
+ tests:
39
+
40
+ - Prototype-polluted option objects could make missing values optional or inject
41
+ defaults. Specs now use null-prototype rule objects and own-property checks.
42
+ - `requiredWhen` predicates could observe inherited env properties. Predicates
43
+ now receive an own-property env facade.
44
+ - Generated `json()` validation could be bypassed through inherited
45
+ object/array keys. JSON parse success no longer depends on target-slot
46
+ sentinel values.
47
+ - Generated function names missed some strict-mode forbidden identifiers. Those
48
+ names are now rejected.
49
+ - Non-expression `requiredWhen` functions could emit invalid generated code.
50
+ They are now rejected at generation time.
51
+ - Non-JSON-stable `json()` defaults could diverge between runtime and generated
52
+ validators. They are now rejected for generated output.
53
+ - CLI generation could overwrite requested output paths. It now requires
54
+ `--force` and refuses symlink outputs.
55
+
56
+ ## Trust Boundary
57
+
58
+ Schema files and `requiredWhen` predicates are application code. The CLI imports
59
+ the schema file you pass with `--schema`, and generated validators serialize
60
+ `requiredWhen` function source. Only run generation against schema files and
61
+ predicates you trust; do not generate validators from untrusted schema packages.
62
+
63
+ Generated `.env.example` output is documentation. It escapes unsafe key/value
64
+ line breaks, but it still reflects schema-provided `example`, `default`,
65
+ `devDefault`, `testDefault`, `desc`, and `docs` metadata. Do not put real
66
+ secrets in schema defaults or examples that you plan to publish.
67
+
68
+ ## Reporting
69
+
70
+ Report security issues privately through GitHub Security Advisories:
71
+
72
+ https://github.com/theaaravagarwal/celery-env/security/advisories/new
73
+
74
+ Include a minimal reproduction, the affected version, and whether the issue
75
+ affects runtime validation, generated validators, or CLI generation.
@@ -0,0 +1,44 @@
1
+ # Benchmarks
2
+
3
+ Benchmark dependencies are kept out of the root package so `celery-env` stays
4
+ dependency-free. The public package ships the headline report and claim rules,
5
+ not the local benchmark lab.
6
+
7
+ ## Current Headline
8
+
9
+ Current report: Node v26.3.0, macOS arm64, Apple M3.
10
+
11
+ | Metric | Result |
12
+ | --- | ---: |
13
+ | Valid real-schema geometric mean | 1.50x over best external competitor |
14
+ | Real `process.env` geometric mean | 1.14x over best external competitor |
15
+ | Invalid real-schema geometric mean | 1.32x over best external competitor |
16
+ | Cold first validation | 2.42x faster than best external competitor |
17
+ | Generated validator size | 526 gzip bytes |
18
+ | Smallest external bundle gap | 2.15x smaller |
19
+
20
+ ## What Is Measured
21
+
22
+ - Synthetic small, medium, and large schemas.
23
+ - Realistic API, web, worker, list-heavy, and JSON-heavy env schemas.
24
+ - Frozen plain env objects and real `process.env`.
25
+ - Invalid input with aggregate errors.
26
+ - Cold import/setup/first validation.
27
+ - Shipped gzip bundle size.
28
+
29
+ ## Competitors
30
+
31
+ The benchmark corpus includes Zod, Valibot, Envalid, Envsafe, env-var, T3 Env
32
+ Core, Valienv, env-schema, env-type-validator, safe-env-vars, and Convict where
33
+ the benchmark applies.
34
+
35
+ ## Claim Rules
36
+
37
+ Use precise benchmark claims:
38
+
39
+ - Good: "1.50x over the best external competitor on the real-schema corpus."
40
+ - Good: "526 gzip bytes for the measured small generated validator."
41
+ - Avoid: "Celery is always 50x faster."
42
+
43
+ Env validation is workload-dependent, especially when reading real
44
+ `process.env`.
package/docs/CLI.md ADDED
@@ -0,0 +1,68 @@
1
+ # CLI
2
+
3
+ The CLI creates schemas and generated validator files.
4
+
5
+ ## Initialize A Schema
6
+
7
+ ```sh
8
+ npx celery-env init --target node --schema env.schema.mjs
9
+ ```
10
+
11
+ Use `init` when starting from scratch. It writes a small schema with common
12
+ Node app variables.
13
+
14
+ Targets:
15
+
16
+ | Target | Use For |
17
+ | --- | --- |
18
+ | `node` | Regular Node apps and services. |
19
+ | `next` | Next.js projects. |
20
+ | `vite` | Vite projects and edge-style environments. |
21
+
22
+ ## Generate
23
+
24
+ ```sh
25
+ npx celery-env generate \
26
+ --schema env.schema.mjs \
27
+ --out src/env.mjs \
28
+ --types src/env.d.ts \
29
+ --example .env.example
30
+ ```
31
+
32
+ Use `generate` after editing `env.schema.mjs`.
33
+
34
+ ## Flags
35
+
36
+ | Flag | Meaning |
37
+ | --- | --- |
38
+ | `--schema <file>` | Schema module to import. |
39
+ | `--out <file>` | Generated validator output path. |
40
+ | `--types <file>` | Generated `.d.ts` output path. |
41
+ | `--example <file>` | Generated `.env.example` output path. |
42
+ | `--function-name <name>` | Generated function name. Default: `loadEnv`. |
43
+ | `--no-process-default` | Do not default to `process.env` in generated output. |
44
+ | `--minify` | Emit smaller generated JavaScript. |
45
+ | `--fail-fast` | Throw on the first error instead of aggregating errors. |
46
+ | `--force` | Overwrite existing generated files. |
47
+ | `--optimize speed` | Emit larger speed-prioritized code for supported cases. |
48
+
49
+ ## Recommended App Command
50
+
51
+ Add a script:
52
+
53
+ ```json
54
+ {
55
+ "scripts": {
56
+ "env:generate": "celery-env generate --schema env.schema.mjs --out src/env.mjs --types src/env.d.ts --example .env.example --minify"
57
+ }
58
+ }
59
+ ```
60
+
61
+ Run it whenever the schema changes:
62
+
63
+ ```sh
64
+ npm run env:generate
65
+ ```
66
+
67
+ Generated files are regular source files. Commit them when you want production
68
+ deployments to run without the generator.
@@ -0,0 +1,58 @@
1
+ # Comparison
2
+
3
+ Celery is not a replacement for general validation libraries. It is a focused
4
+ tool for environment configuration.
5
+
6
+ ## Celery vs Zod
7
+
8
+ Zod is excellent for general TypeScript validation: forms, API payloads,
9
+ domain objects, JSON data, and reusable schemas across an app.
10
+
11
+ Celery is narrower. It validates `process.env`, then can generate a standalone
12
+ validator and declaration file for production startup.
13
+
14
+ | Question | Celery | Zod |
15
+ | --- | --- | --- |
16
+ | Main job | Validate env config. | Validate general data. |
17
+ | Schema shape | One key per env var. | Any object/data shape. |
18
+ | Generated validator | Yes. | No. |
19
+ | Production runtime dependency | None in generated mode. | `zod`. |
20
+ | `.env.example` generation | Built in. | Build yourself. |
21
+ | Env-specific defaults | Built in. | Build yourself. |
22
+ | Secret-safe env errors | Built in. | Build yourself. |
23
+ | Ecosystem size | Small and focused. | Large and mature. |
24
+
25
+ Use Zod when you need general validation. Use Celery when the thing being
26
+ validated is application configuration.
27
+
28
+ ## Celery vs Envalid / Envsafe / env-var
29
+
30
+ These libraries are purpose-built for env validation and are good defaults for
31
+ runtime validation.
32
+
33
+ Celery's main difference is generated mode:
34
+
35
+ - the schema stays in development code;
36
+ - the generated validator can be committed;
37
+ - production can run without loading the schema library;
38
+ - TypeScript declarations can be generated from the same schema;
39
+ - `.env.example` can be generated from schema metadata.
40
+
41
+ ## Choosing A Mode
42
+
43
+ | Use Case | Recommended Mode |
44
+ | --- | --- |
45
+ | Production app or service | Generated |
46
+ | Serverless or cold-start-sensitive app | Generated |
47
+ | CLI script or small internal tool | Runtime |
48
+ | Prototype before deciding schema shape | Runtime |
49
+ | App with no build/generate step allowed | Runtime |
50
+
51
+ ## What Celery Does Not Do
52
+
53
+ - It does not load `.env` files. Use your platform, shell, or a dotenv loader.
54
+ - It does not validate arbitrary request bodies or form data.
55
+ - It does not validate the internal shape of `json()` values.
56
+ - It does not make untrusted schema files safe to execute.
57
+
58
+ Schema files are application code.
@@ -0,0 +1,134 @@
1
+ # Getting Started
2
+
3
+ This guide assumes you have a Node project and want one reliable place to define
4
+ environment variables.
5
+
6
+ ## 1. Install
7
+
8
+ ```sh
9
+ npm install -D celery-env
10
+ ```
11
+
12
+ ```sh
13
+ pnpm add -D celery-env
14
+ yarn add -D celery-env
15
+ bun add -d celery-env
16
+ ```
17
+
18
+ Use a dev dependency when you generate validators. The generated output has no
19
+ runtime dependency on `celery-env`.
20
+
21
+ ## 2. Create A Schema
22
+
23
+ Create `env.schema.mjs` in your project root:
24
+
25
+ ```js
26
+ import { bool, defineEnv, int, oneOf, str, url } from "celery-env";
27
+
28
+ export default defineEnv({
29
+ NODE_ENV: oneOf(["development", "test", "production"], {
30
+ default: "development"
31
+ }),
32
+
33
+ DATABASE_URL: url({
34
+ protocols: ["postgres"]
35
+ }),
36
+
37
+ PORT: int({
38
+ default: 3000,
39
+ min: 1,
40
+ max: 65535
41
+ }),
42
+
43
+ DEBUG: bool({
44
+ default: false
45
+ }),
46
+
47
+ SESSION_SECRET: str({
48
+ optional: true,
49
+ requiredWhen: (env) => env.NODE_ENV === "production",
50
+ desc: "Required in production."
51
+ })
52
+ });
53
+ ```
54
+
55
+ ## 3. Generate The Validator
56
+
57
+ ```sh
58
+ npx celery-env generate \
59
+ --schema env.schema.mjs \
60
+ --out src/env.mjs \
61
+ --types src/env.d.ts \
62
+ --example .env.example \
63
+ --minify
64
+ ```
65
+
66
+ This creates:
67
+
68
+ | File | Purpose |
69
+ | --- | --- |
70
+ | `src/env.mjs` | Runtime validator used by your app. |
71
+ | `src/env.d.ts` | Types for editors and TypeScript. |
72
+ | `.env.example` | Documented env template. |
73
+
74
+ Add the command to `package.json` so the workflow is repeatable:
75
+
76
+ ```json
77
+ {
78
+ "scripts": {
79
+ "env:generate": "celery-env generate --schema env.schema.mjs --out src/env.mjs --types src/env.d.ts --example .env.example --minify"
80
+ }
81
+ }
82
+ ```
83
+
84
+ ## 4. Load Env Once
85
+
86
+ ```js
87
+ import { loadEnv } from "./env.mjs";
88
+
89
+ export const env = loadEnv(process.env);
90
+ ```
91
+
92
+ Use `env` everywhere else instead of reading `process.env` directly.
93
+
94
+ ## 5. Use A Nested App Config
95
+
96
+ If your app already expects a nested config object, keep the generated env flat
97
+ and adapt it in one small file:
98
+
99
+ ```js
100
+ import { loadEnv } from "./env.mjs";
101
+
102
+ export function loadConfig(source = process.env) {
103
+ const env = loadEnv(source);
104
+
105
+ return {
106
+ app: {
107
+ nodeEnv: env.NODE_ENV,
108
+ port: env.PORT
109
+ },
110
+ database: {
111
+ url: env.DATABASE_URL
112
+ }
113
+ };
114
+ }
115
+ ```
116
+
117
+ ## What To Commit
118
+
119
+ For most apps, commit all of these:
120
+
121
+ - `env.schema.mjs`
122
+ - `src/env.mjs`
123
+ - `src/env.d.ts`
124
+ - `.env.example`
125
+
126
+ Committing generated files keeps deployments simple because production does not
127
+ need to run the generator.
128
+
129
+ ## Next Steps
130
+
131
+ - Read [Schema API](SCHEMA.md) when adding validators.
132
+ - Read [TypeScript](TYPESCRIPT.md) if editor types do not look right.
133
+ - Read [Troubleshooting](TROUBLESHOOTING.md) if generation or URL validation
134
+ fails.
@@ -0,0 +1,54 @@
1
+ # Migration Guide
2
+
3
+ Use this guide when adding Celery to an existing app.
4
+
5
+ ## Step 1. Find Env Reads
6
+
7
+ Search for direct env access:
8
+
9
+ ```sh
10
+ rg "process\\.env|env\\.[A-Z_]+"
11
+ ```
12
+
13
+ The goal is one central module that reads env and exports validated config.
14
+
15
+ ## Step 2. Write A Flat Schema
16
+
17
+ Keep schema keys close to actual env var names:
18
+
19
+ ```js
20
+ import { defineEnv, int, oneOf, url } from "celery-env";
21
+
22
+ export default defineEnv({
23
+ NODE_ENV: oneOf(["development", "test", "production"], { default: "development" }),
24
+ DATABASE_URL: url({ protocols: ["postgres"] }),
25
+ PORT: int({ default: 3000 })
26
+ });
27
+ ```
28
+
29
+ ## Step 3. Generate
30
+
31
+ ```sh
32
+ npx celery-env generate --schema env.schema.mjs --out src/env.mjs --types src/env.d.ts --example .env.example --minify
33
+ ```
34
+
35
+ ## Step 4. Keep Your Existing Shape
36
+
37
+ If your app already expects nested config, adapt once:
38
+
39
+ ```js
40
+ import { loadEnv } from "./env.mjs";
41
+
42
+ export function loadConfig(source = process.env) {
43
+ const env = loadEnv(source);
44
+
45
+ return {
46
+ app: { port: env.PORT },
47
+ database: { url: env.DATABASE_URL }
48
+ };
49
+ }
50
+ ```
51
+
52
+ ## Step 5. Remove Direct Env Reads
53
+
54
+ Use the validated config everywhere else.
package/docs/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # celery-env Documentation
2
+
3
+ Start here if you are new to Celery or new to typed env validation.
4
+
5
+ ## Learning Path
6
+
7
+ 1. [Getting Started](GETTING_STARTED.md): install, write a schema, generate a validator.
8
+ 2. [Schema API](SCHEMA.md): every validator and option.
9
+ 3. [CLI](CLI.md): `init`, `generate`, and generation flags.
10
+ 4. [TypeScript](TYPESCRIPT.md): generated types and `InferEnv`.
11
+ 5. [Runtime Mode](RUNTIME.md): use Celery without generation.
12
+ 6. [Comparison](COMPARISON.md): when to use Celery instead of general validators.
13
+ 7. [Troubleshooting](TROUBLESHOOTING.md): common setup and generation issues.
14
+ 8. [Migration Guide](MIGRATION.md): add Celery to an existing project.
15
+ 9. [Benchmarks](BENCHMARKS.md): what is measured and what claims are safe.
@@ -0,0 +1,43 @@
1
+ # Runtime Mode
2
+
3
+ Runtime mode validates with `parseEnv(schema, env)` directly. Use it when:
4
+
5
+ - You do not want generated files.
6
+ - Your app is small and startup cost is not critical.
7
+ - You are prototyping before switching to generated mode.
8
+
9
+ ## Example
10
+
11
+ ```js
12
+ import { defineEnv, int, parseEnv, str } from "celery-env";
13
+
14
+ const schema = defineEnv({
15
+ DATABASE_URL: str({ min: 1 }),
16
+ PORT: int({ default: 3000 })
17
+ });
18
+
19
+ export const env = parseEnv(schema, process.env);
20
+ ```
21
+
22
+ ## Tradeoff
23
+
24
+ Runtime mode is simpler, but generated mode is usually faster and can avoid a
25
+ runtime dependency in production.
26
+
27
+ | Mode | Build Step | Runtime Dependency | Best For |
28
+ | --- | --- | --- | --- |
29
+ | Generated | yes | no | production apps |
30
+ | Runtime | no | yes | small apps, scripts, prototypes |
31
+
32
+ ## Errors
33
+
34
+ Celery aggregates errors by default:
35
+
36
+ ```text
37
+ Invalid environment:
38
+ - DATABASE_URL is required
39
+ - PORT must be an integer
40
+ ```
41
+
42
+ Rejected values are not included in error messages, which helps avoid leaking
43
+ secrets.