@@ -62,7 +62,7 @@ function collectionPlan(entries: BlueprintEntry[], mode: CollectionMode) {
|
||||
const retained = new Set(retainedServers);
|
||||
const matching = new Set(counts.flatMap(entry => entry.existingServers));
|
||||
const removals = mode === 'exact' ? housePartyTargets().filter(name => !retained.has(name)).map(name => ({ name,
|
||||
reason: matching.has(name) ? 'Exceeds the target lobby count' : 'Outside this blueprint or already awaiting removal'
|
||||
reason: matching.has(name) ? 'Exceeds the target lobby count' : 'Outside this collection or already awaiting removal'
|
||||
})) : [];
|
||||
return { counts, retainedServers, removals };
|
||||
}
|
||||
@@ -93,8 +93,8 @@ function blockersFor(servers: CollectionPreview['servers']): string[] {
|
||||
}
|
||||
|
||||
export function previewCollection(blueprintId: unknown, mode: unknown = 'fill'): CollectionPreview {
|
||||
if (typeof blueprintId !== 'string' || !blueprintId) throw new Error('Choose a blueprint to launch.');
|
||||
if (mode !== 'fill' && mode !== 'exact') throw new Error('Choose fill or exact blueprint mode.');
|
||||
if (typeof blueprintId !== 'string' || !blueprintId) throw new Error('Choose a collection to launch.');
|
||||
if (mode !== 'fill' && mode !== 'exact') throw new Error('Choose fill or exact collection mode.');
|
||||
return db().transaction((): CollectionPreview => {
|
||||
const { entries, blueprintName } = blueprintEntries(blueprintId);
|
||||
const { counts, retainedServers, removals } = collectionPlan(entries, mode);
|
||||
@@ -156,8 +156,8 @@ export function queueCollection(input: { previewId?: unknown; keys?: unknown }):
|
||||
const result = destroyServer(server.name, 'blueprint-exact');
|
||||
if (!result.ok || !result.deploymentId) throw new Error('Could not queue removal for ' + server.name);
|
||||
id = result.deploymentId;
|
||||
db().prepare("UPDATE server_deployments SET state = 'cancelled', stage = 'Cancelled by exact blueprint', finished_at = ? WHERE id = ?").run(new Date().toISOString(), queued.id);
|
||||
recordDeploymentEvent(queued.id, 'Queued creation cancelled by exact blueprint; saved key retained.');
|
||||
db().prepare("UPDATE server_deployments SET state = 'cancelled', stage = 'Cancelled by exact collection', finished_at = ? WHERE id = ?").run(new Date().toISOString(), queued.id);
|
||||
recordDeploymentEvent(queued.id, 'Queued creation cancelled by exact collection; saved key retained.');
|
||||
deploymentStage(id, 'Cancelled queued creation; no server was started');
|
||||
finishDeployment(id, { ok: true });
|
||||
} else {
|
||||
|
||||
@@ -43,7 +43,7 @@ function summarizeBlueprint(row: BlueprintRow): BlueprintSummary {
|
||||
|
||||
export function blueprintEntries(id: string): { entries: BlueprintEntry[]; blueprintName: string } {
|
||||
const row = db().prepare('SELECT * FROM server_blueprints WHERE id = ?').get(id) as BlueprintRow | undefined;
|
||||
if (!row) throw new Error('This blueprint is no longer available. Choose another starting point.');
|
||||
if (!row) throw new Error('This collection is no longer available. Choose another starting point.');
|
||||
const entries = readEntries(row.recipe).map(({ count, game, mapSlug }) => ({ count, recipe: captureRecipe(game, mapSlug) }));
|
||||
return { entries, blueprintName: row.name };
|
||||
}
|
||||
@@ -60,7 +60,7 @@ function buildEntries(input: unknown): BlueprintSelection[] {
|
||||
seen.add(key);
|
||||
return { count: entry.count as number, game: entry.game as ZombieGame, mapSlug: entry.mapSlug as string };
|
||||
});
|
||||
if (entries.reduce((total, entry) => total + entry.count, 0) > 100) throw new Error('A blueprint can launch at most 100 servers.');
|
||||
if (entries.reduce((total, entry) => total + entry.count, 0) > 100) throw new Error('A collection can launch at most 100 servers.');
|
||||
return entries;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export function recipeForDeployment(id: string): { recipe: LaunchRecipe; bluepri
|
||||
|
||||
export function blueprintRecipe(id: string): { recipe: LaunchRecipe; blueprintName: string } {
|
||||
const { entries, blueprintName } = blueprintEntries(id);
|
||||
if (entries.length !== 1 || entries[0].count !== 1) throw new Error('This blueprint launches multiple servers. Use the collection preview.');
|
||||
if (entries.length !== 1 || entries[0].count !== 1) throw new Error('This collection launches multiple servers. Use the collection preview.');
|
||||
return { recipe: entries[0].recipe, blueprintName };
|
||||
}
|
||||
|
||||
@@ -112,9 +112,9 @@ export function listBlueprints(): BlueprintSummary[] {
|
||||
}
|
||||
|
||||
function blueprintName(input: { name: unknown; description?: unknown }, exceptId = ''): string {
|
||||
if (typeof input.name !== 'string' || !input.name.trim() || input.name.trim().length > 80) throw new Error('Give the blueprint a name of 1–80 characters.');
|
||||
if (typeof input.name !== 'string' || !input.name.trim() || input.name.trim().length > 80) throw new Error('Give the collection a name of 1–80 characters.');
|
||||
if (input.description !== undefined && (typeof input.description !== 'string' || input.description.length > 500)) throw new Error('Keep the description to 500 characters.');
|
||||
if (db().prepare('SELECT id FROM server_blueprints WHERE name = ? COLLATE NOCASE AND id != ?').get(input.name.trim(), exceptId)) throw new Error('A blueprint with this name already exists. Choose a new name.');
|
||||
if (db().prepare('SELECT id FROM server_blueprints WHERE name = ? COLLATE NOCASE AND id != ?').get(input.name.trim(), exceptId)) throw new Error('A collection with this name already exists. Choose a new name.');
|
||||
return input.name.trim();
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ export function saveBlueprint(input: { name: unknown; description?: unknown; pre
|
||||
export function updateBlueprint(id: string, input: { name: unknown; description?: unknown; entries?: unknown }): BlueprintSummary {
|
||||
return db().transaction(() => {
|
||||
const row = db().prepare('SELECT * FROM server_blueprints WHERE id = ?').get(id) as BlueprintRow | undefined;
|
||||
if (!row) throw new Error('Blueprint not found.');
|
||||
if (!row) throw new Error('Collection not found.');
|
||||
const name = blueprintName(input, id);
|
||||
const entries = buildEntries(input.entries);
|
||||
const recipe = JSON.stringify({ format: 3, entries });
|
||||
|
||||
Reference in New Issue
Block a user