feat: Complete stub services with real implementations and graceful not-configured responses
All checks were successful
Test Asgard Runner / test (push) Successful in 2s

- ChangelogService: inject PlatformChangelog repo, query with findAndCount(skip/take), return actual data
- ChangelogModule: add TypeOrmModule.forFeature([PlatformChangelog])
- MapsService: add uploadMap() — SHA-256 checksum, storage path, full entity save
- MapsController: add POST /maps/upload with FileInterceptor, map.manage permission, @UploadedFile
- AuthService: replace console.log stubs with Logger; forgotPassword returns 200 with clear message; resetPassword throws NotImplementedException
- PluginsService: searchUmod returns { results: [], message: 'not yet configured' } instead of bare []
- SteamService: add Logger.warn on every stub path (checkForceWipe, getPlayerSummary)
- SettingsService: add Logger; both Cloudflare DNS stubs emit Logger.warn before DB save
- MigrationService: add Logger; exportConfig logs warning + returns note field; importConfig throws NotImplementedException
- Install @types/multer dev dependency for Express.Multer.File type support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-02-21 13:33:08 -05:00
parent e1a3ea3b78
commit a181ed7ded
11 changed files with 164 additions and 60 deletions

View File

@@ -1,15 +1,19 @@
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { Injectable, NotFoundException, ConflictException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PluginRegistry } from '../../entities/plugin-registry.entity';
import { InstallPluginDto } from './dto/install-plugin.dto';
import { UpdatePluginConfigDto } from './dto/update-plugin-config.dto';
import { NatsService } from '../../services/nats.service';
@Injectable()
export class PluginsService {
private readonly logger = new Logger(PluginsService.name);
constructor(
@InjectRepository(PluginRegistry)
private readonly pluginRegistryRepo: Repository<PluginRegistry>,
private readonly natsService: NatsService,
) {}
async getPlugins(licenseId: string): Promise<PluginRegistry[]> {
@@ -45,14 +49,22 @@ export class PluginsService {
}
async uninstallPlugin(licenseId: string, pluginId: string): Promise<void> {
const result = await this.pluginRegistryRepo.delete({
id: pluginId,
license_id: licenseId,
const plugin = await this.pluginRegistryRepo.findOne({
where: { id: pluginId, license_id: licenseId },
});
if (result.affected === 0) {
if (!plugin) {
throw new NotFoundException(`Plugin ${pluginId} not found`);
}
await this.pluginRegistryRepo.delete({ id: pluginId, license_id: licenseId });
await this.natsService.publish(`corrosion.${licenseId}.cmd.plugin`, {
action: 'unload',
plugin_name: plugin.plugin_name,
timestamp: new Date().toISOString(),
});
this.logger.log(`Plugin uninstall dispatched for ${plugin.plugin_name} on license ${licenseId}`);
}
async reloadPlugin(
@@ -67,8 +79,13 @@ export class PluginsService {
throw new NotFoundException(`Plugin ${pluginId} not found`);
}
// Stub implementation - in production would trigger NATS command
// to reload plugin on game server
await this.natsService.publish(`corrosion.${licenseId}.cmd.plugin`, {
action: 'reload',
plugin_name: plugin.plugin_name,
timestamp: new Date().toISOString(),
});
this.logger.log(`Plugin reload dispatched for ${plugin.plugin_name} on license ${licenseId}`);
return { reloaded: true, plugin_name: plugin.plugin_name };
}
@@ -90,9 +107,11 @@ export class PluginsService {
return this.pluginRegistryRepo.save(plugin);
}
async searchUmod(query: string): Promise<any[]> {
// Stub implementation - in production would proxy to uMod API
// or use cached plugin directory
return [];
async searchUmod(query: string): Promise<{ results: any[]; message: string }> {
// uMod API integration pending
return {
results: [],
message: 'uMod search integration not yet configured',
};
}
}