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 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, crossLinkData.kinds, apiScope);
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 "typescript";
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).generateVfs();
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).generateVfs();
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 twoslashCache = yield* (yield* TwoslashCacheService).open(twoslashEnv);
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;
@@ -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 "../type-reference-extractor.js";
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,4 +1,4 @@
1
- import { emitFrontmatterBlock } from "../../frontmatter.js";
1
+ import { emitFrontmatterBlock } from "@tsdoctor/model";
2
2
 
3
3
  //#region src/markdown/page-generators/index-pages.ts
4
4
  /**
@@ -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.13.2",
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.0",
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.5.0",
49
- "@effected/tsconfig-json": "^0.6.1",
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.1",
56
- "@tsdoctor/model": "0.4.1",
57
- "@tsdoctor/registry": "0.2.2",
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.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, deprecations } = resolveObservability({
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, LogLevel, ModelInput, MultiApiConfig, PluginOptions, SingleApiConfig, SourceConfig, ThemeConfig, VersionConfig };
315
+ export { AutoDetectDependencies, CategoryConfig, DEFAULT_CATEGORIES, ErrorConfig, ExternalPackageSpec, LlmsPlugin, ModelInput, MultiApiConfig, PluginOptions, SingleApiConfig, SourceConfig, ThemeConfig, VersionConfig };
@@ -31,21 +31,11 @@ function normalizeLevel(value) {
31
31
  return value;
32
32
  }
33
33
  function resolveObservability(input) {
34
- const deprecations = [];
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
- resolved: {
64
- logLevel: level,
65
- json: level === "debug",
66
- tracePath,
67
- progressIntervalMs,
68
- thresholds
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
@@ -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 { PerformanceConfig, PerformanceThresholds };
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 {@link DegradedLive}.
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 `Layer.catchCause` wraps this at all. While the sqlite
27
- * layer was provided inside each method, a construction failure surfaced as
28
- * that method's failure and the in-method handler swallowed it. Hoisting
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. `catchCause` rather than a failure-only catch
33
- * because a defect thrown by the sqlite driver must degrade too.
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.pipe(Layer.catchCause(() => DegradedLive)));
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