@svgrid/enterprise 3.1.16 → 3.1.18
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/SvGridEditPanel.svelte +14 -1
- package/dist/SvGridScheduler.svelte +15 -6
- package/dist/SvSheet.svelte +2 -0
- package/dist/cdn/svgrid-enterprise.svelte-external.js +6582 -6501
- package/dist/designer/assets/{index-C0GDyyFs.js → index-DKudY-XD.js} +357 -346
- package/dist/designer/assets/index-WCxj6WfJ.css +1 -0
- package/dist/designer/index.html +2 -2
- package/dist/fields/SvBase.svelte +36 -33
- package/dist/fields/base-connect.js +50 -9
- package/dist/fields/base-sql.d.ts +8 -0
- package/dist/fields/base-sql.js +12 -3
- package/dist/install.js +3 -3
- package/dist/node/studio.js +205 -60
- package/dist/sheet-enable.d.ts +8 -2
- package/dist/sheet-enable.js +21 -9
- package/dist/sources/introspect-supabase.d.ts +6 -3
- package/dist/sources/introspect-supabase.js +29 -11
- package/dist/sources/supabase.d.ts +10 -0
- package/dist/sources/supabase.js +11 -2
- package/dist/studio/cli.d.ts +9 -0
- package/dist/studio/cli.js +41 -7
- package/dist/studio/emit-project.d.ts +3 -1
- package/dist/studio/emit-project.js +84 -33
- package/dist/studio/emit-schema.js +9 -2
- package/dist/studio/index.d.ts +1 -1
- package/dist/studio/init-flow.d.ts +7 -0
- package/dist/studio/init-flow.js +23 -2
- package/dist/studio/introspect-db.d.ts +15 -1
- package/dist/studio/introspect-db.js +29 -5
- package/dist/sveltekit/sql-source.d.ts +24 -0
- package/dist/sveltekit/sql-source.js +34 -1
- package/dist/sveltekit/sql.js +14 -2
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/wc/GridFooter-BgoA77TJ.js +145 -0
- package/dist/wc/{GridMenus-q9qYpzKh.js → GridMenus-DVGuqp2l.js} +430 -430
- package/dist/wc/{PinSplitter-D-qtDhSM.js → PinSplitter-Btco0txr.js} +24 -24
- package/dist/wc/{SvChartMenu-CQNrQGT2.js → SvChartMenu-Ue-HFR5c.js} +58 -58
- package/dist/wc/{SvDateRangeInput-BYNOfYxD.js → SvDateRangeInput-CJZohgBe.js} +43 -43
- package/dist/wc/{SvDateTimePicker-Bq9N0Oiy.js → SvDateTimePicker-DmK_QkkU.js} +241 -241
- package/dist/wc/{SvField-B_kurx_P.js → SvField-C-OodMMv.js} +71 -71
- package/dist/wc/SvGridCellEditor-C7ios4i_.js +582 -0
- package/dist/wc/{SvGridChart-DrmqEen2.js → SvGridChart-DWRqlhCV.js} +549 -549
- package/dist/wc/{SvGridChartBuilder-XFvW1BdT.js → SvGridChartBuilder-BXW3yUR0.js} +337 -337
- package/dist/wc/{SvGridChartPanel-oJJtUKG6.js → SvGridChartPanel-28n4tomx.js} +354 -354
- package/dist/wc/{SvGridChartView-Cetuj70H.js → SvGridChartView-CbG_WrU-.js} +7 -7
- package/dist/wc/{SvGridDropdown-45WsObLL.js → SvGridDropdown-BVnpNU_I.js} +130 -130
- package/dist/wc/{SvModal-DrfOYYyX.js → SvModal-DLppAQED.js} +91 -91
- package/dist/wc/{client-DQIzjDBG.js → client-GWAV79ON.js} +479 -476
- package/dist/wc/{date-format-DS-z_h9v.js → date-format-4_QoS4zZ.js} +393 -393
- package/dist/wc/{grid-extension.svelte-Bufq4B4C.js → grid-extension.svelte-CucBS4FL.js} +1 -1
- package/dist/wc/sv-sheet-element.js +10475 -10461
- package/dist/wc/{svelte-virtualizer.svelte-CkZaFakp.js → svelte-virtualizer.svelte-BDcouWqw.js} +3 -3
- package/package.json +17 -4
- package/dist/designer/assets/index-BdL--HXH.css +0 -1
- package/dist/wc/GridFooter-4T29pfok.js +0 -145
- package/dist/wc/SvGridCellEditor-Nnl8C3Yj.js +0 -582
package/dist/designer/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>SvGrid Studio - Designer</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-DKudY-XD.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-Dd_uD5pT.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/disclose-version-CIm4S9xS.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="./assets/cell-formatting-JoxA0t65.js">
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
<link rel="stylesheet" crossorigin href="./assets/SvMenuList-DJ47ba1h.css">
|
|
46
46
|
<link rel="stylesheet" crossorigin href="./assets/SvGridChart-BgLuPO7I.css">
|
|
47
47
|
<link rel="stylesheet" crossorigin href="./assets/SvGridChartPanel-4Pc8y5yO.css">
|
|
48
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
48
|
+
<link rel="stylesheet" crossorigin href="./assets/index-WCxj6WfJ.css">
|
|
49
49
|
</head>
|
|
50
50
|
<body>
|
|
51
51
|
<div id="app"></div>
|
|
@@ -525,11 +525,12 @@
|
|
|
525
525
|
})
|
|
526
526
|
</script>
|
|
527
527
|
|
|
528
|
-
|
|
528
|
+
<!-- An empty list still gets the tabs, so "Add table" is there. -->
|
|
529
|
+
{#if tables}
|
|
529
530
|
<div class="sv-fbase-tables" style:height>
|
|
530
531
|
<BaseTabs
|
|
531
532
|
{tables}
|
|
532
|
-
activeId={current
|
|
533
|
+
activeId={current?.id ?? ''}
|
|
533
534
|
onSwitch={switchTo}
|
|
534
535
|
onAdd={addTable}
|
|
535
536
|
onRename={renameTable}
|
|
@@ -539,37 +540,39 @@
|
|
|
539
540
|
status={syncLine}
|
|
540
541
|
/>
|
|
541
542
|
<div class="sv-fbase-slot">
|
|
542
|
-
{#
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
543
|
+
{#if current}
|
|
544
|
+
{#key current.id}
|
|
545
|
+
<BaseTableView
|
|
546
|
+
{...gridProps}
|
|
547
|
+
bare
|
|
548
|
+
data={gridData}
|
|
549
|
+
columns={current.columns}
|
|
550
|
+
views={current.views ?? GRID_ONLY}
|
|
551
|
+
bind:activeView={viewOf[current.id]}
|
|
552
|
+
onViewsChange={(v: FieldView[]) => commit(pulled({ views: v }))}
|
|
553
|
+
table={current}
|
|
554
|
+
tables={() => pulled()}
|
|
555
|
+
runner={automations ? runner : undefined}
|
|
556
|
+
{serverRuns}
|
|
557
|
+
onAutomationsChange={(list: BaseAutomation[]) => commit(pulled({ automations: list }))}
|
|
558
|
+
onFormSubmit={(row: Row, viewId: string) => void runner.handle({ type: 'form', table: current!.id, record: row, view: viewId })}
|
|
559
|
+
newRecord={() => ({ id: newRecordId() })}
|
|
560
|
+
{viewTypes}
|
|
561
|
+
{rowHeights}
|
|
562
|
+
containerHeight="100%"
|
|
563
|
+
onApiReady={(a: any) => {
|
|
564
|
+
api = a
|
|
565
|
+
onApiReady?.(a)
|
|
566
|
+
const rowId = pendingOpen
|
|
567
|
+
pendingOpen = null
|
|
568
|
+
if (rowId) queueMicrotask(() => {
|
|
569
|
+
const ctrl = gridOf(a)
|
|
570
|
+
if (ctrl) openRecord({ ctrl, rowId })
|
|
571
|
+
})
|
|
572
|
+
}}
|
|
573
|
+
/>
|
|
574
|
+
{/key}
|
|
575
|
+
{/if}
|
|
573
576
|
</div>
|
|
574
577
|
</div>
|
|
575
578
|
{:else}
|
|
@@ -5,7 +5,7 @@ import { createSupabaseDataSource } from '../sources/supabase.js';
|
|
|
5
5
|
import { createSupabaseRealtime } from '../sources/realtime-supabase.js';
|
|
6
6
|
import { introspectSupabaseTable, listSupabaseTables } from '../sources/introspect-supabase.js';
|
|
7
7
|
import { applyBaseComments, baseSpecFromSchemas, baseTablesFromSpec, withInverses } from './base-schema.js';
|
|
8
|
-
import { SQL_COMMENT_PREFIX } from './base-sql.js';
|
|
8
|
+
import { BASE_ORDER_COLUMN, SQL_COMMENT_PREFIX } from './base-sql.js';
|
|
9
9
|
const SQL_DIALECT = {
|
|
10
10
|
postgres: { placeholders: '$', ilike: true },
|
|
11
11
|
supabase: { placeholders: '$', ilike: true },
|
|
@@ -13,6 +13,41 @@ const SQL_DIALECT = {
|
|
|
13
13
|
sqlite: { placeholders: '?' },
|
|
14
14
|
mssql: { placeholders: '@' },
|
|
15
15
|
};
|
|
16
|
+
// ---- The order column (BASE_ORDER_COLUMN) -----------------------------------
|
|
17
|
+
// A table made by baseToSql numbers its records in insertion order. The base
|
|
18
|
+
// reads in that order while nothing is sorted, but the column is not a field:
|
|
19
|
+
// it is left out of what the base shows and validates, out of the rows it
|
|
20
|
+
// gets, and out of every write (generated always, so writing it would fail).
|
|
21
|
+
const hasOrder = (s) => s.fields.some((f) => f.field === BASE_ORDER_COLUMN);
|
|
22
|
+
const ORDER = [{ field: BASE_ORDER_COLUMN }];
|
|
23
|
+
/** The schema the base shows: without the order column. */
|
|
24
|
+
function shown(s) {
|
|
25
|
+
return hasOrder(s) ? { ...s, fields: s.fields.filter((f) => f.field !== BASE_ORDER_COLUMN) } : s;
|
|
26
|
+
}
|
|
27
|
+
function dropOrder(row) {
|
|
28
|
+
if (!row || typeof row !== 'object' || !(BASE_ORDER_COLUMN in row))
|
|
29
|
+
return row;
|
|
30
|
+
const copy = { ...row };
|
|
31
|
+
delete copy[BASE_ORDER_COLUMN];
|
|
32
|
+
return copy;
|
|
33
|
+
}
|
|
34
|
+
/** A source that never hands out or writes the order column. */
|
|
35
|
+
function hideOrder(source) {
|
|
36
|
+
return {
|
|
37
|
+
...source,
|
|
38
|
+
getRows: async (request) => {
|
|
39
|
+
const result = await source.getRows(request);
|
|
40
|
+
return { ...result, rows: result.rows.map(dropOrder) };
|
|
41
|
+
},
|
|
42
|
+
createRow: async (input) => dropOrder(await source.createRow(dropOrder(input))),
|
|
43
|
+
updateRow: async (id, patch) => dropOrder(await source.updateRow(id, dropOrder(patch))),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** A table on SQL, in insertion order when it has the order column. */
|
|
47
|
+
function sqlSource(schema, table, dialect, execute) {
|
|
48
|
+
const source = createSqlDataSource({ schema, table, dialect: SQL_DIALECT[dialect], execute, ...(hasOrder(schema) ? { defaultOrder: ORDER } : {}) });
|
|
49
|
+
return hasOrder(schema) ? hideOrder(source) : source;
|
|
50
|
+
}
|
|
16
51
|
const quote = (dialect, name) => dialect === 'mysql' ? `\`${name.replace(/`/g, '``')}\`` : dialect === 'mssql' ? `[${name.replace(/]/g, ']]')}]` : `"${name.replace(/"/g, '""')}"`;
|
|
17
52
|
const param = (dialect, i) => (dialect === 'postgres' || dialect === 'supabase' ? `$${i}` : dialect === 'mssql' ? `@p${i}` : '?');
|
|
18
53
|
/** The values each text column repeats, most used first (at most 13 per column). */
|
|
@@ -130,9 +165,10 @@ async function makesKeys(o, dialect, s) {
|
|
|
130
165
|
async function readDatabase(o) {
|
|
131
166
|
const dialect = o.dialect ?? 'postgres';
|
|
132
167
|
const names = o.tables ?? (await listDatabaseTables(dialect, o.execute));
|
|
133
|
-
const
|
|
168
|
+
const all = [];
|
|
134
169
|
for (const table of names)
|
|
135
|
-
|
|
170
|
+
all.push(await introspectDatabase({ dialect, table, execute: o.execute }));
|
|
171
|
+
const list = all.map(shown);
|
|
136
172
|
// A junction table the list leaves out still carries a link to many.
|
|
137
173
|
const values = o.choices === false ? {} : await readValues(o, dialect, list);
|
|
138
174
|
const keys = new Map();
|
|
@@ -143,7 +179,8 @@ async function readDatabase(o) {
|
|
|
143
179
|
let specs = baseSpecFromSchemas(list, { values, serverIds: (s) => keys.get(s.name) ?? false, order: o.tables ? 'given' : 'links', inverses: !kept });
|
|
144
180
|
if (kept)
|
|
145
181
|
specs = withComments(specs, comments, !!o.tables);
|
|
146
|
-
|
|
182
|
+
// The sources read with the order column; the base never sees it.
|
|
183
|
+
return { specs, schemas: new Map(all.map((s) => [s.name, s])) };
|
|
147
184
|
}
|
|
148
185
|
/** The tables of a database, described as a base: plain JSON (what an endpoint sends). */
|
|
149
186
|
export async function describeDatabase(options) {
|
|
@@ -159,7 +196,7 @@ export async function describeDatabase(options) {
|
|
|
159
196
|
export async function baseFromDatabase(options) {
|
|
160
197
|
const dialect = options.dialect ?? 'postgres';
|
|
161
198
|
const { specs, schemas } = await readDatabase(options);
|
|
162
|
-
return baseTablesFromSpec(specs, (table) =>
|
|
199
|
+
return baseTablesFromSpec(specs, (table) => sqlSource(schemas.get(table), table, dialect, options.execute));
|
|
163
200
|
}
|
|
164
201
|
/**
|
|
165
202
|
* The server half of `baseFromEndpoint`, as a SvelteKit route:
|
|
@@ -194,8 +231,8 @@ export function createBaseEndpoint(options) {
|
|
|
194
231
|
let h = handlers.get(table);
|
|
195
232
|
if (!h) {
|
|
196
233
|
h = createKitHandlers({
|
|
197
|
-
schema,
|
|
198
|
-
source:
|
|
234
|
+
schema: shown(schema),
|
|
235
|
+
source: sqlSource(schema, table, dialect, options.execute),
|
|
199
236
|
...(options.authorize ? { authorize: options.authorize(table) } : {}),
|
|
200
237
|
...(options.audit ? { audit: options.audit(table) } : {}),
|
|
201
238
|
});
|
|
@@ -262,10 +299,14 @@ export async function baseFromSupabase(options) {
|
|
|
262
299
|
const comments = await readSupabaseComments(options);
|
|
263
300
|
const kept = hasComments(comments);
|
|
264
301
|
// Supabase makes the keys: its source inserts without the page's id.
|
|
265
|
-
let specs = baseSpecFromSchemas(schemas, { values, serverIds: () => true, order: options.tables ? 'given' : 'links', inverses: !kept });
|
|
302
|
+
let specs = baseSpecFromSchemas(schemas.map(shown), { values, serverIds: () => true, order: options.tables ? 'given' : 'links', inverses: !kept });
|
|
266
303
|
if (kept)
|
|
267
304
|
specs = withComments(specs, comments, !!options.tables);
|
|
268
|
-
return baseTablesFromSpec(specs, (table) =>
|
|
305
|
+
return baseTablesFromSpec(specs, (table) => {
|
|
306
|
+
const schema = byName.get(table);
|
|
307
|
+
const source = createSupabaseDataSource({ client: options.client, table, schema, ...(hasOrder(schema) ? { defaultOrder: ORDER } : {}) });
|
|
308
|
+
return (hasOrder(schema) ? hideOrder(source) : source);
|
|
309
|
+
}, (s) => options.realtime === false
|
|
269
310
|
? {}
|
|
270
311
|
: { realtime: (onChange) => createSupabaseRealtime({ client: options.client, table: s.id, onChange }) });
|
|
271
312
|
}
|
|
@@ -39,6 +39,14 @@ export type BaseJunctionComment = {
|
|
|
39
39
|
};
|
|
40
40
|
};
|
|
41
41
|
export declare const SQL_COMMENT_PREFIX = "svgrid:";
|
|
42
|
+
/**
|
|
43
|
+
* A column baseToSql gives every table: an identity that numbers the records
|
|
44
|
+
* in the order they were written. Text keys (seed ids, UUIDs) do not sort that
|
|
45
|
+
* way, so the base reads rows in this order while nothing is sorted. It is not
|
|
46
|
+
* a field: baseFromDatabase, createBaseEndpoint and baseFromSupabase leave it
|
|
47
|
+
* out of the base and never write it.
|
|
48
|
+
*/
|
|
49
|
+
export declare const BASE_ORDER_COLUMN = "svgrid_order";
|
|
42
50
|
/** `fixedOn` -> `fixed_on`, `Key results` -> `key_results`. */
|
|
43
51
|
export declare function sqlName(s: string): string;
|
|
44
52
|
export type BaseToSqlOptions = {
|
package/dist/fields/base-sql.js
CHANGED
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
import { colId, primaryOf, rowIdOf } from './base-tables.js';
|
|
15
15
|
import { fillFieldColumn } from './registry.svelte.js';
|
|
16
16
|
export const SQL_COMMENT_PREFIX = 'svgrid:';
|
|
17
|
+
/**
|
|
18
|
+
* A column baseToSql gives every table: an identity that numbers the records
|
|
19
|
+
* in the order they were written. Text keys (seed ids, UUIDs) do not sort that
|
|
20
|
+
* way, so the base reads rows in this order while nothing is sorted. It is not
|
|
21
|
+
* a field: baseFromDatabase, createBaseEndpoint and baseFromSupabase leave it
|
|
22
|
+
* out of the base and never write it.
|
|
23
|
+
*/
|
|
24
|
+
export const BASE_ORDER_COLUMN = 'svgrid_order';
|
|
17
25
|
/** `fixedOn` -> `fixed_on`, `Key results` -> `key_results`. */
|
|
18
26
|
export function sqlName(s) {
|
|
19
27
|
const out = String(s)
|
|
@@ -115,7 +123,7 @@ export function baseToSql(tables, options = {}) {
|
|
|
115
123
|
const name = nameOf.get(t.id);
|
|
116
124
|
const columns = [];
|
|
117
125
|
const extra = [];
|
|
118
|
-
const taken = new Set(['id']);
|
|
126
|
+
const taken = new Set(['id', BASE_ORDER_COLUMN]);
|
|
119
127
|
const column = (base) => {
|
|
120
128
|
let c = sqlName(base);
|
|
121
129
|
while (taken.has(c))
|
|
@@ -153,8 +161,9 @@ export function baseToSql(tables, options = {}) {
|
|
|
153
161
|
columns.push({ def: d, column: column(field) });
|
|
154
162
|
}
|
|
155
163
|
// The database makes the key of a record added later: a Supabase insert
|
|
156
|
-
// carries no id. The records below bring their own.
|
|
157
|
-
|
|
164
|
+
// carries no id. The records below bring their own. The order column
|
|
165
|
+
// numbers them as they are inserted, so the records keep the order below.
|
|
166
|
+
const lines = [` "id" text primary key default gen_random_uuid()::text`, ` ${quote(BASE_ORDER_COLUMN)} bigint generated always as identity`, ...columns.map((c) => ` ${quote(c.column)} ${c.fk ? 'text' : sqlType(c.def)}`)];
|
|
158
167
|
plans.push({ table: t, columns, extra, sql: `create table ${quote(name)} (\n${lines.join(',\n')}\n);` });
|
|
159
168
|
}
|
|
160
169
|
const out = [];
|
package/dist/install.js
CHANGED
|
@@ -14,7 +14,7 @@ import { enableGanttView } from './gantt/gantt.js';
|
|
|
14
14
|
import { enableSelectionBar } from './selection-bar.js';
|
|
15
15
|
import { enableAdvancedFilter } from './advanced-filter-enable.js';
|
|
16
16
|
import { enablePivot } from './pivot-enable.js';
|
|
17
|
-
import {
|
|
17
|
+
import { registerSheetKeymap } from './sheet-enable.js';
|
|
18
18
|
import { enableServerRowModel } from './server/enable.js';
|
|
19
19
|
/**
|
|
20
20
|
* Augment a SvGridApi instance with Pro methods (`exportData`, `print`,
|
|
@@ -59,8 +59,8 @@ export function installEnterprise(api) {
|
|
|
59
59
|
enableAdvancedFilter();
|
|
60
60
|
// Register the Excel keymap (Ctrl+Arrow, Ctrl+D, Ctrl+A and the rest). The
|
|
61
61
|
// grid interprets a key itself only when nothing claims it, so a free grid
|
|
62
|
-
// is unaffected.
|
|
63
|
-
|
|
62
|
+
// is unaffected. No spreadsheet nudge: this app may only export or pivot.
|
|
63
|
+
registerSheetKeymap();
|
|
64
64
|
// Raise the unlicensed nudge for the server-side row model. No registry to fill -
|
|
65
65
|
// the model hands the grid ordinary rows - so this only nudges when unlicensed.
|
|
66
66
|
enableServerRowModel();
|