@subsquid/openreader 2.0.0 → 2.1.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 +5 -2
- package/lib/context.d.ts.map +1 -1
- package/lib/limit.size.d.ts +7 -2
- package/lib/limit.size.d.ts.map +1 -1
- package/lib/limit.size.js +74 -11
- package/lib/limit.size.js.map +1 -1
- package/lib/main.js +7 -1
- package/lib/main.js.map +1 -1
- package/lib/model.d.ts +1 -0
- package/lib/model.d.ts.map +1 -1
- package/lib/model.schema.d.ts.map +1 -1
- package/lib/model.schema.js +21 -4
- package/lib/model.schema.js.map +1 -1
- package/lib/opencrud/schema.d.ts.map +1 -1
- package/lib/opencrud/schema.js +12 -7
- package/lib/opencrud/schema.js.map +1 -1
- package/lib/server.d.ts +16 -12
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +29 -4
- package/lib/server.js.map +1 -1
- package/lib/test/limits.test.d.ts +2 -0
- package/lib/test/limits.test.d.ts.map +1 -0
- package/lib/test/limits.test.js +159 -0
- package/lib/test/limits.test.js.map +1 -0
- package/lib/test/setup.d.ts +2 -1
- package/lib/test/setup.d.ts.map +1 -1
- package/lib/test/setup.js +5 -2
- package/lib/test/setup.js.map +1 -1
- package/lib/util/execute.d.ts +5 -0
- package/lib/util/execute.d.ts.map +1 -0
- package/lib/util/execute.js +28 -0
- package/lib/util/execute.js.map +1 -0
- package/lib/util/limit.d.ts +11 -0
- package/lib/util/limit.d.ts.map +1 -0
- package/lib/util/limit.js +39 -0
- package/lib/util/limit.js.map +1 -0
- package/package.json +2 -2
- package/src/context.ts +5 -2
- package/src/limit.size.ts +96 -12
- package/src/main.ts +19 -10
- package/src/model.schema.ts +24 -4
- package/src/model.ts +1 -0
- package/src/opencrud/schema.ts +14 -7
- package/src/server.ts +66 -26
- package/src/test/limits.test.ts +163 -0
- package/src/test/setup.ts +6 -3
- package/src/util/execute.ts +53 -0
- package/src/util/limit.ts +34 -0
package/lib/server.js
CHANGED
|
@@ -15,13 +15,23 @@ const ws_2 = require("ws");
|
|
|
15
15
|
const db_1 = require("./db");
|
|
16
16
|
const schema_1 = require("./opencrud/schema");
|
|
17
17
|
const error_handling_1 = require("./util/error-handling");
|
|
18
|
+
const execute_1 = require("./util/execute");
|
|
19
|
+
const limit_1 = require("./util/limit");
|
|
18
20
|
async function serve(options) {
|
|
19
|
-
let { connection, subscriptionConnection, subscriptionPollInterval } = options;
|
|
21
|
+
let { connection, subscriptionConnection, subscriptionPollInterval, maxResponseNodes, subscriptionMaxResponseNodes } = options;
|
|
20
22
|
let dialect = options.dialect ?? 'postgres';
|
|
21
23
|
let schema = new schema_1.SchemaBuilder(options).build();
|
|
22
24
|
let context = () => {
|
|
25
|
+
let openreader = new db_1.PoolOpenreaderContext(dialect, connection, subscriptionConnection, subscriptionPollInterval);
|
|
26
|
+
if (maxResponseNodes) {
|
|
27
|
+
openreader.responseSizeLimit = new limit_1.ResponseSizeLimit(maxResponseNodes);
|
|
28
|
+
openreader.subscriptionResponseSizeLimit = new limit_1.ResponseSizeLimit(maxResponseNodes);
|
|
29
|
+
}
|
|
30
|
+
if (subscriptionMaxResponseNodes) {
|
|
31
|
+
openreader.subscriptionResponseSizeLimit = new limit_1.ResponseSizeLimit(subscriptionMaxResponseNodes);
|
|
32
|
+
}
|
|
23
33
|
return {
|
|
24
|
-
openreader
|
|
34
|
+
openreader
|
|
25
35
|
};
|
|
26
36
|
};
|
|
27
37
|
let disposals = [];
|
|
@@ -33,15 +43,19 @@ async function serve(options) {
|
|
|
33
43
|
subscriptions: options.subscriptions,
|
|
34
44
|
log: options.log,
|
|
35
45
|
graphiqlConsole: options.graphiqlConsole,
|
|
36
|
-
maxRequestSizeBytes: options.maxRequestSizeBytes
|
|
46
|
+
maxRequestSizeBytes: options.maxRequestSizeBytes,
|
|
47
|
+
maxRootFields: options.maxRootFields
|
|
37
48
|
}), options.log);
|
|
38
49
|
}
|
|
39
50
|
exports.serve = serve;
|
|
40
51
|
async function runApollo(options) {
|
|
41
|
-
|
|
52
|
+
const { disposals, context, schema, log, maxRootFields } = options;
|
|
42
53
|
let maxRequestSizeBytes = options.maxRequestSizeBytes ?? 256 * 1024;
|
|
43
54
|
let app = (0, express_1.default)();
|
|
44
55
|
let server = http_1.default.createServer(app);
|
|
56
|
+
const execute = maxRootFields
|
|
57
|
+
? (args) => (0, execute_1.executeWithLimit)(maxRootFields, args)
|
|
58
|
+
: undefined;
|
|
45
59
|
if (options.subscriptions) {
|
|
46
60
|
let wsServer = new ws_2.WebSocketServer({
|
|
47
61
|
server,
|
|
@@ -51,6 +65,7 @@ async function runApollo(options) {
|
|
|
51
65
|
let wsServerCleanup = (0, ws_1.useServer)({
|
|
52
66
|
schema,
|
|
53
67
|
context,
|
|
68
|
+
execute,
|
|
54
69
|
onError(ctx, message, errors) {
|
|
55
70
|
if (log) {
|
|
56
71
|
// FIXME: we don't want to log client errors
|
|
@@ -70,6 +85,16 @@ async function runApollo(options) {
|
|
|
70
85
|
schema,
|
|
71
86
|
context,
|
|
72
87
|
stopOnTerminationSignals: false,
|
|
88
|
+
executor: execute && (async (req) => {
|
|
89
|
+
return execute({
|
|
90
|
+
schema,
|
|
91
|
+
document: req.document,
|
|
92
|
+
rootValue: {},
|
|
93
|
+
contextValue: req.context,
|
|
94
|
+
variableValues: req.request.variables,
|
|
95
|
+
operationName: req.operationName
|
|
96
|
+
});
|
|
97
|
+
}),
|
|
73
98
|
plugins: [
|
|
74
99
|
...options.plugins || [],
|
|
75
100
|
{
|
package/lib/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;AACA,mFAA2E;AAE3E,iEAAkD;AAClD,sDAA6B;AAC7B,4CAAmB;AAEnB,8CAA8D;AAC9D,gDAAuB;AACvB,gDAAuB;AAEvB,2BAAkC;AAElC,6BAA0C;AAG1C,8CAA+C;AAC/C,0DAAqD;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.test.d.ts","sourceRoot":"","sources":["../../src/test/limits.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const expect_1 = __importDefault(require("expect"));
|
|
7
|
+
const setup_1 = require("./setup");
|
|
8
|
+
describe('response size limits', function () {
|
|
9
|
+
(0, setup_1.useDatabase)([
|
|
10
|
+
`create table "order1" (id text primary key)`,
|
|
11
|
+
`create table item1 (id text primary key, order_id text, name text)`,
|
|
12
|
+
`create table "order2" (id text primary key)`,
|
|
13
|
+
`create table item2 (id text primary key, order_id text, name text)`,
|
|
14
|
+
`create table "order3" (id text primary key)`,
|
|
15
|
+
`create table item3 (id text primary key, order_id text, name text)`,
|
|
16
|
+
]);
|
|
17
|
+
const client = (0, setup_1.useServer)(`
|
|
18
|
+
type Order1 @entity {
|
|
19
|
+
id: ID!
|
|
20
|
+
items: [Item1!]! @derivedFrom(field: "order")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type Item1 @entity {
|
|
24
|
+
id: ID!
|
|
25
|
+
order: Order1!
|
|
26
|
+
name: String
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Order2 @entity @cardinality(value: 10) {
|
|
30
|
+
id: ID!
|
|
31
|
+
items: [Item2!]! @derivedFrom(field: "order")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type Item2 @entity {
|
|
35
|
+
id: ID!
|
|
36
|
+
order: Order2!
|
|
37
|
+
name: String
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type Order3 @entity {
|
|
41
|
+
id: ID!
|
|
42
|
+
items: [Item3!]! @derivedFrom(field: "order") @cardinality(value: 10)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type Item3 @entity {
|
|
46
|
+
id: ID!
|
|
47
|
+
order: Order3!
|
|
48
|
+
name: String @byteWeight(value: 10.0)
|
|
49
|
+
}
|
|
50
|
+
`, {
|
|
51
|
+
maxResponseNodes: 50,
|
|
52
|
+
maxRootFields: 3
|
|
53
|
+
});
|
|
54
|
+
it('unlimited requests fail', async function () {
|
|
55
|
+
let result = await client.query(`
|
|
56
|
+
query {
|
|
57
|
+
order1s {
|
|
58
|
+
id
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
`);
|
|
62
|
+
(0, expect_1.default)(result).toMatchObject({
|
|
63
|
+
data: null,
|
|
64
|
+
errors: [
|
|
65
|
+
expect_1.default.objectContaining({ message: 'response might exceed the size limit', path: ['order1s'] })
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it('limited requests work', function () {
|
|
70
|
+
return client.test(`
|
|
71
|
+
query {
|
|
72
|
+
order1s(limit: 10) {
|
|
73
|
+
items(limit: 2) {
|
|
74
|
+
id
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
`, {
|
|
79
|
+
order1s: []
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
it('entity level cardinalities are respected', function () {
|
|
83
|
+
return client.test(`
|
|
84
|
+
query {
|
|
85
|
+
order2s {
|
|
86
|
+
id
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
`, {
|
|
90
|
+
order2s: []
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
it('item cardinalities are respected', function () {
|
|
94
|
+
return client.test(`
|
|
95
|
+
query {
|
|
96
|
+
order3s(limit: 1) {
|
|
97
|
+
items { id }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
`, {
|
|
101
|
+
order3s: []
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
it('@byteWeight annotations are respected', async function () {
|
|
105
|
+
let result = await client.query(`
|
|
106
|
+
query {
|
|
107
|
+
order3s(limit: 1) {
|
|
108
|
+
items(limit: 8) { name }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`);
|
|
112
|
+
(0, expect_1.default)(result).toEqual({
|
|
113
|
+
data: null,
|
|
114
|
+
errors: [
|
|
115
|
+
expect_1.default.objectContaining({
|
|
116
|
+
message: 'response might exceed the size limit',
|
|
117
|
+
path: ['order3s']
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
await client.test(`
|
|
122
|
+
query {
|
|
123
|
+
order3s(limit: 1) {
|
|
124
|
+
items(limit: 4) { name }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`, {
|
|
128
|
+
order3s: []
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
it('id_in conditions are understood', function () {
|
|
132
|
+
return client.test(`
|
|
133
|
+
query {
|
|
134
|
+
order1s(where: {id_in: ["1", "2", "3"]}) {
|
|
135
|
+
id
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`, {
|
|
139
|
+
order1s: []
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
it('root query fields limit', async function () {
|
|
143
|
+
return client.errorTest(`
|
|
144
|
+
query {
|
|
145
|
+
a: order1ById(id: "1") { id }
|
|
146
|
+
b: order1ById(id: "1") { id }
|
|
147
|
+
c: order1ById(id: "1") { id }
|
|
148
|
+
d: order1ById(id: "1") { id }
|
|
149
|
+
}
|
|
150
|
+
`, {
|
|
151
|
+
errors: [
|
|
152
|
+
expect_1.default.objectContaining({
|
|
153
|
+
message: 'only 3 root query fields allowed, but got 4'
|
|
154
|
+
})
|
|
155
|
+
]
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=limits.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.test.js","sourceRoot":"","sources":["../../src/test/limits.test.ts"],"names":[],"mappings":";;;;;AAAA,oDAA2B;AAC3B,mCAA8C;AAG9C,QAAQ,CAAC,sBAAsB,EAAE;IAC7B,IAAA,mBAAW,EAAC;QACR,6CAA6C;QAC7C,oEAAoE;QACpE,6CAA6C;QAC7C,oEAAoE;QACpE,6CAA6C;QAC7C,oEAAoE;KACvE,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,IAAA,iBAAS,EAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiCxB,EAAE;QACC,gBAAgB,EAAE,EAAE;QACpB,aAAa,EAAE,CAAC;KACnB,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,KAAK;QAC/B,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;SAM/B,CAAC,CAAA;QACF,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YACzB,IAAI,EAAE,IAAI;YACV,MAAM,EAAE;gBACJ,gBAAM,CAAC,gBAAgB,CAAC,EAAC,OAAO,EAAE,sCAAsC,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAC,CAAC;aAChG;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uBAAuB,EAAE;QACxB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;;;;SAQlB,EAAE;YACC,OAAO,EAAE,EAAE;SACd,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE;QAC3C,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;;SAMlB,EAAE;YACC,OAAO,EAAE,EAAE;SACd,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE;QACnC,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;;SAMlB,EAAE;YACC,OAAO,EAAE,EAAE;SACd,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,KAAK;QAC7C,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;SAM/B,CAAC,CAAA;QACF,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,IAAI;YACV,MAAM,EAAE;gBACJ,gBAAM,CAAC,gBAAgB,CAAC;oBACpB,OAAO,EAAE,sCAAsC;oBAC/C,IAAI,EAAE,CAAC,SAAS,CAAC;iBACpB,CAAC;aACL;SACJ,CAAC,CAAA;QACF,MAAM,MAAM,CAAC,IAAI,CAAC;;;;;;SAMjB,EAAE;YACC,OAAO,EAAE,EAAE;SACd,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;;SAMlB,EAAE;YACC,OAAO,EAAE,EAAE;SACd,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,KAAK;QAC/B,OAAO,MAAM,CAAC,SAAS,CAAC;;;;;;;SAOvB,EAAE;YACC,MAAM,EAAE;gBACJ,gBAAM,CAAC,gBAAgB,CAAC;oBACpB,OAAO,EAAE,6CAA6C;iBACzD,CAAC;aACL;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA"}
|
package/lib/test/setup.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Client } from "gql-test-client";
|
|
2
2
|
import { ClientBase } from "pg";
|
|
3
|
+
import { ServerOptions } from '../server';
|
|
3
4
|
export declare function isCockroach(): boolean;
|
|
4
5
|
export declare const db_config: {
|
|
5
6
|
host: string;
|
|
@@ -12,5 +13,5 @@ export declare function withDatabase(block: (client: ClientBase) => Promise<void
|
|
|
12
13
|
export declare function databaseExecute(sql: string[]): Promise<void>;
|
|
13
14
|
export declare function databaseDelete(): Promise<void>;
|
|
14
15
|
export declare function useDatabase(sql: string[]): void;
|
|
15
|
-
export declare function useServer(schema: string): Client;
|
|
16
|
+
export declare function useServer(schema: string, options?: Partial<ServerOptions>): Client;
|
|
16
17
|
//# sourceMappingURL=setup.d.ts.map
|
package/lib/test/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAA;AAEtC,OAAO,EAAqB,UAAU,EAAO,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAA;AAEtC,OAAO,EAAqB,UAAU,EAAO,MAAM,IAAI,CAAA;AAEvD,OAAO,EAAQ,aAAa,EAAC,MAAM,WAAW,CAAA;AAG9C,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAGD,eAAO,MAAM,SAAS;;;;;;CAQrB,CAAA;AAGD,wBAAsB,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9F;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5D;AAGD,wBAAgB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAK9C;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAK/C;AAGD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAoBlF"}
|
package/lib/test/setup.js
CHANGED
|
@@ -51,7 +51,7 @@ function useDatabase(sql) {
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
exports.useDatabase = useDatabase;
|
|
54
|
-
function useServer(schema) {
|
|
54
|
+
function useServer(schema, options) {
|
|
55
55
|
let client = new gql_test_client_1.Client('not defined');
|
|
56
56
|
let db = new pg_1.Pool(exports.db_config);
|
|
57
57
|
let info;
|
|
@@ -61,7 +61,10 @@ function useServer(schema) {
|
|
|
61
61
|
model: (0, model_schema_1.buildModel)((0, model_schema_1.buildSchema)((0, graphql_1.parse)(schema))),
|
|
62
62
|
port: 0,
|
|
63
63
|
dialect: isCockroach() ? 'cockroach' : 'postgres',
|
|
64
|
-
subscriptions: true
|
|
64
|
+
subscriptions: true,
|
|
65
|
+
subscriptionPollInterval: 500,
|
|
66
|
+
maxRootFields: 10,
|
|
67
|
+
...options
|
|
65
68
|
});
|
|
66
69
|
client.endpoint = `http://localhost:${info.port}/graphql`;
|
|
67
70
|
});
|
package/lib/test/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":";;;AAAA,2DAAqD;AAErD,qDAAsC;AACtC,qCAA6B;AAC7B,2BAAuD;AACvD,kDAAuD;AACvD,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":";;;AAAA,2DAAqD;AAErD,qDAAsC;AACtC,qCAA6B;AAC7B,2BAAuD;AACvD,kDAAuD;AACvD,sCAA8C;AAG9C,SAAgB,WAAW;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,WAAW,CAAA;AAC7C,CAAC;AAFD,kCAEC;AAGY,QAAA,SAAS,GAAG;IACrB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ,CAAC,IAAA,6BAAa,EACxB,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CACzE,CAAC;IACF,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,WAAW;CACxB,CAAA;AAGM,KAAK,UAAU,YAAY,CAAC,KAA4C;IAC3E,IAAI,MAAM,GAAG,IAAI,WAAQ,CAAC,iBAAS,CAAC,CAAA;IACpC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;IACtB,IAAI;QACA,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;KACtB;YAAS;QACN,MAAM,MAAM,CAAC,GAAG,EAAE,CAAA;KACrB;AACL,CAAC;AARD,oCAQC;AAGD,SAAgB,eAAe,CAAC,GAAa;IACzC,OAAO,YAAY,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACjC,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;SAC7B;IACL,CAAC,CAAC,CAAA;AACN,CAAC;AAND,0CAMC;AAGD,SAAgB,cAAc;IAC1B,OAAO,YAAY,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QAC/B,MAAM,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACxD,MAAM,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;AACN,CAAC;AALD,wCAKC;AAGD,SAAgB,WAAW,CAAC,GAAa;IACrC,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,MAAM,cAAc,EAAE,CAAA;QACtB,MAAM,eAAe,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACN,CAAC;AALD,kCAKC;AAGD,SAAgB,SAAS,CAAC,MAAc,EAAE,OAAgC;IACtE,IAAI,MAAM,GAAG,IAAI,wBAAM,CAAC,aAAa,CAAC,CAAA;IACtC,IAAI,EAAE,GAAG,IAAI,SAAI,CAAC,iBAAS,CAAC,CAAA;IAC5B,IAAI,IAAiC,CAAA;IACrC,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,IAAI,GAAG,MAAM,IAAA,cAAK,EAAC;YACf,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,IAAA,yBAAU,EAAC,IAAA,0BAAW,EAAC,IAAA,eAAK,EAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;YACjD,aAAa,EAAE,IAAI;YACnB,wBAAwB,EAAE,GAAG;YAC7B,aAAa,EAAE,EAAE;YACjB,GAAG,OAAO;SACb,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,GAAG,oBAAoB,IAAI,CAAC,IAAI,UAAU,CAAA;IAC7D,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1B,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;IACrB,OAAO,MAAM,CAAA;AACjB,CAAC;AApBD,8BAoBC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ExecutionResult } from 'graphql-ws';
|
|
2
|
+
import { ExecutionArgs } from 'graphql/execution/execute';
|
|
3
|
+
import { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue';
|
|
4
|
+
export declare function executeWithLimit(maxQueries: number, args: ExecutionArgs): PromiseOrValue<ExecutionResult>;
|
|
5
|
+
//# sourceMappingURL=execute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/util/execute.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,YAAY,CAAA;AAC1C,OAAO,EAKH,aAAa,EAEhB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAC,cAAc,EAAC,MAAM,gCAAgC,CAAA;AAG7D,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,CAAC,eAAe,CAAC,CAuCzG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeWithLimit = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const execute_1 = require("graphql/execution/execute");
|
|
6
|
+
function executeWithLimit(maxQueries, args) {
|
|
7
|
+
(0, execute_1.assertValidExecutionArguments)(args.schema, args.document, args.variableValues);
|
|
8
|
+
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
|
+
}
|
|
12
|
+
let etx = xtx;
|
|
13
|
+
if (etx.operation.operation == 'query') {
|
|
14
|
+
let query = (0, graphql_1.getOperationRootType)(etx.schema, etx.operation);
|
|
15
|
+
let fields = (0, execute_1.collectFields)(etx, query, etx.operation.selectionSet, Object.create(null), Object.create(null));
|
|
16
|
+
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
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return (0, execute_1.execute)(args);
|
|
26
|
+
}
|
|
27
|
+
exports.executeWithLimit = executeWithLimit;
|
|
28
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class Limit {
|
|
2
|
+
private error;
|
|
3
|
+
private value;
|
|
4
|
+
constructor(error: Error, value: number);
|
|
5
|
+
get left(): number;
|
|
6
|
+
check(cb: (left: number) => number): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class ResponseSizeLimit extends Limit {
|
|
9
|
+
constructor(maxNodes: number);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limit.d.ts","sourceRoot":"","sources":["../../src/util/limit.ts"],"names":[],"mappings":"AAIA,qBAAa,KAAK;IACF,OAAO,CAAC,KAAK;IAAS,OAAO,CAAC,KAAK;gBAA3B,KAAK,EAAE,KAAK,EAAU,KAAK,EAAE,MAAM;IAIvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;CAS5C;AAOD,qBAAa,iBAAkB,SAAQ,KAAK;gBAC5B,QAAQ,EAAE,MAAM;CAG/B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ResponseSizeLimit = exports.Limit = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const graphql_1 = require("graphql");
|
|
9
|
+
class Limit {
|
|
10
|
+
constructor(error, value) {
|
|
11
|
+
this.error = error;
|
|
12
|
+
this.value = value;
|
|
13
|
+
(0, assert_1.default)(this.value > 0);
|
|
14
|
+
}
|
|
15
|
+
get left() {
|
|
16
|
+
return Math.max(this.value, 0);
|
|
17
|
+
}
|
|
18
|
+
check(cb) {
|
|
19
|
+
if (this.value < 0)
|
|
20
|
+
throw this.error;
|
|
21
|
+
let left = this.value - cb(this.value);
|
|
22
|
+
if (left < 0) {
|
|
23
|
+
throw this.error;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.value = left;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.Limit = Limit;
|
|
31
|
+
const SIZE_LIMIT = new graphql_1.GraphQLError('response might exceed the size limit');
|
|
32
|
+
SIZE_LIMIT.stack = undefined;
|
|
33
|
+
class ResponseSizeLimit extends Limit {
|
|
34
|
+
constructor(maxNodes) {
|
|
35
|
+
super(SIZE_LIMIT, maxNodes);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.ResponseSizeLimit = ResponseSizeLimit;
|
|
39
|
+
//# sourceMappingURL=limit.js.map
|
|
@@ -0,0 +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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subsquid/openreader",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "GraphQL server for postgres-compatible databases",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@graphql-tools/merge": "^8",
|
|
25
|
-
"@subsquid/graphiql-console": "^0.
|
|
25
|
+
"@subsquid/graphiql-console": "^0.3.0",
|
|
26
26
|
"@subsquid/logger": "^0.1.0",
|
|
27
27
|
"@subsquid/util-internal": "^0.0.1",
|
|
28
28
|
"@subsquid/util-internal-commander": "^0.0.0",
|
package/src/context.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {Dialect} from
|
|
2
|
-
import {Query} from
|
|
1
|
+
import {Dialect} from './dialect'
|
|
2
|
+
import {Query} from './sql/query'
|
|
3
|
+
import {Limit} from './util/limit'
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export interface Context {
|
|
@@ -11,4 +12,6 @@ export interface OpenreaderContext {
|
|
|
11
12
|
dialect: Dialect
|
|
12
13
|
executeQuery<T>(query: Query<T>): Promise<T>
|
|
13
14
|
subscription<T>(query: Query<T>): AsyncIterable<T>
|
|
15
|
+
responseSizeLimit?: Limit
|
|
16
|
+
subscriptionResponseSizeLimit?: Limit
|
|
14
17
|
}
|
package/src/limit.size.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {unexpectedCase} from
|
|
2
|
-
import {
|
|
1
|
+
import {unexpectedCase} from '@subsquid/util-internal'
|
|
2
|
+
import {Where} from './ir/args'
|
|
3
|
+
import {RelayConnectionRequest} from './ir/connection'
|
|
4
|
+
import {FieldRequest} from './ir/fields'
|
|
5
|
+
import {Model} from './model'
|
|
6
|
+
import {getEntity} from './model.tools'
|
|
3
7
|
|
|
4
8
|
|
|
5
|
-
export function getSize(fields: FieldRequest[]): number {
|
|
9
|
+
export function getSize(model: Model, fields: FieldRequest[]): number {
|
|
6
10
|
let total = 0
|
|
7
11
|
for (let req of fields) {
|
|
8
|
-
let size = getFieldSize(req)
|
|
12
|
+
let size = getFieldSize(model, req)
|
|
9
13
|
if (Number.isFinite(size)) {
|
|
10
14
|
total += size * req.aliases.length
|
|
11
15
|
} else {
|
|
@@ -16,7 +20,7 @@ export function getSize(fields: FieldRequest[]): number {
|
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
|
|
19
|
-
function getFieldSize(req: FieldRequest): number {
|
|
23
|
+
function getFieldSize(model: Model, req: FieldRequest): number {
|
|
20
24
|
switch(req.kind) {
|
|
21
25
|
case "scalar":
|
|
22
26
|
case "list":
|
|
@@ -27,20 +31,100 @@ function getFieldSize(req: FieldRequest): number {
|
|
|
27
31
|
case "fk":
|
|
28
32
|
case "lookup":
|
|
29
33
|
case "union":
|
|
30
|
-
return getSize(req.children) + 1
|
|
31
|
-
case "list-lookup":
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
return getSize(model, req.children) + 1
|
|
35
|
+
case "list-lookup":
|
|
36
|
+
return getEntityListSize(
|
|
37
|
+
model,
|
|
38
|
+
req.type.entity,
|
|
39
|
+
req.children,
|
|
40
|
+
Math.min(req.args?.limit ?? Infinity, req.prop.cardinality ?? Infinity),
|
|
41
|
+
req.args?.where
|
|
42
|
+
) + 1
|
|
43
|
+
default:
|
|
44
|
+
throw unexpectedCase()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
export function getEntityListSize(
|
|
50
|
+
model: Model,
|
|
51
|
+
entityName: string,
|
|
52
|
+
fields: FieldRequest[],
|
|
53
|
+
limit?: number,
|
|
54
|
+
where?: Where
|
|
55
|
+
): number {
|
|
56
|
+
let cardinality = Math.min(
|
|
57
|
+
getEntityCardinality(model, entityName),
|
|
58
|
+
limit ?? Infinity,
|
|
59
|
+
getWhereCardinality(where)
|
|
60
|
+
)
|
|
61
|
+
if (Number.isFinite(cardinality)) {
|
|
62
|
+
return cardinality * Math.max(getSize(model, fields), 1)
|
|
63
|
+
} else {
|
|
64
|
+
return Infinity
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
function getWhereCardinality(where?: Where): number {
|
|
70
|
+
if (where == null) return Infinity
|
|
71
|
+
switch(where.op) {
|
|
72
|
+
case 'AND': {
|
|
73
|
+
let min = Infinity
|
|
74
|
+
for (let co of where.args) {
|
|
75
|
+
min = Math.min(min, getWhereCardinality(co))
|
|
76
|
+
}
|
|
77
|
+
return min
|
|
78
|
+
}
|
|
79
|
+
case 'OR': {
|
|
80
|
+
if (where.args.length == 0) return Infinity
|
|
81
|
+
let max = 0
|
|
82
|
+
for (let co of where.args) {
|
|
83
|
+
max = Math.max(max, getWhereCardinality(co))
|
|
84
|
+
}
|
|
85
|
+
return max
|
|
86
|
+
}
|
|
87
|
+
case 'eq':
|
|
88
|
+
if (where.field == 'id') {
|
|
89
|
+
return 1
|
|
90
|
+
} else {
|
|
91
|
+
return Infinity
|
|
92
|
+
}
|
|
93
|
+
case 'in':
|
|
94
|
+
if (where.field == 'id') {
|
|
95
|
+
return where.values.length
|
|
35
96
|
} else {
|
|
36
97
|
return Infinity
|
|
37
98
|
}
|
|
38
|
-
}
|
|
39
99
|
default:
|
|
40
|
-
|
|
100
|
+
return Infinity
|
|
41
101
|
}
|
|
42
102
|
}
|
|
43
103
|
|
|
44
104
|
|
|
105
|
+
export function getRelaySize(model: Model, entityName: string, req: RelayConnectionRequest): number {
|
|
106
|
+
let total = 0
|
|
107
|
+
let limit = Math.min(
|
|
108
|
+
getEntityCardinality(model, entityName),
|
|
109
|
+
req.first ?? 100,
|
|
110
|
+
getWhereCardinality(req.where)
|
|
111
|
+
)
|
|
112
|
+
if (req.edgeNode) {
|
|
113
|
+
total += limit * Math.max(getSize(model, req.edgeNode), 1)
|
|
114
|
+
}
|
|
115
|
+
if (req.edgeCursor) {
|
|
116
|
+
total += limit
|
|
117
|
+
}
|
|
118
|
+
if (req.pageInfo) {
|
|
119
|
+
total += 4
|
|
120
|
+
}
|
|
121
|
+
if (req.totalCount) {
|
|
122
|
+
total += 1
|
|
123
|
+
}
|
|
124
|
+
return total
|
|
125
|
+
}
|
|
45
126
|
|
|
46
127
|
|
|
128
|
+
function getEntityCardinality(model: Model, entityName: string): number {
|
|
129
|
+
return getEntity(model, entityName).cardinality ?? Infinity
|
|
130
|
+
}
|