@nsxbet/admin-sdk 0.1.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 +680 -0
- package/dist/auth/client/in-memory.d.ts +27 -0
- package/dist/auth/client/in-memory.d.ts.map +1 -0
- package/dist/auth/client/in-memory.js +242 -0
- package/dist/auth/client/index.d.ts +7 -0
- package/dist/auth/client/index.d.ts.map +1 -0
- package/dist/auth/client/index.js +7 -0
- package/dist/auth/client/interface.d.ts +115 -0
- package/dist/auth/client/interface.d.ts.map +1 -0
- package/dist/auth/client/interface.js +7 -0
- package/dist/auth/client/keycloak.d.ts +19 -0
- package/dist/auth/client/keycloak.d.ts.map +1 -0
- package/dist/auth/client/keycloak.js +126 -0
- package/dist/auth/components/UserSelector.d.ts +19 -0
- package/dist/auth/components/UserSelector.d.ts.map +1 -0
- package/dist/auth/components/UserSelector.js +100 -0
- package/dist/auth/components/index.d.ts +5 -0
- package/dist/auth/components/index.d.ts.map +1 -0
- package/dist/auth/components/index.js +4 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -0
- package/dist/components/AuthProvider.d.ts +48 -0
- package/dist/components/AuthProvider.d.ts.map +1 -0
- package/dist/components/AuthProvider.js +117 -0
- package/dist/hooks/useAuth.d.ts +21 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +34 -0
- package/dist/hooks/useFetch.d.ts +8 -0
- package/dist/hooks/useFetch.d.ts.map +1 -0
- package/dist/hooks/useFetch.js +31 -0
- package/dist/hooks/useI18n.d.ts +46 -0
- package/dist/hooks/useI18n.d.ts.map +1 -0
- package/dist/hooks/useI18n.js +95 -0
- package/dist/hooks/usePlatformAPI.d.ts +12 -0
- package/dist/hooks/usePlatformAPI.d.ts.map +1 -0
- package/dist/hooks/usePlatformAPI.js +10 -0
- package/dist/hooks/useTelemetry.d.ts +17 -0
- package/dist/hooks/useTelemetry.d.ts.map +1 -0
- package/dist/hooks/useTelemetry.js +36 -0
- package/dist/i18n/config.d.ts +26 -0
- package/dist/i18n/config.d.ts.map +1 -0
- package/dist/i18n/config.js +92 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +4 -0
- package/dist/i18n/locales/en-US.json +144 -0
- package/dist/i18n/locales/es.json +144 -0
- package/dist/i18n/locales/pt-BR.json +144 -0
- package/dist/i18n/locales/ro.json +144 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/registry/AdminShellRegistry.d.ts +140 -0
- package/dist/registry/AdminShellRegistry.d.ts.map +1 -0
- package/dist/registry/AdminShellRegistry.js +237 -0
- package/dist/registry/client/http.d.ts +21 -0
- package/dist/registry/client/http.d.ts.map +1 -0
- package/dist/registry/client/http.js +107 -0
- package/dist/registry/client/in-memory.d.ts +36 -0
- package/dist/registry/client/in-memory.d.ts.map +1 -0
- package/dist/registry/client/in-memory.js +242 -0
- package/dist/registry/client/index.d.ts +7 -0
- package/dist/registry/client/index.d.ts.map +1 -0
- package/dist/registry/client/index.js +5 -0
- package/dist/registry/client/interface.d.ts +96 -0
- package/dist/registry/client/interface.d.ts.map +1 -0
- package/dist/registry/client/interface.js +7 -0
- package/dist/registry/index.d.ts +12 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/types/index.d.ts +9 -0
- package/dist/registry/types/index.d.ts.map +1 -0
- package/dist/registry/types/index.js +6 -0
- package/dist/registry/types/manifest.d.ts +98 -0
- package/dist/registry/types/manifest.d.ts.map +1 -0
- package/dist/registry/types/manifest.js +81 -0
- package/dist/registry/types/module.d.ts +115 -0
- package/dist/registry/types/module.d.ts.map +1 -0
- package/dist/registry/types/module.js +6 -0
- package/dist/router/DynamicModule.d.ts +50 -0
- package/dist/router/DynamicModule.d.ts.map +1 -0
- package/dist/router/DynamicModule.js +141 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +1 -0
- package/dist/shell/AdminShell.d.ts +38 -0
- package/dist/shell/AdminShell.d.ts.map +1 -0
- package/dist/shell/AdminShell.js +299 -0
- package/dist/shell/BackofficeShell.d.ts +38 -0
- package/dist/shell/BackofficeShell.d.ts.map +1 -0
- package/dist/shell/BackofficeShell.js +299 -0
- package/dist/shell/components/CommandPalette.d.ts +8 -0
- package/dist/shell/components/CommandPalette.d.ts.map +1 -0
- package/dist/shell/components/CommandPalette.js +197 -0
- package/dist/shell/components/HomePage.d.ts +2 -0
- package/dist/shell/components/HomePage.d.ts.map +1 -0
- package/dist/shell/components/HomePage.js +32 -0
- package/dist/shell/components/LeftNav.d.ts +7 -0
- package/dist/shell/components/LeftNav.d.ts.map +1 -0
- package/dist/shell/components/LeftNav.js +247 -0
- package/dist/shell/components/MainContent.d.ts +9 -0
- package/dist/shell/components/MainContent.d.ts.map +1 -0
- package/dist/shell/components/MainContent.js +88 -0
- package/dist/shell/components/ModuleOverview.d.ts +7 -0
- package/dist/shell/components/ModuleOverview.d.ts.map +1 -0
- package/dist/shell/components/ModuleOverview.js +40 -0
- package/dist/shell/components/ProfilePage.d.ts +2 -0
- package/dist/shell/components/ProfilePage.d.ts.map +1 -0
- package/dist/shell/components/ProfilePage.js +30 -0
- package/dist/shell/components/RegistryPage.d.ts +8 -0
- package/dist/shell/components/RegistryPage.d.ts.map +1 -0
- package/dist/shell/components/RegistryPage.js +129 -0
- package/dist/shell/components/SettingsPage.d.ts +2 -0
- package/dist/shell/components/SettingsPage.d.ts.map +1 -0
- package/dist/shell/components/SettingsPage.js +60 -0
- package/dist/shell/components/TopBar.d.ts +8 -0
- package/dist/shell/components/TopBar.d.ts.map +1 -0
- package/dist/shell/components/TopBar.js +61 -0
- package/dist/shell/components/index.d.ts +10 -0
- package/dist/shell/components/index.d.ts.map +1 -0
- package/dist/shell/components/index.js +7 -0
- package/dist/shell/components/theme-provider.d.ts +15 -0
- package/dist/shell/components/theme-provider.d.ts.map +1 -0
- package/dist/shell/components/theme-provider.js +39 -0
- package/dist/shell/index.d.ts +9 -0
- package/dist/shell/index.d.ts.map +1 -0
- package/dist/shell/index.js +8 -0
- package/dist/shell/search/fuzzy.d.ts +18 -0
- package/dist/shell/search/fuzzy.d.ts.map +1 -0
- package/dist/shell/search/fuzzy.js +121 -0
- package/dist/shell/search/index.d.ts +3 -0
- package/dist/shell/search/index.d.ts.map +1 -0
- package/dist/shell/search/index.js +1 -0
- package/dist/shell/telemetry.d.ts +7 -0
- package/dist/shell/telemetry.d.ts.map +1 -0
- package/dist/shell/telemetry.js +25 -0
- package/dist/shell/types.d.ts +110 -0
- package/dist/shell/types.d.ts.map +1 -0
- package/dist/shell/types.js +4 -0
- package/dist/tailwind/index.d.ts +20 -0
- package/dist/tailwind/index.d.ts.map +1 -0
- package/dist/tailwind/index.js +42 -0
- package/dist/types/keycloak.d.ts +26 -0
- package/dist/types/keycloak.d.ts.map +1 -0
- package/dist/types/keycloak.js +1 -0
- package/dist/types/platform.d.ts +83 -0
- package/dist/types/platform.d.ts.map +1 -0
- package/dist/types/platform.js +5 -0
- package/dist/vite/config.d.ts +71 -0
- package/dist/vite/config.d.ts.map +1 -0
- package/dist/vite/config.js +87 -0
- package/dist/vite/index.d.ts +18 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +17 -0
- package/dist/vite/plugins.d.ts +44 -0
- package/dist/vite/plugins.d.ts.map +1 -0
- package/dist/vite/plugins.js +74 -0
- package/package.json +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
# @nsxbet/admin-sdk
|
|
2
|
+
|
|
3
|
+
SDK for building admin modules for the NSX Admin platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @nsxbet/admin-sdk @nsxbet/admin-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Peer dependencies** (install these too):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add react react-dom react-router-dom i18next react-i18next
|
|
15
|
+
bun add -D @vitejs/plugin-react vite tailwindcss postcss autoprefixer typescript
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
This SDK enables you to build admin modules that integrate with the NSX Admin shell. Modules are loaded dynamically via React.lazy and share the shell's Router context.
|
|
21
|
+
|
|
22
|
+
**Key concepts:**
|
|
23
|
+
- Modules export a default React component from `spa.tsx`
|
|
24
|
+
- Modules share the shell's `BrowserRouter` - use `useNavigate()` from `react-router-dom` directly
|
|
25
|
+
- Use `@nsxbet/admin-ui` for consistent UI components
|
|
26
|
+
- Define module metadata in `admin.module.json`
|
|
27
|
+
|
|
28
|
+
## Architecture Overview
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
32
|
+
│ Shell (BrowserRouter) │
|
|
33
|
+
│ ├── TopBar, LeftNav, CommandPalette │
|
|
34
|
+
│ └── <Route path="/your-module/*"> │
|
|
35
|
+
│ └── React.lazy(() => import(baseUrl/spa.js)) │
|
|
36
|
+
│ └── Your App component (shares Router context) │
|
|
37
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Two entry points pattern:**
|
|
41
|
+
|
|
42
|
+
| File | Purpose | When used |
|
|
43
|
+
|------|---------|-----------|
|
|
44
|
+
| `src/spa.tsx` | Default export of App | Shell loads this via React.lazy |
|
|
45
|
+
| `src/standalone.tsx` | Full app with AdminShell wrapper | Local development (`npm run dev`) |
|
|
46
|
+
|
|
47
|
+
## Complete Module Example
|
|
48
|
+
|
|
49
|
+
Below are all the files needed for a working module. Copy these and modify for your needs.
|
|
50
|
+
|
|
51
|
+
### File: `vite.config.ts`
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { defineModuleConfig } from "@nsxbet/admin-sdk/vite";
|
|
55
|
+
import react from "@vitejs/plugin-react";
|
|
56
|
+
|
|
57
|
+
export default defineModuleConfig({
|
|
58
|
+
port: 3003,
|
|
59
|
+
plugins: [react()],
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### File: `admin.module.json`
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"id": "@admin/my-module",
|
|
68
|
+
"title": "My Module",
|
|
69
|
+
"description": "Description of what this module does",
|
|
70
|
+
"version": "1.0.0",
|
|
71
|
+
"category": "Tools",
|
|
72
|
+
"icon": "clipboard-list",
|
|
73
|
+
"routeBase": "/my-module",
|
|
74
|
+
"keywords": ["my", "module", "example"],
|
|
75
|
+
"commands": [
|
|
76
|
+
{
|
|
77
|
+
"id": "list",
|
|
78
|
+
"title": "List Items",
|
|
79
|
+
"route": "/my-module/list",
|
|
80
|
+
"icon": "file-text"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "new",
|
|
84
|
+
"title": "New Item",
|
|
85
|
+
"route": "/my-module/new",
|
|
86
|
+
"icon": "plus"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"permissions": {
|
|
90
|
+
"view": ["admin.mymodule.view"],
|
|
91
|
+
"edit": ["admin.mymodule.edit"],
|
|
92
|
+
"delete": ["admin.mymodule.delete"]
|
|
93
|
+
},
|
|
94
|
+
"owners": {
|
|
95
|
+
"team": "Platform",
|
|
96
|
+
"supportChannel": "#platform-support"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### File: `src/spa.tsx`
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
/**
|
|
105
|
+
* Module entry point for shell mode.
|
|
106
|
+
* The module shares the shell's Router context.
|
|
107
|
+
*/
|
|
108
|
+
import { App } from "./App";
|
|
109
|
+
|
|
110
|
+
export default App;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### File: `src/standalone.tsx`
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import React from "react";
|
|
117
|
+
import ReactDOM from "react-dom/client";
|
|
118
|
+
import { AdminShell, initI18n, i18n } from "@nsxbet/admin-sdk";
|
|
119
|
+
import type { AdminModuleManifest } from "@nsxbet/admin-sdk";
|
|
120
|
+
import { App } from "./App";
|
|
121
|
+
import manifest from "../admin.module.json";
|
|
122
|
+
|
|
123
|
+
import "./index.css";
|
|
124
|
+
|
|
125
|
+
// Import module translations (optional - for i18n support)
|
|
126
|
+
import enUS from "./i18n/locales/en-US.json";
|
|
127
|
+
import ptBR from "./i18n/locales/pt-BR.json";
|
|
128
|
+
|
|
129
|
+
// Initialize i18n BEFORE shell renders
|
|
130
|
+
initI18n();
|
|
131
|
+
|
|
132
|
+
// Register module translations with namespace matching your module
|
|
133
|
+
const NAMESPACE = "mymodule";
|
|
134
|
+
i18n.addResourceBundle("en-US", NAMESPACE, enUS, true, true);
|
|
135
|
+
i18n.addResourceBundle("pt-BR", NAMESPACE, ptBR, true, true);
|
|
136
|
+
|
|
137
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
138
|
+
<React.StrictMode>
|
|
139
|
+
<AdminShell modules={[manifest as AdminModuleManifest]}>
|
|
140
|
+
<App />
|
|
141
|
+
</AdminShell>
|
|
142
|
+
</React.StrictMode>
|
|
143
|
+
);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### File: `src/App.tsx`
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { Routes, Route, Navigate } from "react-router-dom";
|
|
150
|
+
import { ItemList } from "./ItemList";
|
|
151
|
+
import { NewItem } from "./NewItem";
|
|
152
|
+
|
|
153
|
+
export function App() {
|
|
154
|
+
return (
|
|
155
|
+
<Routes>
|
|
156
|
+
{/* Redirect root to list */}
|
|
157
|
+
<Route path="/" element={<Navigate to="list" replace />} />
|
|
158
|
+
<Route path="list" element={<ItemList />} />
|
|
159
|
+
<Route path="new" element={<NewItem />} />
|
|
160
|
+
</Routes>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### File: `src/ItemList.tsx`
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { useEffect } from "react";
|
|
169
|
+
import { useNavigate } from "react-router-dom";
|
|
170
|
+
import { useAuth, usePlatformAPI, useTelemetry } from "@nsxbet/admin-sdk";
|
|
171
|
+
import { Button, Card, CardContent, Badge } from "@nsxbet/admin-ui";
|
|
172
|
+
|
|
173
|
+
export function ItemList() {
|
|
174
|
+
const navigate = useNavigate();
|
|
175
|
+
const { hasPermission } = useAuth();
|
|
176
|
+
const { api } = usePlatformAPI();
|
|
177
|
+
const { track } = useTelemetry();
|
|
178
|
+
|
|
179
|
+
const canEdit = hasPermission("admin.mymodule.edit");
|
|
180
|
+
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
// Set breadcrumbs
|
|
183
|
+
api?.nav.setBreadcrumbs([
|
|
184
|
+
{ label: "My Module" },
|
|
185
|
+
{ label: "List" }
|
|
186
|
+
]);
|
|
187
|
+
// Track page view
|
|
188
|
+
track("page.viewed", { page: "item_list" });
|
|
189
|
+
}, [api, track]);
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<div className="p-6 max-w-5xl mx-auto">
|
|
193
|
+
<div className="mb-6 flex items-center justify-between">
|
|
194
|
+
<h1 className="text-3xl font-bold">Items</h1>
|
|
195
|
+
{canEdit && (
|
|
196
|
+
<Button onClick={() => navigate("/my-module/new")}>
|
|
197
|
+
New Item
|
|
198
|
+
</Button>
|
|
199
|
+
)}
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<Card>
|
|
203
|
+
<CardContent className="p-4">
|
|
204
|
+
<p className="text-muted-foreground">No items yet.</p>
|
|
205
|
+
</CardContent>
|
|
206
|
+
</Card>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### File: `src/index.css`
|
|
213
|
+
|
|
214
|
+
```css
|
|
215
|
+
@import "@nsxbet/admin-ui/styles.css";
|
|
216
|
+
|
|
217
|
+
@tailwind base;
|
|
218
|
+
@tailwind components;
|
|
219
|
+
@tailwind utilities;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### File: `tailwind.config.js`
|
|
223
|
+
|
|
224
|
+
Use `withAdminSdk` which automatically includes the UI preset and SDK/UI content paths:
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
import { withAdminSdk } from "@nsxbet/admin-sdk/tailwind";
|
|
228
|
+
|
|
229
|
+
/** @type {import('tailwindcss').Config} */
|
|
230
|
+
export default withAdminSdk({
|
|
231
|
+
content: ["./index.html", "./src/**/*.{ts,tsx}"],
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### File: `package.json`
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"name": "@admin/my-module",
|
|
240
|
+
"version": "1.0.0",
|
|
241
|
+
"type": "module",
|
|
242
|
+
"scripts": {
|
|
243
|
+
"dev": "vite",
|
|
244
|
+
"build": "tsc && vite build && cp admin.module.json dist/",
|
|
245
|
+
"preview": "vite preview"
|
|
246
|
+
},
|
|
247
|
+
"dependencies": {
|
|
248
|
+
"@nsxbet/admin-sdk": "latest",
|
|
249
|
+
"@nsxbet/admin-ui": "latest",
|
|
250
|
+
"react": "^18.2.0",
|
|
251
|
+
"react-dom": "^18.2.0",
|
|
252
|
+
"react-router-dom": "^6.20.0",
|
|
253
|
+
"i18next": "^25.0.0",
|
|
254
|
+
"react-i18next": "^16.0.0"
|
|
255
|
+
},
|
|
256
|
+
"devDependencies": {
|
|
257
|
+
"@types/react": "^18.2.0",
|
|
258
|
+
"@types/react-dom": "^18.2.0",
|
|
259
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
260
|
+
"autoprefixer": "^10.4.16",
|
|
261
|
+
"postcss": "^8.4.32",
|
|
262
|
+
"tailwindcss": "^3.4.0",
|
|
263
|
+
"typescript": "^5.2.0",
|
|
264
|
+
"vite": "^5.0.0"
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### File: `tsconfig.json`
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"compilerOptions": {
|
|
274
|
+
"target": "ES2020",
|
|
275
|
+
"useDefineForClassFields": true,
|
|
276
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
277
|
+
"module": "ESNext",
|
|
278
|
+
"skipLibCheck": true,
|
|
279
|
+
"moduleResolution": "bundler",
|
|
280
|
+
"allowImportingTsExtensions": true,
|
|
281
|
+
"resolveJsonModule": true,
|
|
282
|
+
"isolatedModules": true,
|
|
283
|
+
"noEmit": true,
|
|
284
|
+
"jsx": "react-jsx",
|
|
285
|
+
"strict": true,
|
|
286
|
+
"noUnusedLocals": true,
|
|
287
|
+
"noUnusedParameters": true,
|
|
288
|
+
"noFallthroughCasesInSwitch": true
|
|
289
|
+
},
|
|
290
|
+
"include": ["src", "admin.module.json"]
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### File: `index.html`
|
|
295
|
+
|
|
296
|
+
```html
|
|
297
|
+
<!DOCTYPE html>
|
|
298
|
+
<html lang="en">
|
|
299
|
+
<head>
|
|
300
|
+
<meta charset="UTF-8" />
|
|
301
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
302
|
+
<title>My Module - Standalone</title>
|
|
303
|
+
</head>
|
|
304
|
+
<body>
|
|
305
|
+
<div id="root"></div>
|
|
306
|
+
<script type="module" src="/src/standalone.tsx"></script>
|
|
307
|
+
</body>
|
|
308
|
+
</html>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### File: `postcss.config.js`
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
export default {
|
|
315
|
+
plugins: {
|
|
316
|
+
tailwindcss: {},
|
|
317
|
+
autoprefixer: {},
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Manifest Schema (`admin.module.json`)
|
|
323
|
+
|
|
324
|
+
| Field | Type | Required | Description |
|
|
325
|
+
|-------|------|----------|-------------|
|
|
326
|
+
| `id` | string | ✅ | Unique identifier (e.g., `@admin/tasks`) |
|
|
327
|
+
| `title` | string | ✅ | Human-readable title |
|
|
328
|
+
| `routeBase` | string | ✅ | Base route path (must start with `/`) |
|
|
329
|
+
| `description` | string | | What the module does |
|
|
330
|
+
| `version` | string | | Semantic version |
|
|
331
|
+
| `category` | string | | Navigation grouping |
|
|
332
|
+
| `icon` | string | | Lucide icon name in kebab-case |
|
|
333
|
+
| `keywords` | string[] | | Search keywords |
|
|
334
|
+
| `commands` | Command[] | | Available actions |
|
|
335
|
+
| `permissions` | object | | Permission configuration |
|
|
336
|
+
| `owners` | object | | Team ownership info |
|
|
337
|
+
|
|
338
|
+
### Command Schema
|
|
339
|
+
|
|
340
|
+
| Field | Type | Required | Description |
|
|
341
|
+
|-------|------|----------|-------------|
|
|
342
|
+
| `id` | string | ✅ | Unique command identifier |
|
|
343
|
+
| `title` | string | ✅ | Command title |
|
|
344
|
+
| `route` | string | ✅ | Full route path |
|
|
345
|
+
| `icon` | string | | Lucide icon name |
|
|
346
|
+
| `keywords` | string[] | | Search keywords |
|
|
347
|
+
|
|
348
|
+
### Icon Names
|
|
349
|
+
|
|
350
|
+
Use [Lucide](https://lucide.dev/icons) icon names in **kebab-case**:
|
|
351
|
+
|
|
352
|
+
| Category | Icons |
|
|
353
|
+
|----------|-------|
|
|
354
|
+
| Navigation | `home`, `settings`, `menu`, `search`, `chevron-right` |
|
|
355
|
+
| Actions | `plus`, `edit`, `trash`, `copy`, `check` |
|
|
356
|
+
| Content | `file`, `file-text`, `folder`, `clipboard-list` |
|
|
357
|
+
| Users | `user`, `users` |
|
|
358
|
+
| Status | `alert-circle`, `info`, `ban`, `lock` |
|
|
359
|
+
|
|
360
|
+
## Vite Configuration
|
|
361
|
+
|
|
362
|
+
The SDK provides `defineModuleConfig` to simplify Vite setup:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import { defineModuleConfig } from "@nsxbet/admin-sdk/vite";
|
|
366
|
+
import react from "@vitejs/plugin-react";
|
|
367
|
+
|
|
368
|
+
export default defineModuleConfig({
|
|
369
|
+
port: 3003,
|
|
370
|
+
plugins: [react()], // REQUIRED: you must add the React plugin
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Options
|
|
375
|
+
|
|
376
|
+
| Option | Type | Default | Description |
|
|
377
|
+
|--------|------|---------|-------------|
|
|
378
|
+
| `port` | number | **required** | Dev server port |
|
|
379
|
+
| `entry` | string | `"./src/spa.tsx"` | Entry file path |
|
|
380
|
+
| `outDir` | string | `"dist"` | Output directory |
|
|
381
|
+
| `plugins` | Plugin[] | `[]` | Additional Vite plugins |
|
|
382
|
+
| `additionalExternals` | string[] | `[]` | Extra externals |
|
|
383
|
+
| `overrides` | object | `{}` | Override any Vite config |
|
|
384
|
+
|
|
385
|
+
### Shared Externals
|
|
386
|
+
|
|
387
|
+
These dependencies are provided by the shell (do not bundle them):
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
["react", "react-dom", "react-router-dom", "i18next", "react-i18next"]
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## SDK Hooks
|
|
394
|
+
|
|
395
|
+
### `useAuth()`
|
|
396
|
+
|
|
397
|
+
Access authentication and permissions.
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
import { useAuth } from "@nsxbet/admin-sdk";
|
|
401
|
+
|
|
402
|
+
function MyComponent() {
|
|
403
|
+
const { hasPermission, getUser, getAccessToken, logout } = useAuth();
|
|
404
|
+
|
|
405
|
+
if (!hasPermission("admin.mymodule.view")) {
|
|
406
|
+
return <div>Access denied</div>;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const user = getUser();
|
|
410
|
+
console.log(user.email, user.displayName);
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
| Method | Returns | Description |
|
|
415
|
+
|--------|---------|-------------|
|
|
416
|
+
| `hasPermission(perm)` | boolean | Check if user has permission |
|
|
417
|
+
| `getUser()` | User | Get current user info |
|
|
418
|
+
| `getAccessToken()` | Promise\<string\> | Get JWT token |
|
|
419
|
+
| `logout()` | void | Log out user |
|
|
420
|
+
|
|
421
|
+
### `usePlatformAPI()`
|
|
422
|
+
|
|
423
|
+
Access the shell's platform API.
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { usePlatformAPI } from "@nsxbet/admin-sdk";
|
|
427
|
+
|
|
428
|
+
function MyComponent() {
|
|
429
|
+
const { api, isShellMode } = usePlatformAPI();
|
|
430
|
+
|
|
431
|
+
useEffect(() => {
|
|
432
|
+
api?.nav.setBreadcrumbs([
|
|
433
|
+
{ label: "My Module" },
|
|
434
|
+
{ label: "Current Page" }
|
|
435
|
+
]);
|
|
436
|
+
}, [api]);
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### `useFetch()`
|
|
441
|
+
|
|
442
|
+
Make authenticated API requests.
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { useFetch } from "@nsxbet/admin-sdk";
|
|
446
|
+
|
|
447
|
+
function MyComponent() {
|
|
448
|
+
const fetch = useFetch();
|
|
449
|
+
|
|
450
|
+
const loadData = async () => {
|
|
451
|
+
const response = await fetch("/api/data");
|
|
452
|
+
const data = await response.json();
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### `useTelemetry()`
|
|
458
|
+
|
|
459
|
+
Track events and errors.
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import { useTelemetry } from "@nsxbet/admin-sdk";
|
|
463
|
+
|
|
464
|
+
function MyComponent() {
|
|
465
|
+
const { track, trackError } = useTelemetry();
|
|
466
|
+
|
|
467
|
+
const handleClick = () => {
|
|
468
|
+
track("button.clicked", { buttonId: "save" });
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
const handleError = (error: Error) => {
|
|
472
|
+
trackError(error, { context: "save_operation" });
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### `useI18n()`
|
|
478
|
+
|
|
479
|
+
Manage translations and locale.
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
import { useI18n } from "@nsxbet/admin-sdk";
|
|
483
|
+
|
|
484
|
+
function MyComponent() {
|
|
485
|
+
const { t, locale, setLocale } = useI18n();
|
|
486
|
+
|
|
487
|
+
return (
|
|
488
|
+
<div>
|
|
489
|
+
<h1>{t("common.title")}</h1>
|
|
490
|
+
<p>Current locale: {locale}</p>
|
|
491
|
+
</div>
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Navigation
|
|
497
|
+
|
|
498
|
+
**Use `useNavigate` from `react-router-dom` directly:**
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
import { useNavigate } from "react-router-dom";
|
|
502
|
+
|
|
503
|
+
function MyComponent() {
|
|
504
|
+
const navigate = useNavigate();
|
|
505
|
+
|
|
506
|
+
return (
|
|
507
|
+
<Button onClick={() => navigate("/my-module/new")}>
|
|
508
|
+
New Item
|
|
509
|
+
</Button>
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## DO NOT (Common Mistakes)
|
|
515
|
+
|
|
516
|
+
### ❌ DO NOT use MemoryRouter
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
// WRONG - don't create your own router
|
|
520
|
+
import { MemoryRouter, Routes, Route } from "react-router-dom";
|
|
521
|
+
|
|
522
|
+
function App() {
|
|
523
|
+
return (
|
|
524
|
+
<MemoryRouter> {/* ❌ WRONG */}
|
|
525
|
+
<Routes>
|
|
526
|
+
<Route path="/" element={<List />} />
|
|
527
|
+
</Routes>
|
|
528
|
+
</MemoryRouter>
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
```tsx
|
|
534
|
+
// CORRECT - use Routes directly, shell provides BrowserRouter
|
|
535
|
+
import { Routes, Route } from "react-router-dom";
|
|
536
|
+
|
|
537
|
+
function App() {
|
|
538
|
+
return (
|
|
539
|
+
<Routes>
|
|
540
|
+
<Route path="/" element={<List />} />
|
|
541
|
+
</Routes>
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### ❌ DO NOT create BrowserRouter in spa.tsx
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
// WRONG - shell already provides BrowserRouter
|
|
550
|
+
import { BrowserRouter } from "react-router-dom";
|
|
551
|
+
|
|
552
|
+
export default function App() {
|
|
553
|
+
return (
|
|
554
|
+
<BrowserRouter> {/* ❌ WRONG */}
|
|
555
|
+
<MyRoutes />
|
|
556
|
+
</BrowserRouter>
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
```tsx
|
|
562
|
+
// CORRECT - just export the component
|
|
563
|
+
import { App } from "./App";
|
|
564
|
+
export default App;
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### ❌ DO NOT forget the React plugin
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
// WRONG - missing React plugin
|
|
571
|
+
export default defineModuleConfig({
|
|
572
|
+
port: 3003,
|
|
573
|
+
// ❌ No plugins!
|
|
574
|
+
});
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
// CORRECT - include React plugin
|
|
579
|
+
import react from "@vitejs/plugin-react";
|
|
580
|
+
|
|
581
|
+
export default defineModuleConfig({
|
|
582
|
+
port: 3003,
|
|
583
|
+
plugins: [react()], // ✅
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### ❌ DO NOT use external databases
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
// WRONG - no Supabase, Firebase, or external BaaS
|
|
591
|
+
import { createClient } from "@supabase/supabase-js"; // ❌
|
|
592
|
+
import { initializeApp } from "firebase/app"; // ❌
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
// CORRECT - use authenticated fetch for internal APIs
|
|
597
|
+
import { useFetch } from "@nsxbet/admin-sdk";
|
|
598
|
+
|
|
599
|
+
const fetch = useFetch();
|
|
600
|
+
const data = await fetch("/api/internal-endpoint");
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### ❌ DO NOT import useNavigate from SDK
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
// WRONG - useNavigate is not exported from SDK
|
|
607
|
+
import { useNavigate } from "@nsxbet/admin-sdk"; // ❌
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
```typescript
|
|
611
|
+
// CORRECT - import from react-router-dom
|
|
612
|
+
import { useNavigate } from "react-router-dom"; // ✅
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
## Troubleshooting
|
|
616
|
+
|
|
617
|
+
### "Failed to resolve module specifier 'react'"
|
|
618
|
+
|
|
619
|
+
**Cause:** Module is bundling React instead of using shell's version.
|
|
620
|
+
|
|
621
|
+
**Solution:** Ensure `vite.config.ts` uses `defineModuleConfig` or has `external: ["react", "react-dom", "react-router-dom"]`.
|
|
622
|
+
|
|
623
|
+
### "process is not defined"
|
|
624
|
+
|
|
625
|
+
**Cause:** Module code references Node.js globals.
|
|
626
|
+
|
|
627
|
+
**Solution:** `defineModuleConfig` handles this automatically. If using custom config, add:
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
define: {
|
|
631
|
+
"process.env": {},
|
|
632
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Module not loading in shell
|
|
637
|
+
|
|
638
|
+
**Checklist:**
|
|
639
|
+
1. ✅ `spa.tsx` exports default component
|
|
640
|
+
2. ✅ `admin.module.json` has valid `id`, `title`, `routeBase`
|
|
641
|
+
3. ✅ Build outputs to `dist/` with `spa-[hash].js`
|
|
642
|
+
4. ✅ Module is registered in shell's catalog
|
|
643
|
+
|
|
644
|
+
### Styles not working
|
|
645
|
+
|
|
646
|
+
**Checklist:**
|
|
647
|
+
1. ✅ `index.css` imports `@nsxbet/admin-ui/styles.css`
|
|
648
|
+
2. ✅ `tailwind.config.js` uses `withAdminSdk` from `@nsxbet/admin-sdk/tailwind`
|
|
649
|
+
3. ✅ `postcss.config.js` exists with tailwindcss plugin
|
|
650
|
+
|
|
651
|
+
## Running Your Module
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
# Development (standalone with shell UI)
|
|
655
|
+
bun run dev
|
|
656
|
+
# Open http://localhost:3003
|
|
657
|
+
|
|
658
|
+
# Build for production
|
|
659
|
+
bun run build
|
|
660
|
+
# Output: dist/assets/spa-[hash].js
|
|
661
|
+
|
|
662
|
+
# Preview built module
|
|
663
|
+
bun run preview
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
## Types
|
|
667
|
+
|
|
668
|
+
```typescript
|
|
669
|
+
import type {
|
|
670
|
+
AdminModuleManifest,
|
|
671
|
+
ModuleCommand,
|
|
672
|
+
PlatformAPI,
|
|
673
|
+
User,
|
|
674
|
+
Breadcrumb,
|
|
675
|
+
} from "@nsxbet/admin-sdk";
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
## License
|
|
679
|
+
|
|
680
|
+
UNLICENSED - Internal use only
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Auth Client
|
|
3
|
+
*
|
|
4
|
+
* Provides fake authentication for development and testing.
|
|
5
|
+
* Users can be selected from a predefined list or created custom.
|
|
6
|
+
*/
|
|
7
|
+
import type { MockUser, InMemoryAuthClient } from './interface';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating an in-memory auth client
|
|
10
|
+
*/
|
|
11
|
+
export interface InMemoryAuthClientOptions {
|
|
12
|
+
/** Custom mock users (merged with defaults) */
|
|
13
|
+
users?: MockUser[];
|
|
14
|
+
/** Replace default users instead of merging */
|
|
15
|
+
replaceDefaults?: boolean;
|
|
16
|
+
/** localStorage key prefix (defaults to '@nsxbet/auth') */
|
|
17
|
+
storageKey?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create an in-memory auth client for development/testing
|
|
21
|
+
*/
|
|
22
|
+
export declare function createInMemoryAuthClient(options?: InMemoryAuthClientOptions): InMemoryAuthClient;
|
|
23
|
+
/**
|
|
24
|
+
* Clear in-memory auth storage (useful for tests)
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearInMemoryAuth(storageKey?: string): void;
|
|
27
|
+
//# sourceMappingURL=in-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory.d.ts","sourceRoot":"","sources":["../../../src/auth/client/in-memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAgC,MAAM,aAAa,CAAC;AAoD9F;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAYD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,yBAA8B,GAAG,kBAAkB,CAiNpG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,SAAsB,GAAG,IAAI,CAExE"}
|