@openpkg-ts/sdk 0.45.0 → 0.47.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/index.d.ts +187 -98
- package/dist/index.js +783 -82
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1848,9 +1848,13 @@ import ts4 from "typescript";
|
|
|
1848
1848
|
|
|
1849
1849
|
// src/types/schema-builder.ts
|
|
1850
1850
|
import ts3 from "typescript";
|
|
1851
|
+
|
|
1852
|
+
// src/schema/builtins.ts
|
|
1851
1853
|
var BUILTIN_TYPE_SCHEMAS = {
|
|
1854
|
+
Array: { type: "array" },
|
|
1855
|
+
ReadonlyArray: { type: "array" },
|
|
1852
1856
|
Date: { type: "string", format: "date-time" },
|
|
1853
|
-
RegExp: { type: "object"
|
|
1857
|
+
RegExp: { type: "object" },
|
|
1854
1858
|
Error: { type: "object" },
|
|
1855
1859
|
Promise: { type: "object" },
|
|
1856
1860
|
Map: { type: "object" },
|
|
@@ -1860,6 +1864,7 @@ var BUILTIN_TYPE_SCHEMAS = {
|
|
|
1860
1864
|
Function: { type: "object" },
|
|
1861
1865
|
ArrayBuffer: { type: "string", format: "binary" },
|
|
1862
1866
|
ArrayBufferLike: { type: "string", format: "binary" },
|
|
1867
|
+
SharedArrayBuffer: { type: "string", format: "binary" },
|
|
1863
1868
|
DataView: { type: "string", format: "binary" },
|
|
1864
1869
|
Uint8Array: { type: "string", format: "byte" },
|
|
1865
1870
|
Uint16Array: { type: "string", format: "byte" },
|
|
@@ -1872,6 +1877,32 @@ var BUILTIN_TYPE_SCHEMAS = {
|
|
|
1872
1877
|
BigInt64Array: { type: "string", format: "byte" },
|
|
1873
1878
|
BigUint64Array: { type: "string", format: "byte" }
|
|
1874
1879
|
};
|
|
1880
|
+
|
|
1881
|
+
// src/types/schema-builder.ts
|
|
1882
|
+
function escapeRegex(text) {
|
|
1883
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1884
|
+
}
|
|
1885
|
+
function buildTemplatePattern(type) {
|
|
1886
|
+
const slotPattern = (slot) => {
|
|
1887
|
+
if (slot.flags & ts3.TypeFlags.NumberLike)
|
|
1888
|
+
return "-?\\d+(?:\\.\\d+)?";
|
|
1889
|
+
if (slot.flags & ts3.TypeFlags.BigIntLike)
|
|
1890
|
+
return "-?\\d+";
|
|
1891
|
+
if (slot.flags & ts3.TypeFlags.BooleanLike)
|
|
1892
|
+
return "(?:true|false)";
|
|
1893
|
+
return ".*";
|
|
1894
|
+
};
|
|
1895
|
+
let pattern = `^${escapeRegex(type.texts[0] ?? "")}`;
|
|
1896
|
+
type.types.forEach((slot, i) => {
|
|
1897
|
+
pattern += slotPattern(slot) + escapeRegex(type.texts[i + 1] ?? "");
|
|
1898
|
+
});
|
|
1899
|
+
return `${pattern}$`;
|
|
1900
|
+
}
|
|
1901
|
+
function builtinSchema(name) {
|
|
1902
|
+
const schema = { ...BUILTIN_TYPE_SCHEMAS[name] ?? { type: "object" } };
|
|
1903
|
+
setSchemaExtension(schema, "x-ts-type", name);
|
|
1904
|
+
return schema;
|
|
1905
|
+
}
|
|
1875
1906
|
function setSchemaExtension(schema, key, value) {
|
|
1876
1907
|
schema[key] = value;
|
|
1877
1908
|
}
|
|
@@ -2169,9 +2200,15 @@ function buildSchema(type, checker, ctx) {
|
|
|
2169
2200
|
return ensureNonEmptySchema(schema, type, checker);
|
|
2170
2201
|
}
|
|
2171
2202
|
function buildMaxDepthSchema(type, checker) {
|
|
2203
|
+
if (type.flags & ts3.TypeFlags.TypeParameter && type.isThisType !== true) {
|
|
2204
|
+
return { "x-ts-type": checker.typeToString(type) };
|
|
2205
|
+
}
|
|
2172
2206
|
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
2173
2207
|
if (symbol && !isAnonymous(type)) {
|
|
2174
2208
|
const name = symbol.getName();
|
|
2209
|
+
if (BUILTIN_TYPES.has(name) || isBuiltinGeneric(name)) {
|
|
2210
|
+
return builtinSchema(name);
|
|
2211
|
+
}
|
|
2175
2212
|
if (!name.startsWith("__") && !isPrimitiveName(name)) {
|
|
2176
2213
|
return { $ref: `#/types/${name}` };
|
|
2177
2214
|
}
|
|
@@ -2188,6 +2225,13 @@ function buildMaxDepthSchema(type, checker) {
|
|
|
2188
2225
|
return { type: "null" };
|
|
2189
2226
|
if (type.flags & ts3.TypeFlags.Void)
|
|
2190
2227
|
return { type: "void" };
|
|
2228
|
+
if (type.flags & ts3.TypeFlags.TemplateLiteral) {
|
|
2229
|
+
return {
|
|
2230
|
+
type: "string",
|
|
2231
|
+
pattern: buildTemplatePattern(type),
|
|
2232
|
+
"x-ts-type": renderTypeText(type, checker)
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2191
2235
|
if (type.isUnion()) {
|
|
2192
2236
|
const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker));
|
|
2193
2237
|
return { anyOf: schemas };
|
|
@@ -2209,7 +2253,11 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2209
2253
|
}
|
|
2210
2254
|
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
2211
2255
|
if (symbol && !isAnonymous(type)) {
|
|
2212
|
-
|
|
2256
|
+
const name = symbol.getName();
|
|
2257
|
+
if (BUILTIN_TYPES.has(name) || isBuiltinGeneric(name)) {
|
|
2258
|
+
return builtinSchema(name);
|
|
2259
|
+
}
|
|
2260
|
+
return { $ref: `#/types/${name}` };
|
|
2213
2261
|
}
|
|
2214
2262
|
return { type: checker.typeToString(type) };
|
|
2215
2263
|
}
|
|
@@ -2250,6 +2298,9 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2250
2298
|
};
|
|
2251
2299
|
}
|
|
2252
2300
|
}
|
|
2301
|
+
if (type.flags & ts3.TypeFlags.TypeParameter) {
|
|
2302
|
+
return { "x-ts-type": checker.typeToString(type) };
|
|
2303
|
+
}
|
|
2253
2304
|
if (type.flags & ts3.TypeFlags.StringLiteral) {
|
|
2254
2305
|
const literal = type.value;
|
|
2255
2306
|
return { type: "string", enum: [literal] };
|
|
@@ -2273,6 +2324,16 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2273
2324
|
return schema;
|
|
2274
2325
|
}
|
|
2275
2326
|
}
|
|
2327
|
+
if (type.flags & ts3.TypeFlags.TemplateLiteral) {
|
|
2328
|
+
return {
|
|
2329
|
+
type: "string",
|
|
2330
|
+
pattern: buildTemplatePattern(type),
|
|
2331
|
+
"x-ts-type": renderTypeText(type, checker)
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
if (type.flags & ts3.TypeFlags.StringMapping) {
|
|
2335
|
+
return { type: "string", "x-ts-type": renderTypeText(type, checker) };
|
|
2336
|
+
}
|
|
2276
2337
|
if (type.isUnion()) {
|
|
2277
2338
|
const types = type.types;
|
|
2278
2339
|
const allStringLiterals = types.every((t) => t.flags & ts3.TypeFlags.StringLiteral);
|
|
@@ -2285,12 +2346,23 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2285
2346
|
const enumValues = types.map((t) => t.value);
|
|
2286
2347
|
return { type: "number", enum: enumValues };
|
|
2287
2348
|
}
|
|
2349
|
+
const allBooleanLiterals = types.every((t) => t.flags & ts3.TypeFlags.BooleanLiteral);
|
|
2350
|
+
if (allBooleanLiterals) {
|
|
2351
|
+
return { type: "boolean" };
|
|
2352
|
+
}
|
|
2353
|
+
const isBoolLiteral = (t) => !!(t.flags & ts3.TypeFlags.BooleanLiteral);
|
|
2354
|
+
let members = types;
|
|
2355
|
+
if (types.filter(isBoolLiteral).length === 2) {
|
|
2356
|
+
const firstBool = types.findIndex(isBoolLiteral);
|
|
2357
|
+
members = types.filter((t, i) => !isBoolLiteral(t) || i === firstBool);
|
|
2358
|
+
}
|
|
2359
|
+
const buildBranch = (t) => isBoolLiteral(t) ? { type: "boolean" } : buildSchema(t, checker, ctx);
|
|
2288
2360
|
if (ctx) {
|
|
2289
2361
|
return withDepth(ctx, () => ({
|
|
2290
|
-
anyOf:
|
|
2362
|
+
anyOf: members.map(buildBranch)
|
|
2291
2363
|
}));
|
|
2292
2364
|
}
|
|
2293
|
-
return { anyOf:
|
|
2365
|
+
return { anyOf: members.map(buildBranch) };
|
|
2294
2366
|
}
|
|
2295
2367
|
const isIntersectionType = type.isIntersection() || !!(type.flags & ts3.TypeFlags.Intersection);
|
|
2296
2368
|
if (isIntersectionType && "types" in type) {
|
|
@@ -2311,7 +2383,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2311
2383
|
}
|
|
2312
2384
|
const typeString = checker.typeToString(type);
|
|
2313
2385
|
if (typeString === "never[]" || typeString === "[]") {
|
|
2314
|
-
return { type: "array",
|
|
2386
|
+
return { type: "array", prefixItems: [], minItems: 0, maxItems: 0 };
|
|
2315
2387
|
}
|
|
2316
2388
|
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
2317
2389
|
if (symbol?.getName() === "Array" && isBuiltinSymbol(symbol)) {
|
|
@@ -2348,7 +2420,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2348
2420
|
try {
|
|
2349
2421
|
return {
|
|
2350
2422
|
type: "array",
|
|
2351
|
-
|
|
2423
|
+
prefixItems: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
2352
2424
|
minItems: elementTypes.length,
|
|
2353
2425
|
maxItems: elementTypes.length
|
|
2354
2426
|
};
|
|
@@ -2359,7 +2431,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2359
2431
|
}
|
|
2360
2432
|
return {
|
|
2361
2433
|
type: "array",
|
|
2362
|
-
|
|
2434
|
+
prefixItems: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
2363
2435
|
minItems: elementTypes.length,
|
|
2364
2436
|
maxItems: elementTypes.length
|
|
2365
2437
|
};
|
|
@@ -2370,9 +2442,16 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2370
2442
|
const symbol2 = typeRef.target.getSymbol();
|
|
2371
2443
|
const name = symbol2?.getName();
|
|
2372
2444
|
if (name && BUILTIN_TYPES.has(name)) {
|
|
2373
|
-
return
|
|
2445
|
+
return builtinSchema(name);
|
|
2374
2446
|
}
|
|
2375
|
-
if (name &&
|
|
2447
|
+
if (name && isBuiltinGeneric(name)) {
|
|
2448
|
+
const build = () => ({
|
|
2449
|
+
...builtinSchema(name),
|
|
2450
|
+
typeArguments: typeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
2451
|
+
});
|
|
2452
|
+
return ctx ? withDepth(ctx, build) : build();
|
|
2453
|
+
}
|
|
2454
|
+
if (name && !isAnonymous(typeRef.target)) {
|
|
2376
2455
|
const packageOrigin = getTypeOrigin(typeRef.target, checker);
|
|
2377
2456
|
if (ctx) {
|
|
2378
2457
|
return withDepth(ctx, () => {
|
|
@@ -2401,7 +2480,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2401
2480
|
if (aliasSymbol && aliasTypeArgs && aliasTypeArgs.length > 0) {
|
|
2402
2481
|
const name = aliasSymbol.getName();
|
|
2403
2482
|
if (BUILTIN_TYPES.has(name)) {
|
|
2404
|
-
return
|
|
2483
|
+
return builtinSchema(name);
|
|
2405
2484
|
}
|
|
2406
2485
|
if (RESOLVED_UTILITY_TYPES.has(name) && type.flags & ts3.TypeFlags.Object) {
|
|
2407
2486
|
const props = type.getProperties();
|
|
@@ -2410,7 +2489,14 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2410
2489
|
return buildObjectSchema(props, checker, ctx, type);
|
|
2411
2490
|
}
|
|
2412
2491
|
}
|
|
2413
|
-
if (isBuiltinGeneric(name)
|
|
2492
|
+
if (isBuiltinGeneric(name)) {
|
|
2493
|
+
const build = () => ({
|
|
2494
|
+
...builtinSchema(name),
|
|
2495
|
+
typeArguments: aliasTypeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
2496
|
+
});
|
|
2497
|
+
return ctx ? withDepth(ctx, build) : build();
|
|
2498
|
+
}
|
|
2499
|
+
if (!name.startsWith("__")) {
|
|
2414
2500
|
const packageOrigin = getTypeOrigin(type, checker);
|
|
2415
2501
|
if (ctx) {
|
|
2416
2502
|
return withDepth(ctx, () => {
|
|
@@ -2446,7 +2532,10 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2446
2532
|
return { type: name };
|
|
2447
2533
|
}
|
|
2448
2534
|
if (BUILTIN_TYPES.has(name)) {
|
|
2449
|
-
return
|
|
2535
|
+
return builtinSchema(name);
|
|
2536
|
+
}
|
|
2537
|
+
if (isBuiltinGeneric(name) && isBuiltinSymbol(symbol)) {
|
|
2538
|
+
return builtinSchema(name);
|
|
2450
2539
|
}
|
|
2451
2540
|
if (!name.startsWith("__")) {
|
|
2452
2541
|
const packageOrigin = getTypeOrigin(type, checker);
|
|
@@ -2460,7 +2549,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2460
2549
|
if (type.flags & ts3.TypeFlags.Object) {
|
|
2461
2550
|
const objectType = type;
|
|
2462
2551
|
const properties = type.getProperties();
|
|
2463
|
-
if (properties.length > 0 || objectType.objectFlags & ts3.ObjectFlags.Anonymous) {
|
|
2552
|
+
if (properties.length > 0 || objectType.objectFlags & ts3.ObjectFlags.Anonymous || checker.getIndexInfosOfType(type).length > 0) {
|
|
2464
2553
|
return buildObjectSchema(properties, checker, ctx, type);
|
|
2465
2554
|
}
|
|
2466
2555
|
}
|
|
@@ -2480,9 +2569,10 @@ function buildFunctionSchema(callSignatures, checker, ctx) {
|
|
|
2480
2569
|
return [];
|
|
2481
2570
|
const paramType = checker.getTypeOfSymbolAtLocation(param, decl);
|
|
2482
2571
|
const isOptional = !!decl?.questionToken || !!decl?.initializer;
|
|
2572
|
+
const effectiveType = isOptional ? stripUndefinedFromType(paramType, checker) : paramType;
|
|
2483
2573
|
return {
|
|
2484
2574
|
name: param.getName(),
|
|
2485
|
-
schema: buildSchema(
|
|
2575
|
+
schema: buildSchema(effectiveType, checker, ctx),
|
|
2486
2576
|
required: !isOptional
|
|
2487
2577
|
};
|
|
2488
2578
|
});
|
|
@@ -2503,6 +2593,8 @@ function buildFunctionSchema(callSignatures, checker, ctx) {
|
|
|
2503
2593
|
}
|
|
2504
2594
|
function buildObjectSchema(properties, checker, ctx, originalType) {
|
|
2505
2595
|
const isArrayLikeType = originalType ? checker.isArrayType(originalType) || checker.isTupleType(originalType) || originalType.symbol?.getName() === "Array" && isBuiltinSymbol(originalType.symbol) : false;
|
|
2596
|
+
const isStringLikeType = !!(originalType && originalType.flags & ts3.TypeFlags.StringLike);
|
|
2597
|
+
const isNumberLikeType = !!(originalType && originalType.flags & ts3.TypeFlags.NumberLike);
|
|
2506
2598
|
const buildProps = () => {
|
|
2507
2599
|
const props = {};
|
|
2508
2600
|
const required = [];
|
|
@@ -2513,7 +2605,15 @@ function buildObjectSchema(properties, checker, ctx, originalType) {
|
|
|
2513
2605
|
if (isArrayLikeType && ARRAY_PROTOTYPE_METHODS.has(propName)) {
|
|
2514
2606
|
continue;
|
|
2515
2607
|
}
|
|
2516
|
-
|
|
2608
|
+
if (isStringLikeType && STRING_PROTOTYPE_METHODS.has(propName)) {
|
|
2609
|
+
continue;
|
|
2610
|
+
}
|
|
2611
|
+
if (isNumberLikeType && NUMBER_PROTOTYPE_METHODS.has(propName)) {
|
|
2612
|
+
continue;
|
|
2613
|
+
}
|
|
2614
|
+
const isOptionalProp = !!(prop.flags & ts3.SymbolFlags.Optional);
|
|
2615
|
+
const rawPropType = checker.getTypeOfSymbol(prop);
|
|
2616
|
+
const propType = isOptionalProp ? stripUndefinedFromType(rawPropType, checker) : rawPropType;
|
|
2517
2617
|
let propSchema = buildSchema(propType, checker, ctx);
|
|
2518
2618
|
const docComment = prop.getDocumentationComment(checker);
|
|
2519
2619
|
if (docComment.length > 0) {
|
|
@@ -2538,11 +2638,19 @@ function buildObjectSchema(properties, checker, ctx, originalType) {
|
|
|
2538
2638
|
properties: props,
|
|
2539
2639
|
...required.length > 0 ? { required } : {}
|
|
2540
2640
|
};
|
|
2541
|
-
const
|
|
2641
|
+
const indexInfos = originalType ? checker.getIndexInfosOfType(originalType) : [];
|
|
2642
|
+
const stringIndex = indexInfos.find((i) => i.keyType.flags & ts3.TypeFlags.String);
|
|
2542
2643
|
if (stringIndex) {
|
|
2543
2644
|
schema.additionalProperties = buildSchema(stringIndex.type, checker, ctx);
|
|
2544
2645
|
}
|
|
2545
|
-
|
|
2646
|
+
const numberIndex = indexInfos.find((i) => i.keyType.flags & ts3.TypeFlags.Number);
|
|
2647
|
+
if (numberIndex) {
|
|
2648
|
+
schema.patternProperties = {
|
|
2649
|
+
"^\\d+$": buildSchema(numberIndex.type, checker, ctx)
|
|
2650
|
+
};
|
|
2651
|
+
setSchemaExtension(schema, "x-ts-index-key", "number");
|
|
2652
|
+
}
|
|
2653
|
+
if (Object.keys(props).length === 0 && originalType && !stringIndex && !numberIndex) {
|
|
2546
2654
|
setSchemaExtension(schema, "x-ts-type", checker.typeToString(originalType));
|
|
2547
2655
|
}
|
|
2548
2656
|
return schema;
|
|
@@ -2701,6 +2809,9 @@ function extractParameters(signature, ctx) {
|
|
|
2701
2809
|
if (description) {
|
|
2702
2810
|
paramResult.description = description;
|
|
2703
2811
|
}
|
|
2812
|
+
if (decl.initializer) {
|
|
2813
|
+
applyDefault(paramResult, decl.initializer);
|
|
2814
|
+
}
|
|
2704
2815
|
result.push(paramResult);
|
|
2705
2816
|
}
|
|
2706
2817
|
}
|
|
@@ -2733,7 +2844,7 @@ function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
|
|
|
2733
2844
|
param.description = description;
|
|
2734
2845
|
}
|
|
2735
2846
|
if (element.initializer) {
|
|
2736
|
-
param
|
|
2847
|
+
applyDefault(param, element.initializer);
|
|
2737
2848
|
}
|
|
2738
2849
|
result.push(param);
|
|
2739
2850
|
}
|
|
@@ -2781,23 +2892,37 @@ function inferParamAlias(jsdocTags) {
|
|
|
2781
2892
|
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
2782
2893
|
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
2783
2894
|
}
|
|
2784
|
-
function
|
|
2895
|
+
function extractLiteralDefault(initializer) {
|
|
2785
2896
|
if (ts4.isStringLiteral(initializer)) {
|
|
2786
|
-
return initializer.text;
|
|
2897
|
+
return { literal: true, value: initializer.text };
|
|
2787
2898
|
}
|
|
2788
2899
|
if (ts4.isNumericLiteral(initializer)) {
|
|
2789
|
-
return Number(initializer.text);
|
|
2900
|
+
return { literal: true, value: Number(initializer.text) };
|
|
2901
|
+
}
|
|
2902
|
+
if (ts4.isPrefixUnaryExpression(initializer) && initializer.operator === ts4.SyntaxKind.MinusToken && ts4.isNumericLiteral(initializer.operand)) {
|
|
2903
|
+
return { literal: true, value: -Number(initializer.operand.text) };
|
|
2790
2904
|
}
|
|
2791
2905
|
if (initializer.kind === ts4.SyntaxKind.TrueKeyword) {
|
|
2792
|
-
return true;
|
|
2906
|
+
return { literal: true, value: true };
|
|
2793
2907
|
}
|
|
2794
2908
|
if (initializer.kind === ts4.SyntaxKind.FalseKeyword) {
|
|
2795
|
-
return false;
|
|
2909
|
+
return { literal: true, value: false };
|
|
2796
2910
|
}
|
|
2797
2911
|
if (initializer.kind === ts4.SyntaxKind.NullKeyword) {
|
|
2798
|
-
return null;
|
|
2912
|
+
return { literal: true, value: null };
|
|
2913
|
+
}
|
|
2914
|
+
return { literal: false, text: initializer.getText() };
|
|
2915
|
+
}
|
|
2916
|
+
function applyDefault(param, initializer) {
|
|
2917
|
+
const extracted = extractLiteralDefault(initializer);
|
|
2918
|
+
if (extracted.literal) {
|
|
2919
|
+
param.default = extracted.value;
|
|
2920
|
+
if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
2921
|
+
param.schema.default = extracted.value;
|
|
2922
|
+
}
|
|
2923
|
+
} else if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
2924
|
+
param.schema["x-ts-default"] = extracted.text;
|
|
2799
2925
|
}
|
|
2800
|
-
return initializer.getText();
|
|
2801
2926
|
}
|
|
2802
2927
|
function registerReferencedTypes(type, ctx, depth = 0) {
|
|
2803
2928
|
if (depth > ctx.maxTypeDepth)
|
|
@@ -2826,6 +2951,10 @@ function registerReferencedTypes(type, ctx, depth = 0) {
|
|
|
2826
2951
|
registerReferencedTypes(t, ctx, depth + 1);
|
|
2827
2952
|
}
|
|
2828
2953
|
}
|
|
2954
|
+
const typeSymbol = type.aliasSymbol ?? type.getSymbol();
|
|
2955
|
+
if (typeSymbol && ctx.shouldExpandExternal && !typeSymbol.getName().startsWith("__") && !ctx.shouldExpandExternal(typeSymbol)) {
|
|
2956
|
+
return;
|
|
2957
|
+
}
|
|
2829
2958
|
if (type.flags & ts4.TypeFlags.Object) {
|
|
2830
2959
|
const props = type.getProperties();
|
|
2831
2960
|
const limit = ctx.maxProperties;
|
|
@@ -2960,6 +3089,16 @@ class TypeRegistry {
|
|
|
2960
3089
|
return;
|
|
2961
3090
|
if (this.has(name))
|
|
2962
3091
|
return name;
|
|
3092
|
+
if (ctx.shouldExpandExternal && !ctx.shouldExpandExternal(symbol)) {
|
|
3093
|
+
this.add({
|
|
3094
|
+
id: name,
|
|
3095
|
+
name,
|
|
3096
|
+
kind: "external",
|
|
3097
|
+
external: true,
|
|
3098
|
+
schema: { "x-ts-type": renderTypeText(type, ctx.typeChecker) }
|
|
3099
|
+
});
|
|
3100
|
+
return name;
|
|
3101
|
+
}
|
|
2963
3102
|
if (this.processing.has(name))
|
|
2964
3103
|
return name;
|
|
2965
3104
|
this.processing.add(name);
|
|
@@ -3007,10 +3146,15 @@ class TypeRegistry {
|
|
|
3007
3146
|
schema["x-ts-type"] = text;
|
|
3008
3147
|
}
|
|
3009
3148
|
}
|
|
3149
|
+
let typeParameters;
|
|
3150
|
+
if (decl && (ts5.isTypeAliasDeclaration(decl) || ts5.isInterfaceDeclaration(decl) || ts5.isClassDeclaration(decl))) {
|
|
3151
|
+
typeParameters = extractTypeParameters(decl, checker);
|
|
3152
|
+
}
|
|
3010
3153
|
return {
|
|
3011
3154
|
id: name,
|
|
3012
3155
|
name,
|
|
3013
3156
|
kind,
|
|
3157
|
+
...typeParameters && typeParameters.length > 0 ? { typeParameters } : {},
|
|
3014
3158
|
schema,
|
|
3015
3159
|
...external ? { external: true } : {}
|
|
3016
3160
|
};
|
|
@@ -3057,7 +3201,7 @@ class TypeRegistry {
|
|
|
3057
3201
|
const elementTypes = checker.getTypeArguments(type) ?? [];
|
|
3058
3202
|
return {
|
|
3059
3203
|
type: "array",
|
|
3060
|
-
|
|
3204
|
+
prefixItems: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
3061
3205
|
minItems: elementTypes.length,
|
|
3062
3206
|
maxItems: elementTypes.length
|
|
3063
3207
|
};
|
|
@@ -3066,6 +3210,9 @@ class TypeRegistry {
|
|
|
3066
3210
|
const elementType = checker.getTypeArguments(type)?.[0];
|
|
3067
3211
|
return elementType ? { type: "array", items: buildSchema(elementType, checker, ctx) } : { type: "array" };
|
|
3068
3212
|
}
|
|
3213
|
+
if (type.flags & ts5.TypeFlags.Conditional) {
|
|
3214
|
+
return { "x-ts-type": renderTypeText(type, checker) };
|
|
3215
|
+
}
|
|
3069
3216
|
return this.buildObjectSchemaFromProperties(type, checker, ctx);
|
|
3070
3217
|
}
|
|
3071
3218
|
buildEnumSchema(symbol, checker) {
|
|
@@ -3095,8 +3242,10 @@ class TypeRegistry {
|
|
|
3095
3242
|
}
|
|
3096
3243
|
buildObjectSchemaFromProperties(type, checker, ctx) {
|
|
3097
3244
|
const properties = type.getProperties();
|
|
3098
|
-
const
|
|
3099
|
-
|
|
3245
|
+
const indexInfos = checker.getIndexInfosOfType(type);
|
|
3246
|
+
const stringIndex = indexInfos.find((i) => i.keyType.flags & ts5.TypeFlags.String);
|
|
3247
|
+
const numberIndex = indexInfos.find((i) => i.keyType.flags & ts5.TypeFlags.Number);
|
|
3248
|
+
if (properties.length === 0 && !stringIndex && !numberIndex) {
|
|
3100
3249
|
return { type: checker.typeToString(type) };
|
|
3101
3250
|
}
|
|
3102
3251
|
const props = {};
|
|
@@ -3123,7 +3272,8 @@ class TypeRegistry {
|
|
|
3123
3272
|
}
|
|
3124
3273
|
for (const prop of included.slice(0, limit)) {
|
|
3125
3274
|
const propName = prop.getName();
|
|
3126
|
-
const
|
|
3275
|
+
const rawPropType = checker.getTypeOfSymbol(prop);
|
|
3276
|
+
const propType = prop.flags & ts5.SymbolFlags.Optional ? stripUndefinedFromType(rawPropType, checker) : rawPropType;
|
|
3127
3277
|
this.registerType(propType, ctx);
|
|
3128
3278
|
let propSchema = buildSchema(propType, checker, ctx);
|
|
3129
3279
|
const docComment = prop.getDocumentationComment(checker);
|
|
@@ -3148,7 +3298,11 @@ class TypeRegistry {
|
|
|
3148
3298
|
type: "object",
|
|
3149
3299
|
properties: props,
|
|
3150
3300
|
...required.length > 0 ? { required } : {},
|
|
3151
|
-
...stringIndex ? { additionalProperties: buildSchema(stringIndex.type, checker, ctx) } : {}
|
|
3301
|
+
...stringIndex ? { additionalProperties: buildSchema(stringIndex.type, checker, ctx) } : {},
|
|
3302
|
+
...numberIndex ? {
|
|
3303
|
+
patternProperties: { "^\\d+$": buildSchema(numberIndex.type, checker, ctx) },
|
|
3304
|
+
"x-ts-index-key": "number"
|
|
3305
|
+
} : {}
|
|
3152
3306
|
};
|
|
3153
3307
|
}
|
|
3154
3308
|
}
|
|
@@ -3169,7 +3323,8 @@ function createContext(program, sourceFile, options = {}) {
|
|
|
3169
3323
|
registeredTypes: new Set,
|
|
3170
3324
|
includePrivate: options.includePrivate ?? false,
|
|
3171
3325
|
maxProperties: options.maxProperties ?? 500,
|
|
3172
|
-
onTruncation: options.onTruncation
|
|
3326
|
+
onTruncation: options.onTruncation,
|
|
3327
|
+
shouldExpandExternal: options.shouldExpandExternal
|
|
3173
3328
|
};
|
|
3174
3329
|
}
|
|
3175
3330
|
function getInheritedMembers(classType, ownMemberNames, ctx, isStatic = false) {
|
|
@@ -3297,7 +3452,7 @@ function serializeInheritedMember(symbol, inheritedFrom, ctx, isStatic) {
|
|
|
3297
3452
|
description,
|
|
3298
3453
|
tags: tags.length > 0 ? tags : undefined,
|
|
3299
3454
|
visibility,
|
|
3300
|
-
schema: kind !== "method" ? buildSchema(type, checker, ctx) :
|
|
3455
|
+
schema: kind !== "method" ? buildSchema(type, checker, ctx) : decoratePropertySchema({ "x-ts-function": true }, symbol, type, checker),
|
|
3301
3456
|
signatures,
|
|
3302
3457
|
flags: Object.keys(flags).length > 0 ? flags : undefined
|
|
3303
3458
|
};
|
|
@@ -3458,7 +3613,8 @@ function serializeProperty(node, ctx) {
|
|
|
3458
3613
|
if (!ctx.includePrivate && (visibility === "private" || visibility === "protected")) {
|
|
3459
3614
|
return null;
|
|
3460
3615
|
}
|
|
3461
|
-
const
|
|
3616
|
+
const rawType = checker.getTypeAtLocation(node);
|
|
3617
|
+
const type = node.questionToken ? stripUndefinedFromType(rawType, checker) : rawType;
|
|
3462
3618
|
registerReferencedTypes(type, ctx);
|
|
3463
3619
|
let schema = buildSchema(type, checker, ctx);
|
|
3464
3620
|
const flags = {};
|
|
@@ -3512,12 +3668,14 @@ function serializeMethod(node, ctx) {
|
|
|
3512
3668
|
}
|
|
3513
3669
|
const symbol = checker.getSymbolAtLocation(node.name ?? node);
|
|
3514
3670
|
const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
|
|
3671
|
+
const schema = symbol ? decoratePropertySchema({ "x-ts-function": true }, symbol, type, checker) : undefined;
|
|
3515
3672
|
return {
|
|
3516
3673
|
name,
|
|
3517
3674
|
kind: "method",
|
|
3518
3675
|
description,
|
|
3519
3676
|
tags: tags.length > 0 ? tags : undefined,
|
|
3520
3677
|
visibility,
|
|
3678
|
+
schema,
|
|
3521
3679
|
signatures: signatures.length > 0 ? signatures : undefined,
|
|
3522
3680
|
flags: Object.keys(flags).length > 0 ? flags : undefined,
|
|
3523
3681
|
...deprecated ? { deprecated: true, deprecationReason } : {}
|
|
@@ -3850,7 +4008,8 @@ function serializePropertySignature(node, ctx) {
|
|
|
3850
4008
|
const { typeChecker: checker } = ctx;
|
|
3851
4009
|
const name = node.name.getText();
|
|
3852
4010
|
const { description, tags } = getJSDocComment(node);
|
|
3853
|
-
const
|
|
4011
|
+
const rawType = checker.getTypeAtLocation(node);
|
|
4012
|
+
const type = node.questionToken ? stripUndefinedFromType(rawType, checker) : rawType;
|
|
3854
4013
|
let schema = buildSchema(type, checker, ctx);
|
|
3855
4014
|
registerReferencedTypes(type, ctx);
|
|
3856
4015
|
const flags = {};
|
|
@@ -3887,11 +4046,13 @@ function serializeMethodSignature(node, ctx) {
|
|
|
3887
4046
|
flags.methodSyntax = true;
|
|
3888
4047
|
const symbol = checker.getSymbolAtLocation(node.name);
|
|
3889
4048
|
const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
|
|
4049
|
+
const schema = symbol ? decoratePropertySchema({ "x-ts-function": true }, symbol, type, checker) : undefined;
|
|
3890
4050
|
return {
|
|
3891
4051
|
name,
|
|
3892
4052
|
kind: "method",
|
|
3893
4053
|
description,
|
|
3894
4054
|
tags: tags.length > 0 ? tags : undefined,
|
|
4055
|
+
schema,
|
|
3895
4056
|
signatures: signatures.length > 0 ? signatures : undefined,
|
|
3896
4057
|
flags: Object.keys(flags).length > 0 ? flags : undefined,
|
|
3897
4058
|
...deprecated ? { deprecated: true, deprecationReason } : {}
|
|
@@ -3989,7 +4150,7 @@ function serializeTypeAlias(node, ctx) {
|
|
|
3989
4150
|
}
|
|
3990
4151
|
} else if (isInlineFunctionAlias(node.type) && type.getCallSignatures().length > 0) {
|
|
3991
4152
|
schema = buildFunctionSchema(type.getCallSignatures(), ctx.typeChecker, ctx);
|
|
3992
|
-
} else if ((ts10.isMappedTypeNode(node.type) || ts10.isConditionalTypeNode(node.type)) && type.getProperties().length > 0 && type.getCallSignatures().length === 0) {
|
|
4153
|
+
} else if ((ts10.isMappedTypeNode(node.type) || ts10.isConditionalTypeNode(node.type)) && type.getProperties().length > 0 && type.getCallSignatures().length === 0 && !(type.flags & ts10.TypeFlags.Conditional) && !(type.flags & (ts10.TypeFlags.StringLike | ts10.TypeFlags.NumberLike))) {
|
|
3993
4154
|
schema = buildObjectSchema(type.getProperties(), ctx.typeChecker, ctx, type);
|
|
3994
4155
|
members = serializeResolvedMembers(type, node, ctx);
|
|
3995
4156
|
} else {
|
|
@@ -4112,10 +4273,7 @@ function serializeResolvedMembers(type, node, ctx) {
|
|
|
4112
4273
|
flags.readonly = true;
|
|
4113
4274
|
if (prop.flags & ts10.SymbolFlags.Method)
|
|
4114
4275
|
flags.methodSyntax = true;
|
|
4115
|
-
|
|
4116
|
-
if (kind === "property") {
|
|
4117
|
-
schema = decoratePropertySchema(buildSchema(propType, checker, ctx), prop, propType, checker);
|
|
4118
|
-
}
|
|
4276
|
+
const schema = kind === "property" ? decoratePropertySchema(buildSchema(propType, checker, ctx), prop, propType, checker) : decoratePropertySchema({ "x-ts-function": true }, prop, propType, checker);
|
|
4119
4277
|
members.push({
|
|
4120
4278
|
name: prop.getName(),
|
|
4121
4279
|
kind,
|
|
@@ -4324,10 +4482,7 @@ function serializeVariable(node, statement, ctx) {
|
|
|
4324
4482
|
}
|
|
4325
4483
|
|
|
4326
4484
|
// src/types/schema-normalizer.ts
|
|
4327
|
-
|
|
4328
|
-
"draft-2020-12": "https://json-schema.org/draft/2020-12/schema",
|
|
4329
|
-
"draft-07": "http://json-schema.org/draft-07/schema#"
|
|
4330
|
-
};
|
|
4485
|
+
import { JSON_SCHEMA_DRAFT } from "@openpkg-ts/spec";
|
|
4331
4486
|
var TS_PRIMITIVE_NORMALIZATIONS = {
|
|
4332
4487
|
void: () => ({ type: "null", "x-ts-type": "void" }),
|
|
4333
4488
|
never: () => ({ not: {} }),
|
|
@@ -4338,11 +4493,11 @@ var TS_PRIMITIVE_NORMALIZATIONS = {
|
|
|
4338
4493
|
symbol: () => ({ type: "string", "x-ts-type": "symbol" })
|
|
4339
4494
|
};
|
|
4340
4495
|
function normalizeSchema(schema, options = {}) {
|
|
4341
|
-
const { includeSchemaField = false
|
|
4496
|
+
const { includeSchemaField = false } = options;
|
|
4342
4497
|
const normalized = normalizeSchemaInternal(schema, options);
|
|
4343
4498
|
if (includeSchemaField && typeof normalized === "object") {
|
|
4344
4499
|
return {
|
|
4345
|
-
$schema:
|
|
4500
|
+
$schema: JSON_SCHEMA_DRAFT,
|
|
4346
4501
|
...normalized
|
|
4347
4502
|
};
|
|
4348
4503
|
}
|
|
@@ -4363,6 +4518,9 @@ function normalizeSchemaInternal(schema, options) {
|
|
|
4363
4518
|
result[key] = s[key];
|
|
4364
4519
|
}
|
|
4365
4520
|
}
|
|
4521
|
+
if (Array.isArray(s.typeArguments) && s.typeArguments.length > 0 && result["x-ts-type-arguments"] === undefined) {
|
|
4522
|
+
result["x-ts-type-arguments"] = s.typeArguments.map((arg) => normalizeSchemaInternal(arg, options));
|
|
4523
|
+
}
|
|
4366
4524
|
}
|
|
4367
4525
|
return result;
|
|
4368
4526
|
}
|
|
@@ -4468,14 +4626,14 @@ function normalizeSignature(signature, options) {
|
|
|
4468
4626
|
}
|
|
4469
4627
|
function normalizeTupleType(schema, options) {
|
|
4470
4628
|
const result = { type: "array" };
|
|
4471
|
-
|
|
4472
|
-
|
|
4629
|
+
const prefix = Array.isArray(schema.prefixItems) ? schema.prefixItems : Array.isArray(schema.prefixedItems) ? schema.prefixedItems : undefined;
|
|
4630
|
+
if (prefix) {
|
|
4631
|
+
result.prefixItems = prefix.map((item) => normalizeSchemaInternal(item, options));
|
|
4632
|
+
} else if ("items" in schema && Array.isArray(schema.items)) {
|
|
4633
|
+
result.prefixItems = schema.items.map((item) => normalizeSchemaInternal(item, options));
|
|
4473
4634
|
result.minItems = schema.items.length;
|
|
4474
4635
|
result.maxItems = schema.items.length;
|
|
4475
4636
|
}
|
|
4476
|
-
if ("prefixedItems" in schema && Array.isArray(schema.prefixedItems)) {
|
|
4477
|
-
result.prefixedItems = schema.prefixedItems.map((item) => normalizeSchemaInternal(item, options));
|
|
4478
|
-
}
|
|
4479
4637
|
if ("minItems" in schema && typeof schema.minItems === "number") {
|
|
4480
4638
|
result.minItems = schema.minItems;
|
|
4481
4639
|
}
|
|
@@ -4492,8 +4650,9 @@ function normalizeArrayType(schema, options) {
|
|
|
4492
4650
|
if ("items" in schema && schema.items && !Array.isArray(schema.items)) {
|
|
4493
4651
|
result.items = normalizeSchemaInternal(schema.items, options);
|
|
4494
4652
|
}
|
|
4495
|
-
|
|
4496
|
-
|
|
4653
|
+
const arrayPrefix = Array.isArray(schema.prefixItems) ? schema.prefixItems : Array.isArray(schema.prefixedItems) ? schema.prefixedItems : undefined;
|
|
4654
|
+
if (arrayPrefix) {
|
|
4655
|
+
result.prefixItems = arrayPrefix.map((item) => normalizeSchemaInternal(item, options));
|
|
4497
4656
|
}
|
|
4498
4657
|
if ("minItems" in schema && typeof schema.minItems === "number") {
|
|
4499
4658
|
result.minItems = schema.minItems;
|
|
@@ -4501,6 +4660,17 @@ function normalizeArrayType(schema, options) {
|
|
|
4501
4660
|
if ("maxItems" in schema && typeof schema.maxItems === "number") {
|
|
4502
4661
|
result.maxItems = schema.maxItems;
|
|
4503
4662
|
}
|
|
4663
|
+
if (schema.uniqueItems === true) {
|
|
4664
|
+
result.uniqueItems = true;
|
|
4665
|
+
}
|
|
4666
|
+
if (schema.contains && typeof schema.contains === "object") {
|
|
4667
|
+
result.contains = normalizeSchemaInternal(schema.contains, options);
|
|
4668
|
+
}
|
|
4669
|
+
for (const keyword of ["title", "default"]) {
|
|
4670
|
+
if (keyword in schema && schema[keyword] !== undefined) {
|
|
4671
|
+
result[keyword] = schema[keyword];
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4504
4674
|
if ("description" in schema && schema.description) {
|
|
4505
4675
|
result.description = schema.description;
|
|
4506
4676
|
}
|
|
@@ -4525,6 +4695,23 @@ function normalizeObjectType(schema, options) {
|
|
|
4525
4695
|
result.additionalProperties = normalizeSchemaInternal(schema.additionalProperties, options);
|
|
4526
4696
|
}
|
|
4527
4697
|
}
|
|
4698
|
+
for (const keyword of ["patternProperties", "$defs"]) {
|
|
4699
|
+
const value = schema[keyword];
|
|
4700
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
4701
|
+
result[keyword] = Object.fromEntries(Object.entries(value).map(([key, nested]) => [
|
|
4702
|
+
key,
|
|
4703
|
+
normalizeSchemaInternal(nested, options)
|
|
4704
|
+
]));
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
if (schema.propertyNames && typeof schema.propertyNames === "object") {
|
|
4708
|
+
result.propertyNames = normalizeSchemaInternal(schema.propertyNames, options);
|
|
4709
|
+
}
|
|
4710
|
+
for (const keyword of ["title", "default", "examples", "minProperties", "maxProperties"]) {
|
|
4711
|
+
if (keyword in schema && schema[keyword] !== undefined) {
|
|
4712
|
+
result[keyword] = schema[keyword];
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4528
4715
|
if ("description" in schema && schema.description) {
|
|
4529
4716
|
result.description = schema.description;
|
|
4530
4717
|
}
|
|
@@ -4631,7 +4818,7 @@ function isSchemaLike(value) {
|
|
|
4631
4818
|
if (typeof value === "string")
|
|
4632
4819
|
return true;
|
|
4633
4820
|
const obj = value;
|
|
4634
|
-
return "type" in obj || "$ref" in obj || "anyOf" in obj || "allOf" in obj || "oneOf" in obj || "properties" in obj || "items" in obj || "prefixedItems" in obj;
|
|
4821
|
+
return "type" in obj || "$ref" in obj || "anyOf" in obj || "allOf" in obj || "oneOf" in obj || "properties" in obj || "items" in obj || "prefixItems" in obj || "prefixedItems" in obj;
|
|
4635
4822
|
}
|
|
4636
4823
|
function mergeSchemaFields(target, source, excludeKeys) {
|
|
4637
4824
|
if (typeof source !== "object" || source == null) {
|
|
@@ -4648,9 +4835,13 @@ function mergeSchemaFields(target, source, excludeKeys) {
|
|
|
4648
4835
|
}
|
|
4649
4836
|
return result;
|
|
4650
4837
|
}
|
|
4838
|
+
function isVendorSchemaExport(exp) {
|
|
4839
|
+
return !!exp.tags?.some((t) => t.name === "schema-source" && t.text === "standard-json-schema");
|
|
4840
|
+
}
|
|
4651
4841
|
function normalizeExport(exp, options = {}) {
|
|
4652
4842
|
const result = { ...exp };
|
|
4653
|
-
|
|
4843
|
+
const vendorSchema = isVendorSchemaExport(exp);
|
|
4844
|
+
if (exp.schema && !vendorSchema) {
|
|
4654
4845
|
result.schema = normalizeSchema(exp.schema, options);
|
|
4655
4846
|
}
|
|
4656
4847
|
if (exp.signatures) {
|
|
@@ -4659,7 +4850,7 @@ function normalizeExport(exp, options = {}) {
|
|
|
4659
4850
|
if (exp.members) {
|
|
4660
4851
|
result.members = exp.members.map((member) => normalizeMember(member, options));
|
|
4661
4852
|
}
|
|
4662
|
-
if (shouldGenerateMembersSchema(exp.kind) && exp.members && exp.members.length > 0) {
|
|
4853
|
+
if (!vendorSchema && shouldGenerateMembersSchema(exp.kind) && exp.members && exp.members.length > 0) {
|
|
4663
4854
|
result.schema = normalizeMembers(exp.members, options);
|
|
4664
4855
|
}
|
|
4665
4856
|
return result;
|
|
@@ -4710,10 +4901,15 @@ function normalizeMembers(members, options = {}) {
|
|
|
4710
4901
|
const properties = {};
|
|
4711
4902
|
const required = [];
|
|
4712
4903
|
let additionalProperties;
|
|
4904
|
+
let numberIndexSchema;
|
|
4713
4905
|
for (const member of members) {
|
|
4714
4906
|
const { name, kind } = member;
|
|
4715
4907
|
if (kind === "index" || kind === "index-signature") {
|
|
4716
|
-
|
|
4908
|
+
if (name === "[number]") {
|
|
4909
|
+
numberIndexSchema = normalizeMemberToSchema(member, options);
|
|
4910
|
+
} else {
|
|
4911
|
+
additionalProperties = normalizeMemberToSchema(member, options);
|
|
4912
|
+
}
|
|
4717
4913
|
continue;
|
|
4718
4914
|
}
|
|
4719
4915
|
if (!name)
|
|
@@ -4734,6 +4930,10 @@ function normalizeMembers(members, options = {}) {
|
|
|
4734
4930
|
if (additionalProperties !== undefined) {
|
|
4735
4931
|
result.additionalProperties = additionalProperties;
|
|
4736
4932
|
}
|
|
4933
|
+
if (numberIndexSchema !== undefined) {
|
|
4934
|
+
result.patternProperties = { "^\\d+$": numberIndexSchema };
|
|
4935
|
+
result["x-ts-index-key"] = "number";
|
|
4936
|
+
}
|
|
4737
4937
|
return result;
|
|
4738
4938
|
}
|
|
4739
4939
|
function memberDocExtras(member) {
|
|
@@ -4794,6 +4994,10 @@ function normalizeMethodMember(member, options) {
|
|
|
4794
4994
|
if (member.flags?.methodSyntax === true) {
|
|
4795
4995
|
result["x-ts-method"] = true;
|
|
4796
4996
|
}
|
|
4997
|
+
const memberTypeText = member.schema && typeof member.schema === "object" ? member.schema["x-ts-type"] : undefined;
|
|
4998
|
+
if (typeof memberTypeText === "string") {
|
|
4999
|
+
result["x-ts-type"] = memberTypeText;
|
|
5000
|
+
}
|
|
4797
5001
|
if (member.signatures && member.signatures.length > 0) {
|
|
4798
5002
|
result["x-ts-signatures"] = member.signatures.map((sig) => normalizeSignature(sig, options));
|
|
4799
5003
|
}
|
|
@@ -4848,9 +5052,9 @@ async function getExport(options) {
|
|
|
4848
5052
|
const isNamespaceExportDecl = originalDecls.some((d) => ts11.isNamespaceExport(d) || ts11.isNamespaceImport(d));
|
|
4849
5053
|
if (isNamespaceExportDecl) {
|
|
4850
5054
|
const spec2 = serializeNamespaceForGet(targetSymbol, exportName, ctx);
|
|
4851
|
-
const types2 = ctx.typeRegistry.getAll().map((t) => normalizeType(t
|
|
5055
|
+
const types2 = ctx.typeRegistry.getAll().map((t) => normalizeType(t));
|
|
4852
5056
|
return {
|
|
4853
|
-
export: normalizeExport(spec2
|
|
5057
|
+
export: normalizeExport(spec2),
|
|
4854
5058
|
types: types2,
|
|
4855
5059
|
errors
|
|
4856
5060
|
};
|
|
@@ -4883,8 +5087,8 @@ async function getExport(options) {
|
|
|
4883
5087
|
}
|
|
4884
5088
|
return { export: null, types: [], errors: [`Could not serialize '${exportName}'`] };
|
|
4885
5089
|
}
|
|
4886
|
-
spec = normalizeExport(spec
|
|
4887
|
-
const types = ctx.typeRegistry.getAll().map((t) => normalizeType(t
|
|
5090
|
+
spec = normalizeExport(spec);
|
|
5091
|
+
const types = ctx.typeRegistry.getAll().map((t) => normalizeType(t));
|
|
4888
5092
|
return { export: spec, types, errors };
|
|
4889
5093
|
} catch (err) {
|
|
4890
5094
|
errors.push(`Failed to serialize '${exportName}': ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -6012,12 +6216,7 @@ var NODE_MODULES_PKG = /node_modules\/(@[^/]+\/[^/]+|[^/]+)/;
|
|
|
6012
6216
|
function isLibFile(fileName) {
|
|
6013
6217
|
return fileName.includes("/typescript/lib/lib.") || fileName.includes("\\typescript\\lib\\lib.");
|
|
6014
6218
|
}
|
|
6015
|
-
function
|
|
6016
|
-
if (opts.followExternal === false)
|
|
6017
|
-
return;
|
|
6018
|
-
const checker = ctx.typeChecker;
|
|
6019
|
-
const visited = new Set;
|
|
6020
|
-
const MAX_DEPTH = 30;
|
|
6219
|
+
function createExternalExpansionPredicate(opts) {
|
|
6021
6220
|
const packageAllowed = (pkg) => {
|
|
6022
6221
|
if (pkg === "typescript")
|
|
6023
6222
|
return false;
|
|
@@ -6027,6 +6226,25 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6027
6226
|
return true;
|
|
6028
6227
|
return opts.workspacePackages.has(pkg);
|
|
6029
6228
|
};
|
|
6229
|
+
return (symbol) => {
|
|
6230
|
+
const decl = symbol.declarations?.[0];
|
|
6231
|
+
if (!decl)
|
|
6232
|
+
return false;
|
|
6233
|
+
const fileName = decl.getSourceFile().fileName;
|
|
6234
|
+
if (isLibFile(fileName))
|
|
6235
|
+
return false;
|
|
6236
|
+
const match = fileName.match(NODE_MODULES_PKG);
|
|
6237
|
+
if (match)
|
|
6238
|
+
return packageAllowed(match[1]);
|
|
6239
|
+
return true;
|
|
6240
|
+
};
|
|
6241
|
+
}
|
|
6242
|
+
function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
6243
|
+
if (opts.followExternal === false)
|
|
6244
|
+
return;
|
|
6245
|
+
const checker = ctx.typeChecker;
|
|
6246
|
+
const visited = new Set;
|
|
6247
|
+
const MAX_DEPTH = 30;
|
|
6030
6248
|
const entryPackageDir = findPackageDir(opts.entryFile);
|
|
6031
6249
|
const packageLabel = (fileName) => {
|
|
6032
6250
|
const match = fileName.match(NODE_MODULES_PKG);
|
|
@@ -6041,18 +6259,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6041
6259
|
}
|
|
6042
6260
|
return (pkg ?? "local").replace(/^@/, "").replace(/\//g, "-");
|
|
6043
6261
|
};
|
|
6044
|
-
const symbolAllowed = (
|
|
6045
|
-
const decl = symbol.declarations?.[0];
|
|
6046
|
-
if (!decl)
|
|
6047
|
-
return false;
|
|
6048
|
-
const fileName = decl.getSourceFile().fileName;
|
|
6049
|
-
if (isLibFile(fileName))
|
|
6050
|
-
return false;
|
|
6051
|
-
const match = fileName.match(NODE_MODULES_PKG);
|
|
6052
|
-
if (match)
|
|
6053
|
-
return packageAllowed(match[1]);
|
|
6054
|
-
return true;
|
|
6055
|
-
};
|
|
6262
|
+
const symbolAllowed = createExternalExpansionPredicate(opts);
|
|
6056
6263
|
const visit = (type, depth) => {
|
|
6057
6264
|
if (!type || depth > MAX_DEPTH || visited.has(type))
|
|
6058
6265
|
return;
|
|
@@ -6564,7 +6771,11 @@ async function extract(options) {
|
|
|
6564
6771
|
resolveExternalTypes,
|
|
6565
6772
|
includePrivate,
|
|
6566
6773
|
maxProperties,
|
|
6567
|
-
onTruncation
|
|
6774
|
+
onTruncation,
|
|
6775
|
+
shouldExpandExternal: createExternalExpansionPredicate({
|
|
6776
|
+
followExternal: options.followExternal,
|
|
6777
|
+
workspacePackages: result.workspacePackages ?? new Map
|
|
6778
|
+
})
|
|
6568
6779
|
});
|
|
6569
6780
|
ctx.exportedIds = exportedIds;
|
|
6570
6781
|
const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
|
|
@@ -6734,7 +6945,7 @@ async function extract(options) {
|
|
|
6734
6945
|
if (options.schemaExtraction === "hybrid") {
|
|
6735
6946
|
const projectBaseDir2 = baseDir || path9.dirname(entryFile);
|
|
6736
6947
|
const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
|
|
6737
|
-
target:
|
|
6948
|
+
target: "draft-2020-12",
|
|
6738
6949
|
timeout: 15000
|
|
6739
6950
|
});
|
|
6740
6951
|
if (runtimeResult.schemas.size > 0) {
|
|
@@ -6765,8 +6976,8 @@ async function extract(options) {
|
|
|
6765
6976
|
});
|
|
6766
6977
|
}
|
|
6767
6978
|
}
|
|
6768
|
-
const normalizedExports = exports.map((exp) => normalizeExport(exp
|
|
6769
|
-
const normalizedTypes = types.map((t) => normalizeType(t
|
|
6979
|
+
const normalizedExports = exports.map((exp) => normalizeExport(exp));
|
|
6980
|
+
const normalizedTypes = types.map((t) => normalizeType(t));
|
|
6770
6981
|
const spec = {
|
|
6771
6982
|
...includeSchema ? { $schema: SCHEMA_URL } : {},
|
|
6772
6983
|
openpkg: SCHEMA_VERSION,
|
|
@@ -7073,6 +7284,485 @@ async function getPackageMeta(entryFile, baseDir) {
|
|
|
7073
7284
|
|
|
7074
7285
|
// src/primitives/spec.ts
|
|
7075
7286
|
var extractSpec = extract;
|
|
7287
|
+
// src/primitives/validate.ts
|
|
7288
|
+
import {
|
|
7289
|
+
assertSpec,
|
|
7290
|
+
getAvailableVersions,
|
|
7291
|
+
getValidationErrors,
|
|
7292
|
+
LATEST_VERSION,
|
|
7293
|
+
validateSpec as validateSpec2
|
|
7294
|
+
} from "@openpkg-ts/spec";
|
|
7295
|
+
// src/schema/json-schema.ts
|
|
7296
|
+
import { JSON_SCHEMA_DRAFT as JSON_SCHEMA_DRAFT2 } from "@openpkg-ts/spec";
|
|
7297
|
+
|
|
7298
|
+
// src/schema/ref-walker.ts
|
|
7299
|
+
var INTERNAL_REF_PREFIX = "#/types/";
|
|
7300
|
+
function isTsExtensionKey(key) {
|
|
7301
|
+
return (key.startsWith("x-ts-") || key === "x-enum-members") && key !== "x-deprecated-reason";
|
|
7302
|
+
}
|
|
7303
|
+
function stripTsExtensions(schema) {
|
|
7304
|
+
const walk = (value) => {
|
|
7305
|
+
if (Array.isArray(value))
|
|
7306
|
+
return value.map(walk);
|
|
7307
|
+
if (value && typeof value === "object") {
|
|
7308
|
+
const out = {};
|
|
7309
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
7310
|
+
if (isTsExtensionKey(key))
|
|
7311
|
+
continue;
|
|
7312
|
+
out[key] = walk(nested);
|
|
7313
|
+
}
|
|
7314
|
+
return out;
|
|
7315
|
+
}
|
|
7316
|
+
return value;
|
|
7317
|
+
};
|
|
7318
|
+
return walk(schema);
|
|
7319
|
+
}
|
|
7320
|
+
function escapePointerToken(name) {
|
|
7321
|
+
return name.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
7322
|
+
}
|
|
7323
|
+
function bundleRefs(root, spec, options = {}) {
|
|
7324
|
+
const { keepExtensions = false, typeParameterNames = [], onUnresolved = "permissive" } = options;
|
|
7325
|
+
const typeParams = new Set(typeParameterNames);
|
|
7326
|
+
const warnings = [];
|
|
7327
|
+
const defs = {};
|
|
7328
|
+
const defKeyByName = new Map;
|
|
7329
|
+
const lookupType = (name) => {
|
|
7330
|
+
const types = spec.types ?? [];
|
|
7331
|
+
return types.find((t) => t.id === name) ?? types.find((t) => t.name === name);
|
|
7332
|
+
};
|
|
7333
|
+
const assignDefKey = (name) => {
|
|
7334
|
+
const existing = defKeyByName.get(name);
|
|
7335
|
+
if (existing)
|
|
7336
|
+
return existing;
|
|
7337
|
+
let key = escapePointerToken(name);
|
|
7338
|
+
if (Object.hasOwn(defs, key) || Object.values(defKeyByName).includes(key)) {
|
|
7339
|
+
let n = 2;
|
|
7340
|
+
while (Object.hasOwn(defs, `${key}_${n}`) || Object.values(defKeyByName).includes(`${key}_${n}`)) {
|
|
7341
|
+
n++;
|
|
7342
|
+
}
|
|
7343
|
+
warnings.push(`def key collision for "${name}" — using "${key}_${n}"`);
|
|
7344
|
+
key = `${key}_${n}`;
|
|
7345
|
+
}
|
|
7346
|
+
defKeyByName.set(name, key);
|
|
7347
|
+
return key;
|
|
7348
|
+
};
|
|
7349
|
+
const bodyOfType = (type) => {
|
|
7350
|
+
if (type.schema)
|
|
7351
|
+
return normalizeSchema(type.schema);
|
|
7352
|
+
if (type.members && type.members.length > 0)
|
|
7353
|
+
return normalizeMembers(type.members);
|
|
7354
|
+
return {};
|
|
7355
|
+
};
|
|
7356
|
+
const rewrite = (node) => {
|
|
7357
|
+
if (Array.isArray(node))
|
|
7358
|
+
return node.map(rewrite);
|
|
7359
|
+
if (!node || typeof node !== "object")
|
|
7360
|
+
return node;
|
|
7361
|
+
const obj = node;
|
|
7362
|
+
const ref = obj.$ref;
|
|
7363
|
+
if (typeof ref === "string" && ref.startsWith(INTERNAL_REF_PREFIX)) {
|
|
7364
|
+
const name = ref.slice(INTERNAL_REF_PREFIX.length);
|
|
7365
|
+
const siblings = {};
|
|
7366
|
+
for (const [key2, value] of Object.entries(obj)) {
|
|
7367
|
+
if (key2 === "$ref")
|
|
7368
|
+
continue;
|
|
7369
|
+
siblings[key2] = rewrite(value);
|
|
7370
|
+
}
|
|
7371
|
+
if (typeParams.has(name)) {
|
|
7372
|
+
warnings.push(`type parameter "${name}" is not an addressable schema`);
|
|
7373
|
+
return keepExtensions ? { ...siblings, "x-ts-type": name } : {};
|
|
7374
|
+
}
|
|
7375
|
+
const builtin = BUILTIN_TYPE_SCHEMAS[name];
|
|
7376
|
+
if (builtin) {
|
|
7377
|
+
return { ...builtin, ...keepExtensions ? siblings : {} };
|
|
7378
|
+
}
|
|
7379
|
+
const type = lookupType(name);
|
|
7380
|
+
if (!type) {
|
|
7381
|
+
warnings.push(`unresolved ref "${ref}"`);
|
|
7382
|
+
if (onUnresolved === "error") {
|
|
7383
|
+
throw new Error(`bundleRefs: cannot resolve ${ref}`);
|
|
7384
|
+
}
|
|
7385
|
+
return keepExtensions ? { ...siblings, "x-ts-type": name } : {};
|
|
7386
|
+
}
|
|
7387
|
+
const key = assignDefKey(name);
|
|
7388
|
+
if (!Object.hasOwn(defs, key)) {
|
|
7389
|
+
defs[key] = {};
|
|
7390
|
+
defs[key] = rewrite(bodyOfType(type));
|
|
7391
|
+
}
|
|
7392
|
+
const refNode = { $ref: `#/$defs/${key}` };
|
|
7393
|
+
return { ...siblings, ...refNode };
|
|
7394
|
+
}
|
|
7395
|
+
const out = {};
|
|
7396
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
7397
|
+
out[key] = rewrite(value);
|
|
7398
|
+
}
|
|
7399
|
+
return out;
|
|
7400
|
+
};
|
|
7401
|
+
let schema = rewrite(normalizeSchema(root));
|
|
7402
|
+
if (!keepExtensions) {
|
|
7403
|
+
schema = stripTsExtensions(schema);
|
|
7404
|
+
for (const key of Object.keys(defs)) {
|
|
7405
|
+
defs[key] = stripTsExtensions(defs[key]);
|
|
7406
|
+
}
|
|
7407
|
+
}
|
|
7408
|
+
return { schema, defs, warnings };
|
|
7409
|
+
}
|
|
7410
|
+
|
|
7411
|
+
// src/schema/json-schema.ts
|
|
7412
|
+
function typeParamNames(subject) {
|
|
7413
|
+
return (subject.typeParameters ?? []).map((p) => p.name);
|
|
7414
|
+
}
|
|
7415
|
+
function subjectSchema(subject) {
|
|
7416
|
+
if (subject.schema)
|
|
7417
|
+
return normalizeSchema(subject.schema);
|
|
7418
|
+
if (subject.members && subject.members.length > 0)
|
|
7419
|
+
return normalizeMembers(subject.members);
|
|
7420
|
+
return {};
|
|
7421
|
+
}
|
|
7422
|
+
function exportToJsonSchema(subject, spec, options = {}) {
|
|
7423
|
+
const { keepExtensions = false, includeSchemaField = true } = options;
|
|
7424
|
+
const { schema, defs } = bundleRefs(subjectSchema(subject), spec, {
|
|
7425
|
+
keepExtensions,
|
|
7426
|
+
typeParameterNames: typeParamNames(subject)
|
|
7427
|
+
});
|
|
7428
|
+
const doc = { ...schema };
|
|
7429
|
+
if (Object.keys(defs).length > 0)
|
|
7430
|
+
doc.$defs = defs;
|
|
7431
|
+
if (includeSchemaField)
|
|
7432
|
+
return { $schema: JSON_SCHEMA_DRAFT2, ...doc };
|
|
7433
|
+
return doc;
|
|
7434
|
+
}
|
|
7435
|
+
function toJsonSchema(spec, options = {}) {
|
|
7436
|
+
const { root, keepExtensions = false, includeSchemaField = true } = options;
|
|
7437
|
+
if (root) {
|
|
7438
|
+
const subject = spec.exports.find((e) => e.name === root) ?? (spec.types ?? []).find((t) => t.name === root);
|
|
7439
|
+
if (!subject) {
|
|
7440
|
+
throw new Error(`toJsonSchema: no export or type named "${root}"`);
|
|
7441
|
+
}
|
|
7442
|
+
return exportToJsonSchema(subject, spec, { keepExtensions, includeSchemaField });
|
|
7443
|
+
}
|
|
7444
|
+
const defs = {};
|
|
7445
|
+
const mergeInto = (name, bundled) => {
|
|
7446
|
+
for (const [key, value] of Object.entries(bundled.defs)) {
|
|
7447
|
+
if (!Object.hasOwn(defs, key))
|
|
7448
|
+
defs[key] = value;
|
|
7449
|
+
}
|
|
7450
|
+
if (!Object.hasOwn(defs, name))
|
|
7451
|
+
defs[name] = bundled.schema;
|
|
7452
|
+
};
|
|
7453
|
+
for (const type of spec.types ?? []) {
|
|
7454
|
+
mergeInto(type.name, bundleRefs(subjectSchema(type), spec, {
|
|
7455
|
+
keepExtensions,
|
|
7456
|
+
typeParameterNames: typeParamNames(type)
|
|
7457
|
+
}));
|
|
7458
|
+
}
|
|
7459
|
+
for (const exp of spec.exports) {
|
|
7460
|
+
if (!exp.schema && !(exp.members && exp.members.length > 0))
|
|
7461
|
+
continue;
|
|
7462
|
+
mergeInto(exp.name, bundleRefs(subjectSchema(exp), spec, {
|
|
7463
|
+
keepExtensions,
|
|
7464
|
+
typeParameterNames: typeParamNames(exp)
|
|
7465
|
+
}));
|
|
7466
|
+
}
|
|
7467
|
+
const doc = { $defs: defs };
|
|
7468
|
+
if (includeSchemaField)
|
|
7469
|
+
return { $schema: JSON_SCHEMA_DRAFT2, ...doc };
|
|
7470
|
+
return doc;
|
|
7471
|
+
}
|
|
7472
|
+
|
|
7473
|
+
// src/schema/as-standard-schema.ts
|
|
7474
|
+
var DRAFT_07_URL = "http://json-schema.org/draft-07/schema#";
|
|
7475
|
+
function rewriteDefsPointers(value) {
|
|
7476
|
+
if (Array.isArray(value))
|
|
7477
|
+
return value.map(rewriteDefsPointers);
|
|
7478
|
+
if (value && typeof value === "object") {
|
|
7479
|
+
const out = {};
|
|
7480
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
7481
|
+
if (key === "$ref" && typeof nested === "string") {
|
|
7482
|
+
out.$ref = nested.replace("#/$defs/", "#/definitions/");
|
|
7483
|
+
} else {
|
|
7484
|
+
out[key] = rewriteDefsPointers(nested);
|
|
7485
|
+
}
|
|
7486
|
+
}
|
|
7487
|
+
return out;
|
|
7488
|
+
}
|
|
7489
|
+
return value;
|
|
7490
|
+
}
|
|
7491
|
+
function downlevelToDraft07(doc) {
|
|
7492
|
+
const convert = (value) => {
|
|
7493
|
+
if (Array.isArray(value))
|
|
7494
|
+
return value.map(convert);
|
|
7495
|
+
if (value && typeof value === "object") {
|
|
7496
|
+
const obj = value;
|
|
7497
|
+
const out = {};
|
|
7498
|
+
for (const [key, nested] of Object.entries(obj)) {
|
|
7499
|
+
if (key === "$defs") {
|
|
7500
|
+
out.definitions = convert(nested);
|
|
7501
|
+
} else if (key === "prefixItems" && Array.isArray(nested)) {
|
|
7502
|
+
out.items = convert(nested);
|
|
7503
|
+
} else {
|
|
7504
|
+
out[key] = convert(nested);
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
return out;
|
|
7508
|
+
}
|
|
7509
|
+
return value;
|
|
7510
|
+
};
|
|
7511
|
+
const converted = rewriteDefsPointers(convert(doc));
|
|
7512
|
+
converted.$schema = DRAFT_07_URL;
|
|
7513
|
+
return converted;
|
|
7514
|
+
}
|
|
7515
|
+
function downlevelToOpenApi30(doc) {
|
|
7516
|
+
const convert = (value) => {
|
|
7517
|
+
if (Array.isArray(value))
|
|
7518
|
+
return value.map(convert);
|
|
7519
|
+
if (!value || typeof value !== "object")
|
|
7520
|
+
return value;
|
|
7521
|
+
const obj = value;
|
|
7522
|
+
const out = {};
|
|
7523
|
+
if (Array.isArray(obj.anyOf)) {
|
|
7524
|
+
const branches = obj.anyOf;
|
|
7525
|
+
const nulls = branches.filter((b) => b && b.type === "null");
|
|
7526
|
+
const rest = branches.filter((b) => !(b && b.type === "null"));
|
|
7527
|
+
if (nulls.length > 0 && rest.length === 1) {
|
|
7528
|
+
Object.assign(out, convert(rest[0]));
|
|
7529
|
+
out.nullable = true;
|
|
7530
|
+
for (const [key, nested] of Object.entries(obj)) {
|
|
7531
|
+
if (key !== "anyOf")
|
|
7532
|
+
out[key] = convert(nested);
|
|
7533
|
+
}
|
|
7534
|
+
return out;
|
|
7535
|
+
}
|
|
7536
|
+
}
|
|
7537
|
+
for (const [key, nested] of Object.entries(obj)) {
|
|
7538
|
+
if (key === "$schema")
|
|
7539
|
+
continue;
|
|
7540
|
+
if (key === "$defs") {
|
|
7541
|
+
out.definitions = convert(nested);
|
|
7542
|
+
} else if (key === "const") {
|
|
7543
|
+
out.enum = [nested];
|
|
7544
|
+
} else {
|
|
7545
|
+
out[key] = convert(nested);
|
|
7546
|
+
}
|
|
7547
|
+
}
|
|
7548
|
+
return out;
|
|
7549
|
+
};
|
|
7550
|
+
return rewriteDefsPointers(convert(doc));
|
|
7551
|
+
}
|
|
7552
|
+
function asStandardSchema(subject, spec, options = {}) {
|
|
7553
|
+
const resolved = typeof subject === "string" ? spec.exports.find((e) => e.name === subject) ?? (spec.types ?? []).find((t) => t.name === subject) : subject;
|
|
7554
|
+
if (!resolved) {
|
|
7555
|
+
throw new Error(`asStandardSchema: no export or type named "${subject}"`);
|
|
7556
|
+
}
|
|
7557
|
+
const cache = new Map;
|
|
7558
|
+
const build = (opts) => {
|
|
7559
|
+
const target = opts.target;
|
|
7560
|
+
const cached = cache.get(target);
|
|
7561
|
+
if (cached)
|
|
7562
|
+
return cached;
|
|
7563
|
+
const base = exportToJsonSchema(resolved, spec, {
|
|
7564
|
+
keepExtensions: options.keepExtensions,
|
|
7565
|
+
includeSchemaField: true
|
|
7566
|
+
});
|
|
7567
|
+
let result;
|
|
7568
|
+
switch (target) {
|
|
7569
|
+
case "draft-2020-12":
|
|
7570
|
+
result = base;
|
|
7571
|
+
break;
|
|
7572
|
+
case "draft-07":
|
|
7573
|
+
result = downlevelToDraft07(base);
|
|
7574
|
+
break;
|
|
7575
|
+
case "openapi-3.0":
|
|
7576
|
+
result = downlevelToOpenApi30(base);
|
|
7577
|
+
break;
|
|
7578
|
+
default:
|
|
7579
|
+
throw new Error(`asStandardSchema: unsupported target "${target}". Supported: draft-2020-12, draft-07, openapi-3.0`);
|
|
7580
|
+
}
|
|
7581
|
+
cache.set(target, result);
|
|
7582
|
+
return result;
|
|
7583
|
+
};
|
|
7584
|
+
return {
|
|
7585
|
+
"~standard": {
|
|
7586
|
+
version: 1,
|
|
7587
|
+
vendor: "openpkg",
|
|
7588
|
+
jsonSchema: {
|
|
7589
|
+
input: build,
|
|
7590
|
+
output: build
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7593
|
+
};
|
|
7594
|
+
}
|
|
7595
|
+
// src/schema/tool-schema.ts
|
|
7596
|
+
var OPENAI_ALLOWED_KEYWORDS = new Set([
|
|
7597
|
+
"type",
|
|
7598
|
+
"properties",
|
|
7599
|
+
"required",
|
|
7600
|
+
"additionalProperties",
|
|
7601
|
+
"items",
|
|
7602
|
+
"prefixItems",
|
|
7603
|
+
"anyOf",
|
|
7604
|
+
"enum",
|
|
7605
|
+
"const",
|
|
7606
|
+
"description",
|
|
7607
|
+
"title",
|
|
7608
|
+
"$ref",
|
|
7609
|
+
"$defs",
|
|
7610
|
+
"format"
|
|
7611
|
+
]);
|
|
7612
|
+
function isObject(v) {
|
|
7613
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
7614
|
+
}
|
|
7615
|
+
function isObjectNode(node) {
|
|
7616
|
+
return node.type === "object" || "properties" in node;
|
|
7617
|
+
}
|
|
7618
|
+
function isFunctionOnly(schema) {
|
|
7619
|
+
if (!isObject(schema))
|
|
7620
|
+
return false;
|
|
7621
|
+
if (!("x-ts-function" in schema))
|
|
7622
|
+
return false;
|
|
7623
|
+
const keys = Object.keys(schema).filter((k) => !k.startsWith("x-ts-"));
|
|
7624
|
+
return keys.length === 0;
|
|
7625
|
+
}
|
|
7626
|
+
function openAiStrict(node, warnings) {
|
|
7627
|
+
if (Array.isArray(node))
|
|
7628
|
+
return node.map((n) => openAiStrict(n, warnings));
|
|
7629
|
+
if (!isObject(node))
|
|
7630
|
+
return node;
|
|
7631
|
+
const src = { ...node };
|
|
7632
|
+
if ("oneOf" in src && !("anyOf" in src)) {
|
|
7633
|
+
src.anyOf = src.oneOf;
|
|
7634
|
+
delete src.oneOf;
|
|
7635
|
+
}
|
|
7636
|
+
if (Array.isArray(src.allOf)) {
|
|
7637
|
+
const branches = src.allOf;
|
|
7638
|
+
warnings.push("openai-strict: allOf is unsupported — using first branch");
|
|
7639
|
+
delete src.allOf;
|
|
7640
|
+
if (isObject(branches[0]))
|
|
7641
|
+
Object.assign(src, branches[0]);
|
|
7642
|
+
}
|
|
7643
|
+
const out = {};
|
|
7644
|
+
for (const [key, value] of Object.entries(src)) {
|
|
7645
|
+
if (key.startsWith("x-"))
|
|
7646
|
+
continue;
|
|
7647
|
+
if (key === "properties" && isObject(value)) {
|
|
7648
|
+
const props = {};
|
|
7649
|
+
const kept = [];
|
|
7650
|
+
for (const [propName, propSchema] of Object.entries(value)) {
|
|
7651
|
+
if (isFunctionOnly(propSchema)) {
|
|
7652
|
+
warnings.push(`openai-strict: pruned function-typed property "${propName}"`);
|
|
7653
|
+
continue;
|
|
7654
|
+
}
|
|
7655
|
+
props[propName] = openAiStrict(propSchema, warnings);
|
|
7656
|
+
kept.push(propName);
|
|
7657
|
+
}
|
|
7658
|
+
out.properties = props;
|
|
7659
|
+
out.required = kept;
|
|
7660
|
+
continue;
|
|
7661
|
+
}
|
|
7662
|
+
if (key === "required")
|
|
7663
|
+
continue;
|
|
7664
|
+
if (key === "$defs" && isObject(value)) {
|
|
7665
|
+
out.$defs = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, openAiStrict(v, warnings)]));
|
|
7666
|
+
continue;
|
|
7667
|
+
}
|
|
7668
|
+
if (!OPENAI_ALLOWED_KEYWORDS.has(key) && key !== "anyOf" && !key.startsWith("$")) {
|
|
7669
|
+
warnings.push(`openai-strict: dropped unsupported keyword "${key}"`);
|
|
7670
|
+
continue;
|
|
7671
|
+
}
|
|
7672
|
+
out[key] = openAiStrict(value, warnings);
|
|
7673
|
+
}
|
|
7674
|
+
if (isObjectNode(out)) {
|
|
7675
|
+
out.type = "object";
|
|
7676
|
+
if (!("properties" in out))
|
|
7677
|
+
out.properties = {};
|
|
7678
|
+
if (!("required" in out))
|
|
7679
|
+
out.required = Object.keys(out.properties);
|
|
7680
|
+
if (out.additionalProperties !== undefined && out.additionalProperties !== false) {
|
|
7681
|
+
warnings.push("openai-strict: open-ended additionalProperties dropped (record types unsupported)");
|
|
7682
|
+
}
|
|
7683
|
+
out.additionalProperties = false;
|
|
7684
|
+
}
|
|
7685
|
+
return out;
|
|
7686
|
+
}
|
|
7687
|
+
function anthropic(node, warnings) {
|
|
7688
|
+
if (Array.isArray(node))
|
|
7689
|
+
return node.map((n) => anthropic(n, warnings));
|
|
7690
|
+
if (!isObject(node))
|
|
7691
|
+
return node;
|
|
7692
|
+
const out = {};
|
|
7693
|
+
for (const [key, value] of Object.entries(node)) {
|
|
7694
|
+
if (key.startsWith("x-ts-") || key === "x-enum-members")
|
|
7695
|
+
continue;
|
|
7696
|
+
if (key === "properties" && isObject(value)) {
|
|
7697
|
+
const props = {};
|
|
7698
|
+
const dropped = new Set;
|
|
7699
|
+
for (const [propName, propSchema] of Object.entries(value)) {
|
|
7700
|
+
if (isFunctionOnly(propSchema)) {
|
|
7701
|
+
warnings.push(`anthropic: pruned function-typed property "${propName}"`);
|
|
7702
|
+
dropped.add(propName);
|
|
7703
|
+
continue;
|
|
7704
|
+
}
|
|
7705
|
+
props[propName] = anthropic(propSchema, warnings);
|
|
7706
|
+
}
|
|
7707
|
+
out.properties = props;
|
|
7708
|
+
if (Array.isArray(node.required)) {
|
|
7709
|
+
out.required = node.required.filter((r) => !dropped.has(r));
|
|
7710
|
+
}
|
|
7711
|
+
continue;
|
|
7712
|
+
}
|
|
7713
|
+
if (key === "required")
|
|
7714
|
+
continue;
|
|
7715
|
+
out[key] = anthropic(value, warnings);
|
|
7716
|
+
}
|
|
7717
|
+
return out;
|
|
7718
|
+
}
|
|
7719
|
+
function toToolSchema(exp, spec, options) {
|
|
7720
|
+
if (exp.kind !== "function" || !exp.signatures || exp.signatures.length === 0) {
|
|
7721
|
+
throw new TypeError(`toToolSchema: export "${exp.name}" is not a function with signatures (kind: ${exp.kind})`);
|
|
7722
|
+
}
|
|
7723
|
+
const sig = exp.signatures[options.signatureIndex ?? 0] ?? exp.signatures[0];
|
|
7724
|
+
const warnings = [];
|
|
7725
|
+
const properties = {};
|
|
7726
|
+
const required = [];
|
|
7727
|
+
for (const param of sig.parameters ?? []) {
|
|
7728
|
+
let paramSchema = normalizeSchema(param.schema);
|
|
7729
|
+
if (param.rest) {
|
|
7730
|
+
paramSchema = { type: "array", items: paramSchema };
|
|
7731
|
+
}
|
|
7732
|
+
if (param.description && !paramSchema.description) {
|
|
7733
|
+
paramSchema.description = param.description;
|
|
7734
|
+
}
|
|
7735
|
+
properties[param.name] = paramSchema;
|
|
7736
|
+
if (param.required !== false)
|
|
7737
|
+
required.push(param.name);
|
|
7738
|
+
}
|
|
7739
|
+
const wrapper = {
|
|
7740
|
+
type: "object",
|
|
7741
|
+
properties,
|
|
7742
|
+
...required.length > 0 ? { required } : {}
|
|
7743
|
+
};
|
|
7744
|
+
const typeParameterNames = [
|
|
7745
|
+
...(exp.typeParameters ?? []).map((p) => p.name),
|
|
7746
|
+
...(sig.typeParameters ?? []).map((p) => p.name)
|
|
7747
|
+
];
|
|
7748
|
+
const bundled = bundleRefs(wrapper, spec, { keepExtensions: true, typeParameterNames });
|
|
7749
|
+
warnings.push(...bundled.warnings);
|
|
7750
|
+
let parameters = { ...bundled.schema };
|
|
7751
|
+
if (Object.keys(bundled.defs).length > 0)
|
|
7752
|
+
parameters.$defs = bundled.defs;
|
|
7753
|
+
if (options.provider === "openai-strict") {
|
|
7754
|
+
parameters = openAiStrict(parameters, warnings);
|
|
7755
|
+
} else {
|
|
7756
|
+
parameters = stripTsExtensions(anthropic(parameters, warnings));
|
|
7757
|
+
}
|
|
7758
|
+
const description = exp.description ?? sig.description;
|
|
7759
|
+
return {
|
|
7760
|
+
name: exp.name,
|
|
7761
|
+
...description ? { description } : {},
|
|
7762
|
+
parameters,
|
|
7763
|
+
warnings
|
|
7764
|
+
};
|
|
7765
|
+
}
|
|
7076
7766
|
// src/types/utils.ts
|
|
7077
7767
|
import ts18 from "typescript";
|
|
7078
7768
|
function isExported(node) {
|
|
@@ -7092,13 +7782,16 @@ export {
|
|
|
7092
7782
|
zodAdapter,
|
|
7093
7783
|
withDescription,
|
|
7094
7784
|
withDeprecated,
|
|
7785
|
+
validateSpec2 as validateSpec,
|
|
7095
7786
|
valibotAdapter,
|
|
7096
7787
|
typeboxAdapter,
|
|
7788
|
+
toToolSchema,
|
|
7097
7789
|
toSearchIndexJSON,
|
|
7098
7790
|
toSearchIndex,
|
|
7099
7791
|
toPagefindRecords,
|
|
7100
7792
|
toNavigation,
|
|
7101
7793
|
toMarkdown,
|
|
7794
|
+
toJsonSchema,
|
|
7102
7795
|
toJSONString,
|
|
7103
7796
|
toJSON,
|
|
7104
7797
|
toHTML,
|
|
@@ -7106,6 +7799,7 @@ export {
|
|
|
7106
7799
|
toDocusaurusSidebarJS,
|
|
7107
7800
|
toAlgoliaRecords,
|
|
7108
7801
|
stripUndefinedFromType,
|
|
7802
|
+
stripTsExtensions,
|
|
7109
7803
|
sortByName,
|
|
7110
7804
|
shouldEmitAliasTypeText,
|
|
7111
7805
|
serializeVariable,
|
|
@@ -7149,6 +7843,7 @@ export {
|
|
|
7149
7843
|
isAnonymous,
|
|
7150
7844
|
hasDeprecatedTag,
|
|
7151
7845
|
groupByVisibility,
|
|
7846
|
+
getValidationErrors,
|
|
7152
7847
|
getTypeOrigin,
|
|
7153
7848
|
getSourceLocation,
|
|
7154
7849
|
getProperties,
|
|
@@ -7161,6 +7856,7 @@ export {
|
|
|
7161
7856
|
getExportKind,
|
|
7162
7857
|
getExport,
|
|
7163
7858
|
getDeprecationMessage,
|
|
7859
|
+
getAvailableVersions,
|
|
7164
7860
|
toMarkdown as generateDocs,
|
|
7165
7861
|
formatTypeParameters,
|
|
7166
7862
|
formatSchema,
|
|
@@ -7182,6 +7878,7 @@ export {
|
|
|
7182
7878
|
extractParameters,
|
|
7183
7879
|
extract,
|
|
7184
7880
|
exportToMarkdown,
|
|
7881
|
+
exportToJsonSchema,
|
|
7185
7882
|
ensureNonEmptySchema,
|
|
7186
7883
|
diffSpec2 as diffSpecs,
|
|
7187
7884
|
diffSpec,
|
|
@@ -7192,10 +7889,13 @@ export {
|
|
|
7192
7889
|
createDocs,
|
|
7193
7890
|
categorizeBreakingChanges,
|
|
7194
7891
|
calculateNextVersion,
|
|
7892
|
+
bundleRefs,
|
|
7195
7893
|
buildSignatureString,
|
|
7196
7894
|
buildSchema,
|
|
7197
7895
|
buildObjectSchema,
|
|
7198
7896
|
buildFunctionSchema,
|
|
7897
|
+
assertSpec,
|
|
7898
|
+
asStandardSchema,
|
|
7199
7899
|
arktypeAdapter,
|
|
7200
7900
|
analyzeSpec,
|
|
7201
7901
|
TypeRegistry,
|
|
@@ -7203,6 +7903,7 @@ export {
|
|
|
7203
7903
|
QueryBuilder,
|
|
7204
7904
|
PRIMITIVES,
|
|
7205
7905
|
NUMBER_PROTOTYPE_METHODS,
|
|
7906
|
+
LATEST_VERSION,
|
|
7206
7907
|
CacheManager,
|
|
7207
7908
|
CONFIG_FILENAME,
|
|
7208
7909
|
BUILTIN_TYPE_SCHEMAS,
|