@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
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Registered Module Types
3
+ *
4
+ * Types for modules that have been registered in the registry.
5
+ */
6
+ import type { AdminModuleManifest } from './manifest';
7
+ /**
8
+ * A module that has been registered in the registry
9
+ */
10
+ export interface RegisteredModule {
11
+ /** Auto-increment ID */
12
+ id: number;
13
+ /** Module identifier from manifest (e.g., "@admin/tasks") */
14
+ moduleId: string;
15
+ /** Base URL where the module is hosted */
16
+ baseUrl: string;
17
+ /** Full parsed module.manifest.json (without entry - fetched at runtime) */
18
+ manifest: AdminModuleManifest;
19
+ /** Admin-controlled navigation order */
20
+ navOrder: number;
21
+ /** Whether the module is enabled */
22
+ enabled: boolean;
23
+ /** ISO timestamp when registered */
24
+ registeredAt: string;
25
+ /** ISO timestamp when last updated */
26
+ updatedAt: string;
27
+ }
28
+ /**
29
+ * DTO for updating a registered module
30
+ * Only admin-controlled fields can be updated
31
+ */
32
+ export interface UpdateModuleDto {
33
+ /** Update navigation order */
34
+ navOrder?: number;
35
+ /** Enable or disable the module */
36
+ enabled?: boolean;
37
+ }
38
+ /**
39
+ * DTO for reordering modules
40
+ */
41
+ export interface ReorderModuleDto {
42
+ /** Module ID */
43
+ id: number;
44
+ /** New navigation order */
45
+ navOrder: number;
46
+ }
47
+ /**
48
+ * Filters for listing modules
49
+ */
50
+ export interface ModuleFilters {
51
+ /** Filter by enabled status */
52
+ enabled?: boolean;
53
+ /** Filter by category */
54
+ category?: string;
55
+ /** Filter by status */
56
+ status?: 'active' | 'deprecated' | 'disabled';
57
+ }
58
+ /**
59
+ * Catalog structure for shell consumption (denormalized)
60
+ */
61
+ export interface Catalog {
62
+ /** Version identifier */
63
+ version: string;
64
+ /** Timestamp when generated */
65
+ generatedAt: string;
66
+ /** Array of modules in catalog format */
67
+ modules: CatalogModule[];
68
+ }
69
+ /**
70
+ * Module in catalog format (denormalized for shell)
71
+ * Note: entry is not included - DynamicModule fetches module.manifest.json at runtime
72
+ */
73
+ export interface CatalogModule {
74
+ id: string;
75
+ title: string;
76
+ /** i18n key for the title (for translation) */
77
+ titleKey?: string;
78
+ description: string;
79
+ /** i18n key for the description (for translation) */
80
+ descriptionKey?: string;
81
+ category: string;
82
+ routeBase: string;
83
+ /** Base URL where the module is hosted */
84
+ baseUrl: string;
85
+ keywords: string[];
86
+ permissions: {
87
+ view: string[];
88
+ dangerous?: string[];
89
+ };
90
+ owners: {
91
+ team: string;
92
+ supportChannel: string;
93
+ };
94
+ status: 'active' | 'deprecated' | 'disabled';
95
+ navOrder?: number;
96
+ icon?: string;
97
+ commands?: Array<{
98
+ id: string;
99
+ title: string;
100
+ /** i18n key for the title (for translation) */
101
+ titleKey?: string;
102
+ keywords?: string[];
103
+ route: string;
104
+ icon?: string;
105
+ }>;
106
+ }
107
+ /**
108
+ * Import map structure for dynamic module loading
109
+ */
110
+ export interface ImportMap {
111
+ imports: {
112
+ [moduleName: string]: string;
113
+ };
114
+ }
115
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/registry/types/module.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,MAAM,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,+CAA+C;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE;QACP,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;KAC9B,CAAC;CACH"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Registered Module Types
3
+ *
4
+ * Types for modules that have been registered in the registry.
5
+ */
6
+ export {};
@@ -0,0 +1,50 @@
1
+ import { Component, type ReactNode } from "react";
2
+ interface DynamicModuleProps {
3
+ /** Base URL where the module is hosted (e.g., "http://localhost:5001") */
4
+ baseUrl: string;
5
+ /** Module global name (e.g., "TasksAdminModule") - if not provided, uses ES import */
6
+ globalName?: string;
7
+ /** Custom loading fallback */
8
+ fallback?: ReactNode;
9
+ /** Custom error fallback */
10
+ errorFallback?: ReactNode;
11
+ }
12
+ /**
13
+ * Loading spinner shown while module is being fetched
14
+ */
15
+ declare function ModuleLoading(): import("react/jsx-runtime").JSX.Element;
16
+ /**
17
+ * Error boundary for catching module load errors
18
+ */
19
+ interface ErrorBoundaryProps {
20
+ children: ReactNode;
21
+ fallback?: ReactNode;
22
+ onRetry?: () => void;
23
+ }
24
+ interface ErrorBoundaryState {
25
+ hasError: boolean;
26
+ error?: Error;
27
+ }
28
+ declare class ModuleErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
29
+ constructor(props: ErrorBoundaryProps);
30
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
31
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
32
+ handleRetry: () => void;
33
+ render(): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
34
+ }
35
+ /**
36
+ * DynamicModule - Loads a module from a URL using React.lazy
37
+ *
38
+ * This component:
39
+ * 1. Fetches module.manifest.json from baseUrl to get the hashed entry path
40
+ * 2. Loads the module JS file using React.lazy
41
+ * 3. Keeps the module in the shell's React tree for shared Router context
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * <DynamicModule baseUrl="http://localhost:5001" />
46
+ * ```
47
+ */
48
+ export declare function DynamicModule({ baseUrl, globalName, fallback, errorFallback, }: DynamicModuleProps): import("react/jsx-runtime").JSX.Element;
49
+ export { ModuleLoading, ModuleErrorBoundary };
50
+ //# sourceMappingURL=DynamicModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicModule.d.ts","sourceRoot":"","sources":["../../src/router/DynamicModule.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2B,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3E,UAAU,kBAAkB;IAC1B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,4BAA4B;IAC5B,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B;AAUD;;GAEG;AACH,iBAAS,aAAa,4CAerB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,cAAM,mBAAoB,SAAQ,SAAS,CACzC,kBAAkB,EAClB,kBAAkB,CACnB;gBACa,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAIjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS;IAI1D,WAAW,aAGT;IAEF,MAAM;CAkEP;AA0DD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,UAAU,EACV,QAAQ,EACR,aAAa,GACd,EAAE,kBAAkB,2CAsDpB;AAED,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,141 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Suspense, lazy, useMemo, Component } from "react";
3
+ import { Icon, Card, CardContent, Button } from "@nsxbet/admin-ui";
4
+ /**
5
+ * Loading spinner shown while module is being fetched
6
+ */
7
+ function ModuleLoading() {
8
+ return (_jsxs("div", { "data-testid": "module-loading", className: "flex flex-col items-center justify-center h-full min-h-[300px] gap-4", children: [_jsx("div", { className: "inline-flex p-4 rounded-full bg-primary/10", children: _jsx(Icon, { name: "loader-2", className: "h-8 w-8 text-primary animate-spin" }) }), _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-lg font-medium", children: "Loading module..." }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Please wait while the module is being loaded" })] })] }));
9
+ }
10
+ class ModuleErrorBoundary extends Component {
11
+ constructor(props) {
12
+ super(props);
13
+ Object.defineProperty(this, "handleRetry", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: () => {
18
+ this.setState({ hasError: false, error: undefined });
19
+ this.props.onRetry?.();
20
+ }
21
+ });
22
+ this.state = { hasError: false };
23
+ }
24
+ static getDerivedStateFromError(error) {
25
+ return { hasError: true, error };
26
+ }
27
+ componentDidCatch(error, errorInfo) {
28
+ console.error("[DynamicModule] Failed to load module:", error, errorInfo);
29
+ }
30
+ render() {
31
+ if (this.state.hasError) {
32
+ if (this.props.fallback) {
33
+ return this.props.fallback;
34
+ }
35
+ const errorMessage = this.state.error?.message || "An unexpected error occurred";
36
+ const isNetworkError = errorMessage.includes("Failed to fetch") ||
37
+ errorMessage.includes("NetworkError") ||
38
+ errorMessage.includes("Failed to load script");
39
+ return (_jsx("div", { "data-testid": "module-error", className: "flex items-center justify-center h-full min-h-[300px] p-6", children: _jsx(Card, { className: "max-w-md w-full", children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "flex flex-col items-center text-center gap-4", children: [_jsx("div", { className: "inline-flex p-4 rounded-full bg-destructive/10", children: _jsx(Icon, { name: isNetworkError ? "wifi-off" : "alert-triangle", className: "h-8 w-8 text-destructive" }) }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-1", children: isNetworkError ? "Module Unavailable" : "Failed to Load Module" }), _jsx("p", { className: "text-sm text-muted-foreground mb-2", children: isNetworkError
40
+ ? "The module server is not responding. Please ensure the module is running."
41
+ : "An error occurred while loading the module." }), _jsx("p", { className: "text-xs font-mono text-muted-foreground bg-muted p-2 rounded break-all", children: errorMessage })] }), _jsx("div", { className: "flex gap-2", children: _jsxs(Button, { "data-testid": "module-retry-button", onClick: this.handleRetry, variant: "default", children: [_jsx(Icon, { name: "refresh-cw", className: "h-4 w-4 mr-2" }), "Try Again"] }) }), isNetworkError && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Tip: Run the module dev server or check your network connection." }))] }) }) }) }));
42
+ }
43
+ return this.props.children;
44
+ }
45
+ }
46
+ /**
47
+ * Load a script and return the global it exposes
48
+ */
49
+ function loadScript(url, globalName) {
50
+ return new Promise((resolve, reject) => {
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ const win = window;
53
+ // Check if already loaded
54
+ if (win[globalName]) {
55
+ resolve(win[globalName]);
56
+ return;
57
+ }
58
+ const script = document.createElement("script");
59
+ script.src = url;
60
+ script.async = true;
61
+ script.onload = () => {
62
+ const moduleExport = win[globalName];
63
+ if (moduleExport) {
64
+ resolve(moduleExport);
65
+ }
66
+ else {
67
+ reject(new Error(`Global "${globalName}" not found after loading ${url}`));
68
+ }
69
+ };
70
+ script.onerror = () => {
71
+ reject(new Error(`Failed to load script: ${url}`));
72
+ };
73
+ document.head.appendChild(script);
74
+ });
75
+ }
76
+ /**
77
+ * Fetch module manifest to get the entry path
78
+ */
79
+ async function fetchModuleEntry(baseUrl) {
80
+ const manifestUrl = `${baseUrl}/module.manifest.json`;
81
+ console.log(`[DynamicModule] Fetching manifest from ${manifestUrl}`);
82
+ const response = await fetch(manifestUrl);
83
+ if (!response.ok) {
84
+ throw new Error(`Failed to fetch manifest from ${manifestUrl}: ${response.status}`);
85
+ }
86
+ const manifest = await response.json();
87
+ if (!manifest.entry) {
88
+ throw new Error(`Manifest at ${manifestUrl} is missing required 'entry' field`);
89
+ }
90
+ return manifest.entry;
91
+ }
92
+ /**
93
+ * DynamicModule - Loads a module from a URL using React.lazy
94
+ *
95
+ * This component:
96
+ * 1. Fetches module.manifest.json from baseUrl to get the hashed entry path
97
+ * 2. Loads the module JS file using React.lazy
98
+ * 3. Keeps the module in the shell's React tree for shared Router context
99
+ *
100
+ * @example
101
+ * ```tsx
102
+ * <DynamicModule baseUrl="http://localhost:5001" />
103
+ * ```
104
+ */
105
+ export function DynamicModule({ baseUrl, globalName, fallback, errorFallback, }) {
106
+ // Normalize baseUrl (remove trailing slash)
107
+ const normalizedUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
108
+ // Create lazy component - memoized to avoid re-creating on every render
109
+ const ModuleComponent = useMemo(() => lazy(async () => {
110
+ try {
111
+ // Step 1: Fetch manifest to get entry path
112
+ const entry = await fetchModuleEntry(normalizedUrl);
113
+ // Step 2: Load the module
114
+ const moduleUrl = `${normalizedUrl}/${entry}`;
115
+ console.log(`[DynamicModule] Loading module from ${moduleUrl}`);
116
+ let moduleExport;
117
+ if (globalName) {
118
+ // IIFE format: load script and get global
119
+ moduleExport = await loadScript(moduleUrl, globalName);
120
+ }
121
+ else {
122
+ // ES module format: use dynamic import
123
+ moduleExport = await import(/* @vite-ignore */ moduleUrl);
124
+ }
125
+ console.log(`[DynamicModule] Module loaded successfully`);
126
+ // Handle both default export and direct component
127
+ const mod = moduleExport;
128
+ const Component = (mod.default || mod.App || mod);
129
+ if (typeof Component !== "function") {
130
+ throw new Error("Module must export a default component or named App export");
131
+ }
132
+ return { default: Component };
133
+ }
134
+ catch (error) {
135
+ console.error(`[DynamicModule] Failed to load module:`, error);
136
+ throw error;
137
+ }
138
+ }), [normalizedUrl, globalName]);
139
+ return (_jsx(ModuleErrorBoundary, { fallback: errorFallback, children: _jsx(Suspense, { fallback: fallback ?? _jsx(ModuleLoading, {}), children: _jsx(ModuleComponent, {}) }) }));
140
+ }
141
+ export { ModuleLoading, ModuleErrorBoundary };
@@ -0,0 +1,2 @@
1
+ export { DynamicModule, ModuleLoading, ModuleErrorBoundary } from "./DynamicModule";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1 @@
1
+ export { DynamicModule, ModuleLoading, ModuleErrorBoundary } from "./DynamicModule";
@@ -0,0 +1,38 @@
1
+ import type { AuthClient } from "../auth/client/interface";
2
+ import type { AdminModuleManifest, RegistryClient } from "../registry";
3
+ export interface AdminShellProps {
4
+ /**
5
+ * Module manifests to load (used for standalone mode when no registryClient)
6
+ * In standalone mode, modules are rendered via children prop
7
+ */
8
+ modules?: AdminModuleManifest[];
9
+ /**
10
+ * Content to render for standalone module development.
11
+ * Only used in standalone mode (when modules prop is provided)
12
+ */
13
+ children?: React.ReactNode;
14
+ /**
15
+ * Keycloak configuration
16
+ * If not provided, uses in-memory (mock) authentication
17
+ */
18
+ keycloak?: {
19
+ url: string;
20
+ realm: string;
21
+ clientId: string;
22
+ };
23
+ /**
24
+ * Auth client to use for authentication.
25
+ * If not provided, creates one based on keycloak prop or environment.
26
+ */
27
+ authClient?: AuthClient;
28
+ /** Registry client for fetching modules from API */
29
+ registryClient?: RegistryClient;
30
+ /** API URL for registry management (e.g., "http://localhost:4000/api") */
31
+ apiUrl?: string;
32
+ /** Use in-memory registry (default: true, ignored if registryClient is provided) */
33
+ inMemoryRegistry?: boolean;
34
+ /** Environment (default: "local") */
35
+ environment?: string;
36
+ }
37
+ export declare function AdminShell({ modules: manifests, children, keycloak, authClient: providedAuthClient, registryClient, apiUrl, inMemoryRegistry, environment, }: AdminShellProps): import("react/jsx-runtime").JSX.Element;
38
+ //# sourceMappingURL=AdminShell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminShell.d.ts","sourceRoot":"","sources":["../../src/shell/AdminShell.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAMtF,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,oDAAoD;IACpD,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8RD,wBAAgB,UAAU,CAAC,EACzB,OAAO,EAAE,SAAc,EACvB,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,kBAAkB,EAC9B,cAAc,EACd,MAAM,EACN,gBAAuB,EACvB,WAAqB,GACtB,EAAE,eAAe,2CAsLjB"}