From 539893e24db5c36189d446a047efba1b0226cc0f Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Tue, 10 Feb 2026 13:39:26 -0500 Subject: [PATCH 1/6] chore(api): add minimal facade package --- apps/tlon-mobile/src/hooks/analytics.ts | 2 +- .../src/hooks/useBackgroundData.ts | 2 +- .../src/hooks/useNotificationListener.ts | 6 +- .../src/hooks/useOnboardingHelpers.ts | 2 +- .../src/hooks/useReviveSavedOnboarding.ts | 2 +- .../tlon-mobile/src/lib/OnboardingContext.tsx | 4 +- apps/tlon-mobile/src/lib/hostingAuth.ts | 2 +- apps/tlon-mobile/src/lib/signupContext.tsx | 2 +- .../src/screens/Onboarding/CheckOTPScreen.tsx | 2 +- .../screens/Onboarding/JoinWaitListScreen.tsx | 2 +- .../Onboarding/ResetPasswordScreen.tsx | 2 +- .../Onboarding/SetNotificationsScreen.tsx | 2 +- .../screens/Onboarding/ShipLoginScreen.tsx | 2 +- .../src/screens/Onboarding/SignupScreen.tsx | 2 +- .../src/screens/Onboarding/TlonLogin.tsx | 2 +- .../screens/Onboarding/TlonLoginLegacy.tsx | 2 +- apps/tlon-web/src/logic/utils.ts | 6 +- apps/tlon-web/src/main.tsx | 2 +- apps/tlon-web/src/mocks/chat.ts | 4 +- apps/tlon-web/src/mocks/groups.ts | 2 +- apps/tlon-web/src/mocks/handlers.ts | 4 +- apps/tlon-web/src/mocks/heaps.ts | 2 +- apps/tlon-web/src/state/settings.ts | 2 +- apps/tlon-web/src/window.ts | 2 +- packages/api/package.json | 28 ++ .../src/__tests__}/activity.test.ts | 24 +- .../src/__tests__}/contactsApi.test.ts | 5 +- .../__tests__/fixtures}/activityDmFeed.json | 0 .../fixtures}/activityDmReplyFeed.json | 0 .../fixtures}/activityInitFeeds.json | 0 .../__tests__/fixtures}/activityPostFeed.json | 0 .../fixtures}/activityReplyPostFeed.json | 0 .../fixtures}/channelPostWithReplies.json | 0 .../src/__tests__/fixtures}/channelPosts.json | 0 .../fixtures}/dmPostWithReplies.json | 0 .../fixtures}/groupDmPostWithReplies.json | 0 .../src/__tests__/fixtures}/groupsInit5.json | 0 .../api => api/src/__tests__}/initApi.test.ts | 4 +- .../src/__tests__}/postsApi.test.ts | 19 +- .../api => api/src/__tests__}/unreads.test.ts | 2 +- .../src/api => api/src/client}/activityApi.ts | 8 +- .../src/api => api/src/client}/apiUtils.ts | 2 +- .../src/api => api/src/client}/changesApi.ts | 2 +- .../src/client}/channelContentConfig.ts | 2 +- .../src/api => api/src/client}/channelsApi.ts | 6 +- .../src/api => api/src/client}/chatApi.ts | 4 +- .../src/api => api/src/client}/contactsApi.ts | 8 +- .../src/api => api/src/client}/groupsApi.ts | 12 +- .../src/api => api/src/client}/harkApi.ts | 2 +- .../src/api => api/src/client}/hostingApi.ts | 31 +- .../src/api => api/src/client}/index.ts | 4 +- .../src/api => api/src/client}/initApi.ts | 4 +- .../src/api => api/src/client}/inviteApi.ts | 4 +- .../api => api/src/client}/landscapeApi.ts | 0 .../src/api => api/src/client}/lanyardApi.ts | 9 +- .../src/api => api/src/client}/metagrabApi.ts | 27 +- .../src/api => api/src/client}/nounParsers.ts | 5 +- .../src/api => api/src/client}/postsApi.ts | 10 +- .../src/api => api/src/client}/settingsApi.ts | 2 +- .../src/api => api/src/client}/storageApi.ts | 0 .../src/client}/systemContactsApi.native.ts | 21 +- .../src/client}/systemContactsApi.ts | 2 +- .../src/api => api/src/client}/upload.ts | 0 .../src/api => api/src/client}/urbit.ts | 7 +- .../src/api => api/src/client}/vitalsApi.ts | 0 .../{shared => api}/src/http-api/Urbit.ts | 19 +- .../{shared => api}/src/http-api/events.ts | 0 .../src/http-api/fetch-event-source/fetch.ts | 0 .../src/http-api/fetch-event-source/index.ts | 0 .../src/http-api/fetch-event-source/parse.ts | 0 .../{shared => api}/src/http-api/index.ts | 0 .../{shared => api}/src/http-api/types.ts | 0 .../{shared => api}/src/http-api/utils.ts | 0 packages/api/src/index.ts | 1 + .../src/utils => api/src/lib}/EventEmitter.ts | 0 .../utils => api/src/lib}/ProgressManager.ts | 0 .../src/logic => api/src/lib}/activity.ts | 12 +- .../src/utils => api/src/lib}/assertNever.ts | 0 .../{shared/src/utils => api/src/lib}/blob.ts | 0 .../src/logic => api/src/lib}/branch.ts | 6 +- .../logic => api/src/lib}/content-helpers.ts | 34 +- .../src/logic => api/src/lib}/deeplinks.ts | 5 +- .../src/logic => api/src/lib}/featureFlags.ts | 0 .../{shared/src/utils => api/src/lib}/file.ts | 0 .../utils => api/src/lib}/formatMemorySize.ts | 30 +- .../src/logic => api/src/lib}/hosting.ts | 2 +- .../{shared/src/logic => api/src/lib}/noun.ts | 0 .../src/utils => api/src/lib}/number.ts | 0 .../src/utils => api/src/lib}/object.ts | 0 .../src/logic => api/src/lib}/pinning.ts | 0 .../src/logic => api/src/lib}/postContent.ts | 21 +- .../src/logic => api/src/lib}/references.ts | 6 +- .../src/utils => api/src/lib}/spyOn.ts | 0 .../src/lib}/telemetryFormatters.ts | 0 .../utils => api/src/lib}/timeoutSignal.ts | 0 .../src/logic => api/src/lib}/types.ts | 9 +- .../utils => api/src/lib}/utilityTypes.d.ts | 0 .../src/logic => api/src/lib}/utils.ts | 57 +-- .../src/logic => api/src/lib}/wayfinding.ts | 4 +- packages/api/src/test/setup.ts | 9 + .../src/types/ChannelActions.ts | 2 +- .../{shared => api}/src/types/JSONValue.ts | 0 .../src/types/PostCollectionConfiguration.ts | 4 +- packages/api/src/types/activityModels.ts | 69 ++++ .../src/domain => api/src/types}/analytics.ts | 0 .../domain => api/src/types}/attachment.ts | 20 +- .../domain => api/src/types}/attestations.ts | 0 packages/api/src/types/chatModels.ts | 332 ++++++++++++++++++ packages/api/src/types/clientModels.ts | 49 +++ packages/api/src/types/commonModels.ts | 15 + .../src/domain => api/src/types}/constants.ts | 6 + .../src/types}/groupTemplates.ts | 0 packages/{shared => api}/src/types/groups.ts | 0 .../src/domain => api/src/types}/hosting.ts | 0 packages/api/src/types/index.ts | 15 + .../domain => api/src/types}/invite.types.ts | 0 packages/{shared => api}/src/types/native.ts | 0 .../domain => api/src/types}/onboarding.ts | 0 .../src/domain => api/src/types}/post.ts | 3 +- .../domain => api/src/types}/references.ts | 0 .../src/domain => api/src/types}/system.ts | 0 packages/api/src/types/systemContactModels.ts | 40 +++ .../src/types}/systemContacts.ts | 0 packages/api/src/types/types.ts | 5 + .../src/domain => api/src/types}/uploads.ts | 0 .../domain => api/src/types}/wayfinding.ts | 0 .../{shared => api}/src/urbit/activity.ts | 4 +- packages/{shared => api}/src/urbit/channel.ts | 14 +- packages/{shared => api}/src/urbit/contact.ts | 0 packages/{shared => api}/src/urbit/content.ts | 2 +- packages/{shared => api}/src/urbit/dms.ts | 2 +- packages/{shared => api}/src/urbit/groups.ts | 0 packages/{shared => api}/src/urbit/hark.ts | 0 packages/{shared => api}/src/urbit/index.ts | 0 packages/{shared => api}/src/urbit/lanyard.ts | 0 packages/{shared => api}/src/urbit/meta.ts | 0 .../{shared => api}/src/urbit/metagrab.ts | 0 .../{shared => api}/src/urbit/negotiation.ts | 0 .../{shared => api}/src/urbit/settings.ts | 2 +- packages/{shared => api}/src/urbit/sigil.ts | 0 packages/{shared => api}/src/urbit/storage.ts | 2 +- packages/{shared => api}/src/urbit/ui.ts | 0 packages/{shared => api}/src/urbit/utils.ts | 10 +- packages/{shared => api}/src/urbit/vitals.ts | 0 packages/{shared => api}/src/urbit/volume.ts | 0 packages/api/tsconfig.json | 7 + packages/api/vitest.config.ts | 11 + packages/app/contexts/ship.tsx | 2 +- .../app/features/settings/AppInfoScreen.tsx | 2 +- .../features/settings/ManageAccountScreen.tsx | 2 +- .../PushNotificationSettingsScreen.tsx | 2 +- packages/app/features/top/ChannelScreen.tsx | 2 +- packages/app/features/top/ChatListScreen.tsx | 2 +- .../app/features/top/ChatVolumeScreen.tsx | 2 +- .../app/features/top/MessagesFilterMenu.tsx | 2 +- .../app/features/top/QueryBenchScreen.tsx | 4 +- packages/app/features/top/chatDetails.tsx | 2 +- .../features/top/useShipConnectionStatus.tsx | 4 +- packages/app/fixtures/Channel.fixture.tsx | 2 +- packages/app/fixtures/FixtureWrapper.tsx | 2 +- packages/app/fixtures/activityHelpers.tsx | 4 +- packages/app/fixtures/contentHelpers.tsx | 4 +- packages/app/fixtures/fakeData.ts | 2 +- packages/app/hooks/useBootSequence.ts | 4 +- packages/app/hooks/useConfigureUrbitClient.ts | 6 +- packages/app/hooks/useCurrentUser.native.ts | 2 +- packages/app/hooks/useDesktopNotifications.ts | 2 +- packages/app/hooks/useFilteredChats.ts | 2 +- packages/app/hooks/useGroupSearch.ts | 2 +- packages/app/hooks/useHandleLogout.native.ts | 2 +- packages/app/hooks/useHandleLogout.ts | 2 +- packages/app/hooks/useTelemetry.ts | 2 +- packages/app/lib/bootHelpers.ts | 2 +- packages/app/lib/devMenuItems.ts | 2 +- packages/app/lib/notificationsApi.ts | 2 +- .../app/navigation/desktop/HomeSidebar.tsx | 2 +- packages/app/provider/BaseProviderStack.tsx | 2 +- .../app/ui/components/BareChatInput/index.tsx | 4 +- packages/app/ui/components/BigInput.tsx | 2 +- .../ui/components/Channel/DraftInputView.tsx | 2 +- .../app/ui/components/Channel/PostView.tsx | 2 +- packages/app/ui/components/Channel/index.tsx | 4 +- .../ui/components/ChannelFromTemplateView.tsx | 2 +- .../ChatMessageActions/MessageActions.tsx | 2 +- .../app/ui/components/ChatOptionsSheet.tsx | 2 +- .../app/ui/components/ConnectionStatus.tsx | 2 +- .../ContentReference/ContentReference.tsx | 2 +- .../ui/components/EditableProfileImages.tsx | 2 +- .../ui/components/GroupMembersScreenView.tsx | 2 +- .../ManageChannels/CreateChannelSheet.tsx | 2 +- .../MessageInput/MessageInputBase.tsx | 2 +- .../app/ui/components/MessageInput/helpers.ts | 2 +- .../app/ui/components/MessageInput/index.tsx | 6 +- .../components/NotificationLevelSelector.tsx | 2 +- .../ui/components/PhoneAttestationPane.tsx | 2 +- .../app/ui/components/PostCollectionView.tsx | 2 +- packages/app/ui/components/PostScreenView.tsx | 6 +- .../ui/components/TwtitterAttestationPane.tsx | 2 +- .../ui/components/UserProfileScreenView.tsx | 2 +- .../ui/components/draftInputs/LinkInput.tsx | 2 +- .../app/ui/components/draftInputs/shared.ts | 2 +- packages/app/ui/contexts/chatOptions.tsx | 2 +- packages/app/ui/contexts/componentsKits.tsx | 2 +- packages/app/ui/hooks/contactSorters.ts | 2 +- packages/app/ui/utils/user.ts | 2 +- packages/editor/global.d.ts | 2 +- packages/scripts/src/index.ts | 6 +- packages/shared/package.json | 14 +- packages/shared/src/api/negotiationApi.ts | 0 packages/shared/src/db/changeListener.ts | 2 +- packages/shared/src/db/keyValue.ts | 4 +- packages/shared/src/db/modelBuilders.ts | 8 +- packages/shared/src/db/queries.test.ts | 6 +- packages/shared/src/db/queries.ts | 8 +- packages/shared/src/db/query.ts | 2 +- packages/shared/src/db/schema.ts | 4 +- packages/shared/src/db/storageItem.ts | 2 +- packages/shared/src/domain/index.ts | 28 +- packages/shared/src/electronAuth.ts | 72 ++++ packages/shared/src/electrtonAuth.ts | 73 +--- packages/shared/src/index.ts | 18 +- .../shared/src/logic/content-helpers.test.ts | 5 +- packages/shared/src/logic/embed.ts | 2 +- packages/shared/src/logic/index.ts | 26 +- packages/shared/src/logic/navigation.ts | 2 +- packages/shared/src/logic/pinning.test.ts | 2 +- packages/shared/src/logic/tiptap.test.ts | 2 +- packages/shared/src/logic/tiptap.ts | 8 +- packages/shared/src/logic/utils.test.ts | 4 +- packages/shared/src/store/activityActions.ts | 6 +- packages/shared/src/store/channelActions.ts | 8 +- packages/shared/src/store/clientActions.ts | 2 +- packages/shared/src/store/contactActions.ts | 2 +- packages/shared/src/store/dbHooks.ts | 8 +- packages/shared/src/store/dmActions.ts | 2 +- packages/shared/src/store/groupActions.ts | 9 +- packages/shared/src/store/hostingActions.ts | 2 +- packages/shared/src/store/inviteActions.ts | 6 +- packages/shared/src/store/lanyardActions.ts | 2 +- packages/shared/src/store/lure.ts | 6 +- packages/shared/src/store/metagrabActions.ts | 2 +- packages/shared/src/store/postActions.test.ts | 8 +- packages/shared/src/store/postActions.ts | 6 +- packages/shared/src/store/session.ts | 2 +- packages/shared/src/store/settingsActions.ts | 4 +- .../src/store/storage/storageActions.ts | 8 +- .../shared/src/store/storage/storageUtils.ts | 6 +- packages/shared/src/store/sync.test.ts | 19 +- packages/shared/src/store/sync.ts | 6 +- .../shared/src/store/useActivityFetchers.ts | 2 +- .../src/store/useChannelHooksPreview.ts | 4 +- packages/shared/src/store/useChannelPosts.ts | 2 +- packages/shared/src/store/useChannelSearch.ts | 2 +- packages/shared/src/store/useNegotiation.ts | 6 +- .../shared/src/store/usePostDraftCallbacks.ts | 2 +- packages/shared/src/test/helpers.ts | 2 +- packages/shared/src/test/setup.ts | 4 +- packages/shared/src/urbit/changes.ts | 0 .../utils/__tests__/formatMemorySize.test.ts | 8 +- packages/shared/src/utils/index.ts | 24 +- packages/shared/src/utils/useEventEmitter.ts | 2 +- pnpm-lock.yaml | 9 + 262 files changed, 1185 insertions(+), 583 deletions(-) create mode 100644 packages/api/package.json rename packages/{shared/src/api => api/src/__tests__}/activity.test.ts (88%) rename packages/{shared/src/api => api/src/__tests__}/contactsApi.test.ts (93%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/activityDmFeed.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/activityDmReplyFeed.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/activityInitFeeds.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/activityPostFeed.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/activityReplyPostFeed.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/channelPostWithReplies.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/channelPosts.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/dmPostWithReplies.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/groupDmPostWithReplies.json (100%) rename packages/{shared/src/test => api/src/__tests__/fixtures}/groupsInit5.json (100%) rename packages/{shared/src/api => api/src/__tests__}/initApi.test.ts (95%) rename packages/{shared/src/api => api/src/__tests__}/postsApi.test.ts (88%) rename packages/{shared/src/api => api/src/__tests__}/unreads.test.ts (99%) rename packages/{shared/src/api => api/src/client}/activityApi.ts (99%) rename packages/{shared/src/api => api/src/client}/apiUtils.ts (99%) rename packages/{shared/src/api => api/src/client}/changesApi.ts (98%) rename packages/{shared/src/api => api/src/client}/channelContentConfig.ts (99%) rename packages/{shared/src/api => api/src/client}/channelsApi.ts (99%) rename packages/{shared/src/api => api/src/client}/chatApi.ts (99%) rename packages/{shared/src/api => api/src/client}/contactsApi.ts (98%) rename packages/{shared/src/api => api/src/client}/groupsApi.ts (99%) rename packages/{shared/src/api => api/src/client}/harkApi.ts (95%) rename packages/{shared/src/api => api/src/client}/hostingApi.ts (94%) rename packages/{shared/src/api => api/src/client}/index.ts (88%) rename packages/{shared/src/api => api/src/client}/initApi.ts (97%) rename packages/{shared/src/api => api/src/client}/inviteApi.ts (95%) rename packages/{shared/src/api => api/src/client}/landscapeApi.ts (100%) rename packages/{shared/src/api => api/src/client}/lanyardApi.ts (98%) rename packages/{shared/src/api => api/src/client}/metagrabApi.ts (85%) rename packages/{shared/src/api => api/src/client}/nounParsers.ts (98%) rename packages/{shared/src/api => api/src/client}/postsApi.ts (99%) rename packages/{shared/src/api => api/src/client}/settingsApi.ts (99%) rename packages/{shared/src/api => api/src/client}/storageApi.ts (100%) rename packages/{shared/src/api => api/src/client}/systemContactsApi.native.ts (93%) rename packages/{shared/src/api => api/src/client}/systemContactsApi.ts (71%) rename packages/{shared/src/api => api/src/client}/upload.ts (100%) rename packages/{shared/src/api => api/src/client}/urbit.ts (98%) rename packages/{shared/src/api => api/src/client}/vitalsApi.ts (100%) rename packages/{shared => api}/src/http-api/Urbit.ts (98%) rename packages/{shared => api}/src/http-api/events.ts (100%) rename packages/{shared => api}/src/http-api/fetch-event-source/fetch.ts (100%) rename packages/{shared => api}/src/http-api/fetch-event-source/index.ts (100%) rename packages/{shared => api}/src/http-api/fetch-event-source/parse.ts (100%) rename packages/{shared => api}/src/http-api/index.ts (100%) rename packages/{shared => api}/src/http-api/types.ts (100%) rename packages/{shared => api}/src/http-api/utils.ts (100%) create mode 100644 packages/api/src/index.ts rename packages/{shared/src/utils => api/src/lib}/EventEmitter.ts (100%) rename packages/{shared/src/utils => api/src/lib}/ProgressManager.ts (100%) rename packages/{shared/src/logic => api/src/lib}/activity.ts (93%) rename packages/{shared/src/utils => api/src/lib}/assertNever.ts (100%) rename packages/{shared/src/utils => api/src/lib}/blob.ts (100%) rename packages/{shared/src/logic => api/src/lib}/branch.ts (97%) rename packages/{shared/src/logic => api/src/lib}/content-helpers.ts (96%) rename packages/{shared/src/logic => api/src/lib}/deeplinks.ts (97%) rename packages/{shared/src/logic => api/src/lib}/featureFlags.ts (100%) rename packages/{shared/src/utils => api/src/lib}/file.ts (100%) rename packages/{shared/src/utils => api/src/lib}/formatMemorySize.ts (62%) rename packages/{shared/src/logic => api/src/lib}/hosting.ts (85%) rename packages/{shared/src/logic => api/src/lib}/noun.ts (100%) rename packages/{shared/src/utils => api/src/lib}/number.ts (100%) rename packages/{shared/src/utils => api/src/lib}/object.ts (100%) rename packages/{shared/src/logic => api/src/lib}/pinning.ts (100%) rename packages/{shared/src/logic => api/src/lib}/postContent.ts (96%) rename packages/{shared/src/logic => api/src/lib}/references.ts (80%) rename packages/{shared/src/utils => api/src/lib}/spyOn.ts (100%) rename packages/{shared/src/utils => api/src/lib}/telemetryFormatters.ts (100%) rename packages/{shared/src/utils => api/src/lib}/timeoutSignal.ts (100%) rename packages/{shared/src/logic => api/src/lib}/types.ts (64%) rename packages/{shared/src/utils => api/src/lib}/utilityTypes.d.ts (100%) rename packages/{shared/src/logic => api/src/lib}/utils.ts (93%) rename packages/{shared/src/logic => api/src/lib}/wayfinding.ts (96%) create mode 100644 packages/api/src/test/setup.ts rename packages/{shared => api}/src/types/ChannelActions.ts (98%) rename packages/{shared => api}/src/types/JSONValue.ts (100%) rename packages/{shared => api}/src/types/PostCollectionConfiguration.ts (98%) create mode 100644 packages/api/src/types/activityModels.ts rename packages/{shared/src/domain => api/src/types}/analytics.ts (100%) rename packages/{shared/src/domain => api/src/types}/attachment.ts (95%) rename packages/{shared/src/domain => api/src/types}/attestations.ts (100%) create mode 100644 packages/api/src/types/chatModels.ts create mode 100644 packages/api/src/types/clientModels.ts create mode 100644 packages/api/src/types/commonModels.ts rename packages/{shared/src/domain => api/src/types}/constants.ts (86%) rename packages/{shared/src/domain => api/src/types}/groupTemplates.ts (100%) rename packages/{shared => api}/src/types/groups.ts (100%) rename packages/{shared/src/domain => api/src/types}/hosting.ts (100%) create mode 100644 packages/api/src/types/index.ts rename packages/{shared/src/domain => api/src/types}/invite.types.ts (100%) rename packages/{shared => api}/src/types/native.ts (100%) rename packages/{shared/src/domain => api/src/types}/onboarding.ts (100%) rename packages/{shared/src/domain => api/src/types}/post.ts (96%) rename packages/{shared/src/domain => api/src/types}/references.ts (100%) rename packages/{shared/src/domain => api/src/types}/system.ts (100%) create mode 100644 packages/api/src/types/systemContactModels.ts rename packages/{shared/src/domain => api/src/types}/systemContacts.ts (100%) create mode 100644 packages/api/src/types/types.ts rename packages/{shared/src/domain => api/src/types}/uploads.ts (100%) rename packages/{shared/src/domain => api/src/types}/wayfinding.ts (100%) rename packages/{shared => api}/src/urbit/activity.ts (99%) rename packages/{shared => api}/src/urbit/channel.ts (98%) rename packages/{shared => api}/src/urbit/contact.ts (100%) rename packages/{shared => api}/src/urbit/content.ts (99%) rename packages/{shared => api}/src/urbit/dms.ts (99%) rename packages/{shared => api}/src/urbit/groups.ts (100%) rename packages/{shared => api}/src/urbit/hark.ts (100%) rename packages/{shared => api}/src/urbit/index.ts (100%) rename packages/{shared => api}/src/urbit/lanyard.ts (100%) rename packages/{shared => api}/src/urbit/meta.ts (100%) rename packages/{shared => api}/src/urbit/metagrab.ts (100%) rename packages/{shared => api}/src/urbit/negotiation.ts (100%) rename packages/{shared => api}/src/urbit/settings.ts (98%) rename packages/{shared => api}/src/urbit/sigil.ts (100%) rename packages/{shared => api}/src/urbit/storage.ts (94%) rename packages/{shared => api}/src/urbit/ui.ts (100%) rename packages/{shared => api}/src/urbit/utils.ts (96%) rename packages/{shared => api}/src/urbit/vitals.ts (100%) rename packages/{shared => api}/src/urbit/volume.ts (100%) create mode 100644 packages/api/tsconfig.json create mode 100644 packages/api/vitest.config.ts delete mode 100644 packages/shared/src/api/negotiationApi.ts create mode 100644 packages/shared/src/electronAuth.ts delete mode 100644 packages/shared/src/urbit/changes.ts diff --git a/apps/tlon-mobile/src/hooks/analytics.ts b/apps/tlon-mobile/src/hooks/analytics.ts index 6199aa01be..f9e51f79cd 100644 --- a/apps/tlon-mobile/src/hooks/analytics.ts +++ b/apps/tlon-mobile/src/hooks/analytics.ts @@ -1,6 +1,6 @@ import { useLureMetadata } from '@tloncorp/app/contexts/branch'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as Contacts from 'expo-contacts'; import * as Notifications from 'expo-notifications'; diff --git a/apps/tlon-mobile/src/hooks/useBackgroundData.ts b/apps/tlon-mobile/src/hooks/useBackgroundData.ts index ed4a6585a1..ea98e5fbd4 100644 --- a/apps/tlon-mobile/src/hooks/useBackgroundData.ts +++ b/apps/tlon-mobile/src/hooks/useBackgroundData.ts @@ -1,5 +1,5 @@ import { createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { CHANGES_SYNCED_AT_KEY, registerStorageItemListener, diff --git a/apps/tlon-mobile/src/hooks/useNotificationListener.ts b/apps/tlon-mobile/src/hooks/useNotificationListener.ts index dad8dbc9a4..4762e49ff5 100644 --- a/apps/tlon-mobile/src/hooks/useNotificationListener.ts +++ b/apps/tlon-mobile/src/hooks/useNotificationListener.ts @@ -14,11 +14,11 @@ import { syncDms, syncGroups, } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as logic from '@tloncorp/shared/logic'; -import * as ub from '@tloncorp/shared/urbit'; -import { ActivityIncomingEvent } from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; +import { ActivityIncomingEvent } from '@tloncorp/api/urbit'; import { Notification, useLastNotificationResponse } from 'expo-notifications'; import { useEffect, useState } from 'react'; import { Platform } from 'react-native'; diff --git a/apps/tlon-mobile/src/hooks/useOnboardingHelpers.ts b/apps/tlon-mobile/src/hooks/useOnboardingHelpers.ts index aaa573311e..cc2f41e87f 100644 --- a/apps/tlon-mobile/src/hooks/useOnboardingHelpers.ts +++ b/apps/tlon-mobile/src/hooks/useOnboardingHelpers.ts @@ -10,7 +10,7 @@ import { scaffoldPersonalGroup, withRetry, } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { storage } from '@tloncorp/shared/db'; import * as db from '@tloncorp/shared/db'; import { useCallback } from 'react'; diff --git a/apps/tlon-mobile/src/hooks/useReviveSavedOnboarding.ts b/apps/tlon-mobile/src/hooks/useReviveSavedOnboarding.ts index e2b1b21930..17c8e72a72 100644 --- a/apps/tlon-mobile/src/hooks/useReviveSavedOnboarding.ts +++ b/apps/tlon-mobile/src/hooks/useReviveSavedOnboarding.ts @@ -2,7 +2,7 @@ import { NavigationProp, useNavigation } from '@react-navigation/native'; import { useLureMetadata } from '@tloncorp/app/contexts/branch'; import { useShip } from '@tloncorp/app/contexts/ship'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { signupData } from '@tloncorp/shared/db'; import * as db from '@tloncorp/shared/db'; import { SignupParams } from '@tloncorp/shared/domain'; diff --git a/apps/tlon-mobile/src/lib/OnboardingContext.tsx b/apps/tlon-mobile/src/lib/OnboardingContext.tsx index 9d8cd20e79..b40d0e56c8 100644 --- a/apps/tlon-mobile/src/lib/OnboardingContext.tsx +++ b/apps/tlon-mobile/src/lib/OnboardingContext.tsx @@ -3,8 +3,8 @@ import { execute, initClient, } from '@google-cloud/recaptcha-enterprise-react-native'; -import * as hostingApi from '@tloncorp/shared/api'; -import { getLandscapeAuthCookie } from '@tloncorp/shared/api'; +import * as hostingApi from '@tloncorp/api'; +import { getLandscapeAuthCookie } from '@tloncorp/api'; import { createContext, useContext } from 'react'; interface OnboardingContextValue { diff --git a/apps/tlon-mobile/src/lib/hostingAuth.ts b/apps/tlon-mobile/src/lib/hostingAuth.ts index ccce0074b0..464401d21f 100644 --- a/apps/tlon-mobile/src/lib/hostingAuth.ts +++ b/apps/tlon-mobile/src/lib/hostingAuth.ts @@ -1,7 +1,7 @@ import NetInfo from '@react-native-community/netinfo'; import CookieManager from '@react-native-cookies/cookies'; import { createDevLogger } from '@tloncorp/shared'; -import { getHostingHeartBeat } from '@tloncorp/shared/api'; +import { getHostingHeartBeat } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { getConstants } from '@tloncorp/shared/domain'; import { Platform } from 'react-native'; diff --git a/apps/tlon-mobile/src/lib/signupContext.tsx b/apps/tlon-mobile/src/lib/signupContext.tsx index a8113ff089..050adfaa49 100644 --- a/apps/tlon-mobile/src/lib/signupContext.tsx +++ b/apps/tlon-mobile/src/lib/signupContext.tsx @@ -3,7 +3,7 @@ import { useBootSequence } from '@tloncorp/app/hooks/useBootSequence'; import { connectNotifyProvider } from '@tloncorp/app/lib/notificationsApi'; import { createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { didSignUp, signupData } from '@tloncorp/shared/db'; import { AnalyticsEvent, diff --git a/apps/tlon-mobile/src/screens/Onboarding/CheckOTPScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/CheckOTPScreen.tsx index fed8ccce63..abf12db156 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/CheckOTPScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/CheckOTPScreen.tsx @@ -16,7 +16,7 @@ import { AnalyticsSeverity, createDevLogger, } from '@tloncorp/shared'; -import { HostingError } from '@tloncorp/shared/api'; +import { HostingError } from '@tloncorp/api'; import { storage } from '@tloncorp/shared/db'; import { useCallback, useMemo, useState } from 'react'; import { Platform } from 'react-native'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/JoinWaitListScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/JoinWaitListScreen.tsx index ec66030d7b..90034e0412 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/JoinWaitListScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/JoinWaitListScreen.tsx @@ -10,7 +10,7 @@ import { } from '@tloncorp/app/ui'; import { trackOnboardingAction } from '@tloncorp/app/utils/posthog'; import { createDevLogger } from '@tloncorp/shared'; -import { addUserToWaitlist } from '@tloncorp/shared/api'; +import { addUserToWaitlist } from '@tloncorp/api'; import { useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { Alert } from 'react-native'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/ResetPasswordScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/ResetPasswordScreen.tsx index 6c629b9cc5..1671eb716b 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/ResetPasswordScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/ResetPasswordScreen.tsx @@ -10,7 +10,7 @@ import { YStack, } from '@tloncorp/app/ui'; import { createDevLogger } from '@tloncorp/shared'; -import { requestPasswordReset } from '@tloncorp/shared/api'; +import { requestPasswordReset } from '@tloncorp/api'; import { useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/SetNotificationsScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/SetNotificationsScreen.tsx index 6fe2154252..a0311ddca5 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/SetNotificationsScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/SetNotificationsScreen.tsx @@ -7,7 +7,7 @@ import { View, YStack, } from '@tloncorp/app/ui'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { useCallback, useEffect, useState } from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/ShipLoginScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/ShipLoginScreen.tsx index 3bc1d0c8f2..45ac97349e 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/ShipLoginScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/ShipLoginScreen.tsx @@ -18,7 +18,7 @@ import { import { getShipFromCookie } from '@tloncorp/app/utils/ship'; import { transformShipURL } from '@tloncorp/app/utils/string'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; -import { getLandscapeAuthCookie } from '@tloncorp/shared/api'; +import { getLandscapeAuthCookie } from '@tloncorp/api'; import { storage } from '@tloncorp/shared/db'; import { useCallback, useEffect, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/SignupScreen.tsx b/apps/tlon-mobile/src/screens/Onboarding/SignupScreen.tsx index 408c203dd8..302247bffe 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/SignupScreen.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/SignupScreen.tsx @@ -26,7 +26,7 @@ import { AnalyticsSeverity, createDevLogger, } from '@tloncorp/shared'; -import { HostingError } from '@tloncorp/shared/api'; +import { HostingError } from '@tloncorp/api'; import { useCallback, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { Platform } from 'react-native'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/TlonLogin.tsx b/apps/tlon-mobile/src/screens/Onboarding/TlonLogin.tsx index 25b2d19230..271fb74af0 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/TlonLogin.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/TlonLogin.tsx @@ -18,7 +18,7 @@ import { } from '@tloncorp/app/ui'; import { Button } from '@tloncorp/ui'; import { createDevLogger } from '@tloncorp/shared'; -import { HostingError } from '@tloncorp/shared/api'; +import { HostingError } from '@tloncorp/api'; import { useCallback, useEffect, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; diff --git a/apps/tlon-mobile/src/screens/Onboarding/TlonLoginLegacy.tsx b/apps/tlon-mobile/src/screens/Onboarding/TlonLoginLegacy.tsx index 9a2889f14b..b799fe9a50 100644 --- a/apps/tlon-mobile/src/screens/Onboarding/TlonLoginLegacy.tsx +++ b/apps/tlon-mobile/src/screens/Onboarding/TlonLoginLegacy.tsx @@ -15,7 +15,7 @@ import { YStack, } from '@tloncorp/app/ui'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; -import { HostingError } from '@tloncorp/shared/api'; +import { HostingError } from '@tloncorp/api'; import { storage } from '@tloncorp/shared/db'; import { useCallback, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; diff --git a/apps/tlon-web/src/logic/utils.ts b/apps/tlon-web/src/logic/utils.ts index 610cfb2204..91373753ee 100644 --- a/apps/tlon-web/src/logic/utils.ts +++ b/apps/tlon-web/src/logic/utils.ts @@ -5,7 +5,7 @@ import { Verse, VerseBlock, VerseInline, -} from '@tloncorp/shared/urbit/channel'; +} from '@tloncorp/api/urbit/channel'; import { Bold, Cite, @@ -13,7 +13,7 @@ import { Italics, Listing, Strikethrough, -} from '@tloncorp/shared/urbit/content'; +} from '@tloncorp/api/urbit/content'; import { Cabals, ChannelPrivacyType, @@ -25,7 +25,7 @@ import { PrivacyType, Rank, Saga, -} from '@tloncorp/shared/urbit/groups'; +} from '@tloncorp/api/urbit/groups'; import { BigIntOrderedMap, Docket, diff --git a/apps/tlon-web/src/main.tsx b/apps/tlon-web/src/main.tsx index b26eefa516..3f4245afc3 100644 --- a/apps/tlon-web/src/main.tsx +++ b/apps/tlon-web/src/main.tsx @@ -13,7 +13,7 @@ import { RootErrorBoundary } from '@tloncorp/app/RootErrorBoundary'; import { ENABLED_LOGGERS } from '@tloncorp/app/constants'; import { loadConstants } from '@tloncorp/app/lib/constants'; import { addCustomEnabledLoggers, createDevLogger } from '@tloncorp/shared'; -import { QueryClientProvider, queryClient } from '@tloncorp/shared/api'; +import { QueryClientProvider, queryClient } from '@tloncorp/api'; import { PostHogProvider } from 'posthog-js/react'; import { createRoot } from 'react-dom/client'; diff --git a/apps/tlon-web/src/mocks/chat.ts b/apps/tlon-web/src/mocks/chat.ts index 1720087a61..701ded8ffe 100644 --- a/apps/tlon-web/src/mocks/chat.ts +++ b/apps/tlon-web/src/mocks/chat.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; -import { Activity } from '@tloncorp/shared/urbit/activity'; +import { Activity } from '@tloncorp/api/urbit/activity'; import { Post, Posts, Story, storyFromChatStory, -} from '@tloncorp/shared/urbit/channel'; +} from '@tloncorp/api/urbit/channel'; import { decToUd, unixToDa } from '@urbit/api'; import { subDays, subMinutes } from 'date-fns'; import _ from 'lodash'; diff --git a/apps/tlon-web/src/mocks/groups.ts b/apps/tlon-web/src/mocks/groups.ts index 21b0b53f89..6925474e51 100644 --- a/apps/tlon-web/src/mocks/groups.ts +++ b/apps/tlon-web/src/mocks/groups.ts @@ -8,7 +8,7 @@ import { GroupPreview, PrivacyType, Vessel, -} from '@tloncorp/shared/urbit/groups'; +} from '@tloncorp/api/urbit/groups'; import { AUTHORS } from '@/constants'; import { randomElement } from '@/logic/utils'; diff --git a/apps/tlon-web/src/mocks/handlers.ts b/apps/tlon-web/src/mocks/handlers.ts index 29fd4e0c2d..cfffac59ae 100644 --- a/apps/tlon-web/src/mocks/handlers.ts +++ b/apps/tlon-web/src/mocks/handlers.ts @@ -16,8 +16,8 @@ import { DMWhom, DmRsvp, WritDiff, -} from '@tloncorp/shared/urbit/dms'; -import { GroupActionV4 } from '@tloncorp/shared/urbit/groups'; +} from '@tloncorp/api/urbit/dms'; +import { GroupActionV4 } from '@tloncorp/api/urbit/groups'; import { decToUd, udToDec, unixToDa } from '@urbit/api'; import bigInt from 'big-integer'; import _ from 'lodash'; diff --git a/apps/tlon-web/src/mocks/heaps.ts b/apps/tlon-web/src/mocks/heaps.ts index 94e370ef51..e80042b6af 100644 --- a/apps/tlon-web/src/mocks/heaps.ts +++ b/apps/tlon-web/src/mocks/heaps.ts @@ -4,7 +4,7 @@ import { SubscriptionHandler, } from '@tloncorp/mock-http-api'; import { DraftInputId, PostContentRendererId } from '@tloncorp/shared'; -import { Channels, Perm, Posts } from '@tloncorp/shared/urbit/channel'; +import { Channels, Perm, Posts } from '@tloncorp/api/urbit/channel'; import { subMinutes } from 'date-fns'; const unixTime = subMinutes(new Date(), 1).getTime(); diff --git a/apps/tlon-web/src/state/settings.ts b/apps/tlon-web/src/state/settings.ts index c5eae4dfd1..bec10bd398 100644 --- a/apps/tlon-web/src/state/settings.ts +++ b/apps/tlon-web/src/state/settings.ts @@ -1,5 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { DisplayMode, SortMode } from '@tloncorp/shared/urbit/channel'; +import { DisplayMode, SortMode } from '@tloncorp/api/urbit/channel'; import { DelBucket, DelEntry, PutBucket, Value } from '@urbit/api'; import cookies from 'browser-cookies'; import produce from 'immer'; diff --git a/apps/tlon-web/src/window.ts b/apps/tlon-web/src/window.ts index bed0bf3bd6..c08136b6aa 100644 --- a/apps/tlon-web/src/window.ts +++ b/apps/tlon-web/src/window.ts @@ -1,5 +1,5 @@ import type { NativeWebViewOptions } from '@tloncorp/shared'; -import { Rope } from '@tloncorp/shared/urbit/hark'; +import { Rope } from '@tloncorp/api/urbit/hark'; declare global { interface Window { diff --git a/packages/api/package.json b/packages/api/package.json new file mode 100644 index 0000000000..9f0f3a3c52 --- /dev/null +++ b/packages/api/package.json @@ -0,0 +1,28 @@ +{ + "name": "@tloncorp/api", + "version": "0.0.1", + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./api": "./src/client/index.ts", + "./api/*": "./src/client/*.ts", + "./client": "./src/client/index.ts", + "./client/*": "./src/client/*.ts", + "./lib/utilityTypes": "./src/lib/utilityTypes.d.ts", + "./lib/*": "./src/lib/*.ts", + "./urbit": "./src/urbit/index.ts", + "./urbit/*": "./src/urbit/*.ts", + "./http-api": "./src/http-api/index.ts", + "./http-api/*": "./src/http-api/*.ts", + "./types/*": "./src/types/*.ts", + "./package.json": "./package.json" + }, + "scripts": { + "tsc": "tsc --noEmit" + }, + "dependencies": { + "@tloncorp/shared": "workspace:*" + } +} diff --git a/packages/shared/src/api/activity.test.ts b/packages/api/src/__tests__/activity.test.ts similarity index 88% rename from packages/shared/src/api/activity.test.ts rename to packages/api/src/__tests__/activity.test.ts index ec5ba14879..acc529756e 100644 --- a/packages/shared/src/api/activity.test.ts +++ b/packages/api/src/__tests__/activity.test.ts @@ -1,19 +1,17 @@ import { expect, test } from 'vitest'; -import * as db from '../db'; -import dmFeed from '../test/activityDmFeed.json'; -import dmReplyFeed from '../test/activityDmReplyFeed.json'; -import initActivityFeeds from '../test/activityInitFeeds.json'; -import channelPostFeed from '../test/activityPostFeed.json'; -import replyPostFeed from '../test/activityReplyPostFeed.json'; +import type { ActivityEvent } from '@tloncorp/shared/db/types'; +import dmFeed from './fixtures/activityDmFeed.json'; +import dmReplyFeed from './fixtures/activityDmReplyFeed.json'; +import initActivityFeeds from './fixtures/activityInitFeeds.json'; +import channelPostFeed from './fixtures/activityPostFeed.json'; +import replyPostFeed from './fixtures/activityReplyPostFeed.json'; import { fromFeedToActivityEvents, fromInitFeedToBucketedActivityEvents, -} from './activityApi'; +} from '../client/activityApi'; -// const dmFeed: ub.ActivityFeed = await import('../test/activityDmFeed.json'); - -const expectedDmEvent: db.ActivityEvent = { +const expectedDmEvent: ActivityEvent = { id: '170.141.184.506.853.323.579.606.989.072.752.443.392', sourceId: 'ship/~lisfed-hobtex-tinres-walmyr--donsut-toprep-fanfep-samzod', channelId: '~lisfed-hobtex-tinres-walmyr--donsut-toprep-fanfep-samzod', @@ -42,7 +40,7 @@ test('converts a DM activity event feed from server to client format', () => { expect(events[0]).toStrictEqual(expectedDmEvent); }); -const expectedPostEvent: db.ActivityEvent = { +const expectedPostEvent: ActivityEvent = { id: '170.141.184.506.853.155.647.879.036.981.225.717.760', sourceId: 'channel/chat/~lishul-marbyl-nisdeb-nalhec--motfed-lodmyn-tinfed-binzod/welcome-5870', @@ -75,7 +73,7 @@ test('converts a post activity event feed from server to client format', () => { expect(events[0]).toStrictEqual(expectedPostEvent); }); -const expectedReplyEvent: db.ActivityEvent = { +const expectedReplyEvent: ActivityEvent = { id: '170.141.184.506.852.591.480.642.042.887.720.140.800', sourceId: 'thread/chat/~lishul-marbyl-nisdeb-nalhec--motfed-lodmyn-tinfed-binzod/welcome-5870/170.141.184.506.852.591.089.314.701.116.289.581.056', @@ -110,7 +108,7 @@ test('converts a reply activity event feed from server to client format', () => expect(events[0]).toStrictEqual(expectedReplyEvent); }); -const expectedDmReplyEvent: db.ActivityEvent = { +const expectedDmReplyEvent: ActivityEvent = { id: '170.141.184.506.854.078.982.999.616.565.792.473.088', sourceId: 'dm-thread/~pondus-watbel/~lishul-marbyl-nisdeb-nalhec--motfed-lodmyn-tinfed-binzod/170.141.184.506.854.078.840.401.191.304.839.083.065', diff --git a/packages/shared/src/api/contactsApi.test.ts b/packages/api/src/__tests__/contactsApi.test.ts similarity index 93% rename from packages/shared/src/api/contactsApi.test.ts rename to packages/api/src/__tests__/contactsApi.test.ts index fab7749c30..4eaac47c6c 100644 --- a/packages/shared/src/api/contactsApi.test.ts +++ b/packages/api/src/__tests__/contactsApi.test.ts @@ -1,6 +1,9 @@ import { expect, test } from 'vitest'; -import { v0PeerToClientProfile, v0PeersToClientProfiles } from './contactsApi'; +import { + v0PeerToClientProfile, + v0PeersToClientProfiles, +} from '../client/contactsApi'; const inputContact: [string, any] = [ 'test', diff --git a/packages/shared/src/test/activityDmFeed.json b/packages/api/src/__tests__/fixtures/activityDmFeed.json similarity index 100% rename from packages/shared/src/test/activityDmFeed.json rename to packages/api/src/__tests__/fixtures/activityDmFeed.json diff --git a/packages/shared/src/test/activityDmReplyFeed.json b/packages/api/src/__tests__/fixtures/activityDmReplyFeed.json similarity index 100% rename from packages/shared/src/test/activityDmReplyFeed.json rename to packages/api/src/__tests__/fixtures/activityDmReplyFeed.json diff --git a/packages/shared/src/test/activityInitFeeds.json b/packages/api/src/__tests__/fixtures/activityInitFeeds.json similarity index 100% rename from packages/shared/src/test/activityInitFeeds.json rename to packages/api/src/__tests__/fixtures/activityInitFeeds.json diff --git a/packages/shared/src/test/activityPostFeed.json b/packages/api/src/__tests__/fixtures/activityPostFeed.json similarity index 100% rename from packages/shared/src/test/activityPostFeed.json rename to packages/api/src/__tests__/fixtures/activityPostFeed.json diff --git a/packages/shared/src/test/activityReplyPostFeed.json b/packages/api/src/__tests__/fixtures/activityReplyPostFeed.json similarity index 100% rename from packages/shared/src/test/activityReplyPostFeed.json rename to packages/api/src/__tests__/fixtures/activityReplyPostFeed.json diff --git a/packages/shared/src/test/channelPostWithReplies.json b/packages/api/src/__tests__/fixtures/channelPostWithReplies.json similarity index 100% rename from packages/shared/src/test/channelPostWithReplies.json rename to packages/api/src/__tests__/fixtures/channelPostWithReplies.json diff --git a/packages/shared/src/test/channelPosts.json b/packages/api/src/__tests__/fixtures/channelPosts.json similarity index 100% rename from packages/shared/src/test/channelPosts.json rename to packages/api/src/__tests__/fixtures/channelPosts.json diff --git a/packages/shared/src/test/dmPostWithReplies.json b/packages/api/src/__tests__/fixtures/dmPostWithReplies.json similarity index 100% rename from packages/shared/src/test/dmPostWithReplies.json rename to packages/api/src/__tests__/fixtures/dmPostWithReplies.json diff --git a/packages/shared/src/test/groupDmPostWithReplies.json b/packages/api/src/__tests__/fixtures/groupDmPostWithReplies.json similarity index 100% rename from packages/shared/src/test/groupDmPostWithReplies.json rename to packages/api/src/__tests__/fixtures/groupDmPostWithReplies.json diff --git a/packages/shared/src/test/groupsInit5.json b/packages/api/src/__tests__/fixtures/groupsInit5.json similarity index 100% rename from packages/shared/src/test/groupsInit5.json rename to packages/api/src/__tests__/fixtures/groupsInit5.json diff --git a/packages/shared/src/api/initApi.test.ts b/packages/api/src/__tests__/initApi.test.ts similarity index 95% rename from packages/shared/src/api/initApi.test.ts rename to packages/api/src/__tests__/initApi.test.ts index 4ec91280d9..b1eb9be396 100644 --- a/packages/shared/src/api/initApi.test.ts +++ b/packages/api/src/__tests__/initApi.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from 'vitest'; -import rawGroupsInit6 from '../test/groupsInit5.json'; +import rawGroupsInit6 from './fixtures/groupsInit5.json'; import type * as ub from '../urbit'; -import { toInitData } from './initApi'; +import { toInitData } from '../client/initApi'; const groupsInit6 = rawGroupsInit6 as unknown as ub.GroupsInit6; diff --git a/packages/shared/src/api/postsApi.test.ts b/packages/api/src/__tests__/postsApi.test.ts similarity index 88% rename from packages/shared/src/api/postsApi.test.ts rename to packages/api/src/__tests__/postsApi.test.ts index 905b07151e..e6c27b75d0 100644 --- a/packages/shared/src/api/postsApi.test.ts +++ b/packages/api/src/__tests__/postsApi.test.ts @@ -1,15 +1,16 @@ import { expect, test } from 'vitest'; -import { Post } from '../db'; -import rawChannelPostWithRepliesData from '../test/channelPostWithReplies.json'; -import rawChannelPostsData from '../test/channelPosts.json'; -import rawDmPostWithRepliesData from '../test/dmPostWithReplies.json'; -import rawGroupDmPostWithRepliesData from '../test/groupDmPostWithReplies.json'; -import { setupDatabaseTestSuite } from '../test/helpers'; +import type { Post } from '@tloncorp/shared/db/types'; +import rawChannelPostWithRepliesData from './fixtures/channelPostWithReplies.json'; +import rawChannelPostsData from './fixtures/channelPosts.json'; +import rawDmPostWithRepliesData from './fixtures/dmPostWithReplies.json'; +import rawGroupDmPostWithRepliesData from './fixtures/groupDmPostWithReplies.json'; import * as ub from '../urbit'; -import { toPostData, toPostReplyData, toPostsData } from './postsApi'; - -setupDatabaseTestSuite(); +import { + toPostData, + toPostReplyData, + toPostsData, +} from '../client/postsApi'; const botAuthor: ub.BotProfile = { ship: '~bot-test', diff --git a/packages/shared/src/api/unreads.test.ts b/packages/api/src/__tests__/unreads.test.ts similarity index 99% rename from packages/shared/src/api/unreads.test.ts rename to packages/api/src/__tests__/unreads.test.ts index 6b1e2b562e..756071d1e1 100644 --- a/packages/shared/src/api/unreads.test.ts +++ b/packages/api/src/__tests__/unreads.test.ts @@ -6,7 +6,7 @@ import { toClientUnreads, toGroupUnread, toThreadUnread, -} from './activityApi'; +} from '../client/activityApi'; const channelUnread: Record = { 'channel/chat/~lishul-marbyl-nisdeb-nalhec--motfed-lodmyn-tinfed-binzod/welcome-5870': diff --git a/packages/shared/src/api/activityApi.ts b/packages/api/src/client/activityApi.ts similarity index 99% rename from packages/shared/src/api/activityApi.ts rename to packages/api/src/client/activityApi.ts index 9ac1a16aaa..7d304e4af2 100644 --- a/packages/shared/src/api/activityApi.ts +++ b/packages/api/src/client/activityApi.ts @@ -1,10 +1,10 @@ import { da } from '@urbit/aura'; import { backOff } from 'exponential-backoff'; -import * as db from '../db'; -import { BASE_UNREADS_SINGLETON_KEY } from '../db/schema'; -import { createDevLogger, runIfDev } from '../debug'; -import { normalizeUrbitColor } from '../logic'; +import * as db from '@tloncorp/shared/db'; +import { BASE_UNREADS_SINGLETON_KEY } from '@tloncorp/shared/db/schema'; +import { createDevLogger, runIfDev } from '@tloncorp/shared/debug'; +import { normalizeUrbitColor } from '../lib/utils'; import * as ub from '../urbit'; import { formatUd, diff --git a/packages/shared/src/api/apiUtils.ts b/packages/api/src/client/apiUtils.ts similarity index 99% rename from packages/shared/src/api/apiUtils.ts rename to packages/api/src/client/apiUtils.ts index d32a0b6176..26048b0289 100644 --- a/packages/shared/src/api/apiUtils.ts +++ b/packages/api/src/client/apiUtils.ts @@ -6,7 +6,7 @@ import { } from '@urbit/aura'; import bigInt from 'big-integer'; -import * as db from '../db/types'; +import * as db from '@tloncorp/shared/db/types'; import type * as ub from '../urbit'; import { BadResponseError } from './urbit'; diff --git a/packages/shared/src/api/changesApi.ts b/packages/api/src/client/changesApi.ts similarity index 98% rename from packages/shared/src/api/changesApi.ts rename to packages/api/src/client/changesApi.ts index 4fe8a81d25..3e0510b944 100644 --- a/packages/shared/src/api/changesApi.ts +++ b/packages/api/src/client/changesApi.ts @@ -1,6 +1,6 @@ import { da, render } from '@urbit/aura'; -import * as db from '../db'; +import * as db from '@tloncorp/shared/db'; import * as ub from '../urbit'; import { toClientUnreads } from './activityApi'; import { contactToClientProfile } from './contactsApi'; diff --git a/packages/shared/src/api/channelContentConfig.ts b/packages/api/src/client/channelContentConfig.ts similarity index 99% rename from packages/shared/src/api/channelContentConfig.ts rename to packages/api/src/client/channelContentConfig.ts index 88e0bf2c4a..2ebb786708 100644 --- a/packages/shared/src/api/channelContentConfig.ts +++ b/packages/api/src/client/channelContentConfig.ts @@ -1,5 +1,5 @@ import type { JSONValue } from '../types/JSONValue'; -import { ValuesOf } from '../utils'; +import { ValuesOf } from '../lib/utilityTypes'; interface BaseParameterSpec { displayName: string; diff --git a/packages/shared/src/api/channelsApi.ts b/packages/api/src/client/channelsApi.ts similarity index 99% rename from packages/shared/src/api/channelsApi.ts rename to packages/api/src/client/channelsApi.ts index bcb704fd8b..845f8fd876 100644 --- a/packages/shared/src/api/channelsApi.ts +++ b/packages/api/src/client/channelsApi.ts @@ -1,12 +1,12 @@ import { render, da } from '@urbit/aura'; import { Poke } from '@urbit/http-api'; -import * as db from '../db'; -import { createDevLogger } from '../debug'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; import * as ub from '../urbit'; import { Action, ChannelsAction, Posts } from '../urbit'; import { encodeString } from '../urbit/utils'; -import { Stringified } from '../utils'; +import { Stringified } from '../lib/utilityTypes'; import { getCanonicalPostId, getChannelIdType, diff --git a/packages/shared/src/api/chatApi.ts b/packages/api/src/client/chatApi.ts similarity index 99% rename from packages/shared/src/api/chatApi.ts rename to packages/api/src/client/chatApi.ts index a0aa7d810d..2afeb26edd 100644 --- a/packages/shared/src/api/chatApi.ts +++ b/packages/api/src/client/chatApi.ts @@ -1,5 +1,5 @@ -import * as db from '../db'; -import { createDevLogger } from '../debug'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; import * as ub from '../urbit'; import { deriveFullWrit, diff --git a/packages/shared/src/api/contactsApi.ts b/packages/api/src/client/contactsApi.ts similarity index 98% rename from packages/shared/src/api/contactsApi.ts rename to packages/api/src/client/contactsApi.ts index 5094243864..50df75a1a0 100644 --- a/packages/shared/src/api/contactsApi.ts +++ b/packages/api/src/client/contactsApi.ts @@ -1,7 +1,7 @@ -import * as db from '../db'; -import { createDevLogger } from '../debug'; -import { AnalyticsEvent } from '../domain'; -import { normalizeUrbitColor } from '../logic'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { AnalyticsEvent } from '../types/analytics'; +import { normalizeUrbitColor } from '../lib/utils'; import * as ub from '../urbit'; import { parseAttestationId } from './lanyardApi'; import * as NounParsers from './nounParsers'; diff --git a/packages/shared/src/api/groupsApi.ts b/packages/api/src/client/groupsApi.ts similarity index 99% rename from packages/shared/src/api/groupsApi.ts rename to packages/api/src/client/groupsApi.ts index 21cc66e58f..61fbe5b1f6 100644 --- a/packages/shared/src/api/groupsApi.ts +++ b/packages/api/src/client/groupsApi.ts @@ -1,10 +1,10 @@ import { Poke } from '@urbit/http-api'; -import * as db from '../db'; -import { GroupPrivacy } from '../db/schema'; -import { createDevLogger } from '../debug'; -import * as domain from '../domain'; -import { AnalyticsEvent, AnalyticsSeverity } from '../domain'; +import * as db from '@tloncorp/shared/db'; +import { GroupPrivacy } from '@tloncorp/shared/db/schema'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { AnalyticsEvent, AnalyticsSeverity } from '../types/analytics'; +import { PersonalGroupSlugs } from '../types/wayfinding'; import type * as ub from '../urbit'; import { FlaggedContent, @@ -1686,7 +1686,7 @@ export function toClientGroupV7( currentUserIsMember: isJoined, currentUserIsHost: hostUserId === currentUserId, isPersonalGroup: - id === `${currentUserId}/${domain.PersonalGroupSlugs.slug}`, + id === `${currentUserId}/${PersonalGroupSlugs.slug}`, joinStatus: undefined, // v7 groups from init are already joined hostUserId, flaggedPosts, diff --git a/packages/shared/src/api/harkApi.ts b/packages/api/src/client/harkApi.ts similarity index 95% rename from packages/shared/src/api/harkApi.ts rename to packages/api/src/client/harkApi.ts index 4ee59d1c28..b0b5be9f3d 100644 --- a/packages/shared/src/api/harkApi.ts +++ b/packages/api/src/client/harkApi.ts @@ -1,4 +1,4 @@ -import { createDevLogger } from '../debug'; +import { createDevLogger } from '@tloncorp/shared/debug'; import { getCanonicalPostId } from './apiUtils'; const logger = createDevLogger('harkApi', true); diff --git a/packages/shared/src/api/hostingApi.ts b/packages/api/src/client/hostingApi.ts similarity index 94% rename from packages/shared/src/api/hostingApi.ts rename to packages/api/src/client/hostingApi.ts index 330e966fa2..a1bef0a99a 100644 --- a/packages/shared/src/api/hostingApi.ts +++ b/packages/api/src/client/hostingApi.ts @@ -1,17 +1,18 @@ import { Buffer } from 'buffer'; -import * as db from '../db'; -import { createDevLogger } from '../debug'; -import * as domain from '../domain'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; import { - AnalyticsEvent, + AssignmentResponse, + HostedNodeStatus, HostedShipResponse, ReservableShip, ReservedShip, User, - getConstants, -} from '../domain'; -import { withRetry } from '../logic'; +} from '../types/hosting'; +import { AnalyticsEvent } from '../types/analytics'; +import { getConstants } from '../types/constants'; +import { withRetry } from '../lib/utils'; const logger = createDevLogger('hostingApi', false); @@ -432,7 +433,7 @@ export const verifyEmailDigits = async (email: string, digits: string) => hostingFetch(`/v1/verify-email-digits/${email}/${digits}`); export const assignShipToUser = async (userId: string) => { - const response = await hostingFetch( + const response = await hostingFetch( `/v1/users/${userId}/assign-ship`, { method: 'PATCH', @@ -516,7 +517,7 @@ export const bootShip = async (shipId: string) => export const getNodeStatus = async ( nodeId: string -): Promise<{ status: domain.HostedNodeStatus; showWayfinding: boolean }> => { +): Promise<{ status: HostedNodeStatus; showWayfinding: boolean }> => { let result = null; try { result = await getShip(nodeId); @@ -531,7 +532,7 @@ export const getNodeStatus = async ( // If user has a ready ship, let's use it if (nodeStatus === 'Ready') { - return { status: domain.HostedNodeStatus.Running, showWayfinding }; + return { status: HostedNodeStatus.Running, showWayfinding }; } // If user has a paused ship, resume it @@ -539,11 +540,11 @@ export const getNodeStatus = async ( if (!isBooting) { await resumeShip(nodeId); } - return { status: domain.HostedNodeStatus.Paused, showWayfinding }; + return { status: HostedNodeStatus.Paused, showWayfinding }; } if (nodeStatus === 'UnderMaintenance' || manualUpdateNeeded) { - return { status: domain.HostedNodeStatus.UnderMaintenance, showWayfinding }; + return { status: HostedNodeStatus.UnderMaintenance, showWayfinding }; } // If user has a suspended ship, boot it @@ -559,17 +560,17 @@ export const getNodeStatus = async ( err.message.includes(MANUAL_UPDATE_REQUIRED_MESSAGE) ) { return { - status: domain.HostedNodeStatus.UnderMaintenance, + status: HostedNodeStatus.UnderMaintenance, showWayfinding, }; } throw err; } } - return { status: domain.HostedNodeStatus.Suspended, showWayfinding }; + return { status: HostedNodeStatus.Suspended, showWayfinding }; } - return { status: domain.HostedNodeStatus.Unknown, showWayfinding }; + return { status: HostedNodeStatus.Unknown, showWayfinding }; }; export const inviteShipWithLure = async (params: { diff --git a/packages/shared/src/api/index.ts b/packages/api/src/client/index.ts similarity index 88% rename from packages/shared/src/api/index.ts rename to packages/api/src/client/index.ts index 59f2506fc7..d61e4d1fc9 100644 --- a/packages/shared/src/api/index.ts +++ b/packages/api/src/client/index.ts @@ -7,8 +7,7 @@ export * from './groupsApi'; export * from './landscapeApi'; export * from './postsApi'; export * from './urbit'; -export * from './postsApi'; -export * from '../store/reactQuery'; +export { QueryClientProvider, queryClient } from '@tloncorp/shared/store/reactQuery'; export * from './initApi'; export * from './upload'; export * from './settingsApi'; @@ -23,4 +22,3 @@ export * from './apiUtils'; export * from './systemContactsApi'; export * from './metagrabApi'; export * from './changesApi'; -export * from './vitalsApi'; diff --git a/packages/shared/src/api/initApi.ts b/packages/api/src/client/initApi.ts similarity index 97% rename from packages/shared/src/api/initApi.ts rename to packages/api/src/client/initApi.ts index 4f7b96740c..813257f10e 100644 --- a/packages/shared/src/api/initApi.ts +++ b/packages/api/src/client/initApi.ts @@ -1,5 +1,5 @@ -import * as db from '../db'; -import { createDevLogger } from '../debug'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; import type * as ub from '../urbit'; import { toClientUnreads } from './activityApi'; import { ChannelInit, toClientChannelsInit } from './channelsApi'; diff --git a/packages/shared/src/api/inviteApi.ts b/packages/api/src/client/inviteApi.ts similarity index 95% rename from packages/shared/src/api/inviteApi.ts rename to packages/api/src/client/inviteApi.ts index 8ff46c8d69..3d52800773 100644 --- a/packages/shared/src/api/inviteApi.ts +++ b/packages/api/src/client/inviteApi.ts @@ -1,5 +1,5 @@ -import * as db from '../db'; -import { InviteLinkMetadata } from '../domain/invite.types'; +import * as db from '@tloncorp/shared/db'; +import { InviteLinkMetadata } from '../types/invite.types'; import { GroupMeta } from '../urbit'; import { getCurrentUserId, poke, subscribeOnce } from './urbit'; diff --git a/packages/shared/src/api/landscapeApi.ts b/packages/api/src/client/landscapeApi.ts similarity index 100% rename from packages/shared/src/api/landscapeApi.ts rename to packages/api/src/client/landscapeApi.ts diff --git a/packages/shared/src/api/lanyardApi.ts b/packages/api/src/client/lanyardApi.ts similarity index 98% rename from packages/shared/src/api/lanyardApi.ts rename to packages/api/src/client/lanyardApi.ts index 9edcb6def2..a43276b90c 100644 --- a/packages/shared/src/api/lanyardApi.ts +++ b/packages/api/src/client/lanyardApi.ts @@ -1,10 +1,11 @@ import { render, parse } from '@urbit/aura'; import { Atom, Cell, Noun, dejs, dwim, enjs } from '@urbit/nockjs'; -import * as db from '../db'; -import { createDevLogger } from '../debug'; -import { AnalyticsEvent } from '../domain'; -import { Json, getFrondValue, getPatp, simpleHash } from '../logic'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { simpleHash } from '../lib/utils'; +import { Json, getFrondValue, getPatp } from '../lib/noun'; +import { AnalyticsEvent } from '../types/analytics'; import * as ub from '../urbit'; import { encodeString } from '../urbit'; import * as NounParsers from './nounParsers'; diff --git a/packages/shared/src/api/metagrabApi.ts b/packages/api/src/client/metagrabApi.ts similarity index 85% rename from packages/shared/src/api/metagrabApi.ts rename to packages/api/src/client/metagrabApi.ts index b989a136b1..7b752b93b3 100644 --- a/packages/shared/src/api/metagrabApi.ts +++ b/packages/api/src/client/metagrabApi.ts @@ -1,17 +1,18 @@ import { render } from '@urbit/aura'; import { Atom } from '@urbit/nockjs'; -import { createDevLogger } from '../debug'; -import * as domain from '../domain'; -import { getConstants } from '../domain'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import type { LinkMetadata, LinkMetadataError } from '../types/attachment'; +import { getConstants } from '../types/constants'; import * as ub from '../urbit'; +import { AnalyticsEvent } from '../types/analytics'; import { request } from './urbit'; const logger = createDevLogger('metagrabApi', false); export async function getLinkMetadata( url: string -): Promise { +): Promise { try { const encodedUrl = render('uw', Atom.fromCord(url).number); logger.log('encoded', { url, encodedUrl }); @@ -26,7 +27,7 @@ export async function getLinkMetadata( logger.log('metagrab response', response); if (response.status !== 200) { - logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, { + logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, { message: `bad metagrab response: ${response.status}`, response, }); @@ -35,17 +36,17 @@ export async function getLinkMetadata( const parsed = parseLinkMetadataResponse(url, response); if (parsed.type === 'error') { - logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, { + logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, { message: `metagrab error: ${parsed.reason}`, response, parsedResponse: parsed, }); } else { - logger.trackEvent(domain.AnalyticsEvent.FetchLinkMetadata); + logger.trackEvent(AnalyticsEvent.FetchLinkMetadata); } return parsed; } catch (error) { - logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, error); + logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, error); return { type: 'error', reason: 'unknown error' }; } } @@ -53,7 +54,7 @@ export async function getLinkMetadata( function parseLinkMetadataResponse( url: string, response: ub.LinkMetadataResponse -): domain.LinkMetadata | domain.LinkMetadataError { +): LinkMetadata | LinkMetadataError { const { result } = response; if (!result) { return { type: 'redirect' }; @@ -73,7 +74,7 @@ function parseLinkMetadataResponse( const siteDescription = description?.[0]?.value; const imageData = parseImageData(url, image ?? []); - const parsed: domain.LinkMetadata = { + const parsed: LinkMetadata = { type: 'page', url, siteIconUrl, @@ -89,7 +90,7 @@ function parseLinkMetadataResponse( } if (result.type === 'file') { - const parsed: domain.LinkMetadata = { + const parsed: LinkMetadata = { type: 'file', url, mime: result.mime, @@ -140,7 +141,7 @@ function parseImageData(url: string, data: ub.LinkMetadataItem[]) { export async function getFallbackLinkMetadata( url: string -): Promise { +): Promise { try { const env = getConstants(); const response = await fetch(`${env.INVITE_SERVICE_ENDPOINT}/linkPreview`, { @@ -158,7 +159,7 @@ export async function getFallbackLinkMetadata( throw new Error('fallback link meta payload invalid'); } - const meta: domain.LinkMetadata = { + const meta: LinkMetadata = { type: 'page', url, siteIconUrl: payload.siteIconUrl || '', diff --git a/packages/shared/src/api/nounParsers.ts b/packages/api/src/client/nounParsers.ts similarity index 98% rename from packages/shared/src/api/nounParsers.ts rename to packages/api/src/client/nounParsers.ts index b3c4b79bab..e1b3d8e2d4 100644 --- a/packages/shared/src/api/nounParsers.ts +++ b/packages/api/src/client/nounParsers.ts @@ -2,8 +2,9 @@ import { parse, render, da } from '@urbit/aura'; import { Atom, Cell, Noun, cue, dwim, enjs, jam } from '@urbit/nockjs'; import _ from 'lodash'; -import * as db from '../db'; -import { getFrondValue, getPatp, simpleHash } from '../logic'; +import * as db from '@tloncorp/shared/db'; +import { simpleHash } from '../lib/utils'; +import { getFrondValue, getPatp } from '../lib/noun'; import * as ub from '../urbit'; interface HalfSign { diff --git a/packages/shared/src/api/postsApi.ts b/packages/api/src/client/postsApi.ts similarity index 99% rename from packages/shared/src/api/postsApi.ts rename to packages/api/src/client/postsApi.ts index 6c0770b0e3..13f08f36b5 100644 --- a/packages/shared/src/api/postsApi.ts +++ b/packages/api/src/client/postsApi.ts @@ -1,15 +1,15 @@ import { da, render } from '@urbit/aura'; import { Poke } from '@urbit/http-api'; -import * as db from '../db'; -import { createDevLogger } from '../debug'; -import { ContentReference } from '../domain'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { IMAGE_URL_REGEX } from '../lib/utils'; import { - IMAGE_URL_REGEX, PlaintextPreviewConfig, getTextContent, -} from '../logic'; +} from '../lib/postContent'; import * as ub from '../urbit'; +import { ContentReference } from '../types/references'; import { ClubAction, DmAction, diff --git a/packages/shared/src/api/settingsApi.ts b/packages/api/src/client/settingsApi.ts similarity index 99% rename from packages/shared/src/api/settingsApi.ts rename to packages/api/src/client/settingsApi.ts index 232e7c9646..0e31ea1826 100644 --- a/packages/shared/src/api/settingsApi.ts +++ b/packages/api/src/client/settingsApi.ts @@ -1,4 +1,4 @@ -import * as db from '../db'; +import * as db from '@tloncorp/shared/db'; import * as ub from '../urbit'; import { poke, scry, subscribe } from './urbit'; diff --git a/packages/shared/src/api/storageApi.ts b/packages/api/src/client/storageApi.ts similarity index 100% rename from packages/shared/src/api/storageApi.ts rename to packages/api/src/client/storageApi.ts diff --git a/packages/shared/src/api/systemContactsApi.native.ts b/packages/api/src/client/systemContactsApi.native.ts similarity index 93% rename from packages/shared/src/api/systemContactsApi.native.ts rename to packages/api/src/client/systemContactsApi.native.ts index 952814ef59..2a4b3f1462 100644 --- a/packages/shared/src/api/systemContactsApi.native.ts +++ b/packages/api/src/client/systemContactsApi.native.ts @@ -2,9 +2,10 @@ import * as Contacts from 'expo-contacts'; import * as Localization from 'expo-localization'; import * as LibPhone from 'libphonenumber-js'; -import * as db from '../db'; -import { createDevLogger } from '../debug'; -import * as domain from '../domain'; +import * as db from '@tloncorp/shared/db'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import type { SystemContact } from '../types/systemContacts'; +import { AnalyticsEvent, AnalyticsSeverity } from '../types/analytics'; const logger = createDevLogger('SystemContactsApi', true); @@ -21,9 +22,9 @@ export async function getSystemContacts(): Promise { }); nativeContactBook = data; } catch (e) { - logger.trackEvent(domain.AnalyticsEvent.ErrorSystemContacts, { + logger.trackEvent(AnalyticsEvent.ErrorSystemContacts, { context: 'failed to get native contacts', - severity: domain.AnalyticsSeverity.High, + severity: AnalyticsSeverity.High, }); return []; } @@ -31,9 +32,9 @@ export async function getSystemContacts(): Promise { const processedContacts = parseNativeContacts(nativeContactBook); return processedContacts; } catch (e) { - logger.trackEvent(domain.AnalyticsEvent.ErrorSystemContacts, { + logger.trackEvent(AnalyticsEvent.ErrorSystemContacts, { context: 'failed to parse native contacts', - severity: domain.AnalyticsSeverity.High, + severity: AnalyticsSeverity.High, }); return []; } @@ -41,7 +42,7 @@ export async function getSystemContacts(): Promise { export function parseNativeContacts( nativeContacts: Contacts.Contact[] -): domain.SystemContact[] { +): SystemContact[] { const parseCounts = { digitFinds: 0, numberFinds: 0, fallbacks: 0 }; let defaultCountryCode = 'US'; @@ -52,7 +53,7 @@ export function parseNativeContacts( logger.log(`Inferred system default country code: ${defaultCountryCode}`); } } catch (e) { - logger.trackEvent(domain.AnalyticsEvent.DebugSystemContacts, { + logger.trackEvent(AnalyticsEvent.DebugSystemContacts, { context: 'Could not infer system default country code', }); } @@ -203,7 +204,7 @@ export function parseNativeContacts( }) .filter((num): num is string => num !== null); - const sysContact: domain.SystemContact = { + const sysContact: SystemContact = { id: contact.id!, firstName: contact.firstName, lastName: contact.lastName, diff --git a/packages/shared/src/api/systemContactsApi.ts b/packages/api/src/client/systemContactsApi.ts similarity index 71% rename from packages/shared/src/api/systemContactsApi.ts rename to packages/api/src/client/systemContactsApi.ts index 8e0a887ebc..2ba4e6912e 100644 --- a/packages/shared/src/api/systemContactsApi.ts +++ b/packages/api/src/client/systemContactsApi.ts @@ -1,4 +1,4 @@ -import * as db from '../db'; +import * as db from '@tloncorp/shared/db'; export async function getSystemContacts(): Promise { // stub for web diff --git a/packages/shared/src/api/upload.ts b/packages/api/src/client/upload.ts similarity index 100% rename from packages/shared/src/api/upload.ts rename to packages/api/src/client/upload.ts diff --git a/packages/shared/src/api/urbit.ts b/packages/api/src/client/urbit.ts similarity index 98% rename from packages/shared/src/api/urbit.ts rename to packages/api/src/client/urbit.ts index 3686a0006b..36b79a60ef 100644 --- a/packages/shared/src/api/urbit.ts +++ b/packages/api/src/client/urbit.ts @@ -1,9 +1,8 @@ import { Noun } from '@urbit/nockjs'; import _ from 'lodash'; -import { createDevLogger, escapeLog, runIfDev } from '../debug'; -import { AnalyticsEvent, getConstants } from '../domain'; -import * as Hosting from '../domain/hosting'; +import { createDevLogger, escapeLog, runIfDev } from '@tloncorp/shared/debug'; +import { getConstants } from '../types/constants'; import { AuthError, ChannelStatus, @@ -13,6 +12,8 @@ import { Urbit, } from '../http-api'; import { preSig } from '../urbit'; +import { AnalyticsEvent } from '../types/analytics'; +import * as Hosting from '../types/hosting'; import { getLandscapeAuthCookie } from './landscapeApi'; const logger = createDevLogger('urbit', false); diff --git a/packages/shared/src/api/vitalsApi.ts b/packages/api/src/client/vitalsApi.ts similarity index 100% rename from packages/shared/src/api/vitalsApi.ts rename to packages/api/src/client/vitalsApi.ts diff --git a/packages/shared/src/http-api/Urbit.ts b/packages/api/src/http-api/Urbit.ts similarity index 98% rename from packages/shared/src/http-api/Urbit.ts rename to packages/api/src/http-api/Urbit.ts index d4719995dc..278ac152f1 100644 --- a/packages/shared/src/http-api/Urbit.ts +++ b/packages/api/src/http-api/Urbit.ts @@ -1,13 +1,12 @@ import { parse, render } from '@urbit/aura'; import { Atom, Cell, Noun, dejs, enjs, jam } from '@urbit/nockjs'; -import { isBrowser } from 'browser-or-node'; -import { TimeoutError } from '../api'; -import { createDevLogger } from '../debug'; +import { TimeoutError } from '../client'; +import { createDevLogger } from '@tloncorp/shared/debug'; import { desig } from '../urbit'; -import { readArrayBufferFromBlob } from '../utils'; -import * as utils from '../utils'; -import { EventEmitter } from '../utils/EventEmitter'; +import { readArrayBufferFromBlob } from '../lib/blob'; +import { createTimeoutSignal } from '../lib/timeoutSignal'; +import { EventEmitter } from '../lib/EventEmitter'; import { UrbitHttpApiEvent, UrbitHttpApiEventType } from './events'; import { EventSourceMessage, @@ -36,6 +35,8 @@ import { import { hexString, unpackJamBytes } from './utils'; const logger = createDevLogger('UrbitHttpApi', false); +const isBrowser = + typeof window !== 'undefined' && typeof window.document !== 'undefined'; //TODO move into nockjs utils function isNoun(a: any): a is Noun { @@ -923,7 +924,7 @@ export class Urbit { result: T; }> { const { app, path, timeout } = params; - const signal = timeout ? utils.createTimeoutSignal(timeout) : undefined; + const signal = timeout ? createTimeoutSignal(timeout) : undefined; const response = await this.fetchFn( `${this.url}/~/scry/${app}${path}.json`, { @@ -1014,7 +1015,7 @@ export class Urbit { throw new Error('Must supply desk to run thread from'); } - const signal = timeout ? utils.createTimeoutSignal(timeout) : undefined; + const signal = timeout ? createTimeoutSignal(timeout) : undefined; const result = await this.fetchFn( `${this.url}/spider/${desk}/${inputMark}/${threadName}/${outputMark}`, @@ -1073,7 +1074,7 @@ export class Urbit { path = '/' + path; } - const signal = timeout ? utils.createTimeoutSignal(timeout) : undefined; + const signal = timeout ? createTimeoutSignal(timeout) : undefined; // Prepare request options with authentication const requestOptions: RequestInit = { ...this.fetchOptions, diff --git a/packages/shared/src/http-api/events.ts b/packages/api/src/http-api/events.ts similarity index 100% rename from packages/shared/src/http-api/events.ts rename to packages/api/src/http-api/events.ts diff --git a/packages/shared/src/http-api/fetch-event-source/fetch.ts b/packages/api/src/http-api/fetch-event-source/fetch.ts similarity index 100% rename from packages/shared/src/http-api/fetch-event-source/fetch.ts rename to packages/api/src/http-api/fetch-event-source/fetch.ts diff --git a/packages/shared/src/http-api/fetch-event-source/index.ts b/packages/api/src/http-api/fetch-event-source/index.ts similarity index 100% rename from packages/shared/src/http-api/fetch-event-source/index.ts rename to packages/api/src/http-api/fetch-event-source/index.ts diff --git a/packages/shared/src/http-api/fetch-event-source/parse.ts b/packages/api/src/http-api/fetch-event-source/parse.ts similarity index 100% rename from packages/shared/src/http-api/fetch-event-source/parse.ts rename to packages/api/src/http-api/fetch-event-source/parse.ts diff --git a/packages/shared/src/http-api/index.ts b/packages/api/src/http-api/index.ts similarity index 100% rename from packages/shared/src/http-api/index.ts rename to packages/api/src/http-api/index.ts diff --git a/packages/shared/src/http-api/types.ts b/packages/api/src/http-api/types.ts similarity index 100% rename from packages/shared/src/http-api/types.ts rename to packages/api/src/http-api/types.ts diff --git a/packages/shared/src/http-api/utils.ts b/packages/api/src/http-api/utils.ts similarity index 100% rename from packages/shared/src/http-api/utils.ts rename to packages/api/src/http-api/utils.ts diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts new file mode 100644 index 0000000000..4f1cce44fa --- /dev/null +++ b/packages/api/src/index.ts @@ -0,0 +1 @@ +export * from './client'; diff --git a/packages/shared/src/utils/EventEmitter.ts b/packages/api/src/lib/EventEmitter.ts similarity index 100% rename from packages/shared/src/utils/EventEmitter.ts rename to packages/api/src/lib/EventEmitter.ts diff --git a/packages/shared/src/utils/ProgressManager.ts b/packages/api/src/lib/ProgressManager.ts similarity index 100% rename from packages/shared/src/utils/ProgressManager.ts rename to packages/api/src/lib/ProgressManager.ts diff --git a/packages/shared/src/logic/activity.ts b/packages/api/src/lib/activity.ts similarity index 93% rename from packages/shared/src/logic/activity.ts rename to packages/api/src/lib/activity.ts index 60a73933dd..35060d8a6d 100644 --- a/packages/shared/src/logic/activity.ts +++ b/packages/api/src/lib/activity.ts @@ -1,5 +1,5 @@ -import * as db from '../db'; -import { ActivityEvent } from '../db'; +import type { ActivityEvent } from '@tloncorp/shared/db/types'; +import type * as db from '@tloncorp/shared/db/types'; import { ExtendedEventType, NotificationLevel, @@ -96,10 +96,10 @@ export function toSourceActivityEvents( // "source" if it hasn't already been added const individualMentionKey = `${key}/${event.postId}`; if (!eventMap.has(individualMentionKey)) { - const mentionSource = { + const mentionSource: SourceActivityEvents = { newest: event, all: [event], - type: event.type, + type: event.type as ExtendedEventType, sourceId: `${event.sourceId}/${event.postId}`, }; eventMap.set(individualMentionKey, mentionSource); @@ -112,10 +112,10 @@ export function toSourceActivityEvents( } } else { // Create a new entry in the map - const newRollup = { + const newRollup: SourceActivityEvents = { newest: event, all: [event], - type: event.type, + type: event.type as ExtendedEventType, sourceId: event.sourceId, }; eventMap.set(key, newRollup); diff --git a/packages/shared/src/utils/assertNever.ts b/packages/api/src/lib/assertNever.ts similarity index 100% rename from packages/shared/src/utils/assertNever.ts rename to packages/api/src/lib/assertNever.ts diff --git a/packages/shared/src/utils/blob.ts b/packages/api/src/lib/blob.ts similarity index 100% rename from packages/shared/src/utils/blob.ts rename to packages/api/src/lib/blob.ts diff --git a/packages/shared/src/logic/branch.ts b/packages/api/src/lib/branch.ts similarity index 97% rename from packages/shared/src/logic/branch.ts rename to packages/api/src/lib/branch.ts index 6ae24490de..73db3b07b6 100644 --- a/packages/shared/src/logic/branch.ts +++ b/packages/api/src/lib/branch.ts @@ -1,8 +1,8 @@ import { valid } from '@urbit/aura'; -import { getPostInfoFromWer } from '../api/harkApi'; -import { createDevLogger } from '../debug'; -import { getConstants } from '../domain'; +import { getPostInfoFromWer } from '../client/harkApi'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { getConstants } from '../types/constants'; import { preSig } from '../urbit'; import { normalizeUrbitColor } from './utils'; diff --git a/packages/shared/src/logic/content-helpers.ts b/packages/api/src/lib/content-helpers.ts similarity index 96% rename from packages/shared/src/logic/content-helpers.ts rename to packages/api/src/lib/content-helpers.ts index 39cc280dfa..a7d13e8927 100644 --- a/packages/shared/src/logic/content-helpers.ts +++ b/packages/api/src/lib/content-helpers.ts @@ -1,14 +1,14 @@ import isURL from 'validator/lib/isURL'; -import { ChannelType, PostMetadata } from '../db'; -import { createDevLogger } from '../debug'; -import { +import type { ChannelType, PostMetadata } from '@tloncorp/shared/db/types'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import type { FinalizedAttachment, LinkAttachment, ReferenceAttachment, - UploadedFileAttachment, UploadedImageAttachment, -} from '../domain'; +} from '../types/attachment'; +import { UploadedFileAttachment } from '../types/attachment'; import { Block, Inline, @@ -17,8 +17,28 @@ import { constructStory, pathToCite, } from '../urbit'; -import { fileFromPath } from '../utils/file'; -import { makeMention, makeParagraph, makeText } from './tiptap'; +import { fileFromPath } from './file'; + +// Inlined from tiptap.ts to avoid @tiptap dependency +const makeText = (t: string) => ({ type: 'text', text: t }); +const makeMention = (id: string) => ({ + type: 'mention', + attrs: { id }, +}); +const makeParagraph = (content?: JSONContent[]): JSONContent => { + const p = { type: 'paragraph' }; + if (!content) { + return p; + } + if ( + content.length > 0 && + content[0].type === 'text' && + content[0].text === '' + ) { + return p; + } + return { ...p, content }; +}; const logger = createDevLogger('content-helpers', false); diff --git a/packages/shared/src/logic/deeplinks.ts b/packages/api/src/lib/deeplinks.ts similarity index 97% rename from packages/shared/src/logic/deeplinks.ts rename to packages/api/src/lib/deeplinks.ts index 3815c55cd3..95d2f8c03e 100644 --- a/packages/shared/src/logic/deeplinks.ts +++ b/packages/api/src/lib/deeplinks.ts @@ -1,5 +1,6 @@ -import { createDevLogger } from '../debug'; -import { ContentReference, getConstants } from '../domain'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import type { ContentReference } from '../types/references'; +import { getConstants } from '../types/constants'; import { citeToPath } from '../urbit'; import { AppInvite, getBranchLinkMeta, isLureMeta } from './branch'; import { normalizeUrbitColor } from './utils'; diff --git a/packages/shared/src/logic/featureFlags.ts b/packages/api/src/lib/featureFlags.ts similarity index 100% rename from packages/shared/src/logic/featureFlags.ts rename to packages/api/src/lib/featureFlags.ts diff --git a/packages/shared/src/utils/file.ts b/packages/api/src/lib/file.ts similarity index 100% rename from packages/shared/src/utils/file.ts rename to packages/api/src/lib/file.ts diff --git a/packages/shared/src/utils/formatMemorySize.ts b/packages/api/src/lib/formatMemorySize.ts similarity index 62% rename from packages/shared/src/utils/formatMemorySize.ts rename to packages/api/src/lib/formatMemorySize.ts index 6c6ed26e4e..0878abeb84 100644 --- a/packages/shared/src/utils/formatMemorySize.ts +++ b/packages/api/src/lib/formatMemorySize.ts @@ -1,16 +1,14 @@ /** maps available units to how many bytes fit in one unit, ordered by preference */ -const unitToBytes = [ +const unitToBytes: Array<{ + unit: string; + /** how many bytes fit in one unit */ + bytes: number; +}> = [ { unit: 'gb', bytes: Math.pow(1024, 3) }, { unit: 'mb', bytes: Math.pow(1024, 2) }, { unit: 'kb', bytes: Math.pow(1024, 1) }, { unit: 'b', bytes: Math.pow(1024, 0) }, -] as const satisfies Array<{ - unit: string; - /** how many bytes fit in one unit */ - bytes: number; -}>; - -type Unit = (typeof unitToBytes)[number]['unit']; +]; /** * @example @@ -28,19 +26,3 @@ export function formatMemorySize(bytes: number): string { unitToBytes.find((x) => bytes / x.bytes >= 1) ?? unitToBytes.at(-1)!; return format(bytes / matchingUnit.bytes, matchingUnit.unit); } - -/** - * @example - * ```ts - * convert(1, 'kb').to('b') === 1024 - * convert(1, 'gb').to('mb') === 1024 - * ``` - */ -export function convert(value: number, fromUnit: Unit) { - return { - to: (toUnit: Unit) => - value * - (unitToBytes.find((u) => u.unit === fromUnit)!.bytes / - unitToBytes.find((u) => u.unit === toUnit)!.bytes), - }; -} diff --git a/packages/shared/src/logic/hosting.ts b/packages/api/src/lib/hosting.ts similarity index 85% rename from packages/shared/src/logic/hosting.ts rename to packages/api/src/lib/hosting.ts index 3e945e40db..b0896c3863 100644 --- a/packages/shared/src/logic/hosting.ts +++ b/packages/api/src/lib/hosting.ts @@ -1,4 +1,4 @@ -import { getConstants } from '../domain'; +import { getConstants } from '../types/constants'; export const SHIP_COOKIE_REGEX = /(~)[a-z\-]+?(\=)/; diff --git a/packages/shared/src/logic/noun.ts b/packages/api/src/lib/noun.ts similarity index 100% rename from packages/shared/src/logic/noun.ts rename to packages/api/src/lib/noun.ts diff --git a/packages/shared/src/utils/number.ts b/packages/api/src/lib/number.ts similarity index 100% rename from packages/shared/src/utils/number.ts rename to packages/api/src/lib/number.ts diff --git a/packages/shared/src/utils/object.ts b/packages/api/src/lib/object.ts similarity index 100% rename from packages/shared/src/utils/object.ts rename to packages/api/src/lib/object.ts diff --git a/packages/shared/src/logic/pinning.ts b/packages/api/src/lib/pinning.ts similarity index 100% rename from packages/shared/src/logic/pinning.ts rename to packages/api/src/lib/pinning.ts diff --git a/packages/shared/src/logic/postContent.ts b/packages/api/src/lib/postContent.ts similarity index 96% rename from packages/shared/src/logic/postContent.ts rename to packages/api/src/lib/postContent.ts index 81b062d748..0f18cecb4f 100644 --- a/packages/shared/src/logic/postContent.ts +++ b/packages/api/src/lib/postContent.ts @@ -1,7 +1,7 @@ -import * as api from '../api'; -import { ContentReference } from '../domain'; +import { toContentReference } from '../client/postsApi'; +import type { ContentReference } from '../types/references'; import * as ub from '../urbit'; -import { assertNever } from '../utils'; +import { assertNever } from './assertNever'; import { PostBlobDataEntry, parsePostBlob } from './content-helpers'; import { VIDEO_REGEX, containsOnlyEmoji } from './utils'; @@ -161,6 +161,7 @@ export type BlockFromType = Extract< >; export type PostContent = BlockData[]; +type ApiPostContent = (ub.Verse | ContentReference)[] | null; export interface PlaintextPreviewConfig { blockSeparator: string; @@ -337,7 +338,7 @@ export function convertContent( return out; } - const story: api.PostContent = + const story: ApiPostContent = typeof input === 'string' ? JSON.parse(input) : input; if (!story) { @@ -353,7 +354,7 @@ export function convertContent( * applies more type strictness at callsite. */ export function convertContentSafe( - story: Exclude + story: Exclude ): PostContent { const blocks: PostContent = []; for (const verse of story) { @@ -490,9 +491,7 @@ function convertBlock(block: ub.Block): BlockData { }; } case is(block, 'cite'): { - return ( - api.toContentReference(block.cite) ?? errorMessage('Failed to parse') - ); + return toContentReference(block.cite) ?? errorMessage('Failed to parse'); } case is(block, 'link'): { return { @@ -644,15 +643,15 @@ export function appendInline( } export function getTextContent( - postContent: Exclude, + postContent: Exclude, config?: PlaintextPreviewConfig ): string; export function getTextContent( - postContent: api.PostContent, + postContent: ApiPostContent, config?: PlaintextPreviewConfig ): string | null; export function getTextContent( - postContent: api.PostContent, + postContent: ApiPostContent, config: PlaintextPreviewConfig = PlaintextPreviewConfig.defaultConfig ): string | null { return postContent == null diff --git a/packages/shared/src/logic/references.ts b/packages/api/src/lib/references.ts similarity index 80% rename from packages/shared/src/logic/references.ts rename to packages/api/src/lib/references.ts index ffa9837350..eed16c6162 100644 --- a/packages/shared/src/logic/references.ts +++ b/packages/api/src/lib/references.ts @@ -1,6 +1,6 @@ -import * as db from '../db'; -import { ContentReference } from '../domain'; -import { parseIdNumber } from '../api/apiUtils'; +import type * as db from '@tloncorp/shared/db/types'; +import type { ContentReference } from '../types/references'; +import { parseIdNumber } from '../client/apiUtils'; function formatId(id: string) { return parseIdNumber(id).toString(); diff --git a/packages/shared/src/utils/spyOn.ts b/packages/api/src/lib/spyOn.ts similarity index 100% rename from packages/shared/src/utils/spyOn.ts rename to packages/api/src/lib/spyOn.ts diff --git a/packages/shared/src/utils/telemetryFormatters.ts b/packages/api/src/lib/telemetryFormatters.ts similarity index 100% rename from packages/shared/src/utils/telemetryFormatters.ts rename to packages/api/src/lib/telemetryFormatters.ts diff --git a/packages/shared/src/utils/timeoutSignal.ts b/packages/api/src/lib/timeoutSignal.ts similarity index 100% rename from packages/shared/src/utils/timeoutSignal.ts rename to packages/api/src/lib/timeoutSignal.ts diff --git a/packages/shared/src/logic/types.ts b/packages/api/src/lib/types.ts similarity index 64% rename from packages/shared/src/logic/types.ts rename to packages/api/src/lib/types.ts index a20887b376..d930b39712 100644 --- a/packages/shared/src/logic/types.ts +++ b/packages/api/src/lib/types.ts @@ -1,4 +1,4 @@ -import * as db from '../db'; +import type * as db from '@tloncorp/shared/db/types'; export function isChatChannel(channel: db.Channel): boolean { return ( @@ -8,13 +8,6 @@ export function isChatChannel(channel: db.Channel): boolean { ); } -/** - * Ordered posts are the canonical backend source for pinned posts. - */ -export function getPinnedPostId(channel: db.Channel): string | null { - return channel.order?.[0] ?? null; -} - export function isChannel(obj: db.Channel | db.Group): obj is db.Channel { return !('hostUserId' in obj); } diff --git a/packages/shared/src/utils/utilityTypes.d.ts b/packages/api/src/lib/utilityTypes.d.ts similarity index 100% rename from packages/shared/src/utils/utilityTypes.d.ts rename to packages/api/src/lib/utilityTypes.d.ts diff --git a/packages/shared/src/logic/utils.ts b/packages/api/src/lib/utils.ts similarity index 93% rename from packages/shared/src/logic/utils.ts rename to packages/api/src/lib/utils.ts index dd232338f7..e1f5e3e701 100644 --- a/packages/shared/src/logic/utils.ts +++ b/packages/api/src/lib/utils.ts @@ -3,18 +3,18 @@ import anyAscii from 'any-ascii'; import { differenceInDays, endOfToday, format } from 'date-fns'; import emojiRegex from 'emoji-regex'; import { BackoffOptions, backOff } from 'exponential-backoff'; -import { useMemo } from 'react'; -import * as api from '../api'; +import * as api from '../client'; import { isDmChannelId, isGroupChannelId, isGroupDmChannelId, -} from '../api/apiUtils'; -import * as db from '../db'; -import * as domain from '../domain'; +} from '../client/apiUtils'; +import type * as db from '@tloncorp/shared/db/types'; +import type { ContentReference } from '../types/references'; +import { PersonalGroupSlugs } from '../types/wayfinding'; import * as ub from '../urbit'; -import { Stringified } from '../utils'; +import type { Stringified } from './utilityTypes'; export { isDmChannelId, isGroupChannelId, isGroupDmChannelId }; @@ -437,12 +437,12 @@ export function extractInlinesFromContent(story: api.PostContent): ub.Inline[] { export function extractReferencesFromContent( story: api.PostContent -): domain.ContentReference[] { +): ContentReference[] { const references = story !== null ? (story.filter( (s) => 'type' in s && s.type == 'reference' - ) as domain.ContentReference[]) + ) as ContentReference[]) : []; return references; @@ -463,7 +463,7 @@ export const extractContentTypes = ( content: Stringified | api.PostContent ): { inlines: ub.Inline[]; - references: domain.ContentReference[]; + references: ContentReference[]; blocks: ub.Block[]; story: api.PostContent; } => { @@ -479,7 +479,7 @@ export const extractContentTypesFromPost = ( post: db.Post | { content: api.PostContent } ): { inlines: ub.Inline[]; - references: domain.ContentReference[]; + references: ContentReference[]; blocks: ub.Block[]; story: api.PostContent; } => { @@ -639,41 +639,6 @@ export const getPostTypeFromChannelId = ({ } }; -export const usePostMeta = (post: db.Post) => { - const { inlines, references, blocks } = useMemo( - () => extractContentTypesFromPost(post), - [post] - ); - const isText = useMemo(() => isTextPost(post), [post]); - const isImage = useMemo(() => isImagePost(post), [post]); - const isLink = useMemo(() => textPostIsLink(post), [post]); - const isReference = useMemo(() => isReferencePost(post), [post]); - const isLinkedImage = useMemo(() => textPostIsLinkedImage(post), [post]); - const isRefInText = useMemo(() => textPostIsReference(post), [post]); - const image = useMemo( - () => (isImage ? findFirstImageBlock(blocks)?.image : undefined), - [blocks, isImage] - ); - const linkedImage = useMemo( - () => (isLinkedImage ? (inlines[0] as ub.Link).link.href : undefined), - [inlines, isLinkedImage] - ); - - return { - isText, - isImage, - isLink, - isReference, - isLinkedImage, - isRefInText, - inlines, - references, - blocks, - image, - linkedImage, - }; -}; - export const getCompositeGroups = ( groups: db.Group[], base: Partial[] @@ -730,7 +695,7 @@ export function simpleHash(input: string) { return Math.abs(hash).toString(36); } -const wayfindingGroup = domain.PersonalGroupSlugs; +const wayfindingGroup = PersonalGroupSlugs; function isWayfindingChannel(id: string | null | undefined): boolean { if (!id) return false; if (isDmChannelId(id)) return false; diff --git a/packages/shared/src/logic/wayfinding.ts b/packages/api/src/lib/wayfinding.ts similarity index 96% rename from packages/shared/src/logic/wayfinding.ts rename to packages/api/src/lib/wayfinding.ts index 2de0476098..13af3414a4 100644 --- a/packages/shared/src/logic/wayfinding.ts +++ b/packages/api/src/lib/wayfinding.ts @@ -1,5 +1,5 @@ -import * as db from '../db'; -import { PersonalGroupNames, PersonalGroupSlugs } from '../domain'; +import type * as db from '@tloncorp/shared/db/types'; +import { PersonalGroupNames, PersonalGroupSlugs } from '../types/wayfinding'; import { getChannelKindFromType } from '../urbit'; export function getPersonalGroupKeys(currentUserId: string) { diff --git a/packages/api/src/test/setup.ts b/packages/api/src/test/setup.ts new file mode 100644 index 0000000000..947a5ad1ce --- /dev/null +++ b/packages/api/src/test/setup.ts @@ -0,0 +1,9 @@ +import { internalConfigureClient } from '../client/urbit'; + +// @ts-expect-error needed by files that reference __DEV__ +global.__DEV__ = true; + +internalConfigureClient({ + shipName: 'solfer-magfed', + shipUrl: 'http://localhost:8080', +}); diff --git a/packages/shared/src/types/ChannelActions.ts b/packages/api/src/types/ChannelActions.ts similarity index 98% rename from packages/shared/src/types/ChannelActions.ts rename to packages/api/src/types/ChannelActions.ts index 50a430482c..f1627c240c 100644 --- a/packages/shared/src/types/ChannelActions.ts +++ b/packages/api/src/types/ChannelActions.ts @@ -1,4 +1,4 @@ -import * as db from '../db'; +import * as db from '@tloncorp/shared/db'; export type Id = | 'debugJson' diff --git a/packages/shared/src/types/JSONValue.ts b/packages/api/src/types/JSONValue.ts similarity index 100% rename from packages/shared/src/types/JSONValue.ts rename to packages/api/src/types/JSONValue.ts diff --git a/packages/shared/src/types/PostCollectionConfiguration.ts b/packages/api/src/types/PostCollectionConfiguration.ts similarity index 98% rename from packages/shared/src/types/PostCollectionConfiguration.ts rename to packages/api/src/types/PostCollectionConfiguration.ts index 1d9b405829..16594453ee 100644 --- a/packages/shared/src/types/PostCollectionConfiguration.ts +++ b/packages/api/src/types/PostCollectionConfiguration.ts @@ -1,5 +1,5 @@ -import { ChannelContentConfiguration, CollectionRendererId } from '../api'; -import * as db from '../db'; +import { ChannelContentConfiguration, CollectionRendererId } from '../client'; +import * as db from '@tloncorp/shared/db'; import * as ChannelAction from './ChannelActions'; /** diff --git a/packages/api/src/types/activityModels.ts b/packages/api/src/types/activityModels.ts new file mode 100644 index 0000000000..8c85b34564 --- /dev/null +++ b/packages/api/src/types/activityModels.ts @@ -0,0 +1,69 @@ +import type { ExtendedEventType } from '../urbit'; +import type { ActivityBucket } from './commonModels'; + +export interface ChannelUnread { + channelId: string; + type: 'channel' | 'dm'; + notify: boolean; + count: number; + countWithoutThreads: number; + updatedAt: number; + firstUnreadPostId?: string | null; + firstUnreadPostReceivedAt?: number | null; +} + +export interface ThreadUnreadState { + channelId?: string | null; + threadId?: string | null; + notify?: boolean | null; + count?: number | null; + updatedAt: number; + firstUnreadPostId?: string | null; + firstUnreadPostReceivedAt?: number | null; +} + +export interface GroupUnread { + groupId: string; + notify?: boolean | null; + count?: number | null; + notifyCount?: number | null; + updatedAt: number; +} + +export interface BaseUnread { + id: string; + notify?: boolean | null; + count?: number | null; + notifyCount?: number | null; + updatedAt: number; + notifTimestamp?: string | null; +} + +export interface ActivityEvent { + id: string; + bucketId: ActivityBucket; + sourceId: string; + type: ExtendedEventType; + timestamp: number; + postId?: string | null; + authorId?: string | null; + parentId?: string | null; + parentAuthorId?: string | null; + channelId?: string | null; + groupId?: string | null; + isMention?: boolean | null; + shouldNotify?: boolean | null; + content?: any | null; + groupEventUserId?: string | null; + contactUserId?: string | null; + contactUpdateType?: string | null; + contactUpdateValue?: string | null; + contactUpdateGroups?: { groupId: string; activityEventId: string }[] | null; +} + +export interface ActivityInit { + baseUnread?: BaseUnread; + groupUnreads: GroupUnread[]; + channelUnreads: ChannelUnread[]; + threadActivity: ThreadUnreadState[]; +} diff --git a/packages/shared/src/domain/analytics.ts b/packages/api/src/types/analytics.ts similarity index 100% rename from packages/shared/src/domain/analytics.ts rename to packages/api/src/types/analytics.ts diff --git a/packages/shared/src/domain/attachment.ts b/packages/api/src/types/attachment.ts similarity index 95% rename from packages/shared/src/domain/attachment.ts rename to packages/api/src/types/attachment.ts index 22c0dd85ef..f52ae89ed2 100644 --- a/packages/shared/src/domain/attachment.ts +++ b/packages/api/src/types/attachment.ts @@ -1,9 +1,25 @@ -import { ImagePickerAsset } from 'expo-image-picker'; import { memoize, uniqueId } from 'lodash'; import { ContentReference } from './references'; import { UploadState } from './uploads'; +/** + * Platform-agnostic image asset type (compatible with expo-image-picker's ImagePickerAsset) + * This allows the package to work in Node.js, web, and React Native environments. + */ +export interface ImagePickerAsset { + uri: string; + width: number; + height: number; + fileSize?: number; + mimeType?: string; + fileName?: string; + type?: 'image' | 'video'; + duration?: number; + base64?: string; + exif?: Record; +} + export type LinkMetadata = PageMetadata | FileMetadata; export type LinkMetadataError = @@ -387,7 +403,7 @@ export namespace Attachment { }; } } else { - return uploadIntent.finalized; + return (uploadIntent as { needsUpload: false; finalized: FinalizedAttachment }).finalized; } } diff --git a/packages/shared/src/domain/attestations.ts b/packages/api/src/types/attestations.ts similarity index 100% rename from packages/shared/src/domain/attestations.ts rename to packages/api/src/types/attestations.ts diff --git a/packages/api/src/types/chatModels.ts b/packages/api/src/types/chatModels.ts new file mode 100644 index 0000000000..1f662678da --- /dev/null +++ b/packages/api/src/types/chatModels.ts @@ -0,0 +1,332 @@ +import type { NotificationLevel } from '../urbit'; +import type { + AttestationDiscoverability, + AttestationStatus, + AttestationType, + ChannelType, + GroupJoinStatus, + GroupPrivacy, + PinType, + PostDeliveryStatus, + PostType, +} from './commonModels'; + +export interface Contact { + id: string; + peerNickname?: string | null; + customNickname?: string | null; + nickname?: string | null; + peerAvatarImage?: string | null; + customAvatarImage?: string | null; + avatarImage?: string | null; + bio?: string | null; + status?: string | null; + color?: string | null; + coverImage?: string | null; + isBlocked?: boolean | null; + isContact?: boolean | null; + isContactSuggestion?: boolean | null; + pinnedGroups?: ContactPinnedGroup[] | null; + attestations?: ContactAttestation[] | null; +} + +export interface ContactPinnedGroup { + contactId: string; + groupId: string; +} + +export interface Group { + id: string; + iconImage?: string | null; + iconImageColor?: string | null; + coverImage?: string | null; + coverImageColor?: string | null; + title?: string | null; + description?: string | null; + privacy?: GroupPrivacy | null; + haveInvite?: boolean | null; + haveRequestedInvite?: boolean | null; + currentUserIsMember: boolean; + currentUserIsHost: boolean; + hostUserId: string; + isNew?: boolean | null; + isPersonalGroup?: boolean | null; + joinStatus?: GroupJoinStatus | null; + lastPostId?: string | null; + lastPostAt?: number | null; + syncedAt?: number | null; + pendingMembersDismissedAt?: number | null; + memberCount?: number | null; + channels?: Channel[] | null; + flaggedPosts?: GroupFlaggedPosts[] | null; + navSections?: GroupNavSection[] | null; + roles?: GroupRole[] | null; + members?: ChatMember[] | null; + bannedMembers?: GroupMemberBan[] | null; + pendingMembers?: GroupMemberInvite[] | null; + joinRequests?: GroupJoinRequest[] | null; + bannedRanks?: GroupRankBan[] | null; +} + +export interface Channel { + id: string; + type: ChannelType; + groupId?: string | null; + iconImage?: string | null; + iconImageColor?: string | null; + coverImage?: string | null; + coverImageColor?: string | null; + title?: string | null; + description?: string | null; + contactId?: string | null; + addedToGroupAt?: number | null; + currentUserIsMember?: boolean | null; + currentUserIsHost?: boolean | null; + postCount?: number | null; + unreadCount?: number | null; + firstUnreadPostId?: string | null; + lastPostId?: string | null; + lastPostAt?: number | null; + lastPostSequenceNum?: number | null; + isPendingChannel?: boolean | null; + isNewMatchedContact?: boolean | null; + isDmInvite?: boolean | null; + syncedAt?: number | null; + remoteUpdatedAt?: number | null; + lastViewedAt?: number | null; + contentConfiguration?: any | null; + order?: string[] | null; + members?: ChatMember[] | null; + readerRoles?: ChannelReader[] | null; + writerRoles?: ChannelWriter[] | null; +} + +export interface ChannelReader { + channelId: string; + roleId: string; +} + +export interface ChannelWriter { + channelId: string; + roleId: string; +} + +export interface Post { + id: string; + authorId: string; + channelId: string; + groupId?: string | null; + parentId?: string | null; + type: PostType; + title?: string | null; + image?: string | null; + description?: string | null; + cover?: string | null; + content?: any | null; + receivedAt: number; + sentAt: number; + replyCount?: number | null; + replyTime?: number | null; + replyContactIds?: string[] | null; + textContent?: string | null; + hasAppReference?: boolean | null; + hasChannelReference?: boolean | null; + hasGroupReference?: boolean | null; + hasLink?: boolean | null; + hasImage?: boolean | null; + hidden?: boolean | null; + isEdited?: boolean | null; + isDeleted?: boolean | null; + isSequenceStub?: boolean | null; + deletedAt?: number | null; + deliveryStatus?: PostDeliveryStatus | null; + editStatus?: PostDeliveryStatus | null; + deleteStatus?: PostDeliveryStatus | null; + lastEditContent?: any | null; + lastEditTitle?: string | null; + lastEditImage?: string | null; + sequenceNum?: number | null; + syncedAt?: number | null; + backendTime?: string | null; + blob?: string | null; + draft?: any | null; + images?: PostImage[] | null; + reactions?: Reaction[] | null; + replies?: Post[] | null; + author?: Contact | null; +} + +export interface PostFlags { + hasAppReference?: boolean | null; + hasChannelReference?: boolean | null; + hasGroupReference?: boolean | null; + hasImage?: boolean | null; + hasLink?: boolean | null; +} + +export interface PostMetadata { + title?: string | null; + image?: string | null; + description?: string | null; + cover?: string | null; +} + +export interface ReplyMeta { + replyCount: number; + replyTime: number | null; + replyContactIds: string[]; +} + +export interface Reaction { + contactId: string; + postId: string; + value: string; +} + +export interface Pin { + type: PinType; + index: number; + itemId: string; +} + +export interface Settings { + id: string; + theme?: string | null; + disableAppTileUnreads?: boolean | null; + disableAvatars?: boolean | null; + disableRemoteContent?: boolean | null; + disableSpellcheck?: boolean | null; + disableNicknames?: boolean | null; + orderedGroupPins?: any | null; + sideBarSort?: 'alphabetical' | 'arranged' | 'recent' | null; + groupSideBarSort?: any | null; + showActivityMessage?: boolean | null; + logActivity?: boolean | null; + enableTelemetry?: boolean | null; + analyticsId?: string | null; + seenWelcomeCard?: boolean | null; + newGroupFlags?: any | null; + groupsNavState?: string | null; + messagesNavState?: string | null; + messagesFilter?: string | null; + gallerySettings?: string | null; + notebookSettings?: any | null; + activitySeenTimestamp?: number | null; + completedWayfindingSplash?: boolean | null; + completedWayfindingTutorial?: boolean | null; + disableTlonInfraEnhancement?: boolean | null; +} + +export interface ChatMember { + membershipType: 'group' | 'channel'; + chatId?: string | null; + contactId: string; + joinedAt?: number | null; + status?: 'invited' | 'joined' | null; + contact?: Contact | null; + roles?: ChatMemberGroupRole[] | null; +} + +export interface GroupRole { + id: string; + groupId?: string | null; + iconImage?: string | null; + iconImageColor?: string | null; + coverImage?: string | null; + coverImageColor?: string | null; + title?: string | null; + description?: string | null; +} + +export interface ChatMemberGroupRole { + groupId: string; + contactId: string; + roleId: string; +} + +export interface GroupNavSection { + id: string; + sectionId: string; + groupId?: string | null; + iconImage?: string | null; + iconImageColor?: string | null; + coverImage?: string | null; + coverImageColor?: string | null; + title?: string | null; + description?: string | null; + sectionIndex?: number | null; + channels?: GroupNavSectionChannel[] | null; +} + +export interface GroupNavSectionChannel { + groupNavSectionId?: string | null; + channelId?: string | null; + channelIndex?: number | null; +} + +export interface GroupMemberInvite { + groupId: string; + contactId: string; + invitedAt?: number | null; +} + +export interface GroupMemberBan { + groupId: string; + contactId: string; + bannedAt?: number | null; +} + +export interface GroupJoinRequest { + groupId: string; + contactId: string; + requestedAt?: number | null; +} + +export interface GroupRankBan { + groupId: string; + rankId: string; + bannedAt?: number | null; +} + +export interface GroupFlaggedPosts { + groupId: string; + postId: string; + channelId: string; + flaggedByContactId: string; + flaggedAt?: number | null; +} + +export interface VolumeSettings { + itemId: string; + itemType: 'group' | 'channel' | 'thread' | 'base'; + level: NotificationLevel; +} + +export interface PostImage { + postId?: string | null; + src?: string | null; + alt?: string | null; + width?: number | null; + height?: number | null; +} + +export interface Attestation { + id: string; + provider: string; + type: AttestationType; + value?: string | null; + initiatedAt?: number | null; + discoverability: AttestationDiscoverability; + status: AttestationStatus; + statusMessage?: string | null; + contactId: string; + providerUrl?: string | null; + provingTweetId?: string | null; + signature?: string | null; +} + +export interface ContactAttestation { + contactId: string; + attestationId: string; + attestation?: Attestation | null; +} diff --git a/packages/api/src/types/clientModels.ts b/packages/api/src/types/clientModels.ts new file mode 100644 index 0000000000..76af31c102 --- /dev/null +++ b/packages/api/src/types/clientModels.ts @@ -0,0 +1,49 @@ +import type { ActivityEvent, ActivityInit } from './activityModels'; +import type { Contact, Group, Post } from './chatModels'; +import type { SystemContact } from './systemContactModels'; + +export interface ClientMeta { + title?: string | null; + coverImage?: string | null; + iconImage?: string | null; + description?: string | null; + coverImageColor?: string | null; + iconImageColor?: string | null; +} + +export interface ChangesResult { + groups: Group[]; + posts: Post[]; + contacts: Contact[]; + unreads: ActivityInit; + deletedChannelIds: string[]; +} + +export interface PendingMemberDismissal { + groupId: string; + dismissedAt: number; +} + +export type PendingMemberDismissals = PendingMemberDismissal[]; + +export interface GroupEvent extends ActivityEvent { + type: 'group-ask'; + group: Group; + groupId: string; + groupEventUserId: string; + groupEventUser: Contact; +} + +export function isGroupEvent(event: ActivityEvent): event is GroupEvent { + return Boolean( + event.type === 'group-ask' && event.groupEventUserId && event.groupId + ); +} + +export interface AppInfo { + groupsVersion: string; + groupsHash: string; + groupsSyncNode: string; +} + +export type SystemContactLike = Contact | SystemContact; diff --git a/packages/api/src/types/commonModels.ts b/packages/api/src/types/commonModels.ts new file mode 100644 index 0000000000..064b7bb24e --- /dev/null +++ b/packages/api/src/types/commonModels.ts @@ -0,0 +1,15 @@ +export type ChannelType = 'chat' | 'notebook' | 'gallery' | 'dm' | 'groupDm'; +export type PostDeliveryStatus = + | 'enqueued' + | 'pending' + | 'sent' + | 'failed' + | 'needs_verification'; +export type PinType = 'group' | 'channel' | 'dm' | 'groupDm'; +export type GroupPrivacy = 'public' | 'private' | 'secret'; +export type GroupJoinStatus = 'joining' | 'errored'; +export type ActivityBucket = 'all' | 'mentions' | 'replies'; +export type AttestationType = 'phone' | 'node' | 'twitter' | 'dummy'; +export type AttestationDiscoverability = 'public' | 'verified' | 'hidden'; +export type AttestationStatus = 'waiting' | 'pending' | 'verified'; +export type PostType = 'block' | 'chat' | 'notice' | 'note' | 'reply' | 'delete'; diff --git a/packages/shared/src/domain/constants.ts b/packages/api/src/types/constants.ts similarity index 86% rename from packages/shared/src/domain/constants.ts rename to packages/api/src/types/constants.ts index 7ce23b312a..d731375801 100644 --- a/packages/shared/src/domain/constants.ts +++ b/packages/api/src/types/constants.ts @@ -32,6 +32,7 @@ interface Constants { GIT_HASH: string; DISABLE_SPLASH_MODAL: boolean; AUTOMATED_TEST: boolean; + OPENROUTER_API_KEY: string; } export function getConstants(): Constants { @@ -45,3 +46,8 @@ export function getConstants(): Constants { return (global as any)[TLON_NAMESPACE] as Constants; } + +export function isOpenRouterConfigured(): boolean { + const constants = getConstants(); + return !!constants.OPENROUTER_API_KEY && constants.OPENROUTER_API_KEY.length > 0; +} diff --git a/packages/shared/src/domain/groupTemplates.ts b/packages/api/src/types/groupTemplates.ts similarity index 100% rename from packages/shared/src/domain/groupTemplates.ts rename to packages/api/src/types/groupTemplates.ts diff --git a/packages/shared/src/types/groups.ts b/packages/api/src/types/groups.ts similarity index 100% rename from packages/shared/src/types/groups.ts rename to packages/api/src/types/groups.ts diff --git a/packages/shared/src/domain/hosting.ts b/packages/api/src/types/hosting.ts similarity index 100% rename from packages/shared/src/domain/hosting.ts rename to packages/api/src/types/hosting.ts diff --git a/packages/api/src/types/index.ts b/packages/api/src/types/index.ts new file mode 100644 index 0000000000..51ec962360 --- /dev/null +++ b/packages/api/src/types/index.ts @@ -0,0 +1,15 @@ +export * from './analytics'; +export * from './attachment'; +export * from './attestations'; +export * from './constants'; +export * from '../client/channelContentConfig'; +export * from './groupTemplates'; +export * from './hosting'; +export * from './invite.types'; +export * from './onboarding'; +export * from './post'; +export * from './references'; +export * from './system'; +export * from './types'; +export * from './uploads'; +export * from './wayfinding'; diff --git a/packages/shared/src/domain/invite.types.ts b/packages/api/src/types/invite.types.ts similarity index 100% rename from packages/shared/src/domain/invite.types.ts rename to packages/api/src/types/invite.types.ts diff --git a/packages/shared/src/types/native.ts b/packages/api/src/types/native.ts similarity index 100% rename from packages/shared/src/types/native.ts rename to packages/api/src/types/native.ts diff --git a/packages/shared/src/domain/onboarding.ts b/packages/api/src/types/onboarding.ts similarity index 100% rename from packages/shared/src/domain/onboarding.ts rename to packages/api/src/types/onboarding.ts diff --git a/packages/shared/src/domain/post.ts b/packages/api/src/types/post.ts similarity index 96% rename from packages/shared/src/domain/post.ts rename to packages/api/src/types/post.ts index 9736e951d2..69dcebf2e3 100644 --- a/packages/shared/src/domain/post.ts +++ b/packages/api/src/types/post.ts @@ -1,5 +1,4 @@ -import type { ChannelType } from '../db/schema'; -import type { PostMetadata } from '../db/types'; +import type { ChannelType, PostMetadata } from '@tloncorp/shared/db/types'; import { Block, Inline, Story } from '../urbit'; import { Attachment } from './attachment'; diff --git a/packages/shared/src/domain/references.ts b/packages/api/src/types/references.ts similarity index 100% rename from packages/shared/src/domain/references.ts rename to packages/api/src/types/references.ts diff --git a/packages/shared/src/domain/system.ts b/packages/api/src/types/system.ts similarity index 100% rename from packages/shared/src/domain/system.ts rename to packages/api/src/types/system.ts diff --git a/packages/api/src/types/systemContactModels.ts b/packages/api/src/types/systemContactModels.ts new file mode 100644 index 0000000000..abbae9e374 --- /dev/null +++ b/packages/api/src/types/systemContactModels.ts @@ -0,0 +1,40 @@ +import type { Contact } from './chatModels'; + +export interface SystemContact { + id: string; + firstName?: string | null; + lastName?: string | null; + phoneNumber?: string | null; + email?: string | null; + contactId?: string | null; +} + +export interface SystemContactSentInvite { + invitedTo?: string | null; + systemContactId?: string | null; + invitedAt?: number | null; +} + +export const InvitedToPersonalKey = 'personal-invite'; + +export interface SystemContactInviteParams { + type: 'sms' | 'email'; + recipients: string[]; + invite: { + link: string; + message: string; + subject?: string; + }; +} + +export const SystemContactInviteMessages = { + Personal: `I'm inviting you to Tlon Messenger`, +}; + +export function isSystemContact( + contact: Contact | SystemContact +): contact is SystemContact { + const hasPhone = 'phoneNumber' in contact; + const hasEmail = 'email' in contact; + return hasPhone || hasEmail; +} diff --git a/packages/shared/src/domain/systemContacts.ts b/packages/api/src/types/systemContacts.ts similarity index 100% rename from packages/shared/src/domain/systemContacts.ts rename to packages/api/src/types/systemContacts.ts diff --git a/packages/api/src/types/types.ts b/packages/api/src/types/types.ts new file mode 100644 index 0000000000..09b60d19a6 --- /dev/null +++ b/packages/api/src/types/types.ts @@ -0,0 +1,5 @@ +export * from './activityModels'; +export * from './clientModels'; +export * from './chatModels'; +export * from './commonModels'; +export * from './systemContactModels'; diff --git a/packages/shared/src/domain/uploads.ts b/packages/api/src/types/uploads.ts similarity index 100% rename from packages/shared/src/domain/uploads.ts rename to packages/api/src/types/uploads.ts diff --git a/packages/shared/src/domain/wayfinding.ts b/packages/api/src/types/wayfinding.ts similarity index 100% rename from packages/shared/src/domain/wayfinding.ts rename to packages/api/src/types/wayfinding.ts diff --git a/packages/shared/src/urbit/activity.ts b/packages/api/src/urbit/activity.ts similarity index 99% rename from packages/shared/src/urbit/activity.ts rename to packages/api/src/urbit/activity.ts index 751fc89e6c..ebc65ea595 100644 --- a/packages/shared/src/urbit/activity.ts +++ b/packages/api/src/urbit/activity.ts @@ -1,11 +1,11 @@ import { da } from '@urbit/aura'; import _ from 'lodash'; -import type { UnionToIntersection } from '../utils'; +import type { UnionToIntersection } from '../lib/utilityTypes'; import { Kind, Story } from './channel'; import { ContactBookProfile } from './contact'; import { nestToFlag, whomIsDm, whomIsFlag, whomIsMultiDm } from './utils'; -import { parseIdNumber } from '../api/apiUtils'; +import { parseIdNumber } from '../client/apiUtils'; export type Whom = { ship: string } | { club: string }; diff --git a/packages/shared/src/urbit/channel.ts b/packages/api/src/urbit/channel.ts similarity index 98% rename from packages/shared/src/urbit/channel.ts rename to packages/api/src/urbit/channel.ts index a9ac58f95f..8daae91572 100644 --- a/packages/shared/src/urbit/channel.ts +++ b/packages/api/src/urbit/channel.ts @@ -3,9 +3,17 @@ import bigInt, { BigInteger } from 'big-integer'; import _ from 'lodash'; import BTree from 'sorted-btree'; -import { parseIdNumber } from '../api/apiUtils'; -import { Stringified } from '../utils'; -import { Block, Image, Inline, isBlock, isBlockquote, isImage, isBreak } from './content'; +import { parseIdNumber } from '../client/apiUtils'; +import { Stringified } from '../lib/utilityTypes'; +import { + Block, + Image, + Inline, + isBlock, + isBlockquote, + isImage, + isBreak, +} from './content'; import { Flag } from './hark'; import { Metadata } from './meta'; diff --git a/packages/shared/src/urbit/contact.ts b/packages/api/src/urbit/contact.ts similarity index 100% rename from packages/shared/src/urbit/contact.ts rename to packages/api/src/urbit/contact.ts diff --git a/packages/shared/src/urbit/content.ts b/packages/api/src/urbit/content.ts similarity index 99% rename from packages/shared/src/urbit/content.ts rename to packages/api/src/urbit/content.ts index ffed49d880..2ee3c8e33a 100644 --- a/packages/shared/src/urbit/content.ts +++ b/packages/api/src/urbit/content.ts @@ -1,4 +1,4 @@ -import { UnionToIntersection } from '../utils'; +import { UnionToIntersection } from '../lib/utilityTypes'; type Flag = string; type Nest = string; diff --git a/packages/shared/src/urbit/dms.ts b/packages/api/src/urbit/dms.ts similarity index 99% rename from packages/shared/src/urbit/dms.ts rename to packages/api/src/urbit/dms.ts index bcd8e8b095..4935df4dd6 100644 --- a/packages/shared/src/urbit/dms.ts +++ b/packages/api/src/urbit/dms.ts @@ -12,7 +12,7 @@ import { ReplySeal, } from './channel'; import { GroupMeta } from './groups'; -import { parseIdNumber } from '../api/apiUtils'; +import { parseIdNumber } from '../client/apiUtils'; export type Patda = string; export type Ship = string; diff --git a/packages/shared/src/urbit/groups.ts b/packages/api/src/urbit/groups.ts similarity index 100% rename from packages/shared/src/urbit/groups.ts rename to packages/api/src/urbit/groups.ts diff --git a/packages/shared/src/urbit/hark.ts b/packages/api/src/urbit/hark.ts similarity index 100% rename from packages/shared/src/urbit/hark.ts rename to packages/api/src/urbit/hark.ts diff --git a/packages/shared/src/urbit/index.ts b/packages/api/src/urbit/index.ts similarity index 100% rename from packages/shared/src/urbit/index.ts rename to packages/api/src/urbit/index.ts diff --git a/packages/shared/src/urbit/lanyard.ts b/packages/api/src/urbit/lanyard.ts similarity index 100% rename from packages/shared/src/urbit/lanyard.ts rename to packages/api/src/urbit/lanyard.ts diff --git a/packages/shared/src/urbit/meta.ts b/packages/api/src/urbit/meta.ts similarity index 100% rename from packages/shared/src/urbit/meta.ts rename to packages/api/src/urbit/meta.ts diff --git a/packages/shared/src/urbit/metagrab.ts b/packages/api/src/urbit/metagrab.ts similarity index 100% rename from packages/shared/src/urbit/metagrab.ts rename to packages/api/src/urbit/metagrab.ts diff --git a/packages/shared/src/urbit/negotiation.ts b/packages/api/src/urbit/negotiation.ts similarity index 100% rename from packages/shared/src/urbit/negotiation.ts rename to packages/api/src/urbit/negotiation.ts diff --git a/packages/shared/src/urbit/settings.ts b/packages/api/src/urbit/settings.ts similarity index 98% rename from packages/shared/src/urbit/settings.ts rename to packages/api/src/urbit/settings.ts index 4c0947d51e..6db6a343fe 100644 --- a/packages/shared/src/urbit/settings.ts +++ b/packages/api/src/urbit/settings.ts @@ -1,6 +1,6 @@ import { ThemeName } from 'tamagui'; -import { Stringified } from '../utils'; +import { Stringified } from '../lib/utilityTypes'; import { DisplayMode, SortMode } from './channel'; export type AppTheme = ThemeName | 'auto'; diff --git a/packages/shared/src/urbit/sigil.ts b/packages/api/src/urbit/sigil.ts similarity index 100% rename from packages/shared/src/urbit/sigil.ts rename to packages/api/src/urbit/sigil.ts diff --git a/packages/shared/src/urbit/storage.ts b/packages/api/src/urbit/storage.ts similarity index 94% rename from packages/shared/src/urbit/storage.ts rename to packages/api/src/urbit/storage.ts index 936d3f0007..99b159cf06 100644 --- a/packages/shared/src/urbit/storage.ts +++ b/packages/api/src/urbit/storage.ts @@ -1,4 +1,4 @@ -import { StorageCredentials, StorageService } from '../api/upload'; +import { StorageCredentials, StorageService } from '../client/upload'; export interface StorageUpdateCredentials { credentials: StorageCredentials; diff --git a/packages/shared/src/urbit/ui.ts b/packages/api/src/urbit/ui.ts similarity index 100% rename from packages/shared/src/urbit/ui.ts rename to packages/api/src/urbit/ui.ts diff --git a/packages/shared/src/urbit/utils.ts b/packages/api/src/urbit/utils.ts similarity index 96% rename from packages/shared/src/urbit/utils.ts rename to packages/api/src/urbit/utils.ts index 3f7424873b..4cb1fb82de 100644 --- a/packages/shared/src/urbit/utils.ts +++ b/packages/api/src/urbit/utils.ts @@ -1,10 +1,10 @@ import { render, valid, da } from '@urbit/aura'; -import { PostContent } from '../api'; -import { ChannelType } from '../db'; -import { GroupJoinStatus, GroupPrivacy } from '../db/schema'; -import { createDevLogger } from '../debug'; -import { ContentReference } from '../domain'; +import { PostContent } from '../client'; +import { ChannelType } from '@tloncorp/shared/db'; +import { GroupJoinStatus, GroupPrivacy } from '@tloncorp/shared/db/schema'; +import { createDevLogger } from '@tloncorp/shared/debug'; +import { ContentReference } from '../types/references'; import * as ub from './channel'; import * as ubc from './content'; import * as ubg from './groups'; diff --git a/packages/shared/src/urbit/vitals.ts b/packages/api/src/urbit/vitals.ts similarity index 100% rename from packages/shared/src/urbit/vitals.ts rename to packages/api/src/urbit/vitals.ts diff --git a/packages/shared/src/urbit/volume.ts b/packages/api/src/urbit/volume.ts similarity index 100% rename from packages/shared/src/urbit/volume.ts rename to packages/api/src/urbit/volume.ts diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json new file mode 100644 index 0000000000..701b175d29 --- /dev/null +++ b/packages/api/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src"], + "compilerOptions": { + "composite": true + } +} diff --git a/packages/api/vitest.config.ts b/packages/api/vitest.config.ts new file mode 100644 index 0000000000..aa4a0d9c33 --- /dev/null +++ b/packages/api/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'node', + include: ['src/test/**/*.test.ts', 'src/__tests__/**/*.test.ts'], + setupFiles: ['./src/test/setup.ts'], + passWithNoTests: true, + testTimeout: 30000, // 30s for network operations + }, +}); diff --git a/packages/app/contexts/ship.tsx b/packages/app/contexts/ship.tsx index 75b8c30c59..ef7b6ad241 100644 --- a/packages/app/contexts/ship.tsx +++ b/packages/app/contexts/ship.tsx @@ -1,7 +1,7 @@ import crashlytics from '@react-native-firebase/crashlytics'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; import { ShipInfo, storage } from '@tloncorp/shared/db'; -import { preSig } from '@tloncorp/shared/urbit'; +import { preSig } from '@tloncorp/api/urbit'; import type { ReactNode } from 'react'; import { createContext, diff --git a/packages/app/features/settings/AppInfoScreen.tsx b/packages/app/features/settings/AppInfoScreen.tsx index 65b444cacf..fabe8fca55 100644 --- a/packages/app/features/settings/AppInfoScreen.tsx +++ b/packages/app/features/settings/AppInfoScreen.tsx @@ -1,7 +1,7 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { useDebugStore } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; -import { preSig } from '@tloncorp/shared/urbit'; +import { preSig } from '@tloncorp/api/urbit'; import * as Application from 'expo-application'; import { useEffect, useState } from 'react'; import { useCallback } from 'react'; diff --git a/packages/app/features/settings/ManageAccountScreen.tsx b/packages/app/features/settings/ManageAccountScreen.tsx index 987e926515..6ae58f9d73 100644 --- a/packages/app/features/settings/ManageAccountScreen.tsx +++ b/packages/app/features/settings/ManageAccountScreen.tsx @@ -1,5 +1,5 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'; -import { checkIfAccountDeleted } from '@tloncorp/shared/api'; +import { checkIfAccountDeleted } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { useCallback, useEffect, useState } from 'react'; import { Alert } from 'react-native'; diff --git a/packages/app/features/settings/PushNotificationSettingsScreen.tsx b/packages/app/features/settings/PushNotificationSettingsScreen.tsx index 197eb5c600..7230142b13 100644 --- a/packages/app/features/settings/PushNotificationSettingsScreen.tsx +++ b/packages/app/features/settings/PushNotificationSettingsScreen.tsx @@ -2,7 +2,7 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'; import * as db from '@tloncorp/shared/db'; import * as logic from '@tloncorp/shared/logic'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { ComponentProps, useCallback, useMemo } from 'react'; import { Platform } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; diff --git a/packages/app/features/top/ChannelScreen.tsx b/packages/app/features/top/ChannelScreen.tsx index c98f55b1da..3d96c6045d 100644 --- a/packages/app/features/top/ChannelScreen.tsx +++ b/packages/app/features/top/ChannelScreen.tsx @@ -14,7 +14,7 @@ import { usePostReference, usePostWithRelations, } from '@tloncorp/shared/store'; -import { Story } from '@tloncorp/shared/urbit'; +import { Story } from '@tloncorp/api/urbit'; import React, { useCallback, useEffect, diff --git a/packages/app/features/top/ChatListScreen.tsx b/packages/app/features/top/ChatListScreen.tsx index c650af1876..052d845e6c 100644 --- a/packages/app/features/top/ChatListScreen.tsx +++ b/packages/app/features/top/ChatListScreen.tsx @@ -5,7 +5,7 @@ import { } from '@react-navigation/native'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; import { AnalyticsEvent, createDevLogger } from '@tloncorp/shared'; -import { markInvitesRead } from '@tloncorp/shared/api'; +import { markInvitesRead } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as logic from '@tloncorp/shared/logic'; import * as store from '@tloncorp/shared/store'; diff --git a/packages/app/features/top/ChatVolumeScreen.tsx b/packages/app/features/top/ChatVolumeScreen.tsx index ad05032780..a6ad24775a 100644 --- a/packages/app/features/top/ChatVolumeScreen.tsx +++ b/packages/app/features/top/ChatVolumeScreen.tsx @@ -1,7 +1,7 @@ import { useNavigation } from '@react-navigation/native'; import { NativeStackScreenProps } from '@react-navigation/native-stack'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { useCallback } from 'react'; import { useChatSettingsNavigation } from '../../hooks/useChatSettingsNavigation'; diff --git a/packages/app/features/top/MessagesFilterMenu.tsx b/packages/app/features/top/MessagesFilterMenu.tsx index f869437882..76ffad3bb8 100644 --- a/packages/app/features/top/MessagesFilterMenu.tsx +++ b/packages/app/features/top/MessagesFilterMenu.tsx @@ -1,5 +1,5 @@ import * as store from '@tloncorp/shared/store'; -import { TalkSidebarFilter } from '@tloncorp/shared/urbit'; +import { TalkSidebarFilter } from '@tloncorp/api/urbit'; import { PropsWithChildren, useCallback, useMemo, useState } from 'react'; import { ActionSheet, createActionGroups } from '../../ui'; diff --git a/packages/app/features/top/QueryBenchScreen.tsx b/packages/app/features/top/QueryBenchScreen.tsx index 3002b47377..857ffdaf17 100644 --- a/packages/app/features/top/QueryBenchScreen.tsx +++ b/packages/app/features/top/QueryBenchScreen.tsx @@ -1,6 +1,6 @@ -import { toContactsData, toInitData } from '@tloncorp/shared/api'; +import { toContactsData, toInitData } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; -import type * as ub from '@tloncorp/shared/urbit'; +import type * as ub from '@tloncorp/api/urbit'; import { Button, Text, View } from '@tloncorp/ui'; import { useMemo, useState } from 'react'; import { ScrollView } from 'react-native'; diff --git a/packages/app/features/top/chatDetails.tsx b/packages/app/features/top/chatDetails.tsx index 1860739d87..ca07433df2 100644 --- a/packages/app/features/top/chatDetails.tsx +++ b/packages/app/features/top/chatDetails.tsx @@ -1,7 +1,7 @@ // Shared components for ChatDetailsScreen and ChannelDetailsScreen import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { capitalize } from 'lodash'; import React, { useCallback, useMemo, useState } from 'react'; import { Alert } from 'react-native'; diff --git a/packages/app/features/top/useShipConnectionStatus.tsx b/packages/app/features/top/useShipConnectionStatus.tsx index 3cbff0d0f2..884ab301c1 100644 --- a/packages/app/features/top/useShipConnectionStatus.tsx +++ b/packages/app/features/top/useShipConnectionStatus.tsx @@ -1,7 +1,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; -import { ConnectionStatus } from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; +import { ConnectionStatus } from '@tloncorp/api'; import { debounce } from 'lodash'; import { useCurrentUserId } from '../../ui'; diff --git a/packages/app/fixtures/Channel.fixture.tsx b/packages/app/fixtures/Channel.fixture.tsx index 6e606ba8de..40d9268500 100644 --- a/packages/app/fixtures/Channel.fixture.tsx +++ b/packages/app/fixtures/Channel.fixture.tsx @@ -7,7 +7,7 @@ import { import { ChannelContentConfiguration, CollectionRendererId, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import type * as db from '@tloncorp/shared/db'; import { range } from 'lodash'; import type { ComponentProps, PropsWithChildren, SetStateAction } from 'react'; diff --git a/packages/app/fixtures/FixtureWrapper.tsx b/packages/app/fixtures/FixtureWrapper.tsx index 890504f141..0224d8edb1 100644 --- a/packages/app/fixtures/FixtureWrapper.tsx +++ b/packages/app/fixtures/FixtureWrapper.tsx @@ -2,7 +2,7 @@ import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; import { NavigationContainer } from '@react-navigation/native'; import { QueryClientProvider, queryClient } from '@tloncorp/shared'; -import { internalConfigureClient } from '@tloncorp/shared/api'; +import { internalConfigureClient } from '@tloncorp/api'; import { type PropsWithChildren, useEffect, useState } from 'react'; import { useFixtureSelect } from 'react-cosmos/client'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; diff --git a/packages/app/fixtures/activityHelpers.tsx b/packages/app/fixtures/activityHelpers.tsx index a46b3e2ea5..ee7021b281 100644 --- a/packages/app/fixtures/activityHelpers.tsx +++ b/packages/app/fixtures/activityHelpers.tsx @@ -1,7 +1,7 @@ -import { PostContent } from '@tloncorp/shared/api'; +import { PostContent } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as logic from '@tloncorp/shared/logic'; -import { ExtendedEventType } from '@tloncorp/shared/urbit'; +import { ExtendedEventType } from '@tloncorp/api/urbit'; import { exampleContacts, postsByType } from './contentHelpers'; import { group as fakeGroup, tlonLocalIntros } from './fakeData'; diff --git a/packages/app/fixtures/contentHelpers.tsx b/packages/app/fixtures/contentHelpers.tsx index c1c8ac7a4a..27e4d59c18 100644 --- a/packages/app/fixtures/contentHelpers.tsx +++ b/packages/app/fixtures/contentHelpers.tsx @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import { useQuery } from '@tanstack/react-query'; -import type { PostContent } from '@tloncorp/shared/api'; +import type { PostContent } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import type { ContentReference } from '@tloncorp/shared/domain'; import { appendFileUploadToPostBlob } from '@tloncorp/shared/logic'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { createFakePost, diff --git a/packages/app/fixtures/fakeData.ts b/packages/app/fixtures/fakeData.ts index 94a067161a..fc1e178cc7 100644 --- a/packages/app/fixtures/fakeData.ts +++ b/packages/app/fixtures/fakeData.ts @@ -1,6 +1,6 @@ import * as db from '@tloncorp/shared/db'; import { PlaintextPreviewConfig, getTextContent } from '@tloncorp/shared/logic'; -import type { Story } from '@tloncorp/shared/urbit'; +import type { Story } from '@tloncorp/api/urbit'; import { render, da } from '@urbit/aura'; import seedrandom from 'seedrandom'; diff --git a/packages/app/hooks/useBootSequence.ts b/packages/app/hooks/useBootSequence.ts index 28e180f416..7c42f1ae4c 100644 --- a/packages/app/hooks/useBootSequence.ts +++ b/packages/app/hooks/useBootSequence.ts @@ -4,7 +4,7 @@ import { extractNormalizedInviteLink, withRetry, } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { AnalyticsSeverity, @@ -14,7 +14,7 @@ import { } from '@tloncorp/shared/domain'; import * as store from '@tloncorp/shared/store'; import { verifyUserInviteLink } from '@tloncorp/shared/store'; -import { preSig } from '@tloncorp/shared/urbit'; +import { preSig } from '@tloncorp/api/urbit'; import * as utils from '@tloncorp/shared/utils'; import { useCallback, useEffect, useRef, useState } from 'react'; diff --git a/packages/app/hooks/useConfigureUrbitClient.ts b/packages/app/hooks/useConfigureUrbitClient.ts index e663b119f8..ff4bf07a17 100644 --- a/packages/app/hooks/useConfigureUrbitClient.ts +++ b/packages/app/hooks/useConfigureUrbitClient.ts @@ -1,7 +1,7 @@ import { AnalyticsEvent, createDevLogger, sync } from '@tloncorp/shared'; -import { ClientParams } from '@tloncorp/shared/api'; -import { getShipAccessCode } from '@tloncorp/shared/api'; -import * as api from '@tloncorp/shared/api'; +import { ClientParams } from '@tloncorp/api'; +import { getShipAccessCode } from '@tloncorp/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { configureClient } from '@tloncorp/shared/store'; import { useCallback } from 'react'; diff --git a/packages/app/hooks/useCurrentUser.native.ts b/packages/app/hooks/useCurrentUser.native.ts index 21ce359bcb..9663f21004 100644 --- a/packages/app/hooks/useCurrentUser.native.ts +++ b/packages/app/hooks/useCurrentUser.native.ts @@ -1,4 +1,4 @@ -import * as urbit from '@tloncorp/shared/urbit'; +import * as urbit from '@tloncorp/api/urbit'; import { useShip } from '../contexts/ship'; diff --git a/packages/app/hooks/useDesktopNotifications.ts b/packages/app/hooks/useDesktopNotifications.ts index db29284541..0810adab85 100644 --- a/packages/app/hooks/useDesktopNotifications.ts +++ b/packages/app/hooks/useDesktopNotifications.ts @@ -1,5 +1,5 @@ import { createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { getTextContent } from '@tloncorp/shared/logic'; import { useCallback, useEffect, useRef } from 'react'; diff --git a/packages/app/hooks/useFilteredChats.ts b/packages/app/hooks/useFilteredChats.ts index 0dc2b4469d..8cf3cf2e7c 100644 --- a/packages/app/hooks/useFilteredChats.ts +++ b/packages/app/hooks/useFilteredChats.ts @@ -1,6 +1,6 @@ import { configurationFromChannel, useMessagesFilter } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; -import { TalkSidebarFilter } from '@tloncorp/shared/urbit'; +import { TalkSidebarFilter } from '@tloncorp/api/urbit'; import Fuse from 'fuse.js'; import { debounce } from 'lodash'; import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; diff --git a/packages/app/hooks/useGroupSearch.ts b/packages/app/hooks/useGroupSearch.ts index 24f6e58961..880ff3d355 100644 --- a/packages/app/hooks/useGroupSearch.ts +++ b/packages/app/hooks/useGroupSearch.ts @@ -1,6 +1,6 @@ import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; -import { whomIsFlag } from '@tloncorp/shared/urbit'; +import { whomIsFlag } from '@tloncorp/api/urbit'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { GroupPreviewAction } from '../ui'; diff --git a/packages/app/hooks/useHandleLogout.native.ts b/packages/app/hooks/useHandleLogout.native.ts index c0699a70d7..2b2a54e6fd 100644 --- a/packages/app/hooks/useHandleLogout.native.ts +++ b/packages/app/hooks/useHandleLogout.native.ts @@ -1,5 +1,5 @@ import { createDevLogger } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { clearSessionStorageItems } from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; import { useCallback } from 'react'; diff --git a/packages/app/hooks/useHandleLogout.ts b/packages/app/hooks/useHandleLogout.ts index e17fe14708..3e275faa5d 100644 --- a/packages/app/hooks/useHandleLogout.ts +++ b/packages/app/hooks/useHandleLogout.ts @@ -4,7 +4,7 @@ // which isn't made for web. import { createDevLogger } from '@tloncorp/shared'; import { clearAuthInfo, isElectronEnv } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { clearSessionStorageItems } from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; import { useCallback } from 'react'; diff --git a/packages/app/hooks/useTelemetry.ts b/packages/app/hooks/useTelemetry.ts index 7d31049288..4b5325a4f6 100644 --- a/packages/app/hooks/useTelemetry.ts +++ b/packages/app/hooks/useTelemetry.ts @@ -3,7 +3,7 @@ import { createDevLogger, useCurrentSession, } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import { didInitializeTelemetry, hasClearedLegacyWebTelemetry, diff --git a/packages/app/lib/bootHelpers.ts b/packages/app/lib/bootHelpers.ts index 7c89fe2470..ff1fbed02b 100644 --- a/packages/app/lib/bootHelpers.ts +++ b/packages/app/lib/bootHelpers.ts @@ -1,6 +1,6 @@ import { AnalyticsEvent, AppInvite, createDevLogger } from '@tloncorp/shared'; import { HostedNodeStatus } from '@tloncorp/shared'; -import * as hostingApi from '@tloncorp/shared/api'; +import * as hostingApi from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; diff --git a/packages/app/lib/devMenuItems.ts b/packages/app/lib/devMenuItems.ts index d81ba44b84..6b0ac6d61e 100644 --- a/packages/app/lib/devMenuItems.ts +++ b/packages/app/lib/devMenuItems.ts @@ -1,5 +1,5 @@ import { syncSince } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import Constants from 'expo-constants'; import { registerDevMenuItems } from 'expo-dev-menu'; import { Alert, DevSettings } from 'react-native'; diff --git a/packages/app/lib/notificationsApi.ts b/packages/app/lib/notificationsApi.ts index 61f43c0f77..28889595be 100644 --- a/packages/app/lib/notificationsApi.ts +++ b/packages/app/lib/notificationsApi.ts @@ -1,4 +1,4 @@ -import { poke } from '@tloncorp/shared/api'; +import { poke } from '@tloncorp/api'; import { Platform } from 'react-native'; import { NOTIFY_PROVIDER, NOTIFY_SERVICE } from '../constants'; diff --git a/packages/app/navigation/desktop/HomeSidebar.tsx b/packages/app/navigation/desktop/HomeSidebar.tsx index a4ca38a17d..df0d1f4e88 100644 --- a/packages/app/navigation/desktop/HomeSidebar.tsx +++ b/packages/app/navigation/desktop/HomeSidebar.tsx @@ -1,6 +1,6 @@ import { useIsFocused } from '@react-navigation/native'; import { createDevLogger } from '@tloncorp/shared'; -import { markInvitesRead } from '@tloncorp/shared/api'; +import { markInvitesRead } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; import { Text } from '@tloncorp/ui'; diff --git a/packages/app/provider/BaseProviderStack.tsx b/packages/app/provider/BaseProviderStack.tsx index 57d29c13c9..6be1356014 100644 --- a/packages/app/provider/BaseProviderStack.tsx +++ b/packages/app/provider/BaseProviderStack.tsx @@ -1,5 +1,5 @@ import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; -import { QueryClientProvider, queryClient } from '@tloncorp/shared/api'; +import { QueryClientProvider, queryClient } from '@tloncorp/api'; import { ToastProvider } from '@tloncorp/ui'; import { PropsWithChildren } from 'react'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; diff --git a/packages/app/ui/components/BareChatInput/index.tsx b/packages/app/ui/components/BareChatInput/index.tsx index 18814e3617..d8a9ff1ddd 100644 --- a/packages/app/ui/components/BareChatInput/index.tsx +++ b/packages/app/ui/components/BareChatInput/index.tsx @@ -12,11 +12,11 @@ import { import { contentReferenceToCite, toContentReference, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import type * as domain from '@tloncorp/shared/domain'; import * as logic from '@tloncorp/shared/logic'; -import { Story, citeToPath, pathToCite } from '@tloncorp/shared/urbit'; +import { Story, citeToPath, pathToCite } from '@tloncorp/api/urbit'; import { HEADER_HEIGHT, LoadingSpinner, diff --git a/packages/app/ui/components/BigInput.tsx b/packages/app/ui/components/BigInput.tsx index 75aaa62346..66516e7524 100644 --- a/packages/app/ui/components/BigInput.tsx +++ b/packages/app/ui/components/BigInput.tsx @@ -10,7 +10,7 @@ import { } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; import * as domain from '@tloncorp/shared/domain'; -import { Block, Inline, constructStory } from '@tloncorp/shared/urbit'; +import { Block, Inline, constructStory } from '@tloncorp/api/urbit'; import { Button, Icon, diff --git a/packages/app/ui/components/Channel/DraftInputView.tsx b/packages/app/ui/components/Channel/DraftInputView.tsx index ac7bbebeaa..7f4f0f3994 100644 --- a/packages/app/ui/components/Channel/DraftInputView.tsx +++ b/packages/app/ui/components/Channel/DraftInputView.tsx @@ -1,4 +1,4 @@ -import { DraftInputId } from '@tloncorp/shared/api'; +import { DraftInputId } from '@tloncorp/api'; import { useComponentsKitContext } from '../../contexts/componentsKits'; import { DraftInputContext } from '../draftInputs'; diff --git a/packages/app/ui/components/Channel/PostView.tsx b/packages/app/ui/components/Channel/PostView.tsx index 9c0d73aae7..744f46ae3d 100644 --- a/packages/app/ui/components/Channel/PostView.tsx +++ b/packages/app/ui/components/Channel/PostView.tsx @@ -1,5 +1,5 @@ import { JSONValue } from '@tloncorp/shared'; -import { ChannelContentConfiguration } from '@tloncorp/shared/api'; +import { ChannelContentConfiguration } from '@tloncorp/api'; import { useMemo } from 'react'; import { useChannelContext } from '../../contexts'; diff --git a/packages/app/ui/components/Channel/index.tsx b/packages/app/ui/components/Channel/index.tsx index ac8e509f2e..0b306e544b 100644 --- a/packages/app/ui/components/Channel/index.tsx +++ b/packages/app/ui/components/Channel/index.tsx @@ -14,11 +14,11 @@ import { ChannelContentConfiguration, isDmChannelId, isGroupDmChannelId, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as domain from '@tloncorp/shared/domain'; import * as logic from '@tloncorp/shared/logic'; -import { JSONContent } from '@tloncorp/shared/urbit'; +import { JSONContent } from '@tloncorp/api/urbit'; import { useIsWindowNarrow } from '@tloncorp/ui'; import { forwardRef, diff --git a/packages/app/ui/components/ChannelFromTemplateView.tsx b/packages/app/ui/components/ChannelFromTemplateView.tsx index 4a718001bc..3e18cf20e5 100644 --- a/packages/app/ui/components/ChannelFromTemplateView.tsx +++ b/packages/app/ui/components/ChannelFromTemplateView.tsx @@ -5,7 +5,7 @@ import { deleteChannel, useChannelHooksPreview, } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { useIsWindowNarrow } from '@tloncorp/ui'; import { Button } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/ChatMessage/ChatMessageActions/MessageActions.tsx b/packages/app/ui/components/ChatMessage/ChatMessageActions/MessageActions.tsx index 4ff8d93ef0..709f9bfe24 100644 --- a/packages/app/ui/components/ChatMessage/ChatMessageActions/MessageActions.tsx +++ b/packages/app/ui/components/ChatMessage/ChatMessageActions/MessageActions.tsx @@ -1,6 +1,6 @@ import Clipboard from '@react-native-clipboard/clipboard'; import { ChannelAction } from '@tloncorp/shared'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { Attachment } from '@tloncorp/shared/domain'; import * as logic from '@tloncorp/shared/logic'; diff --git a/packages/app/ui/components/ChatOptionsSheet.tsx b/packages/app/ui/components/ChatOptionsSheet.tsx index f8f1e6d05b..8b495dab27 100644 --- a/packages/app/ui/components/ChatOptionsSheet.tsx +++ b/packages/app/ui/components/ChatOptionsSheet.tsx @@ -1,7 +1,7 @@ import { featureFlags } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { Icon, useIsWindowNarrow } from '@tloncorp/ui'; import { IconButton } from '@tloncorp/ui'; import { isEqual } from 'lodash'; diff --git a/packages/app/ui/components/ConnectionStatus.tsx b/packages/app/ui/components/ConnectionStatus.tsx index 52013531c9..34d4fe8605 100644 --- a/packages/app/ui/components/ConnectionStatus.tsx +++ b/packages/app/ui/components/ConnectionStatus.tsx @@ -1,7 +1,7 @@ import { ConnectionState, ConnectionStatus as ConnectionStatusType, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import { Text } from '@tloncorp/ui'; import { useMemo } from 'react'; import { Pressable } from 'react-native'; diff --git a/packages/app/ui/components/ContentReference/ContentReference.tsx b/packages/app/ui/components/ContentReference/ContentReference.tsx index 4c8291bc65..80d2783f62 100644 --- a/packages/app/ui/components/ContentReference/ContentReference.tsx +++ b/packages/app/ui/components/ContentReference/ContentReference.tsx @@ -1,7 +1,7 @@ // tamagui-ignore import * as db from '@tloncorp/shared/db'; import { ContentReference } from '@tloncorp/shared/domain'; -import { getChannelType } from '@tloncorp/shared/urbit'; +import { getChannelType } from '@tloncorp/api/urbit'; import { IconType } from '@tloncorp/ui'; import { Text } from '@tloncorp/ui'; import React, { createContext } from 'react'; diff --git a/packages/app/ui/components/EditableProfileImages.tsx b/packages/app/ui/components/EditableProfileImages.tsx index e9c76e86b0..030a0363a7 100644 --- a/packages/app/ui/components/EditableProfileImages.tsx +++ b/packages/app/ui/components/EditableProfileImages.tsx @@ -1,4 +1,4 @@ -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { Attachment } from '@tloncorp/shared/domain'; import { Icon } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/GroupMembersScreenView.tsx b/packages/app/ui/components/GroupMembersScreenView.tsx index dbd431046c..df7b6f4092 100644 --- a/packages/app/ui/components/GroupMembersScreenView.tsx +++ b/packages/app/ui/components/GroupMembersScreenView.tsx @@ -1,4 +1,4 @@ -import { parseGroupId } from '@tloncorp/shared/api'; +import { parseGroupId } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { SectionListHeader } from '@tloncorp/ui'; import Fuse from 'fuse.js'; diff --git a/packages/app/ui/components/ManageChannels/CreateChannelSheet.tsx b/packages/app/ui/components/ManageChannels/CreateChannelSheet.tsx index 36c8efc8e2..f4a58452df 100644 --- a/packages/app/ui/components/ManageChannels/CreateChannelSheet.tsx +++ b/packages/app/ui/components/ManageChannels/CreateChannelSheet.tsx @@ -12,7 +12,7 @@ import { allCollectionRenderers, allContentRenderers, allDraftInputs, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { objectEntries } from '@tloncorp/shared/utils'; import { Button, Icon, IconButton, Text } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/MessageInput/MessageInputBase.tsx b/packages/app/ui/components/MessageInput/MessageInputBase.tsx index a48485aec8..3e33dc5610 100644 --- a/packages/app/ui/components/MessageInput/MessageInputBase.tsx +++ b/packages/app/ui/components/MessageInput/MessageInputBase.tsx @@ -1,7 +1,7 @@ import type { BridgeState, EditorBridge } from '@10play/tentap-editor'; import * as db from '@tloncorp/shared/db'; import type * as domain from '@tloncorp/shared/domain'; -import { JSONContent, Story } from '@tloncorp/shared/urbit'; +import { JSONContent, Story } from '@tloncorp/api/urbit'; import { Button, FloatingActionButton, Icon } from '@tloncorp/ui'; import { ImagePickerAsset } from 'expo-image-picker'; import { memo } from 'react'; diff --git a/packages/app/ui/components/MessageInput/helpers.ts b/packages/app/ui/components/MessageInput/helpers.ts index 88ffefef22..b65bc5e3d0 100644 --- a/packages/app/ui/components/MessageInput/helpers.ts +++ b/packages/app/ui/components/MessageInput/helpers.ts @@ -8,7 +8,7 @@ import { JSONContent, constructStory, isInline, -} from '@tloncorp/shared/urbit'; +} from '@tloncorp/api/urbit'; const logger = createDevLogger('processReference', true); diff --git a/packages/app/ui/components/MessageInput/index.tsx b/packages/app/ui/components/MessageInput/index.tsx index 22d4f4ca02..16fa290a93 100644 --- a/packages/app/ui/components/MessageInput/index.tsx +++ b/packages/app/ui/components/MessageInput/index.tsx @@ -28,18 +28,18 @@ import { import { contentReferenceToCite, toContentReference, -} from '@tloncorp/shared/api'; +} from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as domain from '@tloncorp/shared/domain'; import * as logic from '@tloncorp/shared/logic'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { Inline, JSONContent, citeToPath, isInline, pathToCite, -} from '@tloncorp/shared/urbit'; +} from '@tloncorp/api/urbit'; import { HEADER_HEIGHT } from '@tloncorp/ui'; import { forwardRef, diff --git a/packages/app/ui/components/NotificationLevelSelector.tsx b/packages/app/ui/components/NotificationLevelSelector.tsx index fe5747d244..61f4c445f9 100644 --- a/packages/app/ui/components/NotificationLevelSelector.tsx +++ b/packages/app/ui/components/NotificationLevelSelector.tsx @@ -1,4 +1,4 @@ -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { useMemo } from 'react'; import { Platform } from 'react-native'; diff --git a/packages/app/ui/components/PhoneAttestationPane.tsx b/packages/app/ui/components/PhoneAttestationPane.tsx index 123d6a7e5b..0cc5be0a52 100644 --- a/packages/app/ui/components/PhoneAttestationPane.tsx +++ b/packages/app/ui/components/PhoneAttestationPane.tsx @@ -1,4 +1,4 @@ -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as domain from '@tloncorp/shared/domain'; import { Button, LoadingSpinner, Text, triggerHaptic } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/PostCollectionView.tsx b/packages/app/ui/components/PostCollectionView.tsx index eddf45469f..83a1893a79 100644 --- a/packages/app/ui/components/PostCollectionView.tsx +++ b/packages/app/ui/components/PostCollectionView.tsx @@ -1,4 +1,4 @@ -import { ChannelContentConfiguration } from '@tloncorp/shared/api'; +import { ChannelContentConfiguration } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import { Ref, useMemo } from 'react'; diff --git a/packages/app/ui/components/PostScreenView.tsx b/packages/app/ui/components/PostScreenView.tsx index 08aaa613bb..dc5e235efc 100644 --- a/packages/app/ui/components/PostScreenView.tsx +++ b/packages/app/ui/components/PostScreenView.tsx @@ -4,12 +4,12 @@ import { makePrettyDayAndTime, useDebouncedValue, } from '@tloncorp/shared'; -import { ChannelContentConfiguration } from '@tloncorp/shared/api'; +import { ChannelContentConfiguration } from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import type * as domain from '@tloncorp/shared/domain'; import * as store from '@tloncorp/shared/store'; -import * as urbit from '@tloncorp/shared/urbit'; -import { JSONContent } from '@tloncorp/shared/urbit'; +import * as urbit from '@tloncorp/api/urbit'; +import { JSONContent } from '@tloncorp/api/urbit'; import { Carousel, ForwardingProps } from '@tloncorp/ui'; import { KeyboardAvoidingView } from '@tloncorp/ui'; import { diff --git a/packages/app/ui/components/TwtitterAttestationPane.tsx b/packages/app/ui/components/TwtitterAttestationPane.tsx index 6758585f14..167da49dc4 100644 --- a/packages/app/ui/components/TwtitterAttestationPane.tsx +++ b/packages/app/ui/components/TwtitterAttestationPane.tsx @@ -1,4 +1,4 @@ -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as domain from '@tloncorp/shared/domain'; import { Button, LoadingSpinner, Text, triggerHaptic } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/UserProfileScreenView.tsx b/packages/app/ui/components/UserProfileScreenView.tsx index 4a143c3abd..5a45e66666 100644 --- a/packages/app/ui/components/UserProfileScreenView.tsx +++ b/packages/app/ui/components/UserProfileScreenView.tsx @@ -1,6 +1,6 @@ import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import * as api from '@tloncorp/shared/api'; +import * as api from '@tloncorp/api'; import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; import { useCopy, useToast } from '@tloncorp/ui'; diff --git a/packages/app/ui/components/draftInputs/LinkInput.tsx b/packages/app/ui/components/draftInputs/LinkInput.tsx index aedf7bb2f5..453eed320d 100644 --- a/packages/app/ui/components/draftInputs/LinkInput.tsx +++ b/packages/app/ui/components/draftInputs/LinkInput.tsx @@ -8,7 +8,7 @@ import { } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { DEFAULT_BOTTOM_PADDING, HEADER_HEIGHT, diff --git a/packages/app/ui/components/draftInputs/shared.ts b/packages/app/ui/components/draftInputs/shared.ts index 30f764ccc9..b9e5c5f055 100644 --- a/packages/app/ui/components/draftInputs/shared.ts +++ b/packages/app/ui/components/draftInputs/shared.ts @@ -1,7 +1,7 @@ import { JSONValue } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; import type * as domain from '@tloncorp/shared/domain'; -import { JSONContent } from '@tloncorp/shared/urbit'; +import { JSONContent } from '@tloncorp/api/urbit'; import { Dispatch, SetStateAction } from 'react'; export type GalleryDraftType = 'caption' | 'text'; diff --git a/packages/app/ui/contexts/chatOptions.tsx b/packages/app/ui/contexts/chatOptions.tsx index 11beb4d197..82c296511d 100644 --- a/packages/app/ui/contexts/chatOptions.tsx +++ b/packages/app/ui/contexts/chatOptions.tsx @@ -1,7 +1,7 @@ import * as db from '@tloncorp/shared/db'; import * as logic from '@tloncorp/shared/logic'; import * as store from '@tloncorp/shared/store'; -import * as ub from '@tloncorp/shared/urbit'; +import * as ub from '@tloncorp/api/urbit'; import { ConfirmDialog, useIsWindowNarrow } from '@tloncorp/ui'; import { ReactNode, diff --git a/packages/app/ui/contexts/componentsKits.tsx b/packages/app/ui/contexts/componentsKits.tsx index 7268df3499..a0b7e83d0c 100644 --- a/packages/app/ui/contexts/componentsKits.tsx +++ b/packages/app/ui/contexts/componentsKits.tsx @@ -5,7 +5,7 @@ import { PostContentRendererId, } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; -import { Story } from '@tloncorp/shared/urbit'; +import { Story } from '@tloncorp/api/urbit'; import { ReactElement, createContext, useContext } from 'react'; import { Text } from 'react-native'; diff --git a/packages/app/ui/hooks/contactSorters.ts b/packages/app/ui/hooks/contactSorters.ts index 4041165fe8..343ce9b7d9 100644 --- a/packages/app/ui/hooks/contactSorters.ts +++ b/packages/app/ui/hooks/contactSorters.ts @@ -1,6 +1,6 @@ import { createDevLogger, logSyncDuration } from '@tloncorp/shared'; import * as db from '@tloncorp/shared/db'; -import { preSig } from '@tloncorp/shared/urbit'; +import { preSig } from '@tloncorp/api/urbit'; import anyAscii from 'any-ascii'; import { useMemo } from 'react'; import { valid } from '@urbit/aura'; diff --git a/packages/app/ui/utils/user.ts b/packages/app/ui/utils/user.ts index 1c24739c16..bbcc3def48 100644 --- a/packages/app/ui/utils/user.ts +++ b/packages/app/ui/utils/user.ts @@ -1,5 +1,5 @@ import * as db from '@tloncorp/shared/db'; -import * as urbit from '@tloncorp/shared/urbit'; +import * as urbit from '@tloncorp/api/urbit'; import { p } from '@urbit/aura'; const USER_ID_SEPARATORS = /([_^-])/; diff --git a/packages/editor/global.d.ts b/packages/editor/global.d.ts index 63e7a97975..378525f360 100644 --- a/packages/editor/global.d.ts +++ b/packages/editor/global.d.ts @@ -1,4 +1,4 @@ -import { Clubs, ContactRolodex, Group } from '@tloncorp/shared/urbit'; +import { Clubs, ContactRolodex, Group } from '@tloncorp/api/urbit'; declare global { interface Window { diff --git a/packages/scripts/src/index.ts b/packages/scripts/src/index.ts index 12b141471a..5afaa7587b 100644 --- a/packages/scripts/src/index.ts +++ b/packages/scripts/src/index.ts @@ -1,12 +1,12 @@ -import { parseContactUpdateEvent } from '@tloncorp/shared/api'; +import { parseContactUpdateEvent } from '@tloncorp/api'; import { getTextContent } from '@tloncorp/shared/logic'; -import type * as ub from '@tloncorp/shared/urbit'; +import type * as ub from '@tloncorp/api/urbit'; import { ActivityIncomingEvent, getIdParts, getSourceForEvent, sourceToString, -} from '@tloncorp/shared/urbit/activity'; +} from '@tloncorp/api/urbit/activity'; import { render, da } from '@urbit/aura'; type PreviewContentNode = diff --git a/packages/shared/package.json b/packages/shared/package.json index b664f7d650..700775506a 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -8,14 +8,24 @@ ".": "./src/index.ts", "./api": "./src/api/index.ts", "./client": "./src/client/index.ts", + "./debug": "./src/debug.ts", "./domain": "./src/domain/index.ts", + "./domain/*": "./src/domain/*.ts", "./db": "./src/db/index.ts", "./db/client": "./src/db/client.ts", "./db/migrations": "./src/db/migrations/index.ts", + "./db/schema": "./src/db/schema.ts", "./db/types": "./src/db/types.ts", "./logic": "./src/logic/index.ts", + "./logic/branch": "./src/logic/index.ts", + "./logic/deeplinks": "./src/logic/index.ts", + "./logic/hosting": "./src/logic/index.ts", + "./logic/noun": "./src/logic/index.ts", + "./logic/pinning": "./src/logic/index.ts", + "./logic/*": "./src/logic/*.ts", "./perf": "./src/perf.ts", "./store": "./src/store/index.ts", + "./store/reactQuery": "./src/store/reactQuery.ts", "./urbit": "./src/urbit/index.ts", "./urbit/activity": "./src/urbit/activity.ts", "./urbit/channel": "./src/urbit/channel.ts", @@ -28,7 +38,8 @@ "./urbit/sigil": "./src/urbit/sigil.ts", "./urbit/ui": "./src/urbit/ui.ts", "./urbit/volume": "./src/urbit/volume.ts", - "./utils": "./src/utils/index.ts" + "./utils": "./src/utils/index.ts", + "./utils/*": "./src/utils/*.ts" }, "scripts": { "preinstall": "rm -f ./tsconfig.tsbuildinfo", @@ -50,6 +61,7 @@ ] }, "dependencies": { + "@tloncorp/api": "workspace:*", "@urbit/aura": "^3.0.0", "@urbit/nockjs": "^1.6.0", "any-ascii": "^0.3.1", diff --git a/packages/shared/src/api/negotiationApi.ts b/packages/shared/src/api/negotiationApi.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/shared/src/db/changeListener.ts b/packages/shared/src/db/changeListener.ts index f7070b9699..7b93e9a52a 100644 --- a/packages/shared/src/db/changeListener.ts +++ b/packages/shared/src/db/changeListener.ts @@ -1,4 +1,4 @@ -import { queryClient } from '../api'; +import { queryClient } from '@tloncorp/api'; import { createDevLogger } from '../debug'; const logger = createDevLogger('db:changeListener', false); diff --git a/packages/shared/src/db/keyValue.ts b/packages/shared/src/db/keyValue.ts index 90fb95b198..fa7121509e 100644 --- a/packages/shared/src/db/keyValue.ts +++ b/packages/shared/src/db/keyValue.ts @@ -4,10 +4,10 @@ import { StorageConfiguration, StorageCredentials, StorageService, -} from '../api'; +} from '@tloncorp/api'; import { NodeBootPhase, SignupParams, WayfindingProgress } from '../domain'; import { Lure } from '../logic'; -import * as ub from '../urbit'; +import * as ub from '@tloncorp/api/urbit'; import { createStorageItem } from './storageItem'; export const pushNotificationSettings = diff --git a/packages/shared/src/db/modelBuilders.ts b/packages/shared/src/db/modelBuilders.ts index 8cd1225202..76f8298865 100644 --- a/packages/shared/src/db/modelBuilders.ts +++ b/packages/shared/src/db/modelBuilders.ts @@ -1,13 +1,13 @@ import { da } from '@urbit/aura'; -import * as api from '../api'; -import { getCanonicalPostId } from '../api/apiUtils'; +import * as api from '@tloncorp/api'; +import { getCanonicalPostId } from '@tloncorp/api'; import * as db from '../db'; import * as domain from '../domain'; import * as logic from '../logic'; import { convertToAscii } from '../logic'; -import * as ub from '../urbit'; -import { getChannelKindFromType } from '../urbit'; +import * as ub from '@tloncorp/api/urbit'; +import { getChannelKindFromType } from '@tloncorp/api/urbit'; import * as types from './types'; export function assembleNewChannelIdAndName({ diff --git a/packages/shared/src/db/queries.test.ts b/packages/shared/src/db/queries.test.ts index 58eec71513..de96e2b4be 100644 --- a/packages/shared/src/db/queries.test.ts +++ b/packages/shared/src/db/queries.test.ts @@ -1,7 +1,7 @@ import { expect, test } from 'vitest'; -import { v0PeersToClientProfiles } from '../api'; -import { toClientGroupsV7 } from '../api/groupsApi'; +import { v0PeersToClientProfiles } from '@tloncorp/api'; +import { toClientGroupsV7 } from '@tloncorp/api'; import * as schema from '../db/schema'; import { syncContacts, syncInitData } from '../store/sync'; import contactBookResponse from '../test/contactBook.json'; @@ -14,7 +14,7 @@ import { } from '../test/helpers'; import initResponse from '../test/init.json'; import suggestedContactsResponse from '../test/suggestedContacts.json'; -import type * as ub from '../urbit/groups'; +import type * as ub from '@tloncorp/api/urbit/groups'; import * as queries from './queries'; import { Post } from './types'; diff --git a/packages/shared/src/db/queries.ts b/packages/shared/src/db/queries.ts index 25ed65125e..09a3de10c1 100644 --- a/packages/shared/src/db/queries.ts +++ b/packages/shared/src/db/queries.ts @@ -31,8 +31,8 @@ import { ACTIVITY_SOURCE_PAGESIZE, ChannelInit, getCurrentUserId, -} from '../api'; -import { parseGroupId } from '../api/apiUtils'; +} from '@tloncorp/api'; +import { parseGroupId } from '@tloncorp/api'; import { createDevLogger } from '../debug'; import * as domain from '../domain'; import { appendContactIdToReplies, getCompositeGroups } from '../logic'; @@ -40,9 +40,9 @@ import { SourceActivityEvents, interleaveActivityEvents, toSourceActivityEvents, -} from '../logic/activity'; +} from '@tloncorp/api/lib/activity'; import { Session } from '../store'; -import { Rank } from '../urbit'; +import { Rank } from '@tloncorp/api/urbit'; import { processBatchOperation } from './dbUtils'; import { createDmChannelsForNewContacts } from './modelBuilders'; import { diff --git a/packages/shared/src/db/query.ts b/packages/shared/src/db/query.ts index ce5b07cc50..b849846591 100644 --- a/packages/shared/src/db/query.ts +++ b/packages/shared/src/db/query.ts @@ -1,6 +1,6 @@ import { sql } from 'drizzle-orm'; -import { queryClient } from '../api'; +import { queryClient } from '@tloncorp/api'; import { createDevLogger, escapeLog, listDebugLabel } from '../debug'; import { AnalyticsEvent } from '../domain'; import { startTrace } from '../perf'; diff --git a/packages/shared/src/db/schema.ts b/packages/shared/src/db/schema.ts index dac9d32955..236e99fd46 100644 --- a/packages/shared/src/db/schema.ts +++ b/packages/shared/src/db/schema.ts @@ -8,8 +8,8 @@ import { uniqueIndex, } from 'drizzle-orm/sqlite-core'; -import { ChannelContentConfiguration } from '../api'; -import { ExtendedEventType, NotificationLevel, Rank } from '../urbit'; +import { ChannelContentConfiguration } from '@tloncorp/api'; +import { ExtendedEventType, NotificationLevel, Rank } from '@tloncorp/api/urbit'; const boolean = (name: string) => { return integer(name, { mode: 'boolean' }); diff --git a/packages/shared/src/db/storageItem.ts b/packages/shared/src/db/storageItem.ts index 8f726a5a4c..ec73e710fc 100644 --- a/packages/shared/src/db/storageItem.ts +++ b/packages/shared/src/db/storageItem.ts @@ -1,6 +1,6 @@ import { QueryKey, useQuery } from '@tanstack/react-query'; -import { queryClient } from '../api'; +import { queryClient } from '@tloncorp/api'; import { createDevLogger } from '../debug'; import { Stringified } from '../utils'; import { getStorageMethods } from './getStorageMethods'; diff --git a/packages/shared/src/domain/index.ts b/packages/shared/src/domain/index.ts index 38cdf2861d..144bf1f1ef 100644 --- a/packages/shared/src/domain/index.ts +++ b/packages/shared/src/domain/index.ts @@ -1,14 +1,14 @@ -export * from './analytics'; -export * from './attachment'; -export * from './attestations'; -export * from './constants'; -export * from './groupTemplates'; -export * from './hosting'; -export * from './invite.types'; -export * from './onboarding'; -export * from './post'; -export * from './references'; -export * from './system'; -export * from './systemContacts'; -export * from './uploads'; -export * from './wayfinding'; +export * from '@tloncorp/api/types/analytics'; +export * from '@tloncorp/api/types/attachment'; +export * from '@tloncorp/api/types/attestations'; +export * from '@tloncorp/api/types/constants'; +export * from '@tloncorp/api/types/groupTemplates'; +export * from '@tloncorp/api/types/hosting'; +export * from '@tloncorp/api/types/invite.types'; +export * from '@tloncorp/api/types/onboarding'; +export * from '@tloncorp/api/types/post'; +export * from '@tloncorp/api/types/references'; +export * from '@tloncorp/api/types/system'; +export * from '@tloncorp/api/types/systemContactModels'; +export * from '@tloncorp/api/types/uploads'; +export * from '@tloncorp/api/types/wayfinding'; diff --git a/packages/shared/src/electronAuth.ts b/packages/shared/src/electronAuth.ts new file mode 100644 index 0000000000..d6893faf8b --- /dev/null +++ b/packages/shared/src/electronAuth.ts @@ -0,0 +1,72 @@ +// Authentication utility for Electron-specific functionality +import { createDevLogger } from './debug'; + +const logger = createDevLogger('electronAuth', false); + +// Type definitions +export interface AuthInfo { + ship: string; + shipUrl: string; + authCookie: string; +} + +// Helper to check if we're in Electron +export const isElectronEnv = (): boolean => { + if (typeof window !== 'undefined') { + return 'electronAPI' in window; + } + return false; +}; + +/** + * Store authentication information + * @param authInfo Authentication details to store + * @returns Promise resolving to success status + */ +export const storeAuthInfo = async (authInfo: AuthInfo): Promise => { + if (isElectronEnv()) { + try { + // Use type assertion to tell TypeScript to trust us + const api = (window as any).electronAPI; + return (await api?.storeAuthInfo?.(authInfo)) ?? false; + } catch (error) { + logger.error('Failed to store auth info:', error); + return false; + } + } + return false; +}; + +/** + * Retrieve stored authentication information + * @returns Promise resolving to auth info or null if not found + */ +export const getAuthInfo = async (): Promise => { + if (isElectronEnv()) { + try { + const api = (window as any).electronAPI; + return (await api?.getAuthInfo?.()) ?? null; + } catch (error) { + logger.error('Failed to get auth info:', error); + return null; + } + } + return null; +}; + +/** + * Clear stored authentication information + * @returns Promise resolving to success status + */ +export const clearAuthInfo = async (): Promise => { + if (isElectronEnv()) { + try { + const api = (window as any).electronAPI; + return (await api?.clearAuthInfo?.()) ?? false; + } catch (error) { + logger.error('Failed to clear auth info:', error); + return false; + } + } + return false; +}; diff --git a/packages/shared/src/electrtonAuth.ts b/packages/shared/src/electrtonAuth.ts index 3e5f972317..f46af89b68 100644 --- a/packages/shared/src/electrtonAuth.ts +++ b/packages/shared/src/electrtonAuth.ts @@ -1,72 +1 @@ -// Authentication utility for Electron-specific functionality -import { createDevLogger } from './debug'; - -const logger = createDevLogger('electronAuth', false); - -// Type definitions -export interface AuthInfo { - ship: string; - shipUrl: string; - authCookie: string; -} - -// Helper to check if we're in Electron -export const isElectronEnv = (): boolean => { - if (typeof window !== 'undefined') { - return 'electronAPI' in window; - } - return false; -}; - -/** - * Store authentication information - * @param authInfo Authentication details to store - * @returns Promise resolving to success status - */ -export const storeAuthInfo = async (authInfo: AuthInfo): Promise => { - if (isElectronEnv()) { - try { - // Use type assertion to tell TypeScript to trust us - const api = (window as any).electronAPI; - return await api?.storeAuthInfo?.(authInfo) ?? false; - } catch (error) { - logger.error('Failed to store auth info:', error); - return false; - } - } - return false; -}; - -/** - * Retrieve stored authentication information - * @returns Promise resolving to auth info or null if not found - */ -export const getAuthInfo = async (): Promise => { - if (isElectronEnv()) { - try { - const api = (window as any).electronAPI; - return await api?.getAuthInfo?.() ?? null; - } catch (error) { - logger.error('Failed to get auth info:', error); - return null; - } - } - return null; -}; - -/** - * Clear stored authentication information - * @returns Promise resolving to success status - */ -export const clearAuthInfo = async (): Promise => { - if (isElectronEnv()) { - try { - const api = (window as any).electronAPI; - return await api?.clearAuthInfo?.() ?? false; - } catch (error) { - logger.error('Failed to clear auth info:', error); - return false; - } - } - return false; -}; +export * from './electronAuth'; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 0bfa92abba..9997be181a 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,6 +1,6 @@ -export * as ChannelAction from './types/ChannelActions'; -export type { GroupMeta } from './types/groups'; -export { JSONValue } from './types/JSONValue'; +export * as ChannelAction from '@tloncorp/api/types/ChannelActions'; +export type { GroupMeta } from '@tloncorp/api/types/groups'; +export { JSONValue } from '@tloncorp/api/types/JSONValue'; export type { NativeWebViewOptions, NativeCommand, @@ -9,17 +9,17 @@ export type { ActiveTabChange, WebAppAction, WebAppCommand, -} from './types/native'; +} from '@tloncorp/api/types/native'; export type { PostCollectionConfiguration, PostCollectionLayout, PostCollectionLayoutType, -} from './types/PostCollectionConfiguration'; +} from '@tloncorp/api/types/PostCollectionConfiguration'; export { configurationFromChannel, layoutForType, layoutTypeFromChannel, -} from './types/PostCollectionConfiguration'; +} from '@tloncorp/api/types/PostCollectionConfiguration'; export { CollectionRendererId, ChannelContentConfiguration, @@ -28,17 +28,17 @@ export { allCollectionRenderers, allDraftInputs, allContentRenderers, -} from './api/channelContentConfig'; +} from '@tloncorp/api'; export * from './logic'; export * from './store'; export * from './domain'; export * as sync from './store/sync'; -export * as utils from './logic/utils'; +export * as utils from '@tloncorp/api/lib/utils'; export * as tiptap from './logic/tiptap'; export * as utilHooks from './logic/utilHooks'; export * from './debug'; export * from './perf'; -export * from './electrtonAuth'; +export * from './electronAuth'; export * from '@urbit/aura'; export * from './store/dbHooks'; export * from './utils'; diff --git a/packages/shared/src/logic/content-helpers.test.ts b/packages/shared/src/logic/content-helpers.test.ts index a9f5a2eb61..851b9f40e4 100644 --- a/packages/shared/src/logic/content-helpers.test.ts +++ b/packages/shared/src/logic/content-helpers.test.ts @@ -1,6 +1,9 @@ import { expect, test } from 'vitest'; -import { Mention, textAndMentionsToContent } from './content-helpers'; +import { + Mention, + textAndMentionsToContent, +} from '@tloncorp/api/lib/content-helpers'; test('textAndMentionsToContent: multiline mentions', () => { const text = "User One Hello, world! here's more to the message.\nUser Two"; diff --git a/packages/shared/src/logic/embed.ts b/packages/shared/src/logic/embed.ts index d4451ffba5..0fa4bbf578 100644 --- a/packages/shared/src/logic/embed.ts +++ b/packages/shared/src/logic/embed.ts @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import { useCallback } from 'react'; -import { isValidUrl, jsonFetch } from './utils'; +import { isValidUrl, jsonFetch } from '@tloncorp/api/lib/utils'; const OEMBED_PROVIDER = 'https://noembed.com/embed'; diff --git a/packages/shared/src/logic/index.ts b/packages/shared/src/logic/index.ts index 69f60039ef..76eed0ba99 100644 --- a/packages/shared/src/logic/index.ts +++ b/packages/shared/src/logic/index.ts @@ -1,17 +1,17 @@ export * from './utilHooks'; -export * from './utils'; -export * from './references'; +export * from '@tloncorp/api/lib/utils'; +export * from '@tloncorp/api/lib/references'; export * from './embed'; -export * from './types'; -export * from './activity'; -export * from './branch'; -export * from './deeplinks'; -export * as featureFlags from './featureFlags'; +export * from '@tloncorp/api/lib/types'; +export * from '@tloncorp/api/lib/activity'; +export * from '@tloncorp/api/lib/branch'; +export * from '@tloncorp/api/lib/deeplinks'; +export * as featureFlags from '@tloncorp/api/lib/featureFlags'; export * from './tiptap'; -export * from './hosting'; -export * from './noun'; -export * from './wayfinding'; -export * from './postContent'; -export * from './content-helpers'; -export * from './pinning'; +export * from '@tloncorp/api/lib/hosting'; +export * from '@tloncorp/api/lib/noun'; export * from './markdown'; +export * from '@tloncorp/api/lib/wayfinding'; +export * from '@tloncorp/api/lib/postContent'; +export * from '@tloncorp/api/lib/content-helpers'; +export * from '@tloncorp/api/lib/pinning'; diff --git a/packages/shared/src/logic/navigation.ts b/packages/shared/src/logic/navigation.ts index 72ec700494..e14dbe228f 100644 --- a/packages/shared/src/logic/navigation.ts +++ b/packages/shared/src/logic/navigation.ts @@ -1,4 +1,4 @@ -import { MobileNavTab } from '../types/native'; +import { MobileNavTab } from '@tloncorp/api/types/native'; export function parseActiveTab(pathname: string): MobileNavTab | null { const parsedPath = trimFullPath(pathname); diff --git a/packages/shared/src/logic/pinning.test.ts b/packages/shared/src/logic/pinning.test.ts index 90f3d65491..6614f41fc3 100644 --- a/packages/shared/src/logic/pinning.test.ts +++ b/packages/shared/src/logic/pinning.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { Channel, Group, Pin, whichPin } from './pinning'; +import { Channel, Group, Pin, whichPin } from '@tloncorp/api/lib/pinning'; describe('whichPin', () => { test('should return pin-channel action when channel has no pin', () => { diff --git a/packages/shared/src/logic/tiptap.test.ts b/packages/shared/src/logic/tiptap.test.ts index 7c01e22d5c..7aaca68704 100644 --- a/packages/shared/src/logic/tiptap.test.ts +++ b/packages/shared/src/logic/tiptap.test.ts @@ -1,6 +1,6 @@ import { expect, test, describe } from 'vitest'; -import { Block, Inline, JSONContent } from '../urbit'; +import { Block, Inline, JSONContent } from '@tloncorp/api/urbit'; import { JSONToInlines } from './tiptap'; test('tiptap: test mixed text, inline code and code block with langs', () => { diff --git a/packages/shared/src/logic/tiptap.ts b/packages/shared/src/logic/tiptap.ts index 8b6051eb43..ad193209dd 100644 --- a/packages/shared/src/logic/tiptap.ts +++ b/packages/shared/src/logic/tiptap.ts @@ -8,10 +8,10 @@ import { JSONContent } from '@tiptap/react'; import { valid } from '@urbit/aura'; import { isEqual, reduce } from 'lodash'; -import { Story } from '../urbit/channel'; -import { Block, Cite, HeaderLevel, Listing } from '../urbit/content'; -import { Inline, InlineKey, Link, Task } from '../urbit/content'; -import { citeToPath, pathToCite, preSig, desig } from '../urbit/utils'; +import { Story } from '@tloncorp/api/urbit/channel'; +import { Block, Cite, HeaderLevel, Listing } from '@tloncorp/api/urbit/content'; +import { Inline, InlineKey, Link, Task } from '@tloncorp/api/urbit/content'; +import { citeToPath, pathToCite, preSig, desig } from '@tloncorp/api/urbit/utils'; export const ALL_MENTION_ID = '-all-'; diff --git a/packages/shared/src/logic/utils.test.ts b/packages/shared/src/logic/utils.test.ts index 7d8cf868b1..e5a42c5f49 100644 --- a/packages/shared/src/logic/utils.test.ts +++ b/packages/shared/src/logic/utils.test.ts @@ -3,8 +3,8 @@ import { describe, expect, it } from 'vitest'; import * as db from '../db'; import { GroupPrivacy } from '../db/schema'; import { PersonalGroupSlugs } from '../domain'; -import { getModelAnalytics, normalizeUrbitColor } from './utils'; -import { isPersonalGroup } from './wayfinding'; +import { getModelAnalytics, normalizeUrbitColor } from '@tloncorp/api/lib/utils'; +import { isPersonalGroup } from '@tloncorp/api/lib/wayfinding'; describe('normalizeUrbitColor', () => { describe('the user submits a color hex value with one or more leading zeroes', () => { diff --git a/packages/shared/src/store/activityActions.ts b/packages/shared/src/store/activityActions.ts index 09bdcf2845..fb4e1e1e3b 100644 --- a/packages/shared/src/store/activityActions.ts +++ b/packages/shared/src/store/activityActions.ts @@ -1,11 +1,11 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { BASE_UNREADS_SINGLETON_KEY } from '../db/schema'; import { createDevLogger } from '../debug'; import { isGroupChannelId } from '../logic'; import * as logic from '../logic'; -import * as ub from '../urbit'; -import { whomIsMultiDm } from '../urbit'; +import * as ub from '@tloncorp/api/urbit'; +import { whomIsMultiDm } from '@tloncorp/api/urbit'; const logger = createDevLogger('activityActions', false); diff --git a/packages/shared/src/store/channelActions.ts b/packages/shared/src/store/channelActions.ts index b5abce52af..7d66133f4a 100644 --- a/packages/shared/src/store/channelActions.ts +++ b/packages/shared/src/store/channelActions.ts @@ -1,15 +1,15 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import { ChannelContentConfiguration, StructuredChannelDescriptionPayload, -} from '../api/channelContentConfig'; -import { TimeoutError } from '../api/urbit'; +} from '@tloncorp/api'; +import { TimeoutError } from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; import * as logic from '../logic'; import { getRandomId } from '../logic'; -import { GroupChannelV7, getChannelKindFromType } from '../urbit'; +import { GroupChannelV7, getChannelKindFromType } from '@tloncorp/api/urbit'; const logger = createDevLogger('ChannelActions', false); diff --git a/packages/shared/src/store/clientActions.ts b/packages/shared/src/store/clientActions.ts index 3c7d6607fe..c652e2908a 100644 --- a/packages/shared/src/store/clientActions.ts +++ b/packages/shared/src/store/clientActions.ts @@ -1,4 +1,4 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import { createDevLogger } from '../debug'; import { getInitializedClient, updateInitializedClient } from './session'; diff --git a/packages/shared/src/store/contactActions.ts b/packages/shared/src/store/contactActions.ts index 082e0011bf..ba15fe24c6 100644 --- a/packages/shared/src/store/contactActions.ts +++ b/packages/shared/src/store/contactActions.ts @@ -1,4 +1,4 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; diff --git a/packages/shared/src/store/dbHooks.ts b/packages/shared/src/store/dbHooks.ts index ee67d80c9b..bb38e5a243 100644 --- a/packages/shared/src/store/dbHooks.ts +++ b/packages/shared/src/store/dbHooks.ts @@ -6,13 +6,13 @@ import { import { isMatch, pick } from 'lodash'; import { useEffect, useMemo } from 'react'; -import * as api from '../api'; -import { getMessagesFilter } from '../api'; +import * as api from '@tloncorp/api'; +import { getMessagesFilter } from '@tloncorp/api'; +import { getConstants } from '@tloncorp/api/types/constants'; import * as db from '../db'; import { GroupedChats } from '../db/types'; -import { getConstants } from '../domain/constants'; import * as logic from '../logic'; -import * as ub from '../urbit'; +import * as ub from '@tloncorp/api/urbit'; import { hasCustomS3Creds, hasHostingUploadCreds } from './storage'; import { syncChannelPreivews, syncPostReference } from './sync'; import { keyFromQueryDeps, useKeyFromQueryDeps } from './useKeyFromQueryDeps'; diff --git a/packages/shared/src/store/dmActions.ts b/packages/shared/src/store/dmActions.ts index 850180a271..6c3cbf469a 100644 --- a/packages/shared/src/store/dmActions.ts +++ b/packages/shared/src/store/dmActions.ts @@ -1,4 +1,4 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; diff --git a/packages/shared/src/store/groupActions.ts b/packages/shared/src/store/groupActions.ts index 2b8ab68862..41fddd6dd4 100644 --- a/packages/shared/src/store/groupActions.ts +++ b/packages/shared/src/store/groupActions.ts @@ -1,15 +1,18 @@ import isEqual from 'lodash/isEqual'; -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { QueryCtx, batchEffects } from '../db/query'; import { GroupPrivacy } from '../db/schema'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; -import { GroupTemplateId, groupTemplatesById } from '../domain/groupTemplates'; +import { + GroupTemplateId, + groupTemplatesById, +} from '@tloncorp/api/types/groupTemplates'; import * as logic from '../logic'; import { getRandomId } from '../logic'; -import { createSectionId, getChannelKindFromType } from '../urbit'; +import { createSectionId, getChannelKindFromType } from '@tloncorp/api/urbit'; import { pinGroup } from './channelActions'; const logger = createDevLogger('groupActions', false); diff --git a/packages/shared/src/store/hostingActions.ts b/packages/shared/src/store/hostingActions.ts index 0d57e48a10..ae143ed178 100644 --- a/packages/shared/src/store/hostingActions.ts +++ b/packages/shared/src/store/hostingActions.ts @@ -1,4 +1,4 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import * as domain from '../domain'; diff --git a/packages/shared/src/store/inviteActions.ts b/packages/shared/src/store/inviteActions.ts index b783a01feb..b82b53e722 100644 --- a/packages/shared/src/store/inviteActions.ts +++ b/packages/shared/src/store/inviteActions.ts @@ -3,8 +3,8 @@ import { enableGroup, getCurrentUserId, groupsDescribe, -} from '../api'; -import * as api from '../api'; +} from '@tloncorp/api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent, getConstants } from '../domain'; @@ -17,7 +17,7 @@ import { getFlagParts, withRetry, } from '../logic'; -import { desig } from '../urbit'; +import { desig } from '@tloncorp/api/urbit'; import { syncGroupPreviews } from './sync'; const logger = createDevLogger('inviteActions', false); diff --git a/packages/shared/src/store/lanyardActions.ts b/packages/shared/src/store/lanyardActions.ts index c8b5295248..7e8ed86dd4 100644 --- a/packages/shared/src/store/lanyardActions.ts +++ b/packages/shared/src/store/lanyardActions.ts @@ -1,4 +1,4 @@ -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent, AnalyticsSeverity } from '../domain'; diff --git a/packages/shared/src/store/lure.ts b/packages/shared/src/store/lure.ts index b2c7ed1cae..5e49d97742 100644 --- a/packages/shared/src/store/lure.ts +++ b/packages/shared/src/store/lure.ts @@ -3,12 +3,12 @@ import produce from 'immer'; import { useEffect, useMemo, useState } from 'react'; import create from 'zustand'; -import { getCurrentUserId, scry, subscribeOnce } from '../api/urbit'; +import { getCurrentUserId, scry, subscribeOnce } from '@tloncorp/api'; +import { DeepLinkMetadata, createDeepLink } from '@tloncorp/api/lib/branch'; +import { asyncWithDefault } from '@tloncorp/api/lib/utils'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; -import { DeepLinkMetadata, createDeepLink } from '../logic/branch'; -import { asyncWithDefault } from '../logic/utils'; import { createGroupInviteLink } from './inviteActions'; interface LureMetadata { diff --git a/packages/shared/src/store/metagrabActions.ts b/packages/shared/src/store/metagrabActions.ts index 3adf277ec3..6dc33b014f 100644 --- a/packages/shared/src/store/metagrabActions.ts +++ b/packages/shared/src/store/metagrabActions.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; -import { getFallbackLinkMetadata, getLinkMetadata } from '../api'; +import { getFallbackLinkMetadata, getLinkMetadata } from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { diff --git a/packages/shared/src/store/postActions.test.ts b/packages/shared/src/store/postActions.test.ts index bac6ba5aea..f39c5fa90e 100644 --- a/packages/shared/src/store/postActions.test.ts +++ b/packages/shared/src/store/postActions.test.ts @@ -1,11 +1,11 @@ import * as $ from 'drizzle-orm'; import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; -import * as api from '../api'; -import { poke, scry } from '../api/urbit'; +import * as api from '@tloncorp/api'; +import { poke, scry } from '@tloncorp/api'; import * as db from '../db'; -import { Attachment, ImageAttachment } from '../domain/attachment'; -import { PostDataDraft } from '../domain/post'; +import { Attachment, ImageAttachment } from '@tloncorp/api/types/attachment'; +import { PostDataDraft } from '@tloncorp/api/types/post'; import { toPostData } from '../logic'; import { getClient, setupDatabaseTestSuite } from '../test/helpers'; import { finalizeAndSendPost } from './postActions'; diff --git a/packages/shared/src/store/postActions.ts b/packages/shared/src/store/postActions.ts index 59f5632e45..31f5964cc7 100644 --- a/packages/shared/src/store/postActions.ts +++ b/packages/shared/src/store/postActions.ts @@ -1,11 +1,11 @@ -import * as api from '../api'; -import { toPostContent } from '../api'; +import * as api from '@tloncorp/api'; +import { toPostContent } from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import type * as domain from '../domain'; import { AnalyticsEvent, Attachment, PostDataDraft } from '../domain'; import * as logic from '../logic'; -import * as urbit from '../urbit'; +import * as urbit from '@tloncorp/api/urbit'; import { sessionActionQueue } from './SessionActionQueue'; import { clearUploadState, diff --git a/packages/shared/src/store/session.ts b/packages/shared/src/store/session.ts index 06c533d41a..03d277118c 100644 --- a/packages/shared/src/store/session.ts +++ b/packages/shared/src/store/session.ts @@ -1,6 +1,6 @@ import { useSyncExternalStore } from 'react'; -import { ChannelStatus } from '../http-api'; +import { ChannelStatus } from '@tloncorp/api/http-api'; export type SyncPhase = 'init' | 'high' | 'low' | 'ready'; diff --git a/packages/shared/src/store/settingsActions.ts b/packages/shared/src/store/settingsActions.ts index 341c85ea94..f50b86b979 100644 --- a/packages/shared/src/store/settingsActions.ts +++ b/packages/shared/src/store/settingsActions.ts @@ -1,12 +1,12 @@ import { ThemeName } from 'tamagui'; -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent, AnalyticsSeverity } from '../domain'; import * as logic from '../logic'; import { withRetry } from '../logic'; -import { TalkSidebarFilter } from '../urbit'; +import { TalkSidebarFilter } from '@tloncorp/api/urbit'; export type AppTheme = ThemeName | 'auto'; diff --git a/packages/shared/src/store/storage/storageActions.ts b/packages/shared/src/store/storage/storageActions.ts index 10f21a2681..a172a6fe50 100644 --- a/packages/shared/src/store/storage/storageActions.ts +++ b/packages/shared/src/store/storage/storageActions.ts @@ -2,16 +2,16 @@ import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { render, da } from '@urbit/aura'; //REVIEW why doesn't this work here? -// import { desig } from '@tloncorp/shared/urbit'; -import { desig } from '../../urbit'; +// import { desig } from '@tloncorp/api/urbit'; +import { desig } from '@tloncorp/api/urbit'; import * as FileSystem from 'expo-file-system'; import { SaveFormat, manipulateAsync } from 'expo-image-manipulator'; -import { RNFile, getCurrentUserId } from '../../api'; +import { RNFile, getCurrentUserId } from '@tloncorp/api'; +import { Attachment } from '@tloncorp/api/types/attachment'; import * as db from '../../db'; import { createDevLogger, escapeLog } from '../../debug'; import { AnalyticsEvent } from '../../domain'; -import { Attachment } from '../../domain/attachment'; import { setUploadState } from './storageUploadState'; import { getExtensionFromMimeType, diff --git a/packages/shared/src/store/storage/storageUtils.ts b/packages/shared/src/store/storage/storageUtils.ts index 5ce9191d6a..fa516f720e 100644 --- a/packages/shared/src/store/storage/storageUtils.ts +++ b/packages/shared/src/store/storage/storageUtils.ts @@ -1,8 +1,8 @@ -import * as api from '../../api'; -import { StorageConfiguration, StorageCredentials, scry } from '../../api'; +import * as api from '@tloncorp/api'; +import { StorageConfiguration, StorageCredentials, scry } from '@tloncorp/api'; import * as db from '../../db'; import { createDevLogger } from '../../debug'; -import { desig } from '../../urbit'; +import { desig } from '@tloncorp/api/urbit'; const logger = createDevLogger('storage utils', false); diff --git a/packages/shared/src/store/sync.test.ts b/packages/shared/src/store/sync.test.ts index 267d19fb29..424370eef8 100644 --- a/packages/shared/src/store/sync.test.ts +++ b/packages/shared/src/store/sync.test.ts @@ -2,17 +2,20 @@ import * as $ from 'drizzle-orm'; import { pick } from 'lodash'; import { expect, test, vi } from 'vitest'; -import { StructuredChannelDescriptionPayload, toClientGroupV7 } from '../api'; -import '../api/channelContentConfig'; +import { + StructuredChannelDescriptionPayload, + toClientGroupV7, +} from '@tloncorp/api'; +import '@tloncorp/api'; import { CollectionRendererId, DraftInputId, PostContentRendererId, -} from '../api/channelContentConfig'; +} from '@tloncorp/api'; import * as db from '../db'; import rawNewestPostData from '../test/channelNewestPost.json'; -import rawChannelPostWithRepliesData from '../test/channelPostWithReplies.json'; -import rawChannelPostsData from '../test/channelPosts.json'; +import rawChannelPostWithRepliesData from '../../../api/src/__tests__/fixtures/channelPostWithReplies.json'; +import rawChannelPostsData from '../../../api/src/__tests__/fixtures/channelPosts.json'; import rawAfterNewestPostData from '../test/channelPostsAfterNewest.json'; import rawContactsData from '../test/contacts.json'; import rawGroupsData from '../test/groups.json'; @@ -30,12 +33,12 @@ import { GroupsInit6, PagedPosts, PostDataResponse, -} from '../urbit'; +} from '@tloncorp/api/urbit'; import { ContactBookScryResult1, Contact as UrbitContact, -} from '../urbit/contact'; -import { GroupV7 as UrbitGroup } from '../urbit/groups'; +} from '@tloncorp/api/urbit/contact'; +import { GroupV7 as UrbitGroup } from '@tloncorp/api/urbit/groups'; import { syncContacts, syncDms, diff --git a/packages/shared/src/store/sync.ts b/packages/shared/src/store/sync.ts index 86e7a9103d..5bde976c20 100644 --- a/packages/shared/src/store/sync.ts +++ b/packages/shared/src/store/sync.ts @@ -2,14 +2,14 @@ import { ChannelStatus } from '@urbit/http-api'; import { backOff } from 'exponential-backoff'; import _ from 'lodash'; -import * as api from '../api'; -import { GetChangedPostsOptions } from '../api'; +import * as api from '@tloncorp/api'; +import { GetChangedPostsOptions } from '@tloncorp/api'; import * as db from '../db'; import { QueryCtx, batchEffects } from '../db/query'; import { SETTINGS_SINGLETON_KEY } from '../db/schema'; import { createDevLogger, runIfDev } from '../debug'; import { AnalyticsEvent, AnalyticsSeverity } from '../domain'; -import { extractClientVolumes } from '../logic/activity'; +import { extractClientVolumes } from '@tloncorp/api/lib/activity'; import { INFINITE_ACTIVITY_QUERY_KEY, resetActivityFetchers, diff --git a/packages/shared/src/store/useActivityFetchers.ts b/packages/shared/src/store/useActivityFetchers.ts index e12e8f0a1b..a15e2df75c 100644 --- a/packages/shared/src/store/useActivityFetchers.ts +++ b/packages/shared/src/store/useActivityFetchers.ts @@ -1,7 +1,7 @@ import { useInfiniteQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; -import * as api from '../api'; +import * as api from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import * as logic from '../logic'; diff --git a/packages/shared/src/store/useChannelHooksPreview.ts b/packages/shared/src/store/useChannelHooksPreview.ts index fe42aadad3..5ab94dccc1 100644 --- a/packages/shared/src/store/useChannelHooksPreview.ts +++ b/packages/shared/src/store/useChannelHooksPreview.ts @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; -import { getChannelHooksPreview } from '../api'; -import * as ub from '../urbit'; +import { getChannelHooksPreview } from '@tloncorp/api'; +import * as ub from '@tloncorp/api/urbit'; export function useChannelHooksPreview(channelId: string) { return useQuery({ diff --git a/packages/shared/src/store/useChannelPosts.ts b/packages/shared/src/store/useChannelPosts.ts index 834062a09b..7d6de8beeb 100644 --- a/packages/shared/src/store/useChannelPosts.ts +++ b/packages/shared/src/store/useChannelPosts.ts @@ -5,7 +5,7 @@ import { } from '@tanstack/react-query'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { getChannelIdType } from '../api/apiUtils'; +import { getChannelIdType } from '@tloncorp/api'; import * as db from '../db'; import { createDevLogger } from '../debug'; import { AnalyticsEvent } from '../domain'; diff --git a/packages/shared/src/store/useChannelSearch.ts b/packages/shared/src/store/useChannelSearch.ts index ee9f212ecb..1c232d7d4e 100644 --- a/packages/shared/src/store/useChannelSearch.ts +++ b/packages/shared/src/store/useChannelSearch.ts @@ -2,7 +2,7 @@ import { useInfiniteQuery } from '@tanstack/react-query'; import { da } from '@urbit/aura'; import { useEffect, useMemo } from 'react'; -import { searchChannel } from '../api/channelsApi'; +import { searchChannel } from '@tloncorp/api'; import { createDevLogger } from '../debug'; import { useAttachAuthorToPosts } from './useAttachAuthorToPosts'; diff --git a/packages/shared/src/store/useNegotiation.ts b/packages/shared/src/store/useNegotiation.ts index 116e726c8d..07a2a5e28a 100644 --- a/packages/shared/src/store/useNegotiation.ts +++ b/packages/shared/src/store/useNegotiation.ts @@ -2,10 +2,10 @@ import { useQuery } from '@tanstack/react-query'; import { debounce } from 'lodash'; import { useCallback, useEffect, useMemo, useRef } from 'react'; -import * as api from '../api'; -import { queryClient } from '../api'; +import * as api from '@tloncorp/api'; +import { queryClient } from '@tloncorp/api'; import { createDevLogger } from '../debug'; -import { MatchingEvent, MatchingResponse } from '../urbit/negotiation'; +import { MatchingEvent, MatchingResponse } from '@tloncorp/api/urbit/negotiation'; const logger = createDevLogger('useNegotiation', false); diff --git a/packages/shared/src/store/usePostDraftCallbacks.ts b/packages/shared/src/store/usePostDraftCallbacks.ts index 283f3c95fc..57f8e31034 100644 --- a/packages/shared/src/store/usePostDraftCallbacks.ts +++ b/packages/shared/src/store/usePostDraftCallbacks.ts @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import * as db from '../db'; import * as kv from '../db/keyValue'; -import { JSONContent } from '../urbit'; +import { JSONContent } from '@tloncorp/api/urbit'; type GalleryDraftType = 'caption' | 'text'; interface PostDraftCallbacks { diff --git a/packages/shared/src/test/helpers.ts b/packages/shared/src/test/helpers.ts index 08102e9c4b..aa38b7cf59 100644 --- a/packages/shared/src/test/helpers.ts +++ b/packages/shared/src/test/helpers.ts @@ -4,7 +4,7 @@ import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import tmp from 'tmp'; import { beforeAll, beforeEach, vi } from 'vitest'; -import { scry } from '../api/urbit'; +import { scry } from '@tloncorp/api'; import { setClient } from '../db'; import { AnySqliteDatabase } from '../db/client'; import * as schema from '../db/schema'; diff --git a/packages/shared/src/test/setup.ts b/packages/shared/src/test/setup.ts index bf029f79ae..060818544d 100644 --- a/packages/shared/src/test/setup.ts +++ b/packages/shared/src/test/setup.ts @@ -57,8 +57,8 @@ vi.mock('../store/storage', async (importOriginal) => { }); export function mockUrbit() { - vi.mock('../api/urbit', async (importOriginal) => { - const mod = await importOriginal(); + vi.mock('@tloncorp/api', async (importOriginal) => { + const mod = await importOriginal(); const out: typeof mod = { ...mod, scry: vi.fn(), diff --git a/packages/shared/src/urbit/changes.ts b/packages/shared/src/urbit/changes.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/shared/src/utils/__tests__/formatMemorySize.test.ts b/packages/shared/src/utils/__tests__/formatMemorySize.test.ts index 9183aa8f11..88f61544dd 100644 --- a/packages/shared/src/utils/__tests__/formatMemorySize.test.ts +++ b/packages/shared/src/utils/__tests__/formatMemorySize.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest'; -import { convert, formatMemorySize } from '../formatMemorySize'; +import { formatMemorySize } from '@tloncorp/api/lib/formatMemorySize'; it('truncates trailing zeros', () => { expect(formatMemorySize(1126)).toBe('1.1kb'); @@ -21,9 +21,3 @@ it('rounds up to 1024 of the lower unit when above 1023.9', () => { expect(formatMemorySize(1023.95)).toBe('1024b'); expect(formatMemorySize(1024)).toBe('1kb'); }); - -it('can convert among different units using `convert`', () => { - expect(convert(1, 'kb').to('b')).toEqual(1024); - expect(convert(1, 'kb').to('kb')).toEqual(1); - expect(convert(2, 'gb').to('kb')).toEqual(2_097_152); -}); diff --git a/packages/shared/src/utils/index.ts b/packages/shared/src/utils/index.ts index deea313bcb..52c8404d18 100644 --- a/packages/shared/src/utils/index.ts +++ b/packages/shared/src/utils/index.ts @@ -2,18 +2,18 @@ * `shared/utils` should contain code that has no other dependencies - just some * really really good typescript. */ -export * from './assertNever'; -export * from './blob'; -export * from './object'; -export type * from './utilityTypes'; -export * from './timeoutSignal'; -export * from './EventEmitter'; +export * from '@tloncorp/api/lib/assertNever'; +export * from '@tloncorp/api/lib/blob'; +export * from '@tloncorp/api/lib/object'; +export type * from '@tloncorp/api/lib/utilityTypes'; +export * from '@tloncorp/api/lib/timeoutSignal'; +export * from '@tloncorp/api/lib/EventEmitter'; export * from './useEventEmitter'; -export * from './ProgressManager'; -export * from './telemetryFormatters'; -export * from './spyOn'; -export * from './file'; -export * from './number'; -export * from './formatMemorySize'; +export * from '@tloncorp/api/lib/ProgressManager'; +export * from '@tloncorp/api/lib/telemetryFormatters'; +export * from '@tloncorp/api/lib/spyOn'; +export * from '@tloncorp/api/lib/file'; +export * from '@tloncorp/api/lib/number'; +export * from '@tloncorp/api/lib/formatMemorySize'; export * from './deferred'; export * from './useMockedQuery'; diff --git a/packages/shared/src/utils/useEventEmitter.ts b/packages/shared/src/utils/useEventEmitter.ts index 4fb374fb85..2b9559ce70 100644 --- a/packages/shared/src/utils/useEventEmitter.ts +++ b/packages/shared/src/utils/useEventEmitter.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; -import { EventEmitter, EventMapForEmitter } from './EventEmitter'; +import { EventEmitter, EventMapForEmitter } from '@tloncorp/api/lib/EventEmitter'; export function useEventEmitter< Emitter extends EventEmitter, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1385b2197..8f43bf4f06 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -937,6 +937,12 @@ importers: specifier: ^7.0.0 version: 7.0.0 + packages/api: + dependencies: + '@tloncorp/shared': + specifier: workspace:* + version: link:../shared + packages/app: dependencies: '@10play/tentap-editor': @@ -1098,6 +1104,9 @@ importers: '@tiptap/suggestion': specifier: 2.6.0 version: 2.6.0(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) + '@tloncorp/api': + specifier: workspace:* + version: link:../api '@urbit/aura': specifier: ^3.0.0 version: 3.0.0 From fca9fb4cbfee0107aed75b49becd262da5259bde Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Fri, 13 Feb 2026 01:35:18 -0500 Subject: [PATCH 2/6] chore(api-move-only): strip non-move refactor churn --- packages/api/src/client/hostingApi.ts | 25 +- packages/api/src/client/metagrabApi.ts | 25 +- .../src/client/systemContactsApi.native.ts | 17 +- packages/api/src/lib/activity.ts | 10 +- packages/api/src/lib/content-helpers.ts | 28 +- packages/api/src/lib/formatMemorySize.ts | 30 +- packages/api/src/lib/postContent.ts | 53 ++- packages/api/src/lib/types.ts | 7 + packages/api/src/lib/utils.ts | 49 ++- packages/api/src/types/activityModels.ts | 69 ---- packages/api/src/types/attachment.ts | 20 +- packages/api/src/types/chatModels.ts | 332 ------------------ packages/api/src/types/clientModels.ts | 49 --- packages/api/src/types/commonModels.ts | 15 - packages/api/src/types/index.ts | 2 +- packages/api/src/types/systemContactModels.ts | 40 --- packages/api/src/types/types.ts | 5 - packages/shared/.eslintrc.cjs | 10 +- packages/shared/src/domain/index.ts | 2 +- packages/shared/src/electronAuth.ts | 72 ---- packages/shared/src/electrtonAuth.ts | 73 +++- packages/shared/src/index.ts | 2 +- .../utils/__tests__/formatMemorySize.test.ts | 8 +- 23 files changed, 252 insertions(+), 691 deletions(-) delete mode 100644 packages/api/src/types/activityModels.ts delete mode 100644 packages/api/src/types/chatModels.ts delete mode 100644 packages/api/src/types/clientModels.ts delete mode 100644 packages/api/src/types/commonModels.ts delete mode 100644 packages/api/src/types/systemContactModels.ts delete mode 100644 packages/api/src/types/types.ts delete mode 100644 packages/shared/src/electronAuth.ts diff --git a/packages/api/src/client/hostingApi.ts b/packages/api/src/client/hostingApi.ts index a1bef0a99a..fd6b080893 100644 --- a/packages/api/src/client/hostingApi.ts +++ b/packages/api/src/client/hostingApi.ts @@ -2,16 +2,15 @@ import { Buffer } from 'buffer'; import * as db from '@tloncorp/shared/db'; import { createDevLogger } from '@tloncorp/shared/debug'; +import * as domain from '../types'; import { - AssignmentResponse, - HostedNodeStatus, + AnalyticsEvent, HostedShipResponse, ReservableShip, ReservedShip, User, -} from '../types/hosting'; -import { AnalyticsEvent } from '../types/analytics'; -import { getConstants } from '../types/constants'; + getConstants, +} from '../types'; import { withRetry } from '../lib/utils'; const logger = createDevLogger('hostingApi', false); @@ -433,7 +432,7 @@ export const verifyEmailDigits = async (email: string, digits: string) => hostingFetch(`/v1/verify-email-digits/${email}/${digits}`); export const assignShipToUser = async (userId: string) => { - const response = await hostingFetch( + const response = await hostingFetch( `/v1/users/${userId}/assign-ship`, { method: 'PATCH', @@ -517,7 +516,7 @@ export const bootShip = async (shipId: string) => export const getNodeStatus = async ( nodeId: string -): Promise<{ status: HostedNodeStatus; showWayfinding: boolean }> => { +): Promise<{ status: domain.HostedNodeStatus; showWayfinding: boolean }> => { let result = null; try { result = await getShip(nodeId); @@ -532,7 +531,7 @@ export const getNodeStatus = async ( // If user has a ready ship, let's use it if (nodeStatus === 'Ready') { - return { status: HostedNodeStatus.Running, showWayfinding }; + return { status: domain.HostedNodeStatus.Running, showWayfinding }; } // If user has a paused ship, resume it @@ -540,11 +539,11 @@ export const getNodeStatus = async ( if (!isBooting) { await resumeShip(nodeId); } - return { status: HostedNodeStatus.Paused, showWayfinding }; + return { status: domain.HostedNodeStatus.Paused, showWayfinding }; } if (nodeStatus === 'UnderMaintenance' || manualUpdateNeeded) { - return { status: HostedNodeStatus.UnderMaintenance, showWayfinding }; + return { status: domain.HostedNodeStatus.UnderMaintenance, showWayfinding }; } // If user has a suspended ship, boot it @@ -560,17 +559,17 @@ export const getNodeStatus = async ( err.message.includes(MANUAL_UPDATE_REQUIRED_MESSAGE) ) { return { - status: HostedNodeStatus.UnderMaintenance, + status: domain.HostedNodeStatus.UnderMaintenance, showWayfinding, }; } throw err; } } - return { status: HostedNodeStatus.Suspended, showWayfinding }; + return { status: domain.HostedNodeStatus.Suspended, showWayfinding }; } - return { status: HostedNodeStatus.Unknown, showWayfinding }; + return { status: domain.HostedNodeStatus.Unknown, showWayfinding }; }; export const inviteShipWithLure = async (params: { diff --git a/packages/api/src/client/metagrabApi.ts b/packages/api/src/client/metagrabApi.ts index 7b752b93b3..edd25aadbb 100644 --- a/packages/api/src/client/metagrabApi.ts +++ b/packages/api/src/client/metagrabApi.ts @@ -2,17 +2,16 @@ import { render } from '@urbit/aura'; import { Atom } from '@urbit/nockjs'; import { createDevLogger } from '@tloncorp/shared/debug'; -import type { LinkMetadata, LinkMetadataError } from '../types/attachment'; -import { getConstants } from '../types/constants'; +import * as domain from '../types'; +import { getConstants } from '../types'; import * as ub from '../urbit'; -import { AnalyticsEvent } from '../types/analytics'; import { request } from './urbit'; const logger = createDevLogger('metagrabApi', false); export async function getLinkMetadata( url: string -): Promise { +): Promise { try { const encodedUrl = render('uw', Atom.fromCord(url).number); logger.log('encoded', { url, encodedUrl }); @@ -27,7 +26,7 @@ export async function getLinkMetadata( logger.log('metagrab response', response); if (response.status !== 200) { - logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, { + logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, { message: `bad metagrab response: ${response.status}`, response, }); @@ -36,17 +35,17 @@ export async function getLinkMetadata( const parsed = parseLinkMetadataResponse(url, response); if (parsed.type === 'error') { - logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, { + logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, { message: `metagrab error: ${parsed.reason}`, response, parsedResponse: parsed, }); } else { - logger.trackEvent(AnalyticsEvent.FetchLinkMetadata); + logger.trackEvent(domain.AnalyticsEvent.FetchLinkMetadata); } return parsed; } catch (error) { - logger.trackError(AnalyticsEvent.ErrorFetchLinkMetadata, error); + logger.trackError(domain.AnalyticsEvent.ErrorFetchLinkMetadata, error); return { type: 'error', reason: 'unknown error' }; } } @@ -54,7 +53,7 @@ export async function getLinkMetadata( function parseLinkMetadataResponse( url: string, response: ub.LinkMetadataResponse -): LinkMetadata | LinkMetadataError { +): domain.LinkMetadata | domain.LinkMetadataError { const { result } = response; if (!result) { return { type: 'redirect' }; @@ -74,7 +73,7 @@ function parseLinkMetadataResponse( const siteDescription = description?.[0]?.value; const imageData = parseImageData(url, image ?? []); - const parsed: LinkMetadata = { + const parsed: domain.LinkMetadata = { type: 'page', url, siteIconUrl, @@ -90,7 +89,7 @@ function parseLinkMetadataResponse( } if (result.type === 'file') { - const parsed: LinkMetadata = { + const parsed: domain.LinkMetadata = { type: 'file', url, mime: result.mime, @@ -141,7 +140,7 @@ function parseImageData(url: string, data: ub.LinkMetadataItem[]) { export async function getFallbackLinkMetadata( url: string -): Promise { +): Promise { try { const env = getConstants(); const response = await fetch(`${env.INVITE_SERVICE_ENDPOINT}/linkPreview`, { @@ -159,7 +158,7 @@ export async function getFallbackLinkMetadata( throw new Error('fallback link meta payload invalid'); } - const meta: LinkMetadata = { + const meta: domain.LinkMetadata = { type: 'page', url, siteIconUrl: payload.siteIconUrl || '', diff --git a/packages/api/src/client/systemContactsApi.native.ts b/packages/api/src/client/systemContactsApi.native.ts index 2a4b3f1462..d2e28178e0 100644 --- a/packages/api/src/client/systemContactsApi.native.ts +++ b/packages/api/src/client/systemContactsApi.native.ts @@ -4,8 +4,7 @@ import * as LibPhone from 'libphonenumber-js'; import * as db from '@tloncorp/shared/db'; import { createDevLogger } from '@tloncorp/shared/debug'; -import type { SystemContact } from '../types/systemContacts'; -import { AnalyticsEvent, AnalyticsSeverity } from '../types/analytics'; +import * as domain from '../types'; const logger = createDevLogger('SystemContactsApi', true); @@ -22,9 +21,9 @@ export async function getSystemContacts(): Promise { }); nativeContactBook = data; } catch (e) { - logger.trackEvent(AnalyticsEvent.ErrorSystemContacts, { + logger.trackEvent(domain.AnalyticsEvent.ErrorSystemContacts, { context: 'failed to get native contacts', - severity: AnalyticsSeverity.High, + severity: domain.AnalyticsSeverity.High, }); return []; } @@ -32,9 +31,9 @@ export async function getSystemContacts(): Promise { const processedContacts = parseNativeContacts(nativeContactBook); return processedContacts; } catch (e) { - logger.trackEvent(AnalyticsEvent.ErrorSystemContacts, { + logger.trackEvent(domain.AnalyticsEvent.ErrorSystemContacts, { context: 'failed to parse native contacts', - severity: AnalyticsSeverity.High, + severity: domain.AnalyticsSeverity.High, }); return []; } @@ -42,7 +41,7 @@ export async function getSystemContacts(): Promise { export function parseNativeContacts( nativeContacts: Contacts.Contact[] -): SystemContact[] { +): domain.SystemContact[] { const parseCounts = { digitFinds: 0, numberFinds: 0, fallbacks: 0 }; let defaultCountryCode = 'US'; @@ -53,7 +52,7 @@ export function parseNativeContacts( logger.log(`Inferred system default country code: ${defaultCountryCode}`); } } catch (e) { - logger.trackEvent(AnalyticsEvent.DebugSystemContacts, { + logger.trackEvent(domain.AnalyticsEvent.DebugSystemContacts, { context: 'Could not infer system default country code', }); } @@ -204,7 +203,7 @@ export function parseNativeContacts( }) .filter((num): num is string => num !== null); - const sysContact: SystemContact = { + const sysContact: domain.SystemContact = { id: contact.id!, firstName: contact.firstName, lastName: contact.lastName, diff --git a/packages/api/src/lib/activity.ts b/packages/api/src/lib/activity.ts index 35060d8a6d..477e0d04f2 100644 --- a/packages/api/src/lib/activity.ts +++ b/packages/api/src/lib/activity.ts @@ -1,5 +1,5 @@ -import type { ActivityEvent } from '@tloncorp/shared/db/types'; import type * as db from '@tloncorp/shared/db/types'; +import type { ActivityEvent } from '@tloncorp/shared/db/types'; import { ExtendedEventType, NotificationLevel, @@ -96,10 +96,10 @@ export function toSourceActivityEvents( // "source" if it hasn't already been added const individualMentionKey = `${key}/${event.postId}`; if (!eventMap.has(individualMentionKey)) { - const mentionSource: SourceActivityEvents = { + const mentionSource = { newest: event, all: [event], - type: event.type as ExtendedEventType, + type: event.type, sourceId: `${event.sourceId}/${event.postId}`, }; eventMap.set(individualMentionKey, mentionSource); @@ -112,10 +112,10 @@ export function toSourceActivityEvents( } } else { // Create a new entry in the map - const newRollup: SourceActivityEvents = { + const newRollup = { newest: event, all: [event], - type: event.type as ExtendedEventType, + type: event.type, sourceId: event.sourceId, }; eventMap.set(key, newRollup); diff --git a/packages/api/src/lib/content-helpers.ts b/packages/api/src/lib/content-helpers.ts index a7d13e8927..d2697ea4fd 100644 --- a/packages/api/src/lib/content-helpers.ts +++ b/packages/api/src/lib/content-helpers.ts @@ -2,13 +2,13 @@ import isURL from 'validator/lib/isURL'; import type { ChannelType, PostMetadata } from '@tloncorp/shared/db/types'; import { createDevLogger } from '@tloncorp/shared/debug'; -import type { +import { FinalizedAttachment, LinkAttachment, ReferenceAttachment, + UploadedFileAttachment, UploadedImageAttachment, -} from '../types/attachment'; -import { UploadedFileAttachment } from '../types/attachment'; +} from '../types'; import { Block, Inline, @@ -18,27 +18,7 @@ import { pathToCite, } from '../urbit'; import { fileFromPath } from './file'; - -// Inlined from tiptap.ts to avoid @tiptap dependency -const makeText = (t: string) => ({ type: 'text', text: t }); -const makeMention = (id: string) => ({ - type: 'mention', - attrs: { id }, -}); -const makeParagraph = (content?: JSONContent[]): JSONContent => { - const p = { type: 'paragraph' }; - if (!content) { - return p; - } - if ( - content.length > 0 && - content[0].type === 'text' && - content[0].text === '' - ) { - return p; - } - return { ...p, content }; -}; +import { makeMention, makeParagraph, makeText } from '@tloncorp/shared/logic/tiptap'; const logger = createDevLogger('content-helpers', false); diff --git a/packages/api/src/lib/formatMemorySize.ts b/packages/api/src/lib/formatMemorySize.ts index 0878abeb84..6c6ed26e4e 100644 --- a/packages/api/src/lib/formatMemorySize.ts +++ b/packages/api/src/lib/formatMemorySize.ts @@ -1,14 +1,16 @@ /** maps available units to how many bytes fit in one unit, ordered by preference */ -const unitToBytes: Array<{ - unit: string; - /** how many bytes fit in one unit */ - bytes: number; -}> = [ +const unitToBytes = [ { unit: 'gb', bytes: Math.pow(1024, 3) }, { unit: 'mb', bytes: Math.pow(1024, 2) }, { unit: 'kb', bytes: Math.pow(1024, 1) }, { unit: 'b', bytes: Math.pow(1024, 0) }, -]; +] as const satisfies Array<{ + unit: string; + /** how many bytes fit in one unit */ + bytes: number; +}>; + +type Unit = (typeof unitToBytes)[number]['unit']; /** * @example @@ -26,3 +28,19 @@ export function formatMemorySize(bytes: number): string { unitToBytes.find((x) => bytes / x.bytes >= 1) ?? unitToBytes.at(-1)!; return format(bytes / matchingUnit.bytes, matchingUnit.unit); } + +/** + * @example + * ```ts + * convert(1, 'kb').to('b') === 1024 + * convert(1, 'gb').to('mb') === 1024 + * ``` + */ +export function convert(value: number, fromUnit: Unit) { + return { + to: (toUnit: Unit) => + value * + (unitToBytes.find((u) => u.unit === fromUnit)!.bytes / + unitToBytes.find((u) => u.unit === toUnit)!.bytes), + }; +} diff --git a/packages/api/src/lib/postContent.ts b/packages/api/src/lib/postContent.ts index 0f18cecb4f..a0107f7d80 100644 --- a/packages/api/src/lib/postContent.ts +++ b/packages/api/src/lib/postContent.ts @@ -1,4 +1,5 @@ -import { toContentReference } from '../client/postsApi'; +import * as api from '../client'; +import { formatUd } from '../client/apiUtils'; import type { ContentReference } from '../types/references'; import * as ub from '../urbit'; import { assertNever } from './assertNever'; @@ -161,7 +162,6 @@ export type BlockFromType = Extract< >; export type PostContent = BlockData[]; -type ApiPostContent = (ub.Verse | ContentReference)[] | null; export interface PlaintextPreviewConfig { blockSeparator: string; @@ -169,6 +169,41 @@ export interface PlaintextPreviewConfig { includeRefTag: boolean; indentDepth?: number; } + +function toContentReference(cite: ub.Cite): ContentReference | null { + if ('chan' in cite) { + const channelId = cite.chan.nest; + // I've seen these forms of reference path: + // /msg/170141184506828851385935487131294105600 + // /msg/170141184506312077223314290444316180480/170141184506312235291442423303751335936 + // /msg/~sogrum-savluc/170.141.184.505.979.681.243.072.382.329.337.971.474 + const messageIdRegex = /\/([0-9\.]+(?=[$\/]?))/g; + const [postId, replyId] = Array.from( + cite.chan.where.matchAll(messageIdRegex) + ).map((m) => m[1].replace(/\./g, '')); + if (!postId) { + return null; + } + return { + type: 'reference', + referenceType: 'channel', + channelId, + postId: formatUd(postId), + replyId: replyId ? formatUd(replyId) : undefined, + }; + } else if ('group' in cite) { + return { type: 'reference', referenceType: 'group', groupId: cite.group }; + } else if ('desk' in cite) { + const parts = cite.desk.flag.split('/'); + const userId = parts[0]; + const appId = parts[1]; + if (!userId || !appId) { + return null; + } + return { type: 'reference', referenceType: 'app', userId, appId }; + } + return null; +} export namespace PlaintextPreviewConfig { export const defaultConfig: PlaintextPreviewConfig = Object.freeze({ blockSeparator: '\n', @@ -338,7 +373,7 @@ export function convertContent( return out; } - const story: ApiPostContent = + const story: api.PostContent = typeof input === 'string' ? JSON.parse(input) : input; if (!story) { @@ -354,7 +389,7 @@ export function convertContent( * applies more type strictness at callsite. */ export function convertContentSafe( - story: Exclude + story: Exclude ): PostContent { const blocks: PostContent = []; for (const verse of story) { @@ -491,7 +526,9 @@ function convertBlock(block: ub.Block): BlockData { }; } case is(block, 'cite'): { - return toContentReference(block.cite) ?? errorMessage('Failed to parse'); + return ( + toContentReference(block.cite) ?? errorMessage('Failed to parse') + ); } case is(block, 'link'): { return { @@ -643,15 +680,15 @@ export function appendInline( } export function getTextContent( - postContent: Exclude, + postContent: Exclude, config?: PlaintextPreviewConfig ): string; export function getTextContent( - postContent: ApiPostContent, + postContent: api.PostContent, config?: PlaintextPreviewConfig ): string | null; export function getTextContent( - postContent: ApiPostContent, + postContent: api.PostContent, config: PlaintextPreviewConfig = PlaintextPreviewConfig.defaultConfig ): string | null { return postContent == null diff --git a/packages/api/src/lib/types.ts b/packages/api/src/lib/types.ts index d930b39712..1786ee6484 100644 --- a/packages/api/src/lib/types.ts +++ b/packages/api/src/lib/types.ts @@ -8,6 +8,13 @@ export function isChatChannel(channel: db.Channel): boolean { ); } +/** + * Ordered posts are the canonical backend source for pinned posts. + */ +export function getPinnedPostId(channel: db.Channel): string | null { + return channel.order?.[0] ?? null; +} + export function isChannel(obj: db.Channel | db.Group): obj is db.Channel { return !('hostUserId' in obj); } diff --git a/packages/api/src/lib/utils.ts b/packages/api/src/lib/utils.ts index e1f5e3e701..96941ab798 100644 --- a/packages/api/src/lib/utils.ts +++ b/packages/api/src/lib/utils.ts @@ -3,6 +3,7 @@ import anyAscii from 'any-ascii'; import { differenceInDays, endOfToday, format } from 'date-fns'; import emojiRegex from 'emoji-regex'; import { BackoffOptions, backOff } from 'exponential-backoff'; +import { useMemo } from 'react'; import * as api from '../client'; import { @@ -11,8 +12,7 @@ import { isGroupDmChannelId, } from '../client/apiUtils'; import type * as db from '@tloncorp/shared/db/types'; -import type { ContentReference } from '../types/references'; -import { PersonalGroupSlugs } from '../types/wayfinding'; +import * as domain from '../types'; import * as ub from '../urbit'; import type { Stringified } from './utilityTypes'; @@ -437,12 +437,12 @@ export function extractInlinesFromContent(story: api.PostContent): ub.Inline[] { export function extractReferencesFromContent( story: api.PostContent -): ContentReference[] { +): domain.ContentReference[] { const references = story !== null ? (story.filter( (s) => 'type' in s && s.type == 'reference' - ) as ContentReference[]) + ) as domain.ContentReference[]) : []; return references; @@ -463,7 +463,7 @@ export const extractContentTypes = ( content: Stringified | api.PostContent ): { inlines: ub.Inline[]; - references: ContentReference[]; + references: domain.ContentReference[]; blocks: ub.Block[]; story: api.PostContent; } => { @@ -479,7 +479,7 @@ export const extractContentTypesFromPost = ( post: db.Post | { content: api.PostContent } ): { inlines: ub.Inline[]; - references: ContentReference[]; + references: domain.ContentReference[]; blocks: ub.Block[]; story: api.PostContent; } => { @@ -639,6 +639,41 @@ export const getPostTypeFromChannelId = ({ } }; +export const usePostMeta = (post: db.Post) => { + const { inlines, references, blocks } = useMemo( + () => extractContentTypesFromPost(post), + [post] + ); + const isText = useMemo(() => isTextPost(post), [post]); + const isImage = useMemo(() => isImagePost(post), [post]); + const isLink = useMemo(() => textPostIsLink(post), [post]); + const isReference = useMemo(() => isReferencePost(post), [post]); + const isLinkedImage = useMemo(() => textPostIsLinkedImage(post), [post]); + const isRefInText = useMemo(() => textPostIsReference(post), [post]); + const image = useMemo( + () => (isImage ? findFirstImageBlock(blocks)?.image : undefined), + [blocks, isImage] + ); + const linkedImage = useMemo( + () => (isLinkedImage ? (inlines[0] as ub.Link).link.href : undefined), + [inlines, isLinkedImage] + ); + + return { + isText, + isImage, + isLink, + isReference, + isLinkedImage, + isRefInText, + inlines, + references, + blocks, + image, + linkedImage, + }; +}; + export const getCompositeGroups = ( groups: db.Group[], base: Partial[] @@ -695,7 +730,7 @@ export function simpleHash(input: string) { return Math.abs(hash).toString(36); } -const wayfindingGroup = PersonalGroupSlugs; +const wayfindingGroup = domain.PersonalGroupSlugs; function isWayfindingChannel(id: string | null | undefined): boolean { if (!id) return false; if (isDmChannelId(id)) return false; diff --git a/packages/api/src/types/activityModels.ts b/packages/api/src/types/activityModels.ts deleted file mode 100644 index 8c85b34564..0000000000 --- a/packages/api/src/types/activityModels.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { ExtendedEventType } from '../urbit'; -import type { ActivityBucket } from './commonModels'; - -export interface ChannelUnread { - channelId: string; - type: 'channel' | 'dm'; - notify: boolean; - count: number; - countWithoutThreads: number; - updatedAt: number; - firstUnreadPostId?: string | null; - firstUnreadPostReceivedAt?: number | null; -} - -export interface ThreadUnreadState { - channelId?: string | null; - threadId?: string | null; - notify?: boolean | null; - count?: number | null; - updatedAt: number; - firstUnreadPostId?: string | null; - firstUnreadPostReceivedAt?: number | null; -} - -export interface GroupUnread { - groupId: string; - notify?: boolean | null; - count?: number | null; - notifyCount?: number | null; - updatedAt: number; -} - -export interface BaseUnread { - id: string; - notify?: boolean | null; - count?: number | null; - notifyCount?: number | null; - updatedAt: number; - notifTimestamp?: string | null; -} - -export interface ActivityEvent { - id: string; - bucketId: ActivityBucket; - sourceId: string; - type: ExtendedEventType; - timestamp: number; - postId?: string | null; - authorId?: string | null; - parentId?: string | null; - parentAuthorId?: string | null; - channelId?: string | null; - groupId?: string | null; - isMention?: boolean | null; - shouldNotify?: boolean | null; - content?: any | null; - groupEventUserId?: string | null; - contactUserId?: string | null; - contactUpdateType?: string | null; - contactUpdateValue?: string | null; - contactUpdateGroups?: { groupId: string; activityEventId: string }[] | null; -} - -export interface ActivityInit { - baseUnread?: BaseUnread; - groupUnreads: GroupUnread[]; - channelUnreads: ChannelUnread[]; - threadActivity: ThreadUnreadState[]; -} diff --git a/packages/api/src/types/attachment.ts b/packages/api/src/types/attachment.ts index f52ae89ed2..22c0dd85ef 100644 --- a/packages/api/src/types/attachment.ts +++ b/packages/api/src/types/attachment.ts @@ -1,25 +1,9 @@ +import { ImagePickerAsset } from 'expo-image-picker'; import { memoize, uniqueId } from 'lodash'; import { ContentReference } from './references'; import { UploadState } from './uploads'; -/** - * Platform-agnostic image asset type (compatible with expo-image-picker's ImagePickerAsset) - * This allows the package to work in Node.js, web, and React Native environments. - */ -export interface ImagePickerAsset { - uri: string; - width: number; - height: number; - fileSize?: number; - mimeType?: string; - fileName?: string; - type?: 'image' | 'video'; - duration?: number; - base64?: string; - exif?: Record; -} - export type LinkMetadata = PageMetadata | FileMetadata; export type LinkMetadataError = @@ -403,7 +387,7 @@ export namespace Attachment { }; } } else { - return (uploadIntent as { needsUpload: false; finalized: FinalizedAttachment }).finalized; + return uploadIntent.finalized; } } diff --git a/packages/api/src/types/chatModels.ts b/packages/api/src/types/chatModels.ts deleted file mode 100644 index 1f662678da..0000000000 --- a/packages/api/src/types/chatModels.ts +++ /dev/null @@ -1,332 +0,0 @@ -import type { NotificationLevel } from '../urbit'; -import type { - AttestationDiscoverability, - AttestationStatus, - AttestationType, - ChannelType, - GroupJoinStatus, - GroupPrivacy, - PinType, - PostDeliveryStatus, - PostType, -} from './commonModels'; - -export interface Contact { - id: string; - peerNickname?: string | null; - customNickname?: string | null; - nickname?: string | null; - peerAvatarImage?: string | null; - customAvatarImage?: string | null; - avatarImage?: string | null; - bio?: string | null; - status?: string | null; - color?: string | null; - coverImage?: string | null; - isBlocked?: boolean | null; - isContact?: boolean | null; - isContactSuggestion?: boolean | null; - pinnedGroups?: ContactPinnedGroup[] | null; - attestations?: ContactAttestation[] | null; -} - -export interface ContactPinnedGroup { - contactId: string; - groupId: string; -} - -export interface Group { - id: string; - iconImage?: string | null; - iconImageColor?: string | null; - coverImage?: string | null; - coverImageColor?: string | null; - title?: string | null; - description?: string | null; - privacy?: GroupPrivacy | null; - haveInvite?: boolean | null; - haveRequestedInvite?: boolean | null; - currentUserIsMember: boolean; - currentUserIsHost: boolean; - hostUserId: string; - isNew?: boolean | null; - isPersonalGroup?: boolean | null; - joinStatus?: GroupJoinStatus | null; - lastPostId?: string | null; - lastPostAt?: number | null; - syncedAt?: number | null; - pendingMembersDismissedAt?: number | null; - memberCount?: number | null; - channels?: Channel[] | null; - flaggedPosts?: GroupFlaggedPosts[] | null; - navSections?: GroupNavSection[] | null; - roles?: GroupRole[] | null; - members?: ChatMember[] | null; - bannedMembers?: GroupMemberBan[] | null; - pendingMembers?: GroupMemberInvite[] | null; - joinRequests?: GroupJoinRequest[] | null; - bannedRanks?: GroupRankBan[] | null; -} - -export interface Channel { - id: string; - type: ChannelType; - groupId?: string | null; - iconImage?: string | null; - iconImageColor?: string | null; - coverImage?: string | null; - coverImageColor?: string | null; - title?: string | null; - description?: string | null; - contactId?: string | null; - addedToGroupAt?: number | null; - currentUserIsMember?: boolean | null; - currentUserIsHost?: boolean | null; - postCount?: number | null; - unreadCount?: number | null; - firstUnreadPostId?: string | null; - lastPostId?: string | null; - lastPostAt?: number | null; - lastPostSequenceNum?: number | null; - isPendingChannel?: boolean | null; - isNewMatchedContact?: boolean | null; - isDmInvite?: boolean | null; - syncedAt?: number | null; - remoteUpdatedAt?: number | null; - lastViewedAt?: number | null; - contentConfiguration?: any | null; - order?: string[] | null; - members?: ChatMember[] | null; - readerRoles?: ChannelReader[] | null; - writerRoles?: ChannelWriter[] | null; -} - -export interface ChannelReader { - channelId: string; - roleId: string; -} - -export interface ChannelWriter { - channelId: string; - roleId: string; -} - -export interface Post { - id: string; - authorId: string; - channelId: string; - groupId?: string | null; - parentId?: string | null; - type: PostType; - title?: string | null; - image?: string | null; - description?: string | null; - cover?: string | null; - content?: any | null; - receivedAt: number; - sentAt: number; - replyCount?: number | null; - replyTime?: number | null; - replyContactIds?: string[] | null; - textContent?: string | null; - hasAppReference?: boolean | null; - hasChannelReference?: boolean | null; - hasGroupReference?: boolean | null; - hasLink?: boolean | null; - hasImage?: boolean | null; - hidden?: boolean | null; - isEdited?: boolean | null; - isDeleted?: boolean | null; - isSequenceStub?: boolean | null; - deletedAt?: number | null; - deliveryStatus?: PostDeliveryStatus | null; - editStatus?: PostDeliveryStatus | null; - deleteStatus?: PostDeliveryStatus | null; - lastEditContent?: any | null; - lastEditTitle?: string | null; - lastEditImage?: string | null; - sequenceNum?: number | null; - syncedAt?: number | null; - backendTime?: string | null; - blob?: string | null; - draft?: any | null; - images?: PostImage[] | null; - reactions?: Reaction[] | null; - replies?: Post[] | null; - author?: Contact | null; -} - -export interface PostFlags { - hasAppReference?: boolean | null; - hasChannelReference?: boolean | null; - hasGroupReference?: boolean | null; - hasImage?: boolean | null; - hasLink?: boolean | null; -} - -export interface PostMetadata { - title?: string | null; - image?: string | null; - description?: string | null; - cover?: string | null; -} - -export interface ReplyMeta { - replyCount: number; - replyTime: number | null; - replyContactIds: string[]; -} - -export interface Reaction { - contactId: string; - postId: string; - value: string; -} - -export interface Pin { - type: PinType; - index: number; - itemId: string; -} - -export interface Settings { - id: string; - theme?: string | null; - disableAppTileUnreads?: boolean | null; - disableAvatars?: boolean | null; - disableRemoteContent?: boolean | null; - disableSpellcheck?: boolean | null; - disableNicknames?: boolean | null; - orderedGroupPins?: any | null; - sideBarSort?: 'alphabetical' | 'arranged' | 'recent' | null; - groupSideBarSort?: any | null; - showActivityMessage?: boolean | null; - logActivity?: boolean | null; - enableTelemetry?: boolean | null; - analyticsId?: string | null; - seenWelcomeCard?: boolean | null; - newGroupFlags?: any | null; - groupsNavState?: string | null; - messagesNavState?: string | null; - messagesFilter?: string | null; - gallerySettings?: string | null; - notebookSettings?: any | null; - activitySeenTimestamp?: number | null; - completedWayfindingSplash?: boolean | null; - completedWayfindingTutorial?: boolean | null; - disableTlonInfraEnhancement?: boolean | null; -} - -export interface ChatMember { - membershipType: 'group' | 'channel'; - chatId?: string | null; - contactId: string; - joinedAt?: number | null; - status?: 'invited' | 'joined' | null; - contact?: Contact | null; - roles?: ChatMemberGroupRole[] | null; -} - -export interface GroupRole { - id: string; - groupId?: string | null; - iconImage?: string | null; - iconImageColor?: string | null; - coverImage?: string | null; - coverImageColor?: string | null; - title?: string | null; - description?: string | null; -} - -export interface ChatMemberGroupRole { - groupId: string; - contactId: string; - roleId: string; -} - -export interface GroupNavSection { - id: string; - sectionId: string; - groupId?: string | null; - iconImage?: string | null; - iconImageColor?: string | null; - coverImage?: string | null; - coverImageColor?: string | null; - title?: string | null; - description?: string | null; - sectionIndex?: number | null; - channels?: GroupNavSectionChannel[] | null; -} - -export interface GroupNavSectionChannel { - groupNavSectionId?: string | null; - channelId?: string | null; - channelIndex?: number | null; -} - -export interface GroupMemberInvite { - groupId: string; - contactId: string; - invitedAt?: number | null; -} - -export interface GroupMemberBan { - groupId: string; - contactId: string; - bannedAt?: number | null; -} - -export interface GroupJoinRequest { - groupId: string; - contactId: string; - requestedAt?: number | null; -} - -export interface GroupRankBan { - groupId: string; - rankId: string; - bannedAt?: number | null; -} - -export interface GroupFlaggedPosts { - groupId: string; - postId: string; - channelId: string; - flaggedByContactId: string; - flaggedAt?: number | null; -} - -export interface VolumeSettings { - itemId: string; - itemType: 'group' | 'channel' | 'thread' | 'base'; - level: NotificationLevel; -} - -export interface PostImage { - postId?: string | null; - src?: string | null; - alt?: string | null; - width?: number | null; - height?: number | null; -} - -export interface Attestation { - id: string; - provider: string; - type: AttestationType; - value?: string | null; - initiatedAt?: number | null; - discoverability: AttestationDiscoverability; - status: AttestationStatus; - statusMessage?: string | null; - contactId: string; - providerUrl?: string | null; - provingTweetId?: string | null; - signature?: string | null; -} - -export interface ContactAttestation { - contactId: string; - attestationId: string; - attestation?: Attestation | null; -} diff --git a/packages/api/src/types/clientModels.ts b/packages/api/src/types/clientModels.ts deleted file mode 100644 index 76af31c102..0000000000 --- a/packages/api/src/types/clientModels.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { ActivityEvent, ActivityInit } from './activityModels'; -import type { Contact, Group, Post } from './chatModels'; -import type { SystemContact } from './systemContactModels'; - -export interface ClientMeta { - title?: string | null; - coverImage?: string | null; - iconImage?: string | null; - description?: string | null; - coverImageColor?: string | null; - iconImageColor?: string | null; -} - -export interface ChangesResult { - groups: Group[]; - posts: Post[]; - contacts: Contact[]; - unreads: ActivityInit; - deletedChannelIds: string[]; -} - -export interface PendingMemberDismissal { - groupId: string; - dismissedAt: number; -} - -export type PendingMemberDismissals = PendingMemberDismissal[]; - -export interface GroupEvent extends ActivityEvent { - type: 'group-ask'; - group: Group; - groupId: string; - groupEventUserId: string; - groupEventUser: Contact; -} - -export function isGroupEvent(event: ActivityEvent): event is GroupEvent { - return Boolean( - event.type === 'group-ask' && event.groupEventUserId && event.groupId - ); -} - -export interface AppInfo { - groupsVersion: string; - groupsHash: string; - groupsSyncNode: string; -} - -export type SystemContactLike = Contact | SystemContact; diff --git a/packages/api/src/types/commonModels.ts b/packages/api/src/types/commonModels.ts deleted file mode 100644 index 064b7bb24e..0000000000 --- a/packages/api/src/types/commonModels.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type ChannelType = 'chat' | 'notebook' | 'gallery' | 'dm' | 'groupDm'; -export type PostDeliveryStatus = - | 'enqueued' - | 'pending' - | 'sent' - | 'failed' - | 'needs_verification'; -export type PinType = 'group' | 'channel' | 'dm' | 'groupDm'; -export type GroupPrivacy = 'public' | 'private' | 'secret'; -export type GroupJoinStatus = 'joining' | 'errored'; -export type ActivityBucket = 'all' | 'mentions' | 'replies'; -export type AttestationType = 'phone' | 'node' | 'twitter' | 'dummy'; -export type AttestationDiscoverability = 'public' | 'verified' | 'hidden'; -export type AttestationStatus = 'waiting' | 'pending' | 'verified'; -export type PostType = 'block' | 'chat' | 'notice' | 'note' | 'reply' | 'delete'; diff --git a/packages/api/src/types/index.ts b/packages/api/src/types/index.ts index 51ec962360..cffdc12dac 100644 --- a/packages/api/src/types/index.ts +++ b/packages/api/src/types/index.ts @@ -10,6 +10,6 @@ export * from './onboarding'; export * from './post'; export * from './references'; export * from './system'; -export * from './types'; +export * from './systemContacts'; export * from './uploads'; export * from './wayfinding'; diff --git a/packages/api/src/types/systemContactModels.ts b/packages/api/src/types/systemContactModels.ts deleted file mode 100644 index abbae9e374..0000000000 --- a/packages/api/src/types/systemContactModels.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { Contact } from './chatModels'; - -export interface SystemContact { - id: string; - firstName?: string | null; - lastName?: string | null; - phoneNumber?: string | null; - email?: string | null; - contactId?: string | null; -} - -export interface SystemContactSentInvite { - invitedTo?: string | null; - systemContactId?: string | null; - invitedAt?: number | null; -} - -export const InvitedToPersonalKey = 'personal-invite'; - -export interface SystemContactInviteParams { - type: 'sms' | 'email'; - recipients: string[]; - invite: { - link: string; - message: string; - subject?: string; - }; -} - -export const SystemContactInviteMessages = { - Personal: `I'm inviting you to Tlon Messenger`, -}; - -export function isSystemContact( - contact: Contact | SystemContact -): contact is SystemContact { - const hasPhone = 'phoneNumber' in contact; - const hasEmail = 'email' in contact; - return hasPhone || hasEmail; -} diff --git a/packages/api/src/types/types.ts b/packages/api/src/types/types.ts deleted file mode 100644 index 09b60d19a6..0000000000 --- a/packages/api/src/types/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './activityModels'; -export * from './clientModels'; -export * from './chatModels'; -export * from './commonModels'; -export * from './systemContactModels'; diff --git a/packages/shared/.eslintrc.cjs b/packages/shared/.eslintrc.cjs index a279e53c57..f7d16a170f 100644 --- a/packages/shared/.eslintrc.cjs +++ b/packages/shared/.eslintrc.cjs @@ -2,7 +2,15 @@ module.exports = { rules: { 'no-restricted-imports': [ 'error', - { patterns: ['@tloncorp/*', 'tlon-mobile', 'tlon-web'] }, + { + patterns: [ + '@tloncorp/*', + '!@tloncorp/api', + '!@tloncorp/api/**', + 'tlon-mobile', + 'tlon-web', + ], + }, ], }, }; diff --git a/packages/shared/src/domain/index.ts b/packages/shared/src/domain/index.ts index 144bf1f1ef..4029c41e16 100644 --- a/packages/shared/src/domain/index.ts +++ b/packages/shared/src/domain/index.ts @@ -9,6 +9,6 @@ export * from '@tloncorp/api/types/onboarding'; export * from '@tloncorp/api/types/post'; export * from '@tloncorp/api/types/references'; export * from '@tloncorp/api/types/system'; -export * from '@tloncorp/api/types/systemContactModels'; +export * from '@tloncorp/api/types/systemContacts'; export * from '@tloncorp/api/types/uploads'; export * from '@tloncorp/api/types/wayfinding'; diff --git a/packages/shared/src/electronAuth.ts b/packages/shared/src/electronAuth.ts deleted file mode 100644 index d6893faf8b..0000000000 --- a/packages/shared/src/electronAuth.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Authentication utility for Electron-specific functionality -import { createDevLogger } from './debug'; - -const logger = createDevLogger('electronAuth', false); - -// Type definitions -export interface AuthInfo { - ship: string; - shipUrl: string; - authCookie: string; -} - -// Helper to check if we're in Electron -export const isElectronEnv = (): boolean => { - if (typeof window !== 'undefined') { - return 'electronAPI' in window; - } - return false; -}; - -/** - * Store authentication information - * @param authInfo Authentication details to store - * @returns Promise resolving to success status - */ -export const storeAuthInfo = async (authInfo: AuthInfo): Promise => { - if (isElectronEnv()) { - try { - // Use type assertion to tell TypeScript to trust us - const api = (window as any).electronAPI; - return (await api?.storeAuthInfo?.(authInfo)) ?? false; - } catch (error) { - logger.error('Failed to store auth info:', error); - return false; - } - } - return false; -}; - -/** - * Retrieve stored authentication information - * @returns Promise resolving to auth info or null if not found - */ -export const getAuthInfo = async (): Promise => { - if (isElectronEnv()) { - try { - const api = (window as any).electronAPI; - return (await api?.getAuthInfo?.()) ?? null; - } catch (error) { - logger.error('Failed to get auth info:', error); - return null; - } - } - return null; -}; - -/** - * Clear stored authentication information - * @returns Promise resolving to success status - */ -export const clearAuthInfo = async (): Promise => { - if (isElectronEnv()) { - try { - const api = (window as any).electronAPI; - return (await api?.clearAuthInfo?.()) ?? false; - } catch (error) { - logger.error('Failed to clear auth info:', error); - return false; - } - } - return false; -}; diff --git a/packages/shared/src/electrtonAuth.ts b/packages/shared/src/electrtonAuth.ts index f46af89b68..3e5f972317 100644 --- a/packages/shared/src/electrtonAuth.ts +++ b/packages/shared/src/electrtonAuth.ts @@ -1 +1,72 @@ -export * from './electronAuth'; +// Authentication utility for Electron-specific functionality +import { createDevLogger } from './debug'; + +const logger = createDevLogger('electronAuth', false); + +// Type definitions +export interface AuthInfo { + ship: string; + shipUrl: string; + authCookie: string; +} + +// Helper to check if we're in Electron +export const isElectronEnv = (): boolean => { + if (typeof window !== 'undefined') { + return 'electronAPI' in window; + } + return false; +}; + +/** + * Store authentication information + * @param authInfo Authentication details to store + * @returns Promise resolving to success status + */ +export const storeAuthInfo = async (authInfo: AuthInfo): Promise => { + if (isElectronEnv()) { + try { + // Use type assertion to tell TypeScript to trust us + const api = (window as any).electronAPI; + return await api?.storeAuthInfo?.(authInfo) ?? false; + } catch (error) { + logger.error('Failed to store auth info:', error); + return false; + } + } + return false; +}; + +/** + * Retrieve stored authentication information + * @returns Promise resolving to auth info or null if not found + */ +export const getAuthInfo = async (): Promise => { + if (isElectronEnv()) { + try { + const api = (window as any).electronAPI; + return await api?.getAuthInfo?.() ?? null; + } catch (error) { + logger.error('Failed to get auth info:', error); + return null; + } + } + return null; +}; + +/** + * Clear stored authentication information + * @returns Promise resolving to success status + */ +export const clearAuthInfo = async (): Promise => { + if (isElectronEnv()) { + try { + const api = (window as any).electronAPI; + return await api?.clearAuthInfo?.() ?? false; + } catch (error) { + logger.error('Failed to clear auth info:', error); + return false; + } + } + return false; +}; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 9997be181a..5afc620efb 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -38,7 +38,7 @@ export * as tiptap from './logic/tiptap'; export * as utilHooks from './logic/utilHooks'; export * from './debug'; export * from './perf'; -export * from './electronAuth'; +export * from './electrtonAuth'; export * from '@urbit/aura'; export * from './store/dbHooks'; export * from './utils'; diff --git a/packages/shared/src/utils/__tests__/formatMemorySize.test.ts b/packages/shared/src/utils/__tests__/formatMemorySize.test.ts index 88f61544dd..c7836bb40a 100644 --- a/packages/shared/src/utils/__tests__/formatMemorySize.test.ts +++ b/packages/shared/src/utils/__tests__/formatMemorySize.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest'; -import { formatMemorySize } from '@tloncorp/api/lib/formatMemorySize'; +import { convert, formatMemorySize } from '@tloncorp/api/lib/formatMemorySize'; it('truncates trailing zeros', () => { expect(formatMemorySize(1126)).toBe('1.1kb'); @@ -21,3 +21,9 @@ it('rounds up to 1024 of the lower unit when above 1023.9', () => { expect(formatMemorySize(1023.95)).toBe('1024b'); expect(formatMemorySize(1024)).toBe('1kb'); }); + +it('can convert among different units using `convert`', () => { + expect(convert(1, 'kb').to('b')).toEqual(1024); + expect(convert(1, 'kb').to('kb')).toEqual(1); + expect(convert(2, 'gb').to('kb')).toEqual(2_097_152); +}); From e8633ba98263595606455ea95f0bedb312607446 Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Thu, 19 Feb 2026 15:02:05 -0500 Subject: [PATCH 3/6] fix: add direct @tloncorp/api deps for app clients --- apps/tlon-mobile/package.json | 3 ++- apps/tlon-web/package.json | 1 + packages/app/package.json | 1 + .../store/__tests__/blockingActions.test.ts | 1 + packages/shared/src/test/setup.ts | 24 +++++++++---------- pnpm-lock.yaml | 9 +++++++ 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/tlon-mobile/package.json b/apps/tlon-mobile/package.json index cb35845588..1c90145112 100644 --- a/apps/tlon-mobile/package.json +++ b/apps/tlon-mobile/package.json @@ -65,6 +65,7 @@ "@shopify/react-native-skia": "1.5.0", "@tamagui/react-native-media-driver": "~1.126.12", "@tanstack/react-query": "~5.32.1", + "@tloncorp/api": "workspace:*", "@tloncorp/app": "workspace:*", "@tloncorp/editor": "workspace:*", "@tloncorp/shared": "workspace:*", @@ -165,4 +166,4 @@ "tailwindcss": "^3.3.3", "vitest": "^1.0.4" } -} \ No newline at end of file +} diff --git a/apps/tlon-web/package.json b/apps/tlon-web/package.json index 1986558b9a..18ea4e7987 100644 --- a/apps/tlon-web/package.json +++ b/apps/tlon-web/package.json @@ -94,6 +94,7 @@ "@tiptap/pm": "^2.6.6", "@tiptap/react": "^2.6.6", "@tiptap/suggestion": "^2.6.6", + "@tloncorp/api": "workspace:*", "@tloncorp/app": "workspace:*", "@tloncorp/mock-http-api": "^1.2.0", "@tloncorp/shared": "workspace:*", diff --git a/packages/app/package.json b/packages/app/package.json index 1d6a30b66b..8e2e74e971 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@emoji-mart/data": "^1.1.2", + "@tloncorp/api": "workspace:*", "@tloncorp/editor": "workspace:*", "@tloncorp/shared": "workspace:*", "@tloncorp/ui": "workspace:*", diff --git a/packages/shared/src/store/__tests__/blockingActions.test.ts b/packages/shared/src/store/__tests__/blockingActions.test.ts index be7e031ead..00d71e8f8e 100644 --- a/packages/shared/src/store/__tests__/blockingActions.test.ts +++ b/packages/shared/src/store/__tests__/blockingActions.test.ts @@ -13,6 +13,7 @@ vi.mock('../reactQuery', () => ({ queryClient: { invalidateQueries: vi.fn(), }, + QueryClientProvider: ({ children }: { children: unknown }) => children, })); describe('blockingLogic', () => { diff --git a/packages/shared/src/test/setup.ts b/packages/shared/src/test/setup.ts index 060818544d..f1ee9e712d 100644 --- a/packages/shared/src/test/setup.ts +++ b/packages/shared/src/test/setup.ts @@ -56,16 +56,14 @@ vi.mock('../store/storage', async (importOriginal) => { }; }); -export function mockUrbit() { - vi.mock('@tloncorp/api', async (importOriginal) => { - const mod = await importOriginal(); - const out: typeof mod = { - ...mod, - scry: vi.fn(), - trackedPoke: vi.fn(), - poke: vi.fn(), - getCurrentUserId: () => '~solfer-magfed', - }; - return out; - }); -} +vi.mock('../../../api/src/client/urbit', async (importOriginal) => { + const mod = (await importOriginal()) as Record; + + return { + ...mod, + scry: vi.fn(), + poke: vi.fn(), + trackedPoke: vi.fn(), + getCurrentUserId: () => '~solfer-magfed', + }; +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f43bf4f06..bce3f7fb8f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -235,6 +235,9 @@ importers: '@tanstack/react-query': specifier: ~5.32.1 version: 5.32.1(react@18.3.1) + '@tloncorp/api': + specifier: workspace:* + version: link:../../packages/api '@tloncorp/app': specifier: workspace:* version: link:../../packages/app @@ -656,6 +659,9 @@ importers: '@tiptap/suggestion': specifier: 2.6.0 version: 2.6.0(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) + '@tloncorp/api': + specifier: workspace:* + version: link:../../packages/api '@tloncorp/app': specifier: workspace:* version: link:../../packages/app @@ -957,6 +963,9 @@ importers: '@tanstack/react-query': specifier: ^5.32.1 version: 5.32.1(react@18.3.1) + '@tloncorp/api': + specifier: workspace:* + version: link:../api '@tloncorp/editor': specifier: workspace:* version: link:../editor From edd35665119eef20c1e53cfa59a9d83c891737f2 Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Thu, 19 Feb 2026 17:37:30 -0500 Subject: [PATCH 4/6] fix(web-e2e): include api workspace in parallel runner image --- apps/tlon-web/rube/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/tlon-web/rube/Dockerfile b/apps/tlon-web/rube/Dockerfile index 2c49a99a01..135a2dc2bc 100644 --- a/apps/tlon-web/rube/Dockerfile +++ b/apps/tlon-web/rube/Dockerfile @@ -37,13 +37,14 @@ COPY ../../../.nvmrc /workspace/ COPY ../../../tsconfig* /workspace/ # Create directory structure for packages -RUN mkdir -p /workspace/packages/shared /workspace/packages/ui /workspace/packages/app /workspace/packages/editor +RUN mkdir -p /workspace/packages/shared /workspace/packages/ui /workspace/packages/app /workspace/packages/editor /workspace/packages/api # Copy package.json files for all workspaces (more specific paths) COPY ../../../packages/shared/package.json /workspace/packages/shared/ COPY ../../../packages/ui/package.json /workspace/packages/ui/ COPY ../../../packages/app/package.json /workspace/packages/app/ COPY ../../../packages/editor/package.json /workspace/packages/editor/ +COPY ../../../packages/api/package.json /workspace/packages/api/ COPY ../../../apps/tlon-web/package.json /workspace/apps/tlon-web/ COPY ../../../apps/tlon-mobile/package.json /workspace/apps/tlon-mobile/ COPY ../../../apps/tlon-desktop/package.json /workspace/apps/tlon-desktop/ @@ -125,4 +126,4 @@ RUN echo "Final check - rube scripts:" && ls -la ./rube/dist/*.js 2>/dev/null || # Entry point for running tests with sharding ENTRYPOINT ["/bin/bash", "-c"] -CMD ["pnpm e2e"] \ No newline at end of file +CMD ["pnpm e2e"] From 876fd6d9881b96eaf9dfab033cefbe3d19b849b5 Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Fri, 20 Feb 2026 11:31:47 -0500 Subject: [PATCH 5/6] fix(shared): repoint markdown urbit imports to api package --- packages/shared/src/logic/markdown/mdastToStory.ts | 4 ++-- packages/shared/src/logic/markdown/parse.ts | 2 +- packages/shared/src/logic/markdown/serialize.ts | 4 ++-- packages/shared/src/logic/markdown/storyToMdast.ts | 4 ++-- packages/shared/src/logic/roundTrip.test.ts | 6 +++--- packages/shared/src/logic/storyToMarkdown.test.ts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/shared/src/logic/markdown/mdastToStory.ts b/packages/shared/src/logic/markdown/mdastToStory.ts index 2c0e2474d1..ca8658fcda 100644 --- a/packages/shared/src/logic/markdown/mdastToStory.ts +++ b/packages/shared/src/logic/markdown/mdastToStory.ts @@ -38,8 +38,8 @@ import { Ship, Strikethrough, Task, -} from '../../urbit/content'; -import { Story, Verse, VerseBlock, VerseInline } from '../../urbit/channel'; +} from '@tloncorp/api/urbit/content'; +import { Story, Verse, VerseBlock, VerseInline } from '@tloncorp/api/urbit/channel'; import type { ShipMention } from './shipMentionPlugin'; /** diff --git a/packages/shared/src/logic/markdown/parse.ts b/packages/shared/src/logic/markdown/parse.ts index afb4d594b3..74133abcfe 100644 --- a/packages/shared/src/logic/markdown/parse.ts +++ b/packages/shared/src/logic/markdown/parse.ts @@ -3,7 +3,7 @@ import remarkParse from 'remark-parse'; import remarkGfm from 'remark-gfm'; import type { Root } from 'mdast'; -import { Story } from '../../urbit/channel'; +import { Story } from '@tloncorp/api/urbit/channel'; import { mdastToStory } from './mdastToStory'; import { remarkShipMentions } from './shipMentionPlugin'; diff --git a/packages/shared/src/logic/markdown/serialize.ts b/packages/shared/src/logic/markdown/serialize.ts index aa29791589..0152b5ffe5 100644 --- a/packages/shared/src/logic/markdown/serialize.ts +++ b/packages/shared/src/logic/markdown/serialize.ts @@ -3,8 +3,8 @@ import remarkStringify from 'remark-stringify'; import remarkGfm from 'remark-gfm'; import type { Root, RootContent, PhrasingContent, Node } from 'mdast'; -import { Story } from '../../urbit/channel'; -import { Block, Inline } from '../../urbit/content'; +import { Story } from '@tloncorp/api/urbit/channel'; +import { Block, Inline } from '@tloncorp/api/urbit/content'; import { storyToMdast, inlinesToPhrasing } from './storyToMdast'; import type { ShipMention } from './shipMentionPlugin'; import { visit, visitAll } from './astUtils'; diff --git a/packages/shared/src/logic/markdown/storyToMdast.ts b/packages/shared/src/logic/markdown/storyToMdast.ts index be5299c471..f299a8cee7 100644 --- a/packages/shared/src/logic/markdown/storyToMdast.ts +++ b/packages/shared/src/logic/markdown/storyToMdast.ts @@ -53,8 +53,8 @@ import { ListItem, Listing, Rule, -} from '../../urbit/content'; -import { Story, Verse, isBlockVerse } from '../../urbit/channel'; +} from '@tloncorp/api/urbit/content'; +import { Story, Verse, isBlockVerse } from '@tloncorp/api/urbit/channel'; import type { ShipMention } from './shipMentionPlugin'; /** diff --git a/packages/shared/src/logic/roundTrip.test.ts b/packages/shared/src/logic/roundTrip.test.ts index 1de302976d..4c9a6710c3 100644 --- a/packages/shared/src/logic/roundTrip.test.ts +++ b/packages/shared/src/logic/roundTrip.test.ts @@ -16,10 +16,10 @@ import { Strikethrough, Task, Blockquote, -} from '../urbit/content'; -import { Story, constructStory } from '../urbit/channel'; +} from '@tloncorp/api/urbit/content'; +import { Story, constructStory } from '@tloncorp/api/urbit/channel'; import { JSONToInlines } from './tiptap'; -import { JSONContent } from '../urbit'; +import { JSONContent } from '@tloncorp/api/urbit'; /** * Round-trip conversion tests for Markdown ↔ Story conversion. diff --git a/packages/shared/src/logic/storyToMarkdown.test.ts b/packages/shared/src/logic/storyToMarkdown.test.ts index d21cff9070..6341d60d33 100644 --- a/packages/shared/src/logic/storyToMarkdown.test.ts +++ b/packages/shared/src/logic/storyToMarkdown.test.ts @@ -17,8 +17,8 @@ import { Ship, Strikethrough, Task, -} from '../urbit/content'; -import { Story } from '../urbit/channel'; +} from '@tloncorp/api/urbit/content'; +import { Story } from '@tloncorp/api/urbit/channel'; import { blockToMarkdown, inlinesToMarkdown, From 63cf3d8bfb176abcbc175b289e1df76f6b6de852 Mon Sep 17 00:00:00 2001 From: Dan Brewster Date: Fri, 20 Feb 2026 12:15:28 -0500 Subject: [PATCH 6/6] fix(web-e2e): skip lifecycle scripts in deps install layer --- apps/tlon-web/rube/Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/tlon-web/rube/Dockerfile b/apps/tlon-web/rube/Dockerfile index 135a2dc2bc..6f03053ce2 100644 --- a/apps/tlon-web/rube/Dockerfile +++ b/apps/tlon-web/rube/Dockerfile @@ -55,9 +55,11 @@ COPY ../../../patches/ /workspace/patches/ # Copy .npmrc if it exists (for npm configurations) COPY ../../../.npmrc* /workspace/ -# Install dependencies (with cache mount for faster rebuilds) +# Install dependencies (with cache mount for faster rebuilds). +# Ignore lifecycle scripts in this dependency-only layer to avoid running +# desktop postinstall hooks (electron native rebuilds) during web E2E image build. RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ - pnpm install --frozen-lockfile + pnpm install --frozen-lockfile --ignore-scripts # Install Playwright browsers and dependencies (before source copy for better caching) WORKDIR /workspace/apps/tlon-web