@m1212e/rumble 0.20.0 → 0.21.3

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/out/index.cjs CHANGED
@@ -208,7 +208,7 @@ function mapNullFieldsToUndefined(obj) {
208
208
  }
209
209
  //#endregion
210
210
  //#region package.json
211
- var version = "0.20.0";
211
+ var version = "0.21.3";
212
212
  //#endregion
213
213
  //#region lib/helpers/mergeFilters.ts
214
214
  function mergeFilters(filterA, filterB, mode = "AND") {
@@ -328,31 +328,70 @@ function createDistinctValuesFromSQLType(sqlType) {
328
328
  }
329
329
  //#endregion
330
330
  //#region lib/helpers/tableHelpers.ts
331
- const drizzleNameSymbol = Symbol.for("drizzle:Name");
332
- const drizzleOriginalNameSymbol = Symbol.for("drizzle:OriginalName");
333
- const drizzleBaseNameSymbol = Symbol.for("drizzle:BaseName");
334
- const drizzleColumnsSymbol = Symbol.for("drizzle:Columns");
331
+ const indexCache = /* @__PURE__ */ new WeakMap();
332
+ function buildIndex(db) {
333
+ const byTsName = /* @__PURE__ */ new Map();
334
+ const byDbName = /* @__PURE__ */ new Map();
335
+ const byTableRef = /* @__PURE__ */ new Map();
336
+ for (const [tsName, rawEntry] of Object.entries(db._.relations ?? {})) {
337
+ const entry = rawEntry;
338
+ const tableObj = entry.table;
339
+ if (!tableObj) continue;
340
+ const columns = (0, drizzle_orm.isTable)(tableObj) ? (0, drizzle_orm.getTableColumns)(tableObj) : {};
341
+ const primaryKey = Object.fromEntries(Object.entries(columns).filter(([, col]) => col.primary));
342
+ const dbName = (0, drizzle_orm.isTable)(tableObj) ? (0, drizzle_orm.getTableName)(tableObj) : entry.name ?? tsName;
343
+ const resolved = {
344
+ name: entry.name ?? tsName,
345
+ dbName,
346
+ table: tableObj,
347
+ columns,
348
+ primaryKey,
349
+ relations: entry.relations ?? {},
350
+ foundRelation: entry
351
+ };
352
+ byTsName.set(resolved.name, resolved);
353
+ byDbName.set(resolved.dbName, resolved);
354
+ byTableRef.set(tableObj, resolved);
355
+ }
356
+ return {
357
+ byTsName,
358
+ byDbName,
359
+ byTableRef
360
+ };
361
+ }
362
+ function getIndex(db) {
363
+ let idx = indexCache.get(db);
364
+ if (!idx) {
365
+ idx = buildIndex(db);
366
+ indexCache.set(db, idx);
367
+ }
368
+ return idx;
369
+ }
335
370
  function tableHelper({ db, table }) {
336
- let tableName;
337
- if (typeof table !== "string") {
371
+ const idx = getIndex(db);
372
+ let entry;
373
+ if (typeof table === "string") entry = idx.byTsName.get(table) ?? idx.byDbName.get(table);
374
+ else if (table && typeof table === "object") {
338
375
  const t = table;
339
- tableName = t.name ?? t[drizzleNameSymbol] ?? t[drizzleOriginalNameSymbol] ?? t[drizzleBaseNameSymbol];
340
- } else tableName = table;
341
- const foundRelation = Object.values(db._.relations).find((entry) => entry.name === tableName || entry.table[drizzleNameSymbol] === tableName || entry.table[drizzleOriginalNameSymbol] === tableName || entry.table[drizzleBaseNameSymbol] === tableName);
342
- if (!foundRelation) throw new RumbleError(`Could not find schema for ${JSON.stringify(tableName)}`);
343
- const tableObj = foundRelation.table;
344
- const columns = tableObj[drizzleColumnsSymbol] ?? {};
345
- const primaryKey = Object.fromEntries(Object.entries(columns).filter(([_, col]) => col.primary));
346
- const dbName = tableObj[drizzleOriginalNameSymbol] ?? tableObj[drizzleBaseNameSymbol] ?? tableObj[drizzleNameSymbol] ?? foundRelation.name;
347
- const tsName = foundRelation.name;
376
+ if (t.table) {
377
+ entry = idx.byTableRef.get(t.table);
378
+ if (!entry && t.name) entry = idx.byTsName.get(t.name) ?? idx.byDbName.get(t.name);
379
+ }
380
+ if (!entry) entry = idx.byTableRef.get(t);
381
+ if (!entry && (0, drizzle_orm.isTable)(t)) {
382
+ const dbName = (0, drizzle_orm.getTableName)(t);
383
+ entry = idx.byDbName.get(dbName);
384
+ }
385
+ }
386
+ if (!entry) throw new RumbleError(`Could not find schema for ${JSON.stringify(typeof table === "string" ? table : "<table-object>")}`);
348
387
  return {
349
- columns,
350
- primaryKey,
351
- relations: foundRelation.relations,
352
- dbName,
353
- tsName,
354
- table: tableObj,
355
- foundRelation
388
+ columns: entry.columns,
389
+ primaryKey: entry.primaryKey,
390
+ relations: entry.relations,
391
+ dbName: entry.dbName,
392
+ tsName: entry.name,
393
+ table: entry.table,
394
+ foundRelation: entry.foundRelation
356
395
  };
357
396
  }
358
397
  //#endregion
@@ -706,9 +745,10 @@ const createOrderArgImplementer = ({ db, schemaBuilder }) => {
706
745
  return acc;
707
746
  }, {});
708
747
  const relations = Object.entries(tableSchema.relations ?? {}).reduce((acc, [key, value]) => {
748
+ const targetTsName = value.targetTableName;
709
749
  const referenceModel = orderArgImplementer({ dbName: tableHelper({
710
750
  db,
711
- table: value.targetTable
751
+ table: targetTsName
712
752
  }).dbName });
713
753
  acc[key] = t.field({
714
754
  type: referenceModel,
@@ -731,21 +771,36 @@ const createOrderArgImplementer = ({ db, schemaBuilder }) => {
731
771
  //#endregion
732
772
  //#region lib/enum.ts
733
773
  /**
734
- * Checks if a column is a PgEnumColumn
774
+ * Checks if a column is a Postgres enum column
735
775
  */
736
776
  function isEnumSchema(schemaType) {
737
- return schemaType instanceof drizzle_orm_pg_core.PgEnumColumn;
777
+ return (0, drizzle_orm.is)(schemaType, drizzle_orm_pg_core.PgEnumColumn) || (0, drizzle_orm.is)(schemaType, drizzle_orm_pg_core.PgEnumObjectColumn);
738
778
  }
739
- const createEnumImplementer = ({ schemaBuilder }) => {
779
+ const createEnumImplementer = ({ schema, schemaBuilder }) => {
740
780
  const referenceStorage = /* @__PURE__ */ new Map();
741
781
  /**
742
782
  * Registers a Postgres enum as a GraphQL enum type.
743
783
  *
744
- * Pass the `enum` option with the pgEnum object (e.g. `moodEnum`),
745
- * or pass the `enumColumn` option with a column that uses the enum.
784
+ * You can identify the enum in three ways:
785
+ * - `tsName`: the exported TypeScript identifier from your schema module. This is the
786
+ * most typesafe form, only valid enum keys autocomplete, typos are caught at compile time.
787
+ * - `enum`: pass the pgEnum object directly.
788
+ * - `enumColumn`: pass a column that uses the enum.
789
+ *
746
790
  * Use `refName` to override the auto-generated GraphQL type name.
747
791
  */
748
- const enumImplementer = ({ enum: enumObject, enumColumn, refName }) => {
792
+ const enumImplementer = (args) => {
793
+ const { refName } = args;
794
+ const tsName = args.tsName;
795
+ const enumObjectArg = args.enum;
796
+ const enumColumn = args.enumColumn;
797
+ let enumObject = enumObjectArg;
798
+ if (tsName) {
799
+ const candidate = schema[tsName];
800
+ if (!candidate || !(0, drizzle_orm_pg_core.isPgEnum)(candidate)) throw new RumbleError(`Could not find a pgEnum exported as ${JSON.stringify(tsName)} in the provided schema. Make sure the identifier exists and refers to a value created with \`pgEnum(...)\`.`);
801
+ enumObject = candidate;
802
+ }
803
+ if (!enumObject && !enumColumn) throw new RumbleError("Could not determine enum structure! Pass one of 'tsName' (requires `schema` on rumble()), 'enum' (the pgEnum object), or 'enumColumn' (a column that uses the enum).");
749
804
  let enumSchemaName;
750
805
  let enumValues;
751
806
  if (enumObject) {
@@ -759,10 +814,9 @@ const createEnumImplementer = ({ schemaBuilder }) => {
759
814
  }
760
815
  if (!enumSchemaName || !enumValues) throw new RumbleError("Could not determine enum structure!");
761
816
  const graphqlImplementationName = refName ?? `${(0, es_toolkit.capitalize)((0, drizzle_orm_casing.toCamelCase)(enumSchemaName))}Enum`;
762
- let ret = referenceStorage.get(graphqlImplementationName);
763
- if (ret) return ret;
764
- const implement = () => schemaBuilder.enumType(graphqlImplementationName, { values: enumValues });
765
- ret = implement();
817
+ const cached = referenceStorage.get(graphqlImplementationName);
818
+ if (cached) return cached;
819
+ const ret = schemaBuilder.enumType(graphqlImplementationName, { values: enumValues });
766
820
  referenceStorage.set(graphqlImplementationName, ret);
767
821
  return ret;
768
822
  };
@@ -830,9 +884,10 @@ const createWhereArgImplementer = ({ db, schemaBuilder, enumImplementer }) => {
830
884
  return acc;
831
885
  }, {});
832
886
  const relations = Object.entries(tableSchema.relations ?? {}).reduce((acc, [key, value]) => {
887
+ const targetTsName = value.targetTableName;
833
888
  const referenceModel = whereArgImplementer({ dbName: tableHelper({
834
889
  db,
835
- table: value.targetTable
890
+ table: targetTsName
836
891
  }).dbName });
837
892
  acc[key] = t.field({
838
893
  type: referenceModel,
@@ -927,7 +982,7 @@ const createCountQueryImplementer = ({ db, schemaBuilder, whereArgImplementer, m
927
982
  type: WhereArg,
928
983
  required: false
929
984
  }) },
930
- resolve: async (root, args, ctx, info) => {
985
+ resolve: async (_root, args, ctx, _info) => {
931
986
  if (isAllowed && !await isAllowed(ctx)) throw new RumbleErrorSafe("Not allowed to perform this action");
932
987
  deepSetProto(args);
933
988
  return db.select({ count: (0, drizzle_orm.count)() }).from(tableSchema.table).where(ctx.abilities[table].filter(listAction).merge(mapNullFieldsToUndefined(args)).sql.where).then(assertFirstEntryExists).then((r) => r.count);
@@ -1054,16 +1109,23 @@ function buildPothosResponseTypeFromGraphQLType({ builder, sqlType, fieldName, n
1054
1109
  }
1055
1110
  //#endregion
1056
1111
  //#region lib/helpers/determineDialectFromSchema.ts
1112
+ const dialectCache = /* @__PURE__ */ new WeakMap();
1057
1113
  function determineDBDialectFromSchema(schema) {
1114
+ const cached = dialectCache.get(schema);
1115
+ if (cached) return cached;
1058
1116
  const found = /* @__PURE__ */ new Set();
1059
1117
  for (const table of Object.values(schema).map((t) => t.table)) {
1060
- if (typeof table !== "object") continue;
1061
- if (table instanceof drizzle_orm_pg_core.PgTable) found.add("postgres");
1062
- else if (table instanceof drizzle_orm_mysql_core.MySqlTable) found.add("mysql");
1063
- else if (table instanceof drizzle_orm_sqlite_core.SQLiteTable) found.add("sqlite");
1118
+ if (!table || typeof table !== "object") continue;
1119
+ if ((0, drizzle_orm.is)(table, drizzle_orm_pg_core.PgTable)) found.add("postgres");
1120
+ else if ((0, drizzle_orm.is)(table, drizzle_orm_mysql_core.MySqlTable)) found.add("mysql");
1121
+ else if ((0, drizzle_orm.is)(table, drizzle_orm_sqlite_core.SQLiteTable)) found.add("sqlite");
1064
1122
  }
1065
1123
  const dialects = Array.from(found);
1066
- if (dialects.length === 1) return dialects[0];
1124
+ if (dialects.length === 1) {
1125
+ const only = dialects[0];
1126
+ dialectCache.set(schema, only);
1127
+ return only;
1128
+ }
1067
1129
  if (dialects.length === 0) throw new Error("No tables found in schema, could not determine dialect");
1068
1130
  throw new Error(`Multiple dialects found in schema: ${dialects.join(", ")}`);
1069
1131
  }
@@ -1095,7 +1157,7 @@ async function initSearchIfApplicable(input) {
1095
1157
  */
1096
1158
  function adjustQueryArgsForSearch({ search, args, tableSchema, abilities }) {
1097
1159
  if (search?.enabled && args.search && args.search.length > 0) {
1098
- const columnsToSearch = (abilities.query.many.columns ? Object.entries(tableSchema.columns).filter(([key]) => abilities.query.many.columns[key]) : Object.entries(tableSchema.columns)).filter(([key, col]) => isStringLikeSQLTypeString(col.getSQLType()) || isIDLikeSQLTypeString(col.getSQLType()));
1160
+ const columnsToSearch = (abilities.query.many.columns ? Object.entries(tableSchema.columns).filter(([key]) => abilities.query.many.columns[key]) : Object.entries(tableSchema.columns)).filter(([_key, col]) => isStringLikeSQLTypeString(col.getSQLType()) || isIDLikeSQLTypeString(col.getSQLType()));
1099
1161
  const searchParam = drizzle_orm.sql`${args.search}`;
1100
1162
  args.extras = { search_distance: (table) => drizzle_orm.sql`${drizzle_orm.sql.join(columnsToSearch.map(([key]) => {
1101
1163
  return drizzle_orm.sql`COALESCE((${table[key]}::TEXT <-> ${searchParam}), 1)`;
@@ -1161,7 +1223,7 @@ const createObjectImplementer = ({ db, search, schemaBuilder, makePubSubInstance
1161
1223
  fields: (t) => {
1162
1224
  const columns = tableSchema.columns;
1163
1225
  const configMap = /* @__PURE__ */ new Map();
1164
- const userAdjustments = adjust?.(new Proxy(t, { get: (target, prop, receiver) => {
1226
+ const userAdjustments = adjust?.(new Proxy(t, { get: (target, prop, _receiver) => {
1165
1227
  if (typeof target[prop] !== "function" || prop === "arg" || prop === "builder" || prop === "graphqlKind" || prop === "kind" || prop === "listRef" || prop === "table" || prop === "typename" || prop === "variant" || prop.toString().startsWith("boolean") || prop.toString().startsWith("float") || prop.toString().startsWith("id") || prop.toString().startsWith("int") || prop.toString().startsWith("string") || prop.toString().startsWith("expose")) return target[prop];
1166
1228
  return (...params) => {
1167
1229
  const ref = target[prop](...params);
@@ -1183,9 +1245,12 @@ const createObjectImplementer = ({ db, search, schemaBuilder, makePubSubInstance
1183
1245
  return acc;
1184
1246
  }
1185
1247
  let isArray = false;
1186
- if (column.dimensions > 0) {
1187
- if (column.dimensions !== 1) throw new RumbleError("Only one-dimensional arrays are supported for default object implementation");
1188
- isArray = true;
1248
+ if ((0, drizzle_orm.is)(column, drizzle_orm_pg_core.PgColumn)) {
1249
+ const dimensions = column.dimensions;
1250
+ if (dimensions && dimensions > 0) {
1251
+ if (dimensions !== 1) throw new RumbleError("Only one-dimensional arrays are supported for default object implementation");
1252
+ isArray = true;
1253
+ }
1189
1254
  }
1190
1255
  if (isEnumSchema(column)) {
1191
1256
  const enumImpl = enumImplementer({ enumColumn: column });
@@ -1204,9 +1269,10 @@ const createObjectImplementer = ({ db, search, schemaBuilder, makePubSubInstance
1204
1269
  return acc;
1205
1270
  }, {});
1206
1271
  const relations = Object.entries(tableSchema.relations ?? {}).reduce((acc, [key, value]) => {
1272
+ const targetTsName = value.targetTableName;
1207
1273
  const relationSchema = tableHelper({
1208
1274
  db,
1209
- table: value.targetTable
1275
+ table: targetTsName
1210
1276
  });
1211
1277
  const WhereArg = whereArgImplementer({ dbName: relationSchema.dbName });
1212
1278
  const OrderArg = orderArgImplementer({ dbName: relationSchema.dbName });
@@ -1214,7 +1280,7 @@ const createObjectImplementer = ({ db, search, schemaBuilder, makePubSubInstance
1214
1280
  let nullable = false;
1215
1281
  let isMany = true;
1216
1282
  let filterSpecifier = "many";
1217
- if (value instanceof drizzle_orm.One) {
1283
+ if ((0, drizzle_orm.is)(value, drizzle_orm.One)) {
1218
1284
  isMany = false;
1219
1285
  nullable = value.optional || !value.sourceColumns.every((column) => column.notNull);
1220
1286
  filterSpecifier = "single";
@@ -1282,7 +1348,7 @@ const createObjectImplementer = ({ db, search, schemaBuilder, makePubSubInstance
1282
1348
  fields.search_distance = t.float({
1283
1349
  description: "The search distance of the object. If a search is provided, this field will be populated with the search distance.",
1284
1350
  nullable: true,
1285
- resolve: (parent, args, ctx, info) => parent.search_distance
1351
+ resolve: (parent, _args, _ctx, _info) => parent.search_distance
1286
1352
  });
1287
1353
  }
1288
1354
  return {
@@ -1647,9 +1713,10 @@ const createSchemaBuilder = ({ db, disableDefaultObjects, pubsub, pothosConfig,
1647
1713
  client: db,
1648
1714
  relations: db._.relations,
1649
1715
  getTableConfig(table) {
1716
+ const columns = (0, drizzle_orm.isTable)(table) ? Object.values((0, drizzle_orm.getTableColumns)(table)) : [];
1650
1717
  return {
1651
- columns: Object.values(table[Symbol.for("drizzle:Columns")]),
1652
- primaryKeys: Object.values(table[Symbol.for("drizzle:Columns")]).filter((v) => v.primary)
1718
+ columns,
1719
+ primaryKeys: columns.filter((v) => v.primary)
1653
1720
  };
1654
1721
  }
1655
1722
  },
@@ -1686,6 +1753,18 @@ export const db = drizzle(
1686
1753
  },
1687
1754
  );
1688
1755
 
1756
+ `);
1757
+ if (!rumbleInput.schema || typeof rumbleInput.schema !== "object" || Object.keys(rumbleInput.schema).length === 0) throw new RumbleError(`
1758
+ rumble requires the drizzle schema object to be passed when initializing.
1759
+ Import your schema module and pass it alongside \`db\`:
1760
+
1761
+ import * as schema from "./db/schema";
1762
+
1763
+ export const r = rumble({
1764
+ db,
1765
+ schema, // <--- add this line
1766
+ });
1767
+
1689
1768
  `);
1690
1769
  if (!rumbleInput.actions) rumbleInput.actions = [
1691
1770
  "read",