rspress-plugin-api-extractor 0.13.2 → 0.14.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/build-program.js +1 -1
- package/build-stages.js +1 -2
- package/index.d.ts +5 -28
- package/layers/config-resolution.js +3 -4
- package/layers/type-environment.js +5 -3
- package/markdown/helpers.js +1 -2
- package/markdown/page-generators/class-page.js +1 -2
- package/markdown/page-generators/function-page.js +1 -2
- package/markdown/page-generators/index-pages.js +1 -1
- package/markdown/page-generators/interface-page.js +1 -2
- package/markdown/page-generators/namespace-page.js +1 -2
- package/markdown/page-generators/type-alias-page.js +1 -2
- package/markdown/page-generators/variable-page.js +1 -2
- package/observability/sinks/console-sink.js +1 -2
- package/package.json +9 -8
- package/plugin.js +1 -9
- package/schemas/config.js +2 -11
- package/schemas/observability.js +8 -21
- package/schemas/performance.js +1 -6
- package/services/TwoslashCacheService.js +17 -13
- package/services/TypeRegistryService.js +4 -4
- package/shiki-transformer.js +12 -51
- package/twoslash-transformer.js +2 -47
- package/api-extracted-package.js +0 -471
- package/frontmatter.js +0 -176
- package/tsconfig-parser.js +0 -115
- package/type-reference-extractor.js +0 -199
- package/typescript-config.js +0 -170
package/build-program.js
CHANGED
|
@@ -59,7 +59,7 @@ function generateApiDocs(apiConfig, fileContextMap) {
|
|
|
59
59
|
})));
|
|
60
60
|
setProseLinker(crossLinkData.routes);
|
|
61
61
|
const apiScope = baseRoute.replace(/^\//, "").split("/")[0] || packageName;
|
|
62
|
-
const shikiCrossLinker = ShikiCrossLinker.fromRoutes(crossLinkData.routes,
|
|
62
|
+
const shikiCrossLinker = ShikiCrossLinker.fromRoutes(crossLinkData.routes, apiScope);
|
|
63
63
|
addTypeRoutes(crossLinkData.routes);
|
|
64
64
|
const vfsConfig = {
|
|
65
65
|
highlighter,
|
package/build-stages.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { parseFrontmatter, stringifyFrontmatter } from "./frontmatter.js";
|
|
2
1
|
import { BuildMetrics } from "./layers/build-metrics.js";
|
|
3
2
|
import { PluginEvent } from "./observability/events.js";
|
|
4
3
|
import { emit } from "./observability/EventBus.js";
|
|
@@ -18,7 +17,7 @@ import { Effect, FileSystem, Metric, Option, Stream } from "effect";
|
|
|
18
17
|
import { deriveScriptBody, headTags } from "@tsdoctor/seo";
|
|
19
18
|
import { SnapshotService, hashContent, hashFrontmatter } from "@tsdoctor/snapshot";
|
|
20
19
|
import { ApiItemKind } from "@microsoft/api-extractor-model";
|
|
21
|
-
import { ApiItems, EntryPoints, Routes, SyntheticBases } from "@tsdoctor/model";
|
|
20
|
+
import { ApiItems, EntryPoints, Routes, SyntheticBases, parseFrontmatter, stringifyFrontmatter } from "@tsdoctor/model";
|
|
22
21
|
|
|
23
22
|
//#region src/build-stages.ts
|
|
24
23
|
/**
|
package/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenGraphImageConfig, OpenGraphImageMetadata, OpenGraphMetadata } from "@tsdoctor/seo";
|
|
2
2
|
import { ApiItemKind, ApiModel } from "@microsoft/api-extractor-model";
|
|
3
3
|
import { Schema } from "effect";
|
|
4
|
-
import "
|
|
4
|
+
import "@tsdoctor/vfs";
|
|
5
5
|
import { RspressPlugin } from "@rspress/shared";
|
|
6
6
|
import "@rspress/shared/logger";
|
|
7
7
|
import "@rspress/shared/node-utils";
|
|
@@ -139,10 +139,6 @@ declare const VersionConfig: Schema.Struct<{
|
|
|
139
139
|
readonly copyButtonText: Schema.withDecodingDefault<Schema.String, never>;
|
|
140
140
|
readonly viewOptions: Schema.withDecodingDefault<Schema.mutable<Schema.$Array<Schema.Literals<readonly ["markdownLink", "chatgpt", "claude"]>>>, never>;
|
|
141
141
|
}>>;
|
|
142
|
-
/** Path to a `tsconfig.json` for this version. */
|
|
143
|
-
readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
|
|
144
|
-
/** TypeScript compiler options for Twoslash. */
|
|
145
|
-
readonly compilerOptions: Schema.optional<Schema.Unknown>;
|
|
146
142
|
}>;
|
|
147
143
|
/** @public */
|
|
148
144
|
type VersionConfig = typeof VersionConfig.Encoded;
|
|
@@ -229,10 +225,6 @@ declare const SingleApiConfig: Schema.Struct<{
|
|
|
229
225
|
readonly copyButtonText: Schema.withDecodingDefault<Schema.String, never>;
|
|
230
226
|
readonly viewOptions: Schema.withDecodingDefault<Schema.mutable<Schema.$Array<Schema.Literals<readonly ["markdownLink", "chatgpt", "claude"]>>>, never>;
|
|
231
227
|
}>>;
|
|
232
|
-
/** Path to a `tsconfig.json` for this version. */
|
|
233
|
-
readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
|
|
234
|
-
/** TypeScript compiler options for Twoslash. */
|
|
235
|
-
readonly compilerOptions: Schema.optional<Schema.Unknown>;
|
|
236
228
|
}>]>>>;
|
|
237
229
|
/** Shiki syntax-highlighting theme. */
|
|
238
230
|
readonly theme: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
|
|
@@ -499,10 +491,6 @@ declare const PluginOptions: Schema.Struct<{
|
|
|
499
491
|
readonly copyButtonText: Schema.withDecodingDefault<Schema.String, never>;
|
|
500
492
|
readonly viewOptions: Schema.withDecodingDefault<Schema.mutable<Schema.$Array<Schema.Literals<readonly ["markdownLink", "chatgpt", "claude"]>>>, never>;
|
|
501
493
|
}>>;
|
|
502
|
-
/** Path to a `tsconfig.json` for this version. */
|
|
503
|
-
readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
|
|
504
|
-
/** TypeScript compiler options for Twoslash. */
|
|
505
|
-
readonly compilerOptions: Schema.optional<Schema.Unknown>;
|
|
506
494
|
}>]>>>;
|
|
507
495
|
/** Shiki syntax-highlighting theme. */
|
|
508
496
|
readonly theme: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
|
|
@@ -712,21 +700,6 @@ declare const PluginOptions: Schema.Struct<{
|
|
|
712
700
|
readonly copyButtonText: Schema.withDecodingDefault<Schema.String, never>;
|
|
713
701
|
readonly viewOptions: Schema.withDecodingDefault<Schema.mutable<Schema.$Array<Schema.Literals<readonly ["markdownLink", "chatgpt", "claude"]>>>, never>;
|
|
714
702
|
}>]>>;
|
|
715
|
-
/** Verbosity level for plugin build output. @deprecated Use `observability.logLevel`. */
|
|
716
|
-
readonly logLevel: Schema.optional<Schema.Literals<readonly ["none", "info", "verbose", "debug", "warn", "error"]>>;
|
|
717
|
-
/** Performance tuning options. @deprecated Use `observability.thresholds`. */
|
|
718
|
-
readonly performance: Schema.optional<Schema.Struct<{
|
|
719
|
-
readonly thresholds: Schema.optional<Schema.Struct<{
|
|
720
|
-
readonly slowCodeBlock: Schema.withDecodingDefault<Schema.Number, never>;
|
|
721
|
-
readonly slowPageGeneration: Schema.withDecodingDefault<Schema.Number, never>;
|
|
722
|
-
readonly slowApiLoad: Schema.withDecodingDefault<Schema.Number, never>;
|
|
723
|
-
readonly slowFileOperation: Schema.withDecodingDefault<Schema.Number, never>;
|
|
724
|
-
readonly slowHttpRequest: Schema.withDecodingDefault<Schema.Number, never>;
|
|
725
|
-
readonly slowDbOperation: Schema.withDecodingDefault<Schema.Number, never>;
|
|
726
|
-
}>>;
|
|
727
|
-
readonly showInsights: Schema.withDecodingDefault<Schema.Boolean, never>;
|
|
728
|
-
readonly trackDetailedMetrics: Schema.withDecodingDefault<Schema.Boolean, never>;
|
|
729
|
-
}>>;
|
|
730
703
|
/** Unified observability configuration (logLevel, trace artifact, thresholds). */
|
|
731
704
|
readonly observability: Schema.optional<Schema.Struct<{
|
|
732
705
|
readonly logLevel: Schema.optional<Schema.Literals<readonly ["none", "error", "warn", "info", "debug", "trace", "verbose"]>>;
|
|
@@ -821,6 +794,10 @@ declare function fromDir(dir: string, overrides?: FromDirOptions): MultiApiConfi
|
|
|
821
794
|
declare function fromParentDir(parentDir: string, options?: FromDirOptions): MultiApiConfig[];
|
|
822
795
|
//#endregion
|
|
823
796
|
//#region src/internal-types.d.ts
|
|
797
|
+
/**
|
|
798
|
+
* Compiler options relevant to type resolution.
|
|
799
|
+
* Subset of TypeScript's CompilerOptions used by the type registry and Twoslash.
|
|
800
|
+
*/
|
|
824
801
|
/**
|
|
825
802
|
* Result returned by a model loader function.
|
|
826
803
|
*
|
|
@@ -2,12 +2,10 @@ import { BuildId } from "../BuildEnv.js";
|
|
|
2
2
|
import { BuildMetrics } from "./build-metrics.js";
|
|
3
3
|
import { PluginEvent } from "../observability/events.js";
|
|
4
4
|
import { emit, wantsLevel } from "../observability/EventBus.js";
|
|
5
|
-
import { TypeReferenceExtractor } from "../type-reference-extractor.js";
|
|
6
5
|
import { withPhase } from "../observability/spans.js";
|
|
7
6
|
import { normalizeThemeConfig } from "../markdown/shiki-utils.js";
|
|
8
7
|
import { apiScopeOf, deriveOutputPaths, normalizeBaseRoute, unscopedName } from "../path-derivation.js";
|
|
9
8
|
import { classifyApiConfig, extractAutoDetectedPackages, isVersionConfig, mergeLlmsPluginConfig, validateExternalPackages } from "../config-utils.js";
|
|
10
|
-
import { ApiExtractedPackage } from "../api-extracted-package.js";
|
|
11
9
|
import { CategoryResolver } from "../category-resolver.js";
|
|
12
10
|
import { ConfigValidationError } from "../errors.js";
|
|
13
11
|
import { loadApiModel, loadPackageJson, loadVersionModel } from "../model-loader.js";
|
|
@@ -21,6 +19,7 @@ import path from "node:path";
|
|
|
21
19
|
import { Effect, Metric } from "effect";
|
|
22
20
|
import { deriveSiteUrl } from "@tsdoctor/seo";
|
|
23
21
|
import { hashContent } from "@tsdoctor/snapshot";
|
|
22
|
+
import { ApiExtractedPackage, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
24
23
|
import { PackageManifest } from "@effected/package-json";
|
|
25
24
|
|
|
26
25
|
//#region src/layers/config-resolution.ts
|
|
@@ -241,7 +240,7 @@ const makeConfigService = Effect.gen(function* () {
|
|
|
241
240
|
});
|
|
242
241
|
const externalPackages = api.externalPackages || extractAutoDetectedPackages(packageJson, api.autoDetectDependencies);
|
|
243
242
|
if (externalPackages && externalPackages.length > 0) yield* Metric.update(BuildMetrics.externalPackagesTotal, externalPackages.length);
|
|
244
|
-
const vfs = ApiExtractedPackage.fromPackage(apiPackage, api.packageName).
|
|
243
|
+
const vfs = ApiExtractedPackage.fromPackage(apiPackage, api.packageName).toVfs();
|
|
245
244
|
const vfsPayloads = prependImportsToVfs(vfs, apiPackage, api.packageName, wantTrace);
|
|
246
245
|
const resolvedOgImage = api.ogImage ?? options.ogImage;
|
|
247
246
|
const resolvedTheme = normalizeThemeConfig(api.theme);
|
|
@@ -321,7 +320,7 @@ const makeConfigService = Effect.gen(function* () {
|
|
|
321
320
|
const autoDetectOptions = versionAutoDetectDependencies || api.autoDetectDependencies;
|
|
322
321
|
const externalPackages = versionExternalPackages || api.externalPackages || extractAutoDetectedPackages(packageJson, autoDetectOptions);
|
|
323
322
|
if (externalPackages && externalPackages.length > 0) yield* Metric.update(BuildMetrics.externalPackagesTotal, externalPackages.length);
|
|
324
|
-
const vfs = ApiExtractedPackage.fromPackage(apiPackage, api.packageName).
|
|
323
|
+
const vfs = ApiExtractedPackage.fromPackage(apiPackage, api.packageName).toVfs();
|
|
325
324
|
const vfsPayloads = prependImportsToVfs(vfs, apiPackage, api.packageName, wantTrace);
|
|
326
325
|
const resolvedOgImage = versionOgImage ?? api.ogImage ?? options.ogImage;
|
|
327
326
|
const resolvedTheme = normalizeThemeConfig(api.theme);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { PluginEvent } from "../observability/events.js";
|
|
2
2
|
import { emit } from "../observability/EventBus.js";
|
|
3
|
-
import { resolveTypeScriptConfig } from "../typescript-config.js";
|
|
4
3
|
import { TwoslashEnvironments } from "../services/TwoslashEnvironments.js";
|
|
5
4
|
import { ConfigValidationError } from "../errors.js";
|
|
6
5
|
import { twoslashEnvHash } from "../twoslash-cache.js";
|
|
7
6
|
import { TwoslashCacheService } from "../services/TwoslashCacheService.js";
|
|
8
7
|
import { Effect } from "effect";
|
|
8
|
+
import { resolveTypeScriptConfig } from "@tsdoctor/vfs";
|
|
9
9
|
import ts from "typescript";
|
|
10
10
|
|
|
11
11
|
//#region src/layers/type-environment.ts
|
|
@@ -64,12 +64,14 @@ const resolveTsConfigTyped = (projectRoot, config) => Effect.tryPromise({
|
|
|
64
64
|
*/
|
|
65
65
|
const registerTypeEnvironments = (input) => Effect.gen(function* () {
|
|
66
66
|
const twoslashEnv = twoslashEnvHash(input.combinedVfs, `typescript@${ts.version}`);
|
|
67
|
-
const
|
|
67
|
+
const cacheSvc = yield* TwoslashCacheService;
|
|
68
|
+
const twoslashCache = yield* cacheSvc.open(twoslashEnv);
|
|
68
69
|
yield* emit(PluginEvent.TwoslashCacheLoaded({
|
|
69
70
|
ctx: {},
|
|
70
71
|
level: "debug",
|
|
71
72
|
envHash: twoslashEnv,
|
|
72
|
-
entries: twoslashCache.entries().size
|
|
73
|
+
entries: twoslashCache.entries().size,
|
|
74
|
+
degraded: cacheSvc.degraded
|
|
73
75
|
}));
|
|
74
76
|
const twoslashStartMs = performance.now();
|
|
75
77
|
const environments = yield* TwoslashEnvironments;
|
package/markdown/helpers.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { emitFrontmatterBlock } from "../frontmatter.js";
|
|
2
1
|
import { classifyCutDirective, isTwoslashDirective } from "../twoslash-patterns.js";
|
|
3
2
|
import { formatCode } from "../prettier-formatter.js";
|
|
4
|
-
import { TypeReferenceExtractor } from "
|
|
3
|
+
import { TypeReferenceExtractor, emitFrontmatterBlock } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/helpers.ts
|
|
7
6
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
|
-
import { ApiItems, Routes, Signature, Tsdoc } from "@tsdoctor/model";
|
|
3
|
+
import { ApiItems, Routes, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/page-generators/class-page.ts
|
|
7
6
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
|
-
import { ApiItems, Signature, Tsdoc } from "@tsdoctor/model";
|
|
3
|
+
import { ApiItems, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/page-generators/function-page.ts
|
|
7
6
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
|
-
import { ApiItems, Routes, Signature, Tsdoc } from "@tsdoctor/model";
|
|
3
|
+
import { ApiItems, Routes, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/page-generators/interface-page.ts
|
|
7
6
|
/**
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
3
|
import { ApiItemKind } from "@microsoft/api-extractor-model";
|
|
5
|
-
import { ApiItems, Signature, Tsdoc } from "@tsdoctor/model";
|
|
4
|
+
import { ApiItems, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
6
5
|
|
|
7
6
|
//#region src/markdown/page-generators/namespace-page.ts
|
|
8
7
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
|
-
import { ApiItems, Signature, Tsdoc } from "@tsdoctor/model";
|
|
3
|
+
import { ApiItems, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/page-generators/type-alias-page.ts
|
|
7
6
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { TypeReferenceExtractor } from "../../type-reference-extractor.js";
|
|
2
1
|
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
3
2
|
import { linkProse } from "../prose-linker.js";
|
|
4
|
-
import { ApiItems, Signature, Tsdoc } from "@tsdoctor/model";
|
|
3
|
+
import { ApiItems, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
5
4
|
|
|
6
5
|
//#region src/markdown/page-generators/variable-page.ts
|
|
7
6
|
/**
|
|
@@ -22,12 +22,11 @@ function render(event) {
|
|
|
22
22
|
case "SlowOperation": return `slow ${event.operation}: ${event.durationMs}ms (>${event.threshold}ms)`;
|
|
23
23
|
case "ConfigCascadeWarning": return event.ignored.length > 2 ? `${event.field}: using '${event.chosen}', ignoring ${event.ignored.length} alternatives (first configured value wins)` : `${event.field}: using '${event.chosen}', ignoring ${event.ignored.join(", ")}`;
|
|
24
24
|
case "ConfigValidationWarning": return `${event.field}: rejected '${event.value}'${event.reason ? ` — ${event.reason}` : ""}`;
|
|
25
|
-
case "DeprecatedConfigUsed": return `option '${event.key}' is deprecated; use ${event.replacement}`;
|
|
26
25
|
case "ModelLoaded": return `loaded model: ${event.itemCount} items, ${event.entryPoints} entry point(s) (${event.durationMs}ms)`;
|
|
27
26
|
case "ConfigResolved": return `resolved ${event.baseRoute}: ${event.categoryCount} categories, ${event.externalCount} external`;
|
|
28
27
|
case "TwoslashDiagnostic": return `Twoslash TS${event.code} in ${event.file}:${event.line}:${event.col}: ${event.message}`;
|
|
29
28
|
case "TwoslashCheckFailed": return `Twoslash check failed (TS${event.code}) in ${event.file}; ${event.fsMapKeys.length} VFS files`;
|
|
30
|
-
case "TwoslashCacheLoaded": return event.entries > 0 ? `Twoslash cache: restored ${event.entries} cached result(s)` : "Twoslash cache: cold (no cached results for this type environment)";
|
|
29
|
+
case "TwoslashCacheLoaded": return event.degraded ? "Twoslash cache: DEGRADED (unusable cache directory) — every block will be type-checked, every build" : event.entries > 0 ? `Twoslash cache: restored ${event.entries} cached result(s)` : "Twoslash cache: cold (no cached results for this type environment)";
|
|
31
30
|
case "TwoslashCacheSaved": {
|
|
32
31
|
const total = event.hits + event.misses;
|
|
33
32
|
const pct = total > 0 ? Math.round(event.hits / total * 100) : 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rspress-plugin-api-extractor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "RSPress plugin for generating API documentation from TypeScript API Extractor models",
|
|
6
6
|
"keywords": [
|
|
@@ -40,23 +40,24 @@
|
|
|
40
40
|
"@effect/platform-node": "4.0.0-rc.109",
|
|
41
41
|
"@effected/github": "^0.8.0",
|
|
42
42
|
"@effected/glob": "^0.4.0",
|
|
43
|
-
"@effected/jsonc": "^0.8.
|
|
43
|
+
"@effected/jsonc": "^0.8.1",
|
|
44
44
|
"@effected/markdown": "^0.7.0",
|
|
45
45
|
"@effected/npm": "^0.12.1",
|
|
46
46
|
"@effected/package-json": "^0.13.0",
|
|
47
47
|
"@effected/semver": "^0.5.0",
|
|
48
|
-
"@effected/store": "^0.
|
|
49
|
-
"@effected/tsconfig-json": "^0.
|
|
48
|
+
"@effected/store": "^0.6.0",
|
|
49
|
+
"@effected/tsconfig-json": "^0.7.0",
|
|
50
50
|
"@effected/walker": "^0.5.0",
|
|
51
51
|
"@effected/xdg": "^0.3.0",
|
|
52
52
|
"@effected/yaml": "^0.12.0",
|
|
53
53
|
"@microsoft/api-extractor-model": "^7.33.11",
|
|
54
54
|
"@shikijs/twoslash": "^4.4.3",
|
|
55
|
-
"@tsdoctor/bundle": "0.2.
|
|
56
|
-
"@tsdoctor/model": "0.
|
|
57
|
-
"@tsdoctor/registry": "0.
|
|
55
|
+
"@tsdoctor/bundle": "0.2.2",
|
|
56
|
+
"@tsdoctor/model": "0.5.0",
|
|
57
|
+
"@tsdoctor/registry": "0.3.0",
|
|
58
58
|
"@tsdoctor/seo": "0.1.1",
|
|
59
|
-
"@tsdoctor/snapshot": "0.2.
|
|
59
|
+
"@tsdoctor/snapshot": "0.2.3",
|
|
60
|
+
"@tsdoctor/vfs": "0.1.0",
|
|
60
61
|
"@typescript/vfs": "^1.6.4",
|
|
61
62
|
"clsx": "^2.1.1",
|
|
62
63
|
"effect": "4.0.0-rc.109",
|
package/plugin.js
CHANGED
|
@@ -54,10 +54,8 @@ function ApiExtractorPluginImpl(rawOptions) {
|
|
|
54
54
|
const isInert = classifyApiConfig(options) === "disabled";
|
|
55
55
|
const envLogLevel = process.env.LOG_LEVEL?.toLowerCase();
|
|
56
56
|
const buildId = `${process.pid}-${performance.now().toString(36)}`;
|
|
57
|
-
const { resolved: obs
|
|
57
|
+
const { resolved: obs } = resolveObservability({
|
|
58
58
|
...options.observability ? { observability: options.observability } : {},
|
|
59
|
-
...options.logLevel ? { logLevel: options.logLevel } : {},
|
|
60
|
-
...options.performance ? { performance: { ...options.performance.thresholds !== void 0 ? { thresholds: options.performance.thresholds } : {} } } : {},
|
|
61
59
|
...envLogLevel ? { envLogLevel } : {},
|
|
62
60
|
cwd: process.cwd(),
|
|
63
61
|
buildId
|
|
@@ -184,12 +182,6 @@ function ApiExtractorPluginImpl(rawOptions) {
|
|
|
184
182
|
clearTypeRoutes();
|
|
185
183
|
fileContextMap.clear();
|
|
186
184
|
issuesSink.reset();
|
|
187
|
-
for (const dep of deprecations) emitSync(PluginEvent.DeprecatedConfigUsed({
|
|
188
|
-
ctx: { buildId },
|
|
189
|
-
level: "warn",
|
|
190
|
-
key: dep.key,
|
|
191
|
-
replacement: dep.replacement
|
|
192
|
-
}));
|
|
193
185
|
if (!isInert) try {
|
|
194
186
|
const rspressConfigSubset = {
|
|
195
187
|
...rspressMultiVersion != null ? { multiVersion: rspressMultiVersion } : {},
|
package/schemas/config.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PerformanceConfig } from "./performance.js";
|
|
2
1
|
import { ObservabilityConfig } from "./observability.js";
|
|
3
2
|
import { Effect, Schema } from "effect";
|
|
4
3
|
import { OpenGraphImageConfig } from "@tsdoctor/seo";
|
|
@@ -190,11 +189,7 @@ const VersionConfig = Schema.Struct({
|
|
|
190
189
|
/** Open Graph image configuration for this version. */
|
|
191
190
|
ogImage: Schema.optional(OpenGraphImageConfig),
|
|
192
191
|
/** LLMs integration options for this version. */
|
|
193
|
-
llmsPlugin: Schema.optional(LlmsPlugin)
|
|
194
|
-
/** Path to a `tsconfig.json` for this version. */
|
|
195
|
-
tsconfig: Schema.optional(ModelInput),
|
|
196
|
-
/** TypeScript compiler options for Twoslash. */
|
|
197
|
-
compilerOptions: Schema.optional(Schema.Unknown)
|
|
192
|
+
llmsPlugin: Schema.optional(LlmsPlugin)
|
|
198
193
|
});
|
|
199
194
|
/** Union for the versions record value: can be a path/function OR a full VersionConfig */
|
|
200
195
|
const VersionValue = Schema.Union([ModelInput, VersionConfig]);
|
|
@@ -312,13 +307,9 @@ const PluginOptions = Schema.Struct({
|
|
|
312
307
|
errors: Schema.optional(ErrorConfig),
|
|
313
308
|
/** LLMs integration options, or `false` to disable. */
|
|
314
309
|
llmsPlugin: Schema.optional(Schema.Union([Schema.Boolean, LlmsPlugin])),
|
|
315
|
-
/** Verbosity level for plugin build output. @deprecated Use `observability.logLevel`. */
|
|
316
|
-
logLevel: Schema.optional(LogLevel),
|
|
317
|
-
/** Performance tuning options. @deprecated Use `observability.thresholds`. */
|
|
318
|
-
performance: Schema.optional(PerformanceConfig),
|
|
319
310
|
/** Unified observability configuration (logLevel, trace artifact, thresholds). */
|
|
320
311
|
observability: Schema.optional(ObservabilityConfig)
|
|
321
312
|
});
|
|
322
313
|
|
|
323
314
|
//#endregion
|
|
324
|
-
export { AutoDetectDependencies, CategoryConfig, DEFAULT_CATEGORIES, ErrorConfig, ExternalPackageSpec, LlmsPlugin,
|
|
315
|
+
export { AutoDetectDependencies, CategoryConfig, DEFAULT_CATEGORIES, ErrorConfig, ExternalPackageSpec, LlmsPlugin, ModelInput, MultiApiConfig, PluginOptions, SingleApiConfig, SourceConfig, ThemeConfig, VersionConfig };
|
package/schemas/observability.js
CHANGED
|
@@ -31,21 +31,11 @@ function normalizeLevel(value) {
|
|
|
31
31
|
return value;
|
|
32
32
|
}
|
|
33
33
|
function resolveObservability(input) {
|
|
34
|
-
const
|
|
35
|
-
if (input.logLevel !== void 0) deprecations.push({
|
|
36
|
-
key: "logLevel",
|
|
37
|
-
replacement: "observability.logLevel"
|
|
38
|
-
});
|
|
39
|
-
if (input.performance !== void 0) deprecations.push({
|
|
40
|
-
key: "performance",
|
|
41
|
-
replacement: "observability.thresholds"
|
|
42
|
-
});
|
|
43
|
-
const level = normalizeLevel(input.envLogLevel) ?? normalizeLevel(input.observability?.logLevel) ?? normalizeLevel(input.logLevel) ?? "info";
|
|
34
|
+
const level = normalizeLevel(input.envLogLevel) ?? normalizeLevel(input.observability?.logLevel) ?? "info";
|
|
44
35
|
const traceOpt = input.observability?.trace;
|
|
45
36
|
const tracePath = typeof traceOpt === "string" ? traceOpt : traceOpt === true ? `${input.cwd}/.api-docs/build/trace-${input.buildId}.jsonl` : null;
|
|
46
37
|
const merged = {
|
|
47
38
|
...DEFAULT_THRESHOLDS,
|
|
48
|
-
...input.performance?.thresholds ?? {},
|
|
49
39
|
...input.observability?.thresholds ?? {}
|
|
50
40
|
};
|
|
51
41
|
const thresholds = {
|
|
@@ -59,16 +49,13 @@ function resolveObservability(input) {
|
|
|
59
49
|
const pi = input.observability?.progressInterval;
|
|
60
50
|
const seconds = pi === false ? null : typeof pi === "number" ? pi : 10;
|
|
61
51
|
const progressIntervalMs = seconds !== null && Number.isFinite(seconds) && seconds > 0 ? seconds * 1e3 : null;
|
|
62
|
-
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
},
|
|
70
|
-
deprecations
|
|
71
|
-
};
|
|
52
|
+
return { resolved: {
|
|
53
|
+
logLevel: level,
|
|
54
|
+
json: level === "debug",
|
|
55
|
+
tracePath,
|
|
56
|
+
progressIntervalMs,
|
|
57
|
+
thresholds
|
|
58
|
+
} };
|
|
72
59
|
}
|
|
73
60
|
|
|
74
61
|
//#endregion
|
package/schemas/performance.js
CHANGED
|
@@ -9,11 +9,6 @@ const PerformanceThresholds = Schema.Struct({
|
|
|
9
9
|
slowHttpRequest: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(2e3))),
|
|
10
10
|
slowDbOperation: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(100)))
|
|
11
11
|
});
|
|
12
|
-
const PerformanceConfig = Schema.Struct({
|
|
13
|
-
thresholds: Schema.optional(PerformanceThresholds),
|
|
14
|
-
showInsights: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
|
|
15
|
-
trackDetailedMetrics: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false)))
|
|
16
|
-
});
|
|
17
12
|
|
|
18
13
|
//#endregion
|
|
19
|
-
export {
|
|
14
|
+
export { PerformanceThresholds };
|
|
@@ -20,23 +20,29 @@ var TwoslashCacheService = class TwoslashCacheService extends Context.Service()(
|
|
|
20
20
|
* @remarks
|
|
21
21
|
* Failure is absorbed at TWO levels, and both are load-bearing. Inside the
|
|
22
22
|
* service, a failed read or write degrades that one operation. Around the
|
|
23
|
-
* layer, a failed CONSTRUCTION — no HOME for XDG, an unwritable cache
|
|
24
|
-
* directory, a corrupt database — degrades to
|
|
23
|
+
* cache layer, a failed CONSTRUCTION — no HOME for XDG, an unwritable cache
|
|
24
|
+
* directory, a corrupt database — degrades to a cache that always misses,
|
|
25
|
+
* via `Cache.degrading` (see {@link CacheLive}).
|
|
25
26
|
*
|
|
26
|
-
* The second is why
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* The second is why anything wraps this at all. While the sqlite layer was
|
|
28
|
+
* provided inside each method, a construction failure surfaced as that
|
|
29
|
+
* method's failure and the in-method handler swallowed it. Hoisting
|
|
29
30
|
* acquisition to layer construction moved the failure to `ManagedRuntime`
|
|
30
31
|
* build time, where it would abort the entire build — breaking the contract
|
|
31
32
|
* this service documents, that an unreachable cache must never fail a build
|
|
32
|
-
* that would otherwise succeed.
|
|
33
|
-
*
|
|
33
|
+
* that would otherwise succeed.
|
|
34
|
+
*
|
|
35
|
+
* There is no separate degraded implementation of this service any more.
|
|
36
|
+
* Degrading one level down, at the `Cache`, means the ordinary
|
|
37
|
+
* implementation running over an always-missing cache IS the degraded
|
|
38
|
+
* behaviour, so a second implementation would only be a way for the two to
|
|
39
|
+
* disagree.
|
|
34
40
|
*
|
|
35
41
|
* `Layer.suspend` because the composition below is declared after this class:
|
|
36
42
|
* a static initializer runs while the module body is still evaluating, so
|
|
37
43
|
* naming those consts directly throws at import time with a clean typecheck.
|
|
38
44
|
*/
|
|
39
|
-
static layer = Layer.suspend(() => CacheBackedLive
|
|
45
|
+
static layer = Layer.suspend(() => CacheBackedLive);
|
|
40
46
|
/**
|
|
41
47
|
* An always-cold in-memory double.
|
|
42
48
|
*
|
|
@@ -50,6 +56,7 @@ var TwoslashCacheService = class TwoslashCacheService extends Context.Service()(
|
|
|
50
56
|
* the render path's SHAPE rather than merely dropping its persistence.
|
|
51
57
|
*/
|
|
52
58
|
static makeTest = (overrides = {}) => ({
|
|
59
|
+
degraded: overrides.degraded ?? false,
|
|
53
60
|
load: overrides.load ?? (() => Effect.succeed(/* @__PURE__ */ new Map())),
|
|
54
61
|
save: overrides.save ?? (() => Effect.void),
|
|
55
62
|
open: overrides.open ?? (() => Effect.succeed(makeTwoslashCache())),
|
|
@@ -117,6 +124,7 @@ function withGeneration(base) {
|
|
|
117
124
|
const CacheBackedLive = Layer.effect(TwoslashCacheService, Effect.gen(function* () {
|
|
118
125
|
const cache = yield* Cache;
|
|
119
126
|
return withGeneration({
|
|
127
|
+
degraded: cache.degraded,
|
|
120
128
|
load: (envHash) => cache.get(twoslashBlobKey(envHash)).pipe(Effect.map((entry) => Option.isSome(entry) ? decodeTwoslashCache(entry.value.value) : /* @__PURE__ */ new Map()), Effect.catch(() => Effect.succeed(/* @__PURE__ */ new Map()))),
|
|
121
129
|
save: (envHash, entries) => cache.set({
|
|
122
130
|
key: twoslashBlobKey(envHash),
|
|
@@ -124,7 +132,7 @@ const CacheBackedLive = Layer.effect(TwoslashCacheService, Effect.gen(function*
|
|
|
124
132
|
tags: ["twoslash"]
|
|
125
133
|
}).pipe(Effect.catch(() => Effect.void))
|
|
126
134
|
});
|
|
127
|
-
})).pipe(Layer.provide(CacheLive));
|
|
135
|
+
})).pipe(Layer.provide(Cache.degrading(CacheLive)));
|
|
128
136
|
/**
|
|
129
137
|
* A cache that holds nothing, for when the real one cannot be opened.
|
|
130
138
|
*
|
|
@@ -132,10 +140,6 @@ const CacheBackedLive = Layer.effect(TwoslashCacheService, Effect.gen(function*
|
|
|
132
140
|
* `load` returns empty and `save` discards, which is precisely the behaviour
|
|
133
141
|
* before this cache existed: type-check everything, persist nothing.
|
|
134
142
|
*/
|
|
135
|
-
const DegradedLive = Layer.succeed(TwoslashCacheService, withGeneration({
|
|
136
|
-
load: () => Effect.succeed(/* @__PURE__ */ new Map()),
|
|
137
|
-
save: () => Effect.void
|
|
138
|
-
}));
|
|
139
143
|
|
|
140
144
|
//#endregion
|
|
141
145
|
export { TwoslashCacheService };
|
|
@@ -3,11 +3,11 @@ import { emit } from "../observability/EventBus.js";
|
|
|
3
3
|
import { resolveExternalPackageVersions } from "../config-utils.js";
|
|
4
4
|
import { TypeRegistryError } from "../errors.js";
|
|
5
5
|
import { AppDirsLive, PlatformLive } from "../layers/xdg.js";
|
|
6
|
-
import { Context, Duration, Effect, Layer, Path } from "effect";
|
|
6
|
+
import { Cause, Context, Duration, Effect, Layer, Path } from "effect";
|
|
7
7
|
import { NodeHttpClient } from "@effect/platform-node";
|
|
8
|
-
import { PackageFetcher, PackageSpec, RegistryObserver, TypeCache, TypeRegistry } from "@tsdoctor/registry";
|
|
9
8
|
import { Cache } from "@effected/store";
|
|
10
9
|
import { AppDirs } from "@effected/xdg";
|
|
10
|
+
import { PackageFetcher, PackageSpec, RegistryObserver, TypeCache, TypeRegistry } from "@tsdoctor/registry";
|
|
11
11
|
|
|
12
12
|
//#region src/services/TypeRegistryService.ts
|
|
13
13
|
var TypeRegistryService = class TypeRegistryService extends Context.Service()("rspress-plugin-api-extractor/TypeRegistryService") {
|
|
@@ -27,7 +27,7 @@ var TypeRegistryService = class TypeRegistryService extends Context.Service()("r
|
|
|
27
27
|
* static initializer runs while the module body is still evaluating, so naming
|
|
28
28
|
* those consts directly throws at import time with a clean typecheck.
|
|
29
29
|
*/
|
|
30
|
-
static layer = Layer.suspend(() => RegistryBackedLive.pipe(Layer.catchCause(() => DegradedLive)));
|
|
30
|
+
static layer = Layer.suspend(() => RegistryBackedLive.pipe(Layer.catchCause((cause) => Cause.hasInterrupts(cause) ? Layer.effectContext(Effect.failCause(Cause.interrupt([...Cause.interruptors(cause)][0]))) : DegradedLive)));
|
|
31
31
|
/**
|
|
32
32
|
* An in-memory double: no network, no XDG cache, no sqlite.
|
|
33
33
|
*
|
|
@@ -132,7 +132,7 @@ const MetadataCacheLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
132
132
|
const path = yield* Path.Path;
|
|
133
133
|
const cacheDir = yield* appDirs.ensureCache;
|
|
134
134
|
return Cache.layerSqlite({ filename: path.join(cacheDir, "metadata.sqlite") });
|
|
135
|
-
})).pipe(Layer.provide(Layer.mergeAll(AppDirsLive, PlatformLive)));
|
|
135
|
+
})).pipe(Layer.provide(Layer.mergeAll(AppDirsLive, PlatformLive)), Cache.degrading);
|
|
136
136
|
/**
|
|
137
137
|
* The full registry runtime: TypeRegistry over an XDG-rooted TypeCache and the
|
|
138
138
|
* jsDelivr PackageFetcher, with the observer that forwards registry events to
|