@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.
- package/lib/context.d.ts +6 -3
- package/lib/context.d.ts.map +1 -1
- package/lib/db.d.ts +11 -13
- package/lib/db.d.ts.map +1 -1
- package/lib/db.js +51 -29
- package/lib/db.js.map +1 -1
- package/lib/limit.size.js.map +1 -1
- package/lib/model.schema.js.map +1 -1
- package/lib/model.tools.js.map +1 -1
- package/lib/opencrud/orderBy.js.map +1 -1
- package/lib/opencrud/schema.js.map +1 -1
- package/lib/opencrud/tree.js.map +1 -1
- package/lib/opencrud/where.js.map +1 -1
- package/lib/scalars/BigDecimal.js.map +1 -1
- package/lib/scalars/BigInt.js.map +1 -1
- package/lib/scalars/Bytes.js.map +1 -1
- package/lib/scalars/DateTime.js.map +1 -1
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +8 -23
- package/lib/server.js.map +1 -1
- package/lib/sql/cursor.js.map +1 -1
- package/lib/sql/mapping.js.map +1 -1
- package/lib/sql/printer.js.map +1 -1
- package/lib/sql/query.js.map +1 -1
- package/lib/sql/util.js.map +1 -1
- package/lib/subscription.js.map +1 -1
- package/lib/test/limits.test.js +1 -1
- package/lib/test/limits.test.js.map +1 -1
- package/lib/test/setup.d.ts.map +1 -1
- package/lib/test/setup.js +1 -0
- package/lib/test/setup.js.map +1 -1
- package/lib/tools.js.map +1 -1
- package/lib/util/big-decimal.js.map +1 -1
- package/lib/util/error-handling.d.ts +8 -9
- package/lib/util/error-handling.d.ts.map +1 -1
- package/lib/util/error-handling.js +32 -32
- package/lib/util/error-handling.js.map +1 -1
- package/lib/util/execute.d.ts +7 -2
- package/lib/util/execute.d.ts.map +1 -1
- package/lib/util/execute.js +74 -14
- package/lib/util/execute.js.map +1 -1
- package/lib/util/lazy-transaction.js.map +1 -1
- package/lib/util/limit.js +2 -2
- package/lib/util/limit.js.map +1 -1
- package/lib/util/resolve-tree.js.map +1 -1
- package/package.json +21 -21
- package/src/context.ts +6 -3
- package/src/db.ts +68 -37
- package/src/server.ts +18 -24
- package/src/test/limits.test.ts +1 -1
- package/src/test/setup.ts +2 -0
- package/src/util/error-handling.ts +40 -30
- package/src/util/execute.ts +96 -14
- package/src/util/limit.ts +2 -2
package/lib/util/execute.js
CHANGED
|
@@ -1,28 +1,88 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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
|
-
|
|
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
|
|
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 >
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
86
|
+
return [];
|
|
26
87
|
}
|
|
27
|
-
exports.executeWithLimit = executeWithLimit;
|
|
28
88
|
//# sourceMappingURL=execute.js.map
|
package/lib/util/execute.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/util/execute.ts"],"names":[],"mappings":";;;AAAA,
|
|
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;
|
|
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
|
|
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) {
|
package/lib/util/limit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limit.js","sourceRoot":"","sources":["../../src/util/limit.ts"],"names":[],"mappings":";;;;;;AAAA,
|
|
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;
|
|
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.
|
|
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.
|
|
24
|
+
"@graphql-tools/merge": "^9.0.1",
|
|
25
25
|
"@subsquid/graphiql-console": "^0.3.0",
|
|
26
|
-
"@subsquid/logger": "^1.3.
|
|
27
|
-
"@subsquid/util-internal": "^
|
|
28
|
-
"@subsquid/util-internal-commander": "^1.3.
|
|
29
|
-
"@subsquid/util-internal-hex": "^1.2.
|
|
30
|
-
"@subsquid/util-internal-http-server": "^1.2.
|
|
31
|
-
"@subsquid/util-naming": "^1.2.
|
|
32
|
-
"apollo-server-core": "^3.
|
|
33
|
-
"apollo-server-express": "^3.
|
|
34
|
-
"commander": "^11.
|
|
35
|
-
"deep-equal": "^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.
|
|
39
|
-
"graphql-ws": "^5.14.
|
|
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.
|
|
53
|
-
"@types/express": "^4.17.
|
|
54
|
-
"@types/mocha": "^10.0.
|
|
55
|
-
"@types/node": "^18.18.
|
|
56
|
-
"@types/pg": "^8.10.
|
|
57
|
-
"@types/ws": "^8.5.
|
|
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.
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
60
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
}
|
package/src/test/limits.test.ts
CHANGED
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
|
|
2
|
-
import {
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
17
|
-
return
|
|
18
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return
|
|
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
|
}
|