@procedures/store 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -0
- package/README.md +109 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/indexeddb/idb.d.ts +100 -0
- package/dist/indexeddb/idb.d.ts.map +1 -0
- package/dist/indexeddb/idb.js +137 -0
- package/dist/indexeddb/idb.js.map +1 -0
- package/dist/indexeddb/program-store.d.ts +42 -0
- package/dist/indexeddb/program-store.d.ts.map +1 -0
- package/dist/indexeddb/program-store.js +71 -0
- package/dist/indexeddb/program-store.js.map +1 -0
- package/dist/indexeddb/queue-store.d.ts +38 -0
- package/dist/indexeddb/queue-store.d.ts.map +1 -0
- package/dist/indexeddb/queue-store.js +73 -0
- package/dist/indexeddb/queue-store.js.map +1 -0
- package/dist/indexeddb.d.ts +19 -0
- package/dist/indexeddb.d.ts.map +1 -0
- package/dist/indexeddb.js +17 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/program-store/file.d.ts +5 -0
- package/dist/program-store/file.d.ts.map +1 -1
- package/dist/program-store/file.js +5 -2
- package/dist/program-store/file.js.map +1 -1
- package/dist/storage/api.d.ts +18 -7
- package/dist/storage/api.d.ts.map +1 -1
- package/dist/storage/api.js +34 -3
- package/dist/storage/api.js.map +1 -1
- package/dist/storage/factory.d.ts +13 -2
- package/dist/storage/factory.d.ts.map +1 -1
- package/dist/storage/factory.js +12 -4
- package/dist/storage/factory.js.map +1 -1
- package/dist/storage/file-queue.d.ts +32 -0
- package/dist/storage/file-queue.d.ts.map +1 -0
- package/dist/storage/file-queue.js +101 -0
- package/dist/storage/file-queue.js.map +1 -0
- package/dist/storage/hybrid.d.ts +361 -42
- package/dist/storage/hybrid.d.ts.map +1 -1
- package/dist/storage/hybrid.js +1102 -251
- package/dist/storage/hybrid.js.map +1 -1
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +5 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/queue.d.ts +67 -0
- package/dist/storage/queue.d.ts.map +1 -0
- package/dist/storage/queue.js +85 -0
- package/dist/storage/queue.js.map +1 -0
- package/dist/storage/synced-registry.d.ts +18 -2
- package/dist/storage/synced-registry.d.ts.map +1 -1
- package/dist/storage/synced-registry.js +37 -3
- package/dist/storage/synced-registry.js.map +1 -1
- package/dist/storage/types.d.ts +5 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/package.json +16 -6
- package/src/indexeddb/idb.ts +190 -0
- package/src/indexeddb/program-store.ts +80 -0
- package/src/indexeddb/queue-store.ts +80 -0
- package/src/indexeddb.ts +19 -0
- package/src/program-store/file.ts +5 -2
- package/src/storage/api.ts +50 -10
- package/src/storage/factory.ts +21 -4
- package/src/storage/file-queue.ts +103 -0
- package/src/storage/hybrid.ts +1151 -275
- package/src/storage/index.ts +15 -2
- package/src/storage/queue.ts +128 -0
- package/src/storage/synced-registry.ts +49 -4
- package/src/storage/types.ts +6 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The part of IndexedDB that the stores of `@procedures/store/indexeddb` use (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* The package compiles without the DOM types, so this module declares the shapes that it uses.
|
|
5
|
+
* The `indexedDB` of a browser fits them, and the `IDBFactory` of `fake-indexeddb` too. Nothing in
|
|
6
|
+
* this module reads a global value when it loads: Node can import it.
|
|
7
|
+
*/
|
|
8
|
+
/** A request of IndexedDB. */
|
|
9
|
+
export interface IdbRequestLike<R = unknown> {
|
|
10
|
+
readonly result: R;
|
|
11
|
+
readonly error: unknown;
|
|
12
|
+
onsuccess: ((event: any) => void) | null;
|
|
13
|
+
onerror: ((event: any) => void) | null;
|
|
14
|
+
}
|
|
15
|
+
/** The request that opens a database. */
|
|
16
|
+
export interface IdbOpenRequestLike extends IdbRequestLike<IdbDatabaseLike> {
|
|
17
|
+
onupgradeneeded: ((event: any) => void) | null;
|
|
18
|
+
}
|
|
19
|
+
/** The factory of the databases: `indexedDB` in a browser. */
|
|
20
|
+
export interface IdbFactoryLike {
|
|
21
|
+
open(name: string, version?: number): IdbOpenRequestLike;
|
|
22
|
+
}
|
|
23
|
+
/** An open database. */
|
|
24
|
+
export interface IdbDatabaseLike {
|
|
25
|
+
readonly objectStoreNames: {
|
|
26
|
+
contains(name: string): boolean;
|
|
27
|
+
};
|
|
28
|
+
createObjectStore(name: string, options?: {
|
|
29
|
+
keyPath?: string;
|
|
30
|
+
autoIncrement?: boolean;
|
|
31
|
+
}): unknown;
|
|
32
|
+
transaction(names: string, mode?: "readonly" | "readwrite"): IdbTransactionLike;
|
|
33
|
+
close(): void;
|
|
34
|
+
onversionchange: ((event: any) => void) | null;
|
|
35
|
+
}
|
|
36
|
+
/** A transaction. */
|
|
37
|
+
export interface IdbTransactionLike {
|
|
38
|
+
readonly error: unknown;
|
|
39
|
+
objectStore(name: string): IdbObjectStoreLike;
|
|
40
|
+
abort(): void;
|
|
41
|
+
oncomplete: ((event: any) => void) | null;
|
|
42
|
+
onerror: ((event: any) => void) | null;
|
|
43
|
+
onabort: ((event: any) => void) | null;
|
|
44
|
+
}
|
|
45
|
+
/** An object store in a transaction. */
|
|
46
|
+
export interface IdbObjectStoreLike {
|
|
47
|
+
get(key: string): IdbRequestLike<unknown>;
|
|
48
|
+
getAll(): IdbRequestLike<unknown[]>;
|
|
49
|
+
count(key?: string): IdbRequestLike<number>;
|
|
50
|
+
put(value: unknown, key?: string): IdbRequestLike<unknown>;
|
|
51
|
+
add(value: unknown, key?: string): IdbRequestLike<unknown>;
|
|
52
|
+
delete(key: string): IdbRequestLike<unknown>;
|
|
53
|
+
clear(): IdbRequestLike<unknown>;
|
|
54
|
+
}
|
|
55
|
+
/** The options of the IndexedDB stores. */
|
|
56
|
+
export interface IndexedDbOptions {
|
|
57
|
+
/**
|
|
58
|
+
* The factory of the databases. The tests give the one of `fake-indexeddb`.
|
|
59
|
+
* @default the `indexedDB` of the global scope
|
|
60
|
+
*/
|
|
61
|
+
indexedDB?: IdbFactoryLike;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* This function gives true when the global scope has IndexedDB. A browser can still refuse to open a database,
|
|
65
|
+
* for example in some private windows: the first operation of a store then fails.
|
|
66
|
+
*/
|
|
67
|
+
export declare function hasIndexedDb(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* One object store in its own database, version 1. The connection opens at the first operation,
|
|
70
|
+
* and a failed open tries again at the next operation.
|
|
71
|
+
*/
|
|
72
|
+
export declare class IdbStoreConnection {
|
|
73
|
+
/** The name of the database. */
|
|
74
|
+
readonly database: string;
|
|
75
|
+
/** The name of the object store. */
|
|
76
|
+
readonly store: string;
|
|
77
|
+
private readonly storeOptions;
|
|
78
|
+
private readonly factory;
|
|
79
|
+
private connection;
|
|
80
|
+
private closed;
|
|
81
|
+
constructor(
|
|
82
|
+
/** The name of the database. */
|
|
83
|
+
database: string,
|
|
84
|
+
/** The name of the object store. */
|
|
85
|
+
store: string, storeOptions: {
|
|
86
|
+
keyPath?: string;
|
|
87
|
+
autoIncrement?: boolean;
|
|
88
|
+
}, factory: IdbFactoryLike | undefined);
|
|
89
|
+
/**
|
|
90
|
+
* This method runs work in one transaction. The work makes the requests, and it gives a function that reads
|
|
91
|
+
* their results. The promise resolves after the transaction commits, so a write is durable when
|
|
92
|
+
* the promise resolves. An error of a request aborts the transaction: each request is undone.
|
|
93
|
+
*/
|
|
94
|
+
run<R>(mode: "readonly" | "readwrite", work: (store: IdbObjectStoreLike) => () => R): Promise<R>;
|
|
95
|
+
/** This method closes the connection. A later operation throws. */
|
|
96
|
+
close(): Promise<void>;
|
|
97
|
+
private open;
|
|
98
|
+
private connect;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=idb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idb.d.ts","sourceRoot":"","sources":["../../src/indexeddb/idb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The part of IndexedDB that the stores of `@procedures/store/indexeddb` use (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* The package compiles without the DOM types, so this module declares the shapes that it uses.
|
|
5
|
+
* The `indexedDB` of a browser fits them, and the `IDBFactory` of `fake-indexeddb` too. Nothing in
|
|
6
|
+
* this module reads a global value when it loads: Node can import it.
|
|
7
|
+
*/
|
|
8
|
+
/** The `indexedDB` of the global scope, or undefined (Node, an old browser, some private windows). */
|
|
9
|
+
function globalFactory() {
|
|
10
|
+
return globalThis.indexedDB ?? undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* This function gives true when the global scope has IndexedDB. A browser can still refuse to open a database,
|
|
14
|
+
* for example in some private windows: the first operation of a store then fails.
|
|
15
|
+
*/
|
|
16
|
+
export function hasIndexedDb() {
|
|
17
|
+
return globalFactory() !== undefined;
|
|
18
|
+
}
|
|
19
|
+
/** The error of a request or a transaction, as an `Error`. */
|
|
20
|
+
function errorOf(cause, message) {
|
|
21
|
+
return cause instanceof Error ? cause : new Error(message, { cause });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One object store in its own database, version 1. The connection opens at the first operation,
|
|
25
|
+
* and a failed open tries again at the next operation.
|
|
26
|
+
*/
|
|
27
|
+
export class IdbStoreConnection {
|
|
28
|
+
database;
|
|
29
|
+
store;
|
|
30
|
+
storeOptions;
|
|
31
|
+
factory;
|
|
32
|
+
connection;
|
|
33
|
+
closed = false;
|
|
34
|
+
constructor(
|
|
35
|
+
/** The name of the database. */
|
|
36
|
+
database,
|
|
37
|
+
/** The name of the object store. */
|
|
38
|
+
store, storeOptions, factory) {
|
|
39
|
+
this.database = database;
|
|
40
|
+
this.store = store;
|
|
41
|
+
this.storeOptions = storeOptions;
|
|
42
|
+
this.factory = factory;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* This method runs work in one transaction. The work makes the requests, and it gives a function that reads
|
|
46
|
+
* their results. The promise resolves after the transaction commits, so a write is durable when
|
|
47
|
+
* the promise resolves. An error of a request aborts the transaction: each request is undone.
|
|
48
|
+
*/
|
|
49
|
+
async run(mode, work) {
|
|
50
|
+
const db = await this.open();
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
let transaction;
|
|
53
|
+
let read;
|
|
54
|
+
try {
|
|
55
|
+
transaction = db.transaction(this.store, mode);
|
|
56
|
+
read = work(transaction.objectStore(this.store));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
reject(error);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
transaction.oncomplete = () => {
|
|
63
|
+
try {
|
|
64
|
+
resolve(read());
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
reject(error);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
transaction.onerror = () => reject(errorOf(transaction.error, `The IndexedDB transaction on ${this.database} failed`));
|
|
71
|
+
transaction.onabort = () => reject(errorOf(transaction.error, `The IndexedDB transaction on ${this.database} was aborted`));
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** This method closes the connection. A later operation throws. */
|
|
75
|
+
async close() {
|
|
76
|
+
this.closed = true;
|
|
77
|
+
const connection = this.connection;
|
|
78
|
+
this.connection = undefined;
|
|
79
|
+
if (!connection)
|
|
80
|
+
return;
|
|
81
|
+
try {
|
|
82
|
+
(await connection).close();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// The open failed: there is nothing to close
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
open() {
|
|
89
|
+
if (this.closed)
|
|
90
|
+
return Promise.reject(new Error(`The IndexedDB store ${this.database} is closed`));
|
|
91
|
+
if (!this.connection) {
|
|
92
|
+
const connection = this.connect();
|
|
93
|
+
this.connection = connection;
|
|
94
|
+
connection.catch(() => {
|
|
95
|
+
if (this.connection === connection)
|
|
96
|
+
this.connection = undefined;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return this.connection;
|
|
100
|
+
}
|
|
101
|
+
connect() {
|
|
102
|
+
const factory = this.factory ?? globalFactory();
|
|
103
|
+
if (!factory)
|
|
104
|
+
return Promise.reject(new Error("IndexedDB is not available in this environment"));
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
let request;
|
|
107
|
+
try {
|
|
108
|
+
request = factory.open(this.database, 1);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
reject(error);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
request.onupgradeneeded = () => {
|
|
115
|
+
const db = request.result;
|
|
116
|
+
if (!db.objectStoreNames.contains(this.store))
|
|
117
|
+
db.createObjectStore(this.store, this.storeOptions);
|
|
118
|
+
};
|
|
119
|
+
request.onsuccess = () => {
|
|
120
|
+
const db = request.result;
|
|
121
|
+
if (!db.objectStoreNames.contains(this.store)) {
|
|
122
|
+
db.close();
|
|
123
|
+
reject(new Error(`The IndexedDB database ${this.database} exists, and it has no object store ${this.store}`));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Another tab wants a new version: close this connection, so the upgrade can run
|
|
127
|
+
db.onversionchange = () => {
|
|
128
|
+
db.close();
|
|
129
|
+
this.connection = undefined;
|
|
130
|
+
};
|
|
131
|
+
resolve(db);
|
|
132
|
+
};
|
|
133
|
+
request.onerror = () => reject(errorOf(request.error, `IndexedDB could not open the database ${this.database}`));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=idb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idb.js","sourceRoot":"","sources":["../../src/indexeddb/idb.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8DH,sGAAsG;AACtG,SAAS,aAAa;IACpB,OAAQ,UAA6C,CAAC,SAAS,IAAI,SAAS,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,aAAa,EAAE,KAAK,SAAS,CAAC;AACvC,CAAC;AAED,8DAA8D;AAC9D,SAAS,OAAO,CAAC,KAAc,EAAE,OAAe;IAC9C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAMlB,QAAQ;IAER,KAAK;IACG,YAAY;IACZ,OAAO;IATlB,UAAU,CAAuC;IACjD,MAAM,GAAG,KAAK,CAAC;IAEvB;IACE,gCAAgC;IACvB,QAAgB;IACzB,oCAAoC;IAC3B,KAAa,EACL,YAA2D,EAC3D,OAAmC;wBAJ3C,QAAQ;qBAER,KAAK;4BACG,YAAY;uBACZ,OAAO;IACvB,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAI,IAA8B,EAAE,IAA4C;QACvF,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,WAA+B,CAAC;YACpC,IAAI,IAAa,CAAC;YAClB,IAAI,CAAC;gBACH,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC/C,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,WAAW,CAAC,UAAU,GAAG,GAAG,EAAE;gBAC5B,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC;YACF,WAAW,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,gCAAgC,IAAI,CAAC,QAAQ,SAAS,CAAC,CAAC,CAAC;YACvH,WAAW,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,gCAAgC,IAAI,CAAC,QAAQ,cAAc,CAAC,CAAC,CAAC;QAC9H,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,UAAU;YAAE,OAAO;QACxB,IAAI,CAAC;YACH,CAAC,MAAM,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IAEO,IAAI;QACV,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,QAAQ,YAAY,CAAC,CAAC,CAAC;QACpG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC7B,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE;gBACpB,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU;oBAAE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAClE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAEO,OAAO;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,aAAa,EAAE,CAAC;QAChD,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC;QACjG,OAAO,IAAI,OAAO,CAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtD,IAAI,OAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,OAAO,CAAC,eAAe,GAAG,GAAG,EAAE;gBAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YACrG,CAAC,CAAC;YACF,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE;gBACvB,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9C,EAAE,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,QAAQ,uCAAuC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBAC9G,OAAO;gBACT,CAAC;gBACD,iFAAiF;gBACjF,EAAE,CAAC,eAAe,GAAG,GAAG,EAAE;oBACxB,EAAE,CAAC,KAAK,EAAE,CAAC;oBACX,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;gBAC9B,CAAC,CAAC;gBACF,OAAO,CAAC,EAAE,CAAC,CAAC;YACd,CAAC,CAAC;YACF,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,yCAAyC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACnH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A program store in IndexedDB, for a browser (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* The programs are in the object store `programs` of one database, with the key of each program
|
|
5
|
+
* as the key of its record. IndexedDB keeps a structured clone of each record, so a caller that
|
|
6
|
+
* changes a result does not change the store. The store checks each record that it reads: the
|
|
7
|
+
* database of a browser can hold records of an older version or of another application.
|
|
8
|
+
*/
|
|
9
|
+
import { type ProgramStore, type StoredProgram } from "../program-store/types.js";
|
|
10
|
+
import { type IndexedDbOptions } from "./idb.js";
|
|
11
|
+
/** The default name of the database of the programs. */
|
|
12
|
+
export declare const DEFAULT_PROGRAM_DATABASE = "procedures-programs";
|
|
13
|
+
/**
|
|
14
|
+
* A program store in IndexedDB.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { IndexedDbProgramStore } from "@procedures/store/indexeddb";
|
|
19
|
+
*
|
|
20
|
+
* const store = new IndexedDbProgramStore("my-app-programs");
|
|
21
|
+
* await store.put({ key: "reports.weekly", path: ["reports", "weekly"], program, storedAt: Date.now() });
|
|
22
|
+
* const programs = await store.list("reports");
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class IndexedDbProgramStore implements ProgramStore {
|
|
26
|
+
readonly kind = "indexeddb";
|
|
27
|
+
private readonly connection;
|
|
28
|
+
/**
|
|
29
|
+
* @param name - The name of the database. The store makes it at the first operation.
|
|
30
|
+
* @param options - The IndexedDB factory. The default is the `indexedDB` of the global scope.
|
|
31
|
+
*/
|
|
32
|
+
constructor(name?: string, options?: IndexedDbOptions);
|
|
33
|
+
/** The name of the database. */
|
|
34
|
+
get name(): string;
|
|
35
|
+
get(key: string): Promise<StoredProgram | undefined>;
|
|
36
|
+
list(prefix?: string): Promise<StoredProgram[]>;
|
|
37
|
+
put(program: StoredProgram): Promise<void>;
|
|
38
|
+
delete(key: string): Promise<boolean>;
|
|
39
|
+
/** This method closes the database. The programs stay in it. */
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=program-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-store.d.ts","sourceRoot":"","sources":["../../src/indexeddb/program-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAyC,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACzH,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAErE,wDAAwD;AACxD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAsB,YAAW,YAAY;IACxD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAEhD;;;OAGG;IACH,YAAY,IAAI,GAAE,MAAiC,EAAE,OAAO,GAAE,gBAAqB,EAElF;IAED,gCAAgC;IAChC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAKnD;IAED,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAK9C;IAEK,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/C;IAED,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpC;IAED,gEAAgE;IAChE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;CACF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A program store in IndexedDB, for a browser (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* The programs are in the object store `programs` of one database, with the key of each program
|
|
5
|
+
* as the key of its record. IndexedDB keeps a structured clone of each record, so a caller that
|
|
6
|
+
* changes a result does not change the store. The store checks each record that it reads: the
|
|
7
|
+
* database of a browser can hold records of an older version or of another application.
|
|
8
|
+
*/
|
|
9
|
+
import { byKey, checkStoredProgram, keyMatches } from "../program-store/types.js";
|
|
10
|
+
import { IdbStoreConnection } from "./idb.js";
|
|
11
|
+
/** The default name of the database of the programs. */
|
|
12
|
+
export const DEFAULT_PROGRAM_DATABASE = "procedures-programs";
|
|
13
|
+
/**
|
|
14
|
+
* A program store in IndexedDB.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { IndexedDbProgramStore } from "@procedures/store/indexeddb";
|
|
19
|
+
*
|
|
20
|
+
* const store = new IndexedDbProgramStore("my-app-programs");
|
|
21
|
+
* await store.put({ key: "reports.weekly", path: ["reports", "weekly"], program, storedAt: Date.now() });
|
|
22
|
+
* const programs = await store.list("reports");
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class IndexedDbProgramStore {
|
|
26
|
+
kind = "indexeddb";
|
|
27
|
+
connection;
|
|
28
|
+
/**
|
|
29
|
+
* @param name - The name of the database. The store makes it at the first operation.
|
|
30
|
+
* @param options - The IndexedDB factory. The default is the `indexedDB` of the global scope.
|
|
31
|
+
*/
|
|
32
|
+
constructor(name = DEFAULT_PROGRAM_DATABASE, options = {}) {
|
|
33
|
+
this.connection = new IdbStoreConnection(name, "programs", { keyPath: "key" }, options.indexedDB);
|
|
34
|
+
}
|
|
35
|
+
/** The name of the database. */
|
|
36
|
+
get name() {
|
|
37
|
+
return this.connection.database;
|
|
38
|
+
}
|
|
39
|
+
get(key) {
|
|
40
|
+
return this.connection.run("readonly", (store) => {
|
|
41
|
+
const request = store.get(key);
|
|
42
|
+
return () => (request.result === undefined ? undefined : checkStoredProgram(request.result));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
list(prefix) {
|
|
46
|
+
return this.connection.run("readonly", (store) => {
|
|
47
|
+
const request = store.getAll();
|
|
48
|
+
return () => byKey(request.result.map((record) => checkStoredProgram(record)).filter((program) => keyMatches(program.key, prefix)));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async put(program) {
|
|
52
|
+
const checked = checkStoredProgram(structuredClone(program));
|
|
53
|
+
await this.connection.run("readwrite", (store) => {
|
|
54
|
+
store.put(checked);
|
|
55
|
+
return () => undefined;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
delete(key) {
|
|
59
|
+
return this.connection.run("readwrite", (store) => {
|
|
60
|
+
// The requests of one transaction run in order: the count sees the record before the delete
|
|
61
|
+
const count = store.count(key);
|
|
62
|
+
store.delete(key);
|
|
63
|
+
return () => count.result > 0;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** This method closes the database. The programs stay in it. */
|
|
67
|
+
close() {
|
|
68
|
+
return this.connection.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=program-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-store.js","sourceRoot":"","sources":["../../src/indexeddb/program-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAyC,MAAM,2BAA2B,CAAC;AACzH,OAAO,EAAE,kBAAkB,EAAyB,MAAM,UAAU,CAAC;AAErE,wDAAwD;AACxD,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,WAAW,CAAC;IACX,UAAU,CAAqB;IAEhD;;;OAGG;IACH,YAAY,IAAI,GAAW,wBAAwB,EAAE,OAAO,GAAqB,EAAE;QACjF,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACpG,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAe;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACtI,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAsB;QAC9B,MAAM,OAAO,GAAG,kBAAkB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAChD,4FAA4F;YAC5F,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClB,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gEAAgE;IAChE,KAAK;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A queue store in IndexedDB, for the `HybridStorage` of a browser (roadmap R28, R45).
|
|
3
|
+
*
|
|
4
|
+
* The operations are in the object store `operations` of one database, under keys that IndexedDB
|
|
5
|
+
* makes in increasing order. `load` gives them in the order of the keys: the oldest first. A
|
|
6
|
+
* `replace` clears the store and adds the operations in one transaction, so a reader never sees a
|
|
7
|
+
* part of it. Give each storage its own database.
|
|
8
|
+
*/
|
|
9
|
+
import { type QueuedOperation, type QueueStore } from "../storage/queue.js";
|
|
10
|
+
import { type IndexedDbOptions } from "./idb.js";
|
|
11
|
+
/**
|
|
12
|
+
* A queue store in IndexedDB.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { HybridStorage } from "@procedures/store";
|
|
17
|
+
* import { IndexedDbQueueStore } from "@procedures/store/indexeddb";
|
|
18
|
+
*
|
|
19
|
+
* const users = new HybridStorage(remote, { mode: "write-back", queueStore: new IndexedDbQueueStore("users-queue") });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class IndexedDbQueueStore implements QueueStore {
|
|
23
|
+
private readonly connection;
|
|
24
|
+
/**
|
|
25
|
+
* @param name - The name of the database: one database for each storage. The store makes it at the first operation.
|
|
26
|
+
* @param options - The IndexedDB factory. The default is the `indexedDB` of the global scope.
|
|
27
|
+
*/
|
|
28
|
+
constructor(name: string, options?: IndexedDbOptions);
|
|
29
|
+
/** The name of the database. */
|
|
30
|
+
get name(): string;
|
|
31
|
+
load(): Promise<QueuedOperation[]>;
|
|
32
|
+
append(operation: QueuedOperation): Promise<void>;
|
|
33
|
+
replace(operations: QueuedOperation[]): Promise<void>;
|
|
34
|
+
clear(): Promise<void>;
|
|
35
|
+
/** This method closes the database. The operations stay in it. */
|
|
36
|
+
close(): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=queue-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-store.d.ts","sourceRoot":"","sources":["../../src/indexeddb/queue-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAqB,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAErE;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,YAAW,UAAU;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAEhD;;;OAGG;IACH,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,EAGvD;IAED,gCAAgC;IAChC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAWjC;IAEK,MAAM,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtD;IAEK,OAAO,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1D;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3B;IAED,kEAAkE;IAClE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;CACF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A queue store in IndexedDB, for the `HybridStorage` of a browser (roadmap R28, R45).
|
|
3
|
+
*
|
|
4
|
+
* The operations are in the object store `operations` of one database, under keys that IndexedDB
|
|
5
|
+
* makes in increasing order. `load` gives them in the order of the keys: the oldest first. A
|
|
6
|
+
* `replace` clears the store and adds the operations in one transaction, so a reader never sees a
|
|
7
|
+
* part of it. Give each storage its own database.
|
|
8
|
+
*/
|
|
9
|
+
import { isQueuedOperation } from "../storage/queue.js";
|
|
10
|
+
import { IdbStoreConnection } from "./idb.js";
|
|
11
|
+
/**
|
|
12
|
+
* A queue store in IndexedDB.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { HybridStorage } from "@procedures/store";
|
|
17
|
+
* import { IndexedDbQueueStore } from "@procedures/store/indexeddb";
|
|
18
|
+
*
|
|
19
|
+
* const users = new HybridStorage(remote, { mode: "write-back", queueStore: new IndexedDbQueueStore("users-queue") });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class IndexedDbQueueStore {
|
|
23
|
+
connection;
|
|
24
|
+
/**
|
|
25
|
+
* @param name - The name of the database: one database for each storage. The store makes it at the first operation.
|
|
26
|
+
* @param options - The IndexedDB factory. The default is the `indexedDB` of the global scope.
|
|
27
|
+
*/
|
|
28
|
+
constructor(name, options = {}) {
|
|
29
|
+
if (typeof name !== "string" || name === "")
|
|
30
|
+
throw new TypeError("IndexedDbQueueStore needs the name of a database");
|
|
31
|
+
this.connection = new IdbStoreConnection(name, "operations", { autoIncrement: true }, options.indexedDB);
|
|
32
|
+
}
|
|
33
|
+
/** The name of the database. */
|
|
34
|
+
get name() {
|
|
35
|
+
return this.connection.database;
|
|
36
|
+
}
|
|
37
|
+
load() {
|
|
38
|
+
return this.connection.run("readonly", (store) => {
|
|
39
|
+
const request = store.getAll();
|
|
40
|
+
return () => request.result.map((value, index) => {
|
|
41
|
+
if (!isQueuedOperation(value)) {
|
|
42
|
+
throw new Error(`The queue database ${this.name} has a record that is not a queued operation (record ${index + 1})`);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async append(operation) {
|
|
49
|
+
await this.connection.run("readwrite", (store) => {
|
|
50
|
+
store.add(operation);
|
|
51
|
+
return () => undefined;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async replace(operations) {
|
|
55
|
+
await this.connection.run("readwrite", (store) => {
|
|
56
|
+
store.clear();
|
|
57
|
+
for (const operation of operations)
|
|
58
|
+
store.add(operation);
|
|
59
|
+
return () => undefined;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async clear() {
|
|
63
|
+
await this.connection.run("readwrite", (store) => {
|
|
64
|
+
store.clear();
|
|
65
|
+
return () => undefined;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** This method closes the database. The operations stay in it. */
|
|
69
|
+
close() {
|
|
70
|
+
return this.connection.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=queue-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-store.js","sourceRoot":"","sources":["../../src/indexeddb/queue-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,iBAAiB,EAAyC,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAyB,MAAM,UAAU,CAAC;AAErE;;;;;;;;;;GAUG;AACH,MAAM,OAAO,mBAAmB;IACb,UAAU,CAAqB;IAEhD;;;OAGG;IACH,YAAY,IAAY,EAAE,OAAO,GAAqB,EAAE;QACtD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;QACrH,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3G,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;IAClC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,GAAG,EAAE,CACV,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBAClC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9B,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,IAAI,wDAAwD,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;gBACvH,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAA0B;QACrC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAA6B;QACzC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,MAAM,SAAS,IAAI,UAAU;gBAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACzD,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kEAAkE;IAClE,KAAK;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry `@procedures/store/indexeddb`: the stores of a browser (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* - `IndexedDbProgramStore` keeps programs in IndexedDB.
|
|
5
|
+
* - `IndexedDbQueueStore` keeps the queue of a `HybridStorage` in IndexedDB.
|
|
6
|
+
* - `MemoryProgramStore` and `MemoryQueueStore` are the fallbacks for a browser without
|
|
7
|
+
* IndexedDB. `hasIndexedDb()` tells which one to use.
|
|
8
|
+
*
|
|
9
|
+
* The package root does not import this entry, and this entry does not import the client or zod:
|
|
10
|
+
* a page that loads it gets only these stores.
|
|
11
|
+
*/
|
|
12
|
+
export { IndexedDbProgramStore, DEFAULT_PROGRAM_DATABASE } from "./indexeddb/program-store.js";
|
|
13
|
+
export { IndexedDbQueueStore } from "./indexeddb/queue-store.js";
|
|
14
|
+
export { hasIndexedDb, type IdbFactoryLike, type IndexedDbOptions } from "./indexeddb/idb.js";
|
|
15
|
+
export { MemoryProgramStore } from "./program-store/memory.js";
|
|
16
|
+
export { MemoryQueueStore } from "./storage/queue.js";
|
|
17
|
+
export type { ProgramStore, StoredProgram } from "./program-store/types.js";
|
|
18
|
+
export type { QueuedOperation, QueueStore } from "./storage/queue.js";
|
|
19
|
+
//# sourceMappingURL=indexeddb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../src/indexeddb.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry `@procedures/store/indexeddb`: the stores of a browser (roadmap R45).
|
|
3
|
+
*
|
|
4
|
+
* - `IndexedDbProgramStore` keeps programs in IndexedDB.
|
|
5
|
+
* - `IndexedDbQueueStore` keeps the queue of a `HybridStorage` in IndexedDB.
|
|
6
|
+
* - `MemoryProgramStore` and `MemoryQueueStore` are the fallbacks for a browser without
|
|
7
|
+
* IndexedDB. `hasIndexedDb()` tells which one to use.
|
|
8
|
+
*
|
|
9
|
+
* The package root does not import this entry, and this entry does not import the client or zod:
|
|
10
|
+
* a page that loads it gets only these stores.
|
|
11
|
+
*/
|
|
12
|
+
export { IndexedDbProgramStore, DEFAULT_PROGRAM_DATABASE } from "./indexeddb/program-store.js";
|
|
13
|
+
export { IndexedDbQueueStore } from "./indexeddb/queue-store.js";
|
|
14
|
+
export { hasIndexedDb } from "./indexeddb/idb.js";
|
|
15
|
+
export { MemoryProgramStore } from "./program-store/memory.js";
|
|
16
|
+
export { MemoryQueueStore } from "./storage/queue.js";
|
|
17
|
+
//# sourceMappingURL=indexeddb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.js","sourceRoot":"","sources":["../src/indexeddb.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAA8C,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* A file that is not valid JSON is an error: the store does not write over it.
|
|
9
9
|
*/
|
|
10
10
|
import { type ProgramStore, type StoredProgram } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* This function runs a file operation again while Windows holds the file for a moment. `FileQueueStore` uses it
|
|
13
|
+
* too.
|
|
14
|
+
*/
|
|
15
|
+
export declare function retryOnContention<T>(operation: () => Promise<T>): Promise<T>;
|
|
11
16
|
export declare class FileProgramStore implements ProgramStore {
|
|
12
17
|
readonly path: string;
|
|
13
18
|
readonly kind = "file";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/program-store/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAyC,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/program-store/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAyC,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAwB1G;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUlF;AAED,qBAAa,gBAAiB,YAAW,YAAY;IAMvC,QAAQ,CAAC,IAAI,EAAE,MAAM;IALjC,QAAQ,CAAC,IAAI,UAAU;IACvB,sFAAsF;IACtF,OAAO,CAAC,KAAK,CAAuC;IAEpD,2FAA2F;IAC3F,YAAqB,IAAI,EAAE,MAAM,EAAI;IAE/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAEzD;IAEK,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAEpD;IAEK,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/C;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ1C;IAED,iEAAiE;YACnD,IAAI;IAwBlB,iGAAiG;IACjG,OAAO,CAAC,MAAM;YASA,KAAK;YAYL,QAAQ;CA0BvB"}
|
|
@@ -25,8 +25,11 @@ function isContention(error) {
|
|
|
25
25
|
return process.platform === "win32" && (code === "EPERM" || code === "EACCES" || code === "EBUSY");
|
|
26
26
|
}
|
|
27
27
|
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* This function runs a file operation again while Windows holds the file for a moment. `FileQueueStore` uses it
|
|
30
|
+
* too.
|
|
31
|
+
*/
|
|
32
|
+
export async function retryOnContention(operation) {
|
|
30
33
|
for (let attempt = 1;; attempt++) {
|
|
31
34
|
try {
|
|
32
35
|
return await operation();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/program-store/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAyC,MAAM,YAAY,CAAC;AAO1G,+EAA+E;AAC/E,MAAM,aAAa,GAAG,MAAM,CAAC;AAC7B,qCAAqC;AACrC,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;IACnD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC;AACrG,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEhF
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/program-store/file.ts"],"names":[],"mappings":"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"}
|