@rebasepro/server-postgresql 0.6.0 → 0.6.1

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
@@ -4,8 +4,8 @@ const require = __createRequire(import.meta.url);
4
4
  import { Client, Pool } from "pg";
5
5
  import { drizzle } from "drizzle-orm/node-postgres";
6
6
  import { createEmailService, extractUserFromToken, logger } from "@rebasepro/server-core";
7
- import { and, asc, count, desc, eq, getTableName, gt, ilike, inArray, isTable, lt, or, relations, sql } from "drizzle-orm";
8
- import { PgChar, PgText, PgVarchar, boolean, getTableConfig, jsonb, pgSchema, pgTable, text, timestamp, unique, uuid, varchar } from "drizzle-orm/pg-core";
7
+ import { and, asc, count, desc, eq, getTableColumns, getTableName, gt, ilike, inArray, isTable, lt, or, relations, sql } from "drizzle-orm";
8
+ import { PgArray, PgChar, PgTable, PgText, PgVarchar, boolean, getTableConfig, jsonb, pgSchema, pgTable, text, timestamp, unique, uuid, varchar } from "drizzle-orm/pg-core";
9
9
  import { createHash, randomUUID } from "crypto";
10
10
  import * as fs from "fs";
11
11
  import { promises } from "fs";
@@ -3720,8 +3720,10 @@ function serializePropertyToServer(value, property) {
3720
3720
  };
3721
3721
  });
3722
3722
  }
3723
+ return value;
3723
3724
  }
3724
- return value;
3725
+ logger.warn(`Expected array value for array property, got ${typeof value}. Coercing to empty array.`);
3726
+ return [];
3725
3727
  case "map":
3726
3728
  if (typeof value === "object" && property.properties) {
3727
3729
  const result = {};
@@ -3943,6 +3945,9 @@ function parsePropertyFromServer(value, property, collection, propertyKey) {
3943
3945
  };
3944
3946
  });
3945
3947
  }
3948
+ } else {
3949
+ logger.warn(`Expected array value from DB for array property, got ${typeof value}. Coercing to array.`);
3950
+ return typeof value === "string" ? [value] : [];
3946
3951
  }
3947
3952
  return value;
3948
3953
  case "map":
@@ -5929,12 +5934,12 @@ var EntityPersistService = class {
5929
5934
  }
5930
5935
  }
5931
5936
  }
5932
- const serializedResult = serializeDataToServer(otherValues, collection.properties, collection, this.registry);
5933
- const inverseRelationUpdates = serializedResult.inverseRelationUpdates;
5934
- const joinPathRelationUpdates = serializedResult.joinPathRelationUpdates;
5935
- const entityData = sanitizeAndConvertDates(serializedResult.scalarData);
5936
5937
  let savedId;
5937
5938
  try {
5939
+ const serializedResult = serializeDataToServer(otherValues, collection.properties, collection, this.registry);
5940
+ const inverseRelationUpdates = serializedResult.inverseRelationUpdates;
5941
+ const joinPathRelationUpdates = serializedResult.joinPathRelationUpdates;
5942
+ const entityData = sanitizeAndConvertDates(serializedResult.scalarData);
5938
5943
  savedId = await this.db.transaction(async (tx) => {
5939
5944
  let currentId;
5940
5945
  if (entityId) {
@@ -10552,6 +10557,39 @@ async function ensureHistoryTableExists(db) {
10552
10557
  }
10553
10558
  }
10554
10559
  //#endregion
10560
+ //#region src/utils/pg-array-null-patch.ts
10561
+ /**
10562
+ * Patches all PgArray columns on the given tables to handle NULL values safely.
10563
+ *
10564
+ * Drizzle ORM's `PgArray.mapFromDriverValue` calls `value.map(...)` without
10565
+ * guarding against `null`. When a PostgreSQL native array column (`text[]`,
10566
+ * `integer[]`, etc.) contains NULL, the pg driver returns `null` in JavaScript,
10567
+ * and `null.map(...)` throws `TypeError: value.map is not a function`.
10568
+ *
10569
+ * This function walks every column of every registered table and, for any
10570
+ * `PgArray` column, wraps its `mapFromDriverValue` to return `null` when the
10571
+ * database value is nullish.
10572
+ *
10573
+ * This is a workaround for a known Drizzle ORM issue. Should be removed once
10574
+ * Drizzle handles nullable arrays natively.
10575
+ */
10576
+ function patchPgArrayNullSafety(tables) {
10577
+ let patchedCount = 0;
10578
+ for (const tableOrRelation of Object.values(tables)) {
10579
+ if (!(tableOrRelation instanceof PgTable)) continue;
10580
+ const columns = getTableColumns(tableOrRelation);
10581
+ for (const column of Object.values(columns)) if (column instanceof PgArray) {
10582
+ const original = column.mapFromDriverValue.bind(column);
10583
+ column.mapFromDriverValue = function(value) {
10584
+ if (value == null) return null;
10585
+ return original(value);
10586
+ };
10587
+ patchedCount++;
10588
+ }
10589
+ }
10590
+ if (patchedCount > 0) logger.debug(`[PgArray] Patched ${patchedCount} array column(s) for null-safety`);
10591
+ }
10592
+ //#endregion
10555
10593
  //#region src/PostgresBootstrapper.ts
10556
10594
  /**
10557
10595
  * PostgresBootstrapper
@@ -10587,6 +10625,7 @@ function createPostgresBootstrapper(pgConfig) {
10587
10625
  });
10588
10626
  if (pgConfig.schema?.enums) registry.registerEnums(pgConfig.schema.enums);
10589
10627
  if (pgConfig.schema?.relations) registry.registerRelations(pgConfig.schema.relations);
10628
+ if (pgConfig.schema?.tables) patchPgArrayNullSafety(pgConfig.schema.tables);
10590
10629
  const mergedSchema = {
10591
10630
  ...pgConfig.schema?.tables,
10592
10631
  ...pgConfig.schema?.relations || {}