@technicity/data-service-generator 0.12.0-next.0 → 0.12.1
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 +7 -0
- package/dist/generation/generate.js +427 -244
- package/dist/getFakeData.d.ts +12 -0
- package/dist/getFakeData.js +90 -0
- package/dist/getIsList.d.ts +1 -0
- package/dist/getIsList.js +7 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -1
- package/dist/runtime/Cache.d.ts +16 -6
- package/dist/runtime/Cache.js +78 -29
- package/dist/runtime/IRuntime.d.ts +30 -3
- package/dist/runtime/RuntimeKSQL.d.ts +7 -0
- package/dist/runtime/RuntimeKSQL.js +22 -15
- package/dist/runtime/RuntimeMSSQL.d.ts +7 -1
- package/dist/runtime/RuntimeMSSQL.js +4 -4
- package/dist/runtime/RuntimeMySQL.d.ts +5 -2
- package/dist/runtime/RuntimeMySQL.js +13 -9
- package/dist/runtime/Stats.d.ts +12 -0
- package/dist/runtime/Stats.js +32 -0
- package/dist/runtime/lib/MSSQL.d.ts +2 -1
- package/dist/runtime/lib/MSSQL.js +11 -6
- package/dist/runtime/lib/MySQL.d.ts +1 -1
- package/dist/runtime/lib/MySQL.js +15 -2
- package/dist/runtime/lib/shared.js +99 -37
- package/dist/runtime/lib/stringifyWhere.js +1 -1
- package/package.json +7 -5
|
@@ -17,6 +17,8 @@ const SqlString = require("sqlstring");
|
|
|
17
17
|
const Cache_1 = require("./Cache");
|
|
18
18
|
const MySQL_1 = require("./lib/MySQL");
|
|
19
19
|
const shared_1 = require("./lib/shared");
|
|
20
|
+
const loglevel_1 = require("loglevel");
|
|
21
|
+
loglevel_1.default.setDefaultLevel("INFO");
|
|
20
22
|
class RuntimeMySQL {
|
|
21
23
|
constructor(clientOpts, otherOpts, artifacts) {
|
|
22
24
|
_RuntimeMySQL_dialect.set(this, "mysql");
|
|
@@ -24,9 +26,8 @@ class RuntimeMySQL {
|
|
|
24
26
|
_RuntimeMySQL_clientCache.set(this, void 0);
|
|
25
27
|
_RuntimeMySQL_middlewareHandler.set(this, void 0);
|
|
26
28
|
__classPrivateFieldSet(this, _RuntimeMySQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
__classPrivateFieldSet(this, _RuntimeMySQL_clientCache, new Cache_1.default(otherOpts.redisHost, debugCache), "f");
|
|
29
|
+
if (otherOpts.redis)
|
|
30
|
+
__classPrivateFieldSet(this, _RuntimeMySQL_clientCache, new Cache_1.default(otherOpts.redis, clientOpts?.debug), "f");
|
|
30
31
|
if (otherOpts.supplementClientOpts) {
|
|
31
32
|
clientOpts = {
|
|
32
33
|
supportBigNumbers: true,
|
|
@@ -49,7 +50,7 @@ class RuntimeMySQL {
|
|
|
49
50
|
}
|
|
50
51
|
return next();
|
|
51
52
|
},
|
|
52
|
-
...clientOpts
|
|
53
|
+
...clientOpts
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
@@ -63,13 +64,13 @@ class RuntimeMySQL {
|
|
|
63
64
|
}
|
|
64
65
|
return next();
|
|
65
66
|
},
|
|
66
|
-
...clientOpts
|
|
67
|
+
...clientOpts
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
__classPrivateFieldSet(this, _RuntimeMySQL_mysqlClient, new MySQL_1.MySQL(clientOpts), "f");
|
|
70
71
|
}
|
|
71
72
|
async resolve(input) {
|
|
72
|
-
return (0, shared_1.resolve)(input, this.dbCall.bind(this), this.formatQuery.bind(this), this.
|
|
73
|
+
return (0, shared_1.resolve)(input, input.dbCall ?? this.dbCall.bind(this), this.formatQuery.bind(this), this.$startTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMySQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMySQL_middlewareHandler, "f"), input.context ?? {}, __classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f"));
|
|
73
74
|
}
|
|
74
75
|
async $queryRaw(sql, values) {
|
|
75
76
|
return this.dbCall(this.formatQuery(sql, values ?? []));
|
|
@@ -84,17 +85,20 @@ class RuntimeMySQL {
|
|
|
84
85
|
return (0, shared_1._prepareWhere)(artifacts, table, data, this.dbCall.bind(this), this.formatQuery.bind(this));
|
|
85
86
|
}
|
|
86
87
|
async $shutdown() {
|
|
88
|
+
if (__classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f")) {
|
|
89
|
+
await __classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f").shutdown();
|
|
90
|
+
}
|
|
87
91
|
await __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").endPool();
|
|
88
92
|
}
|
|
93
|
+
async $startTransaction(input) {
|
|
94
|
+
return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").beginTransaction(input?.isolationLevel);
|
|
95
|
+
}
|
|
89
96
|
dbCall(q) {
|
|
90
97
|
return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").query(q);
|
|
91
98
|
}
|
|
92
99
|
formatQuery(q, values) {
|
|
93
100
|
return SqlString.format(q, values);
|
|
94
101
|
}
|
|
95
|
-
beginTransaction() {
|
|
96
|
-
return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").beginTransaction();
|
|
97
|
-
}
|
|
98
102
|
}
|
|
99
103
|
exports.RuntimeMySQL = RuntimeMySQL;
|
|
100
104
|
_RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_mysqlClient = new WeakMap(), _RuntimeMySQL_clientCache = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Redis, { Cluster } from "ioredis";
|
|
2
|
+
declare class Stats {
|
|
3
|
+
client: Redis | Cluster;
|
|
4
|
+
constructor(client: Redis | Cluster);
|
|
5
|
+
updateStats: (ms: number, category: string) => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
declare namespace timer {
|
|
8
|
+
type Callback = (time: number, ...params: any[]) => void;
|
|
9
|
+
type Params<T> = T extends (ms: number, ...params: infer U) => any ? U : never;
|
|
10
|
+
}
|
|
11
|
+
export declare function timer(): <T extends timer.Callback>(callback: T, ...args: timer.Params<T>) => void;
|
|
12
|
+
export default Stats;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timer = void 0;
|
|
4
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
5
|
+
class Stats {
|
|
6
|
+
constructor(client) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
this.updateStats = async (ms, category) => {
|
|
9
|
+
const redis = this.client;
|
|
10
|
+
const requests = Number(await redis.get(`stats:${category}_requests`)) || 0;
|
|
11
|
+
const average = Number(await redis.get(`stats:${category}_avg`)) || 0;
|
|
12
|
+
const max = Number(await redis.get(`stats:${category}_max`)) || 0;
|
|
13
|
+
const min = Number(await redis.get(`stats:${category}_min`)) || Infinity;
|
|
14
|
+
const newTotalRequests = requests + 1;
|
|
15
|
+
const newAverage = (average * requests + ms) / newTotalRequests;
|
|
16
|
+
await redis.set(`stats:${category}_requests`, newTotalRequests);
|
|
17
|
+
await redis.set(`stats:${category}_avg`, newAverage);
|
|
18
|
+
if (ms > max)
|
|
19
|
+
await redis.set(`stats:${category}_max`, ms);
|
|
20
|
+
if (ms < min)
|
|
21
|
+
await redis.set(`stats:${category}_min`, ms);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function timer() {
|
|
26
|
+
const start = perf_hooks_1.performance.now();
|
|
27
|
+
return (callback, ...args) => {
|
|
28
|
+
callback(perf_hooks_1.performance.now() - start, ...args);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
exports.timer = timer;
|
|
32
|
+
exports.default = Stats;
|
|
@@ -5,8 +5,9 @@ export declare class MSSQL {
|
|
|
5
5
|
dbCall(q: string): Promise<any>;
|
|
6
6
|
private mapResult;
|
|
7
7
|
formatQuery(q: string, values: any[]): any;
|
|
8
|
-
beginTransaction(): Promise<{
|
|
8
|
+
beginTransaction(isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE"): Promise<{
|
|
9
9
|
commit: () => Promise<void>;
|
|
10
|
+
rollback: () => Promise<void>;
|
|
10
11
|
dbCall: (q: string) => Promise<any>;
|
|
11
12
|
}>;
|
|
12
13
|
closePool(): Promise<void>;
|
|
@@ -42,7 +42,7 @@ class MSSQL {
|
|
|
42
42
|
formatQuery(q, values) {
|
|
43
43
|
return TSqlString.format(q, values);
|
|
44
44
|
}
|
|
45
|
-
async beginTransaction() {
|
|
45
|
+
async beginTransaction(isolationLevel) {
|
|
46
46
|
const transaction = new mssql.Transaction(__classPrivateFieldGet(this, _MSSQL_pool, "f"));
|
|
47
47
|
let rolledBack = false;
|
|
48
48
|
transaction.on("rollback", (aborted) => {
|
|
@@ -56,13 +56,18 @@ class MSSQL {
|
|
|
56
56
|
throw err;
|
|
57
57
|
}
|
|
58
58
|
const mapResult = this.mapResult.bind(this);
|
|
59
|
-
|
|
59
|
+
let isolationLevelNumber;
|
|
60
|
+
if (isolationLevel) {
|
|
61
|
+
isolationLevelNumber = mssql.ISOLATION_LEVEL[isolationLevel.replace(" ", "_")];
|
|
62
|
+
if (isolationLevelNumber == null) {
|
|
63
|
+
throw new Error(`Invalid isolationLevel: ${isolationLevel}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
await transaction.begin(isolationLevelNumber);
|
|
60
67
|
return {
|
|
61
68
|
commit: () => transaction.commit().catch(handleError),
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.then(mapResult)
|
|
65
|
-
.catch(handleError),
|
|
69
|
+
rollback: () => transaction.rollback(),
|
|
70
|
+
dbCall: (q) => new mssql.Request(transaction).query(q).then(mapResult).catch(handleError)
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
async closePool() {
|
|
@@ -2,7 +2,7 @@ export declare class MySQL {
|
|
|
2
2
|
pool: any;
|
|
3
3
|
constructor(opts: any);
|
|
4
4
|
query(...args: any[]): any;
|
|
5
|
-
beginTransaction(): Promise<any>;
|
|
5
|
+
beginTransaction(isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE"): Promise<any>;
|
|
6
6
|
getConnection(): Promise<any>;
|
|
7
7
|
endPool(): Promise<void>;
|
|
8
8
|
}
|
|
@@ -13,16 +13,29 @@ class MySQL {
|
|
|
13
13
|
query(...args) {
|
|
14
14
|
return P.using(this.getConnection(), (connection) => connection.queryAsync(...args));
|
|
15
15
|
}
|
|
16
|
-
async beginTransaction() {
|
|
16
|
+
async beginTransaction(isolationLevel) {
|
|
17
17
|
return P.using(this.getConnection(), async (connection) => {
|
|
18
18
|
async function handleError(err) {
|
|
19
19
|
await connection.rollbackAsync();
|
|
20
20
|
throw err;
|
|
21
21
|
}
|
|
22
|
+
// https://dev.mysql.com/doc/refman/8.0/en/set-transaction.html#set-transaction-isolation-level
|
|
23
|
+
// Without any SESSION or GLOBAL keyword:
|
|
24
|
+
// The statement applies only to the next single transaction performed within the session.
|
|
25
|
+
if (isolationLevel != null) {
|
|
26
|
+
if (isolationLevel !== "READ UNCOMMITTED" &&
|
|
27
|
+
isolationLevel !== "READ COMMITTED" &&
|
|
28
|
+
isolationLevel !== "REPEATABLE READ" &&
|
|
29
|
+
isolationLevel !== "SERIALIZABLE") {
|
|
30
|
+
throw new Error(`Invalid isolationLevel: ${isolationLevel}`);
|
|
31
|
+
}
|
|
32
|
+
await connection.queryAsync(`SET TRANSACTION ISOLATION LEVEL ${isolationLevel};`);
|
|
33
|
+
}
|
|
22
34
|
await connection.beginTransactionAsync();
|
|
23
35
|
return {
|
|
24
36
|
commit: () => connection.commitAsync().catch(handleError),
|
|
25
|
-
|
|
37
|
+
rollback: () => connection.rollbackAsync(),
|
|
38
|
+
dbCall: (q) => connection.queryAsync(q).catch(handleError)
|
|
26
39
|
};
|
|
27
40
|
});
|
|
28
41
|
}
|
|
@@ -22,6 +22,7 @@ const SDKNotFoundError_1 = require("./SDKNotFoundError");
|
|
|
22
22
|
const SDKBadWhereError_1 = require("./SDKBadWhereError");
|
|
23
23
|
const stringifyWhere_1 = require("./stringifyWhere");
|
|
24
24
|
const getOrderBy_1 = require("./getOrderBy");
|
|
25
|
+
const Stats_1 = require("../Stats");
|
|
25
26
|
async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, middlewareHandler, context, cache) {
|
|
26
27
|
// https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
|
|
27
28
|
let index = -1;
|
|
@@ -38,17 +39,45 @@ async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, mi
|
|
|
38
39
|
};
|
|
39
40
|
return resource.runInAsyncScope(() => consumer(params));
|
|
40
41
|
}
|
|
42
|
+
if (input?.nullability) {
|
|
43
|
+
return _nullResolve(input);
|
|
44
|
+
}
|
|
41
45
|
return _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context, cache);
|
|
42
46
|
}
|
|
43
47
|
exports.resolve = resolve;
|
|
48
|
+
async function _nullResolve(input) {
|
|
49
|
+
const { nullability } = input;
|
|
50
|
+
if (typeof nullability !== "object" || nullability == null) {
|
|
51
|
+
throw new Error("Invalid nullability");
|
|
52
|
+
}
|
|
53
|
+
const table = input.resource;
|
|
54
|
+
const tableConfig = nullability[table];
|
|
55
|
+
if (tableConfig == null) {
|
|
56
|
+
throw new Error(`Response not configured for \`${table}\`.`);
|
|
57
|
+
}
|
|
58
|
+
const { action } = input;
|
|
59
|
+
const responseFn = tableConfig[action];
|
|
60
|
+
if (responseFn == null) {
|
|
61
|
+
throw new Error(`Response not configured for \`${action}\`, \`${table}\`.`);
|
|
62
|
+
}
|
|
63
|
+
if (typeof responseFn !== "function") {
|
|
64
|
+
throw new Error(`Invalid configured response for \`${action}\`, \`${table}\`: not a function.`);
|
|
65
|
+
}
|
|
66
|
+
return responseFn({
|
|
67
|
+
operation: action,
|
|
68
|
+
model: table,
|
|
69
|
+
args: { select: input.fields, where: input.args?.$where }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
44
72
|
function _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context, cache) {
|
|
45
73
|
switch (input.action) {
|
|
46
|
-
case "findUnique":
|
|
47
74
|
case "findMany":
|
|
75
|
+
return cache && !input.skipCache
|
|
76
|
+
? getCached(input, dbCall, formatQuery, dialect, cache)
|
|
77
|
+
: getData(input, dbCall, formatQuery, dialect);
|
|
78
|
+
case "findUnique":
|
|
48
79
|
case "findManyPaginated":
|
|
49
|
-
return
|
|
50
|
-
getCached(input, dbCall, formatQuery, dialect, cache) :
|
|
51
|
-
getData(input, dbCall, formatQuery, dialect);
|
|
80
|
+
return getData(input, dbCall, formatQuery, dialect);
|
|
52
81
|
case "create":
|
|
53
82
|
return create(input, dbCall, formatQuery, beginTransaction, dialect, context);
|
|
54
83
|
case "update":
|
|
@@ -114,7 +143,7 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
114
143
|
rowWithMatchingCursor = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
|
|
115
144
|
input.resource,
|
|
116
145
|
primaryKey,
|
|
117
|
-
(0, cursor_1.decodeCursor)(cursor)
|
|
146
|
+
(0, cursor_1.decodeCursor)(cursor)
|
|
118
147
|
])).then((xs) => xs[0]);
|
|
119
148
|
if (rowWithMatchingCursor == null) {
|
|
120
149
|
throw new Error(`Invalid cursor: ${cursor}`);
|
|
@@ -138,9 +167,9 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
138
167
|
dialect === "mssql" && paginationType === "limit-offset"
|
|
139
168
|
? {
|
|
140
169
|
orderBy: (0, getOrderBy_1.getOrderBy)(input.args, primaryKey)?.orderBy ?? [
|
|
141
|
-
{ column: primaryKey, direction: "asc" }
|
|
170
|
+
{ column: primaryKey, direction: "asc" }
|
|
142
171
|
],
|
|
143
|
-
flip: false
|
|
172
|
+
flip: false
|
|
144
173
|
}
|
|
145
174
|
: action === "findManyPaginated"
|
|
146
175
|
? (0, getOrderBy_1.getOrderBy)(input.args, primaryKey)
|
|
@@ -158,7 +187,7 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
158
187
|
orderBy: orderByListPaginatedRootResult?.orderBy,
|
|
159
188
|
rowWithMatchingCursor,
|
|
160
189
|
dialect,
|
|
161
|
-
grabMany
|
|
190
|
+
grabMany
|
|
162
191
|
});
|
|
163
192
|
const options = { dialect };
|
|
164
193
|
let { sql, shapeDefinition } = await (0, util_1.compileSqlAST)(sqlAST, context, options);
|
|
@@ -241,7 +270,7 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
241
270
|
// We don't want the where clause to include cursor-related stuff
|
|
242
271
|
rowWithMatchingCursor: null,
|
|
243
272
|
dialect,
|
|
244
|
-
grabMany: true
|
|
273
|
+
grabMany: true
|
|
245
274
|
});
|
|
246
275
|
// Because orderBy doesn't matter for total count.
|
|
247
276
|
// getOrderBy adds an element if paginating, so deleting args.$orderBy
|
|
@@ -266,30 +295,61 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
266
295
|
return data;
|
|
267
296
|
}
|
|
268
297
|
async function getCached(input, dbCall, formatQuery, dialect, cache) {
|
|
298
|
+
const done = (0, Stats_1.timer)();
|
|
299
|
+
const { stats } = cache;
|
|
269
300
|
const { request, cached } = await cache.from(input);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
301
|
+
let results;
|
|
302
|
+
if (cached) {
|
|
303
|
+
if (stats)
|
|
304
|
+
done(stats.updateStats, "get_redis");
|
|
305
|
+
results = cached;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
const remove = ensureUuidSelect(input);
|
|
309
|
+
results = await getData(input, dbCall, formatQuery, dialect);
|
|
310
|
+
if (!Array.isArray(results)) {
|
|
311
|
+
if ("results" in results)
|
|
312
|
+
results = results.results;
|
|
313
|
+
else {
|
|
314
|
+
throw new Error("Bad result returned by getData in SDK.");
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
for (const result of results)
|
|
318
|
+
for (const path of remove) {
|
|
319
|
+
let data = result;
|
|
320
|
+
for (const key of path)
|
|
321
|
+
data = data[key];
|
|
322
|
+
// delete data.uuid;
|
|
323
|
+
}
|
|
324
|
+
cache.insert(request, results);
|
|
325
|
+
if (stats)
|
|
326
|
+
done(stats.updateStats, "get_mysql");
|
|
327
|
+
}
|
|
328
|
+
if (stats)
|
|
329
|
+
done(stats.updateStats, "get");
|
|
275
330
|
return results;
|
|
276
331
|
}
|
|
277
332
|
function ensureUuidSelect(input) {
|
|
278
333
|
const { resource, artifacts } = input;
|
|
334
|
+
const remove = [];
|
|
279
335
|
ensure(resource, input);
|
|
280
|
-
function ensure(type, input) {
|
|
336
|
+
function ensure(type, input, path = []) {
|
|
281
337
|
const { scalarFields, relationFields } = artifacts[type];
|
|
282
338
|
if (!scalarFields.includes("uuid"))
|
|
283
339
|
return;
|
|
284
340
|
const fields = input.fields || [];
|
|
285
|
-
if (!fields.includes("uuid"))
|
|
341
|
+
if (!fields.includes("uuid")) {
|
|
342
|
+
remove.push(path);
|
|
286
343
|
fields.unshift("uuid");
|
|
344
|
+
}
|
|
287
345
|
for (const field of fields)
|
|
288
346
|
if (typeof field == "object") {
|
|
289
|
-
const {
|
|
290
|
-
|
|
347
|
+
const { name } = field;
|
|
348
|
+
const { table } = relationFields[name];
|
|
349
|
+
ensure(table, field, path.concat(name));
|
|
291
350
|
}
|
|
292
351
|
}
|
|
352
|
+
return remove;
|
|
293
353
|
}
|
|
294
354
|
function wrapListPaginationLimitOffset(data, totalCount) {
|
|
295
355
|
return { paginationInfo: { totalCount }, results: data };
|
|
@@ -320,9 +380,9 @@ function wrapListPaginationCursor(data, args, flip, cb, primaryKey, totalCount)
|
|
|
320
380
|
hasNextPage,
|
|
321
381
|
startCursor,
|
|
322
382
|
endCursor,
|
|
323
|
-
totalCount
|
|
383
|
+
totalCount
|
|
324
384
|
},
|
|
325
|
-
results: data
|
|
385
|
+
results: data
|
|
326
386
|
};
|
|
327
387
|
}
|
|
328
388
|
async function getTotalCount(sqlASTTotalCount, dbCall, context, options) {
|
|
@@ -333,8 +393,8 @@ async function getTotalCount(sqlASTTotalCount, dbCall, context, options) {
|
|
|
333
393
|
type: "expression",
|
|
334
394
|
sqlExpr: () => "COUNT(*)",
|
|
335
395
|
fieldName: fieldNameTotalCount,
|
|
336
|
-
as: fieldNameTotalCount
|
|
337
|
-
}
|
|
396
|
+
as: fieldNameTotalCount
|
|
397
|
+
}
|
|
338
398
|
];
|
|
339
399
|
const { sql: sqlTotalCount } = await (0, util_1.compileSqlAST)(sqlASTTotalCount, context, options);
|
|
340
400
|
const totalCount = await dbCall(sqlTotalCount).then((xs) => xs[0][fieldNameTotalCount]);
|
|
@@ -475,7 +535,7 @@ function getCreateTree(data, table, referencedKey, specialCaseUuidColumn, dialec
|
|
|
475
535
|
referencedKey,
|
|
476
536
|
columns: [],
|
|
477
537
|
values: [],
|
|
478
|
-
children: []
|
|
538
|
+
children: []
|
|
479
539
|
};
|
|
480
540
|
for (let i = 0; i < data.length; i++) {
|
|
481
541
|
let d = data[i];
|
|
@@ -608,7 +668,9 @@ async function updateMany(input, dbCall, formatQuery, dialect, cache) {
|
|
|
608
668
|
}
|
|
609
669
|
if (cache)
|
|
610
670
|
try {
|
|
611
|
-
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [
|
|
671
|
+
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [
|
|
672
|
+
input.resource
|
|
673
|
+
]);
|
|
612
674
|
const matches = await dbCall(query);
|
|
613
675
|
const uuids = matches.map((x) => x.uuid);
|
|
614
676
|
cache.purge(...uuids);
|
|
@@ -648,7 +710,7 @@ async function deleteOne(input, dbCall, formatQuery, dialect, cache) {
|
|
|
648
710
|
const current = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
|
|
649
711
|
input.resource,
|
|
650
712
|
findOne.key,
|
|
651
|
-
findOne.value
|
|
713
|
+
findOne.value
|
|
652
714
|
])).then((xs) => xs[0]);
|
|
653
715
|
if (current == null) {
|
|
654
716
|
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
@@ -658,7 +720,7 @@ async function deleteOne(input, dbCall, formatQuery, dialect, cache) {
|
|
|
658
720
|
await dbCall(formatQuery("DELETE FROM ?? WHERE ?? = ?", [
|
|
659
721
|
input.resource,
|
|
660
722
|
findOne.key,
|
|
661
|
-
findOne.value
|
|
723
|
+
findOne.value
|
|
662
724
|
]));
|
|
663
725
|
return true;
|
|
664
726
|
}
|
|
@@ -670,7 +732,9 @@ async function deleteMany(input, dbCall, formatQuery, dialect, cache) {
|
|
|
670
732
|
}
|
|
671
733
|
if (cache)
|
|
672
734
|
try {
|
|
673
|
-
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [
|
|
735
|
+
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [
|
|
736
|
+
input.resource
|
|
737
|
+
]);
|
|
674
738
|
const matches = await dbCall(query);
|
|
675
739
|
const uuids = matches.map((x) => x.uuid);
|
|
676
740
|
cache.purge(...uuids);
|
|
@@ -719,7 +783,7 @@ async function mapMappedFields(artifactsForTable, data, dbCall, formatQuery) {
|
|
|
719
783
|
mappedField.referencedKey,
|
|
720
784
|
mappedField.referencedTable,
|
|
721
785
|
mappedField.name,
|
|
722
|
-
w
|
|
786
|
+
w
|
|
723
787
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
724
788
|
if (result == null) {
|
|
725
789
|
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
@@ -733,7 +797,7 @@ async function mapMappedFields(artifactsForTable, data, dbCall, formatQuery) {
|
|
|
733
797
|
mappedField.referencedKey,
|
|
734
798
|
mappedField.referencedTable,
|
|
735
799
|
mappedField.name,
|
|
736
|
-
v
|
|
800
|
+
v
|
|
737
801
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
738
802
|
if (result == null) {
|
|
739
803
|
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
@@ -765,9 +829,7 @@ function removeExtraKeys(data, fields) {
|
|
|
765
829
|
fieldKeys.push(x.as ?? x.name);
|
|
766
830
|
}
|
|
767
831
|
}
|
|
768
|
-
const dataKeys = Array.isArray(data)
|
|
769
|
-
? Object.keys(data[0])
|
|
770
|
-
: Object.keys(data);
|
|
832
|
+
const dataKeys = Array.isArray(data) ? Object.keys(data[0]) : Object.keys(data);
|
|
771
833
|
const extraDataKeys = _.difference(dataKeys, fieldKeys);
|
|
772
834
|
for (let k of extraDataKeys) {
|
|
773
835
|
if (Array.isArray(data)) {
|
|
@@ -815,7 +877,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
815
877
|
mappedField.referencedKey,
|
|
816
878
|
mappedField.referencedTable,
|
|
817
879
|
mappedField.name,
|
|
818
|
-
v
|
|
880
|
+
v
|
|
819
881
|
])).then((xs) => xs[0]?.[mappedField.referencedKey])));
|
|
820
882
|
if (newVal.some((x) => x == null)) {
|
|
821
883
|
const index = newVal.findIndex((x) => x == null);
|
|
@@ -834,7 +896,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
834
896
|
mappedField.referencedKey,
|
|
835
897
|
mappedField.referencedTable,
|
|
836
898
|
mappedField.name,
|
|
837
|
-
where
|
|
899
|
+
where
|
|
838
900
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
839
901
|
if (newVal == null) {
|
|
840
902
|
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, where));
|
|
@@ -857,7 +919,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
857
919
|
mappedField.referencedKey,
|
|
858
920
|
mappedField.referencedTable,
|
|
859
921
|
mappedField.name,
|
|
860
|
-
v
|
|
922
|
+
v
|
|
861
923
|
])).then((xs) => xs[0]?.[mappedField.referencedKey])));
|
|
862
924
|
if (newVal.some((x) => x == null)) {
|
|
863
925
|
const index = newVal.findIndex((x) => x == null);
|
|
@@ -876,7 +938,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
876
938
|
mappedField.referencedKey,
|
|
877
939
|
mappedField.referencedTable,
|
|
878
940
|
mappedField.name,
|
|
879
|
-
where
|
|
941
|
+
where
|
|
880
942
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
881
943
|
if (newVal == null) {
|
|
882
944
|
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, where));
|
|
@@ -908,7 +970,7 @@ const ops = [
|
|
|
908
970
|
"$like",
|
|
909
971
|
"$nlike",
|
|
910
972
|
"$btwn",
|
|
911
|
-
"$nbtwn"
|
|
973
|
+
"$nbtwn"
|
|
912
974
|
];
|
|
913
975
|
async function traverseWhere(where, cb) {
|
|
914
976
|
return await _traverseWhere(cb, where, "", where);
|
|
@@ -96,7 +96,7 @@ function _stringifyWhere(where, table, escapeId, escape, result) {
|
|
|
96
96
|
}
|
|
97
97
|
const operator = keys[0];
|
|
98
98
|
const operand = v[operator];
|
|
99
|
-
if (operator === "$
|
|
99
|
+
if (operator === "$neq") {
|
|
100
100
|
return `${table}.${escapeId(k)} ${getOperatorNeq(v)} ${printValue(operand)}`;
|
|
101
101
|
}
|
|
102
102
|
if (operator === "$gt") {
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@technicity/data-service-generator",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
7
7
|
],
|
|
8
8
|
"scripts": {
|
|
9
9
|
"compile": "rm -rf dist && tsc",
|
|
10
|
-
"publish:next": "npm version
|
|
10
|
+
"publish:next": "npm version prerelease --preid next",
|
|
11
11
|
"preversion": "npm run compile",
|
|
12
|
-
"
|
|
12
|
+
"reset": "docker-compose rm -svf mysql57 && docker-compose up -d mysql57",
|
|
13
|
+
"test:docker": "docker-compose exec test yarn test:sdk",
|
|
13
14
|
"generate": "npm run compile && concurrently \"node ./test/mysql/generate.js\" \"node ./test/mysql8/generate.js\"",
|
|
14
15
|
"test": "npm run generate && mocha ./test/addNullFallbacks.test.js && mocha ./test/stringifyWhere.test.js && npm run test:sdk",
|
|
15
16
|
"test:prepare": "docker-compose down --volumes && docker-compose up -d --build",
|
|
16
|
-
"test:sdk": "mocha ./test/test.js"
|
|
17
|
+
"test:sdk": "mocha --inspect=0.0.0.0:9229 ./test/test.js"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"bluebird": "^3.7.2",
|
|
@@ -21,13 +22,14 @@
|
|
|
21
22
|
"fs-extra": "10.0.0",
|
|
22
23
|
"graphql": "15.8.0",
|
|
23
24
|
"graphql-relay": "^0.9.0",
|
|
25
|
+
"ioredis": "^5.2.4",
|
|
24
26
|
"join-monster": "git+https://github.com/apalm/join-monster.git#3e93d7028ccbf50f728577b2290b5f2638b639cb",
|
|
25
27
|
"json-schema-to-typescript": "10.1.5",
|
|
26
28
|
"lodash": "^4.17.20",
|
|
29
|
+
"loglevel": "^1.8.1",
|
|
27
30
|
"mssql": "^6.3.1",
|
|
28
31
|
"mysql": "^2.18.1",
|
|
29
32
|
"prettier": "^2.1.2",
|
|
30
|
-
"redis": "^4.3.0",
|
|
31
33
|
"sqlstring": "^2.3.2",
|
|
32
34
|
"tsqlstring": "^1.0.1",
|
|
33
35
|
"uuid": "^8.3.2"
|