Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+179 -51
View File
@@ -3,73 +3,154 @@ import { newFixture, type Fixture } from '../helpers/fixture.js';
import { zombieMaps } from '../../src/lib/map-aliases.js';
import { prepareNativeHost } from '../helpers/native-host.js';
vi.mock('../../src/lib/server/integrations/rcon.js', () => ({ rconGetPlayerCount: vi.fn(async () => 0) }));
vi.mock('../../src/lib/server/integrations/rcon.js', () => ({
rconGetPlayerCount: vi.fn(async () => 0)
}));
let fixture: Fixture;
beforeEach(async () => { vi.resetModules(); fixture = await newFixture([]); });
afterEach(async () => { vi.useRealTimers(); await fixture.cleanup(); vi.restoreAllMocks(); });
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
});
afterEach(async () => {
vi.useRealTimers();
await fixture.cleanup();
vi.restoreAllMocks();
});
const names = ['t6_zombie_town_1', 't6_zombie_town_2'];
const settings = { game: 't6', mapSlug: 'town', maximum: 2, mode: 'create-destroy', emptyMinutes: 1 };
const settings = {
game: 't6',
mapSlug: 'town',
maximum: 2,
mode: 'create-destroy',
emptyMinutes: 1
};
async function setup(gameWide = false) {
const servers = gameWide ? [...names, ...zombieMaps('t6').filter(m => m.slug !== 'town').map(m => `t6_zombie_${m.slug}_1`)] : names;
const servers = gameWide
? [
...names,
...zombieMaps('t6')
.filter((m) => m.slug !== 'town')
.map((m) => `t6_zombie_${m.slug}_1`)
]
: names;
const policySettings = { ...settings, mapSlug: gameWide ? '*' : settings.mapSlug };
const host = await prepareNativeHost(servers);
const { db } = await import('../../src/lib/server/db/index.js');
const scaling = await import('../../src/lib/server/autoscaling/index.js');
const authorization = await import('../../src/lib/server/autoscaling/authorization.js');
db().prepare("UPDATE ec_hosts SET inventory=json_set(inventory,'$.capabilities',json(?)) WHERE id=?").run(JSON.stringify([authorization.autoscalingRemovalCapability]), host.host.id);
const base = Date.now(); vi.useFakeTimers({ toFake: ['Date'] }); vi.setSystemTime(base);
db()
.prepare(
"UPDATE ec_hosts SET inventory=json_set(inventory,'$.capabilities',json(?)) WHERE id=?"
)
.run(JSON.stringify([authorization.autoscalingRemovalCapability]), host.host.id);
const base = Date.now();
vi.useFakeTimers({ toFake: ['Date'] });
vi.setSystemTime(base);
for (const name of servers) {
const map = zombieMaps('t6').find(m => name === `t6_zombie_${m.slug}_1` || name === `t6_zombie_${m.slug}_2`)!;
db().prepare("INSERT INTO servers(name,game,map,map_slug,container_state,last_players) VALUES(?,'t6',?,?,'running',0)").run(name, map.canonical, map.slug);
db().prepare("INSERT INTO server_keys(id,game,pluto_key) VALUES(?,'t6',?)").run(`key-${name}`, `key-${name}`);
}
if (gameWide) for (const map of zombieMaps('t6').filter(m => m.slug !== 'town')) {
db().prepare("INSERT INTO server_keys(id,game,pluto_key) VALUES(?,'t6',?)").run(`key-${map.slug}-2`, `key-${map.slug}-2`);
const map = zombieMaps('t6').find(
(m) => name === `t6_zombie_${m.slug}_1` || name === `t6_zombie_${m.slug}_2`
)!;
db()
.prepare(
"INSERT INTO servers(name,game,map,map_slug,container_state,last_players) VALUES(?,'t6',?,?,'running',0)"
)
.run(name, map.canonical, map.slug);
db()
.prepare("INSERT INTO server_keys(id,game,pluto_key) VALUES(?,'t6',?)")
.run(`key-${name}`, `key-${name}`);
}
if (gameWide)
for (const map of zombieMaps('t6').filter((m) => m.slug !== 'town')) {
db()
.prepare("INSERT INTO server_keys(id,game,pluto_key) VALUES(?,'t6',?)")
.run(`key-${map.slug}-2`, `key-${map.slug}-2`);
}
const fresh = (offset: number) => {
vi.setSystemTime(base + offset); const at = new Date().toISOString();
db().prepare('UPDATE servers SET container_checked_at=?,last_seen_at=?,last_checked_at=?').run(at, at, at);
vi.setSystemTime(base + offset);
const at = new Date().toISOString();
db()
.prepare('UPDATE servers SET container_checked_at=?,last_seen_at=?,last_checked_at=?')
.run(at, at, at);
db().prepare('UPDATE ec_hosts SET last_heartbeat=?').run(at);
};
fresh(0);
const saved = scaling.saveScaling(policySettings);
for (const offset of [0, 30_000, 60_000]) { fresh(offset); await scaling.runAutoscaling(); }
const intent = db().prepare('SELECT operation_id FROM autoscaling_decisions WHERE resolved=0').get() as { operation_id: string };
for (const offset of [0, 30_000, 60_000]) {
fresh(offset);
await scaling.runAutoscaling();
}
const intent = db()
.prepare('SELECT operation_id FROM autoscaling_decisions WHERE resolved=0')
.get() as { operation_id: string };
expect(intent?.operation_id).toBeTruthy();
const backend = await import('../../src/lib/server/backends/native.js');
vi.spyOn(backend, 'nativeRequest').mockResolvedValue({ healthy: true, state: 'running', exists: true } as never);
vi.spyOn(backend, 'nativeRequest').mockResolvedValue({
healthy: true,
state: 'running',
exists: true
} as never);
const { processProvisioning } = await import('../../src/lib/server/provisioning/worker.js');
const dispatch = async () => {
await processProvisioning();
const row = db().prepare('SELECT operation_id FROM native_provisioning WHERE deployment_id=?').get(intent.operation_id) as { operation_id: string };
const row = db()
.prepare('SELECT operation_id FROM native_provisioning WHERE deployment_id=?')
.get(intent.operation_id) as { operation_id: string };
expect(row.operation_id).toBeTruthy();
const { getHostOperation } = await import('../../src/lib/server/hosts/index.js');
const command = getHostOperation(row.operation_id)!;
return { id: row.operation_id, payload: command.payload.autoscaling as Record<string, unknown> };
return {
id: row.operation_id,
payload: command.payload.autoscaling as Record<string, unknown>
};
};
return {
db,
scaling,
authorization,
policy: saved,
operationId: intent.operation_id,
hostId: host.host.id,
fresh,
dispatch,
processProvisioning
};
return { db, scaling, authorization, policy: saved, operationId: intent.operation_id, hostId: host.host.id, fresh, dispatch, processProvisioning };
}
it('removes the higher surplus lobby after a full empty interval and claims authorization once', async () => {
const s = await setup();
expect(s.db().prepare('SELECT server FROM server_deployments WHERE id=?').get(s.operationId)).toEqual({ server: names[1] });
const { enableSafetyOverride } = await import('../../src/lib/server/provisioning/safety-override.js');
expect(
s.db().prepare('SELECT server FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ server: names[1] });
const { enableSafetyOverride } =
await import('../../src/lib/server/provisioning/safety-override.js');
expect(enableSafetyOverride(s.operationId, { id: 'admin', username: 'admin' }).ok).toBe(false);
const command = await s.dispatch();
expect(s.authorization.claimRemovalAuthorization('wrong-host', command.id, command.payload).authorized).toBe(false);
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload)).toMatchObject({ authorized: true, validForMs: 5000 });
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized).toBe(false);
expect(
s.authorization.claimRemovalAuthorization('wrong-host', command.id, command.payload)
.authorized
).toBe(false);
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload)
).toMatchObject({ authorized: true, validForMs: 5000 });
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized
).toBe(false);
});
it('withdraws a queued removal when a player arrives and restarts the empty interval', async () => {
const s = await setup();
s.db().prepare('UPDATE servers SET last_players=1 WHERE name=?').run(names[1]);
await s.scaling.runAutoscaling();
expect(s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)).toEqual({ state: 'cancelled' });
expect(
s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ state: 'cancelled' });
s.db().prepare('UPDATE servers SET last_players=0').run();
s.fresh(90_000); await s.scaling.runAutoscaling();
expect(s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_decisions WHERE resolved=0').get()).toEqual({ n: 0 });
s.fresh(90_000);
await s.scaling.runAutoscaling();
expect(
s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_decisions WHERE resolved=0').get()
).toEqual({ n: 0 });
});
it('rechecks controller occupancy after the async probe even before monitoring refreshes', async () => {
@@ -77,46 +158,93 @@ it('rechecks controller occupancy after the async probe even before monitoring r
const rcon = await import('../../src/lib/server/integrations/rcon.js');
vi.mocked(rcon.rconGetPlayerCount).mockResolvedValueOnce(1);
await s.processProvisioning();
expect(s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)).toEqual({ state: 'cancelled' });
expect(s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_authorizations').get()).toEqual({ n: 0 });
expect(
s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ state: 'cancelled' });
expect(s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_authorizations').get()).toEqual({
n: 0
});
});
it('revokes a delivered removal on policy pause without claiming it was undone', async () => {
const s = await setup(); const command = await s.dispatch();
s.db().prepare('UPDATE ec_host_operations SET last_delivered_at=? WHERE id=?').run(new Date().toISOString(), command.id);
const s = await setup();
const command = await s.dispatch();
s.db()
.prepare('UPDATE ec_host_operations SET last_delivered_at=? WHERE id=?')
.run(new Date().toISOString(), command.id);
const off = { ...settings, mode: 'off' };
s.scaling.saveScaling(off, s.policy.id, s.policy.revision);
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized).toBe(false);
expect(s.db().prepare('SELECT owns_map FROM autoscaling_policies').get()).toEqual({ owns_map: 1 });
expect(s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)).toEqual({ state: 'running' });
expect(s.scaling.scalingReport().policies[0]).toMatchObject({ ownsMap: true, unsettled: [{ id: s.operationId, state: 'running' }] });
expect(() => s.scaling.deleteScaling(s.policy.id, s.scaling.getScalingPolicy(s.policy.id)!.revision)).toThrow('outstanding Provisioning');
expect(s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_authorizations WHERE policy_id=?').get(s.policy.id)).toEqual({ n: 1 });
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized
).toBe(false);
expect(s.db().prepare('SELECT owns_map FROM autoscaling_policies').get()).toEqual({
owns_map: 1
});
expect(
s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ state: 'running' });
expect(s.scaling.scalingReport().policies[0]).toMatchObject({
ownsMap: true,
unsettled: [{ id: s.operationId, state: 'running' }]
});
expect(() =>
s.scaling.deleteScaling(s.policy.id, s.scaling.getScalingPolicy(s.policy.id)!.revision)
).toThrow('outstanding Provisioning');
expect(
s
.db()
.prepare('SELECT COUNT(*) AS n FROM autoscaling_authorizations WHERE policy_id=?')
.get(s.policy.id)
).toEqual({ n: 1 });
});
it('withdraws undelivered commands and reconciles invalidation without a retry or failure pause', async () => {
const s = await setup(); const command = await s.dispatch();
const s = await setup();
const command = await s.dispatch();
s.scaling.setScalingGlobalPause(true);
expect(s.db().prepare('SELECT state FROM ec_host_operations WHERE id=?').get(command.id)).toEqual({ state: 'failed' });
await s.processProvisioning(); await s.scaling.runAutoscaling();
expect(s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)).toEqual({ state: 'cancelled' });
expect(
s.db().prepare('SELECT state FROM ec_host_operations WHERE id=?').get(command.id)
).toEqual({ state: 'failed' });
await s.processProvisioning();
await s.scaling.runAutoscaling();
expect(
s.db().prepare('SELECT state FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ state: 'cancelled' });
expect(s.scaling.getScalingPolicy(s.policy.id)?.pausedReason).toBeNull();
expect(s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_decisions WHERE resolved=0').get()).toEqual({ n: 0 });
expect(
s.db().prepare('SELECT COUNT(*) AS n FROM autoscaling_decisions WHERE resolved=0').get()
).toEqual({ n: 0 });
});
it('rejects expired, changed revision, and newly protected removal authorizations', async () => {
const s = await setup(); const command = await s.dispatch();
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, { ...command.payload, revision: 999 }).authorized).toBe(false);
s.db().prepare("INSERT INTO maintenance_jobs(server,requested_at) VALUES(?,?)").run(names[1], new Date().toISOString());
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized).toBe(false);
const s = await setup();
const command = await s.dispatch();
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, {
...command.payload,
revision: 999
}).authorized
).toBe(false);
s.db()
.prepare('INSERT INTO maintenance_jobs(server,requested_at) VALUES(?,?)')
.run(names[1], new Date().toISOString());
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized
).toBe(false);
s.db().prepare('DELETE FROM maintenance_jobs').run();
s.fresh(130_000);
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized).toBe(false);
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized
).toBe(false);
});
it('authorizes a game-wide removal without trimming any map below its targets', async () => {
const s = await setup(true);
expect(s.db().prepare("SELECT server FROM server_deployments WHERE id=?").get(s.operationId)).toEqual({ server: names[1] });
expect(
s.db().prepare('SELECT server FROM server_deployments WHERE id=?').get(s.operationId)
).toEqual({ server: names[1] });
const command = await s.dispatch();
expect(s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized).toBe(true);
expect(
s.authorization.claimRemovalAuthorization(s.hostId, command.id, command.payload).authorized
).toBe(true);
});