@subsquid/openreader 4.4.1 → 4.5.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 (54) hide show
  1. package/lib/context.d.ts +6 -3
  2. package/lib/context.d.ts.map +1 -1
  3. package/lib/db.d.ts +11 -13
  4. package/lib/db.d.ts.map +1 -1
  5. package/lib/db.js +51 -29
  6. package/lib/db.js.map +1 -1
  7. package/lib/limit.size.js.map +1 -1
  8. package/lib/model.schema.js.map +1 -1
  9. package/lib/model.tools.js.map +1 -1
  10. package/lib/opencrud/orderBy.js.map +1 -1
  11. package/lib/opencrud/schema.js.map +1 -1
  12. package/lib/opencrud/tree.js.map +1 -1
  13. package/lib/opencrud/where.js.map +1 -1
  14. package/lib/scalars/BigDecimal.js.map +1 -1
  15. package/lib/scalars/BigInt.js.map +1 -1
  16. package/lib/scalars/Bytes.js.map +1 -1
  17. package/lib/scalars/DateTime.js.map +1 -1
  18. package/lib/server.d.ts.map +1 -1
  19. package/lib/server.js +8 -23
  20. package/lib/server.js.map +1 -1
  21. package/lib/sql/cursor.js.map +1 -1
  22. package/lib/sql/mapping.js.map +1 -1
  23. package/lib/sql/printer.js.map +1 -1
  24. package/lib/sql/query.js.map +1 -1
  25. package/lib/sql/util.js.map +1 -1
  26. package/lib/subscription.js.map +1 -1
  27. package/lib/test/limits.test.js +1 -1
  28. package/lib/test/limits.test.js.map +1 -1
  29. package/lib/test/setup.d.ts.map +1 -1
  30. package/lib/test/setup.js +1 -0
  31. package/lib/test/setup.js.map +1 -1
  32. package/lib/tools.js.map +1 -1
  33. package/lib/util/big-decimal.js.map +1 -1
  34. package/lib/util/error-handling.d.ts +8 -9
  35. package/lib/util/error-handling.d.ts.map +1 -1
  36. package/lib/util/error-handling.js +32 -32
  37. package/lib/util/error-handling.js.map +1 -1
  38. package/lib/util/execute.d.ts +7 -2
  39. package/lib/util/execute.d.ts.map +1 -1
  40. package/lib/util/execute.js +74 -14
  41. package/lib/util/execute.js.map +1 -1
  42. package/lib/util/lazy-transaction.js.map +1 -1
  43. package/lib/util/limit.js +2 -2
  44. package/lib/util/limit.js.map +1 -1
  45. package/lib/util/resolve-tree.js.map +1 -1
  46. package/package.json +21 -21
  47. package/src/context.ts +6 -3
  48. package/src/db.ts +68 -37
  49. package/src/server.ts +18 -24
  50. package/src/test/limits.test.ts +1 -1
  51. package/src/test/setup.ts +2 -0
  52. package/src/util/error-handling.ts +40 -30
  53. package/src/util/execute.ts +96 -14
  54. package/src/util/limit.ts +2 -2
@@ -1,28 +1,88 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeWithLimit = void 0;
3
+ exports.openreaderSubscribe = exports.openreaderExecute = void 0;
4
+ const logger_1 = require("@subsquid/logger");
5
+ const util_internal_1 = require("@subsquid/util-internal");
6
+ const apollo_server_core_1 = require("apollo-server-core");
4
7
  const graphql_1 = require("graphql");
5
8
  const execute_1 = require("graphql/execution/execute");
6
- function executeWithLimit(maxQueries, args) {
9
+ const error_handling_1 = require("./error-handling");
10
+ async function openreaderExecute(args, options) {
11
+ let log = args.contextValue.openreader.log?.child('gql');
12
+ if (log?.isDebug()) {
13
+ log.debug((0, error_handling_1.getDocumentCtx)(args), 'graphql query');
14
+ }
15
+ let result;
16
+ let errors = validate(args, options);
17
+ if (errors.length > 0) {
18
+ result = { errors };
19
+ }
20
+ else {
21
+ result = await (0, execute_1.execute)(args);
22
+ }
23
+ logResult('graphql result', log, args, result);
24
+ return result;
25
+ }
26
+ exports.openreaderExecute = openreaderExecute;
27
+ async function openreaderSubscribe(args) {
28
+ let log = args.contextValue.openreader.log?.child('gql');
29
+ if (log?.isDebug()) {
30
+ log.debug((0, error_handling_1.getDocumentCtx)(args), 'graphql subscription');
31
+ }
32
+ let result;
33
+ let errors = validate(args, {});
34
+ if (errors.length > 0) {
35
+ result = { errors };
36
+ }
37
+ else {
38
+ result = await (0, graphql_1.subscribe)(args);
39
+ }
40
+ if (result[Symbol.asyncIterator]) {
41
+ log?.debug('graphql subscription initiated');
42
+ if (log)
43
+ return logSubscriptionResults(log, args, result);
44
+ }
45
+ else {
46
+ logResult('graphql subscription result', log, args, result);
47
+ }
48
+ return result;
49
+ }
50
+ exports.openreaderSubscribe = openreaderSubscribe;
51
+ async function* logSubscriptionResults(log, args, results) {
52
+ for await (let result of results) {
53
+ logResult('graphql subscription result', log, args, result);
54
+ yield result;
55
+ }
56
+ log.debug('graphql subscription ended');
57
+ }
58
+ function logResult(msg, log, args, result) {
59
+ if (log == null)
60
+ return;
61
+ if (log.isDebug()) {
62
+ log.debug({
63
+ graphqlResult: log.isTrace() ? result : undefined
64
+ }, msg);
65
+ }
66
+ (0, error_handling_1.logGraphQLErrors)(log, args, result.errors);
67
+ }
68
+ function validate(args, { maxRootFields }) {
7
69
  (0, execute_1.assertValidExecutionArguments)(args.schema, args.document, args.variableValues);
8
70
  let xtx = (0, execute_1.buildExecutionContext)(args.schema, args.document, args.rootValue, args.contextValue, args.variableValues, args.operationName, args.fieldResolver, args.typeResolver);
9
- if (Array.isArray(xtx)) {
10
- return { errors: xtx };
11
- }
71
+ if (Array.isArray(xtx))
72
+ return xtx.map(err => (0, util_internal_1.addErrorContext)(err, {
73
+ __openreaderLogLevel: logger_1.LogLevel.WARN
74
+ }));
12
75
  let etx = xtx;
13
- if (etx.operation.operation == 'query') {
76
+ if (maxRootFields && etx.operation.operation == 'query') {
14
77
  let query = (0, graphql_1.getOperationRootType)(etx.schema, etx.operation);
15
78
  let fields = (0, execute_1.collectFields)(etx, query, etx.operation.selectionSet, Object.create(null), Object.create(null));
16
79
  let fieldsCount = Object.keys(fields).length;
17
- if (fieldsCount > maxQueries) {
18
- return {
19
- errors: [
20
- new graphql_1.GraphQLError(`only ${maxQueries} root query fields allowed, but got ${fieldsCount}`)
21
- ]
22
- };
80
+ if (fieldsCount > maxRootFields) {
81
+ return [
82
+ new apollo_server_core_1.UserInputError(`only ${maxRootFields} root fields allowed, but got ${fieldsCount}`)
83
+ ];
23
84
  }
24
85
  }
25
- return (0, execute_1.execute)(args);
86
+ return [];
26
87
  }
27
- exports.executeWithLimit = executeWithLimit;
28
88
  //# sourceMappingURL=execute.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/util/execute.ts"],"names":[],"mappings":";;;AAAA,qCAA0D;AAE1D,uDAOkC;AAIlC,SAAgB,gBAAgB,CAAC,UAAkB,EAAE,IAAmB;IACpE,IAAA,uCAA6B,EAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;IAE9E,IAAI,GAAG,GAAG,IAAA,+BAAqB,EAC3B,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,YAAY,CACpB,CAAA;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACpB,OAAO,EAAC,MAAM,EAAE,GAAG,EAAC,CAAA;KACvB;IAED,IAAI,GAAG,GAAG,GAAuB,CAAA;IACjC,IAAI,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,OAAO,EAAE;QACpC,IAAI,KAAK,GAAG,IAAA,8BAAoB,EAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;QAC3D,IAAI,MAAM,GAAG,IAAA,uBAAa,EACtB,GAAG,EACH,KAAK,EACL,GAAG,CAAC,SAAS,CAAC,YAAY,EAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EACnB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CACtB,CAAA;QACD,IAAI,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAA;QAC5C,IAAI,WAAW,GAAG,UAAU,EAAE;YAC1B,OAAO;gBACH,MAAM,EAAE;oBACJ,IAAI,sBAAY,CAAC,QAAQ,UAAU,uCAAuC,WAAW,EAAE,CAAC;iBAC3F;aACJ,CAAA;SACJ;KACJ;IAED,OAAO,IAAA,iBAAc,EAAC,IAAI,CAAC,CAAA;AAC/B,CAAC;AAvCD,4CAuCC"}
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/util/execute.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-transaction.js","sourceRoot":"","sources":["../../src/util/lazy-transaction.ts"],"names":[],"mappings":";;;AAMA,MAAa,eAAe;IAKxB,YAAoB,QAAyD;QAAzD,aAAQ,GAAR,QAAQ,CAAiD;QAJrE,WAAM,GAAG,KAAK,CAAA;IAKtB,CAAC;IAED,KAAK,CAAC,GAAG;QACL,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;SACrD;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAC5C,IAAI,EAAC,GAAG,EAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAA;QACzB,OAAO,GAAG,CAAA;IACd,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gBAC9B,OAAO,IAAI,OAAO,CAAO,KAAK,CAAC,EAAE;oBAC7B,OAAO,CAAC;wBACJ,GAAG;wBACH,KAAK,EAAE,GAAG,EAAE;4BACR,KAAK,EAAE,CAAA;4BACP,OAAO,OAAO,CAAA;wBAClB,CAAC;qBACJ,CAAC,CAAA;gBACN,CAAC,CAAC,CAAA;YACN,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QACrC,CAAC,CAAC,CAAA;IACN,CAAC;IAED,KAAK,CAAC,KAAK;QACP,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,IAAI,CAAC,EAAE,EAAE;YACT,IAAI,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;YAChB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAA;YACnB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;SAClC;IACL,CAAC;CACJ;AA1CD,0CA0CC"}
1
+ {"version":3,"file":"lazy-transaction.js","sourceRoot":"","sources":["../../src/util/lazy-transaction.ts"],"names":[],"mappings":";;;AAMA,MAAa,eAAe;IAKxB,YAAoB,QAAyD;QAAzD,aAAQ,GAAR,QAAQ,CAAiD;QAJrE,WAAM,GAAG,KAAK,CAAA;IAKtB,CAAC;IAED,KAAK,CAAC,GAAG;QACL,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;QACtD,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAC5C,IAAI,EAAC,GAAG,EAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAA;QACzB,OAAO,GAAG,CAAA;IACd,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gBAC9B,OAAO,IAAI,OAAO,CAAO,KAAK,CAAC,EAAE;oBAC7B,OAAO,CAAC;wBACJ,GAAG;wBACH,KAAK,EAAE,GAAG,EAAE;4BACR,KAAK,EAAE,CAAA;4BACP,OAAO,OAAO,CAAA;wBAClB,CAAC;qBACJ,CAAC,CAAA;gBACN,CAAC,CAAC,CAAA;YACN,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QACrC,CAAC,CAAC,CAAA;IACN,CAAC;IAED,KAAK,CAAC,KAAK;QACP,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACV,IAAI,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;YAChB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAA;YACnB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;QACnC,CAAC;IACL,CAAC;CACJ;AA1CD,0CA0CC"}
package/lib/util/limit.js CHANGED
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ResponseSizeLimit = exports.Limit = void 0;
7
+ const apollo_server_core_1 = require("apollo-server-core");
7
8
  const assert_1 = __importDefault(require("assert"));
8
- const graphql_1 = require("graphql");
9
9
  class Limit {
10
10
  constructor(error, value) {
11
11
  this.error = error;
@@ -28,7 +28,7 @@ class Limit {
28
28
  }
29
29
  }
30
30
  exports.Limit = Limit;
31
- const SIZE_LIMIT = new graphql_1.GraphQLError('response might exceed the size limit');
31
+ const SIZE_LIMIT = new apollo_server_core_1.UserInputError('response might exceed the size limit');
32
32
  SIZE_LIMIT.stack = undefined;
33
33
  class ResponseSizeLimit extends Limit {
34
34
  constructor(maxNodes) {
@@ -1 +1 @@
1
- {"version":3,"file":"limit.js","sourceRoot":"","sources":["../../src/util/limit.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA2B;AAC3B,qCAAoC;AAGpC,MAAa,KAAK;IACd,YAAoB,KAAY,EAAU,KAAa;QAAnC,UAAK,GAAL,KAAK,CAAO;QAAU,UAAK,GAAL,KAAK,CAAQ;QACnD,IAAA,gBAAM,EAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,EAA4B;QAC9B,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,KAAK,CAAA;QACpC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,IAAI,IAAI,GAAG,CAAC,EAAE;YACV,MAAM,IAAI,CAAC,KAAK,CAAA;SACnB;aAAM;YACH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;SACpB;IACL,CAAC;CACJ;AAlBD,sBAkBC;AAGD,MAAM,UAAU,GAAG,IAAI,sBAAY,CAAC,sCAAsC,CAAC,CAAA;AAC3E,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;AAG5B,MAAa,iBAAkB,SAAQ,KAAK;IACxC,YAAY,QAAgB;QACxB,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC/B,CAAC;CACJ;AAJD,8CAIC"}
1
+ {"version":3,"file":"limit.js","sourceRoot":"","sources":["../../src/util/limit.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAiD;AACjD,oDAA2B;AAG3B,MAAa,KAAK;IACd,YAAoB,KAAY,EAAU,KAAa;QAAnC,UAAK,GAAL,KAAK,CAAO;QAAU,UAAK,GAAL,KAAK,CAAQ;QACnD,IAAA,gBAAM,EAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,EAA4B;QAC9B,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,KAAK,CAAA;QACpC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,KAAK,CAAA;QACpB,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACrB,CAAC;IACL,CAAC;CACJ;AAlBD,sBAkBC;AAGD,MAAM,UAAU,GAAG,IAAI,mCAAc,CAAC,sCAAsC,CAAC,CAAA;AAC7E,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;AAG5B,MAAa,iBAAkB,SAAQ,KAAK;IACxC,YAAY,QAAgB;QACxB,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC/B,CAAC;CACJ;AAJD,8CAIC"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-tree.js","sourceRoot":"","sources":["../../src/util/resolve-tree.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAiD;AACjD,oDAA2B;AAE3B,2EAKmC;AAanC,SAAgB,mBAAmB,CAAC,MAAqB,EAAE,IAAiB,EAAE,QAAgB;IAC1F,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnC,IAAA,gBAAM,EAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IACpB,OAAO,IAAA,sEAAyC,EAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAChE,CAAC;AAJD,kDAIC;AAKD,SAAgB,cAAc,CAAC,IAAwB,EAAE,QAAiB;IACtE,IAAI,IAAI,GAAG,IAAA,6CAAgB,EAAC,IAAI,CAAC,CAAA;IACjC,IAAA,gBAAM,EAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3B,IAAI,QAAQ,EAAE;QACV,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;KAC1D;SAAM;QACH,OAAO,IAAI,CAAA;KACd;AACL,CAAC;AARD,wCAQC;AAGD,SAAS,aAAa,CAAC,WAA8D;IACjF,OAAO,WAAW,IAAI,IAAI,IAAI,WAAW,CAAC,gBAAgB,IAAI,IAAI,CAAA;AACtE,CAAC;AAGD,SAAgB,cAAc,CAAC,UAA6B,EAAE,SAAiB;IAC3E,IAAI,GAA4B,CAAA;IAChC,KAAK,IAAI,KAAK,IAAI,UAAU,EAAE;QAC1B,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QACzB,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS;YAAE,SAAQ;QACjC,IAAI,GAAG,IAAI,IAAI;YAAE,MAAM,IAAI,mCAAc,CAAC,+BAA+B,SAAS,qBAAqB,CAAC,CAAA;QACxG,GAAG,GAAG,CAAC,CAAA;KACV;IACD,OAAO,GAAG,CAAA;AACd,CAAC;AATD,wCASC;AAGD,SAAgB,cAAc,CAAC,UAA6B,EAAE,SAAiB;IAC3E,KAAK,IAAI,KAAK,IAAI,UAAU,EAAE;QAC1B,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QACzB,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS;YAAE,OAAO,IAAI,CAAA;KACvC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAND,wCAMC"}
1
+ {"version":3,"file":"resolve-tree.js","sourceRoot":"","sources":["../../src/util/resolve-tree.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAiD;AACjD,oDAA2B;AAE3B,2EAKmC;AAanC,SAAgB,mBAAmB,CAAC,MAAqB,EAAE,IAAiB,EAAE,QAAgB;IAC1F,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnC,IAAA,gBAAM,EAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IACpB,OAAO,IAAA,sEAAyC,EAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAChE,CAAC;AAJD,kDAIC;AAKD,SAAgB,cAAc,CAAC,IAAwB,EAAE,QAAiB;IACtE,IAAI,IAAI,GAAG,IAAA,6CAAgB,EAAC,IAAI,CAAC,CAAA;IACjC,IAAA,gBAAM,EAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3B,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC3D,CAAC;SAAM,CAAC;QACJ,OAAO,IAAI,CAAA;IACf,CAAC;AACL,CAAC;AARD,wCAQC;AAGD,SAAS,aAAa,CAAC,WAA8D;IACjF,OAAO,WAAW,IAAI,IAAI,IAAI,WAAW,CAAC,gBAAgB,IAAI,IAAI,CAAA;AACtE,CAAC;AAGD,SAAgB,cAAc,CAAC,UAA6B,EAAE,SAAiB;IAC3E,IAAI,GAA4B,CAAA;IAChC,KAAK,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QACzB,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS;YAAE,SAAQ;QACjC,IAAI,GAAG,IAAI,IAAI;YAAE,MAAM,IAAI,mCAAc,CAAC,+BAA+B,SAAS,qBAAqB,CAAC,CAAA;QACxG,GAAG,GAAG,CAAC,CAAA;IACX,CAAC;IACD,OAAO,GAAG,CAAA;AACd,CAAC;AATD,wCASC;AAGD,SAAgB,cAAc,CAAC,UAA6B,EAAE,SAAiB;IAC3E,KAAK,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QACzB,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS;YAAE,OAAO,IAAI,CAAA;IACxC,CAAC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAND,wCAMC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subsquid/openreader",
3
- "version": "4.4.1",
3
+ "version": "4.5.0",
4
4
  "description": "GraphQL server for postgres-compatible databases",
5
5
  "keywords": [
6
6
  "graphql",
@@ -21,22 +21,22 @@
21
21
  "src"
22
22
  ],
23
23
  "dependencies": {
24
- "@graphql-tools/merge": "^9.0.0",
24
+ "@graphql-tools/merge": "^9.0.1",
25
25
  "@subsquid/graphiql-console": "^0.3.0",
26
- "@subsquid/logger": "^1.3.1",
27
- "@subsquid/util-internal": "^2.5.2",
28
- "@subsquid/util-internal-commander": "^1.3.1",
29
- "@subsquid/util-internal-hex": "^1.2.1",
30
- "@subsquid/util-internal-http-server": "^1.2.1",
31
- "@subsquid/util-naming": "^1.2.1",
32
- "apollo-server-core": "^3.12.1",
33
- "apollo-server-express": "^3.12.1",
34
- "commander": "^11.0.0",
35
- "deep-equal": "^2.2.2",
26
+ "@subsquid/logger": "^1.3.2",
27
+ "@subsquid/util-internal": "^3.0.0",
28
+ "@subsquid/util-internal-commander": "^1.3.2",
29
+ "@subsquid/util-internal-hex": "^1.2.2",
30
+ "@subsquid/util-internal-http-server": "^1.2.2",
31
+ "@subsquid/util-naming": "^1.2.2",
32
+ "apollo-server-core": "^3.13.0",
33
+ "apollo-server-express": "^3.13.0",
34
+ "commander": "^11.1.0",
35
+ "deep-equal": "^2.2.3",
36
36
  "express": "^4.18.2",
37
37
  "graphql": "^15.8.0",
38
- "graphql-parse-resolve-info": "^4.13.0",
39
- "graphql-ws": "^5.14.1",
38
+ "graphql-parse-resolve-info": "^4.14.0",
39
+ "graphql-ws": "^5.14.2",
40
40
  "pg": "^8.11.3",
41
41
  "ws": "^8.14.2"
42
42
  },
@@ -49,17 +49,17 @@
49
49
  }
50
50
  },
51
51
  "devDependencies": {
52
- "@types/deep-equal": "^1.0.2",
53
- "@types/express": "^4.17.18",
54
- "@types/mocha": "^10.0.2",
55
- "@types/node": "^18.18.0",
56
- "@types/pg": "^8.10.3",
57
- "@types/ws": "^8.5.6",
52
+ "@types/deep-equal": "^1.0.4",
53
+ "@types/express": "^4.17.21",
54
+ "@types/mocha": "^10.0.6",
55
+ "@types/node": "^18.18.14",
56
+ "@types/pg": "^8.10.9",
57
+ "@types/ws": "^8.5.10",
58
58
  "dotenv": "^16.3.1",
59
59
  "expect": "^29.7.0",
60
60
  "gql-test-client": "^0.0.0",
61
61
  "mocha": "^10.2.0",
62
- "typescript": "~5.2.2"
62
+ "typescript": "~5.3.2"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "rm -rf lib && tsc",
package/src/context.ts CHANGED
@@ -1,6 +1,7 @@
1
- import {Dialect} from './dialect'
2
- import {Query} from './sql/query'
3
- import {Limit} from './util/limit'
1
+ import type {Logger} from '@subsquid/logger'
2
+ import type {Dialect} from './dialect'
3
+ import type {Query} from './sql/query'
4
+ import type {Limit} from './util/limit'
4
5
 
5
6
 
6
7
  export interface Context {
@@ -9,9 +10,11 @@ export interface Context {
9
10
 
10
11
 
11
12
  export interface OpenreaderContext {
13
+ id: number
12
14
  dialect: Dialect
13
15
  executeQuery<T>(query: Query<T>): Promise<T>
14
16
  subscription<T>(query: Query<T>): AsyncIterable<T>
15
17
  responseSizeLimit?: Limit
16
18
  subscriptionResponseSizeLimit?: Limit
19
+ log?: Logger
17
20
  }
package/src/db.ts CHANGED
@@ -1,39 +1,33 @@
1
- import type {ClientBase, Pool} from "pg"
2
- import {OpenreaderContext} from "./context"
3
- import {Dialect} from "./dialect"
4
- import {Query} from "./sql/query"
5
- import {Subscription} from "./subscription"
6
- import {withErrorContext} from "./util/error-handling"
7
- import {LazyTransaction} from "./util/lazy-transaction"
1
+ import type {Logger} from '@subsquid/logger'
2
+ import {addErrorContext} from '@subsquid/util-internal'
3
+ import type {ClientBase, Pool} from 'pg'
4
+ import {QueryResult} from 'pg'
5
+ import {OpenreaderContext} from './context'
6
+ import {Dialect} from './dialect'
7
+ import {Query} from './sql/query'
8
+ import {Subscription} from './subscription'
9
+ import {LazyTransaction} from './util/lazy-transaction'
8
10
 
9
11
 
10
- export interface Database {
11
- query(sql: string, parameters?: any[]): Promise<any[][]>
12
- }
13
-
14
-
15
- export class PgDatabase implements Database {
16
- constructor(private client: ClientBase) {}
17
-
18
- query(sql: string, parameters?: any[]): Promise<any[][]> {
19
- return this.client.query({text: sql, rowMode: 'array'}, parameters)
20
- .then(result => result.rows)
21
- .catch(withErrorContext({sql, parameters}))
22
- }
23
- }
12
+ let CTX_COUNTER = 0
24
13
 
25
14
 
26
15
  export class PoolOpenreaderContext implements OpenreaderContext {
16
+ public id = (CTX_COUNTER = (CTX_COUNTER + 1) % Number.MAX_SAFE_INTEGER)
17
+ public log?: Logger
27
18
  private tx: LazyTransaction<Database>
28
19
  private subscriptionPool: Pool
20
+ private queryCounter = 0
29
21
 
30
22
  constructor(
31
23
  public readonly dialect: Dialect,
32
24
  pool: Pool,
33
25
  subscriptionPool?: Pool,
34
- private subscriptionPollInterval: number = 1000
26
+ private subscriptionPollInterval: number = 1000,
27
+ log?: Logger
35
28
  ) {
36
- this.tx = new LazyTransaction(cb => transact(pool, cb))
29
+ this.log = log?.child({graphqlCtx: this.id})
30
+ this.tx = new LazyTransaction(cb => this.transact(pool, cb))
37
31
  this.subscriptionPool = subscriptionPool || pool
38
32
  }
39
33
 
@@ -43,30 +37,67 @@ export class PoolOpenreaderContext implements OpenreaderContext {
43
37
 
44
38
  async executeQuery<T>(query: Query<T>): Promise<T> {
45
39
  let db = await this.tx.get()
46
- let result = await db.query(query.sql, query.params)
40
+ let result = await db(query.sql, query.params)
47
41
  return query.map(result)
48
42
  }
49
43
 
50
44
  subscription<T>(query: Query<T>): AsyncIterable<T> {
51
- return new Subscription(this.subscriptionPollInterval, () => transact(this.subscriptionPool, async db => {
52
- let result = await db.query(query.sql, query.params)
45
+ return new Subscription(this.subscriptionPollInterval, () => this.transact(this.subscriptionPool, async db => {
46
+ let result = await db(query.sql, query.params)
53
47
  return query.map(result)
54
48
  }))
55
49
  }
56
- }
57
-
58
50
 
59
- async function transact<T>(pool: Pool, cb: (db: Database) => Promise<T>): Promise<T> {
60
- let client = await pool.connect()
61
- try {
62
- await client.query('START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY')
51
+ private async transact<T>(pool: Pool, cb: (db: Database) => Promise<T>): Promise<T> {
52
+ let client = await pool.connect()
63
53
  try {
64
- let db = new PgDatabase(client)
65
- return await cb(db)
54
+ await this.query(client, 'START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY')
55
+ try {
56
+ return await cb(async (sql, parameters) => {
57
+ let result = await this.query(client, sql, parameters)
58
+ return result.rows
59
+ })
60
+ } finally {
61
+ await this.query(client, 'COMMIT').catch(() => {})
62
+ }
66
63
  } finally {
67
- await client.query('COMMIT').catch(() => {})
64
+ client.release()
65
+ }
66
+ }
67
+
68
+ private async query(client: ClientBase, sql: string, parameters?: any[]): Promise<QueryResult> {
69
+ let queryId = this.queryCounter = (this.queryCounter + 1) % Number.MAX_SAFE_INTEGER
70
+
71
+ let ctx = {
72
+ graphqlCtx: this.id,
73
+ graphqlSqlQuery: queryId,
74
+ }
75
+
76
+ let log = this.log?.child('sql', ctx)
77
+
78
+ log?.debug({
79
+ sql,
80
+ parameters
81
+ }, 'sql query')
82
+
83
+ try {
84
+ let result = await client.query({text: sql, rowMode: 'array'}, parameters)
85
+ log?.debug({
86
+ rowCount: result.rowCount || 0,
87
+ rows: log.isTrace() ? result.rows : undefined
88
+ }, 'sql result')
89
+ return result
90
+ } catch(err: any) {
91
+ throw addErrorContext(err, {
92
+ ...ctx,
93
+ sql,
94
+ parameters
95
+ })
68
96
  }
69
- } finally {
70
- client.release()
71
97
  }
72
98
  }
99
+
100
+
101
+ interface Database {
102
+ (sql: string, parameters?: any[]): Promise<any[][]>
103
+ }
package/src/server.ts CHANGED
@@ -15,8 +15,7 @@ import {PoolOpenreaderContext} from './db'
15
15
  import type {Dialect} from './dialect'
16
16
  import type {Model} from './model'
17
17
  import {SchemaBuilder} from './opencrud/schema'
18
- import {logGraphQLError} from './util/error-handling'
19
- import {executeWithLimit} from './util/execute'
18
+ import {openreaderExecute, openreaderSubscribe} from './util/execute'
20
19
  import {ResponseSizeLimit} from './util/limit'
21
20
 
22
21
 
@@ -38,7 +37,15 @@ export interface ServerOptions {
38
37
  }
39
38
 
40
39
  export async function serve(options: ServerOptions): Promise<ListeningServer> {
41
- let {connection, subscriptionConnection, subscriptionPollInterval, maxResponseNodes, subscriptionMaxResponseNodes} = options
40
+ let {
41
+ connection,
42
+ subscriptionConnection,
43
+ subscriptionPollInterval,
44
+ maxResponseNodes,
45
+ subscriptionMaxResponseNodes,
46
+ log
47
+ } = options
48
+
42
49
  let dialect = options.dialect ?? 'postgres'
43
50
 
44
51
  let schema = new SchemaBuilder(options).build()
@@ -48,7 +55,8 @@ export async function serve(options: ServerOptions): Promise<ListeningServer> {
48
55
  dialect,
49
56
  connection,
50
57
  subscriptionConnection,
51
- subscriptionPollInterval
58
+ subscriptionPollInterval,
59
+ log
52
60
  )
53
61
 
54
62
  if (maxResponseNodes) {
@@ -107,9 +115,9 @@ export async function runApollo(options: ApolloOptions): Promise<ListeningServer
107
115
  let app = express()
108
116
  let server = http.createServer(app)
109
117
 
110
- const execute = maxRootFields
111
- ? (args: ExecutionArgs) => executeWithLimit(maxRootFields, args)
112
- : undefined
118
+ let execute = (args: ExecutionArgs) => openreaderExecute(args, {
119
+ maxRootFields: maxRootFields
120
+ })
113
121
 
114
122
  if (options.subscriptions) {
115
123
  let wsServer = new WebSocketServer({
@@ -122,14 +130,7 @@ export async function runApollo(options: ApolloOptions): Promise<ListeningServer
122
130
  schema,
123
131
  context,
124
132
  execute,
125
- onError(ctx, message, errors) {
126
- if (log) {
127
- // FIXME: we don't want to log client errors
128
- for (let err of errors) {
129
- logGraphQLError(log, err)
130
- }
131
- }
132
- },
133
+ subscribe: openreaderSubscribe,
133
134
  onNext(_ctx, _message, args, result) {
134
135
  args.contextValue.openreader.close()
135
136
  return result
@@ -147,7 +148,7 @@ export async function runApollo(options: ApolloOptions): Promise<ListeningServer
147
148
  cache: options.cache,
148
149
  stopOnTerminationSignals: false,
149
150
  allowBatchedHttpRequests: false,
150
- executor: execute && (async req => {
151
+ executor: async req => {
151
152
  return execute({
152
153
  schema,
153
154
  document: req.document,
@@ -156,7 +157,7 @@ export async function runApollo(options: ApolloOptions): Promise<ListeningServer
156
157
  variableValues: req.request.variables,
157
158
  operationName: req.operationName
158
159
  })
159
- }),
160
+ },
160
161
  plugins: [
161
162
  ...options.plugins || [],
162
163
  {
@@ -164,13 +165,6 @@ export async function runApollo(options: ApolloOptions): Promise<ListeningServer
164
165
  return {
165
166
  willSendResponse(req: any) {
166
167
  return req.context.openreader.close()
167
- },
168
- async didEncounterErrors(req) {
169
- if (req.operation && log) {
170
- for (let err of req.errors) {
171
- logGraphQLError(log, err)
172
- }
173
- }
174
168
  }
175
169
  }
176
170
  }
@@ -155,7 +155,7 @@ describe('response size limits', function() {
155
155
  `, {
156
156
  errors: [
157
157
  expect.objectContaining({
158
- message: 'only 3 root query fields allowed, but got 4'
158
+ message: 'only 3 root fields allowed, but got 4'
159
159
  })
160
160
  ]
161
161
  })
package/src/test/setup.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import {createLogger} from '@subsquid/logger'
1
2
  import {assertNotNull} from "@subsquid/util-internal"
2
3
  import {ListeningServer} from "@subsquid/util-internal-http-server"
3
4
  import {Client} from "gql-test-client"
@@ -72,6 +73,7 @@ export function useServer(schema: string, options?: Partial<ServerOptions>): Cli
72
73
  subscriptions: true,
73
74
  subscriptionPollInterval: 500,
74
75
  maxRootFields: 10,
76
+ // log: createLogger('sqd:openreader'),
75
77
  ...options
76
78
  })
77
79
  client.endpoint = `http://localhost:${info.port}/graphql`
@@ -1,40 +1,50 @@
1
- import {Logger, LogLevel} from "@subsquid/logger"
2
- import {GraphQLError, printError} from "graphql"
1
+ import {Logger, LogLevel} from '@subsquid/logger'
2
+ import {weakMemo} from '@subsquid/util-internal'
3
+ import {ExecutionArgs, GraphQLError, print} from 'graphql'
3
4
 
4
5
 
5
- export function logGraphQLError(log: Logger, err: GraphQLError, level: LogLevel = LogLevel.ERROR): void {
6
- if (log.level > level) return
7
- let msg = printError(err) + '\n'
8
- log.write(level, {
9
- graphqlOriginalError: err.originalError,
10
- graphqlPath: err.path?.join('.'),
11
- graphqlQuery: err.source?.body,
12
- }, msg)
6
+ export interface DocumentCtx {
7
+ graphqlOperationName?: string
8
+ graphqlDocument: string
9
+ graphqlVariables: any
13
10
  }
14
11
 
15
12
 
16
- export function withErrorContext(ctx: object): (err: unknown) => never {
17
- return function(err): never {
18
- throw addErrorContext(err, ctx)
13
+ export const getDocumentCtx = weakMemo((args: ExecutionArgs): DocumentCtx => {
14
+ return {
15
+ graphqlOperationName: args.operationName || undefined,
16
+ graphqlDocument: print(args.document),
17
+ graphqlVariables: args.variableValues
19
18
  }
19
+ })
20
+
21
+
22
+ export function logGraphQLErrors(
23
+ log: Logger,
24
+ args: ExecutionArgs,
25
+ errors: readonly GraphQLError[] | undefined,
26
+ ): void {
27
+ if (!errors?.length) return
28
+ let level = 0
29
+ let graphqlErrors = errors.map(err => {
30
+ level = Math.max(level, getErrorLevel(err))
31
+ return {
32
+ message: err.message,
33
+ path: err.path?.join('.'),
34
+ extensions: err.extensions,
35
+ originalError: err.originalError
36
+ }
37
+ })
38
+ if (log.level > level) return
39
+ log.write(level, {
40
+ graphqlErrors,
41
+ ...getDocumentCtx(args)
42
+ }, 'graphql query ended with errors')
20
43
  }
21
44
 
22
45
 
23
- export function addErrorContext(error: unknown, ctx: object): Error {
24
- let e = ensureError(error)
25
- Object.assign(e, ctx)
26
- return e
27
- }
28
-
29
-
30
- export function ensureError(err: unknown): Error {
31
- if (err instanceof Error) return err
32
- return new NonErrorThrown(err)
33
- }
34
-
35
-
36
- export class NonErrorThrown extends Error {
37
- constructor(public readonly value: unknown) {
38
- super('Non error object thrown')
39
- }
46
+ function getErrorLevel(err: GraphQLError): LogLevel {
47
+ if ((err as any).__openreaderLogLevel) return (err as any).__openreaderLogLevel
48
+ if (err.extensions?.code === 'BAD_USER_INPUT') return LogLevel.WARN
49
+ return LogLevel.ERROR
40
50
  }