@openpkg-ts/sdk 0.30.2 → 0.32.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/README.md CHANGED
@@ -75,6 +75,55 @@ import { diffSpecs } from '@openpkg-ts/sdk';
75
75
 
76
76
  const diff = diffSpecs(oldSpec, newSpec);
77
77
  console.log(`Breaking: ${diff.breaking.length}`);
78
+
79
+ // With options
80
+ const diff = diffSpecs(oldSpec, newSpec, {
81
+ includeDocsOnly: false, // exclude docs-only changes
82
+ kinds: ['function', 'class'], // filter by kind
83
+ });
84
+ ```
85
+
86
+ ### filterSpec
87
+
88
+ Immutable spec filtering by criteria.
89
+
90
+ ```typescript
91
+ import { filterSpec } from '@openpkg-ts/sdk';
92
+
93
+ // Filter by kind
94
+ const { spec, matched, total } = filterSpec(fullSpec, {
95
+ kinds: ['function', 'class'],
96
+ });
97
+
98
+ // Filter by tags
99
+ filterSpec(spec, { tags: ['public'] });
100
+
101
+ // Filter deprecated exports
102
+ filterSpec(spec, { deprecated: true });
103
+
104
+ // Search by name/description
105
+ filterSpec(spec, { search: 'client' });
106
+
107
+ // Combine criteria (AND logic)
108
+ filterSpec(spec, {
109
+ kinds: ['function'],
110
+ hasDescription: true,
111
+ deprecated: false,
112
+ });
113
+ ```
114
+
115
+ ### analyzeSpec
116
+
117
+ Analyze spec for quality issues.
118
+
119
+ ```typescript
120
+ import { analyzeSpec } from '@openpkg-ts/sdk';
121
+
122
+ const diagnostics = analyzeSpec(spec);
123
+
124
+ console.log(`Missing descriptions: ${diagnostics.missingDescriptions.length}`);
125
+ console.log(`Deprecated without reason: ${diagnostics.deprecatedNoReason.length}`);
126
+ console.log(`Missing param docs: ${diagnostics.missingParamDocs.length}`);
78
127
  ```
79
128
 
80
129
  ## Documentation Generation
@@ -144,6 +193,10 @@ import type {
144
193
  ExtractResult,
145
194
  DocsInstance,
146
195
  SimplifiedSpec,
196
+ FilterCriteria,
197
+ FilterResult,
198
+ SpecDiagnostics,
199
+ DiffOptions,
147
200
  } from '@openpkg-ts/sdk';
148
201
  ```
149
202
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,39 @@
1
1
  import { BreakingSeverity, CategorizedBreaking, calculateNextVersion, categorizeBreakingChanges, diffSpec, diffSpec as diffSpec2, MemberChangeInfo, recommendSemverBump, SemverBump, SemverRecommendation, SpecDiff } from "@openpkg-ts/spec";
2
+ import { OpenPkg, SpecExport } from "@openpkg-ts/spec";
3
+ interface DiagnosticItem {
4
+ exportId: string;
5
+ exportName: string;
6
+ issue: string;
7
+ /** Member name if issue is on a member */
8
+ member?: string;
9
+ /** Parameter name if issue is on a parameter */
10
+ param?: string;
11
+ }
12
+ interface SpecDiagnostics {
13
+ /** Exports/members without descriptions */
14
+ missingDescriptions: DiagnosticItem[];
15
+ /** Exports marked @deprecated but no reason provided */
16
+ deprecatedNoReason: DiagnosticItem[];
17
+ /** Function params without descriptions in JSDoc */
18
+ missingParamDocs: DiagnosticItem[];
19
+ }
20
+ /**
21
+ * Check if has @deprecated tag.
22
+ */
23
+ declare function hasDeprecatedTag(exp: SpecExport): boolean;
24
+ /**
25
+ * Get deprecation message from @deprecated tag.
26
+ * Returns undefined if no reason provided.
27
+ */
28
+ declare function getDeprecationMessage(exp: SpecExport): string | undefined;
29
+ /**
30
+ * Find params without descriptions in JSDoc.
31
+ */
32
+ declare function findMissingParamDocs(exp: SpecExport): string[];
33
+ /**
34
+ * Analyze a spec for quality issues.
35
+ */
36
+ declare function analyzeSpec(spec: OpenPkg): SpecDiagnostics;
2
37
  import { SpecMember } from "@openpkg-ts/spec";
3
38
  /**
4
39
  * Extract badge strings from a member's visibility and flags.
@@ -9,8 +44,8 @@ declare function getMemberBadges(member: SpecMember): string[];
9
44
  * Format badges array into a display string (space-separated).
10
45
  */
11
46
  declare function formatBadges(badges: string[]): string;
12
- import { OpenPkg as OpenPkg6, SpecExport as SpecExport2, SpecExportKind as SpecExportKind4, SpecType } from "@openpkg-ts/spec";
13
- import { OpenPkg } from "@openpkg-ts/spec";
47
+ import { OpenPkg as OpenPkg7, SpecExport as SpecExport3, SpecExportKind as SpecExportKind4, SpecType } from "@openpkg-ts/spec";
48
+ import { OpenPkg as OpenPkg2 } from "@openpkg-ts/spec";
14
49
  interface HTMLOptions {
15
50
  /** Page title override */
16
51
  title?: string;
@@ -24,6 +59,8 @@ interface HTMLOptions {
24
59
  fullDocument?: boolean;
25
60
  /** Export to render (single mode) */
26
61
  export?: string;
62
+ /** Exports to render (multi-mode) - overridden by `export` if both provided */
63
+ exports?: string[];
27
64
  }
28
65
  /**
29
66
  * Render spec to standalone HTML page.
@@ -46,13 +83,15 @@ interface HTMLOptions {
46
83
  * const fragment = docs.toHTML({ export: 'greet', fullDocument: false })
47
84
  * ```
48
85
  */
49
- declare function toHTML2(spec: OpenPkg, options?: HTMLOptions): string;
50
- import { OpenPkg as OpenPkg2, SpecExportKind } from "@openpkg-ts/spec";
86
+ declare function toHTML2(spec: OpenPkg2, options?: HTMLOptions): string;
87
+ import { OpenPkg as OpenPkg3, SpecExportKind } from "@openpkg-ts/spec";
51
88
  interface JSONOptions {
52
89
  /** Include raw spec data alongside simplified data */
53
90
  includeRaw?: boolean;
54
91
  /** Export to render (single mode) */
55
92
  export?: string;
93
+ /** Exports to render (multi-mode) - overridden by `export` if both provided */
94
+ exports?: string[];
56
95
  /** Include computed fields (signatures, formatted types) */
57
96
  computed?: boolean;
58
97
  /** Flatten nested structures */
@@ -139,7 +178,7 @@ interface SimplifiedSpec {
139
178
  * // { id, name, kind, signature, parameters, returns, ... }
140
179
  * ```
141
180
  */
142
- declare function toJSON2(spec: OpenPkg2, options?: JSONOptions): SimplifiedSpec | SimplifiedExport;
181
+ declare function toJSON2(spec: OpenPkg3, options?: JSONOptions): SimplifiedSpec | SimplifiedExport;
143
182
  /**
144
183
  * Serialize to JSON string with formatting.
145
184
  *
@@ -147,10 +186,10 @@ declare function toJSON2(spec: OpenPkg2, options?: JSONOptions): SimplifiedSpec
147
186
  * @param options - JSON options plus pretty formatting option
148
187
  * @returns JSON string
149
188
  */
150
- declare function toJSONString(spec: OpenPkg2, options?: JSONOptions & {
189
+ declare function toJSONString(spec: OpenPkg3, options?: JSONOptions & {
151
190
  pretty?: boolean;
152
191
  }): string;
153
- import { OpenPkg as OpenPkg3, SpecExport } from "@openpkg-ts/spec";
192
+ import { OpenPkg as OpenPkg4, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
154
193
  interface MarkdownOptions {
155
194
  /** Include frontmatter in output */
156
195
  frontmatter?: boolean;
@@ -171,10 +210,14 @@ interface MarkdownOptions {
171
210
  codeSignatures?: boolean;
172
211
  /** Heading level offset (0 = starts at h1, 1 = starts at h2) */
173
212
  headingOffset?: number;
213
+ /** Collapse unions with more than N members (default: no collapse) */
214
+ collapseUnionThreshold?: number;
174
215
  }
175
216
  interface ExportMarkdownOptions extends MarkdownOptions {
176
- /** Export to render */
217
+ /** Export to render (single mode) */
177
218
  export?: string;
219
+ /** Exports to render (multi-mode) - overridden by `export` if both provided */
220
+ exports?: string[];
178
221
  }
179
222
  /**
180
223
  * Render a single to MDX.
@@ -192,7 +235,7 @@ interface ExportMarkdownOptions extends MarkdownOptions {
192
235
  * })
193
236
  * ```
194
237
  */
195
- declare function exportToMarkdown(exp: SpecExport, options?: MarkdownOptions): string;
238
+ declare function exportToMarkdown(exp: SpecExport2, options?: MarkdownOptions): string;
196
239
  /**
197
240
  * Render entire spec to MDX.
198
241
  *
@@ -212,8 +255,8 @@ declare function exportToMarkdown(exp: SpecExport, options?: MarkdownOptions): s
212
255
  * // Single * const fnMdx = docs.toMarkdown({ export: 'greet' })
213
256
  * ```
214
257
  */
215
- declare function toMarkdown2(spec: OpenPkg3, options?: ExportMarkdownOptions): string;
216
- import { OpenPkg as OpenPkg4, SpecExportKind as SpecExportKind2 } from "@openpkg-ts/spec";
258
+ declare function toMarkdown2(spec: OpenPkg4, options?: ExportMarkdownOptions): string;
259
+ import { OpenPkg as OpenPkg5, SpecExportKind as SpecExportKind2 } from "@openpkg-ts/spec";
217
260
  type NavFormat = "fumadocs" | "docusaurus" | "generic";
218
261
  type GroupBy = "kind" | "module" | "tag" | "none";
219
262
  interface NavOptions {
@@ -288,7 +331,7 @@ type DocusaurusSidebar = DocusaurusSidebarItem[];
288
331
  * const sidebar = docs.toNavigation({ format: 'docusaurus' })
289
332
  * ```
290
333
  */
291
- declare function toNavigation2(spec: OpenPkg4, options?: NavOptions): GenericNav | FumadocsMeta | DocusaurusSidebar;
334
+ declare function toNavigation2(spec: OpenPkg5, options?: NavOptions): GenericNav | FumadocsMeta | DocusaurusSidebar;
292
335
  /**
293
336
  * Generate Fumadocs meta.json file content.
294
337
  *
@@ -302,7 +345,7 @@ declare function toNavigation2(spec: OpenPkg4, options?: NavOptions): GenericNav
302
345
  * fs.writeFileSync('docs/api/meta.json', meta)
303
346
  * ```
304
347
  */
305
- declare function toFumadocsMetaJSON(spec: OpenPkg4, options?: Omit<NavOptions, "format">): string;
348
+ declare function toFumadocsMetaJSON(spec: OpenPkg5, options?: Omit<NavOptions, "format">): string;
306
349
  /**
307
350
  * Generate Docusaurus sidebar config.
308
351
  *
@@ -316,8 +359,8 @@ declare function toFumadocsMetaJSON(spec: OpenPkg4, options?: Omit<NavOptions, "
316
359
  * fs.writeFileSync('sidebars.js', sidebar)
317
360
  * ```
318
361
  */
319
- declare function toDocusaurusSidebarJS(spec: OpenPkg4, options?: Omit<NavOptions, "format">): string;
320
- import { OpenPkg as OpenPkg5, SpecExportKind as SpecExportKind3 } from "@openpkg-ts/spec";
362
+ declare function toDocusaurusSidebarJS(spec: OpenPkg5, options?: Omit<NavOptions, "format">): string;
363
+ import { OpenPkg as OpenPkg6, SpecExportKind as SpecExportKind3 } from "@openpkg-ts/spec";
321
364
  interface SearchOptions {
322
365
  /** Base URL for search result links */
323
366
  baseUrl?: string;
@@ -410,7 +453,7 @@ interface SearchIndex {
410
453
  * // { records: [...], version: '1.0.0', packageName: 'my-lib' }
411
454
  * ```
412
455
  */
413
- declare function toSearchIndex2(spec: OpenPkg5, options?: SearchOptions): SearchIndex;
456
+ declare function toSearchIndex2(spec: OpenPkg6, options?: SearchOptions): SearchIndex;
414
457
  /**
415
458
  * Generate Pagefind-compatible records.
416
459
  *
@@ -426,7 +469,7 @@ declare function toSearchIndex2(spec: OpenPkg5, options?: SearchOptions): Search
426
469
  * })
427
470
  * ```
428
471
  */
429
- declare function toPagefindRecords2(spec: OpenPkg5, options?: SearchOptions): PagefindRecord[];
472
+ declare function toPagefindRecords2(spec: OpenPkg6, options?: SearchOptions): PagefindRecord[];
430
473
  /**
431
474
  * Generate Algolia-compatible records.
432
475
  *
@@ -440,7 +483,7 @@ declare function toPagefindRecords2(spec: OpenPkg5, options?: SearchOptions): Pa
440
483
  * // Upload to Algolia index
441
484
  * ```
442
485
  */
443
- declare function toAlgoliaRecords2(spec: OpenPkg5, options?: SearchOptions): AlgoliaRecord[];
486
+ declare function toAlgoliaRecords2(spec: OpenPkg6, options?: SearchOptions): AlgoliaRecord[];
444
487
  /**
445
488
  * Serialize search index to JSON string.
446
489
  *
@@ -454,36 +497,36 @@ declare function toAlgoliaRecords2(spec: OpenPkg5, options?: SearchOptions): Alg
454
497
  * fs.writeFileSync('search-index.json', json)
455
498
  * ```
456
499
  */
457
- declare function toSearchIndexJSON(spec: OpenPkg5, options?: SearchOptions & {
500
+ declare function toSearchIndexJSON(spec: OpenPkg6, options?: SearchOptions & {
458
501
  pretty?: boolean;
459
502
  }): string;
460
503
  interface LoadOptions {
461
504
  /** Path to openpkg.json file or the spec object directly */
462
- input: string | OpenPkg6;
505
+ input: string | OpenPkg7;
463
506
  }
464
507
  interface DocsInstance {
465
508
  /** The parsed OpenPkg spec */
466
- spec: OpenPkg6;
509
+ spec: OpenPkg7;
467
510
  /** Get an by its ID */
468
- getExport(id: string): SpecExport2 | undefined;
511
+ getExport(id: string): SpecExport3 | undefined;
469
512
  /** Get a type definition by its ID */
470
513
  getType(id: string): SpecType | undefined;
471
514
  /** Get all exports of a specific kind */
472
- getExportsByKind(kind: SpecExportKind4): SpecExport2[];
515
+ getExportsByKind(kind: SpecExportKind4): SpecExport3[];
473
516
  /** Get all exports */
474
- getAllExports(): SpecExport2[];
517
+ getAllExports(): SpecExport3[];
475
518
  /** Get all type definitions */
476
519
  getAllTypes(): SpecType[];
477
520
  /** Get exports by JSDoc tag (e.g., '@beta', '@internal') */
478
- getExportsByTag(tagName: string): SpecExport2[];
521
+ getExportsByTag(tagName: string): SpecExport3[];
479
522
  /** Search exports by name or description */
480
- search(query: string): SpecExport2[];
523
+ search(query: string): SpecExport3[];
481
524
  /** Get exports belonging to a specific module/namespace */
482
- getModule(moduleName: string): SpecExport2[];
525
+ getModule(moduleName: string): SpecExport3[];
483
526
  /** Get deprecated exports */
484
- getDeprecated(): SpecExport2[];
527
+ getDeprecated(): SpecExport3[];
485
528
  /** Get exports grouped by kind */
486
- groupByKind(): Record<SpecExportKind4, SpecExport2[]>;
529
+ groupByKind(): Record<SpecExportKind4, SpecExport3[]>;
487
530
  /** Render spec or single to MDX */
488
531
  toMarkdown(options?: ExportMarkdownOptions): string;
489
532
  /** Render spec or single to HTML */
@@ -511,7 +554,7 @@ interface DocsInstance {
511
554
  * const docs = loadSpec(spec)
512
555
  * ```
513
556
  */
514
- declare function loadSpec(spec: OpenPkg6): DocsInstance;
557
+ declare function loadSpec(spec: OpenPkg7): DocsInstance;
515
558
  /**
516
559
  * Creates a docs instance for querying and rendering API documentation.
517
560
  *
@@ -533,11 +576,13 @@ declare function loadSpec(spec: OpenPkg6): DocsInstance;
533
576
  * docs.search('hook')
534
577
  * ```
535
578
  */
536
- declare function createDocs(input: string | OpenPkg6): DocsInstance;
537
- import { OpenPkg as OpenPkg7, SpecExport as SpecExport3, SpecMember as SpecMember2, SpecSchema, SpecSignature, SpecType as SpecType2, SpecTypeParameter } from "@openpkg-ts/spec";
579
+ declare function createDocs(input: string | OpenPkg7): DocsInstance;
580
+ import { OpenPkg as OpenPkg8, SpecExport as SpecExport4, SpecMember as SpecMember2, SpecSchema, SpecSignature, SpecType as SpecType2, SpecTypeParameter } from "@openpkg-ts/spec";
538
581
  interface FormatSchemaOptions {
539
582
  /** Include package attribution for external types */
540
583
  includePackage?: boolean;
584
+ /** Collapse unions with more than N members (default: no collapse) */
585
+ collapseUnionThreshold?: number;
541
586
  }
542
587
  /**
543
588
  * Format a schema to a human-readable type string.
@@ -613,7 +658,7 @@ declare function formatReturnType(sig?: SpecSignature): string;
613
658
  * // 'class Logger extends EventEmitter'
614
659
  * ```
615
660
  */
616
- declare function buildSignatureString(exp: SpecExport3, sigIndex?: number): string;
661
+ declare function buildSignatureString(exp: SpecExport4, sigIndex?: number): string;
617
662
  /**
618
663
  * Resolve a type reference to its definition.
619
664
  *
@@ -627,7 +672,7 @@ declare function buildSignatureString(exp: SpecExport3, sigIndex?: number): stri
627
672
  * // { id: 'User', name: 'User', kind: 'interface', ... }
628
673
  * ```
629
674
  */
630
- declare function resolveTypeRef(ref: string, spec: OpenPkg7): SpecType2 | undefined;
675
+ declare function resolveTypeRef(ref: string, spec: OpenPkg8): SpecType2 | undefined;
631
676
  /**
632
677
  * Check if a member is a method (has signatures).
633
678
  *
@@ -742,7 +787,49 @@ declare function formatConditionalType(condType: SpecConditionalType): string;
742
787
  * ```
743
788
  */
744
789
  declare function formatMappedType(mappedType: SpecMappedType): string;
745
- import { SpecExport as SpecExport4, SpecType as SpecType3 } from "@openpkg-ts/spec";
790
+ import { OpenPkg as OpenPkg9, SpecExportKind as SpecExportKind5 } from "@openpkg-ts/spec";
791
+ type FilterCriteria = {
792
+ /** Filter by kinds */
793
+ kinds?: SpecExportKind5[];
794
+ /** Filter by names (exact match) */
795
+ names?: string[];
796
+ /** Filter by IDs */
797
+ ids?: string[];
798
+ /** Filter by tags (must have at least one matching tag) */
799
+ tags?: string[];
800
+ /** Filter by deprecation status */
801
+ deprecated?: boolean;
802
+ /** Filter by whether has a description */
803
+ hasDescription?: boolean;
804
+ /** Search term (matches name or description, case-insensitive) */
805
+ search?: string;
806
+ /** Filter by module path (source.file contains this) */
807
+ module?: string;
808
+ /** Also search member names/descriptions (requires search) */
809
+ searchMembers?: boolean;
810
+ /** Also search docs: param descriptions, return descriptions, examples (requires search) */
811
+ searchDocs?: boolean;
812
+ };
813
+ type FilterResult = {
814
+ /** New spec with only matched exports (immutable) */
815
+ spec: OpenPkg9;
816
+ /** Number of exports that matched */
817
+ matched: number;
818
+ /** Total number of exports in original spec */
819
+ total: number;
820
+ };
821
+ /**
822
+ * Filter a spec by various criteria.
823
+ * Returns a new spec with only matched exports (never mutates input).
824
+ * Uses AND logic: all specified criteria must match.
825
+ * Types are always preserved (no pruning).
826
+ *
827
+ * @param spec - The spec to filter
828
+ * @param criteria - Filter criteria (empty criteria matches all)
829
+ * @returns FilterResult with new spec, matched count, total count
830
+ */
831
+ declare function filterSpec(spec: OpenPkg9, criteria: FilterCriteria): FilterResult;
832
+ import { SpecExport as SpecExport5, SpecType as SpecType3 } from "@openpkg-ts/spec";
746
833
  interface GetExportOptions {
747
834
  /** Entry point file path */
748
835
  entryFile: string;
@@ -757,7 +844,7 @@ interface GetExportOptions {
757
844
  }
758
845
  interface GetExportResult {
759
846
  /** The spec, or null if not found */
760
- export: SpecExport4 | null;
847
+ export: SpecExport5 | null;
761
848
  /** Related types referenced by the */
762
849
  types: SpecType3[];
763
850
  /** Errors encountered */
@@ -798,7 +885,7 @@ interface ListExportsResult {
798
885
  * List all exports from a TypeScript entry point
799
886
  */
800
887
  declare function listExports(options: ListExportsOptions): Promise<ListExportsResult>;
801
- import { OpenPkg as OpenPkg8 } from "@openpkg-ts/spec";
888
+ import { OpenPkg as OpenPkg10 } from "@openpkg-ts/spec";
802
889
  interface ExtractOptions {
803
890
  entryFile: string;
804
891
  baseDir?: string;
@@ -819,9 +906,11 @@ interface ExtractOptions {
819
906
  onProgress?: (current: number, total: number, item: string) => void;
820
907
  /** Whether source is a .d.ts file (degraded mode - TSDoc may be missing) */
821
908
  isDtsSource?: boolean;
909
+ /** Include private/protected class members (default: false) */
910
+ includePrivate?: boolean;
822
911
  }
823
912
  interface ExtractResult {
824
- spec: OpenPkg8;
913
+ spec: OpenPkg10;
825
914
  diagnostics: Diagnostic[];
826
915
  forgottenExports?: ForgottenExport[];
827
916
  /** Metadata about runtime schema extraction (when schemaExtraction: 'hybrid') */
@@ -939,6 +1028,8 @@ interface SerializerContext {
939
1028
  visitedTypes: Set<ts.Type>;
940
1029
  /** Flag to indicate we're processing tuple elements - skip Array prototype methods */
941
1030
  inTupleElement?: boolean;
1031
+ /** Include private/protected class members (default: false) */
1032
+ includePrivate?: boolean;
942
1033
  }
943
1034
  declare class TypeRegistry {
944
1035
  private types;
@@ -1002,8 +1093,12 @@ type DeclarationWithTypeParams = ts4.FunctionDeclaration | ts4.ClassDeclaration
1002
1093
  declare function extractTypeParameters(node: DeclarationWithTypeParams, checker: ts4.TypeChecker): SpecTypeParameter2[] | undefined;
1003
1094
  /**
1004
1095
  * Check if a symbol is marked as deprecated via @deprecated JSDoc tag.
1096
+ * Returns deprecation status and optional reason text.
1005
1097
  */
1006
- declare function isSymbolDeprecated(symbol: ts4.Symbol | undefined): boolean;
1098
+ declare function isSymbolDeprecated(symbol: ts4.Symbol | undefined): {
1099
+ deprecated: boolean;
1100
+ reason?: string;
1101
+ };
1007
1102
  /**
1008
1103
  * Target version for JSON Schema generation.
1009
1104
  * @see https://standardschema.dev/json-schema
@@ -1227,24 +1322,24 @@ declare const arktypeAdapter: SchemaAdapter;
1227
1322
  declare const typeboxAdapter: SchemaAdapter;
1228
1323
  declare const valibotAdapter: SchemaAdapter;
1229
1324
  declare const zodAdapter: SchemaAdapter;
1230
- import { SpecExport as SpecExport6 } from "@openpkg-ts/spec";
1231
- import ts6 from "typescript";
1232
- declare function serializeClass(node: ts6.ClassDeclaration, ctx: SerializerContext): SpecExport6 | null;
1233
1325
  import { SpecExport as SpecExport7 } from "@openpkg-ts/spec";
1234
- import ts7 from "typescript";
1235
- declare function serializeEnum(node: ts7.EnumDeclaration, ctx: SerializerContext): SpecExport7 | null;
1326
+ import ts6 from "typescript";
1327
+ declare function serializeClass(node: ts6.ClassDeclaration, ctx: SerializerContext): SpecExport7 | null;
1236
1328
  import { SpecExport as SpecExport8 } from "@openpkg-ts/spec";
1237
- import ts8 from "typescript";
1238
- declare function serializeFunctionExport(node: ts8.FunctionDeclaration | ts8.ArrowFunction, ctx: SerializerContext): SpecExport8 | null;
1329
+ import ts7 from "typescript";
1330
+ declare function serializeEnum(node: ts7.EnumDeclaration, ctx: SerializerContext): SpecExport8 | null;
1239
1331
  import { SpecExport as SpecExport9 } from "@openpkg-ts/spec";
1240
- import ts9 from "typescript";
1241
- declare function serializeInterface(node: ts9.InterfaceDeclaration, ctx: SerializerContext): SpecExport9 | null;
1332
+ import ts8 from "typescript";
1333
+ declare function serializeFunctionExport(node: ts8.FunctionDeclaration | ts8.ArrowFunction, ctx: SerializerContext): SpecExport9 | null;
1242
1334
  import { SpecExport as SpecExport10 } from "@openpkg-ts/spec";
1243
- import ts10 from "typescript";
1244
- declare function serializeTypeAlias(node: ts10.TypeAliasDeclaration, ctx: SerializerContext): SpecExport10 | null;
1335
+ import ts9 from "typescript";
1336
+ declare function serializeInterface(node: ts9.InterfaceDeclaration, ctx: SerializerContext): SpecExport10 | null;
1245
1337
  import { SpecExport as SpecExport11 } from "@openpkg-ts/spec";
1338
+ import ts10 from "typescript";
1339
+ declare function serializeTypeAlias(node: ts10.TypeAliasDeclaration, ctx: SerializerContext): SpecExport11 | null;
1340
+ import { SpecExport as SpecExport12 } from "@openpkg-ts/spec";
1246
1341
  import ts11 from "typescript";
1247
- declare function serializeVariable(node: ts11.VariableDeclaration, statement: ts11.VariableStatement, ctx: SerializerContext): SpecExport11 | null;
1342
+ declare function serializeVariable(node: ts11.VariableDeclaration, statement: ts11.VariableStatement, ctx: SerializerContext): SpecExport12 | null;
1248
1343
  import { SpecSignatureParameter } from "@openpkg-ts/spec";
1249
1344
  import ts12 from "typescript";
1250
1345
  declare function extractParameters(signature: ts12.Signature, ctx: SerializerContext): SpecSignatureParameter[];
@@ -1321,7 +1416,7 @@ declare function deduplicateSchemas(schemas: SpecSchema2[]): SpecSchema2[];
1321
1416
  * A valid discriminator has a unique literal value in each union member.
1322
1417
  */
1323
1418
  declare function findDiscriminatorProperty(unionTypes: ts13.Type[], checker: ts13.TypeChecker): string | undefined;
1324
- import { SpecExport as SpecExport12, SpecMember as SpecMember3, SpecSchema as SpecSchema3, SpecType as SpecType5 } from "@openpkg-ts/spec";
1419
+ import { SpecExport as SpecExport13, SpecMember as SpecMember3, SpecSchema as SpecSchema3, SpecType as SpecType5 } from "@openpkg-ts/spec";
1325
1420
  /**
1326
1421
  * Options for schema normalization
1327
1422
  */
@@ -1352,7 +1447,7 @@ declare function normalizeSchema(schema: SpecSchema3, options?: NormalizeOptions
1352
1447
  * 2. Normalize member schemas
1353
1448
  * 3. Generate a JSON Schema from members if members exist (populates `schema` field)
1354
1449
  */
1355
- declare function normalizeExport(exp: SpecExport12, options?: NormalizeOptions): SpecExport12;
1450
+ declare function normalizeExport(exp: SpecExport13, options?: NormalizeOptions): SpecExport13;
1356
1451
  /**
1357
1452
  * Normalize a SpecType, normalizing its schema and nested schemas.
1358
1453
  *
@@ -1386,4 +1481,4 @@ declare function normalizeMembers(members: SpecMember3[], options?: NormalizeOpt
1386
1481
  import ts14 from "typescript";
1387
1482
  declare function isExported(node: ts14.Node): boolean;
1388
1483
  declare function getNodeName(node: ts14.Node): string | undefined;
1389
- export { zodAdapter, withDescription, valibotAdapter, typeboxAdapter, toSearchIndexJSON, toSearchIndex2 as toSearchIndex, toPagefindRecords2 as toPagefindRecords, toNavigation2 as toNavigation, toMarkdown2 as toMarkdown, toJSONString, toJSON2 as toJSON, toHTML2 as toHTML, toFumadocsMetaJSON, toDocusaurusSidebarJS, toAlgoliaRecords2 as toAlgoliaRecords, sortByName, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, schemasAreEqual, schemaIsAny, resolveTypeRef, resolveExportTarget, resolveCompiledPath, registerReferencedTypes, registerAdapter, recommendSemverBump, normalizeType, normalizeSchema, normalizeMembers, normalizeExport, loadSpec, listExports, isTypeReference, isTypeOnlyExport, isSymbolDeprecated, isStandardJSONSchema, isSchemaType, isPureRefSchema, isProperty, isPrimitiveName, isMethod, isExported, isBuiltinGeneric, isAnonymous, groupByVisibility, getTypeOrigin, getSourceLocation, getProperties, getParamDescription, getNonNullableType, getNodeName, getMethods, getMemberBadges, getJSDocComment, getExport2 as getExport, toMarkdown2 as generateDocs, formatTypeParameters, formatSchema, formatReturnType, formatParameters, formatMappedType, formatConditionalType, formatBadges, findDiscriminatorProperty, findAdapter, extractTypeParameters, extractStandardSchemasFromTs, extractStandardSchemasFromProject, extractStandardSchemas, extractSpec, extractSchemaType, extractParameters, extract, exportToMarkdown, ensureNonEmptySchema, diffSpec2 as diffSpecs, diffSpec, detectTsRuntime, deduplicateSchemas, createProgram, createDocs, categorizeBreakingChanges, calculateNextVersion, buildSignatureString, buildSchema, arktypeAdapter, TypeRegistry, TypeReference2 as TypeReference, TsRuntime, StandardSchemaExtractionResult, StandardSchemaExtractionOutput, StandardJSONSchemaV1, StandardJSONSchemaTarget, StandardJSONSchemaOptions, SpecMappedType, SpecDiff, SpecConditionalType, SimplifiedSpec, SimplifiedSignature, SimplifiedReturn, SimplifiedParameter, SimplifiedMember, SimplifiedExport, SimplifiedExample, SerializerContext, SemverRecommendation, SemverBump, SearchRecord, SearchOptions, SearchIndex, SchemaExtractionResult, SchemaAdapter, ProjectExtractionOutput, ProjectExtractionInfo, ProgramResult, ProgramOptions, PagefindRecord, NormalizeOptions, NavOptions, NavItem, NavGroup, NavFormat, MemberChangeInfo, MarkdownOptions, LoadOptions, ListExportsResult, ListExportsOptions, JSONSchema, JSONOptions, HTMLOptions, GroupBy, GetExportResult, GetExportOptions, GenericNav, FumadocsMetaItem, FumadocsMeta, FormatSchemaOptions, ForgottenExport, ExtractStandardSchemasOptions, ExtractResult, ExtractOptions, ExtractFromProjectOptions, ExportVerification, ExportTracker, ExportMarkdownOptions, ExportItem, DocusaurusSidebarItem, DocusaurusSidebar, DocsInstance, Diagnostic, CategorizedBreaking, BreakingSeverity, BUILTIN_TYPE_SCHEMAS, AlgoliaRecord, ARRAY_PROTOTYPE_METHODS };
1484
+ export { zodAdapter, withDescription, valibotAdapter, typeboxAdapter, toSearchIndexJSON, toSearchIndex2 as toSearchIndex, toPagefindRecords2 as toPagefindRecords, toNavigation2 as toNavigation, toMarkdown2 as toMarkdown, toJSONString, toJSON2 as toJSON, toHTML2 as toHTML, toFumadocsMetaJSON, toDocusaurusSidebarJS, toAlgoliaRecords2 as toAlgoliaRecords, sortByName, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, schemasAreEqual, schemaIsAny, resolveTypeRef, resolveExportTarget, resolveCompiledPath, registerReferencedTypes, registerAdapter, recommendSemverBump, normalizeType, normalizeSchema, normalizeMembers, normalizeExport, loadSpec, listExports, isTypeReference, isTypeOnlyExport, isSymbolDeprecated, isStandardJSONSchema, isSchemaType, isPureRefSchema, isProperty, isPrimitiveName, isMethod, isExported, isBuiltinGeneric, isAnonymous, hasDeprecatedTag, groupByVisibility, getTypeOrigin, getSourceLocation, getProperties, getParamDescription, getNonNullableType, getNodeName, getMethods, getMemberBadges, getJSDocComment, getExport2 as getExport, getDeprecationMessage, toMarkdown2 as generateDocs, formatTypeParameters, formatSchema, formatReturnType, formatParameters, formatMappedType, formatConditionalType, formatBadges, findMissingParamDocs, findDiscriminatorProperty, findAdapter, filterSpec, extractTypeParameters, extractStandardSchemasFromTs, extractStandardSchemasFromProject, extractStandardSchemas, extractSpec, extractSchemaType, extractParameters, extract, exportToMarkdown, ensureNonEmptySchema, diffSpec2 as diffSpecs, diffSpec, detectTsRuntime, deduplicateSchemas, createProgram, createDocs, categorizeBreakingChanges, calculateNextVersion, buildSignatureString, buildSchema, arktypeAdapter, analyzeSpec, TypeRegistry, TypeReference2 as TypeReference, TsRuntime, StandardSchemaExtractionResult, StandardSchemaExtractionOutput, StandardJSONSchemaV1, StandardJSONSchemaTarget, StandardJSONSchemaOptions, SpecMappedType, SpecDiff, SpecDiagnostics, SpecConditionalType, SimplifiedSpec, SimplifiedSignature, SimplifiedReturn, SimplifiedParameter, SimplifiedMember, SimplifiedExport, SimplifiedExample, SerializerContext, SemverRecommendation, SemverBump, SearchRecord, SearchOptions, SearchIndex, SchemaExtractionResult, SchemaAdapter, ProjectExtractionOutput, ProjectExtractionInfo, ProgramResult, ProgramOptions, PagefindRecord, NormalizeOptions, NavOptions, NavItem, NavGroup, NavFormat, MemberChangeInfo, MarkdownOptions, LoadOptions, ListExportsResult, ListExportsOptions, JSONSchema, JSONOptions, HTMLOptions, GroupBy, GetExportResult, GetExportOptions, GenericNav, FumadocsMetaItem, FumadocsMeta, FormatSchemaOptions, ForgottenExport, FilterResult, FilterCriteria, ExtractStandardSchemasOptions, ExtractResult, ExtractOptions, ExtractFromProjectOptions, ExportVerification, ExportTracker, ExportMarkdownOptions, ExportItem, DocusaurusSidebarItem, DocusaurusSidebar, DocsInstance, DiagnosticItem, Diagnostic, CategorizedBreaking, BreakingSeverity, BUILTIN_TYPE_SCHEMAS, AlgoliaRecord, ARRAY_PROTOTYPE_METHODS };
package/dist/index.js CHANGED
@@ -6,6 +6,82 @@ import {
6
6
  diffSpec as diffSpec2,
7
7
  recommendSemverBump
8
8
  } from "@openpkg-ts/spec";
9
+ // src/core/diagnostics.ts
10
+ function hasDeprecatedTag(exp) {
11
+ if (exp.deprecated === true)
12
+ return true;
13
+ return exp.tags?.some((t) => t.name === "deprecated" || t.name === "@deprecated") ?? false;
14
+ }
15
+ function getDeprecationMessage(exp) {
16
+ const tag = exp.tags?.find((t) => t.name === "deprecated" || t.name === "@deprecated");
17
+ if (tag?.text.trim()) {
18
+ return tag.text.trim();
19
+ }
20
+ return;
21
+ }
22
+ function findMissingParamDocs(exp) {
23
+ const missing = [];
24
+ for (const sig of exp.signatures ?? []) {
25
+ for (const param of sig.parameters ?? []) {
26
+ if (!param.description?.trim()) {
27
+ missing.push(param.name);
28
+ }
29
+ }
30
+ }
31
+ return missing;
32
+ }
33
+ function checkMemberDescriptions(exp, members) {
34
+ const items = [];
35
+ for (const member of members) {
36
+ if (!member.description?.trim() && member.name) {
37
+ items.push({
38
+ exportId: exp.id,
39
+ exportName: exp.name,
40
+ issue: "member missing description",
41
+ member: member.name
42
+ });
43
+ }
44
+ }
45
+ return items;
46
+ }
47
+ function analyzeSpec(spec) {
48
+ const missingDescriptions = [];
49
+ const deprecatedNoReason = [];
50
+ const missingParamDocs = [];
51
+ for (const exp of spec.exports) {
52
+ if (!exp.description?.trim()) {
53
+ missingDescriptions.push({
54
+ exportId: exp.id,
55
+ exportName: exp.name,
56
+ issue: "missing description"
57
+ });
58
+ }
59
+ if (exp.members) {
60
+ missingDescriptions.push(...checkMemberDescriptions(exp, exp.members));
61
+ }
62
+ if (hasDeprecatedTag(exp) && !getDeprecationMessage(exp)) {
63
+ deprecatedNoReason.push({
64
+ exportId: exp.id,
65
+ exportName: exp.name,
66
+ issue: "deprecated without reason"
67
+ });
68
+ }
69
+ const missingParams = findMissingParamDocs(exp);
70
+ for (const param of missingParams) {
71
+ missingParamDocs.push({
72
+ exportId: exp.id,
73
+ exportName: exp.name,
74
+ issue: "param missing description",
75
+ param
76
+ });
77
+ }
78
+ }
79
+ return {
80
+ missingDescriptions,
81
+ deprecatedNoReason,
82
+ missingParamDocs
83
+ };
84
+ }
9
85
  // src/core/format.ts
10
86
  function getMemberBadges(member) {
11
87
  const badges = [];
@@ -76,7 +152,15 @@ function formatSchema(schema, options) {
76
152
  return withPackage(baseName);
77
153
  }
78
154
  if ("anyOf" in schema && Array.isArray(schema.anyOf)) {
79
- return schema.anyOf.map((s) => formatSchema(s, options)).join(" | ");
155
+ const threshold = options?.collapseUnionThreshold;
156
+ const members = schema.anyOf;
157
+ if (threshold && members.length > threshold) {
158
+ const shown = members.slice(0, 3);
159
+ const remaining = members.length - 3;
160
+ const shownStr = shown.map((s) => formatSchema(s, options)).join(" | ");
161
+ return `${shownStr} | ... (${remaining} more)`;
162
+ }
163
+ return members.map((s) => formatSchema(s, options)).join(" | ");
80
164
  }
81
165
  if ("allOf" in schema && Array.isArray(schema.allOf)) {
82
166
  return schema.allOf.map((s) => formatSchema(s, options)).join(" & ");
@@ -519,10 +603,15 @@ function toHTML(spec, options = {}) {
519
603
  </body>
520
604
  </html>`;
521
605
  }
606
+ let specExports = spec.exports;
607
+ if (options.exports?.length) {
608
+ const ids = new Set(options.exports);
609
+ specExports = spec.exports.filter((e) => ids.has(e.name) || ids.has(e.id));
610
+ }
522
611
  const title = options.title || `${spec.meta.name} API Reference`;
523
612
  const description = spec.meta.description ? `<p>${escapeHTML(spec.meta.description)}</p>` : "";
524
613
  const byKind = {};
525
- for (const exp of spec.exports) {
614
+ for (const exp of specExports) {
526
615
  if (!byKind[exp.kind])
527
616
  byKind[exp.kind] = [];
528
617
  byKind[exp.kind].push(exp);
@@ -665,7 +754,12 @@ function toJSON(spec, options = {}) {
665
754
  }
666
755
  return simplifyExport(exp);
667
756
  }
668
- const exports = spec.exports.map(simplifyExport);
757
+ let specExports = spec.exports;
758
+ if (options.exports?.length) {
759
+ const ids = new Set(options.exports);
760
+ specExports = spec.exports.filter((e) => ids.has(e.name) || ids.has(e.id));
761
+ }
762
+ const exports = specExports.map(simplifyExport);
669
763
  const byKind = {};
670
764
  for (const exp of exports) {
671
765
  if (!byKind[exp.kind])
@@ -739,12 +833,12 @@ function heading(level, text, offset = 0) {
739
833
  const actualLevel = Math.min(level + offset, 6);
740
834
  return `${"#".repeat(actualLevel)} ${text}`;
741
835
  }
742
- function renderParameters2(sig, offset = 0) {
836
+ function renderParameters2(sig, offset = 0, schemaOpts) {
743
837
  if (!sig?.parameters?.length)
744
838
  return "";
745
839
  const lines = [heading(2, "Parameters", offset), ""];
746
840
  for (const param of sig.parameters) {
747
- const type = formatSchema(param.schema);
841
+ const type = formatSchema(param.schema, schemaOpts);
748
842
  const required = param.required !== false ? "" : "?";
749
843
  const rest = param.rest ? "..." : "";
750
844
  lines.push(`### \`${rest}${param.name}${required}\``);
@@ -763,11 +857,11 @@ function renderParameters2(sig, offset = 0) {
763
857
  return lines.join(`
764
858
  `);
765
859
  }
766
- function renderReturns2(sig, offset = 0) {
860
+ function renderReturns2(sig, offset = 0, schemaOpts) {
767
861
  if (!sig?.returns)
768
862
  return "";
769
863
  const lines = [heading(2, "Returns", offset), ""];
770
- const type = formatSchema(sig.returns.schema);
864
+ const type = formatSchema(sig.returns.schema, schemaOpts);
771
865
  lines.push(`**Type:** \`${type}\``);
772
866
  if (sig.returns.description) {
773
867
  lines.push("");
@@ -819,13 +913,13 @@ function renderExamples2(examples, offset = 0) {
819
913
  return lines.join(`
820
914
  `);
821
915
  }
822
- function renderProperties2(members, offset = 0) {
916
+ function renderProperties2(members, offset = 0, schemaOpts) {
823
917
  const props = getProperties(members);
824
918
  if (!props.length)
825
919
  return "";
826
920
  const lines = [heading(2, "Properties", offset), ""];
827
921
  for (const prop of props) {
828
- const type = formatSchema(prop.schema);
922
+ const type = formatSchema(prop.schema, schemaOpts);
829
923
  lines.push(`### \`${prop.name}\``);
830
924
  lines.push("");
831
925
  if (prop.decorators?.length) {
@@ -858,7 +952,7 @@ function renderProperties2(members, offset = 0) {
858
952
  return lines.join(`
859
953
  `);
860
954
  }
861
- function renderMethods2(members, offset = 0) {
955
+ function renderMethods2(members, offset = 0, schemaOpts) {
862
956
  const methods = getMethods(members);
863
957
  if (!methods.length)
864
958
  return "";
@@ -895,14 +989,14 @@ function renderMethods2(members, offset = 0) {
895
989
  lines.push("**Parameters:**");
896
990
  lines.push("");
897
991
  for (const param of sig.parameters) {
898
- const paramType = formatSchema(param.schema);
992
+ const paramType = formatSchema(param.schema, schemaOpts);
899
993
  const desc = param.description ? ` - ${param.description}` : "";
900
994
  lines.push(`- \`${param.name}\`: \`${paramType}\`${desc}`);
901
995
  }
902
996
  lines.push("");
903
997
  }
904
998
  if (sig?.returns) {
905
- const retType = formatSchema(sig.returns.schema);
999
+ const retType = formatSchema(sig.returns.schema, schemaOpts);
906
1000
  const desc = sig.returns.description ? ` - ${sig.returns.description}` : "";
907
1001
  lines.push(`**Returns:** \`${retType}\`${desc}`);
908
1002
  lines.push("");
@@ -929,6 +1023,7 @@ function renderEnumMembers2(members, offset = 0) {
929
1023
  function exportToMarkdown(exp, options = {}) {
930
1024
  const sections = { ...defaultSections, ...options.sections };
931
1025
  const offset = options.headingOffset ?? 0;
1026
+ const schemaOpts = options.collapseUnionThreshold ? { collapseUnionThreshold: options.collapseUnionThreshold } : undefined;
932
1027
  const parts = [];
933
1028
  if (options.frontmatter !== false) {
934
1029
  parts.push(generateFrontmatter(exp, options.customFrontmatter));
@@ -976,24 +1071,25 @@ function exportToMarkdown(exp, options = {}) {
976
1071
  parts.push("");
977
1072
  }
978
1073
  if (exp.deprecated) {
979
- parts.push("> **Deprecated**");
1074
+ const reason = "deprecationReason" in exp && exp.deprecationReason ? `: ${exp.deprecationReason}` : "";
1075
+ parts.push(`> **Deprecated**${reason}`);
980
1076
  parts.push("");
981
1077
  }
982
1078
  const primarySig = exp.signatures?.[0];
983
1079
  switch (exp.kind) {
984
1080
  case "function":
985
1081
  if (sections.parameters)
986
- parts.push(renderParameters2(primarySig, offset));
1082
+ parts.push(renderParameters2(primarySig, offset, schemaOpts));
987
1083
  if (sections.returns)
988
- parts.push(renderReturns2(primarySig, offset));
1084
+ parts.push(renderReturns2(primarySig, offset, schemaOpts));
989
1085
  parts.push(renderThrows2(primarySig, offset));
990
1086
  break;
991
1087
  case "class":
992
1088
  case "interface":
993
1089
  if (sections.properties)
994
- parts.push(renderProperties2(exp.members, offset));
1090
+ parts.push(renderProperties2(exp.members, offset, schemaOpts));
995
1091
  if (sections.methods)
996
- parts.push(renderMethods2(exp.members, offset));
1092
+ parts.push(renderMethods2(exp.members, offset, schemaOpts));
997
1093
  break;
998
1094
  case "enum":
999
1095
  if (sections.members)
@@ -1018,6 +1114,13 @@ function toMarkdown(spec, options = {}) {
1018
1114
  }
1019
1115
  return exportToMarkdown(exp, options);
1020
1116
  }
1117
+ let specExports = spec.exports;
1118
+ if (options.exports?.length) {
1119
+ const ids = new Set(options.exports);
1120
+ specExports = spec.exports.filter((e) => ids.has(e.name) || ids.has(e.id));
1121
+ if (specExports.length === 0)
1122
+ return "";
1123
+ }
1021
1124
  const parts = [];
1022
1125
  if (options.frontmatter !== false) {
1023
1126
  const frontmatter = {
@@ -1044,7 +1147,7 @@ function toMarkdown(spec, options = {}) {
1044
1147
  parts.push("");
1045
1148
  }
1046
1149
  const byKind = {};
1047
- for (const exp of spec.exports) {
1150
+ for (const exp of specExports) {
1048
1151
  if (!byKind[exp.kind])
1049
1152
  byKind[exp.kind] = [];
1050
1153
  byKind[exp.kind].push(exp);
@@ -1515,6 +1618,109 @@ function extractModuleName(exp) {
1515
1618
  }
1516
1619
  return;
1517
1620
  }
1621
+ // src/primitives/filter.ts
1622
+ function matchesExport(exp, criteria) {
1623
+ if (criteria.kinds && criteria.kinds.length > 0) {
1624
+ if (!criteria.kinds.includes(exp.kind))
1625
+ return false;
1626
+ }
1627
+ if (criteria.names && criteria.names.length > 0) {
1628
+ if (!criteria.names.includes(exp.name))
1629
+ return false;
1630
+ }
1631
+ if (criteria.ids && criteria.ids.length > 0) {
1632
+ if (!criteria.ids.includes(exp.id))
1633
+ return false;
1634
+ }
1635
+ if (criteria.tags && criteria.tags.length > 0) {
1636
+ const expTags = exp.tags?.map((t) => t.name) ?? [];
1637
+ if (!criteria.tags.some((tag) => expTags.includes(tag)))
1638
+ return false;
1639
+ }
1640
+ if (criteria.deprecated !== undefined) {
1641
+ if ((exp.deprecated ?? false) !== criteria.deprecated)
1642
+ return false;
1643
+ }
1644
+ if (criteria.hasDescription !== undefined) {
1645
+ const has = Boolean(exp.description && exp.description.trim().length > 0);
1646
+ if (has !== criteria.hasDescription)
1647
+ return false;
1648
+ }
1649
+ if (criteria.search) {
1650
+ const term = criteria.search.toLowerCase();
1651
+ const nameMatch = exp.name.toLowerCase().includes(term);
1652
+ const descMatch = exp.description?.toLowerCase().includes(term) ?? false;
1653
+ let memberMatch = false;
1654
+ if (criteria.searchMembers && exp.members) {
1655
+ memberMatch = exp.members.some((m) => m.name?.toLowerCase().includes(term) || m.description?.toLowerCase().includes(term));
1656
+ }
1657
+ let docsMatch = false;
1658
+ if (criteria.searchDocs) {
1659
+ for (const sig of exp.signatures ?? []) {
1660
+ for (const param of sig.parameters ?? []) {
1661
+ if (param.description?.toLowerCase().includes(term)) {
1662
+ docsMatch = true;
1663
+ break;
1664
+ }
1665
+ }
1666
+ if (docsMatch)
1667
+ break;
1668
+ if (sig.returns?.description?.toLowerCase().includes(term)) {
1669
+ docsMatch = true;
1670
+ break;
1671
+ }
1672
+ }
1673
+ if (!docsMatch && exp.examples) {
1674
+ for (const ex of exp.examples) {
1675
+ const exText = typeof ex === "string" ? ex : ex.code + (ex.description ?? "");
1676
+ if (exText.toLowerCase().includes(term)) {
1677
+ docsMatch = true;
1678
+ break;
1679
+ }
1680
+ }
1681
+ }
1682
+ }
1683
+ if (!nameMatch && !descMatch && !memberMatch && !docsMatch)
1684
+ return false;
1685
+ }
1686
+ if (criteria.module) {
1687
+ const file = exp.source?.file ?? "";
1688
+ if (!file.includes(criteria.module))
1689
+ return false;
1690
+ }
1691
+ return true;
1692
+ }
1693
+ function filterSpec(spec, criteria) {
1694
+ const total = spec.exports.length;
1695
+ const isEmpty = Object.keys(criteria).length === 0;
1696
+ if (isEmpty) {
1697
+ return {
1698
+ spec: {
1699
+ ...spec,
1700
+ exports: [...spec.exports],
1701
+ types: spec.types ? [...spec.types] : undefined
1702
+ },
1703
+ matched: total,
1704
+ total
1705
+ };
1706
+ }
1707
+ const matched = [];
1708
+ for (const exp of spec.exports) {
1709
+ if (matchesExport(exp, criteria)) {
1710
+ matched.push(exp);
1711
+ }
1712
+ }
1713
+ const newSpec = {
1714
+ ...spec,
1715
+ exports: matched,
1716
+ types: spec.types ? [...spec.types] : undefined
1717
+ };
1718
+ return {
1719
+ spec: newSpec,
1720
+ matched: matched.length,
1721
+ total
1722
+ };
1723
+ }
1518
1724
  // src/primitives/get.ts
1519
1725
  import ts11 from "typescript";
1520
1726
 
@@ -1934,18 +2140,27 @@ function extractTypeParameters(node, checker) {
1934
2140
  }
1935
2141
  function isSymbolDeprecated(symbol) {
1936
2142
  if (!symbol) {
1937
- return false;
2143
+ return { deprecated: false };
1938
2144
  }
1939
2145
  const jsDocTags = symbol.getJsDocTags();
1940
- if (jsDocTags.some((tag) => tag.name.toLowerCase() === "deprecated")) {
1941
- return true;
2146
+ const deprecatedTag = jsDocTags.find((tag) => tag.name.toLowerCase() === "deprecated");
2147
+ if (deprecatedTag) {
2148
+ const reason = deprecatedTag.text?.map((t) => t.text).join("") || undefined;
2149
+ return { deprecated: true, reason };
1942
2150
  }
1943
2151
  for (const declaration of symbol.getDeclarations() ?? []) {
1944
- if (ts2.getJSDocDeprecatedTag(declaration)) {
1945
- return true;
2152
+ const tag = ts2.getJSDocDeprecatedTag(declaration);
2153
+ if (tag) {
2154
+ let reason;
2155
+ if (typeof tag.comment === "string") {
2156
+ reason = tag.comment;
2157
+ } else if (Array.isArray(tag.comment)) {
2158
+ reason = tag.comment.map((c) => typeof c === "string" ? c : c.text).join("");
2159
+ }
2160
+ return { deprecated: true, reason };
1946
2161
  }
1947
2162
  }
1948
- return false;
2163
+ return { deprecated: false };
1949
2164
  }
1950
2165
  function getJSDocForSignature(signature, checker) {
1951
2166
  const decl = signature.getDeclaration();
@@ -3044,7 +3259,8 @@ function createContext(program, sourceFile, options = {}) {
3044
3259
  resolveExternalTypes: options.resolveExternalTypes ?? true,
3045
3260
  typeRegistry: new TypeRegistry,
3046
3261
  exportedIds: new Set,
3047
- visitedTypes: new Set
3262
+ visitedTypes: new Set,
3263
+ includePrivate: options.includePrivate ?? false
3048
3264
  };
3049
3265
  }
3050
3266
  function getInheritedMembers(classType, ownMemberNames, ctx, isStatic = false) {
@@ -3180,7 +3396,7 @@ function serializeClass(node, ctx) {
3180
3396
  const name = symbol?.getName() ?? node.name?.getText();
3181
3397
  if (!name)
3182
3398
  return null;
3183
- const deprecated = isSymbolDeprecated(symbol);
3399
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3184
3400
  const declSourceFile = node.getSourceFile();
3185
3401
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3186
3402
  const source = getSourceLocation(node, declSourceFile);
@@ -3252,7 +3468,7 @@ function serializeClass(node, ctx) {
3252
3468
  signatures: signatures.length > 0 ? signatures : undefined,
3253
3469
  extends: extendsClause,
3254
3470
  implements: implementsClause?.length ? implementsClause : undefined,
3255
- ...deprecated ? { deprecated: true } : {},
3471
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3256
3472
  ...examples.length > 0 ? { examples } : {},
3257
3473
  ...Object.keys(classFlags).length > 0 ? { flags: classFlags } : {}
3258
3474
  };
@@ -3297,8 +3513,9 @@ function serializeProperty(node, ctx) {
3297
3513
  return null;
3298
3514
  const { description, tags } = getJSDocComment(node);
3299
3515
  const visibility = getVisibility(node);
3300
- if (visibility === "private")
3516
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3301
3517
  return null;
3518
+ }
3302
3519
  const type = checker.getTypeAtLocation(node);
3303
3520
  registerReferencedTypes(type, ctx);
3304
3521
  const schema = buildSchema(type, checker, ctx);
@@ -3326,6 +3543,9 @@ function serializeMethod(node, ctx) {
3326
3543
  return null;
3327
3544
  const { description, tags } = getJSDocComment(node);
3328
3545
  const visibility = getVisibility(node);
3546
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3547
+ return null;
3548
+ }
3329
3549
  const type = checker.getTypeAtLocation(node);
3330
3550
  const callSignatures = type.getCallSignatures();
3331
3551
  const signatures = callSignatures.map((sig, index) => {
@@ -3387,6 +3607,9 @@ function serializeAccessor(node, ctx) {
3387
3607
  return null;
3388
3608
  const { description, tags } = getJSDocComment(node);
3389
3609
  const visibility = getVisibility(node);
3610
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3611
+ return null;
3612
+ }
3390
3613
  const type = checker.getTypeAtLocation(node);
3391
3614
  const schema = buildSchema(type, checker, ctx);
3392
3615
  registerReferencedTypes(type, ctx);
@@ -3460,7 +3683,7 @@ function serializeEnum(node, ctx) {
3460
3683
  const name = symbol?.getName() ?? node.name?.getText();
3461
3684
  if (!name)
3462
3685
  return null;
3463
- const deprecated = isSymbolDeprecated(symbol);
3686
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3464
3687
  const declSourceFile = node.getSourceFile();
3465
3688
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3466
3689
  const source = getSourceLocation(node, declSourceFile);
@@ -3493,7 +3716,7 @@ function serializeEnum(node, ctx) {
3493
3716
  tags,
3494
3717
  source,
3495
3718
  members,
3496
- ...deprecated ? { deprecated: true } : {},
3719
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3497
3720
  ...examples.length > 0 ? { examples } : {}
3498
3721
  };
3499
3722
  }
@@ -3533,7 +3756,7 @@ function serializeFunctionExport(node, ctx) {
3533
3756
  const name = symbol?.getName() ?? node.name?.getText();
3534
3757
  if (!name)
3535
3758
  return null;
3536
- const deprecated = isSymbolDeprecated(symbol);
3759
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3537
3760
  const declSourceFile = node.getSourceFile();
3538
3761
  const { description, tags, examples } = getJSDocComment(node, symbol, ctx.typeChecker);
3539
3762
  const source = getSourceLocation(node, declSourceFile);
@@ -3563,7 +3786,7 @@ function serializeFunctionExport(node, ctx) {
3563
3786
  source,
3564
3787
  typeParameters,
3565
3788
  signatures,
3566
- ...deprecated ? { deprecated: true } : {},
3789
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3567
3790
  ...examples.length > 0 ? { examples } : {}
3568
3791
  };
3569
3792
  }
@@ -3576,7 +3799,7 @@ function serializeInterface(node, ctx) {
3576
3799
  const name = symbol?.getName() ?? node.name?.getText();
3577
3800
  if (!name)
3578
3801
  return null;
3579
- const deprecated = isSymbolDeprecated(symbol);
3802
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3580
3803
  const declSourceFile = node.getSourceFile();
3581
3804
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3582
3805
  const source = getSourceLocation(node, declSourceFile);
@@ -3656,7 +3879,7 @@ function serializeInterface(node, ctx) {
3656
3879
  members: members.length > 0 ? members : undefined,
3657
3880
  signatures: exportSignatures,
3658
3881
  extends: extendsClause,
3659
- ...deprecated ? { deprecated: true } : {},
3882
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3660
3883
  ...examples.length > 0 ? { examples } : {}
3661
3884
  };
3662
3885
  }
@@ -3797,7 +4020,7 @@ function serializeTypeAlias(node, ctx) {
3797
4020
  const name = symbol?.getName() ?? node.name?.getText();
3798
4021
  if (!name)
3799
4022
  return null;
3800
- const deprecated = isSymbolDeprecated(symbol);
4023
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3801
4024
  const declSourceFile = node.getSourceFile();
3802
4025
  const { description, tags, examples } = getJSDocComment(node, symbol, ctx.typeChecker);
3803
4026
  const source = getSourceLocation(node, declSourceFile);
@@ -3819,7 +4042,7 @@ function serializeTypeAlias(node, ctx) {
3819
4042
  source,
3820
4043
  typeParameters,
3821
4044
  schema,
3822
- ...deprecated ? { deprecated: true } : {},
4045
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3823
4046
  ...examples.length > 0 ? { examples } : {}
3824
4047
  };
3825
4048
  }
@@ -3993,7 +4216,7 @@ function serializeVariable(node, statement, ctx) {
3993
4216
  const name = symbol?.getName() ?? node.name.getText();
3994
4217
  if (!name)
3995
4218
  return null;
3996
- const deprecated = isSymbolDeprecated(symbol);
4219
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3997
4220
  const declSourceFile = node.getSourceFile();
3998
4221
  const { description, tags, examples } = getJSDocComment(statement, symbol, ctx.typeChecker);
3999
4222
  const source = getSourceLocation(node, declSourceFile);
@@ -4015,7 +4238,7 @@ function serializeVariable(node, statement, ctx) {
4015
4238
  source,
4016
4239
  schema,
4017
4240
  ...flags ? { flags } : {},
4018
- ...deprecated ? { deprecated: true } : {},
4241
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
4019
4242
  ...examples.length > 0 ? { examples } : {}
4020
4243
  };
4021
4244
  }
@@ -5346,7 +5569,8 @@ async function extract(options) {
5346
5569
  only,
5347
5570
  ignore,
5348
5571
  onProgress,
5349
- isDtsSource
5572
+ isDtsSource,
5573
+ includePrivate
5350
5574
  } = options;
5351
5575
  const diagnostics = [];
5352
5576
  let exports = [];
@@ -5385,7 +5609,8 @@ async function extract(options) {
5385
5609
  const ctx = createContext(program, sourceFile, {
5386
5610
  maxTypeDepth,
5387
5611
  maxExternalTypeDepth,
5388
- resolveExternalTypes
5612
+ resolveExternalTypes,
5613
+ includePrivate
5389
5614
  });
5390
5615
  ctx.exportedIds = exportedIds;
5391
5616
  const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
@@ -5401,8 +5626,47 @@ async function extract(options) {
5401
5626
  try {
5402
5627
  const { declaration, targetSymbol, isTypeOnly } = resolveExportTarget2(symbol, typeChecker);
5403
5628
  if (!declaration) {
5404
- tracker.status = "skipped";
5405
- tracker.skipReason = "no-declaration";
5629
+ let externalPackage;
5630
+ const allDecls = [
5631
+ ...targetSymbol.declarations ?? [],
5632
+ ...symbol.declarations ?? []
5633
+ ];
5634
+ for (const decl of allDecls) {
5635
+ const sf = decl.getSourceFile();
5636
+ if (sf?.fileName.includes("node_modules")) {
5637
+ const match = sf.fileName.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
5638
+ if (match) {
5639
+ externalPackage = match[1];
5640
+ break;
5641
+ }
5642
+ }
5643
+ if (ts14.isExportSpecifier(decl)) {
5644
+ const exportDecl = decl.parent?.parent;
5645
+ if (exportDecl && ts14.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
5646
+ const moduleText = exportDecl.moduleSpecifier.getText().slice(1, -1);
5647
+ if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
5648
+ externalPackage = moduleText;
5649
+ break;
5650
+ }
5651
+ }
5652
+ }
5653
+ }
5654
+ if (externalPackage) {
5655
+ const externalExport = {
5656
+ id: exportName,
5657
+ name: exportName,
5658
+ kind: "external",
5659
+ source: {
5660
+ package: externalPackage
5661
+ }
5662
+ };
5663
+ exports.push(externalExport);
5664
+ tracker.status = "success";
5665
+ tracker.kind = "external";
5666
+ } else {
5667
+ tracker.status = "skipped";
5668
+ tracker.skipReason = "no-declaration";
5669
+ }
5406
5670
  continue;
5407
5671
  }
5408
5672
  const exp = serializeDeclaration2(declaration, symbol, targetSymbol, exportName, ctx, isTypeOnly);
@@ -5999,6 +6263,7 @@ export {
5999
6263
  isExported,
6000
6264
  isBuiltinGeneric,
6001
6265
  isAnonymous,
6266
+ hasDeprecatedTag,
6002
6267
  groupByVisibility,
6003
6268
  getTypeOrigin,
6004
6269
  getSourceLocation,
@@ -6010,6 +6275,7 @@ export {
6010
6275
  getMemberBadges,
6011
6276
  getJSDocComment,
6012
6277
  getExport,
6278
+ getDeprecationMessage,
6013
6279
  toMarkdown as generateDocs,
6014
6280
  formatTypeParameters,
6015
6281
  formatSchema,
@@ -6018,8 +6284,10 @@ export {
6018
6284
  formatMappedType,
6019
6285
  formatConditionalType,
6020
6286
  formatBadges,
6287
+ findMissingParamDocs,
6021
6288
  findDiscriminatorProperty,
6022
6289
  findAdapter,
6290
+ filterSpec,
6023
6291
  extractTypeParameters,
6024
6292
  extractStandardSchemasFromTs,
6025
6293
  extractStandardSchemasFromProject,
@@ -6041,6 +6309,7 @@ export {
6041
6309
  buildSignatureString,
6042
6310
  buildSchema,
6043
6311
  arktypeAdapter,
6312
+ analyzeSpec,
6044
6313
  TypeRegistry,
6045
6314
  BUILTIN_TYPE_SCHEMAS,
6046
6315
  ARRAY_PROTOTYPE_METHODS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/sdk",
3
- "version": "0.30.2",
3
+ "version": "0.32.0",
4
4
  "description": "TypeScript API extraction SDK - programmatic primitives for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",
@@ -38,7 +38,7 @@
38
38
  "test": "bun test"
39
39
  },
40
40
  "dependencies": {
41
- "@openpkg-ts/spec": "^0.27.1",
41
+ "@openpkg-ts/spec": "^0.32.0",
42
42
  "typescript": "^5.0.0"
43
43
  },
44
44
  "peerDependencies": {