@offline-protocol/id-react
v0.2.0
Published
Offline ID for React and Next.js: email OTP sign-in, profiles and connections.
Downloads
1,067
Readme
@offline-protocol/id-react
Offline ID for React / Next.js: email/OTP authentication, profiles,
and connections via OfflineAppProvider and hooks. Location proofs
live in @offline-protocol/pol.
License
MIT — free to use in open-source and proprietary apps.
Install
npm install @offline-protocol/id-reactQuick start
import { OfflineAppProvider, useAuth } from '@offline-protocol/id-react';
export function App({ children }: { children: React.ReactNode }) {
return (
<OfflineAppProvider appId="app_xxxxxxxx">
{children}
</OfflineAppProvider>
);
}Replace app_xxxxxxxx with an app ID from your organization on
dev.offlineprotocol.com.
projectId is still accepted as a deprecated alias for appId.
Connections and location sharing
import { useConnections } from '@offline-protocol/id-react';
function Friends() {
const { connections, setLocationSharing } = useConnections();
return (
<ul>
{connections.map((c) => (
<li key={c.id}>
{c.peer}
{c.sharingLocationWithMe && ' shares location with you'}
<label>
<input
type="checkbox"
checked={c.sharingLocationWithThem}
onChange={(e) => setLocationSharing(c.id, e.target.checked)}
/>
Share my location
</label>
</li>
))}
</ul>
);
}Each item in connections is seen from the signed-in user's side:
| Field | Meaning |
| ----- | ------- |
| id | Connection ID |
| peer | The other profile's username |
| sharingLocationWithThem | You share your location with peer |
| sharingLocationWithMe | peer shares their location with you |
Location sharing is per connection and one way, and it is off by default,
including for connections made before it existed. A peer's location is only
returned to you (GET /connections/{username}/locations) once they turn
sharing on for your connection.
setLocationSharing(connectionId, share) turns sharing of your own location
with that peer on or off. It is idempotent and never changes the peer's side.
The connections list updates at once. If several updates to one connection
overlap (a quickly toggled checkbox), they are sent one at a time in the order
you made them, and the last one decides what the list shows. One that a later
update replaces before it is sent is not sent at all.
It resolves to what became of the update:
| status | Meaning | connections shows |
| -------- | ------- | ------------------- |
| applied | The server took it. connection is the updated connection, or null if the server returned none. | The new value |
| rejected | It was not applied: the server turned it down (a 4xx), or nobody is signed in. | What the server last confirmed |
| unknown | No usable answer (a timeout, a dropped connection, a 5xx), and the one automatic retry was not applied either. It may or may not have been applied. | Sharing as on, if it may be on |
| superseded | You made a later update to the same connection before this one was sent. | Whatever the later one settles to |
const result = await setLocationSharing(c.id, false);
if (result.status === 'unknown') {
// Tell the user it could not be confirmed, and let them try again.
}While what the server holds is unknown, the list shows sharing as on rather
than risk saying "not sharing" while your location is shared. It stays that
way until the server answers: call setLocationSharing again (always safe),
or let the list reload on the next sign-in.
One case the SDK cannot rule out: a request that timed out can still reach the
server later, after a newer update to the same connection was confirmed. The
API has no version to refuse the late one with, so after an unknown result,
treat the setting as unconfirmed until an update to it is applied.
Without the hook, call the API directly:
PUT /connections/by-id/{id}/location-sharing with
{ "share": true, "username": "<your profile in the connection>" }.
username is optional unless you own both profiles in the connection.
