@m1212e/rumble 0.23.11 → 0.23.14

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
@@ -46,6 +46,8 @@ _pothos_plugin_smart_subscriptions = __toESM(_pothos_plugin_smart_subscriptions,
46
46
  let _pothos_plugin_tracing = require("@pothos/plugin-tracing");
47
47
  _pothos_plugin_tracing = __toESM(_pothos_plugin_tracing, 1);
48
48
  let graphql_scalars = require("graphql-scalars");
49
+ let dataloader = require("dataloader");
50
+ dataloader = __toESM(dataloader, 1);
49
51
  //#region lib/types/rumbleError.ts
50
52
  /**
51
53
  * An error that gets raised by rumble whenever something does not go according to plan.
@@ -208,7 +210,7 @@ function mapNullFieldsToUndefined(obj) {
208
210
  }
209
211
  //#endregion
210
212
  //#region package.json
211
- var version = "0.23.11";
213
+ var version = "0.23.14";
212
214
  //#endregion
213
215
  //#region lib/helpers/mergeFilters.ts
214
216
  const EmptyFilter$1 = Symbol.for("drizzle:EmptyFilter");
@@ -418,6 +420,7 @@ function buildIndex(db) {
418
420
  columns,
419
421
  primaryKey,
420
422
  relations: entry.relations ?? {},
423
+ isTable: (0, drizzle_orm.isTable)(tableObj),
421
424
  foundRelation: entry
422
425
  };
423
426
  byTsName.set(resolved.name, resolved);
@@ -462,6 +465,7 @@ function tableHelper({ db, table }) {
462
465
  dbName: entry.dbName,
463
466
  tsName: entry.name,
464
467
  table: entry.table,
468
+ isTable: entry.isTable,
465
469
  foundRelation: entry.foundRelation
466
470
  };
467
471
  }
@@ -484,6 +488,10 @@ const makeNothingRegisteredWarner = (logger) => (0, es_toolkit.debounce)((model,
484
488
  const createAbilityBuilder = ({ db, actions, defaultLimit, otel, logger: loggerConfig }) => {
485
489
  const log = loggerConfig?.enabled ? loggerConfig.logger : void 0;
486
490
  const nothingRegisteredWarningLogger = makeNothingRegisteredWarner(log);
491
+ const tableRelationNames = Object.keys(db.query).filter((name) => tableHelper({
492
+ db,
493
+ table: name
494
+ }).isTable);
487
495
  let hasBeenBuilt = false;
488
496
  const createBuilderForTable = () => {
489
497
  const queryFilters = /* @__PURE__ */ new Map();
@@ -569,7 +577,7 @@ by: (explicitFilter) => {
569
577
  }
570
578
  };
571
579
  };
572
- const buildersPerTable = Object.fromEntries(Object.keys(db.query).map((tableName) => [tableName, createBuilderForTable()]));
580
+ const buildersPerTable = Object.fromEntries(tableRelationNames.map((tableName) => [tableName, createBuilderForTable()]));
573
581
  return {
574
582
  ...buildersPerTable,
575
583
  /**
@@ -597,7 +605,7 @@ by: (explicitFilter) => {
597
605
  db,
598
606
  table: tableName
599
607
  });
600
- if (Object.keys(tableSchema.primaryKey).length === 0) throw new RumbleError(`No primary key found for entity ${tableName.toString()}`);
608
+ if (Object.keys(tableSchema.primaryKey).length === 0) throw new RumbleError(`No primary key found for entity ${String(tableName)}`);
601
609
  const primaryKeyField = Object.values(tableSchema.primaryKey)[0];
602
610
  const distinctValues = createDistinctValuesFromSQLType(primaryKeyField.getSQLType());
603
611
  const blockEverythingFilter = { where: { AND: [{ [primaryKeyField.name]: distinctValues.value1 }, { [primaryKeyField.name]: distinctValues.value2 }] } };
@@ -747,7 +755,7 @@ by: (explicitFilter) => {
747
755
  }
748
756
  if (!filters) {
749
757
  span?.setAttribute("abilities.status", "blocked_everything");
750
- nothingRegisteredWarningLogger(tableName.toString(), action);
758
+ nothingRegisteredWarningLogger(String(tableName), action);
751
759
  return transformToResponse(blockEverythingFilter);
752
760
  }
753
761
  const dynamicResults = new Array(dynamicQueryFilters[action].length);
@@ -776,10 +784,10 @@ by: (explicitFilter) => {
776
784
  };
777
785
  if (otel?.enabled && otel.tracer) return otel.tracer.startActiveSpan(`rumble.abilities.prepare`, (span) => {
778
786
  span.setAttribute("rumble.action", action);
779
- span.setAttribute("rumble.table", tableName.toString());
787
+ span.setAttribute("rumble.table", String(tableName));
780
788
  try {
781
789
  const attrs = {
782
- "rumble.table": tableName.toString(),
790
+ "rumble.table": String(tableName),
783
791
  "rumble.action": action
784
792
  };
785
793
  const proxy = new Proxy(span, { get(target, prop) {
@@ -798,7 +806,7 @@ by: (explicitFilter) => {
798
806
  });
799
807
  else {
800
808
  const attrs = {
801
- "rumble.table": tableName.toString(),
809
+ "rumble.table": String(tableName),
802
810
  "rumble.action": action
803
811
  };
804
812
  const result = assembleAbilities(log ? { setAttribute: (k, v) => {
@@ -810,10 +818,10 @@ by: (explicitFilter) => {
810
818
  } };
811
819
  } };
812
820
  };
813
- const abilitiesPerTable = Object.fromEntries(Object.keys(db.query).map((tableName) => [tableName, createFilterForTable(tableName)]));
821
+ const abilitiesPerTable = Object.fromEntries(tableRelationNames.map((tableName) => [tableName, createFilterForTable(tableName)]));
814
822
  hasBeenBuilt = true;
815
823
  return (ctx) => {
816
- return Object.fromEntries(Object.keys(abilitiesPerTable).map((tableName) => [tableName, abilitiesPerTable[tableName].withContext(ctx)]));
824
+ return Object.fromEntries(tableRelationNames.map((tableName) => [tableName, abilitiesPerTable[tableName].withContext(ctx)]));
817
825
  };
818
826
  }
819
827
  }
@@ -1219,11 +1227,11 @@ const createCountQueryImplementer = ({ db, schemaBuilder, whereArgImplementer, m
1219
1227
  table
1220
1228
  });
1221
1229
  return schemaBuilder.queryFields((t) => {
1222
- return { [`${pluralize.default.plural(table.toString())}Count`]: t.field({
1230
+ return { [`${pluralize.default.plural(String(table))}Count`]: t.field({
1223
1231
  type: "Int",
1224
1232
  nullable: false,
1225
1233
  smartSubscription: true,
1226
- description: `Count all ${pluralize.default.plural(table.toString())}`,
1234
+ description: `Count all ${pluralize.default.plural(String(table))}`,
1227
1235
  subscribe: (subscriptions, _root, _args, _ctx, _info) => {
1228
1236
  registerOnInstance({
1229
1237
  instance: subscriptions,
@@ -1690,20 +1698,20 @@ const createObjectImplementer = ({ db, search, logger: loggerConfig, schemaBuild
1690
1698
  });
1691
1699
  if (Object.keys(tableSchema.primaryKey).length === 0) {
1692
1700
  const log = loggerConfig?.enabled ? loggerConfig.logger : void 0;
1693
- const msg = `Could not find primary key for ${table.toString()}. Cannot register subscriptions!`;
1694
- log ? log.warn({ "rumble.table": table.toString() }, msg) : console.warn(msg);
1701
+ const msg = `Could not find primary key for ${String(table)}. Cannot register subscriptions!`;
1702
+ log ? log.warn({ "rumble.table": String(table) }, msg) : console.warn(msg);
1695
1703
  }
1696
1704
  const primaryKey = Object.values(tableSchema.primaryKey)[0];
1697
1705
  const { registerOnInstance } = makePubSubInstance({ table });
1698
1706
  return schemaBuilder.drizzleObject(table, {
1699
- name: refName ?? (0, es_toolkit.capitalize)(table.toString()),
1707
+ name: refName ?? (0, es_toolkit.capitalize)(String(table)),
1700
1708
  subscribe: (subscriptions, element, _context) => {
1701
1709
  if (!primaryKey) return;
1702
1710
  const primaryKeyValue = element[primaryKey.name];
1703
1711
  if (!primaryKeyValue) {
1704
1712
  const log = loggerConfig?.enabled ? loggerConfig.logger : void 0;
1705
- const msg = `Could not find primary key value for element on ${table.toString()}. Cannot register subscription!`;
1706
- log ? log.warn({ "rumble.table": table.toString() }, msg) : console.warn(msg);
1713
+ const msg = `Could not find primary key value for element on ${String(table)}. Cannot register subscription!`;
1714
+ log ? log.warn({ "rumble.table": String(table) }, msg) : console.warn(msg);
1707
1715
  return;
1708
1716
  }
1709
1717
  registerOnInstance({
@@ -1949,10 +1957,10 @@ const createQueryImplementer = ({ db, schemaBuilder, search, logger: loggerConfi
1949
1957
  });
1950
1958
  const primaryKeyField = Object.values(tableSchema.primaryKey)[0];
1951
1959
  const { registerOnInstance } = makePubSubInstance({ table });
1952
- const pluralName = pluralize.default.plural(table.toString());
1953
- const singularName = pluralize.default.singular(table.toString());
1960
+ const pluralName = pluralize.default.plural(String(table));
1961
+ const singularName = pluralize.default.singular(String(table));
1954
1962
  for (const name of [pluralName, singularName]) {
1955
- if (registeredQueryFieldNames.has(name)) throw new RumbleError(`Duplicate query field "${name}": the table "${table.toString()}" generates a query field that collides with one already registered. Use unique table names (or refNames) to avoid plural/singular collisions (e.g. "post" and "posts").`);
1963
+ if (registeredQueryFieldNames.has(name)) throw new RumbleError(`Duplicate query field "${name}": the table "${String(table)}" generates a query field that collides with one already registered. Use unique table names (or refNames) to avoid plural/singular collisions (e.g. "post" and "posts").`);
1956
1964
  registeredQueryFieldNames.add(name);
1957
1965
  }
1958
1966
  return schemaBuilder.queryFields((t) => {
@@ -2303,6 +2311,30 @@ var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
2303
2311
  tracer;
2304
2312
  tracerEnabled;
2305
2313
  logger;
2314
+ filterLoaders = /* @__PURE__ */ new WeakMap();
2315
+ getLoader(context, filter) {
2316
+ let perContext = this.filterLoaders.get(context);
2317
+ if (!perContext) {
2318
+ perContext = /* @__PURE__ */ new Map();
2319
+ this.filterLoaders.set(context, perContext);
2320
+ }
2321
+ let loader = perContext.get(filter);
2322
+ if (!loader) {
2323
+ const prefetchPromise = filter.prefetch ? filter.prefetch({ context }) : void 0;
2324
+ loader = new dataloader.default(async (entities) => {
2325
+ const prefetched = prefetchPromise ? await prefetchPromise : void 0;
2326
+ const allowed = await filter.filter({
2327
+ context,
2328
+ entities,
2329
+ prefetched
2330
+ });
2331
+ const allowedSet = new Set(allowed);
2332
+ return entities.map((entity) => allowedSet.has(entity) ? entity : null);
2333
+ }, { cache: false });
2334
+ perContext.set(filter, loader);
2335
+ }
2336
+ return loader;
2337
+ }
2306
2338
  onTypeConfig(typeConfig) {
2307
2339
  this.tracer = this.builder.options.otel?.tracer;
2308
2340
  this.tracerEnabled = this.builder.options.otel?.enabled;
@@ -2319,44 +2351,20 @@ var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
2319
2351
  const runFilters = async (span) => {
2320
2352
  const allFilters = Array.isArray(filters) ? filters : [filters];
2321
2353
  span?.setAttribute("filters.total", allFilters.length);
2322
- const prefetchedFiltersPromises = Promise.all(allFilters.map(async (filter) => {
2323
- if (filter.prefetch) {
2324
- const prefetched = await filter.prefetch({ context });
2325
- return ({ context, entities }) => filter.filter({
2326
- context,
2327
- entities,
2328
- prefetched
2329
- });
2354
+ const loaders = allFilters.map((filter) => this.getLoader(context, filter));
2355
+ let resolved;
2356
+ if (this.tracer && this.tracerEnabled) resolved = await this.tracer.startActiveSpan(`rumble.filter.resolve`, async (span) => {
2357
+ span.setAttribute("graphql.field.name", fieldConfig.name);
2358
+ try {
2359
+ return await resolver(parent, args, context, info);
2360
+ } finally {
2361
+ span.end();
2330
2362
  }
2331
- return ({ context, entities }) => filter.filter({
2332
- context,
2333
- entities
2334
- });
2335
- }));
2336
- let resolved, prefetchedFilters;
2337
- if (this.tracer && this.tracerEnabled) {
2338
- const o = await this.tracer.startActiveSpan(`rumble.filter.resolve`, async (span) => {
2339
- span.setAttribute("graphql.field.name", fieldConfig.name);
2340
- try {
2341
- return await Promise.all([resolver(parent, args, context, info), prefetchedFiltersPromises]);
2342
- } finally {
2343
- span.end();
2344
- }
2345
- });
2346
- resolved = o[0];
2347
- prefetchedFilters = o[1];
2348
- } else {
2349
- const o = await Promise.all([resolver(parent, args, context, info), prefetchedFiltersPromises]);
2350
- resolved = o[0];
2351
- prefetchedFilters = o[1];
2352
- }
2353
- const allowed = Array.from((await Promise.all(prefetchedFilters.map((f) => f({
2354
- context,
2355
- entities: Array.isArray(resolved) ? resolved : [resolved]
2356
- })))).reduce((acc, val) => {
2357
- for (const element of val) acc.add(element);
2358
- return acc;
2359
- }, /* @__PURE__ */ new Set()));
2363
+ });
2364
+ else resolved = await resolver(parent, args, context, info);
2365
+ const entities = Array.isArray(resolved) ? resolved : [resolved];
2366
+ const perFilterResults = await Promise.all(loaders.map((loader) => Promise.all(entities.map((entity) => loader.load(entity)))));
2367
+ const allowed = entities.filter((_, index) => perFilterResults.some((results) => results[index] != null));
2360
2368
  span?.setAttribute("filters.allowed", allowed.length);
2361
2369
  this.logger?.debug({
2362
2370
  "graphql.field.name": fieldConfig.name,