@openpkg-ts/sdk 0.50.1 → 0.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/index.d.ts +163 -49
- package/dist/index.js +1072 -207
- package/package.json +8 -4
package/dist/index.js
CHANGED
|
@@ -83,9 +83,70 @@ function mergeConfig(fileConfig, cliOptions) {
|
|
|
83
83
|
...hasExternals ? { externals } : {},
|
|
84
84
|
followExternal: cliOptions.followExternal ?? fileConfig.followExternal,
|
|
85
85
|
only: cliOptions.only ?? fileConfig.only,
|
|
86
|
-
ignore: cliOptions.ignore ?? fileConfig.ignore
|
|
86
|
+
ignore: cliOptions.ignore ?? fileConfig.ignore,
|
|
87
|
+
decisions: cliOptions.decisions ?? fileConfig.decisions
|
|
87
88
|
};
|
|
88
89
|
}
|
|
90
|
+
// src/core/decisions.ts
|
|
91
|
+
var JEV_MODEL = "typesafe-ai/jev";
|
|
92
|
+
var JEV_CONFIDENCE = 0.5;
|
|
93
|
+
var MAX_JEV_QUESTIONS = 50;
|
|
94
|
+
async function loadEvaluate() {
|
|
95
|
+
try {
|
|
96
|
+
const specifier = "ai";
|
|
97
|
+
const mod = await import(specifier);
|
|
98
|
+
if (typeof mod.experimental_evaluate !== "function") {
|
|
99
|
+
throw new Error("ai.experimental_evaluate is not a function");
|
|
100
|
+
}
|
|
101
|
+
return (request) => mod.experimental_evaluate({
|
|
102
|
+
...request,
|
|
103
|
+
providerOptions: {
|
|
104
|
+
gateway: { zeroDataRetention: true },
|
|
105
|
+
...request.providerOptions
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
110
|
+
throw new Error(`--jev requires the ai package (AI SDK ≥7.0.105): bun add ai
|
|
111
|
+
${msg}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function namedConfidence(result, id) {
|
|
115
|
+
const named = result.providerMetadata?.typesafe?.confidence?.[id];
|
|
116
|
+
return typeof named === "number" ? named : undefined;
|
|
117
|
+
}
|
|
118
|
+
function choiceConfidence(result, id, choice) {
|
|
119
|
+
const named = namedConfidence(result, id);
|
|
120
|
+
if (named !== undefined)
|
|
121
|
+
return named;
|
|
122
|
+
const p = result.answers[id]?.probabilities?.[choice];
|
|
123
|
+
return typeof p === "number" ? p : 0;
|
|
124
|
+
}
|
|
125
|
+
async function jevEvaluate(evaluate, state, questions) {
|
|
126
|
+
return evaluate({
|
|
127
|
+
model: JEV_MODEL,
|
|
128
|
+
state: JSON.parse(JSON.stringify(state)),
|
|
129
|
+
questions,
|
|
130
|
+
providerOptions: { gateway: { zeroDataRetention: true } }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async function jevChoice(args) {
|
|
134
|
+
const keys = Object.keys(args.criteria);
|
|
135
|
+
if (keys.length < 2)
|
|
136
|
+
return null;
|
|
137
|
+
const id = args.id ?? "choice";
|
|
138
|
+
const result = await jevEvaluate(args.evaluate, args.state, {
|
|
139
|
+
[id]: {
|
|
140
|
+
type: "choice",
|
|
141
|
+
instructions: args.instructions,
|
|
142
|
+
criteria: args.criteria
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const choice = result.answers[id]?.choice;
|
|
146
|
+
if (!choice || !(choice in args.criteria))
|
|
147
|
+
return null;
|
|
148
|
+
return { choice, confidence: choiceConfidence(result, id, choice) };
|
|
149
|
+
}
|
|
89
150
|
// src/core/loader.ts
|
|
90
151
|
import * as fs2 from "node:fs";
|
|
91
152
|
import { validateSpec } from "@openpkg-ts/spec";
|
|
@@ -1200,6 +1261,584 @@ function extractModuleName(exp) {
|
|
|
1200
1261
|
}
|
|
1201
1262
|
return;
|
|
1202
1263
|
}
|
|
1264
|
+
// src/core/resolve-target.ts
|
|
1265
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
1266
|
+
import * as fs3 from "node:fs";
|
|
1267
|
+
import * as os from "node:os";
|
|
1268
|
+
import * as path2 from "node:path";
|
|
1269
|
+
var SKIP_DIRS = new Set(["node_modules", "dist", ".git", "target", "coverage", ".next", "out"]);
|
|
1270
|
+
var CONV = ["src/index.ts", "src/index.tsx", "src/index.mts", "index.ts", "index.tsx"];
|
|
1271
|
+
var ENTRY_EXT = /\.(c|m)?[tj]sx?$/;
|
|
1272
|
+
var MAX_PACKAGES = 200;
|
|
1273
|
+
function isRemoteInput(input) {
|
|
1274
|
+
return /^(https?:\/\/|git@|github\.com\/)/i.test(input);
|
|
1275
|
+
}
|
|
1276
|
+
function isEntryFilePath(input) {
|
|
1277
|
+
return ENTRY_EXT.test(input) || /\.d\.(ts|mts|cts)$/.test(input);
|
|
1278
|
+
}
|
|
1279
|
+
function parseGithubRepo(input) {
|
|
1280
|
+
const trimmed = input.trim().replace(/\.git$/, "");
|
|
1281
|
+
const https = trimmed.match(/github\.com[/:]([^/]+)\/([^/#?]+)/i);
|
|
1282
|
+
if (!https)
|
|
1283
|
+
return null;
|
|
1284
|
+
return { owner: https[1], repo: https[2] };
|
|
1285
|
+
}
|
|
1286
|
+
function runCmd(cmd, args) {
|
|
1287
|
+
return new Promise((resolve2, reject) => {
|
|
1288
|
+
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1289
|
+
let stderr = "";
|
|
1290
|
+
child.stderr.on("data", (chunk) => {
|
|
1291
|
+
stderr += String(chunk);
|
|
1292
|
+
});
|
|
1293
|
+
child.on("error", reject);
|
|
1294
|
+
child.on("close", (code) => {
|
|
1295
|
+
if (code === 0)
|
|
1296
|
+
resolve2();
|
|
1297
|
+
else
|
|
1298
|
+
reject(new Error(`${cmd} ${args.join(" ")} failed: ${stderr.trim() || code}`));
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
function whichCmd(cmd) {
|
|
1303
|
+
const checker = process.platform === "win32" ? "where" : "which";
|
|
1304
|
+
return spawnSync(checker, [cmd], { stdio: "ignore" }).status === 0;
|
|
1305
|
+
}
|
|
1306
|
+
async function cloneRemote(input) {
|
|
1307
|
+
const dest = fs3.mkdtempSync(path2.join(os.tmpdir(), "openpkg-"));
|
|
1308
|
+
const github = parseGithubRepo(input);
|
|
1309
|
+
try {
|
|
1310
|
+
if (github && whichCmd("gh")) {
|
|
1311
|
+
await runCmd("gh", [
|
|
1312
|
+
"repo",
|
|
1313
|
+
"clone",
|
|
1314
|
+
`${github.owner}/${github.repo}`,
|
|
1315
|
+
dest,
|
|
1316
|
+
"--",
|
|
1317
|
+
"--depth",
|
|
1318
|
+
"1"
|
|
1319
|
+
]);
|
|
1320
|
+
} else {
|
|
1321
|
+
const url = input.startsWith("github.com/") ? `https://${input}` : input;
|
|
1322
|
+
await runCmd("git", ["clone", "--depth", "1", url, dest]);
|
|
1323
|
+
}
|
|
1324
|
+
} catch (err) {
|
|
1325
|
+
fs3.rmSync(dest, { recursive: true, force: true });
|
|
1326
|
+
throw err;
|
|
1327
|
+
}
|
|
1328
|
+
return dest;
|
|
1329
|
+
}
|
|
1330
|
+
function existsFile(p) {
|
|
1331
|
+
try {
|
|
1332
|
+
return fs3.existsSync(p) && fs3.statSync(p).isFile();
|
|
1333
|
+
} catch {
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
function existsDir(p) {
|
|
1338
|
+
try {
|
|
1339
|
+
return fs3.existsSync(p) && fs3.statSync(p).isDirectory();
|
|
1340
|
+
} catch {
|
|
1341
|
+
return false;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function readJson(file) {
|
|
1345
|
+
try {
|
|
1346
|
+
return JSON.parse(fs3.readFileSync(file, "utf-8"));
|
|
1347
|
+
} catch {
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
function parsePnpmWorkspace(yaml) {
|
|
1352
|
+
const globs = [];
|
|
1353
|
+
const lines = yaml.split(`
|
|
1354
|
+
`);
|
|
1355
|
+
let inPackages = false;
|
|
1356
|
+
for (const line of lines) {
|
|
1357
|
+
const trimmed = line.trim();
|
|
1358
|
+
if (trimmed === "packages:") {
|
|
1359
|
+
inPackages = true;
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
if (inPackages) {
|
|
1363
|
+
if (!line.startsWith(" ") && !line.startsWith("\t") && !line.startsWith("-") && trimmed) {
|
|
1364
|
+
break;
|
|
1365
|
+
}
|
|
1366
|
+
const match = trimmed.match(/^-\s*['"]?([^'"]+)['"]?$/);
|
|
1367
|
+
if (match)
|
|
1368
|
+
globs.push(match[1]);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return globs;
|
|
1372
|
+
}
|
|
1373
|
+
function expandGlob(root, pattern) {
|
|
1374
|
+
const parts = pattern.split("/").filter(Boolean);
|
|
1375
|
+
const out = [];
|
|
1376
|
+
const walk = (dir, i) => {
|
|
1377
|
+
if (out.length >= MAX_PACKAGES)
|
|
1378
|
+
return;
|
|
1379
|
+
if (i === parts.length) {
|
|
1380
|
+
if (existsFile(path2.join(dir, "package.json")))
|
|
1381
|
+
out.push(dir);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
const part = parts[i];
|
|
1385
|
+
if (!existsDir(dir))
|
|
1386
|
+
return;
|
|
1387
|
+
if (part === "**") {
|
|
1388
|
+
walk(dir, i + 1);
|
|
1389
|
+
let entries = [];
|
|
1390
|
+
try {
|
|
1391
|
+
entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
1392
|
+
} catch {
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
for (const ent of entries) {
|
|
1396
|
+
if (!ent.isDirectory() || SKIP_DIRS.has(ent.name))
|
|
1397
|
+
continue;
|
|
1398
|
+
walk(path2.join(dir, ent.name), i);
|
|
1399
|
+
}
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
if (part === "*") {
|
|
1403
|
+
let entries = [];
|
|
1404
|
+
try {
|
|
1405
|
+
entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
1406
|
+
} catch {
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
for (const ent of entries) {
|
|
1410
|
+
if (!ent.isDirectory() || SKIP_DIRS.has(ent.name))
|
|
1411
|
+
continue;
|
|
1412
|
+
walk(path2.join(dir, ent.name), i + 1);
|
|
1413
|
+
}
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
walk(path2.join(dir, part), i + 1);
|
|
1417
|
+
};
|
|
1418
|
+
walk(root, 0);
|
|
1419
|
+
return out;
|
|
1420
|
+
}
|
|
1421
|
+
function workspaceGlobs(dir) {
|
|
1422
|
+
const pnpm = path2.join(dir, "pnpm-workspace.yaml");
|
|
1423
|
+
if (existsFile(pnpm)) {
|
|
1424
|
+
const globs = parsePnpmWorkspace(fs3.readFileSync(pnpm, "utf-8"));
|
|
1425
|
+
if (globs.length)
|
|
1426
|
+
return globs;
|
|
1427
|
+
}
|
|
1428
|
+
const pkg = readJson(path2.join(dir, "package.json"));
|
|
1429
|
+
if (!pkg)
|
|
1430
|
+
return null;
|
|
1431
|
+
const ws = pkg.workspaces;
|
|
1432
|
+
if (Array.isArray(ws) && ws.every((x) => typeof x === "string"))
|
|
1433
|
+
return ws;
|
|
1434
|
+
if (ws && typeof ws === "object" && Array.isArray(ws.packages)) {
|
|
1435
|
+
return (ws.packages ?? []).filter((x) => typeof x === "string");
|
|
1436
|
+
}
|
|
1437
|
+
return null;
|
|
1438
|
+
}
|
|
1439
|
+
function findWorkspaceRoot(start) {
|
|
1440
|
+
let dir = path2.resolve(start);
|
|
1441
|
+
for (let i = 0;i < 12; i++) {
|
|
1442
|
+
const globs = workspaceGlobs(dir);
|
|
1443
|
+
if (globs?.length)
|
|
1444
|
+
return dir;
|
|
1445
|
+
const parent = path2.dirname(dir);
|
|
1446
|
+
if (parent === dir)
|
|
1447
|
+
break;
|
|
1448
|
+
dir = parent;
|
|
1449
|
+
}
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
function toRecord(dir) {
|
|
1453
|
+
const pkg = readJson(path2.join(dir, "package.json"));
|
|
1454
|
+
if (!pkg)
|
|
1455
|
+
return null;
|
|
1456
|
+
const name = typeof pkg.name === "string" ? pkg.name : path2.basename(dir);
|
|
1457
|
+
const scripts = pkg.scripts && typeof pkg.scripts === "object" ? Object.keys(pkg.scripts) : [];
|
|
1458
|
+
return {
|
|
1459
|
+
name,
|
|
1460
|
+
dir,
|
|
1461
|
+
private: pkg.private === true,
|
|
1462
|
+
...typeof pkg.description === "string" ? { description: pkg.description } : {},
|
|
1463
|
+
...typeof pkg.types === "string" ? { types: pkg.types } : {},
|
|
1464
|
+
...typeof pkg.typings === "string" ? { typings: pkg.typings } : {},
|
|
1465
|
+
...typeof pkg.main === "string" ? { main: pkg.main } : {},
|
|
1466
|
+
...typeof pkg.module === "string" ? { module: pkg.module } : {},
|
|
1467
|
+
hasSrc: CONV.some((c) => existsFile(path2.join(dir, c))),
|
|
1468
|
+
hasDist: existsDir(path2.join(dir, "dist")),
|
|
1469
|
+
scripts
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
function catalogPackages(start) {
|
|
1473
|
+
const abs = path2.resolve(start);
|
|
1474
|
+
const root = findWorkspaceRoot(abs) ?? abs;
|
|
1475
|
+
const seen = new Set;
|
|
1476
|
+
const out = [];
|
|
1477
|
+
const add = (dir2) => {
|
|
1478
|
+
const resolved = path2.resolve(dir2);
|
|
1479
|
+
if (seen.has(resolved) || out.length >= MAX_PACKAGES)
|
|
1480
|
+
return;
|
|
1481
|
+
const rec = toRecord(resolved);
|
|
1482
|
+
if (!rec)
|
|
1483
|
+
return;
|
|
1484
|
+
seen.add(resolved);
|
|
1485
|
+
out.push(rec);
|
|
1486
|
+
};
|
|
1487
|
+
const globs = workspaceGlobs(root);
|
|
1488
|
+
if (globs?.length) {
|
|
1489
|
+
for (const glob of globs) {
|
|
1490
|
+
for (const dir2 of expandGlob(root, glob))
|
|
1491
|
+
add(dir2);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
let dir = abs;
|
|
1495
|
+
for (let i = 0;i < 8; i++) {
|
|
1496
|
+
if (existsFile(path2.join(dir, "package.json"))) {
|
|
1497
|
+
add(dir);
|
|
1498
|
+
break;
|
|
1499
|
+
}
|
|
1500
|
+
const parent = path2.dirname(dir);
|
|
1501
|
+
if (parent === dir)
|
|
1502
|
+
break;
|
|
1503
|
+
dir = parent;
|
|
1504
|
+
}
|
|
1505
|
+
return out;
|
|
1506
|
+
}
|
|
1507
|
+
function collectFromExports(value, out, depth = 0) {
|
|
1508
|
+
if (depth > 4 || value == null)
|
|
1509
|
+
return;
|
|
1510
|
+
if (typeof value === "string") {
|
|
1511
|
+
out.push(value);
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
if (Array.isArray(value)) {
|
|
1515
|
+
for (const v of value)
|
|
1516
|
+
collectFromExports(v, out, depth + 1);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
if (typeof value === "object") {
|
|
1520
|
+
const obj = value;
|
|
1521
|
+
for (const key of ["types", "import", "default", "require", "node", "browser", "module"]) {
|
|
1522
|
+
if (key in obj)
|
|
1523
|
+
collectFromExports(obj[key], out, depth + 1);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
function collectCandidates(pkgDir, pkg) {
|
|
1528
|
+
const seen = new Map;
|
|
1529
|
+
const add = (rel, source) => {
|
|
1530
|
+
const abs = path2.resolve(pkgDir, rel);
|
|
1531
|
+
if (!existsFile(abs))
|
|
1532
|
+
return;
|
|
1533
|
+
const norm = path2.relative(pkgDir, abs).split(path2.sep).join("/");
|
|
1534
|
+
const prev = seen.get(norm);
|
|
1535
|
+
if (!prev)
|
|
1536
|
+
seen.set(norm, { rel: norm, abs, source });
|
|
1537
|
+
else if (!prev.source.includes(source))
|
|
1538
|
+
prev.source += `, ${source}`;
|
|
1539
|
+
};
|
|
1540
|
+
if (typeof pkg.types === "string")
|
|
1541
|
+
add(pkg.types, "types");
|
|
1542
|
+
if (typeof pkg.typings === "string")
|
|
1543
|
+
add(pkg.typings, "typings");
|
|
1544
|
+
if (pkg.exports && typeof pkg.exports === "object") {
|
|
1545
|
+
const exp = pkg.exports;
|
|
1546
|
+
const root = "." in exp ? exp["."] : exp;
|
|
1547
|
+
const paths = [];
|
|
1548
|
+
collectFromExports(root, paths);
|
|
1549
|
+
for (const p of paths)
|
|
1550
|
+
add(p, "exports");
|
|
1551
|
+
}
|
|
1552
|
+
if (typeof pkg.module === "string")
|
|
1553
|
+
add(pkg.module, "module");
|
|
1554
|
+
if (typeof pkg.main === "string")
|
|
1555
|
+
add(pkg.main, "main");
|
|
1556
|
+
for (const c of CONV)
|
|
1557
|
+
add(c, "convention");
|
|
1558
|
+
return [...seen.values()];
|
|
1559
|
+
}
|
|
1560
|
+
function scoreCandidate(c) {
|
|
1561
|
+
const ts = /\.(ts|tsx|mts)$/.test(c.rel) && !/\.d\.(ts|mts|cts)$/.test(c.rel);
|
|
1562
|
+
const dts = /\.d\.(ts|mts|cts)$/.test(c.rel);
|
|
1563
|
+
const src = c.rel.startsWith("src/");
|
|
1564
|
+
let n = 0;
|
|
1565
|
+
if (ts)
|
|
1566
|
+
n += 40;
|
|
1567
|
+
if (src && ts)
|
|
1568
|
+
n += 20;
|
|
1569
|
+
if (c.source.includes("types") || c.source.includes("typings"))
|
|
1570
|
+
n += dts ? 5 : 10;
|
|
1571
|
+
if (c.source.includes("exports"))
|
|
1572
|
+
n += 8;
|
|
1573
|
+
if (c.source.includes("convention"))
|
|
1574
|
+
n += ts ? 15 : 2;
|
|
1575
|
+
if (c.source.includes("module"))
|
|
1576
|
+
n += 4;
|
|
1577
|
+
if (c.source.includes("main"))
|
|
1578
|
+
n += 2;
|
|
1579
|
+
if (dts)
|
|
1580
|
+
n -= 15;
|
|
1581
|
+
if (/\.(js|mjs|cjs)$/.test(c.rel))
|
|
1582
|
+
n -= 20;
|
|
1583
|
+
return n;
|
|
1584
|
+
}
|
|
1585
|
+
function methodFor(c) {
|
|
1586
|
+
if (c.source.includes("convention") && /\.(ts|tsx|mts)$/.test(c.rel) && !c.rel.includes(".d.")) {
|
|
1587
|
+
return "fallback";
|
|
1588
|
+
}
|
|
1589
|
+
if (c.source.includes("types") || c.source.includes("typings"))
|
|
1590
|
+
return "types";
|
|
1591
|
+
if (c.source.includes("exports"))
|
|
1592
|
+
return "exports";
|
|
1593
|
+
if (c.source.includes("module"))
|
|
1594
|
+
return "module";
|
|
1595
|
+
if (c.source.includes("main"))
|
|
1596
|
+
return "main";
|
|
1597
|
+
return "fallback";
|
|
1598
|
+
}
|
|
1599
|
+
function pickEntry(pkgDir) {
|
|
1600
|
+
const pkg = readJson(path2.join(pkgDir, "package.json")) ?? {};
|
|
1601
|
+
const cands = collectCandidates(pkgDir, pkg);
|
|
1602
|
+
if (!cands.length)
|
|
1603
|
+
return null;
|
|
1604
|
+
const best = [...cands].sort((a, b) => scoreCandidate(b) - scoreCandidate(a))[0];
|
|
1605
|
+
return { entryFile: best.abs, entryPointSource: methodFor(best) };
|
|
1606
|
+
}
|
|
1607
|
+
function listEntryCandidates(pkgDir) {
|
|
1608
|
+
const pkg = readJson(path2.join(pkgDir, "package.json")) ?? {};
|
|
1609
|
+
return collectCandidates(pkgDir, pkg);
|
|
1610
|
+
}
|
|
1611
|
+
function isIgnoredPath(dir) {
|
|
1612
|
+
const norm = dir.split(path2.sep).join("/");
|
|
1613
|
+
return /\/(examples|fixtures|__tests__|test-fixtures)(\/|$)/.test(norm);
|
|
1614
|
+
}
|
|
1615
|
+
function isExtractable(pkg) {
|
|
1616
|
+
if (pkg.private)
|
|
1617
|
+
return false;
|
|
1618
|
+
if (isIgnoredPath(pkg.dir))
|
|
1619
|
+
return false;
|
|
1620
|
+
return pkg.hasSrc || Boolean(pkg.types || pkg.typings);
|
|
1621
|
+
}
|
|
1622
|
+
function intentScore(pkg, intent) {
|
|
1623
|
+
const q = intent.toLowerCase().trim();
|
|
1624
|
+
if (!q)
|
|
1625
|
+
return 0;
|
|
1626
|
+
const words = q.split(/\s+/).filter(Boolean);
|
|
1627
|
+
const name = pkg.name.toLowerCase();
|
|
1628
|
+
const desc = (pkg.description ?? "").toLowerCase();
|
|
1629
|
+
const dir = pkg.dir.split(path2.sep).join("/").toLowerCase();
|
|
1630
|
+
let n = 0;
|
|
1631
|
+
if (name === q || name.endsWith(`/${q}`) || name.split("/").pop() === q)
|
|
1632
|
+
n += 20;
|
|
1633
|
+
for (const w of words) {
|
|
1634
|
+
if (name.includes(w))
|
|
1635
|
+
n += 8;
|
|
1636
|
+
if (desc.includes(w))
|
|
1637
|
+
n += 3;
|
|
1638
|
+
if (dir.includes(w))
|
|
1639
|
+
n += 2;
|
|
1640
|
+
}
|
|
1641
|
+
return n;
|
|
1642
|
+
}
|
|
1643
|
+
function enclosingPackage(inputDir, catalog) {
|
|
1644
|
+
const abs = path2.resolve(inputDir);
|
|
1645
|
+
let best;
|
|
1646
|
+
for (const pkg of catalog) {
|
|
1647
|
+
if (abs === pkg.dir || abs.startsWith(pkg.dir + path2.sep)) {
|
|
1648
|
+
if (!best || pkg.dir.length > best.dir.length)
|
|
1649
|
+
best = pkg;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return best;
|
|
1653
|
+
}
|
|
1654
|
+
function buildCommand(pkg) {
|
|
1655
|
+
if (pkg.scripts.includes("build:sdk-wasm"))
|
|
1656
|
+
return "pnpm run build:sdk-wasm";
|
|
1657
|
+
if (pkg.scripts.includes("build"))
|
|
1658
|
+
return "bun run build";
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
function head(abs, maxChars = 1200) {
|
|
1662
|
+
try {
|
|
1663
|
+
return fs3.readFileSync(abs, "utf8").slice(0, maxChars);
|
|
1664
|
+
} catch {
|
|
1665
|
+
return "";
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
async function jevPickPackage(candidates, ctx) {
|
|
1669
|
+
if (!ctx.evaluate || candidates.length < 2)
|
|
1670
|
+
return null;
|
|
1671
|
+
const criteria = {};
|
|
1672
|
+
const byId = new Map;
|
|
1673
|
+
for (const [i, pkg] of candidates.entries()) {
|
|
1674
|
+
const id = `p${i}`;
|
|
1675
|
+
byId.set(id, pkg);
|
|
1676
|
+
criteria[id] = `${pkg.name} — ${pkg.description ?? pkg.dir}${pkg.hasSrc ? " (src)" : ""}`;
|
|
1677
|
+
}
|
|
1678
|
+
const picked = await jevChoice({
|
|
1679
|
+
evaluate: ctx.evaluate,
|
|
1680
|
+
instructions: "Which package is the public TypeScript SDK to extract? Prefer the named product, not examples, wasm glue, or private packages.",
|
|
1681
|
+
criteria,
|
|
1682
|
+
state: {
|
|
1683
|
+
intent: ctx.intent ?? null,
|
|
1684
|
+
catalog: candidates.map((p, i) => ({
|
|
1685
|
+
id: `p${i}`,
|
|
1686
|
+
name: p.name,
|
|
1687
|
+
description: p.description ?? null,
|
|
1688
|
+
hasSrc: p.hasSrc,
|
|
1689
|
+
hasDist: p.hasDist,
|
|
1690
|
+
types: p.types ?? p.typings ?? null,
|
|
1691
|
+
private: p.private
|
|
1692
|
+
}))
|
|
1693
|
+
},
|
|
1694
|
+
id: "package"
|
|
1695
|
+
});
|
|
1696
|
+
if (!picked || picked.confidence < JEV_CONFIDENCE)
|
|
1697
|
+
return null;
|
|
1698
|
+
return byId.get(picked.choice) ?? null;
|
|
1699
|
+
}
|
|
1700
|
+
async function jevPickEntry(cands, ctx) {
|
|
1701
|
+
if (!ctx.evaluate || cands.length < 2)
|
|
1702
|
+
return null;
|
|
1703
|
+
const criteria = {};
|
|
1704
|
+
const byId = new Map;
|
|
1705
|
+
for (const [i, c] of cands.entries()) {
|
|
1706
|
+
const id = `c${i}`;
|
|
1707
|
+
byId.set(id, c);
|
|
1708
|
+
criteria[id] = `${c.rel} (${c.source})`;
|
|
1709
|
+
}
|
|
1710
|
+
const picked = await jevChoice({
|
|
1711
|
+
evaluate: ctx.evaluate,
|
|
1712
|
+
instructions: "Which file is the best OpenPkg entry point? Prefer TypeScript source over .d.ts/.js. Prefer the package root public API.",
|
|
1713
|
+
criteria,
|
|
1714
|
+
state: {
|
|
1715
|
+
candidates: cands.map((c, i) => ({
|
|
1716
|
+
id: `c${i}`,
|
|
1717
|
+
path: c.rel,
|
|
1718
|
+
source: c.source,
|
|
1719
|
+
head: head(c.abs)
|
|
1720
|
+
}))
|
|
1721
|
+
},
|
|
1722
|
+
id: "entry"
|
|
1723
|
+
});
|
|
1724
|
+
if (!picked || picked.confidence < JEV_CONFIDENCE)
|
|
1725
|
+
return null;
|
|
1726
|
+
return byId.get(picked.choice) ?? null;
|
|
1727
|
+
}
|
|
1728
|
+
async function finishPackage(pkg, ctx) {
|
|
1729
|
+
const cands = listEntryCandidates(pkg.dir);
|
|
1730
|
+
if (!cands.length) {
|
|
1731
|
+
return {
|
|
1732
|
+
kind: "needs-build",
|
|
1733
|
+
package: pkg,
|
|
1734
|
+
reason: `no TypeScript entry found in ${pkg.name}`,
|
|
1735
|
+
...buildCommand(pkg) ? { command: buildCommand(pkg) } : {}
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
const heuristic = [...cands].sort((a, b) => scoreCandidate(b) - scoreCandidate(a))[0];
|
|
1739
|
+
let chosen = heuristic;
|
|
1740
|
+
let source = methodFor(heuristic);
|
|
1741
|
+
if (ctx.decisions === "jev" && cands.length >= 2) {
|
|
1742
|
+
const jev = await jevPickEntry(cands, ctx);
|
|
1743
|
+
if (jev) {
|
|
1744
|
+
chosen = jev;
|
|
1745
|
+
source = "llm";
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
return {
|
|
1749
|
+
kind: "ok",
|
|
1750
|
+
package: pkg,
|
|
1751
|
+
entryFile: chosen.abs,
|
|
1752
|
+
entryPointSource: source
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
async function resolveLocal(abs, startDir, ctx) {
|
|
1756
|
+
const catalog = catalogPackages(startDir);
|
|
1757
|
+
if (!catalog.length) {
|
|
1758
|
+
return { kind: "empty", reason: "no JS/TS packages found" };
|
|
1759
|
+
}
|
|
1760
|
+
const root = findWorkspaceRoot(startDir);
|
|
1761
|
+
const pointed = catalog.find((p) => p.dir === abs);
|
|
1762
|
+
if (pointed && (isExtractable(pointed) || pointed.dir !== root)) {
|
|
1763
|
+
return finishPackage(pointed, ctx);
|
|
1764
|
+
}
|
|
1765
|
+
const intent = ctx.intent;
|
|
1766
|
+
if (intent) {
|
|
1767
|
+
const scored = catalog.map((p) => ({ p, n: intentScore(p, intent) })).filter((x) => x.n > 0).sort((a, b) => b.n - a.n);
|
|
1768
|
+
if (!scored.length) {
|
|
1769
|
+
return { kind: "empty", reason: `no package matched intent "${intent}"` };
|
|
1770
|
+
}
|
|
1771
|
+
const top = scored.filter((x) => x.n === scored[0].n).map((x) => x.p);
|
|
1772
|
+
if (top.length === 1)
|
|
1773
|
+
return finishPackage(top[0], ctx);
|
|
1774
|
+
if (ctx.decisions === "jev") {
|
|
1775
|
+
const jev = await jevPickPackage(top, ctx);
|
|
1776
|
+
if (jev)
|
|
1777
|
+
return finishPackage(jev, ctx);
|
|
1778
|
+
}
|
|
1779
|
+
return { kind: "ambiguous", candidates: top };
|
|
1780
|
+
}
|
|
1781
|
+
const enclosed = enclosingPackage(startDir, catalog);
|
|
1782
|
+
if (enclosed && enclosed.dir !== root)
|
|
1783
|
+
return finishPackage(enclosed, ctx);
|
|
1784
|
+
const extractable = catalog.filter(isExtractable);
|
|
1785
|
+
if (extractable.length === 1)
|
|
1786
|
+
return finishPackage(extractable[0], ctx);
|
|
1787
|
+
if (extractable.length > 1) {
|
|
1788
|
+
if (ctx.decisions === "jev") {
|
|
1789
|
+
const jev = await jevPickPackage(extractable, ctx);
|
|
1790
|
+
if (jev)
|
|
1791
|
+
return finishPackage(jev, ctx);
|
|
1792
|
+
}
|
|
1793
|
+
return { kind: "ambiguous", candidates: extractable };
|
|
1794
|
+
}
|
|
1795
|
+
if (catalog.length === 1)
|
|
1796
|
+
return finishPackage(catalog[0], ctx);
|
|
1797
|
+
return { kind: "empty", reason: "no extractable JS/TS packages found" };
|
|
1798
|
+
}
|
|
1799
|
+
async function resolveTarget(options = {}) {
|
|
1800
|
+
const cwd = path2.resolve(options.cwd ?? process.cwd());
|
|
1801
|
+
const raw = options.input?.trim() || cwd;
|
|
1802
|
+
const decisions = options.decisions ?? "heuristic";
|
|
1803
|
+
const ctx = {
|
|
1804
|
+
decisions,
|
|
1805
|
+
evaluate: options.evaluate,
|
|
1806
|
+
intent: options.intent?.trim() || undefined
|
|
1807
|
+
};
|
|
1808
|
+
if (decisions === "jev" && !ctx.evaluate) {
|
|
1809
|
+
if (!process.env.AI_GATEWAY_API_KEY) {
|
|
1810
|
+
return {
|
|
1811
|
+
kind: "unavailable",
|
|
1812
|
+
reason: `--jev requires AI_GATEWAY_API_KEY
|
|
1813
|
+
https://vercel.com/docs/ai-gateway
|
|
1814
|
+
omit --jev to stay local`
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
try {
|
|
1818
|
+
ctx.evaluate = await loadEvaluate();
|
|
1819
|
+
} catch (err) {
|
|
1820
|
+
return { kind: "unavailable", reason: err instanceof Error ? err.message : String(err) };
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
if (isRemoteInput(raw)) {
|
|
1824
|
+
try {
|
|
1825
|
+
const cloned = await (options.clone ?? cloneRemote)(raw);
|
|
1826
|
+
const startDir2 = cloned;
|
|
1827
|
+
return resolveLocal(startDir2, startDir2, ctx);
|
|
1828
|
+
} catch (err) {
|
|
1829
|
+
return {
|
|
1830
|
+
kind: "empty",
|
|
1831
|
+
reason: `failed to clone ${raw}: ${err instanceof Error ? err.message : String(err)}`
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
const abs = path2.resolve(cwd, raw);
|
|
1836
|
+
if (existsFile(abs) && isEntryFilePath(abs)) {
|
|
1837
|
+
return { kind: "explicit", entryFile: abs, entryPointSource: "explicit" };
|
|
1838
|
+
}
|
|
1839
|
+
const startDir = existsDir(abs) ? abs : cwd;
|
|
1840
|
+
return resolveLocal(abs, startDir, ctx);
|
|
1841
|
+
}
|
|
1203
1842
|
// src/primitives/filter.ts
|
|
1204
1843
|
function matchesExport(exp, criteria) {
|
|
1205
1844
|
if (criteria.kinds && criteria.kinds.length > 0) {
|
|
@@ -1304,10 +1943,10 @@ function filterSpec(spec, criteria) {
|
|
|
1304
1943
|
};
|
|
1305
1944
|
}
|
|
1306
1945
|
// src/primitives/get.ts
|
|
1307
|
-
import
|
|
1946
|
+
import ts13 from "typescript";
|
|
1308
1947
|
|
|
1309
1948
|
// src/ast/utils.ts
|
|
1310
|
-
import * as
|
|
1949
|
+
import * as path3 from "node:path";
|
|
1311
1950
|
import ts from "typescript";
|
|
1312
1951
|
var INLINE_TAG_RE = /(^|[^\\])\{@([a-zA-Z][a-zA-Z0-9]*)((?:[^}\\]|\\.)*)\}/g;
|
|
1313
1952
|
function parseInlineTags(...texts) {
|
|
@@ -1366,10 +2005,8 @@ function parseExamplesFromTags(tags) {
|
|
|
1366
2005
|
function stripParamSeparator(text) {
|
|
1367
2006
|
if (!text)
|
|
1368
2007
|
return;
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
stripped = parts[0].trim();
|
|
1372
|
-
return stripped || undefined;
|
|
2008
|
+
const stripped = text.replace(/^-\s*/, "").trim();
|
|
2009
|
+
return splitCommentLevelTags(stripped).retained.trim() || undefined;
|
|
1373
2010
|
}
|
|
1374
2011
|
function stripTypeParamSeparator(text) {
|
|
1375
2012
|
if (!text)
|
|
@@ -1391,6 +2028,7 @@ function extractSeeTagText(tag) {
|
|
|
1391
2028
|
if (seeMatch) {
|
|
1392
2029
|
let text = seeMatch[1].trim();
|
|
1393
2030
|
text = text.replace(/\s*\*\s*$/gm, "").trim();
|
|
2031
|
+
text = text.replace(/^[ \t]*\*[ \t]?/gm, "").trim();
|
|
1394
2032
|
if (text)
|
|
1395
2033
|
return text;
|
|
1396
2034
|
}
|
|
@@ -1494,8 +2132,8 @@ function getJSDocComment(node, symbol, checker) {
|
|
|
1494
2132
|
}
|
|
1495
2133
|
function getSourceLocation(node, sourceFile) {
|
|
1496
2134
|
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
1497
|
-
const
|
|
1498
|
-
const file =
|
|
2135
|
+
const relative3 = path3.relative(process.cwd(), sourceFile.fileName);
|
|
2136
|
+
const file = relative3.startsWith("..") ? sourceFile.fileName : relative3;
|
|
1499
2137
|
return {
|
|
1500
2138
|
file,
|
|
1501
2139
|
line: line + 1
|
|
@@ -1667,8 +2305,8 @@ function getExportKind(declaration, type) {
|
|
|
1667
2305
|
}
|
|
1668
2306
|
|
|
1669
2307
|
// src/compiler/program.ts
|
|
1670
|
-
import * as
|
|
1671
|
-
import * as
|
|
2308
|
+
import * as fs4 from "node:fs";
|
|
2309
|
+
import * as path4 from "node:path";
|
|
1672
2310
|
import ts2 from "typescript";
|
|
1673
2311
|
function isJsFile(file) {
|
|
1674
2312
|
return /\.(js|mjs|cjs|jsx)$/.test(file);
|
|
@@ -1684,48 +2322,48 @@ function getScriptKind(file) {
|
|
|
1684
2322
|
}
|
|
1685
2323
|
var DEFAULT_COMPILER_OPTIONS = {
|
|
1686
2324
|
target: ts2.ScriptTarget.Latest,
|
|
1687
|
-
module: ts2.ModuleKind.
|
|
2325
|
+
module: ts2.ModuleKind.NodeNext,
|
|
1688
2326
|
lib: ["lib.es2021.d.ts"],
|
|
1689
2327
|
declaration: true,
|
|
1690
|
-
moduleResolution: ts2.ModuleResolutionKind.
|
|
2328
|
+
moduleResolution: ts2.ModuleResolutionKind.NodeNext,
|
|
1691
2329
|
strict: true
|
|
1692
2330
|
};
|
|
1693
2331
|
function resolveWorkspaceEntry(pkgDir) {
|
|
1694
2332
|
const candidates = [
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
2333
|
+
path4.join(pkgDir, "src", "index.ts"),
|
|
2334
|
+
path4.join(pkgDir, "src", "index.tsx"),
|
|
2335
|
+
path4.join(pkgDir, "index.ts")
|
|
1698
2336
|
];
|
|
1699
2337
|
try {
|
|
1700
|
-
const pkg = JSON.parse(
|
|
2338
|
+
const pkg = JSON.parse(fs4.readFileSync(path4.join(pkgDir, "package.json"), "utf-8"));
|
|
1701
2339
|
for (const field of [pkg.types, pkg.typings]) {
|
|
1702
2340
|
if (typeof field === "string") {
|
|
1703
|
-
candidates.push(
|
|
2341
|
+
candidates.push(path4.resolve(pkgDir, field));
|
|
1704
2342
|
}
|
|
1705
2343
|
}
|
|
1706
2344
|
} catch {}
|
|
1707
|
-
return candidates.find((c) =>
|
|
2345
|
+
return candidates.find((c) => fs4.existsSync(c));
|
|
1708
2346
|
}
|
|
1709
2347
|
function resolveProjectReferences(configPath, parsedConfig) {
|
|
1710
2348
|
const additionalFiles = [];
|
|
1711
2349
|
if (!parsedConfig.projectReferences?.length) {
|
|
1712
2350
|
return additionalFiles;
|
|
1713
2351
|
}
|
|
1714
|
-
const configDir =
|
|
2352
|
+
const configDir = path4.dirname(configPath);
|
|
1715
2353
|
for (const ref of parsedConfig.projectReferences) {
|
|
1716
|
-
const refPath =
|
|
1717
|
-
const refConfigPath =
|
|
1718
|
-
if (!
|
|
2354
|
+
const refPath = path4.resolve(configDir, ref.path);
|
|
2355
|
+
const refConfigPath = fs4.existsSync(path4.join(refPath, "tsconfig.json")) ? path4.join(refPath, "tsconfig.json") : refPath;
|
|
2356
|
+
if (!fs4.existsSync(refConfigPath))
|
|
1719
2357
|
continue;
|
|
1720
2358
|
const refConfigFile = ts2.readConfigFile(refConfigPath, ts2.sys.readFile);
|
|
1721
2359
|
if (refConfigFile.error)
|
|
1722
2360
|
continue;
|
|
1723
|
-
const refParsed = ts2.parseJsonConfigFileContent(refConfigFile.config, ts2.sys,
|
|
2361
|
+
const refParsed = ts2.parseJsonConfigFileContent(refConfigFile.config, ts2.sys, path4.dirname(refConfigPath));
|
|
1724
2362
|
additionalFiles.push(...refParsed.fileNames);
|
|
1725
2363
|
}
|
|
1726
2364
|
return additionalFiles;
|
|
1727
2365
|
}
|
|
1728
|
-
function
|
|
2366
|
+
function parsePnpmWorkspace2(yamlContent) {
|
|
1729
2367
|
const globs = [];
|
|
1730
2368
|
const lines = yamlContent.split(`
|
|
1731
2369
|
`);
|
|
@@ -1751,52 +2389,52 @@ function parsePnpmWorkspace(yamlContent) {
|
|
|
1751
2389
|
function buildWorkspaceMap(baseDir) {
|
|
1752
2390
|
let currentDir = baseDir;
|
|
1753
2391
|
let rootDir;
|
|
1754
|
-
let
|
|
2392
|
+
let workspaceGlobs2 = [];
|
|
1755
2393
|
for (let i = 0;i < 10; i++) {
|
|
1756
|
-
const pnpmPath =
|
|
1757
|
-
if (
|
|
2394
|
+
const pnpmPath = path4.join(currentDir, "pnpm-workspace.yaml");
|
|
2395
|
+
if (fs4.existsSync(pnpmPath)) {
|
|
1758
2396
|
try {
|
|
1759
|
-
const yamlContent =
|
|
1760
|
-
|
|
1761
|
-
if (
|
|
2397
|
+
const yamlContent = fs4.readFileSync(pnpmPath, "utf-8");
|
|
2398
|
+
workspaceGlobs2 = parsePnpmWorkspace2(yamlContent);
|
|
2399
|
+
if (workspaceGlobs2.length > 0) {
|
|
1762
2400
|
rootDir = currentDir;
|
|
1763
2401
|
break;
|
|
1764
2402
|
}
|
|
1765
2403
|
} catch {}
|
|
1766
2404
|
}
|
|
1767
|
-
const pkgPath =
|
|
1768
|
-
if (
|
|
2405
|
+
const pkgPath = path4.join(currentDir, "package.json");
|
|
2406
|
+
if (fs4.existsSync(pkgPath)) {
|
|
1769
2407
|
try {
|
|
1770
|
-
const pkg = JSON.parse(
|
|
2408
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
|
|
1771
2409
|
if (pkg.workspaces) {
|
|
1772
2410
|
rootDir = currentDir;
|
|
1773
|
-
|
|
2411
|
+
workspaceGlobs2 = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages || [];
|
|
1774
2412
|
break;
|
|
1775
2413
|
}
|
|
1776
2414
|
} catch {}
|
|
1777
2415
|
}
|
|
1778
|
-
const parent =
|
|
2416
|
+
const parent = path4.dirname(currentDir);
|
|
1779
2417
|
if (parent === currentDir)
|
|
1780
2418
|
break;
|
|
1781
2419
|
currentDir = parent;
|
|
1782
2420
|
}
|
|
1783
|
-
if (!rootDir ||
|
|
2421
|
+
if (!rootDir || workspaceGlobs2.length === 0)
|
|
1784
2422
|
return;
|
|
1785
2423
|
const packages = new Map;
|
|
1786
|
-
for (const glob of
|
|
1787
|
-
const globDir =
|
|
1788
|
-
if (!
|
|
2424
|
+
for (const glob of workspaceGlobs2) {
|
|
2425
|
+
const globDir = path4.join(rootDir, glob.replace(/\/\*$/, ""));
|
|
2426
|
+
if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
|
|
1789
2427
|
continue;
|
|
1790
|
-
const entries =
|
|
2428
|
+
const entries = fs4.readdirSync(globDir, { withFileTypes: true });
|
|
1791
2429
|
for (const entry of entries) {
|
|
1792
2430
|
if (!entry.isDirectory())
|
|
1793
2431
|
continue;
|
|
1794
|
-
const pkgDir =
|
|
1795
|
-
const pkgJsonPath =
|
|
1796
|
-
if (!
|
|
2432
|
+
const pkgDir = path4.join(globDir, entry.name);
|
|
2433
|
+
const pkgJsonPath = path4.join(pkgDir, "package.json");
|
|
2434
|
+
if (!fs4.existsSync(pkgJsonPath))
|
|
1797
2435
|
continue;
|
|
1798
2436
|
try {
|
|
1799
|
-
const pkg = JSON.parse(
|
|
2437
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
|
|
1800
2438
|
if (pkg.name) {
|
|
1801
2439
|
packages.set(pkg.name, pkgDir);
|
|
1802
2440
|
}
|
|
@@ -1805,10 +2443,35 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1805
2443
|
}
|
|
1806
2444
|
return packages.size > 0 ? { packages, rootDir } : undefined;
|
|
1807
2445
|
}
|
|
2446
|
+
function discoverAmbientTypePackages(baseDir) {
|
|
2447
|
+
const found = [];
|
|
2448
|
+
const seen = new Set;
|
|
2449
|
+
let currentDir = baseDir;
|
|
2450
|
+
for (let i = 0;i < 10; i++) {
|
|
2451
|
+
const typesDir = path4.join(currentDir, "node_modules", "@types");
|
|
2452
|
+
try {
|
|
2453
|
+
if (fs4.existsSync(typesDir) && fs4.statSync(typesDir).isDirectory()) {
|
|
2454
|
+
for (const entry of fs4.readdirSync(typesDir, { withFileTypes: true })) {
|
|
2455
|
+
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
2456
|
+
continue;
|
|
2457
|
+
if (seen.has(entry.name))
|
|
2458
|
+
continue;
|
|
2459
|
+
seen.add(entry.name);
|
|
2460
|
+
found.push(entry.name);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
} catch {}
|
|
2464
|
+
const parent = path4.dirname(currentDir);
|
|
2465
|
+
if (parent === currentDir)
|
|
2466
|
+
break;
|
|
2467
|
+
currentDir = parent;
|
|
2468
|
+
}
|
|
2469
|
+
return found;
|
|
2470
|
+
}
|
|
1808
2471
|
function createProgram(options) {
|
|
1809
2472
|
const { content } = options;
|
|
1810
|
-
const entryFile =
|
|
1811
|
-
const baseDir =
|
|
2473
|
+
const entryFile = path4.resolve(options.entryFile);
|
|
2474
|
+
const baseDir = path4.resolve(options.baseDir ?? path4.dirname(entryFile));
|
|
1812
2475
|
let configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "tsconfig.json");
|
|
1813
2476
|
if (!configPath) {
|
|
1814
2477
|
configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "jsconfig.json");
|
|
@@ -1817,14 +2480,14 @@ function createProgram(options) {
|
|
|
1817
2480
|
let additionalRootFiles = [];
|
|
1818
2481
|
if (configPath) {
|
|
1819
2482
|
const configFile = ts2.readConfigFile(configPath, ts2.sys.readFile);
|
|
1820
|
-
const parsedConfig = ts2.parseJsonConfigFileContent(configFile.config, ts2.sys,
|
|
2483
|
+
const parsedConfig = ts2.parseJsonConfigFileContent(configFile.config, ts2.sys, path4.dirname(configPath));
|
|
1821
2484
|
compilerOptions = { ...compilerOptions, ...parsedConfig.options };
|
|
1822
2485
|
additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
|
|
1823
2486
|
let sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
|
|
1824
2487
|
if (/\.d\.[cm]?ts$/.test(entryFile)) {
|
|
1825
2488
|
sourceFiles = sourceFiles.filter((f) => {
|
|
1826
2489
|
try {
|
|
1827
|
-
return !ts2.getOutputFileNames(parsedConfig, f, !ts2.sys.useCaseSensitiveFileNames).some((out) =>
|
|
2490
|
+
return !ts2.getOutputFileNames(parsedConfig, f, !ts2.sys.useCaseSensitiveFileNames).some((out) => path4.resolve(out) === entryFile);
|
|
1828
2491
|
} catch {
|
|
1829
2492
|
return true;
|
|
1830
2493
|
}
|
|
@@ -1845,6 +2508,12 @@ function createProgram(options) {
|
|
|
1845
2508
|
compilerOptions = { ...compilerOptions, allowJs: false, checkJs: false };
|
|
1846
2509
|
}
|
|
1847
2510
|
}
|
|
2511
|
+
if (compilerOptions.types === undefined && compilerOptions.typeRoots === undefined) {
|
|
2512
|
+
const ambientTypes = discoverAmbientTypePackages(baseDir);
|
|
2513
|
+
if (ambientTypes.length > 0) {
|
|
2514
|
+
compilerOptions = { ...compilerOptions, types: ambientTypes };
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
1848
2517
|
const workspaceMap = buildWorkspaceMap(baseDir);
|
|
1849
2518
|
const compilerHost = ts2.createCompilerHost(compilerOptions, true);
|
|
1850
2519
|
let inMemorySource;
|
|
@@ -1901,7 +2570,7 @@ import ts5 from "typescript";
|
|
|
1901
2570
|
import ts4 from "typescript";
|
|
1902
2571
|
|
|
1903
2572
|
// src/ast/type-identity.ts
|
|
1904
|
-
import * as
|
|
2573
|
+
import * as path5 from "node:path";
|
|
1905
2574
|
import ts3 from "typescript";
|
|
1906
2575
|
var NODE_MODULES_PKG = /node_modules\/(@[^/]+\/[^/]+|[^/]+)/;
|
|
1907
2576
|
function packageLabel(fileName, workspacePackages) {
|
|
@@ -1909,7 +2578,7 @@ function packageLabel(fileName, workspacePackages) {
|
|
|
1909
2578
|
let pkg = match?.[1];
|
|
1910
2579
|
if (!pkg) {
|
|
1911
2580
|
for (const [name, dir] of workspacePackages) {
|
|
1912
|
-
if (fileName.startsWith(`${
|
|
2581
|
+
if (fileName.startsWith(`${path5.resolve(dir)}${path5.sep}`)) {
|
|
1913
2582
|
pkg = name;
|
|
1914
2583
|
break;
|
|
1915
2584
|
}
|
|
@@ -2317,6 +2986,14 @@ function isAnonymous(type) {
|
|
|
2317
2986
|
const name = symbol.getName();
|
|
2318
2987
|
return name.startsWith("__") || name === "";
|
|
2319
2988
|
}
|
|
2989
|
+
function isFluentThisType(type) {
|
|
2990
|
+
if (!(type.flags & ts4.TypeFlags.TypeParameter))
|
|
2991
|
+
return false;
|
|
2992
|
+
const declarations = type.getSymbol()?.declarations;
|
|
2993
|
+
if (!declarations || declarations.length === 0)
|
|
2994
|
+
return false;
|
|
2995
|
+
return declarations.some((decl) => ts4.isClassDeclaration(decl) || ts4.isClassExpression(decl) || ts4.isInterfaceDeclaration(decl));
|
|
2996
|
+
}
|
|
2320
2997
|
function withDepth(ctx, fn) {
|
|
2321
2998
|
ctx.currentDepth++;
|
|
2322
2999
|
try {
|
|
@@ -2352,7 +3029,7 @@ function buildSchema(type, checker, ctx) {
|
|
|
2352
3029
|
return ensureNonEmptySchema(schema, type, checker);
|
|
2353
3030
|
}
|
|
2354
3031
|
function buildMaxDepthSchema(type, checker) {
|
|
2355
|
-
if (type.flags & ts4.TypeFlags.TypeParameter && type
|
|
3032
|
+
if (type.flags & ts4.TypeFlags.TypeParameter && !isFluentThisType(type)) {
|
|
2356
3033
|
return { "x-ts-type": checker.typeToString(type) };
|
|
2357
3034
|
}
|
|
2358
3035
|
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
@@ -2440,7 +3117,7 @@ function buildSchemaInternal(type, checker, ctx) {
|
|
|
2440
3117
|
return { type: "bigint" };
|
|
2441
3118
|
if (type.flags & ts4.TypeFlags.ESSymbol)
|
|
2442
3119
|
return { type: "symbol" };
|
|
2443
|
-
if (type
|
|
3120
|
+
if (isFluentThisType(type)) {
|
|
2444
3121
|
const constraint = type.getConstraint?.();
|
|
2445
3122
|
const symbol2 = constraint?.getSymbol() ?? type.getSymbol();
|
|
2446
3123
|
if (symbol2 && !isAnonymous(type)) {
|
|
@@ -4501,12 +5178,13 @@ function serializeResolvedMembers(type, node, ctx) {
|
|
|
4501
5178
|
}
|
|
4502
5179
|
|
|
4503
5180
|
// src/schema/registry.ts
|
|
5181
|
+
import ts12 from "typescript";
|
|
4504
5182
|
function isTypeReference(type) {
|
|
4505
|
-
return !!(type.flags &
|
|
5183
|
+
return !!(type.flags & ts12.TypeFlags.Object && type.objectFlags && type.objectFlags & ts12.ObjectFlags.Reference);
|
|
4506
5184
|
}
|
|
4507
5185
|
function getNonNullableType(type) {
|
|
4508
5186
|
if (type.isUnion()) {
|
|
4509
|
-
const nonNullable = type.types.filter((t) => !(t.flags &
|
|
5187
|
+
const nonNullable = type.types.filter((t) => !(t.flags & ts12.TypeFlags.Undefined) && !(t.flags & ts12.TypeFlags.Null));
|
|
4510
5188
|
if (nonNullable.length === 1) {
|
|
4511
5189
|
return nonNullable[0];
|
|
4512
5190
|
}
|
|
@@ -5262,7 +5940,7 @@ async function getExport(options) {
|
|
|
5262
5940
|
ctx.exportedIds = exportedIds;
|
|
5263
5941
|
try {
|
|
5264
5942
|
const originalDecls = targetSymbol.declarations ?? [];
|
|
5265
|
-
const isNamespaceExportDecl = originalDecls.some((d) =>
|
|
5943
|
+
const isNamespaceExportDecl = originalDecls.some((d) => ts13.isNamespaceExport(d) || ts13.isNamespaceImport(d));
|
|
5266
5944
|
if (isNamespaceExportDecl) {
|
|
5267
5945
|
const spec2 = serializeNamespaceForGet(targetSymbol, exportName, ctx);
|
|
5268
5946
|
const types2 = ctx.typeRegistry.getAll().map((t) => normalizeType(t));
|
|
@@ -5313,42 +5991,42 @@ function resolveExportTarget(symbol, checker) {
|
|
|
5313
5991
|
let isTypeOnly = false;
|
|
5314
5992
|
const declarations = symbol.declarations ?? [];
|
|
5315
5993
|
for (const decl of declarations) {
|
|
5316
|
-
if (
|
|
5994
|
+
if (ts13.isExportSpecifier(decl)) {
|
|
5317
5995
|
if (decl.isTypeOnly)
|
|
5318
5996
|
isTypeOnly = true;
|
|
5319
5997
|
const exportDecl = decl.parent?.parent;
|
|
5320
|
-
if (exportDecl &&
|
|
5998
|
+
if (exportDecl && ts13.isExportDeclaration(exportDecl) && exportDecl.isTypeOnly) {
|
|
5321
5999
|
isTypeOnly = true;
|
|
5322
6000
|
}
|
|
5323
6001
|
}
|
|
5324
6002
|
}
|
|
5325
|
-
if (symbol.flags &
|
|
6003
|
+
if (symbol.flags & ts13.SymbolFlags.Alias) {
|
|
5326
6004
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
5327
6005
|
if (aliased && aliased !== symbol) {
|
|
5328
6006
|
resolvedSymbol = aliased;
|
|
5329
6007
|
}
|
|
5330
6008
|
}
|
|
5331
6009
|
const targetDeclarations = resolvedSymbol.declarations ?? [];
|
|
5332
|
-
const declaration = resolvedSymbol.valueDeclaration || targetDeclarations.find((d) => d.kind !==
|
|
6010
|
+
const declaration = resolvedSymbol.valueDeclaration || targetDeclarations.find((d) => d.kind !== ts13.SyntaxKind.ExportSpecifier) || targetDeclarations[0];
|
|
5333
6011
|
return { declaration, resolvedSymbol, isTypeOnly };
|
|
5334
6012
|
}
|
|
5335
6013
|
function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportName, ctx, isTypeOnly) {
|
|
5336
6014
|
let result = null;
|
|
5337
|
-
if (
|
|
6015
|
+
if (ts13.isFunctionDeclaration(declaration)) {
|
|
5338
6016
|
result = serializeFunctionExport(declaration, ctx);
|
|
5339
|
-
} else if (
|
|
6017
|
+
} else if (ts13.isClassDeclaration(declaration)) {
|
|
5340
6018
|
result = serializeClass(declaration, ctx);
|
|
5341
|
-
} else if (
|
|
6019
|
+
} else if (ts13.isInterfaceDeclaration(declaration)) {
|
|
5342
6020
|
result = serializeInterface(declaration, ctx);
|
|
5343
|
-
} else if (
|
|
6021
|
+
} else if (ts13.isTypeAliasDeclaration(declaration)) {
|
|
5344
6022
|
result = serializeTypeAlias(declaration, ctx);
|
|
5345
|
-
} else if (
|
|
6023
|
+
} else if (ts13.isEnumDeclaration(declaration)) {
|
|
5346
6024
|
result = serializeEnum(declaration, ctx);
|
|
5347
|
-
} else if (
|
|
6025
|
+
} else if (ts13.isVariableDeclaration(declaration)) {
|
|
5348
6026
|
const varStatement = declaration.parent?.parent;
|
|
5349
|
-
if (varStatement &&
|
|
5350
|
-
if (declaration.initializer && (
|
|
5351
|
-
const varName =
|
|
6027
|
+
if (varStatement && ts13.isVariableStatement(varStatement)) {
|
|
6028
|
+
if (declaration.initializer && (ts13.isArrowFunction(declaration.initializer) || ts13.isFunctionExpression(declaration.initializer))) {
|
|
6029
|
+
const varName = ts13.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
|
|
5352
6030
|
result = serializeFunctionExport(declaration.initializer, ctx, varName);
|
|
5353
6031
|
} else {
|
|
5354
6032
|
const checker = ctx.program.getTypeChecker();
|
|
@@ -5362,7 +6040,7 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
|
|
|
5362
6040
|
}
|
|
5363
6041
|
}
|
|
5364
6042
|
}
|
|
5365
|
-
} else if (
|
|
6043
|
+
} else if (ts13.isNamespaceExport(declaration) || ts13.isModuleDeclaration(declaration) || ts13.isNamespaceImport(declaration) || ts13.isSourceFile(declaration)) {
|
|
5366
6044
|
result = serializeNamespaceForGet(_exportSymbol, exportName, ctx);
|
|
5367
6045
|
}
|
|
5368
6046
|
if (result) {
|
|
@@ -5378,7 +6056,7 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
|
|
|
5378
6056
|
function serializeNamespaceForGet(symbol, exportName, ctx) {
|
|
5379
6057
|
const checker = ctx.program.getTypeChecker();
|
|
5380
6058
|
let targetSymbol = symbol;
|
|
5381
|
-
if (symbol.flags &
|
|
6059
|
+
if (symbol.flags & ts13.SymbolFlags.Alias) {
|
|
5382
6060
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
5383
6061
|
if (aliased && aliased !== symbol) {
|
|
5384
6062
|
targetSymbol = aliased;
|
|
@@ -5408,7 +6086,7 @@ function serializeNamespaceForGet(symbol, exportName, ctx) {
|
|
|
5408
6086
|
}
|
|
5409
6087
|
function detectExternalPackage(symbol, checker) {
|
|
5410
6088
|
let targetSymbol = symbol;
|
|
5411
|
-
if (symbol.flags &
|
|
6089
|
+
if (symbol.flags & ts13.SymbolFlags.Alias) {
|
|
5412
6090
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
5413
6091
|
if (aliased && aliased !== symbol) {
|
|
5414
6092
|
targetSymbol = aliased;
|
|
@@ -5422,9 +6100,9 @@ function detectExternalPackage(symbol, checker) {
|
|
|
5422
6100
|
if (match)
|
|
5423
6101
|
return match[1];
|
|
5424
6102
|
}
|
|
5425
|
-
if (
|
|
6103
|
+
if (ts13.isExportSpecifier(decl)) {
|
|
5426
6104
|
const exportDecl = decl.parent?.parent;
|
|
5427
|
-
if (exportDecl &&
|
|
6105
|
+
if (exportDecl && ts13.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
|
|
5428
6106
|
const moduleText = exportDecl.moduleSpecifier.text;
|
|
5429
6107
|
if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
|
|
5430
6108
|
return moduleText;
|
|
@@ -5435,8 +6113,8 @@ function detectExternalPackage(symbol, checker) {
|
|
|
5435
6113
|
return;
|
|
5436
6114
|
}
|
|
5437
6115
|
// src/primitives/list.ts
|
|
5438
|
-
import * as
|
|
5439
|
-
import
|
|
6116
|
+
import * as path6 from "node:path";
|
|
6117
|
+
import ts14 from "typescript";
|
|
5440
6118
|
async function listExports(options) {
|
|
5441
6119
|
const { entryFile, baseDir, content } = options;
|
|
5442
6120
|
const errors = [];
|
|
@@ -5479,16 +6157,16 @@ async function listExports(options) {
|
|
|
5479
6157
|
}
|
|
5480
6158
|
function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
5481
6159
|
const name = symbol.getName();
|
|
5482
|
-
const isReexport = !!(symbol.flags &
|
|
6160
|
+
const isReexport = !!(symbol.flags & ts14.SymbolFlags.Alias);
|
|
5483
6161
|
let targetSymbol = symbol;
|
|
5484
|
-
if (symbol.flags &
|
|
6162
|
+
if (symbol.flags & ts14.SymbolFlags.Alias) {
|
|
5485
6163
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
5486
6164
|
if (aliased && aliased !== symbol) {
|
|
5487
6165
|
targetSymbol = aliased;
|
|
5488
6166
|
}
|
|
5489
6167
|
}
|
|
5490
6168
|
const declarations = targetSymbol.declarations ?? [];
|
|
5491
|
-
const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !==
|
|
6169
|
+
const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts14.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
5492
6170
|
if (!declaration) {
|
|
5493
6171
|
return {
|
|
5494
6172
|
name,
|
|
@@ -5498,11 +6176,11 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
5498
6176
|
reexport: true
|
|
5499
6177
|
};
|
|
5500
6178
|
}
|
|
5501
|
-
if (
|
|
6179
|
+
if (ts14.isSourceFile(declaration)) {
|
|
5502
6180
|
return {
|
|
5503
6181
|
name,
|
|
5504
6182
|
kind: "namespace",
|
|
5505
|
-
file:
|
|
6183
|
+
file: path6.relative(path6.dirname(entryFile), declaration.fileName),
|
|
5506
6184
|
line: 1,
|
|
5507
6185
|
reexport: true
|
|
5508
6186
|
};
|
|
@@ -5516,7 +6194,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
5516
6194
|
return {
|
|
5517
6195
|
name,
|
|
5518
6196
|
kind,
|
|
5519
|
-
file:
|
|
6197
|
+
file: path6.relative(path6.dirname(entryFile), sourceFile.fileName),
|
|
5520
6198
|
line: line + 1,
|
|
5521
6199
|
...description ? { description } : {},
|
|
5522
6200
|
...deprecated ? { deprecated: true } : {},
|
|
@@ -5537,21 +6215,21 @@ function getDescriptionPreview(symbol, checker) {
|
|
|
5537
6215
|
return `${firstLine.slice(0, 77)}...`;
|
|
5538
6216
|
}
|
|
5539
6217
|
// src/builder/spec-builder.ts
|
|
5540
|
-
import * as
|
|
5541
|
-
import * as
|
|
6218
|
+
import * as fs7 from "node:fs";
|
|
6219
|
+
import * as path10 from "node:path";
|
|
5542
6220
|
import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
|
|
5543
|
-
import
|
|
6221
|
+
import ts19 from "typescript";
|
|
5544
6222
|
|
|
5545
6223
|
// src/ast/resolve.ts
|
|
5546
|
-
import
|
|
6224
|
+
import ts15 from "typescript";
|
|
5547
6225
|
function isTypeOnlyExport(symbol) {
|
|
5548
6226
|
const declarations = symbol.declarations ?? [];
|
|
5549
6227
|
for (const decl of declarations) {
|
|
5550
|
-
if (
|
|
6228
|
+
if (ts15.isExportSpecifier(decl)) {
|
|
5551
6229
|
if (decl.isTypeOnly)
|
|
5552
6230
|
return true;
|
|
5553
6231
|
const exportDecl = decl.parent?.parent;
|
|
5554
|
-
if (exportDecl &&
|
|
6232
|
+
if (exportDecl && ts15.isExportDeclaration(exportDecl) && exportDecl.isTypeOnly) {
|
|
5555
6233
|
return true;
|
|
5556
6234
|
}
|
|
5557
6235
|
}
|
|
@@ -5561,22 +6239,22 @@ function isTypeOnlyExport(symbol) {
|
|
|
5561
6239
|
function resolveExportTarget2(symbol, checker) {
|
|
5562
6240
|
let targetSymbol = symbol;
|
|
5563
6241
|
const isTypeOnly = isTypeOnlyExport(symbol);
|
|
5564
|
-
if (symbol.flags &
|
|
6242
|
+
if (symbol.flags & ts15.SymbolFlags.Alias) {
|
|
5565
6243
|
const aliasTarget = checker.getAliasedSymbol(symbol);
|
|
5566
6244
|
if (aliasTarget && aliasTarget !== symbol) {
|
|
5567
6245
|
targetSymbol = aliasTarget;
|
|
5568
6246
|
}
|
|
5569
6247
|
}
|
|
5570
6248
|
const declarations = targetSymbol.declarations ?? [];
|
|
5571
|
-
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !==
|
|
6249
|
+
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !== ts15.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
5572
6250
|
return { declaration, targetSymbol, isTypeOnly };
|
|
5573
6251
|
}
|
|
5574
6252
|
|
|
5575
6253
|
// src/schema/standard-schema.ts
|
|
5576
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
5577
|
-
import * as
|
|
5578
|
-
import * as
|
|
5579
|
-
import * as
|
|
6254
|
+
import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
|
|
6255
|
+
import * as fs5 from "node:fs";
|
|
6256
|
+
import * as os2 from "node:os";
|
|
6257
|
+
import * as path7 from "node:path";
|
|
5580
6258
|
var MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
5581
6259
|
function isStandardJSONSchema(obj) {
|
|
5582
6260
|
if (typeof obj !== "object" || obj === null)
|
|
@@ -5598,7 +6276,7 @@ function isStandardJSONSchema(obj) {
|
|
|
5598
6276
|
var cachedRuntime;
|
|
5599
6277
|
function commandExists(cmd) {
|
|
5600
6278
|
try {
|
|
5601
|
-
const result =
|
|
6279
|
+
const result = spawnSync2(process.platform === "win32" ? "where" : "which", [cmd], {
|
|
5602
6280
|
stdio: "ignore"
|
|
5603
6281
|
});
|
|
5604
6282
|
return result.status === 0;
|
|
@@ -5830,21 +6508,21 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5830
6508
|
result.errors.push("No TypeScript runtime available. Install bun, tsx, or ts-node, or use Node 22+.");
|
|
5831
6509
|
return result;
|
|
5832
6510
|
}
|
|
5833
|
-
if (!
|
|
6511
|
+
if (!fs5.existsSync(tsFilePath)) {
|
|
5834
6512
|
result.errors.push(`TypeScript file not found: ${tsFilePath}`);
|
|
5835
6513
|
return result;
|
|
5836
6514
|
}
|
|
5837
|
-
const tempDir =
|
|
5838
|
-
const workerPath =
|
|
6515
|
+
const tempDir = os2.tmpdir();
|
|
6516
|
+
const workerPath = path7.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
|
|
5839
6517
|
try {
|
|
5840
|
-
|
|
6518
|
+
fs5.writeFileSync(workerPath, TS_WORKER_SCRIPT);
|
|
5841
6519
|
const optionsJson = JSON.stringify({ target, libraryOptions });
|
|
5842
6520
|
const args = [...runtime.args, workerPath, tsFilePath, optionsJson];
|
|
5843
|
-
return await new Promise((
|
|
5844
|
-
const child =
|
|
6521
|
+
return await new Promise((resolve4) => {
|
|
6522
|
+
const child = spawn2(runtime.cmd, args, {
|
|
5845
6523
|
timeout,
|
|
5846
6524
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5847
|
-
cwd:
|
|
6525
|
+
cwd: path7.dirname(tsFilePath)
|
|
5848
6526
|
});
|
|
5849
6527
|
let stdout = "";
|
|
5850
6528
|
let stderr = "";
|
|
@@ -5868,7 +6546,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5868
6546
|
});
|
|
5869
6547
|
child.on("close", (code) => {
|
|
5870
6548
|
try {
|
|
5871
|
-
|
|
6549
|
+
fs5.unlinkSync(workerPath);
|
|
5872
6550
|
} catch (cleanupErr) {
|
|
5873
6551
|
if (cleanupErr?.code !== "ENOENT") {
|
|
5874
6552
|
result.warnings.push({ code: "CLEANUP_FAILED", message: String(cleanupErr) });
|
|
@@ -5876,14 +6554,14 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5876
6554
|
}
|
|
5877
6555
|
if (code !== 0) {
|
|
5878
6556
|
result.errors.push(`Extraction failed (${runtime.name}): ${stderr || `exit code ${code}`}`);
|
|
5879
|
-
|
|
6557
|
+
resolve4(result);
|
|
5880
6558
|
return;
|
|
5881
6559
|
}
|
|
5882
6560
|
try {
|
|
5883
6561
|
const parsed = JSON.parse(stdout);
|
|
5884
6562
|
if (!parsed.success) {
|
|
5885
6563
|
result.errors.push(`Extraction failed: ${parsed.error}`);
|
|
5886
|
-
|
|
6564
|
+
resolve4(result);
|
|
5887
6565
|
return;
|
|
5888
6566
|
}
|
|
5889
6567
|
for (const item of parsed.results) {
|
|
@@ -5918,23 +6596,23 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5918
6596
|
message: "stderr exceeded 10MB buffer limit"
|
|
5919
6597
|
});
|
|
5920
6598
|
}
|
|
5921
|
-
|
|
6599
|
+
resolve4(result);
|
|
5922
6600
|
});
|
|
5923
6601
|
child.on("error", (err) => {
|
|
5924
6602
|
try {
|
|
5925
|
-
|
|
6603
|
+
fs5.unlinkSync(workerPath);
|
|
5926
6604
|
} catch (cleanupErr) {
|
|
5927
6605
|
if (cleanupErr?.code !== "ENOENT") {
|
|
5928
6606
|
result.warnings.push({ code: "CLEANUP_FAILED", message: String(cleanupErr) });
|
|
5929
6607
|
}
|
|
5930
6608
|
}
|
|
5931
6609
|
result.errors.push(`Subprocess error: ${err.message}`);
|
|
5932
|
-
|
|
6610
|
+
resolve4(result);
|
|
5933
6611
|
});
|
|
5934
6612
|
});
|
|
5935
6613
|
} catch (e) {
|
|
5936
6614
|
try {
|
|
5937
|
-
|
|
6615
|
+
fs5.unlinkSync(workerPath);
|
|
5938
6616
|
} catch (cleanupErr) {
|
|
5939
6617
|
if (cleanupErr?.code !== "ENOENT") {
|
|
5940
6618
|
result.warnings.push({ code: "CLEANUP_FAILED", message: String(cleanupErr) });
|
|
@@ -5945,12 +6623,12 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5945
6623
|
}
|
|
5946
6624
|
}
|
|
5947
6625
|
function readTsconfigOutDir(baseDir) {
|
|
5948
|
-
const tsconfigPath =
|
|
6626
|
+
const tsconfigPath = path7.join(baseDir, "tsconfig.json");
|
|
5949
6627
|
try {
|
|
5950
|
-
if (!
|
|
6628
|
+
if (!fs5.existsSync(tsconfigPath)) {
|
|
5951
6629
|
return null;
|
|
5952
6630
|
}
|
|
5953
|
-
const content =
|
|
6631
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
5954
6632
|
const stripped = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
5955
6633
|
const tsconfig = JSON.parse(stripped);
|
|
5956
6634
|
if (tsconfig.compilerOptions?.outDir) {
|
|
@@ -5960,7 +6638,7 @@ function readTsconfigOutDir(baseDir) {
|
|
|
5960
6638
|
return null;
|
|
5961
6639
|
}
|
|
5962
6640
|
function resolveCompiledPath(tsPath, baseDir) {
|
|
5963
|
-
const relativePath =
|
|
6641
|
+
const relativePath = path7.relative(baseDir, tsPath);
|
|
5964
6642
|
const withoutExt = relativePath.replace(/\.tsx?$/, "");
|
|
5965
6643
|
const srcPrefix = withoutExt.replace(/^src\//, "");
|
|
5966
6644
|
const tsconfigOutDir = readTsconfigOutDir(baseDir);
|
|
@@ -5968,7 +6646,7 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5968
6646
|
const candidates = [];
|
|
5969
6647
|
if (tsconfigOutDir) {
|
|
5970
6648
|
for (const ext of extensions) {
|
|
5971
|
-
candidates.push(
|
|
6649
|
+
candidates.push(path7.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
|
|
5972
6650
|
}
|
|
5973
6651
|
}
|
|
5974
6652
|
const commonOutDirs = ["dist", "build", "lib", "out"];
|
|
@@ -5976,21 +6654,21 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5976
6654
|
if (outDir === tsconfigOutDir)
|
|
5977
6655
|
continue;
|
|
5978
6656
|
for (const ext of extensions) {
|
|
5979
|
-
candidates.push(
|
|
6657
|
+
candidates.push(path7.join(baseDir, outDir, `${srcPrefix}${ext}`));
|
|
5980
6658
|
}
|
|
5981
6659
|
}
|
|
5982
6660
|
for (const ext of extensions) {
|
|
5983
|
-
candidates.push(
|
|
6661
|
+
candidates.push(path7.join(baseDir, `${withoutExt}${ext}`));
|
|
5984
6662
|
}
|
|
5985
6663
|
const workspaceMatch = baseDir.match(/^(.+\/packages\/[^/]+)$/);
|
|
5986
6664
|
if (workspaceMatch) {
|
|
5987
6665
|
const pkgRoot = workspaceMatch[1];
|
|
5988
6666
|
for (const ext of extensions) {
|
|
5989
|
-
candidates.push(
|
|
6667
|
+
candidates.push(path7.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
|
|
5990
6668
|
}
|
|
5991
6669
|
}
|
|
5992
6670
|
for (const candidate of candidates) {
|
|
5993
|
-
if (
|
|
6671
|
+
if (fs5.existsSync(candidate)) {
|
|
5994
6672
|
return candidate;
|
|
5995
6673
|
}
|
|
5996
6674
|
}
|
|
@@ -6003,13 +6681,13 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
|
|
|
6003
6681
|
errors: [],
|
|
6004
6682
|
warnings: []
|
|
6005
6683
|
};
|
|
6006
|
-
if (!
|
|
6684
|
+
if (!fs5.existsSync(compiledJsPath)) {
|
|
6007
6685
|
result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
|
|
6008
6686
|
return result;
|
|
6009
6687
|
}
|
|
6010
6688
|
const optionsJson = JSON.stringify({ target, libraryOptions });
|
|
6011
|
-
return new Promise((
|
|
6012
|
-
const child =
|
|
6689
|
+
return new Promise((resolve4) => {
|
|
6690
|
+
const child = spawn2("node", ["-e", WORKER_SCRIPT, compiledJsPath, optionsJson], {
|
|
6013
6691
|
timeout,
|
|
6014
6692
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6015
6693
|
});
|
|
@@ -6036,14 +6714,14 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
|
|
|
6036
6714
|
child.on("close", (code) => {
|
|
6037
6715
|
if (code !== 0) {
|
|
6038
6716
|
result.errors.push(`Extraction process failed: ${stderr || `exit code ${code}`}`);
|
|
6039
|
-
|
|
6717
|
+
resolve4(result);
|
|
6040
6718
|
return;
|
|
6041
6719
|
}
|
|
6042
6720
|
try {
|
|
6043
6721
|
const parsed = JSON.parse(stdout);
|
|
6044
6722
|
if (!parsed.success) {
|
|
6045
6723
|
result.errors.push(`Extraction failed: ${parsed.error}`);
|
|
6046
|
-
|
|
6724
|
+
resolve4(result);
|
|
6047
6725
|
return;
|
|
6048
6726
|
}
|
|
6049
6727
|
for (const item of parsed.results) {
|
|
@@ -6078,11 +6756,11 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
|
|
|
6078
6756
|
message: "stderr exceeded 10MB buffer limit"
|
|
6079
6757
|
});
|
|
6080
6758
|
}
|
|
6081
|
-
|
|
6759
|
+
resolve4(result);
|
|
6082
6760
|
});
|
|
6083
6761
|
child.on("error", (err) => {
|
|
6084
6762
|
result.errors.push(`Subprocess error: ${err.message}`);
|
|
6085
|
-
|
|
6763
|
+
resolve4(result);
|
|
6086
6764
|
});
|
|
6087
6765
|
});
|
|
6088
6766
|
}
|
|
@@ -6119,10 +6797,10 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
|
|
|
6119
6797
|
}
|
|
6120
6798
|
|
|
6121
6799
|
// src/builder/external-resolver.ts
|
|
6122
|
-
import * as
|
|
6123
|
-
import * as
|
|
6800
|
+
import * as fs6 from "node:fs";
|
|
6801
|
+
import * as path8 from "node:path";
|
|
6124
6802
|
import picomatch from "picomatch";
|
|
6125
|
-
import
|
|
6803
|
+
import ts16 from "typescript";
|
|
6126
6804
|
function matchesExternalPattern(packageName, include, exclude) {
|
|
6127
6805
|
if (!include?.length)
|
|
6128
6806
|
return false;
|
|
@@ -6138,7 +6816,7 @@ function matchesExternalPattern(packageName, include, exclude) {
|
|
|
6138
6816
|
return true;
|
|
6139
6817
|
}
|
|
6140
6818
|
function resolveExternalModule(moduleSpecifier, containingFile, compilerOptions) {
|
|
6141
|
-
const resolved =
|
|
6819
|
+
const resolved = ts16.resolveModuleName(moduleSpecifier, containingFile, compilerOptions, ts16.sys);
|
|
6142
6820
|
if (!resolved.resolvedModule) {
|
|
6143
6821
|
return null;
|
|
6144
6822
|
}
|
|
@@ -6154,20 +6832,20 @@ function findPackageJson(resolvedPath, packageName) {
|
|
|
6154
6832
|
const isScoped = packageName.startsWith("@");
|
|
6155
6833
|
const packageParts = isScoped ? packageName.split("/").slice(0, 2) : [packageName.split("/")[0]];
|
|
6156
6834
|
const packageDir = packageParts.join("/");
|
|
6157
|
-
let dir =
|
|
6835
|
+
let dir = path8.dirname(resolvedPath);
|
|
6158
6836
|
const maxDepth = 10;
|
|
6159
6837
|
for (let i = 0;i < maxDepth; i++) {
|
|
6160
6838
|
if (dir.endsWith(`node_modules/${packageDir}`)) {
|
|
6161
|
-
const pkgPath =
|
|
6162
|
-
if (
|
|
6839
|
+
const pkgPath = path8.join(dir, "package.json");
|
|
6840
|
+
if (fs6.existsSync(pkgPath)) {
|
|
6163
6841
|
try {
|
|
6164
|
-
return JSON.parse(
|
|
6842
|
+
return JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
6165
6843
|
} catch {
|
|
6166
6844
|
return;
|
|
6167
6845
|
}
|
|
6168
6846
|
}
|
|
6169
6847
|
}
|
|
6170
|
-
const parent =
|
|
6848
|
+
const parent = path8.dirname(dir);
|
|
6171
6849
|
if (parent === dir)
|
|
6172
6850
|
break;
|
|
6173
6851
|
dir = parent;
|
|
@@ -6203,7 +6881,7 @@ function extractExternalExport(exportName, resolvedModule, program, ctx, visited
|
|
|
6203
6881
|
return null;
|
|
6204
6882
|
}
|
|
6205
6883
|
let resolvedSymbol = targetExport;
|
|
6206
|
-
if (targetExport.flags &
|
|
6884
|
+
if (targetExport.flags & ts16.SymbolFlags.Alias) {
|
|
6207
6885
|
const aliased = checker.getAliasedSymbol(targetExport);
|
|
6208
6886
|
if (aliased && aliased !== targetExport) {
|
|
6209
6887
|
resolvedSymbol = aliased;
|
|
@@ -6245,6 +6923,80 @@ function extractExternalExport(exportName, resolvedModule, program, ctx, visited
|
|
|
6245
6923
|
return specExport;
|
|
6246
6924
|
}
|
|
6247
6925
|
|
|
6926
|
+
// src/builder/jev-extract.ts
|
|
6927
|
+
var FOLLOW_SCORE_LEVELS = [
|
|
6928
|
+
"opaque — a stub is enough",
|
|
6929
|
+
"useful — expanding helps",
|
|
6930
|
+
"essential — needed to understand the public API"
|
|
6931
|
+
];
|
|
6932
|
+
var AMBIGUOUS_CODES = new Set([
|
|
6933
|
+
"FORGOTTEN_EXPORT",
|
|
6934
|
+
"SERIALIZATION_FAILED",
|
|
6935
|
+
"RUNTIME_SCHEMA_ERROR"
|
|
6936
|
+
]);
|
|
6937
|
+
async function selectFollowExternal(refs, evaluate) {
|
|
6938
|
+
const sliced = refs.slice(0, MAX_JEV_QUESTIONS);
|
|
6939
|
+
if (!sliced.length)
|
|
6940
|
+
return [];
|
|
6941
|
+
const questions = {};
|
|
6942
|
+
for (const [i, ref] of sliced.entries()) {
|
|
6943
|
+
questions[`t${i}`] = {
|
|
6944
|
+
type: "score",
|
|
6945
|
+
instructions: `How load-bearing is ${ref.typeName} from ${ref.package} for understanding this public TypeScript API?`,
|
|
6946
|
+
criteria: FOLLOW_SCORE_LEVELS
|
|
6947
|
+
};
|
|
6948
|
+
}
|
|
6949
|
+
const result = await jevEvaluate(evaluate, {
|
|
6950
|
+
types: sliced,
|
|
6951
|
+
task: "OpenPkg extracts a public TS API. Stub opaque externals; expand load-bearing ones."
|
|
6952
|
+
}, questions);
|
|
6953
|
+
const follow = new Set;
|
|
6954
|
+
for (const [i, ref] of sliced.entries()) {
|
|
6955
|
+
const id = `t${i}`;
|
|
6956
|
+
const score = result.answers[id]?.score;
|
|
6957
|
+
if (typeof score !== "number")
|
|
6958
|
+
continue;
|
|
6959
|
+
const conf = namedConfidence(result, id) ?? (score >= 1.5 || score <= 0.5 ? 1 : 0);
|
|
6960
|
+
if (score >= 1.5 || score >= 1 && conf >= JEV_CONFIDENCE)
|
|
6961
|
+
follow.add(ref.package);
|
|
6962
|
+
}
|
|
6963
|
+
return [...follow];
|
|
6964
|
+
}
|
|
6965
|
+
async function calibrateDiagnostics(diagnostics, evaluate) {
|
|
6966
|
+
const targets = diagnostics.map((d, index) => ({ d, index })).filter(({ d }) => d.code && AMBIGUOUS_CODES.has(d.code)).slice(0, MAX_JEV_QUESTIONS);
|
|
6967
|
+
if (targets.length < 1)
|
|
6968
|
+
return;
|
|
6969
|
+
const questions = {};
|
|
6970
|
+
for (const [i, { d }] of targets.entries()) {
|
|
6971
|
+
questions[`d${i}`] = {
|
|
6972
|
+
type: "choice",
|
|
6973
|
+
instructions: `What severity should this extraction diagnostic have? ${d.message}`,
|
|
6974
|
+
criteria: {
|
|
6975
|
+
error: "Blocks a correct spec",
|
|
6976
|
+
warning: "Likely a real API gap",
|
|
6977
|
+
info: "Informational only"
|
|
6978
|
+
}
|
|
6979
|
+
};
|
|
6980
|
+
}
|
|
6981
|
+
const result = await jevEvaluate(evaluate, {
|
|
6982
|
+
diagnostics: targets.map(({ d }) => ({
|
|
6983
|
+
code: d.code,
|
|
6984
|
+
message: d.message,
|
|
6985
|
+
severity: d.severity
|
|
6986
|
+
}))
|
|
6987
|
+
}, questions);
|
|
6988
|
+
for (const [i, { d }] of targets.entries()) {
|
|
6989
|
+
const id = `d${i}`;
|
|
6990
|
+
const choice = result.answers[id]?.choice;
|
|
6991
|
+
if (choice !== "error" && choice !== "warning" && choice !== "info")
|
|
6992
|
+
continue;
|
|
6993
|
+
const conf = namedConfidence(result, id) ?? result.answers[id]?.probabilities?.[choice] ?? 0;
|
|
6994
|
+
if (conf < JEV_CONFIDENCE)
|
|
6995
|
+
continue;
|
|
6996
|
+
d.severity = choice;
|
|
6997
|
+
}
|
|
6998
|
+
}
|
|
6999
|
+
|
|
6248
7000
|
// src/builder/schema-merger.ts
|
|
6249
7001
|
function mergeRuntimeSchemas(staticExports, runtimeSchemas) {
|
|
6250
7002
|
let merged = 0;
|
|
@@ -6274,7 +7026,7 @@ function mergeRuntimeSchemas(staticExports, runtimeSchemas) {
|
|
|
6274
7026
|
}
|
|
6275
7027
|
|
|
6276
7028
|
// src/builder/type-cache.ts
|
|
6277
|
-
import
|
|
7029
|
+
import ts17 from "typescript";
|
|
6278
7030
|
|
|
6279
7031
|
// src/utils/cache-manager.ts
|
|
6280
7032
|
class CacheManager {
|
|
@@ -6381,10 +7133,10 @@ function findTypeDefinition(typeName, program, sourceFile) {
|
|
|
6381
7133
|
return typeDefinitionCache.getOrCompute(typeName, () => {
|
|
6382
7134
|
const checker = program.getTypeChecker();
|
|
6383
7135
|
const findInNode = (node) => {
|
|
6384
|
-
if ((
|
|
7136
|
+
if ((ts17.isInterfaceDeclaration(node) || ts17.isTypeAliasDeclaration(node) || ts17.isClassDeclaration(node) || ts17.isEnumDeclaration(node)) && node.name?.text === typeName) {
|
|
6385
7137
|
return node.getSourceFile().fileName;
|
|
6386
7138
|
}
|
|
6387
|
-
return
|
|
7139
|
+
return ts17.forEachChild(node, findInNode);
|
|
6388
7140
|
};
|
|
6389
7141
|
const entryResult = findInNode(sourceFile);
|
|
6390
7142
|
if (entryResult)
|
|
@@ -6396,14 +7148,14 @@ function findTypeDefinition(typeName, program, sourceFile) {
|
|
|
6396
7148
|
return result;
|
|
6397
7149
|
}
|
|
6398
7150
|
}
|
|
6399
|
-
const symbol = checker.resolveName(typeName, sourceFile,
|
|
7151
|
+
const symbol = checker.resolveName(typeName, sourceFile, ts17.SymbolFlags.Type, false);
|
|
6400
7152
|
return symbol?.declarations?.[0]?.getSourceFile().fileName;
|
|
6401
7153
|
});
|
|
6402
7154
|
}
|
|
6403
7155
|
function hasInternalTag(typeName, program, sourceFile) {
|
|
6404
7156
|
return internalTagCache.getOrCompute(typeName, () => {
|
|
6405
7157
|
const checker = program.getTypeChecker();
|
|
6406
|
-
const symbol = checker.resolveName(typeName, sourceFile,
|
|
7158
|
+
const symbol = checker.resolveName(typeName, sourceFile, ts17.SymbolFlags.Type, false);
|
|
6407
7159
|
if (!symbol)
|
|
6408
7160
|
return false;
|
|
6409
7161
|
return symbol.getJsDocTags().some((tag) => tag.name === "internal");
|
|
@@ -6411,7 +7163,7 @@ function hasInternalTag(typeName, program, sourceFile) {
|
|
|
6411
7163
|
}
|
|
6412
7164
|
|
|
6413
7165
|
// src/builder/type-expansion.ts
|
|
6414
|
-
import
|
|
7166
|
+
import ts18 from "typescript";
|
|
6415
7167
|
var NODE_MODULES_PKG2 = /node_modules\/(@[^/]+\/[^/]+|[^/]+)/;
|
|
6416
7168
|
function isLibFile(fileName) {
|
|
6417
7169
|
return fileName.includes("/typescript/lib/lib.") || fileName.includes("\\typescript\\lib\\lib.");
|
|
@@ -6428,8 +7180,9 @@ function createExternalExpansionPredicate(opts) {
|
|
|
6428
7180
|
return false;
|
|
6429
7181
|
if (opts.followExternal === true)
|
|
6430
7182
|
return true;
|
|
6431
|
-
if (Array.isArray(opts.followExternal) && opts.followExternal.some((e) => matchesEntry(e, pkg)))
|
|
7183
|
+
if (Array.isArray(opts.followExternal) && opts.followExternal.some((e) => matchesEntry(e, pkg))) {
|
|
6432
7184
|
return true;
|
|
7185
|
+
}
|
|
6433
7186
|
return opts.workspacePackages.has(pkg);
|
|
6434
7187
|
};
|
|
6435
7188
|
return (symbol) => {
|
|
@@ -6445,6 +7198,66 @@ function createExternalExpansionPredicate(opts) {
|
|
|
6445
7198
|
return true;
|
|
6446
7199
|
};
|
|
6447
7200
|
}
|
|
7201
|
+
function collectReferencedExternals(exportedSymbols, checker, workspacePackages) {
|
|
7202
|
+
const out = [];
|
|
7203
|
+
const seen = new Set;
|
|
7204
|
+
const visited = new Set;
|
|
7205
|
+
const consider = (symbol) => {
|
|
7206
|
+
if (!symbol)
|
|
7207
|
+
return;
|
|
7208
|
+
const decl = symbol.declarations?.[0];
|
|
7209
|
+
if (!decl)
|
|
7210
|
+
return;
|
|
7211
|
+
const fileName = decl.getSourceFile().fileName;
|
|
7212
|
+
if (isLibFile(fileName))
|
|
7213
|
+
return;
|
|
7214
|
+
const match = fileName.match(NODE_MODULES_PKG2);
|
|
7215
|
+
if (!match)
|
|
7216
|
+
return;
|
|
7217
|
+
const pkg = match[1];
|
|
7218
|
+
if (pkg === "typescript" || workspacePackages.has(pkg))
|
|
7219
|
+
return;
|
|
7220
|
+
const typeName = symbol.getName();
|
|
7221
|
+
if (typeName.startsWith("__"))
|
|
7222
|
+
return;
|
|
7223
|
+
const key = `${pkg}:${typeName}`;
|
|
7224
|
+
if (seen.has(key))
|
|
7225
|
+
return;
|
|
7226
|
+
seen.add(key);
|
|
7227
|
+
out.push({ typeName, package: pkg });
|
|
7228
|
+
};
|
|
7229
|
+
const visit = (type, depth) => {
|
|
7230
|
+
if (!type || depth > 20 || visited.has(type))
|
|
7231
|
+
return;
|
|
7232
|
+
visited.add(type);
|
|
7233
|
+
const symbol = type.aliasSymbol ?? type.getSymbol();
|
|
7234
|
+
consider(symbol);
|
|
7235
|
+
const match = symbol?.declarations?.[0]?.getSourceFile().fileName.match(NODE_MODULES_PKG2);
|
|
7236
|
+
if (match && !workspacePackages.has(match[1]))
|
|
7237
|
+
return;
|
|
7238
|
+
for (const arg of type.aliasTypeArguments ?? [])
|
|
7239
|
+
visit(arg, depth + 1);
|
|
7240
|
+
const typeRef = type;
|
|
7241
|
+
if (typeRef.target) {
|
|
7242
|
+
for (const arg of checker.getTypeArguments(typeRef) ?? [])
|
|
7243
|
+
visit(arg, depth + 1);
|
|
7244
|
+
}
|
|
7245
|
+
if (type.isUnion() || type.isIntersection()) {
|
|
7246
|
+
for (const t of type.types)
|
|
7247
|
+
visit(t, depth + 1);
|
|
7248
|
+
}
|
|
7249
|
+
for (const sig of [...type.getCallSignatures(), ...type.getConstructSignatures()]) {
|
|
7250
|
+
for (const param of sig.getParameters())
|
|
7251
|
+
visit(checker.getTypeOfSymbol(param), depth + 1);
|
|
7252
|
+
visit(sig.getReturnType(), depth + 1);
|
|
7253
|
+
}
|
|
7254
|
+
};
|
|
7255
|
+
for (const symbol of exportedSymbols) {
|
|
7256
|
+
visit(checker.getTypeOfSymbol(symbol), 0);
|
|
7257
|
+
visit(checker.getDeclaredTypeOfSymbol(symbol), 0);
|
|
7258
|
+
}
|
|
7259
|
+
return out;
|
|
7260
|
+
}
|
|
6448
7261
|
function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
6449
7262
|
if (opts.followExternal === false)
|
|
6450
7263
|
return;
|
|
@@ -6480,7 +7293,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6480
7293
|
visit(t, depth + 1);
|
|
6481
7294
|
}
|
|
6482
7295
|
}
|
|
6483
|
-
if (!allowed || !(type.flags &
|
|
7296
|
+
if (!allowed || !(type.flags & ts18.TypeFlags.Object || type.isClassOrInterface())) {
|
|
6484
7297
|
return;
|
|
6485
7298
|
}
|
|
6486
7299
|
if (type.isClassOrInterface()) {
|
|
@@ -6503,19 +7316,19 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6503
7316
|
visit(info.type, depth + 1);
|
|
6504
7317
|
}
|
|
6505
7318
|
};
|
|
6506
|
-
const TYPE_SYMBOL_FLAGS =
|
|
7319
|
+
const TYPE_SYMBOL_FLAGS = ts18.SymbolFlags.Interface | ts18.SymbolFlags.TypeAlias | ts18.SymbolFlags.Class | ts18.SymbolFlags.RegularEnum | ts18.SymbolFlags.ConstEnum;
|
|
6507
7320
|
const visitedSymbols = new Set;
|
|
6508
7321
|
const symbolKind = (symbol) => {
|
|
6509
|
-
if (symbol.flags &
|
|
7322
|
+
if (symbol.flags & ts18.SymbolFlags.Interface)
|
|
6510
7323
|
return "interface";
|
|
6511
|
-
if (symbol.flags &
|
|
7324
|
+
if (symbol.flags & ts18.SymbolFlags.Class)
|
|
6512
7325
|
return "class";
|
|
6513
|
-
if (symbol.flags & (
|
|
7326
|
+
if (symbol.flags & (ts18.SymbolFlags.RegularEnum | ts18.SymbolFlags.ConstEnum))
|
|
6514
7327
|
return "enum";
|
|
6515
7328
|
return "type";
|
|
6516
7329
|
};
|
|
6517
7330
|
const resolveAlias = (symbol) => {
|
|
6518
|
-
if (symbol.flags &
|
|
7331
|
+
if (symbol.flags & ts18.SymbolFlags.Alias) {
|
|
6519
7332
|
try {
|
|
6520
7333
|
return checker.getAliasedSymbol(symbol);
|
|
6521
7334
|
} catch {
|
|
@@ -6567,7 +7380,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6567
7380
|
const target = symbol && resolveAlias(symbol);
|
|
6568
7381
|
if (!target || visitedSymbols.has(target))
|
|
6569
7382
|
return;
|
|
6570
|
-
if (!(target.flags & (
|
|
7383
|
+
if (!(target.flags & (ts18.SymbolFlags.ValueModule | ts18.SymbolFlags.NamespaceModule)))
|
|
6571
7384
|
return;
|
|
6572
7385
|
if (!symbolAllowed(target))
|
|
6573
7386
|
return;
|
|
@@ -6582,22 +7395,22 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6582
7395
|
}
|
|
6583
7396
|
};
|
|
6584
7397
|
const walkNode = (node) => {
|
|
6585
|
-
if (
|
|
7398
|
+
if (ts18.isTypeReferenceNode(node)) {
|
|
6586
7399
|
handleRef(node.typeName);
|
|
6587
|
-
if (
|
|
7400
|
+
if (ts18.isQualifiedName(node.typeName)) {
|
|
6588
7401
|
handleNamespaceRef(node.typeName.left);
|
|
6589
7402
|
}
|
|
6590
|
-
} else if (
|
|
7403
|
+
} else if (ts18.isExpressionWithTypeArguments(node)) {
|
|
6591
7404
|
handleRef(node.expression);
|
|
6592
|
-
} else if (
|
|
7405
|
+
} else if (ts18.isTypeQueryNode(node)) {
|
|
6593
7406
|
handleRef(node.exprName);
|
|
6594
|
-
if (
|
|
7407
|
+
if (ts18.isQualifiedName(node.exprName)) {
|
|
6595
7408
|
handleRef(node.exprName.left);
|
|
6596
7409
|
handleNamespaceRef(node.exprName.left);
|
|
6597
7410
|
}
|
|
6598
|
-
} else if (
|
|
7411
|
+
} else if (ts18.isImportTypeNode(node) && node.qualifier) {
|
|
6599
7412
|
handleRef(node.qualifier);
|
|
6600
|
-
if (
|
|
7413
|
+
if (ts18.isQualifiedName(node.qualifier)) {
|
|
6601
7414
|
handleNamespaceRef(node.qualifier.left);
|
|
6602
7415
|
}
|
|
6603
7416
|
}
|
|
@@ -6613,7 +7426,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6613
7426
|
};
|
|
6614
7427
|
for (const exportSymbol of exportedSymbols) {
|
|
6615
7428
|
let target = exportSymbol;
|
|
6616
|
-
if (exportSymbol.flags &
|
|
7429
|
+
if (exportSymbol.flags & ts18.SymbolFlags.Alias) {
|
|
6617
7430
|
try {
|
|
6618
7431
|
target = checker.getAliasedSymbol(exportSymbol);
|
|
6619
7432
|
} catch {
|
|
@@ -6632,7 +7445,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
6632
7445
|
}
|
|
6633
7446
|
|
|
6634
7447
|
// src/builder/verification.ts
|
|
6635
|
-
import * as
|
|
7448
|
+
import * as path9 from "node:path";
|
|
6636
7449
|
var BUILTIN_TYPES2 = new Set([
|
|
6637
7450
|
"Array",
|
|
6638
7451
|
"ArrayBuffer",
|
|
@@ -6721,8 +7534,8 @@ function isExternalType2(definedIn, baseDir) {
|
|
|
6721
7534
|
return true;
|
|
6722
7535
|
if (definedIn.includes("node_modules"))
|
|
6723
7536
|
return true;
|
|
6724
|
-
const normalizedDefined =
|
|
6725
|
-
const normalizedBase =
|
|
7537
|
+
const normalizedDefined = path9.resolve(definedIn);
|
|
7538
|
+
const normalizedBase = path9.resolve(baseDir);
|
|
6726
7539
|
return !normalizedDefined.startsWith(normalizedBase);
|
|
6727
7540
|
}
|
|
6728
7541
|
function shouldSkipDanglingRef(name) {
|
|
@@ -6887,7 +7700,7 @@ async function extract(options) {
|
|
|
6887
7700
|
const { program, sourceFile } = result;
|
|
6888
7701
|
if (!sourceFile) {
|
|
6889
7702
|
return {
|
|
6890
|
-
spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
|
|
7703
|
+
spec: createEmptySpec(entryFile, includeSchema, isDtsSource, options.entryPointSource),
|
|
6891
7704
|
diagnostics: [
|
|
6892
7705
|
{
|
|
6893
7706
|
message: `Entry file not found: ${entryFile}. Specify with: drift list src/index.ts`,
|
|
@@ -6900,7 +7713,7 @@ async function extract(options) {
|
|
|
6900
7713
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
6901
7714
|
if (!moduleSymbol) {
|
|
6902
7715
|
return {
|
|
6903
|
-
spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
|
|
7716
|
+
spec: createEmptySpec(entryFile, includeSchema, isDtsSource, options.entryPointSource),
|
|
6904
7717
|
diagnostics: [
|
|
6905
7718
|
{
|
|
6906
7719
|
message: `No exports found in ${entryFile}. Is this the right entry point?`,
|
|
@@ -6912,7 +7725,7 @@ async function extract(options) {
|
|
|
6912
7725
|
const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
|
|
6913
7726
|
if (exportedSymbols.length === 0) {
|
|
6914
7727
|
return {
|
|
6915
|
-
spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
|
|
7728
|
+
spec: createEmptySpec(entryFile, includeSchema, isDtsSource, options.entryPointSource),
|
|
6916
7729
|
diagnostics: [
|
|
6917
7730
|
{
|
|
6918
7731
|
message: `No exports found in ${entryFile}. Is this the right entry point?`,
|
|
@@ -6936,6 +7749,36 @@ async function extract(options) {
|
|
|
6936
7749
|
...included ? {} : { skipReason: "filtered" }
|
|
6937
7750
|
});
|
|
6938
7751
|
}
|
|
7752
|
+
let followExternal = options.followExternal;
|
|
7753
|
+
let evaluate = options.evaluate;
|
|
7754
|
+
const wantsJev = options.decisions === "jev" || followExternal === "auto";
|
|
7755
|
+
if (wantsJev && !evaluate) {
|
|
7756
|
+
if (process.env.AI_GATEWAY_API_KEY) {
|
|
7757
|
+
try {
|
|
7758
|
+
evaluate = await loadEvaluate();
|
|
7759
|
+
} catch (err) {
|
|
7760
|
+
diagnostics.push({
|
|
7761
|
+
message: err instanceof Error ? err.message : String(err),
|
|
7762
|
+
severity: "error",
|
|
7763
|
+
code: "JEV_UNAVAILABLE"
|
|
7764
|
+
});
|
|
7765
|
+
}
|
|
7766
|
+
} else if (followExternal === "auto") {
|
|
7767
|
+
diagnostics.push({
|
|
7768
|
+
message: "followExternal auto requires --jev and AI_GATEWAY_API_KEY",
|
|
7769
|
+
severity: "error",
|
|
7770
|
+
code: "JEV_UNAVAILABLE"
|
|
7771
|
+
});
|
|
7772
|
+
}
|
|
7773
|
+
}
|
|
7774
|
+
if (followExternal === "auto") {
|
|
7775
|
+
if (!evaluate) {
|
|
7776
|
+
followExternal = undefined;
|
|
7777
|
+
} else {
|
|
7778
|
+
const refs = collectReferencedExternals(exportedSymbols, typeChecker, result.workspacePackages ?? new Map);
|
|
7779
|
+
followExternal = await selectFollowExternal(refs, evaluate);
|
|
7780
|
+
}
|
|
7781
|
+
}
|
|
6939
7782
|
const ctx = createContext(program, sourceFile, {
|
|
6940
7783
|
maxTypeDepth,
|
|
6941
7784
|
maxExternalTypeDepth,
|
|
@@ -6944,7 +7787,7 @@ async function extract(options) {
|
|
|
6944
7787
|
maxProperties,
|
|
6945
7788
|
onTruncation,
|
|
6946
7789
|
shouldExpandExternal: createExternalExpansionPredicate({
|
|
6947
|
-
followExternal
|
|
7790
|
+
followExternal,
|
|
6948
7791
|
workspacePackages: result.workspacePackages ?? new Map
|
|
6949
7792
|
}),
|
|
6950
7793
|
workspacePackages: result.workspacePackages ?? new Map
|
|
@@ -6976,9 +7819,9 @@ async function extract(options) {
|
|
|
6976
7819
|
break;
|
|
6977
7820
|
}
|
|
6978
7821
|
}
|
|
6979
|
-
if (
|
|
7822
|
+
if (ts19.isExportSpecifier(decl)) {
|
|
6980
7823
|
const exportDecl = decl.parent?.parent;
|
|
6981
|
-
if (exportDecl &&
|
|
7824
|
+
if (exportDecl && ts19.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
|
|
6982
7825
|
const moduleText = exportDecl.moduleSpecifier.getText().slice(1, -1);
|
|
6983
7826
|
if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
|
|
6984
7827
|
externalPackage = moduleText;
|
|
@@ -7042,12 +7885,12 @@ async function extract(options) {
|
|
|
7042
7885
|
const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
|
|
7043
7886
|
const meta = await getPackageMeta(entryFile, baseDir);
|
|
7044
7887
|
expandReachableTypes(filteredSymbols, ctx, {
|
|
7045
|
-
followExternal
|
|
7888
|
+
followExternal,
|
|
7046
7889
|
workspacePackages: result.workspacePackages ?? new Map,
|
|
7047
7890
|
entryFile
|
|
7048
7891
|
});
|
|
7049
7892
|
{
|
|
7050
|
-
const symFlags =
|
|
7893
|
+
const symFlags = ts19.SymbolFlags.Type | ts19.SymbolFlags.Interface | ts19.SymbolFlags.Class;
|
|
7051
7894
|
const maxPasses = 5;
|
|
7052
7895
|
for (let pass = 0;pass < maxPasses; pass++) {
|
|
7053
7896
|
const allRefs = new Map;
|
|
@@ -7082,7 +7925,7 @@ async function extract(options) {
|
|
|
7082
7925
|
}
|
|
7083
7926
|
}
|
|
7084
7927
|
const types = ctx.typeRegistry.getAll();
|
|
7085
|
-
const projectBaseDir = baseDir ??
|
|
7928
|
+
const projectBaseDir = baseDir ?? path10.dirname(entryFile);
|
|
7086
7929
|
const definedTypes = new Set(types.map((t) => t.id));
|
|
7087
7930
|
const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
|
|
7088
7931
|
for (const forgotten of forgottenExports) {
|
|
@@ -7115,7 +7958,7 @@ async function extract(options) {
|
|
|
7115
7958
|
}
|
|
7116
7959
|
let runtimeMetadata;
|
|
7117
7960
|
if (options.schemaExtraction === "hybrid") {
|
|
7118
|
-
const projectBaseDir2 = baseDir ||
|
|
7961
|
+
const projectBaseDir2 = baseDir || path10.dirname(entryFile);
|
|
7119
7962
|
const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
|
|
7120
7963
|
target: "draft-2020-12",
|
|
7121
7964
|
timeout: 15000
|
|
@@ -7160,6 +8003,7 @@ async function extract(options) {
|
|
|
7160
8003
|
generator: "@openpkg-ts/sdk",
|
|
7161
8004
|
timestamp: new Date().toISOString(),
|
|
7162
8005
|
mode: isDtsSource ? "declaration-only" : "source",
|
|
8006
|
+
...generationEntry(entryFile, options.entryPointSource),
|
|
7163
8007
|
...options.schemaExtraction === "hybrid" ? { schemaExtraction: "hybrid" } : {},
|
|
7164
8008
|
...isDtsSource && {
|
|
7165
8009
|
limitations: ["No JSDoc descriptions", "No @example tags", "No @param descriptions"]
|
|
@@ -7180,6 +8024,9 @@ async function extract(options) {
|
|
|
7180
8024
|
suggestion: "Check serialization errors for these exports"
|
|
7181
8025
|
});
|
|
7182
8026
|
}
|
|
8027
|
+
if (evaluate) {
|
|
8028
|
+
await calibrateDiagnostics(diagnostics, evaluate);
|
|
8029
|
+
}
|
|
7183
8030
|
return {
|
|
7184
8031
|
spec,
|
|
7185
8032
|
diagnostics,
|
|
@@ -7194,21 +8041,21 @@ async function extract(options) {
|
|
|
7194
8041
|
}
|
|
7195
8042
|
function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTypeOnly = false) {
|
|
7196
8043
|
let result = null;
|
|
7197
|
-
if (
|
|
8044
|
+
if (ts19.isFunctionDeclaration(declaration)) {
|
|
7198
8045
|
result = serializeFunctionExport(declaration, ctx);
|
|
7199
|
-
} else if (
|
|
8046
|
+
} else if (ts19.isClassDeclaration(declaration)) {
|
|
7200
8047
|
result = serializeClass(declaration, ctx);
|
|
7201
|
-
} else if (
|
|
8048
|
+
} else if (ts19.isInterfaceDeclaration(declaration)) {
|
|
7202
8049
|
result = serializeInterface(declaration, ctx);
|
|
7203
|
-
} else if (
|
|
8050
|
+
} else if (ts19.isTypeAliasDeclaration(declaration)) {
|
|
7204
8051
|
result = serializeTypeAlias(declaration, ctx);
|
|
7205
|
-
} else if (
|
|
8052
|
+
} else if (ts19.isEnumDeclaration(declaration)) {
|
|
7206
8053
|
result = serializeEnum(declaration, ctx);
|
|
7207
|
-
} else if (
|
|
8054
|
+
} else if (ts19.isVariableDeclaration(declaration)) {
|
|
7208
8055
|
const varStatement = declaration.parent?.parent;
|
|
7209
|
-
if (varStatement &&
|
|
7210
|
-
if (declaration.initializer && (
|
|
7211
|
-
const varName =
|
|
8056
|
+
if (varStatement && ts19.isVariableStatement(varStatement)) {
|
|
8057
|
+
if (declaration.initializer && (ts19.isArrowFunction(declaration.initializer) || ts19.isFunctionExpression(declaration.initializer))) {
|
|
8058
|
+
const varName = ts19.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
|
|
7212
8059
|
result = serializeFunctionExport(declaration.initializer, ctx, varName);
|
|
7213
8060
|
} else {
|
|
7214
8061
|
result = serializeVariable(declaration, varStatement, ctx);
|
|
@@ -7220,7 +8067,7 @@ function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTyp
|
|
|
7220
8067
|
}
|
|
7221
8068
|
}
|
|
7222
8069
|
}
|
|
7223
|
-
} else if (
|
|
8070
|
+
} else if (ts19.isNamespaceExport(declaration) || ts19.isModuleDeclaration(declaration) || ts19.isNamespaceImport(declaration) || ts19.isSourceFile(declaration)) {
|
|
7224
8071
|
try {
|
|
7225
8072
|
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
7226
8073
|
} catch {
|
|
@@ -7257,7 +8104,7 @@ function serializeNamespaceExport(symbol, exportName, ctx) {
|
|
|
7257
8104
|
const members = [];
|
|
7258
8105
|
const checker = ctx.program.getTypeChecker();
|
|
7259
8106
|
let targetSymbol = symbol;
|
|
7260
|
-
if (symbol.flags &
|
|
8107
|
+
if (symbol.flags & ts19.SymbolFlags.Alias) {
|
|
7261
8108
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
7262
8109
|
if (aliased && aliased !== symbol) {
|
|
7263
8110
|
targetSymbol = aliased;
|
|
@@ -7285,31 +8132,31 @@ function serializeNamespaceExport(symbol, exportName, ctx) {
|
|
|
7285
8132
|
function serializeNamespaceMember(symbol, memberName, ctx) {
|
|
7286
8133
|
const checker = ctx.program.getTypeChecker();
|
|
7287
8134
|
let targetSymbol = symbol;
|
|
7288
|
-
if (symbol.flags &
|
|
8135
|
+
if (symbol.flags & ts19.SymbolFlags.Alias) {
|
|
7289
8136
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
7290
8137
|
if (aliased && aliased !== symbol) {
|
|
7291
8138
|
targetSymbol = aliased;
|
|
7292
8139
|
}
|
|
7293
8140
|
}
|
|
7294
8141
|
const declarations = targetSymbol.declarations ?? [];
|
|
7295
|
-
const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !==
|
|
8142
|
+
const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts19.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
7296
8143
|
if (!declaration)
|
|
7297
8144
|
return null;
|
|
7298
8145
|
const type = checker.getTypeAtLocation(declaration);
|
|
7299
8146
|
const callSignatures = type.getCallSignatures();
|
|
7300
8147
|
const { deprecated } = isSymbolDeprecated(targetSymbol);
|
|
7301
8148
|
let kind = "variable";
|
|
7302
|
-
if (
|
|
8149
|
+
if (ts19.isFunctionDeclaration(declaration) || ts19.isFunctionExpression(declaration)) {
|
|
7303
8150
|
kind = "function";
|
|
7304
|
-
} else if (
|
|
8151
|
+
} else if (ts19.isClassDeclaration(declaration)) {
|
|
7305
8152
|
kind = "class";
|
|
7306
|
-
} else if (
|
|
8153
|
+
} else if (ts19.isInterfaceDeclaration(declaration)) {
|
|
7307
8154
|
kind = "interface";
|
|
7308
|
-
} else if (
|
|
8155
|
+
} else if (ts19.isTypeAliasDeclaration(declaration)) {
|
|
7309
8156
|
kind = "type";
|
|
7310
|
-
} else if (
|
|
8157
|
+
} else if (ts19.isEnumDeclaration(declaration)) {
|
|
7311
8158
|
kind = "enum";
|
|
7312
|
-
} else if (
|
|
8159
|
+
} else if (ts19.isVariableDeclaration(declaration)) {
|
|
7313
8160
|
if (callSignatures.length > 0) {
|
|
7314
8161
|
kind = "function";
|
|
7315
8162
|
}
|
|
@@ -7340,18 +8187,18 @@ function serializeNamespaceMember(symbol, memberName, ctx) {
|
|
|
7340
8187
|
function flattenJSDocComment(comment) {
|
|
7341
8188
|
if (comment === undefined)
|
|
7342
8189
|
return "";
|
|
7343
|
-
return typeof comment === "string" ? comment :
|
|
8190
|
+
return typeof comment === "string" ? comment : ts19.getTextOfJSDocComment(comment) ?? "";
|
|
7344
8191
|
}
|
|
7345
8192
|
function getJSDocFromExportSymbol(symbol) {
|
|
7346
8193
|
const tags = [];
|
|
7347
8194
|
const examples = [];
|
|
7348
8195
|
const decl = symbol.declarations?.[0];
|
|
7349
8196
|
if (decl) {
|
|
7350
|
-
const exportDecl =
|
|
7351
|
-
if (exportDecl &&
|
|
7352
|
-
const jsDocs =
|
|
8197
|
+
const exportDecl = ts19.isNamespaceExport(decl) ? decl.parent : decl;
|
|
8198
|
+
if (exportDecl && ts19.isExportDeclaration(exportDecl)) {
|
|
8199
|
+
const jsDocs = ts19.getJSDocCommentsAndTags(exportDecl);
|
|
7353
8200
|
for (const doc of jsDocs) {
|
|
7354
|
-
if (
|
|
8201
|
+
if (ts19.isJSDoc(doc) && doc.comment) {
|
|
7355
8202
|
const commentText = flattenJSDocComment(doc.comment);
|
|
7356
8203
|
if (commentText) {
|
|
7357
8204
|
return {
|
|
@@ -7410,16 +8257,24 @@ function withExportName(entry, exportName) {
|
|
|
7410
8257
|
name: exportName
|
|
7411
8258
|
};
|
|
7412
8259
|
}
|
|
7413
|
-
function
|
|
8260
|
+
function generationEntry(entryFile, source) {
|
|
8261
|
+
const rel = path10.relative(process.cwd(), entryFile).split(path10.sep).join("/");
|
|
8262
|
+
return {
|
|
8263
|
+
entryPoint: rel || entryFile,
|
|
8264
|
+
entryPointSource: source ?? "explicit"
|
|
8265
|
+
};
|
|
8266
|
+
}
|
|
8267
|
+
function createEmptySpec(entryFile, includeSchema, isDtsSource, entryPointSource) {
|
|
7414
8268
|
return {
|
|
7415
8269
|
...includeSchema ? { $schema: SCHEMA_URL } : {},
|
|
7416
8270
|
openpkg: SCHEMA_VERSION,
|
|
7417
|
-
meta: { name:
|
|
8271
|
+
meta: { name: path10.basename(entryFile, path10.extname(entryFile)) },
|
|
7418
8272
|
exports: [],
|
|
7419
8273
|
generation: {
|
|
7420
8274
|
generator: "@openpkg-ts/sdk",
|
|
7421
8275
|
timestamp: new Date().toISOString(),
|
|
7422
8276
|
mode: isDtsSource ? "declaration-only" : "source",
|
|
8277
|
+
...generationEntry(entryFile, entryPointSource),
|
|
7423
8278
|
...isDtsSource && {
|
|
7424
8279
|
limitations: ["No JSDoc descriptions", "No @example tags", "No @param descriptions"]
|
|
7425
8280
|
}
|
|
@@ -7430,7 +8285,7 @@ function findTypeInProgram(name, checker, program, sourceFile, symFlags) {
|
|
|
7430
8285
|
const localSym = checker.resolveName(name, sourceFile, symFlags, false);
|
|
7431
8286
|
if (localSym)
|
|
7432
8287
|
return checker.getDeclaredTypeOfSymbol(localSym);
|
|
7433
|
-
const entryDir =
|
|
8288
|
+
const entryDir = path10.dirname(sourceFile.fileName);
|
|
7434
8289
|
for (const sf of program.getSourceFiles()) {
|
|
7435
8290
|
const fn = sf.fileName;
|
|
7436
8291
|
if (fn.includes("/typescript/lib/lib.") || fn.includes("\\typescript\\lib\\lib."))
|
|
@@ -7446,22 +8301,22 @@ function findTypeInProgram(name, checker, program, sourceFile, symFlags) {
|
|
|
7446
8301
|
return;
|
|
7447
8302
|
}
|
|
7448
8303
|
async function getPackageMeta(entryFile, baseDir) {
|
|
7449
|
-
let dir = baseDir ??
|
|
7450
|
-
while (dir !==
|
|
7451
|
-
const pkgPath =
|
|
8304
|
+
let dir = baseDir ?? path10.dirname(entryFile);
|
|
8305
|
+
while (dir !== path10.dirname(dir)) {
|
|
8306
|
+
const pkgPath = path10.join(dir, "package.json");
|
|
7452
8307
|
try {
|
|
7453
|
-
if (
|
|
7454
|
-
const pkg = JSON.parse(
|
|
8308
|
+
if (fs7.existsSync(pkgPath)) {
|
|
8309
|
+
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
7455
8310
|
return {
|
|
7456
|
-
name: pkg.name ??
|
|
8311
|
+
name: pkg.name ?? path10.basename(dir),
|
|
7457
8312
|
version: pkg.version,
|
|
7458
8313
|
description: pkg.description
|
|
7459
8314
|
};
|
|
7460
8315
|
}
|
|
7461
8316
|
} catch {}
|
|
7462
|
-
dir =
|
|
8317
|
+
dir = path10.dirname(dir);
|
|
7463
8318
|
}
|
|
7464
|
-
return { name:
|
|
8319
|
+
return { name: path10.basename(baseDir ?? path10.dirname(entryFile)) };
|
|
7465
8320
|
}
|
|
7466
8321
|
|
|
7467
8322
|
// src/primitives/spec.ts
|
|
@@ -7946,12 +8801,12 @@ function toToolSchema(exp, spec, options) {
|
|
|
7946
8801
|
};
|
|
7947
8802
|
}
|
|
7948
8803
|
// src/types/utils.ts
|
|
7949
|
-
import
|
|
8804
|
+
import ts20 from "typescript";
|
|
7950
8805
|
function isExported(node) {
|
|
7951
8806
|
const modifiers = node.modifiers;
|
|
7952
8807
|
if (!modifiers)
|
|
7953
8808
|
return false;
|
|
7954
|
-
return modifiers.some((m) => m.kind ===
|
|
8809
|
+
return modifiers.some((m) => m.kind === ts20.SyntaxKind.ExportKeyword);
|
|
7955
8810
|
}
|
|
7956
8811
|
function getNodeName(node) {
|
|
7957
8812
|
if ("name" in node && node.name) {
|
|
@@ -7995,6 +8850,7 @@ export {
|
|
|
7995
8850
|
schemasAreEqual,
|
|
7996
8851
|
schemaIsAny,
|
|
7997
8852
|
resolveTypeRef,
|
|
8853
|
+
resolveTarget,
|
|
7998
8854
|
resolveExportTarget2 as resolveExportTarget,
|
|
7999
8855
|
resolveCompiledPath,
|
|
8000
8856
|
renderTypeText,
|
|
@@ -8002,6 +8858,8 @@ export {
|
|
|
8002
8858
|
registerAdapter,
|
|
8003
8859
|
recommendSemverBump,
|
|
8004
8860
|
query,
|
|
8861
|
+
pickEntry,
|
|
8862
|
+
parseGithubRepo,
|
|
8005
8863
|
normalizeType,
|
|
8006
8864
|
normalizeSchema,
|
|
8007
8865
|
normalizeMembers,
|
|
@@ -8015,12 +8873,14 @@ export {
|
|
|
8015
8873
|
isSymbolDeprecated,
|
|
8016
8874
|
isStandardJSONSchema,
|
|
8017
8875
|
isSchemaType,
|
|
8876
|
+
isRemoteInput,
|
|
8018
8877
|
isReadonlyPropertySymbol,
|
|
8019
8878
|
isPureRefSchema,
|
|
8020
8879
|
isProperty,
|
|
8021
8880
|
isPrimitiveName,
|
|
8022
8881
|
isMethod,
|
|
8023
8882
|
isExported,
|
|
8883
|
+
isEntryFilePath,
|
|
8024
8884
|
isBuiltinSymbol,
|
|
8025
8885
|
isBuiltinGeneric,
|
|
8026
8886
|
isAnonymous,
|
|
@@ -8048,6 +8908,7 @@ export {
|
|
|
8048
8908
|
formatMappedType,
|
|
8049
8909
|
formatConditionalType,
|
|
8050
8910
|
formatBadges,
|
|
8911
|
+
findWorkspaceRoot,
|
|
8051
8912
|
findMissingParamDocs,
|
|
8052
8913
|
findDiscriminatorProperty,
|
|
8053
8914
|
findAdapter,
|
|
@@ -8071,7 +8932,9 @@ export {
|
|
|
8071
8932
|
declaredTypeNode,
|
|
8072
8933
|
createProgram,
|
|
8073
8934
|
createDocs,
|
|
8935
|
+
cloneRemote,
|
|
8074
8936
|
categorizeBreakingChanges,
|
|
8937
|
+
catalogPackages,
|
|
8075
8938
|
calculateNextVersion,
|
|
8076
8939
|
bundleRefs,
|
|
8077
8940
|
buildSignatureString,
|
|
@@ -8088,6 +8951,8 @@ export {
|
|
|
8088
8951
|
PRIMITIVES,
|
|
8089
8952
|
NUMBER_PROTOTYPE_METHODS,
|
|
8090
8953
|
LATEST_VERSION,
|
|
8954
|
+
JEV_MODEL,
|
|
8955
|
+
JEV_CONFIDENCE,
|
|
8091
8956
|
CacheManager,
|
|
8092
8957
|
CONFIG_FILENAME,
|
|
8093
8958
|
BUILTIN_TYPE_SCHEMAS,
|