@medusajs/index
Version:
Medusa Index module
725 lines • 33.3 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _QueryBuilder_searchVectorColumnName;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryBuilder = exports.OPERATOR_MAP = void 0;
const utils_1 = require("@medusajs/framework/utils");
const normalze_table_name_1 = require("./normalze-table-name");
function escapeJsonPathString(val) {
// Escape for JSONPath string
return val.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
}
function buildSafeJsonPathQuery(field, operator, value) {
let jsonPathOperator = operator;
if (operator === "=") {
jsonPathOperator = "==";
}
else if (operator.toUpperCase().includes("LIKE")) {
jsonPathOperator = "like_regex";
}
else if (operator === "IS") {
jsonPathOperator = "==";
}
else if (operator === "IS NOT") {
jsonPathOperator = "!=";
}
if (typeof value === "string") {
let val = value;
if (jsonPathOperator === "like_regex") {
// Convert SQL LIKE wildcards to regex
val = val.replace(/%/g, ".*").replace(/_/g, ".");
}
value = `"${escapeJsonPathString(val)}"`;
}
else {
if ((operator === "IS" || operator === "IS NOT") && value === null) {
value = "null";
}
}
return `$.${field} ${jsonPathOperator} ${value}`;
}
exports.OPERATOR_MAP = {
$eq: "=",
$lt: "<",
$gt: ">",
$lte: "<=",
$gte: ">=",
$ne: "!=",
$in: "IN",
$is: "IS",
$like: "LIKE",
$ilike: "ILIKE",
};
class QueryBuilder {
constructor(args) {
_QueryBuilder_searchVectorColumnName.set(this, "document_tsv");
this.schema = args.schema;
this.entityMap = args.entityMap;
this.selector = args.selector;
this.options = args.options;
this.knex = args.knex;
this.structure = this.selector.select;
this.allSchemaFields = new Set(Object.values(this.schema).flatMap((entity) => entity.fields ?? []));
this.rawConfig = args.rawConfig;
this.requestedFields = args.requestedFields;
this.idsOnly = args.idsOnly ?? false;
}
getStructureKeys(structure) {
return Object.keys(structure ?? {}).filter((key) => key !== "entity");
}
getEntity(path, throwWhenNotFound = true) {
if (!this.schema._schemaPropertiesMap[path]) {
if (!throwWhenNotFound) {
return;
}
throw new Error(`Could not find entity for path: ${path}. It might not be indexed.`);
}
return this.schema._schemaPropertiesMap[path];
}
getGraphQLType(path, field) {
const entity = this.getEntity(path)?.ref?.entity;
const fieldRef = this.entityMap[entity]._fields[field];
if (!fieldRef) {
throw new Error(`Field ${field} is not indexed.`);
}
const fieldType = fieldRef.type.toString();
const isArray = fieldType.startsWith("[");
const currentType = fieldType.replace(/\[|\]|\!/g, "");
return currentType + (isArray ? "[]" : "");
}
transformValueToType(path, field, value) {
if (value === null) {
return null;
}
const typeToFn = {
Int: (val) => parseInt(val, 10),
Float: (val) => parseFloat(val),
String: (val) => String(val),
Boolean: (val) => Boolean(val),
ID: (val) => String(val),
Date: (val) => new Date(val).toISOString(),
DateTime: (val) => new Date(val).toISOString(),
Time: (val) => new Date(`1970-01-01T${val}Z`).toISOString(),
};
const fullPath = [path, ...field];
const prop = fullPath.pop();
const fieldPath = fullPath.join(".");
const graphqlType = this.getGraphQLType(fieldPath, prop).replace("[]", "");
const fn = typeToFn[graphqlType];
if (Array.isArray(value)) {
return value.map((v) => (!fn ? v : fn(v)));
}
return !fn ? value : fn(value);
}
getPostgresCastType(path, field) {
const graphqlToPostgresTypeMap = {
Int: "::int",
Float: "::double precision",
Boolean: "::boolean",
Date: "::timestamp",
DateTime: "::timestamp",
Time: "::time",
"": "",
};
const defaultValues = {
Int: "0",
Float: "0",
Boolean: "false",
Date: "1970-01-01 00:00:00",
DateTime: "1970-01-01 00:00:00",
Time: "00:00:00",
"": "",
};
const fullPath = [path, ...field];
const prop = fullPath.pop();
const fieldPath = fullPath.join(".");
let graphqlType = this.getGraphQLType(fieldPath, prop);
const isList = graphqlType.endsWith("[]");
graphqlType = graphqlType.replace("[]", "");
const cast = (graphqlToPostgresTypeMap[graphqlType] ?? "") + (isList ? "[]" : "");
function generateCoalesceExpression(field) {
const defaultValue = defaultValues[graphqlType];
return `COALESCE(${field}, '${defaultValue}')${cast}`;
}
return {
cast,
coalesce: generateCoalesceExpression,
};
}
parseWhere(aliasMapping, obj, builder) {
const keys = Object.keys(obj);
const getPathAndField = (key) => {
const path = key.split(".");
const field = [path.pop()];
while (!aliasMapping[path.join(".")] && path.length > 0) {
field.unshift(path.pop());
}
const attr = path.join(".");
return { field, attr };
};
const getPathOperation = (attr, path, value) => {
const partialPath = path.length > 1 ? path.slice(0, -1) : path;
const val = this.transformValueToType(attr, partialPath, value);
const result = path.reduceRight((acc, key) => {
return { [key]: acc };
}, val);
return JSON.stringify(result);
};
keys.forEach((key) => {
let value = obj[key];
if ((key === "$and" || key === "$or") && !Array.isArray(value)) {
value = [value];
}
if (key === "$and" && Array.isArray(value)) {
builder.where((qb) => {
value.forEach((cond) => {
qb.andWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
});
});
}
else if (key === "$or" && Array.isArray(value)) {
builder.where((qb) => {
value.forEach((cond) => {
qb.orWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
});
});
}
else if ((0, utils_1.isObject)(value) && !Array.isArray(value)) {
const subKeys = Object.keys(value);
subKeys.forEach((subKey) => {
let operator = exports.OPERATOR_MAP[subKey];
if (operator) {
const { field, attr } = getPathAndField(key);
const nested = new Array(field.length).join("->?");
const subValue = this.transformValueToType(attr, field, value[subKey]);
let val = operator === "IN" ? subValue : [subValue];
if (operator === "=" && subValue === null) {
operator = "IS";
}
else if (operator === "!=" && subValue === null) {
operator = "IS NOT";
}
if (operator === "=") {
const hasId = field[field.length - 1] === "id";
if (hasId) {
builder.whereRaw(`${aliasMapping[attr]}.id = ?`, subValue);
}
else {
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, subValue)}'::jsonb`);
}
}
else if (operator === "IN") {
if (val && !Array.isArray(val)) {
val = [val];
}
if (!val || val.length === 0) {
return;
}
const inPlaceholders = val.map(() => "?").join(",");
const hasId = field[field.length - 1] === "id";
if (hasId) {
builder.whereRaw(`${aliasMapping[attr]}.id IN (${inPlaceholders})`, val);
}
else {
const targetField = field[field.length - 1];
const jsonbValues = val.map((item) => JSON.stringify({
[targetField]: item === null ? null : item,
}));
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @> ANY(ARRAY[${inPlaceholders}]::JSONB[])`, jsonbValues);
}
}
else {
const potentialIdFields = field[field.length - 1];
const hasId = potentialIdFields === "id";
if (hasId) {
builder.whereRaw(`(${aliasMapping[attr]}.id) ${operator} ?`, [
...val,
]);
}
else {
const targetField = field[field.length - 1];
const jsonPath = buildSafeJsonPathQuery(targetField, operator, val[0]);
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @@ ?`, [
jsonPath,
]);
}
}
}
else {
throw new Error(`Unsupported operator: ${subKey}`);
}
});
}
else {
const { field, attr } = getPathAndField(key);
const nested = new Array(field.length).join("->?");
value = this.transformValueToType(attr, field, value);
if (Array.isArray(value)) {
if (value.length === 0) {
return;
}
const inPlaceholders = value.map(() => "?").join(",");
const hasId = field[field.length - 1] === "id";
if (hasId) {
builder.whereRaw(`${aliasMapping[attr]}.id IN (${inPlaceholders})`, [...value]);
}
else {
const targetField = field[field.length - 1];
const jsonbValues = value.map((item) => JSON.stringify({ [targetField]: item === null ? null : item }));
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @> ANY(ARRAY[${inPlaceholders}]::JSONB[])`, jsonbValues);
}
}
else if ((0, utils_1.isDefined)(value)) {
let operator = "=";
if (operator === "=") {
const hasId = field[field.length - 1] === "id";
if (hasId) {
builder.whereRaw(`${aliasMapping[attr]}.id = ?`, value);
}
else {
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, value)}'::jsonb`);
}
}
else {
if (value === null) {
operator = "IS";
}
const hasId = field[field.length - 1] === "id";
if (hasId) {
builder.whereRaw(`(${aliasMapping[attr]}.id) ${operator} ?`, [
value,
]);
}
else {
const targetField = field[field.length - 1];
const jsonPath = buildSafeJsonPathQuery(targetField, operator, value);
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @@ ?`, [
jsonPath,
]);
}
}
}
}
});
return builder;
}
getShortAlias(aliasMapping, alias, level = 0) {
aliasMapping.__aliasIndex ??= 0;
if (aliasMapping[alias]) {
return aliasMapping[alias];
}
aliasMapping[alias] =
"t_" + aliasMapping.__aliasIndex++ + (level > 0 ? `_${level}` : "");
return aliasMapping[alias];
}
buildQueryParts(structure, parentAlias, parentEntity, parentProperty, aliasPath = [], level = 0, aliasMapping = {}) {
const currentAliasPath = [...aliasPath, parentProperty].join(".");
const isSelectableField = this.allSchemaFields.has(parentProperty);
const entities = this.getEntity(currentAliasPath, false);
// !entityRef.alias means the object has not table, it's a nested object
if (isSelectableField || !entities || !entities?.ref?.alias) {
// We are currently selecting a specific field of the parent entity or the entity is not found on the index schema
// We don't need to build the query parts for this as there is no join
return [];
}
const mainEntity = entities;
const mainAlias = this.getShortAlias(aliasMapping, mainEntity.ref.entity.toLowerCase(), level);
const allEntities = [];
if (!entities.shortCutOf) {
allEntities.push({
entity: entities,
parEntity: parentEntity,
parAlias: parentAlias,
alias: mainAlias,
});
}
else {
const intermediateAlias = entities.shortCutOf.split(".");
for (let i = intermediateAlias.length - 1, x = 0; i >= 0; i--, x++) {
const intermediateEntity = this.getEntity(intermediateAlias.join("."), false);
if (!intermediateEntity) {
break;
}
intermediateAlias.pop();
if (intermediateEntity.ref.entity === parentEntity?.ref.entity) {
break;
}
const parentIntermediateEntity = this.getEntity(intermediateAlias.join("."));
const alias = this.getShortAlias(aliasMapping, intermediateEntity.ref.entity.toLowerCase(), level) +
"_" +
x;
const parAlias = parentIntermediateEntity.ref.entity === parentEntity?.ref.entity
? parentAlias
: this.getShortAlias(aliasMapping, parentIntermediateEntity.ref.entity.toLowerCase(), level) +
"_" +
(x + 1);
if (x === 0) {
aliasMapping[currentAliasPath] = alias;
}
allEntities.unshift({
entity: intermediateEntity,
parEntity: parentIntermediateEntity,
parAlias,
alias,
});
}
}
let queryParts = [];
for (const join of allEntities) {
const joinBuilder = this.knex.queryBuilder();
const { alias, entity, parEntity, parAlias } = join;
aliasMapping[currentAliasPath] = alias;
if (level > 0) {
const cName = (0, normalze_table_name_1.normalizeTableName)(entity.ref.entity);
let joinTable = `cat_${cName} AS ${alias}`;
if (entity.isInverse || parEntity.isInverse) {
const pName = `${entity.ref.entity}${parEntity.ref.entity}`.toLowerCase();
const pivotTable = (0, normalze_table_name_1.getPivotTableName)(pName);
joinBuilder.leftJoin(`${pivotTable} AS ${alias}_ref`, `${alias}_ref.child_id`, `${parAlias}.id`);
joinBuilder.leftJoin(joinTable, `${alias}.id`, `${alias}_ref.parent_id`);
}
else {
const pName = `${parEntity.ref.entity}${entity.ref.entity}`.toLowerCase();
const pivotTable = (0, normalze_table_name_1.getPivotTableName)(pName);
joinBuilder.leftJoin(`${pivotTable} AS ${alias}_ref`, `${alias}_ref.parent_id`, `${parAlias}.id`);
joinBuilder.leftJoin(joinTable, `${alias}.id`, `${alias}_ref.child_id`);
}
const joinWhere = this.selector.joinWhere ?? {};
const joinKey = Object.keys(joinWhere).find((key) => {
const k = key.split(".");
k.pop();
const curPath = k.join(".");
if (curPath === currentAliasPath) {
const relEntity = this.getEntity(curPath, false);
return relEntity?.ref?.entity === entity.ref.entity;
}
return false;
});
if (joinKey) {
this.parseWhere(aliasMapping, { [joinKey]: joinWhere[joinKey] }, joinBuilder);
}
queryParts.push(joinBuilder.toQuery().replace("select * ", "").replace("where", "and"));
}
}
const children = this.getStructureKeys(structure);
for (const child of children) {
const childStructure = structure[child];
queryParts = queryParts
.concat(this.buildQueryParts(childStructure, mainAlias, mainEntity, child, aliasPath.concat(parentProperty), level + 1, aliasMapping))
.filter(Boolean);
}
return queryParts;
}
buildSelectParts(structure, parentProperty, aliasMapping, aliasPath = [], selectParts = {}) {
const currentAliasPath = [...aliasPath, parentProperty].join(".");
const isSelectableField = this.allSchemaFields.has(parentProperty);
if (isSelectableField) {
// We are currently selecting a specific field of the parent entity
// Let's remove the parent alias from the select parts to not select everything entirely
// and add the specific field to the select parts
const parentAliasPath = aliasPath.join(".");
const alias = aliasMapping[parentAliasPath];
delete selectParts[parentAliasPath];
if (parentProperty === "id") {
selectParts[currentAliasPath] = `${alias}.id`;
}
else if (!this.idsOnly) {
selectParts[currentAliasPath] = this.knex.raw(`${alias}.data->'${parentProperty}'`);
}
return selectParts;
}
const alias = aliasMapping[currentAliasPath];
// If the entity is not found in the schema (not indexed), we don't need to build the select parts
if (!alias) {
return selectParts;
}
if (!this.idsOnly) {
selectParts[currentAliasPath] = `${alias}.data`;
}
selectParts[currentAliasPath + ".id"] = `${alias}.id`;
const children = this.getStructureKeys(structure);
for (const child of children) {
const childStructure = structure[child];
this.buildSelectParts(childStructure, child, aliasMapping, aliasPath.concat(parentProperty), selectParts);
}
return selectParts;
}
transformOrderBy(arr) {
const result = {};
const map = new Map();
map.set(true, "ASC");
map.set(1, "ASC");
map.set("ASC", "ASC");
map.set(false, "DESC");
map.set(-1, "DESC");
map.set("DESC", "DESC");
function nested(obj, prefix = "") {
const keys = Object.keys(obj);
if (!keys.length) {
return;
}
else if (keys.length > 1) {
throw new Error("Order by only supports one key per object.");
}
const key = keys[0];
let value = obj[key];
if ((0, utils_1.isObject)(value)) {
nested(value, prefix + key + ".");
}
else {
if ((0, utils_1.isString)(value)) {
value = value.toUpperCase();
}
result[prefix + key] = map.get(value) ?? "ASC";
}
}
arr.forEach((obj) => nested(obj));
return result;
}
buildQuery({ hasPagination = true, hasCount = false, }) {
const selectOnlyStructure = this.selector.select;
const structure = this.requestedFields;
const filter = this.selector.where ?? {};
const { orderBy: order, skip, take } = this.options ?? {};
const orderBy = this.transformOrderBy((order && !Array.isArray(order) ? [order] : order) ?? []);
const take_ = !isNaN(+take) ? +take : 15;
const skip_ = !isNaN(+skip) ? +skip : 0;
const rootKey = this.getStructureKeys(structure)[0];
const rootStructure = structure[rootKey];
const entity = this.getEntity(rootKey);
const rootEntity = entity.ref.entity.toLowerCase();
const aliasMapping = {};
let hasTextSearch = false;
let textSearchQuery = null;
const searchQueryFilterProp = `${rootKey}.q`;
if (searchQueryFilterProp in filter) {
if (!filter[searchQueryFilterProp]) {
delete filter[searchQueryFilterProp];
}
else {
hasTextSearch = true;
textSearchQuery = filter[searchQueryFilterProp];
delete filter[searchQueryFilterProp];
}
}
const filterSortStructure = (0, utils_1.unflattenObjectKeys)({
...(this.rawConfig?.filters
? (0, utils_1.unflattenObjectKeys)(this.rawConfig?.filters)
: {}),
...orderBy,
})[rootKey] ?? {};
const joinParts = this.buildQueryParts(filterSortStructure, "", entity, rootKey, [], 0, aliasMapping);
const rootAlias = aliasMapping[rootKey];
const innerQueryBuilder = this.knex.queryBuilder();
// Outer query to select the full data based on the paginated IDs
const outerQueryBuilder = this.knex.queryBuilder();
innerQueryBuilder.distinct(`${rootAlias}.id`);
const orderBySelects = [];
const orderByClauses = [];
for (const aliasPath in orderBy) {
const path = aliasPath.split(".");
const field = path.pop();
const attr = path.join(".");
const alias = aliasMapping[attr];
const direction = orderBy[aliasPath];
const pgType = this.getPostgresCastType(attr, [field]);
const hasId = field === "id";
let orderExpression = `${rootAlias}.id ${direction}`;
if (alias) {
const aggregateAlias = `"${aliasPath}_agg"`;
let aggregateExpression = `(${alias}.data->>'${field}')${pgType.cast}`;
if (hasId) {
aggregateExpression = `${alias}.id`;
}
else {
orderBySelects.push(direction === "ASC"
? this.knex.raw(`MIN(${aggregateExpression}) AS ${aggregateAlias}`)
: this.knex.raw(`MAX(${aggregateExpression}) AS ${aggregateAlias}`));
orderExpression = `${aggregateAlias} ${direction}`;
}
outerQueryBuilder.orderByRaw(`${aggregateExpression} ${direction}`);
}
orderByClauses.push(orderExpression);
}
// Add ordering columns to the select list of the inner query
if (orderBySelects.length > 0) {
innerQueryBuilder.select(orderBySelects);
}
innerQueryBuilder.from(`cat_${(0, normalze_table_name_1.normalizeTableName)(rootEntity)} AS ${this.getShortAlias(aliasMapping, rootKey)}`);
joinParts.forEach((joinPart) => {
innerQueryBuilder.joinRaw(joinPart);
});
if (hasTextSearch) {
const searchWhereParts = [
`${rootAlias}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple', ?)`,
...joinParts.flatMap((part) => {
const aliases = part
.split(" as ")
.flatMap((chunk) => chunk.split(" on "))
.filter((alias) => alias.startsWith('"t_') && !alias.includes("_ref"));
return aliases.map((alias) => `${alias}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple', ?)`);
}),
];
innerQueryBuilder.whereRaw(`(${searchWhereParts.join(" OR ")})`, Array(searchWhereParts.length).fill(textSearchQuery));
}
this.parseWhere(aliasMapping, filter, innerQueryBuilder);
// Group by root ID in the inner query
if (orderBySelects.length > 0) {
innerQueryBuilder.groupBy(`${rootAlias}.id`);
}
if (orderByClauses.length > 0) {
innerQueryBuilder.orderByRaw(orderByClauses.join(", "));
}
else {
innerQueryBuilder.orderBy(`${rootAlias}.id`, "ASC");
}
// Count query to estimate the number of results in parallel
let countQuery;
if (hasCount) {
const estimateQuery = innerQueryBuilder.clone();
estimateQuery.clearSelect().select(1);
estimateQuery.clearOrder();
estimateQuery.clearCounters();
countQuery = this.knex.raw(`SELECT count_estimate(?) AS estimate_count`, estimateQuery.toQuery());
}
// Apply pagination to the inner query
if (hasPagination) {
innerQueryBuilder.limit(take_);
if (skip_ > 0) {
innerQueryBuilder.offset(skip_);
}
}
const innerQueryAlias = "paginated_ids";
outerQueryBuilder.from(`cat_${(0, normalze_table_name_1.normalizeTableName)(rootEntity)} AS ${this.getShortAlias(aliasMapping, rootKey)}`);
outerQueryBuilder.joinRaw(`INNER JOIN (${innerQueryBuilder.toQuery()}) AS ${innerQueryAlias} ON ${rootAlias}.id = ${innerQueryAlias}.id`);
this.parseWhere(aliasMapping, filter, outerQueryBuilder);
const joinPartsOuterQuery = this.buildQueryParts(rootStructure, "", entity, rootKey, [], 0, aliasMapping);
joinPartsOuterQuery.forEach((joinPart) => {
outerQueryBuilder.joinRaw(joinPart);
});
const finalSelectParts = this.buildSelectParts(selectOnlyStructure[rootKey], rootKey, aliasMapping);
outerQueryBuilder.select(finalSelectParts);
const finalSql = outerQueryBuilder.toQuery();
return {
sql: finalSql,
sqlCount: countQuery?.toQuery?.(),
};
}
buildObjectFromResultset(resultSet) {
const structure = this.structure;
const rootKey = this.getStructureKeys(structure)[0];
const maps = {};
const isListMap = {};
const referenceMap = {};
const pathDetails = {};
const initializeMaps = (structure, path) => {
const currentPath = path.join(".");
const entity = this.getEntity(currentPath, false);
if (!entity) {
return;
}
maps[currentPath] = {};
if (path.length > 1) {
const property = path[path.length - 1];
const parents = path.slice(0, -1);
const parentPath = parents.join(".");
// In the case of specific selection
// We dont need to check if the property is a list
const isSelectableField = this.allSchemaFields.has(property);
if (isSelectableField) {
pathDetails[currentPath] = { property, parents, parentPath };
isListMap[currentPath] = false;
return;
}
isListMap[currentPath] = !!this.getEntity(currentPath, false)?.ref?.parents?.find((p) => p.targetProp === property)?.isList;
pathDetails[currentPath] = { property, parents, parentPath };
}
const children = this.getStructureKeys(structure);
for (const key of children) {
initializeMaps(structure[key], [...path, key]);
}
};
initializeMaps(structure[rootKey], [rootKey]);
function buildReferenceKey(path, id, row) {
let current = "";
let key = "";
for (const p of path) {
current += `${p}`;
key += row[`${current}.id`] + ".";
current += ".";
}
return key + id;
}
const columnMap = {};
const columnNames = Object.keys(resultSet[0] ?? {});
for (const property of columnNames) {
const segments = property.split(".");
const field = segments.pop();
const parent = segments.join(".");
columnMap[parent] ??= [];
columnMap[parent].push({
field,
property,
});
}
resultSet.forEach((row) => {
for (const path in maps) {
const id = row[`${path}.id`];
// root level
if (!pathDetails[path]) {
if (!maps[path][id]) {
maps[path][id] = row[path] || undefined;
// If there is an id, but no object values, it means that specific fields were selected
// so we recompose the object with all selected fields. (id will always be selected)
if (!maps[path][id] && id) {
maps[path][id] = {};
for (const column of columnMap[path]) {
maps[path][id][column.field] = row[column.property];
}
}
}
continue;
}
const { property, parents, parentPath } = pathDetails[path];
const referenceKey = buildReferenceKey(parents, id, row);
if (referenceMap[referenceKey]) {
continue;
}
maps[path][id] = row[path] || undefined;
// If there is an id, but no object values, it means that specific fields were selected
// so we recompose the object with all selected fields. (id will always be selected)
if (!maps[path][id] && id) {
maps[path][id] = {};
for (const column of columnMap[path]) {
maps[path][id][column.field] = row[column.property];
}
}
const parentObj = maps[parentPath][row[`${parentPath}.id`]];
if (!parentObj) {
continue;
}
const isList = isListMap[parentPath + "." + property];
if (isList && !Array.isArray(parentObj[property])) {
parentObj[property] = [];
}
if (maps[path][id] !== undefined) {
if (isList) {
parentObj[property].push(maps[path][id]);
}
else {
parentObj[property] = maps[path][id];
}
}
referenceMap[referenceKey] = true;
}
});
return Object.values(maps[rootKey] ?? {});
}
}
exports.QueryBuilder = QueryBuilder;
_QueryBuilder_searchVectorColumnName = new WeakMap();
//# sourceMappingURL=query-builder.js.map
;