@rebasepro/studio 0.24.0 → 0.24.1-canary.gcb918fc
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/dist/{ApiExplorer-CCtczj3F.js → ApiExplorer-Bzt7Ye49.js} +5 -3
- package/dist/ApiExplorer-Bzt7Ye49.js.map +1 -0
- package/dist/{ApiKeysView-B66TdzhH.js → ApiKeysView-Bqf6XYR1.js} +2 -1
- package/dist/{ApiKeysView-B66TdzhH.js.map → ApiKeysView-Bqf6XYR1.js.map} +1 -1
- package/dist/{BackupsView-DmSMzAbT.js → BackupsView-BhOHB6iP.js} +6 -20
- package/dist/BackupsView-BhOHB6iP.js.map +1 -0
- package/dist/{BranchesView-DP1a87E-.js → BranchesView-BHfwGTYc.js} +5 -3
- package/dist/BranchesView-BHfwGTYc.js.map +1 -0
- package/dist/{CronJobsView-TDErHTuK.js → CronJobsView-CMNK7eWO.js} +52 -59
- package/dist/CronJobsView-CMNK7eWO.js.map +1 -0
- package/dist/{JSEditor-B59pwg4c.js → JSEditor-DIO2Mw8q.js} +115 -96
- package/dist/JSEditor-DIO2Mw8q.js.map +1 -0
- package/dist/{LogsExplorer-BKM4yfP8.js → LogsExplorer-C-bwDFIl.js} +19 -23
- package/dist/LogsExplorer-C-bwDFIl.js.map +1 -0
- package/dist/{RLSEditor-BlLLV6xs.js → RLSEditor-jFD_d06f.js} +10 -8
- package/dist/RLSEditor-jFD_d06f.js.map +1 -0
- package/dist/{SQLEditor-1An7w0j6.js → SQLEditor-D5Ci4pyW.js} +372 -545
- package/dist/SQLEditor-D5Ci4pyW.js.map +1 -0
- package/dist/{SchemaVisualizer-DCLVfA5t.js → SchemaVisualizer-D-rAqwul.js} +479 -206
- package/dist/SchemaVisualizer-D-rAqwul.js.map +1 -0
- package/dist/{StorageView-CbsHuCBf.js → StorageView-CPkDKbsX.js} +498 -241
- package/dist/StorageView-CPkDKbsX.js.map +1 -0
- package/dist/assets/dagre-layout.worker-BFnhAzuR.js.map +1 -0
- package/dist/components/SQLEditor/SQLEditor.d.ts +11 -0
- package/dist/components/SchemaVisualizer/dagre-layout.d.ts +32 -0
- package/dist/components/SchemaVisualizer/dagre-layout.worker.d.ts +13 -0
- package/dist/components/SchemaVisualizer/layout-runner.d.ts +23 -0
- package/dist/components/SchemaVisualizer/schema-visualizer.utils.d.ts +21 -10
- package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +38 -1
- package/dist/components/StorageView/useVisibleFileMetadata.d.ts +46 -0
- package/dist/dagre-layout.worker-j9NbH9Gb.js +27 -0
- package/dist/dagre-layout.worker-j9NbH9Gb.js.map +1 -0
- package/dist/index.es.js +16 -14
- package/dist/index.es.js.map +1 -1
- package/dist/sql_utils-BZD31xE3.js +478 -0
- package/dist/sql_utils-BZD31xE3.js.map +1 -0
- package/dist/utils/sql_utils.d.ts +60 -0
- package/package.json +9 -9
- package/dist/ApiExplorer-CCtczj3F.js.map +0 -1
- package/dist/BackupsView-DmSMzAbT.js.map +0 -1
- package/dist/BranchesView-DP1a87E-.js.map +0 -1
- package/dist/CronJobsView-TDErHTuK.js.map +0 -1
- package/dist/JSEditor-B59pwg4c.js.map +0 -1
- package/dist/LogsExplorer-BKM4yfP8.js.map +0 -1
- package/dist/RLSEditor-BlLLV6xs.js.map +0 -1
- package/dist/SQLEditor-1An7w0j6.js.map +0 -1
- package/dist/SchemaVisualizer-DCLVfA5t.js.map +0 -1
- package/dist/StorageView-CbsHuCBf.js.map +0 -1
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { SQLEditorColumnInfo, TableInfo } from "./sql_editor_types.js";
|
|
3
3
|
export type { SQLEditorColumnInfo, TableInfo };
|
|
4
|
+
/**
|
|
5
|
+
* The box a result cell is edited in. It closes once: Enter saves, Escape
|
|
6
|
+
* cancels, a click away saves — and the blur a closing box can still receive
|
|
7
|
+
* is not a second answer, which made Enter save twice and Escape save at all.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FixedEditorOverlay: ({ displayValue, onSave, onCancel }: {
|
|
10
|
+
displayValue: string;
|
|
11
|
+
/** What the box holds when it closes — the text as typed. */
|
|
12
|
+
onSave: (val: string) => void;
|
|
13
|
+
onCancel: () => void;
|
|
14
|
+
}) => React.JSX.Element;
|
|
4
15
|
export declare const SQLEditor: () => React.JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the layout reads, as plain data: each table's id and box, each
|
|
3
|
+
* relation's ends. Plain so it can cross into the layout worker unchanged.
|
|
4
|
+
*/
|
|
5
|
+
export interface LayoutInput {
|
|
6
|
+
nodes: {
|
|
7
|
+
id: string;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}[];
|
|
11
|
+
edges: {
|
|
12
|
+
source: string;
|
|
13
|
+
target: string;
|
|
14
|
+
}[];
|
|
15
|
+
}
|
|
16
|
+
/** Each table's top-left corner, by node id. */
|
|
17
|
+
export type LayoutPositions = Record<string, {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Place the graph with dagre, top to bottom.
|
|
23
|
+
*
|
|
24
|
+
* An ERD read as a column of tables fits the tall, narrow canvas the
|
|
25
|
+
* visualizer is given, and it is the only layout the visualizer offers.
|
|
26
|
+
* Deterministic: the same input always gives the same positions.
|
|
27
|
+
*
|
|
28
|
+
* The cost is in dagre's ordering phase and grows fast with cross-linked
|
|
29
|
+
* graphs — 5 s at 200 tables with two relations each, 90 s at 500 — which is
|
|
30
|
+
* why the visualizer runs this in a worker (`dagre-layout.worker.ts`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function runDagre(input: LayoutInput): LayoutPositions;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The schema visualizer's layout, off the main thread.
|
|
3
|
+
*
|
|
4
|
+
* Receives one {@link LayoutInput}, answers with its positions (or the error's
|
|
5
|
+
* message). Bundled with dagre by the `?worker&inline` import in
|
|
6
|
+
* `layout-runner.ts`, so it needs nothing from the page that starts it.
|
|
7
|
+
*/
|
|
8
|
+
import { type LayoutPositions } from "./dagre-layout.js";
|
|
9
|
+
export type LayoutWorkerReply = {
|
|
10
|
+
positions: LayoutPositions;
|
|
11
|
+
} | {
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type LayoutInput, type LayoutPositions } from "./dagre-layout.js";
|
|
2
|
+
/**
|
|
3
|
+
* Whether this environment can start the layout worker.
|
|
4
|
+
*
|
|
5
|
+
* No in tests (jsdom has no `Worker`) and on a server render; there the
|
|
6
|
+
* layout runs where it is asked for, as it always did.
|
|
7
|
+
*/
|
|
8
|
+
export declare const canLayOutOffThread: () => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Lay a graph out in a worker of its own, which ends with the layout.
|
|
11
|
+
*
|
|
12
|
+
* The worker is inlined into the bundle (`?worker&inline`) rather than emitted
|
|
13
|
+
* as a file beside it: `@rebasepro/studio` is a library, and a worker file
|
|
14
|
+
* would be found only by an app bundler that rewrites
|
|
15
|
+
* `new URL(…, import.meta.url)` inside dependencies, which Vite's dependency
|
|
16
|
+
* pre-bundling does not. Imported on first use, so a page that never lays a
|
|
17
|
+
* graph out never decodes it.
|
|
18
|
+
*
|
|
19
|
+
* A worker that cannot be started or loaded — a Content-Security-Policy
|
|
20
|
+
* without `blob:` in `worker-src`, say — is not a broken diagram: the layout
|
|
21
|
+
* runs on the main thread instead, as it did before there was a worker.
|
|
22
|
+
*/
|
|
23
|
+
export declare function layOutOffThread(input: LayoutInput): Promise<LayoutPositions>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Node, Edge } from "@xyflow/react";
|
|
2
|
+
import { type LayoutInput, type LayoutPositions } from "./dagre-layout.js";
|
|
2
3
|
export declare const NODE_WIDTH = 280;
|
|
3
4
|
/**
|
|
4
5
|
* Compute the correct header height for a table node.
|
|
@@ -13,18 +14,28 @@ export declare const getHeaderHeight: (opts: {
|
|
|
13
14
|
* relative to the top of the node.
|
|
14
15
|
*/
|
|
15
16
|
export declare const getColumnRowY: (rowIndex: number, headerHeight?: number) => number;
|
|
17
|
+
/** A graph's layout input, and the key its positions are kept under. */
|
|
18
|
+
export interface LayoutPlan {
|
|
19
|
+
input: LayoutInput;
|
|
20
|
+
signature: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* What dagre will be given for these nodes and edges: each node's id and
|
|
24
|
+
* box, each edge's ends, in order. The signature is all of it, so a changed
|
|
25
|
+
* schema — a table, a column count, a relation — is a different key.
|
|
26
|
+
*/
|
|
27
|
+
export declare const planLayout: (nodes: Node[], edges: Edge[]) => LayoutPlan;
|
|
28
|
+
/** The positions for this plan, if it has been laid out before. */
|
|
29
|
+
export declare const cachedLayout: (plan: LayoutPlan) => LayoutPositions | undefined;
|
|
30
|
+
/** Lay the plan out here, on the calling thread. */
|
|
31
|
+
export declare const layOutNow: (plan: LayoutPlan) => LayoutPositions;
|
|
16
32
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* The graph always ranks top to bottom: an ERD read as a column of tables
|
|
21
|
-
* fits the tall, narrow canvas the visualizer is given, and it is the only
|
|
22
|
-
* layout the visualizer offers.
|
|
33
|
+
* Lay the plan out in a worker; the main thread stays free while it runs.
|
|
34
|
+
* See {@link layOutOffThread}.
|
|
23
35
|
*/
|
|
24
|
-
export declare const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
36
|
+
export declare const layOutInBackground: (plan: LayoutPlan) => Promise<LayoutPositions>;
|
|
37
|
+
/** The nodes at their laid-out positions, as new objects. */
|
|
38
|
+
export declare const placeNodes: (nodes: Node[], positions: LayoutPositions) => Node[];
|
|
28
39
|
export interface RelationEdgeData {
|
|
29
40
|
cardinality: "one" | "many";
|
|
30
41
|
direction: "owning" | "inverse";
|
|
@@ -29,16 +29,53 @@ export interface TableNodeData {
|
|
|
29
29
|
icon?: string;
|
|
30
30
|
[key: string]: unknown;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Above this many tables the diagram draws one table's neighbourhood, not
|
|
34
|
+
* the whole schema. Laying out 300 cross-linked tables takes dagre several
|
|
35
|
+
* seconds even in a worker, and a canvas of that many tables is no longer
|
|
36
|
+
* something anyone reads.
|
|
37
|
+
*/
|
|
38
|
+
export declare const LARGE_SCHEMA_TABLES = 300;
|
|
39
|
+
/** How far from the focused table the drawn neighbourhood reaches. */
|
|
40
|
+
export type NeighbourhoodDepth = 1 | 2;
|
|
32
41
|
export interface UseSchemaGraphResult {
|
|
42
|
+
/**
|
|
43
|
+
* The tables and relations on the canvas, placed. Empty while
|
|
44
|
+
* {@link layingOut} — the layout of a graph not seen before runs in a
|
|
45
|
+
* worker, never in render.
|
|
46
|
+
*/
|
|
33
47
|
nodes: Node[];
|
|
34
48
|
edges: Edge[];
|
|
49
|
+
/** Every table and junction table in the schema, drawn or not. */
|
|
50
|
+
allNodes: Node[];
|
|
35
51
|
relayout: () => void;
|
|
52
|
+
/** Tables and relations in the whole schema. */
|
|
36
53
|
tableCount: number;
|
|
37
54
|
relationCount: number;
|
|
55
|
+
/** The layout is running off the main thread. */
|
|
56
|
+
layingOut: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Set when the schema has more than {@link LARGE_SCHEMA_TABLES} tables:
|
|
59
|
+
* which table's neighbourhood is drawn, how far it reaches, how many
|
|
60
|
+
* tables that is, and how many there are in all.
|
|
61
|
+
*/
|
|
62
|
+
neighbourhood: {
|
|
63
|
+
focus: string;
|
|
64
|
+
depth: NeighbourhoodDepth;
|
|
65
|
+
shown: number;
|
|
66
|
+
total: number;
|
|
67
|
+
} | null;
|
|
38
68
|
}
|
|
39
69
|
export declare const useSchemaGraph: (collections: AdminCollection[] | undefined,
|
|
40
70
|
/**
|
|
41
71
|
* `schema.table` for every table the database reports RLS on, or `null`
|
|
42
72
|
* when there is no SQL capability to ask. See {@link useLiveRlsTables}.
|
|
43
73
|
*/
|
|
44
|
-
liveRls?: Set<string> | null
|
|
74
|
+
liveRls?: Set<string> | null,
|
|
75
|
+
/**
|
|
76
|
+
* The table whose neighbourhood a large schema draws, by node id. When it
|
|
77
|
+
* is absent, or not a table of this schema, the most connected one. Not
|
|
78
|
+
* read for a schema of {@link LARGE_SCHEMA_TABLES} tables or fewer, which
|
|
79
|
+
* is drawn whole.
|
|
80
|
+
*/
|
|
81
|
+
focus?: string | null, depth?: NeighbourhoodDepth) => UseSchemaGraphResult;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DownloadConfig, StorageSource } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* What the storage browser shows of a file beyond its name. The listing carries
|
|
4
|
+
* the size and version — and, except on S3, the type — of every file; the rest
|
|
5
|
+
* is read per file, from the server, when it is needed.
|
|
6
|
+
*/
|
|
7
|
+
export interface FileMetadata {
|
|
8
|
+
size?: number;
|
|
9
|
+
contentType?: string;
|
|
10
|
+
/**
|
|
11
|
+
* A link minted when the metadata was read, for the thumbnail only: a
|
|
12
|
+
* private file's token expires, and a link to share or download is minted
|
|
13
|
+
* when it is used (see `FileLink` in `StorageView.tsx`).
|
|
14
|
+
*/
|
|
15
|
+
downloadUrl?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function fileMetadataOf(config: DownloadConfig): FileMetadata;
|
|
18
|
+
/**
|
|
19
|
+
* How many metadata requests run at once: what one origin gets over HTTP/1.1.
|
|
20
|
+
* Each is a round trip to the server, an auth hook and a HEAD on the bucket.
|
|
21
|
+
*/
|
|
22
|
+
export declare const METADATA_CONCURRENCY = 6;
|
|
23
|
+
/**
|
|
24
|
+
* Metadata for the files of a listing, asked for as each comes on screen —
|
|
25
|
+
* and only for those `wants` says need it: the listing already describes most
|
|
26
|
+
* files (see `StorageReference.size`), so what is left is a file a source
|
|
27
|
+
* listed bare, and the link an image's thumbnail is drawn from.
|
|
28
|
+
*
|
|
29
|
+
* The browser used to ask for every file's metadata before it showed any of
|
|
30
|
+
* them: a folder of 1,000 files was 1,001 requests and seconds of a spinner.
|
|
31
|
+
* The listing is shown as it comes back; a file's metadata is asked for when
|
|
32
|
+
* its element — given {@link observe} as its `ref`, and its path as
|
|
33
|
+
* `data-storage-path` — scrolls into view, a few requests at a time.
|
|
34
|
+
*
|
|
35
|
+
* Kept per listing: keyed by path, and dropped when `files` or `source`
|
|
36
|
+
* changes — another folder, another source, or the same folder read again
|
|
37
|
+
* after an upload or a delete, whose files may have changed. Without an
|
|
38
|
+
* `IntersectionObserver` every file of the listing is asked for, still a few
|
|
39
|
+
* at a time and still after the listing is shown.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useVisibleFileMetadata<F extends {
|
|
42
|
+
fullPath: string;
|
|
43
|
+
}>(source: StorageSource | null, files: readonly F[], wants?: (file: F) => boolean): {
|
|
44
|
+
metadata: ReadonlyMap<string, FileMetadata>;
|
|
45
|
+
observe: (element: HTMLElement | null) => (() => void) | undefined;
|
|
46
|
+
};
|