@m1212e/rumble 0.16.41 → 0.16.47

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
@@ -209,7 +209,7 @@ function mapNullFieldsToUndefined(obj) {
209
209
  }
210
210
  //#endregion
211
211
  //#region package.json
212
- var version = "0.16.41";
212
+ var version = "0.16.47";
213
213
  //#endregion
214
214
  //#region lib/helpers/mergeFilters.ts
215
215
  function mergeFilters(filterA, filterB) {
@@ -375,6 +375,9 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
375
375
  const runtimeFilters = /* @__PURE__ */ new Map();
376
376
  for (const action of actions) if (!runtimeFilters.has(action)) runtimeFilters.set(action, []);
377
377
  return {
378
+ /**
379
+ * Allows to perform a specific action on a specific entity
380
+ */
378
381
  allow: (action) => {
379
382
  if (hasBeenBuilt) throw new RumbleError("You can't call allow() after the ability builder has been built. Please ensure that you register all abilities before accessing them.");
380
383
  const actions = Array.isArray(action) ? action : [action];
@@ -385,24 +388,58 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
385
388
  queryFilters.set(action, filters);
386
389
  }
387
390
  }
388
- return { when: (queryFilter) => {
391
+ return {
392
+ /**
393
+ * Restricts the allowed actions to a filter
394
+ * @example
395
+ * ```ts
396
+ * abilityBuilder.users.allow(["read", "update", "delete"]).when(({ userId }) => ({
397
+ * where: {
398
+ * id: userId,
399
+ * },
400
+ * }));
401
+ * ```
402
+ */
403
+ when: (queryFilter) => {
389
404
  for (const action of actions) {
390
405
  if (queryFilters.get(action) === "unrestricted") queryFilters.set(action, []);
391
406
  queryFilters.get(action).push(queryFilter);
392
407
  }
393
408
  } };
394
409
  },
410
+ /**
411
+ * Allows to register an application level filter to restrict some results
412
+ * which were returned by a query
413
+ */
395
414
  filter: (action) => {
396
415
  const actions = Array.isArray(action) ? action : [action];
397
416
  return {
417
+ /**
418
+ * Allows to register an application level prefetch to fetch some data
419
+ * which could be useful for later filtering the results. The prefetch
420
+ * function will be called with the user context but unlike the actual
421
+ * filter function, it will not have access to the result of the query
422
+ * and therefore can be run in parallel with underlying query resolver.
423
+ * A typical use case is to fetch some data which is not directly
424
+ * related to the query but to the context only. So e.g. fetching the
425
+ * user's permissions from an external system and then later applying
426
+ * the filter based on those permissions.
427
+ */
398
428
  prefetch: (prefetch) => {
399
- return { by: (explicitFilter) => {
429
+ return {
430
+ /**
431
+ * The actual filter function to apply. Returns the allowed values
432
+ */
433
+ by: (explicitFilter) => {
400
434
  for (const action of actions) runtimeFilters.get(action).push({
401
435
  filter: explicitFilter,
402
436
  prefetch
403
437
  });
404
438
  } };
405
439
  },
440
+ /**
441
+ * The actual filter function to apply. Returns the allowed values
442
+ */
406
443
  by: (explicitFilter) => {
407
444
  for (const action of actions) runtimeFilters.get(action).push({ filter: explicitFilter });
408
445
  }
@@ -417,6 +454,10 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
417
454
  const buildersPerTable = Object.fromEntries(Object.keys(db.query).map((tableName) => [tableName, createBuilderForTable()]));
418
455
  return {
419
456
  ...buildersPerTable,
457
+ /**
458
+ * @internal
459
+ * @ignore
460
+ */
420
461
  _: {
421
462
  registeredFilters({ action, table }) {
422
463
  return buildersPerTable[table]._.runtimeFilters.get(action);
@@ -461,12 +502,27 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
461
502
  return filters?.where ? (0, drizzle_orm.relationsFilterToSQL)(tableSchema.foundRelation.table, filters.where, tableSchema.relations, db._.relations, casing) : void 0;
462
503
  });
463
504
  if (filters?.columns) return {
505
+ /**
506
+ * Query filters for the drizzle query API.
507
+ * @example
508
+ * ```ts
509
+ * author: t.relation("author", {
510
+ * query: (_args, ctx) => ctx.abilities.users.filter("read").query.single,
511
+ * }),
512
+ * ´´´
513
+ */
464
514
  query: {
515
+ /**
516
+ * For find first calls
517
+ */
465
518
  single: {
466
519
  extras: filters?.extras,
467
520
  where: filters?.where,
468
521
  columns: filters?.columns
469
522
  },
523
+ /**
524
+ * For find many calls
525
+ */
470
526
  many: {
471
527
  extras: filters?.extras,
472
528
  where: filters?.where,
@@ -476,16 +532,50 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
476
532
  }
477
533
  }
478
534
  },
535
+ /**
536
+ * Query filters for the drizzle SQL API as used in e.g. updates.
537
+ * @example
538
+ *
539
+ * ```ts
540
+ * await db
541
+ * .update(schema.users)
542
+ * .set({
543
+ * name: args.newName,
544
+ * })
545
+ * .where(
546
+ * and(
547
+ * eq(schema.users.id, args.userId),
548
+ * ctx.abilities.users.filter("update").sql.where,
549
+ * ),
550
+ * );
551
+ * ```
552
+ *
553
+ */
479
554
  sql: { get where() {
480
555
  return sqlTransformedWhere();
481
556
  } }
482
557
  };
483
558
  else return {
559
+ /**
560
+ * Query filters for the drizzle query API.
561
+ * @example
562
+ * ```ts
563
+ * author: t.relation("author", {
564
+ * query: (_args, ctx) => ctx.abilities.users.filter("read").query.single,
565
+ * }),
566
+ * ´´´
567
+ */
484
568
  query: {
569
+ /**
570
+ * For find first calls
571
+ */
485
572
  single: {
486
573
  extras: filters?.extras,
487
574
  where: filters?.where
488
575
  },
576
+ /**
577
+ * For find many calls
578
+ */
489
579
  many: {
490
580
  extras: filters?.extras,
491
581
  where: filters?.where,
@@ -494,6 +584,25 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
494
584
  }
495
585
  }
496
586
  },
587
+ /**
588
+ * Query filters for the drizzle SQL API as used in e.g. updates.
589
+ * @example
590
+ *
591
+ * ```ts
592
+ * await db
593
+ * .update(schema.users)
594
+ * .set({
595
+ * name: args.newName,
596
+ * })
597
+ * .where(
598
+ * and(
599
+ * eq(schema.users.id, args.userId),
600
+ * ctx.abilities.users.filter("update").sql.where,
601
+ * ),
602
+ * );
603
+ * ```
604
+ *
605
+ */
497
606
  sql: { get where() {
498
607
  return sqlTransformedWhere();
499
608
  } }
@@ -737,7 +846,7 @@ const createWhereArgImplementer = ({ db, schemaBuilder, enumImplementer }) => {
737
846
  //#region lib/client/client.ts
738
847
  const clientCreatorImplementer = ({ builtSchema }) => {
739
848
  const clientCreator = async ({ apiUrl, outputPath, rumbleImportPath, useExternalUrqlClient, removeExisting, forceReactivity, autoIncludeIdField = false }) => {
740
- if (process.env.NODE_ENV !== "development") console.warn(`Running rumble client generation in non development mode. Are you sure this is correct? Called from ${__filename} with arguments: ${JSON.stringify({
849
+ if (process.env.NODE_ENV !== "development") console.warn(`Running rumble client generation in non development mode. Are you sure this is correct? Called with arguments: ${JSON.stringify({
741
850
  outputPath,
742
851
  apiUrl,
743
852
  rumbleImportPath,
@@ -1201,6 +1310,9 @@ const createPubSubInstance = ({ subscriptions }) => {
1201
1310
  return `${SUBSCRIPTION_NOTIFIER_RUMBLE_PREFIX}/${tableName}${primaryKeyValue ? `/${primaryKeyValue}` : ""}/${actionKey}`;
1202
1311
  }
1203
1312
  return {
1313
+ /**
1314
+ * Call this when you want to register a subscription on an instance to this table
1315
+ */
1204
1316
  registerOnInstance({ instance, action, primaryKeyValue }) {
1205
1317
  const key = makePubSubKey({
1206
1318
  tableName: table.toString(),
@@ -1209,6 +1321,9 @@ const createPubSubInstance = ({ subscriptions }) => {
1209
1321
  });
1210
1322
  instance.register(key);
1211
1323
  },
1324
+ /**
1325
+ * Call this when you created an entity of this table
1326
+ */
1212
1327
  created() {
1213
1328
  const key = makePubSubKey({
1214
1329
  tableName: table.toString(),
@@ -1216,6 +1331,9 @@ const createPubSubInstance = ({ subscriptions }) => {
1216
1331
  });
1217
1332
  return pubsub.publish(key);
1218
1333
  },
1334
+ /**
1335
+ * Call this when you removed one or more entities of this table
1336
+ */
1219
1337
  removed() {
1220
1338
  const key = makePubSubKey({
1221
1339
  tableName: table.toString(),
@@ -1223,6 +1341,9 @@ const createPubSubInstance = ({ subscriptions }) => {
1223
1341
  });
1224
1342
  return pubsub.publish(key);
1225
1343
  },
1344
+ /**
1345
+ * Call this when you updated one or more entities of this table
1346
+ */
1226
1347
  updated(primaryKeyValue) {
1227
1348
  const keys = (Array.isArray(primaryKeyValue) ? primaryKeyValue : [primaryKeyValue]).map((primaryKeyValue) => makePubSubKey({
1228
1349
  tableName: table.toString(),
@@ -1682,21 +1803,101 @@ export const db = drizzle(
1682
1803
  });
1683
1804
  };
1684
1805
  return {
1806
+ /**
1807
+ * The ability builder. Use it to declare whats allowed for each entity in your DB.
1808
+ *
1809
+ * @example
1810
+ *
1811
+ * ```ts
1812
+ * // users can edit themselves
1813
+ abilityBuilder.users
1814
+ .allow(["read", "update", "delete"])
1815
+ .when(({ userId }) => ({ where: eq(schema.users.id, userId) }));
1816
+
1817
+ // everyone can read posts
1818
+ abilityBuilder.posts.allow("read");
1819
+ *
1820
+ * ```
1821
+ */
1685
1822
  abilityBuilder,
1823
+ /**
1824
+ * The pothos schema builder. See https://pothos-graphql.dev/docs/plugins/drizzle
1825
+ */
1686
1826
  schemaBuilder,
1827
+ /**
1828
+ * Creates the native yoga instance. Can be used to run an actual HTTP server.
1829
+ *
1830
+ * @example
1831
+ *
1832
+ * ```ts
1833
+ * import { createServer } from "node:http";
1834
+ * const server = createServer(createYoga());
1835
+ * server.listen(3000, () => {
1836
+ * console.info("Visit http://localhost:3000/graphql");
1837
+ * });
1838
+ * ```
1839
+ * https://the-guild.dev/graphql/yoga-server/docs#server
1840
+ */
1687
1841
  createYoga,
1842
+ /**
1843
+ * Creates a sofa instance to offer a REST API.
1844
+ *
1845
+ * ```ts
1846
+ * import express from "express";
1847
+ *
1848
+ * const app = express();
1849
+ * const sofa = createSofa(...);
1850
+ *
1851
+ * app.use("/api", useSofa({ schema }));
1852
+ * ```
1853
+ * https://the-guild.dev/graphql/sofa-api/docs#usage
1854
+ */
1688
1855
  createSofa,
1856
+ /**
1857
+ * A function for creating default objects for your schema
1858
+ */
1689
1859
  object,
1860
+ /**
1861
+ * A function for creating where args to filter entities
1862
+ */
1690
1863
  whereArg,
1864
+ /**
1865
+ * A function for creating order args to sort entities
1866
+ */
1691
1867
  orderArg,
1868
+ /**
1869
+ * A function for creating default READ queries.
1870
+ * Make sure the objects for the table you are creating the queries for are implemented
1871
+ */
1692
1872
  query,
1873
+ /**
1874
+ * A function for creating a pubsub instance for a table. Use this to publish or subscribe events
1875
+ */
1693
1876
  pubsub: makePubSubInstance,
1877
+ /**
1878
+ * A function to implement enums for graphql usage.
1879
+ * The other helpers use this helper internally so in most cases you do not have to
1880
+ * call this helper directly, unless you need the reference to an enum type
1881
+ */
1694
1882
  enum_,
1883
+ /**
1884
+ * Create a client to consume a rumble graphql api at the specified location.
1885
+ * Requires GraphQL, does not work with the SOFA REST API.
1886
+ */
1695
1887
  clientCreator: clientCreatorImplementer({
1696
1888
  ...rumbleInput,
1697
1889
  builtSchema
1698
1890
  }),
1699
- countQuery
1891
+ /**
1892
+ * A function for creating count queries for your tables
1893
+ */
1894
+ countQuery,
1895
+ /**
1896
+ * The generated GraphQL schema. You can use this for example to create a GraphQL server with a different library than Yoga or to generate types with codegen.
1897
+ * When calling this function, the schema will be built for the first time and cached for later usage. So you can call this function multiple times without performance issues.
1898
+ * After calling, you cannot adjust the schema via the schema builder
1899
+ */
1900
+ buildSchema: builtSchema
1700
1901
  };
1701
1902
  };
1702
1903
  //#endregion