Update server/src/db.js

This commit is contained in:
2025-11-13 15:39:28 +00:00
parent 7d2513ab1d
commit 0638d9abf2

View File

@@ -19,52 +19,58 @@ export async function query(q, params) {
} }
} }
// init DB from schema + seed // Initialize DB (schema + seed)
export async function init() { export async function init() {
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8'); const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8');
await query(schema); await query(schema);
const seed = fs.readFileSync(path.join(__dirname, 'seed.sql'), 'utf8'); const seed = fs.readFileSync(path.join(__dirname, 'seed.sql'), 'utf8');
await query(seed); await query(seed);
console.log('DB initialized.');
console.log('DB initialized (characters + items + inventory).');
} }
// Models (simple) /**
* Characters model
export const Users = { * - username + passhash live here
* - bcrypt provides salt + cost factor per hash
*/
export const Characters = {
// create a new character with username + password
async create(username, password) { async create(username, password) {
const passhash = await bcrypt.hash(password, 10); // bcrypt automatically generates a unique salt for each hash.
// You can bump the rounds (12, 14, etc.) if you want more work factor.
const saltRounds = 12;
const passhash = await bcrypt.hash(password, saltRounds);
const { rows } = await query( const { rows } = await query(
'INSERT INTO users (username, passhash) VALUES ($1,$2) RETURNING id, username', 'INSERT INTO characters (username, passhash) VALUES ($1,$2) RETURNING id, username, x, y, level, xp',
[username, passhash] [username, passhash]
); );
// create character with same name
await query(
'INSERT INTO characters (user_id, name) VALUES ($1,$2)',
[rows[0].id, username]
);
return rows[0]; return rows[0];
}, },
// verify username/password; return character row or null
async verify(username, password) { async verify(username, password) {
const { rows } = await query( const { rows } = await query(
'SELECT * FROM users WHERE username=$1', 'SELECT * FROM characters WHERE username=$1',
[username] [username]
); );
if (!rows[0]) return null; const char = rows[0];
const ok = await bcrypt.compare(password, rows[0].passhash); if (!char) return null;
return ok ? rows[0] : null;
}
};
export const Characters = { const ok = await bcrypt.compare(password, char.passhash);
async getByUserId(userId) { return ok ? char : null;
const { rows } = await query( },
'SELECT * FROM characters WHERE user_id=$1 LIMIT 1',
[userId] async getById(id) {
); const { rows } = await query('SELECT * FROM characters WHERE id=$1', [id]);
return rows[0] || null; return rows[0] || null;
}, },
async addXP(id, amount) { async addXP(id, amount) {
await query('UPDATE characters SET xp = xp + $1 WHERE id=$2', [amount, id]); await query('UPDATE characters SET xp = xp + $1 WHERE id=$2', [amount, id]);
} }
@@ -78,19 +84,19 @@ export const Inventory = {
); );
return rows; return rows;
}, },
async add(characterId, itemKey, qty) { async add(characterId, itemKey, qty) {
// upsert const sql = `
const text = `
INSERT INTO inventory (character_id, item_key, qty) INSERT INTO inventory (character_id, item_key, qty)
VALUES ($1,$2,$3) VALUES ($1,$2,$3)
ON CONFLICT (character_id, item_key) ON CONFLICT (character_id, item_key)
DO UPDATE SET qty = inventory.qty + EXCLUDED.qty DO UPDATE SET qty = inventory.qty + EXCLUDED.qty
`; `;
await query(text, [characterId, itemKey, qty]); await query(sql, [characterId, itemKey, qty]);
} }
}; };
// allow manual init: node src/db.js init // allow: node src/db.js init
if (process.argv[2] === 'init') { if (process.argv[2] === 'init') {
init() init()
.then(() => process.exit(0)) .then(() => process.exit(0))