@getcronit/pylon 2.9.3 → 2.9.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.
@@ -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,2 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ export declare const graphqlViewerHandler: MiddlewareHandler;
@@ -0,0 +1,12 @@
1
+ import { Context } from '../../context';
2
+ import { PylonConfig } from '../..';
3
+ interface PylonHandlerOptions {
4
+ graphql: {
5
+ Query: Record<string, any>;
6
+ Mutation?: Record<string, any>;
7
+ Subscription?: Record<string, any>;
8
+ };
9
+ config?: PylonConfig;
10
+ }
11
+ export declare const handler: (options: PylonHandlerOptions) => (c: Context) => Promise<Response>;
12
+ export {};
@@ -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, "/">;
@@ -0,0 +1,5 @@
1
+ import { AuthRequireChecks } from '..';
2
+ export declare function requireAuth(checks?: AuthRequireChecks): {
3
+ <T extends (...args: any[]) => any>(target: Object, propertyKey: string | symbol): void;
4
+ <T>(fn: T): T;
5
+ };
@@ -0,0 +1,21 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import type { IdTokenClaims, IntrospectionResponse } from 'openid-client';
3
+ export type AuthState = IntrospectionResponse & IdTokenClaims & {
4
+ roles: string[];
5
+ };
6
+ export type AuthRequireChecks = {
7
+ roles?: string[];
8
+ };
9
+ export declare const auth: {
10
+ initialize: () => MiddlewareHandler<{
11
+ Variables: {
12
+ auth: AuthState;
13
+ };
14
+ }>;
15
+ require: (checks?: AuthRequireChecks) => MiddlewareHandler<{
16
+ Variables: {
17
+ auth?: AuthState;
18
+ };
19
+ }>;
20
+ };
21
+ export { requireAuth } from './decorators/requireAuth';
@@ -0,0 +1,24 @@
1
+ import { Context as HonoContext } from 'hono';
2
+ import type { Toucan } from 'toucan-js';
3
+ import { AuthState } from './auth';
4
+ import { AsyncLocalStorage } from 'async_hooks';
5
+ import type { GraphQLResolveInfo } from 'graphql';
6
+ export interface Bindings {
7
+ NODE_ENV: string;
8
+ AUTH_PROJECT_ID?: string;
9
+ AUTH_KEY?: string;
10
+ AUTH_ISSUER?: string;
11
+ }
12
+ export interface Variables {
13
+ auth: AuthState;
14
+ sentry: Toucan;
15
+ graphqlResolveInfo?: GraphQLResolveInfo;
16
+ }
17
+ export type Env = {
18
+ Bindings: Bindings;
19
+ Variables: Variables;
20
+ };
21
+ export type Context = HonoContext<Env, string, {}>;
22
+ export declare const asyncContext: AsyncLocalStorage<Context>;
23
+ export declare const getContext: () => Context;
24
+ export declare const setContext: (context: Context) => void;
@@ -0,0 +1,4 @@
1
+ export declare function createDecorator(callback: (...args: any[]) => Promise<void>): {
2
+ <T extends (...args: any[]) => any>(target: Object, propertyKey: string | symbol): void;
3
+ <T>(fn: T): T;
4
+ };
@@ -0,0 +1,21 @@
1
+ import { GraphQLError, GraphQLErrorExtensions } from 'graphql';
2
+ import { Context } from './context';
3
+ export interface Resolvers {
4
+ Query: Record<string, any>;
5
+ Mutation?: Record<string, any>;
6
+ Subscription?: Record<string, any>;
7
+ }
8
+ /**
9
+ * Converts a set of resolvers into a corresponding set of GraphQL resolvers.
10
+ * @param resolvers The original resolvers.
11
+ * @returns The converted GraphQL resolvers.
12
+ */
13
+ export declare const resolversToGraphQLResolvers: (resolvers: Resolvers, configureContext?: (context: Context) => Context) => Resolvers;
14
+ export declare class ServiceError extends GraphQLError {
15
+ extensions: GraphQLErrorExtensions;
16
+ constructor(message: string, extensions: {
17
+ code: string;
18
+ statusCode: number;
19
+ details?: Record<string, any>;
20
+ }, error?: Error);
21
+ }
@@ -0,0 +1 @@
1
+ export declare function getEnv(): import("./context").Bindings | NodeJS.ProcessEnv;
@@ -0,0 +1,20 @@
1
+ import { YogaServerOptions } from 'graphql-yoga';
2
+ import { Context } from './context.js';
3
+ export { ServiceError } from './define-pylon.js';
4
+ export * from './auth/index.js';
5
+ export { Context, Env, Variables, Bindings, asyncContext, getContext, setContext } from './context.js';
6
+ export { app } from './app/index.js';
7
+ export { handler } from './app/handler/pylon-handler.js';
8
+ export { getEnv } from './get-env.js';
9
+ export { createDecorator } from './create-decorator.js';
10
+ export { createPubSub as experimentalCreatePubSub } from 'graphql-yoga';
11
+ export type PylonConfig = Pick<YogaServerOptions<Context, Context>, 'plugins'>;
12
+ export type ID = string & {
13
+ readonly brand?: unique symbol;
14
+ };
15
+ export type Int = number & {
16
+ readonly brand?: unique symbol;
17
+ };
18
+ export type Float = number & {
19
+ readonly brand?: unique symbol;
20
+ };
package/dist/index.js ADDED
@@ -0,0 +1,939 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/define-pylon.ts
9
+ import * as Sentry from "@sentry/bun";
10
+ import consola from "consola";
11
+ import {
12
+ GraphQLError
13
+ } from "graphql";
14
+
15
+ // src/context.ts
16
+ import { AsyncLocalStorage } from "async_hooks";
17
+ import { sendFunctionEvent } from "@getcronit/pylon-telemetry";
18
+ import { env } from "hono/adapter";
19
+ var asyncContext = new AsyncLocalStorage();
20
+ var getContext = () => {
21
+ const start = Date.now();
22
+ const ctx = asyncContext.getStore();
23
+ sendFunctionEvent({
24
+ name: "getContext",
25
+ duration: Date.now() - start
26
+ }).then(() => {
27
+ });
28
+ if (!ctx) {
29
+ throw new Error("Context not defined");
30
+ }
31
+ ctx.env = env(ctx);
32
+ return ctx;
33
+ };
34
+ var setContext = (context) => {
35
+ return asyncContext.enterWith(context);
36
+ };
37
+
38
+ // src/define-pylon.ts
39
+ import { isAsyncIterable } from "graphql-yoga";
40
+ function getAllPropertyNames(instance) {
41
+ const allProps = /* @__PURE__ */ new Set();
42
+ let currentObj = instance;
43
+ while (currentObj && currentObj !== Object.prototype) {
44
+ const ownProps = Object.getOwnPropertyNames(currentObj);
45
+ ownProps.forEach((prop) => allProps.add(prop));
46
+ currentObj = Object.getPrototypeOf(currentObj);
47
+ }
48
+ return Array.from(allProps).filter((prop) => prop !== "constructor");
49
+ }
50
+ async function wrapFunctionsRecursively(obj, wrapper, that = null, selectionSet = [], info) {
51
+ if (obj === null || obj instanceof Date) {
52
+ return obj;
53
+ }
54
+ if (Array.isArray(obj)) {
55
+ return await Promise.all(
56
+ obj.map(async (item) => {
57
+ return await wrapFunctionsRecursively(
58
+ item,
59
+ wrapper,
60
+ that,
61
+ selectionSet,
62
+ info
63
+ );
64
+ })
65
+ );
66
+ } else if (typeof obj === "function") {
67
+ return Sentry.startSpan(
68
+ {
69
+ name: obj.name,
70
+ op: "pylon.fn"
71
+ },
72
+ async () => {
73
+ return await wrapper.call(that, obj, selectionSet, info);
74
+ }
75
+ );
76
+ } else if (obj instanceof Promise) {
77
+ return await wrapFunctionsRecursively(
78
+ await obj,
79
+ wrapper,
80
+ that,
81
+ selectionSet,
82
+ info
83
+ );
84
+ } else if (isAsyncIterable(obj)) {
85
+ return obj;
86
+ } else if (typeof obj === "object") {
87
+ that = obj;
88
+ const result = {};
89
+ for (const key of getAllPropertyNames(obj)) {
90
+ result[key] = await wrapFunctionsRecursively(
91
+ obj[key],
92
+ wrapper,
93
+ that,
94
+ selectionSet,
95
+ info
96
+ );
97
+ }
98
+ return result;
99
+ } else {
100
+ return await obj;
101
+ }
102
+ }
103
+ function spreadFunctionArguments(fn) {
104
+ return (otherArgs, c, info) => {
105
+ const selections = arguments[1];
106
+ const realInfo = arguments[2];
107
+ let args = {};
108
+ if (info) {
109
+ const type = info.parentType;
110
+ const field = type.getFields()[info.fieldName];
111
+ const fieldArguments = field?.args;
112
+ const preparedArguments = fieldArguments?.reduce(
113
+ (acc, arg) => {
114
+ if (otherArgs[arg.name] !== void 0) {
115
+ acc[arg.name] = otherArgs[arg.name];
116
+ } else {
117
+ acc[arg.name] = void 0;
118
+ }
119
+ return acc;
120
+ },
121
+ {}
122
+ );
123
+ if (preparedArguments) {
124
+ args = preparedArguments;
125
+ }
126
+ } else {
127
+ args = otherArgs;
128
+ }
129
+ const orderedArgs = Object.keys(args).map((key) => args[key]);
130
+ const that = this || {};
131
+ const result = wrapFunctionsRecursively(
132
+ fn.call(that, ...orderedArgs),
133
+ spreadFunctionArguments,
134
+ this,
135
+ selections,
136
+ realInfo
137
+ );
138
+ return result;
139
+ };
140
+ }
141
+ var resolversToGraphQLResolvers = (resolvers, configureContext) => {
142
+ const rootGraphqlResolver = (fn) => async (_, args, ctx, info) => {
143
+ return Sentry.withScope(async (scope) => {
144
+ const ctx2 = asyncContext.getStore();
145
+ if (!ctx2) {
146
+ consola.warn(
147
+ "Context is not defined. Make sure AsyncLocalStorage is supported in your environment."
148
+ );
149
+ }
150
+ ctx2?.set("graphqlResolveInfo", info);
151
+ const auth2 = ctx2?.get("auth");
152
+ if (auth2?.active) {
153
+ scope.setUser({
154
+ id: auth2.sub,
155
+ username: auth2.preferred_username,
156
+ email: auth2.email,
157
+ details: auth2
158
+ });
159
+ }
160
+ let type = null;
161
+ switch (info.operation.operation) {
162
+ case "query":
163
+ type = info.schema.getQueryType();
164
+ break;
165
+ case "mutation":
166
+ type = info.schema.getMutationType();
167
+ break;
168
+ case "subscription":
169
+ type = info.schema.getSubscriptionType();
170
+ break;
171
+ default:
172
+ throw new Error("Unknown operation");
173
+ }
174
+ const field = type?.getFields()[info.fieldName];
175
+ const fieldArguments = field?.args || [];
176
+ const preparedArguments = fieldArguments.reduce(
177
+ (acc, arg) => {
178
+ if (args[arg.name] !== void 0) {
179
+ acc[arg.name] = args[arg.name];
180
+ } else {
181
+ acc[arg.name] = void 0;
182
+ }
183
+ return acc;
184
+ },
185
+ {}
186
+ );
187
+ let inner = await fn;
188
+ let baseSelectionSet = [];
189
+ for (const selection of info.operation.selectionSet.selections) {
190
+ if (selection.kind === "Field" && selection.name.value === info.fieldName) {
191
+ baseSelectionSet = selection.selectionSet?.selections || [];
192
+ }
193
+ }
194
+ const wrappedFn = await wrapFunctionsRecursively(
195
+ inner,
196
+ spreadFunctionArguments,
197
+ void 0,
198
+ baseSelectionSet,
199
+ info
200
+ );
201
+ if (typeof wrappedFn !== "function") {
202
+ return wrappedFn;
203
+ }
204
+ const res = await wrappedFn(preparedArguments);
205
+ return res;
206
+ });
207
+ };
208
+ const graphqlResolvers = {};
209
+ for (const key of Object.keys(resolvers.Query)) {
210
+ if (!resolvers.Query[key]) {
211
+ delete resolvers.Query[key];
212
+ }
213
+ }
214
+ if (resolvers.Query && Object.keys(resolvers.Query).length > 0) {
215
+ for (const [key, value] of Object.entries(resolvers.Query)) {
216
+ if (!graphqlResolvers.Query) {
217
+ graphqlResolvers.Query = {};
218
+ }
219
+ graphqlResolvers.Query[key] = rootGraphqlResolver(
220
+ value
221
+ );
222
+ }
223
+ }
224
+ if (resolvers.Mutation && Object.keys(resolvers.Mutation).length > 0) {
225
+ if (!graphqlResolvers.Mutation) {
226
+ graphqlResolvers.Mutation = {};
227
+ }
228
+ for (const [key, value] of Object.entries(resolvers.Mutation)) {
229
+ graphqlResolvers.Mutation[key] = rootGraphqlResolver(
230
+ value
231
+ );
232
+ }
233
+ }
234
+ if (resolvers.Subscription && Object.keys(resolvers.Subscription).length > 0) {
235
+ if (!graphqlResolvers.Subscription) {
236
+ graphqlResolvers.Subscription = {};
237
+ }
238
+ for (const [key, value] of Object.entries(resolvers.Subscription)) {
239
+ graphqlResolvers.Subscription[key] = {
240
+ subscribe: rootGraphqlResolver(value),
241
+ resolve: (payload) => payload
242
+ };
243
+ }
244
+ }
245
+ if (!graphqlResolvers.Query) {
246
+ throw new Error(`At least one 'Query' resolver must be provided.
247
+
248
+ Example:
249
+
250
+ export const graphql = {
251
+ Query: {
252
+ // Define at least one query resolver here
253
+ hello: () => 'world'
254
+ }
255
+ }
256
+ `);
257
+ }
258
+ for (const key of Object.keys(resolvers)) {
259
+ if (key !== "Query" && key !== "Mutation" && key !== "Subscription") {
260
+ graphqlResolvers[key] = resolvers[key];
261
+ }
262
+ }
263
+ return graphqlResolvers;
264
+ };
265
+ var ServiceError = class extends GraphQLError {
266
+ extensions;
267
+ constructor(message, extensions, error) {
268
+ super(message, {
269
+ originalError: error
270
+ });
271
+ this.extensions = extensions;
272
+ this.cause = error;
273
+ }
274
+ };
275
+
276
+ // src/auth/index.ts
277
+ import jwt from "jsonwebtoken";
278
+ import path from "path";
279
+ import { HTTPException as HTTPException2 } from "hono/http-exception";
280
+ import { env as env2 } from "hono/adapter";
281
+ import * as Sentry2 from "@sentry/bun";
282
+ import { existsSync, readFileSync } from "fs";
283
+ import { sendFunctionEvent as sendFunctionEvent4 } from "@getcronit/pylon-telemetry";
284
+
285
+ // src/auth/decorators/requireAuth.ts
286
+ import { sendFunctionEvent as sendFunctionEvent3 } from "@getcronit/pylon-telemetry";
287
+ import { HTTPException } from "hono/http-exception";
288
+
289
+ // src/create-decorator.ts
290
+ import { sendFunctionEvent as sendFunctionEvent2 } from "@getcronit/pylon-telemetry";
291
+ function createDecorator(callback) {
292
+ sendFunctionEvent2({
293
+ name: "createDecorator",
294
+ duration: 0
295
+ }).then(() => {
296
+ });
297
+ function MyDecorator(arg1, propertyKey, descriptor) {
298
+ if (descriptor) {
299
+ const originalMethod = descriptor.value;
300
+ descriptor.value = async function(...args) {
301
+ await callback(...args);
302
+ return originalMethod.apply(this, args);
303
+ };
304
+ return descriptor;
305
+ } else {
306
+ if (!descriptor) {
307
+ if (propertyKey === void 0) {
308
+ const originalFunction = arg1;
309
+ return async function(...args) {
310
+ await callback(...args);
311
+ return originalFunction(...args);
312
+ };
313
+ }
314
+ let value = arg1[propertyKey];
315
+ Object.defineProperty(arg1, propertyKey, {
316
+ get: function() {
317
+ return async function(...args) {
318
+ await callback(...args);
319
+ if (typeof value === "function") {
320
+ return value(...args);
321
+ }
322
+ return value;
323
+ };
324
+ },
325
+ set: function(newValue) {
326
+ value = newValue;
327
+ },
328
+ enumerable: true,
329
+ configurable: true
330
+ });
331
+ return;
332
+ }
333
+ }
334
+ }
335
+ return MyDecorator;
336
+ }
337
+
338
+ // src/auth/decorators/requireAuth.ts
339
+ function requireAuth(checks) {
340
+ sendFunctionEvent3({
341
+ name: "requireAuth",
342
+ duration: 0
343
+ }).then(() => {
344
+ });
345
+ const checkAuth = async (c) => {
346
+ const ctx = await c;
347
+ try {
348
+ await auth.require(checks)(ctx, async () => {
349
+ });
350
+ } catch (e) {
351
+ if (e instanceof HTTPException) {
352
+ if (e.status === 401) {
353
+ throw new ServiceError(e.message, {
354
+ statusCode: 401,
355
+ code: "AUTH_REQUIRED"
356
+ });
357
+ } else if (e.status === 403) {
358
+ const res = e.getResponse();
359
+ throw new ServiceError(res.statusText, {
360
+ statusCode: res.status,
361
+ code: "AUTHORIZATION_REQUIRED",
362
+ details: {
363
+ missingRoles: res.headers.get("Missing-Roles")?.split(","),
364
+ obtainedRoles: res.headers.get("Obtained-Roles")?.split(",")
365
+ }
366
+ });
367
+ } else {
368
+ throw e;
369
+ }
370
+ }
371
+ throw e;
372
+ }
373
+ };
374
+ return createDecorator(async () => {
375
+ const ctx = getContext();
376
+ await checkAuth(ctx);
377
+ });
378
+ }
379
+
380
+ // src/auth/index.ts
381
+ var authInitialize = () => {
382
+ const authKeyFilePath = path.join(process.cwd(), "key.json");
383
+ let API_PRIVATE_KEY_FILE = void 0;
384
+ if (existsSync(authKeyFilePath)) {
385
+ try {
386
+ API_PRIVATE_KEY_FILE = JSON.parse(readFileSync(authKeyFilePath, "utf-8"));
387
+ } catch (error) {
388
+ throw new Error(
389
+ "Error while reading key file. Make sure it is valid JSON"
390
+ );
391
+ }
392
+ }
393
+ const middleware = Sentry2.startSpan(
394
+ {
395
+ name: "AuthMiddleware",
396
+ op: "auth"
397
+ },
398
+ () => async function(ctx, next) {
399
+ const AUTH_ISSUER = env2(ctx).AUTH_ISSUER;
400
+ if (!AUTH_ISSUER) {
401
+ throw new Error("AUTH_ISSUER is not set");
402
+ }
403
+ if (!API_PRIVATE_KEY_FILE) {
404
+ const AUTH_KEY = env2(ctx).AUTH_KEY;
405
+ API_PRIVATE_KEY_FILE = AUTH_KEY ? JSON.parse(AUTH_KEY) : void 0;
406
+ }
407
+ if (!API_PRIVATE_KEY_FILE) {
408
+ throw new Error(
409
+ "You have initialized the auth middleware without a private key file"
410
+ );
411
+ }
412
+ const AUTH_PROJECT_ID = env2(ctx).AUTH_PROJECT_ID;
413
+ const ZITADEL_INTROSPECTION_URL = `${AUTH_ISSUER}/oauth/v2/introspect`;
414
+ async function getRolesFromToken(tokenString) {
415
+ const response = await fetch(
416
+ `${AUTH_ISSUER}/auth/v1/usergrants/me/_search`,
417
+ {
418
+ method: "POST",
419
+ headers: {
420
+ "Content-Type": "application/json",
421
+ Authorization: `Bearer ${tokenString}`
422
+ }
423
+ }
424
+ );
425
+ const data = await response.json();
426
+ const userRoles = data.result?.map((grant) => {
427
+ return (grant.roles || []).map((role) => {
428
+ return `${grant.projectId}:${role}`;
429
+ });
430
+ }) || [];
431
+ const projectScopedRoles = userRoles.flat();
432
+ const rolesSet = new Set(projectScopedRoles);
433
+ if (AUTH_PROJECT_ID) {
434
+ for (const role of projectScopedRoles) {
435
+ const [projectId, ...roleNameParts] = role.split(":");
436
+ const roleName = roleNameParts.join(":");
437
+ if (projectId === AUTH_PROJECT_ID) {
438
+ rolesSet.add(roleName);
439
+ }
440
+ }
441
+ }
442
+ return Array.from(rolesSet);
443
+ }
444
+ async function introspectToken(tokenString) {
445
+ if (!API_PRIVATE_KEY_FILE) {
446
+ throw new Error("Internal error: API_PRIVATE_KEY_FILE is not set");
447
+ }
448
+ const payload = {
449
+ iss: API_PRIVATE_KEY_FILE.clientId,
450
+ sub: API_PRIVATE_KEY_FILE.clientId,
451
+ aud: AUTH_ISSUER,
452
+ exp: Math.floor(Date.now() / 1e3) + 60 * 60,
453
+ // Expires in 1 hour
454
+ iat: Math.floor(Date.now() / 1e3)
455
+ };
456
+ const headers = {
457
+ alg: "RS256",
458
+ kid: API_PRIVATE_KEY_FILE.keyId
459
+ };
460
+ const jwtToken = jwt.sign(payload, API_PRIVATE_KEY_FILE.key, {
461
+ algorithm: "RS256",
462
+ header: headers
463
+ });
464
+ const scopeSet = /* @__PURE__ */ new Set();
465
+ scopeSet.add("openid");
466
+ scopeSet.add("profile");
467
+ scopeSet.add("email");
468
+ if (AUTH_PROJECT_ID) {
469
+ scopeSet.add(
470
+ `urn:zitadel:iam:org:project:id:${AUTH_PROJECT_ID}:aud`
471
+ );
472
+ }
473
+ const scope = Array.from(scopeSet).join(" ");
474
+ const body = new URLSearchParams({
475
+ client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
476
+ client_assertion: jwtToken,
477
+ token: tokenString,
478
+ scope
479
+ }).toString();
480
+ try {
481
+ const response = await fetch(ZITADEL_INTROSPECTION_URL, {
482
+ method: "POST",
483
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
484
+ body
485
+ });
486
+ if (!response.ok) {
487
+ throw new Error("Network response was not ok");
488
+ }
489
+ const tokenData = await response.json();
490
+ const roles = await getRolesFromToken(tokenString);
491
+ const state = {
492
+ ...tokenData,
493
+ roles
494
+ };
495
+ return state;
496
+ } catch (error) {
497
+ console.error("Error while introspecting token", error);
498
+ throw new Error("Token introspection failed");
499
+ }
500
+ }
501
+ let token = void 0;
502
+ if (ctx.req.header("Authorization")) {
503
+ const authHeader = ctx.req.header("Authorization");
504
+ if (authHeader) {
505
+ const parts = authHeader.split(" ");
506
+ if (parts.length === 2 && parts[0] === "Bearer") {
507
+ token = parts[1];
508
+ }
509
+ }
510
+ }
511
+ if (!token) {
512
+ const queryToken = ctx.req.query("token");
513
+ if (queryToken) {
514
+ token = queryToken;
515
+ }
516
+ }
517
+ if (token) {
518
+ const auth2 = await introspectToken(token);
519
+ if (auth2.active) {
520
+ ctx.set("auth", auth2);
521
+ Sentry2.setUser({
522
+ id: auth2.sub,
523
+ username: auth2.preferred_username,
524
+ email: auth2.email,
525
+ details: auth2
526
+ });
527
+ }
528
+ }
529
+ return next();
530
+ }
531
+ );
532
+ sendFunctionEvent4({
533
+ name: "authInitialize",
534
+ duration: 0
535
+ }).then(() => {
536
+ });
537
+ return middleware;
538
+ };
539
+ var authRequire = (checks = {}) => {
540
+ sendFunctionEvent4({
541
+ name: "authRequire",
542
+ duration: 0
543
+ }).then(() => {
544
+ });
545
+ const middleware = async (ctx, next) => {
546
+ const AUTH_PROJECT_ID = env2(ctx).AUTH_PROJECT_ID;
547
+ const auth2 = ctx.get("auth");
548
+ if (!auth2) {
549
+ throw new HTTPException2(401, {
550
+ message: "Authentication required"
551
+ });
552
+ }
553
+ if (checks.roles) {
554
+ const roles = auth2.roles;
555
+ const hasRole = checks.roles.some((role) => {
556
+ return roles.includes(role) || roles.includes(`${AUTH_PROJECT_ID}:${role}`);
557
+ });
558
+ if (!hasRole) {
559
+ const resError = new Response("Forbidden", {
560
+ status: 403,
561
+ statusText: "Forbidden",
562
+ headers: {
563
+ "Missing-Roles": checks.roles.join(","),
564
+ "Obtained-Roles": roles.join(",")
565
+ }
566
+ });
567
+ throw new HTTPException2(resError.status, { res: resError });
568
+ }
569
+ }
570
+ return next();
571
+ };
572
+ sendFunctionEvent4({
573
+ name: "authRequire",
574
+ duration: 0
575
+ }).then(() => {
576
+ });
577
+ return middleware;
578
+ };
579
+ var auth = {
580
+ initialize: authInitialize,
581
+ require: authRequire
582
+ };
583
+
584
+ // src/app/index.ts
585
+ import { Hono } from "hono";
586
+ import { logger } from "hono/logger";
587
+ import { sentry } from "@hono/sentry";
588
+
589
+ // src/app/handler/graphql-viewer-handler.ts
590
+ import { html } from "hono/html";
591
+ var graphqlViewerHandler = async (c, next) => {
592
+ return c.html(html`
593
+ <!DOCTYPE html>
594
+ <html>
595
+ <head>
596
+ <title>Pylon Viewer</title>
597
+ <script src="https://cdn.jsdelivr.net/npm/react@16/umd/react.production.min.js"></script>
598
+ <script src="https://cdn.jsdelivr.net/npm/react-dom@16/umd/react-dom.production.min.js"></script>
599
+
600
+ <link
601
+ rel="stylesheet"
602
+ href="https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.css"
603
+ />
604
+ <style>
605
+ body {
606
+ padding: 0;
607
+ margin: 0;
608
+ width: 100%;
609
+ height: 100vh;
610
+ overflow: hidden;
611
+ }
612
+
613
+ #voyager {
614
+ height: 100%;
615
+ position: relative;
616
+ }
617
+ }
618
+ </style>
619
+ <script src="https://cdn.jsdelivr.net/npm/graphql-voyager/dist/voyager.min.js"></script>
620
+ </head>
621
+ <body>
622
+ <div id="voyager">Loading...</div>
623
+ <script>
624
+ function introspectionProvider(introspectionQuery) {
625
+ // ... do a call to server using introspectionQuery provided
626
+ // or just return pre-fetched introspection
627
+
628
+ // Endpoint is current path instead of root/graphql
629
+ const endpoint = window.location.pathname.replace(
630
+ '/viewer',
631
+ '/graphql'
632
+ )
633
+
634
+ return fetch(endpoint, {
635
+ method: 'post',
636
+ headers: {
637
+ 'Content-Type': 'application/json'
638
+ },
639
+ body: JSON.stringify({query: introspectionQuery})
640
+ }).then(response => response.json())
641
+ }
642
+
643
+ // Render <Voyager />
644
+ GraphQLVoyager.init(document.getElementById('voyager'), {
645
+ introspection: introspectionProvider
646
+ })
647
+ </script>
648
+ </body>
649
+ </html>
650
+ `);
651
+ };
652
+
653
+ // src/app/index.ts
654
+ var app = new Hono();
655
+ app.use("*", sentry());
656
+ app.use("*", async (c, next) => {
657
+ return new Promise((resolve, reject) => {
658
+ asyncContext.run(c, async () => {
659
+ try {
660
+ resolve(await next());
661
+ } catch (error) {
662
+ reject(error);
663
+ }
664
+ });
665
+ });
666
+ });
667
+ app.use("*", logger());
668
+ app.use((c, next) => {
669
+ c.req.id = crypto.randomUUID();
670
+ return next();
671
+ });
672
+ app.get("/viewer", graphqlViewerHandler);
673
+
674
+ // src/app/handler/pylon-handler.ts
675
+ import { createSchema, createYoga } from "graphql-yoga";
676
+ import { GraphQLScalarType, Kind as Kind2 } from "graphql";
677
+ import {
678
+ DateTimeISOResolver,
679
+ GraphQLVoid,
680
+ JSONObjectResolver,
681
+ JSONResolver
682
+ } from "graphql-scalars";
683
+
684
+ // src/app/envelop/use-sentry.ts
685
+ import { Kind, print } from "graphql";
686
+ import {
687
+ getDocumentString,
688
+ handleStreamOrSingleExecutionResult,
689
+ isOriginalGraphQLError
690
+ } from "@envelop/core";
691
+ import * as Sentry3 from "@sentry/node";
692
+ var defaultSkipError = isOriginalGraphQLError;
693
+ var useSentry = (options = {}) => {
694
+ function pick(key, defaultValue) {
695
+ return options[key] ?? defaultValue;
696
+ }
697
+ const startTransaction = pick("startTransaction", true);
698
+ const includeRawResult = pick("includeRawResult", false);
699
+ const includeExecuteVariables = pick("includeExecuteVariables", false);
700
+ const renameTransaction = pick("renameTransaction", false);
701
+ const skipOperation = pick("skip", () => false);
702
+ const skipError = pick("skipError", defaultSkipError);
703
+ const eventIdKey = options.eventIdKey === null ? null : "sentryEventId";
704
+ function addEventId(err, eventId) {
705
+ if (eventIdKey !== null && eventId !== null) {
706
+ err.extensions[eventIdKey] = eventId;
707
+ }
708
+ return err;
709
+ }
710
+ return {
711
+ onExecute({ args }) {
712
+ if (skipOperation(args)) {
713
+ return;
714
+ }
715
+ const rootOperation = args.document.definitions.find(
716
+ (o) => o.kind === Kind.OPERATION_DEFINITION
717
+ );
718
+ const operationType = rootOperation.operation;
719
+ const document = getDocumentString(args.document, print);
720
+ const opName = args.operationName || rootOperation.name?.value || "Anonymous Operation";
721
+ const addedTags = options.appendTags && options.appendTags(args) || {};
722
+ const traceparentData = options.traceparentData && options.traceparentData(args) || {};
723
+ const transactionName = options.transactionName ? options.transactionName(args) : opName;
724
+ const op = options.operationName ? options.operationName(args) : "execute";
725
+ const tags = {
726
+ operationName: opName,
727
+ operation: operationType,
728
+ ...addedTags
729
+ };
730
+ if (options.configureScope) {
731
+ options.configureScope(args, Sentry3.getCurrentScope());
732
+ }
733
+ return {
734
+ onExecuteDone(payload) {
735
+ const handleResult = ({
736
+ result,
737
+ setResult
738
+ }) => {
739
+ Sentry3.startSpanManual(
740
+ {
741
+ op,
742
+ name: opName,
743
+ attributes: tags
744
+ },
745
+ (span) => {
746
+ if (renameTransaction) {
747
+ span.updateName(transactionName);
748
+ }
749
+ span.setAttribute("document", document);
750
+ if (includeRawResult) {
751
+ span.setAttribute("result", JSON.stringify(result));
752
+ }
753
+ if (result.errors && result.errors.length > 0) {
754
+ Sentry3.withScope((scope) => {
755
+ scope.setTransactionName(opName);
756
+ scope.setTag("operation", operationType);
757
+ scope.setTag("operationName", opName);
758
+ scope.setExtra("document", document);
759
+ scope.setTags(addedTags || {});
760
+ if (includeRawResult) {
761
+ scope.setExtra("result", result);
762
+ }
763
+ if (includeExecuteVariables) {
764
+ scope.setExtra("variables", args.variableValues);
765
+ }
766
+ const errors = result.errors?.map((err) => {
767
+ if (skipError(err) === true) {
768
+ return err;
769
+ }
770
+ const errorPath = (err.path ?? []).map(
771
+ (v) => typeof v === "number" ? "$index" : v
772
+ ).join(" > ");
773
+ if (errorPath) {
774
+ scope.addBreadcrumb({
775
+ category: "execution-path",
776
+ message: errorPath,
777
+ level: "debug"
778
+ });
779
+ }
780
+ const eventId = Sentry3.captureException(
781
+ err.originalError,
782
+ {
783
+ fingerprint: [
784
+ "graphql",
785
+ errorPath,
786
+ opName,
787
+ operationType
788
+ ],
789
+ contexts: {
790
+ GraphQL: {
791
+ operationName: opName,
792
+ operationType,
793
+ variables: args.variableValues
794
+ }
795
+ }
796
+ }
797
+ );
798
+ return addEventId(err, eventId);
799
+ });
800
+ setResult({
801
+ ...result,
802
+ errors
803
+ });
804
+ });
805
+ }
806
+ span.end();
807
+ }
808
+ );
809
+ };
810
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
811
+ }
812
+ };
813
+ }
814
+ };
815
+ };
816
+
817
+ // src/app/handler/pylon-handler.ts
818
+ import { readFileSync as readFileSync2 } from "fs";
819
+ import path2 from "path";
820
+ var handler = (options) => {
821
+ let { typeDefs, resolvers, graphql, config } = options;
822
+ if (!typeDefs) {
823
+ const schemaPath = path2.join(process.cwd(), ".pylon", "schema.graphql");
824
+ if (schemaPath) {
825
+ typeDefs = readFileSync2(schemaPath, "utf-8");
826
+ }
827
+ }
828
+ if (!typeDefs) {
829
+ throw new Error("No schema provided.");
830
+ }
831
+ if (!resolvers) {
832
+ const resolversPath = path2.join(process.cwd(), ".pylon", "resolvers.js");
833
+ if (resolversPath) {
834
+ resolvers = __require(resolversPath).resolvers;
835
+ }
836
+ }
837
+ const graphqlResolvers = resolversToGraphQLResolvers(graphql);
838
+ const schema = createSchema({
839
+ typeDefs,
840
+ resolvers: {
841
+ ...graphqlResolvers,
842
+ ...resolvers,
843
+ // Transforms a date object to a timestamp
844
+ Date: DateTimeISOResolver,
845
+ JSON: JSONResolver,
846
+ Object: JSONObjectResolver,
847
+ Void: GraphQLVoid,
848
+ Number: new GraphQLScalarType({
849
+ name: "Number",
850
+ description: "Custom scalar that handles both integers and floats",
851
+ // Parsing input from query variables
852
+ parseValue(value) {
853
+ if (typeof value !== "number") {
854
+ throw new TypeError(`Value is not a number: ${value}`);
855
+ }
856
+ return value;
857
+ },
858
+ // Validation when sending from client (input literals)
859
+ parseLiteral(ast) {
860
+ if (ast.kind === Kind2.INT || ast.kind === Kind2.FLOAT) {
861
+ return parseFloat(ast.value);
862
+ }
863
+ throw new TypeError(
864
+ `Value is not a valid number or float: ${"value" in ast ? ast.value : ast}`
865
+ );
866
+ },
867
+ // Serialize output to be sent to the client
868
+ serialize(value) {
869
+ if (typeof value !== "number") {
870
+ throw new TypeError(`Value is not a number: ${value}`);
871
+ }
872
+ return value;
873
+ }
874
+ })
875
+ }
876
+ });
877
+ const yoga = createYoga({
878
+ landingPage: false,
879
+ graphiql: (req) => {
880
+ return {
881
+ shouldPersistHeaders: true,
882
+ title: "Pylon Playground",
883
+ defaultQuery: `# Welcome to the Pylon Playground!`
884
+ };
885
+ },
886
+ graphqlEndpoint: "/graphql",
887
+ ...config,
888
+ plugins: [useSentry(), ...config?.plugins || []],
889
+ schema
890
+ });
891
+ const handler2 = async (c) => {
892
+ let executionContext = {};
893
+ try {
894
+ executionContext = c.executionCtx;
895
+ } catch (e) {
896
+ }
897
+ const response = await yoga.fetch(c.req.raw, c.env, executionContext);
898
+ return c.newResponse(response.body, response);
899
+ };
900
+ return handler2;
901
+ };
902
+
903
+ // src/get-env.ts
904
+ import { sendFunctionEvent as sendFunctionEvent5 } from "@getcronit/pylon-telemetry";
905
+ function getEnv() {
906
+ const start = Date.now();
907
+ const skipTracing = arguments[0] === true;
908
+ try {
909
+ const context = asyncContext.getStore();
910
+ return context.env || process.env || {};
911
+ } catch {
912
+ return process.env;
913
+ } finally {
914
+ if (!skipTracing) {
915
+ sendFunctionEvent5({
916
+ name: "getEnv",
917
+ duration: Date.now() - start
918
+ }).then(() => {
919
+ });
920
+ }
921
+ }
922
+ }
923
+
924
+ // src/index.ts
925
+ import { createPubSub } from "graphql-yoga";
926
+ export {
927
+ ServiceError,
928
+ app,
929
+ asyncContext,
930
+ auth,
931
+ createDecorator,
932
+ createPubSub as experimentalCreatePubSub,
933
+ getContext,
934
+ getEnv,
935
+ handler,
936
+ requireAuth,
937
+ setContext
938
+ };
939
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/define-pylon.ts", "../src/context.ts", "../src/auth/index.ts", "../src/auth/decorators/requireAuth.ts", "../src/create-decorator.ts", "../src/app/index.ts", "../src/app/handler/graphql-viewer-handler.ts", "../src/app/handler/pylon-handler.ts", "../src/app/envelop/use-sentry.ts", "../src/get-env.ts", "../src/index.ts"],
4
+ "sourcesContent": ["import * as Sentry from '@sentry/bun'\nimport consola from 'consola'\nimport {\n FragmentDefinitionNode,\n GraphQLError,\n GraphQLErrorExtensions,\n GraphQLObjectType,\n GraphQLResolveInfo,\n SelectionSetNode\n} from 'graphql'\n\nimport {Context, asyncContext} from './context'\nimport {isAsyncIterable, Maybe} from 'graphql-yoga'\n\nexport interface Resolvers {\n Query: Record<string, any>\n Mutation?: Record<string, any>\n Subscription?: Record<string, any>\n}\n\ntype FunctionWrapper = (fn: (...args: any[]) => any) => (...args: any[]) => any\n\nfunction getAllPropertyNames(instance: any): string[] {\n const allProps = new Set<string>()\n\n // Traverse the prototype chain\n let currentObj: any = instance\n\n while (currentObj && currentObj !== Object.prototype) {\n // Get all own property names of the current object\n const ownProps = Object.getOwnPropertyNames(currentObj)\n\n // Add each property to the Set\n ownProps.forEach(prop => allProps.add(prop))\n\n // Move up the prototype chain\n currentObj = Object.getPrototypeOf(currentObj)\n }\n\n // Convert Set to array and filter out the constructor if desired\n return Array.from(allProps).filter(prop => prop !== 'constructor')\n}\n\nasync function wrapFunctionsRecursively(\n obj: any,\n wrapper: FunctionWrapper,\n that: any = null,\n selectionSet: SelectionSetNode['selections'] = [],\n info: GraphQLResolveInfo\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(\n item,\n wrapper,\n that,\n selectionSet,\n info\n )\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, info)\n }\n )\n } else if (obj instanceof Promise) {\n return await wrapFunctionsRecursively(\n await obj,\n wrapper,\n that,\n selectionSet,\n info\n )\n } else if (isAsyncIterable(obj)) {\n return obj\n } else if (typeof obj === 'object') {\n that = obj\n\n const result: Record<string, any> = {}\n\n for (const key of getAllPropertyNames(obj)) {\n result[key] = await wrapFunctionsRecursively(\n obj[key],\n wrapper,\n that,\n selectionSet,\n info\n )\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 const realInfo = arguments[2] as GraphQLResolveInfo\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 realInfo\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 (\n _: object,\n args: Record<string, any>,\n ctx: Context,\n info: GraphQLResolveInfo\n ) => {\n return Sentry.withScope(async scope => {\n const ctx = asyncContext.getStore()\n\n\n if (!ctx) {\n consola.warn(\n 'Context is not defined. Make sure AsyncLocalStorage is supported in your environment.'\n )\n }\n\n ctx?.set(\"graphqlResolveInfo\", info)\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 // get query or mutation field\n\n let type: Maybe<GraphQLObjectType> | null = null\n\n switch (info.operation.operation) {\n case 'query':\n type = info.schema.getQueryType()\n break\n case 'mutation':\n type = info.schema.getMutationType()\n break\n case 'subscription':\n type = info.schema.getSubscriptionType()\n break\n default:\n throw new Error('Unknown operation')\n }\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 info\n )\n\n // Call the resolver function with the prepared arguments.\n if (typeof wrappedFn !== 'function') {\n return wrappedFn\n }\n\n const res = await wrappedFn(preparedArguments)\n\n return res\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 && Object.keys(resolvers.Query).length > 0) {\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 && Object.keys(resolvers.Mutation).length > 0) {\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 if (\n resolvers.Subscription &&\n Object.keys(resolvers.Subscription).length > 0\n ) {\n if (!graphqlResolvers.Subscription) {\n graphqlResolvers.Subscription = {}\n }\n\n for (const [key, value] of Object.entries(resolvers.Subscription)) {\n graphqlResolvers.Subscription[key] = {\n subscribe: rootGraphqlResolver(value as Function | object),\n resolve: (payload: any) => payload\n }\n }\n }\n\n // Query root type must be provided.\n if (!graphqlResolvers.Query) {\n // Custom Error for Query root type must be provided.\n\n throw new Error(`At least one 'Query' resolver must be provided.\n\nExample:\n\nexport const graphql = {\n Query: {\n // Define at least one query resolver here\n hello: () => 'world'\n }\n}\n`)\n }\n\n // Add extra resolvers (e.g. custom scalars) to the GraphQL resolvers.\n for (const key of Object.keys(resolvers)) {\n if (key !== 'Query' && key !== 'Mutation' && key !== 'Subscription') {\n graphqlResolvers[key] = resolvers[key]\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", "import {Context as HonoContext} from 'hono'\nimport type {Toucan} from 'toucan-js'\nimport {AuthState} from './auth'\nimport {AsyncLocalStorage} from 'async_hooks'\nimport {sendFunctionEvent} from '@getcronit/pylon-telemetry'\nimport {env} from 'hono/adapter'\nimport type { GraphQLResolveInfo } from 'graphql'\n\nexport interface Bindings {\n NODE_ENV: string\n AUTH_PROJECT_ID?: string\n AUTH_KEY?: string\n AUTH_ISSUER?: string\n}\n\nexport interface Variables {\n auth: AuthState\n sentry: Toucan\n graphqlResolveInfo?: GraphQLResolveInfo\n}\n\nexport type Env = {\n Bindings: Bindings\n Variables: Variables\n}\n\nexport type Context = HonoContext<Env, string, {}>\n\nexport const asyncContext = new AsyncLocalStorage<Context>()\n\nexport const getContext = () => {\n const start = Date.now()\n const ctx = asyncContext.getStore()\n\n sendFunctionEvent({\n name: 'getContext',\n duration: Date.now() - start\n }).then(() => {})\n\n if (!ctx) {\n throw new Error('Context not defined')\n }\n\n ctx.env = env(ctx)\n\n return ctx\n}\n\nexport const setContext = (context: Context) => {\n return asyncContext.enterWith(context)\n}\n", "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 {ContentfulStatusCode} from 'hono/utils/http-status'\nimport {env} from 'hono/adapter'\nimport * as Sentry from '@sentry/bun'\nimport {existsSync, readFileSync} from 'fs'\nimport {sendFunctionEvent} from '@getcronit/pylon-telemetry'\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 // Load private key file from cwd\n let API_PRIVATE_KEY_FILE:\n | {\n type: 'application'\n keyId: string\n key: string\n appId: string\n clientId: string\n }\n | undefined = undefined\n\n if (existsSync(authKeyFilePath)) {\n try {\n API_PRIVATE_KEY_FILE = JSON.parse(readFileSync(authKeyFilePath, 'utf-8'))\n } catch (error) {\n throw new Error(\n 'Error while reading key file. Make sure it is valid JSON'\n )\n }\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 AUTH_ISSUER = env(ctx).AUTH_ISSUER\n\n if (!AUTH_ISSUER) {\n throw new Error('AUTH_ISSUER is not set')\n }\n\n if (!API_PRIVATE_KEY_FILE) {\n // If the private key file is not loaded, try to load it from the environment\n const AUTH_KEY = env(ctx).AUTH_KEY as string | undefined\n\n API_PRIVATE_KEY_FILE = AUTH_KEY ? JSON.parse(AUTH_KEY) : undefined\n }\n\n if (!API_PRIVATE_KEY_FILE) {\n throw new Error(\n 'You have initialized the auth middleware without a private key file'\n )\n }\n\n const AUTH_PROJECT_ID = env(ctx).AUTH_PROJECT_ID\n\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 if (!API_PRIVATE_KEY_FILE) {\n throw new Error('Internal error: API_PRIVATE_KEY_FILE is not set')\n }\n\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 sendFunctionEvent({\n name: 'authInitialize',\n duration: 0\n }).then(() => {})\n\n return middleware\n}\n\nexport type AuthRequireChecks = {\n roles?: string[]\n}\n\nconst authRequire = (checks: AuthRequireChecks = {}) => {\n sendFunctionEvent({\n name: 'authRequire',\n duration: 0\n }).then(() => {})\n\n const middleware: MiddlewareHandler<{\n Variables: {\n auth?: AuthState\n }\n }> = async (ctx, next) => {\n const AUTH_PROJECT_ID = env(ctx).AUTH_PROJECT_ID\n\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 ContentfulStatusCode, {res: resError})\n }\n }\n\n return next()\n }\n\n sendFunctionEvent({\n name: 'authRequire',\n duration: 0\n }).then(() => {})\n\n return middleware\n}\n\nexport const auth = {\n initialize: authInitialize,\n require: authRequire\n}\n\nexport {requireAuth} from './decorators/requireAuth'\n", "import {sendFunctionEvent} from '@getcronit/pylon-telemetry'\nimport {HTTPException} from 'hono/http-exception'\n\nimport {AuthRequireChecks, auth} from '..'\nimport {getContext} from '../../context'\nimport {ServiceError} from '../../define-pylon'\nimport {createDecorator} from '../../create-decorator'\n\nexport function requireAuth(checks?: AuthRequireChecks) {\n sendFunctionEvent({\n name: 'requireAuth',\n duration: 0\n }).then(() => {})\n\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 createDecorator(async () => {\n const ctx = getContext()\n\n await checkAuth(ctx)\n })\n}\n", "import {sendFunctionEvent} from '@getcronit/pylon-telemetry'\n\nexport function createDecorator(callback: (...args: any[]) => Promise<void>) {\n sendFunctionEvent({\n name: 'createDecorator',\n duration: 0\n }).then(() => {})\n\n function MyDecorator<T extends (...args: any[]) => any>(\n target: Object,\n propertyKey: string | symbol\n ): void\n\n function MyDecorator<T>(fn: T): T\n\n function MyDecorator<T>(\n arg1: Object | T,\n propertyKey?: string | symbol,\n descriptor?: PropertyDescriptor\n ): any {\n if (descriptor) {\n const originalMethod = descriptor.value as T\n\n descriptor.value = async function (...args: any[]) {\n await callback(...args)\n return (originalMethod as any).apply(this, args)\n }\n\n return descriptor\n } else {\n if (!descriptor) {\n if (propertyKey === undefined) {\n const originalFunction = arg1 as T\n\n return async function (\n ...args: Parameters<any>\n ): Promise<ReturnType<any>> {\n await callback(...args)\n return (originalFunction as any)(...args)\n } as T\n }\n\n let value: any = arg1[propertyKey]\n Object.defineProperty(arg1, propertyKey, {\n get: function () {\n return async function (...args: Parameters<any>) {\n await callback(...args)\n if (typeof value === 'function') {\n return value(...args)\n }\n\n return value\n }\n },\n set: function (newValue) {\n value = newValue\n },\n enumerable: true,\n configurable: true\n })\n\n return\n }\n }\n }\n\n return MyDecorator\n}\n", "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", "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", "import {createSchema, createYoga} from 'graphql-yoga'\nimport {GraphQLScalarType, Kind} from 'graphql'\nimport {\n DateTimeISOResolver,\n GraphQLVoid,\n JSONObjectResolver,\n JSONResolver\n} from 'graphql-scalars'\n\nimport {useSentry} from '../envelop/use-sentry'\nimport {Context} from '../../context'\nimport {resolversToGraphQLResolvers} from '../../define-pylon'\nimport {PylonConfig} from '../..'\nimport {readFileSync} from 'fs'\nimport path from 'path'\n\ninterface PylonHandlerOptions {\n graphql: {\n Query: Record<string, any>\n Mutation?: Record<string, any>\n Subscription?: Record<string, any>\n }\n config?: PylonConfig\n}\n\nexport const handler = (options: PylonHandlerOptions) => {\n let {typeDefs, resolvers, graphql, config} =\n options as PylonHandlerOptions & {\n typeDefs?: string\n resolvers?: Record<string, any>\n }\n\n if (!typeDefs) {\n // Try to read the schema from the default location\n const schemaPath = path.join(process.cwd(), '.pylon', 'schema.graphql')\n\n // If `schemaPath` is provided, read the schema from the file\n if (schemaPath) {\n typeDefs = readFileSync(schemaPath, 'utf-8')\n }\n }\n\n if (!typeDefs) {\n throw new Error('No schema provided.')\n }\n\n if (!resolvers) {\n // Try to read the resolvers from the default location\n const resolversPath = path.join(process.cwd(), '.pylon', 'resolvers.js')\n\n // If `resolversPath` is provided, read the resolvers from the file\n\n if (resolversPath) {\n resolvers = require(resolversPath).resolvers\n }\n }\n\n const graphqlResolvers = resolversToGraphQLResolvers(graphql)\n\n const schema = createSchema<Context>({\n typeDefs,\n resolvers: {\n ...graphqlResolvers,\n ...resolvers,\n // Transforms a date object to a timestamp\n Date: DateTimeISOResolver,\n JSON: JSONResolver,\n Object: JSONObjectResolver,\n Void: GraphQLVoid,\n Number: new GraphQLScalarType({\n name: 'Number',\n description: 'Custom scalar that handles both integers and floats',\n\n // Parsing input from query variables\n parseValue(value) {\n if (typeof value !== 'number') {\n throw new TypeError(`Value is not a number: ${value}`)\n }\n return value // Valid number\n },\n\n // Validation when sending from client (input literals)\n parseLiteral(ast) {\n if (ast.kind === Kind.INT || ast.kind === Kind.FLOAT) {\n return parseFloat(ast.value) // Convert the value to a float\n }\n throw new TypeError(\n `Value is not a valid number or float: ${\n 'value' in ast ? ast.value : ast\n }`\n )\n },\n\n // Serialize output to be sent to the client\n serialize(value) {\n if (typeof value !== 'number') {\n throw new TypeError(`Value is not a number: ${value}`)\n }\n return value\n }\n })\n }\n })\n\n const yoga = createYoga({\n landingPage: false,\n graphiql: req => {\n return {\n shouldPersistHeaders: true,\n title: 'Pylon Playground',\n defaultQuery: `# Welcome to the Pylon Playground!`\n }\n },\n graphqlEndpoint: '/graphql',\n ...config,\n plugins: [useSentry(), ...(config?.plugins || [])],\n schema\n })\n\n const handler = async (c: Context): Promise<Response> => {\n let executionContext: Context['executionCtx'] | {} = {}\n\n try {\n executionContext = c.executionCtx\n } catch (e) {}\n\n const response = await yoga.fetch(c.req.raw, c.env, executionContext)\n\n return c.newResponse(response.body, response)\n }\n\n return handler\n}\n", "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", "import {sendFunctionEvent} from '@getcronit/pylon-telemetry'\nimport {asyncContext, Context} from './context'\n\nexport function getEnv() {\n const start = Date.now()\n const skipTracing = arguments[0] === true\n\n try {\n const context = asyncContext.getStore() as Context\n\n // Fall back to process.env or an empty object if no context is available\n // This is useful for testing\n // ref: https://hono.dev/docs/guides/testing#env\n return context.env || process.env || {}\n } catch {\n return process.env\n } finally {\n if (!skipTracing) {\n sendFunctionEvent({\n name: 'getEnv',\n duration: Date.now() - start\n }).then(() => {})\n }\n }\n}\n", "import {YogaServerOptions} from 'graphql-yoga'\nimport {Context} from './context.js'\n\nexport {ServiceError} from './define-pylon.js'\nexport * from './auth/index.js'\nexport {\n Context,\n Env,\n Variables,\n Bindings,\n asyncContext,\n getContext,\n setContext\n} from './context.js'\nexport {app} from './app/index.js'\nexport {handler} from './app/handler/pylon-handler.js'\nexport {getEnv} from './get-env.js'\nexport {createDecorator} from './create-decorator.js'\nexport {createPubSub as experimentalCreatePubSub} from 'graphql-yoga'\n\nexport type PylonConfig = Pick<YogaServerOptions<Context, Context>, 'plugins'>\n\nexport type ID = string & {readonly brand?: unique symbol}\nexport type Int = number & {readonly brand?: unique symbol}\nexport type Float = number & {readonly brand?: unique symbol}\n"],
5
+ "mappings": "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",
6
+ "names": ["ctx", "auth", "HTTPException", "env", "Sentry", "sendFunctionEvent", "sendFunctionEvent", "sendFunctionEvent", "sendFunctionEvent", "env", "auth", "sendFunctionEvent", "HTTPException", "Kind", "Sentry", "readFileSync", "path", "path", "readFileSync", "Kind", "handler", "sendFunctionEvent", "sendFunctionEvent"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getcronit/pylon",
3
- "version": "2.9.3",
3
+ "version": "2.9.4",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "openid-client": "^5.6.4",
31
31
  "toucan-js": "^4.1.0",
32
32
  "winston": "^3.8.2",
33
- "@getcronit/pylon-telemetry": "^1.0.2"
33
+ "@getcronit/pylon-telemetry": "^1.0.3"
34
34
  },
35
35
  "engines": {
36
36
  "node": ">=18.0.0"