@ayepi/env 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/dist/load.cjs ADDED
@@ -0,0 +1,40 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_dotenv = require("./dotenv.cjs");
3
+ let node_fs = require("node:fs");
4
+ let node_path = require("node:path");
5
+ //#region src/load.ts
6
+ /**
7
+ * # File loading — `@ayepi/env/load` (the only `node:fs` entry)
8
+ *
9
+ * Read `.env` and `.json` files off disk into a config **source** — a plain record you then feed
10
+ * to an env with `set(...)`. Kept separate from the core so the main entry stays filesystem-free.
11
+ *
12
+ * ```ts
13
+ * import { env } from '@ayepi/env'
14
+ * import { loadEnv } from '@ayepi/env/load'
15
+ *
16
+ * const ENV = env(schema)
17
+ * ENV.set(loadEnv({ files: ['.env', 'config.json'] })) // files win over process.env
18
+ * ENV.set({ ...loadEnv({ files: ['.env'] }), ...process.env }) // …or let process.env win
19
+ * ```
20
+ *
21
+ * @module
22
+ */
23
+ /** Read one `.env` or `.json` file into a config source. A `.json` file may carry already-typed values. */
24
+ function readEnvFile(path) {
25
+ const text = (0, node_fs.readFileSync)(path, "utf8");
26
+ return (0, node_path.extname)(path) === ".json" ? JSON.parse(text) : require_dotenv.parseDotenv(text);
27
+ }
28
+ /** Read the listed files into a single merged source (later files win). Pass the result to `set(...)`. */
29
+ function loadEnv(opts = {}) {
30
+ const out = {};
31
+ const req = opts.required;
32
+ const mustExist = (file) => req === true || Array.isArray(req) && req.includes(file);
33
+ for (const file of opts.files ?? []) if ((0, node_fs.existsSync)(file)) Object.assign(out, readEnvFile(file));
34
+ else if (mustExist(file)) throw new Error(`env file not found: ${file}`);
35
+ return out;
36
+ }
37
+ //#endregion
38
+ exports.loadEnv = loadEnv;
39
+ exports.parseDotenv = require_dotenv.parseDotenv;
40
+ exports.readEnvFile = readEnvFile;
@@ -0,0 +1,21 @@
1
+ import { r as EnvSource, t as parseDotenv } from "./dotenv.cjs";
2
+
3
+ //#region src/load.d.ts
4
+ /** Read one `.env` or `.json` file into a config source. A `.json` file may carry already-typed values. */
5
+ declare function readEnvFile(path: string): EnvSource;
6
+ /** Options for {@link loadEnv}. */
7
+ interface LoadOptions {
8
+ /** Files to read (in order, earlier is lower precedence); `.env` or `.json`. */
9
+ readonly files?: readonly string[];
10
+ /**
11
+ * Which missing files should **throw** instead of being skipped:
12
+ * - `false` / omitted — ignore every missing file (default),
13
+ * - `true` — throw if **any** listed file is missing,
14
+ * - `string[]` — throw only if one of **these specific** files is missing (others are ignored).
15
+ */
16
+ readonly required?: boolean | readonly string[];
17
+ }
18
+ /** Read the listed files into a single merged source (later files win). Pass the result to `set(...)`. */
19
+ declare function loadEnv(opts?: LoadOptions): EnvSource;
20
+ //#endregion
21
+ export { type EnvSource, LoadOptions, loadEnv, parseDotenv, readEnvFile };
package/dist/load.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { r as EnvSource, t as parseDotenv } from "./dotenv.js";
2
+
3
+ //#region src/load.d.ts
4
+ /** Read one `.env` or `.json` file into a config source. A `.json` file may carry already-typed values. */
5
+ declare function readEnvFile(path: string): EnvSource;
6
+ /** Options for {@link loadEnv}. */
7
+ interface LoadOptions {
8
+ /** Files to read (in order, earlier is lower precedence); `.env` or `.json`. */
9
+ readonly files?: readonly string[];
10
+ /**
11
+ * Which missing files should **throw** instead of being skipped:
12
+ * - `false` / omitted — ignore every missing file (default),
13
+ * - `true` — throw if **any** listed file is missing,
14
+ * - `string[]` — throw only if one of **these specific** files is missing (others are ignored).
15
+ */
16
+ readonly required?: boolean | readonly string[];
17
+ }
18
+ /** Read the listed files into a single merged source (later files win). Pass the result to `set(...)`. */
19
+ declare function loadEnv(opts?: LoadOptions): EnvSource;
20
+ //#endregion
21
+ export { type EnvSource, LoadOptions, loadEnv, parseDotenv, readEnvFile };
package/dist/load.js ADDED
@@ -0,0 +1,37 @@
1
+ import { t as parseDotenv } from "./dotenv.js";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { extname } from "node:path";
4
+ //#region src/load.ts
5
+ /**
6
+ * # File loading — `@ayepi/env/load` (the only `node:fs` entry)
7
+ *
8
+ * Read `.env` and `.json` files off disk into a config **source** — a plain record you then feed
9
+ * to an env with `set(...)`. Kept separate from the core so the main entry stays filesystem-free.
10
+ *
11
+ * ```ts
12
+ * import { env } from '@ayepi/env'
13
+ * import { loadEnv } from '@ayepi/env/load'
14
+ *
15
+ * const ENV = env(schema)
16
+ * ENV.set(loadEnv({ files: ['.env', 'config.json'] })) // files win over process.env
17
+ * ENV.set({ ...loadEnv({ files: ['.env'] }), ...process.env }) // …or let process.env win
18
+ * ```
19
+ *
20
+ * @module
21
+ */
22
+ /** Read one `.env` or `.json` file into a config source. A `.json` file may carry already-typed values. */
23
+ function readEnvFile(path) {
24
+ const text = readFileSync(path, "utf8");
25
+ return extname(path) === ".json" ? JSON.parse(text) : parseDotenv(text);
26
+ }
27
+ /** Read the listed files into a single merged source (later files win). Pass the result to `set(...)`. */
28
+ function loadEnv(opts = {}) {
29
+ const out = {};
30
+ const req = opts.required;
31
+ const mustExist = (file) => req === true || Array.isArray(req) && req.includes(file);
32
+ for (const file of opts.files ?? []) if (existsSync(file)) Object.assign(out, readEnvFile(file));
33
+ else if (mustExist(file)) throw new Error(`env file not found: ${file}`);
34
+ return out;
35
+ }
36
+ //#endregion
37
+ export { loadEnv, parseDotenv, readEnvFile };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@ayepi/env",
3
+ "version": "0.2.0",
4
+ "description": "Typed, lazy, reactive environment/config on zod — env({...}) reads process.env, records, .env/JSON files; coerces scalars and JSON-decodes complex types; computed fields, aliasing, and async/dynamic (live, subscribable) values",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ClickerMonkey/ayepi.git",
12
+ "directory": "packages/env"
13
+ },
14
+ "homepage": "https://github.com/ClickerMonkey/ayepi/tree/main/packages/env#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/ClickerMonkey/ayepi/issues"
17
+ },
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "files": [
21
+ "dist",
22
+ "ayepi-*.md"
23
+ ],
24
+ "exports": {
25
+ ".": {
26
+ "import": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "require": {
31
+ "types": "./dist/index.d.cts",
32
+ "default": "./dist/index.cjs"
33
+ }
34
+ },
35
+ "./load": {
36
+ "import": {
37
+ "types": "./dist/load.d.ts",
38
+ "default": "./dist/load.js"
39
+ },
40
+ "require": {
41
+ "types": "./dist/load.d.cts",
42
+ "default": "./dist/load.cjs"
43
+ }
44
+ },
45
+ "./package.json": "./package.json"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "peerDependencies": {
51
+ "zod": "^4"
52
+ },
53
+ "devDependencies": {
54
+ "@vitest/coverage-v8": "^2.1.8",
55
+ "publint": "^0.3.0",
56
+ "tsdown": "^0.12.0",
57
+ "vitest": "^2.1.8",
58
+ "zod": "^4.4.3"
59
+ },
60
+ "keywords": [
61
+ "ayepi",
62
+ "env",
63
+ "environment",
64
+ "config",
65
+ "dotenv",
66
+ "zod",
67
+ "configuration",
68
+ "12-factor"
69
+ ],
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "typecheck": "tsc --noEmit",
73
+ "test": "vitest run --coverage",
74
+ "publint": "publint"
75
+ }
76
+ }