@rebasepro/app 0.0.1-canary.4829d6e

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 (268) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/dist/auth/api.d.ts +66 -0
  4. package/dist/auth/index.d.ts +13 -0
  5. package/dist/auth/types.d.ts +127 -0
  6. package/dist/auth/useRebaseAuthController.d.ts +13 -0
  7. package/dist/components/AIIcon.d.ts +17 -0
  8. package/dist/components/AuthSimulationMenu.d.ts +0 -0
  9. package/dist/components/ConfirmationDialog.d.ts +9 -0
  10. package/dist/components/Debug/UIReferenceView.d.ts +13 -0
  11. package/dist/components/Debug/UIStyleGuide.d.ts +2 -0
  12. package/dist/components/Debug/collection-views/CardViewDemo.d.ts +2 -0
  13. package/dist/components/Debug/collection-views/CollectionTableDemo.d.ts +2 -0
  14. package/dist/components/Debug/collection-views/KanbanBoardDemo.d.ts +2 -0
  15. package/dist/components/Debug/collection-views/index.d.ts +3 -0
  16. package/dist/components/Debug/collection-views/sample_data.d.ts +23 -0
  17. package/dist/components/Debug/crm-dashboard/CalendarWidget.d.ts +22 -0
  18. package/dist/components/Debug/crm-dashboard/CrmDashboardDemo.d.ts +2 -0
  19. package/dist/components/Debug/crm-dashboard/DashboardMetrics.d.ts +15 -0
  20. package/dist/components/Debug/crm-dashboard/PipelineOverview.d.ts +34 -0
  21. package/dist/components/Debug/crm-dashboard/RecentActivity.d.ts +19 -0
  22. package/dist/components/Debug/crm-dashboard/TaskFilters.d.ts +30 -0
  23. package/dist/components/Debug/crm-dashboard/TaskTable.d.ts +50 -0
  24. package/dist/components/Debug/crm-dashboard/TasksView.d.ts +41 -0
  25. package/dist/components/ErrorTooltip.d.ts +3 -0
  26. package/dist/components/ErrorView.d.ts +21 -0
  27. package/dist/components/LanguageToggle.d.ts +2 -0
  28. package/dist/components/LoginView/LoginView.d.ts +113 -0
  29. package/dist/components/LoginView/index.d.ts +2 -0
  30. package/dist/components/NotFoundPage.d.ts +2 -0
  31. package/dist/components/RebaseAuth.d.ts +10 -0
  32. package/dist/components/RebaseLogo.d.ts +7 -0
  33. package/dist/components/SchemaDriftBanner.d.ts +27 -0
  34. package/dist/components/UnsavedChangesDialog.d.ts +9 -0
  35. package/dist/components/UserDisplay.d.ts +7 -0
  36. package/dist/components/UserSelectPopover.d.ts +63 -0
  37. package/dist/components/UserSettingsView.d.ts +2 -0
  38. package/dist/components/common/index.d.ts +6 -0
  39. package/dist/components/common/table_height.d.ts +5 -0
  40. package/dist/components/common/types.d.ts +66 -0
  41. package/dist/components/common/useColumnsIds.d.ts +9 -0
  42. package/dist/components/common/useDataTableController.d.ts +45 -0
  43. package/dist/components/common/useDebouncedData.d.ts +9 -0
  44. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  45. package/dist/components/index.d.ts +18 -0
  46. package/dist/contexts/AdminModeController.d.ts +4 -0
  47. package/dist/contexts/AnalyticsContext.d.ts +3 -0
  48. package/dist/contexts/AuthControllerContext.d.ts +3 -0
  49. package/dist/contexts/CollectionScopeContext.d.ts +50 -0
  50. package/dist/contexts/ComponentOverrideContext.d.ts +42 -0
  51. package/dist/contexts/CustomizationControllerContext.d.ts +3 -0
  52. package/dist/contexts/DataDriverContext.d.ts +3 -0
  53. package/dist/contexts/DataSourcesContext.d.ts +31 -0
  54. package/dist/contexts/DatabaseAdminContext.d.ts +3 -0
  55. package/dist/contexts/DialogsProvider.d.ts +4 -0
  56. package/dist/contexts/EffectiveRoleController.d.ts +4 -0
  57. package/dist/contexts/ModeController.d.ts +4 -0
  58. package/dist/contexts/RebaseClientInstanceContext.d.ts +6 -0
  59. package/dist/contexts/RebaseDataContext.d.ts +3 -0
  60. package/dist/contexts/SnackbarProvider.d.ts +2 -0
  61. package/dist/contexts/StorageSourceContext.d.ts +3 -0
  62. package/dist/contexts/StorageSourcesContext.d.ts +25 -0
  63. package/dist/contexts/UserConfigurationPersistenceContext.d.ts +3 -0
  64. package/dist/contexts/index.d.ts +17 -0
  65. package/dist/core/PluginLifecycleManager.d.ts +17 -0
  66. package/dist/core/PluginProviderStack.d.ts +21 -0
  67. package/dist/core/Rebase.d.ts +15 -0
  68. package/dist/core/RebaseProps.d.ts +291 -0
  69. package/dist/core/RebaseRouter.d.ts +4 -0
  70. package/dist/core/RebaseRoutes.d.ts +17 -0
  71. package/dist/core/index.d.ts +4 -0
  72. package/dist/hooks/ApiConfigContext.d.ts +24 -0
  73. package/dist/hooks/data/delete.d.ts +33 -0
  74. package/dist/hooks/data/save.d.ts +40 -0
  75. package/dist/hooks/data/useCollection.d.ts +62 -0
  76. package/dist/hooks/data/useData.d.ts +13 -0
  77. package/dist/hooks/data/useDataOrder.d.ts +12 -0
  78. package/dist/hooks/data/useFetch.d.ts +43 -0
  79. package/dist/hooks/data/useRelationSelector.d.ts +52 -0
  80. package/dist/hooks/index.d.ts +36 -0
  81. package/dist/hooks/useAdminModeController.d.ts +19 -0
  82. package/dist/hooks/useAnalyticsController.d.ts +5 -0
  83. package/dist/hooks/useAuthController.d.ts +11 -0
  84. package/dist/hooks/useAuthSubscription.d.ts +2 -0
  85. package/dist/hooks/useBackendStorageSource.d.ts +30 -0
  86. package/dist/hooks/useBridgeRegistration.d.ts +18 -0
  87. package/dist/hooks/useBrowserTitleAndIcon.d.ts +6 -0
  88. package/dist/hooks/useBuildAdminModeController.d.ts +6 -0
  89. package/dist/hooks/useBuildEffectiveRoleController.d.ts +8 -0
  90. package/dist/hooks/useBuildLocalConfigurationPersistence.d.ts +2 -0
  91. package/dist/hooks/useBuildModeController.d.ts +6 -0
  92. package/dist/hooks/useClipboard.d.ts +57 -0
  93. package/dist/hooks/useCollapsedGroups.d.ts +27 -0
  94. package/dist/hooks/useComponentOverride.d.ts +32 -0
  95. package/dist/hooks/useCustomizationController.d.ts +11 -0
  96. package/dist/hooks/useDialogsController.d.ts +11 -0
  97. package/dist/hooks/useEffectiveRoleController.d.ts +7 -0
  98. package/dist/hooks/useLargeLayout.d.ts +1 -0
  99. package/dist/hooks/useModeController.d.ts +19 -0
  100. package/dist/hooks/usePermissions.d.ts +12 -0
  101. package/dist/hooks/useRebaseClient.d.ts +5 -0
  102. package/dist/hooks/useRebaseContext.d.ts +11 -0
  103. package/dist/hooks/useRebaseRegistry.d.ts +34 -0
  104. package/dist/hooks/useResolvedComponent.d.ts +47 -0
  105. package/dist/hooks/useSlot.d.ts +18 -0
  106. package/dist/hooks/useSnackbarController.d.ts +20 -0
  107. package/dist/hooks/useStorageSource.d.ts +6 -0
  108. package/dist/hooks/useStudioBridge.d.ts +79 -0
  109. package/dist/hooks/useTranslation.d.ts +17 -0
  110. package/dist/hooks/useUnsavedChangesDialog.d.ts +12 -0
  111. package/dist/hooks/useUserConfigurationPersistence.d.ts +8 -0
  112. package/dist/i18n/RebaseI18nProvider.d.ts +33 -0
  113. package/dist/index.d.ts +16 -0
  114. package/dist/index.es.js +16843 -0
  115. package/dist/index.es.js.map +1 -0
  116. package/dist/index.umd.js +17021 -0
  117. package/dist/index.umd.js.map +1 -0
  118. package/dist/internal/common.d.ts +14 -0
  119. package/dist/internal/useRestoreScroll.d.ts +15 -0
  120. package/dist/locales/de.d.ts +2 -0
  121. package/dist/locales/en.d.ts +10 -0
  122. package/dist/locales/es.d.ts +10 -0
  123. package/dist/locales/fr.d.ts +2 -0
  124. package/dist/locales/hi.d.ts +2 -0
  125. package/dist/locales/it.d.ts +2 -0
  126. package/dist/locales/pt.d.ts +7 -0
  127. package/dist/util/constants.d.ts +1 -0
  128. package/dist/util/createFormexStub.d.ts +2 -0
  129. package/dist/util/entity_cache.d.ts +22 -0
  130. package/dist/util/enums.d.ts +5 -0
  131. package/dist/util/icon_list.d.ts +5 -0
  132. package/dist/util/icons.d.ts +20 -0
  133. package/dist/util/index.d.ts +8 -0
  134. package/dist/util/previews.d.ts +4 -0
  135. package/dist/util/useStorageUploadController.d.ts +44 -0
  136. package/dist/vitePlugin.d.ts +60 -0
  137. package/dist/vitePlugin.js +113 -0
  138. package/package.json +145 -0
  139. package/src/auth/api.ts +148 -0
  140. package/src/auth/index.ts +25 -0
  141. package/src/auth/types.ts +115 -0
  142. package/src/auth/useRebaseAuthController.ts +328 -0
  143. package/src/components/AIIcon.tsx +47 -0
  144. package/src/components/AuthSimulationMenu.tsx +0 -0
  145. package/src/components/ConfirmationDialog.tsx +48 -0
  146. package/src/components/Debug/UIReferenceView.tsx +958 -0
  147. package/src/components/Debug/UIStyleGuide.tsx +156 -0
  148. package/src/components/Debug/collection-views/CardViewDemo.tsx +85 -0
  149. package/src/components/Debug/collection-views/CollectionTableDemo.tsx +107 -0
  150. package/src/components/Debug/collection-views/KanbanBoardDemo.tsx +90 -0
  151. package/src/components/Debug/collection-views/index.ts +3 -0
  152. package/src/components/Debug/collection-views/sample_data.ts +42 -0
  153. package/src/components/Debug/crm-dashboard/CalendarWidget.tsx +389 -0
  154. package/src/components/Debug/crm-dashboard/CrmDashboardDemo.tsx +1102 -0
  155. package/src/components/Debug/crm-dashboard/DashboardMetrics.tsx +133 -0
  156. package/src/components/Debug/crm-dashboard/PipelineOverview.tsx +290 -0
  157. package/src/components/Debug/crm-dashboard/RecentActivity.tsx +215 -0
  158. package/src/components/Debug/crm-dashboard/TaskFilters.tsx +184 -0
  159. package/src/components/Debug/crm-dashboard/TaskTable.tsx +427 -0
  160. package/src/components/Debug/crm-dashboard/TasksView.tsx +234 -0
  161. package/src/components/ErrorTooltip.tsx +12 -0
  162. package/src/components/ErrorView.tsx +94 -0
  163. package/src/components/LanguageToggle.tsx +59 -0
  164. package/src/components/LoginView/LoginView.tsx +932 -0
  165. package/src/components/LoginView/index.ts +2 -0
  166. package/src/components/NotFoundPage.tsx +27 -0
  167. package/src/components/RebaseAuth.tsx +27 -0
  168. package/src/components/RebaseLogo.tsx +29 -0
  169. package/src/components/SchemaDriftBanner.tsx +102 -0
  170. package/src/components/UnsavedChangesDialog.tsx +46 -0
  171. package/src/components/UserDisplay.tsx +54 -0
  172. package/src/components/UserSelectPopover.tsx +399 -0
  173. package/src/components/UserSettingsView.tsx +318 -0
  174. package/src/components/common/index.ts +6 -0
  175. package/src/components/common/table_height.tsx +21 -0
  176. package/src/components/common/types.tsx +66 -0
  177. package/src/components/common/useColumnsIds.tsx +222 -0
  178. package/src/components/common/useDataTableController.tsx +514 -0
  179. package/src/components/common/useDebouncedData.ts +49 -0
  180. package/src/components/common/useScrollRestoration.tsx +68 -0
  181. package/src/components/index.tsx +26 -0
  182. package/src/contexts/AdminModeController.tsx +11 -0
  183. package/src/contexts/AnalyticsContext.tsx +4 -0
  184. package/src/contexts/AuthControllerContext.tsx +4 -0
  185. package/src/contexts/CollectionScopeContext.tsx +67 -0
  186. package/src/contexts/ComponentOverrideContext.tsx +81 -0
  187. package/src/contexts/CustomizationControllerContext.tsx +4 -0
  188. package/src/contexts/DataDriverContext.tsx +4 -0
  189. package/src/contexts/DataSourcesContext.tsx +36 -0
  190. package/src/contexts/DatabaseAdminContext.tsx +4 -0
  191. package/src/contexts/DialogsProvider.tsx +56 -0
  192. package/src/contexts/EffectiveRoleController.tsx +12 -0
  193. package/src/contexts/ModeController.tsx +11 -0
  194. package/src/contexts/RebaseClientInstanceContext.tsx +7 -0
  195. package/src/contexts/RebaseDataContext.tsx +4 -0
  196. package/src/contexts/SnackbarProvider.tsx +15 -0
  197. package/src/contexts/StorageSourceContext.tsx +4 -0
  198. package/src/contexts/StorageSourcesContext.tsx +30 -0
  199. package/src/contexts/UserConfigurationPersistenceContext.tsx +4 -0
  200. package/src/contexts/index.ts +17 -0
  201. package/src/core/PluginLifecycleManager.tsx +95 -0
  202. package/src/core/PluginProviderStack.tsx +40 -0
  203. package/src/core/Rebase.tsx +439 -0
  204. package/src/core/RebaseProps.tsx +320 -0
  205. package/src/core/RebaseRouter.tsx +17 -0
  206. package/src/core/RebaseRoutes.tsx +24 -0
  207. package/src/core/index.tsx +5 -0
  208. package/src/hooks/ApiConfigContext.tsx +41 -0
  209. package/src/hooks/data/delete.ts +55 -0
  210. package/src/hooks/data/save.ts +77 -0
  211. package/src/hooks/data/useCollection.tsx +176 -0
  212. package/src/hooks/data/useData.tsx +18 -0
  213. package/src/hooks/data/useDataOrder.ts +26 -0
  214. package/src/hooks/data/useFetch.tsx +140 -0
  215. package/src/hooks/data/useRelationSelector.tsx +234 -0
  216. package/src/hooks/index.tsx +45 -0
  217. package/src/hooks/useAdminModeController.tsx +23 -0
  218. package/src/hooks/useAnalyticsController.tsx +8 -0
  219. package/src/hooks/useAuthController.tsx +14 -0
  220. package/src/hooks/useAuthSubscription.ts +87 -0
  221. package/src/hooks/useBackendStorageSource.ts +288 -0
  222. package/src/hooks/useBridgeRegistration.tsx +32 -0
  223. package/src/hooks/useBrowserTitleAndIcon.tsx +23 -0
  224. package/src/hooks/useBuildAdminModeController.tsx +24 -0
  225. package/src/hooks/useBuildEffectiveRoleController.tsx +31 -0
  226. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +75 -0
  227. package/src/hooks/useBuildModeController.tsx +71 -0
  228. package/src/hooks/useClipboard.tsx +158 -0
  229. package/src/hooks/useCollapsedGroups.ts +116 -0
  230. package/src/hooks/useComponentOverride.tsx +59 -0
  231. package/src/hooks/useCustomizationController.tsx +14 -0
  232. package/src/hooks/useDialogsController.tsx +15 -0
  233. package/src/hooks/useEffectiveRoleController.tsx +10 -0
  234. package/src/hooks/useLargeLayout.tsx +65 -0
  235. package/src/hooks/useModeController.tsx +23 -0
  236. package/src/hooks/usePermissions.ts +44 -0
  237. package/src/hooks/useRebaseClient.tsx +10 -0
  238. package/src/hooks/useRebaseContext.tsx +83 -0
  239. package/src/hooks/useRebaseRegistry.tsx +91 -0
  240. package/src/hooks/useResolvedComponent.tsx +159 -0
  241. package/src/hooks/useSlot.tsx +64 -0
  242. package/src/hooks/useSnackbarController.tsx +52 -0
  243. package/src/hooks/useStorageSource.tsx +11 -0
  244. package/src/hooks/useStudioBridge.tsx +209 -0
  245. package/src/hooks/useTranslation.ts +33 -0
  246. package/src/hooks/useUnsavedChangesDialog.tsx +64 -0
  247. package/src/hooks/useUserConfigurationPersistence.tsx +11 -0
  248. package/src/i18n/RebaseI18nProvider.tsx +160 -0
  249. package/src/index.ts +25 -0
  250. package/src/internal/common.tsx +16 -0
  251. package/src/internal/useRestoreScroll.tsx +69 -0
  252. package/src/locales/de.ts +902 -0
  253. package/src/locales/en.ts +980 -0
  254. package/src/locales/es.ts +922 -0
  255. package/src/locales/fr.ts +901 -0
  256. package/src/locales/hi.ts +901 -0
  257. package/src/locales/it.ts +901 -0
  258. package/src/locales/pt.ts +909 -0
  259. package/src/util/constants.ts +7 -0
  260. package/src/util/createFormexStub.tsx +66 -0
  261. package/src/util/entity_cache.ts +239 -0
  262. package/src/util/enums.ts +32 -0
  263. package/src/util/icon_list.ts +22 -0
  264. package/src/util/icons.tsx +149 -0
  265. package/src/util/index.ts +12 -0
  266. package/src/util/previews.ts +105 -0
  267. package/src/util/useStorageUploadController.tsx +350 -0
  268. package/src/vitePlugin.ts +196 -0
@@ -0,0 +1,439 @@
1
+ "use client";
2
+ import type { RebaseProps } from "./RebaseProps";
3
+ import type { CustomizationController, RebasePlugin, SlotContribution } from "@rebasepro/types";
4
+ import type { ComponentOverrideMap } from "@rebasepro/types";
5
+
6
+ import React, { useEffect, useMemo, useRef, useState } from "react";
7
+ import { CenteredView, Typography } from "@rebasepro/ui";
8
+ import { RebaseContext, User, CollectionRegistryController, DataDriver, DataSourceDefinition, RebaseData, DEFAULT_DATA_SOURCE_KEY, StorageSource, StorageSourceDefinition, DEFAULT_STORAGE_SOURCE_KEY } from "@rebasepro/types";
9
+ import { PluginProviderStack } from "./PluginProviderStack";
10
+ import { PluginLifecycleManager } from "./PluginLifecycleManager";
11
+ import { AuthControllerContext } from "../contexts";
12
+ import { useCustomizationController, useRebaseContext, useAuthSubscription } from "../hooks";
13
+ import { ApiConfigProvider, useApiConfig } from "../hooks/ApiConfigContext";
14
+ import { ErrorView } from "../components";
15
+ import { StorageSourceContext } from "../contexts/StorageSourceContext";
16
+ import { UserConfigurationPersistenceContext } from "../contexts/UserConfigurationPersistenceContext";
17
+ import { RebaseDataContext } from "../contexts/RebaseDataContext";
18
+ import { DataSourcesContext, DataSourcesContextValue } from "../contexts/DataSourcesContext";
19
+ import { StorageSourcesContext, StorageSourcesContextValue } from "../contexts/StorageSourcesContext";
20
+ import { DatabaseAdminContext } from "../contexts/DatabaseAdminContext";
21
+ import { ModeControllerProvider, AdminModeControllerProvider, SnackbarProvider } from "../contexts";
22
+ import { RebaseI18nProvider } from "../i18n/RebaseI18nProvider";
23
+ import { RebaseRegistryProvider } from "../hooks/useRebaseRegistry";
24
+ import { SchemaDriftProvider } from "../components/SchemaDriftBanner";
25
+ import { GlobalComponentOverrideProvider } from "../contexts/ComponentOverrideContext";
26
+ import { useBuildModeController } from "../hooks/useBuildModeController";
27
+ import { useBuildAdminModeController } from "../hooks/useBuildAdminModeController";
28
+ import { RebaseClientInstanceContext } from "../contexts/RebaseClientInstanceContext";
29
+ import { DialogsProvider } from "../contexts/DialogsProvider";
30
+ import { buildRebaseData, wrapAsEntityData, CollectionRegistry } from "@rebasepro/common";
31
+ import { CustomizationControllerContext } from "../contexts/CustomizationControllerContext";
32
+ import { AnalyticsContext } from "../contexts/AnalyticsContext";
33
+
34
+ import { EffectiveRoleControllerContext } from "../contexts/EffectiveRoleController";
35
+ import { useBuildEffectiveRoleController } from "../hooks/useBuildEffectiveRoleController";
36
+
37
+ /**
38
+ * If you are using independent components of the CMS
39
+ * you need to wrap them with this main component, so the internal hooks work.
40
+ *
41
+ * This is the main component of Rebase. It acts as the provider of all the
42
+ * internal contexts and hooks.
43
+ *
44
+ * You only need to use this component if you are building a custom app.
45
+ *
46
+ * @group Core
47
+ */
48
+ export function Rebase<USER extends User>(props: RebaseProps<USER>) {
49
+
50
+ const {
51
+ children,
52
+ entityLinkBuilder,
53
+ userConfigPersistence,
54
+ dateTimeFormat,
55
+ locale,
56
+ client,
57
+ authController: authControllerProp,
58
+ storageSource: storageSourceProp,
59
+ dataSources: dataSourcesProp,
60
+ storageSources: storageSourcesProp,
61
+
62
+ databaseAdmin,
63
+ plugins: pluginsProp,
64
+ slots: directSlots = [],
65
+ onAnalyticsEvent,
66
+ propertyConfigs,
67
+ entityViews,
68
+ entityActions,
69
+
70
+ effectiveRoleController,
71
+ apiUrl,
72
+ translations,
73
+ components: componentsProp
74
+ } = props;
75
+
76
+ const plugins = pluginsProp;
77
+
78
+ // Validate plugin key uniqueness
79
+ if (plugins) {
80
+ const keys = plugins.map((p) => p.key);
81
+ if (new Set(keys).size !== keys.length) {
82
+ console.error("Duplicate plugin keys detected:", keys.filter((k, i) => keys.indexOf(k) !== i));
83
+ }
84
+ }
85
+
86
+ // Merge direct slots with plugin slots
87
+ const resolvedSlots: SlotContribution[] = useMemo(() => [
88
+ ...directSlots,
89
+ ...((plugins ?? []).flatMap((p) => p.slots ?? []))
90
+ ], [directSlots, plugins]);
91
+
92
+
93
+ // Auth fallback logic
94
+ const clientAuthController = useAuthSubscription(authControllerProp ? undefined : client?.auth);
95
+ const authController = authControllerProp ?? clientAuthController;
96
+
97
+ const normalizedDataSources = useMemo(() => {
98
+ return dataSourcesProp ?? [];
99
+ }, [dataSourcesProp]);
100
+
101
+ // Build the data-source context: the declared registry plus a RebaseData
102
+ // per direct/custom source (those carrying a client-side driver). Server-
103
+ // mediated sources have no entry — they ride the default client.
104
+ //
105
+ // Shallow-compared against the previous build (key/engine/transport +
106
+ // driver instances) so inline `dataSources` literals don't rebuild
107
+ // RebaseData instances every render and thrash data-fetch effects that
108
+ // key off the data identity.
109
+ const dataSourcesRef = useRef<{
110
+ sig: { key: string; engine: string; transport?: string; driver?: DataDriver }[];
111
+ value: DataSourcesContextValue;
112
+ } | null>(null);
113
+ const dataSourcesValue = useMemo<DataSourcesContextValue>(() => {
114
+ const sig = normalizedDataSources.map((d) => ({ key: d.key, engine: d.engine, transport: d.transport, driver: d.driver }));
115
+ const prev = dataSourcesRef.current;
116
+ if (prev
117
+ && prev.sig.length === sig.length
118
+ && sig.every((s, i) => prev.sig[i].key === s.key
119
+ && prev.sig[i].engine === s.engine
120
+ && prev.sig[i].transport === s.transport
121
+ && prev.sig[i].driver === s.driver)) {
122
+ return prev.value;
123
+ }
124
+ const registry: Record<string, DataSourceDefinition> = {};
125
+ const sources: Record<string, RebaseData> = {};
126
+ for (const ds of normalizedDataSources) {
127
+ const { driver, ...definition } = ds;
128
+ // Materialize the inferred transport so downstream consumers
129
+ // (routing, editor capabilities) always see a concrete value.
130
+ registry[ds.key] = {
131
+ ...definition,
132
+ transport: ds.transport ?? (driver ? "direct" : "server")
133
+ };
134
+ if (driver) sources[ds.key] = buildRebaseData(driver);
135
+ }
136
+ const value: DataSourcesContextValue = { registry, sources };
137
+ dataSourcesRef.current = { sig, value };
138
+ return value;
139
+ }, [normalizedDataSources]);
140
+
141
+ // Default data source — serves every collection not routed to a
142
+ // registered direct/custom source. Resolution:
143
+ // 1. A "(default)"-keyed data source with a driver.
144
+ // 2. `client.data`.
145
+ // 3. The sole registered source, when it is the only candidate.
146
+ const resolvedData = useMemo(() => {
147
+ const registeredDefault = dataSourcesValue.sources[DEFAULT_DATA_SOURCE_KEY];
148
+ if (registeredDefault) return registeredDefault;
149
+ // CMS boundary: the SDK client returns flat rows; wrap them into the
150
+ // Entity view-model the admin (`useData()`) renders.
151
+ if (client?.data) return wrapAsEntityData(client.data);
152
+ const built = Object.values(dataSourcesValue.sources);
153
+ if (built.length === 1) return built[0];
154
+ if (built.length > 1) {
155
+ throw new Error(
156
+ "[Rebase] Several data sources are registered but none is the default. " +
157
+ "Pass a `client`, or key one `dataSources` entry \"(default)\"."
158
+ );
159
+ }
160
+ throw new Error("Rebase requires either `client` or a `dataSources` entry with a driver to be provided");
161
+ }, [client, dataSourcesValue]);
162
+
163
+ // Storage fallback logic
164
+ const resolvedStorage = storageSourceProp ?? client?.storage;
165
+
166
+ // ── Storage sources (mirrors the dataSources pattern) ────────────
167
+ // Storage-source definitions discovered from the backend via
168
+ // `GET /api/storage/sources`. The backend is the single source of truth;
169
+ // server-transport sources are auto-wired on the client, `direct` sources
170
+ // are completed by the `storageSources` prop (which holds live instances).
171
+ const [remoteStorageSources, setRemoteStorageSources] = useState<StorageSourceDefinition[]>([]);
172
+ const authUser = authController.user;
173
+ const loginSkipped = authController.loginSkipped;
174
+ useEffect(() => {
175
+ if (!client?.fetchStorageSources) return;
176
+ let cancelled = false;
177
+ client.fetchStorageSources()
178
+ .then((defs) => { if (!cancelled) setRemoteStorageSources(defs); })
179
+ .catch((e) => {
180
+ // A 401 before auth is expected; the effect re-runs once the
181
+ // user logs in (authUser/loginSkipped change) and retries.
182
+ console.debug("[Rebase] Could not load storage sources", e);
183
+ });
184
+ return () => { cancelled = true; };
185
+ // eslint-disable-next-line react-hooks/exhaustive-deps
186
+ }, [client, authUser, loginSkipped]);
187
+
188
+ // Normalize the prop + discovered definitions into a registry + sources map.
189
+ const storageSourcesRef = useRef<{
190
+ propList: { key: string; source?: StorageSource; transport?: string }[];
191
+ remote: StorageSourceDefinition[];
192
+ resolvedStorage?: StorageSource;
193
+ client?: typeof client;
194
+ value: StorageSourcesContextValue;
195
+ } | null>(null);
196
+ const storageSourcesValue = useMemo<StorageSourcesContextValue>(() => {
197
+ const list = storageSourcesProp ?? [];
198
+ const prev = storageSourcesRef.current;
199
+ // Stable identity unless an input actually changed (the prop may be a
200
+ // fresh array literal on every render; sources are compared by identity).
201
+ if (prev
202
+ && prev.remote === remoteStorageSources
203
+ && prev.resolvedStorage === resolvedStorage
204
+ && prev.client === client
205
+ && prev.propList.length === list.length
206
+ && list.every((s, i) => prev.propList[i].key === s.key
207
+ && prev.propList[i].source === s.source
208
+ && prev.propList[i].transport === s.transport)) {
209
+ return prev.value;
210
+ }
211
+ const registry: Record<string, StorageSourceDefinition> = {};
212
+ const sources: Record<string, StorageSource> = {};
213
+
214
+ // 1. Definitions discovered from the backend (labels, engine, transport).
215
+ for (const def of remoteStorageSources) {
216
+ registry[def.key] = def;
217
+ }
218
+
219
+ // 2. Server-backed named sources wired on the client registry: the
220
+ // default, `createRebaseClient({ storageSources })`, and any
221
+ // server-transport sources auto-registered by `fetchStorageSources`.
222
+ if (client?.storageRegistry) {
223
+ for (const key of client.storageRegistry.list()) {
224
+ const source = client.storageRegistry.get(key);
225
+ if (source) sources[key] = source;
226
+ }
227
+ }
228
+
229
+ // 3. App-provided definitions: `direct` live sources and overrides.
230
+ for (const ss of list) {
231
+ const { source, ...definition } = ss;
232
+ registry[ss.key] = definition;
233
+ if (source) {
234
+ // `direct` transport: app-provided live source (e.g. Firebase).
235
+ sources[ss.key] = source;
236
+ } else if (!sources[ss.key]
237
+ && ss.transport === "server"
238
+ && ss.key !== DEFAULT_STORAGE_SOURCE_KEY
239
+ && client?.createStorageSource) {
240
+ // `server` transport declared only on the prop: build a
241
+ // backend-routed source so requests carry `?storageId=key`.
242
+ sources[ss.key] = client.createStorageSource(ss.key);
243
+ }
244
+ }
245
+ // 4. Default/server storage from the client.
246
+ if (resolvedStorage && !sources[DEFAULT_STORAGE_SOURCE_KEY]) {
247
+ sources[DEFAULT_STORAGE_SOURCE_KEY] = resolvedStorage;
248
+ }
249
+ const value: StorageSourcesContextValue = { registry, sources };
250
+ storageSourcesRef.current = {
251
+ propList: list.map((s) => ({ key: s.key, source: s.source, transport: s.transport })),
252
+ remote: remoteStorageSources,
253
+ resolvedStorage,
254
+ client,
255
+ value
256
+ };
257
+ return value;
258
+ }, [storageSourcesProp, remoteStorageSources, resolvedStorage, client]);
259
+
260
+ // Database admin — use explicit prop, or derive from client.ws / driver when available.
261
+ const resolvedDatabaseAdmin = useMemo(() => {
262
+ if (databaseAdmin) return databaseAdmin;
263
+
264
+ // 1. The default source's DataDriver exposes `.admin` capability object
265
+ const defaultDriver = normalizedDataSources.find((d) => d.key === DEFAULT_DATA_SOURCE_KEY && d.driver)?.driver
266
+ ?? (!client && normalizedDataSources.length === 1 ? normalizedDataSources[0].driver : undefined);
267
+ if (defaultDriver?.admin) {
268
+ return defaultDriver.admin;
269
+ }
270
+
271
+ // 2. Auto-derive from the client's WebSocket connection (Rebase backend)
272
+ const ws = client?.ws;
273
+ if (ws && typeof (ws as unknown as Record<string, unknown>).executeSql === "function") {
274
+ const wsAdmin = ws as unknown as import("@rebasepro/types").DatabaseAdmin;
275
+ return {
276
+ executeSql: wsAdmin.executeSql!.bind(wsAdmin),
277
+ fetchAvailableDatabases: wsAdmin.fetchAvailableDatabases?.bind(wsAdmin),
278
+ fetchAvailableRoles: wsAdmin.fetchAvailableRoles?.bind(wsAdmin),
279
+ fetchCurrentDatabase: wsAdmin.fetchCurrentDatabase?.bind(wsAdmin),
280
+ fetchUnmappedTables: wsAdmin.fetchUnmappedTables?.bind(wsAdmin),
281
+ fetchTableMetadata: wsAdmin.fetchTableMetadata?.bind(wsAdmin),
282
+ // Branch admin capabilities
283
+ ...(typeof wsAdmin.createBranch === "function" ? {
284
+ createBranch: wsAdmin.createBranch.bind(wsAdmin),
285
+ deleteBranch: wsAdmin.deleteBranch!.bind(wsAdmin),
286
+ listBranches: wsAdmin.listBranches!.bind(wsAdmin)
287
+ } : {})
288
+ };
289
+ }
290
+
291
+ return undefined;
292
+ }, [databaseAdmin, client, normalizedDataSources]);
293
+
294
+ if (!resolvedStorage && typeof console !== "undefined") {
295
+ console.warn(
296
+ "[Rebase] No storageSource provided. File upload features will not work. " +
297
+ "Provide storageSource via props or through a RebaseClient."
298
+ );
299
+ }
300
+
301
+ const pluginsLoading = plugins?.some((p) => p.loading) ?? false;
302
+
303
+ const loading = authController.initialLoading || pluginsLoading;
304
+
305
+ const customizationController: CustomizationController = useMemo(() => ({
306
+ dateTimeFormat,
307
+ locale,
308
+ entityLinkBuilder,
309
+ plugins,
310
+ resolvedSlots,
311
+ entityViews: entityViews ?? [],
312
+ entityActions: entityActions ?? [],
313
+ propertyConfigs: propertyConfigs ?? {},
314
+ components: componentsProp
315
+ }), [dateTimeFormat, locale, entityLinkBuilder, plugins, resolvedSlots, entityViews, entityActions, propertyConfigs, componentsProp]);
316
+
317
+ const analyticsController = useMemo(() => ({
318
+ onAnalyticsEvent
319
+ }), []);
320
+
321
+ const fallbackEffectiveRoleController = useBuildEffectiveRoleController();
322
+ const activeEffectiveRoleController = effectiveRoleController ?? fallbackEffectiveRoleController;
323
+
324
+ const modeController = useBuildModeController();
325
+ const adminModeController = useBuildAdminModeController();
326
+
327
+ if (authController.authError) {
328
+ return (
329
+ <CenteredView maxWidth={"md"}>
330
+ <ErrorView
331
+ title={"Error loading auth"}
332
+ error={authController.authError as Error | string}/>
333
+ </CenteredView>
334
+ );
335
+ }
336
+
337
+ const content = (
338
+ <RebaseI18nProvider locale={locale} translations={translations}>
339
+ <GlobalComponentOverrideProvider overrides={componentsProp}>
340
+ <SnackbarProvider>
341
+ <ModeControllerProvider value={modeController}>
342
+ <AdminModeControllerProvider value={adminModeController}>
343
+ <RebaseClientInstanceContext.Provider value={client}>
344
+ <AnalyticsContext.Provider value={analyticsController}>
345
+ <CustomizationControllerContext.Provider value={customizationController}>
346
+ <UserConfigurationPersistenceContext.Provider
347
+ value={userConfigPersistence}>
348
+ <StorageSourcesContext.Provider
349
+ value={storageSourcesValue}>
350
+ <StorageSourceContext.Provider
351
+ value={resolvedStorage!}>
352
+ <DataSourcesContext.Provider
353
+ value={dataSourcesValue}>
354
+ <RebaseDataContext.Provider
355
+ value={resolvedData}>
356
+ <DatabaseAdminContext.Provider
357
+ value={resolvedDatabaseAdmin}>
358
+ <AuthControllerContext.Provider
359
+ value={authController}>
360
+ <EffectiveRoleControllerContext.Provider value={activeEffectiveRoleController}>
361
+ <DialogsProvider>
362
+ <SchemaDriftProvider>
363
+ <RebaseRegistryProvider>
364
+ <RebaseInternal
365
+ loading={loading}>
366
+ {children}
367
+ </RebaseInternal>
368
+ </RebaseRegistryProvider>
369
+ </SchemaDriftProvider>
370
+ </DialogsProvider>
371
+ </EffectiveRoleControllerContext.Provider>
372
+ </AuthControllerContext.Provider>
373
+ </DatabaseAdminContext.Provider>
374
+ </RebaseDataContext.Provider>
375
+ </DataSourcesContext.Provider>
376
+ </StorageSourceContext.Provider>
377
+ </StorageSourcesContext.Provider>
378
+ </UserConfigurationPersistenceContext.Provider>
379
+ </CustomizationControllerContext.Provider>
380
+ </AnalyticsContext.Provider>
381
+ </RebaseClientInstanceContext.Provider>
382
+ </AdminModeControllerProvider>
383
+ </ModeControllerProvider>
384
+ </SnackbarProvider>
385
+ </GlobalComponentOverrideProvider>
386
+ </RebaseI18nProvider>
387
+ );
388
+
389
+ const resolvedApiUrl = apiUrl || client?.baseUrl || (typeof window !== "undefined" ? window.location.origin : "");
390
+
391
+ if (resolvedApiUrl) {
392
+ return (
393
+ <ApiConfigProvider apiUrl={resolvedApiUrl} getAuthToken={authController.getAuthToken}>
394
+ {content}
395
+ </ApiConfigProvider>
396
+ );
397
+ }
398
+
399
+ return content;
400
+
401
+ }
402
+
403
+ function RebaseInternal({
404
+ loading,
405
+ children
406
+ }: {
407
+ loading: boolean;
408
+ children: React.ReactNode | ((props: { context: RebaseContext; loading: boolean; }) => React.ReactNode);
409
+ }) {
410
+
411
+ const context = useRebaseContext();
412
+ const customizationController = useCustomizationController();
413
+
414
+ const childrenResult = typeof children === "function" ? children({
415
+ context,
416
+ loading
417
+ }) : children;
418
+
419
+ const plugins = customizationController.plugins;
420
+ const authController = context.authController;
421
+ const authReady = !loading
422
+ && !authController.authLoading
423
+ && (Boolean(authController.user) || authController.loginSkipped);
424
+
425
+ if (plugins && plugins.length > 0) {
426
+ return (
427
+ <PluginProviderStack
428
+ plugins={plugins}
429
+ scope="root"
430
+ scopeProps={{ context }}>
431
+ {authReady && <PluginLifecycleManager plugins={plugins} context={context}/>}
432
+ {childrenResult}
433
+ </PluginProviderStack>
434
+ );
435
+ }
436
+
437
+ return childrenResult;
438
+ }
439
+