@hublo/sentinel 1.2.0-alpha.16 → 1.2.0-alpha.18
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/sentinel.js +1 -1
- package/dist/{chunk-Q3ZLHHW2.js → chunk-MJ3S7LQT.js} +367 -298
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bin/sentinel.js
CHANGED
|
@@ -333,11 +333,19 @@ var BUILD_SCRIPT_NAME = "build";
|
|
|
333
333
|
var SENTINEL_BUILD_COMMAND = "sentinel --run --build --";
|
|
334
334
|
var DEV_SCRIPT_NAME = "serve";
|
|
335
335
|
var SENTINEL_DEV_COMMAND = "sentinel --run --dev";
|
|
336
|
-
|
|
336
|
+
var BUILD_OUTPUT_CANDIDATES = ["dist", ".output", "build"];
|
|
337
|
+
function buildTarget(options) {
|
|
338
|
+
const { moduleName: moduleName3, configFiles = BUILD_CONFIG_FILES, outputs } = options;
|
|
337
339
|
return {
|
|
338
340
|
[BUILD_SCRIPT_NAME]: {
|
|
341
|
+
executor: "nx:run-commands",
|
|
342
|
+
options: {
|
|
343
|
+
command: `pnpm --filter ${moduleName3} run ${BUILD_SCRIPT_NAME}`,
|
|
344
|
+
forwardAllArgs: false
|
|
345
|
+
},
|
|
339
346
|
cache: true,
|
|
340
|
-
inputs: ["default", "^default", ...configFiles.map((name) => `{projectRoot}/${name}`)]
|
|
347
|
+
inputs: ["default", "^default", ...configFiles.map((name) => `{projectRoot}/${name}`)],
|
|
348
|
+
outputs: [...outputs]
|
|
341
349
|
}
|
|
342
350
|
};
|
|
343
351
|
}
|
|
@@ -457,9 +465,9 @@ function binFromOwnInstall(packageName, binName) {
|
|
|
457
465
|
try {
|
|
458
466
|
const manifest = require2.resolve(`${packageName}/package.json`);
|
|
459
467
|
const bin = require2(manifest).bin;
|
|
460
|
-
const
|
|
461
|
-
if (!
|
|
462
|
-
const executable = join4(dirname2(manifest),
|
|
468
|
+
const relative5 = typeof bin === "string" ? bin : bin?.[binName];
|
|
469
|
+
if (!relative5) return void 0;
|
|
470
|
+
const executable = join4(dirname2(manifest), relative5);
|
|
463
471
|
return existsSync5(executable) ? executable : void 0;
|
|
464
472
|
} catch {
|
|
465
473
|
return void 0;
|
|
@@ -472,8 +480,8 @@ function binSearchPath(cwd) {
|
|
|
472
480
|
}
|
|
473
481
|
|
|
474
482
|
// src/roles/build/plan.ts
|
|
475
|
-
import { existsSync as
|
|
476
|
-
import { join as
|
|
483
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
484
|
+
import { join as join9 } from "path";
|
|
477
485
|
|
|
478
486
|
// src/core/config/existing-command.ts
|
|
479
487
|
import { readFileSync as readFileSync5 } from "fs";
|
|
@@ -518,6 +526,9 @@ function selfCommand(cwd, flags) {
|
|
|
518
526
|
if (!isSelfAdoption(cwd) || !own.bin) return void 0;
|
|
519
527
|
return `node ${own.bin.replace(/^\.\//, "")} ${flags}`;
|
|
520
528
|
}
|
|
529
|
+
function adoptedPackageName(cwd) {
|
|
530
|
+
return readProjectPackageJson(cwd).name ?? readNxProjectName(cwd) ?? basename2(cwd);
|
|
531
|
+
}
|
|
521
532
|
function manifestOperation(cwd, scripts) {
|
|
522
533
|
const own = readOwnPackage();
|
|
523
534
|
const value = {
|
|
@@ -530,7 +541,7 @@ function manifestOperation(cwd, scripts) {
|
|
|
530
541
|
return {
|
|
531
542
|
kind: "merge-json",
|
|
532
543
|
path: "package.json",
|
|
533
|
-
value: { name:
|
|
544
|
+
value: { name: adoptedPackageName(cwd), private: true, ...value }
|
|
534
545
|
};
|
|
535
546
|
}
|
|
536
547
|
|
|
@@ -656,7 +667,8 @@ function composeDevScript(existing, command) {
|
|
|
656
667
|
}
|
|
657
668
|
|
|
658
669
|
// src/roles/build/nest/adopt.ts
|
|
659
|
-
import {
|
|
670
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
671
|
+
import { join as join8 } from "path";
|
|
660
672
|
var NEST_CONFIG_FILE = "vite.config.mts";
|
|
661
673
|
function nestConfigSource(cwd, target) {
|
|
662
674
|
const hops = workspaceRootHops(cwd, target);
|
|
@@ -673,34 +685,18 @@ export default nestService({
|
|
|
673
685
|
})
|
|
674
686
|
`;
|
|
675
687
|
}
|
|
676
|
-
function
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
const
|
|
684
|
-
return {
|
|
685
|
-
executor: "nx:run-commands",
|
|
686
|
-
outputs: [`{workspaceRoot}/${target.outputPath}`],
|
|
687
|
-
options: {
|
|
688
|
-
cwd: moduleRoot,
|
|
689
|
-
command: "pnpm exec sentinel --run --build",
|
|
690
|
-
forwardAllArgs: false
|
|
691
|
-
}
|
|
692
|
-
};
|
|
688
|
+
function nestBuildOutputs(target) {
|
|
689
|
+
return [`{workspaceRoot}/${target.outputPath}`];
|
|
690
|
+
}
|
|
691
|
+
var OUT_DIR_IN_CONFIG = /^\s*outDir:\s*'([^']+)'/m;
|
|
692
|
+
function nestOutputsFromConfig(cwd) {
|
|
693
|
+
const configPath = join8(cwd, NEST_CONFIG_FILE);
|
|
694
|
+
if (!existsSync8(configPath)) return void 0;
|
|
695
|
+
const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync6(configPath, "utf8"))?.[1];
|
|
696
|
+
return outDir === void 0 ? void 0 : [`{workspaceRoot}/${outDir}`];
|
|
693
697
|
}
|
|
694
698
|
function nestAdoptionOperations(cwd, target) {
|
|
695
|
-
return [
|
|
696
|
-
{ kind: "write", path: NEST_CONFIG_FILE, contents: nestConfigSource(cwd, target) },
|
|
697
|
-
{ kind: "remove-json-keys", path: "project.json", keys: [["targets", "build"]] },
|
|
698
|
-
{
|
|
699
|
-
kind: "merge-json",
|
|
700
|
-
path: "project.json",
|
|
701
|
-
value: { targets: { build: nestBuildTarget(cwd, target) } }
|
|
702
|
-
}
|
|
703
|
-
];
|
|
699
|
+
return [{ kind: "write", path: NEST_CONFIG_FILE, contents: nestConfigSource(cwd, target) }];
|
|
704
700
|
}
|
|
705
701
|
|
|
706
702
|
// src/roles/build/requirements.ts
|
|
@@ -836,6 +832,9 @@ function rewriteBuildImports(source, fileName = "vite.config.ts") {
|
|
|
836
832
|
}
|
|
837
833
|
|
|
838
834
|
// src/roles/build/plan.ts
|
|
835
|
+
function candidateOutputs() {
|
|
836
|
+
return BUILD_OUTPUT_CANDIDATES.map((name) => `{projectRoot}/${name}`);
|
|
837
|
+
}
|
|
839
838
|
function ownedBuildDependencies(cwd) {
|
|
840
839
|
const manifest = readProjectPackageJson(cwd);
|
|
841
840
|
const keys = [];
|
|
@@ -937,7 +936,15 @@ function planReactApp(context, configFile) {
|
|
|
937
936
|
);
|
|
938
937
|
}
|
|
939
938
|
operations.push(manifestOperation(context.cwd, buildScripts(context.cwd)));
|
|
940
|
-
operations.push(
|
|
939
|
+
operations.push(
|
|
940
|
+
...nxTargetOperations({
|
|
941
|
+
cwd: context.cwd,
|
|
942
|
+
targets: buildTarget({
|
|
943
|
+
moduleName: adoptedPackageName(context.cwd),
|
|
944
|
+
outputs: candidateOutputs()
|
|
945
|
+
})
|
|
946
|
+
})
|
|
947
|
+
);
|
|
941
948
|
const owned = ownedBuildDependencies(context.cwd);
|
|
942
949
|
if (owned.length > 0) {
|
|
943
950
|
operations.push({ kind: "remove-json-keys", path: "package.json", keys: owned });
|
|
@@ -948,8 +955,22 @@ function planReactApp(context, configFile) {
|
|
|
948
955
|
return { operations, notes };
|
|
949
956
|
}
|
|
950
957
|
function planNestService(context, webpackTarget) {
|
|
958
|
+
const outputs = webpackTarget === void 0 ? nestOutputsFromConfig(context.cwd) : nestBuildOutputs(webpackTarget);
|
|
959
|
+
if (outputs === void 0) {
|
|
960
|
+
return {
|
|
961
|
+
operations: [],
|
|
962
|
+
blocked: `${NEST_CONFIG_FILE} does not declare an \`outDir\`, so sentinel cannot say where this service's build lands. Declaring an nx target without it would cache the build and restore nothing from that cache. Nothing was written.`
|
|
963
|
+
};
|
|
964
|
+
}
|
|
951
965
|
const metadata = [
|
|
952
|
-
...
|
|
966
|
+
...nxTargetOperations({
|
|
967
|
+
cwd: context.cwd,
|
|
968
|
+
targets: buildTarget({
|
|
969
|
+
moduleName: adoptedPackageName(context.cwd),
|
|
970
|
+
configFiles: [NEST_CONFIG_FILE],
|
|
971
|
+
outputs
|
|
972
|
+
})
|
|
973
|
+
}),
|
|
953
974
|
manifestOperation(context.cwd, { [BUILD_SCRIPT_NAME]: SENTINEL_BUILD_COMMAND })
|
|
954
975
|
];
|
|
955
976
|
if (webpackTarget === void 0) return { operations: metadata };
|
|
@@ -968,9 +989,9 @@ function planNestService(context, webpackTarget) {
|
|
|
968
989
|
};
|
|
969
990
|
}
|
|
970
991
|
function readConfigSource(cwd, configFile) {
|
|
971
|
-
if (!
|
|
992
|
+
if (!existsSync9(join9(cwd, configFile))) return "";
|
|
972
993
|
try {
|
|
973
|
-
return
|
|
994
|
+
return readFileSync7(join9(cwd, configFile), "utf8");
|
|
974
995
|
} catch {
|
|
975
996
|
return "";
|
|
976
997
|
}
|
|
@@ -1154,6 +1175,199 @@ var ViteDevAdapter = class extends ViteRoleAdapter {
|
|
|
1154
1175
|
}
|
|
1155
1176
|
};
|
|
1156
1177
|
|
|
1178
|
+
// src/roles/build/declared-outputs.ts
|
|
1179
|
+
import { existsSync as existsSync11, statSync } from "fs";
|
|
1180
|
+
import { join as join11 } from "path";
|
|
1181
|
+
|
|
1182
|
+
// src/core/workspace-prep.ts
|
|
1183
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync } from "fs";
|
|
1184
|
+
import { dirname as dirname3, join as join10, relative as relative2 } from "path";
|
|
1185
|
+
|
|
1186
|
+
// src/core/settings.ts
|
|
1187
|
+
var WORKSPACE_ROOT_MARKER = "nx.json";
|
|
1188
|
+
var DEFAULT_MAX_DIAGNOSTICS = 100;
|
|
1189
|
+
|
|
1190
|
+
// src/core/workspace-prep.ts
|
|
1191
|
+
var OVERRIDE_KEY = "i18next>typescript";
|
|
1192
|
+
var NATIVE_TS_ALIAS = "@typescript/native";
|
|
1193
|
+
var WORKSPACE_YAML = "pnpm-workspace.yaml";
|
|
1194
|
+
var RELEASE_AGE_KEY = "minimumReleaseAgeExclude";
|
|
1195
|
+
var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
|
|
1196
|
+
function findWorkspaceRoot(startDir) {
|
|
1197
|
+
let dir = startDir;
|
|
1198
|
+
for (; ; ) {
|
|
1199
|
+
if (existsSync10(join10(dir, WORKSPACE_ROOT_MARKER))) return dir;
|
|
1200
|
+
const parent = dirname3(dir);
|
|
1201
|
+
if (parent === dir) return void 0;
|
|
1202
|
+
dir = parent;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
function declaredNativeTs(pkg) {
|
|
1206
|
+
const spec = pkg.dependencies?.[NATIVE_TS_ALIAS] ?? pkg.devDependencies?.[NATIVE_TS_ALIAS];
|
|
1207
|
+
if (!spec) return void 0;
|
|
1208
|
+
const version = spec.slice(spec.lastIndexOf("@") + 1).replace(/^[\^~>=<\s]+/, "");
|
|
1209
|
+
return version || void 0;
|
|
1210
|
+
}
|
|
1211
|
+
function ensureI18nextSingleton(root, dryRun) {
|
|
1212
|
+
const pkgPath = join10(root, "package.json");
|
|
1213
|
+
if (!existsSync10(pkgPath)) return void 0;
|
|
1214
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
|
|
1215
|
+
const want = declaredNativeTs(pkg);
|
|
1216
|
+
if (!want) return void 0;
|
|
1217
|
+
const have = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
1218
|
+
if (have === want) return void 0;
|
|
1219
|
+
if (dryRun) return `would pin ${OVERRIDE_KEY} to ${want} (i18next singleton)`;
|
|
1220
|
+
pkg.pnpm ??= {};
|
|
1221
|
+
pkg.pnpm.overrides ??= {};
|
|
1222
|
+
pkg.pnpm.overrides[OVERRIDE_KEY] = want;
|
|
1223
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
1224
|
+
return `pinned ${OVERRIDE_KEY} to ${want} in package.json (i18next singleton)`;
|
|
1225
|
+
}
|
|
1226
|
+
function ensureReleaseAgeAllowList(root, dryRun) {
|
|
1227
|
+
const yamlPath = join10(root, WORKSPACE_YAML);
|
|
1228
|
+
if (!existsSync10(yamlPath)) return void 0;
|
|
1229
|
+
const own = readOwnPackage().name;
|
|
1230
|
+
const lines = readFileSync8(yamlPath, "utf8").split("\n");
|
|
1231
|
+
const keyIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === `${RELEASE_AGE_KEY}:`);
|
|
1232
|
+
if (keyIdx === -1) return void 0;
|
|
1233
|
+
let lastItemIdx = keyIdx;
|
|
1234
|
+
let indent = " ";
|
|
1235
|
+
for (let i = keyIdx + 1; i < lines.length; i++) {
|
|
1236
|
+
const match = lines[i]?.match(LIST_ITEM);
|
|
1237
|
+
if (!match) break;
|
|
1238
|
+
indent = match[1] ?? indent;
|
|
1239
|
+
lastItemIdx = i;
|
|
1240
|
+
if ((match[2] ?? "").replace(/^['"]|['"]$/g, "") === own) return void 0;
|
|
1241
|
+
}
|
|
1242
|
+
if (dryRun) return `would allow-list ${own} under ${RELEASE_AGE_KEY}`;
|
|
1243
|
+
lines.splice(lastItemIdx + 1, 0, `${indent}- '${own}'`);
|
|
1244
|
+
writeFileSync(yamlPath, lines.join("\n"));
|
|
1245
|
+
return `allow-listed ${own} under ${RELEASE_AGE_KEY} in ${WORKSPACE_YAML}`;
|
|
1246
|
+
}
|
|
1247
|
+
var PRETTIER_IGNORE = ".prettierignore";
|
|
1248
|
+
var EXCLUSION_HEADER = "# @hublo/sentinel: modules formatted by oxfmt, not by the root Prettier";
|
|
1249
|
+
var ROOT_PRETTIER_CONFIGS = [
|
|
1250
|
+
".prettierrc",
|
|
1251
|
+
".prettierrc.json",
|
|
1252
|
+
".prettierrc.json5",
|
|
1253
|
+
".prettierrc.yml",
|
|
1254
|
+
".prettierrc.yaml",
|
|
1255
|
+
".prettierrc.js",
|
|
1256
|
+
".prettierrc.cjs",
|
|
1257
|
+
".prettierrc.mjs",
|
|
1258
|
+
"prettier.config.js",
|
|
1259
|
+
"prettier.config.cjs",
|
|
1260
|
+
"prettier.config.mjs"
|
|
1261
|
+
];
|
|
1262
|
+
function ensureFormatterExclusion(root, moduleDir, dryRun) {
|
|
1263
|
+
const rel = relative2(root, moduleDir).replaceAll("\\", "/");
|
|
1264
|
+
if (rel === "" || rel.startsWith("..")) return void 0;
|
|
1265
|
+
const ignorePath = join10(root, PRETTIER_IGNORE);
|
|
1266
|
+
const hasPrettier = existsSync10(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync10(join10(root, name)));
|
|
1267
|
+
if (!hasPrettier) return void 0;
|
|
1268
|
+
const pattern = `/${rel}/`;
|
|
1269
|
+
const existing = existsSync10(ignorePath) ? readFileSync8(ignorePath, "utf8") : "";
|
|
1270
|
+
const lines = existing.split("\n");
|
|
1271
|
+
if (lines.some((line) => line.trim().replace(/\/$/, "") === pattern.replace(/\/$/, ""))) {
|
|
1272
|
+
return void 0;
|
|
1273
|
+
}
|
|
1274
|
+
if (dryRun) return `would exclude ${rel} from the root Prettier (${PRETTIER_IGNORE})`;
|
|
1275
|
+
const headerIdx = lines.findIndex((line) => line.trim() === EXCLUSION_HEADER);
|
|
1276
|
+
if (headerIdx === -1) {
|
|
1277
|
+
const prefix = existing.trim() === "" ? "" : `${existing.replace(/\n*$/, "")}
|
|
1278
|
+
|
|
1279
|
+
`;
|
|
1280
|
+
writeFileSync(ignorePath, `${prefix}${EXCLUSION_HEADER}
|
|
1281
|
+
${pattern}
|
|
1282
|
+
`);
|
|
1283
|
+
} else {
|
|
1284
|
+
let end = headerIdx + 1;
|
|
1285
|
+
while (end < lines.length && lines[end]?.trim().startsWith("/")) end += 1;
|
|
1286
|
+
const managed = [...lines.slice(headerIdx + 1, end), pattern].sort();
|
|
1287
|
+
writeFileSync(
|
|
1288
|
+
ignorePath,
|
|
1289
|
+
[...lines.slice(0, headerIdx + 1), ...managed, ...lines.slice(end)].join("\n")
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
return `excluded ${rel} from the root Prettier (${PRETTIER_IGNORE}): it formats itself now`;
|
|
1293
|
+
}
|
|
1294
|
+
function ensureWorkspacePrep(opts) {
|
|
1295
|
+
const dryRun = Boolean(opts.dryRun);
|
|
1296
|
+
return [
|
|
1297
|
+
ensureI18nextSingleton(opts.root, dryRun),
|
|
1298
|
+
ensureReleaseAgeAllowList(opts.root, dryRun),
|
|
1299
|
+
opts.formattedModule === void 0 ? void 0 : ensureFormatterExclusion(opts.root, opts.formattedModule, dryRun)
|
|
1300
|
+
].filter((message) => message !== void 0);
|
|
1301
|
+
}
|
|
1302
|
+
function inspectWorkspacePrep(root) {
|
|
1303
|
+
const entries = [];
|
|
1304
|
+
let pkg = {};
|
|
1305
|
+
const pkgPath = join10(root, "package.json");
|
|
1306
|
+
if (existsSync10(pkgPath)) {
|
|
1307
|
+
try {
|
|
1308
|
+
pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
|
|
1309
|
+
} catch {
|
|
1310
|
+
pkg = {};
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
const pinned = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
1314
|
+
if (pinned !== void 0) {
|
|
1315
|
+
const stillForks = declaredNativeTs(pkg);
|
|
1316
|
+
entries.push({
|
|
1317
|
+
rule: `package.json \u2192 pnpm.overrides.${OVERRIDE_KEY}`,
|
|
1318
|
+
reason: stillForks === void 0 ? `pinned to ${pinned}, but the root no longer declares ${NATIVE_TS_ALIAS}, so nothing forks any more. This override is now dead config and can be removed.` : `pinned to ${pinned}, matching the second TypeScript the root declares (${NATIVE_TS_ALIAS}). It re-resolves i18next for EVERY module that depends on it, not only adopted ones. It retires with the second TypeScript.`
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
const own = readOwnPackage().name;
|
|
1322
|
+
const yamlPath = join10(root, WORKSPACE_YAML);
|
|
1323
|
+
if (existsSync10(yamlPath)) {
|
|
1324
|
+
const yaml = readFileSync8(yamlPath, "utf8");
|
|
1325
|
+
const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
|
|
1326
|
+
if (listed) {
|
|
1327
|
+
const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
|
|
1328
|
+
entries.push({
|
|
1329
|
+
rule: `${WORKSPACE_YAML} \u2192 ${RELEASE_AGE_KEY}: ${own}`,
|
|
1330
|
+
reason: gated ? `${own} is exempt from this workspace's release-age gate, so a freshly published version installs instead of being held. That is a standing exemption from a supply-chain control: the exposure is one bump wide, since the version is pinned and the lockfile carries its integrity, so a re-publish of the same version does not pass. Retire it once a bump can simply wait out the window.` : `${own} is allow-listed, but this workspace no longer sets minimumReleaseAge, so there is no gate to be exempt from. This entry is now dead config and can be removed.`
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
return entries;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// src/roles/build/declared-outputs.ts
|
|
1338
|
+
function declaredBuildTarget(cwd) {
|
|
1339
|
+
return readProjectPackageJson(cwd).nx?.targets?.[BUILD_SCRIPT_NAME];
|
|
1340
|
+
}
|
|
1341
|
+
function resolveOutputToken(token, cwd) {
|
|
1342
|
+
if (token.startsWith("{projectRoot}/")) return join11(cwd, token.slice("{projectRoot}/".length));
|
|
1343
|
+
if (token.startsWith("{workspaceRoot}/")) {
|
|
1344
|
+
const root = findWorkspaceRoot(cwd);
|
|
1345
|
+
return root === void 0 ? void 0 : join11(root, token.slice("{workspaceRoot}/".length));
|
|
1346
|
+
}
|
|
1347
|
+
return join11(cwd, token);
|
|
1348
|
+
}
|
|
1349
|
+
function writtenSince(path, startedAt) {
|
|
1350
|
+
if (!existsSync11(path)) return false;
|
|
1351
|
+
try {
|
|
1352
|
+
return statSync(path).mtimeMs >= startedAt;
|
|
1353
|
+
} catch {
|
|
1354
|
+
return true;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
function outputsProblem(cwd, startedAt) {
|
|
1358
|
+
const target = declaredBuildTarget(cwd);
|
|
1359
|
+
if (target === void 0) return void 0;
|
|
1360
|
+
const declared = target.outputs ?? [];
|
|
1361
|
+
if (declared.length === 0) {
|
|
1362
|
+
if (target.cache !== true) return void 0;
|
|
1363
|
+
return `this module's nx build target sets \`cache: true\` and declares no \`outputs\`, so nx will cache this build and restore nothing from it: the next cache hit reports success and leaves no build on disk. Add the directory this build writes to under \`nx.targets.${BUILD_SCRIPT_NAME}.outputs\` in package.json, or re-run \`sentinel --init --build\`, which declares it.`;
|
|
1364
|
+
}
|
|
1365
|
+
const resolved = declared.map((token) => ({ token, path: resolveOutputToken(token, cwd) })).filter((entry) => entry.path !== void 0);
|
|
1366
|
+
if (resolved.length === 0) return void 0;
|
|
1367
|
+
if (resolved.some((entry) => writtenSince(entry.path, startedAt))) return void 0;
|
|
1368
|
+
return `the build wrote nothing to any of the directories this module declares as its nx \`outputs\` (${declared.join(", ")}), so nx would cache this build and restore an empty result from it. Whatever directory the build DID write to belongs in \`nx.targets.${BUILD_SCRIPT_NAME}.outputs\` in package.json. The build itself succeeded; only its cache declaration is wrong.`;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1157
1371
|
// src/roles/build/prerequisite.ts
|
|
1158
1372
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1159
1373
|
var PREBUILD_SCRIPT_NAME = `pre${BUILD_SCRIPT_NAME}`;
|
|
@@ -1202,7 +1416,15 @@ var ViteAdapter = class extends ViteRoleAdapter {
|
|
|
1202
1416
|
);
|
|
1203
1417
|
return { ok: false, code: prerequisite.code };
|
|
1204
1418
|
}
|
|
1205
|
-
|
|
1419
|
+
const startedAt = Date.now();
|
|
1420
|
+
const result = await this.spawnVite(ctx, ready.vite, ["build"], 1);
|
|
1421
|
+
if (!result.ok) return result;
|
|
1422
|
+
const problem = outputsProblem(ctx.cwd, startedAt);
|
|
1423
|
+
if (problem !== void 0) {
|
|
1424
|
+
this.say(problem);
|
|
1425
|
+
return { ok: false, code: 1 };
|
|
1426
|
+
}
|
|
1427
|
+
return result;
|
|
1206
1428
|
}
|
|
1207
1429
|
/**
|
|
1208
1430
|
* What this module builds with, WITHOUT loading its config.
|
|
@@ -1274,12 +1496,12 @@ function registerBuild() {
|
|
|
1274
1496
|
|
|
1275
1497
|
// src/roles/format/adapters/oxfmt/oxfmt.adapter.ts
|
|
1276
1498
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
1277
|
-
import { existsSync as
|
|
1278
|
-
import { join as
|
|
1499
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
|
|
1500
|
+
import { join as join17 } from "path";
|
|
1279
1501
|
|
|
1280
1502
|
// src/core/config/has-source.ts
|
|
1281
1503
|
import { readdirSync } from "fs";
|
|
1282
|
-
import { extname, join as
|
|
1504
|
+
import { extname, join as join12, relative as relative3 } from "path";
|
|
1283
1505
|
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1284
1506
|
"node_modules",
|
|
1285
1507
|
"dist",
|
|
@@ -1330,7 +1552,7 @@ function hasSourceFiles(cwd, extensions) {
|
|
|
1330
1552
|
}
|
|
1331
1553
|
for (const entry of entries) {
|
|
1332
1554
|
if (entry.isDirectory()) {
|
|
1333
|
-
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(
|
|
1555
|
+
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join12(dir, entry.name));
|
|
1334
1556
|
continue;
|
|
1335
1557
|
}
|
|
1336
1558
|
if (wanted.has(extname(entry.name))) return true;
|
|
@@ -1351,7 +1573,7 @@ function listSourceFiles(cwd, extensions) {
|
|
|
1351
1573
|
continue;
|
|
1352
1574
|
}
|
|
1353
1575
|
for (const entry of entries) {
|
|
1354
|
-
const full =
|
|
1576
|
+
const full = join12(dir, entry.name);
|
|
1355
1577
|
if (entry.isDirectory()) {
|
|
1356
1578
|
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(full);
|
|
1357
1579
|
continue;
|
|
@@ -1369,159 +1591,6 @@ function scopeFlags(paths, options = []) {
|
|
|
1369
1591
|
return [TOLERATE_EMPTY_FLAG];
|
|
1370
1592
|
}
|
|
1371
1593
|
|
|
1372
|
-
// src/core/settings.ts
|
|
1373
|
-
var WORKSPACE_ROOT_MARKER = "nx.json";
|
|
1374
|
-
var DEFAULT_MAX_DIAGNOSTICS = 100;
|
|
1375
|
-
|
|
1376
|
-
// src/core/workspace-prep.ts
|
|
1377
|
-
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync } from "fs";
|
|
1378
|
-
import { dirname as dirname3, join as join10, relative as relative4 } from "path";
|
|
1379
|
-
var OVERRIDE_KEY = "i18next>typescript";
|
|
1380
|
-
var NATIVE_TS_ALIAS = "@typescript/native";
|
|
1381
|
-
var WORKSPACE_YAML = "pnpm-workspace.yaml";
|
|
1382
|
-
var RELEASE_AGE_KEY = "minimumReleaseAgeExclude";
|
|
1383
|
-
var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
|
|
1384
|
-
function findWorkspaceRoot(startDir) {
|
|
1385
|
-
let dir = startDir;
|
|
1386
|
-
for (; ; ) {
|
|
1387
|
-
if (existsSync9(join10(dir, WORKSPACE_ROOT_MARKER))) return dir;
|
|
1388
|
-
const parent = dirname3(dir);
|
|
1389
|
-
if (parent === dir) return void 0;
|
|
1390
|
-
dir = parent;
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
function declaredNativeTs(pkg) {
|
|
1394
|
-
const spec = pkg.dependencies?.[NATIVE_TS_ALIAS] ?? pkg.devDependencies?.[NATIVE_TS_ALIAS];
|
|
1395
|
-
if (!spec) return void 0;
|
|
1396
|
-
const version = spec.slice(spec.lastIndexOf("@") + 1).replace(/^[\^~>=<\s]+/, "");
|
|
1397
|
-
return version || void 0;
|
|
1398
|
-
}
|
|
1399
|
-
function ensureI18nextSingleton(root, dryRun) {
|
|
1400
|
-
const pkgPath = join10(root, "package.json");
|
|
1401
|
-
if (!existsSync9(pkgPath)) return void 0;
|
|
1402
|
-
const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
|
|
1403
|
-
const want = declaredNativeTs(pkg);
|
|
1404
|
-
if (!want) return void 0;
|
|
1405
|
-
const have = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
1406
|
-
if (have === want) return void 0;
|
|
1407
|
-
if (dryRun) return `would pin ${OVERRIDE_KEY} to ${want} (i18next singleton)`;
|
|
1408
|
-
pkg.pnpm ??= {};
|
|
1409
|
-
pkg.pnpm.overrides ??= {};
|
|
1410
|
-
pkg.pnpm.overrides[OVERRIDE_KEY] = want;
|
|
1411
|
-
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
1412
|
-
return `pinned ${OVERRIDE_KEY} to ${want} in package.json (i18next singleton)`;
|
|
1413
|
-
}
|
|
1414
|
-
function ensureReleaseAgeAllowList(root, dryRun) {
|
|
1415
|
-
const yamlPath = join10(root, WORKSPACE_YAML);
|
|
1416
|
-
if (!existsSync9(yamlPath)) return void 0;
|
|
1417
|
-
const own = readOwnPackage().name;
|
|
1418
|
-
const lines = readFileSync7(yamlPath, "utf8").split("\n");
|
|
1419
|
-
const keyIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === `${RELEASE_AGE_KEY}:`);
|
|
1420
|
-
if (keyIdx === -1) return void 0;
|
|
1421
|
-
let lastItemIdx = keyIdx;
|
|
1422
|
-
let indent = " ";
|
|
1423
|
-
for (let i = keyIdx + 1; i < lines.length; i++) {
|
|
1424
|
-
const match = lines[i]?.match(LIST_ITEM);
|
|
1425
|
-
if (!match) break;
|
|
1426
|
-
indent = match[1] ?? indent;
|
|
1427
|
-
lastItemIdx = i;
|
|
1428
|
-
if ((match[2] ?? "").replace(/^['"]|['"]$/g, "") === own) return void 0;
|
|
1429
|
-
}
|
|
1430
|
-
if (dryRun) return `would allow-list ${own} under ${RELEASE_AGE_KEY}`;
|
|
1431
|
-
lines.splice(lastItemIdx + 1, 0, `${indent}- '${own}'`);
|
|
1432
|
-
writeFileSync(yamlPath, lines.join("\n"));
|
|
1433
|
-
return `allow-listed ${own} under ${RELEASE_AGE_KEY} in ${WORKSPACE_YAML}`;
|
|
1434
|
-
}
|
|
1435
|
-
var PRETTIER_IGNORE = ".prettierignore";
|
|
1436
|
-
var EXCLUSION_HEADER = "# @hublo/sentinel: modules formatted by oxfmt, not by the root Prettier";
|
|
1437
|
-
var ROOT_PRETTIER_CONFIGS = [
|
|
1438
|
-
".prettierrc",
|
|
1439
|
-
".prettierrc.json",
|
|
1440
|
-
".prettierrc.json5",
|
|
1441
|
-
".prettierrc.yml",
|
|
1442
|
-
".prettierrc.yaml",
|
|
1443
|
-
".prettierrc.js",
|
|
1444
|
-
".prettierrc.cjs",
|
|
1445
|
-
".prettierrc.mjs",
|
|
1446
|
-
"prettier.config.js",
|
|
1447
|
-
"prettier.config.cjs",
|
|
1448
|
-
"prettier.config.mjs"
|
|
1449
|
-
];
|
|
1450
|
-
function ensureFormatterExclusion(root, moduleDir, dryRun) {
|
|
1451
|
-
const rel = relative4(root, moduleDir).replaceAll("\\", "/");
|
|
1452
|
-
if (rel === "" || rel.startsWith("..")) return void 0;
|
|
1453
|
-
const ignorePath = join10(root, PRETTIER_IGNORE);
|
|
1454
|
-
const hasPrettier = existsSync9(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync9(join10(root, name)));
|
|
1455
|
-
if (!hasPrettier) return void 0;
|
|
1456
|
-
const pattern = `/${rel}/`;
|
|
1457
|
-
const existing = existsSync9(ignorePath) ? readFileSync7(ignorePath, "utf8") : "";
|
|
1458
|
-
const lines = existing.split("\n");
|
|
1459
|
-
if (lines.some((line) => line.trim().replace(/\/$/, "") === pattern.replace(/\/$/, ""))) {
|
|
1460
|
-
return void 0;
|
|
1461
|
-
}
|
|
1462
|
-
if (dryRun) return `would exclude ${rel} from the root Prettier (${PRETTIER_IGNORE})`;
|
|
1463
|
-
const headerIdx = lines.findIndex((line) => line.trim() === EXCLUSION_HEADER);
|
|
1464
|
-
if (headerIdx === -1) {
|
|
1465
|
-
const prefix = existing.trim() === "" ? "" : `${existing.replace(/\n*$/, "")}
|
|
1466
|
-
|
|
1467
|
-
`;
|
|
1468
|
-
writeFileSync(ignorePath, `${prefix}${EXCLUSION_HEADER}
|
|
1469
|
-
${pattern}
|
|
1470
|
-
`);
|
|
1471
|
-
} else {
|
|
1472
|
-
let end = headerIdx + 1;
|
|
1473
|
-
while (end < lines.length && lines[end]?.trim().startsWith("/")) end += 1;
|
|
1474
|
-
const managed = [...lines.slice(headerIdx + 1, end), pattern].sort();
|
|
1475
|
-
writeFileSync(
|
|
1476
|
-
ignorePath,
|
|
1477
|
-
[...lines.slice(0, headerIdx + 1), ...managed, ...lines.slice(end)].join("\n")
|
|
1478
|
-
);
|
|
1479
|
-
}
|
|
1480
|
-
return `excluded ${rel} from the root Prettier (${PRETTIER_IGNORE}): it formats itself now`;
|
|
1481
|
-
}
|
|
1482
|
-
function ensureWorkspacePrep(opts) {
|
|
1483
|
-
const dryRun = Boolean(opts.dryRun);
|
|
1484
|
-
return [
|
|
1485
|
-
ensureI18nextSingleton(opts.root, dryRun),
|
|
1486
|
-
ensureReleaseAgeAllowList(opts.root, dryRun),
|
|
1487
|
-
opts.formattedModule === void 0 ? void 0 : ensureFormatterExclusion(opts.root, opts.formattedModule, dryRun)
|
|
1488
|
-
].filter((message) => message !== void 0);
|
|
1489
|
-
}
|
|
1490
|
-
function inspectWorkspacePrep(root) {
|
|
1491
|
-
const entries = [];
|
|
1492
|
-
let pkg = {};
|
|
1493
|
-
const pkgPath = join10(root, "package.json");
|
|
1494
|
-
if (existsSync9(pkgPath)) {
|
|
1495
|
-
try {
|
|
1496
|
-
pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
|
|
1497
|
-
} catch {
|
|
1498
|
-
pkg = {};
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
const pinned = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
1502
|
-
if (pinned !== void 0) {
|
|
1503
|
-
const stillForks = declaredNativeTs(pkg);
|
|
1504
|
-
entries.push({
|
|
1505
|
-
rule: `package.json \u2192 pnpm.overrides.${OVERRIDE_KEY}`,
|
|
1506
|
-
reason: stillForks === void 0 ? `pinned to ${pinned}, but the root no longer declares ${NATIVE_TS_ALIAS}, so nothing forks any more. This override is now dead config and can be removed.` : `pinned to ${pinned}, matching the second TypeScript the root declares (${NATIVE_TS_ALIAS}). It re-resolves i18next for EVERY module that depends on it, not only adopted ones. It retires with the second TypeScript.`
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
const own = readOwnPackage().name;
|
|
1510
|
-
const yamlPath = join10(root, WORKSPACE_YAML);
|
|
1511
|
-
if (existsSync9(yamlPath)) {
|
|
1512
|
-
const yaml = readFileSync7(yamlPath, "utf8");
|
|
1513
|
-
const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
|
|
1514
|
-
if (listed) {
|
|
1515
|
-
const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
|
|
1516
|
-
entries.push({
|
|
1517
|
-
rule: `${WORKSPACE_YAML} \u2192 ${RELEASE_AGE_KEY}: ${own}`,
|
|
1518
|
-
reason: gated ? `${own} is exempt from this workspace's release-age gate, so a freshly published version installs instead of being held. That is a standing exemption from a supply-chain control: the exposure is one bump wide, since the version is pinned and the lockfile carries its integrity, so a re-publish of the same version does not pass. Retire it once a bump can simply wait out the window.` : `${own} is allow-listed, but this workspace no longer sets minimumReleaseAge, so there is no gate to be exempt from. This entry is now dead config and can be removed.`
|
|
1519
|
-
});
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
return entries;
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
1594
|
// src/roles/format/config-policy.ts
|
|
1526
1595
|
var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
|
|
1527
1596
|
var FORMAT_SCRIPT_NAME = "format";
|
|
@@ -1596,8 +1665,8 @@ function writesWhenRewritten(name, command) {
|
|
|
1596
1665
|
var CHECK_SCRIPT_NAMES = /* @__PURE__ */ new Set(["lint", "format", "check", "test", "typecheck", "verify"]);
|
|
1597
1666
|
|
|
1598
1667
|
// src/roles/format/inherited-ignores.ts
|
|
1599
|
-
import { existsSync as
|
|
1600
|
-
import { join as
|
|
1668
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
1669
|
+
import { join as join13 } from "path";
|
|
1601
1670
|
var ROOT_IGNORE_FILE = ".prettierignore";
|
|
1602
1671
|
function isPattern(line) {
|
|
1603
1672
|
const trimmed = line.trim();
|
|
@@ -1612,11 +1681,11 @@ function toModulePattern(pattern) {
|
|
|
1612
1681
|
}
|
|
1613
1682
|
function inheritedIgnorePatterns(workspaceRoot) {
|
|
1614
1683
|
if (!workspaceRoot) return [];
|
|
1615
|
-
const path =
|
|
1616
|
-
if (!
|
|
1684
|
+
const path = join13(workspaceRoot, ROOT_IGNORE_FILE);
|
|
1685
|
+
if (!existsSync12(path)) return [];
|
|
1617
1686
|
let contents;
|
|
1618
1687
|
try {
|
|
1619
|
-
contents =
|
|
1688
|
+
contents = readFileSync9(path, "utf8");
|
|
1620
1689
|
} catch {
|
|
1621
1690
|
return [];
|
|
1622
1691
|
}
|
|
@@ -1703,13 +1772,13 @@ function formatPresetFor(preset) {
|
|
|
1703
1772
|
}
|
|
1704
1773
|
|
|
1705
1774
|
// src/roles/format/prettier-config.ts
|
|
1706
|
-
import { existsSync as
|
|
1707
|
-
import { join as
|
|
1775
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
1776
|
+
import { join as join15 } from "path";
|
|
1708
1777
|
|
|
1709
1778
|
// src/roles/format/resolve-oxfmt.ts
|
|
1710
|
-
import { readFileSync as
|
|
1779
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
1711
1780
|
import { createRequire as createRequire2 } from "module";
|
|
1712
|
-
import { dirname as dirname4, join as
|
|
1781
|
+
import { dirname as dirname4, join as join14 } from "path";
|
|
1713
1782
|
function resolveOxfmt(cwd) {
|
|
1714
1783
|
return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
|
|
1715
1784
|
}
|
|
@@ -1738,8 +1807,8 @@ function configSchema() {
|
|
|
1738
1807
|
function readConfigSchema() {
|
|
1739
1808
|
try {
|
|
1740
1809
|
const manifest = createRequire2(import.meta.url).resolve("oxfmt/package.json");
|
|
1741
|
-
const schemaPath =
|
|
1742
|
-
return JSON.parse(
|
|
1810
|
+
const schemaPath = join14(dirname4(manifest), "configuration_schema.json");
|
|
1811
|
+
return JSON.parse(readFileSync10(schemaPath, "utf8"));
|
|
1743
1812
|
} catch {
|
|
1744
1813
|
return void 0;
|
|
1745
1814
|
}
|
|
@@ -1770,14 +1839,14 @@ function toOxfmtOverrides(value) {
|
|
|
1770
1839
|
return { overrides, unresolved };
|
|
1771
1840
|
}
|
|
1772
1841
|
function readPrettierSettings(cwd) {
|
|
1773
|
-
const file = PRETTIER_CONFIG_FILES.find((name) =>
|
|
1842
|
+
const file = PRETTIER_CONFIG_FILES.find((name) => existsSync13(join15(cwd, name)));
|
|
1774
1843
|
if (!file) return { options: {}, unresolved: [] };
|
|
1775
1844
|
if (/\.(js|cjs|mjs)$/.test(file)) {
|
|
1776
1845
|
return { options: {}, file, unresolved: [`${file} is JavaScript, so it was not executed`] };
|
|
1777
1846
|
}
|
|
1778
1847
|
let parsed;
|
|
1779
1848
|
try {
|
|
1780
|
-
parsed = parseJsonc(
|
|
1849
|
+
parsed = parseJsonc(readFileSync11(join15(cwd, file), "utf8"), file);
|
|
1781
1850
|
} catch {
|
|
1782
1851
|
return { options: {}, file, unresolved: [`${file} could not be parsed`] };
|
|
1783
1852
|
}
|
|
@@ -1807,8 +1876,8 @@ function readPrettierSettings(cwd) {
|
|
|
1807
1876
|
}
|
|
1808
1877
|
|
|
1809
1878
|
// src/roles/format/read-adoption.ts
|
|
1810
|
-
import { existsSync as
|
|
1811
|
-
import { join as
|
|
1879
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
1880
|
+
import { join as join16 } from "path";
|
|
1812
1881
|
var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
|
|
1813
1882
|
configFile,
|
|
1814
1883
|
preset: null,
|
|
@@ -1824,11 +1893,11 @@ function sameValue(a, b) {
|
|
|
1824
1893
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
1825
1894
|
}
|
|
1826
1895
|
function readFormatAdoption(cwd) {
|
|
1827
|
-
const path =
|
|
1828
|
-
if (!
|
|
1896
|
+
const path = join16(cwd, FORMAT_CONFIG_FILE);
|
|
1897
|
+
if (!existsSync14(path)) return NOT_ADOPTED2(null);
|
|
1829
1898
|
let parsed;
|
|
1830
1899
|
try {
|
|
1831
|
-
parsed = parseJsonc(
|
|
1900
|
+
parsed = parseJsonc(readFileSync12(path, "utf8"), FORMAT_CONFIG_FILE);
|
|
1832
1901
|
} catch (error) {
|
|
1833
1902
|
const reason = error instanceof Error ? error.message : String(error);
|
|
1834
1903
|
return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
|
|
@@ -1953,7 +2022,7 @@ var OxfmtAdapter = class extends BaseAdapter {
|
|
|
1953
2022
|
manifestOperation(context.cwd, this.formatScripts(context.cwd))
|
|
1954
2023
|
];
|
|
1955
2024
|
const prettierConfigs = PRETTIER_CONFIG_FILES.filter(
|
|
1956
|
-
(name) =>
|
|
2025
|
+
(name) => existsSync15(join17(context.cwd, name))
|
|
1957
2026
|
);
|
|
1958
2027
|
for (const name of prettierConfigs) operations.push({ kind: "delete", path: name });
|
|
1959
2028
|
const removableDeps = this.modulePrettierDependencies(context.cwd);
|
|
@@ -2193,7 +2262,7 @@ var OxfmtAdapter = class extends BaseAdapter {
|
|
|
2193
2262
|
modulePrettierDependencies(cwd) {
|
|
2194
2263
|
const isPrettierPackage = (name) => name === "prettier" || name.startsWith("prettier-plugin-") || name.startsWith("@prettier/");
|
|
2195
2264
|
try {
|
|
2196
|
-
const manifest = JSON.parse(
|
|
2265
|
+
const manifest = JSON.parse(readFileSync13(join17(cwd, "package.json"), "utf8"));
|
|
2197
2266
|
return Object.keys(manifest.devDependencies ?? {}).filter(isPrettierPackage).map((name) => ["devDependencies", name]);
|
|
2198
2267
|
} catch {
|
|
2199
2268
|
return [];
|
|
@@ -2275,8 +2344,8 @@ function registerFormat() {
|
|
|
2275
2344
|
|
|
2276
2345
|
// src/roles/lint/adapters/oxlint/oxlint.adapter.ts
|
|
2277
2346
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
2278
|
-
import { existsSync as
|
|
2279
|
-
import { join as
|
|
2347
|
+
import { existsSync as existsSync23, readFileSync as readFileSync21, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
2348
|
+
import { join as join27 } from "path";
|
|
2280
2349
|
|
|
2281
2350
|
// src/core/config/deferred-rules.ts
|
|
2282
2351
|
function deferredRuleNames(rules) {
|
|
@@ -2284,8 +2353,8 @@ function deferredRuleNames(rules) {
|
|
|
2284
2353
|
}
|
|
2285
2354
|
|
|
2286
2355
|
// src/core/fix-report.ts
|
|
2287
|
-
import { statSync } from "fs";
|
|
2288
|
-
import { join as
|
|
2356
|
+
import { statSync as statSync2 } from "fs";
|
|
2357
|
+
import { join as join18 } from "path";
|
|
2289
2358
|
var CONFIG_REFUSED = /failed to parse .*config|invalid config file/i;
|
|
2290
2359
|
function readFailure(output) {
|
|
2291
2360
|
const lines = output.split("\n").map((line2) => line2.trim());
|
|
@@ -2296,7 +2365,7 @@ function readFailure(output) {
|
|
|
2296
2365
|
}
|
|
2297
2366
|
function fingerprint(path) {
|
|
2298
2367
|
try {
|
|
2299
|
-
const stat =
|
|
2368
|
+
const stat = statSync2(path);
|
|
2300
2369
|
return `${stat.size}:${stat.mtimeMs}`;
|
|
2301
2370
|
} catch {
|
|
2302
2371
|
return void 0;
|
|
@@ -2305,7 +2374,7 @@ function fingerprint(path) {
|
|
|
2305
2374
|
function snapshotFiles(cwd, extensions) {
|
|
2306
2375
|
const snapshot = /* @__PURE__ */ new Map();
|
|
2307
2376
|
for (const file of listSourceFiles(cwd, extensions)) {
|
|
2308
|
-
const mark = fingerprint(
|
|
2377
|
+
const mark = fingerprint(join18(cwd, file));
|
|
2309
2378
|
if (mark !== void 0) snapshot.set(file, mark);
|
|
2310
2379
|
}
|
|
2311
2380
|
return snapshot;
|
|
@@ -2313,7 +2382,7 @@ function snapshotFiles(cwd, extensions) {
|
|
|
2313
2382
|
function changedSince(cwd, before, extensions) {
|
|
2314
2383
|
const changed = [];
|
|
2315
2384
|
for (const file of listSourceFiles(cwd, extensions)) {
|
|
2316
|
-
const now = fingerprint(
|
|
2385
|
+
const now = fingerprint(join18(cwd, file));
|
|
2317
2386
|
if (now === void 0) continue;
|
|
2318
2387
|
if (before.get(file) !== now) changed.push(file);
|
|
2319
2388
|
}
|
|
@@ -2332,8 +2401,8 @@ function describeFixOutcome(outcome, toolLabel) {
|
|
|
2332
2401
|
}
|
|
2333
2402
|
|
|
2334
2403
|
// src/roles/lint/module-baseline.ts
|
|
2335
|
-
import { existsSync as
|
|
2336
|
-
import { join as
|
|
2404
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
|
|
2405
|
+
import { join as join19 } from "path";
|
|
2337
2406
|
var LINT_BASELINE_FILE = ".oxlintrc.baseline.json";
|
|
2338
2407
|
var LINT_MEASURE_FILE = ".oxlintrc.measure.json";
|
|
2339
2408
|
var LINT_BASELINE_SPECIFIER = `./${LINT_BASELINE_FILE}`;
|
|
@@ -2377,11 +2446,11 @@ function describeHolds(holds) {
|
|
|
2377
2446
|
return `held ${holds.length} rule(s) at \`warn\` for this module, covering ${total} violation(s) that were already there: ${listed}${rest}. They are written to ${LINT_BASELINE_FILE}, they still report, and they return to \`error\` once fixed and re-initialized`;
|
|
2378
2447
|
}
|
|
2379
2448
|
function heldRules(cwd) {
|
|
2380
|
-
const path =
|
|
2381
|
-
if (!
|
|
2449
|
+
const path = join19(cwd, LINT_BASELINE_FILE);
|
|
2450
|
+
if (!existsSync16(path)) return [];
|
|
2382
2451
|
try {
|
|
2383
2452
|
const parsed = parseJsonc(
|
|
2384
|
-
|
|
2453
|
+
readFileSync14(path, "utf8"),
|
|
2385
2454
|
LINT_BASELINE_FILE
|
|
2386
2455
|
);
|
|
2387
2456
|
return Object.keys(parsed.rules ?? {});
|
|
@@ -4204,14 +4273,14 @@ function downgradedRulesFor(preset) {
|
|
|
4204
4273
|
}
|
|
4205
4274
|
|
|
4206
4275
|
// src/roles/lint/extra-layers.ts
|
|
4207
|
-
import { existsSync as
|
|
4208
|
-
import { isAbsolute as isAbsolute2, join as
|
|
4276
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
|
|
4277
|
+
import { isAbsolute as isAbsolute2, join as join20, resolve as resolve3 } from "path";
|
|
4209
4278
|
function ruleCount(cwd, specifier) {
|
|
4210
4279
|
const path = isAbsolute2(specifier) ? specifier : resolve3(cwd, specifier);
|
|
4211
|
-
if (!
|
|
4280
|
+
if (!existsSync17(path)) return void 0;
|
|
4212
4281
|
try {
|
|
4213
4282
|
const parsed = parseJsonc(
|
|
4214
|
-
|
|
4283
|
+
readFileSync15(path, "utf8"),
|
|
4215
4284
|
specifier
|
|
4216
4285
|
);
|
|
4217
4286
|
return Object.keys(parsed.rules ?? {}).length;
|
|
@@ -4231,7 +4300,7 @@ function extraLayers(cwd, extendsList) {
|
|
|
4231
4300
|
function committedExtendsList(cwd, configFile) {
|
|
4232
4301
|
try {
|
|
4233
4302
|
const parsed = parseJsonc(
|
|
4234
|
-
|
|
4303
|
+
readFileSync15(join20(cwd, configFile), "utf8"),
|
|
4235
4304
|
configFile
|
|
4236
4305
|
);
|
|
4237
4306
|
return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4290,8 +4359,8 @@ function errorCountsByConfigRule(stdout) {
|
|
|
4290
4359
|
}
|
|
4291
4360
|
|
|
4292
4361
|
// src/core/config/read-adoption.ts
|
|
4293
|
-
import { existsSync as
|
|
4294
|
-
import { join as
|
|
4362
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
|
|
4363
|
+
import { join as join22 } from "path";
|
|
4295
4364
|
|
|
4296
4365
|
// src/core/config/owned-keys.ts
|
|
4297
4366
|
function presetOwnedKeys(config, permitted, presetSets) {
|
|
@@ -4306,12 +4375,12 @@ function localOnlyKeys(config, permitted, presetSets) {
|
|
|
4306
4375
|
}
|
|
4307
4376
|
|
|
4308
4377
|
// src/core/config/resolve-config-target.ts
|
|
4309
|
-
import { existsSync as
|
|
4310
|
-
import { join as
|
|
4378
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
|
|
4379
|
+
import { join as join21 } from "path";
|
|
4311
4380
|
function readExtends(absolutePath) {
|
|
4312
4381
|
let parsed;
|
|
4313
4382
|
try {
|
|
4314
|
-
parsed = parseJsonc(
|
|
4383
|
+
parsed = parseJsonc(readFileSync16(absolutePath, "utf8"), absolutePath);
|
|
4315
4384
|
} catch {
|
|
4316
4385
|
return [];
|
|
4317
4386
|
}
|
|
@@ -4325,8 +4394,8 @@ function resolveConfigTarget(moduleDir, { candidates, markers, fallback }) {
|
|
|
4325
4394
|
let existing;
|
|
4326
4395
|
let existingExtendsSomething = false;
|
|
4327
4396
|
for (const candidate of candidates) {
|
|
4328
|
-
const absolutePath =
|
|
4329
|
-
if (!
|
|
4397
|
+
const absolutePath = join21(moduleDir, candidate);
|
|
4398
|
+
if (!existsSync18(absolutePath)) continue;
|
|
4330
4399
|
const chain = readExtends(absolutePath);
|
|
4331
4400
|
if (existing === void 0) {
|
|
4332
4401
|
existing = candidate;
|
|
@@ -4359,12 +4428,12 @@ var NOT_ADOPTED3 = (configFile, unreadable = null) => ({
|
|
|
4359
4428
|
});
|
|
4360
4429
|
function readAdoption(cwd, options) {
|
|
4361
4430
|
const target = resolveConfigTarget(cwd, options);
|
|
4362
|
-
if (target.reason === "none" || !
|
|
4431
|
+
if (target.reason === "none" || !existsSync19(join22(cwd, target.path))) {
|
|
4363
4432
|
return NOT_ADOPTED3(target.reason === "none" ? null : target.path);
|
|
4364
4433
|
}
|
|
4365
4434
|
let parsed;
|
|
4366
4435
|
try {
|
|
4367
|
-
parsed = parseJsonc(
|
|
4436
|
+
parsed = parseJsonc(readFileSync17(join22(cwd, target.path), "utf8"), target.path);
|
|
4368
4437
|
} catch (error) {
|
|
4369
4438
|
const reason = error instanceof Error ? error.message : String(error);
|
|
4370
4439
|
return NOT_ADOPTED3(target.path, `${target.path} could not be parsed (${reason})`);
|
|
@@ -4398,9 +4467,9 @@ function readLintAdoption(cwd) {
|
|
|
4398
4467
|
}
|
|
4399
4468
|
|
|
4400
4469
|
// src/roles/lint/resolve-oxlint.ts
|
|
4401
|
-
import { existsSync as
|
|
4470
|
+
import { existsSync as existsSync20 } from "fs";
|
|
4402
4471
|
import { createRequire as createRequire3 } from "module";
|
|
4403
|
-
import { delimiter as delimiter2, dirname as dirname5, join as
|
|
4472
|
+
import { delimiter as delimiter2, dirname as dirname5, join as join23 } from "path";
|
|
4404
4473
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4405
4474
|
var PACKAGE_OF = {
|
|
4406
4475
|
oxlint: "oxlint",
|
|
@@ -4425,30 +4494,30 @@ function tsgolintShim(cwd) {
|
|
|
4425
4494
|
for (const owner of ["oxlint-tsgolint", "oxlint"]) {
|
|
4426
4495
|
try {
|
|
4427
4496
|
const packageDir = dirname5(require3.resolve(`${owner}/package.json`));
|
|
4428
|
-
candidates.push(
|
|
4429
|
-
candidates.push(
|
|
4497
|
+
candidates.push(join23(packageDir, "node_modules", ".bin", "tsgolint"));
|
|
4498
|
+
candidates.push(join23(packageDir, "..", ".bin", "tsgolint"));
|
|
4430
4499
|
} catch {
|
|
4431
4500
|
}
|
|
4432
4501
|
}
|
|
4433
4502
|
try {
|
|
4434
4503
|
const ownRoot = dirname5(require3.resolve("@hublo/sentinel/package.json"));
|
|
4435
|
-
candidates.push(
|
|
4504
|
+
candidates.push(join23(ownRoot, "node_modules", ".bin", "tsgolint"));
|
|
4436
4505
|
} catch {
|
|
4437
4506
|
candidates.push(resolveBin(dirname5(fileURLToPath2(import.meta.url)), "tsgolint") ?? "");
|
|
4438
4507
|
}
|
|
4439
|
-
return candidates.find((candidate) => candidate !== "" &&
|
|
4508
|
+
return candidates.find((candidate) => candidate !== "" && existsSync20(candidate));
|
|
4440
4509
|
}
|
|
4441
4510
|
function oxlintSearchPath(cwd) {
|
|
4442
4511
|
return binSearchPath(cwd);
|
|
4443
4512
|
}
|
|
4444
4513
|
|
|
4445
4514
|
// src/roles/lint/adapters/oxlint/plan.ts
|
|
4446
|
-
import { existsSync as
|
|
4447
|
-
import { join as
|
|
4515
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
|
|
4516
|
+
import { join as join26 } from "path";
|
|
4448
4517
|
|
|
4449
4518
|
// src/roles/lint/eslint-ignores.ts
|
|
4450
|
-
import { existsSync as
|
|
4451
|
-
import { join as
|
|
4519
|
+
import { existsSync as existsSync21, readFileSync as readFileSync18 } from "fs";
|
|
4520
|
+
import { join as join24 } from "path";
|
|
4452
4521
|
import { parseSync as parseSync2 } from "oxc-parser";
|
|
4453
4522
|
var OPAQUE_SOURCE = /\b(includeIgnoreFile)\s*\([^)]*\)/g;
|
|
4454
4523
|
function toOxlintPattern(pattern) {
|
|
@@ -4460,11 +4529,11 @@ function readRootEslintIgnores(root) {
|
|
|
4460
4529
|
return { patterns: patterns.filter((pattern) => pattern.startsWith("**/")), unresolved };
|
|
4461
4530
|
}
|
|
4462
4531
|
function readEslintIgnores(cwd) {
|
|
4463
|
-
const config = ESLINT_CONFIG_FILES.map((name) =>
|
|
4532
|
+
const config = ESLINT_CONFIG_FILES.map((name) => join24(cwd, name)).find((path) => existsSync21(path));
|
|
4464
4533
|
if (!config) return { patterns: [], unresolved: [] };
|
|
4465
4534
|
let source;
|
|
4466
4535
|
try {
|
|
4467
|
-
source =
|
|
4536
|
+
source = readFileSync18(config, "utf8");
|
|
4468
4537
|
} catch {
|
|
4469
4538
|
return { patterns: [], unresolved: [] };
|
|
4470
4539
|
}
|
|
@@ -4565,8 +4634,8 @@ function lintPresetFor(preset) {
|
|
|
4565
4634
|
}
|
|
4566
4635
|
|
|
4567
4636
|
// src/roles/lint/rename-suppressions.ts
|
|
4568
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
4569
|
-
import { join as
|
|
4637
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync19, statSync as statSync3 } from "fs";
|
|
4638
|
+
import { join as join25, relative as relative4 } from "path";
|
|
4570
4639
|
var SOURCE_EXTENSIONS = [
|
|
4571
4640
|
".ts",
|
|
4572
4641
|
".tsx",
|
|
@@ -4613,10 +4682,10 @@ function* sourceFiles(dir) {
|
|
|
4613
4682
|
return;
|
|
4614
4683
|
}
|
|
4615
4684
|
for (const entry of entries) {
|
|
4616
|
-
const full =
|
|
4685
|
+
const full = join25(dir, entry);
|
|
4617
4686
|
let isDirectory;
|
|
4618
4687
|
try {
|
|
4619
|
-
isDirectory =
|
|
4688
|
+
isDirectory = statSync3(full).isDirectory();
|
|
4620
4689
|
} catch {
|
|
4621
4690
|
continue;
|
|
4622
4691
|
}
|
|
@@ -4633,7 +4702,7 @@ function findSuppressionRenames(cwd, renames) {
|
|
|
4633
4702
|
for (const file of sourceFiles(cwd)) {
|
|
4634
4703
|
let content;
|
|
4635
4704
|
try {
|
|
4636
|
-
content =
|
|
4705
|
+
content = readFileSync19(file, "utf8");
|
|
4637
4706
|
} catch {
|
|
4638
4707
|
continue;
|
|
4639
4708
|
}
|
|
@@ -4657,7 +4726,7 @@ function findSuppressionRenames(cwd, renames) {
|
|
|
4657
4726
|
}
|
|
4658
4727
|
if (hits.length === 0) return;
|
|
4659
4728
|
found.push({
|
|
4660
|
-
file:
|
|
4729
|
+
file: relative4(cwd, file),
|
|
4661
4730
|
line: index + 1,
|
|
4662
4731
|
from: line,
|
|
4663
4732
|
to: line.replace(rules, renamed.join(", ")),
|
|
@@ -4761,7 +4830,7 @@ function plan2(context) {
|
|
|
4761
4830
|
keys: removableDeps
|
|
4762
4831
|
});
|
|
4763
4832
|
}
|
|
4764
|
-
const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) =>
|
|
4833
|
+
const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync22(join26(context.cwd, name)));
|
|
4765
4834
|
for (const name of eslintConfigs) operations.push({ kind: "delete", path: name });
|
|
4766
4835
|
operations.push(
|
|
4767
4836
|
...nxTargetOperations({
|
|
@@ -4859,7 +4928,7 @@ function lintScripts(cwd) {
|
|
|
4859
4928
|
function committedExtends(cwd) {
|
|
4860
4929
|
try {
|
|
4861
4930
|
const parsed = parseJsonc(
|
|
4862
|
-
|
|
4931
|
+
readFileSync20(join26(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
4863
4932
|
LINT_CONFIG_FILE
|
|
4864
4933
|
);
|
|
4865
4934
|
return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4870,7 +4939,7 @@ function committedExtends(cwd) {
|
|
|
4870
4939
|
function committedIgnorePatterns(cwd) {
|
|
4871
4940
|
try {
|
|
4872
4941
|
const parsed = parseJsonc(
|
|
4873
|
-
|
|
4942
|
+
readFileSync20(join26(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
4874
4943
|
LINT_CONFIG_FILE
|
|
4875
4944
|
);
|
|
4876
4945
|
return Array.isArray(parsed.ignorePatterns) ? parsed.ignorePatterns.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4882,7 +4951,7 @@ function moduleEslintDependencies(cwd) {
|
|
|
4882
4951
|
const isEslintPackage = (name) => name === "eslint" || name === "@types/eslint" || name === "typescript-eslint" || name.startsWith("@typescript-eslint/") || name.startsWith("eslint-plugin-") || name.startsWith("eslint-config-") || name.startsWith("@eslint/");
|
|
4883
4952
|
let manifest;
|
|
4884
4953
|
try {
|
|
4885
|
-
manifest = JSON.parse(
|
|
4954
|
+
manifest = JSON.parse(readFileSync20(join26(cwd, "package.json"), "utf8"));
|
|
4886
4955
|
} catch {
|
|
4887
4956
|
return [];
|
|
4888
4957
|
}
|
|
@@ -5016,20 +5085,20 @@ ${result.stderr ?? ""}`);
|
|
|
5016
5085
|
* build the developer can see, rather than a silent half-adoption they cannot.
|
|
5017
5086
|
*/
|
|
5018
5087
|
writeModuleBaseline(ctx, oxlint, env) {
|
|
5019
|
-
const configPath =
|
|
5020
|
-
const baselinePath =
|
|
5021
|
-
if (!
|
|
5088
|
+
const configPath = join27(ctx.cwd, LINT_CONFIG_FILE);
|
|
5089
|
+
const baselinePath = join27(ctx.cwd, LINT_BASELINE_FILE);
|
|
5090
|
+
if (!existsSync23(configPath)) return;
|
|
5022
5091
|
let config;
|
|
5023
5092
|
try {
|
|
5024
5093
|
config = parseJsonc(
|
|
5025
|
-
|
|
5094
|
+
readFileSync21(configPath, "utf8"),
|
|
5026
5095
|
LINT_CONFIG_FILE
|
|
5027
5096
|
);
|
|
5028
5097
|
} catch {
|
|
5029
5098
|
return;
|
|
5030
5099
|
}
|
|
5031
5100
|
const current = Array.isArray(config.extends) ? config.extends : [];
|
|
5032
|
-
const measurePath =
|
|
5101
|
+
const measurePath = join27(ctx.cwd, LINT_MEASURE_FILE);
|
|
5033
5102
|
let measured;
|
|
5034
5103
|
try {
|
|
5035
5104
|
writeFileSync2(
|
|
@@ -5077,7 +5146,7 @@ ${result.stderr ?? ""}`);
|
|
|
5077
5146
|
}
|
|
5078
5147
|
}
|
|
5079
5148
|
async run(ctx) {
|
|
5080
|
-
if (!
|
|
5149
|
+
if (!existsSync23(join27(ctx.cwd, LINT_CONFIG_FILE))) {
|
|
5081
5150
|
process.stderr.write(
|
|
5082
5151
|
`sentinel lint(oxlint): no ${LINT_CONFIG_FILE} in this module; run \`sentinel --init --lint\` to adopt.
|
|
5083
5152
|
`
|
|
@@ -5225,7 +5294,7 @@ ${result.stderr ?? ""}`);
|
|
|
5225
5294
|
let stub;
|
|
5226
5295
|
try {
|
|
5227
5296
|
stub = parseJsonc(
|
|
5228
|
-
|
|
5297
|
+
readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
5229
5298
|
LINT_CONFIG_FILE
|
|
5230
5299
|
);
|
|
5231
5300
|
} catch {
|
|
@@ -5235,7 +5304,7 @@ ${result.stderr ?? ""}`);
|
|
|
5235
5304
|
for (const entry of stub.extends ?? []) {
|
|
5236
5305
|
try {
|
|
5237
5306
|
const preset = parseJsonc(
|
|
5238
|
-
|
|
5307
|
+
readFileSync21(join27(cwd, entry), "utf8"),
|
|
5239
5308
|
entry
|
|
5240
5309
|
);
|
|
5241
5310
|
for (const rule of Object.keys(preset.rules ?? {})) names.add(rule);
|
|
@@ -5305,14 +5374,14 @@ ${result.stderr ?? ""}`);
|
|
|
5305
5374
|
let parsed;
|
|
5306
5375
|
try {
|
|
5307
5376
|
parsed = parseJsonc(
|
|
5308
|
-
|
|
5377
|
+
readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
5309
5378
|
LINT_CONFIG_FILE
|
|
5310
5379
|
);
|
|
5311
5380
|
} catch {
|
|
5312
5381
|
return void 0;
|
|
5313
5382
|
}
|
|
5314
5383
|
const targets = Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : typeof parsed.extends === "string" ? [parsed.extends] : [];
|
|
5315
|
-
return targets.find((target) => !
|
|
5384
|
+
return targets.find((target) => !existsSync23(join27(cwd, target)));
|
|
5316
5385
|
}
|
|
5317
5386
|
/** Announce what is not enforced, so reduced coverage is never silent. */
|
|
5318
5387
|
announceDisabled(preset) {
|
|
@@ -5344,9 +5413,9 @@ function registerLint() {
|
|
|
5344
5413
|
|
|
5345
5414
|
// src/roles/typescript/adapters/tsc/tsc.adapter.ts
|
|
5346
5415
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
5347
|
-
import { existsSync as
|
|
5416
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "fs";
|
|
5348
5417
|
import { createRequire as createRequire4 } from "module";
|
|
5349
|
-
import { join as
|
|
5418
|
+
import { join as join29 } from "path";
|
|
5350
5419
|
|
|
5351
5420
|
// src/roles/typescript/presets/nest.json
|
|
5352
5421
|
var nest_default2 = {
|
|
@@ -5527,8 +5596,8 @@ function readTsconfigAdoption(cwd) {
|
|
|
5527
5596
|
}
|
|
5528
5597
|
|
|
5529
5598
|
// src/roles/typescript/adapters/tsc/plan.ts
|
|
5530
|
-
import { readFileSync as
|
|
5531
|
-
import { join as
|
|
5599
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
5600
|
+
import { join as join28 } from "path";
|
|
5532
5601
|
|
|
5533
5602
|
// src/roles/typescript/typecheck-script.ts
|
|
5534
5603
|
var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
|
|
@@ -5621,7 +5690,7 @@ function planAdoption(context) {
|
|
|
5621
5690
|
};
|
|
5622
5691
|
}
|
|
5623
5692
|
const existing = parseJsonc(
|
|
5624
|
-
|
|
5693
|
+
readFileSync22(join28(context.cwd, target.path), "utf8"),
|
|
5625
5694
|
target.path
|
|
5626
5695
|
);
|
|
5627
5696
|
const extendsChain = composeExtends(existing.extends, preset);
|
|
@@ -5759,7 +5828,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
5759
5828
|
let chain;
|
|
5760
5829
|
try {
|
|
5761
5830
|
const parsed = parseJsonc(
|
|
5762
|
-
|
|
5831
|
+
readFileSync23(join29(cwd, target.path), "utf8"),
|
|
5763
5832
|
target.path
|
|
5764
5833
|
);
|
|
5765
5834
|
chain = parsed.extends;
|
|
@@ -5772,7 +5841,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
5772
5841
|
);
|
|
5773
5842
|
if (preset === void 0) return void 0;
|
|
5774
5843
|
try {
|
|
5775
|
-
createRequire4(
|
|
5844
|
+
createRequire4(join29(cwd, "noop.js")).resolve(preset);
|
|
5776
5845
|
return void 0;
|
|
5777
5846
|
} catch {
|
|
5778
5847
|
return preset;
|
|
@@ -5868,7 +5937,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
5868
5937
|
referencedProjects(cwd, config) {
|
|
5869
5938
|
try {
|
|
5870
5939
|
const parsed = parseJsonc(
|
|
5871
|
-
|
|
5940
|
+
readFileSync23(join29(cwd, config), "utf8"),
|
|
5872
5941
|
config
|
|
5873
5942
|
);
|
|
5874
5943
|
const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
|
|
@@ -5884,7 +5953,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
5884
5953
|
* check.
|
|
5885
5954
|
*/
|
|
5886
5955
|
typecheckTarget(cwd) {
|
|
5887
|
-
if (
|
|
5956
|
+
if (existsSync24(join29(cwd, "tsconfig.json"))) return "tsconfig.json";
|
|
5888
5957
|
const target = resolveTsconfigTarget(cwd);
|
|
5889
5958
|
return target.reason === "none" ? null : target.path;
|
|
5890
5959
|
}
|
|
@@ -6088,7 +6157,7 @@ function replaceLines(current, replacements) {
|
|
|
6088
6157
|
}
|
|
6089
6158
|
|
|
6090
6159
|
// src/core/apply-plan.ts
|
|
6091
|
-
import { existsSync as
|
|
6160
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
6092
6161
|
import { resolve as resolve4, sep } from "path";
|
|
6093
6162
|
import { applyEdits, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
|
|
6094
6163
|
|
|
@@ -6107,7 +6176,7 @@ function resolveWithinRoot(cwd, relativePath) {
|
|
|
6107
6176
|
return absolutePath;
|
|
6108
6177
|
}
|
|
6109
6178
|
function readIfExists(absolutePath) {
|
|
6110
|
-
return
|
|
6179
|
+
return existsSync25(absolutePath) ? readFileSync24(absolutePath, "utf8") : void 0;
|
|
6111
6180
|
}
|
|
6112
6181
|
function* leaves(value, prefix = []) {
|
|
6113
6182
|
for (const [key, keyValue] of Object.entries(value)) {
|
|
@@ -6225,8 +6294,8 @@ function applyPlan(cwd, plan3) {
|
|
|
6225
6294
|
}
|
|
6226
6295
|
|
|
6227
6296
|
// src/core/config/preset-evidence.ts
|
|
6228
|
-
import { existsSync as
|
|
6229
|
-
import { join as
|
|
6297
|
+
import { existsSync as existsSync26, readdirSync as readdirSync3, readFileSync as readFileSync25 } from "fs";
|
|
6298
|
+
import { join as join30 } from "path";
|
|
6230
6299
|
var PATH_SIGNALS = [
|
|
6231
6300
|
{
|
|
6232
6301
|
preset: "nest",
|
|
@@ -6240,11 +6309,11 @@ var DEPENDENCY_SIGNALS = [
|
|
|
6240
6309
|
{ preset: "nest", pattern: /^@nestjs\// }
|
|
6241
6310
|
];
|
|
6242
6311
|
function dependencyNames(cwd) {
|
|
6243
|
-
const path =
|
|
6244
|
-
if (!
|
|
6312
|
+
const path = join30(cwd, "package.json");
|
|
6313
|
+
if (!existsSync26(path)) return [];
|
|
6245
6314
|
try {
|
|
6246
6315
|
const manifest = parseJsonc(
|
|
6247
|
-
|
|
6316
|
+
readFileSync25(path, "utf8"),
|
|
6248
6317
|
path
|
|
6249
6318
|
);
|
|
6250
6319
|
return [
|
|
@@ -6267,7 +6336,7 @@ function declaresJsx(cwd) {
|
|
|
6267
6336
|
for (const name of entries) {
|
|
6268
6337
|
try {
|
|
6269
6338
|
const config = parseJsonc(
|
|
6270
|
-
|
|
6339
|
+
readFileSync25(join30(cwd, name), "utf8"),
|
|
6271
6340
|
name
|
|
6272
6341
|
);
|
|
6273
6342
|
if (config.compilerOptions?.jsx !== void 0) return true;
|
|
@@ -6432,19 +6501,19 @@ export {
|
|
|
6432
6501
|
buildConfigFile,
|
|
6433
6502
|
BaseAdapter,
|
|
6434
6503
|
resolveBin,
|
|
6504
|
+
WORKSPACE_ROOT_MARKER,
|
|
6505
|
+
findWorkspaceRoot,
|
|
6506
|
+
ensureWorkspacePrep,
|
|
6507
|
+
inspectWorkspacePrep,
|
|
6435
6508
|
VERBS,
|
|
6436
6509
|
TARGETS,
|
|
6437
6510
|
LONG_RUNNING_TARGETS,
|
|
6438
6511
|
SWEEPABLE_TARGETS,
|
|
6439
6512
|
PRESET_NAMES,
|
|
6440
|
-
WORKSPACE_ROOT_MARKER,
|
|
6441
|
-
findWorkspaceRoot,
|
|
6442
|
-
ensureWorkspacePrep,
|
|
6443
|
-
inspectWorkspacePrep,
|
|
6444
6513
|
palette,
|
|
6445
6514
|
registerAdapters,
|
|
6446
6515
|
describeFramework,
|
|
6447
6516
|
detectFramework,
|
|
6448
6517
|
dispatch
|
|
6449
6518
|
};
|
|
6450
|
-
//# sourceMappingURL=chunk-
|
|
6519
|
+
//# sourceMappingURL=chunk-MJ3S7LQT.js.map
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.18",
|
|
4
4
|
"description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|