@openpkg-ts/extract 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/tspec.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
detectTsRuntime,
|
|
4
4
|
extract,
|
|
5
5
|
resolveCompiledPath
|
|
6
|
-
} from "../shared/chunk-
|
|
6
|
+
} from "../shared/chunk-v9c97d62.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/spec.ts
|
|
9
9
|
import * as fs from "node:fs";
|
|
@@ -412,7 +412,7 @@ function summary(options) {
|
|
|
412
412
|
}
|
|
413
413
|
// src/cli/spec.ts
|
|
414
414
|
function createProgram() {
|
|
415
|
-
const program = new Command("tspec").description("Extract TypeScript package API to OpenPkg spec").argument("[entry]", "Entry point file").option("-o, --output <file>", "Output file", "openpkg.json").option("--max-depth <n>", "Max type depth (default: 4)").option("--skip-resolve", "Skip external type resolution").option("--runtime", "Enable Standard Schema runtime extraction").option("--only <exports>", "Only extract these exports (comma-separated, supports * wildcards)").option("--ignore <exports>", "Ignore these exports (comma-separated, supports * wildcards)").option("-v, --verbose", "Show detailed output").action(async (entry, options) => {
|
|
415
|
+
const program = new Command("tspec").description("Extract TypeScript package API to OpenPkg spec").argument("[entry]", "Entry point file").option("-o, --output <file>", "Output file", "openpkg.json").option("--max-depth <n>", "Max type depth (default: 4)").option("--skip-resolve", "Skip external type resolution").option("--runtime", "Enable Standard Schema runtime extraction").option("--only <exports>", "Only extract these exports (comma-separated, supports * wildcards)").option("--ignore <exports>", "Ignore these exports (comma-separated, supports * wildcards)").option("-v, --verbose", "Show detailed output").option("--verify", "Enable export count verification mode (exit 1 on failures)").action(async (entry, options) => {
|
|
416
416
|
let entryFile;
|
|
417
417
|
let fromDts = false;
|
|
418
418
|
if (entry) {
|
|
@@ -499,7 +499,34 @@ Extraction completed in declaration-only mode:`);
|
|
|
499
499
|
if (result.runtimeSchemas) {
|
|
500
500
|
sum.addKeyValue("Runtime Schemas", result.runtimeSchemas.merged);
|
|
501
501
|
}
|
|
502
|
+
if (result.verification) {
|
|
503
|
+
const v = result.verification;
|
|
504
|
+
sum.addKeyValue("Discovered", v.discovered);
|
|
505
|
+
sum.addKeyValue("Extracted", v.extracted);
|
|
506
|
+
if (v.failed > 0) {
|
|
507
|
+
sum.addWithThreshold("Failed", v.failed, { value: 0, operator: "<=" });
|
|
508
|
+
}
|
|
509
|
+
}
|
|
502
510
|
sum.print();
|
|
511
|
+
if (result.verification?.failed) {
|
|
512
|
+
console.log(`
|
|
513
|
+
Failed exports:`);
|
|
514
|
+
for (const f of result.verification.details.failed) {
|
|
515
|
+
console.log(` - ${f.name}: ${f.error}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (options.verbose && result.verification?.details.skipped.length) {
|
|
519
|
+
console.log(`
|
|
520
|
+
Skipped exports:`);
|
|
521
|
+
for (const s of result.verification.details.skipped) {
|
|
522
|
+
console.log(` - ${s.name}: ${s.reason}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (options.verify && result.verification?.failed) {
|
|
526
|
+
const v = result.verification;
|
|
527
|
+
spin.fail(`Expected ${v.discovered} exports, got ${v.extracted}`);
|
|
528
|
+
process.exit(1);
|
|
529
|
+
}
|
|
503
530
|
});
|
|
504
531
|
return program;
|
|
505
532
|
}
|
|
@@ -3142,6 +3142,31 @@ function computeDegradedStats(exports) {
|
|
|
3142
3142
|
}
|
|
3143
3143
|
return { exportsWithoutDescription, paramsWithoutDocs, missingExamples };
|
|
3144
3144
|
}
|
|
3145
|
+
function buildVerificationSummary(discoveredCount, extractedCount, tracker) {
|
|
3146
|
+
const skippedDetails = [];
|
|
3147
|
+
const failedDetails = [];
|
|
3148
|
+
for (const entry of tracker.values()) {
|
|
3149
|
+
if (entry.status === "skipped" && entry.skipReason) {
|
|
3150
|
+
skippedDetails.push({ name: entry.name, reason: entry.skipReason });
|
|
3151
|
+
} else if (entry.status === "failed" && entry.error) {
|
|
3152
|
+
failedDetails.push({ name: entry.name, error: entry.error });
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
const skipped = skippedDetails.length;
|
|
3156
|
+
const failed = failedDetails.length;
|
|
3157
|
+
const delta = discoveredCount - extractedCount - skipped;
|
|
3158
|
+
return {
|
|
3159
|
+
discovered: discoveredCount,
|
|
3160
|
+
extracted: extractedCount,
|
|
3161
|
+
skipped,
|
|
3162
|
+
failed,
|
|
3163
|
+
delta,
|
|
3164
|
+
details: {
|
|
3165
|
+
skipped: skippedDetails,
|
|
3166
|
+
failed: failedDetails
|
|
3167
|
+
}
|
|
3168
|
+
};
|
|
3169
|
+
}
|
|
3145
3170
|
var BUILTIN_TYPES2 = new Set([
|
|
3146
3171
|
"Array",
|
|
3147
3172
|
"ArrayBuffer",
|
|
@@ -3263,6 +3288,17 @@ async function extract(options) {
|
|
|
3263
3288
|
for (const symbol of exportedSymbols) {
|
|
3264
3289
|
exportedIds.add(symbol.getName());
|
|
3265
3290
|
}
|
|
3291
|
+
const exportTracker = new Map;
|
|
3292
|
+
for (const symbol of exportedSymbols) {
|
|
3293
|
+
const name = symbol.getName();
|
|
3294
|
+
const included = shouldIncludeExport(name, only, ignore);
|
|
3295
|
+
exportTracker.set(name, {
|
|
3296
|
+
name,
|
|
3297
|
+
discovered: true,
|
|
3298
|
+
status: included ? "pending" : "skipped",
|
|
3299
|
+
...included ? {} : { skipReason: "filtered" }
|
|
3300
|
+
});
|
|
3301
|
+
}
|
|
3266
3302
|
const ctx = createContext(program, sourceFile, {
|
|
3267
3303
|
maxTypeDepth,
|
|
3268
3304
|
maxExternalTypeDepth,
|
|
@@ -3274,24 +3310,39 @@ async function extract(options) {
|
|
|
3274
3310
|
for (let i = 0;i < filteredSymbols.length; i++) {
|
|
3275
3311
|
const symbol = filteredSymbols[i];
|
|
3276
3312
|
const exportName = symbol.getName();
|
|
3313
|
+
const tracker = exportTracker.get(exportName);
|
|
3277
3314
|
onProgress?.(i + 1, total, exportName);
|
|
3278
3315
|
if (i > 0 && i % YIELD_BATCH_SIZE === 0) {
|
|
3279
3316
|
await new Promise((r) => setImmediate(r));
|
|
3280
3317
|
}
|
|
3281
3318
|
try {
|
|
3282
3319
|
const { declaration, targetSymbol } = resolveExportTarget(symbol, typeChecker);
|
|
3283
|
-
if (!declaration)
|
|
3320
|
+
if (!declaration) {
|
|
3321
|
+
tracker.status = "skipped";
|
|
3322
|
+
tracker.skipReason = "no-declaration";
|
|
3284
3323
|
continue;
|
|
3324
|
+
}
|
|
3285
3325
|
const exp = serializeDeclaration(declaration, symbol, targetSymbol, exportName, ctx);
|
|
3286
|
-
if (exp)
|
|
3326
|
+
if (exp) {
|
|
3287
3327
|
exports.push(exp);
|
|
3328
|
+
tracker.status = "success";
|
|
3329
|
+
tracker.kind = exp.kind;
|
|
3330
|
+
} else {
|
|
3331
|
+
tracker.status = "skipped";
|
|
3332
|
+
tracker.skipReason = "internal";
|
|
3333
|
+
}
|
|
3288
3334
|
} catch (err) {
|
|
3335
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3336
|
+
tracker.status = "failed";
|
|
3337
|
+
tracker.error = errorMsg;
|
|
3289
3338
|
diagnostics.push({
|
|
3290
|
-
message: `Failed to serialize ${exportName}: ${
|
|
3291
|
-
severity: "warning"
|
|
3339
|
+
message: `Failed to serialize '${exportName}': ${errorMsg}`,
|
|
3340
|
+
severity: "warning",
|
|
3341
|
+
code: "SERIALIZATION_FAILED"
|
|
3292
3342
|
});
|
|
3293
3343
|
}
|
|
3294
3344
|
}
|
|
3345
|
+
const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
|
|
3295
3346
|
const meta = await getPackageMeta(entryFile, baseDir);
|
|
3296
3347
|
const types = ctx.typeRegistry.getAll();
|
|
3297
3348
|
const projectBaseDir = baseDir ?? path3.dirname(entryFile);
|
|
@@ -3372,9 +3423,19 @@ async function extract(options) {
|
|
|
3372
3423
|
};
|
|
3373
3424
|
const internalForgotten = forgottenExports.filter((f) => !f.isExternal);
|
|
3374
3425
|
const degradedMode = isDtsSource ? { reason: "dts-source", stats: computeDegradedStats(normalizedExports) } : undefined;
|
|
3426
|
+
if (verification.failed > 0) {
|
|
3427
|
+
const failedNames = verification.details.failed.map((f) => f.name).join(", ");
|
|
3428
|
+
diagnostics.push({
|
|
3429
|
+
message: `Export verification: ${verification.failed} export(s) failed: ${failedNames}`,
|
|
3430
|
+
severity: "warning",
|
|
3431
|
+
code: "EXPORT_VERIFICATION_FAILED",
|
|
3432
|
+
suggestion: "Check serialization errors for these exports"
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3375
3435
|
return {
|
|
3376
3436
|
spec,
|
|
3377
3437
|
diagnostics,
|
|
3438
|
+
verification,
|
|
3378
3439
|
...internalForgotten.length > 0 ? { forgottenExports: internalForgotten } : {},
|
|
3379
3440
|
...runtimeMetadata ? { runtimeSchemas: runtimeMetadata } : {},
|
|
3380
3441
|
...degradedMode ? { degradedMode } : {}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -268,6 +268,8 @@ interface ExtractResult {
|
|
|
268
268
|
missingExamples: number;
|
|
269
269
|
};
|
|
270
270
|
};
|
|
271
|
+
/** Export verification comparing discovered vs extracted */
|
|
272
|
+
verification?: ExportVerification;
|
|
271
273
|
}
|
|
272
274
|
interface Diagnostic {
|
|
273
275
|
message: string;
|
|
@@ -295,6 +297,29 @@ interface ForgottenExport {
|
|
|
295
297
|
isExternal: boolean;
|
|
296
298
|
fix?: string;
|
|
297
299
|
}
|
|
300
|
+
/** Verification result comparing discovered vs extracted exports */
|
|
301
|
+
interface ExportVerification {
|
|
302
|
+
/** Total exports discovered by TypeScript */
|
|
303
|
+
discovered: number;
|
|
304
|
+
/** Exports successfully extracted */
|
|
305
|
+
extracted: number;
|
|
306
|
+
/** Exports skipped (filtered, no-declaration, internal) */
|
|
307
|
+
skipped: number;
|
|
308
|
+
/** Exports that failed during serialization */
|
|
309
|
+
failed: number;
|
|
310
|
+
/** Delta: discovered - extracted */
|
|
311
|
+
delta: number;
|
|
312
|
+
details: {
|
|
313
|
+
skipped: Array<{
|
|
314
|
+
name: string;
|
|
315
|
+
reason: "filtered" | "no-declaration" | "internal";
|
|
316
|
+
}>;
|
|
317
|
+
failed: Array<{
|
|
318
|
+
name: string;
|
|
319
|
+
error: string;
|
|
320
|
+
}>;
|
|
321
|
+
};
|
|
322
|
+
}
|
|
298
323
|
declare function extract(options: ExtractOptions): Promise<ExtractResult>;
|
|
299
324
|
import ts4 from "typescript";
|
|
300
325
|
interface ProgramOptions {
|
package/dist/src/index.js
CHANGED