@livestore/livestore 0.0.12 → 0.0.14
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 +25 -28
- package/dist/.tsbuildinfo +1 -0
- package/dist/QueryCache.d.ts +20 -0
- package/dist/QueryCache.d.ts.map +1 -0
- package/dist/QueryCache.js +71 -0
- package/dist/QueryCache.js.map +1 -0
- package/dist/__tests__/react/fixture.d.ts +26 -0
- package/dist/__tests__/react/fixture.d.ts.map +1 -0
- package/dist/__tests__/react/fixture.js +60 -0
- package/dist/__tests__/react/fixture.js.map +1 -0
- package/dist/__tests__/react/useComponentState.test.d.ts +2 -0
- package/dist/__tests__/react/useComponentState.test.d.ts.map +1 -0
- package/dist/__tests__/react/useComponentState.test.js +68 -0
- package/dist/__tests__/react/useComponentState.test.js.map +1 -0
- package/dist/__tests__/react/useLQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useLQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useLQuery.test.js +38 -0
- package/dist/__tests__/react/useLQuery.test.js.map +1 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts +2 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts.map +1 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.js +73 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.js.map +1 -0
- package/dist/__tests__/react/useQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useQuery.test.js +33 -0
- package/dist/__tests__/react/useQuery.test.js.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts +2 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js +38 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js.map +1 -0
- package/dist/__tests__/reactive.test.d.ts +2 -0
- package/dist/__tests__/reactive.test.d.ts.map +1 -0
- package/dist/__tests__/reactive.test.js +271 -0
- package/dist/__tests__/reactive.test.js.map +1 -0
- package/dist/__tests__/reactiveQueries/sql.test.d.ts +2 -0
- package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +1 -0
- package/dist/__tests__/reactiveQueries/sql.test.js +337 -0
- package/dist/__tests__/reactiveQueries/sql.test.js.map +1 -0
- package/dist/bounded-collections.d.ts +34 -0
- package/dist/bounded-collections.d.ts.map +1 -0
- package/dist/bounded-collections.js +103 -0
- package/dist/bounded-collections.js.map +1 -0
- package/dist/componentKey.d.ts +20 -0
- package/dist/componentKey.d.ts.map +1 -0
- package/dist/componentKey.js +3 -0
- package/dist/componentKey.js.map +1 -0
- package/dist/effect/LiveStore.d.ts +36 -0
- package/dist/effect/LiveStore.d.ts.map +1 -0
- package/dist/effect/LiveStore.js +41 -0
- package/dist/effect/LiveStore.js.map +1 -0
- package/dist/effect/index.d.ts +2 -0
- package/dist/effect/index.d.ts.map +1 -0
- package/dist/effect/index.js +2 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/events.d.ts +7 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/inMemoryDatabase.d.ts +56 -0
- package/dist/inMemoryDatabase.d.ts.map +1 -0
- package/dist/inMemoryDatabase.js +223 -0
- package/dist/inMemoryDatabase.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations.d.ts +16 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +67 -0
- package/dist/migrations.js.map +1 -0
- package/dist/otel.d.ts +4 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +6 -0
- package/dist/otel.js.map +1 -0
- package/dist/react/LiveStoreContext.d.ts +11 -0
- package/dist/react/LiveStoreContext.d.ts.map +1 -0
- package/dist/react/LiveStoreContext.js +10 -0
- package/dist/react/LiveStoreContext.js.map +1 -0
- package/dist/react/LiveStoreProvider.d.ts +20 -0
- package/dist/react/LiveStoreProvider.d.ts.map +1 -0
- package/dist/react/LiveStoreProvider.js +52 -0
- package/dist/react/LiveStoreProvider.js.map +1 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useComponentState.d.ts +50 -0
- package/dist/react/useComponentState.d.ts.map +1 -0
- package/dist/react/useComponentState.js +248 -0
- package/dist/react/useComponentState.js.map +1 -0
- package/dist/react/useGlobalQuery.d.ts +3 -0
- package/dist/react/useGlobalQuery.d.ts.map +1 -0
- package/dist/react/useGlobalQuery.js +26 -0
- package/dist/react/useGlobalQuery.js.map +1 -0
- package/dist/react/useGraphQL.d.ts +13 -0
- package/dist/react/useGraphQL.d.ts.map +1 -0
- package/dist/react/useGraphQL.js +87 -0
- package/dist/react/useGraphQL.js.map +1 -0
- package/dist/react/useLiveStoreComponent.d.ts +75 -0
- package/dist/react/useLiveStoreComponent.d.ts.map +1 -0
- package/dist/react/useLiveStoreComponent.js +361 -0
- package/dist/react/useLiveStoreComponent.js.map +1 -0
- package/dist/react/useQuery.d.ts +3 -0
- package/dist/react/useQuery.d.ts.map +1 -0
- package/dist/react/useQuery.js +42 -0
- package/dist/react/useQuery.js.map +1 -0
- package/dist/react/useTemporaryQuery.d.ts +8 -0
- package/dist/react/useTemporaryQuery.d.ts.map +1 -0
- package/dist/react/useTemporaryQuery.js +17 -0
- package/dist/react/useTemporaryQuery.js.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts +3 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.js +40 -0
- package/dist/react/utils/extractNamesFromStackTrace.js.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts +7 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js +40 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js.map +1 -0
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts +13 -0
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +1 -0
- package/dist/react/utils/useStateRefWithReactiveInput.js +38 -0
- package/dist/react/utils/useStateRefWithReactiveInput.js.map +1 -0
- package/dist/reactive.d.ts +134 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +409 -0
- package/dist/reactive.js.map +1 -0
- package/dist/reactiveQueries/base-class.d.ts +32 -0
- package/dist/reactiveQueries/base-class.d.ts.map +1 -0
- package/dist/reactiveQueries/base-class.js +30 -0
- package/dist/reactiveQueries/base-class.js.map +1 -0
- package/dist/reactiveQueries/graph.d.ts +10 -0
- package/dist/reactiveQueries/graph.d.ts.map +1 -0
- package/dist/reactiveQueries/graph.js +6 -0
- package/dist/reactiveQueries/graph.js.map +1 -0
- package/dist/reactiveQueries/graphql.d.ts +42 -0
- package/dist/reactiveQueries/graphql.d.ts.map +1 -0
- package/dist/reactiveQueries/graphql.js +99 -0
- package/dist/reactiveQueries/graphql.js.map +1 -0
- package/dist/reactiveQueries/js.d.ts +23 -0
- package/dist/reactiveQueries/js.d.ts.map +1 -0
- package/dist/reactiveQueries/js.js +36 -0
- package/dist/reactiveQueries/js.js.map +1 -0
- package/dist/reactiveQueries/sql.d.ts +35 -0
- package/dist/reactiveQueries/sql.d.ts.map +1 -0
- package/dist/reactiveQueries/sql.js +97 -0
- package/dist/reactiveQueries/sql.js.map +1 -0
- package/dist/schema.d.ts +81 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +46 -0
- package/dist/schema.js.map +1 -0
- package/dist/storage/in-memory/index.d.ts +15 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -0
- package/dist/storage/in-memory/index.js +14 -0
- package/dist/storage/in-memory/index.js.map +1 -0
- package/dist/storage/index.d.ts +14 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +9 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/tauri/index.d.ts +19 -0
- package/dist/storage/tauri/index.d.ts.map +1 -0
- package/dist/storage/tauri/index.js +38 -0
- package/dist/storage/tauri/index.js.map +1 -0
- package/dist/storage/utils/idb.d.ts +10 -0
- package/dist/storage/utils/idb.d.ts.map +1 -0
- package/dist/storage/utils/idb.js +58 -0
- package/dist/storage/utils/idb.js.map +1 -0
- package/dist/storage/web-worker/index.d.ts +27 -0
- package/dist/storage/web-worker/index.d.ts.map +1 -0
- package/dist/storage/web-worker/index.js +74 -0
- package/dist/storage/web-worker/index.js.map +1 -0
- package/dist/storage/web-worker/worker.d.ts +13 -0
- package/dist/storage/web-worker/worker.d.ts.map +1 -0
- package/dist/storage/web-worker/worker.js +110 -0
- package/dist/storage/web-worker/worker.js.map +1 -0
- package/dist/store.d.ts +159 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +626 -0
- package/dist/store.js.map +1 -0
- package/dist/util.d.ts +28 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +55 -0
- package/dist/util.js.map +1 -0
- package/package.json +47 -19
- package/src/QueryCache.ts +1 -1
- package/src/__tests__/react/fixture.tsx +35 -39
- package/src/__tests__/react/{useLiveStoreComponent.test.tsx → useComponentState.test.tsx} +9 -20
- package/src/__tests__/react/useQuery.test.tsx +48 -0
- package/src/__tests__/react/utils/extractStackInfoFromStackTrace.test.ts +40 -0
- package/src/__tests__/reactive.test.ts +194 -142
- package/src/__tests__/reactiveQueries/sql.test.ts +372 -0
- package/src/effect/LiveStore.ts +22 -31
- package/src/events.ts +1 -1
- package/src/inMemoryDatabase.ts +117 -142
- package/src/index.ts +18 -22
- package/src/migrations.ts +119 -0
- package/src/otel.ts +0 -11
- package/src/react/LiveStoreProvider.tsx +24 -23
- package/src/react/index.ts +12 -7
- package/src/react/useComponentState.ts +409 -0
- package/src/react/useQuery.ts +58 -0
- package/src/react/useTemporaryQuery.ts +21 -0
- package/src/react/utils/extractStackInfoFromStackTrace.ts +47 -0
- package/src/reactive.ts +386 -267
- package/src/reactiveQueries/base-class.ts +61 -39
- package/src/reactiveQueries/graph.ts +15 -0
- package/src/reactiveQueries/graphql.ts +147 -31
- package/src/reactiveQueries/js.ts +54 -21
- package/src/reactiveQueries/sql.ts +128 -37
- package/src/schema.ts +69 -145
- package/src/storage/in-memory/index.ts +21 -0
- package/src/storage/index.ts +27 -0
- package/src/{backends/tauri.ts → storage/tauri/index.ts} +14 -28
- package/src/storage/web-worker/index.ts +116 -0
- package/src/{backends/web-worker.ts → storage/web-worker/worker.ts} +17 -52
- package/src/store.ts +466 -457
- package/src/util.ts +13 -3
- package/tsconfig.json +1 -3
- package/src/backends/base.ts +0 -67
- package/src/backends/index.ts +0 -98
- package/src/backends/noop.ts +0 -32
- package/src/backends/web-in-memory.ts +0 -65
- package/src/backends/web.ts +0 -97
- package/src/react/useGlobalQuery.ts +0 -40
- package/src/react/useGraphQL.ts +0 -112
- package/src/react/useLiveStoreComponent.ts +0 -483
- /package/src/{backends → storage}/utils/idb.ts +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* eslint-disable unicorn/prefer-add-event-listener */
|
|
2
|
+
/* eslint-disable prefer-arrow/prefer-arrow-functions */
|
|
3
|
+
export class IDB {
|
|
4
|
+
constructor(dbName, storeName = 'binary_store') {
|
|
5
|
+
this.dbName = dbName;
|
|
6
|
+
this.storeName = storeName;
|
|
7
|
+
this.db = null;
|
|
8
|
+
}
|
|
9
|
+
async open() {
|
|
10
|
+
if (this.db)
|
|
11
|
+
return this.db;
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const openRequest = indexedDB.open(this.dbName, 1);
|
|
14
|
+
openRequest.onupgradeneeded = () => {
|
|
15
|
+
const db = openRequest.result;
|
|
16
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
17
|
+
db.createObjectStore(this.storeName);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
openRequest.onsuccess = () => {
|
|
21
|
+
this.db = openRequest.result;
|
|
22
|
+
resolve(this.db);
|
|
23
|
+
};
|
|
24
|
+
openRequest.onerror = () => {
|
|
25
|
+
reject(new Error('Failed to open database.'));
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async get(key) {
|
|
30
|
+
const db = await this.open();
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const transaction = db.transaction(this.storeName, 'readonly');
|
|
33
|
+
const store = transaction.objectStore(this.storeName);
|
|
34
|
+
const getRequest = store.get(key);
|
|
35
|
+
getRequest.onsuccess = () => {
|
|
36
|
+
resolve(getRequest.result);
|
|
37
|
+
};
|
|
38
|
+
getRequest.onerror = () => {
|
|
39
|
+
reject(new Error('Failed to get data.'));
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async put(key, value) {
|
|
44
|
+
const db = await this.open();
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const transaction = db.transaction(this.storeName, 'readwrite');
|
|
47
|
+
const store = transaction.objectStore(this.storeName);
|
|
48
|
+
const putRequest = store.put(value, key);
|
|
49
|
+
putRequest.onsuccess = () => {
|
|
50
|
+
resolve();
|
|
51
|
+
};
|
|
52
|
+
putRequest.onerror = () => {
|
|
53
|
+
reject(new Error('Failed to write data.'));
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=idb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idb.js","sourceRoot":"","sources":["../../../src/storage/utils/idb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as otel from '@opentelemetry/api';
|
|
2
|
+
import * as Comlink from 'comlink';
|
|
3
|
+
import type { PreparedBindValues } from '../../util.js';
|
|
4
|
+
import type { Storage, StorageOtelProps } from '../index.js';
|
|
5
|
+
import type { WrappedWorker } from './worker.js';
|
|
6
|
+
export type StorageType = 'opfs' | 'indexeddb';
|
|
7
|
+
export type StorageOptionsWeb = {
|
|
8
|
+
/** Specifies where to persist data for this storage */
|
|
9
|
+
type: StorageType;
|
|
10
|
+
fileName: string;
|
|
11
|
+
};
|
|
12
|
+
export declare class WebWorkerStorage implements Storage {
|
|
13
|
+
worker: Comlink.Remote<WrappedWorker>;
|
|
14
|
+
options: StorageOptionsWeb;
|
|
15
|
+
otelTracer: otel.Tracer;
|
|
16
|
+
executionBacklog: {
|
|
17
|
+
query: string;
|
|
18
|
+
bindValues?: PreparedBindValues;
|
|
19
|
+
}[];
|
|
20
|
+
executionPromise: Promise<void> | undefined;
|
|
21
|
+
private constructor();
|
|
22
|
+
static load: (options: StorageOptionsWeb) => ({ otelTracer }: StorageOtelProps) => WebWorkerStorage;
|
|
23
|
+
execute: (query: string, bindValues?: PreparedBindValues) => void;
|
|
24
|
+
private executeBacklog;
|
|
25
|
+
getPersistedData: (_parentSpan?: otel.Span) => Promise<Uint8Array>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/web-worker/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,IAAI,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAA;AAE9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,uDAAuD;IACvD,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,gBAAiB,YAAW,OAAO;IAC9C,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;IACrC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,UAAU,EAAE,IAAI,CAAC,MAAM,CAAA;IAEvB,gBAAgB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,kBAAkB,CAAA;KAAE,EAAE,CAAK;IAC3E,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAA;IAE3C,OAAO;IAmBP,MAAM,CAAC,IAAI,YAAa,iBAAiB,sBASf,gBAAgB,sBAOzC;IAED,OAAO,UAAW,MAAM,eAAe,kBAAkB,UAaxD;IAED,OAAO,CAAC,cAAc,CAIrB;IAED,gBAAgB,iBAAwB,KAAK,IAAI,KAAG,QAAQ,UAAU,CAAC,CAAkC;CAC1G"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { casesHandled } from '@livestore/utils';
|
|
2
|
+
import * as Comlink from 'comlink';
|
|
3
|
+
import { IDB } from '../utils/idb.js';
|
|
4
|
+
export class WebWorkerStorage {
|
|
5
|
+
constructor({ worker, options, otelTracer, executionPromise, }) {
|
|
6
|
+
this.executionBacklog = [];
|
|
7
|
+
this.execute = (query, bindValues) => {
|
|
8
|
+
this.executionBacklog.push({ query, bindValues });
|
|
9
|
+
// Instead of sending the queries to the worker immediately, we wait a bit and batch them up (which reduces the number of messages sent to the worker)
|
|
10
|
+
if (this.executionPromise === undefined) {
|
|
11
|
+
this.executionPromise = new Promise((resolve) => {
|
|
12
|
+
setTimeout(() => {
|
|
13
|
+
this.executeBacklog();
|
|
14
|
+
resolve();
|
|
15
|
+
}, 10);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
this.executeBacklog = () => {
|
|
20
|
+
void this.worker.executeBulk(this.executionBacklog);
|
|
21
|
+
this.executionBacklog = [];
|
|
22
|
+
this.executionPromise = undefined;
|
|
23
|
+
};
|
|
24
|
+
this.getPersistedData = async (_parentSpan) => getPersistedData(this.options);
|
|
25
|
+
this.worker = worker;
|
|
26
|
+
this.options = options;
|
|
27
|
+
this.otelTracer = otelTracer;
|
|
28
|
+
this.executionPromise = executionPromise;
|
|
29
|
+
executionPromise.then(() => this.executeBacklog());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
WebWorkerStorage.load = (options) => {
|
|
33
|
+
// TODO: Importing the worker like this only works with Vite;
|
|
34
|
+
// should this really be inside the LiveStore library?
|
|
35
|
+
// Doesn't work with Firefox right now during dev https://bugzilla.mozilla.org/show_bug.cgi?id=1247687
|
|
36
|
+
const worker = new Worker(new URL('./worker.js', import.meta.url), {
|
|
37
|
+
type: 'module',
|
|
38
|
+
});
|
|
39
|
+
const wrappedWorker = Comlink.wrap(worker);
|
|
40
|
+
return ({ otelTracer }) => new WebWorkerStorage({
|
|
41
|
+
worker: wrappedWorker,
|
|
42
|
+
options,
|
|
43
|
+
otelTracer,
|
|
44
|
+
executionPromise: wrappedWorker.initialize(options),
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const getPersistedData = async (options) => {
|
|
48
|
+
switch (options.type) {
|
|
49
|
+
case 'opfs': {
|
|
50
|
+
try {
|
|
51
|
+
const rootHandle = await navigator.storage.getDirectory();
|
|
52
|
+
const fileHandle = await rootHandle.getFileHandle(options.fileName + '.db');
|
|
53
|
+
const file = await fileHandle.getFile();
|
|
54
|
+
const buffer = await file.arrayBuffer();
|
|
55
|
+
const data = new Uint8Array(buffer);
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof DOMException && error.name === 'NotFoundError') {
|
|
60
|
+
return new Uint8Array();
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
case 'indexeddb': {
|
|
66
|
+
const idb = new IDB(options.fileName);
|
|
67
|
+
return (await idb.get('db')) ?? new Uint8Array();
|
|
68
|
+
}
|
|
69
|
+
default: {
|
|
70
|
+
casesHandled(options.type);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/web-worker/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Bindable } from '../../util.js';
|
|
2
|
+
import type { StorageOptionsWeb } from './index.js';
|
|
3
|
+
type ExecutionQueueItem = {
|
|
4
|
+
query: string;
|
|
5
|
+
bindValues?: Bindable;
|
|
6
|
+
};
|
|
7
|
+
declare const wrappedWorker: {
|
|
8
|
+
initialize: (options: StorageOptionsWeb) => Promise<void>;
|
|
9
|
+
executeBulk: (executionItems: ExecutionQueueItem[]) => void;
|
|
10
|
+
};
|
|
11
|
+
export type WrappedWorker = typeof wrappedWorker;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/storage/web-worker/worker.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAsEnD,KAAK,kBAAkB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAA;AA8ClE,QAAA,MAAM,aAAa;0BA5FgB,iBAAiB;kCAgDf,kBAAkB,EAAE,KAAG,IAAI;CA4Cf,CAAA;AAEjD,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Web Worker file for running SQLite in a web worker.
|
|
2
|
+
// TODO: create types for these libraries? SQL.js already should have types;
|
|
3
|
+
// we just need the types to apply to the fork.
|
|
4
|
+
import { shouldNeverHappen } from '@livestore/utils';
|
|
5
|
+
import * as Comlink from 'comlink';
|
|
6
|
+
import sqlite3InitModule from 'sqlite-esm';
|
|
7
|
+
import { casesHandled, sql } from '../../util.js';
|
|
8
|
+
import { IDB } from '../utils/idb.js';
|
|
9
|
+
// A global variable to hold the database connection.
|
|
10
|
+
// let db: SqliteWasm.Database
|
|
11
|
+
let db;
|
|
12
|
+
let sqlite3;
|
|
13
|
+
// TODO get rid of this in favour of a "proper" IDB SQLite storage
|
|
14
|
+
let idb;
|
|
15
|
+
/** The location where this database storage persists its data */
|
|
16
|
+
let options_;
|
|
17
|
+
const configureConnection = () => db.exec(sql `
|
|
18
|
+
PRAGMA page_size=8192;
|
|
19
|
+
PRAGMA journal_mode=MEMORY;
|
|
20
|
+
PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
|
|
21
|
+
`);
|
|
22
|
+
/** A full virtual filename in the IDB FS */
|
|
23
|
+
const fullyQualifiedFilename = (name) => `${name}.db`;
|
|
24
|
+
const initialize = async (options) => {
|
|
25
|
+
options_ = options;
|
|
26
|
+
sqlite3 = await sqlite3InitModule({
|
|
27
|
+
print: (message) => console.log(`[sql-client] ${message}`),
|
|
28
|
+
printErr: (message) => console.error(`[sql-client] ${message}`),
|
|
29
|
+
});
|
|
30
|
+
switch (options.type) {
|
|
31
|
+
case 'opfs': {
|
|
32
|
+
try {
|
|
33
|
+
db = new sqlite3.oo1.OpfsDb(fullyQualifiedFilename(options.fileName)); // , 'c'
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
debugger;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case 'indexeddb': {
|
|
41
|
+
try {
|
|
42
|
+
db = new sqlite3.oo1.DB({ filename: ':memory:', flags: 'c' });
|
|
43
|
+
idb = new IDB(options.fileName);
|
|
44
|
+
const bytes = await idb.get('db');
|
|
45
|
+
if (bytes !== undefined) {
|
|
46
|
+
// Based on https://sqlite.org/forum/forumpost/2119230da8ac5357a13b731f462dc76e08621a4a29724f7906d5f35bb8508465
|
|
47
|
+
// TODO find cleaner way to do this once possible in sqlite3-wasm
|
|
48
|
+
const p = sqlite3.wasm.allocFromTypedArray(bytes);
|
|
49
|
+
const _rc = sqlite3.capi.sqlite3_deserialize(db.pointer, 'main', p, bytes.length, bytes.length, 0);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
debugger;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
default: {
|
|
58
|
+
casesHandled(options.type);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
configureConnection();
|
|
62
|
+
};
|
|
63
|
+
// TODO get rid of this in favour of a "proper" IDB SQLite storage
|
|
64
|
+
let idbPersistTimeout;
|
|
65
|
+
const executeBulk = (executionItems) => {
|
|
66
|
+
let batchItems = [];
|
|
67
|
+
while (executionItems.length > 0) {
|
|
68
|
+
try {
|
|
69
|
+
db.exec('BEGIN TRANSACTION'); // Start the transaction
|
|
70
|
+
batchItems = executionItems.splice(0, 50);
|
|
71
|
+
for (const { query, bindValues } of batchItems) {
|
|
72
|
+
db.exec({
|
|
73
|
+
sql: query,
|
|
74
|
+
bind: bindValues,
|
|
75
|
+
returnValue: 'resultRows',
|
|
76
|
+
rowMode: 'object',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
db.exec('COMMIT'); // Commit the transaction
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
try {
|
|
83
|
+
db.exec('ROLLBACK'); // Rollback in case of an error
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
console.error('Error rolling back transaction', e);
|
|
87
|
+
}
|
|
88
|
+
shouldNeverHappen(`Error executing query: ${error} \n ${JSON.stringify(batchItems)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// TODO get rid of this in favour of a "proper" IDB SQLite storage
|
|
92
|
+
if (options_.type === 'indexeddb') {
|
|
93
|
+
if (idbPersistTimeout !== undefined) {
|
|
94
|
+
clearTimeout(idbPersistTimeout);
|
|
95
|
+
}
|
|
96
|
+
idbPersistTimeout = setTimeout(() => {
|
|
97
|
+
const data = sqlite3.capi.sqlite3_js_db_export(db.pointer);
|
|
98
|
+
void idb.put('db', data);
|
|
99
|
+
}, 1000);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const wrappedWorker = { initialize, executeBulk };
|
|
103
|
+
Comlink.expose(wrappedWorker);
|
|
104
|
+
// NOTE keep this around for debugging
|
|
105
|
+
// db.exec({
|
|
106
|
+
// sql: `select * from sqlite_master where name = 'library_tracks'`,
|
|
107
|
+
// callback: (_: TODO) => console.log(_),
|
|
108
|
+
// rowMode: 'object',
|
|
109
|
+
// } as TODO)
|
|
110
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/storage/web-worker/worker.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as otel from '@opentelemetry/api';
|
|
2
|
+
import type { GraphQLSchema } from 'graphql';
|
|
3
|
+
import type * as Sqlite from 'sqlite-esm';
|
|
4
|
+
import type { ComponentKey } from './componentKey.js';
|
|
5
|
+
import type { LiveStoreEvent } from './events.js';
|
|
6
|
+
import { InMemoryDatabase } from './inMemoryDatabase.js';
|
|
7
|
+
import type { ReactiveGraph, Ref } from './reactive.js';
|
|
8
|
+
import type { ILiveStoreQuery } from './reactiveQueries/base-class.js';
|
|
9
|
+
import { type DbContext } from './reactiveQueries/graph.js';
|
|
10
|
+
import type { LiveStoreGraphQLQuery } from './reactiveQueries/graphql.js';
|
|
11
|
+
import type { LiveStoreJSQuery } from './reactiveQueries/js.js';
|
|
12
|
+
import type { LiveStoreSQLQuery } from './reactiveQueries/sql.js';
|
|
13
|
+
import type { GetActionArgs, Schema } from './schema.js';
|
|
14
|
+
import type { Storage, StorageInit } from './storage/index.js';
|
|
15
|
+
import type { ParamsObject } from './util.js';
|
|
16
|
+
export type LiveStoreQuery<TResult extends Record<string, any> = any> = LiveStoreSQLQuery<TResult> | LiveStoreJSQuery<TResult> | LiveStoreGraphQLQuery<TResult, any, any>;
|
|
17
|
+
export type BaseGraphQLContext = {
|
|
18
|
+
queriedTables: Set<string>;
|
|
19
|
+
/** Needed by Pothos Otel plugin for resolver tracing to work */
|
|
20
|
+
otelContext?: otel.Context;
|
|
21
|
+
};
|
|
22
|
+
export type QueryResult<TQuery> = TQuery extends LiveStoreSQLQuery<infer R> ? ReadonlyArray<Readonly<R>> : TQuery extends LiveStoreJSQuery<infer S> ? Readonly<S> : TQuery extends LiveStoreGraphQLQuery<infer Result, any, any> ? Readonly<Result> : never;
|
|
23
|
+
export declare const globalComponentKey: ComponentKey;
|
|
24
|
+
export type GraphQLOptions<TContext> = {
|
|
25
|
+
schema: GraphQLSchema;
|
|
26
|
+
makeContext: (db: InMemoryDatabase, tracer: otel.Tracer) => TContext;
|
|
27
|
+
};
|
|
28
|
+
export type StoreOptions<TGraphQLContext extends BaseGraphQLContext> = {
|
|
29
|
+
db: InMemoryDatabase;
|
|
30
|
+
/** A `Proxy`d version of `db` except that it also mirrors `execute` calls to the storage */
|
|
31
|
+
dbProxy: InMemoryDatabase;
|
|
32
|
+
schema: Schema;
|
|
33
|
+
storage?: Storage;
|
|
34
|
+
graphQLOptions?: GraphQLOptions<TGraphQLContext>;
|
|
35
|
+
otelTracer: otel.Tracer;
|
|
36
|
+
otelRootSpanContext: otel.Context;
|
|
37
|
+
};
|
|
38
|
+
export type RefreshReason = {
|
|
39
|
+
_tag: 'applyEvent';
|
|
40
|
+
/** The event that was applied */
|
|
41
|
+
event: Omit<LiveStoreEvent, 'id'>;
|
|
42
|
+
/** The tables that were written to by the event */
|
|
43
|
+
writeTables: string[];
|
|
44
|
+
} | {
|
|
45
|
+
_tag: 'applyEvents';
|
|
46
|
+
/** The events that was applied */
|
|
47
|
+
events: Omit<LiveStoreEvent, 'id'>[];
|
|
48
|
+
/** The tables that were written to by the event */
|
|
49
|
+
writeTables: string[];
|
|
50
|
+
}
|
|
51
|
+
/** Usually in response to some `applyEvent`/`applyEvents` with `skipRefresh: true` */
|
|
52
|
+
| {
|
|
53
|
+
_tag: 'manualRefresh';
|
|
54
|
+
} | {
|
|
55
|
+
_tag: 'makeThunk';
|
|
56
|
+
label?: string;
|
|
57
|
+
} | {
|
|
58
|
+
_tag: 'unknown';
|
|
59
|
+
};
|
|
60
|
+
export type QueryDebugInfo = {
|
|
61
|
+
_tag: 'graphql' | 'sql' | 'js' | 'unknown';
|
|
62
|
+
label: string;
|
|
63
|
+
query: string;
|
|
64
|
+
};
|
|
65
|
+
export type StoreOtel = {
|
|
66
|
+
tracer: otel.Tracer;
|
|
67
|
+
applyEventsSpanContext: otel.Context;
|
|
68
|
+
queriesSpanContext: otel.Context;
|
|
69
|
+
};
|
|
70
|
+
export declare class Store<TGraphQLContext extends BaseGraphQLContext = BaseGraphQLContext> {
|
|
71
|
+
graph: ReactiveGraph<RefreshReason, QueryDebugInfo, DbContext>;
|
|
72
|
+
inMemoryDB: InMemoryDatabase;
|
|
73
|
+
_proxyDb: InMemoryDatabase;
|
|
74
|
+
schema: Schema;
|
|
75
|
+
graphQLSchema?: GraphQLSchema;
|
|
76
|
+
graphQLContext?: TGraphQLContext;
|
|
77
|
+
otel: StoreOtel;
|
|
78
|
+
/**
|
|
79
|
+
* Note we're using `Ref<null>` here as we don't care about the value but only about *that* something has changed.
|
|
80
|
+
* This only works in combination with `equal: () => false` which will always trigger a refresh.
|
|
81
|
+
*/
|
|
82
|
+
tableRefs: {
|
|
83
|
+
[key: string]: Ref<null>;
|
|
84
|
+
};
|
|
85
|
+
activeQueries: Set<LiveStoreQuery>;
|
|
86
|
+
storage?: Storage;
|
|
87
|
+
temporaryQueries: Set<LiveStoreQuery> | undefined;
|
|
88
|
+
private constructor();
|
|
89
|
+
static createStore: <TGraphQLContext_1 extends BaseGraphQLContext>(storeOptions: StoreOptions<TGraphQLContext_1>, parentSpan: otel.Span) => Store<TGraphQLContext_1>;
|
|
90
|
+
/**
|
|
91
|
+
* Creates a reactive LiveStore SQL query
|
|
92
|
+
*
|
|
93
|
+
* NOTE The query is actually running (even if no one has subscribed to it yet) and will be kept up to date.
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Subscribe to the results of a query
|
|
97
|
+
* Returns a function to cancel the subscription.
|
|
98
|
+
*/
|
|
99
|
+
subscribe: <TResult>(query: ILiveStoreQuery<TResult>, onNewValue: (value: TResult) => void, onSubsubscribe?: () => void, options?: {
|
|
100
|
+
label?: string;
|
|
101
|
+
otelContext?: otel.Context;
|
|
102
|
+
} | undefined) => (() => void);
|
|
103
|
+
/**
|
|
104
|
+
* Destroys the entire store, including all queries and subscriptions.
|
|
105
|
+
*
|
|
106
|
+
* Currently only used when shutting down the app for debugging purposes (e.g. to close Otel spans).
|
|
107
|
+
*/
|
|
108
|
+
destroy: () => void;
|
|
109
|
+
applyEvent: <TEventType extends string>(eventType: TEventType, args?: any, options?: {
|
|
110
|
+
skipRefresh?: boolean;
|
|
111
|
+
}) => {
|
|
112
|
+
durationMs: number;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Apply multiple write events to the store, and refresh all queries in response.
|
|
116
|
+
* This is faster than calling applyEvent many times in quick succession because
|
|
117
|
+
* we can do a single refresh after all the events.
|
|
118
|
+
*/
|
|
119
|
+
applyEvents: (events: Iterable<{
|
|
120
|
+
eventType: string;
|
|
121
|
+
args: any;
|
|
122
|
+
}>, options?: {
|
|
123
|
+
label?: string;
|
|
124
|
+
skipRefresh?: boolean;
|
|
125
|
+
}) => {
|
|
126
|
+
durationMs: number;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* This can be used in combination with `skipRefresh` when applying events.
|
|
130
|
+
* We might need a better solution for this. Let's see.
|
|
131
|
+
*/
|
|
132
|
+
manualRefresh: (options?: {
|
|
133
|
+
label?: string;
|
|
134
|
+
}) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Apply an event to the store.
|
|
137
|
+
* Returns the tables that were affected by the event.
|
|
138
|
+
* This is an internal method that doesn't trigger a refresh;
|
|
139
|
+
* the caller must refresh queries after calling this method.
|
|
140
|
+
*/
|
|
141
|
+
private applyEventWithoutRefresh;
|
|
142
|
+
/**
|
|
143
|
+
* Directly execute a SQL query on the Store.
|
|
144
|
+
* This should only be used for framework-internal purposes;
|
|
145
|
+
* all app writes should go through applyEvent.
|
|
146
|
+
*/
|
|
147
|
+
execute: (query: string, params?: ParamsObject, writeTables?: string[]) => void;
|
|
148
|
+
}
|
|
149
|
+
/** Create a new LiveStore Store */
|
|
150
|
+
export declare const createStore: <TGraphQLContext extends BaseGraphQLContext>({ schema, loadStorage, graphQLOptions, otelTracer, otelRootSpanContext, boot, sqlite3, }: {
|
|
151
|
+
schema: Schema;
|
|
152
|
+
loadStorage: () => StorageInit | Promise<StorageInit>;
|
|
153
|
+
graphQLOptions?: GraphQLOptions<TGraphQLContext> | undefined;
|
|
154
|
+
otelTracer?: otel.Tracer | undefined;
|
|
155
|
+
otelRootSpanContext?: otel.Context | undefined;
|
|
156
|
+
boot?: ((db: InMemoryDatabase, parentSpan: otel.Span) => unknown | Promise<unknown>) | undefined;
|
|
157
|
+
sqlite3: Sqlite.Sqlite3Static;
|
|
158
|
+
}) => Promise<Store<TGraphQLContext>>;
|
|
159
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|