@motherbase/client 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -30
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +6 -5
- package/dist/auth.js.map +1 -1
- package/dist/channel.d.ts +79 -15
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +153 -48
- package/dist/channel.js.map +1 -1
- package/dist/functions.d.ts +11 -0
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +5 -2
- package/dist/functions.js.map +1 -1
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +1 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/postgrest.d.ts.map +1 -1
- package/dist/postgrest.js +2 -1
- package/dist/postgrest.js.map +1 -1
- package/dist/realtime.d.ts +23 -0
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +117 -5
- package/dist/realtime.js.map +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +10 -5
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ import { createClient, localStorageStorage } from '@motherbase/client';
|
|
|
25
25
|
|
|
26
26
|
const client = createClient(
|
|
27
27
|
'http://localhost:5001',
|
|
28
|
-
'your-anon-key',
|
|
29
|
-
{ storage: localStorageStorage() }
|
|
28
|
+
'your-anon-key', // optional; sent as an `apikey` header
|
|
29
|
+
{ storage: localStorageStorage() } // omit for in-memory (SSR-safe) sessions
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
await client.hydrate(); // restore a persisted session (optional)
|
|
@@ -51,14 +51,19 @@ const { data: uploaded } = await client.storage.from('avatars').upload('me.png',
|
|
|
51
51
|
visibility: 'public',
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
// Realtime
|
|
55
|
-
const
|
|
56
|
-
.channel('room-
|
|
57
|
-
.on('postgres_changes', { event: '*', schema: 'public', table: '
|
|
58
|
-
console.log(
|
|
54
|
+
// Realtime — postgres_changes, broadcast, presence over one channel (Supabase-shaped)
|
|
55
|
+
const room = client
|
|
56
|
+
.channel('room-1', { config: { broadcast: { self: true }, presence: { key: userId } } })
|
|
57
|
+
.on('postgres_changes', { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' }, p => {
|
|
58
|
+
console.log(p.eventType, p.new, p.old);
|
|
59
59
|
})
|
|
60
|
+
.on('broadcast', { event: 'cursor' }, ({ payload }) => console.log(payload))
|
|
61
|
+
.on('presence', { event: 'sync' }, () => console.log(room.presenceState()))
|
|
60
62
|
.subscribe();
|
|
61
63
|
|
|
64
|
+
await room.send({ type: 'broadcast', event: 'cursor', payload: { x: 1, y: 2 } });
|
|
65
|
+
await room.track({ online_at: Date.now() });
|
|
66
|
+
|
|
62
67
|
// Edge functions
|
|
63
68
|
const { data: result } = await client.functions.invoke('hello', { body: { name: 'Ada' } });
|
|
64
69
|
```
|
|
@@ -96,7 +101,13 @@ client.storage.from(bucket).createSignedUrl(path, expiresIn)
|
|
|
96
101
|
client.storage.from(bucket).getPublicUrl(path) // sync
|
|
97
102
|
|
|
98
103
|
// Realtime
|
|
99
|
-
client.channel(name
|
|
104
|
+
client.channel(name, { config: { broadcast: { self, ack }, presence: { key } } })
|
|
105
|
+
.on('postgres_changes', { event, schema, table, filter }, cb)
|
|
106
|
+
.on('broadcast', { event }, cb)
|
|
107
|
+
.on('presence', { event: 'sync' | 'join' | 'leave' }, cb)
|
|
108
|
+
.subscribe(status => {}) // SUBSCRIBED | TIMED_OUT | CLOSED | CHANNEL_ERROR
|
|
109
|
+
channel.send({ type: 'broadcast', event, payload })
|
|
110
|
+
channel.track(state); channel.untrack(); channel.presenceState()
|
|
100
111
|
client.removeChannel(channel)
|
|
101
112
|
|
|
102
113
|
// Edge functions → { data, error }
|
|
@@ -105,11 +116,11 @@ client.functions.invoke(name, { body })
|
|
|
105
116
|
|
|
106
117
|
## Storage adapters
|
|
107
118
|
|
|
108
|
-
| Runtime | Adapter
|
|
109
|
-
| -------- |
|
|
110
|
-
| Browser | `localStorageStorage()` or `cookieStorage()`
|
|
119
|
+
| Runtime | Adapter |
|
|
120
|
+
| -------- | ------------------------------------------------------------- |
|
|
121
|
+
| Browser | `localStorageStorage()` or `cookieStorage()` |
|
|
111
122
|
| SSR/Node | `memoryStorage()` (default) or `serverCookieStorage(adapter)` |
|
|
112
|
-
| Expo/RN | custom `{ get, set }` backed by `AsyncStorage`
|
|
123
|
+
| Expo/RN | custom `{ get, set }` backed by `AsyncStorage` |
|
|
113
124
|
|
|
114
125
|
```ts
|
|
115
126
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
@@ -131,24 +142,25 @@ const client = createClient(API_URL, ANON_KEY, {
|
|
|
131
142
|
|
|
132
143
|
## Compatibility matrix
|
|
133
144
|
|
|
134
|
-
| Area
|
|
135
|
-
|
|
|
136
|
-
| `createClient(url, key, options)`
|
|
137
|
-
| `from().select/insert/update/delete`
|
|
138
|
-
| filters `eq/neq/gt/gte/lt/lte/like/ilike/in/is`
|
|
139
|
-
| `order/limit/range/single/maybeSingle`
|
|
140
|
-
| `upsert()`
|
|
141
|
-
| relational embedding (`select('*, author(*)')`)
|
|
142
|
-
| `.rpc()`
|
|
143
|
-
| `.or/.not/.filter/.textSearch/.contains`
|
|
144
|
-
| `auth.signUp/signInWithPassword/signOut`
|
|
145
|
-
| `auth.getUser/getSession/refreshSession/onAuthStateChange`
|
|
146
|
-
| OAuth / magic link / OTP
|
|
147
|
-
| `storage upload/download/remove/createSignedUrl/getPublicUrl` | Partial
|
|
148
|
-
| `storage.list()`
|
|
149
|
-
| `channel().on('postgres_changes').subscribe()`
|
|
150
|
-
| broadcast
|
|
151
|
-
| `
|
|
145
|
+
| Area | Status | Notes |
|
|
146
|
+
| ------------------------------------------------------------- | ------------- | ------------------------------------------------------- |
|
|
147
|
+
| `createClient(url, key, options)` | Supported | `key` sent as `apikey` header. |
|
|
148
|
+
| `from().select/insert/update/delete` | Supported | Awaitable `{ data, error }`. |
|
|
149
|
+
| filters `eq/neq/gt/gte/lt/lte/like/ilike/in/is` | Supported | Mapped to the `/rest/v1` PostgREST dialect. |
|
|
150
|
+
| `order/limit/range/single/maybeSingle` | Supported | `range` → limit/offset. |
|
|
151
|
+
| `upsert()` | Partial | Emulated as `insert` (no `onConflict`). |
|
|
152
|
+
| relational embedding (`select('*, author(*)')`) | Not supported | Backend blocks joins. |
|
|
153
|
+
| `.rpc()` | Not supported | No exposed Postgres functions — use `functions.invoke`. |
|
|
154
|
+
| `.or/.not/.filter/.textSearch/.contains` | Not supported | Not in the backend dialect. |
|
|
155
|
+
| `auth.signUp/signInWithPassword/signOut` | Supported | |
|
|
156
|
+
| `auth.getUser/getSession/refreshSession/onAuthStateChange` | Supported | Events: `SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`. |
|
|
157
|
+
| OAuth / magic link / OTP | Not supported | Email + password only. |
|
|
158
|
+
| `storage upload/download/remove/createSignedUrl/getPublicUrl` | Partial | `path` == server file id returned by `upload`. |
|
|
159
|
+
| `storage.list()` | Stub | Returns an unsupported error instead of throwing. |
|
|
160
|
+
| `channel().on('postgres_changes').subscribe()` | Supported | INSERT/UPDATE/DELETE/`*`, RLS-filtered, column `filter`. |
|
|
161
|
+
| `channel().on('broadcast')` + `.send()` | Supported | `config.broadcast.self` / `.ack`. |
|
|
162
|
+
| `channel().on('presence')` + `.track/.untrack/.presenceState` | Supported | `sync`/`join`/`leave`, keyed by `config.presence.key`. |
|
|
163
|
+
| `functions.invoke(name, { body })` | Supported | Maps to `/api/edge/:name`. |
|
|
152
164
|
|
|
153
165
|
More examples live in [`docs/sdk.md`](../../docs/sdk.md). Project Studio also
|
|
154
166
|
exposes a project-specific Connect page with the exact API URL, WebSocket URL and
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAEV,kBAAkB,EAElB,kBAAkB,EAClB,OAAO,EACP,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAyBD,MAAM,WAAW,YAAY;IAC3B,WAAW,IAAI,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAc,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAxC,IAAI,EAAE,UAAU,EAAmB,KAAK,EAAE,YAAY;IAE7E,MAAM,CACV,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAAC,kBAAkB,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAexE,kBAAkB,CACtB,WAAW,EAAE,6BAA6B,GACzC,OAAO,CAAC,kBAAkB,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAexE,OAAO,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IAUtE,0EAA0E;IACpE,OAAO,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IASnE,0DAA0D;IACpD,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAI5E;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAoBnG,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,GAAG;QAAE,IAAI,EAAE;YAAE,YAAY,EAAE,YAAY,CAAA;SAAE,CAAA;KAAE;IAOzF;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;YAKpB,OAAO;CAKtB"}
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { toError } from './http.js';
|
|
2
|
+
import { HTTP_ROUTES } from '@motherbase/contracts';
|
|
2
3
|
/** Build a clean Session from the Better Auth auth payload. */
|
|
3
4
|
function toSession(payload) {
|
|
4
5
|
return { accessToken: payload.token, user: payload.user };
|
|
@@ -20,7 +21,7 @@ export class AuthClient {
|
|
|
20
21
|
}
|
|
21
22
|
async signUp(credentials) {
|
|
22
23
|
try {
|
|
23
|
-
const payload = await this.http.request(
|
|
24
|
+
const payload = await this.http.request(HTTP_ROUTES.authSignUp, {
|
|
24
25
|
method: 'POST',
|
|
25
26
|
body: { email: credentials.email, password: credentials.password, name: credentials.username ?? credentials.email },
|
|
26
27
|
anonymous: true,
|
|
@@ -35,7 +36,7 @@ export class AuthClient {
|
|
|
35
36
|
}
|
|
36
37
|
async signInWithPassword(credentials) {
|
|
37
38
|
try {
|
|
38
|
-
const payload = await this.http.request(
|
|
39
|
+
const payload = await this.http.request(HTTP_ROUTES.authSignIn, {
|
|
39
40
|
method: 'POST',
|
|
40
41
|
body: { email: credentials.email, password: credentials.password },
|
|
41
42
|
anonymous: true,
|
|
@@ -50,7 +51,7 @@ export class AuthClient {
|
|
|
50
51
|
}
|
|
51
52
|
async signOut() {
|
|
52
53
|
try {
|
|
53
|
-
await this.http.request(
|
|
54
|
+
await this.http.request(HTTP_ROUTES.authSignOut, { method: 'POST', raw: true });
|
|
54
55
|
}
|
|
55
56
|
catch {
|
|
56
57
|
// best-effort; clear locally regardless
|
|
@@ -61,7 +62,7 @@ export class AuthClient {
|
|
|
61
62
|
/** Fetch the current user from Better Auth (requires a valid session). */
|
|
62
63
|
async getUser() {
|
|
63
64
|
try {
|
|
64
|
-
const payload = await this.http.request(
|
|
65
|
+
const payload = await this.http.request(HTTP_ROUTES.authSession, { raw: true });
|
|
65
66
|
return { data: { user: payload?.user ?? null }, error: null };
|
|
66
67
|
}
|
|
67
68
|
catch (err) {
|
|
@@ -83,7 +84,7 @@ export class AuthClient {
|
|
|
83
84
|
return { data: { user: null, session: null }, error: { message: 'Auth session missing!' } };
|
|
84
85
|
}
|
|
85
86
|
try {
|
|
86
|
-
const payload = await this.http.request(
|
|
87
|
+
const payload = await this.http.request(HTTP_ROUTES.authSession, { raw: true });
|
|
87
88
|
if (!payload?.user) {
|
|
88
89
|
await this.store.set(null, 'signOut');
|
|
89
90
|
return { data: { user: null, session: null }, error: { message: 'Session expired' } };
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { RealtimeModule } from './realtime.js';
|
|
2
|
+
import type { RealtimeTopicEnvelope } from '@motherbase/contracts';
|
|
2
3
|
export type PostgresChangeEvent = 'INSERT' | 'UPDATE' | 'DELETE' | '*';
|
|
3
4
|
export interface PostgresChangeFilter {
|
|
4
5
|
event: PostgresChangeEvent;
|
|
5
6
|
schema?: string;
|
|
6
7
|
table: string;
|
|
8
|
+
/** PostgREST-style column filter, e.g. `room_id=eq.42`. Applied server-side in sub-project #4. */
|
|
9
|
+
filter?: string;
|
|
7
10
|
}
|
|
8
11
|
export interface PostgresChangePayload<T = Record<string, unknown>> {
|
|
9
12
|
schema: string;
|
|
@@ -13,28 +16,89 @@ export interface PostgresChangePayload<T = Record<string, unknown>> {
|
|
|
13
16
|
old: T | Record<string, never>;
|
|
14
17
|
commit_timestamp: string;
|
|
15
18
|
}
|
|
16
|
-
export
|
|
19
|
+
export interface BroadcastFilter {
|
|
20
|
+
event: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PresenceFilter {
|
|
23
|
+
event: 'sync' | 'join' | 'leave';
|
|
24
|
+
}
|
|
25
|
+
export interface BroadcastMessage {
|
|
26
|
+
type: 'broadcast';
|
|
27
|
+
event: string;
|
|
28
|
+
payload?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export interface BroadcastReceived {
|
|
31
|
+
type: 'broadcast';
|
|
32
|
+
event: string;
|
|
33
|
+
payload: unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface PresenceEntry {
|
|
36
|
+
presence_ref: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
export type PresenceState<T extends Record<string, unknown> = Record<string, unknown>> = Record<string, Array<T & {
|
|
40
|
+
presence_ref: string;
|
|
41
|
+
}>>;
|
|
42
|
+
export interface PresenceJoinPayload {
|
|
43
|
+
key: string;
|
|
44
|
+
newPresences: PresenceEntry[];
|
|
45
|
+
currentPresences: PresenceEntry[];
|
|
46
|
+
}
|
|
47
|
+
export interface PresenceLeavePayload {
|
|
48
|
+
key: string;
|
|
49
|
+
leftPresences: PresenceEntry[];
|
|
50
|
+
currentPresences: PresenceEntry[];
|
|
51
|
+
}
|
|
52
|
+
export type ChannelStatus = 'SUBSCRIBED' | 'TIMED_OUT' | 'CLOSED' | 'CHANNEL_ERROR';
|
|
53
|
+
export interface RealtimeChannelOptions {
|
|
54
|
+
config?: {
|
|
55
|
+
broadcast?: {
|
|
56
|
+
self?: boolean;
|
|
57
|
+
ack?: boolean;
|
|
58
|
+
};
|
|
59
|
+
presence?: {
|
|
60
|
+
key?: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
}
|
|
17
64
|
/**
|
|
18
|
-
* Supabase-compatible realtime channel.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
65
|
+
* Supabase-compatible realtime channel. Multiplexes broadcast, presence, and
|
|
66
|
+
* postgres_changes over a single topic. `postgres_changes` is delivered through
|
|
67
|
+
* the RealtimeModule.watchTable bridge in this release; broadcast/presence are
|
|
68
|
+
* routed by topic via rt:msg envelopes.
|
|
21
69
|
*/
|
|
22
70
|
export declare class RealtimeChannel {
|
|
23
71
|
readonly topic: string;
|
|
24
72
|
private readonly realtime;
|
|
25
|
-
private readonly
|
|
26
|
-
private readonly
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
|
|
73
|
+
private readonly options;
|
|
74
|
+
private readonly pgBindings;
|
|
75
|
+
private readonly broadcastBindings;
|
|
76
|
+
private readonly presenceBindings;
|
|
77
|
+
private status;
|
|
78
|
+
private presence;
|
|
79
|
+
constructor(topic: string, realtime: RealtimeModule, options?: RealtimeChannelOptions);
|
|
80
|
+
on(type: 'broadcast', filter: BroadcastFilter, callback: (payload: BroadcastReceived) => void): this;
|
|
81
|
+
on(type: 'presence', filter: PresenceFilter, callback: (payload: unknown) => void): this;
|
|
30
82
|
on(type: 'postgres_changes', filter: PostgresChangeFilter, callback: (payload: PostgresChangePayload) => void): this;
|
|
83
|
+
subscribe(onStatus?: (status: ChannelStatus, err?: Error) => void, timeoutMs?: number): this;
|
|
84
|
+
unsubscribe(): Promise<'ok'>;
|
|
31
85
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
86
|
+
* Broadcast a message to the topic. Other clients on the topic with a matching
|
|
87
|
+
* `on('broadcast', { event })` binding receive it; the sender receives its own
|
|
88
|
+
* message only when the channel was created with `config.broadcast.self`.
|
|
89
|
+
* With `config.broadcast.ack`, resolves on the server ack.
|
|
34
90
|
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
91
|
+
send(message: BroadcastMessage): Promise<'ok' | 'timed out' | 'error'>;
|
|
92
|
+
/** Announce this client's presence on the topic with the given state. */
|
|
93
|
+
track(state: Record<string, unknown>): Promise<'ok' | 'timed out' | 'error'>;
|
|
94
|
+
/** Remove this client's presence from the topic. */
|
|
95
|
+
untrack(): Promise<'ok' | 'timed out' | 'error'>;
|
|
96
|
+
/** Current presence state, keyed by presence key. */
|
|
97
|
+
presenceState<T extends Record<string, unknown> = Record<string, unknown>>(): PresenceState<T>;
|
|
98
|
+
/** Internal: receive a topic envelope routed by RealtimeModule. */
|
|
99
|
+
_receive(envelope: RealtimeTopicEnvelope): void;
|
|
100
|
+
private applyPresenceState;
|
|
101
|
+
private emitPresence;
|
|
102
|
+
private buildConfig;
|
|
39
103
|
}
|
|
40
104
|
//# sourceMappingURL=channel.d.ts.map
|
package/dist/channel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
|
package/dist/channel.js
CHANGED
|
@@ -1,74 +1,179 @@
|
|
|
1
|
-
const WATCH_TO_EVENT = {
|
|
2
|
-
created: 'INSERT',
|
|
3
|
-
updated: 'UPDATE',
|
|
4
|
-
deleted: 'DELETE',
|
|
5
|
-
};
|
|
6
1
|
/**
|
|
7
|
-
* Supabase-compatible realtime channel.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* Supabase-compatible realtime channel. Multiplexes broadcast, presence, and
|
|
3
|
+
* postgres_changes over a single topic. `postgres_changes` is delivered through
|
|
4
|
+
* the RealtimeModule.watchTable bridge in this release; broadcast/presence are
|
|
5
|
+
* routed by topic via rt:msg envelopes.
|
|
10
6
|
*/
|
|
11
7
|
export class RealtimeChannel {
|
|
12
|
-
constructor(topic, realtime) {
|
|
8
|
+
constructor(topic, realtime, options = {}) {
|
|
13
9
|
this.topic = topic;
|
|
14
10
|
this.realtime = realtime;
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
11
|
+
this.options = options;
|
|
12
|
+
this.pgBindings = [];
|
|
13
|
+
this.broadcastBindings = [];
|
|
14
|
+
this.presenceBindings = [];
|
|
15
|
+
this.status = 'CLOSED';
|
|
16
|
+
this.presence = {};
|
|
18
17
|
}
|
|
19
|
-
/** Register a `postgres_changes` listener. Chainable, like supabase-js. */
|
|
20
18
|
on(type, filter, callback) {
|
|
21
|
-
if (type
|
|
22
|
-
|
|
19
|
+
if (type === 'broadcast') {
|
|
20
|
+
this.broadcastBindings.push({
|
|
21
|
+
event: filter.event,
|
|
22
|
+
callback: callback,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else if (type === 'presence') {
|
|
26
|
+
this.presenceBindings.push({
|
|
27
|
+
event: filter.event,
|
|
28
|
+
callback: callback,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else if (type === 'postgres_changes') {
|
|
32
|
+
this.pgBindings.push({
|
|
33
|
+
filter: filter,
|
|
34
|
+
callback: callback,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error(`Unsupported channel event type "${type}". Use broadcast | presence | postgres_changes.`);
|
|
23
39
|
}
|
|
24
|
-
this.bindings.push({ filter, callback });
|
|
25
40
|
return this;
|
|
26
41
|
}
|
|
27
|
-
|
|
28
|
-
* Connect (if needed) and start delivering events. Optionally reports status.
|
|
29
|
-
* Returns the channel for chaining, matching supabase-js.
|
|
30
|
-
*/
|
|
31
|
-
subscribe(onStatus) {
|
|
42
|
+
subscribe(onStatus, timeoutMs = 10000) {
|
|
32
43
|
void (async () => {
|
|
33
44
|
try {
|
|
34
45
|
await this.realtime.connect({ fallbackPolling: false });
|
|
35
|
-
for (const binding of this.bindings)
|
|
36
|
-
this.attach(binding);
|
|
37
|
-
this.subscribed = true;
|
|
38
|
-
onStatus?.('SUBSCRIBED');
|
|
39
46
|
}
|
|
40
47
|
catch (err) {
|
|
48
|
+
this.status = 'CHANNEL_ERROR';
|
|
41
49
|
onStatus?.('CHANNEL_ERROR', err instanceof Error ? err : new Error(String(err)));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.realtime.registerChannel(this.topic, this);
|
|
53
|
+
const ack = await this.realtime.joinTopic(this.topic, this.buildConfig(), timeoutMs);
|
|
54
|
+
if (ack.status === 'ok') {
|
|
55
|
+
this.status = 'SUBSCRIBED';
|
|
56
|
+
onStatus?.('SUBSCRIBED');
|
|
57
|
+
}
|
|
58
|
+
else if (ack.error === 'timeout') {
|
|
59
|
+
this.status = 'TIMED_OUT';
|
|
60
|
+
onStatus?.('TIMED_OUT', new Error('Realtime join timed out'));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.status = 'CHANNEL_ERROR';
|
|
64
|
+
onStatus?.('CHANNEL_ERROR', new Error(ack.error ?? 'Realtime join failed'));
|
|
42
65
|
}
|
|
43
66
|
})();
|
|
44
67
|
return this;
|
|
45
68
|
}
|
|
46
|
-
/** Tear down all watchers for this channel. */
|
|
47
69
|
async unsubscribe() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.
|
|
70
|
+
this.realtime.leaveTopic(this.topic);
|
|
71
|
+
this.realtime.unregisterChannel(this.topic);
|
|
72
|
+
this.presence = {};
|
|
73
|
+
this.status = 'CLOSED';
|
|
51
74
|
return 'ok';
|
|
52
75
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Broadcast a message to the topic. Other clients on the topic with a matching
|
|
78
|
+
* `on('broadcast', { event })` binding receive it; the sender receives its own
|
|
79
|
+
* message only when the channel was created with `config.broadcast.self`.
|
|
80
|
+
* With `config.broadcast.ack`, resolves on the server ack.
|
|
81
|
+
*/
|
|
82
|
+
send(message) {
|
|
83
|
+
if (this.options.config?.broadcast?.ack) {
|
|
84
|
+
return this.realtime.sendTopicWithAck(this.topic, 'broadcast', message.event, message.payload ?? {});
|
|
85
|
+
}
|
|
86
|
+
this.realtime.sendTopic(this.topic, 'broadcast', message.event, message.payload ?? {});
|
|
87
|
+
return Promise.resolve('ok');
|
|
88
|
+
}
|
|
89
|
+
/** Announce this client's presence on the topic with the given state. */
|
|
90
|
+
track(state) {
|
|
91
|
+
return this.realtime.sendTopicWithAck(this.topic, 'presence', 'track', { state });
|
|
92
|
+
}
|
|
93
|
+
/** Remove this client's presence from the topic. */
|
|
94
|
+
untrack() {
|
|
95
|
+
return this.realtime.sendTopicWithAck(this.topic, 'presence', 'untrack', {});
|
|
96
|
+
}
|
|
97
|
+
/** Current presence state, keyed by presence key. */
|
|
98
|
+
presenceState() {
|
|
99
|
+
return this.presence;
|
|
100
|
+
}
|
|
101
|
+
/** Internal: receive a topic envelope routed by RealtimeModule. */
|
|
102
|
+
_receive(envelope) {
|
|
103
|
+
if (envelope.type === 'broadcast') {
|
|
104
|
+
for (const binding of this.broadcastBindings) {
|
|
105
|
+
if (binding.event === '*' || binding.event === envelope.event) {
|
|
106
|
+
binding.callback({ type: 'broadcast', event: envelope.event, payload: envelope.payload });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else if (envelope.type === 'presence') {
|
|
111
|
+
// The server sends the full presence state; diff it into sync/join/leave.
|
|
112
|
+
if (envelope.event === 'state')
|
|
113
|
+
this.applyPresenceState(envelope.payload);
|
|
114
|
+
}
|
|
115
|
+
else if (envelope.type === 'postgres_changes') {
|
|
116
|
+
const payload = envelope.payload;
|
|
117
|
+
for (const binding of this.pgBindings) {
|
|
118
|
+
const filter = binding.filter;
|
|
119
|
+
if ((filter.schema ?? 'public') !== payload.schema)
|
|
120
|
+
continue;
|
|
121
|
+
if (filter.table !== payload.table)
|
|
122
|
+
continue;
|
|
123
|
+
if (filter.event !== '*' && filter.event !== payload.eventType)
|
|
124
|
+
continue;
|
|
125
|
+
binding.callback(payload);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
applyPresenceState(next) {
|
|
130
|
+
const prev = this.presence;
|
|
131
|
+
const prevRefs = new Set();
|
|
132
|
+
for (const key of Object.keys(prev))
|
|
133
|
+
for (const p of prev[key])
|
|
134
|
+
prevRefs.add(p.presence_ref);
|
|
135
|
+
const nextRefs = new Set();
|
|
136
|
+
for (const key of Object.keys(next))
|
|
137
|
+
for (const p of next[key])
|
|
138
|
+
nextRefs.add(p.presence_ref);
|
|
139
|
+
for (const key of Object.keys(next)) {
|
|
140
|
+
const newPresences = next[key].filter(p => !prevRefs.has(p.presence_ref));
|
|
141
|
+
if (newPresences.length) {
|
|
142
|
+
this.emitPresence('join', { key, newPresences, currentPresences: next[key] });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
for (const key of Object.keys(prev)) {
|
|
146
|
+
const leftPresences = prev[key].filter(p => !nextRefs.has(p.presence_ref));
|
|
147
|
+
if (leftPresences.length) {
|
|
148
|
+
this.emitPresence('leave', { key, leftPresences, currentPresences: next[key] ?? [] });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
this.presence = next;
|
|
152
|
+
this.emitPresence('sync', undefined);
|
|
153
|
+
}
|
|
154
|
+
emitPresence(event, payload) {
|
|
155
|
+
for (const binding of this.presenceBindings) {
|
|
156
|
+
if (binding.event === event)
|
|
157
|
+
binding.callback(payload);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
buildConfig() {
|
|
161
|
+
const config = {};
|
|
162
|
+
if (this.options.config?.broadcast) {
|
|
163
|
+
config.broadcast = { self: Boolean(this.options.config.broadcast.self) };
|
|
164
|
+
}
|
|
165
|
+
if (this.options.config?.presence) {
|
|
166
|
+
config.presence = { key: this.options.config.presence.key };
|
|
167
|
+
}
|
|
168
|
+
if (this.pgBindings.length) {
|
|
169
|
+
config.postgres_changes = this.pgBindings.map(b => ({
|
|
170
|
+
event: b.filter.event,
|
|
171
|
+
schema: b.filter.schema ?? 'public',
|
|
172
|
+
table: b.filter.table,
|
|
173
|
+
filter: b.filter.filter,
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
return config;
|
|
72
177
|
}
|
|
73
178
|
}
|
|
74
179
|
//# sourceMappingURL=channel.js.map
|
package/dist/channel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
|
package/dist/functions.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { HttpClient } from './http.js';
|
|
2
2
|
import type { MotherbaseResponse } from './types.js';
|
|
3
|
+
export type FunctionInvokeAuth = {
|
|
4
|
+
type: 'edge-token';
|
|
5
|
+
token: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'public';
|
|
8
|
+
};
|
|
3
9
|
export interface FunctionInvokeOptions<Body = unknown> {
|
|
4
10
|
/** JSON body passed to the edge function. */
|
|
5
11
|
body?: Body;
|
|
12
|
+
/**
|
|
13
|
+
* Authentication override. By default the current session bearer is used.
|
|
14
|
+
* Public and dedicated Edge-token invocations must be explicitly selected.
|
|
15
|
+
*/
|
|
16
|
+
auth?: FunctionInvokeAuth;
|
|
6
17
|
}
|
|
7
18
|
/** Supabase-compatible edge functions client: `client.functions.invoke(name, { body })`. */
|
|
8
19
|
export declare class FunctionsClient {
|
package/dist/functions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB,MAAM,WAAW,qBAAqB,CAAC,IAAI,GAAG,OAAO;IACnD,6CAA6C;IAC7C,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC3B;AAED,4FAA4F;AAC5F,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEvC,MAAM,CAAC,MAAM,GAAG,OAAO,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,qBAAqB,CAAC,IAAI,CAAM,GACxC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;CAcvC"}
|