@makerx/graphql-core 3.2.0 → 3.4.0

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.
Files changed (51) hide show
  1. package/README.md +68 -10
  2. package/context.d.cts +7 -0
  3. package/context.d.mts +7 -0
  4. package/context.d.ts +7 -0
  5. package/context.js +6 -5
  6. package/context.js.map +1 -1
  7. package/context.mjs +6 -5
  8. package/context.mjs.map +1 -1
  9. package/deprecation.d.cts +81 -0
  10. package/deprecation.d.mts +81 -0
  11. package/deprecation.d.ts +81 -0
  12. package/deprecation.js +240 -0
  13. package/deprecation.js.map +1 -0
  14. package/deprecation.mjs +235 -0
  15. package/deprecation.mjs.map +1 -0
  16. package/index.d.cts +1 -0
  17. package/index.d.mts +1 -0
  18. package/index.d.ts +1 -0
  19. package/index.js +5 -0
  20. package/index.js.map +1 -1
  21. package/index.mjs +1 -0
  22. package/index.mjs.map +1 -1
  23. package/logging.d.cts +17 -2
  24. package/logging.d.mts +17 -2
  25. package/logging.d.ts +17 -2
  26. package/logging.js +21 -3
  27. package/logging.js.map +1 -1
  28. package/logging.mjs +21 -3
  29. package/logging.mjs.map +1 -1
  30. package/package.json +1 -1
  31. package/subscriptions/context.d.cts +7 -0
  32. package/subscriptions/context.d.mts +7 -0
  33. package/subscriptions/context.d.ts +7 -0
  34. package/subscriptions/context.js +5 -5
  35. package/subscriptions/context.js.map +1 -1
  36. package/subscriptions/context.mjs +6 -6
  37. package/subscriptions/context.mjs.map +1 -1
  38. package/subscriptions/server.d.cts +13 -2
  39. package/subscriptions/server.d.mts +13 -2
  40. package/subscriptions/server.d.ts +13 -2
  41. package/subscriptions/server.js +12 -6
  42. package/subscriptions/server.js.map +1 -1
  43. package/subscriptions/server.mjs +13 -7
  44. package/subscriptions/server.mjs.map +1 -1
  45. package/subscriptions/utils.d.cts +2 -0
  46. package/subscriptions/utils.d.mts +2 -0
  47. package/subscriptions/utils.d.ts +2 -0
  48. package/subscriptions/utils.js +2 -0
  49. package/subscriptions/utils.js.map +1 -1
  50. package/subscriptions/utils.mjs +2 -1
  51. package/subscriptions/utils.mjs.map +1 -1
package/logging.d.cts CHANGED
@@ -3,6 +3,7 @@ import type { ExecutionArgs, GraphQLFormattedError } from 'graphql';
3
3
  import { OperationTypeNode } from 'graphql';
4
4
  import type { ExecutionResult } from 'graphql-ws';
5
5
  import type { GraphQLContext } from './context';
6
+ import type { DeprecatedElementUsage } from './deprecation';
6
7
  type LogFunction = Logger['info'];
7
8
  export type LoggerLogFunctions<T extends Logger> = {
8
9
  [Property in keyof T]: LogFunction;
@@ -57,6 +58,16 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
57
58
  * Whether the operation is a subsequent payload of an incremental response.
58
59
  */
59
60
  isSubsequentPayload?: boolean;
61
+ /**
62
+ * Deprecated schema elements the operation used, as returned by `collectDeprecatedElementUsage`.
63
+ * Omitted from the log entry when empty.
64
+ */
65
+ deprecatedElements?: DeprecatedElementUsage[];
66
+ /**
67
+ * Whether a limit stopped deprecated element collection, meaning `deprecatedElements` may be
68
+ * incomplete. Omitted from the log entry when false.
69
+ */
70
+ deprecatedElementsTruncated?: boolean;
60
71
  /**
61
72
  * The logger to use.
62
73
  */
@@ -70,13 +81,17 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
70
81
  * Logs a GraphQL operation in a consistent format with the option of including any additional data.
71
82
  * Top level and result entries with null or undefined values will be omitted.
72
83
  */
73
- export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
74
- export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, }: {
84
+ export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, deprecatedElements, deprecatedElementsTruncated, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
85
+ export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, includeDeprecatedElements, }: {
75
86
  id?: string;
76
87
  args: ExecutionArgs;
77
88
  result?: ExecutionResult;
78
89
  message?: string;
79
90
  logLevel?: keyof LoggerLogFunctions<TLogger>;
80
91
  resolveLogger?: (context: GraphQLContext) => TLogger;
92
+ /**
93
+ * If true, deprecated schema elements the operation uses are collected and logged.
94
+ */
95
+ includeDeprecatedElements?: boolean;
81
96
  }) => void;
82
97
  export {};
package/logging.d.mts CHANGED
@@ -3,6 +3,7 @@ import type { ExecutionArgs, GraphQLFormattedError } from 'graphql';
3
3
  import { OperationTypeNode } from 'graphql';
4
4
  import type { ExecutionResult } from 'graphql-ws';
5
5
  import type { GraphQLContext } from './context.mjs';
6
+ import type { DeprecatedElementUsage } from './deprecation.mjs';
6
7
  type LogFunction = Logger['info'];
7
8
  export type LoggerLogFunctions<T extends Logger> = {
8
9
  [Property in keyof T]: LogFunction;
@@ -57,6 +58,16 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
57
58
  * Whether the operation is a subsequent payload of an incremental response.
58
59
  */
59
60
  isSubsequentPayload?: boolean;
61
+ /**
62
+ * Deprecated schema elements the operation used, as returned by `collectDeprecatedElementUsage`.
63
+ * Omitted from the log entry when empty.
64
+ */
65
+ deprecatedElements?: DeprecatedElementUsage[];
66
+ /**
67
+ * Whether a limit stopped deprecated element collection, meaning `deprecatedElements` may be
68
+ * incomplete. Omitted from the log entry when false.
69
+ */
70
+ deprecatedElementsTruncated?: boolean;
60
71
  /**
61
72
  * The logger to use.
62
73
  */
@@ -70,13 +81,17 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
70
81
  * Logs a GraphQL operation in a consistent format with the option of including any additional data.
71
82
  * Top level and result entries with null or undefined values will be omitted.
72
83
  */
73
- export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
74
- export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, }: {
84
+ export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, deprecatedElements, deprecatedElementsTruncated, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
85
+ export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, includeDeprecatedElements, }: {
75
86
  id?: string;
76
87
  args: ExecutionArgs;
77
88
  result?: ExecutionResult;
78
89
  message?: string;
79
90
  logLevel?: keyof LoggerLogFunctions<TLogger>;
80
91
  resolveLogger?: (context: GraphQLContext) => TLogger;
92
+ /**
93
+ * If true, deprecated schema elements the operation uses are collected and logged.
94
+ */
95
+ includeDeprecatedElements?: boolean;
81
96
  }) => void;
82
97
  export {};
package/logging.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { ExecutionArgs, GraphQLFormattedError } from 'graphql';
3
3
  import { OperationTypeNode } from 'graphql';
4
4
  import type { ExecutionResult } from 'graphql-ws';
5
5
  import type { GraphQLContext } from './context';
6
+ import type { DeprecatedElementUsage } from './deprecation';
6
7
  type LogFunction = Logger['info'];
7
8
  export type LoggerLogFunctions<T extends Logger> = {
8
9
  [Property in keyof T]: LogFunction;
@@ -57,6 +58,16 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
57
58
  * Whether the operation is a subsequent payload of an incremental response.
58
59
  */
59
60
  isSubsequentPayload?: boolean;
61
+ /**
62
+ * Deprecated schema elements the operation used, as returned by `collectDeprecatedElementUsage`.
63
+ * Omitted from the log entry when empty.
64
+ */
65
+ deprecatedElements?: DeprecatedElementUsage[];
66
+ /**
67
+ * Whether a limit stopped deprecated element collection, meaning `deprecatedElements` may be
68
+ * incomplete. Omitted from the log entry when false.
69
+ */
70
+ deprecatedElementsTruncated?: boolean;
60
71
  /**
61
72
  * The logger to use.
62
73
  */
@@ -70,13 +81,17 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
70
81
  * Logs a GraphQL operation in a consistent format with the option of including any additional data.
71
82
  * Top level and result entries with null or undefined values will be omitted.
72
83
  */
73
- export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
74
- export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, }: {
84
+ export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, deprecatedElements, deprecatedElementsTruncated, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
85
+ export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ id, args, result, message, logLevel, resolveLogger, includeDeprecatedElements, }: {
75
86
  id?: string;
76
87
  args: ExecutionArgs;
77
88
  result?: ExecutionResult;
78
89
  message?: string;
79
90
  logLevel?: keyof LoggerLogFunctions<TLogger>;
80
91
  resolveLogger?: (context: GraphQLContext) => TLogger;
92
+ /**
93
+ * If true, deprecated schema elements the operation uses are collected and logged.
94
+ */
95
+ includeDeprecatedElements?: boolean;
81
96
  }) => void;
82
97
  export {};
package/logging.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var nodeCommon = require('@makerx/node-common');
4
4
  var compat = require('es-toolkit/compat');
5
5
  var graphql = require('graphql');
6
+ var deprecation = require('./deprecation.js');
6
7
  var operation = require('./operation.js');
7
8
  var utils = require('./utils.js');
8
9
 
@@ -10,7 +11,7 @@ var utils = require('./utils.js');
10
11
  * Logs a GraphQL operation in a consistent format with the option of including any additional data.
11
12
  * Top level and result entries with null or undefined values will be omitted.
12
13
  */
13
- const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, operationName, query, variables, result, logger, logLevel = 'info', ...rest }) => {
14
+ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, operationName, query, variables, result, deprecatedElements, deprecatedElementsTruncated, logger, logLevel = 'info', ...rest }) => {
14
15
  const isIntrospection = query && operation.isIntrospectionQuery(query);
15
16
  if (nodeCommon.isLocalDev && isIntrospection)
16
17
  return;
@@ -22,17 +23,32 @@ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, ope
22
23
  duration: started ? Date.now() - started : undefined,
23
24
  result: result ? compat.omitBy(result, utils.isNil) : undefined,
24
25
  isIntrospectionQuery: isIntrospection || undefined,
26
+ deprecatedElements: deprecatedElements?.length ? deprecatedElements : undefined,
27
+ deprecatedElementsTruncated: deprecatedElementsTruncated || undefined,
25
28
  ...compat.omitBy(rest, utils.isNil),
26
29
  }, utils.isNil));
27
30
  };
28
- const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolveLogger, }) => {
31
+ const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolveLogger, includeDeprecatedElements, }) => {
29
32
  const logger = resolveLogger
30
33
  ? resolveLogger(args.contextValue)
31
34
  : args.contextValue.logger;
32
35
  if (!logger)
33
36
  return;
34
- const { operationName, variableValues, document } = args;
37
+ const { operationName, variableValues, document, schema } = args;
35
38
  const { data, ...resultWithoutData } = result ?? {};
39
+ let deprecatedElements;
40
+ let deprecatedElementsTruncated;
41
+ if (includeDeprecatedElements) {
42
+ try {
43
+ const usage = deprecation.collectDeprecatedElementUsage({ schema, document, operationName, variables: variableValues });
44
+ deprecatedElements = usage.elements;
45
+ deprecatedElementsTruncated = usage.truncated;
46
+ }
47
+ catch (error) {
48
+ // Telemetry must never take down the subscription that produced it.
49
+ logger.warn('Failed to collect deprecated schema element usage', { error, operationName });
50
+ }
51
+ }
36
52
  logGraphQLOperation({
37
53
  message,
38
54
  type: graphql.OperationTypeNode.SUBSCRIPTION,
@@ -41,6 +57,8 @@ const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolve
41
57
  query: graphql.print(document),
42
58
  variables: variableValues,
43
59
  result: resultWithoutData,
60
+ deprecatedElements,
61
+ deprecatedElementsTruncated,
44
62
  logger,
45
63
  logLevel,
46
64
  });
package/logging.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","sources":["../src/logging.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { isLocalDev } from '@makerx/node-common'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery } from './operation'\nimport { isNil } from './utils'\n\ntype LogFunction = Logger['info']\nexport type LoggerLogFunctions<T extends Logger> = {\n [Property in keyof T]: LogFunction\n}\n\n/**\n * Info for logging a GraphQL operation in a consistent format with the option of including any additional data.\n */\nexport interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extends Record<string, unknown> {\n /**\n * The message to log, defaults to 'GraphQL operation'.\n */\n message?: string\n /**\n * The timestamp when the operation started, if supplied, the duration will be logged.\n */\n started?: number\n /**\n * The type of GraphQL operation.\n */\n type?: OperationTypeNode | null\n /**\n * The name of the GraphQL operation.\n */\n operationName?: string | null\n /**\n * The formatted GraphQL query.\n */\n query?: string | null\n /**\n * The GraphQL variables.\n */\n variables?: Record<string, unknown> | null\n /**\n * The result of the GraphQL operation.\n * Generally, we don't log the data or extensions, just errors.\n */\n result?: {\n data?: Record<string, unknown> | null\n errors?: readonly GraphQLFormattedError[] | null\n extensions?: Record<string, unknown> | null\n hasNext?: boolean\n }\n /**\n * Whether the operation is an introspection query.\n */\n isIntrospectionQuery?: boolean\n /**\n * Whether the operation is part of an incremental response.\n */\n isIncrementalResponse?: boolean\n /**\n * Whether the operation is a subsequent payload of an incremental response.\n */\n isSubsequentPayload?: boolean\n /**\n * The logger to use.\n */\n logger: TLogger\n /**\n * The logger function to use, defaults to 'info'.\n */\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}\n\n/**\n * Logs a GraphQL operation in a consistent format with the option of including any additional data.\n * Top level and result entries with null or undefined values will be omitted.\n */\nexport const logGraphQLOperation = <TLogger extends Logger = Logger>({\n message = 'GraphQL operation',\n started,\n type,\n operationName,\n query,\n variables,\n result,\n logger,\n logLevel = 'info',\n ...rest\n}: GraphQLLogOperationInfo<TLogger>) => {\n const isIntrospection = query && isIntrospectionQuery(query)\n if (isLocalDev && isIntrospection) return\n logger[logLevel as keyof Logger](\n message,\n omitBy(\n {\n type,\n operationName,\n query,\n variables: variables && Object.keys(variables).length > 0 ? variables : undefined,\n duration: started ? Date.now() - started : undefined,\n result: result ? omitBy(result, isNil) : undefined,\n isIntrospectionQuery: isIntrospection || undefined,\n ...omitBy(rest, isNil),\n },\n isNil,\n ),\n )\n}\n\nexport const logSubscriptionOperation = <TLogger extends Logger = Logger>({\n id,\n args,\n result,\n message,\n logLevel,\n resolveLogger,\n}: {\n id?: string\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n resolveLogger?: (context: GraphQLContext) => TLogger\n}) => {\n const logger = resolveLogger\n ? resolveLogger(args.contextValue as GraphQLContext)\n : ((args.contextValue as GraphQLContext).logger as TLogger)\n if (!logger) return\n\n const { operationName, variableValues, document } = args\n const { data, ...resultWithoutData } = result ?? {}\n\n logGraphQLOperation({\n message,\n type: OperationTypeNode.SUBSCRIPTION,\n subscriptionId: id,\n operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n logger,\n logLevel,\n })\n}\n"],"names":["isIntrospectionQuery","isLocalDev","omitBy","isNil","OperationTypeNode","print"],"mappings":";;;;;;;;AA2EA;;;AAGG;AACI,MAAM,mBAAmB,GAAG,CAAkC,EACnE,OAAO,GAAG,mBAAmB,EAC7B,OAAO,EACP,IAAI,EACJ,aAAa,EACb,KAAK,EACL,SAAS,EACT,MAAM,EACN,MAAM,EACN,QAAQ,GAAG,MAAM,EACjB,GAAG,IAAI,EAC0B,KAAI;IACrC,MAAM,eAAe,GAAG,KAAK,IAAIA,8BAAoB,CAAC,KAAK,CAAC;IAC5D,IAAIC,qBAAU,IAAI,eAAe;QAAE;AACnC,IAAA,MAAM,CAAC,QAAwB,CAAC,CAC9B,OAAO,EACPC,aAAM,CACJ;QACE,IAAI;QACJ,aAAa;QACb,KAAK;QACL,SAAS,EAAE,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS;AACjF,QAAA,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS;AACpD,QAAA,MAAM,EAAE,MAAM,GAAGA,aAAM,CAAC,MAAM,EAAEC,WAAK,CAAC,GAAG,SAAS;QAClD,oBAAoB,EAAE,eAAe,IAAI,SAAS;AAClD,QAAA,GAAGD,aAAM,CAAC,IAAI,EAAEC,WAAK,CAAC;KACvB,EACDA,WAAK,CACN,CACF;AACH;AAEO,MAAM,wBAAwB,GAAG,CAAkC,EACxE,EAAE,EACF,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,GAQd,KAAI;IACH,MAAM,MAAM,GAAG;AACb,UAAE,aAAa,CAAC,IAAI,CAAC,YAA8B;AACnD,UAAI,IAAI,CAAC,YAA+B,CAAC,MAAkB;AAC7D,IAAA,IAAI,CAAC,MAAM;QAAE;IAEb,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI;IACxD,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE;AAEnD,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAEC,yBAAiB,CAAC,YAAY;AACpC,QAAA,cAAc,EAAE,EAAE;QAClB,aAAa;AACb,QAAA,KAAK,EAAEC,aAAK,CAAC,QAAQ,CAAC;AACtB,QAAA,SAAS,EAAE,cAAc;AACzB,QAAA,MAAM,EAAE,iBAAiB;QACzB,MAAM;QACN,QAAQ;AACT,KAAA,CAAC;AACJ;;;;;"}
1
+ {"version":3,"file":"logging.js","sources":["../src/logging.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { isLocalDev } from '@makerx/node-common'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport type { GraphQLContext } from './context'\nimport type { DeprecatedElementUsage } from './deprecation'\nimport { collectDeprecatedElementUsage } from './deprecation'\nimport { isIntrospectionQuery } from './operation'\nimport { isNil } from './utils'\n\ntype LogFunction = Logger['info']\nexport type LoggerLogFunctions<T extends Logger> = {\n [Property in keyof T]: LogFunction\n}\n\n/**\n * Info for logging a GraphQL operation in a consistent format with the option of including any additional data.\n */\nexport interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extends Record<string, unknown> {\n /**\n * The message to log, defaults to 'GraphQL operation'.\n */\n message?: string\n /**\n * The timestamp when the operation started, if supplied, the duration will be logged.\n */\n started?: number\n /**\n * The type of GraphQL operation.\n */\n type?: OperationTypeNode | null\n /**\n * The name of the GraphQL operation.\n */\n operationName?: string | null\n /**\n * The formatted GraphQL query.\n */\n query?: string | null\n /**\n * The GraphQL variables.\n */\n variables?: Record<string, unknown> | null\n /**\n * The result of the GraphQL operation.\n * Generally, we don't log the data or extensions, just errors.\n */\n result?: {\n data?: Record<string, unknown> | null\n errors?: readonly GraphQLFormattedError[] | null\n extensions?: Record<string, unknown> | null\n hasNext?: boolean\n }\n /**\n * Whether the operation is an introspection query.\n */\n isIntrospectionQuery?: boolean\n /**\n * Whether the operation is part of an incremental response.\n */\n isIncrementalResponse?: boolean\n /**\n * Whether the operation is a subsequent payload of an incremental response.\n */\n isSubsequentPayload?: boolean\n /**\n * Deprecated schema elements the operation used, as returned by `collectDeprecatedElementUsage`.\n * Omitted from the log entry when empty.\n */\n deprecatedElements?: DeprecatedElementUsage[]\n /**\n * Whether a limit stopped deprecated element collection, meaning `deprecatedElements` may be\n * incomplete. Omitted from the log entry when false.\n */\n deprecatedElementsTruncated?: boolean\n /**\n * The logger to use.\n */\n logger: TLogger\n /**\n * The logger function to use, defaults to 'info'.\n */\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}\n\n/**\n * Logs a GraphQL operation in a consistent format with the option of including any additional data.\n * Top level and result entries with null or undefined values will be omitted.\n */\nexport const logGraphQLOperation = <TLogger extends Logger = Logger>({\n message = 'GraphQL operation',\n started,\n type,\n operationName,\n query,\n variables,\n result,\n deprecatedElements,\n deprecatedElementsTruncated,\n logger,\n logLevel = 'info',\n ...rest\n}: GraphQLLogOperationInfo<TLogger>) => {\n const isIntrospection = query && isIntrospectionQuery(query)\n if (isLocalDev && isIntrospection) return\n logger[logLevel as keyof Logger](\n message,\n omitBy(\n {\n type,\n operationName,\n query,\n variables: variables && Object.keys(variables).length > 0 ? variables : undefined,\n duration: started ? Date.now() - started : undefined,\n result: result ? omitBy(result, isNil) : undefined,\n isIntrospectionQuery: isIntrospection || undefined,\n deprecatedElements: deprecatedElements?.length ? deprecatedElements : undefined,\n deprecatedElementsTruncated: deprecatedElementsTruncated || undefined,\n ...omitBy(rest, isNil),\n },\n isNil,\n ),\n )\n}\n\nexport const logSubscriptionOperation = <TLogger extends Logger = Logger>({\n id,\n args,\n result,\n message,\n logLevel,\n resolveLogger,\n includeDeprecatedElements,\n}: {\n id?: string\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n resolveLogger?: (context: GraphQLContext) => TLogger\n /**\n * If true, deprecated schema elements the operation uses are collected and logged.\n */\n includeDeprecatedElements?: boolean\n}) => {\n const logger = resolveLogger\n ? resolveLogger(args.contextValue as GraphQLContext)\n : ((args.contextValue as GraphQLContext).logger as TLogger)\n if (!logger) return\n\n const { operationName, variableValues, document, schema } = args\n const { data, ...resultWithoutData } = result ?? {}\n\n let deprecatedElements: DeprecatedElementUsage[] | undefined\n let deprecatedElementsTruncated: boolean | undefined\n if (includeDeprecatedElements) {\n try {\n const usage = collectDeprecatedElementUsage({ schema, document, operationName, variables: variableValues })\n deprecatedElements = usage.elements\n deprecatedElementsTruncated = usage.truncated\n } catch (error) {\n // Telemetry must never take down the subscription that produced it.\n logger.warn('Failed to collect deprecated schema element usage', { error, operationName })\n }\n }\n\n logGraphQLOperation({\n message,\n type: OperationTypeNode.SUBSCRIPTION,\n subscriptionId: id,\n operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n deprecatedElements,\n deprecatedElementsTruncated,\n logger,\n logLevel,\n })\n}\n"],"names":["isIntrospectionQuery","isLocalDev","omitBy","isNil","collectDeprecatedElementUsage","OperationTypeNode","print"],"mappings":";;;;;;;;;AAuFA;;;AAGG;AACI,MAAM,mBAAmB,GAAG,CAAkC,EACnE,OAAO,GAAG,mBAAmB,EAC7B,OAAO,EACP,IAAI,EACJ,aAAa,EACb,KAAK,EACL,SAAS,EACT,MAAM,EACN,kBAAkB,EAClB,2BAA2B,EAC3B,MAAM,EACN,QAAQ,GAAG,MAAM,EACjB,GAAG,IAAI,EAC0B,KAAI;IACrC,MAAM,eAAe,GAAG,KAAK,IAAIA,8BAAoB,CAAC,KAAK,CAAC;IAC5D,IAAIC,qBAAU,IAAI,eAAe;QAAE;AACnC,IAAA,MAAM,CAAC,QAAwB,CAAC,CAC9B,OAAO,EACPC,aAAM,CACJ;QACE,IAAI;QACJ,aAAa;QACb,KAAK;QACL,SAAS,EAAE,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS;AACjF,QAAA,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS;AACpD,QAAA,MAAM,EAAE,MAAM,GAAGA,aAAM,CAAC,MAAM,EAAEC,WAAK,CAAC,GAAG,SAAS;QAClD,oBAAoB,EAAE,eAAe,IAAI,SAAS;QAClD,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;QAC/E,2BAA2B,EAAE,2BAA2B,IAAI,SAAS;AACrE,QAAA,GAAGD,aAAM,CAAC,IAAI,EAAEC,WAAK,CAAC;KACvB,EACDA,WAAK,CACN,CACF;AACH;MAEa,wBAAwB,GAAG,CAAkC,EACxE,EAAE,EACF,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,EACb,yBAAyB,GAY1B,KAAI;IACH,MAAM,MAAM,GAAG;AACb,UAAE,aAAa,CAAC,IAAI,CAAC,YAA8B;AACnD,UAAI,IAAI,CAAC,YAA+B,CAAC,MAAkB;AAC7D,IAAA,IAAI,CAAC,MAAM;QAAE;IAEb,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE;AAEnD,IAAA,IAAI,kBAAwD;AAC5D,IAAA,IAAI,2BAAgD;IACpD,IAAI,yBAAyB,EAAE;AAC7B,QAAA,IAAI;AACF,YAAA,MAAM,KAAK,GAAGC,yCAA6B,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAC3G,YAAA,kBAAkB,GAAG,KAAK,CAAC,QAAQ;AACnC,YAAA,2BAA2B,GAAG,KAAK,CAAC,SAAS;QAC/C;QAAE,OAAO,KAAK,EAAE;;YAEd,MAAM,CAAC,IAAI,CAAC,mDAAmD,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC5F;IACF;AAEA,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAEC,yBAAiB,CAAC,YAAY;AACpC,QAAA,cAAc,EAAE,EAAE;QAClB,aAAa;AACb,QAAA,KAAK,EAAEC,aAAK,CAAC,QAAQ,CAAC;AACtB,QAAA,SAAS,EAAE,cAAc;AACzB,QAAA,MAAM,EAAE,iBAAiB;QACzB,kBAAkB;QAClB,2BAA2B;QAC3B,MAAM;QACN,QAAQ;AACT,KAAA,CAAC;AACJ;;;;;"}
package/logging.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isLocalDev } from '@makerx/node-common';
2
2
  import { omitBy } from 'es-toolkit/compat';
3
3
  import { print, OperationTypeNode } from 'graphql';
4
+ import { collectDeprecatedElementUsage } from './deprecation.mjs';
4
5
  import { isIntrospectionQuery } from './operation.mjs';
5
6
  import { isNil } from './utils.mjs';
6
7
 
@@ -8,7 +9,7 @@ import { isNil } from './utils.mjs';
8
9
  * Logs a GraphQL operation in a consistent format with the option of including any additional data.
9
10
  * Top level and result entries with null or undefined values will be omitted.
10
11
  */
11
- const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, operationName, query, variables, result, logger, logLevel = 'info', ...rest }) => {
12
+ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, operationName, query, variables, result, deprecatedElements, deprecatedElementsTruncated, logger, logLevel = 'info', ...rest }) => {
12
13
  const isIntrospection = query && isIntrospectionQuery(query);
13
14
  if (isLocalDev && isIntrospection)
14
15
  return;
@@ -20,17 +21,32 @@ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, ope
20
21
  duration: started ? Date.now() - started : undefined,
21
22
  result: result ? omitBy(result, isNil) : undefined,
22
23
  isIntrospectionQuery: isIntrospection || undefined,
24
+ deprecatedElements: deprecatedElements?.length ? deprecatedElements : undefined,
25
+ deprecatedElementsTruncated: deprecatedElementsTruncated || undefined,
23
26
  ...omitBy(rest, isNil),
24
27
  }, isNil));
25
28
  };
26
- const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolveLogger, }) => {
29
+ const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolveLogger, includeDeprecatedElements, }) => {
27
30
  const logger = resolveLogger
28
31
  ? resolveLogger(args.contextValue)
29
32
  : args.contextValue.logger;
30
33
  if (!logger)
31
34
  return;
32
- const { operationName, variableValues, document } = args;
35
+ const { operationName, variableValues, document, schema } = args;
33
36
  const { data, ...resultWithoutData } = result ?? {};
37
+ let deprecatedElements;
38
+ let deprecatedElementsTruncated;
39
+ if (includeDeprecatedElements) {
40
+ try {
41
+ const usage = collectDeprecatedElementUsage({ schema, document, operationName, variables: variableValues });
42
+ deprecatedElements = usage.elements;
43
+ deprecatedElementsTruncated = usage.truncated;
44
+ }
45
+ catch (error) {
46
+ // Telemetry must never take down the subscription that produced it.
47
+ logger.warn('Failed to collect deprecated schema element usage', { error, operationName });
48
+ }
49
+ }
34
50
  logGraphQLOperation({
35
51
  message,
36
52
  type: OperationTypeNode.SUBSCRIPTION,
@@ -39,6 +55,8 @@ const logSubscriptionOperation = ({ id, args, result, message, logLevel, resolve
39
55
  query: print(document),
40
56
  variables: variableValues,
41
57
  result: resultWithoutData,
58
+ deprecatedElements,
59
+ deprecatedElementsTruncated,
42
60
  logger,
43
61
  logLevel,
44
62
  });
package/logging.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"logging.mjs","sources":["../src/logging.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { isLocalDev } from '@makerx/node-common'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery } from './operation'\nimport { isNil } from './utils'\n\ntype LogFunction = Logger['info']\nexport type LoggerLogFunctions<T extends Logger> = {\n [Property in keyof T]: LogFunction\n}\n\n/**\n * Info for logging a GraphQL operation in a consistent format with the option of including any additional data.\n */\nexport interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extends Record<string, unknown> {\n /**\n * The message to log, defaults to 'GraphQL operation'.\n */\n message?: string\n /**\n * The timestamp when the operation started, if supplied, the duration will be logged.\n */\n started?: number\n /**\n * The type of GraphQL operation.\n */\n type?: OperationTypeNode | null\n /**\n * The name of the GraphQL operation.\n */\n operationName?: string | null\n /**\n * The formatted GraphQL query.\n */\n query?: string | null\n /**\n * The GraphQL variables.\n */\n variables?: Record<string, unknown> | null\n /**\n * The result of the GraphQL operation.\n * Generally, we don't log the data or extensions, just errors.\n */\n result?: {\n data?: Record<string, unknown> | null\n errors?: readonly GraphQLFormattedError[] | null\n extensions?: Record<string, unknown> | null\n hasNext?: boolean\n }\n /**\n * Whether the operation is an introspection query.\n */\n isIntrospectionQuery?: boolean\n /**\n * Whether the operation is part of an incremental response.\n */\n isIncrementalResponse?: boolean\n /**\n * Whether the operation is a subsequent payload of an incremental response.\n */\n isSubsequentPayload?: boolean\n /**\n * The logger to use.\n */\n logger: TLogger\n /**\n * The logger function to use, defaults to 'info'.\n */\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}\n\n/**\n * Logs a GraphQL operation in a consistent format with the option of including any additional data.\n * Top level and result entries with null or undefined values will be omitted.\n */\nexport const logGraphQLOperation = <TLogger extends Logger = Logger>({\n message = 'GraphQL operation',\n started,\n type,\n operationName,\n query,\n variables,\n result,\n logger,\n logLevel = 'info',\n ...rest\n}: GraphQLLogOperationInfo<TLogger>) => {\n const isIntrospection = query && isIntrospectionQuery(query)\n if (isLocalDev && isIntrospection) return\n logger[logLevel as keyof Logger](\n message,\n omitBy(\n {\n type,\n operationName,\n query,\n variables: variables && Object.keys(variables).length > 0 ? variables : undefined,\n duration: started ? Date.now() - started : undefined,\n result: result ? omitBy(result, isNil) : undefined,\n isIntrospectionQuery: isIntrospection || undefined,\n ...omitBy(rest, isNil),\n },\n isNil,\n ),\n )\n}\n\nexport const logSubscriptionOperation = <TLogger extends Logger = Logger>({\n id,\n args,\n result,\n message,\n logLevel,\n resolveLogger,\n}: {\n id?: string\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n resolveLogger?: (context: GraphQLContext) => TLogger\n}) => {\n const logger = resolveLogger\n ? resolveLogger(args.contextValue as GraphQLContext)\n : ((args.contextValue as GraphQLContext).logger as TLogger)\n if (!logger) return\n\n const { operationName, variableValues, document } = args\n const { data, ...resultWithoutData } = result ?? {}\n\n logGraphQLOperation({\n message,\n type: OperationTypeNode.SUBSCRIPTION,\n subscriptionId: id,\n operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n logger,\n logLevel,\n })\n}\n"],"names":[],"mappings":";;;;;;AA2EA;;;AAGG;AACI,MAAM,mBAAmB,GAAG,CAAkC,EACnE,OAAO,GAAG,mBAAmB,EAC7B,OAAO,EACP,IAAI,EACJ,aAAa,EACb,KAAK,EACL,SAAS,EACT,MAAM,EACN,MAAM,EACN,QAAQ,GAAG,MAAM,EACjB,GAAG,IAAI,EAC0B,KAAI;IACrC,MAAM,eAAe,GAAG,KAAK,IAAI,oBAAoB,CAAC,KAAK,CAAC;IAC5D,IAAI,UAAU,IAAI,eAAe;QAAE;AACnC,IAAA,MAAM,CAAC,QAAwB,CAAC,CAC9B,OAAO,EACP,MAAM,CACJ;QACE,IAAI;QACJ,aAAa;QACb,KAAK;QACL,SAAS,EAAE,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS;AACjF,QAAA,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS;AACpD,QAAA,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS;QAClD,oBAAoB,EAAE,eAAe,IAAI,SAAS;AAClD,QAAA,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;KACvB,EACD,KAAK,CACN,CACF;AACH;AAEO,MAAM,wBAAwB,GAAG,CAAkC,EACxE,EAAE,EACF,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,GAQd,KAAI;IACH,MAAM,MAAM,GAAG;AACb,UAAE,aAAa,CAAC,IAAI,CAAC,YAA8B;AACnD,UAAI,IAAI,CAAC,YAA+B,CAAC,MAAkB;AAC7D,IAAA,IAAI,CAAC,MAAM;QAAE;IAEb,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI;IACxD,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE;AAEnD,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAE,iBAAiB,CAAC,YAAY;AACpC,QAAA,cAAc,EAAE,EAAE;QAClB,aAAa;AACb,QAAA,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;AACtB,QAAA,SAAS,EAAE,cAAc;AACzB,QAAA,MAAM,EAAE,iBAAiB;QACzB,MAAM;QACN,QAAQ;AACT,KAAA,CAAC;AACJ;;;;"}
1
+ {"version":3,"file":"logging.mjs","sources":["../src/logging.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { isLocalDev } from '@makerx/node-common'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport type { GraphQLContext } from './context'\nimport type { DeprecatedElementUsage } from './deprecation'\nimport { collectDeprecatedElementUsage } from './deprecation'\nimport { isIntrospectionQuery } from './operation'\nimport { isNil } from './utils'\n\ntype LogFunction = Logger['info']\nexport type LoggerLogFunctions<T extends Logger> = {\n [Property in keyof T]: LogFunction\n}\n\n/**\n * Info for logging a GraphQL operation in a consistent format with the option of including any additional data.\n */\nexport interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extends Record<string, unknown> {\n /**\n * The message to log, defaults to 'GraphQL operation'.\n */\n message?: string\n /**\n * The timestamp when the operation started, if supplied, the duration will be logged.\n */\n started?: number\n /**\n * The type of GraphQL operation.\n */\n type?: OperationTypeNode | null\n /**\n * The name of the GraphQL operation.\n */\n operationName?: string | null\n /**\n * The formatted GraphQL query.\n */\n query?: string | null\n /**\n * The GraphQL variables.\n */\n variables?: Record<string, unknown> | null\n /**\n * The result of the GraphQL operation.\n * Generally, we don't log the data or extensions, just errors.\n */\n result?: {\n data?: Record<string, unknown> | null\n errors?: readonly GraphQLFormattedError[] | null\n extensions?: Record<string, unknown> | null\n hasNext?: boolean\n }\n /**\n * Whether the operation is an introspection query.\n */\n isIntrospectionQuery?: boolean\n /**\n * Whether the operation is part of an incremental response.\n */\n isIncrementalResponse?: boolean\n /**\n * Whether the operation is a subsequent payload of an incremental response.\n */\n isSubsequentPayload?: boolean\n /**\n * Deprecated schema elements the operation used, as returned by `collectDeprecatedElementUsage`.\n * Omitted from the log entry when empty.\n */\n deprecatedElements?: DeprecatedElementUsage[]\n /**\n * Whether a limit stopped deprecated element collection, meaning `deprecatedElements` may be\n * incomplete. Omitted from the log entry when false.\n */\n deprecatedElementsTruncated?: boolean\n /**\n * The logger to use.\n */\n logger: TLogger\n /**\n * The logger function to use, defaults to 'info'.\n */\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}\n\n/**\n * Logs a GraphQL operation in a consistent format with the option of including any additional data.\n * Top level and result entries with null or undefined values will be omitted.\n */\nexport const logGraphQLOperation = <TLogger extends Logger = Logger>({\n message = 'GraphQL operation',\n started,\n type,\n operationName,\n query,\n variables,\n result,\n deprecatedElements,\n deprecatedElementsTruncated,\n logger,\n logLevel = 'info',\n ...rest\n}: GraphQLLogOperationInfo<TLogger>) => {\n const isIntrospection = query && isIntrospectionQuery(query)\n if (isLocalDev && isIntrospection) return\n logger[logLevel as keyof Logger](\n message,\n omitBy(\n {\n type,\n operationName,\n query,\n variables: variables && Object.keys(variables).length > 0 ? variables : undefined,\n duration: started ? Date.now() - started : undefined,\n result: result ? omitBy(result, isNil) : undefined,\n isIntrospectionQuery: isIntrospection || undefined,\n deprecatedElements: deprecatedElements?.length ? deprecatedElements : undefined,\n deprecatedElementsTruncated: deprecatedElementsTruncated || undefined,\n ...omitBy(rest, isNil),\n },\n isNil,\n ),\n )\n}\n\nexport const logSubscriptionOperation = <TLogger extends Logger = Logger>({\n id,\n args,\n result,\n message,\n logLevel,\n resolveLogger,\n includeDeprecatedElements,\n}: {\n id?: string\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n resolveLogger?: (context: GraphQLContext) => TLogger\n /**\n * If true, deprecated schema elements the operation uses are collected and logged.\n */\n includeDeprecatedElements?: boolean\n}) => {\n const logger = resolveLogger\n ? resolveLogger(args.contextValue as GraphQLContext)\n : ((args.contextValue as GraphQLContext).logger as TLogger)\n if (!logger) return\n\n const { operationName, variableValues, document, schema } = args\n const { data, ...resultWithoutData } = result ?? {}\n\n let deprecatedElements: DeprecatedElementUsage[] | undefined\n let deprecatedElementsTruncated: boolean | undefined\n if (includeDeprecatedElements) {\n try {\n const usage = collectDeprecatedElementUsage({ schema, document, operationName, variables: variableValues })\n deprecatedElements = usage.elements\n deprecatedElementsTruncated = usage.truncated\n } catch (error) {\n // Telemetry must never take down the subscription that produced it.\n logger.warn('Failed to collect deprecated schema element usage', { error, operationName })\n }\n }\n\n logGraphQLOperation({\n message,\n type: OperationTypeNode.SUBSCRIPTION,\n subscriptionId: id,\n operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n deprecatedElements,\n deprecatedElementsTruncated,\n logger,\n logLevel,\n })\n}\n"],"names":[],"mappings":";;;;;;;AAuFA;;;AAGG;AACI,MAAM,mBAAmB,GAAG,CAAkC,EACnE,OAAO,GAAG,mBAAmB,EAC7B,OAAO,EACP,IAAI,EACJ,aAAa,EACb,KAAK,EACL,SAAS,EACT,MAAM,EACN,kBAAkB,EAClB,2BAA2B,EAC3B,MAAM,EACN,QAAQ,GAAG,MAAM,EACjB,GAAG,IAAI,EAC0B,KAAI;IACrC,MAAM,eAAe,GAAG,KAAK,IAAI,oBAAoB,CAAC,KAAK,CAAC;IAC5D,IAAI,UAAU,IAAI,eAAe;QAAE;AACnC,IAAA,MAAM,CAAC,QAAwB,CAAC,CAC9B,OAAO,EACP,MAAM,CACJ;QACE,IAAI;QACJ,aAAa;QACb,KAAK;QACL,SAAS,EAAE,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS;AACjF,QAAA,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS;AACpD,QAAA,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS;QAClD,oBAAoB,EAAE,eAAe,IAAI,SAAS;QAClD,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;QAC/E,2BAA2B,EAAE,2BAA2B,IAAI,SAAS;AACrE,QAAA,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;KACvB,EACD,KAAK,CACN,CACF;AACH;MAEa,wBAAwB,GAAG,CAAkC,EACxE,EAAE,EACF,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,EACb,yBAAyB,GAY1B,KAAI;IACH,MAAM,MAAM,GAAG;AACb,UAAE,aAAa,CAAC,IAAI,CAAC,YAA8B;AACnD,UAAI,IAAI,CAAC,YAA+B,CAAC,MAAkB;AAC7D,IAAA,IAAI,CAAC,MAAM;QAAE;IAEb,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE;AAEnD,IAAA,IAAI,kBAAwD;AAC5D,IAAA,IAAI,2BAAgD;IACpD,IAAI,yBAAyB,EAAE;AAC7B,QAAA,IAAI;AACF,YAAA,MAAM,KAAK,GAAG,6BAA6B,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAC3G,YAAA,kBAAkB,GAAG,KAAK,CAAC,QAAQ;AACnC,YAAA,2BAA2B,GAAG,KAAK,CAAC,SAAS;QAC/C;QAAE,OAAO,KAAK,EAAE;;YAEd,MAAM,CAAC,IAAI,CAAC,mDAAmD,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC5F;IACF;AAEA,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAE,iBAAiB,CAAC,YAAY;AACpC,QAAA,cAAc,EAAE,EAAE;QAClB,aAAa;AACb,QAAA,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;AACtB,QAAA,SAAS,EAAE,cAAc;AACzB,QAAA,MAAM,EAAE,iBAAiB;QACzB,kBAAkB;QAClB,2BAA2B;QAC3B,MAAM;QACN,QAAQ;AACT,KAAA,CAAC;AACJ;;;;"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "**"
5
5
  ],
6
6
  "name": "@makerx/graphql-core",
7
- "version": "3.2.0",
7
+ "version": "3.4.0",
8
8
  "private": false,
9
9
  "description": "A set of core GraphQL utilities that MakerX uses to build GraphQL APIs",
10
10
  "author": "MakerX",
@@ -10,12 +10,19 @@ export interface SubscriptionContextInput {
10
10
  export type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T;
11
11
  export type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>;
12
12
  export type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>;
13
+ export type ExtractSubscriptionToken = (input: Omit<SubscriptionContextInput, 'claims'>) => string | undefined;
13
14
  export type CreateSubscriptionContextConfig<TUser = User | undefined, TAugment extends Record<string, unknown> = Record<string, never>, TLogger extends Logger = Logger> = {
14
15
  requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger;
15
16
  augmentRequestInfo?: AugmentSubscriptionRequestInfo;
16
17
  claimsToLog?: string[];
17
18
  requestInfoToLog?: Array<RequestInfoLogKey>;
18
19
  augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>;
20
+ /**
21
+ * Returns the token that the default `createUser` sets as `User.token`. Use the same function as
22
+ * the `useSubscriptionsServer` `extractToken` option. Not called when you supply `createUser`.
23
+ * Defaults to the bearer token in the `authorization` or `Authorization` connection parameter.
24
+ */
25
+ extractToken?: ExtractSubscriptionToken;
19
26
  } & ([User | undefined] extends [TUser] ? {
20
27
  createUser?: CreateSubscriptionUser<TUser>;
21
28
  } : {
@@ -10,12 +10,19 @@ export interface SubscriptionContextInput {
10
10
  export type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T;
11
11
  export type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>;
12
12
  export type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>;
13
+ export type ExtractSubscriptionToken = (input: Omit<SubscriptionContextInput, 'claims'>) => string | undefined;
13
14
  export type CreateSubscriptionContextConfig<TUser = User | undefined, TAugment extends Record<string, unknown> = Record<string, never>, TLogger extends Logger = Logger> = {
14
15
  requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger;
15
16
  augmentRequestInfo?: AugmentSubscriptionRequestInfo;
16
17
  claimsToLog?: string[];
17
18
  requestInfoToLog?: Array<RequestInfoLogKey>;
18
19
  augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>;
20
+ /**
21
+ * Returns the token that the default `createUser` sets as `User.token`. Use the same function as
22
+ * the `useSubscriptionsServer` `extractToken` option. Not called when you supply `createUser`.
23
+ * Defaults to the bearer token in the `authorization` or `Authorization` connection parameter.
24
+ */
25
+ extractToken?: ExtractSubscriptionToken;
19
26
  } & ([User | undefined] extends [TUser] ? {
20
27
  createUser?: CreateSubscriptionUser<TUser>;
21
28
  } : {
@@ -10,12 +10,19 @@ export interface SubscriptionContextInput {
10
10
  export type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T;
11
11
  export type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>;
12
12
  export type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>;
13
+ export type ExtractSubscriptionToken = (input: Omit<SubscriptionContextInput, 'claims'>) => string | undefined;
13
14
  export type CreateSubscriptionContextConfig<TUser = User | undefined, TAugment extends Record<string, unknown> = Record<string, never>, TLogger extends Logger = Logger> = {
14
15
  requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger;
15
16
  augmentRequestInfo?: AugmentSubscriptionRequestInfo;
16
17
  claimsToLog?: string[];
17
18
  requestInfoToLog?: Array<RequestInfoLogKey>;
18
19
  augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>;
20
+ /**
21
+ * Returns the token that the default `createUser` sets as `User.token`. Use the same function as
22
+ * the `useSubscriptionsServer` `extractToken` option. Not called when you supply `createUser`.
23
+ * Defaults to the bearer token in the `authorization` or `Authorization` connection parameter.
24
+ */
25
+ extractToken?: ExtractSubscriptionToken;
19
26
  } & ([User | undefined] extends [TUser] ? {
20
27
  createUser?: CreateSubscriptionUser<TUser>;
21
28
  } : {
@@ -9,7 +9,8 @@ const createSubscriptionContextFactory = (config) => {
9
9
  const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config;
10
10
  // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided
11
11
  // when TUser is narrower than `User | undefined`, so defaulting is sound here.
12
- const createUser = (config.createUser ?? defaultCreateUser);
12
+ const createUser = (config.createUser ??
13
+ buildDefaultCreateUser(config.extractToken ?? utils.defaultExtractSubscriptionToken));
13
14
  return async (input) => {
14
15
  const { connectRequest: req, claims } = input;
15
16
  // build request info from the connect request and socket
@@ -44,11 +45,10 @@ const createSubscriptionContextFactory = (config) => {
44
45
  return augmentedGraphQLContext;
45
46
  };
46
47
  };
47
- const defaultCreateUser = ({ claims, connectionParams }) => {
48
- if (!claims)
48
+ const buildDefaultCreateUser = (extractToken) => (input) => {
49
+ if (!input.claims)
49
50
  return Promise.resolve(undefined);
50
- const accessToken = utils.extractTokenFromConnectionParams(connectionParams);
51
- return Promise.resolve(new User.User(claims, accessToken ?? ''));
51
+ return Promise.resolve(new User.User(input.claims, extractToken(input) ?? ''));
52
52
  };
53
53
 
54
54
  exports.createSubscriptionContextFactory = createSubscriptionContextFactory;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sources":["../../src/subscriptions/context.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { pick } from 'es-toolkit/compat'\nimport type { IncomingMessage } from 'http'\nimport { User } from '../User'\nimport type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo, RequestInfoLogKey } from '../context'\nimport { buildConnectRequestInfo } from '../request-info'\nimport { extractTokenFromConnectionParams } from './utils'\n\nexport interface SubscriptionContextInput {\n connectRequest: IncomingMessage\n connectionParams?: Readonly<Record<string, unknown>>\n claims?: JwtPayload\n}\n\nexport type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T\nexport type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>\nexport type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>\n\n// `createUser` is optional when TUser is compatible with the default `User | undefined`\n// (i.e. defaultCreateUser can satisfy it), and required when TUser is narrower.\nexport type CreateSubscriptionContextConfig<\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n> = {\n requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger\n augmentRequestInfo?: AugmentSubscriptionRequestInfo\n claimsToLog?: string[]\n requestInfoToLog?: Array<RequestInfoLogKey>\n augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>\n} & ([User | undefined] extends [TUser] ? { createUser?: CreateSubscriptionUser<TUser> } : { createUser: CreateSubscriptionUser<TUser> })\n\nexport const createSubscriptionContextFactory = <\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n>(\n config: CreateSubscriptionContextConfig<TUser, TAugment, TLogger>,\n): CreateSubscriptionContext<GraphQLContext<TLogger, RequestInfo, TUser> & TAugment> => {\n const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config\n // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided\n // when TUser is narrower than `User | undefined`, so defaulting is sound here.\n const createUser = (config.createUser ?? defaultCreateUser) as CreateSubscriptionUser<TUser>\n\n return async (input: SubscriptionContextInput) => {\n const { connectRequest: req, claims } = input\n\n // build request info from the connect request and socket\n const requestInfo: RequestInfo = {\n ...buildConnectRequestInfo(req),\n ...augmentRequestInfo?.(input),\n }\n\n const user = await createUser(input)\n\n // create request logger\n let logger: TLogger\n if (typeof requestLogger === 'function') {\n // build request logger metadata\n const requestLoggerMetadata: Record<string, unknown> = {}\n // add request info to log\n if (requestInfoToLog?.length) requestLoggerMetadata.request = pick(requestInfo, requestInfoToLog)\n // add user claims to log\n if (claims && claimsToLog?.length) requestLoggerMetadata.user = pick(claims, claimsToLog)\n // build the request logger\n logger = requestLogger(requestLoggerMetadata, user)\n } else logger = requestLogger\n\n const graphqlContext: GraphQLContext<TLogger, RequestInfo, TUser> = {\n requestInfo,\n logger,\n user,\n started: Date.now(),\n }\n\n const augmentedGraphQLContext = augmentContext ? { ...graphqlContext, ...(await augmentContext(graphqlContext)) } : graphqlContext\n\n return augmentedGraphQLContext as GraphQLContext<TLogger, RequestInfo, TUser> & TAugment\n }\n}\n\nconst defaultCreateUser: CreateSubscriptionUser<User | undefined> = ({ claims, connectionParams }) => {\n if (!claims) return Promise.resolve(undefined)\n const accessToken = extractTokenFromConnectionParams(connectionParams)\n return Promise.resolve(new User(claims, accessToken ?? ''))\n}\n"],"names":["requestInfo","buildConnectRequestInfo","pick","extractTokenFromConnectionParams","User"],"mappings":";;;;;;;AAgCO,MAAM,gCAAgC,GAAG,CAK9C,MAAiE,KACoB;AACrF,IAAA,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,MAAM;;;IAGnG,MAAM,UAAU,IAAI,MAAM,CAAC,UAAU,IAAI,iBAAiB,CAAkC;AAE5F,IAAA,OAAO,OAAO,KAA+B,KAAI;QAC/C,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK;;AAG7C,QAAA,MAAMA,aAAW,GAAgB;YAC/B,GAAGC,mCAAuB,CAAC,GAAG,CAAC;AAC/B,YAAA,GAAG,kBAAkB,GAAG,KAAK,CAAC;SAC/B;AAED,QAAA,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC;;AAGpC,QAAA,IAAI,MAAe;AACnB,QAAA,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;;YAEvC,MAAM,qBAAqB,GAA4B,EAAE;;YAEzD,IAAI,gBAAgB,EAAE,MAAM;gBAAE,qBAAqB,CAAC,OAAO,GAAGC,WAAI,CAACF,aAAW,EAAE,gBAAgB,CAAC;;AAEjG,YAAA,IAAI,MAAM,IAAI,WAAW,EAAE,MAAM;gBAAE,qBAAqB,CAAC,IAAI,GAAGE,WAAI,CAAC,MAAM,EAAE,WAAW,CAAC;;AAEzF,YAAA,MAAM,GAAG,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACrD;;YAAO,MAAM,GAAG,aAAa;AAE7B,QAAA,MAAM,cAAc,GAAgD;yBAClEF,aAAW;YACX,MAAM;YACN,IAAI;AACJ,YAAA,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;SACpB;QAED,MAAM,uBAAuB,GAAG,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,IAAI,MAAM,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,cAAc;AAElI,QAAA,OAAO,uBAAiF;AAC1F,IAAA,CAAC;AACH;AAEA,MAAM,iBAAiB,GAA6C,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAI;AACnG,IAAA,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;AAC9C,IAAA,MAAM,WAAW,GAAGG,sCAAgC,CAAC,gBAAgB,CAAC;AACtE,IAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAIC,SAAI,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;;;;"}
1
+ {"version":3,"file":"context.js","sources":["../../src/subscriptions/context.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { pick } from 'es-toolkit/compat'\nimport type { IncomingMessage } from 'http'\nimport { User } from '../User'\nimport type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo, RequestInfoLogKey } from '../context'\nimport { buildConnectRequestInfo } from '../request-info'\nimport { defaultExtractSubscriptionToken } from './utils'\n\nexport interface SubscriptionContextInput {\n connectRequest: IncomingMessage\n connectionParams?: Readonly<Record<string, unknown>>\n claims?: JwtPayload\n}\n\nexport type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T\nexport type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>\nexport type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>\n// The token is extracted before the connection is authenticated, so the input has no claims.\nexport type ExtractSubscriptionToken = (input: Omit<SubscriptionContextInput, 'claims'>) => string | undefined\n\n// `createUser` is optional when TUser is compatible with the default `User | undefined`\n// (i.e. defaultCreateUser can satisfy it), and required when TUser is narrower.\nexport type CreateSubscriptionContextConfig<\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n> = {\n requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger\n augmentRequestInfo?: AugmentSubscriptionRequestInfo\n claimsToLog?: string[]\n requestInfoToLog?: Array<RequestInfoLogKey>\n augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>\n /**\n * Returns the token that the default `createUser` sets as `User.token`. Use the same function as\n * the `useSubscriptionsServer` `extractToken` option. Not called when you supply `createUser`.\n * Defaults to the bearer token in the `authorization` or `Authorization` connection parameter.\n */\n extractToken?: ExtractSubscriptionToken\n} & ([User | undefined] extends [TUser] ? { createUser?: CreateSubscriptionUser<TUser> } : { createUser: CreateSubscriptionUser<TUser> })\n\nexport const createSubscriptionContextFactory = <\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n>(\n config: CreateSubscriptionContextConfig<TUser, TAugment, TLogger>,\n): CreateSubscriptionContext<GraphQLContext<TLogger, RequestInfo, TUser> & TAugment> => {\n const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config\n // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided\n // when TUser is narrower than `User | undefined`, so defaulting is sound here.\n const createUser = (config.createUser ??\n buildDefaultCreateUser(config.extractToken ?? defaultExtractSubscriptionToken)) as CreateSubscriptionUser<TUser>\n\n return async (input: SubscriptionContextInput) => {\n const { connectRequest: req, claims } = input\n\n // build request info from the connect request and socket\n const requestInfo: RequestInfo = {\n ...buildConnectRequestInfo(req),\n ...augmentRequestInfo?.(input),\n }\n\n const user = await createUser(input)\n\n // create request logger\n let logger: TLogger\n if (typeof requestLogger === 'function') {\n // build request logger metadata\n const requestLoggerMetadata: Record<string, unknown> = {}\n // add request info to log\n if (requestInfoToLog?.length) requestLoggerMetadata.request = pick(requestInfo, requestInfoToLog)\n // add user claims to log\n if (claims && claimsToLog?.length) requestLoggerMetadata.user = pick(claims, claimsToLog)\n // build the request logger\n logger = requestLogger(requestLoggerMetadata, user)\n } else logger = requestLogger\n\n const graphqlContext: GraphQLContext<TLogger, RequestInfo, TUser> = {\n requestInfo,\n logger,\n user,\n started: Date.now(),\n }\n\n const augmentedGraphQLContext = augmentContext ? { ...graphqlContext, ...(await augmentContext(graphqlContext)) } : graphqlContext\n\n return augmentedGraphQLContext as GraphQLContext<TLogger, RequestInfo, TUser> & TAugment\n }\n}\n\nconst buildDefaultCreateUser =\n (extractToken: ExtractSubscriptionToken): CreateSubscriptionUser<User | undefined> =>\n (input) => {\n if (!input.claims) return Promise.resolve(undefined)\n return Promise.resolve(new User(input.claims, extractToken(input) ?? ''))\n }\n"],"names":["defaultExtractSubscriptionToken","requestInfo","buildConnectRequestInfo","pick","User"],"mappings":";;;;;;;AAwCO,MAAM,gCAAgC,GAAG,CAK9C,MAAiE,KACoB;AACrF,IAAA,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,MAAM;;;AAGnG,IAAA,MAAM,UAAU,IAAI,MAAM,CAAC,UAAU;QACnC,sBAAsB,CAAC,MAAM,CAAC,YAAY,IAAIA,qCAA+B,CAAC,CAAkC;AAElH,IAAA,OAAO,OAAO,KAA+B,KAAI;QAC/C,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK;;AAG7C,QAAA,MAAMC,aAAW,GAAgB;YAC/B,GAAGC,mCAAuB,CAAC,GAAG,CAAC;AAC/B,YAAA,GAAG,kBAAkB,GAAG,KAAK,CAAC;SAC/B;AAED,QAAA,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC;;AAGpC,QAAA,IAAI,MAAe;AACnB,QAAA,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;;YAEvC,MAAM,qBAAqB,GAA4B,EAAE;;YAEzD,IAAI,gBAAgB,EAAE,MAAM;gBAAE,qBAAqB,CAAC,OAAO,GAAGC,WAAI,CAACF,aAAW,EAAE,gBAAgB,CAAC;;AAEjG,YAAA,IAAI,MAAM,IAAI,WAAW,EAAE,MAAM;gBAAE,qBAAqB,CAAC,IAAI,GAAGE,WAAI,CAAC,MAAM,EAAE,WAAW,CAAC;;AAEzF,YAAA,MAAM,GAAG,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACrD;;YAAO,MAAM,GAAG,aAAa;AAE7B,QAAA,MAAM,cAAc,GAAgD;yBAClEF,aAAW;YACX,MAAM;YACN,IAAI;AACJ,YAAA,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;SACpB;QAED,MAAM,uBAAuB,GAAG,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,IAAI,MAAM,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,cAAc;AAElI,QAAA,OAAO,uBAAiF;AAC1F,IAAA,CAAC;AACH;AAEA,MAAM,sBAAsB,GAC1B,CAAC,YAAsC,KACvC,CAAC,KAAK,KAAI;IACR,IAAI,CAAC,KAAK,CAAC,MAAM;AAAE,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;AACpD,IAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAIG,SAAI,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3E,CAAC;;;;"}
@@ -1,13 +1,14 @@
1
1
  import { pick } from 'es-toolkit/compat';
2
2
  import { User } from '../User.mjs';
3
3
  import { buildConnectRequestInfo } from '../request-info.mjs';
4
- import { extractTokenFromConnectionParams } from './utils.mjs';
4
+ import { defaultExtractSubscriptionToken } from './utils.mjs';
5
5
 
6
6
  const createSubscriptionContextFactory = (config) => {
7
7
  const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config;
8
8
  // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided
9
9
  // when TUser is narrower than `User | undefined`, so defaulting is sound here.
10
- const createUser = (config.createUser ?? defaultCreateUser);
10
+ const createUser = (config.createUser ??
11
+ buildDefaultCreateUser(config.extractToken ?? defaultExtractSubscriptionToken));
11
12
  return async (input) => {
12
13
  const { connectRequest: req, claims } = input;
13
14
  // build request info from the connect request and socket
@@ -42,11 +43,10 @@ const createSubscriptionContextFactory = (config) => {
42
43
  return augmentedGraphQLContext;
43
44
  };
44
45
  };
45
- const defaultCreateUser = ({ claims, connectionParams }) => {
46
- if (!claims)
46
+ const buildDefaultCreateUser = (extractToken) => (input) => {
47
+ if (!input.claims)
47
48
  return Promise.resolve(undefined);
48
- const accessToken = extractTokenFromConnectionParams(connectionParams);
49
- return Promise.resolve(new User(claims, accessToken ?? ''));
49
+ return Promise.resolve(new User(input.claims, extractToken(input) ?? ''));
50
50
  };
51
51
 
52
52
  export { createSubscriptionContextFactory };
@@ -1 +1 @@
1
- {"version":3,"file":"context.mjs","sources":["../../src/subscriptions/context.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { pick } from 'es-toolkit/compat'\nimport type { IncomingMessage } from 'http'\nimport { User } from '../User'\nimport type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo, RequestInfoLogKey } from '../context'\nimport { buildConnectRequestInfo } from '../request-info'\nimport { extractTokenFromConnectionParams } from './utils'\n\nexport interface SubscriptionContextInput {\n connectRequest: IncomingMessage\n connectionParams?: Readonly<Record<string, unknown>>\n claims?: JwtPayload\n}\n\nexport type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T\nexport type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>\nexport type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>\n\n// `createUser` is optional when TUser is compatible with the default `User | undefined`\n// (i.e. defaultCreateUser can satisfy it), and required when TUser is narrower.\nexport type CreateSubscriptionContextConfig<\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n> = {\n requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger\n augmentRequestInfo?: AugmentSubscriptionRequestInfo\n claimsToLog?: string[]\n requestInfoToLog?: Array<RequestInfoLogKey>\n augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>\n} & ([User | undefined] extends [TUser] ? { createUser?: CreateSubscriptionUser<TUser> } : { createUser: CreateSubscriptionUser<TUser> })\n\nexport const createSubscriptionContextFactory = <\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n>(\n config: CreateSubscriptionContextConfig<TUser, TAugment, TLogger>,\n): CreateSubscriptionContext<GraphQLContext<TLogger, RequestInfo, TUser> & TAugment> => {\n const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config\n // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided\n // when TUser is narrower than `User | undefined`, so defaulting is sound here.\n const createUser = (config.createUser ?? defaultCreateUser) as CreateSubscriptionUser<TUser>\n\n return async (input: SubscriptionContextInput) => {\n const { connectRequest: req, claims } = input\n\n // build request info from the connect request and socket\n const requestInfo: RequestInfo = {\n ...buildConnectRequestInfo(req),\n ...augmentRequestInfo?.(input),\n }\n\n const user = await createUser(input)\n\n // create request logger\n let logger: TLogger\n if (typeof requestLogger === 'function') {\n // build request logger metadata\n const requestLoggerMetadata: Record<string, unknown> = {}\n // add request info to log\n if (requestInfoToLog?.length) requestLoggerMetadata.request = pick(requestInfo, requestInfoToLog)\n // add user claims to log\n if (claims && claimsToLog?.length) requestLoggerMetadata.user = pick(claims, claimsToLog)\n // build the request logger\n logger = requestLogger(requestLoggerMetadata, user)\n } else logger = requestLogger\n\n const graphqlContext: GraphQLContext<TLogger, RequestInfo, TUser> = {\n requestInfo,\n logger,\n user,\n started: Date.now(),\n }\n\n const augmentedGraphQLContext = augmentContext ? { ...graphqlContext, ...(await augmentContext(graphqlContext)) } : graphqlContext\n\n return augmentedGraphQLContext as GraphQLContext<TLogger, RequestInfo, TUser> & TAugment\n }\n}\n\nconst defaultCreateUser: CreateSubscriptionUser<User | undefined> = ({ claims, connectionParams }) => {\n if (!claims) return Promise.resolve(undefined)\n const accessToken = extractTokenFromConnectionParams(connectionParams)\n return Promise.resolve(new User(claims, accessToken ?? ''))\n}\n"],"names":[],"mappings":";;;;;AAgCO,MAAM,gCAAgC,GAAG,CAK9C,MAAiE,KACoB;AACrF,IAAA,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,MAAM;;;IAGnG,MAAM,UAAU,IAAI,MAAM,CAAC,UAAU,IAAI,iBAAiB,CAAkC;AAE5F,IAAA,OAAO,OAAO,KAA+B,KAAI;QAC/C,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK;;AAG7C,QAAA,MAAM,WAAW,GAAgB;YAC/B,GAAG,uBAAuB,CAAC,GAAG,CAAC;AAC/B,YAAA,GAAG,kBAAkB,GAAG,KAAK,CAAC;SAC/B;AAED,QAAA,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC;;AAGpC,QAAA,IAAI,MAAe;AACnB,QAAA,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;;YAEvC,MAAM,qBAAqB,GAA4B,EAAE;;YAEzD,IAAI,gBAAgB,EAAE,MAAM;gBAAE,qBAAqB,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC;;AAEjG,YAAA,IAAI,MAAM,IAAI,WAAW,EAAE,MAAM;gBAAE,qBAAqB,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;;AAEzF,YAAA,MAAM,GAAG,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACrD;;YAAO,MAAM,GAAG,aAAa;AAE7B,QAAA,MAAM,cAAc,GAAgD;YAClE,WAAW;YACX,MAAM;YACN,IAAI;AACJ,YAAA,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;SACpB;QAED,MAAM,uBAAuB,GAAG,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,IAAI,MAAM,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,cAAc;AAElI,QAAA,OAAO,uBAAiF;AAC1F,IAAA,CAAC;AACH;AAEA,MAAM,iBAAiB,GAA6C,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAI;AACnG,IAAA,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;AAC9C,IAAA,MAAM,WAAW,GAAG,gCAAgC,CAAC,gBAAgB,CAAC;AACtE,IAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;;;;"}
1
+ {"version":3,"file":"context.mjs","sources":["../../src/subscriptions/context.ts"],"sourcesContent":["import type { Logger } from '@makerx/node-common'\nimport { pick } from 'es-toolkit/compat'\nimport type { IncomingMessage } from 'http'\nimport { User } from '../User'\nimport type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo, RequestInfoLogKey } from '../context'\nimport { buildConnectRequestInfo } from '../request-info'\nimport { defaultExtractSubscriptionToken } from './utils'\n\nexport interface SubscriptionContextInput {\n connectRequest: IncomingMessage\n connectionParams?: Readonly<Record<string, unknown>>\n claims?: JwtPayload\n}\n\nexport type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T\nexport type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>\nexport type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>\n// The token is extracted before the connection is authenticated, so the input has no claims.\nexport type ExtractSubscriptionToken = (input: Omit<SubscriptionContextInput, 'claims'>) => string | undefined\n\n// `createUser` is optional when TUser is compatible with the default `User | undefined`\n// (i.e. defaultCreateUser can satisfy it), and required when TUser is narrower.\nexport type CreateSubscriptionContextConfig<\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n> = {\n requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger\n augmentRequestInfo?: AugmentSubscriptionRequestInfo\n claimsToLog?: string[]\n requestInfoToLog?: Array<RequestInfoLogKey>\n augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>\n /**\n * Returns the token that the default `createUser` sets as `User.token`. Use the same function as\n * the `useSubscriptionsServer` `extractToken` option. Not called when you supply `createUser`.\n * Defaults to the bearer token in the `authorization` or `Authorization` connection parameter.\n */\n extractToken?: ExtractSubscriptionToken\n} & ([User | undefined] extends [TUser] ? { createUser?: CreateSubscriptionUser<TUser> } : { createUser: CreateSubscriptionUser<TUser> })\n\nexport const createSubscriptionContextFactory = <\n TUser = User | undefined,\n TAugment extends Record<string, unknown> = Record<string, never>,\n TLogger extends Logger = Logger,\n>(\n config: CreateSubscriptionContextConfig<TUser, TAugment, TLogger>,\n): CreateSubscriptionContext<GraphQLContext<TLogger, RequestInfo, TUser> & TAugment> => {\n const { requestLogger, augmentRequestInfo, claimsToLog, requestInfoToLog, augmentContext } = config\n // The conditional type on CreateSubscriptionContextConfig guarantees `createUser` is provided\n // when TUser is narrower than `User | undefined`, so defaulting is sound here.\n const createUser = (config.createUser ??\n buildDefaultCreateUser(config.extractToken ?? defaultExtractSubscriptionToken)) as CreateSubscriptionUser<TUser>\n\n return async (input: SubscriptionContextInput) => {\n const { connectRequest: req, claims } = input\n\n // build request info from the connect request and socket\n const requestInfo: RequestInfo = {\n ...buildConnectRequestInfo(req),\n ...augmentRequestInfo?.(input),\n }\n\n const user = await createUser(input)\n\n // create request logger\n let logger: TLogger\n if (typeof requestLogger === 'function') {\n // build request logger metadata\n const requestLoggerMetadata: Record<string, unknown> = {}\n // add request info to log\n if (requestInfoToLog?.length) requestLoggerMetadata.request = pick(requestInfo, requestInfoToLog)\n // add user claims to log\n if (claims && claimsToLog?.length) requestLoggerMetadata.user = pick(claims, claimsToLog)\n // build the request logger\n logger = requestLogger(requestLoggerMetadata, user)\n } else logger = requestLogger\n\n const graphqlContext: GraphQLContext<TLogger, RequestInfo, TUser> = {\n requestInfo,\n logger,\n user,\n started: Date.now(),\n }\n\n const augmentedGraphQLContext = augmentContext ? { ...graphqlContext, ...(await augmentContext(graphqlContext)) } : graphqlContext\n\n return augmentedGraphQLContext as GraphQLContext<TLogger, RequestInfo, TUser> & TAugment\n }\n}\n\nconst buildDefaultCreateUser =\n (extractToken: ExtractSubscriptionToken): CreateSubscriptionUser<User | undefined> =>\n (input) => {\n if (!input.claims) return Promise.resolve(undefined)\n return Promise.resolve(new User(input.claims, extractToken(input) ?? ''))\n }\n"],"names":[],"mappings":";;;;;AAwCO,MAAM,gCAAgC,GAAG,CAK9C,MAAiE,KACoB;AACrF,IAAA,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,MAAM;;;AAGnG,IAAA,MAAM,UAAU,IAAI,MAAM,CAAC,UAAU;QACnC,sBAAsB,CAAC,MAAM,CAAC,YAAY,IAAI,+BAA+B,CAAC,CAAkC;AAElH,IAAA,OAAO,OAAO,KAA+B,KAAI;QAC/C,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK;;AAG7C,QAAA,MAAM,WAAW,GAAgB;YAC/B,GAAG,uBAAuB,CAAC,GAAG,CAAC;AAC/B,YAAA,GAAG,kBAAkB,GAAG,KAAK,CAAC;SAC/B;AAED,QAAA,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC;;AAGpC,QAAA,IAAI,MAAe;AACnB,QAAA,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;;YAEvC,MAAM,qBAAqB,GAA4B,EAAE;;YAEzD,IAAI,gBAAgB,EAAE,MAAM;gBAAE,qBAAqB,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC;;AAEjG,YAAA,IAAI,MAAM,IAAI,WAAW,EAAE,MAAM;gBAAE,qBAAqB,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;;AAEzF,YAAA,MAAM,GAAG,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACrD;;YAAO,MAAM,GAAG,aAAa;AAE7B,QAAA,MAAM,cAAc,GAAgD;YAClE,WAAW;YACX,MAAM;YACN,IAAI;AACJ,YAAA,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;SACpB;QAED,MAAM,uBAAuB,GAAG,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,IAAI,MAAM,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,cAAc;AAElI,QAAA,OAAO,uBAAiF;AAC1F,IAAA,CAAC;AACH;AAEA,MAAM,sBAAsB,GAC1B,CAAC,YAAsC,KACvC,CAAC,KAAK,KAAI;IACR,IAAI,CAAC,KAAK,CAAC,MAAM;AAAE,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;AACpD,IAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3E,CAAC;;;;"}
@@ -2,8 +2,8 @@ import type { Logger } from '@makerx/node-common';
2
2
  import type { GraphQLSchema } from 'graphql';
3
3
  import type { Server } from 'http';
4
4
  import type { GraphQLContext, JwtPayload } from '../context';
5
- import type { CreateSubscriptionContext } from './context';
6
- export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, }: {
5
+ import type { CreateSubscriptionContext, ExtractSubscriptionToken } from './context';
6
+ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, extractToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, includeDeprecatedElements, }: {
7
7
  schema: GraphQLSchema;
8
8
  httpServer: Server;
9
9
  createSubscriptionContext: CreateSubscriptionContext;
@@ -11,7 +11,18 @@ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>(
11
11
  operationLogLevel?: keyof TLogger;
12
12
  path?: string;
13
13
  verifyToken?: (host: string, token: string) => Promise<JwtPayload>;
14
+ /**
15
+ * Returns the token to pass to `verifyToken`, e.g. from a JWT assertion header that a proxy adds
16
+ * to the connect request. Defaults to the bearer token in the `authorization` or `Authorization`
17
+ * connection parameter. Pass the same function to `createSubscriptionContextFactory`.
18
+ */
19
+ extractToken?: ExtractSubscriptionToken;
14
20
  requireAuth?: boolean;
15
21
  jwtClaimsToLog?: string[];
16
22
  resolveSubscriptionOperationLogger?: (context: GraphQLContext) => TLogger;
23
+ /**
24
+ * If true, deprecated schema elements a subscription uses are collected and logged when it is
25
+ * established. Not collected per emitted payload: the usage is a property of the operation.
26
+ */
27
+ includeDeprecatedElements?: boolean;
17
28
  }): import("graphql-ws").Disposable;
@@ -2,8 +2,8 @@ import type { Logger } from '@makerx/node-common';
2
2
  import type { GraphQLSchema } from 'graphql';
3
3
  import type { Server } from 'http';
4
4
  import type { GraphQLContext, JwtPayload } from '../context.mjs';
5
- import type { CreateSubscriptionContext } from './context.mjs';
6
- export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, }: {
5
+ import type { CreateSubscriptionContext, ExtractSubscriptionToken } from './context.mjs';
6
+ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, extractToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, includeDeprecatedElements, }: {
7
7
  schema: GraphQLSchema;
8
8
  httpServer: Server;
9
9
  createSubscriptionContext: CreateSubscriptionContext;
@@ -11,7 +11,18 @@ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>(
11
11
  operationLogLevel?: keyof TLogger;
12
12
  path?: string;
13
13
  verifyToken?: (host: string, token: string) => Promise<JwtPayload>;
14
+ /**
15
+ * Returns the token to pass to `verifyToken`, e.g. from a JWT assertion header that a proxy adds
16
+ * to the connect request. Defaults to the bearer token in the `authorization` or `Authorization`
17
+ * connection parameter. Pass the same function to `createSubscriptionContextFactory`.
18
+ */
19
+ extractToken?: ExtractSubscriptionToken;
14
20
  requireAuth?: boolean;
15
21
  jwtClaimsToLog?: string[];
16
22
  resolveSubscriptionOperationLogger?: (context: GraphQLContext) => TLogger;
23
+ /**
24
+ * If true, deprecated schema elements a subscription uses are collected and logged when it is
25
+ * established. Not collected per emitted payload: the usage is a property of the operation.
26
+ */
27
+ includeDeprecatedElements?: boolean;
17
28
  }): import("graphql-ws").Disposable;
@@ -2,8 +2,8 @@ import type { Logger } from '@makerx/node-common';
2
2
  import type { GraphQLSchema } from 'graphql';
3
3
  import type { Server } from 'http';
4
4
  import type { GraphQLContext, JwtPayload } from '../context';
5
- import type { CreateSubscriptionContext } from './context';
6
- export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, }: {
5
+ import type { CreateSubscriptionContext, ExtractSubscriptionToken } from './context';
6
+ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>({ schema, httpServer, createSubscriptionContext, logger, operationLogLevel, path, verifyToken, extractToken, requireAuth, jwtClaimsToLog, resolveSubscriptionOperationLogger, includeDeprecatedElements, }: {
7
7
  schema: GraphQLSchema;
8
8
  httpServer: Server;
9
9
  createSubscriptionContext: CreateSubscriptionContext;
@@ -11,7 +11,18 @@ export declare function useSubscriptionsServer<TLogger extends Logger = Logger>(
11
11
  operationLogLevel?: keyof TLogger;
12
12
  path?: string;
13
13
  verifyToken?: (host: string, token: string) => Promise<JwtPayload>;
14
+ /**
15
+ * Returns the token to pass to `verifyToken`, e.g. from a JWT assertion header that a proxy adds
16
+ * to the connect request. Defaults to the bearer token in the `authorization` or `Authorization`
17
+ * connection parameter. Pass the same function to `createSubscriptionContextFactory`.
18
+ */
19
+ extractToken?: ExtractSubscriptionToken;
14
20
  requireAuth?: boolean;
15
21
  jwtClaimsToLog?: string[];
16
22
  resolveSubscriptionOperationLogger?: (context: GraphQLContext) => TLogger;
23
+ /**
24
+ * If true, deprecated schema elements a subscription uses are collected and logged when it is
25
+ * established. Not collected per emitted payload: the usage is a property of the operation.
26
+ */
27
+ includeDeprecatedElements?: boolean;
17
28
  }): import("graphql-ws").Disposable;