@rebasepro/studio 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{JSEditor-DSucz6wV.js → JSEditor-Sgmw1SHC.js} +28 -32
- package/dist/JSEditor-Sgmw1SHC.js.map +1 -0
- package/dist/{RLSEditor-BM64laoW.js → RLSEditor-DPhky8XW.js} +8 -18
- package/dist/RLSEditor-DPhky8XW.js.map +1 -0
- package/dist/{SQLEditor-CuAhR-zr.js → SQLEditor-CgR2hlUI.js} +5 -5
- package/dist/SQLEditor-CgR2hlUI.js.map +1 -0
- package/dist/{SchemaVisualizer-OibKoD3g.js → SchemaVisualizer-WK4ZZR5X.js} +9 -9
- package/dist/SchemaVisualizer-WK4ZZR5X.js.map +1 -0
- package/dist/{StorageView-CvrnHmDG.js → StorageView-BMhD29YO.js} +33 -5
- package/dist/StorageView-BMhD29YO.js.map +1 -0
- package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +110 -82
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +174 -133
- package/dist/index.umd.js.map +1 -1
- package/dist/utils/pgColumnToProperty.d.ts +3 -3
- package/dist/utils/sql_utils.d.ts +3 -3
- package/package.json +17 -17
- package/src/components/JSEditor/JSEditor.tsx +7 -7
- package/src/components/JSEditor/JSMonacoEditor.tsx +23 -27
- package/src/components/RLSEditor/RLSEditor.tsx +18 -31
- package/src/components/SQLEditor/SQLEditor.tsx +4 -4
- package/src/components/SchemaVisualizer/SchemaVisualizer.tsx +7 -7
- package/src/components/SchemaVisualizer/useSchemaGraph.ts +11 -11
- package/src/components/StorageView/StorageView.tsx +43 -4
- package/src/components/StudioHomePage.tsx +139 -84
- package/src/index.ts +1 -1
- package/src/utils/pgColumnToProperty.ts +4 -4
- package/src/utils/sql_utils.test.ts +6 -6
- package/src/utils/sql_utils.ts +3 -3
- package/dist/JSEditor-DSucz6wV.js.map +0 -1
- package/dist/RLSEditor-BM64laoW.js.map +0 -1
- package/dist/SQLEditor-CuAhR-zr.js.map +0 -1
- package/dist/SchemaVisualizer-OibKoD3g.js.map +0 -1
- package/dist/StorageView-CvrnHmDG.js.map +0 -1
- package/src/vite-env.d.ts +0 -1
package/dist/index.umd.js
CHANGED
|
@@ -60,8 +60,6 @@
|
|
|
60
60
|
var SECTIONS = [
|
|
61
61
|
{
|
|
62
62
|
label: "Database",
|
|
63
|
-
dotColor: "bg-emerald-400",
|
|
64
|
-
iconColor: "text-emerald-400",
|
|
65
63
|
tools: [
|
|
66
64
|
{
|
|
67
65
|
path: "/schema",
|
|
@@ -103,8 +101,6 @@
|
|
|
103
101
|
},
|
|
104
102
|
{
|
|
105
103
|
label: "Compute",
|
|
106
|
-
dotColor: "bg-blue-400",
|
|
107
|
-
iconColor: "text-blue-400",
|
|
108
104
|
tools: [{
|
|
109
105
|
path: "/js",
|
|
110
106
|
name: "JS Console",
|
|
@@ -119,8 +115,6 @@
|
|
|
119
115
|
},
|
|
120
116
|
{
|
|
121
117
|
label: "API",
|
|
122
|
-
dotColor: "bg-violet-400",
|
|
123
|
-
iconColor: "text-violet-400",
|
|
124
118
|
tools: [{
|
|
125
119
|
path: "/api",
|
|
126
120
|
name: "API Explorer",
|
|
@@ -130,8 +124,6 @@
|
|
|
130
124
|
},
|
|
131
125
|
{
|
|
132
126
|
label: "Storage",
|
|
133
|
-
dotColor: "bg-amber-400",
|
|
134
|
-
iconColor: "text-amber-400",
|
|
135
127
|
tools: [{
|
|
136
128
|
path: "/storage",
|
|
137
129
|
name: "Storage",
|
|
@@ -141,8 +133,6 @@
|
|
|
141
133
|
},
|
|
142
134
|
{
|
|
143
135
|
label: "Access Control",
|
|
144
|
-
dotColor: "bg-rose-400",
|
|
145
|
-
iconColor: "text-rose-400",
|
|
146
136
|
tools: [
|
|
147
137
|
{
|
|
148
138
|
path: "/users",
|
|
@@ -165,6 +155,33 @@
|
|
|
165
155
|
]
|
|
166
156
|
}
|
|
167
157
|
];
|
|
158
|
+
var COLLAPSED_STORAGE_KEY = "rebase-studio-home-collapsed";
|
|
159
|
+
function useStudioCollapsedGroups(groupNames) {
|
|
160
|
+
const [collapsed, setCollapsed] = (0, react.useState)(() => {
|
|
161
|
+
try {
|
|
162
|
+
const stored = localStorage.getItem(COLLAPSED_STORAGE_KEY);
|
|
163
|
+
return stored ? new Set(JSON.parse(stored)) : /* @__PURE__ */ new Set();
|
|
164
|
+
} catch {
|
|
165
|
+
return /* @__PURE__ */ new Set();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
const isGroupCollapsed = (name) => collapsed.has(name);
|
|
169
|
+
const toggleGroupCollapsed = (name) => {
|
|
170
|
+
setCollapsed((prev) => {
|
|
171
|
+
const next = new Set(prev);
|
|
172
|
+
if (next.has(name)) next.delete(name);
|
|
173
|
+
else next.add(name);
|
|
174
|
+
try {
|
|
175
|
+
localStorage.setItem(COLLAPSED_STORAGE_KEY, JSON.stringify([...next]));
|
|
176
|
+
} catch {}
|
|
177
|
+
return next;
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
isGroupCollapsed,
|
|
182
|
+
toggleGroupCollapsed
|
|
183
|
+
};
|
|
184
|
+
}
|
|
168
185
|
function StudioHomePage({ additionalActions, additionalChildrenStart, additionalChildrenEnd, sections, hiddenGroups }) {
|
|
169
186
|
const context = (0, _rebasepro_core.useRebaseContext)();
|
|
170
187
|
const breadcrumbs = (0, _rebasepro_core.useStudioBreadcrumbs)();
|
|
@@ -174,9 +191,11 @@
|
|
|
174
191
|
}, [breadcrumbs.set]);
|
|
175
192
|
const { containerRef } = (0, _rebasepro_core.useRestoreScroll)();
|
|
176
193
|
const pluginActions = (0, _rebasepro_core.useSlot)("home.actions", { context });
|
|
194
|
+
const filteredSections = (0, react.useMemo)(() => SECTIONS.filter((s) => !hiddenGroups?.includes(s.label)), [hiddenGroups]);
|
|
195
|
+
const { isGroupCollapsed, toggleGroupCollapsed } = useStudioCollapsedGroups((0, react.useMemo)(() => filteredSections.map((s) => s.label), [filteredSections]));
|
|
177
196
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
178
197
|
ref: containerRef,
|
|
179
|
-
className: "py-2 overflow-auto h-full w-full",
|
|
198
|
+
className: "py-2 overflow-auto h-full w-full bg-surface-50 dark:bg-surface-800",
|
|
180
199
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_rebasepro_ui.Container, {
|
|
181
200
|
maxWidth: "6xl",
|
|
182
201
|
children: [
|
|
@@ -189,68 +208,77 @@
|
|
|
189
208
|
children: [additionalActions, pluginActions]
|
|
190
209
|
}),
|
|
191
210
|
additionalChildrenStart,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
"
|
|
196
|
-
children:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
className: (0, _rebasepro_ui.cls)("
|
|
210
|
-
children:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
211
|
+
filteredSections.map((section) => {
|
|
212
|
+
const sectionCollapsed = isGroupCollapsed(section.label);
|
|
213
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
214
|
+
className: "my-10",
|
|
215
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.ExpandablePanel, {
|
|
216
|
+
invisible: true,
|
|
217
|
+
expanded: !sectionCollapsed,
|
|
218
|
+
onExpandedChange: (open) => {
|
|
219
|
+
if (open !== !sectionCollapsed) toggleGroupCollapsed(section.label);
|
|
220
|
+
},
|
|
221
|
+
className: "mt-6",
|
|
222
|
+
titleClassName: (0, _rebasepro_ui.cls)("min-h-0 p-0 border-none", "rounded flex items-center justify-between w-full", "hover:bg-transparent", "cursor-pointer select-none", sectionCollapsed && "bg-surface-100 dark:bg-surface-900/50"),
|
|
223
|
+
innerClassName: "mt-4 pt-0",
|
|
224
|
+
title: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Typography, {
|
|
225
|
+
variant: "caption",
|
|
226
|
+
component: "h2",
|
|
227
|
+
color: "secondary",
|
|
228
|
+
className: (0, _rebasepro_ui.cls)("px-4 py-1 rounded", "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"),
|
|
229
|
+
children: section.label
|
|
230
|
+
}),
|
|
231
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
232
|
+
className: "mt-4 pt-0",
|
|
233
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
234
|
+
className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
235
|
+
children: section.tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Card, {
|
|
236
|
+
onClick: () => {
|
|
237
|
+
navigate(tool.path);
|
|
238
|
+
context.analyticsController?.onAnalyticsEvent?.("home_navigate_to_view", { path: tool.path });
|
|
239
|
+
},
|
|
240
|
+
className: (0, _rebasepro_ui.cls)("group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out", "hover:bg-primary/5 dark:hover:bg-primary/5"),
|
|
241
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
242
|
+
className: "flex flex-col h-full",
|
|
243
|
+
children: [
|
|
244
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
245
|
+
className: "flex items-center w-full justify-between mb-1",
|
|
246
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
247
|
+
className: "flex items-center gap-3",
|
|
248
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
249
|
+
className: "flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500 transition-colors duration-150 group-hover:text-primary dark:group-hover:text-primary",
|
|
250
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_core.IconForView, {
|
|
251
|
+
collectionOrView: {
|
|
252
|
+
slug: tool.path,
|
|
253
|
+
name: tool.name,
|
|
254
|
+
icon: tool.icon
|
|
255
|
+
},
|
|
256
|
+
size: "small"
|
|
257
|
+
})
|
|
258
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Typography, {
|
|
259
|
+
variant: "subtitle1",
|
|
260
|
+
component: "h2",
|
|
261
|
+
children: tool.name
|
|
262
|
+
})]
|
|
263
|
+
})
|
|
264
|
+
}),
|
|
265
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
266
|
+
className: "pl-8",
|
|
267
|
+
children: tool.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Typography, {
|
|
268
|
+
variant: "caption",
|
|
269
|
+
color: "secondary",
|
|
270
|
+
component: "div",
|
|
271
|
+
children: tool.description
|
|
272
|
+
})
|
|
273
|
+
}),
|
|
274
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "grow" })
|
|
275
|
+
]
|
|
248
276
|
})
|
|
249
|
-
})
|
|
277
|
+
}, tool.path))
|
|
250
278
|
})
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
}, section.label)
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
}, section.label);
|
|
254
282
|
}),
|
|
255
283
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
256
284
|
className: "mt-10 mb-6",
|
|
@@ -261,7 +289,7 @@
|
|
|
261
289
|
variant: "caption",
|
|
262
290
|
component: "h2",
|
|
263
291
|
color: "secondary",
|
|
264
|
-
className: "py-
|
|
292
|
+
className: (0, _rebasepro_ui.cls)("px-4 py-1 rounded", "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"),
|
|
265
293
|
children: "Quick Start"
|
|
266
294
|
})
|
|
267
295
|
}),
|
|
@@ -314,7 +342,7 @@
|
|
|
314
342
|
variant: "caption",
|
|
315
343
|
component: "h2",
|
|
316
344
|
color: "secondary",
|
|
317
|
-
className: "
|
|
345
|
+
className: (0, _rebasepro_ui.cls)("px-4 py-1 rounded", "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"),
|
|
318
346
|
children: s.title
|
|
319
347
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
320
348
|
className: "mt-4",
|
|
@@ -1638,7 +1666,7 @@
|
|
|
1638
1666
|
};
|
|
1639
1667
|
SQLEditor$1 = () => {
|
|
1640
1668
|
const { databaseAdmin, client } = (0, _rebasepro_core.useRebaseContext)();
|
|
1641
|
-
const
|
|
1669
|
+
const sidePanelController = (0, _rebasepro_core.useStudioSidePanelController)();
|
|
1642
1670
|
const snackbarController = (0, _rebasepro_core.useSnackbarController)();
|
|
1643
1671
|
const collectionRegistry = (0, _rebasepro_core.useStudioCollectionRegistry)();
|
|
1644
1672
|
const { t } = (0, _rebasepro_core.useTranslation)();
|
|
@@ -2400,7 +2428,7 @@
|
|
|
2400
2428
|
className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300 transition-colors",
|
|
2401
2429
|
onClick: (e) => {
|
|
2402
2430
|
e.stopPropagation();
|
|
2403
|
-
|
|
2431
|
+
sidePanelController?.open({
|
|
2404
2432
|
path: ra.collection.collection.slug,
|
|
2405
2433
|
entityId: ra.entityId,
|
|
2406
2434
|
collection: ra.collection.collection,
|
|
@@ -2424,7 +2452,7 @@
|
|
|
2424
2452
|
children: rowActions.map((ra) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.MenuItem, {
|
|
2425
2453
|
dense: true,
|
|
2426
2454
|
onClick: () => {
|
|
2427
|
-
|
|
2455
|
+
sidePanelController?.open({
|
|
2428
2456
|
path: ra.collection.collection.slug,
|
|
2429
2457
|
entityId: ra.entityId,
|
|
2430
2458
|
collection: ra.collection.collection,
|
|
@@ -2839,11 +2867,7 @@
|
|
|
2839
2867
|
REBASE_CLIENT_TYPES = `
|
|
2840
2868
|
// ─── Rebase Client SDK Type Definitions ─────────────────────────────
|
|
2841
2869
|
|
|
2842
|
-
|
|
2843
|
-
id: string | number;
|
|
2844
|
-
path: string;
|
|
2845
|
-
values: M;
|
|
2846
|
-
}
|
|
2870
|
+
/** A flat database row with the id merged at the top level. */
|
|
2847
2871
|
|
|
2848
2872
|
interface FindParams {
|
|
2849
2873
|
limit?: number;
|
|
@@ -2855,8 +2879,8 @@ interface FindParams {
|
|
|
2855
2879
|
searchString?: string;
|
|
2856
2880
|
}
|
|
2857
2881
|
|
|
2858
|
-
interface
|
|
2859
|
-
data:
|
|
2882
|
+
interface FindResult<M extends Record<string, any> = any> {
|
|
2883
|
+
data: M[];
|
|
2860
2884
|
meta: {
|
|
2861
2885
|
total: number;
|
|
2862
2886
|
limit: number;
|
|
@@ -2865,63 +2889,63 @@ interface FindResponse<M extends Record<string, any> = any> {
|
|
|
2865
2889
|
};
|
|
2866
2890
|
}
|
|
2867
2891
|
|
|
2868
|
-
type
|
|
2892
|
+
type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "in" | "not-in" | "array-contains" | "array-contains-any";
|
|
2869
2893
|
|
|
2870
2894
|
interface QueryBuilder<M extends Record<string, any> = any> {
|
|
2871
|
-
where(column: keyof M & string, operator:
|
|
2895
|
+
where(column: keyof M & string, operator: WhereFilterOp, value: any): QueryBuilder<M>;
|
|
2872
2896
|
orderBy(column: keyof M & string, direction?: "asc" | "desc"): QueryBuilder<M>;
|
|
2873
2897
|
limit(count: number): QueryBuilder<M>;
|
|
2874
2898
|
offset(count: number): QueryBuilder<M>;
|
|
2875
2899
|
search(searchString: string): QueryBuilder<M>;
|
|
2876
|
-
find(): Promise<
|
|
2877
|
-
findOne(): Promise<Entity<M> | undefined>;
|
|
2900
|
+
find(): Promise<FindResult<M>>;
|
|
2878
2901
|
count(): Promise<number>;
|
|
2879
2902
|
}
|
|
2880
2903
|
|
|
2881
2904
|
interface CollectionClient<M extends Record<string, any> = any> {
|
|
2882
|
-
find(params?: FindParams): Promise<
|
|
2883
|
-
findById(id: string | number): Promise<
|
|
2884
|
-
create(data: Partial<M>, id?: string | number): Promise<
|
|
2885
|
-
update(id: string | number, data: Partial<M>): Promise<
|
|
2905
|
+
find(params?: FindParams): Promise<FindResult<M>>;
|
|
2906
|
+
findById(id: string | number): Promise<M | undefined>;
|
|
2907
|
+
create(data: Partial<M>, id?: string | number): Promise<M>;
|
|
2908
|
+
update(id: string | number, data: Partial<M>): Promise<M>;
|
|
2886
2909
|
delete(id: string | number): Promise<void>;
|
|
2887
|
-
where(column: keyof M & string, operator:
|
|
2910
|
+
where(column: keyof M & string, operator: WhereFilterOp, value: any): QueryBuilder<M>;
|
|
2888
2911
|
orderBy(column: keyof M & string, direction?: "asc" | "desc"): QueryBuilder<M>;
|
|
2889
2912
|
limit(count: number): QueryBuilder<M>;
|
|
2890
2913
|
offset(count: number): QueryBuilder<M>;
|
|
2891
2914
|
search(searchString: string): QueryBuilder<M>;
|
|
2892
|
-
listen?(params: FindParams | undefined, onUpdate: (response:
|
|
2893
|
-
listenById?(id: string | number, onUpdate: (
|
|
2915
|
+
listen?(params: FindParams | undefined, onUpdate: (response: FindResult<M>) => void, onError?: (error: Error) => void): () => void;
|
|
2916
|
+
listenById?(id: string | number, onUpdate: (row: M | undefined) => void, onError?: (error: Error) => void): () => void;
|
|
2894
2917
|
count?(params?: FindParams): Promise<number>;
|
|
2895
2918
|
}
|
|
2896
2919
|
|
|
2897
|
-
interface
|
|
2920
|
+
interface User {
|
|
2898
2921
|
uid: string;
|
|
2899
2922
|
email: string | null;
|
|
2900
2923
|
displayName: string | null;
|
|
2901
2924
|
photoURL: string | null;
|
|
2902
|
-
emailVerified?: boolean;
|
|
2903
|
-
roles?: string[];
|
|
2904
2925
|
providerId: string;
|
|
2905
2926
|
isAnonymous: boolean;
|
|
2927
|
+
emailVerified?: boolean;
|
|
2928
|
+
roles?: string[];
|
|
2929
|
+
metadata?: Record<string, unknown>;
|
|
2906
2930
|
}
|
|
2907
2931
|
|
|
2908
2932
|
interface RebaseSession {
|
|
2909
2933
|
accessToken: string;
|
|
2910
2934
|
refreshToken: string;
|
|
2911
2935
|
expiresAt: number;
|
|
2912
|
-
user:
|
|
2936
|
+
user: User;
|
|
2913
2937
|
}
|
|
2914
2938
|
|
|
2915
2939
|
type AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';
|
|
2916
2940
|
|
|
2917
2941
|
interface RebaseAuth {
|
|
2918
|
-
signInWithEmail(email: string, password: string): Promise<{ user:
|
|
2919
|
-
signUp(email: string, password: string, displayName?: string): Promise<{ user:
|
|
2920
|
-
signInWithGoogle(idToken: string): Promise<{ user:
|
|
2942
|
+
signInWithEmail(email: string, password: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;
|
|
2943
|
+
signUp(email: string, password: string, displayName?: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;
|
|
2944
|
+
signInWithGoogle(idToken: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;
|
|
2921
2945
|
signOut(): Promise<void>;
|
|
2922
2946
|
refreshSession(): Promise<RebaseSession>;
|
|
2923
|
-
getUser(): Promise<
|
|
2924
|
-
updateUser(updates: { displayName?: string; photoURL?: string }): Promise<
|
|
2947
|
+
getUser(): Promise<User>;
|
|
2948
|
+
updateUser(updates: { displayName?: string; photoURL?: string }): Promise<User>;
|
|
2925
2949
|
resetPasswordForEmail(email: string): Promise<{ success: boolean; message: string }>;
|
|
2926
2950
|
resetPassword(token: string, password: string): Promise<{ success: boolean; message: string }>;
|
|
2927
2951
|
changePassword(oldPassword: string, newPassword: string): Promise<{ success: boolean; message: string }>;
|
|
@@ -3611,7 +3635,7 @@ declare const context: JSEditorContext;
|
|
|
3611
3635
|
const apiConfig = (0, _rebasepro_core.useApiConfig)();
|
|
3612
3636
|
const snackbar = (0, _rebasepro_core.useSnackbarController)();
|
|
3613
3637
|
const collectionRegistry = (0, _rebasepro_core.useStudioCollectionRegistry)();
|
|
3614
|
-
const
|
|
3638
|
+
const sidePanelController = (0, _rebasepro_core.useStudioSidePanelController)();
|
|
3615
3639
|
const { t } = (0, _rebasepro_core.useTranslation)();
|
|
3616
3640
|
const currentUser = rebaseContext.authController?.user;
|
|
3617
3641
|
const [tabs, setTabs] = (0, react.useState)(() => loadFromStorage("tabs", [{
|
|
@@ -4246,7 +4270,7 @@ declare const context: JSEditorContext;
|
|
|
4246
4270
|
className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
|
|
4247
4271
|
onClick: (e) => {
|
|
4248
4272
|
e.stopPropagation();
|
|
4249
|
-
|
|
4273
|
+
sidePanelController.open({
|
|
4250
4274
|
path: ra.collection.collectionSlug,
|
|
4251
4275
|
entityId: ra.entityId,
|
|
4252
4276
|
collection: ra.collection.collection,
|
|
@@ -4270,7 +4294,7 @@ declare const context: JSEditorContext;
|
|
|
4270
4294
|
children: rowActions.map((ra) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.MenuItem, {
|
|
4271
4295
|
dense: true,
|
|
4272
4296
|
onClick: () => {
|
|
4273
|
-
|
|
4297
|
+
sidePanelController.open({
|
|
4274
4298
|
path: ra.collection.collectionSlug,
|
|
4275
4299
|
entityId: ra.entityId,
|
|
4276
4300
|
collection: ra.collection.collection,
|
|
@@ -5296,28 +5320,18 @@ return result;
|
|
|
5296
5320
|
status: "live"
|
|
5297
5321
|
};
|
|
5298
5322
|
});
|
|
5299
|
-
if (activeCollection && (0, _rebasepro_types.
|
|
5323
|
+
if (activeCollection && (0, _rebasepro_types.isPostgresCollectionConfig)(activeCollection) && activeCollection.securityRules) activeCollection.securityRules.forEach((rule) => {
|
|
5300
5324
|
const ruleName = rule.name;
|
|
5301
5325
|
if (!ruleName) return;
|
|
5302
|
-
|
|
5303
|
-
policyname: ruleName,
|
|
5304
|
-
tablename: activeTableData.tableName,
|
|
5305
|
-
permissive: (rule.mode || "permissive").toUpperCase(),
|
|
5306
|
-
cmd: (rule.operation || "ALL").toUpperCase(),
|
|
5307
|
-
roles: rule.roles || ["public"],
|
|
5308
|
-
qual: rule.using || null,
|
|
5309
|
-
with_check: rule.withCheck || null,
|
|
5310
|
-
status: "both"
|
|
5311
|
-
};
|
|
5312
|
-
else policiesMap[ruleName] = {
|
|
5326
|
+
policiesMap[ruleName] = {
|
|
5313
5327
|
policyname: ruleName,
|
|
5314
5328
|
tablename: activeTableData.tableName,
|
|
5315
5329
|
permissive: (rule.mode || "permissive").toUpperCase(),
|
|
5316
5330
|
cmd: (rule.operation || "ALL").toUpperCase(),
|
|
5317
|
-
roles: rule.roles
|
|
5331
|
+
roles: [...rule.roles ?? ["public"]],
|
|
5318
5332
|
qual: rule.using || null,
|
|
5319
5333
|
with_check: rule.withCheck || null,
|
|
5320
|
-
status: "code_only"
|
|
5334
|
+
status: policiesMap[ruleName] ? "both" : "code_only"
|
|
5321
5335
|
};
|
|
5322
5336
|
});
|
|
5323
5337
|
return Object.values(policiesMap).sort((a, b) => a.policyname.localeCompare(b.policyname));
|
|
@@ -5698,7 +5712,7 @@ return result;
|
|
|
5698
5712
|
withCheck: newPolicy.with_check || void 0,
|
|
5699
5713
|
roles: newPolicy.roles
|
|
5700
5714
|
};
|
|
5701
|
-
const existingRules = ((0, _rebasepro_types.
|
|
5715
|
+
const existingRules = ((0, _rebasepro_types.isPostgresCollectionConfig)(activeCollection) ? activeCollection.securityRules : void 0) || [];
|
|
5702
5716
|
let newRules;
|
|
5703
5717
|
if (editingPolicy === "new") newRules = [...existingRules, rule];
|
|
5704
5718
|
else newRules = existingRules.map((r) => r.name === editingPolicy.policyname ? rule : r);
|
|
@@ -5895,7 +5909,7 @@ return result;
|
|
|
5895
5909
|
withCheck: policy.with_check || void 0,
|
|
5896
5910
|
roles: policy.roles
|
|
5897
5911
|
};
|
|
5898
|
-
const newRules = [...((0, _rebasepro_types.
|
|
5912
|
+
const newRules = [...((0, _rebasepro_types.isPostgresCollectionConfig)(activeCollection) ? activeCollection.securityRules : void 0) || [], rule];
|
|
5899
5913
|
try {
|
|
5900
5914
|
if (!(await fetch(`${apiUrl}/api/schema-editor/collection/save`, {
|
|
5901
5915
|
method: "POST",
|
|
@@ -6418,8 +6432,16 @@ return result;
|
|
|
6418
6432
|
var StorageView$1;
|
|
6419
6433
|
var init_StorageView = __esmMin((() => {
|
|
6420
6434
|
StorageView$1 = () => {
|
|
6421
|
-
const
|
|
6435
|
+
const defaultStorageSource = (0, _rebasepro_core.useStorageSource)();
|
|
6436
|
+
const storageSources = (0, _rebasepro_core.useStorageSources)();
|
|
6422
6437
|
const snackbarController = (0, _rebasepro_core.useSnackbarController)();
|
|
6438
|
+
const sourceKeys = (0, react.useMemo)(() => {
|
|
6439
|
+
const keys = Object.keys(storageSources.sources);
|
|
6440
|
+
if (!keys.includes(_rebasepro_types.DEFAULT_STORAGE_SOURCE_KEY)) keys.unshift(_rebasepro_types.DEFAULT_STORAGE_SOURCE_KEY);
|
|
6441
|
+
return keys;
|
|
6442
|
+
}, [storageSources.sources]);
|
|
6443
|
+
const [selectedSourceKey, setSelectedSourceKey] = (0, react.useState)(_rebasepro_types.DEFAULT_STORAGE_SOURCE_KEY);
|
|
6444
|
+
const storageSource = storageSources.sources[selectedSourceKey] ?? defaultStorageSource;
|
|
6423
6445
|
const [searchParams, setSearchParams] = (0, react_router_dom.useSearchParams)();
|
|
6424
6446
|
const currentPath = searchParams.get("path") || "";
|
|
6425
6447
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
@@ -6483,7 +6505,11 @@ return result;
|
|
|
6483
6505
|
}, []);
|
|
6484
6506
|
(0, react.useEffect)(() => {
|
|
6485
6507
|
fetchContents(currentPath);
|
|
6486
|
-
}, [
|
|
6508
|
+
}, [
|
|
6509
|
+
currentPath,
|
|
6510
|
+
fetchContents,
|
|
6511
|
+
selectedSourceKey
|
|
6512
|
+
]);
|
|
6487
6513
|
const handleNavigate = (0, react.useCallback)((path) => {
|
|
6488
6514
|
if (!path) setSearchParams({});
|
|
6489
6515
|
else setSearchParams({ path });
|
|
@@ -7163,6 +7189,21 @@ return result;
|
|
|
7163
7189
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7164
7190
|
className: "flex shrink-0 items-center justify-end gap-1.5 pr-1",
|
|
7165
7191
|
children: [
|
|
7192
|
+
sourceKeys.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Select, {
|
|
7193
|
+
size: "small",
|
|
7194
|
+
position: "item-aligned",
|
|
7195
|
+
value: selectedSourceKey,
|
|
7196
|
+
onValueChange: (value) => {
|
|
7197
|
+
if (value) setSelectedSourceKey(value);
|
|
7198
|
+
},
|
|
7199
|
+
renderValue: (key) => {
|
|
7200
|
+
return storageSources.registry[key]?.label ?? (key === _rebasepro_types.DEFAULT_STORAGE_SOURCE_KEY ? "Default" : key);
|
|
7201
|
+
},
|
|
7202
|
+
children: sourceKeys.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.SelectItem, {
|
|
7203
|
+
value: key,
|
|
7204
|
+
children: storageSources.registry[key]?.label ?? (key === _rebasepro_types.DEFAULT_STORAGE_SOURCE_KEY ? "Default" : key)
|
|
7205
|
+
}, key))
|
|
7206
|
+
}),
|
|
7166
7207
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Tooltip, {
|
|
7167
7208
|
title: "Grid view",
|
|
7168
7209
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.IconButton, {
|
|
@@ -8000,7 +8041,7 @@ return result;
|
|
|
8000
8041
|
enumValues
|
|
8001
8042
|
});
|
|
8002
8043
|
}
|
|
8003
|
-
if ((0, _rebasepro_types.
|
|
8044
|
+
if ((0, _rebasepro_types.isPostgresCollectionConfig)(collection)) try {
|
|
8004
8045
|
const resolvedRelations = (0, _rebasepro_common.resolveCollectionRelations)(collection);
|
|
8005
8046
|
for (const rel of Object.values(resolvedRelations)) if (rel.direction === "owning" && rel.cardinality === "one" && rel.localKey) if (!columns.some((c) => c.name === rel.localKey)) columns.push({
|
|
8006
8047
|
name: rel.localKey,
|
|
@@ -8037,7 +8078,7 @@ return result;
|
|
|
8037
8078
|
return fk ? `source-${fk.name}` : "source-default";
|
|
8038
8079
|
};
|
|
8039
8080
|
for (const collection of collections) {
|
|
8040
|
-
if (!(0, _rebasepro_types.
|
|
8081
|
+
if (!(0, _rebasepro_types.isPostgresCollectionConfig)(collection)) continue;
|
|
8041
8082
|
const tableName = collection.table ?? collection.slug;
|
|
8042
8083
|
const nodeId = `table-${tableName}`;
|
|
8043
8084
|
tableToNodeId.set(tableName, nodeId);
|
|
@@ -8066,7 +8107,7 @@ return result;
|
|
|
8066
8107
|
}
|
|
8067
8108
|
const processedJunctions = /* @__PURE__ */ new Set();
|
|
8068
8109
|
for (const collection of collections) {
|
|
8069
|
-
if (!(0, _rebasepro_types.
|
|
8110
|
+
if (!(0, _rebasepro_types.isPostgresCollectionConfig)(collection)) continue;
|
|
8070
8111
|
const tableName = collection.table ?? collection.slug;
|
|
8071
8112
|
const sourceNodeId = tableToNodeId.get(tableName);
|
|
8072
8113
|
if (!sourceNodeId) continue;
|
|
@@ -8083,7 +8124,7 @@ return result;
|
|
|
8083
8124
|
} catch {
|
|
8084
8125
|
continue;
|
|
8085
8126
|
}
|
|
8086
|
-
if (!(0, _rebasepro_types.
|
|
8127
|
+
if (!(0, _rebasepro_types.isPostgresCollectionConfig)(targetCollection)) continue;
|
|
8087
8128
|
const targetTable = targetCollection.table ?? targetCollection.slug;
|
|
8088
8129
|
const targetNodeId = tableToNodeId.get(targetTable);
|
|
8089
8130
|
if (!targetNodeId) continue;
|
|
@@ -8556,7 +8597,7 @@ return result;
|
|
|
8556
8597
|
localStorage.setItem("rebase_schema_viz_sidebar_size", sidebarSize.toString());
|
|
8557
8598
|
} catch {}
|
|
8558
8599
|
}, [sidebarSize]);
|
|
8559
|
-
const postgresCollections = (0, react.useMemo)(() => collections.filter(_rebasepro_types.
|
|
8600
|
+
const postgresCollections = (0, react.useMemo)(() => collections.filter(_rebasepro_types.isPostgresCollectionConfig), [collections]);
|
|
8560
8601
|
const filteredCollections = (0, react.useMemo)(() => {
|
|
8561
8602
|
if (!searchQuery.trim()) return postgresCollections;
|
|
8562
8603
|
const q = searchQuery.toLowerCase();
|
|
@@ -8567,7 +8608,7 @@ return result;
|
|
|
8567
8608
|
tables: tableCount,
|
|
8568
8609
|
relations: relationCount,
|
|
8569
8610
|
junctions: junctionNodes.length,
|
|
8570
|
-
withRls: postgresCollections.filter((c) => (0, _rebasepro_types.
|
|
8611
|
+
withRls: postgresCollections.filter((c) => (0, _rebasepro_types.isPostgresCollectionConfig)(c) && c.securityRules && c.securityRules.length > 0).length
|
|
8571
8612
|
}), [
|
|
8572
8613
|
tableCount,
|
|
8573
8614
|
relationCount,
|
|
@@ -8639,7 +8680,7 @@ return result;
|
|
|
8639
8680
|
}),
|
|
8640
8681
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8641
8682
|
className: "flex items-center gap-1 shrink-0 ml-1",
|
|
8642
|
-
children: [(0, _rebasepro_types.
|
|
8683
|
+
children: [(0, _rebasepro_types.isPostgresCollectionConfig)(collection) && collection.securityRules && collection.securityRules.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Tooltip, {
|
|
8643
8684
|
title: "RLS enabled",
|
|
8644
8685
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500" })
|
|
8645
8686
|
}), collection.history && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_rebasepro_ui.Tooltip, {
|
|
@@ -11419,10 +11460,10 @@ return result;
|
|
|
11419
11460
|
return _rebasepro_core.useStudioNavigationState;
|
|
11420
11461
|
}
|
|
11421
11462
|
});
|
|
11422
|
-
Object.defineProperty(exports, "
|
|
11463
|
+
Object.defineProperty(exports, "useStudioSidePanelController", {
|
|
11423
11464
|
enumerable: true,
|
|
11424
11465
|
get: function() {
|
|
11425
|
-
return _rebasepro_core.
|
|
11466
|
+
return _rebasepro_core.useStudioSidePanelController;
|
|
11426
11467
|
}
|
|
11427
11468
|
});
|
|
11428
11469
|
Object.defineProperty(exports, "useStudioUrlController", {
|