@rebasepro/app 0.17.3 → 0.18.1

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 (185) hide show
  1. package/README.md +4 -1
  2. package/dist/components/index.d.ts +0 -3
  3. package/dist/contexts/AuthControllerContext.d.ts +2 -1
  4. package/dist/contexts/CustomizationControllerContext.d.ts +2 -1
  5. package/dist/contexts/DialogsProvider.d.ts +2 -1
  6. package/dist/contexts/RebaseDataContext.d.ts +10 -1
  7. package/dist/contexts/StorageSourceContext.d.ts +11 -1
  8. package/dist/core/RebaseProps.d.ts +2 -12
  9. package/dist/debug/index.d.ts +19 -0
  10. package/dist/debug.js +3631 -0
  11. package/dist/hooks/data/delete.d.ts +16 -7
  12. package/dist/hooks/data/save.d.ts +18 -4
  13. package/dist/hooks/index.d.ts +1 -0
  14. package/dist/hooks/useAdminModeController.d.ts +5 -4
  15. package/dist/hooks/useNavigationGroupLabel.d.ts +17 -0
  16. package/dist/hooks/useStudioBridge.d.ts +33 -0
  17. package/dist/index.es.js +2599 -6980
  18. package/dist/index.es.js.map +1 -1
  19. package/dist/vitePlugin.d.ts +22 -0
  20. package/dist/vitePlugin.js +40 -1
  21. package/package.json +42 -31
  22. package/src/auth/api.ts +0 -134
  23. package/src/auth/index.ts +0 -26
  24. package/src/auth/types.ts +0 -115
  25. package/src/auth/useRebaseAuthController.ts +0 -345
  26. package/src/collections/collection_view_config.ts +0 -76
  27. package/src/collections/entity-display-cache.ts +0 -195
  28. package/src/collections/entity-display.ts +0 -77
  29. package/src/collections/entity_image_preview.ts +0 -61
  30. package/src/collections/filter-operator-resolution.ts +0 -119
  31. package/src/collections/form-layout.ts +0 -394
  32. package/src/collections/index.ts +0 -13
  33. package/src/collections/navigation_from_path.ts +0 -123
  34. package/src/collections/navigation_utils.ts +0 -171
  35. package/src/collections/parent_references_from_path.ts +0 -59
  36. package/src/collections/property-path.ts +0 -30
  37. package/src/collections/property_presentation.ts +0 -264
  38. package/src/collections/summary-property.ts +0 -114
  39. package/src/collections/title-property.ts +0 -312
  40. package/src/components/AIIcon.tsx +0 -47
  41. package/src/components/AuthSimulationMenu.tsx +0 -0
  42. package/src/components/ConfirmationDialog.tsx +0 -48
  43. package/src/components/Debug/UIReferenceView.tsx +0 -1053
  44. package/src/components/Debug/UIStyleGuide.tsx +0 -159
  45. package/src/components/Debug/collection-views/CardViewDemo.tsx +0 -87
  46. package/src/components/Debug/collection-views/CollectionTableDemo.tsx +0 -107
  47. package/src/components/Debug/collection-views/KanbanBoardDemo.tsx +0 -89
  48. package/src/components/Debug/collection-views/index.ts +0 -3
  49. package/src/components/Debug/collection-views/sample_data.ts +0 -44
  50. package/src/components/Debug/crm-dashboard/CalendarWidget.tsx +0 -387
  51. package/src/components/Debug/crm-dashboard/CrmDashboardDemo.tsx +0 -1100
  52. package/src/components/Debug/crm-dashboard/DashboardMetrics.tsx +0 -131
  53. package/src/components/Debug/crm-dashboard/PipelineOverview.tsx +0 -288
  54. package/src/components/Debug/crm-dashboard/RecentActivity.tsx +0 -213
  55. package/src/components/Debug/crm-dashboard/TaskFilters.tsx +0 -182
  56. package/src/components/Debug/crm-dashboard/TaskTable.tsx +0 -425
  57. package/src/components/Debug/crm-dashboard/TasksView.tsx +0 -234
  58. package/src/components/ErrorTooltip.tsx +0 -12
  59. package/src/components/ErrorView.tsx +0 -94
  60. package/src/components/LanguageToggle.tsx +0 -59
  61. package/src/components/LoginView/LoginView.tsx +0 -1235
  62. package/src/components/LoginView/index.ts +0 -2
  63. package/src/components/LoginView/oauth-redirect-flow.ts +0 -184
  64. package/src/components/NotFoundPage.tsx +0 -27
  65. package/src/components/RebaseAuth.tsx +0 -27
  66. package/src/components/RebaseLogo.tsx +0 -88
  67. package/src/components/SchemaDriftBanner.tsx +0 -102
  68. package/src/components/UnsavedChangesDialog.tsx +0 -46
  69. package/src/components/UserDisplay.tsx +0 -54
  70. package/src/components/UserSelectPopover.tsx +0 -399
  71. package/src/components/UserSettingsView.tsx +0 -318
  72. package/src/components/common/index.ts +0 -6
  73. package/src/components/common/table_height.tsx +0 -21
  74. package/src/components/common/types.tsx +0 -66
  75. package/src/components/common/useColumnsIds.tsx +0 -261
  76. package/src/components/common/useDataTableController.tsx +0 -571
  77. package/src/components/common/useDebouncedData.ts +0 -49
  78. package/src/components/common/useScrollRestoration.tsx +0 -68
  79. package/src/components/index.tsx +0 -26
  80. package/src/contexts/AdminModeController.tsx +0 -11
  81. package/src/contexts/AnalyticsContext.tsx +0 -4
  82. package/src/contexts/AuthControllerContext.tsx +0 -4
  83. package/src/contexts/CollectionResolverContext.tsx +0 -24
  84. package/src/contexts/CollectionScopeContext.tsx +0 -68
  85. package/src/contexts/ComponentOverrideContext.tsx +0 -81
  86. package/src/contexts/CustomizationControllerContext.tsx +0 -4
  87. package/src/contexts/DataDriverContext.tsx +0 -4
  88. package/src/contexts/DataSourcesContext.tsx +0 -36
  89. package/src/contexts/DatabaseAdminContext.tsx +0 -4
  90. package/src/contexts/DialogsProvider.tsx +0 -56
  91. package/src/contexts/EffectiveRoleController.tsx +0 -12
  92. package/src/contexts/ModeController.tsx +0 -11
  93. package/src/contexts/RebaseClientInstanceContext.tsx +0 -7
  94. package/src/contexts/RebaseDataContext.tsx +0 -4
  95. package/src/contexts/SnackbarProvider.tsx +0 -15
  96. package/src/contexts/StorageSourceContext.tsx +0 -4
  97. package/src/contexts/StorageSourcesContext.tsx +0 -30
  98. package/src/contexts/UserConfigurationPersistenceContext.tsx +0 -4
  99. package/src/contexts/index.ts +0 -18
  100. package/src/core/PluginLifecycleManager.tsx +0 -96
  101. package/src/core/PluginProviderStack.tsx +0 -40
  102. package/src/core/Rebase.tsx +0 -488
  103. package/src/core/RebaseProps.tsx +0 -333
  104. package/src/core/RebaseRouter.tsx +0 -18
  105. package/src/core/RebaseRoutes.tsx +0 -24
  106. package/src/core/index.tsx +0 -5
  107. package/src/hooks/ApiConfigContext.tsx +0 -83
  108. package/src/hooks/data/collectionQuery.ts +0 -55
  109. package/src/hooks/data/delete.ts +0 -56
  110. package/src/hooks/data/save.ts +0 -78
  111. package/src/hooks/data/useCollection.tsx +0 -183
  112. package/src/hooks/data/useData.tsx +0 -18
  113. package/src/hooks/data/useDataOrder.ts +0 -26
  114. package/src/hooks/data/useFetch.tsx +0 -156
  115. package/src/hooks/data/useRelationSelector.tsx +0 -280
  116. package/src/hooks/index.tsx +0 -45
  117. package/src/hooks/useAdminModeController.tsx +0 -23
  118. package/src/hooks/useAnalyticsController.tsx +0 -8
  119. package/src/hooks/useAuthController.tsx +0 -15
  120. package/src/hooks/useAuthSubscription.ts +0 -130
  121. package/src/hooks/useBackendStorageSource.ts +0 -295
  122. package/src/hooks/useBridgeRegistration.tsx +0 -32
  123. package/src/hooks/useBrowserTitleAndIcon.tsx +0 -23
  124. package/src/hooks/useBuildAdminModeController.tsx +0 -29
  125. package/src/hooks/useBuildEffectiveRoleController.tsx +0 -30
  126. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +0 -83
  127. package/src/hooks/useBuildModeController.tsx +0 -73
  128. package/src/hooks/useClipboard.tsx +0 -158
  129. package/src/hooks/useCollapsedGroups.ts +0 -116
  130. package/src/hooks/useComponentOverride.tsx +0 -59
  131. package/src/hooks/useCustomizationController.tsx +0 -14
  132. package/src/hooks/useDialogsController.tsx +0 -15
  133. package/src/hooks/useEffectiveRoleController.tsx +0 -10
  134. package/src/hooks/useLargeLayout.tsx +0 -65
  135. package/src/hooks/useModeController.tsx +0 -23
  136. package/src/hooks/useNavigationBlocker.tsx +0 -108
  137. package/src/hooks/usePermissions.ts +0 -45
  138. package/src/hooks/useRebaseClient.tsx +0 -10
  139. package/src/hooks/useRebaseContext.tsx +0 -84
  140. package/src/hooks/useRebaseRegistry.tsx +0 -91
  141. package/src/hooks/useResolvedComponent.tsx +0 -195
  142. package/src/hooks/useSlot.tsx +0 -64
  143. package/src/hooks/useSnackbarController.tsx +0 -80
  144. package/src/hooks/useStorageSource.tsx +0 -11
  145. package/src/hooks/useStudioBridge.tsx +0 -258
  146. package/src/hooks/useTranslation.ts +0 -38
  147. package/src/hooks/useUnsavedChangesDialog.tsx +0 -67
  148. package/src/hooks/useUserConfigurationPersistence.tsx +0 -11
  149. package/src/i18n/RebaseI18nProvider.tsx +0 -159
  150. package/src/index.ts +0 -32
  151. package/src/internal/common.tsx +0 -28
  152. package/src/internal/useRestoreScroll.tsx +0 -69
  153. package/src/locales/de.ts +0 -941
  154. package/src/locales/en.ts +0 -1021
  155. package/src/locales/es.ts +0 -962
  156. package/src/locales/fr.ts +0 -941
  157. package/src/locales/hi.ts +0 -941
  158. package/src/locales/it.ts +0 -941
  159. package/src/locales/pt.ts +0 -949
  160. package/src/util/constants.ts +0 -7
  161. package/src/util/createFormexStub.tsx +0 -66
  162. package/src/util/entity_cache.ts +0 -242
  163. package/src/util/enums.ts +0 -34
  164. package/src/util/icon_list.ts +0 -22
  165. package/src/util/icons.tsx +0 -129
  166. package/src/util/index.ts +0 -13
  167. package/src/util/local_storage.ts +0 -66
  168. package/src/util/previews.ts +0 -127
  169. package/src/util/useStorageUploadController.tsx +0 -354
  170. package/src/vitePlugin.ts +0 -215
  171. /package/dist/{components/Debug → debug}/UIReferenceView.d.ts +0 -0
  172. /package/dist/{components/Debug → debug}/UIStyleGuide.d.ts +0 -0
  173. /package/dist/{components/Debug → debug}/collection-views/CardViewDemo.d.ts +0 -0
  174. /package/dist/{components/Debug → debug}/collection-views/CollectionTableDemo.d.ts +0 -0
  175. /package/dist/{components/Debug → debug}/collection-views/KanbanBoardDemo.d.ts +0 -0
  176. /package/dist/{components/Debug → debug}/collection-views/index.d.ts +0 -0
  177. /package/dist/{components/Debug → debug}/collection-views/sample_data.d.ts +0 -0
  178. /package/dist/{components/Debug → debug}/crm-dashboard/CalendarWidget.d.ts +0 -0
  179. /package/dist/{components/Debug → debug}/crm-dashboard/CrmDashboardDemo.d.ts +0 -0
  180. /package/dist/{components/Debug → debug}/crm-dashboard/DashboardMetrics.d.ts +0 -0
  181. /package/dist/{components/Debug → debug}/crm-dashboard/PipelineOverview.d.ts +0 -0
  182. /package/dist/{components/Debug → debug}/crm-dashboard/RecentActivity.d.ts +0 -0
  183. /package/dist/{components/Debug → debug}/crm-dashboard/TaskFilters.d.ts +0 -0
  184. /package/dist/{components/Debug → debug}/crm-dashboard/TaskTable.d.ts +0 -0
  185. /package/dist/{components/Debug → debug}/crm-dashboard/TasksView.d.ts +0 -0
@@ -1,45 +0,0 @@
1
- export * from "./data/useData";
2
- export * from "./data/useCollection";
3
- export * from "./data/useFetch";
4
- export * from "./data/useRelationSelector";
5
- export * from "./data/save";
6
- export * from "./data/delete";
7
-
8
-
9
- export * from "./useUnsavedChangesDialog";
10
-
11
- export * from "./useStorageSource";
12
- export * from "./useAuthController";
13
- export * from "./useAuthSubscription";
14
- export * from "./useDialogsController";
15
- export * from "./useAdminModeController";
16
- export * from "./useBuildAdminModeController";
17
- export * from "./useEffectiveRoleController";
18
- export * from "./useBuildEffectiveRoleController";
19
- export * from "./useRebaseContext";
20
- export * from "./useSnackbarController";
21
- export * from "./useModeController";
22
- export * from "./useClipboard";
23
- export * from "./useLargeLayout";
24
- export * from "./useCollapsedGroups";
25
-
26
- export * from "./useBrowserTitleAndIcon";
27
- export * from "./useSlot";
28
- export * from "./useCustomizationController";
29
-
30
- export * from "./useBuildLocalConfigurationPersistence";
31
- export * from "./useBuildModeController";
32
-
33
- export * from "./useRebaseRegistry";
34
- export * from "./useBackendStorageSource";
35
- export * from "./usePermissions";
36
-
37
- export * from "./ApiConfigContext";
38
-
39
- export * from "./useTranslation";
40
- export * from "./useRebaseClient";
41
-
42
- export * from "./useAnalyticsController";
43
- export * from "./useUserConfigurationPersistence";
44
- export * from "./useResolvedComponent";
45
- export * from "./useComponentOverride";
@@ -1,23 +0,0 @@
1
- import { AdminModeControllerContext } from "../contexts/AdminModeController";
2
- import { useContext } from "react";
3
-
4
- /**
5
- * Use this controller to change the admin mode (developer vs editor)
6
- * @group Hooks and utilities
7
- */
8
- export interface AdminModeController {
9
- mode: "cms" | "studio" | "settings";
10
- setMode: (mode: "cms" | "studio" | "settings") => void;
11
- }
12
-
13
- /**
14
- * Hook to retrieve the current admin mode ("developer" | "editor"), and `setMode`
15
- * to change it.
16
- *
17
- * Consider that in order to use this hook you need to have a parent
18
- * `Rebase`
19
- *
20
- * @see AdminModeController
21
- * @group Hooks and utilities
22
- */
23
- export const useAdminModeController = () => useContext(AdminModeControllerContext);
@@ -1,8 +0,0 @@
1
- import { useContext } from "react";
2
- import { AnalyticsController } from "@rebasepro/cms-types";
3
- import { AnalyticsContext } from "../contexts/AnalyticsContext";
4
-
5
- /**
6
- * @group Hooks and utilities
7
- */
8
- export const useAnalyticsController = (): AnalyticsController => useContext(AnalyticsContext);
@@ -1,15 +0,0 @@
1
- import { User } from "@rebasepro/types";
2
- import { AuthController } from "@rebasepro/cms-types";
3
- import { useContext } from "react";
4
- import { AuthControllerContext } from "../contexts/AuthControllerContext";
5
-
6
- /**
7
- * Hook to retrieve the AuthContext.
8
- *
9
- * Consider that in order to use this hook you need to have a parent
10
- * `Rebase`
11
- *
12
- * @see AuthController
13
- * @group Hooks and utilities
14
- */
15
- export const useAuthController = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): AuthControllerType => useContext(AuthControllerContext) as AuthControllerType;
@@ -1,130 +0,0 @@
1
- import { useState, useEffect, useMemo, useCallback } from "react";
2
- import { AuthClient, User } from "@rebasepro/types";
3
- import { AuthController } from "@rebasepro/cms-types";
4
-
5
- export function useAuthSubscription(authClient?: AuthClient): AuthController {
6
-
7
- // Check initial state
8
- const currentSession = authClient?.getSession();
9
- const [user, setUser] = useState<User | null>(currentSession?.user ?? null);
10
-
11
- const [authLoading, setAuthLoading] = useState(false);
12
- const [authError, setAuthError] = useState<Error>();
13
- const [loginSkipped, setLoginSkipped] = useState(false);
14
- const [extra, setExtra] = useState<any>();
15
-
16
- /**
17
- * Whether asking the server "who am I?" could possibly answer.
18
- *
19
- * A client configured with `persistSession: false` and JSON auth — the
20
- * shape used when one client borrows another's credential, as the hosted
21
- * Studio does — has no stored session and no auth cookie, so the probe
22
- * below is guaranteed to 401. Sending it anyway put three failing
23
- * `GET /auth/me` calls on the wire per mount, each one landing in the
24
- * *customer's* request log as an authentication failure against their own
25
- * backend.
26
- *
27
- * A client that does not implement the capability is treated as "might
28
- * work" — the historical behaviour.
29
- */
30
- const mayHaveRestorableSession = authClient?.canRestoreSession?.() ?? true;
31
-
32
- /**
33
- * `true` only while a probe is genuinely outstanding.
34
- *
35
- * It used to be seeded from `!currentSession` alone, which left a client
36
- * that cannot restore a session — and therefore never runs the probe that
37
- * clears the flag — reporting "still loading" forever. Anything gated on
38
- * `initialLoading` (a spinner, a redirect to the login view) would never
39
- * resolve.
40
- */
41
- const [initialLoading, setInitialLoading] = useState(!currentSession && mayHaveRestorableSession);
42
-
43
- useEffect(() => {
44
- if (!authClient) return;
45
- // If we don't have a session initially, try to get user which restores session if a persistent token exists
46
- if (!currentSession && mayHaveRestorableSession) {
47
- setInitialLoading(true);
48
- authClient.getUser()
49
- .then(user => {
50
- if (user) {
51
- setUser(user);
52
- }
53
- setAuthError(undefined);
54
- })
55
- .catch((e: unknown) => {
56
- // A 401 or 403 is the ordinary first load of an anonymous
57
- // visitor: there is no session, which is not an error.
58
- //
59
- // Everything else is. This used to swallow the lot with
60
- // "Ignore, user just isn't logged in", leaving `authError`
61
- // — a field this controller declares and `Rebase` renders a
62
- // full-screen "Error loading auth" view for — permanently
63
- // undefined. So the view was unreachable, and a backend that
64
- // was down, misconfigured, or blocked by CORS looked exactly
65
- // like being signed out: the app showed the login form.
66
- const status = (e as { status?: number } | undefined)?.status;
67
- if (status === 401 || status === 403) {
68
- setAuthError(undefined);
69
- return;
70
- }
71
- setAuthError(e instanceof Error ? e : new Error(String(e)));
72
- })
73
- .finally(() => {
74
- setInitialLoading(false);
75
- });
76
- }
77
- }, [authClient, currentSession, mayHaveRestorableSession]);
78
-
79
- useEffect(() => {
80
- if (!authClient) return;
81
- const unsubscribe = authClient.onAuthStateChange((event, session) => {
82
- if (event === "SIGNED_IN" || event === "USER_UPDATED" || event === "TOKEN_REFRESHED") {
83
- setUser(session?.user ?? null);
84
- } else if (event === "SIGNED_OUT") {
85
- setUser(null);
86
- }
87
- });
88
- return unsubscribe;
89
- }, [authClient]);
90
-
91
- const signOut = useCallback(async () => {
92
- if (!authClient) return;
93
- setAuthLoading(true);
94
- try {
95
- await authClient.signOut();
96
- } finally {
97
- setAuthLoading(false);
98
- }
99
- }, [authClient]);
100
-
101
- const getAuthToken = useCallback(async () => {
102
- if (!authClient) return "";
103
- const session = authClient.getSession();
104
- if (!session) return "";
105
- if (session.expiresAt < Date.now()) {
106
- try {
107
- const refreshed = await authClient.refreshSession();
108
- return refreshed.accessToken;
109
- } catch (e) {
110
- return "";
111
- }
112
- }
113
- return session.accessToken;
114
- }, [authClient]);
115
-
116
- return useMemo(() => ({
117
- user,
118
- initialLoading: authClient ? initialLoading : false,
119
- authLoading,
120
- signOut,
121
- authError,
122
- getAuthToken,
123
- loginSkipped,
124
- extra,
125
- setExtra
126
- } as AuthController), [
127
- user, initialLoading, authLoading, signOut, authError,
128
- getAuthToken, loginSkipped, extra, setExtra, authClient
129
- ]);
130
- }
@@ -1,295 +0,0 @@
1
- /**
2
- * React hook for using backend storage API as a StorageSource
3
- */
4
-
5
- import { useMemo, useCallback } from "react";
6
- import {
7
- StorageSource,
8
- UploadFileProps,
9
- UploadFileResult,
10
- DownloadConfig,
11
- StorageListResult
12
- } from "@rebasepro/types";
13
- import { DEFAULT_API_PATH } from "./ApiConfigContext";
14
-
15
- export interface BackendStorageSourceProps {
16
- /**
17
- * Backend API URL (e.g., 'http://localhost:3001')
18
- */
19
- apiUrl: string;
20
- /**
21
- * The path the backend mounts its API under. Defaults to the server's own
22
- * default; pass the backend's `basePath` if it was configured otherwise.
23
- */
24
- apiPath?: string;
25
- /**
26
- * Function to get the current auth token
27
- */
28
- getAuthToken: () => Promise<string>;
29
- }
30
-
31
- /**
32
- * Hook to create a StorageSource that uses the backend storage REST API.
33
- * Use this for self-hosted Rebase with local or S3 storage.
34
- *
35
- * @example
36
- * ```tsx
37
- * const storageSource = useBackendStorageSource({
38
- * apiUrl: 'http://localhost:3001',
39
- * getAuthToken: authController.getAuthToken
40
- * });
41
- *
42
- * // Then pass to Rebase:
43
- * <Rebase storageSource={storageSource} ... />
44
- * ```
45
- */
46
- export function useBackendStorageSource({
47
- apiUrl,
48
- apiPath = DEFAULT_API_PATH,
49
- getAuthToken
50
- }: BackendStorageSourceProps): StorageSource {
51
-
52
- const storageBasePath = `${apiUrl.replace(/\/+$/, "")}${apiPath}/storage`;
53
-
54
- // Cache for download URLs to avoid redundant API calls
55
- const urlsCache = useMemo(() => new Map<string, DownloadConfig>(), []);
56
-
57
- /**
58
- * Make an authenticated request to the storage API
59
- */
60
- const fetchWithAuth = useCallback(async (
61
- url: string,
62
- options: RequestInit = {}
63
- ): Promise<Response> => {
64
- const token = await getAuthToken();
65
- return fetch(url, {
66
- ...options,
67
- headers: {
68
- ...options.headers,
69
- "Authorization": `Bearer ${token}`
70
- }
71
- });
72
- }, [getAuthToken]);
73
-
74
- /**
75
- * Upload a file to storage
76
- */
77
- const putObject = useCallback(async ({
78
- file,
79
- key,
80
- metadata,
81
- bucket
82
- }: UploadFileProps): Promise<UploadFileResult> => {
83
- const formData = new FormData();
84
- formData.append("file", file);
85
-
86
- if (key) {
87
- formData.append("key", key);
88
- }
89
- if (bucket) {
90
- formData.append("bucket", bucket);
91
- }
92
-
93
- // Add metadata fields with prefix
94
- if (metadata) {
95
- for (const [key, value] of Object.entries(metadata)) {
96
- if (value !== undefined && value !== null) {
97
- formData.append(
98
- `metadata_${key}`,
99
- typeof value === "string" ? value : JSON.stringify(value)
100
- );
101
- }
102
- }
103
- }
104
-
105
- const response = await fetchWithAuth(`${storageBasePath}/upload`, {
106
- method: "POST",
107
- body: formData
108
- });
109
-
110
- if (!response.ok) {
111
- const error = await response.json().catch(() => ({ error: "Upload failed" }));
112
- throw new Error(error.error || "Upload failed");
113
- }
114
-
115
- const result = await response.json();
116
- return result.data;
117
- }, [fetchWithAuth, storageBasePath]);
118
-
119
- /**
120
- * Get download URL for a file
121
- */
122
- const getSignedUrl = useCallback(async (
123
- keyOrUrl: string,
124
- bucket?: string
125
- ): Promise<DownloadConfig> => {
126
- // Check cache first
127
- const cacheKey = bucket ? `${bucket}/${keyOrUrl}` : keyOrUrl;
128
- const cached = urlsCache.get(cacheKey);
129
- if (cached) {
130
- return cached;
131
- }
132
-
133
- // Build the file path for the API
134
- let filePath = keyOrUrl;
135
-
136
- // Handle local:// and s3:// URLs
137
- if (filePath && (filePath.startsWith("local://") || filePath.startsWith("s3://"))) {
138
- const withoutProtocol = filePath.substring(filePath.indexOf("://") + 3);
139
- filePath = withoutProtocol;
140
- }
141
-
142
- // If bucket is provided separately, prepend it
143
- if (bucket && filePath && !filePath.startsWith(bucket)) {
144
- filePath = `${bucket}/${filePath}`;
145
- }
146
-
147
- if (!filePath || filePath.trim() === "" || filePath === "/") {
148
- return { url: null,
149
- fileNotFound: true };
150
- }
151
-
152
- const response = await fetchWithAuth(`${storageBasePath}/metadata/${filePath}`);
153
-
154
- if (response.status === 404) {
155
- return {
156
- url: null,
157
- fileNotFound: true
158
- };
159
- }
160
-
161
- if (!response.ok) {
162
- const error = await response.json().catch(() => ({ error: "Failed to get download URL" }));
163
- throw new Error(error.error || "Failed to get download URL");
164
- }
165
-
166
- const result = await response.json();
167
-
168
- const token = await getAuthToken();
169
- const tokenQuery = token ? `?token=${token}` : "";
170
-
171
- // The URL should point to the storage file endpoint
172
- const downloadConfig: DownloadConfig = {
173
- url: `${storageBasePath}/file/${filePath}${tokenQuery}`,
174
- metadata: result.data
175
- };
176
-
177
- // Cache the result
178
- urlsCache.set(cacheKey, downloadConfig);
179
-
180
- return downloadConfig;
181
- }, [fetchWithAuth, storageBasePath, urlsCache]);
182
-
183
- /**
184
- * Get file as a File object
185
- */
186
- const getObject = useCallback(async (
187
- key: string,
188
- bucket?: string
189
- ): Promise<File | null> => {
190
- let filePath = key;
191
-
192
- // Handle protocol URLs
193
- if (filePath && (filePath.startsWith("local://") || filePath.startsWith("s3://"))) {
194
- const withoutProtocol = filePath.substring(filePath.indexOf("://") + 3);
195
- filePath = withoutProtocol;
196
- }
197
-
198
- if (bucket && filePath && !filePath.startsWith(bucket)) {
199
- filePath = `${bucket}/${filePath}`;
200
- }
201
-
202
- if (!filePath || filePath.trim() === "" || filePath === "/") {
203
- return null;
204
- }
205
-
206
- const response = await fetchWithAuth(`${storageBasePath}/file/${filePath}`);
207
-
208
- if (response.status === 404) {
209
- return null;
210
- }
211
-
212
- if (!response.ok) {
213
- throw new Error("Failed to get file");
214
- }
215
-
216
- const blob = await response.blob();
217
- const fileName = filePath.split("/").pop() || "file";
218
- return new File([blob], fileName, { type: blob.type });
219
- }, [fetchWithAuth, storageBasePath]);
220
-
221
- /**
222
- * Delete a file
223
- */
224
- const deleteObject = useCallback(async (
225
- key: string,
226
- bucket?: string
227
- ): Promise<void> => {
228
- let filePath = key;
229
-
230
- // Handle protocol URLs
231
- if (filePath && (filePath.startsWith("local://") || filePath.startsWith("s3://"))) {
232
- const withoutProtocol = filePath.substring(filePath.indexOf("://") + 3);
233
- filePath = withoutProtocol;
234
- }
235
-
236
- if (bucket && filePath && !filePath.startsWith(bucket)) {
237
- filePath = `${bucket}/${filePath}`;
238
- }
239
-
240
- if (!filePath || filePath.trim() === "" || filePath === "/") {
241
- return;
242
- }
243
-
244
- const response = await fetchWithAuth(`${storageBasePath}/file/${filePath}`, {
245
- method: "DELETE"
246
- });
247
-
248
- if (!response.ok && response.status !== 404) {
249
- const error = await response.json().catch(() => ({ error: "Failed to delete file" }));
250
- throw new Error(error.error || "Failed to delete file");
251
- }
252
-
253
- // Clear from cache
254
- urlsCache.delete(bucket ? `${bucket}/${key}` : key);
255
- }, [fetchWithAuth, storageBasePath, urlsCache]);
256
-
257
- /**
258
- * List files in a path
259
- */
260
- const listObjects = useCallback(async (
261
- prefix: string,
262
- options?: {
263
- bucket?: string;
264
- maxResults?: number;
265
- pageToken?: string;
266
- }
267
- ): Promise<StorageListResult> => {
268
- const params = new URLSearchParams();
269
- if (prefix) params.set("prefix", prefix);
270
- if (options?.bucket) params.set("bucket", options.bucket);
271
- if (options?.maxResults) params.set("maxResults", String(options.maxResults));
272
- if (options?.pageToken) params.set("pageToken", options.pageToken);
273
-
274
- const response = await fetchWithAuth(
275
- `${storageBasePath}/list?${params.toString()}`
276
- );
277
-
278
- if (!response.ok) {
279
- const error = await response.json().catch(() => ({ error: "Failed to list files" }));
280
- throw new Error(error.error || "Failed to list files");
281
- }
282
-
283
- const result = await response.json();
284
- return result.data;
285
- }, [fetchWithAuth, storageBasePath]);
286
-
287
- // Return memoized StorageSource
288
- return useMemo<StorageSource>(() => ({
289
- putObject,
290
- getSignedUrl,
291
- getObject,
292
- deleteObject,
293
- listObjects
294
- }), [putObject, getSignedUrl, getObject, deleteObject, listObjects]);
295
- }
@@ -1,32 +0,0 @@
1
- import { useContext, useEffect } from "react";
2
- import type { StudioBridge } from "./useStudioBridge";
3
- import { StudioBridgeRegistryContext } from "./useStudioBridge";
4
-
5
- /**
6
- * Registers a value into the self-assembling Studio bridge.
7
- *
8
- * Each controller (collectionRegistry, sidePanel, url, navigation, breadcrumbs)
9
- * calls this hook on mount to inject its real implementation into the bridge.
10
- * On unmount the slice is automatically removed, reverting to the noop default.
11
- *
12
- * Usage:
13
- * ```tsx
14
- * function SomeProvider({ children }) {
15
- * const controller = useBuildSomeController();
16
- * useBridgeRegistration("sidePanelController", controller);
17
- * return <SomeContext.Provider value={controller}>{children}</SomeContext.Provider>;
18
- * }
19
- * ```
20
- */
21
- export function useBridgeRegistration<K extends keyof StudioBridge>(
22
- key: K,
23
- value: StudioBridge[K]
24
- ): void {
25
- const registry = useContext(StudioBridgeRegistryContext);
26
-
27
- useEffect(() => {
28
- if (!registry) return;
29
- registry.register(key, value);
30
- return () => registry.unregister(key);
31
- }, [registry, key, value]);
32
- }
@@ -1,23 +0,0 @@
1
- import { useEffect } from "react";
2
-
3
- const rebaseLogo = "data:image/png;base64,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";
4
-
5
- /**
6
- * Internal hook to handle the browser title and icon
7
- * @param name
8
- * @param logo
9
- */
10
- export function useBrowserTitleAndIcon(name: string, logo?: string) {
11
- useEffect(() => {
12
- if (document) {
13
- document.title = `${name} - Rebase`;
14
- let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null;
15
- if (!link) {
16
- link = document.createElement("link");
17
- link.rel = "icon";
18
- document.getElementsByTagName("head")[0].appendChild(link);
19
- }
20
- link.href = logo ?? rebaseLogo;
21
- }
22
- }, [name, logo]);
23
- }
@@ -1,29 +0,0 @@
1
- import { useCallback, useMemo, useState } from "react";
2
- import type { AdminModeController } from "./useAdminModeController";
3
- import { readStoredString, writeStoredString } from "../util/local_storage";
4
-
5
- /**
6
- * Use this hook to build an admin mode controller that determines
7
- * whether the UI shows Developer or Editor tools.
8
- */
9
- export function useBuildAdminModeController(): AdminModeController {
10
-
11
- // The content mode was renamed to "cms" when the panel's CMS half became a
12
- // product name. The value is persisted, so a browser that used the panel
13
- // before the rename still has "content" in local storage — read as-is it
14
- // casts to a mode nothing matches, and the drawer renders neither half.
15
- // Migrating on read is the exception the no-shims rule allows for stored data.
16
- const stored = readStoredString("rebase-admin-mode");
17
- const savedMode = (stored === "content" ? "cms" : stored) as "cms" | "studio" | "settings" | null;
18
- const [mode, setMode] = useState<"cms" | "studio" | "settings">(savedMode ?? "cms");
19
-
20
- const setModeInternal = useCallback((newMode: "cms" | "studio" | "settings") => {
21
- writeStoredString("rebase-admin-mode", newMode);
22
- setMode(newMode);
23
- }, []);
24
-
25
- return useMemo(() => ({
26
- mode,
27
- setMode: setModeInternal
28
- }), [mode, setModeInternal]);
29
- }
@@ -1,30 +0,0 @@
1
- import type { EffectiveRoleController } from "@rebasepro/types";
2
- import { useCallback, useState, useMemo } from "react";
3
- import { readStoredString, removeStoredString, writeStoredString } from "../util/local_storage";
4
- ;
5
-
6
- /**
7
- * Use this hook to build an effective role controller that determines
8
- * what role is simulated in Editor mode when Dev mode is active.
9
- *
10
- * It uses localStorage to persist the simulated role across reloads.
11
- */
12
- export function useBuildEffectiveRoleController(): EffectiveRoleController {
13
-
14
- const savedRole = readStoredString("rebase-effective-role");
15
- const [effectiveRole, setEffectiveRole] = useState<string | null>(savedRole ?? null);
16
-
17
- const setRoleInternal = useCallback((newRole: string | null) => {
18
- if (newRole) {
19
- writeStoredString("rebase-effective-role", newRole);
20
- } else {
21
- removeStoredString("rebase-effective-role");
22
- }
23
- setEffectiveRole(newRole);
24
- }, []);
25
-
26
- return useMemo(() => ({
27
- effectiveRole,
28
- setEffectiveRole: setRoleInternal
29
- }), [effectiveRole, setRoleInternal]);
30
- }