@technicity/data-service-generator 0.8.5 → 0.10.0-next.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/dist/generation/generate.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/runtime/Cache.d.ts +18 -0
- package/dist/runtime/Cache.js +90 -0
- package/dist/runtime/RuntimeMySQL.d.ts +1 -0
- package/dist/runtime/RuntimeMySQL.js +8 -3
- package/dist/runtime/lib/SDKBadWhereError.d.ts +4 -0
- package/dist/runtime/lib/SDKBadWhereError.js +10 -0
- package/dist/runtime/lib/shared.d.ts +2 -1
- package/dist/runtime/lib/shared.js +95 -36
- package/dist/runtime/lib/utility.d.ts +5 -0
- package/dist/runtime/lib/utility.js +15 -0
- package/package.json +7 -6
|
@@ -9,6 +9,7 @@ const prettier = require("prettier");
|
|
|
9
9
|
const changeCase = require("change-case");
|
|
10
10
|
const fse = require("fs-extra");
|
|
11
11
|
const _ = require("lodash/fp");
|
|
12
|
+
const uuid_1 = require("uuid");
|
|
12
13
|
const mssql = require("mssql");
|
|
13
14
|
// @ts-ignore
|
|
14
15
|
const TSqlString = require("tsqlstring");
|
|
@@ -83,7 +84,7 @@ async function generate(input) {
|
|
|
83
84
|
typescript: require("../../package.json").devDependencies.typescript,
|
|
84
85
|
},
|
|
85
86
|
};
|
|
86
|
-
const tmpDirPath = path.join(os.tmpdir(), `dsg-${
|
|
87
|
+
const tmpDirPath = path.join(os.tmpdir(), `dsg-${(0, uuid_1.v4)()}`);
|
|
87
88
|
fse.mkdirpSync(tmpDirPath);
|
|
88
89
|
fs.writeFileSync(path.join(tmpDirPath, sdkFilename), sdkSource);
|
|
89
90
|
fs.writeFileSync(path.join(tmpDirPath, artifactsFilename), artifactsSource);
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.traverseFieldArgs = exports.SDKNotFoundError = exports.generate = void 0;
|
|
3
|
+
exports.traverseFieldArgs = exports.SDKBadWhereError = exports.SDKNotFoundError = exports.generate = void 0;
|
|
4
4
|
var generate_1 = require("./generation/generate");
|
|
5
5
|
Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generate_1.generate; } });
|
|
6
6
|
var SDKNotFoundError_1 = require("./runtime/lib/SDKNotFoundError");
|
|
7
7
|
Object.defineProperty(exports, "SDKNotFoundError", { enumerable: true, get: function () { return SDKNotFoundError_1.SDKNotFoundError; } });
|
|
8
|
+
var SDKBadWhereError_1 = require("./runtime/lib/SDKBadWhereError");
|
|
9
|
+
Object.defineProperty(exports, "SDKBadWhereError", { enumerable: true, get: function () { return SDKBadWhereError_1.SDKBadWhereError; } });
|
|
8
10
|
var traverseFieldArgs_1 = require("./traverseFieldArgs");
|
|
9
11
|
Object.defineProperty(exports, "traverseFieldArgs", { enumerable: true, get: function () { return traverseFieldArgs_1.traverseFieldArgs; } });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RedisClientType } from 'redis';
|
|
2
|
+
import { TResolveParams } from './IRuntime';
|
|
3
|
+
declare class Cache {
|
|
4
|
+
protected logs?: boolean | undefined;
|
|
5
|
+
client: RedisClientType;
|
|
6
|
+
waiting?: Set<() => void> | undefined;
|
|
7
|
+
constructor(url: string, logs?: boolean | undefined);
|
|
8
|
+
log(message: string): void;
|
|
9
|
+
pending(): Promise<void>;
|
|
10
|
+
from(input: TResolveParams): Promise<{
|
|
11
|
+
request: string;
|
|
12
|
+
cached: any;
|
|
13
|
+
}>;
|
|
14
|
+
insert(key: string, payload: any): Promise<void>;
|
|
15
|
+
read(key: string): Promise<any>;
|
|
16
|
+
purge(...uuids: string[]): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export default Cache;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const crypto_1 = require("crypto");
|
|
4
|
+
const redis_1 = require("redis");
|
|
5
|
+
const utility_1 = require("./lib/utility");
|
|
6
|
+
class Cache {
|
|
7
|
+
constructor(url, logs) {
|
|
8
|
+
this.logs = logs;
|
|
9
|
+
this.waiting = new Set();
|
|
10
|
+
this.client = (0, redis_1.createClient)({ url: `redis://${url}` });
|
|
11
|
+
this.client.connect();
|
|
12
|
+
this.client.on("connect", () => {
|
|
13
|
+
if (this.waiting)
|
|
14
|
+
this.waiting.forEach(x => x());
|
|
15
|
+
this.waiting = undefined;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
log(message) {
|
|
19
|
+
if (this.logs)
|
|
20
|
+
console.log(message);
|
|
21
|
+
}
|
|
22
|
+
async pending() {
|
|
23
|
+
if (this.waiting)
|
|
24
|
+
return new Promise(res => this.waiting.add(res));
|
|
25
|
+
}
|
|
26
|
+
async from(input) {
|
|
27
|
+
let { action, args, fields, resource } = input;
|
|
28
|
+
const request = JSON.stringify({
|
|
29
|
+
action, resource, args, fields
|
|
30
|
+
});
|
|
31
|
+
const key = (0, crypto_1.createHash)('sha256')
|
|
32
|
+
.update(request)
|
|
33
|
+
.digest('hex');
|
|
34
|
+
const cached = await this.read(key);
|
|
35
|
+
return {
|
|
36
|
+
request: key,
|
|
37
|
+
cached
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async insert(key, payload) {
|
|
41
|
+
const redis = this.client;
|
|
42
|
+
const json = JSON.stringify(payload);
|
|
43
|
+
const regex = /"uuid":"(.+?)"/g;
|
|
44
|
+
const pending = [];
|
|
45
|
+
for (let result; result = regex.exec(json);) {
|
|
46
|
+
const uuid = result[1];
|
|
47
|
+
if (!uuid)
|
|
48
|
+
continue;
|
|
49
|
+
pending.push(redis.sAdd(`deps:${uuid}`, [key]), redis.sAdd(`cached:${key}`, [uuid]));
|
|
50
|
+
}
|
|
51
|
+
if (!pending.length)
|
|
52
|
+
return;
|
|
53
|
+
this.log(`Cache insert: ${key.substring(0, 6)}`);
|
|
54
|
+
await Promise.all([
|
|
55
|
+
redis.set(`cache:${key}`, json),
|
|
56
|
+
...pending
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
async read(key) {
|
|
60
|
+
await this.pending();
|
|
61
|
+
const data = await this.client.get(`cache:${key}`);
|
|
62
|
+
const shorthand = key.substring(0, 6);
|
|
63
|
+
if (data) {
|
|
64
|
+
this.log(`Cache hit: ${shorthand}`);
|
|
65
|
+
return JSON.parse(data);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.log(`Cache miss: ${shorthand}`);
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async purge(...uuids) {
|
|
73
|
+
const redis = this.client;
|
|
74
|
+
await (0, utility_1.mapAsync)(uuids, uuid => {
|
|
75
|
+
const getDependancies = redis.sMembers(`deps:${uuid}`);
|
|
76
|
+
return [
|
|
77
|
+
(0, utility_1.mapAsync)(getDependancies, key => {
|
|
78
|
+
const getDependants = redis.sMembers(`cached:${key}`);
|
|
79
|
+
return [
|
|
80
|
+
(0, utility_1.mapAsync)(getDependants, uuid => (redis.sRem(`deps:${uuid}`, [key]))),
|
|
81
|
+
redis.del(`cache:${key}`),
|
|
82
|
+
redis.del(`cached:${key}`)
|
|
83
|
+
];
|
|
84
|
+
}),
|
|
85
|
+
redis.del(`deps:${uuid}`)
|
|
86
|
+
];
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.default = Cache;
|
|
@@ -5,6 +5,7 @@ export declare class RuntimeMySQL implements IRuntime {
|
|
|
5
5
|
[k: string]: any;
|
|
6
6
|
}, otherOpts: {
|
|
7
7
|
supplementClientOpts?: ISupplementClientOpts;
|
|
8
|
+
redisHost?: string;
|
|
8
9
|
}, artifacts: IArtifacts);
|
|
9
10
|
resolve(input: TResolveParams): Promise<any>;
|
|
10
11
|
$queryRaw(sql: string, values?: any[]): Promise<any>;
|
|
@@ -10,18 +10,23 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _RuntimeMySQL_dialect, _RuntimeMySQL_mysqlClient, _RuntimeMySQL_middlewareHandler;
|
|
13
|
+
var _RuntimeMySQL_dialect, _RuntimeMySQL_mysqlClient, _RuntimeMySQL_clientCache, _RuntimeMySQL_middlewareHandler;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RuntimeMySQL = void 0;
|
|
16
16
|
const SqlString = require("sqlstring");
|
|
17
|
+
const Cache_1 = require("./Cache");
|
|
17
18
|
const MySQL_1 = require("./lib/MySQL");
|
|
18
19
|
const shared_1 = require("./lib/shared");
|
|
19
20
|
class RuntimeMySQL {
|
|
20
21
|
constructor(clientOpts, otherOpts, artifacts) {
|
|
21
22
|
_RuntimeMySQL_dialect.set(this, "mysql");
|
|
22
23
|
_RuntimeMySQL_mysqlClient.set(this, void 0);
|
|
24
|
+
_RuntimeMySQL_clientCache.set(this, void 0);
|
|
23
25
|
_RuntimeMySQL_middlewareHandler.set(this, void 0);
|
|
24
26
|
__classPrivateFieldSet(this, _RuntimeMySQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
|
|
27
|
+
const debugCache = clientOpts?.debug?.includes("Cache");
|
|
28
|
+
if (otherOpts.redisHost)
|
|
29
|
+
__classPrivateFieldSet(this, _RuntimeMySQL_clientCache, new Cache_1.default(otherOpts.redisHost, debugCache), "f");
|
|
25
30
|
if (otherOpts.supplementClientOpts) {
|
|
26
31
|
clientOpts = {
|
|
27
32
|
supportBigNumbers: true,
|
|
@@ -64,7 +69,7 @@ class RuntimeMySQL {
|
|
|
64
69
|
__classPrivateFieldSet(this, _RuntimeMySQL_mysqlClient, new MySQL_1.MySQL(clientOpts), "f");
|
|
65
70
|
}
|
|
66
71
|
async resolve(input) {
|
|
67
|
-
return (0, shared_1.resolve)(input, this.dbCall.bind(this), this.formatQuery.bind(this), this.beginTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMySQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMySQL_middlewareHandler, "f"), input.context ?? {});
|
|
72
|
+
return (0, shared_1.resolve)(input, this.dbCall.bind(this), this.formatQuery.bind(this), this.beginTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMySQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMySQL_middlewareHandler, "f"), input.context ?? {}, __classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f"));
|
|
68
73
|
}
|
|
69
74
|
async $queryRaw(sql, values) {
|
|
70
75
|
return this.dbCall(this.formatQuery(sql, values ?? []));
|
|
@@ -92,4 +97,4 @@ class RuntimeMySQL {
|
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
exports.RuntimeMySQL = RuntimeMySQL;
|
|
95
|
-
_RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_mysqlClient = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
|
|
100
|
+
_RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_mysqlClient = new WeakMap(), _RuntimeMySQL_clientCache = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SDKBadWhereError = void 0;
|
|
4
|
+
const CustomError_1 = require("../../lib/CustomError");
|
|
5
|
+
class SDKBadWhereError extends CustomError_1.CustomError {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message || "Invalid $where");
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.SDKBadWhereError = SDKBadWhereError;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext } from "../IRuntime";
|
|
2
2
|
import type { TMiddleware, TResolveParams } from "../IRuntime";
|
|
3
|
-
|
|
3
|
+
import Cache from "../Cache";
|
|
4
|
+
export declare function resolve(input: TResolveParams, dbCall: TDbCall, formatQuery: TFormatQuery, beginTransaction: TBeginTransaction, dialect: IDialect, middlewareHandler: MiddlewareHandler<TMiddleware>, context: TContext, cache?: Cache): Promise<any>;
|
|
4
5
|
export declare class MiddlewareHandler<M extends Function> {
|
|
5
6
|
private _middlewares;
|
|
6
7
|
register(middleware: M): void;
|
|
@@ -19,9 +19,10 @@ const cursor_1 = require("./cursor");
|
|
|
19
19
|
const runTransforms_1 = require("./runTransforms");
|
|
20
20
|
const addNullFallbacks_1 = require("./addNullFallbacks");
|
|
21
21
|
const SDKNotFoundError_1 = require("./SDKNotFoundError");
|
|
22
|
+
const SDKBadWhereError_1 = require("./SDKBadWhereError");
|
|
22
23
|
const stringifyWhere_1 = require("./stringifyWhere");
|
|
23
24
|
const getOrderBy_1 = require("./getOrderBy");
|
|
24
|
-
async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, middlewareHandler, context) {
|
|
25
|
+
async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, middlewareHandler, context, cache) {
|
|
25
26
|
// https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
|
|
26
27
|
let index = -1;
|
|
27
28
|
if (middlewareHandler.length() > 0) {
|
|
@@ -33,39 +34,34 @@ async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, mi
|
|
|
33
34
|
return nextMiddleware(paramsMaybeMutated, consumer);
|
|
34
35
|
}
|
|
35
36
|
const paramsChanged = { ...input, ...params };
|
|
36
|
-
return _resolve(paramsChanged, dbCall, formatQuery, beginTransaction, dialect, context);
|
|
37
|
+
return _resolve(paramsChanged, dbCall, formatQuery, beginTransaction, dialect, context, cache);
|
|
37
38
|
};
|
|
38
39
|
return resource.runInAsyncScope(() => consumer(params));
|
|
39
40
|
}
|
|
40
|
-
return _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context);
|
|
41
|
+
return _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context, cache);
|
|
41
42
|
}
|
|
42
43
|
exports.resolve = resolve;
|
|
43
|
-
function _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
function _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context, cache) {
|
|
45
|
+
switch (input.action) {
|
|
46
|
+
case "findUnique":
|
|
47
|
+
case "findMany":
|
|
48
|
+
case "findManyPaginated":
|
|
49
|
+
return cache ?
|
|
50
|
+
getCached(input, dbCall, formatQuery, dialect, cache) :
|
|
51
|
+
getData(input, dbCall, formatQuery, dialect);
|
|
52
|
+
case "create":
|
|
53
|
+
return create(input, dbCall, formatQuery, beginTransaction, dialect, context);
|
|
54
|
+
case "update":
|
|
55
|
+
return update(input, dbCall, formatQuery, dialect, cache);
|
|
56
|
+
case "updateMany":
|
|
57
|
+
return updateMany(input, dbCall, formatQuery, dialect, cache);
|
|
58
|
+
case "delete":
|
|
59
|
+
return deleteOne(input, dbCall, formatQuery, dialect, cache);
|
|
60
|
+
case "deleteMany":
|
|
61
|
+
return deleteMany(input, dbCall, formatQuery, dialect, cache);
|
|
62
|
+
default:
|
|
63
|
+
throw new Error("Invalid action: " + input.action);
|
|
46
64
|
}
|
|
47
|
-
if (input.action === "findMany") {
|
|
48
|
-
return getData(input, dbCall, formatQuery, dialect);
|
|
49
|
-
}
|
|
50
|
-
if (input.action === "findManyPaginated") {
|
|
51
|
-
return getData(input, dbCall, formatQuery, dialect);
|
|
52
|
-
}
|
|
53
|
-
if (input.action === "create") {
|
|
54
|
-
return create(input, dbCall, formatQuery, beginTransaction, dialect, context);
|
|
55
|
-
}
|
|
56
|
-
if (input.action === "update") {
|
|
57
|
-
return update(input, dbCall, formatQuery, dialect);
|
|
58
|
-
}
|
|
59
|
-
if (input.action === "updateMany") {
|
|
60
|
-
return updateMany(input, dbCall, formatQuery, dialect);
|
|
61
|
-
}
|
|
62
|
-
if (input.action === "delete") {
|
|
63
|
-
return del(input, dbCall, formatQuery, dialect);
|
|
64
|
-
}
|
|
65
|
-
if (input.action === "deleteMany") {
|
|
66
|
-
return deleteMany(input, dbCall, formatQuery, dialect);
|
|
67
|
-
}
|
|
68
|
-
throw new Error("Invalid action: " + input.action);
|
|
69
65
|
}
|
|
70
66
|
class MiddlewareHandler {
|
|
71
67
|
constructor() {
|
|
@@ -269,6 +265,32 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
269
265
|
}
|
|
270
266
|
return data;
|
|
271
267
|
}
|
|
268
|
+
async function getCached(input, dbCall, formatQuery, dialect, cache) {
|
|
269
|
+
const { request, cached } = await cache.from(input);
|
|
270
|
+
if (cached)
|
|
271
|
+
return cached;
|
|
272
|
+
ensureUuidSelect(input);
|
|
273
|
+
const results = await getData(input, dbCall, formatQuery, dialect);
|
|
274
|
+
cache.insert(request, results);
|
|
275
|
+
return results;
|
|
276
|
+
}
|
|
277
|
+
function ensureUuidSelect(input) {
|
|
278
|
+
const { resource, artifacts } = input;
|
|
279
|
+
ensure(resource, input);
|
|
280
|
+
function ensure(type, input) {
|
|
281
|
+
const { scalarFields, relationFields } = artifacts[type];
|
|
282
|
+
if (!scalarFields.includes("uuid"))
|
|
283
|
+
return;
|
|
284
|
+
const fields = input.fields;
|
|
285
|
+
if (!fields.includes("uuid"))
|
|
286
|
+
fields.unshift("uuid");
|
|
287
|
+
for (const field of fields)
|
|
288
|
+
if (typeof field == "object") {
|
|
289
|
+
const { table } = relationFields[field.name];
|
|
290
|
+
ensure(table, field);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
272
294
|
function wrapListPaginationLimitOffset(data, totalCount) {
|
|
273
295
|
return { paginationInfo: { totalCount }, results: data };
|
|
274
296
|
}
|
|
@@ -485,7 +507,7 @@ function getCreateTree(data, table, referencedKey, specialCaseUuidColumn, dialec
|
|
|
485
507
|
}
|
|
486
508
|
return out;
|
|
487
509
|
}
|
|
488
|
-
async function update(input, dbCall, formatQuery, dialect) {
|
|
510
|
+
async function update(input, dbCall, formatQuery, dialect, cache) {
|
|
489
511
|
async function _update() {
|
|
490
512
|
const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
|
|
491
513
|
const tableArtifacts = input.artifacts[input.resource];
|
|
@@ -497,6 +519,8 @@ async function update(input, dbCall, formatQuery, dialect) {
|
|
|
497
519
|
if (current == null) {
|
|
498
520
|
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
499
521
|
}
|
|
522
|
+
if (cache && current.uuid)
|
|
523
|
+
cache.purge(current.uuid);
|
|
500
524
|
// Shallow clone, as we're going to mutate later
|
|
501
525
|
const data = { ...input.data };
|
|
502
526
|
if (hasMappedFields(input.artifacts, input.resource, data)) {
|
|
@@ -574,7 +598,7 @@ function getUpdateQuery(table, data, where, dialect, formatQuery) {
|
|
|
574
598
|
q += ` WHERE ${where}`;
|
|
575
599
|
return formatQuery(q, values);
|
|
576
600
|
}
|
|
577
|
-
async function updateMany(input, dbCall, formatQuery, dialect) {
|
|
601
|
+
async function updateMany(input, dbCall, formatQuery, dialect, cache) {
|
|
578
602
|
async function _updateMany() {
|
|
579
603
|
const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
|
|
580
604
|
const tableArtifacts = input.artifacts[input.resource];
|
|
@@ -582,6 +606,14 @@ async function updateMany(input, dbCall, formatQuery, dialect) {
|
|
|
582
606
|
if (where == null) {
|
|
583
607
|
throw new Error("Null where");
|
|
584
608
|
}
|
|
609
|
+
if (cache)
|
|
610
|
+
try {
|
|
611
|
+
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [input.resource]);
|
|
612
|
+
const matches = await dbCall(query);
|
|
613
|
+
const uuids = matches.map((x) => x.uuid);
|
|
614
|
+
cache.purge(...uuids);
|
|
615
|
+
}
|
|
616
|
+
catch (err) { }
|
|
585
617
|
// Shallow clone, as we're going to mutate later
|
|
586
618
|
const data = { ...input.data };
|
|
587
619
|
if (hasMappedFields(input.artifacts, input.resource, data)) {
|
|
@@ -610,7 +642,7 @@ async function updateMany(input, dbCall, formatQuery, dialect) {
|
|
|
610
642
|
await _updateMany();
|
|
611
643
|
return getData(input, dbCall, formatQuery, dialect);
|
|
612
644
|
}
|
|
613
|
-
async function
|
|
645
|
+
async function deleteOne(input, dbCall, formatQuery, dialect, cache) {
|
|
614
646
|
const _findOne = Object.entries(input.args.$where)[0];
|
|
615
647
|
const findOne = { key: _findOne[0], value: _findOne[1] };
|
|
616
648
|
const current = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
|
|
@@ -621,6 +653,8 @@ async function del(input, dbCall, formatQuery, dialect) {
|
|
|
621
653
|
if (current == null) {
|
|
622
654
|
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
623
655
|
}
|
|
656
|
+
if (cache && current.uuid)
|
|
657
|
+
cache.purge(current.uuid);
|
|
624
658
|
await dbCall(formatQuery("DELETE FROM ?? WHERE ?? = ?", [
|
|
625
659
|
input.resource,
|
|
626
660
|
findOne.key,
|
|
@@ -628,12 +662,20 @@ async function del(input, dbCall, formatQuery, dialect) {
|
|
|
628
662
|
]));
|
|
629
663
|
return true;
|
|
630
664
|
}
|
|
631
|
-
async function deleteMany(input, dbCall, formatQuery, dialect) {
|
|
665
|
+
async function deleteMany(input, dbCall, formatQuery, dialect, cache) {
|
|
632
666
|
const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
|
|
633
667
|
const where = (0, getWhere_1.getWhere)(escapeId(input.resource), input.args, dialect);
|
|
634
668
|
if (where == null) {
|
|
635
669
|
throw new Error("Null where");
|
|
636
670
|
}
|
|
671
|
+
if (cache)
|
|
672
|
+
try {
|
|
673
|
+
const query = formatQuery(`SELECT uuid FROM ?? WHERE ${where}`, [input.resource]);
|
|
674
|
+
const matches = await dbCall(query);
|
|
675
|
+
const uuids = matches.map((x) => x.uuid);
|
|
676
|
+
cache.purge(...uuids);
|
|
677
|
+
}
|
|
678
|
+
catch (err) { }
|
|
637
679
|
const sql = "DELETE FROM ?? WHERE " + where;
|
|
638
680
|
const values = [input.resource];
|
|
639
681
|
await dbCall(formatQuery(sql, values));
|
|
@@ -776,7 +818,14 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
776
818
|
v,
|
|
777
819
|
])).then((xs) => xs[0]?.[mappedField.referencedKey])));
|
|
778
820
|
if (newVal.some((x) => x == null)) {
|
|
779
|
-
|
|
821
|
+
const index = newVal.findIndex((x) => x == null);
|
|
822
|
+
if (index === -1) {
|
|
823
|
+
throw new SDKBadWhereError_1.SDKBadWhereError();
|
|
824
|
+
}
|
|
825
|
+
else {
|
|
826
|
+
const v = where[index];
|
|
827
|
+
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, v));
|
|
828
|
+
}
|
|
780
829
|
}
|
|
781
830
|
out = _.set(newPath, newVal, out);
|
|
782
831
|
}
|
|
@@ -788,7 +837,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
788
837
|
where,
|
|
789
838
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
790
839
|
if (newVal == null) {
|
|
791
|
-
throw new
|
|
840
|
+
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, where));
|
|
792
841
|
}
|
|
793
842
|
out = _.set(newPath, newVal, out);
|
|
794
843
|
}
|
|
@@ -811,7 +860,14 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
811
860
|
v,
|
|
812
861
|
])).then((xs) => xs[0]?.[mappedField.referencedKey])));
|
|
813
862
|
if (newVal.some((x) => x == null)) {
|
|
814
|
-
|
|
863
|
+
const index = newVal.findIndex((x) => x == null);
|
|
864
|
+
if (index === -1) {
|
|
865
|
+
throw new SDKBadWhereError_1.SDKBadWhereError();
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
const v = where[index];
|
|
869
|
+
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, v));
|
|
870
|
+
}
|
|
815
871
|
}
|
|
816
872
|
out = _.set(newPath, newVal, out);
|
|
817
873
|
}
|
|
@@ -823,7 +879,7 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
823
879
|
where,
|
|
824
880
|
])).then((xs) => xs[0]?.[mappedField.referencedKey]);
|
|
825
881
|
if (newVal == null) {
|
|
826
|
-
throw new
|
|
882
|
+
throw new SDKBadWhereError_1.SDKBadWhereError(getPrepareWhereNotFoundMessage(mappedField, where));
|
|
827
883
|
}
|
|
828
884
|
out = _.set(newPath, newVal, out);
|
|
829
885
|
}
|
|
@@ -837,6 +893,9 @@ async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
|
|
|
837
893
|
return out;
|
|
838
894
|
}
|
|
839
895
|
exports._prepareWhere = _prepareWhere;
|
|
896
|
+
function getPrepareWhereNotFoundMessage(mappedField, value) {
|
|
897
|
+
return `Not found: unable to map \`${mappedField.referencedTable}\`.\`${mappedField.name}\` to \`${mappedField.referencedTable}\`.\`${mappedField.referencedKey}\` for the value \`${value}\`.`;
|
|
898
|
+
}
|
|
840
899
|
const ops = [
|
|
841
900
|
"$eq",
|
|
842
901
|
"$neq",
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eagerly resolve and map input values then concatinate.
|
|
3
|
+
*/
|
|
4
|
+
export declare function mapAsync<T, R>(source: T[] | Promise<T[]>, mapFunction: (item: T) => R | R[] | Promise<R>[] | Promise<R | R[]>): Promise<R[]>;
|
|
5
|
+
export declare function flatten<T>(array: (T | T[])[]): T[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flatten = exports.mapAsync = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Eagerly resolve and map input values then concatinate.
|
|
6
|
+
*/
|
|
7
|
+
async function mapAsync(source, mapFunction) {
|
|
8
|
+
const output = (await source).map(mapFunction);
|
|
9
|
+
return Promise.all(flatten(output)).then(flatten);
|
|
10
|
+
}
|
|
11
|
+
exports.mapAsync = mapAsync;
|
|
12
|
+
function flatten(array) {
|
|
13
|
+
return [].concat(...array);
|
|
14
|
+
}
|
|
15
|
+
exports.flatten = flatten;
|
package/package.json
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@technicity/data-service-generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0-next.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
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"test": "
|
|
13
|
-
"test:sdk": "
|
|
14
|
-
"test:only": "npm run create-database && npm run test:sdk"
|
|
10
|
+
"generate": "npm run compile && concurrently \"node ./test/mysql/generate.js\" \"node ./test/mysql8/generate.js\"",
|
|
11
|
+
"test": "npm run generate && mocha ./test/addNullFallbacks.test.js && mocha ./test/stringifyWhere.test.js && npm run test:sdk",
|
|
12
|
+
"test:prepare": "docker-compose down --volumes && docker-compose up -d --build",
|
|
13
|
+
"test:sdk": "mocha ./test/test.js"
|
|
15
14
|
},
|
|
16
15
|
"dependencies": {
|
|
17
16
|
"bluebird": "^3.7.2",
|
|
@@ -25,6 +24,7 @@
|
|
|
25
24
|
"mssql": "^6.3.1",
|
|
26
25
|
"mysql": "^2.18.1",
|
|
27
26
|
"prettier": "^2.1.2",
|
|
27
|
+
"redis": "^4.3.0",
|
|
28
28
|
"sqlstring": "^2.3.2",
|
|
29
29
|
"tsqlstring": "^1.0.1",
|
|
30
30
|
"uuid": "^8.3.2"
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"@types/prettier": "^2.1.5",
|
|
38
38
|
"@types/sqlstring": "^2.2.1",
|
|
39
39
|
"@types/uuid": "^8.3.1",
|
|
40
|
+
"concurrently": "^7.1.0",
|
|
40
41
|
"env-cmd": "^10.1.0",
|
|
41
42
|
"mocha": "9.1.3",
|
|
42
43
|
"sinon": "12.0.1",
|