@getcronit/pylon 1.2.0 → 2.0.0-beta.2

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.
@@ -0,0 +1,70 @@
1
+ import { isOriginalGraphQLError, TypedExecutionArgs, type Plugin } from '@envelop/core';
2
+ import * as Sentry from '@sentry/node';
3
+ import type { TraceparentData } from '@sentry/types';
4
+ export type SentryPluginOptions<PluginContext extends Record<string, any>> = {
5
+ /**
6
+ * Starts a new transaction for every GraphQL Operation.
7
+ * When disabled, an already existing Transaction will be used.
8
+ *
9
+ * @default true
10
+ */
11
+ startTransaction?: boolean;
12
+ /**
13
+ * Renames Transaction.
14
+ * @default false
15
+ */
16
+ renameTransaction?: boolean;
17
+ /**
18
+ * Adds result of each resolver and operation to Span's data (available under "result")
19
+ * @default false
20
+ */
21
+ includeRawResult?: boolean;
22
+ /**
23
+ * Adds operation's variables to a Scope (only in case of errors)
24
+ * @default false
25
+ */
26
+ includeExecuteVariables?: boolean;
27
+ /**
28
+ * The key of the event id in the error's extension. `null` to disable.
29
+ * @default sentryEventId
30
+ */
31
+ eventIdKey?: string | null;
32
+ /**
33
+ * Adds custom tags to every Transaction.
34
+ */
35
+ appendTags?: (args: TypedExecutionArgs<PluginContext>) => Record<string, unknown>;
36
+ /**
37
+ * Callback to set context information onto the scope.
38
+ */
39
+ configureScope?: (args: TypedExecutionArgs<PluginContext>, scope: Sentry.Scope) => void;
40
+ /**
41
+ * Produces a name of Transaction (only when "renameTransaction" or "startTransaction" are enabled) and description of created Span.
42
+ *
43
+ * @default operation's name or "Anonymous Operation" when missing)
44
+ */
45
+ transactionName?: (args: TypedExecutionArgs<PluginContext>) => string;
46
+ /**
47
+ * Produces tracing data for Transaction
48
+ *
49
+ * @default is empty
50
+ */
51
+ traceparentData?: (args: TypedExecutionArgs<PluginContext>) => TraceparentData | undefined;
52
+ /**
53
+ * Produces a "op" (operation) of created Span.
54
+ *
55
+ * @default execute
56
+ */
57
+ operationName?: (args: TypedExecutionArgs<PluginContext>) => string;
58
+ /**
59
+ * Indicates whether or not to skip the entire Sentry flow for given GraphQL operation.
60
+ * By default, no operations are skipped.
61
+ */
62
+ skip?: (args: TypedExecutionArgs<PluginContext>) => boolean;
63
+ /**
64
+ * Indicates whether or not to skip Sentry exception reporting for a given error.
65
+ * By default, this plugin skips all `GraphQLError` errors and does not report it to Sentry.
66
+ */
67
+ skipError?: (args: Error) => boolean;
68
+ };
69
+ export declare const defaultSkipError: typeof isOriginalGraphQLError;
70
+ export declare const useSentry: <PluginContext extends Record<string, any> = {}>(options?: SentryPluginOptions<PluginContext>) => Plugin<PluginContext>;
@@ -0,0 +1,9 @@
1
+ import { Context } from '../../context';
2
+ export interface SchemaOptions {
3
+ typeDefs: string;
4
+ resolvers: {
5
+ Query: Record<string, any>;
6
+ Mutation: Record<string, any>;
7
+ };
8
+ }
9
+ export declare const graphqlHandler: (c: Context) => ({ typeDefs, resolvers }: SchemaOptions) => import("graphql-yoga").YogaServerInstance<{}, Context>;
@@ -0,0 +1,2 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ export declare const graphqlViewerHandler: MiddlewareHandler;
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ import { Env } from '../context';
3
+ export declare const app: Hono<Env, import("hono/types").BlankSchema, "/">;
package/dist/context.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { Context as HonoContext } from 'hono';
3
+ import type { Toucan } from 'toucan-js';
3
4
  import { AuthState } from './auth';
4
5
  import { AsyncLocalStorage } from 'async_hooks';
5
6
  export type Env = {
@@ -8,6 +9,7 @@ export type Env = {
8
9
  };
9
10
  Variables: {
10
11
  auth: AuthState;
12
+ sentry: Toucan;
11
13
  };
12
14
  };
13
15
  export type Context = HonoContext<Env, string, {}>;
@@ -1,38 +1,15 @@
1
- /// <reference types="bun-types" />
2
1
  import { GraphQLError, GraphQLErrorExtensions } from 'graphql';
3
- import { Hono as _Hono } from 'hono';
4
- import { Server, WebSocketHandler } from 'bun';
5
- import { Context, Env } from './context';
6
- export interface Resolvers<Q, M> {
7
- Query: Q;
8
- Mutation: M;
9
- }
10
- type WebSocketHandlerFunction<T extends Record<string, any>> = (server: Server) => WebSocketHandler<T>;
11
- type Hono = _Hono<Env>;
12
- export interface PylonAPI {
13
- defineService: typeof defineService;
14
- configureApp: (app: Hono) => Hono | void | Promise<void> | Promise<Hono>;
15
- configureServer: (server: Server) => void;
16
- configureWebsocket: WebSocketHandlerFunction<any>;
17
- }
18
- type SingleResolver = ((...args: any[]) => any) | object;
19
- type ReturnTypeOrContext<T> = T extends (...args: any) => any ? ReturnType<T> : Context;
20
- export declare const defineService: <Q extends Record<string, SingleResolver>, M, Options extends {
21
- context: (context: Context) => ReturnTypeOrContext<Options["context"]>;
22
- }>(plainResolvers: {
23
- Query?: Q | undefined;
24
- Mutation?: M | undefined;
25
- }, options?: Options | undefined) => {
26
- graphqlResolvers: GraphQLResolvers;
27
- plainResolvers: Resolvers<Q & {
28
- version: string;
29
- }, M>;
30
- getContext: () => ReturnType<Options["context"]>;
31
- };
32
- type GraphQLResolvers = {
2
+ import { Context } from './context';
3
+ export interface Resolvers {
33
4
  Query: Record<string, any>;
34
5
  Mutation: Record<string, any>;
35
- };
6
+ }
7
+ /**
8
+ * Converts a set of resolvers into a corresponding set of GraphQL resolvers.
9
+ * @param resolvers The original resolvers.
10
+ * @returns The converted GraphQL resolvers.
11
+ */
12
+ export declare const resolversToGraphQLResolvers: (resolvers: Resolvers, configureContext?: ((context: Context) => Context) | undefined) => Resolvers;
36
13
  export declare class ServiceError extends GraphQLError {
37
14
  extensions: GraphQLErrorExtensions;
38
15
  constructor(message: string, extensions: {
@@ -41,4 +18,3 @@ export declare class ServiceError extends GraphQLError {
41
18
  details?: Record<string, any>;
42
19
  }, error?: Error);
43
20
  }
44
- export {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { defineService, ServiceError, PylonAPI } from './define-pylon.js';
2
- export { logger, getLogger } from './logger/index.js';
1
+ export { ServiceError } from './define-pylon.js';
3
2
  export * from './auth/index.js';
4
3
  export { Context, Env, asyncContext, getContext, setContext } from './context.js';
4
+ export { app } from './app/index.js';
5
+ export { graphqlHandler } from './app/handler/graphql-handler.js';
package/dist/index.js CHANGED
@@ -89,21 +89,6 @@ function spreadFunctionArguments(fn) {
89
89
  return result;
90
90
  };
91
91
  }
92
- var defineService = (plainResolvers, options) => {
93
- const typedPlainResolvers = plainResolvers;
94
- typedPlainResolvers.Query = {
95
- ...typedPlainResolvers.Query,
96
- version: "NOT_IMPLEMENTED_YET"
97
- };
98
- const graphqlResolvers = resolversToGraphQLResolvers(typedPlainResolvers, options?.context);
99
- return {
100
- graphqlResolvers,
101
- plainResolvers: typedPlainResolvers,
102
- getContext: () => {
103
- return getContext();
104
- }
105
- };
106
- };
107
92
  var resolversToGraphQLResolvers = (resolvers, configureContext) => {
108
93
  const rootGraphqlResolver = (fn) => async (_, args, ctx, info) => {
109
94
  return Sentry.withScope(async (scope) => {
@@ -158,6 +143,11 @@ var resolversToGraphQLResolvers = (resolvers, configureContext) => {
158
143
  });
159
144
  };
160
145
  const graphqlResolvers = {};
146
+ for (const key of Object.keys(resolvers.Query)) {
147
+ if (!resolvers.Query[key]) {
148
+ delete resolvers.Query[key];
149
+ }
150
+ }
161
151
  if (resolvers.Query) {
162
152
  for (const [key, value] of Object.entries(resolvers.Query)) {
163
153
  if (!graphqlResolvers.Query) {
@@ -187,144 +177,11 @@ class ServiceError extends GraphQLError {
187
177
  this.cause = error;
188
178
  }
189
179
  }
190
- // src/logger/index.ts
191
- import winston from "winston";
192
-
193
- // src/logger/winston-sentry-transport.ts
194
- import * as Sentry2 from "@sentry/bun";
195
- import TransportStream from "winston-transport";
196
- var DEFAULT_LEVELS_MAP = {
197
- silly: "debug" /* Debug */,
198
- verbose: "debug" /* Debug */,
199
- info: "info" /* Info */,
200
- debug: "debug" /* Debug */,
201
- warn: "warning" /* Warning */,
202
- error: "error" /* Error */
203
- };
204
-
205
- class ExtendedError extends Error {
206
- constructor(info) {
207
- super(info.message);
208
- this.name = info.name || "Error";
209
- if (info.stack && typeof info.stack === "string") {
210
- this.stack = info.stack;
211
- }
212
- }
213
- }
214
-
215
- class SentryTransport extends TransportStream {
216
- silent = false;
217
- levelsMap = {};
218
- constructor(opts) {
219
- super(opts);
220
- this.levelsMap = this.setLevelsMap(opts && opts.levelsMap);
221
- this.silent = opts && opts.silent || false;
222
- if (!opts || !opts.skipSentryInit) {
223
- Sentry2.init(SentryTransport.withDefaults(opts && opts.sentry || {}));
224
- }
225
- }
226
- log(info, callback) {
227
- setImmediate(() => {
228
- this.emit("logged", info);
229
- });
230
- if (this.silent)
231
- return callback();
232
- const { message, tags, user, ...meta } = info;
233
- const winstonLevel = info["level"];
234
- const sentryLevel = this.levelsMap[winstonLevel];
235
- const scope = Sentry2.getCurrentScope();
236
- scope.clear();
237
- if (tags !== undefined && SentryTransport.isObject(tags)) {
238
- scope.setTags(tags);
239
- }
240
- scope.setExtras(meta);
241
- if (user !== undefined && SentryTransport.isObject(user)) {
242
- scope.setUser(user);
243
- }
244
- if (SentryTransport.shouldLogException(sentryLevel)) {
245
- const error = Object.values(info).find((value) => value instanceof Error) ?? new ExtendedError(info);
246
- Sentry2.captureException(error, { tags, level: sentryLevel });
247
- return callback();
248
- }
249
- Sentry2.captureMessage(message, sentryLevel);
250
- return callback();
251
- }
252
- end(...args) {
253
- Sentry2.flush().then(() => {
254
- super.end(...args);
255
- });
256
- return this;
257
- }
258
- get sentry() {
259
- return Sentry2;
260
- }
261
- setLevelsMap = (options) => {
262
- if (!options) {
263
- return DEFAULT_LEVELS_MAP;
264
- }
265
- const customLevelsMap = Object.keys(options).reduce((acc, winstonSeverity) => {
266
- acc[winstonSeverity] = options[winstonSeverity];
267
- return acc;
268
- }, {});
269
- return {
270
- ...DEFAULT_LEVELS_MAP,
271
- ...customLevelsMap
272
- };
273
- };
274
- static withDefaults(options) {
275
- return {
276
- ...options,
277
- dsn: options && options.dsn || process.env.SENTRY_DSN || "",
278
- serverName: options && options.serverName || "winston-transport-sentry-node",
279
- environment: options && options.environment || process.env.SENTRY_ENVIRONMENT || "development",
280
- debug: options && options.debug || !!process.env.SENTRY_DEBUG || false,
281
- sampleRate: options && options.sampleRate || 1,
282
- maxBreadcrumbs: options && options.maxBreadcrumbs || 100
283
- };
284
- }
285
- static isObject(obj) {
286
- const type = typeof obj;
287
- return type === "function" || type === "object" && !!obj;
288
- }
289
- static shouldLogException(level) {
290
- return level === "fatal" /* Fatal */ || level === "error" /* Error */;
291
- }
292
- }
293
-
294
- // src/logger/index.ts
295
- var mainLogger = winston.createLogger({
296
- format: winston.format.errors({ stack: true }),
297
- transports: [
298
- new winston.transports.Console({
299
- format: winston.format.combine(winston.format.colorize(), winston.format.timestamp({
300
- format: "YYYY-MM-DD HH:mm:ss"
301
- }), winston.format.errors({ stack: true }), winston.format.printf((info) => {
302
- const label = info.label ? `[${info.label}] ` : "";
303
- if (info.stack) {
304
- return `${label} ${info.timestamp} ${info.level}: ${info.stack}`;
305
- }
306
- return `${label} ${info.timestamp} ${info.level}: ${info.message}`;
307
- }))
308
- }),
309
- new SentryTransport({
310
- level: "info",
311
- skipSentryInit: true
312
- })
313
- ]
314
- });
315
- var logger = mainLogger;
316
- var getLogger = (moduleName) => {
317
- const childLogger = mainLogger.child({ label: moduleName });
318
- childLogger.child = (options) => {
319
- return getLogger(`${moduleName} -> ${options.label}`);
320
- };
321
- return childLogger;
322
- };
323
180
  // src/auth/index.ts
324
181
  import jwt from "jsonwebtoken";
325
182
  import path from "path";
326
183
  import {HTTPException as HTTPException2} from "hono/http-exception";
327
- import * as Sentry3 from "@sentry/bun";
184
+ import * as Sentry2 from "@sentry/bun";
328
185
 
329
186
  // src/auth/decorators/requireAuth.ts
330
187
  import {HTTPException} from "hono/http-exception";
@@ -392,9 +249,7 @@ var authInitialize = () => {
392
249
  if (!AUTH_ISSUER) {
393
250
  throw new Error("AUTH_ISSUER is not set");
394
251
  }
395
- logger.info(`AUTH_ISSUER: ${AUTH_ISSUER}`);
396
- logger.info(`AUTH_PROJECT_ID: ${AUTH_PROJECT_ID}`);
397
- const middleware = Sentry3.startSpan({
252
+ const middleware = Sentry2.startSpan({
398
253
  name: "AuthMiddleware",
399
254
  op: "auth"
400
255
  }, () => async function(ctx, next) {
@@ -497,7 +352,7 @@ var authInitialize = () => {
497
352
  const auth2 = await introspectToken(token);
498
353
  if (auth2.active) {
499
354
  ctx.set("auth", auth2);
500
- Sentry3.setUser({
355
+ Sentry2.setUser({
501
356
  id: auth2.sub,
502
357
  username: auth2.preferred_username,
503
358
  email: auth2.email,
@@ -542,16 +397,287 @@ var auth = {
542
397
  initialize: authInitialize,
543
398
  require: authRequire
544
399
  };
400
+ // src/app/index.ts
401
+ import {Hono} from "hono";
402
+ import {logger as logger2} from "hono/logger";
403
+ import {sentry as sentry2} from "@hono/sentry";
404
+
405
+ // src/app/handler/graphql-viewer-handler.ts
406
+ import {html as html2} from "hono/html";
407
+ var graphqlViewerHandler = async (c, next) => {
408
+ return c.html(html2`
409
+ <!DOCTYPE html>
410
+ <html>
411
+ <head>
412
+ <title>Pylon Viewer</title>
413
+ <script src="https://cdn.jsdelivr.net/npm/react@16/umd/react.production.min.js"></script>
414
+ <script src="https://cdn.jsdelivr.net/npm/react-dom@16/umd/react-dom.production.min.js"></script>
415
+
416
+ <link
417
+ rel="stylesheet"
418
+ href="https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.css"
419
+ />
420
+ <style>
421
+ body {
422
+ padding: 0;
423
+ margin: 0;
424
+ width: 100%;
425
+ height: 100vh;
426
+ overflow: hidden;
427
+ }
428
+
429
+ #voyager {
430
+ height: 100%;
431
+ position: relative;
432
+ }
433
+ }
434
+ </style>
435
+ <script src="https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.min.js"></script>
436
+ </head>
437
+ <body>
438
+ <div id="voyager">Loading...</div>
439
+ <script>
440
+ function introspectionProvider(introspectionQuery) {
441
+ // ... do a call to server using introspectionQuery provided
442
+ // or just return pre-fetched introspection
443
+
444
+ // Endpoint is current path instead of root/graphql
445
+ const endpoint = window.location.pathname.replace(
446
+ '/viewer',
447
+ '/graphql'
448
+ )
449
+
450
+ return fetch(endpoint, {
451
+ method: 'post',
452
+ headers: {
453
+ 'Content-Type': 'application/json'
454
+ },
455
+ body: JSON.stringify({query: introspectionQuery})
456
+ }).then(response => response.json())
457
+ }
458
+
459
+ // Render <Voyager />
460
+ GraphQLVoyager.init(document.getElementById('voyager'), {
461
+ introspection: introspectionProvider
462
+ })
463
+ </script>
464
+ </body>
465
+ </html>
466
+ `);
467
+ };
468
+
469
+ // src/app/index.ts
470
+ var app = new Hono;
471
+ app.use("*", sentry2());
472
+ app.use("*", async (c, next) => {
473
+ return new Promise((resolve, reject) => {
474
+ asyncContext.run(c, async () => {
475
+ try {
476
+ resolve(await next());
477
+ } catch (error) {
478
+ reject(error);
479
+ }
480
+ });
481
+ });
482
+ });
483
+ app.use("*", logger2());
484
+ app.use((c, next) => {
485
+ c.req.id = crypto.randomUUID();
486
+ return next();
487
+ });
488
+ app.get("/viewer", graphqlViewerHandler);
489
+ // src/app/handler/graphql-handler.ts
490
+ import {createSchema, createYoga} from "graphql-yoga";
491
+ import {GraphQLScalarType, Kind as Kind2} from "graphql";
492
+
493
+ // src/app/envelop/use-sentry.ts
494
+ import {Kind, print} from "graphql";
495
+ import {
496
+ getDocumentString,
497
+ handleStreamOrSingleExecutionResult,
498
+ isOriginalGraphQLError
499
+ } from "@envelop/core";
500
+ import * as Sentry3 from "@sentry/node";
501
+ var defaultSkipError = isOriginalGraphQLError;
502
+ var useSentry = (options = {}) => {
503
+ function pick(key, defaultValue) {
504
+ return options[key] ?? defaultValue;
505
+ }
506
+ const startTransaction = pick("startTransaction", true);
507
+ const includeRawResult = pick("includeRawResult", false);
508
+ const includeExecuteVariables = pick("includeExecuteVariables", false);
509
+ const renameTransaction = pick("renameTransaction", false);
510
+ const skipOperation = pick("skip", () => false);
511
+ const skipError = pick("skipError", defaultSkipError);
512
+ const eventIdKey = options.eventIdKey === null ? null : "sentryEventId";
513
+ function addEventId(err, eventId) {
514
+ if (eventIdKey !== null && eventId !== null) {
515
+ err.extensions[eventIdKey] = eventId;
516
+ }
517
+ return err;
518
+ }
519
+ return {
520
+ onExecute({ args }) {
521
+ if (skipOperation(args)) {
522
+ return;
523
+ }
524
+ const rootOperation = args.document.definitions.find((o) => o.kind === Kind.OPERATION_DEFINITION);
525
+ const operationType = rootOperation.operation;
526
+ const document = getDocumentString(args.document, print);
527
+ const opName = args.operationName || rootOperation.name?.value || "Anonymous Operation";
528
+ const addedTags = options.appendTags && options.appendTags(args) || {};
529
+ const traceparentData = options.traceparentData && options.traceparentData(args) || {};
530
+ const transactionName = options.transactionName ? options.transactionName(args) : opName;
531
+ const op = options.operationName ? options.operationName(args) : "execute";
532
+ const tags = {
533
+ operationName: opName,
534
+ operation: operationType,
535
+ ...addedTags
536
+ };
537
+ if (options.configureScope) {
538
+ options.configureScope(args, Sentry3.getCurrentScope());
539
+ }
540
+ return {
541
+ onExecuteDone(payload) {
542
+ const handleResult = ({
543
+ result,
544
+ setResult
545
+ }) => {
546
+ Sentry3.startSpanManual({
547
+ op,
548
+ name: opName,
549
+ attributes: tags
550
+ }, (span) => {
551
+ if (renameTransaction) {
552
+ span.updateName(transactionName);
553
+ }
554
+ span.setAttribute("document", document);
555
+ if (includeRawResult) {
556
+ span.setAttribute("result", JSON.stringify(result));
557
+ }
558
+ if (result.errors && result.errors.length > 0) {
559
+ Sentry3.withScope((scope) => {
560
+ scope.setTransactionName(opName);
561
+ scope.setTag("operation", operationType);
562
+ scope.setTag("operationName", opName);
563
+ scope.setExtra("document", document);
564
+ scope.setTags(addedTags || {});
565
+ if (includeRawResult) {
566
+ scope.setExtra("result", result);
567
+ }
568
+ if (includeExecuteVariables) {
569
+ scope.setExtra("variables", args.variableValues);
570
+ }
571
+ const errors = result.errors?.map((err) => {
572
+ if (skipError(err) === true) {
573
+ return err;
574
+ }
575
+ const errorPath = (err.path ?? []).map((v) => typeof v === "number" ? "$index" : v).join(" > ");
576
+ if (errorPath) {
577
+ scope.addBreadcrumb({
578
+ category: "execution-path",
579
+ message: errorPath,
580
+ level: "debug"
581
+ });
582
+ }
583
+ const eventId = Sentry3.captureException(err.originalError, {
584
+ fingerprint: [
585
+ "graphql",
586
+ errorPath,
587
+ opName,
588
+ operationType
589
+ ],
590
+ contexts: {
591
+ GraphQL: {
592
+ operationName: opName,
593
+ operationType,
594
+ variables: args.variableValues
595
+ }
596
+ }
597
+ });
598
+ return addEventId(err, eventId);
599
+ });
600
+ setResult({
601
+ ...result,
602
+ errors
603
+ });
604
+ });
605
+ }
606
+ span.end();
607
+ });
608
+ };
609
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
610
+ }
611
+ };
612
+ }
613
+ };
614
+ };
615
+
616
+ // src/app/handler/graphql-handler.ts
617
+ var graphqlHandler = (c) => ({ typeDefs, resolvers }) => {
618
+ for (const key in resolvers) {
619
+ if (Object.keys(resolvers[key]).length === 0) {
620
+ delete resolvers[key];
621
+ }
622
+ }
623
+ resolvers = resolversToGraphQLResolvers(resolvers);
624
+ const schema = createSchema({
625
+ typeDefs,
626
+ resolvers: {
627
+ ...resolvers,
628
+ Date: new GraphQLScalarType({
629
+ name: "Date",
630
+ description: "Date custom scalar type",
631
+ parseValue(value) {
632
+ if (typeof value === "string") {
633
+ return new Date(value);
634
+ }
635
+ if (value instanceof Date) {
636
+ return value;
637
+ }
638
+ throw Error("GraphQL Date Scalar parseValue expected a `Date` or string");
639
+ },
640
+ serialize(value) {
641
+ if (value instanceof Date) {
642
+ return value.toISOString();
643
+ }
644
+ throw Error("GraphQL Date Scalar serializer expected a `Date` object");
645
+ },
646
+ parseLiteral(ast) {
647
+ if (ast.kind === Kind2.INT) {
648
+ return new Date(parseInt(ast.value, 10));
649
+ } else if (ast.kind === Kind2.STRING) {
650
+ return new Date(ast.value);
651
+ }
652
+ return null;
653
+ }
654
+ })
655
+ }
656
+ });
657
+ const yoga = createYoga({
658
+ schema,
659
+ landingPage: false,
660
+ plugins: [useSentry()],
661
+ graphiql: (req) => {
662
+ return {
663
+ shouldPersistHeaders: true,
664
+ title: "Pylon Playground",
665
+ defaultQuery: `# Welcome to the Pylon Playground!`
666
+ };
667
+ },
668
+ context: c
669
+ });
670
+ return yoga;
671
+ };
545
672
  export {
546
673
  setContext,
547
674
  requireAuth,
548
- logger,
549
- getLogger,
675
+ graphqlHandler,
550
676
  getContext,
551
- defineService,
552
677
  auth,
553
678
  asyncContext,
679
+ app,
554
680
  ServiceError
555
681
  };
556
682
 
557
- //# debugId=1536EF647381168764756E2164756E21
683
+ //# debugId=29F7E5185902DF9E64756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/define-pylon.ts", "../src/context.ts", "../src/logger/index.ts", "../src/logger/winston-sentry-transport.ts", "../src/auth/index.ts", "../src/auth/decorators/requireAuth.ts"],
3
+ "sources": ["../src/define-pylon.ts", "../src/context.ts", "../src/auth/index.ts", "../src/auth/decorators/requireAuth.ts", "../src/app/index.ts", "../src/app/handler/graphql-viewer-handler.ts", "../src/app/handler/graphql-handler.ts", "../src/app/envelop/use-sentry.ts"],
4
4
  "sourcesContent": [
5
- "import {\n GraphQLError,\n GraphQLErrorExtensions,\n GraphQLResolveInfo,\n SelectionSetNode\n} from 'graphql'\nimport {Hono as _Hono} from 'hono'\nimport {Server, WebSocketHandler} from 'bun'\nimport * as Sentry from '@sentry/bun'\n\nimport {Context, Env, asyncContext, getContext} from './context'\n\nexport interface Resolvers<Q, M> {\n Query: Q\n Mutation: M\n}\n\ntype WebSocketHandlerFunction<T extends Record<string, any>> = (\n server: Server\n) => WebSocketHandler<T>\n\ntype Hono = _Hono<Env>\n\nexport interface PylonAPI {\n defineService: typeof defineService\n configureApp: (app: Hono) => Hono | void | Promise<void> | Promise<Hono>\n configureServer: (server: Server) => void\n configureWebsocket: WebSocketHandlerFunction<any>\n}\n\ntype SingleResolver = ((...args: any[]) => any) | object\n\ntype ReturnTypeOrContext<T> = T extends (...args: any) => any\n ? ReturnType<T>\n : Context\n\nexport const defineService = <\n Q extends Record<string, SingleResolver>,\n M,\n Options extends {\n context: (context: Context) => ReturnTypeOrContext<Options['context']>\n }\n>(\n plainResolvers: {\n Query?: Q\n Mutation?: M\n },\n options?: Options\n) => {\n const typedPlainResolvers = plainResolvers as Resolvers<\n Q & {\n version: string\n },\n M\n >\n\n typedPlainResolvers.Query = {\n ...typedPlainResolvers.Query,\n version: 'NOT_IMPLEMENTED_YET'\n }\n\n const graphqlResolvers = resolversToGraphQLResolvers(\n typedPlainResolvers,\n options?.context\n )\n\n return {\n graphqlResolvers,\n plainResolvers: typedPlainResolvers,\n getContext: () => {\n return getContext() as ReturnType<Options['context']>\n }\n }\n}\n\n// function getAllPropertyNames(obj: any) {\n// function getAllPrototypePropertyNames(obj: any) {\n// let prototypePropertyNames: string[] = []\n// let prototype = Object.getPrototypeOf(obj)\n\n// while (prototype !== null && prototype !== Object.prototype) {\n// prototypePropertyNames = prototypePropertyNames.concat(\n// Object.getOwnPropertyNames(prototype)\n// )\n// prototype = Object.getPrototypeOf(prototype)\n// }\n\n// return Array.from(new Set(prototypePropertyNames))\n// }\n\n// if (obj === null) return []\n\n// const prototypeNames = getAllPrototypePropertyNames(obj)\n// const ownNames = Object.getOwnPropertyNames(obj)\n\n// return Array.from(new Set(prototypeNames.concat(ownNames)))\n// }\n\ntype FunctionWrapper = (fn: (...args: any[]) => any) => (...args: any[]) => any\n\nasync function wrapFunctionsRecursively(\n obj: any,\n wrapper: FunctionWrapper,\n that: any = null,\n selectionSet: SelectionSetNode['selections'] = []\n): Promise<any> {\n // Skip if the object is a Date object or any other special object.\n // Those objects are then handled by custom resolvers.\n if (obj === null || obj instanceof Date) {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return await Promise.all(\n obj.map(async item => {\n return await wrapFunctionsRecursively(item, wrapper, that, selectionSet)\n })\n )\n } else if (typeof obj === 'function') {\n return Sentry.startSpan(\n {\n name: obj.name,\n op: 'pylon.fn'\n },\n async () => {\n // @ts-ignore\n return await wrapper.call(that, obj, selectionSet)\n }\n )\n } else if (obj instanceof Promise) {\n return await wrapFunctionsRecursively(\n await obj,\n wrapper,\n that,\n selectionSet\n )\n } else if (typeof obj === 'object') {\n const result: any = {}\n\n const fields: {\n key: string\n selectionSet: SelectionSetNode['selections']\n }[] = []\n\n that = obj\n\n for (const selection of selectionSet) {\n if (selection.kind === 'Field') {\n selection.selectionSet\n\n fields.push({\n key: selection.name.value,\n selectionSet: selection.selectionSet?.selections || []\n })\n }\n }\n\n for (const {key, selectionSet} of Object.values(fields)) {\n result[key] = await wrapFunctionsRecursively(\n obj[key],\n wrapper,\n that,\n selectionSet\n )\n }\n\n // If no fields were selected, return the original object.\n if (Object.keys(result).length === 0) {\n return obj\n }\n\n return result\n } else {\n return await obj\n }\n}\nfunction spreadFunctionArguments<T extends (...args: any[]) => any>(fn: T) {\n return (otherArgs: Record<string, any>, c: any, info: GraphQLResolveInfo) => {\n const selections = arguments[1] as SelectionSetNode['selections']\n\n let args: Record<string, any> = {}\n\n if (info) {\n const type = info.parentType\n\n const field = type.getFields()[info.fieldName]\n\n const fieldArguments = field?.args\n\n const preparedArguments = fieldArguments?.reduce(\n (acc: {[x: string]: undefined}, arg: {name: string | number}) => {\n if (otherArgs[arg.name] !== undefined) {\n acc[arg.name] = otherArgs[arg.name]\n } else {\n acc[arg.name] = undefined\n }\n\n return acc\n },\n {} as Record<string, any>\n )\n\n if (preparedArguments) {\n args = preparedArguments\n }\n } else {\n args = otherArgs\n }\n\n const orderedArgs = Object.keys(args).map(key => args[key])\n\n const that = this || {}\n\n const result = wrapFunctionsRecursively(\n fn.call(that, ...orderedArgs),\n spreadFunctionArguments,\n this,\n selections\n )\n\n return result as ReturnType<typeof fn>\n }\n}\ntype GraphQLResolvers = {\n Query: Record<string, any>\n Mutation: Record<string, any>\n}\n\n/**\n * Converts a set of resolvers into a corresponding set of GraphQL resolvers.\n * @param resolvers The original resolvers.\n * @returns The converted GraphQL resolvers.\n */\nconst resolversToGraphQLResolvers = <Q, M>(\n resolvers: Resolvers<Q, M>,\n configureContext?: (context: Context) => Context\n): GraphQLResolvers => {\n // Define a root resolver function that maps a given resolver function or object to a GraphQL resolver.\n const rootGraphqlResolver =\n (fn: Function | object | Promise<Function> | Promise<object>) =>\n async (_: object, args: Record<string, any>, ctx: Context, info: any) => {\n return Sentry.withScope(async scope => {\n const ctx = asyncContext.getStore()\n\n if (!ctx) {\n throw new Error('Internal error. Context not defined.')\n }\n\n const auth = ctx.get('auth')\n\n if (auth?.active) {\n scope.setUser({\n id: auth.sub,\n username: auth.preferred_username,\n email: auth.email,\n details: auth\n })\n }\n\n if (configureContext) {\n const configuredCtx = await Sentry.startSpan(\n {\n name: 'Context',\n op: 'pylon.context'\n },\n () => configureContext(ctx)\n )\n\n asyncContext.enterWith(configuredCtx)\n }\n\n // get query or mutation field\n\n const isQuery = info.operation.operation === 'query'\n const isMutation = info.operation.operation === 'mutation'\n\n if (!isQuery && !isMutation) {\n throw new Error('Only queries and mutations are supported.')\n }\n\n // Get the field metadata for the current query or mutation.\n const type = isQuery\n ? info.schema.getQueryType()\n : info.schema.getMutationType()\n\n const field = type?.getFields()[info.fieldName]\n\n // Get the list of arguments expected by the current query field.\n const fieldArguments = field?.args || []\n\n // Prepare the arguments for the resolver function call by adding any missing arguments with an undefined value.\n const preparedArguments = fieldArguments.reduce(\n (acc: {[x: string]: undefined}, arg: {name: string | number}) => {\n if (args[arg.name] !== undefined) {\n acc[arg.name] = args[arg.name]\n } else {\n acc[arg.name] = undefined\n }\n\n return acc\n },\n {} as Record<string, any>\n )\n\n // Determine the resolver function to call (either the given function or the wrappedWithContext function if it exists).\n let inner = await fn\n\n let baseSelectionSet: SelectionSetNode['selections'] = []\n\n // Find the selection set for the current field.\n for (const selection of info.operation.selectionSet.selections) {\n if (\n selection.kind === 'Field' &&\n selection.name.value === info.fieldName\n ) {\n baseSelectionSet = selection.selectionSet?.selections || []\n }\n }\n\n // Wrap the resolver function with any required middleware.\n const wrappedFn = await wrapFunctionsRecursively(\n inner,\n spreadFunctionArguments,\n this,\n baseSelectionSet\n )\n\n // Call the resolver function with the prepared arguments.\n if (typeof wrappedFn !== 'function') {\n return wrappedFn\n }\n\n return await wrappedFn(preparedArguments)\n })\n }\n\n // Convert the Query and Mutation resolvers to GraphQL resolvers.\n const graphqlResolvers = {} as GraphQLResolvers\n\n if (resolvers.Query) {\n for (const [key, value] of Object.entries(resolvers.Query)) {\n if (!graphqlResolvers.Query) {\n graphqlResolvers.Query = {}\n }\n\n graphqlResolvers.Query[key] = rootGraphqlResolver(\n value as Function | object\n )\n }\n }\n\n if (resolvers.Mutation) {\n if (!graphqlResolvers.Mutation) {\n graphqlResolvers.Mutation = {}\n }\n\n for (const [key, value] of Object.entries(resolvers.Mutation)) {\n graphqlResolvers.Mutation[key] = rootGraphqlResolver(\n value as Function | object\n )\n }\n }\n\n return graphqlResolvers\n}\n\nexport class ServiceError extends GraphQLError {\n extensions: GraphQLErrorExtensions\n\n constructor(\n message: string,\n extensions: {\n code: string\n statusCode: number\n details?: Record<string, any>\n },\n error?: Error\n ) {\n super(message, {\n originalError: error\n })\n this.extensions = extensions\n this.cause = error\n }\n}\n",
6
- "import {Context as HonoContext} from 'hono'\nimport {AuthState} from './auth'\nimport {AsyncLocalStorage} from 'async_hooks'\n\nexport type Env = {\n Bindings: {\n NODE_ENV: string\n }\n Variables: {\n auth: AuthState\n }\n}\n\nexport type Context = HonoContext<Env, string, {}>\n\nexport const asyncContext = new AsyncLocalStorage<Context>()\n\nexport const getContext = () => {\n const ctx = asyncContext.getStore()\n\n if (!ctx) {\n throw new Error('Context not defined')\n }\n\n return ctx\n}\n\nexport const setContext = (context: Context) => {\n return asyncContext.enterWith(context)\n}\n",
7
- "import winston from 'winston'\n\nimport WinstonSentryTransport from './winston-sentry-transport'\n\nconst mainLogger = winston.createLogger({\n format: winston.format.errors({stack: true}),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.timestamp({\n format: 'YYYY-MM-DD HH:mm:ss'\n }),\n winston.format.errors({stack: true}),\n winston.format.printf(info => {\n const label = info.label ? `[${info.label}] ` : ''\n\n if (info.stack) {\n return `${label} ${info.timestamp} ${info.level}: ${info.stack}`\n }\n return `${label} ${info.timestamp} ${info.level}: ${info.message}`\n })\n )\n }),\n new WinstonSentryTransport({\n level: 'info',\n skipSentryInit: true\n })\n ]\n})\n\n/**\n * @deprecated Use `getLogger` instead\n *\n * import {getLogger} from '@getcronit/pylon'\n *\n * const logger = getLogger(__filename)\n */\nexport const logger = mainLogger\n\n// Define the getLogger function\nexport const getLogger = (moduleName?: string): winston.Logger => {\n const childLogger = mainLogger.child({label: moduleName})\n\n // Override the child logger's child method to extend the label\n childLogger.child = (options: {label: string}) => {\n return getLogger(`${moduleName} -> ${options.label}`)\n }\n\n return childLogger\n}\n",
8
- "import * as Sentry from '@sentry/bun'\nimport TransportStream from 'winston-transport'\n\nenum SentrySeverity {\n Debug = 'debug',\n Log = 'log',\n Info = 'info',\n Warning = 'warning',\n Error = 'error',\n Fatal = 'fatal'\n}\n\nconst DEFAULT_LEVELS_MAP: SeverityOptions = {\n silly: SentrySeverity.Debug,\n verbose: SentrySeverity.Debug,\n info: SentrySeverity.Info,\n debug: SentrySeverity.Debug,\n warn: SentrySeverity.Warning,\n error: SentrySeverity.Error\n}\n\nexport interface SentryTransportOptions\n extends TransportStream.TransportStreamOptions {\n sentry?: Sentry.BunOptions\n levelsMap?: SeverityOptions\n skipSentryInit?: boolean\n}\n\ninterface SeverityOptions {\n [key: string]: Sentry.SeverityLevel\n}\n\nclass ExtendedError extends Error {\n constructor(info: any) {\n super(info.message)\n\n this.name = info.name || 'Error'\n if (info.stack && typeof info.stack === 'string') {\n this.stack = info.stack\n }\n }\n}\n\nexport default class SentryTransport extends TransportStream {\n public silent = false\n\n private levelsMap: SeverityOptions = {}\n\n public constructor(opts?: SentryTransportOptions) {\n super(opts)\n\n this.levelsMap = this.setLevelsMap(opts && opts.levelsMap)\n this.silent = (opts && opts.silent) || false\n\n if (!opts || !opts.skipSentryInit) {\n Sentry.init(SentryTransport.withDefaults((opts && opts.sentry) || {}))\n }\n }\n\n public log(info: any, callback: () => void) {\n setImmediate(() => {\n this.emit('logged', info)\n })\n\n if (this.silent) return callback()\n\n const {message, tags, user, ...meta} = info\n const winstonLevel = info['level']\n\n const sentryLevel = this.levelsMap[winstonLevel]\n\n const scope = Sentry.getCurrentScope()\n\n scope.clear()\n\n if (tags !== undefined && SentryTransport.isObject(tags)) {\n scope.setTags(tags)\n }\n\n scope.setExtras(meta)\n\n if (user !== undefined && SentryTransport.isObject(user)) {\n scope.setUser(user)\n }\n\n // TODO: add fingerprints\n // scope.setFingerprint(['{{ default }}', path]); // fingerprint should be an array\n\n // scope.clear();\n\n // TODO: add breadcrumbs\n // Sentry.addBreadcrumb({\n // message: 'My Breadcrumb',\n // // ...\n // });\n\n // Capturing Errors / Exceptions\n if (SentryTransport.shouldLogException(sentryLevel)) {\n const error =\n Object.values(info).find(value => value instanceof Error) ??\n new ExtendedError(info)\n Sentry.captureException(error, {tags, level: sentryLevel})\n\n return callback()\n }\n\n // Capturing Messages\n Sentry.captureMessage(message, sentryLevel)\n return callback()\n }\n\n end(...args: any[]) {\n Sentry.flush().then(() => {\n super.end(...args)\n })\n return this\n }\n\n public get sentry() {\n return Sentry\n }\n\n private setLevelsMap = (options?: SeverityOptions): SeverityOptions => {\n if (!options) {\n return DEFAULT_LEVELS_MAP\n }\n\n const customLevelsMap = Object.keys(options).reduce<SeverityOptions>(\n (acc: {[key: string]: any}, winstonSeverity: string) => {\n acc[winstonSeverity] = options[winstonSeverity]\n return acc\n },\n {}\n )\n\n return {\n ...DEFAULT_LEVELS_MAP,\n ...customLevelsMap\n }\n }\n\n private static withDefaults(options: Sentry.BunOptions) {\n return {\n ...options,\n dsn: (options && options.dsn) || process.env.SENTRY_DSN || '',\n serverName:\n (options && options.serverName) || 'winston-transport-sentry-node',\n environment:\n (options && options.environment) ||\n process.env.SENTRY_ENVIRONMENT ||\n process.env.NODE_ENV ||\n 'production',\n debug: (options && options.debug) || !!process.env.SENTRY_DEBUG || false,\n sampleRate: (options && options.sampleRate) || 1.0,\n maxBreadcrumbs: (options && options.maxBreadcrumbs) || 100\n }\n }\n\n // private normalizeMessage(msg: any) {\n // return msg && msg.message ? msg.message : msg;\n // }\n\n private static isObject(obj: any) {\n const type = typeof obj\n return type === 'function' || (type === 'object' && !!obj)\n }\n\n private static shouldLogException(level: Sentry.SeverityLevel) {\n return level === SentrySeverity.Fatal || level === SentrySeverity.Error\n }\n}\n",
9
- "import {MiddlewareHandler} from 'hono'\nimport jwt from 'jsonwebtoken'\nimport type {IdTokenClaims, IntrospectionResponse} from 'openid-client'\nimport path from 'path'\nimport {HTTPException} from 'hono/http-exception'\nimport {StatusCode} from 'hono/utils/http-status'\nimport * as Sentry from '@sentry/bun'\nimport {logger} from '../logger'\n\nconst AUTH_PROJECT_ID = process.env.AUTH_PROJECT_ID\n\nexport type AuthState = IntrospectionResponse &\n IdTokenClaims & {\n roles: string[]\n }\n\nconst authInitialize = () => {\n // Load private key file from cwd\n const authKeyFilePath = path.join(process.cwd(), 'key.json')\n\n const authKey = process.env.AUTH_KEY\n\n // Load private key file from cwd\n const API_PRIVATE_KEY_FILE: {\n type: 'application'\n keyId: string\n key: string\n appId: string\n clientId: string\n } = authKey ? JSON.parse(authKey) : require(authKeyFilePath)\n\n const AUTH_ISSUER = process.env.AUTH_ISSUER\n\n if (!AUTH_ISSUER) {\n throw new Error('AUTH_ISSUER is not set')\n }\n\n logger.info(`AUTH_ISSUER: ${AUTH_ISSUER}`)\n logger.info(`AUTH_PROJECT_ID: ${AUTH_PROJECT_ID}`)\n\n const middleware: MiddlewareHandler<{\n Variables: {\n auth: AuthState\n }\n }> = Sentry.startSpan(\n {\n name: 'AuthMiddleware',\n op: 'auth'\n },\n () =>\n async function (ctx, next) {\n const ZITADEL_INTROSPECTION_URL = `${AUTH_ISSUER}/oauth/v2/introspect`\n\n async function getRolesFromToken(tokenString: string) {\n const response = await fetch(\n `${AUTH_ISSUER}/auth/v1/usergrants/me/_search`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${tokenString}`\n }\n }\n )\n\n const data = (await response.json()) as any\n\n const userRoles = (data.result?.map((grant: any) => {\n return (grant.roles || []).map((role: any) => {\n return `${grant.projectId}:${role}`\n })\n }) || []) as string[][]\n\n const projectScopedRoles = userRoles.flat()\n\n const rolesSet = new Set(projectScopedRoles)\n\n // Add unscoped roles based on project id\n // This is useful so that it is not necessary to specify the project id for every role check\n if (AUTH_PROJECT_ID) {\n for (const role of projectScopedRoles) {\n const [projectId, ...roleNameParts] = role.split(':')\n\n const roleName = roleNameParts.join(':')\n\n if (projectId === AUTH_PROJECT_ID) {\n rolesSet.add(roleName)\n }\n }\n }\n\n return Array.from(rolesSet)\n }\n\n async function introspectToken(\n tokenString: string\n ): Promise<AuthState> {\n // Create JWT for client assertion\n const payload = {\n iss: API_PRIVATE_KEY_FILE.clientId,\n sub: API_PRIVATE_KEY_FILE.clientId,\n aud: AUTH_ISSUER,\n exp: Math.floor(Date.now() / 1000) + 60 * 60, // Expires in 1 hour\n iat: Math.floor(Date.now() / 1000)\n }\n\n const headers = {\n alg: 'RS256',\n kid: API_PRIVATE_KEY_FILE.keyId\n }\n const jwtToken = jwt.sign(payload, API_PRIVATE_KEY_FILE.key, {\n algorithm: 'RS256',\n header: headers\n })\n\n const scopeSet = new Set<string>()\n\n scopeSet.add('openid')\n scopeSet.add('profile')\n scopeSet.add('email')\n\n if (AUTH_PROJECT_ID) {\n scopeSet.add(\n `urn:zitadel:iam:org:project:id:${AUTH_PROJECT_ID}:aud`\n )\n }\n\n const scope = Array.from(scopeSet).join(' ')\n\n // Send introspection request\n const body = new URLSearchParams({\n client_assertion_type:\n 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n client_assertion: jwtToken,\n token: tokenString,\n scope\n }).toString()\n\n try {\n const response = await fetch(ZITADEL_INTROSPECTION_URL, {\n method: 'POST',\n headers: {'Content-Type': 'application/x-www-form-urlencoded'},\n body\n })\n\n if (!response.ok) {\n throw new Error('Network response was not ok')\n }\n\n const tokenData = (await response.json()) as IntrospectionResponse\n\n const roles = await getRolesFromToken(tokenString)\n\n const state = {\n ...tokenData,\n roles\n } as AuthState\n\n return state\n } catch (error) {\n console.error('Error while introspecting token', error)\n throw new Error('Token introspection failed')\n }\n }\n\n let token: string | undefined = undefined\n\n if (ctx.req.header('Authorization')) {\n const authHeader = ctx.req.header('Authorization')\n\n if (authHeader) {\n const parts = authHeader.split(' ')\n\n if (parts.length === 2 && parts[0] === 'Bearer') {\n token = parts[1]\n }\n }\n }\n\n if (!token) {\n const queryToken = ctx.req.query('token')\n\n if (queryToken) {\n token = queryToken\n }\n }\n\n if (token) {\n const auth = await introspectToken(token)\n\n if (auth.active) {\n ctx.set('auth', auth)\n\n Sentry.setUser({\n id: auth.sub,\n username: auth.preferred_username,\n email: auth.email,\n details: auth\n })\n }\n }\n\n return next()\n }\n )\n\n return middleware\n}\n\nexport type AuthRequireChecks = {\n roles?: string[]\n}\n\nconst authRequire = (checks: AuthRequireChecks = {}) => {\n const middleware: MiddlewareHandler<{\n Variables: {\n auth?: AuthState\n }\n }> = async (ctx, next) => {\n // Check if user is authenticated\n const auth = ctx.get('auth')\n\n if (!auth) {\n throw new HTTPException(401, {\n message: 'Authentication required'\n })\n }\n\n if (checks.roles) {\n const roles = auth.roles\n\n const hasRole = checks.roles.some(role => {\n return (\n roles.includes(role) || roles.includes(`${AUTH_PROJECT_ID}:${role}`)\n )\n })\n\n if (!hasRole) {\n const resError = new Response('Forbidden', {\n status: 403,\n statusText: 'Forbidden',\n headers: {\n 'Missing-Roles': checks.roles.join(','),\n 'Obtained-Roles': roles.join(',')\n }\n })\n\n throw new HTTPException(resError.status as StatusCode, {res: resError})\n }\n }\n\n return next()\n }\n\n return middleware\n}\n\nexport const auth = {\n initialize: authInitialize,\n require: authRequire\n}\n\nexport {requireAuth} from './decorators/requireAuth'\n",
10
- "import {ServiceError} from '../../define-pylon'\nimport {AuthRequireChecks, auth} from '..'\nimport {HTTPException} from 'hono/http-exception'\nimport {getContext} from '../../context'\n\nexport function requireAuth(checks?: AuthRequireChecks) {\n const checkAuth = async (c: any) => {\n const ctx = await c\n\n try {\n await auth.require(checks)(ctx, async () => {})\n } catch (e) {\n if (e instanceof HTTPException) {\n if (e.status === 401) {\n throw new ServiceError(e.message, {\n statusCode: 401,\n code: 'AUTH_REQUIRED'\n })\n } else if (e.status === 403) {\n const res = e.getResponse()\n\n throw new ServiceError(res.statusText, {\n statusCode: res.status,\n code: 'AUTHORIZATION_REQUIRED',\n details: {\n missingRoles: res.headers.get('Missing-Roles')?.split(','),\n obtainedRoles: res.headers.get('Obtained-Roles')?.split(',')\n }\n })\n } else {\n throw e\n }\n }\n\n throw e\n }\n }\n\n return function fn(...args: any[]) {\n const target: any = args[0]\n const propertyKey: string = args[1]\n const descriptor: PropertyDescriptor = args[2]\n\n if (descriptor) {\n const originalMethod = descriptor.value\n\n descriptor.value = async function (...args: any[]) {\n await checkAuth(getContext())\n\n return originalMethod.apply(this, args)\n }\n } else {\n Object.defineProperty(target, propertyKey, {\n get: async function () {\n await checkAuth(getContext())\n\n return this._value\n },\n set: function (newValue) {\n this._value = newValue\n }\n })\n }\n }\n}\n"
5
+ "import {\n GraphQLError,\n GraphQLErrorExtensions,\n GraphQLResolveInfo,\n SelectionSetNode\n} from 'graphql'\nimport {Hono as _Hono} from 'hono'\nimport * as Sentry from '@sentry/bun'\n\nimport {Context, Env, asyncContext, getContext} from './context'\n\nexport interface Resolvers {\n Query: Record<string, any>\n Mutation: Record<string, any>\n}\n\ntype FunctionWrapper = (fn: (...args: any[]) => any) => (...args: any[]) => any\n\nasync function wrapFunctionsRecursively(\n obj: any,\n wrapper: FunctionWrapper,\n that: any = null,\n selectionSet: SelectionSetNode['selections'] = []\n): Promise<any> {\n // Skip if the object is a Date object or any other special object.\n // Those objects are then handled by custom resolvers.\n if (obj === null || obj instanceof Date) {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return await Promise.all(\n obj.map(async item => {\n return await wrapFunctionsRecursively(item, wrapper, that, selectionSet)\n })\n )\n } else if (typeof obj === 'function') {\n return Sentry.startSpan(\n {\n name: obj.name,\n op: 'pylon.fn'\n },\n async () => {\n // @ts-ignore\n return await wrapper.call(that, obj, selectionSet)\n }\n )\n } else if (obj instanceof Promise) {\n return await wrapFunctionsRecursively(\n await obj,\n wrapper,\n that,\n selectionSet\n )\n } else if (typeof obj === 'object') {\n const result: any = {}\n\n const fields: {\n key: string\n selectionSet: SelectionSetNode['selections']\n }[] = []\n\n that = obj\n\n for (const selection of selectionSet) {\n if (selection.kind === 'Field') {\n selection.selectionSet\n\n fields.push({\n key: selection.name.value,\n selectionSet: selection.selectionSet?.selections || []\n })\n }\n }\n\n for (const {key, selectionSet} of Object.values(fields)) {\n result[key] = await wrapFunctionsRecursively(\n obj[key],\n wrapper,\n that,\n selectionSet\n )\n }\n\n // If no fields were selected, return the original object.\n if (Object.keys(result).length === 0) {\n return obj\n }\n\n return result\n } else {\n return await obj\n }\n}\nfunction spreadFunctionArguments<T extends (...args: any[]) => any>(fn: T) {\n return (otherArgs: Record<string, any>, c: any, info: GraphQLResolveInfo) => {\n const selections = arguments[1] as SelectionSetNode['selections']\n\n let args: Record<string, any> = {}\n\n if (info) {\n const type = info.parentType\n\n const field = type.getFields()[info.fieldName]\n\n const fieldArguments = field?.args\n\n const preparedArguments = fieldArguments?.reduce(\n (acc: {[x: string]: undefined}, arg: {name: string | number}) => {\n if (otherArgs[arg.name] !== undefined) {\n acc[arg.name] = otherArgs[arg.name]\n } else {\n acc[arg.name] = undefined\n }\n\n return acc\n },\n {} as Record<string, any>\n )\n\n if (preparedArguments) {\n args = preparedArguments\n }\n } else {\n args = otherArgs\n }\n\n const orderedArgs = Object.keys(args).map(key => args[key])\n\n const that = this || {}\n\n const result = wrapFunctionsRecursively(\n fn.call(that, ...orderedArgs),\n spreadFunctionArguments,\n this,\n selections\n )\n\n return result as ReturnType<typeof fn>\n }\n}\n\n/**\n * Converts a set of resolvers into a corresponding set of GraphQL resolvers.\n * @param resolvers The original resolvers.\n * @returns The converted GraphQL resolvers.\n */\nexport const resolversToGraphQLResolvers = (\n resolvers: Resolvers,\n configureContext?: (context: Context) => Context\n): Resolvers => {\n // Define a root resolver function that maps a given resolver function or object to a GraphQL resolver.\n const rootGraphqlResolver =\n (fn: Function | object | Promise<Function> | Promise<object>) =>\n async (_: object, args: Record<string, any>, ctx: Context, info: any) => {\n return Sentry.withScope(async scope => {\n const ctx = asyncContext.getStore()\n\n if (!ctx) {\n throw new Error('Internal error. Context not defined.')\n }\n\n const auth = ctx.get('auth')\n\n if (auth?.active) {\n scope.setUser({\n id: auth.sub,\n username: auth.preferred_username,\n email: auth.email,\n details: auth\n })\n }\n\n if (configureContext) {\n const configuredCtx = await Sentry.startSpan(\n {\n name: 'Context',\n op: 'pylon.context'\n },\n () => configureContext(ctx)\n )\n\n asyncContext.enterWith(configuredCtx)\n }\n\n // get query or mutation field\n\n const isQuery = info.operation.operation === 'query'\n const isMutation = info.operation.operation === 'mutation'\n\n if (!isQuery && !isMutation) {\n throw new Error('Only queries and mutations are supported.')\n }\n\n // Get the field metadata for the current query or mutation.\n const type = isQuery\n ? info.schema.getQueryType()\n : info.schema.getMutationType()\n\n const field = type?.getFields()[info.fieldName]\n\n // Get the list of arguments expected by the current query field.\n const fieldArguments = field?.args || []\n\n // Prepare the arguments for the resolver function call by adding any missing arguments with an undefined value.\n const preparedArguments = fieldArguments.reduce(\n (acc: {[x: string]: undefined}, arg: {name: string | number}) => {\n if (args[arg.name] !== undefined) {\n acc[arg.name] = args[arg.name]\n } else {\n acc[arg.name] = undefined\n }\n\n return acc\n },\n {} as Record<string, any>\n )\n\n // Determine the resolver function to call (either the given function or the wrappedWithContext function if it exists).\n let inner = await fn\n\n let baseSelectionSet: SelectionSetNode['selections'] = []\n\n // Find the selection set for the current field.\n for (const selection of info.operation.selectionSet.selections) {\n if (\n selection.kind === 'Field' &&\n selection.name.value === info.fieldName\n ) {\n baseSelectionSet = selection.selectionSet?.selections || []\n }\n }\n\n // Wrap the resolver function with any required middleware.\n const wrappedFn = await wrapFunctionsRecursively(\n inner,\n spreadFunctionArguments,\n this,\n baseSelectionSet\n )\n\n // Call the resolver function with the prepared arguments.\n if (typeof wrappedFn !== 'function') {\n return wrappedFn\n }\n\n return await wrappedFn(preparedArguments)\n })\n }\n\n // Convert the Query and Mutation resolvers to GraphQL resolvers.\n const graphqlResolvers = {} as Resolvers\n\n // Remove empty resolvers\n for (const key of Object.keys(resolvers.Query)) {\n if (!resolvers.Query[key]) {\n delete resolvers.Query[key]\n }\n }\n\n if (resolvers.Query) {\n for (const [key, value] of Object.entries(resolvers.Query)) {\n if (!graphqlResolvers.Query) {\n graphqlResolvers.Query = {}\n }\n\n graphqlResolvers.Query[key] = rootGraphqlResolver(\n value as Function | object\n )\n }\n }\n\n if (resolvers.Mutation) {\n if (!graphqlResolvers.Mutation) {\n graphqlResolvers.Mutation = {}\n }\n\n for (const [key, value] of Object.entries(resolvers.Mutation)) {\n graphqlResolvers.Mutation[key] = rootGraphqlResolver(\n value as Function | object\n )\n }\n }\n\n return graphqlResolvers\n}\n\nexport class ServiceError extends GraphQLError {\n extensions: GraphQLErrorExtensions\n\n constructor(\n message: string,\n extensions: {\n code: string\n statusCode: number\n details?: Record<string, any>\n },\n error?: Error\n ) {\n super(message, {\n originalError: error\n })\n this.extensions = extensions\n this.cause = error\n }\n}\n",
6
+ "import {Context as HonoContext} from 'hono'\nimport type {Toucan} from 'toucan-js'\nimport {AuthState} from './auth'\nimport {AsyncLocalStorage} from 'async_hooks'\n\nexport type Env = {\n Bindings: {\n NODE_ENV: string\n }\n Variables: {\n auth: AuthState\n sentry: Toucan\n }\n}\n\nexport type Context = HonoContext<Env, string, {}>\n\nexport const asyncContext = new AsyncLocalStorage<Context>()\n\nexport const getContext = () => {\n const ctx = asyncContext.getStore()\n\n if (!ctx) {\n throw new Error('Context not defined')\n }\n\n return ctx\n}\n\nexport const setContext = (context: Context) => {\n return asyncContext.enterWith(context)\n}\n",
7
+ "import {MiddlewareHandler} from 'hono'\nimport jwt from 'jsonwebtoken'\nimport type {IdTokenClaims, IntrospectionResponse} from 'openid-client'\nimport path from 'path'\nimport {HTTPException} from 'hono/http-exception'\nimport {StatusCode} from 'hono/utils/http-status'\nimport * as Sentry from '@sentry/bun'\n\nconst AUTH_PROJECT_ID = process.env.AUTH_PROJECT_ID\n\nexport type AuthState = IntrospectionResponse &\n IdTokenClaims & {\n roles: string[]\n }\n\nconst authInitialize = () => {\n // Load private key file from cwd\n const authKeyFilePath = path.join(process.cwd(), 'key.json')\n\n const authKey = process.env.AUTH_KEY\n\n // Load private key file from cwd\n const API_PRIVATE_KEY_FILE: {\n type: 'application'\n keyId: string\n key: string\n appId: string\n clientId: string\n } = authKey ? JSON.parse(authKey) : require(authKeyFilePath)\n\n const AUTH_ISSUER = process.env.AUTH_ISSUER\n\n if (!AUTH_ISSUER) {\n throw new Error('AUTH_ISSUER is not set')\n }\n\n const middleware: MiddlewareHandler<{\n Variables: {\n auth: AuthState\n }\n }> = Sentry.startSpan(\n {\n name: 'AuthMiddleware',\n op: 'auth'\n },\n () =>\n async function (ctx, next) {\n const ZITADEL_INTROSPECTION_URL = `${AUTH_ISSUER}/oauth/v2/introspect`\n\n async function getRolesFromToken(tokenString: string) {\n const response = await fetch(\n `${AUTH_ISSUER}/auth/v1/usergrants/me/_search`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${tokenString}`\n }\n }\n )\n\n const data = (await response.json()) as any\n\n const userRoles = (data.result?.map((grant: any) => {\n return (grant.roles || []).map((role: any) => {\n return `${grant.projectId}:${role}`\n })\n }) || []) as string[][]\n\n const projectScopedRoles = userRoles.flat()\n\n const rolesSet = new Set(projectScopedRoles)\n\n // Add unscoped roles based on project id\n // This is useful so that it is not necessary to specify the project id for every role check\n if (AUTH_PROJECT_ID) {\n for (const role of projectScopedRoles) {\n const [projectId, ...roleNameParts] = role.split(':')\n\n const roleName = roleNameParts.join(':')\n\n if (projectId === AUTH_PROJECT_ID) {\n rolesSet.add(roleName)\n }\n }\n }\n\n return Array.from(rolesSet)\n }\n\n async function introspectToken(\n tokenString: string\n ): Promise<AuthState> {\n // Create JWT for client assertion\n const payload = {\n iss: API_PRIVATE_KEY_FILE.clientId,\n sub: API_PRIVATE_KEY_FILE.clientId,\n aud: AUTH_ISSUER,\n exp: Math.floor(Date.now() / 1000) + 60 * 60, // Expires in 1 hour\n iat: Math.floor(Date.now() / 1000)\n }\n\n const headers = {\n alg: 'RS256',\n kid: API_PRIVATE_KEY_FILE.keyId\n }\n const jwtToken = jwt.sign(payload, API_PRIVATE_KEY_FILE.key, {\n algorithm: 'RS256',\n header: headers\n })\n\n const scopeSet = new Set<string>()\n\n scopeSet.add('openid')\n scopeSet.add('profile')\n scopeSet.add('email')\n\n if (AUTH_PROJECT_ID) {\n scopeSet.add(\n `urn:zitadel:iam:org:project:id:${AUTH_PROJECT_ID}:aud`\n )\n }\n\n const scope = Array.from(scopeSet).join(' ')\n\n // Send introspection request\n const body = new URLSearchParams({\n client_assertion_type:\n 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n client_assertion: jwtToken,\n token: tokenString,\n scope\n }).toString()\n\n try {\n const response = await fetch(ZITADEL_INTROSPECTION_URL, {\n method: 'POST',\n headers: {'Content-Type': 'application/x-www-form-urlencoded'},\n body\n })\n\n if (!response.ok) {\n throw new Error('Network response was not ok')\n }\n\n const tokenData = (await response.json()) as IntrospectionResponse\n\n const roles = await getRolesFromToken(tokenString)\n\n const state = {\n ...tokenData,\n roles\n } as AuthState\n\n return state\n } catch (error) {\n console.error('Error while introspecting token', error)\n throw new Error('Token introspection failed')\n }\n }\n\n let token: string | undefined = undefined\n\n if (ctx.req.header('Authorization')) {\n const authHeader = ctx.req.header('Authorization')\n\n if (authHeader) {\n const parts = authHeader.split(' ')\n\n if (parts.length === 2 && parts[0] === 'Bearer') {\n token = parts[1]\n }\n }\n }\n\n if (!token) {\n const queryToken = ctx.req.query('token')\n\n if (queryToken) {\n token = queryToken\n }\n }\n\n if (token) {\n const auth = await introspectToken(token)\n\n if (auth.active) {\n ctx.set('auth', auth)\n\n Sentry.setUser({\n id: auth.sub,\n username: auth.preferred_username,\n email: auth.email,\n details: auth\n })\n }\n }\n\n return next()\n }\n )\n\n return middleware\n}\n\nexport type AuthRequireChecks = {\n roles?: string[]\n}\n\nconst authRequire = (checks: AuthRequireChecks = {}) => {\n const middleware: MiddlewareHandler<{\n Variables: {\n auth?: AuthState\n }\n }> = async (ctx, next) => {\n // Check if user is authenticated\n const auth = ctx.get('auth')\n\n if (!auth) {\n throw new HTTPException(401, {\n message: 'Authentication required'\n })\n }\n\n if (checks.roles) {\n const roles = auth.roles\n\n const hasRole = checks.roles.some(role => {\n return (\n roles.includes(role) || roles.includes(`${AUTH_PROJECT_ID}:${role}`)\n )\n })\n\n if (!hasRole) {\n const resError = new Response('Forbidden', {\n status: 403,\n statusText: 'Forbidden',\n headers: {\n 'Missing-Roles': checks.roles.join(','),\n 'Obtained-Roles': roles.join(',')\n }\n })\n\n throw new HTTPException(resError.status as StatusCode, {res: resError})\n }\n }\n\n return next()\n }\n\n return middleware\n}\n\nexport const auth = {\n initialize: authInitialize,\n require: authRequire\n}\n\nexport {requireAuth} from './decorators/requireAuth'\n",
8
+ "import {ServiceError} from '../../define-pylon'\nimport {AuthRequireChecks, auth} from '..'\nimport {HTTPException} from 'hono/http-exception'\nimport {getContext} from '../../context'\n\nexport function requireAuth(checks?: AuthRequireChecks) {\n const checkAuth = async (c: any) => {\n const ctx = await c\n\n try {\n await auth.require(checks)(ctx, async () => {})\n } catch (e) {\n if (e instanceof HTTPException) {\n if (e.status === 401) {\n throw new ServiceError(e.message, {\n statusCode: 401,\n code: 'AUTH_REQUIRED'\n })\n } else if (e.status === 403) {\n const res = e.getResponse()\n\n throw new ServiceError(res.statusText, {\n statusCode: res.status,\n code: 'AUTHORIZATION_REQUIRED',\n details: {\n missingRoles: res.headers.get('Missing-Roles')?.split(','),\n obtainedRoles: res.headers.get('Obtained-Roles')?.split(',')\n }\n })\n } else {\n throw e\n }\n }\n\n throw e\n }\n }\n\n return function fn(...args: any[]) {\n const target: any = args[0]\n const propertyKey: string = args[1]\n const descriptor: PropertyDescriptor = args[2]\n\n if (descriptor) {\n const originalMethod = descriptor.value\n\n descriptor.value = async function (...args: any[]) {\n await checkAuth(getContext())\n\n return originalMethod.apply(this, args)\n }\n } else {\n Object.defineProperty(target, propertyKey, {\n get: async function () {\n await checkAuth(getContext())\n\n return this._value\n },\n set: function (newValue) {\n this._value = newValue\n }\n })\n }\n }\n}\n",
9
+ "import {Hono} from 'hono'\nimport {logger} from 'hono/logger'\nimport {sentry} from '@hono/sentry'\n\nimport {asyncContext, Env} from '../context'\nimport {graphqlViewerHandler} from './handler/graphql-viewer-handler'\n\nexport const app = new Hono<Env>()\n\napp.use('*', sentry())\n\napp.use('*', async (c, next) => {\n return new Promise((resolve, reject) => {\n asyncContext.run(c, async () => {\n try {\n resolve(await next()) // You can pass the value you want to return here\n } catch (error) {\n reject(error) // If an error occurs during the execution of `next()`, reject the Promise\n }\n })\n })\n})\n\napp.use('*', logger())\n\napp.use((c, next) => {\n // @ts-ignore\n c.req.id = crypto.randomUUID()\n return next()\n})\n\napp.get('/viewer', graphqlViewerHandler)\n",
10
+ "import type {MiddlewareHandler} from 'hono'\nimport {html} from 'hono/html'\n\nexport const graphqlViewerHandler: MiddlewareHandler = async (c, next) => {\n return c.html(html`\n <!DOCTYPE html>\n <html>\n <head>\n <title>Pylon Viewer</title>\n <script src=\"https://cdn.jsdelivr.net/npm/react@16/umd/react.production.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/react-dom@16/umd/react-dom.production.min.js\"></script>\n\n <link\n rel=\"stylesheet\"\n href=\"https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.css\"\n />\n <style>\n body {\n padding: 0;\n margin: 0;\n width: 100%;\n height: 100vh;\n overflow: hidden;\n }\n\n #voyager {\n height: 100%;\n position: relative;\n }\n }\n </style>\n <script src=\"https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.min.js\"></script>\n </head>\n <body>\n <div id=\"voyager\">Loading...</div>\n <script>\n function introspectionProvider(introspectionQuery) {\n // ... do a call to server using introspectionQuery provided\n // or just return pre-fetched introspection\n\n // Endpoint is current path instead of root/graphql\n const endpoint = window.location.pathname.replace(\n '/viewer',\n '/graphql'\n )\n\n return fetch(endpoint, {\n method: 'post',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({query: introspectionQuery})\n }).then(response => response.json())\n }\n\n // Render <Voyager />\n GraphQLVoyager.init(document.getElementById('voyager'), {\n introspection: introspectionProvider\n })\n </script>\n </body>\n </html>\n `)\n}\n",
11
+ "import {createSchema, createYoga} from 'graphql-yoga'\nimport {GraphQLScalarType, Kind} from 'graphql'\n\nimport {useSentry} from '../envelop/use-sentry'\nimport {Context} from '../../context'\nimport {resolversToGraphQLResolvers} from '../../define-pylon'\n\nexport interface SchemaOptions {\n typeDefs: string\n resolvers: {\n Query: Record<string, any>\n Mutation: Record<string, any>\n }\n}\n\nexport const graphqlHandler =\n (c: Context) =>\n ({typeDefs, resolvers}: SchemaOptions) => {\n // Remove empty resolvers\n for (const key in resolvers) {\n if (Object.keys(resolvers[key]).length === 0) {\n delete resolvers[key]\n }\n }\n\n resolvers = resolversToGraphQLResolvers(resolvers)\n\n const schema = createSchema({\n typeDefs,\n resolvers: {\n ...resolvers,\n // Transforms a date object to a timestamp\n Date: new GraphQLScalarType({\n name: 'Date',\n description: 'Date custom scalar type',\n parseValue(value) {\n if (typeof value === 'string') {\n return new Date(value)\n }\n\n if (value instanceof Date) {\n return value // value from the client\n }\n\n throw Error(\n 'GraphQL Date Scalar parseValue expected a `Date` or string'\n )\n },\n serialize(value) {\n if (value instanceof Date) {\n return value.toISOString() // value sent to the client\n }\n\n throw Error(\n 'GraphQL Date Scalar serializer expected a `Date` object'\n )\n },\n parseLiteral(ast) {\n if (ast.kind === Kind.INT) {\n return new Date(parseInt(ast.value, 10))\n } else if (ast.kind === Kind.STRING) {\n return new Date(ast.value)\n }\n\n return null\n }\n })\n }\n })\n\n const yoga = createYoga({\n schema: schema as any,\n landingPage: false,\n plugins: [useSentry()],\n graphiql: req => {\n return {\n shouldPersistHeaders: true,\n title: 'Pylon Playground',\n defaultQuery: `# Welcome to the Pylon Playground!`\n }\n },\n context: c\n })\n\n return yoga\n }\n",
12
+ "import {GraphQLError, Kind, OperationDefinitionNode, print} from 'graphql'\nimport {\n getDocumentString,\n handleStreamOrSingleExecutionResult,\n isOriginalGraphQLError,\n OnExecuteDoneHookResultOnNextHook,\n TypedExecutionArgs,\n type Plugin\n} from '@envelop/core'\nimport * as Sentry from '@sentry/node'\nimport type {Span, TraceparentData} from '@sentry/types'\n\nexport type SentryPluginOptions<PluginContext extends Record<string, any>> = {\n /**\n * Starts a new transaction for every GraphQL Operation.\n * When disabled, an already existing Transaction will be used.\n *\n * @default true\n */\n startTransaction?: boolean\n /**\n * Renames Transaction.\n * @default false\n */\n renameTransaction?: boolean\n /**\n * Adds result of each resolver and operation to Span's data (available under \"result\")\n * @default false\n */\n includeRawResult?: boolean\n /**\n * Adds operation's variables to a Scope (only in case of errors)\n * @default false\n */\n includeExecuteVariables?: boolean\n /**\n * The key of the event id in the error's extension. `null` to disable.\n * @default sentryEventId\n */\n eventIdKey?: string | null\n /**\n * Adds custom tags to every Transaction.\n */\n appendTags?: (\n args: TypedExecutionArgs<PluginContext>\n ) => Record<string, unknown>\n /**\n * Callback to set context information onto the scope.\n */\n configureScope?: (\n args: TypedExecutionArgs<PluginContext>,\n scope: Sentry.Scope\n ) => void\n /**\n * Produces a name of Transaction (only when \"renameTransaction\" or \"startTransaction\" are enabled) and description of created Span.\n *\n * @default operation's name or \"Anonymous Operation\" when missing)\n */\n transactionName?: (args: TypedExecutionArgs<PluginContext>) => string\n /**\n * Produces tracing data for Transaction\n *\n * @default is empty\n */\n traceparentData?: (\n args: TypedExecutionArgs<PluginContext>\n ) => TraceparentData | undefined\n /**\n * Produces a \"op\" (operation) of created Span.\n *\n * @default execute\n */\n operationName?: (args: TypedExecutionArgs<PluginContext>) => string\n /**\n * Indicates whether or not to skip the entire Sentry flow for given GraphQL operation.\n * By default, no operations are skipped.\n */\n skip?: (args: TypedExecutionArgs<PluginContext>) => boolean\n /**\n * Indicates whether or not to skip Sentry exception reporting for a given error.\n * By default, this plugin skips all `GraphQLError` errors and does not report it to Sentry.\n */\n skipError?: (args: Error) => boolean\n}\n\nexport const defaultSkipError = isOriginalGraphQLError\n\nexport const useSentry = <PluginContext extends Record<string, any> = {}>(\n options: SentryPluginOptions<PluginContext> = {}\n): Plugin<PluginContext> => {\n function pick<K extends keyof SentryPluginOptions<PluginContext>>(\n key: K,\n defaultValue: NonNullable<SentryPluginOptions<PluginContext>[K]>\n ) {\n return options[key] ?? defaultValue\n }\n\n const startTransaction = pick('startTransaction', true)\n const includeRawResult = pick('includeRawResult', false)\n const includeExecuteVariables = pick('includeExecuteVariables', false)\n const renameTransaction = pick('renameTransaction', false)\n const skipOperation = pick('skip', () => false)\n const skipError = pick('skipError', defaultSkipError)\n\n const eventIdKey = options.eventIdKey === null ? null : 'sentryEventId'\n\n function addEventId(err: GraphQLError, eventId: string | null): GraphQLError {\n if (eventIdKey !== null && eventId !== null) {\n err.extensions[eventIdKey] = eventId\n }\n\n return err\n }\n\n return {\n onExecute({args}) {\n if (skipOperation(args)) {\n return\n }\n\n const rootOperation = args.document.definitions.find(\n o => o.kind === Kind.OPERATION_DEFINITION\n ) as OperationDefinitionNode\n const operationType = rootOperation.operation\n\n const document = getDocumentString(args.document, print)\n\n const opName =\n args.operationName || rootOperation.name?.value || 'Anonymous Operation'\n const addedTags: Record<string, any> =\n (options.appendTags && options.appendTags(args)) || {}\n const traceparentData =\n (options.traceparentData && options.traceparentData(args)) || {}\n\n const transactionName = options.transactionName\n ? options.transactionName(args)\n : opName\n const op = options.operationName ? options.operationName(args) : 'execute'\n const tags = {\n operationName: opName,\n operation: operationType,\n ...addedTags\n }\n\n if (options.configureScope) {\n options.configureScope(args, Sentry.getCurrentScope())\n }\n\n return {\n onExecuteDone(payload) {\n const handleResult: OnExecuteDoneHookResultOnNextHook<{}> = ({\n result,\n setResult\n }) => {\n Sentry.startSpanManual(\n {\n op,\n name: opName,\n attributes: tags\n },\n span => {\n if (renameTransaction) {\n span.updateName(transactionName)\n }\n\n span.setAttribute('document', document)\n\n if (includeRawResult) {\n span.setAttribute('result', JSON.stringify(result))\n }\n\n if (result.errors && result.errors.length > 0) {\n Sentry.withScope(scope => {\n scope.setTransactionName(opName)\n scope.setTag('operation', operationType)\n scope.setTag('operationName', opName)\n scope.setExtra('document', document)\n\n scope.setTags(addedTags || {})\n\n if (includeRawResult) {\n scope.setExtra('result', result)\n }\n\n if (includeExecuteVariables) {\n scope.setExtra('variables', args.variableValues)\n }\n\n const errors = result.errors?.map(err => {\n if (skipError(err) === true) {\n return err\n }\n\n const errorPath = (err.path ?? [])\n .map((v: string | number) =>\n typeof v === 'number' ? '$index' : v\n )\n .join(' > ')\n\n if (errorPath) {\n scope.addBreadcrumb({\n category: 'execution-path',\n message: errorPath,\n level: 'debug'\n })\n }\n\n const eventId = Sentry.captureException(\n err.originalError,\n {\n fingerprint: [\n 'graphql',\n errorPath,\n opName,\n operationType\n ],\n contexts: {\n GraphQL: {\n operationName: opName,\n operationType,\n variables: args.variableValues\n }\n }\n }\n )\n\n return addEventId(err, eventId)\n })\n\n setResult({\n ...result,\n errors\n })\n })\n }\n\n span.end()\n }\n )\n }\n return handleStreamOrSingleExecutionResult(payload, handleResult)\n }\n }\n }\n }\n}\n"
11
13
  ],
12
- "mappings": "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",
13
- "debugId": "1536EF647381168764756E2164756E21",
14
+ "mappings": "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",
15
+ "debugId": "29F7E5185902DF9E64756E2164756E21",
14
16
  "names": []
15
17
  }
package/package.json CHANGED
@@ -1,30 +1,37 @@
1
1
  {
2
2
  "name": "@getcronit/pylon",
3
- "version": "1.2.0",
3
+ "version": "2.0.0-beta.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
- "build": "bun run ../../build.js && bun run build:declarations",
8
+ "build": "rimraf ./dist && bun build ./src/index.ts --target=bun --outdir=./dist --sourcemap=external --packages external && bun run build:declarations",
9
9
  "build:declarations": "tsc --declaration --emitDeclarationOnly --outDir ./dist"
10
10
  },
11
11
  "files": [
12
12
  "dist",
13
13
  "tsconfig.pylon.json"
14
14
  ],
15
- "license": "UNLICENSED",
15
+ "author": "Nico Schett <nico.schett@cronit.io>",
16
+ "license": "Apache-2.0",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/getcronit/pylon.git",
20
+ "directory": "packages/pylon"
21
+ },
22
+ "homepage": "https://pylon.cronit.io",
16
23
  "devDependencies": {
17
24
  "hono": "^4.0.8"
18
25
  },
19
- "peerDependencies": {
20
- "hono": "^4.0.8",
21
- "@sentry/bun": "^8.17.0"
22
- },
23
26
  "dependencies": {
27
+ "@hono/sentry": "^1.2.0",
24
28
  "graphql": "^16.9.0",
29
+ "graphql-yoga": "^5.6.2",
25
30
  "jsonwebtoken": "^9.0.2",
26
31
  "openid-client": "^5.6.4",
27
- "winston": "^3.8.2"
32
+ "winston": "^3.8.2",
33
+ "hono": "^4.0.8",
34
+ "@sentry/bun": "^8.17.0"
28
35
  },
29
36
  "resolutions": {
30
37
  "graphql": "^16.9.0"
@@ -1,8 +1,5 @@
1
1
  {
2
- "compilerOptions": {
3
- // add Bun type definitions
4
- "types": ["bun-types"],
5
-
2
+ "compilerOptions": {
6
3
  // enable latest features
7
4
  "lib": ["esnext"],
8
5
  "module": "esnext",
@@ -21,6 +18,7 @@
21
18
  "forceConsistentCasingInFileNames": true,
22
19
  "skipLibCheck": true,
23
20
  "experimentalDecorators": true,
21
+
24
22
  }
25
23
  }
26
24
 
@@ -1,10 +0,0 @@
1
- import winston from 'winston';
2
- /**
3
- * @deprecated Use `getLogger` instead
4
- *
5
- * import {getLogger} from '@getcronit/pylon'
6
- *
7
- * const logger = getLogger(__filename)
8
- */
9
- export declare const logger: winston.Logger;
10
- export declare const getLogger: (moduleName?: string) => winston.Logger;
@@ -1,23 +0,0 @@
1
- import * as Sentry from '@sentry/bun';
2
- import TransportStream from 'winston-transport';
3
- export interface SentryTransportOptions extends TransportStream.TransportStreamOptions {
4
- sentry?: Sentry.BunOptions;
5
- levelsMap?: SeverityOptions;
6
- skipSentryInit?: boolean;
7
- }
8
- interface SeverityOptions {
9
- [key: string]: Sentry.SeverityLevel;
10
- }
11
- export default class SentryTransport extends TransportStream {
12
- silent: boolean;
13
- private levelsMap;
14
- constructor(opts?: SentryTransportOptions);
15
- log(info: any, callback: () => void): void;
16
- end(...args: any[]): this;
17
- get sentry(): typeof Sentry;
18
- private setLevelsMap;
19
- private static withDefaults;
20
- private static isObject;
21
- private static shouldLogException;
22
- }
23
- export {};