diff --git a/package-lock.json b/package-lock.json index dc394f5ec7..49831c2675 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1254,8 +1254,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.0", - "license": "MIT", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", @@ -1305,11 +1306,12 @@ "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.26.2", - "license": "MIT", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1552,10 +1554,11 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "license": "MIT", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -3090,14 +3093,15 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "license": "MIT", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3106,8 +3110,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.0", - "license": "MIT", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -21892,9 +21897,9 @@ } }, "node_modules/@tanstack/virtual-file-routes": { - "version": "1.81.9", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-file-routes/-/virtual-file-routes-1.81.9.tgz", - "integrity": "sha512-jV5mWJrsh3QXHpb/by6udSqwva0qK50uYHpIXvKsLaxnlbjbLfflfPjFyRWXbMtZsnzCjSUqp5pm5/p+Wpaerg==", + "version": "1.87.6", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-file-routes/-/virtual-file-routes-1.87.6.tgz", + "integrity": "sha512-PTpeM8SHL7AJM0pJOacFvHribbUODS51qe9NsMqku4mogh6BWObY1EeVmeGnp9o3VngAEsf+rJMs2zqIVz3WFA==", "optional": true, "peer": true, "engines": { @@ -44102,13 +44107,12 @@ } }, "node_modules/unplugin": { - "version": "1.12.2", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz", + "integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==", "dev": true, - "license": "MIT", "dependencies": { - "acorn": "^8.12.1", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", + "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" }, "engines": { @@ -44116,9 +44120,10 @@ } }, "node_modules/unplugin/node_modules/acorn": { - "version": "8.12.1", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, diff --git a/packages/app-api/src/controllers/GameServerController.ts b/packages/app-api/src/controllers/GameServerController.ts index fbc96152df..959b807c88 100644 --- a/packages/app-api/src/controllers/GameServerController.ts +++ b/packages/app-api/src/controllers/GameServerController.ts @@ -30,7 +30,19 @@ import { ModuleInstallDTO, } from '../service/GameServerService.js'; import { AuthenticatedRequest, AuthService, checkPermissions } from '../service/AuthService.js'; -import { Body, Get, Post, Delete, JsonController, UseBefore, Req, Put, Params, Res } from 'routing-controllers'; +import { + Body, + Get, + Post, + Delete, + JsonController, + UseBefore, + Req, + Put, + Params, + Res, + ContentType, +} from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { Type } from 'class-transformer'; import { ParamId, PogParam } from '../lib/validators.js'; @@ -233,6 +245,17 @@ class ImportOutputDTO extends TakaroDTO { id!: string; } +class MapTileInputDTO extends TakaroDTO { + @IsUUID('4') + id: string; + @IsNumber() + z: number; + @IsNumber() + x: number; + @IsNumber() + y: number; +} + class ImportOutputDTOAPI extends APIOutput { @Type(() => ImportOutputDTO) @ValidateNested() @@ -588,4 +611,26 @@ export class GameServerController { const result = await service.import(parsedImportData, validatedOptions); return apiResponse(result); } + + @Get('/gameserver/:id/map/info') + @UseBefore(AuthService.getAuthMiddleware([])) + @OpenAPI({ + description: 'Get map metadata for Leaflet', + }) + async getMapInfo(@Req() req: AuthenticatedRequest, @Params() params: ParamId) { + const service = new GameServerService(req.domainId); + return apiResponse(await service.getMapInfo(params.id)); + } + + @Get('/gameserver/:id/map/tile/:x/:y/:z') + @UseBefore(AuthService.getAuthMiddleware([])) + @ContentType('image/png') + @OpenAPI({ + description: 'Get a map tile for Leaflet', + }) + async getMapTile(@Req() req: AuthenticatedRequest, @Params() params: MapTileInputDTO) { + const service = new GameServerService(req.domainId); + const result = await service.getMapTile(params.id, params.x, params.y, params.z); + return result; + } } diff --git a/packages/app-api/src/controllers/Shop/Listing.ts b/packages/app-api/src/controllers/Shop/Listing.ts index d2692e3fcc..8125a594a3 100644 --- a/packages/app-api/src/controllers/Shop/Listing.ts +++ b/packages/app-api/src/controllers/Shop/Listing.ts @@ -15,6 +15,8 @@ import { ShopListingUpdateDTO, ShopListingCreateDTO, ShopImportOptions, + ShopListingItemMetaOutputDTO, + ShopListingItemMetaInputDTO, } from '../../service/Shop/dto.js'; import multer from 'multer'; @@ -156,7 +158,20 @@ export class ShopListingController { const rawImportData = JSON.parse(req.body.import); const rawOptions = JSON.parse(req.body.options); - const importData: ShopListingCreateDTO[] = rawImportData.map((item: any) => new ShopListingCreateDTO(item)); + const importData: ShopListingCreateDTO[] = rawImportData.map( + (listing: any) => + new ShopListingCreateDTO({ + ...listing, + items: listing.items.map( + (item: ShopListingItemMetaOutputDTO) => + new ShopListingItemMetaInputDTO({ + amount: item.amount, + quality: item.quality, + code: item.item.code, + }), + ), + }), + ); const options = new ShopImportOptions(rawOptions); await Promise.all(importData.map((item) => item.validate())); diff --git a/packages/app-api/src/controllers/__tests__/ShopListing.integration.test.ts b/packages/app-api/src/controllers/__tests__/ShopListing.integration.test.ts index 377ff769fe..9621e49899 100644 --- a/packages/app-api/src/controllers/__tests__/ShopListing.integration.test.ts +++ b/packages/app-api/src/controllers/__tests__/ShopListing.integration.test.ts @@ -23,11 +23,16 @@ const shopSetup = async function (this: IntegrationTest): Promise { return this.client.shopListing.shopListingControllerCreate({ gameServerId: this.setupData.gameServer1.id, - items: [{ itemId: items[0].id, amount: 1 }], + items: [{ code: items[0].code, amount: 1 }], price: 100 + i, name: `Test item ${i}`, }); @@ -222,6 +227,8 @@ const tests = [ expect(shop2Listings).to.have.length(shop1Listings.length); // Check createdAt and compare to before to ensure these are new listings expect(shop2ListingsBefore.every((l) => shop2Listings.some((l2) => l2.createdAt < l.createdAt))).to.be.true; + // Ensure there are items in the listing + expect(shop2Listings.every((l) => l.items.length > 0)).to.be.true; }, }), new IntegrationTest({ @@ -237,7 +244,7 @@ const tests = [ Array.from({ length: listingsToMake }).map(async (_, i) => { return this.client.shopListing.shopListingControllerCreate({ gameServerId: this.setupData.gameServer1.id, - items: [{ itemId: items[0].id, amount: 1 }], + items: [{ code: items[0].code, amount: 1 }], price: 100 + i, name: `Test item ${i}`, }); @@ -277,6 +284,8 @@ const tests = [ }) ).data.data; expect(shop2Listings).to.have.length(shop1Listings.length + shop2ListingsBefore.length); + // Ensure there are items in the listing + expect(shop2Listings.every((l) => l.items.length > 0)).to.be.true; }, }), new IntegrationTest({ @@ -292,7 +301,7 @@ const tests = [ Array.from({ length: listingsToMake }).map(async (_, i) => { return this.client.shopListing.shopListingControllerCreate({ gameServerId: this.setupData.gameServer1.id, - items: [{ itemId: items[0].id, amount: 1 }], + items: [{ code: items[0].code, amount: 1 }], price: 100 + i, name: `Test item ${i}`, }); diff --git a/packages/app-api/src/controllers/__tests__/ShopOrder.integration.test.ts b/packages/app-api/src/controllers/__tests__/ShopOrder.integration.test.ts index de0ffffb24..d1d2cbed3c 100644 --- a/packages/app-api/src/controllers/__tests__/ShopOrder.integration.test.ts +++ b/packages/app-api/src/controllers/__tests__/ShopOrder.integration.test.ts @@ -92,14 +92,14 @@ const shopSetup = async function (this: IntegrationTest): Promise; reachable!: boolean; - + deletedAt?: Date; type!: GAME_SERVER_TYPE; static get relationMappings() { @@ -108,7 +108,10 @@ export class GameServerRepo extends ITakaroRepo< async find(filters: ITakaroQuery) { const { query } = await this.getModel(); - const result = await new QueryBuilder(filters).build(query); + const qry = new QueryBuilder(filters).build(query); + qry.andWhere('deletedAt', null); + const result = await qry; + return { total: result.total, results: await Promise.all(result.results.map((item) => new GameServerOutputDTO(item))), @@ -117,7 +120,7 @@ export class GameServerRepo extends ITakaroRepo< async findOne(id: string, decryptConnectionInfo: boolean): Promise { const { query } = await this.getModel(); - const data = await query.findById(id); + const data = await query.findById(id).andWhere('deletedAt', null); if (!data) { throw new errors.NotFoundError(`Record with id ${id} not found`); @@ -148,7 +151,7 @@ export class GameServerRepo extends ITakaroRepo< async delete(id: string): Promise { const { query } = await this.getModel(); - const data = await query.deleteById(id); + const data = await query.update({ deletedAt: new Date() }).where({ id }); return !!data; } diff --git a/packages/app-api/src/db/items.ts b/packages/app-api/src/db/items.ts index 0b01288847..444d190466 100644 --- a/packages/app-api/src/db/items.ts +++ b/packages/app-api/src/db/items.ts @@ -40,6 +40,18 @@ export class ItemRepo extends ITakaroRepo { + const { query } = await this.getModel(); + const data = await query.whereIn('code', codes).andWhere('gameserverId', gameserverId); + + if (!data) { + throw new errors.NotFoundError(); + } + + return Promise.all(data.map((item) => new ItemsOutputDTO(item))); + } + async find(filters: ITakaroQuery) { const { query } = await this.getModel(); diff --git a/packages/app-api/src/db/shopListing.ts b/packages/app-api/src/db/shopListing.ts index 286cb63f96..09a14c4e5f 100644 --- a/packages/app-api/src/db/shopListing.ts +++ b/packages/app-api/src/db/shopListing.ts @@ -2,7 +2,7 @@ import { ITakaroQuery, QueryBuilder, TakaroModel } from '@takaro/db'; import { Model } from 'objection'; import { errors, traceableClass } from '@takaro/util'; import { GameServerModel } from './gameserver.js'; -import { ItemsModel } from './items.js'; +import { ItemRepo, ItemsModel } from './items.js'; import { RoleModel } from './role.js'; import { ITakaroRepo } from './base.js'; import { ShopListingOutputDTO, ShopListingUpdateDTO, ShopListingCreateDTO } from '../service/Shop/dto.js'; @@ -158,12 +158,21 @@ export class ShopListingRepo extends ITakaroRepo< if (!item.items || !item.items.length) throw new errors.BadRequestError('At least one item is required'); - const itemMetas = item.items.map((i) => ({ - listingId: listing.id, - itemId: i.itemId, - amount: i.amount, - quality: i.quality, - })); + const itemRepo = new ItemRepo(this.domainId); + const items = await itemRepo.translateItemCodesToIds( + item.gameServerId, + item.items.map((i) => i.code).filter((code): code is string => code !== undefined), + ); + const itemMetas = item.items + .map((i) => ({ + listingId: listing.id, + itemId: items.find((item) => item.code === i.code)?.id || i.itemId, + amount: i.amount, + quality: i.quality, + })) + .filter((i) => i.itemId); + + if (!itemMetas.length) throw new errors.BadRequestError('No valid items found'); await Promise.all( itemMetas.map(async (i) => { @@ -205,12 +214,21 @@ export class ShopListingRepo extends ITakaroRepo< const res = await query.updateAndFetchById(id, data.toJSON()).returning('*'); if (data.items) { - const itemMetas = data.items.map((i) => ({ - listingId: id, - itemId: i.itemId, - amount: i.amount, - quality: i.quality, - })); + const itemRepo = new ItemRepo(this.domainId); + const items = await itemRepo.translateItemCodesToIds( + data.gameServerId, + data.items.map((i) => i.code).filter((code): code is string => code !== undefined), + ); + const itemMetas = data.items + .map((i) => { + return { + listingId: id, + itemId: items.find((item) => item.code === i.code)?.id || i.itemId, + amount: i.amount, + quality: i.quality, + }; + }) + .filter((i) => i.itemId); await ItemOnShopListingModel.bindKnex(knex).query().delete().where('listingId', id); diff --git a/packages/app-api/src/service/GameServerService.ts b/packages/app-api/src/service/GameServerService.ts index fa3ffc3e8d..ec87977e8a 100644 --- a/packages/app-api/src/service/GameServerService.ts +++ b/packages/app-api/src/service/GameServerService.ts @@ -204,6 +204,13 @@ export class GameServerService extends TakaroService< time: new Date().toISOString(), }); await this.repo.delete(id); + await queueService.queues.system.queue.add( + { + domainId: this.domainId, + }, + {}, + 'gameServerDelete', + ); return id; } @@ -589,4 +596,14 @@ export class GameServerService extends TakaroService< id: job.id, }; } + + async getMapInfo(gameServerId: string) { + const gameInstance = await this.getGame(gameServerId); + return gameInstance.getMapInfo(); + } + + async getMapTile(gameServerId: string, x: number, y: number, z: number) { + const gameInstance = await this.getGame(gameServerId); + return gameInstance.getMapTile(x, y, z); + } } diff --git a/packages/app-api/src/service/Shop/dto.ts b/packages/app-api/src/service/Shop/dto.ts index ac3d5bf533..3d21399760 100644 --- a/packages/app-api/src/service/Shop/dto.ts +++ b/packages/app-api/src/service/Shop/dto.ts @@ -13,7 +13,7 @@ import { TakaroModelDTO, TakaroDTO } from '@takaro/util'; import { Type } from 'class-transformer'; import { ItemsOutputDTO } from '../ItemsService.js'; -class ShopListingItemMetaOutputDTO extends TakaroModelDTO { +export class ShopListingItemMetaOutputDTO extends TakaroModelDTO { @IsNumber() amount: number; @IsString() @@ -30,8 +30,12 @@ export class ShopListingItemMetaInputDTO extends TakaroDTO { diff --git a/packages/app-api/src/service/Shop/index.ts b/packages/app-api/src/service/Shop/index.ts index bb175209ba..7d09f968a6 100644 --- a/packages/app-api/src/service/Shop/index.ts +++ b/packages/app-api/src/service/Shop/index.ts @@ -13,6 +13,7 @@ import { ShopOrderStatus, ShopOrderCreateInternalDTO, ShopImportOptions, + ShopListingItemMetaInputDTO, } from './dto.js'; import { UserService } from '../User/index.js'; import { checkPermissions } from '../AuthService.js'; @@ -29,6 +30,7 @@ import { TakaroEventShopOrderStatusChanged, } from '@takaro/modules'; import { IMessageOptsDTO, IPlayerReferenceDTO } from '@takaro/gameserver'; +import { ItemsService } from '../ItemsService.js'; @traceableClass('service:shopListing') export class ShopListingService extends TakaroService< @@ -93,8 +95,28 @@ export class ShopListingService extends TakaroService< return listing; } - async create(item: ShopListingCreateDTO): Promise { - const created = await this.repo.create(item); + async create(listing: ShopListingCreateDTO): Promise { + const itemCodes = listing.items.map((item) => item.code).filter(Boolean); + const itemsService = new ItemsService(this.domainId); + const items = await itemsService.find({ filters: { code: itemCodes } }); + listing.items = listing.items.map((item) => { + const code = items.results.find((i) => i.code === item.code); + if (!code) { + if (!item.itemId) + throw new errors.BadRequestError(`Item with code ${item.code} not found and no itemId provided`); + return new ShopListingItemMetaInputDTO({ + amount: item.amount, + quality: item.quality, + itemId: item.itemId, + }); + } + return new ShopListingItemMetaInputDTO({ + amount: item.amount, + quality: item.quality, + code: item.code, + }); + }); + const created = await this.repo.create(listing); await this.eventService.create( new EventCreateDTO({ @@ -344,10 +366,10 @@ export class ShopListingService extends TakaroService< } const promises = await Promise.allSettled( - data.map((item) => { - item.draft = options.draft; - item.gameServerId = options.gameServerId; - return this.create(item); + data.map((listing) => { + listing.draft = options.draft; + listing.gameServerId = options.gameServerId; + return this.create(listing); }), ); diff --git a/packages/app-api/src/workers/csmmImportWorker.ts b/packages/app-api/src/workers/csmmImportWorker.ts index 3aa11b9e2b..80279cc08b 100644 --- a/packages/app-api/src/workers/csmmImportWorker.ts +++ b/packages/app-api/src/workers/csmmImportWorker.ts @@ -14,7 +14,6 @@ import { PlayerService } from '../service/PlayerService.js'; import { PlayerOnGameServerService } from '../service/PlayerOnGameserverService.js'; import { IGamePlayer } from '@takaro/modules'; import { ShopListingService } from '../service/Shop/index.js'; -import { ItemsService } from '../service/ItemsService.js'; import { ShopListingCreateDTO, ShopListingItemMetaInputDTO } from '../service/Shop/dto.js'; const log = logger('worker:csmmImport'); @@ -80,7 +79,6 @@ async function process(job: Job) { const playerService = new PlayerService(job.data.domainId); const pogService = new PlayerOnGameServerService(job.data.domainId); const shopListingService = new ShopListingService(job.data.domainId); - const itemService = new ItemsService(job.data.domainId); let server: GameServerOutputDTO | null; @@ -233,7 +231,6 @@ async function process(job: Job) { // Import shop listings if (job.data.options.shop) { for (const listing of data.shopListings) { - const item = await itemService.find({ filters: { code: [listing.name] } }); // CSMM stores quality null as 0... const quality = listing.quality.toString() === '0' ? null : listing.quality; @@ -245,7 +242,7 @@ async function process(job: Job) { items: [ new ShopListingItemMetaInputDTO({ amount: listing.amount, - itemId: item.results[0].id, + code: listing.name, quality: quality, }), ], diff --git a/packages/app-api/src/workers/systemWorker.ts b/packages/app-api/src/workers/systemWorker.ts index 108ed0d614..6e8805bc11 100644 --- a/packages/app-api/src/workers/systemWorker.ts +++ b/packages/app-api/src/workers/systemWorker.ts @@ -5,6 +5,7 @@ import { DomainRepo } from '../db/domain.js'; import ms from 'ms'; import { EventService } from '../service/EventService.js'; import { VariablesService } from '../service/VariablesService.js'; +import { GameServerService } from '../service/GameServerService.js'; export class SystemWorker extends TakaroWorker { constructor() { @@ -35,9 +36,12 @@ export async function processJob(job: Job) { }, ); } + } else if (job.name === 'gameServerDelete') { + await deleteGameServers(job.data.domainId); } else { await cleanEvents(job.data.domainId); await cleanExpiringVariables(job.data.domainId); + await deleteGameServers(job.data.domainId); } } @@ -52,3 +56,10 @@ async function cleanExpiringVariables(domainId: string) { const variableService = new VariablesService(domainId); await variableService.cleanExpiringVariables(); } + +async function deleteGameServers(domainId: string) { + const gameserverService = new GameServerService(domainId); + const repo = gameserverService.repo; + const { query } = await repo.getModel(); + await query.whereNotNull('deletedAt').delete(); +} diff --git a/packages/app-mock-gameserver/src/lib/gameserver/index.ts b/packages/app-mock-gameserver/src/lib/gameserver/index.ts index 2d08395f28..1354e6e32a 100644 --- a/packages/app-mock-gameserver/src/lib/gameserver/index.ts +++ b/packages/app-mock-gameserver/src/lib/gameserver/index.ts @@ -2,7 +2,15 @@ import { errors, logger } from '@takaro/util'; import { Redis } from '@takaro/db'; import { getSocketServer } from '../socket/index.js'; -import { IPlayerReferenceDTO, IGameServer, IMessageOptsDTO, CommandOutput, BanDTO, IItemDTO } from '@takaro/gameserver'; +import { + IPlayerReferenceDTO, + IGameServer, + IMessageOptsDTO, + CommandOutput, + BanDTO, + IItemDTO, + MapInfoDTO, +} from '@takaro/gameserver'; import { EventLogLine, GameEvents, @@ -394,6 +402,21 @@ export class MockGameserver implements IMockGameServer { async shutdown() { await this.sendLog('Shutting down'); } + + async getMapInfo() { + return new MapInfoDTO({ + enabled: false, + mapBlockSize: 100, + maxZoom: 5, + mapSizeX: 1000, + mapSizeY: 1000, + mapSizeZ: 1000, + }); + } + + async getMapTile(_x: number, _y: number, _z: number) { + return Buffer.from('mock-tile'); + } } const cachedMockServer: Map = new Map(); diff --git a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION index 4bc5d61816..758bb9c821 100644 --- a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION +++ b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION @@ -1 +1 @@ -7.9.0 +7.10.0 diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 1038c81e52..822a8f130c 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - c3c169ee2703ed3d5c50c1bb88ccfdd588028ca2 + * The version of the OpenAPI document: development - 531f5c531f94cfc4dc937d631eac00ae915724a1 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -5095,6 +5095,80 @@ export interface LoginOutputDTOAPI { */ meta: MetadataOutput; } +/** + * + * @export + * @interface MapInfoDTO + */ +export interface MapInfoDTO { + /** + * + * @type {boolean} + * @memberof MapInfoDTO + */ + enabled: boolean; + /** + * + * @type {number} + * @memberof MapInfoDTO + */ + mapBlockSize: number; + /** + * + * @type {number} + * @memberof MapInfoDTO + */ + maxZoom: number; + /** + * + * @type {number} + * @memberof MapInfoDTO + */ + mapSizeX: number; + /** + * + * @type {number} + * @memberof MapInfoDTO + */ + mapSizeY: number; + /** + * + * @type {number} + * @memberof MapInfoDTO + */ + mapSizeZ: number; +} +/** + * + * @export + * @interface MapTileInputDTO + */ +export interface MapTileInputDTO { + /** + * + * @type {string} + * @memberof MapTileInputDTO + */ + id: string; + /** + * + * @type {number} + * @memberof MapTileInputDTO + */ + z: number; + /** + * + * @type {number} + * @memberof MapTileInputDTO + */ + x: number; + /** + * + * @type {number} + * @memberof MapTileInputDTO + */ + y: number; +} /** * * @export @@ -7981,7 +8055,13 @@ export interface ShopListingItemMetaInputDTO { * @type {string} * @memberof ShopListingItemMetaInputDTO */ - itemId: string; + code?: string; + /** + * + * @type {string} + * @memberof ShopListingItemMetaInputDTO + */ + itemId?: string; } /** * @@ -14080,6 +14160,91 @@ export const GameServerApiAxiosParamCreator = function (configuration?: Configur options: localVarRequestOptions, }; }, + /** + * Get map metadata for Leaflet + * @summary Get map info + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + gameServerControllerGetMapInfo: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('gameServerControllerGetMapInfo', 'id', id); + const localVarPath = `/gameserver/{id}/map/info`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get a map tile for Leaflet + * @summary Get map tile + * @param {string} id + * @param {string} x + * @param {string} y + * @param {string} z + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + gameServerControllerGetMapTile: async ( + id: string, + x: string, + y: string, + z: string, + options: RawAxiosRequestConfig = {}, + ): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('gameServerControllerGetMapTile', 'id', id); + // verify required parameter 'x' is not null or undefined + assertParamExists('gameServerControllerGetMapTile', 'x', x); + // verify required parameter 'y' is not null or undefined + assertParamExists('gameServerControllerGetMapTile', 'y', y); + // verify required parameter 'z' is not null or undefined + assertParamExists('gameServerControllerGetMapTile', 'z', z); + const localVarPath = `/gameserver/{id}/map/tile/{x}/{y}/{z}` + .replace(`{${'id'}}`, encodeURIComponent(String(id))) + .replace(`{${'x'}}`, encodeURIComponent(String(x))) + .replace(`{${'y'}}`, encodeURIComponent(String(y))) + .replace(`{${'z'}}`, encodeURIComponent(String(z))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Get a module installation by id * @summary Get module installation @@ -14970,6 +15135,58 @@ export const GameServerApiFp = function (configuration?: Configuration) { configuration, )(axios, localVarOperationServerBasePath || basePath); }, + /** + * Get map metadata for Leaflet + * @summary Get map info + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async gameServerControllerGetMapInfo( + id: string, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.gameServerControllerGetMapInfo(id, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['GameServerApi.gameServerControllerGetMapInfo']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Get a map tile for Leaflet + * @summary Get map tile + * @param {string} id + * @param {string} x + * @param {string} y + * @param {string} z + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async gameServerControllerGetMapTile( + id: string, + x: string, + y: string, + z: string, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.gameServerControllerGetMapTile(id, x, y, z, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['GameServerApi.gameServerControllerGetMapTile']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, /** * Get a module installation by id * @summary Get module installation @@ -15566,6 +15783,37 @@ export const GameServerApiFactory = function (configuration?: Configuration, bas .gameServerControllerGetInstalledModules(id, options) .then((request) => request(axios, basePath)); }, + /** + * Get map metadata for Leaflet + * @summary Get map info + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + gameServerControllerGetMapInfo(id: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.gameServerControllerGetMapInfo(id, options).then((request) => request(axios, basePath)); + }, + /** + * Get a map tile for Leaflet + * @summary Get map tile + * @param {string} id + * @param {string} x + * @param {string} y + * @param {string} z + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + gameServerControllerGetMapTile( + id: string, + x: string, + y: string, + z: string, + options?: RawAxiosRequestConfig, + ): AxiosPromise { + return localVarFp + .gameServerControllerGetMapTile(id, x, y, z, options) + .then((request) => request(axios, basePath)); + }, /** * Get a module installation by id * @summary Get module installation @@ -15938,6 +16186,37 @@ export class GameServerApi extends BaseAPI { .then((request) => request(this.axios, this.basePath)); } + /** + * Get map metadata for Leaflet + * @summary Get map info + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof GameServerApi + */ + public gameServerControllerGetMapInfo(id: string, options?: RawAxiosRequestConfig) { + return GameServerApiFp(this.configuration) + .gameServerControllerGetMapInfo(id, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Get a map tile for Leaflet + * @summary Get map tile + * @param {string} id + * @param {string} x + * @param {string} y + * @param {string} z + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof GameServerApi + */ + public gameServerControllerGetMapTile(id: string, x: string, y: string, z: string, options?: RawAxiosRequestConfig) { + return GameServerApiFp(this.configuration) + .gameServerControllerGetMapTile(id, x, y, z, options) + .then((request) => request(this.axios, this.basePath)); + } + /** * Get a module installation by id * @summary Get module installation diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 6d43a79e62..6c10131029 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - c3c169ee2703ed3d5c50c1bb88ccfdd588028ca2 + * The version of the OpenAPI document: development - 531f5c531f94cfc4dc937d631eac00ae915724a1 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 9e88e581bc..3512612862 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - c3c169ee2703ed3d5c50c1bb88ccfdd588028ca2 + * The version of the OpenAPI document: development - 531f5c531f94cfc4dc937d631eac00ae915724a1 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 0667c72e4f..128282af84 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - c3c169ee2703ed3d5c50c1bb88ccfdd588028ca2 + * The version of the OpenAPI document: development - 531f5c531f94cfc4dc937d631eac00ae915724a1 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 9862529dfa..5b66579fea 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - c3c169ee2703ed3d5c50c1bb88ccfdd588028ca2 + * The version of the OpenAPI document: development - 531f5c531f94cfc4dc937d631eac00ae915724a1 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-components/src/components/inputs/selects/SelectQueryField/Generic/index.tsx b/packages/lib-components/src/components/inputs/selects/SelectQueryField/Generic/index.tsx index e578e60307..243d5ef821 100644 --- a/packages/lib-components/src/components/inputs/selects/SelectQueryField/Generic/index.tsx +++ b/packages/lib-components/src/components/inputs/selects/SelectQueryField/Generic/index.tsx @@ -199,7 +199,8 @@ export const GenericSelectQueryField = forwardRef { - const hasOptions = options && Children.count(options[0].props.children) > 1; + const hasProps = options && options[0].props; + const hasOptions = hasProps && Children.count(options[0].props.children) > 1; // initialFocus=-1 is used to prevent the first item from being focused when the list opens return ( diff --git a/packages/lib-db/src/migrations/sql/20241205201123-gameserver-deletedAt.ts b/packages/lib-db/src/migrations/sql/20241205201123-gameserver-deletedAt.ts new file mode 100644 index 0000000000..8cf834de84 --- /dev/null +++ b/packages/lib-db/src/migrations/sql/20241205201123-gameserver-deletedAt.ts @@ -0,0 +1,13 @@ +import { Knex } from 'knex'; + +export async function up(knex: Knex): Promise { + await knex.schema.alterTable('gameservers', (table) => { + table.timestamp('deletedAt').nullable().defaultTo(null); + }); +} + +export async function down(knex: Knex): Promise { + await knex.schema.alterTable('gameservers', (table) => { + table.dropColumn('deletedAt'); + }); +} diff --git a/packages/lib-gameserver/src/gameservers/7d2d/index.ts b/packages/lib-gameserver/src/gameservers/7d2d/index.ts index d1218eac80..689ce9edd5 100644 --- a/packages/lib-gameserver/src/gameservers/7d2d/index.ts +++ b/packages/lib-gameserver/src/gameservers/7d2d/index.ts @@ -340,4 +340,12 @@ export class SevenDaysToDie implements IGameServer { await this.executeConsoleCommand('shutdown'); } } + + async getMapInfo() { + return this.apiClient.getMapInfo(); + } + + async getMapTile(x: number, y: number, z: number) { + return this.apiClient.getMapTile(x, y, z); + } } diff --git a/packages/lib-gameserver/src/gameservers/7d2d/sdtdAPIClient.ts b/packages/lib-gameserver/src/gameservers/7d2d/sdtdAPIClient.ts index ac7d6558df..313788236a 100644 --- a/packages/lib-gameserver/src/gameservers/7d2d/sdtdAPIClient.ts +++ b/packages/lib-gameserver/src/gameservers/7d2d/sdtdAPIClient.ts @@ -8,6 +8,7 @@ import { StatsResponse, } from './apiResponses.js'; import { addCounterToAxios, errors } from '@takaro/util'; +import { MapInfoDTO } from '../../main.js'; export class SdtdApiClient { private client: Axios; @@ -77,4 +78,22 @@ export class SdtdApiClient { async getPlayerInventory(id: string): Promise> { return this.client.get(`/api/getplayerinventory?userid=${id}`); } + + async getMapInfo(): Promise { + const res = await this.client.get('/api/map/config'); + + return new MapInfoDTO({ + enabled: res.data.data.enabled, + mapBlockSize: res.data.data.mapBlockSize, + maxZoom: res.data.data.maxZoom, + mapSizeX: res.data.data.mapSize.x, + mapSizeY: res.data.data.mapSize.y, + mapSizeZ: res.data.data.mapSize.z, + }); + } + + async getMapTile(x: number, y: number, z: number): Promise { + const res = await this.client.get(`/map/${z}/${x}/${y}.png?t=${Date.now() / 1000}`); + return res.data; + } } diff --git a/packages/lib-gameserver/src/gameservers/mock/index.ts b/packages/lib-gameserver/src/gameservers/mock/index.ts index 8b7223ec6c..c9ea3e9ac2 100644 --- a/packages/lib-gameserver/src/gameservers/mock/index.ts +++ b/packages/lib-gameserver/src/gameservers/mock/index.ts @@ -7,6 +7,7 @@ import { IItemDTO, IMessageOptsDTO, IPlayerReferenceDTO, + MapInfoDTO, TestReachabilityOutputDTO, } from '../../interfaces/GameServer.js'; import { MockEmitter } from './emitter.js'; @@ -163,4 +164,19 @@ export class Mock implements IGameServer { async shutdown(): Promise { return this.requestFromServer('shutdown'); } + + async getMapInfo(): Promise { + return new MapInfoDTO({ + enabled: false, + mapBlockSize: 0, + maxZoom: 0, + mapSizeX: 0, + mapSizeY: 0, + mapSizeZ: 0, + }); + } + + async getMapTile(_x: number, _y: number, _z: number): Promise { + throw new Error('Not implemented'); + } } diff --git a/packages/lib-gameserver/src/gameservers/rust/index.ts b/packages/lib-gameserver/src/gameservers/rust/index.ts index 3d79fa8df5..4fa142479f 100644 --- a/packages/lib-gameserver/src/gameservers/rust/index.ts +++ b/packages/lib-gameserver/src/gameservers/rust/index.ts @@ -7,6 +7,7 @@ import { IGameServer, IItemDTO, IPlayerReferenceDTO, + MapInfoDTO, TestReachabilityOutputDTO, } from '../../interfaces/GameServer.js'; import { RustConnectionInfo } from './connectionInfo.js'; @@ -237,4 +238,19 @@ export class Rust implements IGameServer { async shutdown(): Promise { await this.executeConsoleCommand('quit'); } + + async getMapInfo(): Promise { + return new MapInfoDTO({ + enabled: false, + mapBlockSize: 0, + maxZoom: 0, + mapSizeX: 0, + mapSizeY: 0, + mapSizeZ: 0, + }); + } + + async getMapTile(_x: number, _y: number, _z: number): Promise { + throw new Error('Not implemented'); + } } diff --git a/packages/lib-gameserver/src/interfaces/GameServer.ts b/packages/lib-gameserver/src/interfaces/GameServer.ts index fe8cd09911..1b69dacd66 100644 --- a/packages/lib-gameserver/src/interfaces/GameServer.ts +++ b/packages/lib-gameserver/src/interfaces/GameServer.ts @@ -72,6 +72,21 @@ export class BanDTO extends TakaroDTO { expiresAt: string | null; } +export class MapInfoDTO extends TakaroDTO { + @IsBoolean() + enabled: boolean; + @IsNumber() + mapBlockSize: number; + @IsNumber() + maxZoom: number; + @IsNumber() + mapSizeX: number; + @IsNumber() + mapSizeY: number; + @IsNumber() + mapSizeZ: number; +} + export interface IGameServer { connectionInfo: unknown; getEventEmitter(): TakaroEmitter; @@ -100,4 +115,7 @@ export interface IGameServer { unbanPlayer(player: IPlayerReferenceDTO): Promise; listBans(): Promise; shutdown(): Promise; + + getMapInfo(): Promise; + getMapTile(x: number, y: number, z: number): Promise; } diff --git a/packages/lib-queues/src/TakaroQueue.ts b/packages/lib-queues/src/TakaroQueue.ts index 2ec1b29b93..b1020bc20e 100644 --- a/packages/lib-queues/src/TakaroQueue.ts +++ b/packages/lib-queues/src/TakaroQueue.ts @@ -22,13 +22,13 @@ export class TakaroQueue> { return hash; } - add(data: T, extra: JobsOptions = {}) { + add(data: T, extra: JobsOptions = {}, name = this.name) { const jobId = extra.jobId ?? this.getJobId(data); const isRepeatable = extra.repeat ? true : false; if (isRepeatable) { - return this.bullQueue.add(this.name, data, extra); + return this.bullQueue.add(name, data, extra); } else { - return this.bullQueue.add(this.name, data, { jobId, ...extra }); + return this.bullQueue.add(name, data, { jobId, ...extra }); } } diff --git a/packages/test/src/__snapshots__/GameServerController/Create.json b/packages/test/src/__snapshots__/GameServerController/Create.json index bcad4b8869..e233b1f5d7 100644 --- a/packages/test/src/__snapshots__/GameServerController/Create.json +++ b/packages/test/src/__snapshots__/GameServerController/Create.json @@ -5,6 +5,7 @@ "id": "59f2cdbf-ef7d-495f-be9e-531d4fd6ee29", "createdAt": "2023-12-24T15:22:57.559Z", "updatedAt": "2023-12-24T15:22:57.559Z", + "deletedAt": null, "name": "Test gameserver", "enabled": true, "connectionInfo": { diff --git a/packages/test/src/__snapshots__/GameServerController/Get by ID.json b/packages/test/src/__snapshots__/GameServerController/Get by ID.json index 0d4ed132b8..deca6a4b96 100644 --- a/packages/test/src/__snapshots__/GameServerController/Get by ID.json +++ b/packages/test/src/__snapshots__/GameServerController/Get by ID.json @@ -5,6 +5,7 @@ "id": "2600aac2-d5b8-455d-bf6a-12a242f5ee0a", "createdAt": "2023-12-24T15:22:57.034Z", "updatedAt": "2023-12-24T15:22:57.034Z", + "deletedAt": null, "name": "Test gameserver", "enabled": true, "connectionInfo": { diff --git a/packages/test/src/__snapshots__/GameServerController/Update.json b/packages/test/src/__snapshots__/GameServerController/Update.json index 22c4881ce6..4d893fe834 100644 --- a/packages/test/src/__snapshots__/GameServerController/Update.json +++ b/packages/test/src/__snapshots__/GameServerController/Update.json @@ -5,6 +5,7 @@ "id": "4218a6e4-001a-4175-a346-f9b8a920c3f4", "createdAt": "2023-12-24T15:22:57.938Z", "updatedAt": "2023-12-24T15:22:58.000Z", + "deletedAt": null, "name": "Test gameserver 2", "enabled": true, "connectionInfo": { diff --git a/packages/test/src/__snapshots__/ShopController/Update.json b/packages/test/src/__snapshots__/ShopController/Update.json index ff109350f9..525a2dfc4b 100644 --- a/packages/test/src/__snapshots__/ShopController/Update.json +++ b/packages/test/src/__snapshots__/ShopController/Update.json @@ -24,9 +24,9 @@ "createdAt": "2024-07-18T15:25:48.096Z", "updatedAt": "2024-07-18T15:25:48.096Z", "gameserverId": "becf27be-f2db-4a53-a2d4-56608001e5bb", - "name": "Stone", - "code": "stone", - "description": "Stone can get you stoned", + "name": "Wood", + "code": "wood", + "description": "Wood is good", "icon": null } } diff --git a/packages/web-docs/docusaurus.config.ts b/packages/web-docs/docusaurus.config.ts index 17f9ee12b7..91953ab38d 100644 --- a/packages/web-docs/docusaurus.config.ts +++ b/packages/web-docs/docusaurus.config.ts @@ -89,6 +89,21 @@ const config: Config = { theme: prismThemes.github, darkTheme: prismThemes.dracula, }, + algolia: { + // The application ID provided by Algolia + appId: 'EGKNUF24JA', + // Public API key: it is safe to commit it + apiKey: 'c346de81a50d15e8653e738f76871c15', + indexName: 'takaro', + // Optional: see doc section below + contextualSearch: true, + // Optional: Algolia search parameters + searchParameters: {}, + // Optional: path for search page that enabled by default (`false` to disable it) + searchPagePath: 'search', + // Optional: whether the insights feature is enabled or not on Docsearch (`false` by default) + insights: true, + }, } satisfies Preset.ThemeConfig, }; diff --git a/packages/web-main/index.html b/packages/web-main/index.html index 96617c4ec7..3c2d6feac5 100644 --- a/packages/web-main/index.html +++ b/packages/web-main/index.html @@ -43,6 +43,17 @@ + @@ -56,4 +67,4 @@ - \ No newline at end of file + diff --git a/packages/web-main/src/components/cards/ShopListingCard/index.tsx b/packages/web-main/src/components/cards/ShopListingCard/index.tsx index 402e70327a..61f719df65 100644 --- a/packages/web-main/src/components/cards/ShopListingCard/index.tsx +++ b/packages/web-main/src/components/cards/ShopListingCard/index.tsx @@ -27,7 +27,8 @@ export const ShopListingCard: FC = ({ gameServerType, playerCurrencyAmount, }) => { - const shopListingName = shopListing.name || shopListing.items[0].item.name; + const firstItem = shopListing.items[0]?.item || { name: 'Unknown', code: 'unknown' }; + const shopListingName = shopListing.name || firstItem.name; const hasPermission = useHasPermission(['MANAGE_SHOP_LISTINGS']); return ( @@ -48,8 +49,8 @@ export const ShopListingCard: FC = ({ {getInitials(shopListingName)} diff --git a/packages/web-main/src/hooks/useAuth.tsx b/packages/web-main/src/hooks/useAuth.tsx index ce379fc2af..8f3d4d0a79 100644 --- a/packages/web-main/src/hooks/useAuth.tsx +++ b/packages/web-main/src/hooks/useAuth.tsx @@ -34,6 +34,14 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { email: session.user.email, domain: session.domain, }); + + // @ts-expect-error - We load Produktly via a script tag in the index... + window.Produktly.identifyUser(session.user.idpId, { + domain: session.domain, + createdAt: session.user.createdAt, + email: session.user.email, + permissions: session.user.roles.map((role) => role.role.permissions.map((p) => p.permission.permission)).flat(), + }); }, []); const getSession = async function (): Promise { diff --git a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json index bff77c0aba..5b7271d932 100644 --- a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json +++ b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json @@ -1 +1 @@ -{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} +{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions, name?: string): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} diff --git a/packages/web-main/src/routes/_auth/_global/-roles/RolesTableView.tsx b/packages/web-main/src/routes/_auth/_global/-roles/RolesTableView.tsx index ecb2871c37..975758c749 100644 --- a/packages/web-main/src/routes/_auth/_global/-roles/RolesTableView.tsx +++ b/packages/web-main/src/routes/_auth/_global/-roles/RolesTableView.tsx @@ -148,7 +148,7 @@ const PlayerCount: FC<{ roleId: string }> = ({ roleId }) => { return 'unknown'; } - return data.data.length; + return data.meta.total; }; const UserCount: FC<{ roleId: string }> = ({ roleId }) => { @@ -164,5 +164,5 @@ const UserCount: FC<{ roleId: string }> = ({ roleId }) => { return 'unknown'; } - return data.data.length; + return data.meta.total; };