@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.
Files changed (159) hide show
  1. package/README.md +680 -0
  2. package/dist/auth/client/in-memory.d.ts +27 -0
  3. package/dist/auth/client/in-memory.d.ts.map +1 -0
  4. package/dist/auth/client/in-memory.js +242 -0
  5. package/dist/auth/client/index.d.ts +7 -0
  6. package/dist/auth/client/index.d.ts.map +1 -0
  7. package/dist/auth/client/index.js +7 -0
  8. package/dist/auth/client/interface.d.ts +115 -0
  9. package/dist/auth/client/interface.d.ts.map +1 -0
  10. package/dist/auth/client/interface.js +7 -0
  11. package/dist/auth/client/keycloak.d.ts +19 -0
  12. package/dist/auth/client/keycloak.d.ts.map +1 -0
  13. package/dist/auth/client/keycloak.js +126 -0
  14. package/dist/auth/components/UserSelector.d.ts +19 -0
  15. package/dist/auth/components/UserSelector.d.ts.map +1 -0
  16. package/dist/auth/components/UserSelector.js +100 -0
  17. package/dist/auth/components/index.d.ts +5 -0
  18. package/dist/auth/components/index.d.ts.map +1 -0
  19. package/dist/auth/components/index.js +4 -0
  20. package/dist/auth/index.d.ts +7 -0
  21. package/dist/auth/index.d.ts.map +1 -0
  22. package/dist/auth/index.js +7 -0
  23. package/dist/components/AuthProvider.d.ts +48 -0
  24. package/dist/components/AuthProvider.d.ts.map +1 -0
  25. package/dist/components/AuthProvider.js +117 -0
  26. package/dist/hooks/useAuth.d.ts +21 -0
  27. package/dist/hooks/useAuth.d.ts.map +1 -0
  28. package/dist/hooks/useAuth.js +34 -0
  29. package/dist/hooks/useFetch.d.ts +8 -0
  30. package/dist/hooks/useFetch.d.ts.map +1 -0
  31. package/dist/hooks/useFetch.js +31 -0
  32. package/dist/hooks/useI18n.d.ts +46 -0
  33. package/dist/hooks/useI18n.d.ts.map +1 -0
  34. package/dist/hooks/useI18n.js +95 -0
  35. package/dist/hooks/usePlatformAPI.d.ts +12 -0
  36. package/dist/hooks/usePlatformAPI.d.ts.map +1 -0
  37. package/dist/hooks/usePlatformAPI.js +10 -0
  38. package/dist/hooks/useTelemetry.d.ts +17 -0
  39. package/dist/hooks/useTelemetry.d.ts.map +1 -0
  40. package/dist/hooks/useTelemetry.js +36 -0
  41. package/dist/i18n/config.d.ts +26 -0
  42. package/dist/i18n/config.d.ts.map +1 -0
  43. package/dist/i18n/config.js +92 -0
  44. package/dist/i18n/index.d.ts +6 -0
  45. package/dist/i18n/index.d.ts.map +1 -0
  46. package/dist/i18n/index.js +4 -0
  47. package/dist/i18n/locales/en-US.json +144 -0
  48. package/dist/i18n/locales/es.json +144 -0
  49. package/dist/i18n/locales/pt-BR.json +144 -0
  50. package/dist/i18n/locales/ro.json +144 -0
  51. package/dist/index.d.ts +27 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +30 -0
  54. package/dist/registry/AdminShellRegistry.d.ts +140 -0
  55. package/dist/registry/AdminShellRegistry.d.ts.map +1 -0
  56. package/dist/registry/AdminShellRegistry.js +237 -0
  57. package/dist/registry/client/http.d.ts +21 -0
  58. package/dist/registry/client/http.d.ts.map +1 -0
  59. package/dist/registry/client/http.js +107 -0
  60. package/dist/registry/client/in-memory.d.ts +36 -0
  61. package/dist/registry/client/in-memory.d.ts.map +1 -0
  62. package/dist/registry/client/in-memory.js +242 -0
  63. package/dist/registry/client/index.d.ts +7 -0
  64. package/dist/registry/client/index.d.ts.map +1 -0
  65. package/dist/registry/client/index.js +5 -0
  66. package/dist/registry/client/interface.d.ts +96 -0
  67. package/dist/registry/client/interface.d.ts.map +1 -0
  68. package/dist/registry/client/interface.js +7 -0
  69. package/dist/registry/index.d.ts +12 -0
  70. package/dist/registry/index.d.ts.map +1 -0
  71. package/dist/registry/index.js +8 -0
  72. package/dist/registry/types/index.d.ts +9 -0
  73. package/dist/registry/types/index.d.ts.map +1 -0
  74. package/dist/registry/types/index.js +6 -0
  75. package/dist/registry/types/manifest.d.ts +98 -0
  76. package/dist/registry/types/manifest.d.ts.map +1 -0
  77. package/dist/registry/types/manifest.js +81 -0
  78. package/dist/registry/types/module.d.ts +115 -0
  79. package/dist/registry/types/module.d.ts.map +1 -0
  80. package/dist/registry/types/module.js +6 -0
  81. package/dist/router/DynamicModule.d.ts +50 -0
  82. package/dist/router/DynamicModule.d.ts.map +1 -0
  83. package/dist/router/DynamicModule.js +141 -0
  84. package/dist/router/index.d.ts +2 -0
  85. package/dist/router/index.d.ts.map +1 -0
  86. package/dist/router/index.js +1 -0
  87. package/dist/shell/AdminShell.d.ts +38 -0
  88. package/dist/shell/AdminShell.d.ts.map +1 -0
  89. package/dist/shell/AdminShell.js +299 -0
  90. package/dist/shell/BackofficeShell.d.ts +38 -0
  91. package/dist/shell/BackofficeShell.d.ts.map +1 -0
  92. package/dist/shell/BackofficeShell.js +299 -0
  93. package/dist/shell/components/CommandPalette.d.ts +8 -0
  94. package/dist/shell/components/CommandPalette.d.ts.map +1 -0
  95. package/dist/shell/components/CommandPalette.js +197 -0
  96. package/dist/shell/components/HomePage.d.ts +2 -0
  97. package/dist/shell/components/HomePage.d.ts.map +1 -0
  98. package/dist/shell/components/HomePage.js +32 -0
  99. package/dist/shell/components/LeftNav.d.ts +7 -0
  100. package/dist/shell/components/LeftNav.d.ts.map +1 -0
  101. package/dist/shell/components/LeftNav.js +247 -0
  102. package/dist/shell/components/MainContent.d.ts +9 -0
  103. package/dist/shell/components/MainContent.d.ts.map +1 -0
  104. package/dist/shell/components/MainContent.js +88 -0
  105. package/dist/shell/components/ModuleOverview.d.ts +7 -0
  106. package/dist/shell/components/ModuleOverview.d.ts.map +1 -0
  107. package/dist/shell/components/ModuleOverview.js +40 -0
  108. package/dist/shell/components/ProfilePage.d.ts +2 -0
  109. package/dist/shell/components/ProfilePage.d.ts.map +1 -0
  110. package/dist/shell/components/ProfilePage.js +30 -0
  111. package/dist/shell/components/RegistryPage.d.ts +8 -0
  112. package/dist/shell/components/RegistryPage.d.ts.map +1 -0
  113. package/dist/shell/components/RegistryPage.js +129 -0
  114. package/dist/shell/components/SettingsPage.d.ts +2 -0
  115. package/dist/shell/components/SettingsPage.d.ts.map +1 -0
  116. package/dist/shell/components/SettingsPage.js +60 -0
  117. package/dist/shell/components/TopBar.d.ts +8 -0
  118. package/dist/shell/components/TopBar.d.ts.map +1 -0
  119. package/dist/shell/components/TopBar.js +61 -0
  120. package/dist/shell/components/index.d.ts +10 -0
  121. package/dist/shell/components/index.d.ts.map +1 -0
  122. package/dist/shell/components/index.js +7 -0
  123. package/dist/shell/components/theme-provider.d.ts +15 -0
  124. package/dist/shell/components/theme-provider.d.ts.map +1 -0
  125. package/dist/shell/components/theme-provider.js +39 -0
  126. package/dist/shell/index.d.ts +9 -0
  127. package/dist/shell/index.d.ts.map +1 -0
  128. package/dist/shell/index.js +8 -0
  129. package/dist/shell/search/fuzzy.d.ts +18 -0
  130. package/dist/shell/search/fuzzy.d.ts.map +1 -0
  131. package/dist/shell/search/fuzzy.js +121 -0
  132. package/dist/shell/search/index.d.ts +3 -0
  133. package/dist/shell/search/index.d.ts.map +1 -0
  134. package/dist/shell/search/index.js +1 -0
  135. package/dist/shell/telemetry.d.ts +7 -0
  136. package/dist/shell/telemetry.d.ts.map +1 -0
  137. package/dist/shell/telemetry.js +25 -0
  138. package/dist/shell/types.d.ts +110 -0
  139. package/dist/shell/types.d.ts.map +1 -0
  140. package/dist/shell/types.js +4 -0
  141. package/dist/tailwind/index.d.ts +20 -0
  142. package/dist/tailwind/index.d.ts.map +1 -0
  143. package/dist/tailwind/index.js +42 -0
  144. package/dist/types/keycloak.d.ts +26 -0
  145. package/dist/types/keycloak.d.ts.map +1 -0
  146. package/dist/types/keycloak.js +1 -0
  147. package/dist/types/platform.d.ts +83 -0
  148. package/dist/types/platform.d.ts.map +1 -0
  149. package/dist/types/platform.js +5 -0
  150. package/dist/vite/config.d.ts +71 -0
  151. package/dist/vite/config.d.ts.map +1 -0
  152. package/dist/vite/config.js +87 -0
  153. package/dist/vite/index.d.ts +18 -0
  154. package/dist/vite/index.d.ts.map +1 -0
  155. package/dist/vite/index.js +17 -0
  156. package/dist/vite/plugins.d.ts +44 -0
  157. package/dist/vite/plugins.d.ts.map +1 -0
  158. package/dist/vite/plugins.js +74 -0
  159. 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"}