├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── dependabot.yml └── workflows │ └── workflow.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package.json ├── src ├── application │ ├── index.ts │ ├── interfaces │ │ ├── Allocation.ts │ │ ├── Database.ts │ │ ├── Egg.ts │ │ ├── Location.ts │ │ ├── Nest.ts │ │ ├── Node.ts │ │ ├── Server.ts │ │ └── User.ts │ └── methods │ │ ├── allocation.ts │ │ ├── database.ts │ │ ├── location.ts │ │ ├── nest.ts │ │ ├── node.ts │ │ ├── server.ts │ │ └── user.ts ├── client │ ├── Websocket.ts │ ├── index.ts │ ├── interfaces │ │ ├── Allocation.ts │ │ ├── ApiKey.ts │ │ ├── Backups.ts │ │ ├── Database.ts │ │ ├── Permissions.ts │ │ ├── Schedule.ts │ │ ├── Server.ts │ │ ├── ServerFile.ts │ │ ├── ServerResources.ts │ │ ├── SubUser.ts │ │ ├── User.ts │ │ └── WebsocketAuthData.ts │ └── methods │ │ ├── account.ts │ │ ├── backups.ts │ │ ├── console.ts │ │ ├── database.ts │ │ ├── file.ts │ │ ├── network.ts │ │ ├── schedule.ts │ │ ├── server.ts │ │ ├── settings.ts │ │ └── subUser.ts ├── index.ts └── modules │ ├── Error.ts │ ├── Functions.ts │ ├── Request.ts │ └── Socket.ts ├── tsconfig.json ├── tsdoc.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const prettierOptions = JSON.parse( 5 | fs.readFileSync(path.resolve(__dirname, '.prettierrc'), 'utf8') 6 | ); 7 | 8 | /** @type {import("@types/eslint").Linter.Config} */ 9 | module.exports = { 10 | env: { 11 | es2022: true, 12 | node: true 13 | }, 14 | extends: [ 15 | 'eslint:recommended', 16 | 'plugin:@typescript-eslint/recommended', 17 | 'plugin:prettier/recommended' 18 | ], 19 | parser: '@typescript-eslint/parser', 20 | parserOptions: { 21 | ecmaVersion: 'latest', 22 | sourceType: 'module' 23 | }, 24 | plugins: ['@typescript-eslint', 'prettier', 'eslint-plugin-tsdoc'], 25 | ignorePatterns: ['dist', '.eslintrc.js'], 26 | rules: { 27 | 'prettier/prettier': ['error', prettierOptions], 28 | 'tsdoc/syntax': 'warn' 29 | }, 30 | overrides: [ 31 | { 32 | files: ['**/*.ts'], 33 | rules: { 'prettier/prettier': ['error', prettierOptions] } 34 | } 35 | ] 36 | }; 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'npm' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | allow: 8 | - dependency-type: 'production' # Only allow to update production deps 9 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: 18 19 | - name: Install dependencies 20 | uses: bahmutov/npm-install@v1 21 | - name: BuildDocs 22 | if: github.ref == 'refs/heads/master' 23 | run: yarn docs:build 24 | - name: Deploy Docs 25 | if: github.ref == 'refs/heads/master' 26 | uses: JamesIves/github-pages-deploy-action@4.1.7 27 | with: 28 | branch: gh-pages 29 | folder: docs 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | docs 4 | test.ts -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test.js 2 | test.d.ts 3 | .eslintrc.js 4 | .prettierignore 5 | .prettierrc 6 | tsdoc.json -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | docs 3 | node_modules 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 2, 4 | "quoteProps": "consistent", 5 | "arrowParens": "always", 6 | "trailingComma": "none" 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at linas.alexx@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Feel free to contribute to the project by cloning the repository and sending a pull request. 4 | 5 | As always, make sure to state the changes in the title and comment them in description of the PR. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Linux123123 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSPteroAPI 2 | 3 | [![GitHub](https://img.shields.io/github/license/linux123123/jspteroapi)](https://github.com/Linux123123/JSPteroAPI/blob/main/LICENSE) 4 | ![Node.js Package](https://github.com/Linux123123/JSPteroAPI/workflows/Node.js%20Package/badge.svg) 5 | [![GitHub issues](https://img.shields.io/github/issues/linux123123/jspteroapi)](https://github.com/Linux123123/JSPteroAPI/issues) 6 | [![GitHub pull requests](https://img.shields.io/github/issues-pr/linux123123/jspteroapi)](https://github.com/Linux123123/JSPteroAPI/pulls) 7 | 8 | [![NPM](https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white)](https://npmjs.com/package/jspteroapi) 9 | 10 |

A simple Pterodactyl API library using undici (written in typescript)

11 | 12 | Uses only 2 dependencies: 13 | 17 | 18 | # To install: 19 | 20 |
Install from the command line:
21 | 22 | **Npm** 23 | 24 | `npm install jspteroapi` 25 | 26 | **Yarn** 27 | 28 | `yarn add jspteroapi` 29 | 30 | Then include it in your application: 31 | 32 | ```javascript 33 | const node = require('jspteroapi'); 34 | const application = new node.Application('HOST', 'TOKEN'); // for application API 35 | const client = new node.Client('HOST', 'TOKEN'); // for Client API 36 | ``` 37 | 38 | # How to use 39 | 40 | You can use any application funtion you want: 41 | 42 | ```javascript 43 | application.function(parameters).then((response) => { 44 | // response 45 | }); 46 | ``` 47 | 48 | or using async / await 49 | 50 | ```javascript 51 | const res = await application.function(parameters); 52 | ``` 53 | 54 | # Documentation 55 | 56 |

Application

57 |

Client

58 | 59 | # Versions 60 | 61 | **How versions work:** 62 | 63 | - Panel major version 64 | - The second number is the function release. 65 | - The third number is the bug fix release. 66 | 67 | # Disclaimer 68 | 69 | I am not responsible for any damages that you cause to your servers/nodes by using **this API**. 70 | 71 | **Remember: This API can potentially be dangerous with the ability to Delete Servers/Nodes at an instant!** 72 | 73 | # Contributors 74 | 75 | Created and maintained by [Linux123123](https://github.com/linux123123) 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jspteroapi", 3 | "version": "1.11.4", 4 | "description": "A pterodactyl v1 api using undici", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "engines": { 8 | "node": ">=16.8" 9 | }, 10 | "engineStrict": true, 11 | "scripts": { 12 | "dev": "tsc-watch --onCompilationComplete \"node --use-openssl-ca dist/test.js\"", 13 | "build": "rimraf dist/* && tsc", 14 | "lint": "eslint \"src/**\"", 15 | "docs:build": "typedoc --categorizeByGroup --defaultCategory Types --excludeInternal --name JSPteroAPI && echo 'User-agent: *\nDisallow: /' > docs/robots.txt", 16 | "release": "yarn build && np" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/Linux123123/JSPteroAPI.git" 21 | }, 22 | "keywords": [ 23 | "Pterodactyl", 24 | "API", 25 | "undici", 26 | "node-js", 27 | "js", 28 | "ptero-api", 29 | "ptero", 30 | "pterodactyl-api", 31 | "API client" 32 | ], 33 | "author": "Linux123123", 34 | "license": "MIT", 35 | "files": [ 36 | "dist/*" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/Linux123123/JSPteroAPI/issues" 40 | }, 41 | "homepage": "https://jspteroapi.linux123123.com", 42 | "dependencies": { 43 | "undici": "^6.6.2", 44 | "ws": "^8.12.0" 45 | }, 46 | "devDependencies": { 47 | "@microsoft/tsdoc-config": "^0.16.2", 48 | "@types/node": "^18.13.0", 49 | "@types/ws": "^8.5.4", 50 | "@typescript-eslint/eslint-plugin": "^5.51.0", 51 | "@typescript-eslint/parser": "^5.51.0", 52 | "eslint": "^8.33.0", 53 | "eslint-config-prettier": "^8.6.0", 54 | "eslint-plugin-prettier": "^4.2.1", 55 | "eslint-plugin-tsdoc": "^0.2.17", 56 | "prettier": "^2.8.4", 57 | "rimraf": "^4.1.2", 58 | "tsc-watch": "^6.0.0", 59 | "typedoc": "^0.23.24", 60 | "typescript": "^4.9.5" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/application/index.ts: -------------------------------------------------------------------------------- 1 | import { Request } from '../modules/Request'; 2 | import { allocationMethods } from './methods/allocation'; 3 | import { databaseMethods } from './methods/database'; 4 | import { nestMethods } from './methods/nest'; 5 | import { nodeMethods } from './methods/node'; 6 | import { serverMethods } from './methods/server'; 7 | import { userMethods } from './methods/user'; 8 | import { locationMethods } from './methods/location'; 9 | import { JSPteroAPIError } from '../modules/Error'; 10 | class Application { 11 | /** 12 | * @param host - Panels address 13 | * @param key - Api key to use 14 | * @param fast - Fast login (No credential check) 15 | */ 16 | public constructor( 17 | private host: string, 18 | private key: string, 19 | private errorHandler = (error: JSPteroAPIError): void => { 20 | throw error; 21 | }, 22 | fast = false 23 | ) { 24 | host = host.trim(); 25 | if (host.endsWith('/')) host = host.slice(0, -1); 26 | this.host = host; 27 | this.request = new Request(this.host, this.key, this.errorHandler).request; 28 | const servermethods = new serverMethods(this); 29 | this.getAllServers = servermethods.getAllServers; 30 | this.getServerInfo = servermethods.getServerInfo; 31 | this.createServer = servermethods.createServer; 32 | this.deleteServer = servermethods.deleteServer; 33 | this.suspendServer = servermethods.suspendServer; 34 | this.unSuspendServer = servermethods.unSuspendServer; 35 | this.reinstallServer = servermethods.reinstallServer; 36 | this.getServerInfoByExtId = servermethods.getServerInfoByExtId; 37 | this.editServerDetails = servermethods.editServerDetails; 38 | this.editServerBuild = servermethods.editServerBuild; 39 | this.editServerStartup = servermethods.editServerStartup; 40 | const nestmethods = new nestMethods(this); 41 | this.getAllNests = nestmethods.getAllNests; 42 | this.getNestInfo = nestmethods.getNestInfo; 43 | this.getAllNestEggs = nestmethods.getAllNestEggs; 44 | this.getEggInfo = nestmethods.getEggInfo; 45 | const databasemethods = new databaseMethods(this); 46 | this.getServersDatabases = databasemethods.getServersDatabases; 47 | this.getServersDatabaseInfo = databasemethods.getServersDatabaseInfo; 48 | this.createDatabase = databasemethods.createDatabase; 49 | this.resetDatabasePassword = databasemethods.resetDatabasePassword; 50 | this.deleteDatabase = databasemethods.deleteDatabase; 51 | const usermethods = new userMethods(this); 52 | this.getAllUsers = usermethods.getAllUsers; 53 | this.getUserInfo = usermethods.getUserInfo; 54 | this.createUser = usermethods.createUser; 55 | this.editUser = usermethods.editUser; 56 | this.deleteUser = usermethods.deleteUser; 57 | const nodemethods = new nodeMethods(this); 58 | this.getAllNodes = nodemethods.getAllNodes; 59 | this.getNodeInfo = nodemethods.getNodeInfo; 60 | this.getNodeConfig = nodemethods.getNodeConfig; 61 | this.createNode = nodemethods.createNode; 62 | this.editNode = nodemethods.editNode; 63 | this.deleteNode = nodemethods.deleteNode; 64 | const allocationmethods = new allocationMethods(this); 65 | this.getAllAllocations = allocationmethods.getAllAllocations; 66 | this.createAllocation = allocationmethods.createAllocation; 67 | this.deleteAllocation = allocationmethods.deleteAllocation; 68 | const locationmethods = new locationMethods(this); 69 | this.getAllLocations = locationmethods.getAllLocations; 70 | this.getLocationInfo = locationmethods.getLocationInfo; 71 | this.createLocation = locationmethods.createLocation; 72 | this.editLocation = locationmethods.editLocation; 73 | this.deleteLocation = locationmethods.deleteLocation; 74 | 75 | if (!fast) this.testAPI(); 76 | } 77 | /** 78 | * @param throwError - Whether to throw an error or return bool 79 | * @remarks Will not work if using custom error handler. 80 | */ 81 | public testAPI = async (throwError = true): Promise => { 82 | try { 83 | await this.getAllServers(); 84 | return true; 85 | } catch (e) { 86 | if (e instanceof JSPteroAPIError) { 87 | if (throwError) { 88 | if (e.HTML_STATUS === 403) e.ERRORS = ['Invalid Application API key']; 89 | throw e; 90 | } 91 | return false; 92 | } else { 93 | if (throwError) throw e; 94 | return false; 95 | } 96 | } 97 | }; 98 | 99 | /** 100 | @internal 101 | */ 102 | public request; 103 | 104 | // GET 105 | public getAllServers; 106 | public getAllNodes; 107 | public getAllUsers; 108 | public getUserInfo; 109 | public getNodeInfo; 110 | public getServerInfo; 111 | public getAllNests; 112 | public getNestInfo; 113 | public getAllNestEggs; 114 | public getEggInfo; 115 | public getServerInfoByExtId; 116 | public getServersDatabases; 117 | public getServersDatabaseInfo; 118 | public getNodeConfig; 119 | public getAllAllocations; 120 | public getAllLocations; 121 | public getLocationInfo; 122 | // POST 123 | public createUser; 124 | public createServer; 125 | public createNode; 126 | public createDatabase; 127 | public suspendServer; 128 | public unSuspendServer; 129 | public reinstallServer; 130 | public resetDatabasePassword; 131 | public createAllocation; 132 | public createLocation; 133 | // PATCH 134 | public editUser; 135 | public editServerDetails; 136 | public editServerBuild; 137 | public editServerStartup; 138 | public editNode; 139 | public editLocation; 140 | // DELETE 141 | public deleteUser; 142 | public deleteNode; 143 | public deleteServer; 144 | public deleteDatabase; 145 | public deleteAllocation; 146 | public deleteLocation; 147 | } 148 | 149 | export { Application }; 150 | -------------------------------------------------------------------------------- /src/application/interfaces/Allocation.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationAllocation */ 2 | import { Node } from './Node'; 3 | import { Server } from './Server'; 4 | 5 | export interface AllocationIncludeInput { 6 | node?: boolean; 7 | server?: boolean; 8 | } 9 | 10 | export interface AllocationFilterInput { 11 | filter: string; 12 | filterBy: 'ip' | 'port' | 'ip_alias' | 'server_id'; 13 | } 14 | 15 | export interface AllocationRelationships { 16 | server?: Server; 17 | node?: Node; 18 | } 19 | 20 | export interface AllocationAttributes { 21 | id: number; 22 | ip: string; 23 | alias: string | null; 24 | port: number; 25 | notes: string | null; 26 | assigned: boolean; 27 | relationships?: AllocationRelationships; 28 | } 29 | 30 | export interface Allocation { 31 | onject: string; 32 | attributes: AllocationAttributes; 33 | } 34 | 35 | export interface Allocations { 36 | object: string; 37 | data: Allocation[]; 38 | meta: { 39 | pagination: { 40 | total: number; 41 | count: number; 42 | per_page: number; 43 | current_page: number; 44 | total_pages: number; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/application/interfaces/Database.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationDatabase */ 2 | export interface DatabaseIncludeInput { 3 | password?: boolean; 4 | host?: boolean; 5 | } 6 | 7 | export interface DatabasePasswordAttributes { 8 | password: string; 9 | } 10 | export interface DatabasePassword { 11 | object: string; 12 | attributes: DatabasePasswordAttributes; 13 | } 14 | 15 | export interface DatabaseHostAttributes { 16 | id: number; 17 | name: string; 18 | host: string; 19 | port: number; 20 | username: string; 21 | node: number; 22 | created_at: string; 23 | updated_at: string; 24 | } 25 | 26 | export interface DatabaseHost { 27 | object: string; 28 | attributes: DatabaseHostAttributes; 29 | } 30 | 31 | export interface DatabaseRelationships { 32 | password?: DatabasePassword; 33 | host?: DatabaseHost; 34 | } 35 | export interface DatabaseAttributes { 36 | id: number; 37 | server: number; 38 | host: number; 39 | database: string; 40 | username: string; 41 | remote: string; 42 | max_connections: null | number; 43 | created_at: string; 44 | updated_at: string; 45 | relationships?: DatabaseRelationships; 46 | } 47 | 48 | export interface Database { 49 | object: string; 50 | attributes: DatabaseAttributes; 51 | } 52 | -------------------------------------------------------------------------------- /src/application/interfaces/Egg.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationEgg*/ 2 | import { Nest } from './Nest'; 3 | import { Server } from './Server'; 4 | 5 | export interface EggConfig { 6 | files: unknown[]; 7 | startup: Record; 8 | stop: string; 9 | logs: unknown[]; 10 | file_denylist: string[]; 11 | extends: null | unknown; 12 | } 13 | 14 | export interface EggScript { 15 | privileged: boolean; 16 | install: string; 17 | entry: string; 18 | container: string; 19 | extends: null; 20 | } 21 | 22 | export interface EggVariableDataAttributes { 23 | id: number; 24 | egg_id: number; 25 | name: string; 26 | description: string; 27 | env_variable: string; 28 | default_value: string; 29 | user_viewable: boolean; 30 | user_editable: boolean; 31 | rules: string; 32 | created_at: string; 33 | updated_at: string; 34 | } 35 | 36 | export interface EggVariableData { 37 | object: string; 38 | attributes: EggVariableDataAttributes; 39 | } 40 | 41 | export interface EggVariables { 42 | object: string; 43 | data: EggVariableData[]; 44 | } 45 | 46 | export interface EggServers { 47 | object: string; 48 | data: Server[]; 49 | } 50 | 51 | export interface EggRelationships { 52 | nest?: Nest; 53 | servers?: EggServers; 54 | variables?: EggVariables; 55 | } 56 | 57 | export interface EggAttributes { 58 | id: number; 59 | uuid: string; 60 | name: string; 61 | nest: number; 62 | author: string; 63 | description: string; 64 | docker_image: string; 65 | docker_images: Record; 66 | config: EggConfig; 67 | startup: string; 68 | script: EggScript; 69 | created_at: '2021-01-27T13:46:16+00:00'; 70 | updated_at: '2021-01-27T13:46:16+00:00'; 71 | relationships?: EggRelationships; 72 | } 73 | 74 | export interface Egg { 75 | object: string; 76 | attributes: EggAttributes; 77 | } 78 | -------------------------------------------------------------------------------- /src/application/interfaces/Location.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationLocation */ 2 | 3 | import { Node } from './Node'; 4 | import { Server } from './Server'; 5 | 6 | export interface LocationIncludeInput { 7 | nodes?: boolean; 8 | servers?: boolean; 9 | } 10 | 11 | export interface LocationFilterInput { 12 | filter: string; 13 | filterBy: 'short' | 'long'; 14 | } 15 | 16 | export interface LocationNodes { 17 | object: string; 18 | data: Node[]; 19 | } 20 | 21 | export interface LocationServers { 22 | object: string; 23 | data: Server[]; 24 | } 25 | 26 | export interface LocationRelationships { 27 | nodes?: LocationNodes; 28 | servers?: LocationServers; 29 | } 30 | 31 | export interface LocationAttributes { 32 | id: number; 33 | short: string; 34 | long: string; 35 | updated_at: string; 36 | created_at: string; 37 | relationships?: LocationRelationships; 38 | } 39 | 40 | export interface Location { 41 | object: string; 42 | attributes: LocationAttributes; 43 | } 44 | 45 | export interface Locations { 46 | object: string; 47 | data: Location[]; 48 | meta: { 49 | pagination: { 50 | total: number; 51 | count: number; 52 | per_page: number; 53 | current_page: number; 54 | total_pages: number; 55 | }; 56 | }; 57 | } 58 | 59 | export interface EditLocationOptions { 60 | /** The short name */ 61 | shortName?: string; 62 | /** The description */ 63 | description?: string; 64 | /** Include information about locations relationships */ 65 | options?: LocationIncludeInput; 66 | } 67 | -------------------------------------------------------------------------------- /src/application/interfaces/Nest.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationNest */ 2 | import { Egg } from './Egg'; 3 | import { Server } from './Server'; 4 | 5 | export interface NestIncludeInput { 6 | eggs?: boolean; 7 | servers?: boolean; 8 | } 9 | 10 | export interface EggIncludeInput { 11 | nest?: boolean; 12 | servers?: boolean; 13 | variables?: boolean; 14 | } 15 | 16 | export interface NestServers { 17 | object: string; 18 | data: Server[]; 19 | } 20 | 21 | export interface NestEggs { 22 | object: string; 23 | data: Egg[]; 24 | } 25 | 26 | export interface NestRelationships { 27 | eggs?: NestEggs; 28 | servers?: NestServers; 29 | } 30 | 31 | export interface NestAttributes { 32 | id: number; 33 | uuid: string; 34 | author: string; 35 | name: string; 36 | description: string | null; 37 | created_at: string; 38 | updated_at: string; 39 | relationships?: NestRelationships; 40 | } 41 | 42 | export interface Nest { 43 | object: string; 44 | attributes: NestAttributes; 45 | } 46 | 47 | export interface Nests { 48 | object: string; 49 | data: Nest[]; 50 | meta: { 51 | pagination: { 52 | total: number; 53 | count: number; 54 | per_page: number; 55 | current_page: number; 56 | total_pages: number; 57 | }; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /src/application/interfaces/Node.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationNode */ 2 | import { Allocations } from './Allocation'; 3 | import { Location } from './Location'; 4 | import { Server } from './Server'; 5 | 6 | export interface NodeIncludeInput { 7 | allocations?: boolean; 8 | location?: boolean; 9 | servers?: boolean; 10 | } 11 | 12 | export interface NodeFilterInput { 13 | filter: string; 14 | filterBy: 'uuid' | 'name' | 'fqdn' | 'daemon_token_id'; 15 | } 16 | 17 | export interface NodeConfigSsl { 18 | enabled: boolean; 19 | cert: string; 20 | key: string; 21 | } 22 | 23 | export interface NodeConfigApi { 24 | host: string; 25 | port: number; 26 | ssl: NodeConfigSsl; 27 | upload_limit: number; 28 | } 29 | 30 | export interface NodeConfigSftp { 31 | bind_port: number; 32 | } 33 | 34 | export interface NodeConfigSystem { 35 | data: string; 36 | sftp: NodeConfigSftp; 37 | } 38 | 39 | export interface NodeConfig { 40 | debug: boolean; 41 | uuid: string; 42 | token_id: string; 43 | token: string; 44 | api: NodeConfigApi; 45 | system: NodeConfigSystem; 46 | allowed_mounts: string[]; 47 | remote: string; 48 | } 49 | 50 | export interface NodeAllocatedResources { 51 | memory: number; 52 | disk: number; 53 | } 54 | 55 | export interface NodeServers { 56 | object: string; 57 | data: Server[]; 58 | } 59 | 60 | export interface NodeRelationships { 61 | allocations?: Allocations; 62 | location?: Location; 63 | servers?: NodeServers; 64 | } 65 | 66 | export interface NodeAttributes { 67 | id: number; 68 | uuid: string; 69 | public: boolean; 70 | name: string; 71 | description: null | string; 72 | location_id: number; 73 | fqdn: string; 74 | scheme: string; 75 | behind_proxy: boolean; 76 | maintenance_mode: boolean; 77 | memory: number; 78 | memory_overallocate: number; 79 | disk: number; 80 | disk_overallocate: number; 81 | upload_size: number; 82 | daemon_listen: number; 83 | daemon_sftp: number; 84 | daemon_base: string; 85 | created_at: string; 86 | updated_at: string; 87 | allocated_resources: NodeAllocatedResources; 88 | relationships?: NodeRelationships; 89 | } 90 | 91 | export interface Node { 92 | object: string; 93 | attributes: NodeAttributes; 94 | } 95 | 96 | export interface Nodes { 97 | object: string; 98 | data: Node[]; 99 | meta: { 100 | pagination: { 101 | total: number; 102 | count: number; 103 | per_page: number; 104 | current_page: number; 105 | total_pages: number; 106 | }; 107 | }; 108 | } 109 | 110 | export interface NodeEditOptions { 111 | name?: string; 112 | description?: string; 113 | locationID?: number; 114 | fqdn?: string; 115 | scheme?: 'http' | 'https'; 116 | ram?: number; 117 | disk?: number; 118 | isPublic?: boolean; 119 | daemonPort?: number; 120 | daemonSFTPPort?: number; 121 | ramOverAllocate?: number; 122 | diskOverallocate?: number; 123 | daemonDir?: string; 124 | maintenceMode?: boolean; 125 | maxUploadSize?: number; 126 | behindProxy?: boolean; 127 | resetSecret: boolean; 128 | options?: NodeIncludeInput; 129 | } 130 | -------------------------------------------------------------------------------- /src/application/interfaces/Server.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationServer */ 2 | import { Database } from './Database'; 3 | import { Egg } from './Egg'; 4 | import { Location } from './Location'; 5 | import { Nest } from './Nest'; 6 | import { Node } from './Node'; 7 | import { User } from './User'; 8 | 9 | export interface ServerEnvironment { 10 | [key: string]: string | undefined; 11 | MAX_USERS?: string; 12 | MUMBLE_VERSION?: string; 13 | TS_VERSION?: string; 14 | FILE_TRANSFER?: string; 15 | ARK_PASSWORD?: string; 16 | ARK_ADMIN_PASSWORD?: string; 17 | SERVER_MAP?: string; 18 | SRCDS_APPID?: string; 19 | SESSION_NAME?: string; 20 | ENABLE_RCON?: string; 21 | RCON_PORT?: string; 22 | QUERY_PORT?: string; 23 | AUTO_UPDATE?: string; 24 | BATTLE_EYE?: string; 25 | SRCDS_MAP?: string; 26 | STEAM_ACC?: string; 27 | SRCDS_GAME?: string; 28 | WORKSHOP_ID?: string; 29 | GAMEMODE?: string; 30 | MAX_PLAYERS?: string; 31 | TICKRATE?: string; 32 | INSTALL_REPO?: string; 33 | USERNAME?: string; 34 | PASSWORD?: string; 35 | INSTALL_BRANCH?: string; 36 | USER_UPLOAD?: string; 37 | BOT_JS_FILE?: string; 38 | NODE_PACKAGES?: string; 39 | BUNGEE_VERSION?: string; 40 | SERVER_JARFILE?: string; 41 | MC_VERSION?: string; 42 | BUILD_TYPE?: string; 43 | FORGE_VERSION?: string; 44 | MINECRAFT_VERSION?: string; 45 | DL_PATH?: string; 46 | BUILD_NUMBER?: string; 47 | SPONGE_VERSION?: string; 48 | VANILLA_VERSION?: string; 49 | HOSTNAME?: string; 50 | OXIDE?: string; 51 | LEVEL?: string; 52 | DESCRIPTION?: string; 53 | SERVER_URL?: string; 54 | WORLD_SIZE?: string; 55 | WORLD_SEED?: string; 56 | SERVER_IMG?: string; 57 | RCON_PASS?: string; 58 | SAVEINTERVAL?: string; 59 | ADDITIONAL_ARGS?: string; 60 | } 61 | 62 | export interface ServerFilterInput { 63 | filter: string; 64 | filterBy: 'uuidShort' | 'uuid' | 'name' | 'external_id' | 'image'; 65 | } 66 | 67 | export interface ServerIncludesInput { 68 | allocations?: boolean; 69 | user?: boolean; 70 | subusers?: boolean; 71 | nest?: boolean; 72 | egg?: boolean; 73 | variables?: boolean; 74 | location?: boolean; 75 | node?: boolean; 76 | databases?: boolean; 77 | } 78 | 79 | export interface ServerLimits { 80 | memory: number; 81 | swap: number; 82 | disk: number; 83 | io: number; 84 | cpu: number; 85 | threads: null | string | number; 86 | } 87 | 88 | export interface ServerFeatureLimits { 89 | databases: number; 90 | allocations: number; 91 | backups: number; 92 | } 93 | 94 | export interface ServerContainer { 95 | startup_command: string; 96 | image: string; 97 | installed: boolean; 98 | environment: ServerEnvironment; 99 | } 100 | 101 | export interface ServerAllocations { 102 | object: string; 103 | data: ServerAllocation[]; 104 | } 105 | 106 | export interface ServerAllocation { 107 | object: string; 108 | attributes: ServerAllocationAttributes; 109 | } 110 | 111 | export interface ServerAllocationAttributes { 112 | id: number; 113 | ip: string; 114 | alias: string; 115 | port: number; 116 | notes: null | string; 117 | assigned: boolean; 118 | } 119 | 120 | export interface ServerVariables { 121 | object: string; 122 | data: ServerVariable[]; 123 | } 124 | 125 | export interface ServerVariable { 126 | object: string; 127 | attributes: ServerVariableAttributes; 128 | } 129 | 130 | export interface ServerVariableAttributes { 131 | id: number; 132 | egg_id: number; 133 | name: string; 134 | description: string; 135 | env_variable: string; 136 | default_value: string; 137 | user_viewable: boolean; 138 | user_editable: boolean; 139 | rules: string; 140 | created_at: string; 141 | updated_at: string; 142 | server_value: string; 143 | } 144 | 145 | export interface ServerSubUsers { 146 | object: string; 147 | data: ServerSubUser[]; 148 | } 149 | 150 | export interface ServerSubUser { 151 | object: 'subuser'; 152 | attributes: ServerSubUserAttributes; 153 | } 154 | 155 | export interface ServerSubUserAttributes { 156 | id: number; 157 | user_id: number; 158 | server_id: number; 159 | permissions: string[]; 160 | created_at: string; 161 | updated_at: string; 162 | } 163 | 164 | export interface ServerDatabases { 165 | object: string; 166 | data: Database[]; 167 | } 168 | 169 | export interface ServerRelationships { 170 | allocations?: ServerAllocations; 171 | user?: User; 172 | subusers?: ServerSubUsers; 173 | nest?: Nest; 174 | egg?: Egg; 175 | variables?: ServerVariables; 176 | location?: Location; 177 | node?: Node; 178 | databases?: ServerDatabases; 179 | } 180 | 181 | export interface ServerAttributes { 182 | id: number; 183 | external_id: null; 184 | uuid: string; 185 | identifier: string; 186 | name: string; 187 | description: string; 188 | suspended: boolean; 189 | limits: ServerLimits; 190 | feature_limits: ServerFeatureLimits; 191 | user: number; 192 | node: number; 193 | allocation: number; 194 | nest: number; 195 | egg: number; 196 | container: ServerContainer; 197 | updated_at: string; 198 | created_at: string; 199 | relationships?: ServerRelationships; 200 | } 201 | 202 | export interface Server { 203 | object: string; 204 | attributes: ServerAttributes; 205 | } 206 | 207 | export interface Servers { 208 | object: string; 209 | data: Server[]; 210 | meta: { 211 | pagination: { 212 | total: number; 213 | count: number; 214 | per_page: number; 215 | current_page: number; 216 | total_pages: number; 217 | }; 218 | }; 219 | } 220 | 221 | export interface EditServerDetails { 222 | /** New server name */ 223 | name?: string; 224 | /** ID of the new server owner */ 225 | userId?: number; 226 | /** Set the new external ID */ 227 | externalId?: string; 228 | /** Set new description */ 229 | description?: string; 230 | /** Include information about server relationships */ 231 | options?: ServerIncludesInput; 232 | } 233 | 234 | export interface EditServerBuild { 235 | /** The new primary allocation id */ 236 | allocationId?: number; 237 | /** Array of new allocation ids to add */ 238 | addAllocations?: number[]; 239 | /** Array of allocation ids to remove from server */ 240 | removeAllocations?: number[]; 241 | /** Amount of cpu resources to give (1 core = 100) (0 unlimited) */ 242 | cpu?: number; 243 | /** Amount of memory resources to give (1024 = 1GB) (0 unlimited) */ 244 | memory?: number; 245 | /** Amount of disk space to give (1024 = 1GB) (0 unlimited) */ 246 | disk?: number; 247 | /** Amount databases server can create */ 248 | databases?: number; 249 | /** Amount allocations server can create */ 250 | allocations?: number; 251 | /** Amount backups server can create */ 252 | backups?: number; 253 | /** Amount swap resources to give (1024 = 1GB) (-1 unlimited) */ 254 | swap?: number; 255 | /** ADVANCED IO performance of the host server (between 10 and 1000) */ 256 | io?: number; 257 | /** ADVANCED Threads for the server to use */ 258 | threads?: string; 259 | /** Include information about server relationships */ 260 | options?: ServerIncludesInput; 261 | } 262 | 263 | export interface EditServerStartup { 264 | startup?: string; 265 | environment?: ServerEnvironment; 266 | egg?: number; 267 | image?: string; 268 | options?: ServerIncludesInput; 269 | skip_scripts?: boolean; 270 | } 271 | -------------------------------------------------------------------------------- /src/application/interfaces/User.ts: -------------------------------------------------------------------------------- 1 | /** @module ApplicationUser */ 2 | import { Server } from './Server'; 3 | 4 | export interface UserIncludeInput { 5 | servers: boolean; 6 | } 7 | 8 | export interface UserFilterInput { 9 | filter: string; 10 | filterBy: 'email' | 'uuid' | 'username' | 'external_id'; 11 | } 12 | 13 | export interface UserServers { 14 | object: string; 15 | data: Server[]; 16 | } 17 | 18 | export interface UserRelationships { 19 | servers: UserServers; 20 | } 21 | 22 | export interface UserAttributes { 23 | 'id': number; 24 | 'external_id': string | null; 25 | 'uuid': string; 26 | 'username': string; 27 | 'email': string; 28 | 'first_name': string; 29 | 'last_name': string; 30 | 'language': string; 31 | 'root_admin': boolean; 32 | '2fa': boolean; 33 | 'created_at': string; 34 | 'updated_at': string; 35 | 'relationships'?: UserRelationships; 36 | } 37 | 38 | export interface User { 39 | object: string; 40 | attributes: UserAttributes; 41 | } 42 | 43 | export interface Users { 44 | object: string; 45 | data: User[]; 46 | meta: { 47 | pagination: { 48 | total: number; 49 | count: number; 50 | per_page: number; 51 | current_page: number; 52 | total_pages: number; 53 | }; 54 | }; 55 | } 56 | 57 | export interface EditUserOptions { 58 | /** The new username of the user */ 59 | username?: string; 60 | /** The new first name of the user */ 61 | firstName?: string; 62 | /** The new last name of the user */ 63 | lastName?: string; 64 | /** The new email address of the user */ 65 | email?: string; 66 | /** The new password of the user */ 67 | password?: string; 68 | /** Is the user admin */ 69 | isAdmin?: boolean; 70 | /** The new language of the user */ 71 | language?: string; 72 | /** The new external id of user */ 73 | externalId?: string; 74 | /** Include information about relationships */ 75 | options?: UserIncludeInput; 76 | } 77 | -------------------------------------------------------------------------------- /src/application/methods/allocation.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 2 | import { 3 | Allocation, 4 | AllocationFilterInput, 5 | AllocationIncludeInput, 6 | Allocations 7 | } from '../interfaces/Allocation'; 8 | import { Application } from '../index'; 9 | 10 | export class allocationMethods { 11 | constructor(private readonly application: Application) {} 12 | /** 13 | * @internal 14 | */ 15 | private getAllocations = async ( 16 | nodeId: number, 17 | options: MakeOpts 18 | ): Promise => { 19 | return this.application.request( 20 | 'GET', 21 | null, 22 | '', 23 | `/api/application/nodes/${nodeId}/allocations${makeOptions(options)}` 24 | ); 25 | }; 26 | /** 27 | * @param nodeId - The node id of which you want to get allocations from 28 | * @param options - Include information about relationships 29 | * @returns Returns information about node 30 | * @example 31 | * ```ts 32 | * const res = await app.getAllAllocations(1) // res = NodeAttributes 33 | * ``` 34 | * @example 35 | * ```ts 36 | * app.getAllAllocations(1).then((res) => console.log(res)) // res = NodeAttributes 37 | * ``` 38 | */ 39 | public getAllAllocations = async ( 40 | nodeId: number, 41 | options?: AllocationIncludeInput, 42 | filter?: AllocationFilterInput 43 | ): Promise => { 44 | return await paginate(this.getAllocations.bind(this, nodeId), { 45 | includes: { ...options }, 46 | filter 47 | }); 48 | }; 49 | /** 50 | * @param nodeId - The node id of which you want to create allocations 51 | * @param ports - Ports array to add 52 | * @param alias - The alias for this allocation 53 | * @param ip - IP for the allocation 54 | * @returns If successful returns Successfully created! 55 | * @example 56 | * ```ts 57 | * const res = await app.createAllocation(1, ['25565']) // res = Successfully created! 58 | * ``` 59 | * @example 60 | * ```ts 61 | * app.createAllocation(1, ['25565'], 'minecraft').then((res) => console.log(res)) // res = Successfully created! 62 | * ``` 63 | */ 64 | public createAllocation = async ( 65 | nodeId: number, 66 | ports: string[], 67 | alias = '', 68 | ip = '0.0.0.0' 69 | ): Promise => { 70 | return this.application.request( 71 | 'POST', 72 | { 73 | ip: ip, 74 | ports: ports, 75 | allocation_alias: alias 76 | }, 77 | 'Successfully created!', 78 | `/api/application/nodes/${nodeId}/allocations` 79 | ); 80 | }; 81 | /** 82 | * @param nodeId - The node id of which you want to delete allocation 83 | * @param allocationId - The id of allocation to delete 84 | * @returns If successful returns Successfully deleted! 85 | * @example 86 | * ```ts 87 | * const res = await app.deleteAllocation(1, 5) // res = Successfully deleted! 88 | * ``` 89 | * @example 90 | * ```ts 91 | * app.deleteAllocation(1, 8).then((res) => console.log(res)) // res = Successfully deleted! 92 | * ``` 93 | */ 94 | public deleteAllocation = async ( 95 | nodeId: number, 96 | allocationId: number 97 | ): Promise => { 98 | return this.application.request( 99 | 'DELETE', 100 | null, 101 | 'Successfully deleted!', 102 | `/api/application/nodes/${nodeId}/allocations/${allocationId}` 103 | ); 104 | }; 105 | } 106 | -------------------------------------------------------------------------------- /src/application/methods/database.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions } from '../../modules/Functions'; 2 | import { 3 | Database, 4 | DatabaseAttributes, 5 | DatabaseIncludeInput 6 | } from '../interfaces/Database'; 7 | import { Application } from '../index'; 8 | 9 | export class databaseMethods { 10 | constructor(private readonly application: Application) {} 11 | /** 12 | * @param serverId - The server ID to get the databases from 13 | * @param options - Include information about server relationships 14 | * @returns Array of databases 15 | * @example 16 | * ```ts 17 | * const res = await app.getServersDatabase(1) // res = Database[] 18 | * ``` 19 | * @example 20 | * ```ts 21 | * app.getServersDatabase(1).then((res) => console.log(res)) // res = Database[] 22 | * ``` 23 | */ 24 | public getServersDatabases = async ( 25 | serverId: number, 26 | options?: DatabaseIncludeInput 27 | ): Promise => { 28 | return this.application.request( 29 | 'GET', 30 | null, 31 | 'data', 32 | `/api/application/servers/${serverId}/databases${makeOptions({ 33 | includes: { ...options } 34 | })}` 35 | ); 36 | }; 37 | /** 38 | * @param serverId - The server ID to get the database from 39 | * @param databaseId - The ID of the database 40 | * @param options - Include information about server relationships 41 | * @returns Database information 42 | * @example 43 | * ```ts 44 | * const res = await app.getServersDatabaseInfo(1, 1) // res = DatabaseAttributes 45 | * ``` 46 | * @example 47 | * ```ts 48 | * app.getServersDatabaseInfo(1, 2).then((res) => console.log(res)) // res = DatabaseAttributes 49 | * ``` 50 | */ 51 | public getServersDatabaseInfo = async ( 52 | serverId: number, 53 | databaseId: number, 54 | options?: DatabaseIncludeInput 55 | ): Promise => { 56 | return this.application.request( 57 | 'GET', 58 | null, 59 | 'attributes', 60 | `/api/application/servers/${serverId}/databases/${databaseId}${makeOptions( 61 | { includes: { ...options } } 62 | )}` 63 | ); 64 | }; 65 | /** 66 | * @param name - Name of the Database 67 | * @param dbHostId - ID of the Database Host 68 | * @param serverId - The server ID to create the database in 69 | * @param allowedIp - IP allowed to connect, leave "%" if you dont want to restrict 70 | * @param options - Include information about server relationships 71 | * @returns Information about the new database 72 | * @example 73 | * ```ts 74 | * const res = await app.createDatabase('DATABASE_1', 1, 1) // res = DatabaseAttributes 75 | * ``` 76 | * @example 77 | * ```ts 78 | * app.createDatabase('DATABASE_1', 1, 1).then((res) => console.log(res)) // res = DatabaseAttributes 79 | * ``` 80 | */ 81 | public createDatabase = async ( 82 | name: string, 83 | dbHostId: number, 84 | serverId: number, 85 | allowedIp = '%', 86 | options?: DatabaseIncludeInput 87 | ): Promise => { 88 | return this.application.request( 89 | 'POST', 90 | { 91 | database: name, 92 | remote: allowedIp, 93 | host: dbHostId 94 | }, 95 | 'attributes', 96 | `/api/application/servers/${serverId}/databases${makeOptions({ 97 | includes: { ...options } 98 | })}` 99 | ); 100 | }; 101 | /** 102 | * @param serverId - The server ID to get the database from 103 | * @param databaseId - The ID of the database 104 | * @returns If successful returns Successfully reset the password! 105 | * @example 106 | * ```ts 107 | * const res = await app.resetDatabasePassword(1, 1) // res = Successfully reset the password! 108 | * ``` 109 | * @example 110 | * ```ts 111 | * app.resetDatabasePassword(1, 2).then((res) => console.log(res)) // res = Successfully reset the password! 112 | * ``` 113 | */ 114 | public resetDatabasePassword = async ( 115 | serverId: number, 116 | databaseId: number 117 | ): Promise => { 118 | return this.application.request( 119 | 'POST', 120 | null, 121 | 'Successfully reset the password!', 122 | `/api/application/servers/${serverId}/databases/${databaseId}/reset-password` 123 | ); 124 | }; 125 | /** 126 | * @param serverId - The server ID to delete the database in 127 | * @param databaseId - The ID of the database 128 | * @returns If successful returns Successfully deleted the database! 129 | * @example 130 | * ```ts 131 | * const res = await app.resetDatabasePassword(1, 1) // res = Successfully deleted the database! 132 | * ``` 133 | * @example 134 | * ```ts 135 | * app.resetDatabasePassword(1, 2).then((res) => console.log(res)) // res = Successfully deleted the database! 136 | * ``` 137 | */ 138 | public deleteDatabase = async ( 139 | serverId: number, 140 | databaseId: number 141 | ): Promise => { 142 | return this.application.request( 143 | 'DELETE', 144 | null, 145 | 'Successfully deleted the database!', 146 | `/api/application/servers/${serverId}/databases/${databaseId}` 147 | ); 148 | }; 149 | } 150 | -------------------------------------------------------------------------------- /src/application/methods/location.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 2 | import { 3 | EditLocationOptions, 4 | Location, 5 | LocationAttributes, 6 | LocationFilterInput, 7 | LocationIncludeInput, 8 | Locations 9 | } from '../interfaces/Location'; 10 | import { Application } from '../index'; 11 | 12 | export class locationMethods { 13 | constructor(private readonly application: Application) {} 14 | /** 15 | * @internal 16 | */ 17 | private getLocations = async (options: MakeOpts): Promise => { 18 | return this.application.request( 19 | 'GET', 20 | null, 21 | '', 22 | `/api/application/locations${makeOptions(options)}` 23 | ); 24 | }; 25 | /** 26 | * @param options - Include information about locations relationships 27 | * @param filter - Filter Location by specific fields and values 28 | * @returns Array of locations 29 | * @example 30 | * ```ts 31 | * const res = await app.getAllLocations() // res = Location[] 32 | * ``` 33 | * @example 34 | * ```ts 35 | * app.getAllLocations().then((res) => console.log(res)) // res = Location[] 36 | * ``` 37 | */ 38 | public getAllLocations = async ( 39 | options?: LocationIncludeInput, 40 | filter?: LocationFilterInput 41 | ): Promise => { 42 | return await paginate(this.getLocations.bind(this), { 43 | includes: { ...options }, 44 | filter 45 | }); 46 | }; 47 | /** 48 | * @param locationId - The location id to get information about 49 | * @param options - Include information about locations relationships 50 | * @returns Location information 51 | * @example 52 | * ```ts 53 | * const res = await app.getLocationInfo(1) // res = LocationAttributes 54 | * ``` 55 | * @example 56 | * ```ts 57 | * app.getLocationInfo(1).then((res) => console.log(res)) // res = LocationAttributes 58 | * ``` 59 | */ 60 | public getLocationInfo = async ( 61 | locationId: number, 62 | options?: LocationIncludeInput 63 | ): Promise => { 64 | return this.application.request( 65 | 'GET', 66 | null, 67 | 'attributes', 68 | `/api/application/locations/${locationId}${makeOptions({ 69 | includes: { ...options } 70 | })}` 71 | ); 72 | }; 73 | /** 74 | * @param shortName - The short name of the new location 75 | * @param description - The description of location 76 | * @param options - Include information about locations relationships 77 | * @returns Location information 78 | * @example 79 | * ```ts 80 | * const res = await app.createLocation('Home') // res = LocationAttributes 81 | * ``` 82 | * @example 83 | * ```ts 84 | * app.createLocation('Home').then((res) => console.log(res)) // res = LocationAttributes 85 | * ``` 86 | */ 87 | public createLocation = async ( 88 | shortName: string, 89 | description?: string, 90 | options?: LocationIncludeInput 91 | ): Promise => { 92 | return this.application.request( 93 | 'POST', 94 | { 95 | short: shortName, 96 | long: description ? description : '' 97 | }, 98 | 'attributes', 99 | `/api/application/locations${makeOptions({ 100 | includes: { ...options } 101 | })}` 102 | ); 103 | }; 104 | /** 105 | * @param locationId - The location id to edit 106 | * @param options - Location edit options 107 | * @returns Location information 108 | * @example 109 | * ```ts 110 | * const res = await app.editLocation(1, 'Homie') // res = LocationAttributes 111 | * ``` 112 | * @example 113 | * ```ts 114 | * app.editLocation(1, undefined, 'Very good locaiton').then((res) => console.log(res)) // res = LocationAttributes 115 | * ``` 116 | */ 117 | public editLocation = async ( 118 | locationId: number, 119 | options: EditLocationOptions 120 | ): Promise => { 121 | const location = await this.getLocationInfo(locationId); 122 | return this.application.request( 123 | 'PATCH', 124 | { 125 | short: options.shortName ?? location.short, 126 | long: options.description ?? location.long 127 | }, 128 | 'attributes', 129 | `/api/application/locations/${locationId}${makeOptions({ 130 | includes: { ...options.options } 131 | })}` 132 | ); 133 | }; 134 | /** 135 | * @param locationId - The location id to delete 136 | * @returns Successfully deleted the location! 137 | * @example 138 | * ```ts 139 | * const res = await app.deleteLocation(1) // res = Successfully deleted the location! 140 | * ``` 141 | * @example 142 | * ```ts 143 | * app.deleteLocation(1).then((res) => console.log(res)) // res = Successfully deleted the location! 144 | * ``` 145 | */ 146 | public deleteLocation = async (locationId: number): Promise => { 147 | return this.application.request( 148 | 'DELETE', 149 | null, 150 | 'Successfully deleted the location!', 151 | `/api/application/locations/${locationId}` 152 | ); 153 | }; 154 | } 155 | -------------------------------------------------------------------------------- /src/application/methods/nest.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 2 | import { Egg, EggAttributes } from '../interfaces/Egg'; 3 | import { 4 | Nest, 5 | EggIncludeInput, 6 | NestAttributes, 7 | NestIncludeInput, 8 | Nests 9 | } from '../interfaces/Nest'; 10 | import { Application } from '../index'; 11 | 12 | export class nestMethods { 13 | constructor(private readonly application: Application) {} 14 | /** 15 | * @internal 16 | */ 17 | private getNests = async (options: MakeOpts): Promise => { 18 | return this.application.request( 19 | 'GET', 20 | null, 21 | '', 22 | `/api/application/nests${makeOptions(options)}` 23 | ); 24 | }; 25 | /** 26 | * @param options - Include information about: eggs or servers 27 | * @returns Array of nests 28 | * @example 29 | * ```ts 30 | * const res = await app.getAllNests() // res = Nest[] 31 | * ``` 32 | * @example 33 | * ```ts 34 | * app.getAllNests().then((res) => console.log(res)) // res = Nest[] 35 | * ``` 36 | */ 37 | public getAllNests = async (options?: NestIncludeInput): Promise => { 38 | return await paginate(this.getNests.bind(this), { 39 | includes: { ...options } 40 | }); 41 | }; 42 | /** 43 | * @param nestId - The nest ID to get the details of. 44 | * @param options - Include information about: eggs or servers 45 | * @returns Nest details 46 | * @example 47 | * ```ts 48 | * const res = await app.getNestInfo(1) // res = NestAttributes 49 | * ``` 50 | * @example 51 | * ```ts 52 | * app.getNestInfo(1).then((res) => console.log(res)) // res = NestAttributes 53 | * ``` 54 | */ 55 | public getNestInfo = async ( 56 | nestId: number, 57 | options?: NestIncludeInput 58 | ): Promise => { 59 | return this.application.request( 60 | 'GET', 61 | null, 62 | 'attributes', 63 | `/api/application/nests/${nestId}${makeOptions({ 64 | includes: { ...options } 65 | })}` 66 | ); 67 | }; 68 | /** 69 | * @param nestId - The nest ID to get the details of. 70 | * @param options - Include information about: nest or servers or variables 71 | * @returns 72 | * @example 73 | * ```ts 74 | * const res = await app.getAllNestEggs(1) // res = Egg[] 75 | * ``` 76 | * @example 77 | * ```ts 78 | * app.getAllNestEggs(1).then((res) => console.log(res)) // res = Egg[] 79 | * ``` 80 | */ 81 | public getAllNestEggs = async ( 82 | nestId: number, 83 | options?: EggIncludeInput 84 | ): Promise => { 85 | return this.application.request( 86 | 'GET', 87 | null, 88 | 'data', 89 | `/api/application/nests/${nestId}/eggs${makeOptions({ 90 | includes: { ...options } 91 | })}` 92 | ); 93 | }; 94 | /** 95 | * @param nestId - The nest ID to get the details of. 96 | * @param eggId - Egg ID to use when installing the server 97 | * @param options - Include information about: nest or servers or variables 98 | * @returns 99 | * @example 100 | * ```ts 101 | * const res = await app.getEggInfo(1, 1) // res = EggAttributes 102 | * ``` 103 | * @example 104 | * ```ts 105 | * app.getEggInfo(1, 1).then((res) => console.log(res)) // res = EggAttributes 106 | * ``` 107 | */ 108 | public getEggInfo = async ( 109 | nestID: number, 110 | eggId: number, 111 | options?: EggIncludeInput 112 | ): Promise => { 113 | return this.application.request( 114 | 'GET', 115 | null, 116 | 'attributes', 117 | `/api/application/nests/${nestID}/eggs/${eggId}${makeOptions({ 118 | includes: { ...options } 119 | })}` 120 | ); 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /src/application/methods/node.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 2 | import { 3 | Node, 4 | NodeAttributes, 5 | NodeConfig, 6 | NodeEditOptions, 7 | NodeFilterInput, 8 | NodeIncludeInput, 9 | Nodes 10 | } from '../interfaces/Node'; 11 | import { Application } from '../index'; 12 | 13 | export class nodeMethods { 14 | constructor(private readonly application: Application) {} 15 | /** 16 | * @internal 17 | */ 18 | private getNodes = async (options: MakeOpts): Promise => { 19 | return this.application.request( 20 | 'GET', 21 | null, 22 | '', 23 | `/api/application/nodes${makeOptions(options)}` 24 | ); 25 | }; 26 | /** 27 | * @param options - Include information about relationships 28 | * @param filter - Filter Nodes by specific fields and values 29 | * @returns Array of nodes 30 | * @example 31 | * ```ts 32 | * const res = await app.getAllNodes() // res = Node[] 33 | * ``` 34 | * @example 35 | * ```ts 36 | * app.getAllNodes().then((res) => console.log(res)) // res = Node[] 37 | * ``` 38 | */ 39 | public getAllNodes = async ( 40 | options?: NodeIncludeInput, 41 | filter?: NodeFilterInput 42 | ): Promise => { 43 | return await paginate(this.getNodes.bind(this), { 44 | includes: { ...options }, 45 | filter: filter 46 | }); 47 | }; 48 | /** 49 | * @param nodeId - The node id of which you want to get information 50 | * @param options - Include information about relationships 51 | * @returns Returns information about node 52 | * @example 53 | * ```ts 54 | * const res = await app.getNodeInfo(1) // res = NodeAttributes 55 | * ``` 56 | * @example 57 | * ```ts 58 | * app.getNodeInfo(1).then((res) => console.log(res)) // res = NodeAttributes 59 | * ``` 60 | */ 61 | public getNodeInfo = async ( 62 | nodeId: number, 63 | options?: NodeIncludeInput 64 | ): Promise => { 65 | return this.application.request( 66 | 'GET', 67 | null, 68 | 'attributes', 69 | `/api/application/nodes/${nodeId}${makeOptions({ 70 | includes: { ...options } 71 | })}` 72 | ); 73 | }; 74 | /** 75 | * @param nodeId - The node id of which you want to get information 76 | * @returns Returns information about node config 77 | * @example 78 | * ```ts 79 | * const res = await app.getNodeConfig(1) // res = NodeConfig 80 | * ``` 81 | * @example 82 | * ```ts 83 | * app.getNodeConfig(1).then((res) => console.log(res)) // res = NodeConfig 84 | * ``` 85 | */ 86 | public getNodeConfig = (nodeId: number): Promise => { 87 | return this.application.request( 88 | 'GET', 89 | null, 90 | '', 91 | `/api/application/nodes/${nodeId}/configuration` 92 | ); 93 | }; 94 | /** 95 | * @param name - The name of the node 96 | * @param description - A description for the node 97 | * @param locationId - Location ID to use 98 | * @param fqdn - Fully Qualified Domain Name (If you're using an IP scheme needs to be http) 99 | * @param scheme - Scheme to use: http or https 100 | * @param ram - How much RAM should be allocated for the node? 101 | * @param disk - How much disk space be allocated for the node? 102 | * @param isPublic - Is this node public? 103 | * @param daemonPort - The daemon port (default 8080) 104 | * @param daemonSFTPPort - The daemon sftp port (default 2022) 105 | * @param ramOverAllocate - Ram overallocation (default -1) 106 | * @param diskOverallocate - Disk overallocation (default -1) 107 | * @param daemonDir - Directory of the daemon, normally /var/lib/pterodactyl/volumes 108 | * @param maintenceMode - Is the node in maintence mode? 109 | * @param maxUploadSize - Upload size (1-1024) 110 | * @param behindProxy - Is the node behind a proxy? 111 | * @param options - Include information about relationships 112 | * @returns Information about the new node 113 | * @example 114 | * ```ts 115 | * const res = await app.createNode('NEW node', 'Good node', 1, 'node.gfd.com', 'https', 8192, 500000) // res = NodeAttributes 116 | * ``` 117 | * @example 118 | * ```ts 119 | * app.createNode('NEW node', 'Good node', 1, 'node.gfd.com', 'https', 8192, 500000).then((res) => console.log(res)) // res = NodeAttributes 120 | * ``` 121 | */ 122 | public createNode = async ( 123 | name: string, 124 | description: string, 125 | locationID: number, 126 | fqdn: string, 127 | scheme: 'http' | 'https', 128 | ram: number, 129 | disk: number, 130 | isPublic = true, 131 | daemonPort = 8080, 132 | daemonSFTPPort = 2022, 133 | ramOverAllocate = -1, 134 | diskOverallocate = -1, 135 | daemonDir = '/var/lib/pterodactyl/volumes', 136 | maintenceMode = false, 137 | maxUploadSize = 100, 138 | behindProxy = false, 139 | options?: NodeIncludeInput 140 | ): Promise => { 141 | return this.application.request( 142 | 'POST', 143 | { 144 | name: name, 145 | description: description, 146 | location_id: locationID, 147 | public: isPublic, 148 | fqdn: fqdn, 149 | scheme: scheme, 150 | behind_proxy: behindProxy, 151 | memory: ram, 152 | memory_overallocate: ramOverAllocate, 153 | disk: disk, 154 | disk_overallocate: diskOverallocate, 155 | daemon_base: daemonDir, 156 | daemon_listen: daemonPort, 157 | daemon_sftp: daemonSFTPPort, 158 | maintenance_mode: maintenceMode, 159 | upload_size: maxUploadSize 160 | }, 161 | 'attributes', 162 | `/api/application/nodes${makeOptions({ 163 | includes: { ...options } 164 | })}` 165 | ); 166 | }; 167 | /** 168 | * @param nodeId - The node id of which you want to get information 169 | * @param name - The name of the node 170 | * @param description - A description for the node 171 | * @param locationId - Location ID to use 172 | * @param fqdn - Fully Qualified Domain Name (If you're using an IP scheme needs to be http) 173 | * @param scheme - Scheme to use: http or https 174 | * @param ram - How much RAM should be allocated for the node? 175 | * @param disk - How much disk space be allocated for the node? 176 | * @param isPublic - Is this node public? 177 | * @param daemonPort - The daemon port (default 8080) 178 | * @param daemonSFTPPort - The daemon sftp port (default 2022) 179 | * @param ramOverAllocate - Ram overallocation (default -1) 180 | * @param diskOverallocate - Disk overallocation (default -1) 181 | * @param daemonDir - Directory of the daemon, normally /var/lib/pterodactyl/volumes 182 | * @param maintenceMode - Is the node in maintence mode? 183 | * @param maxUploadSize - Upload size (1-1024) 184 | * @param behindProxy - Is the node behind a proxy? 185 | * @param resetSecret - Reset daemonds token? 186 | * @param options - Include information about relationships 187 | * @returns Information about the new node 188 | * @example 189 | * ```ts 190 | * const res = await app.editNode('NEW node', 'Good node', 1, 'node.gfd.com', 'https', 8192, 500000) // res = NodeAttributes 191 | * ``` 192 | * @example 193 | * ```ts 194 | * app.editNode('NEW node', undefined, 1, 'node.gfd.com', undefined, 8192, 500000).then((res) => console.log(res)) // res = NodeAttributes 195 | * ``` 196 | */ 197 | public editNode = async ( 198 | nodeId: number, 199 | options: NodeEditOptions 200 | ): Promise => { 201 | const node = await this.getNodeInfo(nodeId); 202 | return this.application.request( 203 | 'PATCH', 204 | { 205 | name: options.name ?? node.name, 206 | description: options.description ?? node.description, 207 | location_id: options.locationID ?? node.location_id, 208 | public: options.isPublic ?? node.public, 209 | fqdn: options.fqdn ?? node.fqdn, 210 | scheme: options.scheme ?? node.scheme, 211 | behind_proxy: options.behindProxy ?? node.behind_proxy, 212 | memory: options.ram ?? node.memory, 213 | memory_overallocate: 214 | options.ramOverAllocate ?? node.memory_overallocate, 215 | disk: options.disk ?? node.disk, 216 | disk_overallocate: options.diskOverallocate ?? node.disk_overallocate, 217 | daemon_base: options.daemonDir ?? node.daemon_base, 218 | daemon_listen: options.daemonPort ?? node.daemon_listen, 219 | daemon_sftp: options.daemonSFTPPort ?? node.daemon_sftp, 220 | maintenance_mode: options.maintenceMode ?? node.maintenance_mode, 221 | upload_size: options.maxUploadSize ?? node.upload_size, 222 | reset_secret: options.resetSecret 223 | }, 224 | 'attributes', 225 | `/api/application/nodes/${nodeId}${makeOptions({ 226 | includes: { ...options.options } 227 | })}` 228 | ); 229 | }; 230 | /** 231 | * @param nodeId - The node id of which you want to get information 232 | * @returns If successful returns Successfully deleted! 233 | * @example 234 | * ```ts 235 | * const res = await app.deleteNode(1) // res = Successfully deleted! 236 | * ``` 237 | * @example 238 | * ```ts 239 | * app.deleteNode(1).then((res) => console.log(res)) // res = Successfully deleted! 240 | * ``` 241 | */ 242 | public deleteNode = async (nodeId: number): Promise => { 243 | return this.application.request( 244 | 'DELETE', 245 | null, 246 | 'Successfully deleted!', 247 | `/api/application/nodes/${nodeId}` 248 | ); 249 | }; 250 | } 251 | -------------------------------------------------------------------------------- /src/application/methods/server.ts: -------------------------------------------------------------------------------- 1 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 2 | import { 3 | EditServerBuild, 4 | EditServerDetails, 5 | EditServerStartup, 6 | Server, 7 | ServerAttributes, 8 | ServerEnvironment, 9 | ServerFilterInput, 10 | ServerIncludesInput, 11 | Servers 12 | } from '../interfaces/Server'; 13 | import { Application } from '../index'; 14 | 15 | export class serverMethods { 16 | constructor(private readonly application: Application) {} 17 | /** 18 | * @internal 19 | */ 20 | private getServers = async (options: MakeOpts): Promise => { 21 | return this.application.request( 22 | 'GET', 23 | null, 24 | '', 25 | `/api/application/servers${makeOptions(options)}` 26 | ); 27 | }; 28 | /** 29 | * @param options - Include information about server relationships 30 | * @param filter - Filter Servers by specific fields and values 31 | * @returns Array of server 32 | * @example 33 | * ```ts 34 | * const res = await app.getAllServers() // res = Server[] 35 | * ``` 36 | * @example 37 | * ```ts 38 | * app.getAllServers().then((res) => console.log(res)) // res = Server[] 39 | * ``` 40 | */ 41 | public getAllServers = async ( 42 | options?: ServerIncludesInput, 43 | filter?: ServerFilterInput 44 | ): Promise => { 45 | return await paginate(this.getServers.bind(this), { 46 | includes: { ...options }, 47 | filter: filter 48 | }); 49 | }; 50 | /** 51 | * @param serverId - The server ID to get the details of. 52 | * @param options - Include information about server relationships 53 | * @returns Server information 54 | * @example 55 | * ```ts 56 | * const res = await app.getServerInfo(1) // res = ServerAttributes 57 | * ``` 58 | * @example 59 | * ```ts 60 | * app.getServerInfo(1).then((res) => console.log(res)) // res = ServerAttributes 61 | * ``` 62 | */ 63 | public getServerInfo = async ( 64 | serverId: number, 65 | options?: ServerIncludesInput 66 | ): Promise => { 67 | return this.application.request( 68 | 'GET', 69 | null, 70 | 'attributes', 71 | `/api/application/servers/${serverId}${makeOptions({ 72 | includes: { ...options } 73 | })}` 74 | ); 75 | }; 76 | /** 77 | * @param serverId - The external server ID to get the details of. 78 | * @param options - Include information about server relationships 79 | * @returns Server information 80 | * @example 81 | * ```ts 82 | * const res = await app.getServerInfoByExtId('MC_SERVER') // res = ServerAttributes 83 | * ``` 84 | * @example 85 | * ```ts 86 | * app.getServerInfoByExtId('GAMER_SERVER').then((res) => console.log(res)) // res = ServerAttributes 87 | * ``` 88 | */ 89 | public getServerInfoByExtId = async ( 90 | serverId: string, 91 | options?: ServerIncludesInput 92 | ): Promise => { 93 | return this.application.request( 94 | 'GET', 95 | null, 96 | 'attributes', 97 | `/api/application/servers/external/${serverId}${makeOptions({ 98 | includes: { ...options } 99 | })}` 100 | ); 101 | }; 102 | /** 103 | * @param serverId - The server ID to get the details of. 104 | * @param options - The options to edit 105 | * @returns Server information 106 | * @example 107 | * ```ts 108 | * const res = await app.editServerDetails(1, 'Mc server') // res = ServerAttributes 109 | * ``` 110 | * @example 111 | * ```ts 112 | * app.editServerDetails(1, undefined, undefined, 'MC_SERVER').then((res) => console.log(res)) // res = ServerAttributes 113 | * ``` 114 | */ 115 | public editServerDetails = async ( 116 | serverId: number, 117 | options: EditServerDetails 118 | ): Promise => { 119 | const server = await this.getServerInfo(serverId); 120 | return this.application.request( 121 | 'PATCH', 122 | { 123 | name: options.name ?? server.name, 124 | user: options.userId != undefined ? options.userId : server.user, 125 | external_id: options.externalId ?? server.external_id, 126 | description: options.description ?? server.description 127 | }, 128 | 'attributes', 129 | `/api/application/servers/${serverId}/details${makeOptions({ 130 | includes: { ...options.options } 131 | })}` 132 | ); 133 | }; 134 | /** 135 | * @param serverId - The server ID to get the details of. 136 | * @param options - The options to edit 137 | * @returns Server information 138 | * @example 139 | * ```ts 140 | * const res = await app.editServerBuild(1, undefined, undefined, [5, 6]) // res = ServerAttributes 141 | * ``` 142 | * @example 143 | * ```ts 144 | * app.editServerBuild(1, undefined, [1, 3]).then((res) => console.log(res)) // res = ServerAttributes 145 | * ``` 146 | */ 147 | public editServerBuild = async ( 148 | serverId: number, 149 | options: EditServerBuild 150 | ): Promise => { 151 | const server = await this.getServerInfo(serverId); 152 | return this.application.request( 153 | 'PATCH', 154 | { 155 | allocation: 156 | options.allocationId != undefined 157 | ? options.allocationId 158 | : server.allocation, 159 | add_allocations: options.addAllocations ?? [], 160 | remove_allocations: options.removeAllocations ?? [], 161 | memory: 162 | options.memory != undefined ? options.memory : server.limits.memory, 163 | swap: options.swap != undefined ? options.swap : server.limits.swap, 164 | disk: options.disk != undefined ? options.disk : server.limits.disk, 165 | io: options.io != undefined ? options.io : server.limits.io, 166 | cpu: options.cpu != undefined ? options.cpu : server.limits.cpu, 167 | threads: 168 | options.threads != undefined 169 | ? options.threads 170 | : server.limits.threads, 171 | feature_limits: { 172 | databases: 173 | options.databases != undefined 174 | ? options.databases 175 | : server.feature_limits.databases, 176 | allocations: 177 | options.allocations != undefined 178 | ? options.allocations 179 | : server.feature_limits.allocations, 180 | backups: 181 | options.backups != undefined 182 | ? options.backups 183 | : server.feature_limits.backups 184 | } 185 | }, 186 | 'attributes', 187 | `/api/application/servers/${serverId}/build${makeOptions({ 188 | includes: { ...options.options } 189 | })}` 190 | ); 191 | }; 192 | /** 193 | * @param serverId - The external server ID to get the details of. 194 | * @param startup - The new startup command 195 | * @param environment - Servers environment variables. REQUIRED! 196 | * @param egg - The new egg you want to use 197 | * @param image - The new docker image you want to use 198 | * @param skip_scripts - Skip install script boolean (FALSE by default!) 199 | * @param options - Include information about server relationships 200 | * @returns Server information 201 | * @example 202 | * ```ts 203 | * const res = await app.editServerStartup(1, 'node index.js') // res = ServerAttributes 204 | * ``` 205 | * @example 206 | * ```ts 207 | * app.editServerStartup(1, 'node index.js').then((res) => console.log(res)) // res = ServerAttributes 208 | * ``` 209 | */ 210 | public editServerStartup = async ( 211 | serverId: number, 212 | options: EditServerStartup 213 | ): Promise => { 214 | const server = await this.getServerInfo(serverId, { variables: true }); 215 | const envVars: Record = {}; 216 | if (options.environment) { 217 | const env = options.environment; 218 | const givenEnvVars = Object.keys(options.environment); 219 | server.relationships?.variables?.data.forEach((envVar) => { 220 | const envVariable = envVar.attributes.env_variable; 221 | if (givenEnvVars.includes(envVariable)) { 222 | envVars[envVariable] = env[envVariable]; 223 | } else if (envVar.attributes.server_value) { 224 | envVars[envVariable] = envVar.attributes.server_value; 225 | } else if (envVar.attributes.default_value) { 226 | envVars[envVariable] = envVar.attributes.default_value; 227 | } else if (envVar.attributes.rules.includes('nullable')) { 228 | envVars[envVariable] = ''; 229 | } else { 230 | throw new Error( 231 | `Environment variable ${envVariable} was not defined!` 232 | ); 233 | } 234 | }); 235 | } 236 | return this.application.request( 237 | 'PATCH', 238 | { 239 | startup: options.startup ?? server.container.startup_command, 240 | environment: options.environment 241 | ? envVars 242 | : server.container.environment, 243 | egg: options.egg != undefined ? options.egg : server.egg, 244 | image: options.image ?? server.container.image, 245 | skip_scripts: options.skip_scripts ?? false 246 | }, 247 | 'attributes', 248 | `/api/application/servers/${serverId}/startup${makeOptions({ 249 | includes: { ...options.options } 250 | })}` 251 | ); 252 | }; 253 | /** 254 | * @param name -Name of server to create 255 | * @param ownerId - User ID of who should own this server 256 | * @param description - Description of server 257 | * @param nestId - ID of the nest to use when making a server 258 | * @param eggId - Egg ID to use when installing the server 259 | * @param environment - Servers environment variables. Some are REQUIRED! If there is a default value and none is provided default is used! 260 | * @param cpu - Amount of cpu resources to give (1 core = 100) (0 unlimited) 261 | * @param ram - Amount of memory resources to give (1024 = 1GB) (0 unlimited) 262 | * @param disk - Amount of disk space to give (1024 = 1GB) (0 unlimited) 263 | * @param amountOfDatabases - The max amount of databases a server can use 264 | * @param amountOfAllocations - The max amount of allocation(s) a server can use 265 | * @param amountOfBackups - The max amount of backups a server can use 266 | * @param startupCmd - The command to use when starting this server 267 | * @param dockerImage - The image to use from Docker 268 | * @param swap - The amount of Swap the server has 269 | * @param io - Set this to 500. 270 | * @param options - Include information about server relationships 271 | * @returns Returns the created server object 272 | * @example 273 | * ```ts 274 | * const res = await app.createServer('BUNGEE', 1, 'BUNGEE SERVER', 1, 1) // res = ServerAttributes 275 | * ``` 276 | * @example 277 | * ```ts 278 | * app.createServer('BUNGEE', 1, 'BUNGEE SERVER', 1, 1).then((res) => console.log(res)) // res = ServerAttributes 279 | * ``` 280 | */ 281 | public createServer = async ( 282 | name: string, 283 | ownerId: number, 284 | description: string, 285 | nestId: number, 286 | eggId: number, 287 | defaultAllocationId: number, 288 | addAllocationIds: number[] = [], 289 | environment?: ServerEnvironment, 290 | cpu = 0, 291 | ram = 0, 292 | disk = 0, 293 | amountOfDatabases = 0, 294 | amountOfAllocations = 0, 295 | amountOfBackups = 0, 296 | startupCmd?: string, 297 | dockerImage?: string, 298 | swap = 0, 299 | io = 500, 300 | startOnCompletion = false, 301 | options?: ServerIncludesInput // Databases are always empty 302 | ): Promise => { 303 | const egg = await this.application.getEggInfo(nestId, eggId, { 304 | variables: true 305 | }); 306 | const envVars: Record = {}; 307 | let givenEnvVars: string[] = []; 308 | if (environment) givenEnvVars = Object.keys(environment); 309 | egg.relationships?.variables?.data.forEach( 310 | (envVar: { 311 | attributes: { 312 | env_variable: string; 313 | rules: string; 314 | default_value: string; 315 | }; 316 | }) => { 317 | const envVariable = envVar.attributes.env_variable; 318 | if (givenEnvVars.includes(envVariable)) { 319 | envVars[envVariable] = environment?.[envVariable]; 320 | } else if (envVar.attributes.rules.includes('nullable')) { 321 | envVars[envVariable] = ''; 322 | } else if (envVar.attributes.default_value) { 323 | envVars[envVariable] = envVar.attributes.default_value; 324 | } else { 325 | throw new Error( 326 | `Environment variable ${envVariable} was not defined!` 327 | ); 328 | } 329 | } 330 | ); 331 | return this.application.request( 332 | 'POST', 333 | { 334 | name: name, 335 | user: ownerId, 336 | description: description, 337 | egg: eggId, 338 | pack: nestId, 339 | docker_image: dockerImage ? dockerImage : egg.docker_image, 340 | startup: startupCmd ? startupCmd : egg.startup, 341 | limits: { 342 | memory: ram, 343 | swap: swap, 344 | disk: disk, 345 | io: io, 346 | cpu: cpu 347 | }, 348 | feature_limits: { 349 | databases: amountOfDatabases, 350 | allocations: amountOfAllocations, 351 | backups: amountOfBackups 352 | }, 353 | environment: envVars, 354 | allocation: { 355 | default: defaultAllocationId, 356 | allocation_additional: addAllocationIds ?? [] 357 | }, 358 | start_on_completion: startOnCompletion, 359 | skip_scripts: false, 360 | oom_disabled: true 361 | }, 362 | 'attributes', 363 | `/api/application/servers${makeOptions({ 364 | includes: { ...options } 365 | })}` 366 | ); 367 | }; 368 | /** 369 | * @param internalId - Internal ID of the server to delete 370 | * @param forceDelete - Boolean if forcefully delete a server 371 | * @returns If successful returns Successfully deleted! 372 | * @example 373 | * ```ts 374 | * const res = await app.deleteServer(1) // res = Successfully deleted! 375 | * ``` 376 | * @example 377 | * ```ts 378 | * app.deleteServer(1, true).then((res) => console.log(res)) // res = Successfully deleted! 379 | * ``` 380 | */ 381 | public deleteServer = async ( 382 | internalId: number, 383 | forceDelete = false 384 | ): Promise => { 385 | let force = ''; 386 | if (forceDelete) force = '/force'; 387 | return this.application.request( 388 | 'DELETE', 389 | null, 390 | 'Successfully deleted!', 391 | `/api/application/servers/${internalId}${force}` 392 | ); 393 | }; 394 | /** 395 | * @param internalId - Internal ID of the server to suspend 396 | * @returns If successful returns Successfully suspended! 397 | * @example 398 | * ```ts 399 | * const res = await app.suspendServer(1) // res = Successfully suspended! 400 | * ``` 401 | * @example 402 | * ```ts 403 | * app.suspendServer(1).then((res) => console.log(res)) // res = Successfully suspended! 404 | * ``` 405 | */ 406 | public suspendServer = (internalID: number): Promise => { 407 | return this.application.request( 408 | 'POST', 409 | null, 410 | 'Successfully suspended!', 411 | `/api/application/servers/${internalID}/suspend` 412 | ); 413 | }; 414 | /** 415 | * @param internalId - Internal ID of the server to suspend 416 | * @returns If successful returns Successfully unsuspended! 417 | * @example 418 | * ```ts 419 | * const res = await app.unSuspendServer(1) // res = Successfully unsuspended! 420 | * ``` 421 | * @example 422 | * ```ts 423 | * app.unSuspendServer(1).then((res) => console.log(res)) // res = Successfully unsuspended! 424 | * ``` 425 | */ 426 | public unSuspendServer = (internalID: number): Promise => { 427 | return this.application.request( 428 | 'POST', 429 | null, 430 | 'Successfully unsuspended!', 431 | `/api/application/servers/${internalID}/unsuspend` 432 | ); 433 | }; 434 | /** 435 | * @param internalId - Internal ID of the server to reinstall 436 | * @returns If successful returns Successfully reinstalled! 437 | * @example 438 | * ```ts 439 | * const res = await app.reinstallServer(1) // res = Successfully reinstalled! 440 | * ``` 441 | * @example 442 | * ```ts 443 | * app.reinstallServer(1).then((res) => console.log(res)) // res = Successfully reinstalled! 444 | * ``` 445 | */ 446 | public reinstallServer = (internalID: number): Promise => { 447 | return this.application.request( 448 | 'POST', 449 | null, 450 | 'Successfully reinstalled!', 451 | `/api/application/servers/${internalID}/reinstall` 452 | ); 453 | }; 454 | } 455 | -------------------------------------------------------------------------------- /src/application/methods/user.ts: -------------------------------------------------------------------------------- 1 | import { Application } from '../index'; 2 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 3 | import { 4 | EditUserOptions, 5 | User, 6 | UserAttributes, 7 | UserFilterInput, 8 | UserIncludeInput, 9 | Users 10 | } from '../interfaces/User'; 11 | 12 | export class userMethods { 13 | constructor(private readonly application: Application) {} 14 | /** 15 | * @internal 16 | */ 17 | private getUsers = async (options: MakeOpts): Promise => { 18 | return this.application.request( 19 | 'GET', 20 | null, 21 | '', 22 | `/api/application/users${makeOptions(options)}` 23 | ); 24 | }; 25 | /** 26 | * @param options - Include information about relationships 27 | * @param filter - Filter Users by specific fields and values 28 | * @returns Array of users 29 | * @example 30 | * ```ts 31 | * const res = await app.getAllUsers() // res = User[] 32 | * ``` 33 | * @example 34 | * ```ts 35 | * app.getAllUsers().then((res) => console.log(res)) // res = User[] 36 | * ``` 37 | */ 38 | public getAllUsers = async ( 39 | options?: UserIncludeInput, 40 | filter?: UserFilterInput 41 | ): Promise => { 42 | return await paginate(this.getUsers.bind(this), { 43 | includes: { ...options }, 44 | filter: filter 45 | }); 46 | }; 47 | /** 48 | * @param userId - The user id to get information about 49 | * @param options - Include information about relationships 50 | * @returns User information 51 | * @example 52 | * ```ts 53 | * const res = await app.getUserInfo(1) // res = UserAttributes 54 | * ``` 55 | * @example 56 | * ```ts 57 | * app.getUserInfo(1).then((res) => console.log(res)) // res = UserAttributes 58 | * ``` 59 | */ 60 | public getUserInfo = async ( 61 | userId: number, 62 | options?: UserIncludeInput 63 | ): Promise => { 64 | return this.application.request( 65 | 'GET', 66 | null, 67 | 'attributes', 68 | `/api/application/users/${userId}${makeOptions({ 69 | includes: { ...options } 70 | })}` 71 | ); 72 | }; 73 | /** 74 | * @param userId - The external user id to get information about 75 | * @param options - Include information about relationships 76 | * @returns User information 77 | * @example 78 | * ```ts 79 | * const res = await app.getUserInfoByExtId(1) // res = UserAttributes 80 | * ``` 81 | * @example 82 | * ```ts 83 | * app.getUserInfoByExtId(1).then((res) => console.log(res)) // res = UserAttributes 84 | * ``` 85 | */ 86 | public getUserInfoByExtId = async ( 87 | userId: string, 88 | options?: UserIncludeInput 89 | ): Promise => { 90 | return this.application.request( 91 | 'GET', 92 | null, 93 | 'attributes', 94 | `/api/application/users/external/${userId}${makeOptions({ 95 | includes: { ...options } 96 | })}` 97 | ); 98 | }; 99 | /** 100 | * @param username - The username of the user 101 | * @param firstName - The first name of the user 102 | * @param lastName - The last name of the user 103 | * @param email - The email address of the user 104 | * @param password - The password of the user 105 | * @param isAdmin - Is the user admin (default false) 106 | * @param language - The language of the user (default en) 107 | * @param externalId - The external id of user 108 | * @param options - Include information about relationships 109 | * @returns User information 110 | * @example 111 | * ```ts 112 | * const res = await app.createUser('linux123123', 'Linus', 'ADMIN', 'api@gmail.com') // res = UserAttributes 113 | * ``` 114 | * @example 115 | * ```ts 116 | * app.createUser('linux123123', 'Linus', 'ADMIN', 'api@gmail.com').then((res) => console.log(res)) // res = UserAttributes 117 | * ``` 118 | */ 119 | public createUser = async ( 120 | username: string, 121 | firstName: string, 122 | lastName: string, 123 | email: string, 124 | password = '', 125 | isAdmin = false, 126 | language = 'en', 127 | externalId?: string 128 | ): Promise => { 129 | return this.application.request( 130 | 'POST', 131 | { 132 | email: email, 133 | username: username, 134 | first_name: firstName, 135 | last_name: lastName, 136 | language: language, 137 | root_admin: isAdmin, 138 | password: password, 139 | external_id: externalId ? externalId : '' 140 | }, 141 | 'attributes', 142 | `/api/application/users` 143 | ); 144 | }; 145 | /** 146 | * @param userId - The user id of the user to edit 147 | * @param options - Options to edit user 148 | * @returns User information 149 | * @example 150 | * ```ts 151 | * const res = await app.editUser(1, 'linux123123', undefined, 'ADMIN_LAST) // res = UserAttributes 152 | * ``` 153 | * @example 154 | * ```ts 155 | * app.editUser(1, undefined, 'Linux').then((res) => console.log(res)) // res = UserAttributes 156 | * ``` 157 | */ 158 | public editUser = async ( 159 | userId: number, 160 | options: EditUserOptions 161 | ): Promise => { 162 | const user = await this.getUserInfo(userId); 163 | return this.application.request( 164 | 'PATCH', 165 | { 166 | email: options.email ?? user.email, 167 | username: options.username ?? user.username, 168 | first_name: options.firstName ?? user.first_name, 169 | last_name: options.lastName ?? user.last_name, 170 | language: options.language ?? user.language, 171 | root_admin: options.isAdmin ?? user.root_admin, 172 | password: options.password ?? '', 173 | external_id: options.externalId ?? user.external_id 174 | }, 175 | 'attributes', 176 | `/api/application/users/${userId}${makeOptions({ 177 | includes: { ...options.options } 178 | })}` 179 | ); 180 | }; 181 | /** 182 | * @param userId - The user id of the user to delete 183 | * @returns If successful returns Successfully deleted! 184 | * @example 185 | * ```ts 186 | * const res = await app.deleteUser(1) // res = Successfully deleted! 187 | * ``` 188 | * @example 189 | * ```ts 190 | * app.deleteUser(1).then((res) => console.log(res)) // res = Successfully deleted! 191 | * ``` 192 | */ 193 | public deleteUser = async (userId: number): Promise => { 194 | return this.application.request( 195 | 'DELETE', 196 | null, 197 | 'Successfully deleted!', 198 | `/api/application/users/${userId}` 199 | ); 200 | }; 201 | } 202 | -------------------------------------------------------------------------------- /src/client/Websocket.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientWebsocket */ 2 | 3 | import { EventEmitter } from 'node:events'; 4 | import { WebsocketAuthData } from './interfaces/WebsocketAuthData'; 5 | import { JSPteroAPIError } from '../modules/Error'; 6 | import { Socket } from '../modules/Socket'; 7 | 8 | const reconnectErrors = [ 9 | 'jwt: exp claim is invalid', 10 | 'jwt: created too far in past (denylist)' 11 | ]; 12 | 13 | export class WebsocketClient extends EventEmitter { 14 | constructor( 15 | errorHandler: (error: JSPteroAPIError) => void, 16 | auth: WebsocketAuthData, 17 | private getToken: () => Promise 18 | ) { 19 | super(); 20 | // Allow 100 listeners for this instance 21 | this.setMaxListeners(100); 22 | this.updateToken = (( 23 | getToken: () => Promise, 24 | socket: WebsocketClient 25 | ) => { 26 | if (this.isUpdating) { 27 | return; 28 | } 29 | 30 | this.isUpdating = true; 31 | 32 | try { 33 | getToken().then((data) => socket.setToken(data.token)); 34 | } catch (e) { 35 | if (e instanceof JSPteroAPIError) { 36 | if ( 37 | e.ERRORS[0] === 38 | 'This server is currently suspended and the functionality requested is unavailable.' 39 | ) { 40 | return this.close(409, 'Suspended'); 41 | } 42 | return errorHandler(e); 43 | } 44 | throw e; 45 | } 46 | }).bind(undefined, this.getToken, this); 47 | 48 | this.setToken(auth.token).connect(auth.socket); 49 | 50 | // Set listerners 51 | this.on('daemon error', (message) => { 52 | console.error(message); 53 | }); 54 | 55 | this.on('token expiring', () => this.updateToken()); 56 | this.on('token expired', () => this.updateToken()); 57 | this.on('jwt error', (error: string) => { 58 | if (reconnectErrors.find((v) => error.toLowerCase().indexOf(v) >= 0)) { 59 | this.updateToken(); 60 | } else { 61 | throw new Error(error); 62 | } 63 | }); 64 | this.on('transfer status', (status: string) => { 65 | if (status === 'starting' || status === 'success') { 66 | return; 67 | } 68 | 69 | // This code forces a reconnection to the websocket which will connect us to the target node instead of the source node 70 | // in order to be able to receive transfer logs from the target node. 71 | this.close(); 72 | this.open(); 73 | }); 74 | } 75 | 76 | private isUpdating = false; 77 | 78 | // Timer instance for this socket. 79 | private timer!: NodeJS.Timeout; 80 | 81 | // The backoff for the timer, in milliseconds. 82 | private backoff = 5000; 83 | 84 | // The socket instance being tracked. 85 | private socket: Socket | null = null; 86 | 87 | // The URL being connected to for the socket. 88 | private url: string | null = null; 89 | 90 | // The authentication token passed along with every request to the Daemon. 91 | // By default this token expires every 15 minutes and must therefore be 92 | // refreshed at a pretty continuous interval. The socket server will respond 93 | // with "token expiring" and "token expired" events when approaching 3 minutes 94 | // and 0 minutes to expiry. 95 | private token = ''; 96 | 97 | // Connects to the websocket instance and sets the token for the initial request. 98 | private connect(url: string): this { 99 | this.url = url; 100 | 101 | this.timer && clearTimeout(this.timer); 102 | 103 | // Close socket if needed 104 | if (this.socket?.ws.OPEN) { 105 | this.close(); 106 | } 107 | 108 | this.socket = new Socket(this.url, { 109 | onmessage: (e) => { 110 | try { 111 | const { event, args } = JSON.parse(e.data.toString()); 112 | args ? this.emit(event, ...args) : this.emit(event); 113 | } catch (ex) { 114 | console.warn('Failed to parse incoming websocket message.', ex); 115 | } 116 | }, 117 | onopen: () => { 118 | // Clear the timers, we managed to connect just fine. 119 | this.timer && clearTimeout(this.timer); 120 | this.backoff = 5000; 121 | 122 | this.emit('SOCKET_OPEN'); 123 | this.authenticate(); 124 | }, 125 | onreconnect: () => { 126 | this.emit('SOCKET_RECONNECT'); 127 | this.authenticate(); 128 | }, 129 | onclose: () => this.emit('SOCKET_CLOSE'), 130 | onerror: (event) => { 131 | if ( 132 | event.message === 133 | 'WebSocket was closed before the connection was established' 134 | ) 135 | return; 136 | throw new Error(event.message); 137 | }, 138 | onmaximum: () => { 139 | return; 140 | } 141 | }); 142 | 143 | this.timer = setTimeout(() => { 144 | this.backoff = this.backoff + 2500 >= 20000 ? 20000 : this.backoff + 2500; 145 | this.socket && this.socket.close(undefined, 'timeout'); 146 | clearTimeout(this.timer); 147 | 148 | // Re-attempt connecting to the socket. 149 | this.connect(url); 150 | }, this.backoff); 151 | 152 | return this; 153 | } 154 | 155 | private updateToken!: () => void; 156 | 157 | // Sets the authentication token to use when sending commands back and forth 158 | // between the websocket instance. 159 | private setToken(token: string, isUpdate = false): this { 160 | this.token = token; 161 | 162 | if (isUpdate) { 163 | this.authenticate(); 164 | } 165 | 166 | return this; 167 | } 168 | 169 | private authenticate(): void { 170 | if (this.url && this.token) { 171 | this.send('auth', this.token); 172 | } 173 | } 174 | 175 | public close(code?: number, reason?: string): void { 176 | this.url = null; 177 | this.token = ''; 178 | this.socket && this.socket.close(code, reason); 179 | } 180 | 181 | private open(): void { 182 | this.socket && this.socket.open(); 183 | } 184 | 185 | public send(event: string, payload?: string | string[]): void { 186 | this.socket && 187 | this.socket.send( 188 | JSON.stringify({ 189 | event, 190 | args: Array.isArray(payload) ? payload : [payload] 191 | }) 192 | ); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/client/index.ts: -------------------------------------------------------------------------------- 1 | import { Request } from '../modules/Request'; 2 | import { serverMethods } from './methods/server'; 3 | import { consoleMethods } from './methods/console'; 4 | import { fileMethods } from './methods/file'; 5 | import { databaseMethods } from './methods/database'; 6 | import { accountMethods } from './methods/account'; 7 | import { scheduleMethods } from './methods/schedule'; 8 | import { JSPteroAPIError } from '../modules/Error'; 9 | import { networkMethods } from './methods/network'; 10 | import { subUserMethods } from './methods/subUser'; 11 | import { backupMethods } from './methods/backups'; 12 | import { settingsMethods } from './methods/settings'; 13 | 14 | class Client { 15 | /** 16 | * @param host - Panels address 17 | * @param key - Api key to use 18 | * @param errorHandler - A custom function to handle errors 19 | * @param fast - Fast login (No credential check) 20 | */ 21 | public constructor( 22 | private host: string, 23 | private key: string, 24 | private errorHandler = (error: JSPteroAPIError): void => { 25 | throw error; 26 | }, 27 | fast = false 28 | ) { 29 | host = host.trim(); 30 | if (host.endsWith('/')) host = host.slice(0, -1); 31 | this.host = host; 32 | this.request = new Request(this.host, this.key, this.errorHandler).request; 33 | // Server 34 | const servermethods = new serverMethods(this); 35 | this.getAllServers = servermethods.getAllServers; 36 | this.getServerInfo = servermethods.getServerInfo; 37 | this.getServerResources = servermethods.getServerResources; 38 | this.sendCommand = servermethods.sendCommand; 39 | this.setPowerState = servermethods.setPowerState; 40 | // Console 41 | const consolemethods = new consoleMethods(this, this.errorHandler); 42 | this.startConsoleConnection = consolemethods.startConsoleConnection; 43 | // File 44 | const filemethods = new fileMethods(this); 45 | this.getAllFiles = filemethods.getAllFiles; 46 | this.getFileContents = filemethods.getFileContents; 47 | this.writeFile = filemethods.writeFile; 48 | this.renameFile = filemethods.renameFile; 49 | this.copyFile = filemethods.copyFile; 50 | this.getFileDownloadLink = filemethods.getFileDownloadLink; 51 | this.compressFile = filemethods.compressFile; 52 | this.decompressFile = filemethods.decompressFile; 53 | this.deleteFile = filemethods.deleteFile; 54 | this.createFolder = filemethods.createFolder; 55 | this.getFileUploadLink = filemethods.getFileUploadLink; 56 | // Database 57 | const databasemethods = new databaseMethods(this); 58 | this.getAllDatabases = databasemethods.getAllDatabases; 59 | this.createDatabase = databasemethods.createDatabase; 60 | this.deleteDatabase = databasemethods.deleteDatabase; 61 | this.rotateDatabasePass = databasemethods.rotateDatabasePass; 62 | // Account 63 | const accountmethods = new accountMethods(this); 64 | this.getAllPermissions = accountmethods.getAllPermissions; 65 | this.getAccountInfo = accountmethods.getAccountInfo; 66 | this.getAccount2FADetails = accountmethods.getAccount2FADetails; 67 | this.enable2FA = accountmethods.enable2FA; 68 | this.updateEmail = accountmethods.updateEmail; 69 | this.updatePassword = accountmethods.updatePassword; 70 | this.getAllApiKeys = accountmethods.getAllApiKeys; 71 | this.createApiKey = accountmethods.createApiKey; 72 | this.deleteApiKey = accountmethods.deleteApiKey; 73 | // Schedule 74 | const schedulemethods = new scheduleMethods(this); 75 | this.getAllSchedules = schedulemethods.getAllSchedules; 76 | this.createSchedule = schedulemethods.createSchedule; 77 | this.getScheduleInfo = schedulemethods.getScheduleInfo; 78 | this.editSchedule = schedulemethods.editSchedule; 79 | // Network 80 | const networkmethods = new networkMethods(this); 81 | this.getAllAlocations = networkmethods.getAllAlocations; 82 | this.assignAllocation = networkmethods.assignAllocation; 83 | this.setAllocationNote = networkmethods.setAllocationNote; 84 | this.setAllocationPrimary = networkmethods.setAllocationPrimary; 85 | this.deleteAllocation = networkmethods.deleteAllocation; 86 | // SubUsers 87 | const subusermethods = new subUserMethods(this); 88 | this.getAllSubUsers = subusermethods.getAllSubUsers; 89 | this.createSubUser = subusermethods.createSubUser; 90 | this.getSubUserInfo = subusermethods.getSubUserInfo; 91 | this.updateSubUserPermissions = subusermethods.updateSubUserPermissions; 92 | this.deleteSubUser = subusermethods.deleteSubUser; 93 | // Backups 94 | const backupmethods = new backupMethods(this); 95 | this.getAllBackups = backupmethods.getAllBackups; 96 | this.createBackup = backupmethods.createBackup; 97 | this.getBackupInfo = backupmethods.getBackupInfo; 98 | this.getBackupDownloadLink = backupmethods.getBackupDownloadLink; 99 | this.deleteBackup = backupmethods.deleteBackup; 100 | this.toggleLockBackup = backupmethods.toggleLockBackup; 101 | this.restoreBackup = backupmethods.restoreBackup; 102 | // Settings 103 | const settingsmethods = new settingsMethods(this); 104 | this.renameServer = settingsmethods.renameServer; 105 | this.reinstallServer = settingsmethods.reinstallServer; 106 | 107 | if (!fast) this.testAPI(); 108 | } 109 | /** 110 | * @param throwError - Whether to throw an error or return bool 111 | * @remarks Will not work if using custom error handler. 112 | */ 113 | public testAPI = async (throwError = true): Promise => { 114 | try { 115 | await this.getAllServers(); 116 | return true; 117 | } catch (e) { 118 | if (e instanceof JSPteroAPIError) { 119 | if (throwError) { 120 | if (e.HTML_STATUS === 403) e.ERRORS = ['Invalid Client API key']; 121 | throw e; 122 | } 123 | return false; 124 | } else { 125 | if (throwError) throw e; 126 | return false; 127 | } 128 | } 129 | }; 130 | 131 | /** 132 | @internal 133 | */ 134 | public request; 135 | 136 | // Get 137 | public getAllServers; 138 | public getServerInfo; 139 | public getServerResources; 140 | public getAllPermissions; 141 | public getAllDatabases; 142 | public getAllFiles; 143 | public getFileContents; 144 | public getFileDownloadLink; 145 | public getFileUploadLink; 146 | public getAccountInfo; 147 | public getAccount2FADetails; 148 | public getAllApiKeys; 149 | public getAllSchedules; 150 | public getScheduleInfo; 151 | public getAllAlocations; 152 | public getAllSubUsers; 153 | public getSubUserInfo; 154 | public getAllBackups; 155 | public getBackupInfo; 156 | public getBackupDownloadLink; 157 | // POST 158 | public sendCommand; 159 | public setPowerState; 160 | public createDatabase; 161 | public rotateDatabasePass; 162 | public copyFile; 163 | public writeFile; 164 | public compressFile; 165 | public decompressFile; 166 | public deleteFile; 167 | public createFolder; 168 | public enable2FA; 169 | public createApiKey; 170 | public createSchedule; 171 | public editSchedule; 172 | public assignAllocation; 173 | public setAllocationNote; 174 | public setAllocationPrimary; 175 | public createSubUser; 176 | public updateSubUserPermissions; 177 | public createBackup; 178 | public renameServer; 179 | public reinstallServer; 180 | public toggleLockBackup; 181 | public restoreBackup; 182 | // Delete 183 | public deleteDatabase; 184 | public deleteApiKey; 185 | public deleteAllocation; 186 | public deleteSubUser; 187 | public deleteBackup; 188 | // PUT 189 | public renameFile; 190 | public updateEmail; 191 | public updatePassword; 192 | 193 | public startConsoleConnection; 194 | } 195 | 196 | export { Client }; 197 | -------------------------------------------------------------------------------- /src/client/interfaces/Allocation.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientAllocation */ 2 | 3 | export interface Allocation { 4 | id: number; 5 | ip: string; 6 | alias: string | null; 7 | port: number; 8 | notes: string | null; 9 | isDefault: boolean; 10 | } 11 | -------------------------------------------------------------------------------- /src/client/interfaces/ApiKey.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientApiKey */ 2 | 3 | export interface ApiKeyAttributes { 4 | identifier: string; 5 | description: string; 6 | allowed_ips: string[]; 7 | last_used_at: string | null; 8 | created_at: string; 9 | } 10 | 11 | export interface ApiKeyMeta { 12 | secret_token: string; 13 | } 14 | 15 | export interface ApiKey { 16 | object: 'api_key'; 17 | attributes: ApiKeyAttributes; 18 | meta?: ApiKeyMeta; 19 | } 20 | 21 | export interface ApiKeyList { 22 | object: 'list'; 23 | data: ApiKey[]; 24 | } 25 | -------------------------------------------------------------------------------- /src/client/interfaces/Backups.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientBackup */ 2 | 3 | export interface BackupAttributes { 4 | uuid: string; 5 | name: string; 6 | ignored_files: string[]; 7 | checksum: string; 8 | bytes: number; 9 | created_at: string; 10 | completed_at: string; 11 | is_successful: boolean; 12 | is_locked: boolean; 13 | } 14 | 15 | export interface Backup { 16 | object: 'backup'; 17 | attributes: BackupAttributes; 18 | } 19 | 20 | export interface Backups { 21 | object: 'list'; 22 | data: Backup[]; 23 | meta: { 24 | pagination: { 25 | total: number; 26 | count: number; 27 | per_page: number; 28 | current_page: number; 29 | total_pages: number; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/client/interfaces/Database.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientDatabase */ 2 | export interface DatabaseIncludeInput { 3 | password?: boolean; 4 | } 5 | 6 | export interface DatabaseAttributesHost { 7 | address: string; 8 | port: number; 9 | } 10 | 11 | export interface DatabaseAttributes { 12 | id: string; 13 | host: DatabaseAttributesHost; 14 | name: string; 15 | username: string; 16 | connections_from: string; 17 | max_connections: number; 18 | relationships?: DatabaseRelationships; 19 | } 20 | export interface DatabaseRelationships { 21 | password: DatabasePassword; 22 | } 23 | 24 | export interface DatabasePassword { 25 | object: string; 26 | attributes: DatabasePasswordAttributes; 27 | } 28 | 29 | export interface DatabasePasswordAttributes { 30 | password: string; 31 | } 32 | 33 | export interface Database { 34 | object: string; 35 | attributes: DatabaseAttributes; 36 | } 37 | -------------------------------------------------------------------------------- /src/client/interfaces/Permissions.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientPermissions */ 2 | export interface Permissions { 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 4 | permissions: Record; 5 | } 6 | -------------------------------------------------------------------------------- /src/client/interfaces/Schedule.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientSchedule */ 2 | 3 | export interface ScheduleCron { 4 | day_of_week: string; 5 | day_of_month: string; 6 | hour: string; 7 | month: string; 8 | minute: string; 9 | } 10 | 11 | export interface ScheduleTaskAttributes { 12 | id: number; 13 | sequence_id: number; 14 | action: string; 15 | payload: string; 16 | time_offset: number; 17 | is_queued: boolean; 18 | continue_on_failure: boolean; 19 | created_at: string; 20 | updated_at: string; 21 | } 22 | 23 | export interface ScheduleTask { 24 | object: 'schedule_task'; 25 | attributes: ScheduleTaskAttributes; 26 | } 27 | 28 | export interface ScheduleTasks { 29 | object: string; 30 | data: ScheduleTask[]; 31 | } 32 | 33 | export interface ScheduleRelationships { 34 | tasks: ScheduleTasks; 35 | } 36 | 37 | export interface ScheduleAttributes { 38 | id: number; 39 | name: string; 40 | cron: ScheduleCron; 41 | is_active: boolean; 42 | is_processing: boolean; 43 | last_run_at: string | null; 44 | next_run_at: string; 45 | created_at: string; 46 | updated_at: string; 47 | relationships: ScheduleRelationships; 48 | } 49 | 50 | export interface Schedule { 51 | object: 'server_schedule'; 52 | attributes: ScheduleAttributes; 53 | } 54 | 55 | export interface ScheduleList { 56 | object: 'list'; 57 | data: Schedule[]; 58 | } 59 | 60 | export interface SheduleEditOptions { 61 | /** Schedule name */ 62 | name?: string; 63 | /** Cron minute syntax */ 64 | minute?: string; 65 | /** Cron hour syntax */ 66 | hour?: string; 67 | /** Cron day of month syntax */ 68 | dayOfMonth?: string; 69 | /** Cron month syntax */ 70 | month?: string; 71 | /** Cron day of week syntax */ 72 | dayOfWeek?: string; 73 | /** Whether the schedule should be activated on creation */ 74 | isActive?: boolean; 75 | } 76 | 77 | export interface TaskEditOptions { 78 | /** Action that the schedule should perform (command/power/backup) */ 79 | action?: 'command' | 'power' | 'backup'; 80 | /** What that action should do. Command or power (start/stop/restart/kill). Backup payload is ignored file list. */ 81 | payload?: string; 82 | /** The time offset that the task should run after the schdule is triggered. */ 83 | timeOffset?: number; 84 | /** Should the task continue to work on failure. */ 85 | continueOnFailure?: boolean; 86 | } 87 | -------------------------------------------------------------------------------- /src/client/interfaces/Server.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientServer */ 2 | export interface ServerSftpDetails { 3 | ip: string; 4 | port: number; 5 | } 6 | 7 | export interface ServerIncludeInput { 8 | egg?: boolean; 9 | subusers?: boolean; 10 | } 11 | 12 | export interface ServerFilterInput { 13 | filter: string; 14 | filterBy: 'uuid' | 'name' | 'external_id' | '*'; 15 | } 16 | 17 | export interface ServerLimits { 18 | memory: number; 19 | swap: number; 20 | disk: number; 21 | io: number; 22 | cpu: number; 23 | } 24 | 25 | export interface ServerFeatureLimits { 26 | databases: number; 27 | allocations: number; 28 | backups: number; 29 | } 30 | 31 | export interface ServerEggAttributes { 32 | uuid: string; 33 | name: string; 34 | } 35 | 36 | export interface ServerEgg { 37 | object: string; 38 | attributes: ServerEggAttributes; 39 | } 40 | 41 | export interface ServerSubuserAttributes { 42 | 'uuid': string; 43 | 'username': string; 44 | 'email': string; 45 | 'image': string; 46 | '2fa_enabled': boolean; 47 | 'created_at': string; 48 | 'permissions': string[]; 49 | } 50 | 51 | export interface ServerSubuser { 52 | object: string; 53 | attributes: ServerSubuserAttributes; 54 | } 55 | 56 | export interface ServerSubusers { 57 | object: string; 58 | data: ServerSubuser[]; 59 | } 60 | 61 | export interface ServerRelationships { 62 | allocations: ServerAllocations; 63 | variables: ServerVariables; 64 | egg?: ServerEgg; 65 | subusers?: ServerSubusers; 66 | } 67 | 68 | export interface ServerAllocations { 69 | object: string; 70 | data: ServerAllocation[]; 71 | } 72 | 73 | export interface ServerAllocation { 74 | object: string; 75 | attributes: ServerAllocationAttributes; 76 | } 77 | 78 | export interface ServerAllocationAttributes { 79 | id: number; 80 | ip: string; 81 | ip_alias: string; 82 | port: number; 83 | notes: string; 84 | is_default: boolean; 85 | } 86 | 87 | export interface ServerVariables { 88 | object: string; 89 | data: ServerVariable[]; 90 | } 91 | 92 | export interface ServerVariable { 93 | object: string; 94 | attributes: ServerVariableAttributes; 95 | } 96 | 97 | export interface ServerVariableAttributes { 98 | name: string; 99 | description: string; 100 | env_variable: string; 101 | default_value: string; 102 | server_value: string; 103 | is_editable: boolean; 104 | rules: string; 105 | } 106 | 107 | export interface ServerAttributes { 108 | server_owner: boolean; 109 | identifier: string; 110 | internal_id: number; 111 | uuid: string; 112 | name: string; 113 | node: string; 114 | sftp_details: ServerSftpDetails; 115 | description: string; 116 | limits: ServerLimits; 117 | invocation: string; 118 | docker_image: string; 119 | egg_features: unknown; 120 | feature_limits: ServerFeatureLimits; 121 | is_suspended: boolean; 122 | is_installing: boolean; 123 | is_transferring: boolean; 124 | relationships: ServerRelationships; 125 | } 126 | 127 | export interface Server { 128 | object: string; 129 | attributes: ServerAttributes; 130 | } 131 | 132 | export interface Servers { 133 | object: string; 134 | data: Server[]; 135 | meta: { 136 | pagination: { 137 | total: number; 138 | count: number; 139 | per_page: number; 140 | current_page: number; 141 | total_pages: number; 142 | }; 143 | }; 144 | } 145 | -------------------------------------------------------------------------------- /src/client/interfaces/ServerFile.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientServerFiles */ 2 | export interface SeverFileRenameFiles { 3 | from: string; 4 | to: string; 5 | } 6 | 7 | export interface SeverFileRename { 8 | root: string; 9 | files: SeverFileRenameFiles[]; 10 | } 11 | 12 | export interface ServerFileCompress { 13 | root: string; 14 | files: string[]; 15 | } 16 | 17 | export type ServerFileDelete = ServerFileCompress; 18 | 19 | export interface ServerFileDecompress { 20 | root: string; 21 | file: string; 22 | } 23 | 24 | export interface ServerFileCreateFolder { 25 | root: string; 26 | name: string; 27 | } 28 | 29 | export interface ServerFileAttributes { 30 | name: string; 31 | mode: string; 32 | mode_bits: string; 33 | size: number; 34 | is_file: boolean; 35 | is_symlink: boolean; 36 | mimetype: string; 37 | created_at: string; 38 | modified_at: string; 39 | } 40 | 41 | export interface ServerFile { 42 | object: string; 43 | attributes: ServerFileAttributes; 44 | } 45 | -------------------------------------------------------------------------------- /src/client/interfaces/ServerResources.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientServerResources */ 2 | export interface ServerResource { 3 | memory_bytes: number; 4 | cpu_absolute: number; 5 | disk_bytes: number; 6 | network_rx_bytes: number; 7 | network_tx_bytes: number; 8 | } 9 | 10 | export interface ServerResources { 11 | current_state: string; 12 | is_suspended: boolean; 13 | resources: ServerResource; 14 | } 15 | -------------------------------------------------------------------------------- /src/client/interfaces/SubUser.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientSubUser */ 2 | 3 | export type SubuserPermission = 4 | | 'websocket.connect' 5 | | 'control.console' 6 | | 'control.start' 7 | | 'control.stop' 8 | | 'control.restart' 9 | | 'user.create' 10 | | 'user.read' 11 | | 'user.update' 12 | | 'user.delete' 13 | | 'file.create' 14 | | 'file.read' 15 | | 'file.update' 16 | | 'file.delete' 17 | | 'file.archive' 18 | | 'file.sftp' 19 | | 'allocation.read' 20 | | 'allocation.update' 21 | | 'startup.read' 22 | | 'startup.update' 23 | | 'database.create' 24 | | 'database.read' 25 | | 'database.update' 26 | | 'database.delete' 27 | | 'database.view_password' 28 | | 'schedule.create' 29 | | 'schedule.read' 30 | | 'schedule.update' 31 | | 'schedule.delete'; 32 | 33 | export interface SubUserAttributes { 34 | 'uuid': string; 35 | 'username': string; 36 | 'email': string; 37 | 'image': string; 38 | '2fa_enabled': boolean; 39 | 'created_at': string; 40 | 'permissions': SubuserPermission[]; 41 | } 42 | 43 | export interface SubUser { 44 | object: 'server_subuser'; 45 | attributes: SubUserAttributes; 46 | } 47 | -------------------------------------------------------------------------------- /src/client/interfaces/User.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientUser */ 2 | export interface UserAttributes { 3 | id: number; 4 | admin: boolean; 5 | username: string; 6 | email: string; 7 | first_name: string; 8 | last_name: string; 9 | language: string; 10 | } 11 | 12 | export interface User { 13 | object: 'user'; 14 | attributes: UserAttributes; 15 | } 16 | -------------------------------------------------------------------------------- /src/client/interfaces/WebsocketAuthData.ts: -------------------------------------------------------------------------------- 1 | /** @module ClientWebsocketAuthData */ 2 | export interface WebsocketAuthData { 3 | token: string; 4 | socket: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/client/methods/account.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { ApiKey } from '../interfaces/ApiKey'; 3 | import { Permissions } from '../interfaces/Permissions'; 4 | import { UserAttributes } from '../interfaces/User'; 5 | 6 | export class accountMethods { 7 | constructor(private readonly client: Client) {} 8 | /** 9 | * @returns Permission data 10 | * @remarks Just returns all available permissions. Not that useful! 11 | * @example 12 | * ```ts 13 | * const res = await client.getPermissions() // res = Permissions 14 | * ``` 15 | * @example 16 | * ```ts 17 | * client.getPermissions().then((res) => console.log(res)) // res = Permissions 18 | * ``` 19 | */ 20 | public getAllPermissions = async (): Promise => { 21 | return this.client.request( 22 | 'GET', 23 | null, 24 | 'attributes', 25 | `/api/client/permissions` 26 | ); 27 | }; 28 | /** 29 | * @returns Account information 30 | * @example 31 | * ```ts 32 | * const res = await client.getAccountInfo() // res = UserAttributes 33 | * ``` 34 | * @example 35 | * ```ts 36 | * client.getAccountInfo().then((res) => console.log(res)) // res = UserAttributes 37 | * ``` 38 | */ 39 | public getAccountInfo = (): Promise => { 40 | return this.client.request( 41 | 'GET', 42 | null, 43 | 'attributes', 44 | `/api/client/account` 45 | ); 46 | }; 47 | /** 48 | * @returns TOTP QR code image url (otpauth) 49 | * ```ts 50 | * const res = await client.getAccountInfo() // res = string (otpauth) 51 | * ``` 52 | * @example 53 | * ```ts 54 | * client.getAccountInfo().then((res) => console.log(res)) // res = string (otpauth) 55 | * ``` 56 | */ 57 | public getAccount2FADetails = async (): Promise => { 58 | return this.client.request( 59 | 'GET', 60 | null, 61 | 'data.image_url_data', 62 | `/api/client/account/two-factor` 63 | ); 64 | }; 65 | /** 66 | * @param code - The code from authenticator 67 | * @returns Tokens 68 | * ```ts 69 | * const res = await client.enable2FA('505134') // res = string[] (tokens) 70 | * ``` 71 | * @example 72 | * ```ts 73 | * client.enable2FA('505134').then((res) => console.log(res)) // res = string[] (tokens) 74 | * ``` 75 | */ 76 | public enable2FA = async (code: string): Promise => { 77 | return this.client.request( 78 | 'POST', 79 | { 80 | code: code 81 | }, 82 | 'attributes.tokens', 83 | `/api/client/account/two-factor` 84 | ); 85 | }; 86 | /** 87 | * @param password - The code from authenticator 88 | * @returns If succesful returns Successfully disable 2FA! 89 | * ```ts 90 | * const res = await client.disable2FA('securepassword') // res = Successfully disable 2FA! 91 | * ``` 92 | * @example 93 | * ```ts 94 | * client.disable2FA('securepassword').then((res) => console.log(res)) // res = Successfully disable 2FA! 95 | * ``` 96 | */ 97 | public disable2FA = async (password: string): Promise => { 98 | return this.client.request( 99 | 'DELETE', 100 | { 101 | password: password 102 | }, 103 | 'Successfully disable 2FA!', 104 | `/api/client/account/two-factor` 105 | ); 106 | }; 107 | /** 108 | * @param email - The new email address 109 | * @param password - The password of the user 110 | * @returns If succesful returns Successfully updated email! 111 | * ```ts 112 | * const res = await client.updateEmail('jspteroapi@linux123123.cf', 'verySecurePass') // res = Successfully updated email! 113 | * ``` 114 | * @example 115 | * ```ts 116 | * client.updateEmail('jspteroapi@linux123123.cf', 'verySecurePass').then((res) => console.log(res)) // res = Successfully updated email! 117 | * ``` 118 | */ 119 | public updateEmail = async ( 120 | email: string, 121 | password: string 122 | ): Promise => { 123 | return this.client.request( 124 | 'PUT', 125 | { 126 | email: email, 127 | password: password 128 | }, 129 | 'Successfully updated email!', 130 | `/api/client/account/email` 131 | ); 132 | }; 133 | /** 134 | * @param currentPassword - The currect passowrd 135 | * @param password - The new password 136 | * @returns If succesful returns Successfully updated password! 137 | * ```ts 138 | * const res = await client.updatePassword('verySecurePass', 'moreSecurePass') // res = Successfully updated password! 139 | * ``` 140 | * @example 141 | * ```ts 142 | * client.updatePassword('verySecurePass', 'moreSecurePass').then((res) => console.log(res)) // res = Successfully updated password! 143 | * ``` 144 | */ 145 | public updatePassword = async ( 146 | currentPassword: string, 147 | password: string 148 | ): Promise => { 149 | return this.client.request( 150 | 'PUT', 151 | { 152 | current_password: currentPassword, 153 | password: password, 154 | password_confirmation: password 155 | }, 156 | 'Successfully updated password!', 157 | `/api/client/account/password` 158 | ); 159 | }; 160 | /** 161 | * @returns Api key array 162 | * @example 163 | * ```ts 164 | * const res = await client.getAllApiKeys() // res = ApiKey[] 165 | * ``` 166 | * @example 167 | * ```ts 168 | * client.getAllApiKeys().then((res) => console.log(res)) // res = ApiKey[] 169 | * ``` 170 | */ 171 | public getAllApiKeys = async (): Promise => { 172 | return this.client.request( 173 | 'GET', 174 | null, 175 | 'data', 176 | `/api/client/account/api-keys` 177 | ); 178 | }; 179 | /** 180 | * @param description - Api key description 181 | * @param allowedIps - Array of allowed IP addresses (default empty []) 182 | * @returns The new api key information + meta (token) 183 | * ```ts 184 | * const res = await client.createApiKey('TESTING', []) // res = ApiKey + meta (token) 185 | * ``` 186 | * @example 187 | * ```ts 188 | * client.createApiKey('TESTING', []).then((res) => console.log(res)) // res = ApiKey + meta (token) 189 | * ``` 190 | */ 191 | public createApiKey = async ( 192 | description: string, 193 | allowedIps: string[] = [] 194 | ): Promise => { 195 | return this.client.request( 196 | 'POST', 197 | { 198 | description: description, 199 | allowed_ips: allowedIps 200 | }, 201 | '', 202 | `/api/client/account/api-keys` 203 | ); 204 | }; 205 | /** 206 | * @param apiKeyIden - The api keys identifier code 207 | * @returns If succesful returns Successfully deleted api key! 208 | * ```ts 209 | * const res = await client.deleteApiKey('NWKMYMT2Mrav0Iq2') // res = Successfully deleted api key! 210 | * ``` 211 | * @example 212 | * ```ts 213 | * client.deleteApiKey('NWKMYMT2Mrav0Iq2').then((res) => console.log(res)) // res = Successfully deleted api key! 214 | * ``` 215 | */ 216 | public deleteApiKey = async (apiKeyIden: string): Promise => { 217 | return this.client.request( 218 | 'DELETE', 219 | null, 220 | 'Successfully deleted api key!', 221 | `/api/client/account/api-keys/${apiKeyIden}` 222 | ); 223 | }; 224 | } 225 | -------------------------------------------------------------------------------- /src/client/methods/backups.ts: -------------------------------------------------------------------------------- 1 | import { Backup, BackupAttributes, Backups } from 'client/interfaces/Backups'; 2 | import { paginate } from '../../modules/Functions'; 3 | import { Client } from '../index'; 4 | 5 | export class backupMethods { 6 | constructor(private readonly client: Client) {} 7 | /** 8 | * @internal 9 | */ 10 | private getBackups = async (serverId: string): Promise => { 11 | return this.client.request( 12 | 'GET', 13 | null, 14 | '', 15 | `/api/client/servers/${serverId}/backups` 16 | ); 17 | }; 18 | /** 19 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 20 | * @returns An array of backups 21 | * @example 22 | * ```ts 23 | * const res = await client.getAllBackups('7e74354d') // res = Backup[] 24 | * ``` 25 | * @example 26 | * ```ts 27 | * client.getAllBackups('7e74354d').then((res) => console.log(res)) // res = Backup[] 28 | * ``` 29 | */ 30 | public getAllBackups = async (serverId: string): Promise => { 31 | return await paginate(this.getBackups.bind(this, serverId), {}); 32 | }; 33 | /** 34 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 35 | * @param name - Name of the backup 36 | * @param ignored - Ignored files / folders 37 | * @returns Backup information 38 | * @example 39 | * ```ts 40 | * const res = await client.createBackup('7e74354d') // res = BackupAttributes 41 | * ``` 42 | * @example 43 | * ```ts 44 | * client.createBackup('7e74354d', 'RandomBackup').then((res) => console.log(res)) // res = BackupAttributes 45 | * ``` 46 | */ 47 | public createBackup = async ( 48 | serverId: string, 49 | name = '', 50 | ignored: string[] = [], 51 | isLocked = false 52 | ): Promise => { 53 | return this.client.request( 54 | 'POST', 55 | { 56 | name: name, 57 | ignored: ignored.join(' '), 58 | is_locked: isLocked 59 | }, 60 | 'attributes', 61 | `/api/client/servers/${serverId}/backups` 62 | ); 63 | }; 64 | /** 65 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 66 | * @param backupId - ID of the backup to get 67 | * @returns Backup information 68 | * @example 69 | * ```ts 70 | * const res = await client.getBackupInfo('7e74354d', '3a4e4b2a') // res = BackupAttributes 71 | * ``` 72 | * @example 73 | * ```ts 74 | * client.getBackupInfo('7e74354d', '3a4e4b2a').then((res) => console.log(res)) // res = BackupAttributes 75 | * ``` 76 | */ 77 | public getBackupInfo = async ( 78 | serverId: string, 79 | backupId: string 80 | ): Promise => { 81 | return this.client.request( 82 | 'GET', 83 | null, 84 | 'attributes', 85 | `/api/client/servers/${serverId}/backups/${backupId}` 86 | ); 87 | }; 88 | /** 89 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 90 | * @param backupId - ID of the backup to toggle lock of 91 | * @returns Backup information 92 | * @example 93 | * ```ts 94 | * const res = await client.toggleLockBackup('7e74354d', '3a4e4b2a') // res = BackupAttributes 95 | * ``` 96 | * @example 97 | * ```ts 98 | * client.toggleLockBackup('7e74354d', '3a4e4b2a').then((res) => console.log(res)) // res = BackupAttributes 99 | * ``` 100 | */ 101 | public toggleLockBackup = async ( 102 | serverId: string, 103 | backupId: string 104 | ): Promise => { 105 | return this.client.request( 106 | 'POST', 107 | null, 108 | 'attributes', 109 | `/api/client/servers/${serverId}/backups/${backupId}/lock` 110 | ); 111 | }; 112 | /** 113 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 114 | * @param backupId - ID of the backup to restore 115 | * @param truncate - Whether to remove all files before restoring backup 116 | * @returns Sucessfully restored backup 117 | * @example 118 | * ```ts 119 | * const res = await client.restoreBackup('7e74354d', '3a4e4b2a') // res = Sucessfully restored backup 120 | * ``` 121 | * @example 122 | * ```ts 123 | * client.restoreBackup('7e74354d', '3a4e4b2a').then((res) => console.log(res)) // res = Sucessfully restored backup 124 | * ``` 125 | */ 126 | public restoreBackup = async ( 127 | serverId: string, 128 | backupId: string, 129 | truncate = false 130 | ): Promise => { 131 | return this.client.request( 132 | 'POST', 133 | { truncate }, 134 | 'Sucessfully restored backup', 135 | `/api/client/servers/${serverId}/backups/${backupId}/restore` 136 | ); 137 | }; 138 | /** 139 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 140 | * @param backupId - ID of the backup to get 141 | * @returns Returns backup download url 142 | * @example 143 | * ```ts 144 | * const res = await client.getBackupDownloadLink('7e74354d', '3a4e4b2a') // res = url (string) 145 | * ``` 146 | * @example 147 | * ```ts 148 | * client.getBackupDownloadLink('7e74354d', '3a4e4b2a').then((res) => console.log(res)) // res = url (string) 149 | * ``` 150 | */ 151 | public getBackupDownloadLink = async ( 152 | serverId: string, 153 | backupId: string 154 | ): Promise => { 155 | return this.client.request( 156 | 'GET', 157 | null, 158 | 'attributes.url', 159 | `/api/client/servers/${serverId}/backups/${backupId}/download` 160 | ); 161 | }; 162 | /** 163 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 164 | * @param backupId - ID of the backup to delete 165 | * @returns Backup information 166 | * @example 167 | * ```ts 168 | * const res = await client.deleteBackup('7e74354d', '3a4e4b2a') // res = Backup successfully deleted! 169 | * ``` 170 | * @example 171 | * ```ts 172 | * client.deleteBackup('7e74354d', '3a4e4b2a').then((res) => console.log(res)) // res = Backup successfully deleted! 173 | * ``` 174 | */ 175 | public deleteBackup = async ( 176 | serverId: string, 177 | backupId: string 178 | ): Promise => { 179 | return this.client.request( 180 | 'DELETE', 181 | null, 182 | 'Backup successfully deleted!', 183 | `/api/client/servers/${serverId}/backups/${backupId}` 184 | ); 185 | }; 186 | } 187 | -------------------------------------------------------------------------------- /src/client/methods/console.ts: -------------------------------------------------------------------------------- 1 | import { JSPteroAPIError } from 'index'; 2 | import { Client } from '../index'; 3 | import { WebsocketAuthData } from '../interfaces/WebsocketAuthData'; 4 | import { WebsocketClient } from '../Websocket'; 5 | 6 | export class consoleMethods { 7 | constructor( 8 | private readonly client: Client, 9 | private readonly errorHandler: (error: JSPteroAPIError) => void 10 | ) {} 11 | /** 12 | * @internal 13 | */ 14 | private getWebsocketAuthData = async ( 15 | serverId: string 16 | ): Promise => { 17 | return this.client.request( 18 | 'GET', 19 | null, 20 | 'data', 21 | `/api/client/servers/${serverId}/websocket` 22 | ); 23 | }; 24 | /** 25 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 26 | * @remarks This method is used to connect to server websocket and have automatic authentication. This exposes the websocket client. 27 | * @returns WebsocketClient 28 | * @example 29 | * ```ts 30 | * const res = await client.startConsoleConnection('c2f5a3b6') // res = WebsocketClient 31 | * ``` 32 | * @example 33 | * ```ts 34 | * client.startConsoleConnection('c2f5a3b6').then((res) => console.log(res)) // res = WebsocketClient 35 | * ``` 36 | */ 37 | public startConsoleConnection = async ( 38 | serverId: string 39 | ): Promise => { 40 | const auth = await this.getWebsocketAuthData(serverId); 41 | return new WebsocketClient( 42 | this.errorHandler, 43 | auth, 44 | this.getWebsocketAuthData.bind(this, serverId) 45 | ); 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/client/methods/database.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { makeOptions } from '../../modules/Functions'; 3 | import { 4 | Database, 5 | DatabaseAttributes, 6 | DatabaseIncludeInput 7 | } from '../interfaces/Database'; 8 | 9 | export class databaseMethods { 10 | constructor(private readonly client: Client) {} 11 | /** 12 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 13 | * @param options - Include information about relationships 14 | * @returns Returns array of servers databases (Database[]) 15 | * @example 16 | * ```ts 17 | * const res = await client.getAllDatabases('c2f5a3b6') // res = Database[] 18 | * ``` 19 | * @example 20 | * ```ts 21 | * client.getAllDatabases('c2f5a3b6').then((res) => console.log(res)) // res = Database[] 22 | * ``` 23 | */ 24 | public getAllDatabases = async ( 25 | serverId: string, 26 | options?: DatabaseIncludeInput 27 | ): Promise => { 28 | return this.client.request( 29 | 'GET', 30 | null, 31 | 'data', 32 | `/api/client/servers/${serverId}/databases${makeOptions({ 33 | includes: { ...options } 34 | })}` 35 | ); 36 | }; 37 | /** 38 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 39 | * @param databaseName - Database name 40 | * @param connectionsAllowedFrom - Connections allowed from 41 | * @param options - Include information about relationships 42 | * @returns Returns new database information (DatabaseAttributes) 43 | * @example 44 | * ```ts 45 | * const res = await client.createDatabase('c2f5a3b6', 'Information') // res = DatabaseAttributes 46 | * ``` 47 | * @example 48 | * ```ts 49 | * client.createDatabase('c2f5a3b6', 'info').then((res) => console.log(res)) // res = DatabaseAttributes 50 | * ``` 51 | */ 52 | public createDatabase = async ( 53 | serverId: string, 54 | databaseName: string, 55 | connectionsAllowedFrom = '%', 56 | options?: DatabaseIncludeInput 57 | ): Promise => { 58 | return this.client.request( 59 | 'POST', 60 | { database: databaseName, remote: connectionsAllowedFrom }, 61 | 'attributes', 62 | `/api/client/servers/${serverId}/databases${makeOptions({ 63 | includes: { ...options } 64 | })}` 65 | ); 66 | }; 67 | /** 68 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 69 | * @param databaseId - Database id 70 | * @returns If successful returns Sucesfully deleted! 71 | * @example 72 | * ```ts 73 | * const res = await client.deleteDatabase('c2f5a3b6', 's5_info') // res = Sucesfully deleted! 74 | * ``` 75 | * @example 76 | * ```ts 77 | * client.deleteDatabase('c2f5a3b6', 's3_good').then((res) => console.log(res)) // res = Sucesfully deleted! 78 | * ``` 79 | */ 80 | public deleteDatabase = ( 81 | serverId: string, 82 | databaseId: string 83 | ): Promise => { 84 | return this.client.request( 85 | 'DELETE', 86 | null, 87 | 'Sucesfully deleted!', 88 | `/api/client/servers/${serverId}/databases/${databaseId}` 89 | ); 90 | }; 91 | /** 92 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 93 | * @param databaseId - Database id 94 | * @returns Returns database information + Relationships(password) 95 | * @example 96 | * ```ts 97 | * const res = await client.rotateDatabasePass('c2f5a3b6', 's5_info') // res = DatabaseAttributesRelationship 98 | * ``` 99 | * @example 100 | * ```ts 101 | * client.rotateDatabasePass('c2f5a3b6', 's3_good').then((res) => console.log(res)) // res = DatabaseAttributesRelationship 102 | * ``` 103 | */ 104 | public rotateDatabasePass = async ( 105 | serverId: string, 106 | databaseId: string 107 | ): Promise => { 108 | return this.client.request( 109 | 'POST', 110 | null, 111 | 'attributes', 112 | `/api/client/servers/${serverId}/databases/${databaseId}/rotate-password` 113 | ); 114 | }; 115 | } 116 | -------------------------------------------------------------------------------- /src/client/methods/file.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { 3 | ServerFile, 4 | ServerFileAttributes, 5 | ServerFileCompress, 6 | ServerFileCreateFolder, 7 | ServerFileDecompress, 8 | ServerFileDelete, 9 | SeverFileRename 10 | } from '../interfaces/ServerFile'; 11 | 12 | export class fileMethods { 13 | constructor(private readonly client: Client) {} 14 | /** 15 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 16 | * @param dir - Directory to get files from (if not provided gets root server dir) (e. g. dist or dist/classes) 17 | * @returns Array of file objects 18 | * @example 19 | * ```ts 20 | * const res = await client.getAllFiles('c2f5a3b6') // res = ServerFile[] 21 | * ``` 22 | * @example 23 | * ```ts 24 | * client.getAllFiles('c2f5a3b6', 'dist').then((res) => console.log(res)) // res = ServerFile[] 25 | * ``` 26 | */ 27 | public getAllFiles = (serverId: string, dir = ''): Promise => { 28 | return this.client.request( 29 | 'GET', 30 | null, 31 | 'data', 32 | `/api/client/servers/${serverId}/files/list?directory=%2F${dir}` 33 | ); 34 | }; 35 | /** 36 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 37 | * @param file - File to get the contents of (full name like index.js or dist/index.js) 38 | * @returns Contents of the file (string) 39 | * @example 40 | * ```ts 41 | * const res = await client.getFileContents('c2f5a3b6', 'index.js') // res = content of your file (string) 42 | * ``` 43 | * @example 44 | * ```ts 45 | * client.getFileContents('c2f5a3b6', 'dist/index.js').then((res) => console.log(res)) // res = content of your file (string) 46 | * ``` 47 | */ 48 | public getFileContents = async ( 49 | serverId: string, 50 | file: string 51 | ): Promise => { 52 | let filePath = ''; 53 | if (file.includes('/')) { 54 | file.split('/').forEach((f) => (filePath += `%2F${f}`)); 55 | } else filePath = `%2F${file}`; 56 | return this.client.request( 57 | 'GET', 58 | null, 59 | '', 60 | `/api/client/servers/${serverId}/files/contents?file=${filePath}`, 61 | true 62 | ); 63 | }; 64 | /** 65 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 66 | * @param file - File to get the contents of (full name like index.js or dist/index.js) 67 | * @param contents - The contents of file you want to write 68 | * @returns If successful returns Successfuly written the file! 69 | * @example 70 | * ```ts 71 | * const res = await client.writeFile('c2f5a3b6', 'HW.txt', 'Hello world!') // res = Successfuly written the file! 72 | * ``` 73 | * @example 74 | * ```ts 75 | * client.writeFile('c2f5a3b6', 'dist/HW.txt', 'Hello world!').then((res) => console.log(res)) // res = Successfuly written the file! 76 | * ``` 77 | */ 78 | public writeFile = async ( 79 | serverId: string, 80 | file: string, 81 | contents: string 82 | ): Promise => { 83 | return this.client.request( 84 | 'POST', 85 | contents, 86 | 'Successfuly written the file!', 87 | `/api/client/servers/${serverId}/files/write?file=${encodeURIComponent( 88 | file 89 | )}` 90 | ); 91 | }; 92 | /** 93 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 94 | * @param data - An object composed of root of the file and array of objects for files to rename 95 | * @returns If successful returns Successfuly renamed! 96 | * @example 97 | * ```ts 98 | * const res = await client.renameFile('c2f5a3b6', { root: '/', files: [{ from: 'LICENSE', to: 'LIC' }] }) // res = Successfuly renamed! 99 | * ``` 100 | * @example 101 | * ```ts 102 | * client.renameFile('c2f5a3b6', { root: '/dist', files: [{ from: 'LICENSE', to: 'LIC' }] }).then((res) => console.log(res)) // res = Successfuly renamed! 103 | * ``` 104 | */ 105 | public renameFile = async ( 106 | serverId: string, 107 | data: SeverFileRename 108 | ): Promise => { 109 | return this.client.request( 110 | 'PUT', 111 | data, 112 | 'Successfuly renamed!', 113 | `/api/client/servers/${serverId}/files/rename` 114 | ); 115 | }; 116 | /** 117 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 118 | * @param location - Location of file to copy (e. g. /LICENSE) (It will create a /LICENSE copy) 119 | * @returns If successful returns Successfuly copied! 120 | * @example 121 | * ```ts 122 | * const res = await client.copyFile('c2f5a3b6', '/LICENSE') // res = Successfuly copied! 123 | * ``` 124 | * @example 125 | * ```ts 126 | * client.copyFile('c2f5a3b6', '/dist/LICENSE').then((res) => console.log(res)) // res = Successfuly copied! 127 | * ``` 128 | */ 129 | public copyFile = async ( 130 | serverId: string, 131 | location: string 132 | ): Promise => { 133 | return this.client.request( 134 | 'POST', 135 | { location: location }, 136 | 'Successfuly copied!', 137 | `/api/client/servers/${serverId}/files/copy` 138 | ); 139 | }; 140 | /** 141 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 142 | * @param file - File to get the contents of (full name like index.js or dist/index.js) 143 | * @returns Returns file download url 144 | * @example 145 | * ```ts 146 | * const res = await client.getFileDownloadLink('c2f5a3b6', 'index.js') // res = url (string) 147 | * ``` 148 | * @example 149 | * ```ts 150 | * client.getServerResources('c2f5a3b6', 'dist/index.js').then((res) => console.log(res)) // res = url (string) 151 | * ``` 152 | */ 153 | public getFileDownloadLink = async ( 154 | serverId: string, 155 | file: string 156 | ): Promise => { 157 | let filePath = ''; 158 | if (file.includes('/')) { 159 | file.split('/').forEach((f) => (filePath += `%2F${f}`)); 160 | } else filePath = `%2F${file}`; 161 | return this.client.request( 162 | 'GET', 163 | null, 164 | 'attributes.url', 165 | `/api/client/servers/${serverId}/files/download?file=${filePath}` 166 | ); 167 | }; 168 | /** 169 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 170 | * @param data - An object composed of root of the file and array of objects for files to rename 171 | * @returns Returns a archive file information 172 | * @example 173 | * ```ts 174 | * const res = await client.compressFile('c2f5a3b6', { root: '/', files: ['README.md', 'LICENSE'] }) // res = ServerFileAttributes 175 | * ``` 176 | * @example 177 | * ```ts 178 | * client.compressFile('c2f5a3b6', { root: '/', files: ['README.md', 'LICENSE'] }).then((res) => console.log(res)) // res = ServerFileAttributes 179 | * ``` 180 | */ 181 | public compressFile = async ( 182 | serverId: string, 183 | data: ServerFileCompress 184 | ): Promise => { 185 | return this.client.request( 186 | 'POST', 187 | data, 188 | 'attributes', 189 | `/api/client/servers/${serverId}/files/compress` 190 | ); 191 | }; 192 | /** 193 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 194 | * @param data - An object composed of root of the file and file to remove 195 | * @returns If successful returns Successfuly decompressed! 196 | * @example 197 | * ```ts 198 | * const res = await client.decompressFile('c2f5a3b6', { root: '/', file: 'archive.tar.gz' }) // res = Successfuly decompressed! 199 | * ``` 200 | * @example 201 | * ```ts 202 | * client.decompressFile('c2f5a3b6', { root: '/', file: 'archive.tar.gz' }).then((res) => console.log(res)) // res = Successfuly decompressed! 203 | * ``` 204 | */ 205 | public decompressFile = async ( 206 | serverId: string, 207 | data: ServerFileDecompress 208 | ): Promise => { 209 | return this.client.request( 210 | 'POST', 211 | data, 212 | 'Successfuly decompressed!', 213 | `/api/client/servers/${serverId}/files/decompress` 214 | ); 215 | }; 216 | /** 217 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 218 | * @param data - An object composed of root of the file and array of string (file names) for files to rename 219 | * @returns If successful returns Successfuly deleted! 220 | * @example 221 | * ```ts 222 | * const res = await client.deleteFile('c2f5a3b6', { root: '/', files: ['README.md'] }) // res = Successfuly deleted! 223 | * ``` 224 | * @example 225 | * ```ts 226 | * client.deleteFile('c2f5a3b6', { root: '/', files: ['LICENSE', 'README.md'] }).then((res) => console.log(res)) // res = Successfuly deleted! 227 | * ``` 228 | */ 229 | public deleteFile = async ( 230 | serverId: string, 231 | data: ServerFileDelete 232 | ): Promise => { 233 | return this.client.request( 234 | 'POST', 235 | data, 236 | 'Successfuly deleted!', 237 | `/api/client/servers/${serverId}/files/delete` 238 | ); 239 | }; 240 | /** 241 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 242 | * @param data - An object composed of root of the file and file to remove 243 | * @returns If successful returns Successfuly created! 244 | * @example 245 | * ```ts 246 | * const res = await client.createFolder('c2f5a3b6', { root: '/', name: 'world' }) // res = Successfuly created! 247 | * ``` 248 | * @example 249 | * ```ts 250 | * client.createFolder('c2f5a3b6', { root: '/', name: 'world' }).then((res) => console.log(res)) // res = Successfuly created! 251 | * ``` 252 | */ 253 | public createFolder = async ( 254 | serverId: string, 255 | data: ServerFileCreateFolder 256 | ): Promise => { 257 | return this.client.request( 258 | 'POST', 259 | data, 260 | 'Successfuly created!', 261 | `/api/client/servers/${serverId}/files/create-folder` 262 | ); 263 | }; 264 | /** 265 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 266 | * @returns If successful returns upload url 267 | * @example 268 | * ```ts 269 | * const res = await client.getFileUploadLink('c2f5a3b6') // res = url (string) 270 | * ``` 271 | * @example 272 | * ```ts 273 | * client.getFileUploadLink('c2f5a3b6').then((res) => console.log(res)) // res = url (string) 274 | * ``` 275 | */ 276 | public getFileUploadLink = async (serverId: string): Promise => { 277 | return this.client.request( 278 | 'GET', 279 | null, 280 | 'attributes.url', 281 | `/api/client/servers/${serverId}/files/upload` 282 | ); 283 | }; 284 | } 285 | -------------------------------------------------------------------------------- /src/client/methods/network.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { Allocation } from '../interfaces/Allocation'; 3 | 4 | export class networkMethods { 5 | constructor(private readonly client: Client) {} 6 | /** 7 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 8 | * @returns Array of allocations 9 | * @example 10 | * ```ts 11 | * const res = await client.getAllAlocations('c2f5a3b6') // res = Allocation[] 12 | * ``` 13 | * @example 14 | * ```ts 15 | * client.getAllAlocations('c2f5a3b6').then((res) => console.log(res)) // res = Allocation[] 16 | * ``` 17 | */ 18 | public getAllAlocations = (serverId: string): Promise => { 19 | return this.client.request( 20 | 'GET', 21 | null, 22 | 'data', 23 | `/api/client/servers/${serverId}/network/allocations` 24 | ); 25 | }; 26 | /** 27 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 28 | * @remarks This method is only available if auto-assign is enabled 29 | * @example 30 | * ```ts 31 | * const res = await client.assignAllocation('c2f5a3b6') // res = Allocation 32 | * ``` 33 | * @example 34 | * ```ts 35 | * client.assignAllocation('c2f5a3b6').then((res) => console.log(res)) // res = Allocation 36 | * ``` 37 | */ 38 | public assignAllocation = (serverId: string): Promise => { 39 | return this.client.request( 40 | 'POST', 41 | null, 42 | 'attributes', 43 | `/api/client/servers/${serverId}/network/allocations` 44 | ); 45 | }; 46 | /** 47 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 48 | * @param allocationId - ID of the allocation to set the note for 49 | * @param note - The note you want to set 50 | * @example 51 | * ```ts 52 | * const res = await client.setAllocationNote('c2f5a3b6', 1, "Port for RDP") // res = Allocation 53 | * ``` 54 | * @example 55 | * ```ts 56 | * client.setAllocationNote('c2f5a3b6', 1, "Port for RDP").then((res) => console.log(res)) // res = Allocation 57 | * ``` 58 | */ 59 | public setAllocationNote = ( 60 | serverId: string, 61 | allocationId: number, 62 | note: string 63 | ): Promise => { 64 | return this.client.request( 65 | 'POST', 66 | { notes: note }, 67 | 'attributes', 68 | `/api/client/servers/${serverId}/network/allocations/${allocationId}` 69 | ); 70 | }; 71 | /** 72 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 73 | * @param allocationId - ID of the allocation to make primary 74 | * @example 75 | * ```ts 76 | * const res = await client.setAllocationPrimary('c2f5a3b6', 1) // res = Allocation 77 | * ``` 78 | * @example 79 | * ```ts 80 | * client.setAllocationPrimary('c2f5a3b6', 1).then((res) => console.log(res)) // res = Allocation 81 | * ``` 82 | */ 83 | public setAllocationPrimary = ( 84 | serverId: string, 85 | allocationId: number 86 | ): Promise => { 87 | return this.client.request( 88 | 'POST', 89 | null, 90 | 'attributes', 91 | `/api/client/servers/${serverId}/network/allocations/${allocationId}/primary` 92 | ); 93 | }; 94 | /** 95 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 96 | * @param allocationId - ID of the allocation to delete 97 | * @remarks This method is only available if allocation is not primary 98 | * @example 99 | * ```ts 100 | * const res = await client.deleteAllocation('c2f5a3b6', 1) // res = Sucessfully deleted Allocation! 101 | * ``` 102 | * @example 103 | * ```ts 104 | * client.deleteAllocation('c2f5a3b6', 1).then((res) => console.log(res)) // res = Sucessfully deleted Allocation! 105 | * ``` 106 | */ 107 | public deleteAllocation = ( 108 | serverId: string, 109 | allocationId: number 110 | ): Promise => { 111 | return this.client.request( 112 | 'DELETE', 113 | null, 114 | 'Sucessfully deleted Allocation!', 115 | `/api/client/servers/${serverId}/network/allocations/${allocationId}` 116 | ); 117 | }; 118 | } 119 | -------------------------------------------------------------------------------- /src/client/methods/schedule.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { 3 | Schedule, 4 | ScheduleAttributes, 5 | ScheduleTaskAttributes, 6 | SheduleEditOptions, 7 | TaskEditOptions 8 | } from '../interfaces/Schedule'; 9 | 10 | export class scheduleMethods { 11 | constructor(private readonly client: Client) {} 12 | /** 13 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 14 | * @returns An Array of servers schedules 15 | * @example 16 | * ```ts 17 | * const res = await client.getAllSchedules() // res = Schedule[] 18 | * ``` 19 | * @example 20 | * ```ts 21 | * client.getAllSchedules().then((res) => console.log(res)) // res = Schedule[] 22 | * ``` 23 | */ 24 | public getAllSchedules = async (serverId: string): Promise => { 25 | return this.client.request( 26 | 'GET', 27 | null, 28 | 'data', 29 | `/api/client/servers/${serverId}/schedules` 30 | ); 31 | }; 32 | /** 33 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 34 | * @param name - Name of the schedule 35 | * @param minute - Cron minute syntax 36 | * @param hour - Cron hour syntax 37 | * @param dayOfMonth - Cron day of month syntax 38 | * @param month - Cron month syntax 39 | * @param dayOfWeek - Cron day of week syntax 40 | * @param isActive - Whether the schedule should be activated on creation (default true) 41 | * @param onlyWhenOnline - Whether the schedule should only run when server is on (default true) 42 | * @returns The schedule information 43 | * @example 44 | * ```ts 45 | * const res = await client.createSchedule('TESTING', '*', '*', '*', '*') // res = ScheduleAttributes 46 | * ``` 47 | * @example 48 | * ```ts 49 | * client.createSchedule('TESTING', '*', '*', '*', '*').then((res) => console.log(res)) // res = ScheduleAttributes 50 | * ``` 51 | */ 52 | public createSchedule = async ( 53 | serverId: string, 54 | name: string, 55 | minute: string, 56 | hour: string, 57 | dayOfMonth: string, 58 | month: string, 59 | dayOfWeek: string, 60 | isActive = true, 61 | onlyWhenOnline = true 62 | ): Promise => { 63 | return this.client.request( 64 | 'POST', 65 | { 66 | name: name, 67 | minute: minute, 68 | hour: hour, 69 | day_of_month: dayOfMonth, 70 | month: month, 71 | day_of_week: dayOfWeek, 72 | is_active: isActive, 73 | only_when_online: onlyWhenOnline 74 | }, 75 | 'attributes', 76 | `/api/client/servers/${serverId}/schedules` 77 | ); 78 | }; 79 | /** 80 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 81 | * @param scheduleId - Id of the schedule to get info 82 | * @returns Schedule information 83 | * @example 84 | * ```ts 85 | * const res = await client.getScheduleInfo('7e74354d', 7) // res = ScheduleAttributes 86 | * ``` 87 | * @example 88 | * ```ts 89 | * client.getScheduleInfo('7e74354d', 8).then((res) => console.log(res)) // res = ScheduleAttributes 90 | * ``` 91 | */ 92 | public getScheduleInfo = async ( 93 | serverId: string, 94 | scheduleId: number 95 | ): Promise => { 96 | return this.client.request( 97 | 'GET', 98 | null, 99 | 'attributes', 100 | `/api/client/servers/${serverId}/schedules/${scheduleId}` 101 | ); 102 | }; 103 | /** 104 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 105 | * @param scheduleId - Id of the schedule to edit 106 | * @param options - Edit schedule options 107 | * @returns The schedule information 108 | * @example 109 | * ```ts 110 | * const res = await client.editSchedule('7e74354d', 5, { name: 'EditedName' }) // res = ScheduleAttributes 111 | * ``` 112 | * @example 113 | * ```ts 114 | * client.editSchedule('7e74354d', 5, { name: 'EditedName' }).then((res) => console.log(res)) // res = ScheduleAttributes 115 | * ``` 116 | */ 117 | public editSchedule = async ( 118 | serverId: string, 119 | scheduleId: number, 120 | options: SheduleEditOptions 121 | ): Promise => { 122 | const schedule = await this.getScheduleInfo(serverId, scheduleId); 123 | return this.client.request( 124 | 'POST', 125 | { 126 | name: options.name ?? schedule.name, 127 | minute: options.minute ?? schedule.cron.minute, 128 | hour: options.hour ?? schedule.cron.hour, 129 | day_of_month: options.dayOfMonth ?? schedule.cron.day_of_month, 130 | month: options.month ?? schedule.cron.month, 131 | day_of_week: options.dayOfWeek ?? schedule.cron.day_of_week, 132 | is_active: options.isActive ?? schedule.is_active 133 | }, 134 | 'attributes', 135 | `/api/client/servers/${serverId}/schedules/${scheduleId}` 136 | ); 137 | }; 138 | /** 139 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 140 | * @param scheduleId - Id of the schedule to delete 141 | * @returns Successfuly deleted schedule! 142 | * @example 143 | * ```ts 144 | * const res = await client.deleteSchedule('7e74354d', 5) // res = Successfuly deleted schedule! 145 | * ``` 146 | * @example 147 | * ```ts 148 | * client.deleteSchedule('7e74354d', 5).then((res) => console.log(res)) // res = Successfuly deleted schedule! 149 | * ``` 150 | */ 151 | public deleteSchedule = async ( 152 | serverId: string, 153 | scheduleId: number 154 | ): Promise => { 155 | return this.client.request( 156 | 'DELETE', 157 | null, 158 | 'Successfuly deleted schedule!', 159 | `/api/client/servers/${serverId}/schedules/${scheduleId}` 160 | ); 161 | }; 162 | /** 163 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 164 | * @param scheduleId - Id of the schedule to create task for 165 | * @param action - Action that the schedule should perform (command/power/backup) 166 | * @param payload - What that action should do. Command or power (start/stop/restart/kill). Backup payload is ignored file list. 167 | * @param timeOffset - The time offset that the task should run after the schdule is triggered. (default 0) 168 | * @param continueOnFailure - Should the task continue to work on failure. (default false) 169 | * @returns The task information 170 | * @example 171 | * ```ts 172 | * const res = await client.createTask('7e74354d', 5, 'power', 'start') // res = ScheduleTaskAttributes 173 | * ``` 174 | * @example 175 | * ```ts 176 | * client.createTask('7e74354d', 5, 'power', 'start').then((res) => console.log(res)) // res = ScheduleTaskAttributes 177 | * ``` 178 | */ 179 | public createTask = async ( 180 | serverId: string, 181 | scheduleId: number, 182 | action: 'command' | 'power' | 'backup', 183 | payload: string, 184 | timeOffset = 0, 185 | continueOnFailure = false 186 | ): Promise => { 187 | return this.client.request( 188 | 'POST', 189 | { 190 | action: action, 191 | time_offset: timeOffset, 192 | payload: payload, 193 | continue_on_failure: continueOnFailure 194 | }, 195 | 'attributes', 196 | `/api/client/servers/${serverId}/schedules/${scheduleId}/tasks` 197 | ); 198 | }; 199 | /** 200 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 201 | * @param scheduleId - ID of the schedule to edit task for 202 | * @param taskId - ID of the task to edit 203 | * @returns The task information 204 | * @example 205 | * ```ts 206 | * const res = await client.editTask('7e74354d', 5, 1, { payload: 'restart' }) // res = ScheduleTaskAttributes 207 | * ``` 208 | * @example 209 | * ```ts 210 | * client.editTask('7e74354d', 5, 1, { payload: 'restart' }).then((res) => console.log(res)) // res = ScheduleTaskAttributes 211 | * ``` 212 | */ 213 | public editTask = async ( 214 | serverId: string, 215 | scheduleId: number, 216 | taskId: number, 217 | options: TaskEditOptions 218 | ): Promise => { 219 | const schedule = await this.getScheduleInfo(serverId, scheduleId); 220 | const task = schedule.relationships.tasks.data.find( 221 | ({ attributes: { id } }) => id === taskId 222 | )?.attributes; 223 | if (!task) throw new Error('Task could not be found!'); 224 | return this.client.request( 225 | 'POST', 226 | { 227 | action: options.action ?? task.action, 228 | time_offset: options.timeOffset ?? task.time_offset, 229 | payload: options.payload ?? task.payload, 230 | continue_on_failure: 231 | options.continueOnFailure ?? task.continue_on_failure 232 | }, 233 | 'attributes', 234 | `/api/client/servers/${serverId}/schedules/${scheduleId}/tasks/${taskId}` 235 | ); 236 | }; 237 | /** 238 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 239 | * @param scheduleId - ID of the schedule 240 | * @param taskId - ID of the task to delete 241 | * @returns Successfuly deleted schedule! 242 | * @example 243 | * ```ts 244 | * const res = await client.deleteTask('7e74354d', 5) // res = Successfuly deleted schedule! 245 | * ``` 246 | * @example 247 | * ```ts 248 | * client.deleteTask('7e74354d', 5).then((res) => console.log(res)) // res = Successfuly deleted schedule! 249 | * ``` 250 | */ 251 | public deleteTask = async ( 252 | serverId: string, 253 | scheduleId: number, 254 | taskId: number 255 | ): Promise => { 256 | return this.client.request( 257 | 'DELETE', 258 | null, 259 | 'Successfuly deleted task!', 260 | `/api/client/servers/${serverId}/schedules/${scheduleId}/tasks/${taskId}` 261 | ); 262 | }; 263 | } 264 | -------------------------------------------------------------------------------- /src/client/methods/server.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | import { makeOptions, MakeOpts, paginate } from '../../modules/Functions'; 3 | import { 4 | Server, 5 | ServerAttributes, 6 | ServerFilterInput, 7 | ServerIncludeInput, 8 | Servers 9 | } from '../interfaces/Server'; 10 | import { ServerResources } from '../interfaces/ServerResources'; 11 | 12 | export class serverMethods { 13 | constructor(private readonly client: Client) {} 14 | /** 15 | * @internal 16 | */ 17 | private getServers = async (options: MakeOpts): Promise => { 18 | return this.client.request( 19 | 'GET', 20 | null, 21 | '', 22 | `/api/client${makeOptions(options)}` 23 | ); 24 | }; 25 | /** 26 | * @param options - Include information about server relationships 27 | * @param filter - Filter servers by specified field and value 28 | * @returns An Array of servers 29 | * @example 30 | * ```ts 31 | * const res = await client.getAllServers() // res = Server[] 32 | * ``` 33 | * @example 34 | * ```ts 35 | * client.getAllServers().then((res) => console.log(res)) // res = Server[] 36 | * ``` 37 | */ 38 | public getAllServers = async ( 39 | options?: ServerIncludeInput, 40 | filter?: ServerFilterInput, 41 | admin = false 42 | ): Promise => { 43 | return await paginate(this.getServers.bind(this), { 44 | includes: { ...options }, 45 | admin: admin, 46 | filter: filter 47 | }); 48 | }; 49 | /** 50 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 51 | * @param options - Include information about server relationships 52 | * @returns Server information 53 | * @example 54 | * ```ts 55 | * const res = await client.getServerInfo('c2f5a3b6') // res = ServerAttributes 56 | * ``` 57 | * @example 58 | * ```ts 59 | * client.getServerInfo('c2f5a3b6').then((res) => console.log(res)) // res = ServerAttributes 60 | * ``` 61 | */ 62 | public getServerInfo = async ( 63 | serverId: string, 64 | options?: ServerIncludeInput 65 | ): Promise => { 66 | return this.client.request( 67 | 'GET', 68 | null, 69 | 'attributes', 70 | `/api/client/servers/${serverId}${makeOptions({ 71 | includes: { ...options } 72 | })}` 73 | ); 74 | }; 75 | /** 76 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 77 | * @returns Server resource usage object 78 | * @example 79 | * ```ts 80 | * const res = await client.getServerResources('c2f5a3b6') // res = ServerResources 81 | * ``` 82 | * @example 83 | * ```ts 84 | * client.getServerResources('c2f5a3b6').then((res) => console.log(res)) // res = ServerResources 85 | * ``` 86 | */ 87 | public getServerResources = async ( 88 | serverId: string 89 | ): Promise => { 90 | return this.client.request( 91 | 'GET', 92 | null, 93 | 'attributes', 94 | `/api/client/servers/${serverId}/resources` 95 | ); 96 | }; 97 | /** 98 | * @param serverId - ID of the server to send a command to 99 | * @param command - Command to send 100 | * @returns If successful returns Successfuly sent the command! 101 | * @example 102 | * ```ts 103 | * const res = await client.sendCommand('c2f5a3b6', 'give Linux123123 star') // res = Successfuly sent the command! 104 | * ``` 105 | * @example 106 | * ```ts 107 | * client.sendCommand('c2f5a3b6', 'give Linux123123 star').then((res) => console.log(res)) // res = Successfuly sent the command! 108 | * ``` 109 | */ 110 | public sendCommand = async ( 111 | serverId: string, 112 | command: string 113 | ): Promise => { 114 | return this.client.request( 115 | 'POST', 116 | { command: command }, 117 | 'Successfuly sent the command!', 118 | `/api/client/servers/${serverId}/command` 119 | ); 120 | }; 121 | /** 122 | * @param serverId - ID of the server to send a command to 123 | * @param action - start / stop / restart / kill 124 | * @returns If successful returns Successfuly set power state! 125 | * @example 126 | * ```ts 127 | * const res = await client.setPowerState('c2f5a3b6', 'start') // res = Successfuly set power state! 128 | * ``` 129 | * @example 130 | * ```ts 131 | * client.setPowerState('c2f5a3b6', 'kill).then((res) => console.log(res)) // res = Successfuly set power state! 132 | * ``` 133 | */ 134 | public setPowerState = async ( 135 | serverId: string, 136 | action: 'start' | 'stop' | 'restart' | 'kill' 137 | ): Promise => { 138 | return this.client.request( 139 | 'POST', 140 | { signal: action }, 141 | 'Successfuly set power state!', 142 | `/api/client/servers/${serverId}/power` 143 | ); 144 | }; 145 | } 146 | -------------------------------------------------------------------------------- /src/client/methods/settings.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '../index'; 2 | 3 | export class settingsMethods { 4 | constructor(private readonly client: Client) {} 5 | /** 6 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 7 | * @param name - New name for the server 8 | * @returns Successfuly set new server name! 9 | * @example 10 | * ```ts 11 | * const res = await client.renameServer('c2f5a3b6', 'Best Server') // res = Successfuly set new server name! 12 | * ``` 13 | * @example 14 | * ```ts 15 | * client.renameServer('c2f5a3b6', 'Best Server').then((res) => console.log(res)) // res = Successfuly set new server name! 16 | * ``` 17 | */ 18 | public renameServer = async ( 19 | serverId: string, 20 | name: string 21 | ): Promise => { 22 | return await this.client.request( 23 | 'POST', 24 | { name }, 25 | 'Successfuly set new server name!', 26 | `/api/client/servers/${serverId}/settings/rename` 27 | ); 28 | }; 29 | /** 30 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 31 | * @returns Successfuly started reinstalling! 32 | * @example 33 | * ```ts 34 | * const res = await client.reinstallServer('c2f5a3b6') // res = Successfuly started reinstalling! 35 | * ``` 36 | * @example 37 | * ```ts 38 | * client.reinstallServer('c2f5a3b6').then((res) => console.log(res)) // res = Successfuly started reinstalling! 39 | * ``` 40 | */ 41 | public reinstallServer = async (serverId: string): Promise => { 42 | return await this.client.request( 43 | 'POST', 44 | null, 45 | 'Successfuly started reinstalling!', 46 | `/api/client/servers/${serverId}/settings/reinstall` 47 | ); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /src/client/methods/subUser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SubUser, 3 | SubUserAttributes, 4 | SubuserPermission 5 | } from 'client/interfaces/SubUser'; 6 | import { Client } from '../index'; 7 | 8 | export class subUserMethods { 9 | constructor(private readonly client: Client) {} 10 | /** 11 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 12 | * @returns SubUser[] 13 | * @example 14 | * ```ts 15 | * const res = await client.getAllSubUsers('c2f5a3b6') // res = SubUser[] 16 | * ``` 17 | * @example 18 | * ```ts 19 | * client.getAllSubUsers('c2f5a3b6').then((res) => console.log(res)) // res = SubUser[] 20 | * ``` 21 | */ 22 | public getAllSubUsers = async (serverId: string): Promise => { 23 | return this.client.request( 24 | 'GET', 25 | null, 26 | 'data', 27 | `/api/client/servers/${serverId}/users` 28 | ); 29 | }; 30 | /** 31 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 32 | * @param subUserId - UUID of the subuser to get 33 | * @returns SubUserAttributes 34 | * @example 35 | * ```ts 36 | * const res = await client.getSubUserInfo('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4') // res = SubUserAttributes 37 | * ``` 38 | * @example 39 | * ```ts 40 | * client.getSubUserInfo('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4').then((res) => console.log(res)) // res = SubUserAttributes 41 | * ``` 42 | */ 43 | public getSubUserInfo = async ( 44 | serverId: string, 45 | subUserId: string 46 | ): Promise => { 47 | return this.client.request( 48 | 'GET', 49 | null, 50 | 'attributes', 51 | `/api/client/servers/${serverId}/users/${subUserId}` 52 | ); 53 | }; 54 | /** 55 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 56 | * @param email - Email of the subuser 57 | * @param permission - Permission of the subuser 58 | * @returns SubUserAttributes 59 | * @example 60 | * ```ts 61 | * const res = await client.createSubUser('c2f5a3b6', 'api@gmail.com', ['control.console']) // res = SubUserAttributes 62 | * ``` 63 | * @example 64 | * ```ts 65 | * client.createSubUser('c2f5a3b6', 'api@gmail.com', ['control.console']).then((res) => console.log(res)) // res = SubUserAttributes 66 | * ``` 67 | */ 68 | public createSubUser = async ( 69 | serverId: string, 70 | email: string, 71 | permissions: SubuserPermission[] 72 | ): Promise => { 73 | return this.client.request( 74 | 'POST', 75 | { email, permissions }, 76 | 'attributes', 77 | `/api/client/servers/${serverId}/users` 78 | ); 79 | }; 80 | /** 81 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 82 | * @param subUserId - UUID of the subuser to get 83 | * @param permission - Permission of the subuser 84 | * @returns SubUserAttributes 85 | * @example 86 | * ```ts 87 | * const res = await client.updateSubUserPermissions('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4', ['control.console']) // res = SubUserAttributes 88 | * ``` 89 | * @example 90 | * ```ts 91 | * client.updateSubUserPermissions('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4', ['control.console']).then((res) => console.log(res)) // res = SubUserAttributes 92 | * ``` 93 | */ 94 | public updateSubUserPermissions = async ( 95 | serverId: string, 96 | subUserId: string, 97 | permissions: SubuserPermission[] 98 | ): Promise => { 99 | return this.client.request( 100 | 'POST', 101 | { permissions }, 102 | 'attributes', 103 | `/api/client/servers/${serverId}/users/${subUserId}` 104 | ); 105 | }; 106 | /** 107 | * @param serverId - ID of the server to get (In the settings tab of server/in link) 108 | * @param subUserId - UUID of the subuser to get 109 | * @returns If successful returns Successfuly deleted SubUser! 110 | * @example 111 | * ```ts 112 | * const res = await client.deleteSubUser('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4') // res = Successfuly deleted SubUser! 113 | * ``` 114 | * @example 115 | * ```ts 116 | * client.deleteSubUser('c2f5a3b6', '60a7aec3-e17d-4aa9-abb3-56d944d204b4').then((res) => console.log(res)) // res = Successfuly deleted SubUser! 117 | * ``` 118 | */ 119 | public deleteSubUser = async ( 120 | serverId: string, 121 | subUserId: string 122 | ): Promise => { 123 | return this.client.request( 124 | 'DELETE', 125 | null, 126 | 'Successfuly deleted SubUser!', 127 | `/api/client/servers/${serverId}/users/${subUserId}` 128 | ); 129 | }; 130 | } 131 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The main entrypoint for the API 3 | * @module JSPteroAPI 4 | * @category Main 5 | */ 6 | import { Application } from './application/index'; 7 | import { Client } from './client/index'; 8 | import { JSPteroAPIError } from './modules/Error'; 9 | export { Application, Client, JSPteroAPIError }; 10 | export default { 11 | Application, 12 | Client 13 | }; 14 | -------------------------------------------------------------------------------- /src/modules/Error.ts: -------------------------------------------------------------------------------- 1 | /** @module JSPteroAPIError */ 2 | 3 | import { Response } from 'undici'; 4 | 5 | export interface pterodactylError { 6 | errors?: [ 7 | { 8 | code: string; 9 | status: string; 10 | detail: string; 11 | } 12 | ]; 13 | } 14 | 15 | export class JSPteroAPIError extends Error { 16 | constructor( 17 | rawData: Response, 18 | JSONData: pterodactylError, 19 | data: Record | string | null, 20 | requestType: 'GET' | 'POST' | 'DELETE' | 'PATCH' | 'PUT' 21 | ) { 22 | super(); 23 | this.HTML_URL = rawData.url; 24 | this.HTML_STATUS = rawData.status; 25 | this.HTML_STATUS_TEXT = rawData.statusText; 26 | this.REQUEST_TYPE = requestType; 27 | if (data) this.REQUEST_BODY = data; 28 | const errors: string[] = []; 29 | if (JSONData.errors) 30 | JSONData.errors.forEach((element) => { 31 | errors.push(element.detail); 32 | }); 33 | this.ERRORS = errors; 34 | } 35 | public HTML_URL: string; 36 | public HTML_STATUS: number; 37 | public HTML_STATUS_TEXT: string; 38 | public REQUEST_TYPE: 'GET' | 'POST' | 'DELETE' | 'PATCH' | 'PUT'; 39 | public REQUEST_BODY!: Record | string; 40 | public ERRORS: string[]; 41 | } 42 | -------------------------------------------------------------------------------- /src/modules/Functions.ts: -------------------------------------------------------------------------------- 1 | export interface MakeIncl { 2 | [key: string]: boolean; 3 | } 4 | 5 | export interface MakeFilter { 6 | filter: string; 7 | filterBy: string; 8 | } 9 | 10 | export interface MakeOpts { 11 | includes?: MakeIncl; 12 | filter?: MakeFilter; 13 | admin?: boolean; 14 | page?: number; 15 | } 16 | 17 | export const makeOptions = (options: MakeOpts): string => { 18 | const query = new URLSearchParams(); 19 | if (options.page) { 20 | query.append('page', options.page.toString()); 21 | // Also append per page just in case it's not set 22 | // I make 75 the default becase it's a reasonable default 23 | query.append('per_page', '75'); 24 | } 25 | if (options.includes) { 26 | let includes = ''; 27 | const optionsArray = Object.entries(options.includes); 28 | if (optionsArray.some(([, value]) => value === true)) { 29 | optionsArray.forEach(([key, value]) => { 30 | if (value) includes += `${key},`; 31 | }); 32 | } 33 | if (includes) { 34 | query.append('include', includes.slice(0, -1)); 35 | } 36 | } 37 | if (options.filter) 38 | query.append(`filter[${options.filter.filterBy}]`, options.filter.filter); 39 | 40 | if (options.admin) query.append('type', 'admin-all'); 41 | const queryString = query.toString(); 42 | return queryString ? `?${queryString}` : ''; 43 | }; 44 | 45 | export const paginate = async ( 46 | request: (options: MakeOpts) => Promise<{ 47 | data: T[]; 48 | meta: { 49 | pagination: { 50 | total_pages: number; 51 | }; 52 | }; 53 | }>, 54 | options: MakeOpts 55 | ): Promise => { 56 | const page1 = await request({ ...options, page: 1 }); 57 | let data = page1.data; 58 | if (page1.meta.pagination.total_pages > 1) { 59 | for (let i = 2; i <= page1.meta.pagination.total_pages; i++) { 60 | const page = await request({ 61 | ...options, 62 | page: i 63 | }); 64 | data = data.concat(page.data); 65 | } 66 | } 67 | return data; 68 | }; 69 | -------------------------------------------------------------------------------- /src/modules/Request.ts: -------------------------------------------------------------------------------- 1 | import { fetch, RequestInit } from 'undici'; 2 | 3 | import { JSPteroAPIError, pterodactylError } from './Error'; 4 | 5 | export class Request { 6 | constructor( 7 | private readonly host: string, 8 | private readonly key: string, 9 | private readonly errorHandler: (error: JSPteroAPIError) => void 10 | ) {} 11 | /** 12 | * @param requestType - The type of request to use e. g. GET, POST 13 | * @param data - Data to send 14 | * @param dataObj - Data object to return / Text to give on success 15 | * @param endpoint - Endpoint for server to call 16 | * @param text - Boolean if we want to return text of the response 17 | */ 18 | public async request( 19 | requestType: 'GET' | 'POST' | 'DELETE' | 'PATCH' | 'PUT', 20 | data: Record | string | unknown | null, 21 | dataObj: string, 22 | endpoint: string, 23 | text = false 24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 25 | ): Promise { 26 | const URL = this.host + endpoint; 27 | const options: RequestInit = { 28 | method: requestType, 29 | headers: { 30 | 'responseEncoding': 'utf8', 31 | 'Authorization': 'Bearer ' + this.key, 32 | 'Content-Type': `${ 33 | !endpoint.includes('files/write') ? 'application/json' : '' 34 | }`, 35 | 'Accept': 'application/json' 36 | } 37 | }; 38 | if (data && endpoint.includes('files/write')) options.body = data as string; 39 | if (data && !endpoint.includes('files/write')) 40 | options.body = JSON.stringify(data); 41 | const rawData = await fetch(URL, options); 42 | if (!rawData.ok) 43 | return this.errorHandler( 44 | new JSPteroAPIError( 45 | rawData, 46 | (await rawData.json()) as pterodactylError, 47 | data as Record, 48 | requestType 49 | ) 50 | ); 51 | if (rawData.status === 204 || rawData.status === 202) return dataObj; 52 | if (text) return await rawData.text(); 53 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 54 | let res = (await rawData.json()) as any; 55 | if (!dataObj) return res; 56 | const objArr = dataObj.split('.'); 57 | objArr.forEach((obj) => { 58 | res = res[obj]; 59 | }); 60 | return res; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/modules/Socket.ts: -------------------------------------------------------------------------------- 1 | import { WebSocket, Event, MessageEvent, CloseEvent, ErrorEvent } from 'ws'; 2 | 3 | export class Socket { 4 | constructor( 5 | private readonly url: string, 6 | private readonly options: { 7 | onopen: (this: Socket, ev: Event) => void; 8 | onmessage: (this: Socket, ev: MessageEvent) => void; 9 | onreconnect: (this: Socket, ev: Event | CloseEvent | ErrorEvent) => void; 10 | onmaximum: (this: Socket, ev: CloseEvent | ErrorEvent) => void; 11 | onclose: (this: Socket, ev: CloseEvent) => void; 12 | onerror: (this: Socket, ev: ErrorEvent) => void; 13 | } 14 | ) { 15 | this.open(); 16 | } 17 | 18 | declare ws: WebSocket; 19 | declare timer: NodeJS.Timeout; 20 | private reconnectNum = 0; 21 | 22 | public open = () => { 23 | const options = this.options; 24 | const reconnect = this.reconnect; 25 | this.ws = new WebSocket(this.url); 26 | 27 | this.ws.onmessage = options.onmessage; 28 | 29 | const onOpen = options.onopen.bind(this); 30 | this.ws.onopen = (e) => { 31 | onOpen(e); 32 | this.reconnectNum = 0; 33 | }; 34 | 35 | const onClose = options.onclose.bind(this); 36 | this.ws.onclose = function (e) { 37 | e.code === 1e3 || e.code === 1001 || e.code === 1005 || reconnect(e); 38 | onClose(e); 39 | }; 40 | 41 | const onError = options.onerror.bind(this); 42 | this.ws.onerror = function (e) { 43 | e && (e as unknown as Record).code === 'ECONNREFUSED' 44 | ? reconnect(e) 45 | : onError(e); 46 | }; 47 | }; 48 | 49 | private reconnect = (e: CloseEvent | ErrorEvent) => { 50 | const onReconnect = this.options.onreconnect.bind(this); 51 | const onMaximum = this.options.onmaximum.bind(this); 52 | 53 | const open = this.open; 54 | if (this.timer && this.reconnectNum++ < Infinity) { 55 | this.timer = setTimeout(function () { 56 | onReconnect(e); 57 | open(); 58 | }, 1e3); 59 | } else { 60 | onMaximum(e); 61 | } 62 | }; 63 | 64 | public json = (x: unknown) => { 65 | this.ws.send(JSON.stringify(x)); 66 | }; 67 | 68 | public send = (x: string) => { 69 | this.ws.send(x); 70 | }; 71 | 72 | public close = (x?: number, y?: string | Buffer) => { 73 | clearTimeout(this.timer); 74 | this.ws.close(x || 1e3, y); 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, 4 | "module": "CommonJS" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, 5 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, 6 | "declaration": true /* Generates corresponding '.d.ts' file. */, 7 | "baseUrl": "./src" /* Base directory to resolve non-absolute module names. */, 8 | "outDir": "./dist" /* Redirect output structure to the directory. */, 9 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 10 | "strict": true /* Enable all strict type-checking options. */, 11 | "alwaysStrict": true, 12 | "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, 13 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 14 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 15 | }, 16 | "include": ["src"], 17 | "typedocOptions": { 18 | "name": "JSPteroAPI", 19 | "entryPoints": [ 20 | "src/index.ts", 21 | "src/application/interfaces", 22 | "src/client/interfaces", 23 | "src/modules/Error.ts", 24 | "src/client/Websocket.ts" 25 | ], 26 | "entryPointStrategy": "expand", 27 | "out": "docs" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", 3 | "tagDefinitions": [ 4 | { 5 | "tagName": "@module", 6 | "syntaxKind": "modifier" 7 | }, 8 | { 9 | "tagName": "@category", 10 | "syntaxKind": "modifier" 11 | } 12 | ] 13 | } 14 | --------------------------------------------------------------------------------