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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs 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.13",
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.13",
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.13",
50
51
  "@pinia/colada": "^1.4.2",
51
52
  "vue": "^3.6.0-rc.4"
52
53
  }