@lbu/code-gen
Version:
Generate various boring parts of your server
137 lines (120 loc) • 3.86 kB
JavaScript
import { upperCaseFirst } from "../../utils.js";
import { js } from "../tag/tag.js";
import { importCreator } from "../utils.js";
import { getPrimaryKeyWithType, getQueryEnabledObjects } from "./utils.js";
/**
* Get other entities by following the relations across entities
* @param {CodeGenContext} context
*/
export function generateTraversalQueries(context) {
const traversePartials = [];
const names = [];
const imports = importCreator();
imports.destructureImport("query", `@lbu/store`);
for (const type of getQueryEnabledObjects(context)) {
imports.destructureImport(
`${type.name}Fields`,
`./query-partials${context.importExtension}`,
);
imports.destructureImport(
`${type.name}Where`,
`./query-partials${context.importExtension}`,
);
imports.destructureImport(
`${type.name}OrderBy`,
`./query-partials${context.importExtension}`,
);
names.push(`traverse${upperCaseFirst(type.name)}`);
traversePartials.push(traversalQuery(context, imports, type));
// partials.push
}
const contents = js`
${imports.print()}
${traversePartials}
`;
context.rootExports.push(
`export { ${names.join(", ")} } from "./query-traverser${
context.importExtension
}";`,
);
context.outputFiles.push({
contents: contents,
relativePath: `./query-traverser${context.extension}`,
});
}
/**
* @param {CodeGenContext} context
* @param {ImportCreator} imports
* @param {CodeGenObjectType} type
*/
function traversalQuery(context, imports, type) {
const partials = [];
const docPartials = [];
for (const relation of type.relations) {
const { key: primaryKey } = getPrimaryKeyWithType(type);
const otherSide = relation.reference.reference;
const referencedKey =
["oneToMany", "oneToOneReverse"].indexOf(relation.subType) !== -1
? relation.referencedKey
: getPrimaryKeyWithType(otherSide).key;
const ownKey =
["manyToOne", "oneToOne"].indexOf(relation.subType) !== -1
? relation.ownKey
: primaryKey;
const part = js`
/**
* @param {${otherSide.uniqueName}Where} [where={}]
* @returns {Traverse${upperCaseFirst(otherSide.name)}}
*/
get${upperCaseFirst(relation.ownKey)}(where = {}) {
where.${referencedKey}In = query\`
SELECT ${type.shortName}."${ownKey}"
FROM "${type.name}" ${type.shortName}
WHERE $\{${type.name}Where(thisWhere)}
\`;
return traverse${upperCaseFirst(otherSide.name)}(where);
},
`;
partials.push(part);
docPartials.push(
`* @property {function(where: ${
otherSide.uniqueName
}Where=): Traverse${upperCaseFirst(otherSide.name)}} get${upperCaseFirst(
relation.ownKey,
)}`,
);
}
return js`
/**
* @name Traverse${upperCaseFirst(type.name)}
* @typedef {object}
${docPartials}
* @property {QueryPart} queryPart
* @property {function(sql: Postgres): Promise<${type.uniqueName}[]>} exec
*/
/**
* @param {${type.uniqueName}Where} [thisWhere={}]
* @returns {Traverse${upperCaseFirst(type.name)}}
*/
export function traverse${upperCaseFirst(type.name)}(thisWhere = {}) {
return {
${partials}
get queryPart() {
return query\`
SELECT $\{${type.name}Fields()}
FROM "${type.name}" ${type.shortName}
WHERE $\{${type.name}Where(thisWhere)}
ORDER BY $\{${type.name}OrderBy()}
\`;
}, exec(sql) {
return query\`
SELECT $\{${type.name}Fields()}
FROM "${type.name}" ${type.shortName}
WHERE $\{${type.name}Where(thisWhere)}
ORDER BY $\{${type.name}OrderBy()}
\`.exec(sql);
}
};
}
`;
}