providerrefactor part1

This commit is contained in:
seb
2026-09-21 03:33:55 +02:00
parent 53a20c4353
commit 4ed6260e91
57 changed files with 1662 additions and 145 deletions

View File

@@ -1,6 +1,8 @@
import { ADD } from '../../providers/mssql/queries/google_auth.js';
import { ADD as MSSQL_ADD } from '../../providers/mssql/queries/google_auth.js';
import { ADD as SQLITE_ADD } from '../../providers/sqlite3/queries/google_auth.js';
export default function add(pool) {
export default function add(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_ADD : MSSQL_ADD;
/**
* Adds a new allowed Google auth email.
*
@@ -12,11 +14,7 @@ export default function add(pool) {
* // => 1
*/
return async (email) => {
const result = await pool
.request()
.input('email', email)
.query(ADD);
return result.recordset[0].id;
const result = await provider.query(sql, { email });
return result.rows[0]?.id ?? result.insertId;
};
}

View File

@@ -1,6 +1,8 @@
import { GET_BY_EMAIL } from '../../providers/mssql/queries/google_auth.js';
import { GET_BY_EMAIL as MSSQL_GET } from '../../providers/mssql/queries/google_auth.js';
import { GET_BY_EMAIL as SQLITE_GET } from '../../providers/sqlite3/queries/google_auth.js';
export default function getByEmail(pool) {
export default function getByEmail(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
/**
* Returns a Google auth row by email.
*
@@ -12,11 +14,7 @@ export default function getByEmail(pool) {
* // => { id, email, ... }
*/
return async (email) => {
const result = await pool
.request()
.input('email', email)
.query(GET_BY_EMAIL);
return result.recordset[0];
const result = await provider.query(sql, { email });
return result.rows[0];
};
}

View File

@@ -1,6 +1,8 @@
import { GET_BY_ID } from '../../providers/mssql/queries/google_auth.js';
import { GET_BY_ID as MSSQL_GET } from '../../providers/mssql/queries/google_auth.js';
import { GET_BY_ID as SQLITE_GET } from '../../providers/sqlite3/queries/google_auth.js';
export default function getById(pool) {
export default function getById(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
/**
* Returns a Google auth row by its id.
*
@@ -12,11 +14,7 @@ export default function getById(pool) {
* // => { id, email, ... }
*/
return async (googleAuthId) => {
const result = await pool
.request()
.input('googleAuthId', googleAuthId)
.query(GET_BY_ID);
return result.recordset[0];
const result = await provider.query(sql, { googleAuthId });
return result.rows[0];
};
}

View File

@@ -1,6 +1,8 @@
import { LIST_ALLOWED_EMAILS } from '../../providers/mssql/queries/google_auth.js';
import { LIST_ALLOWED_EMAILS as MSSQL_LIST } from '../../providers/mssql/queries/google_auth.js';
import { LIST_ALLOWED_EMAILS as SQLITE_LIST } from '../../providers/sqlite3/queries/google_auth.js';
export default function listAllowedEmails(pool) {
export default function listAllowedEmails(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_LIST : MSSQL_LIST;
/**
* Lists all allowed Google auth emails.
*
@@ -11,7 +13,7 @@ export default function listAllowedEmails(pool) {
* // => [{ id, email }]
*/
return async () => {
const result = await pool.request().query(LIST_ALLOWED_EMAILS);
return result.recordset;
const result = await provider.query(sql);
return result.rows;
};
}

View File

@@ -1,6 +1,8 @@
import { REMOVE_ALLOWED_EMAIL } from '../../providers/mssql/queries/google_auth.js';
import { REMOVE_ALLOWED_EMAIL as MSSQL_REMOVE } from '../../providers/mssql/queries/google_auth.js';
import { REMOVE_ALLOWED_EMAIL as SQLITE_REMOVE } from '../../providers/sqlite3/queries/google_auth.js';
export default function removeAllowedEmail(pool) {
export default function removeAllowedEmail(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_REMOVE : MSSQL_REMOVE;
/**
* Removes an allowed Google auth email.
*
@@ -11,9 +13,6 @@ export default function removeAllowedEmail(pool) {
* await store.google_auth.removeAllowedEmail('user@example.com');
*/
return async (email) => {
await pool
.request()
.input('email', email)
.query(REMOVE_ALLOWED_EMAIL);
await provider.query(sql, { email });
};
}

View File

@@ -1,6 +1,8 @@
import { SET_PROFILE } from '../../providers/mssql/queries/google_auth.js';
import { SET_PROFILE as MSSQL_SET } from '../../providers/mssql/queries/google_auth.js';
import { SET_PROFILE as SQLITE_SET } from '../../providers/sqlite3/queries/google_auth.js';
export default function setProfile(pool) {
export default function setProfile(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_SET : MSSQL_SET;
/**
* Updates the profile (picture, picture binary, sub) of a Google auth user.
*
@@ -23,15 +25,14 @@ export default function setProfile(pool) {
throw new Error('Invalid pictureBinary');
}
const result = await pool
.request()
.input('googleAuthId', googleAuthId)
.input('picture', picture)
.input('pictureBinary', pictureBinary)
.input('sub', sub)
.query(SET_PROFILE);
const result = await provider.query(sql, {
googleAuthId,
picture,
pictureBinary,
sub,
});
if (!result.rowsAffected[0]) {
if (!result.rowsAffected) {
throw new Error('User not found');
}
};

View File

@@ -1,6 +1,8 @@
import { SET_SELECTED_COMPANY } from '../../providers/mssql/queries/google_auth.js';
import { SET_SELECTED_COMPANY as MSSQL_SET } from '../../providers/mssql/queries/google_auth.js';
import { SET_SELECTED_COMPANY as SQLITE_SET } from '../../providers/sqlite3/queries/google_auth.js';
export default function setSelectedCompany(pool) {
export default function setSelectedCompany(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_SET : MSSQL_SET;
/**
* Sets the currently selected company for a Google auth user.
*
@@ -12,10 +14,6 @@ export default function setSelectedCompany(pool) {
* await store.google_auth.setSelectedCompany(42, 1);
*/
return async (googleAuthId, companyId) => {
await pool
.request()
.input('googleAuthId', googleAuthId)
.input('companyId', companyId)
.query(SET_SELECTED_COMPANY);
await provider.query(sql, { googleAuthId, companyId });
};
}

View File

@@ -1,7 +1,9 @@
import { CREATE } from '../../providers/mssql/queries/language.js';
import request from '../request.js';
import { CREATE as MSSQL_CREATE } from '../../providers/mssql/queries/language.js';
import { CREATE as SQLITE_CREATE } from '../../providers/sqlite3/queries/language.js';
import makeRunner from '../runner.js';
export default function create(pool) {
export default function create(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_CREATE : MSSQL_CREATE;
/**
* Creates a new language by its ISO 639 code.
*
@@ -14,10 +16,7 @@ export default function create(pool) {
* // => 1
*/
return async (iso639, tx) => {
const result = await request(pool, tx)
.input('iso639', iso639)
.query(CREATE);
return result.recordset[0].id;
const result = await makeRunner(provider, tx).query(sql, { iso639 });
return result.rows[0]?.id ?? result.insertId;
};
}

View File

@@ -1,6 +1,8 @@
import { DELETE } from '../../providers/mssql/queries/language.js';
import { DELETE as MSSQL_DELETE } from '../../providers/mssql/queries/language.js';
import { DELETE as SQLITE_DELETE } from '../../providers/sqlite3/queries/language.js';
export default function del(pool) {
export default function del(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
/**
* Deletes a language by its id.
*
@@ -11,9 +13,6 @@ export default function del(pool) {
* await store.lang.delete(1);
*/
return async (id) => {
await pool
.request()
.input('id', id)
.query(DELETE);
await provider.query(sql, { id });
};
}

View File

@@ -1,9 +1,9 @@
import getByIso639 from './getByIso639.js';
import create from './create.js';
export default function ensure(pool) {
const get = getByIso639(pool);
const add = create(pool);
export default function ensure(provider) {
const get = getByIso639(provider);
const add = create(provider);
/**
* Returns the id of a language by ISO code, creating it if it does not exist.
*

View File

@@ -1,7 +1,9 @@
import { GET_BY_ISO639 } from '../../providers/mssql/queries/language.js';
import request from '../request.js';
import { GET_BY_ISO639 as MSSQL_GET } from '../../providers/mssql/queries/language.js';
import { GET_BY_ISO639 as SQLITE_GET } from '../../providers/sqlite3/queries/language.js';
import makeRunner from '../runner.js';
export default function getByIso639(pool) {
export default function getByIso639(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
/**
* Returns a language row by its ISO 639 code.
*
@@ -14,10 +16,7 @@ export default function getByIso639(pool) {
* // => { id: 1, iso639: 'de' }
*/
return async (iso639, tx) => {
const result = await request(pool, tx)
.input('iso639', iso639)
.query(GET_BY_ISO639);
return result.recordset[0];
const result = await makeRunner(provider, tx).query(sql, { iso639 });
return result.rows[0];
};
}

View File

@@ -1,6 +1,8 @@
import { LIST } from '../../providers/mssql/queries/language.js';
import { LIST as MSSQL_LIST } from '../../providers/mssql/queries/language.js';
import { LIST as SQLITE_LIST } from '../../providers/sqlite3/queries/language.js';
export default function list(pool) {
export default function list(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_LIST : MSSQL_LIST;
/**
* Lists all languages.
*
@@ -11,7 +13,7 @@ export default function list(pool) {
* // => [{ id: 1, iso639: 'de' }]
*/
return async () => {
const result = await pool.request().query(LIST);
return result.recordset;
const result = await provider.query(sql);
return result.rows;
};
}

49
src/store/runner.js Normal file
View File

@@ -0,0 +1,49 @@
/**
* Resolves the object a store method should query through.
*
* Converted store modules call `runner.query(sql, params)`. During the
* incremental migration (see TODO.md §1) they may still be constructed with a
* raw `mssql` pool, or called with a raw `mssql` Transaction as `tx`. This
* adapter exposes the provider 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 {import('../providers/provider.js').DatabaseProvider}
*/
/** 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;
// Provider instances expose `dialect`; legacy mssql pools also have a
// `query()` method, so check for the marker before trusting `query`.
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) {
return normalize(tx) ?? normalize(provider) ?? provider;
}
return normalize(provider) ?? provider;
}

View File

@@ -1,7 +1,9 @@
import { CREATE } from '../../providers/mssql/queries/tax.js';
import request from '../request.js';
import { CREATE as MSSQL_CREATE } from '../../providers/mssql/queries/tax.js';
import { CREATE as SQLITE_CREATE } from '../../providers/sqlite3/queries/tax.js';
import makeRunner from '../runner.js';
export default function create(pool) {
export default function create(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_CREATE : MSSQL_CREATE;
/**
* Creates a new tax rate.
*
@@ -14,10 +16,7 @@ export default function create(pool) {
* // => 1
*/
return async (rate, tx) => {
const result = await request(pool, tx)
.input('rate', rate)
.query(CREATE);
return result.recordset[0].id;
const result = await makeRunner(provider, tx).query(sql, { rate });
return result.rows[0]?.id ?? result.insertId;
};
}

View File

@@ -1,9 +1,9 @@
import getByRate from './getByRate.js';
import create from './create.js';
export default function ensure(pool) {
const get = getByRate(pool);
const add = create(pool);
export default function ensure(provider) {
const get = getByRate(provider);
const add = create(provider);
/**
* Returns the id of a tax rate, creating it if it does not exist.
*

View File

@@ -1,7 +1,9 @@
import { GET_BY_RATE } from '../../providers/mssql/queries/tax.js';
import request from '../request.js';
import { GET_BY_RATE as MSSQL_GET } from '../../providers/mssql/queries/tax.js';
import { GET_BY_RATE as SQLITE_GET } from '../../providers/sqlite3/queries/tax.js';
import makeRunner from '../runner.js';
export default function getByRate(pool) {
export default function getByRate(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
/**
* Returns a tax row by its rate.
*
@@ -14,10 +16,7 @@ export default function getByRate(pool) {
* // => { id: 1, rate: 19 }
*/
return async (rate, tx) => {
const result = await request(pool, tx)
.input('rate', rate)
.query(GET_BY_RATE);
return result.recordset[0];
const result = await makeRunner(provider, tx).query(sql, { rate });
return result.rows[0];
};
}

View File

@@ -1,6 +1,8 @@
import { LIST } from '../../providers/mssql/queries/tax.js';
import { LIST as MSSQL_LIST } from '../../providers/mssql/queries/tax.js';
import { LIST as SQLITE_LIST } from '../../providers/sqlite3/queries/tax.js';
export default function list(pool) {
export default function list(provider) {
const sql = provider.dialect === 'sqlite3' ? SQLITE_LIST : MSSQL_LIST;
/**
* Lists all tax rates.
*
@@ -11,7 +13,7 @@ export default function list(pool) {
* // => [{ id: 1, rate: 19 }]
*/
return async () => {
const result = await pool.request().query(LIST);
return result.recordset;
const result = await provider.query(sql);
return result.rows;
};
}