@rebasepro/types 0.23.0 → 0.24.1-canary.g19596ef
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 +8 -4
- package/dist/controllers/client.d.ts +113 -24
- package/dist/controllers/collection_registry.d.ts +17 -0
- package/dist/controllers/data.d.ts +570 -122
- package/dist/controllers/data_driver.d.ts +85 -1
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/storage-references.d.ts +114 -0
- package/dist/controllers/storage.d.ts +73 -13
- package/dist/errors.d.ts +15 -1
- package/dist/index.es.js +1228 -43
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +1 -1
- package/dist/types/api_keys.d.ts +68 -36
- package/dist/types/auth_adapter.d.ts +97 -2
- package/dist/types/backend.d.ts +356 -9
- package/dist/types/backup.d.ts +102 -0
- package/dist/types/collection_patch.d.ts +74 -0
- package/dist/types/collections.d.ts +23 -0
- package/dist/types/cron.d.ts +58 -7
- package/dist/types/database_adapter.d.ts +34 -8
- package/dist/types/entities.d.ts +11 -0
- package/dist/types/history.d.ts +15 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/project_manifest.d.ts +73 -1
- package/dist/types/properties.d.ts +39 -2
- package/dist/types/register.d.ts +43 -0
- package/dist/types/relations.d.ts +37 -1
- package/dist/types/resource_kinds.d.ts +20 -10
- package/dist/types/schema_editing.d.ts +39 -13
- package/dist/types/scopes.d.ts +272 -0
- package/dist/types/storage_authorize.d.ts +10 -1
- package/dist/types/storage_source.d.ts +2 -6
- package/dist/types/websockets.d.ts +32 -1
- package/dist/users/user.d.ts +7 -0
- package/package.json +1 -1
package/dist/types/backend.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { AuthAdapter } from "./auth_adapter.js";
|
|
|
6
6
|
import type { HistoryConfig } from "../controllers/client.js";
|
|
7
7
|
import type { ChannelBusSetting } from "./channel_bus.js";
|
|
8
8
|
import type { SchemaEditingAdmin } from "./schema_editing.js";
|
|
9
|
+
import type { AccessModel } from "./scopes.js";
|
|
9
10
|
/**
|
|
10
11
|
* Abstract database connection interface.
|
|
11
12
|
* Represents a connection to any database system.
|
|
@@ -246,6 +247,58 @@ export interface RealtimeChannelsConfig {
|
|
|
246
247
|
* Defaults to `{ type: "memory" }` — i.e. they don't.
|
|
247
248
|
*/
|
|
248
249
|
bus?: ChannelBusSetting;
|
|
250
|
+
/**
|
|
251
|
+
* How many subscriptions one socket may hold; the next is refused with
|
|
252
|
+
* `TOO_MANY_SUBSCRIPTIONS`. A positive whole number, checked at boot.
|
|
253
|
+
* Defaults to 1000. `REALTIME_MAX_SUBSCRIPTIONS_PER_SOCKET` wins over it.
|
|
254
|
+
*/
|
|
255
|
+
maxSubscriptionsPerSocket?: number;
|
|
256
|
+
/**
|
|
257
|
+
* How many sockets one user (one identity: a signed-in user, an API key's
|
|
258
|
+
* user, an impersonated user) may hold open on one server instance. The
|
|
259
|
+
* next one's `AUTHENTICATE` is refused with `TOO_MANY_SOCKETS` and the
|
|
260
|
+
* socket closed with 4002; the SDK keeps retrying with backoff, so it gets
|
|
261
|
+
* in once another closes. A positive whole number, checked at boot.
|
|
262
|
+
* Unset (the default) is no ceiling. `REALTIME_MAX_SOCKETS_PER_USER` wins
|
|
263
|
+
* over it.
|
|
264
|
+
*/
|
|
265
|
+
maxSocketsPerUser?: number;
|
|
266
|
+
/**
|
|
267
|
+
* The longest a change waits for the refetch that delivers it, in ms. A
|
|
268
|
+
* refetch waits for 300 ms without a change, and at most this long under a
|
|
269
|
+
* steady stream of writes. Defaults to 1000. A positive whole number,
|
|
270
|
+
* checked at boot. `REALTIME_REFETCH_MAX_WAIT_MS` wins over it.
|
|
271
|
+
*/
|
|
272
|
+
refetchMaxWaitMs?: number;
|
|
273
|
+
/**
|
|
274
|
+
* How long a big list subscription's total may be reused before it is
|
|
275
|
+
* counted again, in ms. Unset (the default), every frame counts. Frames
|
|
276
|
+
* that reuse it carry `meta.totalAsOf`. `REALTIME_RECOUNT_INTERVAL_MS`
|
|
277
|
+
* wins over it.
|
|
278
|
+
*/
|
|
279
|
+
recountIntervalMs?: number;
|
|
280
|
+
/**
|
|
281
|
+
* The smallest last total at which {@link recountIntervalMs} applies;
|
|
282
|
+
* smaller lists are counted on every frame. Defaults to 100 000.
|
|
283
|
+
* `REALTIME_RECOUNT_MIN_ROWS` wins over it.
|
|
284
|
+
*/
|
|
285
|
+
recountMinRows?: number;
|
|
286
|
+
/**
|
|
287
|
+
* How changes are captured for realtime. `auto` (the default) installs
|
|
288
|
+
* database-level capture where the connection can and falls back to
|
|
289
|
+
* announcing the API's own writes where it cannot; `trigger` asks for
|
|
290
|
+
* capture and warns when it is refused; `wal` is `trigger` until WAL
|
|
291
|
+
* streaming ships; `off` announces the API's own writes only.
|
|
292
|
+
* `REALTIME_CDC` wins over it.
|
|
293
|
+
*/
|
|
294
|
+
cdc?: "auto" | "wal" | "trigger" | "off";
|
|
295
|
+
/**
|
|
296
|
+
* The URL path the realtime socket accepts upgrades on. Defaults to the
|
|
297
|
+
* one the server derives from where it is mounted — `/` for a server at
|
|
298
|
+
* `/api`, which is where the SDK dials. Set it when clients dial elsewhere
|
|
299
|
+
* (a `websocketUrl` with a path). See {@link RealtimeSocketOptions.path}.
|
|
300
|
+
*/
|
|
301
|
+
path?: string;
|
|
249
302
|
}
|
|
250
303
|
/**
|
|
251
304
|
* Abstract realtime provider interface.
|
|
@@ -293,6 +346,25 @@ export interface RealtimeProvider {
|
|
|
293
346
|
* Called during graceful shutdown before closing database connections.
|
|
294
347
|
*/
|
|
295
348
|
stopListening?(): Promise<void>;
|
|
349
|
+
/**
|
|
350
|
+
* The long-lived connections realtime depends on, for `/health`. A change
|
|
351
|
+
* feed that has gone quiet — a half-open LISTEN connection — loses every
|
|
352
|
+
* external and cross-instance change while writes through this instance
|
|
353
|
+
* still look live, so it is reported rather than inferred.
|
|
354
|
+
*/
|
|
355
|
+
health?(): RealtimeListenerHealth[];
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* One long-lived realtime connection, as `/health` reports it.
|
|
359
|
+
* @group Backend
|
|
360
|
+
*/
|
|
361
|
+
export interface RealtimeListenerHealth {
|
|
362
|
+
/** What it carries — `"cdc"`, `"cross-instance"`, `"channel-bus"`. */
|
|
363
|
+
name: string;
|
|
364
|
+
/** Listening on a connection that answered its last heartbeat. */
|
|
365
|
+
connected: boolean;
|
|
366
|
+
/** When (epoch ms) it went down, while it is down. */
|
|
367
|
+
downSince?: number;
|
|
296
368
|
}
|
|
297
369
|
/**
|
|
298
370
|
* Abstract collection registry interface.
|
|
@@ -341,6 +413,124 @@ export interface DataTransformer {
|
|
|
341
413
|
*/
|
|
342
414
|
deserializeFromDatabase<M extends Record<string, unknown>>(data: Record<string, unknown>, collection: CollectionConfig): Promise<M>;
|
|
343
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* The table column a value of a {@link SqlScriptResult} was read from, as the
|
|
418
|
+
* database itself reported it — not as the query's text suggests.
|
|
419
|
+
*
|
|
420
|
+
* @group Admin
|
|
421
|
+
*/
|
|
422
|
+
export interface SqlScriptColumnSource {
|
|
423
|
+
schema: string;
|
|
424
|
+
table: string;
|
|
425
|
+
column: string;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* One column of a {@link SqlScriptResult}, in result order.
|
|
429
|
+
*
|
|
430
|
+
* @group Admin
|
|
431
|
+
*/
|
|
432
|
+
export interface SqlScriptColumn {
|
|
433
|
+
/** The name the result gives it. Two columns of one result may share it. */
|
|
434
|
+
name: string;
|
|
435
|
+
/** Its type, as the database names it: `integer`, `text[]`, `timestamp with time zone`. */
|
|
436
|
+
type?: string;
|
|
437
|
+
/**
|
|
438
|
+
* Where the database says the value came from: a plain reference to a
|
|
439
|
+
* column of a table or view, through any number of subqueries.
|
|
440
|
+
*
|
|
441
|
+
* Absent for everything no stored row holds — an expression, a cast that
|
|
442
|
+
* changes the type, a literal, an aggregate, a function's output, a
|
|
443
|
+
* `UNION`.
|
|
444
|
+
*/
|
|
445
|
+
source?: SqlScriptColumnSource;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* A table or view some column of a {@link SqlScriptResult} came from.
|
|
449
|
+
*
|
|
450
|
+
* @group Admin
|
|
451
|
+
*/
|
|
452
|
+
export interface SqlScriptTable {
|
|
453
|
+
schema: string;
|
|
454
|
+
table: string;
|
|
455
|
+
/** What the relation is. Only a `table` or a `partitioned table` holds rows that can be updated by key. */
|
|
456
|
+
kind: "table" | "partitioned table" | "view" | "materialized view" | "foreign table" | "other";
|
|
457
|
+
/** Its primary key columns, in key order. Empty when it has none. */
|
|
458
|
+
primaryKey: string[];
|
|
459
|
+
/**
|
|
460
|
+
* Other tables inherit this one (by `INHERITS`, not as partitions). A row
|
|
461
|
+
* read from it may live in one of them, and a primary key is not unique
|
|
462
|
+
* across them.
|
|
463
|
+
*/
|
|
464
|
+
hasInheritors: boolean;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Something the database said while a script ran: `there is no transaction in
|
|
468
|
+
* progress` for a ROLLBACK with nothing to end, a `RAISE NOTICE`.
|
|
469
|
+
*
|
|
470
|
+
* @group Admin
|
|
471
|
+
*/
|
|
472
|
+
export interface SqlScriptNotice {
|
|
473
|
+
severity: string;
|
|
474
|
+
message: string;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* What a SQL script a person wrote returned. See {@link SQLAdmin.runSqlScript}.
|
|
478
|
+
*
|
|
479
|
+
* @group Admin
|
|
480
|
+
*/
|
|
481
|
+
export interface SqlScriptResult {
|
|
482
|
+
/**
|
|
483
|
+
* The last statement's rows, every value as the text the database wrote
|
|
484
|
+
* for it and `null` for SQL NULL — so a value written back is the value
|
|
485
|
+
* that was read, whatever its type. Keyed by column name: of two columns
|
|
486
|
+
* that share a name, the row holds the last.
|
|
487
|
+
*/
|
|
488
|
+
rows: Record<string, string | null>[];
|
|
489
|
+
/** The last statement's columns, in order. */
|
|
490
|
+
columns: SqlScriptColumn[];
|
|
491
|
+
/** The tables and views {@link SqlScriptColumn.source} names. */
|
|
492
|
+
tables: SqlScriptTable[];
|
|
493
|
+
/** The last statement's command: `SELECT`, `UPDATE`, `CREATE TABLE` … */
|
|
494
|
+
command?: string;
|
|
495
|
+
/**
|
|
496
|
+
* How many rows the last statement returned or changed, when its command
|
|
497
|
+
* reports a count — or, for a {@link truncated} result, how many it
|
|
498
|
+
* returned, of which {@link rows} holds the first.
|
|
499
|
+
*/
|
|
500
|
+
rowCount?: number;
|
|
501
|
+
/**
|
|
502
|
+
* The last statement returned more than a run keeps, and {@link rows}
|
|
503
|
+
* holds only its first rows. The Studio console's door keeps at most
|
|
504
|
+
* 10,000 rows, or 32 Mi characters of values, of one result: a run that
|
|
505
|
+
* held every row of a million-row table took the server down with it.
|
|
506
|
+
*/
|
|
507
|
+
truncated?: boolean;
|
|
508
|
+
/** What the database said while the script ran, in order. */
|
|
509
|
+
notices: SqlScriptNotice[];
|
|
510
|
+
/**
|
|
511
|
+
* The database role the script ran as, when it asked for one — said by
|
|
512
|
+
* the transport that ran it. The role asked for, unless the server has
|
|
513
|
+
* role switching turned off (`DISABLE_DB_ROLE_SWITCHING`) and runs every
|
|
514
|
+
* statement as the connection owner, who is named here instead.
|
|
515
|
+
*/
|
|
516
|
+
effectiveRole?: string;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* A query's result being read a batch at a time — see `SQLAdmin.openSqlCursor`.
|
|
520
|
+
*
|
|
521
|
+
* @group Admin
|
|
522
|
+
*/
|
|
523
|
+
export interface SqlCursor {
|
|
524
|
+
/** The result's column names, in order. */
|
|
525
|
+
readonly columns: string[];
|
|
526
|
+
/**
|
|
527
|
+
* The next rows, each value the text the database wrote for it and `null`
|
|
528
|
+
* for NULL — `null` once there are none left.
|
|
529
|
+
*/
|
|
530
|
+
read(): Promise<(string | null)[][] | null>;
|
|
531
|
+
/** End the read and give the session back. Safe to call more than once. */
|
|
532
|
+
close(): Promise<void>;
|
|
533
|
+
}
|
|
344
534
|
/**
|
|
345
535
|
* Administrative operations for SQL-based databases (PostgreSQL, MySQL, etc.).
|
|
346
536
|
* Used by the SQL Editor, RLS Editor, and schema browser.
|
|
@@ -356,13 +546,60 @@ export interface SQLAdmin {
|
|
|
356
546
|
* before it is reused. For SQL a person wrote (the Studio editor), which
|
|
357
547
|
* may `SET ROLE` and must not leave that on a pooled connection the
|
|
358
548
|
* server's own queries use next.
|
|
549
|
+
*
|
|
550
|
+
* `maxResultBytes` refuses a result whose rows take more than that many
|
|
551
|
+
* bytes, with an error whose `code` is `RESULT_TOO_LARGE`, rather than
|
|
552
|
+
* return it — never a part of it. On a session of its own the read stops
|
|
553
|
+
* there; elsewhere the rows are measured once read. The WebSocket
|
|
554
|
+
* `EXECUTE_SQL` door sets it for every caller.
|
|
359
555
|
*/
|
|
360
556
|
executeSql(sql: string, options?: {
|
|
361
557
|
database?: string;
|
|
362
558
|
role?: string;
|
|
363
559
|
params?: unknown[];
|
|
364
560
|
isolateSession?: boolean;
|
|
561
|
+
maxResultBytes?: number;
|
|
365
562
|
}): Promise<Record<string, unknown>[]>;
|
|
563
|
+
/**
|
|
564
|
+
* Run a script a person wrote — the Studio SQL console — and describe what
|
|
565
|
+
* it returned.
|
|
566
|
+
*
|
|
567
|
+
* On a session of its own, reset afterwards, as `role` for every statement
|
|
568
|
+
* of it. Values come back as the database's text, and each column says
|
|
569
|
+
* which table column it was read from, when the database says so: what
|
|
570
|
+
* the console needs to write a cell back to the row it came from and to
|
|
571
|
+
* no other. A script that leaves a transaction open is refused, and the
|
|
572
|
+
* transaction rolled back: nothing outlives the run to be committed or
|
|
573
|
+
* rolled back by a later one.
|
|
574
|
+
*
|
|
575
|
+
* Aborting `signal` cancels the run: the statement in progress is stopped
|
|
576
|
+
* (`pg_cancel_backend` on a Postgres server; the in-process development
|
|
577
|
+
* database cannot be interrupted, and the run ends on its own), and the
|
|
578
|
+
* promise rejects.
|
|
579
|
+
*/
|
|
580
|
+
runSqlScript?(sql: string, options?: {
|
|
581
|
+
database?: string;
|
|
582
|
+
role?: string;
|
|
583
|
+
signal?: AbortSignal;
|
|
584
|
+
}): Promise<SqlScriptResult>;
|
|
585
|
+
/**
|
|
586
|
+
* Read the whole result of ONE query a person wrote, a batch at a time —
|
|
587
|
+
* the Studio SQL console's "Download full result as CSV", which the
|
|
588
|
+
* console's 10,000-row cap would otherwise leave no way to get.
|
|
589
|
+
*
|
|
590
|
+
* Through a server-side cursor, in a read-only transaction, on a session
|
|
591
|
+
* of its own, as `role`: a write is refused by the database, and a second
|
|
592
|
+
* statement by the protocol. Each batch is read when the previous one has
|
|
593
|
+
* been consumed, so memory holds one batch whatever the result's size;
|
|
594
|
+
* every read runs under the session's `statement_timeout`. The session is
|
|
595
|
+
* reset and returned when the cursor is closed — which the caller must do,
|
|
596
|
+
* on success, failure or a reader that went away.
|
|
597
|
+
*/
|
|
598
|
+
openSqlCursor?(sql: string, options?: {
|
|
599
|
+
database?: string;
|
|
600
|
+
role?: string;
|
|
601
|
+
batchSize?: number;
|
|
602
|
+
}): Promise<SqlCursor>;
|
|
366
603
|
/**
|
|
367
604
|
* Fetch the available databases on the server.
|
|
368
605
|
*/
|
|
@@ -388,6 +625,21 @@ export interface SQLAdmin {
|
|
|
388
625
|
* Fetch the current database name.
|
|
389
626
|
*/
|
|
390
627
|
fetchCurrentDatabase?(): Promise<string | undefined>;
|
|
628
|
+
/**
|
|
629
|
+
* Hold a `LISTEN` on `channel`, on a connection of its own that stays open
|
|
630
|
+
* and comes back after a drop, and call `onNotify` with each payload — what
|
|
631
|
+
* wakes the job worker when another process enqueues, instead of a poll
|
|
632
|
+
* every two seconds.
|
|
633
|
+
*
|
|
634
|
+
* Resolves once listening, with the stop. Rejects when no such connection
|
|
635
|
+
* can be had — an in-process database, a first connect that fails — so the
|
|
636
|
+
* caller can fall back to polling. `onReconnect` is called each time a
|
|
637
|
+
* dropped connection is listening again: whatever was sent meanwhile is
|
|
638
|
+
* lost. `channel` must be a plain identifier.
|
|
639
|
+
*/
|
|
640
|
+
listen?(channel: string, onNotify: (payload: string) => void, options?: {
|
|
641
|
+
onReconnect?: () => void;
|
|
642
|
+
}): Promise<() => Promise<void>>;
|
|
391
643
|
}
|
|
392
644
|
/**
|
|
393
645
|
* Administrative operations for document-based databases (MongoDB, Firestore, etc.).
|
|
@@ -433,6 +685,12 @@ export interface SchemaAdmin {
|
|
|
433
685
|
export interface BranchInfo {
|
|
434
686
|
/** Branch name (without prefix). */
|
|
435
687
|
name: string;
|
|
688
|
+
/**
|
|
689
|
+
* The PostgreSQL database the branch is — what to connect to, and what to
|
|
690
|
+
* name as the source when copying it. As the branch's record says, never
|
|
691
|
+
* derived from `name` again.
|
|
692
|
+
*/
|
|
693
|
+
database: string;
|
|
436
694
|
/** The database this branch was created from. */
|
|
437
695
|
parentDatabase: string;
|
|
438
696
|
/** When the branch was created. */
|
|
@@ -598,6 +856,15 @@ export interface DataRateLimitCaller {
|
|
|
598
856
|
* the caller by address at the anonymous allowance.
|
|
599
857
|
*/
|
|
600
858
|
uid?: string;
|
|
859
|
+
/**
|
|
860
|
+
* The API key the connection authenticated with. Its frames count in the
|
|
861
|
+
* key's own bucket at the key's own `rate_limit`, the bucket its HTTP
|
|
862
|
+
* requests count in, rather than as `uid`.
|
|
863
|
+
*/
|
|
864
|
+
apiKey?: {
|
|
865
|
+
id: string;
|
|
866
|
+
rate_limit: number | null;
|
|
867
|
+
};
|
|
601
868
|
/**
|
|
602
869
|
* A header of the request that opened the connection, by lower-case name:
|
|
603
870
|
* the proxy headers an address is read from when proxies are declared.
|
|
@@ -607,11 +874,48 @@ export interface DataRateLimitCaller {
|
|
|
607
874
|
socketAddress?: string;
|
|
608
875
|
}
|
|
609
876
|
/**
|
|
610
|
-
*
|
|
611
|
-
*
|
|
877
|
+
* What the realtime socket shares with the HTTP data API: its request limits,
|
|
878
|
+
* so a frame carries the ones an HTTP request to the same rows does, and its
|
|
879
|
+
* API-key verification, so a key means the same thing on both.
|
|
612
880
|
* @group Backend
|
|
613
881
|
*/
|
|
614
|
-
export interface
|
|
882
|
+
export interface RealtimeSocketOptions {
|
|
883
|
+
/**
|
|
884
|
+
* Verify an `rk_` API key presented to `AUTHENTICATE`: the identity it acts
|
|
885
|
+
* as and the scopes it holds, or why it does not authenticate. Absent when
|
|
886
|
+
* the deployment has no API-key store, and then keys cannot authenticate
|
|
887
|
+
* the socket.
|
|
888
|
+
*/
|
|
889
|
+
resolveApiKey?: (token: string) => Promise<{
|
|
890
|
+
uid: string;
|
|
891
|
+
roles: string[];
|
|
892
|
+
scopes: string[];
|
|
893
|
+
/** The key itself: its id and `rate_limit` decide which rate-limit bucket its frames count in. */
|
|
894
|
+
apiKey?: {
|
|
895
|
+
id: string;
|
|
896
|
+
rate_limit: number | null;
|
|
897
|
+
};
|
|
898
|
+
} | {
|
|
899
|
+
message: string;
|
|
900
|
+
}>;
|
|
901
|
+
/**
|
|
902
|
+
* Verify a session token presented to `AUTHENTICATE` with the backend's own
|
|
903
|
+
* keys, when the socket has no auth adapter to ask: who it names, or null
|
|
904
|
+
* when it does not verify. The server passes its backend's; absent, the
|
|
905
|
+
* driver falls back to the process default.
|
|
906
|
+
*/
|
|
907
|
+
verifyAccessToken?: (token: string) => Promise<{
|
|
908
|
+
uid: string;
|
|
909
|
+
roles?: string[];
|
|
910
|
+
isAnonymous?: boolean;
|
|
911
|
+
claims?: Record<string, unknown>;
|
|
912
|
+
} | null>;
|
|
913
|
+
/**
|
|
914
|
+
* The backend's access model — what a session's roles hold on the socket's
|
|
915
|
+
* admin frames. The server passes its backend's; absent, the driver falls
|
|
916
|
+
* back to the process default.
|
|
917
|
+
*/
|
|
918
|
+
accessModel?: AccessModel;
|
|
615
919
|
/**
|
|
616
920
|
* The largest frame accepted, in bytes — the data API's body limit. `0` or
|
|
617
921
|
* less for none. Defaults to the server's default body limit.
|
|
@@ -626,6 +930,36 @@ export interface RealtimeSocketLimits {
|
|
|
626
930
|
allowed: boolean;
|
|
627
931
|
retryAfterMs: number;
|
|
628
932
|
} | null>;
|
|
933
|
+
/**
|
|
934
|
+
* How often a socket that only listens has its identity re-read, in ms
|
|
935
|
+
* (default 30 000). A socket that sends frames is re-checked before each
|
|
936
|
+
* one; this bounds how long a subscription keeps receiving rows as an
|
|
937
|
+
* identity that has since signed out, been revoked, demoted or deleted.
|
|
938
|
+
*/
|
|
939
|
+
identityRecheckIntervalMs?: number;
|
|
940
|
+
/**
|
|
941
|
+
* How often a socket that asked for heartbeats (`?rebase_caps=heartbeat`)
|
|
942
|
+
* is sent one, in ms (default 30 000). The SDK redials after two missed.
|
|
943
|
+
*/
|
|
944
|
+
heartbeatIntervalMs?: number;
|
|
945
|
+
/**
|
|
946
|
+
* How many sockets one identity may hold open on this server; the next
|
|
947
|
+
* one's `AUTHENTICATE` is refused with `TOO_MANY_SOCKETS` and the socket
|
|
948
|
+
* closed (4002). Unset for no ceiling. See `realtime.maxSocketsPerUser`.
|
|
949
|
+
*/
|
|
950
|
+
maxSocketsPerUser?: number;
|
|
951
|
+
/**
|
|
952
|
+
* The URL path the socket accepts upgrades on (default `/`). The SDK dials
|
|
953
|
+
* its `baseUrl` with no extra segment, so for a server mounted at `/api`
|
|
954
|
+
* this is `/`, and for one at `/app/api` it is `/app`. A trailing `/` is
|
|
955
|
+
* ignored, and so is the query string.
|
|
956
|
+
*
|
|
957
|
+
* An upgrade to any other path is not this socket's: it is left untouched
|
|
958
|
+
* for another `upgrade` listener on the same `http.Server` — a host app's
|
|
959
|
+
* own WebSocket server — or, when the socket's listener is the only one,
|
|
960
|
+
* answered `404` and closed, so the client is not left hanging.
|
|
961
|
+
*/
|
|
962
|
+
path?: string;
|
|
629
963
|
}
|
|
630
964
|
/**
|
|
631
965
|
* A `BackendBootstrapper` encapsulates all driver-specific initialization logic.
|
|
@@ -703,8 +1037,11 @@ export interface BackendBootstrapper {
|
|
|
703
1037
|
*/
|
|
704
1038
|
initializeRealtime?(config: unknown, driverResult: InitializedDriver): Promise<RealtimeProvider | undefined>;
|
|
705
1039
|
/**
|
|
706
|
-
*
|
|
707
|
-
*
|
|
1040
|
+
* Never called: the server mounts no route on a bootstrapper's behalf. A
|
|
1041
|
+
* driver that needs HTTP routes exports a route factory, and the app
|
|
1042
|
+
* mounts it where it chooses.
|
|
1043
|
+
*
|
|
1044
|
+
* @deprecated Never called. Will be removed in a future release.
|
|
708
1045
|
*/
|
|
709
1046
|
mountRoutes?(app: unknown, basePath: string, driverResult: InitializedDriver): void;
|
|
710
1047
|
/**
|
|
@@ -832,7 +1169,7 @@ export interface BackendBootstrapper {
|
|
|
832
1169
|
/**
|
|
833
1170
|
* Initialize WebSocket server for realtime operations.
|
|
834
1171
|
*/
|
|
835
|
-
initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import("../controllers/data_driver.js").DataDriver, config?: unknown, authAdapter?: AuthAdapter, limits?:
|
|
1172
|
+
initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import("../controllers/data_driver.js").DataDriver, config?: unknown, authAdapter?: AuthAdapter, limits?: RealtimeSocketOptions): Promise<void> | void;
|
|
836
1173
|
}
|
|
837
1174
|
/**
|
|
838
1175
|
* Result of `BackendBootstrapper.initializeDriver()`.
|
|
@@ -852,11 +1189,23 @@ export interface InitializedDriver {
|
|
|
852
1189
|
* instead of collections loaded from config files.
|
|
853
1190
|
*/
|
|
854
1191
|
collections?: import("./collections.js").CollectionConfig[];
|
|
1192
|
+
/**
|
|
1193
|
+
* Tables the driver found while deriving {@link collections} and did not
|
|
1194
|
+
* serve, because row-level security is disabled on them and so they have
|
|
1195
|
+
* no authorization model (`baas.unprotectedTables` left at `"exclude"`).
|
|
1196
|
+
*
|
|
1197
|
+
* The server names them when it has nothing to serve: "the database has
|
|
1198
|
+
* no tables" is untrue of a database whose tables were all skipped.
|
|
1199
|
+
*/
|
|
1200
|
+
unprotectedTables?: {
|
|
1201
|
+
schema: string;
|
|
1202
|
+
table: string;
|
|
1203
|
+
}[];
|
|
855
1204
|
/** The underlying database connection (for lifecycle management). */
|
|
856
1205
|
connection?: DatabaseConnection;
|
|
857
1206
|
/**
|
|
858
1207
|
* Opaque handle that the bootstrapper can use in subsequent hooks
|
|
859
|
-
* (e.g., `initializeAuth`, `
|
|
1208
|
+
* (e.g., `initializeAuth`, `getAdmin`) to access driver internals.
|
|
860
1209
|
* Not used by the coordinator.
|
|
861
1210
|
*/
|
|
862
1211
|
internals?: unknown;
|
|
@@ -868,8 +1217,6 @@ export interface InitializedDriver {
|
|
|
868
1217
|
export interface BootstrappedAuth {
|
|
869
1218
|
/** User management service. */
|
|
870
1219
|
userService: unknown;
|
|
871
|
-
/** Role management service (optional, roles are now simple strings). */
|
|
872
|
-
roleService?: unknown;
|
|
873
1220
|
/** Email service (optional). */
|
|
874
1221
|
emailService?: unknown;
|
|
875
1222
|
/** Combined Auth Repository for unified token and user management. */
|
package/dist/types/backup.d.ts
CHANGED
|
@@ -25,3 +25,105 @@ export interface BackupInfo {
|
|
|
25
25
|
*/
|
|
26
26
|
globalsKey?: string;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* How one run of the scheduled backup went, read from the cron's run history.
|
|
30
|
+
*/
|
|
31
|
+
export interface BackupRunOutcome {
|
|
32
|
+
/** ISO timestamp the run started. */
|
|
33
|
+
startedAt: string;
|
|
34
|
+
/** ISO timestamp the run ended. */
|
|
35
|
+
finishedAt: string;
|
|
36
|
+
/** Whether the run produced a backup. */
|
|
37
|
+
success: boolean;
|
|
38
|
+
/** Why it did not, when it failed — e.g. `Could not find the 'pg_dump' binary.` */
|
|
39
|
+
error?: string;
|
|
40
|
+
/** True when someone triggered the run by hand rather than the schedule. */
|
|
41
|
+
manual: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The deployment's scheduled backup job — the cron that default-exports
|
|
45
|
+
* `createBackupCron` — and the outcome of its last run.
|
|
46
|
+
*
|
|
47
|
+
* Shown by the Backups panel so a backup that fails every night is visible
|
|
48
|
+
* where the backups are listed, rather than only in the cron history.
|
|
49
|
+
*/
|
|
50
|
+
export interface BackupScheduleStatus {
|
|
51
|
+
/** The cron job's id, which is its file's name. */
|
|
52
|
+
jobId: string;
|
|
53
|
+
/** The job's display name. */
|
|
54
|
+
name: string;
|
|
55
|
+
/** Its cron expression. */
|
|
56
|
+
schedule: string;
|
|
57
|
+
/** False when the job is paused (or declared `enabled: false`), or refused. */
|
|
58
|
+
enabled: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* True when the job is off because its own definition says
|
|
61
|
+
* `enabled: false` — the documented backup cron file exports it that way
|
|
62
|
+
* while `BACKUP_SCHEDULE` is unset — and not because someone paused it.
|
|
63
|
+
* Resuming it in Cron Jobs would run that definition as written.
|
|
64
|
+
*/
|
|
65
|
+
disabledInCode?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Why the scheduler refused the job — an invalid schedule, timezone or
|
|
68
|
+
* timeout. A refused job is not registered and never runs; the cron file
|
|
69
|
+
* has to change.
|
|
70
|
+
*/
|
|
71
|
+
refused?: string;
|
|
72
|
+
/** ISO timestamp of the next scheduled run, when one is armed. */
|
|
73
|
+
nextRunAt?: string;
|
|
74
|
+
/**
|
|
75
|
+
* The most recent scheduled run, absent when the schedule has never run
|
|
76
|
+
* it — or when its run history could not be read, which
|
|
77
|
+
* {@link historyError} says. A run someone started by hand is not one:
|
|
78
|
+
* see {@link lastManualRun}.
|
|
79
|
+
*/
|
|
80
|
+
lastRun?: BackupRunOutcome;
|
|
81
|
+
/** A run started by hand ("Run Now") since {@link lastRun}, when there is one. */
|
|
82
|
+
lastManualRun?: BackupRunOutcome;
|
|
83
|
+
/**
|
|
84
|
+
* Why the job's run history could not be read. Whether it ran, and how it
|
|
85
|
+
* went, is then unknown: `lastRun` is absent for that reason, not because
|
|
86
|
+
* the job never ran.
|
|
87
|
+
*/
|
|
88
|
+
historyError?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A short-lived link to one backup's bytes, from `POST /admin/backups/download-url`.
|
|
92
|
+
*
|
|
93
|
+
* The URL needs no `Authorization` header — the token in it stands in for one,
|
|
94
|
+
* for this backup only — so a browser can be sent to it and stream the dump to
|
|
95
|
+
* disk instead of holding it in the page.
|
|
96
|
+
*/
|
|
97
|
+
export interface BackupDownloadLink {
|
|
98
|
+
/**
|
|
99
|
+
* `…/admin/backups/download?key=…&token=…`. The server answers it as a
|
|
100
|
+
* path on itself; the SDK's `downloadUrl()` answers it absolute, on the
|
|
101
|
+
* client's own base URL.
|
|
102
|
+
*/
|
|
103
|
+
url: string;
|
|
104
|
+
/** The token in {@link url}, on its own. */
|
|
105
|
+
token: string;
|
|
106
|
+
/** Seconds until the link stops working (60). */
|
|
107
|
+
expiresIn: number;
|
|
108
|
+
}
|
|
109
|
+
/** What the backup listing (`GET /admin/backups`) answers. */
|
|
110
|
+
export interface BackupListing {
|
|
111
|
+
/** Backups at the destination, newest first. */
|
|
112
|
+
backups: BackupInfo[];
|
|
113
|
+
/** The kind of destination they were read from. */
|
|
114
|
+
destinationKind: BackupDestinationKind;
|
|
115
|
+
/** False when `BACKUP_DESTINATION` is unset. */
|
|
116
|
+
configured: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* The scheduled backup job, or `null` when the deployment registers none.
|
|
119
|
+
* Absent from a server that predates the field.
|
|
120
|
+
*/
|
|
121
|
+
schedule?: BackupScheduleStatus | null;
|
|
122
|
+
/**
|
|
123
|
+
* True when the destination is a local path and the scheduled backup runs
|
|
124
|
+
* in another process (the worker of a split deployment). The backups
|
|
125
|
+
* listed are the ones on this process's disk; the scheduled runs write to
|
|
126
|
+
* theirs, which is the same directory only when both mount it.
|
|
127
|
+
*/
|
|
128
|
+
localDiskOfThisProcess?: boolean;
|
|
129
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** One change to a collection. `path` is a list of object keys. */
|
|
2
|
+
export type CollectionPatchOp = {
|
|
3
|
+
op: "set";
|
|
4
|
+
path: string[];
|
|
5
|
+
value: unknown;
|
|
6
|
+
} | {
|
|
7
|
+
op: "remove";
|
|
8
|
+
path: string[];
|
|
9
|
+
};
|
|
10
|
+
/** @group Models */
|
|
11
|
+
export type CollectionPatch = CollectionPatchOp[];
|
|
12
|
+
/**
|
|
13
|
+
* Keys the runtime adds to a collection that must never be written into its
|
|
14
|
+
* source. `resolvedRelation` is the registry's resolved form of a relation; a
|
|
15
|
+
* file holding one does not type-check (`target` is missing from it).
|
|
16
|
+
*/
|
|
17
|
+
export declare const RUNTIME_ONLY_COLLECTION_KEYS: readonly string[];
|
|
18
|
+
/** A JSON value as JSON would carry it: functions, `undefined` and symbols dropped. */
|
|
19
|
+
export declare function toCollectionJson(value: unknown): unknown;
|
|
20
|
+
/**
|
|
21
|
+
* The operations that take `before` to `after`, both JSON values.
|
|
22
|
+
*
|
|
23
|
+
* Objects are compared key by key; anything else that differs — a primitive,
|
|
24
|
+
* an array, a change of kind — is set whole.
|
|
25
|
+
*/
|
|
26
|
+
export declare function diffJsonValues(before: unknown, after: unknown, path?: string[]): CollectionPatch;
|
|
27
|
+
/**
|
|
28
|
+
* The patch, with every flat presentation key moved into its `admin` block.
|
|
29
|
+
*
|
|
30
|
+
* The panel edits a flat view model — `icon` beside `name`, a property's
|
|
31
|
+
* `readOnly` beside its `type` — while the file keeps them under `admin`. The
|
|
32
|
+
* difference is taken on the flat model, because that is where a cleared field
|
|
33
|
+
* shows up as a removed key (the `admin` copy the model was loaded with still
|
|
34
|
+
* holds the old value), and moved here.
|
|
35
|
+
*
|
|
36
|
+
* The flat value wins over the `admin` copy, as in {@link nestAdminKeysOf}:
|
|
37
|
+
* operations that were already under `admin` are ordered first, so the flat
|
|
38
|
+
* one — what the form just wrote — is applied last.
|
|
39
|
+
*/
|
|
40
|
+
export declare function nestCollectionPatchPaths(patch: CollectionPatch): CollectionPatch;
|
|
41
|
+
/**
|
|
42
|
+
* The patch that takes the collection the editor loaded to the one it is
|
|
43
|
+
* saving, in the authoring shape. Empty when nothing changed.
|
|
44
|
+
*
|
|
45
|
+
* Both sides go through JSON first, so whatever JSON cannot carry — a
|
|
46
|
+
* function, a value it drops — is equally absent from both and never appears
|
|
47
|
+
* as a change.
|
|
48
|
+
*/
|
|
49
|
+
export declare function diffCollections(loaded: unknown, saving: unknown): CollectionPatch;
|
|
50
|
+
/**
|
|
51
|
+
* Why a patch may not be applied, or an empty list.
|
|
52
|
+
*
|
|
53
|
+
* Checked by every door that accepts one: a path is a list of non-empty object
|
|
54
|
+
* keys that cannot reach a prototype, and no runtime-only key may be written.
|
|
55
|
+
*/
|
|
56
|
+
export declare function collectionPatchProblems(patch: unknown): string[];
|
|
57
|
+
/**
|
|
58
|
+
* The first runtime-only key (see {@link RUNTIME_ONLY_COLLECTION_KEYS}) found
|
|
59
|
+
* anywhere in a value, or `undefined`. For the doors that take a whole
|
|
60
|
+
* collection rather than a patch.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runtimeOnlyKeyIn(value: unknown): string | undefined;
|
|
63
|
+
/** A patch every door may apply: {@link collectionPatchProblems} found nothing. */
|
|
64
|
+
export declare function isCollectionPatch(patch: unknown): patch is CollectionPatch;
|
|
65
|
+
/**
|
|
66
|
+
* `target` with the patch applied, copying only what it changes.
|
|
67
|
+
*
|
|
68
|
+
* Everything the patch does not reach is shared with `target` by reference —
|
|
69
|
+
* functions, thunks and all — which is what lets a planner see a relation's
|
|
70
|
+
* `target()` on the patched collection exactly as it was. Intermediate objects
|
|
71
|
+
* a `set` needs are created; a `remove` of a key that is not there is nothing
|
|
72
|
+
* to do.
|
|
73
|
+
*/
|
|
74
|
+
export declare function applyCollectionPatch<T>(target: T, patch: CollectionPatch): T;
|
|
@@ -4,6 +4,7 @@ import type { User } from "../users/index.js";
|
|
|
4
4
|
import type { EmailSendResult } from "../controllers/email.js";
|
|
5
5
|
import type { Relation } from "./relations.js";
|
|
6
6
|
import type { SecurityRule } from "./security_rules.js";
|
|
7
|
+
import type { RoleDefinition, ScopeDefinition } from "./scopes.js";
|
|
7
8
|
import type { SearchConfig } from "./search.js";
|
|
8
9
|
import type { CollectionIndex } from "./indexes.js";
|
|
9
10
|
import type { CollectionTenantConfig } from "./tenancy.js";
|
|
@@ -614,6 +615,28 @@ export type InferCollectionConfigType<S extends CollectionConfig> = S extends Co
|
|
|
614
615
|
export interface AuthCollectionConfig {
|
|
615
616
|
/** Set to true to mark this collection as the authentication collection. */
|
|
616
617
|
enabled: boolean;
|
|
618
|
+
/**
|
|
619
|
+
* The app's roles and the admin-plane scopes each holds.
|
|
620
|
+
*
|
|
621
|
+
* `admin` is built in — it holds every scope — and cannot be declared. A
|
|
622
|
+
* role used only by RLS policies needs no entry here. See
|
|
623
|
+
* {@link RoleDefinition}.
|
|
624
|
+
*/
|
|
625
|
+
roles?: Record<string, RoleDefinition>;
|
|
626
|
+
/**
|
|
627
|
+
* Scopes the app defines for its own operations, named `resource:action`
|
|
628
|
+
* like the built-in ones and checked with `requireScope` in a function.
|
|
629
|
+
* Every signed-in person holds them; they exist so a key can be narrowed
|
|
630
|
+
* to one action. See {@link ScopeDefinition}.
|
|
631
|
+
*/
|
|
632
|
+
scopes?: Record<string, ScopeDefinition>;
|
|
633
|
+
/**
|
|
634
|
+
* Let every signed-in account mint personal API keys at
|
|
635
|
+
* `/api/auth/keys`. A personal key acts as its owner and can never hold
|
|
636
|
+
* a scope its owner does not. Off by default: each one is a long-lived
|
|
637
|
+
* credential for the account, and an app opts into handing those out.
|
|
638
|
+
*/
|
|
639
|
+
personalKeys?: boolean;
|
|
617
640
|
/**
|
|
618
641
|
* Called when an admin creates a user, through the collection REST API or
|
|
619
642
|
* `POST /admin/users`.
|