@m1212e/rumble 0.23.8 → 0.23.10

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,6 +1,6 @@
1
1
  import { t as lazy } from "./lazy-C7IyM4M4.mjs";
2
2
  import { t as generateFromSchema } from "./generate-0QFVc3Sg.mjs";
3
- import { GraphQLError, GraphQLSchema, execute as defaultExecute, subscribe as defaultSubscribe } from "graphql";
3
+ import { GraphQLError, GraphQLSchema, execute as defaultExecute, getOperationAST, print, 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";
@@ -180,7 +180,7 @@ function mapNullFieldsToUndefined(obj) {
180
180
  }
181
181
  //#endregion
182
182
  //#region package.json
183
- var version = "0.23.8";
183
+ var version = "0.23.10";
184
184
  //#endregion
185
185
  //#region lib/helpers/mergeFilters.ts
186
186
  const EmptyFilter$1 = Symbol.for("drizzle:EmptyFilter");
@@ -1171,7 +1171,13 @@ function deepSetProto(obj, proto = Object.prototype, seen = /* @__PURE__ */ new
1171
1171
  if (obj === null || typeof obj !== "object") return;
1172
1172
  if (seen.has(obj)) return;
1173
1173
  seen.add(obj);
1174
- if (!Array.isArray(obj)) Object.setPrototypeOf(obj, proto);
1174
+ if (Array.isArray(obj)) {
1175
+ for (const item of obj) deepSetProto(item, proto, seen);
1176
+ return;
1177
+ }
1178
+ const currentProto = Object.getPrototypeOf(obj);
1179
+ if (currentProto !== Object.prototype && currentProto !== null) return;
1180
+ Object.setPrototypeOf(obj, proto);
1175
1181
  for (const key of Object.keys(obj)) deepSetProto(obj[key], proto, seen);
1176
1182
  }
1177
1183
  //#endregion
@@ -1299,31 +1305,81 @@ const sofaOpenAPIWebhookDocs = {
1299
1305
  } }
1300
1306
  };
1301
1307
  //#endregion
1308
+ //#region lib/helpers/errorLogging.ts
1309
+ function hasMessage(error) {
1310
+ return typeof error === "object" && error !== null && "message" in error;
1311
+ }
1312
+ function toLoggedException(error) {
1313
+ if (hasMessage(error)) {
1314
+ const gqlError = error;
1315
+ return {
1316
+ "exception.type": gqlError.constructor?.name ?? gqlError.name ?? "Error",
1317
+ "exception.message": String(gqlError.message),
1318
+ ...gqlError.stack ? { "exception.stacktrace": gqlError.stack } : {},
1319
+ ...gqlError.path ? { path: gqlError.path } : {},
1320
+ ...gqlError.extensions && Object.keys(gqlError.extensions).length > 0 ? { extensions: gqlError.extensions } : {}
1321
+ };
1322
+ }
1323
+ return {
1324
+ "exception.type": "UnknownError",
1325
+ "exception.message": String(error)
1326
+ };
1327
+ }
1328
+ /**
1329
+ * Every erroneous rumble log carries the same `errors` array shape,
1330
+ * whether it originates from a thrown exception (single-element array)
1331
+ * or a GraphQL `ExecutionResult.errors` list (multi-element array).
1332
+ */
1333
+ function errorsLogField(errors) {
1334
+ return { errors: errors.map(toLoggedException) };
1335
+ }
1336
+ function errorLogField(error) {
1337
+ return errorsLogField([error]);
1338
+ }
1339
+ //#endregion
1302
1340
  //#region lib/helpers/tracing.ts
1341
+ const SUBSCRIBE_SPAN_NAME = "graphql.subscribe";
1342
+ function getOperationType(options) {
1343
+ return getOperationAST(options.document, options.operationName)?.operation;
1344
+ }
1345
+ function operationLogFields(operationName, operationType) {
1346
+ return {
1347
+ "graphql.operation.name": operationName,
1348
+ ...operationType ? { "graphql.operation.type": operationType } : {}
1349
+ };
1350
+ }
1351
+ function traceIdLogFields(span) {
1352
+ const { traceId, spanId, traceFlags } = span.spanContext();
1353
+ return {
1354
+ trace_id: traceId,
1355
+ span_id: spanId,
1356
+ trace_flags: traceFlags.toString(16).padStart(2, "0")
1357
+ };
1358
+ }
1303
1359
  function isAsyncIterable(value) {
1304
1360
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
1305
1361
  }
1306
- async function* wrapSubscriptionIterator(iterator, log, operationName) {
1362
+ async function* wrapSubscriptionIterator(iterator, log, operationName, operationType) {
1307
1363
  let eventCount = 0;
1308
1364
  try {
1309
1365
  for await (const event of iterator) {
1310
1366
  eventCount++;
1311
1367
  if (event.errors?.length) log.error({
1312
- "graphql.operation.name": operationName,
1313
- eventCount,
1314
- errors: event.errors.map((e) => e.message)
1368
+ ...operationLogFields(operationName, operationType),
1369
+ event_count: eventCount,
1370
+ ...errorsLogField(event.errors)
1315
1371
  }, "graphql subscription event error");
1316
1372
  yield event;
1317
1373
  }
1318
1374
  log.info({
1319
- "graphql.operation.name": operationName,
1320
- eventCount
1375
+ ...operationLogFields(operationName, operationType),
1376
+ event_count: eventCount
1321
1377
  }, "graphql subscription completed");
1322
1378
  } catch (error) {
1323
1379
  log.error({
1324
- "graphql.operation.name": operationName,
1325
- eventCount,
1326
- err: error
1380
+ ...operationLogFields(operationName, operationType),
1381
+ event_count: eventCount,
1382
+ ...errorLogField(error)
1327
1383
  }, "graphql subscription threw");
1328
1384
  throw error;
1329
1385
  }
@@ -1332,32 +1388,28 @@ function buildTracedExecute(executeFn, rumbleInput) {
1332
1388
  return async (options) => {
1333
1389
  let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1334
1390
  const operationName = options.operationName ?? "anonymous";
1391
+ const operationType = getOperationType(options);
1335
1392
  const start = Date.now();
1336
- log?.info({ "graphql.operation.name": operationName }, "graphql execute start");
1393
+ log?.info(operationLogFields(operationName, operationType), "graphql execute start");
1337
1394
  const run = async () => {
1338
1395
  const result = await executeFn(options);
1339
1396
  if (result && "errors" in result && result.errors?.length) log?.error({
1340
- "graphql.operation.name": operationName,
1341
- durationMs: Date.now() - start,
1342
- errors: result.errors.map((e) => e.message)
1397
+ ...operationLogFields(operationName, operationType),
1398
+ duration_ms: Date.now() - start,
1399
+ ...errorsLogField(result.errors)
1343
1400
  }, "graphql execute completed with errors");
1344
1401
  else log?.info({
1345
- "graphql.operation.name": operationName,
1346
- durationMs: Date.now() - start
1402
+ ...operationLogFields(operationName, operationType),
1403
+ duration_ms: Date.now() - start
1347
1404
  }, "graphql execute completed");
1348
1405
  return result;
1349
1406
  };
1350
1407
  if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SpanNames.EXECUTE, { attributes: {
1351
1408
  [AttributeNames.OPERATION_NAME]: operationName,
1352
- [AttributeNames.SOURCE]: options.document
1409
+ ...operationType ? { [AttributeNames.OPERATION_TYPE]: operationType } : {},
1410
+ "graphql.document": print(options.document)
1353
1411
  } }, async (span) => {
1354
- if (log && rumbleInput.logger?.injectTraceId !== false) {
1355
- const { traceId, spanId } = span.spanContext();
1356
- log = log.child({
1357
- traceId,
1358
- spanId
1359
- });
1360
- }
1412
+ if (log && rumbleInput.logger?.injectTraceId !== false) log = log.child(traceIdLogFields(span));
1361
1413
  try {
1362
1414
  const result = await run();
1363
1415
  if (result && "errors" in result && result.errors?.length) {
@@ -1368,9 +1420,9 @@ function buildTracedExecute(executeFn, rumbleInput) {
1368
1420
  } catch (error) {
1369
1421
  if (error instanceof Error) span.recordException(error);
1370
1422
  log?.error({
1371
- "graphql.operation.name": operationName,
1372
- durationMs: Date.now() - start,
1373
- err: error
1423
+ ...operationLogFields(operationName, operationType),
1424
+ duration_ms: Date.now() - start,
1425
+ ...errorLogField(error)
1374
1426
  }, "graphql execute threw");
1375
1427
  span.setStatus({ code: SpanStatusCode.ERROR });
1376
1428
  throw error;
@@ -1382,9 +1434,9 @@ function buildTracedExecute(executeFn, rumbleInput) {
1382
1434
  return await run();
1383
1435
  } catch (error) {
1384
1436
  log?.error({
1385
- "graphql.operation.name": operationName,
1386
- durationMs: Date.now() - start,
1387
- err: error
1437
+ ...operationLogFields(operationName, operationType),
1438
+ duration_ms: Date.now() - start,
1439
+ ...errorLogField(error)
1388
1440
  }, "graphql execute threw");
1389
1441
  throw error;
1390
1442
  }
@@ -1394,34 +1446,33 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1394
1446
  return async (options) => {
1395
1447
  let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1396
1448
  const operationName = options.operationName ?? "anonymous";
1449
+ const operationType = getOperationType(options);
1397
1450
  const start = Date.now();
1398
1451
  const doSubscribe = async () => {
1399
- log?.info({ "graphql.operation.name": operationName }, "graphql subscribe start");
1452
+ log?.info(operationLogFields(operationName, operationType), "graphql subscribe start");
1400
1453
  const result = await subscribeFn(options);
1401
1454
  if (!isAsyncIterable(result)) {
1402
1455
  const execResult = result;
1403
1456
  if (execResult.errors?.length) log?.error({
1404
- "graphql.operation.name": operationName,
1405
- durationMs: Date.now() - start,
1406
- errors: execResult.errors.map((e) => e.message)
1457
+ ...operationLogFields(operationName, operationType),
1458
+ duration_ms: Date.now() - start,
1459
+ ...errorsLogField(execResult.errors)
1407
1460
  }, "graphql subscribe completed with errors");
1408
1461
  return execResult;
1409
1462
  }
1410
1463
  log?.info({
1411
- "graphql.operation.name": operationName,
1412
- durationMs: Date.now() - start
1464
+ ...operationLogFields(operationName, operationType),
1465
+ duration_ms: Date.now() - start
1413
1466
  }, "graphql subscription established");
1414
- if (log) return wrapSubscriptionIterator(result, log, operationName);
1467
+ if (log) return wrapSubscriptionIterator(result, log, operationName, operationType);
1415
1468
  return result;
1416
1469
  };
1417
- if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan("graphql.subscribe", async (span) => {
1418
- if (log && rumbleInput.logger?.injectTraceId !== false) {
1419
- const { traceId, spanId } = span.spanContext();
1420
- log = log.child({
1421
- traceId,
1422
- spanId
1423
- });
1424
- }
1470
+ if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SUBSCRIBE_SPAN_NAME, { attributes: {
1471
+ [AttributeNames.OPERATION_NAME]: operationName,
1472
+ ...operationType ? { [AttributeNames.OPERATION_TYPE]: operationType } : {},
1473
+ "graphql.document": print(options.document)
1474
+ } }, async (span) => {
1475
+ if (log && rumbleInput.logger?.injectTraceId !== false) log = log.child(traceIdLogFields(span));
1425
1476
  try {
1426
1477
  const result = await doSubscribe();
1427
1478
  if (!isAsyncIterable(result)) {
@@ -1435,9 +1486,9 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1435
1486
  } catch (error) {
1436
1487
  if (error instanceof Error) span.recordException(error);
1437
1488
  log?.error({
1438
- "graphql.operation.name": operationName,
1439
- durationMs: Date.now() - start,
1440
- err: error
1489
+ ...operationLogFields(operationName, operationType),
1490
+ duration_ms: Date.now() - start,
1491
+ ...errorLogField(error)
1441
1492
  }, "graphql subscribe threw");
1442
1493
  span.setStatus({ code: SpanStatusCode.ERROR });
1443
1494
  throw error;
@@ -1449,9 +1500,9 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1449
1500
  return await doSubscribe();
1450
1501
  } catch (error) {
1451
1502
  log?.error({
1452
- "graphql.operation.name": operationName,
1453
- durationMs: Date.now() - start,
1454
- err: error
1503
+ ...operationLogFields(operationName, operationType),
1504
+ duration_ms: Date.now() - start,
1505
+ ...errorLogField(error)
1455
1506
  }, "graphql subscribe threw");
1456
1507
  throw error;
1457
1508
  }
@@ -1544,7 +1595,7 @@ async function initSearchIfApplicable(input) {
1544
1595
  await input.db.execute(sql`CREATE EXTENSION IF NOT EXISTS pg_trgm;`);
1545
1596
  } catch (error) {
1546
1597
  const msg = "Failed to create pg_trgm extension. Search functionality may not work. Ensure the database user has CREATE privilege or the extension is pre-installed.";
1547
- log ? log.error({ err: error }, msg) : console.error(msg, error);
1598
+ log ? log.error(errorLogField(error), msg) : console.error(msg, error);
1548
1599
  return;
1549
1600
  }
1550
1601
  if (input.search?.threshold) {
@@ -2294,7 +2345,7 @@ var RuntimeFiltersPlugin = class extends BasePlugin {
2294
2345
  } catch (error) {
2295
2346
  this.logger?.error({
2296
2347
  "graphql.field.name": fieldConfig.name,
2297
- err: error
2348
+ ...errorLogField(error)
2298
2349
  }, "runtime filter threw");
2299
2350
  throw error;
2300
2351
  } finally {
@@ -2306,7 +2357,7 @@ var RuntimeFiltersPlugin = class extends BasePlugin {
2306
2357
  } catch (error) {
2307
2358
  this.logger?.error({
2308
2359
  "graphql.field.name": fieldConfig.name,
2309
- err: error
2360
+ ...errorLogField(error)
2310
2361
  }, "runtime filter threw");
2311
2362
  throw error;
2312
2363
  }
@@ -2359,13 +2410,13 @@ const createSchemaBuilder = ({ db, pubsub, pothosConfig, otel, logger }) => {
2359
2410
  if (error) log.error({
2360
2411
  "graphql.field.name": config.name,
2361
2412
  "graphql.parent.type": config.parentType,
2362
- durationMs: duration,
2363
- err: error
2413
+ duration_ms: duration,
2414
+ ...errorLogField(error)
2364
2415
  }, "resolver failed");
2365
2416
  else log.debug({
2366
2417
  "graphql.field.name": config.name,
2367
2418
  "graphql.parent.type": config.parentType,
2368
- durationMs: duration
2419
+ duration_ms: duration
2369
2420
  }, "resolver completed");
2370
2421
  });
2371
2422
  }