silosdk 0.0.0 → 0.0.1
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 +3 -1
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/cli/d1.cjs +93 -0
- package/dist/cli/d1.mjs +92 -0
- package/dist/cli/index.cjs +93 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +94 -0
- package/dist/cli/init.cjs +134 -0
- package/dist/cli/init.mjs +133 -0
- package/dist/cli/kv.cjs +63 -0
- package/dist/cli/kv.mjs +60 -0
- package/dist/cli/r2.cjs +83 -0
- package/dist/cli/r2.mjs +82 -0
- package/dist/cli/wrangler.cjs +93 -0
- package/dist/cli/wrangler.mjs +89 -0
- package/dist/local/adapters/cloudflare.cjs +200 -0
- package/dist/local/adapters/cloudflare.d.cts +50 -0
- package/dist/local/adapters/cloudflare.d.mts +50 -0
- package/dist/local/adapters/cloudflare.mjs +200 -0
- package/dist/local/auth-context.cjs +14 -0
- package/dist/local/auth-context.d.cts +7 -0
- package/dist/local/auth-context.d.mts +7 -0
- package/dist/local/auth-context.mjs +12 -0
- package/dist/local/auth.cjs +109 -0
- package/dist/local/auth.d.cts +26 -0
- package/dist/local/auth.d.mts +26 -0
- package/dist/local/auth.mjs +99 -0
- package/dist/local/commit.cjs +350 -0
- package/dist/local/commit.d.cts +59 -0
- package/dist/local/commit.d.mts +59 -0
- package/dist/local/commit.mjs +349 -0
- package/dist/local/config.cjs +17 -0
- package/dist/local/config.mjs +15 -0
- package/dist/local/index.cjs +16 -0
- package/dist/local/index.d.cts +10 -0
- package/dist/local/index.d.mts +10 -0
- package/dist/local/index.mjs +9 -0
- package/dist/local/provider.cjs +204 -0
- package/dist/local/provider.d.cts +25 -0
- package/dist/local/provider.d.mts +25 -0
- package/dist/local/provider.mjs +203 -0
- package/dist/local/query-store.cjs +276 -0
- package/dist/local/query-store.mjs +274 -0
- package/dist/local/storage.cjs +71 -0
- package/dist/local/storage.d.cts +7 -0
- package/dist/local/storage.d.mts +7 -0
- package/dist/local/storage.mjs +68 -0
- package/dist/local/sync.cjs +124 -0
- package/dist/local/sync.d.cts +36 -0
- package/dist/local/sync.d.mts +36 -0
- package/dist/local/sync.mjs +122 -0
- package/dist/local/view.cjs +257 -0
- package/dist/local/view.d.cts +24 -0
- package/dist/local/view.d.mts +24 -0
- package/dist/local/view.mjs +254 -0
- package/dist/package.cjs +11 -0
- package/dist/package.mjs +5 -0
- package/dist/schema/index.cjs +276 -0
- package/dist/schema/index.d.cts +207 -0
- package/dist/schema/index.d.mts +207 -0
- package/dist/schema/index.mjs +265 -0
- package/dist/server/auth.cjs +132 -0
- package/dist/server/auth.d.cts +49 -0
- package/dist/server/auth.d.mts +49 -0
- package/dist/server/auth.mjs +122 -0
- package/dist/server/d1.cjs +120 -0
- package/dist/server/d1.mjs +116 -0
- package/dist/server/do.cjs +132 -0
- package/dist/server/do.d.cts +21 -0
- package/dist/server/do.d.mts +21 -0
- package/dist/server/do.mjs +131 -0
- package/dist/server/index.cjs +355 -0
- package/dist/server/index.d.cts +65 -0
- package/dist/server/index.d.mts +65 -0
- package/dist/server/index.mjs +348 -0
- package/dist/server/protect.cjs +34 -0
- package/dist/server/protect.d.cts +32 -0
- package/dist/server/protect.d.mts +32 -0
- package/dist/server/protect.mjs +33 -0
- package/dist/server/r2.cjs +58 -0
- package/dist/server/r2.d.cts +4 -0
- package/dist/server/r2.d.mts +4 -0
- package/dist/server/r2.mjs +53 -0
- package/package.json +55 -2
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_config = require('./config.cjs');
|
|
3
|
+
const require_view = require('./view.cjs');
|
|
4
|
+
const require_storage = require('./storage.cjs');
|
|
5
|
+
let expo_sqlite = require("expo-sqlite");
|
|
6
|
+
let nanoid_non_secure = require("nanoid/non-secure");
|
|
7
|
+
|
|
8
|
+
//#region src/local/commit.ts
|
|
9
|
+
function isCrudOp(op) {
|
|
10
|
+
return op.kind === "add" || op.kind === "update" || op.kind === "remove";
|
|
11
|
+
}
|
|
12
|
+
function isObject(value) {
|
|
13
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
function collectResolvedAssetKeys(value, out) {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
for (const item of value) collectResolvedAssetKeys(item, out);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (!isObject(value)) return;
|
|
21
|
+
if (require_storage.isResolvedAsset(value)) {
|
|
22
|
+
out.add(value.key);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
for (const nested of Object.values(value)) collectResolvedAssetKeys(nested, out);
|
|
26
|
+
}
|
|
27
|
+
function buildAssetCleanupTasks(oldValue, newValue, scope) {
|
|
28
|
+
const oldKeys = /* @__PURE__ */ new Set();
|
|
29
|
+
const newKeys = /* @__PURE__ */ new Set();
|
|
30
|
+
collectResolvedAssetKeys(oldValue, oldKeys);
|
|
31
|
+
collectResolvedAssetKeys(newValue, newKeys);
|
|
32
|
+
const tasks = [];
|
|
33
|
+
for (const key of oldKeys) if (!newKeys.has(key)) tasks.push({
|
|
34
|
+
key,
|
|
35
|
+
scope
|
|
36
|
+
});
|
|
37
|
+
return tasks;
|
|
38
|
+
}
|
|
39
|
+
async function resolveAssetsDeep(value, scope, url, getToken) {
|
|
40
|
+
if (Array.isArray(value)) {
|
|
41
|
+
const out$1 = [];
|
|
42
|
+
for (const item of value) out$1.push(await resolveAssetsDeep(item, scope, url, getToken));
|
|
43
|
+
return out$1;
|
|
44
|
+
}
|
|
45
|
+
if (!isObject(value)) return value;
|
|
46
|
+
if (require_storage.isAssetValue(value)) return require_storage.resolvePendingAsset(value, scope, url, getToken);
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [k, v] of Object.entries(value)) out[k] = await resolveAssetsDeep(v, scope, url, getToken);
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
async function resolveAssetsInOps(ops, url, getToken) {
|
|
52
|
+
const resolved = [];
|
|
53
|
+
for (const op of ops) {
|
|
54
|
+
if (!isCrudOp(op)) {
|
|
55
|
+
resolved.push(op);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (op.kind === "remove") {
|
|
59
|
+
resolved.push(op);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const scope = op.scope ?? "private";
|
|
63
|
+
if (op.kind === "add") {
|
|
64
|
+
const value$1 = await resolveAssetsDeep(op.value, scope, url, getToken);
|
|
65
|
+
resolved.push({
|
|
66
|
+
...op,
|
|
67
|
+
value: value$1
|
|
68
|
+
});
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const value = await resolveAssetsDeep(op.value, scope, url, getToken);
|
|
72
|
+
resolved.push({
|
|
73
|
+
...op,
|
|
74
|
+
value
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return resolved;
|
|
78
|
+
}
|
|
79
|
+
async function getExistingRowData(db, viewName, id) {
|
|
80
|
+
const row = await db.getFirstAsync(`SELECT data FROM views WHERE id = ? AND view = ?`, [id, viewName]);
|
|
81
|
+
if (!row?.data) return null;
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(row.data);
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function mergeForUpdate(existing, patch) {
|
|
89
|
+
if (!isObject(existing)) return patch;
|
|
90
|
+
if (!isObject(patch)) return existing;
|
|
91
|
+
return {
|
|
92
|
+
...existing,
|
|
93
|
+
...patch
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function planAssetCleanupFromOps(db, ops) {
|
|
97
|
+
const tasks = [];
|
|
98
|
+
for (const op of ops) {
|
|
99
|
+
if (!isCrudOp(op)) continue;
|
|
100
|
+
const scope = op.scope ?? "private";
|
|
101
|
+
if (op.kind === "remove") {
|
|
102
|
+
const existing = await getExistingRowData(db, op.view.name, op.id);
|
|
103
|
+
tasks.push(...buildAssetCleanupTasks(existing, null, scope));
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (op.kind === "update") {
|
|
107
|
+
const existing = await getExistingRowData(db, op.view.name, op.id);
|
|
108
|
+
const merged = mergeForUpdate(existing, op.value);
|
|
109
|
+
tasks.push(...buildAssetCleanupTasks(existing, merged, scope));
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return tasks;
|
|
114
|
+
}
|
|
115
|
+
async function performAssetCleanup(tasks, url, getToken) {
|
|
116
|
+
if (!url || tasks.length === 0) return;
|
|
117
|
+
const unique = /* @__PURE__ */ new Map();
|
|
118
|
+
for (const t of tasks) unique.set(`${t.scope}:${t.key}`, t);
|
|
119
|
+
const headers = {};
|
|
120
|
+
if (getToken) {
|
|
121
|
+
const token = await getToken();
|
|
122
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
123
|
+
}
|
|
124
|
+
await Promise.all(Array.from(unique.values()).map(async ({ key }) => {
|
|
125
|
+
const res = await fetch(`${url}/storage/${encodeURIComponent(key)}`, {
|
|
126
|
+
method: "DELETE",
|
|
127
|
+
headers
|
|
128
|
+
});
|
|
129
|
+
if (![
|
|
130
|
+
204,
|
|
131
|
+
404,
|
|
132
|
+
401,
|
|
133
|
+
403
|
|
134
|
+
].includes(res.status)) console.warn(`[silosdk] asset cleanup failed for key ${key}: ${res.status}`);
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
function useCommit() {
|
|
138
|
+
const db = (0, expo_sqlite.useSQLiteContext)();
|
|
139
|
+
const config = require_config.useConfig();
|
|
140
|
+
const { subscribers, syncAdapter } = config;
|
|
141
|
+
const ops = [];
|
|
142
|
+
const touchedViews = /* @__PURE__ */ new Set();
|
|
143
|
+
function view(v, idOrOpts, opts) {
|
|
144
|
+
const id = typeof idOrOpts === "string" ? idOrOpts : void 0;
|
|
145
|
+
const scope = (typeof idOrOpts === "object" ? idOrOpts?.scope : opts?.scope) ?? "private";
|
|
146
|
+
if (id) return {
|
|
147
|
+
update: (value) => {
|
|
148
|
+
touchedViews.add(v);
|
|
149
|
+
ops.push({
|
|
150
|
+
kind: "update",
|
|
151
|
+
view: v,
|
|
152
|
+
id,
|
|
153
|
+
value,
|
|
154
|
+
scope
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
remove: () => {
|
|
158
|
+
touchedViews.add(v);
|
|
159
|
+
ops.push({
|
|
160
|
+
kind: "remove",
|
|
161
|
+
view: v,
|
|
162
|
+
id,
|
|
163
|
+
scope
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
child: (subview) => ({
|
|
167
|
+
add: (cid) => {
|
|
168
|
+
touchedViews.add(v);
|
|
169
|
+
touchedViews.add(subview);
|
|
170
|
+
ops.push({
|
|
171
|
+
kind: "link",
|
|
172
|
+
parent: {
|
|
173
|
+
view: v,
|
|
174
|
+
id
|
|
175
|
+
},
|
|
176
|
+
child: {
|
|
177
|
+
view: subview,
|
|
178
|
+
id: cid
|
|
179
|
+
},
|
|
180
|
+
scope
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
remove: (cid) => {
|
|
184
|
+
touchedViews.add(v);
|
|
185
|
+
touchedViews.add(subview);
|
|
186
|
+
ops.push({
|
|
187
|
+
kind: "unlink",
|
|
188
|
+
parent: {
|
|
189
|
+
view: v,
|
|
190
|
+
id
|
|
191
|
+
},
|
|
192
|
+
child: {
|
|
193
|
+
view: subview,
|
|
194
|
+
id: cid
|
|
195
|
+
},
|
|
196
|
+
scope
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
};
|
|
201
|
+
return { add: (value) => {
|
|
202
|
+
touchedViews.add(v);
|
|
203
|
+
const id$1 = (0, nanoid_non_secure.nanoid)();
|
|
204
|
+
ops.push({
|
|
205
|
+
kind: "add",
|
|
206
|
+
view: v,
|
|
207
|
+
id: id$1,
|
|
208
|
+
value,
|
|
209
|
+
scope
|
|
210
|
+
});
|
|
211
|
+
return id$1;
|
|
212
|
+
} };
|
|
213
|
+
}
|
|
214
|
+
return async (handler) => {
|
|
215
|
+
await handler({ view });
|
|
216
|
+
const resolvedOps = await resolveAssetsInOps(ops, config.url, config.getToken);
|
|
217
|
+
const cleanupTasks = await planAssetCleanupFromOps(db, resolvedOps);
|
|
218
|
+
const privateOps = resolvedOps.filter((op) => (op.scope ?? "private") === "private");
|
|
219
|
+
const publicOps = resolvedOps.filter((op) => op.scope === "public");
|
|
220
|
+
const syncOps = privateOps.length > 0 ? await applyOpsToSqlite(db, privateOps) : [];
|
|
221
|
+
for (const sub of subscribers) for (const coll of touchedViews) if (coll.scope !== "public" && sub[0].includes(coll.name)) {
|
|
222
|
+
sub[1].update();
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
if (syncAdapter && syncOps.length > 0) await syncAdapter.send({ ops: syncOps });
|
|
226
|
+
if (publicOps.length > 0) {
|
|
227
|
+
const qs = require_view.getQueryStoreInstance();
|
|
228
|
+
const url = config.url;
|
|
229
|
+
const getToken = config.getToken;
|
|
230
|
+
const publicViewNames = new Set(publicOps.map((op) => op.kind === "link" || op.kind === "unlink" ? op.parent.view.name : op.view.name));
|
|
231
|
+
qs.invalidate(publicViewNames);
|
|
232
|
+
if (url) {
|
|
233
|
+
const byView = /* @__PURE__ */ new Map();
|
|
234
|
+
for (const op of publicOps) {
|
|
235
|
+
const viewName = op.kind === "link" || op.kind === "unlink" ? op.parent.view.name : op.view.name;
|
|
236
|
+
const existing = byView.get(viewName) ?? [];
|
|
237
|
+
existing.push(op);
|
|
238
|
+
byView.set(viewName, existing);
|
|
239
|
+
}
|
|
240
|
+
const headers = { "Content-Type": "application/json" };
|
|
241
|
+
if (getToken) headers["Authorization"] = `Bearer ${await getToken()}`;
|
|
242
|
+
await Promise.all(Array.from(byView.entries()).map(async ([viewName, viewOps]) => {
|
|
243
|
+
const res = await fetch(`${url}/public/${viewName}`, {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers,
|
|
246
|
+
body: JSON.stringify({ ops: viewOps })
|
|
247
|
+
});
|
|
248
|
+
if (!res.ok) {
|
|
249
|
+
qs.invalidate(new Set([viewName]));
|
|
250
|
+
throw new Error(`Public write to ${viewName} failed: ${res.status}`);
|
|
251
|
+
}
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
await performAssetCleanup(cleanupTasks, config.url, config.getToken);
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
async function applyOpsToSqlite(db, ops) {
|
|
259
|
+
const syncOps = [];
|
|
260
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
261
|
+
await db.withTransactionAsync(async () => {
|
|
262
|
+
for (const op of ops) {
|
|
263
|
+
if (op.kind === "add" && !!op.value) {
|
|
264
|
+
const version = 1;
|
|
265
|
+
await db.runAsync(`INSERT INTO views (id, view, data, createdAt, updatedAt, version) VALUES (?, ?, ?, ?, ?, ?);`, [
|
|
266
|
+
op.id,
|
|
267
|
+
op.view.name,
|
|
268
|
+
JSON.stringify(op.value),
|
|
269
|
+
timestamp,
|
|
270
|
+
timestamp,
|
|
271
|
+
version
|
|
272
|
+
]);
|
|
273
|
+
syncOps.push({
|
|
274
|
+
...op,
|
|
275
|
+
version,
|
|
276
|
+
timestamp
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (op.kind === "update" && !!op.id && !!op.value) {
|
|
280
|
+
await db.runAsync(`UPDATE views
|
|
281
|
+
SET data = jsonb_patch(data, ?), updatedAt = ?, version = version + 1
|
|
282
|
+
WHERE id = ? AND view = ?;`, [
|
|
283
|
+
JSON.stringify(op.value),
|
|
284
|
+
timestamp,
|
|
285
|
+
op.id,
|
|
286
|
+
op.view.name
|
|
287
|
+
]);
|
|
288
|
+
const result = await db.getFirstAsync(`SELECT version, data FROM views WHERE id = ? AND view = ?`, [op.id, op.view.name]);
|
|
289
|
+
const version = result?.version ?? 1;
|
|
290
|
+
const fullData = result?.data ? JSON.parse(result.data) : op.value;
|
|
291
|
+
syncOps.push({
|
|
292
|
+
...op,
|
|
293
|
+
value: fullData,
|
|
294
|
+
version,
|
|
295
|
+
timestamp
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
if (op.kind === "remove" && !!op.id) {
|
|
299
|
+
const version = ((await db.getFirstAsync(`SELECT version FROM views WHERE id = ? AND view = ?`, [op.id, op.view.name]))?.version ?? 0) + 1;
|
|
300
|
+
await db.runAsync(`DELETE FROM views WHERE id = ? AND view = ?;`, [op.id, op.view.name]);
|
|
301
|
+
await db.runAsync(`DELETE FROM relations
|
|
302
|
+
WHERE (parent = ? AND pid = ?)
|
|
303
|
+
OR (child = ? AND cid = ?);`, [
|
|
304
|
+
op.view.name,
|
|
305
|
+
op.id,
|
|
306
|
+
op.view.name,
|
|
307
|
+
op.id
|
|
308
|
+
]);
|
|
309
|
+
syncOps.push({
|
|
310
|
+
...op,
|
|
311
|
+
version,
|
|
312
|
+
timestamp
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
if (op.kind === "link") {
|
|
316
|
+
await db.runAsync(`INSERT INTO relations (parent, pid, child, cid) VALUES (?, ?, ?, ?);`, [
|
|
317
|
+
op.parent.view.name,
|
|
318
|
+
op.parent.id,
|
|
319
|
+
op.child.view.name,
|
|
320
|
+
op.child.id
|
|
321
|
+
]);
|
|
322
|
+
syncOps.push({
|
|
323
|
+
...op,
|
|
324
|
+
version: 0,
|
|
325
|
+
timestamp
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (op.kind === "unlink") {
|
|
329
|
+
await db.runAsync(`DELETE FROM relations WHERE parent = ? AND pid = ? AND child = ? AND cid = ?;`, [
|
|
330
|
+
op.parent.view.name,
|
|
331
|
+
op.parent.id,
|
|
332
|
+
op.child.view.name,
|
|
333
|
+
op.child.id
|
|
334
|
+
]);
|
|
335
|
+
syncOps.push({
|
|
336
|
+
...op,
|
|
337
|
+
version: 0,
|
|
338
|
+
timestamp
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}).catch((err) => {
|
|
343
|
+
console.error(err);
|
|
344
|
+
throw err;
|
|
345
|
+
});
|
|
346
|
+
return syncOps;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//#endregion
|
|
350
|
+
exports.useCommit = useCommit;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Infer, Prettify, Scope, View } from "../schema/index.cjs";
|
|
2
|
+
import "./view.cjs";
|
|
3
|
+
import "./sync.cjs";
|
|
4
|
+
import { SQLiteDatabase } from "expo-sqlite";
|
|
5
|
+
|
|
6
|
+
//#region src/local/commit.d.ts
|
|
7
|
+
type AddOp<V extends View = View> = {
|
|
8
|
+
kind: 'add';
|
|
9
|
+
view: V;
|
|
10
|
+
id: string;
|
|
11
|
+
value: Infer<V>;
|
|
12
|
+
scope?: Scope;
|
|
13
|
+
};
|
|
14
|
+
type UpdateOp<V extends View = View> = {
|
|
15
|
+
kind: 'update';
|
|
16
|
+
view: V;
|
|
17
|
+
id: string;
|
|
18
|
+
value: Partial<Infer<V>>;
|
|
19
|
+
scope?: Scope;
|
|
20
|
+
};
|
|
21
|
+
type RemoveOp<V extends View = View> = {
|
|
22
|
+
kind: 'remove';
|
|
23
|
+
view: V;
|
|
24
|
+
id: string;
|
|
25
|
+
scope?: Scope;
|
|
26
|
+
};
|
|
27
|
+
type LinkOp<Child extends View, Parent extends View> = {
|
|
28
|
+
kind: 'link' | 'unlink';
|
|
29
|
+
parent: {
|
|
30
|
+
view: Parent;
|
|
31
|
+
id: string;
|
|
32
|
+
};
|
|
33
|
+
child: {
|
|
34
|
+
view: Child;
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
scope?: Scope;
|
|
38
|
+
};
|
|
39
|
+
declare function useCommit(): (handler: (batch: {
|
|
40
|
+
view: {
|
|
41
|
+
<V extends View, Value extends Prettify<Infer<V>>>(v: V, opts?: {
|
|
42
|
+
scope?: Scope;
|
|
43
|
+
}): {
|
|
44
|
+
add: (value: Value) => string;
|
|
45
|
+
};
|
|
46
|
+
<V extends View, Value extends Prettify<Infer<V>>>(v: V, id: string, opts?: {
|
|
47
|
+
scope?: Scope;
|
|
48
|
+
}): {
|
|
49
|
+
update: (value: Partial<Value>) => void;
|
|
50
|
+
remove: () => void;
|
|
51
|
+
child: <Subview extends View>(subview: Subview) => {
|
|
52
|
+
add: (id: string) => void;
|
|
53
|
+
remove: (id: string) => void;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}) => any) => Promise<void>;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { AddOp, LinkOp, RemoveOp, UpdateOp, useCommit };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Infer, Prettify, Scope, View } from "../schema/index.mjs";
|
|
2
|
+
import "./view.mjs";
|
|
3
|
+
import "./sync.mjs";
|
|
4
|
+
import { SQLiteDatabase } from "expo-sqlite";
|
|
5
|
+
|
|
6
|
+
//#region src/local/commit.d.ts
|
|
7
|
+
type AddOp<V extends View = View> = {
|
|
8
|
+
kind: 'add';
|
|
9
|
+
view: V;
|
|
10
|
+
id: string;
|
|
11
|
+
value: Infer<V>;
|
|
12
|
+
scope?: Scope;
|
|
13
|
+
};
|
|
14
|
+
type UpdateOp<V extends View = View> = {
|
|
15
|
+
kind: 'update';
|
|
16
|
+
view: V;
|
|
17
|
+
id: string;
|
|
18
|
+
value: Partial<Infer<V>>;
|
|
19
|
+
scope?: Scope;
|
|
20
|
+
};
|
|
21
|
+
type RemoveOp<V extends View = View> = {
|
|
22
|
+
kind: 'remove';
|
|
23
|
+
view: V;
|
|
24
|
+
id: string;
|
|
25
|
+
scope?: Scope;
|
|
26
|
+
};
|
|
27
|
+
type LinkOp<Child extends View, Parent extends View> = {
|
|
28
|
+
kind: 'link' | 'unlink';
|
|
29
|
+
parent: {
|
|
30
|
+
view: Parent;
|
|
31
|
+
id: string;
|
|
32
|
+
};
|
|
33
|
+
child: {
|
|
34
|
+
view: Child;
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
scope?: Scope;
|
|
38
|
+
};
|
|
39
|
+
declare function useCommit(): (handler: (batch: {
|
|
40
|
+
view: {
|
|
41
|
+
<V extends View, Value extends Prettify<Infer<V>>>(v: V, opts?: {
|
|
42
|
+
scope?: Scope;
|
|
43
|
+
}): {
|
|
44
|
+
add: (value: Value) => string;
|
|
45
|
+
};
|
|
46
|
+
<V extends View, Value extends Prettify<Infer<V>>>(v: V, id: string, opts?: {
|
|
47
|
+
scope?: Scope;
|
|
48
|
+
}): {
|
|
49
|
+
update: (value: Partial<Value>) => void;
|
|
50
|
+
remove: () => void;
|
|
51
|
+
child: <Subview extends View>(subview: Subview) => {
|
|
52
|
+
add: (id: string) => void;
|
|
53
|
+
remove: (id: string) => void;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}) => any) => Promise<void>;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { AddOp, LinkOp, RemoveOp, UpdateOp, useCommit };
|