@rebasepro/types 0.12.1-canary.gf5f1d39 → 0.13.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/controllers/client.d.ts +41 -12
- package/dist/controllers/data_driver.d.ts +11 -0
- package/dist/index.es.js +41 -6
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +2 -2
- package/dist/types/backend.d.ts +27 -0
- package/dist/types/chips.d.ts +12 -1
- package/dist/types/cron.d.ts +31 -0
- package/dist/types/database_adapter.d.ts +35 -1
- package/dist/types/policy.d.ts +34 -2
- package/dist/types/project_manifest.d.ts +15 -0
- package/dist/types/relations.d.ts +51 -0
- package/dist/users/user.d.ts +2 -2
- package/package.json +4 -4
- package/src/controllers/client.ts +44 -13
- package/src/controllers/data_driver.ts +11 -0
- package/src/types/admin_block.ts +2 -1
- package/src/types/backend.ts +30 -0
- package/src/types/chips.ts +14 -1
- package/src/types/cron.ts +32 -0
- package/src/types/database_adapter.ts +41 -0
- package/src/types/policy.ts +38 -2
- package/src/types/project_manifest.ts +15 -0
- package/src/types/relations.ts +51 -0
- package/src/users/user.ts +2 -2
|
@@ -82,14 +82,55 @@ export interface DatabaseAdapter {
|
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
* Initialize WebSocket server for realtime operations.
|
|
85
|
+
*
|
|
86
|
+
* `adapter` is the configured AuthAdapter, if any. It is what makes the
|
|
87
|
+
* socket secure by default: an implementation that receives one requires
|
|
88
|
+
* authentication regardless of whether a local `jwtSecret` exists. The
|
|
89
|
+
* parameter was missing from this signature while the caller in `init.ts`
|
|
90
|
+
* already passed it, so it was dropped at every adapter that routed through
|
|
91
|
+
* here — turning an adapter-authenticated server's socket into one that
|
|
92
|
+
* accepted every client as already authenticated.
|
|
85
93
|
*/
|
|
86
94
|
initializeWebsockets?(
|
|
87
95
|
server: unknown,
|
|
88
96
|
realtimeService: RealtimeProvider,
|
|
89
97
|
driver: DataDriver,
|
|
90
98
|
config?: unknown,
|
|
99
|
+
adapter?: import("./auth_adapter").AuthAdapter,
|
|
91
100
|
): Promise<void> | void;
|
|
92
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Bring the database's collection tables up to date, additively — the boot
|
|
104
|
+
* companion to `db push`. See `BackendBootstrapper.ensureCollectionSchema`
|
|
105
|
+
* for the contract (create-only; never drop, narrow, or rewrite).
|
|
106
|
+
*
|
|
107
|
+
* Optional, and MUST be forwarded by any wrapper that turns this adapter
|
|
108
|
+
* into a `BackendBootstrapper`: the runtime calls it through the bootstrapper
|
|
109
|
+
* at boot, and a wrapper that silently omits it leaves a managed tenant
|
|
110
|
+
* 500ing every data route with no create step ever having run.
|
|
111
|
+
*/
|
|
112
|
+
ensureCollectionSchema?(
|
|
113
|
+
collections: unknown[],
|
|
114
|
+
driverResult: InitializedDriver,
|
|
115
|
+
log?: (message: string) => void,
|
|
116
|
+
): Promise<{ applied: number }>;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Apply the collections' RLS policies (ENABLE ROW LEVEL SECURITY + the
|
|
120
|
+
* `securityRules` compiled to `CREATE POLICY`) — the boot companion to the
|
|
121
|
+
* policy half of `db push`. Idempotent; see
|
|
122
|
+
* `BackendBootstrapper.ensureCollectionPolicies`.
|
|
123
|
+
*
|
|
124
|
+
* Same forwarding requirement as `ensureCollectionSchema`: without the
|
|
125
|
+
* policies, tables exist but every user-context read is denied (a public
|
|
126
|
+
* collection answers 401).
|
|
127
|
+
*/
|
|
128
|
+
ensureCollectionPolicies?(
|
|
129
|
+
collections: unknown[],
|
|
130
|
+
driverResult: InitializedDriver,
|
|
131
|
+
log?: (message: string) => void,
|
|
132
|
+
): Promise<{ applied: number }>;
|
|
133
|
+
|
|
93
134
|
/**
|
|
94
135
|
* Return admin capabilities for this database (SQL editor, schema browser, branching).
|
|
95
136
|
*/
|
package/src/types/policy.ts
CHANGED
|
@@ -42,13 +42,49 @@ export type PolicyExpression =
|
|
|
42
42
|
*
|
|
43
43
|
* The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
|
|
44
44
|
* tautology on the user path** — it is true for anonymous visitors too. Use
|
|
45
|
-
* {@link policy.authenticated}
|
|
46
|
-
*
|
|
45
|
+
* {@link policy.authenticated} to mean "signed in", and
|
|
46
|
+
* {@link policy.serverContext} to mean "the trusted server context". Do not
|
|
47
|
+
* hand-write the comparison: see {@link ANONYMOUS_USER_IDS} for why one
|
|
48
|
+
* literal is not enough.
|
|
47
49
|
*
|
|
48
50
|
* @group Models
|
|
49
51
|
*/
|
|
50
52
|
export const ANONYMOUS_USER_ID = "anonymous";
|
|
51
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Every uid that has ever meant "nobody is signed in" — newest first.
|
|
56
|
+
*
|
|
57
|
+
* There are two because there were two. The types, the policy compiler, the
|
|
58
|
+
* JavaScript evaluator and the linter were all built on
|
|
59
|
+
* {@link ANONYMOUS_USER_ID}, while the request path scoped unauthenticated
|
|
60
|
+
* callers as `'anon'` — so `policy.authenticated()`, which compiled to
|
|
61
|
+
* `auth.uid() <> 'anonymous'`, was *true* for an anonymous visitor. The
|
|
62
|
+
* sanctioned way to write "signed in" granted to everyone, and the linter
|
|
63
|
+
* flagged the spelling that actually worked as a foreign convention.
|
|
64
|
+
*
|
|
65
|
+
* The request path now reports {@link ANONYMOUS_USER_ID}. `'anon'` stays here
|
|
66
|
+
* because policies outlive the server that generated them: a database still
|
|
67
|
+
* holding policies from before the fix, or a project whose server has not been
|
|
68
|
+
* upgraded yet, must not become a grant in either direction. Compile against
|
|
69
|
+
* this list, not against a single literal.
|
|
70
|
+
*
|
|
71
|
+
* No real user id is ever one of these, so a match is always "not signed in".
|
|
72
|
+
*
|
|
73
|
+
* @group Models
|
|
74
|
+
*/
|
|
75
|
+
export const ANONYMOUS_USER_IDS: readonly string[] = [ANONYMOUS_USER_ID, "anon"];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Whether a uid stands for "no one is signed in", in any spelling rebase has
|
|
79
|
+
* used. `null`/`undefined` is the trusted server context, not an anonymous
|
|
80
|
+
* caller, and is therefore **not** anonymous — see {@link ANONYMOUS_USER_ID}.
|
|
81
|
+
*
|
|
82
|
+
* @group Models
|
|
83
|
+
*/
|
|
84
|
+
export function isAnonymousUid(uid: string | null | undefined): boolean {
|
|
85
|
+
return typeof uid === "string" && ANONYMOUS_USER_IDS.includes(uid);
|
|
86
|
+
}
|
|
87
|
+
|
|
52
88
|
/** Always allows. Compiles to `true`. @group Models */
|
|
53
89
|
export interface TruePolicyExpression {
|
|
54
90
|
kind: "true";
|
|
@@ -200,6 +200,21 @@ export interface RebaseProjectManifest {
|
|
|
200
200
|
* common project and must not be required to say so.
|
|
201
201
|
*/
|
|
202
202
|
storage?: Record<string, RebaseStorageSourceConfig>;
|
|
203
|
+
/**
|
|
204
|
+
* Repository-wide opt-out from anonymous CLI usage sharing.
|
|
205
|
+
*
|
|
206
|
+
* **Only `false` does anything.** It suppresses sharing for everyone who
|
|
207
|
+
* clones this repository, overriding each developer's own opt-in — an
|
|
208
|
+
* organisation setting policy for work done on its behalf, the same shape
|
|
209
|
+
* as a committed `.npmrc`.
|
|
210
|
+
*
|
|
211
|
+
* `true` is deliberately ignored, and the CLI says so rather than obeying
|
|
212
|
+
* quietly. This file is committed, so a `true` here would be one developer
|
|
213
|
+
* answering a privacy question for every colleague who later clones the
|
|
214
|
+
* repo — consent by proxy, which is the exact thing opt-in exists to
|
|
215
|
+
* prevent. Individuals opt in with `rebase telemetry enable`.
|
|
216
|
+
*/
|
|
217
|
+
telemetry?: boolean;
|
|
203
218
|
}
|
|
204
219
|
|
|
205
220
|
/**
|
package/src/types/relations.ts
CHANGED
|
@@ -82,6 +82,15 @@ export interface HasOneRelation extends RelationBase {
|
|
|
82
82
|
* Defaults to `<thisCollection>_id`.
|
|
83
83
|
*/
|
|
84
84
|
foreignKeyOnTarget?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Column on **this** collection's table whose value `foreignKeyOnTarget`
|
|
87
|
+
* holds. Defaults to this collection's primary key.
|
|
88
|
+
*
|
|
89
|
+
* Set it when the two sides are joined on a natural key rather than on the
|
|
90
|
+
* row id — an external identity id, a SKU, a tenant slug. See
|
|
91
|
+
* {@link HasManyRelation.sourceKey}, which this mirrors.
|
|
92
|
+
*/
|
|
93
|
+
sourceKey?: string;
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
/**
|
|
@@ -100,6 +109,30 @@ export interface HasManyRelation extends RelationBase {
|
|
|
100
109
|
* Defaults to `<thisCollection>_id`.
|
|
101
110
|
*/
|
|
102
111
|
foreignKeyOnTarget?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Column on **this** collection's table whose value `foreignKeyOnTarget`
|
|
114
|
+
* holds. Defaults to this collection's primary key.
|
|
115
|
+
*
|
|
116
|
+
* The mirror of `localKey` on {@link BelongsToRelation}: that one names the
|
|
117
|
+
* column this side reads from, this one names the column the other side
|
|
118
|
+
* points at. Without it the pair can only be joined on the row id, which
|
|
119
|
+
* makes a natural-key link — `auth_user_id ↔ auth_user_id`, a SKU, a tenant
|
|
120
|
+
* slug — inexpressible as `hasMany`, and it has to drop to the read-only
|
|
121
|
+
* `via`.
|
|
122
|
+
*
|
|
123
|
+
* The column must be unique: the link addresses one source row per value,
|
|
124
|
+
* and Postgres will not accept a foreign key against a non-unique column.
|
|
125
|
+
*
|
|
126
|
+
* ```ts
|
|
127
|
+
* applications: {
|
|
128
|
+
* kind: "hasMany",
|
|
129
|
+
* target: () => talentApplications,
|
|
130
|
+
* sourceKey: "auth_user_id",
|
|
131
|
+
* foreignKeyOnTarget: "auth_user_id"
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
sourceKey?: string;
|
|
103
136
|
}
|
|
104
137
|
|
|
105
138
|
/**
|
|
@@ -248,6 +281,8 @@ export interface ResolvedHasOne extends ResolvedRelationBase {
|
|
|
248
281
|
shared: false;
|
|
249
282
|
/** Column on the target's table. */
|
|
250
283
|
foreignKeyOnTarget: string;
|
|
284
|
+
/** @see ResolvedHasMany.sourceKey */
|
|
285
|
+
sourceKey?: string;
|
|
251
286
|
}
|
|
252
287
|
|
|
253
288
|
/** @group Models */
|
|
@@ -258,6 +293,22 @@ export interface ResolvedHasMany extends ResolvedRelationBase {
|
|
|
258
293
|
shared: false;
|
|
259
294
|
/** Column on the target's table. */
|
|
260
295
|
foreignKeyOnTarget: string;
|
|
296
|
+
/**
|
|
297
|
+
* Column on the source's table that `foreignKeyOnTarget` points at, or
|
|
298
|
+
* `undefined` for the source's primary key.
|
|
299
|
+
*
|
|
300
|
+
* The one optional field on a resolved relation, and deliberately so. Every
|
|
301
|
+
* other default is filled in here because it can be: a table name and a
|
|
302
|
+
* column name are derivable from the relation and its two endpoints alone.
|
|
303
|
+
* The primary key is not — this driver resolves it from `isId`, then the
|
|
304
|
+
* Drizzle schema, then a column named `id`, and the middle tier does not
|
|
305
|
+
* exist at resolution time.
|
|
306
|
+
*
|
|
307
|
+
* So `undefined` is a sentinel with exactly one meaning, not a field a
|
|
308
|
+
* consumer is invited to guess at. Read it through `sourceKeyField()`,
|
|
309
|
+
* which is the only place that turns it into a column name.
|
|
310
|
+
*/
|
|
311
|
+
sourceKey?: string;
|
|
261
312
|
}
|
|
262
313
|
|
|
263
314
|
/** @group Models */
|
package/src/users/user.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* The canonical representation of an authenticated user in the Rebase ecosystem.
|
|
4
4
|
*
|
|
5
5
|
* Used by {@link AuthController}, collections, callbacks, and both the
|
|
6
|
-
* `@rebasepro/client` and `@rebasepro/app` packages.
|
|
7
|
-
*
|
|
6
|
+
* `@rebasepro/client` and `@rebasepro/app` packages. It is the only user type
|
|
7
|
+
* those packages export — the `RebaseUser` / `UserInfo` aliases are gone.
|
|
8
8
|
*
|
|
9
9
|
* **Backend-managed fields** (`uid`, `email`, `roles`, `metadata`, `createdAt`)
|
|
10
10
|
* are populated by the server. **Client-visible fields** (`displayName`,
|