@alint-js/core 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +98 -79
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import lockfile from "proper-lockfile";
|
|
|
14
14
|
import { isNodeErrorCode } from "@alint-js/utils/node";
|
|
15
15
|
import { errorMessageFrom } from "@moeru/std/error";
|
|
16
16
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
17
|
+
import { setImmediate } from "node:timers/promises";
|
|
17
18
|
import { streamText } from "@xsai/stream-text";
|
|
18
19
|
//#region src/config/config-array.ts
|
|
19
20
|
const effectiveBasePathSymbol = Symbol("effectiveBasePath");
|
|
@@ -270,7 +271,7 @@ function mergeStopGateConfig(resolved, item) {
|
|
|
270
271
|
}
|
|
271
272
|
//#endregion
|
|
272
273
|
//#region package.json
|
|
273
|
-
var version = "0.7.
|
|
274
|
+
var version = "0.7.1";
|
|
274
275
|
//#endregion
|
|
275
276
|
//#region src/core/cache/types.ts
|
|
276
277
|
const CACHE_MAGIC = "ALINT_CACHE";
|
|
@@ -2363,88 +2364,14 @@ function projectExecution(runtime) {
|
|
|
2363
2364
|
//#endregion
|
|
2364
2365
|
//#region src/core/source/planner.ts
|
|
2365
2366
|
/**
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2368
|
-
* The returned outcome promise captures only cache ownership and hashes. This function does not
|
|
2369
|
-
* await rule execution, so its `SourceFile`, parser output, and rich targets become unreachable
|
|
2370
|
-
* when planning returns.
|
|
2371
|
-
*/
|
|
2372
|
-
async function planSource(input, options) {
|
|
2373
|
-
if (options.signal?.aborted) return { outcomes: Promise.resolve([]) };
|
|
2374
|
-
let file;
|
|
2375
|
-
try {
|
|
2376
|
-
file = await options.src.readFile(input.path);
|
|
2377
|
-
} catch (error) {
|
|
2378
|
-
reportFilePlanningComplete(input, 0, options);
|
|
2379
|
-
return {
|
|
2380
|
-
failure: fileFailure(input, "read", failureMessage(error, "Failed to read source file.")),
|
|
2381
|
-
outcomes: Promise.resolve([])
|
|
2382
|
-
};
|
|
2383
|
-
}
|
|
2384
|
-
if (options.signal?.aborted) return { outcomes: Promise.resolve([]) };
|
|
2385
|
-
let targets;
|
|
2386
|
-
try {
|
|
2387
|
-
targets = await input.language.extract(file, {
|
|
2388
|
-
cwd: options.cwd,
|
|
2389
|
-
languageOptions: input.languageOptions,
|
|
2390
|
-
src: options.src
|
|
2391
|
-
});
|
|
2392
|
-
} catch (error) {
|
|
2393
|
-
reportFilePlanningComplete(input, 0, options);
|
|
2394
|
-
return {
|
|
2395
|
-
failure: fileFailure(input, "extract", failureMessage(error, "Failed to extract source targets.")),
|
|
2396
|
-
outcomes: Promise.resolve([])
|
|
2397
|
-
};
|
|
2398
|
-
}
|
|
2399
|
-
const { contentHash } = file;
|
|
2400
|
-
let cacheOwner;
|
|
2401
|
-
let jobs;
|
|
2402
|
-
let project;
|
|
2403
|
-
try {
|
|
2404
|
-
project = options.projectSnapshots === false ? void 0 : createProjectSnapshot(input, file.language, file.path, contentHash, targets);
|
|
2405
|
-
cacheOwner = options.cacheStore.beginOwner({
|
|
2406
|
-
kind: "file",
|
|
2407
|
-
path: file.path
|
|
2408
|
-
}, { contentHash });
|
|
2409
|
-
const baseFile = {
|
|
2410
|
-
contentHash,
|
|
2411
|
-
language: file.language,
|
|
2412
|
-
path: file.path
|
|
2413
|
-
};
|
|
2414
|
-
jobs = createSourceJobs(input, createExecutionTargets(input, targets, baseFile, options.ruleRuntimes, options.cwd, cacheOwner));
|
|
2415
|
-
} catch (error) {
|
|
2416
|
-
reportFilePlanningComplete(input, 0, options);
|
|
2417
|
-
return {
|
|
2418
|
-
failure: fileFailure(input, "extract", failureMessage(error, "Failed to plan source targets.")),
|
|
2419
|
-
outcomes: Promise.resolve([])
|
|
2420
|
-
};
|
|
2421
|
-
}
|
|
2422
|
-
if (options.signal?.aborted) {
|
|
2423
|
-
cacheOwner.commit({ mode: "merge" });
|
|
2424
|
-
return {
|
|
2425
|
-
outcomes: Promise.resolve([]),
|
|
2426
|
-
project
|
|
2427
|
-
};
|
|
2428
|
-
}
|
|
2429
|
-
const batch = options.scheduler.schedule(jobs);
|
|
2430
|
-
reportFilePlanningComplete(input, batch.jobsAdded, options);
|
|
2431
|
-
return {
|
|
2432
|
-
outcomes: batch.outcomes.then(async (settled) => {
|
|
2433
|
-
cacheOwner.commit(options.signal?.aborted ? { mode: "merge" } : void 0);
|
|
2434
|
-
await options.cacheStore.flush();
|
|
2435
|
-
return settled;
|
|
2436
|
-
}),
|
|
2437
|
-
project
|
|
2438
|
-
};
|
|
2439
|
-
}
|
|
2440
|
-
/**
|
|
2441
|
-
* Starts every input plan independently and preserves input-ordered results.
|
|
2367
|
+
* Starts every input read independently, then batches CPU-heavy extraction and job admission.
|
|
2442
2368
|
*/
|
|
2443
2369
|
async function planSources(inputs, options) {
|
|
2444
|
-
|
|
2370
|
+
const waitForPlanning = createPlanningAdmission();
|
|
2371
|
+
return Promise.all(inputs.map((input) => planSourceWithAdmission(input, {
|
|
2445
2372
|
...options,
|
|
2446
2373
|
ruleRuntimes: options.createRuleRuntimes(input)
|
|
2447
|
-
})));
|
|
2374
|
+
}, waitForPlanning)));
|
|
2448
2375
|
}
|
|
2449
2376
|
function createExecutionTargets(input, targets, file, runtimes, cwd, cacheOwner) {
|
|
2450
2377
|
const resolveIdentity = createTargetIdentityResolver(targets.map((target) => ({
|
|
@@ -2499,6 +2426,28 @@ function createExecutionTargets(input, targets, file, runtimes, cwd, cacheOwner)
|
|
|
2499
2426
|
};
|
|
2500
2427
|
});
|
|
2501
2428
|
}
|
|
2429
|
+
function createPlanningAdmission() {
|
|
2430
|
+
const batchSize = 32;
|
|
2431
|
+
let admitted = 0;
|
|
2432
|
+
let pendingYield;
|
|
2433
|
+
return async () => {
|
|
2434
|
+
let currentPendingYield = pendingYield;
|
|
2435
|
+
while (currentPendingYield) {
|
|
2436
|
+
await currentPendingYield;
|
|
2437
|
+
currentPendingYield = pendingYield;
|
|
2438
|
+
}
|
|
2439
|
+
admitted += 1;
|
|
2440
|
+
if (admitted < batchSize) return;
|
|
2441
|
+
admitted = 0;
|
|
2442
|
+
const currentYield = setImmediate();
|
|
2443
|
+
pendingYield = currentYield;
|
|
2444
|
+
try {
|
|
2445
|
+
await currentYield;
|
|
2446
|
+
} finally {
|
|
2447
|
+
if (pendingYield === currentYield) pendingYield = void 0;
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2502
2451
|
function createProjectSnapshot(input, language, path, contentHash, targets) {
|
|
2503
2452
|
return {
|
|
2504
2453
|
configHash: input.configHash,
|
|
@@ -2570,6 +2519,76 @@ function fileFailure(input, kind, message) {
|
|
|
2570
2519
|
message
|
|
2571
2520
|
};
|
|
2572
2521
|
}
|
|
2522
|
+
async function planSourceWithAdmission(input, options, waitForPlanning) {
|
|
2523
|
+
if (options.signal?.aborted) return { outcomes: Promise.resolve([]) };
|
|
2524
|
+
let file;
|
|
2525
|
+
try {
|
|
2526
|
+
file = await options.src.readFile(input.path);
|
|
2527
|
+
} catch (error) {
|
|
2528
|
+
reportFilePlanningComplete(input, 0, options);
|
|
2529
|
+
return {
|
|
2530
|
+
failure: fileFailure(input, "read", failureMessage(error, "Failed to read source file.")),
|
|
2531
|
+
outcomes: Promise.resolve([])
|
|
2532
|
+
};
|
|
2533
|
+
}
|
|
2534
|
+
if (options.signal?.aborted) return { outcomes: Promise.resolve([]) };
|
|
2535
|
+
await waitForPlanning?.();
|
|
2536
|
+
if (options.signal?.aborted) return { outcomes: Promise.resolve([]) };
|
|
2537
|
+
let targets;
|
|
2538
|
+
try {
|
|
2539
|
+
targets = await input.language.extract(file, {
|
|
2540
|
+
cwd: options.cwd,
|
|
2541
|
+
languageOptions: input.languageOptions,
|
|
2542
|
+
src: options.src
|
|
2543
|
+
});
|
|
2544
|
+
} catch (error) {
|
|
2545
|
+
reportFilePlanningComplete(input, 0, options);
|
|
2546
|
+
return {
|
|
2547
|
+
failure: fileFailure(input, "extract", failureMessage(error, "Failed to extract source targets.")),
|
|
2548
|
+
outcomes: Promise.resolve([])
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
const { contentHash } = file;
|
|
2552
|
+
let cacheOwner;
|
|
2553
|
+
let jobs;
|
|
2554
|
+
let project;
|
|
2555
|
+
try {
|
|
2556
|
+
project = options.projectSnapshots === false ? void 0 : createProjectSnapshot(input, file.language, file.path, contentHash, targets);
|
|
2557
|
+
cacheOwner = options.cacheStore.beginOwner({
|
|
2558
|
+
kind: "file",
|
|
2559
|
+
path: file.path
|
|
2560
|
+
}, { contentHash });
|
|
2561
|
+
const baseFile = {
|
|
2562
|
+
contentHash,
|
|
2563
|
+
language: file.language,
|
|
2564
|
+
path: file.path
|
|
2565
|
+
};
|
|
2566
|
+
jobs = createSourceJobs(input, createExecutionTargets(input, targets, baseFile, options.ruleRuntimes, options.cwd, cacheOwner));
|
|
2567
|
+
} catch (error) {
|
|
2568
|
+
reportFilePlanningComplete(input, 0, options);
|
|
2569
|
+
return {
|
|
2570
|
+
failure: fileFailure(input, "extract", failureMessage(error, "Failed to plan source targets.")),
|
|
2571
|
+
outcomes: Promise.resolve([])
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2574
|
+
if (options.signal?.aborted) {
|
|
2575
|
+
cacheOwner.commit({ mode: "merge" });
|
|
2576
|
+
return {
|
|
2577
|
+
outcomes: Promise.resolve([]),
|
|
2578
|
+
project
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2581
|
+
const batch = options.scheduler.schedule(jobs);
|
|
2582
|
+
reportFilePlanningComplete(input, batch.jobsAdded, options);
|
|
2583
|
+
return {
|
|
2584
|
+
outcomes: batch.outcomes.then(async (settled) => {
|
|
2585
|
+
cacheOwner.commit(options.signal?.aborted ? { mode: "merge" } : void 0);
|
|
2586
|
+
await options.cacheStore.flush();
|
|
2587
|
+
return settled;
|
|
2588
|
+
}),
|
|
2589
|
+
project
|
|
2590
|
+
};
|
|
2591
|
+
}
|
|
2573
2592
|
function reportFilePlanningComplete(input, jobsAdded, options) {
|
|
2574
2593
|
try {
|
|
2575
2594
|
const progress = options.scheduler.completeFilePlanning();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alint-js/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"description": "Public rule and plugin SDK and run engine for alint",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"pathe": "^2.0.3",
|
|
57
57
|
"proper-lockfile": "4.1.2",
|
|
58
58
|
"valibot": "^1.4.2",
|
|
59
|
-
"@alint-js/utils": "0.7.
|
|
59
|
+
"@alint-js/utils": "0.7.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/proper-lockfile": "4.1.4",
|