local-lite 0.0.3 → 0.0.4
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/README.md +421 -362
- package/dist/adapters/local/better-sqlite3.d.ts +2 -0
- package/dist/adapters/local/better-sqlite3.js +46 -25
- package/dist/adapters/local/expo-sqlite.d.ts +5 -1
- package/dist/adapters/local/expo-sqlite.js +40 -7
- package/dist/adapters/local/index.d.ts +1 -0
- package/dist/adapters/local/node-sqlite.d.ts +2 -0
- package/dist/adapters/local/node-sqlite.js +45 -22
- package/dist/adapters/local/op-sqlite.d.ts +1 -0
- package/dist/adapters/local/op-sqlite.js +6 -0
- package/dist/adapters/local/sql-js.d.ts +1 -0
- package/dist/adapters/local/sql-js.js +5 -0
- package/dist/adapters/network/index.js +33 -0
- package/dist/adapters/remote/convex.d.ts +2 -2
- package/dist/adapters/remote/convex.js +8 -12
- package/dist/adapters/remote/demo.d.ts +1 -1
- package/dist/adapters/remote/demo.js +3 -0
- package/dist/adapters/remote/firestore.d.ts +3 -2
- package/dist/adapters/remote/firestore.js +69 -46
- package/dist/adapters/remote/index.d.ts +6 -4
- package/dist/adapters/remote/supabase.d.ts +34 -6
- package/dist/adapters/remote/supabase.js +340 -79
- package/dist/config/index.js +7 -10
- package/dist/config/resolve-local.js +12 -1
- package/dist/config/resolve-remote.js +33 -28
- package/dist/config/types.d.ts +30 -5
- package/dist/core/client.d.ts +86 -3
- package/dist/core/client.js +423 -41
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.js +29 -0
- package/dist/core/outbox-store.d.ts +8 -4
- package/dist/core/outbox-store.js +84 -65
- package/dist/core/query.d.ts +8 -0
- package/dist/core/query.js +37 -0
- package/dist/core/schema-manager.d.ts +9 -0
- package/dist/core/schema-manager.js +68 -0
- package/dist/core/sync-worker.d.ts +38 -1
- package/dist/core/sync-worker.js +351 -104
- package/dist/core/table-manager.js +26 -29
- package/dist/core/types.d.ts +8 -0
- package/dist/react/BenchmarkModal.d.ts +32 -0
- package/dist/react/BenchmarkModal.js +777 -0
- package/dist/react/SyncInspector.d.ts +31 -0
- package/dist/react/SyncInspector.js +655 -0
- package/dist/react/index.d.ts +51 -19
- package/dist/react/index.js +265 -105
- package/dist/react/runner.d.ts +7 -0
- package/dist/react/runner.js +42 -0
- package/dist/react/status.d.ts +24 -0
- package/dist/react/status.js +123 -0
- package/dist/react/theme.d.ts +18 -0
- package/dist/react/theme.js +46 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.js +20 -0
- package/package.json +138 -133
|
@@ -4,6 +4,15 @@ exports.TableManager = void 0;
|
|
|
4
4
|
const sql_js_1 = require("../utils/sql.js");
|
|
5
5
|
const schema_manager_js_1 = require("./schema-manager.js");
|
|
6
6
|
const defaultSchemaManager = new schema_manager_js_1.SchemaManager();
|
|
7
|
+
function formatPayload(payload) {
|
|
8
|
+
const formatted = {};
|
|
9
|
+
if (payload && typeof payload === 'object') {
|
|
10
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
11
|
+
formatted[k] = (0, schema_manager_js_1.formatValueForStorage)(v);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return formatted;
|
|
15
|
+
}
|
|
7
16
|
class TableManager {
|
|
8
17
|
/**
|
|
9
18
|
* Applies an insert, update, or delete mutation on a local data table.
|
|
@@ -21,40 +30,28 @@ class TableManager {
|
|
|
21
30
|
await tx.execute(`DELETE FROM ${safeTable} WHERE ${safePk} = ?`, [rowId]);
|
|
22
31
|
return;
|
|
23
32
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
const formatted = {};
|
|
31
|
-
if (payload && typeof payload === 'object') {
|
|
32
|
-
for (const k of Object.keys(payload)) {
|
|
33
|
-
formatted[k] = (0, schema_manager_js_1.formatValueForStorage)(payload[k]);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
rowData = { ...formatted, [primaryKey]: rowId };
|
|
37
|
-
}
|
|
33
|
+
const formatted = options?.autoSchema
|
|
34
|
+
? await sm.ensureColumns(tx, tableName, payload, primaryKey)
|
|
35
|
+
: formatPayload(payload);
|
|
36
|
+
const rowData = { ...formatted, [primaryKey]: rowId };
|
|
38
37
|
const keys = Object.keys(rowData);
|
|
39
38
|
if (keys.length === 0)
|
|
40
39
|
return;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
// Use atomic SQLite UPSERT (INSERT ... ON CONFLICT DO UPDATE) for both INSERT and UPDATE.
|
|
41
|
+
// Handles missing rows, existing rows, and partial updates in a single SQL round-trip,
|
|
42
|
+
// completely eliminating the redundant SELECT 1 pre-check on every mutation!
|
|
43
|
+
const updateKeys = keys.filter((k) => k !== primaryKey);
|
|
44
|
+
const cols = keys.map((k) => (0, sql_js_1.escapeIdentifier)(k)).join(', ');
|
|
45
|
+
const placeholders = keys.map(() => '?').join(', ');
|
|
46
|
+
const values = keys.map((k) => rowData[k]);
|
|
47
|
+
if (updateKeys.length > 0) {
|
|
48
|
+
const updateClause = updateKeys
|
|
49
|
+
.map((k) => `${(0, sql_js_1.escapeIdentifier)(k)} = excluded.${(0, sql_js_1.escapeIdentifier)(k)}`)
|
|
50
|
+
.join(', ');
|
|
51
|
+
await tx.execute(`INSERT INTO ${safeTable} (${cols}) VALUES (${placeholders}) ON CONFLICT (${safePk}) DO UPDATE SET ${updateClause}`, values);
|
|
51
52
|
}
|
|
52
53
|
else {
|
|
53
|
-
|
|
54
|
-
const cols = keys.map((k) => (0, sql_js_1.escapeIdentifier)(k)).join(', ');
|
|
55
|
-
const placeholders = keys.map(() => '?').join(', ');
|
|
56
|
-
const values = keys.map((k) => rowData[k]);
|
|
57
|
-
await tx.execute(`INSERT INTO ${safeTable} (${cols}) VALUES (${placeholders})`, values);
|
|
54
|
+
await tx.execute(`INSERT OR IGNORE INTO ${safeTable} (${cols}) VALUES (${placeholders})`, values);
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
57
|
/**
|
package/dist/core/types.d.ts
CHANGED
|
@@ -8,6 +8,12 @@ export interface SyncOperation {
|
|
|
8
8
|
payload: Record<string, any> | null;
|
|
9
9
|
timestamp: number;
|
|
10
10
|
}
|
|
11
|
+
export interface PushResult {
|
|
12
|
+
success?: boolean;
|
|
13
|
+
successfulIds?: string[];
|
|
14
|
+
failedIds?: string[];
|
|
15
|
+
errors?: Record<string, string>;
|
|
16
|
+
}
|
|
11
17
|
export interface OutboxRecord extends SyncOperation {
|
|
12
18
|
status: OutboxStatus;
|
|
13
19
|
retryCount: number;
|
|
@@ -90,11 +96,13 @@ export type WhereFilter = Record<string, FieldFilter> | ((row: Record<string, an
|
|
|
90
96
|
[key: string]: any;
|
|
91
97
|
};
|
|
92
98
|
export interface QueryOptions {
|
|
99
|
+
select?: string[];
|
|
93
100
|
where?: WhereFilter;
|
|
94
101
|
orderBy?: string;
|
|
95
102
|
order?: 'asc' | 'desc' | 'ASC' | 'DESC';
|
|
96
103
|
limit?: number;
|
|
97
104
|
offset?: number;
|
|
105
|
+
includeDeleted?: boolean;
|
|
98
106
|
}
|
|
99
107
|
/**
|
|
100
108
|
* Individual mutation descriptor for atomic batch execution.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LocalFirstClient } from '../core/client.js';
|
|
3
|
+
import { type SyncThemeColors } from './theme.js';
|
|
4
|
+
export interface BuiltinBenchmarkResult {
|
|
5
|
+
name: string;
|
|
6
|
+
category: 'Local-Lite Client' | 'ACID / Transactions' | 'Outbox / Sync' | 'Memory / JSON';
|
|
7
|
+
description: string;
|
|
8
|
+
operations: number;
|
|
9
|
+
durationMs: number;
|
|
10
|
+
opsPerSec: number;
|
|
11
|
+
status: 'pending' | 'running' | 'success' | 'failed';
|
|
12
|
+
note?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface BenchmarkModalProps {
|
|
15
|
+
client: LocalFirstClient | null | undefined;
|
|
16
|
+
visible: boolean;
|
|
17
|
+
onDismiss: () => void;
|
|
18
|
+
theme?: 'auto' | 'dark' | 'light' | Partial<SyncThemeColors>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Executes a comprehensive performance & ACID test suite
|
|
22
|
+
* directly testing local-lite client APIs:
|
|
23
|
+
* client.batch(), client.insert(), client.update(), client.findById(),
|
|
24
|
+
* client.findMany() with SQL pushdown ($gt, $contains), client.transaction() rollbacks,
|
|
25
|
+
* client.trackMutation() outbox pipeline, and client.delete().
|
|
26
|
+
*/
|
|
27
|
+
export declare function runSQLiteBenchmark(clientOrDb: any, onProgress?: (step: string, progress: number) => void): Promise<BuiltinBenchmarkResult[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Pure package-driven, full-height Performance Benchmark Modal.
|
|
30
|
+
* Opens full-height with zero screen flickering or dynamic jumping.
|
|
31
|
+
*/
|
|
32
|
+
export declare function BenchmarkModal({ client, visible, onDismiss, theme }: BenchmarkModalProps): React.JSX.Element | null;
|