@hublo/sentinel 1.2.0-alpha.26 → 1.2.0-alpha.28
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
CHANGED
|
@@ -241,9 +241,16 @@ function workspaceRootHops(cwd, target) {
|
|
|
241
241
|
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
242
242
|
import { join as join5 } from "path";
|
|
243
243
|
|
|
244
|
-
// src/
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
// src/core/config/module-type.ts
|
|
245
|
+
function esmReadiness(fileName, packageType) {
|
|
246
|
+
if (/\.(mts|mjs)$/.test(fileName)) return { kind: "ready" };
|
|
247
|
+
if (packageType === "module") return { kind: "ready" };
|
|
248
|
+
const rename = fileName.replace(/\.(ts|js)$/, ".mts");
|
|
249
|
+
return {
|
|
250
|
+
kind: "blocked",
|
|
251
|
+
why: `sentinel is ESM only, and this module ${packageType === void 0 ? 'declares no `"type"`' : `declares \`"type": "${packageType}"\``}, so Node loads ${fileName} as CommonJS and the import fails. Two remedies, and adoption takes neither by itself because both reach beyond this build: add \`"type": "module"\` to this module's package.json, which changes how EVERY \`.js\` here loads, or rename the config to \`${rename}\`, which settles it in the filename where nothing can undo it.`
|
|
252
|
+
};
|
|
253
|
+
}
|
|
247
254
|
|
|
248
255
|
// src/core/config/manifest.ts
|
|
249
256
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
@@ -406,7 +413,9 @@ var SENTINEL_OWNED_BUILD_PACKAGES = OWNED_PACKAGES.map(
|
|
|
406
413
|
(entry) => entry.package
|
|
407
414
|
);
|
|
408
415
|
|
|
409
|
-
// src/roles/build/
|
|
416
|
+
// src/roles/build/project-json.ts
|
|
417
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
418
|
+
import { join as join4 } from "path";
|
|
410
419
|
function projectTargets(cwd) {
|
|
411
420
|
const path = join4(cwd, "project.json");
|
|
412
421
|
if (!existsSync4(path)) return void 0;
|
|
@@ -416,6 +425,8 @@ function projectTargets(cwd) {
|
|
|
416
425
|
return void 0;
|
|
417
426
|
}
|
|
418
427
|
}
|
|
428
|
+
|
|
429
|
+
// src/roles/build/adoption-drift.ts
|
|
419
430
|
function buildAdoptionDrift(cwd) {
|
|
420
431
|
const drift = [];
|
|
421
432
|
const manifest = readProjectPackageJson(cwd);
|
|
@@ -457,6 +468,12 @@ function buildAdoptionDrift(cwd) {
|
|
|
457
468
|
`still declares a \`${BUILD_SCRIPT_NAME}\` target in project.json beside the one in package.json, so the module has two and which runs depends on the caller`
|
|
458
469
|
);
|
|
459
470
|
}
|
|
471
|
+
const devScript = moduleScripts(cwd)[DEV_SCRIPT_NAME];
|
|
472
|
+
if (devScript?.includes(SENTINEL_DEV_COMMAND) === true && projectTargets(cwd)?.[DEV_SCRIPT_NAME] !== void 0) {
|
|
473
|
+
drift.push(
|
|
474
|
+
`runs its \`${DEV_SCRIPT_NAME}\` script through sentinel but still declares a \`${DEV_SCRIPT_NAME}\` target in project.json, so one dev server has two declarations and editing the target stops the script from being what runs`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
460
477
|
return drift;
|
|
461
478
|
}
|
|
462
479
|
|
|
@@ -511,7 +528,10 @@ function readBuildAdoption(cwd) {
|
|
|
511
528
|
} catch (error) {
|
|
512
529
|
return NOT_ADOPTED(configFile, error instanceof Error ? error.message : String(error));
|
|
513
530
|
}
|
|
514
|
-
if (!importsPreset(source))
|
|
531
|
+
if (!importsPreset(source)) {
|
|
532
|
+
const esm = esmReadiness(configFile, readProjectPackageJson(cwd).type);
|
|
533
|
+
return NOT_ADOPTED(configFile, esm.kind === "blocked" ? esm.why : null);
|
|
534
|
+
}
|
|
515
535
|
const manifest = readProjectPackageJson(cwd);
|
|
516
536
|
const declared = { ...manifest.dependencies, ...manifest.devDependencies };
|
|
517
537
|
const ownDeclarations = SENTINEL_OWNED_BUILD_PACKAGES.filter((name) => name in declared).map(
|
|
@@ -886,6 +906,43 @@ function composeDevScript(existing, command) {
|
|
|
886
906
|
return chunks.join(CHAIN);
|
|
887
907
|
}
|
|
888
908
|
|
|
909
|
+
// src/roles/build/dev-target.ts
|
|
910
|
+
var DELEGATION_KEYS = /* @__PURE__ */ new Set(["executor", "options"]);
|
|
911
|
+
var DELEGATION_OPTION_KEYS = /* @__PURE__ */ new Set(["command", "cwd"]);
|
|
912
|
+
function delegatesToScript(target, scriptName) {
|
|
913
|
+
if (typeof target !== "object" || target === null || Array.isArray(target)) return false;
|
|
914
|
+
const entries = target;
|
|
915
|
+
if (!Object.keys(entries).every((key) => DELEGATION_KEYS.has(key))) return false;
|
|
916
|
+
if (entries["executor"] !== "nx:run-commands") return false;
|
|
917
|
+
const options = entries["options"];
|
|
918
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) return false;
|
|
919
|
+
const declared = options;
|
|
920
|
+
if (!Object.keys(declared).every((key) => DELEGATION_OPTION_KEYS.has(key))) return false;
|
|
921
|
+
const command = declared["command"];
|
|
922
|
+
if (typeof command !== "string") return false;
|
|
923
|
+
return new RegExp(String.raw`(^|\s)run\s+${scriptName}$`).test(command.trim());
|
|
924
|
+
}
|
|
925
|
+
function devScriptIsAdopted(devScript) {
|
|
926
|
+
return devScript !== void 0 && devScript.includes(SENTINEL_DEV_COMMAND);
|
|
927
|
+
}
|
|
928
|
+
function devTargetOperations(cwd, devScript) {
|
|
929
|
+
if (!devScriptIsAdopted(devScript)) return { operations: [] };
|
|
930
|
+
const target = projectTargets(cwd)?.[DEV_SCRIPT_NAME];
|
|
931
|
+
if (target === void 0) return { operations: [] };
|
|
932
|
+
if (!delegatesToScript(target, DEV_SCRIPT_NAME)) {
|
|
933
|
+
return {
|
|
934
|
+
operations: [],
|
|
935
|
+
note: `left the \`${DEV_SCRIPT_NAME}\` target in project.json alone: it does more than call \`pnpm run ${DEV_SCRIPT_NAME}\`, so removing it would drop behaviour this role never declared. Move what it does into the script, or keep it and accept the second home.`
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
return {
|
|
939
|
+
operations: [
|
|
940
|
+
{ kind: "remove-json-keys", path: "project.json", keys: [["targets", DEV_SCRIPT_NAME]] }
|
|
941
|
+
],
|
|
942
|
+
note: `removed the \`${DEV_SCRIPT_NAME}\` target from project.json: it only called \`pnpm run ${DEV_SCRIPT_NAME}\`, which nx infers from the script itself. host-admin has run without that target all along.`
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
|
|
889
946
|
// src/roles/build/nest/adopt.ts
|
|
890
947
|
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
891
948
|
import { join as join10 } from "path";
|
|
@@ -977,11 +1034,6 @@ function describeUnmet(preset, unmet) {
|
|
|
977
1034
|
// src/core/config/rewrite-imports.ts
|
|
978
1035
|
import { parseSync } from "oxc-parser";
|
|
979
1036
|
var movedSpecifiers = (toolchain) => new Set(toolchain.owned.map((entry) => entry.specifier));
|
|
980
|
-
function esmBlocker(fileName, packageType) {
|
|
981
|
-
if (/\.(mts|mjs)$/.test(fileName)) return void 0;
|
|
982
|
-
if (packageType === "module") return void 0;
|
|
983
|
-
return `sentinel is ESM only, and this module does not declare \`"type": "module"\`, so Vite would load ${fileName} as CommonJS and fail to require it. Add \`"type": "module"\` to this module's package.json, or rename the config to \`${fileName.replace(/\.(ts|js)$/, ".m$1")}\`, then run this again.`;
|
|
984
|
-
}
|
|
985
1037
|
var defaultExportNames = (toolchain) => Object.fromEntries(
|
|
986
1038
|
toolchain.owned.filter((entry) => entry.default !== void 0).map((entry) => [entry.specifier, entry.default])
|
|
987
1039
|
);
|
|
@@ -1152,8 +1204,8 @@ function plan(context) {
|
|
|
1152
1204
|
function planReactApp(context, configFile) {
|
|
1153
1205
|
const notes = [];
|
|
1154
1206
|
const operations = [];
|
|
1155
|
-
const
|
|
1156
|
-
if (
|
|
1207
|
+
const esm = esmReadiness(configFile, readProjectPackageJson(context.cwd).type);
|
|
1208
|
+
if (esm.kind === "blocked") return { operations: [], skipped: esm.why };
|
|
1157
1209
|
const rewrite = rewriteBuildImports(readConfigSource(context.cwd, configFile), configFile);
|
|
1158
1210
|
if (rewrite.kind === "blocked") {
|
|
1159
1211
|
return {
|
|
@@ -1182,7 +1234,8 @@ function planReactApp(context, configFile) {
|
|
|
1182
1234
|
`${configFile} now imports ${rewrite.moved.join(", ")} from \`${BUILD_PRESET_SPECIFIER}\`. Only the import lines changed: every attribute, alias and path is untouched, so this build produces what it produced before.`
|
|
1183
1235
|
);
|
|
1184
1236
|
}
|
|
1185
|
-
|
|
1237
|
+
const scripts = buildScripts(context.cwd);
|
|
1238
|
+
operations.push(manifestOperation(context.cwd, scripts));
|
|
1186
1239
|
operations.push(
|
|
1187
1240
|
...nxTargetOperations({
|
|
1188
1241
|
cwd: context.cwd,
|
|
@@ -1192,6 +1245,9 @@ function planReactApp(context, configFile) {
|
|
|
1192
1245
|
})
|
|
1193
1246
|
})
|
|
1194
1247
|
);
|
|
1248
|
+
const dev = devTargetOperations(context.cwd, scripts[DEV_SCRIPT_NAME]);
|
|
1249
|
+
operations.push(...dev.operations);
|
|
1250
|
+
if (dev.note !== void 0) notes.push(dev.note);
|
|
1195
1251
|
const owned = ownedBuildDependencies(context.cwd);
|
|
1196
1252
|
if (owned.length > 0) {
|
|
1197
1253
|
operations.push({ kind: "remove-json-keys", path: "package.json", keys: owned });
|
|
@@ -6631,4 +6687,4 @@ export {
|
|
|
6631
6687
|
detectFramework,
|
|
6632
6688
|
dispatch
|
|
6633
6689
|
};
|
|
6634
|
-
//# sourceMappingURL=chunk-
|
|
6690
|
+
//# sourceMappingURL=chunk-LNSAUFIM.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.28",
|
|
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",
|