@rebasepro/types 0.13.0 → 0.13.1-canary.g394d868
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/dist/call_context.d.ts +61 -4
- package/dist/controllers/client.d.ts +16 -59
- package/dist/controllers/data.d.ts +150 -16
- package/dist/controllers/data_driver.d.ts +44 -0
- package/dist/errors.d.ts +30 -4
- package/dist/index.es.js +2 -1
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +1 -1
- package/dist/types/collections.d.ts +21 -3
- package/dist/types/cron.d.ts +50 -9
- package/dist/types/entity_callbacks.d.ts +2 -1
- package/dist/types/properties.d.ts +22 -4
- package/package.json +2 -2
- package/src/call_context.ts +59 -4
- package/src/controllers/client.ts +16 -80
- package/src/controllers/data.ts +148 -16
- package/src/controllers/data_driver.ts +45 -0
- package/src/errors.ts +43 -4
- package/src/types/admin_block.ts +1 -0
- package/src/types/collections.ts +21 -3
- package/src/types/cron.ts +51 -9
- package/src/types/entity_callbacks.ts +2 -1
- package/src/types/properties.ts +23 -4
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*
|
|
30
30
|
* @group Models
|
|
31
31
|
*/
|
|
32
|
-
export declare const ADMIN_COLLECTION_KEYS: readonly ["Actions", "additionalFields", "alwaysApplyDefaultValues", "components", "defaultEntityAction", "defaultFilter", "defaultSelectedView", "defaultSize", "defaultViewMode", "disableDefaultActions", "enabledViews", "entityActions", "entityViews", "exportable", "filterPresets", "fixedFilter", "form", "formAutoSave", "formView", "group", "hideFromNavigation", "hideIdFromCollection", "hideIdFromForm", "icon", "includeJsonView", "inlineEditing", "kanban", "listProperties", "localChangesBackup", "openEntityMode", "orderProperty", "pagination", "previewProperties", "propertiesOrder", "selectionController", "selectionEnabled", "sideDialogWidth", "sort", "titleProperty"];
|
|
32
|
+
export declare const ADMIN_COLLECTION_KEYS: readonly ["Actions", "additionalFields", "alwaysApplyDefaultValues", "components", "defaultEntityAction", "defaultFilter", "defaultSelectedView", "defaultSize", "defaultViewMode", "disableDefaultActions", "display", "enabledViews", "entityActions", "entityViews", "exportable", "filterPresets", "fixedFilter", "form", "formAutoSave", "formView", "group", "hideFromNavigation", "hideIdFromCollection", "hideIdFromForm", "icon", "includeJsonView", "inlineEditing", "kanban", "listProperties", "localChangesBackup", "openEntityMode", "orderProperty", "pagination", "previewProperties", "propertiesOrder", "selectionController", "selectionEnabled", "sideDialogWidth", "sort", "titleProperty"];
|
|
33
33
|
/** A key of a collection's `admin` block. @group Models */
|
|
34
34
|
export type AdminCollectionKey = typeof ADMIN_COLLECTION_KEYS[number];
|
|
35
35
|
/**
|
|
@@ -13,9 +13,27 @@ import type { SecurityRule } from "./security_rules";
|
|
|
13
13
|
*/
|
|
14
14
|
export interface BaseCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* The collection's identity. Required, and the value nearly everything else
|
|
17
|
+
* keys on:
|
|
18
|
+
*
|
|
19
|
+
* - the REST path — `/api/data/<slug>`
|
|
20
|
+
* - the SDK accessor — `client.data.<slug>` / `client.data.collection("<slug>")`
|
|
21
|
+
* - the admin panel's URL
|
|
22
|
+
* - the target of a `reference` or `relation` property
|
|
23
|
+
*
|
|
24
|
+
* Conventionally kebab-case and plural (`blog-posts`). It is independent of
|
|
25
|
+
* {@link table}: the slug is what callers say, the table is where the rows
|
|
26
|
+
* live, and renaming one does not rename the other.
|
|
27
|
+
*
|
|
28
|
+
* Treat it as frozen once anything has shipped against it — changing a slug
|
|
29
|
+
* changes every URL and every generated accessor at once.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* defineCollection({
|
|
33
|
+
* slug: "blog-posts", // /api/data/blog-posts, client.data.blogPosts
|
|
34
|
+
* table: "posts",
|
|
35
|
+
* properties: { … }
|
|
36
|
+
* })
|
|
19
37
|
*/
|
|
20
38
|
slug: string;
|
|
21
39
|
/**
|
package/dist/types/cron.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RebaseServerClient } from "../controllers/client";
|
|
2
|
+
import type { RebaseSdkData } from "../controllers/data";
|
|
2
3
|
/**
|
|
3
4
|
* Cron Job type definitions for Rebase.
|
|
4
5
|
*
|
|
@@ -75,16 +76,56 @@ export interface CronJobContext {
|
|
|
75
76
|
/** A simple logger scoped to this job run. */
|
|
76
77
|
log: (...args: unknown[]) => void;
|
|
77
78
|
/**
|
|
78
|
-
* The server-side
|
|
79
|
-
*
|
|
80
|
-
*
|
|
79
|
+
* The server-side Rebase singleton — the **same object** `import { rebase }
|
|
80
|
+
* from "@rebasepro/server"` returns, and the same one `defineFunction`
|
|
81
|
+
* hands its callback. Spelled the same way here so that one thing has one
|
|
82
|
+
* name across every server-side authoring surface.
|
|
81
83
|
*
|
|
82
|
-
* Its data plane
|
|
83
|
-
* RLS** (`{ uid: "service", roles:
|
|
84
|
-
*
|
|
85
|
-
*
|
|
84
|
+
* Its data plane is {@link RebaseServerClient.dataAsAdmin}, which runs with
|
|
85
|
+
* **admin privileges and bypasses RLS** (`{ uid: "service", roles:
|
|
86
|
+
* ["admin"] }`). A cron has no per-request user, so there is no user-scoped
|
|
87
|
+
* alternative here and no policy to fall back on: scope every query's
|
|
88
|
+
* filters yourself.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* export default defineCron({
|
|
92
|
+
* name: "Nightly cleanup",
|
|
93
|
+
* schedule: "0 3 * * *",
|
|
94
|
+
* async handler({ rebase, log }) {
|
|
95
|
+
* const expired = await rebase.dataAsAdmin.sessions.findAll({
|
|
96
|
+
* where: { expired: ["==", true] }
|
|
97
|
+
* });
|
|
98
|
+
* for (const session of expired) {
|
|
99
|
+
* await rebase.dataAsAdmin.sessions.delete(session.id as string);
|
|
100
|
+
* }
|
|
101
|
+
* log(`Deleted ${expired.length} expired sessions`);
|
|
102
|
+
* }
|
|
103
|
+
* });
|
|
104
|
+
*/
|
|
105
|
+
rebase: RebaseServerClient;
|
|
106
|
+
/**
|
|
107
|
+
* The same object as {@link rebase}, under the name this context used
|
|
108
|
+
* before.
|
|
109
|
+
*
|
|
110
|
+
* @deprecated Use `rebase` instead. Two things made the old name a problem,
|
|
111
|
+
* and neither was cosmetic. It contradicted every other server surface,
|
|
112
|
+
* where the singleton is `rebase` — the previous docstring had to end with
|
|
113
|
+
* *"it is only named `client` here"*. And typing it as `RebaseClient`
|
|
114
|
+
* re-exposed `client.data`, the alias that {@link RebaseServerClient}
|
|
115
|
+
* deliberately `Omit`s so the RLS-bypassing plane has exactly one name and
|
|
116
|
+
* the privilege is visible at the call site. A reader who learned
|
|
117
|
+
* `client.data` here carried it to a collection callback, where
|
|
118
|
+
* `context.data` is the *user-scoped* plane — same spelling, opposite
|
|
119
|
+
* privilege.
|
|
120
|
+
*
|
|
121
|
+
* Still the full server client at runtime, and `data` still resolves, so
|
|
122
|
+
* existing cron files keep working and keep compiling. It will be removed
|
|
123
|
+
* in the next major.
|
|
86
124
|
*/
|
|
87
|
-
client:
|
|
125
|
+
client: RebaseServerClient & {
|
|
126
|
+
/** @deprecated Use `rebase.dataAsAdmin` — the name states the privilege. */
|
|
127
|
+
data: RebaseSdkData;
|
|
128
|
+
};
|
|
88
129
|
}
|
|
89
130
|
export type CronJobRunState = "idle" | "running" | "success" | "error" | "disabled";
|
|
90
131
|
/**
|
|
@@ -7,7 +7,8 @@ import type { RebaseCallContext } from "../call_context";
|
|
|
7
7
|
*
|
|
8
8
|
* Register per-collection on the collection's `callbacks` field, or globally
|
|
9
9
|
* via `initializeRebaseBackend({ callbacks })`. Fires on **every** data path — REST API,
|
|
10
|
-
* WebSocket / realtime subscriptions, and server-side
|
|
10
|
+
* WebSocket / realtime subscriptions, and server-side writes through
|
|
11
|
+
* `rebase.dataAsAdmin`.
|
|
11
12
|
*
|
|
12
13
|
* When both global and per-collection callbacks are registered, execution
|
|
13
14
|
* order is: **global → collection → property callbacks**.
|
|
@@ -166,7 +166,7 @@ export interface BaseProperty<CustomProps = unknown> {
|
|
|
166
166
|
* written and queryable server-side; it is stripped from every row the API
|
|
167
167
|
* serves, for every caller, including admins and service keys.
|
|
168
168
|
*
|
|
169
|
-
* This is a server-side guarantee, unlike `
|
|
169
|
+
* This is a server-side guarantee, unlike `admin.hideFromCollection`, which
|
|
170
170
|
* only stops the admin panel from *rendering* a field and leaves it in the
|
|
171
171
|
* JSON payload.
|
|
172
172
|
*/
|
|
@@ -904,6 +904,17 @@ export interface ImageResize {
|
|
|
904
904
|
* @group Entity properties
|
|
905
905
|
*/
|
|
906
906
|
export type JsonLogicRule = Record<string, any>;
|
|
907
|
+
/**
|
|
908
|
+
* A condition that is either a JSON Logic rule or a literal answer.
|
|
909
|
+
*
|
|
910
|
+
* The unconditional case is the common one — "this field is never editable",
|
|
911
|
+
* "this field is never shown" — and with only a rule accepted it had to be
|
|
912
|
+
* spelled `{ "==": [1, 1] }`, which reads as a puzzle at the call site. A plain
|
|
913
|
+
* `true` says the same thing.
|
|
914
|
+
*
|
|
915
|
+
* @group Entity properties
|
|
916
|
+
*/
|
|
917
|
+
export type ConditionRule = JsonLogicRule | boolean;
|
|
907
918
|
/**
|
|
908
919
|
* Conditions for individual enum values within a property.
|
|
909
920
|
* @group Entity properties
|
|
@@ -945,8 +956,10 @@ export interface PropertyConditions {
|
|
|
945
956
|
* \`\`\`json
|
|
946
957
|
* { "==": [{ "var": "values.status" }, "archived"] }
|
|
947
958
|
* \`\`\`
|
|
959
|
+
*
|
|
960
|
+
* A literal `true` disables it unconditionally.
|
|
948
961
|
*/
|
|
949
|
-
disabled?:
|
|
962
|
+
disabled?: ConditionRule;
|
|
950
963
|
/**
|
|
951
964
|
* Message to display when the field is disabled by a condition.
|
|
952
965
|
*/
|
|
@@ -959,13 +972,18 @@ export interface PropertyConditions {
|
|
|
959
972
|
/**
|
|
960
973
|
* Hide the field completely when this condition evaluates to true.
|
|
961
974
|
* The field is removed from the form (not just visually hidden).
|
|
975
|
+
*
|
|
976
|
+
* A literal `true` hides it unconditionally. This is the way to keep a
|
|
977
|
+
* property out of the form without keeping it out of the collection.
|
|
962
978
|
*/
|
|
963
|
-
hidden?:
|
|
979
|
+
hidden?: ConditionRule;
|
|
964
980
|
/**
|
|
965
981
|
* Make the field read-only when this condition evaluates to true.
|
|
966
982
|
* Renders as a preview instead of an input.
|
|
983
|
+
*
|
|
984
|
+
* A literal `true` makes it read-only unconditionally.
|
|
967
985
|
*/
|
|
968
|
-
readOnly?:
|
|
986
|
+
readOnly?: ConditionRule;
|
|
969
987
|
/**
|
|
970
988
|
* Make the field required when this condition evaluates to true.
|
|
971
989
|
* Overrides the static `validation.required` setting.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/types",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.1-canary.g394d868",
|
|
5
5
|
"description": "Rebase type definitions — shared interfaces and controller types",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@types/node": "^26.1.2",
|
|
43
43
|
"@types/object-hash": "^3.0.6",
|
|
44
44
|
"@types/react-measure": "^2.0.12",
|
|
45
|
-
"hono": "^4.
|
|
45
|
+
"hono": "^4.13.0",
|
|
46
46
|
"jest": "^30.4.2",
|
|
47
47
|
"ts-jest": "^29.4.12",
|
|
48
48
|
"typescript": "^6.0.3",
|
package/src/call_context.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DataDriver } from "./controllers/data_driver";
|
|
1
2
|
import type { StorageSource } from "./controllers/storage";
|
|
2
3
|
import type { RebaseClient } from "./controllers/client";
|
|
3
4
|
import type { RebaseSdkData } from "./controllers/data";
|
|
@@ -21,7 +22,14 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
21
22
|
* The Rebase client instance.
|
|
22
23
|
* Available in all entity callbacks (beforeSave, afterSave, afterRead,
|
|
23
24
|
* beforeDelete, afterDelete) and in CollectionActionsProps via context.
|
|
24
|
-
* Use it to call backend functions, access
|
|
25
|
+
* Use it to call backend functions, access storage, send email, etc.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ **Not the same trust level as {@link data}.** Server-side this is the
|
|
28
|
+
* app singleton, so `client.dataAsAdmin` is **always** the RLS-bypassing
|
|
29
|
+
* plane — while {@link data}, one property over, follows whoever triggered
|
|
30
|
+
* the callback. On a user request, reaching for `context.client.dataAsAdmin`
|
|
31
|
+
* silently escalates a user-scoped operation to admin. For queries in a
|
|
32
|
+
* callback use {@link data}; come here for functions, storage and email.
|
|
25
33
|
*
|
|
26
34
|
* @example
|
|
27
35
|
* // In a beforeSave callback:
|
|
@@ -38,12 +46,59 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
38
46
|
* Unified data access — `context.data.products.create(...)`.
|
|
39
47
|
* Access any collection as a dynamic property.
|
|
40
48
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
49
|
+
* **Inherits the privilege of whatever triggered the callback.** This is not
|
|
50
|
+
* a fixed trust level, and it is the one thing to know about this accessor:
|
|
51
|
+
*
|
|
52
|
+
* - Triggered by a **user request** (REST, realtime, an admin-panel edit):
|
|
53
|
+
* user-scoped. The callback runs on the RLS-bound transaction opened for
|
|
54
|
+
* that request, so policies apply to reads *and* writes — a callback
|
|
55
|
+
* cannot see a row its caller could not.
|
|
56
|
+
* - Triggered by **server-context work** (`rebase.dataAsAdmin`, a cron):
|
|
57
|
+
* unscoped, on the owner connection, bypassing RLS.
|
|
58
|
+
*
|
|
59
|
+
* So a callback that reads a sibling row will find it when an admin task
|
|
60
|
+
* saves and may find nothing when an end user saves — without an error,
|
|
61
|
+
* because RLS filters rather than raises. Write callbacks that tolerate
|
|
62
|
+
* that, or reach for {@link client}`.dataAsAdmin` deliberately when the
|
|
63
|
+
* callback genuinely has to see past its caller.
|
|
64
|
+
*
|
|
65
|
+
* Verified end-to-end against Postgres rather than asserted — see
|
|
66
|
+
* `"scopes context.data to the caller when a callback runs on a user
|
|
67
|
+
* request"` in `server-postgres`' `rls-enforcement` e2e suite. The
|
|
68
|
+
* documentation previously claimed the opposite (that callbacks always have
|
|
69
|
+
* full access), which is the unsafe direction to be wrong in.
|
|
70
|
+
*
|
|
71
|
+
* Returns flat rows (`{ id, ...columns }`), identical in *shape* to the
|
|
72
|
+
* frontend SDK client — so `context.data` in a backend callback and
|
|
73
|
+
* `client.data` in the frontend are accessed the same way (`row.title`,
|
|
74
|
+
* never `row.values.title`). Shape only: privilege differs as above.
|
|
44
75
|
*/
|
|
45
76
|
data: RebaseSdkData;
|
|
46
77
|
|
|
78
|
+
/**
|
|
79
|
+
* The driver executing the operation this callback is attached to.
|
|
80
|
+
*
|
|
81
|
+
* Present server-side only. Declared here because it is already public in
|
|
82
|
+
* practice — the backend has always passed it, and the callbacks guide
|
|
83
|
+
* documented `context.driver.withAuth(user)` in all six locales. The
|
|
84
|
+
* contract simply did not name it, so `buildCallContext` was cast through
|
|
85
|
+
* `as unknown as RebaseCallContext` and nothing about the object was
|
|
86
|
+
* type-checked at all.
|
|
87
|
+
*
|
|
88
|
+
* The guide no longer recommends `withAuth` — {@link data} is already
|
|
89
|
+
* user-scoped on a user request, so the manual re-scoping it described was
|
|
90
|
+
* answering a problem that did not exist. The field stays declared rather
|
|
91
|
+
* than removed: it is on the runtime object, dropping it would break anyone
|
|
92
|
+
* who found it, and a named optional is better than a silent extra.
|
|
93
|
+
*
|
|
94
|
+
* `withAuth` is not on {@link DataDriver} because not every engine supports
|
|
95
|
+
* RLS scoping; it is narrowed here, and left optional so a driver without it
|
|
96
|
+
* is a compile-time absence rather than a runtime surprise.
|
|
97
|
+
*/
|
|
98
|
+
driver?: DataDriver & {
|
|
99
|
+
withAuth?(user: { uid: string; roles?: string[] }): Promise<DataDriver>;
|
|
100
|
+
};
|
|
101
|
+
|
|
47
102
|
/**
|
|
48
103
|
* Used storage implementation
|
|
49
104
|
*/
|
|
@@ -362,7 +362,22 @@ export interface RebaseClient<DB = unknown> {
|
|
|
362
362
|
/** Resolve the current auth token */
|
|
363
363
|
resolveToken?(): Promise<string | null>;
|
|
364
364
|
|
|
365
|
-
/**
|
|
365
|
+
/**
|
|
366
|
+
* POST to an arbitrary path on the backend — the escape hatch, not the way
|
|
367
|
+
* to call a function.
|
|
368
|
+
*
|
|
369
|
+
* For a custom function use {@link functions}`.invoke(name, payload)`: it
|
|
370
|
+
* targets `/functions/<name>`, takes a method and sub-path, and returns the
|
|
371
|
+
* response body as sent. This posts wherever you point it and **unwraps**:
|
|
372
|
+
* it returns `res.data` when the response has a `data` property and the
|
|
373
|
+
* whole envelope otherwise — so an endpoint that legitimately answers
|
|
374
|
+
* `{ data: null }` hands back the envelope rather than `null`. Two ways to
|
|
375
|
+
* reach a function with two different response contracts is a trap; this is
|
|
376
|
+
* the one that exists for paths `invoke` cannot express.
|
|
377
|
+
*
|
|
378
|
+
* @internal Prefer `functions.invoke()`. Kept public because a backend can
|
|
379
|
+
* mount routes outside `/functions`, and nothing else reaches those.
|
|
380
|
+
*/
|
|
366
381
|
call?<T = unknown>(endpoint: string, payload?: unknown): Promise<T>;
|
|
367
382
|
|
|
368
383
|
/**
|
|
@@ -410,85 +425,6 @@ export interface RebaseServerClient<DB = unknown> extends Omit<RebaseClient<DB>,
|
|
|
410
425
|
sql(query: string, options?: { database?: string; role?: string; params?: unknown[] }): Promise<Record<string, unknown>[]>;
|
|
411
426
|
}
|
|
412
427
|
|
|
413
|
-
// ─── RebaseBrowserClient ─────────────────────────────────────────────────────
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* The browser-side Rebase surface — the shape produced by
|
|
417
|
-
* `createRebaseClient()` in `@rebasepro/client`.
|
|
418
|
-
*
|
|
419
|
-
* Its {@link data} accessor is **user-scoped**: every call carries the signed-in
|
|
420
|
-
* user's token, so backend RLS policies apply. It deliberately omits the
|
|
421
|
-
* server-only members — there is no `sql`, no `email`, and no
|
|
422
|
-
* `dataAsAdmin`, so the RLS-bypassing accessor can never be reached from
|
|
423
|
-
* browser code.
|
|
424
|
-
*/
|
|
425
|
-
export interface RebaseBrowserClient<DB = unknown> {
|
|
426
|
-
/** User-scoped data access layer (carries the signed-in user's token). */
|
|
427
|
-
data: RebaseSdkData<DB>;
|
|
428
|
-
|
|
429
|
-
/** Unified Authentication layer */
|
|
430
|
-
auth: AuthClient;
|
|
431
|
-
|
|
432
|
-
/** Unified Storage layer (default storage source, backward-compatible) */
|
|
433
|
-
storage?: StorageSource;
|
|
434
|
-
|
|
435
|
-
/** Registry of all named storage sources for multi-backend support */
|
|
436
|
-
storageRegistry?: StorageSourceRegistry;
|
|
437
|
-
|
|
438
|
-
/** Build a server-backed {@link StorageSource} for a named storage source. */
|
|
439
|
-
createStorageSource?(storageId: string): StorageSource;
|
|
440
|
-
|
|
441
|
-
/** Discover the storage sources declared on the backend. */
|
|
442
|
-
fetchStorageSources?(): Promise<StorageSourceDefinition[]>;
|
|
443
|
-
|
|
444
|
-
/** Admin API for user management */
|
|
445
|
-
admin?: AdminAPI;
|
|
446
|
-
|
|
447
|
-
/** Cron job management API */
|
|
448
|
-
cron?: CronAPI;
|
|
449
|
-
|
|
450
|
-
/** Database backup management API */
|
|
451
|
-
backups?: BackupsAPI;
|
|
452
|
-
|
|
453
|
-
/** Custom backend functions API */
|
|
454
|
-
functions?: FunctionsAPI;
|
|
455
|
-
|
|
456
|
-
/** Service API keys management API */
|
|
457
|
-
apiKeys?: ApiKeysAPI;
|
|
458
|
-
|
|
459
|
-
/** Base HTTP URL of the backend server */
|
|
460
|
-
baseUrl?: string;
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* The path every API route is mounted under, appended to {@link baseUrl}.
|
|
464
|
-
*
|
|
465
|
-
* `"/api"` unless the backend was configured with a different `basePath`
|
|
466
|
-
* and the client told to match. Exposed because code that builds a URL by
|
|
467
|
-
* hand — rather than going through the client's own methods — otherwise has
|
|
468
|
-
* to guess, and guessing `/api` is wrong for exactly the projects that set
|
|
469
|
-
* the option.
|
|
470
|
-
*/
|
|
471
|
-
apiPath?: string;
|
|
472
|
-
|
|
473
|
-
/** WebSocket client for realtime subscriptions */
|
|
474
|
-
ws?: RebaseWebSocket;
|
|
475
|
-
|
|
476
|
-
/** Set the auth token for subsequent requests */
|
|
477
|
-
setToken?(token: string | null): void;
|
|
478
|
-
|
|
479
|
-
/** Set a function that lazily resolves the auth token */
|
|
480
|
-
setAuthTokenGetter?(getter: () => Promise<string | null>): void;
|
|
481
|
-
|
|
482
|
-
/** Set handler called when a request returns 401 */
|
|
483
|
-
setOnUnauthorized?(handler: () => Promise<boolean>): void;
|
|
484
|
-
|
|
485
|
-
/** Resolve the current auth token */
|
|
486
|
-
resolveToken?(): Promise<string | null>;
|
|
487
|
-
|
|
488
|
-
/** Make a raw HTTP call to the backend */
|
|
489
|
-
call?<T = unknown>(endpoint: string, payload?: unknown): Promise<T>;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
428
|
/**
|
|
493
429
|
* Client-side registry for managing multiple storage sources.
|
|
494
430
|
*
|