@rebasepro/server-postgres 0.19.1 → 0.19.2-canary.g08eed46
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/{BranchService-ByLfM_Tt.js → BranchService-W3DMfcZZ.js} +2 -2
- package/dist/{BranchService-ByLfM_Tt.js.map → BranchService-W3DMfcZZ.js.map} +1 -1
- package/dist/PostgresBackendDriver.d.ts +81 -7
- package/dist/PostgresBootstrapper.d.ts +10 -0
- package/dist/{backup-cli-oM9WQVlV.js → backup-cli-DSpQyqcG.js} +2 -2
- package/dist/{backup-cli-oM9WQVlV.js.map → backup-cli-DSpQyqcG.js.map} +1 -1
- package/dist/{backup-service-Br3tqwsy.js → backup-service-DA7a6SUV.js} +2 -2
- package/dist/{backup-service-Br3tqwsy.js.map → backup-service-DA7a6SUV.js.map} +1 -1
- package/dist/{cli-errors-DxN4yzdH.js → cli-errors-C3g_kHBw.js} +137 -18
- package/dist/cli-errors-C3g_kHBw.js.map +1 -0
- package/dist/cli-errors.d.ts +19 -0
- package/dist/cli-helpers.d.ts +47 -0
- package/dist/cli.js +233 -19
- package/dist/cli.js.map +1 -1
- package/dist/{collection-index-BHgT_TKd.js → collection-index-DdnsxiJ_.js} +14 -4
- package/dist/{collection-index-BHgT_TKd.js.map → collection-index-DdnsxiJ_.js.map} +1 -1
- package/dist/collections/validate-relations.d.ts +7 -0
- package/dist/column-plan-helpers-CpILzHJS.js +145 -0
- package/dist/column-plan-helpers-CpILzHJS.js.map +1 -0
- package/dist/{doctor-D7HWmGzs.js → doctor-D5SrGJ5P.js} +175 -61
- package/dist/doctor-D5SrGJ5P.js.map +1 -0
- package/dist/{ensure-collection-policies-2c2NV8zX.js → ensure-collection-policies-CHO0moXQ.js} +5 -5
- package/dist/{ensure-collection-policies-2c2NV8zX.js.map → ensure-collection-policies-CHO0moXQ.js.map} +1 -1
- package/dist/{ensure-collection-tables-D4wJzM4y.js → ensure-collection-tables-Bkvehxdm.js} +318 -312
- package/dist/ensure-collection-tables-Bkvehxdm.js.map +1 -0
- package/dist/{ensure-tables-CIojK-Rx.js → ensure-tables-CYMtuuOd.js} +2 -2
- package/dist/{ensure-tables-CIojK-Rx.js.map → ensure-tables-CYMtuuOd.js.map} +1 -1
- package/dist/generate-drizzle-schema-logic-Dfyf_MRu.js +228 -0
- package/dist/generate-drizzle-schema-logic-Dfyf_MRu.js.map +1 -0
- package/dist/{generate-drizzle-schema-CwEgVyjO.js → generate-drizzle-schema-vSK-VdYT.js} +3 -3
- package/dist/generate-drizzle-schema-vSK-VdYT.js.map +1 -0
- package/dist/generate-postgres-ddl-logic-CR2xcS7e.js +475 -0
- package/dist/generate-postgres-ddl-logic-CR2xcS7e.js.map +1 -0
- package/dist/{generated-schema-staleness-DQdfJl2A.js → generated-schema-staleness-DRQe2BpC.js} +81 -3
- package/dist/{generated-schema-staleness-DQdfJl2A.js.map → generated-schema-staleness-DRQe2BpC.js.map} +1 -1
- package/dist/history/HistoryService.d.ts +23 -4
- package/dist/index.es.js +1991 -580
- package/dist/index.es.js.map +1 -1
- package/dist/introspect-db-logic-C6LQdTxj.js.map +1 -1
- package/dist/plan-schema-Hgl62S-w.js +1531 -0
- package/dist/plan-schema-Hgl62S-w.js.map +1 -0
- package/dist/{policy-drift-kNJ6X2Uj.js → policy-drift-B0GDRh7_.js} +2 -2
- package/dist/{policy-drift-kNJ6X2Uj.js.map → policy-drift-B0GDRh7_.js.map} +1 -1
- package/dist/{rls-bootstrap-sql-DLDnUjtx.js → rls-bootstrap-sql-BlzsOUtz.js} +111 -8
- package/dist/{rls-bootstrap-sql-DLDnUjtx.js.map → rls-bootstrap-sql-BlzsOUtz.js.map} +1 -1
- package/dist/{rls-enforcement-DeYEjYLt.js → rls-enforcement-BV12vBwQ.js} +2 -1
- package/dist/rls-enforcement-BV12vBwQ.js.map +1 -0
- package/dist/schema/catalogue-schema.d.ts +97 -0
- package/dist/schema/collection-index.d.ts +9 -0
- package/dist/schema/column-plan-helpers.d.ts +125 -0
- package/dist/schema/config-relations.d.ts +32 -0
- package/dist/schema/doctor-cli.js +4 -4
- package/dist/schema/doctor.d.ts +9 -0
- package/dist/schema/dynamic-tables.d.ts +27 -6
- package/dist/schema/ensure-collection-tables.d.ts +31 -268
- package/dist/schema/generate-drizzle-schema-logic.d.ts +26 -8
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-postgres-ddl-logic.d.ts +84 -168
- package/dist/schema/generate-postgres-ddl.js +8 -2
- package/dist/schema/generate-postgres-ddl.js.map +1 -1
- package/dist/schema/generated-column-conflicts.d.ts +84 -0
- package/dist/schema/generated-schema-diff.d.ts +56 -0
- package/dist/schema/generated-schema-staleness.d.ts +33 -0
- package/dist/schema/introspect-db-logic.d.ts +2 -0
- package/dist/schema/plan/diff-plan.d.ts +220 -0
- package/dist/schema/plan/plan-schema.d.ts +84 -0
- package/dist/schema/plan/render-ddl.d.ts +62 -0
- package/dist/schema/plan/render-drizzle.d.ts +31 -0
- package/dist/schema/plan/types.d.ts +410 -0
- package/dist/schema/plan/updated-at-trigger.d.ts +22 -0
- package/dist/schema/relation-names.d.ts +28 -0
- package/dist/schema/search-column.d.ts +9 -0
- package/dist/security/rls-enforcement.d.ts +17 -0
- package/dist/services/FetchService.d.ts +176 -36
- package/dist/services/PersistService.d.ts +17 -4
- package/dist/services/RelationService.d.ts +11 -3
- package/dist/services/collection-helpers.d.ts +16 -2
- package/dist/services/dataService.d.ts +29 -2
- package/dist/services/field-op-sql.d.ts +16 -0
- package/dist/services/field-viewer.d.ts +19 -0
- package/dist/services/realtimeService.d.ts +35 -1
- package/dist/services/row-pipeline.d.ts +29 -5
- package/dist/services/soft-delete.d.ts +73 -0
- package/dist/utils/pg-error-utils.d.ts +41 -1
- package/dist/{vector-index-DkWxm2de.js → vector-index-CMJKb3C9.js} +3 -14
- package/dist/{vector-index-DkWxm2de.js.map → vector-index-CMJKb3C9.js.map} +1 -1
- package/package.json +18 -10
- package/dist/cli-errors-DxN4yzdH.js.map +0 -1
- package/dist/doctor-D7HWmGzs.js.map +0 -1
- package/dist/ensure-collection-tables-D4wJzM4y.js.map +0 -1
- package/dist/generate-drizzle-schema-CwEgVyjO.js.map +0 -1
- package/dist/generate-drizzle-schema-logic-so2Z_lyC.js +0 -528
- package/dist/generate-drizzle-schema-logic-so2Z_lyC.js.map +0 -1
- package/dist/generate-postgres-ddl-logic-CtnpIBVv.js +0 -1312
- package/dist/generate-postgres-ddl-logic-CtnpIBVv.js.map +0 -1
- package/dist/rls-enforcement-DeYEjYLt.js.map +0 -1
|
@@ -1,528 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "module";
|
|
2
|
-
__createRequire(import.meta.url);
|
|
3
|
-
import { t as defaultBelongsToOnDelete, v as buildSearchColumnSpec } from "./generate-postgres-ddl-logic-CtnpIBVv.js";
|
|
4
|
-
import { logger } from "@rebasepro/server";
|
|
5
|
-
import { hasForeignKeyOnTarget, isManyToMany, isPostgresCollectionConfig } from "@rebasepro/types";
|
|
6
|
-
import { fieldKeyForColumn, findRelation, getEffectiveSecurityRules, getEnumVarName, getJunctionCollectionConfig, getJunctionSecurityRules, getTableName, getTableVarName, policyToPostgres, relationalCollections, resolveCollectionRelations, resolveJunctionSpecs, resolveStringColumnLength, securityRuleToConditions, sortCollectionsBySlug } from "@rebasepro/common";
|
|
7
|
-
import { getPolicyNamesForRule, toSnakeCase } from "@rebasepro/utils";
|
|
8
|
-
//#region src/schema/generate-drizzle-schema-logic.ts
|
|
9
|
-
/**
|
|
10
|
-
* Resolve the SQL column name for a property.
|
|
11
|
-
* Uses the explicit `columnName` when set (e.g. from introspection),
|
|
12
|
-
* falling back to `toSnakeCase(propName)` for manually-authored collections.
|
|
13
|
-
*/
|
|
14
|
-
var JS_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
15
|
-
/**
|
|
16
|
-
* A string literal for the generated schema file.
|
|
17
|
-
*
|
|
18
|
-
* Column names, table names and enum values are all written into this file as
|
|
19
|
-
* literals, and none of them is constrained to be quote-free: a Postgres
|
|
20
|
-
* identifier only has to be quoted, and `O'Brien` is an ordinary enum value.
|
|
21
|
-
* Interpolating them raw ended the literal early — for enum values, inside
|
|
22
|
-
* single quotes, where an apostrophe is not an edge case.
|
|
23
|
-
*/
|
|
24
|
-
var quote = (value) => JSON.stringify(value);
|
|
25
|
-
/** An object key: verbatim when it is an identifier, quoted otherwise. */
|
|
26
|
-
var propKey = (name) => JS_IDENTIFIER.test(name) ? name : quote(name);
|
|
27
|
-
/**
|
|
28
|
-
* A property access on a generated table variable.
|
|
29
|
-
*
|
|
30
|
-
* `users.full name` is not an expression; `users["full name"]` is, and Drizzle
|
|
31
|
-
* treats the two identically.
|
|
32
|
-
*/
|
|
33
|
-
var member = (object, key) => JS_IDENTIFIER.test(key) ? `${object}.${key}` : `${object}[${quote(key)}]`;
|
|
34
|
-
var resolveColumnName = (propName, prop) => {
|
|
35
|
-
if (prop && "columnName" in prop && typeof prop.columnName === "string") return prop.columnName;
|
|
36
|
-
return toSnakeCase(propName);
|
|
37
|
-
};
|
|
38
|
-
var getPrimaryKeyProp = (collection) => {
|
|
39
|
-
if (collection.properties) {
|
|
40
|
-
const idPropEntry = Object.entries(collection.properties).find(([_, prop]) => "isId" in prop && Boolean(prop.isId));
|
|
41
|
-
if (idPropEntry) {
|
|
42
|
-
const prop = idPropEntry[1];
|
|
43
|
-
const isUuid = prop.type === "string" && "isId" in prop && prop.isId === "uuid";
|
|
44
|
-
return {
|
|
45
|
-
name: idPropEntry[0],
|
|
46
|
-
type: prop.type === "number" ? "number" : "string",
|
|
47
|
-
isUuid
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const idProp = collection.properties?.["id"];
|
|
52
|
-
if (idProp?.type === "number") return {
|
|
53
|
-
name: "id",
|
|
54
|
-
type: "number",
|
|
55
|
-
isUuid: false
|
|
56
|
-
};
|
|
57
|
-
return {
|
|
58
|
-
name: "id",
|
|
59
|
-
type: "string",
|
|
60
|
-
isUuid: idProp?.type === "string" && "isId" in idProp && idProp.isId === "uuid"
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* Given a raw DB column name (e.g. "client_id"), the Drizzle property key that
|
|
65
|
-
* maps to it.
|
|
66
|
-
*
|
|
67
|
-
* One line, because the rule is shared: the Drizzle object key is the wire
|
|
68
|
-
* name, and {@link fieldKeyForColumn} is the one definition of what a column is
|
|
69
|
-
* named on the wire. This used to be a private copy that fell back to the
|
|
70
|
-
* column verbatim, which is how a derived foreign key ended up served as
|
|
71
|
-
* `author_id` beside a hand-authored `displayName`.
|
|
72
|
-
*/
|
|
73
|
-
var resolvePropertyKeyForColumn = (collection, column) => fieldKeyForColumn(collection, column);
|
|
74
|
-
var isNumericId = (collection) => {
|
|
75
|
-
return getPrimaryKeyProp(collection).type === "number";
|
|
76
|
-
};
|
|
77
|
-
var getPrimaryKeyName = (collection) => {
|
|
78
|
-
return getPrimaryKeyProp(collection).name;
|
|
79
|
-
};
|
|
80
|
-
var isIdProperty = (propName, prop, collection) => {
|
|
81
|
-
if ("isId" in prop && Boolean(prop.isId)) return true;
|
|
82
|
-
return !Object.values(collection.properties ?? {}).some((p) => "isId" in p && Boolean(p.isId)) && propName === "id";
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* The Drizzle column declaration a property compiles to, or `null` when the
|
|
86
|
-
* property puts no column on *this* table (an inverse relation, whose column
|
|
87
|
-
* lives on the target). Exported so it can be checked against its DDL twin
|
|
88
|
-
* `getSqlColumnType` directly — the two disagreeing is what left `geopoint`
|
|
89
|
-
* with a database column and no Drizzle key.
|
|
90
|
-
*/
|
|
91
|
-
var getDrizzleColumn = (propName, prop, collection, collections) => {
|
|
92
|
-
const colName = resolveColumnName(propName, prop);
|
|
93
|
-
let columnDefinition;
|
|
94
|
-
switch (prop.type) {
|
|
95
|
-
case "string": {
|
|
96
|
-
const stringProp = prop;
|
|
97
|
-
if (stringProp.enum) columnDefinition = `${getEnumVarName(getTableName(collection), propName)}(${quote(colName)})`;
|
|
98
|
-
else if ("isId" in stringProp && stringProp.isId === "uuid") columnDefinition = `uuid(${quote(colName)})`;
|
|
99
|
-
else if (stringProp.columnType === "uuid") columnDefinition = `uuid(${quote(colName)})`;
|
|
100
|
-
else if (stringProp.columnType === "char") columnDefinition = `char(${quote(colName)}, { length: ${resolveStringColumnLength(stringProp)} })`;
|
|
101
|
-
else if (stringProp.columnType === "varchar") columnDefinition = `varchar(${quote(colName)}, { length: ${resolveStringColumnLength(stringProp)} })`;
|
|
102
|
-
else columnDefinition = `text(${quote(colName)})`;
|
|
103
|
-
if (isIdProperty(propName, prop, collection)) columnDefinition += ".primaryKey()";
|
|
104
|
-
if ("isId" in stringProp && stringProp.isId !== "manual" && stringProp.isId !== true) {
|
|
105
|
-
if (stringProp.isId === "uuid") columnDefinition += ".defaultRandom()";
|
|
106
|
-
else if (stringProp.isId === "cuid") columnDefinition += ".default(sql`cuid()`)";
|
|
107
|
-
else if (typeof stringProp.isId === "string") {
|
|
108
|
-
const sqlContent = stringProp.isId.startsWith("sql`") && stringProp.isId.endsWith("`") ? stringProp.isId.substring(4, stringProp.isId.length - 1) : stringProp.isId;
|
|
109
|
-
columnDefinition += `.default(sql\`${sqlContent}\`)`;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (stringProp.validation?.unique) columnDefinition += ".unique()";
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
case "number": {
|
|
116
|
-
const numProp = prop;
|
|
117
|
-
const isId = isIdProperty(propName, prop, collection);
|
|
118
|
-
let baseType = numProp.validation?.integer || isId ? `integer(${quote(colName)})` : `numeric(${quote(colName)})`;
|
|
119
|
-
if (numProp.columnType) if (numProp.columnType === "double precision") baseType = `doublePrecision(${quote(colName)})`;
|
|
120
|
-
else if (numProp.columnType === "bigint" || numProp.columnType === "bigserial") baseType = `${numProp.columnType}(${quote(colName)}, { mode: "number" })`;
|
|
121
|
-
else baseType = `${numProp.columnType}(${quote(colName)})`;
|
|
122
|
-
if ("isId" in numProp && numProp.isId === "increment") columnDefinition = `${baseType}.generatedByDefaultAsIdentity()`;
|
|
123
|
-
else if ("isId" in numProp && typeof numProp.isId === "string" && numProp.isId !== "manual") {
|
|
124
|
-
columnDefinition = baseType;
|
|
125
|
-
const sqlContent = numProp.isId.startsWith("sql`") && numProp.isId.endsWith("`") ? numProp.isId.substring(4, numProp.isId.length - 1) : numProp.isId;
|
|
126
|
-
columnDefinition += `.default(sql\`${sqlContent}\`)`;
|
|
127
|
-
} else columnDefinition = baseType;
|
|
128
|
-
if (isId) columnDefinition += ".primaryKey()";
|
|
129
|
-
if (numProp.validation?.unique) columnDefinition += ".unique()";
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
case "boolean":
|
|
133
|
-
columnDefinition = `boolean(${quote(colName)})`;
|
|
134
|
-
break;
|
|
135
|
-
case "date": {
|
|
136
|
-
const dateProp = prop;
|
|
137
|
-
if (dateProp.columnType === "date") columnDefinition = `date(${quote(colName)}, { mode: 'string' })`;
|
|
138
|
-
else if (dateProp.columnType === "time") columnDefinition = `time(${quote(colName)})`;
|
|
139
|
-
else columnDefinition = `timestamp(${quote(colName)}, { withTimezone: true, mode: 'string' })`;
|
|
140
|
-
if (dateProp.autoValue === "on_create" || dateProp.autoValue === "on_update") columnDefinition += ".default(sql`now()`)";
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
case "map":
|
|
144
|
-
if (prop.columnType === "json") columnDefinition = `json(${quote(colName)})`;
|
|
145
|
-
else columnDefinition = `jsonb(${quote(colName)})`;
|
|
146
|
-
break;
|
|
147
|
-
case "geopoint":
|
|
148
|
-
columnDefinition = `jsonb(${quote(colName)})`;
|
|
149
|
-
break;
|
|
150
|
-
case "array": {
|
|
151
|
-
const arrayProp = prop;
|
|
152
|
-
let colType = arrayProp.columnType;
|
|
153
|
-
if (!colType && arrayProp.of && !Array.isArray(arrayProp.of)) {
|
|
154
|
-
const ofProp = arrayProp.of;
|
|
155
|
-
if (ofProp.type === "string") colType = "text[]";
|
|
156
|
-
else if (ofProp.type === "number") colType = ofProp.validation?.integer ? "integer[]" : "numeric[]";
|
|
157
|
-
else if (ofProp.type === "boolean") colType = "boolean[]";
|
|
158
|
-
}
|
|
159
|
-
if (colType === "json") columnDefinition = `json(${quote(colName)})`;
|
|
160
|
-
else if (colType === "text[]") columnDefinition = `text(${quote(colName)}).array()`;
|
|
161
|
-
else if (colType === "integer[]") columnDefinition = `integer(${quote(colName)}).array()`;
|
|
162
|
-
else if (colType === "boolean[]") columnDefinition = `boolean(${quote(colName)}).array()`;
|
|
163
|
-
else if (colType === "numeric[]") columnDefinition = `numeric(${quote(colName)}).array()`;
|
|
164
|
-
else columnDefinition = `jsonb(${quote(colName)})`;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
case "vector": {
|
|
168
|
-
const vp = prop;
|
|
169
|
-
columnDefinition = `vector(${quote(colName)}, { dimensions: ${vp.dimensions} })`;
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
case "binary":
|
|
173
|
-
columnDefinition = `customType({ dataType() { return 'bytea'; } })(${quote(colName)})`;
|
|
174
|
-
break;
|
|
175
|
-
case "relation": {
|
|
176
|
-
const refProp = prop;
|
|
177
|
-
const relation = findRelation(resolveCollectionRelations(collection), refProp.relation?.relationName ?? propName);
|
|
178
|
-
if (!relation || relation.kind !== "belongsTo") return null;
|
|
179
|
-
const fkFieldKey = fieldKeyForColumn(collection, relation.localKey);
|
|
180
|
-
if (collection.properties[fkFieldKey] && propName !== fkFieldKey) return null;
|
|
181
|
-
let targetCollection;
|
|
182
|
-
try {
|
|
183
|
-
targetCollection = relation.target();
|
|
184
|
-
} catch {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
const fkColumnName = relation.localKey;
|
|
188
|
-
const targetTableVar = getTableVarName(getTableName(targetCollection));
|
|
189
|
-
const pkProp = getPrimaryKeyProp(targetCollection);
|
|
190
|
-
const targetIdField = pkProp.name;
|
|
191
|
-
const baseColumn = pkProp.type === "number" ? `integer(${quote(fkColumnName)})` : pkProp.isUuid ? `uuid(${quote(fkColumnName)})` : `text(${quote(fkColumnName)})`;
|
|
192
|
-
const onUpdate = relation.onUpdate ? `onUpdate: "${relation.onUpdate}"` : "";
|
|
193
|
-
const required = prop.validation?.required;
|
|
194
|
-
const refOptionsParts = [onUpdate, `onDelete: \"${relation.onDelete ?? defaultBelongsToOnDelete(required).toLowerCase()}\"`].filter(Boolean);
|
|
195
|
-
const refOptions = refOptionsParts.length > 0 ? `{ ${refOptionsParts.join(", ")} }` : "";
|
|
196
|
-
let columnDef = `${baseColumn}.references(() => ${member(targetTableVar, targetIdField)}${refOptions ? `, ${refOptions}` : ""})`;
|
|
197
|
-
if (required) columnDef += ".notNull()";
|
|
198
|
-
return ` ${propKey(fkFieldKey)}: ${columnDef}`;
|
|
199
|
-
}
|
|
200
|
-
case "reference": {
|
|
201
|
-
const refProp = prop;
|
|
202
|
-
const targetCollection = collections.find((c) => c.slug === refProp.path || getTableName(c) === refProp.path);
|
|
203
|
-
if (!targetCollection) {
|
|
204
|
-
columnDefinition = `text(${quote(colName)})`;
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
const pkProp = getPrimaryKeyProp(targetCollection);
|
|
208
|
-
const targetTableVar = getTableVarName(getTableName(targetCollection));
|
|
209
|
-
const targetIdField = pkProp.name;
|
|
210
|
-
const baseColumn = pkProp.type === "number" ? `integer(${quote(colName)})` : pkProp.isUuid ? `uuid(${quote(colName)})` : `text(${quote(colName)})`;
|
|
211
|
-
const required = prop.validation?.required;
|
|
212
|
-
const refOptions = `{ onDelete: "${required ? "cascade" : "set null"}" }`;
|
|
213
|
-
columnDefinition = `${baseColumn}.references(() => ${member(targetTableVar, targetIdField)}, ${refOptions})`;
|
|
214
|
-
if (required) columnDefinition += ".notNull()";
|
|
215
|
-
return ` ${propKey(propName)}: ${columnDefinition}`;
|
|
216
|
-
}
|
|
217
|
-
default: throw new Error(`No Postgres column mapping for property '${propName}' of type '${prop.type}' in collection '${collection.slug}'. Add a case to \`getDrizzleColumn\` (and to \`getSqlColumnType\`, which must agree).`);
|
|
218
|
-
}
|
|
219
|
-
if (prop.validation?.required) columnDefinition += ".notNull()";
|
|
220
|
-
return ` ${propKey(propName)}: ${columnDefinition}`;
|
|
221
|
-
};
|
|
222
|
-
/**
|
|
223
|
-
* Wraps a compiled SQL clause in a Drizzle `sql\`...\`` template literal.
|
|
224
|
-
*
|
|
225
|
-
* The clause is SQL being written into a TypeScript file, so it has to survive
|
|
226
|
-
* being read back as a template literal. Three characters do not:
|
|
227
|
-
*
|
|
228
|
-
* - `` ` `` closes the template early, and the rest of the clause becomes code.
|
|
229
|
-
* - `${` opens an interpolation — the file stops compiling, or worse, compiles
|
|
230
|
-
* against whatever identifier happens to be in scope.
|
|
231
|
-
* - `\` is an escape, and Drizzle's `sql` tag reads the *cooked* strings, not
|
|
232
|
-
* `.raw`. So a policy written as `email ~ '^admin\.user@corp\.com$'` reaches
|
|
233
|
-
* the database as `^admin.user@corp.com$`, where every `\.` now matches any
|
|
234
|
-
* character. A `USING` clause is a security boundary and that one silently
|
|
235
|
-
* widened it — the SQL file emitted by the DDL generator kept the backslashes
|
|
236
|
-
* while this path dropped them, so the two disagreed about who could read the
|
|
237
|
-
* table.
|
|
238
|
-
*
|
|
239
|
-
* Escaping here rather than in the compiler: the clause is correct SQL, and it
|
|
240
|
-
* is only this destination that has an opinion about backslashes.
|
|
241
|
-
*/
|
|
242
|
-
var wrapSql = (clause) => `sql\`${clause.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\``;
|
|
243
|
-
var generatePolicyCode = (collection, rule, index, resolveCollection) => {
|
|
244
|
-
const tableName = getTableName(collection);
|
|
245
|
-
const ops = rule.operations && rule.operations.length > 0 ? rule.operations : [rule.operation ?? "all"];
|
|
246
|
-
const policyNames = getPolicyNamesForRule(rule, tableName);
|
|
247
|
-
return ops.map((op, opIdx) => {
|
|
248
|
-
return generateSinglePolicyCode(collection, rule, op, policyNames[opIdx], resolveCollection);
|
|
249
|
-
}).join("");
|
|
250
|
-
};
|
|
251
|
-
/**
|
|
252
|
-
* Generates a single pgPolicy() call for one specific operation.
|
|
253
|
-
*/
|
|
254
|
-
var generateSinglePolicyCode = (collection, rule, operation, policyName, resolveCollection) => {
|
|
255
|
-
const mode = rule.mode ?? "permissive";
|
|
256
|
-
const needsUsing = operation !== "insert";
|
|
257
|
-
const needsWithCheck = operation !== "select" && operation !== "delete";
|
|
258
|
-
const { usingExpr, withCheckExpr } = securityRuleToConditions(rule);
|
|
259
|
-
let usingClause = needsUsing && usingExpr ? wrapSql(policyToPostgres(usingExpr, collection, { resolveCollection })) : null;
|
|
260
|
-
let withCheckClause = needsWithCheck && withCheckExpr ? wrapSql(policyToPostgres(withCheckExpr, collection, { resolveCollection })) : null;
|
|
261
|
-
if (!usingClause && needsUsing) usingClause = "sql`false`";
|
|
262
|
-
if (!withCheckClause && needsWithCheck) withCheckClause = "sql`false`";
|
|
263
|
-
const parts = [];
|
|
264
|
-
parts.push(`as: "${mode}"`);
|
|
265
|
-
parts.push(`for: "${operation}"`);
|
|
266
|
-
const toRoles = rule.pgRoles ? [...rule.pgRoles].sort() : ["public"];
|
|
267
|
-
parts.push(`to: [${toRoles.map((r) => `"${r}"`).join(", ")}]`);
|
|
268
|
-
if (usingClause) parts.push(`using: ${usingClause}`);
|
|
269
|
-
if (withCheckClause) parts.push(`withCheck: ${withCheckClause}`);
|
|
270
|
-
return ` pgPolicy(${quote(policyName)}, { ${parts.join(", ")} }),\n`;
|
|
271
|
-
};
|
|
272
|
-
/**
|
|
273
|
-
* Computes a deterministic shared relation name for Drizzle.
|
|
274
|
-
*
|
|
275
|
-
* Drizzle requires both sides of a relation (owning + inverse) to use the
|
|
276
|
-
* exact same `relationName` string so it can pair them. Each collection
|
|
277
|
-
* definition may use a different local `relationName`, so we need a canonical
|
|
278
|
-
* form that both sides can independently compute.
|
|
279
|
-
*
|
|
280
|
-
* Strategy: `{owningTable}_{foreignKey}`
|
|
281
|
-
* - owning side → `{thisTable}_{localKey}` e.g. "jobs_company_id"
|
|
282
|
-
* - inverse side → `{targetTable}_{foreignKeyOnTarget}` e.g. "jobs_company_id"
|
|
283
|
-
*
|
|
284
|
-
* For M2M with junction tables the owning relation name is already shared via
|
|
285
|
-
* the junction table wiring, so we keep it as-is.
|
|
286
|
-
*
|
|
287
|
-
* Falls back to the local relation name when the counterpart can't be resolved.
|
|
288
|
-
*/
|
|
289
|
-
var computeSharedRelationName = (rel, sourceCollection, _collections) => {
|
|
290
|
-
const fallback = rel.relationName ?? toSnakeCase(rel.target().slug);
|
|
291
|
-
if (rel.kind === "belongsTo") {
|
|
292
|
-
const normalisedKey = resolvePropertyKeyForColumn(sourceCollection, rel.localKey);
|
|
293
|
-
return `${getTableName(sourceCollection)}_${normalisedKey}`;
|
|
294
|
-
}
|
|
295
|
-
if (rel.kind === "hasMany" || rel.kind === "hasOne") try {
|
|
296
|
-
const targetCollection = rel.target();
|
|
297
|
-
const normalisedFK = resolvePropertyKeyForColumn(targetCollection, rel.foreignKeyOnTarget);
|
|
298
|
-
return `${getTableName(targetCollection)}_${normalisedFK}`;
|
|
299
|
-
} catch {
|
|
300
|
-
return fallback;
|
|
301
|
-
}
|
|
302
|
-
return fallback;
|
|
303
|
-
};
|
|
304
|
-
var generateSchema = async (allCollections, stripPolicies = false) => {
|
|
305
|
-
const collections = sortCollectionsBySlug(relationalCollections(allCollections));
|
|
306
|
-
let schemaContent = "// This file is auto-generated by the Rebase Drizzle generator. Do not edit manually.\n\n";
|
|
307
|
-
const hasUuid = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "string" && (p.autoValue === "uuid" || p.isId === "uuid")));
|
|
308
|
-
const hasVector = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "vector"));
|
|
309
|
-
const hasBinary = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "binary"));
|
|
310
|
-
const hasSearch = collections.some((c) => buildSearchColumnSpec(c) !== void 0);
|
|
311
|
-
const pgCoreImports = [
|
|
312
|
-
"primaryKey",
|
|
313
|
-
"pgTable",
|
|
314
|
-
"integer",
|
|
315
|
-
"varchar",
|
|
316
|
-
"text",
|
|
317
|
-
"char",
|
|
318
|
-
"boolean",
|
|
319
|
-
"timestamp",
|
|
320
|
-
"date",
|
|
321
|
-
"time",
|
|
322
|
-
"jsonb",
|
|
323
|
-
"json",
|
|
324
|
-
"pgEnum",
|
|
325
|
-
"numeric",
|
|
326
|
-
"real",
|
|
327
|
-
"doublePrecision",
|
|
328
|
-
"bigint",
|
|
329
|
-
"serial",
|
|
330
|
-
"bigserial",
|
|
331
|
-
"pgPolicy"
|
|
332
|
-
];
|
|
333
|
-
if (hasUuid) pgCoreImports.push("uuid");
|
|
334
|
-
if (hasVector) pgCoreImports.push("vector");
|
|
335
|
-
if (hasBinary || hasSearch) pgCoreImports.push("customType");
|
|
336
|
-
const uniqueSchemas = Array.from(new Set(collections.map((c) => isPostgresCollectionConfig(c) ? c.schema : void 0).filter(Boolean)));
|
|
337
|
-
if (uniqueSchemas.length > 0) pgCoreImports.push("pgSchema");
|
|
338
|
-
schemaContent += `import { ${pgCoreImports.join(", ")} } from 'drizzle-orm/pg-core';\n`;
|
|
339
|
-
schemaContent += "import { relations as drizzleRelations, sql } from 'drizzle-orm';\n\n";
|
|
340
|
-
uniqueSchemas.forEach((schema) => {
|
|
341
|
-
schemaContent += `export const ${schema}Schema = pgSchema("${schema}");\n`;
|
|
342
|
-
});
|
|
343
|
-
if (uniqueSchemas.length > 0) schemaContent += "\n";
|
|
344
|
-
const exportedTableVars = [];
|
|
345
|
-
const exportedEnumVars = [];
|
|
346
|
-
const exportedRelationVars = [];
|
|
347
|
-
const allTablesToGenerate = /* @__PURE__ */ new Map();
|
|
348
|
-
collections.forEach((collection) => {
|
|
349
|
-
const collectionPath = getTableName(collection);
|
|
350
|
-
Object.entries(collection.properties ?? {}).forEach(([propName, prop]) => {
|
|
351
|
-
if ("enum" in prop && (prop.type === "string" || prop.type === "number") && prop.enum) {
|
|
352
|
-
const enumVarName = getEnumVarName(collectionPath, propName);
|
|
353
|
-
const enumDbName = `${collectionPath}_${resolveColumnName(propName, prop)}`;
|
|
354
|
-
const values = Array.isArray(prop.enum) ? prop.enum.map((v) => String(typeof v === "object" && v !== null && "id" in v ? v.id : v)) : Object.keys(prop.enum);
|
|
355
|
-
if (values.length > 0) {
|
|
356
|
-
schemaContent += `export const ${enumVarName} = pgEnum(${quote(enumDbName)}, [${values.map((v) => quote(v)).join(", ")}]);\n`;
|
|
357
|
-
if (!exportedEnumVars.includes(enumVarName)) exportedEnumVars.push(enumVarName);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
schemaContent += "\n";
|
|
363
|
-
const junctionSpecs = resolveJunctionSpecs(collections);
|
|
364
|
-
for (const collection of collections) {
|
|
365
|
-
const tableName = getTableName(collection);
|
|
366
|
-
if (tableName) allTablesToGenerate.set(tableName, { collection });
|
|
367
|
-
const resolvedRelations = resolveCollectionRelations(collection);
|
|
368
|
-
for (const relation of Object.values(resolvedRelations)) if (isManyToMany(relation)) {
|
|
369
|
-
const junctionTableName = relation.through.table;
|
|
370
|
-
if (!allTablesToGenerate.has(junctionTableName)) allTablesToGenerate.set(junctionTableName, {
|
|
371
|
-
collection: {
|
|
372
|
-
table: junctionTableName,
|
|
373
|
-
properties: {}
|
|
374
|
-
},
|
|
375
|
-
isJunction: true,
|
|
376
|
-
relation,
|
|
377
|
-
sourceCollection: collection
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
for (const [tableName, { collection, isJunction, relation, sourceCollection }] of allTablesToGenerate.entries()) {
|
|
382
|
-
const tableVarName = getTableVarName(tableName);
|
|
383
|
-
if (isJunction && relation && sourceCollection && isManyToMany(relation)) {
|
|
384
|
-
const targetCollection = relation.target();
|
|
385
|
-
const tableCreator = "pgTable";
|
|
386
|
-
const baseTableName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
|
|
387
|
-
const { sourceColumn, targetColumn } = relation.through;
|
|
388
|
-
const refOptions = `{ onDelete: \"${relation.onDelete ?? "cascade"}\" }`;
|
|
389
|
-
const sourceColType = isNumericId(sourceCollection) ? "integer" : getPrimaryKeyProp(sourceCollection).isUuid ? "uuid" : "text";
|
|
390
|
-
const targetColType = isNumericId(targetCollection) ? "integer" : getPrimaryKeyProp(targetCollection).isUuid ? "uuid" : "text";
|
|
391
|
-
const sourceId = getPrimaryKeyName(sourceCollection);
|
|
392
|
-
const targetId = getPrimaryKeyName(targetCollection);
|
|
393
|
-
schemaContent += `export const ${tableVarName} = ${tableCreator}(\"${baseTableName}\", {\n`;
|
|
394
|
-
schemaContent += ` ${propKey(sourceColumn)}: ${sourceColType}(${quote(sourceColumn)}).notNull().references(() => ${member(getTableVarName(getTableName(sourceCollection)), sourceId)}, ${refOptions}),\n`;
|
|
395
|
-
schemaContent += ` ${propKey(targetColumn)}: ${targetColType}(${quote(targetColumn)}).notNull().references(() => ${member(getTableVarName(getTableName(targetCollection)), targetId)}, ${refOptions}),\n`;
|
|
396
|
-
schemaContent += "}, (table) => ([\n";
|
|
397
|
-
schemaContent += ` primaryKey({ columns: [${member("table", sourceColumn)}, ${member("table", targetColumn)}] }),\n`;
|
|
398
|
-
const junctionSpec = junctionSpecs.get(baseTableName);
|
|
399
|
-
if (!stripPolicies && junctionSpec) {
|
|
400
|
-
const junctionCollection = getJunctionCollectionConfig(junctionSpec);
|
|
401
|
-
const resolveCollection = (slug) => collections.find((c) => c.slug === slug || getTableName(c) === slug);
|
|
402
|
-
getJunctionSecurityRules(junctionSpec).forEach((rule, idx) => {
|
|
403
|
-
schemaContent += generatePolicyCode(junctionCollection, rule, idx, resolveCollection);
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
schemaContent += "])).enableRLS();\n\n";
|
|
407
|
-
} else if (!isJunction) {
|
|
408
|
-
const schema = isPostgresCollectionConfig(collection) ? collection.schema : void 0;
|
|
409
|
-
const tableCreator = schema ? `${schema}Schema.table` : "pgTable";
|
|
410
|
-
const baseTableName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
|
|
411
|
-
schemaContent += `export const ${tableVarName} = ${tableCreator}(\"${baseTableName}\", {\n`;
|
|
412
|
-
const columns = /* @__PURE__ */ new Set();
|
|
413
|
-
Object.entries(collection.properties ?? {}).forEach(([propName, prop]) => {
|
|
414
|
-
const columnString = getDrizzleColumn(propName, prop, collection, collections);
|
|
415
|
-
if (columnString) columns.add(columnString);
|
|
416
|
-
});
|
|
417
|
-
const searchSpec = buildSearchColumnSpec(collection);
|
|
418
|
-
if (searchSpec) {
|
|
419
|
-
columns.add(` ${propKey(searchSpec.column)}: customType({ dataType() { return 'tsvector'; } })(${quote(searchSpec.column)}).generatedAlwaysAs(sql\`${searchSpec.expression}\`)`);
|
|
420
|
-
if (searchSpec.fuzzy) columns.add(` ${propKey(searchSpec.fuzzy.column)}: text(${quote(searchSpec.fuzzy.column)}).generatedAlwaysAs(sql\`${searchSpec.fuzzy.expression}\`)`);
|
|
421
|
-
}
|
|
422
|
-
if (!Array.from(columns).some((col) => col.includes(".primaryKey()"))) columns.add(" id: text(\"id\").primaryKey()");
|
|
423
|
-
schemaContent += `${Array.from(columns).join(",\n")}`;
|
|
424
|
-
const securityRules = getEffectiveSecurityRules(collection);
|
|
425
|
-
if (!stripPolicies && securityRules.length > 0) {
|
|
426
|
-
schemaContent += "\n}, (table) => ([\n";
|
|
427
|
-
const resolveCollection = (slug) => collections.find((c) => c.slug === slug || getTableName(c) === slug);
|
|
428
|
-
securityRules.forEach((rule, idx) => {
|
|
429
|
-
schemaContent += generatePolicyCode(collection, rule, idx, resolveCollection);
|
|
430
|
-
});
|
|
431
|
-
schemaContent += "])).enableRLS();\n\n";
|
|
432
|
-
} else schemaContent += "\n}).enableRLS();\n\n";
|
|
433
|
-
}
|
|
434
|
-
if (!exportedTableVars.includes(tableVarName)) exportedTableVars.push(tableVarName);
|
|
435
|
-
}
|
|
436
|
-
for (const [tableName, { collection, isJunction }] of allTablesToGenerate.entries()) {
|
|
437
|
-
const tableVarName = getTableVarName(tableName);
|
|
438
|
-
const tableRelations = [];
|
|
439
|
-
if (isJunction) {
|
|
440
|
-
const relationInfo = Array.from(allTablesToGenerate.values()).find((v) => v.isJunction && getTableName(v.collection) === tableName);
|
|
441
|
-
if (relationInfo && relationInfo.relation && relationInfo.sourceCollection && isManyToMany(relationInfo.relation)) {
|
|
442
|
-
const { relation, sourceCollection } = relationInfo;
|
|
443
|
-
const targetCollection = relation.target();
|
|
444
|
-
const sourceTableVar = getTableVarName(getTableName(sourceCollection));
|
|
445
|
-
const targetTableVar = getTableVarName(getTableName(targetCollection));
|
|
446
|
-
const sourceId = getPrimaryKeyName(sourceCollection);
|
|
447
|
-
const targetId = getPrimaryKeyName(targetCollection);
|
|
448
|
-
if (!relation?.through) throw new Error("Internal, the relation should have a through property. Relations passed to this script should sanitized first with sanitizeRelation().");
|
|
449
|
-
const owningRelationName = relation.relationName ?? toSnakeCase(getTableName(targetCollection));
|
|
450
|
-
let inverseRelationName = null;
|
|
451
|
-
try {
|
|
452
|
-
const targetRelations = resolveCollectionRelations(targetCollection);
|
|
453
|
-
for (const [, targetRel] of Object.entries(targetRelations)) if (targetRel.kind !== "belongsTo" && targetRel.cardinality === "many" && targetRel.relationName === owningRelationName) {
|
|
454
|
-
inverseRelationName = targetRel.relationName ?? null;
|
|
455
|
-
break;
|
|
456
|
-
}
|
|
457
|
-
} catch {}
|
|
458
|
-
tableRelations.push(` ${quote(relation.through.sourceColumn)}: one(${sourceTableVar}, {\n fields: [${member(tableVarName, relation.through.sourceColumn)}],\n references: [${member(sourceTableVar, sourceId)}],\n relationName: ${quote(owningRelationName)}\n })`);
|
|
459
|
-
const targetRelationName = inverseRelationName ? inverseRelationName : `${tableName}_${relation.through.targetColumn}`;
|
|
460
|
-
tableRelations.push(` ${quote(relation.through.targetColumn)}: one(${targetTableVar}, {\n fields: [${member(tableVarName, relation.through.targetColumn)}],\n references: [${member(targetTableVar, targetId)}],\n relationName: ${quote(targetRelationName)}\n })`);
|
|
461
|
-
}
|
|
462
|
-
} else {
|
|
463
|
-
const resolvedRelations = resolveCollectionRelations(collection);
|
|
464
|
-
const emittedRelationNames = /* @__PURE__ */ new Set();
|
|
465
|
-
for (const [relationKey, rel] of Object.entries(resolvedRelations)) try {
|
|
466
|
-
const target = rel.target();
|
|
467
|
-
const targetTableVar = getTableVarName(getTableName(target));
|
|
468
|
-
const drizzleRelationName = computeSharedRelationName(rel, collection, collections);
|
|
469
|
-
const deduplicationKey = `${drizzleRelationName}::${rel.kind}`;
|
|
470
|
-
if (emittedRelationNames.has(deduplicationKey)) continue;
|
|
471
|
-
emittedRelationNames.add(deduplicationKey);
|
|
472
|
-
switch (rel.kind) {
|
|
473
|
-
case "belongsTo": {
|
|
474
|
-
const localFieldKey = resolvePropertyKeyForColumn(collection, rel.localKey);
|
|
475
|
-
tableRelations.push(` ${quote(relationKey)}: one(${targetTableVar}, {\n fields: [${member(tableVarName, localFieldKey)}],\n references: [${member(targetTableVar, getPrimaryKeyName(target))}],\n relationName: ${quote(drizzleRelationName)}\n })`);
|
|
476
|
-
break;
|
|
477
|
-
}
|
|
478
|
-
case "hasOne":
|
|
479
|
-
tableRelations.push(` ${quote(relationKey)}: one(${targetTableVar}, {\n relationName: ${quote(drizzleRelationName)}\n })`);
|
|
480
|
-
break;
|
|
481
|
-
case "hasMany":
|
|
482
|
-
tableRelations.push(` ${quote(relationKey)}: many(${targetTableVar}, { relationName: ${quote(drizzleRelationName)} })`);
|
|
483
|
-
break;
|
|
484
|
-
case "manyToMany": {
|
|
485
|
-
const junctionTableVar = getTableVarName(rel.through.table);
|
|
486
|
-
tableRelations.push(` ${quote(relationKey)}: many(${junctionTableVar}, { relationName: ${quote(drizzleRelationName)} })`);
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
|
-
case "via": break;
|
|
490
|
-
}
|
|
491
|
-
} catch (e) {
|
|
492
|
-
logger.warn(`Could not generate relation ${relationKey} for ${collection.name}`, { error: e });
|
|
493
|
-
}
|
|
494
|
-
for (const otherCollection of collections) {
|
|
495
|
-
if (otherCollection.slug === collection.slug) continue;
|
|
496
|
-
const otherRelations = resolveCollectionRelations(otherCollection);
|
|
497
|
-
for (const [otherKey, otherRel] of Object.entries(otherRelations)) if (hasForeignKeyOnTarget(otherRel)) try {
|
|
498
|
-
if (otherRel.target().slug === collection.slug) {
|
|
499
|
-
const drizzleRelationName = computeSharedRelationName(otherRel, otherCollection, collections);
|
|
500
|
-
const deduplicationKey = `${drizzleRelationName}::belongsTo`;
|
|
501
|
-
if (!emittedRelationNames.has(deduplicationKey)) {
|
|
502
|
-
const otherTableVar = getTableVarName(getTableName(otherCollection));
|
|
503
|
-
const drizzleFieldKey = resolvePropertyKeyForColumn(collection, otherRel.foreignKeyOnTarget);
|
|
504
|
-
const referencedKey = otherRel.sourceKey ? resolvePropertyKeyForColumn(otherCollection, otherRel.sourceKey) : getPrimaryKeyName(otherCollection);
|
|
505
|
-
const synthKey = `_synth_${otherTableVar}_${drizzleFieldKey}`;
|
|
506
|
-
tableRelations.push(` ${quote(synthKey)}: one(${otherTableVar}, {\n fields: [${member(tableVarName, drizzleFieldKey)}],\n references: [${member(otherTableVar, referencedKey)}],\n relationName: ${quote(drizzleRelationName)}\n })`);
|
|
507
|
-
emittedRelationNames.add(deduplicationKey);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
} catch (e) {}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
if (tableRelations.length > 0) {
|
|
514
|
-
const relVarName = `${tableVarName}Relations`;
|
|
515
|
-
schemaContent += `export const ${relVarName} = drizzleRelations(${tableVarName}, ({ one, many }) => ({\n${tableRelations.join(",\n")}\n}));\n\n`;
|
|
516
|
-
if (!exportedRelationVars.includes(relVarName)) exportedRelationVars.push(relVarName);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
const tablesExport = `export const tables = { ${exportedTableVars.join(", ")} };\n`;
|
|
520
|
-
const enumsExport = `export const enums = { ${exportedEnumVars.join(", ")} };\n`;
|
|
521
|
-
const relationsExport = `export const relations = { ${exportedRelationVars.join(", ")} };\n\n`;
|
|
522
|
-
schemaContent += tablesExport + enumsExport + relationsExport;
|
|
523
|
-
return schemaContent;
|
|
524
|
-
};
|
|
525
|
-
//#endregion
|
|
526
|
-
export { getDrizzleColumn as n, generateSchema as t };
|
|
527
|
-
|
|
528
|
-
//# sourceMappingURL=generate-drizzle-schema-logic-so2Z_lyC.js.map
|