@rebasepro/types 0.20.0 → 0.21.0
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 +23 -2
- package/dist/controllers/data_driver.d.ts +33 -0
- package/dist/errors.d.ts +0 -15
- package/dist/index.es.js +25 -22
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +9 -4
- package/dist/types/project_manifest.d.ts +64 -3
- package/dist/types/websockets.d.ts +120 -0
- package/package.json +1 -1
package/dist/call_context.d.ts
CHANGED
|
@@ -3,6 +3,25 @@ import type { StorageSource } from "./controllers/storage.js";
|
|
|
3
3
|
import type { RebaseClient } from "./controllers/client.js";
|
|
4
4
|
import type { RebaseSdkData } from "./controllers/data.js";
|
|
5
5
|
import type { User } from "./users/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* The client a collection callback is handed as `context.client`: the Rebase
|
|
8
|
+
* client **without `data`**.
|
|
9
|
+
*
|
|
10
|
+
* A callback's queries go through {@link RebaseCallContext.data}. This client
|
|
11
|
+
* is for everything else — functions, storage, email, and `dataAsAdmin` when a
|
|
12
|
+
* callback deliberately needs an admin's reach.
|
|
13
|
+
*
|
|
14
|
+
* `data` is left off because server-side there is none. The object is the
|
|
15
|
+
* `rebase` singleton, which omits `data` so that its admin-scoped plane has
|
|
16
|
+
* exactly one name. This used to be declared as the full `RebaseClient`, so
|
|
17
|
+
* `context.client.data.collection(…)` compiled and then threw "Cannot read
|
|
18
|
+
* properties of undefined" in production. In the browser the panel's client
|
|
19
|
+
* does carry a `data`, but `context.data` is the accessor there too: one name
|
|
20
|
+
* for a callback's queries on both sides of the wire.
|
|
21
|
+
*
|
|
22
|
+
* @group Hooks and utilities
|
|
23
|
+
*/
|
|
24
|
+
export type RebaseCallbackClient<DB = unknown> = Omit<RebaseClient<DB>, "data">;
|
|
6
25
|
/**
|
|
7
26
|
* Context that is provided to entity callbacks (hooks).
|
|
8
27
|
* It contains only the dependencies that are available in both the frontend and the backend.
|
|
@@ -51,6 +70,8 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
51
70
|
* user-scoped operation to admin. For queries in a callback use
|
|
52
71
|
* {@link data}; come here for functions, storage and email.
|
|
53
72
|
*
|
|
73
|
+
* There is no `context.client.data`: see {@link RebaseCallbackClient}.
|
|
74
|
+
*
|
|
54
75
|
* @example
|
|
55
76
|
* // In a beforeSave callback:
|
|
56
77
|
* const result = await context.client.functions.invoke('my-function', { ... });
|
|
@@ -60,7 +81,7 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
60
81
|
* const { client } = props.context;
|
|
61
82
|
* const result = await client.functions.invoke('extract-job', { url });
|
|
62
83
|
*/
|
|
63
|
-
client:
|
|
84
|
+
client: RebaseCallbackClient;
|
|
64
85
|
/**
|
|
65
86
|
* Unified data access — `context.data.products.create(...)`.
|
|
66
87
|
* Access any collection as a dynamic property.
|
|
@@ -107,7 +128,7 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
107
128
|
* practice — the backend has always passed it, and the callbacks guide
|
|
108
129
|
* documented `context.driver.withAuth(user)` in all six locales. The
|
|
109
130
|
* contract simply did not name it, so `buildCallContext` was cast through
|
|
110
|
-
* `as
|
|
131
|
+
* `as RebaseCallContext` and nothing about the object was
|
|
111
132
|
* type-checked at all.
|
|
112
133
|
*
|
|
113
134
|
* The guide no longer recommends `withAuth` — {@link data} is already
|
|
@@ -279,6 +279,25 @@ export interface DeleteManyProps<M extends Record<string, unknown> = Record<stri
|
|
|
279
279
|
/** See {@link DeleteProps.hard}. */
|
|
280
280
|
hard?: boolean;
|
|
281
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Addressing ONE link of a many-to-many, to set the columns it carries.
|
|
284
|
+
*
|
|
285
|
+
* `path` is the relation on a row — `posts/1/tags` — and `targetId` the row on
|
|
286
|
+
* the far side, so the pair names exactly one junction row. Not a `SaveProps`,
|
|
287
|
+
* because a save at that address means "write the target row", and a link's own
|
|
288
|
+
* columns are not the target's: two posts sharing a tag see one tag and two
|
|
289
|
+
* different links.
|
|
290
|
+
*
|
|
291
|
+
* @internal
|
|
292
|
+
*/
|
|
293
|
+
export interface UpdateRelationPivotProps {
|
|
294
|
+
/** The nested relation path, e.g. `posts/1/tags`. */
|
|
295
|
+
path: string;
|
|
296
|
+
/** The far side's key. */
|
|
297
|
+
targetId: string | number;
|
|
298
|
+
/** The junction columns to set, keyed by the property key `through.properties` declares. */
|
|
299
|
+
pivot: Record<string, unknown>;
|
|
300
|
+
}
|
|
282
301
|
/**
|
|
283
302
|
* One operation of a {@link DataDriver.batchWrite}.
|
|
284
303
|
*
|
|
@@ -429,6 +448,20 @@ export interface DataDriver {
|
|
|
429
448
|
* @param path Collection path
|
|
430
449
|
*/
|
|
431
450
|
deleteAll?(path: string): Promise<void>;
|
|
451
|
+
/**
|
|
452
|
+
* Set the columns ONE many-to-many link carries, leaving the membership
|
|
453
|
+
* alone — `manyToMany`'s `through.properties`.
|
|
454
|
+
*
|
|
455
|
+
* `PATCH /api/data/<c>/<id>/<relation>/<targetId>` with a `_pivot` body
|
|
456
|
+
* reaches this. The membership array cannot express it: sending one element
|
|
457
|
+
* would unlink everything else, and re-sending the whole set to change one
|
|
458
|
+
* value reintroduces the lost update the membership diff exists to avoid.
|
|
459
|
+
*
|
|
460
|
+
* Optional. A driver whose junctions carry nothing but the two keys leaves
|
|
461
|
+
* it undefined, and the REST layer answers `RELATION_PIVOT_UNSUPPORTED`
|
|
462
|
+
* rather than pretending the write landed.
|
|
463
|
+
*/
|
|
464
|
+
updateRelationPivot?(props: UpdateRelationPivotProps): Promise<void>;
|
|
432
465
|
/**
|
|
433
466
|
* Delete many rows in one transaction, addressed by id.
|
|
434
467
|
*
|
package/dist/errors.d.ts
CHANGED
|
@@ -132,21 +132,6 @@ export declare class RebaseClientError extends RebaseApiError {
|
|
|
132
132
|
*/
|
|
133
133
|
constructor(message: string, init?: RebaseErrorInit);
|
|
134
134
|
}
|
|
135
|
-
/**
|
|
136
|
-
* Build the stub a client installs for a contract method it cannot serve.
|
|
137
|
-
*
|
|
138
|
-
* `listen`, `listenById` and `count` are part of `SDKCollectionClient`, not
|
|
139
|
-
* optional extras — a caller should be able to write
|
|
140
|
-
* `client.data.posts.count()` without asking first, and a transport that cannot
|
|
141
|
-
* serve it should answer with a sentence naming the configuration that would,
|
|
142
|
-
* rather than with `undefined is not a function` at the call site. Where the
|
|
143
|
-
* transport genuinely cannot (a client built with `realtime: false`, a driver
|
|
144
|
-
* with no `listenCollection`), it installs one of these instead of omitting the
|
|
145
|
-
* method.
|
|
146
|
-
*
|
|
147
|
-
* @param message What to tell the caller, naming the fix.
|
|
148
|
-
* @group Errors
|
|
149
|
-
*/
|
|
150
135
|
export declare function unsupportedMethod<F>(message: string): F;
|
|
151
136
|
/**
|
|
152
137
|
* Can this method actually do anything?
|
package/dist/index.es.js
CHANGED
|
@@ -81,21 +81,6 @@ var RebaseClientError = class extends RebaseApiError {
|
|
|
81
81
|
* agree about it, and a module-local symbol would not.
|
|
82
82
|
*/
|
|
83
83
|
var UNSUPPORTED_METHOD = Symbol.for("rebase.unsupportedMethod");
|
|
84
|
-
/**
|
|
85
|
-
* Build the stub a client installs for a contract method it cannot serve.
|
|
86
|
-
*
|
|
87
|
-
* `listen`, `listenById` and `count` are part of `SDKCollectionClient`, not
|
|
88
|
-
* optional extras — a caller should be able to write
|
|
89
|
-
* `client.data.posts.count()` without asking first, and a transport that cannot
|
|
90
|
-
* serve it should answer with a sentence naming the configuration that would,
|
|
91
|
-
* rather than with `undefined is not a function` at the call site. Where the
|
|
92
|
-
* transport genuinely cannot (a client built with `realtime: false`, a driver
|
|
93
|
-
* with no `listenCollection`), it installs one of these instead of omitting the
|
|
94
|
-
* method.
|
|
95
|
-
*
|
|
96
|
-
* @param message What to tell the caller, naming the fix.
|
|
97
|
-
* @group Errors
|
|
98
|
-
*/
|
|
99
84
|
function unsupportedMethod(message) {
|
|
100
85
|
const stub = () => {
|
|
101
86
|
throw new RebaseClientError(message, { code: "REALTIME_DISABLED" });
|
|
@@ -574,23 +559,41 @@ function nestAdminKeysOf(source, adminKeys) {
|
|
|
574
559
|
function nestAdminCollectionKeys(collection) {
|
|
575
560
|
return nestAdminKeysOf(collection, ADMIN_COLLECTION_KEYS);
|
|
576
561
|
}
|
|
562
|
+
/** A record of properties, keyed by name — a map's `properties`, or a `oneOf` block's. */
|
|
563
|
+
function nestEachProperty(properties) {
|
|
564
|
+
return Object.fromEntries(Object.entries(properties).map(([key, child]) => [key, isNestable(child) ? nestAdminPropertyKeys(child) : child]));
|
|
565
|
+
}
|
|
566
|
+
/** Anything the walk can descend into: a plain object, not an array. */
|
|
567
|
+
function isNestable(value) {
|
|
568
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
569
|
+
}
|
|
577
570
|
/**
|
|
578
571
|
* {@link nestAdminKeysOf} for a property, applied to its children too.
|
|
579
572
|
*
|
|
580
|
-
* A map property carries `properties`, an array property carries `of`, and
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
573
|
+
* A map property carries `properties`, an array property carries `of`, and an
|
|
574
|
+
* array of typed blocks carries `oneOf.properties` — a record of properties like
|
|
575
|
+
* a map's. All of them hold properties with `admin` blocks of their own. A flat
|
|
576
|
+
* `readOnly` left on a child is as dead — and as fatal at the next boot — as one
|
|
577
|
+
* left on the parent, so the walk goes all the way down.
|
|
578
|
+
*
|
|
579
|
+
* `oneOf` was the container this walk did not know about, and it is the one the
|
|
580
|
+
* block-based collection templates are built out of: every block inside them
|
|
581
|
+
* kept its flat `markdown`, and the collection they created would not boot.
|
|
584
582
|
*
|
|
585
583
|
* @group Models
|
|
586
584
|
*/
|
|
587
585
|
function nestAdminPropertyKeys(property) {
|
|
588
586
|
const nested = nestAdminKeysOf(property, ADMIN_PROPERTY_KEYS);
|
|
589
587
|
const children = nested.properties;
|
|
590
|
-
if (
|
|
588
|
+
if (isNestable(children)) nested.properties = nestEachProperty(children);
|
|
589
|
+
const oneOf = nested.oneOf;
|
|
590
|
+
if (isNestable(oneOf) && isNestable(oneOf.properties)) nested.oneOf = {
|
|
591
|
+
...oneOf,
|
|
592
|
+
properties: nestEachProperty(oneOf.properties)
|
|
593
|
+
};
|
|
591
594
|
const of = nested.of;
|
|
592
|
-
if (Array.isArray(of)) nested.of = of.map((entry) =>
|
|
593
|
-
else if (of
|
|
595
|
+
if (Array.isArray(of)) nested.of = of.map((entry) => isNestable(entry) ? nestAdminPropertyKeys(entry) : entry);
|
|
596
|
+
else if (isNestable(of)) nested.of = nestAdminPropertyKeys(of);
|
|
594
597
|
return nested;
|
|
595
598
|
}
|
|
596
599
|
//#endregion
|