@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.
Files changed (48) hide show
  1. package/lib/context.d.ts +5 -2
  2. package/lib/context.d.ts.map +1 -1
  3. package/lib/limit.size.d.ts +7 -2
  4. package/lib/limit.size.d.ts.map +1 -1
  5. package/lib/limit.size.js +74 -11
  6. package/lib/limit.size.js.map +1 -1
  7. package/lib/main.js +7 -1
  8. package/lib/main.js.map +1 -1
  9. package/lib/model.d.ts +1 -0
  10. package/lib/model.d.ts.map +1 -1
  11. package/lib/model.schema.d.ts.map +1 -1
  12. package/lib/model.schema.js +21 -4
  13. package/lib/model.schema.js.map +1 -1
  14. package/lib/opencrud/schema.d.ts.map +1 -1
  15. package/lib/opencrud/schema.js +12 -7
  16. package/lib/opencrud/schema.js.map +1 -1
  17. package/lib/server.d.ts +16 -12
  18. package/lib/server.d.ts.map +1 -1
  19. package/lib/server.js +29 -4
  20. package/lib/server.js.map +1 -1
  21. package/lib/test/limits.test.d.ts +2 -0
  22. package/lib/test/limits.test.d.ts.map +1 -0
  23. package/lib/test/limits.test.js +159 -0
  24. package/lib/test/limits.test.js.map +1 -0
  25. package/lib/test/setup.d.ts +2 -1
  26. package/lib/test/setup.d.ts.map +1 -1
  27. package/lib/test/setup.js +5 -2
  28. package/lib/test/setup.js.map +1 -1
  29. package/lib/util/execute.d.ts +5 -0
  30. package/lib/util/execute.d.ts.map +1 -0
  31. package/lib/util/execute.js +28 -0
  32. package/lib/util/execute.js.map +1 -0
  33. package/lib/util/limit.d.ts +11 -0
  34. package/lib/util/limit.d.ts.map +1 -0
  35. package/lib/util/limit.js +39 -0
  36. package/lib/util/limit.js.map +1 -0
  37. package/package.json +2 -2
  38. package/src/context.ts +5 -2
  39. package/src/limit.size.ts +96 -12
  40. package/src/main.ts +19 -10
  41. package/src/model.schema.ts +24 -4
  42. package/src/model.ts +1 -0
  43. package/src/opencrud/schema.ts +14 -7
  44. package/src/server.ts +66 -26
  45. package/src/test/limits.test.ts +163 -0
  46. package/src/test/setup.ts +6 -3
  47. package/src/util/execute.ts +53 -0
  48. 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: new db_1.PoolOpenreaderContext(dialect, connection, subscriptionConnection, subscriptionPollInterval)
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
- let { disposals, context, schema, log } = options;
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":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=limits.test.d.ts.map
@@ -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"}
@@ -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
@@ -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;AAKvD,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,GAAG,MAAM,CAiBhD"}
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
  });
@@ -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,sCAA+B;AAG/B,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;IACpC,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;SACtB,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;AAjBD,8BAiBC"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"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"}
@@ -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.0.0",
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.2.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 "./dialect"
2
- import {Query} from "./sql/query"
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 "@subsquid/util-internal"
2
- import {FieldRequest} from "./ir/fields"
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
- let limit = Math.min(req.args?.limit ?? Infinity, req.prop.cardinality ?? Infinity)
33
- if (Number.isFinite(limit)) {
34
- return limit * Math.max(getSize(req.children), 1)
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
- throw unexpectedCase()
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
+ }