@subsquid/openreader 0.2.0 → 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 (128) hide show
  1. package/README.md +2 -15
  2. package/bin/main.js +2 -0
  3. package/dist/db.d.ts +28 -0
  4. package/dist/db.d.ts.map +1 -0
  5. package/dist/db.js +69 -0
  6. package/dist/db.js.map +1 -0
  7. package/dist/gql/opencrud.d.ts +1 -0
  8. package/dist/gql/opencrud.d.ts.map +1 -0
  9. package/dist/gql/opencrud.js +10 -9
  10. package/dist/gql/opencrud.js.map +1 -1
  11. package/dist/gql/schema.d.ts +1 -0
  12. package/dist/gql/schema.d.ts.map +1 -0
  13. package/dist/main.d.ts +2 -3
  14. package/dist/main.d.ts.map +1 -0
  15. package/dist/main.js +6 -30
  16. package/dist/main.js.map +1 -1
  17. package/dist/model.d.ts +1 -0
  18. package/dist/model.d.ts.map +1 -0
  19. package/dist/model.tools.d.ts +1 -0
  20. package/dist/model.tools.d.ts.map +1 -0
  21. package/dist/orderBy.d.ts +1 -0
  22. package/dist/orderBy.d.ts.map +1 -0
  23. package/dist/queryBuilder.d.ts +3 -2
  24. package/dist/queryBuilder.d.ts.map +1 -0
  25. package/dist/queryBuilder.js +28 -27
  26. package/dist/queryBuilder.js.map +1 -1
  27. package/dist/relayConnection.d.ts +1 -0
  28. package/dist/relayConnection.d.ts.map +1 -0
  29. package/dist/requestedFields.d.ts +1 -0
  30. package/dist/requestedFields.d.ts.map +1 -0
  31. package/dist/requestedFields.js +3 -3
  32. package/dist/requestedFields.js.map +1 -1
  33. package/dist/resolver.d.ts +3 -2
  34. package/dist/resolver.d.ts.map +1 -0
  35. package/dist/resolver.js +12 -11
  36. package/dist/resolver.js.map +1 -1
  37. package/dist/scalars.d.ts +2 -2
  38. package/dist/scalars.d.ts.map +1 -0
  39. package/dist/scalars.js +6 -2
  40. package/dist/scalars.js.map +1 -1
  41. package/dist/server.d.ts +5 -11
  42. package/dist/server.d.ts.map +1 -0
  43. package/dist/server.js +13 -31
  44. package/dist/server.js.map +1 -1
  45. package/dist/test/basic.test.d.ts +2 -0
  46. package/dist/test/basic.test.d.ts.map +1 -0
  47. package/dist/test/basic.test.js +286 -0
  48. package/dist/test/basic.test.js.map +1 -0
  49. package/dist/test/connection.test.d.ts +2 -0
  50. package/dist/test/connection.test.d.ts.map +1 -0
  51. package/dist/test/connection.test.js +193 -0
  52. package/dist/test/connection.test.js.map +1 -0
  53. package/dist/test/fts.test.d.ts +2 -0
  54. package/dist/test/fts.test.d.ts.map +1 -0
  55. package/dist/test/fts.test.js +110 -0
  56. package/dist/test/fts.test.js.map +1 -0
  57. package/dist/test/lists.test.d.ts +2 -0
  58. package/dist/test/lists.test.d.ts.map +1 -0
  59. package/dist/test/lists.test.js +266 -0
  60. package/dist/test/lists.test.js.map +1 -0
  61. package/dist/test/lookup.test.d.ts +2 -0
  62. package/dist/test/lookup.test.d.ts.map +1 -0
  63. package/dist/test/lookup.test.js +109 -0
  64. package/dist/test/lookup.test.js.map +1 -0
  65. package/dist/test/scalars.test.d.ts +2 -0
  66. package/dist/test/scalars.test.d.ts.map +1 -0
  67. package/dist/test/scalars.test.js +303 -0
  68. package/dist/test/scalars.test.js.map +1 -0
  69. package/dist/test/tools.test.d.ts +2 -0
  70. package/dist/test/tools.test.d.ts.map +1 -0
  71. package/dist/test/tools.test.js +49 -0
  72. package/dist/test/tools.test.js.map +1 -0
  73. package/dist/test/typed-json.test.d.ts +2 -0
  74. package/dist/test/typed-json.test.d.ts.map +1 -0
  75. package/dist/test/typed-json.test.js +75 -0
  76. package/dist/test/typed-json.test.js.map +1 -0
  77. package/dist/test/unions.test.d.ts +2 -0
  78. package/dist/test/unions.test.d.ts.map +1 -0
  79. package/dist/test/unions.test.js +84 -0
  80. package/dist/test/unions.test.js.map +1 -0
  81. package/dist/test/util/setup.d.ts +7 -0
  82. package/dist/test/util/setup.d.ts.map +1 -0
  83. package/dist/test/util/setup.js +60 -0
  84. package/dist/test/util/setup.js.map +1 -0
  85. package/dist/test/where.test.d.ts +2 -0
  86. package/dist/test/where.test.d.ts.map +1 -0
  87. package/dist/test/where.test.js +127 -0
  88. package/dist/test/where.test.js.map +1 -0
  89. package/dist/tools.d.ts +1 -0
  90. package/dist/tools.d.ts.map +1 -0
  91. package/dist/util.d.ts +1 -13
  92. package/dist/util.d.ts.map +1 -0
  93. package/dist/util.js +6 -79
  94. package/dist/util.js.map +1 -1
  95. package/dist/where.d.ts +1 -0
  96. package/dist/where.d.ts.map +1 -0
  97. package/package.json +26 -20
  98. package/src/db.ts +83 -0
  99. package/src/gql/opencrud.ts +328 -0
  100. package/src/gql/schema.ts +337 -0
  101. package/src/main.ts +51 -0
  102. package/src/model.tools.ts +173 -0
  103. package/src/model.ts +125 -0
  104. package/src/orderBy.ts +105 -0
  105. package/src/queryBuilder.ts +785 -0
  106. package/src/relayConnection.ts +80 -0
  107. package/src/requestedFields.ts +246 -0
  108. package/src/resolver.ts +199 -0
  109. package/src/scalars.ts +247 -0
  110. package/src/server.ts +115 -0
  111. package/src/test/basic.test.ts +339 -0
  112. package/src/test/connection.test.ts +195 -0
  113. package/src/test/fts.test.ts +114 -0
  114. package/src/test/lists.test.ts +278 -0
  115. package/src/test/lookup.test.ts +111 -0
  116. package/src/test/scalars.test.ts +316 -0
  117. package/src/test/tools.test.ts +27 -0
  118. package/src/test/typed-json.test.ts +76 -0
  119. package/src/test/unions.test.ts +85 -0
  120. package/src/test/util/setup.ts +63 -0
  121. package/src/test/where.test.ts +135 -0
  122. package/src/tools.ts +33 -0
  123. package/src/util.ts +39 -0
  124. package/src/where.ts +110 -0
  125. package/CHANGELOG.md +0 -16
  126. package/dist/transaction.d.ts +0 -10
  127. package/dist/transaction.js +0 -47
  128. package/dist/transaction.js.map +0 -1
@@ -0,0 +1,135 @@
1
+ import {useDatabase, useServer} from "./util/setup"
2
+
3
+ describe('AND, OR on entity filters', function () {
4
+ useDatabase([
5
+ `create table item (id text primary key, a int, b int)`,
6
+ `insert into item (id, a, b) values ('1', 1, 1)`,
7
+ `insert into item (id, a, b) values ('2', 2, 2)`,
8
+ `insert into item (id, a, b) values ('3', 3, 2)`,
9
+ `insert into item (id, a, b) values ('4', 4, 4)`,
10
+ `insert into item (id, a, b) values ('5', 5, 4)`,
11
+ `insert into item (id, a, b) values ('6', 5, 6)`,
12
+ ])
13
+
14
+ const client = useServer(`
15
+ type Item @entity {
16
+ id: ID!
17
+ a: Int
18
+ b: Int
19
+ }
20
+ `)
21
+
22
+ it('{c, and: {c}}', function () {
23
+ return client.test(`
24
+ query {
25
+ items(where: {a_eq: 1, AND: {b_eq: 1}} orderBy: id_ASC) { id }
26
+ }
27
+ `, {
28
+ items: [
29
+ {id: '1'}
30
+ ]
31
+ })
32
+ })
33
+
34
+ it('{and: {and: {c}, c}}', function () {
35
+ return client.test(`
36
+ query {
37
+ items(where: {AND: {b_eq: 2, AND: {a_eq: 3}}} orderBy: id_ASC) { id }
38
+ }
39
+ `, {
40
+ items: [
41
+ {id: '3'}
42
+ ]
43
+ })
44
+ })
45
+
46
+ it('{and: [{c}, {c}]}', function () {
47
+ return client.test(`
48
+ query {
49
+ items(where: {AND: [{a_eq: 2}, {b_eq: 2}]} orderBy: id_ASC) { id }
50
+ }
51
+ `, {
52
+ items: [
53
+ {id: '2'}
54
+ ]
55
+ })
56
+ })
57
+
58
+ it('{c, {or: {c}}}', function () {
59
+ return client.test(`
60
+ query {
61
+ items(where: {a_eq: 1, OR: {a_eq: 2}} orderBy: id_ASC) { id }
62
+ }
63
+ `, {
64
+ items: [
65
+ {id: '1'},
66
+ {id: '2'}
67
+ ]
68
+ })
69
+ })
70
+
71
+ it('{or: [{c}, {c}]}', function () {
72
+ return client.test(`
73
+ query {
74
+ items(where: {OR: [{a_eq: 2}, {a_eq: 3}]} orderBy: id_ASC) { id }
75
+ }
76
+ `, {
77
+ items: [
78
+ {id: '2'},
79
+ {id: '3'}
80
+ ]
81
+ })
82
+ })
83
+
84
+ it('{or: {or: {c}, c}}', function () {
85
+ return client.test(`
86
+ query {
87
+ items(where: {OR: {a_eq: 1, OR: {b_eq: 2}}} orderBy: id_ASC) { id }
88
+ }
89
+ `, {
90
+ items: [
91
+ {id: '1'},
92
+ {id: '2'},
93
+ {id: '3'}
94
+ ]
95
+ })
96
+ })
97
+
98
+ it('{and: [{or: {c}, c}, {or: {c}, c}]}', function () {
99
+ return client.test(`
100
+ query {
101
+ items(where: {AND: [{OR: {a_eq: 5}, a_eq: 4}, {OR: {b_eq: 2}, b_eq: 4}]} orderBy: id_ASC) { id }
102
+ }
103
+ `, {
104
+ items: [
105
+ {id: '4'},
106
+ {id: '5'}
107
+ ]
108
+ })
109
+ })
110
+
111
+ it('{c, and: {c}, or: {c}}', function () {
112
+ return client.test(`
113
+ query {
114
+ items(where: { a_eq: 4, AND: {b_eq: 4}, OR: {b_eq: 6} } orderBy: id_ASC) { id }
115
+ }
116
+ `, {
117
+ items: [
118
+ {id: '4'},
119
+ {id: '6'}
120
+ ]
121
+ })
122
+ })
123
+
124
+ it('handles empty wheres', function () {
125
+ return client.test(`
126
+ query {
127
+ items(where: { a_eq: 4, AND: { OR: {}, AND: {} }, OR: { OR: {AND: {} } } } orderBy: id_ASC) { id }
128
+ }
129
+ `, {
130
+ items: [
131
+ {id: '4'}
132
+ ]
133
+ })
134
+ })
135
+ })
package/src/tools.ts ADDED
@@ -0,0 +1,33 @@
1
+ import {mergeTypeDefs} from "@graphql-tools/merge"
2
+ import * as fs from "fs"
3
+ import * as path from "path"
4
+ import {parse, Source} from "graphql"
5
+ import {buildModel, buildSchema} from "./gql/schema"
6
+ import type {Model} from "./model"
7
+
8
+
9
+ export function loadModel(schemaFile: string): Model {
10
+ let files: string[] = []
11
+ if (fs.statSync(schemaFile).isDirectory()) {
12
+ fs.readdirSync(schemaFile, {withFileTypes: true}).forEach(item => {
13
+ if (item.isFile() && (item.name.endsWith('.graphql') || item.name.endsWith('.gql'))) {
14
+ files.push(path.join(schemaFile, item.name))
15
+ }
16
+ })
17
+ } else {
18
+ files.push(schemaFile)
19
+ }
20
+
21
+ let docs = files.map(f => {
22
+ let src = new Source(
23
+ fs.readFileSync(f, 'utf-8'),
24
+ f
25
+ )
26
+ return parse(src)
27
+ })
28
+
29
+ if (docs.length == 0) return {}
30
+ let doc = docs.length == 1 ? docs[0] : mergeTypeDefs(docs)
31
+ let schema = buildSchema(doc)
32
+ return buildModel(schema)
33
+ }
package/src/util.ts ADDED
@@ -0,0 +1,39 @@
1
+ import {toCamelCase, toPlural, toSnakeCase} from "@subsquid/util"
2
+ import assert from "assert"
3
+
4
+
5
+ export function toQueryListField(entityName: string): string {
6
+ return toPlural(toCamelCase(entityName))
7
+ }
8
+
9
+
10
+ export function toColumn(gqlFieldName: string): string {
11
+ return toSnakeCase(gqlFieldName)
12
+ }
13
+
14
+
15
+ export function toFkColumn(gqlFieldName: string): string {
16
+ return toSnakeCase(gqlFieldName) + '_id'
17
+ }
18
+
19
+
20
+ export function toTable(entityName: string): string {
21
+ return toSnakeCase(entityName)
22
+ }
23
+
24
+
25
+ export function ensureArray<T>(item: T | T[]): T[] {
26
+ return Array.isArray(item) ? item : [item]
27
+ }
28
+
29
+
30
+ export function unsupportedCase(value: string): Error {
31
+ return new Error(`Unsupported case: ${value}`)
32
+ }
33
+
34
+
35
+ export function toInt(val: number | string): number {
36
+ let i = parseInt(val as string)
37
+ assert(!isNaN(i) && isFinite(i))
38
+ return i
39
+ }
package/src/where.ts ADDED
@@ -0,0 +1,110 @@
1
+
2
+ export type WhereOp =
3
+ '-' | // no operator
4
+ 'eq' | 'not_eq' |
5
+ 'gt' |
6
+ 'gte' |
7
+ 'lt' |
8
+ 'lte' |
9
+ 'in' | 'not_in' |
10
+ 'contains' | 'not_contains' |
11
+ 'startsWith' | 'not_startsWith' |
12
+ 'endsWith' | 'not_endsWith' |
13
+ 'containsAll' |
14
+ 'containsAny' |
15
+ 'containsNone' |
16
+ 'some' |
17
+ 'every' |
18
+ 'none'
19
+
20
+
21
+ const ENDINGS = [
22
+ 'eq',
23
+ 'not_eq',
24
+ 'gt',
25
+ 'gte',
26
+ 'lt',
27
+ 'lte',
28
+ 'in',
29
+ 'not_in',
30
+ 'contains',
31
+ 'not_contains',
32
+ 'startsWith',
33
+ 'not_startsWith',
34
+ 'endsWith',
35
+ 'not_endsWith',
36
+ 'containsAll',
37
+ 'containsAny',
38
+ 'containsNone',
39
+ 'some',
40
+ 'every',
41
+ 'none'
42
+ ].sort((a, b) => b.length - a.length).map(e => '_' + e)
43
+
44
+
45
+ function parseEnding(field: string): string {
46
+ for (let i = 0; i < ENDINGS.length; i++) {
47
+ if (field.endsWith(ENDINGS[i])) return ENDINGS[i].slice(1)
48
+ }
49
+ return ''
50
+ }
51
+
52
+
53
+ export function parseWhereField(field: string): {op: WhereOp, field: string} {
54
+ let ending = parseEnding(field)
55
+ if (!ending) return {op: '-', field}
56
+ let fieldName = field.slice(0, -(ending.length + 1))
57
+ return {
58
+ op: ending as WhereOp,
59
+ field: fieldName
60
+ }
61
+ }
62
+
63
+
64
+ export function hasConditions(where?: any): where is any {
65
+ if (where == null) return false
66
+ for (let key in where) {
67
+ switch(key) {
68
+ case 'AND':
69
+ case 'OR':
70
+ break
71
+ default:
72
+ return true
73
+ }
74
+ }
75
+ if (Array.isArray(where.AND)) {
76
+ if (where.AND.some(hasConditions)) return true
77
+ } else if (where.AND && hasConditions(where.AND)) {
78
+ return true
79
+ }
80
+ if (Array.isArray(where.OR)) {
81
+ if (where.OR.some(hasConditions)) return true
82
+ } else if (where.OR && hasConditions(where.OR)) {
83
+ return true
84
+ }
85
+ return false
86
+ }
87
+
88
+
89
+ export function whereOpToSqlOperator(op: WhereOp): string {
90
+ switch(op) {
91
+ case 'eq':
92
+ return '='
93
+ case 'not_eq':
94
+ return '!='
95
+ case 'gt':
96
+ return '>'
97
+ case 'gte':
98
+ return '>='
99
+ case 'lt':
100
+ return '<'
101
+ case 'lte':
102
+ return '<='
103
+ case 'in':
104
+ return 'IN'
105
+ case 'not_in':
106
+ return 'NOT IN'
107
+ default:
108
+ throw new Error(`Operator ${op} doesn't have SQL analog`)
109
+ }
110
+ }
package/CHANGELOG.md DELETED
@@ -1,16 +0,0 @@
1
- ## 0.2.0 (2021-10-24)
2
-
3
- * new: support for one-to-one lookups
4
- * new: `_doc` column is no longer required for FTS queries
5
- * internal: rename `list-relation` property kind to `list-lookup`
6
- * internal: move gql doc merging from `buildSchema()` to `loadModel()`
7
-
8
- ## 0.1.0 (2021-10-06)
9
-
10
- * fix DateTime serialization in subqueries ([03f71f1](https://github.com/subsquid/openreader/commit/03f71f1))
11
- * internal preparations for usage within hydra
12
-
13
- ## 0.0.0
14
-
15
- * First release
16
-
@@ -1,10 +0,0 @@
1
- import type { Pool, ClientBase } from "pg";
2
- export declare class Transaction {
3
- private pool;
4
- private client;
5
- private closed;
6
- constructor(pool: Pool);
7
- get(): Promise<ClientBase>;
8
- private startTransaction;
9
- close(): Promise<void>;
10
- }
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Transaction = void 0;
4
- class Transaction {
5
- constructor(pool) {
6
- this.pool = pool;
7
- this.closed = false;
8
- }
9
- get() {
10
- if (this.closed) {
11
- throw new Error('Too late to request transaction');
12
- }
13
- if (this.client) {
14
- return this.client;
15
- }
16
- else {
17
- return this.client = this.startTransaction();
18
- }
19
- }
20
- async startTransaction() {
21
- let client = await this.pool.connect();
22
- try {
23
- await client.query('START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY');
24
- return client;
25
- }
26
- catch (e) {
27
- client.release();
28
- throw e;
29
- }
30
- }
31
- close() {
32
- this.closed = true;
33
- return this.client?.then(async (client) => {
34
- try {
35
- await client.query('COMMIT');
36
- }
37
- catch (e) {
38
- // ignore
39
- }
40
- finally {
41
- client.release();
42
- }
43
- }) || Promise.resolve();
44
- }
45
- }
46
- exports.Transaction = Transaction;
47
- //# sourceMappingURL=transaction.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":";;;AAGA,MAAa,WAAW;IAIpB,YAAoB,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;QAFtB,WAAM,GAAG,KAAK,CAAA;IAEW,CAAC;IAElC,GAAG;QACC,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;SACrD;QACD,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,OAAO,IAAI,CAAC,MAAM,CAAA;SACrB;aAAM;YACH,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAA;SAC/C;IACL,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC1B,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;QACtC,IAAI;YACA,MAAM,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YAC9E,OAAO,MAAM,CAAA;SAChB;QAAC,OAAM,CAAM,EAAE;YACZ,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,MAAM,CAAC,CAAA;SACV;IACL,CAAC;IAED,KAAK;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;YACpC,IAAI;gBACA,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;aAC/B;YAAC,OAAM,CAAM,EAAE;gBACZ,SAAS;aACZ;oBAAS;gBACN,MAAM,CAAC,OAAO,EAAE,CAAA;aACnB;QACL,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAA;IAC3B,CAAC;CACJ;AAxCD,kCAwCC"}