@modern-admin/web 0.3.4 → 0.4.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/README.md +42 -0
- package/dist/config/runtime-config.d.ts +84 -0
- package/dist/config/runtime-config.js +19 -0
- package/dist/config/vite.d.ts +84 -0
- package/dist/config/vite.js +166 -0
- package/dist/lib/index.js +0 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/mount.d.ts.map +1 -1
- package/dist/standalone/assets/{action-component-host-CXIbN-8V.js → action-component-host-CuzX-99S.js} +2 -2
- package/dist/standalone/assets/action-component-host-CuzX-99S.js.br +0 -0
- package/dist/standalone/assets/action-component-host-CuzX-99S.js.gz +0 -0
- package/dist/standalone/assets/{action-component-host-CXIbN-8V.js.map → action-component-host-CuzX-99S.js.map} +1 -1
- package/dist/standalone/assets/{action-page-OsWfKQ6C.js → action-page-BUTCUZ7e.js} +2 -2
- package/dist/standalone/assets/action-page-BUTCUZ7e.js.br +0 -0
- package/dist/standalone/assets/action-page-BUTCUZ7e.js.gz +0 -0
- package/dist/standalone/assets/{action-page-OsWfKQ6C.js.map → action-page-BUTCUZ7e.js.map} +1 -1
- package/dist/standalone/assets/{ai-assistant-widget-Bt4Z7Fmr.js → ai-assistant-widget-B3Xy7bCi.js} +2 -2
- package/dist/standalone/assets/ai-assistant-widget-B3Xy7bCi.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-B3Xy7bCi.js.gz +0 -0
- package/dist/standalone/assets/{ai-assistant-widget-Bt4Z7Fmr.js.map → ai-assistant-widget-B3Xy7bCi.js.map} +1 -1
- package/dist/standalone/assets/{audit-log-page-2wuGiWg-.js → audit-log-page-GHzf7mLS.js} +2 -2
- package/dist/standalone/assets/audit-log-page-GHzf7mLS.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-GHzf7mLS.js.gz +0 -0
- package/dist/standalone/assets/{audit-log-page-2wuGiWg-.js.map → audit-log-page-GHzf7mLS.js.map} +1 -1
- package/dist/standalone/assets/{calendar-BZVUWakC.js → calendar-DxUwrP2r.js} +2 -2
- package/dist/standalone/assets/calendar-DxUwrP2r.js.br +0 -0
- package/dist/standalone/assets/calendar-DxUwrP2r.js.gz +0 -0
- package/dist/standalone/assets/{calendar-BZVUWakC.js.map → calendar-DxUwrP2r.js.map} +1 -1
- package/dist/standalone/assets/{chart-widget-BtJb6YXV.js → chart-widget-DnK78Joj.js} +2 -2
- package/dist/standalone/assets/chart-widget-DnK78Joj.js.br +0 -0
- package/dist/standalone/assets/chart-widget-DnK78Joj.js.gz +0 -0
- package/dist/standalone/assets/{chart-widget-BtJb6YXV.js.map → chart-widget-DnK78Joj.js.map} +1 -1
- package/dist/standalone/assets/{command-BNF_evMy.js → command-Df4Effbo.js} +2 -2
- package/dist/standalone/assets/command-Df4Effbo.js.br +0 -0
- package/dist/standalone/assets/command-Df4Effbo.js.gz +0 -0
- package/dist/standalone/assets/{command-BNF_evMy.js.map → command-Df4Effbo.js.map} +1 -1
- package/dist/standalone/assets/{date-picker-LfbUehd1.js → date-picker-BM6tYOT1.js} +2 -2
- package/dist/standalone/assets/date-picker-BM6tYOT1.js.br +0 -0
- package/dist/standalone/assets/date-picker-BM6tYOT1.js.gz +0 -0
- package/dist/standalone/assets/{date-picker-LfbUehd1.js.map → date-picker-BM6tYOT1.js.map} +1 -1
- package/dist/standalone/assets/{edit-page-DCRB9Y_q.js → edit-page-C_QYbzrq.js} +2 -2
- package/dist/standalone/assets/edit-page-C_QYbzrq.js.br +0 -0
- package/dist/standalone/assets/edit-page-C_QYbzrq.js.gz +0 -0
- package/dist/standalone/assets/{edit-page-DCRB9Y_q.js.map → edit-page-C_QYbzrq.js.map} +1 -1
- package/dist/standalone/assets/{empty-DAEAjFd3.js → empty-BQFNUnfh.js} +2 -2
- package/dist/standalone/assets/empty-BQFNUnfh.js.br +0 -0
- package/dist/standalone/assets/empty-BQFNUnfh.js.gz +0 -0
- package/dist/standalone/assets/{empty-DAEAjFd3.js.map → empty-BQFNUnfh.js.map} +1 -1
- package/dist/standalone/assets/{global-search-dialog-HMLztOho.js → global-search-dialog-DMgCfJpF.js} +2 -2
- package/dist/standalone/assets/global-search-dialog-DMgCfJpF.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-DMgCfJpF.js.gz +0 -0
- package/dist/standalone/assets/{global-search-dialog-HMLztOho.js.map → global-search-dialog-DMgCfJpF.js.map} +1 -1
- package/dist/standalone/assets/{heavy-fields-ZuqfOFMv.js → heavy-fields-Do2qd-Wi.js} +2 -2
- package/dist/standalone/assets/heavy-fields-Do2qd-Wi.js.br +0 -0
- package/dist/standalone/assets/{heavy-fields-ZuqfOFMv.js.gz → heavy-fields-Do2qd-Wi.js.gz} +0 -0
- package/dist/standalone/assets/{heavy-fields-ZuqfOFMv.js.map → heavy-fields-Do2qd-Wi.js.map} +1 -1
- package/dist/standalone/assets/{home-page-HmheewiP.js → home-page-eGVeZnKR.js} +3 -3
- package/dist/standalone/assets/home-page-eGVeZnKR.js.br +0 -0
- package/dist/standalone/assets/home-page-eGVeZnKR.js.gz +0 -0
- package/dist/standalone/assets/{home-page-HmheewiP.js.map → home-page-eGVeZnKR.js.map} +1 -1
- package/dist/standalone/assets/{icon-registry-BV44--RL.js → icon-registry-BroqBCns.js} +2 -2
- package/dist/standalone/assets/icon-registry-BroqBCns.js.br +0 -0
- package/dist/standalone/assets/{icon-registry-BV44--RL.js.gz → icon-registry-BroqBCns.js.gz} +0 -0
- package/dist/standalone/assets/{icon-registry-BV44--RL.js.map → icon-registry-BroqBCns.js.map} +1 -1
- package/dist/standalone/assets/index-C3MuojaM.js +15 -0
- package/dist/standalone/assets/index-C3MuojaM.js.br +0 -0
- package/dist/standalone/assets/index-C3MuojaM.js.gz +0 -0
- package/dist/standalone/assets/{index-t4woXGa-.js.map → index-C3MuojaM.js.map} +1 -1
- package/dist/standalone/assets/{json-editor-sGw4fDoj.js → json-editor-BQLKoybQ.js} +2 -2
- package/dist/standalone/assets/json-editor-BQLKoybQ.js.br +0 -0
- package/dist/standalone/assets/json-editor-BQLKoybQ.js.gz +0 -0
- package/dist/standalone/assets/{json-editor-sGw4fDoj.js.map → json-editor-BQLKoybQ.js.map} +1 -1
- package/dist/standalone/assets/{property-renderer-DyCwdVkh.js → property-renderer--LvNtRJE.js} +4 -4
- package/dist/standalone/assets/property-renderer--LvNtRJE.js.br +0 -0
- package/dist/standalone/assets/property-renderer--LvNtRJE.js.gz +0 -0
- package/dist/standalone/assets/{property-renderer-DyCwdVkh.js.map → property-renderer--LvNtRJE.js.map} +1 -1
- package/dist/standalone/assets/{reference-Dfd804y3.js → reference-UuQ6Jts1.js} +2 -2
- package/dist/standalone/assets/reference-UuQ6Jts1.js.br +0 -0
- package/dist/standalone/assets/reference-UuQ6Jts1.js.gz +0 -0
- package/dist/standalone/assets/{reference-Dfd804y3.js.map → reference-UuQ6Jts1.js.map} +1 -1
- package/dist/standalone/assets/{revisions-button-DXZAh2Lu.js → revisions-button-DHcQjj4r.js} +2 -2
- package/dist/standalone/assets/revisions-button-DHcQjj4r.js.br +0 -0
- package/dist/standalone/assets/revisions-button-DHcQjj4r.js.gz +0 -0
- package/dist/standalone/assets/{revisions-button-DXZAh2Lu.js.map → revisions-button-DHcQjj4r.js.map} +1 -1
- package/dist/standalone/assets/{select-BWf6walM.js → select-B30EsRTA.js} +2 -2
- package/dist/standalone/assets/select-B30EsRTA.js.br +0 -0
- package/dist/standalone/assets/select-B30EsRTA.js.gz +0 -0
- package/dist/standalone/assets/{select-BWf6walM.js.map → select-B30EsRTA.js.map} +1 -1
- package/dist/standalone/assets/{settings-page-Co7sWbbL.js → settings-page-3r5atVKG.js} +2 -2
- package/dist/standalone/assets/settings-page-3r5atVKG.js.br +0 -0
- package/dist/standalone/assets/settings-page-3r5atVKG.js.gz +0 -0
- package/dist/standalone/assets/{settings-page-Co7sWbbL.js.map → settings-page-3r5atVKG.js.map} +1 -1
- package/dist/standalone/assets/{show-page-D-_vldWV.js → show-page-CmRDBZRg.js} +2 -2
- package/dist/standalone/assets/show-page-CmRDBZRg.js.br +0 -0
- package/dist/standalone/assets/show-page-CmRDBZRg.js.gz +0 -0
- package/dist/standalone/assets/{show-page-D-_vldWV.js.map → show-page-CmRDBZRg.js.map} +1 -1
- package/dist/standalone/assets/{tabs-khcHka8W.js → tabs-BXeUKAN4.js} +2 -2
- package/dist/standalone/assets/tabs-BXeUKAN4.js.br +0 -0
- package/dist/standalone/assets/tabs-BXeUKAN4.js.gz +0 -0
- package/dist/standalone/assets/{tabs-khcHka8W.js.map → tabs-BXeUKAN4.js.map} +1 -1
- package/dist/standalone/assets/{value-format-CPnbnlE6.js → value-format-BikdS7In.js} +2 -2
- package/dist/standalone/assets/value-format-BikdS7In.js.br +0 -0
- package/dist/standalone/assets/value-format-BikdS7In.js.gz +0 -0
- package/dist/standalone/assets/{value-format-CPnbnlE6.js.map → value-format-BikdS7In.js.map} +1 -1
- package/dist/standalone/assets/{wizard-create-page-CFwMs8E3.js → wizard-create-page-ChrGqxlO.js} +2 -2
- package/dist/standalone/assets/wizard-create-page-ChrGqxlO.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-ChrGqxlO.js.gz +0 -0
- package/dist/standalone/assets/{wizard-create-page-CFwMs8E3.js.map → wizard-create-page-ChrGqxlO.js.map} +1 -1
- package/dist/standalone/assets/{zod-BbfEBA4A.js → zod-CF8JsamI.js} +2 -2
- package/dist/standalone/assets/zod-CF8JsamI.js.br +0 -0
- package/dist/standalone/assets/zod-CF8JsamI.js.gz +0 -0
- package/dist/standalone/assets/{zod-BbfEBA4A.js.map → zod-CF8JsamI.js.map} +1 -1
- package/dist/standalone/index.html +4 -4
- package/dist/standalone/index.html.br +0 -0
- package/dist/standalone/index.html.gz +0 -0
- package/package.json +28 -6
- package/src/mount.tsx +8 -2
- package/src/standalone.tsx +1 -0
- package/src/vite.ts +219 -0
- package/vite.config.ts +13 -104
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.br +0 -0
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.gz +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.br +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.gz +0 -0
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.gz +0 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.gz +0 -0
- package/dist/standalone/assets/calendar-BZVUWakC.js.br +0 -0
- package/dist/standalone/assets/calendar-BZVUWakC.js.gz +0 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.br +0 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.gz +0 -0
- package/dist/standalone/assets/command-BNF_evMy.js.br +0 -0
- package/dist/standalone/assets/command-BNF_evMy.js.gz +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js.br +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js.gz +0 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.br +0 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.gz +0 -0
- package/dist/standalone/assets/empty-DAEAjFd3.js.br +0 -0
- package/dist/standalone/assets/empty-DAEAjFd3.js.gz +0 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.gz +0 -0
- package/dist/standalone/assets/heavy-fields-ZuqfOFMv.js.br +0 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.br +0 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.gz +0 -0
- package/dist/standalone/assets/icon-registry-BV44--RL.js.br +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js +0 -15
- package/dist/standalone/assets/index-t4woXGa-.js.br +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js.gz +0 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.br +0 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.br +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.gz +0 -0
- package/dist/standalone/assets/reference-Dfd804y3.js.br +0 -0
- package/dist/standalone/assets/reference-Dfd804y3.js.gz +0 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.br +0 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.gz +0 -0
- package/dist/standalone/assets/select-BWf6walM.js.br +0 -0
- package/dist/standalone/assets/select-BWf6walM.js.gz +0 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.br +0 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.gz +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.br +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.gz +0 -0
- package/dist/standalone/assets/tabs-khcHka8W.js.br +0 -0
- package/dist/standalone/assets/tabs-khcHka8W.js.gz +0 -0
- package/dist/standalone/assets/value-format-CPnbnlE6.js.br +0 -0
- package/dist/standalone/assets/value-format-CPnbnlE6.js.gz +0 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.gz +0 -0
- package/dist/standalone/assets/zod-BbfEBA4A.js.br +0 -0
- package/dist/standalone/assets/zod-BbfEBA4A.js.gz +0 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
smoke tests), the standalone entry falls back to same-origin defaults.
|
|
13
13
|
-->
|
|
14
14
|
<!--MODERN_ADMIN_CONFIG-->
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-C3MuojaM.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/createLucideIcon-CUopU_LC.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/with-selector-NDLhu4dT.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/dist-BSbFjTlr.js">
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
<link rel="modulepreload" crossorigin href="./assets/router-wFvtgo77.js">
|
|
22
22
|
<link rel="modulepreload" crossorigin href="./assets/dist-BcL2U6dT.js">
|
|
23
23
|
<link rel="stylesheet" crossorigin href="./assets/index-95cwJ2RY.css">
|
|
24
|
-
<link rel="prefetch" as="script" href="./assets/home-page-
|
|
25
|
-
<link rel="prefetch" as="script" href="./assets/icon-registry-
|
|
26
|
-
<link rel="prefetch" as="script" href="./assets/property-renderer
|
|
24
|
+
<link rel="prefetch" as="script" href="./assets/home-page-eGVeZnKR.js">
|
|
25
|
+
<link rel="prefetch" as="script" href="./assets/icon-registry-BroqBCns.js">
|
|
26
|
+
<link rel="prefetch" as="script" href="./assets/property-renderer--LvNtRJE.js">
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
29
29
|
<div id="root"></div>
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modern-admin/web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Pre-built React admin SPA. Mount it into a host page or let @modern-admin/nest serve the standalone bundle.",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"types": "./dist/lib/index.d.ts",
|
|
36
36
|
"default": "./dist/lib/index.js"
|
|
37
37
|
},
|
|
38
|
+
"./vite": {
|
|
39
|
+
"types": "./dist/config/vite.d.ts",
|
|
40
|
+
"default": "./dist/config/vite.js"
|
|
41
|
+
},
|
|
38
42
|
"./standalone/*": "./dist/standalone/*",
|
|
39
43
|
"./package.json": "./package.json"
|
|
40
44
|
},
|
|
@@ -48,23 +52,30 @@
|
|
|
48
52
|
"types": "./dist/lib/index.d.ts",
|
|
49
53
|
"default": "./dist/lib/index.js"
|
|
50
54
|
},
|
|
55
|
+
"./vite": {
|
|
56
|
+
"types": "./dist/config/vite.d.ts",
|
|
57
|
+
"default": "./dist/config/vite.js"
|
|
58
|
+
},
|
|
51
59
|
"./standalone/*": "./dist/standalone/*",
|
|
52
60
|
"./package.json": "./package.json"
|
|
53
61
|
}
|
|
54
62
|
},
|
|
55
63
|
"peerDependencies": {
|
|
56
64
|
"react": "^19.2.6",
|
|
57
|
-
"react-dom": "^19.2.6"
|
|
65
|
+
"react-dom": "^19.2.6",
|
|
66
|
+
"@tailwindcss/vite": "^4.2.4",
|
|
67
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
68
|
+
"vite": "^8.0.10"
|
|
58
69
|
},
|
|
59
70
|
"dependencies": {
|
|
60
|
-
"@modern-admin/core": "^0.3.
|
|
71
|
+
"@modern-admin/core": "^0.3.5",
|
|
61
72
|
"@modern-admin/i18n": "^0.3.4",
|
|
62
|
-
"@modern-admin/react": "^0.
|
|
63
|
-
"@modern-admin/ui": "^0.
|
|
73
|
+
"@modern-admin/react": "^0.4.0",
|
|
74
|
+
"@modern-admin/ui": "^0.4.0",
|
|
64
75
|
"@tanstack/react-query": "^5.100.9"
|
|
65
76
|
},
|
|
66
77
|
"devDependencies": {
|
|
67
|
-
"@modern-admin/tsconfig": "0.
|
|
78
|
+
"@modern-admin/tsconfig": "0.4.0",
|
|
68
79
|
"@tailwindcss/vite": "^4.2.4",
|
|
69
80
|
"@types/react": "^19.2.14",
|
|
70
81
|
"@types/react-dom": "^19.2.3",
|
|
@@ -75,5 +86,16 @@
|
|
|
75
86
|
"typescript": "^6.0.3",
|
|
76
87
|
"vite": "^8.0.10",
|
|
77
88
|
"vite-plugin-dts": "^5.0.1"
|
|
89
|
+
},
|
|
90
|
+
"peerDependenciesMeta": {
|
|
91
|
+
"@tailwindcss/vite": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"@vitejs/plugin-react": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"vite": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
78
100
|
}
|
|
79
101
|
}
|
package/src/mount.tsx
CHANGED
|
@@ -5,15 +5,21 @@
|
|
|
5
5
|
* import { mount } from '@modern-admin/web'
|
|
6
6
|
* mount(document.getElementById('root')!, { apiUrl: 'https://api.example.com' })
|
|
7
7
|
*
|
|
8
|
+
* This module deliberately does **not** import the stylesheet: an app that
|
|
9
|
+
* registers its own components needs to own the Tailwind root so its classes
|
|
10
|
+
* get scanned, and a second root here would compile Tailwind twice. Import it
|
|
11
|
+
* yourself, either directly or from your own CSS:
|
|
12
|
+
*
|
|
13
|
+
* import '@modern-admin/react/styles.css'
|
|
14
|
+
*
|
|
8
15
|
* For the prebuilt standalone bundle, `src/standalone.tsx` calls this for
|
|
9
|
-
* you using `window.__MODERN_ADMIN__
|
|
16
|
+
* you using `window.__MODERN_ADMIN__` and pulls in the stylesheet.
|
|
10
17
|
*/
|
|
11
18
|
|
|
12
19
|
import { StrictMode } from 'react'
|
|
13
20
|
import { createRoot, type Root } from 'react-dom/client'
|
|
14
21
|
import { type ComponentLoader } from '@modern-admin/react'
|
|
15
22
|
import { initTheme } from '@modern-admin/ui'
|
|
16
|
-
import '@modern-admin/ui/styles.css'
|
|
17
23
|
import { App } from './app.js'
|
|
18
24
|
import type { ModernAdminRuntimeConfig } from './runtime-config.js'
|
|
19
25
|
|
package/src/standalone.tsx
CHANGED
package/src/vite.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite config kit for apps that build their own copy of the admin SPA.
|
|
3
|
+
*
|
|
4
|
+
* The prebuilt `@modern-admin/web` standalone bundle registers no custom
|
|
5
|
+
* components, so any app that uses `component: '…'` on an action or
|
|
6
|
+
* `components: { edit: '…' }` on a property has to build its own bundle. That
|
|
7
|
+
* bundle has to match what `@modern-admin/nest`'s StaticUiMiddleware expects
|
|
8
|
+
* — `dist/standalone/{index.html,assets/**}` with relative `./assets/` URLs —
|
|
9
|
+
* which used to mean copying this package's `vite.config.ts` wholesale.
|
|
10
|
+
*
|
|
11
|
+
* // vite.config.ts
|
|
12
|
+
* import { defineAdminAppConfig } from '@modern-admin/web/vite'
|
|
13
|
+
* export default defineAdminAppConfig({ apiProxy: 'http://localhost:3011' })
|
|
14
|
+
*
|
|
15
|
+
* // src/main.tsx
|
|
16
|
+
* import { mount, readWindowConfig } from '@modern-admin/web'
|
|
17
|
+
* import './styles.css'
|
|
18
|
+
* mount(document.getElementById('root')!, {
|
|
19
|
+
* config: readWindowConfig(),
|
|
20
|
+
* components: new ComponentLoader().add('SendPushForm', SendPushForm),
|
|
21
|
+
* })
|
|
22
|
+
*
|
|
23
|
+
* `packages/web/vite.config.ts` consumes this same factory, so the kit can't
|
|
24
|
+
* drift from the bundle we ship.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import path from 'node:path'
|
|
28
|
+
import { promises as fs } from 'node:fs'
|
|
29
|
+
import { promisify } from 'node:util'
|
|
30
|
+
import zlib from 'node:zlib'
|
|
31
|
+
import type { ConfigEnv, Plugin, PluginOption, UserConfig } from 'vite'
|
|
32
|
+
import react from '@vitejs/plugin-react'
|
|
33
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
34
|
+
import type { ModernAdminRuntimeConfig } from './runtime-config.js'
|
|
35
|
+
|
|
36
|
+
const brotli = promisify(zlib.brotliCompress)
|
|
37
|
+
const gzip = promisify(zlib.gzip)
|
|
38
|
+
|
|
39
|
+
/** Layout StaticUiMiddleware resolves as `<webPackage>/dist/standalone`. */
|
|
40
|
+
const STANDALONE_OUT_DIR = 'dist/standalone'
|
|
41
|
+
|
|
42
|
+
export interface AdminAppConfigOptions {
|
|
43
|
+
/** Dev server port. Defaults to `WEB_PORT`, then 3000. */
|
|
44
|
+
port?: number
|
|
45
|
+
/**
|
|
46
|
+
* Origin of the NestJS admin API, proxied during `vite dev` so the SPA and
|
|
47
|
+
* the API stay same-origin and session cookies work (e.g.
|
|
48
|
+
* `http://localhost:3011`). Omit if you serve both yourself.
|
|
49
|
+
*/
|
|
50
|
+
apiProxy?: string
|
|
51
|
+
/**
|
|
52
|
+
* Path prefixes forwarded to `apiProxy`. Defaults to the REST/auth prefix
|
|
53
|
+
* every `@modern-admin/nest` controller lives under plus the socket.io
|
|
54
|
+
* endpoint used by `@modern-admin/realtime`.
|
|
55
|
+
*/
|
|
56
|
+
apiProxyPath?: string | string[]
|
|
57
|
+
/**
|
|
58
|
+
* Runtime config for `vite dev` only. In production the host server
|
|
59
|
+
* injects `window.__MODERN_ADMIN__` into the shell, so there is nothing to
|
|
60
|
+
* configure at build time — this fills the same slot while developing.
|
|
61
|
+
*/
|
|
62
|
+
devConfig?: ModernAdminRuntimeConfig
|
|
63
|
+
/** Directory the standalone build writes to. Rarely worth changing. */
|
|
64
|
+
outDir?: string
|
|
65
|
+
/** Extra plugins, appended after the built-in ones. */
|
|
66
|
+
plugins?: PluginOption[]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Emits `.br` and `.gz` siblings next to every compressible standalone
|
|
71
|
+
* asset. StaticUiMiddleware serves whichever variant the browser's
|
|
72
|
+
* `Accept-Encoding` allows and falls back to the plain file, so this is an
|
|
73
|
+
* optimisation rather than a correctness requirement.
|
|
74
|
+
*/
|
|
75
|
+
export function precompressPlugin(outDir = STANDALONE_OUT_DIR): Plugin {
|
|
76
|
+
const COMPRESSIBLE = new Set(['.js', '.mjs', '.css', '.html', '.svg', '.json'])
|
|
77
|
+
const MIN_SIZE = 1024
|
|
78
|
+
return {
|
|
79
|
+
name: 'modern-admin:precompress',
|
|
80
|
+
apply: 'build',
|
|
81
|
+
async writeBundle(options) {
|
|
82
|
+
const dir = options.dir ?? path.resolve(process.cwd(), outDir)
|
|
83
|
+
const walk = async (d: string): Promise<string[]> => {
|
|
84
|
+
const entries = await fs.readdir(d, { withFileTypes: true })
|
|
85
|
+
const nested = await Promise.all(
|
|
86
|
+
entries.map((e) => (e.isDirectory() ? walk(path.join(d, e.name)) : [path.join(d, e.name)])),
|
|
87
|
+
)
|
|
88
|
+
return nested.flat()
|
|
89
|
+
}
|
|
90
|
+
const files = (await walk(dir)).filter((f) => COMPRESSIBLE.has(path.extname(f)))
|
|
91
|
+
await Promise.all(
|
|
92
|
+
files.map(async (file) => {
|
|
93
|
+
const source = await fs.readFile(file)
|
|
94
|
+
if (source.length < MIN_SIZE) return
|
|
95
|
+
const [br, gz] = await Promise.all([
|
|
96
|
+
brotli(source, { params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 } }),
|
|
97
|
+
gzip(source, { level: zlib.constants.Z_BEST_COMPRESSION }),
|
|
98
|
+
])
|
|
99
|
+
await Promise.all([fs.writeFile(`${file}.br`, br), fs.writeFile(`${file}.gz`, gz)])
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Injects low-priority `<link rel="prefetch">` hints for the lazy chunks a
|
|
108
|
+
* fresh session is almost certain to need right after the shell renders:
|
|
109
|
+
* the dashboard landing page, the full icon registry (sidebar), and the
|
|
110
|
+
* resource list page + property renderer (first sidebar click). The browser
|
|
111
|
+
* fetches them during idle time instead of on first navigation, without
|
|
112
|
+
* competing with the critical-path entry chunk. Relative `./assets/` hrefs
|
|
113
|
+
* are rewritten to the mount path by StaticUiMiddleware like every other
|
|
114
|
+
* asset reference.
|
|
115
|
+
*/
|
|
116
|
+
export function prefetchHintsPlugin(): Plugin {
|
|
117
|
+
const PREFETCH_CHUNKS = new Set(['home-page', 'icon-registry', 'list-page', 'property-renderer'])
|
|
118
|
+
return {
|
|
119
|
+
name: 'modern-admin:prefetch-hints',
|
|
120
|
+
apply: 'build',
|
|
121
|
+
transformIndexHtml: {
|
|
122
|
+
order: 'post',
|
|
123
|
+
handler(_html, ctx) {
|
|
124
|
+
const chunks = Object.values(ctx.bundle ?? {}).filter(
|
|
125
|
+
(out) => out.type === 'chunk' && out.name && PREFETCH_CHUNKS.has(out.name),
|
|
126
|
+
)
|
|
127
|
+
return chunks.map((chunk) => ({
|
|
128
|
+
tag: 'link',
|
|
129
|
+
attrs: { rel: 'prefetch', as: 'script', href: `./${chunk.fileName}` },
|
|
130
|
+
injectTo: 'head' as const,
|
|
131
|
+
}))
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Injects `window.__MODERN_ADMIN__` while developing. In production the same
|
|
139
|
+
* slot is filled per-request by the host server (StaticUiMiddleware replaces
|
|
140
|
+
* the `<!--MODERN_ADMIN_CONFIG-->` marker, or falls back to `</head>`), so
|
|
141
|
+
* this plugin is dev-only and never affects the built bundle.
|
|
142
|
+
*/
|
|
143
|
+
export function devRuntimeConfigPlugin(config: ModernAdminRuntimeConfig): Plugin {
|
|
144
|
+
return {
|
|
145
|
+
name: 'modern-admin:dev-runtime-config',
|
|
146
|
+
apply: 'serve',
|
|
147
|
+
transformIndexHtml: {
|
|
148
|
+
order: 'pre',
|
|
149
|
+
handler() {
|
|
150
|
+
// `</script>` inside the JSON would close the tag early.
|
|
151
|
+
const json = JSON.stringify(config).replace(/</g, '\\u003c')
|
|
152
|
+
return [
|
|
153
|
+
{
|
|
154
|
+
tag: 'script',
|
|
155
|
+
children: `window.__MODERN_ADMIN__ = ${json};`,
|
|
156
|
+
injectTo: 'head-prepend' as const,
|
|
157
|
+
},
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* `ws: true` so the realtime gateway's socket.io upgrade survives the proxy;
|
|
166
|
+
* `changeOrigin` keeps the session cookie's Origin check happy.
|
|
167
|
+
*/
|
|
168
|
+
function buildProxy(
|
|
169
|
+
target: string,
|
|
170
|
+
paths: string | string[],
|
|
171
|
+
): Record<string, { target: string; changeOrigin: boolean; ws: boolean }> {
|
|
172
|
+
const list = Array.isArray(paths) ? paths : [paths]
|
|
173
|
+
return Object.fromEntries(list.map((p) => [p, { target, changeOrigin: true, ws: true }]))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Builds the Vite config for a custom admin SPA. Pass the result straight to
|
|
178
|
+
* `export default` — it resolves `vite dev` and `vite build` itself, so no
|
|
179
|
+
* `--mode` flag is required.
|
|
180
|
+
*/
|
|
181
|
+
export function defineAdminAppConfig(
|
|
182
|
+
options: AdminAppConfigOptions = {},
|
|
183
|
+
): (env: ConfigEnv) => UserConfig {
|
|
184
|
+
const {
|
|
185
|
+
apiProxy,
|
|
186
|
+
apiProxyPath = ['/admin/api', '/socket.io'],
|
|
187
|
+
devConfig,
|
|
188
|
+
outDir = STANDALONE_OUT_DIR,
|
|
189
|
+
plugins: extraPlugins = [],
|
|
190
|
+
} = options
|
|
191
|
+
return ({ command }) => {
|
|
192
|
+
const shared: PluginOption[] = [react(), tailwindcss()]
|
|
193
|
+
if (command === 'build') {
|
|
194
|
+
return {
|
|
195
|
+
plugins: [...shared, precompressPlugin(outDir), prefetchHintsPlugin(), ...extraPlugins],
|
|
196
|
+
// Relative base so one bundle can be mounted under any path — the
|
|
197
|
+
// host server rewrites `./assets/` to its own mount prefix.
|
|
198
|
+
base: './',
|
|
199
|
+
build: {
|
|
200
|
+
outDir,
|
|
201
|
+
emptyOutDir: true,
|
|
202
|
+
sourcemap: true,
|
|
203
|
+
},
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
plugins: [
|
|
208
|
+
...shared,
|
|
209
|
+
...(devConfig ? [devRuntimeConfigPlugin(devConfig)] : []),
|
|
210
|
+
...extraPlugins,
|
|
211
|
+
],
|
|
212
|
+
server: {
|
|
213
|
+
port: options.port ?? Number(process.env.WEB_PORT ?? 3000),
|
|
214
|
+
host: true,
|
|
215
|
+
...(apiProxy ? { proxy: buildProxy(apiProxy, apiProxyPath) } : {}),
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
package/vite.config.ts
CHANGED
|
@@ -7,61 +7,23 @@
|
|
|
7
7
|
* `mode` is set by Vite from the `--mode` CLI flag. Other modes (dev,
|
|
8
8
|
* preview) get the standalone SPA config — that's what you serve from
|
|
9
9
|
* `bun run dev`.
|
|
10
|
+
*
|
|
11
|
+
* The standalone/dev half is `defineAdminAppConfig()` from `src/vite.ts`,
|
|
12
|
+
* i.e. the very config we hand to apps that build their own bundle
|
|
13
|
+
* (`@modern-admin/web/vite`). Dogfooding it here is what stops the two from
|
|
14
|
+
* drifting apart.
|
|
10
15
|
*/
|
|
11
16
|
|
|
12
|
-
import { defineConfig, type
|
|
17
|
+
import { defineConfig, type UserConfig } from 'vite'
|
|
13
18
|
import react from '@vitejs/plugin-react'
|
|
14
19
|
import tailwindcss from '@tailwindcss/vite'
|
|
15
20
|
import dts from 'vite-plugin-dts'
|
|
16
21
|
import { fileURLToPath } from 'node:url'
|
|
17
22
|
import path from 'node:path'
|
|
18
|
-
import {
|
|
19
|
-
import { promisify } from 'node:util'
|
|
20
|
-
import zlib from 'node:zlib'
|
|
23
|
+
import { defineAdminAppConfig } from './src/vite.js'
|
|
21
24
|
|
|
22
25
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
23
26
|
|
|
24
|
-
const brotli = promisify(zlib.brotliCompress)
|
|
25
|
-
const gzip = promisify(zlib.gzip)
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Emits `.br` and `.gz` siblings next to every compressible standalone
|
|
29
|
-
* asset. `@modern-admin/nest`'s StaticUiMiddleware picks whichever variant
|
|
30
|
-
* the browser's `Accept-Encoding` allows — no runtime compression cost.
|
|
31
|
-
* Sourcemaps are skipped (fetched only with devtools open) and so are
|
|
32
|
-
* files that compression wouldn't meaningfully shrink.
|
|
33
|
-
*/
|
|
34
|
-
function precompressPlugin(): Plugin {
|
|
35
|
-
const COMPRESSIBLE = new Set(['.js', '.mjs', '.css', '.html', '.svg', '.json'])
|
|
36
|
-
const MIN_SIZE = 1024
|
|
37
|
-
return {
|
|
38
|
-
name: 'modern-admin:precompress',
|
|
39
|
-
apply: 'build',
|
|
40
|
-
async writeBundle(options) {
|
|
41
|
-
const dir = options.dir ?? path.resolve(__dirname, 'dist/standalone')
|
|
42
|
-
const walk = async (d: string): Promise<string[]> => {
|
|
43
|
-
const entries = await fs.readdir(d, { withFileTypes: true })
|
|
44
|
-
const nested = await Promise.all(
|
|
45
|
-
entries.map((e) => (e.isDirectory() ? walk(path.join(d, e.name)) : [path.join(d, e.name)])),
|
|
46
|
-
)
|
|
47
|
-
return nested.flat()
|
|
48
|
-
}
|
|
49
|
-
const files = (await walk(dir)).filter((f) => COMPRESSIBLE.has(path.extname(f)))
|
|
50
|
-
await Promise.all(
|
|
51
|
-
files.map(async (file) => {
|
|
52
|
-
const source = await fs.readFile(file)
|
|
53
|
-
if (source.length < MIN_SIZE) return
|
|
54
|
-
const [br, gz] = await Promise.all([
|
|
55
|
-
brotli(source, { params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 } }),
|
|
56
|
-
gzip(source, { level: zlib.constants.Z_BEST_COMPRESSION }),
|
|
57
|
-
])
|
|
58
|
-
await Promise.all([fs.writeFile(`${file}.br`, br), fs.writeFile(`${file}.gz`, gz)])
|
|
59
|
-
}),
|
|
60
|
-
)
|
|
61
|
-
},
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
27
|
// External deps for the library build — host apps provide their own copy
|
|
66
28
|
// (deduped by the workspace / package manager). The standalone SPA bundle
|
|
67
29
|
// inlines all of these so the served `<script>` is self-contained.
|
|
@@ -101,7 +63,7 @@ const libConfig: UserConfig = {
|
|
|
101
63
|
entryRoot: 'src',
|
|
102
64
|
outDirs: 'dist/lib',
|
|
103
65
|
include: ['src/**/*.ts', 'src/**/*.tsx'],
|
|
104
|
-
exclude: ['src/standalone.tsx'],
|
|
66
|
+
exclude: ['src/standalone.tsx', 'src/vite.ts'],
|
|
105
67
|
}),
|
|
106
68
|
],
|
|
107
69
|
// Don't copy public/ (favicon.svg etc.) into the library output — those
|
|
@@ -122,62 +84,9 @@ const libConfig: UserConfig = {
|
|
|
122
84
|
},
|
|
123
85
|
}
|
|
124
86
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* resource list page + property renderer (first sidebar click). The browser
|
|
130
|
-
* fetches them during idle time instead of on first navigation, without
|
|
131
|
-
* competing with the critical-path entry chunk. Relative `./assets/` hrefs
|
|
132
|
-
* are rewritten to the mount path by StaticUiMiddleware like every other
|
|
133
|
-
* asset reference.
|
|
134
|
-
*/
|
|
135
|
-
function prefetchHintsPlugin(): Plugin {
|
|
136
|
-
const PREFETCH_CHUNKS = new Set(['home-page', 'icon-registry', 'list-page', 'property-renderer'])
|
|
137
|
-
return {
|
|
138
|
-
name: 'modern-admin:prefetch-hints',
|
|
139
|
-
apply: 'build',
|
|
140
|
-
transformIndexHtml: {
|
|
141
|
-
order: 'post',
|
|
142
|
-
handler(_html, ctx) {
|
|
143
|
-
const chunks = Object.values(ctx.bundle ?? {}).filter(
|
|
144
|
-
(out) => out.type === 'chunk' && out.name && PREFETCH_CHUNKS.has(out.name),
|
|
145
|
-
)
|
|
146
|
-
return chunks.map((chunk) => ({
|
|
147
|
-
tag: 'link',
|
|
148
|
-
attrs: { rel: 'prefetch', as: 'script', href: `./${chunk.fileName}` },
|
|
149
|
-
injectTo: 'head' as const,
|
|
150
|
-
}))
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const standaloneConfig: UserConfig = {
|
|
157
|
-
plugins: [react(), tailwindcss(), precompressPlugin(), prefetchHintsPlugin()],
|
|
158
|
-
// Relative base so the same bundle can be mounted under any path
|
|
159
|
-
// (e.g. `/admin/`) — the server rewrites asset URLs in index.html.
|
|
160
|
-
base: './',
|
|
161
|
-
build: {
|
|
162
|
-
outDir: 'dist/standalone',
|
|
163
|
-
emptyOutDir: true,
|
|
164
|
-
sourcemap: true,
|
|
165
|
-
rollupOptions: {
|
|
166
|
-
input: path.resolve(__dirname, 'index.html'),
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const devConfig: UserConfig = {
|
|
172
|
-
plugins: [react(), tailwindcss()],
|
|
173
|
-
server: {
|
|
174
|
-
port: Number(process.env.WEB_PORT ?? 3000),
|
|
175
|
-
host: true,
|
|
176
|
-
},
|
|
177
|
-
}
|
|
87
|
+
// `vite build --mode standalone` arrives as command 'build'; `vite` and
|
|
88
|
+
// `vite preview` as 'serve'. Rollup's input defaults to `<root>/index.html`,
|
|
89
|
+
// which is exactly the shell this package ships.
|
|
90
|
+
const adminApp = defineAdminAppConfig()
|
|
178
91
|
|
|
179
|
-
export default defineConfig((
|
|
180
|
-
if (mode === 'lib') return libConfig
|
|
181
|
-
if (mode === 'standalone') return standaloneConfig
|
|
182
|
-
return devConfig
|
|
183
|
-
})
|
|
92
|
+
export default defineConfig((env) => (env.mode === 'lib' ? libConfig : adminApp(env)))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|