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 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":";;AAMA,wCA+DC;AArED,yCAA+E;AAE/E,mCAAsC;AAGtC,mFAAmF;AACnF,SAAgB,cAAc,CAC5B,IAAU,EACV,MAAuB,EACvB,QAA6C;IAE7C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAEnC,wEAAwE;IACxE,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC;IAE5F,8CAA8C;IAC9C,MAAM,KAAK,GAAG,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAA,cAAE,EAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAA,cAAE,EAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE/E,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAE,CAAC;IAEjE,IAAI,KAAK,GAAgC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1B,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,OAAO;gBACV,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAChE,MAAM;YACR,KAAK,OAAO;gBACV,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzE,MAAM;YACR,KAAK,SAAS;gBACZ,SAAS;gBACT,MAAM;YACR;gBACE,IAAA,mBAAW,EAAC,CAAC,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpF,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,qBAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;YAC9B,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,QAAQ;QACb,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YACnD,qFAAqF;YACrF,IAAI,aAAa,EAAE,CAAC;gBAClB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAA,iBAAK,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAA,iBAAK,EAAC,KAAK,EAAE,MAAM,CAAC,CAAQ,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IAEL,IAAI,KAAK;QAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,MAAM;QAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -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"}
@@ -0,0 +1,2 @@
1
+ export declare function assertNever(x: never): never;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -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,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertNever = assertNever;
4
+ function assertNever(x) {
5
+ throw new Error("Unexpected object: " + x);
6
+ }
7
+ //# sourceMappingURL=utils.js.map
@@ -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
+ }