@rebasepro/types 0.25.0 → 0.26.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 +18 -0
- package/dist/controllers/client.d.ts +32 -1
- package/dist/controllers/data_driver.d.ts +22 -0
- package/dist/index.es.js +122 -1
- package/dist/index.es.js.map +1 -1
- package/dist/types/api_keys.d.ts +20 -0
- package/dist/types/auth_adapter.d.ts +83 -0
- package/dist/types/backend.d.ts +275 -1
- package/dist/types/properties.d.ts +3 -3
- package/dist/types/relations.d.ts +17 -6
- package/dist/types/scopes.d.ts +14 -0
- package/dist/users/user.d.ts +8 -0
- package/package.json +1 -4
package/dist/types/api_keys.d.ts
CHANGED
|
@@ -24,6 +24,26 @@ import type { ScopeSummary } from "./scopes.js";
|
|
|
24
24
|
* @group Models
|
|
25
25
|
*/
|
|
26
26
|
export type ApiKeyKind = "service" | "personal";
|
|
27
|
+
/**
|
|
28
|
+
* The API key a request authenticated with, as server-side code sees it:
|
|
29
|
+
* `context.credential` in a collection callback, and `credential` on the
|
|
30
|
+
* identity the request's driver is scoped to.
|
|
31
|
+
*
|
|
32
|
+
* It tells a write made with a key from the same person's own session. A
|
|
33
|
+
* personal key acts as its owner, so `context.user` is the owner either way;
|
|
34
|
+
* this is what says "the CI token did it" rather than "Ada did it". Never the
|
|
35
|
+
* secret: only what the key list shows.
|
|
36
|
+
*
|
|
37
|
+
* @group Models
|
|
38
|
+
*/
|
|
39
|
+
export interface CallerCredential {
|
|
40
|
+
/** `"personal"` acts as its owner (`context.user`); `"service"` as the key itself. */
|
|
41
|
+
kind: ApiKeyKind;
|
|
42
|
+
/** The key's id, as `GET /api/auth/keys` lists it. */
|
|
43
|
+
id: string;
|
|
44
|
+
/** The name the key was given when it was created. */
|
|
45
|
+
name: string;
|
|
46
|
+
}
|
|
27
47
|
/**
|
|
28
48
|
* An API key with the secret masked — what list / get / update return.
|
|
29
49
|
* @group Models
|
|
@@ -65,6 +65,89 @@ export interface MountableRouter {
|
|
|
65
65
|
* @group Auth
|
|
66
66
|
*/
|
|
67
67
|
export declare const IMPERSONATE_HEADER = "x-rebase-impersonate";
|
|
68
|
+
/**
|
|
69
|
+
* The request header that asks for a data-plane request to run as a role —
|
|
70
|
+
* the RLS simulator's "view as". Alone it runs as a signed-in holder of that
|
|
71
|
+
* role who owns no rows; with {@link SIMULATE_USER_ID_HEADER} it runs as that
|
|
72
|
+
* uid holding that role, whether or not such an account exists.
|
|
73
|
+
*
|
|
74
|
+
* `anon` (or `anonymous`) runs as a caller with no session at all.
|
|
75
|
+
*
|
|
76
|
+
* Like {@link IMPERSONATE_HEADER}, only a signed-in administrator's own session
|
|
77
|
+
* may send it; anyone else is refused with 403, never answered as themselves.
|
|
78
|
+
*
|
|
79
|
+
* @group Auth
|
|
80
|
+
*/
|
|
81
|
+
export declare const SIMULATE_ROLE_HEADER = "x-rebase-simulate-role";
|
|
82
|
+
/**
|
|
83
|
+
* The uid a simulated request runs as. With {@link SIMULATE_ROLE_HEADER} it is
|
|
84
|
+
* a hypothetical — "u_1 holding customer" — and need not name an account;
|
|
85
|
+
* without it, the uid must be an active user and runs with their roles now.
|
|
86
|
+
*
|
|
87
|
+
* @group Auth
|
|
88
|
+
*/
|
|
89
|
+
export declare const SIMULATE_USER_ID_HEADER = "x-rebase-simulate-user-id";
|
|
90
|
+
/**
|
|
91
|
+
* The id of a service API key a simulated request runs as: the key's identity,
|
|
92
|
+
* its RLS roles and its scopes, exactly as a request presenting the key would.
|
|
93
|
+
* Excludes the other two simulation headers.
|
|
94
|
+
*
|
|
95
|
+
* @group Auth
|
|
96
|
+
*/
|
|
97
|
+
export declare const SIMULATE_API_KEY_ID_HEADER = "x-rebase-simulate-api-key-id";
|
|
98
|
+
/**
|
|
99
|
+
* The response header naming what a simulated request ran as:
|
|
100
|
+
* `role=<role>;sub=<uid>;masked_columns=<a,b>`, plus `api_key=<id>` and
|
|
101
|
+
* `collection=<slug>` when they apply. Every value is URI-encoded. Read it
|
|
102
|
+
* with {@link parseSimulatedContext}.
|
|
103
|
+
*
|
|
104
|
+
* @group Auth
|
|
105
|
+
*/
|
|
106
|
+
export declare const SIMULATED_CONTEXT_HEADER = "x-rebase-simulated-context";
|
|
107
|
+
/**
|
|
108
|
+
* What an administrator asks a request to run as. Exactly one of these
|
|
109
|
+
* shapes is honoured: a role (optionally with a uid), a uid alone (an existing
|
|
110
|
+
* user, with their roles), or an API key id alone.
|
|
111
|
+
*
|
|
112
|
+
* @group Auth
|
|
113
|
+
*/
|
|
114
|
+
export interface AccessSimulation {
|
|
115
|
+
role?: string;
|
|
116
|
+
userId?: string;
|
|
117
|
+
apiKeyId?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The request headers for an {@link AccessSimulation}. Empty when it asks for
|
|
121
|
+
* nothing, so spreading it into a header set is always safe.
|
|
122
|
+
*
|
|
123
|
+
* @group Auth
|
|
124
|
+
*/
|
|
125
|
+
export declare function simulationHeaders(simulation: AccessSimulation | null | undefined): Record<string, string>;
|
|
126
|
+
/**
|
|
127
|
+
* What {@link SIMULATED_CONTEXT_HEADER} says a request ran as.
|
|
128
|
+
*
|
|
129
|
+
* @group Auth
|
|
130
|
+
*/
|
|
131
|
+
export interface SimulatedContext {
|
|
132
|
+
role: string;
|
|
133
|
+
sub: string;
|
|
134
|
+
maskedColumns: string[];
|
|
135
|
+
apiKeyId?: string;
|
|
136
|
+
collection?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Write a {@link SimulatedContext} as the header value.
|
|
140
|
+
*
|
|
141
|
+
* @group Auth
|
|
142
|
+
*/
|
|
143
|
+
export declare function formatSimulatedContext(context: SimulatedContext): string;
|
|
144
|
+
/**
|
|
145
|
+
* Read {@link SIMULATED_CONTEXT_HEADER}. `undefined` for an absent header or one
|
|
146
|
+
* missing `role` or `sub`.
|
|
147
|
+
*
|
|
148
|
+
* @group Auth
|
|
149
|
+
*/
|
|
150
|
+
export declare function parseSimulatedContext(value: string | null | undefined): SimulatedContext | undefined;
|
|
68
151
|
/**
|
|
69
152
|
* The normalized user object returned by `AuthAdapter.verifyRequest()`.
|
|
70
153
|
*
|
package/dist/types/backend.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ 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
9
|
import type { AccessModel } from "./scopes.js";
|
|
10
|
+
import type { ApiKeyKind } from "./api_keys.js";
|
|
10
11
|
/**
|
|
11
12
|
* Abstract database connection interface.
|
|
12
13
|
* Represents a connection to any database system.
|
|
@@ -353,6 +354,14 @@ export interface RealtimeProvider {
|
|
|
353
354
|
* still look live, so it is reported rather than inferred.
|
|
354
355
|
*/
|
|
355
356
|
health?(): RealtimeListenerHealth[];
|
|
357
|
+
/**
|
|
358
|
+
* Run the provider's own background reads — the refetches a change
|
|
359
|
+
* schedules, whatever announced it (a write here, change capture, another
|
|
360
|
+
* instance) — through `run`. The server passes one that enters the backend
|
|
361
|
+
* owning this provider, so a hook such a read reaches sees that backend as
|
|
362
|
+
* `rebase`. Without it they run in the context of whatever scheduled them.
|
|
363
|
+
*/
|
|
364
|
+
setScopeRunner?(run: <T>(fn: () => T) => T): void;
|
|
356
365
|
}
|
|
357
366
|
/**
|
|
358
367
|
* One long-lived realtime connection, as `/health` reports it.
|
|
@@ -697,6 +706,13 @@ export interface BranchInfo {
|
|
|
697
706
|
createdAt: Date;
|
|
698
707
|
/** Size in bytes, if available from the server. */
|
|
699
708
|
sizeBytes?: number;
|
|
709
|
+
/**
|
|
710
|
+
* The transaction that created the branch database, recorded when it was
|
|
711
|
+
* made: the fork point a branch diff tells the two sides' writes apart by.
|
|
712
|
+
* Absent for a branch made before it was recorded, or by a server that
|
|
713
|
+
* does not record it.
|
|
714
|
+
*/
|
|
715
|
+
forkXid?: string;
|
|
700
716
|
}
|
|
701
717
|
/**
|
|
702
718
|
* Administrative operations for database branching.
|
|
@@ -715,6 +731,250 @@ export interface BranchAdmin {
|
|
|
715
731
|
listBranches(): Promise<BranchInfo[]>;
|
|
716
732
|
/** Get info about a specific branch. */
|
|
717
733
|
getBranchInfo(name: string): Promise<BranchInfo | undefined>;
|
|
734
|
+
/**
|
|
735
|
+
* What the branch changed, against the database it was made from: its
|
|
736
|
+
* tables, columns, constraints, indexes, triggers, row-level-security
|
|
737
|
+
* policies, enum types, views and functions, and per table the rows it
|
|
738
|
+
* inserted, updated and deleted. Reads only.
|
|
739
|
+
*/
|
|
740
|
+
diffBranch?(name: string, options?: BranchDiffOptions): Promise<BranchDiff>;
|
|
741
|
+
/**
|
|
742
|
+
* Apply the rows the branch changed to the database it was made from. See
|
|
743
|
+
* {@link BranchMergeOptions} for what wins, and when nothing is written.
|
|
744
|
+
*/
|
|
745
|
+
mergeBranch?(name: string, options: BranchMergeOptions): Promise<BranchMergeResult>;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* What {@link BranchAdmin.diffBranch} compares.
|
|
749
|
+
* @group Admin
|
|
750
|
+
*/
|
|
751
|
+
export interface BranchDiffOptions {
|
|
752
|
+
/** Rows shown per table, across every kind of change. Default 100, at most 1,000. */
|
|
753
|
+
sampleLimit?: number;
|
|
754
|
+
/** Schemas to compare. Default: every schema but the system's, without Rebase's own tables. */
|
|
755
|
+
schemas?: string[];
|
|
756
|
+
/**
|
|
757
|
+
* Rows a table may hold, on either side, for its rows to be matched one by
|
|
758
|
+
* one. A larger table that differs is reported with its row counts only,
|
|
759
|
+
* and cannot be merged. Default 100,000.
|
|
760
|
+
*/
|
|
761
|
+
maxRowsPerTable?: number;
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* One change to the schema: a table, a column, a policy, a table's row-level
|
|
765
|
+
* security, a constraint (unique, foreign key, check, exclusion), an index, a
|
|
766
|
+
* trigger — or, outside any table, an enum type, a view or a function.
|
|
767
|
+
* @group Admin
|
|
768
|
+
*/
|
|
769
|
+
export interface BranchSchemaChange {
|
|
770
|
+
object: "table" | "column" | "policy" | "rls" | "constraint" | "index" | "trigger" | "enum" | "view" | "function";
|
|
771
|
+
change: "added" | "dropped" | "altered";
|
|
772
|
+
schema: string;
|
|
773
|
+
/**
|
|
774
|
+
* The table the change is on — or, for an enum, a view or a function, the
|
|
775
|
+
* object's own name (a function's with its argument types).
|
|
776
|
+
*/
|
|
777
|
+
table: string;
|
|
778
|
+
/** The column's, policy's, constraint's, index's or trigger's name. */
|
|
779
|
+
name?: string;
|
|
780
|
+
/** The definition on the target, as SQL. Absent for an addition. */
|
|
781
|
+
before?: string;
|
|
782
|
+
/** The definition on the branch, as SQL. Absent for a drop. */
|
|
783
|
+
after?: string;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Why the changed rows of a table cannot be merged.
|
|
787
|
+
* @group Admin
|
|
788
|
+
*/
|
|
789
|
+
export interface BranchMergeBlock {
|
|
790
|
+
/**
|
|
791
|
+
* `TABLE_REWRITTEN`: one side wrote every row anew since the branch was
|
|
792
|
+
* made (a column type change, a volatile default, `VACUUM FULL`), so which
|
|
793
|
+
* side changed which row can no longer be told.
|
|
794
|
+
*/
|
|
795
|
+
code: "TABLE_ADDED" | "TABLE_DROPPED" | "COLUMNS_DIFFER" | "PRIMARY_KEY_DIFFERS" | "NO_PRIMARY_KEY" | "TOO_LARGE" | "TABLE_REWRITTEN";
|
|
796
|
+
message: string;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* One row the branch changed, or one both sides changed.
|
|
800
|
+
*
|
|
801
|
+
* Values are the text the database writes for them, `null` for SQL NULL, so a
|
|
802
|
+
* `bigint` or a `numeric` reads exactly as it is stored — except a column named
|
|
803
|
+
* like a credential (`password_hash`, `*_token`, `*secret*`, `*_hash`), whose
|
|
804
|
+
* value reads `"[redacted]"`. It is still listed in {@link changedColumns}.
|
|
805
|
+
*
|
|
806
|
+
* A `"conflict"` with no {@link after} is a row the branch deleted that rows
|
|
807
|
+
* the target wrote since the branch was made still reference — see
|
|
808
|
+
* {@link BranchTableDataDiff.referencedBy}.
|
|
809
|
+
* @group Admin
|
|
810
|
+
*/
|
|
811
|
+
export interface BranchRowChange {
|
|
812
|
+
change: "inserted" | "updated" | "deleted" | "conflict";
|
|
813
|
+
/** The primary key, as a JSON array of its columns' values. */
|
|
814
|
+
key: string;
|
|
815
|
+
/** The row on the target. Absent for an insert. */
|
|
816
|
+
before?: Record<string, string | null>;
|
|
817
|
+
/** The row on the branch. Absent for a delete. */
|
|
818
|
+
after?: Record<string, string | null>;
|
|
819
|
+
/** The columns whose values differ, for an update or a conflict. */
|
|
820
|
+
changedColumns?: string[];
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* The rows of one table that differ between the branch and its target.
|
|
824
|
+
* @group Admin
|
|
825
|
+
*/
|
|
826
|
+
export interface BranchTableDataDiff {
|
|
827
|
+
schema: string;
|
|
828
|
+
table: string;
|
|
829
|
+
/** The collection whose table this is, when the server knows one. */
|
|
830
|
+
collection?: string;
|
|
831
|
+
primaryKey: string[];
|
|
832
|
+
/** Rows the branch inserted. */
|
|
833
|
+
inserted: number;
|
|
834
|
+
/** Rows the branch updated. */
|
|
835
|
+
updated: number;
|
|
836
|
+
/** Rows the branch deleted. */
|
|
837
|
+
deleted: number;
|
|
838
|
+
/**
|
|
839
|
+
* Rows both sides changed since the branch was made, differently — and
|
|
840
|
+
* rows the branch deleted that rows the target wrote since still
|
|
841
|
+
* reference through a foreign key ({@link referencedBy}). Deleting one of
|
|
842
|
+
* those on the target would cascade into, or rewrite, the target's own
|
|
843
|
+
* rows, so it is a conflict {@link BranchMergeOptions.onConflict} decides.
|
|
844
|
+
*/
|
|
845
|
+
conflicts: number;
|
|
846
|
+
/**
|
|
847
|
+
* Rows the target changed since the branch was made, and the branch did
|
|
848
|
+
* not. A merge leaves them as they are.
|
|
849
|
+
*/
|
|
850
|
+
targetChanges: number;
|
|
851
|
+
/** Up to {@link BranchDiffOptions.sampleLimit} of the rows counted above, but not of {@link targetChanges}. */
|
|
852
|
+
samples: BranchRowChange[];
|
|
853
|
+
/** Present when this table's rows cannot be merged. A merge refuses it unless told to skip it. */
|
|
854
|
+
blocked?: BranchMergeBlock;
|
|
855
|
+
/**
|
|
856
|
+
* Rows on each side, for a table whose rows were not matched one by one.
|
|
857
|
+
* Its inserted, updated, deleted and conflict counts are then 0 because
|
|
858
|
+
* they are unknown, not because nothing changed.
|
|
859
|
+
*/
|
|
860
|
+
rowCounts?: {
|
|
861
|
+
target: number;
|
|
862
|
+
branch: number;
|
|
863
|
+
};
|
|
864
|
+
/**
|
|
865
|
+
* The foreign keys through which rows the target wrote since the branch
|
|
866
|
+
* was made reference rows of this table the branch deleted. Each such
|
|
867
|
+
* delete is counted in {@link conflicts}.
|
|
868
|
+
*/
|
|
869
|
+
referencedBy?: BranchReferencingRows[];
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Rows of one table, written on the target since the branch was made, that
|
|
873
|
+
* reference rows the branch deleted.
|
|
874
|
+
* @group Admin
|
|
875
|
+
*/
|
|
876
|
+
export interface BranchReferencingRows {
|
|
877
|
+
schema: string;
|
|
878
|
+
table: string;
|
|
879
|
+
/** The foreign key's name. */
|
|
880
|
+
constraint: string;
|
|
881
|
+
/** What deleting the referenced row does to them on the target. */
|
|
882
|
+
onDelete: "cascade" | "set null" | "set default" | "restrict" | "no action";
|
|
883
|
+
/** How many of them there are. */
|
|
884
|
+
rows: number;
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* What {@link BranchAdmin.diffBranch} returns.
|
|
888
|
+
* @group Admin
|
|
889
|
+
*/
|
|
890
|
+
export interface BranchDiff {
|
|
891
|
+
branch: string;
|
|
892
|
+
/** The branch's database. */
|
|
893
|
+
branchDatabase: string;
|
|
894
|
+
/** The database the branch was made from, which a merge writes to. */
|
|
895
|
+
targetDatabase: string;
|
|
896
|
+
/** The schemas compared. */
|
|
897
|
+
schemas: string[];
|
|
898
|
+
/**
|
|
899
|
+
* Whether rows could be told apart by which side changed them since the
|
|
900
|
+
* branch was made. When `false`, every row that differs is counted as the
|
|
901
|
+
* branch's change, and a merge would undo what the target changed.
|
|
902
|
+
*/
|
|
903
|
+
forkPointKnown: boolean;
|
|
904
|
+
/** Pass to {@link BranchAdmin.mergeBranch}: what this diff saw, on both sides. */
|
|
905
|
+
fingerprint: string;
|
|
906
|
+
schema: BranchSchemaChange[];
|
|
907
|
+
/** Only the tables with rows that differ. */
|
|
908
|
+
data: BranchTableDataDiff[];
|
|
909
|
+
sampleLimit: number;
|
|
910
|
+
computedAt: string;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* How {@link BranchAdmin.mergeBranch} applies a branch.
|
|
914
|
+
*
|
|
915
|
+
* A merge writes the rows the branch inserted, updated and deleted to the
|
|
916
|
+
* target, in one statement: all of them, or none. Rows the target changed
|
|
917
|
+
* since the branch was made are kept. Schema and policy changes are never
|
|
918
|
+
* merged — they belong to the collections and their migrations.
|
|
919
|
+
*
|
|
920
|
+
* Nothing is written when either side changed since the diff that produced
|
|
921
|
+
* {@link expectedFingerprint}, when a table with changed rows cannot be merged
|
|
922
|
+
* (unless {@link skipBlocked}), or when a row was changed on both sides and
|
|
923
|
+
* {@link onConflict} is `"abort"`.
|
|
924
|
+
* @group Admin
|
|
925
|
+
*/
|
|
926
|
+
export interface BranchMergeOptions {
|
|
927
|
+
/** {@link BranchDiff.fingerprint} of the diff that was reviewed. */
|
|
928
|
+
expectedFingerprint: string;
|
|
929
|
+
/**
|
|
930
|
+
* A row both sides changed: `"abort"` (the default) writes nothing,
|
|
931
|
+
* `"branch"` writes the branch's row over the target's, `"target"` keeps
|
|
932
|
+
* the target's.
|
|
933
|
+
*
|
|
934
|
+
* A row the branch deleted that the target's newer rows reference
|
|
935
|
+
* ({@link BranchTableDataDiff.referencedBy}) is a conflict too: `"target"`
|
|
936
|
+
* keeps it, and with it the rows that reference it; `"branch"` deletes it,
|
|
937
|
+
* and the foreign key's `ON DELETE` reaches those rows — the result's
|
|
938
|
+
* `warnings` say which.
|
|
939
|
+
*/
|
|
940
|
+
onConflict?: "abort" | "branch" | "target";
|
|
941
|
+
/** Merge the other tables when some cannot be merged, instead of writing nothing. */
|
|
942
|
+
skipBlocked?: boolean;
|
|
943
|
+
/** The schemas the reviewed diff compared, when it was not the default. */
|
|
944
|
+
schemas?: string[];
|
|
945
|
+
/** The row limit the reviewed diff used, when it was not the default. */
|
|
946
|
+
maxRowsPerTable?: number;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* What {@link BranchAdmin.mergeBranch} wrote.
|
|
950
|
+
* @group Admin
|
|
951
|
+
*/
|
|
952
|
+
export interface BranchMergeResult {
|
|
953
|
+
branch: string;
|
|
954
|
+
targetDatabase: string;
|
|
955
|
+
tables: {
|
|
956
|
+
schema: string;
|
|
957
|
+
table: string;
|
|
958
|
+
inserted: number;
|
|
959
|
+
updated: number;
|
|
960
|
+
deleted: number;
|
|
961
|
+
}[];
|
|
962
|
+
/** Tables left unmerged because they could not be, with `skipBlocked`. */
|
|
963
|
+
skipped: {
|
|
964
|
+
schema: string;
|
|
965
|
+
table: string;
|
|
966
|
+
reason: BranchMergeBlock;
|
|
967
|
+
}[];
|
|
968
|
+
/** Rows both sides changed that kept the target's version, with `onConflict: "target"`. */
|
|
969
|
+
conflictsKept: number;
|
|
970
|
+
/** Schema and policy changes on the branch, none of which a merge applies. */
|
|
971
|
+
schemaChangesNotMerged: number;
|
|
972
|
+
/**
|
|
973
|
+
* What the merge did beyond the rows it counts, or what went wrong after
|
|
974
|
+
* they were written: a delete whose foreign keys reached the target's own
|
|
975
|
+
* rows (with `onConflict: "branch"`), a sequence left behind them.
|
|
976
|
+
*/
|
|
977
|
+
warnings: string[];
|
|
718
978
|
}
|
|
719
979
|
/**
|
|
720
980
|
* Union type for all admin capabilities.
|
|
@@ -890,10 +1150,16 @@ export interface RealtimeSocketOptions {
|
|
|
890
1150
|
uid: string;
|
|
891
1151
|
roles: string[];
|
|
892
1152
|
scopes: string[];
|
|
893
|
-
/**
|
|
1153
|
+
/**
|
|
1154
|
+
* The key itself: its id and `rate_limit` decide which rate-limit
|
|
1155
|
+
* bucket its frames count in. With `name` and `kind`, collection
|
|
1156
|
+
* callbacks on its write frames read it as `context.credential`.
|
|
1157
|
+
*/
|
|
894
1158
|
apiKey?: {
|
|
895
1159
|
id: string;
|
|
896
1160
|
rate_limit: number | null;
|
|
1161
|
+
name?: string;
|
|
1162
|
+
kind?: ApiKeyKind;
|
|
897
1163
|
};
|
|
898
1164
|
} | {
|
|
899
1165
|
message: string;
|
|
@@ -960,6 +1226,14 @@ export interface RealtimeSocketOptions {
|
|
|
960
1226
|
* answered `404` and closed, so the client is not left hanging.
|
|
961
1227
|
*/
|
|
962
1228
|
path?: string;
|
|
1229
|
+
/**
|
|
1230
|
+
* Run `fn` on behalf of the backend that owns this socket: each connection
|
|
1231
|
+
* and each frame is handled inside it, so a hook a frame reaches sees that
|
|
1232
|
+
* backend as `rebase`, as it does over REST. The server passes its own.
|
|
1233
|
+
* Absent, frames run in the context the HTTP connection was accepted in —
|
|
1234
|
+
* the process default's.
|
|
1235
|
+
*/
|
|
1236
|
+
runInScope?: <T>(fn: () => T) => T;
|
|
963
1237
|
}
|
|
964
1238
|
/**
|
|
965
1239
|
* A `BackendBootstrapper` encapsulates all driver-specific initialization logic.
|
|
@@ -392,9 +392,9 @@ export interface BaseProperty<CustomProps = unknown> {
|
|
|
392
392
|
* Give the expression, in the template form `isId` takes
|
|
393
393
|
* (``databaseDefault: "sql`gen_random_uuid()`"``), and the schema planner
|
|
394
394
|
* writes it as the column's `DEFAULT`, so `rebase db push` keeps it. `true`
|
|
395
|
-
* declares a DEFAULT someone else wrote
|
|
396
|
-
* one
|
|
397
|
-
* `rebase schema introspect` set the expression they read.
|
|
395
|
+
* declares a DEFAULT someone else wrote: the planner writes none, and
|
|
396
|
+
* `rebase db push` leaves the one the database holds as it is. "Import
|
|
397
|
+
* from table" and `rebase schema introspect` set the expression they read.
|
|
398
398
|
*/
|
|
399
399
|
databaseDefault?: boolean | SqlExpression;
|
|
400
400
|
/**
|
|
@@ -314,9 +314,11 @@ export interface ViaRelation extends RelationBase {
|
|
|
314
314
|
* The joins, in order, from this collection's table to the target's.
|
|
315
315
|
*
|
|
316
316
|
* Each step names a table and the columns to join it on; the last step's
|
|
317
|
-
* table is the target.
|
|
318
|
-
*
|
|
319
|
-
*
|
|
317
|
+
* table is the target. A single-hop chain is writable through a create or
|
|
318
|
+
* update — to-one in one step (the target holds the key), to-many through
|
|
319
|
+
* one junction table — and a longer one is read-only, because Rebase will
|
|
320
|
+
* not work out how to write through an arbitrary chain, and guessing is
|
|
321
|
+
* what this kind exists to stop.
|
|
320
322
|
*/
|
|
321
323
|
joinPath: JoinStep[];
|
|
322
324
|
}
|
|
@@ -379,8 +381,12 @@ export interface ResolvedRelationBase {
|
|
|
379
381
|
*/
|
|
380
382
|
cardinality: "one" | "many";
|
|
381
383
|
/**
|
|
382
|
-
* Whether Rebase
|
|
383
|
-
* {@link ResolvedVia}
|
|
384
|
+
* Whether Rebase writes this link through a create or update. True for
|
|
385
|
+
* every kind but a multi-hop {@link ResolvedVia}: a `via` is writable when
|
|
386
|
+
* it has a single link to set — a to-one chain of one step (the target
|
|
387
|
+
* holds the key) or a to-many chain through one junction table — and
|
|
388
|
+
* read-only otherwise, since Rebase will not invent a write for a longer
|
|
389
|
+
* chain.
|
|
384
390
|
*/
|
|
385
391
|
writable: boolean;
|
|
386
392
|
/**
|
|
@@ -463,7 +469,12 @@ export interface ResolvedManyToMany extends ResolvedRelationBase {
|
|
|
463
469
|
/** @group Models */
|
|
464
470
|
export interface ResolvedVia extends ResolvedRelationBase {
|
|
465
471
|
kind: "via";
|
|
466
|
-
|
|
472
|
+
/**
|
|
473
|
+
* True for a single-hop chain — to-one through one step, or to-many through
|
|
474
|
+
* one junction table — and false for anything longer. See
|
|
475
|
+
* {@link ResolvedRelationBase.writable}.
|
|
476
|
+
*/
|
|
477
|
+
writable: boolean;
|
|
467
478
|
/** The chain as authored — see {@link ViaRelation.joinPath}. Nothing to default. */
|
|
468
479
|
joinPath: JoinStep[];
|
|
469
480
|
}
|
package/dist/types/scopes.d.ts
CHANGED
|
@@ -164,6 +164,20 @@ export declare function isDataPlaneScope(scope: string): scope is DataPlaneScope
|
|
|
164
164
|
export declare function isAdminScope(scope: string): scope is AdminScope;
|
|
165
165
|
/** Does this list of roles include the built-in `admin` role? @group Auth */
|
|
166
166
|
export declare function hasAdminRole(roles: readonly string[] | null | undefined): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Why `name` cannot be written as a role, or `undefined` when it can.
|
|
169
|
+
*
|
|
170
|
+
* No naming pattern is imposed — an app may call its roles anything. What is
|
|
171
|
+
* refused is a name that would be read back as *other* roles: a role travels as
|
|
172
|
+
* one element of a Postgres `text[]` and as one entry of the comma-joined
|
|
173
|
+
* `app.user_roles` setting that RLS policies split with
|
|
174
|
+
* `string_to_array(…, ',')`. Written as `"support,admin"`, a role comes back as
|
|
175
|
+
* `admin`; braces, quotes and backslashes are array-literal syntax, so they are
|
|
176
|
+
* refused too, as are empty names and control characters.
|
|
177
|
+
*
|
|
178
|
+
* @group Auth
|
|
179
|
+
*/
|
|
180
|
+
export declare function roleNameProblem(name: unknown): string | undefined;
|
|
167
181
|
/**
|
|
168
182
|
* Does a set of held scopes grant `scope`, optionally on one `target`?
|
|
169
183
|
*
|
package/dist/users/user.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CallerCredential } from "../types/api_keys.js";
|
|
1
2
|
/**
|
|
2
3
|
* The canonical representation of an authenticated user in the Rebase ecosystem.
|
|
3
4
|
*
|
|
@@ -86,5 +87,12 @@ export type User = {
|
|
|
86
87
|
* anonymous request.
|
|
87
88
|
*/
|
|
88
89
|
readonly claims?: Record<string, unknown>;
|
|
90
|
+
/**
|
|
91
|
+
* The API key this request authenticated with, when it was one. Set
|
|
92
|
+
* server-side on the identity a request's driver is scoped to, and read by
|
|
93
|
+
* collection callbacks as `context.credential`. Absent for a session, a
|
|
94
|
+
* service-key request and in the browser.
|
|
95
|
+
*/
|
|
96
|
+
readonly credential?: CallerCredential;
|
|
89
97
|
getIdToken?: (forceRefresh?: boolean) => Promise<string>;
|
|
90
98
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Rebase type definitions — shared interfaces and controller types",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rebase",
|
|
@@ -79,9 +79,6 @@
|
|
|
79
79
|
"node"
|
|
80
80
|
],
|
|
81
81
|
"testEnvironment": "node",
|
|
82
|
-
"testPathIgnorePatterns": [
|
|
83
|
-
"/bivariance/"
|
|
84
|
-
],
|
|
85
82
|
"moduleNameMapper": {
|
|
86
83
|
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js"
|
|
87
84
|
}
|