@everysk/apps-devkit 0.1.0-beta.0
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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/eslint/index.d.ts +20 -0
- package/dist/eslint/index.d.ts.map +1 -0
- package/dist/eslint/index.js +85 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/prettier/index.json +8 -0
- package/dist/vite/index.d.ts +30 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +70 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/plugins/envVarsLocation.d.ts +3 -0
- package/dist/vite/plugins/envVarsLocation.d.ts.map +1 -0
- package/dist/vite/plugins/envVarsLocation.js +10 -0
- package/dist/vite/plugins/envVarsLocation.js.map +1 -0
- package/dist/vite/plugins/serveDevAppConfig.d.ts +15 -0
- package/dist/vite/plugins/serveDevAppConfig.d.ts.map +1 -0
- package/dist/vite/plugins/serveDevAppConfig.js +47 -0
- package/dist/vite/plugins/serveDevAppConfig.js.map +1 -0
- package/dist/vite/serverProxy.d.ts +16 -0
- package/dist/vite/serverProxy.d.ts.map +1 -0
- package/dist/vite/serverProxy.js +81 -0
- package/dist/vite/serverProxy.js.map +1 -0
- package/dist/vitest/index.d.ts +33 -0
- package/dist/vitest/index.d.ts.map +1 -0
- package/dist/vitest/index.js +76 -0
- package/dist/vitest/index.js.map +1 -0
- package/package.json +90 -0
- package/src/eslint/index.ts +90 -0
- package/src/prettier/index.json +8 -0
- package/src/vite/index.ts +82 -0
- package/src/vite/plugins/envVarsLocation.ts +11 -0
- package/src/vite/plugins/serveDevAppConfig.ts +51 -0
- package/src/vite/serverProxy.ts +88 -0
- package/src/vitest/index.ts +81 -0
- package/tsconfig/app.json +35 -0
- package/tsconfig/node.json +25 -0
- package/tsconfig/vitest.json +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Everysk Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# @everysk/apps-devkit
|
|
2
|
+
|
|
3
|
+
(C) Copyright 2026 EVERYSK TECHNOLOGIES
|
|
4
|
+
|
|
5
|
+
The build configuration every Everysk app extends: Vite, ESLint, Vitest, TypeScript and
|
|
6
|
+
Prettier presets — and the toolchain itself. Declared as a `devDependency`.
|
|
7
|
+
|
|
8
|
+
Part of [everysk/apps-sdk](https://github.com/everysk/apps-sdk), alongside
|
|
9
|
+
[`@everysk/apps-sdk`](../apps-sdk) (the runtime) and [`@everysk/apps-cli`](../apps-cli) (the
|
|
10
|
+
`everysk-apps` bin).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install --save-dev @everysk/apps-devkit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Vite, ESLint, Vitest and Prettier are its own `dependencies`, not peers, so an app gets the
|
|
19
|
+
whole toolchain from this one line — and `npm ci --omit=dev` still drops every bit of it from a
|
|
20
|
+
deploy image. That is the boundary the package exists to draw: a required peer of a
|
|
21
|
+
`dependency` **is** installed under `--omit=dev`, measured, so putting the runner there would
|
|
22
|
+
have shipped it to production.
|
|
23
|
+
|
|
24
|
+
## Use
|
|
25
|
+
|
|
26
|
+
Each preset takes overrides, merged with Vite's own `mergeConfig`, so an app adds to the preset
|
|
27
|
+
rather than replacing it.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// vite.config.ts
|
|
31
|
+
import { defineAppConfig } from "@everysk/apps-devkit/vite";
|
|
32
|
+
|
|
33
|
+
export default defineAppConfig();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// vitest.config.ts
|
|
38
|
+
import { defineAppTestConfig } from "@everysk/apps-devkit/vitest";
|
|
39
|
+
|
|
40
|
+
export default defineAppTestConfig();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// eslint.config.js
|
|
45
|
+
import { everyskConfig } from "@everysk/apps-devkit/eslint";
|
|
46
|
+
|
|
47
|
+
export default everyskConfig();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```jsonc
|
|
51
|
+
// tsconfig.app.json
|
|
52
|
+
{
|
|
53
|
+
"extends": "@everysk/apps-devkit/tsconfig",
|
|
54
|
+
// paths is re-declared here on purpose — see below
|
|
55
|
+
"compilerOptions": { "paths": { "@/*": ["./src/*"] } },
|
|
56
|
+
"include": ["src"]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
"@everysk/apps-devkit/prettier" // .prettierrc
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| Subpath | |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `/vite` | `defineAppConfig`, plus the dev proxy and the two config plugins on their own |
|
|
67
|
+
| `/vitest` | `defineAppTestConfig` |
|
|
68
|
+
| `/eslint` | `everyskConfig` |
|
|
69
|
+
| `/prettier` | the Prettier config as JSON |
|
|
70
|
+
| `/tsconfig`, `/tsconfig/node`, `/tsconfig/vitest` | the TypeScript bases |
|
|
71
|
+
|
|
72
|
+
## What the presets decide
|
|
73
|
+
|
|
74
|
+
**Vite** — `base: "./"`, `envDir` at `PROJECT_ROOT` (an app builds from `apps/<name>/project`
|
|
75
|
+
but `.env` lives at the repository root), the `@` alias, React with the compiler, Tailwind, and
|
|
76
|
+
the `/api` dev proxy that authenticates with OAuth2 client credentials and refreshes the token
|
|
77
|
+
before it expires.
|
|
78
|
+
|
|
79
|
+
It also serves the app's `config.json` `env_vars` at `/app-config.json` in dev, read **one level
|
|
80
|
+
above** the Vite root. That is why an app is `<name>/{config.json, project/}`: flatten it and the
|
|
81
|
+
app boots with no configuration, silently.
|
|
82
|
+
|
|
83
|
+
**ESLint** — the conventions lint can actually check: no MUI barrel imports, and no direct data
|
|
84
|
+
access from `src/pages/**` or `src/components/**`.
|
|
85
|
+
|
|
86
|
+
**Vitest** — jsdom, `@everysk/apps-sdk/test/setup` as the setup file, a 30s timeout (Vitest's 5s
|
|
87
|
+
default trips MUI transition-driven tests under `--coverage`, and every app was raising it by
|
|
88
|
+
hand) and an 80 % coverage floor.
|
|
89
|
+
|
|
90
|
+
## Two traps this package encodes
|
|
91
|
+
|
|
92
|
+
**`tsconfig/app.json` deliberately omits `paths`.** TypeScript resolves a config's paths relative
|
|
93
|
+
to the file that *declares* them, so an `@/*` mapping written here would point at this package's
|
|
94
|
+
own `src`. Each app re-declares it.
|
|
95
|
+
|
|
96
|
+
**Barrels are excluded from coverage at exactly one level.** The recursive form also matches every
|
|
97
|
+
`index.tsx`, which silently drops real components out of the report — found while building the
|
|
98
|
+
SDK, encoded here so no app repeats it.
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
Node 22 or newer, npm 12 or newer.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineConfig } from "eslint/config";
|
|
2
|
+
/**
|
|
3
|
+
* everyskConfig
|
|
4
|
+
*
|
|
5
|
+
* The ESLint configuration every Everysk app shares, so an app's `eslint.config.js` is:
|
|
6
|
+
*
|
|
7
|
+
* ```js
|
|
8
|
+
* import { everyskConfig } from "@everysk/apps-devkit/eslint";
|
|
9
|
+
* export default everyskConfig();
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* It encodes the conventions that lint can actually check: no MUI barrel imports, and no
|
|
13
|
+
* direct data access from pages or components. The rules that lint cannot express — which
|
|
14
|
+
* subpath to import, which provider to wire — belong to the `everysk-apps` generator.
|
|
15
|
+
*
|
|
16
|
+
* @param {ReturnType<typeof defineConfig>} [extra] - Appended after the preset, so an app can
|
|
17
|
+
* add or override rules for its own files.
|
|
18
|
+
*/
|
|
19
|
+
export declare const everyskConfig: (extra?: ReturnType<typeof defineConfig>) => import("eslint/config").Config[];
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAI,QAAO,UAAU,CAAC,OAAO,YAAY,CAAM,qCAgDnE,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
4
|
+
import reactRefresh from "eslint-plugin-react-refresh";
|
|
5
|
+
import tseslint from "typescript-eslint";
|
|
6
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
7
|
+
// Barrel bans applied to every file: faster dev startup and reliable tree-shaking.
|
|
8
|
+
const noBarrelPaths = [
|
|
9
|
+
{
|
|
10
|
+
name: "@mui/material",
|
|
11
|
+
message: "Avoid the barrel. Import from the deep path, e.g. `@mui/material/Button` or `@mui/material/styles`.",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "@mui/icons-material",
|
|
15
|
+
message: "Avoid the barrel. Import the specific icon, e.g. `@mui/icons-material/Search`.",
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
// Data-layer rule: pages and components reach data only through entity hooks.
|
|
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
|
+
/**
|
|
21
|
+
* everyskConfig
|
|
22
|
+
*
|
|
23
|
+
* The ESLint configuration every Everysk app shares, so an app's `eslint.config.js` is:
|
|
24
|
+
*
|
|
25
|
+
* ```js
|
|
26
|
+
* import { everyskConfig } from "@everysk/apps-devkit/eslint";
|
|
27
|
+
* export default everyskConfig();
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* It encodes the conventions that lint can actually check: no MUI barrel imports, and no
|
|
31
|
+
* direct data access from pages or components. The rules that lint cannot express — which
|
|
32
|
+
* subpath to import, which provider to wire — belong to the `everysk-apps` generator.
|
|
33
|
+
*
|
|
34
|
+
* @param {ReturnType<typeof defineConfig>} [extra] - Appended after the preset, so an app can
|
|
35
|
+
* add or override rules for its own files.
|
|
36
|
+
*/
|
|
37
|
+
export const everyskConfig = (extra = []) => defineConfig([
|
|
38
|
+
globalIgnores(["dist", "coverage"]),
|
|
39
|
+
{
|
|
40
|
+
files: ["**/*.{ts,tsx}"],
|
|
41
|
+
extends: [
|
|
42
|
+
js.configs.recommended,
|
|
43
|
+
tseslint.configs.recommended,
|
|
44
|
+
reactHooks.configs.flat["recommended-latest"],
|
|
45
|
+
reactRefresh.configs.vite,
|
|
46
|
+
],
|
|
47
|
+
languageOptions: {
|
|
48
|
+
ecmaVersion: 2020,
|
|
49
|
+
globals: globals.browser,
|
|
50
|
+
},
|
|
51
|
+
rules: {
|
|
52
|
+
"@typescript-eslint/no-restricted-imports": ["error", { paths: noBarrelPaths }],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
// A same-named rule REPLACES the base one for these files rather than merging, so
|
|
57
|
+
// the barrel bans are repeated here.
|
|
58
|
+
files: ["src/pages/**/*.{ts,tsx}", "src/components/**/*.{ts,tsx}"],
|
|
59
|
+
rules: {
|
|
60
|
+
"@typescript-eslint/no-restricted-imports": [
|
|
61
|
+
"error",
|
|
62
|
+
{
|
|
63
|
+
paths: [
|
|
64
|
+
...noBarrelPaths,
|
|
65
|
+
{ name: "axios", message: dataLayerMessage },
|
|
66
|
+
{ name: "@/api", message: dataLayerMessage },
|
|
67
|
+
],
|
|
68
|
+
patterns: [{ group: ["@/api/*"], message: dataLayerMessage }],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
// Tests may reach the data layer directly, to mock an api module or build axios
|
|
75
|
+
// stubs. Only the barrel bans remain, and the Fast Refresh rule is relaxed for
|
|
76
|
+
// test utilities that export helpers.
|
|
77
|
+
files: ["src/**/*.{test,spec}.{ts,tsx}", "src/test/**/*.{ts,tsx}"],
|
|
78
|
+
rules: {
|
|
79
|
+
"@typescript-eslint/no-restricted-imports": ["error", { paths: noBarrelPaths }],
|
|
80
|
+
"react-refresh/only-export-components": "off",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
...extra,
|
|
84
|
+
]);
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAEzJ;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAyC,EAAE,EAAE,EAAE,CACzE,YAAY,CAAC;IACT,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC;QACI,KAAK,EAAE,CAAC,eAAe,CAAC;QACxB,OAAO,EAAE;YACL,EAAE,CAAC,OAAO,CAAC,WAAW;YACtB,QAAQ,CAAC,OAAO,CAAC,WAAW;YAC5B,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC;YAC7C,YAAY,CAAC,OAAO,CAAC,IAAI;SAC5B;QACD,eAAe,EAAE;YACb,WAAW,EAAE,IAAI;YACjB,OAAO,EAAE,OAAO,CAAC,OAAO;SAC3B;QACD,KAAK,EAAE;YACH,0CAA0C,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;SAClF;KACJ;IACD;QACI,kFAAkF;QAClF,qCAAqC;QACrC,KAAK,EAAE,CAAC,yBAAyB,EAAE,8BAA8B,CAAC;QAClE,KAAK,EAAE;YACH,0CAA0C,EAAE;gBACxC,OAAO;gBACP;oBACI,KAAK,EAAE;wBACH,GAAG,aAAa;wBAChB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE;wBAC5C,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE;qBAC/C;oBACD,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;iBAChE;aACJ;SACJ;KACJ;IACD;QACI,gFAAgF;QAChF,+EAA+E;QAC/E,sCAAsC;QACtC,KAAK,EAAE,CAAC,+BAA+B,EAAE,wBAAwB,CAAC;QAClE,KAAK,EAAE;YACH,0CAA0C,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAC/E,sCAAsC,EAAE,KAAK;SAChD;KACJ;IACD,GAAG,KAAK;CACX,CAAC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type UserConfig } from "vite";
|
|
2
|
+
export { createDevServerProxy } from "./serverProxy.js";
|
|
3
|
+
export { envVarsLocationPlugin } from "./plugins/envVarsLocation.js";
|
|
4
|
+
export { serveDevAppConfigPlugin } from "./plugins/serveDevAppConfig.js";
|
|
5
|
+
/**
|
|
6
|
+
* defineAppConfig
|
|
7
|
+
*
|
|
8
|
+
* The Vite configuration every Everysk app shares, so an app's own `vite.config.ts` is three
|
|
9
|
+
* lines instead of a copy that drifts:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { defineAppConfig } from "@everysk/apps-devkit/vite";
|
|
13
|
+
* export default defineAppConfig();
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* What it sets up:
|
|
17
|
+
*
|
|
18
|
+
* - `base: "./"` and `envDir` at `PROJECT_ROOT`, because an app is built from
|
|
19
|
+
* `apps/<name>/project/` but its `.env` lives at the repository root.
|
|
20
|
+
* - The `@` alias to the app's `src/`.
|
|
21
|
+
* - The dev server on `PORT` (default 5173, `strictPort`), with the `/api` proxy that
|
|
22
|
+
* authenticates against `EVERYSK_API_URL` using OAuth2 client credentials.
|
|
23
|
+
* - React with the compiler preset, Tailwind, and the two plugins that carry the app's
|
|
24
|
+
* `config.json` `env_vars` into the page — a meta tag in build, `/app-config.json` in dev.
|
|
25
|
+
*
|
|
26
|
+
* @param {UserConfig} [overrides] - Merged over the preset with Vite's own `mergeConfig`, so
|
|
27
|
+
* arrays (plugins, aliases) are concatenated rather than replaced.
|
|
28
|
+
*/
|
|
29
|
+
export declare const defineAppConfig: (overrides?: UserConfig) => import("vite").UserConfigFnObject;
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAU3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,eAAe,GAAI,YAAW,UAAe,sCAyCpD,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from "node:url";
|
|
2
|
+
import { defineConfig, loadEnv, mergeConfig } from "vite";
|
|
3
|
+
import react, { reactCompilerPreset } from "@vitejs/plugin-react";
|
|
4
|
+
import babel from "@rolldown/plugin-babel";
|
|
5
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
6
|
+
import { createDevServerProxy } from "./serverProxy.js";
|
|
7
|
+
import { envVarsLocationPlugin } from "./plugins/envVarsLocation.js";
|
|
8
|
+
import { serveDevAppConfigPlugin } from "./plugins/serveDevAppConfig.js";
|
|
9
|
+
export { createDevServerProxy } from "./serverProxy.js";
|
|
10
|
+
export { envVarsLocationPlugin } from "./plugins/envVarsLocation.js";
|
|
11
|
+
export { serveDevAppConfigPlugin } from "./plugins/serveDevAppConfig.js";
|
|
12
|
+
/**
|
|
13
|
+
* defineAppConfig
|
|
14
|
+
*
|
|
15
|
+
* The Vite configuration every Everysk app shares, so an app's own `vite.config.ts` is three
|
|
16
|
+
* lines instead of a copy that drifts:
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { defineAppConfig } from "@everysk/apps-devkit/vite";
|
|
20
|
+
* export default defineAppConfig();
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* What it sets up:
|
|
24
|
+
*
|
|
25
|
+
* - `base: "./"` and `envDir` at `PROJECT_ROOT`, because an app is built from
|
|
26
|
+
* `apps/<name>/project/` but its `.env` lives at the repository root.
|
|
27
|
+
* - The `@` alias to the app's `src/`.
|
|
28
|
+
* - The dev server on `PORT` (default 5173, `strictPort`), with the `/api` proxy that
|
|
29
|
+
* authenticates against `EVERYSK_API_URL` using OAuth2 client credentials.
|
|
30
|
+
* - React with the compiler preset, Tailwind, and the two plugins that carry the app's
|
|
31
|
+
* `config.json` `env_vars` into the page — a meta tag in build, `/app-config.json` in dev.
|
|
32
|
+
*
|
|
33
|
+
* @param {UserConfig} [overrides] - Merged over the preset with Vite's own `mergeConfig`, so
|
|
34
|
+
* arrays (plugins, aliases) are concatenated rather than replaced.
|
|
35
|
+
*/
|
|
36
|
+
export const defineAppConfig = (overrides = {}) => defineConfig(({ mode, command }) => {
|
|
37
|
+
// The app is built from apps/<name>/project, but .env lives at the repo root; the
|
|
38
|
+
// devcontainer exports PROJECT_ROOT for exactly this.
|
|
39
|
+
const root = process.env.PROJECT_ROOT ?? process.cwd();
|
|
40
|
+
const env = loadEnv(mode, root, "");
|
|
41
|
+
Object.assign(process.env, env);
|
|
42
|
+
const preset = {
|
|
43
|
+
base: "./",
|
|
44
|
+
envDir: root,
|
|
45
|
+
resolve: {
|
|
46
|
+
alias: {
|
|
47
|
+
"@": fileURLToPath(new URL("./src", `file://${process.cwd()}/`)),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
build: {
|
|
51
|
+
outDir: "./dist",
|
|
52
|
+
emptyOutDir: true,
|
|
53
|
+
},
|
|
54
|
+
server: {
|
|
55
|
+
host: true,
|
|
56
|
+
port: Number(process.env.PORT) || 5173,
|
|
57
|
+
strictPort: true,
|
|
58
|
+
proxy: command === "serve" ? createDevServerProxy() : undefined,
|
|
59
|
+
},
|
|
60
|
+
plugins: [
|
|
61
|
+
react(),
|
|
62
|
+
babel({ presets: [reactCompilerPreset()] }),
|
|
63
|
+
tailwindcss(),
|
|
64
|
+
envVarsLocationPlugin(),
|
|
65
|
+
serveDevAppConfigPlugin(),
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
return mergeConfig(preset, overrides);
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAmB,MAAM,MAAM,CAAC;AAE3E,OAAO,KAAK,EAAE,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,MAAM,wBAAwB,CAAC;AAC3C,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAwB,EAAE,EAAE,EAAE,CAC1D,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;IAC/B,kFAAkF;IAClF,sDAAsD;IACtD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAe;QACvB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,IAAI;QAEZ,OAAO,EAAE;YACL,KAAK,EAAE;gBACH,GAAG,EAAE,aAAa,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;aACnE;SACJ;QAED,KAAK,EAAE;YACH,MAAM,EAAE,QAAQ;YAChB,WAAW,EAAE,IAAI;SACpB;QAED,MAAM,EAAE;YACJ,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI;YACtC,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,SAAS;SAClE;QAED,OAAO,EAAE;YACL,KAAK,EAAE;YACP,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,mBAAmB,EAAE,CAAC,EAAE,CAAC;YAC3C,WAAW,EAAE;YACb,qBAAqB,EAAE;YACvB,uBAAuB,EAAE;SAC5B;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envVarsLocation.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/envVarsLocation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,wBAAgB,qBAAqB,IAAI,MAAM,CAQ9C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function envVarsLocationPlugin() {
|
|
2
|
+
return {
|
|
3
|
+
name: "env_vars_location",
|
|
4
|
+
apply: "build",
|
|
5
|
+
transformIndexHtml() {
|
|
6
|
+
return [{ tag: "meta", attrs: { name: "app-config" }, injectTo: "head" }];
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=envVarsLocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envVarsLocation.js","sourceRoot":"","sources":["../../../src/vite/plugins/envVarsLocation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,OAAO;QACd,kBAAkB;YAChB,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* In production the platform injects `window.APP_CONFIG` from the app's `config.json` `env_vars`
|
|
4
|
+
* (via the `app-config` meta tag added by the build plugin). There is no platform in dev, so this
|
|
5
|
+
* plugin serves that same `env_vars` object at `/app-config.json`, read from the app's `config.json`
|
|
6
|
+
* one level up from the Vite root (apps/<name>/config.json, sibling of project/). `main.tsx` fetches
|
|
7
|
+
* it on bootstrap and merges it into `window.APP_CONFIG`, so dev mirrors production from a single
|
|
8
|
+
* source of truth — there is no separate dev config file to keep in sync.
|
|
9
|
+
*
|
|
10
|
+
* Because `config.json` lives outside the Vite root it is not watched by default, and `main.tsx`
|
|
11
|
+
* only reads it once at bootstrap. So we also add it to the watcher and trigger a full page reload
|
|
12
|
+
* on change — a full reload re-runs the bootstrap fetch, picking up edits to `env_vars` live.
|
|
13
|
+
*/
|
|
14
|
+
export declare function serveDevAppConfigPlugin(): Plugin;
|
|
15
|
+
//# sourceMappingURL=serveDevAppConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serveDevAppConfig.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/serveDevAppConfig.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAiChD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
/**
|
|
4
|
+
* In production the platform injects `window.APP_CONFIG` from the app's `config.json` `env_vars`
|
|
5
|
+
* (via the `app-config` meta tag added by the build plugin). There is no platform in dev, so this
|
|
6
|
+
* plugin serves that same `env_vars` object at `/app-config.json`, read from the app's `config.json`
|
|
7
|
+
* one level up from the Vite root (apps/<name>/config.json, sibling of project/). `main.tsx` fetches
|
|
8
|
+
* it on bootstrap and merges it into `window.APP_CONFIG`, so dev mirrors production from a single
|
|
9
|
+
* source of truth — there is no separate dev config file to keep in sync.
|
|
10
|
+
*
|
|
11
|
+
* Because `config.json` lives outside the Vite root it is not watched by default, and `main.tsx`
|
|
12
|
+
* only reads it once at bootstrap. So we also add it to the watcher and trigger a full page reload
|
|
13
|
+
* on change — a full reload re-runs the bootstrap fetch, picking up edits to `env_vars` live.
|
|
14
|
+
*/
|
|
15
|
+
export function serveDevAppConfigPlugin() {
|
|
16
|
+
return {
|
|
17
|
+
name: "serve-dev-app-config",
|
|
18
|
+
apply: "serve",
|
|
19
|
+
configureServer(server) {
|
|
20
|
+
// apps/<name>/config.json — one level up from the Vite root (the app's project/ dir).
|
|
21
|
+
const configPath = path.resolve(process.cwd(), "..", "config.json");
|
|
22
|
+
server.middlewares.use(async (req, res, next) => {
|
|
23
|
+
if (req.url !== "/app-config.json")
|
|
24
|
+
return next();
|
|
25
|
+
try {
|
|
26
|
+
const content = await fs.readFile(configPath, "utf-8");
|
|
27
|
+
const envVars = (JSON.parse(content).env_vars ?? {});
|
|
28
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
29
|
+
res.statusCode = 200;
|
|
30
|
+
res.end(JSON.stringify(envVars));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
res.statusCode = 404;
|
|
34
|
+
res.end();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// config.json is outside the Vite root, so watch it explicitly and full-reload on change.
|
|
38
|
+
server.watcher.add(configPath);
|
|
39
|
+
server.watcher.on("change", (file) => {
|
|
40
|
+
if (path.resolve(file) === configPath) {
|
|
41
|
+
server.hot.send({ type: "full-reload" });
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=serveDevAppConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serveDevAppConfig.js","sourceRoot":"","sources":["../../../src/vite/plugins/serveDevAppConfig.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAIlC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,OAAO;QACd,eAAe,CAAC,MAAM;YACpB,sFAAsF;YACtF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;YAEpE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;gBAC9C,IAAI,GAAG,CAAC,GAAG,KAAK,kBAAkB;oBAAE,OAAO,IAAI,EAAE,CAAC;gBAElD,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBACvD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;oBAEhF,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAC;oBACjE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;oBACrB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;oBACrB,GAAG,CAAC,GAAG,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,0FAA0F;YAC1F,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;gBACnC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;oBACtC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProxyOptions } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* createDevServerProxy — Vite dev proxy for `/api`, authenticated with OAuth2 client credentials.
|
|
4
|
+
*
|
|
5
|
+
* Forwards `/api/*` to `EVERYSK_API_URL` (stripping the `/api` prefix) and injects an
|
|
6
|
+
* `Authorization: Bearer <access_token>` header. The token is obtained from
|
|
7
|
+
* `${EVERYSK_API_URL}/oauth2/token` with the `client_credentials` grant, cached in memory, and
|
|
8
|
+
* refreshed in the background shortly before it expires. It is fetched eagerly at startup so a
|
|
9
|
+
* token is ready before the first API call.
|
|
10
|
+
*
|
|
11
|
+
* @returns {Record<string, string | ProxyOptions>} The Vite `server.proxy` config for `/api`.
|
|
12
|
+
* @throws {Error} If `EVERYSK_API_URL`, `EVERYSK_API_CLIENT_ID`, or `EVERYSK_API_CLIENT_SECRET`
|
|
13
|
+
* is missing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDevServerProxy(): Record<string, string | ProxyOptions>;
|
|
16
|
+
//# sourceMappingURL=serverProxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverProxy.d.ts","sourceRoot":"","sources":["../../src/vite/serverProxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAMzC;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAoE5E"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Refresh the OAuth2 token this many ms before it actually expires, so an in-flight
|
|
2
|
+
// request never races a just-expired token.
|
|
3
|
+
const REFRESH_SKEW_MS = 60_000;
|
|
4
|
+
/**
|
|
5
|
+
* createDevServerProxy — Vite dev proxy for `/api`, authenticated with OAuth2 client credentials.
|
|
6
|
+
*
|
|
7
|
+
* Forwards `/api/*` to `EVERYSK_API_URL` (stripping the `/api` prefix) and injects an
|
|
8
|
+
* `Authorization: Bearer <access_token>` header. The token is obtained from
|
|
9
|
+
* `${EVERYSK_API_URL}/oauth2/token` with the `client_credentials` grant, cached in memory, and
|
|
10
|
+
* refreshed in the background shortly before it expires. It is fetched eagerly at startup so a
|
|
11
|
+
* token is ready before the first API call.
|
|
12
|
+
*
|
|
13
|
+
* @returns {Record<string, string | ProxyOptions>} The Vite `server.proxy` config for `/api`.
|
|
14
|
+
* @throws {Error} If `EVERYSK_API_URL`, `EVERYSK_API_CLIENT_ID`, or `EVERYSK_API_CLIENT_SECRET`
|
|
15
|
+
* is missing.
|
|
16
|
+
*/
|
|
17
|
+
export function createDevServerProxy() {
|
|
18
|
+
const EVERYSK_API_URL = process.env.EVERYSK_API_URL;
|
|
19
|
+
if (!EVERYSK_API_URL)
|
|
20
|
+
throw new Error("EVERYSK_API_URL must be set.");
|
|
21
|
+
const clientId = process.env.EVERYSK_API_CLIENT_ID;
|
|
22
|
+
const clientSecret = process.env.EVERYSK_API_CLIENT_SECRET;
|
|
23
|
+
if (!clientId || !clientSecret) {
|
|
24
|
+
throw new Error("EVERYSK_API_CLIENT_ID and EVERYSK_API_CLIENT_SECRET must be set (OAuth2 client credentials).");
|
|
25
|
+
}
|
|
26
|
+
// Captured into an object so the narrowed `string` type survives inside the async closure below.
|
|
27
|
+
const credentials = { clientId, clientSecret };
|
|
28
|
+
const tokenUrl = `${EVERYSK_API_URL.replace(/\/$/, "")}/oauth2/token`;
|
|
29
|
+
let accessToken = null;
|
|
30
|
+
let refreshTimer = null;
|
|
31
|
+
/**
|
|
32
|
+
* refreshToken — fetch a fresh access token and schedule the next refresh before it expires.
|
|
33
|
+
*
|
|
34
|
+
* @returns {Promise<void>} Resolves once `accessToken` is updated.
|
|
35
|
+
* @throws {Error} If the token request fails or returns no `access_token`.
|
|
36
|
+
*/
|
|
37
|
+
async function refreshToken() {
|
|
38
|
+
const res = await fetch(tokenUrl, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
41
|
+
body: new URLSearchParams({
|
|
42
|
+
grant_type: "client_credentials",
|
|
43
|
+
client_id: credentials.clientId,
|
|
44
|
+
client_secret: credentials.clientSecret,
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
if (!res.ok)
|
|
48
|
+
throw new Error(`OAuth2 token request failed: ${res.status} ${res.statusText}`);
|
|
49
|
+
const data = (await res.json());
|
|
50
|
+
if (!data.access_token)
|
|
51
|
+
throw new Error("OAuth2 token response had no access_token.");
|
|
52
|
+
accessToken = data.access_token;
|
|
53
|
+
const ttlMs = (data.expires_in ?? 3600) * 1000;
|
|
54
|
+
if (refreshTimer)
|
|
55
|
+
clearTimeout(refreshTimer);
|
|
56
|
+
refreshTimer = setTimeout(() => {
|
|
57
|
+
void refreshToken().catch((error) => console.error("[dev proxy] OAuth2 token refresh failed:", error));
|
|
58
|
+
}, Math.max(ttlMs - REFRESH_SKEW_MS, 30_000));
|
|
59
|
+
refreshTimer.unref?.();
|
|
60
|
+
}
|
|
61
|
+
// Warm the token before the first request; a failure is logged, not fatal (the request will 401).
|
|
62
|
+
void refreshToken().catch((error) => console.error("[dev proxy] initial OAuth2 token fetch failed:", error));
|
|
63
|
+
return {
|
|
64
|
+
"/api": {
|
|
65
|
+
target: EVERYSK_API_URL,
|
|
66
|
+
changeOrigin: true,
|
|
67
|
+
xfwd: true,
|
|
68
|
+
rewrite: (p) => p.replace(/^\/api(?=\/|$)/, ""),
|
|
69
|
+
configure: (proxy) => {
|
|
70
|
+
proxy.on("proxyReq", (proxyReq) => {
|
|
71
|
+
proxyReq.removeHeader("origin");
|
|
72
|
+
proxyReq.removeHeader("referer");
|
|
73
|
+
if (accessToken) {
|
|
74
|
+
proxyReq.setHeader("Authorization", `Bearer ${accessToken}`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=serverProxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverProxy.js","sourceRoot":"","sources":["../../src/vite/serverProxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ViteUserConfig } from "vitest/config";
|
|
2
|
+
/**
|
|
3
|
+
* defineAppTestConfig
|
|
4
|
+
*
|
|
5
|
+
* The Vitest configuration every Everysk app shares:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { defineAppTestConfig } from "@everysk/apps-devkit/vitest";
|
|
9
|
+
* export default defineAppTestConfig();
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Standalone from the Vite config on purpose — the same split the template kept. The library
|
|
13
|
+
* build, the dev proxy and the React Compiler pass are irrelevant to tests; all they need is
|
|
14
|
+
* the React transform, the `@` alias and jsdom.
|
|
15
|
+
*
|
|
16
|
+
* Notable defaults:
|
|
17
|
+
*
|
|
18
|
+
* - `setupFiles` points at `@everysk/apps-sdk/test/setup`, which installs the jsdom gaps MUI
|
|
19
|
+
* needs (matchMedia, ResizeObserver). It seeds no page globals: an app injects configuration
|
|
20
|
+
* per test with `renderWithProviders(ui, { appId, appEnvironmentVar })`.
|
|
21
|
+
* - `testTimeout` is 30s, not Vitest's 5s. The template's default trips MUI transition-driven
|
|
22
|
+
* tests under `--coverage`, and every app had to raise it by hand.
|
|
23
|
+
* - Coverage thresholds at 80% on all four counters, which the deploy gate enforces. `branches`
|
|
24
|
+
* is listed explicitly: leaving it out does not inherit the others, it leaves that counter
|
|
25
|
+
* unenforced, and an untested `if` is exactly what a coverage floor is there to catch. Barrels
|
|
26
|
+
* are excluded at
|
|
27
|
+
* exactly one level deep. A recursive glob would also swallow every `index.tsx` and quietly
|
|
28
|
+
* drop real components out of the report — which is what happened while building the SDK.
|
|
29
|
+
*
|
|
30
|
+
* @param {ViteUserConfig} [overrides] - Merged over the preset with Vite's `mergeConfig`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const defineAppTestConfig: (overrides?: ViteUserConfig) => ViteUserConfig;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vitest/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAI/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,mBAAmB,GAAI,YAAW,cAAmB,mBA4CjE,CAAC"}
|