tyfigo 0.1.0 → 0.1.1-next.ce8c251.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.
Files changed (56) hide show
  1. package/README.md +11 -3
  2. package/dist/bun.d.mts +8 -1
  3. package/dist/bun.mjs +4 -3
  4. package/dist/bun.mjs.map +1 -1
  5. package/dist/effect.mjs +2 -2
  6. package/dist/{env-Bd-1Atoz.mjs → env-C18Zet33.mjs} +2 -2
  7. package/dist/{env-Bd-1Atoz.mjs.map → env-C18Zet33.mjs.map} +1 -1
  8. package/dist/{env-R3_XPW_u.mjs → env-CWXftFpA.mjs} +13 -3
  9. package/dist/env-CWXftFpA.mjs.map +1 -0
  10. package/dist/index.mjs +1 -1
  11. package/dist/{load-DxIjRpX6.mjs → load-BZqp318Y.mjs} +43 -17
  12. package/dist/load-BZqp318Y.mjs.map +1 -0
  13. package/dist/{load-C-kweoyY.d.mts → load-D1KO5LdK.d.mts} +6 -4
  14. package/dist/plugins/esbuild.d.mts +2 -2
  15. package/dist/plugins/esbuild.mjs +1 -1
  16. package/dist/plugins/jest.d.mts +1 -1
  17. package/dist/plugins/jest.mjs +3 -3
  18. package/dist/plugins/loader.d.mts +1 -1
  19. package/dist/plugins/loader.mjs +1 -1
  20. package/dist/plugins/next.d.mts +1 -1
  21. package/dist/plugins/next.mjs +1 -1
  22. package/dist/plugins/rolldown.d.mts +2 -2
  23. package/dist/plugins/rolldown.mjs +1 -1
  24. package/dist/plugins/rollup.d.mts +2 -2
  25. package/dist/plugins/rollup.mjs +1 -1
  26. package/dist/plugins/rsbuild.d.mts +2 -2
  27. package/dist/plugins/rsbuild.mjs +1 -1
  28. package/dist/plugins/rspack.d.mts +2 -2
  29. package/dist/plugins/rspack.mjs +1 -1
  30. package/dist/plugins/vite.d.mts +2 -2
  31. package/dist/plugins/vite.mjs +1 -1
  32. package/dist/plugins/webpack.d.mts +2 -2
  33. package/dist/plugins/webpack.mjs +1 -1
  34. package/dist/register.mjs +1 -1
  35. package/dist/{resolve-D3geHCGs.mjs → resolve-DTfgGkq5.mjs} +22 -3
  36. package/dist/resolve-DTfgGkq5.mjs.map +1 -0
  37. package/dist/runtime/index.d.mts +13 -4
  38. package/dist/runtime/index.mjs +2 -2
  39. package/dist/{runtime-DeRUtPZ9.mjs → runtime-B-47CreJ.mjs} +12 -8
  40. package/dist/runtime-B-47CreJ.mjs.map +1 -0
  41. package/dist/{shared-CZ44uwQq.d.mts → shared-B6Y3_kdn.d.mts} +6 -5
  42. package/dist/{shared-BnK77Zcp.mjs → shared-Cndg8CKC.mjs} +2 -2
  43. package/dist/shared-Cndg8CKC.mjs.map +1 -0
  44. package/dist/{sync-B-HAK-_E.mjs → sync-DYO2PsXt.mjs} +2 -2
  45. package/dist/{sync-B-HAK-_E.mjs.map → sync-DYO2PsXt.mjs.map} +1 -1
  46. package/dist/unplugin-BYfqHkIE.d.mts +2 -0
  47. package/dist/{unplugin-BQGm_bhA.mjs → unplugin-DaIHdNM0.mjs} +8 -7
  48. package/dist/unplugin-DaIHdNM0.mjs.map +1 -0
  49. package/package.json +1 -1
  50. package/dist/env-R3_XPW_u.mjs.map +0 -1
  51. package/dist/load-DxIjRpX6.mjs.map +0 -1
  52. package/dist/resolve-D3geHCGs.mjs.map +0 -1
  53. package/dist/runtime-DeRUtPZ9.mjs.map +0 -1
  54. package/dist/shared-BnK77Zcp.mjs.map +0 -1
  55. package/dist/unplugin-AC_HM_T2.d.mts +0 -2
  56. package/dist/unplugin-BQGm_bhA.mjs.map +0 -1
package/README.md CHANGED
@@ -121,6 +121,11 @@ config/app.production.config.yaml(7,20): error TS2322: Type 'number' is not assi
121
121
  src/main.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'.
122
122
  ```
123
123
 
124
+ Without a schema, the types are strict and widened: an environment file can't add a key (so there are no optional sections),
125
+ `logLevel: info` is `string` rather than `'info' | 'debug'`, a placeholder without a default is `string`, and a `loadConfig`
126
+ mismatch is reported at the call rather than on the YAML line. A schema handles each of these; see
127
+ [What tsc checks without a schema](https://tyfigo.vercel.app/docs/type-checking#what-tsc-checks-without-a-schema).
128
+
124
129
  `database.url` has no default, so set `DATABASE_URL` (in `.env` or the environment) before you run the example. Without it, the import fails
125
130
  with `Environment variable 'DATABASE_URL' is not set (missing-variable)`.
126
131
 
@@ -173,9 +178,12 @@ const env = loadEnv(z.object({ NODE_ENV: z.enum(['development', 'production', 't
173
178
  | Jest | `'tyfigo/jest'` as the `transform` for config files, with their extensions in `moduleFileExtensions` | [jest](https://github.com/imranbarbhuiya/tyfigo/tree/main/examples/jest) |
174
179
 
175
180
  Browser builds get the base and environment files inlined, and a `${VAR}` placeholder or an import of `loadEnv` in a client bundle
176
- fails the build. Server bundles fix the environment when they build: they inline the base, environment and local files, ignore
177
- `NODE_ENV` at run time for picking layers, and read `.env` files and environment variables when they start. See
178
- [Browser builds](https://tyfigo.vercel.app/docs/browser-builds).
181
+ fails the build. Server bundles are built once and deployed anywhere: they inline the base, local and every environment's
182
+ files, pick the layers by `NODE_ENV` when they start (unless the plugin's `environment` option fixes it), and read `.env` files
183
+ and environment variables then. See [Server bundles](https://tyfigo.vercel.app/docs/browser-builds#server-bundles).
184
+
185
+ `next build` can't pass `--runExternalCode` to its type check, so `withTyfigo` turns Next's check off and runs
186
+ `tsc --noEmit --runExternalCode` itself after the compile. See [Next.js](https://tyfigo.vercel.app/docs/bundlers/next).
179
187
 
180
188
  ## Formats
181
189
 
package/dist/bun.d.mts CHANGED
@@ -1,7 +1,14 @@
1
1
  import { BunPlugin } from "bun";
2
+ export interface TyfigoBunOptions {
3
+ /**
4
+ * The environment name. Defaults to `NODE_ENV`, read when the config loads, or when a server `Bun.build` bundle starts.
5
+ * Setting it fixes the environment of a server bundle.
6
+ */
7
+ readonly environment?: string | undefined;
8
+ }
2
9
  /**
3
10
  * The tyfigo Bun plugin. Importing `tyfigo/bun` (a `bunfig.toml` `preload`) registers it for the runtime and `bun test`; pass
4
11
  * `tyfigo()` in `plugins` to use it with `Bun.build`, where a `browser` target inlines the config and a server target inlines the config files and reads `.env` files when it runs.
5
12
  */
6
- export declare const tyfigo: () => BunPlugin;
13
+ export declare const tyfigo: (options?: TyfigoBunOptions) => BunPlugin;
7
14
  //# sourceMappingURL=bun.d.mts.map
package/dist/bun.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as formatProblems } from "./problems-BNAqmOzL.mjs";
2
2
  import { t as configSuffixes } from "./formats-D_dKXoPf.mjs";
3
- import { t as load } from "./load-DxIjRpX6.mjs";
3
+ import { t as load } from "./load-BZqp318Y.mjs";
4
4
  import { extname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { plugin } from "bun";
@@ -11,7 +11,7 @@ const filter = new RegExp(`[^/\\\\](?:${configSuffixes.map((suffix) => suffix.re
11
11
  * The tyfigo Bun plugin. Importing `tyfigo/bun` (a `bunfig.toml` `preload`) registers it for the runtime and `bun test`; pass
12
12
  * `tyfigo()` in `plugins` to use it with `Bun.build`, where a `browser` target inlines the config and a server target inlines the config files and reads `.env` files when it runs.
13
13
  */
14
- const tyfigo = () => ({
14
+ const tyfigo = (options = {}) => ({
15
15
  name: "tyfigo",
16
16
  setup(build) {
17
17
  const config = build.config;
@@ -20,7 +20,8 @@ const tyfigo = () => ({
20
20
  const result = load(path, {
21
21
  target,
22
22
  runtime,
23
- bundle: config !== void 0
23
+ bundle: config !== void 0,
24
+ environment: options.environment
24
25
  });
25
26
  if (result.problems.length > 0) throw new Error(`Invalid config ${path}\n${formatProblems(result.problems)}`);
26
27
  return {
package/dist/bun.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bun.mjs","names":[],"sources":["../src/bun.ts"],"sourcesContent":["import { extname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { plugin } from 'bun';\n\nimport { configSuffixes, formatProblems } from './core/index.ts';\nimport { load } from './runtime/index.ts';\n\nimport type { BunPlugin } from 'bun';\n\n// The runtime next to this module, so it resolves from config files outside the dependency tree: `.ts` in this repo, `.mjs` once built.\nconst runtime = fileURLToPath(new URL(`runtime/index${extname(import.meta.url)}`, import.meta.url));\n\nconst filter = new RegExp(`[^/\\\\\\\\](?:${configSuffixes.map((suffix) => suffix.replaceAll('.', '\\\\.')).join('|')})$`);\n\n/**\n * The tyfigo Bun plugin. Importing `tyfigo/bun` (a `bunfig.toml` `preload`) registers it for the runtime and `bun test`; pass\n * `tyfigo()` in `plugins` to use it with `Bun.build`, where a `browser` target inlines the config and a server target inlines the config files and reads `.env` files when it runs.\n */\nexport const tyfigo = (): BunPlugin => ({\n\tname: 'tyfigo',\n\tsetup(build) {\n\t\tconst config = build.config as typeof build.config | undefined;\n\t\tconst target = config?.target === 'browser' ? 'browser' : 'server';\n\t\tbuild.onLoad({ filter }, ({ path }) => {\n\t\t\tconst result = load(path, { target, runtime, bundle: config !== undefined });\n\t\t\tif (result.problems.length > 0) {\n\t\t\t\tthrow new Error(`Invalid config ${path}\\n${formatProblems(result.problems)}`);\n\t\t\t}\n\t\t\treturn { contents: result.code, loader: 'js' };\n\t\t});\n\t},\n});\n\nvoid plugin(tyfigo());\n"],"mappings":";;;;;;;AAWA,MAAM,UAAU,cAAc,IAAI,IAAI,gBAAgB,QAAQ,YAAY,GAAG,KAAK,YAAY,GAAG,CAAC;AAElG,MAAM,SAAS,IAAI,OAAO,cAAc,eAAe,KAAK,WAAW,OAAO,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,GAAG;;;;;AAMnH,MAAa,gBAA2B;CACvC,MAAM;CACN,MAAM,OAAO;EACZ,MAAM,SAAS,MAAM;EACrB,MAAM,SAAS,QAAQ,WAAW,YAAY,YAAY;EAC1D,MAAM,OAAO,EAAE,OAAO,IAAI,EAAE,WAAW;GACtC,MAAM,SAAS,KAAK,MAAM;IAAE;IAAQ;IAAS,QAAQ,WAAW,KAAA;GAAU,CAAC;GAC3E,IAAI,OAAO,SAAS,SAAS,GAC5B,MAAM,IAAI,MAAM,kBAAkB,KAAK,IAAI,eAAe,OAAO,QAAQ,GAAG;GAE7E,OAAO;IAAE,UAAU,OAAO;IAAM,QAAQ;GAAK;EAC9C,CAAC;CACF;AACD;AAEK,OAAO,OAAO,CAAC"}
1
+ {"version":3,"file":"bun.mjs","names":[],"sources":["../src/bun.ts"],"sourcesContent":["import { extname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { plugin } from 'bun';\n\nimport { configSuffixes, formatProblems } from './core/index.ts';\nimport { load } from './runtime/index.ts';\n\nimport type { BunPlugin } from 'bun';\n\n// The runtime next to this module, so it resolves from config files outside the dependency tree: `.ts` in this repo, `.mjs` once built.\nconst runtime = fileURLToPath(new URL(`runtime/index${extname(import.meta.url)}`, import.meta.url));\n\nconst filter = new RegExp(`[^/\\\\\\\\](?:${configSuffixes.map((suffix) => suffix.replaceAll('.', '\\\\.')).join('|')})$`);\n\nexport interface TyfigoBunOptions {\n\t/**\n\t * The environment name. Defaults to `NODE_ENV`, read when the config loads, or when a server `Bun.build` bundle starts.\n\t * Setting it fixes the environment of a server bundle.\n\t */\n\treadonly environment?: string | undefined;\n}\n\n/**\n * The tyfigo Bun plugin. Importing `tyfigo/bun` (a `bunfig.toml` `preload`) registers it for the runtime and `bun test`; pass\n * `tyfigo()` in `plugins` to use it with `Bun.build`, where a `browser` target inlines the config and a server target inlines the config files and reads `.env` files when it runs.\n */\nexport const tyfigo = (options: TyfigoBunOptions = {}): BunPlugin => ({\n\tname: 'tyfigo',\n\tsetup(build) {\n\t\tconst config = build.config as typeof build.config | undefined;\n\t\tconst target = config?.target === 'browser' ? 'browser' : 'server';\n\t\tbuild.onLoad({ filter }, ({ path }) => {\n\t\t\tconst result = load(path, {\n\t\t\t\ttarget,\n\t\t\t\truntime,\n\t\t\t\tbundle: config !== undefined,\n\t\t\t\tenvironment: options.environment,\n\t\t\t});\n\t\t\tif (result.problems.length > 0) {\n\t\t\t\tthrow new Error(`Invalid config ${path}\\n${formatProblems(result.problems)}`);\n\t\t\t}\n\t\t\treturn { contents: result.code, loader: 'js' };\n\t\t});\n\t},\n});\n\nvoid plugin(tyfigo());\n"],"mappings":";;;;;;;AAWA,MAAM,UAAU,cAAc,IAAI,IAAI,gBAAgB,QAAQ,YAAY,GAAG,KAAK,YAAY,GAAG,CAAC;AAElG,MAAM,SAAS,IAAI,OAAO,cAAc,eAAe,KAAK,WAAW,OAAO,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,GAAG;;;;;AAcnH,MAAa,UAAU,UAA4B,CAAC,OAAkB;CACrE,MAAM;CACN,MAAM,OAAO;EACZ,MAAM,SAAS,MAAM;EACrB,MAAM,SAAS,QAAQ,WAAW,YAAY,YAAY;EAC1D,MAAM,OAAO,EAAE,OAAO,IAAI,EAAE,WAAW;GACtC,MAAM,SAAS,KAAK,MAAM;IACzB;IACA;IACA,QAAQ,WAAW,KAAA;IACnB,aAAa,QAAQ;GACtB,CAAC;GACD,IAAI,OAAO,SAAS,SAAS,GAC5B,MAAM,IAAI,MAAM,kBAAkB,KAAK,IAAI,eAAe,OAAO,QAAQ,GAAG;GAE7E,OAAO;IAAE,UAAU,OAAO;IAAM,QAAQ;GAAK;EAC9C,CAAC;CACF;AACD;AAEK,OAAO,OAAO,CAAC"}
package/dist/effect.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as ConfigValidationError } from "./schema-DcD4N9N-.mjs";
2
- import { t as decodeEnv } from "./env-Bd-1Atoz.mjs";
2
+ import { t as decodeEnv } from "./env-C18Zet33.mjs";
3
3
  import { a as layerConfig, i as ConfigService, n as layerConfigProvider, o as loadConfig, r as ConfigError, t as configProvider } from "./effect.browser-CO87TEE_.mjs";
4
- import { t as resolveConfig } from "./resolve-D3geHCGs.mjs";
4
+ import { t as resolveConfig } from "./resolve-DTfgGkq5.mjs";
5
5
  import { ConfigProvider, Effect, Layer } from "effect";
6
6
  // src/effect/env.ts
7
7
  /**
@@ -1,4 +1,4 @@
1
- import { n as processEnv, r as readEnv } from "./env-R3_XPW_u.mjs";
1
+ import { n as processEnv, r as readEnv } from "./env-CWXftFpA.mjs";
2
2
  import { r as validate } from "./schema-DcD4N9N-.mjs";
3
3
  import { Effect } from "effect";
4
4
  import { join } from "node:path";
@@ -24,4 +24,4 @@ const decodeEnv = Effect.fn("decodeEnv")(function* (schema, options) {
24
24
  });
25
25
  export { decodeEnv as t };
26
26
 
27
- //# sourceMappingURL=env-Bd-1Atoz.mjs.map
27
+ //# sourceMappingURL=env-C18Zet33.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"env-Bd-1Atoz.mjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { join } from 'node:path';\nimport process from 'node:process';\n\nimport { Effect } from 'effect';\n\nimport { processEnv, readEnv } from './core/env.ts';\nimport { validate } from './schema.ts';\n\nimport type { ConfigSchema, LoadEnvOptions } from './schema.ts';\n\nexport const decodeEnv = Effect.fn('decodeEnv')(function* <S extends ConfigSchema>(\n\tschema: S,\n\toptions: LoadEnvOptions & { readonly async: boolean; readonly native?: boolean | undefined },\n) {\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst result = yield* readEnv(join(options.cwd ?? process.cwd(), '.env'), { environment, env });\n\treturn yield* validate(schema, result.variables, {\n\t\tsubject: 'environment variables',\n\t\tasync: options.async,\n\t\tnative: options.native,\n\t\tissues: result.problems.map((problem) => ({\n\t\t\tpath: [],\n\t\t\tmessage: problem.message,\n\t\t\tlocation: `${problem.file}:${problem.line}:${problem.column}`,\n\t\t})),\n\t});\n});\n"],"mappings":";;;;;;AAUA,MAAa,YAAY,OAAO,GAAG,WAAW,CAAC,CAAC,WAC/C,QACA,SACC;CACD,MAAM,MAAM,QAAQ,OAAO,WAAW;CACtC,MAAM,cAAc,QAAQ,gBAAgB,IAAI,YAAY,KAAA;CAC5D,MAAM,SAAS,OAAO,QAAQ,KAAK,QAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM,GAAG;EAAE;EAAa;CAAI,CAAC;CAC9F,OAAO,OAAO,SAAS,QAAQ,OAAO,WAAW;EAChD,SAAS;EACT,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,QAAQ,OAAO,SAAS,KAAK,aAAa;GACzC,MAAM,CAAC;GACP,SAAS,QAAQ;GACjB,UAAU,GAAG,QAAQ,KAAK,GAAG,QAAQ,KAAK,GAAG,QAAQ;EACtD,EAAE;CACH,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"env-C18Zet33.mjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { join } from 'node:path';\nimport process from 'node:process';\n\nimport { Effect } from 'effect';\n\nimport { processEnv, readEnv } from './core/env.ts';\nimport { validate } from './schema.ts';\n\nimport type { ConfigSchema, LoadEnvOptions } from './schema.ts';\n\nexport const decodeEnv = Effect.fn('decodeEnv')(function* <S extends ConfigSchema>(\n\tschema: S,\n\toptions: LoadEnvOptions & { readonly async: boolean; readonly native?: boolean | undefined },\n) {\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst result = yield* readEnv(join(options.cwd ?? process.cwd(), '.env'), { environment, env });\n\treturn yield* validate(schema, result.variables, {\n\t\tsubject: 'environment variables',\n\t\tasync: options.async,\n\t\tnative: options.native,\n\t\tissues: result.problems.map((problem) => ({\n\t\t\tpath: [],\n\t\t\tmessage: problem.message,\n\t\t\tlocation: `${problem.file}:${problem.line}:${problem.column}`,\n\t\t})),\n\t});\n});\n"],"mappings":";;;;;;AAUA,MAAa,YAAY,OAAO,GAAG,WAAW,CAAC,CAAC,WAC/C,QACA,SACC;CACD,MAAM,MAAM,QAAQ,OAAO,WAAW;CACtC,MAAM,cAAc,QAAQ,gBAAgB,IAAI,YAAY,KAAA;CAC5D,MAAM,SAAS,OAAO,QAAQ,KAAK,QAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM,GAAG;EAAE;EAAa;CAAI,CAAC;CAC9F,OAAO,OAAO,SAAS,QAAQ,OAAO,WAAW;EAChD,SAAS;EACT,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,QAAQ,OAAO,SAAS,KAAK,aAAa;GACzC,MAAM,CAAC;GACP,SAAS,QAAQ;GACjB,UAAU,GAAG,QAAQ,KAAK,GAAG,QAAQ,KAAK,GAAG,QAAQ;EACtD,EAAE;CACH,CAAC;AACF,CAAC"}
@@ -2,11 +2,21 @@ import { t as fileProblem } from "./problems-BNAqmOzL.mjs";
2
2
  import { Effect, Result } from "effect";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import process from "node:process";
5
- import { readFileSync, statSync } from "node:fs";
5
+ import { readFileSync, readdirSync, statSync } from "node:fs";
6
6
  import { parseEnv } from "node:util";
7
7
  // src/core/files.ts
8
8
  const isFile = (path) => Effect.sync(() => statSync(path, { throwIfNoEntry: false })?.isFile() ?? false);
9
9
  /**
10
+ * The names of the entries in `directory`, or none when it cannot be read.
11
+ */
12
+ const listDirectory = (directory) => Effect.sync(() => {
13
+ try {
14
+ return readdirSync(directory);
15
+ } catch {
16
+ return [];
17
+ }
18
+ });
19
+ /**
10
20
  * The nearest directory at or above `directory` that has a `package.json`.
11
21
  */
12
22
  const findProjectRoot = Effect.fn("findProjectRoot")(function* (directory) {
@@ -73,6 +83,6 @@ const readEnv = Effect.fn("readEnv")(function* (baseFile, options = {}) {
73
83
  problems
74
84
  };
75
85
  });
76
- export { findProjectRoot as a, findFile as i, processEnv as n, isFile as o, readEnv as r, searchDirectories as s, envFileNames as t };
86
+ export { findProjectRoot as a, searchDirectories as c, findFile as i, processEnv as n, isFile as o, readEnv as r, listDirectory as s, envFileNames as t };
77
87
 
78
- //# sourceMappingURL=env-R3_XPW_u.mjs.map
88
+ //# sourceMappingURL=env-CWXftFpA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-CWXftFpA.mjs","names":[],"sources":["../src/core/files.ts","../src/core/env.ts"],"sourcesContent":["import { readdirSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { Effect } from 'effect';\n\nexport const isFile = (path: string): Effect.Effect<boolean> =>\n\tEffect.sync(() => statSync(path, { throwIfNoEntry: false })?.isFile() ?? false);\n\n/**\n * The names of the entries in `directory`, or none when it cannot be read.\n */\nexport const listDirectory = (directory: string): Effect.Effect<readonly string[]> =>\n\tEffect.sync(() => {\n\t\ttry {\n\t\t\treturn readdirSync(directory);\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t});\n\n/**\n * The nearest directory at or above `directory` that has a `package.json`.\n */\nexport const findProjectRoot = Effect.fn('findProjectRoot')(function* (directory: string) {\n\tfor (let current = directory; ; current = dirname(current)) {\n\t\tif (yield* isFile(join(current, 'package.json'))) return current;\n\t\tif (dirname(current) === current) return undefined;\n\t}\n});\n\n/**\n * The first existing `name` in `directories`.\n */\nexport const findFile = Effect.fn('findFile')(function* (directories: readonly string[], name: string) {\n\tfor (const directory of directories) {\n\t\tconst path = join(directory, name);\n\t\tif (yield* isFile(path)) return path;\n\t}\n\treturn undefined;\n});\n\n/**\n * The base file's directory followed by the project root when it is a different directory.\n */\nexport const searchDirectories = Effect.fn('searchDirectories')(function* (baseFile: string) {\n\tconst directory = dirname(baseFile);\n\tconst root = yield* findProjectRoot(directory);\n\treturn root === undefined || root === directory ? [directory] : [directory, root];\n});\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport process from 'node:process';\nimport { parseEnv } from 'node:util';\n\nimport { Effect, Result } from 'effect';\n\nimport { findFile, searchDirectories } from './files.ts';\nimport { fileProblem } from './problems.ts';\n\nimport type { Problem } from './problems.ts';\n\nexport type EnvVariables = Readonly<Record<string, string | undefined>>;\n\nexport interface EnvResult {\n\t/**\n\t * The `.env` values with the real environment on top.\n\t */\n\treadonly variables: EnvVariables;\n\t/**\n\t * The `.env` files that were read, in the order they apply.\n\t */\n\treadonly files: readonly string[];\n\treadonly problems: readonly Problem[];\n}\n\n/**\n * A copy of the real environment. This is the only place tyfigo reads `process.env`.\n */\nexport const processEnv = (): EnvVariables => ({ ...process.env });\n\nexport const envFileNames = (environment?: string): readonly string[] =>\n\tenvironment ? ['.env', '.env.local', `.env.${environment}`, `.env.${environment}.local`] : ['.env', '.env.local'];\n\n/**\n * Reads `.env`, `.env.local`, `.env.<environment>` and `.env.<environment>.local` (each later one wins) and puts `env` on top.\n * Each file is searched next to `baseFile` first, then in the nearest directory with a `package.json`. Never writes `process.env`.\n */\nexport const readEnv = Effect.fn('readEnv')(function* (\n\tbaseFile: string,\n\toptions: { readonly environment?: string | undefined; readonly env?: EnvVariables | undefined } = {},\n) {\n\tconst directories = yield* searchDirectories(resolve(baseFile));\n\tconst variables: Record<string, string | undefined> = {};\n\tconst files: string[] = [];\n\tconst problems: Problem[] = [];\n\tfor (const name of envFileNames(options.environment)) {\n\t\tconst file = yield* findFile(directories, name);\n\t\tif (!file) continue;\n\t\tconst parsed = yield* Effect.result(\n\t\t\tEffect.try({\n\t\t\t\ttry: () => parseEnv(readFileSync(file, 'utf8')),\n\t\t\t\tcatch: (error) => fileProblem(file, 'read-error', `Cannot read ${file}: ${(error as Error).message}`),\n\t\t\t}),\n\t\t);\n\t\tif (Result.isFailure(parsed)) {\n\t\t\tproblems.push(parsed.failure);\n\t\t\tcontinue;\n\t\t}\n\n\t\tfiles.push(file);\n\t\tObject.assign(variables, parsed.success);\n\t}\n\n\tfor (const [key, value] of Object.entries(options.env ?? processEnv())) {\n\t\tif (value !== undefined) variables[key] = value;\n\t}\n\treturn { variables, files, problems } satisfies EnvResult;\n});\n"],"mappings":";;;;;;;AAKA,MAAa,UAAU,SACtB,OAAO,WAAW,SAAS,MAAM,EAAE,gBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK;;;;AAK/E,MAAa,iBAAiB,cAC7B,OAAO,WAAW;CACjB,IAAI;EACH,OAAO,YAAY,SAAS;CAC7B,QAAQ;EACP,OAAO,CAAC;CACT;AACD,CAAC;;;;AAKF,MAAa,kBAAkB,OAAO,GAAG,iBAAiB,CAAC,CAAC,WAAW,WAAmB;CACzF,KAAK,IAAI,UAAU,YAAa,UAAU,QAAQ,OAAO,GAAG;EAC3D,IAAI,OAAO,OAAO,KAAK,SAAS,cAAc,CAAC,GAAG,OAAO;EACzD,IAAI,QAAQ,OAAO,MAAM,SAAS,OAAO,KAAA;CAC1C;AACD,CAAC;;;;AAKD,MAAa,WAAW,OAAO,GAAG,UAAU,CAAC,CAAC,WAAW,aAAgC,MAAc;CACtG,KAAK,MAAM,aAAa,aAAa;EACpC,MAAM,OAAO,KAAK,WAAW,IAAI;EACjC,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO;CACjC;AAED,CAAC;;;;AAKD,MAAa,oBAAoB,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,UAAkB;CAC5F,MAAM,YAAY,QAAQ,QAAQ;CAClC,MAAM,OAAO,OAAO,gBAAgB,SAAS;CAC7C,OAAO,SAAS,KAAA,KAAa,SAAS,YAAY,CAAC,SAAS,IAAI,CAAC,WAAW,IAAI;AACjF,CAAC;;;;;ACnBD,MAAa,oBAAkC,EAAE,GAAG,QAAQ,IAAI;AAEhE,MAAa,gBAAgB,gBAC5B,cAAc;CAAC;CAAQ;CAAc,QAAQ;CAAe,QAAQ,YAAY;AAAO,IAAI,CAAC,QAAQ,YAAY;;;;;AAMjH,MAAa,UAAU,OAAO,GAAG,SAAS,CAAC,CAAC,WAC3C,UACA,UAAkG,CAAC,GAClG;CACD,MAAM,cAAc,OAAO,kBAAkB,QAAQ,QAAQ,CAAC;CAC9D,MAAM,YAAgD,CAAC;CACvD,MAAM,QAAkB,CAAC;CACzB,MAAM,WAAsB,CAAC;CAC7B,KAAK,MAAM,QAAQ,aAAa,QAAQ,WAAW,GAAG;EACrD,MAAM,OAAO,OAAO,SAAS,aAAa,IAAI;EAC9C,IAAI,CAAC,MAAM;EACX,MAAM,SAAS,OAAO,OAAO,OAC5B,OAAO,IAAI;GACV,WAAW,SAAS,aAAa,MAAM,MAAM,CAAC;GAC9C,QAAQ,UAAU,YAAY,MAAM,cAAc,eAAe,KAAK,IAAK,MAAgB,SAAS;EACrG,CAAC,CACF;EACA,IAAI,OAAO,UAAU,MAAM,GAAG;GAC7B,SAAS,KAAK,OAAO,OAAO;GAC5B;EACD;EAEA,MAAM,KAAK,IAAI;EACf,OAAO,OAAO,WAAW,OAAO,OAAO;CACxC;CAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,OAAO,WAAW,CAAC,GACpE,IAAI,UAAU,KAAA,GAAW,UAAU,OAAO;CAE3C,OAAO;EAAE;EAAW;EAAO;CAAS;AACrC,CAAC"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as ConfigValidationError } from "./schema-DcD4N9N-.mjs";
2
- import { t as decodeEnv } from "./env-Bd-1Atoz.mjs";
2
+ import { t as decodeEnv } from "./env-C18Zet33.mjs";
3
3
  import { n as loadConfigAsync, t as loadConfig } from "./index.browser-C5z_VT_3.mjs";
4
4
  import { Effect } from "effect";
5
5
  // src/index.ts
@@ -1,8 +1,8 @@
1
- import { a as findProjectRoot, n as processEnv, o as isFile, s as searchDirectories, t as envFileNames } from "./env-R3_XPW_u.mjs";
1
+ import { a as findProjectRoot, c as searchDirectories, n as processEnv, o as isFile, t as envFileNames } from "./env-CWXftFpA.mjs";
2
2
  import { n as formatProblems, r as problemAt, t as fileProblem } from "./problems-BNAqmOzL.mjs";
3
3
  import { n as formatPath, r as pathKey, t as SourceIndex } from "./positions-BCTEFZTX.mjs";
4
4
  import { i as isPlainObject, n as parseConfigFileName, r as hasPlaceholder, t as configSuffixes } from "./formats-D_dKXoPf.mjs";
5
- import { t as resolveConfig } from "./resolve-D3geHCGs.mjs";
5
+ import { r as discoverEnvironments, t as resolveConfig } from "./resolve-DTfgGkq5.mjs";
6
6
  import { Effect } from "effect";
7
7
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
8
  // src/runtime/load.ts
@@ -89,25 +89,51 @@ const browserModule = Effect.fn("browserModule")(function* (file, options) {
89
89
  problems
90
90
  };
91
91
  });
92
+ const layerOrder = {
93
+ base: 0,
94
+ environment: 1,
95
+ local: 2,
96
+ "environment-local": 3
97
+ };
92
98
  const bundledServerModule = Effect.fn("bundledServerModule")(function* (file, options) {
93
- const environment = options.environment ?? (processEnv().NODE_ENV || void 0);
94
- const result = yield* resolveConfig(file, { environment });
95
- const problems = result.problems.filter((problem) => problem.code !== "missing-variable" && problem.code !== "placeholder-type");
96
- const root = (yield* findProjectRoot(dirname(result.file))) ?? dirname(result.file);
99
+ const environments = options.environment === void 0 ? [void 0, ...yield* discoverEnvironments(file)] : [options.environment];
100
+ const results = [];
101
+ for (const environment of environments) results.push(yield* resolveConfig(file, environment === void 0 ? { layers: ["base", "local"] } : { environment }));
102
+ const root = (yield* findProjectRoot(dirname(file))) ?? dirname(file);
97
103
  const name = (path) => relative(root, path).split(sep).join("/");
104
+ const problems = /* @__PURE__ */ new Map();
105
+ const layers = /* @__PURE__ */ new Map();
106
+ for (const result of results) {
107
+ for (const problem of result.problems) {
108
+ if (problem.code === "missing-variable" || problem.code === "placeholder-type") continue;
109
+ problems.set(JSON.stringify([
110
+ problem.file,
111
+ problem.start,
112
+ problem.code,
113
+ problem.message
114
+ ]), problem);
115
+ }
116
+ for (const layer of result.layers) {
117
+ const specific = layer.kind === "environment" || layer.kind === "environment-local";
118
+ layers.set(layer.file, {
119
+ file: name(layer.file),
120
+ kind: layer.kind,
121
+ ...specific ? { environment: result.environment } : {},
122
+ text: layer.text
123
+ });
124
+ }
125
+ }
98
126
  const bundle = {
99
- file: name(result.file),
100
- environment,
101
- layers: result.layers.map((layer) => ({
102
- file: name(layer.file),
103
- kind: layer.kind,
104
- text: layer.text
105
- }))
127
+ file: name(file),
128
+ ...options.environment === void 0 ? {} : { environment: options.environment },
129
+ layers: [...layers.values()].toSorted((a, b) => layerOrder[a.kind] - layerOrder[b.kind])
106
130
  };
131
+ const watchFiles = /* @__PURE__ */ new Set();
132
+ for (const environment of /* @__PURE__ */ new Set([...environments, processEnv().NODE_ENV || void 0])) for (const watchFile of yield* watchFilesOf(file, environment, "server")) watchFiles.add(watchFile);
107
133
  return {
108
- code: problems.length > 0 ? failingCode(result.file, problems) : `import { resolveBundledConfigModule } from ${JSON.stringify(options.runtime ?? "tyfigo/runtime")};\n\nexport default resolveBundledConfigModule(${JSON.stringify(bundle)});\n`,
109
- watchFiles: yield* watchFilesOf(result.file, environment, "server"),
110
- problems
134
+ code: problems.size > 0 ? failingCode(file, [...problems.values()]) : `import { resolveBundledConfigModule } from ${JSON.stringify(options.runtime ?? "tyfigo/runtime")};\n\nexport default resolveBundledConfigModule(${JSON.stringify(bundle)});\n`,
135
+ watchFiles: [...watchFiles],
136
+ problems: [...problems.values()]
111
137
  };
112
138
  });
113
139
  /**
@@ -124,4 +150,4 @@ const loadModule = Effect.fn("loadModule")(function* (path, options) {
124
150
  const load = (path, options) => Effect.runSync(loadModule(path, options));
125
151
  export { loadModule as n, valueLiteral as r, load as t };
126
152
 
127
- //# sourceMappingURL=load-DxIjRpX6.mjs.map
153
+ //# sourceMappingURL=load-BZqp318Y.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-BZqp318Y.mjs","names":[],"sources":["../src/runtime/load.ts"],"sourcesContent":["import { basename, dirname, join, relative, resolve, sep } from 'node:path';\n\nimport { Effect } from 'effect';\n\nimport { findProjectRoot, isFile, searchDirectories } from '../core/files.ts';\nimport {\n\tconfigSuffixes,\n\tdiscoverEnvironments,\n\tenvFileNames,\n\tfileProblem,\n\tformatPath,\n\tformatProblems,\n\thasPlaceholder,\n\tisPlainObject,\n\tparseConfigFileName,\n\tpathKey,\n\tproblemAt,\n\tprocessEnv,\n\tresolveConfig,\n\tSourceIndex,\n} from '../core/index.ts';\n\nimport type { LayerKind, Path, PositionMap, Problem, ResolvedConfig } from '../core/index.ts';\nimport type { BundledConfig, BundledLayer } from './resolve.ts';\n\nexport type LoadTarget = 'server' | 'browser';\n\nexport interface LoadOptions {\n\t/**\n\t * `server` resolves the config when the module runs. `browser` inlines the base and environment files at build time and\n\t * reports every placeholder as a problem.\n\t */\n\treadonly target: LoadTarget;\n\t/**\n\t * The environment name, such as the bundler's mode. Defaults to `NODE_ENV`, read when the server module runs and when\n\t * `load` runs for the browser. A bundled server module inlines only this environment's files when it is given, and every\n\t * environment's files otherwise.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The specifier the server module imports the runtime from. Defaults to `tyfigo/runtime`.\n\t */\n\treadonly runtime?: string | undefined;\n\t/**\n\t * For `server`: inline the text of the layer files that exist at build time, for every environment unless `environment` is\n\t * given, and pick the environment's layers and read `.env` files and environment variables from `process.cwd()` when the\n\t * module runs, so a bundle does not depend on the paths of the machine that built it.\n\t */\n\treadonly bundle?: boolean | undefined;\n}\n\nexport interface LoadResult {\n\t/**\n\t * The JavaScript module, with the config as its default export.\n\t */\n\treadonly code: string;\n\t/**\n\t * Every file whose creation, change or removal changes the module, whether or not it exists now.\n\t */\n\treadonly watchFiles: readonly string[];\n\treadonly problems: readonly Problem[];\n}\n\nconst browserLayers = ['base', 'environment'] as const;\n\nconst watchFilesOf = Effect.fn('watchFilesOf')(function* (\n\tfile: string,\n\tenvironment: string | undefined,\n\ttarget: LoadTarget,\n) {\n\tconst name = parseConfigFileName(basename(file));\n\tif (!name) return [file];\n\n\tconst files = [file];\n\tif (environment) files.push(join(dirname(file), `${name.stem}.${environment}${name.suffix}`));\n\tif (target === 'browser') return files;\n\n\tconst directories = yield* searchDirectories(file);\n\tconst locals = environment\n\t\t? [`${name.stem}.local${name.suffix}`, `${name.stem}.${environment}.local${name.suffix}`]\n\t\t: [`${name.stem}.local${name.suffix}`];\n\tfor (const fileName of [...locals, ...envFileNames(environment)]) {\n\t\tfor (const directory of directories) files.push(join(directory, fileName));\n\t}\n\treturn files;\n});\n\n/**\n * A JavaScript expression that evaluates to a deep-frozen copy of a config value.\n */\nexport const valueLiteral = (value: unknown, indent = ''): string => {\n\tif (value === undefined) return 'undefined';\n\tif (typeof value === 'number') return Object.is(value, -0) ? '-0' : String(value);\n\tif (typeof value === 'bigint') return `${value}n`;\n\tif (value instanceof Date) return `new Date(${valueLiteral(value.getTime(), indent)})`;\n\tconst inner = `${indent}\\t`;\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return 'Object.freeze([])';\n\t\tconst items = value.map((item) => `${inner}${valueLiteral(item, inner)},\\n`);\n\t\treturn `Object.freeze([\\n${items.join('')}${indent}])`;\n\t}\n\tif (isPlainObject(value)) {\n\t\tconst entries = Object.entries(value);\n\t\tif (entries.length === 0) return 'Object.freeze({})';\n\t\tconst properties = entries.map(([key, item]) => {\n\t\t\tconst name = key === '__proto__' ? `[${JSON.stringify(key)}]` : JSON.stringify(key);\n\t\t\treturn `${inner}${name}: ${valueLiteral(item, inner)},\\n`;\n\t\t});\n\t\treturn `Object.freeze({\\n${properties.join('')}${indent}})`;\n\t}\n\treturn JSON.stringify(value);\n};\n\nconst hasUnescapedPlaceholder = (text: string) => hasPlaceholder(text.replaceAll('$${', ''));\n\nconst placeholderProblems = (file: string, text: string, value: unknown, positions: PositionMap) => {\n\tconst source = new SourceIndex(text);\n\tconst problems: Problem[] = [];\n\tconst visit = (item: unknown, path: Path) => {\n\t\tif (typeof item === 'string') {\n\t\t\tif (!hasUnescapedPlaceholder(item)) return;\n\t\t\tconst span = positions.get(pathKey(path));\n\t\t\tproblems.push(\n\t\t\t\tproblemAt(\n\t\t\t\t\tsource,\n\t\t\t\t\tfile,\n\t\t\t\t\tspan?.valueStart ?? 0,\n\t\t\t\t\tspan?.valueLength ?? 0,\n\t\t\t\t\t'browser-placeholder',\n\t\t\t\t\t`'${formatPath(path) || '(root)'}' uses an environment placeholder, which browser builds cannot read`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (Array.isArray(item)) for (const [index, child] of item.entries()) visit(child, [...path, index]);\n\t\telse if (isPlainObject(item)) for (const [key, child] of Object.entries(item)) visit(child, [...path, key]);\n\t};\n\tvisit(value, []);\n\treturn problems;\n};\n\nconst failingCode = (file: string, problems: readonly Problem[]) =>\n\t`throw new Error(${JSON.stringify(`Invalid config ${file}\\n${formatProblems(problems)}`)});\\n\\nexport default undefined;\\n`;\n\nconst serverModule = Effect.fn('serverModule')(function* (file: string, options: LoadOptions) {\n\tconst problems: Problem[] = [];\n\tif (!parseConfigFileName(basename(file))) {\n\t\tproblems.push(\n\t\t\tfileProblem(\n\t\t\t\tfile,\n\t\t\t\t'unsupported-file',\n\t\t\t\t`${basename(file)} is not a config file; expected a name ending in ${configSuffixes.join(', ')}`,\n\t\t\t),\n\t\t);\n\t} else if (!(yield* isFile(file))) problems.push(fileProblem(file, 'file-not-found', `Cannot find ${file}`));\n\n\tconst settings =\n\t\toptions.environment === undefined ? '' : `, { environment: ${JSON.stringify(options.environment)} }`;\n\tconst code = `import { resolveConfigModule } from ${JSON.stringify(options.runtime ?? 'tyfigo/runtime')};\\n\\nexport default resolveConfigModule(${JSON.stringify(file)}${settings});\\n`;\n\tconst environment = options.environment ?? (processEnv().NODE_ENV || undefined);\n\treturn { code, watchFiles: yield* watchFilesOf(file, environment, 'server'), problems } satisfies LoadResult;\n});\n\nconst browserModule = Effect.fn('browserModule')(function* (file: string, options: LoadOptions) {\n\tconst environment = options.environment ?? (processEnv().NODE_ENV || undefined);\n\tconst result = yield* resolveConfig(file, { environment, env: {}, layers: browserLayers });\n\tconst files = new Set([result.file, ...result.layers.map((layer) => layer.file)]);\n\tconst problems = result.problems.filter(\n\t\t(problem) =>\n\t\t\tfiles.has(problem.file) && problem.code !== 'missing-variable' && problem.code !== 'invalid-placeholder',\n\t);\n\tfor (const layer of result.layers) {\n\t\tconst parsed = result.format?.parse(layer.text, layer.file);\n\t\tif (parsed?.value !== undefined) {\n\t\t\tproblems.push(...placeholderProblems(layer.file, layer.text, parsed.value, layer.positions));\n\t\t}\n\t}\n\n\tconst code =\n\t\tproblems.length > 0\n\t\t\t? failingCode(result.file, problems)\n\t\t\t: `export default ${valueLiteral(result.value, '')};\\n`;\n\treturn {\n\t\tcode,\n\t\twatchFiles: yield* watchFilesOf(result.file, environment, 'browser'),\n\t\tproblems,\n\t} satisfies LoadResult;\n});\n\nconst layerOrder: Readonly<Record<LayerKind, number>> = { base: 0, environment: 1, local: 2, 'environment-local': 3 };\n\nconst bundledServerModule = Effect.fn('bundledServerModule')(function* (file: string, options: LoadOptions) {\n\tconst environments =\n\t\toptions.environment === undefined ? [undefined, ...(yield* discoverEnvironments(file))] : [options.environment];\n\tconst results: ResolvedConfig[] = [];\n\tfor (const environment of environments) {\n\t\tresults.push(\n\t\t\tyield* resolveConfig(file, environment === undefined ? { layers: ['base', 'local'] } : { environment }),\n\t\t);\n\t}\n\n\tconst root = (yield* findProjectRoot(dirname(file))) ?? dirname(file);\n\tconst name = (path: string) => relative(root, path).split(sep).join('/');\n\tconst problems = new Map<string, Problem>();\n\tconst layers = new Map<string, BundledLayer>();\n\tfor (const result of results) {\n\t\tfor (const problem of result.problems) {\n\t\t\tif (problem.code === 'missing-variable' || problem.code === 'placeholder-type') continue;\n\t\t\tproblems.set(JSON.stringify([problem.file, problem.start, problem.code, problem.message]), problem);\n\t\t}\n\t\tfor (const layer of result.layers) {\n\t\t\tconst specific = layer.kind === 'environment' || layer.kind === 'environment-local';\n\t\t\tlayers.set(layer.file, {\n\t\t\t\tfile: name(layer.file),\n\t\t\t\tkind: layer.kind,\n\t\t\t\t...(specific ? { environment: result.environment } : {}),\n\t\t\t\ttext: layer.text,\n\t\t\t});\n\t\t}\n\t}\n\tconst bundle: BundledConfig = {\n\t\tfile: name(file),\n\t\t...(options.environment === undefined ? {} : { environment: options.environment }),\n\t\tlayers: [...layers.values()].toSorted((a, b) => layerOrder[a.kind] - layerOrder[b.kind]),\n\t};\n\n\tconst watchFiles = new Set<string>();\n\tfor (const environment of new Set([...environments, processEnv().NODE_ENV || undefined])) {\n\t\tfor (const watchFile of yield* watchFilesOf(file, environment, 'server')) watchFiles.add(watchFile);\n\t}\n\tconst code =\n\t\tproblems.size > 0\n\t\t\t? failingCode(file, [...problems.values()])\n\t\t\t: `import { resolveBundledConfigModule } from ${JSON.stringify(options.runtime ?? 'tyfigo/runtime')};\\n\\nexport default resolveBundledConfigModule(${JSON.stringify(bundle)});\\n`;\n\treturn {\n\t\tcode,\n\t\twatchFiles: [...watchFiles],\n\t\tproblems: [...problems.values()],\n\t} satisfies LoadResult;\n});\n\n/**\n * Generates the JavaScript module for a config file import. Loaders fail the import or build when `problems` is not empty.\n */\nexport const loadModule = Effect.fn('loadModule')(function* (path: string, options: LoadOptions) {\n\tconst file = resolve(path);\n\tif (options.target === 'browser') return yield* browserModule(file, options);\n\treturn options.bundle ? yield* bundledServerModule(file, options) : yield* serverModule(file, options);\n});\n\n/**\n * {@link loadModule} for synchronous callers such as Node `registerHooks` load hooks.\n */\nexport const load = (path: string, options: LoadOptions): LoadResult => Effect.runSync(loadModule(path, options));\n"],"mappings":";;;;;;;;AA+DA,MAAM,gBAAgB,CAAC,QAAQ,aAAa;AAE5C,MAAM,eAAe,OAAO,GAAG,cAAc,CAAC,CAAC,WAC9C,MACA,aACA,QACC;CACD,MAAM,OAAO,oBAAoB,SAAS,IAAI,CAAC;CAC/C,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI;CAEvB,MAAM,QAAQ,CAAC,IAAI;CACnB,IAAI,aAAa,MAAM,KAAK,KAAK,QAAQ,IAAI,GAAG,GAAG,KAAK,KAAK,GAAG,cAAc,KAAK,QAAQ,CAAC;CAC5F,IAAI,WAAW,WAAW,OAAO;CAEjC,MAAM,cAAc,OAAO,kBAAkB,IAAI;CACjD,MAAM,SAAS,cACZ,CAAC,GAAG,KAAK,KAAK,QAAQ,KAAK,UAAU,GAAG,KAAK,KAAK,GAAG,YAAY,QAAQ,KAAK,QAAQ,IACtF,CAAC,GAAG,KAAK,KAAK,QAAQ,KAAK,QAAQ;CACtC,KAAK,MAAM,YAAY,CAAC,GAAG,QAAQ,GAAG,aAAa,WAAW,CAAC,GAC9D,KAAK,MAAM,aAAa,aAAa,MAAM,KAAK,KAAK,WAAW,QAAQ,CAAC;CAE1E,OAAO;AACR,CAAC;;;;AAKD,MAAa,gBAAgB,OAAgB,SAAS,OAAe;CACpE,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,GAAG,OAAO,EAAE,IAAI,OAAO,OAAO,KAAK;CAChF,IAAI,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM;CAC/C,IAAI,iBAAiB,MAAM,OAAO,YAAY,aAAa,MAAM,QAAQ,GAAG,MAAM,EAAE;CACpF,MAAM,QAAQ,GAAG,OAAO;CACxB,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzB,IAAI,MAAM,WAAW,GAAG,OAAO;EAE/B,OAAO,oBADO,MAAM,KAAK,SAAS,GAAG,QAAQ,aAAa,MAAM,KAAK,EAAE,IACxC,CAAC,CAAC,KAAK,EAAE,IAAI,OAAO;CACpD;CACA,IAAI,cAAc,KAAK,GAAG;EACzB,MAAM,UAAU,OAAO,QAAQ,KAAK;EACpC,IAAI,QAAQ,WAAW,GAAG,OAAO;EAKjC,OAAO,oBAJY,QAAQ,KAAK,CAAC,KAAK,UAAU;GAC/C,MAAM,OAAO,QAAQ,cAAc,IAAI,KAAK,UAAU,GAAG,EAAE,KAAK,KAAK,UAAU,GAAG;GAClF,OAAO,GAAG,QAAQ,KAAK,IAAI,aAAa,MAAM,KAAK,EAAE;EACtD,CACoC,CAAC,CAAC,KAAK,EAAE,IAAI,OAAO;CACzD;CACA,OAAO,KAAK,UAAU,KAAK;AAC5B;AAEA,MAAM,2BAA2B,SAAiB,eAAe,KAAK,WAAW,OAAO,EAAE,CAAC;AAE3F,MAAM,uBAAuB,MAAc,MAAc,OAAgB,cAA2B;CACnG,MAAM,SAAS,IAAI,YAAY,IAAI;CACnC,MAAM,WAAsB,CAAC;CAC7B,MAAM,SAAS,MAAe,SAAe;EAC5C,IAAI,OAAO,SAAS,UAAU;GAC7B,IAAI,CAAC,wBAAwB,IAAI,GAAG;GACpC,MAAM,OAAO,UAAU,IAAI,QAAQ,IAAI,CAAC;GACxC,SAAS,KACR,UACC,QACA,MACA,MAAM,cAAc,GACpB,MAAM,eAAe,GACrB,uBACA,IAAI,WAAW,IAAI,KAAK,SAAS,oEAClC,CACD;EACD,OAAO,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK,MAAM,CAAC,OAAO,UAAU,KAAK,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC;OACrG,IAAI,cAAc,IAAI,GAAG,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC;CAC3G;CACA,MAAM,OAAO,CAAC,CAAC;CACf,OAAO;AACR;AAEA,MAAM,eAAe,MAAc,aAClC,mBAAmB,KAAK,UAAU,kBAAkB,KAAK,IAAI,eAAe,QAAQ,GAAG,EAAE;AAE1F,MAAM,eAAe,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,MAAc,SAAsB;CAC7F,MAAM,WAAsB,CAAC;CAC7B,IAAI,CAAC,oBAAoB,SAAS,IAAI,CAAC,GACtC,SAAS,KACR,YACC,MACA,oBACA,GAAG,SAAS,IAAI,EAAE,mDAAmD,eAAe,KAAK,IAAI,GAC9F,CACD;MACM,IAAI,EAAE,OAAO,OAAO,IAAI,IAAI,SAAS,KAAK,YAAY,MAAM,kBAAkB,eAAe,MAAM,CAAC;CAE3G,MAAM,WACL,QAAQ,gBAAgB,KAAA,IAAY,KAAK,oBAAoB,KAAK,UAAU,QAAQ,WAAW,EAAE;CAClG,MAAM,OAAO,uCAAuC,KAAK,UAAU,QAAQ,WAAW,gBAAgB,EAAE,0CAA0C,KAAK,UAAU,IAAI,IAAI,SAAS;CAClL,MAAM,cAAc,QAAQ,gBAAgB,WAAW,CAAC,CAAC,YAAY,KAAA;CACrE,OAAO;EAAE;EAAM,YAAY,OAAO,aAAa,MAAM,aAAa,QAAQ;EAAG;CAAS;AACvF,CAAC;AAED,MAAM,gBAAgB,OAAO,GAAG,eAAe,CAAC,CAAC,WAAW,MAAc,SAAsB;CAC/F,MAAM,cAAc,QAAQ,gBAAgB,WAAW,CAAC,CAAC,YAAY,KAAA;CACrE,MAAM,SAAS,OAAO,cAAc,MAAM;EAAE;EAAa,KAAK,CAAC;EAAG,QAAQ;CAAc,CAAC;CACzF,MAAM,wBAAQ,IAAI,IAAI,CAAC,OAAO,MAAM,GAAG,OAAO,OAAO,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC;CAChF,MAAM,WAAW,OAAO,SAAS,QAC/B,YACA,MAAM,IAAI,QAAQ,IAAI,KAAK,QAAQ,SAAS,sBAAsB,QAAQ,SAAS,qBACrF;CACA,KAAK,MAAM,SAAS,OAAO,QAAQ;EAClC,MAAM,SAAS,OAAO,QAAQ,MAAM,MAAM,MAAM,MAAM,IAAI;EAC1D,IAAI,QAAQ,UAAU,KAAA,GACrB,SAAS,KAAK,GAAG,oBAAoB,MAAM,MAAM,MAAM,MAAM,OAAO,OAAO,MAAM,SAAS,CAAC;CAE7F;CAMA,OAAO;EACN,MAJA,SAAS,SAAS,IACf,YAAY,OAAO,MAAM,QAAQ,IACjC,kBAAkB,aAAa,OAAO,OAAO,EAAE,EAAE;EAGpD,YAAY,OAAO,aAAa,OAAO,MAAM,aAAa,SAAS;EACnE;CACD;AACD,CAAC;AAED,MAAM,aAAkD;CAAE,MAAM;CAAG,aAAa;CAAG,OAAO;CAAG,qBAAqB;AAAE;AAEpH,MAAM,sBAAsB,OAAO,GAAG,qBAAqB,CAAC,CAAC,WAAW,MAAc,SAAsB;CAC3G,MAAM,eACL,QAAQ,gBAAgB,KAAA,IAAY,CAAC,KAAA,GAAW,GAAI,OAAO,qBAAqB,IAAI,CAAE,IAAI,CAAC,QAAQ,WAAW;CAC/G,MAAM,UAA4B,CAAC;CACnC,KAAK,MAAM,eAAe,cACzB,QAAQ,KACP,OAAO,cAAc,MAAM,gBAAgB,KAAA,IAAY,EAAE,QAAQ,CAAC,QAAQ,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CACvG;CAGD,MAAM,QAAQ,OAAO,gBAAgB,QAAQ,IAAI,CAAC,MAAM,QAAQ,IAAI;CACpE,MAAM,QAAQ,SAAiB,SAAS,MAAM,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;CACvE,MAAM,2BAAW,IAAI,IAAqB;CAC1C,MAAM,yBAAS,IAAI,IAA0B;CAC7C,KAAK,MAAM,UAAU,SAAS;EAC7B,KAAK,MAAM,WAAW,OAAO,UAAU;GACtC,IAAI,QAAQ,SAAS,sBAAsB,QAAQ,SAAS,oBAAoB;GAChF,SAAS,IAAI,KAAK,UAAU;IAAC,QAAQ;IAAM,QAAQ;IAAO,QAAQ;IAAM,QAAQ;GAAO,CAAC,GAAG,OAAO;EACnG;EACA,KAAK,MAAM,SAAS,OAAO,QAAQ;GAClC,MAAM,WAAW,MAAM,SAAS,iBAAiB,MAAM,SAAS;GAChE,OAAO,IAAI,MAAM,MAAM;IACtB,MAAM,KAAK,MAAM,IAAI;IACrB,MAAM,MAAM;IACZ,GAAI,WAAW,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;IACtD,MAAM,MAAM;GACb,CAAC;EACF;CACD;CACA,MAAM,SAAwB;EAC7B,MAAM,KAAK,IAAI;EACf,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,QAAQ,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,WAAW,EAAE,QAAQ,WAAW,EAAE,KAAK;CACxF;CAEA,MAAM,6BAAa,IAAI,IAAY;CACnC,KAAK,MAAM,+BAAe,IAAI,IAAI,CAAC,GAAG,cAAc,WAAW,CAAC,CAAC,YAAY,KAAA,CAAS,CAAC,GACtF,KAAK,MAAM,aAAa,OAAO,aAAa,MAAM,aAAa,QAAQ,GAAG,WAAW,IAAI,SAAS;CAMnG,OAAO;EACN,MAJA,SAAS,OAAO,IACb,YAAY,MAAM,CAAC,GAAG,SAAS,OAAO,CAAC,CAAC,IACxC,8CAA8C,KAAK,UAAU,QAAQ,WAAW,gBAAgB,EAAE,iDAAiD,KAAK,UAAU,MAAM,EAAE;EAG7K,YAAY,CAAC,GAAG,UAAU;EAC1B,UAAU,CAAC,GAAG,SAAS,OAAO,CAAC;CAChC;AACD,CAAC;;;;AAKD,MAAa,aAAa,OAAO,GAAG,YAAY,CAAC,CAAC,WAAW,MAAc,SAAsB;CAChG,MAAM,OAAO,QAAQ,IAAI;CACzB,IAAI,QAAQ,WAAW,WAAW,OAAO,OAAO,cAAc,MAAM,OAAO;CAC3E,OAAO,QAAQ,SAAS,OAAO,oBAAoB,MAAM,OAAO,IAAI,OAAO,aAAa,MAAM,OAAO;AACtG,CAAC;;;;AAKD,MAAa,QAAQ,MAAc,YAAqC,OAAO,QAAQ,WAAW,MAAM,OAAO,CAAC"}
@@ -9,7 +9,8 @@ interface LoadOptions {
9
9
  readonly target: LoadTarget;
10
10
  /**
11
11
  * The environment name, such as the bundler's mode. Defaults to `NODE_ENV`, read when the server module runs and when
12
- * `load` runs for the browser.
12
+ * `load` runs for the browser. A bundled server module inlines only this environment's files when it is given, and every
13
+ * environment's files otherwise.
13
14
  */
14
15
  readonly environment?: string | undefined;
15
16
  /**
@@ -17,8 +18,9 @@ interface LoadOptions {
17
18
  */
18
19
  readonly runtime?: string | undefined;
19
20
  /**
20
- * For `server`: inline the text of the layer files that exist at build time, and read `.env` files and environment variables
21
- * from `process.cwd()` when the module runs, so a bundle does not depend on the paths of the machine that built it.
21
+ * For `server`: inline the text of the layer files that exist at build time, for every environment unless `environment` is
22
+ * given, and pick the environment's layers and read `.env` files and environment variables from `process.cwd()` when the
23
+ * module runs, so a bundle does not depend on the paths of the machine that built it.
22
24
  */
23
25
  readonly bundle?: boolean | undefined;
24
26
  }
@@ -50,4 +52,4 @@ declare const loadModule: (path: string, options: LoadOptions) => Effect.Effect<
50
52
  */
51
53
  declare const load: (path: string, options: LoadOptions) => LoadResult;
52
54
  export { loadModule as a, load as i, LoadResult as n, valueLiteral as o, LoadTarget as r, LoadOptions as t };
53
- //# sourceMappingURL=load-C-kweoyY.d.mts.map
55
+ //# sourceMappingURL=load-D1KO5LdK.d.mts.map
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("esbuild").Plugin;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=esbuild.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/esbuild.ts
3
3
  var esbuild_default = tyfigo.esbuild;
4
4
  export { esbuild_default as default };
@@ -1,4 +1,4 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
2
  import { SyncTransformer } from "@jest/transform";
3
3
  export type TyfigoJestOptions = Omit<TyfigoPluginOptions, 'target'>;
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { n as formatProblems } from "../problems-BNAqmOzL.mjs";
2
- import { n as resolveConfigSync } from "../sync-B-HAK-_E.mjs";
3
- import { r as valueLiteral } from "../load-DxIjRpX6.mjs";
4
- import { i as loadConfigImport } from "../shared-BnK77Zcp.mjs";
2
+ import { n as resolveConfigSync } from "../sync-DYO2PsXt.mjs";
3
+ import { r as valueLiteral } from "../load-BZqp318Y.mjs";
4
+ import { i as loadConfigImport } from "../shared-Cndg8CKC.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  // src/plugins/jest.ts
7
7
  const generate = (file, options) => {
@@ -1,4 +1,4 @@
1
- import { n as WebpackLikePlatform, t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
1
+ import { n as WebpackLikePlatform, t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
2
  export interface TyfigoLoaderContext {
3
3
  readonly resourcePath: string;
4
4
  readonly getOptions: () => TyfigoPluginOptions;
@@ -1,4 +1,4 @@
1
- import { i as loadConfigImport, n as findNodeOnlyImports, r as isServerPlatform, t as configFilePattern } from "../shared-BnK77Zcp.mjs";
1
+ import { i as loadConfigImport, n as findNodeOnlyImports, r as isServerPlatform, t as configFilePattern } from "../shared-Cndg8CKC.mjs";
2
2
  // src/plugins/loader.ts
3
3
  /**
4
4
  * A webpack loader for config files, for webpack-compatible loader runners such as Turbopack's. Without a `target` option it
@@ -1,4 +1,4 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
2
  import { NextConfig } from "next";
3
3
  export interface WithTyfigoOptions extends Omit<TyfigoPluginOptions, 'target'> {
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { t as configSuffixes } from "../formats-D_dKXoPf.mjs";
2
- import { t as configFilePattern } from "../shared-BnK77Zcp.mjs";
2
+ import { t as configFilePattern } from "../shared-Cndg8CKC.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { dirname, extname, join, resolve } from "node:path";
5
5
  import process from "node:process";
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("rolldown").Plugin<any>;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=rolldown.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/rolldown.ts
3
3
  var rolldown_default = tyfigo.rolldown;
4
4
  export { rolldown_default as default };
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("rollup").Plugin<any>;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=rollup.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/rollup.ts
3
3
  var rollup_default = tyfigo.rollup;
4
4
  export { rollup_default as default };
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("unplugin").RsbuildPlugin;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=rsbuild.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/rsbuild.ts
3
3
  var rsbuild_default = tyfigo.rsbuild;
4
4
  export { rsbuild_default as default };
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("unplugin").RspackPluginInstance;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=rspack.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/rspack.ts
3
3
  var rspack_default = tyfigo.rspack;
4
4
  export { rspack_default as default };
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("vite").Plugin<any>;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=vite.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/vite.ts
3
3
  var vite_default = tyfigo.vite;
4
4
  export { vite_default as default };
@@ -1,5 +1,5 @@
1
- import { t as TyfigoPluginOptions } from "../shared-CZ44uwQq.mjs";
2
- import "../unplugin-AC_HM_T2.mjs";
1
+ import { t as TyfigoPluginOptions } from "../shared-B6Y3_kdn.mjs";
2
+ import "../unplugin-BYfqHkIE.mjs";
3
3
  declare const _default: (options?: TyfigoPluginOptions | undefined) => import("webpack").WebpackPluginInstance;
4
4
  export { type TyfigoPluginOptions, _default as default };
5
5
  //# sourceMappingURL=webpack.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as tyfigo } from "../unplugin-BQGm_bhA.mjs";
1
+ import { t as tyfigo } from "../unplugin-DaIHdNM0.mjs";
2
2
  // src/plugins/webpack.ts
3
3
  var webpack_default = tyfigo.webpack;
4
4
  export { webpack_default as default };
package/dist/register.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as formatProblems } from "./problems-BNAqmOzL.mjs";
2
2
  import { n as parseConfigFileName } from "./formats-D_dKXoPf.mjs";
3
- import { t as load } from "./load-DxIjRpX6.mjs";
3
+ import { t as load } from "./load-BZqp318Y.mjs";
4
4
  import { registerHooks } from "node:module";
5
5
  import { basename, extname } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
@@ -1,4 +1,4 @@
1
- import { i as findFile, n as processEnv, o as isFile, r as readEnv, s as searchDirectories } from "./env-R3_XPW_u.mjs";
1
+ import { c as searchDirectories, i as findFile, n as processEnv, o as isFile, r as readEnv, s as listDirectory } from "./env-CWXftFpA.mjs";
2
2
  import { r as problemAt, t as fileProblem } from "./problems-BNAqmOzL.mjs";
3
3
  import { n as formatPath, r as pathKey, t as SourceIndex } from "./positions-BCTEFZTX.mjs";
4
4
  import { a as kindOf, i as isPlainObject, n as parseConfigFileName, o as resolvePlaceholders, t as configSuffixes } from "./formats-D_dKXoPf.mjs";
@@ -42,6 +42,25 @@ const discoverLayers = Effect.fn("discoverLayers")(function* (baseFile, environm
42
42
  }
43
43
  return layers;
44
44
  });
45
+ /**
46
+ * The environment names that have a layer file for a base config file: every `app.<environment>.config.yaml` next to it, and
47
+ * every `app.<environment>.local.config.yaml` where {@link discoverLayers} searches local files. Sorted.
48
+ */
49
+ const discoverEnvironments = Effect.fn("discoverEnvironments")(function* (baseFile) {
50
+ const file = resolve(baseFile);
51
+ const name = parseConfigFileName(basename(file));
52
+ if (!name) return [];
53
+ const environments = /* @__PURE__ */ new Set();
54
+ for (const directory of yield* searchDirectories(file)) for (const entry of yield* listDirectory(directory)) {
55
+ if (!entry.startsWith(`${name.stem}.`) || !entry.endsWith(name.suffix)) continue;
56
+ const middle = entry.slice(name.stem.length + 1, -name.suffix.length);
57
+ const local = middle.endsWith(".local");
58
+ const environment = local ? middle.slice(0, -6) : middle;
59
+ if (!local && directory !== dirname(file)) continue;
60
+ if (/^[^.]+$/u.test(environment) && environment !== "local") environments.add(environment);
61
+ }
62
+ return [...environments].toSorted((a, b) => a.localeCompare(b));
63
+ });
45
64
  // src/core/merge.ts
46
65
  const isWithin = (id, prefix) => id === prefix || id.startsWith(prefix === "[]" ? "[" : `${prefix.slice(0, -1)},`);
47
66
  const locate = (file, positions) => new Map([...positions].map(([id, span]) => [id, {
@@ -237,6 +256,6 @@ const resolveConfigSources = Effect.fn("resolveConfigSources")(function* (file,
237
256
  problems: [...envResult.problems, ...merged.problems]
238
257
  };
239
258
  });
240
- export { resolveConfigSources as n, resolveConfig as t };
259
+ export { resolveConfigSources as n, discoverEnvironments as r, resolveConfig as t };
241
260
 
242
- //# sourceMappingURL=resolve-D3geHCGs.mjs.map
261
+ //# sourceMappingURL=resolve-DTfgGkq5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-DTfgGkq5.mjs","names":[],"sources":["../src/core/layers.ts","../src/core/merge.ts","../src/core/resolve.ts"],"sourcesContent":["import { basename, dirname, join, resolve } from 'node:path';\n\nimport { Effect } from 'effect';\n\nimport { findFile, isFile, listDirectory, searchDirectories } from './files.ts';\nimport { parseConfigFileName } from './formats/index.ts';\n\nexport type LayerKind = 'base' | 'environment' | 'local' | 'environment-local';\n\nexport interface LayerFile {\n\treadonly file: string;\n\treadonly kind: LayerKind;\n}\n\n/**\n * The layer files of a base config file, in the order they apply: `app.config.yaml`, `app.<environment>.config.yaml`,\n * `app.local.config.yaml` and `app.<environment>.local.config.yaml`. Only files that exist are listed. Environment files sit next\n * to the base file, and local files are searched next to it first, then in the nearest directory with a `package.json`.\n */\nexport const discoverLayers = Effect.fn('discoverLayers')(function* (baseFile: string, environment?: string) {\n\tconst file = resolve(baseFile);\n\tconst name = parseConfigFileName(basename(file));\n\tif (!name) return [];\n\n\tconst directories = yield* searchDirectories(file);\n\tconst layers: LayerFile[] = [];\n\tif (yield* isFile(file)) layers.push({ file, kind: 'base' });\n\tif (environment) {\n\t\tconst environmentFile = join(dirname(file), `${name.stem}.${environment}${name.suffix}`);\n\t\tif (yield* isFile(environmentFile)) layers.push({ file: environmentFile, kind: 'environment' });\n\t}\n\n\tconst local = yield* findFile(directories, `${name.stem}.local${name.suffix}`);\n\tif (local) layers.push({ file: local, kind: 'local' });\n\tif (environment) {\n\t\tconst environmentLocal = yield* findFile(directories, `${name.stem}.${environment}.local${name.suffix}`);\n\t\tif (environmentLocal) layers.push({ file: environmentLocal, kind: 'environment-local' });\n\t}\n\n\treturn layers;\n});\n\n/**\n * The environment names that have a layer file for a base config file: every `app.<environment>.config.yaml` next to it, and\n * every `app.<environment>.local.config.yaml` where {@link discoverLayers} searches local files. Sorted.\n */\nexport const discoverEnvironments = Effect.fn('discoverEnvironments')(function* (baseFile: string) {\n\tconst file = resolve(baseFile);\n\tconst name = parseConfigFileName(basename(file));\n\tif (!name) return [];\n\n\tconst environments = new Set<string>();\n\tfor (const directory of yield* searchDirectories(file)) {\n\t\tfor (const entry of yield* listDirectory(directory)) {\n\t\t\tif (!entry.startsWith(`${name.stem}.`) || !entry.endsWith(name.suffix)) continue;\n\t\t\tconst middle = entry.slice(name.stem.length + 1, -name.suffix.length);\n\t\t\tconst local = middle.endsWith('.local');\n\t\t\tconst environment = local ? middle.slice(0, -'.local'.length) : middle;\n\t\t\tif (!local && directory !== dirname(file)) continue;\n\t\t\tif (/^[^.]+$/u.test(environment) && environment !== 'local') environments.add(environment);\n\t\t}\n\t}\n\treturn [...environments].toSorted((a, b) => a.localeCompare(b));\n});\n","import { basename } from 'node:path';\n\nimport { isPlainObject, kindOf } from './placeholders.ts';\nimport { formatPath, pathKey } from './positions.ts';\nimport { problemAt } from './problems.ts';\n\nimport type { Path, PositionMap, SourceIndex, Span } from './positions.ts';\nimport type { Problem } from './problems.ts';\n\n/**\n * A {@link Span} together with the file it is in.\n */\nexport interface LocatedSpan extends Span {\n\treadonly file: string;\n}\n\nexport interface MergeLayer {\n\treadonly file: string;\n\treadonly value: unknown;\n\treadonly positions: PositionMap;\n\treadonly source: SourceIndex;\n}\n\nexport interface MergeResult {\n\treadonly value: unknown;\n\treadonly positions: ReadonlyMap<string, LocatedSpan>;\n\treadonly problems: readonly Problem[];\n}\n\nconst isWithin = (id: string, prefix: string) =>\n\tid === prefix || id.startsWith(prefix === '[]' ? '[' : `${prefix.slice(0, -1)},`);\n\nexport const locate = (file: string, positions: PositionMap): Map<string, LocatedSpan> =>\n\tnew Map([...positions].map(([id, span]) => [id, { ...span, file }]));\n\n/**\n * Applies `layer` over `base`. Objects merge, arrays and primitives replace. A key that `base` lacks, or a value of a different\n * type (`null`, boolean, number, string, array or object), is a problem and that part of the layer is skipped.\n */\nexport const mergeLayer = (\n\tbase: { readonly value: unknown; readonly positions: ReadonlyMap<string, LocatedSpan> },\n\tlayer: MergeLayer,\n): MergeResult => {\n\tconst positions = new Map(base.positions);\n\tconst problems: Problem[] = [];\n\n\tconst report = (path: Path, onKey: boolean, code: 'unknown-key' | 'type-mismatch', message: string) => {\n\t\tconst span = layer.positions.get(pathKey(path));\n\t\tconst start = span ? (onKey ? span.keyStart : span.valueStart) : 0;\n\t\tconst length = span ? (onKey ? span.keyLength : span.valueLength) : 0;\n\t\tproblems.push(problemAt(layer.source, layer.file, start, length, code, message));\n\t};\n\n\tconst origin = (path: Path) => {\n\t\tconst file = positions.get(pathKey(path))?.file;\n\t\treturn file ? basename(file) : 'the base file';\n\t};\n\n\tconst replace = (path: Path) => {\n\t\tconst prefix = pathKey(path);\n\t\tfor (const id of positions.keys()) if (isWithin(id, prefix)) positions.delete(id);\n\t\tfor (const [id, span] of layer.positions) {\n\t\t\tif (isWithin(id, prefix)) positions.set(id, { ...span, file: layer.file });\n\t\t}\n\t};\n\n\tconst merge = (current: unknown, next: unknown, path: Path): unknown => {\n\t\tif (isPlainObject(current) && isPlainObject(next)) {\n\t\t\tconst result = { ...current };\n\t\t\tfor (const [key, value] of Object.entries(next)) {\n\t\t\t\tconst childPath = [...path, key];\n\t\t\t\tif (Object.hasOwn(current, key)) result[key] = merge(current[key], value, childPath);\n\t\t\t\telse {\n\t\t\t\t\treport(\n\t\t\t\t\t\tchildPath,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t'unknown-key',\n\t\t\t\t\t\t`'${formatPath(childPath)}' is not in ${origin(path)}; environment and local files can only override existing keys`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tconst expected = kindOf(current);\n\t\tconst actual = kindOf(next);\n\t\tif (expected !== actual) {\n\t\t\treport(\n\t\t\t\tpath,\n\t\t\t\tfalse,\n\t\t\t\t'type-mismatch',\n\t\t\t\t`Expected ${expected} at '${formatPath(path) || '(root)'}' as in ${origin(path)}, got ${actual}`,\n\t\t\t);\n\t\t\treturn current;\n\t\t}\n\n\t\treplace(path);\n\t\treturn next;\n\t};\n\n\treturn { value: merge(base.value, layer.value, []), positions, problems };\n};\n","import { readFileSync } from 'node:fs';\nimport { basename, resolve } from 'node:path';\n\nimport { Effect, Result } from 'effect';\n\nimport { processEnv, readEnv } from './env.ts';\nimport { isFile } from './files.ts';\nimport { configSuffixes, parseConfigFileName } from './formats/index.ts';\nimport { discoverLayers } from './layers.ts';\nimport { locate, mergeLayer } from './merge.ts';\nimport { resolvePlaceholders } from './placeholders.ts';\nimport { SourceIndex } from './positions.ts';\nimport { fileProblem } from './problems.ts';\n\nimport type { EnvVariables } from './env.ts';\nimport type { Format } from './formats/index.ts';\nimport type { LayerFile, LayerKind } from './layers.ts';\nimport type { LocatedSpan } from './merge.ts';\nimport type { Path, PositionMap } from './positions.ts';\nimport type { Problem } from './problems.ts';\n\nexport interface ResolveOptions {\n\t/**\n\t * The real environment variables, which win over every `.env` file. Defaults to a copy of the current ones.\n\t */\n\treadonly env?: EnvVariables | undefined;\n\t/**\n\t * The environment name that picks `app.<environment>.config.yaml` and `.env.<environment>`. Defaults to `env.NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The layer kinds to read. Defaults to all of them.\n\t */\n\treadonly layers?: readonly LayerKind[] | undefined;\n}\n\nexport interface ResolvedLayer {\n\treadonly file: string;\n\treadonly kind: LayerKind;\n\treadonly text: string;\n\t/**\n\t * The parsed value with placeholders resolved, or `undefined` when the file could not be parsed.\n\t */\n\treadonly value: unknown;\n\treadonly positions: PositionMap;\n}\n\nexport interface ResolvedConfig {\n\t/**\n\t * The base file, resolved to an absolute path.\n\t */\n\treadonly file: string;\n\treadonly format: Format | undefined;\n\treadonly environment: string | undefined;\n\t/**\n\t * The merged value, or `undefined` when the base file is missing or could not be parsed.\n\t */\n\treadonly value: unknown;\n\treadonly layers: readonly ResolvedLayer[];\n\treadonly envFiles: readonly string[];\n\t/**\n\t * Where each key path of `value` came from, keyed by `pathKey`.\n\t */\n\treadonly positions: ReadonlyMap<string, LocatedSpan>;\n\treadonly problems: readonly Problem[];\n}\n\nconst readText = (file: string) =>\n\tEffect.try({\n\t\ttry: () => readFileSync(file, 'utf8'),\n\t\tcatch: (error) => fileProblem(file, 'read-error', `Cannot read ${file}: ${(error as Error).message}`),\n\t});\n\nconst valueAt = (value: unknown, path: Path): unknown =>\n\tpath.reduce<unknown>(\n\t\t(current, segment) =>\n\t\t\ttypeof current === 'object' && current !== null && Object.hasOwn(current, segment)\n\t\t\t\t? (current as Record<string | number, unknown>)[segment]\n\t\t\t\t: undefined,\n\t\tvalue,\n\t);\n\nconst mergeLayers = Effect.fn('mergeLayers')(function* <Layer extends LayerFile>(\n\tformat: Format,\n\tfiles: readonly Layer[],\n\tread: (layer: Layer) => Effect.Effect<string, Problem>,\n\tvariables: EnvVariables,\n) {\n\tconst problems: Problem[] = [];\n\tconst layers: ResolvedLayer[] = [];\n\tlet merged: { value: unknown; positions: ReadonlyMap<string, LocatedSpan> } | undefined;\n\n\tfor (const layer of files) {\n\t\tconst content = yield* Effect.result(read(layer));\n\t\tif (Result.isFailure(content)) {\n\t\t\tproblems.push(content.failure);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst text = content.success;\n\t\tconst parsed = format.parse(text, layer.file);\n\t\tproblems.push(...parsed.problems);\n\t\tconst source = new SourceIndex(text);\n\t\tconst base = merged?.value;\n\t\tconst resolved =\n\t\t\tparsed.value === undefined\n\t\t\t\t? { value: undefined, problems: [] }\n\t\t\t\t: resolvePlaceholders({\n\t\t\t\t\t\tvalue: parsed.value,\n\t\t\t\t\t\tpositions: parsed.positions,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\tfile: layer.file,\n\t\t\t\t\t\tformat,\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t\tbaseValueAt: merged && ((path) => valueAt(base, path)),\n\t\t\t\t\t});\n\t\tproblems.push(...resolved.problems);\n\t\tlayers.push({ file: layer.file, kind: layer.kind, text, value: resolved.value, positions: parsed.positions });\n\t\tif (resolved.value === undefined) continue;\n\n\t\tif (!merged) {\n\t\t\tmerged =\n\t\t\t\tlayer.kind === 'base'\n\t\t\t\t\t? { value: resolved.value, positions: locate(layer.file, parsed.positions) }\n\t\t\t\t\t: undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tconst result = mergeLayer(merged, {\n\t\t\tfile: layer.file,\n\t\t\tvalue: resolved.value,\n\t\t\tpositions: parsed.positions,\n\t\t\tsource,\n\t\t});\n\t\tproblems.push(...result.problems);\n\t\tmerged = result;\n\t}\n\n\treturn { layers, value: merged?.value, positions: merged?.positions ?? new Map(), problems };\n});\n\nconst unsupportedFile = (file: string) =>\n\tfileProblem(\n\t\tfile,\n\t\t'unsupported-file',\n\t\t`${basename(file)} is not a config file; expected a name ending in ${configSuffixes.join(', ')}`,\n\t);\n\n/**\n * Reads a config file with its environment and local layers and `.env` files, resolves placeholders and merges the layers.\n * Never fails: everything that went wrong is in `problems`.\n */\nexport const resolveConfig = Effect.fn('resolveConfig')(function* (path: string, options: ResolveOptions = {}) {\n\tconst file = resolve(path);\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst name = parseConfigFileName(basename(file));\n\tconst empty = {\n\t\tfile,\n\t\tformat: name?.format,\n\t\tenvironment,\n\t\tvalue: undefined,\n\t\tlayers: [],\n\t\tenvFiles: [],\n\t\tpositions: new Map(),\n\t};\n\tif (!name) return { ...empty, problems: [unsupportedFile(file)] } satisfies ResolvedConfig;\n\tif (!(yield* isFile(file))) {\n\t\treturn {\n\t\t\t...empty,\n\t\t\tproblems: [fileProblem(file, 'file-not-found', `Cannot find ${file}`)],\n\t\t} satisfies ResolvedConfig;\n\t}\n\n\tconst envResult = yield* readEnv(file, { environment, env });\n\tconst files = (yield* discoverLayers(file, environment)).filter(\n\t\t(layer) => !options.layers || options.layers.includes(layer.kind),\n\t);\n\tconst merged = yield* mergeLayers(name.format, files, (layer) => readText(layer.file), envResult.variables);\n\treturn {\n\t\t...empty,\n\t\t...merged,\n\t\tenvFiles: envResult.files,\n\t\tproblems: [...envResult.problems, ...merged.problems],\n\t} satisfies ResolvedConfig;\n});\n\nexport interface LayerSource extends LayerFile {\n\treadonly text: string;\n}\n\nexport interface ResolveSourcesOptions {\n\treadonly env?: EnvVariables | undefined;\n\treadonly environment?: string | undefined;\n\t/**\n\t * A path in the directory to search `.env` files from first, before the nearest directory with a `package.json`.\n\t */\n\treadonly envFrom: string;\n}\n\n/**\n * {@link resolveConfig} for layer files whose text was read earlier, such as the layers a bundler inlined at build time. `file`\n * names the base file and picks the format; it is used as given and never read. Never fails: everything that went wrong is in\n * `problems`.\n */\nexport const resolveConfigSources = Effect.fn('resolveConfigSources')(function* (\n\tfile: string,\n\tsources: readonly LayerSource[],\n\toptions: ResolveSourcesOptions,\n) {\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst name = parseConfigFileName(basename(file));\n\tconst empty = {\n\t\tfile,\n\t\tformat: name?.format,\n\t\tenvironment,\n\t\tvalue: undefined,\n\t\tlayers: [],\n\t\tenvFiles: [],\n\t\tpositions: new Map(),\n\t};\n\tif (!name) return { ...empty, problems: [unsupportedFile(file)] } satisfies ResolvedConfig;\n\n\tconst envResult = yield* readEnv(options.envFrom, { environment, env });\n\tconst merged = yield* mergeLayers(name.format, sources, (layer) => Effect.succeed(layer.text), envResult.variables);\n\treturn {\n\t\t...empty,\n\t\t...merged,\n\t\tenvFiles: envResult.files,\n\t\tproblems: [...envResult.problems, ...merged.problems],\n\t} satisfies ResolvedConfig;\n});\n"],"mappings":";;;;;;;;;;;;;AAmBA,MAAa,iBAAiB,OAAO,GAAG,gBAAgB,CAAC,CAAC,WAAW,UAAkB,aAAsB;CAC5G,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,OAAO,oBAAoB,SAAS,IAAI,CAAC;CAC/C,IAAI,CAAC,MAAM,OAAO,CAAC;CAEnB,MAAM,cAAc,OAAO,kBAAkB,IAAI;CACjD,MAAM,SAAsB,CAAC;CAC7B,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO,KAAK;EAAE;EAAM,MAAM;CAAO,CAAC;CAC3D,IAAI,aAAa;EAChB,MAAM,kBAAkB,KAAK,QAAQ,IAAI,GAAG,GAAG,KAAK,KAAK,GAAG,cAAc,KAAK,QAAQ;EACvF,IAAI,OAAO,OAAO,eAAe,GAAG,OAAO,KAAK;GAAE,MAAM;GAAiB,MAAM;EAAc,CAAC;CAC/F;CAEA,MAAM,QAAQ,OAAO,SAAS,aAAa,GAAG,KAAK,KAAK,QAAQ,KAAK,QAAQ;CAC7E,IAAI,OAAO,OAAO,KAAK;EAAE,MAAM;EAAO,MAAM;CAAQ,CAAC;CACrD,IAAI,aAAa;EAChB,MAAM,mBAAmB,OAAO,SAAS,aAAa,GAAG,KAAK,KAAK,GAAG,YAAY,QAAQ,KAAK,QAAQ;EACvG,IAAI,kBAAkB,OAAO,KAAK;GAAE,MAAM;GAAkB,MAAM;EAAoB,CAAC;CACxF;CAEA,OAAO;AACR,CAAC;;;;;AAMD,MAAa,uBAAuB,OAAO,GAAG,sBAAsB,CAAC,CAAC,WAAW,UAAkB;CAClG,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,OAAO,oBAAoB,SAAS,IAAI,CAAC;CAC/C,IAAI,CAAC,MAAM,OAAO,CAAC;CAEnB,MAAM,+BAAe,IAAI,IAAY;CACrC,KAAK,MAAM,aAAa,OAAO,kBAAkB,IAAI,GACpD,KAAK,MAAM,SAAS,OAAO,cAAc,SAAS,GAAG;EACpD,IAAI,CAAC,MAAM,WAAW,GAAG,KAAK,KAAK,EAAE,KAAK,CAAC,MAAM,SAAS,KAAK,MAAM,GAAG;EACxE,MAAM,SAAS,MAAM,MAAM,KAAK,KAAK,SAAS,GAAG,CAAC,KAAK,OAAO,MAAM;EACpE,MAAM,QAAQ,OAAO,SAAS,QAAQ;EACtC,MAAM,cAAc,QAAQ,OAAO,MAAM,GAAG,EAAgB,IAAI;EAChE,IAAI,CAAC,SAAS,cAAc,QAAQ,IAAI,GAAG;EAC3C,IAAI,WAAW,KAAK,WAAW,KAAK,gBAAgB,SAAS,aAAa,IAAI,WAAW;CAC1F;CAED,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,UAAU,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC/D,CAAC;;AClCD,MAAM,YAAY,IAAY,WAC7B,OAAO,UAAU,GAAG,WAAW,WAAW,OAAO,MAAM,GAAG,OAAO,MAAM,GAAG,EAAE,EAAE,EAAE;AAEjF,MAAa,UAAU,MAAc,cACpC,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI;CAAE,GAAG;CAAM;AAAK,CAAC,CAAC,CAAC;;;;;AAMpE,MAAa,cACZ,MACA,UACiB;CACjB,MAAM,YAAY,IAAI,IAAI,KAAK,SAAS;CACxC,MAAM,WAAsB,CAAC;CAE7B,MAAM,UAAU,MAAY,OAAgB,MAAuC,YAAoB;EACtG,MAAM,OAAO,MAAM,UAAU,IAAI,QAAQ,IAAI,CAAC;EAC9C,MAAM,QAAQ,OAAQ,QAAQ,KAAK,WAAW,KAAK,aAAc;EACjE,MAAM,SAAS,OAAQ,QAAQ,KAAK,YAAY,KAAK,cAAe;EACpE,SAAS,KAAK,UAAU,MAAM,QAAQ,MAAM,MAAM,OAAO,QAAQ,MAAM,OAAO,CAAC;CAChF;CAEA,MAAM,UAAU,SAAe;EAC9B,MAAM,OAAO,UAAU,IAAI,QAAQ,IAAI,CAAC,CAAC,EAAE;EAC3C,OAAO,OAAO,SAAS,IAAI,IAAI;CAChC;CAEA,MAAM,WAAW,SAAe;EAC/B,MAAM,SAAS,QAAQ,IAAI;EAC3B,KAAK,MAAM,MAAM,UAAU,KAAK,GAAG,IAAI,SAAS,IAAI,MAAM,GAAG,UAAU,OAAO,EAAE;EAChF,KAAK,MAAM,CAAC,IAAI,SAAS,MAAM,WAC9B,IAAI,SAAS,IAAI,MAAM,GAAG,UAAU,IAAI,IAAI;GAAE,GAAG;GAAM,MAAM,MAAM;EAAK,CAAC;CAE3E;CAEA,MAAM,SAAS,SAAkB,MAAe,SAAwB;EACvE,IAAI,cAAc,OAAO,KAAK,cAAc,IAAI,GAAG;GAClD,MAAM,SAAS,EAAE,GAAG,QAAQ;GAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;IAChD,MAAM,YAAY,CAAC,GAAG,MAAM,GAAG;IAC/B,IAAI,OAAO,OAAO,SAAS,GAAG,GAAG,OAAO,OAAO,MAAM,QAAQ,MAAM,OAAO,SAAS;SAElF,OACC,WACA,MACA,eACA,IAAI,WAAW,SAAS,EAAE,cAAc,OAAO,IAAI,EAAE,8DACtD;GAEF;GACA,OAAO;EACR;EAEA,MAAM,WAAW,OAAO,OAAO;EAC/B,MAAM,SAAS,OAAO,IAAI;EAC1B,IAAI,aAAa,QAAQ;GACxB,OACC,MACA,OACA,iBACA,YAAY,SAAS,OAAO,WAAW,IAAI,KAAK,SAAS,UAAU,OAAO,IAAI,EAAE,QAAQ,QACzF;GACA,OAAO;EACR;EAEA,QAAQ,IAAI;EACZ,OAAO;CACR;CAEA,OAAO;EAAE,OAAO,MAAM,KAAK,OAAO,MAAM,OAAO,CAAC,CAAC;EAAG;EAAW;CAAS;AACzE;;AClCA,MAAM,YAAY,SACjB,OAAO,IAAI;CACV,WAAW,aAAa,MAAM,MAAM;CACpC,QAAQ,UAAU,YAAY,MAAM,cAAc,eAAe,KAAK,IAAK,MAAgB,SAAS;AACrG,CAAC;AAEF,MAAM,WAAW,OAAgB,SAChC,KAAK,QACH,SAAS,YACT,OAAO,YAAY,YAAY,YAAY,QAAQ,OAAO,OAAO,SAAS,OAAO,IAC7E,QAA6C,WAC9C,KAAA,GACJ,KACD;AAED,MAAM,cAAc,OAAO,GAAG,aAAa,CAAC,CAAC,WAC5C,QACA,OACA,MACA,WACC;CACD,MAAM,WAAsB,CAAC;CAC7B,MAAM,SAA0B,CAAC;CACjC,IAAI;CAEJ,KAAK,MAAM,SAAS,OAAO;EAC1B,MAAM,UAAU,OAAO,OAAO,OAAO,KAAK,KAAK,CAAC;EAChD,IAAI,OAAO,UAAU,OAAO,GAAG;GAC9B,SAAS,KAAK,QAAQ,OAAO;GAC7B;EACD;EAEA,MAAM,OAAO,QAAQ;EACrB,MAAM,SAAS,OAAO,MAAM,MAAM,MAAM,IAAI;EAC5C,SAAS,KAAK,GAAG,OAAO,QAAQ;EAChC,MAAM,SAAS,IAAI,YAAY,IAAI;EACnC,MAAM,OAAO,QAAQ;EACrB,MAAM,WACL,OAAO,UAAU,KAAA,IACd;GAAE,OAAO,KAAA;GAAW,UAAU,CAAC;EAAE,IACjC,oBAAoB;GACpB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB;GACA,MAAM,MAAM;GACZ;GACA;GACA,aAAa,YAAY,SAAS,QAAQ,MAAM,IAAI;EACrD,CAAC;EACJ,SAAS,KAAK,GAAG,SAAS,QAAQ;EAClC,OAAO,KAAK;GAAE,MAAM,MAAM;GAAM,MAAM,MAAM;GAAM;GAAM,OAAO,SAAS;GAAO,WAAW,OAAO;EAAU,CAAC;EAC5G,IAAI,SAAS,UAAU,KAAA,GAAW;EAElC,IAAI,CAAC,QAAQ;GACZ,SACC,MAAM,SAAS,SACZ;IAAE,OAAO,SAAS;IAAO,WAAW,OAAO,MAAM,MAAM,OAAO,SAAS;GAAE,IACzE,KAAA;GACJ;EACD;EACA,MAAM,SAAS,WAAW,QAAQ;GACjC,MAAM,MAAM;GACZ,OAAO,SAAS;GAChB,WAAW,OAAO;GAClB;EACD,CAAC;EACD,SAAS,KAAK,GAAG,OAAO,QAAQ;EAChC,SAAS;CACV;CAEA,OAAO;EAAE;EAAQ,OAAO,QAAQ;EAAO,WAAW,QAAQ,6BAAa,IAAI,IAAI;EAAG;CAAS;AAC5F,CAAC;AAED,MAAM,mBAAmB,SACxB,YACC,MACA,oBACA,GAAG,SAAS,IAAI,EAAE,mDAAmD,eAAe,KAAK,IAAI,GAC9F;;;;;AAMD,MAAa,gBAAgB,OAAO,GAAG,eAAe,CAAC,CAAC,WAAW,MAAc,UAA0B,CAAC,GAAG;CAC9G,MAAM,OAAO,QAAQ,IAAI;CACzB,MAAM,MAAM,QAAQ,OAAO,WAAW;CACtC,MAAM,cAAc,QAAQ,gBAAgB,IAAI,YAAY,KAAA;CAC5D,MAAM,OAAO,oBAAoB,SAAS,IAAI,CAAC;CAC/C,MAAM,QAAQ;EACb;EACA,QAAQ,MAAM;EACd;EACA,OAAO,KAAA;EACP,QAAQ,CAAC;EACT,UAAU,CAAC;EACX,2BAAW,IAAI,IAAI;CACpB;CACA,IAAI,CAAC,MAAM,OAAO;EAAE,GAAG;EAAO,UAAU,CAAC,gBAAgB,IAAI,CAAC;CAAE;CAChE,IAAI,EAAE,OAAO,OAAO,IAAI,IACvB,OAAO;EACN,GAAG;EACH,UAAU,CAAC,YAAY,MAAM,kBAAkB,eAAe,MAAM,CAAC;CACtE;CAGD,MAAM,YAAY,OAAO,QAAQ,MAAM;EAAE;EAAa;CAAI,CAAC;CAC3D,MAAM,SAAS,OAAO,eAAe,MAAM,WAAW,EAAA,CAAG,QACvD,UAAU,CAAC,QAAQ,UAAU,QAAQ,OAAO,SAAS,MAAM,IAAI,CACjE;CACA,MAAM,SAAS,OAAO,YAAY,KAAK,QAAQ,QAAQ,UAAU,SAAS,MAAM,IAAI,GAAG,UAAU,SAAS;CAC1G,OAAO;EACN,GAAG;EACH,GAAG;EACH,UAAU,UAAU;EACpB,UAAU,CAAC,GAAG,UAAU,UAAU,GAAG,OAAO,QAAQ;CACrD;AACD,CAAC;;;;;;AAoBD,MAAa,uBAAuB,OAAO,GAAG,sBAAsB,CAAC,CAAC,WACrE,MACA,SACA,SACC;CACD,MAAM,MAAM,QAAQ,OAAO,WAAW;CACtC,MAAM,cAAc,QAAQ,gBAAgB,IAAI,YAAY,KAAA;CAC5D,MAAM,OAAO,oBAAoB,SAAS,IAAI,CAAC;CAC/C,MAAM,QAAQ;EACb;EACA,QAAQ,MAAM;EACd;EACA,OAAO,KAAA;EACP,QAAQ,CAAC;EACT,UAAU,CAAC;EACX,2BAAW,IAAI,IAAI;CACpB;CACA,IAAI,CAAC,MAAM,OAAO;EAAE,GAAG;EAAO,UAAU,CAAC,gBAAgB,IAAI,CAAC;CAAE;CAEhE,MAAM,YAAY,OAAO,QAAQ,QAAQ,SAAS;EAAE;EAAa;CAAI,CAAC;CACtE,MAAM,SAAS,OAAO,YAAY,KAAK,QAAQ,UAAU,UAAU,OAAO,QAAQ,MAAM,IAAI,GAAG,UAAU,SAAS;CAClH,OAAO;EACN,GAAG;EACH,GAAG;EACH,UAAU,UAAU;EACpB,UAAU,CAAC,GAAG,UAAU,UAAU,GAAG,OAAO,QAAQ;CACrD;AACD,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { o as Problem, t as LayerSource } from "../index-jUM0zKD5.mjs";
2
2
  import { i as getConfigSource, n as SourcePosition, r as configSource, t as ConfigSource } from "../source-BWf_Y0YZ.mjs";
3
- import { a as loadModule, i as load, n as LoadResult, o as valueLiteral, r as LoadTarget, t as LoadOptions } from "../load-C-kweoyY.mjs";
3
+ import { a as loadModule, i as load, n as LoadResult, o as valueLiteral, r as LoadTarget, t as LoadOptions } from "../load-D1KO5LdK.mjs";
4
4
  declare const ConfigModuleError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
5
5
  readonly _tag: "ConfigModuleError";
6
6
  } & Readonly<A>;
@@ -21,17 +21,26 @@ export declare const deepFreeze: <T>(value: T) => T;
21
21
  * generated server module calls when it is evaluated. Throws a {@link ConfigModuleError} listing every problem.
22
22
  */
23
23
  export declare const resolveConfigModule: (file: string, options?: ConfigModuleOptions) => unknown;
24
+ export interface BundledLayer extends LayerSource {
25
+ /**
26
+ * The environment an `environment` or `environment-local` layer belongs to.
27
+ */
28
+ readonly environment?: string | undefined;
29
+ }
24
30
  /**
25
31
  * The layer files a bundled server module carries, with paths relative to the project root of the machine that built it.
26
32
  */
27
33
  export interface BundledConfig {
28
34
  readonly file: string;
35
+ /**
36
+ * The environment the bundle was built for, which wins over `NODE_ENV`.
37
+ */
29
38
  readonly environment?: string | undefined;
30
- readonly layers: readonly LayerSource[];
39
+ readonly layers: readonly BundledLayer[];
31
40
  }
32
41
  /**
33
- * {@link resolveConfigModule} for a bundled server module: merges the layers inlined at build time with the `.env` files found
34
- * from `process.cwd()` and the environment variables.
42
+ * {@link resolveConfigModule} for a bundled server module: picks the inlined layers of the environment (`NODE_ENV` unless the
43
+ * bundle fixes it) and merges them with the `.env` files found from `process.cwd()` and the environment variables.
35
44
  */
36
45
  export declare const resolveBundledConfigModule: (bundle: BundledConfig) => unknown;
37
46
  export { ConfigSource, LoadOptions, LoadResult, LoadTarget, SourcePosition, configSource, getConfigSource, load, loadModule, valueLiteral };
@@ -1,4 +1,4 @@
1
1
  import { n as getConfigSource, t as configSource } from "../source-CcI86kKk.mjs";
2
- import { n as loadModule, r as valueLiteral, t as load } from "../load-DxIjRpX6.mjs";
3
- import { i as resolveConfigModule, n as deepFreeze, r as resolveBundledConfigModule, t as ConfigModuleError } from "../runtime-DeRUtPZ9.mjs";
2
+ import { n as loadModule, r as valueLiteral, t as load } from "../load-BZqp318Y.mjs";
3
+ import { i as resolveConfigModule, n as deepFreeze, r as resolveBundledConfigModule, t as ConfigModuleError } from "../runtime-B-47CreJ.mjs";
4
4
  export { ConfigModuleError, configSource, deepFreeze, getConfigSource, load, loadModule, resolveBundledConfigModule, resolveConfigModule, valueLiteral };
@@ -1,7 +1,8 @@
1
+ import { n as processEnv } from "./env-CWXftFpA.mjs";
1
2
  import { n as formatProblems } from "./problems-BNAqmOzL.mjs";
2
3
  import { r as pathKey, t as SourceIndex } from "./positions-BCTEFZTX.mjs";
3
4
  import { t as configSource } from "./source-CcI86kKk.mjs";
4
- import { n as resolveConfigSync, t as resolveConfigSourcesSync } from "./sync-B-HAK-_E.mjs";
5
+ import { n as resolveConfigSync, t as resolveConfigSourcesSync } from "./sync-DYO2PsXt.mjs";
5
6
  import { Data } from "effect";
6
7
  import { basename, join } from "node:path";
7
8
  import process from "node:process";
@@ -57,13 +58,16 @@ const toModule = (result) => {
57
58
  */
58
59
  const resolveConfigModule = (file, options = {}) => toModule(resolveConfigSync(file, { environment: options.environment }));
59
60
  /**
60
- * {@link resolveConfigModule} for a bundled server module: merges the layers inlined at build time with the `.env` files found
61
- * from `process.cwd()` and the environment variables.
61
+ * {@link resolveConfigModule} for a bundled server module: picks the inlined layers of the environment (`NODE_ENV` unless the
62
+ * bundle fixes it) and merges them with the `.env` files found from `process.cwd()` and the environment variables.
62
63
  */
63
- const resolveBundledConfigModule = (bundle) => toModule(resolveConfigSourcesSync(bundle.file, bundle.layers, {
64
- environment: bundle.environment,
65
- envFrom: join(process.cwd(), basename(bundle.file))
66
- }));
64
+ const resolveBundledConfigModule = (bundle) => {
65
+ const environment = bundle.environment ?? (processEnv().NODE_ENV || void 0);
66
+ return toModule(resolveConfigSourcesSync(bundle.file, bundle.layers.filter((layer) => layer.environment === void 0 || layer.environment === environment), {
67
+ environment,
68
+ envFrom: join(process.cwd(), basename(bundle.file))
69
+ }));
70
+ };
67
71
  export { resolveConfigModule as i, deepFreeze as n, resolveBundledConfigModule as r, ConfigModuleError as t };
68
72
 
69
- //# sourceMappingURL=runtime-DeRUtPZ9.mjs.map
73
+ //# sourceMappingURL=runtime-B-47CreJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-B-47CreJ.mjs","names":[],"sources":["../src/runtime/resolve.ts"],"sourcesContent":["import { basename, join } from 'node:path';\nimport process from 'node:process';\n\nimport { Data } from 'effect';\n\nimport { configSource } from './source.ts';\n\nimport {\n\tformatProblems,\n\tpathKey,\n\tprocessEnv,\n\tresolveConfigSourcesSync,\n\tresolveConfigSync,\n\tSourceIndex,\n} from '../core/index.ts';\n\nimport type { LayerSource, Problem, ResolvedConfig } from '../core/index.ts';\nimport type { ConfigSource } from './source.ts';\n\nexport class ConfigModuleError extends Data.TaggedError('ConfigModuleError')<{\n\treadonly message: string;\n\treadonly file: string;\n\treadonly problems: readonly Problem[];\n}> {}\n\nexport interface ConfigModuleOptions {\n\t/**\n\t * The environment name that picks `app.<environment>.config.yaml` and `.env.<environment>`. Defaults to `NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n}\n\nexport const deepFreeze = <T>(value: T): T => {\n\tif (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {\n\t\tObject.freeze(value);\n\t\tfor (const item of Object.values(value)) deepFreeze(item);\n\t}\n\treturn value;\n};\n\nconst sourceOf = (result: ResolvedConfig): ConfigSource => {\n\tconst texts = new Map(result.layers.map((layer) => [layer.file, layer.text]));\n\tconst indexes = new Map<string, SourceIndex>();\n\tconst indexOf = (file: string) => {\n\t\tconst text = texts.get(file);\n\t\tif (text === undefined) return undefined;\n\t\tconst index = indexes.get(file) ?? new SourceIndex(text);\n\t\tindexes.set(file, index);\n\t\treturn index;\n\t};\n\n\treturn {\n\t\tfile: result.file,\n\t\tenvironment: result.environment,\n\t\tlayers: result.layers.map((layer) => layer.file),\n\t\tenvFiles: result.envFiles,\n\t\tposition: (path) => {\n\t\t\tfor (let depth = path.length; depth >= 0; depth--) {\n\t\t\t\tconst span = result.positions.get(pathKey(path.slice(0, depth)));\n\t\t\t\tif (!span) continue;\n\t\t\t\tconst index = indexOf(span.file);\n\t\t\t\treturn index ? { file: span.file, ...index.lineColumn(span.valueStart) } : undefined;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n};\n\nconst toModule = (result: ResolvedConfig): unknown => {\n\tif (result.problems.length > 0) {\n\t\tthrow new ConfigModuleError({\n\t\t\tmessage: `Invalid config ${result.file}\\n${formatProblems(result.problems)}`,\n\t\t\tfile: result.file,\n\t\t\tproblems: result.problems,\n\t\t});\n\t}\n\n\tif (typeof result.value === 'object' && result.value !== null) {\n\t\tObject.defineProperty(result.value, configSource, { value: sourceOf(result) });\n\t}\n\treturn deepFreeze(result.value);\n};\n\n/**\n * Resolves a config file with its layers, `.env` files and placeholders, and returns the deep-frozen value. This is what a\n * generated server module calls when it is evaluated. Throws a {@link ConfigModuleError} listing every problem.\n */\nexport const resolveConfigModule = (file: string, options: ConfigModuleOptions = {}): unknown =>\n\ttoModule(resolveConfigSync(file, { environment: options.environment }));\n\nexport interface BundledLayer extends LayerSource {\n\t/**\n\t * The environment an `environment` or `environment-local` layer belongs to.\n\t */\n\treadonly environment?: string | undefined;\n}\n\n/**\n * The layer files a bundled server module carries, with paths relative to the project root of the machine that built it.\n */\nexport interface BundledConfig {\n\treadonly file: string;\n\t/**\n\t * The environment the bundle was built for, which wins over `NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n\treadonly layers: readonly BundledLayer[];\n}\n\n/**\n * {@link resolveConfigModule} for a bundled server module: picks the inlined layers of the environment (`NODE_ENV` unless the\n * bundle fixes it) and merges them with the `.env` files found from `process.cwd()` and the environment variables.\n */\nexport const resolveBundledConfigModule = (bundle: BundledConfig): unknown => {\n\tconst environment = bundle.environment ?? (processEnv().NODE_ENV || undefined);\n\treturn toModule(\n\t\tresolveConfigSourcesSync(\n\t\t\tbundle.file,\n\t\t\tbundle.layers.filter((layer) => layer.environment === undefined || layer.environment === environment),\n\t\t\t{ environment, envFrom: join(process.cwd(), basename(bundle.file)) },\n\t\t),\n\t);\n};\n"],"mappings":";;;;;;;;;AAmBA,IAAa,oBAAb,cAAuC,KAAK,YAAY,mBAAmB,CAAC,CAIzE,CAAC;AASJ,MAAa,cAAiB,UAAgB;CAC7C,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG;EAC3E,OAAO,OAAO,KAAK;EACnB,KAAK,MAAM,QAAQ,OAAO,OAAO,KAAK,GAAG,WAAW,IAAI;CACzD;CACA,OAAO;AACR;AAEA,MAAM,YAAY,WAAyC;CAC1D,MAAM,QAAQ,IAAI,IAAI,OAAO,OAAO,KAAK,UAAU,CAAC,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC;CAC5E,MAAM,0BAAU,IAAI,IAAyB;CAC7C,MAAM,WAAW,SAAiB;EACjC,MAAM,OAAO,MAAM,IAAI,IAAI;EAC3B,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;EAC/B,MAAM,QAAQ,QAAQ,IAAI,IAAI,KAAK,IAAI,YAAY,IAAI;EACvD,QAAQ,IAAI,MAAM,KAAK;EACvB,OAAO;CACR;CAEA,OAAO;EACN,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,QAAQ,OAAO,OAAO,KAAK,UAAU,MAAM,IAAI;EAC/C,UAAU,OAAO;EACjB,WAAW,SAAS;GACnB,KAAK,IAAI,QAAQ,KAAK,QAAQ,SAAS,GAAG,SAAS;IAClD,MAAM,OAAO,OAAO,UAAU,IAAI,QAAQ,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM;IACX,MAAM,QAAQ,QAAQ,KAAK,IAAI;IAC/B,OAAO,QAAQ;KAAE,MAAM,KAAK;KAAM,GAAG,MAAM,WAAW,KAAK,UAAU;IAAE,IAAI,KAAA;GAC5E;EAED;CACD;AACD;AAEA,MAAM,YAAY,WAAoC;CACrD,IAAI,OAAO,SAAS,SAAS,GAC5B,MAAM,IAAI,kBAAkB;EAC3B,SAAS,kBAAkB,OAAO,KAAK,IAAI,eAAe,OAAO,QAAQ;EACzE,MAAM,OAAO;EACb,UAAU,OAAO;CAClB,CAAC;CAGF,IAAI,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,MACxD,OAAO,eAAe,OAAO,OAAO,cAAc,EAAE,OAAO,SAAS,MAAM,EAAE,CAAC;CAE9E,OAAO,WAAW,OAAO,KAAK;AAC/B;;;;;AAMA,MAAa,uBAAuB,MAAc,UAA+B,CAAC,MACjF,SAAS,kBAAkB,MAAM,EAAE,aAAa,QAAQ,YAAY,CAAC,CAAC;;;;;AAyBvE,MAAa,8BAA8B,WAAmC;CAC7E,MAAM,cAAc,OAAO,gBAAgB,WAAW,CAAC,CAAC,YAAY,KAAA;CACpE,OAAO,SACN,yBACC,OAAO,MACP,OAAO,OAAO,QAAQ,UAAU,MAAM,gBAAgB,KAAA,KAAa,MAAM,gBAAgB,WAAW,GACpG;EAAE;EAAa,SAAS,KAAK,QAAQ,IAAI,GAAG,SAAS,OAAO,IAAI,CAAC;CAAE,CACpE,CACD;AACD"}
@@ -1,13 +1,14 @@
1
- import { r as LoadTarget } from "./load-C-kweoyY.mjs";
1
+ import { r as LoadTarget } from "./load-D1KO5LdK.mjs";
2
2
  interface TyfigoPluginOptions {
3
3
  /**
4
4
  * Overrides the detected target. `browser` inlines the base and environment files and fails on placeholders and on imports of
5
- * `loadEnv` and the other exports that need Node.js. `server` inlines the base, environment and local files of the build's
6
- * environment and reads `.env` files and environment variables when the bundle runs.
5
+ * `loadEnv` and the other exports that need Node.js. `server` inlines the base, local and every environment's files, and picks
6
+ * the environment's files and reads `.env` files and environment variables when the bundle runs.
7
7
  */
8
8
  readonly target?: LoadTarget | undefined;
9
9
  /**
10
- * The environment name. Defaults to the bundler's mode where it has one (Vite, webpack, Rspack, Rsbuild), otherwise `NODE_ENV`.
10
+ * The environment name. A server bundle reads `NODE_ENV` when it starts unless this is set, which fixes it. Browser builds
11
+ * and the Vite dev server default to the bundler's mode where it has one (Vite, webpack, Rspack, Rsbuild), otherwise `NODE_ENV`.
11
12
  */
12
13
  readonly environment?: string | undefined;
13
14
  /**
@@ -20,4 +21,4 @@ interface WebpackLikePlatform {
20
21
  readonly node?: boolean | null;
21
22
  }
22
23
  export { WebpackLikePlatform as n, TyfigoPluginOptions as t };
23
- //# sourceMappingURL=shared-CZ44uwQq.d.mts.map
24
+ //# sourceMappingURL=shared-B6Y3_kdn.d.mts.map
@@ -1,6 +1,6 @@
1
1
  import { n as formatProblems } from "./problems-BNAqmOzL.mjs";
2
2
  import { t as configSuffixes } from "./formats-D_dKXoPf.mjs";
3
- import { t as load } from "./load-DxIjRpX6.mjs";
3
+ import { t as load } from "./load-BZqp318Y.mjs";
4
4
  // src/plugins/shared.ts
5
5
  const configFilePattern = new RegExp(`(?:${configSuffixes.map((suffix) => suffix.replaceAll(".", String.raw`\.`)).join("|")})$`, "u");
6
6
  /**
@@ -52,4 +52,4 @@ const findNodeOnlyImports = (code, id) => {
52
52
  };
53
53
  export { tyfigoImportPattern as a, loadConfigImport as i, findNodeOnlyImports as n, isServerPlatform as r, configFilePattern as t };
54
54
 
55
- //# sourceMappingURL=shared-BnK77Zcp.mjs.map
55
+ //# sourceMappingURL=shared-Cndg8CKC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-Cndg8CKC.mjs","names":[],"sources":["../src/plugins/shared.ts"],"sourcesContent":["import { configSuffixes, formatProblems } from '../core/index.ts';\nimport { load } from '../runtime/load.ts';\n\nimport type { LoadOptions, LoadResult, LoadTarget } from '../runtime/load.ts';\n\nexport interface TyfigoPluginOptions {\n\t/**\n\t * Overrides the detected target. `browser` inlines the base and environment files and fails on placeholders and on imports of\n\t * `loadEnv` and the other exports that need Node.js. `server` inlines the base, local and every environment's files, and picks\n\t * the environment's files and reads `.env` files and environment variables when the bundle runs.\n\t */\n\treadonly target?: LoadTarget | undefined;\n\t/**\n\t * The environment name. A server bundle reads `NODE_ENV` when it starts unless this is set, which fixes it. Browser builds\n\t * and the Vite dev server default to the bundler's mode where it has one (Vite, webpack, Rspack, Rsbuild), otherwise `NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The specifier server modules import the runtime from. Defaults to `tyfigo/runtime`.\n\t */\n\treadonly runtime?: string | undefined;\n}\n\nexport const configFilePattern = new RegExp(\n\t`(?:${configSuffixes.map((suffix) => suffix.replaceAll('.', String.raw`\\.`)).join('|')})$`,\n\t'u',\n);\n\n/**\n * Generates the module for a config import and throws one error listing every problem, which fails the build.\n */\nexport const loadConfigImport = (file: string, options: LoadOptions): LoadResult => {\n\tconst result = load(file, options);\n\tif (result.problems.length > 0) throw new Error(`Invalid config ${file}\\n${formatProblems(result.problems)}`);\n\treturn result;\n};\n\nexport interface WebpackLikePlatform {\n\treadonly web?: boolean | null;\n\treadonly node?: boolean | null;\n}\n\nexport interface WebpackLikeCompiler {\n\treadonly platform: WebpackLikePlatform;\n\treadonly options: { readonly mode?: string | undefined };\n}\n\nexport const isServerPlatform = (platform: WebpackLikePlatform): boolean => platform.node === true && !platform.web;\n\nconst nodeOnlyExports: Readonly<Record<string, readonly string[]>> = {\n\ttyfigo: ['loadEnv', 'loadEnvAsync'],\n\t'tyfigo/effect': ['loadEnv', 'layerEnv', 'configProviderFromFile', 'layerConfigProviderFromFile'],\n};\n\nconst tyfigoSource = /\\bfrom\\s*[\"'](tyfigo(?:\\/effect)?)[\"']/gu;\n\nexport const tyfigoImportPattern = /[\"']tyfigo(?:\\/effect)?[\"']/u;\n\nconst usesNamespaceMember = (code: string, namespace: string, name: string) =>\n\tnew RegExp(String.raw`(?<![\\w$.])${namespace.replaceAll('$', String.raw`\\$`)}\\s*\\??\\.\\s*${name}\\b`, 'u').test(code);\n\nconst namedSpecifiers = (clause: string): string[] => {\n\tconst open = clause.indexOf('{');\n\tconst close = clause.indexOf('}', open);\n\tif (open === -1 || close === -1) return [];\n\treturn clause\n\t\t.slice(open + 1, close)\n\t\t.split(',')\n\t\t.map((specifier) => specifier.trim().split(/\\s/u)[0] ?? '');\n};\n\n/**\n * Finds imports of the tyfigo exports that need Node.js, such as `loadEnv`, and returns one message per import for a browser\n * build to fail with.\n */\nexport const findNodeOnlyImports = (code: string, id: string): string[] => {\n\tconst messages: string[] = [];\n\tfor (const match of code.matchAll(tyfigoSource)) {\n\t\tconst source = match[1] ?? '';\n\t\tconst start = Math.max(code.lastIndexOf('import', match.index), code.lastIndexOf('export', match.index));\n\t\tconst clause = code.slice(start + 'import'.length, match.index);\n\t\tif (start === -1 || /[;'\"`]/u.test(clause) || /^\\s*type[\\s{]/u.test(clause)) continue;\n\n\t\tconst specifiers = namedSpecifiers(clause);\n\t\tconst namespace = /\\*\\s*as\\s+([\\w$]+)/u.exec(clause)?.[1];\n\t\tconst used = (nodeOnlyExports[source] ?? []).filter(\n\t\t\t(name) =>\n\t\t\t\tspecifiers.includes(name) || (namespace !== undefined && usesNamespaceMember(code, namespace, name)),\n\t\t);\n\t\tconst before = code.slice(0, start);\n\t\tconst location = `${id}:${before.split('\\n').length}:${start - before.lastIndexOf('\\n')}`;\n\t\tfor (const name of used) {\n\t\t\tmessages.push(\n\t\t\t\t`${location} - ${name} from '${source}' reads files and environment variables with Node.js, so it cannot run in a browser bundle. Call it in server code, or set the tyfigo plugin's target option to 'server' if this bundle runs on a server.`,\n\t\t\t);\n\t\t}\n\t}\n\treturn messages;\n};\n"],"mappings":";;;;AAuBA,MAAa,oBAAoB,IAAI,OACpC,MAAM,eAAe,KAAK,WAAW,OAAO,WAAW,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,KACvF,GACD;;;;AAKA,MAAa,oBAAoB,MAAc,YAAqC;CACnF,MAAM,SAAS,KAAK,MAAM,OAAO;CACjC,IAAI,OAAO,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,kBAAkB,KAAK,IAAI,eAAe,OAAO,QAAQ,GAAG;CAC5G,OAAO;AACR;AAYA,MAAa,oBAAoB,aAA2C,SAAS,SAAS,QAAQ,CAAC,SAAS;AAEhH,MAAM,kBAA+D;CACpE,QAAQ,CAAC,WAAW,cAAc;CAClC,iBAAiB;EAAC;EAAW;EAAY;EAA0B;CAA6B;AACjG;AAEA,MAAM,eAAe;AAErB,MAAa,sBAAsB;AAEnC,MAAM,uBAAuB,MAAc,WAAmB,SAC7D,IAAI,OAAO,OAAO,GAAG,cAAc,UAAU,WAAW,KAAK,OAAO,GAAG,IAAI,EAAE,aAAa,KAAK,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI;AAEnH,MAAM,mBAAmB,WAA6B;CACrD,MAAM,OAAO,OAAO,QAAQ,GAAG;CAC/B,MAAM,QAAQ,OAAO,QAAQ,KAAK,IAAI;CACtC,IAAI,SAAS,MAAM,UAAU,IAAI,OAAO,CAAC;CACzC,OAAO,OACL,MAAM,OAAO,GAAG,KAAK,CAAC,CACtB,MAAM,GAAG,CAAC,CACV,KAAK,cAAc,UAAU,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE;AAC5D;;;;;AAMA,MAAa,uBAAuB,MAAc,OAAyB;CAC1E,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,SAAS,KAAK,SAAS,YAAY,GAAG;EAChD,MAAM,SAAS,MAAM,MAAM;EAC3B,MAAM,QAAQ,KAAK,IAAI,KAAK,YAAY,UAAU,MAAM,KAAK,GAAG,KAAK,YAAY,UAAU,MAAM,KAAK,CAAC;EACvG,MAAM,SAAS,KAAK,MAAM,QAAQ,GAAiB,MAAM,KAAK;EAC9D,IAAI,UAAU,MAAM,UAAU,KAAK,MAAM,KAAK,iBAAiB,KAAK,MAAM,GAAG;EAE7E,MAAM,aAAa,gBAAgB,MAAM;EACzC,MAAM,YAAY,sBAAsB,KAAK,MAAM,CAAC,GAAG;EACvD,MAAM,QAAQ,gBAAgB,WAAW,CAAC,EAAA,CAAG,QAC3C,SACA,WAAW,SAAS,IAAI,KAAM,cAAc,KAAA,KAAa,oBAAoB,MAAM,WAAW,IAAI,CACpG;EACA,MAAM,SAAS,KAAK,MAAM,GAAG,KAAK;EAClC,MAAM,WAAW,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI,CAAC,CAAC,OAAO,GAAG,QAAQ,OAAO,YAAY,IAAI;EACtF,KAAK,MAAM,QAAQ,MAClB,SAAS,KACR,GAAG,SAAS,KAAK,KAAK,SAAS,OAAO,0MACvC;CAEF;CACA,OAAO;AACR"}
@@ -1,4 +1,4 @@
1
- import { n as resolveConfigSources, t as resolveConfig } from "./resolve-D3geHCGs.mjs";
1
+ import { n as resolveConfigSources, t as resolveConfig } from "./resolve-DTfgGkq5.mjs";
2
2
  import { Effect } from "effect";
3
3
  // src/core/sync.ts
4
4
  /**
@@ -11,4 +11,4 @@ const resolveConfigSync = (path, options) => Effect.runSync(resolveConfig(path,
11
11
  const resolveConfigSourcesSync = (file, sources, options) => Effect.runSync(resolveConfigSources(file, sources, options));
12
12
  export { resolveConfigSync as n, resolveConfigSourcesSync as t };
13
13
 
14
- //# sourceMappingURL=sync-B-HAK-_E.mjs.map
14
+ //# sourceMappingURL=sync-DYO2PsXt.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-B-HAK-_E.mjs","names":[],"sources":["../src/core/sync.ts"],"sourcesContent":["import { Effect } from 'effect';\n\nimport { resolveConfig, resolveConfigSources } from './resolve.ts';\n\nimport type { LayerSource, ResolveOptions, ResolveSourcesOptions, ResolvedConfig } from './resolve.ts';\n\n/**\n * {@link resolveConfig} for synchronous callers such as Node `registerHooks` load hooks.\n */\nexport const resolveConfigSync = (path: string, options?: ResolveOptions): ResolvedConfig =>\n\tEffect.runSync(resolveConfig(path, options));\n\n/**\n * {@link resolveConfigSources} for synchronous callers such as the module a bundler generates.\n */\nexport const resolveConfigSourcesSync = (\n\tfile: string,\n\tsources: readonly LayerSource[],\n\toptions: ResolveSourcesOptions,\n): ResolvedConfig => Effect.runSync(resolveConfigSources(file, sources, options));\n"],"mappings":";;;;;;AASA,MAAa,qBAAqB,MAAc,YAC/C,OAAO,QAAQ,cAAc,MAAM,OAAO,CAAC;;;;AAK5C,MAAa,4BACZ,MACA,SACA,YACoB,OAAO,QAAQ,qBAAqB,MAAM,SAAS,OAAO,CAAC"}
1
+ {"version":3,"file":"sync-DYO2PsXt.mjs","names":[],"sources":["../src/core/sync.ts"],"sourcesContent":["import { Effect } from 'effect';\n\nimport { resolveConfig, resolveConfigSources } from './resolve.ts';\n\nimport type { LayerSource, ResolveOptions, ResolveSourcesOptions, ResolvedConfig } from './resolve.ts';\n\n/**\n * {@link resolveConfig} for synchronous callers such as Node `registerHooks` load hooks.\n */\nexport const resolveConfigSync = (path: string, options?: ResolveOptions): ResolvedConfig =>\n\tEffect.runSync(resolveConfig(path, options));\n\n/**\n * {@link resolveConfigSources} for synchronous callers such as the module a bundler generates.\n */\nexport const resolveConfigSourcesSync = (\n\tfile: string,\n\tsources: readonly LayerSource[],\n\toptions: ResolveSourcesOptions,\n): ResolvedConfig => Effect.runSync(resolveConfigSources(file, sources, options));\n"],"mappings":";;;;;;AASA,MAAa,qBAAqB,MAAc,YAC/C,OAAO,QAAQ,cAAc,MAAM,OAAO,CAAC;;;;AAK5C,MAAa,4BACZ,MACA,SACA,YACoB,OAAO,QAAQ,qBAAqB,MAAM,SAAS,OAAO,CAAC"}
@@ -0,0 +1,2 @@
1
+ import "./shared-B6Y3_kdn.mjs";
2
+ import "unplugin";
@@ -1,4 +1,4 @@
1
- import { a as tyfigoImportPattern, i as loadConfigImport, n as findNodeOnlyImports, r as isServerPlatform, t as configFilePattern } from "./shared-BnK77Zcp.mjs";
1
+ import { a as tyfigoImportPattern, i as loadConfigImport, n as findNodeOnlyImports, r as isServerPlatform, t as configFilePattern } from "./shared-Cndg8CKC.mjs";
2
2
  import { createUnplugin } from "unplugin";
3
3
  // src/plugins/unplugin.ts
4
4
  const webpackMode = (compiler) => compiler.options.mode === "none" ? void 0 : compiler.options.mode;
@@ -13,7 +13,7 @@ const unpluginFactory = (options = {}) => {
13
13
  return {
14
14
  target: isServerPlatform(compiler.platform) ? "server" : "browser",
15
15
  bundle: true,
16
- environment: webpackMode(compiler)
16
+ mode: webpackMode(compiler)
17
17
  };
18
18
  }
19
19
  if (native?.framework === "esbuild") return {
@@ -25,7 +25,7 @@ const unpluginFactory = (options = {}) => {
25
25
  return {
26
26
  target: (consumer === void 0 ? loadOptions?.ssr : consumer === "server") ? "server" : "browser",
27
27
  bundle: viteCommand === "build",
28
- environment: viteMode
28
+ mode: viteMode
29
29
  };
30
30
  }
31
31
  return {
@@ -40,10 +40,11 @@ const unpluginFactory = (options = {}) => {
40
40
  filter: { id: configFilePattern },
41
41
  handler(id, loadOptions) {
42
42
  const detected = detect(this, loadOptions);
43
+ const target = options.target ?? detected.target;
43
44
  const result = loadConfigImport(id, {
44
- ...detected,
45
- target: options.target ?? detected.target,
46
- environment: options.environment ?? detected.environment,
45
+ target,
46
+ bundle: detected.bundle,
47
+ environment: options.environment ?? (target === "server" && detected.bundle ? void 0 : detected.mode),
47
48
  runtime: options.runtime
48
49
  });
49
50
  for (const file of result.watchFiles) this.addWatchFile(file);
@@ -80,4 +81,4 @@ const unpluginFactory = (options = {}) => {
80
81
  const tyfigo = createUnplugin(unpluginFactory);
81
82
  export { tyfigo as t };
82
83
 
83
- //# sourceMappingURL=unplugin-BQGm_bhA.mjs.map
84
+ //# sourceMappingURL=unplugin-DaIHdNM0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unplugin-DaIHdNM0.mjs","names":[],"sources":["../src/plugins/unplugin.ts"],"sourcesContent":["import { createUnplugin } from 'unplugin';\n\nimport {\n\tconfigFilePattern,\n\tfindNodeOnlyImports,\n\tisServerPlatform,\n\tloadConfigImport,\n\ttyfigoImportPattern,\n} from './shared.ts';\n\nimport type { LoadOptions } from '../runtime/load.ts';\nimport type { TyfigoPluginOptions, WebpackLikeCompiler } from './shared.ts';\nimport type { UnpluginBuildContext, UnpluginFactory } from 'unplugin';\n\nexport type { TyfigoPluginOptions } from './shared.ts';\n\nconst webpackMode = (compiler: WebpackLikeCompiler) =>\n\tcompiler.options.mode === 'none' ? undefined : compiler.options.mode;\n\ninterface ViteContext {\n\treadonly environment?: { readonly config: { readonly consumer: string } };\n}\n\nexport const unpluginFactory: UnpluginFactory<TyfigoPluginOptions | undefined, false> = (options = {}) => {\n\tlet viteCommand: string | undefined;\n\tlet viteMode: string | undefined;\n\tlet rolldownPlatform: string | undefined;\n\n\tconst detect = (\n\t\tcontext: UnpluginBuildContext,\n\t\tloadOptions: { readonly ssr?: boolean } | undefined,\n\t): Pick<LoadOptions, 'target' | 'bundle'> & { readonly mode?: string | undefined } => {\n\t\tconst native = context.getNativeBuildContext?.();\n\t\tif (native?.framework === 'webpack' || native?.framework === 'rspack') {\n\t\t\tconst compiler = native.compiler as WebpackLikeCompiler;\n\t\t\treturn {\n\t\t\t\ttarget: isServerPlatform(compiler.platform) ? 'server' : 'browser',\n\t\t\t\tbundle: true,\n\t\t\t\tmode: webpackMode(compiler),\n\t\t\t};\n\t\t}\n\t\tif (native?.framework === 'esbuild') {\n\t\t\treturn { target: native.build.initialOptions.platform === 'node' ? 'server' : 'browser', bundle: true };\n\t\t}\n\t\tif (viteCommand) {\n\t\t\tconst consumer = (context as ViteContext).environment?.config.consumer;\n\t\t\treturn {\n\t\t\t\ttarget: (consumer === undefined ? loadOptions?.ssr : consumer === 'server') ? 'server' : 'browser',\n\t\t\t\tbundle: viteCommand === 'build',\n\t\t\t\tmode: viteMode,\n\t\t\t};\n\t\t}\n\t\treturn { target: rolldownPlatform === 'node' ? 'server' : 'browser', bundle: true };\n\t};\n\n\treturn {\n\t\tname: 'tyfigo',\n\t\tenforce: 'pre',\n\t\tload: {\n\t\t\tfilter: { id: configFilePattern },\n\t\t\thandler(id, loadOptions?: { readonly ssr?: boolean }) {\n\t\t\t\tconst detected = detect(this, loadOptions);\n\t\t\t\tconst target = options.target ?? detected.target;\n\t\t\t\tconst result = loadConfigImport(id, {\n\t\t\t\t\ttarget,\n\t\t\t\t\tbundle: detected.bundle,\n\t\t\t\t\tenvironment:\n\t\t\t\t\t\toptions.environment ?? (target === 'server' && detected.bundle ? undefined : detected.mode),\n\t\t\t\t\truntime: options.runtime,\n\t\t\t\t});\n\t\t\t\tfor (const file of result.watchFiles) this.addWatchFile(file);\n\t\t\t\treturn { code: result.code, moduleType: 'js' };\n\t\t\t},\n\t\t},\n\t\ttransform: {\n\t\t\tfilter: {\n\t\t\t\tid: { include: /\\.(?:[cm]?[jt]sx?|vue|svelte|astro)(?:\\?|$)/u, exclude: /[\\\\/]node_modules[\\\\/]/u },\n\t\t\t\tcode: tyfigoImportPattern,\n\t\t\t},\n\t\t\thandler(code, id, transformOptions?: { readonly ssr?: boolean }) {\n\t\t\t\tif ((options.target ?? detect(this, transformOptions).target) !== 'browser') return;\n\t\t\t\tconst messages = findNodeOnlyImports(code, id);\n\t\t\t\tif (messages.length > 0) throw new Error(messages.join('\\n'));\n\t\t\t},\n\t\t},\n\t\tvite: {\n\t\t\tconfigResolved(config) {\n\t\t\t\tviteCommand = config.command;\n\t\t\t\tviteMode = config.mode;\n\t\t\t},\n\t\t},\n\t\trolldown: {\n\t\t\toptions(input) {\n\t\t\t\trolldownPlatform = input.platform;\n\t\t\t},\n\t\t},\n\t\tesbuild: { loader: 'js' },\n\t};\n};\n\nexport const tyfigo = createUnplugin(unpluginFactory);\n"],"mappings":";;;AAgBA,MAAM,eAAe,aACpB,SAAS,QAAQ,SAAS,SAAS,KAAA,IAAY,SAAS,QAAQ;AAMjE,MAAa,mBAA4E,UAAU,CAAC,MAAM;CACzG,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,UACL,SACA,gBACqF;EACrF,MAAM,SAAS,QAAQ,wBAAwB;EAC/C,IAAI,QAAQ,cAAc,aAAa,QAAQ,cAAc,UAAU;GACtE,MAAM,WAAW,OAAO;GACxB,OAAO;IACN,QAAQ,iBAAiB,SAAS,QAAQ,IAAI,WAAW;IACzD,QAAQ;IACR,MAAM,YAAY,QAAQ;GAC3B;EACD;EACA,IAAI,QAAQ,cAAc,WACzB,OAAO;GAAE,QAAQ,OAAO,MAAM,eAAe,aAAa,SAAS,WAAW;GAAW,QAAQ;EAAK;EAEvG,IAAI,aAAa;GAChB,MAAM,WAAY,QAAwB,aAAa,OAAO;GAC9D,OAAO;IACN,SAAS,aAAa,KAAA,IAAY,aAAa,MAAM,aAAa,YAAY,WAAW;IACzF,QAAQ,gBAAgB;IACxB,MAAM;GACP;EACD;EACA,OAAO;GAAE,QAAQ,qBAAqB,SAAS,WAAW;GAAW,QAAQ;EAAK;CACnF;CAEA,OAAO;EACN,MAAM;EACN,SAAS;EACT,MAAM;GACL,QAAQ,EAAE,IAAI,kBAAkB;GAChC,QAAQ,IAAI,aAA0C;IACrD,MAAM,WAAW,OAAO,MAAM,WAAW;IACzC,MAAM,SAAS,QAAQ,UAAU,SAAS;IAC1C,MAAM,SAAS,iBAAiB,IAAI;KACnC;KACA,QAAQ,SAAS;KACjB,aACC,QAAQ,gBAAgB,WAAW,YAAY,SAAS,SAAS,KAAA,IAAY,SAAS;KACvF,SAAS,QAAQ;IAClB,CAAC;IACD,KAAK,MAAM,QAAQ,OAAO,YAAY,KAAK,aAAa,IAAI;IAC5D,OAAO;KAAE,MAAM,OAAO;KAAM,YAAY;IAAK;GAC9C;EACD;EACA,WAAW;GACV,QAAQ;IACP,IAAI;KAAE,SAAS;KAAgD,SAAS;IAA0B;IAClG,MAAM;GACP;GACA,QAAQ,MAAM,IAAI,kBAA+C;IAChE,KAAK,QAAQ,UAAU,OAAO,MAAM,gBAAgB,CAAC,CAAC,YAAY,WAAW;IAC7E,MAAM,WAAW,oBAAoB,MAAM,EAAE;IAC7C,IAAI,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,KAAK,IAAI,CAAC;GAC7D;EACD;EACA,MAAM,EACL,eAAe,QAAQ;GACtB,cAAc,OAAO;GACrB,WAAW,OAAO;EACnB,EACD;EACA,UAAU,EACT,QAAQ,OAAO;GACd,mBAAmB,MAAM;EAC1B,EACD;EACA,SAAS,EAAE,QAAQ,KAAK;CACzB;AACD;AAEA,MAAa,SAAS,eAAe,eAAe"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tyfigo",
3
- "version": "0.1.0",
3
+ "version": "0.1.1-next.ce8c251.0",
4
4
  "description": "Typed, validated application config for TypeScript: import layered YAML, TOML, JSONC, JSON5, INI, .properties and XML config files, typed by a TypeScript 7.1 content mapper",
5
5
  "keywords": [
6
6
  "config",
@@ -1 +0,0 @@
1
- {"version":3,"file":"env-R3_XPW_u.mjs","names":[],"sources":["../src/core/files.ts","../src/core/env.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { Effect } from 'effect';\n\nexport const isFile = (path: string): Effect.Effect<boolean> =>\n\tEffect.sync(() => statSync(path, { throwIfNoEntry: false })?.isFile() ?? false);\n\n/**\n * The nearest directory at or above `directory` that has a `package.json`.\n */\nexport const findProjectRoot = Effect.fn('findProjectRoot')(function* (directory: string) {\n\tfor (let current = directory; ; current = dirname(current)) {\n\t\tif (yield* isFile(join(current, 'package.json'))) return current;\n\t\tif (dirname(current) === current) return undefined;\n\t}\n});\n\n/**\n * The first existing `name` in `directories`.\n */\nexport const findFile = Effect.fn('findFile')(function* (directories: readonly string[], name: string) {\n\tfor (const directory of directories) {\n\t\tconst path = join(directory, name);\n\t\tif (yield* isFile(path)) return path;\n\t}\n\treturn undefined;\n});\n\n/**\n * The base file's directory followed by the project root when it is a different directory.\n */\nexport const searchDirectories = Effect.fn('searchDirectories')(function* (baseFile: string) {\n\tconst directory = dirname(baseFile);\n\tconst root = yield* findProjectRoot(directory);\n\treturn root === undefined || root === directory ? [directory] : [directory, root];\n});\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport process from 'node:process';\nimport { parseEnv } from 'node:util';\n\nimport { Effect, Result } from 'effect';\n\nimport { findFile, searchDirectories } from './files.ts';\nimport { fileProblem } from './problems.ts';\n\nimport type { Problem } from './problems.ts';\n\nexport type EnvVariables = Readonly<Record<string, string | undefined>>;\n\nexport interface EnvResult {\n\t/**\n\t * The `.env` values with the real environment on top.\n\t */\n\treadonly variables: EnvVariables;\n\t/**\n\t * The `.env` files that were read, in the order they apply.\n\t */\n\treadonly files: readonly string[];\n\treadonly problems: readonly Problem[];\n}\n\n/**\n * A copy of the real environment. This is the only place tyfigo reads `process.env`.\n */\nexport const processEnv = (): EnvVariables => ({ ...process.env });\n\nexport const envFileNames = (environment?: string): readonly string[] =>\n\tenvironment ? ['.env', '.env.local', `.env.${environment}`, `.env.${environment}.local`] : ['.env', '.env.local'];\n\n/**\n * Reads `.env`, `.env.local`, `.env.<environment>` and `.env.<environment>.local` (each later one wins) and puts `env` on top.\n * Each file is searched next to `baseFile` first, then in the nearest directory with a `package.json`. Never writes `process.env`.\n */\nexport const readEnv = Effect.fn('readEnv')(function* (\n\tbaseFile: string,\n\toptions: { readonly environment?: string | undefined; readonly env?: EnvVariables | undefined } = {},\n) {\n\tconst directories = yield* searchDirectories(resolve(baseFile));\n\tconst variables: Record<string, string | undefined> = {};\n\tconst files: string[] = [];\n\tconst problems: Problem[] = [];\n\tfor (const name of envFileNames(options.environment)) {\n\t\tconst file = yield* findFile(directories, name);\n\t\tif (!file) continue;\n\t\tconst parsed = yield* Effect.result(\n\t\t\tEffect.try({\n\t\t\t\ttry: () => parseEnv(readFileSync(file, 'utf8')),\n\t\t\t\tcatch: (error) => fileProblem(file, 'read-error', `Cannot read ${file}: ${(error as Error).message}`),\n\t\t\t}),\n\t\t);\n\t\tif (Result.isFailure(parsed)) {\n\t\t\tproblems.push(parsed.failure);\n\t\t\tcontinue;\n\t\t}\n\n\t\tfiles.push(file);\n\t\tObject.assign(variables, parsed.success);\n\t}\n\n\tfor (const [key, value] of Object.entries(options.env ?? processEnv())) {\n\t\tif (value !== undefined) variables[key] = value;\n\t}\n\treturn { variables, files, problems } satisfies EnvResult;\n});\n"],"mappings":";;;;;;;AAKA,MAAa,UAAU,SACtB,OAAO,WAAW,SAAS,MAAM,EAAE,gBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK;;;;AAK/E,MAAa,kBAAkB,OAAO,GAAG,iBAAiB,CAAC,CAAC,WAAW,WAAmB;CACzF,KAAK,IAAI,UAAU,YAAa,UAAU,QAAQ,OAAO,GAAG;EAC3D,IAAI,OAAO,OAAO,KAAK,SAAS,cAAc,CAAC,GAAG,OAAO;EACzD,IAAI,QAAQ,OAAO,MAAM,SAAS,OAAO,KAAA;CAC1C;AACD,CAAC;;;;AAKD,MAAa,WAAW,OAAO,GAAG,UAAU,CAAC,CAAC,WAAW,aAAgC,MAAc;CACtG,KAAK,MAAM,aAAa,aAAa;EACpC,MAAM,OAAO,KAAK,WAAW,IAAI;EACjC,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO;CACjC;AAED,CAAC;;;;AAKD,MAAa,oBAAoB,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,UAAkB;CAC5F,MAAM,YAAY,QAAQ,QAAQ;CAClC,MAAM,OAAO,OAAO,gBAAgB,SAAS;CAC7C,OAAO,SAAS,KAAA,KAAa,SAAS,YAAY,CAAC,SAAS,IAAI,CAAC,WAAW,IAAI;AACjF,CAAC;;;;;ACPD,MAAa,oBAAkC,EAAE,GAAG,QAAQ,IAAI;AAEhE,MAAa,gBAAgB,gBAC5B,cAAc;CAAC;CAAQ;CAAc,QAAQ;CAAe,QAAQ,YAAY;AAAO,IAAI,CAAC,QAAQ,YAAY;;;;;AAMjH,MAAa,UAAU,OAAO,GAAG,SAAS,CAAC,CAAC,WAC3C,UACA,UAAkG,CAAC,GAClG;CACD,MAAM,cAAc,OAAO,kBAAkB,QAAQ,QAAQ,CAAC;CAC9D,MAAM,YAAgD,CAAC;CACvD,MAAM,QAAkB,CAAC;CACzB,MAAM,WAAsB,CAAC;CAC7B,KAAK,MAAM,QAAQ,aAAa,QAAQ,WAAW,GAAG;EACrD,MAAM,OAAO,OAAO,SAAS,aAAa,IAAI;EAC9C,IAAI,CAAC,MAAM;EACX,MAAM,SAAS,OAAO,OAAO,OAC5B,OAAO,IAAI;GACV,WAAW,SAAS,aAAa,MAAM,MAAM,CAAC;GAC9C,QAAQ,UAAU,YAAY,MAAM,cAAc,eAAe,KAAK,IAAK,MAAgB,SAAS;EACrG,CAAC,CACF;EACA,IAAI,OAAO,UAAU,MAAM,GAAG;GAC7B,SAAS,KAAK,OAAO,OAAO;GAC5B;EACD;EAEA,MAAM,KAAK,IAAI;EACf,OAAO,OAAO,WAAW,OAAO,OAAO;CACxC;CAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,OAAO,WAAW,CAAC,GACpE,IAAI,UAAU,KAAA,GAAW,UAAU,OAAO;CAE3C,OAAO;EAAE;EAAW;EAAO;CAAS;AACrC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"load-DxIjRpX6.mjs","names":[],"sources":["../src/runtime/load.ts"],"sourcesContent":["import { basename, dirname, join, relative, resolve, sep } from 'node:path';\n\nimport { Effect } from 'effect';\n\nimport { findProjectRoot, isFile, searchDirectories } from '../core/files.ts';\nimport {\n\tconfigSuffixes,\n\tenvFileNames,\n\tfileProblem,\n\tformatPath,\n\tformatProblems,\n\thasPlaceholder,\n\tisPlainObject,\n\tparseConfigFileName,\n\tpathKey,\n\tproblemAt,\n\tprocessEnv,\n\tresolveConfig,\n\tSourceIndex,\n} from '../core/index.ts';\n\nimport type { Path, PositionMap, Problem } from '../core/index.ts';\nimport type { BundledConfig } from './resolve.ts';\n\nexport type LoadTarget = 'server' | 'browser';\n\nexport interface LoadOptions {\n\t/**\n\t * `server` resolves the config when the module runs. `browser` inlines the base and environment files at build time and\n\t * reports every placeholder as a problem.\n\t */\n\treadonly target: LoadTarget;\n\t/**\n\t * The environment name, such as the bundler's mode. Defaults to `NODE_ENV`, read when the server module runs and when\n\t * `load` runs for the browser.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The specifier the server module imports the runtime from. Defaults to `tyfigo/runtime`.\n\t */\n\treadonly runtime?: string | undefined;\n\t/**\n\t * For `server`: inline the text of the layer files that exist at build time, and read `.env` files and environment variables\n\t * from `process.cwd()` when the module runs, so a bundle does not depend on the paths of the machine that built it.\n\t */\n\treadonly bundle?: boolean | undefined;\n}\n\nexport interface LoadResult {\n\t/**\n\t * The JavaScript module, with the config as its default export.\n\t */\n\treadonly code: string;\n\t/**\n\t * Every file whose creation, change or removal changes the module, whether or not it exists now.\n\t */\n\treadonly watchFiles: readonly string[];\n\treadonly problems: readonly Problem[];\n}\n\nconst browserLayers = ['base', 'environment'] as const;\n\nconst watchFilesOf = Effect.fn('watchFilesOf')(function* (\n\tfile: string,\n\tenvironment: string | undefined,\n\ttarget: LoadTarget,\n) {\n\tconst name = parseConfigFileName(basename(file));\n\tif (!name) return [file];\n\n\tconst files = [file];\n\tif (environment) files.push(join(dirname(file), `${name.stem}.${environment}${name.suffix}`));\n\tif (target === 'browser') return files;\n\n\tconst directories = yield* searchDirectories(file);\n\tconst locals = environment\n\t\t? [`${name.stem}.local${name.suffix}`, `${name.stem}.${environment}.local${name.suffix}`]\n\t\t: [`${name.stem}.local${name.suffix}`];\n\tfor (const fileName of [...locals, ...envFileNames(environment)]) {\n\t\tfor (const directory of directories) files.push(join(directory, fileName));\n\t}\n\treturn files;\n});\n\n/**\n * A JavaScript expression that evaluates to a deep-frozen copy of a config value.\n */\nexport const valueLiteral = (value: unknown, indent = ''): string => {\n\tif (value === undefined) return 'undefined';\n\tif (typeof value === 'number') return Object.is(value, -0) ? '-0' : String(value);\n\tif (typeof value === 'bigint') return `${value}n`;\n\tif (value instanceof Date) return `new Date(${valueLiteral(value.getTime(), indent)})`;\n\tconst inner = `${indent}\\t`;\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return 'Object.freeze([])';\n\t\tconst items = value.map((item) => `${inner}${valueLiteral(item, inner)},\\n`);\n\t\treturn `Object.freeze([\\n${items.join('')}${indent}])`;\n\t}\n\tif (isPlainObject(value)) {\n\t\tconst entries = Object.entries(value);\n\t\tif (entries.length === 0) return 'Object.freeze({})';\n\t\tconst properties = entries.map(([key, item]) => {\n\t\t\tconst name = key === '__proto__' ? `[${JSON.stringify(key)}]` : JSON.stringify(key);\n\t\t\treturn `${inner}${name}: ${valueLiteral(item, inner)},\\n`;\n\t\t});\n\t\treturn `Object.freeze({\\n${properties.join('')}${indent}})`;\n\t}\n\treturn JSON.stringify(value);\n};\n\nconst hasUnescapedPlaceholder = (text: string) => hasPlaceholder(text.replaceAll('$${', ''));\n\nconst placeholderProblems = (file: string, text: string, value: unknown, positions: PositionMap) => {\n\tconst source = new SourceIndex(text);\n\tconst problems: Problem[] = [];\n\tconst visit = (item: unknown, path: Path) => {\n\t\tif (typeof item === 'string') {\n\t\t\tif (!hasUnescapedPlaceholder(item)) return;\n\t\t\tconst span = positions.get(pathKey(path));\n\t\t\tproblems.push(\n\t\t\t\tproblemAt(\n\t\t\t\t\tsource,\n\t\t\t\t\tfile,\n\t\t\t\t\tspan?.valueStart ?? 0,\n\t\t\t\t\tspan?.valueLength ?? 0,\n\t\t\t\t\t'browser-placeholder',\n\t\t\t\t\t`'${formatPath(path) || '(root)'}' uses an environment placeholder, which browser builds cannot read`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (Array.isArray(item)) for (const [index, child] of item.entries()) visit(child, [...path, index]);\n\t\telse if (isPlainObject(item)) for (const [key, child] of Object.entries(item)) visit(child, [...path, key]);\n\t};\n\tvisit(value, []);\n\treturn problems;\n};\n\nconst failingCode = (file: string, problems: readonly Problem[]) =>\n\t`throw new Error(${JSON.stringify(`Invalid config ${file}\\n${formatProblems(problems)}`)});\\n\\nexport default undefined;\\n`;\n\nconst serverModule = Effect.fn('serverModule')(function* (file: string, options: LoadOptions) {\n\tconst problems: Problem[] = [];\n\tif (!parseConfigFileName(basename(file))) {\n\t\tproblems.push(\n\t\t\tfileProblem(\n\t\t\t\tfile,\n\t\t\t\t'unsupported-file',\n\t\t\t\t`${basename(file)} is not a config file; expected a name ending in ${configSuffixes.join(', ')}`,\n\t\t\t),\n\t\t);\n\t} else if (!(yield* isFile(file))) problems.push(fileProblem(file, 'file-not-found', `Cannot find ${file}`));\n\n\tconst settings =\n\t\toptions.environment === undefined ? '' : `, { environment: ${JSON.stringify(options.environment)} }`;\n\tconst code = `import { resolveConfigModule } from ${JSON.stringify(options.runtime ?? 'tyfigo/runtime')};\\n\\nexport default resolveConfigModule(${JSON.stringify(file)}${settings});\\n`;\n\tconst environment = options.environment ?? (processEnv().NODE_ENV || undefined);\n\treturn { code, watchFiles: yield* watchFilesOf(file, environment, 'server'), problems } satisfies LoadResult;\n});\n\nconst browserModule = Effect.fn('browserModule')(function* (file: string, options: LoadOptions) {\n\tconst environment = options.environment ?? (processEnv().NODE_ENV || undefined);\n\tconst result = yield* resolveConfig(file, { environment, env: {}, layers: browserLayers });\n\tconst files = new Set([result.file, ...result.layers.map((layer) => layer.file)]);\n\tconst problems = result.problems.filter(\n\t\t(problem) =>\n\t\t\tfiles.has(problem.file) && problem.code !== 'missing-variable' && problem.code !== 'invalid-placeholder',\n\t);\n\tfor (const layer of result.layers) {\n\t\tconst parsed = result.format?.parse(layer.text, layer.file);\n\t\tif (parsed?.value !== undefined) {\n\t\t\tproblems.push(...placeholderProblems(layer.file, layer.text, parsed.value, layer.positions));\n\t\t}\n\t}\n\n\tconst code =\n\t\tproblems.length > 0\n\t\t\t? failingCode(result.file, problems)\n\t\t\t: `export default ${valueLiteral(result.value, '')};\\n`;\n\treturn {\n\t\tcode,\n\t\twatchFiles: yield* watchFilesOf(result.file, environment, 'browser'),\n\t\tproblems,\n\t} satisfies LoadResult;\n});\n\nconst bundledServerModule = Effect.fn('bundledServerModule')(function* (file: string, options: LoadOptions) {\n\tconst environment = options.environment ?? (processEnv().NODE_ENV || undefined);\n\tconst result = yield* resolveConfig(file, { environment });\n\tconst problems = result.problems.filter(\n\t\t(problem) => problem.code !== 'missing-variable' && problem.code !== 'placeholder-type',\n\t);\n\tconst root = (yield* findProjectRoot(dirname(result.file))) ?? dirname(result.file);\n\tconst name = (path: string) => relative(root, path).split(sep).join('/');\n\tconst bundle: BundledConfig = {\n\t\tfile: name(result.file),\n\t\tenvironment,\n\t\tlayers: result.layers.map((layer) => ({ file: name(layer.file), kind: layer.kind, text: layer.text })),\n\t};\n\n\tconst code =\n\t\tproblems.length > 0\n\t\t\t? failingCode(result.file, problems)\n\t\t\t: `import { resolveBundledConfigModule } from ${JSON.stringify(options.runtime ?? 'tyfigo/runtime')};\\n\\nexport default resolveBundledConfigModule(${JSON.stringify(bundle)});\\n`;\n\treturn {\n\t\tcode,\n\t\twatchFiles: yield* watchFilesOf(result.file, environment, 'server'),\n\t\tproblems,\n\t} satisfies LoadResult;\n});\n\n/**\n * Generates the JavaScript module for a config file import. Loaders fail the import or build when `problems` is not empty.\n */\nexport const loadModule = Effect.fn('loadModule')(function* (path: string, options: LoadOptions) {\n\tconst file = resolve(path);\n\tif (options.target === 'browser') return yield* browserModule(file, options);\n\treturn options.bundle ? yield* bundledServerModule(file, options) : yield* serverModule(file, options);\n});\n\n/**\n * {@link loadModule} for synchronous callers such as Node `registerHooks` load hooks.\n */\nexport const load = (path: string, options: LoadOptions): LoadResult => Effect.runSync(loadModule(path, options));\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve-D3geHCGs.mjs","names":[],"sources":["../src/core/layers.ts","../src/core/merge.ts","../src/core/resolve.ts"],"sourcesContent":["import { basename, dirname, join, resolve } from 'node:path';\n\nimport { Effect } from 'effect';\n\nimport { findFile, isFile, searchDirectories } from './files.ts';\nimport { parseConfigFileName } from './formats/index.ts';\n\nexport type LayerKind = 'base' | 'environment' | 'local' | 'environment-local';\n\nexport interface LayerFile {\n\treadonly file: string;\n\treadonly kind: LayerKind;\n}\n\n/**\n * The layer files of a base config file, in the order they apply: `app.config.yaml`, `app.<environment>.config.yaml`,\n * `app.local.config.yaml` and `app.<environment>.local.config.yaml`. Only files that exist are listed. Environment files sit next\n * to the base file, and local files are searched next to it first, then in the nearest directory with a `package.json`.\n */\nexport const discoverLayers = Effect.fn('discoverLayers')(function* (baseFile: string, environment?: string) {\n\tconst file = resolve(baseFile);\n\tconst name = parseConfigFileName(basename(file));\n\tif (!name) return [];\n\n\tconst directories = yield* searchDirectories(file);\n\tconst layers: LayerFile[] = [];\n\tif (yield* isFile(file)) layers.push({ file, kind: 'base' });\n\tif (environment) {\n\t\tconst environmentFile = join(dirname(file), `${name.stem}.${environment}${name.suffix}`);\n\t\tif (yield* isFile(environmentFile)) layers.push({ file: environmentFile, kind: 'environment' });\n\t}\n\n\tconst local = yield* findFile(directories, `${name.stem}.local${name.suffix}`);\n\tif (local) layers.push({ file: local, kind: 'local' });\n\tif (environment) {\n\t\tconst environmentLocal = yield* findFile(directories, `${name.stem}.${environment}.local${name.suffix}`);\n\t\tif (environmentLocal) layers.push({ file: environmentLocal, kind: 'environment-local' });\n\t}\n\n\treturn layers;\n});\n","import { basename } from 'node:path';\n\nimport { isPlainObject, kindOf } from './placeholders.ts';\nimport { formatPath, pathKey } from './positions.ts';\nimport { problemAt } from './problems.ts';\n\nimport type { Path, PositionMap, SourceIndex, Span } from './positions.ts';\nimport type { Problem } from './problems.ts';\n\n/**\n * A {@link Span} together with the file it is in.\n */\nexport interface LocatedSpan extends Span {\n\treadonly file: string;\n}\n\nexport interface MergeLayer {\n\treadonly file: string;\n\treadonly value: unknown;\n\treadonly positions: PositionMap;\n\treadonly source: SourceIndex;\n}\n\nexport interface MergeResult {\n\treadonly value: unknown;\n\treadonly positions: ReadonlyMap<string, LocatedSpan>;\n\treadonly problems: readonly Problem[];\n}\n\nconst isWithin = (id: string, prefix: string) =>\n\tid === prefix || id.startsWith(prefix === '[]' ? '[' : `${prefix.slice(0, -1)},`);\n\nexport const locate = (file: string, positions: PositionMap): Map<string, LocatedSpan> =>\n\tnew Map([...positions].map(([id, span]) => [id, { ...span, file }]));\n\n/**\n * Applies `layer` over `base`. Objects merge, arrays and primitives replace. A key that `base` lacks, or a value of a different\n * type (`null`, boolean, number, string, array or object), is a problem and that part of the layer is skipped.\n */\nexport const mergeLayer = (\n\tbase: { readonly value: unknown; readonly positions: ReadonlyMap<string, LocatedSpan> },\n\tlayer: MergeLayer,\n): MergeResult => {\n\tconst positions = new Map(base.positions);\n\tconst problems: Problem[] = [];\n\n\tconst report = (path: Path, onKey: boolean, code: 'unknown-key' | 'type-mismatch', message: string) => {\n\t\tconst span = layer.positions.get(pathKey(path));\n\t\tconst start = span ? (onKey ? span.keyStart : span.valueStart) : 0;\n\t\tconst length = span ? (onKey ? span.keyLength : span.valueLength) : 0;\n\t\tproblems.push(problemAt(layer.source, layer.file, start, length, code, message));\n\t};\n\n\tconst origin = (path: Path) => {\n\t\tconst file = positions.get(pathKey(path))?.file;\n\t\treturn file ? basename(file) : 'the base file';\n\t};\n\n\tconst replace = (path: Path) => {\n\t\tconst prefix = pathKey(path);\n\t\tfor (const id of positions.keys()) if (isWithin(id, prefix)) positions.delete(id);\n\t\tfor (const [id, span] of layer.positions) {\n\t\t\tif (isWithin(id, prefix)) positions.set(id, { ...span, file: layer.file });\n\t\t}\n\t};\n\n\tconst merge = (current: unknown, next: unknown, path: Path): unknown => {\n\t\tif (isPlainObject(current) && isPlainObject(next)) {\n\t\t\tconst result = { ...current };\n\t\t\tfor (const [key, value] of Object.entries(next)) {\n\t\t\t\tconst childPath = [...path, key];\n\t\t\t\tif (Object.hasOwn(current, key)) result[key] = merge(current[key], value, childPath);\n\t\t\t\telse {\n\t\t\t\t\treport(\n\t\t\t\t\t\tchildPath,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t'unknown-key',\n\t\t\t\t\t\t`'${formatPath(childPath)}' is not in ${origin(path)}; environment and local files can only override existing keys`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tconst expected = kindOf(current);\n\t\tconst actual = kindOf(next);\n\t\tif (expected !== actual) {\n\t\t\treport(\n\t\t\t\tpath,\n\t\t\t\tfalse,\n\t\t\t\t'type-mismatch',\n\t\t\t\t`Expected ${expected} at '${formatPath(path) || '(root)'}' as in ${origin(path)}, got ${actual}`,\n\t\t\t);\n\t\t\treturn current;\n\t\t}\n\n\t\treplace(path);\n\t\treturn next;\n\t};\n\n\treturn { value: merge(base.value, layer.value, []), positions, problems };\n};\n","import { readFileSync } from 'node:fs';\nimport { basename, resolve } from 'node:path';\n\nimport { Effect, Result } from 'effect';\n\nimport { processEnv, readEnv } from './env.ts';\nimport { isFile } from './files.ts';\nimport { configSuffixes, parseConfigFileName } from './formats/index.ts';\nimport { discoverLayers } from './layers.ts';\nimport { locate, mergeLayer } from './merge.ts';\nimport { resolvePlaceholders } from './placeholders.ts';\nimport { SourceIndex } from './positions.ts';\nimport { fileProblem } from './problems.ts';\n\nimport type { EnvVariables } from './env.ts';\nimport type { Format } from './formats/index.ts';\nimport type { LayerFile, LayerKind } from './layers.ts';\nimport type { LocatedSpan } from './merge.ts';\nimport type { Path, PositionMap } from './positions.ts';\nimport type { Problem } from './problems.ts';\n\nexport interface ResolveOptions {\n\t/**\n\t * The real environment variables, which win over every `.env` file. Defaults to a copy of the current ones.\n\t */\n\treadonly env?: EnvVariables | undefined;\n\t/**\n\t * The environment name that picks `app.<environment>.config.yaml` and `.env.<environment>`. Defaults to `env.NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The layer kinds to read. Defaults to all of them.\n\t */\n\treadonly layers?: readonly LayerKind[] | undefined;\n}\n\nexport interface ResolvedLayer {\n\treadonly file: string;\n\treadonly kind: LayerKind;\n\treadonly text: string;\n\t/**\n\t * The parsed value with placeholders resolved, or `undefined` when the file could not be parsed.\n\t */\n\treadonly value: unknown;\n\treadonly positions: PositionMap;\n}\n\nexport interface ResolvedConfig {\n\t/**\n\t * The base file, resolved to an absolute path.\n\t */\n\treadonly file: string;\n\treadonly format: Format | undefined;\n\treadonly environment: string | undefined;\n\t/**\n\t * The merged value, or `undefined` when the base file is missing or could not be parsed.\n\t */\n\treadonly value: unknown;\n\treadonly layers: readonly ResolvedLayer[];\n\treadonly envFiles: readonly string[];\n\t/**\n\t * Where each key path of `value` came from, keyed by `pathKey`.\n\t */\n\treadonly positions: ReadonlyMap<string, LocatedSpan>;\n\treadonly problems: readonly Problem[];\n}\n\nconst readText = (file: string) =>\n\tEffect.try({\n\t\ttry: () => readFileSync(file, 'utf8'),\n\t\tcatch: (error) => fileProblem(file, 'read-error', `Cannot read ${file}: ${(error as Error).message}`),\n\t});\n\nconst valueAt = (value: unknown, path: Path): unknown =>\n\tpath.reduce<unknown>(\n\t\t(current, segment) =>\n\t\t\ttypeof current === 'object' && current !== null && Object.hasOwn(current, segment)\n\t\t\t\t? (current as Record<string | number, unknown>)[segment]\n\t\t\t\t: undefined,\n\t\tvalue,\n\t);\n\nconst mergeLayers = Effect.fn('mergeLayers')(function* <Layer extends LayerFile>(\n\tformat: Format,\n\tfiles: readonly Layer[],\n\tread: (layer: Layer) => Effect.Effect<string, Problem>,\n\tvariables: EnvVariables,\n) {\n\tconst problems: Problem[] = [];\n\tconst layers: ResolvedLayer[] = [];\n\tlet merged: { value: unknown; positions: ReadonlyMap<string, LocatedSpan> } | undefined;\n\n\tfor (const layer of files) {\n\t\tconst content = yield* Effect.result(read(layer));\n\t\tif (Result.isFailure(content)) {\n\t\t\tproblems.push(content.failure);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst text = content.success;\n\t\tconst parsed = format.parse(text, layer.file);\n\t\tproblems.push(...parsed.problems);\n\t\tconst source = new SourceIndex(text);\n\t\tconst base = merged?.value;\n\t\tconst resolved =\n\t\t\tparsed.value === undefined\n\t\t\t\t? { value: undefined, problems: [] }\n\t\t\t\t: resolvePlaceholders({\n\t\t\t\t\t\tvalue: parsed.value,\n\t\t\t\t\t\tpositions: parsed.positions,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\tfile: layer.file,\n\t\t\t\t\t\tformat,\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t\tbaseValueAt: merged && ((path) => valueAt(base, path)),\n\t\t\t\t\t});\n\t\tproblems.push(...resolved.problems);\n\t\tlayers.push({ file: layer.file, kind: layer.kind, text, value: resolved.value, positions: parsed.positions });\n\t\tif (resolved.value === undefined) continue;\n\n\t\tif (!merged) {\n\t\t\tmerged =\n\t\t\t\tlayer.kind === 'base'\n\t\t\t\t\t? { value: resolved.value, positions: locate(layer.file, parsed.positions) }\n\t\t\t\t\t: undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tconst result = mergeLayer(merged, {\n\t\t\tfile: layer.file,\n\t\t\tvalue: resolved.value,\n\t\t\tpositions: parsed.positions,\n\t\t\tsource,\n\t\t});\n\t\tproblems.push(...result.problems);\n\t\tmerged = result;\n\t}\n\n\treturn { layers, value: merged?.value, positions: merged?.positions ?? new Map(), problems };\n});\n\nconst unsupportedFile = (file: string) =>\n\tfileProblem(\n\t\tfile,\n\t\t'unsupported-file',\n\t\t`${basename(file)} is not a config file; expected a name ending in ${configSuffixes.join(', ')}`,\n\t);\n\n/**\n * Reads a config file with its environment and local layers and `.env` files, resolves placeholders and merges the layers.\n * Never fails: everything that went wrong is in `problems`.\n */\nexport const resolveConfig = Effect.fn('resolveConfig')(function* (path: string, options: ResolveOptions = {}) {\n\tconst file = resolve(path);\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst name = parseConfigFileName(basename(file));\n\tconst empty = {\n\t\tfile,\n\t\tformat: name?.format,\n\t\tenvironment,\n\t\tvalue: undefined,\n\t\tlayers: [],\n\t\tenvFiles: [],\n\t\tpositions: new Map(),\n\t};\n\tif (!name) return { ...empty, problems: [unsupportedFile(file)] } satisfies ResolvedConfig;\n\tif (!(yield* isFile(file))) {\n\t\treturn {\n\t\t\t...empty,\n\t\t\tproblems: [fileProblem(file, 'file-not-found', `Cannot find ${file}`)],\n\t\t} satisfies ResolvedConfig;\n\t}\n\n\tconst envResult = yield* readEnv(file, { environment, env });\n\tconst files = (yield* discoverLayers(file, environment)).filter(\n\t\t(layer) => !options.layers || options.layers.includes(layer.kind),\n\t);\n\tconst merged = yield* mergeLayers(name.format, files, (layer) => readText(layer.file), envResult.variables);\n\treturn {\n\t\t...empty,\n\t\t...merged,\n\t\tenvFiles: envResult.files,\n\t\tproblems: [...envResult.problems, ...merged.problems],\n\t} satisfies ResolvedConfig;\n});\n\nexport interface LayerSource extends LayerFile {\n\treadonly text: string;\n}\n\nexport interface ResolveSourcesOptions {\n\treadonly env?: EnvVariables | undefined;\n\treadonly environment?: string | undefined;\n\t/**\n\t * A path in the directory to search `.env` files from first, before the nearest directory with a `package.json`.\n\t */\n\treadonly envFrom: string;\n}\n\n/**\n * {@link resolveConfig} for layer files whose text was read earlier, such as the layers a bundler inlined at build time. `file`\n * names the base file and picks the format; it is used as given and never read. Never fails: everything that went wrong is in\n * `problems`.\n */\nexport const resolveConfigSources = Effect.fn('resolveConfigSources')(function* (\n\tfile: string,\n\tsources: readonly LayerSource[],\n\toptions: ResolveSourcesOptions,\n) {\n\tconst env = options.env ?? processEnv();\n\tconst environment = options.environment ?? (env.NODE_ENV || undefined);\n\tconst name = parseConfigFileName(basename(file));\n\tconst empty = {\n\t\tfile,\n\t\tformat: name?.format,\n\t\tenvironment,\n\t\tvalue: undefined,\n\t\tlayers: [],\n\t\tenvFiles: [],\n\t\tpositions: new Map(),\n\t};\n\tif (!name) return { ...empty, problems: [unsupportedFile(file)] } satisfies ResolvedConfig;\n\n\tconst envResult = yield* readEnv(options.envFrom, { environment, env });\n\tconst merged = yield* mergeLayers(name.format, sources, (layer) => Effect.succeed(layer.text), envResult.variables);\n\treturn {\n\t\t...empty,\n\t\t...merged,\n\t\tenvFiles: envResult.files,\n\t\tproblems: [...envResult.problems, ...merged.problems],\n\t} satisfies ResolvedConfig;\n});\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-DeRUtPZ9.mjs","names":[],"sources":["../src/runtime/resolve.ts"],"sourcesContent":["import { basename, join } from 'node:path';\nimport process from 'node:process';\n\nimport { Data } from 'effect';\n\nimport { configSource } from './source.ts';\n\nimport { formatProblems, pathKey, resolveConfigSourcesSync, resolveConfigSync, SourceIndex } from '../core/index.ts';\n\nimport type { LayerSource, Problem, ResolvedConfig } from '../core/index.ts';\nimport type { ConfigSource } from './source.ts';\n\nexport class ConfigModuleError extends Data.TaggedError('ConfigModuleError')<{\n\treadonly message: string;\n\treadonly file: string;\n\treadonly problems: readonly Problem[];\n}> {}\n\nexport interface ConfigModuleOptions {\n\t/**\n\t * The environment name that picks `app.<environment>.config.yaml` and `.env.<environment>`. Defaults to `NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n}\n\nexport const deepFreeze = <T>(value: T): T => {\n\tif (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {\n\t\tObject.freeze(value);\n\t\tfor (const item of Object.values(value)) deepFreeze(item);\n\t}\n\treturn value;\n};\n\nconst sourceOf = (result: ResolvedConfig): ConfigSource => {\n\tconst texts = new Map(result.layers.map((layer) => [layer.file, layer.text]));\n\tconst indexes = new Map<string, SourceIndex>();\n\tconst indexOf = (file: string) => {\n\t\tconst text = texts.get(file);\n\t\tif (text === undefined) return undefined;\n\t\tconst index = indexes.get(file) ?? new SourceIndex(text);\n\t\tindexes.set(file, index);\n\t\treturn index;\n\t};\n\n\treturn {\n\t\tfile: result.file,\n\t\tenvironment: result.environment,\n\t\tlayers: result.layers.map((layer) => layer.file),\n\t\tenvFiles: result.envFiles,\n\t\tposition: (path) => {\n\t\t\tfor (let depth = path.length; depth >= 0; depth--) {\n\t\t\t\tconst span = result.positions.get(pathKey(path.slice(0, depth)));\n\t\t\t\tif (!span) continue;\n\t\t\t\tconst index = indexOf(span.file);\n\t\t\t\treturn index ? { file: span.file, ...index.lineColumn(span.valueStart) } : undefined;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n};\n\nconst toModule = (result: ResolvedConfig): unknown => {\n\tif (result.problems.length > 0) {\n\t\tthrow new ConfigModuleError({\n\t\t\tmessage: `Invalid config ${result.file}\\n${formatProblems(result.problems)}`,\n\t\t\tfile: result.file,\n\t\t\tproblems: result.problems,\n\t\t});\n\t}\n\n\tif (typeof result.value === 'object' && result.value !== null) {\n\t\tObject.defineProperty(result.value, configSource, { value: sourceOf(result) });\n\t}\n\treturn deepFreeze(result.value);\n};\n\n/**\n * Resolves a config file with its layers, `.env` files and placeholders, and returns the deep-frozen value. This is what a\n * generated server module calls when it is evaluated. Throws a {@link ConfigModuleError} listing every problem.\n */\nexport const resolveConfigModule = (file: string, options: ConfigModuleOptions = {}): unknown =>\n\ttoModule(resolveConfigSync(file, { environment: options.environment }));\n\n/**\n * The layer files a bundled server module carries, with paths relative to the project root of the machine that built it.\n */\nexport interface BundledConfig {\n\treadonly file: string;\n\treadonly environment?: string | undefined;\n\treadonly layers: readonly LayerSource[];\n}\n\n/**\n * {@link resolveConfigModule} for a bundled server module: merges the layers inlined at build time with the `.env` files found\n * from `process.cwd()` and the environment variables.\n */\nexport const resolveBundledConfigModule = (bundle: BundledConfig): unknown =>\n\ttoModule(\n\t\tresolveConfigSourcesSync(bundle.file, bundle.layers, {\n\t\t\tenvironment: bundle.environment,\n\t\t\tenvFrom: join(process.cwd(), basename(bundle.file)),\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;AAYA,IAAa,oBAAb,cAAuC,KAAK,YAAY,mBAAmB,CAAC,CAIzE,CAAC;AASJ,MAAa,cAAiB,UAAgB;CAC7C,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG;EAC3E,OAAO,OAAO,KAAK;EACnB,KAAK,MAAM,QAAQ,OAAO,OAAO,KAAK,GAAG,WAAW,IAAI;CACzD;CACA,OAAO;AACR;AAEA,MAAM,YAAY,WAAyC;CAC1D,MAAM,QAAQ,IAAI,IAAI,OAAO,OAAO,KAAK,UAAU,CAAC,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC;CAC5E,MAAM,0BAAU,IAAI,IAAyB;CAC7C,MAAM,WAAW,SAAiB;EACjC,MAAM,OAAO,MAAM,IAAI,IAAI;EAC3B,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;EAC/B,MAAM,QAAQ,QAAQ,IAAI,IAAI,KAAK,IAAI,YAAY,IAAI;EACvD,QAAQ,IAAI,MAAM,KAAK;EACvB,OAAO;CACR;CAEA,OAAO;EACN,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,QAAQ,OAAO,OAAO,KAAK,UAAU,MAAM,IAAI;EAC/C,UAAU,OAAO;EACjB,WAAW,SAAS;GACnB,KAAK,IAAI,QAAQ,KAAK,QAAQ,SAAS,GAAG,SAAS;IAClD,MAAM,OAAO,OAAO,UAAU,IAAI,QAAQ,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM;IACX,MAAM,QAAQ,QAAQ,KAAK,IAAI;IAC/B,OAAO,QAAQ;KAAE,MAAM,KAAK;KAAM,GAAG,MAAM,WAAW,KAAK,UAAU;IAAE,IAAI,KAAA;GAC5E;EAED;CACD;AACD;AAEA,MAAM,YAAY,WAAoC;CACrD,IAAI,OAAO,SAAS,SAAS,GAC5B,MAAM,IAAI,kBAAkB;EAC3B,SAAS,kBAAkB,OAAO,KAAK,IAAI,eAAe,OAAO,QAAQ;EACzE,MAAM,OAAO;EACb,UAAU,OAAO;CAClB,CAAC;CAGF,IAAI,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,MACxD,OAAO,eAAe,OAAO,OAAO,cAAc,EAAE,OAAO,SAAS,MAAM,EAAE,CAAC;CAE9E,OAAO,WAAW,OAAO,KAAK;AAC/B;;;;;AAMA,MAAa,uBAAuB,MAAc,UAA+B,CAAC,MACjF,SAAS,kBAAkB,MAAM,EAAE,aAAa,QAAQ,YAAY,CAAC,CAAC;;;;;AAevE,MAAa,8BAA8B,WAC1C,SACC,yBAAyB,OAAO,MAAM,OAAO,QAAQ;CACpD,aAAa,OAAO;CACpB,SAAS,KAAK,QAAQ,IAAI,GAAG,SAAS,OAAO,IAAI,CAAC;AACnD,CAAC,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared-BnK77Zcp.mjs","names":[],"sources":["../src/plugins/shared.ts"],"sourcesContent":["import { configSuffixes, formatProblems } from '../core/index.ts';\nimport { load } from '../runtime/load.ts';\n\nimport type { LoadOptions, LoadResult, LoadTarget } from '../runtime/load.ts';\n\nexport interface TyfigoPluginOptions {\n\t/**\n\t * Overrides the detected target. `browser` inlines the base and environment files and fails on placeholders and on imports of\n\t * `loadEnv` and the other exports that need Node.js. `server` inlines the base, environment and local files of the build's\n\t * environment and reads `.env` files and environment variables when the bundle runs.\n\t */\n\treadonly target?: LoadTarget | undefined;\n\t/**\n\t * The environment name. Defaults to the bundler's mode where it has one (Vite, webpack, Rspack, Rsbuild), otherwise `NODE_ENV`.\n\t */\n\treadonly environment?: string | undefined;\n\t/**\n\t * The specifier server modules import the runtime from. Defaults to `tyfigo/runtime`.\n\t */\n\treadonly runtime?: string | undefined;\n}\n\nexport const configFilePattern = new RegExp(\n\t`(?:${configSuffixes.map((suffix) => suffix.replaceAll('.', String.raw`\\.`)).join('|')})$`,\n\t'u',\n);\n\n/**\n * Generates the module for a config import and throws one error listing every problem, which fails the build.\n */\nexport const loadConfigImport = (file: string, options: LoadOptions): LoadResult => {\n\tconst result = load(file, options);\n\tif (result.problems.length > 0) throw new Error(`Invalid config ${file}\\n${formatProblems(result.problems)}`);\n\treturn result;\n};\n\nexport interface WebpackLikePlatform {\n\treadonly web?: boolean | null;\n\treadonly node?: boolean | null;\n}\n\nexport interface WebpackLikeCompiler {\n\treadonly platform: WebpackLikePlatform;\n\treadonly options: { readonly mode?: string | undefined };\n}\n\nexport const isServerPlatform = (platform: WebpackLikePlatform): boolean => platform.node === true && !platform.web;\n\nconst nodeOnlyExports: Readonly<Record<string, readonly string[]>> = {\n\ttyfigo: ['loadEnv', 'loadEnvAsync'],\n\t'tyfigo/effect': ['loadEnv', 'layerEnv', 'configProviderFromFile', 'layerConfigProviderFromFile'],\n};\n\nconst tyfigoSource = /\\bfrom\\s*[\"'](tyfigo(?:\\/effect)?)[\"']/gu;\n\nexport const tyfigoImportPattern = /[\"']tyfigo(?:\\/effect)?[\"']/u;\n\nconst usesNamespaceMember = (code: string, namespace: string, name: string) =>\n\tnew RegExp(String.raw`(?<![\\w$.])${namespace.replaceAll('$', String.raw`\\$`)}\\s*\\??\\.\\s*${name}\\b`, 'u').test(code);\n\nconst namedSpecifiers = (clause: string): string[] => {\n\tconst open = clause.indexOf('{');\n\tconst close = clause.indexOf('}', open);\n\tif (open === -1 || close === -1) return [];\n\treturn clause\n\t\t.slice(open + 1, close)\n\t\t.split(',')\n\t\t.map((specifier) => specifier.trim().split(/\\s/u)[0] ?? '');\n};\n\n/**\n * Finds imports of the tyfigo exports that need Node.js, such as `loadEnv`, and returns one message per import for a browser\n * build to fail with.\n */\nexport const findNodeOnlyImports = (code: string, id: string): string[] => {\n\tconst messages: string[] = [];\n\tfor (const match of code.matchAll(tyfigoSource)) {\n\t\tconst source = match[1] ?? '';\n\t\tconst start = Math.max(code.lastIndexOf('import', match.index), code.lastIndexOf('export', match.index));\n\t\tconst clause = code.slice(start + 'import'.length, match.index);\n\t\tif (start === -1 || /[;'\"`]/u.test(clause) || /^\\s*type[\\s{]/u.test(clause)) continue;\n\n\t\tconst specifiers = namedSpecifiers(clause);\n\t\tconst namespace = /\\*\\s*as\\s+([\\w$]+)/u.exec(clause)?.[1];\n\t\tconst used = (nodeOnlyExports[source] ?? []).filter(\n\t\t\t(name) =>\n\t\t\t\tspecifiers.includes(name) || (namespace !== undefined && usesNamespaceMember(code, namespace, name)),\n\t\t);\n\t\tconst before = code.slice(0, start);\n\t\tconst location = `${id}:${before.split('\\n').length}:${start - before.lastIndexOf('\\n')}`;\n\t\tfor (const name of used) {\n\t\t\tmessages.push(\n\t\t\t\t`${location} - ${name} from '${source}' reads files and environment variables with Node.js, so it cannot run in a browser bundle. Call it in server code, or set the tyfigo plugin's target option to 'server' if this bundle runs on a server.`,\n\t\t\t);\n\t\t}\n\t}\n\treturn messages;\n};\n"],"mappings":";;;;AAsBA,MAAa,oBAAoB,IAAI,OACpC,MAAM,eAAe,KAAK,WAAW,OAAO,WAAW,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,KACvF,GACD;;;;AAKA,MAAa,oBAAoB,MAAc,YAAqC;CACnF,MAAM,SAAS,KAAK,MAAM,OAAO;CACjC,IAAI,OAAO,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,kBAAkB,KAAK,IAAI,eAAe,OAAO,QAAQ,GAAG;CAC5G,OAAO;AACR;AAYA,MAAa,oBAAoB,aAA2C,SAAS,SAAS,QAAQ,CAAC,SAAS;AAEhH,MAAM,kBAA+D;CACpE,QAAQ,CAAC,WAAW,cAAc;CAClC,iBAAiB;EAAC;EAAW;EAAY;EAA0B;CAA6B;AACjG;AAEA,MAAM,eAAe;AAErB,MAAa,sBAAsB;AAEnC,MAAM,uBAAuB,MAAc,WAAmB,SAC7D,IAAI,OAAO,OAAO,GAAG,cAAc,UAAU,WAAW,KAAK,OAAO,GAAG,IAAI,EAAE,aAAa,KAAK,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI;AAEnH,MAAM,mBAAmB,WAA6B;CACrD,MAAM,OAAO,OAAO,QAAQ,GAAG;CAC/B,MAAM,QAAQ,OAAO,QAAQ,KAAK,IAAI;CACtC,IAAI,SAAS,MAAM,UAAU,IAAI,OAAO,CAAC;CACzC,OAAO,OACL,MAAM,OAAO,GAAG,KAAK,CAAC,CACtB,MAAM,GAAG,CAAC,CACV,KAAK,cAAc,UAAU,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE;AAC5D;;;;;AAMA,MAAa,uBAAuB,MAAc,OAAyB;CAC1E,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,SAAS,KAAK,SAAS,YAAY,GAAG;EAChD,MAAM,SAAS,MAAM,MAAM;EAC3B,MAAM,QAAQ,KAAK,IAAI,KAAK,YAAY,UAAU,MAAM,KAAK,GAAG,KAAK,YAAY,UAAU,MAAM,KAAK,CAAC;EACvG,MAAM,SAAS,KAAK,MAAM,QAAQ,GAAiB,MAAM,KAAK;EAC9D,IAAI,UAAU,MAAM,UAAU,KAAK,MAAM,KAAK,iBAAiB,KAAK,MAAM,GAAG;EAE7E,MAAM,aAAa,gBAAgB,MAAM;EACzC,MAAM,YAAY,sBAAsB,KAAK,MAAM,CAAC,GAAG;EACvD,MAAM,QAAQ,gBAAgB,WAAW,CAAC,EAAA,CAAG,QAC3C,SACA,WAAW,SAAS,IAAI,KAAM,cAAc,KAAA,KAAa,oBAAoB,MAAM,WAAW,IAAI,CACpG;EACA,MAAM,SAAS,KAAK,MAAM,GAAG,KAAK;EAClC,MAAM,WAAW,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI,CAAC,CAAC,OAAO,GAAG,QAAQ,OAAO,YAAY,IAAI;EACtF,KAAK,MAAM,QAAQ,MAClB,SAAS,KACR,GAAG,SAAS,KAAK,KAAK,SAAS,OAAO,0MACvC;CAEF;CACA,OAAO;AACR"}
@@ -1,2 +0,0 @@
1
- import "./shared-CZ44uwQq.mjs";
2
- import "unplugin";
@@ -1 +0,0 @@
1
- {"version":3,"file":"unplugin-BQGm_bhA.mjs","names":[],"sources":["../src/plugins/unplugin.ts"],"sourcesContent":["import { createUnplugin } from 'unplugin';\n\nimport {\n\tconfigFilePattern,\n\tfindNodeOnlyImports,\n\tisServerPlatform,\n\tloadConfigImport,\n\ttyfigoImportPattern,\n} from './shared.ts';\n\nimport type { LoadOptions } from '../runtime/load.ts';\nimport type { TyfigoPluginOptions, WebpackLikeCompiler } from './shared.ts';\nimport type { UnpluginBuildContext, UnpluginFactory } from 'unplugin';\n\nexport type { TyfigoPluginOptions } from './shared.ts';\n\nconst webpackMode = (compiler: WebpackLikeCompiler) =>\n\tcompiler.options.mode === 'none' ? undefined : compiler.options.mode;\n\ninterface ViteContext {\n\treadonly environment?: { readonly config: { readonly consumer: string } };\n}\n\nexport const unpluginFactory: UnpluginFactory<TyfigoPluginOptions | undefined, false> = (options = {}) => {\n\tlet viteCommand: string | undefined;\n\tlet viteMode: string | undefined;\n\tlet rolldownPlatform: string | undefined;\n\n\tconst detect = (\n\t\tcontext: UnpluginBuildContext,\n\t\tloadOptions: { readonly ssr?: boolean } | undefined,\n\t): Pick<LoadOptions, 'target' | 'bundle' | 'environment'> => {\n\t\tconst native = context.getNativeBuildContext?.();\n\t\tif (native?.framework === 'webpack' || native?.framework === 'rspack') {\n\t\t\tconst compiler = native.compiler as WebpackLikeCompiler;\n\t\t\treturn {\n\t\t\t\ttarget: isServerPlatform(compiler.platform) ? 'server' : 'browser',\n\t\t\t\tbundle: true,\n\t\t\t\tenvironment: webpackMode(compiler),\n\t\t\t};\n\t\t}\n\t\tif (native?.framework === 'esbuild') {\n\t\t\treturn { target: native.build.initialOptions.platform === 'node' ? 'server' : 'browser', bundle: true };\n\t\t}\n\t\tif (viteCommand) {\n\t\t\tconst consumer = (context as ViteContext).environment?.config.consumer;\n\t\t\treturn {\n\t\t\t\ttarget: (consumer === undefined ? loadOptions?.ssr : consumer === 'server') ? 'server' : 'browser',\n\t\t\t\tbundle: viteCommand === 'build',\n\t\t\t\tenvironment: viteMode,\n\t\t\t};\n\t\t}\n\t\treturn { target: rolldownPlatform === 'node' ? 'server' : 'browser', bundle: true };\n\t};\n\n\treturn {\n\t\tname: 'tyfigo',\n\t\tenforce: 'pre',\n\t\tload: {\n\t\t\tfilter: { id: configFilePattern },\n\t\t\thandler(id, loadOptions?: { readonly ssr?: boolean }) {\n\t\t\t\tconst detected = detect(this, loadOptions);\n\t\t\t\tconst result = loadConfigImport(id, {\n\t\t\t\t\t...detected,\n\t\t\t\t\ttarget: options.target ?? detected.target,\n\t\t\t\t\tenvironment: options.environment ?? detected.environment,\n\t\t\t\t\truntime: options.runtime,\n\t\t\t\t});\n\t\t\t\tfor (const file of result.watchFiles) this.addWatchFile(file);\n\t\t\t\treturn { code: result.code, moduleType: 'js' };\n\t\t\t},\n\t\t},\n\t\ttransform: {\n\t\t\tfilter: {\n\t\t\t\tid: { include: /\\.(?:[cm]?[jt]sx?|vue|svelte|astro)(?:\\?|$)/u, exclude: /[\\\\/]node_modules[\\\\/]/u },\n\t\t\t\tcode: tyfigoImportPattern,\n\t\t\t},\n\t\t\thandler(code, id, transformOptions?: { readonly ssr?: boolean }) {\n\t\t\t\tif ((options.target ?? detect(this, transformOptions).target) !== 'browser') return;\n\t\t\t\tconst messages = findNodeOnlyImports(code, id);\n\t\t\t\tif (messages.length > 0) throw new Error(messages.join('\\n'));\n\t\t\t},\n\t\t},\n\t\tvite: {\n\t\t\tconfigResolved(config) {\n\t\t\t\tviteCommand = config.command;\n\t\t\t\tviteMode = config.mode;\n\t\t\t},\n\t\t},\n\t\trolldown: {\n\t\t\toptions(input) {\n\t\t\t\trolldownPlatform = input.platform;\n\t\t\t},\n\t\t},\n\t\tesbuild: { loader: 'js' },\n\t};\n};\n\nexport const tyfigo = createUnplugin(unpluginFactory);\n"],"mappings":";;;AAgBA,MAAM,eAAe,aACpB,SAAS,QAAQ,SAAS,SAAS,KAAA,IAAY,SAAS,QAAQ;AAMjE,MAAa,mBAA4E,UAAU,CAAC,MAAM;CACzG,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,UACL,SACA,gBAC4D;EAC5D,MAAM,SAAS,QAAQ,wBAAwB;EAC/C,IAAI,QAAQ,cAAc,aAAa,QAAQ,cAAc,UAAU;GACtE,MAAM,WAAW,OAAO;GACxB,OAAO;IACN,QAAQ,iBAAiB,SAAS,QAAQ,IAAI,WAAW;IACzD,QAAQ;IACR,aAAa,YAAY,QAAQ;GAClC;EACD;EACA,IAAI,QAAQ,cAAc,WACzB,OAAO;GAAE,QAAQ,OAAO,MAAM,eAAe,aAAa,SAAS,WAAW;GAAW,QAAQ;EAAK;EAEvG,IAAI,aAAa;GAChB,MAAM,WAAY,QAAwB,aAAa,OAAO;GAC9D,OAAO;IACN,SAAS,aAAa,KAAA,IAAY,aAAa,MAAM,aAAa,YAAY,WAAW;IACzF,QAAQ,gBAAgB;IACxB,aAAa;GACd;EACD;EACA,OAAO;GAAE,QAAQ,qBAAqB,SAAS,WAAW;GAAW,QAAQ;EAAK;CACnF;CAEA,OAAO;EACN,MAAM;EACN,SAAS;EACT,MAAM;GACL,QAAQ,EAAE,IAAI,kBAAkB;GAChC,QAAQ,IAAI,aAA0C;IACrD,MAAM,WAAW,OAAO,MAAM,WAAW;IACzC,MAAM,SAAS,iBAAiB,IAAI;KACnC,GAAG;KACH,QAAQ,QAAQ,UAAU,SAAS;KACnC,aAAa,QAAQ,eAAe,SAAS;KAC7C,SAAS,QAAQ;IAClB,CAAC;IACD,KAAK,MAAM,QAAQ,OAAO,YAAY,KAAK,aAAa,IAAI;IAC5D,OAAO;KAAE,MAAM,OAAO;KAAM,YAAY;IAAK;GAC9C;EACD;EACA,WAAW;GACV,QAAQ;IACP,IAAI;KAAE,SAAS;KAAgD,SAAS;IAA0B;IAClG,MAAM;GACP;GACA,QAAQ,MAAM,IAAI,kBAA+C;IAChE,KAAK,QAAQ,UAAU,OAAO,MAAM,gBAAgB,CAAC,CAAC,YAAY,WAAW;IAC7E,MAAM,WAAW,oBAAoB,MAAM,EAAE;IAC7C,IAAI,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,KAAK,IAAI,CAAC;GAC7D;EACD;EACA,MAAM,EACL,eAAe,QAAQ;GACtB,cAAc,OAAO;GACrB,WAAW,OAAO;EACnB,EACD;EACA,UAAU,EACT,QAAQ,OAAO;GACd,mBAAmB,MAAM;EAC1B,EACD;EACA,SAAS,EAAE,QAAQ,KAAK;CACzB;AACD;AAEA,MAAa,SAAS,eAAe,eAAe"}