From 9fd8d4b4703408fcfa3b3c8b21e84fef9f529a46 Mon Sep 17 00:00:00 2001 From: Kiril Popov Date: Sun, 18 May 2025 10:12:31 +0300 Subject: [PATCH] Fix configs DTO names and description --- .gitattributes | 2 + src/apps/dto/app.dto.ts | 2 +- src/apps/dto/get-apps-response.dto.ts | 2 +- src/configs/config.controller.ts | 50 +++--- src/configs/config.service.ts | 164 +++++++++---------- src/configs/dto/get-configs-request.dto.ts | 17 +- src/configs/dto/get-configs-response.dto.ts | 37 +++-- src/layouts/dto/delete-layout-request.dto.ts | 2 +- src/layouts/dto/get-layouts-response.dto.ts | 2 +- src/layouts/dto/layout.dto.ts | 2 +- src/layouts/dto/rename-layout-request.dto.ts | 2 +- src/layouts/dto/save-layout-request.dto.ts | 2 +- src/layouts/layouts.service.ts | 8 +- src/main.ts | 6 +- src/prefs/dto/add-request.dto.ts | 2 +- src/prefs/dto/get-request.dto.ts | 2 +- src/prefs/dto/prefs.dto.ts | 2 +- src/prefs/dto/remove-request.dto.ts | 2 +- src/prefs/prefs.controller.ts | 18 +- src/prefs/prefs.service.ts | 13 +- 20 files changed, 170 insertions(+), 167 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7124b40 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.ts text eol=crlf +*.json text eol=crlf diff --git a/src/apps/dto/app.dto.ts b/src/apps/dto/app.dto.ts index b197c61..48732b8 100644 --- a/src/apps/dto/app.dto.ts +++ b/src/apps/dto/app.dto.ts @@ -8,4 +8,4 @@ export class ApplicationDto { @ApiProperty({ description: 'The name of the application. For a full set of properties see https://docs.interop.io/desktop/developers/configuration/application/index.html ', example: 'client-list', type: String }) name: string; -} \ No newline at end of file +} diff --git a/src/apps/dto/get-apps-response.dto.ts b/src/apps/dto/get-apps-response.dto.ts index f005654..9ccd0db 100644 --- a/src/apps/dto/get-apps-response.dto.ts +++ b/src/apps/dto/get-apps-response.dto.ts @@ -10,4 +10,4 @@ export class GetAppsResponseDto { type: [ApplicationDto] }) applications: ApplicationDto[]; -} \ No newline at end of file +} diff --git a/src/configs/config.controller.ts b/src/configs/config.controller.ts index aeab4af..684fade 100644 --- a/src/configs/config.controller.ts +++ b/src/configs/config.controller.ts @@ -1,25 +1,25 @@ -import { Controller, Headers, Get, Query, Post, Body } from '@nestjs/common'; -import { FileBasedConfigService } from './config.service'; -import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; -import { GetConfigsRequestDto } from './dto/get-configs-request.dto'; -import { GetConfigsResponsetDto } from './dto/get-configs-response.dto'; - -@ApiTags('Configurations') -@Controller("configs") -export class ConfigController { - constructor(private readonly service: FileBasedConfigService) { } - - @Post() - @ApiOperation({ - summary: "Retrieve configuration objects" - }) - @ApiOkResponse({ - description: 'Successfully retrieved configurations.', - type: GetConfigsResponsetDto - }) - async get(@Body() config : GetConfigsRequestDto): Promise> { - let configsParam: string = config.configs ?? "*"; - console.log("Getting configs"); - return this.service.get(configsParam); - } -} +import { Controller, Headers, Get, Query, Post, Body } from '@nestjs/common'; +import { FileBasedConfigService } from './config.service'; +import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { GetConfigsRequestDto } from './dto/get-configs-request.dto'; +import { GetConfigsResponseDto } from './dto/get-configs-response.dto'; + +@ApiTags('Configurations') +@Controller("configs") +export class ConfigController { + constructor(private readonly service: FileBasedConfigService) { } + + @Post() + @ApiOperation({ + summary: "Retrieve configuration objects" + }) + @ApiOkResponse({ + description: 'Successfully retrieved configurations.', + type: GetConfigsResponseDto + }) + async get(@Body() config : GetConfigsRequestDto): Promise> { + let configsParam: string = config.configs ?? "*"; + console.log("Getting configs"); + return this.service.get(configsParam); + } +} diff --git a/src/configs/config.service.ts b/src/configs/config.service.ts index 2c3a564..546e6fc 100644 --- a/src/configs/config.service.ts +++ b/src/configs/config.service.ts @@ -1,82 +1,82 @@ -import { Injectable } from '@nestjs/common'; -import { promisify } from "util"; -import { readdir, readFile, mkdir, existsSync } from "fs"; -import * as json5 from "json5"; -import { join } from "path"; - -const readDirPromisfied = promisify(readdir); -const readFilePromisified = promisify(readFile); -const mkDirPromisified = promisify(mkdir); - -@Injectable() -export class FileBasedConfigService { - private folder = process.env.CONFIGS_FOLDER || "./configuration/configs"; - // some of the confis are actually arrays (not objects) - private arrayConfigs = ["themes.json", "channels.json"]; - - constructor() { - mkDirPromisified(this.folder, { recursive: true }); - } - - public async get(configsR: string): Promise> { - let configs: string[] = []; - if (configsR === "*") { - configs = await this.getAvailableConfigFiles(); - } else { - configs = configsR.split(","); - } - - const result: Record = {}; - if (configs) { - for (const config of configs) { - let contents; - try { - contents = await this.fetchConfiguration(config); - } catch (e) { - // TODO log - console.error("Error reading config file", e); - } - result[config] = { contents }; - } - } - return result; - } - - private async fetchConfiguration(configName: string) { - const isArrayResult = this.arrayConfigs.includes(configName); - const result = await this.readConfigFile(configName, isArrayResult); - return result; - } - - private async readConfigFile(configName: string, arrayResult = false) { - let defaultResult: any = {}; - if (arrayResult) { - defaultResult = []; - } - try { - const filePath = join(this.folder, configName); - if (!existsSync(filePath)) { - return defaultResult; - } - return readFilePromisified(join(filePath), "utf8"); - } catch { - return defaultResult; - } - } - - private async getAvailableConfigFiles() { - let names: string[] = []; - try { - names = await readDirPromisfied(this.folder); - names = names - .filter(n => n.endsWith(".json") && !n.includes("-")) - } catch (e) { - // TODO log - } - - if (names === undefined) { - names = []; - } - return names; - } -} \ No newline at end of file +import { Injectable } from '@nestjs/common'; +import { promisify } from "util"; +import { readdir, readFile, mkdir, existsSync } from "fs"; +import * as json5 from "json5"; +import { join } from "path"; + +const readDirPromisfied = promisify(readdir); +const readFilePromisified = promisify(readFile); +const mkDirPromisified = promisify(mkdir); + +@Injectable() +export class FileBasedConfigService { + private folder = process.env.CONFIGS_FOLDER || "./configuration/configs"; + // some of the confis are actually arrays (not objects) + private arrayConfigs = ["themes.json", "channels.json"]; + + constructor() { + mkDirPromisified(this.folder, { recursive: true }); + } + + public async get(configsR: string): Promise> { + let configs: string[] = []; + if (configsR === "*") { + configs = await this.getAvailableConfigFiles(); + } else { + configs = configsR.split(","); + } + + const result: Record = {}; + if (configs) { + for (const config of configs) { + let contents; + try { + contents = await this.fetchConfiguration(config); + } catch (e) { + // TODO log + console.error("Error reading config file", e); + } + result[config] = { contents }; + } + } + return result; + } + + private async fetchConfiguration(configName: string) { + const isArrayResult = this.arrayConfigs.includes(configName); + const result = await this.readConfigFile(configName, isArrayResult); + return result; + } + + private async readConfigFile(configName: string, arrayResult = false) { + let defaultResult: any = {}; + if (arrayResult) { + defaultResult = []; + } + try { + const filePath = join(this.folder, configName); + if (!existsSync(filePath)) { + return defaultResult; + } + return readFilePromisified(filePath, "utf8"); + } catch { + return defaultResult; + } + } + + private async getAvailableConfigFiles() { + let names: string[] = []; + try { + names = await readDirPromisfied(this.folder); + names = names + .filter(n => n.endsWith(".json") && !n.includes("-")) + } catch (e) { + // TODO log + } + + if (names === undefined) { + names = []; + } + return names; + } +} diff --git a/src/configs/dto/get-configs-request.dto.ts b/src/configs/dto/get-configs-request.dto.ts index 0ba36d2..b30012d 100644 --- a/src/configs/dto/get-configs-request.dto.ts +++ b/src/configs/dto/get-configs-request.dto.ts @@ -1,8 +1,9 @@ -import { ApiProperty } from "@nestjs/swagger"; - -export class GetConfigsRequestDto { - @ApiProperty({ - description: 'Comma seperated list of JSON configurations files to retrieve. If', - }) - configs: string; -} \ No newline at end of file +import { ApiProperty } from "@nestjs/swagger"; + +export class GetConfigsRequestDto { + @ApiProperty({ + description: 'Comma separated list of JSON configuration files to retrieve. Use "*" to retrieve all configurations.', + }) + configs: string; +} + diff --git a/src/configs/dto/get-configs-response.dto.ts b/src/configs/dto/get-configs-response.dto.ts index cc1b331..5ac6c11 100644 --- a/src/configs/dto/get-configs-response.dto.ts +++ b/src/configs/dto/get-configs-response.dto.ts @@ -1,18 +1,19 @@ -import { ApiProperty } from "@nestjs/swagger"; - -export class GetConfigsResponsetDto { - @ApiProperty({ - description: 'Overriding JSON configuration for the `system.json` file of io.Connect Desktop.', - }) - "system.json": string; - - @ApiProperty({ - description: 'Overriding JSON configuration for the `channels.json` file of io.Connect Desktop', - }) - "channels.json": string; - - @ApiProperty({ - description: 'Overriding JSON configuration for the `logger.json` file of io.Connect Desktop', - }) - "logger.json": string; -} +import { ApiProperty } from "@nestjs/swagger"; + +export class GetConfigsResponseDto { + @ApiProperty({ + description: 'Overriding JSON configuration for the `system.json` file of io.Connect Desktop.', + }) + "system.json": string; + + @ApiProperty({ + description: 'Overriding JSON configuration for the `channels.json` file of io.Connect Desktop', + }) + "channels.json": string; + + @ApiProperty({ + description: 'Overriding JSON configuration for the `logger.json` file of io.Connect Desktop', + }) + "logger.json": string; +} + diff --git a/src/layouts/dto/delete-layout-request.dto.ts b/src/layouts/dto/delete-layout-request.dto.ts index baba12d..0afabd8 100644 --- a/src/layouts/dto/delete-layout-request.dto.ts +++ b/src/layouts/dto/delete-layout-request.dto.ts @@ -9,4 +9,4 @@ export class DeleteLayoutRequestDto { @ApiProperty({ description: 'The ids of the layouts to be removed. Use this if you want to remove multiple layouts at once.'}) ids?: string[]; -} \ No newline at end of file +} diff --git a/src/layouts/dto/get-layouts-response.dto.ts b/src/layouts/dto/get-layouts-response.dto.ts index 3160b0e..23ea6cb 100644 --- a/src/layouts/dto/get-layouts-response.dto.ts +++ b/src/layouts/dto/get-layouts-response.dto.ts @@ -4,4 +4,4 @@ import { LayoutDto } from "./layout.dto"; export class GetLayoutsResponseDto { @ApiProperty({ description: 'The list of layouts', type: [LayoutDto] }) layouts: LayoutDto[]; -} \ No newline at end of file +} diff --git a/src/layouts/dto/layout.dto.ts b/src/layouts/dto/layout.dto.ts index 3c57954..41fbd46 100644 --- a/src/layouts/dto/layout.dto.ts +++ b/src/layouts/dto/layout.dto.ts @@ -6,4 +6,4 @@ export class LayoutDto { @ApiProperty({ description: 'The type of the layout'}) type: string; -} \ No newline at end of file +} diff --git a/src/layouts/dto/rename-layout-request.dto.ts b/src/layouts/dto/rename-layout-request.dto.ts index 2586c99..3c8f68b 100644 --- a/src/layouts/dto/rename-layout-request.dto.ts +++ b/src/layouts/dto/rename-layout-request.dto.ts @@ -8,4 +8,4 @@ export class RenameLayoutRequestDto{ @ApiProperty({ description: 'The new name for the layout'}) newName: string; -} \ No newline at end of file +} diff --git a/src/layouts/dto/save-layout-request.dto.ts b/src/layouts/dto/save-layout-request.dto.ts index 4aa66f4..cceb727 100644 --- a/src/layouts/dto/save-layout-request.dto.ts +++ b/src/layouts/dto/save-layout-request.dto.ts @@ -4,4 +4,4 @@ import { LayoutDto } from "./layout.dto"; export class SaveLayoutRequestDto { @ApiProperty({ description: 'The layout to be saved'}) layout: LayoutDto; -} \ No newline at end of file +} diff --git a/src/layouts/layouts.service.ts b/src/layouts/layouts.service.ts index 23d89f0..4226ab2 100644 --- a/src/layouts/layouts.service.ts +++ b/src/layouts/layouts.service.ts @@ -21,7 +21,7 @@ const unlinkFilePromisified = promisify(unlink); export class FileBasedLayoutsService { - private layoutsFolder = process.env.APPS_FOLDER || "./configuration/layouts"; + private layoutsFolder = process.env.LAYOUTS_FOLDER || "./configuration/layouts"; private defaultLayoutType = "default"; async getAll(): Promise { @@ -83,9 +83,9 @@ export class FileBasedLayoutsService { console.error("Error deleting old layout file:", error); } - layout.name = newName; - this.saveLayout(layout); - } + layout.name = newName; + await this.saveLayout(layout); + } getLayoutPath(layout: LayoutDto): string { return join(this.layoutsFolder, this.getLayoutName(layout)); diff --git a/src/main.ts b/src/main.ts index 0c8c241..608364c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,6 +14,6 @@ async function bootstrap() { const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); - await app.listen(process.env.PORT ?? 8004); -} -bootstrap(); + await app.listen(process.env.SERVER_PORT ?? 8004); +} +bootstrap(); diff --git a/src/prefs/dto/add-request.dto.ts b/src/prefs/dto/add-request.dto.ts index 6354926..34f34df 100644 --- a/src/prefs/dto/add-request.dto.ts +++ b/src/prefs/dto/add-request.dto.ts @@ -6,4 +6,4 @@ export class AddPrefsRequestDto { @ApiProperty({ description: 'The actual data to be stored', type: Object}) data?: Record; -} \ No newline at end of file +} diff --git a/src/prefs/dto/get-request.dto.ts b/src/prefs/dto/get-request.dto.ts index 79a036e..060f998 100644 --- a/src/prefs/dto/get-request.dto.ts +++ b/src/prefs/dto/get-request.dto.ts @@ -6,4 +6,4 @@ export class GetAppPrefsRequestDto { @ApiProperty({ description: 'If specified will return the preferences only if they were updated after this date.', type: Date }) lastKnownUpdate?: Date; -} \ No newline at end of file +} diff --git a/src/prefs/dto/prefs.dto.ts b/src/prefs/dto/prefs.dto.ts index 40a235d..7044856 100644 --- a/src/prefs/dto/prefs.dto.ts +++ b/src/prefs/dto/prefs.dto.ts @@ -9,4 +9,4 @@ export class AppPreferencesDto { @ApiProperty({ description: 'The last update time for the preferences of this applicaiton', type: Date }) lastKnownUpdate: Date; -} \ No newline at end of file +} diff --git a/src/prefs/dto/remove-request.dto.ts b/src/prefs/dto/remove-request.dto.ts index 1fe7ef7..3d4e2a6 100644 --- a/src/prefs/dto/remove-request.dto.ts +++ b/src/prefs/dto/remove-request.dto.ts @@ -3,4 +3,4 @@ import { ApiProperty } from "@nestjs/swagger"; export class RemoveAppPrefsRequestDto { @ApiProperty({ description: 'The name of the application' }) app?: string; -} \ No newline at end of file +} diff --git a/src/prefs/prefs.controller.ts b/src/prefs/prefs.controller.ts index a3e4cc8..4210d2c 100644 --- a/src/prefs/prefs.controller.ts +++ b/src/prefs/prefs.controller.ts @@ -55,12 +55,12 @@ export class PrefsController { @ApiOperation({ summary: "Removes preferences for an application" }) - removeApp(@Body() removeRequest: RemoveAppPrefsRequestDto): Promise { - console.log("Removing prefs", removeRequest); - if (!removeRequest.app) { - return this.service.remove(removeRequest.app); - } else { - return this.service.clear(); - } - } -} + removeApp(@Body() removeRequest: RemoveAppPrefsRequestDto): Promise { + console.log("Removing prefs", removeRequest); + if (removeRequest.app) { + return this.service.remove(removeRequest.app); + } else { + return this.service.clear(); + } + } +} diff --git a/src/prefs/prefs.service.ts b/src/prefs/prefs.service.ts index e8e505f..91a3889 100644 --- a/src/prefs/prefs.service.ts +++ b/src/prefs/prefs.service.ts @@ -68,13 +68,12 @@ export class FileBasedPrefsService { return unlinkFilePromisified(file); } - public async clear(): Promise { - let files = await readDirPromisfied(this.folder); - files = files.filter(f => f.endsWith(".json")); - files.map((f) => { - unlinkFilePromisified(join(this.folder, f)); - }); - } + public async clear(): Promise { + let files = await readDirPromisfied(this.folder); + files = files.filter(f => f.endsWith(".json")); + const promises = files.map(f => unlinkFilePromisified(join(this.folder, f))); + await Promise.all(promises); + } private fullPath(app: string) { const fileName = `${app}.json`;