joist-knex 1.228.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/build/buildKnexQuery.d.ts +9 -0
- package/build/buildKnexQuery.d.ts.map +1 -0
- package/build/buildKnexQuery.js +58 -0
- package/build/buildKnexQuery.js.map +1 -0
- package/build/index.d.ts +29 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +34 -0
- package/build/index.js.map +1 -0
- package/build/utils.d.ts +2 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +7 -0
- package/build/utils.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
# joist-knex
|
|
3
|
+
|
|
4
|
+
`joist-knex` provides a `buildQuery` function that takes `em.find`-style input and returns a Knex `QueryBuilder`.
|
|
5
|
+
|
|
6
|
+
This is useful for creating the "last 5%" of queries that need SQL features that `em.find` doesn't support, i.e. primarily aggregation, but also more complicated joins, query conditions, etc.
|
|
7
|
+
|
|
8
|
+
Knex itself is well-suited to this task, because it has structured methods like `clearOrder`, `select`, etc. to help munge the initial `buildQuery`-created query into the custom query, without tedious string parsing.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ParsedFindQuery } from "joist-orm";
|
|
2
|
+
import { Knex } from "knex";
|
|
3
|
+
import QueryBuilder = Knex.QueryBuilder;
|
|
4
|
+
/** Transforms Joist's internal `ParsedFindQuery` AST into a Knex query builder. */
|
|
5
|
+
export declare function buildKnexQuery(knex: Knex, parsed: ParsedFindQuery, settings: {
|
|
6
|
+
limit?: number;
|
|
7
|
+
offset?: number;
|
|
8
|
+
}): QueryBuilder<{}, unknown[]>;
|
|
9
|
+
//# sourceMappingURL=buildKnexQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildKnexQuery.d.ts","sourceRoot":"","sources":["../src/buildKnexQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,eAAe,EAAe,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;AAExC,mFAAmF;AACnF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CA2D7B"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildKnexQuery = buildKnexQuery;
|
|
4
|
+
const joist_orm_1 = require("joist-orm");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
/** Transforms Joist's internal `ParsedFindQuery` AST into a Knex query builder. */
|
|
7
|
+
function buildKnexQuery(knex, parsed, settings) {
|
|
8
|
+
const { limit, offset } = settings;
|
|
9
|
+
// If we're doing o2m joins, add a `DISTINCT` clause to avoid duplicates
|
|
10
|
+
const needsDistinct = parsed.tables.some((t) => t.join === "outer" && t.distinct !== false);
|
|
11
|
+
// We need the `knex` param to call `knex.raw`
|
|
12
|
+
const asRaw = (t) => knex.raw(`${(0, joist_orm_1.kq)(t.table)} as ${(0, joist_orm_1.kq)(t.alias)}`);
|
|
13
|
+
const primary = parsed.tables.find((t) => t.join === "primary");
|
|
14
|
+
let query = knex.from(asRaw(primary));
|
|
15
|
+
parsed.selects.forEach((s, i) => {
|
|
16
|
+
const maybeDistinct = i === 0 && needsDistinct ? "distinct " : "";
|
|
17
|
+
query.select(knex.raw(`${maybeDistinct}${s}`));
|
|
18
|
+
});
|
|
19
|
+
parsed.tables.forEach((t) => {
|
|
20
|
+
switch (t.join) {
|
|
21
|
+
case "inner":
|
|
22
|
+
query.join(asRaw(t), knex.raw(t.col1), knex.raw(t.col2));
|
|
23
|
+
break;
|
|
24
|
+
case "outer":
|
|
25
|
+
query.leftOuterJoin(asRaw(t), knex.raw(t.col1), knex.raw(t.col2));
|
|
26
|
+
break;
|
|
27
|
+
case "primary":
|
|
28
|
+
// ignore
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
(0, utils_1.assertNever)(t);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
if (parsed.lateralJoins) {
|
|
35
|
+
query.joinRaw(parsed.lateralJoins.joins.join("\n"), parsed.lateralJoins.bindings);
|
|
36
|
+
}
|
|
37
|
+
if (parsed.condition) {
|
|
38
|
+
const where = joist_orm_1.internals.buildWhereClause(parsed.condition, true);
|
|
39
|
+
if (where) {
|
|
40
|
+
const [sql, bindings] = where;
|
|
41
|
+
query.whereRaw(sql, bindings);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
parsed.orderBys &&
|
|
45
|
+
parsed.orderBys.forEach(({ alias, column, order }) => {
|
|
46
|
+
// If we're doing "select distinct" for o2m joins, then all order bys must be selects
|
|
47
|
+
if (needsDistinct) {
|
|
48
|
+
query.select(knex.raw((0, joist_orm_1.kqDot)(alias, column)));
|
|
49
|
+
}
|
|
50
|
+
query.orderBy(knex.raw((0, joist_orm_1.kqDot)(alias, column)), order);
|
|
51
|
+
});
|
|
52
|
+
if (limit)
|
|
53
|
+
query.limit(limit);
|
|
54
|
+
if (offset)
|
|
55
|
+
query.offset(offset);
|
|
56
|
+
return query;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=buildKnexQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildKnexQuery.js","sourceRoot":"","sources":["../src/buildKnexQuery.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Entity, FilterAndSettings, MaybeAbstractEntityConstructor } from "joist-orm";
|
|
2
|
+
import { Knex } from "knex";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the Knex queries from `em.find`-style parameters.
|
|
5
|
+
*
|
|
6
|
+
* This is useful for the "last 5%" of SQL queries that require SQL features that `em.find`
|
|
7
|
+
* itself doesn't support, i.e. primarily aggregation, but also complicated joins. etc.
|
|
8
|
+
*
|
|
9
|
+
* You can also `buildQuery` to get the regular `em.find` niceties around great join syntax,
|
|
10
|
+
* join pruning, inline conditions, etc., but then take the `QueryBuilder` that it produces
|
|
11
|
+
* and "muck with it". I.e. add different order bys, group bys, etc.
|
|
12
|
+
*
|
|
13
|
+
* The Knex API is actually well-suited for this, as it provides structure-aware methods like
|
|
14
|
+
* `clearOrder`, `clearSelect`, etc. that mean you can munge the initial query without any
|
|
15
|
+
* complicated string parsing.
|
|
16
|
+
*
|
|
17
|
+
* @param knex The Knex instance to use for building the query.
|
|
18
|
+
* @param type The primary entity type that `filter` is based on.
|
|
19
|
+
* @param filter[keepAliases] Marks specific aliases to keep in the query, even if they are not used
|
|
20
|
+
* by any selects or conditions, i.e. because you plan on adding your own joins/conditions
|
|
21
|
+
* against the `QueryBuilder` directly.
|
|
22
|
+
* @param filter[pruneJoins] Disables removing any unused joins, i.e. because you plan on adding your
|
|
23
|
+
* own joins/conditions against the `QueryBuilder` directly.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildQuery<T extends Entity>(knex: Knex, type: MaybeAbstractEntityConstructor<T>, filter: FilterAndSettings<T> & {
|
|
26
|
+
pruneJoins?: boolean;
|
|
27
|
+
keepAliases?: string[];
|
|
28
|
+
}): Knex.QueryBuilder<{}, unknown[]>;
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAe,8BAA8B,EAAkB,MAAM,WAAW,CAAC;AACnH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,8BAA8B,CAAC,CAAC,CAAC,EACvC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,GACA,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAclC"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildQuery = buildQuery;
|
|
4
|
+
const joist_orm_1 = require("joist-orm");
|
|
5
|
+
const buildKnexQuery_1 = require("./buildKnexQuery");
|
|
6
|
+
/**
|
|
7
|
+
* Builds the Knex queries from `em.find`-style parameters.
|
|
8
|
+
*
|
|
9
|
+
* This is useful for the "last 5%" of SQL queries that require SQL features that `em.find`
|
|
10
|
+
* itself doesn't support, i.e. primarily aggregation, but also complicated joins. etc.
|
|
11
|
+
*
|
|
12
|
+
* You can also `buildQuery` to get the regular `em.find` niceties around great join syntax,
|
|
13
|
+
* join pruning, inline conditions, etc., but then take the `QueryBuilder` that it produces
|
|
14
|
+
* and "muck with it". I.e. add different order bys, group bys, etc.
|
|
15
|
+
*
|
|
16
|
+
* The Knex API is actually well-suited for this, as it provides structure-aware methods like
|
|
17
|
+
* `clearOrder`, `clearSelect`, etc. that mean you can munge the initial query without any
|
|
18
|
+
* complicated string parsing.
|
|
19
|
+
*
|
|
20
|
+
* @param knex The Knex instance to use for building the query.
|
|
21
|
+
* @param type The primary entity type that `filter` is based on.
|
|
22
|
+
* @param filter[keepAliases] Marks specific aliases to keep in the query, even if they are not used
|
|
23
|
+
* by any selects or conditions, i.e. because you plan on adding your own joins/conditions
|
|
24
|
+
* against the `QueryBuilder` directly.
|
|
25
|
+
* @param filter[pruneJoins] Disables removing any unused joins, i.e. because you plan on adding your
|
|
26
|
+
* own joins/conditions against the `QueryBuilder` directly.
|
|
27
|
+
*/
|
|
28
|
+
function buildQuery(knex, type, filter) {
|
|
29
|
+
const meta = (0, joist_orm_1.getMetadata)(type);
|
|
30
|
+
const { where, conditions, orderBy, limit, offset, pruneJoins = true, keepAliases = [], softDeletes = "exclude", } = filter;
|
|
31
|
+
const parsed = (0, joist_orm_1.parseFindQuery)(meta, where, { conditions, orderBy, pruneJoins, keepAliases, softDeletes });
|
|
32
|
+
return (0, buildKnexQuery_1.buildKnexQuery)(knex, parsed, { limit, offset });
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AA0BA,gCAqBC;AA/CD,yCAAmH;AAEnH,qDAAkD;AAElD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,UAAU,CACxB,IAAU,EACV,IAAuC,EACvC,MAGC;IAED,MAAM,IAAI,GAAG,IAAA,uBAAW,EAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,EACJ,KAAK,EACL,UAAU,EACV,OAAO,EACP,KAAK,EACL,MAAM,EACN,UAAU,GAAG,IAAI,EACjB,WAAW,GAAG,EAAE,EAChB,WAAW,GAAG,SAAS,GACxB,GAAG,MAAM,CAAC;IACX,MAAM,MAAM,GAAG,IAAA,0BAAc,EAAC,IAAI,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1G,OAAO,IAAA,+BAAc,EAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACzD,CAAC"}
|
package/build/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAE3C"}
|
package/build/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;AAAA,kCAEC;AAFD,SAAgB,WAAW,CAAC,CAAQ;IAClC,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "joist-knex",
|
|
3
|
+
"version": "1.228.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/joist-orm/joist-orm.git",
|
|
8
|
+
"directory": "packages/knex"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.js",
|
|
11
|
+
"types": "build/index.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"format": "prettier --ignore-path ../../.prettierignore --write '{schema,migrations,src}/**/*.{ts,js,tsx,jsx,graphql}'"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"build"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"knex": "^3.1.0",
|
|
20
|
+
"pg": "^8.13.3"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@swc/core": "^1.10.16",
|
|
24
|
+
"@swc/jest": "^0.2.37",
|
|
25
|
+
"@types/jest": "^29.5.14",
|
|
26
|
+
"@types/node": "^22.13.4",
|
|
27
|
+
"jest": "30.0.0-alpha.7",
|
|
28
|
+
"prettier": "^3.5.1",
|
|
29
|
+
"prettier-plugin-organize-imports": "^4.1.0",
|
|
30
|
+
"ts-node-dev": "^2.0.0",
|
|
31
|
+
"tsconfig-paths": "^4.2.0",
|
|
32
|
+
"typescript": "5.7.3"
|
|
33
|
+
}
|
|
34
|
+
}
|