@rebasepro/types 0.11.1-canary.gfadf355 → 0.12.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/index.es.js +147 -115
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +1 -1
- package/dist/types/api_keys.d.ts +60 -5
- package/dist/types/collections.d.ts +56 -31
- package/dist/types/data_source.d.ts +10 -0
- package/dist/types/history.d.ts +62 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/postgres_introspection.d.ts +95 -0
- package/dist/types/properties.d.ts +37 -48
- package/dist/types/websockets.d.ts +0 -37
- package/package.json +1 -1
- package/src/types/admin_block.ts +5 -0
- package/src/types/api_keys.ts +61 -5
- package/src/types/collections.ts +68 -38
- package/src/types/data_source.ts +15 -0
- package/src/types/history.ts +66 -0
- package/src/types/index.ts +2 -0
- package/src/types/postgres_introspection.ts +101 -0
- package/src/types/properties.ts +42 -55
- package/src/types/websockets.ts +0 -42
package/src/types/api_keys.ts
CHANGED
|
@@ -1,16 +1,56 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Service API keys — machine-to-machine authentication for scripts, cron jobs
|
|
3
|
+
* and third-party integrations.
|
|
4
|
+
*
|
|
5
|
+
* The wire contract lives here because all three sides need it and used to
|
|
6
|
+
* declare it separately: `@rebasepro/server` implements the routes,
|
|
7
|
+
* `@rebasepro/client` calls them, and {@link ApiKeysAPI} types the SDK surface.
|
|
8
|
+
* The client's copy had already drifted — it never gained `admin`.
|
|
9
|
+
*
|
|
10
|
+
* The database row itself (`ApiKey`, which carries `key_hash`) stays in the
|
|
11
|
+
* server package: nothing off the server may see it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A single permission entry scoping an API key to a collection and set of
|
|
16
|
+
* operations.
|
|
17
|
+
*
|
|
18
|
+
* Use `"*"` as the collection value to grant access to all collections (and all
|
|
19
|
+
* custom functions). Custom functions are addressed with the `functions`
|
|
20
|
+
* namespace: `"functions"` grants every function, `"functions/<name>"` grants a
|
|
21
|
+
* single one.
|
|
22
|
+
*
|
|
23
|
+
* @group Models
|
|
24
|
+
*/
|
|
2
25
|
export interface ApiKeyPermission {
|
|
26
|
+
/** Collection slug, `"functions"`/`"functions/<name>"`, or `"*"` for everything. */
|
|
3
27
|
collection: string;
|
|
28
|
+
/** Allowed operations on the collection. */
|
|
4
29
|
operations: ("read" | "write" | "delete")[];
|
|
5
30
|
}
|
|
6
31
|
|
|
7
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* An API key with the secret portion masked — what list / get / update return.
|
|
34
|
+
* @group Models
|
|
35
|
+
*/
|
|
8
36
|
export interface ApiKeyMasked {
|
|
9
37
|
id: string;
|
|
10
38
|
name: string;
|
|
39
|
+
/** First 12 characters of the plaintext key, for display only. */
|
|
11
40
|
key_prefix: string;
|
|
12
41
|
permissions: ApiKeyPermission[];
|
|
42
|
+
/**
|
|
43
|
+
* When true, the key is granted the `admin` role: it passes the admin-gated
|
|
44
|
+
* routes (users, roles, cron, backups, logs, API keys) and the RLS
|
|
45
|
+
* `default_admin` policies. Non-admin keys carry only the `service` role —
|
|
46
|
+
* RLS grants them nothing unless a collection policy names that role.
|
|
47
|
+
*/
|
|
13
48
|
admin: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Requests per 15-minute window. `null` means "no per-key override" — the
|
|
51
|
+
* data rate limiter then applies its default API-key limit (1000/window
|
|
52
|
+
* unless configured otherwise), not unlimited.
|
|
53
|
+
*/
|
|
14
54
|
rate_limit: number | null;
|
|
15
55
|
created_by: string;
|
|
16
56
|
created_at: string;
|
|
@@ -20,29 +60,45 @@ export interface ApiKeyMasked {
|
|
|
20
60
|
revoked_at: string | null;
|
|
21
61
|
}
|
|
22
62
|
|
|
23
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* Returned exactly once, when a key is created. The `key` field holds the full
|
|
65
|
+
* plaintext key — it is never stored or returned again.
|
|
66
|
+
* @group Models
|
|
67
|
+
*/
|
|
24
68
|
export interface ApiKeyWithSecret extends ApiKeyMasked {
|
|
69
|
+
/** Full plaintext API key (e.g. `rk_live_abc123...`). */
|
|
25
70
|
key: string;
|
|
26
71
|
}
|
|
27
72
|
|
|
28
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Payload for creating a new API key.
|
|
75
|
+
* @group Models
|
|
76
|
+
*/
|
|
29
77
|
export interface CreateApiKeyRequest {
|
|
30
78
|
name: string;
|
|
31
79
|
permissions: ApiKeyPermission[];
|
|
80
|
+
/** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
|
|
32
81
|
admin?: boolean;
|
|
82
|
+
/** Requests per 15-minute window. Omit or `null` for the server default. */
|
|
33
83
|
rate_limit?: number | null;
|
|
84
|
+
/** ISO-8601 expiration timestamp. Omit for no expiration. */
|
|
34
85
|
expires_at?: string | null;
|
|
35
86
|
}
|
|
36
87
|
|
|
37
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Payload for updating an existing API key. Only the fields provided change.
|
|
90
|
+
* @group Models
|
|
91
|
+
*/
|
|
38
92
|
export interface UpdateApiKeyRequest {
|
|
39
93
|
name?: string;
|
|
40
94
|
permissions?: ApiKeyPermission[];
|
|
95
|
+
/** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
|
|
41
96
|
admin?: boolean;
|
|
42
97
|
rate_limit?: number | null;
|
|
43
98
|
expires_at?: string | null;
|
|
44
99
|
}
|
|
45
100
|
|
|
101
|
+
/** @group Models */
|
|
46
102
|
export interface ApiKeysAPI {
|
|
47
103
|
listKeys(): Promise<{ keys: ApiKeyMasked[] }>;
|
|
48
104
|
getKey(id: string): Promise<{ key: ApiKeyMasked }>;
|
package/src/types/collections.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { EnumValues, Properties, PostgresProperties, FirebaseProperties, Mo
|
|
|
5
5
|
import type { User } from "../users";
|
|
6
6
|
import type { Relation } from "./relations";
|
|
7
7
|
import type { SecurityRule } from "./security_rules";
|
|
8
|
+
import { getDataSourceCapabilities } from "./data_source";
|
|
8
9
|
import type { WhereFilterOp, FilterValues, FilterPreset } from "./filter-operators";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -116,30 +117,34 @@ export interface BaseCollectionConfig<M extends Record<string, unknown> = Record
|
|
|
116
117
|
*/
|
|
117
118
|
auth?: boolean | AuthCollectionConfig;
|
|
118
119
|
|
|
119
|
-
/**
|
|
120
|
-
* Opt out of the framework's default Row Level Security policies.
|
|
121
|
-
*
|
|
122
|
-
* The schema generator automatically injects, for every collection, a
|
|
123
|
-
* baseline SELECT policy granting the trusted server context and the
|
|
124
|
-
* `admin` role read access (reads run under a restricted role, so RLS
|
|
125
|
-
* default-denies without it). For auth collections it additionally injects
|
|
126
|
-
* a self-read policy (`id = auth.uid()`) and an admin-only write gate
|
|
127
|
-
* (INSERT/UPDATE/DELETE require the `admin` role or the trusted server
|
|
128
|
-
* context), making privileged columns such as `roles` safe by default.
|
|
129
|
-
*
|
|
130
|
-
* Author-defined `securityRules` are permissive and broaden access on top
|
|
131
|
-
* of these defaults. Set this flag to `true` to remove the defaults
|
|
132
|
-
* entirely and take full responsibility for the collection's RLS.
|
|
133
|
-
*
|
|
134
|
-
* @default false
|
|
135
|
-
*/
|
|
136
|
-
disableDefaultPolicies?: boolean;
|
|
137
120
|
|
|
138
121
|
|
|
139
122
|
|
|
140
123
|
|
|
141
124
|
|
|
142
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Row-level authorization rules for this collection.
|
|
128
|
+
*
|
|
129
|
+
* Driver-agnostic on purpose, unlike `disableDefaultPolicies`, `table` and
|
|
130
|
+
* `relations`, which are declared on {@link PostgresCollectionConfig} only.
|
|
131
|
+
* The rules are a *contract* — who may read or write which rows — and each
|
|
132
|
+
* engine enforces it its own way:
|
|
133
|
+
*
|
|
134
|
+
* - **Postgres** compiles them to real `CREATE POLICY` statements and lets
|
|
135
|
+
* the database enforce them (see {@link PostgresCollectionConfig.securityRules},
|
|
136
|
+
* which narrows this with the raw-SQL details).
|
|
137
|
+
* - **MongoDB** translates them into a query filter it AND-s into every
|
|
138
|
+
* read and write, honouring `access`, `ownerField`, `roles`, `mode` and
|
|
139
|
+
* the `operation`/`operations` selectors, and making a best effort at raw
|
|
140
|
+
* `using`/`withCheck` SQL.
|
|
141
|
+
* - **Firestore** does not implement them at all; its own rules language is
|
|
142
|
+
* evaluated by Google, not from here. `supportsRLS` on
|
|
143
|
+
* {@link DataSourceCapabilities} reports which engines generate policies,
|
|
144
|
+
* which is not the same question as whether an engine honours a rule.
|
|
145
|
+
*/
|
|
146
|
+
securityRules?: readonly SecurityRule[];
|
|
147
|
+
|
|
143
148
|
/**
|
|
144
149
|
* This interface defines all the callbacks that can be used when a entity
|
|
145
150
|
* is being created, updated or deleted.
|
|
@@ -202,26 +207,6 @@ export interface BaseCollectionConfig<M extends Record<string, unknown> = Record
|
|
|
202
207
|
|
|
203
208
|
|
|
204
209
|
|
|
205
|
-
/**
|
|
206
|
-
* The database table name for this collection.
|
|
207
|
-
* Automatically set for PostgreSQL collections.
|
|
208
|
-
* For non-SQL backends, this may be undefined.
|
|
209
|
-
*/
|
|
210
|
-
table?: string;
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Relations defined for this collection.
|
|
214
|
-
* Populated at normalization time from inline relation properties
|
|
215
|
-
* or explicit relation definitions.
|
|
216
|
-
*/
|
|
217
|
-
relations?: Relation[];
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Security rules for this collection (Row Level Security).
|
|
221
|
-
* When defined, the backend enforces access control policies.
|
|
222
|
-
*/
|
|
223
|
-
securityRules?: readonly SecurityRule[];
|
|
224
|
-
|
|
225
210
|
}
|
|
226
211
|
|
|
227
212
|
// ── Driver-specific collection types ──────────────────────────────────
|
|
@@ -279,6 +264,25 @@ export interface PostgresCollectionConfig<M extends Record<string, unknown> = Re
|
|
|
279
264
|
* - `auth.jwt()` — full JWT claims as JSONB
|
|
280
265
|
*/
|
|
281
266
|
securityRules?: readonly SecurityRule[];
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Opt out of the framework's default Row Level Security policies.
|
|
270
|
+
*
|
|
271
|
+
* The schema generator automatically injects, for every collection, a
|
|
272
|
+
* baseline SELECT policy granting the trusted server context and the
|
|
273
|
+
* `admin` role read access (reads run under a restricted role, so RLS
|
|
274
|
+
* default-denies without it). For auth collections it additionally injects
|
|
275
|
+
* a self-read policy (`id = auth.uid()`) and an admin-only write gate
|
|
276
|
+
* (INSERT/UPDATE/DELETE require the `admin` role or the trusted server
|
|
277
|
+
* context), making privileged columns such as `roles` safe by default.
|
|
278
|
+
*
|
|
279
|
+
* Author-defined `securityRules` are permissive and broaden access on top
|
|
280
|
+
* of these defaults. Set this flag to `true` to remove the defaults
|
|
281
|
+
* entirely and take full responsibility for the collection's RLS.
|
|
282
|
+
*
|
|
283
|
+
* @default false
|
|
284
|
+
*/
|
|
285
|
+
disableDefaultPolicies?: boolean;
|
|
282
286
|
}
|
|
283
287
|
|
|
284
288
|
/**
|
|
@@ -424,6 +428,32 @@ export function isPostgresCollectionConfig<C extends CollectionConfig<any, any>>
|
|
|
424
428
|
return !collection.engine || collection.engine === "postgres";
|
|
425
429
|
}
|
|
426
430
|
|
|
431
|
+
/**
|
|
432
|
+
* Narrows to the SQL collection fields — `table`, `relations`,
|
|
433
|
+
* `disableDefaultPolicies` — by asking the engine's declared capabilities
|
|
434
|
+
* rather than by naming Postgres.
|
|
435
|
+
*
|
|
436
|
+
* The two halves of this already existed and were never joined. The engine
|
|
437
|
+
* split (`PostgresCollectionConfig` / `FirebaseCollectionConfig` /
|
|
438
|
+
* `MongoDBCollectionConfig`) said which fields belong to which engine at the
|
|
439
|
+
* type level; {@link DataSourceCapabilities} said the same thing at runtime,
|
|
440
|
+
* down to a `supportsRelations` flag. So call sites guarded on the capability
|
|
441
|
+
* and then read a field the base type had to declare for them — which is why
|
|
442
|
+
* those fields were on the base, and why a MongoDB collection could be written
|
|
443
|
+
* with a `table`.
|
|
444
|
+
*
|
|
445
|
+
* Prefer this over {@link isPostgresCollectionConfig} wherever the question is
|
|
446
|
+
* "does this collection live in a SQL table", so a custom SQL engine
|
|
447
|
+
* registered through `registerDataSourceCapabilities` is included.
|
|
448
|
+
*
|
|
449
|
+
* @group Models
|
|
450
|
+
*/
|
|
451
|
+
export function isRelationalCollectionConfig<C extends CollectionConfig<any, any>>(
|
|
452
|
+
collection: C
|
|
453
|
+
): collection is C & PostgresCollectionConfig<any, any> {
|
|
454
|
+
return getDataSourceCapabilities(collection.engine).supportsRelations;
|
|
455
|
+
}
|
|
456
|
+
|
|
427
457
|
/**
|
|
428
458
|
* Type guard for Firebase / Firestore collections.
|
|
429
459
|
* @group Models
|
package/src/types/data_source.ts
CHANGED
|
@@ -37,6 +37,17 @@ export interface DataSourceCapabilities {
|
|
|
37
37
|
/** Does this source support real-time listeners? */
|
|
38
38
|
supportsRealtime: boolean;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Does this source store vectors natively?
|
|
42
|
+
*
|
|
43
|
+
* `VectorProperty` carries a `dimensions` and is pgvector-shaped. It was
|
|
44
|
+
* the one driver-specific property kind with no flag to gate it, so unlike
|
|
45
|
+
* every other field in this descriptor there was not even a runtime answer
|
|
46
|
+
* to appeal to — a Firestore collection could declare an embedding column
|
|
47
|
+
* and no driver would do anything with it.
|
|
48
|
+
*/
|
|
49
|
+
supportsVectors: boolean;
|
|
50
|
+
|
|
40
51
|
/**
|
|
41
52
|
* Canonical filter operators this engine can execute.
|
|
42
53
|
*
|
|
@@ -197,6 +208,7 @@ export const POSTGRES_CAPABILITIES: DataSourceCapabilities = {
|
|
|
197
208
|
supportsReferences: false,
|
|
198
209
|
supportsColumnTypes: true,
|
|
199
210
|
supportsRealtime: true,
|
|
211
|
+
supportsVectors: true,
|
|
200
212
|
filterOperators: ALL_WHERE_FILTER_OPS,
|
|
201
213
|
// `via` is absent: its join path is authored source → target with no
|
|
202
214
|
// stated inverse, so the driver has nothing to reverse into a filter.
|
|
@@ -216,6 +228,7 @@ export const FIREBASE_CAPABILITIES: DataSourceCapabilities = {
|
|
|
216
228
|
supportsReferences: true,
|
|
217
229
|
supportsColumnTypes: false,
|
|
218
230
|
supportsRealtime: true,
|
|
231
|
+
supportsVectors: false,
|
|
219
232
|
// Firestore has no SQL pattern matching — the driver throws on the LIKE
|
|
220
233
|
// family, so the UI must never offer it.
|
|
221
234
|
filterOperators: ALL_WHERE_FILTER_OPS.filter(op =>
|
|
@@ -237,6 +250,7 @@ export const MONGODB_CAPABILITIES: DataSourceCapabilities = {
|
|
|
237
250
|
supportsReferences: true,
|
|
238
251
|
supportsColumnTypes: false,
|
|
239
252
|
supportsRealtime: false,
|
|
253
|
+
supportsVectors: false,
|
|
240
254
|
filterOperators: ALL_WHERE_FILTER_OPS,
|
|
241
255
|
filterableRelationKinds: [],
|
|
242
256
|
supportsSQLAdmin: false,
|
|
@@ -258,6 +272,7 @@ export const DEFAULT_CAPABILITIES: DataSourceCapabilities = {
|
|
|
258
272
|
supportsReferences: true,
|
|
259
273
|
supportsColumnTypes: true,
|
|
260
274
|
supportsRealtime: true,
|
|
275
|
+
supportsVectors: true,
|
|
261
276
|
filterOperators: ALL_WHERE_FILTER_OPS,
|
|
262
277
|
// The exception to this descriptor's "enable everything" rule. The other
|
|
263
278
|
// flags hide a tab or a picker when they are wrong; this one decides
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity change history — the shape a history entry has on the wire.
|
|
3
|
+
*
|
|
4
|
+
* This was declared three times: once in `@rebasepro/server-postgres`, once in
|
|
5
|
+
* `@rebasepro/server-mongo`, and once again in the admin's `useHistory` hook.
|
|
6
|
+
* The two driver copies disagreed on the one field that matters for a consumer,
|
|
7
|
+
* `updated_at`, which was a `string` in Postgres and a `Date` in MongoDB — so
|
|
8
|
+
* nothing could read history without first choosing a driver.
|
|
9
|
+
*
|
|
10
|
+
* The contract is the wire shape, and on the wire it is an ISO-8601 string.
|
|
11
|
+
* A driver whose stored document differs (MongoDB keeps a `Date` and an
|
|
12
|
+
* `ObjectId`) declares that storage row for itself and maps to this on the way
|
|
13
|
+
* out; it is not the shared type.
|
|
14
|
+
*
|
|
15
|
+
* @group Backend
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* One recorded change to a row.
|
|
20
|
+
* @group Backend
|
|
21
|
+
*/
|
|
22
|
+
export interface EntityHistoryEntry {
|
|
23
|
+
id: string;
|
|
24
|
+
/** The table (Postgres) or collection (MongoDB) the row belongs to. */
|
|
25
|
+
table_name: string;
|
|
26
|
+
/** The row's id, as a string regardless of its native type. */
|
|
27
|
+
entity_id: string;
|
|
28
|
+
action: "create" | "update" | "delete";
|
|
29
|
+
/** Which fields changed. `null` for creates and deletes. */
|
|
30
|
+
changed_fields: string[] | null;
|
|
31
|
+
values: Record<string, unknown> | null;
|
|
32
|
+
previous_values: Record<string, unknown> | null;
|
|
33
|
+
updated_by: string | null;
|
|
34
|
+
/** ISO-8601. A driver storing a native date converts on read. */
|
|
35
|
+
updated_at: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Arguments to record one change.
|
|
40
|
+
* @group Backend
|
|
41
|
+
*/
|
|
42
|
+
export interface RecordHistoryParams {
|
|
43
|
+
tableName: string;
|
|
44
|
+
id: string;
|
|
45
|
+
action: "create" | "update" | "delete";
|
|
46
|
+
values?: Record<string, unknown> | null;
|
|
47
|
+
previousValues?: Record<string, unknown> | null;
|
|
48
|
+
updatedBy?: string | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* How much history to keep. Pruning runs per row after each write.
|
|
53
|
+
* @group Backend
|
|
54
|
+
*/
|
|
55
|
+
export interface HistoryRetentionConfig {
|
|
56
|
+
/** Max entries per row. Oldest pruned first. Default 200. */
|
|
57
|
+
maxEntries: number;
|
|
58
|
+
/** Entries older than this many days are pruned. Default 90. */
|
|
59
|
+
ttlDays: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @group Backend */
|
|
63
|
+
export interface FetchHistoryOptions {
|
|
64
|
+
limit?: number;
|
|
65
|
+
offset?: number;
|
|
66
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -21,6 +21,8 @@ export * from "./component_ref";
|
|
|
21
21
|
export * from "./auth_adapter";
|
|
22
22
|
export * from "./database_adapter";
|
|
23
23
|
export * from "./api_keys";
|
|
24
|
+
export * from "./history";
|
|
25
|
+
export * from "./postgres_introspection";
|
|
24
26
|
export * from "./project_manifest";
|
|
25
27
|
export * from "./collection_contract";
|
|
26
28
|
export * from "./schema_version";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shapes returned by Postgres introspection queries.
|
|
3
|
+
*
|
|
4
|
+
* These are **not** driver-agnostic and they are not a model of anything — each
|
|
5
|
+
* one is the projection of a specific `SELECT` against `information_schema` or
|
|
6
|
+
* `pg_policies`, which is why the fields are snake_cased and why `is_nullable`
|
|
7
|
+
* is a string rather than a boolean. They describe rows, not concepts.
|
|
8
|
+
*
|
|
9
|
+
* They were spread across three places that had nothing to do with each other:
|
|
10
|
+
* the `Table*` shapes sat in `websockets.ts`, next to the WebSocket frame types
|
|
11
|
+
* they share no relationship with, and `PostgresPolicy` was declared twice — in
|
|
12
|
+
* `@rebasepro/admin`'s RLS tab and again in `@rebasepro/studio`'s RLS editor,
|
|
13
|
+
* the second with a comment explaining it was inline "to avoid depending on
|
|
14
|
+
* @rebasepro/studio". Neither had to: this package is already a dependency of
|
|
15
|
+
* both.
|
|
16
|
+
*
|
|
17
|
+
* Producer: `@rebasepro/server-postgres`. Consumers: the collection editor, the
|
|
18
|
+
* studio schema browser, the RLS editors.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A column, as `information_schema.columns` reports it.
|
|
23
|
+
* @group Models
|
|
24
|
+
*/
|
|
25
|
+
export interface TableColumnInfo {
|
|
26
|
+
column_name: string;
|
|
27
|
+
data_type: string;
|
|
28
|
+
udt_name: string;
|
|
29
|
+
/** `"YES"` or `"NO"` — `information_schema` reports this as text. */
|
|
30
|
+
is_nullable: string;
|
|
31
|
+
column_default: string | null;
|
|
32
|
+
character_maximum_length: number | null;
|
|
33
|
+
/** Enum values, populated for USER-DEFINED (enum) columns */
|
|
34
|
+
enum_values?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @group Models */
|
|
38
|
+
export interface TableForeignKeyInfo {
|
|
39
|
+
column_name: string;
|
|
40
|
+
foreign_table_name: string;
|
|
41
|
+
foreign_column_name: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** @group Models */
|
|
45
|
+
export interface TableJunctionInfo {
|
|
46
|
+
junction_table_name: string;
|
|
47
|
+
source_column_name: string;
|
|
48
|
+
target_table_name: string;
|
|
49
|
+
target_column_name: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A policy as the *table metadata* query projects it.
|
|
54
|
+
*
|
|
55
|
+
* Distinct from {@link PostgresPolicy}, which is the RLS editor's fuller
|
|
56
|
+
* projection of `pg_policies` — this one carries only what the collection
|
|
57
|
+
* editor needs to show that a table is protected.
|
|
58
|
+
*
|
|
59
|
+
* @group Models
|
|
60
|
+
*/
|
|
61
|
+
export interface TablePolicyInfo {
|
|
62
|
+
policy_name: string;
|
|
63
|
+
roles: string[];
|
|
64
|
+
cmd: string;
|
|
65
|
+
qual?: string;
|
|
66
|
+
with_check?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** @group Models */
|
|
70
|
+
export interface TableMetadata {
|
|
71
|
+
columns: TableColumnInfo[];
|
|
72
|
+
foreignKeys: TableForeignKeyInfo[];
|
|
73
|
+
junctions: TableJunctionInfo[];
|
|
74
|
+
policies: TablePolicyInfo[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A row of `pg_policies`, as the RLS editors read it.
|
|
79
|
+
*
|
|
80
|
+
* Note the unseparated column names (`policyname`, `tablename`) — those are
|
|
81
|
+
* Postgres's, not ours. See {@link TablePolicyInfo} for the narrower projection
|
|
82
|
+
* the collection editor uses.
|
|
83
|
+
*
|
|
84
|
+
* @group Models
|
|
85
|
+
*/
|
|
86
|
+
export interface PostgresPolicy {
|
|
87
|
+
policyname: string;
|
|
88
|
+
tablename: string;
|
|
89
|
+
permissive: "PERMISSIVE" | "RESTRICTIVE";
|
|
90
|
+
roles: string[];
|
|
91
|
+
cmd: "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "ALL";
|
|
92
|
+
/** The `USING` clause. */
|
|
93
|
+
qual: string | null;
|
|
94
|
+
/** The `WITH CHECK` clause. */
|
|
95
|
+
with_check: string | null;
|
|
96
|
+
/**
|
|
97
|
+
* Whether this policy exists in the live database, in the collection's
|
|
98
|
+
* `securityRules`, or both. Computed by the editor, not by Postgres.
|
|
99
|
+
*/
|
|
100
|
+
status?: "live" | "code_only" | "both";
|
|
101
|
+
}
|
package/src/types/properties.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { ComponentRef } from "./component_ref";
|
|
|
2
2
|
|
|
3
3
|
import type { Entity, EntityReference, EntityRelation, EntityValues, GeoPoint, Vector } from "./entities";
|
|
4
4
|
import type { JoinStep, OnAction, Relation, ResolvedRelation } from "./relations";
|
|
5
|
-
import type { CollectionConfig, FilterValues, WhereFilterOp } from "./collections";
|
|
6
5
|
import type { ColorKey, ColorScheme } from "./chips";
|
|
7
6
|
import type { AuthState } from "../controllers/auth_state";
|
|
8
7
|
import type { AfterReadProps, BeforeSaveProps } from "./entity_callbacks";
|
|
@@ -65,19 +64,49 @@ export type Properties = {
|
|
|
65
64
|
[key: string]: Property;
|
|
66
65
|
};
|
|
67
66
|
|
|
67
|
+
/**
|
|
68
|
+
* `Omit` that survives a union.
|
|
69
|
+
*
|
|
70
|
+
* `Property` is a union discriminated on `type`, and a bare `Omit<Property, K>`
|
|
71
|
+
* collapses it into one object whose `type` is the union of every tag — so
|
|
72
|
+
* `property.type === "string"` stops narrowing and the concrete property types
|
|
73
|
+
* become unreachable. The `T extends unknown` clause makes it distribute, so
|
|
74
|
+
* each member is omitted from separately and keeps its own discriminant.
|
|
75
|
+
*/
|
|
76
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The fields that describe a property's **column**, which only an engine with
|
|
80
|
+
* columns has.
|
|
81
|
+
*
|
|
82
|
+
* `columnType` names a Postgres type (`uuid`, `bigserial`, `jsonb`, `text[]`)
|
|
83
|
+
* and `columnName` overrides the snake_case derivation used to build a column
|
|
84
|
+
* name. `DataSourceCapabilities.supportsColumnTypes` already reported this at
|
|
85
|
+
* runtime — `false` for both document engines — while the types let a MongoDB
|
|
86
|
+
* property declare `columnType: "bigserial"`.
|
|
87
|
+
*
|
|
88
|
+
* They stay declared on the concrete property interfaces rather than moving,
|
|
89
|
+
* because that is where their per-type value unions live; what changes is that
|
|
90
|
+
* the document engines' property aliases omit them.
|
|
91
|
+
*/
|
|
92
|
+
type SqlColumnFields = "columnType" | "columnName";
|
|
93
|
+
|
|
68
94
|
export type PostgresProperty = Exclude<Property, ReferenceProperty>;
|
|
69
95
|
export type PostgresProperties = {
|
|
70
96
|
[key: string]: PostgresProperty;
|
|
71
97
|
};
|
|
72
98
|
|
|
73
|
-
export type FirebaseProperty = Exclude<Property, RelationProperty>;
|
|
99
|
+
export type FirebaseProperty = DistributiveOmit<Exclude<Property, RelationProperty | VectorProperty>, SqlColumnFields>;
|
|
74
100
|
export type FirebaseProperties = {
|
|
75
101
|
[key: string]: FirebaseProperty;
|
|
76
102
|
};
|
|
77
103
|
|
|
78
104
|
// MongoDB is a document store: it uses references (stored pointers), not
|
|
79
105
|
// SQL-style relations/joins. Same gating as Firestore.
|
|
80
|
-
|
|
106
|
+
//
|
|
107
|
+
// `vector` goes with them: it is pgvector-shaped, only `@rebasepro/server-postgres`
|
|
108
|
+
// reads it, and `supportsVectors` on the engine's capabilities says so.
|
|
109
|
+
export type MongoProperty = DistributiveOmit<Exclude<Property, RelationProperty | VectorProperty>, SqlColumnFields>;
|
|
81
110
|
export type MongoProperties = {
|
|
82
111
|
[key: string]: MongoProperty;
|
|
83
112
|
};
|
|
@@ -473,20 +502,6 @@ export interface ReferenceProperty extends BaseProperty {
|
|
|
473
502
|
* property.
|
|
474
503
|
*/
|
|
475
504
|
path?: string;
|
|
476
|
-
/**
|
|
477
|
-
* Allow selection of entities that pass the given filter only.
|
|
478
|
-
* e.g. `fixedFilter: { age: [">=", 18] }`
|
|
479
|
-
*/
|
|
480
|
-
fixedFilter?: FilterValues<string>;
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Should the reference include the ID of the entity. Defaults to `true`
|
|
484
|
-
*/
|
|
485
|
-
includeId?: boolean;
|
|
486
|
-
/**
|
|
487
|
-
* Should the reference include a link to the entity (open the entity details). Defaults to `true`
|
|
488
|
-
*/
|
|
489
|
-
includeEntityLink?: boolean;
|
|
490
505
|
}
|
|
491
506
|
|
|
492
507
|
/**
|
|
@@ -548,29 +563,6 @@ export interface RelationProperty extends BaseProperty {
|
|
|
548
563
|
* collection's `relations` array.
|
|
549
564
|
*/
|
|
550
565
|
resolvedRelation?: ResolvedRelation;
|
|
551
|
-
|
|
552
|
-
// ─── UI configuration ───
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* Allow selection of entities that pass the given filter only.
|
|
556
|
-
* e.g. `fixedFilter: { age: [">=", 18] }`
|
|
557
|
-
*/
|
|
558
|
-
fixedFilter?: FilterValues<string>;
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* Should the reference include the ID of the entity. Defaults to `true`
|
|
562
|
-
*/
|
|
563
|
-
includeId?: boolean;
|
|
564
|
-
/**
|
|
565
|
-
* Should the reference include a link to the entity (open the entity details). Defaults to `true`
|
|
566
|
-
*/
|
|
567
|
-
includeEntityLink?: boolean;
|
|
568
|
-
|
|
569
|
-
/**
|
|
570
|
-
* Choose the widget to use for selecting the relation.
|
|
571
|
-
* Defaults to `select`.
|
|
572
|
-
*/
|
|
573
|
-
widget?: "select" | "dialog";
|
|
574
566
|
}
|
|
575
567
|
|
|
576
568
|
export interface ArrayProperty extends BaseProperty {
|
|
@@ -634,17 +626,6 @@ export interface ArrayProperty extends BaseProperty {
|
|
|
634
626
|
* Rules for validating this property
|
|
635
627
|
*/
|
|
636
628
|
validation?: ArrayPropertyValidationSchema;
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* Can the elements in this array be reordered. Defaults to `true`.
|
|
640
|
-
* This prop has no effect if `disabled` is set to true.
|
|
641
|
-
*/
|
|
642
|
-
sortable?: boolean;
|
|
643
|
-
/**
|
|
644
|
-
* Can the elements in this array be added. Defaults to `true`
|
|
645
|
-
* This prop has no effect if `disabled` is set to true.
|
|
646
|
-
*/
|
|
647
|
-
canAddElements?: boolean;
|
|
648
629
|
}
|
|
649
630
|
|
|
650
631
|
export interface MapProperty extends BaseProperty {
|
|
@@ -665,6 +646,12 @@ export interface MapProperty extends BaseProperty {
|
|
|
665
646
|
* Order in which the properties are displayed.
|
|
666
647
|
* If you are specifying your collection as code, the order is the same as the
|
|
667
648
|
* one you define in `properties`, and you don't need to specify this prop.
|
|
649
|
+
*
|
|
650
|
+
* Stays on the property rather than moving to the `admin` block, unlike the
|
|
651
|
+
* rest of the map's presentation options: `sortProperties` in
|
|
652
|
+
* `@rebasepro/common` reads it recursively, and `@rebasepro/firebase` calls
|
|
653
|
+
* that when it builds collections. A core package cannot read the admin
|
|
654
|
+
* block — the field exists only once `@rebasepro/admin-types` is installed.
|
|
668
655
|
*/
|
|
669
656
|
propertiesOrder?: string[];
|
|
670
657
|
/**
|
|
@@ -673,13 +660,13 @@ export interface MapProperty extends BaseProperty {
|
|
|
673
660
|
* will be considered valid, even if you set `required` in the properties.
|
|
674
661
|
*/
|
|
675
662
|
validation?: PropertyValidationSchema;
|
|
676
|
-
/**
|
|
677
|
-
* Properties that are displayed when rendered as a preview
|
|
678
|
-
*/
|
|
679
|
-
previewProperties?: string[];
|
|
680
663
|
/**
|
|
681
664
|
* Render this map as a key-value table that allows to use
|
|
682
665
|
* arbitrary keys. You don't need to define the properties in this case.
|
|
666
|
+
*
|
|
667
|
+
* Core rather than admin despite the wording: it says the map has no
|
|
668
|
+
* declared shape, which is what the OpenAPI generator emits the schema
|
|
669
|
+
* from (`additionalProperties` instead of a property list).
|
|
683
670
|
*/
|
|
684
671
|
keyValue?: boolean;
|
|
685
672
|
}
|
package/src/types/websockets.ts
CHANGED
|
@@ -115,45 +115,3 @@ export interface ChannelHistoryMessage extends WebSocketMessage {
|
|
|
115
115
|
*/
|
|
116
116
|
latestSeq?: number;
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Column metadata returned by table introspection.
|
|
121
|
-
*/
|
|
122
|
-
export interface TableColumnInfo {
|
|
123
|
-
column_name: string;
|
|
124
|
-
data_type: string;
|
|
125
|
-
udt_name: string;
|
|
126
|
-
is_nullable: string;
|
|
127
|
-
column_default: string | null;
|
|
128
|
-
character_maximum_length: number | null;
|
|
129
|
-
/** Enum values, populated for USER-DEFINED (enum) columns */
|
|
130
|
-
enum_values?: string[];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface TableForeignKeyInfo {
|
|
134
|
-
column_name: string;
|
|
135
|
-
foreign_table_name: string;
|
|
136
|
-
foreign_column_name: string;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface TableJunctionInfo {
|
|
140
|
-
junction_table_name: string;
|
|
141
|
-
source_column_name: string;
|
|
142
|
-
target_table_name: string;
|
|
143
|
-
target_column_name: string;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export interface TablePolicyInfo {
|
|
147
|
-
policy_name: string;
|
|
148
|
-
roles: string[];
|
|
149
|
-
cmd: string;
|
|
150
|
-
qual?: string;
|
|
151
|
-
with_check?: string;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export interface TableMetadata {
|
|
155
|
-
columns: TableColumnInfo[];
|
|
156
|
-
foreignKeys: TableForeignKeyInfo[];
|
|
157
|
-
junctions: TableJunctionInfo[];
|
|
158
|
-
policies: TablePolicyInfo[];
|
|
159
|
-
}
|