@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
|
@@ -119,17 +119,22 @@ export interface DatabaseAdapterInitConfig {
|
|
|
119
119
|
/** The shared collection registry to register into. */
|
|
120
120
|
collectionRegistry: CollectionRegistryInterface;
|
|
121
121
|
/**
|
|
122
|
-
*
|
|
122
|
+
* Whether this driver should describe its own schema.
|
|
123
123
|
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
124
|
+
* True when the project declared no collections, so there is nothing to
|
|
125
|
+
* serve unless the driver reads the live database and reports what it found
|
|
126
|
+
* on `InitializedDriver.collections`. Drivers that cannot introspect may
|
|
127
|
+
* ignore it — `initializeRebaseBackend` fails the boot with their name
|
|
128
|
+
* rather than serving nothing.
|
|
129
|
+
*
|
|
130
|
+
* This was a `mode: "cms" | "baas"` flag, which was never independent of
|
|
131
|
+
* `collections`: every consumer already required the list to be empty
|
|
132
|
+
* before acting on it, so the flag could only ever agree or contradict.
|
|
128
133
|
*/
|
|
129
|
-
|
|
134
|
+
introspectCollections?: boolean;
|
|
130
135
|
/**
|
|
131
|
-
*
|
|
132
|
-
* introspect should honour `unprotectedTables`.
|
|
136
|
+
* Options for an introspecting driver — see `RebaseBackendConfig.baas`.
|
|
137
|
+
* Drivers that introspect should honour `unprotectedTables`.
|
|
133
138
|
*/
|
|
134
139
|
baas?: { unprotectedTables?: "exclude" | "serve" };
|
|
135
140
|
}
|
|
@@ -85,7 +85,7 @@ export interface AfterReadProps<M extends Record<string, unknown> = Record<strin
|
|
|
85
85
|
collection: CollectionConfig<M>;
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* Full path of the
|
|
88
|
+
* Full path of the admin where this collection is being fetched.
|
|
89
89
|
* Might contain unresolved aliases.
|
|
90
90
|
*/
|
|
91
91
|
path: string;
|
|
@@ -132,7 +132,7 @@ export interface AfterSaveProps<M extends Record<string, unknown> = Record<strin
|
|
|
132
132
|
collection: CollectionConfig<M>;
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
* Full path of the
|
|
135
|
+
* Full path of the admin where this entity is being saved.
|
|
136
136
|
* Might contain unresolved aliases.
|
|
137
137
|
*/
|
|
138
138
|
path: string;
|
|
@@ -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
|
+
}
|
|
@@ -25,30 +25,50 @@
|
|
|
25
25
|
* project.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
import type { StorageSourceDefinition } from "./storage_source";
|
|
29
|
+
|
|
28
30
|
/**
|
|
29
31
|
* Which kind of thing an app is.
|
|
30
32
|
*
|
|
31
33
|
* - `backend` — the collections/hooks/functions that define the project's API.
|
|
32
34
|
* Exactly one per *project* (not per repository); the registry enforces it.
|
|
33
|
-
* - `static` — a pre-built client bundle (SPA, static site) served
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* hatch: full control, no managed-runtime guarantees.
|
|
35
|
+
* - `static` — a pre-built client bundle (SPA, static site), served from the
|
|
36
|
+
* backend process at its declared `path` or from a CDN. The admin panel is
|
|
37
|
+
* one of these: it is an app in the user's repository like any other.
|
|
38
|
+
*
|
|
39
|
+
* That is the whole list. Ownership of the server process is a property of the
|
|
40
|
+
* backend app ({@link RebaseBackendAppConfig.runtime}), not an app type.
|
|
40
41
|
*/
|
|
41
|
-
export type RebaseAppType = "backend" | "static"
|
|
42
|
+
export type RebaseAppType = "backend" | "static";
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
45
|
* The backend app: the project's API surface.
|
|
45
46
|
*
|
|
46
47
|
* Paths are relative to the directory holding `rebase.json`. The defaults match
|
|
47
48
|
* the layout `rebase init` scaffolds, so a stock project may declare simply
|
|
48
|
-
* `{ "type": "backend" }`.
|
|
49
|
+
* `{ "type": "backend", "runtime": "managed" }`.
|
|
49
50
|
*/
|
|
50
51
|
export interface RebaseBackendAppConfig {
|
|
51
52
|
type: "backend";
|
|
53
|
+
/**
|
|
54
|
+
* Who owns the process this backend runs in.
|
|
55
|
+
*
|
|
56
|
+
* - `managed` — the platform's runtime image boots this project's bundle.
|
|
57
|
+
* You supply collections, functions, crons and schema; Rebase supplies the
|
|
58
|
+
* server.
|
|
59
|
+
* - `custom` — this repository builds its own image and entrypoint. The
|
|
60
|
+
* escape hatch: full control, no managed-runtime guarantees.
|
|
61
|
+
*
|
|
62
|
+
* Independent of *where* it runs. Both run on Rebase Cloud and both
|
|
63
|
+
* self-host — the destination lives in `.rebase/cloud.json`, not here. See
|
|
64
|
+
* `docker/docker-compose.selfhost.yml`, which boots a managed bundle on a
|
|
65
|
+
* developer's own Docker host.
|
|
66
|
+
*
|
|
67
|
+
* This is authored rather than inferred on purpose. It is the single most
|
|
68
|
+
* consequential fact about a deployment, and inferring it is what used to
|
|
69
|
+
* land projects on the custom runtime without anyone choosing it.
|
|
70
|
+
*/
|
|
71
|
+
runtime: "managed" | "custom";
|
|
52
72
|
/** Directory of the config package (collections + index). Default `config`. */
|
|
53
73
|
config?: string;
|
|
54
74
|
/** Directory of server functions. Default `backend/functions`. */
|
|
@@ -60,23 +80,25 @@ export interface RebaseBackendAppConfig {
|
|
|
60
80
|
* Default `backend/src/schema.generated.ts`.
|
|
61
81
|
*/
|
|
62
82
|
schema?: string;
|
|
63
|
-
/**
|
|
64
|
-
* Which collections source the runtime uses.
|
|
65
|
-
*
|
|
66
|
-
* - `cms` (default) — collections come from the config package.
|
|
67
|
-
* - `baas` — collections are introspected from the live database at boot and
|
|
68
|
-
* the config package is not required.
|
|
69
|
-
*/
|
|
70
|
-
mode?: "cms" | "baas";
|
|
71
83
|
/**
|
|
72
84
|
* Module path (relative to `config`) exporting the auth users collection as
|
|
73
85
|
* its default export. Default `collections/users`.
|
|
74
86
|
*/
|
|
75
87
|
usersCollection?: string;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* `runtime: "custom"` only. Dockerfile path relative to the repository root.
|
|
91
|
+
* Default `Dockerfile`.
|
|
92
|
+
*/
|
|
93
|
+
dockerfile?: string;
|
|
94
|
+
/** `runtime: "custom"` only. Build context relative to the root. Default `.`. */
|
|
95
|
+
context?: string;
|
|
96
|
+
/** `runtime: "custom"` only. Port the container listens on. Default 8080. */
|
|
97
|
+
port?: number;
|
|
76
98
|
}
|
|
77
99
|
|
|
78
100
|
/**
|
|
79
|
-
* A static client bundle — SPA or static site — built here and served
|
|
101
|
+
* A static client bundle — SPA or static site — built here and served at `path`.
|
|
80
102
|
*/
|
|
81
103
|
export interface RebaseStaticAppConfig {
|
|
82
104
|
type: "static";
|
|
@@ -87,64 +109,50 @@ export interface RebaseStaticAppConfig {
|
|
|
87
109
|
/** Directory of built assets, relative to the repository root. */
|
|
88
110
|
output: string;
|
|
89
111
|
/**
|
|
90
|
-
*
|
|
112
|
+
* Public base path this app is served under. Default `/`.
|
|
113
|
+
*
|
|
114
|
+
* Several static apps run in one process, each at its own path — the API at
|
|
115
|
+
* `/api`, a site at `/`, the admin at `/admin` — which is what keeps a
|
|
116
|
+
* self-hosted deployment a single container.
|
|
117
|
+
*
|
|
118
|
+
* **This is a build-time input, not only a serving concern.** An app mounted
|
|
119
|
+
* at `/admin` must be *built* for `/admin` (Vite's `base`), or `index.html`
|
|
120
|
+
* loads and every asset 404s: a blank page with no server error. `rebase
|
|
121
|
+
* build` passes it as `REBASE_APP_BASE` and asserts the emitted HTML honours
|
|
122
|
+
* it. Changing this value requires rebuilding the app.
|
|
123
|
+
*/
|
|
124
|
+
path?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Serve `index.html` for unmatched paths under `path` (client-side routing).
|
|
91
127
|
* Default `true` — the overwhelmingly common case for a client app, and a
|
|
92
128
|
* static *site* generator emits real files for its routes anyway.
|
|
93
129
|
*/
|
|
94
130
|
spa?: boolean;
|
|
95
131
|
}
|
|
96
132
|
|
|
97
|
-
|
|
98
|
-
* The admin panel.
|
|
99
|
-
*
|
|
100
|
-
* `hosted` is the default and means the platform serves it — nothing is built
|
|
101
|
-
* into this repository and nothing ships in the bundle. `bundled` builds it here,
|
|
102
|
-
* which is what a self-hosted or air-gapped deployment wants.
|
|
103
|
-
*/
|
|
104
|
-
export interface RebaseAdminAppConfig {
|
|
105
|
-
type: "admin";
|
|
106
|
-
mode?: "hosted" | "bundled";
|
|
107
|
-
/** Only for `bundled`: package directory containing the admin sources. */
|
|
108
|
-
root?: string;
|
|
109
|
-
/** Only for `bundled`: build command. */
|
|
110
|
-
build?: string;
|
|
111
|
-
/** Only for `bundled`: directory of built assets. */
|
|
112
|
-
output?: string;
|
|
113
|
-
}
|
|
133
|
+
export type RebaseAppConfig = RebaseBackendAppConfig | RebaseStaticAppConfig;
|
|
114
134
|
|
|
115
135
|
/**
|
|
116
|
-
*
|
|
117
|
-
*/
|
|
118
|
-
export interface RebaseMobileAppConfig {
|
|
119
|
-
type: "mobile";
|
|
120
|
-
platform: "ios" | "android" | "other";
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* An app built from a Dockerfile into an arbitrary image.
|
|
136
|
+
* One declared storage source, as authored in `rebase.json`.
|
|
125
137
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
138
|
+
* The key comes from the enclosing record, so this is
|
|
139
|
+
* {@link StorageSourceDefinition} minus its `key` — the same document the
|
|
140
|
+
* runtime registry and the frontend router consume, expressed the way a JSON
|
|
141
|
+
* object naturally expresses "a set of named things".
|
|
130
142
|
*/
|
|
131
|
-
export interface
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
143
|
+
export interface RebaseStorageSourceConfig {
|
|
144
|
+
/** Engine backing this source: `local`, `s3`, `gcs`, or a custom id. */
|
|
145
|
+
engine: string;
|
|
146
|
+
/**
|
|
147
|
+
* How the frontend reaches it. Default `server` (proxied through
|
|
148
|
+
* `/api/storage`). `direct` means a provider SDK talks to the bucket and the
|
|
149
|
+
* backend is not in the upload path.
|
|
150
|
+
*/
|
|
151
|
+
transport?: "server" | "direct";
|
|
152
|
+
/** Human-readable label for the console and the admin UI. */
|
|
153
|
+
label?: string;
|
|
139
154
|
}
|
|
140
155
|
|
|
141
|
-
export type RebaseAppConfig =
|
|
142
|
-
| RebaseBackendAppConfig
|
|
143
|
-
| RebaseStaticAppConfig
|
|
144
|
-
| RebaseAdminAppConfig
|
|
145
|
-
| RebaseMobileAppConfig
|
|
146
|
-
| RebaseCustomAppConfig;
|
|
147
|
-
|
|
148
156
|
/**
|
|
149
157
|
* `rebase.json` — the authored project manifest.
|
|
150
158
|
*/
|
|
@@ -152,13 +160,17 @@ export interface RebaseProjectManifest {
|
|
|
152
160
|
/** JSON Schema URL, for editor completion. Ignored by the tooling. */
|
|
153
161
|
$schema?: string;
|
|
154
162
|
/**
|
|
155
|
-
* The runtime **major** this project targets, as a semver range
|
|
163
|
+
* The runtime contract **major** this project targets, as a semver range
|
|
156
164
|
* (e.g. `^1`, `~1.4`, or an exact `1.4.2` to pin).
|
|
157
165
|
*
|
|
158
166
|
* The platform upgrades patches and minors underneath a project without
|
|
159
167
|
* asking; it never crosses a major. See {@link RUNTIME_CONTRACT_VERSION}.
|
|
168
|
+
*
|
|
169
|
+
* Named `rebase` rather than `runtime` so that `runtime` means exactly one
|
|
170
|
+
* thing — {@link RebaseBackendAppConfig.runtime}, who owns the process. It
|
|
171
|
+
* reads like `engines` in a `package.json`, which is what it is.
|
|
160
172
|
*/
|
|
161
|
-
|
|
173
|
+
rebase: string;
|
|
162
174
|
/**
|
|
163
175
|
* Apps this repository contributes, keyed by app name. The key is the app's
|
|
164
176
|
* identity within the project: it is what `rebase deploy <app>` names, what
|
|
@@ -166,6 +178,28 @@ export interface RebaseProjectManifest {
|
|
|
166
178
|
* not collide with.
|
|
167
179
|
*/
|
|
168
180
|
apps: Record<string, RebaseAppConfig>;
|
|
181
|
+
/**
|
|
182
|
+
* Storage sources this project uses, keyed by source key.
|
|
183
|
+
*
|
|
184
|
+
* **Topology only — never credentials.** Which buckets exist is a property of
|
|
185
|
+
* the project and belongs in the repository; how to reach each one is a
|
|
186
|
+
* property of the deployment and lives in the environment, read per source
|
|
187
|
+
* from `<BASE>__<KEY>` (`S3_BUCKET__MEDIA` for a source keyed `media`). The
|
|
188
|
+
* default source takes no suffix, so a single-bucket project configured with
|
|
189
|
+
* plain `S3_BUCKET` keeps working having declared nothing at all.
|
|
190
|
+
*
|
|
191
|
+
* Declared here rather than only in the config package because this file is
|
|
192
|
+
* the one artifact a host can read *before* running a build. That is what
|
|
193
|
+
* lets a console show "this project wants a `media` bucket, and it has none"
|
|
194
|
+
* on a project's first deploy, and it is why the managed and custom runtimes
|
|
195
|
+
* can present the same list — a custom build emits no bundle manifest, so a
|
|
196
|
+
* declaration that lived only in compiled config would leave every custom
|
|
197
|
+
* project invisible.
|
|
198
|
+
*
|
|
199
|
+
* Omitted entirely means one default source, which is the overwhelmingly
|
|
200
|
+
* common project and must not be required to say so.
|
|
201
|
+
*/
|
|
202
|
+
storage?: Record<string, RebaseStorageSourceConfig>;
|
|
169
203
|
}
|
|
170
204
|
|
|
171
205
|
/**
|
|
@@ -212,8 +246,16 @@ export interface ManagedCompatibility {
|
|
|
212
246
|
* not read. A runtime accepts any bundle whose `bundleFormat` is less than or
|
|
213
247
|
* equal to its own — old bundles keep booting on new runtimes, which is the
|
|
214
248
|
* whole point of separating the artifact from the engine.
|
|
249
|
+
*
|
|
250
|
+
* - **1** — `mode: "cms" | "baas" | "static"`, `entry.static` a single directory
|
|
251
|
+
* string, `entry.admin` for a bundled admin panel.
|
|
252
|
+
* - **2** — `kind: "backend" | "static"`, `entry.static` a list of
|
|
253
|
+
* {@link RebaseBundleStatic}, `entry.admin` removed. A format-1 runtime reading
|
|
254
|
+
* one of these would find no `mode` and an array where it expects a string, so
|
|
255
|
+
* the bump is what turns that into a refusal to boot instead of a bundle that
|
|
256
|
+
* starts and serves nothing.
|
|
215
257
|
*/
|
|
216
|
-
export const BUNDLE_FORMAT_VERSION =
|
|
258
|
+
export const BUNDLE_FORMAT_VERSION = 2;
|
|
217
259
|
|
|
218
260
|
/**
|
|
219
261
|
* The runtime contract major.
|
|
@@ -239,10 +281,25 @@ export interface RebaseBundleEntrypoints {
|
|
|
239
281
|
schema?: string;
|
|
240
282
|
/** Module exporting the auth users collection (default export). */
|
|
241
283
|
usersCollection?: string;
|
|
242
|
-
/**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Built static apps to serve from this process, in declaration order.
|
|
286
|
+
*
|
|
287
|
+
* A list rather than a single directory because one process serves several
|
|
288
|
+
* apps at different paths — a site at `/` and the admin at `/admin`. The
|
|
289
|
+
* runtime mounts them longest-path-first so the `/`-rooted app's catch-all
|
|
290
|
+
* does not claim its siblings' URLs.
|
|
291
|
+
*/
|
|
292
|
+
static?: RebaseBundleStatic[];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** One built static app inside a bundle. */
|
|
296
|
+
export interface RebaseBundleStatic {
|
|
297
|
+
/** Public base path, e.g. `/` or `/admin`. */
|
|
298
|
+
path: string;
|
|
299
|
+
/** Bundle-relative directory holding the built assets. */
|
|
300
|
+
dir: string;
|
|
301
|
+
/** Serve `index.html` for unmatched paths under `path`. */
|
|
302
|
+
spa: boolean;
|
|
246
303
|
}
|
|
247
304
|
|
|
248
305
|
/**
|
|
@@ -287,15 +344,17 @@ export interface RebaseBundleManifest {
|
|
|
287
344
|
/**
|
|
288
345
|
* What the runtime does with this bundle.
|
|
289
346
|
*
|
|
290
|
-
* - `
|
|
291
|
-
*
|
|
292
|
-
* - `
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
347
|
+
* - `backend` — boot the full server: database, auth and the data API, plus
|
|
348
|
+
* any static apps in `entry.static`.
|
|
349
|
+
* - `static` — no backend at all: serve `entry.static` and nothing else. No
|
|
350
|
+
* database, no auth, no data sources. This is how a static app runs on the
|
|
351
|
+
* same image as the backend.
|
|
352
|
+
*
|
|
353
|
+
* Replaces an earlier `mode: "cms" | "baas" | "static"`. The cms/baas
|
|
354
|
+
* distinction was never a third kind of thing — it is simply whether
|
|
355
|
+
* `entry.config` is present, so it is derived rather than declared.
|
|
297
356
|
*/
|
|
298
|
-
|
|
357
|
+
kind: "backend" | "static";
|
|
299
358
|
entry: RebaseBundleEntrypoints;
|
|
300
359
|
/** Collection slugs contained in the bundle, for quick inspection. */
|
|
301
360
|
collections?: string[];
|
|
@@ -326,6 +385,17 @@ export interface RebaseBundleManifest {
|
|
|
326
385
|
storage?: {
|
|
327
386
|
/** Whether the config package exports a `storageAuthorize` hook. */
|
|
328
387
|
authorize: boolean;
|
|
388
|
+
/**
|
|
389
|
+
* Every storage source this bundle expects, resolved at build time from
|
|
390
|
+
* `rebase.json`'s `storage` block merged with any `storageSources` the
|
|
391
|
+
* config package exports.
|
|
392
|
+
*
|
|
393
|
+
* Recorded so the runtime does not have to import user code to learn its
|
|
394
|
+
* own topology, and so a host can tell — from the artifact alone, before
|
|
395
|
+
* starting anything — which buckets need configuring. Absent on bundles
|
|
396
|
+
* built before this field existed, which means one default source.
|
|
397
|
+
*/
|
|
398
|
+
sources?: StorageSourceDefinition[];
|
|
329
399
|
};
|
|
330
400
|
deps: {
|
|
331
401
|
/** Runtime dependencies of user code, as declared. */
|
|
@@ -350,7 +420,6 @@ export interface RebaseProjectContract {
|
|
|
350
420
|
version: string;
|
|
351
421
|
contract: number;
|
|
352
422
|
};
|
|
353
|
-
mode: "cms" | "baas";
|
|
354
423
|
/** Full collection definitions, serialized — the input to SDK generation. */
|
|
355
424
|
collections: unknown[];
|
|
356
425
|
/** Collection slugs, for cheap inspection without parsing the definitions. */
|