@hublo/sentinel 1.2.0-alpha.25 → 1.2.0-alpha.27
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-C4BWV6SU.js → chunk-LNSAUFIM.js} +305 -218
- package/dist/index.js +1 -1
- package/package.json +1 -1
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(
|
|
@@ -591,8 +611,8 @@ function binSearchPath(cwd) {
|
|
|
591
611
|
}
|
|
592
612
|
|
|
593
613
|
// src/roles/build/plan.ts
|
|
594
|
-
import { existsSync as
|
|
595
|
-
import { join as
|
|
614
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
615
|
+
import { join as join11 } from "path";
|
|
596
616
|
|
|
597
617
|
// src/core/config/existing-command.ts
|
|
598
618
|
import { readFileSync as readFileSync6 } from "fs";
|
|
@@ -711,6 +731,161 @@ function keepsOtherCommands(script, sentinelCommand) {
|
|
|
711
731
|
return script.split(SEGMENT_SEPARATOR).filter((_, index) => !isSeparatorAt(index)).some((segment) => segment.trim() !== "" && segment.trim() !== sentinelCommand);
|
|
712
732
|
}
|
|
713
733
|
|
|
734
|
+
// src/roles/format/read-adoption.ts
|
|
735
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
736
|
+
import { join as join9 } from "path";
|
|
737
|
+
|
|
738
|
+
// src/roles/format/config-policy.ts
|
|
739
|
+
var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
|
|
740
|
+
var FORMAT_SCRIPT_NAME = "format";
|
|
741
|
+
var PROVENANCE_KEY = "$sentinel";
|
|
742
|
+
var PERMITTED_LOCAL_KEYS = [
|
|
743
|
+
"useTabs",
|
|
744
|
+
"tabWidth",
|
|
745
|
+
"printWidth",
|
|
746
|
+
"semi",
|
|
747
|
+
"singleQuote",
|
|
748
|
+
"jsxSingleQuote",
|
|
749
|
+
"trailingComma",
|
|
750
|
+
"quoteProps",
|
|
751
|
+
"bracketSpacing",
|
|
752
|
+
"bracketSameLine",
|
|
753
|
+
"arrowParens",
|
|
754
|
+
"endOfLine",
|
|
755
|
+
"objectWrap",
|
|
756
|
+
"proseWrap",
|
|
757
|
+
"experimentalOperatorPosition"
|
|
758
|
+
];
|
|
759
|
+
var ALWAYS_LOCAL_KEYS = ["ignorePatterns", "overrides"];
|
|
760
|
+
var FORMAT_DEFAULT_IGNORES = ["**/*.toml"];
|
|
761
|
+
var PRETTIER_CONFIG_FILES = [
|
|
762
|
+
".prettierrc",
|
|
763
|
+
".prettierrc.json",
|
|
764
|
+
".prettierrc.json5",
|
|
765
|
+
".prettierrc.yml",
|
|
766
|
+
".prettierrc.yaml",
|
|
767
|
+
".prettierrc.js",
|
|
768
|
+
".prettierrc.cjs",
|
|
769
|
+
".prettierrc.mjs",
|
|
770
|
+
"prettier.config.js",
|
|
771
|
+
"prettier.config.cjs",
|
|
772
|
+
"prettier.config.mjs"
|
|
773
|
+
];
|
|
774
|
+
function formatTargets() {
|
|
775
|
+
return {
|
|
776
|
+
[FORMAT_SCRIPT_NAME]: {
|
|
777
|
+
cache: true,
|
|
778
|
+
inputs: ["default", `{projectRoot}/${FORMAT_CONFIG_FILE}`]
|
|
779
|
+
},
|
|
780
|
+
[`${FORMAT_SCRIPT_NAME}:fix`]: { cache: false }
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// src/roles/format/presets/base.json
|
|
785
|
+
var base_default = {
|
|
786
|
+
printWidth: 80,
|
|
787
|
+
semi: false,
|
|
788
|
+
singleQuote: true,
|
|
789
|
+
trailingComma: "all",
|
|
790
|
+
sortPackageJson: false,
|
|
791
|
+
sortImports: false
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
// src/roles/format/presets/nest-imports.json
|
|
795
|
+
var nest_imports_default = {
|
|
796
|
+
customGroups: [
|
|
797
|
+
{
|
|
798
|
+
groupName: "workspace",
|
|
799
|
+
elementNamePattern: ["@hublo/**", "@shared/**", "@front/**", "@network/**"]
|
|
800
|
+
}
|
|
801
|
+
],
|
|
802
|
+
groups: ["builtin", "external", "workspace", ["parent", "index"], "sibling"],
|
|
803
|
+
newlinesBetween: true,
|
|
804
|
+
order: "asc",
|
|
805
|
+
ignoreCase: false
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// src/roles/format/preset-data.ts
|
|
809
|
+
var FORMAT_PRESETS = ["base", "svelte", "nest"];
|
|
810
|
+
function hasFormatPreset(name) {
|
|
811
|
+
return FORMAT_PRESETS.includes(name);
|
|
812
|
+
}
|
|
813
|
+
function formatPresetName(declared) {
|
|
814
|
+
if (declared === "svelte") return "svelte";
|
|
815
|
+
if (declared === "nest") return "nest";
|
|
816
|
+
return "base";
|
|
817
|
+
}
|
|
818
|
+
function formatPresetFor(preset) {
|
|
819
|
+
const base = base_default;
|
|
820
|
+
const name = formatPresetName(preset);
|
|
821
|
+
if (name === "svelte") return { ...base, svelte: true };
|
|
822
|
+
if (name === "nest") return { ...base, sortImports: nest_imports_default };
|
|
823
|
+
return base;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/roles/format/read-adoption.ts
|
|
827
|
+
var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
|
|
828
|
+
configFile,
|
|
829
|
+
preset: null,
|
|
830
|
+
adopted: false,
|
|
831
|
+
conformant: false,
|
|
832
|
+
drift: [],
|
|
833
|
+
local: {},
|
|
834
|
+
presetVersion: null,
|
|
835
|
+
effective: {},
|
|
836
|
+
unreadable
|
|
837
|
+
});
|
|
838
|
+
function sameValue(a, b) {
|
|
839
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
840
|
+
}
|
|
841
|
+
function readFormatAdoption(cwd) {
|
|
842
|
+
const path = join9(cwd, FORMAT_CONFIG_FILE);
|
|
843
|
+
if (!existsSync9(path)) return NOT_ADOPTED2(null);
|
|
844
|
+
let parsed;
|
|
845
|
+
try {
|
|
846
|
+
parsed = parseJsonc(readFileSync7(path, "utf8"), FORMAT_CONFIG_FILE);
|
|
847
|
+
} catch (error) {
|
|
848
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
849
|
+
return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
|
|
850
|
+
}
|
|
851
|
+
const provenance = parsed[PROVENANCE_KEY];
|
|
852
|
+
if (!provenance || typeof provenance.preset !== "string") return NOT_ADOPTED2(FORMAT_CONFIG_FILE);
|
|
853
|
+
if (!hasFormatPreset(provenance.preset)) {
|
|
854
|
+
return NOT_ADOPTED2(
|
|
855
|
+
FORMAT_CONFIG_FILE,
|
|
856
|
+
`${FORMAT_CONFIG_FILE} declares the format preset "${provenance.preset}", which sentinel does not ship (shipped: ${FORMAT_PRESETS.join(", ")}). Re-run \`sentinel --init --format\`.`
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
const declaredLocal = Array.isArray(provenance.local) ? provenance.local : [];
|
|
860
|
+
const preset = formatPresetFor(provenance.preset);
|
|
861
|
+
const drift = [];
|
|
862
|
+
const local = {};
|
|
863
|
+
for (const [key, expected] of Object.entries(preset)) {
|
|
864
|
+
if (declaredLocal.includes(key)) {
|
|
865
|
+
local[key] = parsed[key];
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
if (!(key in parsed) || !sameValue(parsed[key], expected)) drift.push(key);
|
|
869
|
+
}
|
|
870
|
+
for (const key of declaredLocal) {
|
|
871
|
+
if (!(key in preset)) local[key] = parsed[key];
|
|
872
|
+
}
|
|
873
|
+
for (const key of ALWAYS_LOCAL_KEYS) {
|
|
874
|
+
if (key in parsed) local[key] = parsed[key];
|
|
875
|
+
}
|
|
876
|
+
return {
|
|
877
|
+
configFile: FORMAT_CONFIG_FILE,
|
|
878
|
+
preset: provenance.preset,
|
|
879
|
+
adopted: true,
|
|
880
|
+
conformant: drift.length === 0,
|
|
881
|
+
drift,
|
|
882
|
+
local,
|
|
883
|
+
presetVersion: typeof provenance.version === "string" ? provenance.version : null,
|
|
884
|
+
effective: parsed,
|
|
885
|
+
unreadable: null
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
|
|
714
889
|
// src/roles/build/dev-script.ts
|
|
715
890
|
var CHAIN = " -- ";
|
|
716
891
|
var VITE_TOKEN = /(^|\s|\/)vite(\s|$)/;
|
|
@@ -731,14 +906,76 @@ function composeDevScript(existing, command) {
|
|
|
731
906
|
return chunks.join(CHAIN);
|
|
732
907
|
}
|
|
733
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
|
+
|
|
734
946
|
// src/roles/build/nest/adopt.ts
|
|
735
|
-
import { existsSync as
|
|
736
|
-
import { join as
|
|
947
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
948
|
+
import { join as join10 } from "path";
|
|
737
949
|
var NEST_CONFIG_FILE = "vite.config.mts";
|
|
950
|
+
function asSource(value, depth) {
|
|
951
|
+
const pad = " ".repeat(depth);
|
|
952
|
+
const inner = " ".repeat(depth + 1);
|
|
953
|
+
if (Array.isArray(value)) {
|
|
954
|
+
if (value.length === 0) return "[]";
|
|
955
|
+
return `[
|
|
956
|
+
${value.map((item) => `${inner}${asSource(item, depth + 1)}`).join(",\n")},
|
|
957
|
+
${pad}]`;
|
|
958
|
+
}
|
|
959
|
+
if (value !== null && typeof value === "object") {
|
|
960
|
+
const entries = Object.entries(value);
|
|
961
|
+
if (entries.length === 0) return "{}";
|
|
962
|
+
return `{
|
|
963
|
+
${entries.map(([key, item]) => `${inner}${asKey(key)}: ${asSource(item, depth + 1)}`).join(",\n")},
|
|
964
|
+
${pad}}`;
|
|
965
|
+
}
|
|
966
|
+
if (typeof value === "string") return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
967
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
968
|
+
throw new Error(
|
|
969
|
+
`sentinel build(nest): cannot write ${typeof value} into the generated config. The build target carries a shape this translation was not written for, and it should refuse rather than emit something nobody has read.`
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
function asKey(key) {
|
|
973
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
|
|
974
|
+
}
|
|
738
975
|
function nestConfigSource(cwd, target) {
|
|
739
976
|
const hops = workspaceRootHops(cwd, target);
|
|
740
977
|
const up = Array.from({ length: hops }, () => "..").join("/");
|
|
741
|
-
const carried = (name, value) => value === void 0 || value.length === 0 ? "" : ` ${name}: ${
|
|
978
|
+
const carried = (name, value) => value === void 0 || value.length === 0 ? "" : ` ${name}: ${asSource(value, 1)},
|
|
742
979
|
`;
|
|
743
980
|
return `import path from 'node:path'
|
|
744
981
|
|
|
@@ -757,9 +994,9 @@ function nestBuildOutputs(target) {
|
|
|
757
994
|
}
|
|
758
995
|
var OUT_DIR_IN_CONFIG = /^\s*outDir:\s*'([^']+)'/m;
|
|
759
996
|
function nestOutputsFromConfig(cwd) {
|
|
760
|
-
const configPath =
|
|
761
|
-
if (!
|
|
762
|
-
const outDir = OUT_DIR_IN_CONFIG.exec(
|
|
997
|
+
const configPath = join10(cwd, NEST_CONFIG_FILE);
|
|
998
|
+
if (!existsSync10(configPath)) return void 0;
|
|
999
|
+
const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync8(configPath, "utf8"))?.[1];
|
|
763
1000
|
return outDir === void 0 ? void 0 : [`{workspaceRoot}/${outDir}`];
|
|
764
1001
|
}
|
|
765
1002
|
function nestAdoptionOperations(cwd, target) {
|
|
@@ -797,11 +1034,6 @@ function describeUnmet(preset, unmet) {
|
|
|
797
1034
|
// src/core/config/rewrite-imports.ts
|
|
798
1035
|
import { parseSync } from "oxc-parser";
|
|
799
1036
|
var movedSpecifiers = (toolchain) => new Set(toolchain.owned.map((entry) => entry.specifier));
|
|
800
|
-
function esmBlocker(fileName, packageType) {
|
|
801
|
-
if (/\.(mts|mjs)$/.test(fileName)) return void 0;
|
|
802
|
-
if (packageType === "module") return void 0;
|
|
803
|
-
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.`;
|
|
804
|
-
}
|
|
805
1037
|
var defaultExportNames = (toolchain) => Object.fromEntries(
|
|
806
1038
|
toolchain.owned.filter((entry) => entry.default !== void 0).map((entry) => [entry.specifier, entry.default])
|
|
807
1039
|
);
|
|
@@ -972,8 +1204,8 @@ function plan(context) {
|
|
|
972
1204
|
function planReactApp(context, configFile) {
|
|
973
1205
|
const notes = [];
|
|
974
1206
|
const operations = [];
|
|
975
|
-
const
|
|
976
|
-
if (
|
|
1207
|
+
const esm = esmReadiness(configFile, readProjectPackageJson(context.cwd).type);
|
|
1208
|
+
if (esm.kind === "blocked") return { operations: [], skipped: esm.why };
|
|
977
1209
|
const rewrite = rewriteBuildImports(readConfigSource(context.cwd, configFile), configFile);
|
|
978
1210
|
if (rewrite.kind === "blocked") {
|
|
979
1211
|
return {
|
|
@@ -1002,7 +1234,8 @@ function planReactApp(context, configFile) {
|
|
|
1002
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.`
|
|
1003
1235
|
);
|
|
1004
1236
|
}
|
|
1005
|
-
|
|
1237
|
+
const scripts = buildScripts(context.cwd);
|
|
1238
|
+
operations.push(manifestOperation(context.cwd, scripts));
|
|
1006
1239
|
operations.push(
|
|
1007
1240
|
...nxTargetOperations({
|
|
1008
1241
|
cwd: context.cwd,
|
|
@@ -1012,6 +1245,9 @@ function planReactApp(context, configFile) {
|
|
|
1012
1245
|
})
|
|
1013
1246
|
})
|
|
1014
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);
|
|
1015
1251
|
const owned = ownedBuildDependencies(context.cwd);
|
|
1016
1252
|
if (owned.length > 0) {
|
|
1017
1253
|
operations.push({ kind: "remove-json-keys", path: "package.json", keys: owned });
|
|
@@ -1019,6 +1255,10 @@ function planReactApp(context, configFile) {
|
|
|
1019
1255
|
`removed ${owned.map(([, name]) => name).join(", ")} from this module: sentinel owns them now, and two copies of Vite in one build give the plugins a different Vite than the one running them.`
|
|
1020
1256
|
);
|
|
1021
1257
|
}
|
|
1258
|
+
const formatted = readFormatAdoption(context.cwd).adopted;
|
|
1259
|
+
notes.push(
|
|
1260
|
+
formatted ? `run \`sentinel --run --format --fix\` on this module: adoption rewrote ${configFile}, and a rewritten import can be longer than your formatter wraps at.` : `this module is formatted by the workspace, not by sentinel, so format ${configFile} with whatever owns it before committing: a rewritten import can be longer than that formatter wraps at, and the check would fail on a file nobody typed.`
|
|
1261
|
+
);
|
|
1022
1262
|
notes.push(
|
|
1023
1263
|
`this config is code, and it runs before the build does: any environment variable it reads has to be present wherever you build, including a fresh clone, another CI job or an image. Adoption does not change what it reads, but a failure there arrives early and names this role rather than the variable.`
|
|
1024
1264
|
);
|
|
@@ -1059,9 +1299,9 @@ function planNestService(context, webpackTarget) {
|
|
|
1059
1299
|
};
|
|
1060
1300
|
}
|
|
1061
1301
|
function readConfigSource(cwd, configFile) {
|
|
1062
|
-
if (!
|
|
1302
|
+
if (!existsSync11(join11(cwd, configFile))) return "";
|
|
1063
1303
|
try {
|
|
1064
|
-
return
|
|
1304
|
+
return readFileSync9(join11(cwd, configFile), "utf8");
|
|
1065
1305
|
} catch {
|
|
1066
1306
|
return "";
|
|
1067
1307
|
}
|
|
@@ -1246,12 +1486,12 @@ var ViteDevAdapter = class extends ViteRoleAdapter {
|
|
|
1246
1486
|
};
|
|
1247
1487
|
|
|
1248
1488
|
// src/roles/build/declared-outputs.ts
|
|
1249
|
-
import { existsSync as
|
|
1250
|
-
import { join as
|
|
1489
|
+
import { existsSync as existsSync13, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1490
|
+
import { join as join13 } from "path";
|
|
1251
1491
|
|
|
1252
1492
|
// src/core/workspace-prep.ts
|
|
1253
|
-
import { existsSync as
|
|
1254
|
-
import { dirname as dirname3, join as
|
|
1493
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync } from "fs";
|
|
1494
|
+
import { dirname as dirname3, join as join12, relative as relative2 } from "path";
|
|
1255
1495
|
|
|
1256
1496
|
// src/core/settings.ts
|
|
1257
1497
|
var WORKSPACE_ROOT_MARKER = "nx.json";
|
|
@@ -1266,7 +1506,7 @@ var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
|
|
|
1266
1506
|
function findWorkspaceRoot(startDir) {
|
|
1267
1507
|
let dir = startDir;
|
|
1268
1508
|
for (; ; ) {
|
|
1269
|
-
if (
|
|
1509
|
+
if (existsSync12(join12(dir, WORKSPACE_ROOT_MARKER))) return dir;
|
|
1270
1510
|
const parent = dirname3(dir);
|
|
1271
1511
|
if (parent === dir) return void 0;
|
|
1272
1512
|
dir = parent;
|
|
@@ -1279,9 +1519,9 @@ function declaredNativeTs(pkg) {
|
|
|
1279
1519
|
return version || void 0;
|
|
1280
1520
|
}
|
|
1281
1521
|
function ensureI18nextSingleton(root, dryRun) {
|
|
1282
|
-
const pkgPath =
|
|
1283
|
-
if (!
|
|
1284
|
-
const pkg = JSON.parse(
|
|
1522
|
+
const pkgPath = join12(root, "package.json");
|
|
1523
|
+
if (!existsSync12(pkgPath)) return void 0;
|
|
1524
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
|
|
1285
1525
|
const want = declaredNativeTs(pkg);
|
|
1286
1526
|
if (!want) return void 0;
|
|
1287
1527
|
const have = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
@@ -1294,10 +1534,10 @@ function ensureI18nextSingleton(root, dryRun) {
|
|
|
1294
1534
|
return `pinned ${OVERRIDE_KEY} to ${want} in package.json (i18next singleton)`;
|
|
1295
1535
|
}
|
|
1296
1536
|
function ensureReleaseAgeAllowList(root, dryRun) {
|
|
1297
|
-
const yamlPath =
|
|
1298
|
-
if (!
|
|
1537
|
+
const yamlPath = join12(root, WORKSPACE_YAML);
|
|
1538
|
+
if (!existsSync12(yamlPath)) return void 0;
|
|
1299
1539
|
const own = readOwnPackage().name;
|
|
1300
|
-
const lines =
|
|
1540
|
+
const lines = readFileSync10(yamlPath, "utf8").split("\n");
|
|
1301
1541
|
const keyIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === `${RELEASE_AGE_KEY}:`);
|
|
1302
1542
|
if (keyIdx === -1) return void 0;
|
|
1303
1543
|
let lastItemIdx = keyIdx;
|
|
@@ -1332,11 +1572,11 @@ var ROOT_PRETTIER_CONFIGS = [
|
|
|
1332
1572
|
function ensureFormatterExclusion(root, moduleDir, dryRun) {
|
|
1333
1573
|
const rel = relative2(root, moduleDir).replaceAll("\\", "/");
|
|
1334
1574
|
if (rel === "" || rel.startsWith("..")) return void 0;
|
|
1335
|
-
const ignorePath =
|
|
1336
|
-
const hasPrettier =
|
|
1575
|
+
const ignorePath = join12(root, PRETTIER_IGNORE);
|
|
1576
|
+
const hasPrettier = existsSync12(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync12(join12(root, name)));
|
|
1337
1577
|
if (!hasPrettier) return void 0;
|
|
1338
1578
|
const pattern = `/${rel}/`;
|
|
1339
|
-
const existing =
|
|
1579
|
+
const existing = existsSync12(ignorePath) ? readFileSync10(ignorePath, "utf8") : "";
|
|
1340
1580
|
const lines = existing.split("\n");
|
|
1341
1581
|
if (lines.some((line) => line.trim().replace(/\/$/, "") === pattern.replace(/\/$/, ""))) {
|
|
1342
1582
|
return void 0;
|
|
@@ -1372,10 +1612,10 @@ function ensureWorkspacePrep(opts) {
|
|
|
1372
1612
|
function inspectWorkspacePrep(root) {
|
|
1373
1613
|
const entries = [];
|
|
1374
1614
|
let pkg = {};
|
|
1375
|
-
const pkgPath =
|
|
1376
|
-
if (
|
|
1615
|
+
const pkgPath = join12(root, "package.json");
|
|
1616
|
+
if (existsSync12(pkgPath)) {
|
|
1377
1617
|
try {
|
|
1378
|
-
pkg = JSON.parse(
|
|
1618
|
+
pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
|
|
1379
1619
|
} catch {
|
|
1380
1620
|
pkg = {};
|
|
1381
1621
|
}
|
|
@@ -1389,9 +1629,9 @@ function inspectWorkspacePrep(root) {
|
|
|
1389
1629
|
});
|
|
1390
1630
|
}
|
|
1391
1631
|
const own = readOwnPackage().name;
|
|
1392
|
-
const yamlPath =
|
|
1393
|
-
if (
|
|
1394
|
-
const yaml =
|
|
1632
|
+
const yamlPath = join12(root, WORKSPACE_YAML);
|
|
1633
|
+
if (existsSync12(yamlPath)) {
|
|
1634
|
+
const yaml = readFileSync10(yamlPath, "utf8");
|
|
1395
1635
|
const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
|
|
1396
1636
|
if (listed) {
|
|
1397
1637
|
const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
|
|
@@ -1409,15 +1649,15 @@ function declaredBuildTarget(cwd) {
|
|
|
1409
1649
|
return readProjectPackageJson(cwd).nx?.targets?.[BUILD_SCRIPT_NAME];
|
|
1410
1650
|
}
|
|
1411
1651
|
function resolveOutputToken(token, cwd) {
|
|
1412
|
-
if (token.startsWith("{projectRoot}/")) return
|
|
1652
|
+
if (token.startsWith("{projectRoot}/")) return join13(cwd, token.slice("{projectRoot}/".length));
|
|
1413
1653
|
if (token.startsWith("{workspaceRoot}/")) {
|
|
1414
1654
|
const root = findWorkspaceRoot(cwd);
|
|
1415
|
-
return root === void 0 ? void 0 :
|
|
1655
|
+
return root === void 0 ? void 0 : join13(root, token.slice("{workspaceRoot}/".length));
|
|
1416
1656
|
}
|
|
1417
|
-
return
|
|
1657
|
+
return join13(cwd, token);
|
|
1418
1658
|
}
|
|
1419
1659
|
function buildStamp(cwd) {
|
|
1420
|
-
const marker =
|
|
1660
|
+
const marker = join13(cwd, `.sentinel-build-stamp-${process.pid}`);
|
|
1421
1661
|
try {
|
|
1422
1662
|
writeFileSync2(marker, "");
|
|
1423
1663
|
const stamp = statSync(marker).mtimeMs;
|
|
@@ -1428,7 +1668,7 @@ function buildStamp(cwd) {
|
|
|
1428
1668
|
}
|
|
1429
1669
|
}
|
|
1430
1670
|
function writtenSince(path, startedAt) {
|
|
1431
|
-
if (!
|
|
1671
|
+
if (!existsSync13(path)) return false;
|
|
1432
1672
|
try {
|
|
1433
1673
|
return statSync(path).mtimeMs >= startedAt;
|
|
1434
1674
|
} catch {
|
|
@@ -1582,7 +1822,7 @@ import { join as join18 } from "path";
|
|
|
1582
1822
|
|
|
1583
1823
|
// src/core/config/has-source.ts
|
|
1584
1824
|
import { readdirSync } from "fs";
|
|
1585
|
-
import { extname, join as
|
|
1825
|
+
import { extname, join as join14, relative as relative3 } from "path";
|
|
1586
1826
|
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1587
1827
|
"node_modules",
|
|
1588
1828
|
"dist",
|
|
@@ -1633,7 +1873,7 @@ function hasSourceFiles(cwd, extensions) {
|
|
|
1633
1873
|
}
|
|
1634
1874
|
for (const entry of entries) {
|
|
1635
1875
|
if (entry.isDirectory()) {
|
|
1636
|
-
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(
|
|
1876
|
+
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join14(dir, entry.name));
|
|
1637
1877
|
continue;
|
|
1638
1878
|
}
|
|
1639
1879
|
if (wanted.has(extname(entry.name))) return true;
|
|
@@ -1654,7 +1894,7 @@ function listSourceFiles(cwd, extensions) {
|
|
|
1654
1894
|
continue;
|
|
1655
1895
|
}
|
|
1656
1896
|
for (const entry of entries) {
|
|
1657
|
-
const full =
|
|
1897
|
+
const full = join14(dir, entry.name);
|
|
1658
1898
|
if (entry.isDirectory()) {
|
|
1659
1899
|
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(full);
|
|
1660
1900
|
continue;
|
|
@@ -1672,52 +1912,6 @@ function scopeFlags(paths, options = []) {
|
|
|
1672
1912
|
return [TOLERATE_EMPTY_FLAG];
|
|
1673
1913
|
}
|
|
1674
1914
|
|
|
1675
|
-
// src/roles/format/config-policy.ts
|
|
1676
|
-
var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
|
|
1677
|
-
var FORMAT_SCRIPT_NAME = "format";
|
|
1678
|
-
var PROVENANCE_KEY = "$sentinel";
|
|
1679
|
-
var PERMITTED_LOCAL_KEYS = [
|
|
1680
|
-
"useTabs",
|
|
1681
|
-
"tabWidth",
|
|
1682
|
-
"printWidth",
|
|
1683
|
-
"semi",
|
|
1684
|
-
"singleQuote",
|
|
1685
|
-
"jsxSingleQuote",
|
|
1686
|
-
"trailingComma",
|
|
1687
|
-
"quoteProps",
|
|
1688
|
-
"bracketSpacing",
|
|
1689
|
-
"bracketSameLine",
|
|
1690
|
-
"arrowParens",
|
|
1691
|
-
"endOfLine",
|
|
1692
|
-
"objectWrap",
|
|
1693
|
-
"proseWrap",
|
|
1694
|
-
"experimentalOperatorPosition"
|
|
1695
|
-
];
|
|
1696
|
-
var ALWAYS_LOCAL_KEYS = ["ignorePatterns", "overrides"];
|
|
1697
|
-
var FORMAT_DEFAULT_IGNORES = ["**/*.toml"];
|
|
1698
|
-
var PRETTIER_CONFIG_FILES = [
|
|
1699
|
-
".prettierrc",
|
|
1700
|
-
".prettierrc.json",
|
|
1701
|
-
".prettierrc.json5",
|
|
1702
|
-
".prettierrc.yml",
|
|
1703
|
-
".prettierrc.yaml",
|
|
1704
|
-
".prettierrc.js",
|
|
1705
|
-
".prettierrc.cjs",
|
|
1706
|
-
".prettierrc.mjs",
|
|
1707
|
-
"prettier.config.js",
|
|
1708
|
-
"prettier.config.cjs",
|
|
1709
|
-
"prettier.config.mjs"
|
|
1710
|
-
];
|
|
1711
|
-
function formatTargets() {
|
|
1712
|
-
return {
|
|
1713
|
-
[FORMAT_SCRIPT_NAME]: {
|
|
1714
|
-
cache: true,
|
|
1715
|
-
inputs: ["default", `{projectRoot}/${FORMAT_CONFIG_FILE}`]
|
|
1716
|
-
},
|
|
1717
|
-
[`${FORMAT_SCRIPT_NAME}:fix`]: { cache: false }
|
|
1718
|
-
};
|
|
1719
|
-
}
|
|
1720
|
-
|
|
1721
1915
|
// src/roles/format/format-script.ts
|
|
1722
1916
|
var SENTINEL_FORMAT_COMMAND = "sentinel --run --format";
|
|
1723
1917
|
function isPrettierSegment(segment) {
|
|
@@ -1746,8 +1940,8 @@ function writesWhenRewritten(name, command) {
|
|
|
1746
1940
|
var CHECK_SCRIPT_NAMES = /* @__PURE__ */ new Set(["lint", "format", "check", "test", "typecheck", "verify"]);
|
|
1747
1941
|
|
|
1748
1942
|
// src/roles/format/inherited-ignores.ts
|
|
1749
|
-
import { existsSync as
|
|
1750
|
-
import { join as
|
|
1943
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
|
|
1944
|
+
import { join as join15 } from "path";
|
|
1751
1945
|
var ROOT_IGNORE_FILE = ".prettierignore";
|
|
1752
1946
|
function isPattern(line) {
|
|
1753
1947
|
const trimmed = line.trim();
|
|
@@ -1762,11 +1956,11 @@ function toModulePattern(pattern) {
|
|
|
1762
1956
|
}
|
|
1763
1957
|
function inheritedIgnorePatterns(workspaceRoot) {
|
|
1764
1958
|
if (!workspaceRoot) return [];
|
|
1765
|
-
const path =
|
|
1766
|
-
if (!
|
|
1959
|
+
const path = join15(workspaceRoot, ROOT_IGNORE_FILE);
|
|
1960
|
+
if (!existsSync14(path)) return [];
|
|
1767
1961
|
let contents;
|
|
1768
1962
|
try {
|
|
1769
|
-
contents =
|
|
1963
|
+
contents = readFileSync11(path, "utf8");
|
|
1770
1964
|
} catch {
|
|
1771
1965
|
return [];
|
|
1772
1966
|
}
|
|
@@ -1810,56 +2004,14 @@ function needsSvelteCompiler(output) {
|
|
|
1810
2004
|
return /svelte\/compiler/.test(output);
|
|
1811
2005
|
}
|
|
1812
2006
|
|
|
1813
|
-
// src/roles/format/presets/base.json
|
|
1814
|
-
var base_default = {
|
|
1815
|
-
printWidth: 80,
|
|
1816
|
-
semi: false,
|
|
1817
|
-
singleQuote: true,
|
|
1818
|
-
trailingComma: "all",
|
|
1819
|
-
sortPackageJson: false,
|
|
1820
|
-
sortImports: false
|
|
1821
|
-
};
|
|
1822
|
-
|
|
1823
|
-
// src/roles/format/presets/nest-imports.json
|
|
1824
|
-
var nest_imports_default = {
|
|
1825
|
-
customGroups: [
|
|
1826
|
-
{
|
|
1827
|
-
groupName: "workspace",
|
|
1828
|
-
elementNamePattern: ["@hublo/**", "@shared/**", "@front/**", "@network/**"]
|
|
1829
|
-
}
|
|
1830
|
-
],
|
|
1831
|
-
groups: ["builtin", "external", "workspace", ["parent", "index"], "sibling"],
|
|
1832
|
-
newlinesBetween: true,
|
|
1833
|
-
order: "asc",
|
|
1834
|
-
ignoreCase: false
|
|
1835
|
-
};
|
|
1836
|
-
|
|
1837
|
-
// src/roles/format/preset-data.ts
|
|
1838
|
-
var FORMAT_PRESETS = ["base", "svelte", "nest"];
|
|
1839
|
-
function hasFormatPreset(name) {
|
|
1840
|
-
return FORMAT_PRESETS.includes(name);
|
|
1841
|
-
}
|
|
1842
|
-
function formatPresetName(declared) {
|
|
1843
|
-
if (declared === "svelte") return "svelte";
|
|
1844
|
-
if (declared === "nest") return "nest";
|
|
1845
|
-
return "base";
|
|
1846
|
-
}
|
|
1847
|
-
function formatPresetFor(preset) {
|
|
1848
|
-
const base = base_default;
|
|
1849
|
-
const name = formatPresetName(preset);
|
|
1850
|
-
if (name === "svelte") return { ...base, svelte: true };
|
|
1851
|
-
if (name === "nest") return { ...base, sortImports: nest_imports_default };
|
|
1852
|
-
return base;
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
2007
|
// src/roles/format/prettier-config.ts
|
|
1856
|
-
import { existsSync as
|
|
1857
|
-
import { join as
|
|
2008
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
|
|
2009
|
+
import { join as join17 } from "path";
|
|
1858
2010
|
|
|
1859
2011
|
// src/roles/format/resolve-oxfmt.ts
|
|
1860
|
-
import { readFileSync as
|
|
2012
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
1861
2013
|
import { createRequire as createRequire2 } from "module";
|
|
1862
|
-
import { dirname as dirname4, join as
|
|
2014
|
+
import { dirname as dirname4, join as join16 } from "path";
|
|
1863
2015
|
function resolveOxfmt(cwd) {
|
|
1864
2016
|
return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
|
|
1865
2017
|
}
|
|
@@ -1888,8 +2040,8 @@ function configSchema() {
|
|
|
1888
2040
|
function readConfigSchema() {
|
|
1889
2041
|
try {
|
|
1890
2042
|
const manifest = createRequire2(import.meta.url).resolve("oxfmt/package.json");
|
|
1891
|
-
const schemaPath =
|
|
1892
|
-
return JSON.parse(
|
|
2043
|
+
const schemaPath = join16(dirname4(manifest), "configuration_schema.json");
|
|
2044
|
+
return JSON.parse(readFileSync12(schemaPath, "utf8"));
|
|
1893
2045
|
} catch {
|
|
1894
2046
|
return void 0;
|
|
1895
2047
|
}
|
|
@@ -1920,14 +2072,14 @@ function toOxfmtOverrides(value) {
|
|
|
1920
2072
|
return { overrides, unresolved };
|
|
1921
2073
|
}
|
|
1922
2074
|
function readPrettierSettings(cwd) {
|
|
1923
|
-
const file = PRETTIER_CONFIG_FILES.find((name) =>
|
|
2075
|
+
const file = PRETTIER_CONFIG_FILES.find((name) => existsSync15(join17(cwd, name)));
|
|
1924
2076
|
if (!file) return { options: {}, unresolved: [] };
|
|
1925
2077
|
if (/\.(js|cjs|mjs)$/.test(file)) {
|
|
1926
2078
|
return { options: {}, file, unresolved: [`${file} is JavaScript, so it was not executed`] };
|
|
1927
2079
|
}
|
|
1928
2080
|
let parsed;
|
|
1929
2081
|
try {
|
|
1930
|
-
parsed = parseJsonc(
|
|
2082
|
+
parsed = parseJsonc(readFileSync13(join17(cwd, file), "utf8"), file);
|
|
1931
2083
|
} catch {
|
|
1932
2084
|
return { options: {}, file, unresolved: [`${file} could not be parsed`] };
|
|
1933
2085
|
}
|
|
@@ -1956,71 +2108,6 @@ function readPrettierSettings(cwd) {
|
|
|
1956
2108
|
return { options, file, unresolved };
|
|
1957
2109
|
}
|
|
1958
2110
|
|
|
1959
|
-
// src/roles/format/read-adoption.ts
|
|
1960
|
-
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
|
|
1961
|
-
import { join as join17 } from "path";
|
|
1962
|
-
var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
|
|
1963
|
-
configFile,
|
|
1964
|
-
preset: null,
|
|
1965
|
-
adopted: false,
|
|
1966
|
-
conformant: false,
|
|
1967
|
-
drift: [],
|
|
1968
|
-
local: {},
|
|
1969
|
-
presetVersion: null,
|
|
1970
|
-
effective: {},
|
|
1971
|
-
unreadable
|
|
1972
|
-
});
|
|
1973
|
-
function sameValue(a, b) {
|
|
1974
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
1975
|
-
}
|
|
1976
|
-
function readFormatAdoption(cwd) {
|
|
1977
|
-
const path = join17(cwd, FORMAT_CONFIG_FILE);
|
|
1978
|
-
if (!existsSync15(path)) return NOT_ADOPTED2(null);
|
|
1979
|
-
let parsed;
|
|
1980
|
-
try {
|
|
1981
|
-
parsed = parseJsonc(readFileSync13(path, "utf8"), FORMAT_CONFIG_FILE);
|
|
1982
|
-
} catch (error) {
|
|
1983
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1984
|
-
return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
|
|
1985
|
-
}
|
|
1986
|
-
const provenance = parsed[PROVENANCE_KEY];
|
|
1987
|
-
if (!provenance || typeof provenance.preset !== "string") return NOT_ADOPTED2(FORMAT_CONFIG_FILE);
|
|
1988
|
-
if (!hasFormatPreset(provenance.preset)) {
|
|
1989
|
-
return NOT_ADOPTED2(
|
|
1990
|
-
FORMAT_CONFIG_FILE,
|
|
1991
|
-
`${FORMAT_CONFIG_FILE} declares the format preset "${provenance.preset}", which sentinel does not ship (shipped: ${FORMAT_PRESETS.join(", ")}). Re-run \`sentinel --init --format\`.`
|
|
1992
|
-
);
|
|
1993
|
-
}
|
|
1994
|
-
const declaredLocal = Array.isArray(provenance.local) ? provenance.local : [];
|
|
1995
|
-
const preset = formatPresetFor(provenance.preset);
|
|
1996
|
-
const drift = [];
|
|
1997
|
-
const local = {};
|
|
1998
|
-
for (const [key, expected] of Object.entries(preset)) {
|
|
1999
|
-
if (declaredLocal.includes(key)) {
|
|
2000
|
-
local[key] = parsed[key];
|
|
2001
|
-
continue;
|
|
2002
|
-
}
|
|
2003
|
-
if (!(key in parsed) || !sameValue(parsed[key], expected)) drift.push(key);
|
|
2004
|
-
}
|
|
2005
|
-
for (const key of declaredLocal) {
|
|
2006
|
-
if (!(key in preset)) local[key] = parsed[key];
|
|
2007
|
-
}
|
|
2008
|
-
for (const key of ALWAYS_LOCAL_KEYS) {
|
|
2009
|
-
if (key in parsed) local[key] = parsed[key];
|
|
2010
|
-
}
|
|
2011
|
-
return {
|
|
2012
|
-
configFile: FORMAT_CONFIG_FILE,
|
|
2013
|
-
preset: provenance.preset,
|
|
2014
|
-
adopted: true,
|
|
2015
|
-
conformant: drift.length === 0,
|
|
2016
|
-
drift,
|
|
2017
|
-
local,
|
|
2018
|
-
presetVersion: typeof provenance.version === "string" ? provenance.version : null,
|
|
2019
|
-
effective: parsed,
|
|
2020
|
-
unreadable: null
|
|
2021
|
-
};
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
2111
|
// src/roles/format/unenforced.ts
|
|
2025
2112
|
function unenforcedFormatOptions(options) {
|
|
2026
2113
|
const gaps = [];
|
|
@@ -6600,4 +6687,4 @@ export {
|
|
|
6600
6687
|
detectFramework,
|
|
6601
6688
|
dispatch
|
|
6602
6689
|
};
|
|
6603
|
-
//# 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.27",
|
|
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",
|