cojson-storage-indexeddb 0.10.6 → 0.10.8
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/CoJsonIDBTransaction.js +84 -0
- package/dist/CoJsonIDBTransaction.js.map +1 -0
- package/dist/idbClient.js +48 -58
- package/dist/idbClient.js.map +1 -1
- package/dist/idbNode.js +1 -3
- package/dist/idbNode.js.map +1 -1
- package/dist/tests/CoJsonIDBTransaction.test.js +125 -0
- package/dist/tests/CoJsonIDBTransaction.test.js.map +1 -0
- package/package.json +3 -3
- package/src/CoJsonIDBTransaction.ts +111 -0
- package/src/idbClient.ts +86 -124
- package/src/idbNode.ts +1 -12
- package/src/tests/CoJsonIDBTransaction.test.ts +170 -0
- package/dist/syncPromises.js +0 -163
- package/dist/syncPromises.js.map +0 -1
- package/src/syncPromises.ts +0 -224
package/src/idbClient.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CojsonInternalTypes, RawCoID } from "cojson";
|
|
1
|
+
import type { CojsonInternalTypes, RawCoID, SessionID } from "cojson";
|
|
2
2
|
import type {
|
|
3
3
|
CoValueRow,
|
|
4
4
|
DBClientInterface,
|
|
@@ -8,119 +8,60 @@ import type {
|
|
|
8
8
|
StoredSessionRow,
|
|
9
9
|
TransactionRow,
|
|
10
10
|
} from "cojson-storage";
|
|
11
|
-
import {
|
|
11
|
+
import { CoJsonIDBTransaction } from "./CoJsonIDBTransaction.js";
|
|
12
12
|
|
|
13
13
|
export class IDBClient implements DBClientInterface {
|
|
14
14
|
private db;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
id: number;
|
|
19
|
-
tx: IDBTransaction;
|
|
20
|
-
stores: {
|
|
21
|
-
coValues: IDBObjectStore;
|
|
22
|
-
sessions: IDBObjectStore;
|
|
23
|
-
transactions: IDBObjectStore;
|
|
24
|
-
signatureAfter: IDBObjectStore;
|
|
25
|
-
};
|
|
26
|
-
startedAt: number;
|
|
27
|
-
pendingRequests: ((txEntry: {
|
|
28
|
-
stores: {
|
|
29
|
-
coValues: IDBObjectStore;
|
|
30
|
-
sessions: IDBObjectStore;
|
|
31
|
-
transactions: IDBObjectStore;
|
|
32
|
-
signatureAfter: IDBObjectStore;
|
|
33
|
-
};
|
|
34
|
-
}) => void)[];
|
|
35
|
-
}
|
|
36
|
-
| undefined;
|
|
37
|
-
|
|
38
|
-
currentTxID = 0;
|
|
16
|
+
activeTransaction: CoJsonIDBTransaction | undefined;
|
|
17
|
+
autoBatchingTransaction: CoJsonIDBTransaction | undefined;
|
|
39
18
|
|
|
40
19
|
constructor(db: IDBDatabase) {
|
|
41
20
|
this.db = db;
|
|
42
21
|
}
|
|
43
22
|
|
|
44
23
|
makeRequest<T>(
|
|
45
|
-
handler: (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
sessions: IDBObjectStore;
|
|
61
|
-
transactions: IDBObjectStore;
|
|
62
|
-
signatureAfter: IDBObjectStore;
|
|
63
|
-
};
|
|
64
|
-
}) => {
|
|
65
|
-
const request = handler(stores);
|
|
66
|
-
request.onerror = () => {
|
|
67
|
-
console.error("Error in request", request.error);
|
|
68
|
-
this.currentTx = undefined;
|
|
69
|
-
reject(request.error);
|
|
70
|
-
};
|
|
71
|
-
request.onsuccess = () => {
|
|
72
|
-
const value = request.result as T;
|
|
73
|
-
resolve(value);
|
|
74
|
-
|
|
75
|
-
const next = txEntry?.pendingRequests.shift();
|
|
76
|
-
|
|
77
|
-
if (next) {
|
|
78
|
-
next({ stores });
|
|
79
|
-
} else {
|
|
80
|
-
if (this.currentTx === txEntry) {
|
|
81
|
-
this.currentTx = undefined;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Transaction batching
|
|
88
|
-
if (!txEntry || performance.now() - txEntry.startedAt > 20) {
|
|
89
|
-
const tx = this.db.transaction(
|
|
90
|
-
["coValues", "sessions", "transactions", "signatureAfter"],
|
|
91
|
-
"readwrite",
|
|
92
|
-
);
|
|
93
|
-
txEntry = {
|
|
94
|
-
id: this.currentTxID++,
|
|
95
|
-
tx,
|
|
96
|
-
stores: {
|
|
97
|
-
coValues: tx.objectStore("coValues"),
|
|
98
|
-
sessions: tx.objectStore("sessions"),
|
|
99
|
-
transactions: tx.objectStore("transactions"),
|
|
100
|
-
signatureAfter: tx.objectStore("signatureAfter"),
|
|
101
|
-
},
|
|
102
|
-
startedAt: performance.now(),
|
|
103
|
-
pendingRequests: [],
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
this.currentTx = txEntry;
|
|
107
|
-
|
|
108
|
-
requestEntry(txEntry);
|
|
109
|
-
} else {
|
|
110
|
-
txEntry.pendingRequests.push(requestEntry);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
24
|
+
handler: (txEntry: CoJsonIDBTransaction) => IDBRequest<T>,
|
|
25
|
+
): Promise<T> {
|
|
26
|
+
if (this.activeTransaction) {
|
|
27
|
+
return this.activeTransaction.handleRequest<T>(handler);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (this.autoBatchingTransaction?.isReusable()) {
|
|
31
|
+
return this.autoBatchingTransaction.handleRequest<T>(handler);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const tx = new CoJsonIDBTransaction(this.db);
|
|
35
|
+
|
|
36
|
+
this.autoBatchingTransaction = tx;
|
|
37
|
+
|
|
38
|
+
return tx.handleRequest<T>(handler);
|
|
113
39
|
}
|
|
114
40
|
|
|
115
41
|
async getCoValue(coValueId: RawCoID): Promise<StoredCoValueRow | undefined> {
|
|
116
|
-
return this.makeRequest<StoredCoValueRow | undefined>((
|
|
117
|
-
coValues.index("coValuesById").get(coValueId),
|
|
42
|
+
return this.makeRequest<StoredCoValueRow | undefined>((tx) =>
|
|
43
|
+
tx.getObjectStore("coValues").index("coValuesById").get(coValueId),
|
|
118
44
|
);
|
|
119
45
|
}
|
|
120
46
|
|
|
121
47
|
async getCoValueSessions(coValueRowId: number): Promise<StoredSessionRow[]> {
|
|
122
|
-
return this.makeRequest<StoredSessionRow[]>((
|
|
123
|
-
|
|
48
|
+
return this.makeRequest<StoredSessionRow[]>((tx) =>
|
|
49
|
+
tx
|
|
50
|
+
.getObjectStore("sessions")
|
|
51
|
+
.index("sessionsByCoValue")
|
|
52
|
+
.getAll(coValueRowId),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async getSingleCoValueSession(
|
|
57
|
+
coValueRowId: number,
|
|
58
|
+
sessionID: SessionID,
|
|
59
|
+
): Promise<StoredSessionRow | undefined> {
|
|
60
|
+
return this.makeRequest<StoredSessionRow>((tx) =>
|
|
61
|
+
tx
|
|
62
|
+
.getObjectStore("sessions")
|
|
63
|
+
.index("uniqueSessions")
|
|
64
|
+
.get([coValueRowId, sessionID]),
|
|
124
65
|
);
|
|
125
66
|
}
|
|
126
67
|
|
|
@@ -128,13 +69,15 @@ export class IDBClient implements DBClientInterface {
|
|
|
128
69
|
sessionRowId: number,
|
|
129
70
|
firstNewTxIdx: number,
|
|
130
71
|
): Promise<TransactionRow[]> {
|
|
131
|
-
return this.makeRequest<TransactionRow[]>((
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
72
|
+
return this.makeRequest<TransactionRow[]>((tx) =>
|
|
73
|
+
tx
|
|
74
|
+
.getObjectStore("transactions")
|
|
75
|
+
.getAll(
|
|
76
|
+
IDBKeyRange.bound(
|
|
77
|
+
[sessionRowId, firstNewTxIdx],
|
|
78
|
+
[sessionRowId, Number.POSITIVE_INFINITY],
|
|
79
|
+
),
|
|
136
80
|
),
|
|
137
|
-
),
|
|
138
81
|
);
|
|
139
82
|
}
|
|
140
83
|
|
|
@@ -142,9 +85,10 @@ export class IDBClient implements DBClientInterface {
|
|
|
142
85
|
sessionRowId: number,
|
|
143
86
|
firstNewTxIdx: number,
|
|
144
87
|
): Promise<SignatureAfterRow[]> {
|
|
145
|
-
return this.makeRequest<SignatureAfterRow[]>(
|
|
146
|
-
|
|
147
|
-
|
|
88
|
+
return this.makeRequest<SignatureAfterRow[]>((tx) =>
|
|
89
|
+
tx
|
|
90
|
+
.getObjectStore("signatureAfter")
|
|
91
|
+
.getAll(
|
|
148
92
|
IDBKeyRange.bound(
|
|
149
93
|
[sessionRowId, firstNewTxIdx],
|
|
150
94
|
[sessionRowId, Number.POSITIVE_INFINITY],
|
|
@@ -160,8 +104,8 @@ export class IDBClient implements DBClientInterface {
|
|
|
160
104
|
throw new Error(`Header is required, coId: ${msg.id}`);
|
|
161
105
|
}
|
|
162
106
|
|
|
163
|
-
return (await this.makeRequest<IDBValidKey>((
|
|
164
|
-
coValues.put({
|
|
107
|
+
return (await this.makeRequest<IDBValidKey>((tx) =>
|
|
108
|
+
tx.getObjectStore("coValues").put({
|
|
165
109
|
id: msg.id,
|
|
166
110
|
// biome-ignore lint/style/noNonNullAssertion: TODO(JAZZ-561): Review
|
|
167
111
|
header: msg.header!,
|
|
@@ -176,25 +120,26 @@ export class IDBClient implements DBClientInterface {
|
|
|
176
120
|
sessionUpdate: SessionRow;
|
|
177
121
|
sessionRow?: StoredSessionRow;
|
|
178
122
|
}): Promise<number> {
|
|
179
|
-
return this.makeRequest<number>(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
123
|
+
return this.makeRequest<number>(
|
|
124
|
+
(tx) =>
|
|
125
|
+
tx.getObjectStore("sessions").put(
|
|
126
|
+
sessionRow?.rowID
|
|
127
|
+
? {
|
|
128
|
+
rowID: sessionRow.rowID,
|
|
129
|
+
...sessionUpdate,
|
|
130
|
+
}
|
|
131
|
+
: sessionUpdate,
|
|
132
|
+
) as IDBRequest<number>,
|
|
188
133
|
);
|
|
189
134
|
}
|
|
190
135
|
|
|
191
|
-
addTransaction(
|
|
136
|
+
async addTransaction(
|
|
192
137
|
sessionRowID: number,
|
|
193
138
|
idx: number,
|
|
194
139
|
newTransaction: CojsonInternalTypes.Transaction,
|
|
195
140
|
) {
|
|
196
|
-
|
|
197
|
-
transactions.add({
|
|
141
|
+
await this.makeRequest((tx) =>
|
|
142
|
+
tx.getObjectStore("transactions").add({
|
|
198
143
|
ses: sessionRowID,
|
|
199
144
|
idx,
|
|
200
145
|
tx: newTransaction,
|
|
@@ -211,8 +156,8 @@ export class IDBClient implements DBClientInterface {
|
|
|
211
156
|
idx: number;
|
|
212
157
|
signature: CojsonInternalTypes.Signature;
|
|
213
158
|
}) {
|
|
214
|
-
return this.makeRequest((
|
|
215
|
-
signatureAfter.put({
|
|
159
|
+
return this.makeRequest((tx) =>
|
|
160
|
+
tx.getObjectStore("signatureAfter").put({
|
|
216
161
|
ses: sessionRowID,
|
|
217
162
|
idx,
|
|
218
163
|
signature,
|
|
@@ -220,7 +165,24 @@ export class IDBClient implements DBClientInterface {
|
|
|
220
165
|
);
|
|
221
166
|
}
|
|
222
167
|
|
|
223
|
-
|
|
224
|
-
|
|
168
|
+
closeTransaction(tx: CoJsonIDBTransaction) {
|
|
169
|
+
tx.commit();
|
|
170
|
+
|
|
171
|
+
if (tx === this.activeTransaction) {
|
|
172
|
+
this.activeTransaction = undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async transaction(operationsCallback: () => unknown) {
|
|
177
|
+
const tx = new CoJsonIDBTransaction(this.db);
|
|
178
|
+
|
|
179
|
+
this.activeTransaction = tx;
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
await operationsCallback();
|
|
183
|
+
tx.commit(); // Tells the browser to not wait for another possible request and commit the transaction immediately
|
|
184
|
+
} finally {
|
|
185
|
+
this.activeTransaction = undefined;
|
|
186
|
+
}
|
|
225
187
|
}
|
|
226
188
|
}
|
package/src/idbNode.ts
CHANGED
|
@@ -33,18 +33,7 @@ export class IDBNode {
|
|
|
33
33
|
}
|
|
34
34
|
await this.syncManager.handleSyncMessage(msg);
|
|
35
35
|
} catch (e) {
|
|
36
|
-
console.error(
|
|
37
|
-
new Error(
|
|
38
|
-
`Error reading from localNode, handling msg\n\n${JSON.stringify(
|
|
39
|
-
msg,
|
|
40
|
-
(k, v) =>
|
|
41
|
-
k === "changes" || k === "encryptedChanges"
|
|
42
|
-
? `${v.slice(0, 20)}...`
|
|
43
|
-
: v,
|
|
44
|
-
)}`,
|
|
45
|
-
{ cause: e },
|
|
46
|
-
),
|
|
47
|
-
);
|
|
36
|
+
console.error(e);
|
|
48
37
|
}
|
|
49
38
|
}
|
|
50
39
|
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { CoJsonIDBTransaction } from "../CoJsonIDBTransaction";
|
|
3
|
+
|
|
4
|
+
const TEST_DB_NAME = "test-cojson-idb-transaction";
|
|
5
|
+
|
|
6
|
+
describe("CoJsonIDBTransaction", () => {
|
|
7
|
+
let db: IDBDatabase;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
// Create test database
|
|
11
|
+
await new Promise<void>((resolve, reject) => {
|
|
12
|
+
const request = indexedDB.open(TEST_DB_NAME, 1);
|
|
13
|
+
|
|
14
|
+
request.onerror = () => reject(request.error);
|
|
15
|
+
|
|
16
|
+
request.onupgradeneeded = (event) => {
|
|
17
|
+
const db = request.result;
|
|
18
|
+
// Create test stores
|
|
19
|
+
db.createObjectStore("coValues", { keyPath: "id" });
|
|
20
|
+
const sessions = db.createObjectStore("sessions", { keyPath: "id" });
|
|
21
|
+
sessions.createIndex("uniqueSessions", ["coValue", "sessionID"], {
|
|
22
|
+
unique: true,
|
|
23
|
+
});
|
|
24
|
+
db.createObjectStore("transactions", { keyPath: "id" });
|
|
25
|
+
db.createObjectStore("signatureAfter", { keyPath: "id" });
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
request.onsuccess = () => {
|
|
29
|
+
db = request.result;
|
|
30
|
+
resolve();
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(async () => {
|
|
36
|
+
// Close and delete test database
|
|
37
|
+
db.close();
|
|
38
|
+
await new Promise<void>((resolve, reject) => {
|
|
39
|
+
const request = indexedDB.deleteDatabase(TEST_DB_NAME);
|
|
40
|
+
request.onerror = () => reject(request.error);
|
|
41
|
+
request.onsuccess = () => resolve();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("handles successful write and read operations", async () => {
|
|
46
|
+
const tx = new CoJsonIDBTransaction(db);
|
|
47
|
+
|
|
48
|
+
// Write test
|
|
49
|
+
await tx.handleRequest((tx) =>
|
|
50
|
+
tx.getObjectStore("coValues").put({
|
|
51
|
+
id: "test1",
|
|
52
|
+
value: "hello",
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Read test
|
|
57
|
+
const readTx = new CoJsonIDBTransaction(db);
|
|
58
|
+
const result = await readTx.handleRequest((tx) =>
|
|
59
|
+
tx.getObjectStore("coValues").get("test1"),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(result).toEqual({
|
|
63
|
+
id: "test1",
|
|
64
|
+
value: "hello",
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("handles multiple operations in single transaction", async () => {
|
|
69
|
+
const tx = new CoJsonIDBTransaction(db);
|
|
70
|
+
|
|
71
|
+
// Multiple writes
|
|
72
|
+
await Promise.all([
|
|
73
|
+
tx.handleRequest((tx) =>
|
|
74
|
+
tx.getObjectStore("coValues").put({
|
|
75
|
+
id: "test1",
|
|
76
|
+
value: "hello",
|
|
77
|
+
}),
|
|
78
|
+
),
|
|
79
|
+
tx.handleRequest((tx) =>
|
|
80
|
+
tx.getObjectStore("coValues").put({
|
|
81
|
+
id: "test2",
|
|
82
|
+
value: "world",
|
|
83
|
+
}),
|
|
84
|
+
),
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
// Read results
|
|
88
|
+
const readTx = new CoJsonIDBTransaction(db);
|
|
89
|
+
const [result1, result2] = await Promise.all([
|
|
90
|
+
readTx.handleRequest((tx) => tx.getObjectStore("coValues").get("test1")),
|
|
91
|
+
readTx.handleRequest((tx) => tx.getObjectStore("coValues").get("test2")),
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
expect(result1).toEqual({
|
|
95
|
+
id: "test1",
|
|
96
|
+
value: "hello",
|
|
97
|
+
});
|
|
98
|
+
expect(result2).toEqual({
|
|
99
|
+
id: "test2",
|
|
100
|
+
value: "world",
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("handles transaction across multiple stores", async () => {
|
|
105
|
+
const tx = new CoJsonIDBTransaction(db);
|
|
106
|
+
|
|
107
|
+
await Promise.all([
|
|
108
|
+
tx.handleRequest((tx) =>
|
|
109
|
+
tx.getObjectStore("coValues").put({
|
|
110
|
+
id: "value1",
|
|
111
|
+
data: "value data",
|
|
112
|
+
}),
|
|
113
|
+
),
|
|
114
|
+
tx.handleRequest((tx) =>
|
|
115
|
+
tx.getObjectStore("sessions").put({
|
|
116
|
+
id: "session1",
|
|
117
|
+
data: "session data",
|
|
118
|
+
}),
|
|
119
|
+
),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
const readTx = new CoJsonIDBTransaction(db);
|
|
123
|
+
const [valueResult, sessionResult] = await Promise.all([
|
|
124
|
+
readTx.handleRequest((tx) => tx.getObjectStore("coValues").get("value1")),
|
|
125
|
+
readTx.handleRequest((tx) =>
|
|
126
|
+
tx.getObjectStore("sessions").get("session1"),
|
|
127
|
+
),
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
expect(valueResult).toEqual({
|
|
131
|
+
id: "value1",
|
|
132
|
+
data: "value data",
|
|
133
|
+
});
|
|
134
|
+
expect(sessionResult).toEqual({
|
|
135
|
+
id: "session1",
|
|
136
|
+
data: "session data",
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("handles failed transactions", async () => {
|
|
141
|
+
const tx = new CoJsonIDBTransaction(db);
|
|
142
|
+
|
|
143
|
+
await expect(
|
|
144
|
+
tx.handleRequest((tx) =>
|
|
145
|
+
tx.getObjectStore("sessions").put({
|
|
146
|
+
id: 1,
|
|
147
|
+
coValue: "value1",
|
|
148
|
+
sessionID: "session1",
|
|
149
|
+
data: "session data",
|
|
150
|
+
}),
|
|
151
|
+
),
|
|
152
|
+
).resolves.toBe(1);
|
|
153
|
+
|
|
154
|
+
expect(tx.failed).toBe(false);
|
|
155
|
+
|
|
156
|
+
const badTx = new CoJsonIDBTransaction(db);
|
|
157
|
+
await expect(
|
|
158
|
+
badTx.handleRequest((tx) =>
|
|
159
|
+
tx.getObjectStore("sessions").put({
|
|
160
|
+
id: 2,
|
|
161
|
+
coValue: "value1",
|
|
162
|
+
sessionID: "session1",
|
|
163
|
+
data: "session data",
|
|
164
|
+
}),
|
|
165
|
+
),
|
|
166
|
+
).rejects.toThrow();
|
|
167
|
+
|
|
168
|
+
expect(badTx.failed).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
});
|
package/dist/syncPromises.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
const isFunction = (func) => typeof func === "function";
|
|
2
|
-
const isObject = (supposedObject) => typeof supposedObject === "object" &&
|
|
3
|
-
supposedObject !== null &&
|
|
4
|
-
!Array.isArray(supposedObject);
|
|
5
|
-
const isThenable = (obj) => isObject(obj) && isFunction(obj.then);
|
|
6
|
-
const identity = (co) => co;
|
|
7
|
-
export { identity, isFunction, isObject, isThenable };
|
|
8
|
-
var States;
|
|
9
|
-
(function (States) {
|
|
10
|
-
States["PENDING"] = "PENDING";
|
|
11
|
-
States["RESOLVED"] = "RESOLVED";
|
|
12
|
-
States["REJECTED"] = "REJECTED";
|
|
13
|
-
})(States || (States = {}));
|
|
14
|
-
export class SyncPromise {
|
|
15
|
-
constructor(callback) {
|
|
16
|
-
this.state = States.PENDING;
|
|
17
|
-
this.handlers = [];
|
|
18
|
-
this.resolve = (value) => {
|
|
19
|
-
return this.setResult(value, States.RESOLVED);
|
|
20
|
-
};
|
|
21
|
-
this.reject = (reason) => {
|
|
22
|
-
return this.setResult(reason, States.REJECTED);
|
|
23
|
-
};
|
|
24
|
-
this.setResult = (value, state) => {
|
|
25
|
-
const set = () => {
|
|
26
|
-
if (this.state !== States.PENDING) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
if (isThenable(value)) {
|
|
30
|
-
return value.then(this.resolve, this.reject);
|
|
31
|
-
}
|
|
32
|
-
this.value = value;
|
|
33
|
-
this.state = state;
|
|
34
|
-
return this.executeHandlers();
|
|
35
|
-
};
|
|
36
|
-
void set();
|
|
37
|
-
};
|
|
38
|
-
this.executeHandlers = () => {
|
|
39
|
-
if (this.state === States.PENDING) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
for (const handler of this.handlers) {
|
|
43
|
-
if (this.state === States.REJECTED) {
|
|
44
|
-
handler.onFail(this.value);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
handler.onSuccess(this.value);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
this.handlers = [];
|
|
51
|
-
};
|
|
52
|
-
this.attachHandler = (handler) => {
|
|
53
|
-
this.handlers = [...this.handlers, handler];
|
|
54
|
-
this.executeHandlers();
|
|
55
|
-
};
|
|
56
|
-
try {
|
|
57
|
-
callback(this.resolve, this.reject);
|
|
58
|
-
}
|
|
59
|
-
catch (e) {
|
|
60
|
-
this.reject(e);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// biome-ignore lint/suspicious/noThenProperty: TODO(JAZZ-561): Review
|
|
64
|
-
then(onSuccess, onFail) {
|
|
65
|
-
return new SyncPromise((resolve, reject) => {
|
|
66
|
-
return this.attachHandler({
|
|
67
|
-
onSuccess: (result) => {
|
|
68
|
-
try {
|
|
69
|
-
return resolve(onSuccess(result));
|
|
70
|
-
}
|
|
71
|
-
catch (e) {
|
|
72
|
-
return reject(e);
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
onFail: (reason) => {
|
|
76
|
-
if (!onFail) {
|
|
77
|
-
return reject(reason);
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
return resolve(onFail(reason));
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
return reject(e);
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
catch(onFail) {
|
|
90
|
-
return this.then(identity, onFail);
|
|
91
|
-
}
|
|
92
|
-
// methods
|
|
93
|
-
toString() {
|
|
94
|
-
return "[object SyncPromise]";
|
|
95
|
-
}
|
|
96
|
-
finally(cb) {
|
|
97
|
-
return new SyncPromise((resolve, reject) => {
|
|
98
|
-
let co;
|
|
99
|
-
let isRejected;
|
|
100
|
-
return this.then((value) => {
|
|
101
|
-
isRejected = false;
|
|
102
|
-
co = value;
|
|
103
|
-
return cb();
|
|
104
|
-
}, (reason) => {
|
|
105
|
-
isRejected = true;
|
|
106
|
-
co = reason;
|
|
107
|
-
return cb();
|
|
108
|
-
}).then(() => {
|
|
109
|
-
if (isRejected) {
|
|
110
|
-
return reject(co);
|
|
111
|
-
}
|
|
112
|
-
return resolve(co);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
spread(handler) {
|
|
117
|
-
return this.then((collection) => {
|
|
118
|
-
if (Array.isArray(collection)) {
|
|
119
|
-
return handler(...collection);
|
|
120
|
-
}
|
|
121
|
-
return handler(collection);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
// static
|
|
125
|
-
static resolve(value) {
|
|
126
|
-
return new SyncPromise((resolve) => {
|
|
127
|
-
return resolve(value);
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
static reject(reason) {
|
|
131
|
-
return new SyncPromise((_resolve, reject) => {
|
|
132
|
-
return reject(reason);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
static all(collection) {
|
|
136
|
-
return new SyncPromise((resolve, reject) => {
|
|
137
|
-
if (!Array.isArray(collection)) {
|
|
138
|
-
return reject(new TypeError("An array must be provided."));
|
|
139
|
-
}
|
|
140
|
-
if (collection.length === 0) {
|
|
141
|
-
return resolve([]);
|
|
142
|
-
}
|
|
143
|
-
let counter = collection.length;
|
|
144
|
-
const resolvedCollection = [];
|
|
145
|
-
const tryResolve = (value, index) => {
|
|
146
|
-
counter -= 1;
|
|
147
|
-
resolvedCollection[index] = value;
|
|
148
|
-
if (counter !== 0) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
return resolve(resolvedCollection);
|
|
152
|
-
};
|
|
153
|
-
return collection.forEach((item, index) => {
|
|
154
|
-
return SyncPromise.resolve(item)
|
|
155
|
-
.then((value) => {
|
|
156
|
-
return tryResolve(value, index);
|
|
157
|
-
})
|
|
158
|
-
.catch(reject);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
//# sourceMappingURL=syncPromises.js.map
|
package/dist/syncPromises.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syncPromises.js","sourceRoot":"","sources":["../src/syncPromises.ts"],"names":[],"mappings":"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"}
|