@subsquid/openreader 0.3.2 → 0.3.3

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 (104) hide show
  1. package/dist/db.d.ts +1 -0
  2. package/dist/db.d.ts.map +1 -0
  3. package/dist/gql/opencrud.d.ts +1 -0
  4. package/dist/gql/opencrud.d.ts.map +1 -0
  5. package/dist/gql/schema.d.ts +1 -0
  6. package/dist/gql/schema.d.ts.map +1 -0
  7. package/dist/main.d.ts +1 -0
  8. package/dist/main.d.ts.map +1 -0
  9. package/dist/model.d.ts +1 -0
  10. package/dist/model.d.ts.map +1 -0
  11. package/dist/model.tools.d.ts +1 -0
  12. package/dist/model.tools.d.ts.map +1 -0
  13. package/dist/orderBy.d.ts +1 -0
  14. package/dist/orderBy.d.ts.map +1 -0
  15. package/dist/queryBuilder.d.ts +1 -0
  16. package/dist/queryBuilder.d.ts.map +1 -0
  17. package/dist/relayConnection.d.ts +1 -0
  18. package/dist/relayConnection.d.ts.map +1 -0
  19. package/dist/requestedFields.d.ts +1 -0
  20. package/dist/requestedFields.d.ts.map +1 -0
  21. package/dist/resolver.d.ts +1 -0
  22. package/dist/resolver.d.ts.map +1 -0
  23. package/dist/scalars.d.ts +1 -0
  24. package/dist/scalars.d.ts.map +1 -0
  25. package/dist/server.d.ts +1 -0
  26. package/dist/server.d.ts.map +1 -0
  27. package/dist/test/basic.test.d.ts +2 -0
  28. package/dist/test/basic.test.d.ts.map +1 -0
  29. package/dist/test/basic.test.js +286 -0
  30. package/dist/test/basic.test.js.map +1 -0
  31. package/dist/test/connection.test.d.ts +2 -0
  32. package/dist/test/connection.test.d.ts.map +1 -0
  33. package/dist/test/connection.test.js +193 -0
  34. package/dist/test/connection.test.js.map +1 -0
  35. package/dist/test/fts.test.d.ts +2 -0
  36. package/dist/test/fts.test.d.ts.map +1 -0
  37. package/dist/test/fts.test.js +110 -0
  38. package/dist/test/fts.test.js.map +1 -0
  39. package/dist/test/lists.test.d.ts +2 -0
  40. package/dist/test/lists.test.d.ts.map +1 -0
  41. package/dist/test/lists.test.js +266 -0
  42. package/dist/test/lists.test.js.map +1 -0
  43. package/dist/test/lookup.test.d.ts +2 -0
  44. package/dist/test/lookup.test.d.ts.map +1 -0
  45. package/dist/test/lookup.test.js +109 -0
  46. package/dist/test/lookup.test.js.map +1 -0
  47. package/dist/test/scalars.test.d.ts +2 -0
  48. package/dist/test/scalars.test.d.ts.map +1 -0
  49. package/dist/test/scalars.test.js +303 -0
  50. package/dist/test/scalars.test.js.map +1 -0
  51. package/dist/test/tools.test.d.ts +2 -0
  52. package/dist/test/tools.test.d.ts.map +1 -0
  53. package/dist/test/tools.test.js +49 -0
  54. package/dist/test/tools.test.js.map +1 -0
  55. package/dist/test/typed-json.test.d.ts +2 -0
  56. package/dist/test/typed-json.test.d.ts.map +1 -0
  57. package/dist/test/typed-json.test.js +75 -0
  58. package/dist/test/typed-json.test.js.map +1 -0
  59. package/dist/test/unions.test.d.ts +2 -0
  60. package/dist/test/unions.test.d.ts.map +1 -0
  61. package/dist/test/unions.test.js +84 -0
  62. package/dist/test/unions.test.js.map +1 -0
  63. package/dist/test/util/setup.d.ts +7 -0
  64. package/dist/test/util/setup.d.ts.map +1 -0
  65. package/dist/test/util/setup.js +60 -0
  66. package/dist/test/util/setup.js.map +1 -0
  67. package/dist/test/where.test.d.ts +2 -0
  68. package/dist/test/where.test.d.ts.map +1 -0
  69. package/dist/test/where.test.js +127 -0
  70. package/dist/test/where.test.js.map +1 -0
  71. package/dist/tools.d.ts +1 -0
  72. package/dist/tools.d.ts.map +1 -0
  73. package/dist/util.d.ts +1 -0
  74. package/dist/util.d.ts.map +1 -0
  75. package/dist/where.d.ts +1 -0
  76. package/dist/where.d.ts.map +1 -0
  77. package/package.json +4 -3
  78. package/src/db.ts +83 -0
  79. package/src/gql/opencrud.ts +328 -0
  80. package/src/gql/schema.ts +337 -0
  81. package/src/main.ts +51 -0
  82. package/src/model.tools.ts +173 -0
  83. package/src/model.ts +125 -0
  84. package/src/orderBy.ts +105 -0
  85. package/src/queryBuilder.ts +785 -0
  86. package/src/relayConnection.ts +80 -0
  87. package/src/requestedFields.ts +246 -0
  88. package/src/resolver.ts +199 -0
  89. package/src/scalars.ts +247 -0
  90. package/src/server.ts +115 -0
  91. package/src/test/basic.test.ts +339 -0
  92. package/src/test/connection.test.ts +195 -0
  93. package/src/test/fts.test.ts +114 -0
  94. package/src/test/lists.test.ts +278 -0
  95. package/src/test/lookup.test.ts +111 -0
  96. package/src/test/scalars.test.ts +316 -0
  97. package/src/test/tools.test.ts +27 -0
  98. package/src/test/typed-json.test.ts +76 -0
  99. package/src/test/unions.test.ts +85 -0
  100. package/src/test/util/setup.ts +63 -0
  101. package/src/test/where.test.ts +135 -0
  102. package/src/tools.ts +33 -0
  103. package/src/util.ts +39 -0
  104. package/src/where.ts +110 -0
@@ -0,0 +1,195 @@
1
+ import {useDatabase, useServer} from "./util/setup"
2
+
3
+ describe('relay connections', function () {
4
+ useDatabase([
5
+ `create table letter (id text primary key)`,
6
+ `insert into letter (id) values ('a')`,
7
+ `insert into letter (id) values ('b')`,
8
+ `insert into letter (id) values ('c')`,
9
+ `insert into letter (id) values ('d')`,
10
+ `insert into letter (id) values ('e')`,
11
+ `insert into letter (id) values ('f')`,
12
+ `insert into letter (id) values ('g')`,
13
+ `create table empty (id text primary key)`
14
+ ])
15
+
16
+ const client = useServer(`
17
+ type Letter @entity {
18
+ id: ID!
19
+ }
20
+
21
+ type Empty @entity {
22
+ id: ID!
23
+ }
24
+ `)
25
+
26
+ it('pagination', function () {
27
+ return client.test(`
28
+ query {
29
+ page1: lettersConnection(orderBy: id_ASC, first: 3) {
30
+ ...fields
31
+ }
32
+ page2: lettersConnection(orderBy: id_ASC, first: 3, after: "3") {
33
+ ...fields
34
+ }
35
+ page3: lettersConnection(orderBy: id_ASC, first: 3, after: "6") {
36
+ ...fields
37
+ }
38
+ }
39
+ fragment fields on LettersConnection {
40
+ edges {
41
+ node { id }
42
+ cursor
43
+ }
44
+ pageInfo {
45
+ hasNextPage
46
+ hasPreviousPage
47
+ startCursor
48
+ endCursor
49
+ }
50
+ totalCount
51
+ }
52
+ `, {
53
+ page1: {
54
+ edges: [
55
+ {node: {id: 'a'}, cursor: '1'},
56
+ {node: {id: 'b'}, cursor: '2'},
57
+ {node: {id: 'c'}, cursor: '3'},
58
+ ],
59
+ pageInfo: {
60
+ hasNextPage: true,
61
+ hasPreviousPage: false,
62
+ startCursor: '1',
63
+ endCursor: '3'
64
+ },
65
+ totalCount: 7
66
+ },
67
+ page2: {
68
+ edges: [
69
+ {node: {id: 'd'}, cursor: '4'},
70
+ {node: {id: 'e'}, cursor: '5'},
71
+ {node: {id: 'f'}, cursor: '6'},
72
+ ],
73
+ pageInfo: {
74
+ hasNextPage: true,
75
+ hasPreviousPage: true,
76
+ startCursor: '4',
77
+ endCursor: '6'
78
+ },
79
+ totalCount: 7
80
+ },
81
+ page3: {
82
+ edges: [
83
+ {node: {id: 'g'}, cursor: '7'},
84
+ ],
85
+ pageInfo: {
86
+ hasNextPage: false,
87
+ hasPreviousPage: true,
88
+ startCursor: '7',
89
+ endCursor: '7'
90
+ },
91
+ totalCount: 7
92
+ }
93
+ })
94
+ })
95
+
96
+ it('pagination without nodes', function () {
97
+ return client.test(`
98
+ query {
99
+ page1: lettersConnection(orderBy: id_ASC, first: 3) {
100
+ ...fields
101
+ }
102
+ page2: lettersConnection(orderBy: id_ASC, first: 3, after: "3") {
103
+ ...fields
104
+ }
105
+ page3: lettersConnection(orderBy: id_ASC, first: 3, after: "6") {
106
+ ...fields
107
+ }
108
+ }
109
+ fragment fields on LettersConnection {
110
+ edges {
111
+ cursor
112
+ }
113
+ pageInfo {
114
+ hasNextPage
115
+ hasPreviousPage
116
+ startCursor
117
+ endCursor
118
+ }
119
+ totalCount
120
+ }
121
+ `, {
122
+ page1: {
123
+ edges: [
124
+ {cursor: '1'},
125
+ {cursor: '2'},
126
+ {cursor: '3'},
127
+ ],
128
+ pageInfo: {
129
+ hasNextPage: true,
130
+ hasPreviousPage: false,
131
+ startCursor: '1',
132
+ endCursor: '3'
133
+ },
134
+ totalCount: 7
135
+ },
136
+ page2: {
137
+ edges: [
138
+ {cursor: '4'},
139
+ {cursor: '5'},
140
+ {cursor: '6'},
141
+ ],
142
+ pageInfo: {
143
+ hasNextPage: true,
144
+ hasPreviousPage: true,
145
+ startCursor: '4',
146
+ endCursor: '6'
147
+ },
148
+ totalCount: 7
149
+ },
150
+ page3: {
151
+ edges: [
152
+ {cursor: '7'},
153
+ ],
154
+ pageInfo: {
155
+ hasNextPage: false,
156
+ hasPreviousPage: true,
157
+ startCursor: '7',
158
+ endCursor: '7'
159
+ },
160
+ totalCount: 7
161
+ }
162
+ })
163
+ })
164
+
165
+ it('request to empty table', function () {
166
+ return client.test(`
167
+ query {
168
+ emptiesConnection(orderBy: id_ASC) {
169
+ edges {
170
+ node { id }
171
+ cursor
172
+ }
173
+ pageInfo {
174
+ hasNextPage
175
+ hasPreviousPage
176
+ startCursor
177
+ endCursor
178
+ }
179
+ totalCount
180
+ }
181
+ }
182
+ `, {
183
+ emptiesConnection: {
184
+ edges: [],
185
+ pageInfo: {
186
+ hasNextPage: false,
187
+ hasPreviousPage: false,
188
+ startCursor: '',
189
+ endCursor: ''
190
+ },
191
+ totalCount: 0
192
+ }
193
+ })
194
+ })
195
+ })
@@ -0,0 +1,114 @@
1
+ import {useDatabase, useServer} from "./util/setup"
2
+
3
+ function tsvector(columns: string[]) {
4
+ return columns.map(col => `setweight(to_tsvector('english', coalesce(${col}, '')), 'A')`).join(' || ')
5
+ }
6
+
7
+ describe('full text search', function () {
8
+ useDatabase([
9
+ `create table foo (
10
+ id text primary key,
11
+ foo int,
12
+ comment text,
13
+ search_tsv tsvector generated always as ( ${tsvector(['comment'])} ) stored
14
+ )`,
15
+ `create table bar (
16
+ id text primary key,
17
+ bar text,
18
+ description text,
19
+ search_tsv tsvector generated always as ( ${tsvector(['bar', 'description'])} ) stored
20
+ )`,
21
+ `insert into foo (id, foo, comment) values ('1', 1, 'Some man greeted me with hello')`,
22
+ `insert into foo (id, foo, comment) values ('2', 2, 'Deeply buried lorem ipsum dolor sit amet, then comes baz')`,
23
+ `insert into foo (id, foo, comment) values ('3', 3, 'Lorem ipsum dolor sit amet')`,
24
+ `insert into bar (id, bar, description) values ('1', 'every bar is followed by baz. Baz!', 'Absolutely!')`,
25
+ `insert into bar (id, bar, description) values ('2', 'qux', 'Baz should be here! Baz! Baz! Baz!')`,
26
+ ])
27
+
28
+ const client = useServer(`
29
+ type Foo @entity {
30
+ id: ID!
31
+ foo: Int
32
+ comment: String @fulltext(query: "search")
33
+ }
34
+
35
+ type Bar @entity {
36
+ id: ID!
37
+ bar: String @fulltext(query: "search")
38
+ description: String @fulltext(query: "search")
39
+ }
40
+ `)
41
+
42
+ it('finds "hello" across entities in Foo.comment and highlights it', function () {
43
+ return client.test(`
44
+ query {
45
+ search(text: "hello") {
46
+ item {
47
+ ... on Foo { id, foo }
48
+ }
49
+ highlight
50
+ }
51
+ }
52
+ `, {
53
+ search: [{
54
+ item: {id: '1', foo: 1},
55
+ highlight: 'Some man greeted me with <b>hello</b>'
56
+ }]
57
+ })
58
+ })
59
+
60
+ it('finds "absolute" across entities in Bar.description and highlights it', function () {
61
+ return client.test(`
62
+ query {
63
+ search(text: "absolute") {
64
+ item {
65
+ ... on Bar { id, bar }
66
+ }
67
+ highlight
68
+ }
69
+ }
70
+ `, {
71
+ search: [{
72
+ item: {id: '1', bar: 'every bar is followed by baz. Baz!'},
73
+ highlight: 'every bar is followed by baz. Baz!\n\n<b>Absolutely</b>!'
74
+ }]
75
+ })
76
+ })
77
+
78
+ it('finds and arranges "Baz"', function () {
79
+ return client.test(`
80
+ query {
81
+ search(text: "baz") {
82
+ item {
83
+ ... on Foo { id foo }
84
+ ... on Bar { id bar }
85
+ }
86
+ }
87
+ }
88
+ `, {
89
+ search: [
90
+ {item: {id: '2', bar: 'qux'}},
91
+ {item: {id: '1', bar: 'every bar is followed by baz. Baz!'}},
92
+ {item: {id: '2', foo: 2}},
93
+ ]
94
+ })
95
+ })
96
+
97
+ it('supports where conditions', function () {
98
+ return client.test(`
99
+ query {
100
+ search(text: "baz" whereBar: {bar_eq: "qux"}) {
101
+ item {
102
+ ... on Foo { id foo }
103
+ ... on Bar { id bar }
104
+ }
105
+ }
106
+ }
107
+ `, {
108
+ search: [
109
+ {item: {id: '2', bar: 'qux'}},
110
+ {item: {id: '2', foo: 2}}
111
+ ]
112
+ })
113
+ })
114
+ })
@@ -0,0 +1,278 @@
1
+ import {useDatabase, useServer} from "./util/setup"
2
+
3
+
4
+ describe('lists', function () {
5
+ useDatabase([
6
+ `create table lists (
7
+ id text primary key,
8
+ int_array integer[],
9
+ bigint_array numeric[],
10
+ enum_array text[],
11
+ datetime_array timestamptz[],
12
+ bytes_array bytea[],
13
+ list_of_list_of_int jsonb,
14
+ list_of_json_objects jsonb
15
+ )`,
16
+ `insert into lists (id, int_array) values ('1', '{1, 2, 3}')`,
17
+ `insert into lists (id, int_array) values ('2', '{4, 5, 6}')`,
18
+ `insert into lists (id, int_array) values ('20', '{7, 8}')`,
19
+ `insert into lists (id, bigint_array) values ('3', '{1000000000000000000000000000, 2000000000000000000000000000}')`,
20
+ `insert into lists (id, bigint_array) values ('4', '{3000000000000000000000000000, 4000000000000000000000000000}')`,
21
+ `insert into lists (id, list_of_list_of_int) values ('5', '[[1, 2], [3, 4], [5]]'::jsonb)`,
22
+ `insert into lists (id, list_of_json_objects) values ('6', '[{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}]'::jsonb)`,
23
+ `insert into lists (id, datetime_array) values ('7', array['2020-01-01T00:00:00Z', '2021-01-01T00:00:00Z']::timestamptz[])`,
24
+ `insert into lists (id, datetime_array) values ('70', array['2020-01-01T00:00:00Z', '2022-01-01T00:00:00Z']::timestamptz[])`,
25
+ `insert into lists (id, bytes_array) values ('8', array['hello', 'world']::bytea[])`,
26
+ `insert into lists (id, bytes_array) values ('9', array['hello', 'big', 'world']::bytea[])`,
27
+ `insert into lists (id, enum_array) values ('10', array['A', 'B', 'C'])`,
28
+ `insert into lists (id, enum_array) values ('11', array['C', 'D'])`,
29
+ `insert into lists (id, enum_array) values ('12', array['A', 'D'])`,
30
+ ])
31
+
32
+ const client = useServer(`
33
+ type Lists @entity {
34
+ intArray: [Int!]
35
+ enumArray: [Enum!]
36
+ bigintArray: [BigInt!]
37
+ datetimeArray: [DateTime!]
38
+ bytesArray: [Bytes!]
39
+ listOfListOfInt: [[Int]]
40
+ listOfJsonObjects: [Foo!]
41
+ }
42
+
43
+ enum Enum {
44
+ A B C D E F
45
+ }
46
+
47
+ type Foo {
48
+ foo: Int
49
+ bar: Int
50
+ }
51
+ `)
52
+
53
+ describe('integer arrays', function () {
54
+ it('outputs correctly', function () {
55
+ return client.test(`
56
+ query {
57
+ lists(where: {id_in: ["1", "2"]} orderBy: id_ASC) {
58
+ intArray
59
+ }
60
+ }
61
+ `, {
62
+ lists: [
63
+ {intArray: [1, 2, 3]},
64
+ {intArray: [4, 5, 6]}
65
+ ]
66
+ })
67
+ })
68
+
69
+ it('support where conditions', function () {
70
+ return client.test(`
71
+ query {
72
+ all: lists(where: {intArray_containsAll: [1, 3]} orderBy: id_ASC) {
73
+ id
74
+ }
75
+ any: lists(where: {intArray_containsAny: [4, 7]} orderBy: id_ASC) {
76
+ id
77
+ }
78
+ none: lists(where: {intArray_containsNone: 5} orderBy: id_ASC) {
79
+ id
80
+ }
81
+ nothing: lists(where: {intArray_containsNone: [1, 4, 7]} orderBy: id_ASC) {
82
+ id
83
+ }
84
+ }
85
+ `, {
86
+ all: [{id: '1'}],
87
+ any: [{id: '2'}, {id: '20'}],
88
+ none: [{id: '1'}, {id: '20'}],
89
+ nothing: []
90
+ })
91
+ })
92
+ })
93
+
94
+ describe('enum arrays', function () {
95
+ it('outputs correctly', function () {
96
+ return client.test(`
97
+ query {
98
+ lists(where: {id_in: ["10", "11", "12"]} orderBy: id_ASC) {
99
+ id
100
+ enumArray
101
+ }
102
+ }
103
+ `, {
104
+ lists: [
105
+ {id: '10', enumArray: ['A', 'B', 'C']},
106
+ {id: '11', enumArray: ['C', 'D']},
107
+ {id: '12', enumArray: ['A', 'D']}
108
+ ]
109
+ })
110
+ })
111
+
112
+ it('supports where conditions', function () {
113
+ return client.test(`
114
+ query {
115
+ all : lists(where: {enumArray_containsAll: [A, B]} orderBy: id_ASC) { id }
116
+ any : lists(where: {enumArray_containsAny: D} orderBy: id_ASC) { id }
117
+ none: lists(where: {enumArray_containsNone: A} orderBy: id_ASC) { id }
118
+ }
119
+ `, {
120
+ all: [{id: '10'}],
121
+ any: [{id: '11'}, {id: '12'}],
122
+ none: [{id: '11'}],
123
+ })
124
+ })
125
+ })
126
+
127
+ describe('big integer arrays', function () {
128
+ it('outputs correctly', function () {
129
+ return client.test(`
130
+ query {
131
+ lists(where: {id_in: ["3", "4"]} orderBy: id_ASC) {
132
+ bigintArray
133
+ }
134
+ }
135
+ `, {
136
+ lists: [
137
+ {bigintArray: ['1000000000000000000000000000', '2000000000000000000000000000']},
138
+ {bigintArray: ['3000000000000000000000000000', '4000000000000000000000000000']}
139
+ ]
140
+ })
141
+ })
142
+
143
+ it('supports where conditions', function () {
144
+ return client.test(`
145
+ query {
146
+ all: lists(where: {bigintArray_containsAll: 1000000000000000000000000000} orderBy: id_ASC) {
147
+ id
148
+ }
149
+ any: lists(where: {bigintArray_containsAny: [3000000000000000000000000000, 2000000000000000000000000000]} orderBy: id_ASC) {
150
+ id
151
+ }
152
+ none: lists(where: {bigintArray_containsNone: "2000000000000000000000000000"} orderBy: id_ASC) {
153
+ id
154
+ }
155
+ }
156
+ `, {
157
+ all: [{id: '3'}],
158
+ any: [{id: '3'}, {id: '4'}],
159
+ none: [{id: '4'}]
160
+ })
161
+ })
162
+ })
163
+
164
+ describe('date-time arrays', function () {
165
+ it('outputs correctly', function () {
166
+ return client.test(`
167
+ query {
168
+ lists(where: {id_eq: "7"}) {
169
+ datetimeArray
170
+ }
171
+ }
172
+ `, {
173
+ lists: [{
174
+ datetimeArray: [
175
+ '2020-01-01T00:00:00.000Z',
176
+ '2021-01-01T00:00:00.000Z'
177
+ ]
178
+ }]
179
+ })
180
+ })
181
+
182
+ it('supports where conditions', function () {
183
+ return client.test(`
184
+ query {
185
+ all: lists(where: {datetimeArray_containsAll: ["2020-01-01T00:00:00Z", "2022-01-01T00:00:00Z"]} orderBy: id_ASC) {
186
+ id
187
+ }
188
+ any: lists(where: {datetimeArray_containsAny: ["2020-01-01T00:00:00Z", "2022-01-01T00:00:00Z"]} orderBy: id_ASC) {
189
+ id
190
+ }
191
+ none: lists(where: {datetimeArray_containsNone: ["2024-01-01T00:00:00Z", "2022-01-01T00:00:00Z"]} orderBy: id_ASC) {
192
+ id
193
+ }
194
+ }
195
+ `, {
196
+ all: [{id: '70'}],
197
+ any: [{id: '7'}, {id: '70'}],
198
+ none: [{id: '7'}]
199
+ })
200
+ })
201
+ })
202
+
203
+ describe('bytes array', function () {
204
+ it('outputs correctly', function () {
205
+ return client.test(`
206
+ query {
207
+ lists(where: {id_eq: "8"}) {
208
+ bytesArray
209
+ }
210
+ }
211
+ `, {
212
+ lists: [{
213
+ bytesArray: [
214
+ '0x68656c6c6f',
215
+ '0x776f726c64'
216
+ ]
217
+ }]
218
+ })
219
+ })
220
+
221
+ it('supports where conditions', function () {
222
+ return client.test(`
223
+ query {
224
+ all: lists(where: {bytesArray_containsAll: ["0x68656c6c6f", "0x626967"]} orderBy: id_ASC) {
225
+ id
226
+ }
227
+ any: lists(where: {bytesArray_containsAny: "0x776f726c64"} orderBy: id_ASC) {
228
+ id
229
+ }
230
+ none: lists(where: {bytesArray_containsNone: ["0x626967", "0xaa"]} orderBy: id_ASC) {
231
+ id
232
+ }
233
+ }
234
+ `, {
235
+ all: [{id: '9'}],
236
+ any: [{id: '8'}, {id: '9'}],
237
+ none: [{id: '8'}],
238
+ })
239
+ })
240
+ })
241
+
242
+ describe('json lists', function () {
243
+ it('outputs list of list of integers', function () {
244
+ return client.test(`
245
+ query {
246
+ lists(where: {id_eq: "5"}) {
247
+ listOfListOfInt
248
+ }
249
+ }
250
+ `, {
251
+ lists: [
252
+ {listOfListOfInt: [[1, 2], [3, 4], [5]]}
253
+ ]
254
+ })
255
+ })
256
+
257
+ it('outputs list of json objects', function () {
258
+ return client.test(`
259
+ query {
260
+ lists(where: {id_eq: "6"}) {
261
+ listOfJsonObjects {
262
+ foo
263
+ }
264
+ }
265
+ }
266
+ `, {
267
+ lists: [
268
+ {
269
+ listOfJsonObjects: [
270
+ {foo: 1},
271
+ {foo: 3}
272
+ ]
273
+ }
274
+ ]
275
+ })
276
+ })
277
+ })
278
+ })
@@ -0,0 +1,111 @@
1
+ import {useDatabase, useServer} from "./util/setup"
2
+
3
+ describe('lookup test', function () {
4
+ useDatabase([
5
+ `create table issue (id text primary key)`,
6
+ `create table issue_payment (id text primary key, issue_id text not null unique, amount numeric)`,
7
+ `create table issue_cancellation (id text primary key, issue_id text not null unique, height int)`,
8
+ `insert into issue (id) values ('1')`,
9
+ `insert into issue (id) values ('2')`,
10
+ `insert into issue (id) values ('3')`,
11
+ `insert into issue_payment (id, issue_id, amount) values ('1', '1', 2)`,
12
+ `insert into issue_payment (id, issue_id, amount) values ('2', '2', 1)`,
13
+ `insert into issue_cancellation (id, issue_id, height) values ('3', '3', 10)`,
14
+ ])
15
+
16
+ const client = useServer(`
17
+ type Issue @entity {
18
+ id: ID!
19
+ payment: IssuePayment @derivedFrom(field: "issue")
20
+ cancellation: IssueCancellation @derivedFrom(field: "issue")
21
+ }
22
+
23
+ type IssuePayment @entity {
24
+ id: ID!
25
+ issue: Issue! @unique
26
+ amount: Int!
27
+ }
28
+
29
+ type IssueCancellation @entity {
30
+ id: ID!
31
+ issue: Issue! @unique
32
+ height: Int!
33
+ }
34
+ `)
35
+
36
+ it('fetches correctly', function () {
37
+ return client.test(`
38
+ query {
39
+ issues(orderBy: [id_ASC]) {
40
+ id
41
+ payment {
42
+ amount
43
+ }
44
+ cancellation {
45
+ height
46
+ issue {
47
+ cancellation {
48
+ id
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ `, {
55
+ issues: [
56
+ {
57
+ id: '1',
58
+ payment: {amount: 2},
59
+ cancellation: null
60
+ },
61
+ {
62
+ id: '2',
63
+ payment: {amount: 1},
64
+ cancellation: null
65
+ },
66
+ {
67
+ id: '3',
68
+ payment: null,
69
+ cancellation: {
70
+ height: 10,
71
+ issue: {
72
+ cancellation: {
73
+ id: '3'
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ]
79
+ })
80
+ })
81
+
82
+ it('supports sorting on lookup fields', function () {
83
+ return client.test(`
84
+ query {
85
+ issues(orderBy: [payment_amount_DESC]) {
86
+ id
87
+ }
88
+ }
89
+ `, {
90
+ issues: [
91
+ {id: '3'},
92
+ {id: '1'},
93
+ {id: '2'}
94
+ ]
95
+ })
96
+ })
97
+
98
+ it('supports where conditions', function () {
99
+ return client.test(`
100
+ query {
101
+ issues(where: {payment: {amount_gt: 1}}) {
102
+ id
103
+ }
104
+ }
105
+ `, {
106
+ issues: [
107
+ {id: '1'}
108
+ ]
109
+ })
110
+ })
111
+ })