@delta-comic/db 3.0.0-next.11 → 3.0.0-next.12

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.d.mts CHANGED
@@ -1,8 +1,29 @@
1
1
  import { isTauri } from "@tauri-apps/api/core";
2
- import { InsertObject, JSONColumnType, Kysely, Kysely as Kysely$1, SelectQueryBuilder, Selectable } from "kysely";
2
+ import { InsertObject, JSONColumnType, Kysely, Kysely as Kysely$1, KyselyPlugin, PluginTransformQueryArgs, PluginTransformResultArgs, QueryResult, RootOperationNode, SelectQueryBuilder, Selectable, UnknownRow } from "kysely";
3
3
  import { EntryKey } from "@pinia/colada";
4
- import { FormResult, FormSingleConfigure, PluginManifest, SourcedKeyType, SourcedValue, UniEpRaw, UniItem, UniItemAuthor, UniItemRaw } from "@delta-comic/model";
5
4
  import { MaybeRefOrGetter, Ref } from "vue";
5
+ import { FormResult, FormSingleConfigure, PluginManifest, SourcedKeyType, SourcedValue, UniEpRaw, UniItem, UniItemAuthor, UniItemRaw } from "@delta-comic/model";
6
+ import { TSchema } from "typebox";
7
+ //#region lib/generated/favourite_card.table.d.ts
8
+ interface FavouriteCardTable {
9
+ createAt: number;
10
+ title: string;
11
+ private: boolean;
12
+ description: string;
13
+ }
14
+ //#endregion
15
+ //#region lib/generated/favourite_item.table.d.ts
16
+ interface FavouriteItemTable {
17
+ addTime: number;
18
+ belongTo: number;
19
+ itemKey: string;
20
+ }
21
+ //#endregion
22
+ //#region lib/generated/item_store.table.d.ts
23
+ interface ItemStoreTable {
24
+ key: string;
25
+ item: JSONColumnType<UniItemRaw>;
26
+ }
6
27
  declare namespace utils_d_exports {
7
28
  export { CommonQueryKey, countDb, withTransition };
8
29
  }
@@ -14,11 +35,7 @@ declare enum CommonQueryKey {
14
35
  declare namespace itemStore_d_exports {
15
36
  export { QueryKey$5 as QueryKey, StorableItem, StoredItem, Table$6 as Table, itemKey, useUpsert$4 as useUpsert };
16
37
  }
17
- interface Table$6 {
18
- /** @description primary key */
19
- key: string;
20
- item: JSONColumnType<UniItemRaw>;
21
- }
38
+ type Table$6 = ItemStoreTable;
22
39
  type StorableItem = UniItem | UniItemRaw;
23
40
  type StoredItem = Selectable<Table$6>;
24
41
  declare const itemKey: SourcedValue<[string, string]>;
@@ -50,20 +67,9 @@ declare const useUpsert$4: () => {
50
67
  declare namespace favourite_d_exports {
51
68
  export { Card, CardTable, Item$3 as Item, ItemTable, QueryKey$4 as QueryKey, useCreateCard, useMoveItem, useQueryCard, useQueryItem, useUpsertItem };
52
69
  }
53
- interface CardTable {
54
- title: string;
55
- private: boolean;
56
- description: string;
57
- /** @description primary key */
58
- createAt: number;
59
- }
70
+ type CardTable = FavouriteCardTable;
60
71
  type Card = Selectable<CardTable>;
61
- interface ItemTable {
62
- itemKey: string;
63
- /** @description foreign key */
64
- belongTo: CardTable['createAt'];
65
- addTime: number;
66
- }
72
+ type ItemTable = FavouriteItemTable;
67
73
  type Item$3 = Selectable<ItemTable>;
68
74
  declare enum QueryKey$4 {
69
75
  item = "db:favouriteItem:",
@@ -75,7 +81,7 @@ declare const useUpsertItem: () => {
75
81
  belongTos: Item$3["belongTo"][];
76
82
  trx?: Kysely$1<DB>;
77
83
  }) => Promise<void>;
78
- key: (CommonQueryKey | QueryKey$4 | QueryKey$5)[];
84
+ key: (CommonQueryKey | QueryKey$5 | QueryKey$4)[];
79
85
  state: import("vue").ComputedRef<import("@pinia/colada").DataState<void, Error, undefined>>;
80
86
  status: import("vue").ShallowRef<import("@pinia/colada").DataStateStatus>;
81
87
  asyncStatus: import("vue").ShallowRef<import("@pinia/colada").AsyncStatus>;
@@ -144,23 +150,27 @@ declare const useCreateCard: () => {
144
150
  }) => void;
145
151
  reset: () => void;
146
152
  };
147
- declare const useQueryItem: <T>(query: (db: SelectQueryBuilder<DB, "favouriteItem", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
148
- declare const useQueryCard: <T>(query: (db: SelectQueryBuilder<DB, "favouriteCard", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
149
- declare namespace plugin_d_exports {
150
- export { Archive, Meta, QueryKey$3 as QueryKey, Table$5 as Table, removeByNames, useQuery$4 as useQuery, useRemove$3 as useRemove, useToggleEnable, useUpsert$3 as useUpsert };
151
- }
152
- type Meta = PluginManifest;
153
- interface Table$5 {
153
+ declare const useQueryItem: <T>(query: (db: SelectQueryBuilder<DB, "favouriteItem", {}>) => Promise<T>, otherKeys?: MaybeRefOrGetter<EntryKey>, initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
154
+ declare const useQueryCard: <T>(query: (db: SelectQueryBuilder<DB, "favouriteCard", {}>) => Promise<T>, otherKeys?: MaybeRefOrGetter<EntryKey>, initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
155
+ //#endregion
156
+ //#region lib/generated/plugin.table.d.ts
157
+ interface PluginTable {
154
158
  installerName: string;
155
159
  loaderName: string;
156
- /** @description primary key */
157
160
  pluginName: string;
158
- meta: JSONColumnType<Meta>;
161
+ meta: JSONColumnType<PluginManifest>;
159
162
  enable: boolean;
160
163
  installInput: string;
161
- displayName: string;
164
+ displayName: string | null;
162
165
  }
163
- /** @description Not Blue */
166
+ declare namespace plugin_d_exports {
167
+ export { Archive, Meta, QueryKey$3 as QueryKey, Table$5 as Table, removeByNames, useQuery$4 as useQuery, useRemove$3 as useRemove, useToggleEnable, useUpsert$3 as useUpsert };
168
+ }
169
+ type Meta = PluginManifest;
170
+ type Table$5 = Omit<PluginTable, 'meta' | 'enable'> & {
171
+ meta: Selectable<PluginTable>['meta'];
172
+ enable: boolean;
173
+ };
164
174
  type Archive = Selectable<Table$5>;
165
175
  declare enum QueryKey$3 {
166
176
  item = "db:plugin:"
@@ -233,15 +243,17 @@ declare const useToggleEnable: () => {
233
243
  reset: () => void;
234
244
  };
235
245
  declare const useQuery$4: <T>(query: (db: SelectQueryBuilder<DB, "plugin", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
236
- declare namespace history_d_exports {
237
- export { Item$2 as Item, QueryKey$2 as QueryKey, Table$4 as Table, useQuery$3 as useQuery, useRemove$2 as useRemove, useUpsert$2 as useUpsert };
238
- }
239
- interface Table$4 {
240
- /** @description primary key */
246
+ //#endregion
247
+ //#region lib/generated/history.table.d.ts
248
+ interface HistoryTable {
249
+ ep: JSONColumnType<UniEpRaw>;
241
250
  timestamp: number;
242
251
  itemKey: string;
243
- ep: JSONColumnType<UniEpRaw>;
244
252
  }
253
+ declare namespace history_d_exports {
254
+ export { Item$2 as Item, QueryKey$2 as QueryKey, Table$4 as Table, useQuery$3 as useQuery, useRemove$2 as useRemove, useUpsert$2 as useUpsert };
255
+ }
256
+ type Table$4 = HistoryTable;
245
257
  type Item$2 = Selectable<Table$4>;
246
258
  declare enum QueryKey$2 {
247
259
  item = "db:history:"
@@ -291,39 +303,44 @@ declare const useRemove$2: () => {
291
303
  reset: () => void;
292
304
  };
293
305
  declare const useQuery$3: <T>(query: (db: SelectQueryBuilder<DB, "history", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
294
- declare namespace config_d_exports {
295
- export { ConfigDescription, ConfigRef, Table$3 as Table, useConfig };
296
- }
297
- interface Table$3 {
298
- /** @description config owner, usually plugin name */
306
+ //#endregion
307
+ //#region lib/generated/config.table.d.ts
308
+ interface ConfigTable {
299
309
  belongTo: string;
300
- /** @description serialized form structure */
301
310
  form: string;
302
- /** @description serialized config data */
303
311
  data: string;
304
312
  }
313
+ declare namespace config_d_exports {
314
+ export { ConfigDescription, ConfigRef, Table$3 as Table, useConfig };
315
+ }
316
+ type Table$3 = ConfigTable;
305
317
  type ConfigRef<T> = Ref<T> & {
306
318
  readonly ready: Promise<void>;
307
319
  };
308
320
  type ConfigDescription = Record<string, Required<Pick<FormSingleConfigure, 'defaultValue'>> & FormSingleConfigure>;
309
321
  declare const useConfig: <T extends ConfigDescription>(belongTo: string, form: T) => ConfigRef<FormResult<T>>;
310
322
  //#endregion
311
- //#region lib/nativeStore/index.d.ts
312
- interface Table {
323
+ //#region lib/generated/native_store.table.d.ts
324
+ interface NativeStoreTable {
313
325
  namespace: string;
314
326
  key: string;
315
327
  value: string;
316
328
  }
329
+ //#endregion
330
+ //#region lib/nativeStore/index.d.ts
331
+ type Table = NativeStoreTable;
317
332
  declare const useNativeStore: <T extends object>(namespace: string, key: MaybeRefOrGetter<string>, defaultValue: MaybeRefOrGetter<T>) => Ref<T, T>;
318
- declare namespace recentView_d_exports {
319
- export { Item$1 as Item, QueryKey$1 as QueryKey, Table$2 as Table, useQuery$2 as useQuery, useRemove$1 as useRemove, useUpsert$1 as useUpsert };
320
- }
321
- interface Table$2 {
322
- /** @description primary key */
333
+ //#endregion
334
+ //#region lib/generated/recent_view.table.d.ts
335
+ interface RecentViewTable {
323
336
  timestamp: number;
324
337
  itemKey: string;
325
338
  isViewed: boolean;
326
339
  }
340
+ declare namespace recentView_d_exports {
341
+ export { Item$1 as Item, QueryKey$1 as QueryKey, Table$2 as Table, useQuery$2 as useQuery, useRemove$1 as useRemove, useUpsert$1 as useUpsert };
342
+ }
343
+ type Table$2 = RecentViewTable;
327
344
  type Item$1 = Selectable<Table$2>;
328
345
  declare enum QueryKey$1 {
329
346
  item = "db:recentView:"
@@ -373,31 +390,34 @@ declare const useRemove$1: () => {
373
390
  reset: () => void;
374
391
  };
375
392
  declare const useQuery$2: <T>(query: (db: SelectQueryBuilder<DB, "recentView", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
393
+ //#endregion
394
+ //#region lib/generated/subscribe.table.d.ts
395
+ interface SubscribeTable {
396
+ itemKey: string | null;
397
+ author: JSONColumnType<UniItemAuthor> | null;
398
+ type: string;
399
+ key: string;
400
+ plugin: string;
401
+ }
376
402
  declare namespace subscribe_d_exports {
377
403
  export { AuthorItem, AuthorTable, EpItem, EpTable, Item, Key, Key_, QueryKey, Table$1 as Table, key, useQuery$1 as useQuery, useRemove, useUpsert };
378
404
  }
379
405
  declare const key: SourcedValue<[plugin: string, label: string]>;
380
406
  type Key_ = SourcedKeyType<typeof key>;
381
407
  type Key = Exclude<Key_, string>;
382
- interface AuthorTable {
383
- author: JSONColumnType<UniItemAuthor>;
408
+ type AuthorTable = Omit<SubscribeTable, 'itemKey' | 'author' | 'type'> & {
409
+ author: Selectable<SubscribeTable>['author'];
384
410
  itemKey: null;
385
411
  type: 'author';
386
- /** @description primary key */
387
- key: string;
388
- plugin: string;
389
- }
390
- type AuthorItem = Selectable<AuthorTable>;
391
- interface EpTable {
412
+ };
413
+ type AuthorItem = AuthorTable;
414
+ type EpTable = Omit<SubscribeTable, 'itemKey' | 'author' | 'type'> & {
392
415
  author: null;
393
416
  itemKey: string;
394
417
  type: 'ep';
395
- /** @description primary key */
396
- key: string;
397
- plugin: string;
398
- }
399
- type EpItem = Selectable<EpTable>;
400
- type Table$1 = AuthorTable | EpTable;
418
+ };
419
+ type EpItem = EpTable;
420
+ type Table$1 = SubscribeTable;
401
421
  type Item = AuthorItem | EpItem;
402
422
  declare enum QueryKey {
403
423
  item = "db:subscribe:"
@@ -448,6 +468,447 @@ declare const useRemove: () => {
448
468
  };
449
469
  declare const useQuery$1: <T>(query: (db: SelectQueryBuilder<DB, "subscribe", {}>) => Promise<T>, otherKeys?: readonly EntryKey[], initialData?: () => T) => import("@pinia/colada").UseQueryReturn<T, Error, T>;
450
470
  //#endregion
471
+ //#region lib/writeValidation.d.ts
472
+ /**
473
+ * Centralized write gate: validates every insert/replace/update against the
474
+ * generated camelCase row schema before it reaches the dialect. Registered
475
+ * before CamelCasePlugin, so it observes camelCase identifiers and raw values.
476
+ */
477
+ declare class WriteValidationPlugin implements KyselyPlugin {
478
+ transformQuery({ node }: PluginTransformQueryArgs): RootOperationNode;
479
+ transformResult({ result }: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>>;
480
+ }
481
+ //#endregion
482
+ //#region lib/generated/schemas.d.ts
483
+ declare const clientCamelRowSchemas: {
484
+ itemStore: {
485
+ readonly type: "object";
486
+ readonly properties: {
487
+ readonly key: {
488
+ readonly type: "string";
489
+ };
490
+ readonly item: {
491
+ readonly anyOf: readonly [{
492
+ readonly type: "object";
493
+ }, {
494
+ readonly type: "string";
495
+ }];
496
+ };
497
+ };
498
+ readonly required: readonly ["key", "item"];
499
+ readonly additionalProperties: false;
500
+ };
501
+ favouriteCard: {
502
+ readonly type: "object";
503
+ readonly properties: {
504
+ readonly createAt: {
505
+ readonly type: "integer";
506
+ };
507
+ readonly title: {
508
+ readonly type: "string";
509
+ };
510
+ readonly private: {
511
+ readonly anyOf: readonly [{
512
+ readonly type: "boolean";
513
+ }, {
514
+ readonly const: 0;
515
+ }, {
516
+ readonly const: 1;
517
+ }];
518
+ };
519
+ readonly description: {
520
+ readonly type: "string";
521
+ };
522
+ };
523
+ readonly required: readonly ["createAt", "title", "private", "description"];
524
+ readonly additionalProperties: false;
525
+ };
526
+ favouriteItem: {
527
+ readonly type: "object";
528
+ readonly properties: {
529
+ readonly addTime: {
530
+ readonly type: "integer";
531
+ };
532
+ readonly belongTo: {
533
+ readonly type: "integer";
534
+ };
535
+ readonly itemKey: {
536
+ readonly type: "string";
537
+ };
538
+ };
539
+ readonly required: readonly ["addTime", "belongTo", "itemKey"];
540
+ readonly additionalProperties: false;
541
+ };
542
+ history: {
543
+ readonly type: "object";
544
+ readonly properties: {
545
+ readonly ep: {
546
+ readonly anyOf: readonly [{
547
+ readonly type: "object";
548
+ }, {
549
+ readonly type: "string";
550
+ }];
551
+ };
552
+ readonly timestamp: {
553
+ readonly type: "integer";
554
+ };
555
+ readonly itemKey: {
556
+ readonly type: "string";
557
+ };
558
+ };
559
+ readonly required: readonly ["ep", "timestamp", "itemKey"];
560
+ readonly additionalProperties: false;
561
+ };
562
+ recentView: {
563
+ readonly type: "object";
564
+ readonly properties: {
565
+ readonly timestamp: {
566
+ readonly type: "integer";
567
+ };
568
+ readonly itemKey: {
569
+ readonly type: "string";
570
+ };
571
+ readonly isViewed: {
572
+ readonly anyOf: readonly [{
573
+ readonly type: "boolean";
574
+ }, {
575
+ readonly const: 0;
576
+ }, {
577
+ readonly const: 1;
578
+ }];
579
+ };
580
+ };
581
+ readonly required: readonly ["timestamp", "itemKey", "isViewed"];
582
+ readonly additionalProperties: false;
583
+ };
584
+ subscribe: {
585
+ readonly type: "object";
586
+ readonly properties: {
587
+ readonly itemKey: {
588
+ readonly anyOf: readonly [{
589
+ readonly type: "string";
590
+ }, {
591
+ readonly type: "null";
592
+ }];
593
+ };
594
+ readonly author: {
595
+ readonly anyOf: readonly [{
596
+ readonly type: "object";
597
+ }, {
598
+ readonly type: "string";
599
+ }, {
600
+ readonly type: "null";
601
+ }];
602
+ };
603
+ readonly type: {
604
+ readonly type: "string";
605
+ };
606
+ readonly key: {
607
+ readonly type: "string";
608
+ };
609
+ readonly plugin: {
610
+ readonly type: "string";
611
+ };
612
+ };
613
+ readonly required: readonly ["itemKey", "author", "type", "key", "plugin"];
614
+ readonly additionalProperties: false;
615
+ };
616
+ plugin: {
617
+ readonly type: "object";
618
+ readonly properties: {
619
+ readonly installerName: {
620
+ readonly type: "string";
621
+ };
622
+ readonly loaderName: {
623
+ readonly type: "string";
624
+ };
625
+ readonly pluginName: {
626
+ readonly type: "string";
627
+ };
628
+ readonly meta: {
629
+ readonly anyOf: readonly [{
630
+ readonly type: "object";
631
+ }, {
632
+ readonly type: "string";
633
+ }];
634
+ };
635
+ readonly enable: {
636
+ readonly anyOf: readonly [{
637
+ readonly type: "boolean";
638
+ }, {
639
+ readonly const: 0;
640
+ }, {
641
+ readonly const: 1;
642
+ }];
643
+ };
644
+ readonly installInput: {
645
+ readonly type: "string";
646
+ };
647
+ readonly displayName: {
648
+ readonly anyOf: readonly [{
649
+ readonly type: "string";
650
+ }, {
651
+ readonly type: "null";
652
+ }];
653
+ };
654
+ };
655
+ readonly required: readonly ["installerName", "loaderName", "pluginName", "meta", "enable", "installInput", "displayName"];
656
+ readonly additionalProperties: false;
657
+ };
658
+ nativeStore: {
659
+ readonly type: "object";
660
+ readonly properties: {
661
+ readonly namespace: {
662
+ readonly type: "string";
663
+ };
664
+ readonly key: {
665
+ readonly type: "string";
666
+ };
667
+ readonly value: {
668
+ readonly type: "string";
669
+ };
670
+ };
671
+ readonly required: readonly ["namespace", "key", "value"];
672
+ readonly additionalProperties: false;
673
+ };
674
+ config: {
675
+ readonly type: "object";
676
+ readonly properties: {
677
+ readonly belongTo: {
678
+ readonly type: "string";
679
+ };
680
+ readonly form: {
681
+ readonly type: "string";
682
+ };
683
+ readonly data: {
684
+ readonly type: "string";
685
+ };
686
+ };
687
+ readonly required: readonly ["belongTo", "form", "data"];
688
+ readonly additionalProperties: false;
689
+ };
690
+ };
691
+ //#endregion
692
+ //#region lib/validation.d.ts
693
+ type ClientTableName = keyof typeof clientCamelRowSchemas;
694
+ declare const tableSchema: <K extends ClientTableName>(table: K) => {
695
+ itemStore: {
696
+ readonly type: "object";
697
+ readonly properties: {
698
+ readonly key: {
699
+ readonly type: "string";
700
+ };
701
+ readonly item: {
702
+ readonly anyOf: readonly [{
703
+ readonly type: "object";
704
+ }, {
705
+ readonly type: "string";
706
+ }];
707
+ };
708
+ };
709
+ readonly required: readonly ["key", "item"];
710
+ readonly additionalProperties: false;
711
+ };
712
+ favouriteCard: {
713
+ readonly type: "object";
714
+ readonly properties: {
715
+ readonly createAt: {
716
+ readonly type: "integer";
717
+ };
718
+ readonly title: {
719
+ readonly type: "string";
720
+ };
721
+ readonly private: {
722
+ readonly anyOf: readonly [{
723
+ readonly type: "boolean";
724
+ }, {
725
+ readonly const: 0;
726
+ }, {
727
+ readonly const: 1;
728
+ }];
729
+ };
730
+ readonly description: {
731
+ readonly type: "string";
732
+ };
733
+ };
734
+ readonly required: readonly ["createAt", "title", "private", "description"];
735
+ readonly additionalProperties: false;
736
+ };
737
+ favouriteItem: {
738
+ readonly type: "object";
739
+ readonly properties: {
740
+ readonly addTime: {
741
+ readonly type: "integer";
742
+ };
743
+ readonly belongTo: {
744
+ readonly type: "integer";
745
+ };
746
+ readonly itemKey: {
747
+ readonly type: "string";
748
+ };
749
+ };
750
+ readonly required: readonly ["addTime", "belongTo", "itemKey"];
751
+ readonly additionalProperties: false;
752
+ };
753
+ history: {
754
+ readonly type: "object";
755
+ readonly properties: {
756
+ readonly ep: {
757
+ readonly anyOf: readonly [{
758
+ readonly type: "object";
759
+ }, {
760
+ readonly type: "string";
761
+ }];
762
+ };
763
+ readonly timestamp: {
764
+ readonly type: "integer";
765
+ };
766
+ readonly itemKey: {
767
+ readonly type: "string";
768
+ };
769
+ };
770
+ readonly required: readonly ["ep", "timestamp", "itemKey"];
771
+ readonly additionalProperties: false;
772
+ };
773
+ recentView: {
774
+ readonly type: "object";
775
+ readonly properties: {
776
+ readonly timestamp: {
777
+ readonly type: "integer";
778
+ };
779
+ readonly itemKey: {
780
+ readonly type: "string";
781
+ };
782
+ readonly isViewed: {
783
+ readonly anyOf: readonly [{
784
+ readonly type: "boolean";
785
+ }, {
786
+ readonly const: 0;
787
+ }, {
788
+ readonly const: 1;
789
+ }];
790
+ };
791
+ };
792
+ readonly required: readonly ["timestamp", "itemKey", "isViewed"];
793
+ readonly additionalProperties: false;
794
+ };
795
+ subscribe: {
796
+ readonly type: "object";
797
+ readonly properties: {
798
+ readonly itemKey: {
799
+ readonly anyOf: readonly [{
800
+ readonly type: "string";
801
+ }, {
802
+ readonly type: "null";
803
+ }];
804
+ };
805
+ readonly author: {
806
+ readonly anyOf: readonly [{
807
+ readonly type: "object";
808
+ }, {
809
+ readonly type: "string";
810
+ }, {
811
+ readonly type: "null";
812
+ }];
813
+ };
814
+ readonly type: {
815
+ readonly type: "string";
816
+ };
817
+ readonly key: {
818
+ readonly type: "string";
819
+ };
820
+ readonly plugin: {
821
+ readonly type: "string";
822
+ };
823
+ };
824
+ readonly required: readonly ["itemKey", "author", "type", "key", "plugin"];
825
+ readonly additionalProperties: false;
826
+ };
827
+ plugin: {
828
+ readonly type: "object";
829
+ readonly properties: {
830
+ readonly installerName: {
831
+ readonly type: "string";
832
+ };
833
+ readonly loaderName: {
834
+ readonly type: "string";
835
+ };
836
+ readonly pluginName: {
837
+ readonly type: "string";
838
+ };
839
+ readonly meta: {
840
+ readonly anyOf: readonly [{
841
+ readonly type: "object";
842
+ }, {
843
+ readonly type: "string";
844
+ }];
845
+ };
846
+ readonly enable: {
847
+ readonly anyOf: readonly [{
848
+ readonly type: "boolean";
849
+ }, {
850
+ readonly const: 0;
851
+ }, {
852
+ readonly const: 1;
853
+ }];
854
+ };
855
+ readonly installInput: {
856
+ readonly type: "string";
857
+ };
858
+ readonly displayName: {
859
+ readonly anyOf: readonly [{
860
+ readonly type: "string";
861
+ }, {
862
+ readonly type: "null";
863
+ }];
864
+ };
865
+ };
866
+ readonly required: readonly ["installerName", "loaderName", "pluginName", "meta", "enable", "installInput", "displayName"];
867
+ readonly additionalProperties: false;
868
+ };
869
+ nativeStore: {
870
+ readonly type: "object";
871
+ readonly properties: {
872
+ readonly namespace: {
873
+ readonly type: "string";
874
+ };
875
+ readonly key: {
876
+ readonly type: "string";
877
+ };
878
+ readonly value: {
879
+ readonly type: "string";
880
+ };
881
+ };
882
+ readonly required: readonly ["namespace", "key", "value"];
883
+ readonly additionalProperties: false;
884
+ };
885
+ config: {
886
+ readonly type: "object";
887
+ readonly properties: {
888
+ readonly belongTo: {
889
+ readonly type: "string";
890
+ };
891
+ readonly form: {
892
+ readonly type: "string";
893
+ };
894
+ readonly data: {
895
+ readonly type: "string";
896
+ };
897
+ };
898
+ readonly required: readonly ["belongTo", "form", "data"];
899
+ readonly additionalProperties: false;
900
+ };
901
+ }[K];
902
+ /** Validates a row before writing; throws to block invalid data from persisting. */
903
+ declare const assertWrite: <T>(schema: TSchema, table: string, value: T) => T;
904
+ declare const assertWriteRow: <K extends ClientTableName, T>(table: K, value: T) => T;
905
+ /** Validates a row on read; failures are non-intrusive: logged and the value returned as-is. */
906
+ declare const validateRead: <T>(schema: TSchema, table: string, value: T) => T;
907
+ declare const validateReadRow: <K extends ClientTableName, T>(table: K, value: T) => T;
908
+ /** Filters invalid rows on read; failures are non-intrusive: logged and the row dropped. */
909
+ declare const filterValidRows: <T>(schema: TSchema, table: string, rows: readonly T[]) => T[];
910
+ declare const filterValidRowsFor: <K extends ClientTableName, T>(table: K, rows: readonly T[]) => T[];
911
+ //#endregion
451
912
  //#region lib/index.d.ts
452
913
  interface DB {
453
914
  itemStore: Table$6;
@@ -456,12 +917,12 @@ interface DB {
456
917
  history: Table$4;
457
918
  recentView: Table$2;
458
919
  subscribe: Table$1;
459
- plugin: Table$5;
920
+ plugin: PluginTable;
460
921
  nativeStore: Table;
461
922
  config: Table$3;
462
923
  }
463
924
  declare const isTauriRuntime: typeof isTauri;
464
925
  declare const db: Kysely$1<DB>;
465
926
  //#endregion
466
- export { config_d_exports as ConfigDB, DB, utils_d_exports as DBUtils, favourite_d_exports as FavouriteDB, history_d_exports as HistoryDB, type InsertObject, itemStore_d_exports as ItemStoreDB, type Kysely, plugin_d_exports as PluginArchiveDB, recentView_d_exports as RecentDB, subscribe_d_exports as SubscribeDB, Table, db, isTauriRuntime, useConfig, useNativeStore };
927
+ export { ClientTableName, config_d_exports as ConfigDB, DB, utils_d_exports as DBUtils, favourite_d_exports as FavouriteDB, history_d_exports as HistoryDB, type InsertObject, itemStore_d_exports as ItemStoreDB, type Kysely, plugin_d_exports as PluginArchiveDB, type PluginTable, recentView_d_exports as RecentDB, subscribe_d_exports as SubscribeDB, Table, WriteValidationPlugin, assertWrite, assertWriteRow, db, filterValidRows, filterValidRowsFor, isTauriRuntime, tableSchema, useConfig, useNativeStore, validateRead, validateReadRow };
467
928
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -4,9 +4,11 @@ import { isTauri } from "@tauri-apps/api/core";
4
4
  import { CamelCasePlugin, Kysely } from "kysely";
5
5
  import { SerializePlugin } from "kysely-plugin-serialize";
6
6
  import { defineMutation, useMutation, useQuery, useQueryCache } from "@pinia/colada";
7
+ import { ref, toValue, watch } from "vue";
7
8
  import { SourcedValue, Struct, UniContentPage } from "@delta-comic/model";
8
9
  import { fromPairs } from "es-toolkit/compat";
9
- import { ref, toValue, watch } from "vue";
10
+ import { Compile } from "typebox/compile";
11
+ import { Value } from "typebox/value";
10
12
  //#region lib/utils.ts
11
13
  var utils_exports = /* @__PURE__ */ __exportAll({
12
14
  CommonQueryKey: () => CommonQueryKey,
@@ -261,7 +263,7 @@ const useQueryItem = (query, otherKeys = [], initialData) => useQuery({
261
263
  "db:favouriteItem:",
262
264
  "db:favouriteCard:",
263
265
  query,
264
- ...otherKeys
266
+ ...toValue(otherKeys)
265
267
  ],
266
268
  staleTime: 15e3,
267
269
  initialData,
@@ -275,7 +277,7 @@ const useQueryCard = (query, otherKeys = [], initialData) => useQuery({
275
277
  key: () => [
276
278
  "db:favouriteCard:",
277
279
  query,
278
- ...otherKeys
280
+ ...toValue(otherKeys)
279
281
  ],
280
282
  staleTime: 15e3,
281
283
  refetchOnMount: "always",
@@ -311,7 +313,7 @@ const useUpsert$2 = defineMutation(() => {
311
313
  await trx.replaceInto("history").values({
312
314
  itemKey,
313
315
  timestamp: Date.now(),
314
- ep: Struct.toRaw(item)
316
+ ep: Struct.toRaw(item.thisEp)
315
317
  }).execute();
316
318
  }, trx),
317
319
  onSettled: () => {
@@ -573,6 +575,302 @@ const useConfig = (belongTo, form) => {
573
575
  });
574
576
  return Object.assign(data, { ready });
575
577
  };
578
+ const clientCamelRowSchemas = {
579
+ itemStore: {
580
+ type: "object",
581
+ properties: {
582
+ key: { type: "string" },
583
+ item: { anyOf: [{ type: "object" }, { type: "string" }] }
584
+ },
585
+ required: ["key", "item"],
586
+ additionalProperties: false
587
+ },
588
+ favouriteCard: {
589
+ type: "object",
590
+ properties: {
591
+ createAt: { type: "integer" },
592
+ title: { type: "string" },
593
+ private: { anyOf: [
594
+ { type: "boolean" },
595
+ { const: 0 },
596
+ { const: 1 }
597
+ ] },
598
+ description: { type: "string" }
599
+ },
600
+ required: [
601
+ "createAt",
602
+ "title",
603
+ "private",
604
+ "description"
605
+ ],
606
+ additionalProperties: false
607
+ },
608
+ favouriteItem: {
609
+ type: "object",
610
+ properties: {
611
+ addTime: { type: "integer" },
612
+ belongTo: { type: "integer" },
613
+ itemKey: { type: "string" }
614
+ },
615
+ required: [
616
+ "addTime",
617
+ "belongTo",
618
+ "itemKey"
619
+ ],
620
+ additionalProperties: false
621
+ },
622
+ history: {
623
+ type: "object",
624
+ properties: {
625
+ ep: { anyOf: [{ type: "object" }, { type: "string" }] },
626
+ timestamp: { type: "integer" },
627
+ itemKey: { type: "string" }
628
+ },
629
+ required: [
630
+ "ep",
631
+ "timestamp",
632
+ "itemKey"
633
+ ],
634
+ additionalProperties: false
635
+ },
636
+ recentView: {
637
+ type: "object",
638
+ properties: {
639
+ timestamp: { type: "integer" },
640
+ itemKey: { type: "string" },
641
+ isViewed: { anyOf: [
642
+ { type: "boolean" },
643
+ { const: 0 },
644
+ { const: 1 }
645
+ ] }
646
+ },
647
+ required: [
648
+ "timestamp",
649
+ "itemKey",
650
+ "isViewed"
651
+ ],
652
+ additionalProperties: false
653
+ },
654
+ subscribe: {
655
+ type: "object",
656
+ properties: {
657
+ itemKey: { anyOf: [{ type: "string" }, { type: "null" }] },
658
+ author: { anyOf: [
659
+ { type: "object" },
660
+ { type: "string" },
661
+ { type: "null" }
662
+ ] },
663
+ type: { type: "string" },
664
+ key: { type: "string" },
665
+ plugin: { type: "string" }
666
+ },
667
+ required: [
668
+ "itemKey",
669
+ "author",
670
+ "type",
671
+ "key",
672
+ "plugin"
673
+ ],
674
+ additionalProperties: false
675
+ },
676
+ plugin: {
677
+ type: "object",
678
+ properties: {
679
+ installerName: { type: "string" },
680
+ loaderName: { type: "string" },
681
+ pluginName: { type: "string" },
682
+ meta: { anyOf: [{ type: "object" }, { type: "string" }] },
683
+ enable: { anyOf: [
684
+ { type: "boolean" },
685
+ { const: 0 },
686
+ { const: 1 }
687
+ ] },
688
+ installInput: { type: "string" },
689
+ displayName: { anyOf: [{ type: "string" }, { type: "null" }] }
690
+ },
691
+ required: [
692
+ "installerName",
693
+ "loaderName",
694
+ "pluginName",
695
+ "meta",
696
+ "enable",
697
+ "installInput",
698
+ "displayName"
699
+ ],
700
+ additionalProperties: false
701
+ },
702
+ nativeStore: {
703
+ type: "object",
704
+ properties: {
705
+ namespace: { type: "string" },
706
+ key: { type: "string" },
707
+ value: { type: "string" }
708
+ },
709
+ required: [
710
+ "namespace",
711
+ "key",
712
+ "value"
713
+ ],
714
+ additionalProperties: false
715
+ },
716
+ config: {
717
+ type: "object",
718
+ properties: {
719
+ belongTo: { type: "string" },
720
+ form: { type: "string" },
721
+ data: { type: "string" }
722
+ },
723
+ required: [
724
+ "belongTo",
725
+ "form",
726
+ "data"
727
+ ],
728
+ additionalProperties: false
729
+ }
730
+ };
731
+ //#endregion
732
+ //#region lib/validation.ts
733
+ const validationLogger = logger.scoped("db:validation");
734
+ const validators = /* @__PURE__ */ new WeakMap();
735
+ const validatorFor = (schema) => {
736
+ const cached = validators.get(schema);
737
+ if (cached) return cached;
738
+ const validator = Compile(schema);
739
+ validators.set(schema, validator);
740
+ return validator;
741
+ };
742
+ const validationDetails = (schema, value) => [...Value.Errors(schema, value)].slice(0, 5).map((error) => ({
743
+ instancePath: error.instancePath,
744
+ message: error.message
745
+ }));
746
+ const tableSchema = (table) => clientCamelRowSchemas[table];
747
+ /** Validates a row before writing; throws to block invalid data from persisting. */
748
+ const assertWrite = (schema, table, value) => {
749
+ if (!validatorFor(schema).Check(value)) {
750
+ validationLogger.error("database write validation failed", {
751
+ table,
752
+ errors: validationDetails(schema, value)
753
+ });
754
+ throw new Error(`database write validation failed for ${table}: ${JSON.stringify(validationDetails(schema, value))}`);
755
+ }
756
+ return value;
757
+ };
758
+ const assertWriteRow = (table, value) => assertWrite(tableSchema(table), table, value);
759
+ /** Validates a row on read; failures are non-intrusive: logged and the value returned as-is. */
760
+ const validateRead = (schema, table, value) => {
761
+ if (!validatorFor(schema).Check(value)) validationLogger.warn("database read validation failed", {
762
+ table,
763
+ errors: validationDetails(schema, value)
764
+ });
765
+ return value;
766
+ };
767
+ const validateReadRow = (table, value) => validateRead(tableSchema(table), table, value);
768
+ /** Filters invalid rows on read; failures are non-intrusive: logged and the row dropped. */
769
+ const filterValidRows = (schema, table, rows) => {
770
+ const valid = [];
771
+ for (const row of rows) {
772
+ if (validatorFor(schema).Check(row)) {
773
+ valid.push(row);
774
+ continue;
775
+ }
776
+ validationLogger.warn("database read validation failed, row dropped", {
777
+ table,
778
+ errors: validationDetails(schema, row)
779
+ });
780
+ }
781
+ return valid;
782
+ };
783
+ const filterValidRowsFor = (table, rows) => filterValidRows(tableSchema(table), table, rows);
784
+ //#endregion
785
+ //#region lib/writeValidation.ts
786
+ const isTableNode = (node) => node?.kind === "TableNode";
787
+ const isValuesNode = (node) => node?.kind === "ValuesNode";
788
+ const isValueNode = (node) => node.kind === "ValueNode";
789
+ const isColumnNode = (node) => node.kind === "ColumnNode";
790
+ const tableNameOf = (node) => {
791
+ if (!isTableNode(node)) return null;
792
+ return node.table.identifier.name;
793
+ };
794
+ const rowObjectsOf = (node) => {
795
+ const columns = node.columns;
796
+ if (!columns || columns.length === 0) return null;
797
+ const names = columns.map((column) => column.column.name);
798
+ const values = node.values;
799
+ if (!isValuesNode(values)) return null;
800
+ const rows = [];
801
+ for (const list of values.values) {
802
+ let entries;
803
+ if (list.kind === "PrimitiveValueListNode") entries = [...list.values];
804
+ else if (list.kind === "ValueListNode") {
805
+ const wrapped = [];
806
+ for (const entry of list.values) {
807
+ if (!isValueNode(entry)) return null;
808
+ wrapped.push(entry.value);
809
+ }
810
+ entries = wrapped;
811
+ } else return null;
812
+ if (entries.length !== names.length) return null;
813
+ rows.push(Object.fromEntries(names.map((name, index) => [name, entries[index]])));
814
+ }
815
+ return rows;
816
+ };
817
+ const updatePatchOf = (node) => {
818
+ if (!node.updates || node.updates.length === 0) return null;
819
+ const patch = {};
820
+ for (const update of node.updates) {
821
+ if (!isColumnNode(update.column)) return null;
822
+ const value = update.value;
823
+ if (!isValueNode(value)) return null;
824
+ patch[update.column.column.name] = value.value;
825
+ }
826
+ return patch;
827
+ };
828
+ const partialSchemas = /* @__PURE__ */ new WeakMap();
829
+ const partialOf = (schema) => {
830
+ const cached = partialSchemas.get(schema);
831
+ if (cached) return cached;
832
+ const partial = {
833
+ ...schema,
834
+ required: void 0
835
+ };
836
+ partialSchemas.set(schema, partial);
837
+ return partial;
838
+ };
839
+ const validateWriteNode = (node) => {
840
+ let tableName = null;
841
+ let rows = null;
842
+ let patch = null;
843
+ if (node.kind === "InsertQueryNode") {
844
+ tableName = tableNameOf(node.into);
845
+ rows = rowObjectsOf(node);
846
+ } else if (node.kind === "UpdateQueryNode") {
847
+ tableName = tableNameOf(node.table);
848
+ patch = updatePatchOf(node);
849
+ } else return;
850
+ if (tableName === null) return;
851
+ const schema = clientCamelRowSchemas[tableName];
852
+ if (!schema) return;
853
+ if (rows !== null) {
854
+ if (rows.length === 0) return;
855
+ for (const row of rows) assertWrite(schema, tableName, row);
856
+ return;
857
+ }
858
+ if (patch !== null) assertWrite(partialOf(schema), tableName, patch);
859
+ };
860
+ /**
861
+ * Centralized write gate: validates every insert/replace/update against the
862
+ * generated camelCase row schema before it reaches the dialect. Registered
863
+ * before CamelCasePlugin, so it observes camelCase identifiers and raw values.
864
+ */
865
+ var WriteValidationPlugin = class {
866
+ transformQuery({ node }) {
867
+ validateWriteNode(node);
868
+ return node;
869
+ }
870
+ async transformResult({ result }) {
871
+ return result;
872
+ }
873
+ };
576
874
  //#endregion
577
875
  //#region lib/nativeStore/index.ts
578
876
  const nativeStoreLogger = logger.scoped("db:native-store");
@@ -682,9 +980,13 @@ const createDialect = async () => {
682
980
  };
683
981
  const db = new Kysely({
684
982
  dialect: await createDialect(),
685
- plugins: [new CamelCasePlugin(), new SerializePlugin()]
983
+ plugins: [
984
+ new WriteValidationPlugin(),
985
+ new CamelCasePlugin(),
986
+ new SerializePlugin()
987
+ ]
686
988
  });
687
989
  //#endregion
688
- 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 };
990
+ 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, WriteValidationPlugin, assertWrite, assertWriteRow, db, filterValidRows, filterValidRowsFor, isTauriRuntime, tableSchema, useConfig, useNativeStore, validateRead, validateReadRow };
689
991
 
690
992
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["QueryKey","useUpsert","useRemove","useQuery","useColadaQuery","QueryKey","useUpsert","QueryKey","ItemStoreDB.useUpsert","useColadaQuery","QueryKey","useUpsert","ItemStoreDB.useUpsert","useRemove","useQuery","useColadaQuery","QueryKey","useUpsert","useRemove","useQuery","useColadaQuery","ItemStoreDB.useUpsert","useQuery","useColadaQuery"],"sources":["../lib/utils.ts","../lib/plugin.ts","../lib/itemStore.ts","../lib/favourite.ts","../lib/history.ts","../lib/subscribe.ts","../lib/recentView.ts","../lib/config.ts","../lib/nativeStore/index.ts","../lib/index.ts"],"sourcesContent":["import { logger } from '@delta-comic/logger'\nimport type { Kysely, SelectQueryBuilder } from 'kysely'\n\nimport type { DB } from '.'\n\nconst transactionLogger = logger.scoped('db:transaction')\n\nexport const withTransition = async <T>(\n handler: (trx: Kysely<DB>) => Promise<T>,\n trx?: Kysely<DB>,\n) => {\n if (trx) return await handler(trx)\n else {\n const { db } = await import('.')\n transactionLogger.trace('database transaction started')\n try {\n const result = await db\n .transaction()\n .setAccessMode('read write')\n .setIsolationLevel('read committed')\n .execute(handler)\n transactionLogger.trace('database transaction committed')\n return result\n } catch (error) {\n transactionLogger.error('database transaction failed', error)\n throw error\n }\n }\n}\n\nexport async function countDb<TB extends keyof DB, O extends object>(\n sql: SelectQueryBuilder<DB, TB, O>,\n) {\n const v = await sql.select(db => db.fn.countAll<number>().as('count')).executeTakeFirstOrThrow()\n return v.count\n}\n\nexport enum CommonQueryKey {\n common = 'db',\n}","import type { PluginManifest } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { JSONColumnType, Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type Meta = PluginManifest\n\nexport interface Table {\n installerName: string\n loaderName: string\n /** @description primary key */\n pluginName: string\n meta: JSONColumnType<Meta>\n enable: boolean\n installInput: string\n displayName: string\n}\n\n/** @description Not Blue */\nexport type Archive = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:plugin:',\n}\n\nexport const removeByNames = async (keys: Archive['pluginName'][], trx: Kysely<DB>) => {\n if (keys.length === 0) return\n await trx.deleteFrom('plugin').where('plugin.pluginName', 'in', keys).execute()\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ archives, trx }: { archives: Archive[]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx\n .replaceInto('plugin')\n .values(archives.map(a => ({ ...a, meta: JSON.stringify(a.meta) })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Archive['pluginName'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await removeByNames(keys, trx)\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useToggleEnable = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Archive['pluginName'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n for (const key of keys) {\n const isEnable = await trx\n .selectFrom('plugin')\n .where('pluginName', '=', key)\n .select('enable')\n .executeTakeFirstOrThrow()\n return trx\n .updateTable('plugin')\n .where('pluginName', '=', key)\n .set({ enable: !isEnable.enable })\n .execute()\n }\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, toggle: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'plugin', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('plugin'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import {\n SourcedValue,\n Struct,\n UniContentPage,\n type UniItem,\n type UniItemRaw,\n} from '@delta-comic/model'\nimport { defineMutation, useMutation, useQueryCache } from '@pinia/colada'\nimport type { JSONColumnType, Kysely, Selectable } from 'kysely'\n\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport interface Table {\n /** @description primary key */\n key: string\n item: JSONColumnType<UniItemRaw>\n}\nexport type StorableItem = UniItem | UniItemRaw\nexport type StoredItem = Selectable<Table>\nexport const itemKey = new SourcedValue('*')\n\nexport enum QueryKey {\n item = 'db:itemStore:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const k = itemKey.toString([\n UniContentPage.contentPages.key.toString(item.contentType),\n item.id,\n ])\n await trx\n .replaceInto('itemStore')\n .values({ item: Struct.toRaw(item), key: k })\n .execute()\n return k\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})","import {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport interface CardTable {\n title: string\n private: boolean\n description: string\n /** @description primary key */\n createAt: number\n}\n\nexport type Card = Selectable<CardTable>\n\nexport interface ItemTable {\n itemKey: string\n /** @description foreign key */\n belongTo: CardTable['createAt']\n addTime: number\n}\n\nexport type Item = Selectable<ItemTable>\n\nexport enum QueryKey {\n item = 'db:favouriteItem:',\n card = 'db:favouriteCard:',\n}\n\nexport const useUpsertItem = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({\n item,\n belongTos,\n trx,\n }: {\n item: ItemStoreDB.StorableItem\n belongTos: Item['belongTo'][]\n trx?: Kysely<DB>\n }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('favouriteItem')\n .values(belongTos.map(belongTo => ({ addTime: Date.now(), itemKey, belongTo })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useMoveItem = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({\n item,\n from,\n aims,\n trx,\n }: {\n item: ItemStoreDB.StorableItem\n from: Item['belongTo']\n aims: Item['belongTo'][]\n trx?: Kysely<DB>\n }) =>\n withTransition(async trx => {\n await trx\n .deleteFrom('favouriteItem')\n .where('itemKey', '=', item.id)\n .where('belongTo', '=', from)\n .execute()\n await trx\n .replaceInto('favouriteItem')\n .values(aims.map(to => ({ addTime: Date.now(), itemKey: item.id, belongTo: to })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, move: mutateAsync, key }\n})\n\nexport const useCreateCard = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [QueryKey.card, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ card, trx }: { card: Card; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.replaceInto('favouriteCard').values(card).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, createCard: mutateAsync, key }\n})\n\nexport const useQueryItem = <T>(\n query: (db: SelectQueryBuilder<DB, 'favouriteItem', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('favouriteItem'))\n },\n key: () => [QueryKey.item, QueryKey.card, query, ...otherKeys],\n staleTime: 15000,\n initialData,\n initialDataUpdatedAt: 0,\n })\n\nexport const useQueryCard = <T>(\n query: (db: SelectQueryBuilder<DB, 'favouriteCard', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('favouriteCard'))\n },\n key: () => [QueryKey.card, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { Struct, type UniEpRaw } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { JSONColumnType, Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport interface Table {\n /** @description primary key */\n timestamp: number\n itemKey: string\n ep: JSONColumnType<UniEpRaw>\n}\n\nexport type Item = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:history:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: ItemStoreDB.StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('history')\n .values({ itemKey, timestamp: Date.now(), ep: Struct.toRaw(item) })\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: ({ keys, trx }: { keys: Item['timestamp'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('history').where('history.timestamp', 'is', keys).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'history', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('history'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { SourcedValue, type SourcedKeyType, type UniItemAuthor } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { JSONColumnType, Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport const key = new SourcedValue<[plugin: string, label: string]>()\nexport type Key_ = SourcedKeyType<typeof key>\nexport type Key = Exclude<Key_, string>\n\nexport interface AuthorTable {\n author: JSONColumnType<UniItemAuthor>\n itemKey: null\n type: 'author'\n /** @description primary key */\n key: string\n plugin: string\n}\nexport type AuthorItem = Selectable<AuthorTable>\n\nexport interface EpTable {\n author: null\n itemKey: string // not f key\n type: 'ep'\n /** @description primary key */\n key: string\n plugin: string\n}\nexport type EpItem = Selectable<EpTable>\n\nexport type Table = AuthorTable | EpTable\nexport type Item = AuthorItem | EpItem\n\nexport enum QueryKey {\n item = 'db:subscribe:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ items, trx }: { items: Item[]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx\n .replaceInto('subscribe')\n .values(items.map(item => ({ ...item, author: JSON.stringify(item.author) })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Item['key'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('subscribe').where('subscribe.key', 'is', keys).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'subscribe', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('subscribe'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport interface Table {\n /** @description primary key */\n timestamp: number\n itemKey: string\n isViewed: boolean\n}\nexport type Item = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:recentView:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: ItemStoreDB.StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('recentView')\n .values({ isViewed: false, itemKey, timestamp: Date.now() })\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ items, trx }: { items: Item['timestamp'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('recentView').where('recentView.timestamp', 'is', items).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'recentView', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('recentView'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { logger } from '@delta-comic/logger'\nimport type { FormResult, FormSingleConfigure } from '@delta-comic/model'\nimport { fromPairs } from 'es-toolkit/compat'\nimport { ref, watch, type Ref } from 'vue'\n\nconst configLogger = logger.scoped('db:config')\n\nexport interface Table {\n /** @description config owner, usually plugin name */\n belongTo: string\n /** @description serialized form structure */\n form: string\n /** @description serialized config data */\n data: string\n}\n\nexport type ConfigRef<T> = Ref<T> & { readonly ready: Promise<void> }\n\nexport type ConfigDescription = Record<\n string,\n Required<Pick<FormSingleConfigure, 'defaultValue'>> & FormSingleConfigure\n>\n\nconst cloneValue = <T>(value: T): T => {\n if (typeof structuredClone === 'function') return structuredClone(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nconst createDefaultData = <T extends ConfigDescription>(config: T): FormResult<T> =>\n fromPairs(\n Object.entries(config).map(([name, desc]) => [name, desc.defaultValue]),\n ) as FormResult<T>\n\nconst parseJson = <T>(value: unknown, fallback: T): T => {\n if (!value) return cloneValue(fallback)\n if (typeof value !== 'string') return cloneValue(value as T)\n try {\n return JSON.parse(value) as T\n } catch (error) {\n configLogger.warn('failed to parse config value', error)\n return cloneValue(fallback)\n }\n}\n\nconst upsertConfig = async (belongTo: string, form: ConfigDescription, data: unknown) => {\n const { db } = await import('.')\n await db\n .replaceInto('config')\n .values({ belongTo, form: JSON.stringify(form), data: JSON.stringify(data) })\n .execute()\n configLogger.debug('config persisted', { belongTo })\n}\n\nexport const useConfig = <T extends ConfigDescription>(\n belongTo: string,\n form: T,\n): ConfigRef<FormResult<T>> => {\n const defaultData = createDefaultData(form)\n const data = ref(cloneValue(defaultData)) as Ref<FormResult<T>>\n let hydrated = false\n let saveTimer: ReturnType<typeof setTimeout> | undefined\n\n const persist = () => {\n if (saveTimer) clearTimeout(saveTimer)\n saveTimer = setTimeout(() => {\n void upsertConfig(belongTo, form, data.value).catch(error => {\n configLogger.warn('failed to persist config value', { belongTo }, error)\n })\n }, 100)\n }\n\n const ready = (async () => {\n try {\n const { db } = await import('.')\n const stored = await db\n .selectFrom('config')\n .select(['form', 'data'])\n .where('belongTo', '=', belongTo)\n .executeTakeFirst()\n data.value = parseJson(stored?.data, defaultData)\n configLogger.debug('config hydrated', { belongTo, found: Boolean(stored) })\n hydrated = true\n const storedForm =\n typeof stored?.form === 'string' ? stored.form : JSON.stringify(stored?.form)\n if (!stored || storedForm !== JSON.stringify(form)) persist()\n } catch (error) {\n configLogger.warn('failed to load config value', { belongTo }, error)\n data.value = cloneValue(defaultData)\n hydrated = true\n }\n })()\n\n watch(\n data,\n () => {\n if (!hydrated) return\n persist()\n },\n { deep: true, flush: 'sync' },\n )\n\n return Object.assign(data, { ready })\n}","import { logger } from '@delta-comic/logger'\nimport { SourcedValue } from '@delta-comic/model'\nimport { ref, toValue, watch, type MaybeRefOrGetter, type Ref } from 'vue'\n\nconst nativeStoreLogger = logger.scoped('db:native-store')\n\nexport interface Table {\n namespace: string\n key: string\n value: string\n}\n\nconst saveKey = new SourcedValue<[namespace: string, key: string]>()\n\nconst cloneDefault = <T extends object>(defaultValue: MaybeRefOrGetter<T>): T => {\n const value = toValue(defaultValue)\n if (typeof structuredClone === 'function') return structuredClone(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nconst legacyValue = (namespace: string, key: string) => {\n try {\n return globalThis.localStorage?.getItem(saveKey.toString([namespace, key])) ?? null\n } catch {\n return null\n }\n}\n\nconst parseValue = <T extends object>(value: unknown, defaultValue: MaybeRefOrGetter<T>): T => {\n if (value === null || value === '') return cloneDefault(defaultValue)\n if (typeof value !== 'string') {\n if (typeof structuredClone === 'function') return structuredClone(value as T)\n return JSON.parse(JSON.stringify(value)) as T\n }\n try {\n return JSON.parse(value) as T\n } catch (error) {\n nativeStoreLogger.warn('failed to parse native store value', error)\n return cloneDefault(defaultValue)\n }\n}\n\nconst getStoreValue = async (namespace: string, key: string) => {\n const { db } = await import('../index')\n return (\n (\n await db\n .selectFrom('nativeStore')\n .select('value')\n .where('namespace', '=', namespace)\n .where('key', '=', key)\n .executeTakeFirst()\n )?.value ?? null\n )\n}\n\nconst setStoreValue = async (namespace: string, key: string, value: string) => {\n const { db } = await import('../index')\n await db.replaceInto('nativeStore').values({ namespace, key, value }).execute()\n}\n\nexport const useNativeStore = <T extends object>(\n namespace: string,\n key: MaybeRefOrGetter<string>,\n defaultValue: MaybeRefOrGetter<T>,\n) => {\n const state = ref(cloneDefault(defaultValue)) as Ref<T>\n let version = 0\n let hydrated = false\n let saveTimer: ReturnType<typeof setTimeout> | undefined\n\n const persist = (resolvedKey: string, value: T) => {\n if (saveTimer) clearTimeout(saveTimer)\n const encoded = JSON.stringify(value)\n saveTimer = setTimeout(() => {\n void setStoreValue(namespace, resolvedKey, encoded).catch(error => {\n nativeStoreLogger.warn(\n 'failed to persist native store value',\n { key: resolvedKey, namespace },\n error,\n )\n })\n }, 100)\n }\n\n const load = async () => {\n const current = ++version\n const resolvedKey = toValue(key)\n hydrated = false\n try {\n const storeValue = await getStoreValue(namespace, resolvedKey)\n const storedValue = storeValue ?? legacyValue(namespace, resolvedKey)\n if (current !== version) return\n state.value = parseValue(storedValue, defaultValue)\n nativeStoreLogger.debug('native store value hydrated', {\n key: resolvedKey,\n namespace,\n source: storeValue === null ? 'legacy-or-default' : 'database',\n })\n hydrated = true\n if (storeValue === null) persist(resolvedKey, state.value)\n } catch (error) {\n nativeStoreLogger.warn(\n 'failed to load native store value',\n { key: resolvedKey, namespace },\n error,\n )\n if (current !== version) return\n state.value = cloneDefault(defaultValue)\n hydrated = true\n }\n }\n\n watch(\n () => toValue(key),\n () => void load(),\n { immediate: true },\n )\n watch(\n state,\n value => {\n if (!hydrated) return\n persist(toValue(key), value)\n },\n { deep: true },\n )\n\n return state\n}","import { logger } from '@delta-comic/logger'\nimport { isTauri } from '@tauri-apps/api/core'\nimport { CamelCasePlugin, type Dialect, Kysely } from 'kysely'\nimport { SerializePlugin } from 'kysely-plugin-serialize'\n\nimport type * as FavouriteDB from './favourite'\nexport * as PluginArchiveDB from './plugin'\nimport type * as HistoryDB from './history'\nexport * as FavouriteDB from './favourite'\nimport type * as ConfigDB from './config'\nimport type * as ItemStoreDB from './itemStore'\nimport type * as NativeStoreDB from './nativeStore'\nexport * as HistoryDB from './history'\nimport type * as PluginArchiveDB from './plugin'\nexport * as ItemStoreDB from './itemStore'\nimport type * as RecentDB from './recentView'\nexport * as SubscribeDB from './subscribe'\nimport type * as SubscribeDB from './subscribe'\nexport * as RecentDB from './recentView'\nexport * as ConfigDB from './config'\n\nexport interface DB {\n itemStore: ItemStoreDB.Table\n favouriteCard: FavouriteDB.CardTable\n favouriteItem: FavouriteDB.ItemTable\n history: HistoryDB.Table\n recentView: RecentDB.Table\n subscribe: SubscribeDB.Table\n plugin: PluginArchiveDB.Table\n nativeStore: NativeStoreDB.Table\n config: ConfigDB.Table\n}\n\nconst databaseLogger = logger.scoped('db:lifecycle')\n\ndatabaseLogger.info('database initialization started')\n\nexport const isTauriRuntime = isTauri\n\nconst createDialect = async (): Promise<Dialect> => {\n if (isTauriRuntime()) {\n const [{ default: Database }, { TauriSqliteDialect }] = await Promise.all([\n import('@tauri-apps/plugin-sql'),\n import('kysely-dialect-tauri'),\n ])\n const database = await Database.load('sqlite:app.db')\n databaseLogger.info('native sqlite dialect initialized')\n return new TauriSqliteDialect({ database })\n }\n\n const { createWebDialect } = await import('./web')\n databaseLogger.info('web sqlite dialect initialized')\n return createWebDialect()\n}\n\nexport const db = new Kysely<DB>({\n dialect: await createDialect(),\n plugins: [new CamelCasePlugin(), new SerializePlugin()],\n})\n\nexport * as DBUtils from './utils'\n\nexport type { InsertObject, Kysely } from 'kysely'\n\nexport * from './nativeStore'\nexport { useConfig } from './config'"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["QueryKey","useUpsert","useRemove","useQuery","useColadaQuery","QueryKey","useUpsert","QueryKey","ItemStoreDB.useUpsert","useColadaQuery","QueryKey","useUpsert","ItemStoreDB.useUpsert","useRemove","useQuery","useColadaQuery","QueryKey","useUpsert","useRemove","useQuery","useColadaQuery","ItemStoreDB.useUpsert","useQuery","useColadaQuery"],"sources":["../lib/utils.ts","../lib/plugin.ts","../lib/itemStore.ts","../lib/favourite.ts","../lib/history.ts","../lib/subscribe.ts","../lib/recentView.ts","../lib/config.ts","../lib/generated/schemas.ts","../lib/validation.ts","../lib/writeValidation.ts","../lib/nativeStore/index.ts","../lib/index.ts"],"sourcesContent":["import { logger } from '@delta-comic/logger'\nimport type { Kysely, SelectQueryBuilder } from 'kysely'\n\nimport type { DB } from '.'\n\nconst transactionLogger = logger.scoped('db:transaction')\n\nexport const withTransition = async <T>(\n handler: (trx: Kysely<DB>) => Promise<T>,\n trx?: Kysely<DB>,\n) => {\n if (trx) return await handler(trx)\n else {\n const { db } = await import('.')\n transactionLogger.trace('database transaction started')\n try {\n const result = await db\n .transaction()\n .setAccessMode('read write')\n .setIsolationLevel('read committed')\n .execute(handler)\n transactionLogger.trace('database transaction committed')\n return result\n } catch (error) {\n transactionLogger.error('database transaction failed', error)\n throw error\n }\n }\n}\n\nexport async function countDb<TB extends keyof DB, O extends object>(\n sql: SelectQueryBuilder<DB, TB, O>,\n) {\n const v = await sql.select(db => db.fn.countAll<number>().as('count')).executeTakeFirstOrThrow()\n return v.count\n}\n\nexport enum CommonQueryKey {\n common = 'db',\n}","import type { PluginManifest } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport type { PluginTable } from './generated/plugin.table'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type Meta = PluginManifest\n\nexport type Table = Omit<PluginTable, 'meta' | 'enable'> & {\n meta: Selectable<PluginTable>['meta']\n enable: boolean\n}\n\nexport type Archive = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:plugin:',\n}\n\nexport const removeByNames = async (keys: Archive['pluginName'][], trx: Kysely<DB>) => {\n if (keys.length === 0) return\n await trx.deleteFrom('plugin').where('plugin.pluginName', 'in', keys).execute()\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ archives, trx }: { archives: Archive[]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx\n .replaceInto('plugin')\n .values(archives.map(a => ({ ...a, meta: JSON.stringify(a.meta) })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Archive['pluginName'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await removeByNames(keys, trx)\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useToggleEnable = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Archive['pluginName'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n for (const key of keys) {\n const isEnable = await trx\n .selectFrom('plugin')\n .where('pluginName', '=', key)\n .select('enable')\n .executeTakeFirstOrThrow()\n return trx\n .updateTable('plugin')\n .where('pluginName', '=', key)\n .set({ enable: !isEnable.enable })\n .execute()\n }\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, toggle: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'plugin', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('plugin'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import {\n SourcedValue,\n Struct,\n UniContentPage,\n type UniItem,\n type UniItemRaw,\n} from '@delta-comic/model'\nimport { defineMutation, useMutation, useQueryCache } from '@pinia/colada'\nimport type { Kysely, Selectable } from 'kysely'\n\nimport type { ItemStoreTable } from './generated/item_store.table'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type Table = ItemStoreTable\nexport type StorableItem = UniItem | UniItemRaw\nexport type StoredItem = Selectable<Table>\nexport const itemKey = new SourcedValue('*')\n\nexport enum QueryKey {\n item = 'db:itemStore:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const k = itemKey.toString([\n UniContentPage.contentPages.key.toString(item.contentType),\n item.id,\n ])\n await trx\n .replaceInto('itemStore')\n .values({ item: Struct.toRaw(item), key: k })\n .execute()\n return k\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})","import {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\nimport type { MaybeRefOrGetter } from 'vue'\nimport { toValue } from 'vue'\n\nimport type { FavouriteCardTable } from './generated/favourite_card.table'\nimport type { FavouriteItemTable as GeneratedFavouriteItemTable } from './generated/favourite_item.table'\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type CardTable = FavouriteCardTable\n\nexport type Card = Selectable<CardTable>\n\nexport type ItemTable = GeneratedFavouriteItemTable\n\nexport type Item = Selectable<ItemTable>\n\nexport enum QueryKey {\n item = 'db:favouriteItem:',\n card = 'db:favouriteCard:',\n}\n\nexport const useUpsertItem = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({\n item,\n belongTos,\n trx,\n }: {\n item: ItemStoreDB.StorableItem\n belongTos: Item['belongTo'][]\n trx?: Kysely<DB>\n }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('favouriteItem')\n .values(belongTos.map(belongTo => ({ addTime: Date.now(), itemKey, belongTo })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useMoveItem = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({\n item,\n from,\n aims,\n trx,\n }: {\n item: ItemStoreDB.StorableItem\n from: Item['belongTo']\n aims: Item['belongTo'][]\n trx?: Kysely<DB>\n }) =>\n withTransition(async trx => {\n await trx\n .deleteFrom('favouriteItem')\n .where('itemKey', '=', item.id)\n .where('belongTo', '=', from)\n .execute()\n await trx\n .replaceInto('favouriteItem')\n .values(aims.map(to => ({ addTime: Date.now(), itemKey: item.id, belongTo: to })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, move: mutateAsync, key }\n})\n\nexport const useCreateCard = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [QueryKey.card, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ card, trx }: { card: Card; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.replaceInto('favouriteCard').values(card).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, createCard: mutateAsync, key }\n})\n\nexport const useQueryItem = <T>(\n query: (db: SelectQueryBuilder<DB, 'favouriteItem', {}>) => Promise<T>,\n otherKeys: MaybeRefOrGetter<EntryKey> = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('favouriteItem'))\n },\n key: () => [QueryKey.item, QueryKey.card, query, ...toValue(otherKeys)],\n staleTime: 15000,\n initialData,\n initialDataUpdatedAt: 0,\n })\n\nexport const useQueryCard = <T>(\n query: (db: SelectQueryBuilder<DB, 'favouriteCard', {}>) => Promise<T>,\n otherKeys: MaybeRefOrGetter<EntryKey> = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('favouriteCard'))\n },\n key: () => [QueryKey.card, query, ...toValue(otherKeys)],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { Struct } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport type { HistoryTable } from './generated/history.table'\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type Table = HistoryTable\n\nexport type Item = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:history:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: ItemStoreDB.StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('history')\n .values({ itemKey, timestamp: Date.now(), ep: Struct.toRaw(item.thisEp) })\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: ({ keys, trx }: { keys: Item['timestamp'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('history').where('history.timestamp', 'is', keys).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'history', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('history'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { SourcedValue, type SourcedKeyType } from '@delta-comic/model'\nimport {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport type { SubscribeTable } from './generated/subscribe.table'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport const key = new SourcedValue<[plugin: string, label: string]>()\nexport type Key_ = SourcedKeyType<typeof key>\nexport type Key = Exclude<Key_, string>\n\nexport type AuthorTable = Omit<SubscribeTable, 'itemKey' | 'author' | 'type'> & {\n author: Selectable<SubscribeTable>['author']\n itemKey: null\n type: 'author'\n}\nexport type AuthorItem = AuthorTable\n\nexport type EpTable = Omit<SubscribeTable, 'itemKey' | 'author' | 'type'> & {\n author: null\n itemKey: string // not f key\n type: 'ep'\n}\nexport type EpItem = EpTable\n\nexport type Table = SubscribeTable\nexport type Item = AuthorItem | EpItem\n\nexport enum QueryKey {\n item = 'db:subscribe:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ items, trx }: { items: Item[]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx\n .replaceInto('subscribe')\n .values(items.map(item => ({ ...item, author: JSON.stringify(item.author) })))\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ keys, trx }: { keys: Item['key'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('subscribe').where('subscribe.key', 'is', keys).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'subscribe', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('subscribe'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import {\n defineMutation,\n useMutation,\n useQueryCache,\n useQuery as useColadaQuery,\n type EntryKey,\n} from '@pinia/colada'\nimport type { Kysely, Selectable, SelectQueryBuilder } from 'kysely'\n\nimport type { RecentViewTable } from './generated/recent_view.table'\nimport * as ItemStoreDB from './itemStore'\nimport { CommonQueryKey, withTransition } from './utils'\n\nimport type { DB } from '.'\n\nexport type Table = RecentViewTable\nexport type Item = Selectable<Table>\n\nexport enum QueryKey {\n item = 'db:recentView:',\n}\n\nexport const useUpsert = defineMutation(() => {\n const queryCache = useQueryCache()\n const { key: iKey, upsert } = ItemStoreDB.useUpsert()\n const key = [CommonQueryKey.common, QueryKey.item, ...iKey]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ item, trx }: { item: ItemStoreDB.StorableItem; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n const itemKey = await upsert({ item, trx })\n await trx\n .replaceInto('recentView')\n .values({ isViewed: false, itemKey, timestamp: Date.now() })\n .execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, upsert: mutateAsync, key }\n})\n\nexport const useRemove = defineMutation(() => {\n const queryCache = useQueryCache()\n const key = [CommonQueryKey.common, QueryKey.item]\n const { mutateAsync, ...mutation } = useMutation({\n mutation: async ({ items, trx }: { items: Item['timestamp'][]; trx?: Kysely<DB> }) =>\n withTransition(async trx => {\n await trx.deleteFrom('recentView').where('recentView.timestamp', 'is', items).execute()\n }, trx),\n onSettled: () => {\n void queryCache.invalidateQueries({ key })\n },\n key,\n })\n return { ...mutation, remove: mutateAsync, key }\n})\n\nexport const useQuery = <T>(\n query: (db: SelectQueryBuilder<DB, 'recentView', {}>) => Promise<T>,\n otherKeys: readonly EntryKey[] = [],\n initialData?: () => T,\n) =>\n useColadaQuery({\n query: async () => {\n const { db } = await import('.')\n return await query(db.selectFrom('recentView'))\n },\n key: () => [CommonQueryKey.common, QueryKey.item, query, ...otherKeys],\n staleTime: 15000,\n refetchOnMount: 'always',\n initialData,\n initialDataUpdatedAt: 0,\n })","import { logger } from '@delta-comic/logger'\nimport type { FormResult, FormSingleConfigure } from '@delta-comic/model'\nimport { fromPairs } from 'es-toolkit/compat'\nimport { ref, watch, type Ref } from 'vue'\n\nimport type { ConfigTable } from './generated/config.table'\nconst configLogger = logger.scoped('db:config')\n\nexport type Table = ConfigTable\n\nexport type ConfigRef<T> = Ref<T> & { readonly ready: Promise<void> }\n\nexport type ConfigDescription = Record<\n string,\n Required<Pick<FormSingleConfigure, 'defaultValue'>> & FormSingleConfigure\n>\n\nconst cloneValue = <T>(value: T): T => {\n if (typeof structuredClone === 'function') return structuredClone(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nconst createDefaultData = <T extends ConfigDescription>(config: T): FormResult<T> =>\n fromPairs(\n Object.entries(config).map(([name, desc]) => [name, desc.defaultValue]),\n ) as FormResult<T>\n\nconst parseJson = <T>(value: unknown, fallback: T): T => {\n if (!value) return cloneValue(fallback)\n if (typeof value !== 'string') return cloneValue(value as T)\n try {\n return JSON.parse(value) as T\n } catch (error) {\n configLogger.warn('failed to parse config value', error)\n return cloneValue(fallback)\n }\n}\n\nconst upsertConfig = async (belongTo: string, form: ConfigDescription, data: unknown) => {\n const { db } = await import('.')\n await db\n .replaceInto('config')\n .values({ belongTo, form: JSON.stringify(form), data: JSON.stringify(data) })\n .execute()\n configLogger.debug('config persisted', { belongTo })\n}\n\nexport const useConfig = <T extends ConfigDescription>(\n belongTo: string,\n form: T,\n): ConfigRef<FormResult<T>> => {\n const defaultData = createDefaultData(form)\n const data = ref(cloneValue(defaultData)) as Ref<FormResult<T>>\n let hydrated = false\n let saveTimer: ReturnType<typeof setTimeout> | undefined\n\n const persist = () => {\n if (saveTimer) clearTimeout(saveTimer)\n saveTimer = setTimeout(() => {\n void upsertConfig(belongTo, form, data.value).catch(error => {\n configLogger.warn('failed to persist config value', { belongTo }, error)\n })\n }, 100)\n }\n\n const ready = (async () => {\n try {\n const { db } = await import('.')\n const stored = await db\n .selectFrom('config')\n .select(['form', 'data'])\n .where('belongTo', '=', belongTo)\n .executeTakeFirst()\n data.value = parseJson(stored?.data, defaultData)\n configLogger.debug('config hydrated', { belongTo, found: Boolean(stored) })\n hydrated = true\n const storedForm =\n typeof stored?.form === 'string' ? stored.form : JSON.stringify(stored?.form)\n if (!stored || storedForm !== JSON.stringify(form)) persist()\n } catch (error) {\n configLogger.warn('failed to load config value', { belongTo }, error)\n data.value = cloneValue(defaultData)\n hydrated = true\n }\n })()\n\n watch(\n data,\n () => {\n if (!hydrated) return\n persist()\n },\n { deep: true, flush: 'sync' },\n )\n\n return Object.assign(data, { ready })\n}","import type { TSchema } from 'typebox'\n\n/** Runtime SQLite row schema for item_store. */\nexport const itemStoreRowSchema = {\n type: 'object',\n properties: { key: { type: 'string' }, item: { type: 'string' } },\n required: ['key', 'item'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for favourite_card. */\nexport const favouriteCardRowSchema = {\n type: 'object',\n properties: {\n create_at: { type: 'integer' },\n title: { type: 'string' },\n private: { type: 'integer' },\n description: { type: 'string' },\n },\n required: ['create_at', 'title', 'private', 'description'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for favourite_item. */\nexport const favouriteItemRowSchema = {\n type: 'object',\n properties: {\n add_time: { type: 'integer' },\n belong_to: { type: 'integer' },\n item_key: { type: 'string' },\n },\n required: ['add_time', 'belong_to', 'item_key'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for history. */\nexport const historyRowSchema = {\n type: 'object',\n properties: {\n ep: { type: 'string' },\n timestamp: { type: 'integer' },\n item_key: { type: 'string' },\n },\n required: ['ep', 'timestamp', 'item_key'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for recent_view. */\nexport const recentViewRowSchema = {\n type: 'object',\n properties: {\n timestamp: { type: 'integer' },\n item_key: { type: 'string' },\n is_viewed: { type: 'integer' },\n },\n required: ['timestamp', 'item_key', 'is_viewed'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for subscribe. */\nexport const subscribeRowSchema = {\n type: 'object',\n properties: {\n item_key: { anyOf: [{ type: 'string' }, { type: 'null' }] },\n author: { anyOf: [{ type: 'string' }, { type: 'null' }] },\n type: { type: 'string' },\n key: { type: 'string' },\n plugin: { type: 'string' },\n },\n required: ['item_key', 'author', 'type', 'key', 'plugin'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for plugin. */\nexport const pluginRowSchema = {\n type: 'object',\n properties: {\n installer_name: { type: 'string' },\n loader_name: { type: 'string' },\n plugin_name: { type: 'string' },\n meta: { type: 'string' },\n enable: { type: 'integer' },\n install_input: { type: 'string' },\n display_name: { anyOf: [{ type: 'string' }, { type: 'null' }] },\n },\n required: [\n 'installer_name',\n 'loader_name',\n 'plugin_name',\n 'meta',\n 'enable',\n 'install_input',\n 'display_name',\n ],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for native_store. */\nexport const nativeStoreRowSchema = {\n type: 'object',\n properties: { namespace: { type: 'string' }, key: { type: 'string' }, value: { type: 'string' } },\n required: ['namespace', 'key', 'value'],\n additionalProperties: false,\n} as const\n\n/** Runtime SQLite row schema for config. */\nexport const configRowSchema = {\n type: 'object',\n properties: { belong_to: { type: 'string' }, form: { type: 'string' }, data: { type: 'string' } },\n required: ['belong_to', 'form', 'data'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for item_store (camelCase keys). */\nexport const itemStoreCamelRowSchema = {\n type: 'object',\n properties: {\n key: { type: 'string' },\n item: { anyOf: [{ type: 'object' }, { type: 'string' }] },\n },\n required: ['key', 'item'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for favourite_card (camelCase keys). */\nexport const favouriteCardCamelRowSchema = {\n type: 'object',\n properties: {\n createAt: { type: 'integer' },\n title: { type: 'string' },\n private: { anyOf: [{ type: 'boolean' }, { const: 0 }, { const: 1 }] },\n description: { type: 'string' },\n },\n required: ['createAt', 'title', 'private', 'description'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for favourite_item (camelCase keys). */\nexport const favouriteItemCamelRowSchema = {\n type: 'object',\n properties: {\n addTime: { type: 'integer' },\n belongTo: { type: 'integer' },\n itemKey: { type: 'string' },\n },\n required: ['addTime', 'belongTo', 'itemKey'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for history (camelCase keys). */\nexport const historyCamelRowSchema = {\n type: 'object',\n properties: {\n ep: { anyOf: [{ type: 'object' }, { type: 'string' }] },\n timestamp: { type: 'integer' },\n itemKey: { type: 'string' },\n },\n required: ['ep', 'timestamp', 'itemKey'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for recent_view (camelCase keys). */\nexport const recentViewCamelRowSchema = {\n type: 'object',\n properties: {\n timestamp: { type: 'integer' },\n itemKey: { type: 'string' },\n isViewed: { anyOf: [{ type: 'boolean' }, { const: 0 }, { const: 1 }] },\n },\n required: ['timestamp', 'itemKey', 'isViewed'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for subscribe (camelCase keys). */\nexport const subscribeCamelRowSchema = {\n type: 'object',\n properties: {\n itemKey: { anyOf: [{ type: 'string' }, { type: 'null' }] },\n author: { anyOf: [{ type: 'object' }, { type: 'string' }, { type: 'null' }] },\n type: { type: 'string' },\n key: { type: 'string' },\n plugin: { type: 'string' },\n },\n required: ['itemKey', 'author', 'type', 'key', 'plugin'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for plugin (camelCase keys). */\nexport const pluginCamelRowSchema = {\n type: 'object',\n properties: {\n installerName: { type: 'string' },\n loaderName: { type: 'string' },\n pluginName: { type: 'string' },\n meta: { anyOf: [{ type: 'object' }, { type: 'string' }] },\n enable: { anyOf: [{ type: 'boolean' }, { const: 0 }, { const: 1 }] },\n installInput: { type: 'string' },\n displayName: { anyOf: [{ type: 'string' }, { type: 'null' }] },\n },\n required: [\n 'installerName',\n 'loaderName',\n 'pluginName',\n 'meta',\n 'enable',\n 'installInput',\n 'displayName',\n ],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for native_store (camelCase keys). */\nexport const nativeStoreCamelRowSchema = {\n type: 'object',\n properties: { namespace: { type: 'string' }, key: { type: 'string' }, value: { type: 'string' } },\n required: ['namespace', 'key', 'value'],\n additionalProperties: false,\n} as const\n\n/** Runtime TS-level row schema for config (camelCase keys). */\nexport const configCamelRowSchema = {\n type: 'object',\n properties: { belongTo: { type: 'string' }, form: { type: 'string' }, data: { type: 'string' } },\n required: ['belongTo', 'form', 'data'],\n additionalProperties: false,\n} as const\n\nexport const clientRowSchemas = {\n item_store: itemStoreRowSchema,\n favourite_card: favouriteCardRowSchema,\n favourite_item: favouriteItemRowSchema,\n history: historyRowSchema,\n recent_view: recentViewRowSchema,\n subscribe: subscribeRowSchema,\n plugin: pluginRowSchema,\n native_store: nativeStoreRowSchema,\n config: configRowSchema,\n} satisfies Record<string, TSchema>\nexport const clientCamelRowSchemas = {\n itemStore: itemStoreCamelRowSchema,\n favouriteCard: favouriteCardCamelRowSchema,\n favouriteItem: favouriteItemCamelRowSchema,\n history: historyCamelRowSchema,\n recentView: recentViewCamelRowSchema,\n subscribe: subscribeCamelRowSchema,\n plugin: pluginCamelRowSchema,\n nativeStore: nativeStoreCamelRowSchema,\n config: configCamelRowSchema,\n} satisfies Record<string, TSchema>","import { logger } from '@delta-comic/logger'\nimport type { TSchema } from 'typebox'\nimport { Compile } from 'typebox/compile'\nimport { Value } from 'typebox/value'\n\nimport { clientCamelRowSchemas } from './generated/schemas'\n\nconst validationLogger = logger.scoped('db:validation')\n\nexport type ClientTableName = keyof typeof clientCamelRowSchemas\n\nconst validators = new WeakMap<object, ReturnType<typeof Compile>>()\n\nconst validatorFor = (schema: TSchema): ReturnType<typeof Compile> => {\n const cached = validators.get(schema)\n if (cached) return cached\n const validator = Compile(schema)\n validators.set(schema, validator)\n return validator\n}\n\nconst validationDetails = (schema: TSchema, value: unknown) =>\n [...Value.Errors(schema, value)]\n .slice(0, 5)\n .map(error => ({ instancePath: error.instancePath, message: error.message }))\n\nexport const tableSchema = <K extends ClientTableName>(table: K) => clientCamelRowSchemas[table]\n\n/** Validates a row before writing; throws to block invalid data from persisting. */\nexport const assertWrite = <T>(schema: TSchema, table: string, value: T): T => {\n if (!validatorFor(schema).Check(value)) {\n validationLogger.error('database write validation failed', {\n table,\n errors: validationDetails(schema, value),\n })\n throw new Error(\n `database write validation failed for ${table}: ${JSON.stringify(\n validationDetails(schema, value),\n )}`,\n )\n }\n return value\n}\n\nexport const assertWriteRow = <K extends ClientTableName, T>(table: K, value: T): T =>\n assertWrite(tableSchema(table), table, value)\n\n/** Validates a row on read; failures are non-intrusive: logged and the value returned as-is. */\nexport const validateRead = <T>(schema: TSchema, table: string, value: T): T => {\n if (!validatorFor(schema).Check(value)) {\n validationLogger.warn('database read validation failed', {\n table,\n errors: validationDetails(schema, value),\n })\n }\n return value\n}\n\nexport const validateReadRow = <K extends ClientTableName, T>(table: K, value: T): T =>\n validateRead(tableSchema(table), table, value)\n\n/** Filters invalid rows on read; failures are non-intrusive: logged and the row dropped. */\nexport const filterValidRows = <T>(schema: TSchema, table: string, rows: readonly T[]): T[] => {\n const valid: T[] = []\n for (const row of rows) {\n if (validatorFor(schema).Check(row)) {\n valid.push(row)\n continue\n }\n validationLogger.warn('database read validation failed, row dropped', {\n table,\n errors: validationDetails(schema, row),\n })\n }\n return valid\n}\n\nexport const filterValidRowsFor = <K extends ClientTableName, T>(\n table: K,\n rows: readonly T[],\n): T[] => filterValidRows(tableSchema(table), table, rows)","import type {\n ColumnNode,\n InsertQueryNode,\n KyselyPlugin,\n OperationNode,\n PluginTransformQueryArgs,\n PluginTransformResultArgs,\n QueryResult,\n RootOperationNode,\n TableNode,\n UpdateQueryNode,\n UnknownRow,\n ValueNode,\n ValuesNode,\n} from 'kysely'\nimport type { TSchema } from 'typebox'\n\nimport { clientCamelRowSchemas } from './generated/schemas'\nimport { assertWrite } from './validation'\n\nconst isTableNode = (node: OperationNode | undefined): node is TableNode =>\n node?.kind === 'TableNode'\n\nconst isValuesNode = (node: OperationNode | undefined): node is ValuesNode =>\n node?.kind === 'ValuesNode'\n\nconst isValueNode = (node: OperationNode): node is ValueNode => node.kind === 'ValueNode'\n\nconst isColumnNode = (node: OperationNode): node is ColumnNode => node.kind === 'ColumnNode'\n\nconst tableNameOf = (node: OperationNode | undefined): string | null => {\n if (!isTableNode(node)) return null\n return node.table.identifier.name\n}\n\nconst rowObjectsOf = (node: InsertQueryNode): readonly unknown[] | null => {\n const columns = node.columns\n if (!columns || columns.length === 0) return null\n const names = columns.map(column => column.column.name)\n const values = node.values\n if (!isValuesNode(values)) return null\n const rows: unknown[] = []\n for (const list of values.values) {\n let entries: unknown[]\n if (list.kind === 'PrimitiveValueListNode') {\n entries = [...list.values]\n } else if (list.kind === 'ValueListNode') {\n const wrapped: unknown[] = []\n for (const entry of list.values) {\n if (!isValueNode(entry)) return null\n wrapped.push(entry.value)\n }\n entries = wrapped\n } else {\n return null\n }\n if (entries.length !== names.length) return null\n rows.push(Object.fromEntries(names.map((name, index) => [name, entries[index]])))\n }\n return rows\n}\n\nconst updatePatchOf = (node: UpdateQueryNode): Record<string, unknown> | null => {\n if (!node.updates || node.updates.length === 0) return null\n const patch: Record<string, unknown> = {}\n for (const update of node.updates) {\n if (!isColumnNode(update.column)) return null\n const value = update.value\n if (!isValueNode(value)) return null\n patch[update.column.column.name] = value.value\n }\n return patch\n}\n\nconst partialSchemas = new WeakMap<object, TSchema>()\n\nconst partialOf = (schema: TSchema): TSchema => {\n const cached = partialSchemas.get(schema)\n if (cached) return cached\n const partial = { ...schema, required: undefined }\n partialSchemas.set(schema, partial)\n return partial\n}\n\nexport const validateWriteNode = (node: RootOperationNode): void => {\n let tableName: string | null = null\n let rows: readonly unknown[] | null = null\n let patch: Record<string, unknown> | null = null\n if (node.kind === 'InsertQueryNode') {\n tableName = tableNameOf(node.into)\n rows = rowObjectsOf(node)\n } else if (node.kind === 'UpdateQueryNode') {\n tableName = tableNameOf(node.table)\n patch = updatePatchOf(node)\n } else {\n return\n }\n if (tableName === null) return\n const schema = (clientCamelRowSchemas as Record<string, TSchema>)[tableName]\n if (!schema) return\n if (rows !== null) {\n if (rows.length === 0) return\n for (const row of rows) assertWrite(schema, tableName, row)\n return\n }\n if (patch !== null) {\n assertWrite(partialOf(schema), tableName, patch)\n }\n}\n\n/**\n * Centralized write gate: validates every insert/replace/update against the\n * generated camelCase row schema before it reaches the dialect. Registered\n * before CamelCasePlugin, so it observes camelCase identifiers and raw values.\n */\nexport class WriteValidationPlugin implements KyselyPlugin {\n transformQuery({ node }: PluginTransformQueryArgs): RootOperationNode {\n validateWriteNode(node)\n return node\n }\n\n async transformResult({ result }: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>> {\n return result\n }\n}","import { logger } from '@delta-comic/logger'\nimport { SourcedValue } from '@delta-comic/model'\nimport { ref, toValue, watch, type MaybeRefOrGetter, type Ref } from 'vue'\n\nimport type { NativeStoreTable } from '../generated/native_store.table'\n\nconst nativeStoreLogger = logger.scoped('db:native-store')\n\nexport type Table = NativeStoreTable\n\nconst saveKey = new SourcedValue<[namespace: string, key: string]>()\n\nconst cloneDefault = <T extends object>(defaultValue: MaybeRefOrGetter<T>): T => {\n const value = toValue(defaultValue)\n if (typeof structuredClone === 'function') return structuredClone(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nconst legacyValue = (namespace: string, key: string) => {\n try {\n return globalThis.localStorage?.getItem(saveKey.toString([namespace, key])) ?? null\n } catch {\n return null\n }\n}\n\nconst parseValue = <T extends object>(value: unknown, defaultValue: MaybeRefOrGetter<T>): T => {\n if (value === null || value === '') return cloneDefault(defaultValue)\n if (typeof value !== 'string') {\n if (typeof structuredClone === 'function') return structuredClone(value as T)\n return JSON.parse(JSON.stringify(value)) as T\n }\n try {\n return JSON.parse(value) as T\n } catch (error) {\n nativeStoreLogger.warn('failed to parse native store value', error)\n return cloneDefault(defaultValue)\n }\n}\n\nconst getStoreValue = async (namespace: string, key: string) => {\n const { db } = await import('../index')\n return (\n (\n await db\n .selectFrom('nativeStore')\n .select('value')\n .where('namespace', '=', namespace)\n .where('key', '=', key)\n .executeTakeFirst()\n )?.value ?? null\n )\n}\n\nconst setStoreValue = async (namespace: string, key: string, value: string) => {\n const { db } = await import('../index')\n await db.replaceInto('nativeStore').values({ namespace, key, value }).execute()\n}\n\nexport const useNativeStore = <T extends object>(\n namespace: string,\n key: MaybeRefOrGetter<string>,\n defaultValue: MaybeRefOrGetter<T>,\n) => {\n const state = ref(cloneDefault(defaultValue)) as Ref<T>\n let version = 0\n let hydrated = false\n let saveTimer: ReturnType<typeof setTimeout> | undefined\n\n const persist = (resolvedKey: string, value: T) => {\n if (saveTimer) clearTimeout(saveTimer)\n const encoded = JSON.stringify(value)\n saveTimer = setTimeout(() => {\n void setStoreValue(namespace, resolvedKey, encoded).catch(error => {\n nativeStoreLogger.warn(\n 'failed to persist native store value',\n { key: resolvedKey, namespace },\n error,\n )\n })\n }, 100)\n }\n\n const load = async () => {\n const current = ++version\n const resolvedKey = toValue(key)\n hydrated = false\n try {\n const storeValue = await getStoreValue(namespace, resolvedKey)\n const storedValue = storeValue ?? legacyValue(namespace, resolvedKey)\n if (current !== version) return\n state.value = parseValue(storedValue, defaultValue)\n nativeStoreLogger.debug('native store value hydrated', {\n key: resolvedKey,\n namespace,\n source: storeValue === null ? 'legacy-or-default' : 'database',\n })\n hydrated = true\n if (storeValue === null) persist(resolvedKey, state.value)\n } catch (error) {\n nativeStoreLogger.warn(\n 'failed to load native store value',\n { key: resolvedKey, namespace },\n error,\n )\n if (current !== version) return\n state.value = cloneDefault(defaultValue)\n hydrated = true\n }\n }\n\n watch(\n () => toValue(key),\n () => void load(),\n { immediate: true },\n )\n watch(\n state,\n value => {\n if (!hydrated) return\n persist(toValue(key), value)\n },\n { deep: true },\n )\n\n return state\n}","import { logger } from '@delta-comic/logger'\nimport { isTauri } from '@tauri-apps/api/core'\nimport { CamelCasePlugin, type Dialect, Kysely } from 'kysely'\nimport { SerializePlugin } from 'kysely-plugin-serialize'\n\nimport type * as FavouriteDB from './favourite'\nexport * as PluginArchiveDB from './plugin'\nimport type * as HistoryDB from './history'\nexport * as FavouriteDB from './favourite'\nimport type * as ConfigDB from './config'\nimport type { PluginTable } from './generated/plugin.table'\nimport type * as ItemStoreDB from './itemStore'\nimport type * as NativeStoreDB from './nativeStore'\nexport type { PluginTable } from './generated/plugin.table'\nexport * as HistoryDB from './history'\nexport * as ItemStoreDB from './itemStore'\nimport type * as RecentDB from './recentView'\nexport * as SubscribeDB from './subscribe'\nimport type * as SubscribeDB from './subscribe'\nexport * as RecentDB from './recentView'\nexport * as ConfigDB from './config'\nimport { WriteValidationPlugin } from './writeValidation'\nexport { WriteValidationPlugin } from './writeValidation'\nexport * from './validation'\n\nexport interface DB {\n itemStore: ItemStoreDB.Table\n favouriteCard: FavouriteDB.CardTable\n favouriteItem: FavouriteDB.ItemTable\n history: HistoryDB.Table\n recentView: RecentDB.Table\n subscribe: SubscribeDB.Table\n plugin: PluginTable\n nativeStore: NativeStoreDB.Table\n config: ConfigDB.Table\n}\n\nconst databaseLogger = logger.scoped('db:lifecycle')\n\ndatabaseLogger.info('database initialization started')\n\nexport const isTauriRuntime = isTauri\n\nconst createDialect = async (): Promise<Dialect> => {\n if (isTauriRuntime()) {\n const [{ default: Database }, { TauriSqliteDialect }] = await Promise.all([\n import('@tauri-apps/plugin-sql'),\n import('kysely-dialect-tauri'),\n ])\n const database = await Database.load('sqlite:app.db')\n databaseLogger.info('native sqlite dialect initialized')\n return new TauriSqliteDialect({ database })\n }\n\n const { createWebDialect } = await import('./web')\n databaseLogger.info('web sqlite dialect initialized')\n return createWebDialect()\n}\n\nexport const db = new Kysely<DB>({\n dialect: await createDialect(),\n plugins: [new WriteValidationPlugin(), new CamelCasePlugin(), new SerializePlugin()],\n})\n\nexport * as DBUtils from './utils'\n\nexport type { InsertObject, Kysely } from 'kysely'\n\nexport * from './nativeStore'\nexport { useConfig } from './config'"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delta-comic/db",
3
- "version": "3.0.0-next.11",
3
+ "version": "3.0.0-next.12",
4
4
  "description": "空阙虱楼",
5
5
  "homepage": "https://github.com/delta-comic/delta-comic",
6
6
  "license": "AGPL-3.0-only",
@@ -29,7 +29,7 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@delta-comic/logger": "3.0.0-next.11",
32
+ "@delta-comic/logger": "3.0.0-next.12",
33
33
  "@subframe7536/sqlite-wasm": "^1.3.1",
34
34
  "@tauri-apps/api": "^2.11.1",
35
35
  "@tauri-apps/plugin-sql": "^2.4.0",
@@ -38,7 +38,8 @@
38
38
  "kysely-dialect-tauri": "^2.0.1",
39
39
  "kysely-plugin-serialize": "^0.8.2",
40
40
  "kysely-wasqlite-worker": "^2.0.1",
41
- "mitt": "^3.0.1"
41
+ "mitt": "^3.0.1",
42
+ "typebox": "^1.3.14"
42
43
  },
43
44
  "devDependencies": {
44
45
  "typescript": "npm:typescript-native-bridge@6.0.3-bridge.8.tsgo.7.0.2",
@@ -46,7 +47,7 @@
46
47
  "vite-plus": "^0.2.9"
47
48
  },
48
49
  "peerDependencies": {
49
- "@delta-comic/model": "3.0.0-next.11",
50
+ "@delta-comic/model": "3.0.0-next.12",
50
51
  "@pinia/colada": "^1.4.2",
51
52
  "vue": "^3.6.0-rc.4"
52
53
  }