@rebasepro/types 0.11.1-canary.gfd39654 → 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/controllers/collection_registry.d.ts +1 -1
- package/dist/controllers/data.d.ts +148 -9
- package/dist/index.es.js +287 -97
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +20 -0
- package/dist/types/api_keys.d.ts +60 -5
- package/dist/types/collections.d.ts +56 -31
- package/dist/types/data_source.d.ts +42 -1
- package/dist/types/database_adapter.d.ts +13 -8
- package/dist/types/entity_callbacks.d.ts +2 -2
- 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/project_manifest.d.ts +146 -73
- package/dist/types/properties.d.ts +38 -49
- package/dist/types/storage_source.d.ts +60 -0
- package/dist/types/websockets.d.ts +0 -37
- package/package.json +1 -1
- package/src/controllers/collection_registry.ts +1 -1
- package/src/controllers/data.ts +155 -9
- package/src/types/admin_block.ts +48 -0
- package/src/types/api_keys.ts +61 -5
- package/src/types/collections.ts +68 -39
- package/src/types/data_source.ts +60 -1
- package/src/types/database_adapter.ts +13 -8
- package/src/types/entity_callbacks.ts +2 -2
- 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/project_manifest.ts +149 -80
- package/src/types/properties.ts +43 -56
- package/src/types/storage_source.ts +130 -0
- package/src/types/websockets.ts +0 -42
|
@@ -32,3 +32,23 @@
|
|
|
32
32
|
export declare const ADMIN_COLLECTION_KEYS: readonly ["Actions", "additionalFields", "alwaysApplyDefaultValues", "components", "defaultEntityAction", "defaultFilter", "defaultSelectedView", "defaultSize", "defaultViewMode", "disableDefaultActions", "enabledViews", "entityActions", "entityViews", "exportable", "filterPresets", "fixedFilter", "formAutoSave", "formView", "group", "hideFromNavigation", "hideIdFromCollection", "hideIdFromForm", "icon", "includeJsonView", "inlineEditing", "kanban", "listProperties", "localChangesBackup", "openEntityMode", "orderProperty", "pagination", "previewProperties", "propertiesOrder", "selectionController", "selectionEnabled", "sideDialogWidth", "sort", "titleProperty"];
|
|
33
33
|
/** A key of a collection's `admin` block. @group Models */
|
|
34
34
|
export type AdminCollectionKey = typeof ADMIN_COLLECTION_KEYS[number];
|
|
35
|
+
/**
|
|
36
|
+
* Every key that belongs inside a *property's* `admin` block, as data.
|
|
37
|
+
*
|
|
38
|
+
* The union of `AdminPropertyOptions` and its per-type extensions
|
|
39
|
+
* (`AdminStringOptions`, `AdminArrayOptions`, …) in `@rebasepro/admin-types`.
|
|
40
|
+
* It lives here for the same reason {@link ADMIN_COLLECTION_KEYS} does: the
|
|
41
|
+
* runtime consumers are core packages that the BaaS guard forbids from
|
|
42
|
+
* importing `@rebasepro/admin-types`. Here it is the boot-time collection
|
|
43
|
+
* validator in `@rebasepro/server`, which has to tell "you left `readOnly` at
|
|
44
|
+
* the top of the property, where nothing reads it" apart from "you invented a
|
|
45
|
+
* key we have never heard of".
|
|
46
|
+
*
|
|
47
|
+
* `@rebasepro/admin-types` re-exports this and asserts it names only real
|
|
48
|
+
* option keys.
|
|
49
|
+
*
|
|
50
|
+
* @group Models
|
|
51
|
+
*/
|
|
52
|
+
export declare const ADMIN_PROPERTY_KEYS: readonly ["canAddElements", "clearable", "columnWidth", "customProps", "disabled", "expanded", "Field", "Filter", "filterOperators", "fixedFilter", "hideFromCollection", "includeEntityLink", "includeId", "markdown", "minimalistView", "multiline", "Preview", "previewAsTag", "previewProperties", "readOnly", "sortable", "spreadChildren", "urlPreview", "widget", "widthPercentage"];
|
|
53
|
+
/** A key of a property's `admin` block. @group Models */
|
|
54
|
+
export type AdminPropertyKey = typeof ADMIN_PROPERTY_KEYS[number];
|
package/dist/types/api_keys.d.ts
CHANGED
|
@@ -1,15 +1,54 @@
|
|
|
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
|
+
* A single permission entry scoping an API key to a collection and set of
|
|
15
|
+
* operations.
|
|
16
|
+
*
|
|
17
|
+
* Use `"*"` as the collection value to grant access to all collections (and all
|
|
18
|
+
* custom functions). Custom functions are addressed with the `functions`
|
|
19
|
+
* namespace: `"functions"` grants every function, `"functions/<name>"` grants a
|
|
20
|
+
* single one.
|
|
21
|
+
*
|
|
22
|
+
* @group Models
|
|
23
|
+
*/
|
|
2
24
|
export interface ApiKeyPermission {
|
|
25
|
+
/** Collection slug, `"functions"`/`"functions/<name>"`, or `"*"` for everything. */
|
|
3
26
|
collection: string;
|
|
27
|
+
/** Allowed operations on the collection. */
|
|
4
28
|
operations: ("read" | "write" | "delete")[];
|
|
5
29
|
}
|
|
6
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* An API key with the secret portion masked — what list / get / update return.
|
|
32
|
+
* @group Models
|
|
33
|
+
*/
|
|
7
34
|
export interface ApiKeyMasked {
|
|
8
35
|
id: string;
|
|
9
36
|
name: string;
|
|
37
|
+
/** First 12 characters of the plaintext key, for display only. */
|
|
10
38
|
key_prefix: string;
|
|
11
39
|
permissions: ApiKeyPermission[];
|
|
40
|
+
/**
|
|
41
|
+
* When true, the key is granted the `admin` role: it passes the admin-gated
|
|
42
|
+
* routes (users, roles, cron, backups, logs, API keys) and the RLS
|
|
43
|
+
* `default_admin` policies. Non-admin keys carry only the `service` role —
|
|
44
|
+
* RLS grants them nothing unless a collection policy names that role.
|
|
45
|
+
*/
|
|
12
46
|
admin: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Requests per 15-minute window. `null` means "no per-key override" — the
|
|
49
|
+
* data rate limiter then applies its default API-key limit (1000/window
|
|
50
|
+
* unless configured otherwise), not unlimited.
|
|
51
|
+
*/
|
|
13
52
|
rate_limit: number | null;
|
|
14
53
|
created_by: string;
|
|
15
54
|
created_at: string;
|
|
@@ -18,26 +57,42 @@ export interface ApiKeyMasked {
|
|
|
18
57
|
expires_at: string | null;
|
|
19
58
|
revoked_at: string | null;
|
|
20
59
|
}
|
|
21
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Returned exactly once, when a key is created. The `key` field holds the full
|
|
62
|
+
* plaintext key — it is never stored or returned again.
|
|
63
|
+
* @group Models
|
|
64
|
+
*/
|
|
22
65
|
export interface ApiKeyWithSecret extends ApiKeyMasked {
|
|
66
|
+
/** Full plaintext API key (e.g. `rk_live_abc123...`). */
|
|
23
67
|
key: string;
|
|
24
68
|
}
|
|
25
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Payload for creating a new API key.
|
|
71
|
+
* @group Models
|
|
72
|
+
*/
|
|
26
73
|
export interface CreateApiKeyRequest {
|
|
27
74
|
name: string;
|
|
28
75
|
permissions: ApiKeyPermission[];
|
|
76
|
+
/** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
|
|
29
77
|
admin?: boolean;
|
|
78
|
+
/** Requests per 15-minute window. Omit or `null` for the server default. */
|
|
30
79
|
rate_limit?: number | null;
|
|
80
|
+
/** ISO-8601 expiration timestamp. Omit for no expiration. */
|
|
31
81
|
expires_at?: string | null;
|
|
32
82
|
}
|
|
33
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Payload for updating an existing API key. Only the fields provided change.
|
|
85
|
+
* @group Models
|
|
86
|
+
*/
|
|
34
87
|
export interface UpdateApiKeyRequest {
|
|
35
88
|
name?: string;
|
|
36
89
|
permissions?: ApiKeyPermission[];
|
|
90
|
+
/** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
|
|
37
91
|
admin?: boolean;
|
|
38
92
|
rate_limit?: number | null;
|
|
39
93
|
expires_at?: string | null;
|
|
40
94
|
}
|
|
95
|
+
/** @group Models */
|
|
41
96
|
export interface ApiKeysAPI {
|
|
42
97
|
listKeys(): Promise<{
|
|
43
98
|
keys: ApiKeyMasked[];
|
|
@@ -90,23 +90,26 @@ export interface BaseCollectionConfig<M extends Record<string, unknown> = Record
|
|
|
90
90
|
*/
|
|
91
91
|
auth?: boolean | AuthCollectionConfig;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* The schema generator automatically injects, for every collection, a
|
|
96
|
-
* baseline SELECT policy granting the trusted server context and the
|
|
97
|
-
* `admin` role read access (reads run under a restricted role, so RLS
|
|
98
|
-
* default-denies without it). For auth collections it additionally injects
|
|
99
|
-
* a self-read policy (`id = auth.uid()`) and an admin-only write gate
|
|
100
|
-
* (INSERT/UPDATE/DELETE require the `admin` role or the trusted server
|
|
101
|
-
* context), making privileged columns such as `roles` safe by default.
|
|
93
|
+
* Row-level authorization rules for this collection.
|
|
102
94
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
95
|
+
* Driver-agnostic on purpose, unlike `disableDefaultPolicies`, `table` and
|
|
96
|
+
* `relations`, which are declared on {@link PostgresCollectionConfig} only.
|
|
97
|
+
* The rules are a *contract* — who may read or write which rows — and each
|
|
98
|
+
* engine enforces it its own way:
|
|
106
99
|
*
|
|
107
|
-
*
|
|
100
|
+
* - **Postgres** compiles them to real `CREATE POLICY` statements and lets
|
|
101
|
+
* the database enforce them (see {@link PostgresCollectionConfig.securityRules},
|
|
102
|
+
* which narrows this with the raw-SQL details).
|
|
103
|
+
* - **MongoDB** translates them into a query filter it AND-s into every
|
|
104
|
+
* read and write, honouring `access`, `ownerField`, `roles`, `mode` and
|
|
105
|
+
* the `operation`/`operations` selectors, and making a best effort at raw
|
|
106
|
+
* `using`/`withCheck` SQL.
|
|
107
|
+
* - **Firestore** does not implement them at all; its own rules language is
|
|
108
|
+
* evaluated by Google, not from here. `supportsRLS` on
|
|
109
|
+
* {@link DataSourceCapabilities} reports which engines generate policies,
|
|
110
|
+
* which is not the same question as whether an engine honours a rule.
|
|
108
111
|
*/
|
|
109
|
-
|
|
112
|
+
securityRules?: readonly SecurityRule[];
|
|
110
113
|
/**
|
|
111
114
|
* This interface defines all the callbacks that can be used when a entity
|
|
112
115
|
* is being created, updated or deleted.
|
|
@@ -140,23 +143,6 @@ export interface BaseCollectionConfig<M extends Record<string, unknown> = Record
|
|
|
140
143
|
* quietly worked. The second case is the reason for the escape hatch.
|
|
141
144
|
*/
|
|
142
145
|
strictWrites?: boolean;
|
|
143
|
-
/**
|
|
144
|
-
* The database table name for this collection.
|
|
145
|
-
* Automatically set for PostgreSQL collections.
|
|
146
|
-
* For non-SQL backends, this may be undefined.
|
|
147
|
-
*/
|
|
148
|
-
table?: string;
|
|
149
|
-
/**
|
|
150
|
-
* Relations defined for this collection.
|
|
151
|
-
* Populated at normalization time from inline relation properties
|
|
152
|
-
* or explicit relation definitions.
|
|
153
|
-
*/
|
|
154
|
-
relations?: Relation[];
|
|
155
|
-
/**
|
|
156
|
-
* Security rules for this collection (Row Level Security).
|
|
157
|
-
* When defined, the backend enforces access control policies.
|
|
158
|
-
*/
|
|
159
|
-
securityRules?: readonly SecurityRule[];
|
|
160
146
|
}
|
|
161
147
|
/**
|
|
162
148
|
* A collection backed by PostgreSQL (or any SQL database).
|
|
@@ -205,6 +191,24 @@ export interface PostgresCollectionConfig<M extends Record<string, unknown> = Re
|
|
|
205
191
|
* - `auth.jwt()` — full JWT claims as JSONB
|
|
206
192
|
*/
|
|
207
193
|
securityRules?: readonly SecurityRule[];
|
|
194
|
+
/**
|
|
195
|
+
* Opt out of the framework's default Row Level Security policies.
|
|
196
|
+
*
|
|
197
|
+
* The schema generator automatically injects, for every collection, a
|
|
198
|
+
* baseline SELECT policy granting the trusted server context and the
|
|
199
|
+
* `admin` role read access (reads run under a restricted role, so RLS
|
|
200
|
+
* default-denies without it). For auth collections it additionally injects
|
|
201
|
+
* a self-read policy (`id = auth.uid()`) and an admin-only write gate
|
|
202
|
+
* (INSERT/UPDATE/DELETE require the `admin` role or the trusted server
|
|
203
|
+
* context), making privileged columns such as `roles` safe by default.
|
|
204
|
+
*
|
|
205
|
+
* Author-defined `securityRules` are permissive and broaden access on top
|
|
206
|
+
* of these defaults. Set this flag to `true` to remove the defaults
|
|
207
|
+
* entirely and take full responsibility for the collection's RLS.
|
|
208
|
+
*
|
|
209
|
+
* @default false
|
|
210
|
+
*/
|
|
211
|
+
disableDefaultPolicies?: boolean;
|
|
208
212
|
}
|
|
209
213
|
/**
|
|
210
214
|
* A collection backed by Firebase / Firestore.
|
|
@@ -329,6 +333,27 @@ export type AnyCollectionConfig = CollectionConfig<any, any>;
|
|
|
329
333
|
* @group Models
|
|
330
334
|
*/
|
|
331
335
|
export declare function isPostgresCollectionConfig<C extends CollectionConfig<any, any>>(collection: C): collection is C & PostgresCollectionConfig<any, any>;
|
|
336
|
+
/**
|
|
337
|
+
* Narrows to the SQL collection fields — `table`, `relations`,
|
|
338
|
+
* `disableDefaultPolicies` — by asking the engine's declared capabilities
|
|
339
|
+
* rather than by naming Postgres.
|
|
340
|
+
*
|
|
341
|
+
* The two halves of this already existed and were never joined. The engine
|
|
342
|
+
* split (`PostgresCollectionConfig` / `FirebaseCollectionConfig` /
|
|
343
|
+
* `MongoDBCollectionConfig`) said which fields belong to which engine at the
|
|
344
|
+
* type level; {@link DataSourceCapabilities} said the same thing at runtime,
|
|
345
|
+
* down to a `supportsRelations` flag. So call sites guarded on the capability
|
|
346
|
+
* and then read a field the base type had to declare for them — which is why
|
|
347
|
+
* those fields were on the base, and why a MongoDB collection could be written
|
|
348
|
+
* with a `table`.
|
|
349
|
+
*
|
|
350
|
+
* Prefer this over {@link isPostgresCollectionConfig} wherever the question is
|
|
351
|
+
* "does this collection live in a SQL table", so a custom SQL engine
|
|
352
|
+
* registered through `registerDataSourceCapabilities` is included.
|
|
353
|
+
*
|
|
354
|
+
* @group Models
|
|
355
|
+
*/
|
|
356
|
+
export declare function isRelationalCollectionConfig<C extends CollectionConfig<any, any>>(collection: C): collection is C & PostgresCollectionConfig<any, any>;
|
|
332
357
|
/**
|
|
333
358
|
* Type guard for Firebase / Firestore collections.
|
|
334
359
|
* @group Models
|
|
@@ -3,7 +3,7 @@ import { WhereFilterOp } from "./filter-operators";
|
|
|
3
3
|
* Describes the capabilities and features supported by a data source (driver).
|
|
4
4
|
*
|
|
5
5
|
* Each driver (Postgres, Firebase, MongoDB, etc.) declares which features it
|
|
6
|
-
* supports. The
|
|
6
|
+
* supports. The admin uses this descriptor to:
|
|
7
7
|
* - Show/hide editor tabs (e.g. Relations for SQL, Subcollections for Firebase)
|
|
8
8
|
* - Filter the property type picker (e.g. `relation` for SQL, `reference` for Firebase)
|
|
9
9
|
* - Toggle driver-specific form controls (e.g. `columnType` for SQL)
|
|
@@ -27,6 +27,16 @@ export interface DataSourceCapabilities {
|
|
|
27
27
|
supportsColumnTypes: boolean;
|
|
28
28
|
/** Does this source support real-time listeners? */
|
|
29
29
|
supportsRealtime: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Does this source store vectors natively?
|
|
32
|
+
*
|
|
33
|
+
* `VectorProperty` carries a `dimensions` and is pgvector-shaped. It was
|
|
34
|
+
* the one driver-specific property kind with no flag to gate it, so unlike
|
|
35
|
+
* every other field in this descriptor there was not even a runtime answer
|
|
36
|
+
* to appeal to — a Firestore collection could declare an embedding column
|
|
37
|
+
* and no driver would do anything with it.
|
|
38
|
+
*/
|
|
39
|
+
supportsVectors: boolean;
|
|
30
40
|
/**
|
|
31
41
|
* Canonical filter operators this engine can execute.
|
|
32
42
|
*
|
|
@@ -37,6 +47,27 @@ export interface DataSourceCapabilities {
|
|
|
37
47
|
* would throw at query time.
|
|
38
48
|
*/
|
|
39
49
|
filterOperators: readonly WhereFilterOp[];
|
|
50
|
+
/**
|
|
51
|
+
* Relation kinds this engine's driver can compile into a filter.
|
|
52
|
+
*
|
|
53
|
+
* Only `belongsTo` puts a column on the row being filtered; the others are
|
|
54
|
+
* answered with a correlated subquery over the junction or the target
|
|
55
|
+
* table, which not every driver can build. An engine with no relations at
|
|
56
|
+
* all declares none.
|
|
57
|
+
*
|
|
58
|
+
* The admin uses this to decide whether a relation column offers a filter
|
|
59
|
+
* control. Offering one an engine cannot answer is not cosmetic: a driver
|
|
60
|
+
* that drops the key it cannot resolve *widens* the read to every row, and
|
|
61
|
+
* one that fails closed answers a control the admin itself put on screen
|
|
62
|
+
* with a 400.
|
|
63
|
+
*
|
|
64
|
+
* Optional, so a third-party driver registered before this existed still
|
|
65
|
+
* compiles. Omitted means {@link DEFAULT_FILTERABLE_RELATION_KINDS} — the
|
|
66
|
+
* one kind that is a plain column comparison, which every relational
|
|
67
|
+
* driver can do. The subquery kinds are a real capability and have to be
|
|
68
|
+
* claimed rather than assumed: assuming them wrongly is the widening.
|
|
69
|
+
*/
|
|
70
|
+
filterableRelationKinds?: readonly string[];
|
|
40
71
|
/** Does this source support SQL admin operations (SQL editor, EXPLAIN, etc.)? */
|
|
41
72
|
supportsSQLAdmin: boolean;
|
|
42
73
|
/** Does this source support document admin operations (aggregation, stats)? */
|
|
@@ -128,6 +159,16 @@ export interface ResolvedDataSource {
|
|
|
128
159
|
/** Capabilities derived from {@link engine}. */
|
|
129
160
|
capabilities: DataSourceCapabilities;
|
|
130
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Relation kinds assumed filterable when a driver does not say.
|
|
164
|
+
*
|
|
165
|
+
* `belongsTo` alone: its filter is a comparison on a column of the row being
|
|
166
|
+
* filtered, the one shape that needs no query construction a driver might not
|
|
167
|
+
* have. Everything else is a correlated subquery over another table.
|
|
168
|
+
*
|
|
169
|
+
* @group Models
|
|
170
|
+
*/
|
|
171
|
+
export declare const DEFAULT_FILTERABLE_RELATION_KINDS: readonly string[];
|
|
131
172
|
/** @group Models */
|
|
132
173
|
export declare const POSTGRES_CAPABILITIES: DataSourceCapabilities;
|
|
133
174
|
/** @group Models */
|
|
@@ -93,17 +93,22 @@ export interface DatabaseAdapterInitConfig {
|
|
|
93
93
|
/** The shared collection registry to register into. */
|
|
94
94
|
collectionRegistry: CollectionRegistryInterface;
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
96
|
+
* Whether this driver should describe its own schema.
|
|
97
97
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
98
|
+
* True when the project declared no collections, so there is nothing to
|
|
99
|
+
* serve unless the driver reads the live database and reports what it found
|
|
100
|
+
* on `InitializedDriver.collections`. Drivers that cannot introspect may
|
|
101
|
+
* ignore it — `initializeRebaseBackend` fails the boot with their name
|
|
102
|
+
* rather than serving nothing.
|
|
103
|
+
*
|
|
104
|
+
* This was a `mode: "cms" | "baas"` flag, which was never independent of
|
|
105
|
+
* `collections`: every consumer already required the list to be empty
|
|
106
|
+
* before acting on it, so the flag could only ever agree or contradict.
|
|
102
107
|
*/
|
|
103
|
-
|
|
108
|
+
introspectCollections?: boolean;
|
|
104
109
|
/**
|
|
105
|
-
*
|
|
106
|
-
* introspect should honour `unprotectedTables`.
|
|
110
|
+
* Options for an introspecting driver — see `RebaseBackendConfig.baas`.
|
|
111
|
+
* Drivers that introspect should honour `unprotectedTables`.
|
|
107
112
|
*/
|
|
108
113
|
baas?: {
|
|
109
114
|
unprotectedTables?: "exclude" | "serve";
|
|
@@ -69,7 +69,7 @@ export interface AfterReadProps<M extends Record<string, unknown> = Record<strin
|
|
|
69
69
|
*/
|
|
70
70
|
collection: CollectionConfig<M>;
|
|
71
71
|
/**
|
|
72
|
-
* Full path of the
|
|
72
|
+
* Full path of the admin where this collection is being fetched.
|
|
73
73
|
* Might contain unresolved aliases.
|
|
74
74
|
*/
|
|
75
75
|
path: string;
|
|
@@ -106,7 +106,7 @@ export interface AfterSaveProps<M extends Record<string, unknown> = Record<strin
|
|
|
106
106
|
*/
|
|
107
107
|
collection: CollectionConfig<M>;
|
|
108
108
|
/**
|
|
109
|
-
* Full path of the
|
|
109
|
+
* Full path of the admin where this entity is being saved.
|
|
110
110
|
* Might contain unresolved aliases.
|
|
111
111
|
*/
|
|
112
112
|
path: string;
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
* One recorded change to a row.
|
|
19
|
+
* @group Backend
|
|
20
|
+
*/
|
|
21
|
+
export interface EntityHistoryEntry {
|
|
22
|
+
id: string;
|
|
23
|
+
/** The table (Postgres) or collection (MongoDB) the row belongs to. */
|
|
24
|
+
table_name: string;
|
|
25
|
+
/** The row's id, as a string regardless of its native type. */
|
|
26
|
+
entity_id: string;
|
|
27
|
+
action: "create" | "update" | "delete";
|
|
28
|
+
/** Which fields changed. `null` for creates and deletes. */
|
|
29
|
+
changed_fields: string[] | null;
|
|
30
|
+
values: Record<string, unknown> | null;
|
|
31
|
+
previous_values: Record<string, unknown> | null;
|
|
32
|
+
updated_by: string | null;
|
|
33
|
+
/** ISO-8601. A driver storing a native date converts on read. */
|
|
34
|
+
updated_at: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Arguments to record one change.
|
|
38
|
+
* @group Backend
|
|
39
|
+
*/
|
|
40
|
+
export interface RecordHistoryParams {
|
|
41
|
+
tableName: string;
|
|
42
|
+
id: string;
|
|
43
|
+
action: "create" | "update" | "delete";
|
|
44
|
+
values?: Record<string, unknown> | null;
|
|
45
|
+
previousValues?: Record<string, unknown> | null;
|
|
46
|
+
updatedBy?: string | null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* How much history to keep. Pruning runs per row after each write.
|
|
50
|
+
* @group Backend
|
|
51
|
+
*/
|
|
52
|
+
export interface HistoryRetentionConfig {
|
|
53
|
+
/** Max entries per row. Oldest pruned first. Default 200. */
|
|
54
|
+
maxEntries: number;
|
|
55
|
+
/** Entries older than this many days are pruned. Default 90. */
|
|
56
|
+
ttlDays: number;
|
|
57
|
+
}
|
|
58
|
+
/** @group Backend */
|
|
59
|
+
export interface FetchHistoryOptions {
|
|
60
|
+
limit?: number;
|
|
61
|
+
offset?: number;
|
|
62
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from "./component_ref";
|
|
|
19
19
|
export * from "./auth_adapter";
|
|
20
20
|
export * from "./database_adapter";
|
|
21
21
|
export * from "./api_keys";
|
|
22
|
+
export * from "./history";
|
|
23
|
+
export * from "./postgres_introspection";
|
|
22
24
|
export * from "./project_manifest";
|
|
23
25
|
export * from "./collection_contract";
|
|
24
26
|
export * from "./schema_version";
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
* A column, as `information_schema.columns` reports it.
|
|
22
|
+
* @group Models
|
|
23
|
+
*/
|
|
24
|
+
export interface TableColumnInfo {
|
|
25
|
+
column_name: string;
|
|
26
|
+
data_type: string;
|
|
27
|
+
udt_name: string;
|
|
28
|
+
/** `"YES"` or `"NO"` — `information_schema` reports this as text. */
|
|
29
|
+
is_nullable: string;
|
|
30
|
+
column_default: string | null;
|
|
31
|
+
character_maximum_length: number | null;
|
|
32
|
+
/** Enum values, populated for USER-DEFINED (enum) columns */
|
|
33
|
+
enum_values?: string[];
|
|
34
|
+
}
|
|
35
|
+
/** @group Models */
|
|
36
|
+
export interface TableForeignKeyInfo {
|
|
37
|
+
column_name: string;
|
|
38
|
+
foreign_table_name: string;
|
|
39
|
+
foreign_column_name: string;
|
|
40
|
+
}
|
|
41
|
+
/** @group Models */
|
|
42
|
+
export interface TableJunctionInfo {
|
|
43
|
+
junction_table_name: string;
|
|
44
|
+
source_column_name: string;
|
|
45
|
+
target_table_name: string;
|
|
46
|
+
target_column_name: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A policy as the *table metadata* query projects it.
|
|
50
|
+
*
|
|
51
|
+
* Distinct from {@link PostgresPolicy}, which is the RLS editor's fuller
|
|
52
|
+
* projection of `pg_policies` — this one carries only what the collection
|
|
53
|
+
* editor needs to show that a table is protected.
|
|
54
|
+
*
|
|
55
|
+
* @group Models
|
|
56
|
+
*/
|
|
57
|
+
export interface TablePolicyInfo {
|
|
58
|
+
policy_name: string;
|
|
59
|
+
roles: string[];
|
|
60
|
+
cmd: string;
|
|
61
|
+
qual?: string;
|
|
62
|
+
with_check?: string;
|
|
63
|
+
}
|
|
64
|
+
/** @group Models */
|
|
65
|
+
export interface TableMetadata {
|
|
66
|
+
columns: TableColumnInfo[];
|
|
67
|
+
foreignKeys: TableForeignKeyInfo[];
|
|
68
|
+
junctions: TableJunctionInfo[];
|
|
69
|
+
policies: TablePolicyInfo[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A row of `pg_policies`, as the RLS editors read it.
|
|
73
|
+
*
|
|
74
|
+
* Note the unseparated column names (`policyname`, `tablename`) — those are
|
|
75
|
+
* Postgres's, not ours. See {@link TablePolicyInfo} for the narrower projection
|
|
76
|
+
* the collection editor uses.
|
|
77
|
+
*
|
|
78
|
+
* @group Models
|
|
79
|
+
*/
|
|
80
|
+
export interface PostgresPolicy {
|
|
81
|
+
policyname: string;
|
|
82
|
+
tablename: string;
|
|
83
|
+
permissive: "PERMISSIVE" | "RESTRICTIVE";
|
|
84
|
+
roles: string[];
|
|
85
|
+
cmd: "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "ALL";
|
|
86
|
+
/** The `USING` clause. */
|
|
87
|
+
qual: string | null;
|
|
88
|
+
/** The `WITH CHECK` clause. */
|
|
89
|
+
with_check: string | null;
|
|
90
|
+
/**
|
|
91
|
+
* Whether this policy exists in the live database, in the collection's
|
|
92
|
+
* `securityRules`, or both. Computed by the editor, not by Postgres.
|
|
93
|
+
*/
|
|
94
|
+
status?: "live" | "code_only" | "both";
|
|
95
|
+
}
|