Files
dashlibstorage/src/store/runner.js
2026-10-03 23:13:40 +02:00

79 lines
3.1 KiB
JavaScript

/**
* Resolves the object a store method should query through.
*
* Converted store modules call `runner(sql, params)` or `runner.query(sql, params)`.
* During the incremental migration they may still be constructed with a
* raw `mssql` pool, or called with a raw `mssql` Transaction as `tx`. This
* adapter exposes the unified runner contract over both so mixed call sites keep
* working until every module is converted.
*
* @param {import('../providers/provider.js').DatabaseProvider} provider
* @param {object} [tx] Optional provider runner or legacy mssql Transaction.
* @returns {((sql: string, params?: object) => Promise<import('../providers/provider.js').QueryResult>) & { query: Function, dialect?: string }}
*/
/** Wraps a raw mssql pool/transaction in the provider query contract. */
function wrapMssql(target) {
return {
dialect: 'mssql',
async query(sql, params = {}) {
const req = target.request();
for (const [key, value] of Object.entries(params)) {
req.input(key, value);
}
const result = await req.query(sql);
const rows = result.recordset ?? [];
const rowsAffected = Array.isArray(result.rowsAffected)
? result.rowsAffected.reduce((a, b) => a + b, 0)
: 0;
return { rows, rowsAffected, insertId: null };
},
};
}
function normalize(target) {
if (!target) return null;
if (typeof target === 'function' && typeof target.query === 'function') return target;
if (target.dialect) return target;
if (typeof target.request === 'function') return wrapMssql(target);
if (typeof target.query === 'function') return target;
return null;
}
export default function makeRunner(provider, tx) {
if (tx && tx !== provider) {
if (typeof tx === 'function' && typeof tx.query === 'function') return tx;
const normTx = normalize(tx);
if (normTx) return createCallableRunner(normTx);
}
if (typeof provider === 'function' && typeof provider.query === 'function') return provider;
const normProvider = normalize(provider);
if (normProvider) return createCallableRunner(normProvider);
return null;
}
function createCallableRunner(base) {
if (typeof base === 'function' && typeof base.query === 'function') return base;
const run = async (sql, params) => {
return base.query(sql, params);
};
run.query = run;
run.exec = base.exec ? base.exec.bind(base) : undefined;
run.dialect = base.dialect;
run.provider = base.provider || base;
run.writeFileContent = base.writeFileContent?.bind(base);
run.readFileContent = base.readFileContent?.bind(base);
run.writeThumbAvif = base.writeThumbAvif?.bind(base);
run.readThumbAvif = base.readThumbAvif?.bind(base);
run.writePicFull = base.writePicFull?.bind(base);
run.readPicFull = base.readPicFull?.bind(base);
run.writePicThumb = base.writePicThumb?.bind(base);
run.readPicThumb = base.readPicThumb?.bind(base);
run.deleteFile = base.deleteFile?.bind(base);
run.deletePic = base.deletePic?.bind(base);
run.writeVfsContent = base.writeVfsContent?.bind(base);
run.readVfsContent = base.readVfsContent?.bind(base);
run.deleteVfsContent = base.deleteVfsContent?.bind(base);
return run;
}