@rebasepro/server-postgres 0.13.0 → 0.13.1-canary.gcd6689e

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/index.es.js CHANGED
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
2
2
  import process from "process";
3
3
  __createRequire(import.meta.url);
4
4
  import { a as guardPoolAgainstDirtyRelease, i as createReadReplicaConnection, n as createDirectDatabaseConnection, o as pinSearchPath, r as createPostgresDatabaseConnection } from "./connection-BuZ97wsr.js";
5
- import { A as toSnakeCase, C as normalizeToEntityRelation, D as getPolicyNamesForRule, F as Vector, N as hasForeignKeyOnTarget, O as mergeDeep, P as isManyToMany, S as createRelationRefWithData, T as generateForeignKeyName, _ as buildCompositeId, a as getJunctionSecurityRules, b as parseIdValues, c as policyToPostgres, d as findRelation, f as getColumnName, g as resolveCollectionRelations, h as getTableVarName, i as getJunctionCollectionConfig, k as camelCase, l as securityRuleToConditions, m as getTableName$1, n as CollectionRegistry, o as resolveJunctionSpecs, p as getEnumVarName, r as resolveStringColumnLength, s as getEffectiveSecurityRules, t as buildSdkData, u as findAnonymousGrants, v as getDeclaredPrimaryKeys, w as updateDateAutoValues, x as createRelationRef, y as isAddressableId } from "./src-DlPBctw_.js";
5
+ import { A as toSnakeCase, C as normalizeToEntityRelation, D as getPolicyNamesForRule, E as legacyForeignKeyName, F as Vector, N as hasForeignKeyOnTarget, O as mergeDeep, P as isManyToMany, S as createRelationRefWithData, T as generateForeignKeyName, _ as buildCompositeId, a as getJunctionSecurityRules, b as parseIdValues, c as policyToPostgres, d as findRelation, f as getColumnName, g as resolveCollectionRelations, h as getTableVarName, i as getJunctionCollectionConfig, k as camelCase, l as securityRuleToConditions, m as getTableName$1, n as CollectionRegistry, o as resolveJunctionSpecs, p as getEnumVarName, r as resolveStringColumnLength, s as getEffectiveSecurityRules, t as buildSdkData, u as findAnonymousGrants, v as getDeclaredPrimaryKeys, w as updateDateAutoValues, x as createRelationRef, y as isAddressableId } from "./src-DlPBctw_.js";
6
6
  import { n as isPostgresCollectionConfig, r as isRelationalCollectionConfig } from "./src-DoU9yPqq.js";
7
7
  import { t as ANONYMOUS_USER_ID } from "./policy-CeA1JcxP.js";
8
8
  import { t as createPostgresWebSocket } from "./websocket-B2LsrINK.js";
@@ -3796,51 +3796,6 @@ var FetchService = class {
3796
3796
  return !!this.getQueryBuilder(tableName);
3797
3797
  }
3798
3798
  /**
3799
- * Attempt to use Drizzle's relational query API (db.query.<table>.findMany)
3800
- * for efficient JOIN-based relation loading.
3801
- * Returns null if the API is not available or the query fails.
3802
- * Note: Primary path now uses `buildWithConfig` + `buildDrizzleQueryOptions`.
3803
- */
3804
- async fetchWithDrizzleQuery(collectionPath, collection, options, include, idInfo, idInfoArray) {
3805
- try {
3806
- const table = getTableForCollection(collection, this.registry);
3807
- const tableName = getTableName(table);
3808
- const queryTarget = this.getQueryBuilder(tableName);
3809
- if (!queryTarget?.findMany) return null;
3810
- const resolvedRelations = resolveCollectionRelations(collection);
3811
- const withConfig = {};
3812
- for (const [key, relation] of Object.entries(resolvedRelations)) if (include[0] === "*" || include.includes(key)) {
3813
- const drizzleRelName = relation.relationName || key;
3814
- withConfig[drizzleRelName] = true;
3815
- }
3816
- const queryOpts = { with: withConfig };
3817
- if (options.limit) queryOpts.limit = options.limit;
3818
- if (options.filter) {
3819
- const filterConditions = this.buildFilterConditions(options.filter, table, collectionPath);
3820
- if (filterConditions.length > 0) queryOpts.where = and(...filterConditions);
3821
- }
3822
- if (options.orderBy) {
3823
- const orderByField = this.resolveOrderByField(table, options.orderBy, collection);
3824
- if (orderByField) queryOpts.orderBy = options.order === "asc" ? asc(orderByField) : desc(orderByField);
3825
- }
3826
- return (await queryTarget.findMany(queryOpts)).map((row) => {
3827
- const flat = {};
3828
- for (const [k, v] of Object.entries(row)) if (Array.isArray(v)) flat[k] = v.map((item) => {
3829
- const keys = Object.keys(item);
3830
- const nestedObj = keys.find((nk) => typeof item[nk] === "object" && item[nk] !== null && !Array.isArray(item[nk]));
3831
- if (nestedObj && keys.length <= 3) return { ...item[nestedObj] };
3832
- return { ...item };
3833
- });
3834
- else if (typeof v === "object" && v !== null) flat[k] = { ...v };
3835
- else flat[k] = v;
3836
- return flat;
3837
- });
3838
- } catch (e) {
3839
- logger.warn(`[include] Drizzle relational query failed for '${collectionPath}', falling back`, { error: e });
3840
- return null;
3841
- }
3842
- }
3843
- /**
3844
3799
  * Fallback path used when db.query is unavailable.
3845
3800
  * The primary path uses db.query.findMany with `with` config, which
3846
3801
  * loads all relations in a single query.
@@ -9203,6 +9158,54 @@ var quote = (xs) => Array.from(xs).map((s) => `\`${s}\``).join(", ");
9203
9158
  /** `on.from` / `on.to` accept a single column or a composite tuple. */
9204
9159
  var asColumns = (value) => Array.isArray(value) ? value : [value];
9205
9160
  /**
9161
+ * Distinguish "this column name is wrong" from "the generated schema is old".
9162
+ *
9163
+ * They present identically here — a relation asks for a column the registered
9164
+ * table does not have — but they are opposite problems with opposite fixes, and
9165
+ * getting them the wrong way round is how the 0.12 → 0.13 upgrade bricked
9166
+ * projects.
9167
+ *
9168
+ * The registered table is not the database. It comes from the project's
9169
+ * checked-in `backend/src/schema.generated.ts`, and 0.13 changed the rule that
9170
+ * derives foreign-key names: `categories` yields `category_id` where it used to
9171
+ * yield `categorie_id`. Boot-ensure renames the database column to match, so by
9172
+ * the time this runs the *database* is correct and the *generated module* is the
9173
+ * stale one. Reporting "not a column" then points at the wrong artifact, and the
9174
+ * generic fix — "set `through.targetColumn` to one of: …", listing the legacy
9175
+ * name because that is what the stale module still has — talks the reader into
9176
+ * pinning a column that no longer exists.
9177
+ *
9178
+ * So when the wanted name is what the current rule derives, and the table
9179
+ * carries what the *previous* rule would have derived from the same source, say
9180
+ * that instead.
9181
+ *
9182
+ * @param wanted the column the relation asks for
9183
+ * @param available every column the registered table has
9184
+ * @param sources names the default could have been derived from (a slug, a
9185
+ * relation name) — checking against these rather than guessing
9186
+ * backwards from `wanted` keeps the match exact
9187
+ */
9188
+ function staleCodegenRename(wanted, available, sources) {
9189
+ for (const source of sources) {
9190
+ if (!source) continue;
9191
+ const current = generateForeignKeyName(source);
9192
+ const legacy = legacyForeignKeyName(source);
9193
+ if (current !== wanted || legacy === current) continue;
9194
+ if (available.has(legacy) && !available.has(current)) return {
9195
+ legacy,
9196
+ current
9197
+ };
9198
+ }
9199
+ return null;
9200
+ }
9201
+ /** The shared explanation, so every relation kind reports it identically. */
9202
+ function staleCodegenDefect(table, { legacy, current }) {
9203
+ return {
9204
+ problem: `the generated Drizzle schema still declares \`${legacy}\` on \`${table}\`, but this release derives \`${current}\` — the generated schema predates the foreign-key naming fix and no longer describes the database`,
9205
+ fix: `regenerate it with \`rebase schema generate\` (or \`pnpm run schema:generate\`). The database column has already been renamed for you at boot, so nothing else is needed. To keep \`${legacy}\` instead, name it explicitly on the relation and regenerate.`
9206
+ };
9207
+ }
9208
+ /**
9206
9209
  * Relations whose names do not resolve against the registered schema.
9207
9210
  *
9208
9211
  * Fails open wherever it cannot see enough to be sure — an unregistered source
@@ -9249,19 +9252,31 @@ function findRelationDefects(collections, registry) {
9249
9252
  const targetColumns = columnNames(targetTable);
9250
9253
  switch (relation.kind) {
9251
9254
  case "belongsTo":
9252
- if (!sourceColumns.has(relation.localKey)) defects.push({
9253
- ...at,
9254
- problem: `\`localKey: "${relation.localKey}"\` is not a column on \`${sourceTableName}\``,
9255
- fix: `add the column, or set \`localKey\` to one of: ${quote(sourceColumns)}`
9256
- });
9255
+ if (!sourceColumns.has(relation.localKey)) {
9256
+ const stale = staleCodegenRename(relation.localKey, sourceColumns, [relation.relationName, targetCollection.slug]);
9257
+ defects.push(stale ? {
9258
+ ...at,
9259
+ ...staleCodegenDefect(sourceTableName, stale)
9260
+ } : {
9261
+ ...at,
9262
+ problem: `\`localKey: "${relation.localKey}"\` is not a column on \`${sourceTableName}\``,
9263
+ fix: `add the column, or set \`localKey\` to one of: ${quote(sourceColumns)}`
9264
+ });
9265
+ }
9257
9266
  break;
9258
9267
  case "hasOne":
9259
9268
  case "hasMany":
9260
- if (!targetColumns.has(relation.foreignKeyOnTarget)) defects.push({
9261
- ...at,
9262
- problem: `\`foreignKeyOnTarget: "${relation.foreignKeyOnTarget}"\` is not a column on the target table \`${targetTableName}\``,
9263
- fix: `add the column, or set \`foreignKeyOnTarget\` to one of: ${quote(targetColumns)}`
9264
- });
9269
+ if (!targetColumns.has(relation.foreignKeyOnTarget)) {
9270
+ const stale = staleCodegenRename(relation.foreignKeyOnTarget, targetColumns, [collection.slug]);
9271
+ defects.push(stale ? {
9272
+ ...at,
9273
+ ...staleCodegenDefect(targetTableName, stale)
9274
+ } : {
9275
+ ...at,
9276
+ problem: `\`foreignKeyOnTarget: "${relation.foreignKeyOnTarget}"\` is not a column on the target table \`${targetTableName}\``,
9277
+ fix: `add the column, or set \`foreignKeyOnTarget\` to one of: ${quote(targetColumns)}`
9278
+ });
9279
+ }
9265
9280
  if (relation.sourceKey && !sourceColumns.has(relation.sourceKey)) defects.push({
9266
9281
  ...at,
9267
9282
  problem: `\`sourceKey: "${relation.sourceKey}"\` is not a column on \`${sourceTableName}\``,
@@ -9280,11 +9295,21 @@ function findRelationDefects(collections, registry) {
9280
9295
  break;
9281
9296
  }
9282
9297
  const junctionColumns = columnNames(junction);
9283
- for (const [label, column] of [["sourceColumn", sourceColumn], ["targetColumn", targetColumn]]) if (!junctionColumns.has(column)) defects.push({
9284
- ...at,
9285
- problem: `\`through.${label}: "${column}"\` is not a column on the junction table \`${table}\``,
9286
- fix: `set \`through.${label}\` to one of: ${quote(junctionColumns)}` + (label === "sourceColumn" ? " — it is the column naming *this* collection" : "")
9287
- });
9298
+ const derivedFrom = {
9299
+ sourceColumn: [collection.slug],
9300
+ targetColumn: [targetCollection.slug]
9301
+ };
9302
+ for (const [label, column] of [["sourceColumn", sourceColumn], ["targetColumn", targetColumn]]) if (!junctionColumns.has(column)) {
9303
+ const stale = staleCodegenRename(column, junctionColumns, [...derivedFrom[label]]);
9304
+ defects.push(stale ? {
9305
+ ...at,
9306
+ ...staleCodegenDefect(table, stale)
9307
+ } : {
9308
+ ...at,
9309
+ problem: `\`through.${label}: "${column}"\` is not a column on the junction table \`${table}\``,
9310
+ fix: `set \`through.${label}\` to one of: ${quote(junctionColumns)}` + (label === "sourceColumn" ? " — it is the column naming *this* collection" : "")
9311
+ });
9312
+ }
9288
9313
  break;
9289
9314
  }
9290
9315
  case "via": {