@rebasepro/studio 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 (81) hide show
  1. package/LICENSE +0 -1
  2. package/README.md +12 -4
  3. package/dist/{ApiKeysView-DiCurTEU.js → ApiKeysView-EIvegrUk.js} +54 -39
  4. package/dist/ApiKeysView-EIvegrUk.js.map +1 -0
  5. package/dist/{BackupsView-DNS6LdVg.js → BackupsView-DVkKzaPR.js} +29 -31
  6. package/dist/BackupsView-DVkKzaPR.js.map +1 -0
  7. package/dist/{BranchesView-CM3B-ER3.js → BranchesView-Df8hQ8wE.js} +85 -24
  8. package/dist/BranchesView-Df8hQ8wE.js.map +1 -0
  9. package/dist/{CronJobsView-BHtJZeJZ.js → CronJobsView-CLOGjb-L.js} +32 -27
  10. package/dist/CronJobsView-CLOGjb-L.js.map +1 -0
  11. package/dist/{RLSEditor-CBX4uD66.js → RLSEditor-Sa1D34ny.js} +724 -615
  12. package/dist/RLSEditor-Sa1D34ny.js.map +1 -0
  13. package/dist/{SQLEditor-ByecwX8B.js → SQLEditor-BfNA8xM3.js} +9 -4
  14. package/dist/{SQLEditor-ByecwX8B.js.map → SQLEditor-BfNA8xM3.js.map} +1 -1
  15. package/dist/{SchemaVisualizer-D6tMZgeC.js → SchemaVisualizer-DTDMYL6o.js} +84 -110
  16. package/dist/SchemaVisualizer-DTDMYL6o.js.map +1 -0
  17. package/dist/{StorageView-BGDeC5GI.js → StorageView-Ed9Q_VlB.js} +5 -32
  18. package/dist/StorageView-Ed9Q_VlB.js.map +1 -0
  19. package/dist/components/RLSEditor/saveRules.d.ts +38 -0
  20. package/dist/components/RebaseStudio.d.ts +1 -1
  21. package/dist/components/SchemaVisualizer/schema-visualizer.utils.d.ts +5 -2
  22. package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +0 -4
  23. package/dist/components/load-failure-view.d.ts +17 -0
  24. package/dist/components/load-failure.d.ts +47 -0
  25. package/dist/index.es.js +56 -36
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/load-failure-C6OMJSGC.js +31 -0
  28. package/dist/load-failure-C6OMJSGC.js.map +1 -0
  29. package/dist/load-failure-view-CBTB_h-h.js +48 -0
  30. package/dist/load-failure-view-CBTB_h-h.js.map +1 -0
  31. package/package.json +36 -21
  32. package/dist/ApiKeysView-DiCurTEU.js.map +0 -1
  33. package/dist/BackupsView-DNS6LdVg.js.map +0 -1
  34. package/dist/BranchesView-CM3B-ER3.js.map +0 -1
  35. package/dist/CronJobsView-BHtJZeJZ.js.map +0 -1
  36. package/dist/RLSEditor-CBX4uD66.js.map +0 -1
  37. package/dist/SchemaVisualizer-D6tMZgeC.js.map +0 -1
  38. package/dist/StorageView-BGDeC5GI.js.map +0 -1
  39. package/dist/components/StorageView/storage-failure.d.ts +0 -34
  40. package/src/components/ApiExplorer/ApiExplorer.tsx +0 -299
  41. package/src/components/ApiExplorer/EndpointDetail.tsx +0 -279
  42. package/src/components/ApiExplorer/TryItPanel.tsx +0 -499
  43. package/src/components/ApiExplorer/parseSpec.ts +0 -104
  44. package/src/components/ApiExplorer/types.ts +0 -84
  45. package/src/components/ApiKeys/ApiKeysView.tsx +0 -479
  46. package/src/components/ApiKeys/CreateApiKeyDialog.tsx +0 -711
  47. package/src/components/ApiKeys/permissions.ts +0 -145
  48. package/src/components/AuthSimulationSelector.tsx +0 -72
  49. package/src/components/Backups/BackupsView.tsx +0 -185
  50. package/src/components/Branches/BranchesView.tsx +0 -386
  51. package/src/components/CronJobs/CronJobsView.tsx +0 -413
  52. package/src/components/JSEditor/JSEditor.tsx +0 -1100
  53. package/src/components/JSEditor/JSEditorSidebar.tsx +0 -350
  54. package/src/components/JSEditor/JSMonacoEditor.tsx +0 -410
  55. package/src/components/LogsExplorer/LogsExplorer.tsx +0 -273
  56. package/src/components/LogsExplorer/useLogTail.ts +0 -356
  57. package/src/components/RLSEditor/PolicyEditor.tsx +0 -399
  58. package/src/components/RLSEditor/RLSEditor.tsx +0 -1128
  59. package/src/components/RLSEditor/index.ts +0 -1
  60. package/src/components/RLSEditor/policy-presets.ts +0 -176
  61. package/src/components/RLSEditor/saveSecurityRules.ts +0 -48
  62. package/src/components/RebaseStudio.tsx +0 -174
  63. package/src/components/SQLEditor/ExplainVisualizer.tsx +0 -128
  64. package/src/components/SQLEditor/MonacoEditor.tsx +0 -203
  65. package/src/components/SQLEditor/SQLEditor.tsx +0 -1518
  66. package/src/components/SQLEditor/SQLEditorSidebar.tsx +0 -173
  67. package/src/components/SQLEditor/SchemaBrowser.tsx +0 -168
  68. package/src/components/SQLEditor/sql_editor_types.ts +0 -18
  69. package/src/components/SchemaVisualizer/RelationEdge.tsx +0 -102
  70. package/src/components/SchemaVisualizer/SchemaVisualizer.tsx +0 -710
  71. package/src/components/SchemaVisualizer/TableNode.tsx +0 -257
  72. package/src/components/SchemaVisualizer/schema-visualizer.utils.ts +0 -140
  73. package/src/components/SchemaVisualizer/useLiveRls.ts +0 -86
  74. package/src/components/SchemaVisualizer/useSchemaGraph.ts +0 -426
  75. package/src/components/StorageView/StorageView.tsx +0 -1588
  76. package/src/components/StorageView/storage-failure.ts +0 -63
  77. package/src/components/StudioHomePage.tsx +0 -430
  78. package/src/index.ts +0 -31
  79. package/src/utils/parseSpec.test.ts +0 -309
  80. package/src/utils/sql_utils.test.ts +0 -265
  81. package/src/utils/sql_utils.ts +0 -291
@@ -1,63 +0,0 @@
1
- /**
2
- * Why a storage listing failed — and whether it is the platform's fault.
3
- *
4
- * ## Why this is a function
5
- *
6
- * The pane rendered one view for every failure: a red card titled **"Error
7
- * loading storage"** with whatever string came back underneath.
8
- *
9
- * On 2026-08-27 a customer opened the Files tab of a healthy project and read
10
- * "Error loading storage — Not authorized for this object". Nothing was broken.
11
- * That project's own `storageAuthorize` hook refuses an unscoped listing on
12
- * purpose — its comment says a `list` that is not scoped to a team "is precisely
13
- * the enumeration this exists to stop" — and the Files tab always opens at the
14
- * bucket root. The console took a policy working exactly as written and
15
- * presented it as a fault in the platform, which sends the reader hunting for a
16
- * problem that does not exist.
17
- *
18
- * A refusal and a failure need different words, a different colour, and a
19
- * different next step: one is "your rule said no", the other is "we could not
20
- * ask". Retry is an affordance for the second and noise on the first.
21
- */
22
-
23
- export type StorageFailureKind =
24
- /** The project's own authorize hook said no. Not an error. */
25
- | "denied"
26
- /** We could not reach or read the store. */
27
- | "unavailable";
28
-
29
- export interface StorageFailure {
30
- kind: StorageFailureKind;
31
- /** The message as the server gave it, never re-worded. */
32
- detail: string;
33
- /** Offering retry against a standing policy teaches people the button does nothing. */
34
- retryable: boolean;
35
- }
36
-
37
- /** HTTP status carried by whatever the SDK threw, if it carries one. */
38
- function statusOf(err: unknown): number | null {
39
- if (typeof err !== "object" || err === null) return null;
40
- for (const key of ["status", "statusCode", "code"]) {
41
- const v = (err as Record<string, unknown>)[key];
42
- if (typeof v === "number" && v >= 100 && v < 600) return v;
43
- }
44
- return null;
45
- }
46
-
47
- export function classifyStorageFailure(err: unknown): StorageFailure {
48
- const detail = err instanceof Error ? err.message : String(err);
49
- const status = statusOf(err);
50
-
51
- // 403 is the hook's answer; 401 means the caller is not signed in as anyone
52
- // the hook can evaluate, which is the same conversation from the other end.
53
- // The message match is the fallback, because an SDK that flattens an error
54
- // to a string is exactly how this reached the screen unclassified.
55
- const denied =
56
- status === 403 ||
57
- status === 401 ||
58
- /\bnot authori[sz]ed\b|\bforbidden\b|\bpermission denied\b/i.test(detail);
59
-
60
- return denied
61
- ? { kind: "denied", detail, retryable: false }
62
- : { kind: "unavailable", detail, retryable: true };
63
- }
@@ -1,430 +0,0 @@
1
- import type { AppView, HomePageSection, PluginGenericProps } from "@rebasepro/cms-types";
2
- import React, { useEffect, useMemo, useState } from "react";
3
- import { Card, cls, Container, ExpandablePanel, Typography } from "@rebasepro/ui";
4
- import { IconForView, useRebaseContext, useRebaseRegistry, useRestoreScroll, useSlot } from "@rebasepro/app";
5
- import { useNavigate } from "react-router";
6
- import { useStudioBreadcrumbs, SchemaDriftBanner } from "@rebasepro/app";
7
-
8
- /* ═══════════════════════════════════════════════════════════════
9
- Studio tool sections, derived from the registered Studio views
10
- ═══════════════════════════════════════════════════════════════ */
11
-
12
- interface StudioTool {
13
- path: string;
14
- name: string;
15
- description: string;
16
- icon?: string | React.ReactNode;
17
- }
18
-
19
- interface StudioSection {
20
- label: string;
21
- tools: StudioTool[];
22
- }
23
-
24
- /** The view metadata the cards need — not the rendered `view` itself. */
25
- type StudioViewMeta = Pick<AppView, "slug" | "name" | "group" | "description" | "icon" | "hideFromNavigation">;
26
-
27
- /** Group order for the home page; unknown groups are appended in view order. */
28
- const GROUP_ORDER = ["Database", "Compute", "Storage", "API", "Access Control"];
29
-
30
- const UNGROUPED_LABEL = "Tools";
31
-
32
- /**
33
- * Build the home page sections from the Studio views that are actually
34
- * registered, so a card exists if and only if its route does. A hand-written
35
- * list drifts: it used to advertise Users and Roles pages that 404, while
36
- * omitting the Backups view that does exist.
37
- */
38
- function buildSections(views: StudioViewMeta[]): StudioSection[] {
39
- const byGroup = new Map<string, StudioTool[]>();
40
-
41
- for (const view of views) {
42
- if (view.hideFromNavigation) continue;
43
- const label = view.group ?? UNGROUPED_LABEL;
44
- const tools = byGroup.get(label) ?? [];
45
- tools.push({
46
- path: `/${view.slug}`,
47
- name: view.name,
48
- description: view.description ?? "",
49
- icon: view.icon
50
- });
51
- byGroup.set(label, tools);
52
- }
53
-
54
- const ordered = [
55
- ...GROUP_ORDER.filter(g => byGroup.has(g)),
56
- ...[...byGroup.keys()].filter(g => !GROUP_ORDER.includes(g))
57
- ];
58
-
59
- return ordered.map(label => ({ label,
60
- tools: byGroup.get(label)! }));
61
- }
62
-
63
- /* ═══════════════════════════════════════════════════════════════ */
64
-
65
- const COLLAPSED_STORAGE_KEY = "rebase-studio-home-collapsed";
66
-
67
- function useStudioCollapsedGroups(groupNames: string[]) {
68
- const [collapsed, setCollapsed] = useState<Set<string>>(() => {
69
- try {
70
- const stored = localStorage.getItem(COLLAPSED_STORAGE_KEY);
71
- return stored ? new Set(JSON.parse(stored)) : new Set<string>();
72
- } catch {
73
- return new Set<string>();
74
- }
75
- });
76
-
77
- const isGroupCollapsed = (name: string) => collapsed.has(name);
78
-
79
- const toggleGroupCollapsed = (name: string) => {
80
- setCollapsed(prev => {
81
- const next = new Set(prev);
82
- if (next.has(name)) {
83
- next.delete(name);
84
- } else {
85
- next.add(name);
86
- }
87
- try {
88
- localStorage.setItem(COLLAPSED_STORAGE_KEY, JSON.stringify([...next]));
89
- } catch { /* noop */ }
90
- return next;
91
- });
92
- };
93
-
94
- return { isGroupCollapsed, toggleGroupCollapsed };
95
- }
96
-
97
- export function StudioHomePage({
98
- additionalActions,
99
- additionalChildrenStart,
100
- additionalChildrenEnd,
101
- sections,
102
- hiddenGroups
103
- }: {
104
- additionalActions?: React.ReactNode;
105
- additionalChildrenStart?: React.ReactNode;
106
- additionalChildrenEnd?: React.ReactNode;
107
- sections?: HomePageSection[];
108
- hiddenGroups?: string[];
109
- }) {
110
- const context = useRebaseContext();
111
- const breadcrumbs = useStudioBreadcrumbs();
112
- const navigate = useNavigate();
113
- const registry = useRebaseRegistry();
114
-
115
- useEffect(() => {
116
- breadcrumbs.set({ breadcrumbs: [] });
117
- }, [breadcrumbs.set]);
118
-
119
- const { containerRef } = useRestoreScroll();
120
-
121
- const sectionProps: PluginGenericProps = { context };
122
-
123
- const pluginActions = useSlot("home.actions", sectionProps);
124
-
125
- // The collection editor ("schema") is not part of `devViews` — RebaseNavigation
126
- // injects it when the admin enables a collection editor. Mirror that condition so
127
- // the card tracks the route.
128
- const schemaEnabled = Boolean(registry.studioConfig && registry.cmsConfig?.collectionEditor);
129
-
130
- const filteredSections = useMemo(() => {
131
- const views: StudioViewMeta[] = [];
132
- if (schemaEnabled) {
133
- views.push({
134
- slug: "schema",
135
- name: "Collections",
136
- group: "Database",
137
- icon: "LayoutList",
138
- description: "Define and manage your data model and collection schemas"
139
- });
140
- }
141
- views.push(...(registry.studioConfig?.devViews ?? []));
142
- return buildSections(views).filter(s => !hiddenGroups?.includes(s.label));
143
- }, [registry.studioConfig?.devViews, schemaEnabled, hiddenGroups]);
144
-
145
- const groupNames = useMemo(
146
- () => filteredSections.map(s => s.label),
147
- [filteredSections]
148
- );
149
-
150
- const { isGroupCollapsed, toggleGroupCollapsed } = useStudioCollapsedGroups(groupNames);
151
-
152
- return (
153
- <div ref={containerRef} className="py-2 overflow-auto h-full w-full bg-surface-50 dark:bg-surface-800">
154
- <Container maxWidth="6xl">
155
- <div className="mb-4 flex flex-col gap-2">
156
- <SchemaDriftBanner />
157
- </div>
158
-
159
- {(additionalActions || pluginActions) && (
160
- <div className="w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4 justify-end">
161
- {additionalActions}
162
- {pluginActions}
163
- </div>
164
- )}
165
-
166
- {additionalChildrenStart}
167
-
168
- {/* ── Tool sections ── */}
169
- {filteredSections.map((section) => {
170
- const sectionCollapsed = isGroupCollapsed(section.label);
171
-
172
- return (
173
- <div key={section.label} className="my-10">
174
- <ExpandablePanel
175
- invisible
176
- expanded={!sectionCollapsed}
177
- onExpandedChange={(open) => {
178
- if (open !== !sectionCollapsed) {
179
- toggleGroupCollapsed(section.label);
180
- }
181
- }}
182
- className="mt-6"
183
- titleClassName={cls(
184
- "min-h-0 p-0 border-none",
185
- "rounded flex items-center justify-between w-full",
186
- "hover:bg-transparent",
187
- "cursor-pointer select-none",
188
- sectionCollapsed && "bg-surface-100 dark:bg-surface-900/50"
189
- )}
190
- innerClassName="mt-4 pt-0"
191
- title={
192
- <Typography
193
- variant="caption"
194
- component="h2"
195
- color="secondary"
196
- className={cls(
197
- "px-4 py-1 rounded",
198
- "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"
199
- )}
200
- >
201
- {section.label}
202
- </Typography>
203
- }
204
- >
205
- <div className="mt-4 pt-0">
206
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
207
- {section.tools.map((tool) => (
208
- <Card
209
- key={tool.path}
210
- onClick={() => {
211
- navigate(tool.path);
212
- context.analyticsController?.onAnalyticsEvent?.(
213
- "home_navigate_to_view",
214
- { path: tool.path }
215
- );
216
- }}
217
- className={cls(
218
- "group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out",
219
- "hover:bg-primary/5 dark:hover:bg-primary/5"
220
- )}
221
- >
222
- <div className="flex flex-col h-full">
223
- {/* Header: icon + title */}
224
- <div className="flex items-center w-full justify-between mb-1">
225
- <div className="flex items-center gap-3">
226
- <div 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">
227
- <IconForView
228
- collectionOrView={{ slug: tool.path, name: tool.name, icon: tool.icon }}
229
- size="small"
230
- />
231
- </div>
232
- <Typography variant="subtitle1" component="h2">
233
- {tool.name}
234
- </Typography>
235
- </div>
236
- </div>
237
-
238
- {/* Description indented to align with title */}
239
- <div className="pl-8">
240
- {tool.description && (
241
- <Typography variant="caption" color="secondary" component="div">
242
- {tool.description}
243
- </Typography>
244
- )}
245
- </div>
246
-
247
- {/* Spacer */}
248
- <div className="grow"/>
249
- </div>
250
- </Card>
251
- ))}
252
- </div>
253
- </div>
254
- </ExpandablePanel>
255
- </div>
256
- );
257
- })}
258
-
259
- {/* ── SDK Quick Start ── */}
260
- <div className="mt-10 mb-6">
261
- <div className="flex items-center mb-1">
262
- <Typography
263
- variant="caption"
264
- component="h2"
265
- color="secondary"
266
- className={cls(
267
- "px-4 py-1 rounded",
268
- "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"
269
- )}
270
- >
271
- Quick Start
272
- </Typography>
273
- </div>
274
-
275
- <Typography variant="body2" color="secondary" className="mb-4 max-w-2xl">
276
- Generate a fully-typed SDK from your collections with{" "}
277
- <code className="text-emerald-400 font-mono text-xs bg-emerald-400/10 px-1.5 py-0.5 rounded">
278
- npx rebase generate-sdk
279
- </code>
280
- {" "}and start querying your data with full TypeScript autocompletion.
281
- </Typography>
282
-
283
- <div className="rounded-lg border border-surface-200/40 dark:border-surface-700/40 bg-white dark:bg-surface-950 overflow-hidden">
284
- {/* Title bar */}
285
- <div className="flex items-center justify-between px-4 py-2.5 border-b border-surface-200/40 dark:border-surface-700/40 bg-surface-50 dark:bg-surface-900/80">
286
- <div className="flex items-center gap-2.5">
287
- <div className="flex gap-1.5">
288
- <span className="w-2.5 h-2.5 rounded-full bg-red-400/60"/>
289
- <span className="w-2.5 h-2.5 rounded-full bg-amber-400/60"/>
290
- <span className="w-2.5 h-2.5 rounded-full bg-emerald-400/60"/>
291
- </div>
292
- <span className="text-xs font-mono text-surface-400 dark:text-surface-500 ml-1">
293
- app.ts
294
- </span>
295
- </div>
296
- <span className="text-xs font-mono text-surface-400 dark:text-surface-500">
297
- TypeScript
298
- </span>
299
- </div>
300
-
301
- {/* Syntax-highlighted code */}
302
- <div className="px-5 py-4 overflow-x-auto text-[13px] leading-6 font-mono">
303
- <SyntaxHighlightedSnippet/>
304
- </div>
305
- </div>
306
- </div>
307
-
308
- {/* ── Extra sections from props ── */}
309
- {sections?.map((s) => (
310
- <div key={s.key} className="my-10">
311
- <Typography
312
- variant="caption"
313
- component="h2"
314
- color="secondary"
315
- className={cls(
316
- "px-4 py-1 rounded",
317
- "font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"
318
- )}
319
- >
320
- {s.title}
321
- </Typography>
322
- <div className="mt-4">{s.children}</div>
323
- </div>
324
- ))}
325
-
326
- {additionalChildrenEnd}
327
- </Container>
328
- </div>
329
- );
330
- }
331
-
332
- /* ═══════════════════════════════════════════════════════════════
333
- Hand-crafted syntax-highlighted code snippet.
334
- Uses inline spans with Tailwind color classes to avoid
335
- pulling in a syntax highlighting library.
336
- ═══════════════════════════════════════════════════════════════ */
337
-
338
- function SyntaxHighlightedSnippet() {
339
- const kw = "text-violet-600 dark:text-violet-400"; // keywords
340
- const str = "text-emerald-600 dark:text-emerald-400"; // strings
341
- const typ = "text-amber-600 dark:text-amber-300"; // types
342
- const fn = "text-blue-600 dark:text-blue-400"; // functions
343
- const cm = "text-surface-500 dark:text-surface-400 italic"; // comments
344
- const op = "text-surface-500 dark:text-surface-400"; // operators / punctuation
345
- const tx = "text-surface-950 dark:text-surface-200"; // plain text
346
-
347
- return (
348
- <pre className="m-0 whitespace-pre">
349
- <span className={kw}>import</span>
350
- <span className={tx}>{" { "}</span>
351
- <span className={fn}>createRebaseClient</span>
352
- <span className={tx}>{" } "}</span>
353
- <span className={kw}>from</span>
354
- <span className={tx}> </span>
355
- <span className={str}>&apos;@rebasepro/client&apos;</span>
356
- <span className={op}>;</span>
357
- {"\n"}
358
-
359
- <span className={kw}>import</span>
360
- <span className={tx}> </span>
361
- <span className={kw}>type</span>
362
- <span className={tx}>{" { "}</span>
363
- <span className={typ}>Database</span>
364
- <span className={tx}>{" } "}</span>
365
- <span className={kw}>from</span>
366
- <span className={tx}> </span>
367
- <span className={str}>&apos;./database.types&apos;</span>
368
- <span className={op}>;</span>
369
- {"\n\n"}
370
-
371
- <span className={kw}>const</span>
372
- <span className={tx}> rebase </span>
373
- <span className={op}>= </span>
374
- <span className={fn}>createRebaseClient</span>
375
- <span className={op}>{"<"}</span>
376
- <span className={typ}>Database</span>
377
- <span className={op}>{">("}</span>
378
- <span className={tx}>{"{"}</span>
379
- {"\n"}
380
- <span className={tx}>{" baseUrl"}</span>
381
- <span className={op}>: </span>
382
- <span className={str}>&apos;http://localhost:3001&apos;</span>
383
- <span className={op}>,</span>
384
- {"\n"}
385
- <span className={tx}>{"}"}</span>
386
- <span className={op}>);</span>
387
- {"\n\n"}
388
-
389
- <span className={cm}>{"// Fully typed — autocompletion for tables and columns"}</span>
390
- {"\n"}
391
- <span className={kw}>const</span>
392
- <span className={tx}>{" { "}</span>
393
- <span className={tx}>data</span>
394
- <span className={op}>: </span>
395
- <span className={tx}>users</span>
396
- <span className={tx}>{" } "}</span>
397
- <span className={op}>= </span>
398
- <span className={kw}>await</span>
399
- <span className={tx}> rebase</span>
400
- <span className={op}>.</span>
401
- <span className={tx}>data</span>
402
- <span className={op}>.</span>
403
- <span className={tx}>users</span>
404
- <span className={op}>.</span>
405
- <span className={fn}>find</span>
406
- <span className={op}>();</span>
407
- {"\n"}
408
-
409
- <span className={kw}>const</span>
410
- <span className={tx}>{" { "}</span>
411
- <span className={tx}>data</span>
412
- <span className={op}>: </span>
413
- <span className={tx}>posts</span>
414
- <span className={tx}>{" } "}</span>
415
- <span className={op}>= </span>
416
- <span className={kw}>await</span>
417
- <span className={tx}> rebase</span>
418
- <span className={op}>.</span>
419
- <span className={tx}>data</span>
420
- <span className={op}>.</span>
421
- <span className={fn}>collection</span>
422
- <span className={op}>(</span>
423
- <span className={str}>&apos;posts&apos;</span>
424
- <span className={op}>)</span>
425
- <span className={op}>.</span>
426
- <span className={fn}>find</span>
427
- <span className={op}>();</span>
428
- </pre>
429
- );
430
- }
package/src/index.ts DELETED
@@ -1,31 +0,0 @@
1
- // ─── Bridge ─────────────────────────────────────────────────────────
2
- // Re-export the Studio Bridge from @rebasepro/app.
3
- // The bridge lives in core so both studio and admin can access it
4
- // without circular dependencies.
5
- export {
6
- StudioBridgeProvider,
7
- StudioBridgeContext,
8
- useStudioCollectionRegistry,
9
- useStudioSidePanelController,
10
- useStudioUrlController,
11
- useStudioNavigationState,
12
- useStudioBreadcrumbs
13
- } from "@rebasepro/app";
14
- export type {
15
- StudioBridge,
16
- BreadcrumbEntry,
17
- BreadcrumbsController
18
- } from "@rebasepro/app";
19
-
20
- // ─── Studio Entry Point ─────────────────────────────────────────────
21
- // Only export the lightweight orchestrator & home page.
22
- // Individual tools (SQLEditor, JSEditor, RLSEditor, StorageView, etc.)
23
- // are lazy-loaded by RebaseStudio.tsx — DO NOT re-export them here
24
- // or they'll be pulled into the main bundle, defeating code splitting.
25
- export * from "./components/RebaseStudio";
26
- export * from "./components/StudioHomePage";
27
-
28
- // ─── Direct tool imports (for advanced usage) ───────────────────────
29
- // Consumers that need direct access to a tool should use deep imports:
30
- // import { SQLEditor } from "@rebasepro/studio/components/SQLEditor/SQLEditor";
31
- // This avoids pulling all tools into their bundle.