// SQL behind the Team provider — three questions core asks, answered from the // guild board and the roster Protocol 4 put there. // // Every statement reads only THIS module's tables. Core's Team tables are // core-internal (docs/website/TEAMS.md §10.3) and this module must never name // one, even though it is what fills them. // `query` is destructured from the core facade at require time, like every other // *.db.js here. The facade resolves `ctx` per call, so taking it now is safe even // though `ctx` does not exist yet when this file is first required. const { query } = require('../../core') /** * The guild board — one row per guild the shard has told us about. * * `members`/`online` here are the COUNTS `guild.update` carries; the roster is a * separate table (Protocol 4). Both are read, because a count is what the shard * asserts and a roster is what it enumerated, and they can legitimately disagree * for the moment between a membership change and the sweep that reports it. */ const listGuilds = () => query( `SELECT id, name, abbr, alliance, members, online, leader_serial, leader_name, leader_acct FROM shard_guilds ORDER BY name ASC`, ) const findGuild = (id) => query( `SELECT id, name, abbr, alliance, members, online, leader_serial, leader_name, leader_acct FROM shard_guilds WHERE id = ? LIMIT 1`, [id], ) /** * One guild's roster, with the site link and live presence folded in. * * Two LEFT JOINs, both deliberate: * * - `shard_account_links` resolves `user_id` HERE rather than in core, because * this module owns that table and a core that read it would be core naming a * module's table by name (§2.3). It is also why a freshly linked account * appears as linked on the next reconcile rather than needing core to know * anything about linking. * - `shard_online` is how a member's `online` is answered at all. The roster * frame does not carry it — the wire's member is the standard actor object * (`serial`, `name`, `player`, `acct?`, `webId?`), and the board's `online` is * a count, not a set. Presence therefore comes from the online table, which * is the same source the public "who's online" surface already uses. * * `web_id` on the roster row is preferred over the link table when present: it is * what the shard itself asserted at roster time, and the join is the fallback for * a member whose row predates their link. */ const listGuildMembers = (guildId) => query( `SELECT m.serial, m.name, m.acct, m.web_id, m.is_player, l.user_id AS linked_user_id, (o.serial IS NOT NULL) AS is_online FROM shard_guild_members m LEFT JOIN shard_account_links l ON l.account = m.acct LEFT JOIN shard_online o ON o.serial = m.serial WHERE m.guild_id = ? ORDER BY m.name ASC`, [guildId], ) module.exports = { listGuilds, findGuild, listGuildMembers }