@delta-comic/db 2.2.0 → 3.0.0-next.5

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/index.mjs ADDED
@@ -0,0 +1,705 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { logger } from "@delta-comic/logger";
3
+ import { isTauri } from "@tauri-apps/api/core";
4
+ import { CamelCasePlugin, Kysely } from "kysely";
5
+ import { SerializePlugin } from "kysely-plugin-serialize";
6
+ import { defineMutation, useMutation, useQuery, useQueryCache } from "@pinia/colada";
7
+ import { SourcedValue, Struct, UniContentPage } from "@delta-comic/model";
8
+ import { fromPairs } from "es-toolkit/compat";
9
+ import { ref, toValue, watch } from "vue";
10
+ //#region lib/utils.ts
11
+ var utils_exports = /* @__PURE__ */ __exportAll({
12
+ CommonQueryKey: () => CommonQueryKey,
13
+ countDb: () => countDb,
14
+ withTransition: () => withTransition
15
+ });
16
+ const transactionLogger = logger.scoped("db:transaction");
17
+ const withTransition = async (handler, trx) => {
18
+ if (trx) return await handler(trx);
19
+ else {
20
+ const { db } = await import("./index.mjs");
21
+ transactionLogger.trace("database transaction started");
22
+ try {
23
+ const result = await db.transaction().setAccessMode("read write").setIsolationLevel("read committed").execute(handler);
24
+ transactionLogger.trace("database transaction committed");
25
+ return result;
26
+ } catch (error) {
27
+ transactionLogger.error("database transaction failed", error);
28
+ throw error;
29
+ }
30
+ }
31
+ };
32
+ async function countDb(sql) {
33
+ return (await sql.select((db) => db.fn.countAll().as("count")).executeTakeFirstOrThrow()).count;
34
+ }
35
+ let CommonQueryKey = /* @__PURE__ */ function(CommonQueryKey) {
36
+ CommonQueryKey["common"] = "db";
37
+ return CommonQueryKey;
38
+ }({});
39
+ //#endregion
40
+ //#region lib/plugin.ts
41
+ var plugin_exports = /* @__PURE__ */ __exportAll({
42
+ QueryKey: () => QueryKey$5,
43
+ removeByNames: () => removeByNames,
44
+ useQuery: () => useQuery$4,
45
+ useRemove: () => useRemove$3,
46
+ useSetKind: () => useSetKind,
47
+ useToggleEnable: () => useToggleEnable,
48
+ useUpsert: () => useUpsert$4
49
+ });
50
+ let QueryKey$5 = /* @__PURE__ */ function(QueryKey) {
51
+ QueryKey["item"] = "db:plugin:";
52
+ return QueryKey;
53
+ }({});
54
+ const removeByNames = async (keys, trx) => {
55
+ if (keys.length === 0) return;
56
+ await trx.deleteFrom("plugin").where("plugin.pluginName", "in", keys).execute();
57
+ };
58
+ const useUpsert$4 = defineMutation(() => {
59
+ const queryCache = useQueryCache();
60
+ const key = ["db", "db:plugin:"];
61
+ const { mutateAsync, ...mutation } = useMutation({
62
+ mutation: async ({ archives, trx }) => withTransition(async (trx) => {
63
+ await trx.replaceInto("plugin").values(archives.map((a) => ({
64
+ ...a,
65
+ meta: JSON.stringify(a.meta)
66
+ }))).execute();
67
+ }, trx),
68
+ onSettled: () => {
69
+ queryCache.invalidateQueries({ key });
70
+ },
71
+ key
72
+ });
73
+ return {
74
+ ...mutation,
75
+ upsert: mutateAsync,
76
+ key
77
+ };
78
+ });
79
+ const useRemove$3 = defineMutation(() => {
80
+ const queryCache = useQueryCache();
81
+ const key = ["db", "db:plugin:"];
82
+ const { mutateAsync, ...mutation } = useMutation({
83
+ mutation: async ({ keys, trx }) => withTransition(async (trx) => {
84
+ await removeByNames(keys, trx);
85
+ }, trx),
86
+ onSettled: () => {
87
+ queryCache.invalidateQueries({ key });
88
+ },
89
+ key
90
+ });
91
+ return {
92
+ ...mutation,
93
+ remove: mutateAsync,
94
+ key
95
+ };
96
+ });
97
+ const useToggleEnable = defineMutation(() => {
98
+ const queryCache = useQueryCache();
99
+ const key = ["db", "db:plugin:"];
100
+ const { mutateAsync, ...mutation } = useMutation({
101
+ mutation: async ({ keys, trx }) => withTransition(async (trx) => {
102
+ for (const key of keys) {
103
+ const isEnable = await trx.selectFrom("plugin").where("pluginName", "=", key).select("enable").executeTakeFirstOrThrow();
104
+ return trx.updateTable("plugin").where("pluginName", "=", key).set({ enable: !isEnable.enable }).execute();
105
+ }
106
+ }, trx),
107
+ onSettled: () => {
108
+ queryCache.invalidateQueries({ key });
109
+ },
110
+ key
111
+ });
112
+ return {
113
+ ...mutation,
114
+ toggle: mutateAsync,
115
+ key
116
+ };
117
+ });
118
+ const useSetKind = defineMutation(() => {
119
+ const queryCache = useQueryCache();
120
+ const key = ["db", "db:plugin:"];
121
+ const { mutateAsync, ...mutation } = useMutation({
122
+ mutation: async ({ pluginName, kind }) => withTransition(async (trx) => {
123
+ const plugin = await trx.selectFrom("plugin").select(["loaderName", "meta"]).where("pluginName", "=", pluginName).executeTakeFirstOrThrow();
124
+ if (plugin.loaderName === "builtin") throw new Error("built-in plugin kind cannot be changed");
125
+ await trx.updateTable("plugin").set({ meta: JSON.stringify({
126
+ ...plugin.meta,
127
+ kind
128
+ }) }).where("pluginName", "=", pluginName).execute();
129
+ }),
130
+ onSettled: () => {
131
+ queryCache.invalidateQueries({ key });
132
+ },
133
+ key
134
+ });
135
+ return {
136
+ ...mutation,
137
+ setKind: mutateAsync,
138
+ key
139
+ };
140
+ });
141
+ const useQuery$4 = (query, otherKeys = [], initialData) => useQuery({
142
+ query: async () => {
143
+ const { db } = await import("./index.mjs");
144
+ return await query(db.selectFrom("plugin"));
145
+ },
146
+ key: () => [
147
+ "db",
148
+ "db:plugin:",
149
+ query
150
+ ].concat(otherKeys),
151
+ staleTime: 15e3,
152
+ refetchOnMount: "always",
153
+ initialData,
154
+ initialDataUpdatedAt: 0
155
+ });
156
+ //#endregion
157
+ //#region lib/itemStore.ts
158
+ var itemStore_exports = /* @__PURE__ */ __exportAll({
159
+ QueryKey: () => QueryKey$4,
160
+ itemKey: () => itemKey,
161
+ useUpsert: () => useUpsert$3
162
+ });
163
+ const itemKey = new SourcedValue("*");
164
+ let QueryKey$4 = /* @__PURE__ */ function(QueryKey) {
165
+ QueryKey["item"] = "db:itemStore:";
166
+ return QueryKey;
167
+ }({});
168
+ const useUpsert$3 = defineMutation(() => {
169
+ const queryCache = useQueryCache();
170
+ const key = ["db", "db:itemStore:"];
171
+ const { mutateAsync, ...mutation } = useMutation({
172
+ mutation: async ({ item, trx }) => withTransition(async (trx) => {
173
+ const k = itemKey.toString([UniContentPage.contentPages.key.toString(item.contentType), item.id]);
174
+ await trx.replaceInto("itemStore").values({
175
+ item: Struct.toRaw(item),
176
+ key: k
177
+ }).execute();
178
+ return k;
179
+ }, trx),
180
+ onSettled: () => {
181
+ queryCache.invalidateQueries({ key });
182
+ },
183
+ key
184
+ });
185
+ return {
186
+ ...mutation,
187
+ upsert: mutateAsync,
188
+ key
189
+ };
190
+ });
191
+ //#endregion
192
+ //#region lib/favourite.ts
193
+ var favourite_exports = /* @__PURE__ */ __exportAll({
194
+ QueryKey: () => QueryKey$3,
195
+ useCreateCard: () => useCreateCard,
196
+ useMoveItem: () => useMoveItem,
197
+ useQueryCard: () => useQueryCard,
198
+ useQueryItem: () => useQueryItem,
199
+ useUpsertItem: () => useUpsertItem
200
+ });
201
+ let QueryKey$3 = /* @__PURE__ */ function(QueryKey) {
202
+ QueryKey["item"] = "db:favouriteItem:";
203
+ QueryKey["card"] = "db:favouriteCard:";
204
+ return QueryKey;
205
+ }({});
206
+ const useUpsertItem = defineMutation(() => {
207
+ const queryCache = useQueryCache();
208
+ const { key: iKey, upsert } = useUpsert$3();
209
+ const key = [
210
+ "db",
211
+ "db:favouriteItem:",
212
+ ...iKey
213
+ ];
214
+ const { mutateAsync, ...mutation } = useMutation({
215
+ mutation: async ({ item, belongTos, trx }) => withTransition(async (trx) => {
216
+ const itemKey = await upsert({
217
+ item,
218
+ trx
219
+ });
220
+ await trx.replaceInto("favouriteItem").values(belongTos.map((belongTo) => ({
221
+ addTime: Date.now(),
222
+ itemKey,
223
+ belongTo
224
+ }))).execute();
225
+ }, trx),
226
+ onSettled: () => {
227
+ queryCache.invalidateQueries({ key });
228
+ },
229
+ key
230
+ });
231
+ return {
232
+ ...mutation,
233
+ upsert: mutateAsync,
234
+ key
235
+ };
236
+ });
237
+ const useMoveItem = defineMutation(() => {
238
+ const queryCache = useQueryCache();
239
+ const key = ["db:favouriteItem:"];
240
+ const { mutateAsync, ...mutation } = useMutation({
241
+ mutation: async ({ item, from, aims, trx }) => withTransition(async (trx) => {
242
+ await trx.deleteFrom("favouriteItem").where("itemKey", "=", item.id).where("belongTo", "=", from).execute();
243
+ await trx.replaceInto("favouriteItem").values(aims.map((to) => ({
244
+ addTime: Date.now(),
245
+ itemKey: item.id,
246
+ belongTo: to
247
+ }))).execute();
248
+ }, trx),
249
+ onSettled: () => {
250
+ queryCache.invalidateQueries({ key });
251
+ },
252
+ key
253
+ });
254
+ return {
255
+ ...mutation,
256
+ move: mutateAsync,
257
+ key
258
+ };
259
+ });
260
+ const useCreateCard = defineMutation(() => {
261
+ const queryCache = useQueryCache();
262
+ const key = ["db:favouriteCard:", "db:favouriteItem:"];
263
+ const { mutateAsync, ...mutation } = useMutation({
264
+ mutation: async ({ card, trx }) => withTransition(async (trx) => {
265
+ await trx.replaceInto("favouriteCard").values(card).execute();
266
+ }, trx),
267
+ onSettled: () => {
268
+ queryCache.invalidateQueries({ key });
269
+ },
270
+ key
271
+ });
272
+ return {
273
+ ...mutation,
274
+ createCard: mutateAsync,
275
+ key
276
+ };
277
+ });
278
+ const useQueryItem = (query, otherKeys = [], initialData) => useQuery({
279
+ query: async () => {
280
+ const { db } = await import("./index.mjs");
281
+ return await query(db.selectFrom("favouriteItem"));
282
+ },
283
+ key: () => [
284
+ "db:favouriteItem:",
285
+ "db:favouriteCard:",
286
+ query
287
+ ].concat(otherKeys),
288
+ staleTime: 15e3,
289
+ initialData,
290
+ initialDataUpdatedAt: 0
291
+ });
292
+ const useQueryCard = (query, otherKeys = [], initialData) => useQuery({
293
+ query: async () => {
294
+ const { db } = await import("./index.mjs");
295
+ return await query(db.selectFrom("favouriteCard"));
296
+ },
297
+ key: () => ["db:favouriteCard:", query].concat(otherKeys),
298
+ staleTime: 15e3,
299
+ refetchOnMount: "always",
300
+ initialData,
301
+ initialDataUpdatedAt: 0
302
+ });
303
+ //#endregion
304
+ //#region lib/history.ts
305
+ var history_exports = /* @__PURE__ */ __exportAll({
306
+ QueryKey: () => QueryKey$2,
307
+ useQuery: () => useQuery$3,
308
+ useRemove: () => useRemove$2,
309
+ useUpsert: () => useUpsert$2
310
+ });
311
+ let QueryKey$2 = /* @__PURE__ */ function(QueryKey) {
312
+ QueryKey["item"] = "db:history:";
313
+ return QueryKey;
314
+ }({});
315
+ const useUpsert$2 = defineMutation(() => {
316
+ const queryCache = useQueryCache();
317
+ const { key: iKey, upsert } = useUpsert$3();
318
+ const key = [
319
+ "db",
320
+ "db:history:",
321
+ ...iKey
322
+ ];
323
+ const { mutateAsync, ...mutation } = useMutation({
324
+ mutation: async ({ item, trx }) => withTransition(async (trx) => {
325
+ const itemKey = await upsert({
326
+ item,
327
+ trx
328
+ });
329
+ await trx.replaceInto("history").values({
330
+ itemKey,
331
+ timestamp: Date.now(),
332
+ ep: Struct.toRaw(item)
333
+ }).execute();
334
+ }, trx),
335
+ onSettled: () => {
336
+ queryCache.invalidateQueries({ key });
337
+ },
338
+ key
339
+ });
340
+ return {
341
+ ...mutation,
342
+ upsert: mutateAsync,
343
+ key
344
+ };
345
+ });
346
+ const useRemove$2 = defineMutation(() => {
347
+ const queryCache = useQueryCache();
348
+ const key = ["db", "db:history:"];
349
+ const { mutateAsync, ...mutation } = useMutation({
350
+ mutation: ({ keys, trx }) => withTransition(async (trx) => {
351
+ await trx.deleteFrom("history").where("history.timestamp", "is", keys).execute();
352
+ }, trx),
353
+ onSettled: () => {
354
+ queryCache.invalidateQueries({ key });
355
+ },
356
+ key
357
+ });
358
+ return {
359
+ ...mutation,
360
+ remove: mutateAsync,
361
+ key
362
+ };
363
+ });
364
+ const useQuery$3 = (query, otherKeys = [], initialData) => useQuery({
365
+ query: async () => {
366
+ const { db } = await import("./index.mjs");
367
+ return await query(db.selectFrom("history"));
368
+ },
369
+ key: () => [
370
+ "db",
371
+ "db:history:",
372
+ query
373
+ ].concat(otherKeys),
374
+ staleTime: 15e3,
375
+ refetchOnMount: "always",
376
+ initialData,
377
+ initialDataUpdatedAt: 0
378
+ });
379
+ //#endregion
380
+ //#region lib/subscribe.ts
381
+ var subscribe_exports = /* @__PURE__ */ __exportAll({
382
+ QueryKey: () => QueryKey$1,
383
+ key: () => key,
384
+ useQuery: () => useQuery$2,
385
+ useRemove: () => useRemove$1,
386
+ useUpsert: () => useUpsert$1
387
+ });
388
+ const key = new SourcedValue();
389
+ let QueryKey$1 = /* @__PURE__ */ function(QueryKey) {
390
+ QueryKey["item"] = "db:subscribe:";
391
+ return QueryKey;
392
+ }({});
393
+ const useUpsert$1 = defineMutation(() => {
394
+ const queryCache = useQueryCache();
395
+ const key = ["db", "db:subscribe:"];
396
+ const { mutateAsync, ...mutation } = useMutation({
397
+ mutation: async ({ items, trx }) => withTransition(async (trx) => {
398
+ await trx.replaceInto("subscribe").values(items.map((item) => ({
399
+ ...item,
400
+ author: JSON.stringify(item.author)
401
+ }))).execute();
402
+ }, trx),
403
+ onSettled: () => {
404
+ queryCache.invalidateQueries({ key });
405
+ },
406
+ key
407
+ });
408
+ return {
409
+ ...mutation,
410
+ upsert: mutateAsync,
411
+ key
412
+ };
413
+ });
414
+ const useRemove$1 = defineMutation(() => {
415
+ const queryCache = useQueryCache();
416
+ const key = ["db", "db:subscribe:"];
417
+ const { mutateAsync, ...mutation } = useMutation({
418
+ mutation: async ({ keys, trx }) => withTransition(async (trx) => {
419
+ await trx.deleteFrom("subscribe").where("subscribe.key", "is", keys).execute();
420
+ }, trx),
421
+ onSettled: () => {
422
+ queryCache.invalidateQueries({ key });
423
+ },
424
+ key
425
+ });
426
+ return {
427
+ ...mutation,
428
+ remove: mutateAsync,
429
+ key
430
+ };
431
+ });
432
+ const useQuery$2 = (query, otherKeys = [], initialData) => useQuery({
433
+ query: async () => {
434
+ const { db } = await import("./index.mjs");
435
+ return await query(db.selectFrom("subscribe"));
436
+ },
437
+ key: () => [
438
+ "db",
439
+ "db:subscribe:",
440
+ query
441
+ ].concat(otherKeys),
442
+ staleTime: 15e3,
443
+ refetchOnMount: "always",
444
+ initialData,
445
+ initialDataUpdatedAt: 0
446
+ });
447
+ //#endregion
448
+ //#region lib/recentView.ts
449
+ var recentView_exports = /* @__PURE__ */ __exportAll({
450
+ QueryKey: () => QueryKey,
451
+ useQuery: () => useQuery$1,
452
+ useRemove: () => useRemove,
453
+ useUpsert: () => useUpsert
454
+ });
455
+ let QueryKey = /* @__PURE__ */ function(QueryKey) {
456
+ QueryKey["item"] = "db:recentView:";
457
+ return QueryKey;
458
+ }({});
459
+ const useUpsert = defineMutation(() => {
460
+ const queryCache = useQueryCache();
461
+ const { key: iKey, upsert } = useUpsert$3();
462
+ const key = [
463
+ "db",
464
+ "db:recentView:",
465
+ ...iKey
466
+ ];
467
+ const { mutateAsync, ...mutation } = useMutation({
468
+ mutation: async ({ item, trx }) => withTransition(async (trx) => {
469
+ const itemKey = await upsert({
470
+ item,
471
+ trx
472
+ });
473
+ await trx.replaceInto("recentView").values({
474
+ isViewed: false,
475
+ itemKey,
476
+ timestamp: Date.now()
477
+ }).execute();
478
+ }, trx),
479
+ onSettled: () => {
480
+ queryCache.invalidateQueries({ key });
481
+ },
482
+ key
483
+ });
484
+ return {
485
+ ...mutation,
486
+ upsert: mutateAsync,
487
+ key
488
+ };
489
+ });
490
+ const useRemove = defineMutation(() => {
491
+ const queryCache = useQueryCache();
492
+ const key = ["db", "db:recentView:"];
493
+ const { mutateAsync, ...mutation } = useMutation({
494
+ mutation: async ({ items, trx }) => withTransition(async (trx) => {
495
+ await trx.deleteFrom("recentView").where("recentView.timestamp", "is", items).execute();
496
+ }, trx),
497
+ onSettled: () => {
498
+ queryCache.invalidateQueries({ key });
499
+ },
500
+ key
501
+ });
502
+ return {
503
+ ...mutation,
504
+ remove: mutateAsync,
505
+ key
506
+ };
507
+ });
508
+ const useQuery$1 = (query, otherKeys = [], initialData) => useQuery({
509
+ query: async () => {
510
+ const { db } = await import("./index.mjs");
511
+ return await query(db.selectFrom("recentView"));
512
+ },
513
+ key: () => [
514
+ "db",
515
+ "db:recentView:",
516
+ query
517
+ ].concat(otherKeys),
518
+ staleTime: 15e3,
519
+ refetchOnMount: "always",
520
+ initialData,
521
+ initialDataUpdatedAt: 0
522
+ });
523
+ //#endregion
524
+ //#region lib/config.ts
525
+ var config_exports = /* @__PURE__ */ __exportAll({ useConfig: () => useConfig });
526
+ const configLogger = logger.scoped("db:config");
527
+ const cloneValue = (value) => {
528
+ if (typeof structuredClone === "function") return structuredClone(value);
529
+ return JSON.parse(JSON.stringify(value));
530
+ };
531
+ const createDefaultData = (config) => fromPairs(Object.entries(config).map(([name, desc]) => [name, desc.defaultValue]));
532
+ const parseJson = (value, fallback) => {
533
+ if (!value) return cloneValue(fallback);
534
+ if (typeof value !== "string") return cloneValue(value);
535
+ try {
536
+ return JSON.parse(value);
537
+ } catch (error) {
538
+ configLogger.warn("failed to parse config value", error);
539
+ return cloneValue(fallback);
540
+ }
541
+ };
542
+ const upsertConfig = async (belongTo, form, data) => {
543
+ const { db } = await import("./index.mjs");
544
+ await db.replaceInto("config").values({
545
+ belongTo,
546
+ form: JSON.stringify(form),
547
+ data: JSON.stringify(data)
548
+ }).execute();
549
+ configLogger.debug("config persisted", { belongTo });
550
+ };
551
+ const useConfig = (belongTo, form) => {
552
+ const defaultData = createDefaultData(form);
553
+ const data = ref(cloneValue(defaultData));
554
+ let hydrated = false;
555
+ let saveTimer;
556
+ const persist = () => {
557
+ if (saveTimer) clearTimeout(saveTimer);
558
+ saveTimer = setTimeout(() => {
559
+ upsertConfig(belongTo, form, data.value).catch((error) => {
560
+ configLogger.warn("failed to persist config value", { belongTo }, error);
561
+ });
562
+ }, 100);
563
+ };
564
+ const ready = (async () => {
565
+ try {
566
+ const { db } = await import("./index.mjs");
567
+ const stored = await db.selectFrom("config").select(["form", "data"]).where("belongTo", "=", belongTo).executeTakeFirst();
568
+ data.value = parseJson(stored?.data, defaultData);
569
+ configLogger.debug("config hydrated", {
570
+ belongTo,
571
+ found: Boolean(stored)
572
+ });
573
+ hydrated = true;
574
+ const storedForm = typeof stored?.form === "string" ? stored.form : JSON.stringify(stored?.form);
575
+ if (!stored || storedForm !== JSON.stringify(form)) persist();
576
+ } catch (error) {
577
+ configLogger.warn("failed to load config value", { belongTo }, error);
578
+ data.value = cloneValue(defaultData);
579
+ hydrated = true;
580
+ }
581
+ })();
582
+ watch(data, () => {
583
+ if (!hydrated) return;
584
+ persist();
585
+ }, {
586
+ deep: true,
587
+ flush: "sync"
588
+ });
589
+ return Object.assign(data, { ready });
590
+ };
591
+ //#endregion
592
+ //#region lib/nativeStore/index.ts
593
+ const nativeStoreLogger = logger.scoped("db:native-store");
594
+ const saveKey = new SourcedValue();
595
+ const cloneDefault = (defaultValue) => {
596
+ const value = toValue(defaultValue);
597
+ if (typeof structuredClone === "function") return structuredClone(value);
598
+ return JSON.parse(JSON.stringify(value));
599
+ };
600
+ const legacyValue = (namespace, key) => {
601
+ try {
602
+ return globalThis.localStorage?.getItem(saveKey.toString([namespace, key])) ?? null;
603
+ } catch {
604
+ return null;
605
+ }
606
+ };
607
+ const parseValue = (value, defaultValue) => {
608
+ if (value === null || value === "") return cloneDefault(defaultValue);
609
+ if (typeof value !== "string") {
610
+ if (typeof structuredClone === "function") return structuredClone(value);
611
+ return JSON.parse(JSON.stringify(value));
612
+ }
613
+ try {
614
+ return JSON.parse(value);
615
+ } catch (error) {
616
+ nativeStoreLogger.warn("failed to parse native store value", error);
617
+ return cloneDefault(defaultValue);
618
+ }
619
+ };
620
+ const getStoreValue = async (namespace, key) => {
621
+ const { db } = await import("./index.mjs");
622
+ return (await db.selectFrom("nativeStore").select("value").where("namespace", "=", namespace).where("key", "=", key).executeTakeFirst())?.value ?? null;
623
+ };
624
+ const setStoreValue = async (namespace, key, value) => {
625
+ const { db } = await import("./index.mjs");
626
+ await db.replaceInto("nativeStore").values({
627
+ namespace,
628
+ key,
629
+ value
630
+ }).execute();
631
+ };
632
+ const useNativeStore = (namespace, key, defaultValue) => {
633
+ const state = ref(cloneDefault(defaultValue));
634
+ let version = 0;
635
+ let hydrated = false;
636
+ let saveTimer;
637
+ const persist = (resolvedKey, value) => {
638
+ if (saveTimer) clearTimeout(saveTimer);
639
+ const encoded = JSON.stringify(value);
640
+ saveTimer = setTimeout(() => {
641
+ setStoreValue(namespace, resolvedKey, encoded).catch((error) => {
642
+ nativeStoreLogger.warn("failed to persist native store value", {
643
+ key: resolvedKey,
644
+ namespace
645
+ }, error);
646
+ });
647
+ }, 100);
648
+ };
649
+ const load = async () => {
650
+ const current = ++version;
651
+ const resolvedKey = toValue(key);
652
+ hydrated = false;
653
+ try {
654
+ const storeValue = await getStoreValue(namespace, resolvedKey);
655
+ const storedValue = storeValue ?? legacyValue(namespace, resolvedKey);
656
+ if (current !== version) return;
657
+ state.value = parseValue(storedValue, defaultValue);
658
+ nativeStoreLogger.debug("native store value hydrated", {
659
+ key: resolvedKey,
660
+ namespace,
661
+ source: storeValue === null ? "legacy-or-default" : "database"
662
+ });
663
+ hydrated = true;
664
+ if (storeValue === null) persist(resolvedKey, state.value);
665
+ } catch (error) {
666
+ nativeStoreLogger.warn("failed to load native store value", {
667
+ key: resolvedKey,
668
+ namespace
669
+ }, error);
670
+ if (current !== version) return;
671
+ state.value = cloneDefault(defaultValue);
672
+ hydrated = true;
673
+ }
674
+ };
675
+ watch(() => toValue(key), () => void load(), { immediate: true });
676
+ watch(state, (value) => {
677
+ if (!hydrated) return;
678
+ persist(toValue(key), value);
679
+ }, { deep: true });
680
+ return state;
681
+ };
682
+ //#endregion
683
+ //#region lib/index.ts
684
+ const databaseLogger = logger.scoped("db:lifecycle");
685
+ databaseLogger.info("database initialization started");
686
+ const isTauriRuntime = isTauri;
687
+ const createDialect = async () => {
688
+ if (isTauriRuntime()) {
689
+ const [{ default: Database }, { TauriSqliteDialect }] = await Promise.all([import("@tauri-apps/plugin-sql"), import("kysely-dialect-tauri")]);
690
+ const database = await Database.load("sqlite:app.db");
691
+ databaseLogger.info("native sqlite dialect initialized");
692
+ return new TauriSqliteDialect({ database });
693
+ }
694
+ const { createWebDialect } = await import("./web-Bv0LYYK_.mjs");
695
+ databaseLogger.info("web sqlite dialect initialized");
696
+ return createWebDialect();
697
+ };
698
+ const db = new Kysely({
699
+ dialect: await createDialect(),
700
+ plugins: [new CamelCasePlugin(), new SerializePlugin()]
701
+ });
702
+ //#endregion
703
+ export { config_exports as ConfigDB, utils_exports as DBUtils, favourite_exports as FavouriteDB, history_exports as HistoryDB, itemStore_exports as ItemStoreDB, plugin_exports as PluginArchiveDB, recentView_exports as RecentDB, subscribe_exports as SubscribeDB, db, isTauriRuntime, useConfig, useNativeStore };
704
+
705
+ //# sourceMappingURL=index.mjs.map