@plures/pluresdb 1.6.10 → 2.9.6
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 +97 -289
- package/crates/README.md +99 -0
- package/crates/pluresdb-node/README.md +181 -0
- package/crates/pluresdb-node/index.d.ts +0 -0
- package/crates/pluresdb-node/index.js +265 -0
- package/crates/pluresdb-node/package.json +35 -0
- package/dist/napi/index.js +60 -0
- package/embedded.d.ts +1 -0
- package/embedded.js +46 -0
- package/package.json +20 -9
- package/dist/.tsbuildinfo +0 -1
- package/dist/better-sqlite3-shared.d.ts +0 -12
- package/dist/better-sqlite3-shared.d.ts.map +0 -1
- package/dist/better-sqlite3-shared.js +0 -143
- package/dist/better-sqlite3-shared.js.map +0 -1
- package/dist/better-sqlite3.d.ts +0 -4
- package/dist/better-sqlite3.d.ts.map +0 -1
- package/dist/better-sqlite3.js +0 -8
- package/dist/better-sqlite3.js.map +0 -1
- package/dist/cli.d.ts +0 -7
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/local-first/unified-api.d.ts +0 -110
- package/dist/local-first/unified-api.d.ts.map +0 -1
- package/dist/local-first/unified-api.js +0 -348
- package/dist/local-first/unified-api.js.map +0 -1
- package/dist/node-index.d.ts +0 -150
- package/dist/node-index.d.ts.map +0 -1
- package/dist/node-index.js +0 -668
- package/dist/node-index.js.map +0 -1
- package/dist/node-wrapper.d.ts +0 -44
- package/dist/node-wrapper.d.ts.map +0 -1
- package/dist/node-wrapper.js +0 -296
- package/dist/node-wrapper.js.map +0 -1
- package/dist/types/index.d.ts +0 -28
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/types/node-types.d.ts +0 -71
- package/dist/types/node-types.d.ts.map +0 -1
- package/dist/types/node-types.js +0 -6
- package/dist/types/node-types.js.map +0 -1
- package/dist/util/debug.d.ts +0 -3
- package/dist/util/debug.d.ts.map +0 -1
- package/dist/util/debug.js +0 -34
- package/dist/util/debug.js.map +0 -1
- package/dist/vscode/extension.d.ts +0 -81
- package/dist/vscode/extension.d.ts.map +0 -1
- package/dist/vscode/extension.js +0 -309
- package/dist/vscode/extension.js.map +0 -1
- package/examples/basic-usage.d.ts +0 -2
- package/examples/basic-usage.d.ts.map +0 -1
- package/examples/basic-usage.js +0 -26
- package/examples/basic-usage.js.map +0 -1
- package/examples/basic-usage.ts +0 -29
- package/examples/browser-demo/README.md +0 -204
- package/examples/browser-demo/index.html +0 -466
- package/examples/browser-wasm-integration.md +0 -411
- package/examples/ipc-demo/README.md +0 -127
- package/examples/local-first-usage.ts +0 -138
- package/examples/native-ipc-integration.md +0 -526
- package/examples/tauri-demo/README.md +0 -240
- package/examples/tauri-integration.md +0 -260
- package/examples/vscode-extension-example/README.md +0 -95
- package/examples/vscode-extension-example/package.json +0 -49
- package/examples/vscode-extension-example/src/extension.ts +0 -172
- package/examples/vscode-extension-example/tsconfig.json +0 -12
- package/examples/vscode-extension-integration.d.ts +0 -31
- package/examples/vscode-extension-integration.d.ts.map +0 -1
- package/examples/vscode-extension-integration.js +0 -319
- package/examples/vscode-extension-integration.js.map +0 -1
- package/examples/vscode-extension-integration.ts +0 -41
- package/legacy/benchmarks/memory-benchmarks.ts +0 -350
- package/legacy/benchmarks/run-benchmarks.ts +0 -315
- package/legacy/better-sqlite3-shared.ts +0 -157
- package/legacy/better-sqlite3.ts +0 -4
- package/legacy/cli.ts +0 -241
- package/legacy/config.ts +0 -50
- package/legacy/core/crdt.ts +0 -107
- package/legacy/core/database.ts +0 -529
- package/legacy/healthcheck.ts +0 -162
- package/legacy/http/api-server.ts +0 -569
- package/legacy/index.ts +0 -31
- package/legacy/local-first/unified-api.ts +0 -449
- package/legacy/logic/rules.ts +0 -46
- package/legacy/main.rs +0 -3
- package/legacy/main.ts +0 -197
- package/legacy/network/websocket-server.ts +0 -115
- package/legacy/node-index.ts +0 -827
- package/legacy/node-wrapper.ts +0 -329
- package/legacy/plugins/README.md +0 -181
- package/legacy/plugins/example-embedding-plugin.ts +0 -56
- package/legacy/plugins/plugin-system.ts +0 -315
- package/legacy/sqlite-compat.ts +0 -633
- package/legacy/sqlite3-compat.ts +0 -55
- package/legacy/storage/kv-storage.ts +0 -73
- package/legacy/tests/core.test.ts +0 -305
- package/legacy/tests/fixtures/performance-data.json +0 -71
- package/legacy/tests/fixtures/test-data.json +0 -129
- package/legacy/tests/integration/api-server.test.ts +0 -334
- package/legacy/tests/integration/mesh-network.test.ts +0 -303
- package/legacy/tests/logic.test.ts +0 -34
- package/legacy/tests/performance/load.test.ts +0 -290
- package/legacy/tests/security/input-validation.test.ts +0 -286
- package/legacy/tests/unit/core.test.ts +0 -226
- package/legacy/tests/unit/local-first-api.test.ts +0 -65
- package/legacy/tests/unit/plugin-system.test.ts +0 -388
- package/legacy/tests/unit/subscriptions.test.ts +0 -135
- package/legacy/tests/unit/vector-search.test.ts +0 -173
- package/legacy/tests/vscode_extension_test.ts +0 -281
- package/legacy/types/index.ts +0 -32
- package/legacy/types/node-types.ts +0 -80
- package/legacy/util/debug.ts +0 -27
- package/legacy/vector/index.ts +0 -59
- package/legacy/vscode/extension.ts +0 -387
- package/scripts/compiled-crud-verify.ts +0 -30
- package/scripts/dogfood.ts +0 -297
- package/scripts/postinstall.js +0 -156
- package/scripts/publish-crates.sh +0 -95
- package/scripts/release-check.js +0 -224
- package/scripts/run-tests.ts +0 -178
- package/scripts/setup-libclang.ps1 +0 -209
- package/scripts/update-changelog.js +0 -214
- package/scripts/validate-npm-publish.js +0 -228
- package/web/README.md +0 -27
- package/web/svelte/package.json +0 -31
|
@@ -1,449 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Local-First API for PluresDB
|
|
3
|
-
*
|
|
4
|
-
* Automatically selects the best integration method based on runtime environment:
|
|
5
|
-
* - Browser (WASM): Direct in-process WebAssembly
|
|
6
|
-
* - Tauri: Direct Rust crate linking via Tauri commands
|
|
7
|
-
* - Native IPC: Shared memory inter-process communication
|
|
8
|
-
* - Network: HTTP REST API (fallback for backward compatibility)
|
|
9
|
-
*
|
|
10
|
-
* This provides a consistent API across all platforms while maximizing performance
|
|
11
|
-
* and minimizing network overhead.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { debugLog } from "../util/debug";
|
|
15
|
-
|
|
16
|
-
export interface LocalFirstOptions {
|
|
17
|
-
/**
|
|
18
|
-
* Integration mode. If not specified, auto-detects the best mode.
|
|
19
|
-
* - "auto": Auto-detect runtime environment
|
|
20
|
-
* - "wasm": WebAssembly (browser)
|
|
21
|
-
* - "tauri": Tauri native integration
|
|
22
|
-
* - "ipc": Shared memory IPC
|
|
23
|
-
* - "network": HTTP REST API (backward compatibility)
|
|
24
|
-
*/
|
|
25
|
-
mode?: "auto" | "wasm" | "tauri" | "ipc" | "network";
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Database name (for WASM mode)
|
|
29
|
-
*/
|
|
30
|
-
dbName?: string;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* IPC channel name (for IPC mode)
|
|
34
|
-
*/
|
|
35
|
-
channelName?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Network URL (for network mode)
|
|
39
|
-
*/
|
|
40
|
-
networkUrl?: string;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Network port (for network mode)
|
|
44
|
-
*/
|
|
45
|
-
port?: number;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface LocalFirstBackend {
|
|
49
|
-
put(id: string, data: unknown): Promise<string>;
|
|
50
|
-
get(id: string): Promise<unknown>;
|
|
51
|
-
delete(id: string): Promise<void>;
|
|
52
|
-
list(): Promise<unknown[]>;
|
|
53
|
-
vectorSearch?(query: string, limit: number): Promise<unknown[]>;
|
|
54
|
-
close?(): Promise<void>;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Runtime environment detection
|
|
59
|
-
*/
|
|
60
|
-
class RuntimeDetector {
|
|
61
|
-
static isBrowser(): boolean {
|
|
62
|
-
return typeof globalThis !== "undefined" &&
|
|
63
|
-
typeof (globalThis as any).window !== "undefined" &&
|
|
64
|
-
typeof (globalThis as any).document !== "undefined" &&
|
|
65
|
-
typeof (globalThis as any).WebAssembly !== "undefined";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
static isTauri(): boolean {
|
|
69
|
-
return typeof globalThis !== "undefined" &&
|
|
70
|
-
typeof (globalThis as any).window !== "undefined" &&
|
|
71
|
-
(globalThis as any).window?.__TAURI__ !== undefined;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
static isNode(): boolean {
|
|
75
|
-
const globalProcess = (globalThis as any).process;
|
|
76
|
-
return typeof globalProcess !== "undefined" &&
|
|
77
|
-
globalProcess.versions?.node != null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
static isDeno(): boolean {
|
|
81
|
-
return typeof globalThis !== "undefined" &&
|
|
82
|
-
(globalThis as any).Deno !== undefined;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static hasIPCEnvironment(): boolean {
|
|
86
|
-
if (this.isNode()) {
|
|
87
|
-
return (globalThis as any).process?.env?.PLURESDB_IPC === "true";
|
|
88
|
-
}
|
|
89
|
-
if (this.isDeno()) {
|
|
90
|
-
const Deno = (globalThis as any).Deno;
|
|
91
|
-
return Deno?.env?.get?.("PLURESDB_IPC") === "true";
|
|
92
|
-
}
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
static detectBestMode(): "wasm" | "tauri" | "ipc" | "network" {
|
|
97
|
-
if (this.isTauri()) {
|
|
98
|
-
debugLog("Detected Tauri environment - using native integration");
|
|
99
|
-
return "tauri";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (this.isBrowser()) {
|
|
103
|
-
debugLog("Detected browser environment - using WASM");
|
|
104
|
-
return "wasm";
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (this.hasIPCEnvironment()) {
|
|
108
|
-
debugLog("Detected IPC environment - using shared memory");
|
|
109
|
-
return "ipc";
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
debugLog("Using network mode (fallback)");
|
|
113
|
-
return "network";
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* WASM Backend (Browser)
|
|
119
|
-
*
|
|
120
|
-
* Uses WebAssembly for direct in-process database access.
|
|
121
|
-
* Data is persisted in IndexedDB.
|
|
122
|
-
*/
|
|
123
|
-
class WasmBackend implements LocalFirstBackend {
|
|
124
|
-
private db: unknown = null;
|
|
125
|
-
private dbName: string;
|
|
126
|
-
|
|
127
|
-
constructor(dbName: string = "pluresdb") {
|
|
128
|
-
this.dbName = dbName;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async initialize(): Promise<void> {
|
|
132
|
-
// Note: This is a placeholder. The actual WASM module will be implemented
|
|
133
|
-
// in Phase 1 of the roadmap (pluresdb-wasm crate).
|
|
134
|
-
throw new Error(
|
|
135
|
-
"WASM backend not yet implemented. Please see docs/LOCAL_FIRST_INTEGRATION.md for implementation status.",
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async put(id: string, data: unknown): Promise<string> {
|
|
140
|
-
if (!this.db) await this.initialize();
|
|
141
|
-
return (this.db as any).put(id, data);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async get(id: string): Promise<unknown> {
|
|
145
|
-
if (!this.db) await this.initialize();
|
|
146
|
-
return (this.db as any).get(id);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async delete(id: string): Promise<void> {
|
|
150
|
-
if (!this.db) await this.initialize();
|
|
151
|
-
return (this.db as any).delete(id);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async list(): Promise<unknown[]> {
|
|
155
|
-
if (!this.db) await this.initialize();
|
|
156
|
-
return (this.db as any).list();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async vectorSearch(query: string, limit: number): Promise<unknown[]> {
|
|
160
|
-
if (!this.db) await this.initialize();
|
|
161
|
-
return (this.db as any).vectorSearch(query, limit);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async close(): Promise<void> {
|
|
165
|
-
if (this.db) {
|
|
166
|
-
await (this.db as any).close();
|
|
167
|
-
this.db = null;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Tauri Backend
|
|
174
|
-
*
|
|
175
|
-
* Uses Tauri commands to invoke Rust functions directly.
|
|
176
|
-
* Provides native performance with no network overhead.
|
|
177
|
-
*/
|
|
178
|
-
class TauriBackend implements LocalFirstBackend {
|
|
179
|
-
private invoke: any;
|
|
180
|
-
|
|
181
|
-
constructor() {
|
|
182
|
-
const win = typeof globalThis !== "undefined" ? (globalThis as any).window : undefined;
|
|
183
|
-
if (!win || !win.__TAURI__) {
|
|
184
|
-
throw new Error("Tauri backend requires Tauri environment");
|
|
185
|
-
}
|
|
186
|
-
this.invoke = win.__TAURI__.invoke;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async put(id: string, data: unknown): Promise<string> {
|
|
190
|
-
return await this.invoke("pluresdb_put", { id, data });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async get(id: string): Promise<unknown> {
|
|
194
|
-
return await this.invoke("pluresdb_get", { id });
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async delete(id: string): Promise<void> {
|
|
198
|
-
await this.invoke("pluresdb_delete", { id });
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
async list(): Promise<unknown[]> {
|
|
202
|
-
return await this.invoke("pluresdb_list");
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
async vectorSearch(query: string, limit: number): Promise<unknown[]> {
|
|
206
|
-
return await this.invoke("pluresdb_vector_search", { query, limit });
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* IPC Backend (Native Apps)
|
|
212
|
-
*
|
|
213
|
-
* Uses shared memory and message passing for inter-process communication.
|
|
214
|
-
* Provides low-latency access without network overhead.
|
|
215
|
-
*/
|
|
216
|
-
class IPCBackend implements LocalFirstBackend {
|
|
217
|
-
private channelName: string;
|
|
218
|
-
|
|
219
|
-
constructor(channelName: string = "pluresdb") {
|
|
220
|
-
this.channelName = channelName;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async initialize(): Promise<void> {
|
|
224
|
-
// Note: This is a placeholder. The actual IPC implementation will be
|
|
225
|
-
// in Phase 3 of the roadmap (pluresdb-ipc crate).
|
|
226
|
-
throw new Error(
|
|
227
|
-
"IPC backend not yet implemented. Please see docs/LOCAL_FIRST_INTEGRATION.md for implementation status.",
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async put(id: string, data: unknown): Promise<string> {
|
|
232
|
-
throw new Error("IPC backend not yet implemented");
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async get(id: string): Promise<unknown> {
|
|
236
|
-
throw new Error("IPC backend not yet implemented");
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
async delete(id: string): Promise<void> {
|
|
240
|
-
throw new Error("IPC backend not yet implemented");
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
async list(): Promise<unknown[]> {
|
|
244
|
-
throw new Error("IPC backend not yet implemented");
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async vectorSearch(query: string, limit: number): Promise<unknown[]> {
|
|
248
|
-
throw new Error("IPC backend not yet implemented");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Network Backend (HTTP REST API)
|
|
254
|
-
*
|
|
255
|
-
* Uses HTTP requests to communicate with a PluresDB server.
|
|
256
|
-
* This is the fallback mode for backward compatibility.
|
|
257
|
-
*/
|
|
258
|
-
class NetworkBackend implements LocalFirstBackend {
|
|
259
|
-
private baseUrl: string;
|
|
260
|
-
|
|
261
|
-
constructor(url?: string, port?: number) {
|
|
262
|
-
this.baseUrl = url || `http://localhost:${port || 34567}`;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
async put(id: string, data: unknown): Promise<string> {
|
|
266
|
-
const response = await fetch(`${this.baseUrl}/api/put`, {
|
|
267
|
-
method: "POST",
|
|
268
|
-
headers: { "Content-Type": "application/json" },
|
|
269
|
-
body: JSON.stringify({ id, data }),
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
if (!response.ok) {
|
|
273
|
-
throw new Error(`PUT failed: ${response.statusText}`);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// API returns { ok: true }, return the id
|
|
277
|
-
await response.json();
|
|
278
|
-
return id;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async get(id: string): Promise<unknown> {
|
|
282
|
-
const response = await fetch(`${this.baseUrl}/api/get?id=${encodeURIComponent(id)}`);
|
|
283
|
-
|
|
284
|
-
if (!response.ok) {
|
|
285
|
-
if (response.status === 404) return null;
|
|
286
|
-
throw new Error(`GET failed: ${response.statusText}`);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// API returns the node data directly (can be null)
|
|
290
|
-
return await response.json();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
async delete(id: string): Promise<void> {
|
|
294
|
-
const response = await fetch(`${this.baseUrl}/api/delete?id=${encodeURIComponent(id)}`, {
|
|
295
|
-
method: "DELETE",
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
if (!response.ok) {
|
|
299
|
-
throw new Error(`DELETE failed: ${response.statusText}`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async list(): Promise<unknown[]> {
|
|
304
|
-
const response = await fetch(`${this.baseUrl}/api/list`);
|
|
305
|
-
|
|
306
|
-
if (!response.ok) {
|
|
307
|
-
throw new Error(`LIST failed: ${response.statusText}`);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// API returns array of { id, data }
|
|
311
|
-
const nodes = await response.json() as Array<{ id: string; data: unknown }>;
|
|
312
|
-
return nodes;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async vectorSearch(query: string, limit: number): Promise<unknown[]> {
|
|
316
|
-
const response = await fetch(`${this.baseUrl}/api/search`, {
|
|
317
|
-
method: "POST",
|
|
318
|
-
headers: { "Content-Type": "application/json" },
|
|
319
|
-
body: JSON.stringify({ query, limit }),
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
if (!response.ok) {
|
|
323
|
-
throw new Error(`VECTOR_SEARCH failed: ${response.statusText}`);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// API returns array of { id, data }
|
|
327
|
-
const nodes = await response.json() as Array<{ id: string; data: unknown }>;
|
|
328
|
-
return nodes;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* PluresDB Local-First API
|
|
334
|
-
*
|
|
335
|
-
* Unified interface that works across all platforms:
|
|
336
|
-
* - Browser (WASM)
|
|
337
|
-
* - Tauri (native)
|
|
338
|
-
* - Native apps (IPC)
|
|
339
|
-
* - Traditional apps (network)
|
|
340
|
-
*
|
|
341
|
-
* Automatically selects the best integration method or allows manual override.
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```typescript
|
|
345
|
-
* // Auto-detect best mode
|
|
346
|
-
* const db = new PluresDBLocalFirst();
|
|
347
|
-
*
|
|
348
|
-
* // Manual mode selection
|
|
349
|
-
* const db = new PluresDBLocalFirst({ mode: "wasm", dbName: "my-app" });
|
|
350
|
-
*
|
|
351
|
-
* // Use the API (same across all modes)
|
|
352
|
-
* await db.put("user:1", { name: "Alice", email: "alice@example.com" });
|
|
353
|
-
* const user = await db.get("user:1");
|
|
354
|
-
* const results = await db.vectorSearch("Find users named Alice", 10);
|
|
355
|
-
* ```
|
|
356
|
-
*/
|
|
357
|
-
export class PluresDBLocalFirst {
|
|
358
|
-
private backend: LocalFirstBackend;
|
|
359
|
-
private mode: string;
|
|
360
|
-
|
|
361
|
-
constructor(options: LocalFirstOptions = {}) {
|
|
362
|
-
const mode = options.mode || "auto";
|
|
363
|
-
const actualMode = mode === "auto" ? RuntimeDetector.detectBestMode() : mode;
|
|
364
|
-
|
|
365
|
-
this.mode = actualMode;
|
|
366
|
-
|
|
367
|
-
switch (actualMode) {
|
|
368
|
-
case "wasm":
|
|
369
|
-
this.backend = new WasmBackend(options.dbName);
|
|
370
|
-
break;
|
|
371
|
-
|
|
372
|
-
case "tauri":
|
|
373
|
-
this.backend = new TauriBackend();
|
|
374
|
-
break;
|
|
375
|
-
|
|
376
|
-
case "ipc":
|
|
377
|
-
this.backend = new IPCBackend(options.channelName);
|
|
378
|
-
break;
|
|
379
|
-
|
|
380
|
-
case "network":
|
|
381
|
-
this.backend = new NetworkBackend(options.networkUrl, options.port);
|
|
382
|
-
break;
|
|
383
|
-
|
|
384
|
-
default:
|
|
385
|
-
throw new Error(`Unknown mode: ${actualMode}`);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
debugLog(`Initialized in ${this.mode} mode`);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Get the current integration mode
|
|
393
|
-
*/
|
|
394
|
-
getMode(): string {
|
|
395
|
-
return this.mode;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Insert or update a node
|
|
400
|
-
*/
|
|
401
|
-
async put(id: string, data: unknown): Promise<string> {
|
|
402
|
-
return this.backend.put(id, data);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Retrieve a node by ID
|
|
407
|
-
*/
|
|
408
|
-
async get(id: string): Promise<unknown> {
|
|
409
|
-
return this.backend.get(id);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Delete a node by ID
|
|
414
|
-
*/
|
|
415
|
-
async delete(id: string): Promise<void> {
|
|
416
|
-
return this.backend.delete(id);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* List all nodes
|
|
421
|
-
*/
|
|
422
|
-
async list(): Promise<unknown[]> {
|
|
423
|
-
return this.backend.list();
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Vector search (semantic similarity)
|
|
428
|
-
*/
|
|
429
|
-
async vectorSearch(query: string, limit: number = 10): Promise<unknown[]> {
|
|
430
|
-
if (!this.backend.vectorSearch) {
|
|
431
|
-
throw new Error("Vector search not supported in this mode");
|
|
432
|
-
}
|
|
433
|
-
return this.backend.vectorSearch(query, limit);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Close the database connection
|
|
438
|
-
*/
|
|
439
|
-
async close(): Promise<void> {
|
|
440
|
-
if (this.backend.close) {
|
|
441
|
-
await this.backend.close();
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Legacy export for backward compatibility
|
|
448
|
-
*/
|
|
449
|
-
export default PluresDBLocalFirst;
|
package/legacy/logic/rules.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { NodeRecord } from "../types/index.ts";
|
|
2
|
-
|
|
3
|
-
// Minimal DB interface to avoid circular imports
|
|
4
|
-
export interface DatabaseLike {
|
|
5
|
-
put(id: string, data: Record<string, unknown>): Promise<void>;
|
|
6
|
-
get<T = Record<string, unknown>>(
|
|
7
|
-
id: string,
|
|
8
|
-
): Promise<(T & { id: string }) | null>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface RuleContext {
|
|
12
|
-
db: DatabaseLike;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type RulePredicate = (node: NodeRecord) => boolean | Promise<boolean>;
|
|
16
|
-
export type RuleAction = (ctx: RuleContext, node: NodeRecord) => Promise<void>;
|
|
17
|
-
|
|
18
|
-
export interface Rule {
|
|
19
|
-
name: string;
|
|
20
|
-
whenType?: string;
|
|
21
|
-
predicate?: RulePredicate;
|
|
22
|
-
action: RuleAction;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class RuleEngine {
|
|
26
|
-
private readonly rules: Map<string, Rule> = new Map();
|
|
27
|
-
|
|
28
|
-
addRule(rule: Rule): void {
|
|
29
|
-
this.rules.set(rule.name, rule);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
removeRule(name: string): void {
|
|
33
|
-
this.rules.delete(name);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async evaluateNode(node: NodeRecord, ctx: RuleContext): Promise<void> {
|
|
37
|
-
for (const rule of this.rules.values()) {
|
|
38
|
-
if (rule.whenType && node.type !== rule.whenType) continue;
|
|
39
|
-
if (rule.predicate) {
|
|
40
|
-
const ok = await rule.predicate(node);
|
|
41
|
-
if (!ok) continue;
|
|
42
|
-
}
|
|
43
|
-
await rule.action(ctx, node);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
package/legacy/main.rs
DELETED
package/legacy/main.ts
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { GunDB } from "./core/database.ts";
|
|
2
|
-
import { debugLog as _debugLog } from "./util/debug.ts";
|
|
3
|
-
import { startApiServer } from "./http/api-server.ts";
|
|
4
|
-
import { loadConfig, saveConfig } from "./config.ts";
|
|
5
|
-
|
|
6
|
-
function printUsage() {
|
|
7
|
-
console.log(
|
|
8
|
-
[
|
|
9
|
-
"Usage:",
|
|
10
|
-
" deno run -A src/main.ts serve [--port <port>] [--kv <path>] [ws://peer ...]",
|
|
11
|
-
" deno run -A src/main.ts put <id> <json> [--kv <path>]",
|
|
12
|
-
" deno run -A src/main.ts get <id> [--kv <path>]",
|
|
13
|
-
" deno run -A src/main.ts delete <id> [--kv <path>]",
|
|
14
|
-
" deno run -A src/main.ts vsearch <query> <k> [--kv <path>]",
|
|
15
|
-
" deno run -A src/main.ts type <id> <TypeName> [--kv <path>]",
|
|
16
|
-
" deno run -A src/main.ts instances <TypeName> [--kv <path>]",
|
|
17
|
-
" deno run -A src/main.ts list [--kv <path>]",
|
|
18
|
-
"",
|
|
19
|
-
].join("\n"),
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (import.meta.main) {
|
|
24
|
-
const [cmd, ...rest] = Deno.args;
|
|
25
|
-
switch (cmd) {
|
|
26
|
-
case "serve": {
|
|
27
|
-
const cfg = await loadConfig();
|
|
28
|
-
let port = cfg.port ?? 8080;
|
|
29
|
-
let kvPath: string | undefined = cfg.kvPath;
|
|
30
|
-
const pi = rest.indexOf("--port");
|
|
31
|
-
if (pi >= 0 && rest[pi + 1]) {
|
|
32
|
-
const n = Number(rest[pi + 1]);
|
|
33
|
-
if (Number.isFinite(n)) port = n;
|
|
34
|
-
}
|
|
35
|
-
const ki = rest.indexOf("--kv");
|
|
36
|
-
if (ki >= 0 && rest[ki + 1]) kvPath = rest[ki + 1];
|
|
37
|
-
const peers = (cfg.peers ?? []).concat(
|
|
38
|
-
rest.filter((v) => v.startsWith("ws://") || v.startsWith("wss://")),
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const db = new GunDB();
|
|
42
|
-
await db.ready(kvPath);
|
|
43
|
-
db.serve({ port });
|
|
44
|
-
for (const p of peers) db.connect(p);
|
|
45
|
-
|
|
46
|
-
const api = startApiServer({ port: port + (cfg.apiPortOffset ?? 1), db });
|
|
47
|
-
console.log(`PluresDB node serving on ws://localhost:${port}`);
|
|
48
|
-
console.log(`HTTP API/UI on ${api.url}`);
|
|
49
|
-
if (peers.length) console.log("Connected to peers:", peers.join(", "));
|
|
50
|
-
|
|
51
|
-
// Keep process alive
|
|
52
|
-
await new Promise(() => {});
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
case "put": {
|
|
56
|
-
const [id, json, ...flags] = rest;
|
|
57
|
-
if (!id || !json) {
|
|
58
|
-
printUsage();
|
|
59
|
-
Deno.exit(1);
|
|
60
|
-
}
|
|
61
|
-
let kvPath: string | undefined;
|
|
62
|
-
const ki = flags.indexOf("--kv");
|
|
63
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
64
|
-
const db = new GunDB();
|
|
65
|
-
await db.ready(kvPath);
|
|
66
|
-
const obj = JSON.parse(json);
|
|
67
|
-
await db.put(id, obj);
|
|
68
|
-
console.log("ok");
|
|
69
|
-
await db.close();
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
case "get": {
|
|
73
|
-
const [id, ...flags] = rest;
|
|
74
|
-
if (!id) {
|
|
75
|
-
printUsage();
|
|
76
|
-
Deno.exit(1);
|
|
77
|
-
}
|
|
78
|
-
let kvPath: string | undefined;
|
|
79
|
-
const ki = flags.indexOf("--kv");
|
|
80
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
81
|
-
const db = new GunDB();
|
|
82
|
-
await db.ready(kvPath);
|
|
83
|
-
const val = await db.get<Record<string, unknown>>(id);
|
|
84
|
-
console.log(JSON.stringify(val));
|
|
85
|
-
await db.close();
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
case "delete": {
|
|
89
|
-
const [id, ...flags] = rest;
|
|
90
|
-
if (!id) {
|
|
91
|
-
printUsage();
|
|
92
|
-
Deno.exit(1);
|
|
93
|
-
}
|
|
94
|
-
let kvPath: string | undefined;
|
|
95
|
-
const ki = flags.indexOf("--kv");
|
|
96
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
97
|
-
const db = new GunDB();
|
|
98
|
-
await db.ready(kvPath);
|
|
99
|
-
await db.delete(id);
|
|
100
|
-
console.log("ok");
|
|
101
|
-
await db.close();
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case "vsearch": {
|
|
105
|
-
const [query, kRaw, ...flags] = rest;
|
|
106
|
-
if (!query || !kRaw) {
|
|
107
|
-
printUsage();
|
|
108
|
-
Deno.exit(1);
|
|
109
|
-
}
|
|
110
|
-
const k = Number(kRaw);
|
|
111
|
-
if (!Number.isFinite(k)) {
|
|
112
|
-
printUsage();
|
|
113
|
-
Deno.exit(1);
|
|
114
|
-
}
|
|
115
|
-
let kvPath: string | undefined;
|
|
116
|
-
const ki = flags.indexOf("--kv");
|
|
117
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
118
|
-
const db = new GunDB();
|
|
119
|
-
await db.ready(kvPath);
|
|
120
|
-
const results = await db.vectorSearch(query, k);
|
|
121
|
-
console.log(
|
|
122
|
-
JSON.stringify(results.map((n) => ({ id: n.id, data: n.data }))),
|
|
123
|
-
);
|
|
124
|
-
await db.close();
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
case "type": {
|
|
128
|
-
const [id, typeName, ...flags] = rest;
|
|
129
|
-
if (!id || !typeName) {
|
|
130
|
-
printUsage();
|
|
131
|
-
Deno.exit(1);
|
|
132
|
-
}
|
|
133
|
-
let kvPath: string | undefined;
|
|
134
|
-
const ki = flags.indexOf("--kv");
|
|
135
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
136
|
-
const db = new GunDB();
|
|
137
|
-
await db.ready(kvPath);
|
|
138
|
-
await db.setType(id, typeName);
|
|
139
|
-
console.log("ok");
|
|
140
|
-
await db.close();
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
case "instances": {
|
|
144
|
-
const [typeName, ...flags] = rest;
|
|
145
|
-
if (!typeName) {
|
|
146
|
-
printUsage();
|
|
147
|
-
Deno.exit(1);
|
|
148
|
-
}
|
|
149
|
-
let kvPath: string | undefined;
|
|
150
|
-
const ki = flags.indexOf("--kv");
|
|
151
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
152
|
-
const db = new GunDB();
|
|
153
|
-
await db.ready(kvPath);
|
|
154
|
-
const rows = await db.instancesOf(typeName);
|
|
155
|
-
console.log(
|
|
156
|
-
JSON.stringify(rows.map((n) => ({ id: n.id, data: n.data }))),
|
|
157
|
-
);
|
|
158
|
-
await db.close();
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
case "list": {
|
|
162
|
-
const flags = rest;
|
|
163
|
-
let kvPath: string | undefined;
|
|
164
|
-
const ki = flags.indexOf("--kv");
|
|
165
|
-
if (ki >= 0 && flags[ki + 1]) kvPath = flags[ki + 1];
|
|
166
|
-
const db = new GunDB();
|
|
167
|
-
await db.ready(kvPath);
|
|
168
|
-
const nodes = await db.getAll();
|
|
169
|
-
const out = nodes.map((node) => ({
|
|
170
|
-
id: node.id,
|
|
171
|
-
data: node.data as Record<string, unknown>,
|
|
172
|
-
}));
|
|
173
|
-
console.log(JSON.stringify(out));
|
|
174
|
-
await db.close();
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
case "config": {
|
|
178
|
-
const cfg = await loadConfig();
|
|
179
|
-
console.log(JSON.stringify(cfg, null, 2));
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
case "config:set": {
|
|
183
|
-
const [key, value] = rest;
|
|
184
|
-
if (!key || value === undefined) {
|
|
185
|
-
printUsage();
|
|
186
|
-
Deno.exit(1);
|
|
187
|
-
}
|
|
188
|
-
const cfg = await loadConfig();
|
|
189
|
-
(cfg as any)[key] = /^[0-9]+$/.test(value) ? Number(value) : value;
|
|
190
|
-
await saveConfig(cfg);
|
|
191
|
-
console.log("ok");
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
default:
|
|
195
|
-
printUsage();
|
|
196
|
-
}
|
|
197
|
-
}
|