@rebasepro/types 0.17.1 → 0.17.2-canary.ga94217a

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.
@@ -21,6 +21,35 @@ export interface DatabaseOptions extends DeclareOptions {
21
21
  databaseId?: string;
22
22
  /** Directory of migration files, relative to the config directory. */
23
23
  migrations?: string;
24
+ /**
25
+ * Server extensions Rebase may install on this database.
26
+ *
27
+ * A permission, not a request: naming one grants leave to run
28
+ * `CREATE EXTENSION IF NOT EXISTS <name>`, and Rebase issues it only when
29
+ * something in the schema actually needs it. Naming an extension nothing
30
+ * needs installs nothing.
31
+ *
32
+ * It has to be said out loud because installing an extension is a decision
33
+ * with a deployment behind it — the image has to ship the library, the role
34
+ * has to be allowed to install it, and a managed provider has to have it on
35
+ * an allow-list. Rebase cannot see any of that from inside the connection,
36
+ * so the answer comes from whoever chose the database.
37
+ *
38
+ * Today `vector` is the one that matters: a `{ type: "vector" }` property
39
+ * compiles to a `VECTOR(n)` column, which does not exist until pgvector is
40
+ * installed. Without this, Rebase creates the column and lets Postgres
41
+ * refuse, naming the option.
42
+ *
43
+ * ```ts
44
+ * export const main = database({ extensions: ["vector"] });
45
+ * ```
46
+ *
47
+ * `pg_trgm` and `unaccent` are not on this list and need no permission: a
48
+ * `search` block installs them unasked, because they are contrib modules
49
+ * present in every Postgres distribution. pgvector is a separate build that
50
+ * a stock `postgres:18` does not carry.
51
+ */
52
+ extensions?: string[];
24
53
  }
25
54
  /** A database handle. Collections point at it via `dataSource`. */
26
55
  export type DatabaseHandle = ResourceHandle;
@@ -28,11 +57,31 @@ export type DatabaseHandle = ResourceHandle;
28
57
  * Declare a database.
29
58
  *
30
59
  * ```ts
31
- * export const main = database(); // the default one
32
- * export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
60
+ * export const main = database(); // the default one
61
+ * export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
62
+ * export const withPgv = database({ extensions: ["vector"] }); // the default one, configured
33
63
  * ```
64
+ *
65
+ * The third form exists because the default database has no name to pass, and
66
+ * the alternative was `database("(default)", { … })` — writing out an internal
67
+ * sentinel to reach the options. A key is a string and options are an object,
68
+ * so the two can never be confused for one another.
34
69
  */
70
+ export declare function database(options?: DatabaseOptions): DatabaseHandle;
35
71
  export declare function database(key?: string, options?: DatabaseOptions): DatabaseHandle;
72
+ /**
73
+ * The extensions the project's databases gave Rebase leave to install.
74
+ *
75
+ * A flat union rather than a per-database answer, because the surfaces that ask
76
+ * — `rebase db push` and the boot schema-ensure — drive one connection and
77
+ * generate one `schema.sql` for every collection regardless of `dataSource`.
78
+ * Splitting the permission by data source would be a distinction the rest of
79
+ * that pipeline does not make, and a false precision is worse than none.
80
+ *
81
+ * Empty for a project that declared nothing, which is every project that has
82
+ * not opted in — so this reads as a refusal by default, on purpose.
83
+ */
84
+ export declare function declaredDatabaseExtensions(): readonly string[];
36
85
  /** Options a bucket accepts beyond the common ones. */
37
86
  export interface BucketOptions extends DeclareOptions {
38
87
  /**
@@ -60,6 +60,8 @@ export interface SchemaCommitPaths {
60
60
  ddlFile: string;
61
61
  policiesFile: string;
62
62
  searchFile: string;
63
+ /** Vector columns and ANN indexes — like search, applied by Rebase not Atlas. */
64
+ vectorFile: string;
63
65
  }
64
66
  export declare const DEFAULT_COMMIT_PATHS: SchemaCommitPaths;
65
67
  /** One file the commit writes, as content rather than as a path on a disk. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/types",
3
3
  "type": "module",
4
- "version": "0.17.1",
4
+ "version": "0.17.2-canary.ga94217a",
5
5
  "description": "Rebase type definitions — shared interfaces and controller types",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -34,7 +34,7 @@ registerResourceKind({
34
34
  // No per-engine narrowing: every engine binds from the same three, and the
35
35
  // driver package that differs between them is named by REBASE_DRIVER either
36
36
  // way.
37
- optionKeys: ["databaseId", "migrations"],
37
+ optionKeys: ["databaseId", "migrations", "extensions"],
38
38
  // A backend without a database is not a backend, so one exists whether or
39
39
  // not a project says so.
40
40
  implicitDefault: true
@@ -49,6 +49,35 @@ export interface DatabaseOptions extends DeclareOptions {
49
49
  databaseId?: string;
50
50
  /** Directory of migration files, relative to the config directory. */
51
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[];
52
81
  }
53
82
 
54
83
  /** A database handle. Collections point at it via `dataSource`. */
@@ -58,12 +87,49 @@ export type DatabaseHandle = ResourceHandle;
58
87
  * Declare a database.
59
88
  *
60
89
  * ```ts
61
- * export const main = database(); // the default one
62
- * export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
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
63
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.
64
99
  */
65
- export function database(key: string = DEFAULT_RESOURCE_KEY, options: DatabaseOptions = {}): DatabaseHandle {
66
- return declareResource("database", key, options);
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();
67
133
  }
68
134
 
69
135
  // ── bucket ───────────────────────────────────────────────────────────────────
@@ -75,13 +75,16 @@ export interface SchemaCommitPaths {
75
75
  ddlFile: string;
76
76
  policiesFile: string;
77
77
  searchFile: string;
78
+ /** Vector columns and ANN indexes — like search, applied by Rebase not Atlas. */
79
+ vectorFile: string;
78
80
  }
79
81
 
80
82
  export const DEFAULT_COMMIT_PATHS: SchemaCommitPaths = {
81
83
  schemaFile: "backend/src/schema.generated.ts",
82
84
  ddlFile: "drizzle/schema.sql",
83
85
  policiesFile: "drizzle/policies.sql",
84
- searchFile: "drizzle/search.sql"
86
+ searchFile: "drizzle/search.sql",
87
+ vectorFile: "drizzle/vector.sql"
85
88
  };
86
89
 
87
90
  /** One file the commit writes, as content rather than as a path on a disk. */