tyfigo 0.2.0-next.a30eb96.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -4
- package/dist/bun.d.mts +8 -1
- package/dist/bun.mjs +7 -7
- package/dist/bun.mjs.map +1 -1
- package/dist/effect.mjs +2 -2
- package/dist/{env-Bd-1Atoz.mjs → env--pSRlq_k.mjs} +2 -2
- package/dist/{env-Bd-1Atoz.mjs.map → env--pSRlq_k.mjs.map} +1 -1
- package/dist/env-Dv5OHfEf.mjs +51 -0
- package/dist/env-Dv5OHfEf.mjs.map +1 -0
- package/dist/{formats-D_dKXoPf.mjs → formats-Bf8-iQw-.mjs} +43 -15
- package/dist/{formats-D_dKXoPf.mjs.map → formats-Bf8-iQw-.mjs.map} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{load-C-kweoyY.d.mts → load-D1KO5LdK.d.mts} +6 -4
- package/dist/{load-DxIjRpX6.mjs → load-yFCdP4to.mjs} +49 -23
- package/dist/load-yFCdP4to.mjs.map +1 -0
- package/dist/mapper.mjs +28 -11
- package/dist/mapper.mjs.map +1 -1
- package/dist/plugins/esbuild.d.mts +2 -2
- package/dist/plugins/esbuild.mjs +1 -1
- package/dist/plugins/jest.d.mts +1 -1
- package/dist/plugins/jest.mjs +4 -4
- package/dist/plugins/loader.d.mts +1 -1
- package/dist/plugins/loader.mjs +3 -2
- package/dist/plugins/loader.mjs.map +1 -1
- package/dist/plugins/next.d.mts +1 -1
- package/dist/plugins/next.mjs +9 -4
- package/dist/plugins/next.mjs.map +1 -1
- package/dist/plugins/rolldown.d.mts +2 -2
- package/dist/plugins/rolldown.mjs +1 -1
- package/dist/plugins/rollup.d.mts +2 -2
- package/dist/plugins/rollup.mjs +1 -1
- package/dist/plugins/rsbuild.d.mts +2 -2
- package/dist/plugins/rsbuild.mjs +1 -1
- package/dist/plugins/rspack.d.mts +2 -2
- package/dist/plugins/rspack.mjs +1 -1
- package/dist/plugins/vite.d.mts +2 -2
- package/dist/plugins/vite.mjs +1 -1
- package/dist/plugins/webpack.d.mts +2 -2
- package/dist/plugins/webpack.mjs +1 -1
- package/dist/problems-DS_eJB6e.mjs +86 -0
- package/dist/problems-DS_eJB6e.mjs.map +1 -0
- package/dist/register.mjs +5 -5
- package/dist/register.mjs.map +1 -1
- package/dist/{resolve-D3geHCGs.mjs → resolve-DQfTdYJN.mjs} +32 -12
- package/dist/resolve-DQfTdYJN.mjs.map +1 -0
- package/dist/runtime/index.d.mts +13 -4
- package/dist/runtime/index.mjs +2 -2
- package/dist/{runtime-DeRUtPZ9.mjs → runtime-B3GmIYop.mjs} +13 -9
- package/dist/runtime-B3GmIYop.mjs.map +1 -0
- package/dist/{shared-CZ44uwQq.d.mts → shared-B6Y3_kdn.d.mts} +6 -5
- package/dist/{shared-BnK77Zcp.mjs → shared-DOMPQnVO.mjs} +4 -6
- package/dist/shared-DOMPQnVO.mjs.map +1 -0
- package/dist/{sync-B-HAK-_E.mjs → sync-mWkXcCOW.mjs} +2 -2
- package/dist/{sync-B-HAK-_E.mjs.map → sync-mWkXcCOW.mjs.map} +1 -1
- package/dist/unplugin-BYfqHkIE.d.mts +2 -0
- package/dist/{unplugin-BQGm_bhA.mjs → unplugin-BoZ7PwTA.mjs} +36 -13
- package/dist/unplugin-BoZ7PwTA.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/env-R3_XPW_u.mjs +0 -78
- package/dist/env-R3_XPW_u.mjs.map +0 -1
- package/dist/load-DxIjRpX6.mjs.map +0 -1
- package/dist/problems-BNAqmOzL.mjs +0 -23
- package/dist/problems-BNAqmOzL.mjs.map +0 -1
- package/dist/resolve-D3geHCGs.mjs.map +0 -1
- package/dist/runtime-DeRUtPZ9.mjs.map +0 -1
- package/dist/shared-BnK77Zcp.mjs.map +0 -1
- package/dist/unplugin-AC_HM_T2.d.mts +0 -2
- package/dist/unplugin-BQGm_bhA.mjs.map +0 -1
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { c as isFile, d as listDirectory, o as findFile, r as problemAt, t as fileProblem, u as layerDirectories } from "./problems-DS_eJB6e.mjs";
|
|
2
|
+
import { n as processEnv, r as readEnv } from "./env-Dv5OHfEf.mjs";
|
|
3
3
|
import { n as formatPath, r as pathKey, t as SourceIndex } from "./positions-BCTEFZTX.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { c as isPlainObject, l as kindOf, o as parseConfigPath, t as configFileDescription, u as resolvePlaceholders } from "./formats-Bf8-iQw-.mjs";
|
|
5
5
|
import { Effect, Result } from "effect";
|
|
6
6
|
import { basename, dirname, join, resolve } from "node:path";
|
|
7
7
|
import { readFileSync } from "node:fs";
|
|
8
8
|
// src/core/layers.ts
|
|
9
9
|
/**
|
|
10
10
|
* The layer files of a base config file, in the order they apply: `app.config.yaml`, `app.<environment>.config.yaml`,
|
|
11
|
-
* `app.local.config.yaml` and `app.<environment>.local.config.yaml`.
|
|
12
|
-
*
|
|
11
|
+
* `app.local.config.yaml` and `app.<environment>.local.config.yaml` (`.config/app.yaml`, `.config/app.<environment>.yaml` and so
|
|
12
|
+
* on in a `.config` directory). Only files that exist are listed. Environment files sit next to the base file, and local files are
|
|
13
|
+
* searched next to it first, then in the project root (or its `.config` directory), see {@link layerDirectories}.
|
|
13
14
|
*/
|
|
14
15
|
const discoverLayers = Effect.fn("discoverLayers")(function* (baseFile, environment) {
|
|
15
16
|
const file = resolve(baseFile);
|
|
16
|
-
const name =
|
|
17
|
+
const name = parseConfigPath(file);
|
|
17
18
|
if (!name) return [];
|
|
18
|
-
const directories = yield*
|
|
19
|
+
const directories = yield* layerDirectories(file);
|
|
19
20
|
const layers = [];
|
|
20
21
|
if (yield* isFile(file)) layers.push({
|
|
21
22
|
file,
|
|
@@ -42,6 +43,25 @@ const discoverLayers = Effect.fn("discoverLayers")(function* (baseFile, environm
|
|
|
42
43
|
}
|
|
43
44
|
return layers;
|
|
44
45
|
});
|
|
46
|
+
/**
|
|
47
|
+
* The environment names that have a layer file for a base config file: every `app.<environment>.config.yaml` next to it, and
|
|
48
|
+
* every `app.<environment>.local.config.yaml` where {@link discoverLayers} searches local files. Sorted.
|
|
49
|
+
*/
|
|
50
|
+
const discoverEnvironments = Effect.fn("discoverEnvironments")(function* (baseFile) {
|
|
51
|
+
const file = resolve(baseFile);
|
|
52
|
+
const name = parseConfigPath(file);
|
|
53
|
+
if (!name) return [];
|
|
54
|
+
const environments = /* @__PURE__ */ new Set();
|
|
55
|
+
for (const directory of yield* layerDirectories(file)) for (const entry of yield* listDirectory(directory)) {
|
|
56
|
+
if (!entry.startsWith(`${name.stem}.`) || !entry.endsWith(name.suffix)) continue;
|
|
57
|
+
const middle = entry.slice(name.stem.length + 1, -name.suffix.length);
|
|
58
|
+
const local = middle.endsWith(".local");
|
|
59
|
+
const environment = local ? middle.slice(0, -6) : middle;
|
|
60
|
+
if (!local && directory !== dirname(file)) continue;
|
|
61
|
+
if (/^[^.]+$/u.test(environment) && environment !== "local") environments.add(environment);
|
|
62
|
+
}
|
|
63
|
+
return [...environments].toSorted((a, b) => a.localeCompare(b));
|
|
64
|
+
});
|
|
45
65
|
// src/core/merge.ts
|
|
46
66
|
const isWithin = (id, prefix) => id === prefix || id.startsWith(prefix === "[]" ? "[" : `${prefix.slice(0, -1)},`);
|
|
47
67
|
const locate = (file, positions) => new Map([...positions].map(([id, span]) => [id, {
|
|
@@ -163,7 +183,7 @@ const mergeLayers = Effect.fn("mergeLayers")(function* (format, files, read, var
|
|
|
163
183
|
problems
|
|
164
184
|
};
|
|
165
185
|
});
|
|
166
|
-
const unsupportedFile = (file) => fileProblem(file, "unsupported-file", `${basename(file)} is not a config file; expected
|
|
186
|
+
const unsupportedFile = (file) => fileProblem(file, "unsupported-file", `${basename(file)} is not a config file; expected ${configFileDescription}`);
|
|
167
187
|
/**
|
|
168
188
|
* Reads a config file with its environment and local layers and `.env` files, resolves placeholders and merges the layers.
|
|
169
189
|
* Never fails: everything that went wrong is in `problems`.
|
|
@@ -172,7 +192,7 @@ const resolveConfig = Effect.fn("resolveConfig")(function* (path, options = {})
|
|
|
172
192
|
const file = resolve(path);
|
|
173
193
|
const env = options.env ?? processEnv();
|
|
174
194
|
const environment = options.environment ?? (env.NODE_ENV || void 0);
|
|
175
|
-
const name =
|
|
195
|
+
const name = parseConfigPath(file);
|
|
176
196
|
const empty = {
|
|
177
197
|
file,
|
|
178
198
|
format: name?.format,
|
|
@@ -211,7 +231,7 @@ const resolveConfig = Effect.fn("resolveConfig")(function* (path, options = {})
|
|
|
211
231
|
const resolveConfigSources = Effect.fn("resolveConfigSources")(function* (file, sources, options) {
|
|
212
232
|
const env = options.env ?? processEnv();
|
|
213
233
|
const environment = options.environment ?? (env.NODE_ENV || void 0);
|
|
214
|
-
const name =
|
|
234
|
+
const name = parseConfigPath(file);
|
|
215
235
|
const empty = {
|
|
216
236
|
file,
|
|
217
237
|
format: name?.format,
|
|
@@ -237,6 +257,6 @@ const resolveConfigSources = Effect.fn("resolveConfigSources")(function* (file,
|
|
|
237
257
|
problems: [...envResult.problems, ...merged.problems]
|
|
238
258
|
};
|
|
239
259
|
});
|
|
240
|
-
export { resolveConfigSources as n, resolveConfig as t };
|
|
260
|
+
export { resolveConfigSources as n, discoverEnvironments as r, resolveConfig as t };
|
|
241
261
|
|
|
242
|
-
//# sourceMappingURL=resolve-
|
|
262
|
+
//# sourceMappingURL=resolve-DQfTdYJN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-DQfTdYJN.mjs","names":[],"sources":["../src/core/layers.ts","../src/core/merge.ts","../src/core/resolve.ts"],"sourcesContent":["import { dirname, join, resolve } from 'node:path';\n\nimport { Effect } from 'effect';\n\nimport { findFile, isFile, layerDirectories, listDirectory } from './files.ts';\nimport { parseConfigPath } 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` (`.config/app.yaml`, `.config/app.<environment>.yaml` and so\n * on in a `.config` directory). Only files that exist are listed. Environment files sit next to the base file, and local files are\n * searched next to it first, then in the project root (or its `.config` directory), see {@link layerDirectories}.\n */\nexport const discoverLayers = Effect.fn('discoverLayers')(function* (baseFile: string, environment?: string) {\n\tconst file = resolve(baseFile);\n\tconst name = parseConfigPath(file);\n\tif (!name) return [];\n\n\tconst directories = yield* layerDirectories(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 = parseConfigPath(file);\n\tif (!name) return [];\n\n\tconst environments = new Set<string>();\n\tfor (const directory of yield* layerDirectories(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 { configFileDescription, parseConfigPath } 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(file, 'unsupported-file', `${basename(file)} is not a config file; expected ${configFileDescription}`);\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 = parseConfigPath(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 = parseConfigPath(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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"}
|
package/dist/runtime/index.d.mts
CHANGED
|
@@ -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-
|
|
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
|
|
39
|
+
readonly layers: readonly BundledLayer[];
|
|
31
40
|
}
|
|
32
41
|
/**
|
|
33
|
-
* {@link resolveConfigModule} for a bundled server module:
|
|
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 };
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -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-
|
|
3
|
-
import { i as resolveConfigModule, n as deepFreeze, r as resolveBundledConfigModule, t as ConfigModuleError } from "../runtime-
|
|
2
|
+
import { n as loadModule, r as valueLiteral, t as load } from "../load-yFCdP4to.mjs";
|
|
3
|
+
import { i as resolveConfigModule, n as deepFreeze, r as resolveBundledConfigModule, t as ConfigModuleError } from "../runtime-B3GmIYop.mjs";
|
|
4
4
|
export { ConfigModuleError, configSource, deepFreeze, getConfigSource, load, loadModule, resolveBundledConfigModule, resolveConfigModule, valueLiteral };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { n as formatProblems } from "./problems-
|
|
1
|
+
import { n as formatProblems } from "./problems-DS_eJB6e.mjs";
|
|
2
|
+
import { n as processEnv } from "./env-Dv5OHfEf.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-
|
|
5
|
+
import { n as resolveConfigSync, t as resolveConfigSourcesSync } from "./sync-mWkXcCOW.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:
|
|
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) =>
|
|
64
|
-
environment
|
|
65
|
-
|
|
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-
|
|
73
|
+
//# sourceMappingURL=runtime-B3GmIYop.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-B3GmIYop.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-
|
|
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,
|
|
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.
|
|
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-
|
|
24
|
+
//# sourceMappingURL=shared-B6Y3_kdn.d.mts.map
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { n as formatProblems } from "./problems-
|
|
2
|
-
import { t as
|
|
3
|
-
import { t as load } from "./load-DxIjRpX6.mjs";
|
|
1
|
+
import { n as formatProblems } from "./problems-DS_eJB6e.mjs";
|
|
2
|
+
import { t as load } from "./load-yFCdP4to.mjs";
|
|
4
3
|
// src/plugins/shared.ts
|
|
5
|
-
const configFilePattern = new RegExp(`(?:${configSuffixes.map((suffix) => suffix.replaceAll(".", String.raw`\.`)).join("|")})$`, "u");
|
|
6
4
|
/**
|
|
7
5
|
* Generates the module for a config import and throws one error listing every problem, which fails the build.
|
|
8
6
|
*/
|
|
@@ -50,6 +48,6 @@ const findNodeOnlyImports = (code, id) => {
|
|
|
50
48
|
}
|
|
51
49
|
return messages;
|
|
52
50
|
};
|
|
53
|
-
export { tyfigoImportPattern as
|
|
51
|
+
export { tyfigoImportPattern as i, isServerPlatform as n, loadConfigImport as r, findNodeOnlyImports as t };
|
|
54
52
|
|
|
55
|
-
//# sourceMappingURL=shared-
|
|
53
|
+
//# sourceMappingURL=shared-DOMPQnVO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-DOMPQnVO.mjs","names":[],"sources":["../src/plugins/shared.ts"],"sourcesContent":["import { 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\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":";;;;;;AA0BA,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-
|
|
1
|
+
import { n as resolveConfigSources, t as resolveConfig } from "./resolve-DQfTdYJN.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-
|
|
14
|
+
//# sourceMappingURL=sync-mWkXcCOW.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-
|
|
1
|
+
{"version":3,"file":"sync-mWkXcCOW.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,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as configPathPattern } from "./formats-Bf8-iQw-.mjs";
|
|
2
|
+
import { i as tyfigoImportPattern, n as isServerPlatform, r as loadConfigImport, t as findNodeOnlyImports } from "./shared-DOMPQnVO.mjs";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
2
4
|
import { createUnplugin } from "unplugin";
|
|
3
5
|
// src/plugins/unplugin.ts
|
|
4
6
|
const webpackMode = (compiler) => compiler.options.mode === "none" ? void 0 : compiler.options.mode;
|
|
@@ -6,6 +8,8 @@ const unpluginFactory = (options = {}) => {
|
|
|
6
8
|
let viteCommand;
|
|
7
9
|
let viteMode;
|
|
8
10
|
let rolldownPlatform;
|
|
11
|
+
let viteServer;
|
|
12
|
+
const missingLayers = /* @__PURE__ */ new Map();
|
|
9
13
|
const detect = (context, loadOptions) => {
|
|
10
14
|
const native = context.getNativeBuildContext?.();
|
|
11
15
|
if (native?.framework === "webpack" || native?.framework === "rspack") {
|
|
@@ -13,7 +17,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
13
17
|
return {
|
|
14
18
|
target: isServerPlatform(compiler.platform) ? "server" : "browser",
|
|
15
19
|
bundle: true,
|
|
16
|
-
|
|
20
|
+
mode: webpackMode(compiler)
|
|
17
21
|
};
|
|
18
22
|
}
|
|
19
23
|
if (native?.framework === "esbuild") return {
|
|
@@ -25,7 +29,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
25
29
|
return {
|
|
26
30
|
target: (consumer === void 0 ? loadOptions?.ssr : consumer === "server") ? "server" : "browser",
|
|
27
31
|
bundle: viteCommand === "build",
|
|
28
|
-
|
|
32
|
+
mode: viteMode
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
35
|
return {
|
|
@@ -37,16 +41,20 @@ const unpluginFactory = (options = {}) => {
|
|
|
37
41
|
name: "tyfigo",
|
|
38
42
|
enforce: "pre",
|
|
39
43
|
load: {
|
|
40
|
-
filter: { id:
|
|
44
|
+
filter: { id: configPathPattern },
|
|
41
45
|
handler(id, loadOptions) {
|
|
42
46
|
const detected = detect(this, loadOptions);
|
|
47
|
+
const target = options.target ?? detected.target;
|
|
43
48
|
const result = loadConfigImport(id, {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
environment: options.environment ?? detected.
|
|
49
|
+
target,
|
|
50
|
+
bundle: detected.bundle,
|
|
51
|
+
environment: options.environment ?? (target === "server" && detected.bundle ? void 0 : detected.mode),
|
|
47
52
|
runtime: options.runtime
|
|
48
53
|
});
|
|
49
|
-
for (const file of result.watchFiles)
|
|
54
|
+
for (const file of result.watchFiles) if (viteServer && !existsSync(file)) {
|
|
55
|
+
missingLayers.set(file, (missingLayers.get(file) ?? /* @__PURE__ */ new Set()).add(id));
|
|
56
|
+
viteServer.watcher.add(file);
|
|
57
|
+
} else this.addWatchFile(file);
|
|
50
58
|
return {
|
|
51
59
|
code: result.code,
|
|
52
60
|
moduleType: "js"
|
|
@@ -67,10 +75,25 @@ const unpluginFactory = (options = {}) => {
|
|
|
67
75
|
if (messages.length > 0) throw new Error(messages.join("\n"));
|
|
68
76
|
}
|
|
69
77
|
},
|
|
70
|
-
vite: {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
vite: {
|
|
79
|
+
configResolved(config) {
|
|
80
|
+
viteCommand = config.command;
|
|
81
|
+
viteMode = config.mode;
|
|
82
|
+
},
|
|
83
|
+
configureServer(server) {
|
|
84
|
+
viteServer = server;
|
|
85
|
+
server.watcher.on("add", (file) => {
|
|
86
|
+
const ids = missingLayers.get(file);
|
|
87
|
+
if (!ids) return;
|
|
88
|
+
missingLayers.delete(file);
|
|
89
|
+
for (const environment of Object.values(server.environments)) for (const id of ids) {
|
|
90
|
+
const module = environment.moduleGraph.getModuleById(id);
|
|
91
|
+
if (module) environment.moduleGraph.invalidateModule(module);
|
|
92
|
+
}
|
|
93
|
+
server.ws.send({ type: "full-reload" });
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
},
|
|
74
97
|
rolldown: { options(input) {
|
|
75
98
|
rolldownPlatform = input.platform;
|
|
76
99
|
} },
|
|
@@ -80,4 +103,4 @@ const unpluginFactory = (options = {}) => {
|
|
|
80
103
|
const tyfigo = createUnplugin(unpluginFactory);
|
|
81
104
|
export { tyfigo as t };
|
|
82
105
|
|
|
83
|
-
//# sourceMappingURL=unplugin-
|
|
106
|
+
//# sourceMappingURL=unplugin-BoZ7PwTA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unplugin-BoZ7PwTA.mjs","names":[],"sources":["../src/plugins/unplugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { createUnplugin } from 'unplugin';\n\nimport { findNodeOnlyImports, isServerPlatform, loadConfigImport, tyfigoImportPattern } from './shared.ts';\n\nimport { configPathPattern } from '../core/index.ts';\n\nimport type { LoadOptions } from '../runtime/load.ts';\nimport type { TyfigoPluginOptions, WebpackLikeCompiler } from './shared.ts';\nimport type { UnpluginBuildContext, UnpluginFactory } from 'unplugin';\nimport type { ViteDevServer } from 'vite';\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\tlet viteServer: ViteDevServer | undefined;\n\tconst missingLayers = new Map<string, Set<string>>();\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: configPathPattern },\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) {\n\t\t\t\t\tif (viteServer && !existsSync(file)) {\n\t\t\t\t\t\tmissingLayers.set(file, (missingLayers.get(file) ?? new Set()).add(id));\n\t\t\t\t\t\tviteServer.watcher.add(file);\n\t\t\t\t\t} else this.addWatchFile(file);\n\t\t\t\t}\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\tconfigureServer(server) {\n\t\t\t\tviteServer = server;\n\t\t\t\tserver.watcher.on('add', (file) => {\n\t\t\t\t\tconst ids = missingLayers.get(file);\n\t\t\t\t\tif (!ids) return;\n\t\t\t\t\tmissingLayers.delete(file);\n\t\t\t\t\tfor (const environment of Object.values(server.environments)) {\n\t\t\t\t\t\tfor (const id of ids) {\n\t\t\t\t\t\t\tconst module = environment.moduleGraph.getModuleById(id);\n\t\t\t\t\t\t\tif (module) environment.moduleGraph.invalidateModule(module);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tserver.ws.send({ type: 'full-reload' });\n\t\t\t\t});\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":";;;;;AAeA,MAAM,eAAe,aACpB,SAAS,QAAQ,SAAS,SAAS,KAAA,IAAY,SAAS,QAAQ;AAMjE,MAAa,mBAA4E,UAAU,CAAC,MAAM;CACzG,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,gCAAgB,IAAI,IAAyB;CAEnD,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,YACzB,IAAI,cAAc,CAAC,WAAW,IAAI,GAAG;KACpC,cAAc,IAAI,OAAO,cAAc,IAAI,IAAI,qBAAK,IAAI,IAAI,EAAA,CAAG,IAAI,EAAE,CAAC;KACtE,WAAW,QAAQ,IAAI,IAAI;IAC5B,OAAO,KAAK,aAAa,IAAI;IAE9B,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;GACL,eAAe,QAAQ;IACtB,cAAc,OAAO;IACrB,WAAW,OAAO;GACnB;GACA,gBAAgB,QAAQ;IACvB,aAAa;IACb,OAAO,QAAQ,GAAG,QAAQ,SAAS;KAClC,MAAM,MAAM,cAAc,IAAI,IAAI;KAClC,IAAI,CAAC,KAAK;KACV,cAAc,OAAO,IAAI;KACzB,KAAK,MAAM,eAAe,OAAO,OAAO,OAAO,YAAY,GAC1D,KAAK,MAAM,MAAM,KAAK;MACrB,MAAM,SAAS,YAAY,YAAY,cAAc,EAAE;MACvD,IAAI,QAAQ,YAAY,YAAY,iBAAiB,MAAM;KAC5D;KAED,OAAO,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;IACvC,CAAC;GACF;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.2.
|
|
3
|
+
"version": "0.2.1",
|
|
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",
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
},
|
|
213
213
|
"lint-staged": {
|
|
214
214
|
"*": "oxfmt --no-error-on-unmatched-pattern",
|
|
215
|
-
"*.{js,mjs,cjs,ts,mts,cts}": "oxlint --fix"
|
|
215
|
+
"*.{js,mjs,cjs,ts,mts,cts}": "oxlint --fix --no-error-on-unmatched-pattern"
|
|
216
216
|
},
|
|
217
217
|
"commitlint": {
|
|
218
218
|
"extends": [
|
package/dist/env-R3_XPW_u.mjs
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { t as fileProblem } from "./problems-BNAqmOzL.mjs";
|
|
2
|
-
import { Effect, Result } from "effect";
|
|
3
|
-
import { dirname, join, resolve } from "node:path";
|
|
4
|
-
import process from "node:process";
|
|
5
|
-
import { readFileSync, statSync } from "node:fs";
|
|
6
|
-
import { parseEnv } from "node:util";
|
|
7
|
-
// src/core/files.ts
|
|
8
|
-
const isFile = (path) => Effect.sync(() => statSync(path, { throwIfNoEntry: false })?.isFile() ?? false);
|
|
9
|
-
/**
|
|
10
|
-
* The nearest directory at or above `directory` that has a `package.json`.
|
|
11
|
-
*/
|
|
12
|
-
const findProjectRoot = Effect.fn("findProjectRoot")(function* (directory) {
|
|
13
|
-
for (let current = directory;; current = dirname(current)) {
|
|
14
|
-
if (yield* isFile(join(current, "package.json"))) return current;
|
|
15
|
-
if (dirname(current) === current) return void 0;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
/**
|
|
19
|
-
* The first existing `name` in `directories`.
|
|
20
|
-
*/
|
|
21
|
-
const findFile = Effect.fn("findFile")(function* (directories, name) {
|
|
22
|
-
for (const directory of directories) {
|
|
23
|
-
const path = join(directory, name);
|
|
24
|
-
if (yield* isFile(path)) return path;
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* The base file's directory followed by the project root when it is a different directory.
|
|
29
|
-
*/
|
|
30
|
-
const searchDirectories = Effect.fn("searchDirectories")(function* (baseFile) {
|
|
31
|
-
const directory = dirname(baseFile);
|
|
32
|
-
const root = yield* findProjectRoot(directory);
|
|
33
|
-
return root === void 0 || root === directory ? [directory] : [directory, root];
|
|
34
|
-
});
|
|
35
|
-
// src/core/env.ts
|
|
36
|
-
/**
|
|
37
|
-
* A copy of the real environment. This is the only place tyfigo reads `process.env`.
|
|
38
|
-
*/
|
|
39
|
-
const processEnv = () => ({ ...process.env });
|
|
40
|
-
const envFileNames = (environment) => environment ? [
|
|
41
|
-
".env",
|
|
42
|
-
".env.local",
|
|
43
|
-
`.env.${environment}`,
|
|
44
|
-
`.env.${environment}.local`
|
|
45
|
-
] : [".env", ".env.local"];
|
|
46
|
-
/**
|
|
47
|
-
* Reads `.env`, `.env.local`, `.env.<environment>` and `.env.<environment>.local` (each later one wins) and puts `env` on top.
|
|
48
|
-
* Each file is searched next to `baseFile` first, then in the nearest directory with a `package.json`. Never writes `process.env`.
|
|
49
|
-
*/
|
|
50
|
-
const readEnv = Effect.fn("readEnv")(function* (baseFile, options = {}) {
|
|
51
|
-
const directories = yield* searchDirectories(resolve(baseFile));
|
|
52
|
-
const variables = {};
|
|
53
|
-
const files = [];
|
|
54
|
-
const problems = [];
|
|
55
|
-
for (const name of envFileNames(options.environment)) {
|
|
56
|
-
const file = yield* findFile(directories, name);
|
|
57
|
-
if (!file) continue;
|
|
58
|
-
const parsed = yield* Effect.result(Effect.try({
|
|
59
|
-
try: () => parseEnv(readFileSync(file, "utf8")),
|
|
60
|
-
catch: (error) => fileProblem(file, "read-error", `Cannot read ${file}: ${error.message}`)
|
|
61
|
-
}));
|
|
62
|
-
if (Result.isFailure(parsed)) {
|
|
63
|
-
problems.push(parsed.failure);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
files.push(file);
|
|
67
|
-
Object.assign(variables, parsed.success);
|
|
68
|
-
}
|
|
69
|
-
for (const [key, value] of Object.entries(options.env ?? processEnv())) if (value !== void 0) variables[key] = value;
|
|
70
|
-
return {
|
|
71
|
-
variables,
|
|
72
|
-
files,
|
|
73
|
-
problems
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
export { findProjectRoot as a, findFile as i, processEnv as n, isFile as o, readEnv as r, searchDirectories as s, envFileNames as t };
|
|
77
|
-
|
|
78
|
-
//# sourceMappingURL=env-R3_XPW_u.mjs.map
|
|
@@ -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,23 +0,0 @@
|
|
|
1
|
-
// src/core/problems.ts
|
|
2
|
-
const problemAt = (source, file, start, length, code, message) => ({
|
|
3
|
-
file,
|
|
4
|
-
start,
|
|
5
|
-
length,
|
|
6
|
-
...source.lineColumn(start),
|
|
7
|
-
message,
|
|
8
|
-
code
|
|
9
|
-
});
|
|
10
|
-
const fileProblem = (file, code, message) => ({
|
|
11
|
-
file,
|
|
12
|
-
start: 0,
|
|
13
|
-
length: 0,
|
|
14
|
-
line: 1,
|
|
15
|
-
column: 1,
|
|
16
|
-
message,
|
|
17
|
-
code
|
|
18
|
-
});
|
|
19
|
-
const formatProblem = (problem) => `${problem.file}:${problem.line}:${problem.column} - ${problem.message} (${problem.code})`;
|
|
20
|
-
const formatProblems = (problems) => problems.map(formatProblem).join("\n");
|
|
21
|
-
export { formatProblems as n, problemAt as r, fileProblem as t };
|
|
22
|
-
|
|
23
|
-
//# sourceMappingURL=problems-BNAqmOzL.mjs.map
|