@benmore/bm 0.0.0-stage → 2.7.309
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 +19 -2
- package/index.d.ts +392 -0
- package/index.js +2203 -0
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @benmore/bm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The zero-dependency ESM browser SDK for frontends hosted outside Benmore.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import bm from "@benmore/bm";
|
|
7
|
+
|
|
8
|
+
const contacts = await bm.table("contacts").list();
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Native Benmore apps keep using `import bm from "bm"`; their generated
|
|
12
|
+
`src/bm.d.ts` augments the SDK with schema-specific table, flow, and app types.
|
|
13
|
+
|
|
14
|
+
This package's `index.js` is staged byte-for-byte from the framework's canonical
|
|
15
|
+
`embedded/bm.js`; it has no separate runtime implementation or build step.
|
|
16
|
+
|
|
17
|
+
App-building agents use the [harness guide](https://github.com/Benmore-Studio/benmore/blob/main/docs/agent/harness.md) and
|
|
18
|
+
canonical `sdk` / `existing-frontends` API recipes. The SDK is separate from the
|
|
19
|
+
native hosted CLI and does not install agent skills or deploy an app. Inspect
|
|
20
|
+
live tables and authorization before replacing `contacts` in the example.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
export interface User {
|
|
2
|
+
id: number | string;
|
|
3
|
+
email: string;
|
|
4
|
+
first_name?: string | null;
|
|
5
|
+
last_name?: string | null;
|
|
6
|
+
role: string;
|
|
7
|
+
verified: number;
|
|
8
|
+
[field: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ListOpts {
|
|
12
|
+
limit?: number;
|
|
13
|
+
offset?: number;
|
|
14
|
+
cursor?: string | number;
|
|
15
|
+
q?: string;
|
|
16
|
+
/** Column to order by (snake_case, as stored). */
|
|
17
|
+
sort?: string;
|
|
18
|
+
order?: 'asc' | 'desc';
|
|
19
|
+
where?: Record<string, string | number | boolean>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ApiResult<T = unknown> {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
status: number;
|
|
25
|
+
data: T | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ChangeEvent =
|
|
29
|
+
| { action: "insert" | "update" | "delete"; table: string }
|
|
30
|
+
| { action: "refresh"; table: "" };
|
|
31
|
+
|
|
32
|
+
export interface ApiCalls {
|
|
33
|
+
raw: {
|
|
34
|
+
get<T = unknown>(path: string): Promise<ApiResult<T>>;
|
|
35
|
+
post<T = unknown>(path: string, body?: unknown): Promise<ApiResult<T>>;
|
|
36
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<ApiResult<T>>;
|
|
37
|
+
delete<T = unknown>(path: string): Promise<ApiResult<T>>;
|
|
38
|
+
};
|
|
39
|
+
get<T = unknown>(path: string): Promise<T>;
|
|
40
|
+
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
41
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
42
|
+
delete(path: string): Promise<void>;
|
|
43
|
+
optimistic<T = unknown, Snapshot = unknown>(opts: {
|
|
44
|
+
apply: () => void;
|
|
45
|
+
request: () => Promise<T> | T;
|
|
46
|
+
snapshot?: () => Snapshot;
|
|
47
|
+
revert?: (snapshot: Snapshot) => void;
|
|
48
|
+
}): Promise<T>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AuthCalls {
|
|
52
|
+
me(): Promise<User | null>;
|
|
53
|
+
signOut(): Promise<void>;
|
|
54
|
+
refreshMe(): Promise<User | null>;
|
|
55
|
+
signIn(identifier: string, password: string): Promise<User | null>;
|
|
56
|
+
signUp(fields: { email: string; password: string; [extraField: string]: unknown }): Promise<User | null>;
|
|
57
|
+
/** Passkeys (WebAuthn): Face ID, Touch ID, Windows Hello, a phone. */
|
|
58
|
+
passkey: PasskeyCalls;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface Passkey {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
created_at: string;
|
|
65
|
+
last_used_at: string | null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PasskeyCalls {
|
|
69
|
+
/** False where the browser has no WebAuthn. */
|
|
70
|
+
supported(): boolean;
|
|
71
|
+
/** Signed in: create a passkey on this device and save it. Send the current
|
|
72
|
+
* password or an authenticator code; optional within 10 minutes of signing in. */
|
|
73
|
+
register(name?: string, proof?: { password?: string; mfa_code?: string }): Promise<{ id: number; name: string }>;
|
|
74
|
+
/** Signed out: sign in with any passkey saved for this site. */
|
|
75
|
+
signIn(): Promise<User | null>;
|
|
76
|
+
list(): Promise<Passkey[]>;
|
|
77
|
+
remove(id: number): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface UsersCalls {
|
|
81
|
+
list(opts?: { limit?: number; offset?: number }): Promise<User[]>;
|
|
82
|
+
get(id: number | string): Promise<User>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface CountOpts {
|
|
86
|
+
where?: Record<string, string | number | boolean>;
|
|
87
|
+
q?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface UpdateReceipt {
|
|
91
|
+
status: 'updated';
|
|
92
|
+
}
|
|
93
|
+
export interface VersionMetadata {
|
|
94
|
+
_version: number;
|
|
95
|
+
_valid_from: string;
|
|
96
|
+
_valid_to: string | null;
|
|
97
|
+
_changed_by: number | null;
|
|
98
|
+
_change_type: string;
|
|
99
|
+
}
|
|
100
|
+
export interface VersionHistory {
|
|
101
|
+
id: string;
|
|
102
|
+
versions: VersionMetadata[];
|
|
103
|
+
}
|
|
104
|
+
export interface RevertReceipt {
|
|
105
|
+
status: 'reverted';
|
|
106
|
+
id: string;
|
|
107
|
+
reverted_to_version: string;
|
|
108
|
+
owned_fields_kept: string[] | null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface TableClient<Row = Record<string, unknown>> {
|
|
112
|
+
readonly name: string;
|
|
113
|
+
list(opts?: ListOpts): Promise<Row[]>;
|
|
114
|
+
get(id: number | string): Promise<Row>;
|
|
115
|
+
create(body: Partial<Row>): Promise<Row>;
|
|
116
|
+
update(id: number | string, body: Partial<Row>): Promise<UpdateReceipt>;
|
|
117
|
+
delete(id: number | string): Promise<void>;
|
|
118
|
+
count(opts?: CountOpts): Promise<number>;
|
|
119
|
+
restore(id: number | string): Promise<Row>;
|
|
120
|
+
versions(id: number | string): Promise<VersionHistory>;
|
|
121
|
+
revertTo(id: number | string, version: number): Promise<RevertReceipt>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface RoomClient {
|
|
125
|
+
readonly name: string;
|
|
126
|
+
on(kind: string, fn: (payload: unknown, from: number | string) => void): this;
|
|
127
|
+
onAny(fn: (payload: unknown, from: number | string, kind: string) => void): this;
|
|
128
|
+
off(kind: string, fn: Function): this;
|
|
129
|
+
send(payload: unknown): void;
|
|
130
|
+
leave(): void;
|
|
131
|
+
readonly raw: WebSocket;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface WorkflowClient {
|
|
135
|
+
readonly table: string;
|
|
136
|
+
readonly id: number | string;
|
|
137
|
+
transitionTo(state: string): Promise<{ state: string }>;
|
|
138
|
+
available(): Promise<string[]>;
|
|
139
|
+
current(): Promise<string>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface Job<Result = unknown> {
|
|
143
|
+
job_id: string;
|
|
144
|
+
status_url?: string;
|
|
145
|
+
status(): Promise<JobStatus<Result>>;
|
|
146
|
+
wait(opts?: JobWaitOpts): Promise<Result>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface JobStatus<Result = unknown> {
|
|
150
|
+
status: "pending" | "running" | "completed" | "failed" | string;
|
|
151
|
+
result?: Result;
|
|
152
|
+
error?: string;
|
|
153
|
+
[field: string]: unknown;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface JobWaitOpts {
|
|
157
|
+
intervalMs?: number;
|
|
158
|
+
timeoutMs?: number;
|
|
159
|
+
statusUrl?: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface Notification {
|
|
163
|
+
id: number | string;
|
|
164
|
+
[field: string]: unknown;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface UploadResult {
|
|
168
|
+
path: string;
|
|
169
|
+
url?: string;
|
|
170
|
+
read_url?: string;
|
|
171
|
+
size?: number;
|
|
172
|
+
mime?: string;
|
|
173
|
+
[field: string]: unknown;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface SafeHtml {
|
|
177
|
+
readonly value: string;
|
|
178
|
+
toString(): string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface PresenceMember {
|
|
182
|
+
user_id: number | string;
|
|
183
|
+
joined_at: string;
|
|
184
|
+
last_seen_at: string;
|
|
185
|
+
[field: string]: unknown;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface PresenceHandle {
|
|
189
|
+
readonly slug: string;
|
|
190
|
+
members(): Promise<PresenceMember[]>;
|
|
191
|
+
count(): Promise<number>;
|
|
192
|
+
onChange(fn: () => void): () => void;
|
|
193
|
+
leave(): void;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface CacheClient {
|
|
197
|
+
readonly name: string;
|
|
198
|
+
readonly version: string;
|
|
199
|
+
get(): string | undefined;
|
|
200
|
+
set(value: string): void;
|
|
201
|
+
clear(): void;
|
|
202
|
+
purgeOld(): void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface StorePersistOpts {
|
|
206
|
+
name: string;
|
|
207
|
+
version?: string | number;
|
|
208
|
+
storage?: "session" | "persistent";
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface Store<State extends Record<string, unknown>> {
|
|
212
|
+
get(): State;
|
|
213
|
+
set(patch: Partial<State> | State | ((state: State) => Partial<State> | State | void | null)): State;
|
|
214
|
+
subscribe(listener: (state: State, previous: State) => void): () => void;
|
|
215
|
+
subscribe<Slice>(selector: (state: State) => Slice, listener: (slice: Slice, previous: Slice) => void, equal?: (a: Slice, b: Slice) => boolean): () => void;
|
|
216
|
+
reset(nextState?: State): State;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface QuerySnapshot<T = unknown> {
|
|
220
|
+
data: T | undefined;
|
|
221
|
+
error: unknown;
|
|
222
|
+
updatedAt: number;
|
|
223
|
+
pending: boolean;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface QueryFetchOpts {
|
|
227
|
+
key?: unknown;
|
|
228
|
+
staleTime?: number;
|
|
229
|
+
staleMs?: number;
|
|
230
|
+
force?: boolean;
|
|
231
|
+
live?: boolean;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface QuerySpec {
|
|
235
|
+
table: string;
|
|
236
|
+
select?: string[];
|
|
237
|
+
where?: Record<string, unknown>;
|
|
238
|
+
group_by?: string[];
|
|
239
|
+
aggregates?: Array<{ fn: "count" | "sum" | "avg" | "min" | "max"; col?: string; as?: string }>;
|
|
240
|
+
order_by?: Array<{ col: string; dir?: "asc" | "desc" }>;
|
|
241
|
+
limit?: number;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface QueryMutateOpts<Result = unknown> {
|
|
245
|
+
key?: unknown;
|
|
246
|
+
keys?: unknown[];
|
|
247
|
+
request: () => Promise<Result>;
|
|
248
|
+
apply?: (current: unknown, key: unknown) => unknown;
|
|
249
|
+
rollback?: (snapshot: unknown, error: unknown, key: unknown) => unknown;
|
|
250
|
+
invalidate?: unknown | ((rawKey: unknown, stableKey: string) => boolean);
|
|
251
|
+
refetch?: boolean;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface BroadcastPublisher {
|
|
255
|
+
slug: string;
|
|
256
|
+
sessionId: string;
|
|
257
|
+
pc: RTCPeerConnection;
|
|
258
|
+
stop(): Promise<void>;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface BroadcastSubscription {
|
|
262
|
+
slug: string;
|
|
263
|
+
sessionId: string;
|
|
264
|
+
pc: RTCPeerConnection;
|
|
265
|
+
stream: MediaStream;
|
|
266
|
+
policy: RTCIceTransportPolicy;
|
|
267
|
+
stop(): void;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface IceServer {
|
|
271
|
+
urls: string | string[];
|
|
272
|
+
username?: string;
|
|
273
|
+
credential?: string;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export const api: ApiCalls;
|
|
277
|
+
export const auth: AuthCalls;
|
|
278
|
+
export const users: UsersCalls;
|
|
279
|
+
|
|
280
|
+
export function table<Row = Record<string, unknown>>(name: string): TableClient<Row>;
|
|
281
|
+
export namespace table {
|
|
282
|
+
interface ReadContext { table: string; op: "list" | "get" | "count" }
|
|
283
|
+
interface WriteContext { table: string; op: "create" | "update" | "delete" }
|
|
284
|
+
function before(kind: "read", fn: (opts: unknown, context: ReadContext) => unknown | void): () => void;
|
|
285
|
+
function before(kind: "write", fn: (opts: unknown, context: WriteContext) => unknown | void): () => void;
|
|
286
|
+
function clearHooks(): void;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function live(table: string, callback: (event: ChangeEvent) => void): () => void;
|
|
290
|
+
export namespace live {
|
|
291
|
+
function scoped(table: string, fetchAndRender: () => unknown | Promise<unknown>, opts?: { debounce?: number }): () => void;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function room(name: string): RoomClient;
|
|
295
|
+
export const flows: Record<string, (params?: Record<string, unknown>, body?: unknown) => Promise<unknown | Job>>;
|
|
296
|
+
export function workflow(table: string, id: number | string): WorkflowClient;
|
|
297
|
+
export function aggregate<Result = unknown>(name: string): Promise<Result | null>;
|
|
298
|
+
export const aggregates: {
|
|
299
|
+
get<Result = unknown>(name: string): Promise<Result | null>;
|
|
300
|
+
all(): Promise<Record<string, unknown>>;
|
|
301
|
+
};
|
|
302
|
+
export const jobs: {
|
|
303
|
+
status<Result = unknown>(jobId: string, statusUrl?: string): Promise<JobStatus<Result>>;
|
|
304
|
+
wait<Result = unknown>(jobId: string, opts?: JobWaitOpts): Promise<Result>;
|
|
305
|
+
};
|
|
306
|
+
export const notifications: {
|
|
307
|
+
list(opts?: { limit?: number; offset?: number; unread?: boolean }): Promise<Notification[]>;
|
|
308
|
+
markRead(id: number | string): Promise<void>;
|
|
309
|
+
markAllRead(): Promise<void>;
|
|
310
|
+
delete(id: number | string): Promise<void>;
|
|
311
|
+
onNew(callback: (notification: Notification) => void): () => void;
|
|
312
|
+
};
|
|
313
|
+
export function upload(file: File | Blob, opts?: { filename?: string; kind?: string }): Promise<UploadResult>;
|
|
314
|
+
export const audit: { list(filter?: Record<string, string | number | boolean>): Promise<Record<string, unknown>[]> };
|
|
315
|
+
export const permissions: {
|
|
316
|
+
share(table: string, id: number | string, email: string, permission?: "view" | "edit" | "delete" | "admin", expiresAt?: string): Promise<void>;
|
|
317
|
+
revoke(table: string, id: number | string, email: string): Promise<void>;
|
|
318
|
+
list(table: string, id: number | string): Promise<unknown>;
|
|
319
|
+
};
|
|
320
|
+
/** Time-limited URL for a file. Default lifetime 300s; audio/video default to 4h so playback does not outlive the link (max 6h). */
|
|
321
|
+
export function signedUrl(path: string, opts?: number | { ttl?: number; ttlSeconds?: number; record?: { table: string; id: number | string } }): Promise<string>;
|
|
322
|
+
export function t(key: string, vars?: Record<string, string | number>): string;
|
|
323
|
+
export const broadcast: {
|
|
324
|
+
publish(slug: string, stream: MediaStream): Promise<BroadcastPublisher>;
|
|
325
|
+
subscribe(slug: string, opts?: { waitForPublisher?: number; signal?: AbortSignal }): Promise<BroadcastSubscription>;
|
|
326
|
+
stats(slug: string): Promise<{ live: boolean; viewers: number; started_at?: string }>;
|
|
327
|
+
};
|
|
328
|
+
export const webrtc: { iceServers(): Promise<IceServer[]> };
|
|
329
|
+
export const mfa: {
|
|
330
|
+
enroll(): Promise<{ qr_data_url: string; secret: string; backup_codes: string[] }>;
|
|
331
|
+
verify(code: string): Promise<{ ok: boolean }>;
|
|
332
|
+
disable(password: string): Promise<{ ok: boolean }>;
|
|
333
|
+
};
|
|
334
|
+
export function html(strings: TemplateStringsArray, ...values: unknown[]): SafeHtml;
|
|
335
|
+
export function raw(value: string): SafeHtml;
|
|
336
|
+
export function createStore<State extends Record<string, unknown>>(initialState?: State, opts?: { persist?: StorePersistOpts; cache?: StorePersistOpts }): Store<State>;
|
|
337
|
+
export const query: {
|
|
338
|
+
key(key: unknown): string;
|
|
339
|
+
stableStringify(value: unknown): string;
|
|
340
|
+
get<T = unknown>(key: unknown): T | undefined;
|
|
341
|
+
set<T = unknown>(key: unknown, data: T): T;
|
|
342
|
+
subscribe<T = unknown>(key: unknown, fn: (snapshot: QuerySnapshot<T>) => void): () => void;
|
|
343
|
+
fetch<T = unknown>(key: unknown, fetcher: () => Promise<T> | T, opts?: QueryFetchOpts): Promise<T>;
|
|
344
|
+
refetch<T = unknown>(key: unknown): Promise<T | undefined>;
|
|
345
|
+
invalidate(match: unknown | ((rawKey: unknown, stableKey: string) => boolean), opts?: { refetch?: boolean }): string[];
|
|
346
|
+
tableKey(table: string, spec?: Record<string, unknown>): unknown[];
|
|
347
|
+
read<T = unknown>(spec: QuerySpec, opts?: QueryFetchOpts): Promise<T[]>;
|
|
348
|
+
table<T = unknown>(table: string, opts?: Omit<QuerySpec, "table"> & QueryFetchOpts): Promise<T[]>;
|
|
349
|
+
invalidateTable(table: string, opts?: { refetch?: boolean }): string[];
|
|
350
|
+
mutate<T = unknown>(opts: QueryMutateOpts<T>): Promise<T>;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
declare function markdown(text: string, opts?: { inline?: boolean }): Promise<string>;
|
|
354
|
+
declare function markdownBatch(items: Array<string | { text: string; inline?: boolean }>): Promise<string[]>;
|
|
355
|
+
declare function presence(slug: string): PresenceHandle;
|
|
356
|
+
declare const cache: {
|
|
357
|
+
namespaced(name: string, version: string | number): CacheClient | null;
|
|
358
|
+
persistent(name: string, version: string | number): CacheClient | null;
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
declare const bm: {
|
|
362
|
+
api: typeof api;
|
|
363
|
+
auth: typeof auth;
|
|
364
|
+
users: typeof users;
|
|
365
|
+
table: typeof table;
|
|
366
|
+
live: typeof live;
|
|
367
|
+
room: typeof room;
|
|
368
|
+
flows: typeof flows;
|
|
369
|
+
workflow: typeof workflow;
|
|
370
|
+
aggregate: typeof aggregate;
|
|
371
|
+
aggregates: typeof aggregates;
|
|
372
|
+
jobs: typeof jobs;
|
|
373
|
+
notifications: typeof notifications;
|
|
374
|
+
upload: typeof upload;
|
|
375
|
+
audit: typeof audit;
|
|
376
|
+
permissions: typeof permissions;
|
|
377
|
+
signedUrl: typeof signedUrl;
|
|
378
|
+
t: typeof t;
|
|
379
|
+
mfa: typeof mfa;
|
|
380
|
+
webrtc: typeof webrtc;
|
|
381
|
+
broadcast: typeof broadcast;
|
|
382
|
+
markdown: typeof markdown;
|
|
383
|
+
markdownBatch: typeof markdownBatch;
|
|
384
|
+
presence: typeof presence;
|
|
385
|
+
cache: typeof cache;
|
|
386
|
+
createStore: typeof createStore;
|
|
387
|
+
query: typeof query;
|
|
388
|
+
html: typeof html;
|
|
389
|
+
raw: typeof raw;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
export default bm;
|