@technicity/data-service-generator 0.5.15 → 0.7.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/CHANGELOG.md +166 -0
- package/dist/generation/generate.js +19 -23
- package/dist/runtime/IRuntime.d.ts +2 -2
- package/dist/runtime/RuntimeKSQL.d.ts +8 -10
- package/dist/runtime/RuntimeKSQL.js +389 -82
- package/dist/runtime/RuntimeMySQL.js +7 -6
- package/dist/runtime/lib/getOrderBy.js +7 -0
- package/dist/runtime/lib/mysql.d.ts +7 -0
- package/dist/runtime/lib/mysql.js +36 -0
- package/dist/runtime/lib/shared.d.ts +2 -1
- package/dist/runtime/lib/shared.js +13 -3
- package/package.json +8 -7
- package/dist/mysql.d.ts +0 -3
- package/dist/mysql.js +0 -35
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# 0.7.0 [2022.01.17]
|
|
2
|
+
|
|
3
|
+
- Add support for MySQL 8
|
|
4
|
+
|
|
5
|
+
# 0.5.12 [2021.11.18]
|
|
6
|
+
|
|
7
|
+
- Add `$queryRaw`
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
await sdk.$queryRaw("SELECT * FROM Foo WHERE id = ?", [2]);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Use the `?` character as a placeholder for values that need to be escaped.
|
|
14
|
+
|
|
15
|
+
# 0.5.12 [2021.11.18]
|
|
16
|
+
|
|
17
|
+
- Add support for nested creates. All of the specified creates are wrapped in a transaction.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
await sdk.postFoo({
|
|
21
|
+
foo: "blah",
|
|
22
|
+
barList: {
|
|
23
|
+
$create: [
|
|
24
|
+
{
|
|
25
|
+
note: "blah",
|
|
26
|
+
bazList: { $create: [{ baz: "asdf" }, { baz: "zzz" }] },
|
|
27
|
+
},
|
|
28
|
+
{ note: "blah 2" },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
In the above example, 5 records are created: 1 `Foo` record, 2 `Bar` records, and 2 `Baz` records.
|
|
35
|
+
|
|
36
|
+
# 0.5.7 [2021.10.12]
|
|
37
|
+
|
|
38
|
+
- Add `$nlike` operator. Equivalent to SQL's `NOT LIKE` operator.
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
await sdk.getFooList({
|
|
42
|
+
$where: { bar: { $nlike: "%baz%" } },
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
# 0.5.5 [2021.10.12]
|
|
47
|
+
|
|
48
|
+
- Add limit + offset pagination
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
await sdk.getFooListPaginated({
|
|
52
|
+
$paginate: { limit: 5, offset: 2 },
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
# 0.5.0 [2021.10.08]
|
|
57
|
+
|
|
58
|
+
- Add support for middleware
|
|
59
|
+
|
|
60
|
+
Generated SDKs now have a `$use` method, which takes a single argument: your middleware function.
|
|
61
|
+
|
|
62
|
+
Example middleware that logs the amount of time an operation took:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
sdk.$use(async (params, next) => {
|
|
66
|
+
const start = process.hrtime();
|
|
67
|
+
const result = await next(params);
|
|
68
|
+
const end = process.hrtime(start);
|
|
69
|
+
console.log(`${params.resource}.${params.action} took ${end[1] / 1000000}ms`);
|
|
70
|
+
return result;
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Migrating from 0.4.x
|
|
75
|
+
|
|
76
|
+
1. `npm install -S @technicity/data-service-generator@0.5.0`
|
|
77
|
+
2. Regenerate SDK
|
|
78
|
+
|
|
79
|
+
# 0.4.0 [2021.09.17]
|
|
80
|
+
|
|
81
|
+
- Implement operations on update for string, number fields
|
|
82
|
+
|
|
83
|
+
## string
|
|
84
|
+
|
|
85
|
+
### `$prepend`
|
|
86
|
+
|
|
87
|
+
Prepend a string to the current value. If the current value is `null`, the value is not updated.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
await sdk.patchFoo(
|
|
91
|
+
{ id: 1 },
|
|
92
|
+
{ bar: { $prepend: `BAZ_` }
|
|
93
|
+
);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `$append`
|
|
97
|
+
|
|
98
|
+
Append a string to the current value. If the current value is `null`, the value is not updated.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
await sdk.patchFoo(
|
|
102
|
+
{ id: 1 },
|
|
103
|
+
{ bar: { $append: `_BAZ` }
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## number
|
|
108
|
+
|
|
109
|
+
### `$increment`
|
|
110
|
+
|
|
111
|
+
Increment the current value. If the current value is `null`, the value is not updated.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
await sdk.patchBar(
|
|
115
|
+
{ id: 1 },
|
|
116
|
+
{ foo: { $increment: 5 }
|
|
117
|
+
);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `$decrement`
|
|
121
|
+
|
|
122
|
+
Decrement the current value. If the current value is `null`, the value is not updated.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
await sdk.patchBar(
|
|
126
|
+
{ id: 1 },
|
|
127
|
+
{ foo: { $decrement: 5 }
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Migrating from 0.3.x
|
|
132
|
+
|
|
133
|
+
1. `npm install -S @technicity/data-service-generator@0.4.0`
|
|
134
|
+
2. Regenerate SDK
|
|
135
|
+
|
|
136
|
+
# 0.3.1 [2021.09.09]
|
|
137
|
+
|
|
138
|
+
- [MSSQL] Allow passing custom `typeCast`
|
|
139
|
+
|
|
140
|
+
# 0.3.0 [2021.09.08]
|
|
141
|
+
|
|
142
|
+
- For the generated SDK, instead of specifying a `dialect`, specify a `runtime`. This reduces the need to regenerate SDKs, since updates and bugfixes to the runtime side can be obtained solely by updating the `@technicity/data-service-generator` version, instead of both updating the `@technicity/data-service-generator` version and regenerating the SDK. It also allows for custom runtimes that live outside this package. `@technicity/data-service-generator` ships with 3 runtimes: `RuntimeMySQL`, `RuntimeMSSQL`, `RuntimeKSQL`.
|
|
143
|
+
- Add KSQL support
|
|
144
|
+
- `driverOpts` -> `clientOpts`
|
|
145
|
+
- Add `otherOpts` to allow passing extra runtime-specific options
|
|
146
|
+
|
|
147
|
+
## Migrating from 0.2.x
|
|
148
|
+
|
|
149
|
+
1. `npm install -S @technicity/data-service-generator@0.3.0`
|
|
150
|
+
2. Regenerate SDK
|
|
151
|
+
3. Update SDK instantiation:
|
|
152
|
+
|
|
153
|
+
```diff
|
|
154
|
+
+ import { RuntimeMySQL } from "@technicity/data-service-generator/dist/runtime/RuntimeMySQL";
|
|
155
|
+
|
|
156
|
+
const sdk = new SDK({
|
|
157
|
+
- dialect: "mysql",
|
|
158
|
+
+ runtime: RuntimeMySQL,
|
|
159
|
+
- driverOpts: {
|
|
160
|
+
+ clientOpts: {
|
|
161
|
+
database: "MY_DATABASE",
|
|
162
|
+
user: "MY_USER",
|
|
163
|
+
password: "MY_PASSWORD",
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
@@ -15,7 +15,7 @@ const TSqlString = require("tsqlstring");
|
|
|
15
15
|
const json_schema_to_typescript_1 = require("json-schema-to-typescript");
|
|
16
16
|
const getDuplicates_1 = require("../lib/getDuplicates");
|
|
17
17
|
const isNotNullOrUndefined_1 = require("../lib/isNotNullOrUndefined");
|
|
18
|
-
const
|
|
18
|
+
const mysql_1 = require("../runtime/lib/mysql");
|
|
19
19
|
// json-schema-to-typescript inlines everything. We don't want that,
|
|
20
20
|
// so use `tsType`, and add imports manually.
|
|
21
21
|
// https://github.com/bcherny/json-schema-to-typescript#custom-schema-properties
|
|
@@ -114,7 +114,7 @@ async function generate(input) {
|
|
|
114
114
|
const tmpBuildOutputPath = path.join(tmpDirPath, "sdk-ts");
|
|
115
115
|
const outdir = path.resolve(input.outdir);
|
|
116
116
|
const sdkOutputPath = path.join(outdir, "sdk-ts");
|
|
117
|
-
const nccVersion = "^0.
|
|
117
|
+
const nccVersion = "^0.33.0";
|
|
118
118
|
child_process.execSync("npm i", { cwd: tmpDirPath, stdio: "inherit" });
|
|
119
119
|
child_process.execSync(`npx -p @vercel/ncc@${nccVersion} ncc build ./${sdkFilename} -o ${tmpBuildOutputPath} -e ./artifacts`, { cwd: tmpDirPath, stdio: "inherit" });
|
|
120
120
|
// TODO: workaround for artifacts.js not being output by ncc
|
|
@@ -138,14 +138,14 @@ exports.generate = generate;
|
|
|
138
138
|
function init(input) {
|
|
139
139
|
const { database, user, password, host, port, server } = input;
|
|
140
140
|
if (dialect === "mysql") {
|
|
141
|
-
mysql.
|
|
141
|
+
let mysql = new mysql_1.MySQL({
|
|
142
142
|
user,
|
|
143
143
|
password,
|
|
144
144
|
host,
|
|
145
145
|
port,
|
|
146
146
|
database,
|
|
147
147
|
});
|
|
148
|
-
query = mysql.query;
|
|
148
|
+
query = mysql.query.bind(mysql);
|
|
149
149
|
}
|
|
150
150
|
if (dialect === "mssql" || dialect === "ksql") {
|
|
151
151
|
const pool = new mssql.ConnectionPool({
|
|
@@ -815,27 +815,23 @@ async function getJSONSchemaWhere(table) {
|
|
|
815
815
|
};
|
|
816
816
|
}
|
|
817
817
|
async function getTypeOrderBy(table, name) {
|
|
818
|
-
return (0, json_schema_to_typescript_1.compile)((await getJSONSchemaOrderBy(table)), name, json2TsOpts);
|
|
818
|
+
return (0, json_schema_to_typescript_1.compile)((await getJSONSchemaOrderBy(table, name)), name, json2TsOpts);
|
|
819
819
|
}
|
|
820
|
-
async function getJSONSchemaOrderBy(table) {
|
|
820
|
+
async function getJSONSchemaOrderBy(table, name) {
|
|
821
821
|
const fieldNames = await getTableMeta(table).then((xs) => xs.map((x) => x.Field));
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
822
|
+
const def = {
|
|
823
|
+
oneOf: fieldNames.map((k) => ({
|
|
824
|
+
type: "object",
|
|
825
|
+
properties: { [k]: { enum: ["asc", "desc"] } },
|
|
826
|
+
required: [k],
|
|
827
|
+
additionalProperties: false,
|
|
828
|
+
})),
|
|
829
|
+
};
|
|
830
|
+
const defName = `_${name}`;
|
|
831
|
+
const _schema = { $ref: `#/definitions/${defName}` };
|
|
828
832
|
return {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
{
|
|
832
|
-
type: "array",
|
|
833
|
-
items: { oneOf: fieldSchemas },
|
|
834
|
-
// minItems: 1,
|
|
835
|
-
// maxItems: fieldNames.length,
|
|
836
|
-
// uniqueItems: true,
|
|
837
|
-
},
|
|
838
|
-
],
|
|
833
|
+
definitions: { [defName]: def },
|
|
834
|
+
oneOf: [_schema, { type: "array", items: _schema }],
|
|
839
835
|
};
|
|
840
836
|
}
|
|
841
837
|
function getTypeShared() {
|
|
@@ -1244,7 +1240,7 @@ const getRelationsOneToMany = _.memoize(async function getRelationsOneToMany(tab
|
|
|
1244
1240
|
nullable: false,
|
|
1245
1241
|
};
|
|
1246
1242
|
})));
|
|
1247
|
-
return _.sortBy((x) => x.referencedTable, xs);
|
|
1243
|
+
return _.sortBy((x) => x.referencedKey, _.sortBy((x) => x.referencedTable, xs));
|
|
1248
1244
|
});
|
|
1249
1245
|
async function getPrimaryColumn(table) {
|
|
1250
1246
|
const tableMeta = await getTableMeta(table);
|
|
@@ -26,10 +26,10 @@ export declare type TBeginTransaction = () => Promise<{
|
|
|
26
26
|
commit: () => Promise<void>;
|
|
27
27
|
}>;
|
|
28
28
|
export declare type ISupplementClientOpts = boolean;
|
|
29
|
-
export declare type IOrderBy =
|
|
29
|
+
export declare type IOrderBy = {
|
|
30
30
|
column: string;
|
|
31
31
|
direction: any;
|
|
32
|
-
}
|
|
32
|
+
}[];
|
|
33
33
|
export declare type IArgs = {
|
|
34
34
|
[k: string]: any;
|
|
35
35
|
};
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import type { IRuntime, TMiddleware, TResolveParams, IArtifacts,
|
|
1
|
+
import type { IRuntime, TMiddleware, TResolveParams, IArtifacts, TDbCall } from "./IRuntime";
|
|
2
2
|
import { KSQL } from "../ksql";
|
|
3
|
-
|
|
3
|
+
declare type TGetTableName = (table: string) => string;
|
|
4
4
|
export declare class RuntimeKSQL implements IRuntime {
|
|
5
5
|
#private;
|
|
6
6
|
constructor(clientOpts: ConstructorParameters<typeof KSQL>[0], otherOpts: {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
getBaseTableName: TGetTableName;
|
|
8
|
+
getMaterializedViewName: TGetTableName;
|
|
9
|
+
doNotUseMaterializedViews?: boolean;
|
|
10
|
+
_dbCall: TDbCall;
|
|
9
11
|
}, artifacts: IArtifacts);
|
|
10
12
|
resolve(input: TResolveParams): Promise<any>;
|
|
11
|
-
$queryRaw(sql: string, values?: any[]): Promise<any
|
|
13
|
+
$queryRaw(sql: string, values?: any[]): Promise<any>;
|
|
12
14
|
$use(middleware: TMiddleware): Promise<void>;
|
|
13
15
|
$whereNeedsProcessing(where: any): boolean;
|
|
14
16
|
$prepareWhere(artifacts: IArtifacts, table: string, data: any): Promise<{}>;
|
|
15
|
-
private post;
|
|
16
|
-
private patch;
|
|
17
|
-
private patchList;
|
|
18
|
-
private del;
|
|
19
|
-
private deleteList;
|
|
20
17
|
}
|
|
18
|
+
export {};
|
|
@@ -10,81 +10,43 @@ 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 _RuntimeKSQL_ksql,
|
|
13
|
+
var _RuntimeKSQL_ksql, _RuntimeKSQL_middlewareHandler, _RuntimeKSQL_dbCall, _RuntimeKSQL_formatQuery, _RuntimeKSQL_getBaseTableName, _RuntimeKSQL_getMaterializedViewName, _RuntimeKSQL_doNotUseMaterializedViews;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RuntimeKSQL = void 0;
|
|
16
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");
|
|
17
20
|
const shared_1 = require("./lib/shared");
|
|
18
|
-
const getWhere_1 = require("./lib/getWhere");
|
|
19
21
|
const ksql_1 = require("../ksql");
|
|
20
22
|
const SDKNotFoundError_1 = require("./lib/SDKNotFoundError");
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
+
const stringifyWhere_1 = require("./lib/stringifyWhere");
|
|
24
|
+
const cursor_1 = require("./lib/cursor");
|
|
25
|
+
const escapeId = SqlString.escapeId.bind(SqlString);
|
|
23
26
|
class RuntimeKSQL {
|
|
24
27
|
constructor(clientOpts, otherOpts, artifacts) {
|
|
25
28
|
_RuntimeKSQL_ksql.set(this, void 0);
|
|
26
|
-
_RuntimeKSQL_mssqlClient.set(this, void 0);
|
|
27
29
|
_RuntimeKSQL_middlewareHandler.set(this, void 0);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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");
|
|
31
36
|
__classPrivateFieldSet(this, _RuntimeKSQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
|
|
32
|
-
__classPrivateFieldSet(this,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
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");
|
|
40
44
|
}
|
|
41
45
|
async resolve(input) {
|
|
42
|
-
|
|
43
|
-
const primaryKey = input.artifacts[input.resource].primaryKey;
|
|
44
|
-
// Overwrite
|
|
45
|
-
input.fields = [primaryKey];
|
|
46
|
-
const resolved = await (0, shared_1.resolve)(input, __classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f").dbCall.bind(__classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f")), __classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f").formatQuery.bind(__classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f")), __classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f").beginTransaction.bind(__classPrivateFieldGet(this, _RuntimeKSQL_mssqlClient, "f")), "mssql", __classPrivateFieldGet(this, _RuntimeKSQL_middlewareHandler, "f"), input.context ?? {});
|
|
47
|
-
const keys = input.action === "findMany"
|
|
48
|
-
? resolved.map((x) => x[primaryKey])
|
|
49
|
-
: resolved.results.map((x) => x[primaryKey]);
|
|
50
|
-
if (keys.length === 0) {
|
|
51
|
-
return resolved;
|
|
52
|
-
}
|
|
53
|
-
const sql = SqlString.format("SELECT * FROM ?? WHERE ?? IN (?);", [
|
|
54
|
-
getKSQLTablename(input.resource, input?.context?.hydrate),
|
|
55
|
-
primaryKey,
|
|
56
|
-
keys,
|
|
57
|
-
]);
|
|
58
|
-
const results = await __classPrivateFieldGet(this, _RuntimeKSQL_ksql, "f").streamQuery(sql);
|
|
59
|
-
for (let x of results) {
|
|
60
|
-
mapKeys(x, __classPrivateFieldGet(this, _RuntimeKSQL_tableKeyMap, "f")[input.resource]);
|
|
61
|
-
}
|
|
62
|
-
if (input.action == "findMany") {
|
|
63
|
-
return results;
|
|
64
|
-
}
|
|
65
|
-
resolved.results = results;
|
|
66
|
-
return resolved;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
const table = input.resource;
|
|
70
|
-
const tableKSQL = getKSQLTablename(input.resource, input?.context?.hydrate);
|
|
71
|
-
const where = (0, getWhere_1.getWhere)(SqlString.escapeId(tableKSQL), input.args, "mysql");
|
|
72
|
-
if (!where) {
|
|
73
|
-
throw new Error("Invalid $where");
|
|
74
|
-
}
|
|
75
|
-
const sql = SqlString.format(`SELECT * FROM ?? WHERE ${where};`, [
|
|
76
|
-
tableKSQL,
|
|
77
|
-
]);
|
|
78
|
-
let out = await __classPrivateFieldGet(this, _RuntimeKSQL_ksql, "f").streamQuery(sql).then((xs) => xs[0]);
|
|
79
|
-
if (out == null) {
|
|
80
|
-
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
81
|
-
}
|
|
82
|
-
mapKeys(out, __classPrivateFieldGet(this, _RuntimeKSQL_tableKeyMap, "f")[table]);
|
|
83
|
-
return out;
|
|
84
|
-
}
|
|
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"));
|
|
85
47
|
}
|
|
86
48
|
async $queryRaw(sql, values) {
|
|
87
|
-
return __classPrivateFieldGet(this,
|
|
49
|
+
return __classPrivateFieldGet(this, _RuntimeKSQL_dbCall, "f").call(this, SqlString.format(sql, values ?? []));
|
|
88
50
|
}
|
|
89
51
|
async $use(middleware) {
|
|
90
52
|
__classPrivateFieldGet(this, _RuntimeKSQL_middlewareHandler, "f").register(middleware);
|
|
@@ -93,39 +55,384 @@ class RuntimeKSQL {
|
|
|
93
55
|
return (0, shared_1.whereNeedsProcessing)(where);
|
|
94
56
|
}
|
|
95
57
|
async $prepareWhere(artifacts, table, data) {
|
|
96
|
-
return (0, shared_1._prepareWhere)(artifacts, table, data, __classPrivateFieldGet(this,
|
|
58
|
+
return (0, shared_1._prepareWhere)(artifacts, table, data, __classPrivateFieldGet(this, _RuntimeKSQL_dbCall, "f").bind(this), __classPrivateFieldGet(this, _RuntimeKSQL_formatQuery, "f").bind(this));
|
|
97
59
|
}
|
|
98
|
-
|
|
60
|
+
}
|
|
61
|
+
exports.RuntimeKSQL = RuntimeKSQL;
|
|
62
|
+
_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();
|
|
63
|
+
async function resolve(input, dbCall, formatQuery, middlewareHandler, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
64
|
+
// https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
|
|
65
|
+
let index = -1;
|
|
66
|
+
if (middlewareHandler.length() > 0) {
|
|
67
|
+
const resource = new async_hooks_1.AsyncResource("sdk-request");
|
|
68
|
+
const params = input;
|
|
69
|
+
const consumer = (paramsMaybeMutated) => {
|
|
70
|
+
const nextMiddleware = middlewareHandler.get(++index);
|
|
71
|
+
if (nextMiddleware != null) {
|
|
72
|
+
return nextMiddleware(paramsMaybeMutated, consumer);
|
|
73
|
+
}
|
|
74
|
+
const paramsChanged = { ...input, ...params };
|
|
75
|
+
return _resolve(paramsChanged, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
76
|
+
};
|
|
77
|
+
return resource.runInAsyncScope(() => consumer(params));
|
|
78
|
+
}
|
|
79
|
+
return _resolve(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
80
|
+
}
|
|
81
|
+
function _resolve(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
82
|
+
if (input.action === "findUnique") {
|
|
83
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
84
|
+
}
|
|
85
|
+
if (input.action === "findMany") {
|
|
86
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
87
|
+
}
|
|
88
|
+
if (input.action === "findManyPaginated") {
|
|
89
|
+
return getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
90
|
+
}
|
|
91
|
+
if (input.action === "create") {
|
|
99
92
|
throw new Error("Not implemented.");
|
|
100
93
|
}
|
|
101
|
-
|
|
94
|
+
if (input.action === "update") {
|
|
102
95
|
throw new Error("Not implemented.");
|
|
103
96
|
}
|
|
104
|
-
|
|
97
|
+
if (input.action === "updateMany") {
|
|
105
98
|
throw new Error("Not implemented.");
|
|
106
99
|
}
|
|
107
|
-
|
|
100
|
+
if (input.action === "delete") {
|
|
108
101
|
throw new Error("Not implemented.");
|
|
109
102
|
}
|
|
110
|
-
|
|
103
|
+
if (input.action === "deleteMany") {
|
|
111
104
|
throw new Error("Not implemented.");
|
|
112
105
|
}
|
|
106
|
+
throw new Error("Invalid action: " + input.action);
|
|
113
107
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
async function getData(input, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
109
|
+
const { action } = input;
|
|
110
|
+
const grabMany = action === "findMany" ||
|
|
111
|
+
action === "findManyPaginated" ||
|
|
112
|
+
action === "updateMany" ||
|
|
113
|
+
action === "deleteMany";
|
|
114
|
+
const data = await _getData(input, grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews);
|
|
115
|
+
if (data == null && !grabMany) {
|
|
116
|
+
throw new SDKNotFoundError_1.SDKNotFoundError();
|
|
117
|
+
}
|
|
118
|
+
const scalarFields = input.artifacts[input.resource].scalarFields;
|
|
119
|
+
if (action === "findManyPaginated" && data?.results != null) {
|
|
120
|
+
(0, shared_1.postProcess)(data.results, input.fields ?? scalarFields, true);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
(0, shared_1.postProcess)(data, input.fields ?? scalarFields, true);
|
|
124
|
+
}
|
|
125
|
+
return data;
|
|
120
126
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
async function _getData(input, grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
128
|
+
const { resource: table, artifacts, args, action } = input;
|
|
129
|
+
const tableArtifacts = artifacts[table];
|
|
130
|
+
const isInputFieldAnArray = Array.isArray(input.fields);
|
|
131
|
+
let fields = input.fields;
|
|
132
|
+
if (!Array.isArray(fields)) {
|
|
133
|
+
fields = tableArtifacts.scalarFields;
|
|
134
|
+
}
|
|
135
|
+
let useMaterializedView = !doNotUseMaterializedViews &&
|
|
136
|
+
// If fields isn't an array, we're only getting scalar fields,
|
|
137
|
+
// so no point using the materialized view.
|
|
138
|
+
isInputFieldAnArray &&
|
|
139
|
+
// We're getting relation fields
|
|
140
|
+
fields.some((x) => typeof x === "object") &&
|
|
141
|
+
Object.values(tableArtifacts.relationFields).filter((x) => x.type === "one-to-many__many-to-one" && x.kind === "many-to-one").length > 0 &&
|
|
142
|
+
!Object.values(tableArtifacts.relationFields).some((x) => x.type === "one-to-many__many-to-one" &&
|
|
143
|
+
x.kind === "many-to-one" &&
|
|
144
|
+
x.nullable === true);
|
|
145
|
+
const getTableName = useMaterializedView
|
|
146
|
+
? getMaterializedViewName
|
|
147
|
+
: getBaseTableName;
|
|
148
|
+
let where = undefined;
|
|
149
|
+
if (args?.$where != null) {
|
|
150
|
+
let argsMapped = args;
|
|
151
|
+
if (Array.isArray(argsMapped?.$where)) {
|
|
152
|
+
argsMapped = _.cloneDeep(argsMapped);
|
|
153
|
+
argsMapped.$where = argsMapped.$where[0];
|
|
154
|
+
}
|
|
155
|
+
const whereResult = (0, stringifyWhere_1.stringifyWhere)({
|
|
156
|
+
where: argsMapped.$where,
|
|
157
|
+
table: escapeId(getTableName(table)),
|
|
158
|
+
dialect: "mysql",
|
|
159
|
+
args: argsMapped,
|
|
160
|
+
});
|
|
161
|
+
if (whereResult) {
|
|
162
|
+
where = whereResult;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
let columns = [];
|
|
166
|
+
let mappedFields = [];
|
|
167
|
+
let relationFields = [];
|
|
168
|
+
for (let x of fields) {
|
|
169
|
+
if (typeof x === "string") {
|
|
170
|
+
const mappedField = tableArtifacts.mappedFields?.[x];
|
|
171
|
+
if (mappedField != null) {
|
|
172
|
+
mappedFields.push(x);
|
|
173
|
+
if (!columns.includes(mappedField.foreignKey)) {
|
|
174
|
+
columns.push(mappedField.foreignKey);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
columns.push(x);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
183
|
+
if (relationField == null) {
|
|
184
|
+
throw new Error(`Invalid relation field: ${x.name}`);
|
|
185
|
+
}
|
|
186
|
+
if (relationField.type === "one-to-many__many-to-one") {
|
|
187
|
+
relationFields.push(x);
|
|
188
|
+
if (!columns.includes(relationField.relation.foreignKey)) {
|
|
189
|
+
columns.push(relationField.relation.foreignKey);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (relationField.type === "many-to-many") {
|
|
193
|
+
relationFields.push(x);
|
|
194
|
+
if (!columns.includes(relationField.relations[0].referencedKey)) {
|
|
195
|
+
columns.push(relationField.relations[0].referencedKey);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (action === "findManyPaginated") {
|
|
201
|
+
// For cursor
|
|
202
|
+
if (!columns.includes(tableArtifacts.primaryKey)) {
|
|
203
|
+
columns.push(tableArtifacts.primaryKey);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (useMaterializedView) {
|
|
207
|
+
relationFields = relationFields.filter((x) => {
|
|
208
|
+
if (typeof x === "string") {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
212
|
+
if (relationField == null) {
|
|
213
|
+
throw new Error(`Invalid relation field: ${x.name}`);
|
|
214
|
+
}
|
|
215
|
+
// Since we're going to use the materialized view,
|
|
216
|
+
// filter out non-nullable many-to-one relations.
|
|
217
|
+
return !(relationField.type === "one-to-many__many-to-one" &&
|
|
218
|
+
relationField.kind === "many-to-one" &&
|
|
219
|
+
relationField.nullable === false);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
let s = useMaterializedView
|
|
223
|
+
? formatQuery(`SELECT * FROM ??`, [getTableName(table)])
|
|
224
|
+
: formatQuery(`SELECT ?? FROM ??`, [columns, getTableName(table)]);
|
|
225
|
+
if (where) {
|
|
226
|
+
s += ` WHERE ${where}`;
|
|
227
|
+
}
|
|
228
|
+
s += ";";
|
|
229
|
+
return dbCall(s).then((_result) => {
|
|
230
|
+
let result = grabMany ? _result : _result[0];
|
|
231
|
+
if (result == null) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
if (grabMany && Array.isArray(result)) {
|
|
235
|
+
// Important: ordering must be before pagination, since pagination is done in code
|
|
236
|
+
let orderBy;
|
|
237
|
+
if (args == null || args.$orderBy == null) {
|
|
238
|
+
orderBy = [{ column: tableArtifacts.primaryKey, direction: "asc" }];
|
|
239
|
+
}
|
|
240
|
+
else if (Array.isArray(args.$orderBy)) {
|
|
241
|
+
orderBy = args.$orderBy.map((x) => {
|
|
242
|
+
const [column, direction] = Object.entries(x)[0];
|
|
243
|
+
return { column, direction };
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
const [column, direction] = Object.entries(args.$orderBy)[0];
|
|
248
|
+
orderBy = [{ column, direction }];
|
|
249
|
+
}
|
|
250
|
+
for (let x of orderBy) {
|
|
251
|
+
if (!["asc", "desc"].includes(x.direction)) {
|
|
252
|
+
throw new Error(`Expected \`asc\` or \`desc\` for \`direction\` but got: ${x.direction}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
result = _.orderBy(result, orderBy.map((x) => x.column), orderBy.map((x) => x.direction));
|
|
256
|
+
if (action === "findManyPaginated") {
|
|
257
|
+
result = paginate(result, args, tableArtifacts.primaryKey, action);
|
|
258
|
+
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) => {
|
|
259
|
+
result.results = xx;
|
|
260
|
+
return result;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const limit = args?.$limit;
|
|
264
|
+
if (typeof limit === "number") {
|
|
265
|
+
result = result.slice(0, limit);
|
|
266
|
+
}
|
|
267
|
+
return Promise.all(result.map((x) => resolveDependentFields(table, x, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => mergeSubResults(x, xx))));
|
|
268
|
+
}
|
|
269
|
+
return resolveDependentFields(table, result, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => mergeSubResults(result, xx));
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
async function resolveDependentFields(table, parentData, mappedFields, relationFields, artifacts, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews) {
|
|
273
|
+
const tableArtifacts = artifacts[table];
|
|
274
|
+
return Promise.all([]
|
|
275
|
+
.concat(mappedFields.map((x) => {
|
|
276
|
+
const mappedField = tableArtifacts.mappedFields?.[x];
|
|
277
|
+
if (mappedField == null) {
|
|
278
|
+
throw new Error(`Invalid mappedField: ${x}`);
|
|
279
|
+
}
|
|
280
|
+
if (parentData?.[mappedField.foreignKey] == null) {
|
|
281
|
+
return { [x]: null };
|
|
282
|
+
}
|
|
283
|
+
const s = formatQuery(`SELECT ?? FROM ?? WHERE ?? = ?;`, [
|
|
284
|
+
mappedField.name,
|
|
285
|
+
getBaseTableName(mappedField.referencedTable),
|
|
286
|
+
mappedField.referencedKey,
|
|
287
|
+
parentData?.[mappedField.foreignKey],
|
|
288
|
+
]);
|
|
289
|
+
return dbCall(s).then((xs) => ({
|
|
290
|
+
[x]: xs?.[0]?.[mappedField.name] ?? null,
|
|
291
|
+
}));
|
|
292
|
+
}))
|
|
293
|
+
.concat(relationFields.map((x) => {
|
|
294
|
+
if (typeof x === "string") {
|
|
295
|
+
throw new Error(`Invalid field: ${x}`);
|
|
296
|
+
}
|
|
297
|
+
const relationField = tableArtifacts.relationFields?.[x.name];
|
|
298
|
+
if (relationField == null) {
|
|
299
|
+
throw new Error("Invalid field: " + table + "." + x.name);
|
|
300
|
+
}
|
|
301
|
+
if (relationField.type === "many-to-many") {
|
|
302
|
+
const junctionReferencedKey = relationField.relations[0].referencedKey;
|
|
303
|
+
const junctionKeyValue = parentData?.[junctionReferencedKey];
|
|
304
|
+
if (junctionKeyValue == null) {
|
|
305
|
+
return { [x.as ?? x.name]: [] };
|
|
306
|
+
}
|
|
307
|
+
let whereJunction = x.args != null && Array.isArray(x.args.$where)
|
|
308
|
+
? _.cloneDeep(x.args.$where[1])
|
|
309
|
+
: {};
|
|
310
|
+
whereJunction = {
|
|
311
|
+
$and: [
|
|
312
|
+
{ [relationField.relations[0].foreignKey]: junctionKeyValue },
|
|
313
|
+
whereJunction,
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
const key = relationField.relations[1].foreignKey;
|
|
317
|
+
const s = formatQuery(`SELECT ?? FROM ?? WHERE ${(0, stringifyWhere_1.stringifyWhere)({
|
|
318
|
+
where: whereJunction,
|
|
319
|
+
table: escapeId(getBaseTableName(relationField.junctionTable)),
|
|
320
|
+
dialect: "mysql",
|
|
321
|
+
// Since we're paginating, empty is fine
|
|
322
|
+
args: {},
|
|
323
|
+
})};`, [key, getBaseTableName(relationField.junctionTable)]);
|
|
324
|
+
return dbCall(s)
|
|
325
|
+
.then((xs) => xs.map((x) => x?.[key]))
|
|
326
|
+
.then((keys) => {
|
|
327
|
+
const whereDest = {
|
|
328
|
+
[relationField.relations[1].referencedKey]: { $in: keys },
|
|
329
|
+
};
|
|
330
|
+
const argsMapped = x.args == null ? {} : _.cloneDeep(x.args);
|
|
331
|
+
if (Array.isArray(argsMapped.$where)) {
|
|
332
|
+
argsMapped.$where = {
|
|
333
|
+
$and: [whereDest, argsMapped.$where[0]],
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
else if (argsMapped.$where != null) {
|
|
337
|
+
argsMapped.$where = { $and: [whereDest, argsMapped.$where] };
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
argsMapped.$where = whereDest;
|
|
341
|
+
}
|
|
342
|
+
return _getData({
|
|
343
|
+
resource: relationField.table,
|
|
344
|
+
args: argsMapped,
|
|
345
|
+
fields: x.fields,
|
|
346
|
+
artifacts,
|
|
347
|
+
action: relationField.grabMany ? "findMany" : "findUnique",
|
|
348
|
+
}, relationField.grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => ({ [x.as ?? x.name]: xx }));
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
if (relationField.type === "one-to-many__many-to-one") {
|
|
352
|
+
const referencedKey = relationField.relation.referencedKey;
|
|
353
|
+
const foreignKeyValue = parentData?.[relationField.relation.foreignKey];
|
|
354
|
+
if (foreignKeyValue == null) {
|
|
355
|
+
return { [x.as ?? x.name]: relationField.grabMany ? [] : null };
|
|
356
|
+
}
|
|
357
|
+
const whereRef = { [referencedKey]: foreignKeyValue };
|
|
358
|
+
const argsMapped = x.args == null ? {} : _.cloneDeep(x.args);
|
|
359
|
+
if (argsMapped.$where == null) {
|
|
360
|
+
argsMapped.$where = whereRef;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
argsMapped.$where = { $and: [whereRef, argsMapped.$where] };
|
|
364
|
+
}
|
|
365
|
+
return _getData({
|
|
366
|
+
resource: relationField.table,
|
|
367
|
+
args: argsMapped,
|
|
368
|
+
fields: x.fields,
|
|
369
|
+
artifacts,
|
|
370
|
+
action: relationField.grabMany ? "findMany" : "findUnique",
|
|
371
|
+
}, relationField.grabMany, dbCall, formatQuery, getBaseTableName, getMaterializedViewName, doNotUseMaterializedViews).then((xx) => ({ [x.as ?? x.name]: xx }));
|
|
372
|
+
}
|
|
373
|
+
throw new Error(`Invalid relationField.type`);
|
|
374
|
+
})));
|
|
375
|
+
}
|
|
376
|
+
function mergeSubResults(result, subResults) {
|
|
377
|
+
for (let x of subResults) {
|
|
378
|
+
result = { ...result, ...x };
|
|
379
|
+
}
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
382
|
+
function paginate(data, args, primaryKey, action) {
|
|
383
|
+
if (action === "findManyPaginated") {
|
|
384
|
+
if (typeof args?.$paginate?.limit === "number") {
|
|
385
|
+
const totalCount = data.length;
|
|
386
|
+
const limit = args.$paginate.limit;
|
|
387
|
+
const offset = args.$paginate.offset ?? 0;
|
|
388
|
+
data = data.slice(offset, offset + limit);
|
|
389
|
+
return {
|
|
390
|
+
results: data,
|
|
391
|
+
paginationInfo: { totalCount },
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
if (typeof args?.$paginate?.first === "number" ||
|
|
395
|
+
typeof args?.$paginate?.last === "number") {
|
|
396
|
+
const totalCount = data.length;
|
|
397
|
+
let argsMapped = args;
|
|
398
|
+
// Convert cursor(s) for graphql-relay
|
|
399
|
+
for (let k of ["after", "before"]) {
|
|
400
|
+
if (args?.$paginate?.[k] != null) {
|
|
401
|
+
argsMapped = _.cloneDeep(argsMapped);
|
|
402
|
+
const offset = data.findIndex((x) => x[primaryKey] === (0, cursor_1.decodeCursor)(args.$paginate[k]));
|
|
403
|
+
if (offset === -1) {
|
|
404
|
+
throw new Error(`Invalid cursor: ${args.$paginate[k]}`);
|
|
405
|
+
}
|
|
406
|
+
argsMapped.$paginate[k] = (0, graphql_relay_1.offsetToCursor)(offset);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
const connection = (0, graphql_relay_1.connectionFromArray)(data, argsMapped.$paginate);
|
|
410
|
+
const results = connection.edges.map((x) => x.node);
|
|
411
|
+
// Convert cursors back
|
|
412
|
+
const startKey = results[0]?.[primaryKey];
|
|
413
|
+
const endKey = results[results.length - 1]?.[primaryKey];
|
|
414
|
+
const startCursor = startKey == null ? null : (0, cursor_1.encodeCursor)(startKey);
|
|
415
|
+
const endCursor = endKey == null ? null : (0, cursor_1.encodeCursor)(endKey);
|
|
416
|
+
return {
|
|
417
|
+
results,
|
|
418
|
+
paginationInfo: {
|
|
419
|
+
...connection.pageInfo,
|
|
420
|
+
startCursor,
|
|
421
|
+
endCursor,
|
|
422
|
+
totalCount,
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
throw new Error(`Invalid pagination action: ${action}`);
|
|
428
|
+
}
|
|
429
|
+
function mapResult(data) {
|
|
430
|
+
return data.map((x) => {
|
|
431
|
+
for (let k of Object.keys(x)) {
|
|
432
|
+
if (typeof x[k] === "string" && (k === "uuid" || k.endsWith("Uuid"))) {
|
|
433
|
+
x[k] = x[k].toLocaleLowerCase();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return x;
|
|
437
|
+
});
|
|
131
438
|
}
|
|
@@ -10,15 +10,16 @@ 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_middlewareHandler;
|
|
13
|
+
var _RuntimeMySQL_dialect, _RuntimeMySQL_mysqlClient, _RuntimeMySQL_middlewareHandler;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RuntimeMySQL = void 0;
|
|
16
16
|
const SqlString = require("sqlstring");
|
|
17
|
-
const
|
|
17
|
+
const MySQL_1 = require("./lib/MySQL");
|
|
18
18
|
const shared_1 = require("./lib/shared");
|
|
19
19
|
class RuntimeMySQL {
|
|
20
20
|
constructor(clientOpts, otherOpts, artifacts) {
|
|
21
21
|
_RuntimeMySQL_dialect.set(this, "mysql");
|
|
22
|
+
_RuntimeMySQL_mysqlClient.set(this, void 0);
|
|
22
23
|
_RuntimeMySQL_middlewareHandler.set(this, void 0);
|
|
23
24
|
__classPrivateFieldSet(this, _RuntimeMySQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
|
|
24
25
|
if (otherOpts.supplementClientOpts) {
|
|
@@ -60,7 +61,7 @@ class RuntimeMySQL {
|
|
|
60
61
|
...clientOpts,
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
|
-
(
|
|
64
|
+
__classPrivateFieldSet(this, _RuntimeMySQL_mysqlClient, new MySQL_1.MySQL(clientOpts), "f");
|
|
64
65
|
}
|
|
65
66
|
async resolve(input) {
|
|
66
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 ?? {});
|
|
@@ -78,14 +79,14 @@ class RuntimeMySQL {
|
|
|
78
79
|
return (0, shared_1._prepareWhere)(artifacts, table, data, this.dbCall.bind(this), this.formatQuery.bind(this));
|
|
79
80
|
}
|
|
80
81
|
dbCall(q) {
|
|
81
|
-
return (
|
|
82
|
+
return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").query(q);
|
|
82
83
|
}
|
|
83
84
|
formatQuery(q, values) {
|
|
84
85
|
return SqlString.format(q, values);
|
|
85
86
|
}
|
|
86
87
|
beginTransaction() {
|
|
87
|
-
return (
|
|
88
|
+
return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").beginTransaction();
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
exports.RuntimeMySQL = RuntimeMySQL;
|
|
91
|
-
_RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
|
|
92
|
+
_RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_mysqlClient = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
|
|
@@ -32,6 +32,13 @@ function getOrderBy(args, primaryKey) {
|
|
|
32
32
|
out = flipOrderByDirection(out);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
if (Array.isArray(out)) {
|
|
36
|
+
for (let x of out) {
|
|
37
|
+
if (!["asc", "desc"].includes(x.direction)) {
|
|
38
|
+
throw new Error(`Expected \`asc\` or \`desc\` for \`direction\` but got: ${x.direction}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
35
42
|
return { orderBy: out, flip };
|
|
36
43
|
}
|
|
37
44
|
exports.getOrderBy = getOrderBy;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MySQL = void 0;
|
|
4
|
+
const mysql = require("mysql");
|
|
5
|
+
const P = require("bluebird");
|
|
6
|
+
P.promisifyAll(require("mysql/lib/Connection").prototype);
|
|
7
|
+
P.promisifyAll(require("mysql/lib/Pool").prototype);
|
|
8
|
+
class MySQL {
|
|
9
|
+
constructor(opts) {
|
|
10
|
+
this.pool = mysql.createPool(opts);
|
|
11
|
+
}
|
|
12
|
+
// http://bluebirdjs.com/docs/api/promise.using.html
|
|
13
|
+
query(...args) {
|
|
14
|
+
return P.using(this.getConnection(), (connection) => connection.queryAsync(...args));
|
|
15
|
+
}
|
|
16
|
+
async beginTransaction() {
|
|
17
|
+
return P.using(this.getConnection(), async (connection) => {
|
|
18
|
+
async function handleError(err) {
|
|
19
|
+
await connection.rollbackAsync();
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
await connection.beginTransactionAsync();
|
|
23
|
+
return {
|
|
24
|
+
commit: () => connection.commitAsync().catch(handleError),
|
|
25
|
+
dbCall: (q) => connection.queryAsync(q).catch(handleError),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// http://bluebirdjs.com/docs/api/disposer.html
|
|
30
|
+
async getConnection() {
|
|
31
|
+
return this.pool
|
|
32
|
+
.getConnectionAsync()
|
|
33
|
+
.disposer((connection) => connection.release());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.MySQL = MySQL;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext } from "../IRuntime";
|
|
1
|
+
import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext } from "../IRuntime";
|
|
2
2
|
import type { TMiddleware, TResolveParams } from "../IRuntime";
|
|
3
3
|
export declare function resolve(input: TResolveParams, dbCall: TDbCall, formatQuery: TFormatQuery, beginTransaction: TBeginTransaction, dialect: IDialect, middlewareHandler: MiddlewareHandler<TMiddleware>, context: TContext): Promise<any>;
|
|
4
4
|
export declare class MiddlewareHandler<M extends Function> {
|
|
@@ -8,5 +8,6 @@ export declare class MiddlewareHandler<M extends Function> {
|
|
|
8
8
|
has(id: number): boolean;
|
|
9
9
|
length(): number;
|
|
10
10
|
}
|
|
11
|
+
export declare function postProcess(data: any, fields: IGetSQLASTInput["fields"], shouldRemoveExtraKeys: boolean): void;
|
|
11
12
|
export declare function whereNeedsProcessing(where: any): boolean;
|
|
12
13
|
export declare function _prepareWhere(artifacts: IArtifacts, table: string, data: any, dbCall: TDbCall, formatQuery: TFormatQuery): Promise<{}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports._prepareWhere = exports.whereNeedsProcessing = exports.MiddlewareHandler = exports.resolve = void 0;
|
|
3
|
+
exports._prepareWhere = exports.whereNeedsProcessing = exports.postProcess = exports.MiddlewareHandler = exports.resolve = void 0;
|
|
4
4
|
// @ts-ignore
|
|
5
5
|
// import * as queryAST from "join-monster/dist/query-ast-to-sql-ast";
|
|
6
6
|
// @ts-ignore
|
|
@@ -102,7 +102,8 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
102
102
|
limit = input.args.$paginate.limit;
|
|
103
103
|
offset = input.args.$paginate.offset;
|
|
104
104
|
}
|
|
105
|
-
else
|
|
105
|
+
else if (typeof input?.args?.$paginate?.first === "number" ||
|
|
106
|
+
typeof input?.args?.$paginate?.last === "number") {
|
|
106
107
|
paginationType = "cursor";
|
|
107
108
|
limit = (typeof input?.args?.$paginate?.first === "number"
|
|
108
109
|
? input?.args?.$paginate?.first
|
|
@@ -119,11 +120,19 @@ async function getData(input, dbCall, formatQuery, dialect) {
|
|
|
119
120
|
primaryKey,
|
|
120
121
|
(0, cursor_1.decodeCursor)(cursor),
|
|
121
122
|
])).then((xs) => xs[0]);
|
|
123
|
+
if (rowWithMatchingCursor == null) {
|
|
124
|
+
throw new Error(`Invalid cursor: ${cursor}`);
|
|
125
|
+
}
|
|
122
126
|
}
|
|
123
127
|
}
|
|
128
|
+
else {
|
|
129
|
+
throw new Error(`Invalid $paginate: ${input?.args?.$paginate}`);
|
|
130
|
+
}
|
|
124
131
|
}
|
|
125
132
|
else if (action === "findMany") {
|
|
126
|
-
|
|
133
|
+
if (typeof input?.args?.$limit === "number") {
|
|
134
|
+
limit = input?.args?.$limit;
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
// we need to read the query AST and build a new "SQL AST" from which the SQL and
|
|
129
138
|
// const sqlAST = queryAST.queryASTToSqlAST(resolveInfo, options, context);
|
|
@@ -700,6 +709,7 @@ function postProcess(data, fields, shouldRemoveExtraKeys) {
|
|
|
700
709
|
}
|
|
701
710
|
(0, runTransforms_1.runTransforms)(data, fields);
|
|
702
711
|
}
|
|
712
|
+
exports.postProcess = postProcess;
|
|
703
713
|
function removeExtraKeys(data, fields) {
|
|
704
714
|
if (data == null || (Array.isArray(data) && data[0] == null)) {
|
|
705
715
|
return;
|
package/package.json
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@technicity/data-service-generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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
|
-
"create-database": "env-cmd node ./test/mysql/create-database.js && env-cmd node ./test/mssql/create-database.js",
|
|
11
|
-
"generate": "npm run compile && npm run create-database && env-cmd node ./test/mysql/generate.js && env-cmd node ./test/mssql/generate.js",
|
|
10
|
+
"create-database": "env-cmd node ./test/mysql/create-database.js && env-cmd node ./test/mysql8/create-database.js && env-cmd node ./test/mssql/create-database.js",
|
|
11
|
+
"generate": "npm run compile && npm run create-database && env-cmd node ./test/mysql/generate.js && env-cmd node ./test/mysql8/generate.js && env-cmd node ./test/mssql/generate.js",
|
|
12
12
|
"test": "npm run generate && env-cmd mocha ./test/addNullFallbacks.test.js && env-cmd mocha ./test/stringifyWhere.test.js && env-cmd mocha ./test/test.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"bluebird": "^3.7.2",
|
|
16
16
|
"change-case": "^4.1.1",
|
|
17
17
|
"fs-extra": "10.0.0",
|
|
18
|
-
"graphql": "
|
|
19
|
-
"
|
|
18
|
+
"graphql": "15.8.0",
|
|
19
|
+
"graphql-relay": "^0.9.0",
|
|
20
|
+
"join-monster": "apalm/join-monster#340bcad96da4c268e874d07552d564c98ecf39ea",
|
|
20
21
|
"json-schema-to-typescript": "10.1.5",
|
|
21
22
|
"lodash": "^4.17.20",
|
|
22
23
|
"mssql": "^6.3.1",
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/fs-extra": "9.0.13",
|
|
31
|
-
"@types/lodash": "4.14.
|
|
32
|
+
"@types/lodash": "4.14.177",
|
|
32
33
|
"@types/mssql": "^6.0.7",
|
|
33
34
|
"@types/node": "14.17.9",
|
|
34
35
|
"@types/prettier": "^2.1.5",
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
"@types/uuid": "^8.3.1",
|
|
37
38
|
"env-cmd": "^10.1.0",
|
|
38
39
|
"mocha": "9.1.3",
|
|
39
|
-
"sinon": "
|
|
40
|
+
"sinon": "12.0.1",
|
|
40
41
|
"typescript": "^4.0.5"
|
|
41
42
|
}
|
|
42
43
|
}
|
package/dist/mysql.d.ts
DELETED
package/dist/mysql.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const mysql = require("mysql");
|
|
3
|
-
const Promise = require("bluebird");
|
|
4
|
-
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
|
|
5
|
-
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
|
|
6
|
-
let pool;
|
|
7
|
-
function init(opts) {
|
|
8
|
-
pool = mysql.createPool(opts);
|
|
9
|
-
}
|
|
10
|
-
// http://bluebirdjs.com/docs/api/disposer.html
|
|
11
|
-
async function getConnection() {
|
|
12
|
-
return pool
|
|
13
|
-
.getConnectionAsync()
|
|
14
|
-
.disposer((connection) => connection.release());
|
|
15
|
-
}
|
|
16
|
-
// http://bluebirdjs.com/docs/api/promise.using.html
|
|
17
|
-
function query(...args) {
|
|
18
|
-
return Promise.using(getConnection(), (connection) => connection.queryAsync(...args));
|
|
19
|
-
}
|
|
20
|
-
async function beginTransaction() {
|
|
21
|
-
return Promise.using(getConnection(), async (connection) => {
|
|
22
|
-
async function handleError(err) {
|
|
23
|
-
await connection.rollbackAsync();
|
|
24
|
-
throw err;
|
|
25
|
-
}
|
|
26
|
-
await connection.beginTransactionAsync();
|
|
27
|
-
return {
|
|
28
|
-
commit: () => connection.commitAsync().catch(handleError),
|
|
29
|
-
dbCall: (q) => connection.queryAsync(q).catch(handleError),
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
module.exports.init = init;
|
|
34
|
-
module.exports.query = query;
|
|
35
|
-
module.exports.beginTransaction = beginTransaction;
|