@m1212e/rumble 0.23.2 → 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.2";
183
+ var version = "0.23.4";
184
184
  //#endregion
185
185
  //#region lib/helpers/mergeFilters.ts
186
186
  function mergeFilters(filterA, filterB, mode = "AND") {
@@ -1272,6 +1272,165 @@ const sofaOpenAPIWebhookDocs = {
1272
1272
  } }
1273
1273
  };
1274
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
1275
1434
  //#region lib/helpers/sqlTypes/mapDrizzleTypeToGraphQlType.ts
1276
1435
  function buildPothosResponseTypeFromGraphQLType({ builder, sqlType, fieldName, nullable, isArray }) {
1277
1436
  const gqlType = mapSQLTypeToGraphQLType({
@@ -2309,59 +2468,7 @@ export const r = rumble({
2309
2468
  ...args?.plugins ?? [],
2310
2469
  ...enableApiDocs ? [] : [useDisableIntrospection(), EnvelopArmorPlugin(args?.armorConfig)],
2311
2470
  rumbleInput.otel?.enabled || rumbleInput.logger?.enabled ? { onExecute: ({ setExecuteFn, executeFn }) => {
2312
- setExecuteFn(async (options) => {
2313
- const log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
2314
- const operationName = options.operationName ?? "anonymous";
2315
- const start = Date.now();
2316
- log?.info({ "graphql.operation.name": operationName }, "graphql execute start");
2317
- const run = async () => {
2318
- const result = await executeFn(options);
2319
- if (result && "errors" in result && result.errors?.length) log?.error({
2320
- "graphql.operation.name": operationName,
2321
- durationMs: Date.now() - start,
2322
- errors: result.errors.map((e) => e.message)
2323
- }, "graphql execute completed with errors");
2324
- else log?.info({
2325
- "graphql.operation.name": operationName,
2326
- durationMs: Date.now() - start
2327
- }, "graphql execute completed");
2328
- return result;
2329
- };
2330
- if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SpanNames.EXECUTE, { attributes: {
2331
- [AttributeNames.OPERATION_NAME]: operationName,
2332
- [AttributeNames.SOURCE]: options.document
2333
- } }, async (span) => {
2334
- try {
2335
- const result = await run();
2336
- if (result && "errors" in result && result.errors?.length) {
2337
- for (const error of result.errors) span.recordException(error);
2338
- span.setStatus({ code: SpanStatusCode.ERROR });
2339
- }
2340
- return result;
2341
- } catch (error) {
2342
- if (error instanceof Error) span.recordException(error);
2343
- log?.error({
2344
- "graphql.operation.name": operationName,
2345
- durationMs: Date.now() - start,
2346
- err: error
2347
- }, "graphql execute threw");
2348
- span.setStatus({ code: SpanStatusCode.ERROR });
2349
- throw error;
2350
- } finally {
2351
- span.end();
2352
- }
2353
- });
2354
- try {
2355
- return await run();
2356
- } catch (error) {
2357
- log?.error({
2358
- "graphql.operation.name": operationName,
2359
- durationMs: Date.now() - start,
2360
- err: error
2361
- }, "graphql execute threw");
2362
- throw error;
2363
- }
2364
- });
2471
+ setExecuteFn(buildTracedExecute(executeFn, rumbleInput));
2365
2472
  } } : false
2366
2473
  ].filter(Boolean)
2367
2474
  });
@@ -2382,6 +2489,8 @@ export const r = rumble({
2382
2489
  ...args,
2383
2490
  schema: builtSchema(),
2384
2491
  context,
2492
+ execute: buildTracedExecute(args.execute ?? defaultExecute, rumbleInput),
2493
+ subscribe: buildTracedSubscribe(args.subscribe ?? defaultSubscribe, rumbleInput),
2385
2494
  errorHandler(errors) {
2386
2495
  const span = trace.getActiveSpan();
2387
2496
  for (const error of errors) span?.recordException(error);
@@ -2394,7 +2503,9 @@ export const r = rumble({
2394
2503
  return implementation({
2395
2504
  ...args,
2396
2505
  schema: builtSchema(),
2397
- context
2506
+ context,
2507
+ execute: buildTracedExecute(args.execute ?? defaultExecute, rumbleInput),
2508
+ subscribe: buildTracedSubscribe(args.subscribe ?? defaultSubscribe, rumbleInput)
2398
2509
  }, ...rest);
2399
2510
  };
2400
2511
  return {