diff --git a/apps/tlon-mobile/android/app/proguard-rules.pro b/apps/tlon-mobile/android/app/proguard-rules.pro index 551eb41da2..392da8436c 100644 --- a/apps/tlon-mobile/android/app/proguard-rules.pro +++ b/apps/tlon-mobile/android/app/proguard-rules.pro @@ -11,4 +11,7 @@ -keep class com.swmansion.reanimated.** { *; } -keep class com.facebook.react.turbomodule.** { *; } +# realm +-keep class io.realm.react.** + # Add any project specific keep options here: diff --git a/apps/tlon-mobile/ios/Landscape.xcodeproj/project.pbxproj b/apps/tlon-mobile/ios/Landscape.xcodeproj/project.pbxproj index a3a421cf6c..83a2bb814f 100644 --- a/apps/tlon-mobile/ios/Landscape.xcodeproj/project.pbxproj +++ b/apps/tlon-mobile/ios/Landscape.xcodeproj/project.pbxproj @@ -482,7 +482,7 @@ mainGroup = 83CBB9F61A601CBA00E9B192; packageReferences = ( 70A62C5F2A5A6B1A00EBED16 /* XCRemoteSwiftPackageReference "SimpleKeychain" */, - 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire" */, + 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire.git" */, 70D3866D2A60A3B300AFB46E /* XCRemoteSwiftPackageReference "UrsusSigil" */, ); productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; @@ -1177,6 +1177,12 @@ " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1250,6 +1256,12 @@ " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1318,7 +1330,7 @@ minimumVersion = 1.0.0; }; }; - 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire" */ = { + 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; requirement = { @@ -1342,7 +1354,7 @@ minimumVersion = 1.0.0; }; }; - 70DBBFE32B7C60B50021EA96 /* XCRemoteSwiftPackageReference "Alamofire" */ = { + 70DBBFE32B7C60B50021EA96 /* XCRemoteSwiftPackageReference "Alamofire.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; requirement = { @@ -1368,7 +1380,7 @@ }; 70D386472A6098F800AFB46E /* Alamofire */ = { isa = XCSwiftPackageProductDependency; - package = 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire" */; + package = 70D386462A6098F800AFB46E /* XCRemoteSwiftPackageReference "Alamofire.git" */; productName = Alamofire; }; 70D3866E2A60A3B300AFB46E /* UrsusSigil */ = { @@ -1383,7 +1395,7 @@ }; 70DBBFE22B7C60B50021EA96 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; - package = 70DBBFE32B7C60B50021EA96 /* XCRemoteSwiftPackageReference "Alamofire" */; + package = 70DBBFE32B7C60B50021EA96 /* XCRemoteSwiftPackageReference "Alamofire.git" */; productName = Alamofire; }; 70DBBFE42B7C60B50021EA96 /* UrsusSigil */ = { diff --git a/apps/tlon-mobile/ios/Podfile.lock b/apps/tlon-mobile/ios/Podfile.lock index 9e88dde902..d120bd8db0 100644 --- a/apps/tlon-mobile/ios/Podfile.lock +++ b/apps/tlon-mobile/ios/Podfile.lock @@ -1174,6 +1174,8 @@ PODS: - React-jsi (= 0.73.4) - React-logger (= 0.73.4) - React-perflogger (= 0.73.4) + - RealmJS (12.6.0): + - React - recaptcha-enterprise-react-native (18.4.0): - React-Core - RecaptchaEnterprise (= 18.4.0) @@ -1289,6 +1291,7 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - RealmJS (from `../../../node_modules/realm`) - "recaptcha-enterprise-react-native (from `../../../node_modules/@google-cloud/recaptcha-enterprise-react-native`)" - "RNCAsyncStorage (from `../../../node_modules/@react-native-async-storage/async-storage`)" - RNDeviceInfo (from `../../../node_modules/react-native-device-info`) @@ -1468,6 +1471,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/utils" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RealmJS: + :path: "../../../node_modules/realm" recaptcha-enterprise-react-native: :path: "../../../node_modules/@google-cloud/recaptcha-enterprise-react-native" RNCAsyncStorage: @@ -1579,6 +1584,7 @@ SPEC CHECKSUMS: React-runtimescheduler: 1c054b58fef2ce74cdcbdcd70db190e10f56a617 React-utils: 21a798438d45e70ed9c2e2fe0894ee32ba7b7c5b ReactCommon: dcc65c813041388dead6c8b477444757425ce961 + RealmJS: a62dc7a1f94b888fe9e8712cd650167ad97dc636 recaptcha-enterprise-react-native: 7d63c5bdde3b48996b984a86ac2b536a1d8f5f16 RecaptchaEnterprise: dc302910b77963a0cc6f6908407e30b35268a755 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 @@ -1593,7 +1599,7 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 sqlite3: f163dbbb7aa3339ad8fc622782c2d9d7b72f7e9c UMAppLoader: 5df85360d65cabaef544be5424ac64672e648482 - Yoga: 1b901a6d6eeba4e8a2e8f308f708691cdb5db312 + Yoga: 64cd2a583ead952b0315d5135bf39e053ae9be70 PODFILE CHECKSUM: 82da24eb176d4abdeaf445b3581717ec492dd7e8 diff --git a/apps/tlon-mobile/package.json b/apps/tlon-mobile/package.json index 6c873553e0..c397a590df 100644 --- a/apps/tlon-mobile/package.json +++ b/apps/tlon-mobile/package.json @@ -38,6 +38,7 @@ "@react-navigation/bottom-tabs": "^6.5.12", "@react-navigation/native": "^6.1.7", "@react-navigation/native-stack": "^6.9.13", + "@realm/react": "^0.6.2", "@tloncorp/shared": "*", "@urbit/aura": "^1.0.0", "classnames": "^2.3.2", @@ -71,6 +72,7 @@ "react-native-storage": "^1.0.1", "react-native-svg": "^14.1.0", "react-native-webview": "13.6.4", + "realm": "^12.6.0", "tailwind-rn": "^4.2.0" }, "devDependencies": { diff --git a/apps/tlon-mobile/src/App.tsx b/apps/tlon-mobile/src/App.tsx index 5d28197ec1..8a1e75d217 100644 --- a/apps/tlon-mobile/src/App.tsx +++ b/apps/tlon-mobile/src/App.tsx @@ -17,10 +17,12 @@ import { useTailwind } from 'tailwind-rn'; import { LoadingSpinner } from './components/LoadingSpinner'; import { ShipProvider, useShip } from './contexts/ship'; +import * as db from './db'; import { useDeepLink } from './hooks/useDeepLink'; import { useIsDarkMode } from './hooks/useIsDarkMode'; import { useScreenOptions } from './hooks/useScreenOptions'; import { inviteShipWithLure } from './lib/hostingApi'; +import { syncContacts } from './lib/sync'; import { TabStack } from './navigation/TabStack'; import { CheckVerifyScreen } from './screens/CheckVerifyScreen'; import { EULAScreen } from './screens/EULAScreen'; @@ -55,6 +57,12 @@ const App = ({ wer: initialWer }: Props) => { const screenOptions = useScreenOptions(); const gotoPath = wer ?? initialWer; + useEffect(() => { + if (isAuthenticated) { + syncContacts(); + } + }, [isAuthenticated]); + useEffect(() => { const unsubscribeFromNetInfo = NetInfo.addEventListener( ({ isConnected }) => { @@ -223,17 +231,19 @@ const App = ({ wer: initialWer }: Props) => { ); }; -export default function AnalyticsApp(props: Props) { +export default function ConnectedApp(props: Props) { const isDarkMode = useIsDarkMode(); return ( - - - - - - - - - + + + + + + + + + + + ); } diff --git a/apps/tlon-mobile/src/db/index.ts b/apps/tlon-mobile/src/db/index.ts new file mode 100644 index 0000000000..ac2f66eea9 --- /dev/null +++ b/apps/tlon-mobile/src/db/index.ts @@ -0,0 +1,2 @@ +export * from './realm'; +export * from './schemas'; diff --git a/apps/tlon-mobile/src/db/realm.tsx b/apps/tlon-mobile/src/db/realm.tsx new file mode 100644 index 0000000000..3d46a4a48d --- /dev/null +++ b/apps/tlon-mobile/src/db/realm.tsx @@ -0,0 +1,90 @@ +import { createRealmContext } from '@realm/react'; +import React from 'react'; +import type { PropsWithChildren } from 'react'; +import type Realm from 'realm'; + +import type { SchemaMap, SchemaName } from './schemas'; +import { schemas } from './schemas'; + +// This is a copy of Realm's `UpdateMode` enum. Not ideal, but realm only +// exports `UpdateMode` as a type, which causes a lint error if we try to use it +// directly. +export enum UpdateMode { + Never = 'never', + Modified = 'modified', + All = 'all', +} + +// Realm provider setup + +const config: Realm.Configuration = { + schema: schemas, + schemaVersion: 0, +}; + +const { + RealmProvider: BaseRealmProvider, + useObject, + useQuery, + useRealm, +} = createRealmContext(config); + +let realmInstance: Realm | null = null; + +function realm() { + if (!realmInstance) { + throw new Error('Realm instance not available'); + } + return realmInstance; +} + +// The only straightforward way to get the realm instance here is to use the +// `realmRef` property. Since the property takes a ref, we use a proxy to +// synchronously mirror the set value to the local `realm` variable. +const realmRefProxy = { + set current(val: Realm | null) { + realmInstance = val; + }, +}; + +const RealmProvider = ({ children }: PropsWithChildren) => { + return ( + {children} + ); +}; + +export { RealmProvider, useObject, useQuery, useRealm }; + +// Utility functions + +export function createBatch( + model: T, + data: SchemaMap[T][], + updateMode = UpdateMode.Modified +): SchemaMap[T][] { + return realm().write(() => + data.map((d) => { + return realm().create(model, d, updateMode); + }) + ); +} + +export function create( + model: T, + data: SchemaMap[T], + updateMode = UpdateMode.Modified +): SchemaMap[T] { + return realm().write(() => + realm().create(model, data, updateMode) + ); +} + +export function update( + model: T, + data: Partial, + updateMode = UpdateMode.Modified +): SchemaMap[T] { + return realm().write(() => + realm().create(model, data, updateMode) + ); +} diff --git a/apps/tlon-mobile/src/db/schemas.ts b/apps/tlon-mobile/src/db/schemas.ts new file mode 100644 index 0000000000..3e446e8d9c --- /dev/null +++ b/apps/tlon-mobile/src/db/schemas.ts @@ -0,0 +1,35 @@ +export type Contact = { + id: string; + nickname: string | null; + bio: string | null; + status: string | null; + color: string | null; + avatarImage: string | null; + coverImage: string | null; + pinnedGroupIds: string[]; +}; + +const contactSchema = { + name: 'Contact', + properties: { + id: 'string', + nickname: 'string?', + bio: 'string?', + status: 'string?', + color: 'string?', + avatarImage: 'string?', + coverImage: 'string?', + pinnedGroupIds: 'string[]', + }, + primaryKey: 'id', +}; + +// Should contain all schemas, will be passed to Realm constructor +export const schemas = [contactSchema]; + +// Should contain all schema types, used to map Realm object types to TypeScript types +export type SchemaMap = { + Contact: Contact; +}; + +export type SchemaName = keyof SchemaMap; diff --git a/apps/tlon-mobile/src/lib/api.ts b/apps/tlon-mobile/src/lib/api.ts index 6137778379..2246243fde 100644 --- a/apps/tlon-mobile/src/lib/api.ts +++ b/apps/tlon-mobile/src/lib/api.ts @@ -53,3 +53,13 @@ export const poke = async ({ mark, json, }); + +export const scry = async ({ app, path }: { app: string; path: string }) => { + return fetch(`${config.shipUrl}/~/scry/${app}${path}.json`, { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + credentials: 'include', + }).then((res) => res.json()) as Promise; +}; diff --git a/apps/tlon-mobile/src/lib/contactsApi.test.ts b/apps/tlon-mobile/src/lib/contactsApi.test.ts new file mode 100644 index 0000000000..7c9d06a350 --- /dev/null +++ b/apps/tlon-mobile/src/lib/contactsApi.test.ts @@ -0,0 +1,47 @@ +import { expect, test } from 'vitest'; + +import { toClientContact, toClientContacts } from './contactsApi'; + +const inputContact: [string, any] = [ + 'test', + { + status: 'listening to music', + avatar: null, + cover: + 'https://20-urbit.s3.us-west-1.amazonaws.com/ravmel-ropdyl/2021.2.13..00.31.09-Manaslu-crevasses.jpg', + bio: 'happy to chat, send a dm any time', + nickname: 'galen', + color: '0xff.ffff', + groups: [ + '~ravmel-ropdyl/audio-video-images', + '~nibset-napwyn/tlon', + '~ravmel-ropdyl/crate', + ], + }, +]; + +const outputContact = { + id: 'test', + avatarImage: null, + coverImage: + 'https://20-urbit.s3.us-west-1.amazonaws.com/ravmel-ropdyl/2021.2.13..00.31.09-Manaslu-crevasses.jpg', + bio: 'happy to chat, send a dm any time', + nickname: 'galen', + status: 'listening to music', + color: '#ffffff', + pinnedGroupIds: [ + '~ravmel-ropdyl/audio-video-images', + '~nibset-napwyn/tlon', + '~ravmel-ropdyl/crate', + ], +}; + +test('converts a contact from server to client format', () => { + expect(toClientContact(...inputContact)).toStrictEqual(outputContact); +}); + +test('converts an array of contacts from server to client format', () => { + expect( + toClientContacts({ [inputContact[0]]: inputContact[1] }) + ).toStrictEqual([outputContact]); +}); diff --git a/apps/tlon-mobile/src/lib/contactsApi.ts b/apps/tlon-mobile/src/lib/contactsApi.ts new file mode 100644 index 0000000000..94972e857b --- /dev/null +++ b/apps/tlon-mobile/src/lib/contactsApi.ts @@ -0,0 +1,35 @@ +import type * as ub from '@tloncorp/shared/dist/urbit/contact'; +import { parseUx } from '@urbit/aura'; + +import type * as db from '../db'; +import { scry } from './api'; + +export const getContacts = async () => { + const results = await scry({ + app: 'contacts', + path: '/all', + }); + return toClientContacts(results); +}; + +export const toClientContacts = (contacts: ub.ContactRolodex): db.Contact[] => { + return Object.entries(contacts).map(([ship, contact]) => + toClientContact(ship, contact) + ); +}; + +export const toClientContact = ( + id: string, + contact: ub.Contact | null +): db.Contact => { + return { + id, + nickname: contact?.nickname ?? null, + bio: contact?.bio ?? null, + status: contact?.status ?? null, + color: contact?.color ? '#' + parseUx(contact.color) : null, + coverImage: contact?.cover ?? null, + avatarImage: contact?.avatar ?? null, + pinnedGroupIds: contact?.groups ?? [], + }; +}; diff --git a/apps/tlon-mobile/src/lib/sync.ts b/apps/tlon-mobile/src/lib/sync.ts new file mode 100644 index 0000000000..dd4bcba663 --- /dev/null +++ b/apps/tlon-mobile/src/lib/sync.ts @@ -0,0 +1,8 @@ +import * as db from '../db'; +import { getContacts } from './contactsApi'; + +export const syncContacts = async () => { + const contacts = await getContacts(); + db.createBatch('Contact', contacts, db.UpdateMode.All); + console.log('Synced', contacts.length, 'contacts'); +}; diff --git a/package-lock.json b/package-lock.json index 695ad5f200..820b50c120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "@react-navigation/bottom-tabs": "^6.5.12", "@react-navigation/native": "^6.1.7", "@react-navigation/native-stack": "^6.9.13", + "@realm/react": "^0.6.2", "@tloncorp/shared": "*", "@urbit/aura": "^1.0.0", "classnames": "^2.3.2", @@ -67,6 +68,7 @@ "react-native-storage": "^1.0.1", "react-native-svg": "^14.1.0", "react-native-webview": "13.6.4", + "realm": "^12.6.0", "tailwind-rn": "^4.2.0" }, "devDependencies": { @@ -12168,7 +12170,6 @@ "version": "0.73.14", "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.14.tgz", "integrity": "sha512-KzIwsTvAJrXPtwhGOSm+OcJH1B8TpY8cS4xxzu/e2qv3a2n4VLePHTPAfco1tmvekV8OHWvvD9JSIX7i2fB1gg==", - "peer": true, "dependencies": { "@react-native-community/cli-server-api": "12.3.2", "@react-native-community/cli-tools": "12.3.2", @@ -12190,7 +12191,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -12205,7 +12205,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12221,7 +12220,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -12232,14 +12230,12 @@ "node_modules/@react-native/community-cli-plugin/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/@react-native/community-cli-plugin/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -12262,7 +12258,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "peer": true, "engines": { "node": ">=10" }, @@ -12274,7 +12269,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, "engines": { "node": ">=8" } @@ -12283,7 +12277,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "peer": true, "engines": { "node": ">=10.17.0" } @@ -12292,7 +12285,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "peer": true, "dependencies": { "path-key": "^3.0.0" }, @@ -12304,7 +12296,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "peer": true, "engines": { "node": ">=6" } @@ -12313,7 +12304,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -12397,7 +12387,6 @@ "version": "0.73.14", "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.14.tgz", "integrity": "sha512-5wLeYw/lormpSqYfI9H/geZ/EtPmi+x5qLkEit15Q/70hkzYo/M+aWztUtbOITfgTEOP8d6ybROzoGsqgyZLcw==", - "peer": true, "dependencies": { "@babel/core": "^7.20.0", "@react-native/babel-preset": "0.73.20", @@ -12668,6 +12657,22 @@ "nanoid": "^3.1.23" } }, + "node_modules/@realm/react": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@realm/react/-/react-0.6.2.tgz", + "integrity": "sha512-FQ05Ab8Ty9FbKcZtW9i9+eP6pfxwsRV9cwhkVxFJ7kwBoozyAGCByIx3Fwfm/pPTGoHqPMfqaXe5HYEnde/CHg==", + "dependencies": { + "lodash": "^4.17.21" + }, + "optionalDependencies": { + "@babel/runtime": ">=7", + "react-native": ">=0.68" + }, + "peerDependencies": { + "react": ">=17.0.2", + "realm": "^12.0.0-browser || ^12.0.0 || ^12.0.0-rc || ^11.0.0" + } + }, "node_modules/@remirror/core-constants": { "version": "2.0.1", "license": "MIT", @@ -18378,6 +18383,17 @@ "node-int64": "^0.4.0" } }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/buffer": { "version": "5.7.1", "funding": [ @@ -19806,6 +19822,20 @@ "node": ">=0.10" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -21694,6 +21724,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/expect": { "version": "28.1.3", "dev": true, @@ -22796,6 +22834,11 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -23007,6 +23050,11 @@ "node": ">=6" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.2.3", "license": "ISC", @@ -27243,6 +27291,17 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "license": "MIT", @@ -27422,7 +27481,6 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "dev": true, "license": "MIT" }, "node_modules/mlly": { @@ -27662,6 +27720,11 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -27762,6 +27825,31 @@ "node": ">=12.0.0" } }, + "node_modules/node-abi": { + "version": "3.55.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.55.0.tgz", + "integrity": "sha512-uPEjtyh2tFEvWYt4Jw7McOD5FPcHkcxm/tHZc5PWaDB3JYq0rGFUbgaAK+CT5pYpQddBfsZVWI08OwoRfdfbcQ==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", @@ -27825,6 +27913,11 @@ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, + "node_modules/node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==" + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -29345,6 +29438,70 @@ "fflate": "^0.4.1" } }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/prebuild-install/node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -30217,7 +30374,6 @@ "version": "0.73.3", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.3.tgz", "integrity": "sha512-RSQDtT2DNUcmB4IgmW9NhRb5wqvXFl6DI2NEJmt0ps2OrVHpoA8Tkq+lkFOA/fvPscJKtFKEHFBDSR5UHR3PUw==", - "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native-community/cli": "12.3.2", @@ -30478,7 +30634,6 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "peer": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -30494,7 +30649,6 @@ "version": "15.0.19", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "peer": true, "dependencies": { "@types/yargs-parser": "*" } @@ -30503,7 +30657,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -30518,7 +30671,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -30534,7 +30686,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -30545,14 +30696,12 @@ "node_modules/react-native/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/react-native/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, "engines": { "node": ">=8" } @@ -30561,7 +30710,6 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "peer": true, "dependencies": { "@jest/types": "^26.6.2", "ansi-regex": "^5.0.0", @@ -30575,14 +30723,12 @@ "node_modules/react-native/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "peer": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/react-native/node_modules/scheduler": { "version": "0.24.0-canary-efb381bbf-20230505", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -30591,7 +30737,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30603,7 +30748,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "peer": true, "dependencies": { "async-limiter": "~1.0.0" } @@ -30988,6 +31132,29 @@ "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, + "node_modules/realm": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/realm/-/realm-12.6.0.tgz", + "integrity": "sha512-lwixjVE8uiHXqRggJ9DwCxy3P1I0SUGBFG3dLQnXT20o6PdDVpXsTgE82m0svviKyDLs8yb5hLim5HRcHkH5rA==", + "hasInstallScript": true, + "dependencies": { + "bson": "^4.7.2", + "debug": "^4.3.4", + "node-machine-id": "^1.1.12", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react-native": ">=0.71.0" + }, + "peerDependenciesMeta": { + "react-native": { + "optional": true + } + } + }, "node_modules/recast": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", @@ -31784,6 +31951,49 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-plist": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", @@ -34045,6 +34255,17 @@ "dev": true, "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "dev": true,