@edge-base/web 0.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 +352 -0
- package/dist/analytics.d.ts +60 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +146 -0
- package/dist/analytics.js.map +1 -0
- package/dist/auth-refresh.d.ts +5 -0
- package/dist/auth-refresh.d.ts.map +1 -0
- package/dist/auth-refresh.js +26 -0
- package/dist/auth-refresh.js.map +1 -0
- package/dist/auth.d.ts +314 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +518 -0
- package/dist/auth.js.map +1 -0
- package/dist/browser-storage.d.ts +7 -0
- package/dist/browser-storage.d.ts.map +1 -0
- package/dist/browser-storage.js +43 -0
- package/dist/browser-storage.js.map +1 -0
- package/dist/client.d.ts +145 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +310 -0
- package/dist/client.js.map +1 -0
- package/dist/database-live.d.ts +65 -0
- package/dist/database-live.d.ts.map +1 -0
- package/dist/database-live.js +486 -0
- package/dist/database-live.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/match-filter.d.ts +30 -0
- package/dist/match-filter.d.ts.map +1 -0
- package/dist/match-filter.js +86 -0
- package/dist/match-filter.js.map +1 -0
- package/dist/room-realtime-media.d.ts +96 -0
- package/dist/room-realtime-media.d.ts.map +1 -0
- package/dist/room-realtime-media.js +418 -0
- package/dist/room-realtime-media.js.map +1 -0
- package/dist/room.d.ts +450 -0
- package/dist/room.d.ts.map +1 -0
- package/dist/room.js +1506 -0
- package/dist/room.js.map +1 -0
- package/dist/token-manager.d.ts +73 -0
- package/dist/token-manager.d.ts.map +1 -0
- package/dist/token-manager.js +378 -0
- package/dist/token-manager.js.map +1 -0
- package/dist/turnstile.d.ts +56 -0
- package/dist/turnstile.d.ts.map +1 -0
- package/dist/turnstile.js +191 -0
- package/dist/turnstile.js.map +1 -0
- package/llms.txt +549 -0
- package/package.json +50 -0
package/llms.txt
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
# EdgeBase JS Web SDK
|
|
2
|
+
|
|
3
|
+
Use this file as a quick-reference contract for AI coding assistants working with `@edge-base/web`.
|
|
4
|
+
|
|
5
|
+
## Package Boundary
|
|
6
|
+
|
|
7
|
+
Use `@edge-base/web` for browser and untrusted client environments.
|
|
8
|
+
|
|
9
|
+
Do not use this package for privileged server-side work that needs admin access, raw SQL, or trusted secrets. Use `@edge-base/admin` for that. Use `@edge-base/ssr` when you specifically need SSR cookie helpers.
|
|
10
|
+
|
|
11
|
+
## Source Of Truth
|
|
12
|
+
|
|
13
|
+
- Package README: https://github.com/edge-base/edgebase/blob/main/packages/sdk/js/packages/web/README.md
|
|
14
|
+
- Quickstart: https://edgebase.fun/docs/getting-started/quickstart
|
|
15
|
+
- Client SDK docs: https://edgebase.fun/docs/database/client-sdk
|
|
16
|
+
- Database subscriptions: https://edgebase.fun/docs/database/subscriptions
|
|
17
|
+
- Authentication: https://edgebase.fun/docs/authentication
|
|
18
|
+
- Room client SDK: https://edgebase.fun/docs/room/client-sdk
|
|
19
|
+
- Functions client SDK: https://edgebase.fun/docs/functions/client-sdk
|
|
20
|
+
|
|
21
|
+
If code examples, docs, and assumptions disagree, prefer the current package API and official docs over guessed patterns.
|
|
22
|
+
|
|
23
|
+
Async methods below are shown with their real `Promise<...>` return types. In example code, `await` them unless the method is explicitly synchronous.
|
|
24
|
+
|
|
25
|
+
## Recommended Project Layout
|
|
26
|
+
|
|
27
|
+
If adding EdgeBase to an existing frontend project, a good default is:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
your-frontend-project/
|
|
31
|
+
package.json
|
|
32
|
+
src/
|
|
33
|
+
edgebase/
|
|
34
|
+
edgebase.config.ts
|
|
35
|
+
functions/
|
|
36
|
+
package.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Typical setup:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd your-frontend-project
|
|
43
|
+
npm create edge-base@latest edgebase
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This is a recommendation, not a requirement. Separate repos or a different subdirectory name are also valid.
|
|
47
|
+
|
|
48
|
+
## Canonical Examples
|
|
49
|
+
|
|
50
|
+
### Create a client
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { createClient } from '@edge-base/web';
|
|
54
|
+
|
|
55
|
+
const client = createClient('https://your-project.edgebase.fun');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Sign in and react to auth changes
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
await client.auth.signIn({
|
|
62
|
+
email: 'june@example.com',
|
|
63
|
+
password: 'pass1234',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const user = client.auth.currentUser;
|
|
67
|
+
|
|
68
|
+
const unsubscribeAuth = client.auth.onAuthStateChange((nextUser) => {
|
|
69
|
+
console.log('auth changed:', nextUser);
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Query data from a single-instance block
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type Post = {
|
|
77
|
+
id: string;
|
|
78
|
+
title: string;
|
|
79
|
+
published: boolean;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const posts = await client
|
|
83
|
+
.db('app')
|
|
84
|
+
.table<Post>('posts')
|
|
85
|
+
.where('published', '==', true)
|
|
86
|
+
.orderBy('title', 'asc')
|
|
87
|
+
.limit(20)
|
|
88
|
+
.getList();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Query data from an instance database
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const docs = await client
|
|
95
|
+
.db('workspace', 'ws-1')
|
|
96
|
+
.table('docs')
|
|
97
|
+
.getList();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Subscribe to live updates
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const unsubscribe = client
|
|
104
|
+
.db('app')
|
|
105
|
+
.table('posts')
|
|
106
|
+
.onSnapshot((change) => {
|
|
107
|
+
console.log(change.changeType, change.data);
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Upload a file and create a signed URL
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const bucket = client.storage.bucket('avatars');
|
|
115
|
+
|
|
116
|
+
await bucket.upload('me.jpg', file);
|
|
117
|
+
|
|
118
|
+
const signedUrl = await bucket.createSignedUrl('me.jpg', {
|
|
119
|
+
expiresIn: '1h',
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Call a function
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const result = await client.functions.post('contact/send', {
|
|
127
|
+
email: 'june@example.com',
|
|
128
|
+
message: 'Hello from the browser',
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Join a room
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const room = client.room('game', 'lobby-1');
|
|
136
|
+
|
|
137
|
+
await room.join();
|
|
138
|
+
|
|
139
|
+
room.leave();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Update special fields
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { deleteField, increment } from '@edge-base/web';
|
|
146
|
+
|
|
147
|
+
await client
|
|
148
|
+
.db('app')
|
|
149
|
+
.table('posts')
|
|
150
|
+
.update('post-1', {
|
|
151
|
+
views: increment(1),
|
|
152
|
+
temporaryField: deleteField(),
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Common Mistakes
|
|
157
|
+
|
|
158
|
+
- `client.auth.currentUser` is a property, not a method
|
|
159
|
+
- `client.auth.onAuthStateChange()` callback receives `(user)`, not `(event, user)`
|
|
160
|
+
- `client.db(namespace, id?)` uses a positional instance id, not a named object
|
|
161
|
+
- database block names like `app`, `shared`, and `workspace` are examples, not reserved keywords
|
|
162
|
+
- `table.get()` returns a list result, not a single document
|
|
163
|
+
- `table.getOne(id)` or `table.doc(id).get()` returns a single document
|
|
164
|
+
- write operations require an authenticated user
|
|
165
|
+
- `requestPasswordReset()` takes the email as the first positional argument
|
|
166
|
+
- `changePassword()` expects `currentPassword`, not `oldPassword`
|
|
167
|
+
- `createSignedUrl()` expects `expiresIn` as a string like `'1h'`, not a number
|
|
168
|
+
- batch updates and deletes are chained from filters, for example `table.where(...).updateMany(...)`
|
|
169
|
+
|
|
170
|
+
## Quick Reference
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
// Initialize
|
|
174
|
+
import { createClient } from '@edge-base/web'
|
|
175
|
+
const client = createClient('https://my-project.edgebase.fun')
|
|
176
|
+
|
|
177
|
+
// Auth — currentUser is a PROPERTY, not a method
|
|
178
|
+
const user = client.auth.currentUser // TokenUser | null
|
|
179
|
+
|
|
180
|
+
// Auth state — callback receives (user), NOT (event, user)
|
|
181
|
+
const unsub = client.auth.onAuthStateChange((user) => { /* user or null */ })
|
|
182
|
+
|
|
183
|
+
// Sign up with profile data
|
|
184
|
+
await client.auth.signUp({ email: 'a@b.com', password: 'pass123', data: { displayName: 'June' } })
|
|
185
|
+
|
|
186
|
+
// Password reset — positional args, NOT object
|
|
187
|
+
await client.auth.requestPasswordReset('user@test.com')
|
|
188
|
+
await client.auth.resetPassword(token, 'newPass123')
|
|
189
|
+
|
|
190
|
+
// Change password — field is currentPassword, NOT oldPassword
|
|
191
|
+
await client.auth.changePassword({ currentPassword: 'old', newPassword: 'new' })
|
|
192
|
+
|
|
193
|
+
// DB access — instanceId is positional, NOT named
|
|
194
|
+
const posts = client.db('shared').table('posts')
|
|
195
|
+
const docs = client.db('workspace', 'ws-1').table('docs')
|
|
196
|
+
|
|
197
|
+
// get() returns ListResult, NOT a single record
|
|
198
|
+
const list = await posts.get() // { items, total, page, perPage, hasMore, cursor }
|
|
199
|
+
const one = await posts.getOne('id-1') // single record
|
|
200
|
+
const one2 = await posts.doc('id-1').get() // same thing
|
|
201
|
+
|
|
202
|
+
// Batch ops — chain where() first, NOT pass filter as arg
|
|
203
|
+
await posts.where('status', '==', 'old').updateMany({ status: 'archived' })
|
|
204
|
+
await posts.where('status', '==', 'old').deleteMany()
|
|
205
|
+
|
|
206
|
+
// Signed URLs — expiresIn is a STRING like '1h', NOT a number
|
|
207
|
+
const url = await bucket.createSignedUrl('file.pdf', { expiresIn: '1h' })
|
|
208
|
+
|
|
209
|
+
// Special field ops
|
|
210
|
+
import { increment, deleteField } from '@edge-base/web'
|
|
211
|
+
await posts.update(id, { views: increment(1), temp: deleteField() })
|
|
212
|
+
|
|
213
|
+
// Write operations require authenticated user
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### createClient
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
import { createClient } from '@edge-base/web'
|
|
220
|
+
const client = createClient(url, options?: { schema?, databaseLive?: { autoReconnect?, maxReconnectAttempts?, reconnectBaseDelay? } })
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Client Lifecycle
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
client.destroy() → void (cleanup all resources, subscriptions, timers)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Auth
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
client.auth.currentUser → TokenUser | null (PROPERTY, not method)
|
|
233
|
+
client.auth.signUp({email, password, data?, locale?, captchaToken?}) → Promise<AuthResult>
|
|
234
|
+
client.auth.signIn({email, password, captchaToken?}) → Promise<AuthResult | {mfaRequired, mfaTicket, factors}>
|
|
235
|
+
client.auth.signInAnonymously({captchaToken?}?) → Promise<AuthResult>
|
|
236
|
+
client.auth.signOut() → Promise<void>
|
|
237
|
+
client.auth.signInWithOAuth(provider, {redirectUrl?, captchaToken?}) → {url}
|
|
238
|
+
client.auth.handleOAuthCallback(url?) → Promise<AuthResult | null>
|
|
239
|
+
client.auth.signInWithMagicLink({email, captchaToken?, redirectUrl?, state?}) → Promise<void>
|
|
240
|
+
client.auth.verifyMagicLink(token) → Promise<AuthResult>
|
|
241
|
+
client.auth.signInWithEmailOtp({email}) → Promise<void>
|
|
242
|
+
client.auth.verifyEmailOtp({email, code}) → Promise<AuthResult>
|
|
243
|
+
client.auth.signInWithPhone({phone, captchaToken?}) → Promise<void>
|
|
244
|
+
client.auth.verifyPhone({phone, code}) → Promise<AuthResult>
|
|
245
|
+
client.auth.requestPasswordReset(email, {captchaToken?, redirectUrl?, state?}?) → Promise<void>
|
|
246
|
+
client.auth.resetPassword(token, newPassword) → Promise<void>
|
|
247
|
+
client.auth.changePassword({currentPassword, newPassword}) → Promise<AuthResult>
|
|
248
|
+
client.auth.changeEmail({newEmail, password, redirectUrl?, state?}) → Promise<void>
|
|
249
|
+
client.auth.verifyEmailChange(token) → Promise<void>
|
|
250
|
+
client.auth.updateProfile({displayName?, avatarUrl?, emailVisibility?, locale?}) → Promise<TokenUser>
|
|
251
|
+
client.auth.updateLocale(locale) → Promise<TokenUser>
|
|
252
|
+
client.auth.refreshSession() → Promise<AuthResult>
|
|
253
|
+
client.auth.listSessions() → Promise<Session[]>
|
|
254
|
+
client.auth.revokeSession(sessionId) → Promise<void>
|
|
255
|
+
client.auth.onAuthStateChange(cb: (user: TokenUser | null) => void) → unsubscribe()
|
|
256
|
+
client.auth.requestEmailVerification({redirectUrl?, state?}?) → Promise<void>
|
|
257
|
+
client.auth.verifyEmail(token) → Promise<void>
|
|
258
|
+
client.auth.listIdentities() → Promise<{identities, methods}>
|
|
259
|
+
client.auth.unlinkIdentity(identityId) → Promise<{identities, methods}>
|
|
260
|
+
client.auth.linkWithEmail({email, password}) → Promise<AuthResult>
|
|
261
|
+
client.auth.linkWithPhone({phone}) → Promise<void>
|
|
262
|
+
client.auth.verifyLinkPhone({phone, code}) → Promise<void>
|
|
263
|
+
client.auth.linkWithOAuth(provider, {redirectUrl?, state?}?) → Promise<{redirectUrl}>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### MFA
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
client.auth.mfa.enrollTotp() → Promise<{factorId, secret, qrCodeUri, recoveryCodes}>
|
|
270
|
+
client.auth.mfa.verifyTotpEnrollment(factorId, code) → Promise<{ok: true}>
|
|
271
|
+
client.auth.mfa.verifyTotp(mfaTicket, code) → Promise<AuthResult>
|
|
272
|
+
client.auth.mfa.useRecoveryCode(mfaTicket, code) → Promise<AuthResult>
|
|
273
|
+
client.auth.mfa.disableTotp({password?, code?}?) → Promise<{ok: true}>
|
|
274
|
+
client.auth.mfa.listFactors() → Promise<{factors}>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### Passkeys
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
client.auth.passkeysRegisterOptions() → Promise<unknown>
|
|
281
|
+
client.auth.passkeysRegister(credential) → Promise<unknown>
|
|
282
|
+
client.auth.passkeysAuthOptions({email?}?) → Promise<unknown>
|
|
283
|
+
client.auth.passkeysAuthenticate(assertion) → Promise<AuthResult>
|
|
284
|
+
client.auth.passkeysList() → Promise<unknown>
|
|
285
|
+
client.auth.passkeysDelete(credentialId) → Promise<unknown>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Database
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
client.db(namespace: 'shared' | 'workspace' | 'user' | string, instanceId?: string)
|
|
292
|
+
.table(name) → TableRef
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Read
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
table.getList() → Promise<{items, total, page, perPage, hasMore, cursor}>
|
|
299
|
+
table.get() → Promise<{items, total, page, perPage, hasMore, cursor}> (NOT get-by-id)
|
|
300
|
+
table.getOne(id) → Promise<record>
|
|
301
|
+
table.doc(id).get() → Promise<record>
|
|
302
|
+
table.getFirst() → Promise<record | null>
|
|
303
|
+
table.count() → Promise<number>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Query (immutable chaining)
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
table.where(field, op, value) → TableRef ops: == != < <= > >= in not-in contains array-contains
|
|
310
|
+
table.or(q => q.where(...).where(...)) → TableRef OR conditions
|
|
311
|
+
table.orderBy(field, 'asc'|'desc') → TableRef
|
|
312
|
+
table.limit(n) → TableRef
|
|
313
|
+
table.offset(n) → TableRef
|
|
314
|
+
table.page(n) → TableRef 1-based
|
|
315
|
+
table.search(query) → TableRef
|
|
316
|
+
table.after(cursor) → TableRef
|
|
317
|
+
table.before(cursor) → TableRef
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Write (require auth)
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
table.insert(data) → Promise<record>
|
|
324
|
+
table.insertMany(items[]) → Promise<record[]> auto-chunks at 500
|
|
325
|
+
table.update(id, data) → Promise<record> supports increment(), deleteField()
|
|
326
|
+
table.delete(id) → Promise<void>
|
|
327
|
+
table.upsert(data, {conflictTarget?}?) → Promise<record & {action: 'inserted'|'updated'}>
|
|
328
|
+
table.upsertMany(items[], {conflictTarget?}?) → Promise<record[]>
|
|
329
|
+
table.where(...).updateMany(data) → Promise<{totalProcessed, totalSucceeded, errors}>
|
|
330
|
+
table.where(...).deleteMany() → Promise<{totalProcessed, totalSucceeded, errors}>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### Special fields
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
import { increment, deleteField } from '@edge-base/web'
|
|
337
|
+
table.update(id, { views: increment(1), old: deleteField() })
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### Doc ref
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
table.doc(id).get() → Promise<record>
|
|
344
|
+
table.doc(id).update(data) → Promise<record>
|
|
345
|
+
table.doc(id).delete() → Promise<void>
|
|
346
|
+
table.doc(id).onSnapshot(cb: (data, change) => void) → unsubscribe()
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Database Live
|
|
350
|
+
|
|
351
|
+
```
|
|
352
|
+
table.onSnapshot(cb: (snapshot) => void) → unsubscribe()
|
|
353
|
+
table.where(...).onSnapshot(cb) → unsubscribe()
|
|
354
|
+
table.doc(id).onSnapshot(cb: (data, change) => void) → unsubscribe()
|
|
355
|
+
|
|
356
|
+
snapshot = { items: T[], changes: { added: T[], modified: T[], removed: T[] } }
|
|
357
|
+
change = { changeType: 'added'|'modified'|'removed', data, docId }
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Storage
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
client.storage.bucket(name) → StorageBucket
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Operations
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
bucket.upload(key, File|Blob|ArrayBuffer|Uint8Array, {contentType?, customMetadata?, onProgress?, signal?}?) → UploadTask<FileInfo>
|
|
370
|
+
bucket.uploadString(key, value, format?: 'raw'|'base64'|'base64url'|'data_url', opts?) → UploadTask<FileInfo>
|
|
371
|
+
bucket.download(key, {as?: 'blob'|'arraybuffer'|'stream'|'text'}?) → Promise<Blob|...>
|
|
372
|
+
bucket.getUrl(key) → string (sync)
|
|
373
|
+
bucket.createSignedUrl(key, {expiresIn?: '1h'|'30m'|'7d'}) → Promise<string> expiresIn is STRING not number
|
|
374
|
+
bucket.createSignedUrls(keys[], {expiresIn?}) → Promise<Array<{key, url, expiresAt}>>
|
|
375
|
+
bucket.createSignedUploadUrl(key, {expiresIn?, maxFileSize?}) → Promise<{url, expiresAt, maxFileSize, uploadedBy}>
|
|
376
|
+
bucket.getMetadata(key) → Promise<FileInfo>
|
|
377
|
+
bucket.updateMetadata(key, {customMetadata?, contentType?}) → Promise<FileInfo>
|
|
378
|
+
bucket.exists(key) → Promise<boolean>
|
|
379
|
+
bucket.list({prefix?, cursor?, limit?}?) → Promise<{files: FileInfo[], cursor, truncated}>
|
|
380
|
+
bucket.delete(key) → Promise<void>
|
|
381
|
+
bucket.deleteMany(keys[]) → Promise<{deleted, failed}>
|
|
382
|
+
bucket.resumeUpload(key, uploadId, data, opts?) → UploadTask<FileInfo>
|
|
383
|
+
bucket.getUploadParts(key, uploadId) → Promise<{uploadId, key, parts: [{partNumber, etag}]}>
|
|
384
|
+
|
|
385
|
+
upload() returns UploadTask (Promise + .cancel() method)
|
|
386
|
+
on resumable upload failure: catch ResumableUploadError {key, uploadId, completedParts, failedPartNumber}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### Convenience (without bucket ref)
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
client.storage.upload(bucketName, key, data, opts?) → UploadTask<FileInfo>
|
|
393
|
+
client.storage.delete(bucketName, key) → Promise<void>
|
|
394
|
+
client.storage.getUrl(bucketName, key) → string
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Room
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
const room = client.room(namespace, roomId, {autoReconnect?, maxReconnectAttempts?, reconnectBaseDelay?, sendTimeout?}?)
|
|
401
|
+
room.join() → Promise<void>
|
|
402
|
+
room.leave() → void
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### Members
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
room.members.list() → RoomMember[]
|
|
409
|
+
room.members.onSync(cb) → Subscription (.unsubscribe())
|
|
410
|
+
room.members.onJoin(cb) → Subscription
|
|
411
|
+
room.members.onLeave(cb: (member, reason: 'leave'|'timeout'|'kicked') => void) → Subscription
|
|
412
|
+
room.members.setState(state) → Promise<void>
|
|
413
|
+
room.members.clearState() → Promise<void>
|
|
414
|
+
room.members.onStateChange(cb) → Subscription
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### State
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
room.state.getShared() → Record<string, unknown>
|
|
421
|
+
room.state.getMine() → Record<string, unknown>
|
|
422
|
+
room.state.onSharedChange(cb) → Subscription
|
|
423
|
+
room.state.onMineChange(cb) → Subscription
|
|
424
|
+
room.state.send(actionType, payload?) → Promise<response>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
#### Signals
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
room.signals.send(event, payload?, {includeSelf?}?) → Promise<void>
|
|
431
|
+
room.signals.sendTo(memberId, event, payload?) → Promise<void>
|
|
432
|
+
room.signals.on(event, cb: (payload, meta) => void) → Subscription
|
|
433
|
+
room.signals.onAny(cb: (event, payload, meta) => void) → Subscription
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### Media
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
room.media.audio.enable() / disable() / setMuted(bool) → Promise<void>
|
|
440
|
+
room.media.video.enable() / disable() / setMuted(bool) → Promise<void>
|
|
441
|
+
room.media.screen.start() / stop() → Promise<void>
|
|
442
|
+
room.media.list() → RoomMediaMember[]
|
|
443
|
+
room.media.devices.switch({audioInputId?, videoInputId?}) → Promise<void>
|
|
444
|
+
room.media.onTrack(cb) → Subscription
|
|
445
|
+
room.media.onTrackRemoved(cb) → Subscription
|
|
446
|
+
room.media.onStateChange(cb) → Subscription
|
|
447
|
+
room.media.onDeviceChange(cb) → Subscription
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### Admin (in-room moderation)
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
room.admin.kick(memberId) → Promise<void>
|
|
454
|
+
room.admin.mute(memberId) → Promise<void>
|
|
455
|
+
room.admin.block(memberId) → Promise<void>
|
|
456
|
+
room.admin.setRole(memberId, role) → Promise<void>
|
|
457
|
+
room.admin.disableVideo(memberId) → Promise<void>
|
|
458
|
+
room.admin.stopScreenShare(memberId) → Promise<void>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### Meta
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
room.meta.get() → Promise<Record<string, unknown>>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
#### Realtime (WebRTC) — HTTP Wrappers
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
room.media.realtime.createSession(payload?) → Promise<{sessionId, sessionDescription?}>
|
|
471
|
+
room.media.realtime.getIceServers({ttl?}?) → Promise<{iceServers}>
|
|
472
|
+
room.media.realtime.addTracks({sessionId, tracks, sessionDescription?}) → Promise<{sessionDescription?, tracks?}>
|
|
473
|
+
room.media.realtime.renegotiate({sessionId, sessionDescription}) → Promise<{sessionDescription?, tracks?}>
|
|
474
|
+
room.media.realtime.closeTracks({sessionId, tracks: [{mid}]}) → Promise<{sessionDescription?, tracks?}>
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
For higher-level WebRTC transport, use the built-in room transport or the `RoomRealtimeMediaTransport` export from `@edge-base/web`:
|
|
478
|
+
```
|
|
479
|
+
const transport = room.media.realtime.transport({ autoSubscribe: true });
|
|
480
|
+
await transport.connect();
|
|
481
|
+
await transport.enableAudio();
|
|
482
|
+
await transport.enableVideo();
|
|
483
|
+
transport.onRemoteTrack(event => { ... });
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### Session
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
room.session.onConnectionStateChange(cb: (state: 'idle'|'connecting'|'connected'|'reconnecting'|'disconnected'|'auth_lost'|'kicked') => void) → Subscription
|
|
490
|
+
room.session.onKicked(cb) → Subscription
|
|
491
|
+
room.session.onError(cb) → Subscription
|
|
492
|
+
room.session.onReconnect(cb) → Subscription
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Functions
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
client.functions.call(name, {method?, body?, query?}?) → Promise<T>
|
|
499
|
+
client.functions.get(path, query?) → Promise<T>
|
|
500
|
+
client.functions.post(path, body?) → Promise<T>
|
|
501
|
+
client.functions.put(path, body?) → Promise<T>
|
|
502
|
+
client.functions.patch(path, body?) → Promise<T>
|
|
503
|
+
client.functions.delete(path) → Promise<T>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Analytics
|
|
507
|
+
|
|
508
|
+
```
|
|
509
|
+
client.analytics.track(name, properties?: Record<string, string|number|boolean>) → void (batched)
|
|
510
|
+
client.analytics.flush() → Promise<void>
|
|
511
|
+
client.analytics.destroy() → void (flush + cleanup)
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Push
|
|
515
|
+
|
|
516
|
+
```
|
|
517
|
+
client.push.setTokenProvider(provider: () => Promise<string>) → void
|
|
518
|
+
client.push.register({metadata?}?) → Promise<void>
|
|
519
|
+
client.push.unregister(deviceId?) → Promise<void>
|
|
520
|
+
client.push.subscribeTopic(topic) → Promise<void>
|
|
521
|
+
client.push.unsubscribeTopic(topic) → Promise<void>
|
|
522
|
+
client.push.onMessage(cb: (msg: {title?, body?, data?}) => void)
|
|
523
|
+
client.push.onMessageOpenedApp(cb: (msg) => void) → void (notification tap opened app)
|
|
524
|
+
client.push.getPermissionStatus() → 'granted'|'denied'|'notDetermined'
|
|
525
|
+
client.push.requestPermission() → Promise<'granted'|'denied'>
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### Errors
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
import { EdgeBaseError } from '@edge-base/web'
|
|
532
|
+
EdgeBaseError extends Error {
|
|
533
|
+
code: number // HTTP status code (e.g. 400, 401, 404)
|
|
534
|
+
message: string
|
|
535
|
+
slug?: string // machine-readable error identifier
|
|
536
|
+
data?: Record<string, FieldError> // per-field validation errors
|
|
537
|
+
status: number // getter, alias for code
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Utility
|
|
542
|
+
|
|
543
|
+
```
|
|
544
|
+
client.setLocale(locale: string | undefined)
|
|
545
|
+
client.getLocale() → string | undefined
|
|
546
|
+
client.setContext(ctx) → void
|
|
547
|
+
client.getContext() → ContextValue
|
|
548
|
+
client.getRoomMetadata(namespace, roomId) → Promise<Record<string, unknown>>
|
|
549
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edge-base/web",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "EdgeBase web SDK — browser client with database-live subscriptions, room, and auth persistence",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/edge-base/edgebase.git",
|
|
9
|
+
"directory": "packages/sdk/js/packages/web"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://edgebase.fun",
|
|
12
|
+
"bugs": "https://github.com/edge-base/edgebase/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"edgebase",
|
|
15
|
+
"sdk",
|
|
16
|
+
"web",
|
|
17
|
+
"database-live",
|
|
18
|
+
"baas"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"llms.txt"
|
|
33
|
+
],
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"dev": "tsc --watch",
|
|
40
|
+
"test": "tsc --noEmit && vitest run test/unit/",
|
|
41
|
+
"prepack": "pnpm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@edge-base/core": "workspace:*"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"typescript": "^5.7.0",
|
|
48
|
+
"vitest": "^3.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|