diff --git a/apps/mobile/package.json b/apps/mobile/package.json index defc71d6d..9e02af1e7 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -23,6 +23,7 @@ "@expo/react-native-action-sheet": "4.1.1", "@follow/components": "workspace:*", "@follow/constants": "workspace:*", + "@follow/database": "workspace:*", "@follow/hooks": "workspace:*", "@follow/legal": "workspace:*", "@follow/models": "workspace:*", diff --git a/apps/mobile/src/components/ui/carousel/MediaCarousel.tsx b/apps/mobile/src/components/ui/carousel/MediaCarousel.tsx index c65329a9f..8017cc37b 100644 --- a/apps/mobile/src/components/ui/carousel/MediaCarousel.tsx +++ b/apps/mobile/src/components/ui/carousel/MediaCarousel.tsx @@ -1,4 +1,5 @@ import type { FeedViewType } from "@follow/constants" +import type { MediaModel } from "@follow/database/src/schemas/types" import { useEffect, useMemo, useState } from "react" import { ScrollView, View } from "react-native" import Animated, { @@ -9,7 +10,6 @@ import Animated, { } from "react-native-reanimated" import { Galeria } from "@/src/components/ui/image/galeria" -import type { MediaModel } from "@/src/database/schemas/types" import { EntryGridFooter } from "@/src/modules/entry-content/EntryGridFooter" import { Image } from "../image/Image" diff --git a/apps/mobile/src/components/ui/icon/feed-icon.tsx b/apps/mobile/src/components/ui/icon/feed-icon.tsx index 6730f6036..493ed80eb 100644 --- a/apps/mobile/src/components/ui/icon/feed-icon.tsx +++ b/apps/mobile/src/components/ui/icon/feed-icon.tsx @@ -1,8 +1,8 @@ import type { FeedViewType } from "@follow/constants" +import type { FeedSchema } from "@follow/database/src/schemas/types" import type { ReactNode } from "react" import { useCallback, useMemo, useState } from "react" -import type { FeedSchema } from "@/src/database/schemas/types" import { getFeedIconSource } from "@/src/lib/image" import type { ImageProps } from "../image/Image" diff --git a/apps/mobile/src/database/index.ts b/apps/mobile/src/database/index.ts index 8c9088f44..563c5a44b 100644 --- a/apps/mobile/src/database/index.ts +++ b/apps/mobile/src/database/index.ts @@ -1,24 +1,5 @@ -import type { ExpoSQLiteDatabase } from "drizzle-orm/expo-sqlite" -import { drizzle } from "drizzle-orm/expo-sqlite" import * as FileSystem from "expo-file-system" -import * as SQLite from "expo-sqlite" -import * as schema from "./schemas" - -export const sqlite = SQLite.openDatabaseSync("follow.db") - -let db: ExpoSQLiteDatabase & { - $client: SQLite.SQLiteDatabase -} - -export function initializeDb() { - db = drizzle(sqlite, { - schema, - logger: false, - }) -} - -export { db } export const getDbPath = () => { return `${FileSystem.documentDirectory}SQLite/follow.db` } diff --git a/apps/mobile/src/initialize/index.ts b/apps/mobile/src/initialize/index.ts index 1d0b20165..e025e2d9c 100644 --- a/apps/mobile/src/initialize/index.ts +++ b/apps/mobile/src/initialize/index.ts @@ -1,7 +1,7 @@ +import { initializeDb } from "@follow/database/src/db" import { tracker } from "@follow/tracker" import { nativeApplicationVersion } from "expo-application" -import { initializeDb } from "../database" import { settingSyncQueue } from "../modules/settings/sync-queue" import { initAnalytics } from "./analytics" import { initializeAppCheck } from "./app-check" diff --git a/apps/mobile/src/initialize/migration.ts b/apps/mobile/src/initialize/migration.ts index 82ec8039b..ef2503414 100644 --- a/apps/mobile/src/initialize/migration.ts +++ b/apps/mobile/src/initialize/migration.ts @@ -1,10 +1,6 @@ -import { migrate } from "drizzle-orm/expo-sqlite/migrator" +import { migrateDb } from "@follow/database/src/db" import { useSyncExternalStore } from "react" -import migrations from "@/drizzle/migrations" - -import { db } from "../database" - let storeChangeFn: () => void const subscribe = (onStoreChange: () => void) => { storeChangeFn = onStoreChange @@ -20,7 +16,7 @@ const migrateStore = { export const migrateDatabase = async () => { try { - await migrate(db, migrations) + await migrateDb() migrateStore.success = true storeChangeFn?.() } catch (error) { diff --git a/apps/mobile/src/lib/player.ts b/apps/mobile/src/lib/player.ts index e692db355..14fa50b9b 100644 --- a/apps/mobile/src/lib/player.ts +++ b/apps/mobile/src/lib/player.ts @@ -1,9 +1,8 @@ +import type { AttachmentsModel } from "@follow/database/src/schemas/types" import { atom, useAtom } from "jotai" import { useCallback, useEffect } from "react" import TrackPlayer, { State, useActiveTrack, usePlaybackState } from "react-native-track-player" -import type { AttachmentsModel } from "../database/schemas/types" - const LOADING_SUFFIX = "_loading" export function usePlayingUrl() { diff --git a/apps/mobile/src/modules/entry-list/templates/EntryPictureItem.tsx b/apps/mobile/src/modules/entry-list/templates/EntryPictureItem.tsx index 8c570aa39..c309b07d9 100644 --- a/apps/mobile/src/modules/entry-list/templates/EntryPictureItem.tsx +++ b/apps/mobile/src/modules/entry-list/templates/EntryPictureItem.tsx @@ -1,4 +1,5 @@ import { FeedViewType } from "@follow/constants" +import type { MediaModel } from "@follow/database/src/schemas/types" import { tracker } from "@follow/tracker" import { uniqBy } from "es-toolkit/compat" import { useMemo } from "react" @@ -7,7 +8,6 @@ import { Text, View } from "react-native" import { showEntryGaleriaAccessory } from "@/src/components/native/GaleriaAccessory/EntryGaleriaAccessory" import { preloadWebViewEntry } from "@/src/components/native/webview/EntryContentWebView" import { MediaCarousel } from "@/src/components/ui/carousel/MediaCarousel" -import type { MediaModel } from "@/src/database/schemas/types" import { getFeedIconSource } from "@/src/lib/image" import { useEntry } from "@/src/store/entry/hooks" import { getFeed } from "@/src/store/feed/getter" diff --git a/apps/mobile/src/morph/db-store.ts b/apps/mobile/src/morph/db-store.ts index 339d68023..7038a94cc 100644 --- a/apps/mobile/src/morph/db-store.ts +++ b/apps/mobile/src/morph/db-store.ts @@ -1,4 +1,5 @@ -import type { EntrySchema, SubscriptionSchema } from "../database/schemas/types" +import type { EntrySchema, SubscriptionSchema } from "@follow/database/src/schemas/types" + import type { EntryModel } from "../store/entry/types" import type { SubscriptionModel } from "../store/subscription/store" diff --git a/apps/mobile/src/morph/hono.ts b/apps/mobile/src/morph/hono.ts index 48c1c4bc4..64c60688a 100644 --- a/apps/mobile/src/morph/hono.ts +++ b/apps/mobile/src/morph/hono.ts @@ -1,6 +1,6 @@ import type { FeedViewType } from "@follow/constants" +import type { FeedSchema, InboxSchema } from "@follow/database/src/schemas/types" -import type { FeedSchema, InboxSchema } from "../database/schemas/types" import type { CollectionModel } from "../store/collection/types" import type { EntryModel } from "../store/entry/types" import type { FeedModel } from "../store/feed/types" diff --git a/apps/mobile/src/morph/store-db.ts b/apps/mobile/src/morph/store-db.ts index 17c6466c1..551b78c0f 100644 --- a/apps/mobile/src/morph/store-db.ts +++ b/apps/mobile/src/morph/store-db.ts @@ -1,4 +1,9 @@ -import type { EntrySchema, ListSchema, SubscriptionSchema } from "../database/schemas/types" +import type { + EntrySchema, + ListSchema, + SubscriptionSchema, +} from "@follow/database/src/schemas/types" + import type { EntryModel } from "../store/entry/types" import type { ListModel } from "../store/list/store" import type { SubscriptionModel } from "../store/subscription/store" diff --git a/apps/mobile/src/providers/index.tsx b/apps/mobile/src/providers/index.tsx index 62b785bf4..07ea3e05a 100644 --- a/apps/mobile/src/providers/index.tsx +++ b/apps/mobile/src/providers/index.tsx @@ -1,4 +1,5 @@ import { ActionSheetProvider } from "@expo/react-native-action-sheet" +import { sqlite } from "@follow/database/src/db" import { jotaiStore } from "@follow/utils" import { PortalProvider } from "@gorhom/portal" import { QueryClientProvider } from "@tanstack/react-query" @@ -13,7 +14,6 @@ import { useCurrentColorsVariants } from "react-native-uikit-colors" import { ErrorBoundary } from "../components/common/ErrorBoundary" import { GlobalErrorScreen } from "../components/errors/GlobalErrorScreen" -import { sqlite } from "../database" import { queryClient } from "../lib/query-client" import { MigrationProvider } from "./migration" import { ServerConfigsProvider } from "./ServerConfigsProvider" diff --git a/apps/mobile/src/services/collection.ts b/apps/mobile/src/services/collection.ts index 2428f6dd5..088b7b310 100644 --- a/apps/mobile/src/services/collection.ts +++ b/apps/mobile/src/services/collection.ts @@ -1,8 +1,8 @@ +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 { db } from "../database" -import { collectionsTable } from "../database/schemas" -import type { CollectionSchema } from "../database/schemas/types" import { collectionActions } from "../store/collection/store" import type { Hydratable, Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" diff --git a/apps/mobile/src/services/entry.ts b/apps/mobile/src/services/entry.ts index 2d9d2e62d..98948b379 100644 --- a/apps/mobile/src/services/entry.ts +++ b/apps/mobile/src/services/entry.ts @@ -1,9 +1,9 @@ +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 { db } from "../database" -import { entriesTable } from "../database/schemas" -import type { EntrySchema } from "../database/schemas/types" import { dbStoreMorph } from "../morph/db-store" import { entryActions } from "../store/entry/store" import type { PublishAtTimeRangeFilter } from "../store/unread/types" diff --git a/apps/mobile/src/services/feed.ts b/apps/mobile/src/services/feed.ts index 5c7174230..5abe91302 100644 --- a/apps/mobile/src/services/feed.ts +++ b/apps/mobile/src/services/feed.ts @@ -1,6 +1,7 @@ -import { db } from "../database" -import { feedsTable } from "../database/schemas" -import type { FeedSchema } from "../database/schemas/types" +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" diff --git a/apps/mobile/src/services/image.ts b/apps/mobile/src/services/image.ts index 6336d8a2b..cc3a1184d 100644 --- a/apps/mobile/src/services/image.ts +++ b/apps/mobile/src/services/image.ts @@ -1,7 +1,7 @@ -import { imagesTable } from "@/src/database/schemas" -import type { ImageSchema } from "@/src/database/schemas/types" +import { db } from "@follow/database/src/db" +import { imagesTable } from "@follow/database/src/schemas" +import type { ImageSchema } from "@follow/database/src/schemas/types" -import { db } from "../database" import { imageActions } from "../store/image/store" import type { Hydratable, Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" diff --git a/apps/mobile/src/services/inbox.ts b/apps/mobile/src/services/inbox.ts index 49b2591ea..132a1ccd3 100644 --- a/apps/mobile/src/services/inbox.ts +++ b/apps/mobile/src/services/inbox.ts @@ -1,7 +1,7 @@ -import { inboxesTable } from "@/src/database/schemas" -import type { InboxSchema } from "@/src/database/schemas/types" +import { db } from "@follow/database/src/db" +import { inboxesTable } from "@follow/database/src/schemas" +import type { InboxSchema } from "@follow/database/src/schemas/types" -import { db } from "../database" import { inboxActions } from "../store/inbox/store" import type { Hydratable, Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" diff --git a/apps/mobile/src/services/list.ts b/apps/mobile/src/services/list.ts index 98c7c1ed4..0003893f1 100644 --- a/apps/mobile/src/services/list.ts +++ b/apps/mobile/src/services/list.ts @@ -1,8 +1,8 @@ +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 { db } from "../database" -import { listsTable } from "../database/schemas" -import type { ListSchema } from "../database/schemas/types" import { listActions } from "../store/list/store" import type { Hydratable, Resetable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" diff --git a/apps/mobile/src/services/subscription.ts b/apps/mobile/src/services/subscription.ts index c45241caa..a6f17dd6f 100644 --- a/apps/mobile/src/services/subscription.ts +++ b/apps/mobile/src/services/subscription.ts @@ -1,9 +1,14 @@ 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 { and, eq, inArray, notInArray, sql } from "drizzle-orm" -import { db } from "../database" -import { feedsTable, inboxesTable, listsTable, subscriptionsTable } from "../database/schemas" -import type { SubscriptionSchema } from "../database/schemas/types" import { dbStoreMorph } from "../morph/db-store" import { subscriptionActions } from "../store/subscription/store" import type { Hydratable, Resetable } from "./internal/base" diff --git a/apps/mobile/src/services/summary.ts b/apps/mobile/src/services/summary.ts index d3d95ddfd..2b4f605e2 100644 --- a/apps/mobile/src/services/summary.ts +++ b/apps/mobile/src/services/summary.ts @@ -1,9 +1,8 @@ +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 "../database" -import { summariesTable } from "../database/schemas" -import type { SummarySchema } from "../database/schemas/types" - class SummaryServiceStatic { async insertSummary(data: Omit) { const updateExceptEmpty = Object.fromEntries( diff --git a/apps/mobile/src/services/translation.ts b/apps/mobile/src/services/translation.ts index 7bd1744b9..648dfa07d 100644 --- a/apps/mobile/src/services/translation.ts +++ b/apps/mobile/src/services/translation.ts @@ -1,8 +1,8 @@ +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 { db } from "../database" -import { translationsTable } from "../database/schemas" -import type { TranslationSchema } from "../database/schemas/types" import { translationActions } from "../store/translation/store" import type { Hydratable, Resetable } from "./internal/base" diff --git a/apps/mobile/src/services/unread.ts b/apps/mobile/src/services/unread.ts index 85be3590e..b40985007 100644 --- a/apps/mobile/src/services/unread.ts +++ b/apps/mobile/src/services/unread.ts @@ -1,6 +1,7 @@ -import { db } from "../database" -import { unreadTable } from "../database/schemas" -import type { UnreadSchema } from "../database/schemas/types" +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" diff --git a/apps/mobile/src/services/user.ts b/apps/mobile/src/services/user.ts index fc5a0a5f8..1f2f2c158 100644 --- a/apps/mobile/src/services/user.ts +++ b/apps/mobile/src/services/user.ts @@ -1,8 +1,8 @@ +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 { db } from "../database" -import { usersTable } from "../database/schemas" -import type { UserSchema } from "../database/schemas/types" import { userActions } from "../store/user/store" import type { Hydratable } from "./internal/base" import { conflictUpdateAllExcept } from "./internal/utils" diff --git a/apps/mobile/src/store/collection/store.ts b/apps/mobile/src/store/collection/store.ts index 6fd44a0a0..370e78776 100644 --- a/apps/mobile/src/store/collection/store.ts +++ b/apps/mobile/src/store/collection/store.ts @@ -1,6 +1,6 @@ import type { FeedViewType } from "@follow/constants" +import type { CollectionSchema } from "@follow/database/src/schemas/types" -import type { CollectionSchema } from "@/src/database/schemas/types" import { apiClient } from "@/src/lib/api-fetch" import { CollectionService } from "@/src/services/collection" diff --git a/apps/mobile/src/store/collection/types.ts b/apps/mobile/src/store/collection/types.ts index 9f0dd5bec..df7c9c5ac 100644 --- a/apps/mobile/src/store/collection/types.ts +++ b/apps/mobile/src/store/collection/types.ts @@ -1,3 +1,3 @@ -import type { CollectionSchema } from "@/src/database/schemas/types" +import type { CollectionSchema } from "@follow/database/src/schemas/types" export type CollectionModel = CollectionSchema diff --git a/apps/mobile/src/store/entry/types.ts b/apps/mobile/src/store/entry/types.ts index 45b32e6ec..98eeb2352 100644 --- a/apps/mobile/src/store/entry/types.ts +++ b/apps/mobile/src/store/entry/types.ts @@ -1,4 +1,4 @@ -import type { EntrySchema } from "@/src/database/schemas/types" +import type { EntrySchema } from "@follow/database/src/schemas/types" import type { EntryTranslation } from "../translation/types" diff --git a/apps/mobile/src/store/feed/getter.ts b/apps/mobile/src/store/feed/getter.ts index 506c3a71f..f819a36d9 100644 --- a/apps/mobile/src/store/feed/getter.ts +++ b/apps/mobile/src/store/feed/getter.ts @@ -1,4 +1,4 @@ -import type { FeedSchema } from "@/src/database/schemas/types" +import type { FeedSchema } from "@follow/database/src/schemas/types" import { useFeedStore } from "./store" diff --git a/apps/mobile/src/store/feed/store.ts b/apps/mobile/src/store/feed/store.ts index 79606e580..2eacdea5a 100644 --- a/apps/mobile/src/store/feed/store.ts +++ b/apps/mobile/src/store/feed/store.ts @@ -1,4 +1,5 @@ -import type { FeedSchema } from "@/src/database/schemas/types" +import type { FeedSchema } from "@follow/database/src/schemas/types" + import { apiClient } from "@/src/lib/api-fetch" import { FeedService } from "@/src/services/feed" diff --git a/apps/mobile/src/store/feed/types.ts b/apps/mobile/src/store/feed/types.ts index 3127792ec..738b307b4 100644 --- a/apps/mobile/src/store/feed/types.ts +++ b/apps/mobile/src/store/feed/types.ts @@ -1,4 +1,4 @@ -import type { FeedSchema } from "@/src/database/schemas/types" +import type { FeedSchema } from "@follow/database/src/schemas/types" export type FeedModel = FeedSchema & { nonce?: string diff --git a/apps/mobile/src/store/image/store.ts b/apps/mobile/src/store/image/store.ts index d0d0eb79a..d81b541f8 100644 --- a/apps/mobile/src/store/image/store.ts +++ b/apps/mobile/src/store/image/store.ts @@ -1,6 +1,6 @@ +import type { ImageSchema } from "@follow/database/src/schemas/types" import ImageColors from "react-native-image-colors" -import type { ImageSchema } from "@/src/database/schemas/types" import { ImagesService } from "@/src/services/image" import { createImmerSetter, createTransaction, createZustandStore } from "../internal/helper" diff --git a/apps/mobile/src/store/inbox/store.ts b/apps/mobile/src/store/inbox/store.ts index bcd77310f..b0035be20 100644 --- a/apps/mobile/src/store/inbox/store.ts +++ b/apps/mobile/src/store/inbox/store.ts @@ -1,4 +1,5 @@ -import type { InboxSchema } from "@/src/database/schemas/types" +import type { InboxSchema } from "@follow/database/src/schemas/types" + import { InboxService } from "@/src/services/inbox" import { createTransaction, createZustandStore } from "../internal/helper" diff --git a/apps/mobile/src/store/list/store.ts b/apps/mobile/src/store/list/store.ts index a0922b40d..98f610812 100644 --- a/apps/mobile/src/store/list/store.ts +++ b/apps/mobile/src/store/list/store.ts @@ -1,4 +1,5 @@ -import type { ListSchema } from "@/src/database/schemas/types" +import type { ListSchema } from "@follow/database/src/schemas/types" + import { apiClient } from "@/src/lib/api-fetch" import { honoMorph } from "@/src/morph/hono" import { storeDbMorph } from "@/src/morph/store-db" diff --git a/apps/mobile/src/store/subscription/store.ts b/apps/mobile/src/store/subscription/store.ts index 0571c7185..d08edf287 100644 --- a/apps/mobile/src/store/subscription/store.ts +++ b/apps/mobile/src/store/subscription/store.ts @@ -1,7 +1,7 @@ import { FeedViewType } from "@follow/constants" +import type { SubscriptionSchema } from "@follow/database/src/schemas/types" import { tracker } from "@follow/tracker" -import type { SubscriptionSchema } from "@/src/database/schemas/types" import { apiClient } from "@/src/lib/api-fetch" import { toast } from "@/src/lib/toast" import { honoMorph } from "@/src/morph/hono" diff --git a/apps/mobile/src/store/summary/store.ts b/apps/mobile/src/store/summary/store.ts index cc153b08c..95fe46e0f 100644 --- a/apps/mobile/src/store/summary/store.ts +++ b/apps/mobile/src/store/summary/store.ts @@ -1,5 +1,6 @@ +import type { SummarySchema } from "@follow/database/src/schemas/types" + import { getActionLanguage } from "@/src/atoms/settings/general" -import type { SummarySchema } from "@/src/database/schemas/types" import { apiClient } from "@/src/lib/api-fetch" import { summaryService } from "@/src/services/summary" diff --git a/apps/mobile/src/store/translation/store.ts b/apps/mobile/src/store/translation/store.ts index 2560f84d3..9785c59ca 100644 --- a/apps/mobile/src/store/translation/store.ts +++ b/apps/mobile/src/store/translation/store.ts @@ -1,4 +1,5 @@ -import type { TranslationSchema } from "@/src/database/schemas/types" +import type { TranslationSchema } from "@follow/database/src/schemas/types" + import { apiClient } from "@/src/lib/api-fetch" import type { SupportedLanguages } from "@/src/lib/language" import { checkLanguage } from "@/src/lib/translation" diff --git a/apps/mobile/src/store/unread/store.ts b/apps/mobile/src/store/unread/store.ts index b9936da5b..2c3fa9bc4 100644 --- a/apps/mobile/src/store/unread/store.ts +++ b/apps/mobile/src/store/unread/store.ts @@ -1,7 +1,7 @@ import type { FeedViewType } from "@follow/constants" +import type { UnreadSchema } from "@follow/database/src/schemas/types" import { getGeneralSettings } from "@/src/atoms/settings/general" -import type { UnreadSchema } from "@/src/database/schemas/types" import { apiClient } from "@/src/lib/api-fetch" import { setBadgeCountAsyncWithPermission } from "@/src/lib/permission" import { EntryService } from "@/src/services/entry" diff --git a/apps/mobile/src/store/user/store.ts b/apps/mobile/src/store/user/store.ts index 3d00ba5e7..f1922fa43 100644 --- a/apps/mobile/src/store/user/store.ts +++ b/apps/mobile/src/store/user/store.ts @@ -1,7 +1,7 @@ import { UserRole } from "@follow/constants" +import type { UserSchema } from "@follow/database/src/schemas/types" import type { AuthSession } from "@follow/shared" -import type { UserSchema } from "@/src/database/schemas/types" import { apiClient } from "@/src/lib/api-fetch" import { changeEmail, sendVerificationEmail, twoFactor, updateUser } from "@/src/lib/auth" import { toast } from "@/src/lib/toast" diff --git a/packages/configs/tsconfig.extend.json b/packages/configs/tsconfig.extend.json index 8a045309d..d49bec03a 100644 --- a/packages/configs/tsconfig.extend.json +++ b/packages/configs/tsconfig.extend.json @@ -13,6 +13,7 @@ "noEmit": true, "strict": true, "noUncheckedIndexedAccess": true, - "noImplicitOverride": true + "noImplicitOverride": true, + "allowJs": true } } diff --git a/packages/internal/database/drizzle.config.ts b/packages/internal/database/drizzle.config.ts new file mode 100644 index 000000000..0fd984273 --- /dev/null +++ b/packages/internal/database/drizzle.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "drizzle-kit" + +export default defineConfig({ + dialect: "sqlite", + driver: "expo", + schema: "./src/schemas/index.ts", + out: "./src/drizzle", +}) diff --git a/packages/internal/database/package.json b/packages/internal/database/package.json new file mode 100644 index 000000000..1e35d55df --- /dev/null +++ b/packages/internal/database/package.json @@ -0,0 +1,36 @@ +{ + "name": "@follow/database", + "type": "module", + "private": true, + "author": "Folo Team", + "license": "GPL-3.0-only", + "homepage": "https://github.com/RSSNext", + "repository": { + "url": "https://github.com/RSSNext/follow", + "type": "git" + }, + "sideEffects": false, + "exports": { + "./src/*": { + "types": "./src/*.ts", + "require": "./src/*.ts", + "import": "./src/*.ts" + } + }, + "scripts": { + "generate": "drizzle-kit generate", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@follow/constants": "workspace:*", + "@follow/models": "workspace:*", + "@follow/shared": "workspace:*", + "drizzle-orm": "0.42.0", + "expo-sqlite": "15.2.9", + "sqlocal": "0.14.1" + }, + "devDependencies": { + "@follow/configs": "workspace:*", + "drizzle-kit": "0.31.0" + } +} diff --git a/packages/internal/database/src/constant.ts b/packages/internal/database/src/constant.ts new file mode 100644 index 000000000..95893a1bc --- /dev/null +++ b/packages/internal/database/src/constant.ts @@ -0,0 +1 @@ +export const SQLITE_DB_NAME = "follow.db" diff --git a/packages/internal/database/src/db.desktop.ts b/packages/internal/database/src/db.desktop.ts new file mode 100644 index 000000000..46fd1f89f --- /dev/null +++ b/packages/internal/database/src/db.desktop.ts @@ -0,0 +1,24 @@ +import type { SqliteRemoteDatabase } from "drizzle-orm/sqlite-proxy" +import { drizzle } from "drizzle-orm/sqlite-proxy" +import { SQLocalDrizzle } from "sqlocal/drizzle" + +import { SQLITE_DB_NAME } from "./constant" +import migrations from "./drizzle/migrations" +import { migrate } from "./migrator" +import * as schema from "./schemas" + +export const sqlite = new SQLocalDrizzle(SQLITE_DB_NAME) + +let db: SqliteRemoteDatabase + +export function initializeDb() { + db = drizzle(sqlite.driver, sqlite.batchDriver, { + schema, + logger: false, + }) +} +export { db } + +export function migrateDb() { + return migrate(db, migrations) +} diff --git a/packages/internal/database/src/db.rn.ts b/packages/internal/database/src/db.rn.ts new file mode 100644 index 000000000..64999561a --- /dev/null +++ b/packages/internal/database/src/db.rn.ts @@ -0,0 +1,26 @@ +import type { ExpoSQLiteDatabase } from "drizzle-orm/expo-sqlite" +import { drizzle } from "drizzle-orm/expo-sqlite" +import { migrate } from "drizzle-orm/expo-sqlite/migrator" +import * as SQLite from "expo-sqlite" + +import { SQLITE_DB_NAME } from "./constant" +import migrations from "./drizzle/migrations" +import * as schema from "./schemas" + +export const sqlite = SQLite.openDatabaseSync(SQLITE_DB_NAME) + +let db: ExpoSQLiteDatabase & { + $client: SQLite.SQLiteDatabase +} + +export function initializeDb() { + db = drizzle(sqlite, { + schema, + logger: false, + }) +} +export { db } + +export function migrateDb(): Promise { + return migrate(db, migrations) +} diff --git a/packages/internal/database/src/db.ts b/packages/internal/database/src/db.ts new file mode 100644 index 000000000..9c3eac546 --- /dev/null +++ b/packages/internal/database/src/db.ts @@ -0,0 +1,6 @@ +import type { DB } from "./types" + +export declare const sqlite: unknown +export declare const db: DB +export declare function initializeDb(): void +export declare function migrateDb(): Promise diff --git a/apps/mobile/drizzle/0000_harsh_shiva.sql b/packages/internal/database/src/drizzle/0000_harsh_shiva.sql similarity index 100% rename from apps/mobile/drizzle/0000_harsh_shiva.sql rename to packages/internal/database/src/drizzle/0000_harsh_shiva.sql diff --git a/apps/mobile/drizzle/0001_bored_hobgoblin.sql b/packages/internal/database/src/drizzle/0001_bored_hobgoblin.sql similarity index 100% rename from apps/mobile/drizzle/0001_bored_hobgoblin.sql rename to packages/internal/database/src/drizzle/0001_bored_hobgoblin.sql diff --git a/apps/mobile/drizzle/0002_smart_power_man.sql b/packages/internal/database/src/drizzle/0002_smart_power_man.sql similarity index 100% rename from apps/mobile/drizzle/0002_smart_power_man.sql rename to packages/internal/database/src/drizzle/0002_smart_power_man.sql diff --git a/apps/mobile/drizzle/0003_known_roland_deschain.sql b/packages/internal/database/src/drizzle/0003_known_roland_deschain.sql similarity index 100% rename from apps/mobile/drizzle/0003_known_roland_deschain.sql rename to packages/internal/database/src/drizzle/0003_known_roland_deschain.sql diff --git a/apps/mobile/drizzle/0004_majestic_thunderbolt_ross.sql b/packages/internal/database/src/drizzle/0004_majestic_thunderbolt_ross.sql similarity index 100% rename from apps/mobile/drizzle/0004_majestic_thunderbolt_ross.sql rename to packages/internal/database/src/drizzle/0004_majestic_thunderbolt_ross.sql diff --git a/apps/mobile/drizzle/0005_tense_sleepwalker.sql b/packages/internal/database/src/drizzle/0005_tense_sleepwalker.sql similarity index 100% rename from apps/mobile/drizzle/0005_tense_sleepwalker.sql rename to packages/internal/database/src/drizzle/0005_tense_sleepwalker.sql diff --git a/apps/mobile/drizzle/0006_exotic_kid_colt.sql b/packages/internal/database/src/drizzle/0006_exotic_kid_colt.sql similarity index 100% rename from apps/mobile/drizzle/0006_exotic_kid_colt.sql rename to packages/internal/database/src/drizzle/0006_exotic_kid_colt.sql diff --git a/apps/mobile/drizzle/0007_curvy_tarantula.sql b/packages/internal/database/src/drizzle/0007_curvy_tarantula.sql similarity index 100% rename from apps/mobile/drizzle/0007_curvy_tarantula.sql rename to packages/internal/database/src/drizzle/0007_curvy_tarantula.sql diff --git a/apps/mobile/drizzle/0008_last_the_santerians.sql b/packages/internal/database/src/drizzle/0008_last_the_santerians.sql similarity index 100% rename from apps/mobile/drizzle/0008_last_the_santerians.sql rename to packages/internal/database/src/drizzle/0008_last_the_santerians.sql diff --git a/apps/mobile/drizzle/0009_lucky_power_man.sql b/packages/internal/database/src/drizzle/0009_lucky_power_man.sql similarity index 100% rename from apps/mobile/drizzle/0009_lucky_power_man.sql rename to packages/internal/database/src/drizzle/0009_lucky_power_man.sql diff --git a/apps/mobile/drizzle/0010_legal_ben_grimm.sql b/packages/internal/database/src/drizzle/0010_legal_ben_grimm.sql similarity index 100% rename from apps/mobile/drizzle/0010_legal_ben_grimm.sql rename to packages/internal/database/src/drizzle/0010_legal_ben_grimm.sql diff --git a/apps/mobile/drizzle/0011_mysterious_stark_industries.sql b/packages/internal/database/src/drizzle/0011_mysterious_stark_industries.sql similarity index 100% rename from apps/mobile/drizzle/0011_mysterious_stark_industries.sql rename to packages/internal/database/src/drizzle/0011_mysterious_stark_industries.sql diff --git a/apps/mobile/drizzle/0012_magenta_thing.sql b/packages/internal/database/src/drizzle/0012_magenta_thing.sql similarity index 100% rename from apps/mobile/drizzle/0012_magenta_thing.sql rename to packages/internal/database/src/drizzle/0012_magenta_thing.sql diff --git a/apps/mobile/drizzle/0013_chunky_stephen_strange.sql b/packages/internal/database/src/drizzle/0013_chunky_stephen_strange.sql similarity index 100% rename from apps/mobile/drizzle/0013_chunky_stephen_strange.sql rename to packages/internal/database/src/drizzle/0013_chunky_stephen_strange.sql diff --git a/apps/mobile/drizzle/0014_chemical_shocker.sql b/packages/internal/database/src/drizzle/0014_chemical_shocker.sql similarity index 100% rename from apps/mobile/drizzle/0014_chemical_shocker.sql rename to packages/internal/database/src/drizzle/0014_chemical_shocker.sql diff --git a/apps/mobile/drizzle/0015_colorful_warbird.sql b/packages/internal/database/src/drizzle/0015_colorful_warbird.sql similarity index 100% rename from apps/mobile/drizzle/0015_colorful_warbird.sql rename to packages/internal/database/src/drizzle/0015_colorful_warbird.sql diff --git a/apps/mobile/drizzle/0016_curious_carnage.sql b/packages/internal/database/src/drizzle/0016_curious_carnage.sql similarity index 100% rename from apps/mobile/drizzle/0016_curious_carnage.sql rename to packages/internal/database/src/drizzle/0016_curious_carnage.sql diff --git a/apps/mobile/drizzle/0017_talented_captain_cross.sql b/packages/internal/database/src/drizzle/0017_talented_captain_cross.sql similarity index 100% rename from apps/mobile/drizzle/0017_talented_captain_cross.sql rename to packages/internal/database/src/drizzle/0017_talented_captain_cross.sql diff --git a/apps/mobile/drizzle/0018_dashing_the_fury.sql b/packages/internal/database/src/drizzle/0018_dashing_the_fury.sql similarity index 100% rename from apps/mobile/drizzle/0018_dashing_the_fury.sql rename to packages/internal/database/src/drizzle/0018_dashing_the_fury.sql diff --git a/apps/mobile/drizzle/0019_wonderful_shape.sql b/packages/internal/database/src/drizzle/0019_wonderful_shape.sql similarity index 100% rename from apps/mobile/drizzle/0019_wonderful_shape.sql rename to packages/internal/database/src/drizzle/0019_wonderful_shape.sql diff --git a/apps/mobile/drizzle/0020_little_marauders.sql b/packages/internal/database/src/drizzle/0020_little_marauders.sql similarity index 100% rename from apps/mobile/drizzle/0020_little_marauders.sql rename to packages/internal/database/src/drizzle/0020_little_marauders.sql diff --git a/apps/mobile/drizzle/0021_wakeful_onslaught.sql b/packages/internal/database/src/drizzle/0021_wakeful_onslaught.sql similarity index 100% rename from apps/mobile/drizzle/0021_wakeful_onslaught.sql rename to packages/internal/database/src/drizzle/0021_wakeful_onslaught.sql diff --git a/apps/mobile/drizzle/meta/0000_snapshot.json b/packages/internal/database/src/drizzle/meta/0000_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0000_snapshot.json rename to packages/internal/database/src/drizzle/meta/0000_snapshot.json diff --git a/apps/mobile/drizzle/meta/0001_snapshot.json b/packages/internal/database/src/drizzle/meta/0001_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0001_snapshot.json rename to packages/internal/database/src/drizzle/meta/0001_snapshot.json diff --git a/apps/mobile/drizzle/meta/0002_snapshot.json b/packages/internal/database/src/drizzle/meta/0002_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0002_snapshot.json rename to packages/internal/database/src/drizzle/meta/0002_snapshot.json diff --git a/apps/mobile/drizzle/meta/0003_snapshot.json b/packages/internal/database/src/drizzle/meta/0003_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0003_snapshot.json rename to packages/internal/database/src/drizzle/meta/0003_snapshot.json diff --git a/apps/mobile/drizzle/meta/0004_snapshot.json b/packages/internal/database/src/drizzle/meta/0004_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0004_snapshot.json rename to packages/internal/database/src/drizzle/meta/0004_snapshot.json diff --git a/apps/mobile/drizzle/meta/0005_snapshot.json b/packages/internal/database/src/drizzle/meta/0005_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0005_snapshot.json rename to packages/internal/database/src/drizzle/meta/0005_snapshot.json diff --git a/apps/mobile/drizzle/meta/0006_snapshot.json b/packages/internal/database/src/drizzle/meta/0006_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0006_snapshot.json rename to packages/internal/database/src/drizzle/meta/0006_snapshot.json diff --git a/apps/mobile/drizzle/meta/0007_snapshot.json b/packages/internal/database/src/drizzle/meta/0007_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0007_snapshot.json rename to packages/internal/database/src/drizzle/meta/0007_snapshot.json diff --git a/apps/mobile/drizzle/meta/0008_snapshot.json b/packages/internal/database/src/drizzle/meta/0008_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0008_snapshot.json rename to packages/internal/database/src/drizzle/meta/0008_snapshot.json diff --git a/apps/mobile/drizzle/meta/0009_snapshot.json b/packages/internal/database/src/drizzle/meta/0009_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0009_snapshot.json rename to packages/internal/database/src/drizzle/meta/0009_snapshot.json diff --git a/apps/mobile/drizzle/meta/0010_snapshot.json b/packages/internal/database/src/drizzle/meta/0010_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0010_snapshot.json rename to packages/internal/database/src/drizzle/meta/0010_snapshot.json diff --git a/apps/mobile/drizzle/meta/0011_snapshot.json b/packages/internal/database/src/drizzle/meta/0011_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0011_snapshot.json rename to packages/internal/database/src/drizzle/meta/0011_snapshot.json diff --git a/apps/mobile/drizzle/meta/0012_snapshot.json b/packages/internal/database/src/drizzle/meta/0012_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0012_snapshot.json rename to packages/internal/database/src/drizzle/meta/0012_snapshot.json diff --git a/apps/mobile/drizzle/meta/0013_snapshot.json b/packages/internal/database/src/drizzle/meta/0013_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0013_snapshot.json rename to packages/internal/database/src/drizzle/meta/0013_snapshot.json diff --git a/apps/mobile/drizzle/meta/0014_snapshot.json b/packages/internal/database/src/drizzle/meta/0014_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0014_snapshot.json rename to packages/internal/database/src/drizzle/meta/0014_snapshot.json diff --git a/apps/mobile/drizzle/meta/0015_snapshot.json b/packages/internal/database/src/drizzle/meta/0015_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0015_snapshot.json rename to packages/internal/database/src/drizzle/meta/0015_snapshot.json diff --git a/apps/mobile/drizzle/meta/0016_snapshot.json b/packages/internal/database/src/drizzle/meta/0016_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0016_snapshot.json rename to packages/internal/database/src/drizzle/meta/0016_snapshot.json diff --git a/apps/mobile/drizzle/meta/0017_snapshot.json b/packages/internal/database/src/drizzle/meta/0017_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0017_snapshot.json rename to packages/internal/database/src/drizzle/meta/0017_snapshot.json diff --git a/apps/mobile/drizzle/meta/0018_snapshot.json b/packages/internal/database/src/drizzle/meta/0018_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0018_snapshot.json rename to packages/internal/database/src/drizzle/meta/0018_snapshot.json diff --git a/apps/mobile/drizzle/meta/0019_snapshot.json b/packages/internal/database/src/drizzle/meta/0019_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0019_snapshot.json rename to packages/internal/database/src/drizzle/meta/0019_snapshot.json diff --git a/apps/mobile/drizzle/meta/0020_snapshot.json b/packages/internal/database/src/drizzle/meta/0020_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0020_snapshot.json rename to packages/internal/database/src/drizzle/meta/0020_snapshot.json diff --git a/apps/mobile/drizzle/meta/0021_snapshot.json b/packages/internal/database/src/drizzle/meta/0021_snapshot.json similarity index 100% rename from apps/mobile/drizzle/meta/0021_snapshot.json rename to packages/internal/database/src/drizzle/meta/0021_snapshot.json diff --git a/apps/mobile/drizzle/meta/_journal.json b/packages/internal/database/src/drizzle/meta/_journal.json similarity index 100% rename from apps/mobile/drizzle/meta/_journal.json rename to packages/internal/database/src/drizzle/meta/_journal.json diff --git a/apps/mobile/drizzle/migrations.js b/packages/internal/database/src/drizzle/migrations.js similarity index 100% rename from apps/mobile/drizzle/migrations.js rename to packages/internal/database/src/drizzle/migrations.js diff --git a/packages/internal/database/src/migrator.ts b/packages/internal/database/src/migrator.ts new file mode 100644 index 000000000..39851156d --- /dev/null +++ b/packages/internal/database/src/migrator.ts @@ -0,0 +1,98 @@ +import { sql } from "drizzle-orm" +import type { SqliteRemoteDatabase } from "drizzle-orm/sqlite-proxy" + +interface MigrationConfig { + journal: MigrationJournal + migrations: Record + migrationsTable?: string +} + +interface MigrationJournal { + version: string + dialect: string + entries: { + idx: number + version: string + when: number + tag: string + breakpoints: boolean + }[] +} + +interface MigrationMeta { + sql: string[] + folderMillis: number + hash: string + bps: boolean +} + +// https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/expo-sqlite/migrator.ts +async function readMigrationFiles({ + journal, + migrations, +}: MigrationConfig): Promise { + const migrationQueries: MigrationMeta[] = [] + + for await (const journalEntry of journal.entries) { + const query = migrations[`m${journalEntry.idx.toString().padStart(4, "0")}`] + + if (!query) { + throw new Error(`Missing migration: ${journalEntry.tag}`) + } + + try { + const result = query.split("--> statement-breakpoint").map((it) => { + return it + }) + + migrationQueries.push({ + sql: result, + bps: journalEntry.breakpoints, + folderMillis: journalEntry.when, + hash: "", + }) + } catch { + throw new Error(`Failed to parse migration: ${journalEntry.tag}`) + } + } + + return migrationQueries +} + +// https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/sqlite-proxy/migrator.ts +export async function migrate>( + db: SqliteRemoteDatabase, + config: MigrationConfig, +) { + const migrations = await readMigrationFiles(config) + + const migrationTableCreate = sql` + CREATE TABLE IF NOT EXISTS "__drizzle_migrations" ( + id SERIAL PRIMARY KEY, + hash text NOT NULL, + created_at numeric + ) + ` + + await db.run(migrationTableCreate) + + const dbMigrations = await db.values<[number, string, string]>( + sql`SELECT id, hash, created_at FROM "__drizzle_migrations" ORDER BY created_at DESC LIMIT 1`, + ) + + const lastDbMigration = dbMigrations[0] ?? undefined + + const queriesToRun: string[] = [] + for (const migration of migrations) { + if (!lastDbMigration || Number(lastDbMigration[2])! < migration.folderMillis) { + queriesToRun.push( + ...migration.sql, + `INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES('${migration.hash}', '${migration.folderMillis}')`, + ) + } + } + + for (const query of queriesToRun) { + await db.run(sql.raw(query)) + } +} diff --git a/apps/mobile/src/database/schemas/index.ts b/packages/internal/database/src/schemas/index.ts similarity index 93% rename from apps/mobile/src/database/schemas/index.ts rename to packages/internal/database/src/schemas/index.ts index d5228f8ff..620f867b4 100644 --- a/apps/mobile/src/database/schemas/index.ts +++ b/packages/internal/database/src/schemas/index.ts @@ -1,16 +1,10 @@ import type { FeedViewType } from "@follow/constants" +import type { ActionSettings } from "@follow/models/src/types" +import type { SupportedActionLanguage } from "@follow/shared/src/language" import { sql } from "drizzle-orm" import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core" -import type { SupportedLanguages } from "@/src/lib/language" - -import type { - ActionSettings, - AttachmentsModel, - ExtraModel, - ImageColorsResult, - MediaModel, -} from "./types" +import type { AttachmentsModel, ExtraModel, ImageColorsResult, MediaModel } from "./types" export const feedsTable = sqliteTable("feeds", { id: text("id").primaryKey(), @@ -120,7 +114,7 @@ export const translationsTable = sqliteTable( "translations", (t) => ({ entryId: t.text("entry_id").notNull().primaryKey(), - language: t.text("language").$type().notNull(), + language: t.text("language").$type().notNull(), title: t.text("title"), description: t.text("description"), content: t.text("content"), diff --git a/apps/mobile/src/database/schemas/types.ts b/packages/internal/database/src/schemas/types.ts similarity index 66% rename from apps/mobile/src/database/schemas/types.ts rename to packages/internal/database/src/schemas/types.ts index 4165e5cd2..e2f2d1ce8 100644 --- a/apps/mobile/src/database/schemas/types.ts +++ b/packages/internal/database/src/schemas/types.ts @@ -1,5 +1,3 @@ -import type { HonoApiClient } from "@/src/morph/types" - import type { collectionsTable, entriesTable, @@ -36,8 +34,6 @@ export type TranslationSchema = typeof translationsTable.$inferInsert export type ImageSchema = typeof imagesTable.$inferInsert -export type ActionSettings = HonoApiClient.ActionSettings - export type MediaModel = { url: string type: "photo" | "video" @@ -63,4 +59,37 @@ export type ExtraModel = { }[] } -export { ImageColorsResult } from "react-native-image-colors" +// export { ImageColorsResult } from "react-native-image-colors" + +interface AndroidImageColors { + dominant: string + average: string + vibrant: string + darkVibrant: string + lightVibrant: string + darkMuted: string + lightMuted: string + muted: string + platform: "android" +} + +interface WebImageColors { + dominant: string + vibrant: string + darkVibrant: string + lightVibrant: string + darkMuted: string + lightMuted: string + muted: string + platform: "web" +} + +interface IOSImageColors { + background: string + primary: string + secondary: string + detail: string + platform: "ios" +} + +export type ImageColorsResult = AndroidImageColors | IOSImageColors | WebImageColors diff --git a/packages/internal/database/src/types.ts b/packages/internal/database/src/types.ts new file mode 100644 index 000000000..9b5e24bc0 --- /dev/null +++ b/packages/internal/database/src/types.ts @@ -0,0 +1,7 @@ +import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core/db" + +import type * as schema from "./schemas" + +export type DB = + | BaseSQLiteDatabase<"async", any, typeof schema> + | BaseSQLiteDatabase<"sync", any, typeof schema> diff --git a/packages/internal/database/tsconfig.json b/packages/internal/database/tsconfig.json new file mode 100644 index 000000000..bf6445b43 --- /dev/null +++ b/packages/internal/database/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@follow/configs/tsconfig.extend.json", + "compilerOptions": { + "types": ["vite/client"] + }, + "include": ["src/**/*", "drizzle.config.ts"] +} diff --git a/packages/internal/models/package.json b/packages/internal/models/package.json index 9426203fa..822716f6b 100644 --- a/packages/internal/models/package.json +++ b/packages/internal/models/package.json @@ -11,6 +11,11 @@ "import": "./src/rsshub.ts", "types": "./src/rsshub.ts" }, + "./src/*": { + "types": "./src/*.ts", + "require": "./src/*.ts", + "import": "./src/*.ts" + }, "./types": { "import": "./src/types.ts", "require": "./src/types.ts" diff --git a/packages/internal/models/src/types.ts b/packages/internal/models/src/types.ts index ff907f3a6..484cfe213 100644 --- a/packages/internal/models/src/types.ts +++ b/packages/internal/models/src/types.ts @@ -62,6 +62,8 @@ export type EntriesResponse = Array< | Exclude>["data"], undefined> >[number] +export type ActionSettings = Exclude + export type CombinedEntryModel = Omit & { entries: { content?: string | null @@ -88,6 +90,7 @@ export type DataResponse = { data?: T } +type Nullable = T | null | undefined export type ActiveEntryId = Nullable export type SubscriptionModel = ExtractBizResponse< diff --git a/packages/internal/shared/package.json b/packages/internal/shared/package.json index 16ad95a6a..ec2b40724 100644 --- a/packages/internal/shared/package.json +++ b/packages/internal/shared/package.json @@ -25,6 +25,11 @@ "types": "./src/interface/*.ts", "require": "./src/interface/*.ts", "import": "./src/interface/*.ts" + }, + "./src/*": { + "types": "./src/*.ts", + "require": "./src/*.ts", + "import": "./src/*.ts" } }, "main": "./exports.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f81ff93c..3042bda46 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -763,6 +763,9 @@ importers: '@follow/constants': specifier: workspace:* version: link:../../packages/internal/constants + '@follow/database': + specifier: workspace:* + version: link:../../packages/internal/database '@follow/hooks': specifier: workspace:* version: link:../../packages/internal/hooks @@ -1565,6 +1568,34 @@ importers: specifier: workspace:* version: link:../types + packages/internal/database: + dependencies: + '@follow/constants': + specifier: workspace:* + version: link:../constants + '@follow/models': + specifier: workspace:* + version: link:../models + '@follow/shared': + specifier: workspace:* + version: link:../shared + drizzle-orm: + specifier: 0.42.0 + version: 0.42.0(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.9(expo@53.0.4(@babel/core@7.26.10)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.13.5(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.27.6) + expo-sqlite: + specifier: 15.2.9 + version: 15.2.9(expo@53.0.4(@babel/core@7.26.10)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.13.5(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0) + sqlocal: + specifier: 0.14.1 + version: 0.14.1(bufferutil@4.0.9)(drizzle-orm@0.42.0(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.9(expo@53.0.4(@babel/core@7.26.10)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.13.5(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.27.6))(kysely@0.27.6) + devDependencies: + '@follow/configs': + specifier: workspace:* + version: link:../../configs + drizzle-kit: + specifier: 0.31.0 + version: 0.31.0 + packages/internal/hooks: dependencies: '@follow/shared': @@ -5901,6 +5932,10 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@sqlite.org/sqlite-wasm@3.49.1-build4': + resolution: {integrity: sha512-TBbTTWhiI6v2CT7J1hij5shx+RGL4iICprVGYhO+LKv5Nbn3NeJPWCY8kMKL5vA6b33NeWkBk4dy6RFbNh3jBw==} + hasBin: true + '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} @@ -6258,6 +6293,9 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@ungap/with-resolvers@0.1.0': + resolution: {integrity: sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==} + '@unocss/config@66.1.2': resolution: {integrity: sha512-2sQXj+Qaq4RVDELVTPoXMggZ30g1WKHeCuur396I12Ab0HgAR6bTc/DIrNtqKVHFI3mmlvP1oM1ynhKWSKPsTg==} engines: {node: '>=14'} @@ -7398,6 +7436,9 @@ packages: code-inspector-plugin@0.20.10: resolution: {integrity: sha512-G3aQ+t65N+rJlydPRUoG4vegjQb3seitCXCuNICUMhkDLetdVONLTASePVPCADv+fXl0vyW0hnZzAAxb9UnwOQ==} + coincident@1.2.3: + resolution: {integrity: sha512-Uxz3BMTWIslzeWjuQnizGWVg0j6khbvHUQ8+5BdM7WuJEm4ALXwq3wluYoB+uF68uPBz/oUOeJnYURKyfjexlA==} + collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -9558,6 +9599,9 @@ packages: resolution: {integrity: sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==} engines: {node: '>= 12'} + gc-hook@0.3.1: + resolution: {integrity: sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A==} + generate-function@2.3.1: resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} @@ -12571,6 +12615,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-target@3.0.2: + resolution: {integrity: sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ==} + public-encrypt@4.0.3: resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} @@ -13717,6 +13764,17 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + sqlocal@0.14.1: + resolution: {integrity: sha512-UhmNKWT7WBgJIrvp5JVuKAOOLXww4ZDVBfouPb/CIg/ONSCVPqaXFzwvTZ3vZY6SkfJLw9JCX+dZU+T1/orHmg==} + peerDependencies: + drizzle-orm: '*' + kysely: '*' + peerDependenciesMeta: + drizzle-orm: + optional: true + kysely: + optional: true + ssri@9.0.1: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -20106,7 +20164,7 @@ snapshots: debug: 2.6.9 invariant: 2.2.4 metro: 0.82.4(bufferutil@4.0.9) - metro-config: 0.82.4(bufferutil@4.0.9) + metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5) metro-core: 0.82.4 semver: 7.7.1 transitivePeerDependencies: @@ -20653,6 +20711,8 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@sqlite.org/sqlite-wasm@3.49.1-build4': {} + '@standard-schema/utils@0.3.0': {} '@stylistic/eslint-plugin@4.4.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)': @@ -21082,6 +21142,8 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@ungap/with-resolvers@0.1.0': {} + '@unocss/config@66.1.2': dependencies: '@unocss/core': 66.1.2 @@ -22524,6 +22586,18 @@ snapshots: transitivePeerDependencies: - supports-color + coincident@1.2.3(bufferutil@4.0.9): + dependencies: + '@ungap/structured-clone': 1.3.0 + '@ungap/with-resolvers': 0.1.0 + gc-hook: 0.3.1 + proxy-target: 3.0.2 + optionalDependencies: + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@6.0.5) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + collapse-white-space@2.1.0: {} color-convert@0.5.3: @@ -25280,6 +25354,8 @@ snapshots: transitivePeerDependencies: - supports-color + gc-hook@0.3.1: {} + generate-function@2.3.1: dependencies: is-property: 1.0.2 @@ -27174,21 +27250,6 @@ snapshots: transitivePeerDependencies: - supports-color - metro-config@0.82.4(bufferutil@4.0.9): - dependencies: - connect: 3.7.0 - cosmiconfig: 5.2.1 - flow-enums-runtime: 0.0.6 - jest-validate: 29.7.0 - metro: 0.82.4(bufferutil@4.0.9) - metro-cache: 0.82.4 - metro-core: 0.82.4 - metro-runtime: 0.82.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - metro-config@0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5): dependencies: connect: 3.7.0 @@ -27203,7 +27264,6 @@ snapshots: - bufferutil - supports-color - utf-8-validate - optional: true metro-core@0.82.4: dependencies: @@ -27315,7 +27375,6 @@ snapshots: - bufferutil - supports-color - utf-8-validate - optional: true metro@0.82.4(bufferutil@4.0.9): dependencies: @@ -27343,7 +27402,7 @@ snapshots: metro-babel-transformer: 0.82.4 metro-cache: 0.82.4 metro-cache-key: 0.82.4 - metro-config: 0.82.4(bufferutil@4.0.9) + metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5) metro-core: 0.82.4 metro-file-map: 0.82.4 metro-resolver: 0.82.4 @@ -27410,7 +27469,6 @@ snapshots: - bufferutil - supports-color - utf-8-validate - optional: true micromark-core-commonmark@2.0.3: dependencies: @@ -28791,6 +28849,8 @@ snapshots: proxy-from-env@1.1.0: {} + proxy-target@3.0.2: {} + public-encrypt@4.0.3: dependencies: bn.js: 4.12.2 @@ -30218,6 +30278,17 @@ snapshots: sprintf-js@1.1.3: {} + sqlocal@0.14.1(bufferutil@4.0.9)(drizzle-orm@0.42.0(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.9(expo@53.0.4(@babel/core@7.26.10)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.13.5(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.27.6))(kysely@0.27.6): + dependencies: + '@sqlite.org/sqlite-wasm': 3.49.1-build4 + coincident: 1.2.3(bufferutil@4.0.9) + optionalDependencies: + drizzle-orm: 0.42.0(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.9(expo@53.0.4(@babel/core@7.26.10)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.13.5(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.26.10)(@types/react@19.1.3)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.27.6) + kysely: 0.27.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + ssri@9.0.1: dependencies: minipass: 3.3.6