51 lines
1.9 KiB
JavaScript
51 lines
1.9 KiB
JavaScript
import {
|
|
SelectQueryNode as SelectQueryNodeClass,
|
|
InsertQueryNode as InsertQueryNodeClass,
|
|
UpdateQueryNode as UpdateQueryNodeClass,
|
|
DeleteQueryNode as DeleteQueryNodeClass,
|
|
} from 'kysely';
|
|
import { MikroTransformer } from './transformer.js';
|
|
/** Kysely plugin that transforms queries and results to use MikroORM entity/property naming conventions. */
|
|
export class MikroKyselyPlugin {
|
|
static #queryNodeCache = new WeakMap();
|
|
#transformer;
|
|
#options;
|
|
constructor(em, options = {}) {
|
|
this.#options = options;
|
|
this.#transformer = new MikroTransformer(em, options);
|
|
}
|
|
transformQuery(args) {
|
|
this.#transformer.reset();
|
|
const result = this.#transformer.transformNode(args.node, args.queryId);
|
|
// Cache the entity map if it is one we can process (for use in transformResult)
|
|
if (
|
|
SelectQueryNodeClass.is(args.node) ||
|
|
InsertQueryNodeClass.is(args.node) ||
|
|
UpdateQueryNodeClass.is(args.node) ||
|
|
DeleteQueryNodeClass.is(args.node)
|
|
) {
|
|
// clone the entityMap because the transformer's internal map will be cleared and reused by the next query
|
|
const entityMap = new Map(this.#transformer.getOutputEntityMap());
|
|
MikroKyselyPlugin.#queryNodeCache.set(args.queryId, { entityMap });
|
|
}
|
|
return result;
|
|
}
|
|
async transformResult(args) {
|
|
// Only transform results if columnNamingStrategy is 'property' or convertValues is true
|
|
if (this.#options.columnNamingStrategy !== 'property' && !this.#options.convertValues) {
|
|
return args.result;
|
|
}
|
|
// Retrieve the cached query node and metadata
|
|
const cache = MikroKyselyPlugin.#queryNodeCache.get(args.queryId);
|
|
if (!cache) {
|
|
return args.result;
|
|
}
|
|
// Transform the result rows using the transformer
|
|
const transformedRows = this.#transformer.transformResult(args.result.rows ?? [], cache.entityMap);
|
|
return {
|
|
...args.result,
|
|
rows: transformedRows ?? [],
|
|
};
|
|
}
|
|
}
|