@m1212e/rumble 0.23.0 → 0.23.4

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.mjs CHANGED
@@ -1,10 +1,9 @@
1
1
  import { t as lazy } from "./lazy-C7IyM4M4.mjs";
2
2
  import { t as generateFromSchema } from "./generate-0QFVc3Sg.mjs";
3
- import { GraphQLError, GraphQLSchema } from "graphql";
3
+ import { GraphQLError, GraphQLSchema, execute as defaultExecute, subscribe as defaultSubscribe } from "graphql";
4
4
  import { EnvelopArmorPlugin } from "@escape.tech/graphql-armor";
5
5
  import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";
6
6
  import { SpanStatusCode, trace } from "@opentelemetry/api";
7
- import { AttributeNames, SpanNames, createOpenTelemetryWrapper } from "@pothos/tracing-opentelemetry";
8
7
  import { capitalize, cloneDeep, debounce, merge, toMerged } from "es-toolkit";
9
8
  import { createPubSub, createYoga } from "graphql-yoga";
10
9
  import { One, count, getTableColumns, getTableName, is, isTable, relationsFilterToSQL, sql } from "drizzle-orm";
@@ -12,6 +11,7 @@ import { toCamelCase } from "drizzle-orm/casing";
12
11
  import { PgColumn, PgEnumColumn, PgEnumObjectColumn, PgTable, isPgEnum } from "drizzle-orm/pg-core";
13
12
  import { MySqlEnumColumn, MySqlEnumObjectColumn, MySqlTable } from "drizzle-orm/mysql-core";
14
13
  import pluralize from "pluralize";
14
+ import { AttributeNames, SpanNames, createOpenTelemetryWrapper } from "@pothos/tracing-opentelemetry";
15
15
  import { SQLiteTable } from "drizzle-orm/sqlite-core";
16
16
  import SchemaBuilder, { BasePlugin } from "@pothos/core";
17
17
  import DrizzlePlugin from "@pothos/plugin-drizzle";
@@ -180,7 +180,7 @@ function mapNullFieldsToUndefined(obj) {
180
180
  }
181
181
  //#endregion
182
182
  //#region package.json
183
- var version = "0.23.0";
183
+ var version = "0.23.4";
184
184
  //#endregion
185
185
  //#region lib/helpers/mergeFilters.ts
186
186
  function mergeFilters(filterA, filterB, mode = "AND") {
@@ -676,7 +676,8 @@ by: (explicitFilter) => {
676
676
  * Merges the current query filters with the provided filters for this call only
677
677
  */
678
678
  function merge(p) {
679
- return internalTransformer(mergeFilters(ret.query.many, p), p.limit);
679
+ const merged = mergeFilters(ret.query.many, p);
680
+ return internalTransformer(merged, p.limit);
680
681
  }
681
682
  ret.merge = merge;
682
683
  return ret;
@@ -726,13 +727,14 @@ by: (explicitFilter) => {
726
727
  "rumble.table": tableName.toString(),
727
728
  "rumble.action": action
728
729
  };
729
- const result = assembleAbilities(new Proxy(span, { get(target, prop) {
730
+ const proxy = new Proxy(span, { get(target, prop) {
730
731
  if (prop === "setAttribute") return (k, v) => {
731
732
  attrs[k] = v;
732
733
  return target.setAttribute(k, v);
733
734
  };
734
735
  return target[prop];
735
- } }));
736
+ } });
737
+ const result = assembleAbilities(proxy);
736
738
  log?.debug(attrs, "abilities prepared");
737
739
  return result;
738
740
  } finally {
@@ -1068,10 +1070,11 @@ const createWhereArgImplementer = ({ db, schemaBuilder, enumImplementer }) => {
1068
1070
  }, {});
1069
1071
  const relations = Object.entries(tableSchema.relations ?? {}).reduce((acc, [key, value]) => {
1070
1072
  const targetTsName = value.targetTableName;
1071
- const referenceModel = whereArgImplementer({ dbName: tableHelper({
1073
+ const relationSchema = tableHelper({
1072
1074
  db,
1073
1075
  table: targetTsName
1074
- }).dbName });
1076
+ });
1077
+ const referenceModel = whereArgImplementer({ dbName: relationSchema.dbName });
1075
1078
  acc[key] = t.field({
1076
1079
  type: referenceModel,
1077
1080
  required: false
@@ -1269,6 +1272,165 @@ const sofaOpenAPIWebhookDocs = {
1269
1272
  } }
1270
1273
  };
1271
1274
  //#endregion
1275
+ //#region lib/helpers/tracing.ts
1276
+ function isAsyncIterable(value) {
1277
+ return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
1278
+ }
1279
+ async function* wrapSubscriptionIterator(iterator, log, operationName) {
1280
+ let eventCount = 0;
1281
+ try {
1282
+ for await (const event of iterator) {
1283
+ eventCount++;
1284
+ if (event.errors?.length) log.error({
1285
+ "graphql.operation.name": operationName,
1286
+ eventCount,
1287
+ errors: event.errors.map((e) => e.message)
1288
+ }, "graphql subscription event error");
1289
+ yield event;
1290
+ }
1291
+ log.info({
1292
+ "graphql.operation.name": operationName,
1293
+ eventCount
1294
+ }, "graphql subscription completed");
1295
+ } catch (error) {
1296
+ log.error({
1297
+ "graphql.operation.name": operationName,
1298
+ eventCount,
1299
+ err: error
1300
+ }, "graphql subscription threw");
1301
+ throw error;
1302
+ }
1303
+ }
1304
+ function buildTracedExecute(executeFn, rumbleInput) {
1305
+ return async (options) => {
1306
+ let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1307
+ const operationName = options.operationName ?? "anonymous";
1308
+ const start = Date.now();
1309
+ log?.info({ "graphql.operation.name": operationName }, "graphql execute start");
1310
+ const run = async () => {
1311
+ const result = await executeFn(options);
1312
+ if (result && "errors" in result && result.errors?.length) log?.error({
1313
+ "graphql.operation.name": operationName,
1314
+ durationMs: Date.now() - start,
1315
+ errors: result.errors.map((e) => e.message)
1316
+ }, "graphql execute completed with errors");
1317
+ else log?.info({
1318
+ "graphql.operation.name": operationName,
1319
+ durationMs: Date.now() - start
1320
+ }, "graphql execute completed");
1321
+ return result;
1322
+ };
1323
+ if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SpanNames.EXECUTE, { attributes: {
1324
+ [AttributeNames.OPERATION_NAME]: operationName,
1325
+ [AttributeNames.SOURCE]: options.document
1326
+ } }, async (span) => {
1327
+ if (log && rumbleInput.logger?.injectTraceId !== false) {
1328
+ const { traceId, spanId } = span.spanContext();
1329
+ log = log.child({
1330
+ traceId,
1331
+ spanId
1332
+ });
1333
+ }
1334
+ try {
1335
+ const result = await run();
1336
+ if (result && "errors" in result && result.errors?.length) {
1337
+ for (const error of result.errors) span.recordException(error);
1338
+ span.setStatus({ code: SpanStatusCode.ERROR });
1339
+ }
1340
+ return result;
1341
+ } catch (error) {
1342
+ if (error instanceof Error) span.recordException(error);
1343
+ log?.error({
1344
+ "graphql.operation.name": operationName,
1345
+ durationMs: Date.now() - start,
1346
+ err: error
1347
+ }, "graphql execute threw");
1348
+ span.setStatus({ code: SpanStatusCode.ERROR });
1349
+ throw error;
1350
+ } finally {
1351
+ span.end();
1352
+ }
1353
+ });
1354
+ try {
1355
+ return await run();
1356
+ } catch (error) {
1357
+ log?.error({
1358
+ "graphql.operation.name": operationName,
1359
+ durationMs: Date.now() - start,
1360
+ err: error
1361
+ }, "graphql execute threw");
1362
+ throw error;
1363
+ }
1364
+ };
1365
+ }
1366
+ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1367
+ return async (options) => {
1368
+ let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1369
+ const operationName = options.operationName ?? "anonymous";
1370
+ const start = Date.now();
1371
+ const doSubscribe = async () => {
1372
+ log?.info({ "graphql.operation.name": operationName }, "graphql subscribe start");
1373
+ const result = await subscribeFn(options);
1374
+ if (!isAsyncIterable(result)) {
1375
+ const execResult = result;
1376
+ if (execResult.errors?.length) log?.error({
1377
+ "graphql.operation.name": operationName,
1378
+ durationMs: Date.now() - start,
1379
+ errors: execResult.errors.map((e) => e.message)
1380
+ }, "graphql subscribe completed with errors");
1381
+ return execResult;
1382
+ }
1383
+ log?.info({
1384
+ "graphql.operation.name": operationName,
1385
+ durationMs: Date.now() - start
1386
+ }, "graphql subscription established");
1387
+ if (log) return wrapSubscriptionIterator(result, log, operationName);
1388
+ return result;
1389
+ };
1390
+ if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan("graphql.subscribe", async (span) => {
1391
+ if (log && rumbleInput.logger?.injectTraceId !== false) {
1392
+ const { traceId, spanId } = span.spanContext();
1393
+ log = log.child({
1394
+ traceId,
1395
+ spanId
1396
+ });
1397
+ }
1398
+ try {
1399
+ const result = await doSubscribe();
1400
+ if (!isAsyncIterable(result)) {
1401
+ const execResult = result;
1402
+ if (execResult.errors?.length) {
1403
+ for (const error of execResult.errors) span.recordException(error);
1404
+ span.setStatus({ code: SpanStatusCode.ERROR });
1405
+ }
1406
+ }
1407
+ return result;
1408
+ } catch (error) {
1409
+ if (error instanceof Error) span.recordException(error);
1410
+ log?.error({
1411
+ "graphql.operation.name": operationName,
1412
+ durationMs: Date.now() - start,
1413
+ err: error
1414
+ }, "graphql subscribe threw");
1415
+ span.setStatus({ code: SpanStatusCode.ERROR });
1416
+ throw error;
1417
+ } finally {
1418
+ span.end();
1419
+ }
1420
+ });
1421
+ try {
1422
+ return await doSubscribe();
1423
+ } catch (error) {
1424
+ log?.error({
1425
+ "graphql.operation.name": operationName,
1426
+ durationMs: Date.now() - start,
1427
+ err: error
1428
+ }, "graphql subscribe threw");
1429
+ throw error;
1430
+ }
1431
+ };
1432
+ }
1433
+ //#endregion
1272
1434
  //#region lib/helpers/sqlTypes/mapDrizzleTypeToGraphQlType.ts
1273
1435
  function buildPothosResponseTypeFromGraphQLType({ builder, sqlType, fieldName, nullable, isArray }) {
1274
1436
  const gqlType = mapSQLTypeToGraphQLType({
@@ -2306,59 +2468,7 @@ export const r = rumble({
2306
2468
  ...args?.plugins ?? [],
2307
2469
  ...enableApiDocs ? [] : [useDisableIntrospection(), EnvelopArmorPlugin(args?.armorConfig)],
2308
2470
  rumbleInput.otel?.enabled || rumbleInput.logger?.enabled ? { onExecute: ({ setExecuteFn, executeFn }) => {
2309
- setExecuteFn(async (options) => {
2310
- const log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
2311
- const operationName = options.operationName ?? "anonymous";
2312
- const start = Date.now();
2313
- log?.info({ "graphql.operation.name": operationName }, "graphql execute start");
2314
- const run = async () => {
2315
- const result = await executeFn(options);
2316
- if (result && "errors" in result && result.errors?.length) log?.error({
2317
- "graphql.operation.name": operationName,
2318
- durationMs: Date.now() - start,
2319
- errors: result.errors.map((e) => e.message)
2320
- }, "graphql execute completed with errors");
2321
- else log?.info({
2322
- "graphql.operation.name": operationName,
2323
- durationMs: Date.now() - start
2324
- }, "graphql execute completed");
2325
- return result;
2326
- };
2327
- if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SpanNames.EXECUTE, { attributes: {
2328
- [AttributeNames.OPERATION_NAME]: operationName,
2329
- [AttributeNames.SOURCE]: options.document
2330
- } }, async (span) => {
2331
- try {
2332
- const result = await run();
2333
- if (result && "errors" in result && result.errors?.length) {
2334
- for (const error of result.errors) span.recordException(error);
2335
- span.setStatus({ code: SpanStatusCode.ERROR });
2336
- }
2337
- return result;
2338
- } catch (error) {
2339
- if (error instanceof Error) span.recordException(error);
2340
- log?.error({
2341
- "graphql.operation.name": operationName,
2342
- durationMs: Date.now() - start,
2343
- err: error
2344
- }, "graphql execute threw");
2345
- span.setStatus({ code: SpanStatusCode.ERROR });
2346
- throw error;
2347
- } finally {
2348
- span.end();
2349
- }
2350
- });
2351
- try {
2352
- return await run();
2353
- } catch (error) {
2354
- log?.error({
2355
- "graphql.operation.name": operationName,
2356
- durationMs: Date.now() - start,
2357
- err: error
2358
- }, "graphql execute threw");
2359
- throw error;
2360
- }
2361
- });
2471
+ setExecuteFn(buildTracedExecute(executeFn, rumbleInput));
2362
2472
  } } : false
2363
2473
  ].filter(Boolean)
2364
2474
  });
@@ -2379,6 +2489,8 @@ export const r = rumble({
2379
2489
  ...args,
2380
2490
  schema: builtSchema(),
2381
2491
  context,
2492
+ execute: buildTracedExecute(args.execute ?? defaultExecute, rumbleInput),
2493
+ subscribe: buildTracedSubscribe(args.subscribe ?? defaultSubscribe, rumbleInput),
2382
2494
  errorHandler(errors) {
2383
2495
  const span = trace.getActiveSpan();
2384
2496
  for (const error of errors) span?.recordException(error);
@@ -2391,7 +2503,9 @@ export const r = rumble({
2391
2503
  return implementation({
2392
2504
  ...args,
2393
2505
  schema: builtSchema(),
2394
- context
2506
+ context,
2507
+ execute: buildTracedExecute(args.execute ?? defaultExecute, rumbleInput),
2508
+ subscribe: buildTracedSubscribe(args.subscribe ?? defaultSubscribe, rumbleInput)
2395
2509
  }, ...rest);
2396
2510
  };
2397
2511
  return {