From 94bb3afef858e134ab1c3a9cd5ef8486fdf3175b Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Mon, 26 May 2025 15:56:23 +0800 Subject: [PATCH] refactor(mobile): move service to database package (#3817) --- apps/mobile/src/initialize/hydrate.ts | 2 +- apps/mobile/src/services/feed.ts | 30 ------------------- apps/mobile/src/services/index.ts | 28 ----------------- apps/mobile/src/store/collection/store.ts | 10 +++++-- apps/mobile/src/store/entry/store.ts | 15 ++++++++-- apps/mobile/src/store/feed/store.ts | 10 +++++-- apps/mobile/src/store/image/store.ts | 11 +++++-- apps/mobile/src/store/inbox/store.ts | 10 +++++-- apps/mobile/src/store/index.ts | 29 ++++++++++++++++++ .../src/{services => store}/internal/base.ts | 4 --- apps/mobile/src/store/list/store.ts | 15 ++++++++-- apps/mobile/src/store/subscription/store.ts | 12 ++++++-- apps/mobile/src/store/summary/store.ts | 2 +- apps/mobile/src/store/translation/store.ts | 10 +++++-- apps/mobile/src/store/unread/store.ts | 11 +++++-- apps/mobile/src/store/user/store.ts | 9 ++++-- .../database}/src/services/collection.ts | 16 +++++----- .../internal/database}/src/services/entry.ts | 28 ++++++++--------- .../internal/database/src/services/feed.ts | 27 +++++++++++++++++ .../internal/database}/src/services/image.ts | 20 ++++++------- .../internal/database}/src/services/inbox.ts | 16 ++++------ .../database/src/services/internal/base.ts | 3 ++ .../database}/src/services/internal/utils.ts | 0 .../internal/database}/src/services/list.ts | 25 +++++++--------- .../database}/src/services/subscription.ts | 29 +++++++----------- .../database}/src/services/summary.ts | 7 +++-- .../database}/src/services/translation.ts | 17 +++++------ .../internal/database}/src/services/unread.ts | 23 +++++++------- .../internal/database}/src/services/user.ts | 19 +++++------- 29 files changed, 236 insertions(+), 202 deletions(-) delete mode 100644 apps/mobile/src/services/feed.ts delete mode 100644 apps/mobile/src/services/index.ts create mode 100644 apps/mobile/src/store/index.ts rename apps/mobile/src/{services => store}/internal/base.ts (50%) rename {apps/mobile => packages/internal/database}/src/services/collection.ts (61%) rename {apps/mobile => packages/internal/database}/src/services/entry.ts (64%) create mode 100644 packages/internal/database/src/services/feed.ts rename {apps/mobile => packages/internal/database}/src/services/image.ts (50%) rename {apps/mobile => packages/internal/database}/src/services/inbox.ts (54%) create mode 100644 packages/internal/database/src/services/internal/base.ts rename {apps/mobile => packages/internal/database}/src/services/internal/utils.ts (100%) rename {apps/mobile => packages/internal/database}/src/services/list.ts (51%) rename {apps/mobile => packages/internal/database}/src/services/subscription.ts (77%) rename {apps/mobile => packages/internal/database}/src/services/summary.ts (84%) rename {apps/mobile => packages/internal/database}/src/services/translation.ts (64%) rename {apps/mobile => packages/internal/database}/src/services/unread.ts (55%) rename {apps/mobile => packages/internal/database}/src/services/user.ts (53%) diff --git a/apps/mobile/src/initialize/hydrate.ts b/apps/mobile/src/initialize/hydrate.ts index ae154f633..a0d86f2ac 100644 --- a/apps/mobile/src/initialize/hydrate.ts +++ b/apps/mobile/src/initialize/hydrate.ts @@ -2,7 +2,7 @@ import { persistQueryClient } from "@tanstack/react-query-persist-client" import { kvStoragePersister, queryClient } from "../lib/query-client" -export { hydrateDatabaseToStore } from "../services" +export { hydrateDatabaseToStore } from "../store" export const hydrateSettings = () => {} export const hydrateQueryClient = () => { persistQueryClient({ diff --git a/apps/mobile/src/services/feed.ts b/apps/mobile/src/services/feed.ts deleted file mode 100644 index 5abe91302..000000000 --- a/apps/mobile/src/services/feed.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { db } from "@follow/database/src/db" -import { feedsTable } from "@follow/database/src/schemas" -import type { FeedSchema } from "@follow/database/src/schemas/types" - -import { feedActions } from "../store/feed/store" -import type { Hydratable, Resetable } from "./internal/base" -import { conflictUpdateAllExcept } from "./internal/utils" - -class FeedServiceStatic implements Hydratable, Resetable { - async reset() { - await db.delete(feedsTable).execute() - } - async upsertMany(feed: FeedSchema[]) { - if (feed.length === 0) return - await db - .insert(feedsTable) - .values(feed) - .onConflictDoUpdate({ - target: [feedsTable.id], - set: conflictUpdateAllExcept(feedsTable, ["id"]), - }) - } - - async hydrate() { - const feeds = await db.query.feedsTable.findMany() - feedActions.upsertManyInSession(feeds) - } -} - -export const FeedService = new FeedServiceStatic() diff --git a/apps/mobile/src/services/index.ts b/apps/mobile/src/services/index.ts deleted file mode 100644 index 758e0dfc6..000000000 --- a/apps/mobile/src/services/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { CollectionService } from "./collection" -import { EntryService } from "./entry" -import { FeedService } from "./feed" -import { ImagesService } from "./image" -import { InboxService } from "./inbox" -import type { Hydratable } from "./internal/base" -import { ListService } from "./list" -import { SubscriptionService } from "./subscription" -import { TranslationService } from "./translation" -import { UnreadService } from "./unread" -import { UserService } from "./user" - -const hydrates: Hydratable[] = [ - FeedService, - SubscriptionService, - InboxService, - ListService, - UnreadService, - UserService, - EntryService, - CollectionService, - ImagesService, - TranslationService, -] - -export const hydrateDatabaseToStore = async () => { - await Promise.all(hydrates.map((h) => h.hydrate())) -} diff --git a/apps/mobile/src/store/collection/store.ts b/apps/mobile/src/store/collection/store.ts index 370e78776..6fadd569f 100644 --- a/apps/mobile/src/store/collection/store.ts +++ b/apps/mobile/src/store/collection/store.ts @@ -1,9 +1,10 @@ import type { FeedViewType } from "@follow/constants" import type { CollectionSchema } from "@follow/database/src/schemas/types" +import { CollectionService } from "@follow/database/src/services/collection" import { apiClient } from "@/src/lib/api-fetch" -import { CollectionService } from "@/src/services/collection" +import type { Hydratable } from "../internal/base" import { createTransaction, createZustandStore } from "../internal/helper" interface CollectionState { @@ -81,7 +82,12 @@ class CollectionSyncService { } } -class CollectionActions { +class CollectionActions implements Hydratable { + async hydrate() { + const collections = await CollectionService.getCollectionAll() + collectionActions.upsertManyInSession(collections) + } + async upsertManyInSession(collections: CollectionSchema[]) { const state = useCollectionStore.getState() const nextCollections: CollectionState["collections"] = { diff --git a/apps/mobile/src/store/entry/store.ts b/apps/mobile/src/store/entry/store.ts index 70ae5368b..3203719d9 100644 --- a/apps/mobile/src/store/entry/store.ts +++ b/apps/mobile/src/store/entry/store.ts @@ -1,16 +1,18 @@ import { FeedViewType } from "@follow/constants" +import { EntryService } from "@follow/database/src/services/entry" import { debounce } from "es-toolkit/compat" import { fetch as expoFetch } from "expo/fetch" import { getGeneralSettings } from "@/src/atoms/settings/general" import { apiClient } from "@/src/lib/api-fetch" import { getCookie } from "@/src/lib/auth" +import { dbStoreMorph } from "@/src/morph/db-store" import { honoMorph } from "@/src/morph/hono" import { storeDbMorph } from "@/src/morph/store-db" -import { EntryService } from "@/src/services/entry" import { collectionActions } from "../collection/store" import { feedActions } from "../feed/store" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import { getSubscription } from "../subscription/getter" import { getDefaultCategory } from "../subscription/utils" @@ -56,7 +58,16 @@ export const useEntryStore = createZustandStore("entry")(() => defau const immerSet = createImmerSetter(useEntryStore) -class EntryActions { +class EntryActions implements Hydratable { + async hydrate() { + const entries = await EntryService.getEntryAll() + const { unreadOnly } = getGeneralSettings() + entryActions.upsertManyInSession( + entries.map((e) => dbStoreMorph.toEntryModel(e)), + { unreadOnly }, + ) + } + private addEntryIdToView({ draft, feedId, diff --git a/apps/mobile/src/store/feed/store.ts b/apps/mobile/src/store/feed/store.ts index 2eacdea5a..76f4bf801 100644 --- a/apps/mobile/src/store/feed/store.ts +++ b/apps/mobile/src/store/feed/store.ts @@ -1,8 +1,9 @@ import type { FeedSchema } from "@follow/database/src/schemas/types" +import { FeedService } from "@follow/database/src/services/feed" import { apiClient } from "@/src/lib/api-fetch" -import { FeedService } from "@/src/services/feed" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import type { FeedModel } from "./types" @@ -18,7 +19,12 @@ const set = useFeedStore.setState const immerSet = createImmerSetter(useFeedStore) // const get = useFeedStore.getState // const distanceTime = 1000 * 60 * 60 * 9 -class FeedActions { +class FeedActions implements Hydratable { + async hydrate() { + const feeds = await FeedService.getFeedAll() + feedActions.upsertManyInSession(feeds) + } + clear() { set({ feeds: {} }) } diff --git a/apps/mobile/src/store/image/store.ts b/apps/mobile/src/store/image/store.ts index d81b541f8..6707222ba 100644 --- a/apps/mobile/src/store/image/store.ts +++ b/apps/mobile/src/store/image/store.ts @@ -1,8 +1,8 @@ import type { ImageSchema } from "@follow/database/src/schemas/types" +import { ImagesService } from "@follow/database/src/services/image" import ImageColors from "react-native-image-colors" -import { ImagesService } from "@/src/services/image" - +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import { getImageInfo } from "./getters" @@ -33,7 +33,12 @@ class ImageSyncService { } } -class ImageActions { +class ImageActions implements Hydratable { + async hydrate() { + const images = await ImagesService.getImageAll() + imageActions.upsertManyInSession(images) + } + upsertManyInSession(images: ImageModel[]) { immerSet((state) => { for (const image of images) { diff --git a/apps/mobile/src/store/inbox/store.ts b/apps/mobile/src/store/inbox/store.ts index b0035be20..87803ea2f 100644 --- a/apps/mobile/src/store/inbox/store.ts +++ b/apps/mobile/src/store/inbox/store.ts @@ -1,7 +1,7 @@ import type { InboxSchema } from "@follow/database/src/schemas/types" +import { InboxService } from "@follow/database/src/services/inbox" -import { InboxService } from "@/src/services/inbox" - +import type { Hydratable } from "../internal/base" import { createTransaction, createZustandStore } from "../internal/helper" interface InboxState { @@ -16,7 +16,11 @@ export const useInboxStore = createZustandStore("inbox")(() => defau // const get = useInboxStore.getState const set = useInboxStore.setState -class InboxActions { +class InboxActions implements Hydratable { + async hydrate() { + const inboxes = await InboxService.getInbox() + inboxActions.upsertManyInSession(inboxes) + } async upsertManyInSession(inboxes: InboxSchema[]) { const state = useInboxStore.getState() const nextInboxes: InboxState["inboxes"] = { diff --git a/apps/mobile/src/store/index.ts b/apps/mobile/src/store/index.ts new file mode 100644 index 000000000..9a2d92220 --- /dev/null +++ b/apps/mobile/src/store/index.ts @@ -0,0 +1,29 @@ +import { collectionActions } from "./collection/store" +import { entryActions } from "./entry/store" +import { feedActions } from "./feed/store" +import { imageActions } from "./image/store" +import { inboxActions } from "./inbox/store" +import type { Hydratable } from "./internal/base" +import { listActions } from "./list/store" +import { subscriptionActions } from "./subscription/store" +import { translationActions } from "./translation/store" +import { unreadActions } from "./unread/store" +import { userActions } from "./user/store" + +/// keep-sorted +const hydrates: Hydratable[] = [ + collectionActions, + entryActions, + feedActions, + imageActions, + inboxActions, + listActions, + subscriptionActions, + translationActions, + unreadActions, + userActions, +] + +export const hydrateDatabaseToStore = async () => { + await Promise.all(hydrates.map((h) => h.hydrate())) +} diff --git a/apps/mobile/src/services/internal/base.ts b/apps/mobile/src/store/internal/base.ts similarity index 50% rename from apps/mobile/src/services/internal/base.ts rename to apps/mobile/src/store/internal/base.ts index 4e4b9bd3a..cb58aae60 100644 --- a/apps/mobile/src/services/internal/base.ts +++ b/apps/mobile/src/store/internal/base.ts @@ -1,7 +1,3 @@ export interface Hydratable { hydrate: () => Promise } - -export interface Resetable { - reset: () => Promise -} diff --git a/apps/mobile/src/store/list/store.ts b/apps/mobile/src/store/list/store.ts index 98f610812..9247c4bd1 100644 --- a/apps/mobile/src/store/list/store.ts +++ b/apps/mobile/src/store/list/store.ts @@ -1,11 +1,12 @@ import type { ListSchema } from "@follow/database/src/schemas/types" +import { ListService } from "@follow/database/src/services/list" import { apiClient } from "@/src/lib/api-fetch" import { honoMorph } from "@/src/morph/hono" import { storeDbMorph } from "@/src/morph/store-db" -import { ListService } from "@/src/services/list" import { feedActions } from "../feed/store" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import { getList } from "./getters" import type { CreateListModel } from "./types" @@ -29,7 +30,17 @@ export const useListStore = createZustandStore("list")(() => defaultS const get = useListStore.getState const set = useListStore.setState const immerSet = createImmerSetter(useListStore) -class ListActions { +class ListActions implements Hydratable { + async hydrate() { + const lists = await ListService.getListAll() + listActions.upsertManyInSession( + lists.map((list) => ({ + ...list, + feedIds: JSON.parse(list.feedIds || "[]") as string[], + })), + ) + } + upsertManyInSession(lists: ListModel[]) { const state = get() diff --git a/apps/mobile/src/store/subscription/store.ts b/apps/mobile/src/store/subscription/store.ts index d08edf287..f1cfbaa0a 100644 --- a/apps/mobile/src/store/subscription/store.ts +++ b/apps/mobile/src/store/subscription/store.ts @@ -1,15 +1,17 @@ import { FeedViewType } from "@follow/constants" import type { SubscriptionSchema } from "@follow/database/src/schemas/types" +import { SubscriptionService } from "@follow/database/src/services/subscription" import { tracker } from "@follow/tracker" import { apiClient } from "@/src/lib/api-fetch" import { toast } from "@/src/lib/toast" +import { dbStoreMorph } from "@/src/morph/db-store" import { honoMorph } from "@/src/morph/hono" import { buildSubscriptionDbId, storeDbMorph } from "@/src/morph/store-db" -import { SubscriptionService } from "@/src/services/subscription" import { feedActions } from "../feed/store" import { inboxActions } from "../inbox/store" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import { listActions } from "../list/store" import { whoami } from "../user/getters" @@ -66,7 +68,13 @@ export const useSubscriptionStore = createZustandStore("subsc const get = useSubscriptionStore.getState const immerSet = createImmerSetter(useSubscriptionStore) -class SubscriptionActions { +class SubscriptionActions implements Hydratable { + async hydrate() { + const subscriptions = await SubscriptionService.getSubscriptionAll() + subscriptionActions.upsertManyInSession( + subscriptions.map((s) => dbStoreMorph.toSubscriptionModel(s)), + ) + } async upsertManyInSession(subscriptions: SubscriptionModel[]) { immerSet((draft) => { for (const subscription of subscriptions) { diff --git a/apps/mobile/src/store/summary/store.ts b/apps/mobile/src/store/summary/store.ts index 95fe46e0f..427803936 100644 --- a/apps/mobile/src/store/summary/store.ts +++ b/apps/mobile/src/store/summary/store.ts @@ -1,8 +1,8 @@ import type { SummarySchema } from "@follow/database/src/schemas/types" +import { summaryService } from "@follow/database/src/services/summary" import { getActionLanguage } from "@/src/atoms/settings/general" import { apiClient } from "@/src/lib/api-fetch" -import { summaryService } from "@/src/services/summary" import { getEntry } from "../entry/getter" import { createImmerSetter, createZustandStore } from "../internal/helper" diff --git a/apps/mobile/src/store/translation/store.ts b/apps/mobile/src/store/translation/store.ts index 9785c59ca..cb013ce0c 100644 --- a/apps/mobile/src/store/translation/store.ts +++ b/apps/mobile/src/store/translation/store.ts @@ -1,11 +1,12 @@ import type { TranslationSchema } from "@follow/database/src/schemas/types" +import { TranslationService } from "@follow/database/src/services/translation" import { apiClient } from "@/src/lib/api-fetch" import type { SupportedLanguages } from "@/src/lib/language" import { checkLanguage } from "@/src/lib/translation" -import { TranslationService } from "@/src/services/translation" import { getEntry } from "../entry/getter" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createZustandStore } from "../internal/helper" import type { EntryTranslation, TranslationFieldArray } from "./types" import { translationFields } from "./types" @@ -24,7 +25,12 @@ export const useTranslationStore = createZustandStore("transla const get = useTranslationStore.getState const immerSet = createImmerSetter(useTranslationStore) -class TranslationActions { +class TranslationActions implements Hydratable { + async hydrate() { + const translations = await TranslationService.getTranslationAll() + translationActions.upsertManyInSession(translations) + } + upsertManyInSession(translations: TranslationModel[]) { translations.forEach((translation) => { immerSet((state) => { diff --git a/apps/mobile/src/store/unread/store.ts b/apps/mobile/src/store/unread/store.ts index 2c3fa9bc4..f138c77e5 100644 --- a/apps/mobile/src/store/unread/store.ts +++ b/apps/mobile/src/store/unread/store.ts @@ -1,14 +1,15 @@ import type { FeedViewType } from "@follow/constants" import type { UnreadSchema } from "@follow/database/src/schemas/types" +import { EntryService } from "@follow/database/src/services/entry" +import { UnreadService } from "@follow/database/src/services/unread" import { getGeneralSettings } from "@/src/atoms/settings/general" import { apiClient } from "@/src/lib/api-fetch" import { setBadgeCountAsyncWithPermission } from "@/src/lib/permission" -import { EntryService } from "@/src/services/entry" -import { UnreadService } from "@/src/services/unread" import { getEntry } from "../entry/getter" import { entryActions } from "../entry/store" +import type { Hydratable } from "../internal/base" import { createTransaction, createZustandStore } from "../internal/helper" import { getListFeedIds } from "../list/getters" import { getSubscriptionByView } from "../subscription/getter" @@ -185,7 +186,11 @@ class UnreadSyncService { } } -class UnreadActions { +class UnreadActions implements Hydratable { + async hydrate() { + const unreads = await UnreadService.getUnreadAll() + unreadActions.upsertManyInSession(unreads) + } upsertManyInSession(unreads: UnreadSchema[], options?: UnreadUpdateOptions) { const state = useUnreadStore.getState() const nextData = options?.reset ? {} : { ...state.data } diff --git a/apps/mobile/src/store/user/store.ts b/apps/mobile/src/store/user/store.ts index f1922fa43..48e119e78 100644 --- a/apps/mobile/src/store/user/store.ts +++ b/apps/mobile/src/store/user/store.ts @@ -1,13 +1,14 @@ import { UserRole } from "@follow/constants" import type { UserSchema } from "@follow/database/src/schemas/types" +import { UserService } from "@follow/database/src/services/user" import type { AuthSession } from "@follow/shared" import { apiClient } from "@/src/lib/api-fetch" import { changeEmail, sendVerificationEmail, twoFactor, updateUser } from "@/src/lib/auth" import { toast } from "@/src/lib/toast" import { honoMorph } from "@/src/morph/hono" -import { UserService } from "@/src/services/user" +import type { Hydratable } from "../internal/base" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" import type { UserProfileEditable } from "./types" @@ -171,7 +172,11 @@ class UserSyncService { } } -class UserActions { +class UserActions implements Hydratable { + async hydrate() { + const users = await UserService.getUserAll() + userActions.upsertManyInSession(users) + } upsertManyInSession(users: UserModel[]) { immerSet((state) => { for (const user of users) { diff --git a/apps/mobile/src/services/collection.ts b/packages/internal/database/src/services/collection.ts similarity index 61% rename from apps/mobile/src/services/collection.ts rename to packages/internal/database/src/services/collection.ts index 088b7b310..7ee0dab39 100644 --- a/apps/mobile/src/services/collection.ts +++ b/packages/internal/database/src/services/collection.ts @@ -1,13 +1,12 @@ -import { db } from "@follow/database/src/db" -import { collectionsTable } from "@follow/database/src/schemas" -import type { CollectionSchema } from "@follow/database/src/schemas/types" import { eq, inArray } from "drizzle-orm" -import { collectionActions } from "../store/collection/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { collectionsTable } from "../schemas" +import type { CollectionSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class CollectionServiceStatic implements Hydratable, Resetable { +class CollectionServiceStatic implements Resetable { async reset() { await db.delete(collectionsTable).execute() } @@ -31,9 +30,8 @@ class CollectionServiceStatic implements Hydratable, Resetable { return db.query.collectionsTable.findMany({ where: inArray(collectionsTable.entryId, entryId) }) } - async hydrate() { - const collections = await db.query.collectionsTable.findMany() - collectionActions.upsertManyInSession(collections) + getCollectionAll() { + return db.query.collectionsTable.findMany() } } diff --git a/apps/mobile/src/services/entry.ts b/packages/internal/database/src/services/entry.ts similarity index 64% rename from apps/mobile/src/services/entry.ts rename to packages/internal/database/src/services/entry.ts index 98948b379..8210eb419 100644 --- a/apps/mobile/src/services/entry.ts +++ b/packages/internal/database/src/services/entry.ts @@ -1,16 +1,17 @@ -import { db } from "@follow/database/src/db" -import { entriesTable } from "@follow/database/src/schemas" -import type { EntrySchema } from "@follow/database/src/schemas/types" import { and, between, eq, inArray, or } from "drizzle-orm" -import { getGeneralSettings } from "../atoms/settings/general" -import { dbStoreMorph } from "../morph/db-store" -import { entryActions } from "../store/entry/store" -import type { PublishAtTimeRangeFilter } from "../store/unread/types" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { entriesTable } from "../schemas" +import type { EntrySchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class EntryServiceStatic implements Hydratable, Resetable { +interface PublishAtTimeRangeFilter { + startTime: number + endTime: number +} + +class EntryServiceStatic implements Resetable { async reset() { await db.delete(entriesTable).execute() } @@ -59,13 +60,8 @@ class EntryServiceStatic implements Hydratable, Resetable { return db.query.entriesTable.findMany({ where: inArray(entriesTable.id, entryId) }) } - async hydrate() { - const entries = await db.query.entriesTable.findMany() - const { unreadOnly } = getGeneralSettings() - entryActions.upsertManyInSession( - entries.map((e) => dbStoreMorph.toEntryModel(e)), - { unreadOnly }, - ) + getEntryAll() { + return db.query.entriesTable.findMany() } } diff --git a/packages/internal/database/src/services/feed.ts b/packages/internal/database/src/services/feed.ts new file mode 100644 index 000000000..8498163a5 --- /dev/null +++ b/packages/internal/database/src/services/feed.ts @@ -0,0 +1,27 @@ +import { db } from "../db" +import { feedsTable } from "../schemas" +import type { FeedSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" +import { conflictUpdateAllExcept } from "./internal/utils" + +class FeedServiceStatic implements Resetable { + async reset() { + await db.delete(feedsTable).execute() + } + async upsertMany(feed: FeedSchema[]) { + if (feed.length === 0) return + await db + .insert(feedsTable) + .values(feed) + .onConflictDoUpdate({ + target: [feedsTable.id], + set: conflictUpdateAllExcept(feedsTable, ["id"]), + }) + } + + getFeedAll() { + return db.query.feedsTable.findMany() + } +} + +export const FeedService = new FeedServiceStatic() diff --git a/apps/mobile/src/services/image.ts b/packages/internal/database/src/services/image.ts similarity index 50% rename from apps/mobile/src/services/image.ts rename to packages/internal/database/src/services/image.ts index cc3a1184d..12c5ab02f 100644 --- a/apps/mobile/src/services/image.ts +++ b/packages/internal/database/src/services/image.ts @@ -1,19 +1,13 @@ -import { db } from "@follow/database/src/db" -import { imagesTable } from "@follow/database/src/schemas" -import type { ImageSchema } from "@follow/database/src/schemas/types" - -import { imageActions } from "../store/image/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { imagesTable } from "../schemas" +import type { ImageSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class ImageServiceStatic implements Hydratable, Resetable { +class ImageServiceStatic implements Resetable { async reset() { await db.delete(imagesTable).execute() } - async hydrate() { - const images = await db.query.imagesTable.findMany() - imageActions.upsertManyInSession(images) - } async upsertMany(imageColors: ImageSchema[]) { if (imageColors.length === 0) return @@ -25,6 +19,10 @@ class ImageServiceStatic implements Hydratable, Resetable { set: conflictUpdateAllExcept(imagesTable, ["url"]), }) } + + async getImageAll() { + return db.query.imagesTable.findMany() + } } export const ImagesService = new ImageServiceStatic() diff --git a/apps/mobile/src/services/inbox.ts b/packages/internal/database/src/services/inbox.ts similarity index 54% rename from apps/mobile/src/services/inbox.ts rename to packages/internal/database/src/services/inbox.ts index 132a1ccd3..88e264ac4 100644 --- a/apps/mobile/src/services/inbox.ts +++ b/packages/internal/database/src/services/inbox.ts @@ -1,22 +1,16 @@ -import { db } from "@follow/database/src/db" -import { inboxesTable } from "@follow/database/src/schemas" -import type { InboxSchema } from "@follow/database/src/schemas/types" - -import { inboxActions } from "../store/inbox/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { inboxesTable } from "../schemas" +import type { InboxSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class InboxServiceStatic implements Hydratable, Resetable { +class InboxServiceStatic implements Resetable { async reset() { await db.delete(inboxesTable).execute() } async getInbox(): Promise { return await db.select().from(inboxesTable) } - async hydrate() { - const inboxes = await db.query.inboxesTable.findMany() - inboxActions.upsertManyInSession(inboxes) - } async upsertMany(inboxes: InboxSchema[]) { if (inboxes.length === 0) return diff --git a/packages/internal/database/src/services/internal/base.ts b/packages/internal/database/src/services/internal/base.ts new file mode 100644 index 000000000..9a93196a6 --- /dev/null +++ b/packages/internal/database/src/services/internal/base.ts @@ -0,0 +1,3 @@ +export interface Resetable { + reset: () => Promise +} diff --git a/apps/mobile/src/services/internal/utils.ts b/packages/internal/database/src/services/internal/utils.ts similarity index 100% rename from apps/mobile/src/services/internal/utils.ts rename to packages/internal/database/src/services/internal/utils.ts diff --git a/apps/mobile/src/services/list.ts b/packages/internal/database/src/services/list.ts similarity index 51% rename from apps/mobile/src/services/list.ts rename to packages/internal/database/src/services/list.ts index 0003893f1..bbf63e794 100644 --- a/apps/mobile/src/services/list.ts +++ b/packages/internal/database/src/services/list.ts @@ -1,25 +1,16 @@ -import { db } from "@follow/database/src/db" -import { listsTable } from "@follow/database/src/schemas" -import type { ListSchema } from "@follow/database/src/schemas/types" import { eq } from "drizzle-orm" -import { listActions } from "../store/list/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { listsTable } from "../schemas" +import type { ListSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class ListServiceStatic implements Hydratable, Resetable { +class ListServiceStatic implements Resetable { async reset() { await db.delete(listsTable).execute() } - async hydrate() { - const lists = await db.query.listsTable.findMany() - listActions.upsertManyInSession( - lists.map((list) => ({ - ...list, - feedIds: JSON.parse(list.feedIds || "[]") as string[], - })), - ) - } + async upsertMany(lists: ListSchema[]) { if (lists.length === 0) return await db @@ -34,6 +25,10 @@ class ListServiceStatic implements Hydratable, Resetable { async deleteList(params: { listId: string }) { await db.delete(listsTable).where(eq(listsTable.id, params.listId)) } + + getListAll() { + return db.query.listsTable.findMany() + } } export const ListService = new ListServiceStatic() diff --git a/apps/mobile/src/services/subscription.ts b/packages/internal/database/src/services/subscription.ts similarity index 77% rename from apps/mobile/src/services/subscription.ts rename to packages/internal/database/src/services/subscription.ts index a6f17dd6f..047596142 100644 --- a/apps/mobile/src/services/subscription.ts +++ b/packages/internal/database/src/services/subscription.ts @@ -1,19 +1,16 @@ -import type { FeedViewType } from "@follow/constants/src/enums" -import { db } from "@follow/database/src/db" -import { - feedsTable, - inboxesTable, - listsTable, - subscriptionsTable, -} from "@follow/database/src/schemas" -import type { SubscriptionSchema } from "@follow/database/src/schemas/types" +import type { FeedViewType } from "@follow/constants" import { and, eq, inArray, notInArray, sql } from "drizzle-orm" -import { dbStoreMorph } from "../morph/db-store" -import { subscriptionActions } from "../store/subscription/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { feedsTable, inboxesTable, listsTable, subscriptionsTable } from "../schemas" +import type { SubscriptionSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" + +class SubscriptionServiceStatic implements Resetable { + getSubscriptionAll() { + return db.query.subscriptionsTable.findMany() + } -class SubscriptionServiceStatic implements Hydratable, Resetable { async reset() { await db.delete(subscriptionsTable).execute() } @@ -42,12 +39,6 @@ class SubscriptionServiceStatic implements Hydratable, Resetable { .set(subscription) .where(eq(subscriptionsTable.id, subscription.id)) } - async hydrate() { - const subscriptions = await db.query.subscriptionsTable.findMany() - subscriptionActions.upsertManyInSession( - subscriptions.map((s) => dbStoreMorph.toSubscriptionModel(s)), - ) - } async deleteNotExists(existsIds: string[], view?: FeedViewType) { const notExistsIds = await db.query.subscriptionsTable.findMany({ diff --git a/apps/mobile/src/services/summary.ts b/packages/internal/database/src/services/summary.ts similarity index 84% rename from apps/mobile/src/services/summary.ts rename to packages/internal/database/src/services/summary.ts index 2b4f605e2..457bd40bf 100644 --- a/apps/mobile/src/services/summary.ts +++ b/packages/internal/database/src/services/summary.ts @@ -1,8 +1,9 @@ -import { db } from "@follow/database/src/db" -import { summariesTable } from "@follow/database/src/schemas" -import type { SummarySchema } from "@follow/database/src/schemas/types" import { eq } from "drizzle-orm" +import { db } from "../db" +import { summariesTable } from "../schemas" +import type { SummarySchema } from "../schemas/types" + class SummaryServiceStatic { async insertSummary(data: Omit) { const updateExceptEmpty = Object.fromEntries( diff --git a/apps/mobile/src/services/translation.ts b/packages/internal/database/src/services/translation.ts similarity index 64% rename from apps/mobile/src/services/translation.ts rename to packages/internal/database/src/services/translation.ts index 648dfa07d..a032b28a6 100644 --- a/apps/mobile/src/services/translation.ts +++ b/packages/internal/database/src/services/translation.ts @@ -1,16 +1,15 @@ -import { db } from "@follow/database/src/db" -import { translationsTable } from "@follow/database/src/schemas" -import type { TranslationSchema } from "@follow/database/src/schemas/types" import { eq } from "drizzle-orm" -import { translationActions } from "../store/translation/store" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { translationsTable } from "../schemas" +import type { TranslationSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" -class TranslationServiceStatic implements Hydratable, Resetable { - async hydrate() { - const translations = await db.query.translationsTable.findMany() - translationActions.upsertManyInSession(translations) +class TranslationServiceStatic implements Resetable { + getTranslationAll() { + return db.query.translationsTable.findMany() } + async reset() { await db.delete(translationsTable).execute() } diff --git a/apps/mobile/src/services/unread.ts b/packages/internal/database/src/services/unread.ts similarity index 55% rename from apps/mobile/src/services/unread.ts rename to packages/internal/database/src/services/unread.ts index b40985007..fbba78103 100644 --- a/apps/mobile/src/services/unread.ts +++ b/packages/internal/database/src/services/unread.ts @@ -1,19 +1,20 @@ -import { db } from "@follow/database/src/db" -import { unreadTable } from "@follow/database/src/schemas" -import type { UnreadSchema } from "@follow/database/src/schemas/types" - -import { unreadActions } from "../store/unread/store" -import type { UnreadUpdateOptions } from "../store/unread/types" -import type { Hydratable, Resetable } from "./internal/base" +import { db } from "../db" +import { unreadTable } from "../schemas" +import type { UnreadSchema } from "../schemas/types" +import type { Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" -class UnreadServiceStatic implements Hydratable, Resetable { +interface UnreadUpdateOptions { + reset?: boolean +} + +class UnreadServiceStatic implements Resetable { async reset() { await db.delete(unreadTable).execute() } - async hydrate() { - const unreads = await db.query.unreadTable.findMany() - unreadActions.upsertManyInSession(unreads) + + async getUnreadAll() { + return db.query.unreadTable.findMany() } async upsertMany(unreads: UnreadSchema[], options?: UnreadUpdateOptions) { diff --git a/apps/mobile/src/services/user.ts b/packages/internal/database/src/services/user.ts similarity index 53% rename from apps/mobile/src/services/user.ts rename to packages/internal/database/src/services/user.ts index 1f2f2c158..4929b2eef 100644 --- a/apps/mobile/src/services/user.ts +++ b/packages/internal/database/src/services/user.ts @@ -1,13 +1,15 @@ -import { db } from "@follow/database/src/db" -import { usersTable } from "@follow/database/src/schemas" -import type { UserSchema } from "@follow/database/src/schemas/types" import { eq } from "drizzle-orm" -import { userActions } from "../store/user/store" -import type { Hydratable } from "./internal/base" +import { db } from "../db" +import { usersTable } from "../schemas" +import type { UserSchema } from "../schemas/types" import { conflictUpdateAllExcept } from "./internal/utils" -class UserServiceStatic implements Hydratable { +class UserServiceStatic { + getUserAll() { + return db.query.usersTable.findMany() + } + async upsertMany(users: UserSchema[]) { await db .insert(usersTable) @@ -18,11 +20,6 @@ class UserServiceStatic implements Hydratable { }) } - async hydrate() { - const users = await db.query.usersTable.findMany() - userActions.upsertManyInSession(users) - } - async removeCurrentUser() { await db.update(usersTable).set({ isMe: false }).where(eq(usersTable.isMe, true)) }