@openpkg-ts/sdk 0.31.0 → 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.
Files changed (3) hide show
  1. package/dist/index.d.ts +87 -71
  2. package/dist/index.js +211 -109
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -1,43 +1,5 @@
1
- import { OpenPkg, SpecExportKind } from "@openpkg-ts/spec";
2
- type FilterCriteria = {
3
- /** Filter by kinds */
4
- kinds?: SpecExportKind[];
5
- /** Filter by names (exact match) */
6
- names?: string[];
7
- /** Filter by IDs */
8
- ids?: string[];
9
- /** Filter by tags (must have at least one matching tag) */
10
- tags?: string[];
11
- /** Filter by deprecation status */
12
- deprecated?: boolean;
13
- /** Filter by whether has a description */
14
- hasDescription?: boolean;
15
- /** Search term (matches name or description, case-insensitive) */
16
- search?: string;
17
- /** Filter by module path (source.file contains this) */
18
- module?: string;
19
- };
20
- type FilterResult = {
21
- /** New spec with only matched exports (immutable) */
22
- spec: OpenPkg;
23
- /** Number of exports that matched */
24
- matched: number;
25
- /** Total number of exports in original spec */
26
- total: number;
27
- };
28
- /**
29
- * Filter a spec by various criteria.
30
- * Returns a new spec with only matched exports (never mutates input).
31
- * Uses AND logic: all specified criteria must match.
32
- * Types are always preserved (no pruning).
33
- *
34
- * @param spec - The spec to filter
35
- * @param criteria - Filter criteria (empty criteria matches all)
36
- * @returns FilterResult with new spec, matched count, total count
37
- */
38
- declare function filterSpec(spec: OpenPkg, criteria: FilterCriteria): FilterResult;
39
1
  import { BreakingSeverity, CategorizedBreaking, calculateNextVersion, categorizeBreakingChanges, diffSpec, diffSpec as diffSpec2, MemberChangeInfo, recommendSemverBump, SemverBump, SemverRecommendation, SpecDiff } from "@openpkg-ts/spec";
40
- import { OpenPkg as OpenPkg2, SpecExport } from "@openpkg-ts/spec";
2
+ import { OpenPkg, SpecExport } from "@openpkg-ts/spec";
41
3
  interface DiagnosticItem {
42
4
  exportId: string;
43
5
  exportName: string;
@@ -71,7 +33,7 @@ declare function findMissingParamDocs(exp: SpecExport): string[];
71
33
  /**
72
34
  * Analyze a spec for quality issues.
73
35
  */
74
- declare function analyzeSpec(spec: OpenPkg2): SpecDiagnostics;
36
+ declare function analyzeSpec(spec: OpenPkg): SpecDiagnostics;
75
37
  import { SpecMember } from "@openpkg-ts/spec";
76
38
  /**
77
39
  * Extract badge strings from a member's visibility and flags.
@@ -82,8 +44,8 @@ declare function getMemberBadges(member: SpecMember): string[];
82
44
  * Format badges array into a display string (space-separated).
83
45
  */
84
46
  declare function formatBadges(badges: string[]): string;
85
- import { OpenPkg as OpenPkg8, SpecExport as SpecExport3, SpecExportKind as SpecExportKind5, SpecType } from "@openpkg-ts/spec";
86
- import { OpenPkg as OpenPkg3 } 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";
87
49
  interface HTMLOptions {
88
50
  /** Page title override */
89
51
  title?: string;
@@ -121,8 +83,8 @@ interface HTMLOptions {
121
83
  * const fragment = docs.toHTML({ export: 'greet', fullDocument: false })
122
84
  * ```
123
85
  */
124
- declare function toHTML2(spec: OpenPkg3, options?: HTMLOptions): string;
125
- import { OpenPkg as OpenPkg4, SpecExportKind as SpecExportKind2 } from "@openpkg-ts/spec";
86
+ declare function toHTML2(spec: OpenPkg2, options?: HTMLOptions): string;
87
+ import { OpenPkg as OpenPkg3, SpecExportKind } from "@openpkg-ts/spec";
126
88
  interface JSONOptions {
127
89
  /** Include raw spec data alongside simplified data */
128
90
  includeRaw?: boolean;
@@ -170,7 +132,7 @@ interface SimplifiedExample {
170
132
  interface SimplifiedExport {
171
133
  id: string;
172
134
  name: string;
173
- kind: SpecExportKind2;
135
+ kind: SpecExportKind;
174
136
  signature: string;
175
137
  description?: string;
176
138
  deprecated: boolean;
@@ -192,7 +154,7 @@ interface SimplifiedSpec {
192
154
  version?: string;
193
155
  description?: string;
194
156
  exports: SimplifiedExport[];
195
- byKind: Record<SpecExportKind2, SimplifiedExport[]>;
157
+ byKind: Record<SpecExportKind, SimplifiedExport[]>;
196
158
  totalExports: number;
197
159
  }
198
160
  /**
@@ -216,7 +178,7 @@ interface SimplifiedSpec {
216
178
  * // { id, name, kind, signature, parameters, returns, ... }
217
179
  * ```
218
180
  */
219
- declare function toJSON2(spec: OpenPkg4, options?: JSONOptions): SimplifiedSpec | SimplifiedExport;
181
+ declare function toJSON2(spec: OpenPkg3, options?: JSONOptions): SimplifiedSpec | SimplifiedExport;
220
182
  /**
221
183
  * Serialize to JSON string with formatting.
222
184
  *
@@ -224,10 +186,10 @@ declare function toJSON2(spec: OpenPkg4, options?: JSONOptions): SimplifiedSpec
224
186
  * @param options - JSON options plus pretty formatting option
225
187
  * @returns JSON string
226
188
  */
227
- declare function toJSONString(spec: OpenPkg4, options?: JSONOptions & {
189
+ declare function toJSONString(spec: OpenPkg3, options?: JSONOptions & {
228
190
  pretty?: boolean;
229
191
  }): string;
230
- import { OpenPkg as OpenPkg5, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
192
+ import { OpenPkg as OpenPkg4, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
231
193
  interface MarkdownOptions {
232
194
  /** Include frontmatter in output */
233
195
  frontmatter?: boolean;
@@ -248,6 +210,8 @@ interface MarkdownOptions {
248
210
  codeSignatures?: boolean;
249
211
  /** Heading level offset (0 = starts at h1, 1 = starts at h2) */
250
212
  headingOffset?: number;
213
+ /** Collapse unions with more than N members (default: no collapse) */
214
+ collapseUnionThreshold?: number;
251
215
  }
252
216
  interface ExportMarkdownOptions extends MarkdownOptions {
253
217
  /** Export to render (single mode) */
@@ -291,8 +255,8 @@ declare function exportToMarkdown(exp: SpecExport2, options?: MarkdownOptions):
291
255
  * // Single * const fnMdx = docs.toMarkdown({ export: 'greet' })
292
256
  * ```
293
257
  */
294
- declare function toMarkdown2(spec: OpenPkg5, options?: ExportMarkdownOptions): string;
295
- import { OpenPkg as OpenPkg6, SpecExportKind as SpecExportKind3 } 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";
296
260
  type NavFormat = "fumadocs" | "docusaurus" | "generic";
297
261
  type GroupBy = "kind" | "module" | "tag" | "none";
298
262
  interface NavOptions {
@@ -307,7 +271,7 @@ interface NavOptions {
307
271
  /** Include index pages for groups */
308
272
  includeGroupIndex?: boolean;
309
273
  /** Custom kind labels */
310
- kindLabels?: Partial<Record<SpecExportKind3, string>>;
274
+ kindLabels?: Partial<Record<SpecExportKind2, string>>;
311
275
  /** Sort exports alphabetically */
312
276
  sortAlphabetically?: boolean;
313
277
  }
@@ -367,7 +331,7 @@ type DocusaurusSidebar = DocusaurusSidebarItem[];
367
331
  * const sidebar = docs.toNavigation({ format: 'docusaurus' })
368
332
  * ```
369
333
  */
370
- declare function toNavigation2(spec: OpenPkg6, options?: NavOptions): GenericNav | FumadocsMeta | DocusaurusSidebar;
334
+ declare function toNavigation2(spec: OpenPkg5, options?: NavOptions): GenericNav | FumadocsMeta | DocusaurusSidebar;
371
335
  /**
372
336
  * Generate Fumadocs meta.json file content.
373
337
  *
@@ -381,7 +345,7 @@ declare function toNavigation2(spec: OpenPkg6, options?: NavOptions): GenericNav
381
345
  * fs.writeFileSync('docs/api/meta.json', meta)
382
346
  * ```
383
347
  */
384
- declare function toFumadocsMetaJSON(spec: OpenPkg6, options?: Omit<NavOptions, "format">): string;
348
+ declare function toFumadocsMetaJSON(spec: OpenPkg5, options?: Omit<NavOptions, "format">): string;
385
349
  /**
386
350
  * Generate Docusaurus sidebar config.
387
351
  *
@@ -395,8 +359,8 @@ declare function toFumadocsMetaJSON(spec: OpenPkg6, options?: Omit<NavOptions, "
395
359
  * fs.writeFileSync('sidebars.js', sidebar)
396
360
  * ```
397
361
  */
398
- declare function toDocusaurusSidebarJS(spec: OpenPkg6, options?: Omit<NavOptions, "format">): string;
399
- import { OpenPkg as OpenPkg7, SpecExportKind as SpecExportKind4 } 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";
400
364
  interface SearchOptions {
401
365
  /** Base URL for search result links */
402
366
  baseUrl?: string;
@@ -440,7 +404,7 @@ interface PagefindRecord {
440
404
  interface AlgoliaRecord {
441
405
  objectID: string;
442
406
  name: string;
443
- kind: SpecExportKind4;
407
+ kind: SpecExportKind3;
444
408
  description?: string;
445
409
  signature: string;
446
410
  content: string;
@@ -460,7 +424,7 @@ interface AlgoliaRecord {
460
424
  interface SearchRecord {
461
425
  id: string;
462
426
  name: string;
463
- kind: SpecExportKind4;
427
+ kind: SpecExportKind3;
464
428
  signature: string;
465
429
  description?: string;
466
430
  content: string;
@@ -489,7 +453,7 @@ interface SearchIndex {
489
453
  * // { records: [...], version: '1.0.0', packageName: 'my-lib' }
490
454
  * ```
491
455
  */
492
- declare function toSearchIndex2(spec: OpenPkg7, options?: SearchOptions): SearchIndex;
456
+ declare function toSearchIndex2(spec: OpenPkg6, options?: SearchOptions): SearchIndex;
493
457
  /**
494
458
  * Generate Pagefind-compatible records.
495
459
  *
@@ -505,7 +469,7 @@ declare function toSearchIndex2(spec: OpenPkg7, options?: SearchOptions): Search
505
469
  * })
506
470
  * ```
507
471
  */
508
- declare function toPagefindRecords2(spec: OpenPkg7, options?: SearchOptions): PagefindRecord[];
472
+ declare function toPagefindRecords2(spec: OpenPkg6, options?: SearchOptions): PagefindRecord[];
509
473
  /**
510
474
  * Generate Algolia-compatible records.
511
475
  *
@@ -519,7 +483,7 @@ declare function toPagefindRecords2(spec: OpenPkg7, options?: SearchOptions): Pa
519
483
  * // Upload to Algolia index
520
484
  * ```
521
485
  */
522
- declare function toAlgoliaRecords2(spec: OpenPkg7, options?: SearchOptions): AlgoliaRecord[];
486
+ declare function toAlgoliaRecords2(spec: OpenPkg6, options?: SearchOptions): AlgoliaRecord[];
523
487
  /**
524
488
  * Serialize search index to JSON string.
525
489
  *
@@ -533,22 +497,22 @@ declare function toAlgoliaRecords2(spec: OpenPkg7, options?: SearchOptions): Alg
533
497
  * fs.writeFileSync('search-index.json', json)
534
498
  * ```
535
499
  */
536
- declare function toSearchIndexJSON(spec: OpenPkg7, options?: SearchOptions & {
500
+ declare function toSearchIndexJSON(spec: OpenPkg6, options?: SearchOptions & {
537
501
  pretty?: boolean;
538
502
  }): string;
539
503
  interface LoadOptions {
540
504
  /** Path to openpkg.json file or the spec object directly */
541
- input: string | OpenPkg8;
505
+ input: string | OpenPkg7;
542
506
  }
543
507
  interface DocsInstance {
544
508
  /** The parsed OpenPkg spec */
545
- spec: OpenPkg8;
509
+ spec: OpenPkg7;
546
510
  /** Get an by its ID */
547
511
  getExport(id: string): SpecExport3 | undefined;
548
512
  /** Get a type definition by its ID */
549
513
  getType(id: string): SpecType | undefined;
550
514
  /** Get all exports of a specific kind */
551
- getExportsByKind(kind: SpecExportKind5): SpecExport3[];
515
+ getExportsByKind(kind: SpecExportKind4): SpecExport3[];
552
516
  /** Get all exports */
553
517
  getAllExports(): SpecExport3[];
554
518
  /** Get all type definitions */
@@ -562,7 +526,7 @@ interface DocsInstance {
562
526
  /** Get deprecated exports */
563
527
  getDeprecated(): SpecExport3[];
564
528
  /** Get exports grouped by kind */
565
- groupByKind(): Record<SpecExportKind5, SpecExport3[]>;
529
+ groupByKind(): Record<SpecExportKind4, SpecExport3[]>;
566
530
  /** Render spec or single to MDX */
567
531
  toMarkdown(options?: ExportMarkdownOptions): string;
568
532
  /** Render spec or single to HTML */
@@ -590,7 +554,7 @@ interface DocsInstance {
590
554
  * const docs = loadSpec(spec)
591
555
  * ```
592
556
  */
593
- declare function loadSpec(spec: OpenPkg8): DocsInstance;
557
+ declare function loadSpec(spec: OpenPkg7): DocsInstance;
594
558
  /**
595
559
  * Creates a docs instance for querying and rendering API documentation.
596
560
  *
@@ -612,11 +576,13 @@ declare function loadSpec(spec: OpenPkg8): DocsInstance;
612
576
  * docs.search('hook')
613
577
  * ```
614
578
  */
615
- declare function createDocs(input: string | OpenPkg8): DocsInstance;
616
- import { OpenPkg as OpenPkg9, SpecExport as SpecExport4, 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";
617
581
  interface FormatSchemaOptions {
618
582
  /** Include package attribution for external types */
619
583
  includePackage?: boolean;
584
+ /** Collapse unions with more than N members (default: no collapse) */
585
+ collapseUnionThreshold?: number;
620
586
  }
621
587
  /**
622
588
  * Format a schema to a human-readable type string.
@@ -706,7 +672,7 @@ declare function buildSignatureString(exp: SpecExport4, sigIndex?: number): stri
706
672
  * // { id: 'User', name: 'User', kind: 'interface', ... }
707
673
  * ```
708
674
  */
709
- declare function resolveTypeRef(ref: string, spec: OpenPkg9): SpecType2 | undefined;
675
+ declare function resolveTypeRef(ref: string, spec: OpenPkg8): SpecType2 | undefined;
710
676
  /**
711
677
  * Check if a member is a method (has signatures).
712
678
  *
@@ -821,6 +787,48 @@ declare function formatConditionalType(condType: SpecConditionalType): string;
821
787
  * ```
822
788
  */
823
789
  declare function formatMappedType(mappedType: SpecMappedType): string;
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;
824
832
  import { SpecExport as SpecExport5, SpecType as SpecType3 } from "@openpkg-ts/spec";
825
833
  interface GetExportOptions {
826
834
  /** Entry point file path */
@@ -898,6 +906,8 @@ interface ExtractOptions {
898
906
  onProgress?: (current: number, total: number, item: string) => void;
899
907
  /** Whether source is a .d.ts file (degraded mode - TSDoc may be missing) */
900
908
  isDtsSource?: boolean;
909
+ /** Include private/protected class members (default: false) */
910
+ includePrivate?: boolean;
901
911
  }
902
912
  interface ExtractResult {
903
913
  spec: OpenPkg10;
@@ -1018,6 +1028,8 @@ interface SerializerContext {
1018
1028
  visitedTypes: Set<ts.Type>;
1019
1029
  /** Flag to indicate we're processing tuple elements - skip Array prototype methods */
1020
1030
  inTupleElement?: boolean;
1031
+ /** Include private/protected class members (default: false) */
1032
+ includePrivate?: boolean;
1021
1033
  }
1022
1034
  declare class TypeRegistry {
1023
1035
  private types;
@@ -1081,8 +1093,12 @@ type DeclarationWithTypeParams = ts4.FunctionDeclaration | ts4.ClassDeclaration
1081
1093
  declare function extractTypeParameters(node: DeclarationWithTypeParams, checker: ts4.TypeChecker): SpecTypeParameter2[] | undefined;
1082
1094
  /**
1083
1095
  * Check if a symbol is marked as deprecated via @deprecated JSDoc tag.
1096
+ * Returns deprecation status and optional reason text.
1084
1097
  */
1085
- declare function isSymbolDeprecated(symbol: ts4.Symbol | undefined): boolean;
1098
+ declare function isSymbolDeprecated(symbol: ts4.Symbol | undefined): {
1099
+ deprecated: boolean;
1100
+ reason?: string;
1101
+ };
1086
1102
  /**
1087
1103
  * Target version for JSON Schema generation.
1088
1104
  * @see https://standardschema.dev/json-schema
package/dist/index.js CHANGED
@@ -1,72 +1,3 @@
1
- // src/primitives/filter.ts
2
- function matchesExport(exp, criteria) {
3
- if (criteria.kinds && criteria.kinds.length > 0) {
4
- if (!criteria.kinds.includes(exp.kind))
5
- return false;
6
- }
7
- if (criteria.names && criteria.names.length > 0) {
8
- if (!criteria.names.includes(exp.name))
9
- return false;
10
- }
11
- if (criteria.ids && criteria.ids.length > 0) {
12
- if (!criteria.ids.includes(exp.id))
13
- return false;
14
- }
15
- if (criteria.tags && criteria.tags.length > 0) {
16
- const expTags = exp.tags?.map((t) => t.name) ?? [];
17
- if (!criteria.tags.some((tag) => expTags.includes(tag)))
18
- return false;
19
- }
20
- if (criteria.deprecated !== undefined) {
21
- if ((exp.deprecated ?? false) !== criteria.deprecated)
22
- return false;
23
- }
24
- if (criteria.hasDescription !== undefined) {
25
- const has = Boolean(exp.description && exp.description.trim().length > 0);
26
- if (has !== criteria.hasDescription)
27
- return false;
28
- }
29
- if (criteria.search) {
30
- const term = criteria.search.toLowerCase();
31
- const nameMatch = exp.name.toLowerCase().includes(term);
32
- const descMatch = exp.description?.toLowerCase().includes(term) ?? false;
33
- if (!nameMatch && !descMatch)
34
- return false;
35
- }
36
- if (criteria.module) {
37
- const file = exp.source?.file ?? "";
38
- if (!file.includes(criteria.module))
39
- return false;
40
- }
41
- return true;
42
- }
43
- function filterSpec(spec, criteria) {
44
- const total = spec.exports.length;
45
- const isEmpty = Object.keys(criteria).length === 0;
46
- if (isEmpty) {
47
- return {
48
- spec: { ...spec, exports: [...spec.exports], types: spec.types ? [...spec.types] : undefined },
49
- matched: total,
50
- total
51
- };
52
- }
53
- const matched = [];
54
- for (const exp of spec.exports) {
55
- if (matchesExport(exp, criteria)) {
56
- matched.push(exp);
57
- }
58
- }
59
- const newSpec = {
60
- ...spec,
61
- exports: matched,
62
- types: spec.types ? [...spec.types] : undefined
63
- };
64
- return {
65
- spec: newSpec,
66
- matched: matched.length,
67
- total
68
- };
69
- }
70
1
  // src/primitives/diff.ts
71
2
  import {
72
3
  calculateNextVersion,
@@ -83,7 +14,7 @@ function hasDeprecatedTag(exp) {
83
14
  }
84
15
  function getDeprecationMessage(exp) {
85
16
  const tag = exp.tags?.find((t) => t.name === "deprecated" || t.name === "@deprecated");
86
- if (tag && tag.text.trim()) {
17
+ if (tag?.text.trim()) {
87
18
  return tag.text.trim();
88
19
  }
89
20
  return;
@@ -221,7 +152,15 @@ function formatSchema(schema, options) {
221
152
  return withPackage(baseName);
222
153
  }
223
154
  if ("anyOf" in schema && Array.isArray(schema.anyOf)) {
224
- 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(" | ");
225
164
  }
226
165
  if ("allOf" in schema && Array.isArray(schema.allOf)) {
227
166
  return schema.allOf.map((s) => formatSchema(s, options)).join(" & ");
@@ -894,12 +833,12 @@ function heading(level, text, offset = 0) {
894
833
  const actualLevel = Math.min(level + offset, 6);
895
834
  return `${"#".repeat(actualLevel)} ${text}`;
896
835
  }
897
- function renderParameters2(sig, offset = 0) {
836
+ function renderParameters2(sig, offset = 0, schemaOpts) {
898
837
  if (!sig?.parameters?.length)
899
838
  return "";
900
839
  const lines = [heading(2, "Parameters", offset), ""];
901
840
  for (const param of sig.parameters) {
902
- const type = formatSchema(param.schema);
841
+ const type = formatSchema(param.schema, schemaOpts);
903
842
  const required = param.required !== false ? "" : "?";
904
843
  const rest = param.rest ? "..." : "";
905
844
  lines.push(`### \`${rest}${param.name}${required}\``);
@@ -918,11 +857,11 @@ function renderParameters2(sig, offset = 0) {
918
857
  return lines.join(`
919
858
  `);
920
859
  }
921
- function renderReturns2(sig, offset = 0) {
860
+ function renderReturns2(sig, offset = 0, schemaOpts) {
922
861
  if (!sig?.returns)
923
862
  return "";
924
863
  const lines = [heading(2, "Returns", offset), ""];
925
- const type = formatSchema(sig.returns.schema);
864
+ const type = formatSchema(sig.returns.schema, schemaOpts);
926
865
  lines.push(`**Type:** \`${type}\``);
927
866
  if (sig.returns.description) {
928
867
  lines.push("");
@@ -974,13 +913,13 @@ function renderExamples2(examples, offset = 0) {
974
913
  return lines.join(`
975
914
  `);
976
915
  }
977
- function renderProperties2(members, offset = 0) {
916
+ function renderProperties2(members, offset = 0, schemaOpts) {
978
917
  const props = getProperties(members);
979
918
  if (!props.length)
980
919
  return "";
981
920
  const lines = [heading(2, "Properties", offset), ""];
982
921
  for (const prop of props) {
983
- const type = formatSchema(prop.schema);
922
+ const type = formatSchema(prop.schema, schemaOpts);
984
923
  lines.push(`### \`${prop.name}\``);
985
924
  lines.push("");
986
925
  if (prop.decorators?.length) {
@@ -1013,7 +952,7 @@ function renderProperties2(members, offset = 0) {
1013
952
  return lines.join(`
1014
953
  `);
1015
954
  }
1016
- function renderMethods2(members, offset = 0) {
955
+ function renderMethods2(members, offset = 0, schemaOpts) {
1017
956
  const methods = getMethods(members);
1018
957
  if (!methods.length)
1019
958
  return "";
@@ -1050,14 +989,14 @@ function renderMethods2(members, offset = 0) {
1050
989
  lines.push("**Parameters:**");
1051
990
  lines.push("");
1052
991
  for (const param of sig.parameters) {
1053
- const paramType = formatSchema(param.schema);
992
+ const paramType = formatSchema(param.schema, schemaOpts);
1054
993
  const desc = param.description ? ` - ${param.description}` : "";
1055
994
  lines.push(`- \`${param.name}\`: \`${paramType}\`${desc}`);
1056
995
  }
1057
996
  lines.push("");
1058
997
  }
1059
998
  if (sig?.returns) {
1060
- const retType = formatSchema(sig.returns.schema);
999
+ const retType = formatSchema(sig.returns.schema, schemaOpts);
1061
1000
  const desc = sig.returns.description ? ` - ${sig.returns.description}` : "";
1062
1001
  lines.push(`**Returns:** \`${retType}\`${desc}`);
1063
1002
  lines.push("");
@@ -1084,6 +1023,7 @@ function renderEnumMembers2(members, offset = 0) {
1084
1023
  function exportToMarkdown(exp, options = {}) {
1085
1024
  const sections = { ...defaultSections, ...options.sections };
1086
1025
  const offset = options.headingOffset ?? 0;
1026
+ const schemaOpts = options.collapseUnionThreshold ? { collapseUnionThreshold: options.collapseUnionThreshold } : undefined;
1087
1027
  const parts = [];
1088
1028
  if (options.frontmatter !== false) {
1089
1029
  parts.push(generateFrontmatter(exp, options.customFrontmatter));
@@ -1131,24 +1071,25 @@ function exportToMarkdown(exp, options = {}) {
1131
1071
  parts.push("");
1132
1072
  }
1133
1073
  if (exp.deprecated) {
1134
- parts.push("> **Deprecated**");
1074
+ const reason = "deprecationReason" in exp && exp.deprecationReason ? `: ${exp.deprecationReason}` : "";
1075
+ parts.push(`> **Deprecated**${reason}`);
1135
1076
  parts.push("");
1136
1077
  }
1137
1078
  const primarySig = exp.signatures?.[0];
1138
1079
  switch (exp.kind) {
1139
1080
  case "function":
1140
1081
  if (sections.parameters)
1141
- parts.push(renderParameters2(primarySig, offset));
1082
+ parts.push(renderParameters2(primarySig, offset, schemaOpts));
1142
1083
  if (sections.returns)
1143
- parts.push(renderReturns2(primarySig, offset));
1084
+ parts.push(renderReturns2(primarySig, offset, schemaOpts));
1144
1085
  parts.push(renderThrows2(primarySig, offset));
1145
1086
  break;
1146
1087
  case "class":
1147
1088
  case "interface":
1148
1089
  if (sections.properties)
1149
- parts.push(renderProperties2(exp.members, offset));
1090
+ parts.push(renderProperties2(exp.members, offset, schemaOpts));
1150
1091
  if (sections.methods)
1151
- parts.push(renderMethods2(exp.members, offset));
1092
+ parts.push(renderMethods2(exp.members, offset, schemaOpts));
1152
1093
  break;
1153
1094
  case "enum":
1154
1095
  if (sections.members)
@@ -1677,6 +1618,109 @@ function extractModuleName(exp) {
1677
1618
  }
1678
1619
  return;
1679
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
+ }
1680
1724
  // src/primitives/get.ts
1681
1725
  import ts11 from "typescript";
1682
1726
 
@@ -2096,18 +2140,27 @@ function extractTypeParameters(node, checker) {
2096
2140
  }
2097
2141
  function isSymbolDeprecated(symbol) {
2098
2142
  if (!symbol) {
2099
- return false;
2143
+ return { deprecated: false };
2100
2144
  }
2101
2145
  const jsDocTags = symbol.getJsDocTags();
2102
- if (jsDocTags.some((tag) => tag.name.toLowerCase() === "deprecated")) {
2103
- 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 };
2104
2150
  }
2105
2151
  for (const declaration of symbol.getDeclarations() ?? []) {
2106
- if (ts2.getJSDocDeprecatedTag(declaration)) {
2107
- 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 };
2108
2161
  }
2109
2162
  }
2110
- return false;
2163
+ return { deprecated: false };
2111
2164
  }
2112
2165
  function getJSDocForSignature(signature, checker) {
2113
2166
  const decl = signature.getDeclaration();
@@ -3206,7 +3259,8 @@ function createContext(program, sourceFile, options = {}) {
3206
3259
  resolveExternalTypes: options.resolveExternalTypes ?? true,
3207
3260
  typeRegistry: new TypeRegistry,
3208
3261
  exportedIds: new Set,
3209
- visitedTypes: new Set
3262
+ visitedTypes: new Set,
3263
+ includePrivate: options.includePrivate ?? false
3210
3264
  };
3211
3265
  }
3212
3266
  function getInheritedMembers(classType, ownMemberNames, ctx, isStatic = false) {
@@ -3342,7 +3396,7 @@ function serializeClass(node, ctx) {
3342
3396
  const name = symbol?.getName() ?? node.name?.getText();
3343
3397
  if (!name)
3344
3398
  return null;
3345
- const deprecated = isSymbolDeprecated(symbol);
3399
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3346
3400
  const declSourceFile = node.getSourceFile();
3347
3401
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3348
3402
  const source = getSourceLocation(node, declSourceFile);
@@ -3414,7 +3468,7 @@ function serializeClass(node, ctx) {
3414
3468
  signatures: signatures.length > 0 ? signatures : undefined,
3415
3469
  extends: extendsClause,
3416
3470
  implements: implementsClause?.length ? implementsClause : undefined,
3417
- ...deprecated ? { deprecated: true } : {},
3471
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3418
3472
  ...examples.length > 0 ? { examples } : {},
3419
3473
  ...Object.keys(classFlags).length > 0 ? { flags: classFlags } : {}
3420
3474
  };
@@ -3459,8 +3513,9 @@ function serializeProperty(node, ctx) {
3459
3513
  return null;
3460
3514
  const { description, tags } = getJSDocComment(node);
3461
3515
  const visibility = getVisibility(node);
3462
- if (visibility === "private")
3516
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3463
3517
  return null;
3518
+ }
3464
3519
  const type = checker.getTypeAtLocation(node);
3465
3520
  registerReferencedTypes(type, ctx);
3466
3521
  const schema = buildSchema(type, checker, ctx);
@@ -3488,6 +3543,9 @@ function serializeMethod(node, ctx) {
3488
3543
  return null;
3489
3544
  const { description, tags } = getJSDocComment(node);
3490
3545
  const visibility = getVisibility(node);
3546
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3547
+ return null;
3548
+ }
3491
3549
  const type = checker.getTypeAtLocation(node);
3492
3550
  const callSignatures = type.getCallSignatures();
3493
3551
  const signatures = callSignatures.map((sig, index) => {
@@ -3549,6 +3607,9 @@ function serializeAccessor(node, ctx) {
3549
3607
  return null;
3550
3608
  const { description, tags } = getJSDocComment(node);
3551
3609
  const visibility = getVisibility(node);
3610
+ if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
3611
+ return null;
3612
+ }
3552
3613
  const type = checker.getTypeAtLocation(node);
3553
3614
  const schema = buildSchema(type, checker, ctx);
3554
3615
  registerReferencedTypes(type, ctx);
@@ -3622,7 +3683,7 @@ function serializeEnum(node, ctx) {
3622
3683
  const name = symbol?.getName() ?? node.name?.getText();
3623
3684
  if (!name)
3624
3685
  return null;
3625
- const deprecated = isSymbolDeprecated(symbol);
3686
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3626
3687
  const declSourceFile = node.getSourceFile();
3627
3688
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3628
3689
  const source = getSourceLocation(node, declSourceFile);
@@ -3655,7 +3716,7 @@ function serializeEnum(node, ctx) {
3655
3716
  tags,
3656
3717
  source,
3657
3718
  members,
3658
- ...deprecated ? { deprecated: true } : {},
3719
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3659
3720
  ...examples.length > 0 ? { examples } : {}
3660
3721
  };
3661
3722
  }
@@ -3695,7 +3756,7 @@ function serializeFunctionExport(node, ctx) {
3695
3756
  const name = symbol?.getName() ?? node.name?.getText();
3696
3757
  if (!name)
3697
3758
  return null;
3698
- const deprecated = isSymbolDeprecated(symbol);
3759
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3699
3760
  const declSourceFile = node.getSourceFile();
3700
3761
  const { description, tags, examples } = getJSDocComment(node, symbol, ctx.typeChecker);
3701
3762
  const source = getSourceLocation(node, declSourceFile);
@@ -3725,7 +3786,7 @@ function serializeFunctionExport(node, ctx) {
3725
3786
  source,
3726
3787
  typeParameters,
3727
3788
  signatures,
3728
- ...deprecated ? { deprecated: true } : {},
3789
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3729
3790
  ...examples.length > 0 ? { examples } : {}
3730
3791
  };
3731
3792
  }
@@ -3738,7 +3799,7 @@ function serializeInterface(node, ctx) {
3738
3799
  const name = symbol?.getName() ?? node.name?.getText();
3739
3800
  if (!name)
3740
3801
  return null;
3741
- const deprecated = isSymbolDeprecated(symbol);
3802
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3742
3803
  const declSourceFile = node.getSourceFile();
3743
3804
  const { description, tags, examples } = getJSDocComment(node, symbol, checker);
3744
3805
  const source = getSourceLocation(node, declSourceFile);
@@ -3818,7 +3879,7 @@ function serializeInterface(node, ctx) {
3818
3879
  members: members.length > 0 ? members : undefined,
3819
3880
  signatures: exportSignatures,
3820
3881
  extends: extendsClause,
3821
- ...deprecated ? { deprecated: true } : {},
3882
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3822
3883
  ...examples.length > 0 ? { examples } : {}
3823
3884
  };
3824
3885
  }
@@ -3959,7 +4020,7 @@ function serializeTypeAlias(node, ctx) {
3959
4020
  const name = symbol?.getName() ?? node.name?.getText();
3960
4021
  if (!name)
3961
4022
  return null;
3962
- const deprecated = isSymbolDeprecated(symbol);
4023
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3963
4024
  const declSourceFile = node.getSourceFile();
3964
4025
  const { description, tags, examples } = getJSDocComment(node, symbol, ctx.typeChecker);
3965
4026
  const source = getSourceLocation(node, declSourceFile);
@@ -3981,7 +4042,7 @@ function serializeTypeAlias(node, ctx) {
3981
4042
  source,
3982
4043
  typeParameters,
3983
4044
  schema,
3984
- ...deprecated ? { deprecated: true } : {},
4045
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
3985
4046
  ...examples.length > 0 ? { examples } : {}
3986
4047
  };
3987
4048
  }
@@ -4155,7 +4216,7 @@ function serializeVariable(node, statement, ctx) {
4155
4216
  const name = symbol?.getName() ?? node.name.getText();
4156
4217
  if (!name)
4157
4218
  return null;
4158
- const deprecated = isSymbolDeprecated(symbol);
4219
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
4159
4220
  const declSourceFile = node.getSourceFile();
4160
4221
  const { description, tags, examples } = getJSDocComment(statement, symbol, ctx.typeChecker);
4161
4222
  const source = getSourceLocation(node, declSourceFile);
@@ -4177,7 +4238,7 @@ function serializeVariable(node, statement, ctx) {
4177
4238
  source,
4178
4239
  schema,
4179
4240
  ...flags ? { flags } : {},
4180
- ...deprecated ? { deprecated: true } : {},
4241
+ ...deprecated ? { deprecated: true, deprecationReason } : {},
4181
4242
  ...examples.length > 0 ? { examples } : {}
4182
4243
  };
4183
4244
  }
@@ -5508,7 +5569,8 @@ async function extract(options) {
5508
5569
  only,
5509
5570
  ignore,
5510
5571
  onProgress,
5511
- isDtsSource
5572
+ isDtsSource,
5573
+ includePrivate
5512
5574
  } = options;
5513
5575
  const diagnostics = [];
5514
5576
  let exports = [];
@@ -5547,7 +5609,8 @@ async function extract(options) {
5547
5609
  const ctx = createContext(program, sourceFile, {
5548
5610
  maxTypeDepth,
5549
5611
  maxExternalTypeDepth,
5550
- resolveExternalTypes
5612
+ resolveExternalTypes,
5613
+ includePrivate
5551
5614
  });
5552
5615
  ctx.exportedIds = exportedIds;
5553
5616
  const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
@@ -5563,8 +5626,47 @@ async function extract(options) {
5563
5626
  try {
5564
5627
  const { declaration, targetSymbol, isTypeOnly } = resolveExportTarget2(symbol, typeChecker);
5565
5628
  if (!declaration) {
5566
- tracker.status = "skipped";
5567
- 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
+ }
5568
5670
  continue;
5569
5671
  }
5570
5672
  const exp = serializeDeclaration2(declaration, symbol, targetSymbol, exportName, ctx, isTypeOnly);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/sdk",
3
- "version": "0.31.0",
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.31.0",
41
+ "@openpkg-ts/spec": "^0.32.0",
42
42
  "typescript": "^5.0.0"
43
43
  },
44
44
  "peerDependencies": {