@rebasepro/types 0.16.0 → 0.16.1-canary.g2d1aec8

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.
@@ -1,9 +1,10 @@
1
- import type { CollectionConfig, FilterValues, WhereFilterOp } from "./collections";
2
- import type { OrderByTuple } from "./filter-operators";
3
- import type { LogicalCondition } from "../controllers/data";
4
- import type { AuthAdapter } from "./auth_adapter";
5
- import type { HistoryConfig } from "../controllers/client";
6
- import type { ChannelBusSetting } from "./channel_bus";
1
+ import type { CollectionConfig, FilterValues, WhereFilterOp } from "./collections.js";
2
+ import type { OrderByTuple } from "./filter-operators.js";
3
+ import type { LogicalCondition } from "../controllers/data.js";
4
+ import type { AuthAdapter } from "./auth_adapter.js";
5
+ import type { HistoryConfig } from "../controllers/client.js";
6
+ import type { ChannelBusSetting } from "./channel_bus.js";
7
+ import type { SchemaEditingAdmin } from "./schema_editing.js";
7
8
  /**
8
9
  * Abstract database connection interface.
9
10
  * Represents a connection to any database system.
@@ -433,7 +434,19 @@ export interface BranchAdmin {
433
434
  *
434
435
  * @group Admin
435
436
  */
436
- export type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin>;
437
+ export type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin> & Partial<SchemaEditingAdmin>;
438
+ /**
439
+ * Type guard: can this admin plan a live schema change?
440
+ *
441
+ * Planning is engine-specific — it renders DDL, a Drizzle schema and the
442
+ * declarative SQL artifacts — so the implementation lives in the driver
443
+ * package. The server detects the capability structurally, exactly as it does
444
+ * for SQL, rather than importing an engine it is supposed to know nothing
445
+ * about.
446
+ *
447
+ * @group Admin
448
+ */
449
+ export declare function isSchemaEditingAdmin(admin: DatabaseAdmin | undefined): admin is SchemaEditingAdmin;
437
450
  /**
438
451
  * Type guard: does this admin support SQL operations?
439
452
  * @group Admin
@@ -697,7 +710,7 @@ export interface BackendBootstrapper {
697
710
  /**
698
711
  * Initialize WebSocket server for realtime operations.
699
712
  */
700
- initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import("../controllers/data_driver").DataDriver, config?: unknown, authAdapter?: AuthAdapter): Promise<void> | void;
713
+ initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import("../controllers/data_driver.js").DataDriver, config?: unknown, authAdapter?: AuthAdapter): Promise<void> | void;
701
714
  }
702
715
  /**
703
716
  * Result of `BackendBootstrapper.initializeDriver()`.
@@ -705,7 +718,7 @@ export interface BackendBootstrapper {
705
718
  */
706
719
  export interface InitializedDriver {
707
720
  /** The DataDriver instance, ready for use. */
708
- driver: import("../controllers/data_driver").DataDriver;
721
+ driver: import("../controllers/data_driver.js").DataDriver;
709
722
  /** The realtime service, if the driver created one during init. */
710
723
  realtimeProvider?: RealtimeProvider;
711
724
  /** A collection registry to register schema / tables into. */
@@ -716,7 +729,7 @@ export interface InitializedDriver {
716
729
  * Set by drivers that introspect in `baas` mode; the server serves these
717
730
  * instead of collections loaded from config files.
718
731
  */
719
- collections?: import("./collections").CollectionConfig[];
732
+ collections?: import("./collections.js").CollectionConfig[];
720
733
  /** The underlying database connection (for lifecycle management). */
721
734
  connection?: DatabaseConnection;
722
735
  /**
@@ -1,4 +1,4 @@
1
- import type { CollectionConfig } from "./collections";
1
+ import type { CollectionConfig } from "./collections.js";
2
2
  /**
3
3
  * Serializing collections so they survive a network hop.
4
4
  *
@@ -1,9 +1,9 @@
1
- import type { CollectionCallbacks } from "./entity_callbacks";
2
- import type { Properties, PostgresProperties, FirebaseProperties, MongoProperties } from "./properties";
3
- import type { User } from "../users";
4
- import type { Relation } from "./relations";
5
- import type { SecurityRule } from "./security_rules";
6
- import type { SearchConfig } from "./search";
1
+ import type { CollectionCallbacks } from "./entity_callbacks.js";
2
+ import type { Properties, PostgresProperties, FirebaseProperties, MongoProperties } from "./properties.js";
3
+ import type { User } from "../users/index.js";
4
+ import type { Relation } from "./relations.js";
5
+ import type { SecurityRule } from "./security_rules.js";
6
+ import type { SearchConfig } from "./search.js";
7
7
  /**
8
8
  * Base interface containing all driver-agnostic collection properties.
9
9
  * Use {@link PostgresCollectionConfig} or {@link FirebaseCollectionConfig} for
@@ -475,7 +475,7 @@ export interface EntityChildView<M extends Record<string, unknown> = Record<stri
475
475
  collection: CollectionConfig<M>;
476
476
  source: ChildViewSource;
477
477
  }
478
- export type { WhereFilterOp, FilterValues, WireFilterValues, FilterPreset } from "./filter-operators";
478
+ export type { WhereFilterOp, FilterValues, WireFilterValues, FilterPreset } from "./filter-operators.js";
479
479
  export type InferCollectionConfigType<S extends CollectionConfig> = S extends CollectionConfig<infer M> ? M : never;
480
480
  /**
481
481
  * Configuration for authentication collections.
@@ -1,5 +1,5 @@
1
- import type { RebaseServerClient } from "../controllers/client";
2
- import type { RebaseSdkData } from "../controllers/data";
1
+ import type { RebaseServerClient } from "../controllers/client.js";
2
+ import type { RebaseSdkData } from "../controllers/data.js";
3
3
  /**
4
4
  * Cron Job type definitions for Rebase.
5
5
  *
@@ -1,4 +1,4 @@
1
- import { WhereFilterOp } from "./filter-operators";
1
+ import { WhereFilterOp } from "./filter-operators.js";
2
2
  /**
3
3
  * Describes the capabilities and features supported by a data source (driver).
4
4
  *
@@ -19,10 +19,10 @@
19
19
  *
20
20
  * @group Backend
21
21
  */
22
- import type { DataDriver } from "../controllers/data_driver";
23
- import type { CollectionConfig } from "./collections";
24
- import type { CollectionRegistryInterface, DatabaseAdmin, InitializedDriver, RealtimeProvider, BootstrappedAuth } from "./backend";
25
- import type { HistoryConfig } from "../controllers/client";
22
+ import type { DataDriver } from "../controllers/data_driver.js";
23
+ import type { CollectionConfig } from "./collections.js";
24
+ import type { CollectionRegistryInterface, DatabaseAdmin, InitializedDriver, RealtimeProvider, BootstrappedAuth } from "./backend.js";
25
+ import type { HistoryConfig } from "../controllers/client.js";
26
26
  /**
27
27
  * A `DatabaseAdapter` provides data persistence for Rebase.
28
28
  *
@@ -74,7 +74,7 @@ export interface DatabaseAdapter {
74
74
  * here — turning an adapter-authenticated server's socket into one that
75
75
  * accepted every client as already authenticated.
76
76
  */
77
- initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: DataDriver, config?: unknown, adapter?: import("./auth_adapter").AuthAdapter): Promise<void> | void;
77
+ initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: DataDriver, config?: unknown, adapter?: import("./auth_adapter.js").AuthAdapter): Promise<void> | void;
78
78
  /**
79
79
  * Bring the database's collection tables up to date, additively — the boot
80
80
  * companion to `db push`. See `BackendBootstrapper.ensureCollectionSchema`
@@ -1,4 +1,4 @@
1
- import type { SearchMatch } from "./search";
1
+ import type { SearchMatch } from "./search.js";
2
2
  /**
3
3
  * New or existing status
4
4
  * @group Models
@@ -1,7 +1,7 @@
1
- import type { CollectionConfig } from "./collections";
2
- import type { EntityStatus, EntityValues } from "./entities";
3
- import type { User } from "../users";
4
- import type { RebaseCallContext } from "../call_context";
1
+ import type { CollectionConfig } from "./collections.js";
2
+ import type { EntityStatus, EntityValues } from "./entities.js";
3
+ import type { User } from "../users/index.js";
4
+ import type { RebaseCallContext } from "../call_context.js";
5
5
  /**
6
6
  * Lifecycle callbacks for entity CRUD operations.
7
7
  *
@@ -1,29 +1,30 @@
1
- export * from "./entities";
2
- export * from "./filter-operators";
3
- export * from "./chips";
4
- export * from "./properties";
5
- export * from "./admin_block";
6
- export * from "./collections";
7
- export * from "./search";
8
- export * from "./relations";
9
- export * from "./policy";
10
- export * from "./rls-functions";
11
- export * from "./security_rules";
12
- export * from "./entity_callbacks";
13
- export * from "./websockets";
14
- export * from "./backend";
15
- export * from "./channel_bus";
16
- export * from "./data_source";
17
- export * from "./storage_source";
18
- export * from "./cron";
19
- export * from "./backup";
20
- export * from "./component_ref";
21
- export * from "./auth_adapter";
22
- export * from "./database_adapter";
23
- export * from "./api_keys";
24
- export * from "./history";
25
- export * from "./postgres_introspection";
26
- export * from "./project_manifest";
27
- export * from "./collection_contract";
28
- export * from "./schema_version";
29
- export * from "./storage_authorize";
1
+ export * from "./entities.js";
2
+ export * from "./filter-operators.js";
3
+ export * from "./chips.js";
4
+ export * from "./properties.js";
5
+ export * from "./admin_block.js";
6
+ export * from "./collections.js";
7
+ export * from "./search.js";
8
+ export * from "./relations.js";
9
+ export * from "./policy.js";
10
+ export * from "./rls-functions.js";
11
+ export * from "./security_rules.js";
12
+ export * from "./entity_callbacks.js";
13
+ export * from "./websockets.js";
14
+ export * from "./backend.js";
15
+ export * from "./schema_editing.js";
16
+ export * from "./channel_bus.js";
17
+ export * from "./data_source.js";
18
+ export * from "./storage_source.js";
19
+ export * from "./cron.js";
20
+ export * from "./backup.js";
21
+ export * from "./component_ref.js";
22
+ export * from "./auth_adapter.js";
23
+ export * from "./database_adapter.js";
24
+ export * from "./api_keys.js";
25
+ export * from "./history.js";
26
+ export * from "./postgres_introspection.js";
27
+ export * from "./project_manifest.js";
28
+ export * from "./collection_contract.js";
29
+ export * from "./schema_version.js";
30
+ export * from "./storage_authorize.js";
@@ -24,7 +24,7 @@
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
28
  /**
29
29
  * Which kind of thing an app is.
30
30
  *
@@ -313,6 +313,35 @@ export interface NativeDependency {
313
313
  * `manifest.json` — generated, and the document the runtime and control plane
314
314
  * both validate against.
315
315
  */
316
+ /**
317
+ * One custom function, as recorded in a built bundle.
318
+ *
319
+ * @see RebaseBundleManifest.functions
320
+ */
321
+ export interface RebaseBundleFunction {
322
+ /**
323
+ * The filename without its extension — which is also the URL segment it
324
+ * mounts at (`/api/functions/<name>`), the API-key permission that grants
325
+ * it, and the name `REBASE_FUNCTIONS_ONLY` selects by. One identity, used
326
+ * everywhere.
327
+ */
328
+ name: string;
329
+ /** Path inside the bundle, so a host can point at the file. */
330
+ file: string;
331
+ /**
332
+ * `false` when the function's own source imports a Node built-in or a
333
+ * package that needs one.
334
+ *
335
+ * Descriptive, never a gate: nothing refuses to build or deploy on this. It
336
+ * says where this function *could* run, not where it should.
337
+ */
338
+ portable: boolean;
339
+ /**
340
+ * Why it is not portable — one short phrase per reason, deduplicated.
341
+ * Absent when it is.
342
+ */
343
+ requires?: string[];
344
+ }
316
345
  export interface RebaseBundleManifest {
317
346
  /** @see BUNDLE_FORMAT_VERSION */
318
347
  bundleFormat: number;
@@ -353,6 +382,28 @@ export interface RebaseBundleManifest {
353
382
  entry: RebaseBundleEntrypoints;
354
383
  /** Collection slugs contained in the bundle, for quick inspection. */
355
384
  collections?: string[];
385
+ /**
386
+ * Every custom function in the bundle, named and classified.
387
+ *
388
+ * Two things are recorded per function, and both are answers a host would
389
+ * otherwise have to get by importing user code:
390
+ *
391
+ * - **What it is called.** That name is the function's identity everywhere —
392
+ * the URL segment it mounts at, the `functions/<name>` API-key
393
+ * permission, the value `REBASE_FUNCTIONS_ONLY` selects by. A host that
394
+ * wants to give one slow function its own replica count currently has to
395
+ * boot the bundle to discover what is in it.
396
+ * - **Whether it needs Node.** Purely descriptive: a function that opens a
397
+ * file or runs raw SQL is a fine function, and every deployment today is
398
+ * a Node process. It is recorded because the question "which of these
399
+ * could run somewhere else" has to be answerable from the artifact, and
400
+ * because answering it per-file after the fact — across a codebase
401
+ * already written — is the expensive version of the same question.
402
+ *
403
+ * Absent on a bundle built before this field existed, which is why every
404
+ * consumer must treat it as optional rather than as an empty list.
405
+ */
406
+ functions?: RebaseBundleFunction[];
356
407
  hooks: {
357
408
  /**
358
409
  * Whether the dependency closure contains native code.
@@ -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,127 @@
1
+ /**
2
+ * The vocabulary a live schema change is described in.
3
+ *
4
+ * Declared here, and nowhere else, because two packages that must not import
5
+ * each other both need it: `@rebasepro/server-postgres` decides what a change
6
+ * means and renders the files it needs, while `@rebasepro/server` commits those
7
+ * files and serves the routes. Neither can reach the other — the server is
8
+ * engine-agnostic by design — so the shared kernel holds the shapes and the
9
+ * driver is detected structurally through {@link SchemaEditingAdmin}.
10
+ *
11
+ * Nothing here executes anything. These are the nouns.
12
+ */
13
+ /**
14
+ * What a change will do to a live database.
15
+ *
16
+ * - `safe` — the boot-time ensure path expresses it, and the result matches the
17
+ * configuration.
18
+ * - `diverges` — the ensure path applies *something*, but the database will not
19
+ * match what the configuration declares, and nothing reports it. This is the
20
+ * category worth having: adding a required property to a populated table
21
+ * yields a nullable column, and adding a value to an existing enum yields
22
+ * nothing at all. Both read as success.
23
+ * - `needs-migration` — the ensure path cannot express it. Dropping anything,
24
+ * changing a type, moving a primary key.
25
+ */
26
+ export type SchemaChangeVerdict = "safe" | "diverges" | "needs-migration";
27
+ export type SchemaChangeKind = "add-collection" | "remove-collection" | "add-property" | "remove-property" | "change-property-type" | "rename-column" | "add-enum-value" | "remove-enum-value" | "change-required" | "change-primary-key";
28
+ export interface SchemaChange {
29
+ kind: SchemaChangeKind;
30
+ verdict: SchemaChangeVerdict;
31
+ /** Collection slug. */
32
+ collection: string;
33
+ /** Property name, where the change is to one. */
34
+ property?: string;
35
+ /** One line, specific: what changed and what it will do. */
36
+ detail: string;
37
+ /** What to do instead, when the verdict is not `safe`. */
38
+ remedy?: string;
39
+ }
40
+ export interface ClassifiedSchemaChanges {
41
+ changes: SchemaChange[];
42
+ /** The worst verdict present, or `safe` for an empty diff. */
43
+ verdict: SchemaChangeVerdict;
44
+ /** True only when every change is `safe` — the one case an editor may apply. */
45
+ applicable: boolean;
46
+ }
47
+ /**
48
+ * Where a project's generated schema artifacts live, relative to the **project**
49
+ * root — which is the repository root only when the project is the whole
50
+ * repository.
51
+ *
52
+ * Here rather than in the Postgres package because it is a contract, not an
53
+ * engine detail: `@rebasepro/server` has to derive these for a project in a
54
+ * subdirectory, and it cannot import a driver to do it.
55
+ */
56
+ export interface SchemaCommitPaths {
57
+ /** Drizzle schema, imported by the backend. */
58
+ schemaFile: string;
59
+ /** Declarative DDL, what `db push` applies and Atlas diffs against. */
60
+ ddlFile: string;
61
+ policiesFile: string;
62
+ searchFile: string;
63
+ }
64
+ export declare const DEFAULT_COMMIT_PATHS: SchemaCommitPaths;
65
+ /** One file the commit writes, as content rather than as a path on a disk. */
66
+ export interface SchemaChangeFile {
67
+ path: string;
68
+ contents: string;
69
+ }
70
+ /**
71
+ * Everything a change needs written and run.
72
+ *
73
+ * Computed without touching a disk or a network. The database is *read* — what
74
+ * a change means depends on what is already there, and a plan that guessed
75
+ * would be guessing about whether the statements it returns will be accepted.
76
+ */
77
+ export interface SchemaChangePlan {
78
+ /** Every file the commit writes — collection source and generated artifacts. */
79
+ files: SchemaChangeFile[];
80
+ /** The additive DDL this change adds, in dependency order. */
81
+ statements: string[];
82
+ classified: ClassifiedSchemaChanges;
83
+ /** A commit message describing the change rather than announcing one. */
84
+ message: string;
85
+ /**
86
+ * Constraints the configuration asks for that these statements do not
87
+ * carry, and why.
88
+ *
89
+ * Almost always empty. When it is not, it is the part the person confirming
90
+ * needs to read: the change will apply, and the database will still not
91
+ * enforce something the configuration says — a required property over a
92
+ * table that already holds rows with no value for it. Optional so a plan
93
+ * from an engine that does not distinguish these cases stays valid.
94
+ */
95
+ withheldConstraints?: WithheldSchemaConstraint[];
96
+ }
97
+ /** A constraint a plan asks for and does not apply. */
98
+ export interface WithheldSchemaConstraint {
99
+ /** `schema.table.column`. */
100
+ target: string;
101
+ kind: "not-null";
102
+ /** What is in the way, naming the obstacle rather than the rule. */
103
+ reason: string;
104
+ /** What would make it applicable. */
105
+ remedy: string;
106
+ }
107
+ /**
108
+ * An admin that can plan a schema change.
109
+ *
110
+ * Planning only. Applying is `executeSql`, which every SQL admin already has,
111
+ * and committing belongs to whatever holds the repository — keeping those three
112
+ * apart is what lets the same plan be committed locally on a developer's machine
113
+ * and through a GitHub App from a cloud tenant.
114
+ *
115
+ * @group Admin
116
+ */
117
+ export interface SchemaEditingAdmin {
118
+ /**
119
+ * Decide what the change means and render everything it needs.
120
+ *
121
+ * Rejects when the change is not applicable, carrying the classification so
122
+ * a caller can say which change was the problem.
123
+ */
124
+ planSchemaChange(before: unknown[], after: unknown[], options?: {
125
+ paths?: Partial<SchemaCommitPaths>;
126
+ }): Promise<SchemaChangePlan>;
127
+ }
@@ -1,4 +1,4 @@
1
- import type { CollectionConfig } from "./collections";
1
+ import type { CollectionConfig } from "./collections.js";
2
2
  /**
3
3
  * Compute the canonical string a schema version hashes.
4
4
  *
@@ -15,7 +15,7 @@
15
15
  * them with `getPolicyNamesForRule`/`getEffectiveSecurityRules` rather than
16
16
  * matching on `rule.name`.
17
17
  */
18
- import type { PolicyExpression } from "./policy";
18
+ import type { PolicyExpression } from "./policy.js";
19
19
  /**
20
20
  * SQL operation that a policy applies to.
21
21
  * @group Models
@@ -1 +1 @@
1
- export * from "./user";
1
+ export * from "./user.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/types",
3
3
  "type": "module",
4
- "version": "0.16.0",
4
+ "version": "0.16.1-canary.g2d1aec8",
5
5
  "description": "Rebase type definitions — shared interfaces and controller types",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -88,7 +88,7 @@
88
88
  },
89
89
  "scripts": {
90
90
  "watch": "vite build --watch",
91
- "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json && node ../../scripts/assert-build-output.mjs",
91
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json && node ../../scripts/add-dts-extensions.mjs dist && node ../../scripts/assert-build-output.mjs",
92
92
  "test:lint": "eslint \"src/**\" --quiet",
93
93
  "test": "jest --passWithNoTests",
94
94
  "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
@@ -437,6 +437,19 @@ export interface RebaseServerClient<DB = unknown> extends Omit<RebaseClient<DB>,
437
437
  * Execute raw SQL against the database. Always present server-side for SQL
438
438
  * engines. Values interpolated into the query should be passed via
439
439
  * `params`, referenced as `$1`, `$2`, … placeholders in the query text.
440
+ *
441
+ * **Runtime note.** This is the one accessor on this object that is not
442
+ * portable. It runs on the database owner connection over a TCP socket, so
443
+ * it is available wherever the framework holds that connection — every Node
444
+ * deployment, self-hosted or managed — and not on a host that has no
445
+ * sockets and no business holding owner credentials.
446
+ *
447
+ * Nothing about that is a problem for a Node deployment, and it is not a
448
+ * reason to avoid it there. It is a reason not to build a function's *only*
449
+ * data path on it if that function may later move: `c.get("driver")` and
450
+ * `rebase.dataAsAdmin` go over the same wire wherever they run. A function
451
+ * that genuinely needs raw SQL can ask `runtimeKey()` and degrade, rather
452
+ * than discovering it at the call.
440
453
  */
441
454
  sql(query: string, options?: { database?: string; role?: string; params?: unknown[] }): Promise<Record<string, unknown>[]>;
442
455
  }
@@ -4,6 +4,7 @@ import type { LogicalCondition } from "../controllers/data";
4
4
  import type { AuthAdapter } from "./auth_adapter";
5
5
  import type { HistoryConfig } from "../controllers/client";
6
6
  import type { ChannelBusSetting } from "./channel_bus";
7
+ import type { SchemaEditingAdmin } from "./schema_editing";
7
8
 
8
9
  // =============================================================================
9
10
  // DATABASE CONNECTION INTERFACES
@@ -564,7 +565,23 @@ export interface BranchAdmin {
564
565
  *
565
566
  * @group Admin
566
567
  */
567
- export type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin>;
568
+ export type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin>
569
+ & Partial<BranchAdmin> & Partial<SchemaEditingAdmin>;
570
+
571
+ /**
572
+ * Type guard: can this admin plan a live schema change?
573
+ *
574
+ * Planning is engine-specific — it renders DDL, a Drizzle schema and the
575
+ * declarative SQL artifacts — so the implementation lives in the driver
576
+ * package. The server detects the capability structurally, exactly as it does
577
+ * for SQL, rather than importing an engine it is supposed to know nothing
578
+ * about.
579
+ *
580
+ * @group Admin
581
+ */
582
+ export function isSchemaEditingAdmin(admin: DatabaseAdmin | undefined): admin is SchemaEditingAdmin {
583
+ return !!admin && typeof (admin as SchemaEditingAdmin).planSchemaChange === "function";
584
+ }
568
585
 
569
586
  /**
570
587
  * Type guard: does this admin support SQL operations?
@@ -14,6 +14,7 @@ export * from "./security_rules";
14
14
  export * from "./entity_callbacks";
15
15
  export * from "./websockets";
16
16
  export * from "./backend";
17
+ export * from "./schema_editing";
17
18
  export * from "./channel_bus";
18
19
  export * from "./data_source";
19
20
  export * from "./storage_source";