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() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8');
await query(schema);
const seed = fs.readFileSync(path.join(__dirname, 'seed.sql'), 'utf8');
await query(seed);
console.log('DB initialized.');
console.log('DB initialized (characters + items + inventory).');
}
// Models (simple)
export const Users = {
/**
* Characters model
* - 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) {
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(
'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]
);
// create character with same name
await query(
'INSERT INTO characters (user_id, name) VALUES ($1,$2)',
[rows[0].id, username]
);
return rows[0];
},
// verify username/password; return character row or null
async verify(username, password) {
const { rows } = await query(
'SELECT * FROM users WHERE username=$1',
'SELECT * FROM characters WHERE username=$1',
[username]
);
if (!rows[0]) return null;
const ok = await bcrypt.compare(password, rows[0].passhash);
return ok ? rows[0] : null;
}
};
const char = rows[0];
if (!char) return null;
export const Characters = {
async getByUserId(userId) {
const { rows } = await query(
'SELECT * FROM characters WHERE user_id=$1 LIMIT 1',
[userId]
);
const ok = await bcrypt.compare(password, char.passhash);
return ok ? char : null;
},
async getById(id) {
const { rows } = await query('SELECT * FROM characters WHERE id=$1', [id]);
return rows[0] || null;
},
async addXP(id, amount) {
await query('UPDATE characters SET xp = xp + $1 WHERE id=$2', [amount, id]);
}
@@ -78,19 +84,19 @@ export const Inventory = {
);
return rows;
},
async add(characterId, itemKey, qty) {
// upsert
const text = `
const sql = `
INSERT INTO inventory (character_id, item_key, qty)
VALUES ($1,$2,$3)
ON CONFLICT (character_id, item_key)
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') {
init()
.then(() => process.exit(0))