@hublo/sentinel 1.2.0-alpha.0 → 1.2.0-alpha.2
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/README.md +2 -2
- package/dist/bin/sentinel.d.ts +5 -0
- package/dist/bin/sentinel.js +27 -4
- package/dist/{chunk-TWL6T237.js → chunk-SA2RMTVI.js} +886 -528
- package/dist/index.js +1 -2
- package/dist/roles/build/toolchain.d.ts +5 -0
- package/dist/roles/build/toolchain.js +16 -0
- package/package.json +4 -3
- package/dist/chunk-XSCDJZDY.js +0 -26
- package/dist/roles/build/react-app.d.ts +0 -116
- package/dist/roles/build/react-app.js +0 -111
package/dist/index.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as tailwindcss } from '@tailwindcss/vite';
|
|
2
|
+
export { default as react } from '@vitejs/plugin-react';
|
|
3
|
+
export { nitro } from 'nitro/vite';
|
|
4
|
+
export { default as svgr } from 'vite-plugin-svgr';
|
|
5
|
+
export { Plugin, PluginOption, SassPreprocessorOptions, UserConfig, UserConfigExport, defineConfig, loadEnv, mergeConfig } from 'vite';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/roles/build/toolchain.ts
|
|
2
|
+
import { default as default2 } from "@tailwindcss/vite";
|
|
3
|
+
import { default as default3 } from "@vitejs/plugin-react";
|
|
4
|
+
import { nitro } from "nitro/vite";
|
|
5
|
+
import { default as default4 } from "vite-plugin-svgr";
|
|
6
|
+
import { defineConfig, loadEnv, mergeConfig } from "vite";
|
|
7
|
+
export {
|
|
8
|
+
defineConfig,
|
|
9
|
+
loadEnv,
|
|
10
|
+
mergeConfig,
|
|
11
|
+
nitro,
|
|
12
|
+
default3 as react,
|
|
13
|
+
default4 as svgr,
|
|
14
|
+
default2 as tailwindcss
|
|
15
|
+
};
|
|
16
|
+
//# 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.
|
|
3
|
+
"version": "1.2.0-alpha.2",
|
|
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",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"default": "./dist/tsconfig/node.json"
|
|
40
40
|
},
|
|
41
41
|
"./build/react": {
|
|
42
|
-
"types": "./dist/roles/build/
|
|
43
|
-
"import": "./dist/roles/build/
|
|
42
|
+
"types": "./dist/roles/build/toolchain.d.ts",
|
|
43
|
+
"import": "./dist/roles/build/toolchain.js"
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"files": [
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"eslint-plugin-styled-components-a11y": "2.2.0",
|
|
63
63
|
"jsonc-parser": "^3.3.1",
|
|
64
64
|
"nitro": "3.0.260415-beta",
|
|
65
|
+
"oxc-parser": "0.147.0",
|
|
65
66
|
"oxfmt": "0.63.0",
|
|
66
67
|
"oxlint": "1.77.0",
|
|
67
68
|
"oxlint-tsgolint": "7.0.2001",
|
package/dist/chunk-XSCDJZDY.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// src/roles/build/presets/base.json
|
|
2
|
-
var base_default = {
|
|
3
|
-
target: "chrome89",
|
|
4
|
-
allowedHosts: [".hubpreprod.com", ".playground-hublo.com"],
|
|
5
|
-
publicAssets: [
|
|
6
|
-
{
|
|
7
|
-
dir: "public/branding",
|
|
8
|
-
baseURL: "/branding",
|
|
9
|
-
maxAge: 31536e3
|
|
10
|
-
}
|
|
11
|
-
]
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// src/roles/build/preset-data.ts
|
|
15
|
-
var REACT_APP_DEFAULTS = base_default;
|
|
16
|
-
|
|
17
|
-
// src/shared/deep-merge.ts
|
|
18
|
-
function isPlainObject(value) {
|
|
19
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export {
|
|
23
|
-
REACT_APP_DEFAULTS,
|
|
24
|
-
isPlainObject
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=chunk-XSCDJZDY.js.map
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { PluginOption, UserConfig } from 'vite';
|
|
2
|
-
export { defineConfig, loadEnv } from 'vite';
|
|
3
|
-
|
|
4
|
-
/** The convention values, in one place so `--inspect` can report what an app departs from. */
|
|
5
|
-
declare const REACT_APP_DEFAULTS: {
|
|
6
|
-
target: string;
|
|
7
|
-
allowedHosts: string[];
|
|
8
|
-
publicAssets: {
|
|
9
|
-
dir: string;
|
|
10
|
-
baseURL: string;
|
|
11
|
-
maxAge: number;
|
|
12
|
-
}[];
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/** Where the router's routes live and where it writes its generated tree. */
|
|
16
|
-
interface RouterPaths {
|
|
17
|
-
routesDirectory: string;
|
|
18
|
-
generatedRouteTree: string;
|
|
19
|
-
/** Extra lines appended to the generated tree. Two of the three apps use it. */
|
|
20
|
-
routeTreeFileFooter?: string[];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* The TanStack factories, supplied by the app.
|
|
24
|
-
*
|
|
25
|
-
* Typed loosely on purpose: sentinel decides WHEN to call them and with what, and has no
|
|
26
|
-
* business asserting their return shape. Narrowing this would only couple sentinel to a
|
|
27
|
-
* version of a package it does not own.
|
|
28
|
-
*/
|
|
29
|
-
interface TanstackFactories {
|
|
30
|
-
start: (options: {
|
|
31
|
-
router: RouterPaths;
|
|
32
|
-
}) => PluginOption[];
|
|
33
|
-
router: (options: RouterPaths & {
|
|
34
|
-
target: string;
|
|
35
|
-
autoCodeSplitting: boolean;
|
|
36
|
-
}) => PluginOption;
|
|
37
|
-
}
|
|
38
|
-
/** Everything an app declares. */
|
|
39
|
-
interface ReactAppOptions {
|
|
40
|
-
/** The app's own directory. Always `__dirname`. */
|
|
41
|
-
root: string;
|
|
42
|
-
/** Vite's `mode`, from the config callback. */
|
|
43
|
-
mode: string;
|
|
44
|
-
/** Served under, e.g. `/console/`. */
|
|
45
|
-
base: string;
|
|
46
|
-
/** Dev server port. */
|
|
47
|
-
port: number;
|
|
48
|
-
/** HMR port. Explicit, NOT `port + 1`: career goes DOWN to 9998 where the others go up. */
|
|
49
|
-
hmrPort: number;
|
|
50
|
-
router: RouterPaths;
|
|
51
|
-
tanstack: TanstackFactories;
|
|
52
|
-
/**
|
|
53
|
-
* Sourcemaps: a boolean, however the app decided it.
|
|
54
|
-
*
|
|
55
|
-
* The three apps disagree on how — two use a mode allowlist, one reads an env var. That is
|
|
56
|
-
* an inconsistency in the repo rather than a requirement, and encoding both would make
|
|
57
|
-
* sentinel the owner of a decision it should not hold.
|
|
58
|
-
*/
|
|
59
|
-
sourcemap?: boolean;
|
|
60
|
-
/** Passed through verbatim, never read. See the note above. */
|
|
61
|
-
alias?: unknown[];
|
|
62
|
-
/** The app's own plugins (branding, babel). Appended AFTER the base set. */
|
|
63
|
-
plugins?: PluginOption[];
|
|
64
|
-
/** Conventions the app may override. */
|
|
65
|
-
target?: string;
|
|
66
|
-
allowedHosts?: string[];
|
|
67
|
-
/**
|
|
68
|
-
* Anything else this app needs, merged over the preset LAST.
|
|
69
|
-
*
|
|
70
|
-
* The preset is a starting point, not a cage. Two things an app must be able to do and
|
|
71
|
-
* could not before: override a NESTED attribute without losing its siblings, and add an
|
|
72
|
-
* attribute the preset knows nothing about.
|
|
73
|
-
*
|
|
74
|
-
* Objects merge, everything else replaces — see `merge-config` for why arrays replace
|
|
75
|
-
* rather than concatenate. Whatever lands here is reported by `--inspect --build`, so an
|
|
76
|
-
* override is a visible, countable decision instead of something found by reading a config.
|
|
77
|
-
*
|
|
78
|
-
* Real cases today: console needs `ssr`, `optimizeDeps` and `preview`; career needs
|
|
79
|
-
* `css.preprocessorOptions` for Sass; all three need their own `nitro.publicAssets`.
|
|
80
|
-
*/
|
|
81
|
-
overrides?: Record<string, unknown>;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* The environment, loaded the way all three apps already load it.
|
|
86
|
-
*
|
|
87
|
-
* `production` is normalised to `prd` because that is this repository's deployment tag: it is
|
|
88
|
-
* the `.env.prd` the build reads and the SSM path segment the values come from. Not a
|
|
89
|
-
* preference, a fact about the repo — which is exactly why it belongs in the preset rather
|
|
90
|
-
* than being retyped in every config.
|
|
91
|
-
*/
|
|
92
|
-
declare function appEnv(root: string, mode: string): Record<string, string>;
|
|
93
|
-
/** True when this run is a test rather than a real build. */
|
|
94
|
-
declare function isTestMode(mode: string, env?: NodeJS.ProcessEnv): boolean;
|
|
95
|
-
/**
|
|
96
|
-
* WHICH plugins run, as names, in order.
|
|
97
|
-
*
|
|
98
|
-
* Split out from building them so the rule can be tested without instantiating a single
|
|
99
|
-
* plugin. The rule is the part that must not diverge between apps; the instances are just
|
|
100
|
-
* function calls.
|
|
101
|
-
*
|
|
102
|
-
* Under test the router plugin runs alone: `tanstackStart` and `nitro` bring a server the
|
|
103
|
-
* tests neither need nor can run. All three apps already do this, identically.
|
|
104
|
-
*/
|
|
105
|
-
declare function pluginPlan(isTest: boolean, extras?: number): string[];
|
|
106
|
-
/**
|
|
107
|
-
* The Vite config for a React app, minus the plugins.
|
|
108
|
-
*
|
|
109
|
-
* Pure and separately testable: everything here is data in, data out, so the composition
|
|
110
|
-
* rules can be asserted without a bundler anywhere near the test.
|
|
111
|
-
*/
|
|
112
|
-
declare function reactAppConfig(options: ReactAppOptions): Omit<UserConfig, 'plugins'>;
|
|
113
|
-
/** The config an app spreads into `defineConfig`. */
|
|
114
|
-
declare function reactApp(options: ReactAppOptions): UserConfig;
|
|
115
|
-
|
|
116
|
-
export { REACT_APP_DEFAULTS, type ReactAppOptions, type RouterPaths, type TanstackFactories, appEnv, isTestMode, pluginPlan, reactApp, reactAppConfig };
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
REACT_APP_DEFAULTS,
|
|
3
|
-
isPlainObject
|
|
4
|
-
} from "../../chunk-XSCDJZDY.js";
|
|
5
|
-
|
|
6
|
-
// src/roles/build/react-app.ts
|
|
7
|
-
import tailwindcss from "@tailwindcss/vite";
|
|
8
|
-
import react from "@vitejs/plugin-react";
|
|
9
|
-
import { nitro } from "nitro/vite";
|
|
10
|
-
import { loadEnv } from "vite";
|
|
11
|
-
import svgr from "vite-plugin-svgr";
|
|
12
|
-
|
|
13
|
-
// src/roles/build/merge-config.ts
|
|
14
|
-
function mergeConfig(base, overrides) {
|
|
15
|
-
if (!overrides) return base;
|
|
16
|
-
const out = { ...base };
|
|
17
|
-
for (const [key, value] of Object.entries(overrides)) {
|
|
18
|
-
if (value === void 0) {
|
|
19
|
-
delete out[key];
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
const current = out[key];
|
|
23
|
-
out[key] = isPlainObject(current) && isPlainObject(value) ? mergeConfig(current, value) : value;
|
|
24
|
-
}
|
|
25
|
-
return out;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// src/roles/build/react-app.ts
|
|
29
|
-
import { defineConfig, loadEnv as loadEnv2 } from "vite";
|
|
30
|
-
function appEnv(root, mode) {
|
|
31
|
-
return loadEnv(mode === "production" ? "prd" : mode, root, "");
|
|
32
|
-
}
|
|
33
|
-
function isTestMode(mode, env = process.env) {
|
|
34
|
-
return mode === "test" || env.VITEST === "true";
|
|
35
|
-
}
|
|
36
|
-
function pluginPlan(isTest, extras = 0) {
|
|
37
|
-
return [
|
|
38
|
-
"tailwindcss",
|
|
39
|
-
...isTest ? ["tanstackRouter"] : ["tanstackStart", "nitro"],
|
|
40
|
-
"react",
|
|
41
|
-
"svgr",
|
|
42
|
-
...Array.from({ length: extras }, (_, at) => `app:${at}`)
|
|
43
|
-
];
|
|
44
|
-
}
|
|
45
|
-
function basePlugins(options, isTest) {
|
|
46
|
-
const { tanstack, router } = options;
|
|
47
|
-
return [
|
|
48
|
-
tailwindcss(),
|
|
49
|
-
...isTest ? [tanstack.router({ ...router, target: "react", autoCodeSplitting: true })] : [...tanstack.start({ router }), nitro()],
|
|
50
|
-
react(),
|
|
51
|
-
svgr(),
|
|
52
|
-
...options.plugins ?? []
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
function reactAppConfig(options) {
|
|
56
|
-
const preset = {
|
|
57
|
-
base: options.base,
|
|
58
|
-
root: options.root,
|
|
59
|
-
define: {
|
|
60
|
-
// Development only. In a build this would leak a browser global into SSR output.
|
|
61
|
-
...options.mode === "development" ? { global: "window" } : {}
|
|
62
|
-
},
|
|
63
|
-
server: {
|
|
64
|
-
port: options.port,
|
|
65
|
-
allowedHosts: options.allowedHosts ?? [...REACT_APP_DEFAULTS.allowedHosts],
|
|
66
|
-
hmr: { host: "localhost", protocol: "ws", port: options.hmrPort }
|
|
67
|
-
},
|
|
68
|
-
build: {
|
|
69
|
-
target: options.target ?? REACT_APP_DEFAULTS.target,
|
|
70
|
-
sourcemap: options.sourcemap ?? false
|
|
71
|
-
},
|
|
72
|
-
/*
|
|
73
|
-
* Nitro's two settings are sentinel's, and both were measured across the three apps rather
|
|
74
|
-
* than assumed.
|
|
75
|
-
*
|
|
76
|
-
* `baseURL` is always the app's `base`, without exception: `/console/`, `/` and `/admin/`.
|
|
77
|
-
* It is derived, so an app cannot get them out of step.
|
|
78
|
-
*
|
|
79
|
-
* `publicAssets` is byte-identical in all three — the branding directory, its URL and a
|
|
80
|
-
* one-year max-age. That is a convention about where branding lives, not data about an
|
|
81
|
-
* app, and it was sitting in three `overrides` blocks saying the same thing.
|
|
82
|
-
*
|
|
83
|
-
* An app that needs MORE from nitro overrides the key: career adds `externals` to keep the
|
|
84
|
-
* SSR sanitisation chain out of the server bundle. `mergeConfig` merges objects, so adding
|
|
85
|
-
* one key does not take these two away.
|
|
86
|
-
*/
|
|
87
|
-
nitro: {
|
|
88
|
-
baseURL: options.base,
|
|
89
|
-
publicAssets: [...REACT_APP_DEFAULTS.publicAssets]
|
|
90
|
-
},
|
|
91
|
-
...options.alias ? { resolve: { alias: options.alias } } : {}
|
|
92
|
-
};
|
|
93
|
-
return mergeConfig(preset, options.overrides);
|
|
94
|
-
}
|
|
95
|
-
function reactApp(options) {
|
|
96
|
-
return {
|
|
97
|
-
...reactAppConfig(options),
|
|
98
|
-
plugins: basePlugins(options, isTestMode(options.mode))
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
export {
|
|
102
|
-
REACT_APP_DEFAULTS,
|
|
103
|
-
appEnv,
|
|
104
|
-
defineConfig,
|
|
105
|
-
isTestMode,
|
|
106
|
-
loadEnv2 as loadEnv,
|
|
107
|
-
pluginPlan,
|
|
108
|
-
reactApp,
|
|
109
|
-
reactAppConfig
|
|
110
|
-
};
|
|
111
|
-
//# sourceMappingURL=react-app.js.map
|