@hublo/sentinel 1.2.0-alpha.10 → 1.2.0-alpha.12
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
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
registerAdapters,
|
|
23
23
|
resolve,
|
|
24
24
|
resolveBin
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-I4ATYZKK.js";
|
|
26
26
|
|
|
27
27
|
// bin/sentinel.ts
|
|
28
28
|
import { program } from "commander";
|
|
@@ -114,7 +114,7 @@ function resolveContext(cwd2, opts2) {
|
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
// src/roles/build/
|
|
117
|
+
// src/roles/build/declined.ts
|
|
118
118
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
119
119
|
import { join as join3 } from "path";
|
|
120
120
|
var DEPRECATED_NX_BUILDER = "@nx/webpack:webpack";
|
|
@@ -128,7 +128,7 @@ function buildsWithDeprecatedExecutor(cwd2) {
|
|
|
128
128
|
return false;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
function
|
|
131
|
+
function explainDecline(cwd2) {
|
|
132
132
|
if (buildConfigFile(cwd2) !== void 0) {
|
|
133
133
|
return ` This module HAS a Vite config, so detection is the likely problem: the build toolchain is declared at the workspace root, which makes a front app detect as "node". Pass --preset to say what it is.`;
|
|
134
134
|
}
|
|
@@ -176,7 +176,7 @@ async function runInit(ctx) {
|
|
|
176
176
|
} catch (error) {
|
|
177
177
|
if (error instanceof PresetUnsupportedError) {
|
|
178
178
|
if (ctx.targetsExplicit) {
|
|
179
|
-
const hint = type === "build" ?
|
|
179
|
+
const hint = type === "build" ? explainDecline(module.root) : ` Pass --preset if it was detected wrongly (hoisted dependencies make detection fall back to "node").`;
|
|
180
180
|
process.stderr.write(
|
|
181
181
|
`
|
|
182
182
|
sentinel (${type}): this module's preset is "${error.preset}", and --${type} has no adapter for it.${hint}
|
|
@@ -504,7 +504,7 @@ function composeDevScript(existing, command) {
|
|
|
504
504
|
if (at === -1) return existing;
|
|
505
505
|
const rest = (chunks[at] ?? "").replace(/^.*?(^|\s|\/)vite(\s|$)/, "");
|
|
506
506
|
const options = appOptions(rest);
|
|
507
|
-
chunks[at] = options === "" ? command : `${command} -- ${options}`;
|
|
507
|
+
chunks[at] = options === "" ? `${command} --` : `${command} -- ${options}`;
|
|
508
508
|
return chunks.join(CHAIN);
|
|
509
509
|
}
|
|
510
510
|
|
|
@@ -656,6 +656,7 @@ var REACT_PLUGIN_SPECIFIERS = ["@vitejs/plugin-react", "@tanstack/react-start"];
|
|
|
656
656
|
function declaredBuildPreset(cwd) {
|
|
657
657
|
const source = readBuildConfigSource(cwd);
|
|
658
658
|
if (source === void 0) {
|
|
659
|
+
if (buildConfigFile(cwd) !== void 0) return void 0;
|
|
659
660
|
return webpackBuildTarget(cwd) === void 0 ? void 0 : "nest";
|
|
660
661
|
}
|
|
661
662
|
if (importsSpecifier(source, BUILD_PRESET_SPECIFIERS.nest)) return "nest";
|
|
@@ -857,9 +858,9 @@ function buildScripts(cwd) {
|
|
|
857
858
|
const own2 = moduleName(cwd);
|
|
858
859
|
scripts[DEV_SCRIPT_NAME] = composeDevScript(
|
|
859
860
|
existingDev,
|
|
860
|
-
//
|
|
861
|
-
//
|
|
862
|
-
`${selfCommand(cwd, "--run --dev") ?? SENTINEL_DEV_COMMAND} --module ${own2}
|
|
861
|
+
// No trailing `--` here: `composeDevScript` owns the separator, and adding one on both
|
|
862
|
+
// sides produced `-- --`, handing Vite an argument nobody wrote.
|
|
863
|
+
`${selfCommand(cwd, "--run --dev") ?? SENTINEL_DEV_COMMAND} --module ${own2}`
|
|
863
864
|
);
|
|
864
865
|
}
|
|
865
866
|
return scripts;
|
|
@@ -873,75 +874,59 @@ function plan(context) {
|
|
|
873
874
|
if (unmet.length > 0) {
|
|
874
875
|
return { operations: [], skipped: describeUnmet(context.preset, unmet) };
|
|
875
876
|
}
|
|
876
|
-
|
|
877
|
+
const declaredPreset2 = declaredBuildPreset(context.cwd);
|
|
878
|
+
const configFile = buildConfigFile(context.cwd);
|
|
879
|
+
if (declaredPreset2 === void 0 && configFile !== void 0) {
|
|
877
880
|
return {
|
|
878
881
|
operations: [],
|
|
879
|
-
skipped: `this module has a Vite config, but it
|
|
882
|
+
skipped: `this module has a Vite config, but it builds neither a React app (no @vitejs/plugin-react or @tanstack/react-start) nor a Nest service (no ${BUILD_PRESET_SPECIFIERS.nest}). Those are the two families this role serves.`
|
|
880
883
|
};
|
|
881
884
|
}
|
|
882
|
-
const notes = [];
|
|
883
|
-
const operations = [];
|
|
884
|
-
const configFile = buildConfigFile(context.cwd);
|
|
885
885
|
const webpackTarget = webpackBuildTarget(context.cwd);
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (webpackTarget === void 0) {
|
|
889
|
-
return {
|
|
890
|
-
operations: [],
|
|
891
|
-
skipped: `already building through sentinel: ${configFile ?? NEST_CONFIG_FILE} imports the nest preset and the nx target runs it. Nothing to change.`
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
const refusal = refusalFor(context.cwd, webpackTarget);
|
|
895
|
-
if (refusal !== void 0) return { operations: [], blocked: refusal };
|
|
896
|
-
const dropped = Object.keys(webpackTarget.configurations ?? {});
|
|
897
|
-
return {
|
|
898
|
-
operations: nestAdoptionOperations(context.cwd, webpackTarget),
|
|
899
|
-
notes: [
|
|
900
|
-
`wrote ${NEST_CONFIG_FILE} and pointed the nx build target at sentinel. The target stays \`nx:run-commands\` with \`forwardAllArgs: false\`, so the image's \`--generatePackageJson\` still works and the Dockerfile needs no change.`,
|
|
901
|
-
...dropped.length > 0 ? [
|
|
902
|
-
`dropped the \`${dropped.join("`, `")}\` configuration${dropped.length > 1 ? "s" : ""} from the build target: its fileReplacements point at files that do not exist, so it replaced nothing. A live one would have blocked this instead.`
|
|
903
|
-
] : [],
|
|
904
|
-
`verify with \`nx run ${webpackTarget.project}:generate-swagger-file\` and \`git diff --exit-code\`: it runs the built bundle, so it proves the service boots AND that its published contract did not move.`
|
|
905
|
-
]
|
|
906
|
-
};
|
|
886
|
+
if (declaredBuildPreset(context.cwd) === "nest" || webpackTarget !== void 0) {
|
|
887
|
+
return planNestService(context, configFile, webpackTarget);
|
|
907
888
|
}
|
|
908
889
|
if (configFile === void 0) {
|
|
909
890
|
return {
|
|
910
891
|
operations: [],
|
|
911
892
|
skipped: `no Vite config in this module, so there is nothing to point at sentinel. This role moves an existing config's imports; it does not introduce a bundler. If this module builds another way (36 services here build through \`@nx/webpack\`), the build role does not apply to it.`
|
|
912
893
|
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
operations
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
if (rewrite.kind === "rewritten") {
|
|
894
|
+
}
|
|
895
|
+
return planReactApp(context, configFile);
|
|
896
|
+
}
|
|
897
|
+
function planReactApp(context, configFile) {
|
|
898
|
+
const notes = [];
|
|
899
|
+
const operations = [];
|
|
900
|
+
const notEsm = esmBlocker(configFile, readProjectPackageJson(context.cwd).type);
|
|
901
|
+
if (notEsm !== void 0) return { operations: [], skipped: notEsm };
|
|
902
|
+
const rewrite = rewriteBuildImports(readConfigSource(context.cwd, configFile), configFile);
|
|
903
|
+
if (rewrite.kind === "blocked") {
|
|
904
|
+
return {
|
|
905
|
+
operations: [],
|
|
906
|
+
skipped: `${configFile} could not be pointed at sentinel, so nothing was written: ${rewrite.why}. Nothing here is broken; this needs a look before the role applies.`
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
if (rewrite.kind === "rewritten") {
|
|
910
|
+
operations.push({ kind: "write", path: configFile, contents: rewrite.source });
|
|
911
|
+
}
|
|
912
|
+
for (const name of COMPANION_CONFIG_FILES) {
|
|
913
|
+
const source = readConfigSource(context.cwd, name);
|
|
914
|
+
if (source === "") continue;
|
|
915
|
+
const companion = rewriteBuildImports(source, name);
|
|
916
|
+
if (companion.kind === "rewritten") {
|
|
917
|
+
operations.push({ kind: "write", path: name, contents: companion.source });
|
|
918
|
+
notes.push(`${name} now imports ${companion.moved.join(", ")} from sentinel too.`);
|
|
919
|
+
} else if (companion.kind === "blocked") {
|
|
940
920
|
notes.push(
|
|
941
|
-
`${
|
|
921
|
+
`${name} imports the toolchain and could NOT be pointed at sentinel: ${companion.why}. It will stop resolving when the workspace root drops these packages, and it will fail your TESTS rather than your build.`
|
|
942
922
|
);
|
|
943
923
|
}
|
|
944
924
|
}
|
|
925
|
+
if (rewrite.kind === "rewritten") {
|
|
926
|
+
notes.push(
|
|
927
|
+
`${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.`
|
|
928
|
+
);
|
|
929
|
+
}
|
|
945
930
|
operations.push(manifestOperation(context.cwd, buildScripts(context.cwd)));
|
|
946
931
|
operations.push(...nxTargetOperations({ cwd: context.cwd, targets: buildTarget() }));
|
|
947
932
|
const owned = ownedBuildDependencies(context.cwd);
|
|
@@ -953,6 +938,27 @@ function plan(context) {
|
|
|
953
938
|
}
|
|
954
939
|
return { operations, notes };
|
|
955
940
|
}
|
|
941
|
+
function planNestService(context, configFile, webpackTarget) {
|
|
942
|
+
if (webpackTarget === void 0) {
|
|
943
|
+
return {
|
|
944
|
+
operations: [],
|
|
945
|
+
skipped: `already building through sentinel: ${configFile ?? NEST_CONFIG_FILE} imports the nest preset and the nx target runs it. Nothing to change.`
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
const refusal = refusalFor(context.cwd, webpackTarget);
|
|
949
|
+
if (refusal !== void 0) return { operations: [], blocked: refusal };
|
|
950
|
+
const dropped = Object.keys(webpackTarget.configurations ?? {});
|
|
951
|
+
return {
|
|
952
|
+
operations: nestAdoptionOperations(context.cwd, webpackTarget),
|
|
953
|
+
notes: [
|
|
954
|
+
`wrote ${NEST_CONFIG_FILE} and pointed the nx build target at sentinel. The target stays \`nx:run-commands\` with \`forwardAllArgs: false\`, so the image's \`--generatePackageJson\` still works and the Dockerfile needs no change.`,
|
|
955
|
+
...dropped.length > 0 ? [
|
|
956
|
+
`dropped the \`${dropped.join("`, `")}\` configuration${dropped.length > 1 ? "s" : ""} from the build target: its fileReplacements point at files that do not exist, so it replaced nothing. A live one would have blocked this instead.`
|
|
957
|
+
] : [],
|
|
958
|
+
`verify with \`nx run ${webpackTarget.project}:generate-swagger-file\` and \`git diff --exit-code\`: it runs the built bundle, so it proves the service boots AND that its published contract did not move.`
|
|
959
|
+
]
|
|
960
|
+
};
|
|
961
|
+
}
|
|
956
962
|
function readConfigSource(cwd, configFile) {
|
|
957
963
|
if (!existsSync8(join8(cwd, configFile))) return "";
|
|
958
964
|
try {
|
|
@@ -6427,4 +6433,4 @@ export {
|
|
|
6427
6433
|
detectFramework,
|
|
6428
6434
|
dispatch
|
|
6429
6435
|
};
|
|
6430
|
-
//# sourceMappingURL=chunk-
|
|
6436
|
+
//# sourceMappingURL=chunk-I4ATYZKK.js.map
|
package/dist/index.js
CHANGED
|
@@ -93,8 +93,9 @@ var DEFAULT_PROVIDED_BY_IMAGE = ["@prisma"];
|
|
|
93
93
|
var externalPackages = (bundle) => {
|
|
94
94
|
const emitted = new Set(Object.keys(bundle));
|
|
95
95
|
const packages = /* @__PURE__ */ new Set();
|
|
96
|
-
for (const
|
|
97
|
-
|
|
96
|
+
for (const emittedFile of Object.values(bundle)) {
|
|
97
|
+
if (emittedFile.type !== "chunk") continue;
|
|
98
|
+
for (const imported of emittedFile.imports) {
|
|
98
99
|
if (emitted.has(imported)) continue;
|
|
99
100
|
if (imported.startsWith(".") || imported.startsWith("/")) continue;
|
|
100
101
|
if (isBuiltin(imported)) continue;
|
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.12",
|
|
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",
|