/** * 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) & { 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; }