@loomcore/api 0.1.118 → 0.1.120
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/databases/postgres/queries/postgres-get-all.query.js +7 -3
- package/dist/databases/postgres/queries/postgres-get-by-id.query.js +7 -4
- package/dist/databases/postgres/queries/postgres-get.query.js +8 -5
- package/dist/databases/postgres/utils/build-join-clauses.d.ts +4 -1
- package/dist/databases/postgres/utils/build-join-clauses.js +33 -2
- package/dist/databases/postgres/utils/build-order-by-clause.d.ts +4 -1
- package/dist/databases/postgres/utils/build-order-by-clause.js +3 -2
- package/dist/databases/postgres/utils/build-select-clause.d.ts +1 -0
- package/dist/databases/postgres/utils/build-select-clause.js +169 -11
- package/dist/middleware/error-handler.js +1 -1
- package/package.json +2 -2
|
@@ -3,14 +3,18 @@ import { InnerJoin } from "../../operations/inner-join.operation.js";
|
|
|
3
3
|
import { LeftJoinMany } from "../../operations/left-join-many.operation.js";
|
|
4
4
|
import { buildJoinClauses } from '../utils/build-join-clauses.js';
|
|
5
5
|
import { buildSelectClause } from '../utils/build-select-clause.js';
|
|
6
|
-
import { transformJoinResults } from '../utils/transform-join-results.js';
|
|
7
6
|
export async function getAll(client, operations, pluralResourceName) {
|
|
8
|
-
const joinClauses = buildJoinClauses(operations, pluralResourceName);
|
|
9
7
|
const hasJoins = operations.some(op => op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany);
|
|
8
|
+
const joinClauses = hasJoins
|
|
9
|
+
? buildJoinClauses(operations, pluralResourceName, { oneToOneOnly: true })
|
|
10
|
+
: buildJoinClauses(operations, pluralResourceName);
|
|
10
11
|
const selectClause = hasJoins
|
|
11
12
|
? await buildSelectClause(client, pluralResourceName, operations)
|
|
12
13
|
: '*';
|
|
13
14
|
const query = `SELECT ${selectClause} FROM "${pluralResourceName}" ${joinClauses}`;
|
|
14
15
|
const result = await client.query(query);
|
|
15
|
-
|
|
16
|
+
if (hasJoins) {
|
|
17
|
+
return result.rows.map(r => r.entity);
|
|
18
|
+
}
|
|
19
|
+
return result.rows;
|
|
16
20
|
}
|
|
@@ -3,14 +3,15 @@ import { InnerJoin } from "../../operations/inner-join.operation.js";
|
|
|
3
3
|
import { LeftJoinMany } from "../../operations/left-join-many.operation.js";
|
|
4
4
|
import { buildJoinClauses } from "../utils/build-join-clauses.js";
|
|
5
5
|
import { buildSelectClause } from "../utils/build-select-clause.js";
|
|
6
|
-
import { transformJoinResults } from "../utils/transform-join-results.js";
|
|
7
6
|
import { BadRequestError } from '../../../errors/index.js';
|
|
8
7
|
import { buildWhereClause } from '../utils/build-where-clause.js';
|
|
9
8
|
export async function getById(client, operations, queryObject, id, pluralResourceName) {
|
|
10
9
|
if (!id)
|
|
11
10
|
throw new BadRequestError('id is required');
|
|
12
|
-
const joinClauses = buildJoinClauses(operations, pluralResourceName);
|
|
13
11
|
const hasJoins = operations.some(op => op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany);
|
|
12
|
+
const joinClauses = hasJoins
|
|
13
|
+
? buildJoinClauses(operations, pluralResourceName, { oneToOneOnly: true })
|
|
14
|
+
: buildJoinClauses(operations, pluralResourceName);
|
|
14
15
|
const selectClause = hasJoins
|
|
15
16
|
? await buildSelectClause(client, pluralResourceName, operations)
|
|
16
17
|
: '*';
|
|
@@ -23,6 +24,8 @@ export async function getById(client, operations, queryObject, id, pluralResourc
|
|
|
23
24
|
if (result.rows.length === 0) {
|
|
24
25
|
return null;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
if (hasJoins) {
|
|
28
|
+
return result.rows[0].entity;
|
|
29
|
+
}
|
|
30
|
+
return result.rows[0];
|
|
28
31
|
}
|
|
@@ -5,15 +5,16 @@ import { buildWhereClause } from "../utils/build-where-clause.js";
|
|
|
5
5
|
import { buildOrderByClause } from "../utils/build-order-by-clause.js";
|
|
6
6
|
import { buildJoinClauses } from "../utils/build-join-clauses.js";
|
|
7
7
|
import { buildSelectClause } from "../utils/build-select-clause.js";
|
|
8
|
-
import { transformJoinResults } from "../utils/transform-join-results.js";
|
|
9
8
|
import { executeCountQuery } from "../utils/build-count-query.js";
|
|
10
9
|
import { apiUtils } from "../../../utils/api.utils.js";
|
|
11
10
|
import { buildPaginationClause } from '../utils/build-pagination-clause.js';
|
|
12
11
|
export async function get(client, operations, queryOptions, pluralResourceName) {
|
|
13
|
-
const joinClauses = buildJoinClauses(operations, pluralResourceName);
|
|
14
|
-
const orderByClause = buildOrderByClause(queryOptions);
|
|
15
|
-
const paginationClause = buildPaginationClause(queryOptions);
|
|
16
12
|
const hasJoins = operations.some(op => op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany);
|
|
13
|
+
const joinClauses = hasJoins
|
|
14
|
+
? buildJoinClauses(operations, pluralResourceName, { oneToOneOnly: true })
|
|
15
|
+
: buildJoinClauses(operations, pluralResourceName);
|
|
16
|
+
const orderByClause = buildOrderByClause(queryOptions, hasJoins ? { tablePrefix: pluralResourceName } : undefined);
|
|
17
|
+
const paginationClause = buildPaginationClause(queryOptions);
|
|
17
18
|
const selectClause = hasJoins
|
|
18
19
|
? await buildSelectClause(client, pluralResourceName, operations)
|
|
19
20
|
: '*';
|
|
@@ -23,6 +24,8 @@ export async function get(client, operations, queryOptions, pluralResourceName)
|
|
|
23
24
|
const total = await executeCountQuery(client, pluralResourceName, queryOptions);
|
|
24
25
|
const dataQuery = `${baseQuery} ${orderByClause} ${paginationClause}`.trim();
|
|
25
26
|
const dataResult = await client.query(dataQuery, values);
|
|
26
|
-
const entities =
|
|
27
|
+
const entities = hasJoins
|
|
28
|
+
? dataResult.rows.map(r => r.entity)
|
|
29
|
+
: dataResult.rows;
|
|
27
30
|
return apiUtils.getPagedResult(entities, total, queryOptions);
|
|
28
31
|
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { Operation } from "../../operations/operation.js";
|
|
2
|
-
export
|
|
2
|
+
export interface BuildJoinClausesOptions {
|
|
3
|
+
oneToOneOnly?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function buildJoinClauses(operations: Operation[], mainTableName?: string, options?: BuildJoinClausesOptions): string;
|
|
@@ -1,11 +1,42 @@
|
|
|
1
1
|
import { LeftJoin } from "../../operations/left-join.operation.js";
|
|
2
2
|
import { InnerJoin } from "../../operations/inner-join.operation.js";
|
|
3
3
|
import { LeftJoinMany } from "../../operations/left-join-many.operation.js";
|
|
4
|
-
|
|
4
|
+
function getParentAlias(localField) {
|
|
5
|
+
if (!localField.includes('.'))
|
|
6
|
+
return null;
|
|
7
|
+
return localField.split('.')[0];
|
|
8
|
+
}
|
|
9
|
+
function getThroughTableAliases(operations) {
|
|
10
|
+
const through = new Set();
|
|
11
|
+
for (const op of operations) {
|
|
12
|
+
if (op instanceof LeftJoinMany && op.localField.includes('.')) {
|
|
13
|
+
through.add(op.localField.split('.')[0]);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return through;
|
|
17
|
+
}
|
|
18
|
+
export function buildJoinClauses(operations, mainTableName, options) {
|
|
19
|
+
const oneToOneOnly = options?.oneToOneOnly ?? false;
|
|
20
|
+
const throughTableAliases = oneToOneOnly ? getThroughTableAliases(operations) : new Set();
|
|
5
21
|
const joinClauses = [];
|
|
22
|
+
const oneToOneAliasesInScope = new Set();
|
|
6
23
|
for (const operation of operations) {
|
|
24
|
+
if (operation instanceof LeftJoinMany) {
|
|
25
|
+
if (oneToOneOnly)
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
else if (operation instanceof LeftJoin || operation instanceof InnerJoin) {
|
|
29
|
+
if (oneToOneOnly) {
|
|
30
|
+
const parent = getParentAlias(operation.localField);
|
|
31
|
+
const parentInScope = parent === null || parent === mainTableName || oneToOneAliasesInScope.has(parent);
|
|
32
|
+
if (!parentInScope)
|
|
33
|
+
continue;
|
|
34
|
+
oneToOneAliasesInScope.add(operation.as);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
7
37
|
if (operation instanceof LeftJoin || operation instanceof InnerJoin || operation instanceof LeftJoinMany) {
|
|
8
|
-
const
|
|
38
|
+
const useLeftJoin = oneToOneOnly && operation instanceof InnerJoin && throughTableAliases.has(operation.as);
|
|
39
|
+
const joinType = useLeftJoin || operation instanceof LeftJoin || operation instanceof LeftJoinMany ? "LEFT JOIN" : "INNER JOIN";
|
|
9
40
|
let leftSide;
|
|
10
41
|
if (operation.localField.includes(".")) {
|
|
11
42
|
const [alias, column] = operation.localField.split(".");
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { IQueryOptions } from "@loomcore/common/models";
|
|
2
|
-
export
|
|
2
|
+
export interface BuildOrderByClauseOptions {
|
|
3
|
+
tablePrefix?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function buildOrderByClause(queryObject: IQueryOptions, options?: BuildOrderByClauseOptions): string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export function buildOrderByClause(queryObject) {
|
|
1
|
+
export function buildOrderByClause(queryObject, options) {
|
|
2
2
|
if (!queryObject.orderBy) {
|
|
3
3
|
return '';
|
|
4
4
|
}
|
|
5
5
|
const orderBy = queryObject.orderBy;
|
|
6
6
|
const sortDirection = queryObject.sortDirection || 'asc';
|
|
7
|
-
|
|
7
|
+
const qualified = options?.tablePrefix ? `"${options.tablePrefix}"."${orderBy}"` : orderBy;
|
|
8
|
+
return `ORDER BY ${qualified} ${sortDirection}`;
|
|
8
9
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { Client } from 'pg';
|
|
2
2
|
import { Operation } from '../../operations/operation.js';
|
|
3
|
+
export declare function getTableColumns(client: Client, tableName: string): Promise<string[]>;
|
|
3
4
|
export declare function buildSelectClause(client: Client, mainTableName: string, operations: Operation[]): Promise<string>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { LeftJoin } from '../../operations/left-join.operation.js';
|
|
2
2
|
import { InnerJoin } from '../../operations/inner-join.operation.js';
|
|
3
3
|
import { LeftJoinMany } from '../../operations/left-join-many.operation.js';
|
|
4
|
-
|
|
4
|
+
const PK = '_id';
|
|
5
|
+
export async function getTableColumns(client, tableName) {
|
|
5
6
|
const result = await client.query(`
|
|
6
7
|
SELECT column_name
|
|
7
8
|
FROM information_schema.columns
|
|
@@ -11,19 +12,176 @@ async function getTableColumns(client, tableName) {
|
|
|
11
12
|
`, [tableName]);
|
|
12
13
|
return result.rows.map(row => row.column_name);
|
|
13
14
|
}
|
|
15
|
+
function getParentAlias(localField) {
|
|
16
|
+
if (!localField.includes('.'))
|
|
17
|
+
return null;
|
|
18
|
+
return localField.split('.')[0];
|
|
19
|
+
}
|
|
20
|
+
function getChildOperations(operations, parentAlias) {
|
|
21
|
+
return operations.filter(op => {
|
|
22
|
+
const p = getParentAlias(op.localField);
|
|
23
|
+
return p === parentAlias;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function getTopLevelOperations(operations, mainTableName) {
|
|
27
|
+
return operations.filter(op => {
|
|
28
|
+
const p = getParentAlias(op.localField);
|
|
29
|
+
return p === null || p === mainTableName;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function sqlQuote(s) {
|
|
33
|
+
return "'" + s.replace(/'/g, "''") + "'";
|
|
34
|
+
}
|
|
35
|
+
function jsonbBuildObject(entries) {
|
|
36
|
+
if (entries.length === 0)
|
|
37
|
+
return "''{}''::jsonb";
|
|
38
|
+
const parts = entries.flatMap(({ key, expr }) => [sqlQuote(key), expr]);
|
|
39
|
+
return `jsonb_build_object(${parts.join(', ')})`;
|
|
40
|
+
}
|
|
41
|
+
function buildParentRef(localField, mainTableName) {
|
|
42
|
+
if (!localField.includes('.')) {
|
|
43
|
+
return `"${mainTableName}"."${localField}"`;
|
|
44
|
+
}
|
|
45
|
+
const [alias, column] = localField.split('.');
|
|
46
|
+
return `"${alias}"."${column}"`;
|
|
47
|
+
}
|
|
48
|
+
async function buildOneToOneValue(client, op, operations, mainTableName, inScopeAliases) {
|
|
49
|
+
const alias = op.as;
|
|
50
|
+
const columns = await getTableColumns(client, op.from);
|
|
51
|
+
const childOps = getChildOperations(operations, alias);
|
|
52
|
+
const entries = columns.map(col => ({
|
|
53
|
+
key: col,
|
|
54
|
+
expr: `"${alias}"."${col}"`
|
|
55
|
+
}));
|
|
56
|
+
for (const child of childOps) {
|
|
57
|
+
if (child instanceof LeftJoin || child instanceof InnerJoin) {
|
|
58
|
+
const childVal = await buildOneToOneValue(client, child, operations, mainTableName, inScopeAliases);
|
|
59
|
+
entries.push({ key: child.as, expr: childVal });
|
|
60
|
+
}
|
|
61
|
+
else if (child instanceof LeftJoinMany) {
|
|
62
|
+
const childVal = await buildManyValue(client, child, operations, mainTableName, alias, inScopeAliases);
|
|
63
|
+
entries.push({ key: child.as, expr: childVal });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const obj = jsonbBuildObject(entries);
|
|
67
|
+
return `CASE WHEN "${alias}"."${PK}" IS NOT NULL THEN ${obj} ELSE NULL END`;
|
|
68
|
+
}
|
|
69
|
+
function getThroughJoin(operations, localField) {
|
|
70
|
+
if (!localField.includes('.'))
|
|
71
|
+
return null;
|
|
72
|
+
const throughAlias = localField.split('.')[0];
|
|
73
|
+
const throughOp = operations.find(o => o instanceof InnerJoin && o.as === throughAlias);
|
|
74
|
+
return throughOp ?? null;
|
|
75
|
+
}
|
|
76
|
+
function getThroughAliasesUsedBySiblings(childOps) {
|
|
77
|
+
const throughAliases = new Set();
|
|
78
|
+
for (const op of childOps) {
|
|
79
|
+
if (op instanceof LeftJoinMany && op.localField.includes('.')) {
|
|
80
|
+
throughAliases.add(op.localField.split('.')[0]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return throughAliases;
|
|
84
|
+
}
|
|
85
|
+
async function buildManyValue(client, op, operations, mainTableName, parentAlias, inScopeAliases) {
|
|
86
|
+
const alias = op.as;
|
|
87
|
+
const columns = await getTableColumns(client, op.from);
|
|
88
|
+
const childOps = getChildOperations(operations, alias);
|
|
89
|
+
const throughJoin = getThroughJoin(operations, op.localField);
|
|
90
|
+
const parentRef = buildParentRef(op.localField, mainTableName);
|
|
91
|
+
let fromClause;
|
|
92
|
+
let whereClause;
|
|
93
|
+
if (throughJoin) {
|
|
94
|
+
const throughAlias = throughJoin.as;
|
|
95
|
+
const linkColumn = op.localField.split('.')[1];
|
|
96
|
+
fromClause = `"${throughJoin.from}" AS "${throughAlias}" INNER JOIN "${op.from}" AS "${alias}" ON "${throughAlias}"."${linkColumn}" = "${alias}"."${op.foreignField}"`;
|
|
97
|
+
const throughParentRef = buildParentRef(throughJoin.localField, mainTableName);
|
|
98
|
+
whereClause = `"${throughAlias}"."${throughJoin.foreignField}" = ${throughParentRef}`;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
fromClause = `"${op.from}" AS "${alias}"`;
|
|
102
|
+
whereClause = `"${alias}"."${op.foreignField}" = ${parentRef}`;
|
|
103
|
+
}
|
|
104
|
+
const throughAliasesUsedBySiblings = getThroughAliasesUsedBySiblings(childOps);
|
|
105
|
+
const oneToOneChildren = childOps.filter(c => c instanceof LeftJoin || c instanceof InnerJoin);
|
|
106
|
+
for (const child of oneToOneChildren) {
|
|
107
|
+
const leftCol = child.localField.includes('.') ? child.localField.split('.')[1] : child.localField;
|
|
108
|
+
fromClause += ` LEFT JOIN "${child.from}" AS "${child.as}" ON "${alias}"."${leftCol}" = "${child.as}"."${child.foreignField}"`;
|
|
109
|
+
}
|
|
110
|
+
const itemEntries = columns.map(col => ({
|
|
111
|
+
key: col,
|
|
112
|
+
expr: `"${alias}"."${col}"`
|
|
113
|
+
}));
|
|
114
|
+
for (const child of childOps) {
|
|
115
|
+
if (child instanceof LeftJoin || child instanceof InnerJoin) {
|
|
116
|
+
const childColumns = await getTableColumns(client, child.from);
|
|
117
|
+
const nestedChildOps = getChildOperations(operations, child.as);
|
|
118
|
+
const nestedEntries = childColumns.map(c => ({
|
|
119
|
+
key: c,
|
|
120
|
+
expr: `"${child.as}"."${c}"`
|
|
121
|
+
}));
|
|
122
|
+
for (const n of nestedChildOps) {
|
|
123
|
+
if (n instanceof LeftJoin || n instanceof InnerJoin) {
|
|
124
|
+
const grandCols = await getTableColumns(client, n.from);
|
|
125
|
+
nestedEntries.push(...grandCols.map(c => ({ key: c, expr: `"${n.as}"."${c}"` })));
|
|
126
|
+
}
|
|
127
|
+
else if (n instanceof LeftJoinMany) {
|
|
128
|
+
const sub = await buildManyValue(client, n, operations, mainTableName, child.as, inScopeAliases);
|
|
129
|
+
nestedEntries.push({ key: n.as, expr: sub });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const nestedObj = jsonbBuildObject(nestedEntries);
|
|
133
|
+
itemEntries.push({
|
|
134
|
+
key: child.as,
|
|
135
|
+
expr: `CASE WHEN "${child.as}"."${PK}" IS NOT NULL THEN ${nestedObj} ELSE NULL END`
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else if (child instanceof LeftJoinMany) {
|
|
139
|
+
const sub = await buildManyValue(client, child, operations, mainTableName, alias, inScopeAliases);
|
|
140
|
+
itemEntries.push({ key: child.as, expr: sub });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const itemExpr = jsonbBuildObject(itemEntries);
|
|
144
|
+
if (throughAliasesUsedBySiblings.size > 0) {
|
|
145
|
+
const orderByPk = `"${alias}"."${PK}"`;
|
|
146
|
+
const innerSelect = `SELECT DISTINCT ON (${orderByPk}) ${itemExpr} AS item FROM ${fromClause} WHERE ${whereClause} ORDER BY ${orderByPk}`;
|
|
147
|
+
return `(SELECT COALESCE(jsonb_agg(sub.item), '[]'::jsonb) FROM (${innerSelect}) sub)`;
|
|
148
|
+
}
|
|
149
|
+
return `(SELECT COALESCE(jsonb_agg(${itemExpr}), '[]'::jsonb) FROM ${fromClause} WHERE ${whereClause})`;
|
|
150
|
+
}
|
|
151
|
+
async function buildJoinDataObject(client, operations, mainTableName) {
|
|
152
|
+
const topLevel = getTopLevelOperations(operations, mainTableName);
|
|
153
|
+
const oneToOneAliases = new Set(operations.filter(o => o instanceof LeftJoin || o instanceof InnerJoin).map(o => o.as));
|
|
154
|
+
const entries = [];
|
|
155
|
+
for (const op of topLevel) {
|
|
156
|
+
if (op instanceof LeftJoin || op instanceof InnerJoin) {
|
|
157
|
+
const val = await buildOneToOneValue(client, op, operations, mainTableName, oneToOneAliases);
|
|
158
|
+
entries.push({ key: op.as, expr: val });
|
|
159
|
+
}
|
|
160
|
+
else if (op instanceof LeftJoinMany) {
|
|
161
|
+
const parentRef = buildParentRef(op.localField, mainTableName);
|
|
162
|
+
const val = await buildManyValue(client, op, operations, mainTableName, mainTableName, oneToOneAliases);
|
|
163
|
+
entries.push({ key: op.as, expr: val });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (entries.length === 0)
|
|
167
|
+
return "''{}''::jsonb";
|
|
168
|
+
return jsonbBuildObject(entries);
|
|
169
|
+
}
|
|
14
170
|
export async function buildSelectClause(client, mainTableName, operations) {
|
|
15
171
|
const leftJoinOperations = operations.filter(op => op instanceof LeftJoin);
|
|
16
172
|
const innerJoinOperations = operations.filter(op => op instanceof InnerJoin);
|
|
17
173
|
const leftJoinManyOperations = operations.filter(op => op instanceof LeftJoinMany);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
for (const join of [...leftJoinOperations, ...innerJoinOperations, ...leftJoinManyOperations]) {
|
|
22
|
-
const joinColumns = await getTableColumns(client, join.from);
|
|
23
|
-
for (const col of joinColumns) {
|
|
24
|
-
joinSelects.push(`"${join.as}"."${col}" AS "${join.as}__${col}"`);
|
|
25
|
-
}
|
|
174
|
+
const hasJoins = leftJoinOperations.length > 0 || innerJoinOperations.length > 0 || leftJoinManyOperations.length > 0;
|
|
175
|
+
if (!hasJoins) {
|
|
176
|
+
return '*';
|
|
26
177
|
}
|
|
27
|
-
const
|
|
28
|
-
|
|
178
|
+
const mainColumns = await getTableColumns(client, mainTableName);
|
|
179
|
+
const mainEntries = mainColumns.map(col => ({
|
|
180
|
+
key: col,
|
|
181
|
+
expr: `"${mainTableName}"."${col}"`
|
|
182
|
+
}));
|
|
183
|
+
const joinDataExpr = await buildJoinDataObject(client, operations, mainTableName);
|
|
184
|
+
mainEntries.push({ key: '_joinData', expr: joinDataExpr });
|
|
185
|
+
const entityExpr = jsonbBuildObject(mainEntries);
|
|
186
|
+
return `${entityExpr} AS entity`;
|
|
29
187
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcore/api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.120",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Loom Core Api - An opinionated Node.js api using Typescript, Express, and MongoDb or PostgreSQL",
|
|
6
6
|
"scripts": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"qs": "^6.15.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@loomcore/common": "^0.0.
|
|
61
|
+
"@loomcore/common": "^0.0.54",
|
|
62
62
|
"@sinclair/typebox": "0.34.33",
|
|
63
63
|
"cookie-parser": "^1.4.6",
|
|
64
64
|
"cors": "^2.8.5",
|