@sebspark/environment 0.1.3 → 0.1.5

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @sebspark/environment
2
2
 
3
+ ## 0.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 176ea40: `initEnvironment`, its `optional` view and `initSecretStore` now return `undefined` for symbol keys instead of throwing a `TypeError`, so the proxies can be inspected and logged. `initSecretStore` now treats a fallback entry that is explicitly `undefined` as missing and throws `Secret <KEY> is required`, instead of returning `undefined`.
8
+
9
+ ## 0.1.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 9f44fbd: Updated dependencies
14
+
3
15
  ## 0.1.3
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- //#region src/index.d.ts
2
1
  export declare const initEnvironment: <T extends Record<string, string>>() => T & {
3
2
  optional: Partial<T>;
4
3
  } & {
@@ -12,5 +11,5 @@ type SecretStoreOptions<T> = {
12
11
  export declare const initSecretStore: <T extends Record<string, string>>(opts?: SecretStoreOptions<T>) => T & {
13
12
  [key: string]: string;
14
13
  };
15
- //#endregion
14
+ export {};
16
15
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";qBAIa,kBAAmB,UAAU,6BAiCnC;EAAM,UAAU,QAAQ;;GAAU;;qBAG5B,oBACX,UAAU,wBACV,UAAU,wBAAsB,KAE3B,GAAC,SACG,MACR,IAAI;KAYF,mBAAmB;EACtB;EACA,qBAAqB,QAAQ;;qBAGlB,kBAAmB,UAAU,wBAAsB,OACvD,mBAAmB,OAwCrB;GAAO"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"A,qBAIa,kBAAmB,UAAU,6BAmCnC;EAAM,UAAU,QAAQ;;GAAU;;qBAG5B,oBACX,UAAU,wBACV,UAAU,wBAAsB,KAE3B,GAAC,SACG,MACR,IAAI;KAaF,mBAAmB;EACtB;EACA,qBAAqB,QAAQ;;qBAGlB,kBAAmB,UAAU,wBAAsB,OACvD,mBAAmB,OA4CrB;GAAO"}
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import assert from "node:assert";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
- //#region src/index.ts
4
+ // src/index.ts
5
5
  const initEnvironment = () => {
6
6
  const environmentCache = {};
7
- return new Proxy({}, { get(_, k) {
8
- const key = k;
9
- if (key === "optional") return new Proxy({}, { get(_, k) {
10
- const key = k;
7
+ return new Proxy({}, { get(_, key) {
8
+ if (typeof key !== "string") return void 0;
9
+ if (key === "optional") return new Proxy({}, { get(_, key) {
10
+ if (typeof key !== "string") return void 0;
11
11
  if (key in environmentCache) return environmentCache[key];
12
12
  const { [key]: value } = process.env;
13
13
  environmentCache[key] = value;
@@ -31,8 +31,8 @@ const mergeEnvironments = (env, secrets) => new Proxy({}, { get(_, key) {
31
31
  const initSecretStore = (opts) => {
32
32
  const secretCache = {};
33
33
  const { dir, fallback } = opts ?? {};
34
- return new Proxy({}, { get(_, k) {
35
- const key = k;
34
+ return new Proxy({}, { get(_, key) {
35
+ if (typeof key !== "string") return void 0;
36
36
  if (key in secretCache) return secretCache[key];
37
37
  const filePath = dir ? join(dir, key) : key;
38
38
  try {
@@ -46,14 +46,16 @@ const initSecretStore = (opts) => {
46
46
  secretCache[key] = value;
47
47
  return secretCache[key];
48
48
  }
49
- } else if (fallback && key in fallback) {
50
- secretCache[key] = fallback[key];
51
- return secretCache[key];
49
+ } else if (fallback) {
50
+ const value = fallback[key];
51
+ if (value !== void 0) {
52
+ secretCache[key] = value;
53
+ return secretCache[key];
54
+ }
52
55
  }
53
56
  throw new Error(`Secret ${key} is required`);
54
57
  } });
55
58
  };
56
- //#endregion
57
59
  export { initEnvironment, initSecretStore, mergeEnvironments };
58
60
 
59
61
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import assert from 'node:assert'\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nexport const initEnvironment = <T extends Record<string, string>>() => {\n const environmentCache: Record<string, string | undefined> = {}\n\n return new Proxy(\n {},\n {\n get(_, k: keyof T | 'optional' | string | symbol) {\n const key = k as string\n if (key === 'optional') {\n return new Proxy(\n {},\n {\n get(_, k: keyof T | string | symbol) {\n const key = k as string\n if (key in environmentCache) {\n return environmentCache[key]\n }\n const { [key]: value } = process.env\n environmentCache[key] = value\n return environmentCache[key]\n },\n }\n ) as T\n }\n if (key in environmentCache) {\n return environmentCache[key]\n }\n const { [key]: value } = process.env\n assert(value, `${key} is required`)\n environmentCache[key] = value\n return environmentCache[key]\n },\n }\n ) as T & { optional: Partial<T> } & { [key: string]: string }\n}\n\nexport const mergeEnvironments = <\n T extends Record<string, string>,\n U extends Record<string, string>,\n>(\n env: T,\n secrets: U\n): T & U =>\n new Proxy({} as T & U, {\n get(_, key) {\n if (typeof key !== 'string') return undefined\n try {\n return (secrets as Record<string, string>)[key]\n } catch {\n return (env as Record<string, string>)[key]\n }\n },\n })\n\ntype SecretStoreOptions<T> = {\n dir?: string\n fallback?: boolean | Partial<T>\n}\n\nexport const initSecretStore = <T extends Record<string, string>>(\n opts?: SecretStoreOptions<T>\n) => {\n const secretCache: Record<string, string | undefined> = {}\n const { dir, fallback } = opts ?? {}\n\n return new Proxy(\n {},\n {\n get(_, k: keyof T | string | symbol) {\n const key = k as string\n if (key in secretCache) {\n return secretCache[key]\n }\n\n // 1. Try reading from file (dir/KEY or just KEY if no dir)\n const filePath = dir ? join(dir, key) : key\n try {\n const value = readFileSync(filePath, 'utf-8').trim()\n secretCache[key] = value\n return secretCache[key]\n } catch {\n // file not found — continue to fallback\n }\n\n // 2. Try fallback\n if (fallback === true) {\n // auto-read from process.env using the same key name\n const { [key]: value } = process.env\n if (value !== undefined) {\n secretCache[key] = value\n return secretCache[key]\n }\n } else if (fallback && key in fallback) {\n secretCache[key] = fallback[key as keyof T] as string\n return secretCache[key]\n }\n\n throw new Error(`Secret ${key} is required`)\n },\n }\n ) as T & { [key: string]: string }\n}\n"],"mappings":";;;;AAIA,MAAa,wBAA0D;CACrE,MAAM,mBAAuD,CAAC;CAE9D,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,GAA2C;EAChD,MAAM,MAAM;EACZ,IAAI,QAAQ,YACV,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,GAA8B;GACnC,MAAM,MAAM;GACZ,IAAI,OAAO,kBACT,OAAO,iBAAiB;GAE1B,MAAM,GAAG,MAAM,UAAU,QAAQ;GACjC,iBAAiB,OAAO;GACxB,OAAO,iBAAiB;EAC1B,EACF,CACF;EAEF,IAAI,OAAO,kBACT,OAAO,iBAAiB;EAE1B,MAAM,GAAG,MAAM,UAAU,QAAQ;EACjC,OAAO,OAAO,GAAG,IAAI,aAAa;EAClC,iBAAiB,OAAO;EACxB,OAAO,iBAAiB;CAC1B,EACF,CACF;AACF;AAEA,MAAa,qBAIX,KACA,YAEA,IAAI,MAAM,CAAC,GAAY,EACrB,IAAI,GAAG,KAAK;CACV,IAAI,OAAO,QAAQ,UAAU,OAAO,KAAA;CACpC,IAAI;EACF,OAAQ,QAAmC;CAC7C,QAAQ;EACN,OAAQ,IAA+B;CACzC;AACF,EACF,CAAC;AAOH,MAAa,mBACX,SACG;CACH,MAAM,cAAkD,CAAC;CACzD,MAAM,EAAE,KAAK,aAAa,QAAQ,CAAC;CAEnC,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,GAA8B;EACnC,MAAM,MAAM;EACZ,IAAI,OAAO,aACT,OAAO,YAAY;EAIrB,MAAM,WAAW,MAAM,KAAK,KAAK,GAAG,IAAI;EACxC,IAAI;GACF,MAAM,QAAQ,aAAa,UAAU,OAAO,CAAC,CAAC,KAAK;GACnD,YAAY,OAAO;GACnB,OAAO,YAAY;EACrB,QAAQ,CAER;EAGA,IAAI,aAAa,MAAM;GAErB,MAAM,GAAG,MAAM,UAAU,QAAQ;GACjC,IAAI,UAAU,KAAA,GAAW;IACvB,YAAY,OAAO;IACnB,OAAO,YAAY;GACrB;EACF,OAAO,IAAI,YAAY,OAAO,UAAU;GACtC,YAAY,OAAO,SAAS;GAC5B,OAAO,YAAY;EACrB;EAEA,MAAM,IAAI,MAAM,UAAU,IAAI,aAAa;CAC7C,EACF,CACF;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import assert from 'node:assert'\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nexport const initEnvironment = <T extends Record<string, string>>() => {\n const environmentCache: Record<string, string | undefined> = {}\n\n // biome-ignore lint/plugin/no-type-assertion: the Proxy resolves keys from process.env at runtime; this is the typed surface it implements\n return new Proxy(\n {},\n {\n get(_, key) {\n if (typeof key !== 'string') return undefined\n if (key === 'optional') {\n // biome-ignore lint/plugin/no-type-assertion: the Proxy resolves keys from process.env at runtime; this is the typed surface it implements\n return new Proxy(\n {},\n {\n get(_, key) {\n if (typeof key !== 'string') return undefined\n if (key in environmentCache) {\n return environmentCache[key]\n }\n const { [key]: value } = process.env\n environmentCache[key] = value\n return environmentCache[key]\n },\n }\n ) as T\n }\n if (key in environmentCache) {\n return environmentCache[key]\n }\n const { [key]: value } = process.env\n assert(value, `${key} is required`)\n environmentCache[key] = value\n return environmentCache[key]\n },\n }\n ) as T & { optional: Partial<T> } & { [key: string]: string }\n}\n\nexport const mergeEnvironments = <\n T extends Record<string, string>,\n U extends Record<string, string>,\n>(\n env: T,\n secrets: U\n): T & U =>\n // biome-ignore lint/plugin/no-type-assertion: the Proxy delegates every key to secrets or env at runtime; this is the typed surface it implements\n new Proxy({} as T & U, {\n get(_, key) {\n if (typeof key !== 'string') return undefined\n try {\n return secrets[key]\n } catch {\n return env[key]\n }\n },\n })\n\ntype SecretStoreOptions<T> = {\n dir?: string\n fallback?: boolean | Partial<T>\n}\n\nexport const initSecretStore = <T extends Record<string, string>>(\n opts?: SecretStoreOptions<T>\n) => {\n const secretCache: Record<string, string | undefined> = {}\n const { dir, fallback } = opts ?? {}\n\n // biome-ignore lint/plugin/no-type-assertion: the Proxy resolves keys from files or fallbacks at runtime; this is the typed surface it implements\n return new Proxy(\n {},\n {\n get(_, key) {\n if (typeof key !== 'string') return undefined\n if (key in secretCache) {\n return secretCache[key]\n }\n\n // 1. Try reading from file (dir/KEY or just KEY if no dir)\n const filePath = dir ? join(dir, key) : key\n try {\n const value = readFileSync(filePath, 'utf-8').trim()\n secretCache[key] = value\n return secretCache[key]\n } catch {\n // file not found — continue to fallback\n }\n\n // 2. Try fallback\n if (fallback === true) {\n // auto-read from process.env using the same key name\n const { [key]: value } = process.env\n if (value !== undefined) {\n secretCache[key] = value\n return secretCache[key]\n }\n } else if (fallback) {\n const value = fallback[key]\n if (value !== undefined) {\n secretCache[key] = value\n return secretCache[key]\n }\n }\n\n throw new Error(`Secret ${key} is required`)\n },\n }\n ) as T & { [key: string]: string }\n}\n"],"mappings":";;;;AAIA,MAAa,wBAA0D;CACrE,MAAM,mBAAuD,CAAC;CAG9D,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,KAAK;EACV,IAAI,OAAO,QAAQ,UAAU,OAAO,KAAA;EACpC,IAAI,QAAQ,YAEV,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,KAAK;GACV,IAAI,OAAO,QAAQ,UAAU,OAAO,KAAA;GACpC,IAAI,OAAO,kBACT,OAAO,iBAAiB;GAE1B,MAAM,GAAG,MAAM,UAAU,QAAQ;GACjC,iBAAiB,OAAO;GACxB,OAAO,iBAAiB;EAC1B,EACF,CACF;EAEF,IAAI,OAAO,kBACT,OAAO,iBAAiB;EAE1B,MAAM,GAAG,MAAM,UAAU,QAAQ;EACjC,OAAO,OAAO,GAAG,IAAI,aAAa;EAClC,iBAAiB,OAAO;EACxB,OAAO,iBAAiB;CAC1B,EACF,CACF;AACF;AAEA,MAAa,qBAIX,KACA,YAGA,IAAI,MAAM,CAAC,GAAY,EACrB,IAAI,GAAG,KAAK;CACV,IAAI,OAAO,QAAQ,UAAU,OAAO,KAAA;CACpC,IAAI;EACF,OAAO,QAAQ;CACjB,QAAQ;EACN,OAAO,IAAI;CACb;AACF,EACF,CAAC;AAOH,MAAa,mBACX,SACG;CACH,MAAM,cAAkD,CAAC;CACzD,MAAM,EAAE,KAAK,aAAa,QAAQ,CAAC;CAGnC,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,GAAG,KAAK;EACV,IAAI,OAAO,QAAQ,UAAU,OAAO,KAAA;EACpC,IAAI,OAAO,aACT,OAAO,YAAY;EAIrB,MAAM,WAAW,MAAM,KAAK,KAAK,GAAG,IAAI;EACxC,IAAI;GACF,MAAM,QAAQ,aAAa,UAAU,OAAO,CAAC,CAAC,KAAK;GACnD,YAAY,OAAO;GACnB,OAAO,YAAY;EACrB,QAAQ,CAER;EAGA,IAAI,aAAa,MAAM;GAErB,MAAM,GAAG,MAAM,UAAU,QAAQ;GACjC,IAAI,UAAU,KAAA,GAAW;IACvB,YAAY,OAAO;IACnB,OAAO,YAAY;GACrB;EACF,OAAO,IAAI,UAAU;GACnB,MAAM,QAAQ,SAAS;GACvB,IAAI,UAAU,KAAA,GAAW;IACvB,YAAY,OAAO;IACnB,OAAO,YAAY;GACrB;EACF;EAEA,MAAM,IAAI,MAAM,UAAU,IAAI,aAAa;CAC7C,EACF,CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebspark/environment",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -16,22 +16,20 @@
16
16
  ],
17
17
  "scripts": {
18
18
  "build": "spark-build src/index.ts",
19
- "depcheck": "depcheck",
20
19
  "dev": "tsc --watch --noEmit",
21
20
  "lint": "biome check .",
22
- "test": "vitest run --passWithNoTests --coverage",
23
- "typecheck": "vitest --typecheck.only --passWithNoTests --run"
21
+ "test": "vitest run --passWithNoTests --coverage --fsModuleCachePath node_modules/.vitest-cache",
22
+ "typecheck": "tsc --noEmit -p . && vitest --typecheck.only --passWithNoTests --run"
24
23
  },
25
24
  "repository": {
26
25
  "type": "git",
27
26
  "url": "https://github.com/seb-oss/Spark-packages.git"
28
27
  },
29
28
  "devDependencies": {
30
- "@biomejs/biome": "2.5.12",
31
- "@sebspark/tsconfig": "*",
32
- "depcheck": "1.4.7",
29
+ "@biomejs/biome": "2.6.4",
30
+ "@sebspark/tsconfig": "3.0.28",
33
31
  "typescript": "7.0.2",
34
- "vite": "8.2.2",
35
- "vitest": "5.0.0"
32
+ "vite": "8.3.5",
33
+ "vitest": "5.0.5"
36
34
  }
37
35
  }