@squarecloud/api
Version:
A NodeJS wrapper for Square Cloud API
1 lines • 74.5 kB
Source Map (JSON)
{"version":3,"sources":["../package.json","../src/index.ts","../src/structures/application/base.ts","../src/lib/routes.ts","../src/modules/applications.ts","../src/services/cache/base.ts","../src/services/cache/application.ts","../src/structures/backup.ts","../src/modules/backups.ts","../src/structures/deploy.ts","../src/modules/deploys.ts","../src/modules/files.ts","../src/modules/network.ts","../src/modules/user.ts","../src/services/api.ts","../src/services/cache/global.ts","../src/structures/application/application.ts","../src/structures/application/website.ts","../src/structures/collection.ts","../src/structures/error.ts","../src/structures/status.ts","../src/structures/user.ts","../src/assertions/common.ts","../src/assertions/literal.ts","../src/types/client.ts"],"sourcesContent":["{\n\t\"name\": \"@squarecloud/api\",\n\t\"version\": \"3.7.9\",\n\t\"description\": \"A NodeJS wrapper for Square Cloud API\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./lib/index.d.ts\",\n\t\t\t\t\"default\": \"./lib/index.js\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./lib/index.d.cts\",\n\t\t\t\t\"default\": \"./lib/index.cjs\"\n\t\t\t},\n\t\t\t\"default\": \"./lib/index.js\"\n\t\t}\n\t},\n\t\"packageManager\": \"pnpm@10.11.1\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"release\": \"pnpm build && changeset publish\",\n\t\t\"build\": \"tsup ./src\",\n\t\t\"check-types\": \"tsc --noEmit\",\n\t\t\"lint\": \"biome check --write .\",\n\t\t\"lint:ci\": \"biome check .\",\n\t\t\"test\": \"node --test test/*.test.js\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=18.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@biomejs/biome\": \"^1.9.4\",\n\t\t\"@changesets/cli\": \"^2.29.4\",\n\t\t\"@squarecloud/api-types\": \"^0.5.0\",\n\t\t\"@types/node\": \"^22.15.29\",\n\t\t\"ts-node\": \"^10.9.2\",\n\t\t\"ts-node-dev\": \"^2.0.0\",\n\t\t\"tsc-alias\": \"^1.8.16\",\n\t\t\"tsup\": \"^8.5.0\",\n\t\t\"typescript\": \"^5.8.3\"\n\t},\n\t\"keywords\": [\n\t\t\"wrapper\",\n\t\t\"square\",\n\t\t\"squarecloud\",\n\t\t\"api\",\n\t\t\"typescript\",\n\t\t\"app\",\n\t\t\"bot\",\n\t\t\"website\",\n\t\t\"host\"\n\t],\n\t\"author\": {\n\t\t\"name\": \"joaotonaco\",\n\t\t\"url\": \"https://github.com/joaotonaco\"\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/squarecloudofc/sdk-api-js.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/squarecloudofc/sdk-api-js/issues\"\n\t},\n\t\"homepage\": \"https://docs.squarecloud.app/sdks/js/client\",\n\t\"license\": \"MIT\"\n}\n","import { assertString } from \"./assertions/literal\";\nimport { ApplicationsModule, UserModule } from \"./modules\";\nimport { APIService, GlobalCacheService } from \"./services\";\nimport { type ClientEvents, TypedEventEmitter } from \"./types\";\n\nexport class SquareCloudAPI extends TypedEventEmitter<ClientEvents> {\n\tpublic static apiInfo = {\n\t\tbaseUrl: \"https://api.squarecloud.app\",\n\t\tversion: \"v2\",\n\t};\n\n\t/** The API service */\n\tpublic readonly api: APIService;\n\n\t/** The applications module */\n\tpublic readonly applications = new ApplicationsModule(this);\n\t/** The user module */\n\tpublic readonly user = new UserModule(this);\n\t/** The global cache service */\n\tpublic readonly cache = new GlobalCacheService();\n\n\t/**\n\t * Creates an API instance\n\t *\n\t * @param apiKey - Your API Token (request at [Square Cloud Dashboard](https://squarecloud.app/dashboard))\n\t */\n\tconstructor(apiKey: string) {\n\t\tsuper();\n\n\t\tassertString(apiKey, \"API_KEY\");\n\t\tthis.api = new APIService(apiKey);\n\t}\n\n\t/** @deprecated Use SquareCloudAPI#user instead. */\n\tget users() {\n\t\tconsole.warn(\n\t\t\t\"[SquareCloudAPI] The 'users' property is deprecated and will be removed in the next major version. Use SquareCloudAPI#user instead.\",\n\t\t);\n\t\treturn this.user;\n\t}\n}\n\nexport * from \"./structures\";\nexport * from \"./types\";\n","import type {\n\tAPIUserApplication,\n\tApplicationLanguage,\n} from \"@squarecloud/api-types/v2\";\nimport { readFile } from \"fs/promises\";\n\nimport { assertPathLike, assertString } from \"@/assertions/literal\";\nimport type { SquareCloudAPI } from \"@/index\";\nimport { Routes } from \"@/lib/routes\";\nimport { BackupsModule, DeploysModule, FilesModule } from \"@/modules\";\nimport { ApplicationCacheService } from \"@/services\";\nimport { ApplicationStatus } from \"@/structures\";\nimport type { Application } from \"./application\";\n\n/**\n * Represents the base application from the user endpoint\n */\nexport class BaseApplication {\n\t/** The application ID */\n\tpublic readonly id: string;\n\t/** The application display name */\n\tpublic name: string;\n\t/** The application description */\n\tpublic description?: string;\n\t/** The url to manage the application via web */\n\tpublic url: string;\n\t/** The application total ram */\n\tpublic ram: number;\n\t/** The application current cluster */\n\tpublic cluster: string;\n\t/**\n\t * The application programming language\n\t *\n\t * - `javascript`\n\t * - `typescript`\n\t * - `python`\n\t * - `java`\n\t * - `elixir`\n\t * - `rust`\n\t * - `go`\n\t * - `php`\n\t * - `dotnet`\n\t * - `static`\n\t */\n\tpublic language: ApplicationLanguage;\n\n\t/** Cache service for this application */\n\tpublic readonly cache = new ApplicationCacheService();\n\t/** Files module for this application */\n\tpublic readonly files = new FilesModule(this);\n\t/** Backup module for this application */\n\tpublic readonly backups = new BackupsModule(this);\n\t/** Deploys module for this application */\n\tpublic readonly deploys = new DeploysModule(this);\n\n\t/**\n\t * Represents the base application from the user endpoint\n\t *\n\t * @constructor\n\t * @param client - The client for this application\n\t * @param data - The data from this application\n\t */\n\tconstructor(\n\t\tpublic readonly client: SquareCloudAPI,\n\t\tdata: APIUserApplication,\n\t) {\n\t\tconst { id, name, desc, ram, lang, cluster } = data;\n\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t\tthis.description = desc;\n\t\tthis.ram = ram;\n\t\tthis.language = lang;\n\t\tthis.cluster = cluster;\n\t\tthis.url = `https://squarecloud.app/dashboard/app/${id}`;\n\t}\n\n\t/** @deprecated Use `Application#backups` instead */\n\tget backup() {\n\t\tconsole.warn(\n\t\t\t\"[SquareCloudAPI] The 'backup' property is deprecated and will be removed in the the next major version. Use Application#backups instead.\",\n\t\t);\n\t\treturn this.backups;\n\t}\n\n\t/**\n\t * Fetches this application for full information\n\t */\n\tasync fetch(): Promise<Application> {\n\t\treturn this.client.applications.fetch(this.id);\n\t}\n\n\t/**\n\t * Gets the application current status information\n\t */\n\tasync getStatus(): Promise<ApplicationStatus> {\n\t\tconst data = await this.client.api.request(Routes.apps.status(this.id));\n\t\tconst status = new ApplicationStatus(this.client, data.response, this.id);\n\n\t\tthis.client.emit(\"statusUpdate\", this, this.cache.status, status);\n\t\tthis.cache.set(\"status\", status);\n\n\t\treturn status;\n\t}\n\n\t/**\n\t * Gets the application current logs\n\t */\n\tasync getLogs(): Promise<string> {\n\t\tconst data = await this.client.api.request(Routes.apps.logs(this.id));\n\t\tconst { logs } = data.response;\n\n\t\tthis.client.emit(\"logsUpdate\", this, this.cache.logs, logs);\n\t\tthis.cache.set(\"logs\", logs);\n\n\t\treturn logs;\n\t}\n\n\t/**\n\t * Starts up the application\n\t * @returns `boolean` for success or fail\n\t */\n\tasync start(): Promise<boolean> {\n\t\tconst data = await this.client.api.request(Routes.apps.start(this.id), {\n\t\t\tmethod: \"POST\",\n\t\t});\n\n\t\treturn data?.status === \"success\";\n\t}\n\n\t/**\n\t * Stops the application\n\t * @returns `boolean` for success or fail\n\t */\n\tasync stop(): Promise<boolean> {\n\t\tconst data = await this.client.api.request(Routes.apps.stop(this.id), {\n\t\t\tmethod: \"POST\",\n\t\t});\n\n\t\treturn data?.status === \"success\";\n\t}\n\n\t/**\n\t * Restarts the application\n\t * @returns `boolean` for success or fail\n\t */\n\tasync restart(): Promise<boolean> {\n\t\tconst data = await this.client.api.request(Routes.apps.restart(this.id), {\n\t\t\tmethod: \"POST\",\n\t\t});\n\n\t\treturn data?.status === \"success\";\n\t}\n\n\t/**\n\t * Deletes your whole application\n\t * - This action is irreversible.\n\t *\n\t * @returns `boolean` for success or fail\n\t */\n\tasync delete(): Promise<boolean> {\n\t\tconst data = await this.client.api.request(Routes.apps.delete(this.id), {\n\t\t\tmethod: \"DELETE\",\n\t\t});\n\n\t\treturn data?.status === \"success\";\n\t}\n\n\t/**\n\t * Commit files to your application folder\n\t *\n\t * - This action is irreversible.\n\t *\n\t * - Tip: use this to get an absolute path.\n\t * ```ts\n\t * require('path').join(__dirname, 'fileName')\n\t * ```\n\t * - Tip 2: use a zip file to commit more than one archive\n\t *\n\t * @param file - Buffer or absolute path to the file\n\t * @param fileName - The file name (e.g.: \"index.js\")\n\t * @param restart - Whether the application should be restarted after the commit\n\t * @returns `true` for success or `false` for fail\n\t */\n\tasync commit(file: string | Buffer, fileName?: string): Promise<boolean> {\n\t\tassertPathLike(file, \"COMMIT_FILE\");\n\n\t\tif (fileName) {\n\t\t\tassertString(fileName, \"FILE_NAME\");\n\t\t}\n\n\t\tif (typeof file === \"string\") {\n\t\t\tfile = await readFile(file);\n\t\t}\n\n\t\tconst formData = new FormData();\n\t\tconst blob = new Blob([file]);\n\t\tformData.append(\"file\", blob, fileName || \"commit.zip\");\n\n\t\tconst data = await this.client.api.request(Routes.apps.commit(this.id), {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: formData,\n\t\t});\n\n\t\treturn data?.status === \"success\";\n\t}\n}\n","import type { APIEndpoint } from \"@/types\";\n\nexport type Route<T extends APIEndpoint> = string & { __route: T };\nexport const Route = <T extends APIEndpoint>(route: string) =>\n\troute as Route<T>;\n\ninterface IRoutes {\n\t[k: string]: ((...args: string[]) => Route<APIEndpoint>) | IRoutes;\n}\n\nexport const Routes = {\n\tuser: () => {\n\t\treturn Route<\"user\">(\"users/me\");\n\t},\n\tservice: {\n\t\tstatus: () => {\n\t\t\treturn Route<\"service/status\">(\"service/status\");\n\t\t},\n\t},\n\tapps: {\n\t\tupload: () => {\n\t\t\treturn Route<\"apps/upload\">(\"apps\");\n\t\t},\n\t\tstatusAll: () => {\n\t\t\treturn Route<\"apps/status-all\">(\"apps/status\");\n\t\t},\n\t\tinfo: (appId: string) => {\n\t\t\treturn Route<\"apps/info\">(`apps/${appId}`);\n\t\t},\n\t\tstatus: (appId: string) => {\n\t\t\treturn Route<\"apps/status\">(`apps/${appId}/status`);\n\t\t},\n\t\tlogs: (appId: string) => {\n\t\t\treturn Route<\"apps/logs\">(`apps/${appId}/logs`);\n\t\t},\n\t\tdelete: (appId: string) => {\n\t\t\treturn Route<\"apps/delete\">(`apps/${appId}`);\n\t\t},\n\t\tcommit: (appId: string) => {\n\t\t\treturn Route<\"apps/commit\">(`apps/${appId}/commit`);\n\t\t},\n\t\tsnapshots: (appId: string) => {\n\t\t\treturn Route<\"apps/snapshots\">(`apps/${appId}/snapshots`);\n\t\t},\n\t\tgenerateSnapshot: (appId: string) => {\n\t\t\treturn Route<\"apps/generate-snapshot\">(`apps/${appId}/snapshots`);\n\t\t},\n\t\tstart: (appId: string) => {\n\t\t\treturn Route<\"apps/start\">(`apps/${appId}/start`);\n\t\t},\n\t\trestart: (appId: string) => {\n\t\t\treturn Route<\"apps/restart\">(`apps/${appId}/restart`);\n\t\t},\n\t\tstop: (appId: string) => {\n\t\t\treturn Route<\"apps/stop\">(`apps/${appId}/stop`);\n\t\t},\n\t\tfiles: {\n\t\t\tread: (appId: string) => {\n\t\t\t\treturn Route<\"apps/files/read\">(`apps/${appId}/files/content`);\n\t\t\t},\n\t\t\tlist: (appId: string) => {\n\t\t\t\treturn Route<\"apps/files/list\">(`apps/${appId}/files`);\n\t\t\t},\n\t\t\tupsert: (appId: string) => {\n\t\t\t\treturn Route<\"apps/files/upsert\">(`apps/${appId}/files`);\n\t\t\t},\n\t\t\tmove: (appId: string) => {\n\t\t\t\treturn Route<\"apps/files/move\">(`apps/${appId}/files`);\n\t\t\t},\n\t\t\tdelete: (appId: string) => {\n\t\t\t\treturn Route<\"apps/files/delete\">(`apps/${appId}/files`);\n\t\t\t},\n\t\t},\n\t\tdeployments: {\n\t\t\tlist: (appId: string) => {\n\t\t\t\treturn Route<\"apps/deployments/list\">(`apps/${appId}/deployments`);\n\t\t\t},\n\t\t\tcurrent: (appId: string) => {\n\t\t\t\treturn Route<\"apps/deployments/current\">(\n\t\t\t\t\t`apps/${appId}/deployments/current`,\n\t\t\t\t);\n\t\t\t},\n\t\t\twebhook: (appId: string) => {\n\t\t\t\treturn Route<\"apps/deployments/webhook\">(\n\t\t\t\t\t`apps/${appId}/deploy/webhook`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\tnetwork: {\n\t\t\tdns: (appId: string) => {\n\t\t\t\treturn Route<\"apps/network/dns\">(`apps/${appId}/network/dns`);\n\t\t\t},\n\t\t\tcustom: (appId: string) => {\n\t\t\t\treturn Route<\"apps/network/custom\">(`apps/${appId}/network/custom`);\n\t\t\t},\n\t\t\tanalytics: (appId: string) => {\n\t\t\t\treturn Route<\"apps/network/analytics\">(\n\t\t\t\t\t`apps/${appId}/network/analytics`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t},\n} satisfies IRoutes;\n","import type { RESTPostAPIApplicationUploadResult } from \"@squarecloud/api-types/v2\";\nimport { readFile } from \"fs/promises\";\n\nimport { assertPathLike, assertString } from \"@/assertions/literal\";\nimport { Routes } from \"@/lib/routes\";\nimport {\n\tApplication,\n\ttype BaseApplication,\n\ttype Collection,\n\tSimpleApplicationStatus,\n\tSquareCloudAPIError,\n\tUser,\n} from \"@/structures\";\nimport type { SquareCloudAPI } from \"..\";\n\nexport class ApplicationsModule {\n\tconstructor(public readonly client: SquareCloudAPI) {}\n\n\t/**\n\t * If the ID is provided, it will return an application that you can manage or get information\n\t * If the ID is not provided, it will return a collection of applications\n\t *\n\t * @param applicationId - The application ID, you must own the application\n\t */\n\tasync get(): Promise<Collection<string, BaseApplication>>;\n\tasync get(applicationId: string): Promise<BaseApplication>;\n\tasync get(\n\t\tapplicationId?: string,\n\t): Promise<BaseApplication | Collection<string, BaseApplication>> {\n\t\tconst { response } = await this.client.api.request(Routes.user());\n\t\tconst user = new User(this.client, response);\n\n\t\tthis.client.emit(\"userUpdate\", this.client.cache.user, user);\n\t\tthis.client.cache.set(\"user\", user);\n\n\t\tif (applicationId) {\n\t\t\tassertString(applicationId, \"APP_ID\");\n\t\t\tconst application = user.applications.get(applicationId);\n\n\t\t\tif (!application) {\n\t\t\t\tthrow new SquareCloudAPIError(\"APP_NOT_FOUND\");\n\t\t\t}\n\n\t\t\treturn application;\n\t\t}\n\n\t\treturn user.applications;\n\t}\n\n\t/**\n\t * Uploads an application\n\t *\n\t * @param file - The zip file path or Buffer\n\t *\n\t * @returns The uploaded application data\n\t */\n\tasync create(\n\t\tfile: string | Buffer,\n\t): Promise<RESTPostAPIApplicationUploadResult> {\n\t\tassertPathLike(file, \"UPLOAD_FILE\");\n\n\t\tif (typeof file === \"string\") {\n\t\t\tfile = await readFile(file);\n\t\t}\n\n\t\tconst formData = new FormData();\n\t\tconst blob = new Blob([file]);\n\t\tformData.append(\"file\", blob, \"app.zip\");\n\n\t\tconst data = await this.client.api.request(Routes.apps.upload(), {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: formData,\n\t\t});\n\n\t\treturn data.response;\n\t}\n\n\t/**\n\t * Gets the summary status for all your applications\n\t */\n\tasync statusAll(): Promise<SimpleApplicationStatus[]> {\n\t\tconst data = await this.client.api.request(Routes.apps.statusAll());\n\n\t\treturn data.response.map(\n\t\t\t(status) => new SimpleApplicationStatus(this.client, status),\n\t\t);\n\t}\n\n\t/**\n\t * Returns an application that you can manage or get information\n\t *\n\t * @param applicationId - The application ID, you must own the application\n\t */\n\tasync fetch(applicationId: string): Promise<Application> {\n\t\tconst { response } = await this.client.api.request(\n\t\t\tRoutes.apps.info(applicationId),\n\t\t);\n\n\t\treturn new Application(this.client, response);\n\t}\n}\n\nexport * from \"../services/cache/application\";\nexport * from \"./backups\";\nexport * from \"./deploys\";\nexport * from \"./files\";\nexport * from \"./network\";\n","export abstract class BaseCacheService<\n\tStruct extends object,\n\tKeys extends keyof Struct = keyof Struct,\n> {\n\tprotected cache: Struct;\n\n\tset<T extends Keys>(key: T, value: Struct[T]) {\n\t\tReflect.set(this.cache, key, value);\n\t}\n\n\tget<T extends Keys>(key: T): Struct[T] {\n\t\treturn this.cache[key];\n\t}\n\n\tremove<T extends Keys>(key: T) {\n\t\tReflect.set(this.cache, key, undefined);\n\t}\n}\n","import type { ApplicationStatus } from \"@/structures\";\nimport type { Backup } from \"@/structures/backup\";\nimport { BaseCacheService } from \"./base\";\n\nexport interface ApplicationCache {\n\treadonly status?: ApplicationStatus;\n\treadonly backups?: Backup[];\n\treadonly logs?: string;\n}\n\nexport class ApplicationCacheService extends BaseCacheService<ApplicationCache> {\n\tprotected cache: ApplicationCache = {\n\t\tstatus: undefined,\n\t\tbackups: undefined,\n\t\tlogs: undefined,\n\t};\n\n\tget status() {\n\t\treturn this.cache.status;\n\t}\n\n\tget backups() {\n\t\treturn this.cache.backups;\n\t}\n\n\tget logs() {\n\t\treturn this.cache.logs;\n\t}\n}\n","import type { APIApplicationBackup } from \"@squarecloud/api-types/v2\";\n\nimport type { BaseApplication } from \"./application/base\";\n\n/**\n * Represents an application backup (snapshot)\n */\nexport class Backup {\n\t/** Size of the backup in bytes. */\n\tpublic size: number;\n\n\t/** Date of the last modification of the backup. */\n\tpublic modifiedAt: Date;\n\n\t/** Date of the last modification of the backup in millisseconds. */\n\tpublic modifiedTimestamp: number;\n\n\t/** AWS access key for the backup. */\n\tpublic readonly key: string;\n\n\t/** The URL for downloading this backup */\n\tpublic readonly url: string;\n\n\t/**\n\t * Represents an application backup (snapshot)\n\t *\n\t * @constructor\n\t * @param application - The application from which you fetched the backups\n\t * @param data - The data from this backup\n\t */\n\tconstructor(\n\t\tpublic readonly application: BaseApplication,\n\t\tdata: APIApplicationBackup,\n\t) {\n\t\tconst { name, size, modified, key } = data;\n\t\tconst { userId } = application.client.api;\n\n\t\tthis.size = size;\n\t\tthis.modifiedAt = new Date(modified);\n\t\tthis.modifiedTimestamp = this.modifiedAt.getTime();\n\t\tthis.key = key;\n\t\tthis.url = `https://snapshots.squarecloud.app/applications/${userId}/${name}.zip?${key}`;\n\t}\n\n\t/**\n\t * Downloads this backup\n\t * @returns The downloaded backup bufer\n\t */\n\tasync download(): Promise<Buffer> {\n\t\tconst res = await fetch(this.url)\n\t\t\t.then((res) => res.arrayBuffer())\n\t\t\t.catch(() => undefined);\n\n\t\tif (!res) {\n\t\t\tthrow new Error(\"BACKUP_DOWNLOAD_FAILED\");\n\t\t}\n\n\t\treturn Buffer.from(res);\n\t}\n}\n","import type { RESTPostAPIApplicationBackupResult } from \"@squarecloud/api-types/v2\";\n\nimport { Routes } from \"@/lib/routes\";\nimport { type BaseApplication, SquareCloudAPIError } from \"@/structures\";\nimport { Backup } from \"@/structures/backup\";\n\nexport class BackupsModule {\n\tconstructor(public readonly application: BaseApplication) {}\n\n\t/**\n\t * Gets the list of generated backups (snapshots) for this application\n\t */\n\tasync list(): Promise<Backup[]> {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.snapshots(this.application.id),\n\t\t);\n\n\t\tconst backups = data.response.map(\n\t\t\t(backup) => new Backup(this.application, backup),\n\t\t);\n\n\t\tthis.application.client.emit(\n\t\t\t\"backupsUpdate\",\n\t\t\tthis.application,\n\t\t\tthis.application.cache.backups,\n\t\t\tbackups,\n\t\t);\n\t\tthis.application.cache.set(\"backups\", backups);\n\n\t\treturn backups;\n\t}\n\n\t/**\n\t * Generates a new backup\n\t * @returns The generated backup URL and key\n\t */\n\tasync create(): Promise<RESTPostAPIApplicationBackupResult> {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.generateSnapshot(this.application.id),\n\t\t\t{ method: \"POST\" },\n\t\t);\n\n\t\treturn data.response;\n\t}\n\n\t/**\n\t * Generates a new backup and downloads it\n\t * @returns The downloaded backup bufer\n\t */\n\tasync download(): Promise<Buffer> {\n\t\tconst backup = await this.create();\n\n\t\tconst res = await fetch(backup.url)\n\t\t\t.then((res) => res.arrayBuffer())\n\t\t\t.catch(() => undefined);\n\n\t\tif (!res) {\n\t\t\tthrow new SquareCloudAPIError(\"BACKUP_DOWNLOAD_FAILED\");\n\t\t}\n\n\t\treturn Buffer.from(res);\n\t}\n}\n","import type { APIDeployment, DeploymentState } from \"@squarecloud/api-types/v2\";\n\nimport type { BaseApplication } from \"./application/base\";\n\n/**\n * Represents an application deployment\n */\nexport class Deployment {\n\t/** The ID of the deploy. */\n\tpublic readonly id: `git-${string}`;\n\n\t/** The current state of the deploy. */\n\tpublic state: DeploymentState;\n\n\t/** The date the deploy was created. */\n\tpublic createdAt: Date;\n\n\t/** The date the deploy was created in millisseconds. */\n\tpublic createdTimestamp: number;\n\n\t/**\n\t * Represents an application deployment\n\t *\n\t * @constructor\n\t * @param application - The application from which you fetched the deployment\n\t * @param data - The data from this deployment\n\t */\n\tconstructor(\n\t\tpublic readonly application: BaseApplication,\n\t\tdata: APIDeployment,\n\t) {\n\t\tconst { id, state, date } = data;\n\n\t\tthis.id = id;\n\t\tthis.state = state;\n\t\tthis.createdAt = new Date(date);\n\t\tthis.createdTimestamp = this.createdAt.getTime();\n\t}\n}\n","import { assertString } from \"@/assertions/literal\";\nimport { Routes } from \"@/lib/routes\";\nimport type { BaseApplication } from \"@/structures\";\nimport { Deployment } from \"@/structures/deploy\";\n\nexport class DeploysModule {\n\tconstructor(public readonly application: BaseApplication) {}\n\n\t/**\n\t * Integrates Square Cloud with GitHub webhooks\n\t *\n\t * @param accessToken - The access token for your GitHub repository. You can find this in your [GitHub Tokens Classic](https://github.com/settings/tokens/new)\n\t */\n\tasync integrateGithubWebhook(accessToken: string) {\n\t\tassertString(accessToken);\n\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.deployments.webhook(this.application.id),\n\t\t\t{ method: \"POST\", body: { access_token: accessToken } },\n\t\t);\n\n\t\treturn data.response.webhook;\n\t}\n\n\t/**\n\t * Gets the last 10 deployments of an application from the last 24 hours\n\t */\n\tasync list() {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.deployments.list(this.application.id),\n\t\t);\n\n\t\treturn data.response.map(\n\t\t\t(deployment) => new Deployment(this.application, deployment),\n\t\t);\n\t}\n\n\t/**\n\t * Gets the current webhook URL\n\t */\n\tasync webhookURL() {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.deployments.current(this.application.id),\n\t\t);\n\n\t\treturn data.response.webhook;\n\t}\n}\n","import { join } from \"path\";\nimport { readFile } from \"fs/promises\";\n\nimport { assertPathLike, assertString } from \"@/assertions/literal\";\nimport { Routes } from \"@/lib/routes\";\nimport type { BaseApplication } from \"@/structures\";\n\nexport class FilesModule {\n\tconstructor(public readonly application: BaseApplication) {}\n\n\t/**\n\t * Lists the files inside a directory\n\t *\n\t * @param path - The absolute directory path\n\t */\n\tasync list(path = \"/\") {\n\t\tassertString(path, \"LIST_FILES_PATH\");\n\n\t\tconst { response } = await this.application.client.api.request(\n\t\t\tRoutes.apps.files.list(this.application.id),\n\t\t\t{ query: { path } },\n\t\t);\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Reads the specified file content\n\t *\n\t * @param path - The absolute file path\n\t */\n\tasync read(path: string) {\n\t\tassertString(path, \"READ_FILE_PATH\");\n\n\t\tconst { response } = await this.application.client.api.request(\n\t\t\tRoutes.apps.files.read(this.application.id),\n\t\t\t{ query: { path } },\n\t\t);\n\n\t\tif (!response) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn Buffer.from(response.data);\n\t}\n\n\t/**\n\t * Creates a new file\n\t *\n\t * @param file - The file content\n\t * @param fileName - The file name with extension\n\t * @param path - The absolute file path\n\t */\n\tasync create(file: string | Buffer, fileName: string, path = \"/\") {\n\t\tassertPathLike(file, \"CREATE_FILE\");\n\t\tassertString(fileName, \"CREATE_FILE_NAME\");\n\t\tassertString(path, \"CREATE_FILE_PATH\");\n\n\t\tif (typeof file === \"string\") {\n\t\t\tfile = await readFile(file);\n\t\t}\n\t\tpath = join(path, fileName).replaceAll(\"\\\\\", \"/\");\n\n\t\tconst { status } = await this.application.client.api.request(\n\t\t\tRoutes.apps.files.upsert(this.application.id),\n\t\t\t{\n\t\t\t\tmethod: \"PUT\",\n\t\t\t\tbody: { content: file.toString(\"utf8\"), path },\n\t\t\t},\n\t\t);\n\n\t\treturn status === \"success\";\n\t}\n\n\t/**\n\t * Edits an existing file (same as create)\n\t *\n\t * @param file - The file content\n\t * @param path - The absolute file path\n\t */\n\tasync edit(file: string | Buffer, path = \"/\") {\n\t\tassertPathLike(file, \"EDIT_FILE\");\n\t\tassertString(path, \"EDIT_FILE_PATH\");\n\n\t\treturn this.create(file, \"\", path);\n\t}\n\n\t/**\n\t * Moves or renames a file\n\t *\n\t * @param path - The current absolute file path\n\t * @param newPath - The new absolute file path\n\t */\n\tasync move(path: string, newPath: string) {\n\t\tassertString(path, \"MOVE_FILE_PATH\");\n\t\tassertString(newPath, \"MOVE_FILE_NEW_PATH\");\n\n\t\tconst { status } = await this.application.client.api.request(\n\t\t\tRoutes.apps.files.move(this.application.id),\n\t\t\t{ method: \"PATCH\", body: { path, to: newPath } },\n\t\t);\n\n\t\treturn status === \"success\";\n\t}\n\n\t/**\n\t * Deletes the specified file or directory\n\t *\n\t * @param path - The absolute file or directory path\n\t */\n\tasync delete(path: string) {\n\t\tassertString(path, \"DELETE_FILE_PATH\");\n\n\t\tconst { status } = await this.application.client.api.request(\n\t\t\tRoutes.apps.files.delete(this.application.id),\n\t\t\t{ method: \"DELETE\", body: { path } },\n\t\t);\n\n\t\treturn status === \"success\";\n\t}\n}\n","import { assertString } from \"@/assertions/literal\";\nimport { Routes } from \"@/lib/routes\";\nimport type { WebsiteApplication } from \"@/structures\";\n\nexport class NetworkModule {\n\tconstructor(public readonly application: WebsiteApplication) {}\n\n\t/**\n\t * Integrates your website with a custom domain\n\t * - Requires [Senior plan](https://squarecloud.app/plans) or higher\n\t *\n\t * @param custom - The custom domain you want to use (e.g. yoursite.com)\n\t */\n\tasync setCustomDomain(custom: string) {\n\t\tassertString(custom, \"CUSTOM_DOMAIN\");\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.network.custom(this.application.id),\n\t\t\t{ method: \"POST\", body: { custom } },\n\t\t);\n\n\t\treturn data.status === \"success\";\n\t}\n\n\t/**\n\t * Gets analytics for a custom domain\n\t * - Requires [Senior plan](https://squarecloud.app/plans) or higher\n\t * - Requires the application to have an integrated custom domain\n\t */\n\tasync analytics() {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.network.analytics(this.application.id),\n\t\t);\n\n\t\treturn data?.response;\n\t}\n\n\t/**\n\t * Get the DNS records for your custom domain.\n\t */\n\tasync dns() {\n\t\tconst data = await this.application.client.api.request(\n\t\t\tRoutes.apps.network.dns(this.application.id),\n\t\t);\n\n\t\treturn data?.response;\n\t}\n}\n","import { Routes } from \"@/lib/routes\";\nimport { User } from \"@/structures\";\nimport type { SquareCloudAPI } from \"..\";\n\nexport class UserModule {\n\tconstructor(public readonly client: SquareCloudAPI) {}\n\n\t/**\n\t * Gets the authenticated user information\n\t */\n\tasync get(): Promise<User> {\n\t\tconst { response } = await this.client.api.request(Routes.user());\n\t\tconst user = new User(this.client, response);\n\n\t\tthis.client.emit(\"userUpdate\", this.client.cache.user, user);\n\t\tthis.client.cache.set(\"user\", user);\n\n\t\treturn user;\n\t}\n}\n","import type { APIVersion } from \"@squarecloud/api-types/v2\";\n\nimport { SquareCloudAPIError } from \"@/structures\";\nimport type {\n\tAPIEndpoint,\n\tAPIRequestArgs,\n\tAPIRequestOptions,\n\tAPIResponse,\n} from \"@/types\";\n\nexport class APIService {\n\tpublic readonly baseUrl = \"https://api.squarecloud.app\";\n\tpublic readonly version: APIVersion<1 | 2> = \"v2\";\n\tpublic readonly sdkVersion: string = require(\"../../package.json\").version;\n\tpublic readonly userId: string;\n\n\tconstructor(protected readonly apiKey: string) {\n\t\tthis.userId = apiKey.split(\"-\")[0];\n\t}\n\n\tasync request<T extends APIEndpoint>(\n\t\t...[path, options]: APIRequestArgs<T>\n\t): Promise<APIResponse<T>> {\n\t\tconst { url, init } = this.parseRequestOptions(path, options);\n\n\t\tconst response = await fetch(url, init).catch((err) => {\n\t\t\tthrow new SquareCloudAPIError(err.code, err.message);\n\t\t});\n\n\t\tif (response.status === 413) {\n\t\t\tthrow new SquareCloudAPIError(\"PAYLOAD_TOO_LARGE\");\n\t\t}\n\n\t\tif (response.status === 429) {\n\t\t\tthrow new SquareCloudAPIError(\"RATE_LIMIT_EXCEEDED\", \"Try again later\");\n\t\t}\n\n\t\tif (response.status === 502 || response.status === 504) {\n\t\t\tthrow new SquareCloudAPIError(\"SERVER_UNAVAILABLE\", \"Try again later\");\n\t\t}\n\n\t\tconst data = await response.json().catch(() => {\n\t\t\tthrow new SquareCloudAPIError(\n\t\t\t\t\"CANNOT_PARSE_RESPONSE\",\n\t\t\t\t`Failed with status ${response.status}`,\n\t\t\t);\n\t\t});\n\n\t\tif (!data || data.status === \"error\" || !response.ok) {\n\t\t\tthrow new SquareCloudAPIError(data?.code || \"COMMON_ERROR\");\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tprivate parseRequestOptions(\n\t\tpath: string,\n\t\toptions?: APIRequestOptions<APIEndpoint>,\n\t) {\n\t\tconst init: RequestInit = options || {};\n\n\t\tinit.method = init.method || \"GET\";\n\t\tinit.headers = {\n\t\t\tAccept: \"application/json\",\n\t\t\t...(init.headers || {}),\n\t\t\tAuthorization: this.apiKey,\n\t\t\t\"User-Agent\": `squarecloud-sdk-js/${this.sdkVersion}`,\n\t\t};\n\n\t\tconst url = new URL(path, `${this.baseUrl}/${this.version}/`);\n\n\t\tif (\"query\" in init && init.query) {\n\t\t\tconst query = new URLSearchParams(init.query as Record<string, string>);\n\t\t\turl.search = query.toString();\n\t\t\tinit.query = undefined;\n\t\t}\n\n\t\tif (\"body\" in init && init.body && !(init.body instanceof FormData)) {\n\t\t\tinit.body = JSON.stringify(init.body);\n\t\t\tinit.headers = {\n\t\t\t\t...init.headers,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t};\n\t\t}\n\n\t\treturn { url, init };\n\t}\n}\n","import type { User } from \"@/structures\";\nimport { BaseCacheService } from \"./base\";\n\nexport interface GlobalCache {\n\treadonly user?: User;\n}\n\nexport class GlobalCacheService extends BaseCacheService<GlobalCache> {\n\tprotected cache: GlobalCache = {\n\t\tuser: undefined,\n\t};\n\n\tget user() {\n\t\treturn this.cache.user;\n\t}\n}\n","import type { APIApplication } from \"@squarecloud/api-types/v2\";\n\nimport type { SquareCloudAPI } from \"@/index\";\nimport { BaseApplication } from \"./base\";\nimport type { WebsiteApplication } from \"./website\";\n\n/**\n * Represents a Square Cloud application\n */\nexport class Application extends BaseApplication {\n\t/**\n\t * Represents a Square Cloud application\n\t *\n\t * @constructor\n\t * @param client - The client for this application\n\t * @param data - The data from this application\n\t */\n\tconstructor(\n\t\tpublic readonly client: SquareCloudAPI,\n\t\tdata: APIApplication,\n\t) {\n\t\tsuper(client, { ...data, lang: data.language });\n\t}\n\n\tisWebsite(): this is WebsiteApplication {\n\t\tconst domain = Reflect.get(this, \"domain\");\n\t\treturn Boolean(domain);\n\t}\n}\n","import type { APIWebsiteApplication } from \"@squarecloud/api-types/v2\";\n\nimport type { SquareCloudAPI } from \"@/index\";\nimport { NetworkModule } from \"@/modules\";\nimport { Application } from \"./application\";\n\n/**\n * Represents a Square Cloud application\n */\nexport class WebsiteApplication extends Application {\n\t/** The application default domain (e.g. example.squareweb.app) */\n\tpublic domain: string;\n\t/** The custom configured domain (e.g. yoursite.com) */\n\tpublic custom?: string;\n\n\t/** Network module for this application */\n\tpublic readonly network = new NetworkModule(this);\n\n\t/**\n\t * Represents a Square Cloud application\n\t *\n\t * @constructor\n\t * @param client - The client for this application\n\t * @param data - The data from this application\n\t */\n\tconstructor(\n\t\tpublic readonly client: SquareCloudAPI,\n\t\tdata: APIWebsiteApplication,\n\t) {\n\t\tsuper(client, data);\n\n\t\tconst { domain, custom } = data;\n\n\t\tthis.domain = domain;\n\t\tthis.custom = custom || undefined;\n\t}\n}\n","/**\n * @internal\n */\nexport interface CollectionConstructor {\n\tnew (): Collection<unknown, unknown>;\n\tnew <K, V>(entries?: readonly (readonly [K, V])[] | null): Collection<K, V>;\n\tnew <K, V>(iterable: Iterable<readonly [K, V]>): Collection<K, V>;\n\treadonly prototype: Collection<unknown, unknown>;\n\treadonly [Symbol.species]: CollectionConstructor;\n}\n\n/**\n * Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself\n *\n * @internal\n */\nexport interface Collection<K, V> extends Map<K, V> {\n\tconstructor: CollectionConstructor;\n}\n\n/**\n * A Map with additional utility methods. This is used throughout \\@squarecloud/api rather than Arrays for anything that has\n * an ID, for significantly improved performance and ease-of-use.\n *\n * @typeParam K - The key type this collection holds\n * @typeParam V - The value type this collection holds\n */\n// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: Needed to merge the constructor and the instance methods\nexport class Collection<K, V> extends Map<K, V> {\n\t/**\n\t * Obtains the first value(s) in this collection.\n\t *\n\t * @param amount - Amount of values to obtain from the beginning\n\t * @returns A single value if no amount is provided or an array of values, starting from the end if amount is negative\n\t */\n\tpublic first(): V | undefined;\n\tpublic first(amount: number): V[];\n\tpublic first(amount?: number): V | V[] | undefined {\n\t\tif (typeof amount === \"undefined\") {\n\t\t\treturn this.values().next().value;\n\t\t}\n\n\t\tif (amount < 0) {\n\t\t\treturn this.last(amount * -1);\n\t\t}\n\n\t\tamount = Math.min(this.size, amount);\n\t\treturn Array.from({ length: amount }, (): V => this.values().next().value);\n\t}\n\n\t/**\n\t * Obtains the last value(s) in this collection.\n\t *\n\t * @param amount - Amount of values to obtain from the end\n\t * @returns A single value if no amount is provided or an array of values, starting from the start if\n\t * amount is negative\n\t */\n\tpublic last(): V | undefined;\n\tpublic last(amount: number): V[];\n\tpublic last(amount?: number): V | V[] | undefined {\n\t\tconst arr = [...this.values()];\n\t\tif (typeof amount === \"undefined\") return arr[arr.length - 1];\n\t\tif (amount < 0) return this.first(amount * -1);\n\t\tif (!amount) return [];\n\t\treturn arr.slice(-amount);\n\t}\n\n\t/**\n\t * Identical to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse Array.reverse()}\n\t * but returns a Collection instead of an Array.\n\t */\n\tpublic reverse() {\n\t\tconst entries = [...this.entries()].reverse();\n\t\tthis.clear();\n\n\t\tfor (const [key, value] of entries) {\n\t\t\tthis.set(key, value);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Searches for a single item where the given function returns a truthy value. This behaves like\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find Array.find()}.\n\t *\n\t * @param fn - The function to test with (should return boolean)\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection.find(user => user.username === 'Bob');\n\t * ```\n\t */\n\tpublic find<V2 extends V>(\n\t\tfn: (value: V, key: K, collection: this) => value is V2,\n\t): V2 | undefined;\n\n\tpublic find(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t): V | undefined;\n\n\tpublic find<This, V2 extends V>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => value is V2,\n\t\tthisArg: This,\n\t): V2 | undefined;\n\n\tpublic find<This>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => unknown,\n\t\tthisArg: This,\n\t): V | undefined;\n\n\tpublic find(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t\tthisArg?: unknown,\n\t): V | undefined {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tif (typeof thisArg !== \"undefined\") {\n\t\t\tfn = fn.bind(thisArg);\n\t\t}\n\n\t\tfor (const [key, val] of this) {\n\t\t\tif (fn(val, key, this)) return val;\n\t\t}\n\t}\n\n\t/**\n\t * Identical to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter Array.filter()},\n\t * but returns a Collection instead of an Array.\n\t *\n\t * @param fn - The function to test with (should return boolean)\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection.filter(user => user.username === 'Bob');\n\t * ```\n\t */\n\tpublic filter<K2 extends K>(\n\t\tfn: (value: V, key: K, collection: this) => key is K2,\n\t): Collection<K2, V>;\n\n\tpublic filter<V2 extends V>(\n\t\tfn: (value: V, key: K, collection: this) => value is V2,\n\t): Collection<K, V2>;\n\n\tpublic filter(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t): Collection<K, V>;\n\n\tpublic filter<This, K2 extends K>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => key is K2,\n\t\tthisArg: This,\n\t): Collection<K2, V>;\n\n\tpublic filter<This, V2 extends V>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => value is V2,\n\t\tthisArg: This,\n\t): Collection<K, V2>;\n\n\tpublic filter<This>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => unknown,\n\t\tthisArg: This,\n\t): Collection<K, V>;\n\n\tpublic filter(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t\tthisArg?: unknown,\n\t): Collection<K, V> {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tif (typeof thisArg !== \"undefined\") {\n\t\t\tfn = fn.bind(thisArg);\n\t\t}\n\n\t\tconst results = new this.constructor[Symbol.species]<K, V>();\n\t\tfor (const [key, val] of this) {\n\t\t\tif (fn(val, key, this)) results.set(key, val);\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t/**\n\t * Maps each item to another value into an array. Identical in behavior to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map Array.map()}.\n\t *\n\t * @param fn - Function that produces an element of the new array, taking three arguments\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection.map(user => user.name);\n\t * ```\n\t */\n\tpublic map<T>(fn: (value: V, key: K, collection: this) => T): T[];\n\tpublic map<This, T>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => T,\n\t\tthisArg: This,\n\t): T[];\n\n\tpublic map<T>(\n\t\tfn: (value: V, key: K, collection: this) => T,\n\t\tthisArg?: unknown,\n\t): T[] {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tif (typeof thisArg !== \"undefined\") {\n\t\t\tfn = fn.bind(thisArg);\n\t\t}\n\n\t\treturn Array.from({ length: this.size }, (): T => {\n\t\t\tconst [key, value] = this.entries().next().value;\n\t\t\treturn fn(value, key, this);\n\t\t});\n\t}\n\n\t/**\n\t * Checks if there exists an item that passes a test. Identical in behavior to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some Array.some()}.\n\t *\n\t * @param fn - Function used to test (should return a boolean)\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection.some(user => user.discriminator === '0000');\n\t * ```\n\t */\n\tpublic some(fn: (value: V, key: K, collection: this) => unknown): boolean;\n\tpublic some<T>(\n\t\tfn: (this: T, value: V, key: K, collection: this) => unknown,\n\t\tthisArg: T,\n\t): boolean;\n\n\tpublic some(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t\tthisArg?: unknown,\n\t): boolean {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tif (typeof thisArg !== \"undefined\") {\n\t\t\tfn = fn.bind(thisArg);\n\t\t}\n\n\t\tfor (const [key, val] of this) {\n\t\t\tif (fn(val, key, this)) return true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Checks if all items passes a test. Identical in behavior to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every Array.every()}.\n\t *\n\t * @param fn - Function used to test (should return a boolean)\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection.every(user => !user.bot);\n\t * ```\n\t */\n\tpublic every<K2 extends K>(\n\t\tfn: (value: V, key: K, collection: this) => key is K2,\n\t): this is Collection<K2, V>;\n\n\tpublic every<V2 extends V>(\n\t\tfn: (value: V, key: K, collection: this) => value is V2,\n\t): this is Collection<K, V2>;\n\n\tpublic every(fn: (value: V, key: K, collection: this) => unknown): boolean;\n\tpublic every<This, K2 extends K>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => key is K2,\n\t\tthisArg: This,\n\t): this is Collection<K2, V>;\n\n\tpublic every<This, V2 extends V>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => value is V2,\n\t\tthisArg: This,\n\t): this is Collection<K, V2>;\n\n\tpublic every<This>(\n\t\tfn: (this: This, value: V, key: K, collection: this) => unknown,\n\t\tthisArg: This,\n\t): boolean;\n\n\tpublic every(\n\t\tfn: (value: V, key: K, collection: this) => unknown,\n\t\tthisArg?: unknown,\n\t): boolean {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tif (typeof thisArg !== \"undefined\") {\n\t\t\tfn = fn.bind(thisArg);\n\t\t}\n\n\t\tfor (const [key, val] of this) {\n\t\t\tif (!fn(val, key, this)) return false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Applies a function to produce a single value. Identical in behavior to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce Array.reduce()}.\n\t *\n\t * @param fn - Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`,\n\t * and `collection`\n\t * @param initialValue - Starting value for the accumulator\n\t * @example\n\t * ```ts\n\t * collection.reduce((acc, guild) => acc + guild.memberCount, 0);\n\t * ```\n\t */\n\tpublic reduce<T>(\n\t\tfn: (accumulator: T, value: V, key: K, collection: this) => T,\n\t\tinitialValue?: T,\n\t): T {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\t\tlet accumulator!: T;\n\n\t\tif (typeof initialValue !== \"undefined\") {\n\t\t\taccumulator = initialValue;\n\t\t\tfor (const [key, val] of this) {\n\t\t\t\taccumulator = fn(accumulator, val, key, this);\n\t\t\t}\n\t\t\treturn accumulator;\n\t\t}\n\n\t\tlet first = true;\n\t\tfor (const [key, val] of this) {\n\t\t\tif (first) {\n\t\t\t\taccumulator = val as unknown as T;\n\t\t\t\tfirst = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\taccumulator = fn(accumulator, val, key, this);\n\t\t}\n\n\t\tif (first) {\n\t\t\tthrow new TypeError(\"Reduce of empty collection with no initial value\");\n\t\t}\n\n\t\treturn accumulator;\n\t}\n\n\t/**\n\t * Identical to\n\t * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach Map.forEach()},\n\t * but returns the collection instead of undefined.\n\t *\n\t * @param fn - Function to execute for each element\n\t * @param thisArg - Value to use as `this` when executing function\n\t * @example\n\t * ```ts\n\t * collection\n\t * .each(user => console.log(user.username))\n\t * .filter(user => user.bot)\n\t * .each(user => console.log(user.username));\n\t * ```\n\t */\n\tpublic each(fn: (value: V, key: K, collection: this) => void): this;\n\tpublic each<T>(\n\t\tfn: (this: T, value: V, key: K, collection: this) => void,\n\t\tthisArg: T,\n\t): this;\n\n\tpublic each(\n\t\tfn: (value: V, key: K, collection: this) => void,\n\t\tthisArg?: unknown,\n\t): this {\n\t\tif (typeof fn !== \"function\") {\n\t\t\tthrow new TypeError(`${fn} is not a function`);\n\t\t}\n\n\t\tthis.forEach(fn as (value: V, key: K, map: Map<K, V>) => void, thisArg);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Creates an identical shallow copy of this collection.\n\t *\n\t * @example\n\t * ```ts\n\t * const newColl = someColl.clone();\n\t * ```\n\t */\n\tpublic clone(): Collection<K, V> {\n\t\treturn new this.constructor[Symbol.species](this);\n\t}\n\n\tpublic toJSON() {\n\t\treturn [...this.values()];\n\t}\n}\n","export class SquareCloudAPIError extends TypeError {\n\tconstructor(\n\t\tcode: string,\n\t\tmessage?: string,\n\t\toptions?: { stack?: string; cause?: unknown },\n\t) {\n\t\tsuper(code);\n\n\t\tthis.name = \"SquareCloudAPIError\";\n\n\t\tthis.message =\n\t\t\t(code\n\t\t\t\t?.replaceAll(\"_\", \" \")\n\t\t\t\t.toLowerCase()\n\t\t\t\t.replace(/(^|\\s)\\S/g, (L) => L.toUpperCase()) || \"UNKNOWN_CODE\") +\n\t\t\t(message ? `: ${message}` : \"\");\n\n\t\tif (options?.stack) {\n\t\t\tthis.stack = options.stack;\n\t\t}\n\n\t\tif (options?.cause) {\n\t\t\tthis.cause = options.cause;\n\t\t}\n\t}\n}\n","import type {\n\tAPIApplicationStatus,\n\tAPIApplicationStatusAll,\n\tApplicationStatus as ApplicationStatusType,\n} from \"@squarecloud/api-types/v2\";\n\nimport { Routes } from \"@/lib/routes\";\nimport type { ApplicationStatusUsage } from \"@/types/application\";\nimport type { SquareCloudAPI } from \"..\";\n\n/**\n * Represents an application status fetched from status all endpoint\n */\nexport class SimpleApplicationStatus<R extends boolean = boolean> {\n\t/** The application's ID this status came from */\n\tpublic readonly applicationId: string;\n\t/** Usage statuses for this application */\n\tpublic usage: R extends true\n\t\t? Pick<ApplicationStatusUsage, \"cpu\" | \"ram\">\n\t\t: undefined;\n\t/** Whether the application is running or not */\n\tpublic running: R;\n\n\t/**\n\t * Represents an application status fetched from status all endpoint\n\t *\n\t * @constructor\n\t * @param client - The client for this status\n\t * @param data - The data from this status\n\t */\n\tconstructor(\n\t\tpublic readonly client: SquareCloudAPI,\n\t\tdata: APIApplicationStatusAll,\n\t) {\n\t\tconst { id, running } = data;\n\n\t\tthis.applicationId = id;\n\t\tthis.running = running as R;\n\n\t\tif (running) {\n\t\t\tconst { cpu, ram } = data;\n\n\t\t\tthis.usage = { cpu, ram } as R extends true\n\t\t\t\t? Pick<ApplicationStatusUsage, \"cpu\" | \"ram\">\n\t\t\t\t: undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Fetches the full application status\n\t */\n\tasync fetch() {\n\t\tconst data = await this.client.api.request(\n\t\t\tRoutes.apps.status(this.applicationId),\n\t\t);\n\n\t\treturn new ApplicationStatus(\n\t\t\tthis.client,\n\t\t\tdata.response,\n\t\t\tthis.applicationId,\n\t\t);\n\t}\n}\n\n/**\n * Represents an application status\n */\nexport class ApplicationStatus {\n\t/** The application's ID this status came from */\n\tpublic readonly applicationId: string;\n\t/** Usage statuses for this application */\n\tpublic usage: ApplicationStatusUsage;\n\t/** Whether the application is running or not */\n\tpublic running: boolean;\n\t/**\n\t * The status of the application\n\t *\n\t * - 'exited' (stopped)\n\t * - 'created' (being created)\n\t * - 'running'\n\t * - 'starting'\n\t * - 'restarting'\n\t * - 'deleting'\n\t */\n\tpublic status: ApplicationStatusType;\n\t/** For how long the app is running in millisseconds */\n\tpublic uptimeTimestamp?: number;\n\t/** For how long the app is running */\n\tpublic uptime?: Date;\n\n\t/**\n\t * Represents an application status\n\t *\n\t * @constructor\n\t * @param client - The client for this status\n\t * @param data - The data from this status\n\t * @param applicationId - The application ID this status came from\n\t */\n\tconstructor(\n\t\tpublic readonly client: SquareCloudAPI,\n\t\tdata: APIApplicationStatus,\n\t\tapplicationId: string,\n\t) {\n\t\tconst { cpu, ram, network, storage, running, status, uptime } = data;\n\n\t\tthis.applicationId = applicationId;\n\t\tthis.usage = { cpu, ram, network, storage };\n\t\tthis.running = running;\n\t\tthis.status = status;\n\t\tthis.uptime = uptime ? new Date(uptime) : undefined;\n\t\tthis.uptimeTimestamp = uptime ?? undefined;\n\t}\n}\n","import type { APIUserInfo } from \"@squarecloud/api-types/v2\";\n\nimport type { UserPlan } from \"@/types/user\";\nimport type { SquareCloudAPI } from \"..\";\nimport { BaseApplication } from \"./application/base\";\nimport { Collection } from \"./collection\";\n\n/**\n * Represents a Square Cloud user\n */\nexport class User {\n\t/** The user's id */\n\tpublic readonly id: string;\n\t/** The user's disp