@tsdoctor/vfs 0.4.7 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TsEnvironment.js +1 -2
- package/TsconfigParser.js +3 -3
- package/TwoslashCache.js +31 -18
- package/TypeResolutionOptions.js +1 -2
- package/TypeScriptConfig.js +4 -4
- package/Vfs.js +1 -2
- package/VirtualPackage.js +1 -2
- package/index.d.ts +11 -19
- package/package.json +7 -3
- package/tsdoc-metadata.json +1 -1
package/TsEnvironment.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isTypeDefinition } from "./Vfs.js";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/TsEnvironment.ts
|
|
5
5
|
/**
|
|
6
6
|
* Raised when building a virtual TypeScript environment fails — including
|
|
7
7
|
* when the optional `typescript` / `@typescript/vfs` /
|
|
@@ -91,5 +91,4 @@ var TsEnvironment = class {
|
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
//#endregion
|
|
95
94
|
export { TsEnvironment, TsEnvironmentError };
|
package/TsconfigParser.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { decodeCompilerOptions } from "./TypeResolutionOptions.js";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { ErrorText } from "@effected/engine";
|
|
4
5
|
import { TsconfigLoaderSync } from "@effected/tsconfig-json";
|
|
5
6
|
import { Result } from "effect";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// src/TsconfigParser.ts
|
|
8
9
|
/**
|
|
9
10
|
* Reading a `tsconfig.json` into the compiler options the plugin consumes.
|
|
10
11
|
*
|
|
@@ -87,12 +88,11 @@ function parseTsConfig(configPath, projectRoot) {
|
|
|
87
88
|
try {
|
|
88
89
|
options = TsconfigLoaderSync.compilerOptions(absolutePath, syncHost);
|
|
89
90
|
} catch (error) {
|
|
90
|
-
throw new TsConfigParseError(absolutePath,
|
|
91
|
+
throw new TsConfigParseError(absolutePath, ErrorText.describe(error), error);
|
|
91
92
|
}
|
|
92
93
|
const decoded = decodeCompilerOptions(options);
|
|
93
94
|
if (Result.isFailure(decoded)) throw new TsConfigParseError(absolutePath, decoded.failure.message, decoded.failure);
|
|
94
95
|
return decoded.success;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
//#endregion
|
|
98
98
|
export { TsConfigParseError, parseTsConfig };
|
package/TwoslashCache.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { Result } from "effect";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
4
|
+
import { JsoncCanonicalizeOptions, JsoncFingerprint } from "@effected/jsonc";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
// src/TwoslashCache.ts
|
|
5
7
|
/**
|
|
6
8
|
* Persisted Twoslash result cache.
|
|
7
9
|
*
|
|
@@ -62,10 +64,16 @@ import { gunzipSync, gzipSync } from "node:zlib";
|
|
|
62
64
|
*
|
|
63
65
|
* @public
|
|
64
66
|
*/
|
|
65
|
-
const TWOSLASH_CACHE_FORMAT =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const TWOSLASH_CACHE_FORMAT = 2;
|
|
68
|
+
const digest = (bytes) => createHash("sha256").update(bytes).digest();
|
|
69
|
+
/**
|
|
70
|
+
* Compiler options are TypeScript's own plain JSON shape, but a member may be
|
|
71
|
+
* present and `undefined`; those are omitted, as `JSON.stringify` would.
|
|
72
|
+
*/
|
|
73
|
+
const COMPILER_OPTIONS_CANONICALIZATION = JsoncCanonicalizeOptions.make({
|
|
74
|
+
undefined: "omit",
|
|
75
|
+
nonFinite: "null"
|
|
76
|
+
});
|
|
69
77
|
/**
|
|
70
78
|
* Fingerprint the type environment a generation is checked against.
|
|
71
79
|
*
|
|
@@ -88,28 +96,31 @@ function sha256(input) {
|
|
|
88
96
|
*/
|
|
89
97
|
function twoslashEnvHash(vfs, toolchain) {
|
|
90
98
|
const hash = createHash("sha256");
|
|
91
|
-
hash.update(`format:${
|
|
99
|
+
hash.update(`format:${2}\0toolchain:${toolchain}\0`);
|
|
92
100
|
for (const key of [...vfs.keys()].sort()) hash.update(`${key}\0${vfs.get(key) ?? ""}\0`);
|
|
93
101
|
return hash.digest("hex");
|
|
94
102
|
}
|
|
95
|
-
/** JSON with object keys sorted, so equivalent options hash identically. */
|
|
96
|
-
function stableStringify(value) {
|
|
97
|
-
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
98
|
-
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
99
|
-
return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
100
|
-
}
|
|
101
103
|
/**
|
|
102
104
|
* Per-entry key: the code, its language, and the compiler configuration it is
|
|
103
105
|
* checked under.
|
|
104
106
|
*
|
|
105
107
|
* The configuration matters because two APIs on one site may be documented
|
|
106
108
|
* under different `tsconfig`s — the same source checked under different options
|
|
107
|
-
* can produce different types, so it must not share a cache entry.
|
|
109
|
+
* can produce different types, so it must not share a cache entry. The options
|
|
110
|
+
* are folded in through their RFC 8785 canonical form, so key order does not
|
|
111
|
+
* matter.
|
|
112
|
+
*
|
|
113
|
+
* Returns `undefined` when the options cannot be canonicalized (a function or a
|
|
114
|
+
* non-plain object among them): such a block is not cached, rather than keyed
|
|
115
|
+
* on a spelling that could collide with different options.
|
|
108
116
|
*
|
|
109
117
|
* @public
|
|
110
118
|
*/
|
|
111
119
|
function twoslashEntryKey(code, lang, compilerOptions) {
|
|
112
|
-
|
|
120
|
+
const options = JsoncFingerprint.canonicalizeResult(compilerOptions ?? {}, COMPILER_OPTIONS_CANONICALIZATION);
|
|
121
|
+
if (Result.isFailure(options)) return void 0;
|
|
122
|
+
const key = JsoncFingerprint.hashTextResult(`${lang ?? "ts"}\0${options.success}\0${code}`, digest);
|
|
123
|
+
return Result.isSuccess(key) ? key.success : void 0;
|
|
113
124
|
}
|
|
114
125
|
/**
|
|
115
126
|
* The cache key a whole generation is stored under. One blob per environment,
|
|
@@ -118,7 +129,7 @@ function twoslashEntryKey(code, lang, compilerOptions) {
|
|
|
118
129
|
* @public
|
|
119
130
|
*/
|
|
120
131
|
function twoslashBlobKey(envHash) {
|
|
121
|
-
return `twoslash/v${
|
|
132
|
+
return `twoslash/v${2}/${envHash}`;
|
|
122
133
|
}
|
|
123
134
|
/**
|
|
124
135
|
* Build a synchronous Twoslash cache over an in-memory map, optionally seeded
|
|
@@ -133,7 +144,8 @@ function makeTwoslashCache(initial) {
|
|
|
133
144
|
let dirty = false;
|
|
134
145
|
return {
|
|
135
146
|
read: (code, lang, options) => {
|
|
136
|
-
const
|
|
147
|
+
const key = twoslashEntryKey(code, lang, options?.compilerOptions);
|
|
148
|
+
const found = key === void 0 ? void 0 : map.get(key);
|
|
137
149
|
if (found === void 0) {
|
|
138
150
|
misses += 1;
|
|
139
151
|
return null;
|
|
@@ -142,12 +154,14 @@ function makeTwoslashCache(initial) {
|
|
|
142
154
|
return found;
|
|
143
155
|
},
|
|
144
156
|
write: (code, data, lang, options) => {
|
|
157
|
+
const key = twoslashEntryKey(code, lang, options?.compilerOptions);
|
|
158
|
+
if (key === void 0) return;
|
|
145
159
|
const value = {
|
|
146
160
|
nodes: data.nodes,
|
|
147
161
|
code: data.code,
|
|
148
162
|
...data.meta?.extension != null ? { meta: { extension: data.meta.extension } } : {}
|
|
149
163
|
};
|
|
150
|
-
map.set(
|
|
164
|
+
map.set(key, value);
|
|
151
165
|
dirty = true;
|
|
152
166
|
},
|
|
153
167
|
stats: () => ({
|
|
@@ -184,5 +198,4 @@ function decodeTwoslashCache(blob) {
|
|
|
184
198
|
}
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
//#endregion
|
|
188
201
|
export { TWOSLASH_CACHE_FORMAT, decodeTwoslashCache, encodeTwoslashCache, makeTwoslashCache, twoslashBlobKey, twoslashEntryKey, twoslashEnvHash };
|
package/TypeResolutionOptions.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CompilerOptions, CompilerOptionsFromProgrammatic, TsEnumCodec } from "@effected/tsconfig-json";
|
|
2
2
|
import { Result, Schema } from "effect";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/TypeResolutionOptions.ts
|
|
5
5
|
const fields = CompilerOptions.schema.fields;
|
|
6
6
|
/**
|
|
7
7
|
* The compiler options that may influence how a documentation example
|
|
@@ -94,5 +94,4 @@ const decodeCompilerOptions = (input) => Result.map(Schema.decodeUnknownResult(C
|
|
|
94
94
|
*/
|
|
95
95
|
const toProgrammaticCompilerOptions = (options) => TsEnumCodec.encodeCompilerOptions(options);
|
|
96
96
|
|
|
97
|
-
//#endregion
|
|
98
97
|
export { TypeResolutionCompilerOptions, decodeCompilerOptions, toProgrammaticCompilerOptions };
|
package/TypeScriptConfig.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { decodeCompilerOptions } from "./TypeResolutionOptions.js";
|
|
2
2
|
import { TsConfigParseError, parseTsConfig } from "./TsconfigParser.js";
|
|
3
|
+
import { ErrorText } from "@effected/engine";
|
|
3
4
|
import { Result } from "effect";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
// src/TypeScriptConfig.ts
|
|
6
7
|
/**
|
|
7
8
|
* Default TypeScript compiler options for Twoslash and type resolution.
|
|
8
9
|
*
|
|
@@ -120,7 +121,7 @@ function resolveTypeScriptConfigSingle(config, projectRoot) {
|
|
|
120
121
|
options = parseTsConfig(tsconfigPath, projectRoot);
|
|
121
122
|
} catch (error) {
|
|
122
123
|
if (error instanceof TsConfigParseError) throw error;
|
|
123
|
-
throw new TsConfigParseError(tsconfigPath,
|
|
124
|
+
throw new TsConfigParseError(tsconfigPath, ErrorText.describe(error), error);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
if (config.compilerOptions) options = mergeCompilerOptions(options, decodeInput(config.compilerOptions, "compilerOptions"));
|
|
@@ -168,7 +169,7 @@ async function resolveTypeScriptConfigSingleAsync(config, projectRoot) {
|
|
|
168
169
|
options = parseTsConfig(tsconfigPath, projectRoot);
|
|
169
170
|
} catch (error) {
|
|
170
171
|
if (error instanceof TsConfigParseError) throw error;
|
|
171
|
-
throw new TsConfigParseError(tsconfigPath,
|
|
172
|
+
throw new TsConfigParseError(tsconfigPath, ErrorText.describe(error), error);
|
|
172
173
|
}
|
|
173
174
|
}
|
|
174
175
|
}
|
|
@@ -222,5 +223,4 @@ async function resolveTypeScriptConfig(projectRoot, global, api) {
|
|
|
222
223
|
return options;
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
//#endregion
|
|
226
226
|
export { DEFAULT_COMPILER_OPTIONS, mergeCompilerOptions, resolveTypeScriptConfig, resolveTypeScriptConfigSingle, resolveTypeScriptConfigSingleAsync };
|
package/Vfs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/Vfs.ts
|
|
2
2
|
/**
|
|
3
3
|
* Merge VFS maps left to right into a new map; later entries win on path
|
|
4
4
|
* collisions.
|
|
@@ -43,5 +43,4 @@ const prefixVfs = (name, entries) => {
|
|
|
43
43
|
*/
|
|
44
44
|
const isTypeDefinition = (filePath) => filePath.endsWith(".d.ts") || filePath.endsWith(".d.mts") || filePath.endsWith(".d.cts");
|
|
45
45
|
|
|
46
|
-
//#endregion
|
|
47
46
|
export { isTypeDefinition, mergeVfs, prefixVfs };
|
package/VirtualPackage.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, FileSystem, Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/VirtualPackage.ts
|
|
4
4
|
/**
|
|
5
5
|
* A synthetic npm package built from locally supplied TypeScript declaration
|
|
6
6
|
* content, for inclusion in a {@link Vfs} without fetching from the CDN.
|
|
@@ -122,5 +122,4 @@ var VirtualPackage = class VirtualPackage extends Schema.Class("VirtualPackage")
|
|
|
122
122
|
}
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
//#endregion
|
|
126
125
|
export { VirtualPackage };
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { Effect, FileSystem, PlatformError, Result, Schema } from "effect";
|
|
|
3
3
|
import { VirtualTypeScriptEnvironment } from "@typescript/vfs";
|
|
4
4
|
import { TwoslashTypesCache } from "@shikijs/twoslash";
|
|
5
5
|
import { PathLike } from "node:fs";
|
|
6
|
-
//#region src/TypeResolutionOptions.d.ts
|
|
7
6
|
/**
|
|
8
7
|
* The compiler options that may influence how a documentation example
|
|
9
8
|
* type-checks.
|
|
@@ -79,8 +78,6 @@ export declare const decodeCompilerOptions: (input: unknown) => Result.Result<Ty
|
|
|
79
78
|
* @public
|
|
80
79
|
*/
|
|
81
80
|
export declare const toProgrammaticCompilerOptions: (options: TypeResolutionCompilerOptions) => ProgrammaticCompilerOptions;
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/TsconfigParser.d.ts
|
|
84
81
|
/**
|
|
85
82
|
* Error thrown when tsconfig.json parsing fails.
|
|
86
83
|
*
|
|
@@ -97,8 +94,8 @@ export declare const toProgrammaticCompilerOptions: (options: TypeResolutionComp
|
|
|
97
94
|
*/
|
|
98
95
|
export declare class TsConfigParseError extends Error {
|
|
99
96
|
readonly configPath: string;
|
|
100
|
-
readonly cause?: unknown
|
|
101
|
-
constructor(configPath: string, message: string, cause?: unknown
|
|
97
|
+
readonly cause?: unknown;
|
|
98
|
+
constructor(configPath: string, message: string, cause?: unknown);
|
|
102
99
|
}
|
|
103
100
|
/**
|
|
104
101
|
* Parse a `tsconfig.json` and extract the compiler options used for type
|
|
@@ -118,8 +115,6 @@ export declare class TsConfigParseError extends Error {
|
|
|
118
115
|
* @public
|
|
119
116
|
*/
|
|
120
117
|
export declare function parseTsConfig(configPath: string, projectRoot: string): TypeResolutionCompilerOptions;
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/Vfs.d.ts
|
|
123
118
|
/**
|
|
124
119
|
* The package's currency type: a virtual file system mapping
|
|
125
120
|
* `node_modules/`-prefixed paths to file contents.
|
|
@@ -171,8 +166,6 @@ export declare const prefixVfs: (name: string, entries: ReadonlyMap<string, stri
|
|
|
171
166
|
* @public
|
|
172
167
|
*/
|
|
173
168
|
export declare const isTypeDefinition: (filePath: string) => boolean;
|
|
174
|
-
//#endregion
|
|
175
|
-
//#region src/TsEnvironment.d.ts
|
|
176
169
|
declare const TsEnvironmentError_base: Schema.Class<TsEnvironmentError, Schema.TaggedStruct<"TsEnvironmentError", {
|
|
177
170
|
/** The underlying failure, preserved structurally. */
|
|
178
171
|
readonly cause: Schema.Defect;
|
|
@@ -252,8 +245,6 @@ export declare class TsEnvironment {
|
|
|
252
245
|
/** Build a `VirtualTypeScriptEnvironment` over a {@link Vfs}. */
|
|
253
246
|
static make(options: TsEnvironmentOptions): Effect.Effect<VirtualTypeScriptEnvironment, TsEnvironmentError>;
|
|
254
247
|
}
|
|
255
|
-
//#endregion
|
|
256
|
-
//#region src/TwoslashCache.d.ts
|
|
257
248
|
/**
|
|
258
249
|
* Persisted Twoslash result cache.
|
|
259
250
|
*
|
|
@@ -314,7 +305,7 @@ export declare class TsEnvironment {
|
|
|
314
305
|
*
|
|
315
306
|
* @public
|
|
316
307
|
*/
|
|
317
|
-
export declare const TWOSLASH_CACHE_FORMAT =
|
|
308
|
+
export declare const TWOSLASH_CACHE_FORMAT = 2;
|
|
318
309
|
/**
|
|
319
310
|
* The subset of a Twoslash run that Shiki consumes, and all this cache stores.
|
|
320
311
|
*
|
|
@@ -376,11 +367,17 @@ export declare function twoslashEnvHash(vfs: ReadonlyMap<string, string>, toolch
|
|
|
376
367
|
*
|
|
377
368
|
* The configuration matters because two APIs on one site may be documented
|
|
378
369
|
* under different `tsconfig`s — the same source checked under different options
|
|
379
|
-
* can produce different types, so it must not share a cache entry.
|
|
370
|
+
* can produce different types, so it must not share a cache entry. The options
|
|
371
|
+
* are folded in through their RFC 8785 canonical form, so key order does not
|
|
372
|
+
* matter.
|
|
373
|
+
*
|
|
374
|
+
* Returns `undefined` when the options cannot be canonicalized (a function or a
|
|
375
|
+
* non-plain object among them): such a block is not cached, rather than keyed
|
|
376
|
+
* on a spelling that could collide with different options.
|
|
380
377
|
*
|
|
381
378
|
* @public
|
|
382
379
|
*/
|
|
383
|
-
export declare function twoslashEntryKey(code: string, lang: string | undefined, compilerOptions?: unknown): string;
|
|
380
|
+
export declare function twoslashEntryKey(code: string, lang: string | undefined, compilerOptions?: unknown): string | undefined;
|
|
384
381
|
/**
|
|
385
382
|
* The cache key a whole generation is stored under. One blob per environment,
|
|
386
383
|
* so a changed environment reads as a miss rather than serving stale results.
|
|
@@ -409,8 +406,6 @@ export declare function encodeTwoslashCache(entries: ReadonlyMap<string, Twoslas
|
|
|
409
406
|
* @public
|
|
410
407
|
*/
|
|
411
408
|
export declare function decodeTwoslashCache(blob: Uint8Array): Map<string, TwoslashCacheValue>;
|
|
412
|
-
//#endregion
|
|
413
|
-
//#region src/TypeScriptConfig.d.ts
|
|
414
409
|
/**
|
|
415
410
|
* How a caller points at TypeScript configuration: a `tsconfig.json`, inline
|
|
416
411
|
* compiler options, or both.
|
|
@@ -584,8 +579,6 @@ export declare function resolveTypeScriptConfigSingleAsync(config: TypeScriptCon
|
|
|
584
579
|
* @public
|
|
585
580
|
*/
|
|
586
581
|
export declare function resolveTypeScriptConfig(projectRoot: string, global?: TypeScriptConfig, api?: TypeScriptConfig): Promise<TypeResolutionCompilerOptions>;
|
|
587
|
-
//#endregion
|
|
588
|
-
//#region src/VirtualPackage.d.ts
|
|
589
582
|
declare const VirtualPackage_base: Schema.Class<VirtualPackage, Schema.Struct<{
|
|
590
583
|
/** The package name (e.g. `"@my-org/api-types"`). */
|
|
591
584
|
readonly name: Schema.String;
|
|
@@ -658,6 +651,5 @@ export declare class VirtualPackage extends VirtualPackage_base {
|
|
|
658
651
|
toVfs(): Vfs;
|
|
659
652
|
private toPackageJson;
|
|
660
653
|
}
|
|
661
|
-
//#endregion
|
|
662
654
|
export type { CompilerOptionsInput, TsEnvironmentOptions, TwoslashCacheStats, TwoslashCacheValue, TwoslashResultCache, TypeScriptConfig, Vfs };
|
|
663
655
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsdoctor/vfs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Virtual TypeScript projects for documentation tooling: the Vfs currency type, declaration-backed virtual packages, @typescript/vfs environments, and the compiler-option resolution that configures them.",
|
|
6
6
|
"keywords": [
|
|
@@ -36,11 +36,15 @@
|
|
|
36
36
|
},
|
|
37
37
|
"./package.json": "./package.json"
|
|
38
38
|
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@effected/engine": "^0.10.0",
|
|
41
|
+
"@effected/jsonc": "^0.21.0"
|
|
42
|
+
},
|
|
39
43
|
"peerDependencies": {
|
|
40
|
-
"@effected/tsconfig-json": "^0.
|
|
44
|
+
"@effected/tsconfig-json": "^0.18.0",
|
|
41
45
|
"@shikijs/twoslash": "^4.4.3",
|
|
42
46
|
"@typescript/vfs": "^1.6.5",
|
|
43
|
-
"effect": "^4.0.
|
|
47
|
+
"effect": "^4.0.7",
|
|
44
48
|
"typescript": "^6.0.3"
|
|
45
49
|
},
|
|
46
50
|
"peerDependenciesMeta": {
|