@subsquid/openreader 0.2.1 → 0.4.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/README.md +2 -15
- package/bin/main.js +2 -0
- package/dist/db.d.ts +28 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +69 -0
- package/dist/db.js.map +1 -0
- package/dist/gql/opencrud.d.ts +1 -0
- package/dist/gql/opencrud.d.ts.map +1 -0
- package/dist/gql/opencrud.js +10 -9
- package/dist/gql/opencrud.js.map +1 -1
- package/dist/gql/schema.d.ts +1 -0
- package/dist/gql/schema.d.ts.map +1 -0
- package/dist/gql/schema.js +116 -17
- package/dist/gql/schema.js.map +1 -1
- package/dist/main.d.ts +2 -3
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +6 -30
- package/dist/main.js.map +1 -1
- package/dist/model.d.ts +9 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.tools.d.ts +2 -0
- package/dist/model.tools.d.ts.map +1 -0
- package/dist/model.tools.js +27 -1
- package/dist/model.tools.js.map +1 -1
- package/dist/orderBy.d.ts +1 -0
- package/dist/orderBy.d.ts.map +1 -0
- package/dist/queryBuilder.d.ts +3 -2
- package/dist/queryBuilder.d.ts.map +1 -0
- package/dist/queryBuilder.js +28 -27
- package/dist/queryBuilder.js.map +1 -1
- package/dist/relayConnection.d.ts +1 -0
- package/dist/relayConnection.d.ts.map +1 -0
- package/dist/requestedFields.d.ts +1 -0
- package/dist/requestedFields.d.ts.map +1 -0
- package/dist/requestedFields.js +3 -3
- package/dist/requestedFields.js.map +1 -1
- package/dist/resolver.d.ts +3 -2
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +12 -11
- package/dist/resolver.js.map +1 -1
- package/dist/scalars.d.ts +2 -2
- package/dist/scalars.d.ts.map +1 -0
- package/dist/scalars.js.map +1 -1
- package/dist/server.d.ts +5 -11
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +13 -31
- package/dist/server.js.map +1 -1
- package/dist/test/basic.test.d.ts +2 -0
- package/dist/test/basic.test.d.ts.map +1 -0
- package/dist/test/basic.test.js +286 -0
- package/dist/test/basic.test.js.map +1 -0
- package/dist/test/connection.test.d.ts +2 -0
- package/dist/test/connection.test.d.ts.map +1 -0
- package/dist/test/connection.test.js +193 -0
- package/dist/test/connection.test.js.map +1 -0
- package/dist/test/fts.test.d.ts +2 -0
- package/dist/test/fts.test.d.ts.map +1 -0
- package/dist/test/fts.test.js +110 -0
- package/dist/test/fts.test.js.map +1 -0
- package/dist/test/lists.test.d.ts +2 -0
- package/dist/test/lists.test.d.ts.map +1 -0
- package/dist/test/lists.test.js +266 -0
- package/dist/test/lists.test.js.map +1 -0
- package/dist/test/lookup.test.d.ts +2 -0
- package/dist/test/lookup.test.d.ts.map +1 -0
- package/dist/test/lookup.test.js +109 -0
- package/dist/test/lookup.test.js.map +1 -0
- package/dist/test/scalars.test.d.ts +2 -0
- package/dist/test/scalars.test.d.ts.map +1 -0
- package/dist/test/scalars.test.js +303 -0
- package/dist/test/scalars.test.js.map +1 -0
- package/dist/test/tools.test.d.ts +2 -0
- package/dist/test/tools.test.d.ts.map +1 -0
- package/dist/test/tools.test.js +49 -0
- package/dist/test/tools.test.js.map +1 -0
- package/dist/test/typed-json.test.d.ts +2 -0
- package/dist/test/typed-json.test.d.ts.map +1 -0
- package/dist/test/typed-json.test.js +75 -0
- package/dist/test/typed-json.test.js.map +1 -0
- package/dist/test/unions.test.d.ts +2 -0
- package/dist/test/unions.test.d.ts.map +1 -0
- package/dist/test/unions.test.js +84 -0
- package/dist/test/unions.test.js.map +1 -0
- package/dist/test/util/setup.d.ts +7 -0
- package/dist/test/util/setup.d.ts.map +1 -0
- package/dist/test/util/setup.js +60 -0
- package/dist/test/util/setup.js.map +1 -0
- package/dist/test/where.test.d.ts +2 -0
- package/dist/test/where.test.d.ts.map +1 -0
- package/dist/test/where.test.js +127 -0
- package/dist/test/where.test.js.map +1 -0
- package/dist/tools.d.ts +1 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/util.d.ts +1 -13
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +6 -79
- package/dist/util.js.map +1 -1
- package/dist/where.d.ts +1 -0
- package/dist/where.d.ts.map +1 -0
- package/package.json +26 -20
- package/src/db.ts +83 -0
- package/src/gql/opencrud.ts +328 -0
- package/src/gql/schema.ts +463 -0
- package/src/main.ts +51 -0
- package/src/model.tools.ts +201 -0
- package/src/model.ts +137 -0
- package/src/orderBy.ts +105 -0
- package/src/queryBuilder.ts +785 -0
- package/src/relayConnection.ts +80 -0
- package/src/requestedFields.ts +246 -0
- package/src/resolver.ts +199 -0
- package/src/scalars.ts +247 -0
- package/src/server.ts +115 -0
- package/src/test/basic.test.ts +339 -0
- package/src/test/connection.test.ts +195 -0
- package/src/test/fts.test.ts +114 -0
- package/src/test/lists.test.ts +278 -0
- package/src/test/lookup.test.ts +111 -0
- package/src/test/scalars.test.ts +316 -0
- package/src/test/tools.test.ts +27 -0
- package/src/test/typed-json.test.ts +76 -0
- package/src/test/unions.test.ts +85 -0
- package/src/test/util/setup.ts +63 -0
- package/src/test/where.test.ts +135 -0
- package/src/tools.ts +33 -0
- package/src/util.ts +39 -0
- package/src/where.ts +110 -0
- package/CHANGELOG.md +0 -20
- package/dist/transaction.d.ts +0 -10
- package/dist/transaction.js +0 -47
- package/dist/transaction.js.map +0 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const setup_1 = require("./util/setup");
|
|
4
|
+
describe('unions', function () {
|
|
5
|
+
(0, setup_1.useDatabase)([
|
|
6
|
+
`create table "user" (id text primary key, login text)`,
|
|
7
|
+
`create table equipment (id text primary key, name text, owner jsonb)`,
|
|
8
|
+
`insert into "user" (id, login) values ('1', 'farmer')`,
|
|
9
|
+
`insert into "user" (id, login) values ('2', 'programmer')`,
|
|
10
|
+
`insert into equipment (id, name, owner) values ('1', 'combine', '{"isTypeOf": "Farmer", "user": "1", "crop": 100}'::jsonb)`,
|
|
11
|
+
`insert into equipment (id, name, owner) values ('2', 'computer', '{"isTypeOf": "Programmer", "user": "2", "stack": "Python"}'::jsonb)`
|
|
12
|
+
]);
|
|
13
|
+
const client = (0, setup_1.useServer)(`
|
|
14
|
+
type User @entity {
|
|
15
|
+
id: ID!
|
|
16
|
+
login: String!
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type Farmer {
|
|
20
|
+
user: User!
|
|
21
|
+
crop: Int
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type Programmer {
|
|
25
|
+
user: User!
|
|
26
|
+
stack: String
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
union Owner = Farmer | Programmer
|
|
30
|
+
|
|
31
|
+
type Equipment @entity {
|
|
32
|
+
name: String!
|
|
33
|
+
owner: Owner!
|
|
34
|
+
}
|
|
35
|
+
`);
|
|
36
|
+
it('output', function () {
|
|
37
|
+
return client.test(`
|
|
38
|
+
query {
|
|
39
|
+
equipment(orderBy: id_ASC) {
|
|
40
|
+
name
|
|
41
|
+
owner {
|
|
42
|
+
... on Farmer {
|
|
43
|
+
user { login }
|
|
44
|
+
crop
|
|
45
|
+
}
|
|
46
|
+
... on Programmer {
|
|
47
|
+
user { login }
|
|
48
|
+
stack
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`, {
|
|
54
|
+
equipment: [
|
|
55
|
+
{
|
|
56
|
+
name: 'combine',
|
|
57
|
+
owner: {
|
|
58
|
+
user: { login: 'farmer' },
|
|
59
|
+
crop: 100
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'computer',
|
|
64
|
+
owner: {
|
|
65
|
+
user: { login: 'programmer' },
|
|
66
|
+
stack: 'Python'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
it('filtering', function () {
|
|
73
|
+
return client.test(`
|
|
74
|
+
query {
|
|
75
|
+
type_farmer: equipment(where: {owner: {isTypeOf_eq: "Farmer"}}) { id }
|
|
76
|
+
stack_Python: equipment(where: {owner: {stack_eq: "Python"}}) { id }
|
|
77
|
+
}
|
|
78
|
+
`, {
|
|
79
|
+
type_farmer: [{ id: '1' }],
|
|
80
|
+
stack_Python: [{ id: '2' }]
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=unions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unions.test.js","sourceRoot":"","sources":["../../src/test/unions.test.ts"],"names":[],"mappings":";;AAAA,wCAAmD;AAEnD,QAAQ,CAAC,QAAQ,EAAE;IACf,IAAA,mBAAW,EAAC;QACR,uDAAuD;QACvD,sEAAsE;QACtE,uDAAuD;QACvD,2DAA2D;QAC3D,4HAA4H;QAC5H,uIAAuI;KAC1I,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,IAAA,iBAAS,EAAC;;;;;;;;;;;;;;;;;;;;;;KAsBxB,CAAC,CAAA;IAEF,EAAE,CAAC,QAAQ,EAAE;QACT,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;SAgBlB,EAAE;YACC,SAAS,EAAE;gBACP;oBACI,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE;wBACH,IAAI,EAAE,EAAC,KAAK,EAAE,QAAQ,EAAC;wBACvB,IAAI,EAAE,GAAG;qBACZ;iBACJ;gBACD;oBACI,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE;wBACH,IAAI,EAAE,EAAC,KAAK,EAAE,YAAY,EAAC;wBAC3B,KAAK,EAAE,QAAQ;qBAClB;iBACJ;aACJ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,WAAW,EAAE;QACZ,OAAO,MAAM,CAAC,IAAI,CAAC;;;;;SAKlB,EAAE;YACC,WAAW,EAAE,CAAC,EAAC,EAAE,EAAE,GAAG,EAAC,CAAC;YACxB,YAAY,EAAE,CAAC,EAAC,EAAE,EAAE,GAAG,EAAC,CAAC;SAC5B,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Client } from "gql-test-client";
|
|
2
|
+
export declare const db_config: import("pg").PoolConfig;
|
|
3
|
+
export declare function databaseInit(sql: string[]): Promise<void>;
|
|
4
|
+
export declare function databaseDelete(): Promise<void>;
|
|
5
|
+
export declare function useDatabase(sql: string[]): void;
|
|
6
|
+
export declare function useServer(schema: string): Client;
|
|
7
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/test/util/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAA;AAQtC,eAAO,MAAM,SAAS,yBAAqB,CAAA;AAc3C,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzD;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,CAehD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useServer = exports.useDatabase = exports.databaseDelete = exports.databaseInit = exports.db_config = void 0;
|
|
4
|
+
const gql_test_client_1 = require("gql-test-client");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const pg_1 = require("pg");
|
|
7
|
+
const db_1 = require("../../db");
|
|
8
|
+
const schema_1 = require("../../gql/schema");
|
|
9
|
+
const server_1 = require("../../server");
|
|
10
|
+
exports.db_config = (0, db_1.createPoolConfig)();
|
|
11
|
+
async function withClient(block) {
|
|
12
|
+
let client = new pg_1.Client(exports.db_config);
|
|
13
|
+
await client.connect();
|
|
14
|
+
try {
|
|
15
|
+
await block(client);
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
await client.end();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function databaseInit(sql) {
|
|
22
|
+
return withClient(async (client) => {
|
|
23
|
+
for (let i = 0; i < sql.length; i++) {
|
|
24
|
+
await client.query(sql[i]);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
exports.databaseInit = databaseInit;
|
|
29
|
+
function databaseDelete() {
|
|
30
|
+
return withClient(async (client) => {
|
|
31
|
+
await client.query(`DROP SCHEMA IF EXISTS public CASCADE`);
|
|
32
|
+
await client.query(`CREATE SCHEMA public`);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
exports.databaseDelete = databaseDelete;
|
|
36
|
+
function useDatabase(sql) {
|
|
37
|
+
before(async () => {
|
|
38
|
+
await databaseDelete();
|
|
39
|
+
await databaseInit(sql);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
exports.useDatabase = useDatabase;
|
|
43
|
+
function useServer(schema) {
|
|
44
|
+
let client = new gql_test_client_1.Client('not defined');
|
|
45
|
+
let db = new pg_1.Pool(exports.db_config);
|
|
46
|
+
let info;
|
|
47
|
+
before(async () => {
|
|
48
|
+
info = await (0, server_1.serve)({
|
|
49
|
+
db,
|
|
50
|
+
model: (0, schema_1.buildModel)((0, schema_1.buildSchema)((0, graphql_1.parse)(schema))),
|
|
51
|
+
port: 0
|
|
52
|
+
});
|
|
53
|
+
client.endpoint = `http://localhost:${info.port}/graphql`;
|
|
54
|
+
});
|
|
55
|
+
after(() => info?.stop());
|
|
56
|
+
after(() => db.end());
|
|
57
|
+
return client;
|
|
58
|
+
}
|
|
59
|
+
exports.useServer = useServer;
|
|
60
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/test/util/setup.ts"],"names":[],"mappings":";;;AAAA,qDAAsC;AACtC,qCAA6B;AAC7B,2BAAuD;AACvD,iCAAyC;AACzC,6CAAwD;AACxD,yCAAmD;AAGtC,QAAA,SAAS,GAAG,IAAA,qBAAgB,GAAE,CAAA;AAG3C,KAAK,UAAU,UAAU,CAAC,KAA4C;IAClE,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;AAGD,SAAgB,YAAY,CAAC,GAAa;IACtC,OAAO,UAAU,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QAC7B,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,oCAMC;AAGD,SAAgB,cAAc;IAC1B,OAAO,UAAU,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QAC7B,MAAM,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;QAC1D,MAAM,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;IAC9C,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,YAAY,CAAC,GAAG,CAAC,CAAA;IAC3B,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,EAAE;YACF,KAAK,EAAE,IAAA,mBAAU,EAAC,IAAA,oBAAW,EAAC,IAAA,eAAK,EAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,IAAI,EAAE,CAAC;SACV,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,IAAI,EAAE,CAAC,CAAA;IACzB,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;IACrB,OAAO,MAAM,CAAA;AACjB,CAAC;AAfD,8BAeC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where.test.d.ts","sourceRoot":"","sources":["../../src/test/where.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const setup_1 = require("./util/setup");
|
|
4
|
+
describe('AND, OR on entity filters', function () {
|
|
5
|
+
(0, setup_1.useDatabase)([
|
|
6
|
+
`create table item (id text primary key, a int, b int)`,
|
|
7
|
+
`insert into item (id, a, b) values ('1', 1, 1)`,
|
|
8
|
+
`insert into item (id, a, b) values ('2', 2, 2)`,
|
|
9
|
+
`insert into item (id, a, b) values ('3', 3, 2)`,
|
|
10
|
+
`insert into item (id, a, b) values ('4', 4, 4)`,
|
|
11
|
+
`insert into item (id, a, b) values ('5', 5, 4)`,
|
|
12
|
+
`insert into item (id, a, b) values ('6', 5, 6)`,
|
|
13
|
+
]);
|
|
14
|
+
const client = (0, setup_1.useServer)(`
|
|
15
|
+
type Item @entity {
|
|
16
|
+
id: ID!
|
|
17
|
+
a: Int
|
|
18
|
+
b: Int
|
|
19
|
+
}
|
|
20
|
+
`);
|
|
21
|
+
it('{c, and: {c}}', function () {
|
|
22
|
+
return client.test(`
|
|
23
|
+
query {
|
|
24
|
+
items(where: {a_eq: 1, AND: {b_eq: 1}} orderBy: id_ASC) { id }
|
|
25
|
+
}
|
|
26
|
+
`, {
|
|
27
|
+
items: [
|
|
28
|
+
{ id: '1' }
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it('{and: {and: {c}, c}}', function () {
|
|
33
|
+
return client.test(`
|
|
34
|
+
query {
|
|
35
|
+
items(where: {AND: {b_eq: 2, AND: {a_eq: 3}}} orderBy: id_ASC) { id }
|
|
36
|
+
}
|
|
37
|
+
`, {
|
|
38
|
+
items: [
|
|
39
|
+
{ id: '3' }
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
it('{and: [{c}, {c}]}', function () {
|
|
44
|
+
return client.test(`
|
|
45
|
+
query {
|
|
46
|
+
items(where: {AND: [{a_eq: 2}, {b_eq: 2}]} orderBy: id_ASC) { id }
|
|
47
|
+
}
|
|
48
|
+
`, {
|
|
49
|
+
items: [
|
|
50
|
+
{ id: '2' }
|
|
51
|
+
]
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
it('{c, {or: {c}}}', function () {
|
|
55
|
+
return client.test(`
|
|
56
|
+
query {
|
|
57
|
+
items(where: {a_eq: 1, OR: {a_eq: 2}} orderBy: id_ASC) { id }
|
|
58
|
+
}
|
|
59
|
+
`, {
|
|
60
|
+
items: [
|
|
61
|
+
{ id: '1' },
|
|
62
|
+
{ id: '2' }
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
it('{or: [{c}, {c}]}', function () {
|
|
67
|
+
return client.test(`
|
|
68
|
+
query {
|
|
69
|
+
items(where: {OR: [{a_eq: 2}, {a_eq: 3}]} orderBy: id_ASC) { id }
|
|
70
|
+
}
|
|
71
|
+
`, {
|
|
72
|
+
items: [
|
|
73
|
+
{ id: '2' },
|
|
74
|
+
{ id: '3' }
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it('{or: {or: {c}, c}}', function () {
|
|
79
|
+
return client.test(`
|
|
80
|
+
query {
|
|
81
|
+
items(where: {OR: {a_eq: 1, OR: {b_eq: 2}}} orderBy: id_ASC) { id }
|
|
82
|
+
}
|
|
83
|
+
`, {
|
|
84
|
+
items: [
|
|
85
|
+
{ id: '1' },
|
|
86
|
+
{ id: '2' },
|
|
87
|
+
{ id: '3' }
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
it('{and: [{or: {c}, c}, {or: {c}, c}]}', function () {
|
|
92
|
+
return client.test(`
|
|
93
|
+
query {
|
|
94
|
+
items(where: {AND: [{OR: {a_eq: 5}, a_eq: 4}, {OR: {b_eq: 2}, b_eq: 4}]} orderBy: id_ASC) { id }
|
|
95
|
+
}
|
|
96
|
+
`, {
|
|
97
|
+
items: [
|
|
98
|
+
{ id: '4' },
|
|
99
|
+
{ id: '5' }
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
it('{c, and: {c}, or: {c}}', function () {
|
|
104
|
+
return client.test(`
|
|
105
|
+
query {
|
|
106
|
+
items(where: { a_eq: 4, AND: {b_eq: 4}, OR: {b_eq: 6} } orderBy: id_ASC) { id }
|
|
107
|
+
}
|
|
108
|
+
`, {
|
|
109
|
+
items: [
|
|
110
|
+
{ id: '4' },
|
|
111
|
+
{ id: '6' }
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
it('handles empty wheres', function () {
|
|
116
|
+
return client.test(`
|
|
117
|
+
query {
|
|
118
|
+
items(where: { a_eq: 4, AND: { OR: {}, AND: {} }, OR: { OR: {AND: {} } } } orderBy: id_ASC) { id }
|
|
119
|
+
}
|
|
120
|
+
`, {
|
|
121
|
+
items: [
|
|
122
|
+
{ id: '4' }
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=where.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where.test.js","sourceRoot":"","sources":["../../src/test/where.test.ts"],"names":[],"mappings":";;AAAA,wCAAmD;AAEnD,QAAQ,CAAC,2BAA2B,EAAE;IAClC,IAAA,mBAAW,EAAC;QACR,uDAAuD;QACvD,gDAAgD;QAChD,gDAAgD;QAChD,gDAAgD;QAChD,gDAAgD;QAChD,gDAAgD;QAChD,gDAAgD;KACnD,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,IAAA,iBAAS,EAAC;;;;;;KAMxB,CAAC,CAAA;IAEF,EAAE,CAAC,eAAe,EAAE;QAChB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sBAAsB,EAAE;QACvB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mBAAmB,EAAE;QACpB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gBAAgB,EAAE;QACjB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kBAAkB,EAAE;QACnB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oBAAoB,EAAE;QACrB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE;QACtC,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wBAAwB,EAAE;QACzB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;gBACT,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sBAAsB,EAAE;QACvB,OAAO,MAAM,CAAC,IAAI,CAAC;;;;SAIlB,EAAE;YACC,KAAK,EAAE;gBACH,EAAC,EAAE,EAAE,GAAG,EAAC;aACZ;SACJ,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,SAAS,CAAA;AAGlC,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAwBnD"}
|
package/dist/util.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { pluralize } from "inflected";
|
|
2
|
-
export { pluralize };
|
|
3
|
-
export declare function snakeCase(name: string): string;
|
|
4
|
-
export declare function lowerCaseFirst(s: string): string;
|
|
5
|
-
export declare function upperCaseFirst(s: string): string;
|
|
6
1
|
export declare function toQueryListField(entityName: string): string;
|
|
7
2
|
export declare function toColumn(gqlFieldName: string): string;
|
|
8
3
|
export declare function toFkColumn(gqlFieldName: string): string;
|
|
@@ -10,11 +5,4 @@ export declare function toTable(entityName: string): string;
|
|
|
10
5
|
export declare function ensureArray<T>(item: T | T[]): T[];
|
|
11
6
|
export declare function unsupportedCase(value: string): Error;
|
|
12
7
|
export declare function toInt(val: number | string): number;
|
|
13
|
-
|
|
14
|
-
private out;
|
|
15
|
-
private indent;
|
|
16
|
-
line(s?: string): void;
|
|
17
|
-
block(start: string, cb: () => void): void;
|
|
18
|
-
lazy(gen: () => string[]): void;
|
|
19
|
-
toString(): string;
|
|
20
|
-
}
|
|
8
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAGD,wBAAgB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAErD;AAGD,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEvD;AAGD,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAElD;AAGD,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAEjD;AAGD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAEpD;AAGD,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAIlD"}
|
package/dist/util.js
CHANGED
|
@@ -3,46 +3,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.toInt = exports.unsupportedCase = exports.ensureArray = exports.toTable = exports.toFkColumn = exports.toColumn = exports.toQueryListField = void 0;
|
|
7
|
+
const util_1 = require("@subsquid/util");
|
|
7
8
|
const assert_1 = __importDefault(require("assert"));
|
|
8
|
-
const inflected_1 = require("inflected");
|
|
9
|
-
Object.defineProperty(exports, "pluralize", { enumerable: true, get: function () { return inflected_1.pluralize; } });
|
|
10
|
-
function snakeCase(name) {
|
|
11
|
-
return (0, inflected_1.underscore)(name);
|
|
12
|
-
}
|
|
13
|
-
exports.snakeCase = snakeCase;
|
|
14
|
-
function lowerCaseFirst(s) {
|
|
15
|
-
if (s) {
|
|
16
|
-
return s[0].toLowerCase() + s.slice(1);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
return s;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.lowerCaseFirst = lowerCaseFirst;
|
|
23
|
-
function upperCaseFirst(s) {
|
|
24
|
-
if (s) {
|
|
25
|
-
return s[0].toUpperCase() + s.slice(1);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
return s;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
exports.upperCaseFirst = upperCaseFirst;
|
|
32
9
|
function toQueryListField(entityName) {
|
|
33
|
-
return (0,
|
|
10
|
+
return (0, util_1.toPlural)((0, util_1.toCamelCase)(entityName));
|
|
34
11
|
}
|
|
35
12
|
exports.toQueryListField = toQueryListField;
|
|
36
13
|
function toColumn(gqlFieldName) {
|
|
37
|
-
return
|
|
14
|
+
return (0, util_1.toSnakeCase)(gqlFieldName);
|
|
38
15
|
}
|
|
39
16
|
exports.toColumn = toColumn;
|
|
40
17
|
function toFkColumn(gqlFieldName) {
|
|
41
|
-
return
|
|
18
|
+
return (0, util_1.toSnakeCase)(gqlFieldName) + '_id';
|
|
42
19
|
}
|
|
43
20
|
exports.toFkColumn = toFkColumn;
|
|
44
21
|
function toTable(entityName) {
|
|
45
|
-
return
|
|
22
|
+
return (0, util_1.toSnakeCase)(entityName);
|
|
46
23
|
}
|
|
47
24
|
exports.toTable = toTable;
|
|
48
25
|
function ensureArray(item) {
|
|
@@ -59,54 +36,4 @@ function toInt(val) {
|
|
|
59
36
|
return i;
|
|
60
37
|
}
|
|
61
38
|
exports.toInt = toInt;
|
|
62
|
-
class Output {
|
|
63
|
-
constructor() {
|
|
64
|
-
this.out = [];
|
|
65
|
-
this.indent = '';
|
|
66
|
-
}
|
|
67
|
-
line(s) {
|
|
68
|
-
if (s) {
|
|
69
|
-
this.out.push(this.indent + s);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
this.out.push('');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
block(start, cb) {
|
|
76
|
-
this.line(start + ' {');
|
|
77
|
-
this.indent += ' ';
|
|
78
|
-
try {
|
|
79
|
-
cb();
|
|
80
|
-
}
|
|
81
|
-
finally {
|
|
82
|
-
this.indent = this.indent.slice(0, this.indent.length - 2);
|
|
83
|
-
}
|
|
84
|
-
this.line('}');
|
|
85
|
-
}
|
|
86
|
-
lazy(gen) {
|
|
87
|
-
this.out.push({ indent: this.indent, gen });
|
|
88
|
-
}
|
|
89
|
-
toString() {
|
|
90
|
-
let out = '';
|
|
91
|
-
for (let i = 0; i < this.out.length; i++) {
|
|
92
|
-
let line = this.out[i];
|
|
93
|
-
if (typeof line == 'string') {
|
|
94
|
-
out += line + '\n';
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
let lazy = line;
|
|
98
|
-
lazy.gen().forEach(s => {
|
|
99
|
-
if (s) {
|
|
100
|
-
out += lazy.indent + s + '\n';
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
out += '\n';
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return out;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
exports.Output = Output;
|
|
112
39
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAiE;AACjE,oDAA2B;AAG3B,SAAgB,gBAAgB,CAAC,UAAkB;IAC/C,OAAO,IAAA,eAAQ,EAAC,IAAA,kBAAW,EAAC,UAAU,CAAC,CAAC,CAAA;AAC5C,CAAC;AAFD,4CAEC;AAGD,SAAgB,QAAQ,CAAC,YAAoB;IACzC,OAAO,IAAA,kBAAW,EAAC,YAAY,CAAC,CAAA;AACpC,CAAC;AAFD,4BAEC;AAGD,SAAgB,UAAU,CAAC,YAAoB;IAC3C,OAAO,IAAA,kBAAW,EAAC,YAAY,CAAC,GAAG,KAAK,CAAA;AAC5C,CAAC;AAFD,gCAEC;AAGD,SAAgB,OAAO,CAAC,UAAkB;IACtC,OAAO,IAAA,kBAAW,EAAC,UAAU,CAAC,CAAA;AAClC,CAAC;AAFD,0BAEC;AAGD,SAAgB,WAAW,CAAI,IAAa;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAC9C,CAAC;AAFD,kCAEC;AAGD,SAAgB,eAAe,CAAC,KAAa;IACzC,OAAO,IAAI,KAAK,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAA;AAClD,CAAC;AAFD,0CAEC;AAGD,SAAgB,KAAK,CAAC,GAAoB;IACtC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAa,CAAC,CAAA;IAC/B,IAAA,gBAAM,EAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAChC,OAAO,CAAC,CAAA;AACZ,CAAC;AAJD,sBAIC"}
|
package/dist/where.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../src/where.ts"],"names":[],"mappings":"AACA,oBAAY,OAAO,GACf,GAAG,GAAG,cAAc;AACpB,IAAI,GAAG,QAAQ,GACf,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,IAAI,GAAG,QAAQ,GACf,UAAU,GAAG,cAAc,GAC3B,YAAY,GAAG,gBAAgB,GAC/B,UAAU,GAAG,cAAc,GAC3B,aAAa,GACb,aAAa,GACb,cAAc,GACd,MAAM,GACN,OAAO,GACP,MAAM,CAAA;AAmCV,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAQ3E;AAGD,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,KAAK,IAAI,GAAG,CAsBvD;AAGD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAqBxD"}
|
package/package.json
CHANGED
|
@@ -1,44 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subsquid/openreader",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "GraphQL server for
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "GraphQL server for squid framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
7
7
|
"opencrud"
|
|
8
8
|
],
|
|
9
|
-
"license": "
|
|
10
|
-
"repository": "git@github.com:subsquid/
|
|
9
|
+
"license": "GPL-3.0-or-later",
|
|
10
|
+
"repository": "git@github.com:subsquid/squid.git",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"openreader": "./
|
|
15
|
+
"openreader": "./bin/main.js"
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
|
+
"bin",
|
|
18
19
|
"dist",
|
|
19
|
-
"
|
|
20
|
+
"src"
|
|
20
21
|
],
|
|
21
22
|
"dependencies": {
|
|
22
23
|
"@graphql-tools/merge": "^8",
|
|
23
24
|
"@graphql-tools/utils": "^8",
|
|
24
25
|
"@subsquid/graphiql-console": "^0.2.0",
|
|
25
|
-
"
|
|
26
|
-
"apollo-server-
|
|
27
|
-
"express": "^
|
|
28
|
-
"
|
|
26
|
+
"@subsquid/util": "^0.0.3",
|
|
27
|
+
"apollo-server-core": "^3.5.0",
|
|
28
|
+
"apollo-server-express": "^3.5.0",
|
|
29
|
+
"express": "^4.17.2",
|
|
30
|
+
"graphql": "^15.8.0",
|
|
29
31
|
"graphql-parse-resolve-info": "^4.12.0",
|
|
30
|
-
"inflected": "^2.1.0",
|
|
31
32
|
"pg": "^8.7.1"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
|
-
"@types/
|
|
35
|
+
"@types/express": "^4.17.13",
|
|
35
36
|
"@types/mocha": "^9.0.0",
|
|
36
|
-
"@types/node
|
|
37
|
-
"@types/pg": "^8.6.
|
|
37
|
+
"@types/node": "^16.11.17",
|
|
38
|
+
"@types/pg": "^8.6.3",
|
|
38
39
|
"dotenv": "^10.0.0",
|
|
39
|
-
"expect": "^27.
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"typescript": "
|
|
43
|
-
}
|
|
44
|
-
|
|
40
|
+
"expect": "^27.4.6",
|
|
41
|
+
"gql-test-client": "^0.0.0",
|
|
42
|
+
"mocha": "^9.1.3",
|
|
43
|
+
"typescript": "~4.5.4"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "rm -rf dist && tsc",
|
|
47
|
+
"test": "make up && sleep 1 && make test && make down || (make down && exit 1)"
|
|
48
|
+
},
|
|
49
|
+
"readme": "# OpenReader\n\nGraphQL server for squid framework. Given [data schema](https://docs.subsquid.io/schema-spec) \nand compatible Postgres database it serves \"read part\" of [OpenCRUD spec](https://www.opencrud.org).\n\n## Usage\n\n```bash\nopenreader schema.graphql\n```\n\nDatabase connection and server port are configured via environment variables:\n\n```\nDB_NAME\nDB_USER\nDB_PASS\nDB_HOST\nDB_PORT\nGRAPHQL_SERVER_PORT\n```\n"
|
|
50
|
+
}
|
package/src/db.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type {ClientBase, Pool, PoolClient, PoolConfig} from "pg"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface Database {
|
|
5
|
+
query(sql: string, parameters?: any[]): Promise<any[][]>
|
|
6
|
+
escapeIdentifier(name: string): string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This is an interface OpenReader uses to interact with underling database.
|
|
12
|
+
*/
|
|
13
|
+
export interface Transaction {
|
|
14
|
+
get(): Promise<Database>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export class PgDatabase implements Database {
|
|
19
|
+
constructor(private client: ClientBase) {}
|
|
20
|
+
|
|
21
|
+
query(sql: string, parameters?: any[]): Promise<any[]> {
|
|
22
|
+
return this.client.query({text: sql, rowMode: 'array'}, parameters).then(result => result.rows)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
escapeIdentifier(name: string): string {
|
|
26
|
+
return this.client.escapeIdentifier(name)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export class PoolTransaction implements Transaction {
|
|
32
|
+
private tx: Promise<{client: PoolClient, db: Database}> | undefined
|
|
33
|
+
private closed = false
|
|
34
|
+
|
|
35
|
+
constructor(private pool: Pool) {}
|
|
36
|
+
|
|
37
|
+
async get(): Promise<Database> {
|
|
38
|
+
if (this.closed) {
|
|
39
|
+
throw new Error('Too late to request transaction')
|
|
40
|
+
}
|
|
41
|
+
this.tx = this.tx || this.startTransaction()
|
|
42
|
+
let {db} = await this.tx
|
|
43
|
+
return db
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private async startTransaction(): Promise<{client: PoolClient, db: Database}> {
|
|
47
|
+
let client = await this.pool.connect()
|
|
48
|
+
try {
|
|
49
|
+
await client.query('START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY')
|
|
50
|
+
return {
|
|
51
|
+
client,
|
|
52
|
+
db: new PgDatabase(client)
|
|
53
|
+
}
|
|
54
|
+
} catch(e: any) {
|
|
55
|
+
client.release()
|
|
56
|
+
throw e
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
close(): Promise<void> {
|
|
61
|
+
this.closed = true
|
|
62
|
+
return this.tx?.then(async ({client}) => {
|
|
63
|
+
try {
|
|
64
|
+
await client.query('COMMIT')
|
|
65
|
+
} catch(e: any) {
|
|
66
|
+
// ignore
|
|
67
|
+
} finally {
|
|
68
|
+
client.release()
|
|
69
|
+
}
|
|
70
|
+
}) || Promise.resolve()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
export function createPoolConfig(): PoolConfig {
|
|
76
|
+
return {
|
|
77
|
+
host: process.env.DB_HOST || 'localhost',
|
|
78
|
+
port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432,
|
|
79
|
+
database: process.env.DB_NAME || 'postgres',
|
|
80
|
+
user: process.env.DB_USER || 'postgres',
|
|
81
|
+
password: process.env.DB_PASS || 'postgres'
|
|
82
|
+
}
|
|
83
|
+
}
|