-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3283 from tloncorp/db/contact-sync
Add Realm + Contact sync
- Loading branch information
Showing
13 changed files
with
527 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './realm'; | ||
export * from './schemas'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<BaseRealmProvider realmRef={realmRefProxy}>{children}</BaseRealmProvider> | ||
); | ||
}; | ||
|
||
export { RealmProvider, useObject, useQuery, useRealm }; | ||
|
||
// Utility functions | ||
|
||
export function createBatch<T extends SchemaName>( | ||
model: T, | ||
data: SchemaMap[T][], | ||
updateMode = UpdateMode.Modified | ||
): SchemaMap[T][] { | ||
return realm().write(() => | ||
data.map((d) => { | ||
return realm().create<SchemaMap[T]>(model, d, updateMode); | ||
}) | ||
); | ||
} | ||
|
||
export function create<T extends SchemaName>( | ||
model: T, | ||
data: SchemaMap[T], | ||
updateMode = UpdateMode.Modified | ||
): SchemaMap[T] { | ||
return realm().write(() => | ||
realm().create<SchemaMap[T]>(model, data, updateMode) | ||
); | ||
} | ||
|
||
export function update<T extends SchemaName>( | ||
model: T, | ||
data: Partial<SchemaMap[T]>, | ||
updateMode = UpdateMode.Modified | ||
): SchemaMap[T] { | ||
return realm().write(() => | ||
realm().create<SchemaMap[T]>(model, data, updateMode) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]); | ||
}); |
Oops, something went wrong.