@effected/tsconfig-json 0.3.2 → 0.4.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.
@@ -86,6 +86,7 @@ const PRESERVED_OPTIONS = [
86
86
  ...PRESERVED_ENUM_OPTIONS,
87
87
  ...PRESERVED_STRING_OPTIONS
88
88
  ];
89
+ const OPT_IN_TYPES_OPTION = "types";
89
90
  /**
90
91
  * A `ResolvedTsconfig` carries a string `configPath`, an array `extendedPaths`
91
92
  * AND an object `compilerOptions`; a bare `CompilerOptions.Type` never carries
@@ -101,23 +102,17 @@ const PRESERVED_OPTIONS = [
101
102
  * is filtered, which is the safe outcome.)
102
103
  */
103
104
  const isResolvedTsconfig = (input) => typeof input.configPath === "string" && Array.isArray(input.extendedPaths) && typeof input.compilerOptions === "object" && input.compilerOptions !== null;
104
- /**
105
- * Project a {@link (ResolvedTsconfig:interface)} or a bare
106
- * `CompilerOptions.Type` down to a {@link (PortableTsconfig:interface)}: copy
107
- * only the allow-listed type-semantics options, force `composite: false` and
108
- * `noEmit: true` regardless of what the source declared, and stamp `$schema`.
109
- * Every other key — including every unknown passthrough key the source
110
- * preserved for forward tolerance — is dropped; this is an allow-list, not a
111
- * deny-list, so an option this package does not yet classify never leaks onto
112
- * the portable shape by accident.
113
- */
114
- const make = (input) => {
105
+ const make = (input, options) => {
115
106
  const source = isResolvedTsconfig(input) ? input.compilerOptions : input;
116
107
  const compilerOptions = {};
117
108
  for (const key of PRESERVED_OPTIONS) {
118
109
  const value = source[key];
119
110
  if (value !== void 0) compilerOptions[key] = value;
120
111
  }
112
+ if (options?.includeTypes === true) {
113
+ const types = source[OPT_IN_TYPES_OPTION];
114
+ if (types !== void 0) compilerOptions[OPT_IN_TYPES_OPTION] = types;
115
+ }
121
116
  compilerOptions.composite = false;
122
117
  compilerOptions.noEmit = true;
123
118
  return {
@@ -126,13 +121,40 @@ const make = (input) => {
126
121
  };
127
122
  };
128
123
  /**
129
- * The portable-tsconfig filter: {@link (PortableTsconfig:variable).make}
124
+ * The portable-tsconfig filter: {@link (PortableTsconfig:class).make}
130
125
  * narrows a resolved or bare compiler-options object to the allow-listed,
131
126
  * machine-independent subset described on {@link (PortableTsconfig:interface)}.
132
127
  *
133
128
  * @public
134
129
  */
135
- const PortableTsconfig = { make };
130
+ var PortableTsconfig = class {
131
+ constructor() {}
132
+ /**
133
+ * Project a {@link (ResolvedTsconfig:interface)} or a bare
134
+ * `CompilerOptions.Type` down to a {@link (PortableTsconfig:interface)}:
135
+ * copy only the allow-listed type-semantics options, force
136
+ * `composite: false` and `noEmit: true` regardless of what the source
137
+ * declared, and stamp `$schema`. Every other key — including every
138
+ * unknown passthrough key the source preserved for forward tolerance —
139
+ * is dropped; this is an allow-list, not a deny-list, so an option this
140
+ * package does not yet classify never leaks onto the portable shape by
141
+ * accident.
142
+ *
143
+ * `types` is the one deliberate exception, and it is opt-in rather than
144
+ * unclassified: it is portable (package names, not paths) but carrying it
145
+ * makes TypeScript demand those packages be resolvable, which a virtual
146
+ * environment with no `node_modules` cannot satisfy. Pass
147
+ * {@link PortableTsconfigOptions.includeTypes} when the consumer
148
+ * materializes `@types`; leave it off for the permissive default. Related
149
+ * `typeRoots` is never carried — machine-specific,
150
+ * config-location-dependent directories.
151
+ *
152
+ * @param input - The resolved config, or a bare compiler-options bag.
153
+ * @param options - Opt-ins for options that are portable but
154
+ * resolution-dependent. Omitted means the strict, always-safe subset.
155
+ */
156
+ static make = make;
157
+ };
136
158
 
137
159
  //#endregion
138
160
  export { PortableTsconfig };
package/README.md CHANGED
@@ -82,8 +82,13 @@ console.log(TsEnumCodec.encodeCompilerOptions({ target: "es2023", strict: true,
82
82
 
83
83
  console.log(PortableTsconfig.make(resolved).compilerOptions.noEmit);
84
84
  // true — always forced, whatever the source config declared
85
+
86
+ console.log(PortableTsconfig.make(resolved, { includeTypes: true }).compilerOptions.types);
87
+ // carries the source config's `types` package names when it declares them, omitted when absent
85
88
  ```
86
89
 
90
+ `includeTypes` is opt-in and defaults to `false` because emitting `types` makes tsc demand those `@types` packages resolve — a hard error in a virtual environment with no `node_modules`. Pass it when your environment materializes `@types` itself; leave it off for the permissive default where TypeScript auto-includes whatever it finds.
91
+
87
92
  ## Synchronous loading
88
93
 
89
94
  Bundler plugin hooks and config factories often cannot await. `TsconfigLoaderSync` runs the unchanged loader pipeline synchronously over file and path operations you supply — the package still imports no `node:*` module, and Node's built-ins satisfy the operations directly:
@@ -154,7 +159,7 @@ console.log(fsMap.size);
154
159
  - `ResolvedTsconfig` — the pure merge engine behind `resolve`: per-field merge semantics, path-option absolutization against the declaring config's directory, final `${configDir}` substitution and `pathsBase` provenance, with no filesystem access at all.
155
160
  - `TsconfigDiscovery.findNearest` — the nearest `tsconfig.json` (or any filename via `options.filename`) at or above a starting directory, over `@effected/walker`; one unreadable ancestor cannot hide a config above it.
156
161
  - `TsEnumCodec` — the string↔numeric enum tables as plain data with zero `typescript` imports. `encodeCompilerOptions` returns the exported `ProgrammaticCompilerOptions` type — the numeric shape `ts.CompilerOptions` expects, so you hand it to a `ts.CompilerOptions`-shaped API without a cast — with `lib` entries in the file-name form the compiler resolves verbatim; `decodeCompilerOptions` reverses it.
157
- - `PortableTsconfig.make` — an allow-list projection down to machine-independent type-semantics options, with `composite: false` and `noEmit: true` forced: the slice a virtual TypeScript environment (Twoslash, API Extractor, an in-memory language service) can safely inherit.
162
+ - `PortableTsconfig.make` — an allow-list projection down to machine-independent type-semantics options, with `composite: false` and `noEmit: true` forced: the slice a virtual TypeScript environment (Twoslash, API Extractor, an in-memory language service) can safely inherit. An optional `{ includeTypes }` argument carries the source config's `types` package names onto the portable shape too, for a caller whose virtual environment can resolve `@types` packages itself; `typeRoots` stays dropped either way, since it names machine-specific, config-location-dependent directories.
158
163
  - `JsxConfig.fromCompilerOptions` — the JSX transform a bundler can configure, projected from decoded options: `react-jsx` / `react-jsxdev` select the automatic runtime with its import source (defaulting to `react`, tsc's own default), `react` selects classic, and `preserve`, `react-native` or an absent `jsx` yield `Option.none()`.
159
164
  - Typed failures everywhere: a malformed file is a `TsconfigParseError` carrying its path, a broken chain is a `TsconfigExtendsError` with a `not-found` / `cycle` / `depth` / `empty` reason and the full resolution chain, and IO errors flow through as `PlatformError`. Nothing fails as a defect.
160
165
 
@@ -72,16 +72,6 @@ const transformCompilerOptionPaths = (co, transform, includePathsValues) => {
72
72
  }
73
73
  return out;
74
74
  };
75
- /**
76
- * Absolutize a config's path-typed options (E5) against its own `configDir`,
77
- * using the injected `join` (`Path.Path.resolve` at the call site — so an
78
- * already-absolute value is preserved). `${configDir}`-prefixed values are
79
- * exempt (resolved later, in {@link (ResolvedTsconfig:variable).substituteConfigDir}), and
80
- * `paths` VALUES stay verbatim. Only `compilerOptions` path surfaces are
81
- * touched; `files`/`include`/`exclude` are re-rooted at merge time instead (E4).
82
- *
83
- * @public
84
- */
85
75
  const absolutize = (doc, configDir, join) => {
86
76
  const co = doc.compilerOptions;
87
77
  if (co === void 0) return doc;
@@ -153,14 +143,6 @@ const mergeWatchOptions = (base, derived) => {
153
143
  ...derived
154
144
  };
155
145
  };
156
- /**
157
- * Fold one more-derived config onto the accumulated base (E4), derived winning.
158
- * The loader (Task 8) applies this across the resolution chain, own config last.
159
- * `derivedPath` is the derived config's absolute normalized path, from which the
160
- * re-rooting frame and `pathsBase` are computed.
161
- *
162
- * @public
163
- */
164
146
  const merge = (base, derived, derivedPath) => {
165
147
  const finalDir = dirname(derivedPath);
166
148
  const baseDir = dirname(base.configPath);
@@ -202,15 +184,6 @@ const substituteWatchExcludes = (wo, substitute) => {
202
184
  }
203
185
  return out;
204
186
  };
205
- /**
206
- * The E5 final phase: replace a leading `${configDir}` token (case-insensitive,
207
- * leading position only) with `finalDir` — the top-level extending config's
208
- * directory — across every eligible surface: compilerOptions path options,
209
- * `paths` values, `files`/`include`/`exclude`, and `watchOptions`'
210
- * `excludeDirectories`/`excludeFiles`. Every other field is left untouched.
211
- *
212
- * @public
213
- */
214
187
  const substituteConfigDir = (resolved, finalDir) => {
215
188
  const substitute = (value) => startsWithConfigDir(value) ? finalDir + value.slice(CONFIG_DIR_TEMPLATE.length) : value;
216
189
  const compilerOptions = transformCompilerOptionPaths(resolved.compilerOptions, substitute, true);
@@ -229,16 +202,42 @@ const substituteConfigDir = (resolved, finalDir) => {
229
202
  };
230
203
  /**
231
204
  * The pure extends-merge engine: parse-time path absolutization
232
- * ({@link (ResolvedTsconfig:variable).absolutize}), the per-field merge fold
233
- * ({@link (ResolvedTsconfig:variable).merge}), and the `${configDir}` final
234
- * phase ({@link (ResolvedTsconfig:variable).substituteConfigDir}).
205
+ * ({@link (ResolvedTsconfig:class).absolutize}), the per-field merge fold
206
+ * ({@link (ResolvedTsconfig:class).merge}), and the `${configDir}` final
207
+ * phase ({@link (ResolvedTsconfig:class).substituteConfigDir}).
235
208
  *
236
209
  * @public
237
210
  */
238
- const ResolvedTsconfig = {
239
- absolutize,
240
- merge,
241
- substituteConfigDir
211
+ var ResolvedTsconfig = class {
212
+ constructor() {}
213
+ /**
214
+ * Absolutize a config's path-typed options (E5) against its own
215
+ * `configDir`, using the injected `join` (`Path.Path.resolve` at the call
216
+ * site — so an already-absolute value is preserved). `${configDir}`-prefixed
217
+ * values are exempt (resolved later, in
218
+ * {@link (ResolvedTsconfig:class).substituteConfigDir}), and `paths`
219
+ * VALUES stay verbatim. Only `compilerOptions` path surfaces are touched;
220
+ * `files`/`include`/`exclude` are re-rooted at merge time instead (E4).
221
+ */
222
+ static absolutize = absolutize;
223
+ /**
224
+ * Fold one more-derived config onto the accumulated base (E4), derived
225
+ * winning. The loader (Task 8) applies this across the resolution chain,
226
+ * own config last. `derivedPath` is the derived config's absolute
227
+ * normalized path, from which the re-rooting frame and `pathsBase` are
228
+ * computed.
229
+ */
230
+ static merge = merge;
231
+ /**
232
+ * The E5 final phase: replace a leading `${configDir}` token
233
+ * (case-insensitive, leading position only) with `finalDir` — the
234
+ * top-level extending config's directory — across every eligible
235
+ * surface: compilerOptions path options, `paths` values,
236
+ * `files`/`include`/`exclude`, and `watchOptions`'
237
+ * `excludeDirectories`/`excludeFiles`. Every other field is left
238
+ * untouched.
239
+ */
240
+ static substituteConfigDir = substituteConfigDir;
242
241
  };
243
242
 
244
243
  //#endregion
package/TsEnumCodec.js CHANGED
@@ -94,31 +94,8 @@ const TABLES = {
94
94
  ["fixedchunksize", 3]
95
95
  ])
96
96
  };
97
- /**
98
- * Encodes a family's canonical (or alias) string spelling to its numeric
99
- * form. `Option.none()` for a string with no table entry — never guessed.
100
- *
101
- * @public
102
- */
103
97
  const encode = (family, value) => Option.fromNullishOr(TABLES[family].forward.get(value));
104
- /**
105
- * Decodes a family's numeric value to its canonical string spelling.
106
- * `Option.none()` for a numeric value with no table entry (a future TS enum
107
- * member) — never guessed.
108
- *
109
- * @public
110
- */
111
98
  const decode = (family, value) => Option.fromNullishOr(TABLES[family].reverse.get(value));
112
- /**
113
- * Normalizes any spelling of a `lib` reference — the plain short name
114
- * (`esnext`), the on-disk file name (`lib.esnext.d.ts`), or an absolute path
115
- * to one (`/…/typescript/lib/lib.dom.iterable.d.ts`) — to the canonical
116
- * lowercase short name (`esnext`, `dom.iterable`). Strips a leading
117
- * directory, the `lib.` prefix and the `.d.ts` suffix; idempotent on an
118
- * already-short name.
119
- *
120
- * @public
121
- */
122
99
  const normalizeLibReference = (lib) => {
123
100
  const base = (lib.split("/").pop() ?? lib).toLowerCase();
124
101
  const withoutPrefix = base.startsWith("lib.") ? base.slice(4) : base;
@@ -133,24 +110,6 @@ const COMPILER_OPTION_ENUM_KEYS = [
133
110
  ["newLine", "newLine"],
134
111
  ["moduleDetection", "moduleDetection"]
135
112
  ];
136
- /**
137
- * Encodes a decoded `compilerOptions` object into the numeric-enum-shaped
138
- * {@link ProgrammaticCompilerOptions} form `ts.CompilerOptions` (and
139
- * `@typescript/vfs`'s `TsEnvironment`) expect: every R1.6 enum family becomes
140
- * its numeric value, and `lib` entries become the file-name form
141
- * (`lib.esnext.d.ts`) — see the module banner for the evidence. Every other key
142
- * (booleans, strings, arrays, unknown passthrough keys) is copied through
143
- * untouched.
144
- *
145
- * The return carries this package's single narrowing from the codec's internal
146
- * `Record<string, unknown>` (whose values include the schema's `unknown`
147
- * passthrough and its `readonly` arrays) to {@link ProgrammaticCompilerOptions}
148
- * — see that type's docs for why the package owns this one assertion instead of
149
- * leaving every consumer to cast. Runtime behavior is unchanged; only the
150
- * declared return type narrows.
151
- *
152
- * @public
153
- */
154
113
  const encodeCompilerOptions = (options) => {
155
114
  const source = options;
156
115
  const result = { ...source };
@@ -165,20 +124,6 @@ const encodeCompilerOptions = (options) => {
165
124
  if (Array.isArray(lib)) result.lib = lib.map((entry) => typeof entry === "string" ? `lib.${normalizeLibReference(entry)}.d.ts` : entry);
166
125
  return result;
167
126
  };
168
- /**
169
- * Decodes a numeric-enum-shaped `compilerOptions` object (as produced by
170
- * {@link (TsEnumCodec:variable).encodeCompilerOptions} or read off a live
171
- * `ts.CompilerOptions`) back into the string-enum shape this package's
172
- * schemas use: every R1.6 enum family becomes its canonical string, and
173
- * `lib` entries become the short form. A numeric value with no table entry —
174
- * a future TS enum member — is left as-is (passthrough, never an error) —
175
- * which is why the return type stays the wider `Record<string, unknown>`
176
- * rather than {@link (CompilerOptions:variable).Type}: an unmappable
177
- * passthrough value would violate that narrower type's contract. Every other
178
- * key is copied through untouched.
179
- *
180
- * @public
181
- */
182
127
  const decodeCompilerOptions = (numeric) => {
183
128
  const result = { ...numeric };
184
129
  for (const [key, family] of COMPILER_OPTION_ENUM_KEYS) {
@@ -199,12 +144,61 @@ const decodeCompilerOptions = (numeric) => {
199
144
  *
200
145
  * @public
201
146
  */
202
- const TsEnumCodec = {
203
- encode,
204
- decode,
205
- normalizeLibReference,
206
- encodeCompilerOptions,
207
- decodeCompilerOptions
147
+ var TsEnumCodec = class {
148
+ constructor() {}
149
+ /**
150
+ * Encodes a family's canonical (or alias) string spelling to its numeric
151
+ * form. `Option.none()` for a string with no table entry — never guessed.
152
+ */
153
+ static encode = encode;
154
+ /**
155
+ * Decodes a family's numeric value to its canonical string spelling.
156
+ * `Option.none()` for a numeric value with no table entry (a future TS
157
+ * enum member) — never guessed.
158
+ */
159
+ static decode = decode;
160
+ /**
161
+ * Normalizes any spelling of a `lib` reference — the plain short name
162
+ * (`esnext`), the on-disk file name (`lib.esnext.d.ts`), or an absolute
163
+ * path to one (`/…/typescript/lib/lib.dom.iterable.d.ts`) — to the
164
+ * canonical lowercase short name (`esnext`, `dom.iterable`). Strips a
165
+ * leading directory, the `lib.` prefix and the `.d.ts` suffix; idempotent
166
+ * on an already-short name.
167
+ */
168
+ static normalizeLibReference = normalizeLibReference;
169
+ /**
170
+ * Encodes a decoded `compilerOptions` object into the
171
+ * numeric-enum-shaped {@link ProgrammaticCompilerOptions} form
172
+ * `ts.CompilerOptions` (and `@typescript/vfs`'s `TsEnvironment`) expect:
173
+ * every R1.6 enum family becomes its numeric value, and `lib` entries
174
+ * become the file-name form (`lib.esnext.d.ts`) — see the module banner
175
+ * for the evidence. Every other key (booleans, strings, arrays, unknown
176
+ * passthrough keys) is copied through untouched.
177
+ *
178
+ * @remarks
179
+ * The return carries this package's single narrowing from the codec's
180
+ * internal `Record<string, unknown>` (whose values include the schema's
181
+ * `unknown` passthrough and its `readonly` arrays) to
182
+ * {@link ProgrammaticCompilerOptions} — see that type's docs for why the
183
+ * package owns this one assertion instead of leaving every consumer to
184
+ * cast. Runtime behavior is unchanged; only the declared return type
185
+ * narrows.
186
+ */
187
+ static encodeCompilerOptions = encodeCompilerOptions;
188
+ /**
189
+ * Decodes a numeric-enum-shaped `compilerOptions` object (as produced by
190
+ * {@link TsEnumCodec.encodeCompilerOptions} or read off a live
191
+ * `ts.CompilerOptions`) back into the string-enum shape this package's
192
+ * schemas use: every R1.6 enum family becomes its canonical string, and
193
+ * `lib` entries become the short form. A numeric value with no table
194
+ * entry — a future TS enum member — is left as-is (passthrough, never an
195
+ * error) — which is why the return type stays the wider
196
+ * `Record<string, unknown>` rather than
197
+ * {@link (CompilerOptions:namespace).Type}: an unmappable passthrough
198
+ * value would violate that narrower type's contract. Every other key is
199
+ * copied through untouched.
200
+ */
201
+ static decodeCompilerOptions = decodeCompilerOptions;
208
202
  };
209
203
 
210
204
  //#endregion
@@ -2,16 +2,6 @@ import { Effect, Path } from "effect";
2
2
  import { Walker } from "@effected/walker";
3
3
 
4
4
  //#region src/TsconfigDiscovery.ts
5
- /**
6
- * Find the nearest `tsconfig.json` (or `options.filename`) at or above
7
- * `start`, ascending toward the filesystem root. Absence — nowhere on the
8
- * chain, or every candidate unreadable — is `Option.none()`, never an error;
9
- * discovery is best-effort per `Walker.findUpward`'s absorption posture, and a
10
- * permission-denied probe on one directory does not hide a config file above
11
- * it.
12
- *
13
- * @public
14
- */
15
5
  const findNearest = (start, options) => Effect.gen(function* () {
16
6
  const path = yield* Path.Path;
17
7
  const filename = options?.filename ?? "tsconfig.json";
@@ -23,7 +13,18 @@ const findNearest = (start, options) => Effect.gen(function* () {
23
13
  *
24
14
  * @public
25
15
  */
26
- const TsconfigDiscovery = { findNearest };
16
+ var TsconfigDiscovery = class {
17
+ constructor() {}
18
+ /**
19
+ * Find the nearest `tsconfig.json` (or `options.filename`) at or above
20
+ * `start`, ascending toward the filesystem root. Absence — nowhere on the
21
+ * chain, or every candidate unreadable — is `Option.none()`, never an
22
+ * error; discovery is best-effort per `Walker.findUpward`'s absorption
23
+ * posture, and a permission-denied probe on one directory does not hide a
24
+ * config file above it.
25
+ */
26
+ static findNearest = findNearest;
27
+ };
27
28
 
28
29
  //#endregion
29
30
  export { TsconfigDiscovery };
package/TsconfigLoader.js CHANGED
@@ -58,14 +58,6 @@ const loadAbs = (abs) => Effect.gen(function* () {
58
58
  cause
59
59
  })));
60
60
  });
61
- /**
62
- * Read one config file and decode it through {@link TsconfigJsonFromString}. A
63
- * decode failure is wrapped in a {@link TsconfigParseError} carrying the file's
64
- * absolute path; a `PlatformError` from the read flows through untranslated. No
65
- * `extends` resolution — {@link TsconfigLoader.resolve} drives that.
66
- *
67
- * @public
68
- */
69
61
  const load = Effect.fn("TsconfigLoader.load")(function* (configPath) {
70
62
  const path = yield* Path.Path;
71
63
  return yield* loadAbs(normalizeSlashes(path.resolve(configPath)));
@@ -119,19 +111,6 @@ const collect = (configPath, chain) => Effect.gen(function* () {
119
111
  });
120
112
  return layers;
121
113
  });
122
- /**
123
- * Resolve a tsconfig.json and its full `extends` chain into a
124
- * {@link (ResolvedTsconfig:interface)}: load and decode each config, absolutize its path
125
- * options (E5), resolve `extends` depth-first with per-branch cycle and depth
126
- * guards (E1-E3, E6), fold the chain own-config-last (E4), then substitute a
127
- * leading `${configDir}` once against the top config's directory (E5 final
128
- * phase). `configPath` + `extendedPaths` come back base-most first, own config
129
- * last. Every failure is a typed error — `TsconfigParseError` (a malformed file,
130
- * carrying that file's path), `TsconfigExtendsError` (a broken chain), or a
131
- * `PlatformError` from IO — never a defect.
132
- *
133
- * @public
134
- */
135
114
  const resolve = Effect.fn("TsconfigLoader.resolve")(function* (configPath) {
136
115
  const path = yield* Path.Path;
137
116
  const topAbs = normalizeSlashes(path.resolve(configPath));
@@ -144,14 +123,6 @@ const resolve = Effect.fn("TsconfigLoader.resolve")(function* (configPath) {
144
123
  for (const entry of layers) acc = ResolvedTsconfig.merge(acc, entry.doc, entry.path);
145
124
  return ResolvedTsconfig.substituteConfigDir(acc, path.dirname(topAbs));
146
125
  });
147
- /**
148
- * Resolve a tsconfig.json's full `extends` chain and project out the merged
149
- * `compilerOptions` — a thin projection of {@link TsconfigLoader.resolve} for
150
- * the common "just give me the effective options" query. Same pipeline, same
151
- * typed failures.
152
- *
153
- * @public
154
- */
155
126
  const compilerOptions = Effect.fn("TsconfigLoader.compilerOptions")(function* (configPath) {
156
127
  return (yield* resolve(configPath)).compilerOptions;
157
128
  });
@@ -163,10 +134,36 @@ const compilerOptions = Effect.fn("TsconfigLoader.compilerOptions")(function* (c
163
134
  *
164
135
  * @public
165
136
  */
166
- const TsconfigLoader = {
167
- load,
168
- resolve,
169
- compilerOptions
137
+ var TsconfigLoader = class {
138
+ constructor() {}
139
+ /**
140
+ * Read one config file and decode it through {@link TsconfigJsonFromString}.
141
+ * A decode failure is wrapped in a {@link TsconfigParseError} carrying the
142
+ * file's absolute path; a `PlatformError` from the read flows through
143
+ * untranslated. No `extends` resolution — {@link TsconfigLoader.resolve}
144
+ * drives that.
145
+ */
146
+ static load = load;
147
+ /**
148
+ * Resolve a tsconfig.json and its full `extends` chain into a
149
+ * {@link (ResolvedTsconfig:interface)}: load and decode each config,
150
+ * absolutize its path options (E5), resolve `extends` depth-first with
151
+ * per-branch cycle and depth guards (E1-E3, E6), fold the chain
152
+ * own-config-last (E4), then substitute a leading `${configDir}` once
153
+ * against the top config's directory (E5 final phase). `configPath` +
154
+ * `extendedPaths` come back base-most first, own config last. Every
155
+ * failure is a typed error — `TsconfigParseError` (a malformed file,
156
+ * carrying that file's path), `TsconfigExtendsError` (a broken chain), or
157
+ * a `PlatformError` from IO — never a defect.
158
+ */
159
+ static resolve = resolve;
160
+ /**
161
+ * Resolve a tsconfig.json's full `extends` chain and project out the
162
+ * merged `compilerOptions` — a thin projection of
163
+ * {@link TsconfigLoader.resolve} for the common "just give me the
164
+ * effective options" query. Same pipeline, same typed failures.
165
+ */
166
+ static compilerOptions = compilerOptions;
170
167
  };
171
168
 
172
169
  //#endregion
@@ -67,30 +67,8 @@ const runWith = (options, effect) => {
67
67
  if (Result.isSuccess(defect)) throw defect.success;
68
68
  throw Cause.squash(exit.cause);
69
69
  };
70
- /**
71
- * {@link TsconfigLoader.load}, synchronously: read and decode one config file
72
- * through the consumer-supplied operations. Throws `TsconfigParseError` or a
73
- * `PlatformError` — the async pipeline's exact typed failures.
74
- *
75
- * @public
76
- */
77
70
  const load = (configPath, options) => runWith(options, TsconfigLoader.load(configPath));
78
- /**
79
- * {@link TsconfigLoader.resolve}, synchronously: the full load -\> extends -\>
80
- * merge -\> `${configDir}` pipeline through the consumer-supplied operations.
81
- * Throws `TsconfigParseError`, `TsconfigExtendsError` or a `PlatformError` —
82
- * the async pipeline's exact typed failures.
83
- *
84
- * @public
85
- */
86
71
  const resolve = (configPath, options) => runWith(options, TsconfigLoader.resolve(configPath));
87
- /**
88
- * {@link TsconfigLoader.compilerOptions}, synchronously: resolve the full
89
- * `extends` chain and project out the merged `compilerOptions`. Throws the
90
- * same typed failures as {@link TsconfigLoaderSync.resolve}.
91
- *
92
- * @public
93
- */
94
72
  const compilerOptions = (configPath, options) => resolve(configPath, options).compilerOptions;
95
73
  /**
96
74
  * The synchronous tsconfig.json loader facade: the {@link TsconfigLoader}
@@ -121,10 +99,29 @@ const compilerOptions = (configPath, options) => resolve(configPath, options).co
121
99
  *
122
100
  * @public
123
101
  */
124
- const TsconfigLoaderSync = {
125
- load,
126
- resolve,
127
- compilerOptions
102
+ var TsconfigLoaderSync = class {
103
+ constructor() {}
104
+ /**
105
+ * {@link TsconfigLoader.load}, synchronously: read and decode one config
106
+ * file through the consumer-supplied operations. Throws
107
+ * `TsconfigParseError` or a `PlatformError` — the async pipeline's exact
108
+ * typed failures.
109
+ */
110
+ static load = load;
111
+ /**
112
+ * {@link TsconfigLoader.resolve}, synchronously: the full load -\>
113
+ * extends -\> merge -\> `${configDir}` pipeline through the
114
+ * consumer-supplied operations. Throws `TsconfigParseError`,
115
+ * `TsconfigExtendsError` or a `PlatformError` — the async pipeline's exact
116
+ * typed failures.
117
+ */
118
+ static resolve = resolve;
119
+ /**
120
+ * {@link TsconfigLoader.compilerOptions}, synchronously: resolve the full
121
+ * `extends` chain and project out the merged `compilerOptions`. Throws
122
+ * the same typed failures as {@link TsconfigLoaderSync.resolve}.
123
+ */
124
+ static compilerOptions = compilerOptions;
128
125
  };
129
126
 
130
127
  //#endregion
package/index.d.ts CHANGED
@@ -550,17 +550,43 @@ interface ResolvedTsconfig {
550
550
  }
551
551
  /**
552
552
  * The pure extends-merge engine: parse-time path absolutization
553
- * ({@link (ResolvedTsconfig:variable).absolutize}), the per-field merge fold
554
- * ({@link (ResolvedTsconfig:variable).merge}), and the `${configDir}` final
555
- * phase ({@link (ResolvedTsconfig:variable).substituteConfigDir}).
553
+ * ({@link (ResolvedTsconfig:class).absolutize}), the per-field merge fold
554
+ * ({@link (ResolvedTsconfig:class).merge}), and the `${configDir}` final
555
+ * phase ({@link (ResolvedTsconfig:class).substituteConfigDir}).
556
556
  *
557
557
  * @public
558
558
  */
559
- declare const ResolvedTsconfig: {
560
- readonly absolutize: (doc: TsconfigJson.Type, configDir: string, join: (a: string, b: string) => string) => TsconfigJson.Type;
561
- readonly merge: (base: ResolvedTsconfig, derived: TsconfigJson.Type, derivedPath: string) => ResolvedTsconfig;
562
- readonly substituteConfigDir: (resolved: ResolvedTsconfig, finalDir: string) => ResolvedTsconfig;
563
- };
559
+ declare class ResolvedTsconfig {
560
+ private constructor();
561
+ /**
562
+ * Absolutize a config's path-typed options (E5) against its own
563
+ * `configDir`, using the injected `join` (`Path.Path.resolve` at the call
564
+ * site — so an already-absolute value is preserved). `${configDir}`-prefixed
565
+ * values are exempt (resolved later, in
566
+ * {@link (ResolvedTsconfig:class).substituteConfigDir}), and `paths`
567
+ * VALUES stay verbatim. Only `compilerOptions` path surfaces are touched;
568
+ * `files`/`include`/`exclude` are re-rooted at merge time instead (E4).
569
+ */
570
+ static readonly absolutize: (doc: TsconfigJson.Type, configDir: string, join: (a: string, b: string) => string) => TsconfigJson.Type;
571
+ /**
572
+ * Fold one more-derived config onto the accumulated base (E4), derived
573
+ * winning. The loader (Task 8) applies this across the resolution chain,
574
+ * own config last. `derivedPath` is the derived config's absolute
575
+ * normalized path, from which the re-rooting frame and `pathsBase` are
576
+ * computed.
577
+ */
578
+ static readonly merge: (base: ResolvedTsconfig, derived: TsconfigJson.Type, derivedPath: string) => ResolvedTsconfig;
579
+ /**
580
+ * The E5 final phase: replace a leading `${configDir}` token
581
+ * (case-insensitive, leading position only) with `finalDir` — the
582
+ * top-level extending config's directory — across every eligible
583
+ * surface: compilerOptions path options, `paths` values,
584
+ * `files`/`include`/`exclude`, and `watchOptions`'
585
+ * `excludeDirectories`/`excludeFiles`. Every other field is left
586
+ * untouched.
587
+ */
588
+ static readonly substituteConfigDir: (resolved: ResolvedTsconfig, finalDir: string) => ResolvedTsconfig;
589
+ }
564
590
  //#endregion
565
591
  //#region src/PortableTsconfig.d.ts
566
592
  /**
@@ -578,15 +604,62 @@ interface PortableTsconfig {
578
604
  readonly compilerOptions: Record<string, unknown>;
579
605
  }
580
606
  /**
581
- * The portable-tsconfig filter: {@link (PortableTsconfig:variable).make}
607
+ * Options for {@link (PortableTsconfig:class).make}.
608
+ *
609
+ * @public
610
+ */
611
+ interface PortableTsconfigOptions {
612
+ /**
613
+ * Carry `types` (an array of `@types` package NAMES) onto the portable
614
+ * shape when the source declares it. Defaults to `false`.
615
+ *
616
+ * Opt in when the consuming environment can resolve those packages — it
617
+ * materializes `@types` into its virtual filesystem, or type-checks against
618
+ * a real `node_modules`. Leaving it off keeps the permissive default, where
619
+ * TypeScript auto-includes whatever `@types` the environment happens to
620
+ * have and never errors on a missing one.
621
+ *
622
+ * `typeRoots` is NOT carried under this flag: it names filesystem
623
+ * directories, which are machine-specific and config-location-dependent,
624
+ * so they are never portable.
625
+ */
626
+ readonly includeTypes?: boolean;
627
+ }
628
+ /**
629
+ * The portable-tsconfig filter: {@link (PortableTsconfig:class).make}
582
630
  * narrows a resolved or bare compiler-options object to the allow-listed,
583
631
  * machine-independent subset described on {@link (PortableTsconfig:interface)}.
584
632
  *
585
633
  * @public
586
634
  */
587
- declare const PortableTsconfig: {
588
- readonly make: (input: ResolvedTsconfig | CompilerOptions.Type) => PortableTsconfig;
589
- };
635
+ declare class PortableTsconfig {
636
+ private constructor();
637
+ /**
638
+ * Project a {@link (ResolvedTsconfig:interface)} or a bare
639
+ * `CompilerOptions.Type` down to a {@link (PortableTsconfig:interface)}:
640
+ * copy only the allow-listed type-semantics options, force
641
+ * `composite: false` and `noEmit: true` regardless of what the source
642
+ * declared, and stamp `$schema`. Every other key — including every
643
+ * unknown passthrough key the source preserved for forward tolerance —
644
+ * is dropped; this is an allow-list, not a deny-list, so an option this
645
+ * package does not yet classify never leaks onto the portable shape by
646
+ * accident.
647
+ *
648
+ * `types` is the one deliberate exception, and it is opt-in rather than
649
+ * unclassified: it is portable (package names, not paths) but carrying it
650
+ * makes TypeScript demand those packages be resolvable, which a virtual
651
+ * environment with no `node_modules` cannot satisfy. Pass
652
+ * {@link PortableTsconfigOptions.includeTypes} when the consumer
653
+ * materializes `@types`; leave it off for the permissive default. Related
654
+ * `typeRoots` is never carried — machine-specific,
655
+ * config-location-dependent directories.
656
+ *
657
+ * @param input - The resolved config, or a bare compiler-options bag.
658
+ * @param options - Opt-ins for options that are portable but
659
+ * resolution-dependent. Omitted means the strict, always-safe subset.
660
+ */
661
+ static readonly make: (input: ResolvedTsconfig | CompilerOptions.Type, options?: PortableTsconfigOptions) => PortableTsconfig;
662
+ }
590
663
  //#endregion
591
664
  //#region src/TsconfigDiscovery.d.ts
592
665
  /**
@@ -605,9 +678,18 @@ interface FindNearestOptions {
605
678
  *
606
679
  * @public
607
680
  */
608
- declare const TsconfigDiscovery: {
609
- readonly findNearest: (start: string, options?: FindNearestOptions) => Effect.Effect<Option.Option<string>, never, FileSystem.FileSystem | Path.Path>;
610
- };
681
+ declare class TsconfigDiscovery {
682
+ private constructor();
683
+ /**
684
+ * Find the nearest `tsconfig.json` (or `options.filename`) at or above
685
+ * `start`, ascending toward the filesystem root. Absence — nowhere on the
686
+ * chain, or every candidate unreadable — is `Option.none()`, never an
687
+ * error; discovery is best-effort per `Walker.findUpward`'s absorption
688
+ * posture, and a permission-denied probe on one directory does not hide a
689
+ * config file above it.
690
+ */
691
+ static readonly findNearest: (start: string, options?: FindNearestOptions) => Effect.Effect<Option.Option<string>, never, FileSystem.FileSystem | Path.Path>;
692
+ }
611
693
  //#endregion
612
694
  //#region src/TsconfigLoader.d.ts
613
695
  declare const TsconfigExtendsError_base: Schema.Class<TsconfigExtendsError, Schema.TaggedStruct<"TsconfigExtendsError", {
@@ -642,8 +724,16 @@ declare class TsconfigExtendsError extends TsconfigExtendsError_base {
642
724
  *
643
725
  * @public
644
726
  */
645
- declare const TsconfigLoader: {
646
- readonly load: (configPath: string) => Effect.Effect<{
727
+ declare class TsconfigLoader {
728
+ private constructor();
729
+ /**
730
+ * Read one config file and decode it through {@link TsconfigJsonFromString}.
731
+ * A decode failure is wrapped in a {@link TsconfigParseError} carrying the
732
+ * file's absolute path; a `PlatformError` from the read flows through
733
+ * untranslated. No `extends` resolution — {@link TsconfigLoader.resolve}
734
+ * drives that.
735
+ */
736
+ static readonly load: (configPath: string) => Effect.Effect<{
647
737
  readonly [x: string]: unknown;
648
738
  readonly compilerOptions?: {
649
739
  readonly [x: string]: unknown;
@@ -790,8 +880,26 @@ declare const TsconfigLoader: {
790
880
  readonly compileOnSave?: boolean | undefined;
791
881
  readonly $schema?: string | undefined;
792
882
  }, PlatformError.PlatformError | TsconfigParseError, FileSystem.FileSystem | Path.Path>;
793
- readonly resolve: (configPath: string) => Effect.Effect<ResolvedTsconfig, PlatformError.PlatformError | TsconfigExtendsError | TsconfigParseError, FileSystem.FileSystem | Path.Path>;
794
- readonly compilerOptions: (configPath: string) => Effect.Effect<{
883
+ /**
884
+ * Resolve a tsconfig.json and its full `extends` chain into a
885
+ * {@link (ResolvedTsconfig:interface)}: load and decode each config,
886
+ * absolutize its path options (E5), resolve `extends` depth-first with
887
+ * per-branch cycle and depth guards (E1-E3, E6), fold the chain
888
+ * own-config-last (E4), then substitute a leading `${configDir}` once
889
+ * against the top config's directory (E5 final phase). `configPath` +
890
+ * `extendedPaths` come back base-most first, own config last. Every
891
+ * failure is a typed error — `TsconfigParseError` (a malformed file,
892
+ * carrying that file's path), `TsconfigExtendsError` (a broken chain), or
893
+ * a `PlatformError` from IO — never a defect.
894
+ */
895
+ static readonly resolve: (configPath: string) => Effect.Effect<ResolvedTsconfig, PlatformError.PlatformError | TsconfigExtendsError | TsconfigParseError, FileSystem.FileSystem | Path.Path>;
896
+ /**
897
+ * Resolve a tsconfig.json's full `extends` chain and project out the
898
+ * merged `compilerOptions` — a thin projection of
899
+ * {@link TsconfigLoader.resolve} for the common "just give me the
900
+ * effective options" query. Same pipeline, same typed failures.
901
+ */
902
+ static readonly compilerOptions: (configPath: string) => Effect.Effect<{
795
903
  readonly [x: string]: unknown;
796
904
  readonly target?: "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "es2023" | "es2024" | "es2025" | "es5" | "es6" | "esnext" | undefined;
797
905
  readonly module?: "amd" | "commonjs" | "es2015" | "es2020" | "es2022" | "es6" | "esnext" | "node16" | "node18" | "node20" | "nodenext" | "none" | "preserve" | "system" | "umd" | undefined;
@@ -909,7 +1017,7 @@ declare const TsconfigLoader: {
909
1017
  }[] | undefined;
910
1018
  readonly maxNodeModuleJsDepth?: number | undefined;
911
1019
  }, PlatformError.PlatformError | TsconfigExtendsError | TsconfigParseError, FileSystem.FileSystem | Path.Path>;
912
- };
1020
+ }
913
1021
  //#endregion
914
1022
  //#region src/TsconfigLoaderSync.d.ts
915
1023
  /**
@@ -1012,11 +1120,30 @@ interface TsconfigLoaderSyncOptions {
1012
1120
  *
1013
1121
  * @public
1014
1122
  */
1015
- declare const TsconfigLoaderSync: {
1016
- readonly load: (configPath: string, options: TsconfigLoaderSyncOptions) => TsconfigJson.Type;
1017
- readonly resolve: (configPath: string, options: TsconfigLoaderSyncOptions) => ResolvedTsconfig;
1018
- readonly compilerOptions: (configPath: string, options: TsconfigLoaderSyncOptions) => CompilerOptions.Type;
1019
- };
1123
+ declare class TsconfigLoaderSync {
1124
+ private constructor();
1125
+ /**
1126
+ * {@link TsconfigLoader.load}, synchronously: read and decode one config
1127
+ * file through the consumer-supplied operations. Throws
1128
+ * `TsconfigParseError` or a `PlatformError` — the async pipeline's exact
1129
+ * typed failures.
1130
+ */
1131
+ static readonly load: (configPath: string, options: TsconfigLoaderSyncOptions) => TsconfigJson.Type;
1132
+ /**
1133
+ * {@link TsconfigLoader.resolve}, synchronously: the full load -\>
1134
+ * extends -\> merge -\> `${configDir}` pipeline through the
1135
+ * consumer-supplied operations. Throws `TsconfigParseError`,
1136
+ * `TsconfigExtendsError` or a `PlatformError` — the async pipeline's exact
1137
+ * typed failures.
1138
+ */
1139
+ static readonly resolve: (configPath: string, options: TsconfigLoaderSyncOptions) => ResolvedTsconfig;
1140
+ /**
1141
+ * {@link TsconfigLoader.compilerOptions}, synchronously: resolve the full
1142
+ * `extends` chain and project out the merged `compilerOptions`. Throws
1143
+ * the same typed failures as {@link TsconfigLoaderSync.resolve}.
1144
+ */
1145
+ static readonly compilerOptions: (configPath: string, options: TsconfigLoaderSyncOptions) => CompilerOptions.Type;
1146
+ }
1020
1147
  //#endregion
1021
1148
  //#region src/TsEnumCodec.d.ts
1022
1149
  /**
@@ -1068,7 +1195,7 @@ type ProgrammaticCompilerOptionsValue = string | number | boolean | (string | nu
1068
1195
  readonly circular?: boolean;
1069
1196
  }[] | null | undefined;
1070
1197
  /**
1071
- * The shape {@link (TsEnumCodec:variable).encodeCompilerOptions} returns: the
1198
+ * The shape {@link TsEnumCodec.encodeCompilerOptions} returns: the
1072
1199
  * numeric-enum-encoded `compilerOptions` a virtual-TS environment and the
1073
1200
  * TypeScript compiler API consume programmatically.
1074
1201
  *
@@ -1115,13 +1242,62 @@ interface ProgrammaticCompilerOptions {
1115
1242
  *
1116
1243
  * @public
1117
1244
  */
1118
- declare const TsEnumCodec: {
1119
- readonly encode: (family: EnumFamily, value: string) => Option.Option<number>;
1120
- readonly decode: (family: EnumFamily, value: number) => Option.Option<string>;
1121
- readonly normalizeLibReference: (lib: string) => string;
1122
- readonly encodeCompilerOptions: (options: CompilerOptions.Type) => ProgrammaticCompilerOptions;
1123
- readonly decodeCompilerOptions: (numeric: Readonly<Record<string, unknown>>) => Record<string, unknown>;
1124
- };
1245
+ declare class TsEnumCodec {
1246
+ private constructor();
1247
+ /**
1248
+ * Encodes a family's canonical (or alias) string spelling to its numeric
1249
+ * form. `Option.none()` for a string with no table entry — never guessed.
1250
+ */
1251
+ static readonly encode: (family: EnumFamily, value: string) => Option.Option<number>;
1252
+ /**
1253
+ * Decodes a family's numeric value to its canonical string spelling.
1254
+ * `Option.none()` for a numeric value with no table entry (a future TS
1255
+ * enum member) — never guessed.
1256
+ */
1257
+ static readonly decode: (family: EnumFamily, value: number) => Option.Option<string>;
1258
+ /**
1259
+ * Normalizes any spelling of a `lib` reference — the plain short name
1260
+ * (`esnext`), the on-disk file name (`lib.esnext.d.ts`), or an absolute
1261
+ * path to one (`/…/typescript/lib/lib.dom.iterable.d.ts`) — to the
1262
+ * canonical lowercase short name (`esnext`, `dom.iterable`). Strips a
1263
+ * leading directory, the `lib.` prefix and the `.d.ts` suffix; idempotent
1264
+ * on an already-short name.
1265
+ */
1266
+ static readonly normalizeLibReference: (lib: string) => string;
1267
+ /**
1268
+ * Encodes a decoded `compilerOptions` object into the
1269
+ * numeric-enum-shaped {@link ProgrammaticCompilerOptions} form
1270
+ * `ts.CompilerOptions` (and `@typescript/vfs`'s `TsEnvironment`) expect:
1271
+ * every R1.6 enum family becomes its numeric value, and `lib` entries
1272
+ * become the file-name form (`lib.esnext.d.ts`) — see the module banner
1273
+ * for the evidence. Every other key (booleans, strings, arrays, unknown
1274
+ * passthrough keys) is copied through untouched.
1275
+ *
1276
+ * @remarks
1277
+ * The return carries this package's single narrowing from the codec's
1278
+ * internal `Record<string, unknown>` (whose values include the schema's
1279
+ * `unknown` passthrough and its `readonly` arrays) to
1280
+ * {@link ProgrammaticCompilerOptions} — see that type's docs for why the
1281
+ * package owns this one assertion instead of leaving every consumer to
1282
+ * cast. Runtime behavior is unchanged; only the declared return type
1283
+ * narrows.
1284
+ */
1285
+ static readonly encodeCompilerOptions: (options: CompilerOptions.Type) => ProgrammaticCompilerOptions;
1286
+ /**
1287
+ * Decodes a numeric-enum-shaped `compilerOptions` object (as produced by
1288
+ * {@link TsEnumCodec.encodeCompilerOptions} or read off a live
1289
+ * `ts.CompilerOptions`) back into the string-enum shape this package's
1290
+ * schemas use: every R1.6 enum family becomes its canonical string, and
1291
+ * `lib` entries become the short form. A numeric value with no table
1292
+ * entry — a future TS enum member — is left as-is (passthrough, never an
1293
+ * error) — which is why the return type stays the wider
1294
+ * `Record<string, unknown>` rather than
1295
+ * {@link (CompilerOptions:namespace).Type}: an unmappable passthrough
1296
+ * value would violate that narrower type's contract. Every other key is
1297
+ * copied through untouched.
1298
+ */
1299
+ static readonly decodeCompilerOptions: (numeric: Readonly<Record<string, unknown>>) => Record<string, unknown>;
1300
+ }
1125
1301
  //#endregion
1126
- export { CompilerOptions, type EnumFamily, FallbackPolling, type FindNearestOptions, Jsx, JsxConfig, Lib, Module, ModuleDetection, ModuleResolution, NewLine, PortableTsconfig, type ProgrammaticCompilerOptions, type ProgrammaticCompilerOptionsValue, Reference, ResolvedTsconfig, type SyncFileSystem, type SyncPath, Target, TsEnumCodec, TsconfigDiscovery, TsconfigExtendsError, TsconfigJson, TsconfigJsonFromString, TsconfigLoader, TsconfigLoaderSync, type TsconfigLoaderSyncOptions, TsconfigParseError, TypeAcquisition, WatchDirectory, WatchFile, WatchOptions };
1302
+ export { CompilerOptions, type EnumFamily, FallbackPolling, type FindNearestOptions, Jsx, JsxConfig, Lib, Module, ModuleDetection, ModuleResolution, NewLine, PortableTsconfig, type PortableTsconfigOptions, type ProgrammaticCompilerOptions, type ProgrammaticCompilerOptionsValue, Reference, ResolvedTsconfig, type SyncFileSystem, type SyncPath, Target, TsEnumCodec, TsconfigDiscovery, TsconfigExtendsError, TsconfigJson, TsconfigJsonFromString, TsconfigLoader, TsconfigLoaderSync, type TsconfigLoaderSyncOptions, TsconfigParseError, TypeAcquisition, WatchDirectory, WatchFile, WatchOptions };
1127
1303
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/tsconfig-json",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Composable tsconfig.json handling for Effect: schemas, extends-chain resolution, and config discovery.",
6
6
  "keywords": [
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@effected/jsonc": "~0.5.1",
43
- "@effected/walker": "~0.3.2",
43
+ "@effected/walker": "~0.3.3",
44
44
  "effect": "4.0.0-beta.101"
45
45
  },
46
46
  "engines": {