@hublo/sentinel 1.2.0-alpha.13 → 1.2.0-alpha.15

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.
@@ -4,3 +4,4 @@ import '@vitejs/plugin-react';
4
4
  import 'nitro/vite';
5
5
  import 'vite-plugin-svgr';
6
6
  import 'vite';
7
+ import 'vitest/config';
@@ -22,7 +22,7 @@ import {
22
22
  registerAdapters,
23
23
  resolve,
24
24
  resolveBin
25
- } from "../chunk-X675OYUC.js";
25
+ } from "../chunk-RV34GQVH.js";
26
26
 
27
27
  // bin/sentinel.ts
28
28
  import { program } from "commander";
@@ -333,11 +333,11 @@ 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
- function buildTarget() {
336
+ function buildTarget(configFiles = BUILD_CONFIG_FILES) {
337
337
  return {
338
338
  [BUILD_SCRIPT_NAME]: {
339
339
  cache: true,
340
- inputs: ["default", "^default", ...BUILD_CONFIG_FILES.map((name) => `{projectRoot}/${name}`)]
340
+ inputs: ["default", "^default", ...configFiles.map((name) => `{projectRoot}/${name}`)]
341
341
  }
342
342
  };
343
343
  }
@@ -572,6 +572,11 @@ function existingCommand(cwd, target) {
572
572
  // src/core/config/nx-target.ts
573
573
  import { existsSync as existsSync7 } from "fs";
574
574
  import { join as join7 } from "path";
575
+ function nxTargetMetadataOperations(options) {
576
+ const { targets } = options;
577
+ if (Object.keys(targets).length === 0) return [];
578
+ return [{ kind: "merge-json", path: "package.json", value: { nx: { targets } } }];
579
+ }
575
580
  function nxTargetOperations(options) {
576
581
  const { cwd, targets } = options;
577
582
  const names = Object.keys(targets);
@@ -584,11 +589,7 @@ function nxTargetOperations(options) {
584
589
  keys: names.map((name) => ["targets", name])
585
590
  });
586
591
  }
587
- operations.push({
588
- kind: "merge-json",
589
- path: "package.json",
590
- value: { nx: { targets } }
591
- });
592
+ operations.push(...nxTargetMetadataOperations(options));
592
593
  return operations;
593
594
  }
594
595
 
@@ -730,32 +731,31 @@ function describeUnmet(preset, unmet) {
730
731
  return `the build role does not apply to this module yet: ${list}. ${entry?.why ?? ""}. Nothing was written. Raise those versions, check the module still builds and its tests still pass, then re-run \`sentinel --init --build\`.`;
731
732
  }
732
733
 
733
- // src/roles/build/rewrite-imports.ts
734
+ // src/core/config/rewrite-imports.ts
734
735
  import { parseSync } from "oxc-parser";
735
- var MOVED_SPECIFIERS = new Set(OWNED_PACKAGES.map((entry) => entry.specifier));
736
+ var movedSpecifiers = (toolchain) => new Set(toolchain.owned.map((entry) => entry.specifier));
736
737
  function esmBlocker(fileName, packageType) {
737
738
  if (/\.(mts|mjs)$/.test(fileName)) return void 0;
738
739
  if (packageType === "module") return void 0;
739
740
  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.`;
740
741
  }
741
- var DEFAULT_EXPORT_NAMES = Object.fromEntries(
742
- OWNED_PACKAGES.filter((entry) => entry.default !== void 0).map((entry) => [
743
- entry.specifier,
744
- entry.default
745
- ])
742
+ var defaultExportNames = (toolchain) => Object.fromEntries(
743
+ toolchain.owned.filter((entry) => entry.default !== void 0).map((entry) => [entry.specifier, entry.default])
746
744
  );
747
- function renderImport(bindings) {
745
+ function renderImport(bindings, presetSpecifier) {
748
746
  const render = (list) => list.map((b) => b.exported === b.local ? b.exported : `${b.exported} as ${b.local}`).sort((left, right) => left.localeCompare(right)).join(", ");
749
747
  const values = bindings.filter((b) => !b.typeOnly);
750
748
  const types = bindings.filter((b) => b.typeOnly);
751
749
  const lines = [];
752
- if (values.length > 0) lines.push(`import { ${render(values)} } from '${BUILD_PRESET_SPECIFIER}'`);
750
+ if (values.length > 0) lines.push(`import { ${render(values)} } from '${presetSpecifier}'`);
753
751
  if (types.length > 0) {
754
- lines.push(`import type { ${render(types)} } from '${BUILD_PRESET_SPECIFIER}'`);
752
+ lines.push(`import type { ${render(types)} } from '${presetSpecifier}'`);
755
753
  }
756
754
  return lines.join("\n");
757
755
  }
758
- function rewriteBuildImports(source, fileName = "vite.config.ts") {
756
+ function rewriteToolchainImports(toolchain, source, fileName) {
757
+ const moved = movedSpecifiers(toolchain);
758
+ const defaults = defaultExportNames(toolchain);
759
759
  const { program, errors } = parseSync(fileName, source, { sourceType: "module" });
760
760
  if (errors.length > 0) {
761
761
  return {
@@ -766,10 +766,10 @@ function rewriteBuildImports(source, fileName = "vite.config.ts") {
766
766
  const imports = program.body.filter(
767
767
  (node) => node.type === "ImportDeclaration"
768
768
  );
769
- if (imports.some((node) => node.source.value === BUILD_PRESET_SPECIFIER)) {
769
+ if (imports.some((node) => node.source.value === toolchain.presetSpecifier)) {
770
770
  return { kind: "unchanged", why: "this config already imports its toolchain from sentinel" };
771
771
  }
772
- const moving = imports.filter((node) => MOVED_SPECIFIERS.has(node.source.value));
772
+ const moving = imports.filter((node) => moved.has(node.source.value));
773
773
  if (moving.length === 0) {
774
774
  return {
775
775
  kind: "unchanged",
@@ -786,7 +786,7 @@ function rewriteBuildImports(source, fileName = "vite.config.ts") {
786
786
  for (const spec of specifiers) {
787
787
  const typeOnly = node.importKind === "type" || spec.importKind === "type";
788
788
  if (spec.type === "ImportDefaultSpecifier") {
789
- const exported = DEFAULT_EXPORT_NAMES[from];
789
+ const exported = defaults[from];
790
790
  if (!exported) {
791
791
  return {
792
792
  kind: "blocked",
@@ -818,7 +818,7 @@ function rewriteBuildImports(source, fileName = "vite.config.ts") {
818
818
  const after = out.slice(span.end).match(/^\r?\n/)?.[0].length ?? 0;
819
819
  out = out.slice(0, span.start) + out.slice(span.end + after);
820
820
  }
821
- out = out.slice(0, first.start) + renderImport(bindings) + out.slice(first.end);
821
+ out = out.slice(0, first.start) + renderImport(bindings, toolchain.presetSpecifier) + out.slice(first.end);
822
822
  return {
823
823
  kind: "rewritten",
824
824
  source: out,
@@ -826,6 +826,15 @@ function rewriteBuildImports(source, fileName = "vite.config.ts") {
826
826
  };
827
827
  }
828
828
 
829
+ // src/roles/build/rewrite-imports.ts
830
+ var BUILD_TOOLCHAIN = {
831
+ presetSpecifier: BUILD_PRESET_SPECIFIER,
832
+ owned: OWNED_PACKAGES
833
+ };
834
+ function rewriteBuildImports(source, fileName = "vite.config.ts") {
835
+ return rewriteToolchainImports(BUILD_TOOLCHAIN, source, fileName);
836
+ }
837
+
829
838
  // src/roles/build/plan.ts
830
839
  function ownedBuildDependencies(cwd) {
831
840
  const manifest = readProjectPackageJson(cwd);
@@ -889,7 +898,7 @@ function plan(context) {
889
898
  if (configFile === void 0) {
890
899
  return {
891
900
  operations: [],
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.`
901
+ 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 (38 services here build through \`@nx/webpack\`), the build role does not apply to it.`
893
902
  };
894
903
  }
895
904
  return planReactApp(context, configFile);
@@ -949,7 +958,16 @@ function planNestService(context, configFile, webpackTarget) {
949
958
  if (refusal !== void 0) return { operations: [], blocked: refusal };
950
959
  const dropped = Object.keys(webpackTarget.configurations ?? {});
951
960
  return {
952
- operations: nestAdoptionOperations(context.cwd, webpackTarget),
961
+ operations: [
962
+ ...nestAdoptionOperations(context.cwd, webpackTarget),
963
+ // The same nx metadata the React path writes, and for the same reason: declaring `inputs`
964
+ // at all REPLACES nx's default `['default','^default']`, so a target that declares none
965
+ // runs on defaults while every other target this module has declares them. The Nest path
966
+ // wrote none, which left its build the one target that could replay a stale bundle after a
967
+ // dependency changed. One name, because a Nest service's config can only be `.mts`.
968
+ ...nxTargetMetadataOperations({ cwd: context.cwd, targets: buildTarget([NEST_CONFIG_FILE]) }),
969
+ manifestOperation(context.cwd, { [BUILD_SCRIPT_NAME]: SENTINEL_BUILD_COMMAND })
970
+ ],
953
971
  notes: [
954
972
  `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
973
  ...dropped.length > 0 ? [
@@ -1003,7 +1021,7 @@ var ViteRoleAdapter = class extends BaseAdapter {
1003
1021
  * which tells nobody what to do about it.
1004
1022
  *
1005
1023
  * Nest it now serves too, through `@hublo/sentinel/build/nest`. It used to be declined on the
1006
- * grounds that "there is nothing to bundle", which was never true: those 36 services bundle
1024
+ * grounds that "there is nothing to bundle", which was never true: those 38 services bundle
1007
1025
  * with webpack. What changed is that Nx v24 removes the `@nx/webpack:webpack` executor and
1008
1026
  * the `composePlugins` / `withNx` helpers their shared config is built on, and nx's own
1009
1027
  * migration generator refuses every one of them because they use `@nx/js:node`
@@ -6439,4 +6457,4 @@ export {
6439
6457
  detectFramework,
6440
6458
  dispatch
6441
6459
  };
6442
- //# sourceMappingURL=chunk-X675OYUC.js.map
6460
+ //# sourceMappingURL=chunk-RV34GQVH.js.map
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  registerAdapters,
8
8
  resolve,
9
9
  setDefaultRunner
10
- } from "./chunk-X675OYUC.js";
10
+ } from "./chunk-RV34GQVH.js";
11
11
  export {
12
12
  BaseAdapter,
13
13
  all,
@@ -0,0 +1,2 @@
1
+ export { ConfigEnv, TestUserConfig, ViteUserConfig, defineConfig, mergeConfig } from 'vitest/config';
2
+ export { loadEnv } from 'vite';
@@ -0,0 +1,9 @@
1
+ // src/roles/test/react/toolchain.ts
2
+ import { defineConfig, mergeConfig } from "vitest/config";
3
+ import { loadEnv } from "vite";
4
+ export {
5
+ defineConfig,
6
+ loadEnv,
7
+ mergeConfig
8
+ };
9
+ //# sourceMappingURL=toolchain.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.2.0-alpha.13",
3
+ "version": "1.2.0-alpha.15",
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",
@@ -45,6 +45,10 @@
45
45
  "./build/nest": {
46
46
  "types": "./dist/roles/build/nest/toolchain.d.ts",
47
47
  "import": "./dist/roles/build/nest/toolchain.js"
48
+ },
49
+ "./test/react": {
50
+ "types": "./dist/roles/test/react/toolchain.d.ts",
51
+ "import": "./dist/roles/test/react/toolchain.js"
48
52
  }
49
53
  },
50
54
  "files": [
@@ -72,7 +76,8 @@
72
76
  "oxlint-tsgolint": "7.0.2001",
73
77
  "typescript": "5.9.3",
74
78
  "vite": "8.0.8",
75
- "vite-plugin-svgr": "5.2.0"
79
+ "vite-plugin-svgr": "5.2.0",
80
+ "vitest": "4.1.4"
76
81
  },
77
82
  "devDependencies": {
78
83
  "@hublo/sentinel": "link:.",