@rebasepro/types 0.17.3 → 0.18.1
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/README.md +4 -0
- package/dist/call_context.d.ts +20 -0
- package/dist/controllers/client.d.ts +36 -4
- package/dist/controllers/data.d.ts +120 -10
- package/dist/errors.d.ts +83 -4
- package/dist/index.es.js +522 -160
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +2 -2
- package/dist/types/auth_adapter.d.ts +41 -6
- package/dist/types/backend.d.ts +48 -0
- package/dist/types/collections.d.ts +25 -1
- package/dist/types/cron.d.ts +34 -0
- package/dist/types/database_adapter.d.ts +39 -0
- package/dist/types/entity_callbacks.d.ts +14 -1
- package/dist/types/filter-operators.d.ts +24 -1
- package/dist/types/policy.d.ts +29 -1
- package/dist/types/properties.d.ts +216 -3
- package/dist/types/relations.d.ts +65 -7
- package/dist/types/resource_kinds.d.ts +173 -17
- package/dist/types/resources.d.ts +108 -7
- package/dist/types/rls-functions.d.ts +11 -0
- package/dist/types/storage_source.d.ts +12 -23
- package/package.json +24 -23
- package/src/call_context.ts +0 -120
- package/src/controllers/auth_state.ts +0 -24
- package/src/controllers/client.ts +0 -494
- package/src/controllers/collection_registry.ts +0 -62
- package/src/controllers/data.ts +0 -1012
- package/src/controllers/data_driver.ts +0 -576
- package/src/controllers/effective_role.ts +0 -4
- package/src/controllers/email.ts +0 -91
- package/src/controllers/index.ts +0 -11
- package/src/controllers/storage.ts +0 -252
- package/src/errors.ts +0 -119
- package/src/index.ts +0 -5
- package/src/types/admin_block.ts +0 -209
- package/src/types/api_keys.ts +0 -108
- package/src/types/auth_adapter.ts +0 -580
- package/src/types/backend.ts +0 -987
- package/src/types/backup.ts +0 -26
- package/src/types/channel_bus.ts +0 -202
- package/src/types/chips.ts +0 -34
- package/src/types/collection_contract.ts +0 -278
- package/src/types/collections.ts +0 -763
- package/src/types/component_ref.ts +0 -92
- package/src/types/cron.ts +0 -213
- package/src/types/data_source.ts +0 -357
- package/src/types/database_adapter.ts +0 -267
- package/src/types/entities.ts +0 -226
- package/src/types/entity_callbacks.ts +0 -229
- package/src/types/filter-operators.ts +0 -444
- package/src/types/history.ts +0 -66
- package/src/types/index.ts +0 -36
- package/src/types/indexes.ts +0 -180
- package/src/types/policy.ts +0 -328
- package/src/types/postgres_introspection.ts +0 -101
- package/src/types/project_manifest.ts +0 -598
- package/src/types/properties.ts +0 -1368
- package/src/types/relations.ts +0 -417
- package/src/types/resource_kinds.ts +0 -390
- package/src/types/resources.ts +0 -368
- package/src/types/rls-functions.ts +0 -98
- package/src/types/schema_editing.ts +0 -157
- package/src/types/schema_version.ts +0 -112
- package/src/types/search.ts +0 -247
- package/src/types/security_rules.ts +0 -344
- package/src/types/storage_authorize.ts +0 -77
- package/src/types/storage_source.ts +0 -248
- package/src/types/websockets.ts +0 -117
- package/src/users/index.ts +0 -2
- package/src/users/user.ts +0 -69
|
@@ -1,390 +0,0 @@
|
|
|
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 {
|
|
15
|
-
DEFAULT_RESOURCE_KEY,
|
|
16
|
-
declareResource,
|
|
17
|
-
declaredResources,
|
|
18
|
-
registerResourceKind,
|
|
19
|
-
type DeclareOptions,
|
|
20
|
-
type ResourceHandle,
|
|
21
|
-
type ResourceTransport
|
|
22
|
-
} from "./resources";
|
|
23
|
-
|
|
24
|
-
// ── database ─────────────────────────────────────────────────────────────────
|
|
25
|
-
|
|
26
|
-
registerResourceKind({
|
|
27
|
-
kind: "database",
|
|
28
|
-
engines: ["postgres", "mongodb", "firestore", "sqlite"],
|
|
29
|
-
defaultEngine: "postgres",
|
|
30
|
-
// REBASE_DRIVER overrides the engine's default driver package; the pool
|
|
31
|
-
// ceiling is per-source because one source can be a single-session PGlite
|
|
32
|
-
// and another a real server.
|
|
33
|
-
envBases: ["DATABASE_URL", "REBASE_DRIVER", "REBASE_DB_POOL_MAX"],
|
|
34
|
-
// No per-engine narrowing: every engine binds from the same three, and the
|
|
35
|
-
// driver package that differs between them is named by REBASE_DRIVER either
|
|
36
|
-
// way.
|
|
37
|
-
optionKeys: ["databaseId", "migrations", "extensions"],
|
|
38
|
-
// A backend without a database is not a backend, so one exists whether or
|
|
39
|
-
// not a project says so.
|
|
40
|
-
implicitDefault: true
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
/** Options a database accepts beyond the common ones. */
|
|
44
|
-
export interface DatabaseOptions extends DeclareOptions {
|
|
45
|
-
/**
|
|
46
|
-
* The physical database or schema within the engine, when it differs from
|
|
47
|
-
* the engine's own default. Threaded to drivers as `databaseId`.
|
|
48
|
-
*/
|
|
49
|
-
databaseId?: string;
|
|
50
|
-
/** Directory of migration files, relative to the config directory. */
|
|
51
|
-
migrations?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Server extensions Rebase may install on this database.
|
|
54
|
-
*
|
|
55
|
-
* A permission, not a request: naming one grants leave to run
|
|
56
|
-
* `CREATE EXTENSION IF NOT EXISTS <name>`, and Rebase issues it only when
|
|
57
|
-
* something in the schema actually needs it. Naming an extension nothing
|
|
58
|
-
* needs installs nothing.
|
|
59
|
-
*
|
|
60
|
-
* It has to be said out loud because installing an extension is a decision
|
|
61
|
-
* with a deployment behind it — the image has to ship the library, the role
|
|
62
|
-
* has to be allowed to install it, and a managed provider has to have it on
|
|
63
|
-
* an allow-list. Rebase cannot see any of that from inside the connection,
|
|
64
|
-
* so the answer comes from whoever chose the database.
|
|
65
|
-
*
|
|
66
|
-
* Today `vector` is the one that matters: a `{ type: "vector" }` property
|
|
67
|
-
* compiles to a `VECTOR(n)` column, which does not exist until pgvector is
|
|
68
|
-
* installed. Without this, Rebase creates the column and lets Postgres
|
|
69
|
-
* refuse, naming the option.
|
|
70
|
-
*
|
|
71
|
-
* ```ts
|
|
72
|
-
* export const main = database({ extensions: ["vector"] });
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* `pg_trgm` and `unaccent` are not on this list and need no permission: a
|
|
76
|
-
* `search` block installs them unasked, because they are contrib modules
|
|
77
|
-
* present in every Postgres distribution. pgvector is a separate build that
|
|
78
|
-
* a stock `postgres:18` does not carry.
|
|
79
|
-
*/
|
|
80
|
-
extensions?: string[];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** A database handle. Collections point at it via `dataSource`. */
|
|
84
|
-
export type DatabaseHandle = ResourceHandle;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Declare a database.
|
|
88
|
-
*
|
|
89
|
-
* ```ts
|
|
90
|
-
* export const main = database(); // the default one
|
|
91
|
-
* export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
|
|
92
|
-
* export const withPgv = database({ extensions: ["vector"] }); // the default one, configured
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
|
-
* The third form exists because the default database has no name to pass, and
|
|
96
|
-
* the alternative was `database("(default)", { … })` — writing out an internal
|
|
97
|
-
* sentinel to reach the options. A key is a string and options are an object,
|
|
98
|
-
* so the two can never be confused for one another.
|
|
99
|
-
*/
|
|
100
|
-
export function database(options?: DatabaseOptions): DatabaseHandle;
|
|
101
|
-
export function database(key?: string, options?: DatabaseOptions): DatabaseHandle;
|
|
102
|
-
export function database(
|
|
103
|
-
keyOrOptions: string | DatabaseOptions = DEFAULT_RESOURCE_KEY,
|
|
104
|
-
options: DatabaseOptions = {}
|
|
105
|
-
): DatabaseHandle {
|
|
106
|
-
return typeof keyOrOptions === "string"
|
|
107
|
-
? declareResource("database", keyOrOptions, options)
|
|
108
|
-
: declareResource("database", DEFAULT_RESOURCE_KEY, keyOrOptions);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* The extensions the project's databases gave Rebase leave to install.
|
|
113
|
-
*
|
|
114
|
-
* A flat union rather than a per-database answer, because the surfaces that ask
|
|
115
|
-
* — `rebase db push` and the boot schema-ensure — drive one connection and
|
|
116
|
-
* generate one `schema.sql` for every collection regardless of `dataSource`.
|
|
117
|
-
* Splitting the permission by data source would be a distinction the rest of
|
|
118
|
-
* that pipeline does not make, and a false precision is worse than none.
|
|
119
|
-
*
|
|
120
|
-
* Empty for a project that declared nothing, which is every project that has
|
|
121
|
-
* not opted in — so this reads as a refusal by default, on purpose.
|
|
122
|
-
*/
|
|
123
|
-
export function declaredDatabaseExtensions(): readonly string[] {
|
|
124
|
-
const names = new Set<string>();
|
|
125
|
-
for (const declaration of declaredResources("database")) {
|
|
126
|
-
const declared = declaration.options.extensions;
|
|
127
|
-
if (!Array.isArray(declared)) continue;
|
|
128
|
-
for (const name of declared) {
|
|
129
|
-
if (typeof name === "string" && name.trim()) names.add(name.trim());
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return [...names].sort();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ── bucket ───────────────────────────────────────────────────────────────────
|
|
136
|
-
|
|
137
|
-
registerResourceKind({
|
|
138
|
-
kind: "bucket",
|
|
139
|
-
engines: ["local", "s3", "gcs", "azure", "firebase"],
|
|
140
|
-
defaultEngine: "local",
|
|
141
|
-
envBases: ["S3_BUCKET", "GCS_BUCKET", "STORAGE_BUCKET", "STORAGE_PUBLIC_URL"],
|
|
142
|
-
envBasesByEngine: {
|
|
143
|
-
local: ["STORAGE_BUCKET"],
|
|
144
|
-
s3: ["S3_BUCKET", "STORAGE_ENDPOINT", "STORAGE_REGION", "STORAGE_PUBLIC_URL"],
|
|
145
|
-
gcs: ["GCS_BUCKET", "STORAGE_PUBLIC_URL"],
|
|
146
|
-
azure: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"],
|
|
147
|
-
firebase: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"]
|
|
148
|
-
},
|
|
149
|
-
optionKeys: ["publicRead", "prefix", "account"],
|
|
150
|
-
// Storage is genuinely optional: plenty of projects store nothing.
|
|
151
|
-
implicitDefault: false
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
/** Options a bucket accepts beyond the common ones. */
|
|
155
|
-
export interface BucketOptions extends DeclareOptions {
|
|
156
|
-
/**
|
|
157
|
-
* Whether objects are world-readable by default.
|
|
158
|
-
*
|
|
159
|
-
* Declared rather than inferred from the engine, because the two have
|
|
160
|
-
* disagreed before: a private object served through a cacheable public URL
|
|
161
|
-
* is a data leak that nothing errors on.
|
|
162
|
-
*/
|
|
163
|
-
publicRead?: boolean;
|
|
164
|
-
/** Key prefix within the bucket, for sharing one bucket between sources. */
|
|
165
|
-
prefix?: string;
|
|
166
|
-
/**
|
|
167
|
-
* The credential set this bucket signs with, when several share one.
|
|
168
|
-
*
|
|
169
|
-
* `bucket("media", { engine: "s3", account: "minio" })` keeps reading its own
|
|
170
|
-
* `S3_BUCKET__MEDIA` — the bucket name is what distinguishes one source from
|
|
171
|
-
* another and never falls back — while the provider-level variables
|
|
172
|
-
* (`S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_ENDPOINT`, `S3_REGION`,
|
|
173
|
-
* `S3_FORCE_PATH_STYLE`) fall back to `__MINIO` when no per-key value is set.
|
|
174
|
-
*
|
|
175
|
-
* Fifteen buckets on one install go from ninety variables to eighteen, and
|
|
176
|
-
* rotating the key becomes one edit. A per-bucket value still wins, so a
|
|
177
|
-
* single source can move to another provider without breaking the rest off
|
|
178
|
-
* their shared account.
|
|
179
|
-
*/
|
|
180
|
-
account?: string;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** A bucket handle. Storage properties point at it via `storageSource`. */
|
|
184
|
-
export type BucketHandle = ResourceHandle;
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Declare a bucket.
|
|
188
|
-
*
|
|
189
|
-
* ```ts
|
|
190
|
-
* export const media = bucket("media", { transport: "direct" });
|
|
191
|
-
* ```
|
|
192
|
-
*
|
|
193
|
-
* `transport: "direct"` means a provider SDK talks to the bucket and the
|
|
194
|
-
* backend is not in the upload path.
|
|
195
|
-
*/
|
|
196
|
-
export function bucket(key: string = DEFAULT_RESOURCE_KEY, options: BucketOptions = {}): BucketHandle {
|
|
197
|
-
return declareResource("bucket", key, options);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// ── topic ────────────────────────────────────────────────────────────────────
|
|
201
|
-
|
|
202
|
-
registerResourceKind({
|
|
203
|
-
kind: "topic",
|
|
204
|
-
// `jobs` is the durable local implementation: a topic fans out to one job
|
|
205
|
-
// row per subscription, so each subscriber retries on its own schedule and
|
|
206
|
-
// a failure is a row somebody can look at rather than a lost message.
|
|
207
|
-
engines: ["jobs"],
|
|
208
|
-
defaultEngine: "jobs",
|
|
209
|
-
envBases: ["REBASE_TOPIC_URL"],
|
|
210
|
-
optionKeys: ["delivery", "maxAttempts"],
|
|
211
|
-
implicitDefault: false
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* How hard the runtime tries to deliver.
|
|
216
|
-
*
|
|
217
|
-
* Only `at-least-once` is implemented, and it is the honest name for what a
|
|
218
|
-
* retrying queue does: a handler must tolerate seeing the same event twice.
|
|
219
|
-
* `at-most-once` is listed so a future transport can offer it without the
|
|
220
|
-
* option changing shape, and is refused today rather than silently upgraded.
|
|
221
|
-
*/
|
|
222
|
-
export type TopicDelivery = "at-least-once" | "at-most-once";
|
|
223
|
-
|
|
224
|
-
/** Options a topic accepts beyond the common ones. */
|
|
225
|
-
export interface TopicOptions extends DeclareOptions {
|
|
226
|
-
delivery?: TopicDelivery;
|
|
227
|
-
/** Attempts per subscription before a message is left failed. Default 5. */
|
|
228
|
-
maxAttempts?: number;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* What a subscription does with an event.
|
|
233
|
-
*
|
|
234
|
-
* `attempt` counts from 1. Worth branching on: the first delivery and the
|
|
235
|
-
* fourth are the same call, but the fourth is where it is worth logging loudly.
|
|
236
|
-
*/
|
|
237
|
-
export type TopicHandler<T> = (event: T, context: { attempt: number; topic: string; subscription: string }) => Promise<void> | void;
|
|
238
|
-
|
|
239
|
-
/** A declared subscription, as recorded in the graph and wired at boot. */
|
|
240
|
-
export interface TopicSubscription<T = unknown> {
|
|
241
|
-
topic: string;
|
|
242
|
-
name: string;
|
|
243
|
-
handler: TopicHandler<T>;
|
|
244
|
-
maxAttempts?: number;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* What a topic publishes through.
|
|
249
|
-
*
|
|
250
|
-
* Installed by `@rebasepro/server` at boot. Absent — in the CLI evaluating
|
|
251
|
-
* config to derive the graph, or in a unit test — publishing throws a message
|
|
252
|
-
* naming the cause, rather than resolving and dropping the event. A publish
|
|
253
|
-
* that silently does nothing is the failure mode a queue exists to prevent.
|
|
254
|
-
*/
|
|
255
|
-
export interface TopicRuntime {
|
|
256
|
-
publish(topic: string, event: unknown): Promise<void>;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const runtimeHolder: { current: TopicRuntime | null } = { current: null };
|
|
260
|
-
|
|
261
|
-
/** Install the transport topics publish through. Called by the server at boot. */
|
|
262
|
-
export function setTopicRuntime(runtime: TopicRuntime | null): void {
|
|
263
|
-
runtimeHolder.current = runtime;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const subscriptions: TopicSubscription[] = [];
|
|
267
|
-
|
|
268
|
-
/** Every declared subscription, for the worker to wire and the graph to record. */
|
|
269
|
-
export function declaredSubscriptions(topic?: string): TopicSubscription[] {
|
|
270
|
-
return topic ? subscriptions.filter(s => s.topic === topic) : subscriptions.slice();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** Forget declared subscriptions. For tests, alongside `resetDeclaredResources`. */
|
|
274
|
-
export function resetDeclaredSubscriptions(): void {
|
|
275
|
-
subscriptions.length = 0;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/** A topic handle, carrying its payload type. */
|
|
279
|
-
export interface TopicHandle<T> extends ResourceHandle {
|
|
280
|
-
/**
|
|
281
|
-
* Publish an event.
|
|
282
|
-
*
|
|
283
|
-
* Resolves once the event is durably recorded for every subscription, not
|
|
284
|
-
* once they have run. Enqueued inside a transaction that rolls back, it was
|
|
285
|
-
* never published.
|
|
286
|
-
*/
|
|
287
|
-
publish(event: T): Promise<void>;
|
|
288
|
-
/**
|
|
289
|
-
* Declare a subscription.
|
|
290
|
-
*
|
|
291
|
-
* The name is its identity: it is what the job row records, what a retry
|
|
292
|
-
* counts against, and what a second subscription must not collide with.
|
|
293
|
-
*/
|
|
294
|
-
subscription(name: string, handler: TopicHandler<T>, options?: { maxAttempts?: number }): void;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Declare a topic.
|
|
299
|
-
*
|
|
300
|
-
* ```ts
|
|
301
|
-
* export const signups = topic<{ userId: string }>("signups");
|
|
302
|
-
* signups.subscription("send-welcome", async (event) => { … });
|
|
303
|
-
* await signups.publish({ userId });
|
|
304
|
-
* ```
|
|
305
|
-
*/
|
|
306
|
-
export function topic<T = unknown>(key: string, options: TopicOptions = {}): TopicHandle<T> {
|
|
307
|
-
if (options.delivery === "at-most-once") {
|
|
308
|
-
throw new Error(
|
|
309
|
-
`Topic "${key}" asks for at-most-once delivery, which no shipped transport implements. ` +
|
|
310
|
-
"The durable queue behind topics retries, so it is at-least-once and a handler must " +
|
|
311
|
-
"tolerate seeing an event twice. Refused rather than quietly given the other guarantee."
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
const handle = declareResource("topic", key, options);
|
|
315
|
-
|
|
316
|
-
return {
|
|
317
|
-
...handle,
|
|
318
|
-
toString() { return key; },
|
|
319
|
-
async publish(event: T): Promise<void> {
|
|
320
|
-
const runtime = runtimeHolder.current;
|
|
321
|
-
if (!runtime) {
|
|
322
|
-
throw new Error(
|
|
323
|
-
`Cannot publish to topic "${key}": no topic runtime is installed. ` +
|
|
324
|
-
"Publishing works inside a running Rebase backend; this looks like config " +
|
|
325
|
-
"being evaluated outside one (a build, a script, or a test without a harness)."
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
await runtime.publish(key, event);
|
|
329
|
-
},
|
|
330
|
-
subscription(name: string, handler: TopicHandler<T>, subOptions: { maxAttempts?: number } = {}): void {
|
|
331
|
-
if (!name || name.trim() === "") {
|
|
332
|
-
throw new Error(`A subscription on topic "${key}" needs a non-empty name.`);
|
|
333
|
-
}
|
|
334
|
-
if (subscriptions.some(s => s.topic === key && s.name === name)) {
|
|
335
|
-
throw new Error(
|
|
336
|
-
`Topic "${key}" already has a subscription named "${name}". ` +
|
|
337
|
-
"The name is what a job row records and what a retry counts against, so two " +
|
|
338
|
-
"cannot share one."
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
subscriptions.push({
|
|
342
|
-
topic: key,
|
|
343
|
-
name,
|
|
344
|
-
handler: handler as TopicHandler<unknown>,
|
|
345
|
-
...(subOptions.maxAttempts !== undefined ? { maxAttempts: subOptions.maxAttempts } : {})
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
} as TopicHandle<T>;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// ── Handing declarations to the frontend ─────────────────────────────────────
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* The declared databases, in the shape `<Rebase dataSources>` takes.
|
|
355
|
-
*
|
|
356
|
-
* The frontend needs to know which sources exist and how they are reached — a
|
|
357
|
-
* `direct`-transport source is one the browser talks to itself — and it imports
|
|
358
|
-
* the same config package the backend does. Without these it would mean writing
|
|
359
|
-
* the list a second time, by hand, next to the declarations, which is precisely
|
|
360
|
-
* the two-homes problem this model removed everywhere else.
|
|
361
|
-
*
|
|
362
|
-
* ```tsx
|
|
363
|
-
* import "../config/resources"; // registers them
|
|
364
|
-
* import { declaredDataSources, declaredStorageSources } from "@rebasepro/types";
|
|
365
|
-
*
|
|
366
|
-
* <Rebase dataSources={declaredDataSources()} storageSources={declaredStorageSources()} />
|
|
367
|
-
* ```
|
|
368
|
-
*
|
|
369
|
-
* The import is what registers them, so a bundler that drops an unused module
|
|
370
|
-
* would leave this empty — hence the side-effect import above rather than a
|
|
371
|
-
* bare re-export.
|
|
372
|
-
*/
|
|
373
|
-
export function declaredDataSources(): { key: string; engine: string; transport: ResourceTransport; label?: string }[] {
|
|
374
|
-
return declaredResources("database").map(r => ({
|
|
375
|
-
key: r.key,
|
|
376
|
-
engine: r.engine,
|
|
377
|
-
transport: r.transport,
|
|
378
|
-
...(r.label !== undefined ? { label: r.label } : {})
|
|
379
|
-
}));
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/** The declared buckets, in the shape `<Rebase storageSources>` takes. */
|
|
383
|
-
export function declaredStorageSources(): { key: string; engine: string; transport: ResourceTransport; label?: string }[] {
|
|
384
|
-
return declaredResources("bucket").map(r => ({
|
|
385
|
-
key: r.key,
|
|
386
|
-
engine: r.engine,
|
|
387
|
-
transport: r.transport,
|
|
388
|
-
...(r.label !== undefined ? { label: r.label } : {})
|
|
389
|
-
}));
|
|
390
|
-
}
|