@rozenite/sqlite-plugin 2.0.0 → 2.1.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/CHANGELOG.md +8 -0
- package/dist/devtools/assets/{panel-CsA6Ejak.js → panel-BsdCagVv.js} +3 -3
- package/dist/devtools/panel.html +1 -1
- package/dist/react-native/chunks/index.require.js +4 -16
- package/dist/react-native/chunks/sql.require.js +1 -3
- package/dist/react-native/chunks/useRozeniteSqlitePlugin.require.js +92 -110
- package/dist/react-native/index.d.ts +1 -1
- package/dist/rozenite.json +1 -1
- package/package.json +23 -23
- package/react-native.ts +7 -14
- package/src/react-native/adapters/__tests__/expo-sqlite.test.ts +4 -14
- package/src/react-native/adapters/expo-sqlite.ts +11 -40
- package/src/react-native/adapters/generic.ts +5 -13
- package/src/react-native/adapters/index.ts +1 -4
- package/src/react-native/sqlite-view.ts +2 -8
- package/src/react-native/useRozeniteSqlitePlugin.ts +110 -130
- package/src/react-native/useSqliteAgentTools.ts +6 -18
- package/src/shared/__tests__/bridge-values.test.ts +6 -11
- package/src/shared/__tests__/sql.test.ts +4 -8
- package/src/shared/bridge-values.ts +2 -5
- package/src/shared/sql.ts +3 -7
- package/src/ui/__tests__/sql-editor-utils.test.ts +1 -5
- package/src/ui/__tests__/sqlite-drop-mutations.test.ts +6 -3
- package/src/ui/__tests__/sqlite-row-mutations.test.ts +1 -3
- package/src/ui/__tests__/sqlite-table-column-order.test.ts +4 -19
- package/src/ui/cell-detail-drawer.tsx +1 -6
- package/src/ui/globals.css +14 -65
- package/src/ui/panel.tsx +256 -596
- package/src/ui/query-result-table.tsx +8 -26
- package/src/ui/sql-editor-utils.ts +24 -55
- package/src/ui/sql-editor.tsx +13 -46
- package/src/ui/sqlite-data-table.tsx +11 -28
- package/src/ui/sqlite-drop-modal.tsx +17 -43
- package/src/ui/sqlite-drop-mutations.ts +3 -10
- package/src/ui/sqlite-introspection.ts +9 -25
- package/src/ui/sqlite-row-delete-modal.tsx +5 -12
- package/src/ui/sqlite-row-edit-modal.tsx +22 -64
- package/src/ui/sqlite-row-edit-value.ts +2 -11
- package/src/ui/sqlite-row-mutations.ts +10 -32
- package/src/ui/sqlite-table-column-order.ts +8 -23
- package/src/ui/use-sqlite-requests.ts +46 -86
- package/src/ui/utils.ts +1 -5
- package/src/ui/value-utils.tsx +3 -11
|
@@ -54,13 +54,10 @@ export type SqliteIndexColumnInfo = {
|
|
|
54
54
|
const buildQualifiedEntityName = (schemaName: string, entityName: string) =>
|
|
55
55
|
`${quoteSqlIdentifier(schemaName)}.${quoteSqlIdentifier(entityName)}`;
|
|
56
56
|
|
|
57
|
-
const buildPragmaPrefix = (schemaName: string) =>
|
|
58
|
-
`${quoteSqlIdentifier(schemaName)}.`;
|
|
57
|
+
const buildPragmaPrefix = (schemaName: string) => `${quoteSqlIdentifier(schemaName)}.`;
|
|
59
58
|
|
|
60
|
-
const asString = (value: unknown) =>
|
|
61
|
-
|
|
62
|
-
const asNullableString = (value: unknown) =>
|
|
63
|
-
value == null ? null : String(value);
|
|
59
|
+
const asString = (value: unknown) => (typeof value === 'string' ? value : String(value ?? ''));
|
|
60
|
+
const asNullableString = (value: unknown) => (value == null ? null : String(value));
|
|
64
61
|
const asNumber = (value: unknown) => {
|
|
65
62
|
const parsed = Number(value ?? 0);
|
|
66
63
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
@@ -93,10 +90,7 @@ export const buildBrowseEntitySql = (
|
|
|
93
90
|
export const buildEntityCountSql = (schemaName: string, entityName: string) =>
|
|
94
91
|
`SELECT COUNT(*) AS count FROM ${buildQualifiedEntityName(schemaName, entityName)}`;
|
|
95
92
|
|
|
96
|
-
export const buildCreateSqlLookup = (
|
|
97
|
-
schemaName: string,
|
|
98
|
-
entityName: string,
|
|
99
|
-
) => `
|
|
93
|
+
export const buildCreateSqlLookup = (schemaName: string, entityName: string) => `
|
|
100
94
|
SELECT sql
|
|
101
95
|
FROM ${quoteSqlIdentifier(schemaName)}.sqlite_schema
|
|
102
96
|
WHERE type IN ('table', 'view')
|
|
@@ -125,17 +119,12 @@ export const parseSchemas = (result: SqliteQueryResult): SqliteSchema[] =>
|
|
|
125
119
|
}))
|
|
126
120
|
.filter((schema) => !!schema.name);
|
|
127
121
|
|
|
128
|
-
export const parseEntities = (
|
|
129
|
-
result: SqliteQueryResult,
|
|
130
|
-
schemaName: string,
|
|
131
|
-
): SqliteEntity[] =>
|
|
122
|
+
export const parseEntities = (result: SqliteQueryResult, schemaName: string): SqliteEntity[] =>
|
|
132
123
|
result.rows
|
|
133
124
|
.map((row) => ({
|
|
134
125
|
schemaName,
|
|
135
126
|
name: asString(row.name),
|
|
136
|
-
type: (asString(row.type) === 'view'
|
|
137
|
-
? 'view'
|
|
138
|
-
: 'table') as SqliteEntityType,
|
|
127
|
+
type: (asString(row.type) === 'view' ? 'view' : 'table') as SqliteEntityType,
|
|
139
128
|
sql: asNullableString(row.sql),
|
|
140
129
|
}))
|
|
141
130
|
.filter((entity) => !!entity.name);
|
|
@@ -151,9 +140,7 @@ export const parseColumns = (result: SqliteQueryResult): SqliteColumnInfo[] =>
|
|
|
151
140
|
hidden: asNumber(row.hidden),
|
|
152
141
|
}));
|
|
153
142
|
|
|
154
|
-
export const parseForeignKeys = (
|
|
155
|
-
result: SqliteQueryResult,
|
|
156
|
-
): SqliteForeignKeyInfo[] =>
|
|
143
|
+
export const parseForeignKeys = (result: SqliteQueryResult): SqliteForeignKeyInfo[] =>
|
|
157
144
|
result.rows.map((row) => ({
|
|
158
145
|
id: asNumber(row.id),
|
|
159
146
|
seq: asNumber(row.seq),
|
|
@@ -174,9 +161,7 @@ export const parseIndexes = (result: SqliteQueryResult): SqliteIndexInfo[] =>
|
|
|
174
161
|
partial: asNumber(row.partial) === 1,
|
|
175
162
|
}));
|
|
176
163
|
|
|
177
|
-
export const parseIndexColumns = (
|
|
178
|
-
result: SqliteQueryResult,
|
|
179
|
-
): SqliteIndexColumnInfo[] =>
|
|
164
|
+
export const parseIndexColumns = (result: SqliteQueryResult): SqliteIndexColumnInfo[] =>
|
|
180
165
|
result.rows
|
|
181
166
|
.map((row) => ({
|
|
182
167
|
seqno: asNumber(row.seqno),
|
|
@@ -185,5 +170,4 @@ export const parseIndexColumns = (
|
|
|
185
170
|
}))
|
|
186
171
|
.filter((column) => !!column.name);
|
|
187
172
|
|
|
188
|
-
export const parseCount = (result: SqliteQueryResult) =>
|
|
189
|
-
asNumber(result.rows[0]?.count);
|
|
173
|
+
export const parseCount = (result: SqliteQueryResult) => asNumber(result.rows[0]?.count);
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Modal, useOverlayState } from '@heroui/react';
|
|
2
2
|
import { AlertTriangle, Trash2 } from 'lucide-react';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
SqliteModalCloseButton,
|
|
6
|
-
sqliteSecondaryButtonClassName,
|
|
7
|
-
} from './sqlite-modal-controls';
|
|
4
|
+
import { SqliteModalCloseButton, sqliteSecondaryButtonClassName } from './sqlite-modal-controls';
|
|
8
5
|
|
|
9
6
|
type SqliteRowDeleteModalProps = {
|
|
10
7
|
isOpen: boolean;
|
|
@@ -50,9 +47,7 @@ export const SqliteRowDeleteModal = ({
|
|
|
50
47
|
await onDelete();
|
|
51
48
|
onClose();
|
|
52
49
|
} catch (nextError) {
|
|
53
|
-
setError(
|
|
54
|
-
nextError instanceof Error ? nextError.message : String(nextError),
|
|
55
|
-
);
|
|
50
|
+
setError(nextError instanceof Error ? nextError.message : String(nextError));
|
|
56
51
|
} finally {
|
|
57
52
|
setDeleting(false);
|
|
58
53
|
}
|
|
@@ -76,9 +71,7 @@ export const SqliteRowDeleteModal = ({
|
|
|
76
71
|
<AlertTriangle aria-hidden="true" className="h-5 w-5" />
|
|
77
72
|
</div>
|
|
78
73
|
<div>
|
|
79
|
-
<h2 className="text-lg font-semibold text-white">
|
|
80
|
-
Delete Row {rowNumber}
|
|
81
|
-
</h2>
|
|
74
|
+
<h2 className="text-lg font-semibold text-white">Delete Row {rowNumber}</h2>
|
|
82
75
|
<p className="mt-1 text-sm text-slate-400">{entityName}</p>
|
|
83
76
|
</div>
|
|
84
77
|
</div>
|
|
@@ -88,8 +81,8 @@ export const SqliteRowDeleteModal = ({
|
|
|
88
81
|
<Modal.Body className="space-y-0 p-0">
|
|
89
82
|
<div className="space-y-5 px-5 py-5">
|
|
90
83
|
<p className="text-sm leading-6 text-slate-300">
|
|
91
|
-
This will permanently delete the selected row and immediately
|
|
92
|
-
|
|
84
|
+
This will permanently delete the selected row and immediately refetch the current
|
|
85
|
+
page.
|
|
93
86
|
</p>
|
|
94
87
|
|
|
95
88
|
{error ? (
|
|
@@ -74,10 +74,7 @@ const stringifyDraftValue = (value: unknown, kind: EditableValueKind) => {
|
|
|
74
74
|
return String(value);
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const createFieldDraft = (
|
|
78
|
-
column: SqliteColumnInfo,
|
|
79
|
-
value: unknown,
|
|
80
|
-
): EditableFieldDraft => {
|
|
77
|
+
const createFieldDraft = (column: SqliteColumnInfo, value: unknown): EditableFieldDraft => {
|
|
81
78
|
const compatibleKinds = getCompatibleValueKinds(column, value);
|
|
82
79
|
const kind = compatibleKinds[0] ?? 'text';
|
|
83
80
|
|
|
@@ -104,10 +101,7 @@ export const SqliteRowEditModal = ({
|
|
|
104
101
|
}
|
|
105
102
|
},
|
|
106
103
|
});
|
|
107
|
-
const primaryKeyColumns = useMemo(
|
|
108
|
-
() => getPrimaryKeyColumns(columns),
|
|
109
|
-
[columns],
|
|
110
|
-
);
|
|
104
|
+
const primaryKeyColumns = useMemo(() => getPrimaryKeyColumns(columns), [columns]);
|
|
111
105
|
const editableColumns = useMemo(() => getEditableColumns(columns), [columns]);
|
|
112
106
|
const [drafts, setDrafts] = useState<Record<string, EditableFieldDraft>>({});
|
|
113
107
|
const [submitting, setSubmitting] = useState(false);
|
|
@@ -123,10 +117,7 @@ export const SqliteRowEditModal = ({
|
|
|
123
117
|
|
|
124
118
|
setDrafts(
|
|
125
119
|
Object.fromEntries(
|
|
126
|
-
editableColumns.map((column) => [
|
|
127
|
-
column.name,
|
|
128
|
-
createFieldDraft(column, row[column.name]),
|
|
129
|
-
]),
|
|
120
|
+
editableColumns.map((column) => [column.name, createFieldDraft(column, row[column.name])]),
|
|
130
121
|
),
|
|
131
122
|
);
|
|
132
123
|
setSubmitting(false);
|
|
@@ -134,9 +125,7 @@ export const SqliteRowEditModal = ({
|
|
|
134
125
|
}, [editableColumns, isOpen, row]);
|
|
135
126
|
|
|
136
127
|
const handleKindChange = (columnName: string, kind: EditableValueKind) => {
|
|
137
|
-
const column = editableColumns.find(
|
|
138
|
-
(candidate) => candidate.name === columnName,
|
|
139
|
-
);
|
|
128
|
+
const column = editableColumns.find((candidate) => candidate.name === columnName);
|
|
140
129
|
|
|
141
130
|
setDrafts((current) => ({
|
|
142
131
|
...current,
|
|
@@ -151,16 +140,12 @@ export const SqliteRowEditModal = ({
|
|
|
151
140
|
? '{}'
|
|
152
141
|
: kind === 'null'
|
|
153
142
|
? ''
|
|
154
|
-
: kind === 'number' &&
|
|
155
|
-
current[columnName]?.rawValue === 'true'
|
|
143
|
+
: kind === 'number' && current[columnName]?.rawValue === 'true'
|
|
156
144
|
? '1'
|
|
157
|
-
: kind === 'number' &&
|
|
158
|
-
current[columnName]?.rawValue === 'false'
|
|
145
|
+
: kind === 'number' && current[columnName]?.rawValue === 'false'
|
|
159
146
|
? '0'
|
|
160
147
|
: (current[columnName]?.rawValue ??
|
|
161
|
-
(column
|
|
162
|
-
? createFieldDraft(column, null).rawValue
|
|
163
|
-
: '')),
|
|
148
|
+
(column ? createFieldDraft(column, null).rawValue : '')),
|
|
164
149
|
},
|
|
165
150
|
}));
|
|
166
151
|
};
|
|
@@ -186,9 +171,7 @@ export const SqliteRowEditModal = ({
|
|
|
186
171
|
await onSave(nextValues);
|
|
187
172
|
onClose();
|
|
188
173
|
} catch (nextError) {
|
|
189
|
-
setError(
|
|
190
|
-
nextError instanceof Error ? nextError.message : String(nextError),
|
|
191
|
-
);
|
|
174
|
+
setError(nextError instanceof Error ? nextError.message : String(nextError));
|
|
192
175
|
} finally {
|
|
193
176
|
setSubmitting(false);
|
|
194
177
|
}
|
|
@@ -210,9 +193,7 @@ export const SqliteRowEditModal = ({
|
|
|
210
193
|
<div>
|
|
211
194
|
<div className="flex items-center gap-2">
|
|
212
195
|
<Pencil aria-hidden="true" className="h-4 w-4 text-sky-300" />
|
|
213
|
-
<h2 className="text-lg font-semibold text-white">
|
|
214
|
-
Edit Row {rowNumber}
|
|
215
|
-
</h2>
|
|
196
|
+
<h2 className="text-lg font-semibold text-white">Edit Row {rowNumber}</h2>
|
|
216
197
|
</div>
|
|
217
198
|
<p className="mt-1 text-sm text-slate-400">{entityName}</p>
|
|
218
199
|
</div>
|
|
@@ -224,12 +205,9 @@ export const SqliteRowEditModal = ({
|
|
|
224
205
|
{primaryKeyColumns.length > 0 ? (
|
|
225
206
|
<section className="space-y-3">
|
|
226
207
|
<div>
|
|
227
|
-
<h3 className="text-sm font-medium text-slate-200">
|
|
228
|
-
Row Identifier
|
|
229
|
-
</h3>
|
|
208
|
+
<h3 className="text-sm font-medium text-slate-200">Row Identifier</h3>
|
|
230
209
|
<p className="mt-1 text-xs text-slate-400">
|
|
231
|
-
Primary-key fields are shown for reference and cannot be
|
|
232
|
-
edited.
|
|
210
|
+
Primary-key fields are shown for reference and cannot be edited.
|
|
233
211
|
</p>
|
|
234
212
|
</div>
|
|
235
213
|
<div className="grid gap-3 md:grid-cols-2">
|
|
@@ -240,16 +218,12 @@ export const SqliteRowEditModal = ({
|
|
|
240
218
|
>
|
|
241
219
|
<div className="flex items-center justify-between gap-3">
|
|
242
220
|
<div>
|
|
243
|
-
<p className="text-sm font-medium text-white">
|
|
244
|
-
{column.name}
|
|
245
|
-
</p>
|
|
221
|
+
<p className="text-sm font-medium text-white">{column.name}</p>
|
|
246
222
|
<p className="text-xs uppercase tracking-[0.24em] text-slate-500">
|
|
247
223
|
{column.type || 'value'}
|
|
248
224
|
</p>
|
|
249
225
|
</div>
|
|
250
|
-
<span className="sqlite-chip sqlite-chip-static">
|
|
251
|
-
PK
|
|
252
|
-
</span>
|
|
226
|
+
<span className="sqlite-chip sqlite-chip-static">PK</span>
|
|
253
227
|
</div>
|
|
254
228
|
<p className="mt-3 break-all font-mono text-sm text-slate-200">
|
|
255
229
|
{getValuePreview(row?.[column.name])}
|
|
@@ -265,36 +239,27 @@ export const SqliteRowEditModal = ({
|
|
|
265
239
|
|
|
266
240
|
<section className="space-y-3">
|
|
267
241
|
<div>
|
|
268
|
-
<h3 className="text-sm font-medium text-slate-200">
|
|
269
|
-
Editable Values
|
|
270
|
-
</h3>
|
|
242
|
+
<h3 className="text-sm font-medium text-slate-200">Editable Values</h3>
|
|
271
243
|
<p className="mt-1 text-xs text-slate-400">
|
|
272
|
-
Update any non-primary-key column and save to write the
|
|
273
|
-
row back to SQLite.
|
|
244
|
+
Update any non-primary-key column and save to write the row back to SQLite.
|
|
274
245
|
</p>
|
|
275
246
|
</div>
|
|
276
247
|
|
|
277
248
|
{editableColumns.length === 0 ? (
|
|
278
249
|
<div className="rounded-2xl border border-white/8 bg-white/[0.03] p-4 text-sm text-slate-300">
|
|
279
|
-
This row does not expose editable, non-primary-key
|
|
280
|
-
columns.
|
|
250
|
+
This row does not expose editable, non-primary-key columns.
|
|
281
251
|
</div>
|
|
282
252
|
) : (
|
|
283
253
|
<div className="space-y-4">
|
|
284
254
|
{editableColumns.map((column) => {
|
|
285
255
|
const draft =
|
|
286
|
-
drafts[column.name] ??
|
|
287
|
-
|
|
288
|
-
const compatibleKinds = getCompatibleValueKinds(
|
|
289
|
-
column,
|
|
290
|
-
row?.[column.name],
|
|
291
|
-
);
|
|
256
|
+
drafts[column.name] ?? createFieldDraft(column, row?.[column.name]);
|
|
257
|
+
const compatibleKinds = getCompatibleValueKinds(column, row?.[column.name]);
|
|
292
258
|
const allowNull = canColumnBeNull(column);
|
|
293
259
|
const shouldUseTextArea =
|
|
294
260
|
draft.kind === 'blob-ish' ||
|
|
295
261
|
draft.kind === 'json' ||
|
|
296
|
-
(draft.kind === 'text' &&
|
|
297
|
-
draft.rawValue.includes('\n'));
|
|
262
|
+
(draft.kind === 'text' && draft.rawValue.includes('\n'));
|
|
298
263
|
|
|
299
264
|
return (
|
|
300
265
|
<div
|
|
@@ -347,9 +312,7 @@ export const SqliteRowEditModal = ({
|
|
|
347
312
|
: 'Text'}
|
|
348
313
|
</option>
|
|
349
314
|
))}
|
|
350
|
-
{allowNull ?
|
|
351
|
-
<option value="null">NULL</option>
|
|
352
|
-
) : null}
|
|
315
|
+
{allowNull ? <option value="null">NULL</option> : null}
|
|
353
316
|
</select>
|
|
354
317
|
</div>
|
|
355
318
|
) : (
|
|
@@ -428,16 +391,11 @@ export const SqliteRowEditModal = ({
|
|
|
428
391
|
</div>
|
|
429
392
|
|
|
430
393
|
<p className="mt-2 text-xs text-slate-500">
|
|
431
|
-
Current value:{
|
|
432
|
-
{getValuePreview(row?.[column.name])} (
|
|
394
|
+
Current value: {getValuePreview(row?.[column.name])} (
|
|
433
395
|
{getValueKind(row?.[column.name])}) · Compatible:{' '}
|
|
434
396
|
{compatibleKinds
|
|
435
397
|
.map((kind) =>
|
|
436
|
-
kind === 'blob-ish'
|
|
437
|
-
? 'blob'
|
|
438
|
-
: kind === 'json'
|
|
439
|
-
? 'json'
|
|
440
|
-
: kind,
|
|
398
|
+
kind === 'blob-ish' ? 'blob' : kind === 'json' ? 'json' : kind,
|
|
441
399
|
)
|
|
442
400
|
.join(', ')}
|
|
443
401
|
{allowNull ? ', null' : ''}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
export type EditableValueKind =
|
|
2
|
-
| 'null'
|
|
3
|
-
| 'text'
|
|
4
|
-
| 'number'
|
|
5
|
-
| 'boolean'
|
|
6
|
-
| 'blob-ish'
|
|
7
|
-
| 'json';
|
|
1
|
+
export type EditableValueKind = 'null' | 'text' | 'number' | 'boolean' | 'blob-ish' | 'json';
|
|
8
2
|
|
|
9
3
|
export type EditableFieldDraft = {
|
|
10
4
|
kind: EditableValueKind;
|
|
@@ -36,10 +30,7 @@ export const parseEditableFieldValue = (draft: EditableFieldDraft): unknown => {
|
|
|
36
30
|
case 'blob-ish': {
|
|
37
31
|
const parsed = JSON.parse(draft.rawValue);
|
|
38
32
|
|
|
39
|
-
if (
|
|
40
|
-
!Array.isArray(parsed) ||
|
|
41
|
-
!parsed.every((item) => typeof item === 'number')
|
|
42
|
-
) {
|
|
33
|
+
if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === 'number')) {
|
|
43
34
|
throw new Error('Blob values must be JSON arrays of numbers.');
|
|
44
35
|
}
|
|
45
36
|
|
|
@@ -9,12 +9,7 @@ const SQLITE_ROWID_IDENTIFIERS = ['rowid', '_rowid_', 'oid'] as const;
|
|
|
9
9
|
|
|
10
10
|
export type SqliteRowIdIdentifier = (typeof SQLITE_ROWID_IDENTIFIERS)[number];
|
|
11
11
|
|
|
12
|
-
export type SqliteEditableValueKind =
|
|
13
|
-
| 'text'
|
|
14
|
-
| 'number'
|
|
15
|
-
| 'boolean'
|
|
16
|
-
| 'blob-ish'
|
|
17
|
-
| 'json';
|
|
12
|
+
export type SqliteEditableValueKind = 'text' | 'number' | 'boolean' | 'blob-ish' | 'json';
|
|
18
13
|
|
|
19
14
|
export type SqliteRowMutationDescriptor =
|
|
20
15
|
| {
|
|
@@ -57,16 +52,11 @@ export const getPrimaryKeyColumns = (columns: SqliteColumnInfo[]) =>
|
|
|
57
52
|
.sort((left, right) => left.primaryKeyOrder - right.primaryKeyOrder);
|
|
58
53
|
|
|
59
54
|
export const getEditableColumns = (columns: SqliteColumnInfo[]) =>
|
|
60
|
-
columns.filter(
|
|
61
|
-
(column) => column.primaryKeyOrder === 0 && column.hidden === 0,
|
|
62
|
-
);
|
|
55
|
+
columns.filter((column) => column.primaryKeyOrder === 0 && column.hidden === 0);
|
|
63
56
|
|
|
64
|
-
const getNormalizedColumnType = (column: SqliteColumnInfo) =>
|
|
65
|
-
column.type.trim().toLowerCase();
|
|
57
|
+
const getNormalizedColumnType = (column: SqliteColumnInfo) => column.type.trim().toLowerCase();
|
|
66
58
|
|
|
67
|
-
const inferValueKindFromRuntimeValue = (
|
|
68
|
-
value: unknown,
|
|
69
|
-
): SqliteEditableValueKind => {
|
|
59
|
+
const inferValueKindFromRuntimeValue = (value: unknown): SqliteEditableValueKind => {
|
|
70
60
|
if (typeof value === 'number') {
|
|
71
61
|
return 'number';
|
|
72
62
|
}
|
|
@@ -76,9 +66,7 @@ const inferValueKindFromRuntimeValue = (
|
|
|
76
66
|
}
|
|
77
67
|
|
|
78
68
|
if (Array.isArray(value)) {
|
|
79
|
-
return value.every((item) => typeof item === 'number')
|
|
80
|
-
? 'blob-ish'
|
|
81
|
-
: 'json';
|
|
69
|
+
return value.every((item) => typeof item === 'number') ? 'blob-ish' : 'json';
|
|
82
70
|
}
|
|
83
71
|
|
|
84
72
|
if (value && typeof value === 'object') {
|
|
@@ -135,14 +123,10 @@ export const canColumnBeNull = (column: SqliteColumnInfo) => !column.notNull;
|
|
|
135
123
|
export const getAvailableRowIdIdentifier = (
|
|
136
124
|
columns: SqliteColumnInfo[],
|
|
137
125
|
): SqliteRowIdIdentifier | null => {
|
|
138
|
-
const lowerCaseColumnNames = new Set(
|
|
139
|
-
columns.map((column) => column.name.toLowerCase()),
|
|
140
|
-
);
|
|
126
|
+
const lowerCaseColumnNames = new Set(columns.map((column) => column.name.toLowerCase()));
|
|
141
127
|
|
|
142
128
|
return (
|
|
143
|
-
SQLITE_ROWID_IDENTIFIERS.find(
|
|
144
|
-
(identifier) => !lowerCaseColumnNames.has(identifier),
|
|
145
|
-
) ?? null
|
|
129
|
+
SQLITE_ROWID_IDENTIFIERS.find((identifier) => !lowerCaseColumnNames.has(identifier)) ?? null
|
|
146
130
|
);
|
|
147
131
|
};
|
|
148
132
|
|
|
@@ -182,9 +166,7 @@ const buildWhereClause = (
|
|
|
182
166
|
descriptor: SqliteRowMutationDescriptor,
|
|
183
167
|
) => {
|
|
184
168
|
if (descriptor.mode === 'primary-key') {
|
|
185
|
-
const params = descriptor.primaryKeyColumns.map(
|
|
186
|
-
(column) => row[column.name],
|
|
187
|
-
);
|
|
169
|
+
const params = descriptor.primaryKeyColumns.map((column) => row[column.name]);
|
|
188
170
|
const clause = descriptor.primaryKeyColumns
|
|
189
171
|
.map((column) => `${quoteSqlIdentifier(column.name)} = ?`)
|
|
190
172
|
.join(' AND ');
|
|
@@ -210,9 +192,7 @@ export const buildRowUpdateMutation = ({
|
|
|
210
192
|
}: BuildRowUpdateMutationInput): SqliteMutationResult => {
|
|
211
193
|
const updateColumnNames = getEditableColumns(columns)
|
|
212
194
|
.map((column) => column.name)
|
|
213
|
-
.filter((columnName) =>
|
|
214
|
-
Object.prototype.hasOwnProperty.call(nextValues, columnName),
|
|
215
|
-
);
|
|
195
|
+
.filter((columnName) => Object.prototype.hasOwnProperty.call(nextValues, columnName));
|
|
216
196
|
|
|
217
197
|
if (updateColumnNames.length === 0) {
|
|
218
198
|
throw new Error('No editable columns are available for this row.');
|
|
@@ -221,9 +201,7 @@ export const buildRowUpdateMutation = ({
|
|
|
221
201
|
const assignments = updateColumnNames.map(
|
|
222
202
|
(columnName) => `${quoteSqlIdentifier(columnName)} = ?`,
|
|
223
203
|
);
|
|
224
|
-
const assignmentParams = updateColumnNames.map(
|
|
225
|
-
(columnName) => nextValues[columnName],
|
|
226
|
-
);
|
|
204
|
+
const assignmentParams = updateColumnNames.map((columnName) => nextValues[columnName]);
|
|
227
205
|
const where = buildWhereClause(row, descriptor);
|
|
228
206
|
|
|
229
207
|
return {
|
|
@@ -17,13 +17,8 @@ type ReorderTableColumnOrderInput = NormalizeTableColumnOrderInput & {
|
|
|
17
17
|
overColumnId: string;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const applyUpdater = <TValue>(
|
|
21
|
-
updater:
|
|
22
|
-
currentValue: TValue,
|
|
23
|
-
): TValue =>
|
|
24
|
-
typeof updater === 'function'
|
|
25
|
-
? (updater as (old: TValue) => TValue)(currentValue)
|
|
26
|
-
: updater;
|
|
20
|
+
const applyUpdater = <TValue>(updater: Updater<TValue>, currentValue: TValue): TValue =>
|
|
21
|
+
typeof updater === 'function' ? (updater as (old: TValue) => TValue)(currentValue) : updater;
|
|
27
22
|
|
|
28
23
|
export const getDefaultTableColumnOrder = (
|
|
29
24
|
columnIds: string[],
|
|
@@ -95,9 +90,7 @@ export const reorderTableColumnOrder = ({
|
|
|
95
90
|
return normalizedOrder;
|
|
96
91
|
}
|
|
97
92
|
|
|
98
|
-
const movableColumnOrder = normalizedOrder.filter(
|
|
99
|
-
(columnId) => !fixedColumnIds.has(columnId),
|
|
100
|
-
);
|
|
93
|
+
const movableColumnOrder = normalizedOrder.filter((columnId) => !fixedColumnIds.has(columnId));
|
|
101
94
|
const activeIndex = movableColumnOrder.indexOf(activeColumnId);
|
|
102
95
|
const overIndex = movableColumnOrder.indexOf(overColumnId);
|
|
103
96
|
|
|
@@ -131,24 +124,16 @@ export const resolveTableColumnOrderUpdate = ({
|
|
|
131
124
|
});
|
|
132
125
|
};
|
|
133
126
|
|
|
134
|
-
export const areColumnOrdersEqual = (
|
|
135
|
-
leftColumnOrder: string[],
|
|
136
|
-
rightColumnOrder: string[],
|
|
137
|
-
) =>
|
|
127
|
+
export const areColumnOrdersEqual = (leftColumnOrder: string[], rightColumnOrder: string[]) =>
|
|
138
128
|
leftColumnOrder.length === rightColumnOrder.length &&
|
|
139
|
-
leftColumnOrder.every(
|
|
140
|
-
(columnId, columnIndex) => columnId === rightColumnOrder[columnIndex],
|
|
141
|
-
);
|
|
129
|
+
leftColumnOrder.every((columnId, columnIndex) => columnId === rightColumnOrder[columnIndex]);
|
|
142
130
|
|
|
143
131
|
export const buildEntityTableId = (
|
|
144
132
|
scope: 'data' | 'structure-columns' | 'structure-indexes',
|
|
145
133
|
databaseId: string | null,
|
|
146
134
|
schemaName: string | null,
|
|
147
135
|
entityName: string | null,
|
|
148
|
-
) =>
|
|
149
|
-
`${scope}:${databaseId ?? 'unknown'}:${schemaName ?? 'unknown'}:${entityName ?? 'unknown'}`;
|
|
136
|
+
) => `${scope}:${databaseId ?? 'unknown'}:${schemaName ?? 'unknown'}:${entityName ?? 'unknown'}`;
|
|
150
137
|
|
|
151
|
-
export const buildQueryTableId = (
|
|
152
|
-
databaseId
|
|
153
|
-
columnIds: string[],
|
|
154
|
-
) => `query:${databaseId ?? 'unknown'}:${JSON.stringify(columnIds)}`;
|
|
138
|
+
export const buildQueryTableId = (databaseId: string | null, columnIds: string[]) =>
|
|
139
|
+
`query:${databaseId ?? 'unknown'}:${JSON.stringify(columnIds)}`;
|