diff --git a/package.json b/package.json index d072f01..860b181 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "archrepo", - "version": "0.0.1", + "version": "2.0.2", "description": "", "author": "", "private": true, diff --git a/src/app.controller.ts b/src/app.controller.ts index 6a774bf..812fafb 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -7,6 +7,7 @@ import { Header, Res, Param, + Query, Headers, HttpException, HttpStatus, @@ -14,7 +15,10 @@ import { } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ApiOkResponse, ApiNotFoundResponse } from '@nestjs/swagger'; -import { GetObjectCommandInput } from '@aws-sdk/client-s3'; +import { + GetObjectCommandInput, + ListObjectsV2CommandInput, +} from '@aws-sdk/client-s3'; import { AppService } from './app.service'; @@ -33,9 +37,9 @@ export class AppController { @ApiOkResponse() @ApiNotFoundResponse() - @Get(`:repo/os/:arch/:pkg`) + @Get(':repo/os/:arch/:pkg') @Header('Accept-Ranges', 'bytes') - async getRepo( + async getPackage( @Headers('Range') range: string, @Res({ passthrough: true }) res: Response, @Param('repo') repo: string, @@ -66,4 +70,38 @@ export class AppController { } return new StreamableFile(output.Body as Readable); } + + @ApiOkResponse() + @ApiNotFoundResponse() + @Get(':repo/os/:arch') + async getPackageList( + @Res({ passthrough: true }) res: Response, + @Param('repo') repo: string, + @Param('arch') arch: string, + @Query('format') format: string, + ): Promise { + if (repo !== this.configService.get('REPO_NAME')) + throw new HttpException(`Repo '${repo}' not exist`, HttpStatus.NOT_FOUND) + if (arch !== this.configService.get('ARCH_NAME')) + throw new HttpException( + `Architecture '${arch}' not exist`, + HttpStatus.NOT_FOUND, + ); + + const output = await this.appService.getObjectList({ + Bucket: this.configService.get('MINIO_BUCKET') + } as ListObjectsV2CommandInput); + if (!output) { + console.log('Cannot list files'); + throw new HttpException(`Cannot list files`, HttpStatus.NOT_FOUND); + } + + if (format === 'json') + return JSON.stringify(output.Contents?.reduce((acc, cur) => { + acc.push(cur.Key ?? ''); + return acc; + }, Array()), null, 2); + return output.Contents?.reduce( + (acc, cur) => `${acc}\n${cur.Key ?? ''}`, '') ?? ''; + } } diff --git a/src/app.service.ts b/src/app.service.ts index adef9c9..4c9e7a3 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -6,6 +6,9 @@ import { GetObjectCommand, GetObjectCommandInput, GetObjectCommandOutput, + ListObjectsV2Command, + ListObjectsV2CommandInput, + ListObjectsV2CommandOutput, NoSuchKey, } from '@aws-sdk/client-s3'; @@ -30,9 +33,9 @@ export class AppService { } async getObject( - getObjectConfig: GetObjectCommandInput, + config: GetObjectCommandInput, ): Promise { - const command = new GetObjectCommand(getObjectConfig); + const command = new GetObjectCommand(config); try { return await this.s3Client.send(command); } catch (err: unknown) { @@ -40,4 +43,17 @@ export class AppService { throw err; } } + + async getObjectList( + config: ListObjectsV2CommandInput, + ): Promise { + const command = new ListObjectsV2Command(config); + try { + return await this.s3Client.send(command); + } catch (err: unknown) { + if (err instanceof Error) + return null; + throw err; + } + } }