@everysk/apps-devkit 0.3.0-beta-20261019175049 → 0.3.0-beta-20261021182446
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 +6 -4
- package/dist/eslint/index.d.ts +5 -5
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +28 -4
- package/dist/eslint/index.js.map +1 -1
- package/package.json +1 -1
- package/src/eslint/index.ts +37 -6
package/README.md
CHANGED
|
@@ -54,15 +54,17 @@ export default defineAppTestConfig();
|
|
|
54
54
|
|
|
55
55
|
```js
|
|
56
56
|
// eslint.config.js
|
|
57
|
-
import {
|
|
57
|
+
import { defineAppLintConfig } from "@everysk/apps-devkit/eslint";
|
|
58
58
|
|
|
59
|
-
export default
|
|
59
|
+
export default defineAppLintConfig({ tsconfigRootDir: import.meta.dirname });
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
`tsconfigRootDir` is the app's own directory, which only its config can name. In a repository of
|
|
63
63
|
several apps, linting them in one run (an editor does, and so does `eslint` from the root) fails
|
|
64
64
|
with "No tsconfigRootDir was set, and multiple candidate TSConfigRootDirs are present" without it.
|
|
65
|
-
|
|
65
|
+
The app's own blocks go in `extra`: `defineAppLintConfig({ tsconfigRootDir, extra: [{ files, rules }] })`,
|
|
66
|
+
or the array alone, `defineAppLintConfig([...])`. Any other key throws: a block passed without its
|
|
67
|
+
array used to be read as options and its rules dropped in silence.
|
|
66
68
|
|
|
67
69
|
```jsonc
|
|
68
70
|
// tsconfig.app.json
|
|
@@ -82,7 +84,7 @@ with "No tsconfigRootDir was set, and multiple candidate TSConfigRootDirs are pr
|
|
|
82
84
|
|---|---|
|
|
83
85
|
| `/vite` | `defineAppConfig`, plus on their own: the dev proxy, the `/file/` route plugin, the token source they share, and the two config plugins |
|
|
84
86
|
| `/vitest` | `defineAppTestConfig` |
|
|
85
|
-
| `/eslint` | `
|
|
87
|
+
| `/eslint` | `defineAppLintConfig` |
|
|
86
88
|
| `/prettier` | the Prettier config as JSON |
|
|
87
89
|
| `/tsconfig`, `/tsconfig/node`, `/tsconfig/vitest` | the TypeScript bases |
|
|
88
90
|
|
package/dist/eslint/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineConfig } from "eslint/config";
|
|
2
|
-
export type
|
|
2
|
+
export type AppLintConfigOptions = {
|
|
3
3
|
/**
|
|
4
4
|
* The app's directory, `import.meta.dirname` in its `eslint.config.js`. An editor lints a
|
|
5
5
|
* repository of several apps in one ESLint process, where typescript-eslint refuses to pick
|
|
@@ -10,13 +10,13 @@ export type EveryskConfigOptions = {
|
|
|
10
10
|
extra?: ReturnType<typeof defineConfig>;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* defineAppLintConfig
|
|
14
14
|
*
|
|
15
15
|
* The ESLint configuration every Everysk app shares, so an app's `eslint.config.js` is:
|
|
16
16
|
*
|
|
17
17
|
* ```js
|
|
18
|
-
* import {
|
|
19
|
-
* export default
|
|
18
|
+
* import { defineAppLintConfig } from "@everysk/apps-devkit/eslint";
|
|
19
|
+
* export default defineAppLintConfig({ tsconfigRootDir: import.meta.dirname });
|
|
20
20
|
* ```
|
|
21
21
|
*
|
|
22
22
|
* It encodes the conventions that lint can actually check: no MUI barrel imports, and no
|
|
@@ -25,5 +25,5 @@ export type EveryskConfigOptions = {
|
|
|
25
25
|
*
|
|
26
26
|
* Takes the options, or the app's own blocks alone, as it did before there were options.
|
|
27
27
|
*/
|
|
28
|
-
export declare const
|
|
28
|
+
export declare const defineAppLintConfig: (optionsOrExtra?: AppLintConfigOptions | ReturnType<typeof defineConfig>) => import("eslint/config").ConfigObject[];
|
|
29
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAiB,MAAM,eAAe,CAAC;AAmB5D,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wFAAwF;IACxF,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CAC3C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAiB,MAAM,eAAe,CAAC;AAmB5D,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wFAAwF;IACxF,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CAC3C,CAAC;AA+BF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,GAC5B,iBAAgB,oBAAoB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAM,2CAyD9E,CAAC"}
|
package/dist/eslint/index.js
CHANGED
|
@@ -17,14 +17,36 @@ const noBarrelPaths = [
|
|
|
17
17
|
];
|
|
18
18
|
// Data-layer rule: pages and components reach data only through entity hooks.
|
|
19
19
|
const dataLayerMessage = "Data access only via entity hooks (@everysk/apps-sdk/<entity> or @/hooks/...). Pages and components must not call axios or an api module directly.";
|
|
20
|
+
const OPTION_KEYS = [
|
|
21
|
+
"tsconfigRootDir",
|
|
22
|
+
"extra",
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Throws on a key that is not an option, and on an `extra` that is not an array. A block passed
|
|
26
|
+
* without its array (`{ files, rules }`) used to be read as options with neither option set,
|
|
27
|
+
* which dropped the app's rules in silence, and as `extra` it threw "extra is not iterable";
|
|
28
|
+
* `eslint.config.js` is JavaScript, so the options type never got to catch either.
|
|
29
|
+
*/
|
|
30
|
+
const assertOptions = (options) => {
|
|
31
|
+
if (options.extra !== undefined && !Array.isArray(options.extra)) {
|
|
32
|
+
throw new Error("defineAppLintConfig: extra must be an array of blocks: extra: [{ files, rules }].");
|
|
33
|
+
}
|
|
34
|
+
const unknown = Object.keys(options).filter((key) => !OPTION_KEYS.includes(key));
|
|
35
|
+
if (unknown.length === 0)
|
|
36
|
+
return;
|
|
37
|
+
throw new Error(`defineAppLintConfig: ${unknown.map((key) => `"${key}"`).join(", ")} ` +
|
|
38
|
+
`${unknown.length === 1 ? "is not an option" : "are not options"}. ` +
|
|
39
|
+
`The options are ${OPTION_KEYS.join(" and ")}; ` +
|
|
40
|
+
"the app's own blocks go in extra: [{ files, rules }].");
|
|
41
|
+
};
|
|
20
42
|
/**
|
|
21
|
-
*
|
|
43
|
+
* defineAppLintConfig
|
|
22
44
|
*
|
|
23
45
|
* The ESLint configuration every Everysk app shares, so an app's `eslint.config.js` is:
|
|
24
46
|
*
|
|
25
47
|
* ```js
|
|
26
|
-
* import {
|
|
27
|
-
* export default
|
|
48
|
+
* import { defineAppLintConfig } from "@everysk/apps-devkit/eslint";
|
|
49
|
+
* export default defineAppLintConfig({ tsconfigRootDir: import.meta.dirname });
|
|
28
50
|
* ```
|
|
29
51
|
*
|
|
30
52
|
* It encodes the conventions that lint can actually check: no MUI barrel imports, and no
|
|
@@ -33,7 +55,9 @@ const dataLayerMessage = "Data access only via entity hooks (@everysk/apps-sdk/<
|
|
|
33
55
|
*
|
|
34
56
|
* Takes the options, or the app's own blocks alone, as it did before there were options.
|
|
35
57
|
*/
|
|
36
|
-
export const
|
|
58
|
+
export const defineAppLintConfig = (optionsOrExtra = {}) => {
|
|
59
|
+
if (!Array.isArray(optionsOrExtra))
|
|
60
|
+
assertOptions(optionsOrExtra);
|
|
37
61
|
const { tsconfigRootDir, extra = [] } = Array.isArray(optionsOrExtra)
|
|
38
62
|
? { extra: optionsOrExtra }
|
|
39
63
|
: optionsOrExtra;
|
package/dist/eslint/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,UAAU,MAAM,2BAA2B,CAAC;AACnD,OAAO,YAAY,MAAM,6BAA6B,CAAC;AACvD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE5D,mFAAmF;AACnF,MAAM,aAAa,GAAG;IAClB;QACI,IAAI,EAAE,eAAe;QACrB,OAAO,EACH,qGAAqG;KAC5G;IACD;QACI,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,gFAAgF;KAC5F;CACJ,CAAC;AAEF,8EAA8E;AAC9E,MAAM,gBAAgB,GAClB,oJAAoJ,CAAC;AAazJ;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/eslint/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ const noBarrelPaths = [
|
|
|
22
22
|
const dataLayerMessage =
|
|
23
23
|
"Data access only via entity hooks (@everysk/apps-sdk/<entity> or @/hooks/...). Pages and components must not call axios or an api module directly.";
|
|
24
24
|
|
|
25
|
-
export type
|
|
25
|
+
export type AppLintConfigOptions = {
|
|
26
26
|
/**
|
|
27
27
|
* The app's directory, `import.meta.dirname` in its `eslint.config.js`. An editor lints a
|
|
28
28
|
* repository of several apps in one ESLint process, where typescript-eslint refuses to pick
|
|
@@ -33,14 +33,43 @@ export type EveryskConfigOptions = {
|
|
|
33
33
|
extra?: ReturnType<typeof defineConfig>;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
const OPTION_KEYS: readonly string[] = [
|
|
37
|
+
"tsconfigRootDir",
|
|
38
|
+
"extra",
|
|
39
|
+
] satisfies (keyof AppLintConfigOptions)[];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Throws on a key that is not an option, and on an `extra` that is not an array. A block passed
|
|
43
|
+
* without its array (`{ files, rules }`) used to be read as options with neither option set,
|
|
44
|
+
* which dropped the app's rules in silence, and as `extra` it threw "extra is not iterable";
|
|
45
|
+
* `eslint.config.js` is JavaScript, so the options type never got to catch either.
|
|
46
|
+
*/
|
|
47
|
+
const assertOptions = (options: AppLintConfigOptions) => {
|
|
48
|
+
if (options.extra !== undefined && !Array.isArray(options.extra)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
"defineAppLintConfig: extra must be an array of blocks: extra: [{ files, rules }].",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const unknown = Object.keys(options).filter((key) => !OPTION_KEYS.includes(key));
|
|
55
|
+
if (unknown.length === 0) return;
|
|
56
|
+
|
|
57
|
+
throw new Error(
|
|
58
|
+
`defineAppLintConfig: ${unknown.map((key) => `"${key}"`).join(", ")} ` +
|
|
59
|
+
`${unknown.length === 1 ? "is not an option" : "are not options"}. ` +
|
|
60
|
+
`The options are ${OPTION_KEYS.join(" and ")}; ` +
|
|
61
|
+
"the app's own blocks go in extra: [{ files, rules }].",
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
36
65
|
/**
|
|
37
|
-
*
|
|
66
|
+
* defineAppLintConfig
|
|
38
67
|
*
|
|
39
68
|
* The ESLint configuration every Everysk app shares, so an app's `eslint.config.js` is:
|
|
40
69
|
*
|
|
41
70
|
* ```js
|
|
42
|
-
* import {
|
|
43
|
-
* export default
|
|
71
|
+
* import { defineAppLintConfig } from "@everysk/apps-devkit/eslint";
|
|
72
|
+
* export default defineAppLintConfig({ tsconfigRootDir: import.meta.dirname });
|
|
44
73
|
* ```
|
|
45
74
|
*
|
|
46
75
|
* It encodes the conventions that lint can actually check: no MUI barrel imports, and no
|
|
@@ -49,9 +78,11 @@ export type EveryskConfigOptions = {
|
|
|
49
78
|
*
|
|
50
79
|
* Takes the options, or the app's own blocks alone, as it did before there were options.
|
|
51
80
|
*/
|
|
52
|
-
export const
|
|
53
|
-
optionsOrExtra:
|
|
81
|
+
export const defineAppLintConfig = (
|
|
82
|
+
optionsOrExtra: AppLintConfigOptions | ReturnType<typeof defineConfig> = {},
|
|
54
83
|
) => {
|
|
84
|
+
if (!Array.isArray(optionsOrExtra)) assertOptions(optionsOrExtra);
|
|
85
|
+
|
|
55
86
|
const { tsconfigRootDir, extra = [] } = Array.isArray(optionsOrExtra)
|
|
56
87
|
? { extra: optionsOrExtra }
|
|
57
88
|
: optionsOrExtra;
|