@openpkg-ts/sdk 0.54.10 → 0.55.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/dist/browser.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  toPagefindRecords,
22
22
  toSearchIndex,
23
23
  toSearchIndexJSON
24
- } from "./shared/chunk-7287tqkx.js";
24
+ } from "./shared/chunk-pwvdnach.js";
25
25
  // src/core/spec-converters.ts
26
26
  function getLangForHighlight(lang) {
27
27
  const langMap = {
package/dist/index.d.ts CHANGED
@@ -1333,7 +1333,7 @@ declare function getJSDocComment(node: ts4.Node, symbol?: ts4.Symbol, checker?:
1333
1333
  };
1334
1334
  declare function getSourceLocation(node: ts4.Node, sourceFile: ts4.SourceFile): SpecSource;
1335
1335
  /**
1336
- * Get description for a destructured parameter property from JSDoc @param tags.
1336
+ * Get description for a parameter or destructured key from JSDoc @param tags.
1337
1337
  * Matches patterns like:
1338
1338
  * - @param paramName - exact match
1339
1339
  * - @param opts.paramName - dotted notation with alias
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  toPagefindRecords,
26
26
  toSearchIndex,
27
27
  toSearchIndexJSON
28
- } from "./shared/chunk-7287tqkx.js";
28
+ } from "./shared/chunk-pwvdnach.js";
29
29
 
30
30
  // src/primitives/diff.ts
31
31
  import {
@@ -2111,17 +2111,41 @@ function getSourceLocation(node, sourceFile) {
2111
2111
  line: line + 1
2112
2112
  };
2113
2113
  }
2114
+ function bindingPatternKind(decl) {
2115
+ if (!decl)
2116
+ return;
2117
+ if (ts2.isObjectBindingPattern(decl.name))
2118
+ return "object";
2119
+ if (ts2.isArrayBindingPattern(decl.name))
2120
+ return "array";
2121
+ return;
2122
+ }
2123
+ function destructuredParamName(kind, taken, jsdocName) {
2124
+ if (jsdocName && !taken.has(jsdocName))
2125
+ return jsdocName;
2126
+ const base = kind === "object" ? "options" : "args";
2127
+ if (!taken.has(base))
2128
+ return base;
2129
+ let i = 2;
2130
+ while (taken.has(`${base}${i}`))
2131
+ i++;
2132
+ return `${base}${i}`;
2133
+ }
2134
+ function jsdocParamTagName(tag) {
2135
+ if (tag.tagName.text !== "param")
2136
+ return "";
2137
+ const paramTag = tag;
2138
+ try {
2139
+ return paramTag.name?.getText() ?? "";
2140
+ } catch {
2141
+ return paramTag.name?.text ?? "";
2142
+ }
2143
+ }
2114
2144
  function getParamDescription(propertyName, jsdocTags, inferredAlias) {
2115
2145
  for (const tag of jsdocTags) {
2116
2146
  if (tag.tagName.text !== "param")
2117
2147
  continue;
2118
- const paramTag = tag;
2119
- let tagParamName = "";
2120
- try {
2121
- tagParamName = paramTag.name?.getText() ?? "";
2122
- } catch {
2123
- tagParamName = paramTag.name?.text ?? "";
2124
- }
2148
+ const tagParamName = jsdocParamTagName(tag);
2125
2149
  const isMatch = tagParamName === propertyName || inferredAlias && tagParamName === `${inferredAlias}.${propertyName}` || tagParamName.endsWith(`.${propertyName}`);
2126
2150
  if (isMatch) {
2127
2151
  const comment = typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment);
@@ -3066,6 +3090,7 @@ var BUILTIN_GENERICS = new Set([
3066
3090
  "AsyncIterableIterator",
3067
3091
  "Generator",
3068
3092
  "AsyncGenerator",
3093
+ "ArrayLike",
3069
3094
  "Partial",
3070
3095
  "Required",
3071
3096
  "Readonly",
@@ -3210,6 +3235,7 @@ var BUILTIN_TYPES = new Set([
3210
3235
  "Error",
3211
3236
  "Function",
3212
3237
  "ArrayBuffer",
3238
+ "ArrayBufferLike",
3213
3239
  "SharedArrayBuffer",
3214
3240
  "DataView",
3215
3241
  "Uint8Array",
@@ -3656,6 +3682,9 @@ function buildSchemaInternal(type, checker, ctx, typeNode) {
3656
3682
  }
3657
3683
  if (type.aliasSymbol && !type.aliasTypeArguments?.length) {
3658
3684
  const aliasName = type.aliasSymbol.getName();
3685
+ if ((BUILTIN_TYPES.has(aliasName) || isBuiltinGeneric(aliasName)) && isBuiltinSymbol(type.aliasSymbol)) {
3686
+ return builtinSchema(aliasName);
3687
+ }
3659
3688
  if (!aliasName.startsWith("__") && !isPrimitiveName(aliasName)) {
3660
3689
  const packageOrigin = getTypeOrigin(type, checker);
3661
3690
  const schema = { $ref: `#/types/${namedRefId(type, aliasName, ctx)}` };
@@ -3888,6 +3917,7 @@ function buildSchemaInternal(type, checker, ctx, typeNode) {
3888
3917
  function buildFunctionSchema(callSignatures, checker, ctx) {
3889
3918
  const buildSignatures = () => {
3890
3919
  const signatures = callSignatures.map((sig) => {
3920
+ const taken = new Set(sig.getParameters().filter((p) => !bindingPatternKind(p.valueDeclaration)).map((p) => p.getName()));
3891
3921
  const params = sig.getParameters().flatMap((param) => {
3892
3922
  const decl = param.valueDeclaration;
3893
3923
  if (!decl)
@@ -3895,11 +3925,18 @@ function buildFunctionSchema(callSignatures, checker, ctx) {
3895
3925
  const paramType = checker.getTypeOfSymbolAtLocation(param, decl);
3896
3926
  const isOptional = !!decl?.questionToken || !!decl?.initializer;
3897
3927
  const effectiveType = isOptional ? stripUndefinedFromType(paramType, checker) : paramType;
3928
+ const pattern = bindingPatternKind(decl);
3929
+ let name = param.getName();
3930
+ if (pattern) {
3931
+ name = destructuredParamName(pattern, taken);
3932
+ taken.add(name);
3933
+ }
3898
3934
  return {
3899
- name: param.getName(),
3935
+ name,
3900
3936
  schema: buildSchema(effectiveType, checker, ctx, decl.type),
3901
3937
  required: !isOptional && !decl.dotDotDotToken,
3902
- ...decl.dotDotDotToken ? { rest: true } : {}
3938
+ ...decl.dotDotDotToken ? { rest: true } : {},
3939
+ ...pattern ? { "x-ts-destructured": true } : {}
3903
3940
  };
3904
3941
  });
3905
3942
  const returnType = checker.getReturnTypeOfSignature(sig);
@@ -4500,121 +4537,185 @@ function extractParameters(signature, ctx) {
4500
4537
  const result = [];
4501
4538
  const signatureDecl = signature.getDeclaration();
4502
4539
  const jsdocTags = signatureDecl ? ts7.getJSDocTags(signatureDecl) : [];
4540
+ const names = destructuredNames(signature.getParameters(), jsdocTags, checker);
4503
4541
  for (const param of signature.getParameters()) {
4504
4542
  const decl = param.valueDeclaration;
4505
4543
  if (!decl)
4506
4544
  continue;
4507
4545
  const defer = typeNodeDefersExpansion(decl.type, checker, ctx.program);
4508
4546
  const type = defer ? undefined : checker.getTypeOfSymbolAtLocation(param, decl);
4509
- if (decl && ts7.isObjectBindingPattern(decl.name)) {
4510
- const expandedParams = expandBindingPattern(decl, type ?? checker.getTypeOfSymbolAtLocation(param, decl), jsdocTags, ctx);
4511
- result.push(...expandedParams);
4512
- } else {
4513
- const isOptional = !!decl?.questionToken || !!decl?.initializer;
4514
- const isRest = !!decl.dotDotDotToken;
4515
- const paramName = param.getName();
4516
- const description = getParamDescription(paramName, jsdocTags);
4517
- const schema = defer ? buildSchemaFromTypeNode(decl.type, checker, ctx) : buildSchema(isOptional ? stripUndefinedFromType(type, checker) : type, checker, ctx, decl.type);
4518
- if (!defer && type) {
4519
- registerReferencedTypes(isOptional ? stripUndefinedFromType(type, checker) : type, ctx);
4520
- }
4521
- const paramResult = {
4522
- name: paramName,
4523
- schema,
4524
- required: !isOptional && !isRest,
4525
- ...isRest ? { rest: true } : {}
4526
- };
4527
- if (description) {
4528
- paramResult.description = description;
4529
- const inlineTags = parseInlineTags(description);
4530
- if (inlineTags)
4531
- paramResult.inlineTags = inlineTags;
4532
- }
4533
- if (decl.initializer) {
4534
- applyDefault(paramResult, decl.initializer);
4535
- }
4536
- result.push(paramResult);
4537
- }
4538
- }
4539
- return result;
4540
- }
4541
- function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
4542
- const { typeChecker: checker } = ctx;
4543
- const result = [];
4544
- const bindingPattern = paramDecl.name;
4545
- const allProperties = getEffectiveProperties(paramType, checker);
4546
- const inferredAlias = inferParamAlias(jsdocTags);
4547
- for (const element of bindingPattern.elements) {
4548
- if (!ts7.isBindingElement(element))
4549
- continue;
4550
- const propertyName = element.propertyName ? ts7.isIdentifier(element.propertyName) ? element.propertyName.text : element.propertyName.getText() : ts7.isIdentifier(element.name) ? element.name.text : element.name.getText();
4551
- const propSymbol = allProperties.get(propertyName);
4552
- if (!propSymbol)
4553
- continue;
4554
- const isOptional = !!(propSymbol.flags & ts7.SymbolFlags.Optional) || element.initializer !== undefined;
4555
- const propType = checker.getTypeOfSymbol(propSymbol);
4556
- const effectiveType = isOptional ? stripUndefinedFromType(propType, checker) : propType;
4557
- registerReferencedTypes(effectiveType, ctx);
4558
- const description = getParamDescription(propertyName, jsdocTags, inferredAlias);
4559
- const param = {
4560
- name: propertyName,
4561
- schema: buildSchema(effectiveType, checker, ctx, declaredTypeNode(propSymbol.valueDeclaration)),
4562
- required: !isOptional
4547
+ const isOptional = !!decl.questionToken || !!decl.initializer;
4548
+ const isRest = !!decl.dotDotDotToken;
4549
+ const pattern = bindingPatternKind(decl);
4550
+ const paramName = pattern ? names.get(param) ?? param.getName() : param.getName();
4551
+ const description = getParamDescription(paramName, jsdocTags);
4552
+ let schema = defer ? buildSchemaFromTypeNode(decl.type, checker, ctx) : buildSchema(isOptional ? stripUndefinedFromType(type, checker) : type, checker, ctx, decl.type);
4553
+ if (!defer && type) {
4554
+ registerReferencedTypes(isOptional ? stripUndefinedFromType(type, checker) : type, ctx);
4555
+ }
4556
+ if (pattern === "object") {
4557
+ schema = resolvedObjectSchema(schema, param, decl, isOptional, ctx);
4558
+ }
4559
+ const paramResult = {
4560
+ name: paramName,
4561
+ schema,
4562
+ required: !isOptional && !isRest,
4563
+ ...isRest ? { rest: true } : {},
4564
+ ...pattern ? { "x-ts-destructured": true } : {}
4563
4565
  };
4564
4566
  if (description) {
4565
- param.description = description;
4567
+ paramResult.description = description;
4566
4568
  const inlineTags = parseInlineTags(description);
4567
4569
  if (inlineTags)
4568
- param.inlineTags = inlineTags;
4570
+ paramResult.inlineTags = inlineTags;
4569
4571
  }
4570
- if (element.initializer) {
4571
- applyDefault(param, element.initializer);
4572
+ if (decl.initializer) {
4573
+ applyDefault(paramResult, decl.initializer);
4574
+ }
4575
+ if (pattern === "object") {
4576
+ annotateBindingElements(decl.name, paramResult, jsdocTags);
4572
4577
  }
4573
- result.push(param);
4578
+ result.push(paramResult);
4574
4579
  }
4575
4580
  return result;
4576
4581
  }
4577
- function getEffectiveProperties(type, _checker) {
4578
- const properties = new Map;
4579
- if (type.isIntersection()) {
4580
- for (const subType of type.types) {
4581
- for (const prop of subType.getProperties()) {
4582
- properties.set(prop.getName(), prop);
4583
- }
4582
+ function destructuredNames(params, jsdocTags, checker) {
4583
+ const names = new Map;
4584
+ const taken = new Set;
4585
+ const patterns = [];
4586
+ for (const param of params) {
4587
+ const decl = param.valueDeclaration;
4588
+ const kind = bindingPatternKind(decl);
4589
+ if (!kind || !decl) {
4590
+ taken.add(param.getName());
4591
+ continue;
4584
4592
  }
4585
- } else {
4586
- for (const prop of type.getProperties()) {
4587
- properties.set(prop.getName(), prop);
4593
+ patterns.push({ symbol: param, decl, kind });
4594
+ }
4595
+ if (patterns.length === 0)
4596
+ return names;
4597
+ const tagNames = jsdocTags.map(jsdocParamTagName).filter((n) => n && !n.startsWith("__"));
4598
+ if (tagNames.length === 0) {
4599
+ for (const { symbol, kind } of patterns) {
4600
+ const name = destructuredParamName(kind, taken);
4601
+ taken.add(name);
4602
+ names.set(symbol, name);
4588
4603
  }
4604
+ return names;
4589
4605
  }
4590
- return properties;
4591
- }
4592
- function inferParamAlias(jsdocTags) {
4593
- const prefixes = [];
4594
- for (const tag of jsdocTags) {
4595
- if (tag.tagName.text !== "param")
4606
+ const keys = new Set;
4607
+ for (const { symbol, decl } of patterns) {
4608
+ for (const element of decl.name.elements) {
4609
+ const key = bindingElementKey(element);
4610
+ if (key)
4611
+ keys.add(key);
4612
+ }
4613
+ const type = checker.getTypeOfSymbolAtLocation(symbol, decl);
4614
+ for (const prop of resolvedProperties(type, checker))
4615
+ keys.add(prop.getName());
4616
+ }
4617
+ const candidates = [];
4618
+ for (const tagName of tagNames) {
4619
+ const [head, ...rest] = tagName.split(".");
4620
+ if (taken.has(head))
4596
4621
  continue;
4597
- const tagText = typeof tag.comment === "string" ? tag.comment : ts7.getTextOfJSDocComment(tag.comment) ?? "";
4598
- const paramTag = tag;
4599
- const paramName = paramTag.name?.getText() ?? "";
4600
- if (paramName.includes(".")) {
4601
- const prefix = paramName.split(".")[0];
4602
- if (prefix && !prefix.startsWith("__")) {
4603
- prefixes.push(prefix);
4604
- }
4605
- } else if (tagText.includes(".")) {
4606
- const match = tagText.match(/^(\w+)\./);
4607
- if (match && !match[1].startsWith("__")) {
4608
- prefixes.push(match[1]);
4609
- }
4622
+ if (rest.length === 0 && keys.has(head))
4623
+ continue;
4624
+ if (!candidates.includes(head))
4625
+ candidates.push(head);
4626
+ }
4627
+ patterns.forEach(({ symbol, kind }, i) => {
4628
+ const name = destructuredParamName(kind, taken, candidates[i]);
4629
+ taken.add(name);
4630
+ names.set(symbol, name);
4631
+ });
4632
+ return names;
4633
+ }
4634
+ function bindingElementKey(element) {
4635
+ if (!ts7.isBindingElement(element) || element.dotDotDotToken)
4636
+ return;
4637
+ const key = element.propertyName ?? element.name;
4638
+ if (ts7.isIdentifier(key))
4639
+ return key.text;
4640
+ if (ts7.isStringLiteral(key) || ts7.isNumericLiteral(key))
4641
+ return key.text;
4642
+ return;
4643
+ }
4644
+ function resolvedProperties(type, checker) {
4645
+ const seen = new Map;
4646
+ for (const arm of objectArms(type, checker)) {
4647
+ for (const prop of armProperties(arm, checker)) {
4648
+ if (!seen.has(prop.getName()))
4649
+ seen.set(prop.getName(), prop);
4610
4650
  }
4611
4651
  }
4612
- if (prefixes.length === 0)
4652
+ return [...seen.values()];
4653
+ }
4654
+ var PRIMITIVE_LIKE = ts7.TypeFlags.StringLike | ts7.TypeFlags.NumberLike | ts7.TypeFlags.BigIntLike | ts7.TypeFlags.BooleanLike | ts7.TypeFlags.ESSymbolLike | ts7.TypeFlags.Void | ts7.TypeFlags.Undefined | ts7.TypeFlags.Null;
4655
+ function objectArms(type, checker) {
4656
+ const arms = type.isUnion() ? type.types : [type];
4657
+ return arms.filter((arm) => !(arm.flags & PRIMITIVE_LIKE) && armProperties(arm, checker).length > 0);
4658
+ }
4659
+ function armProperties(arm, checker) {
4660
+ const own = checker.getPropertiesOfType(arm);
4661
+ return own.length > 0 ? own : checker.getPropertiesOfType(checker.getApparentType(arm));
4662
+ }
4663
+ function resolvedObjectSchema(schema, param, decl, isOptional, ctx) {
4664
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
4665
+ return schema;
4666
+ const current = schema;
4667
+ if (current.properties || current.$ref)
4668
+ return schema;
4669
+ const { typeChecker: checker } = ctx;
4670
+ const raw = checker.getTypeOfSymbolAtLocation(param, decl);
4671
+ const type = isOptional ? stripUndefinedFromType(raw, checker) : raw;
4672
+ const arms = objectArms(type, checker);
4673
+ if (arms.length === 0)
4674
+ return schema;
4675
+ const props = resolvedProperties(type, checker);
4676
+ const resolved = buildObjectSchema(props, checker, ctx, type);
4677
+ if (arms.length > 1) {
4678
+ const requiredInAll = new Set(props.map((p) => p.getName()));
4679
+ for (const arm of arms) {
4680
+ const armRequired = new Set(armProperties(arm, checker).filter((p) => !(p.flags & ts7.SymbolFlags.Optional)).map((p) => p.getName()));
4681
+ for (const name of [...requiredInAll])
4682
+ if (!armRequired.has(name))
4683
+ requiredInAll.delete(name);
4684
+ }
4685
+ const required = resolved.required?.filter((n) => requiredInAll.has(n));
4686
+ if (required?.length)
4687
+ resolved.required = required;
4688
+ else
4689
+ delete resolved.required;
4690
+ }
4691
+ resolved["x-ts-type"] = renderTypeText(type, checker, decl);
4692
+ return resolved;
4693
+ }
4694
+ function annotateBindingElements(pattern, param, jsdocTags) {
4695
+ const schema = param.schema;
4696
+ const properties = schema?.properties;
4697
+ if (!properties)
4613
4698
  return;
4614
- const counts = new Map;
4615
- for (const p of prefixes)
4616
- counts.set(p, (counts.get(p) ?? 0) + 1);
4617
- return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
4699
+ for (const element of pattern.elements) {
4700
+ const propertyName = bindingElementKey(element);
4701
+ if (!propertyName)
4702
+ continue;
4703
+ const prop = properties[propertyName];
4704
+ if (!prop || typeof prop !== "object" || Array.isArray(prop))
4705
+ continue;
4706
+ const propSchema = prop;
4707
+ const description = getParamDescription(propertyName, jsdocTags, param.name);
4708
+ if (description && propSchema.description === undefined) {
4709
+ propSchema.description = description;
4710
+ }
4711
+ if (element.initializer) {
4712
+ const extracted = extractLiteralDefault(element.initializer);
4713
+ if (extracted.literal)
4714
+ propSchema.default = extracted.value;
4715
+ else
4716
+ propSchema["x-ts-default"] = extracted.text;
4717
+ }
4718
+ }
4618
4719
  }
4619
4720
  function extractLiteralDefault(initializer) {
4620
4721
  if (ts7.isStringLiteral(initializer)) {
@@ -6184,7 +6285,8 @@ function normalizeSignature(signature, options) {
6184
6285
  ...param.required !== undefined ? { required: param.required } : {},
6185
6286
  ...param.description ? { description: param.description } : {},
6186
6287
  ...param.default !== undefined ? { default: param.default } : {},
6187
- ...param.rest ? { rest: param.rest } : {}
6288
+ ...param.rest ? { rest: param.rest } : {},
6289
+ ...param["x-ts-destructured"] ? { "x-ts-destructured": true } : {}
6188
6290
  }));
6189
6291
  }
6190
6292
  if (signature.returns) {
@@ -97,7 +97,8 @@ function formatSchema(schema, options) {
97
97
  }
98
98
  if ("type" in schema && schema.type === "object") {
99
99
  if ("properties" in schema && schema.properties) {
100
- const props = Object.entries(schema.properties).map(([k, v]) => `${k}: ${formatSchema(v, nextOpts)}`).join("; ");
100
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
101
+ const props = Object.entries(schema.properties).map(([k, v]) => `${k}${required.has(k) ? "" : "?"}: ${formatSchema(v, nextOpts)}`).join("; ");
101
102
  return `{ ${props} }`;
102
103
  }
103
104
  return "object";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/sdk",
3
- "version": "0.54.10",
3
+ "version": "0.55.0",
4
4
  "description": "TypeScript API extraction SDK - programmatic primitives for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",
@@ -43,7 +43,7 @@
43
43
  "test": "bun test"
44
44
  },
45
45
  "dependencies": {
46
- "@openpkg-ts/spec": "^0.54.9",
46
+ "@openpkg-ts/spec": "^0.55.0",
47
47
  "picomatch": "4.0.3",
48
48
  "typescript": "^5.0.0 || ^6.0.0"
49
49
  },