rspress-plugin-api-extractor 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/api-extracted-package.js +2 -1
  2. package/build-program.js +20 -12
  3. package/build-stages.js +124 -30
  4. package/config-utils.js +36 -7
  5. package/content-hash.js +1 -1
  6. package/errors.js +1 -1
  7. package/index.d.ts +329 -202
  8. package/layers/ConfigServiceLive.js +300 -136
  9. package/layers/ObservabilityLive.js +49 -85
  10. package/layers/TypeRegistryServiceLive.js +122 -21
  11. package/layers/build-metrics.js +61 -0
  12. package/llms-program.js +29 -7
  13. package/loader.js +16 -2
  14. package/markdown/helpers.js +1 -1
  15. package/markdown/index.js +1 -1
  16. package/markdown/shiki-utils.js +16 -2
  17. package/observability/EventBus.js +38 -0
  18. package/observability/events.js +17 -0
  19. package/observability/sinks/console-sink.js +63 -0
  20. package/observability/sinks/metrics-sink.js +68 -0
  21. package/observability/sinks/trace-sink.js +38 -0
  22. package/observability/spans.js +57 -0
  23. package/og-resolver.js +37 -5
  24. package/package.json +6 -6
  25. package/plugin.js +73 -19
  26. package/prettier-formatter.js +15 -4
  27. package/remark-api-codeblocks.js +22 -3
  28. package/remark-with-api.js +27 -14
  29. package/route-collisions.js +1 -1
  30. package/runtime/components/ApiExample/index.js +5 -5
  31. package/runtime/components/ApiMember/index.js +5 -7
  32. package/runtime/components/ApiSignature/index.js +4 -6
  33. package/runtime/components/EnumMembersTable/index.js +5 -0
  34. package/runtime/components/ExampleBlock/index.js +5 -3
  35. package/runtime/components/MemberSignature/index.js +4 -2
  36. package/runtime/components/ParametersTable/index.js +5 -0
  37. package/runtime/components/SignatureBlock/index.js +4 -2
  38. package/runtime/components/shared/variables.css +0 -15
  39. package/runtime/index.d.ts +65 -399
  40. package/runtime/index.js +1 -5
  41. package/runtime/utils/hast-renderer.js +1 -0
  42. package/schemas/config.js +105 -4
  43. package/schemas/index.js +3 -2
  44. package/schemas/observability.js +62 -0
  45. package/schemas/opengraph.js +30 -0
  46. package/schemas/performance.js +1 -1
  47. package/serve.js +13 -0
  48. package/tsconfig-parser.js +1 -1
  49. package/twoslash-patterns.js +1 -1
  50. package/twoslash-transformer.js +93 -8
  51. package/typescript-config.js +1 -1
package/schemas/config.js CHANGED
@@ -1,5 +1,6 @@
1
- import { OpenGraphImageConfig } from "./opengraph.js";
2
1
  import { PerformanceConfig } from "./performance.js";
2
+ import { ObservabilityConfig } from "./observability.js";
3
+ import { OpenGraphImageConfig } from "./opengraph.js";
3
4
  import { Schema } from "effect";
4
5
  import { ApiItemKind } from "@microsoft/api-extractor-model";
5
6
 
@@ -9,6 +10,11 @@ import { ApiItemKind } from "@microsoft/api-extractor-model";
9
10
  * an async loader function, or a URL.
10
11
  */
11
12
  const ModelInput = Schema.declare((input) => typeof input === "string" || typeof input === "function" || input instanceof URL);
13
+ /**
14
+ * Verbosity level for plugin build output.
15
+ *
16
+ * @public
17
+ */
12
18
  const LogLevel$1 = Schema.Literal("none", "info", "verbose", "debug", "warn", "error");
13
19
  const ExternalPackageSpec = Schema.mutable(Schema.Struct({
14
20
  name: Schema.String,
@@ -17,7 +23,7 @@ const ExternalPackageSpec = Schema.mutable(Schema.Struct({
17
23
  compilerOptions: Schema.optional(Schema.Unknown)
18
24
  }));
19
25
  const AutoDetectDependencies = Schema.mutable(Schema.Struct({
20
- dependencies: Schema.optionalWith(Schema.Boolean, { default: () => false }),
26
+ dependencies: Schema.optionalWith(Schema.Boolean, { default: () => true }),
21
27
  devDependencies: Schema.optionalWith(Schema.Boolean, { default: () => false }),
22
28
  peerDependencies: Schema.optionalWith(Schema.Boolean, { default: () => true }),
23
29
  autoDependencies: Schema.optionalWith(Schema.Boolean, { default: () => true })
@@ -37,18 +43,38 @@ const LlmsPlugin = Schema.mutable(Schema.Struct({
37
43
  ] })
38
44
  }));
39
45
  const ApiItemKindSchema = Schema.declare((input) => typeof input === "number");
46
+ /**
47
+ * Configuration for a single documentation category (e.g. Classes, Functions).
48
+ *
49
+ * @public
50
+ */
40
51
  const CategoryConfig = Schema.mutable(Schema.Struct({
52
+ /** Human-readable plural display name shown in the sidebar. */
41
53
  displayName: Schema.String,
54
+ /** Human-readable singular name used in page titles. */
42
55
  singularName: Schema.String,
56
+ /** Folder name under the API base route (URL segment). */
43
57
  folderName: Schema.String,
58
+ /** API item kinds included in this category. */
44
59
  itemKinds: Schema.optional(Schema.mutable(Schema.Array(ApiItemKindSchema))),
60
+ /** TSDoc modifier tag that marks items for this category. */
45
61
  tsdocModifier: Schema.optional(Schema.String),
62
+ /** Whether the sidebar section is collapsible. Defaults to `true`. */
46
63
  collapsible: Schema.optionalWith(Schema.Boolean, { default: () => true }),
64
+ /** Whether the sidebar section starts collapsed. Defaults to `true`. */
47
65
  collapsed: Schema.optionalWith(Schema.Boolean, { default: () => true }),
66
+ /** Heading levels shown in the overview. Defaults to `[2]`. */
48
67
  overviewHeaders: Schema.optionalWith(Schema.mutable(Schema.Array(Schema.Number)), { default: () => [2] })
49
68
  }));
69
+ /**
70
+ * Source repository link configuration for an API.
71
+ *
72
+ * @public
73
+ */
50
74
  const SourceConfig = Schema.mutable(Schema.Struct({
75
+ /** Base URL of the source repository (e.g. `"https://github.com/org/repo/blob/main/src"`). */
51
76
  url: Schema.String,
77
+ /** Optional git ref (branch, tag, or commit SHA) appended to source links. */
52
78
  ref: Schema.optional(Schema.String)
53
79
  }));
54
80
  const ThemeConfig = Schema.Union(Schema.String, Schema.mutable(Schema.Struct({
@@ -59,7 +85,10 @@ const ThemeConfig = Schema.Union(Schema.String, Schema.mutable(Schema.Struct({
59
85
  value: Schema.Unknown
60
86
  })));
61
87
  /**
62
- * Built-in default categories
88
+ * Built-in default category definitions covering Classes, Interfaces, Functions,
89
+ * Types, Enums, Variables, and Namespaces.
90
+ *
91
+ * @public
63
92
  */
64
93
  const DEFAULT_CATEGORIES = {
65
94
  classes: {
@@ -131,68 +160,140 @@ const CategoriesRecord = Schema.mutable(Schema.Record({
131
160
  key: Schema.String,
132
161
  value: CategoryConfig
133
162
  }));
163
+ /**
164
+ * Configuration for a single version of an API within a multi-version setup.
165
+ *
166
+ * @public
167
+ */
134
168
  const VersionConfig = Schema.mutable(Schema.Struct({
169
+ /** Path or loader for the `.api.json` model file for this version. */
135
170
  model: ModelInput,
171
+ /** Path or loader for the `package.json` for this version. */
136
172
  packageJson: Schema.optional(ModelInput),
173
+ /** Category overrides for this version. */
137
174
  categories: Schema.optional(CategoriesRecord),
175
+ /** Source repository link configuration for this version. */
138
176
  source: Schema.optional(SourceConfig),
177
+ /** External npm packages whose types should be loaded for Twoslash. */
139
178
  externalPackages: Schema.optional(Schema.mutable(Schema.Array(ExternalPackageSpec))),
179
+ /** Auto-detect external packages from `package.json` dependency fields. */
140
180
  autoDetectDependencies: Schema.optional(AutoDetectDependencies),
181
+ /** Open Graph image configuration for this version. */
141
182
  ogImage: Schema.optional(OpenGraphImageConfig),
183
+ /** LLMs integration options for this version. */
142
184
  llmsPlugin: Schema.optional(LlmsPlugin),
185
+ /** Path to a `tsconfig.json` for this version. */
143
186
  tsconfig: Schema.optional(ModelInput),
187
+ /** TypeScript compiler options for Twoslash. */
144
188
  compilerOptions: Schema.optional(Schema.Unknown)
145
189
  }));
146
190
  /** Union for the versions record value: can be a path/function OR a full VersionConfig */
147
191
  const VersionValue = Schema.Union(ModelInput, VersionConfig);
192
+ /**
193
+ * Configuration for a single-package API documentation site (the `api:` option).
194
+ *
195
+ * @public
196
+ */
148
197
  const SingleApiConfig = Schema.mutable(Schema.Struct({
198
+ /** npm package name of the documented package. */
149
199
  packageName: Schema.String,
200
+ /** Optional display name shown in the sidebar and page titles. */
150
201
  name: Schema.optional(Schema.String),
202
+ /** Base URL route for API pages (defaults to `/api`). */
151
203
  baseRoute: Schema.optional(Schema.String),
204
+ /** Subfolder name under `baseRoute` for API pages, or `null` to omit. */
152
205
  apiFolder: Schema.optional(Schema.Union(Schema.String, Schema.Null)),
206
+ /** Path or loader for the `.api.json` model file. */
153
207
  model: Schema.optional(ModelInput),
208
+ /** Path or loader for the `package.json`. */
154
209
  packageJson: Schema.optional(ModelInput),
210
+ /** Versioned models keyed by version label. */
155
211
  versions: Schema.optional(Schema.mutable(Schema.Record({
156
212
  key: Schema.String,
157
213
  value: VersionValue
158
214
  }))),
215
+ /** Shiki syntax-highlighting theme. */
159
216
  theme: Schema.optional(ThemeConfig),
217
+ /** Category definitions (defaults to {@link DEFAULT_CATEGORIES}). */
160
218
  categories: Schema.optional(CategoriesRecord),
219
+ /** Source repository link configuration. */
161
220
  source: Schema.optional(SourceConfig),
221
+ /** External npm packages whose types should be loaded for Twoslash. */
162
222
  externalPackages: Schema.optional(Schema.mutable(Schema.Array(ExternalPackageSpec))),
223
+ /** Auto-detect external packages from `package.json` dependency fields. */
163
224
  autoDetectDependencies: Schema.optional(AutoDetectDependencies),
225
+ /** Open Graph image configuration. */
164
226
  ogImage: Schema.optional(OpenGraphImageConfig),
227
+ /** LLMs integration options. */
165
228
  llmsPlugin: Schema.optional(LlmsPlugin),
229
+ /** Path to a `tsconfig.json` for Twoslash. */
166
230
  tsconfig: Schema.optional(ModelInput),
231
+ /** TypeScript compiler options for Twoslash. */
167
232
  compilerOptions: Schema.optional(Schema.Unknown)
168
233
  }));
234
+ /**
235
+ * Configuration for one package in a multi-API portal (each element of the `apis:` array).
236
+ *
237
+ * @public
238
+ */
169
239
  const MultiApiConfig = Schema.mutable(Schema.Struct({
240
+ /** npm package name of the documented package. */
170
241
  packageName: Schema.String,
242
+ /** Optional display name shown in the sidebar and page titles. */
171
243
  name: Schema.optional(Schema.String),
244
+ /** Base URL route for this package's API pages. */
172
245
  baseRoute: Schema.optional(Schema.String),
246
+ /** Subfolder name under `baseRoute` for API pages, or `null` to omit. */
173
247
  apiFolder: Schema.optional(Schema.Union(Schema.String, Schema.Null)),
248
+ /** Path or loader for the `.api.json` model file (required). */
174
249
  model: ModelInput,
250
+ /** Path or loader for the `package.json`. */
175
251
  packageJson: Schema.optional(ModelInput),
252
+ /** Shiki syntax-highlighting theme. */
176
253
  theme: Schema.optional(ThemeConfig),
254
+ /** Category definitions (defaults to {@link DEFAULT_CATEGORIES}). */
177
255
  categories: Schema.optional(CategoriesRecord),
256
+ /** Source repository link configuration. */
178
257
  source: Schema.optional(SourceConfig),
258
+ /** External npm packages whose types should be loaded for Twoslash. */
179
259
  externalPackages: Schema.optional(Schema.mutable(Schema.Array(ExternalPackageSpec))),
260
+ /** Auto-detect external packages from `package.json` dependency fields. */
180
261
  autoDetectDependencies: Schema.optional(AutoDetectDependencies),
262
+ /** Open Graph image configuration. */
181
263
  ogImage: Schema.optional(OpenGraphImageConfig),
264
+ /** LLMs integration options. */
182
265
  llmsPlugin: Schema.optional(LlmsPlugin),
266
+ /** Path to a `tsconfig.json` for Twoslash. */
183
267
  tsconfig: Schema.optional(ModelInput),
268
+ /** TypeScript compiler options for Twoslash. */
184
269
  compilerOptions: Schema.optional(Schema.Unknown)
185
270
  }));
271
+ /**
272
+ * Top-level options passed to {@link ApiExtractorPlugin}.
273
+ *
274
+ * @public
275
+ */
186
276
  const PluginOptions = Schema.mutable(Schema.Struct({
277
+ /** Single-API configuration (mutually exclusive with `apis`). */
187
278
  api: Schema.optional(SingleApiConfig),
279
+ /** Multi-API portal configuration (mutually exclusive with `api`). */
188
280
  apis: Schema.optional(Schema.mutable(Schema.Array(MultiApiConfig))),
281
+ /** Canonical site URL used for Open Graph absolute URLs. */
189
282
  siteUrl: Schema.optional(Schema.String),
283
+ /** Global Open Graph image configuration (overridden per-API). */
190
284
  ogImage: Schema.optional(OpenGraphImageConfig),
285
+ /** Override the default category definitions for all APIs. */
191
286
  defaultCategories: Schema.optional(CategoriesRecord),
287
+ /** Error display options for code examples. */
192
288
  errors: Schema.optional(ErrorConfig),
289
+ /** LLMs integration options, or `false` to disable. */
193
290
  llmsPlugin: Schema.optional(Schema.Union(Schema.Boolean, LlmsPlugin)),
291
+ /** Verbosity level for plugin build output. @deprecated Use `observability.logLevel`. */
194
292
  logLevel: Schema.optional(LogLevel$1),
195
- performance: Schema.optional(PerformanceConfig)
293
+ /** Performance tuning options. @deprecated Use `observability.thresholds`. */
294
+ performance: Schema.optional(PerformanceConfig),
295
+ /** Unified observability configuration (logLevel, trace artifact, thresholds). */
296
+ observability: Schema.optional(ObservabilityConfig)
196
297
  }));
197
298
 
198
299
  //#endregion
package/schemas/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { OpenGraphImageConfig, OpenGraphImageMetadata } from "./opengraph.js";
2
1
  import { PerformanceConfig, PerformanceThresholds } from "./performance.js";
2
+ import { EventLevelSchema, ObservabilityConfig, resolveObservability } from "./observability.js";
3
+ import { OpenGraphImageConfig, OpenGraphImageMetadata } from "./opengraph.js";
3
4
  import { AutoDetectDependencies, CategoryConfig, DEFAULT_CATEGORIES, ErrorConfig, ExternalPackageSpec, LlmsPlugin, LogLevel, ModelInput, MultiApiConfig, PluginOptions, SingleApiConfig, SourceConfig, ThemeConfig, VersionConfig } from "./config.js";
4
5
 
5
- export { };
6
+ export { DEFAULT_CATEGORIES, PluginOptions };
@@ -0,0 +1,62 @@
1
+ import { PerformanceThresholds } from "./performance.js";
2
+ import { Schema } from "effect";
3
+
4
+ //#region src/schemas/observability.ts
5
+ const EventLevelSchema = Schema.Literal("none", "error", "warn", "info", "debug", "trace", "verbose");
6
+ const ObservabilityConfig = Schema.mutable(Schema.Struct({
7
+ logLevel: Schema.optional(EventLevelSchema),
8
+ trace: Schema.optional(Schema.Union(Schema.Boolean, Schema.String)),
9
+ thresholds: Schema.optional(PerformanceThresholds)
10
+ }));
11
+ const DEFAULT_THRESHOLDS = {
12
+ slowCodeBlock: 500,
13
+ slowPageGeneration: 500,
14
+ slowApiLoad: 1e3,
15
+ slowFileOperation: 50,
16
+ slowHttpRequest: 2e3,
17
+ slowDbOperation: 100
18
+ };
19
+ function normalizeLevel(value) {
20
+ if (value === void 0) return void 0;
21
+ if (value === "verbose") return "debug";
22
+ return value;
23
+ }
24
+ function resolveObservability(input) {
25
+ const deprecations = [];
26
+ if (input.logLevel !== void 0) deprecations.push({
27
+ key: "logLevel",
28
+ replacement: "observability.logLevel"
29
+ });
30
+ if (input.performance !== void 0) deprecations.push({
31
+ key: "performance",
32
+ replacement: "observability.thresholds"
33
+ });
34
+ const level = normalizeLevel(input.envLogLevel) ?? normalizeLevel(input.observability?.logLevel) ?? normalizeLevel(input.logLevel) ?? "info";
35
+ const traceOpt = input.observability?.trace;
36
+ const tracePath = typeof traceOpt === "string" ? traceOpt : traceOpt === true ? `${input.outDir}/.api-extractor/trace-${input.buildId}.jsonl` : null;
37
+ const merged = {
38
+ ...DEFAULT_THRESHOLDS,
39
+ ...input.performance?.thresholds ?? {},
40
+ ...input.observability?.thresholds ?? {}
41
+ };
42
+ const thresholds = {
43
+ slowCodeBlock: merged.slowCodeBlock ?? DEFAULT_THRESHOLDS.slowCodeBlock,
44
+ slowPageGeneration: merged.slowPageGeneration ?? DEFAULT_THRESHOLDS.slowPageGeneration,
45
+ slowApiLoad: merged.slowApiLoad ?? DEFAULT_THRESHOLDS.slowApiLoad,
46
+ slowFileOperation: merged.slowFileOperation ?? DEFAULT_THRESHOLDS.slowFileOperation,
47
+ slowHttpRequest: merged.slowHttpRequest ?? DEFAULT_THRESHOLDS.slowHttpRequest,
48
+ slowDbOperation: merged.slowDbOperation ?? DEFAULT_THRESHOLDS.slowDbOperation
49
+ };
50
+ return {
51
+ resolved: {
52
+ logLevel: level,
53
+ json: level === "debug",
54
+ tracePath,
55
+ thresholds
56
+ },
57
+ deprecations
58
+ };
59
+ }
60
+
61
+ //#endregion
62
+ export { EventLevelSchema, ObservabilityConfig, resolveObservability };
@@ -1,24 +1,54 @@
1
1
  import { Schema } from "effect";
2
2
 
3
3
  //#region src/schemas/opengraph.ts
4
+ /**
5
+ * Structured Open Graph image metadata (alternative to a plain URL string).
6
+ *
7
+ * @public
8
+ */
4
9
  const OpenGraphImageMetadata = Schema.mutable(Schema.Struct({
10
+ /** Absolute URL of the image. */
5
11
  url: Schema.String,
12
+ /** HTTPS URL of the image (for secure contexts). */
6
13
  secureUrl: Schema.optional(Schema.String),
14
+ /** MIME type of the image (e.g. `"image/png"`). */
7
15
  type: Schema.optional(Schema.String),
16
+ /** Image width in pixels. */
8
17
  width: Schema.optional(Schema.Number),
18
+ /** Image height in pixels. */
9
19
  height: Schema.optional(Schema.Number),
20
+ /** Alt text for the image. */
10
21
  alt: Schema.optional(Schema.String)
11
22
  }));
23
+ /**
24
+ * Open Graph image: either a plain URL string or structured `OpenGraphImageMetadata`.
25
+ *
26
+ * @public
27
+ */
12
28
  const OpenGraphImageConfig = Schema.Union(Schema.String, OpenGraphImageMetadata);
29
+ /**
30
+ * Resolved Open Graph metadata emitted into each generated page's frontmatter.
31
+ *
32
+ * @public
33
+ */
13
34
  const OpenGraphMetadata = Schema.mutable(Schema.Struct({
35
+ /** Canonical site base URL. */
14
36
  siteUrl: Schema.String,
37
+ /** Page route path (e.g. `/api/classes/myclass`). */
15
38
  pageRoute: Schema.String,
39
+ /** Page description for the `og:description` tag. */
16
40
  description: Schema.String,
41
+ /** ISO 8601 date string for `article:published_time`. */
17
42
  publishedTime: Schema.String,
43
+ /** ISO 8601 date string for `article:modified_time`. */
18
44
  modifiedTime: Schema.String,
45
+ /** Article section label (e.g. `"API"`). */
19
46
  section: Schema.String,
47
+ /** Article tag keywords. */
20
48
  tags: Schema.mutable(Schema.Array(Schema.String)),
49
+ /** Optional structured image metadata. */
21
50
  ogImage: Schema.optional(OpenGraphImageMetadata),
51
+ /** Open Graph object type (e.g. `"article"`). */
22
52
  ogType: Schema.String
23
53
  }));
24
54
 
@@ -2,7 +2,7 @@ import { Schema } from "effect";
2
2
 
3
3
  //#region src/schemas/performance.ts
4
4
  const PerformanceThresholds = Schema.mutable(Schema.Struct({
5
- slowCodeBlock: Schema.optionalWith(Schema.Number, { default: () => 100 }),
5
+ slowCodeBlock: Schema.optionalWith(Schema.Number, { default: () => 500 }),
6
6
  slowPageGeneration: Schema.optionalWith(Schema.Number, { default: () => 500 }),
7
7
  slowApiLoad: Schema.optionalWith(Schema.Number, { default: () => 1e3 }),
8
8
  slowFileOperation: Schema.optionalWith(Schema.Number, { default: () => 50 }),
package/serve.js CHANGED
@@ -9,6 +9,11 @@ const DEFAULT_PORT = 4173;
9
9
  * "ready ... built in" line, kept as a fallback in case the address-line format
10
10
  * changes. Pure and exported so it can be unit-tested and reused as a
11
11
  * {@link ServeOptions.readyWhen} building block.
12
+ *
13
+ * @param mode - the server mode (`"dev"` or `"preview"`)
14
+ * @param output - a chunk of combined stdout/stderr from the server process
15
+ * @returns `true` when the server appears to be listening
16
+ * @public
12
17
  */
13
18
  function isServerReady(mode, output) {
14
19
  if (output.includes("Local:")) return true;
@@ -19,6 +24,10 @@ function isServerReady(mode, output) {
19
24
  * Resolve {@link ServeOptions} into a concrete {@link ResolvedServeConfig},
20
25
  * applying all defaults. Pure (modulo reading `process.env`) and exported so
21
26
  * the resolution logic can be unit-tested without spawning a server.
27
+ *
28
+ * @param options - optional serve options; all fields have sensible defaults
29
+ * @returns a fully resolved config with all defaults applied
30
+ * @public
22
31
  */
23
32
  function resolveServeConfig(options = {}) {
24
33
  const mode = options.mode ?? "dev";
@@ -81,6 +90,10 @@ function killProcessOnPort(port) {
81
90
  * returned promise resolves once the server is ready and the browser has been
82
91
  * opened; it does not resolve when the server stops. Port-freeing and browser
83
92
  * opening are best-effort and never reject.
93
+ *
94
+ * @param options - optional serve options; all fields have sensible defaults
95
+ * @returns a promise that resolves once the server is ready and the browser has been opened
96
+ * @public
84
97
  */
85
98
  async function serve(options = {}) {
86
99
  const config = resolveServeConfig(options);
@@ -124,4 +124,4 @@ function extractTypeResolutionOptions(tsOptions) {
124
124
  }
125
125
 
126
126
  //#endregion
127
- export { TsConfigParseError, parseTsConfig };
127
+ export { TsConfigParseError, parseTsConfig, parseTsConfigWithMetadata };
@@ -84,4 +84,4 @@ function classifyCutDirective(trimmedLine) {
84
84
  }
85
85
 
86
86
  //#endregion
87
- export { classifyCutDirective, isTwoslashDirective };
87
+ export { RE_ANNOTATION, RE_CONFIG, RE_CUT, classifyCutDirective, isTwoslashDirective };
@@ -1,6 +1,5 @@
1
- import { BuildMetrics } from "./layers/ObservabilityLive.js";
1
+ import { PluginEvent } from "./observability/events.js";
2
2
  import { DEFAULT_COMPILER_OPTIONS } from "./typescript-config.js";
3
- import { Effect, Metric } from "effect";
4
3
  import { rendererRich, transformerTwoslash } from "@shikijs/twoslash";
5
4
  import { fromMarkdown } from "mdast-util-from-markdown";
6
5
  import { toHast } from "mdast-util-to-hast";
@@ -8,6 +7,22 @@ import { toHast } from "mdast-util-to-hast";
8
7
  //#region src/twoslash-transformer.ts
9
8
  /* v8 ignore start -- Shiki/Twoslash integration, requires full highlighter setup for testing */
10
9
  /**
10
+ * Module-level emitter seam. Default is a no-op; wire in `setEventEmitter(emitSync)`
11
+ * from plugin.ts right after the runtime emitter is created so that Twoslash error
12
+ * events flow through the EventBus even though they fire in a sync Shiki callback
13
+ * outside any Effect fiber.
14
+ */
15
+ let emitEvent = () => {};
16
+ let currentBuildId = "";
17
+ /**
18
+ * Inject the runtime-bound emitter into the Twoslash module.
19
+ * Call this right after `makeRuntimeEmitter` in plugin.ts.
20
+ */
21
+ function setEventEmitter(fn, buildId = "") {
22
+ emitEvent = fn;
23
+ currentBuildId = buildId;
24
+ }
25
+ /**
11
26
  * Module-level type routes map for resolving link references.
12
27
  * This is set by TwoslashManager.setTypeRoutes() before initialization.
13
28
  */
@@ -134,7 +149,7 @@ function renderMarkdown(markdown) {
134
149
  * Tags to hide entirely in hover popups.
135
150
  * These are either redundant with the API documentation structure or add noise.
136
151
  */
137
- const HIDDEN_TAGS = new Set([
152
+ const HIDDEN_TAGS = /* @__PURE__ */ new Set([
138
153
  "example",
139
154
  "public",
140
155
  "internal",
@@ -219,6 +234,23 @@ var TwoslashManager = class TwoslashManager {
219
234
  */
220
235
  transformer = null;
221
236
  /**
237
+ * VFS keys snapshot captured at initialize() time.
238
+ * Returned by vfsKeysSnapshot() for TwoslashCheckFailed events.
239
+ */
240
+ _vfsKeys = [];
241
+ /**
242
+ * Resolved compiler options captured at initialize() time.
243
+ * Returned by compilerOptionsSnapshot() for TwoslashCheckFailed events.
244
+ */
245
+ _resolvedCompilerOptions = DEFAULT_COMPILER_OPTIONS;
246
+ /**
247
+ * Path of the file whose code block is currently being processed.
248
+ * Used to attribute Twoslash error events to a source file. Defaults to
249
+ * "unknown"; remark plugins set this via setCurrentFile() before rendering
250
+ * each block (wired in Task 11).
251
+ */
252
+ currentFilePath = "unknown";
253
+ /**
222
254
  * Private constructor to enforce singleton pattern
223
255
  */
224
256
  constructor() {}
@@ -242,7 +274,9 @@ var TwoslashManager = class TwoslashManager {
242
274
  initialize(vfs, _reserved, _reserved2, tsEnvCache, compilerOptions) {
243
275
  const extraFiles = {};
244
276
  for (const [path, content] of vfs.entries()) extraFiles[path] = content;
277
+ this._vfsKeys = Array.from(vfs.keys());
245
278
  const resolvedOptions = compilerOptions ?? DEFAULT_COMPILER_OPTIONS;
279
+ this._resolvedCompilerOptions = resolvedOptions;
246
280
  this.transformer = transformerTwoslash({
247
281
  renderer: rendererRich({
248
282
  processHoverInfo: (info) => {
@@ -260,10 +294,8 @@ var TwoslashManager = class TwoslashManager {
260
294
  },
261
295
  explicitTrigger: true,
262
296
  throws: false,
263
- onTwoslashError: (error, _code) => {
264
- Effect.runSync(Metric.increment(BuildMetrics.twoslashErrors));
265
- const errorMsg = error instanceof Error ? error.message : String(error);
266
- console.error(`🔴 Twoslash error: ${errorMsg}`);
297
+ onTwoslashError: (error, code) => {
298
+ this.handleTwoslashError(error, code, this.currentFilePath);
267
299
  }
268
300
  });
269
301
  }
@@ -275,6 +307,15 @@ var TwoslashManager = class TwoslashManager {
275
307
  return this.transformer;
276
308
  }
277
309
  /**
310
+ * Set the source file path used to attribute subsequent Twoslash error events.
311
+ * Remark plugins call this before rendering each code block (wired in Task 11).
312
+ *
313
+ * @param path - Source file path (e.g. "kitchensink/api/class/plugin.md")
314
+ */
315
+ setCurrentFile(path) {
316
+ this.currentFilePath = path;
317
+ }
318
+ /**
278
319
  * Clear the Twoslash transformer (useful for testing or reinitializing)
279
320
  */
280
321
  clear() {
@@ -286,6 +327,50 @@ var TwoslashManager = class TwoslashManager {
286
327
  static reset() {
287
328
  TwoslashManager.instance = null;
288
329
  }
330
+ /** Returns VFS keys snapshotted at initialize() time. Empty array before initialize(). */
331
+ vfsKeysSnapshot() {
332
+ return this._vfsKeys;
333
+ }
334
+ /** Returns compiler options snapshotted at initialize() time. Falls back to DEFAULT_COMPILER_OPTIONS. */
335
+ compilerOptionsSnapshot() {
336
+ return this._resolvedCompilerOptions;
337
+ }
338
+ handleTwoslashError(error, _code, file) {
339
+ const message = error instanceof Error ? error.message : String(error);
340
+ const match = /TS(\d+)/.exec(message);
341
+ const tsCode = match ? Number(match[1]) : 0;
342
+ emitEvent(PluginEvent.TwoslashDiagnostic({
343
+ ctx: {
344
+ buildId: currentBuildId,
345
+ file
346
+ },
347
+ level: "warn",
348
+ file,
349
+ line: 0,
350
+ col: 0,
351
+ code: tsCode,
352
+ message,
353
+ snippet: ""
354
+ }));
355
+ emitEvent(PluginEvent.TwoslashCheckFailed({
356
+ ctx: {
357
+ buildId: currentBuildId,
358
+ file
359
+ },
360
+ level: "trace",
361
+ file,
362
+ code: tsCode,
363
+ fsMapKeys: this.vfsKeysSnapshot(),
364
+ compilerOptions: JSON.stringify(this.compilerOptionsSnapshot())
365
+ }));
366
+ }
367
+ /**
368
+ * Test seam: drive `handleTwoslashError` directly without going through the Shiki transformer.
369
+ * @internal
370
+ */
371
+ handleTwoslashErrorForTest(error, code, file) {
372
+ this.handleTwoslashError(error, code, file);
373
+ }
289
374
  /**
290
375
  * Set the type routes map for resolving link references in hover docs.
291
376
  * This should be called before initialize() to enable type linking.
@@ -313,4 +398,4 @@ var TwoslashManager = class TwoslashManager {
313
398
  };
314
399
 
315
400
  //#endregion
316
- export { TwoslashManager };
401
+ export { TwoslashManager, setEventEmitter };
@@ -165,4 +165,4 @@ async function resolveTypeScriptConfig(projectRoot, global, api, version, packag
165
165
  }
166
166
 
167
167
  //#endregion
168
- export { DEFAULT_COMPILER_OPTIONS, resolveTypeScriptConfig };
168
+ export { DEFAULT_COMPILER_OPTIONS, mergeCompilerOptions, resolveTypeScriptConfig, resolveTypeScriptConfigSingleAsync };