@rebasepro/server-postgres 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.
- package/dist/PostgresAdapter.d.ts +1 -1
- package/dist/PostgresBackendDriver.d.ts +75 -12
- package/dist/PostgresBootstrapper.d.ts +6 -6
- package/dist/auth/services.d.ts +1 -1
- package/dist/backup/backup-cron.d.ts +1 -1
- package/dist/backup/backup-service.d.ts +2 -2
- package/dist/backup/index.d.ts +4 -4
- package/dist/{backup-service-BZoixhVl.js → backup-service-BtgHxfFm.js} +5 -4
- package/dist/{backup-service-BZoixhVl.js.map → backup-service-BtgHxfFm.js.map} +1 -1
- package/dist/cli-helpers.d.ts +41 -0
- package/dist/{auth-users-columns-CgyPWQ18.js → collection-index-DxJBvVTH.js} +486 -503
- package/dist/collection-index-DxJBvVTH.js.map +1 -0
- package/dist/collections/PostgresCollectionRegistry.d.ts +1 -1
- package/dist/collections/buildRegistry.d.ts +1 -1
- package/dist/collections/validate-relations.d.ts +1 -1
- package/dist/{connection-BuZ97wsr.js → connection-GOKU3Hu5.js} +34 -7
- package/dist/connection-GOKU3Hu5.js.map +1 -0
- package/dist/connection.d.ts +16 -0
- package/dist/data-transformer.d.ts +1 -1
- package/dist/{ensure-collection-policies-BVFb2olB.js → ensure-collection-policies-DFpOl8SM.js} +4 -4
- package/dist/{ensure-collection-policies-BVFb2olB.js.map → ensure-collection-policies-DFpOl8SM.js.map} +1 -1
- package/dist/ensure-collection-tables-DMjOkeRy.js +1952 -0
- package/dist/ensure-collection-tables-DMjOkeRy.js.map +1 -0
- package/dist/index.d.ts +16 -16
- package/dist/index.es.js +19 -7128
- package/dist/index.es.js.map +1 -1
- package/dist/{rls-bootstrap-sql-B5Sajku6.js → rls-bootstrap-sql-DNzaWd4C.js} +3 -3
- package/dist/{rls-bootstrap-sql-B5Sajku6.js.map → rls-bootstrap-sql-DNzaWd4C.js.map} +1 -1
- package/dist/{rls-enforcement-Ch0T6OwW.js → rls-enforcement-CInuYj1-.js} +14 -4
- package/dist/rls-enforcement-CInuYj1-.js.map +1 -0
- package/dist/schema/classify-change.d.ts +82 -0
- package/dist/schema/collection-index.d.ts +182 -0
- package/dist/schema/dynamic-tables.d.ts +1 -1
- package/dist/schema/ensure-collection-policies.d.ts +1 -1
- package/dist/schema/ensure-collection-tables.d.ts +93 -2
- package/dist/schema/generate-schema-commit.d.ts +136 -0
- package/dist/schema/generated-schema-staleness.d.ts +19 -0
- package/dist/schema/introspect-db-constraints.d.ts +1 -1
- package/dist/schema/introspect-db-logic.d.ts +3 -3
- package/dist/schema/introspect-db-project.d.ts +1 -1
- package/dist/schema/introspect-db-queries.d.ts +1 -1
- package/dist/schema/introspect-db-structure.d.ts +2 -2
- package/dist/schema/introspect-runtime.d.ts +1 -1
- package/dist/schema/vector-index.d.ts +88 -0
- package/dist/services/BranchService.d.ts +2 -2
- package/dist/services/FetchService.d.ts +4 -4
- package/dist/services/PersistService.d.ts +5 -5
- package/dist/services/RelationService.d.ts +3 -3
- package/dist/services/RelationWriteService.d.ts +3 -3
- package/dist/services/cdc/junction-tables.d.ts +1 -1
- package/dist/services/cdc/trigger-cdc.d.ts +1 -1
- package/dist/services/channel-bus/PostgresChannelBus.d.ts +1 -1
- package/dist/services/channel-bus/index.d.ts +2 -2
- package/dist/services/collection-helpers.d.ts +1 -1
- package/dist/services/dataService.d.ts +10 -10
- package/dist/services/index.d.ts +4 -4
- package/dist/services/junction-writes.d.ts +2 -2
- package/dist/services/nested-path.d.ts +1 -1
- package/dist/services/realtimeService.d.ts +3 -3
- package/dist/services/row-pipeline.d.ts +1 -1
- package/dist/services/write-denial.d.ts +1 -1
- package/dist/{src-BBFsDaeA.js → src-DiDgtX8P.js} +97 -1
- package/dist/src-DiDgtX8P.js.map +1 -0
- package/dist/utils/drizzle-conditions.d.ts +2 -2
- package/dist/websocket-CUnpSe8v.js +8188 -0
- package/dist/websocket-CUnpSe8v.js.map +1 -0
- package/dist/websocket.d.ts +29 -2
- package/package.json +7 -7
- package/src/PostgresBackendDriver.ts +190 -59
- package/src/backup/backup-service.ts +1 -1
- package/src/cli-helpers.ts +117 -2
- package/src/cli.ts +22 -0
- package/src/connection.ts +37 -3
- package/src/databasePoolManager.ts +5 -2
- package/src/schema/classify-change.ts +436 -0
- package/src/schema/collection-index.ts +427 -0
- package/src/schema/ensure-collection-tables.test.ts +168 -1
- package/src/schema/ensure-collection-tables.ts +365 -14
- package/src/schema/generate-drizzle-schema-logic.ts +23 -11
- package/src/schema/generate-drizzle-schema.ts +13 -2
- package/src/schema/generate-postgres-ddl-logic.ts +33 -6
- package/src/schema/generate-postgres-ddl.ts +13 -2
- package/src/schema/generate-schema-commit.ts +242 -0
- package/src/schema/generated-schema-staleness.ts +114 -1
- package/src/schema/vector-index.ts +278 -0
- package/src/services/collection-helpers.ts +3 -2
- package/src/websocket.ts +47 -3
- package/dist/auth-users-columns-CgyPWQ18.js.map +0 -1
- package/dist/connection-BuZ97wsr.js.map +0 -1
- package/dist/data_driver-ULAyJEi9.js +0 -193
- package/dist/data_driver-ULAyJEi9.js.map +0 -1
- package/dist/ensure-collection-tables-BY1pHRD_.js +0 -840
- package/dist/ensure-collection-tables-BY1pHRD_.js.map +0 -1
- package/dist/rls-enforcement-Ch0T6OwW.js.map +0 -1
- package/dist/src-BBFsDaeA.js.map +0 -1
- package/dist/utils/table-classification.d.ts +0 -8
- package/dist/websocket-BVgDVO-V.js +0 -614
- package/dist/websocket-BVgDVO-V.js.map +0 -1
- package/src/utils/table-classification.ts +0 -16
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a schema change has to write, as file contents.
|
|
3
|
+
*
|
|
4
|
+
* A live schema editor that only edits the collection source produces a repo
|
|
5
|
+
* that does not build: `backend/src/schema.generated.ts` is a committed
|
|
6
|
+
* artifact, and a stale one has broken every deploy at least once. So the unit
|
|
7
|
+
* of a schema change is not a file, it is a **commit** — and this module
|
|
8
|
+
* produces one, without touching a disk, a database or a network.
|
|
9
|
+
*
|
|
10
|
+
* Pure on purpose. The risky half of "commit, then apply" is generating a
|
|
11
|
+
* correct commit; keeping it a function from collections to file contents is
|
|
12
|
+
* what lets that half be tested by building a database from the result and
|
|
13
|
+
* comparing it to the one the change describes.
|
|
14
|
+
*
|
|
15
|
+
* ## Where the migration comes from, and why not from Atlas
|
|
16
|
+
*
|
|
17
|
+
* `rebase db generate` mints migrations by running Atlas over the generated
|
|
18
|
+
* `schema.sql`. Atlas is an external binary, it wants a dev database, and it
|
|
19
|
+
* maintains an `atlas.sum` integrity file whose hash this module would have to
|
|
20
|
+
* reproduce byte-for-byte to stay valid.
|
|
21
|
+
*
|
|
22
|
+
* None of that is necessary here, because of what the editor is allowed to do.
|
|
23
|
+
* `classify-change.ts` refuses anything the boot-time ensure path cannot
|
|
24
|
+
* express, which leaves only additive statements — and those are computable as
|
|
25
|
+
* a plain difference between two ensure plans:
|
|
26
|
+
*
|
|
27
|
+
* plan(after, nothing) − plan(before, nothing)
|
|
28
|
+
*
|
|
29
|
+
* Both plans are pure functions of the collections, every statement is
|
|
30
|
+
* idempotent, and the difference is exactly what the change adds. No diff
|
|
31
|
+
* engine, no database, no binary.
|
|
32
|
+
*
|
|
33
|
+
* The statements are *returned* rather than written into a migration file. A
|
|
34
|
+
* project provisioned by boot-ensure needs no migration at all — its
|
|
35
|
+
* collections are the schema — while a project provisioned by migrations needs
|
|
36
|
+
* the file to carry an Atlas hash, which only Atlas can mint. Writing a
|
|
37
|
+
* migration this module cannot make valid would be worse than handing the
|
|
38
|
+
* statements to a caller who knows which kind of project it is.
|
|
39
|
+
*/
|
|
40
|
+
import { type CollectionConfig, type SchemaCommitPaths } from "@rebasepro/types";
|
|
41
|
+
import { type EnsureOptions, type ExistingSchema, type WithheldConstraint } from "./ensure-collection-tables.js";
|
|
42
|
+
import { type ClassifiedChanges } from "./classify-change.js";
|
|
43
|
+
/**
|
|
44
|
+
* Re-exported from the shared kernel. `@rebasepro/server` derives these for a
|
|
45
|
+
* project in a subdirectory and cannot import a driver to do it, so the shape
|
|
46
|
+
* and the defaults live in `@rebasepro/types`.
|
|
47
|
+
*/
|
|
48
|
+
export { DEFAULT_COMMIT_PATHS, type SchemaCommitPaths } from "@rebasepro/types";
|
|
49
|
+
export interface SchemaCommitFile {
|
|
50
|
+
path: string;
|
|
51
|
+
contents: string;
|
|
52
|
+
}
|
|
53
|
+
export interface SchemaCommitInput {
|
|
54
|
+
/** What the running database was built from. */
|
|
55
|
+
before: CollectionConfig[];
|
|
56
|
+
/** What the editor is proposing. */
|
|
57
|
+
after: CollectionConfig[];
|
|
58
|
+
/**
|
|
59
|
+
* Files the caller has already produced — in practice the rewritten
|
|
60
|
+
* collection source from the AST editor. Carried through unchanged so the
|
|
61
|
+
* commit is complete in one object.
|
|
62
|
+
*/
|
|
63
|
+
sourceFiles?: SchemaCommitFile[];
|
|
64
|
+
paths?: Partial<SchemaCommitPaths>;
|
|
65
|
+
/**
|
|
66
|
+
* What the database this change is destined for actually has.
|
|
67
|
+
*
|
|
68
|
+
* Supplied by the live editor, which read it a moment ago; omitted by the
|
|
69
|
+
* pure callers, which have no database. It decides two things a plan cannot
|
|
70
|
+
* know from the collections alone — whether a table holds rows, and which
|
|
71
|
+
* values an enum type already carries — and both are the difference between
|
|
72
|
+
* a statement that applies and one that is rejected.
|
|
73
|
+
*/
|
|
74
|
+
existing?: ExistingSchema;
|
|
75
|
+
}
|
|
76
|
+
export interface SchemaCommit {
|
|
77
|
+
/** Every file the commit writes, source and generated alike. */
|
|
78
|
+
files: SchemaCommitFile[];
|
|
79
|
+
/**
|
|
80
|
+
* The additive statements this change adds, in dependency order.
|
|
81
|
+
*
|
|
82
|
+
* Empty when the change needs no DDL. Not written to a migration file —
|
|
83
|
+
* see the module comment.
|
|
84
|
+
*/
|
|
85
|
+
statements: string[];
|
|
86
|
+
classified: ClassifiedChanges;
|
|
87
|
+
/** A commit message describing the change in the terms a reader wants. */
|
|
88
|
+
message: string;
|
|
89
|
+
/**
|
|
90
|
+
* Constraints this change asks for that the statements do not carry, and
|
|
91
|
+
* why. Empty for almost every change; when it is not, it is the thing the
|
|
92
|
+
* person confirming needs to read before they confirm.
|
|
93
|
+
*/
|
|
94
|
+
withheldConstraints: WithheldConstraint[];
|
|
95
|
+
}
|
|
96
|
+
export declare class SchemaCommitError extends Error {
|
|
97
|
+
readonly classified: ClassifiedChanges;
|
|
98
|
+
constructor(message: string, classified: ClassifiedChanges);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The statements that take `before` to `after`.
|
|
102
|
+
*
|
|
103
|
+
* Both sides are planned against the *same* database and the difference is
|
|
104
|
+
* taken by exact statement text. That works because the planner is
|
|
105
|
+
* deterministic: the same collections against the same schema produce the same
|
|
106
|
+
* strings, so anything in the second plan and absent from the first is what
|
|
107
|
+
* this change adds — and nothing else. Planning both sides is what keeps
|
|
108
|
+
* pre-existing drift, which belongs to neither side of the edit, out of the
|
|
109
|
+
* statements this change gets credited with.
|
|
110
|
+
*
|
|
111
|
+
* ## Why `existing` matters more than it looks
|
|
112
|
+
*
|
|
113
|
+
* Planned against `nothing()`, every table reads as one this plan is creating,
|
|
114
|
+
* and the planner is then free to attach constraints that only hold on a table
|
|
115
|
+
* with no rows: a new required property comes out as
|
|
116
|
+
* `ADD COLUMN "x" TEXT NOT NULL`, which is right for a fresh table and fails
|
|
117
|
+
* against a live one holding rows. Those statements would be generated,
|
|
118
|
+
* committed, and then rejected by the very database they were written for.
|
|
119
|
+
*
|
|
120
|
+
* So a caller holding a real database passes it, and gets statements that
|
|
121
|
+
* describe that database. `nothing()` stays the default for the pure uses —
|
|
122
|
+
* generating a commit for inspection, and the tests that compare two plans —
|
|
123
|
+
* where there is no database to describe.
|
|
124
|
+
*/
|
|
125
|
+
export declare function additiveStatements(before: CollectionConfig[], after: CollectionConfig[], existing?: ExistingSchema, options?: EnsureOptions): string[];
|
|
126
|
+
/** A commit message that says what changed rather than that something did. */
|
|
127
|
+
export declare function commitMessage(classified: ClassifiedChanges): string;
|
|
128
|
+
/**
|
|
129
|
+
* Build the commit.
|
|
130
|
+
*
|
|
131
|
+
* Refuses when the change is not applicable — a commit describing a schema the
|
|
132
|
+
* ensure path will not produce is a commit that makes the repository lie about
|
|
133
|
+
* the database. The classification travels on the error so a caller can show
|
|
134
|
+
* exactly which change was the problem.
|
|
135
|
+
*/
|
|
136
|
+
export declare function generateSchemaCommit(input: SchemaCommitInput): Promise<SchemaCommit>;
|
|
@@ -37,3 +37,22 @@ export interface LegacyForeignKeyName {
|
|
|
37
37
|
export declare function findLegacyForeignKeyNames(generatedSource: string, collections: CollectionConfig[]): LegacyForeignKeyName[];
|
|
38
38
|
/** One-line summary for a log or a CLI notice. */
|
|
39
39
|
export declare function describeLegacyForeignKeyNames(found: LegacyForeignKeyName[]): string;
|
|
40
|
+
/** Something the collections derive that the generated schema does not declare. */
|
|
41
|
+
export interface MissingGeneratedName {
|
|
42
|
+
/** The table it belongs to, or is. */
|
|
43
|
+
table: string;
|
|
44
|
+
/** The column, when a column is what is missing. */
|
|
45
|
+
column?: string;
|
|
46
|
+
/** `<collection>` or `<collection>.<relation>`, for the message. */
|
|
47
|
+
source: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Tables and derived foreign-key columns the collections name and the generated
|
|
51
|
+
* schema does not.
|
|
52
|
+
*
|
|
53
|
+
* @param generatedSource contents of `backend/src/schema.generated.ts`
|
|
54
|
+
* @param collections the project's collections, as this release reads them
|
|
55
|
+
*/
|
|
56
|
+
export declare function findMissingGeneratedNames(generatedSource: string, collections: CollectionConfig[]): MissingGeneratedName[];
|
|
57
|
+
/** One-line summary for a log or a CLI notice. */
|
|
58
|
+
export declare function describeMissingGeneratedNames(missing: MissingGeneratedName[]): string;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*
|
|
22
22
|
* Pure module: no I/O, no logging.
|
|
23
23
|
*/
|
|
24
|
-
import type { CheckConstraintRow } from "./introspect-db-logic";
|
|
24
|
+
import type { CheckConstraintRow } from "./introspect-db-logic.js";
|
|
25
25
|
/** What a table's CHECK constraints say about one column. */
|
|
26
26
|
export interface ColumnCheckFacts {
|
|
27
27
|
/** Allowed values, from `IN (…)` / `= ANY (ARRAY[…])` / `= 'literal'`. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mapPgType } from "./introspect-db-types";
|
|
2
|
-
import type { CheckFactsByTable } from "./introspect-db-constraints";
|
|
3
|
-
import type { TableClassification } from "./introspect-db-structure";
|
|
1
|
+
import { mapPgType } from "./introspect-db-types.js";
|
|
2
|
+
import type { CheckFactsByTable } from "./introspect-db-constraints.js";
|
|
3
|
+
import type { TableClassification } from "./introspect-db-structure.js";
|
|
4
4
|
export interface TableRow {
|
|
5
5
|
table_name: string;
|
|
6
6
|
/** True for the parent of a partitioned table (`relkind = 'p'`). */
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* No side effects beyond `SELECT`. Introspection reads a database it does not
|
|
10
10
|
* own — it must never `ANALYZE`, create a temp table, or otherwise write.
|
|
11
11
|
*/
|
|
12
|
-
import type { SchemaMetadata } from "./introspect-db-logic";
|
|
12
|
+
import type { SchemaMetadata } from "./introspect-db-logic.js";
|
|
13
13
|
/** The subset of `pg.Client` this module needs, so tests can pass a fake. */
|
|
14
14
|
export interface QueryableClient {
|
|
15
15
|
query<R = Record<string, unknown>>(text: string, values?: unknown[]): Promise<{
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
* which the caller fills from {@link ./introspect-db-queries.countRowsUpTo} for
|
|
34
34
|
* the tables {@link lookupCandidates} names.
|
|
35
35
|
*/
|
|
36
|
-
import type { ForeignKeyRow, SchemaMetadata, TableColumn, TableMeta } from "./introspect-db-logic";
|
|
37
|
-
import type { CheckFactsByTable } from "./introspect-db-constraints";
|
|
36
|
+
import type { ForeignKeyRow, SchemaMetadata, TableColumn, TableMeta } from "./introspect-db-logic.js";
|
|
37
|
+
import type { CheckFactsByTable } from "./introspect-db-constraints.js";
|
|
38
38
|
/**
|
|
39
39
|
* The row count above which a referenced table is a real entity rather than a
|
|
40
40
|
* code list. Deliberately low: `pagila.category` has 16 rows and `language` 6,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the same way whether it was generated or introspected.
|
|
13
13
|
*/
|
|
14
14
|
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
15
|
-
import { TableMeta } from "./introspect-db-logic";
|
|
15
|
+
import { TableMeta } from "./introspect-db-logic.js";
|
|
16
16
|
export interface IntrospectedSchema {
|
|
17
17
|
tablesMap: Map<string, TableMeta>;
|
|
18
18
|
enumMap: Map<string, string[]>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a `{ type: "vector" }` property becomes an ANN index.
|
|
3
|
+
*
|
|
4
|
+
* Without an index, pgvector answers `ORDER BY embedding <=> $1` by computing
|
|
5
|
+
* the distance to every row and sorting — exact, and linear. That is the right
|
|
6
|
+
* answer at ten thousand rows and the wrong one at a million, which is why the
|
|
7
|
+
* default here is to build an index rather than to leave the column bare.
|
|
8
|
+
*
|
|
9
|
+
* ## The operator class is not a detail
|
|
10
|
+
*
|
|
11
|
+
* An index is built for exactly one operator class, and the planner uses it
|
|
12
|
+
* only for the operator that class implements. `vector_cosine_ops` answers
|
|
13
|
+
* `<=>` and nothing else; a query asking for `<->` against a cosine index gets
|
|
14
|
+
* a sequential scan and no error. So the default indexed distance here is
|
|
15
|
+
* `cosine`, because `cosine` is what `vectorSearch` measures with when the
|
|
16
|
+
* caller does not say — see `DrizzleConditionBuilder.buildVectorSearch`. The
|
|
17
|
+
* two defaults have to agree, and this comment is the reason they do.
|
|
18
|
+
*
|
|
19
|
+
* ## Why 2000 dimensions is a ceiling and not an error
|
|
20
|
+
*
|
|
21
|
+
* pgvector cannot index a `vector` wider than 2000 dimensions with either
|
|
22
|
+
* method. A 3072-dimension embedding (`text-embedding-3-large`) is therefore
|
|
23
|
+
* storable and searchable but not indexable. Refusing the boot over that would
|
|
24
|
+
* make a working configuration unbootable; silently indexing it is impossible.
|
|
25
|
+
* So the column is created, the index is skipped, and the reason is reported.
|
|
26
|
+
*
|
|
27
|
+
* Like `search-column.ts`, this module exists so that the DDL generator and the
|
|
28
|
+
* boot-time ensure render the *same* specification rather than describing the
|
|
29
|
+
* same index twice, differently. `contracts/derived-names.txt` records the
|
|
30
|
+
* names both produce, and CI fails if they diverge.
|
|
31
|
+
*/
|
|
32
|
+
import type { CollectionConfig, Property, VectorDistance } from "@rebasepro/types";
|
|
33
|
+
/**
|
|
34
|
+
* The widest `vector` pgvector will build an HNSW or IVFFlat index over.
|
|
35
|
+
* Storage and exact search are unaffected by this limit.
|
|
36
|
+
*/
|
|
37
|
+
export declare const MAX_INDEXABLE_VECTOR_DIMENSIONS = 2000;
|
|
38
|
+
/** The distance indexed when a property does not name one. */
|
|
39
|
+
export declare const DEFAULT_VECTOR_DISTANCE: VectorDistance;
|
|
40
|
+
/** The index method used when a property does not name one. */
|
|
41
|
+
export declare const DEFAULT_VECTOR_INDEX_METHOD: "hnsw";
|
|
42
|
+
export interface VectorIndexSpec {
|
|
43
|
+
schema: string;
|
|
44
|
+
table: string;
|
|
45
|
+
column: string;
|
|
46
|
+
indexName: string;
|
|
47
|
+
method: "hnsw" | "ivfflat";
|
|
48
|
+
distance: VectorDistance;
|
|
49
|
+
operatorClass: string;
|
|
50
|
+
/** Rendered into `WITH (...)`; empty when every parameter is defaulted. */
|
|
51
|
+
parameters: Array<[string, number]>;
|
|
52
|
+
}
|
|
53
|
+
/** A vector column that will not be indexed, and why. */
|
|
54
|
+
export interface SkippedVectorIndex {
|
|
55
|
+
schema: string;
|
|
56
|
+
table: string;
|
|
57
|
+
column: string;
|
|
58
|
+
dimensions: number;
|
|
59
|
+
reason: string;
|
|
60
|
+
}
|
|
61
|
+
export interface VectorIndexPlan {
|
|
62
|
+
specs: VectorIndexSpec[];
|
|
63
|
+
skipped: SkippedVectorIndex[];
|
|
64
|
+
}
|
|
65
|
+
export declare class VectorIndexConfigError extends Error {
|
|
66
|
+
constructor(message: string);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Every ANN index a collection's vector properties call for.
|
|
70
|
+
*
|
|
71
|
+
* `resolveColumn` is passed in rather than imported so that this module stays
|
|
72
|
+
* free of the DDL generator, which imports *it*. Both callers hand it the same
|
|
73
|
+
* `resolveColumnName`, and a contract test asserts the names agree.
|
|
74
|
+
*/
|
|
75
|
+
export declare const buildVectorIndexPlan: (collection: CollectionConfig, resolveColumn: (propName: string, prop?: Property | null) => string) => VectorIndexPlan;
|
|
76
|
+
/**
|
|
77
|
+
* The `CREATE INDEX` for one spec.
|
|
78
|
+
*
|
|
79
|
+
* `CONCURRENTLY` is deliberately absent, for the same reason it is absent from
|
|
80
|
+
* `searchIndexStatements`: this form is replayed as part of a migration, where
|
|
81
|
+
* a concurrent build is not allowed. The boot-time ensure rewrites it — see
|
|
82
|
+
* `ensureCollectionTables`.
|
|
83
|
+
*/
|
|
84
|
+
export declare const vectorIndexStatement: (spec: VectorIndexSpec) => string;
|
|
85
|
+
/** Every statement for a plan, in a stable order. */
|
|
86
|
+
export declare const vectorIndexStatements: (plan: VectorIndexPlan) => string[];
|
|
87
|
+
/** The index names a plan creates — what the derived-names contract records. */
|
|
88
|
+
export declare const vectorIndexNames: (plan: VectorIndexPlan) => string[];
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* same `rebase` schema convention used by entity_history, auth, etc.
|
|
8
8
|
*/
|
|
9
9
|
import { BranchInfo } from "@rebasepro/types";
|
|
10
|
-
import { DrizzleClient } from "../interfaces";
|
|
11
|
-
import { DatabasePoolManager } from "../databasePoolManager";
|
|
10
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
11
|
+
import { DatabasePoolManager } from "../databasePoolManager.js";
|
|
12
12
|
export declare class BranchService {
|
|
13
13
|
private db;
|
|
14
14
|
private poolManager;
|
|
@@ -2,10 +2,10 @@ import { SQL } from "drizzle-orm";
|
|
|
2
2
|
import { PgTable } from "drizzle-orm/pg-core";
|
|
3
3
|
import { FilterValues, OrderByTuple, LogicalCondition } from "@rebasepro/types";
|
|
4
4
|
import type { VectorSearchParams } from "@rebasepro/types";
|
|
5
|
-
import { RelationService } from "./RelationService";
|
|
6
|
-
import { DrizzleClient } from "../interfaces";
|
|
7
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
8
|
-
import { type NestedPathHop } from "./nested-path";
|
|
5
|
+
import { RelationService } from "./RelationService.js";
|
|
6
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
7
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
8
|
+
import { type NestedPathHop } from "./nested-path.js";
|
|
9
9
|
/**
|
|
10
10
|
* Service for handling all row read operations.
|
|
11
11
|
* Handles fetching, searching, counting, and filtering rows.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { RelationService } from "./RelationService";
|
|
2
|
-
import { RelationWriteService } from "./RelationWriteService";
|
|
3
|
-
import { FetchService } from "./FetchService";
|
|
4
|
-
import { DrizzleClient } from "../interfaces";
|
|
5
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
1
|
+
import { RelationService } from "./RelationService.js";
|
|
2
|
+
import { RelationWriteService } from "./RelationWriteService.js";
|
|
3
|
+
import { FetchService } from "./FetchService.js";
|
|
4
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
5
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
6
6
|
/**
|
|
7
7
|
* Service for handling all row write operations.
|
|
8
8
|
* Handles saving, deleting, and updating rows.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DrizzleClient } from "../interfaces";
|
|
1
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
2
2
|
import { CollectionConfig, FilterValues, OrderByTuple, ResolvedRelation, ResolvedHasMany, ResolvedHasOne } from "@rebasepro/types";
|
|
3
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
4
|
-
import type { NestedPathHop } from "./nested-path";
|
|
3
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
4
|
+
import type { NestedPathHop } from "./nested-path.js";
|
|
5
5
|
/**
|
|
6
6
|
* Service for handling all relation-related operations.
|
|
7
7
|
* Handles fetching, updating, and managing row relations.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CollectionConfig, ResolvedManyToMany, ResolvedRelation, ResolvedVia } from "@rebasepro/types";
|
|
2
|
-
import { DrizzleClient } from "../interfaces";
|
|
3
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
4
|
-
import type { NestedPathHop } from "./nested-path";
|
|
2
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
3
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
4
|
+
import type { NestedPathHop } from "./nested-path.js";
|
|
5
5
|
/**
|
|
6
6
|
* Writing relations: junction membership, foreign-key stamping, and the links a
|
|
7
7
|
* nested path creates or removes.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionConfig } from "@rebasepro/types";
|
|
2
|
-
import { PostgresCollectionRegistry } from "../../collections/PostgresCollectionRegistry";
|
|
2
|
+
import { PostgresCollectionRegistry } from "../../collections/PostgresCollectionRegistry.js";
|
|
3
3
|
/**
|
|
4
4
|
* One end of a many-to-many, as seen from the junction table.
|
|
5
5
|
*
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* than correctness. That is what makes coalescing safe.
|
|
27
27
|
*/
|
|
28
28
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
29
|
-
import { ChannelBus, ChannelBusFrame, ChannelBusHandler } from "./ChannelBus";
|
|
29
|
+
import { ChannelBus, ChannelBusFrame, ChannelBusHandler } from "./ChannelBus.js";
|
|
30
30
|
/** NOTIFY channel carrying channel-bus frames. */
|
|
31
31
|
export declare const CHANNEL_BUS_NOTIFY_CHANNEL = "rebase_channel_bus";
|
|
32
32
|
/**
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
18
18
|
import { type ChannelBus, type ChannelBusSetting } from "@rebasepro/types";
|
|
19
|
-
export * from "./ChannelBus";
|
|
20
|
-
export { PostgresChannelBus, CHANNEL_BUS_NOTIFY_CHANNEL, PG_NOTIFY_MAX_PAYLOAD_BYTES, DEFAULT_BATCH_WINDOW_MS, parseChannelBusFrame, parseChannelBusPayload } from "./PostgresChannelBus";
|
|
19
|
+
export * from "./ChannelBus.js";
|
|
20
|
+
export { PostgresChannelBus, CHANNEL_BUS_NOTIFY_CHANNEL, PG_NOTIFY_MAX_PAYLOAD_BYTES, DEFAULT_BATCH_WINDOW_MS, parseChannelBusFrame, parseChannelBusPayload } from "./PostgresChannelBus.js";
|
|
21
21
|
export interface ChannelBusDeps {
|
|
22
22
|
db: NodePgDatabase<Record<string, unknown>>;
|
|
23
23
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PgTable, AnyPgColumn } from "drizzle-orm/pg-core";
|
|
2
2
|
import { CollectionConfig, ResolvedHasMany, ResolvedHasOne } from "@rebasepro/types";
|
|
3
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
3
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
4
4
|
import { ApiError } from "@rebasepro/server";
|
|
5
5
|
export { buildCompositeId, parseIdValues, isAddressableId, COMPOSITE_ID_SEPARATOR } from "@rebasepro/common";
|
|
6
6
|
export type { PrimaryKeyInfo } from "@rebasepro/common";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { FilterValues, LogicalCondition, OrderByTuple } from "@rebasepro/types";
|
|
2
2
|
import type { VectorSearchParams } from "@rebasepro/types";
|
|
3
|
-
import { FetchService } from "./FetchService";
|
|
4
|
-
import { PersistService } from "./PersistService";
|
|
5
|
-
import { RelationService } from "./RelationService";
|
|
6
|
-
import { DataRepository, DrizzleClient } from "../interfaces";
|
|
7
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
8
|
-
export { sanitizeAndConvertDates, serializeDataToServer, parseDataFromServer } from "../data-transformer";
|
|
9
|
-
export { FetchService } from "./FetchService";
|
|
10
|
-
export { PersistService } from "./PersistService";
|
|
11
|
-
export { RelationService } from "./RelationService";
|
|
12
|
-
export * from "../interfaces";
|
|
3
|
+
import { FetchService } from "./FetchService.js";
|
|
4
|
+
import { PersistService } from "./PersistService.js";
|
|
5
|
+
import { RelationService } from "./RelationService.js";
|
|
6
|
+
import { DataRepository, DrizzleClient } from "../interfaces.js";
|
|
7
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
8
|
+
export { sanitizeAndConvertDates, serializeDataToServer, parseDataFromServer } from "../data-transformer.js";
|
|
9
|
+
export { FetchService } from "./FetchService.js";
|
|
10
|
+
export { PersistService } from "./PersistService.js";
|
|
11
|
+
export { RelationService } from "./RelationService.js";
|
|
12
|
+
export * from "../interfaces.js";
|
|
13
13
|
/**
|
|
14
14
|
* DataService - Facade for row operations.
|
|
15
15
|
*
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { FetchService } from "./FetchService";
|
|
2
|
-
export { PersistService } from "./PersistService";
|
|
3
|
-
export { RelationService } from "./RelationService";
|
|
4
|
-
export { getCollectionByPath, getTableForCollection, getPrimaryKeys, deriveRowAddress, parseIdValues, buildCompositeId } from "./collection-helpers";
|
|
1
|
+
export { FetchService } from "./FetchService.js";
|
|
2
|
+
export { PersistService } from "./PersistService.js";
|
|
3
|
+
export { RelationService } from "./RelationService.js";
|
|
4
|
+
export { getCollectionByPath, getTableForCollection, getPrimaryKeys, deriveRowAddress, parseIdValues, buildCompositeId } from "./collection-helpers.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnyPgColumn, PgTable } from "drizzle-orm/pg-core";
|
|
2
2
|
import type { ResolvedVia } from "@rebasepro/types";
|
|
3
|
-
import { DrizzleClient } from "../interfaces";
|
|
4
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
3
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
4
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
5
5
|
/**
|
|
6
6
|
* Writing a many-to-many means writing rows in a junction table, and doing that
|
|
7
7
|
* needs three things: the table, the column naming the row being written from,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionConfig, ResolvedRelation } from "@rebasepro/types";
|
|
2
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
2
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
3
3
|
/**
|
|
4
4
|
* The last hop of a nested collection path, e.g. `authors/1/posts`.
|
|
5
5
|
*
|
|
@@ -2,9 +2,9 @@ import { WebSocket } from "ws";
|
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
3
|
import { DataDriver, WebSocketMessage, LogicalCondition, OrderByTuple } from "@rebasepro/types";
|
|
4
4
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
5
|
-
import { RealtimeProvider, CollectionSubscriptionConfig, SingleSubscriptionConfig } from "../interfaces";
|
|
6
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
7
|
-
import { ChannelBus } from "./channel-bus";
|
|
5
|
+
import { RealtimeProvider, CollectionSubscriptionConfig, SingleSubscriptionConfig } from "../interfaces.js";
|
|
6
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
7
|
+
import { ChannelBus } from "./channel-bus/index.js";
|
|
8
8
|
import type { ChannelRetentionRule } from "@rebasepro/types";
|
|
9
9
|
/**
|
|
10
10
|
* Auth context stored per-subscription so real-time refetches respect RLS.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionConfig, ResolvedRelation } from "@rebasepro/types";
|
|
2
|
-
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
|
|
2
|
+
import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry.js";
|
|
3
3
|
/**
|
|
4
4
|
* Turning a drizzle result into a row we serve.
|
|
5
5
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SQL } from "drizzle-orm";
|
|
2
2
|
import { PgTable } from "drizzle-orm/pg-core";
|
|
3
3
|
import { ApiError } from "@rebasepro/server";
|
|
4
|
-
import { DrizzleClient } from "../interfaces";
|
|
4
|
+
import { DrizzleClient } from "../interfaces.js";
|
|
5
5
|
/**
|
|
6
6
|
* Explain a write that matched no rows.
|
|
7
7
|
*
|
|
@@ -410,6 +410,102 @@ function usesLegacyRlsFunctions(sql) {
|
|
|
410
410
|
return /\bauth\.(uid|jwt|roles)\s*\(\s*\)/i.test(sql);
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
|
+
//#region ../types/src/types/resources.ts
|
|
414
|
+
var GLOBAL_KEY = Symbol.for("@rebasepro/types.resourceRegistry");
|
|
415
|
+
function registry() {
|
|
416
|
+
const g = globalThis;
|
|
417
|
+
let existing = g[GLOBAL_KEY];
|
|
418
|
+
if (!existing) {
|
|
419
|
+
existing = {
|
|
420
|
+
kinds: /* @__PURE__ */ new Map(),
|
|
421
|
+
declarations: /* @__PURE__ */ new Map()
|
|
422
|
+
};
|
|
423
|
+
g[GLOBAL_KEY] = existing;
|
|
424
|
+
}
|
|
425
|
+
return existing;
|
|
426
|
+
}
|
|
427
|
+
/** Register a resource kind. Idempotent for an identical spec; throws on a conflicting one. */
|
|
428
|
+
function registerResourceKind(spec) {
|
|
429
|
+
const existing = registry().kinds.get(spec.kind);
|
|
430
|
+
if (existing && JSON.stringify(existing) !== JSON.stringify(spec)) throw new Error(`Resource kind "${spec.kind}" is already registered with a different definition. Two packages cannot define the same kind.`);
|
|
431
|
+
registry().kinds.set(spec.kind, spec);
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region ../types/src/types/resource_kinds.ts
|
|
435
|
+
/**
|
|
436
|
+
* The kinds Rebase ships, and the constructors a project declares them with.
|
|
437
|
+
*
|
|
438
|
+
* Each kind is registered rather than hardcoded, so a fourth one arrives
|
|
439
|
+
* without editing a manifest schema, a validator and a switch statement. That
|
|
440
|
+
* cost is precisely why databases and buckets ended up declared in different
|
|
441
|
+
* files with different rules — the cheapest thing to do was always to bolt the
|
|
442
|
+
* new kind onto whichever home was nearest.
|
|
443
|
+
*
|
|
444
|
+
* A kind owns its engine list. `custom:<id>` is always accepted, so a build
|
|
445
|
+
* that ships an engine this package has never heard of says so at the call site
|
|
446
|
+
* instead of looking like a typo of one that exists.
|
|
447
|
+
*/
|
|
448
|
+
registerResourceKind({
|
|
449
|
+
kind: "database",
|
|
450
|
+
engines: [
|
|
451
|
+
"postgres",
|
|
452
|
+
"mongodb",
|
|
453
|
+
"firestore",
|
|
454
|
+
"sqlite"
|
|
455
|
+
],
|
|
456
|
+
defaultEngine: "postgres",
|
|
457
|
+
envBases: [
|
|
458
|
+
"DATABASE_URL",
|
|
459
|
+
"REBASE_DRIVER",
|
|
460
|
+
"REBASE_DB_POOL_MAX"
|
|
461
|
+
],
|
|
462
|
+
optionKeys: ["databaseId", "migrations"],
|
|
463
|
+
implicitDefault: true
|
|
464
|
+
});
|
|
465
|
+
registerResourceKind({
|
|
466
|
+
kind: "bucket",
|
|
467
|
+
engines: [
|
|
468
|
+
"local",
|
|
469
|
+
"s3",
|
|
470
|
+
"gcs",
|
|
471
|
+
"azure",
|
|
472
|
+
"firebase"
|
|
473
|
+
],
|
|
474
|
+
defaultEngine: "local",
|
|
475
|
+
envBases: [
|
|
476
|
+
"S3_BUCKET",
|
|
477
|
+
"GCS_BUCKET",
|
|
478
|
+
"STORAGE_BUCKET",
|
|
479
|
+
"STORAGE_PUBLIC_URL"
|
|
480
|
+
],
|
|
481
|
+
envBasesByEngine: {
|
|
482
|
+
local: ["STORAGE_BUCKET"],
|
|
483
|
+
s3: [
|
|
484
|
+
"S3_BUCKET",
|
|
485
|
+
"STORAGE_ENDPOINT",
|
|
486
|
+
"STORAGE_REGION",
|
|
487
|
+
"STORAGE_PUBLIC_URL"
|
|
488
|
+
],
|
|
489
|
+
gcs: ["GCS_BUCKET", "STORAGE_PUBLIC_URL"],
|
|
490
|
+
azure: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"],
|
|
491
|
+
firebase: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"]
|
|
492
|
+
},
|
|
493
|
+
optionKeys: [
|
|
494
|
+
"publicRead",
|
|
495
|
+
"prefix",
|
|
496
|
+
"account"
|
|
497
|
+
],
|
|
498
|
+
implicitDefault: false
|
|
499
|
+
});
|
|
500
|
+
registerResourceKind({
|
|
501
|
+
kind: "topic",
|
|
502
|
+
engines: ["jobs"],
|
|
503
|
+
defaultEngine: "jobs",
|
|
504
|
+
envBases: ["REBASE_TOPIC_URL"],
|
|
505
|
+
optionKeys: ["delivery", "maxAttempts"],
|
|
506
|
+
implicitDefault: false
|
|
507
|
+
});
|
|
508
|
+
//#endregion
|
|
413
509
|
export { isRelationAggregateSort as _, rewriteLegacyRlsFunctions as a, toCanonicalOp as b, isPostgresCollectionConfig as c, getDataSourceCapabilities as d, ALL_WHERE_FILTER_OPS as f, encodeRelationAggregateSort as g, REST_TO_CANONICAL as h, RLS_UID_SQL as i, isRelationalCollectionConfig as l, NULL_OPS as m, REBASE_SCHEMA as n, usesLegacyRlsFunctions as o, CANONICAL_TO_REST as p, RLS_ROLES_SQL as r, getDeclaredSubcollections as s, LEGACY_RLS_SCHEMA as t, DEFAULT_DATA_SOURCE_KEY as u, parseRelationAggregateSort as v, sortKeyToString as y };
|
|
414
510
|
|
|
415
|
-
//# sourceMappingURL=src-
|
|
511
|
+
//# sourceMappingURL=src-DiDgtX8P.js.map
|