@edge-base/server 0.2.0 → 0.2.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.
- package/admin-build/_app/immutable/assets/19.4Si2ZFC_.css +1 -0
- package/admin-build/_app/immutable/assets/{3.Dg81Pgmd.css → 3.BtHYobTg.css} +1 -1
- package/admin-build/_app/immutable/assets/SqlEditor.Bbp1RIk0.css +1 -0
- package/admin-build/_app/immutable/assets/TableSqlTab.yeNZfhgG.css +1 -0
- package/admin-build/_app/immutable/chunks/B0QyxC2M.js +128 -0
- package/admin-build/_app/immutable/chunks/{DpuSetmN.js → BCKr7yKd.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BSfSfeDG.js → BFs_qStz.js} +1 -1
- package/admin-build/_app/immutable/chunks/{D43CH5ty.js → BTJcQFEp.js} +1 -1
- package/admin-build/_app/immutable/chunks/BY07qVPA.js +1 -0
- package/admin-build/_app/immutable/chunks/{mD4EETH_.js → BcIUK2sk.js} +1 -1
- package/admin-build/_app/immutable/chunks/{DgxOZ3uv.js → BsFiK_FJ.js} +1 -1
- package/admin-build/_app/immutable/chunks/{CN6aakgF.js → CSGrwS7E.js} +1 -1
- package/admin-build/_app/immutable/chunks/{B14gOIqE.js → CqUxCvs_.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BKLsgaNT.js → D-x55wdW.js} +1 -1
- package/admin-build/_app/immutable/chunks/{CfPHB4r5.js → D755Tqat.js} +1 -1
- package/admin-build/_app/immutable/chunks/{cqSkc6KP.js → DjOEv9M9.js} +1 -1
- package/admin-build/_app/immutable/chunks/{DP9kmlCd.js → DnLqc9L1.js} +1 -1
- package/admin-build/_app/immutable/chunks/{B-WlnirM.js → Dqk2TGNU.js} +1 -1
- package/admin-build/_app/immutable/chunks/{2nyN5wuZ.js → k0CIJkw4.js} +1 -1
- package/admin-build/_app/immutable/chunks/lSpxLU5p.js +2 -0
- package/admin-build/_app/immutable/chunks/{uboHVq-x.js → m9QZTyVV.js} +1 -1
- package/admin-build/_app/immutable/entry/{app.Dc071f6C.js → app.BTsq3_xq.js} +2 -2
- package/admin-build/_app/immutable/entry/start.zXCirpgY.js +1 -0
- package/admin-build/_app/immutable/nodes/0.BZ00WDYH.js +1 -0
- package/admin-build/_app/immutable/nodes/{1.rMaczUKT.js → 1.RzSJ3yyr.js} +1 -1
- package/admin-build/_app/immutable/nodes/{10.DIOlO4hv.js → 10.D-rsiquF.js} +1 -1
- package/admin-build/_app/immutable/nodes/{11.WxD9E0Eq.js → 11.l7-bgtFD.js} +1 -1
- package/admin-build/_app/immutable/nodes/{12.CNcefK3l.js → 12.Dkq0H7B5.js} +1 -1
- package/admin-build/_app/immutable/nodes/{13.aAWsqDdR.js → 13.DtK_4oRz.js} +1 -1
- package/admin-build/_app/immutable/nodes/{14.C9hdr3EN.js → 14.BKo7-AMx.js} +1 -1
- package/admin-build/_app/immutable/nodes/{15.43r5uVx5.js → 15.CQAj_6lq.js} +1 -1
- package/admin-build/_app/immutable/nodes/{16.D519948J.js → 16.XVIG-Ffr.js} +1 -1
- package/admin-build/_app/immutable/nodes/{17.ks4I4yoH.js → 17.g6raZLCM.js} +1 -1
- package/admin-build/_app/immutable/nodes/{18.ZuNm22dY.js → 18.IQz6a3T6.js} +1 -1
- package/admin-build/_app/immutable/nodes/19.CAAZ8i8h.js +2 -0
- package/admin-build/_app/immutable/nodes/{20.C9ASlwCn.js → 20.BPcX3KPj.js} +1 -1
- package/admin-build/_app/immutable/nodes/21.DoPabrY_.js +1 -0
- package/admin-build/_app/immutable/nodes/{22.6k8cg0Pr.js → 22.Br5AG_5Z.js} +1 -1
- package/admin-build/_app/immutable/nodes/{23.B9hcFTU-.js → 23.KjbrdXoE.js} +1 -1
- package/admin-build/_app/immutable/nodes/{24.OsQM9QtS.js → 24.C3n2-hgw.js} +1 -1
- package/admin-build/_app/immutable/nodes/{25.ClwkdaPp.js → 25.SFDSBzHd.js} +1 -1
- package/admin-build/_app/immutable/nodes/26.D95vui6E.js +1 -0
- package/admin-build/_app/immutable/nodes/{27.J1QASB3b.js → 27.FgLgdjwB.js} +1 -1
- package/admin-build/_app/immutable/nodes/{28.BKP1tVcZ.js → 28.B9sYYm1F.js} +1 -1
- package/admin-build/_app/immutable/nodes/{29.mqIe62On.js → 29.DyqZ_wbN.js} +1 -1
- package/admin-build/_app/immutable/nodes/3.Bzo2yVIO.js +2 -0
- package/admin-build/_app/immutable/nodes/{30.BRk-4B3j.js → 30.c1CiNwiS.js} +1 -1
- package/admin-build/_app/immutable/nodes/{31.BBqGNVXN.js → 31.CXty66Vh.js} +1 -1
- package/admin-build/_app/immutable/nodes/{4.Bi91lv2V.js → 4.BgQaXZ27.js} +1 -1
- package/admin-build/_app/immutable/nodes/{5.BumjsbNK.js → 5.BuJrHvxH.js} +1 -1
- package/admin-build/_app/immutable/nodes/{6.CMTP_7xN.js → 6.CkBBC94k.js} +1 -1
- package/admin-build/_app/immutable/nodes/{7.4T4wo7Kg.js → 7.D2YBvNFM.js} +1 -1
- package/admin-build/_app/immutable/nodes/{8.MUZQPNsN.js → 8.D8qQWo_z.js} +1 -1
- package/admin-build/_app/immutable/nodes/{9.3SV00WXe.js → 9.BLDLX5hV.js} +1 -1
- package/admin-build/_app/version.json +1 -1
- package/admin-build/index.html +7 -7
- package/package.json +2 -2
- package/src/__tests__/pagination.test.ts +12 -8
- package/src/__tests__/postgres-dialect.test.ts +2 -2
- package/src/__tests__/query.test.ts +7 -7
- package/src/durable-objects/database-do.ts +3 -3
- package/src/durable-objects/logs-do.ts +2 -2
- package/src/lib/auth-d1-service.ts +1 -1
- package/src/lib/auth-d1.ts +10 -0
- package/src/lib/d1-handler.ts +23 -4
- package/src/lib/pagination.ts +3 -3
- package/src/lib/postgres-handler.ts +2 -2
- package/src/lib/query-engine.ts +2 -2
- package/src/middleware/rate-limit.ts +11 -11
- package/src/routes/admin.ts +2 -2
- package/src/routes/auth.ts +7 -0
- package/admin-build/_app/immutable/assets/TableSqlTab.BHquaMBM.css +0 -1
- package/admin-build/_app/immutable/chunks/CkdaVlhQ.js +0 -2
- package/admin-build/_app/immutable/chunks/D8Nrx_IG.js +0 -128
- package/admin-build/_app/immutable/entry/start.Bhlxoqtt.js +0 -1
- package/admin-build/_app/immutable/nodes/0.CCfcYVV2.js +0 -1
- package/admin-build/_app/immutable/nodes/19.D519948J.js +0 -1
- package/admin-build/_app/immutable/nodes/21.BhSD2EfX.js +0 -1
- package/admin-build/_app/immutable/nodes/26._-65WG0q.js +0 -1
- package/admin-build/_app/immutable/nodes/3.WkDZWDQC.js +0 -2
package/admin-build/index.html
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>EdgeBase Admin</title>
|
|
7
7
|
<link rel="icon" href="/admin/favicon.svg" type="image/svg+xml" />
|
|
8
|
-
<link href="/admin/_app/immutable/entry/start.
|
|
9
|
-
<link href="/admin/_app/immutable/chunks/
|
|
8
|
+
<link href="/admin/_app/immutable/entry/start.zXCirpgY.js" rel="modulepreload">
|
|
9
|
+
<link href="/admin/_app/immutable/chunks/m9QZTyVV.js" rel="modulepreload">
|
|
10
10
|
<link href="/admin/_app/immutable/chunks/BdTBlfLy.js" rel="modulepreload">
|
|
11
11
|
<link href="/admin/_app/immutable/chunks/Bn2NtlTj.js" rel="modulepreload">
|
|
12
|
-
<link href="/admin/_app/immutable/chunks/
|
|
13
|
-
<link href="/admin/_app/immutable/entry/app.
|
|
12
|
+
<link href="/admin/_app/immutable/chunks/D755Tqat.js" rel="modulepreload">
|
|
13
|
+
<link href="/admin/_app/immutable/entry/app.BTsq3_xq.js" rel="modulepreload">
|
|
14
14
|
<link href="/admin/_app/immutable/chunks/B2bEC_Hm.js" rel="modulepreload">
|
|
15
15
|
<link href="/admin/_app/immutable/chunks/Bb0e0sAP.js" rel="modulepreload">
|
|
16
16
|
<link href="/admin/_app/immutable/chunks/DtZk82gG.js" rel="modulepreload">
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div style="display: contents">
|
|
27
27
|
<script>
|
|
28
28
|
{
|
|
29
|
-
|
|
29
|
+
__sveltekit_1vwf6db = {
|
|
30
30
|
base: "/admin",
|
|
31
31
|
assets: "/admin"
|
|
32
32
|
};
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
const element = document.currentScript.parentElement;
|
|
35
35
|
|
|
36
36
|
Promise.all([
|
|
37
|
-
import("/admin/_app/immutable/entry/start.
|
|
38
|
-
import("/admin/_app/immutable/entry/app.
|
|
37
|
+
import("/admin/_app/immutable/entry/start.zXCirpgY.js"),
|
|
38
|
+
import("/admin/_app/immutable/entry/app.BTsq3_xq.js")
|
|
39
39
|
]).then(([kit, app]) => {
|
|
40
40
|
kit.start(app, element);
|
|
41
41
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edge-base/server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "EdgeBase runtime assets consumed by the EdgeBase CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"jose": "^6.0.0",
|
|
35
35
|
"pg": "^8.16.3",
|
|
36
36
|
"zod": "^4.3.6",
|
|
37
|
-
"@edge-base/shared": "0.2.
|
|
37
|
+
"@edge-base/shared": "0.2.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@cloudflare/vitest-pool-workers": "^0.8.71",
|
|
@@ -10,7 +10,7 @@ import { parsePagination } from '../lib/pagination.js';
|
|
|
10
10
|
describe('parsePagination', () => {
|
|
11
11
|
// ── Defaults ──
|
|
12
12
|
it('returns defaults when no params provided', () => {
|
|
13
|
-
expect(parsePagination(undefined, undefined)).toEqual({ limit:
|
|
13
|
+
expect(parsePagination(undefined, undefined)).toEqual({ limit: 100, offset: 0 });
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
// ── Valid values ──
|
|
@@ -23,21 +23,25 @@ describe('parsePagination', () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
// ── Limit clamping ──
|
|
26
|
-
it('clamps limit to
|
|
27
|
-
expect(parsePagination('
|
|
26
|
+
it('clamps limit to 1000', () => {
|
|
27
|
+
expect(parsePagination('9999', '0')).toEqual({ limit: 1000, offset: 0 });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('accepts limit within range (500)', () => {
|
|
31
|
+
expect(parsePagination('500', '0')).toEqual({ limit: 500, offset: 0 });
|
|
28
32
|
});
|
|
29
33
|
|
|
30
34
|
it('rejects limit=0 (falls back to default)', () => {
|
|
31
|
-
expect(parsePagination('0', '0')).toEqual({ limit:
|
|
35
|
+
expect(parsePagination('0', '0')).toEqual({ limit: 100, offset: 0 });
|
|
32
36
|
});
|
|
33
37
|
|
|
34
38
|
// ── REGRESSION: negative and NaN values ──
|
|
35
39
|
it('rejects negative limit', () => {
|
|
36
|
-
expect(parsePagination('-5', '0')).toEqual({ limit:
|
|
40
|
+
expect(parsePagination('-5', '0')).toEqual({ limit: 100, offset: 0 });
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
it('rejects NaN limit', () => {
|
|
40
|
-
expect(parsePagination('abc', '0')).toEqual({ limit:
|
|
44
|
+
expect(parsePagination('abc', '0')).toEqual({ limit: 100, offset: 0 });
|
|
41
45
|
});
|
|
42
46
|
|
|
43
47
|
it('rejects negative offset', () => {
|
|
@@ -49,11 +53,11 @@ describe('parsePagination', () => {
|
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
it('rejects Infinity limit', () => {
|
|
52
|
-
expect(parsePagination('Infinity', '0')).toEqual({ limit:
|
|
56
|
+
expect(parsePagination('Infinity', '0')).toEqual({ limit: 100, offset: 0 });
|
|
53
57
|
});
|
|
54
58
|
|
|
55
59
|
// ── Empty string (same as undefined) ──
|
|
56
60
|
it('treats empty strings as defaults', () => {
|
|
57
|
-
expect(parsePagination('', '')).toEqual({ limit:
|
|
61
|
+
expect(parsePagination('', '')).toEqual({ limit: 100, offset: 0 });
|
|
58
62
|
});
|
|
59
63
|
});
|
|
@@ -43,7 +43,7 @@ describe('PostgreSQL dialect — bind params', () => {
|
|
|
43
43
|
const { sql, params } = buildListQuery('products', {}, 'postgres');
|
|
44
44
|
expect(sql).toContain('LIMIT $1');
|
|
45
45
|
expect(sql).not.toContain('?');
|
|
46
|
-
expect(params).toEqual([
|
|
46
|
+
expect(params).toEqual([100]);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it('buildListQuery with offset → $1 OFFSET $2', () => {
|
|
@@ -71,7 +71,7 @@ describe('PostgreSQL dialect — bind params', () => {
|
|
|
71
71
|
expect(sql).toContain('"status" = $1');
|
|
72
72
|
expect(sql).toContain('"price" > $2');
|
|
73
73
|
expect(sql).toContain('LIMIT $3');
|
|
74
|
-
expect(params).toEqual(['active', 100,
|
|
74
|
+
expect(params).toEqual(['active', 100, 100]);
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it('buildListQuery cursor after → $1 for cursor, $2 for limit', () => {
|
|
@@ -79,10 +79,10 @@ describe('buildListQuery — no filters', () => {
|
|
|
79
79
|
expect(sql).toContain('LIMIT');
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
it('default limit is
|
|
82
|
+
it('default limit is 100', () => {
|
|
83
83
|
const { params } = buildListQuery('posts', {});
|
|
84
|
-
// params should contain
|
|
85
|
-
expect(params).toContain(
|
|
84
|
+
// params should contain 100 as default limit
|
|
85
|
+
expect(params).toContain(100);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
it('generates countSql for non-cursor pagination', () => {
|
|
@@ -313,9 +313,9 @@ describe('buildSearchQuery', () => {
|
|
|
313
313
|
expect(sql).toContain('"posts_fts"');
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
-
it('default limit
|
|
316
|
+
it('default limit 100, offset 0', () => {
|
|
317
317
|
const { params } = buildSearchQuery('posts', 'q');
|
|
318
|
-
expect(params[1]).toBe(
|
|
318
|
+
expect(params[1]).toBe(100);
|
|
319
319
|
expect(params[2]).toBeUndefined();
|
|
320
320
|
});
|
|
321
321
|
|
|
@@ -560,7 +560,7 @@ describe('3-way sync: QUERY_PARAM_KEYS ↔ Zod queryParamsSchema', () => {
|
|
|
560
560
|
describe('buildListQuery — exact params verification', () => {
|
|
561
561
|
it('no filters → params contains only default limit', () => {
|
|
562
562
|
const { params } = buildListQuery('t', {});
|
|
563
|
-
expect(params).toEqual([
|
|
563
|
+
expect(params).toEqual([100]);
|
|
564
564
|
});
|
|
565
565
|
|
|
566
566
|
it('no filters → countParams is empty array', () => {
|
|
@@ -722,7 +722,7 @@ describe('buildSubstringSearchQuery', () => {
|
|
|
722
722
|
const { sql, params } = buildSubstringSearchQuery('posts', '준규', { fields: ['title', 'content'] });
|
|
723
723
|
expect(sql).toContain('instr(lower(CAST("title" AS TEXT)), lower(?)) > 0');
|
|
724
724
|
expect(sql).toContain('instr(lower(CAST("content" AS TEXT)), lower(?)) > 0');
|
|
725
|
-
expect(params).toEqual(['준규', '준규',
|
|
725
|
+
expect(params).toEqual(['준규', '준규', 100]);
|
|
726
726
|
});
|
|
727
727
|
|
|
728
728
|
it('passes the raw term through the SQLite instr() fallback', () => {
|
|
@@ -470,7 +470,7 @@ export class DatabaseDO extends DurableObject<DOEnv> {
|
|
|
470
470
|
if (countSql && countParams) {
|
|
471
471
|
const countResult = [...this.sql(countSql, ...countParams)];
|
|
472
472
|
const total = (countResult[0]?.total as number) ?? 0;
|
|
473
|
-
const perPage = options.pagination?.perPage ?? options.pagination?.limit ??
|
|
473
|
+
const perPage = options.pagination?.perPage ?? options.pagination?.limit ?? 100;
|
|
474
474
|
response.total = total;
|
|
475
475
|
response.page = options.pagination?.page ?? 1;
|
|
476
476
|
response.perPage = perPage;
|
|
@@ -478,7 +478,7 @@ export class DatabaseDO extends DurableObject<DOEnv> {
|
|
|
478
478
|
|
|
479
479
|
// Cursor pagination: always include cursor and hasMore when items exist
|
|
480
480
|
// so clients can start cursor-based pagination from any page (including the first)
|
|
481
|
-
const limit = options.pagination?.limit ?? options.pagination?.perPage ??
|
|
481
|
+
const limit = options.pagination?.limit ?? options.pagination?.perPage ?? 100;
|
|
482
482
|
const hasMore = normalizedRows.length === limit;
|
|
483
483
|
response.hasMore = hasMore;
|
|
484
484
|
if (normalizedRows.length > 0) {
|
|
@@ -516,7 +516,7 @@ export class DatabaseDO extends DurableObject<DOEnv> {
|
|
|
516
516
|
return c.json({ items: [] });
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
-
const limit = options.pagination?.limit ?? options.pagination?.perPage ??
|
|
519
|
+
const limit = options.pagination?.limit ?? options.pagination?.perPage ?? 100;
|
|
520
520
|
const offset = options.pagination?.offset ?? ((options.pagination?.page ?? 1) - 1) * limit;
|
|
521
521
|
|
|
522
522
|
const tableConfig = this.getTableConfig(name);
|
|
@@ -484,10 +484,10 @@ export class LogsDO extends DurableObject<LogsDOEnv> {
|
|
|
484
484
|
whereParts.push('status >= ?');
|
|
485
485
|
params.push(SERVER_ERROR_STATUS);
|
|
486
486
|
} else if (level === 'warn') {
|
|
487
|
-
whereParts.push('status >= ? AND status < ?');
|
|
487
|
+
whereParts.push('(status >= ? AND status < ? AND status != 304)');
|
|
488
488
|
params.push(300, SERVER_ERROR_STATUS);
|
|
489
489
|
} else if (level === 'info') {
|
|
490
|
-
whereParts.push('status >= ? AND status < ?');
|
|
490
|
+
whereParts.push('(status >= ? AND status < ? OR status = 304)');
|
|
491
491
|
params.push(200, 300);
|
|
492
492
|
}
|
|
493
493
|
|
|
@@ -194,7 +194,7 @@ export async function updateUser(
|
|
|
194
194
|
'email', 'passwordHash', 'displayName', 'avatarUrl', 'emailVisibility',
|
|
195
195
|
'role', 'status', 'verified', 'isAnonymous', 'locale', 'metadata', 'appMetadata',
|
|
196
196
|
'customClaims', 'phone', 'phoneVerified', 'disabled', 'bannedUntil',
|
|
197
|
-
'lastSignInAt', 'updatedAt',
|
|
197
|
+
'lastSignInAt', 'lastSignedInAt', 'updatedAt',
|
|
198
198
|
]);
|
|
199
199
|
|
|
200
200
|
const sets: string[] = [];
|
package/src/lib/auth-d1.ts
CHANGED
|
@@ -125,6 +125,7 @@ CREATE TABLE IF NOT EXISTS _users (
|
|
|
125
125
|
disabled INTEGER DEFAULT 0,
|
|
126
126
|
status TEXT DEFAULT 'active',
|
|
127
127
|
locale TEXT DEFAULT 'en',
|
|
128
|
+
lastSignedInAt TEXT,
|
|
128
129
|
createdAt TEXT NOT NULL,
|
|
129
130
|
updatedAt TEXT NOT NULL
|
|
130
131
|
);
|
|
@@ -309,6 +310,7 @@ CREATE TABLE IF NOT EXISTS _users (
|
|
|
309
310
|
disabled INTEGER DEFAULT 0,
|
|
310
311
|
status TEXT DEFAULT 'active',
|
|
311
312
|
locale TEXT DEFAULT 'en',
|
|
313
|
+
lastSignedInAt TEXT,
|
|
312
314
|
createdAt TEXT NOT NULL,
|
|
313
315
|
updatedAt TEXT NOT NULL
|
|
314
316
|
);
|
|
@@ -403,6 +405,14 @@ export async function ensureAuthSchema(db: AuthDb): Promise<void> {
|
|
|
403
405
|
.filter((s) => s.length > 0);
|
|
404
406
|
|
|
405
407
|
await db.batch(statements.map((sql) => ({ sql })));
|
|
408
|
+
|
|
409
|
+
// Migrate existing _users tables: add lastSignedInAt if missing
|
|
410
|
+
try {
|
|
411
|
+
await db.run('ALTER TABLE _users ADD COLUMN lastSignedInAt TEXT', []);
|
|
412
|
+
} catch {
|
|
413
|
+
// Column already exists — safe to ignore
|
|
414
|
+
}
|
|
415
|
+
|
|
406
416
|
schemaInitialized = true;
|
|
407
417
|
}
|
|
408
418
|
|
package/src/lib/d1-handler.ts
CHANGED
|
@@ -399,8 +399,27 @@ async function handleList(
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
const queryOpts = parseQueryParams(Object.fromEntries(new URL(c.req.url).searchParams));
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
let query = buildListQuery(tableName, queryOpts, 'sqlite');
|
|
403
|
+
let result;
|
|
404
|
+
try {
|
|
405
|
+
result = await executeD1Query(resolved.db, query.sql, query.params);
|
|
406
|
+
} catch {
|
|
407
|
+
// FTS table may not exist — fall back to substring search
|
|
408
|
+
if (queryOpts.search) {
|
|
409
|
+
const searchFields = tableConfig.schema ? Object.keys(tableConfig.schema).filter(k => tableConfig.schema![k] !== false) : ['id'];
|
|
410
|
+
query = buildSubstringSearchQuery(tableName, queryOpts.search, {
|
|
411
|
+
pagination: queryOpts.pagination,
|
|
412
|
+
filters: queryOpts.filters,
|
|
413
|
+
orFilters: queryOpts.orFilters,
|
|
414
|
+
sort: queryOpts.sort,
|
|
415
|
+
fields: searchFields,
|
|
416
|
+
}, 'sqlite');
|
|
417
|
+
result = await executeD1Query(resolved.db, query.sql, query.params);
|
|
418
|
+
} else {
|
|
419
|
+
throw new Error('Query failed');
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const { countSql, countParams } = query;
|
|
404
423
|
|
|
405
424
|
// Apply read rules per row + normalize booleans/JSON
|
|
406
425
|
let items = result.rows.map(r => normalizeRow(stripInternalFields(r), tableConfig));
|
|
@@ -435,7 +454,7 @@ async function handleList(
|
|
|
435
454
|
total = Number(countResult.rows[0]?.total ?? 0);
|
|
436
455
|
}
|
|
437
456
|
|
|
438
|
-
const perPage = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ??
|
|
457
|
+
const perPage = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ?? 100;
|
|
439
458
|
const page = queryOpts.pagination?.page ?? 1;
|
|
440
459
|
// Always include cursor/hasMore like DO does — clients can start cursor pagination from any page
|
|
441
460
|
const hasMore = items.length === perPage;
|
|
@@ -497,7 +516,7 @@ async function handleSearch(
|
|
|
497
516
|
|
|
498
517
|
let items: Record<string, unknown>[];
|
|
499
518
|
let total = 0;
|
|
500
|
-
const limit = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ??
|
|
519
|
+
const limit = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ?? 100;
|
|
501
520
|
const offset = queryOpts.pagination?.offset ?? ((queryOpts.pagination?.page ?? 1) - 1) * limit;
|
|
502
521
|
const searchQuery = buildSearchQuery(tableName, searchTerm, {
|
|
503
522
|
pagination: queryOpts.pagination,
|
package/src/lib/pagination.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pagination parameter validation.
|
|
3
3
|
*
|
|
4
|
-
* Clamps limit to 1..
|
|
4
|
+
* Clamps limit to 1..1000 (default 100) and offset to ≥0 (default 0).
|
|
5
5
|
* Handles NaN, negative, and absurdly large values safely.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -9,8 +9,8 @@ export function parsePagination(
|
|
|
9
9
|
limitParam: string | undefined,
|
|
10
10
|
offsetParam: string | undefined,
|
|
11
11
|
): { limit: number; offset: number } {
|
|
12
|
-
const rawLimit = parseInt(limitParam || '
|
|
13
|
-
const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit,
|
|
12
|
+
const rawLimit = parseInt(limitParam || '100', 10);
|
|
13
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 1000) : 100;
|
|
14
14
|
|
|
15
15
|
const rawOffset = parseInt(offsetParam || '0', 10);
|
|
16
16
|
const offset = Number.isFinite(rawOffset) && rawOffset >= 0 ? rawOffset : 0;
|
|
@@ -365,7 +365,7 @@ async function handleList(
|
|
|
365
365
|
total = Number(countResult.rows[0]?.total ?? 0);
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
const perPage = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ??
|
|
368
|
+
const perPage = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ?? 100;
|
|
369
369
|
const page = queryOpts.pagination?.page ?? 1;
|
|
370
370
|
const hasMore = queryOpts.pagination?.after || queryOpts.pagination?.before
|
|
371
371
|
? items.length >= perPage
|
|
@@ -428,7 +428,7 @@ async function handleSearch(
|
|
|
428
428
|
const ftsFields = tableConfig.fts?.length
|
|
429
429
|
? tableConfig.fts
|
|
430
430
|
: getTextFields(tableConfig);
|
|
431
|
-
const limit = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ??
|
|
431
|
+
const limit = queryOpts.pagination?.limit ?? queryOpts.pagination?.perPage ?? 100;
|
|
432
432
|
const offset = queryOpts.pagination?.offset ?? ((queryOpts.pagination?.page ?? 1) - 1) * limit;
|
|
433
433
|
const searchQuery = buildSearchQuery(tableName, searchTerm, {
|
|
434
434
|
pagination: queryOpts.pagination,
|
package/src/lib/query-engine.ts
CHANGED
|
@@ -657,10 +657,10 @@ function buildLimitClause(
|
|
|
657
657
|
const _bt = bt ?? new BindTracker('sqlite');
|
|
658
658
|
|
|
659
659
|
if (!pagination) {
|
|
660
|
-
return { limitClause: `LIMIT ${_bt.next()}`, limitParams: [
|
|
660
|
+
return { limitClause: `LIMIT ${_bt.next()}`, limitParams: [100] }; // Default limit
|
|
661
661
|
}
|
|
662
662
|
|
|
663
|
-
const limit = pagination.limit ?? pagination.perPage ??
|
|
663
|
+
const limit = Math.min(pagination.limit ?? pagination.perPage ?? 100, 1000);
|
|
664
664
|
|
|
665
665
|
// Cursor-based: no offset
|
|
666
666
|
if (pagination.after || pagination.before) {
|
|
@@ -50,17 +50,17 @@ export const RATE_LIMIT_DEFAULTS: Record<string, { requests: number; windowSec:
|
|
|
50
50
|
events: { requests: 100, windowSec: 60 },
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
// Dev mode defaults:
|
|
54
|
-
// hot-reload page refreshes,
|
|
53
|
+
// Dev mode defaults: significantly higher to accommodate React strict mode double-rendering,
|
|
54
|
+
// hot-reload page refreshes, onSnapshot polling, and multi-client testing during development.
|
|
55
55
|
export const RATE_LIMIT_DEV_DEFAULTS: Record<string, { requests: number; windowSec: number }> = {
|
|
56
56
|
global: { requests: 10_000_000, windowSec: 60 },
|
|
57
|
-
db: { requests:
|
|
58
|
-
storage: { requests:
|
|
59
|
-
functions: { requests:
|
|
60
|
-
auth: { requests:
|
|
57
|
+
db: { requests: 5000, windowSec: 60 },
|
|
58
|
+
storage: { requests: 1000, windowSec: 60 },
|
|
59
|
+
functions: { requests: 1000, windowSec: 60 },
|
|
60
|
+
auth: { requests: 500, windowSec: 60 },
|
|
61
61
|
authSignin: { requests: 100, windowSec: 60 },
|
|
62
62
|
authSignup: { requests: 100, windowSec: 60 },
|
|
63
|
-
events: { requests:
|
|
63
|
+
events: { requests: 5000, windowSec: 60 },
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
// ─── Window parser ───
|
|
@@ -256,7 +256,7 @@ export const rateLimitMiddleware: MiddlewareHandler<HonoEnv> = async (c, next) =
|
|
|
256
256
|
if (!counter.check(counterKey, requests, windowSec)) {
|
|
257
257
|
c.header('Retry-After', String(counter.getRetryAfter(counterKey)));
|
|
258
258
|
return c.json(
|
|
259
|
-
{ code: 429, message: 'Too many requests. Please try again later.' },
|
|
259
|
+
{ code: 429, message: 'Too many requests. Please try again later.', group },
|
|
260
260
|
429,
|
|
261
261
|
);
|
|
262
262
|
}
|
|
@@ -268,7 +268,7 @@ export const rateLimitMiddleware: MiddlewareHandler<HonoEnv> = async (c, next) =
|
|
|
268
268
|
if (!success) {
|
|
269
269
|
c.header('Retry-After', '60');
|
|
270
270
|
return c.json(
|
|
271
|
-
{ code: 429, message: 'Too many requests. Please try again later.' },
|
|
271
|
+
{ code: 429, message: 'Too many requests. Please try again later.', group },
|
|
272
272
|
429,
|
|
273
273
|
);
|
|
274
274
|
}
|
|
@@ -282,7 +282,7 @@ export const rateLimitMiddleware: MiddlewareHandler<HonoEnv> = async (c, next) =
|
|
|
282
282
|
if (!counter.check(globalKey, globalLimit.requests, globalLimit.windowSec)) {
|
|
283
283
|
c.header('Retry-After', String(counter.getRetryAfter(globalKey)));
|
|
284
284
|
return c.json(
|
|
285
|
-
{ code: 429, message: 'Too many requests. Please try again later.' },
|
|
285
|
+
{ code: 429, message: 'Too many requests. Please try again later.', group: 'global' },
|
|
286
286
|
429,
|
|
287
287
|
);
|
|
288
288
|
}
|
|
@@ -294,7 +294,7 @@ export const rateLimitMiddleware: MiddlewareHandler<HonoEnv> = async (c, next) =
|
|
|
294
294
|
if (!success) {
|
|
295
295
|
c.header('Retry-After', '60');
|
|
296
296
|
return c.json(
|
|
297
|
-
{ code: 429, message: 'Too many requests. Please try again later.' },
|
|
297
|
+
{ code: 429, message: 'Too many requests. Please try again later.', group: 'global' },
|
|
298
298
|
429,
|
|
299
299
|
);
|
|
300
300
|
}
|
package/src/routes/admin.ts
CHANGED
|
@@ -240,8 +240,8 @@ function getLogStatusCode(log: Record<string, unknown>): number {
|
|
|
240
240
|
function matchesLogLevel(status: number, level: string): boolean {
|
|
241
241
|
const normalized = level.toLowerCase();
|
|
242
242
|
if (normalized === 'error') return status >= 500;
|
|
243
|
-
if (normalized === 'warn') return status >= 300 && status < 500;
|
|
244
|
-
if (normalized === 'info') return status >= 200 && status < 300;
|
|
243
|
+
if (normalized === 'warn') return (status >= 300 && status < 500 && status !== 304);
|
|
244
|
+
if (normalized === 'info') return (status >= 200 && status < 300) || status === 304;
|
|
245
245
|
return true;
|
|
246
246
|
}
|
|
247
247
|
|
package/src/routes/auth.ts
CHANGED
|
@@ -509,6 +509,13 @@ async function createSessionAndTokens(
|
|
|
509
509
|
metadata,
|
|
510
510
|
});
|
|
511
511
|
|
|
512
|
+
// Update lastSignedInAt on the user record
|
|
513
|
+
try {
|
|
514
|
+
await db.run('UPDATE _users SET lastSignedInAt = ? WHERE id = ?', [now, userId]);
|
|
515
|
+
} catch {
|
|
516
|
+
// Non-critical: don't block sign-in if this column doesn't exist yet
|
|
517
|
+
}
|
|
518
|
+
|
|
512
519
|
return { accessToken, refreshToken, sessionId };
|
|
513
520
|
}
|
|
514
521
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.sql-editor-wrap.svelte-392xt8{border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:hidden}.sql-editor-wrap.svelte-392xt8 .cm-editor{min-height:120px}.sql-editor-wrap.svelte-392xt8 .cm-editor.cm-focused{border-color:var(--color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--color-primary) 20%,transparent)}.table-sql.svelte-1syrthj{display:flex;flex-direction:column;gap:var(--space-4)}.table-sql__toolbar.svelte-1syrthj{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}.table-sql__target.svelte-1syrthj{display:inline-flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-bg-secondary);font-size:12px}.table-sql__target-label.svelte-1syrthj{color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.04em}.table-sql__target.svelte-1syrthj code:where(.svelte-1syrthj){font-family:var(--font-mono);color:var(--color-text)}.table-sql__shortcut.svelte-1syrthj{font-size:12px;color:var(--color-text-tertiary);margin-left:auto}.table-sql__result-tabs.svelte-1syrthj{display:flex;flex-wrap:wrap;gap:var(--space-2)}.table-sql__result-tab.svelte-1syrthj{display:inline-flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-bg-secondary);color:var(--color-text-secondary);cursor:pointer}.table-sql__result-tab--active.svelte-1syrthj{border-color:var(--color-primary);color:var(--color-primary)}.table-sql__result-open.svelte-1syrthj{border:none;background:transparent;color:inherit;cursor:pointer;padding:0;font:inherit}.table-sql__result-close.svelte-1syrthj{border:none;background:transparent;color:inherit;cursor:pointer;padding:0;line-height:1}.table-sql__result-panel.svelte-1syrthj{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-4);background:var(--color-bg)}.table-sql__result-meta.svelte-1syrthj{margin-bottom:var(--space-3);font-size:12px;color:var(--color-text-secondary)}.table-sql__result-error.svelte-1syrthj{color:var(--color-danger, #ef4444)}.table-sql__error-block.svelte-1syrthj,.table-sql__empty.svelte-1syrthj{margin:0;padding:var(--space-4);border-radius:var(--radius-md);background:var(--color-bg-secondary);color:var(--color-text-secondary);font-size:13px}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import"./CWj6FrbW.js";import{p as je,w as le,a as Be,b as k,g as o,d as M,M as Ke,t as E,u as D,s as w,c as g,r as h,ae as ke,f as Ge}from"./BdTBlfLy.js";import{s as B,d as Ye,a as pe}from"./DtZk82gG.js";import{a as C,f as P,t as He}from"./DEELgv7K.js";import{i as W}from"./Y22E1hJM.js";import{a as Je,t as $e,e as et}from"./B14gOIqE.js";import{s as tt,a as at}from"./CoI6jjbg.js";import{a as rt,s as st}from"./Cp8V0Xy2.js";import{B as ot}from"./C72lTcG0.js";import{D as nt}from"./D8Nrx_IG.js";import{o as lt,a as it}from"./Bn2NtlTj.js";import{b as ct}from"./CGgVJi7f.js";import{p as xe}from"./F9_4wRrd.js";import{L as dt,a as ft,i as mt,c as ut,b as ht,d as vt,f as Ot,s as gt,t as m,E as bt,e as kt,g as pt,h as se,j as xt,k as yt,l as Qt,m as _t,n as Ct,p as St,o as wt,q as Pt,r as Tt}from"./gtu8uwJD.js";import{s as ye}from"./BKLsgaNT.js";const qt=36,Qe=1,Ut=2,V=3,oe=4,jt=5,Bt=6,Et=7,It=8,Dt=9,Lt=10,Rt=11,Xt=12,Nt=13,Zt=14,zt=15,Vt=16,Mt=17,_e=18,At=19,Ee=20,Ie=21,Ce=22,Ft=23,Wt=24;function ie(t){return t>=65&&t<=90||t>=97&&t<=122||t>=48&&t<=57}function Kt(t){return t>=48&&t<=57||t>=97&&t<=102||t>=65&&t<=70}function R(t,e,r){for(let a=!1;;){if(t.next<0)return;if(t.next==e&&!a){t.advance();return}a=r&&!a&&t.next==92,t.advance()}}function Gt(t,e){e:for(;;){if(t.next<0)return;if(t.next==36){t.advance();for(let r=0;r<e.length;r++){if(t.next!=e.charCodeAt(r))continue e;t.advance()}if(t.next==36){t.advance();return}}else t.advance()}}function Yt(t,e){let r="[{<(".indexOf(String.fromCharCode(e)),a=r<0?e:"]}>)".charCodeAt(r);for(;;){if(t.next<0)return;if(t.next==a&&t.peek(1)==39){t.advance(2);return}t.advance()}}function ce(t,e){for(;!(t.next!=95&&!ie(t.next));)e!=null&&(e+=String.fromCharCode(t.next)),t.advance();return e}function Ht(t){if(t.next==39||t.next==34||t.next==96){let e=t.next;t.advance(),R(t,e,!1)}else ce(t)}function Se(t,e){for(;t.next==48||t.next==49;)t.advance();e&&t.next==e&&t.advance()}function we(t,e){for(;;){if(t.next==46){if(e)break;e=!0}else if(t.next<48||t.next>57)break;t.advance()}if(t.next==69||t.next==101)for(t.advance(),(t.next==43||t.next==45)&&t.advance();t.next>=48&&t.next<=57;)t.advance()}function Pe(t){for(;!(t.next<0||t.next==10);)t.advance()}function L(t,e){for(let r=0;r<e.length;r++)if(e.charCodeAt(r)==t)return!0;return!1}const ne=` \r
|
|
2
|
-
`;function De(t,e,r){let a=Object.create(null);a.true=a.false=jt,a.null=a.unknown=Bt;for(let s of t.split(" "))s&&(a[s]=Ee);for(let s of e.split(" "))s&&(a[s]=Ie);for(let s of(r||"").split(" "))s&&(a[s]=Wt);return a}const Le="array binary bit boolean char character clob date decimal double float int integer interval large national nchar nclob numeric object precision real smallint time timestamp varchar varying ",Re="absolute action add after all allocate alter and any are as asc assertion at authorization before begin between both breadth by call cascade cascaded case cast catalog check close collate collation column commit condition connect connection constraint constraints constructor continue corresponding count create cross cube current current_date current_default_transform_group current_transform_group_for_type current_path current_role current_time current_timestamp current_user cursor cycle data day deallocate declare default deferrable deferred delete depth deref desc describe descriptor deterministic diagnostics disconnect distinct do domain drop dynamic each else elseif end end-exec equals escape except exception exec execute exists exit external fetch first for foreign found from free full function general get global go goto grant group grouping handle having hold hour identity if immediate in indicator initially inner inout input insert intersect into is isolation join key language last lateral leading leave left level like limit local localtime localtimestamp locator loop map match method minute modifies module month names natural nesting new next no none not of old on only open option or order ordinality out outer output overlaps pad parameter partial path prepare preserve primary prior privileges procedure public read reads recursive redo ref references referencing relative release repeat resignal restrict result return returns revoke right role rollback rollup routine row rows savepoint schema scroll search second section select session session_user set sets signal similar size some space specific specifictype sql sqlexception sqlstate sqlwarning start state static system_user table temporary then timezone_hour timezone_minute to trailing transaction translation treat trigger under undo union unique unnest until update usage user using value values view when whenever where while with without work write year zone ",de={backslashEscapes:!1,hashComments:!1,spaceAfterDashes:!1,slashComments:!1,doubleQuotedStrings:!1,doubleDollarQuotedStrings:!1,unquotedBitLiterals:!1,treatBitsAsBytes:!1,charSetCasts:!1,plsqlQuotingMechanism:!1,operatorChars:"*+-%<>!=&|~^/",specialVar:"?",identifierQuotes:'"',caseInsensitiveIdentifiers:!1,words:De(Re,Le)};function Jt(t,e,r,a){let s={};for(let n in de)s[n]=(t.hasOwnProperty(n)?t:de)[n];return e&&(s.words=De(e,r||"",a)),s}function Xe(t){return new bt(e=>{var r;let{next:a}=e;if(e.advance(),L(a,ne)){for(;L(e.next,ne);)e.advance();e.acceptToken(qt)}else if(a==36&&t.doubleDollarQuotedStrings){let s=ce(e,"");e.next==36&&(e.advance(),Gt(e,s),e.acceptToken(V))}else if(a==39||a==34&&t.doubleQuotedStrings)R(e,a,t.backslashEscapes),e.acceptToken(V);else if(a==35&&t.hashComments||a==47&&e.next==47&&t.slashComments)Pe(e),e.acceptToken(Qe);else if(a==45&&e.next==45&&(!t.spaceAfterDashes||e.peek(1)==32))Pe(e),e.acceptToken(Qe);else if(a==47&&e.next==42){e.advance();for(let s=1;;){let n=e.next;if(e.next<0)break;if(e.advance(),n==42&&e.next==47){if(s--,e.advance(),!s)break}else n==47&&e.next==42&&(s++,e.advance())}e.acceptToken(Ut)}else if((a==101||a==69)&&e.next==39)e.advance(),R(e,39,!0),e.acceptToken(V);else if((a==110||a==78)&&e.next==39&&t.charSetCasts)e.advance(),R(e,39,t.backslashEscapes),e.acceptToken(V);else if(a==95&&t.charSetCasts)for(let s=0;;s++){if(e.next==39&&s>1){e.advance(),R(e,39,t.backslashEscapes),e.acceptToken(V);break}if(!ie(e.next))break;e.advance()}else if(t.plsqlQuotingMechanism&&(a==113||a==81)&&e.next==39&&e.peek(1)>0&&!L(e.peek(1),ne)){let s=e.peek(1);e.advance(2),Yt(e,s),e.acceptToken(V)}else if(L(a,t.identifierQuotes)){const s=a==91?93:a;R(e,s,!1),e.acceptToken(At)}else if(a==40)e.acceptToken(Et);else if(a==41)e.acceptToken(It);else if(a==123)e.acceptToken(Dt);else if(a==125)e.acceptToken(Lt);else if(a==91)e.acceptToken(Rt);else if(a==93)e.acceptToken(Xt);else if(a==59)e.acceptToken(Nt);else if(t.unquotedBitLiterals&&a==48&&e.next==98)e.advance(),Se(e),e.acceptToken(Ce);else if((a==98||a==66)&&(e.next==39||e.next==34)){const s=e.next;e.advance(),t.treatBitsAsBytes?(R(e,s,t.backslashEscapes),e.acceptToken(Ft)):(Se(e,s),e.acceptToken(Ce))}else if(a==48&&(e.next==120||e.next==88)||(a==120||a==88)&&e.next==39){let s=e.next==39;for(e.advance();Kt(e.next);)e.advance();s&&e.next==39&&e.advance(),e.acceptToken(oe)}else if(a==46&&e.next>=48&&e.next<=57)we(e,!0),e.acceptToken(oe);else if(a==46)e.acceptToken(Zt);else if(a>=48&&a<=57)we(e,!1),e.acceptToken(oe);else if(L(a,t.operatorChars)){for(;L(e.next,t.operatorChars);)e.advance();e.acceptToken(zt)}else if(L(a,t.specialVar))e.next==a&&e.advance(),Ht(e),e.acceptToken(Mt);else if(a==58||a==44)e.acceptToken(Vt);else if(ie(a)){let s=ce(e,String.fromCharCode(a));e.acceptToken(e.next==46||e.peek(-s.length-1)==46?_e:(r=t.words[s.toLowerCase()])!==null&&r!==void 0?r:_e)}})}const Ne=Xe(de),$t=kt.deserialize({version:14,states:"%vQ]QQOOO#wQRO'#DSO$OQQO'#CwO%eQQO'#CxO%lQQO'#CyO%sQQO'#CzOOQQ'#DS'#DSOOQQ'#C}'#C}O'UQRO'#C{OOQQ'#Cv'#CvOOQQ'#C|'#C|Q]QQOOQOQQOOO'`QQO'#DOO(xQRO,59cO)PQQO,59cO)UQQO'#DSOOQQ,59d,59dO)cQQO,59dOOQQ,59e,59eO)jQQO,59eOOQQ,59f,59fO)qQQO,59fOOQQ-E6{-E6{OOQQ,59b,59bOOQQ-E6z-E6zOOQQ,59j,59jOOQQ-E6|-E6|O+VQRO1G.}O+^QQO,59cOOQQ1G/O1G/OOOQQ1G/P1G/POOQQ1G/Q1G/QP+kQQO'#C}O+rQQO1G.}O)PQQO,59cO,PQQO'#Cw",stateData:",[~OtOSPOSQOS~ORUOSUOTUOUUOVROXSOZTO]XO^QO_UO`UOaPObPOcPOdUOeUOfUOgUOhUO~O^]ORvXSvXTvXUvXVvXXvXZvX]vX_vX`vXavXbvXcvXdvXevXfvXgvXhvX~OsvX~P!jOa_Ob_Oc_O~ORUOSUOTUOUUOVROXSOZTO^tO_UO`UOa`Ob`Oc`OdUOeUOfUOgUOhUO~OWaO~P$ZOYcO~P$ZO[eO~P$ZORUOSUOTUOUUOVROXSOZTO^QO_UO`UOaPObPOcPOdUOeUOfUOgUOhUO~O]hOsoX~P%zOajObjOcjO~O^]ORkaSkaTkaUkaVkaXkaZka]ka_ka`kaakabkackadkaekafkagkahka~Oska~P'kO^]O~OWvXYvX[vX~P!jOWnO~P$ZOYoO~P$ZO[pO~P$ZO^]ORkiSkiTkiUkiVkiXkiZki]ki_ki`kiakibkickidkiekifkigkihki~Oski~P)xOWkaYka[ka~P'kO]hO~P$ZOWkiYki[ki~P)xOasObsOcsO~O",goto:"#hwPPPPPPPPPPPPPPPPPPPPPPPPPPx||||!Y!^!d!xPPP#[TYOZeUORSTWZbdfqT[OZQZORiZSWOZQbRQdSQfTZgWbdfqQ^PWk^lmrQl_Qm`RrseVORSTWZbdfq",nodeNames:"⚠ LineComment BlockComment String Number Bool Null ( ) { } [ ] ; . Operator Punctuation SpecialVar Identifier QuotedIdentifier Keyword Type Bits Bytes Builtin Script Statement CompositeIdentifier Parens Braces Brackets Statement",maxTerm:38,nodeProps:[["isolate",-4,1,2,3,19,""]],skippedNodes:[0,1,2],repeatNodeCount:3,tokenData:"RORO",tokenizers:[0,Ne],topRules:{Script:[0,25]},tokenPrec:0});function fe(t){let e=t.cursor().moveTo(t.from,-1);for(;/Comment/.test(e.name);)e.moveTo(e.from,-1);return e.node}function K(t,e){let r=t.sliceString(e.from,e.to),a=/^([`'"\[])(.*)([`'"\]])$/.exec(r);return a?a[2]:r}function ee(t){return t&&(t.name=="Identifier"||t.name=="QuotedIdentifier")}function ea(t,e){if(e.name=="CompositeIdentifier"){let r=[];for(let a=e.firstChild;a;a=a.nextSibling)ee(a)&&r.push(K(t,a));return r}return[K(t,e)]}function Te(t,e){for(let r=[];;){if(!e||e.name!=".")return r;let a=fe(e);if(!ee(a))return r;r.unshift(K(t,a)),e=fe(a)}}function ta(t,e){let r=pt(t).resolveInner(e,-1),a=ra(t.doc,r);return r.name=="Identifier"||r.name=="QuotedIdentifier"||r.name=="Keyword"?{from:r.from,quoted:r.name=="QuotedIdentifier"?t.doc.sliceString(r.from,r.from+1):null,parents:Te(t.doc,fe(r)),aliases:a}:r.name=="."?{from:e,quoted:null,parents:Te(t.doc,r),aliases:a}:{from:e,quoted:null,parents:[],empty:!0,aliases:a}}const aa=new Set("where group having order union intersect except all distinct limit offset fetch for".split(" "));function ra(t,e){let r;for(let s=e;!r;s=s.parent){if(!s)return null;s.name=="Statement"&&(r=s)}let a=null;for(let s=r.firstChild,n=!1,f=null;s;s=s.nextSibling){let l=s.name=="Keyword"?t.sliceString(s.from,s.to).toLowerCase():null,i=null;if(!n)n=l=="from";else if(l=="as"&&f&&ee(s.nextSibling))i=K(t,s.nextSibling);else{if(l&&aa.has(l))break;f&&ee(s)&&(i=K(t,s))}i&&(a||(a=Object.create(null)),a[i]=ea(t,f)),f=/Identifier$/.test(s.name)?s:null}return a}function sa(t,e,r){return r.map(a=>({...a,label:a.label[0]==t?a.label:t+a.label+e,apply:void 0}))}const oa=/^\w*$/,na=/^[`'"\[]?\w*[`'"\]]?$/;function qe(t){return t.self&&typeof t.self.label=="string"}class me{constructor(e,r){this.idQuote=e,this.idCaseInsensitive=r,this.list=[],this.children=void 0}child(e){let r=this.children||(this.children=Object.create(null)),a=r[e];return a||(e&&!this.list.some(s=>s.label==e)&&this.list.push(Ue(e,"type",this.idQuote,this.idCaseInsensitive)),r[e]=new me(this.idQuote,this.idCaseInsensitive))}maybeChild(e){return this.children?this.children[e]:null}addCompletion(e){let r=this.list.findIndex(a=>a.label==e.label);r>-1?this.list[r]=e:this.list.push(e)}addCompletions(e){for(let r of e)this.addCompletion(typeof r=="string"?Ue(r,"property",this.idQuote,this.idCaseInsensitive):r)}addNamespace(e){Array.isArray(e)?this.addCompletions(e):qe(e)?this.addNamespace(e.children):this.addNamespaceObject(e)}addNamespaceObject(e){for(let r of Object.keys(e)){let a=e[r],s=null,n=r.replace(/\\?\./g,l=>l=="."?"\0":l).split("\0"),f=this;qe(a)&&(s=a.self,a=a.children);for(let l=0;l<n.length;l++)s&&l==n.length-1&&f.addCompletion(s),f=f.child(n[l].replace(/\\\./g,"."));f.addNamespace(a)}}}function Ue(t,e,r,a){return new RegExp("^[a-z_][a-z_\\d]*$",a?"i":"").test(t)?{label:t,type:e}:{label:t,type:e,apply:r+t+Ze(r)}}function Ze(t){return t==="["?"]":t}function la(t,e,r,a,s,n){var f;let l=((f=n==null?void 0:n.spec.identifierQuotes)===null||f===void 0?void 0:f[0])||'"',i=new me(l,!!(n!=null&&n.spec.caseInsensitiveIdentifiers)),v=s?i.child(s):null;return i.addNamespace(t),e&&(v||i).addCompletions(e),r&&i.addCompletions(r),v&&i.addCompletions(v.list),a&&i.addCompletions((v||i).child(a).list),p=>{let{parents:O,from:y,quoted:T,empty:te,aliases:X}=ta(p.state,p.pos);if(te&&!p.explicit)return null;X&&O.length==1&&(O=X[O[0]]||O);let x=i;for(let S of O){for(;!x.children||!x.children[S];)if(x==i&&v)x=v;else if(x==v&&a)x=x.child(a);else return null;let q=x.maybeChild(S);if(!q)return null;x=q}let N=x.list;if(x==i&&X&&(N=N.concat(Object.keys(X).map(S=>({label:S,type:"constant"})))),T){let S=T[0],q=Ze(S),A=p.state.sliceDoc(p.pos,p.pos+1)==q;return{from:y,to:A?p.pos+1:void 0,options:sa(S,q,N),validFor:na}}else return{from:y,options:N,validFor:oa}}}function ia(t){return t==Ie?"type":t==Ee?"keyword":"variable"}function ca(t,e,r){let a=Object.keys(t).map(s=>r(e?s.toUpperCase():s,ia(t[s])));return mt(["QuotedIdentifier","String","LineComment","BlockComment","."],ut(a))}let da=$t.configure({props:[ht.add({Statement:vt()}),Ot.add({Statement(t,e){return{from:Math.min(t.from+100,e.doc.lineAt(t.from).to),to:t.to}},BlockComment(t){return{from:t.from+2,to:t.to-2}}}),gt({Keyword:m.keyword,Type:m.typeName,Builtin:m.standard(m.name),Bits:m.number,Bytes:m.string,Bool:m.bool,Null:m.null,Number:m.number,String:m.string,Identifier:m.name,QuotedIdentifier:m.special(m.string),SpecialVar:m.special(m.name),LineComment:m.lineComment,BlockComment:m.blockComment,Operator:m.operator,"Semi Punctuation":m.punctuation,"( )":m.paren,"{ }":m.brace,"[ ]":m.squareBracket})]});class G{constructor(e,r,a){this.dialect=e,this.language=r,this.spec=a}get extension(){return this.language.extension}configureLanguage(e,r){return new G(this.dialect,this.language.configure(e,r),this.spec)}static define(e){let r=Jt(e,e.keywords,e.types,e.builtin),a=ft.define({name:"sql",parser:da.configure({tokenizers:[{from:Ne,to:Xe(r)}]}),languageData:{commentTokens:{line:"--",block:{open:"/*",close:"*/"}},closeBrackets:{brackets:["(","[","{","'",'"',"`"]}}});return new G(r,a,e)}}function fa(t,e){return{label:t,type:e,boost:-1}}function ma(t,e=!1,r){return ca(t.dialect.words,e,r||fa)}function ua(t){return t.schema?la(t.schema,t.tables,t.schemas,t.defaultTable,t.defaultSchema,t.dialect||ue):()=>null}function ha(t){return t.schema?(t.dialect||ue).language.data.of({autocomplete:ua(t)}):[]}function va(t={}){let e=t.dialect||ue;return new dt(e.language,[ha(t),e.language.data.of({autocomplete:ma(e,t.upperCaseKeywords,t.keywordCompletion)})])}const ue=G.define({}),Oa=G.define({keywords:Re+"abort analyze attach autoincrement conflict database detach exclusive fail glob ignore index indexed instead isnull notnull offset plan pragma query raise regexp reindex rename replace temp vacuum virtual",types:Le+"bool blob long longblob longtext medium mediumblob mediumint mediumtext tinyblob tinyint tinytext text bigint int2 int8 unsigned signed real",builtin:"auth backup bail changes clone databases dbinfo dump echo eqp explain fullschema headers help import imposter indexes iotrace lint load log mode nullvalue once print prompt quit restore save scanstats separator shell show stats system tables testcase timeout timer trace vfsinfo vfslist vfsname width",operatorChars:"*+-%<>!=&|/~",identifierQuotes:'`"',specialVar:"@:?$"});var ga=P('<div class="sql-editor-wrap svelte-392xt8"></div>');function ba(t,e){je(e,!0);let r=xe(e,"placeholder",3,""),a=xe(e,"schema",19,()=>({})),s,n,f=M(!1);function l(){return document.documentElement.dataset.theme==="dark"||document.documentElement.dataset.theme!=="light"&&window.matchMedia("(prefers-color-scheme: dark)").matches}function i(){const O=[va({dialect:Oa,schema:a()}),yt(),Qt.of([..._t,Ct,{key:"Mod-Enter",run:()=>{var y;return(y=e.onExecute)==null||y.call(e),!0}}]),se.updateListener.of(y=>{if(y.docChanged){const T=y.state.doc.toString();e.onchange(T)}}),se.theme({"&":{fontSize:"13px",maxHeight:"300px"},".cm-scroller":{overflow:"auto",fontFamily:"var(--font-mono)"},".cm-content":{minHeight:"100px",padding:"8px 0"},"&.cm-focused":{outline:"none"}})];return r()&&O.push(St(r())),o(f)?O.push(wt):O.push(Pt(Tt)),O}function v(){n&&n.destroy(),n=new se({state:xt.create({doc:e.value,extensions:i()}),parent:s})}lt(()=>{k(f,l(),!0),v();const O=new MutationObserver(()=>{const y=l();if(y!==o(f)){k(f,y,!0);const T=(n==null?void 0:n.state.doc.toString())??e.value;v(),T!==e.value&&(n==null||n.dispatch({changes:{from:0,to:n.state.doc.length,insert:T}}))}});return O.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),()=>{O.disconnect(),n==null||n.destroy()}}),it(()=>{n==null||n.destroy()}),le(()=>{n&&e.value!==n.state.doc.toString()&&n.dispatch({changes:{from:0,to:n.state.doc.length,insert:e.value}})});var p=ga();ct(p,O=>s=O,()=>s),C(t,p),Be()}var ka=P('<div class="table-sql__target svelte-1syrthj"><span class="table-sql__target-label svelte-1syrthj"> </span> <code class="svelte-1syrthj"> </code></div>'),pa=P('<div><button type="button" class="table-sql__result-open svelte-1syrthj"><span> </span></button> <button type="button" class="table-sql__result-close svelte-1syrthj">×</button></div>'),xa=P('<span class="table-sql__result-error svelte-1syrthj"> </span>'),ya=P("<span> </span>"),Qa=P('<pre class="table-sql__error-block svelte-1syrthj"> </pre>'),_a=P('<div class="table-sql__empty svelte-1syrthj">Query returned no rows.</div>'),Ca=P('<div class="table-sql__result-panel svelte-1syrthj"><div class="table-sql__result-meta svelte-1syrthj"><!></div> <!></div>'),Sa=P('<div class="table-sql__result-tabs svelte-1syrthj"></div> <!>',1),wa=P('<div class="table-sql__empty svelte-1syrthj">Run a query against <code> </code> to inspect rows, joins, or aggregates for this target.</div>'),Pa=P('<div class="table-sql svelte-1syrthj"><div class="table-sql__toolbar svelte-1syrthj"><div class="table-sql__target svelte-1syrthj"><span class="table-sql__target-label svelte-1syrthj">Database</span> <code class="svelte-1syrthj"> </code></div> <!> <!> <span class="table-sql__shortcut svelte-1syrthj"></span></div> <!> <!></div>');function Ma(t,e){var be;je(e,!0);const r=()=>rt(ye,"$schemaStore",a),[a,s]=st();let n=M(""),f=M(!1),l=M(Ke([])),i=M(0),v=M(0),p=D(()=>r().schema[e.tableName]),O=D(()=>(()=>{const c={},d=r().schema;for(const[u,_]of Object.entries(d)){const I=_.fields;c[u]=I?Object.keys(I):[]}return c})()),y=D(()=>{var c;return(c=o(p))!=null&&c.dynamic?"Per-tenant DB":"Single DB"}),T=D(()=>{var c,d,u;return((u=(d=(c=o(p))==null?void 0:c.instanceDiscovery)==null?void 0:d.targetLabel)==null?void 0:u.trim())||"Target"}),te=D(()=>e.instanceId||"Not selected");function X(c){return`SELECT * FROM "${c}" LIMIT 100;`}le(()=>{k(n,X(e.tableName),!0)}),le(()=>{Object.keys(r().schema).length===0&&ye.loadSchema({silent:!0})});async function x(){if(o(n).trim()){k(f,!0);try{const c=await Je.fetch("data/sql",{method:"POST",body:{namespace:e.namespace,id:e.instanceId||void 0,sql:o(n).trim()}}),d=(c.columns??[]).map(u=>({key:u,label:u,type:"text",editable:!1}));k(v,o(v)+1),k(l,[...o(l),{id:o(v),sql:o(n).trim(),columns:d,rows:c.rows??[],rowCount:c.rowCount??0,time:c.time??0}],!0),k(i,o(l).length-1)}catch(c){const d=c instanceof Error?c.message:"Query failed";$e(d),k(v,o(v)+1),k(l,[...o(l),{id:o(v),sql:o(n).trim(),columns:[],rows:[],rowCount:0,time:0,error:d}],!0),k(i,o(l).length-1)}finally{k(f,!1)}}}function N(c){const d=o(l).filter((u,_)=>_!==c);o(i)>c?k(i,o(i)-1):o(i)===c&&k(i,Math.min(c,Math.max(0,d.length-1)),!0),k(l,d,!0)}var S=Pa(),q=g(S),A=g(q),he=w(g(A),2),ze=g(he,!0);h(he),h(A);var ve=w(A,2);{var Ve=c=>{var d=ka(),u=g(d),_=g(u,!0);h(u);var I=w(u,2),U=g(I,!0);h(I),h(d),E(()=>{B(_,o(T)),B(U,o(te))}),C(c,d)};W(ve,c=>{var d;(d=o(p))!=null&&d.dynamic&&c(Ve)})}var Oe=w(ve,2);{let c=D(()=>o(f)||!o(n).trim());ot(Oe,{variant:"primary",size:"sm",onclick:x,get loading(){return o(f)},get disabled(){return o(c)},children:(d,u)=>{ke();var _=He();E(()=>B(_,o(f)?"Executing...":"Execute")),C(d,_)},$$slots:{default:!0}})}var Me=w(Oe,2);Me.textContent=`${(be=navigator.platform)!=null&&be.includes("Mac")?"⌘":"Ctrl"}+Enter`,h(q);var ge=w(q,2);{let c=D(()=>`SELECT * FROM "${e.tableName}" LIMIT 100;`);ba(ge,{get value(){return o(n)},onchange:d=>k(n,d,!0),onExecute:x,get placeholder(){return o(c)},get schema(){return o(O)}})}var Ae=w(ge,2);{var Fe=c=>{var d=Sa(),u=Ge(d);et(u,23,()=>o(l),U=>U.id,(U,Y,j)=>{var Z=pa();let H;var z=g(Z),J=g(z),ae=g(J);h(J),h(z);var $=w(z,2);h(Z),E(()=>{H=tt(Z,1,"table-sql__result-tab svelte-1syrthj",null,H,{"table-sql__result-tab--active":o(j)===o(i)}),B(ae,`Result ${o(j)+1}`),at($,"aria-label",`Close result ${o(j)+1}`)}),pe("click",z,()=>k(i,o(j),!0)),pe("click",$,re=>{re.stopPropagation(),N(o(j))}),C(U,Z)}),h(u);var _=w(u,2);{var I=U=>{var Y=Ca(),j=g(Y),Z=g(j);{var H=b=>{var Q=xa(),F=g(Q,!0);h(Q),E(()=>B(F,o(l)[o(i)].error)),C(b,Q)},z=b=>{var Q=ya(),F=g(Q);h(Q),E(()=>B(F,`${o(l)[o(i)].rowCount??""} row${o(l)[o(i)].rowCount===1?"":"s"} · ${o(l)[o(i)].time??""}ms`)),C(b,Q)};W(Z,b=>{o(l)[o(i)].error?b(H):b(z,!1)})}h(j);var J=w(j,2);{var ae=b=>{var Q=Qa(),F=g(Q,!0);h(Q),E(()=>B(F,o(l)[o(i)].sql)),C(b,Q)},$=b=>{var Q=_a();C(b,Q)},re=b=>{nt(b,{get columns(){return o(l)[o(i)].columns},get rows(){return o(l)[o(i)].rows},readonly:!0})};W(J,b=>{o(l)[o(i)].error?b(ae):o(l)[o(i)].rows.length===0?b($,1):b(re,!1)})}h(Y),C(U,Y)};W(_,U=>{o(l)[o(i)]&&U(I)})}C(c,d)},We=c=>{var d=wa(),u=w(g(d)),_=g(u,!0);h(u),ke(),h(d),E(()=>B(_,e.tableName)),C(c,d)};W(Ae,c=>{o(l).length>0?c(Fe):c(We,!1)})}h(S),E(()=>B(ze,o(y))),C(t,S),Be(),s()}Ye(["click"]);export{Ma as default};
|