@rebasepro/types 0.10.0 → 0.10.1-canary.0a881d4

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.
Files changed (96) hide show
  1. package/dist/call_context.d.ts +51 -0
  2. package/dist/controllers/auth_state.d.ts +23 -0
  3. package/dist/controllers/client.d.ts +3 -1
  4. package/dist/controllers/collection_registry.d.ts +5 -1
  5. package/dist/controllers/data_driver.d.ts +31 -2
  6. package/dist/controllers/index.d.ts +1 -10
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.es.js +374 -1
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/types/admin_block.d.ts +34 -0
  11. package/dist/types/backend.d.ts +30 -1
  12. package/dist/types/channel_bus.d.ts +192 -0
  13. package/dist/types/collection_contract.d.ts +43 -0
  14. package/dist/types/collections.d.ts +17 -789
  15. package/dist/types/component_ref.d.ts +39 -6
  16. package/dist/types/entity_callbacks.d.ts +1 -1
  17. package/dist/types/index.d.ts +7 -15
  18. package/dist/types/project_manifest.d.ts +336 -0
  19. package/dist/types/properties.d.ts +12 -157
  20. package/dist/types/schema_version.d.ts +18 -0
  21. package/dist/types/security_rules.d.ts +320 -0
  22. package/dist/types/storage_authorize.d.ts +74 -0
  23. package/package.json +3 -6
  24. package/src/call_context.ts +56 -0
  25. package/src/controllers/auth_state.ts +24 -0
  26. package/src/controllers/client.ts +3 -2
  27. package/src/controllers/collection_registry.ts +5 -1
  28. package/src/controllers/data_driver.ts +58 -2
  29. package/src/controllers/index.ts +1 -10
  30. package/src/index.ts +1 -1
  31. package/src/types/admin_block.ts +75 -0
  32. package/src/types/backend.ts +33 -1
  33. package/src/types/channel_bus.ts +202 -0
  34. package/src/types/collection_contract.ts +278 -0
  35. package/src/types/collections.ts +25 -848
  36. package/src/types/component_ref.ts +40 -6
  37. package/src/types/entity_callbacks.ts +1 -1
  38. package/src/types/index.ts +7 -15
  39. package/src/types/policy.ts +25 -11
  40. package/src/types/project_manifest.ts +362 -0
  41. package/src/types/properties.ts +11 -169
  42. package/src/types/schema_version.ts +112 -0
  43. package/src/types/security_rules.ts +344 -0
  44. package/src/types/storage_authorize.ts +77 -0
  45. package/dist/controllers/analytics_controller.d.ts +0 -7
  46. package/dist/controllers/auth.d.ts +0 -110
  47. package/dist/controllers/customization_controller.d.ts +0 -61
  48. package/dist/controllers/dialogs_controller.d.ts +0 -36
  49. package/dist/controllers/local_config_persistence.d.ts +0 -20
  50. package/dist/controllers/navigation.d.ts +0 -225
  51. package/dist/controllers/registry.d.ts +0 -80
  52. package/dist/controllers/side_dialogs_controller.d.ts +0 -67
  53. package/dist/controllers/side_panel_controller.d.ts +0 -97
  54. package/dist/controllers/snackbar.d.ts +0 -24
  55. package/dist/rebase_context.d.ts +0 -110
  56. package/dist/types/breadcrumbs.d.ts +0 -26
  57. package/dist/types/builders.d.ts +0 -15
  58. package/dist/types/component_overrides.d.ts +0 -196
  59. package/dist/types/entity_actions.d.ts +0 -104
  60. package/dist/types/entity_link_builder.d.ts +0 -7
  61. package/dist/types/entity_views.d.ts +0 -95
  62. package/dist/types/export_import.d.ts +0 -21
  63. package/dist/types/formex.d.ts +0 -40
  64. package/dist/types/locales.d.ts +0 -4
  65. package/dist/types/modify_collections.d.ts +0 -5
  66. package/dist/types/plugins.d.ts +0 -277
  67. package/dist/types/property_config.d.ts +0 -74
  68. package/dist/types/slots.d.ts +0 -262
  69. package/dist/types/translations.d.ts +0 -915
  70. package/dist/types/user_management_delegate.d.ts +0 -22
  71. package/src/controllers/analytics_controller.tsx +0 -57
  72. package/src/controllers/auth.tsx +0 -121
  73. package/src/controllers/customization_controller.tsx +0 -72
  74. package/src/controllers/dialogs_controller.tsx +0 -37
  75. package/src/controllers/local_config_persistence.tsx +0 -22
  76. package/src/controllers/navigation.ts +0 -267
  77. package/src/controllers/registry.ts +0 -95
  78. package/src/controllers/side_dialogs_controller.tsx +0 -82
  79. package/src/controllers/side_panel_controller.tsx +0 -112
  80. package/src/controllers/snackbar.ts +0 -29
  81. package/src/rebase_context.tsx +0 -130
  82. package/src/types/breadcrumbs.ts +0 -27
  83. package/src/types/builders.ts +0 -17
  84. package/src/types/component_overrides.ts +0 -244
  85. package/src/types/entity_actions.tsx +0 -125
  86. package/src/types/entity_link_builder.ts +0 -8
  87. package/src/types/entity_views.tsx +0 -114
  88. package/src/types/export_import.ts +0 -26
  89. package/src/types/formex.ts +0 -45
  90. package/src/types/locales.ts +0 -81
  91. package/src/types/modify_collections.tsx +0 -6
  92. package/src/types/plugins.tsx +0 -346
  93. package/src/types/property_config.tsx +0 -95
  94. package/src/types/slots.tsx +0 -307
  95. package/src/types/translations.ts +0 -1026
  96. package/src/types/user_management_delegate.ts +0 -23
@@ -1,4 +1,37 @@
1
- import type React from "react";
1
+ /**
2
+ * How a collection points at a UI component without the backend learning about React.
3
+ *
4
+ * This file is the hinge the BaaS/admin split turns on. `ComponentRef` is named
5
+ * by `properties.ts` (`ui.Field`, `ui.Preview`, `ui.Filter`), and `properties.ts`
6
+ * must stay in the React-free core because every backend subsystem — validation,
7
+ * the drizzle schema generator, the OpenAPI generator, the SDK codegen — reads
8
+ * property definitions. If `ComponentRef` needed `React.ComponentType`, the whole
9
+ * property model would have to move to the admin layer with it.
10
+ *
11
+ * So the React types are described structurally instead of imported. Every form
12
+ * a React component takes is assignable to {@link ComponentLike}:
13
+ *
14
+ * - a function component is `(props: P) => ReactNode`
15
+ * - a class component satisfies the construct signature (`Component` has `render`)
16
+ * - `memo` and `forwardRef` return exotic components, which are callable
17
+ *
18
+ * The cost is that the return type is `unknown` rather than `ReactNode`, so a
19
+ * function that returns something React could not render is accepted here.
20
+ * `@rebasepro/admin-types` re-exports a `ReactComponentRef<P>` narrowed against
21
+ * the real `React.ComponentType` for authoring and for the admin's internals,
22
+ * which restores that check where it can be enforced.
23
+ */
24
+
25
+ /**
26
+ * Structural stand-in for `React.ComponentType<P>`.
27
+ *
28
+ * Deliberately not `Function` or `unknown`: those would accept anything and the
29
+ * resolver's runtime heuristics ({@link ComponentRef} form 3) would be all that
30
+ * stood between a typo and a blank screen.
31
+ */
32
+ export type ComponentLike<P = any> =
33
+ | ((props: P) => unknown)
34
+ | (new (props: P, context?: unknown) => { render(): unknown });
2
35
 
3
36
  /**
4
37
  * Internal marker for a lazily-loaded component reference.
@@ -9,11 +42,11 @@ import type React from "react";
9
42
  */
10
43
  export interface LazyComponentRef<P = unknown> {
11
44
  readonly __rebaseLazy: true;
12
- readonly load: () => Promise<{ default: React.ComponentType<P> }>;
45
+ readonly load: () => Promise<{ default: ComponentLike<P> }>;
13
46
  }
14
47
 
15
48
  /**
16
- * A reference to a React component that can be provided in three forms:
49
+ * A reference to a UI component that can be provided in three forms:
17
50
  *
18
51
  * 1. **String path** (recommended for collection configs):
19
52
  * ```ts
@@ -34,14 +67,15 @@ export interface LazyComponentRef<P = unknown> {
34
67
  * ```
35
68
  * Importing a component at the top level will pull React into the
36
69
  * backend runtime — only safe in code that the backend never imports.
70
+ * `pnpm check:headless` fails on a collection file that does this.
37
71
  *
38
72
  * @group Types
39
73
  */
40
74
  export type ComponentRef<P = any> =
41
- | React.ComponentType<P>
75
+ | string
42
76
  | LazyComponentRef<P>
43
- | (() => Promise<{ default: React.ComponentType<P> }>)
44
- | string;
77
+ | (() => Promise<{ default: ComponentLike<P> }>)
78
+ | ComponentLike<P>;
45
79
 
46
80
  /**
47
81
  * Type guard: checks if a value is a `LazyComponentRef` produced by the
@@ -1,7 +1,7 @@
1
1
  import type { CollectionConfig } from "./collections";
2
2
  import type { EntityStatus, EntityValues } from "./entities";
3
3
  import type { User } from "../users";
4
- import type { RebaseCallContext } from "../rebase_context";
4
+ import type { RebaseCallContext } from "../call_context";
5
5
 
6
6
  /**
7
7
  * Lifecycle callbacks for entity CRUD operations.
@@ -3,26 +3,16 @@ export * from "./filter-operators";
3
3
  export * from "./chips";
4
4
 
5
5
  export * from "./properties";
6
+ export * from "./admin_block";
6
7
  export * from "./collections";
7
8
  export * from "./relations";
8
9
  export * from "./policy";
10
+ export * from "./security_rules";
9
11
 
10
- export * from "./locales";
11
- export * from "./entity_link_builder";
12
- export * from "./user_management_delegate";
13
12
  export * from "./entity_callbacks";
14
- export * from "./export_import";
15
- export * from "./modify_collections";
16
- export * from "./formex";
17
13
  export * from "./websockets";
18
14
  export * from "./backend";
19
- export * from "./translations";
20
- export * from "./plugins";
21
- export * from "./builders";
22
- export * from "./slots";
23
- export * from "./entity_actions";
24
- export * from "./property_config";
25
- export * from "./entity_views";
15
+ export * from "./channel_bus";
26
16
  export * from "./data_source";
27
17
  export * from "./storage_source";
28
18
  export * from "./cron";
@@ -30,7 +20,9 @@ export * from "./backup";
30
20
  export * from "./component_ref";
31
21
  export * from "./auth_adapter";
32
22
  export * from "./database_adapter";
33
- export * from "./breadcrumbs";
34
- export * from "./component_overrides";
35
23
  export * from "./api_keys";
24
+ export * from "./project_manifest";
25
+ export * from "./collection_contract";
26
+ export * from "./schema_version";
27
+ export * from "./storage_authorize";
36
28
 
@@ -258,21 +258,35 @@ export interface AuthRolesPolicyOperand {
258
258
  export const policy = {
259
259
  true: (): TruePolicyExpression => ({ kind: "true" }),
260
260
  false: (): FalsePolicyExpression => ({ kind: "false" }),
261
- and: (...operands: readonly PolicyExpression[]): AndPolicyExpression => ({ kind: "and", operands: operands as PolicyExpression[] }),
262
- or: (...operands: readonly PolicyExpression[]): OrPolicyExpression => ({ kind: "or", operands: operands as PolicyExpression[] }),
263
- not: (operand: PolicyExpression): NotPolicyExpression => ({ kind: "not", operand }),
261
+ and: (...operands: readonly PolicyExpression[]): AndPolicyExpression => ({ kind: "and",
262
+ operands: operands as PolicyExpression[] }),
263
+ or: (...operands: readonly PolicyExpression[]): OrPolicyExpression => ({ kind: "or",
264
+ operands: operands as PolicyExpression[] }),
265
+ not: (operand: PolicyExpression): NotPolicyExpression => ({ kind: "not",
266
+ operand }),
264
267
  compare: (left: PolicyOperand, op: PolicyCompareOperator, right: PolicyOperand): ComparePolicyExpression =>
265
- ({ kind: "compare", op, left, right }),
266
- rolesOverlap: (roles: readonly string[]): RolesOverlapPolicyExpression => ({ kind: "rolesOverlap", roles: roles as string[] }),
267
- rolesContain: (roles: readonly string[]): RolesContainPolicyExpression => ({ kind: "rolesContain", roles: roles as string[] }),
268
+ ({ kind: "compare",
269
+ op,
270
+ left,
271
+ right }),
272
+ rolesOverlap: (roles: readonly string[]): RolesOverlapPolicyExpression => ({ kind: "rolesOverlap",
273
+ roles: roles as string[] }),
274
+ rolesContain: (roles: readonly string[]): RolesContainPolicyExpression => ({ kind: "rolesContain",
275
+ roles: roles as string[] }),
268
276
  authenticated: (): AuthenticatedPolicyExpression => ({ kind: "authenticated" }),
269
277
  serverContext: (): ServerContextPolicyExpression => ({ kind: "serverContext" }),
270
278
  existsIn: (args: { collection: string; where: PolicyExpression }): ExistsInPolicyExpression =>
271
- ({ kind: "existsIn", collection: args.collection, where: args.where }),
272
- raw: (sql: string): RawPolicyExpression => ({ kind: "raw", sql }),
273
- field: (name: string): FieldPolicyOperand => ({ kind: "field", name }),
274
- outerField: (name: string): OuterFieldPolicyOperand => ({ kind: "outerField", name }),
275
- literal: (value: string | number | boolean | null): LiteralPolicyOperand => ({ kind: "literal", value }),
279
+ ({ kind: "existsIn",
280
+ collection: args.collection,
281
+ where: args.where }),
282
+ raw: (sql: string): RawPolicyExpression => ({ kind: "raw",
283
+ sql }),
284
+ field: (name: string): FieldPolicyOperand => ({ kind: "field",
285
+ name }),
286
+ outerField: (name: string): OuterFieldPolicyOperand => ({ kind: "outerField",
287
+ name }),
288
+ literal: (value: string | number | boolean | null): LiteralPolicyOperand => ({ kind: "literal",
289
+ value }),
276
290
  authUid: (): AuthUidPolicyOperand => ({ kind: "authUid" }),
277
291
  authRoles: (): AuthRolesPolicyOperand => ({ kind: "authRoles" })
278
292
  };
@@ -0,0 +1,362 @@
1
+ /**
2
+ * The project manifest (`rebase.json`) and the build artifacts derived from it.
3
+ *
4
+ * Three separate documents live in this file, and keeping them distinct matters:
5
+ *
6
+ * 1. {@link RebaseProjectManifest} — `rebase.json`. **Authored** by the developer,
7
+ * committed to the repository. Declares topology only: which runtime major the
8
+ * project targets, and which apps *this repository* contributes to the project.
9
+ * Schema, security rules, hooks and functions stay in TypeScript under the
10
+ * config package — nothing that needs a type system belongs here.
11
+ *
12
+ * 2. {@link RebaseProjectLink} — the per-checkout link (`.rebase/cloud.json`).
13
+ * **Not committed**, because it is per-developer like a git remote. Says which
14
+ * deployed project this working copy points at, whether that is a Rebase Cloud
15
+ * project or the base URL of a self-hosted backend.
16
+ *
17
+ * 3. {@link RebaseBundleManifest} — `manifest.json` inside a built bundle.
18
+ * **Generated**, never hand-edited. It is the lockfile analogue: the exact
19
+ * contract a built artifact claims to satisfy, which the runtime validates
20
+ * before it boots and a control plane validates before it deploys.
21
+ *
22
+ * A repository declares only the apps it contains. The set of apps belonging to a
23
+ * project is held by the project itself, which is what makes multi-repo projects
24
+ * work: two repositories never need to know about each other, only about the
25
+ * project.
26
+ */
27
+
28
+ /**
29
+ * Which kind of thing an app is.
30
+ *
31
+ * - `backend` — the collections/hooks/functions that define the project's API.
32
+ * Exactly one per *project* (not per repository); the registry enforces it.
33
+ * - `static` — a pre-built client bundle (SPA, static site) served over CDN.
34
+ * - `admin` — the Rebase admin panel, either hosted by the platform or built
35
+ * into this repository.
36
+ * - `mobile` — a native app. Registration only: it gets client credentials and
37
+ * configuration, and is never built or hosted here.
38
+ * - `custom` — an arbitrary container image built from a Dockerfile. The eject
39
+ * hatch: full control, no managed-runtime guarantees.
40
+ */
41
+ export type RebaseAppType = "backend" | "static" | "admin" | "mobile" | "custom";
42
+
43
+ /**
44
+ * The backend app: the project's API surface.
45
+ *
46
+ * Paths are relative to the directory holding `rebase.json`. The defaults match
47
+ * the layout `rebase init` scaffolds, so a stock project may declare simply
48
+ * `{ "type": "backend" }`.
49
+ */
50
+ export interface RebaseBackendAppConfig {
51
+ type: "backend";
52
+ /** Directory of the config package (collections + index). Default `config`. */
53
+ config?: string;
54
+ /** Directory of server functions. Default `backend/functions`. */
55
+ functions?: string;
56
+ /** Directory of cron job definitions. Default `backend/crons` when present. */
57
+ crons?: string;
58
+ /**
59
+ * Path to the generated Drizzle schema module (tables/enums/relations).
60
+ * Default `backend/src/schema.generated.ts`.
61
+ */
62
+ 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
+ /**
72
+ * Module path (relative to `config`) exporting the auth users collection as
73
+ * its default export. Default `collections/users`.
74
+ */
75
+ usersCollection?: string;
76
+ }
77
+
78
+ /**
79
+ * A static client bundle — SPA or static site — built here and served from CDN.
80
+ */
81
+ export interface RebaseStaticAppConfig {
82
+ type: "static";
83
+ /** Package directory containing the client sources. */
84
+ root: string;
85
+ /** Command that produces `output`. Run from the repository root. */
86
+ build?: string;
87
+ /** Directory of built assets, relative to the repository root. */
88
+ output: string;
89
+ /**
90
+ * Serve `index.html` for unmatched paths (client-side routing).
91
+ * Default `true` — the overwhelmingly common case for a client app, and a
92
+ * static *site* generator emits real files for its routes anyway.
93
+ */
94
+ spa?: boolean;
95
+ }
96
+
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
+ }
114
+
115
+ /**
116
+ * A native app. Registered for credentials and configuration; never built here.
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.
125
+ *
126
+ * This is the deliberate escape hatch. A project containing one is not eligible
127
+ * for the managed runtime — the platform cannot make guarantees about an image
128
+ * it did not build — but it still deploys, and nothing else about the project
129
+ * changes.
130
+ */
131
+ export interface RebaseCustomAppConfig {
132
+ type: "custom";
133
+ /** Dockerfile path relative to the repository root. */
134
+ dockerfile?: string;
135
+ /** Build context relative to the repository root. Default `.`. */
136
+ context?: string;
137
+ /** Port the container listens on. Default 8080. */
138
+ port?: number;
139
+ }
140
+
141
+ export type RebaseAppConfig =
142
+ | RebaseBackendAppConfig
143
+ | RebaseStaticAppConfig
144
+ | RebaseAdminAppConfig
145
+ | RebaseMobileAppConfig
146
+ | RebaseCustomAppConfig;
147
+
148
+ /**
149
+ * `rebase.json` — the authored project manifest.
150
+ */
151
+ export interface RebaseProjectManifest {
152
+ /** JSON Schema URL, for editor completion. Ignored by the tooling. */
153
+ $schema?: string;
154
+ /**
155
+ * The runtime **major** this project targets, as a semver range
156
+ * (e.g. `^1`, `~1.4`, or an exact `1.4.2` to pin).
157
+ *
158
+ * The platform upgrades patches and minors underneath a project without
159
+ * asking; it never crosses a major. See {@link RUNTIME_CONTRACT_VERSION}.
160
+ */
161
+ runtime: string;
162
+ /**
163
+ * Apps this repository contributes, keyed by app name. The key is the app's
164
+ * identity within the project: it is what `rebase deploy <app>` names, what
165
+ * client credentials are issued against, and what a second repository must
166
+ * not collide with.
167
+ */
168
+ apps: Record<string, RebaseAppConfig>;
169
+ }
170
+
171
+ /**
172
+ * The per-checkout project link.
173
+ *
174
+ * Deliberately separate from `rebase.json`: the manifest is committed and shared,
175
+ * while the link is per-developer. Keeping them in one file would mean either
176
+ * committing someone's project id or gitignoring the topology.
177
+ */
178
+ export interface RebaseProjectLink {
179
+ /**
180
+ * A Rebase Cloud project id, or the base URL of any running Rebase backend
181
+ * (`https://api.example.com`). Both are first-class: every command that
182
+ * accepts a project reference accepts either, so a self-hosted project has
183
+ * the same tooling as a cloud one.
184
+ */
185
+ project: string;
186
+ /** Organization slug. Cloud projects only. */
187
+ org?: string;
188
+ /** Explicit API base URL, when it differs from the project's default. */
189
+ apiUrl?: string;
190
+ }
191
+
192
+ /**
193
+ * Whether a project can run on the managed runtime, and if not, precisely why.
194
+ *
195
+ * The reasons are returned rather than summarised so tooling can print something
196
+ * a developer can act on. "Not eligible" is never a dead end — it selects the
197
+ * custom-runtime path, which still deploys.
198
+ */
199
+ export interface ManagedCompatibility {
200
+ eligible: boolean;
201
+ reasons: string[];
202
+ }
203
+
204
+ // ─────────────────────────────────────────────────────────────────────────────
205
+ // Bundle
206
+ // ─────────────────────────────────────────────────────────────────────────────
207
+
208
+ /**
209
+ * Version of the bundle *format* itself.
210
+ *
211
+ * Bumped only when the on-disk layout changes in a way an older runtime could
212
+ * not read. A runtime accepts any bundle whose `bundleFormat` is less than or
213
+ * equal to its own — old bundles keep booting on new runtimes, which is the
214
+ * whole point of separating the artifact from the engine.
215
+ */
216
+ export const BUNDLE_FORMAT_VERSION = 1;
217
+
218
+ /**
219
+ * The runtime contract major.
220
+ *
221
+ * Distinct from the `@rebasepro/server` package version: the package may release
222
+ * any number of minors and patches while this stays put. It changes only when
223
+ * the bundle/runtime contract breaks compatibility, and a project's
224
+ * `manifest.runtime` range is matched against *this*.
225
+ */
226
+ export const RUNTIME_CONTRACT_VERSION = 1;
227
+
228
+ /** Where the runtime finds each part of the bundle. Paths are bundle-relative. */
229
+ export interface RebaseBundleEntrypoints {
230
+ /** Compiled config package directory (collections live under it). */
231
+ config?: string;
232
+ /** Compiled collections directory, when it differs from `<config>/collections`. */
233
+ collections?: string;
234
+ /** Compiled functions directory. */
235
+ functions?: string;
236
+ /** Compiled crons directory. */
237
+ crons?: string;
238
+ /** Compiled Drizzle schema module. */
239
+ schema?: string;
240
+ /** Module exporting the auth users collection (default export). */
241
+ usersCollection?: string;
242
+ /** Built admin assets, when the admin panel is bundled rather than hosted. */
243
+ admin?: string;
244
+ /** Built static assets to serve from the runtime, when not on a CDN. */
245
+ static?: string;
246
+ }
247
+
248
+ /**
249
+ * A native module found in the dependency closure.
250
+ *
251
+ * Recorded rather than merely counted so a rejection can name the offending
252
+ * package instead of saying "something here is native".
253
+ */
254
+ export interface NativeDependency {
255
+ name: string;
256
+ /** Why it was flagged — a `.node` binary, a gyp build, or an install script. */
257
+ reason: string;
258
+ }
259
+
260
+ /**
261
+ * `manifest.json` — generated, and the document the runtime and control plane
262
+ * both validate against.
263
+ */
264
+ export interface RebaseBundleManifest {
265
+ /** @see BUNDLE_FORMAT_VERSION */
266
+ bundleFormat: number;
267
+ runtime: {
268
+ /** The `runtime` range copied from `rebase.json`. */
269
+ range: string;
270
+ /** Exact `@rebasepro/server` version this bundle was built against. */
271
+ builtAgainst: string;
272
+ /** Runtime contract major this bundle requires. */
273
+ contract: number;
274
+ };
275
+ /**
276
+ * Hash of the compiled collection definitions.
277
+ *
278
+ * This is the contract stamp. A generated SDK records the value it was built
279
+ * from, a client sends it back, and a mismatch is what lets the platform say
280
+ * "this app was built against an older schema" instead of failing mysteriously
281
+ * at the first request. It covers collections only — a hook edit does not
282
+ * change a client's contract, so it must not invalidate every SDK.
283
+ */
284
+ schemaVersion: string;
285
+ /** Which app in `rebase.json` this bundle was built from. */
286
+ app: string;
287
+ /**
288
+ * What the runtime does with this bundle.
289
+ *
290
+ * - `cms` — a backend with declared collections; the runtime provisions their
291
+ * tables and serves the data API.
292
+ * - `baas` — a backend that introspects an existing database rather than
293
+ * declaring collections.
294
+ * - `static` — no backend at all: the bundle is a built SPA (`entry.static`),
295
+ * and the runtime only serves those assets. No database, no data sources —
296
+ * this is how a `static`/`admin` app runs on the same image as the backend.
297
+ */
298
+ mode: "cms" | "baas" | "static";
299
+ entry: RebaseBundleEntrypoints;
300
+ /** Collection slugs contained in the bundle, for quick inspection. */
301
+ collections?: string[];
302
+ hooks: {
303
+ /**
304
+ * Whether the dependency closure contains native code.
305
+ *
306
+ * The managed runtime refuses these: a prebuilt binary cannot be run on
307
+ * an image the platform did not build it for, and the honest failure is
308
+ * at deploy time rather than at 3am in a crash loop.
309
+ */
310
+ native: boolean;
311
+ nativeModules?: NativeDependency[];
312
+ };
313
+ /**
314
+ * What the bundle's config says about storage access control.
315
+ *
316
+ * Storage is not under RLS and its keys share one flat namespace, so a
317
+ * deployment with file storage enabled and no access model serves every
318
+ * user's files to every signed-in user. The runtime refuses to boot in that
319
+ * state — which, on a hosted platform that enables storage from the *console*
320
+ * rather than from the bundle, surfaces as a crash loop the developer cannot
321
+ * read.
322
+ *
323
+ * Recording it here lets a host reject the deploy with the reason instead.
324
+ * Absent on bundles built before this field existed.
325
+ */
326
+ storage?: {
327
+ /** Whether the config package exports a `storageAuthorize` hook. */
328
+ authorize: boolean;
329
+ };
330
+ deps: {
331
+ /** Runtime dependencies of user code, as declared. */
332
+ declared: Record<string, string>;
333
+ };
334
+ build: {
335
+ /** `@rebasepro/cli` version that produced this bundle. */
336
+ cli: string;
337
+ /** Node major the bundle was compiled on. */
338
+ node: string;
339
+ /** ISO-8601. */
340
+ createdAt: string;
341
+ };
342
+ }
343
+
344
+ /** The contract a running backend serves at `GET /api/meta/contract`. */
345
+ export interface RebaseProjectContract {
346
+ /** Matches {@link RebaseBundleManifest.schemaVersion}. */
347
+ schemaVersion: string;
348
+ runtime: {
349
+ /** `@rebasepro/server` version currently running. */
350
+ version: string;
351
+ contract: number;
352
+ };
353
+ mode: "cms" | "baas";
354
+ /** Full collection definitions, serialized — the input to SDK generation. */
355
+ collections: unknown[];
356
+ /** Collection slugs, for cheap inspection without parsing the definitions. */
357
+ collectionSlugs: string[];
358
+ generatedAt: string;
359
+ }
360
+
361
+ /** Header carrying the schema version an SDK was generated from. */
362
+ export const SCHEMA_VERSION_HEADER = "x-rebase-schema";