@technicity/data-service-generator 0.14.0 → 0.14.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.d.ts +0 -1
- package/dist/generation/generate.js +309 -917
- package/dist/ksql.d.ts +15 -0
- package/dist/ksql.js +55 -0
- package/dist/runtime/Cache.js +3 -6
- package/dist/runtime/IRuntime.d.ts +17 -46
- package/dist/runtime/RuntimeKSQL.d.ts +19 -0
- package/dist/runtime/RuntimeKSQL.js +446 -0
- package/dist/runtime/RuntimeMSSQL.d.ts +1 -7
- package/dist/runtime/RuntimeMSSQL.js +4 -4
- package/dist/runtime/RuntimeMySQL.d.ts +1 -3
- package/dist/runtime/RuntimeMySQL.js +7 -33
- package/dist/runtime/lib/MSSQL.d.ts +1 -2
- package/dist/runtime/lib/MSSQL.js +8 -36
- package/dist/runtime/lib/MySQL.d.ts +1 -1
- package/dist/runtime/lib/MySQL.js +2 -15
- package/dist/runtime/lib/getSqlAst.js +121 -158
- package/dist/runtime/lib/runTransforms.d.ts +2 -0
- package/dist/runtime/lib/runTransforms.js +36 -0
- package/dist/runtime/lib/shared.d.ts +2 -1
- package/dist/runtime/lib/shared.js +71 -180
- package/dist/runtime/lib/stringifyWhere.js +12 -39
- package/dist/runtime/lib/typeCastMSSQL.js +1 -24
- package/dist/traverseFieldArgs.d.ts +2 -2
- package/dist/traverseFieldArgs.js +3 -8
- package/package.json +4 -1
- package/dist/runtime/RuntimeSQLite.d.ts +0 -38
- package/dist/runtime/RuntimeSQLite.js +0 -135
- package/dist/runtime/lib/addNullFallbacks.test.d.ts +0 -1
- package/dist/runtime/lib/addNullFallbacks.test.js +0 -206
- package/dist/runtime/lib/stringifyWhere.test.d.ts +0 -1
- package/dist/runtime/lib/stringifyWhere.test.js +0 -236
- package/dist/traverseFieldArgs.test.d.ts +0 -1
- package/dist/traverseFieldArgs.test.js +0 -56
package/dist/ksql.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare type THeaders = {
|
|
2
|
+
[k: string]: any;
|
|
3
|
+
};
|
|
4
|
+
export declare class KSQL {
|
|
5
|
+
hostname: string;
|
|
6
|
+
port: number;
|
|
7
|
+
headers?: THeaders;
|
|
8
|
+
constructor(options: {
|
|
9
|
+
hostname: string;
|
|
10
|
+
port: number;
|
|
11
|
+
headers?: THeaders;
|
|
12
|
+
});
|
|
13
|
+
streamQuery(s: string): Promise<any[]>;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
package/dist/ksql.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KSQL = void 0;
|
|
4
|
+
const http2 = require("http2");
|
|
5
|
+
class KSQL {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.hostname = options.hostname;
|
|
8
|
+
this.port = options.port;
|
|
9
|
+
this.headers = options.headers;
|
|
10
|
+
}
|
|
11
|
+
async streamQuery(s) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const reqBody = JSON.stringify({
|
|
14
|
+
sql: s,
|
|
15
|
+
properties: {
|
|
16
|
+
"ksql.streams.auto.offset.reset": "earliest",
|
|
17
|
+
"ksql.query.pull.table.scan.enabled": true,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const client = http2.connect(`https://${this.hostname}:${this.port}`);
|
|
21
|
+
const req = client.request({
|
|
22
|
+
[http2.constants.HTTP2_HEADER_SCHEME]: "https",
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
"Content-Length": reqBody.length,
|
|
25
|
+
":method": "POST",
|
|
26
|
+
":path": `/query-stream`,
|
|
27
|
+
...this.headers,
|
|
28
|
+
});
|
|
29
|
+
req.setEncoding("utf8");
|
|
30
|
+
let columnNames = [];
|
|
31
|
+
let rows = [];
|
|
32
|
+
req.on("data", (d) => {
|
|
33
|
+
const resData = JSON.parse(d);
|
|
34
|
+
if (resData.error_code) {
|
|
35
|
+
return reject(new Error(resData.message));
|
|
36
|
+
}
|
|
37
|
+
if (resData.columnNames) {
|
|
38
|
+
columnNames = resData.columnNames;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
let out = {};
|
|
42
|
+
resData.forEach((rd, i) => {
|
|
43
|
+
out[columnNames[i]] = rd;
|
|
44
|
+
});
|
|
45
|
+
rows.push(out);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
req.on("close", () => resolve(rows));
|
|
49
|
+
req.on("error", (error) => reject(error));
|
|
50
|
+
req.write(reqBody);
|
|
51
|
+
req.end();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.KSQL = KSQL;
|
package/dist/runtime/Cache.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
const crypto_1 = require("crypto");
|
|
7
|
-
const ioredis_1 =
|
|
8
|
-
const loglevel_1 =
|
|
4
|
+
const ioredis_1 = require("ioredis");
|
|
5
|
+
const loglevel_1 = require("loglevel");
|
|
9
6
|
const utility_1 = require("./lib/utility");
|
|
10
|
-
const Stats_1 =
|
|
7
|
+
const Stats_1 = require("./Stats");
|
|
11
8
|
class Cache {
|
|
12
9
|
constructor(redisConfig, debug) {
|
|
13
10
|
this.waiting = new Set();
|
|
@@ -5,35 +5,28 @@ export interface IRuntime {
|
|
|
5
5
|
$whereNeedsProcessing(where: any): boolean;
|
|
6
6
|
$prepareWhere(artifacts: IArtifacts, table: string, data: any): Promise<any>;
|
|
7
7
|
$shutdown(): Promise<void>;
|
|
8
|
-
$startTransaction(input?: {
|
|
9
|
-
isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE";
|
|
10
|
-
}): Promise<TBeginTransactionResult>;
|
|
11
8
|
}
|
|
12
|
-
export declare type TAction = "findUnique" | "findMany" | "findManyPaginated" | "create" | "update" | "updateMany" | "delete" | "deleteMany";
|
|
13
9
|
export declare type TResolveParams = {
|
|
14
10
|
resource: string;
|
|
15
|
-
action:
|
|
16
|
-
args?: IArgs;
|
|
11
|
+
action: "findUnique" | "findMany" | "findManyPaginated" | "create" | "update" | "updateMany" | "delete" | "deleteMany";
|
|
12
|
+
args?: IArgs | undefined;
|
|
17
13
|
data?: any;
|
|
18
14
|
artifacts: IArtifacts;
|
|
19
|
-
fields?:
|
|
20
|
-
context?: TContext;
|
|
15
|
+
fields?: IField[] | undefined;
|
|
16
|
+
context?: TContext | undefined;
|
|
21
17
|
skipCache?: boolean;
|
|
22
|
-
dbCall?: TDbCall;
|
|
23
18
|
};
|
|
24
19
|
export declare type TContext = {
|
|
25
20
|
[k: string]: any;
|
|
26
21
|
};
|
|
27
22
|
export declare type TMiddleware = (params: TResolveParams, next: (params: TResolveParams) => Promise<any>) => Promise<any>;
|
|
28
|
-
export declare type IDialect = "mysql" | "mssql" | "
|
|
23
|
+
export declare type IDialect = "mysql" | "mssql" | "ksql";
|
|
29
24
|
export declare type TDbCall = (q: string) => Promise<any>;
|
|
30
25
|
export declare type TFormatQuery = (q: string, values: any[]) => string;
|
|
31
|
-
export declare type TBeginTransaction = () => Promise<
|
|
32
|
-
declare type TBeginTransactionResult = {
|
|
26
|
+
export declare type TBeginTransaction = () => Promise<{
|
|
33
27
|
dbCall: (q: string) => Promise<any>;
|
|
34
28
|
commit: () => Promise<void>;
|
|
35
|
-
|
|
36
|
-
};
|
|
29
|
+
}>;
|
|
37
30
|
export declare type ISupplementClientOpts = boolean;
|
|
38
31
|
export declare type IOrderBy = {
|
|
39
32
|
column: string;
|
|
@@ -42,10 +35,12 @@ export declare type IOrderBy = {
|
|
|
42
35
|
export declare type IArgs = {
|
|
43
36
|
[k: string]: any;
|
|
44
37
|
};
|
|
45
|
-
export declare type
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
export declare type IField = string | {
|
|
39
|
+
name: string;
|
|
40
|
+
as?: string;
|
|
41
|
+
fields: IField[];
|
|
42
|
+
args?: IArgs;
|
|
43
|
+
transform?: (record: any) => any;
|
|
49
44
|
};
|
|
50
45
|
declare type IWhere = (table: string, args: IArgs) => string | undefined;
|
|
51
46
|
declare type IASTChildColumn = {
|
|
@@ -53,14 +48,14 @@ declare type IASTChildColumn = {
|
|
|
53
48
|
name: string;
|
|
54
49
|
fieldName: string;
|
|
55
50
|
as: string;
|
|
56
|
-
fromOtherTable?: string;
|
|
51
|
+
fromOtherTable?: string | undefined;
|
|
57
52
|
};
|
|
58
53
|
declare type IASTChildComposite = {
|
|
59
54
|
type: "composite";
|
|
60
55
|
name: string[];
|
|
61
56
|
fieldName: string;
|
|
62
57
|
as: string;
|
|
63
|
-
fromOtherTable?: string;
|
|
58
|
+
fromOtherTable?: string | undefined;
|
|
64
59
|
};
|
|
65
60
|
declare type ISqlJoin = (t1: string, t2: string, args: IArgs) => string;
|
|
66
61
|
declare type ISqlBatch = {
|
|
@@ -86,7 +81,7 @@ declare type IJunction = {
|
|
|
86
81
|
export declare type IGetSQLASTInput = {
|
|
87
82
|
table: string;
|
|
88
83
|
fieldName: string;
|
|
89
|
-
fields:
|
|
84
|
+
fields: IField[];
|
|
90
85
|
args?: IArgs;
|
|
91
86
|
where?: IWhere;
|
|
92
87
|
sqlJoin?: ISqlJoin;
|
|
@@ -94,7 +89,7 @@ export declare type IGetSQLASTInput = {
|
|
|
94
89
|
junction?: IJunction;
|
|
95
90
|
grabMany: boolean;
|
|
96
91
|
getWhere: (table: string, args: any, dialect: IDialect, orderBy?: IOrderBy | undefined, rowWithMatchingCursor?: any) => string | null;
|
|
97
|
-
orderBy?: IOrderBy;
|
|
92
|
+
orderBy?: IOrderBy | undefined;
|
|
98
93
|
rowWithMatchingCursor?: any;
|
|
99
94
|
artifacts: IArtifacts;
|
|
100
95
|
dialect: IDialect;
|
|
@@ -158,30 +153,6 @@ export declare type IArtifacts = {
|
|
|
158
153
|
[k: string]: boolean;
|
|
159
154
|
};
|
|
160
155
|
dateTimeFieldsCount: number;
|
|
161
|
-
fields: TField[];
|
|
162
|
-
dump: {
|
|
163
|
-
schema: string;
|
|
164
|
-
} | null;
|
|
165
156
|
};
|
|
166
157
|
};
|
|
167
|
-
export declare type TFieldType = "string" | "boolean" | "number" | "integer";
|
|
168
|
-
export declare type TField = {
|
|
169
|
-
kind: "scalar";
|
|
170
|
-
type: TFieldType;
|
|
171
|
-
name: string;
|
|
172
|
-
nullable: boolean;
|
|
173
|
-
hasDefaultValue: boolean;
|
|
174
|
-
mapped?: true;
|
|
175
|
-
} | {
|
|
176
|
-
kind: "enum";
|
|
177
|
-
values: unknown[];
|
|
178
|
-
name: string;
|
|
179
|
-
nullable: boolean;
|
|
180
|
-
} | {
|
|
181
|
-
kind: "object";
|
|
182
|
-
type: string;
|
|
183
|
-
name: string;
|
|
184
|
-
isList: boolean;
|
|
185
|
-
nullable: boolean;
|
|
186
|
-
};
|
|
187
158
|
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IRuntime, TMiddleware, TResolveParams, IArtifacts, TDbCall } from "./IRuntime";
|
|
2
|
+
import { KSQL } from "../ksql";
|
|
3
|
+
declare type TGetTableName = (table: string) => string;
|
|
4
|
+
export declare class RuntimeKSQL implements IRuntime {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(clientOpts: ConstructorParameters<typeof KSQL>[0], otherOpts: {
|
|
7
|
+
getBaseTableName: TGetTableName;
|
|
8
|
+
getMaterializedViewName: TGetTableName;
|
|
9
|
+
doNotUseMaterializedViews?: boolean;
|
|
10
|
+
_dbCall: TDbCall;
|
|
11
|
+
}, artifacts: IArtifacts);
|
|
12
|
+
resolve(input: TResolveParams): Promise<any>;
|
|
13
|
+
$queryRaw(sql: string, values?: any[]): Promise<any>;
|
|
14
|
+
$use(middleware: TMiddleware): Promise<void>;
|
|
15
|
+
$whereNeedsProcessing(where: any): boolean;
|
|
16
|
+
$prepareWhere(artifacts: IArtifacts, table: string, data: any): Promise<{}>;
|
|
17
|
+
$shutdown(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _RuntimeKSQL_ksql, _RuntimeKSQL_middlewareHandler, _RuntimeKSQL_dbCall, _RuntimeKSQL_formatQuery, _RuntimeKSQL_getBaseTableName, _RuntimeKSQL_getMaterializedViewName, _RuntimeKSQL_doNotUseMaterializedViews;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RuntimeKSQL = void 0;
|
|
16
|
+
const SqlString = require("sqlstring");
|
|
17
|
+
const async_hooks_1 = require("async_hooks");
|
|
18
|
+
const _ = require("lodash");
|
|
19
|
+
const graphql_relay_1 = require("graphql-relay");
|
|
20
|
+
const shared_1 = require("./lib/shared");
|
|
21
|
+
const ksql_1 = require("../ksql");
|
|
22
|
+
const SDKNotFoundError_1 = require("./lib/SDKNotFoundError");
|
|
23
|
+
const stringifyWhere_1 = require("./lib/stringifyWhere");
|
|
24
|
+
const cursor_1 = require("./lib/cursor");
|
|
25
|
+
const escapeId = SqlString.escapeId.bind(SqlString);
|
|
26
|
+
class RuntimeKSQL {
|
|
27
|
+
constructor(clientOpts, otherOpts, artifacts) {
|
|
28
|
+
_RuntimeKSQL_ksql.set(this, void 0);
|
|
29
|
+
_RuntimeKSQL_middlewareHandler.set(this, void 0);
|
|
30
|
+
_RuntimeKSQL_dbCall.set(this, void 0);
|
|
31
|
+
_RuntimeKSQL_formatQuery.set(this, void 0);
|
|
32
|
+
_RuntimeKSQL_getBaseTableName.set(this, void 0);
|
|
33
|
+
_RuntimeKSQL_getMaterializedViewName.set(this, void 0);
|
|
34
|
+
_RuntimeKSQL_doNotUseMaterializedViews.set(this, void 0);
|
|
35
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_ksql, new ksql_1.KSQL(clientOpts ?? {}), "f");
|
|
36
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
|
|
37
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_dbCall, typeof otherOpts._dbCall === "function"
|
|
38
|
+
? (q) => otherOpts._dbCall(q).then(mapResult)
|
|
39
|
+
: (q) => __classPrivateFieldGet(this, _RuntimeKSQL_ksql, "f").streamQuery(q).then(mapResult), "f");
|
|
40
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_getBaseTableName, otherOpts.getBaseTableName, "f");
|
|
41
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_getMaterializedViewName, otherOpts.getMaterializedViewName, "f");
|
|
42
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_doNotUseMaterializedViews, otherOpts.doNotUseMaterializedViews ?? false, "f");
|
|
43
|
+
__classPrivateFieldSet(this, _RuntimeKSQL_formatQuery, SqlString.format.bind(SqlString), "f");
|
|
44
|
+
}
|
|
45
|
+
async resolve(input) {
|
|
46
|
+
return resolve(input, __classPrivateFieldGet(this, _RuntimeKSQL_dbCall, "f").bind(this), __classPrivateFieldGet(this, _RuntimeKSQL_formatQuery, "f").bind(this), __classPrivateFieldGet(this, _RuntimeKSQL_middlewareHandler, "f"), __classPrivateFieldGet(this, _RuntimeKSQL_getBaseTableName, "f"), __classPrivateFieldGet(this, _RuntimeKSQL_getMaterializedViewName, "f"), __classPrivateFieldGet(this, _RuntimeKSQL_doNotUseMaterializedViews, "f"));
|
|
47
|
+
}
|
|
48
|
+
async $queryRaw(sql, values) {
|
|
49
|
+
return __classPrivateFieldGet(this, _RuntimeKSQL_dbCall, "f").call(this, SqlString.format(sql, values ?? []));
|
|
50
|
+
}
|
|
51
|
+
async $use(middleware) {
|
|
52
|
+
__classPrivateFieldGet(this, _RuntimeKSQL_middlewareHandler, "f").register(middleware);
|
|
53
|
+
}
|
|
54
|
+
$whereNeedsProcessing(where) {
|
|
55
|
+
return (0, shared_1.whereNeedsProcessing)(where);
|
|
56
|
+
}
|
|
57
|
+
async $prepareWhere(artifacts, table, data) {
|
|
58
|
+
return (0, shared_1._prepareWhere)(artifacts, table, data, __classPrivateFieldGet(this, _RuntimeKSQL_dbCall, "f").bind(this), __classPrivateFieldGet(this, _RuntimeKSQL_formatQuery, "f").bind(this));
|
|
59
|
+
}
|
|
60
|
+
async $shutdown() {
|
|
61
|
+
// Nothing to do here, I think
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.RuntimeKSQL = RuntimeKSQL;
|
|
65
|
+
_RuntimeKSQL_ksql = new WeakMap(), _RuntimeKSQL_middlewareHandler = new WeakMap(), _RuntimeKSQL_dbCall = new WeakMap(), _RuntimeKSQL_formatQuery = new WeakMap(), _RuntimeKSQL_getBaseTableName = new WeakMap(), _RuntimeKSQL_getMaterializedViewName = new WeakMap(), _RuntimeKSQL_doNotUseMaterializedViews = new WeakMap();
|
|
66
|
+
async function resolve(input, dbCall, formatQuery, middlewareHandler, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
67
|
+
// https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
|
|
68
|
+
let index = -1;
|
|
69
|
+
if (middlewareHandler.length() > 0) {
|
|
70
|
+
const resource = new async_hooks_1.AsyncResource("sdk-request");
|
|
71
|
+
const params = input;
|
|
72
|
+
const consumer = (paramsMaybeMutated) => {
|
|
73
|
+
const nextMiddleware = middlewareHandler.get(++index);
|
|
74
|
+
if (nextMiddleware != null) {
|
|
75
|
+
return nextMiddleware(paramsMaybeMutated, consumer);
|
|
76
|
+
}
|
|
77
|
+
const paramsChanged = { ...input, ...params };
|
|
78
|
+
return _resolve(paramsChanged, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
79
|
+
};
|
|
80
|
+
return resource.runInAsyncScope(() => consumer(params));
|
|
81
|
+
}
|
|
82
|
+
return _resolve(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
83
|
+
}
|
|
84
|
+
function _resolve(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
85
|
+
if (input.action === "findUnique") {
|
|
86
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
87
|
+
}
|
|
88
|
+
if (input.action === "findMany") {
|
|
89
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
90
|
+
}
|
|
91
|
+
if (input.action === "findManyPaginated") {
|
|
92
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
93
|
+
}
|
|
94
|
+
if (input.action === "create") {
|
|
95
|
+
throw new Error("Not implemented.");
|
|
96
|
+
}
|
|
97
|
+
if (input.action === "update") {
|
|
98
|
+
throw new Error("Not implemented.");
|
|
99
|
+
}
|
|
100
|
+
if (input.action === "updateMany") {
|
|
101
|
+
throw new Error("Not implemented.");
|
|
102
|
+
}
|
|
103
|
+
if (input.action === "delete") {
|
|
104
|
+
throw new Error("Not implemented.");
|
|
105
|
+
}
|
|
106
|
+
if (input.action === "deleteMany") {
|
|
107
|
+
throw new Error("Not implemented.");
|
|
108
|
+
}
|
|
109
|
+
throw new Error("Invalid action: " + input.action);
|
|
110
|
+
}
|
|
111
|
+
async function getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
112
|
+
const { action } = input;
|
|
113
|
+
const grabMany = action === "findMany" ||
|
|
114
|
+
action === "findManyPaginated" ||
|
|
115
|
+
action === "updateMany" ||
|
|
116
|
+
action === "deleteMany";
|
|
117
|
+
const data = await _getData(input, grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
118
|
+
if (data == null && !grabMany) {
|
|
119
|
+
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
120
|
+
}
|
|
121
|
+
const scalarFields = input.artifacts[input.resource].scalarFields;
|
|
122
|
+
if (action === "findManyPaginated" && data?.results != null) {
|
|
123
|
+
(0, shared_1.postProcess)(data.results, input.fields ?? scalarFields, true);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
(0, shared_1.postProcess)(data, input.fields ?? scalarFields, true);
|
|
127
|
+
}
|
|
128
|
+
return data;
|
|
129
|
+
}
|
|
130
|
+
async function _getData(input, grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
131
|
+
const { resource: table, artifacts, args, action } = input;
|
|
132
|
+
const tableArtifacts = artifacts[table];
|
|
133
|
+
const isInputFieldAnArray = Array.isArray(input.fields);
|
|
134
|
+
let fields = input.fields;
|
|
135
|
+
if (!Array.isArray(fields)) {
|
|
136
|
+
fields = tableArtifacts.scalarFields;
|
|
137
|
+
}
|
|
138
|
+
let useMaterializedView = !doNotUseMaterializedViews &&
|
|
139
|
+
// If fields isn't an array, we're only getting scalar fields,
|
|
140
|
+
// so no point using the materialized view.
|
|
141
|
+
isInputFieldAnArray &&
|
|
142
|
+
// We're getting relation fields
|
|
143
|
+
fields.some((x) => typeof x === "object") &&
|
|
144
|
+
Object.values(tableArtifacts.relationFields).filter((x) => x.type === "one-to-many__many-to-one" && x.kind === "many-to-one").length > 0 &&
|
|
145
|
+
!Object.values(tableArtifacts.relationFields).some((x) => x.type === "one-to-many__many-to-one" &&
|
|
146
|
+
x.kind === "many-to-one" &&
|
|
147
|
+
x.nullable === true);
|
|
148
|
+
const getTableName = useMaterializedView
|
|
149
|
+
? getMaterializedViewName
|
|
150
|
+
: getBaseTableName;
|
|
151
|
+
let where = undefined;
|
|
152
|
+
if (args?.$where != null) {
|
|
153
|
+
let argsMapped = args;
|
|
154
|
+
if (typeof argsMapped.$where === "object" &&
|
|
155
|
+
argsMapped.$where[table] != null) {
|
|
156
|
+
argsMapped = _.cloneDeep(argsMapped);
|
|
157
|
+
argsMapped.$where = argsMapped.$where[table];
|
|
158
|
+
}
|
|
159
|
+
const whereResult = (0, stringifyWhere_1.stringifyWhere)({
|
|
160
|
+
where: argsMapped.$where,
|
|
161
|
+
table: escapeId(getTableName(table)),
|
|
162
|
+
dialect: "mysql",
|
|
163
|
+
args: argsMapped,
|
|
164
|
+
});
|
|
165
|
+
if (whereResult) {
|
|
166
|
+
where = whereResult;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
let columns = [];
|
|
170
|
+
let mappedFields = [];
|
|
171
|
+
let relationFields = [];
|
|
172
|
+
for (let x of fields) {
|
|
173
|
+
if (typeof x === "string") {
|
|
174
|
+
const mappedField = tableArtifacts.mappedFields?.[x];
|
|
175
|
+
if (mappedField != null) {
|
|
176
|
+
mappedFields.push(x);
|
|
177
|
+
if (!columns.includes(mappedField.foreignKey)) {
|
|
178
|
+
columns.push(mappedField.foreignKey);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
columns.push(x);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
187
|
+
if (relationField == null) {
|
|
188
|
+
throw new Error(`Invalid relation field: ${x.name}`);
|
|
189
|
+
}
|
|
190
|
+
if (relationField.type === "one-to-many__many-to-one") {
|
|
191
|
+
relationFields.push(x);
|
|
192
|
+
if (!columns.includes(relationField.relation.foreignKey)) {
|
|
193
|
+
columns.push(relationField.relation.foreignKey);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (relationField.type === "many-to-many") {
|
|
197
|
+
relationFields.push(x);
|
|
198
|
+
if (!columns.includes(relationField.relations[0].referencedKey)) {
|
|
199
|
+
columns.push(relationField.relations[0].referencedKey);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (action === "findManyPaginated") {
|
|
205
|
+
// For cursor
|
|
206
|
+
if (!columns.includes(tableArtifacts.primaryKey)) {
|
|
207
|
+
columns.push(tableArtifacts.primaryKey);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (useMaterializedView) {
|
|
211
|
+
relationFields = relationFields.filter((x) => {
|
|
212
|
+
if (typeof x === "string") {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
216
|
+
if (relationField == null) {
|
|
217
|
+
throw new Error(`Invalid relation field: ${x.name}`);
|
|
218
|
+
}
|
|
219
|
+
// Since we're going to use the materialized view,
|
|
220
|
+
// filter out non-nullable many-to-one relations.
|
|
221
|
+
return !(relationField.type === "one-to-many__many-to-one" &&
|
|
222
|
+
relationField.kind === "many-to-one" &&
|
|
223
|
+
relationField.nullable === false);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
let s = useMaterializedView
|
|
227
|
+
? formatQuery(`SELECT * FROM ??`, [getTableName(table)])
|
|
228
|
+
: formatQuery(`SELECT ?? FROM ??`, [columns, getTableName(table)]);
|
|
229
|
+
if (where) {
|
|
230
|
+
s += ` WHERE ${where}`;
|
|
231
|
+
}
|
|
232
|
+
s += ";";
|
|
233
|
+
return dbCall(s).then((_result) => {
|
|
234
|
+
let result = grabMany ? _result : _result[0];
|
|
235
|
+
if (result == null) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (grabMany && Array.isArray(result)) {
|
|
239
|
+
// Important: ordering must be before pagination, since pagination is done in code
|
|
240
|
+
let orderBy;
|
|
241
|
+
if (args == null || args.$orderBy == null) {
|
|
242
|
+
orderBy = [{ column: tableArtifacts.primaryKey, direction: "asc" }];
|
|
243
|
+
}
|
|
244
|
+
else if (Array.isArray(args.$orderBy)) {
|
|
245
|
+
orderBy = args.$orderBy.map((x) => {
|
|
246
|
+
const [column, direction] = Object.entries(x)[0];
|
|
247
|
+
return { column, direction };
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
const [column, direction] = Object.entries(args.$orderBy)[0];
|
|
252
|
+
orderBy = [{ column, direction }];
|
|
253
|
+
}
|
|
254
|
+
for (let x of orderBy) {
|
|
255
|
+
if (!["asc", "desc"].includes(x.direction)) {
|
|
256
|
+
throw new Error(`Expected \`asc\` or \`desc\` for \`direction\` but got: ${x.direction}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
result = _.orderBy(result, orderBy.map((x) => x.column), orderBy.map((x) => x.direction));
|
|
260
|
+
if (action === "findManyPaginated") {
|
|
261
|
+
result = paginate(result, args, tableArtifacts.primaryKey, action);
|
|
262
|
+
return Promise.all(result.results.map((x) => resolveDependentFields(table, x, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => mergeSubResults(x, xx)))).then((xx) => {
|
|
263
|
+
result.results = xx;
|
|
264
|
+
return result;
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
const limit = args?.$limit;
|
|
268
|
+
if (typeof limit === "number") {
|
|
269
|
+
result = result.slice(0, limit);
|
|
270
|
+
}
|
|
271
|
+
return Promise.all(result.map((x) => resolveDependentFields(table, x, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => mergeSubResults(x, xx))));
|
|
272
|
+
}
|
|
273
|
+
return resolveDependentFields(table, result, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => mergeSubResults(result, xx));
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
async function resolveDependentFields(table, parentData, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
277
|
+
const tableArtifacts = artifacts[table];
|
|
278
|
+
return Promise.all([]
|
|
279
|
+
.concat(mappedFields.map((x) => {
|
|
280
|
+
const mappedField = tableArtifacts.mappedFields?.[x];
|
|
281
|
+
if (mappedField == null) {
|
|
282
|
+
throw new Error(`Invalid mappedField: ${x}`);
|
|
283
|
+
}
|
|
284
|
+
if (parentData?.[mappedField.foreignKey] == null) {
|
|
285
|
+
return { [x]: null };
|
|
286
|
+
}
|
|
287
|
+
const s = formatQuery(`SELECT ?? FROM ?? WHERE ?? = ?;`, [
|
|
288
|
+
mappedField.name,
|
|
289
|
+
getBaseTableName(mappedField.referencedTable),
|
|
290
|
+
mappedField.referencedKey,
|
|
291
|
+
parentData?.[mappedField.foreignKey],
|
|
292
|
+
]);
|
|
293
|
+
return dbCall(s).then((xs) => ({
|
|
294
|
+
[x]: xs?.[0]?.[mappedField.name] ?? null,
|
|
295
|
+
}));
|
|
296
|
+
}))
|
|
297
|
+
.concat(relationFields.map((x) => {
|
|
298
|
+
if (typeof x === "string") {
|
|
299
|
+
throw new Error(`Invalid field: ${x}`);
|
|
300
|
+
}
|
|
301
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
302
|
+
if (relationField == null) {
|
|
303
|
+
throw new Error("Invalid field: " + table + "." + x.name);
|
|
304
|
+
}
|
|
305
|
+
if (relationField.type === "many-to-many") {
|
|
306
|
+
const junctionReferencedKey = relationField.relations[0].referencedKey;
|
|
307
|
+
const junctionKeyValue = parentData?.[junctionReferencedKey];
|
|
308
|
+
if (junctionKeyValue == null) {
|
|
309
|
+
return { [x.as ?? x.name]: [] };
|
|
310
|
+
}
|
|
311
|
+
let whereJunction = typeof x?.args?.$where === "object" &&
|
|
312
|
+
x.args.$where != null &&
|
|
313
|
+
x.args.$where[relationField.junctionTable] != null
|
|
314
|
+
? _.cloneDeep(x.args.$where[relationField.junctionTable])
|
|
315
|
+
: {};
|
|
316
|
+
whereJunction = {
|
|
317
|
+
$and: [
|
|
318
|
+
{ [relationField.relations[0].foreignKey]: junctionKeyValue },
|
|
319
|
+
whereJunction,
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
const key = relationField.relations[1].foreignKey;
|
|
323
|
+
const s = formatQuery(`SELECT ?? FROM ?? WHERE ${(0, stringifyWhere_1.stringifyWhere)({
|
|
324
|
+
where: whereJunction,
|
|
325
|
+
table: escapeId(getBaseTableName(relationField.junctionTable)),
|
|
326
|
+
dialect: "mysql",
|
|
327
|
+
// Since we're paginating, empty is fine
|
|
328
|
+
args: {},
|
|
329
|
+
})};`, [key, getBaseTableName(relationField.junctionTable)]);
|
|
330
|
+
return dbCall(s)
|
|
331
|
+
.then((xs) => xs.map((x) => x?.[key]))
|
|
332
|
+
.then((keys) => {
|
|
333
|
+
const whereDest = {
|
|
334
|
+
[relationField.relations[1].referencedKey]: { $in: keys },
|
|
335
|
+
};
|
|
336
|
+
const argsMapped = x.args == null ? {} : _.cloneDeep(x.args);
|
|
337
|
+
if (typeof argsMapped?.$where === "object" &&
|
|
338
|
+
argsMapped.$where != null &&
|
|
339
|
+
argsMapped.$where[relationField.table] != null) {
|
|
340
|
+
argsMapped.$where = {
|
|
341
|
+
$and: [whereDest, argsMapped.$where[relationField.table]],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
else if (argsMapped.$where != null) {
|
|
345
|
+
argsMapped.$where = { $and: [whereDest, argsMapped.$where] };
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
argsMapped.$where = whereDest;
|
|
349
|
+
}
|
|
350
|
+
return _getData({
|
|
351
|
+
resource: relationField.table,
|
|
352
|
+
args: argsMapped,
|
|
353
|
+
fields: x.fields,
|
|
354
|
+
artifacts,
|
|
355
|
+
action: relationField.grabMany ? "findMany" : "findUnique",
|
|
356
|
+
}, relationField.grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => ({ [x.as ?? x.name]: xx }));
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
if (relationField.type === "one-to-many__many-to-one") {
|
|
360
|
+
const referencedKey = relationField.relation.referencedKey;
|
|
361
|
+
const foreignKeyValue = parentData?.[relationField.relation.foreignKey];
|
|
362
|
+
if (foreignKeyValue == null) {
|
|
363
|
+
return { [x.as ?? x.name]: relationField.grabMany ? [] : null };
|
|
364
|
+
}
|
|
365
|
+
const whereRef = { [referencedKey]: foreignKeyValue };
|
|
366
|
+
const argsMapped = x.args == null ? {} : _.cloneDeep(x.args);
|
|
367
|
+
if (argsMapped.$where == null) {
|
|
368
|
+
argsMapped.$where = whereRef;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
argsMapped.$where = { $and: [whereRef, argsMapped.$where] };
|
|
372
|
+
}
|
|
373
|
+
return _getData({
|
|
374
|
+
resource: relationField.table,
|
|
375
|
+
args: argsMapped,
|
|
376
|
+
fields: x.fields,
|
|
377
|
+
artifacts,
|
|
378
|
+
action: relationField.grabMany ? "findMany" : "findUnique",
|
|
379
|
+
}, relationField.grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => ({ [x.as ?? x.name]: xx }));
|
|
380
|
+
}
|
|
381
|
+
throw new Error(`Invalid relationField.type`);
|
|
382
|
+
})));
|
|
383
|
+
}
|
|
384
|
+
function mergeSubResults(result, subResults) {
|
|
385
|
+
for (let x of subResults) {
|
|
386
|
+
result = { ...result, ...x };
|
|
387
|
+
}
|
|
388
|
+
return result;
|
|
389
|
+
}
|
|
390
|
+
function paginate(data, args, primaryKey, action) {
|
|
391
|
+
if (action === "findManyPaginated") {
|
|
392
|
+
if (typeof args?.$paginate?.limit === "number") {
|
|
393
|
+
const totalCount = data.length;
|
|
394
|
+
const limit = args.$paginate.limit;
|
|
395
|
+
const offset = args.$paginate.offset ?? 0;
|
|
396
|
+
data = data.slice(offset, offset + limit);
|
|
397
|
+
return {
|
|
398
|
+
results: data,
|
|
399
|
+
paginationInfo: { totalCount },
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
if (typeof args?.$paginate?.first === "number" ||
|
|
403
|
+
typeof args?.$paginate?.last === "number") {
|
|
404
|
+
const totalCount = data.length;
|
|
405
|
+
let argsMapped = args;
|
|
406
|
+
// Convert cursor(s) for graphql-relay
|
|
407
|
+
for (let k of ["after", "before"]) {
|
|
408
|
+
if (args?.$paginate?.[k] != null) {
|
|
409
|
+
argsMapped = _.cloneDeep(argsMapped);
|
|
410
|
+
const offset = data.findIndex((x) => x[primaryKey] === (0, cursor_1.decodeCursor)(args.$paginate[k]));
|
|
411
|
+
if (offset === -1) {
|
|
412
|
+
throw new Error(`Invalid cursor: ${args.$paginate[k]}`);
|
|
413
|
+
}
|
|
414
|
+
argsMapped.$paginate[k] = (0, graphql_relay_1.offsetToCursor)(offset);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
const connection = (0, graphql_relay_1.connectionFromArray)(data, argsMapped.$paginate);
|
|
418
|
+
const results = connection.edges.map((x) => x.node);
|
|
419
|
+
// Convert cursors back
|
|
420
|
+
const startKey = results[0]?.[primaryKey];
|
|
421
|
+
const endKey = results[results.length - 1]?.[primaryKey];
|
|
422
|
+
const startCursor = startKey == null ? null : (0, cursor_1.encodeCursor)(startKey);
|
|
423
|
+
const endCursor = endKey == null ? null : (0, cursor_1.encodeCursor)(endKey);
|
|
424
|
+
return {
|
|
425
|
+
results,
|
|
426
|
+
paginationInfo: {
|
|
427
|
+
...connection.pageInfo,
|
|
428
|
+
startCursor,
|
|
429
|
+
endCursor,
|
|
430
|
+
totalCount,
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
throw new Error(`Invalid pagination action: ${action}`);
|
|
436
|
+
}
|
|
437
|
+
function mapResult(data) {
|
|
438
|
+
return data.map((x) => {
|
|
439
|
+
for (let k of Object.keys(x)) {
|
|
440
|
+
if (typeof x[k] === "string" && (k === "uuid" || k.endsWith("Uuid"))) {
|
|
441
|
+
x[k] = x[k].toLocaleLowerCase();
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return x;
|
|
445
|
+
});
|
|
446
|
+
}
|