@arcote.tech/arc-react 0.0.21 → 0.0.22
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/dist/form.d.ts +1 -0
- package/dist/idb.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +104 -80
- package/dist/reactModel.d.ts +5 -4
- package/package.json +6 -5
package/dist/form.d.ts
CHANGED
package/dist/idb.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -8,6 +8,10 @@ function formResolver(schema) {
|
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
// idb.ts
|
|
11
|
+
import {
|
|
12
|
+
ArcCollection,
|
|
13
|
+
ArcIndexedCollection
|
|
14
|
+
} from "@arcote.tech/arc";
|
|
11
15
|
var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, reject) => {
|
|
12
16
|
const dbRequest = indexedDB.open(name, version);
|
|
13
17
|
dbRequest.addEventListener("error", (err) => {
|
|
@@ -18,7 +22,7 @@ var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, re
|
|
|
18
22
|
});
|
|
19
23
|
dbRequest.addEventListener("upgradeneeded", (ev) => {
|
|
20
24
|
const db = ev.target.result;
|
|
21
|
-
context.
|
|
25
|
+
context.elements.filter((element) => element instanceof ArcIndexedCollection || element instanceof ArcCollection).forEach((collection) => {
|
|
22
26
|
const name2 = collection.name;
|
|
23
27
|
if (db.objectStoreNames.contains(name2)) {
|
|
24
28
|
db.deleteObjectStore(collection.name);
|
|
@@ -26,7 +30,7 @@ var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, re
|
|
|
26
30
|
const objectStore = db.createObjectStore(collection.name, {
|
|
27
31
|
keyPath: "_id"
|
|
28
32
|
});
|
|
29
|
-
if (collection
|
|
33
|
+
if (collection instanceof ArcIndexedCollection) {
|
|
30
34
|
Object.entries(collection.indexes).forEach(([name3, keyPath]) => {
|
|
31
35
|
objectStore.createIndex(name3, keyPath, {
|
|
32
36
|
unique: false
|
|
@@ -34,6 +38,12 @@ var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, re
|
|
|
34
38
|
});
|
|
35
39
|
}
|
|
36
40
|
});
|
|
41
|
+
if (db.objectStoreNames.contains("state")) {
|
|
42
|
+
db.deleteObjectStore("state");
|
|
43
|
+
}
|
|
44
|
+
db.createObjectStore("state", {
|
|
45
|
+
keyPath: "_id"
|
|
46
|
+
});
|
|
37
47
|
});
|
|
38
48
|
});
|
|
39
49
|
|
|
@@ -42,45 +52,39 @@ class IDBReadTransaction {
|
|
|
42
52
|
constructor(transaction) {
|
|
43
53
|
this.transaction = transaction;
|
|
44
54
|
}
|
|
45
|
-
async findById(
|
|
55
|
+
async findById(store, id) {
|
|
46
56
|
return new Promise((resolve) => {
|
|
47
|
-
const result = this.transaction.objectStore(
|
|
57
|
+
const result = this.transaction.objectStore(store).get(id);
|
|
48
58
|
result.onsuccess = (e) => {
|
|
49
|
-
|
|
50
|
-
return resolve(undefined);
|
|
51
|
-
const deserialized = collection.deserialize(e.target.result);
|
|
52
|
-
resolve(deserialized);
|
|
59
|
+
resolve(e.target.result);
|
|
53
60
|
};
|
|
54
61
|
});
|
|
55
62
|
}
|
|
56
|
-
async findByIndex(
|
|
63
|
+
async findByIndex(store, index, data) {
|
|
57
64
|
return new Promise((resolve) => {
|
|
58
|
-
const idbIndex = this.transaction.objectStore(
|
|
65
|
+
const idbIndex = this.transaction.objectStore(store).index(index);
|
|
59
66
|
const value = idbIndex.keyPath.map((key) => data[key]);
|
|
60
67
|
const keyRange = IDBKeyRange.only(value);
|
|
61
68
|
const result = idbIndex.getAll(keyRange);
|
|
62
69
|
result.onsuccess = (e) => {
|
|
63
|
-
|
|
64
|
-
resolve(deserialized);
|
|
70
|
+
resolve(e.target.result);
|
|
65
71
|
};
|
|
66
72
|
});
|
|
67
73
|
}
|
|
68
|
-
async findAll(
|
|
74
|
+
async findAll(store) {
|
|
69
75
|
return new Promise((resolve) => {
|
|
70
|
-
const result = this.transaction.objectStore(
|
|
76
|
+
const result = this.transaction.objectStore(store).getAll();
|
|
71
77
|
result.onsuccess = (e) => {
|
|
72
|
-
|
|
73
|
-
resolve(deserialized);
|
|
78
|
+
resolve(e.target.result);
|
|
74
79
|
};
|
|
75
80
|
});
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
class IDBReadWriteTransaction extends IDBReadTransaction {
|
|
80
|
-
async set(
|
|
85
|
+
async set(store, data) {
|
|
81
86
|
return new Promise((resolve, reject) => {
|
|
82
|
-
const
|
|
83
|
-
const result = this.transaction.objectStore(collection.name).put(serialized);
|
|
87
|
+
const result = this.transaction.objectStore(store).put(data);
|
|
84
88
|
result.onsuccess = (e) => {
|
|
85
89
|
resolve();
|
|
86
90
|
};
|
|
@@ -89,9 +93,9 @@ class IDBReadWriteTransaction extends IDBReadTransaction {
|
|
|
89
93
|
};
|
|
90
94
|
});
|
|
91
95
|
}
|
|
92
|
-
async remove(
|
|
96
|
+
async remove(store, id) {
|
|
93
97
|
return new Promise((resolve, reject) => {
|
|
94
|
-
const result = this.transaction.objectStore(
|
|
98
|
+
const result = this.transaction.objectStore(store).delete(id);
|
|
95
99
|
result.onsuccess = (e) => {
|
|
96
100
|
resolve();
|
|
97
101
|
};
|
|
@@ -115,98 +119,118 @@ class IDBAdapter {
|
|
|
115
119
|
constructor(db) {
|
|
116
120
|
this.db = db;
|
|
117
121
|
}
|
|
118
|
-
readWriteTransaction(
|
|
119
|
-
|
|
122
|
+
readWriteTransaction(stores) {
|
|
123
|
+
if (!stores)
|
|
124
|
+
stores = Array.from(this.db.objectStoreNames);
|
|
125
|
+
const transaction = this.db.transaction(stores, "readwrite");
|
|
120
126
|
return new IDBReadWriteTransaction(transaction);
|
|
121
127
|
}
|
|
122
|
-
readTransaction(
|
|
123
|
-
|
|
128
|
+
readTransaction(stores) {
|
|
129
|
+
if (!stores)
|
|
130
|
+
stores = Array.from(this.db.objectStoreNames);
|
|
131
|
+
const transaction = this.db.transaction(stores, "readonly");
|
|
124
132
|
return new IDBReadTransaction(transaction);
|
|
125
133
|
}
|
|
126
134
|
}
|
|
127
135
|
// reactModel.tsx
|
|
128
136
|
import {
|
|
129
|
-
|
|
137
|
+
MasterDataStorage,
|
|
138
|
+
rtcClientFactory
|
|
130
139
|
} from "@arcote.tech/arc";
|
|
131
|
-
import { createContext, useContext, useEffect, useState } from "react";
|
|
140
|
+
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
132
141
|
import { jsx } from "react/jsx-runtime";
|
|
133
|
-
var reactModel = (
|
|
142
|
+
var reactModel = (arcContext, databaseName) => {
|
|
134
143
|
const LiveModelContext = createContext(null);
|
|
135
144
|
const LocalModelContext = createContext(null);
|
|
145
|
+
let dataStorage = null;
|
|
136
146
|
return [
|
|
137
|
-
function LiveModelProvider(
|
|
147
|
+
function LiveModelProvider({ children }) {
|
|
148
|
+
const dbAdapterPromise = idbAdapterFactory(databaseName, arcContext.version)(arcContext);
|
|
149
|
+
dataStorage = new MasterDataStorage(dbAdapterPromise, rtcClientFactory, arcContext);
|
|
138
150
|
return /* @__PURE__ */ jsx(LiveModelContext.Provider, {
|
|
139
|
-
value: {
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
children: props.children
|
|
151
|
+
value: { dataStorage, dbAdapterPromise },
|
|
152
|
+
children
|
|
143
153
|
}, undefined, false, undefined, this);
|
|
144
154
|
},
|
|
145
|
-
function LocalModelProvider(
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
155
|
+
function LocalModelProvider({ children }) {
|
|
156
|
+
const parentContext = useContext(LiveModelContext);
|
|
157
|
+
if (!parentContext) {
|
|
148
158
|
throw new Error("LocalModelProvider must be used within a LiveModelProvider");
|
|
149
159
|
}
|
|
150
|
-
const [
|
|
160
|
+
const [localContext] = useState(() => ({
|
|
161
|
+
dbAdapterPromise: parentContext.dbAdapterPromise,
|
|
162
|
+
dataStorage: parentContext.dataStorage.fork()
|
|
163
|
+
}));
|
|
151
164
|
return /* @__PURE__ */ jsx(LocalModelContext.Provider, {
|
|
152
|
-
value:
|
|
153
|
-
|
|
154
|
-
},
|
|
155
|
-
children: props.children
|
|
165
|
+
value: localContext,
|
|
166
|
+
children
|
|
156
167
|
}, undefined, false, undefined, this);
|
|
157
168
|
},
|
|
158
|
-
function useQuery(
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
throw new Error("useQuery must be used within a LiveModelProvider or LocalModelProvider");
|
|
169
|
+
function useQuery(queryBuilderFn, dependencies = []) {
|
|
170
|
+
const context = useContext(LocalModelContext) || useContext(LiveModelContext);
|
|
171
|
+
if (!context) {
|
|
172
|
+
throw new Error("useQuery must be used within a ModelProvider");
|
|
173
|
+
}
|
|
164
174
|
const [result, setResult] = useState(null);
|
|
165
175
|
const [loading, setLoading] = useState(true);
|
|
176
|
+
const queryRef = useRef(null);
|
|
166
177
|
useEffect(() => {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
const queryBuilder = arcContext.queryBuilder();
|
|
179
|
+
const query = queryBuilderFn(queryBuilder).toQuery();
|
|
180
|
+
queryRef.current = query;
|
|
181
|
+
const runQuery = async () => {
|
|
182
|
+
const result2 = await query.run(context.dataStorage, (newResult) => {
|
|
183
|
+
console.log("newResult", newResult);
|
|
184
|
+
setResult(newResult);
|
|
185
|
+
setLoading(false);
|
|
186
|
+
});
|
|
171
187
|
setResult(result2);
|
|
172
188
|
setLoading(false);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
189
|
+
};
|
|
190
|
+
runQuery();
|
|
176
191
|
return () => {
|
|
177
|
-
|
|
192
|
+
queryRef.current?.unsubscribe();
|
|
193
|
+
queryRef.current = null;
|
|
178
194
|
};
|
|
179
|
-
}, [context
|
|
195
|
+
}, [context, ...dependencies]);
|
|
180
196
|
return [result, loading];
|
|
181
197
|
},
|
|
182
198
|
function useCommands() {
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
error: (error) => {
|
|
199
|
-
reject(error);
|
|
199
|
+
const context = useContext(LocalModelContext) || useContext(LiveModelContext);
|
|
200
|
+
if (!context) {
|
|
201
|
+
throw new Error("useQuery must be used within a ModelProvider");
|
|
202
|
+
}
|
|
203
|
+
const commands = arcContext.commands;
|
|
204
|
+
return new Proxy({}, {
|
|
205
|
+
get: (_, name) => {
|
|
206
|
+
if (name in commands) {
|
|
207
|
+
return async (...args) => {
|
|
208
|
+
const dataStorage2 = context.dataStorage.fork();
|
|
209
|
+
const commandContext = arcContext.commandContext(dataStorage2);
|
|
210
|
+
const result = await commands[name](commandContext, ...args);
|
|
211
|
+
await dataStorage2.merge();
|
|
212
|
+
return result;
|
|
213
|
+
};
|
|
200
214
|
}
|
|
201
|
-
|
|
215
|
+
console.warn(`Command '${name}' not found in the context.`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
202
218
|
});
|
|
203
219
|
},
|
|
204
|
-
function
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
220
|
+
async function query(queryBuilderFn) {
|
|
221
|
+
const queryBuilder = arcContext.queryBuilder();
|
|
222
|
+
const query = queryBuilderFn(queryBuilder).toQuery();
|
|
223
|
+
if (!dataStorage)
|
|
224
|
+
throw new Error("dataStorage not found");
|
|
225
|
+
const result = await query.run(dataStorage);
|
|
226
|
+
return result;
|
|
227
|
+
},
|
|
228
|
+
function useLocalDataStorage() {
|
|
229
|
+
const context = useContext(LocalModelContext);
|
|
230
|
+
if (!context) {
|
|
231
|
+
throw new Error("hook must be used within a ModelProvider");
|
|
208
232
|
}
|
|
209
|
-
return
|
|
233
|
+
return context.dataStorage;
|
|
210
234
|
}
|
|
211
235
|
];
|
|
212
236
|
};
|
|
@@ -216,4 +240,4 @@ export {
|
|
|
216
240
|
formResolver
|
|
217
241
|
};
|
|
218
242
|
|
|
219
|
-
//# debugId=
|
|
243
|
+
//# debugId=9B2592D89513AAF264756E2164756E21
|
package/dist/reactModel.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare const reactModel: <
|
|
1
|
+
import { ForkedDataStorage, type ArcContextAny, type CommandsClient, type QueryBuilderFunctionResult, type QueryFactoryFunction } from "@arcote.tech/arc";
|
|
2
|
+
export declare const reactModel: <C extends ArcContextAny>(arcContext: C, databaseName: string) => readonly [({ children }: {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
-
}) => import("react/jsx-dev-runtime").JSX.Element, (
|
|
4
|
+
}) => import("react/jsx-dev-runtime").JSX.Element, ({ children }: {
|
|
5
5
|
children: React.ReactNode;
|
|
6
|
-
}) => import("react/jsx-dev-runtime").JSX.Element, <QueryBuilderFn extends QueryFactoryFunction<
|
|
6
|
+
}) => import("react/jsx-dev-runtime").JSX.Element, <QueryBuilderFn extends QueryFactoryFunction<C>>(queryBuilderFn: QueryBuilderFn, dependencies?: any[]) => [QueryBuilderFunctionResult<QueryBuilderFn>, boolean], () => CommandsClient<C["commands"]>, <QueryBuilderFn extends QueryFactoryFunction<C>>(queryBuilderFn: QueryBuilderFn) => Promise<QueryBuilderFunctionResult<QueryBuilderFn>>, () => ForkedDataStorage];
|
|
7
|
+
//# sourceMappingURL=reactModel.d.ts.map
|
package/package.json
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "0.0.
|
|
7
|
+
"version": "0.0.22",
|
|
8
8
|
"private": false,
|
|
9
9
|
"author": "Przemysław Krasiński [arcote.tech]",
|
|
10
10
|
"description": "React client for the Arc framework, providing utilities for querying data and executing commands, enhancing the development of reactive and efficient user interfaces.",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "rm -rf dist && bun run ./build.ts && bun run build:declaration",
|
|
13
|
-
"build:declaration": "tsc --emitDeclarationOnly --project tsconfig.types.json",
|
|
13
|
+
"build:declaration": "tsc --emitDeclarationOnly --project tsconfig.types.json --declarationMap",
|
|
14
14
|
"postbuild": "rimraf tsconfig.types.tsbuildinfo",
|
|
15
15
|
"type-check": "tsc",
|
|
16
16
|
"dev": "nodemon --ignore dist -e ts,tsx --exec 'bun run build'"
|
|
@@ -18,15 +18,16 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@arcote.tech/arc": "latest",
|
|
20
20
|
"react": "^18.3.1",
|
|
21
|
-
"
|
|
21
|
+
"react-dom": "^18.3.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/bun": "latest",
|
|
25
25
|
"@types/react": "^18.3.5",
|
|
26
|
+
"@types/react-dom": "^18.3.1",
|
|
27
|
+
"nodemon": "^2.0.22",
|
|
26
28
|
"prettier": "^3.0.3",
|
|
27
29
|
"rimraf": "^5.0.5",
|
|
28
|
-
"typescript": "^5.2.2"
|
|
29
|
-
"nodemon": "^2.0.22"
|
|
30
|
+
"typescript": "^5.2.2"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"typescript": "^5.0.0"
|