@rebasepro/types 0.16.0 → 0.16.1-canary.g0d7af95

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 (57) hide show
  1. package/dist/call_context.d.ts +5 -5
  2. package/dist/controllers/auth_state.d.ts +1 -1
  3. package/dist/controllers/client.d.ts +22 -9
  4. package/dist/controllers/collection_registry.d.ts +2 -2
  5. package/dist/controllers/data.d.ts +4 -12
  6. package/dist/controllers/data_driver.d.ts +7 -7
  7. package/dist/controllers/email.d.ts +54 -2
  8. package/dist/controllers/index.d.ts +8 -9
  9. package/dist/controllers/storage.d.ts +4 -4
  10. package/dist/index.d.ts +5 -5
  11. package/dist/index.es.js +433 -3
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/types/admin_block.d.ts +1 -1
  14. package/dist/types/auth_adapter.d.ts +18 -9
  15. package/dist/types/backend.d.ts +23 -10
  16. package/dist/types/collection_contract.d.ts +1 -1
  17. package/dist/types/collections.d.ts +34 -9
  18. package/dist/types/component_ref.d.ts +3 -2
  19. package/dist/types/cron.d.ts +1 -25
  20. package/dist/types/data_source.d.ts +1 -1
  21. package/dist/types/database_adapter.d.ts +5 -5
  22. package/dist/types/entities.d.ts +1 -1
  23. package/dist/types/entity_callbacks.d.ts +4 -4
  24. package/dist/types/index.d.ts +33 -29
  25. package/dist/types/indexes.d.ts +179 -0
  26. package/dist/types/project_manifest.d.ts +132 -27
  27. package/dist/types/properties.d.ts +58 -6
  28. package/dist/types/relations.d.ts +1 -1
  29. package/dist/types/resource_kinds.d.ts +189 -0
  30. package/dist/types/resources.d.ts +197 -0
  31. package/dist/types/schema_editing.d.ts +127 -0
  32. package/dist/types/schema_version.d.ts +1 -1
  33. package/dist/types/security_rules.d.ts +1 -1
  34. package/dist/types/storage_source.d.ts +27 -0
  35. package/dist/users/index.d.ts +1 -1
  36. package/package.json +2 -2
  37. package/src/controllers/client.ts +14 -1
  38. package/src/controllers/data.ts +0 -9
  39. package/src/controllers/email.ts +55 -2
  40. package/src/controllers/index.ts +0 -1
  41. package/src/controllers/storage.ts +4 -4
  42. package/src/types/admin_block.ts +1 -2
  43. package/src/types/auth_adapter.ts +18 -10
  44. package/src/types/backend.ts +18 -1
  45. package/src/types/collections.ts +28 -2
  46. package/src/types/component_ref.ts +3 -2
  47. package/src/types/cron.ts +0 -24
  48. package/src/types/index.ts +4 -0
  49. package/src/types/indexes.ts +180 -0
  50. package/src/types/project_manifest.ts +139 -26
  51. package/src/types/properties.ts +54 -0
  52. package/src/types/resource_kinds.ts +324 -0
  53. package/src/types/resources.ts +368 -0
  54. package/src/types/schema_editing.ts +154 -0
  55. package/src/types/storage_source.ts +28 -0
  56. package/dist/controllers/database_admin.d.ts +0 -11
  57. package/src/controllers/database_admin.ts +0 -22
@@ -24,7 +24,8 @@
24
24
  * work: two repositories never need to know about each other, only about the
25
25
  * project.
26
26
  */
27
- import type { StorageSourceDefinition } from "./storage_source";
27
+ import type { StorageSourceDefinition } from "./storage_source.js";
28
+ import type { ResourceGraph } from "./resources.js";
28
29
  /**
29
30
  * Which kind of thing an app is.
30
31
  *
@@ -58,7 +59,7 @@ export interface RebaseBackendAppConfig {
58
59
  *
59
60
  * Independent of *where* it runs. Both run on Rebase Cloud and both
60
61
  * self-host — the destination lives in `.rebase/cloud.json`, not here. See
61
- * `docker/docker-compose.selfhost.yml`, which boots a managed bundle on a
62
+ * `infra/docker/docker-compose.selfhost.yml`, which boots a managed bundle on a
62
63
  * developer's own Docker host.
63
64
  *
64
65
  * This is authored rather than inferred on purpose. It is the single most
@@ -125,6 +126,31 @@ export interface RebaseStaticAppConfig {
125
126
  spa?: boolean;
126
127
  }
127
128
  export type RebaseAppConfig = RebaseBackendAppConfig | RebaseStaticAppConfig;
129
+ /**
130
+ * Path prefixes the backend owns, which no static app may claim.
131
+ *
132
+ * One process — and, on the platform, one hostname — serves both the API and
133
+ * however many static apps a project has. Mounting is longest-path-first, so an
134
+ * app declaring `/api` would win against the API itself and every request to it
135
+ * would be answered with that app's `index.html`: a 200 carrying HTML where the
136
+ * caller expected JSON, from a project that looks deployed and healthy.
137
+ *
138
+ * Declared here rather than in either enforcer because both must agree. The CLI
139
+ * checks it so a developer finds out while editing `rebase.json`; the control
140
+ * plane checks it again at deploy intake, because the front door's correctness
141
+ * cannot rest on a check that ran in somebody else's CLI — and a repository can
142
+ * be deployed by a CLI older than this rule.
143
+ */
144
+ export declare const RESERVED_BACKEND_PREFIXES: readonly ["/api", "/health", "/healthz", "/livez", "/readyz", "/metrics"];
145
+ /**
146
+ * Whether `path` collides with a prefix the backend owns.
147
+ *
148
+ * Compares at segment boundaries, so `/api` and `/api/v2` collide while
149
+ * `/apidocs` does not — the same rule the router matches with, because a check
150
+ * that is stricter than the router rejects paths that would have worked, and one
151
+ * that is looser admits paths that will not.
152
+ */
153
+ export declare function reservedPrefixFor(path: string): string | undefined;
128
154
  /**
129
155
  * One declared storage source, as authored in `rebase.json`.
130
156
  *
@@ -171,27 +197,20 @@ export interface RebaseProjectManifest {
171
197
  */
172
198
  apps: Record<string, RebaseAppConfig>;
173
199
  /**
174
- * Storage sources this project uses, keyed by source key.
200
+ * Buckets are NOT declared here any more.
175
201
  *
176
- * **Topology only — never credentials.** Which buckets exist is a property of
177
- * the project and belongs in the repository; how to reach each one is a
178
- * property of the deployment and lives in the environment, read per source
179
- * from `<BASE>__<KEY>` (`S3_BUCKET__MEDIA` for a source keyed `media`). The
180
- * default source takes no suffix, so a single-bucket project configured with
181
- * plain `S3_BUCKET` keeps working having declared nothing at all.
202
+ * They were, and the runtime merged this block with the declarations in
203
+ * config code — a bucket named in both had one engine kept and the other
204
+ * silently discarded. Two homes for one concept, with a merge to decide
205
+ * between them, is the shape this whole model replaced.
182
206
  *
183
- * Declared here rather than only in the config package because this file is
184
- * the one artifact a host can read *before* running a build. That is what
185
- * lets a console show "this project wants a `media` bucket, and it has none"
186
- * on a project's first deploy, and it is why the managed and custom runtimes
187
- * can present the same list — a custom build emits no bundle manifest, so a
188
- * declaration that lived only in compiled config would leave every custom
189
- * project invisible.
190
- *
191
- * Omitted entirely means one default source, which is the overwhelmingly
192
- * common project and must not be required to say so.
207
+ * `bucket("media", { engine: "s3" })` in the project's config declares one
208
+ * now, and `rebase resources --write` generates `rebase.resources.json`,
209
+ * which is what a host reads before a build. A `storage` block left in this
210
+ * file is refused by the validator, by name, with the replacement in the
211
+ * message — not ignored, because a key that still parses and does nothing
212
+ * is the failure this removed.
193
213
  */
194
- storage?: Record<string, RebaseStorageSourceConfig>;
195
214
  /**
196
215
  * Repository-wide opt-out from anonymous CLI usage sharing.
197
216
  *
@@ -263,6 +282,31 @@ export declare const BUNDLE_FORMAT_VERSION = 2;
263
282
  * any number of minors and patches while this stays put. It changes only when
264
283
  * the bundle/runtime contract breaks compatibility, and a project's
265
284
  * `manifest.runtime` range is matched against *this*.
285
+ *
286
+ * ## v2 — resources are declared, not configured
287
+ *
288
+ * `RebaseBackendConfig.dataSources` and `.storageSources` are gone. A project
289
+ * declares its databases and buckets with `database()` / `bucket()` in its
290
+ * config, and the runtime reads those declarations.
291
+ *
292
+ * This had to be a major, and the reason is the managed tier: it moves projects
293
+ * onto new images WITHOUT rebuilding them. A bundle built against v1 exports
294
+ * those keys, and a v2 runtime refuses them at boot — so without this bump, one
295
+ * image rollout would crash-loop every tenant that had ever declared a second
296
+ * database or bucket, in a wave, with the cause in a container log nobody is
297
+ * watching.
298
+ *
299
+ * With the bump, a v1 bundle on a v2 runtime is refused by
300
+ * `assertBundleCompatibility` with the remedy in the message, and the platform
301
+ * keeps it on a v1 image until it is rebuilt. That is the whole purpose of this
302
+ * number.
303
+ *
304
+ * **Release order matters and is not optional.** The control plane is the side
305
+ * that rejects, so it ships FIRST: raise `SUPPORTED_RUNTIME_CONTRACT` in the
306
+ * saas repo (it rejects only `contract >` its own, so it then accepts both),
307
+ * deploy that, and only then release a runtime implementing v2. Shipping the
308
+ * runtime first turns every deploy into a rejected intake blaming the tenant's
309
+ * bundle.
266
310
  */
267
311
  export declare const RUNTIME_CONTRACT_VERSION = 1;
268
312
  /** Where the runtime finds each part of the bundle. Paths are bundle-relative. */
@@ -313,6 +357,35 @@ export interface NativeDependency {
313
357
  * `manifest.json` — generated, and the document the runtime and control plane
314
358
  * both validate against.
315
359
  */
360
+ /**
361
+ * One custom function, as recorded in a built bundle.
362
+ *
363
+ * @see RebaseBundleManifest.functions
364
+ */
365
+ export interface RebaseBundleFunction {
366
+ /**
367
+ * The filename without its extension — which is also the URL segment it
368
+ * mounts at (`/api/functions/<name>`), the API-key permission that grants
369
+ * it, and the name `REBASE_FUNCTIONS_ONLY` selects by. One identity, used
370
+ * everywhere.
371
+ */
372
+ name: string;
373
+ /** Path inside the bundle, so a host can point at the file. */
374
+ file: string;
375
+ /**
376
+ * `false` when the function's own source imports a Node built-in or a
377
+ * package that needs one.
378
+ *
379
+ * Descriptive, never a gate: nothing refuses to build or deploy on this. It
380
+ * says where this function *could* run, not where it should.
381
+ */
382
+ portable: boolean;
383
+ /**
384
+ * Why it is not portable — one short phrase per reason, deduplicated.
385
+ * Absent when it is.
386
+ */
387
+ requires?: string[];
388
+ }
316
389
  export interface RebaseBundleManifest {
317
390
  /** @see BUNDLE_FORMAT_VERSION */
318
391
  bundleFormat: number;
@@ -353,6 +426,28 @@ export interface RebaseBundleManifest {
353
426
  entry: RebaseBundleEntrypoints;
354
427
  /** Collection slugs contained in the bundle, for quick inspection. */
355
428
  collections?: string[];
429
+ /**
430
+ * Every custom function in the bundle, named and classified.
431
+ *
432
+ * Two things are recorded per function, and both are answers a host would
433
+ * otherwise have to get by importing user code:
434
+ *
435
+ * - **What it is called.** That name is the function's identity everywhere —
436
+ * the URL segment it mounts at, the `functions/<name>` API-key
437
+ * permission, the value `REBASE_FUNCTIONS_ONLY` selects by. A host that
438
+ * wants to give one slow function its own replica count currently has to
439
+ * boot the bundle to discover what is in it.
440
+ * - **Whether it needs Node.** Purely descriptive: a function that opens a
441
+ * file or runs raw SQL is a fine function, and every deployment today is
442
+ * a Node process. It is recorded because the question "which of these
443
+ * could run somewhere else" has to be answerable from the artifact, and
444
+ * because answering it per-file after the fact — across a codebase
445
+ * already written — is the expensive version of the same question.
446
+ *
447
+ * Absent on a bundle built before this field existed, which is why every
448
+ * consumer must treat it as optional rather than as an empty list.
449
+ */
450
+ functions?: RebaseBundleFunction[];
356
451
  hooks: {
357
452
  /**
358
453
  * Whether the dependency closure contains native code.
@@ -381,17 +476,27 @@ export interface RebaseBundleManifest {
381
476
  /** Whether the config package exports a `storageAuthorize` hook. */
382
477
  authorize: boolean;
383
478
  /**
384
- * Every storage source this bundle expects, resolved at build time from
385
- * `rebase.json`'s `storage` block merged with any `storageSources` the
386
- * config package exports.
479
+ * Buckets, on bundles built before {@link RebaseBundleManifest.resources}.
387
480
  *
388
- * Recorded so the runtime does not have to import user code to learn its
389
- * own topology, and so a host can tell — from the artifact alone, before
390
- * starting anything — which buckets need configuring. Absent on bundles
391
- * built before this field existed, which means one default source.
481
+ * No longer written. A host reads `resources`, which carries every kind
482
+ * in one list; this stays declared so a control plane can keep reading
483
+ * the bundles a project shipped before it was rebuilt.
392
484
  */
393
485
  sources?: StorageSourceDefinition[];
394
486
  };
487
+ /**
488
+ * Everything the project declares it needs — databases, buckets, topics,
489
+ * and whatever kind is registered next.
490
+ *
491
+ * Recorded so a host can tell, from the artifact alone and before starting
492
+ * anything, what a deploy will need provisioned. That question used to be
493
+ * answerable for buckets and for nothing else, because buckets were the
494
+ * only kind written into an artifact — which is how a project's databases
495
+ * became invisible to the platform that runs them.
496
+ *
497
+ * Absent on bundles built before this field existed.
498
+ */
499
+ resources?: ResourceGraph;
395
500
  deps: {
396
501
  /** Runtime dependencies of user code, as declared. */
397
502
  declared: Record<string, string>;
@@ -1,9 +1,9 @@
1
- import type { Entity, EntityReference, EntityRelation, EntityValues, GeoPoint, Vector } from "./entities";
2
- import type { Relation, ResolvedRelation } from "./relations";
3
- import type { ColorKey, ColorScheme } from "./chips";
4
- import type { AuthState } from "../controllers/auth_state";
5
- import type { AfterReadProps, BeforeSaveProps } from "./entity_callbacks";
6
- import type { User } from "../users";
1
+ import type { Entity, EntityReference, EntityRelation, EntityValues, GeoPoint, Vector } from "./entities.js";
2
+ import type { Relation, ResolvedRelation } from "./relations.js";
3
+ import type { ColorKey, ColorScheme } from "./chips.js";
4
+ import type { AuthState } from "../controllers/auth_state.js";
5
+ import type { AfterReadProps, BeforeSaveProps } from "./entity_callbacks.js";
6
+ import type { User } from "../users/index.js";
7
7
  /**
8
8
  * Callbacks/Hooks for individual property fields
9
9
  * @group Entity properties
@@ -324,6 +324,46 @@ export interface BooleanProperty extends BaseProperty {
324
324
  */
325
325
  validation?: PropertyValidationSchema;
326
326
  }
327
+ /**
328
+ * Which pgvector distance a query measures with, and therefore which operator
329
+ * class an index has to be built for. The names match the `distance` option on
330
+ * `vectorSearch`, because an index built for one operator is not used by a
331
+ * query that asks for another.
332
+ *
333
+ * @group Entity properties
334
+ */
335
+ export type VectorDistance = "cosine" | "l2" | "inner_product";
336
+ /**
337
+ * How the ANN index over a vector column is built.
338
+ *
339
+ * Without an index, `vectorSearch` is an exact scan: correct at any size,
340
+ * and linear in the number of rows. With one, it is approximate and fast.
341
+ * That trade is why this is configurable rather than implied.
342
+ *
343
+ * @group Entity properties
344
+ */
345
+ export interface VectorIndexConfig {
346
+ /**
347
+ * `hnsw` (the default) builds a navigable-graph index: slower to build,
348
+ * better recall, and it needs no training data, so it works on an empty
349
+ * table. `ivfflat` is cheaper to build but partitions by centroid, so an
350
+ * index built on an empty or tiny table has useless partitions — build it
351
+ * after the data is loaded, and set {@link lists}.
352
+ */
353
+ method?: "hnsw" | "ivfflat";
354
+ /**
355
+ * Which distance operators to index, defaulting to `cosine` — the default
356
+ * `vectorSearch` measures with. Name several to index several; each one is
357
+ * a separate index with its own build cost and its own storage.
358
+ */
359
+ distance?: VectorDistance | VectorDistance[];
360
+ /** HNSW: connections per node. Postgres defaults to 16. */
361
+ m?: number;
362
+ /** HNSW: candidate-list size while building. Postgres defaults to 64. */
363
+ efConstruction?: number;
364
+ /** IVFFlat: number of partitions. Postgres defaults to 100. */
365
+ lists?: number;
366
+ }
327
367
  export interface VectorProperty extends BaseProperty {
328
368
  type: "vector";
329
369
  /**
@@ -331,6 +371,18 @@ export interface VectorProperty extends BaseProperty {
331
371
  */
332
372
  defaultValue?: Vector;
333
373
  dimensions: number;
374
+ /**
375
+ * ANN index configuration for this column.
376
+ *
377
+ * Omitted, a single HNSW index for cosine distance is created — which is
378
+ * what the default `vectorSearch` uses. `false` creates none, leaving
379
+ * `vectorSearch` an exact scan.
380
+ *
381
+ * Indexes are only created when {@link dimensions} is at most 2000:
382
+ * pgvector cannot index a wider `vector` column, so a 3072-dimension
383
+ * embedding is left unindexed rather than failing the boot.
384
+ */
385
+ index?: VectorIndexConfig | false;
334
386
  validation?: PropertyValidationSchema;
335
387
  }
336
388
  /**
@@ -1,4 +1,4 @@
1
- import type { AnyCollectionConfig } from "./collections";
1
+ import type { AnyCollectionConfig } from "./collections.js";
2
2
  /**
3
3
  * @group Models
4
4
  */
@@ -0,0 +1,189 @@
1
+ /**
2
+ * The kinds Rebase ships, and the constructors a project declares them with.
3
+ *
4
+ * Each kind is registered rather than hardcoded, so a fourth one arrives
5
+ * without editing a manifest schema, a validator and a switch statement. That
6
+ * cost is precisely why databases and buckets ended up declared in different
7
+ * files with different rules — the cheapest thing to do was always to bolt the
8
+ * new kind onto whichever home was nearest.
9
+ *
10
+ * A kind owns its engine list. `custom:<id>` is always accepted, so a build
11
+ * that ships an engine this package has never heard of says so at the call site
12
+ * instead of looking like a typo of one that exists.
13
+ */
14
+ import { type DeclareOptions, type ResourceHandle, type ResourceTransport } from "./resources.js";
15
+ /** Options a database accepts beyond the common ones. */
16
+ export interface DatabaseOptions extends DeclareOptions {
17
+ /**
18
+ * The physical database or schema within the engine, when it differs from
19
+ * the engine's own default. Threaded to drivers as `databaseId`.
20
+ */
21
+ databaseId?: string;
22
+ /** Directory of migration files, relative to the config directory. */
23
+ migrations?: string;
24
+ }
25
+ /** A database handle. Collections point at it via `dataSource`. */
26
+ export type DatabaseHandle = ResourceHandle;
27
+ /**
28
+ * Declare a database.
29
+ *
30
+ * ```ts
31
+ * export const main = database(); // the default one
32
+ * export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
33
+ * ```
34
+ */
35
+ export declare function database(key?: string, options?: DatabaseOptions): DatabaseHandle;
36
+ /** Options a bucket accepts beyond the common ones. */
37
+ export interface BucketOptions extends DeclareOptions {
38
+ /**
39
+ * Whether objects are world-readable by default.
40
+ *
41
+ * Declared rather than inferred from the engine, because the two have
42
+ * disagreed before: a private object served through a cacheable public URL
43
+ * is a data leak that nothing errors on.
44
+ */
45
+ publicRead?: boolean;
46
+ /** Key prefix within the bucket, for sharing one bucket between sources. */
47
+ prefix?: string;
48
+ /**
49
+ * The credential set this bucket signs with, when several share one.
50
+ *
51
+ * `bucket("media", { engine: "s3", account: "minio" })` keeps reading its own
52
+ * `S3_BUCKET__MEDIA` — the bucket name is what distinguishes one source from
53
+ * another and never falls back — while the provider-level variables
54
+ * (`S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_ENDPOINT`, `S3_REGION`,
55
+ * `S3_FORCE_PATH_STYLE`) fall back to `__MINIO` when no per-key value is set.
56
+ *
57
+ * Fifteen buckets on one install go from ninety variables to eighteen, and
58
+ * rotating the key becomes one edit. A per-bucket value still wins, so a
59
+ * single source can move to another provider without breaking the rest off
60
+ * their shared account.
61
+ */
62
+ account?: string;
63
+ }
64
+ /** A bucket handle. Storage properties point at it via `storageSource`. */
65
+ export type BucketHandle = ResourceHandle;
66
+ /**
67
+ * Declare a bucket.
68
+ *
69
+ * ```ts
70
+ * export const media = bucket("media", { transport: "direct" });
71
+ * ```
72
+ *
73
+ * `transport: "direct"` means a provider SDK talks to the bucket and the
74
+ * backend is not in the upload path.
75
+ */
76
+ export declare function bucket(key?: string, options?: BucketOptions): BucketHandle;
77
+ /**
78
+ * How hard the runtime tries to deliver.
79
+ *
80
+ * Only `at-least-once` is implemented, and it is the honest name for what a
81
+ * retrying queue does: a handler must tolerate seeing the same event twice.
82
+ * `at-most-once` is listed so a future transport can offer it without the
83
+ * option changing shape, and is refused today rather than silently upgraded.
84
+ */
85
+ export type TopicDelivery = "at-least-once" | "at-most-once";
86
+ /** Options a topic accepts beyond the common ones. */
87
+ export interface TopicOptions extends DeclareOptions {
88
+ delivery?: TopicDelivery;
89
+ /** Attempts per subscription before a message is left failed. Default 5. */
90
+ maxAttempts?: number;
91
+ }
92
+ /**
93
+ * What a subscription does with an event.
94
+ *
95
+ * `attempt` counts from 1. Worth branching on: the first delivery and the
96
+ * fourth are the same call, but the fourth is where it is worth logging loudly.
97
+ */
98
+ export type TopicHandler<T> = (event: T, context: {
99
+ attempt: number;
100
+ topic: string;
101
+ subscription: string;
102
+ }) => Promise<void> | void;
103
+ /** A declared subscription, as recorded in the graph and wired at boot. */
104
+ export interface TopicSubscription<T = unknown> {
105
+ topic: string;
106
+ name: string;
107
+ handler: TopicHandler<T>;
108
+ maxAttempts?: number;
109
+ }
110
+ /**
111
+ * What a topic publishes through.
112
+ *
113
+ * Installed by `@rebasepro/server` at boot. Absent — in the CLI evaluating
114
+ * config to derive the graph, or in a unit test — publishing throws a message
115
+ * naming the cause, rather than resolving and dropping the event. A publish
116
+ * that silently does nothing is the failure mode a queue exists to prevent.
117
+ */
118
+ export interface TopicRuntime {
119
+ publish(topic: string, event: unknown): Promise<void>;
120
+ }
121
+ /** Install the transport topics publish through. Called by the server at boot. */
122
+ export declare function setTopicRuntime(runtime: TopicRuntime | null): void;
123
+ /** Every declared subscription, for the worker to wire and the graph to record. */
124
+ export declare function declaredSubscriptions(topic?: string): TopicSubscription[];
125
+ /** Forget declared subscriptions. For tests, alongside `resetDeclaredResources`. */
126
+ export declare function resetDeclaredSubscriptions(): void;
127
+ /** A topic handle, carrying its payload type. */
128
+ export interface TopicHandle<T> extends ResourceHandle {
129
+ /**
130
+ * Publish an event.
131
+ *
132
+ * Resolves once the event is durably recorded for every subscription, not
133
+ * once they have run. Enqueued inside a transaction that rolls back, it was
134
+ * never published.
135
+ */
136
+ publish(event: T): Promise<void>;
137
+ /**
138
+ * Declare a subscription.
139
+ *
140
+ * The name is its identity: it is what the job row records, what a retry
141
+ * counts against, and what a second subscription must not collide with.
142
+ */
143
+ subscription(name: string, handler: TopicHandler<T>, options?: {
144
+ maxAttempts?: number;
145
+ }): void;
146
+ }
147
+ /**
148
+ * Declare a topic.
149
+ *
150
+ * ```ts
151
+ * export const signups = topic<{ userId: string }>("signups");
152
+ * signups.subscription("send-welcome", async (event) => { … });
153
+ * await signups.publish({ userId });
154
+ * ```
155
+ */
156
+ export declare function topic<T = unknown>(key: string, options?: TopicOptions): TopicHandle<T>;
157
+ /**
158
+ * The declared databases, in the shape `<Rebase dataSources>` takes.
159
+ *
160
+ * The frontend needs to know which sources exist and how they are reached — a
161
+ * `direct`-transport source is one the browser talks to itself — and it imports
162
+ * the same config package the backend does. Without these it would mean writing
163
+ * the list a second time, by hand, next to the declarations, which is precisely
164
+ * the two-homes problem this model removed everywhere else.
165
+ *
166
+ * ```tsx
167
+ * import "../config/resources"; // registers them
168
+ * import { declaredDataSources, declaredStorageSources } from "@rebasepro/types";
169
+ *
170
+ * <Rebase dataSources={declaredDataSources()} storageSources={declaredStorageSources()} />
171
+ * ```
172
+ *
173
+ * The import is what registers them, so a bundler that drops an unused module
174
+ * would leave this empty — hence the side-effect import above rather than a
175
+ * bare re-export.
176
+ */
177
+ export declare function declaredDataSources(): {
178
+ key: string;
179
+ engine: string;
180
+ transport: ResourceTransport;
181
+ label?: string;
182
+ }[];
183
+ /** The declared buckets, in the shape `<Rebase storageSources>` takes. */
184
+ export declare function declaredStorageSources(): {
185
+ key: string;
186
+ engine: string;
187
+ transport: ResourceTransport;
188
+ label?: string;
189
+ }[];