feat(isac): add specialization data management

This commit is contained in:
JB
2026-07-26 16:20:04 -04:00
parent ed31748102
commit 6722665f5c
25 changed files with 3369 additions and 25 deletions
+17 -1
View File
@@ -27,7 +27,23 @@ export async function recordIsacAudit(input: {
}
export async function auditRecord(table: string, id: string): Promise<Record<string, unknown> | null> {
if (!['stat_attributes', 'talents', 'talent_triggers', 'brand_sets', 'gear', 'weapons', 'weapon_mods', 'gear_mods', 'os_protocols', 'skill_chip_sets', 'roles'].includes(table)) {
if (![
'stat_attributes',
'talents',
'talent_triggers',
'brand_sets',
'gear',
'weapons',
'weapon_mods',
'gear_mods',
'os_protocols',
'skill_chip_sets',
'specializations',
'specialization_focuses',
'specialization_abilities',
'specialization_tree_nodes',
'roles'
].includes(table)) {
throw new Error('Unsupported audit table');
}
const database = await getDatabase();
+10 -2
View File
@@ -6,7 +6,7 @@ import { recordIsacAudit } from '$lib/server/audit';
import { getContributorMode } from '$lib/server/contributor-mode';
import { notifyOversightReview } from '$lib/server/oversight-notifications';
export const DATA_MODULES = ['configuration', 'attributes', 'talents', 'brands', 'gear', 'weapons', 'weaponmods', 'gearmods', 'protocols', 'skillchips'] as const;
export const DATA_MODULES = ['configuration', 'attributes', 'talents', 'brands', 'gear', 'weapons', 'weaponmods', 'gearmods', 'protocols', 'skillchips', 'specializations'] as const;
export type DataModule = typeof DATA_MODULES[number];
const proposalResultKeys: Partial<Record<DataModule, Record<string, { saved: string; mode?: string }>>> = {
@@ -28,7 +28,15 @@ const proposalResultKeys: Partial<Record<DataModule, Record<string, { saved: str
save: { saved: 'protocolSaved', mode: 'protocolMode' },
saveProfile: { saved: 'profileSaved' }
},
skillchips: { save: { saved: 'skillChipSaved', mode: 'skillChipMode' } }
skillchips: { save: { saved: 'skillChipSaved', mode: 'skillChipMode' } },
specializations: {
saveProgression: { saved: 'progressionSaved' },
saveSpecialization: { saved: 'specializationSaved', mode: 'specializationMode' },
saveFocus: { saved: 'focusSaved', mode: 'focusMode' },
saveAbility: { saved: 'abilitySaved', mode: 'abilityMode' },
saveFocusAbilities: { saved: 'focusAbilitiesSaved' },
saveNode: { saved: 'nodeSaved', mode: 'nodeMode' }
}
};
export function proposalActionResult(module: DataModule, action: string, edit: boolean, proposalId: string) {
+5 -2
View File
@@ -4,13 +4,16 @@ import path from 'node:path';
import sharp from 'sharp';
import { BackgroundRemovalError, removeBackgroundPreview } from './remove-background';
export const GAME_ICON_TYPES = ['talent', 'brand_set', 'os_protocol', 'skill_chip'] as const;
export const GAME_ICON_TYPES = [
'talent', 'brand_set', 'os_protocol', 'skill_chip',
'specialization', 'specialization_ability', 'specialization_node'
] as const;
export type GameDataIconType = (typeof GAME_ICON_TYPES)[number];
export const MAX_GAME_ICON_BYTES = 2 * 1024 * 1024;
export const MAX_GAME_ICON_PIXELS = 12_000_000;
export const GAME_ICON_SIZE = 256;
const ENTITY_ID_PATTERN = /^[0-9a-f-]{36}$/i;
const STORAGE_KEY_PATTERN = /^(talent|brand_set|os_protocol|skill_chip)-[0-9a-f-]{36}\.webp$/i;
const STORAGE_KEY_PATTERN = /^(talent|brand_set|os_protocol|skill_chip|specialization|specialization_ability|specialization_node)-[0-9a-f-]{36}\.webp$/i;
export class GameDataIconValidationError extends Error {}
+1 -1
View File
@@ -6,7 +6,7 @@ import { BackgroundRemovalError, removeBackgroundPreview } from './remove-backgr
export const MANAGED_IMAGE_CATEGORIES = [
'General', 'Interface', 'Gear', 'Weapons', 'Weapon Mods', 'Gear Mods',
'Talents', 'Brands', 'OS Protocols', 'Skill Chips', 'System'
'Talents', 'Brands', 'OS Protocols', 'Skill Chips', 'Specializations', 'System'
] as const;
export const MAX_MANAGED_IMAGE_BYTES = 5 * 1024 * 1024;
const MAX_PIXELS = 24_000_000;