@makerx/graphql-core 2.2.2 → 3.0.0-beta.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 (53) hide show
  1. package/README.md +76 -100
  2. package/User.js.map +1 -1
  3. package/User.mjs.map +1 -1
  4. package/context.d.ts +17 -20
  5. package/context.js +19 -28
  6. package/context.js.map +1 -1
  7. package/context.mjs +13 -22
  8. package/context.mjs.map +1 -1
  9. package/index.d.ts +4 -4
  10. package/index.js +10 -9
  11. package/index.js.map +1 -1
  12. package/index.mjs +3 -3
  13. package/logging.d.ts +6 -4
  14. package/logging.js +8 -6
  15. package/logging.js.map +1 -1
  16. package/logging.mjs +6 -4
  17. package/logging.mjs.map +1 -1
  18. package/package.json +7 -11
  19. package/request-info.d.ts +22 -0
  20. package/request-info.js +85 -0
  21. package/request-info.js.map +1 -0
  22. package/request-info.mjs +80 -0
  23. package/request-info.mjs.map +1 -0
  24. package/schema-util.js.map +1 -1
  25. package/schema-util.mjs.map +1 -1
  26. package/shield.d.ts +2 -2
  27. package/shield.js.map +1 -1
  28. package/shield.mjs +1 -1
  29. package/shield.mjs.map +1 -1
  30. package/subscriptions/context.d.ts +12 -10
  31. package/subscriptions/context.js +16 -25
  32. package/subscriptions/context.js.map +1 -1
  33. package/subscriptions/context.mjs +12 -21
  34. package/subscriptions/context.mjs.map +1 -1
  35. package/subscriptions/server.d.ts +3 -3
  36. package/subscriptions/server.js +7 -7
  37. package/subscriptions/server.js.map +1 -1
  38. package/subscriptions/server.mjs +4 -4
  39. package/subscriptions/server.mjs.map +1 -1
  40. package/subscriptions/utils.d.ts +0 -1
  41. package/subscriptions/utils.js +1 -1
  42. package/subscriptions/utils.js.map +1 -1
  43. package/subscriptions/utils.mjs +1 -1
  44. package/subscriptions/utils.mjs.map +1 -1
  45. package/utils.d.ts +1 -1
  46. package/utils.js.map +1 -1
  47. package/utils.mjs.map +1 -1
  48. package/testing.d.ts +0 -7
  49. package/testing.js +0 -68
  50. package/testing.js.map +0 -1
  51. package/testing.mjs +0 -60
  52. package/testing.mjs.map +0 -1
  53. /package/{models.d.ts → type-utils.d.ts} +0 -0
package/index.js CHANGED
@@ -1,24 +1,25 @@
1
1
  'use strict';
2
2
 
3
3
  var context = require('./context.js');
4
- var User = require('./User.js');
5
- var utils = require('./utils.js');
6
4
  var logging = require('./logging.js');
5
+ var requestInfo = require('./request-info.js');
7
6
  var schemaUtil = require('./schema-util.js');
8
- var shield = require('./shield.js');
7
+ var User = require('./User.js');
8
+ var utils = require('./utils.js');
9
9
 
10
10
 
11
11
 
12
12
  exports.createContextFactory = context.createContextFactory;
13
13
  exports.defaultCreateUser = context.defaultCreateUser;
14
+ exports.logGraphQLOperation = logging.logGraphQLOperation;
15
+ exports.logSubscriptionOperation = logging.logSubscriptionOperation;
16
+ exports.buildBaseRequestInfo = requestInfo.buildBaseRequestInfo;
17
+ exports.buildConnectRequestInfo = requestInfo.buildConnectRequestInfo;
18
+ exports.connectRequestBaseUrl = requestInfo.connectRequestBaseUrl;
19
+ exports.requestBaseUrl = requestInfo.requestBaseUrl;
20
+ exports.requireExplicitResolversForScalars = schemaUtil.requireExplicitResolversForScalars;
14
21
  exports.User = User.User;
15
22
  exports.isIntrospectionQuery = utils.isIntrospectionQuery;
16
23
  exports.isNil = utils.isNil;
17
24
  exports.isNotNil = utils.isNotNil;
18
- exports.logGraphQLOperation = logging.logGraphQLOperation;
19
- exports.logSubscriptionOperation = logging.logSubscriptionOperation;
20
- exports.requireExplicitResolversForScalars = schemaUtil.requireExplicitResolversForScalars;
21
- exports.combineRuleWithAll = shield.combineRuleWithAll;
22
- exports.createRule = shield.createRule;
23
- exports.createShieldSchema = shield.createShieldSchema;
24
25
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
package/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  export { createContextFactory, defaultCreateUser } from './context.mjs';
2
- export { User } from './User.mjs';
3
- export { isIntrospectionQuery, isNil, isNotNil } from './utils.mjs';
4
2
  export { logGraphQLOperation, logSubscriptionOperation } from './logging.mjs';
3
+ export { buildBaseRequestInfo, buildConnectRequestInfo, connectRequestBaseUrl, requestBaseUrl } from './request-info.mjs';
5
4
  export { requireExplicitResolversForScalars } from './schema-util.mjs';
6
- export { combineRuleWithAll, createRule, createShieldSchema } from './shield.mjs';
5
+ export { User } from './User.mjs';
6
+ export { isIntrospectionQuery, isNil, isNotNil } from './utils.mjs';
7
7
  //# sourceMappingURL=index.mjs.map
package/logging.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { Logger } from '@makerx/node-common';
2
2
  import type { ExecutionArgs, GraphQLFormattedError } from 'graphql';
3
3
  import { OperationTypeNode } from 'graphql';
4
4
  import type { ExecutionResult } from 'graphql-ws';
5
+ import type { GraphQLContext } from './context';
5
6
  type LogFunction = Logger['info'];
6
7
  export type LoggerLogFunctions<T extends Logger> = {
7
8
  [Property in keyof T]: LogFunction;
@@ -70,10 +71,11 @@ export interface GraphQLLogOperationInfo<TLogger extends Logger = Logger> extend
70
71
  * Top level and result entries with null or undefined values will be omitted.
71
72
  */
72
73
  export declare const logGraphQLOperation: <TLogger extends Logger = Logger>({ message, started, type, operationName, query, variables, result, logger, logLevel, ...rest }: GraphQLLogOperationInfo<TLogger>) => void;
73
- export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ args, result, message, logLevel, }: {
74
+ export declare const logSubscriptionOperation: <TLogger extends Logger = Logger>({ args, result, message, logLevel, resolveLogger, }: {
74
75
  args: ExecutionArgs;
75
- result?: ExecutionResult<Record<string, unknown>, Record<string, unknown>> | undefined;
76
- message?: string | undefined;
77
- logLevel?: keyof TLogger | undefined;
76
+ result?: ExecutionResult;
77
+ message?: string;
78
+ logLevel?: keyof LoggerLogFunctions<TLogger>;
79
+ resolveLogger?: (context: GraphQLContext) => TLogger;
78
80
  }) => void;
79
81
  export {};
package/logging.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var nodeCommon = require('@makerx/node-common');
4
4
  var graphql = require('graphql');
5
- var lodash = require('lodash');
5
+ var compat = require('es-toolkit/compat');
6
6
  var utils = require('./utils.js');
7
7
 
8
8
  /**
@@ -13,19 +13,21 @@ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, ope
13
13
  const isIntrospection = query && utils.isIntrospectionQuery(query);
14
14
  if (nodeCommon.isLocalDev && isIntrospection)
15
15
  return;
16
- logger[logLevel](message, lodash.omitBy({
16
+ logger[logLevel](message, compat.omitBy({
17
17
  type,
18
18
  operationName,
19
19
  query,
20
20
  variables: variables && Object.keys(variables).length > 0 ? variables : undefined,
21
21
  duration: started ? Date.now() - started : undefined,
22
- result: result ? lodash.omitBy(result, utils.isNil) : undefined,
22
+ result: result ? compat.omitBy(result, utils.isNil) : undefined,
23
23
  isIntrospectionQuery: isIntrospection || undefined,
24
- ...lodash.omitBy(rest, utils.isNil),
24
+ ...compat.omitBy(rest, utils.isNil),
25
25
  }, utils.isNil));
26
26
  };
27
- const logSubscriptionOperation = ({ args, result, message, logLevel, }) => {
28
- const logger = args.contextValue.logger;
27
+ const logSubscriptionOperation = ({ args, result, message, logLevel, resolveLogger, }) => {
28
+ const logger = resolveLogger
29
+ ? resolveLogger(args.contextValue)
30
+ : args.contextValue.logger;
29
31
  if (!logger)
30
32
  return;
31
33
  const { operationName, variableValues, document } = args;
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 type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport { omitBy } from 'lodash'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery, 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 args,\n result,\n message,\n logLevel,\n}: {\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}) => {\n const logger = (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 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":";;;;;;;AA0EA;;;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,0BAAoB,CAAC,KAAK,CAAC,CAAA;IAC5D,IAAIC,qBAAU,IAAI,eAAe;QAAE,OAAM;AACzC,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,CAAA;AACH,EAAC;AAEM,MAAM,wBAAwB,GAAG,CAAkC,EACxE,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,GAMT,KAAI;AACH,IAAA,MAAM,MAAM,GAAI,IAAI,CAAC,YAA+B,CAAC,MAAiB,CAAA;AACtE,IAAA,IAAI,CAAC,MAAM;QAAE,OAAM;IAEnB,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACxD,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE,CAAA;AAEnD,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAEC,yBAAiB,CAAC,YAAY;QACpC,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,CAAA;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 type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery, 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 args,\n result,\n message,\n logLevel,\n resolveLogger,\n}: {\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 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":";;;;;;;AA0EA;;;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,0BAAoB,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,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,GAOd,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;QACpC,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;;;;;"}
package/logging.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isLocalDev } from '@makerx/node-common';
2
- import { OperationTypeNode, print } from 'graphql';
3
- import { omitBy } from 'lodash';
2
+ import { print, OperationTypeNode } from 'graphql';
3
+ import { omitBy } from 'es-toolkit/compat';
4
4
  import { isIntrospectionQuery, isNil } from './utils.mjs';
5
5
 
6
6
  /**
@@ -22,8 +22,10 @@ const logGraphQLOperation = ({ message = 'GraphQL operation', started, type, ope
22
22
  ...omitBy(rest, isNil),
23
23
  }, isNil));
24
24
  };
25
- const logSubscriptionOperation = ({ args, result, message, logLevel, }) => {
26
- const logger = args.contextValue.logger;
25
+ const logSubscriptionOperation = ({ args, result, message, logLevel, resolveLogger, }) => {
26
+ const logger = resolveLogger
27
+ ? resolveLogger(args.contextValue)
28
+ : args.contextValue.logger;
27
29
  if (!logger)
28
30
  return;
29
31
  const { operationName, variableValues, document } = args;
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 type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport { omitBy } from 'lodash'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery, 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 args,\n result,\n message,\n logLevel,\n}: {\n args: ExecutionArgs\n result?: ExecutionResult\n message?: string\n logLevel?: keyof LoggerLogFunctions<TLogger>\n}) => {\n const logger = (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 operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n logger,\n logLevel,\n })\n}\n"],"names":[],"mappings":";;;;;AA0EA;;;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,CAAA;IAC5D,IAAI,UAAU,IAAI,eAAe;QAAE,OAAM;AACzC,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,CAAA;AACH,EAAC;AAEM,MAAM,wBAAwB,GAAG,CAAkC,EACxE,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,GAMT,KAAI;AACH,IAAA,MAAM,MAAM,GAAI,IAAI,CAAC,YAA+B,CAAC,MAAiB,CAAA;AACtE,IAAA,IAAI,CAAC,MAAM;QAAE,OAAM;IAEnB,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACxD,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,IAAI,EAAE,CAAA;AAEnD,IAAA,mBAAmB,CAAC;QAClB,OAAO;QACP,IAAI,EAAE,iBAAiB,CAAC,YAAY;QACpC,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,CAAA;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 type { ExecutionArgs, GraphQLFormattedError } from 'graphql'\nimport { OperationTypeNode, print } from 'graphql'\nimport type { ExecutionResult } from 'graphql-ws'\nimport { omitBy } from 'es-toolkit/compat'\nimport type { GraphQLContext } from './context'\nimport { isIntrospectionQuery, 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 args,\n result,\n message,\n logLevel,\n resolveLogger,\n}: {\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 operationName,\n query: print(document),\n variables: variableValues,\n result: resultWithoutData,\n logger,\n logLevel,\n })\n}\n"],"names":[],"mappings":";;;;;AA0EA;;;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,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,GAOd,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;QACpC,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;;;;"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "**"
5
5
  ],
6
6
  "name": "@makerx/graphql-core",
7
- "version": "2.2.2",
7
+ "version": "3.0.0-beta.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",
@@ -21,21 +21,17 @@
21
21
  "url": "git+https://github.com/MakerXStudio/graphql-core.git"
22
22
  },
23
23
  "dependencies": {
24
- "@makerx/node-common": "^1.4.0"
24
+ "@makerx/node-common": "^1.5.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@apollo/client": "*",
27
+ "es-toolkit": ">=1",
28
28
  "express": "*",
29
29
  "graphql": "*",
30
30
  "graphql-shield": "*",
31
31
  "graphql-ws": "*",
32
- "lodash": "*",
33
32
  "ws": "*"
34
33
  },
35
34
  "peerDependenciesMeta": {
36
- "@apollo/client": {
37
- "optional": true
38
- },
39
35
  "graphql-ws": {
40
36
  "optional": true
41
37
  },
@@ -53,10 +49,10 @@
53
49
  "import": "./index.mjs",
54
50
  "require": "./index.js"
55
51
  },
56
- "./testing": {
57
- "types": "./testing.d.ts",
58
- "import": "./testing.mjs",
59
- "require": "./testing.js"
52
+ "./shield": {
53
+ "types": "./shield.d.ts",
54
+ "import": "./shield.mjs",
55
+ "require": "./shield.js"
60
56
  },
61
57
  "./subscriptions": {
62
58
  "types": "./subscriptions/index.d.ts",
@@ -0,0 +1,22 @@
1
+ import type { Request } from 'express';
2
+ import type { IncomingMessage } from 'http';
3
+ export interface BaseRequestInfo extends Record<string, unknown> {
4
+ requestId: string;
5
+ source: 'http' | 'subscription';
6
+ protocol: 'http' | 'https' | 'ws' | 'wss';
7
+ host: string;
8
+ port?: number;
9
+ method: string;
10
+ baseUrl: string;
11
+ url: string;
12
+ origin: string;
13
+ referer?: string;
14
+ correlationId?: string;
15
+ arrLogId?: string;
16
+ clientIp?: string;
17
+ userAgent?: string;
18
+ }
19
+ export declare const requestBaseUrl: (req: Request) => string;
20
+ export declare const connectRequestBaseUrl: (req: IncomingMessage) => string;
21
+ export declare const buildBaseRequestInfo: (req: Request) => BaseRequestInfo;
22
+ export declare const buildConnectRequestInfo: (req: IncomingMessage) => BaseRequestInfo;
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ const isDefaultPort = (protocol, port) => port == null || (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443);
6
+ const formatBaseUrl = (protocol, hostname, port) => isDefaultPort(protocol, port) ? `${protocol}://${hostname}` : `${protocol}://${hostname}:${port}`;
7
+ const firstHeaderValue = (value) => {
8
+ const raw = Array.isArray(value) ? value[0] : value;
9
+ return raw?.split(',')[0]?.trim() || undefined;
10
+ };
11
+ const parseHostHeader = (hostHeader) => {
12
+ const url = new URL(`http://${hostHeader}`);
13
+ return { hostname: url.hostname, port: url.port ? Number(url.port) : undefined };
14
+ };
15
+ const isEncryptedSocket = (req) => 'encrypted' in req.socket && req.socket.encrypted === true;
16
+ const isEncryptedConnect = (req) => {
17
+ const forwarded = firstHeaderValue(req.headers['x-forwarded-proto'])?.toLowerCase();
18
+ if (forwarded === 'https' || forwarded === 'wss')
19
+ return true;
20
+ if (forwarded === 'http' || forwarded === 'ws')
21
+ return false;
22
+ return isEncryptedSocket(req);
23
+ };
24
+ const resolveForwardedHost = (req) => firstHeaderValue(req.headers['x-forwarded-host']);
25
+ const resolveHostAndPort = (req, fallbackHostname) => {
26
+ const headerValue = resolveForwardedHost(req) ?? req.headers.host;
27
+ if (headerValue) {
28
+ const { hostname, port } = parseHostHeader(headerValue);
29
+ return { host: hostname, port };
30
+ }
31
+ return { host: fallbackHostname ?? '', port: undefined };
32
+ };
33
+ const requestBaseUrl = (req) => {
34
+ const { host, port } = resolveHostAndPort(req, req.hostname);
35
+ return formatBaseUrl(req.protocol, host, port);
36
+ };
37
+ const connectRequestBaseUrl = (req) => {
38
+ const { host, port } = resolveHostAndPort(req);
39
+ if (!host)
40
+ throw new Error('Cannot determine base URL from websocket connect request');
41
+ return formatBaseUrl(isEncryptedConnect(req) ? 'https' : 'http', host, port);
42
+ };
43
+ const buildSharedRequestInfo = (req) => ({
44
+ requestId: req.headers['x-request-id']?.toString() ?? crypto.randomUUID(),
45
+ method: req.method ?? '',
46
+ origin: req.headers.origin ?? '',
47
+ referer: req.headers.referer?.toString() ?? '',
48
+ arrLogId: req.headers['x-arr-log-id']?.toString() ?? undefined,
49
+ clientIp: firstHeaderValue(req.headers['x-forwarded-for']) ?? req.socket.remoteAddress,
50
+ correlationId: req.headers['x-correlation-id']?.toString() ?? undefined,
51
+ userAgent: req.headers['user-agent']?.toString() ?? undefined,
52
+ });
53
+ const buildBaseRequestInfo = (req) => {
54
+ const { host, port } = resolveHostAndPort(req, req.hostname);
55
+ return {
56
+ ...buildSharedRequestInfo(req),
57
+ source: 'http',
58
+ protocol: req.protocol,
59
+ host,
60
+ port,
61
+ baseUrl: formatBaseUrl(req.protocol, host, port),
62
+ url: req.originalUrl,
63
+ };
64
+ };
65
+ const buildConnectRequestInfo = (req) => {
66
+ const { host, port } = resolveHostAndPort(req);
67
+ const protocol = isEncryptedConnect(req) ? 'wss' : 'ws';
68
+ if (!host)
69
+ throw new Error('Cannot determine base URL from websocket connect request');
70
+ return {
71
+ ...buildSharedRequestInfo(req),
72
+ source: 'subscription',
73
+ protocol,
74
+ host,
75
+ port,
76
+ baseUrl: formatBaseUrl(protocol === 'wss' ? 'https' : 'http', host, port),
77
+ url: req.url ?? '',
78
+ };
79
+ };
80
+
81
+ exports.buildBaseRequestInfo = buildBaseRequestInfo;
82
+ exports.buildConnectRequestInfo = buildConnectRequestInfo;
83
+ exports.connectRequestBaseUrl = connectRequestBaseUrl;
84
+ exports.requestBaseUrl = requestBaseUrl;
85
+ //# sourceMappingURL=request-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-info.js","sources":["../src/request-info.ts"],"sourcesContent":["import { randomUUID } from 'crypto'\nimport type { Request } from 'express'\nimport type { IncomingMessage } from 'http'\nimport type { TLSSocket } from 'tls'\n\nexport interface BaseRequestInfo extends Record<string, unknown> {\n requestId: string\n source: 'http' | 'subscription'\n protocol: 'http' | 'https' | 'ws' | 'wss'\n host: string\n port?: number\n method: string\n baseUrl: string\n url: string\n origin: string\n referer?: string\n correlationId?: string\n arrLogId?: string\n clientIp?: string\n userAgent?: string\n}\n\nconst isDefaultPort = (protocol: string, port: number | undefined): boolean =>\n port == null || (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)\n\nconst formatBaseUrl = (protocol: string, hostname: string, port: number | undefined): string =>\n isDefaultPort(protocol, port) ? `${protocol}://${hostname}` : `${protocol}://${hostname}:${port}`\n\nconst firstHeaderValue = (value: string | string[] | undefined): string | undefined => {\n const raw = Array.isArray(value) ? value[0] : value\n return raw?.split(',')[0]?.trim() || undefined\n}\n\nconst parseHostHeader = (hostHeader: string): { hostname: string; port: number | undefined } => {\n const url = new URL(`http://${hostHeader}`)\n return { hostname: url.hostname, port: url.port ? Number(url.port) : undefined }\n}\n\nconst isEncryptedSocket = (req: IncomingMessage): boolean => 'encrypted' in req.socket && (req.socket as TLSSocket).encrypted === true\n\nconst isEncryptedConnect = (req: IncomingMessage): boolean => {\n const forwarded = firstHeaderValue(req.headers['x-forwarded-proto'])?.toLowerCase()\n if (forwarded === 'https' || forwarded === 'wss') return true\n if (forwarded === 'http' || forwarded === 'ws') return false\n return isEncryptedSocket(req)\n}\n\nconst resolveForwardedHost = (req: IncomingMessage): string | undefined => firstHeaderValue(req.headers['x-forwarded-host'])\n\nconst resolveHostAndPort = (req: IncomingMessage, fallbackHostname?: string): { host: string; port: number | undefined } => {\n const headerValue = resolveForwardedHost(req) ?? req.headers.host\n if (headerValue) {\n const { hostname, port } = parseHostHeader(headerValue)\n return { host: hostname, port }\n }\n return { host: fallbackHostname ?? '', port: undefined }\n}\n\nexport const requestBaseUrl = (req: Request): string => {\n const { host, port } = resolveHostAndPort(req, req.hostname)\n return formatBaseUrl(req.protocol, host, port)\n}\n\nexport const connectRequestBaseUrl = (req: IncomingMessage): string => {\n const { host, port } = resolveHostAndPort(req)\n if (!host) throw new Error('Cannot determine base URL from websocket connect request')\n return formatBaseUrl(isEncryptedConnect(req) ? 'https' : 'http', host, port)\n}\n\nconst buildSharedRequestInfo = (req: IncomingMessage) => ({\n requestId: req.headers['x-request-id']?.toString() ?? randomUUID(),\n method: req.method ?? '',\n origin: req.headers.origin ?? '',\n referer: req.headers.referer?.toString() ?? '',\n arrLogId: req.headers['x-arr-log-id']?.toString() ?? undefined,\n clientIp: firstHeaderValue(req.headers['x-forwarded-for']) ?? req.socket.remoteAddress,\n correlationId: req.headers['x-correlation-id']?.toString() ?? undefined,\n userAgent: req.headers['user-agent']?.toString() ?? undefined,\n})\n\nexport const buildBaseRequestInfo = (req: Request): BaseRequestInfo => {\n const { host, port } = resolveHostAndPort(req, req.hostname)\n return {\n ...buildSharedRequestInfo(req),\n source: 'http',\n protocol: req.protocol as 'http' | 'https',\n host,\n port,\n baseUrl: formatBaseUrl(req.protocol, host, port),\n url: req.originalUrl,\n }\n}\n\nexport const buildConnectRequestInfo = (req: IncomingMessage): BaseRequestInfo => {\n const { host, port } = resolveHostAndPort(req)\n const protocol = isEncryptedConnect(req) ? 'wss' : 'ws'\n if (!host) throw new Error('Cannot determine base URL from websocket connect request')\n return {\n ...buildSharedRequestInfo(req),\n source: 'subscription',\n protocol,\n host,\n port,\n baseUrl: formatBaseUrl(protocol === 'wss' ? 'https' : 'http', host, port),\n url: req.url ?? '',\n }\n}\n"],"names":["randomUUID"],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { randomUUID } from 'crypto';
2
+
3
+ const isDefaultPort = (protocol, port) => port == null || (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443);
4
+ const formatBaseUrl = (protocol, hostname, port) => isDefaultPort(protocol, port) ? `${protocol}://${hostname}` : `${protocol}://${hostname}:${port}`;
5
+ const firstHeaderValue = (value) => {
6
+ const raw = Array.isArray(value) ? value[0] : value;
7
+ return raw?.split(',')[0]?.trim() || undefined;
8
+ };
9
+ const parseHostHeader = (hostHeader) => {
10
+ const url = new URL(`http://${hostHeader}`);
11
+ return { hostname: url.hostname, port: url.port ? Number(url.port) : undefined };
12
+ };
13
+ const isEncryptedSocket = (req) => 'encrypted' in req.socket && req.socket.encrypted === true;
14
+ const isEncryptedConnect = (req) => {
15
+ const forwarded = firstHeaderValue(req.headers['x-forwarded-proto'])?.toLowerCase();
16
+ if (forwarded === 'https' || forwarded === 'wss')
17
+ return true;
18
+ if (forwarded === 'http' || forwarded === 'ws')
19
+ return false;
20
+ return isEncryptedSocket(req);
21
+ };
22
+ const resolveForwardedHost = (req) => firstHeaderValue(req.headers['x-forwarded-host']);
23
+ const resolveHostAndPort = (req, fallbackHostname) => {
24
+ const headerValue = resolveForwardedHost(req) ?? req.headers.host;
25
+ if (headerValue) {
26
+ const { hostname, port } = parseHostHeader(headerValue);
27
+ return { host: hostname, port };
28
+ }
29
+ return { host: fallbackHostname ?? '', port: undefined };
30
+ };
31
+ const requestBaseUrl = (req) => {
32
+ const { host, port } = resolveHostAndPort(req, req.hostname);
33
+ return formatBaseUrl(req.protocol, host, port);
34
+ };
35
+ const connectRequestBaseUrl = (req) => {
36
+ const { host, port } = resolveHostAndPort(req);
37
+ if (!host)
38
+ throw new Error('Cannot determine base URL from websocket connect request');
39
+ return formatBaseUrl(isEncryptedConnect(req) ? 'https' : 'http', host, port);
40
+ };
41
+ const buildSharedRequestInfo = (req) => ({
42
+ requestId: req.headers['x-request-id']?.toString() ?? randomUUID(),
43
+ method: req.method ?? '',
44
+ origin: req.headers.origin ?? '',
45
+ referer: req.headers.referer?.toString() ?? '',
46
+ arrLogId: req.headers['x-arr-log-id']?.toString() ?? undefined,
47
+ clientIp: firstHeaderValue(req.headers['x-forwarded-for']) ?? req.socket.remoteAddress,
48
+ correlationId: req.headers['x-correlation-id']?.toString() ?? undefined,
49
+ userAgent: req.headers['user-agent']?.toString() ?? undefined,
50
+ });
51
+ const buildBaseRequestInfo = (req) => {
52
+ const { host, port } = resolveHostAndPort(req, req.hostname);
53
+ return {
54
+ ...buildSharedRequestInfo(req),
55
+ source: 'http',
56
+ protocol: req.protocol,
57
+ host,
58
+ port,
59
+ baseUrl: formatBaseUrl(req.protocol, host, port),
60
+ url: req.originalUrl,
61
+ };
62
+ };
63
+ const buildConnectRequestInfo = (req) => {
64
+ const { host, port } = resolveHostAndPort(req);
65
+ const protocol = isEncryptedConnect(req) ? 'wss' : 'ws';
66
+ if (!host)
67
+ throw new Error('Cannot determine base URL from websocket connect request');
68
+ return {
69
+ ...buildSharedRequestInfo(req),
70
+ source: 'subscription',
71
+ protocol,
72
+ host,
73
+ port,
74
+ baseUrl: formatBaseUrl(protocol === 'wss' ? 'https' : 'http', host, port),
75
+ url: req.url ?? '',
76
+ };
77
+ };
78
+
79
+ export { buildBaseRequestInfo, buildConnectRequestInfo, connectRequestBaseUrl, requestBaseUrl };
80
+ //# sourceMappingURL=request-info.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-info.mjs","sources":["../src/request-info.ts"],"sourcesContent":["import { randomUUID } from 'crypto'\nimport type { Request } from 'express'\nimport type { IncomingMessage } from 'http'\nimport type { TLSSocket } from 'tls'\n\nexport interface BaseRequestInfo extends Record<string, unknown> {\n requestId: string\n source: 'http' | 'subscription'\n protocol: 'http' | 'https' | 'ws' | 'wss'\n host: string\n port?: number\n method: string\n baseUrl: string\n url: string\n origin: string\n referer?: string\n correlationId?: string\n arrLogId?: string\n clientIp?: string\n userAgent?: string\n}\n\nconst isDefaultPort = (protocol: string, port: number | undefined): boolean =>\n port == null || (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)\n\nconst formatBaseUrl = (protocol: string, hostname: string, port: number | undefined): string =>\n isDefaultPort(protocol, port) ? `${protocol}://${hostname}` : `${protocol}://${hostname}:${port}`\n\nconst firstHeaderValue = (value: string | string[] | undefined): string | undefined => {\n const raw = Array.isArray(value) ? value[0] : value\n return raw?.split(',')[0]?.trim() || undefined\n}\n\nconst parseHostHeader = (hostHeader: string): { hostname: string; port: number | undefined } => {\n const url = new URL(`http://${hostHeader}`)\n return { hostname: url.hostname, port: url.port ? Number(url.port) : undefined }\n}\n\nconst isEncryptedSocket = (req: IncomingMessage): boolean => 'encrypted' in req.socket && (req.socket as TLSSocket).encrypted === true\n\nconst isEncryptedConnect = (req: IncomingMessage): boolean => {\n const forwarded = firstHeaderValue(req.headers['x-forwarded-proto'])?.toLowerCase()\n if (forwarded === 'https' || forwarded === 'wss') return true\n if (forwarded === 'http' || forwarded === 'ws') return false\n return isEncryptedSocket(req)\n}\n\nconst resolveForwardedHost = (req: IncomingMessage): string | undefined => firstHeaderValue(req.headers['x-forwarded-host'])\n\nconst resolveHostAndPort = (req: IncomingMessage, fallbackHostname?: string): { host: string; port: number | undefined } => {\n const headerValue = resolveForwardedHost(req) ?? req.headers.host\n if (headerValue) {\n const { hostname, port } = parseHostHeader(headerValue)\n return { host: hostname, port }\n }\n return { host: fallbackHostname ?? '', port: undefined }\n}\n\nexport const requestBaseUrl = (req: Request): string => {\n const { host, port } = resolveHostAndPort(req, req.hostname)\n return formatBaseUrl(req.protocol, host, port)\n}\n\nexport const connectRequestBaseUrl = (req: IncomingMessage): string => {\n const { host, port } = resolveHostAndPort(req)\n if (!host) throw new Error('Cannot determine base URL from websocket connect request')\n return formatBaseUrl(isEncryptedConnect(req) ? 'https' : 'http', host, port)\n}\n\nconst buildSharedRequestInfo = (req: IncomingMessage) => ({\n requestId: req.headers['x-request-id']?.toString() ?? randomUUID(),\n method: req.method ?? '',\n origin: req.headers.origin ?? '',\n referer: req.headers.referer?.toString() ?? '',\n arrLogId: req.headers['x-arr-log-id']?.toString() ?? undefined,\n clientIp: firstHeaderValue(req.headers['x-forwarded-for']) ?? req.socket.remoteAddress,\n correlationId: req.headers['x-correlation-id']?.toString() ?? undefined,\n userAgent: req.headers['user-agent']?.toString() ?? undefined,\n})\n\nexport const buildBaseRequestInfo = (req: Request): BaseRequestInfo => {\n const { host, port } = resolveHostAndPort(req, req.hostname)\n return {\n ...buildSharedRequestInfo(req),\n source: 'http',\n protocol: req.protocol as 'http' | 'https',\n host,\n port,\n baseUrl: formatBaseUrl(req.protocol, host, port),\n url: req.originalUrl,\n }\n}\n\nexport const buildConnectRequestInfo = (req: IncomingMessage): BaseRequestInfo => {\n const { host, port } = resolveHostAndPort(req)\n const protocol = isEncryptedConnect(req) ? 'wss' : 'ws'\n if (!host) throw new Error('Cannot determine base URL from websocket connect request')\n return {\n ...buildSharedRequestInfo(req),\n source: 'subscription',\n protocol,\n host,\n port,\n baseUrl: formatBaseUrl(protocol === 'wss' ? 'https' : 'http', host, port),\n url: req.url ?? '',\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-util.js","sources":["../src/schema-util.ts"],"sourcesContent":["import type { GraphQLSchema } from 'graphql'\nimport { GraphQLScalarType } from 'graphql'\n\n/**\n * It is possible to register a custom scalar with apollo server without defining an explicit resolver (a default resolver is used in\n * this case), but it is rarely desirable. This function, when provided with your built schema, will ensure any registered scalar types\n * provide at least a base level of validation by failing to parse a Symbol instance. The default resolver does not pass this test\n * meaning any scalars that are falling back to the default resolver will fail.\n * @param schema A schema object, the result of calling `makeExecutableSchema` from `@graphql-tools/schema`\n */\nexport function requireExplicitResolversForScalars(schema: GraphQLSchema, ...scalarsToIgnore: string[]) {\n const testSymbol = Symbol('testSymbol')\n const scalars = Object.values(schema.getTypeMap()).filter((t): t is GraphQLScalarType => t instanceof GraphQLScalarType)\n for (const scalar of scalars) {\n if (scalar.name === 'Void' || scalar.name === 'JSON' || scalarsToIgnore.includes(scalar.name)) continue\n try {\n scalar.parseValue(testSymbol)\n } catch {\n // We expect that a good parser should throw when parsing a random symbol\n continue\n }\n throw new Error(\n `Scalar ${scalar.name} does not appear to have an explicit resolver, or is not performing sufficient validation when parsing input. ` +\n \"If you're satisfied with this scalar you can ignore it in the call to `requireExplicitResolversForScalars`.\",\n )\n }\n}\n"],"names":["GraphQLScalarType"],"mappings":";;;;AAGA;;;;;;AAMG;SACa,kCAAkC,CAAC,MAAqB,EAAE,GAAG,eAAyB,EAAA;AACpG,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAA6B,CAAC,YAAYA,yBAAiB,CAAC,CAAA;AACxH,IAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAC5B,QAAA,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,SAAQ;AACvG,QAAA,IAAI;AACF,YAAA,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;SAC9B;AAAC,QAAA,MAAM;;YAEN,SAAQ;SACT;AACD,QAAA,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,CAAC,IAAI,CAAgH,8GAAA,CAAA;AACnI,YAAA,6GAA6G,CAChH,CAAA;KACF;AACH;;;;"}
1
+ {"version":3,"file":"schema-util.js","sources":["../src/schema-util.ts"],"sourcesContent":["import type { GraphQLSchema } from 'graphql'\nimport { GraphQLScalarType } from 'graphql'\n\n/**\n * It is possible to register a custom scalar with apollo server without defining an explicit resolver (a default resolver is used in\n * this case), but it is rarely desirable. This function, when provided with your built schema, will ensure any registered scalar types\n * provide at least a base level of validation by failing to parse a Symbol instance. The default resolver does not pass this test\n * meaning any scalars that are falling back to the default resolver will fail.\n * @param schema A schema object, the result of calling `makeExecutableSchema` from `@graphql-tools/schema`\n */\nexport function requireExplicitResolversForScalars(schema: GraphQLSchema, ...scalarsToIgnore: string[]) {\n const testSymbol = Symbol('testSymbol')\n const scalars = Object.values(schema.getTypeMap()).filter((t): t is GraphQLScalarType => t instanceof GraphQLScalarType)\n for (const scalar of scalars) {\n if (scalar.name === 'Void' || scalar.name === 'JSON' || scalarsToIgnore.includes(scalar.name)) continue\n try {\n scalar.parseValue(testSymbol)\n } catch {\n // We expect that a good parser should throw when parsing a random symbol\n continue\n }\n throw new Error(\n `Scalar ${scalar.name} does not appear to have an explicit resolver, or is not performing sufficient validation when parsing input. ` +\n \"If you're satisfied with this scalar you can ignore it in the call to `requireExplicitResolversForScalars`.\",\n )\n }\n}\n"],"names":["GraphQLScalarType"],"mappings":";;;;AAGA;;;;;;AAMG;SACa,kCAAkC,CAAC,MAAqB,EAAE,GAAG,eAAyB,EAAA;AACpG,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAA6B,CAAC,YAAYA,yBAAiB,CAAC;AACxH,IAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAC5B,QAAA,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE;AAC/F,QAAA,IAAI;AACF,YAAA,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;QAC/B;AAAE,QAAA,MAAM;;YAEN;QACF;AACA,QAAA,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,CAAC,IAAI,CAAA,8GAAA,CAAgH;AACnI,YAAA,6GAA6G,CAChH;IACH;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-util.mjs","sources":["../src/schema-util.ts"],"sourcesContent":["import type { GraphQLSchema } from 'graphql'\nimport { GraphQLScalarType } from 'graphql'\n\n/**\n * It is possible to register a custom scalar with apollo server without defining an explicit resolver (a default resolver is used in\n * this case), but it is rarely desirable. This function, when provided with your built schema, will ensure any registered scalar types\n * provide at least a base level of validation by failing to parse a Symbol instance. The default resolver does not pass this test\n * meaning any scalars that are falling back to the default resolver will fail.\n * @param schema A schema object, the result of calling `makeExecutableSchema` from `@graphql-tools/schema`\n */\nexport function requireExplicitResolversForScalars(schema: GraphQLSchema, ...scalarsToIgnore: string[]) {\n const testSymbol = Symbol('testSymbol')\n const scalars = Object.values(schema.getTypeMap()).filter((t): t is GraphQLScalarType => t instanceof GraphQLScalarType)\n for (const scalar of scalars) {\n if (scalar.name === 'Void' || scalar.name === 'JSON' || scalarsToIgnore.includes(scalar.name)) continue\n try {\n scalar.parseValue(testSymbol)\n } catch {\n // We expect that a good parser should throw when parsing a random symbol\n continue\n }\n throw new Error(\n `Scalar ${scalar.name} does not appear to have an explicit resolver, or is not performing sufficient validation when parsing input. ` +\n \"If you're satisfied with this scalar you can ignore it in the call to `requireExplicitResolversForScalars`.\",\n )\n }\n}\n"],"names":[],"mappings":";;AAGA;;;;;;AAMG;SACa,kCAAkC,CAAC,MAAqB,EAAE,GAAG,eAAyB,EAAA;AACpG,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAA6B,CAAC,YAAY,iBAAiB,CAAC,CAAA;AACxH,IAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAC5B,QAAA,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,SAAQ;AACvG,QAAA,IAAI;AACF,YAAA,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;SAC9B;AAAC,QAAA,MAAM;;YAEN,SAAQ;SACT;AACD,QAAA,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,CAAC,IAAI,CAAgH,8GAAA,CAAA;AACnI,YAAA,6GAA6G,CAChH,CAAA;KACF;AACH;;;;"}
1
+ {"version":3,"file":"schema-util.mjs","sources":["../src/schema-util.ts"],"sourcesContent":["import type { GraphQLSchema } from 'graphql'\nimport { GraphQLScalarType } from 'graphql'\n\n/**\n * It is possible to register a custom scalar with apollo server without defining an explicit resolver (a default resolver is used in\n * this case), but it is rarely desirable. This function, when provided with your built schema, will ensure any registered scalar types\n * provide at least a base level of validation by failing to parse a Symbol instance. The default resolver does not pass this test\n * meaning any scalars that are falling back to the default resolver will fail.\n * @param schema A schema object, the result of calling `makeExecutableSchema` from `@graphql-tools/schema`\n */\nexport function requireExplicitResolversForScalars(schema: GraphQLSchema, ...scalarsToIgnore: string[]) {\n const testSymbol = Symbol('testSymbol')\n const scalars = Object.values(schema.getTypeMap()).filter((t): t is GraphQLScalarType => t instanceof GraphQLScalarType)\n for (const scalar of scalars) {\n if (scalar.name === 'Void' || scalar.name === 'JSON' || scalarsToIgnore.includes(scalar.name)) continue\n try {\n scalar.parseValue(testSymbol)\n } catch {\n // We expect that a good parser should throw when parsing a random symbol\n continue\n }\n throw new Error(\n `Scalar ${scalar.name} does not appear to have an explicit resolver, or is not performing sufficient validation when parsing input. ` +\n \"If you're satisfied with this scalar you can ignore it in the call to `requireExplicitResolversForScalars`.\",\n )\n }\n}\n"],"names":[],"mappings":";;AAGA;;;;;;AAMG;SACa,kCAAkC,CAAC,MAAqB,EAAE,GAAG,eAAyB,EAAA;AACpG,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAA6B,CAAC,YAAY,iBAAiB,CAAC;AACxH,IAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAC5B,QAAA,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE;AAC/F,QAAA,IAAI;AACF,YAAA,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;QAC/B;AAAE,QAAA,MAAM;;YAEN;QACF;AACA,QAAA,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,CAAC,IAAI,CAAA,8GAAA,CAAgH;AACnI,YAAA,6GAA6G,CAChH;IACH;AACF;;;;"}
package/shield.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { and, chain, or, race } from 'graphql-shield';
2
2
  import { allow } from 'graphql-shield';
3
- import type { Primitive } from './models';
3
+ import type { Primitive } from './type-utils';
4
4
  type RuleCombinator = typeof chain | typeof race | typeof or | typeof and;
5
5
  export type ShieldRule = ReturnType<(typeof allow)['getRules']>[number];
6
- export declare const createRule: <TContext, TParent = unknown, TArgs = unknown>(logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error, cache?: 'contextual' | 'strict') => ShieldRule;
6
+ export declare const createRule: <TContext, TParent = unknown, TArgs = unknown>(logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error, cache?: "contextual" | "strict") => ShieldRule;
7
7
  /**
8
8
  * Combines a given rule with all existing defined rules using the provided combinator
9
9
  * @param schema The existing shield schema with rules
package/shield.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shield.js","sources":["../src/shield.ts"],"sourcesContent":["import type { and, chain, or, race } from 'graphql-shield'\nimport { allow, rule, shield } from 'graphql-shield'\nimport type { IRules } from 'graphql-shield'\nimport type { Primitive } from './models'\n\ntype RuleCombinator = typeof chain | typeof race | typeof or | typeof and\n// For whatever reason, graphql-shield doesn't export this type, but we can extract if from\n// what it does export.\nexport type ShieldRule = ReturnType<(typeof allow)['getRules']>[number]\nexport const createRule = <TContext, TParent = unknown, TArgs = unknown>(\n logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error,\n cache: 'contextual' | 'strict' = 'strict',\n): ShieldRule => rule({ cache })(async (parent, args, ctx) => logic(parent, args, ctx))\n\n/**\n * Combines a given rule with all existing defined rules using the provided combinator\n * @param schema The existing shield schema with rules\n * @param rule The rule to be combined with existing rules\n * @param combinator The combinator to use. Eg. and | or | chain | race\n *\n * Usage:\n *\n * const updatedSchema = combineRuleWithAll(shieldSchema, rules.accountNotBlocked, chain)\n */\nexport function combineRuleWithAll<T>(schema: ShieldSchema<T>, rule: ShieldRule, combinator: RuleCombinator): ShieldSchema<T> {\n return Object.fromEntries(\n Object.entries(schema).map(([key, value]) => {\n if (value.constructor.name !== 'Object') {\n return [key, combinator(rule, value)]\n }\n return [key, combineRuleWithAll(value, rule, combinator)]\n }),\n ) as ShieldSchema<T>\n}\n\n/**\n * Creates graphql shield middleware making use of generics to type the definition of the rules.\n * @param schema A mapping of schema objects to the shield rules that define the access to that object\n * @param fallbackRule A fallback rule to apply to any object or property which doesn't have a defined rule.\n *\n * Usage:\n * import { Resolvers } from '../generated/types'\n *\n * const shieldSchema = createShieldSchema<Resolvers>({\n * Query: {\n * getThings: allow,\n * dontGetThings: deny,\n * }\n * })\n *\n * let schema = makeExecutableSchema({...})\n *\n * schema = applyMiddleware(schema, shieldSchema)\n */\nexport function createShieldSchema<TRootResolvers>(schema: ShieldSchema<TRootResolvers>, fallbackRule: ShieldRule = allow) {\n return shield(schema as IRules, {\n allowExternalErrors: true,\n fallbackRule: fallbackRule,\n })\n}\n\nexport type ShieldSchema<TResolver> = TResolver extends Primitive\n ? ShieldRule\n : {\n [key in keyof TResolver]?: ShieldSchema<TResolver[key]> | ShieldRule\n } & {\n '*'?: ShieldRule\n }\n"],"names":["rule","allow","shield"],"mappings":";;;;AASa,MAAA,UAAU,GAAG,CACxB,KAA0F,EAC1F,KAAA,GAAiC,QAAQ,KAC1BA,kBAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAC;AAEvF;;;;;;;;;AASG;SACa,kBAAkB,CAAI,MAAuB,EAAE,IAAgB,EAAE,UAA0B,EAAA;IACzG,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;QAC1C,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;SACtC;AACD,QAAA,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;KAC1D,CAAC,CACgB,CAAA;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;AAkBG;SACa,kBAAkB,CAAiB,MAAoC,EAAE,eAA2BC,mBAAK,EAAA;IACvH,OAAOC,oBAAM,CAAC,MAAgB,EAAE;AAC9B,QAAA,mBAAmB,EAAE,IAAI;AACzB,QAAA,YAAY,EAAE,YAAY;AAC3B,KAAA,CAAC,CAAA;AACJ;;;;;;"}
1
+ {"version":3,"file":"shield.js","sources":["../src/shield.ts"],"sourcesContent":["import type { and, chain, IRules, or, race } from 'graphql-shield'\nimport { allow, rule, shield } from 'graphql-shield'\nimport type { Primitive } from './type-utils'\n\ntype RuleCombinator = typeof chain | typeof race | typeof or | typeof and\n// For whatever reason, graphql-shield doesn't export this type, but we can extract if from\n// what it does export.\nexport type ShieldRule = ReturnType<(typeof allow)['getRules']>[number]\nexport const createRule = <TContext, TParent = unknown, TArgs = unknown>(\n logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error,\n cache: 'contextual' | 'strict' = 'strict',\n): ShieldRule => rule({ cache })(async (parent, args, ctx) => logic(parent, args, ctx))\n\n/**\n * Combines a given rule with all existing defined rules using the provided combinator\n * @param schema The existing shield schema with rules\n * @param rule The rule to be combined with existing rules\n * @param combinator The combinator to use. Eg. and | or | chain | race\n *\n * Usage:\n *\n * const updatedSchema = combineRuleWithAll(shieldSchema, rules.accountNotBlocked, chain)\n */\nexport function combineRuleWithAll<T>(schema: ShieldSchema<T>, rule: ShieldRule, combinator: RuleCombinator): ShieldSchema<T> {\n return Object.fromEntries(\n Object.entries(schema).map(([key, value]) => {\n if (value.constructor.name !== 'Object') {\n return [key, combinator(rule, value)]\n }\n return [key, combineRuleWithAll(value, rule, combinator)]\n }),\n ) as ShieldSchema<T>\n}\n\n/**\n * Creates graphql shield middleware making use of generics to type the definition of the rules.\n * @param schema A mapping of schema objects to the shield rules that define the access to that object\n * @param fallbackRule A fallback rule to apply to any object or property which doesn't have a defined rule.\n *\n * Usage:\n * import { Resolvers } from '../generated/types'\n *\n * const shieldSchema = createShieldSchema<Resolvers>({\n * Query: {\n * getThings: allow,\n * dontGetThings: deny,\n * }\n * })\n *\n * let schema = makeExecutableSchema({...})\n *\n * schema = applyMiddleware(schema, shieldSchema)\n */\nexport function createShieldSchema<TRootResolvers>(schema: ShieldSchema<TRootResolvers>, fallbackRule: ShieldRule = allow) {\n return shield(schema as IRules, {\n allowExternalErrors: true,\n fallbackRule: fallbackRule,\n })\n}\n\nexport type ShieldSchema<TResolver> = TResolver extends Primitive\n ? ShieldRule\n : {\n [key in keyof TResolver]?: ShieldSchema<TResolver[key]> | ShieldRule\n } & {\n '*'?: ShieldRule\n }\n"],"names":["rule","allow","shield"],"mappings":";;;;AAQO,MAAM,UAAU,GAAG,CACxB,KAA0F,EAC1F,KAAA,GAAiC,QAAQ,KAC1BA,kBAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC;AAEtF;;;;;;;;;AASG;SACa,kBAAkB,CAAI,MAAuB,EAAE,IAAgB,EAAE,UAA0B,EAAA;IACzG,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;QAC1C,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC;AACA,QAAA,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC,CAAC,CACgB;AACtB;AAEA;;;;;;;;;;;;;;;;;;AAkBG;SACa,kBAAkB,CAAiB,MAAoC,EAAE,eAA2BC,mBAAK,EAAA;IACvH,OAAOC,oBAAM,CAAC,MAAgB,EAAE;AAC9B,QAAA,mBAAmB,EAAE,IAAI;AACzB,QAAA,YAAY,EAAE,YAAY;AAC3B,KAAA,CAAC;AACJ;;;;;;"}
package/shield.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { rule, shield, allow } from 'graphql-shield';
1
+ import { allow, rule, shield } from 'graphql-shield';
2
2
 
3
3
  const createRule = (logic, cache = 'strict') => rule({ cache })(async (parent, args, ctx) => logic(parent, args, ctx));
4
4
  /**
package/shield.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shield.mjs","sources":["../src/shield.ts"],"sourcesContent":["import type { and, chain, or, race } from 'graphql-shield'\nimport { allow, rule, shield } from 'graphql-shield'\nimport type { IRules } from 'graphql-shield'\nimport type { Primitive } from './models'\n\ntype RuleCombinator = typeof chain | typeof race | typeof or | typeof and\n// For whatever reason, graphql-shield doesn't export this type, but we can extract if from\n// what it does export.\nexport type ShieldRule = ReturnType<(typeof allow)['getRules']>[number]\nexport const createRule = <TContext, TParent = unknown, TArgs = unknown>(\n logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error,\n cache: 'contextual' | 'strict' = 'strict',\n): ShieldRule => rule({ cache })(async (parent, args, ctx) => logic(parent, args, ctx))\n\n/**\n * Combines a given rule with all existing defined rules using the provided combinator\n * @param schema The existing shield schema with rules\n * @param rule The rule to be combined with existing rules\n * @param combinator The combinator to use. Eg. and | or | chain | race\n *\n * Usage:\n *\n * const updatedSchema = combineRuleWithAll(shieldSchema, rules.accountNotBlocked, chain)\n */\nexport function combineRuleWithAll<T>(schema: ShieldSchema<T>, rule: ShieldRule, combinator: RuleCombinator): ShieldSchema<T> {\n return Object.fromEntries(\n Object.entries(schema).map(([key, value]) => {\n if (value.constructor.name !== 'Object') {\n return [key, combinator(rule, value)]\n }\n return [key, combineRuleWithAll(value, rule, combinator)]\n }),\n ) as ShieldSchema<T>\n}\n\n/**\n * Creates graphql shield middleware making use of generics to type the definition of the rules.\n * @param schema A mapping of schema objects to the shield rules that define the access to that object\n * @param fallbackRule A fallback rule to apply to any object or property which doesn't have a defined rule.\n *\n * Usage:\n * import { Resolvers } from '../generated/types'\n *\n * const shieldSchema = createShieldSchema<Resolvers>({\n * Query: {\n * getThings: allow,\n * dontGetThings: deny,\n * }\n * })\n *\n * let schema = makeExecutableSchema({...})\n *\n * schema = applyMiddleware(schema, shieldSchema)\n */\nexport function createShieldSchema<TRootResolvers>(schema: ShieldSchema<TRootResolvers>, fallbackRule: ShieldRule = allow) {\n return shield(schema as IRules, {\n allowExternalErrors: true,\n fallbackRule: fallbackRule,\n })\n}\n\nexport type ShieldSchema<TResolver> = TResolver extends Primitive\n ? ShieldRule\n : {\n [key in keyof TResolver]?: ShieldSchema<TResolver[key]> | ShieldRule\n } & {\n '*'?: ShieldRule\n }\n"],"names":[],"mappings":";;AASa,MAAA,UAAU,GAAG,CACxB,KAA0F,EAC1F,KAAA,GAAiC,QAAQ,KAC1B,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAC;AAEvF;;;;;;;;;AASG;SACa,kBAAkB,CAAI,MAAuB,EAAE,IAAgB,EAAE,UAA0B,EAAA;IACzG,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;QAC1C,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;SACtC;AACD,QAAA,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;KAC1D,CAAC,CACgB,CAAA;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;AAkBG;SACa,kBAAkB,CAAiB,MAAoC,EAAE,eAA2B,KAAK,EAAA;IACvH,OAAO,MAAM,CAAC,MAAgB,EAAE;AAC9B,QAAA,mBAAmB,EAAE,IAAI;AACzB,QAAA,YAAY,EAAE,YAAY;AAC3B,KAAA,CAAC,CAAA;AACJ;;;;"}
1
+ {"version":3,"file":"shield.mjs","sources":["../src/shield.ts"],"sourcesContent":["import type { and, chain, IRules, or, race } from 'graphql-shield'\nimport { allow, rule, shield } from 'graphql-shield'\nimport type { Primitive } from './type-utils'\n\ntype RuleCombinator = typeof chain | typeof race | typeof or | typeof and\n// For whatever reason, graphql-shield doesn't export this type, but we can extract if from\n// what it does export.\nexport type ShieldRule = ReturnType<(typeof allow)['getRules']>[number]\nexport const createRule = <TContext, TParent = unknown, TArgs = unknown>(\n logic: (parent: TParent, args: TArgs, ctx: TContext) => boolean | Promise<boolean> | Error,\n cache: 'contextual' | 'strict' = 'strict',\n): ShieldRule => rule({ cache })(async (parent, args, ctx) => logic(parent, args, ctx))\n\n/**\n * Combines a given rule with all existing defined rules using the provided combinator\n * @param schema The existing shield schema with rules\n * @param rule The rule to be combined with existing rules\n * @param combinator The combinator to use. Eg. and | or | chain | race\n *\n * Usage:\n *\n * const updatedSchema = combineRuleWithAll(shieldSchema, rules.accountNotBlocked, chain)\n */\nexport function combineRuleWithAll<T>(schema: ShieldSchema<T>, rule: ShieldRule, combinator: RuleCombinator): ShieldSchema<T> {\n return Object.fromEntries(\n Object.entries(schema).map(([key, value]) => {\n if (value.constructor.name !== 'Object') {\n return [key, combinator(rule, value)]\n }\n return [key, combineRuleWithAll(value, rule, combinator)]\n }),\n ) as ShieldSchema<T>\n}\n\n/**\n * Creates graphql shield middleware making use of generics to type the definition of the rules.\n * @param schema A mapping of schema objects to the shield rules that define the access to that object\n * @param fallbackRule A fallback rule to apply to any object or property which doesn't have a defined rule.\n *\n * Usage:\n * import { Resolvers } from '../generated/types'\n *\n * const shieldSchema = createShieldSchema<Resolvers>({\n * Query: {\n * getThings: allow,\n * dontGetThings: deny,\n * }\n * })\n *\n * let schema = makeExecutableSchema({...})\n *\n * schema = applyMiddleware(schema, shieldSchema)\n */\nexport function createShieldSchema<TRootResolvers>(schema: ShieldSchema<TRootResolvers>, fallbackRule: ShieldRule = allow) {\n return shield(schema as IRules, {\n allowExternalErrors: true,\n fallbackRule: fallbackRule,\n })\n}\n\nexport type ShieldSchema<TResolver> = TResolver extends Primitive\n ? ShieldRule\n : {\n [key in keyof TResolver]?: ShieldSchema<TResolver[key]> | ShieldRule\n } & {\n '*'?: ShieldRule\n }\n"],"names":[],"mappings":";;AAQO,MAAM,UAAU,GAAG,CACxB,KAA0F,EAC1F,KAAA,GAAiC,QAAQ,KAC1B,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC;AAEtF;;;;;;;;;AASG;SACa,kBAAkB,CAAI,MAAuB,EAAE,IAAgB,EAAE,UAA0B,EAAA;IACzG,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;QAC1C,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC;AACA,QAAA,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC,CAAC,CACgB;AACtB;AAEA;;;;;;;;;;;;;;;;;;AAkBG;SACa,kBAAkB,CAAiB,MAAoC,EAAE,eAA2B,KAAK,EAAA;IACvH,OAAO,MAAM,CAAC,MAAgB,EAAE;AAC9B,QAAA,mBAAmB,EAAE,IAAI;AACzB,QAAA,YAAY,EAAE,YAAY;AAC3B,KAAA,CAAC;AACJ;;;;"}
@@ -1,22 +1,24 @@
1
- /// <reference types="node" />
2
1
  import type { Logger } from '@makerx/node-common';
3
2
  import type { IncomingMessage } from 'http';
4
3
  import { User } from '../User';
5
- import type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo } from '../context';
4
+ import type { CreateRequestLogger, GraphQLContext, JwtPayload, RequestInfo, RequestInfoLogKey } from '../context';
6
5
  export interface SubscriptionContextInput {
7
6
  connectRequest: IncomingMessage;
8
7
  connectionParams?: Readonly<Record<string, unknown>>;
9
8
  claims?: JwtPayload;
10
9
  }
11
- export type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T>;
10
+ export type CreateSubscriptionUser<T = User | undefined> = (input: SubscriptionContextInput) => Promise<T> | T;
12
11
  export type CreateSubscriptionContext<TContext = GraphQLContext> = (input: SubscriptionContextInput) => Promise<TContext>;
13
12
  export type AugmentSubscriptionRequestInfo = (input: SubscriptionContextInput) => Record<string, unknown>;
14
- export interface CreateSubscriptionContextConfig<TContext = GraphQLContext> {
15
- requestLogger: CreateRequestLogger | Logger;
13
+ export type CreateSubscriptionContextConfig<TUser = User | undefined, TAugment extends Record<string, unknown> = Record<string, never>, TLogger extends Logger = Logger> = {
14
+ requestLogger: CreateRequestLogger<TUser, TLogger> | TLogger;
16
15
  augmentRequestInfo?: AugmentSubscriptionRequestInfo;
17
16
  claimsToLog?: string[];
18
- createUser?: CreateSubscriptionUser;
19
- requestInfoToLog?: Array<keyof RequestInfo>;
20
- augmentContext?: (context: TContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
21
- }
22
- export declare const createSubscriptionContextFactory: <TContext extends GraphQLContext<Logger, RequestInfo, User | undefined> = GraphQLContext<Logger, RequestInfo, User | undefined>>({ requestLogger, augmentRequestInfo, claimsToLog, createUser, requestInfoToLog, augmentContext, }: CreateSubscriptionContextConfig<TContext>) => CreateSubscriptionContext<TContext>;
17
+ requestInfoToLog?: Array<RequestInfoLogKey>;
18
+ augmentContext?: (context: GraphQLContext<TLogger, RequestInfo, TUser>) => TAugment | Promise<TAugment>;
19
+ } & ([User | undefined] extends [TUser] ? {
20
+ createUser?: CreateSubscriptionUser<TUser>;
21
+ } : {
22
+ createUser: CreateSubscriptionUser<TUser>;
23
+ });
24
+ export declare const createSubscriptionContextFactory: <TUser = User | undefined, TAugment extends Record<string, unknown> = Record<string, never>, TLogger extends Logger = Logger>(config: CreateSubscriptionContextConfig<TUser, TAugment, TLogger>) => CreateSubscriptionContext<GraphQLContext<TLogger, RequestInfo, TUser> & TAugment>;