diff --git a/.github/workflows/package-pr.yaml b/.github/workflows/package-pr.yaml index ded9014..7f1849d 100644 --- a/.github/workflows/package-pr.yaml +++ b/.github/workflows/package-pr.yaml @@ -8,7 +8,6 @@ on: - synchronize paths: - 'packages/**' - workflow_dispatch: jobs: check-pkg: diff --git a/api/.gitignore b/api/.gitignore index 4b5a9b8..9639bab 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -1 +1,2 @@ _piston +api/dist diff --git a/api/Dockerfile b/api/Dockerfile index ec0d2a8..82d8410 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -18,12 +18,19 @@ RUN apt-get update && \ RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +RUN npm install --global pnpm + WORKDIR /piston_api -COPY ["package.json", "package-lock.json", "./"] -RUN npm install +COPY ["package.json", "pnpm-lock.yaml", "tsconfig.json", "./"] COPY ./src ./src -RUN make -C ./src/nosocket/ all && make -C ./src/nosocket/ install +RUN pnpm install +RUN pnpm build -CMD [ "node", "src"] +COPY ./src/nosocket ./dist/nosocket + +RUN make -C ./dist/nosocket/ all && make -C ./dist/nosocket/ install + + +CMD [ "pnpm", "api"] EXPOSE 2000/tcp diff --git a/api/package-lock.json b/api/package-lock.json deleted file mode 100644 index 3813c0a..0000000 --- a/api/package-lock.json +++ /dev/null @@ -1,1100 +0,0 @@ -{ - "name": "piston-api", - "version": "3.1.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "piston-api", - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "body-parser": "^1.19.0", - "chownr": "^2.0.0", - "express": "^4.17.1", - "express-ws": "^5.0.2", - "is-docker": "^2.1.1", - "logplease": "^1.2.15", - "nocamel": "HexF/nocamel#patch-1", - "node-fetch": "^2.6.7", - "semver": "^7.3.4", - "uuid": "^8.3.2", - "waitpid": "git+https://github.com/HexF/node-waitpid.git" - } - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-ws": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz", - "integrity": "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==", - "dependencies": { - "ws": "^7.4.6" - }, - "engines": { - "node": ">=4.5.0" - }, - "peerDependencies": { - "express": "^4.0.0 || ^5.0.0-alpha.1" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-docker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", - "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/logplease": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", - "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", - "dependencies": { - "mime-db": "1.46.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nocamel": { - "resolved": "git+ssh://git@github.com/HexF/nocamel.git#89a5bfbbd07c72c302d968b967d0f4fe54846544" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/waitpid": { - "resolved": "git+ssh://git@github.com/HexF/node-waitpid.git#a08d116a5d993a747624fe72ff890167be8c34aa", - "hasInstallScript": true - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - }, - "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "express-ws": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz", - "integrity": "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==", - "requires": { - "ws": "^7.4.6" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-docker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", - "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==" - }, - "logplease": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", - "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" - }, - "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", - "requires": { - "mime-db": "1.46.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "nocamel": { - "version": "git+ssh://git@github.com/HexF/nocamel.git#89a5bfbbd07c72c302d968b967d0f4fe54846544", - "from": "nocamel@HexF/nocamel#patch-1" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "waitpid": { - "version": "git+ssh://git@github.com/HexF/node-waitpid.git#a08d116a5d993a747624fe72ff890167be8c34aa", - "from": "waitpid@git+https://github.com/HexF/node-waitpid.git" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "requires": {} - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/api/package.json b/api/package.json index 7f22601..53d8ba6 100644 --- a/api/package.json +++ b/api/package.json @@ -1,20 +1,29 @@ { "name": "piston-api", - "version": "3.1.0", + "version": "3.2.0", "description": "API for piston - a high performance code execution engine", - "main": "src/index.js", + "module": "./dist/index.js", + "type": "module", + "scripts": { + "api": "node ./dist/index.js", + "build": "npx tsc" + }, "dependencies": { "body-parser": "^1.19.0", "chownr": "^2.0.0", - "express": "^4.17.1", + "express": "^4.17.3", "express-ws": "^5.0.2", "is-docker": "^2.1.1", - "logplease": "^1.2.15", - "nocamel": "HexF/nocamel#patch-1", + "logplease": "github:Endercheif/logplease#feature/quality", "node-fetch": "^2.6.7", "semver": "^7.3.4", "uuid": "^8.3.2", "waitpid": "git+https://github.com/HexF/node-waitpid.git" }, - "license": "MIT" + "license": "MIT", + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node-fetch": "^2.6.2", + "typescript": "^4.9.5" + } } diff --git a/api/pnpm-lock.yaml b/api/pnpm-lock.yaml new file mode 100644 index 0000000..0940f3e --- /dev/null +++ b/api/pnpm-lock.yaml @@ -0,0 +1,655 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/express': ^4.17.17 + '@types/node-fetch': ^2.6.2 + body-parser: ^1.19.0 + chownr: ^2.0.0 + express: ^4.17.3 + express-ws: ^5.0.2 + is-docker: ^2.1.1 + logplease: github:Endercheif/logplease#feature/quality + node-fetch: ^2.6.7 + semver: ^7.3.4 + typescript: ^4.9.5 + uuid: ^8.3.2 + waitpid: git+https://github.com/HexF/node-waitpid.git + +dependencies: + body-parser: 1.20.2 + chownr: 2.0.0 + express: 4.18.2 + express-ws: 5.0.2_express@4.18.2 + is-docker: 2.2.1 + logplease: github.com/Endercheif/logplease/808583a0f24b2d6625d0d30da5b4164cc7bbf23a + node-fetch: 2.6.9 + semver: 7.3.8 + uuid: 8.3.2 + waitpid: github.com/HexF/node-waitpid/a08d116a5d993a747624fe72ff890167be8c34aa + +devDependencies: + '@types/express': 4.17.17 + '@types/node-fetch': 2.6.2 + typescript: 4.9.5 + +packages: + + /@types/body-parser/1.19.2: + resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} + dependencies: + '@types/connect': 3.4.35 + '@types/node': 18.14.1 + dev: true + + /@types/connect/3.4.35: + resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} + dependencies: + '@types/node': 18.14.1 + dev: true + + /@types/express-serve-static-core/4.17.33: + resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} + dependencies: + '@types/node': 18.14.1 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + dev: true + + /@types/express/4.17.17: + resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 4.17.33 + '@types/qs': 6.9.7 + '@types/serve-static': 1.15.1 + dev: true + + /@types/mime/3.0.1: + resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} + dev: true + + /@types/node-fetch/2.6.2: + resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} + dependencies: + '@types/node': 18.14.1 + form-data: 3.0.1 + dev: true + + /@types/node/18.14.1: + resolution: {integrity: sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==} + dev: true + + /@types/qs/6.9.7: + resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} + dev: true + + /@types/range-parser/1.2.4: + resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + dev: true + + /@types/serve-static/1.15.1: + resolution: {integrity: sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==} + dependencies: + '@types/mime': 3.0.1 + '@types/node': 18.14.1 + dev: true + + /accepts/1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /array-flatten/1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /asynckit/0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /body-parser/1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /body-parser/1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /bytes/3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.0 + dev: false + + /chownr/2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /content-disposition/0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type/1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature/1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /delayed-stream/1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /depd/2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy/1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /ee-first/1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encodeurl/1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /escape-html/1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /etag/1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express-ws/5.0.2_express@4.18.2: + resolution: {integrity: sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==} + engines: {node: '>=4.5.0'} + peerDependencies: + express: ^4.0.0 || ^5.0.0-alpha.1 + dependencies: + express: 4.18.2 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /express/4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /finalhandler/1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /form-data/3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /forwarded/0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh/0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /get-intrinsic/1.2.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /http-errors/2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js/1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-docker/2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /media-typer/0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors/1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods/1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /node-fetch/2.6.9: + resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /object-inspect/1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: false + + /on-finished/2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /parseurl/1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-to-regexp/0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr/2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs/6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser/1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body/2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /raw-body/2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /send/0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static/1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof/1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + object-inspect: 1.12.3 + dev: false + + /statuses/2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /toidentifier/1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /tr46/0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /type-is/1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typescript/4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /unpipe/1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /uuid/8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + + /vary/1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /webidl-conversions/3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url/5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /ws/7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + github.com/Endercheif/logplease/808583a0f24b2d6625d0d30da5b4164cc7bbf23a: + resolution: {tarball: https://codeload.github.com/Endercheif/logplease/tar.gz/808583a0f24b2d6625d0d30da5b4164cc7bbf23a} + name: logplease + version: 1.3.5 + dev: false + + github.com/HexF/node-waitpid/a08d116a5d993a747624fe72ff890167be8c34aa: + resolution: {tarball: https://codeload.github.com/HexF/node-waitpid/tar.gz/a08d116a5d993a747624fe72ff890167be8c34aa} + name: waitpid + version: 0.1.1 + requiresBuild: true + dev: false diff --git a/api/src/api/v2.js b/api/src/api/v2.ts similarity index 89% rename from api/src/api/v2.js rename to api/src/api/v2.ts index 4f0c3e2..69f6d3d 100644 --- a/api/src/api/v2.js +++ b/api/src/api/v2.ts @@ -1,12 +1,18 @@ -const express = require('express'); -const router = express.Router(); +import { Router } from 'express'; -const events = require('events'); +import { EventEmitter } from 'node:events'; -const runtime = require('../runtime'); -const { Job } = require('../job'); -const package = require('../package'); -const logger = require('logplease').create('api/v2'); +import { + get_latest_runtime_matching_language_version, + runtimes as _runtimes, +} from '../runtime.js'; +import Job from '../job.js'; +import package_ from '../package.js'; +import { create } from 'logplease'; +import { RequestBody } from '../types.js'; + +const logger = create('api/v2', {}); +const router = Router(); const SIGNALS = [ 'SIGABRT', @@ -47,10 +53,10 @@ const SIGNALS = [ 'SIGXCPU', 'SIGXFSZ', 'SIGWINCH', -]; +] as const; // ref: https://man7.org/linux/man-pages/man7/signal.7.html -function get_job(body) { +function get_job(body: RequestBody): Promise { let { language, version, @@ -63,7 +69,7 @@ function get_job(body) { compile_timeout, } = body; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { if (!language || typeof language !== 'string') { return reject({ message: 'language is required as a string', @@ -87,7 +93,7 @@ function get_job(body) { } } - const rt = runtime.get_latest_runtime_matching_language_version( + const rt = get_latest_runtime_matching_language_version( language, version ); @@ -163,7 +169,7 @@ router.use((req, res, next) => { return next(); } - if (!req.headers['content-type'].startsWith('application/json')) { + if (!req.headers['content-type']?.startsWith('application/json')) { return res.status(415).send({ message: 'requests must be of type application/json', }); @@ -171,10 +177,10 @@ router.use((req, res, next) => { next(); }); - +// @ts-ignore router.ws('/connect', async (ws, req) => { let job = null; - let eventBus = new events.EventEmitter(); + let eventBus = new EventEmitter(); eventBus.on('stdout', data => ws.send( @@ -203,7 +209,7 @@ router.ws('/connect', async (ws, req) => { ws.on('message', async data => { try { - const msg = JSON.parse(data); + const msg = JSON.parse(data.toString()); switch (msg.type) { case 'init': @@ -286,7 +292,7 @@ router.post('/execute', async (req, res) => { }); router.get('/runtimes', (req, res) => { - const runtimes = runtime.map(rt => { + const runtimes = _runtimes.map(rt => { return { language: rt.language, version: rt.version.raw, @@ -299,10 +305,12 @@ router.get('/runtimes', (req, res) => { }); router.get('/packages', async (req, res) => { + console.log({req, res}); + logger.debug('Request to list packages'); - let packages = await package.get_package_list(); + let packages = await package_.get_package_list(); - packages = packages.map(pkg => { + const pkgs = packages.map(pkg => { return { language: pkg.language, language_version: pkg.version.raw, @@ -310,7 +318,7 @@ router.get('/packages', async (req, res) => { }; }); - return res.status(200).send(packages); + return res.status(200).send(pkgs); }); router.post('/packages', async (req, res) => { @@ -318,7 +326,7 @@ router.post('/packages', async (req, res) => { const { language, version } = req.body; - const pkg = await package.get_package(language, version); + const pkg = await package_.get_package(language, version); if (pkg == null) { return res.status(404).send({ @@ -347,7 +355,7 @@ router.delete('/packages', async (req, res) => { const { language, version } = req.body; - const pkg = await package.get_package(language, version); + const pkg = await package_.get_package(language, version); if (pkg == null) { return res.status(404).send({ @@ -371,4 +379,4 @@ router.delete('/packages', async (req, res) => { } }); -module.exports = router; +export default router; diff --git a/api/src/config.js b/api/src/config.ts similarity index 67% rename from api/src/config.js rename to api/src/config.ts index 9452b82..0bd1442 100644 --- a/api/src/config.js +++ b/api/src/config.ts @@ -1,14 +1,15 @@ -const fss = require('fs'); -const Logger = require('logplease'); -const logger = Logger.create('config'); +import { existsSync } from 'fs'; +import { create, type LogLevel, LogLevels } from 'logplease'; +import { Limit, Limits, ObjectType } from './types.js'; +const logger = create('config', {}); const options = { log_level: { desc: 'Level of data to log', - default: 'INFO', + default: 'INFO' as LogLevel, validators: [ x => - Object.values(Logger.LogLevels).includes(x) || + Object.values(LogLevels).includes(x) || `Log level ${x} does not exist`, ], }, @@ -20,33 +21,31 @@ const options = { data_directory: { desc: 'Absolute path to store all piston related data at', default: '/piston', - validators: [ - x => fss.exists_sync(x) || `Directory ${x} does not exist`, - ], + validators: [x => existsSync(x) || `Directory ${x} does not exist`], }, runner_uid_min: { desc: 'Minimum uid to use for runner', default: 1001, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, runner_uid_max: { desc: 'Maximum uid to use for runner', default: 1500, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, runner_gid_min: { desc: 'Minimum gid to use for runner', default: 1001, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, runner_gid_max: { desc: 'Maximum gid to use for runner', default: 1500, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, disable_networking: { desc: 'Set to true to disable networking', @@ -57,50 +56,50 @@ const options = { output_max_size: { desc: 'Max size of each stdio buffer', default: 1024, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, max_process_count: { desc: 'Max number of processes per job', default: 64, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, max_open_files: { desc: 'Max number of open files per job', default: 2048, - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, max_file_size: { desc: 'Max file size in bytes for a file', default: 10000000, //10MB - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, compile_timeout: { desc: 'Max time allowed for compile stage in milliseconds', default: 10000, // 10 seconds - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, run_timeout: { desc: 'Max time allowed for run stage in milliseconds', default: 3000, // 3 seconds - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, compile_memory_limit: { desc: 'Max memory usage for compile stage in bytes (set to -1 for no limit)', default: -1, // no limit - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, run_memory_limit: { desc: 'Max memory usage for run stage in bytes (set to -1 for no limit)', default: -1, // no limit - parser: parse_int, - validators: [(x, raw) => !is_nan(x) || `${raw} is not a number`], + parser: parseInt, + validators: [(x, raw) => !isNaN(x) || `${raw} is not a number`], }, repo_url: { desc: 'URL of repo index', @@ -111,14 +110,14 @@ const options = { max_concurrent_jobs: { desc: 'Maximum number of concurrent jobs to run at one time', default: 64, - parser: parse_int, + parser: parseInt, validators: [x => x > 0 || `${x} cannot be negative`], }, limit_overrides: { desc: 'Per-language exceptions in JSON format for each of:\ max_process_count, max_open_files, max_file_size, compile_memory_limit,\ run_memory_limit, compile_timeout, run_timeout, output_max_size', - default: {}, + default: {} as Record, parser: parse_overrides, validators: [ x => !!x || `Failed to parse the overrides\n${x}`, @@ -129,7 +128,7 @@ const options = { Object.freeze(options); -function apply_validators(validators, validator_parameters) { +function apply_validators(validators: Array<(...args: unknown[]) => true | string>, validator_parameters: unknown[]) { for (const validator of validators) { const validation_response = validator(...validator_parameters); if (validation_response !== true) { @@ -139,8 +138,8 @@ function apply_validators(validators, validator_parameters) { return true; } -function parse_overrides(overrides_string) { - function get_parsed_json_or_null(overrides) { +function parse_overrides(overrides_string: string): Record { + function get_parsed_json_or_null(overrides: string): Record> | null { try { return JSON.parse(overrides); } catch (e) { @@ -152,7 +151,7 @@ function parse_overrides(overrides_string) { if (overrides === null) { return null; } - const parsed_overrides = {}; + const parsed_overrides: Record> = {}; for (const language in overrides) { parsed_overrides[language] = {}; for (const key in overrides[language]) { @@ -171,21 +170,22 @@ function parse_overrides(overrides_string) { return null; } // Find the option for the override - const option = options[key]; + const option = options[key as Limit]; const parser = option.parser; - const raw_value = overrides[language][key]; + const raw_value = overrides[language][key as Limit]; + // @ts-ignore: lgtm const parsed_value = parser(raw_value); parsed_overrides[language][key] = parsed_value; } } - return parsed_overrides; + return parsed_overrides as Record; } -function validate_overrides(overrides) { +function validate_overrides(overrides: Record) { for (const language in overrides) { for (const key in overrides[language]) { - const value = overrides[language][key]; - const option = options[key]; + const value = overrides[language][key as Limit]; + const option = options[key as Limit]; const validators = option.validators; const validation_response = apply_validators(validators, [ value, @@ -201,12 +201,12 @@ function validate_overrides(overrides) { logger.info(`Loading Configuration from environment`); -let config = {}; +let config = {} as ObjectType; for (const option_name in options) { - const env_key = 'PISTON_' + option_name.to_upper_case(); + const env_key = 'PISTON_' + option_name.toUpperCase(); const option = options[option_name]; - const parser = option.parser || (x => x); + const parser = option.parser || ((x: unknown) => x); const env_val = process.env[env_key]; const parsed_val = parser(env_val); const value = env_val === undefined ? option.default : parsed_val; @@ -228,4 +228,4 @@ for (const option_name in options) { logger.info('Configuration successfully loaded'); -module.exports = config; +export default config; diff --git a/api/src/globals.js b/api/src/globals.js deleted file mode 100644 index 933d2ca..0000000 --- a/api/src/globals.js +++ /dev/null @@ -1,20 +0,0 @@ -// Globals are things the user shouldn't change in config, but is good to not use inline constants for -const is_docker = require('is-docker'); -const fs = require('fs'); -const platform = `${is_docker() ? 'docker' : 'baremetal'}-${fs - .read_file_sync('/etc/os-release') - .toString() - .split('\n') - .find(x => x.startsWith('ID')) - .replace('ID=', '')}`; - -module.exports = { - data_directories: { - packages: 'packages', - jobs: 'jobs', - }, - version: require('../package.json').version, - platform, - pkg_installed_file: '.ppman-installed', //Used as indication for if a package was installed - clean_directories: ['/dev/shm', '/run/lock', '/tmp', '/var/tmp'], -}; diff --git a/api/src/globals.ts b/api/src/globals.ts new file mode 100644 index 0000000..25cdfe6 --- /dev/null +++ b/api/src/globals.ts @@ -0,0 +1,24 @@ +// Globals are things the user shouldn't change in config, but is good to not use inline constants for +import is_docker from 'is-docker'; +import { readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; + +const require = createRequire(import.meta.url); + +export const platform = `${is_docker() ? 'docker' : 'baremetal'}-${readFileSync( + '/etc/os-release' +) + .toString() + .split('\n') + .find(x => x.startsWith('ID')) + .replace('ID=', '')}`; + +export const data_directories = { + packages: 'packages', + jobs: 'jobs', +}; +// @ts-ignore +export const version: string = require('../package.json').version; + +export const pkg_installed_file = '.ppman-installed'; //Used as indication for if a package was installed +export const clean_directories = ['/dev/shm', '/run/lock', '/tmp', '/var/tmp']; diff --git a/api/src/index.js b/api/src/index.js deleted file mode 100644 index 2870902..0000000 --- a/api/src/index.js +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env node -require('nocamel'); -const Logger = require('logplease'); -const express = require('express'); -const expressWs = require('express-ws'); -const globals = require('./globals'); -const config = require('./config'); -const path = require('path'); -const fs = require('fs/promises'); -const fss = require('fs'); -const body_parser = require('body-parser'); -const runtime = require('./runtime'); - -const logger = Logger.create('index'); -const app = express(); -expressWs(app); - -(async () => { - logger.info('Setting loglevel to', config.log_level); - Logger.setLogLevel(config.log_level); - logger.debug('Ensuring data directories exist'); - - Object.values(globals.data_directories).for_each(dir => { - let data_path = path.join(config.data_directory, dir); - - logger.debug(`Ensuring ${data_path} exists`); - - if (!fss.exists_sync(data_path)) { - logger.info(`${data_path} does not exist.. Creating..`); - - try { - fss.mkdir_sync(data_path); - } catch (e) { - logger.error(`Failed to create ${data_path}: `, e.message); - } - } - }); - fss.chmodSync(path.join(config.data_directory, globals.data_directories.jobs), 0o711) - - logger.info('Loading packages'); - const pkgdir = path.join( - config.data_directory, - globals.data_directories.packages - ); - - const pkglist = await fs.readdir(pkgdir); - - const languages = await Promise.all( - pkglist.map(lang => { - return fs.readdir(path.join(pkgdir, lang)).then(x => { - return x.map(y => path.join(pkgdir, lang, y)); - }); - }) - ); - - const installed_languages = languages - .flat() - .filter(pkg => - fss.exists_sync(path.join(pkg, globals.pkg_installed_file)) - ); - - installed_languages.for_each(pkg => runtime.load_package(pkg)); - - logger.info('Starting API Server'); - logger.debug('Constructing Express App'); - logger.debug('Registering middleware'); - - app.use(body_parser.urlencoded({ extended: true })); - app.use(body_parser.json()); - - app.use((err, req, res, next) => { - return res.status(400).send({ - stack: err.stack, - }); - }); - - logger.debug('Registering Routes'); - - const api_v2 = require('./api/v2'); - app.use('/api/v2', api_v2); - - app.use((req, res, next) => { - return res.status(404).send({ message: 'Not Found' }); - }); - - logger.debug('Calling app.listen'); - const [address, port] = config.bind_address.split(':'); - - app.listen(port, address, () => { - logger.info('API server started on', config.bind_address); - }); -})(); diff --git a/api/src/index.ts b/api/src/index.ts new file mode 100644 index 0000000..2e432ed --- /dev/null +++ b/api/src/index.ts @@ -0,0 +1,98 @@ +#!/usr/bin/env node +import { create, setLogLevel } from 'logplease'; +import express from 'express'; +import expressWs from 'express-ws'; +import * as globals from './globals.js'; +import config from './config.js'; +import { join } from 'path'; +import { readdir } from 'node:fs/promises'; +import { existsSync, mkdirSync, chmodSync } from 'node:fs'; +import bodyParser from 'body-parser'; +import { load_package } from './runtime.js'; + +const logger = create('index', {}); +const app = express(); +expressWs(app); + +(async () => { + logger.info('Setting loglevel to'); + setLogLevel(config.log_level); + logger.debug('Ensuring data directories exist'); + + Object.values(globals.data_directories).forEach(dir => { + let data_path = join(config.data_directory, dir); + + logger.debug(`Ensuring ${data_path} exists`); + + if (!existsSync(data_path)) { + logger.info(`${data_path} does not exist.. Creating..`); + + try { + mkdirSync(data_path); + } catch (e) { + logger.error(`Failed to create ${data_path}: `, e.message); + } + } + }); + chmodSync( + join(config.data_directory, globals.data_directories.jobs), + 0o711 + ); + + logger.info('Loading packages'); + const pkgdir = join( + config.data_directory, + globals.data_directories.packages + ); + + const pkglist = await readdir(pkgdir); + + const languages = await Promise.all( + pkglist.map(async lang => { + const x = await readdir(join(pkgdir, lang)); + return x.map(y => join(pkgdir, lang, y)); + }) + ); + + const installed_languages = languages + .flat() + .filter(pkg => existsSync(join(pkg, globals.pkg_installed_file))); + + installed_languages.forEach(pkg => load_package(pkg)); + + logger.info('Starting API Server'); + logger.debug('Constructing Express App'); + logger.debug('Registering middleware'); + + app.use(bodyParser.urlencoded({ extended: true })); + app.use(bodyParser.json()); + + app.use( + ( + err: Error, + req: express.Request, + res: express.Response, + next: express.NextFunction + ) => { + return res.status(400).send({ + stack: err.stack, + }); + } + ); + + logger.debug('Registering Routes'); + + const api_v2 = (await import('./api/v2.js')).default; + app.use('/api/v2', api_v2); + + app.use((req, res, next) => { + return res.status(404).send({ message: 'Not Found' }); + }); + + logger.debug('Calling app.listen'); + const [address, port] = config.bind_address.split(':'); + + app.listen(+port, address, () => { + logger.info('API server started on', config.bind_address); + }); +})(); diff --git a/api/src/job.js b/api/src/job.ts similarity index 74% rename from api/src/job.js rename to api/src/job.ts index ecc19e5..db5d77c 100644 --- a/api/src/job.js +++ b/api/src/job.ts @@ -1,19 +1,30 @@ -const logplease = require('logplease'); -const logger = logplease.create('job'); -const { v4: uuidv4 } = require('uuid'); -const cp = require('child_process'); -const path = require('path'); -const config = require('./config'); -const globals = require('./globals'); -const fs = require('fs/promises'); -const fss = require('fs'); -const wait_pid = require('waitpid'); +import { create, type Logger } from 'logplease'; + +const logger = create('job'); +import { v4 as uuidv4 } from 'uuid'; +import { spawn } from 'child_process'; +import { join, relative, dirname } from 'node:path'; +import config from './config.js'; +import * as globals from './globals.js'; +import { + mkdir, + chown, + writeFile, + readdir, + stat as _stat, + rm, +} from 'node:fs/promises'; +import { readdirSync, readFileSync } from 'node:fs'; +import wait_pid from 'waitpid'; +import EventEmitter from 'events'; + +import { File, ResponseBody } from './types.js'; const job_states = { READY: Symbol('Ready to be primed'), PRIMED: Symbol('Primed and ready for execution'), EXECUTED: Symbol('Executed and ready for cleanup'), -}; +} as const; let uid = 0; let gid = 0; @@ -28,14 +39,40 @@ setInterval(() => { } }, 10); -class Job { - constructor({ runtime, files, args, stdin, timeouts, memory_limits }) { +export default class Job { + uuid: string; + logger: Logger; + runtime: any; + files: File[]; + args: string[]; + stdin: string; + timeouts: { compile: number; run: number }; + memory_limits: { compile: number; run: number }; + uid: number; + gid: number; + state: symbol; + dir: string; + constructor({ + runtime, + files, + args, + stdin, + timeouts, + memory_limits, + }: { + runtime: unknown; + files: File[]; + args: string[]; + stdin: string; + timeouts: { compile: number; run: number }; + memory_limits: { compile: number; run: number }; + }) { this.uuid = uuidv4(); - this.logger = logplease.create(`job/${this.uuid}`); + this.logger = create(`job/${this.uuid}`, {}); this.runtime = runtime; - this.files = files.map((file, i) => ({ + this.files = files.map((file: File, i: number) => ({ name: file.name || `file${i}.code`, content: file.content, encoding: ['base64', 'hex', 'utf8'].includes(file.encoding) @@ -61,7 +98,7 @@ class Job { this.logger.debug(`Assigned uid=${this.uid} gid=${this.gid}`); this.state = job_states.READY; - this.dir = path.join( + this.dir = join( config.data_directory, globals.data_directories.jobs, this.uuid @@ -82,12 +119,12 @@ class Job { this.logger.debug(`Transfering ownership`); - await fs.mkdir(this.dir, { mode: 0o700 }); - await fs.chown(this.dir, this.uid, this.gid); + await mkdir(this.dir, { mode: 0o700 }); + await chown(this.dir, this.uid, this.gid); for (const file of this.files) { - const file_path = path.join(this.dir, file.name); - const rel = path.relative(this.dir, file_path); + const file_path = join(this.dir, file.name); + const rel = relative(this.dir, file_path); const file_content = Buffer.from(file.content, file.encoding); if (rel.startsWith('..')) @@ -95,14 +132,14 @@ class Job { `File path "${file.name}" tries to escape parent directory: ${rel}` ); - await fs.mkdir(path.dirname(file_path), { + await mkdir(dirname(file_path), { recursive: true, mode: 0o700, }); - await fs.chown(path.dirname(file_path), this.uid, this.gid); + await chown(dirname(file_path), this.uid, this.gid); - await fs.write_file(file_path, file_content); - await fs.chown(file_path, this.uid, this.gid); + await writeFile(file_path, file_content); + await chown(file_path, this.uid, this.gid); } this.state = job_states.PRIMED; @@ -110,7 +147,13 @@ class Job { this.logger.debug('Primed job'); } - async safe_call(file, args, timeout, memory_limit, eventBus = null) { + async safe_call( + file: string, + args: string[], + timeout: number, + memory_limit: string | number, + eventBus: EventEmitter = null + ): Promise { return new Promise((resolve, reject) => { const nonetwork = config.disable_networking ? ['nosocket'] : []; @@ -120,16 +163,19 @@ class Job { '--nofile=' + this.runtime.max_open_files, '--fsize=' + this.runtime.max_file_size, ]; - + const timeout_call = [ - 'timeout', '-s', '9', Math.ceil(timeout / 1000), + 'timeout', + '-s', + '9', + Math.ceil(timeout / 1000), ]; if (memory_limit >= 0) { prlimit.push('--as=' + memory_limit); } - const proc_call = [ + const proc_call = [ 'nice', ...timeout_call, ...prlimit, @@ -137,13 +183,13 @@ class Job { 'bash', file, ...args, - ]; + ] as Array; var stdout = ''; var stderr = ''; var output = ''; - const proc = cp.spawn(proc_call[0], proc_call.splice(1), { + const proc = spawn(proc_call[0], proc_call.splice(1), { env: { ...this.runtime.env_vars, PISTON_LANGUAGE: this.runtime.language, @@ -160,18 +206,18 @@ class Job { proc.stdin.end(); proc.stdin.destroy(); } else { - eventBus.on('stdin', data => { + eventBus.on('stdin', (data: any) => { proc.stdin.write(data); }); - eventBus.on('kill', signal => { + eventBus.on('kill', (signal: NodeJS.Signals | number) => { proc.kill(signal); }); } const kill_timeout = (timeout >= 0 && - set_timeout(async _ => { + setTimeout(async _ => { this.logger.info(`Timeout exceeded timeout=${timeout}`); process.kill(proc.pid, 'SIGKILL'); }, timeout)) || @@ -202,7 +248,7 @@ class Job { }); const exit_cleanup = () => { - clear_timeout(kill_timeout); + clearTimeout(kill_timeout); proc.stderr.destroy(); proc.stdout.destroy(); @@ -237,15 +283,15 @@ class Job { const code_files = (this.runtime.language === 'file' && this.files) || - this.files.filter(file => file.encoding == 'utf8'); + this.files.filter((file: File) => file.encoding == 'utf8'); this.logger.debug('Compiling'); - let compile; + let compile: unknown; if (this.runtime.compiled) { compile = await this.safe_call( - path.join(this.runtime.pkgdir, 'compile'), + join(this.runtime.pkgdir, 'compile'), code_files.map(x => x.name), this.timeouts.compile, this.memory_limits.compile @@ -255,7 +301,7 @@ class Job { this.logger.debug('Running'); const run = await this.safe_call( - path.join(this.runtime.pkgdir, 'run'), + join(this.runtime.pkgdir, 'run'), [code_files[0].name, ...this.args], this.timeouts.run, this.memory_limits.run @@ -271,7 +317,7 @@ class Job { }; } - async execute_interactive(eventBus) { + async execute_interactive(eventBus: EventEmitter) { if (this.state !== job_states.PRIMED) { throw new Error( 'Job must be in primed state, current state: ' + @@ -290,7 +336,7 @@ class Job { if (this.runtime.compiled) { eventBus.emit('stage', 'compile'); const { error, code, signal } = await this.safe_call( - path.join(this.runtime.pkgdir, 'compile'), + join(this.runtime.pkgdir, 'compile'), code_files.map(x => x.name), this.timeouts.compile, this.memory_limits.compile, @@ -303,7 +349,7 @@ class Job { this.logger.debug('Running'); eventBus.emit('stage', 'run'); const { error, code, signal } = await this.safe_call( - path.join(this.runtime.pkgdir, 'run'), + join(this.runtime.pkgdir, 'run'), [code_files[0].name, ...this.args], this.timeouts.run, this.memory_limits.run, @@ -316,42 +362,43 @@ class Job { } cleanup_processes(dont_wait = []) { - let processes = [1]; + let processes: number[] = [1]; const to_wait = []; this.logger.debug(`Cleaning up processes`); while (processes.length > 0) { processes = []; - const proc_ids = fss.readdir_sync('/proc'); + const proc_ids = readdirSync('/proc'); processes = proc_ids.map(proc_id => { - if (isNaN(proc_id)) return -1; + if (isNaN(+proc_id)) return -1; try { - const proc_status = fss.read_file_sync( - path.join('/proc', proc_id, 'status') + const proc_status = readFileSync( + join('/proc', proc_id, 'status') ); - const proc_lines = proc_status.to_string().split('\n'); + const proc_lines = proc_status.toString().split('\n'); const state_line = proc_lines.find(line => - line.starts_with('State:') + line.startsWith('State:') ); const uid_line = proc_lines.find(line => - line.starts_with('Uid:') + line.startsWith('Uid:') ); const [_, ruid, euid, suid, fuid] = uid_line.split(/\s+/); const [_1, state, user_friendly] = state_line.split(/\s+/); - - const proc_id_int = parse_int(proc_id); - - // Skip over any processes that aren't ours. - if(ruid != this.uid && euid != this.uid) return -1; - if (state == 'Z'){ + const proc_id_int = parseInt(proc_id); + + // Skip over any processes that aren't ours. + // @ts-ignore: dont want to risk fixing this + if (ruid != this.uid && euid != this.uid) return -1; + + if (state == 'Z') { // Zombie process, just needs to be waited, regardless of the user id - if(!to_wait.includes(proc_id_int)) + if (!to_wait.includes(proc_id_int)) to_wait.push(proc_id_int); - + return -1; } // We should kill in all other state (Sleep, Stopped & Running) @@ -386,7 +433,7 @@ class Job { // Then clear them out of the process tree try { process.kill(proc, 'SIGKILL'); - } catch(e) { + } catch (e) { // Could already be dead and just needs to be waited on this.logger.debug( `Got error while SIGKILLing process ${proc}:`, @@ -413,16 +460,16 @@ class Job { async cleanup_filesystem() { for (const clean_path of globals.clean_directories) { - const contents = await fs.readdir(clean_path); + const contents = await readdir(clean_path); for (const file of contents) { - const file_path = path.join(clean_path, file); + const file_path = join(clean_path, file); try { - const stat = await fs.stat(file_path); + const stat = await _stat(file_path); if (stat.uid === this.uid) { - await fs.rm(file_path, { + await rm(file_path, { recursive: true, force: true, }); @@ -434,7 +481,7 @@ class Job { } } - await fs.rm(this.dir, { recursive: true, force: true }); + await rm(this.dir, { recursive: true, force: true }); } async cleanup() { @@ -446,7 +493,3 @@ class Job { remaining_job_spaces++; } } - -module.exports = { - Job, -}; diff --git a/api/src/package.js b/api/src/package.ts similarity index 64% rename from api/src/package.js rename to api/src/package.ts index 11e4f34..1f8fb03 100644 --- a/api/src/package.js +++ b/api/src/package.ts @@ -1,33 +1,46 @@ -const logger = require('logplease').create('package'); -const semver = require('semver'); -const config = require('./config'); -const globals = require('./globals'); -const fetch = require('node-fetch'); -const path = require('path'); -const fs = require('fs/promises'); -const fss = require('fs'); -const cp = require('child_process'); -const crypto = require('crypto'); -const runtime = require('./runtime'); -const chownr = require('chownr'); -const util = require('util'); +import { create } from 'logplease'; +import { parse, satisfies, rcompare, type SemVer } from 'semver'; +import config from './config.js'; +import * as globals from './globals.js'; +import fetch from 'node-fetch'; +import { join } from 'path'; +import { rm, mkdir, writeFile, rmdir } from 'fs/promises'; +import { existsSync, createWriteStream, createReadStream } from 'fs'; +import { exec, spawn } from 'child_process'; +import { createHash } from 'crypto'; +import { load_package, get_runtime_by_name_and_version } from './runtime.js'; +import chownr from 'chownr'; +import { promisify } from 'util'; +const logger = create('package', {}); class Package { - constructor({ language, version, download, checksum }) { + language: string; + version: SemVer; + checksum: string; + download: string; + constructor({ + language, + version, + download, + checksum, + }: { + language: string; + version: string; + checksum: string; + download: string; + }) { this.language = language; - this.version = semver.parse(version); + this.version = parse(version); this.checksum = checksum; this.download = download; } get installed() { - return fss.exists_sync( - path.join(this.install_path, globals.pkg_installed_file) - ); + return existsSync(join(this.install_path, globals.pkg_installed_file)); } get install_path() { - return path.join( + return join( config.data_directory, globals.data_directories.packages, this.language, @@ -42,23 +55,24 @@ class Package { logger.info(`Installing ${this.language}-${this.version.raw}`); - if (fss.exists_sync(this.install_path)) { + if (existsSync(this.install_path)) { logger.warn( `${this.language}-${this.version.raw} has residual files. Removing them.` ); - await fs.rm(this.install_path, { recursive: true, force: true }); + await rm(this.install_path, { recursive: true, force: true }); } logger.debug(`Making directory ${this.install_path}`); - await fs.mkdir(this.install_path, { recursive: true }); + await mkdir(this.install_path, { recursive: true }); logger.debug( `Downloading package from ${this.download} in to ${this.install_path}` ); - const pkgpath = path.join(this.install_path, 'pkg.tar.gz'); - const download = await fetch(this.download); + const pkgpath = join(this.install_path, 'pkg.tar.gz'); + // @ts-ignore + const download = (await fetch(this.download)) as fetch.Response; - const file_stream = fss.create_write_stream(pkgpath); + const file_stream = createWriteStream(pkgpath); await new Promise((resolve, reject) => { download.body.pipe(file_stream); download.body.on('error', reject); @@ -68,10 +82,10 @@ class Package { logger.debug('Validating checksums'); logger.debug(`Assert sha256(pkg.tar.gz) == ${this.checksum}`); - const hash = crypto.create_hash('sha256'); + const hash = createHash('sha256'); - const read_stream = fss.create_read_stream(pkgpath); - await new Promise((resolve, reject) => { + const read_stream = createReadStream(pkgpath); + await new Promise((resolve, reject) => { read_stream.on('data', chunk => hash.update(chunk)); read_stream.on('end', () => resolve()); read_stream.on('error', error => reject(error)); @@ -89,8 +103,8 @@ class Package { `Extracting package files from archive ${pkgpath} in to ${this.install_path}` ); - await new Promise((resolve, reject) => { - const proc = cp.exec( + await new Promise((resolve, reject) => { + const proc = exec( `bash -c 'cd "${this.install_path}" && tar xzf ${pkgpath}'` ); @@ -105,15 +119,15 @@ class Package { }); logger.debug('Registering runtime'); - runtime.load_package(this.install_path); + load_package(this.install_path); logger.debug('Caching environment'); const get_env_command = `cd ${this.install_path}; source environment; env`; - const envout = await new Promise((resolve, reject) => { + const envout = await new Promise((resolve, reject) => { let stdout = ''; - const proc = cp.spawn( + const proc = spawn( 'env', ['-i', 'bash', '-c', `${get_env_command}`], { @@ -142,14 +156,14 @@ class Package { ) .join('\n'); - await fs.write_file(path.join(this.install_path, '.env'), filtered_env); + await writeFile(join(this.install_path, '.env'), filtered_env); logger.debug('Changing Ownership of package directory'); - await util.promisify(chownr)(this.install_path, 0, 0); + await promisify(chownr)(this.install_path, 0, 0); logger.debug('Writing installed state to disk'); - await fs.write_file( - path.join(this.install_path, globals.pkg_installed_file), + await writeFile( + join(this.install_path, globals.pkg_installed_file), Date.now().toString() ); @@ -161,11 +175,11 @@ class Package { }; } - async uninstall() { + async uninstall(): Promise<{ language: string; version: string }> { logger.info(`Uninstalling ${this.language}-${this.version.raw}`); logger.debug('Finding runtime'); - const found_runtime = runtime.get_runtime_by_name_and_version( + const found_runtime = get_runtime_by_name_and_version( this.language, this.version.raw ); @@ -183,7 +197,7 @@ class Package { found_runtime.unregister(); logger.debug('Cleaning files from disk'); - await fs.rmdir(this.install_path, { recursive: true }); + await rmdir(this.install_path, { recursive: true }); logger.info(`Uninstalled ${this.language}-${this.version.raw}`); @@ -194,7 +208,10 @@ class Package { } static async get_package_list() { - const repo_content = await fetch(config.repo_url).then(x => x.text()); + // @ts-ignore + const repo_content: string = await fetch(config.repo_url).then( + (x: fetch.Response) => x.text() + ); const entries = repo_content.split('\n').filter(x => x.length > 0); @@ -210,19 +227,17 @@ class Package { }); } - static async get_package(lang, version) { + static async get_package(lang: string, version: string) { const packages = await Package.get_package_list(); const candidates = packages.filter(pkg => { - return ( - pkg.language == lang && semver.satisfies(pkg.version, version) - ); + return pkg.language == lang && satisfies(pkg.version, version); }); - candidates.sort((a, b) => semver.rcompare(a.version, b.version)); + candidates.sort((a, b) => rcompare(a.version, b.version)); return candidates[0] || null; } } -module.exports = Package; +export default Package; diff --git a/api/src/runtime.js b/api/src/runtime.ts similarity index 59% rename from api/src/runtime.js rename to api/src/runtime.ts index 6c6f10e..ae2c445 100644 --- a/api/src/runtime.js +++ b/api/src/runtime.ts @@ -1,44 +1,60 @@ -const logger = require('logplease').create('runtime'); -const semver = require('semver'); -const config = require('./config'); -const globals = require('./globals'); -const fss = require('fs'); -const path = require('path'); +import { create } from 'logplease'; +import { parse, satisfies, rcompare, type SemVer } from 'semver'; +import config from './config.js'; +import { platform } from './globals.js'; +import { readFileSync, existsSync } from 'fs'; +import { join } from 'path'; +import { Limit, Limits, PackageInfo } from './types.js'; -const runtimes = []; +const logger = create('runtime', {}); -class Runtime { - constructor({ - language, - version, - aliases, - pkgdir, - runtime, - timeouts, - memory_limits, - max_process_count, - max_open_files, - max_file_size, - output_max_size, +export const runtimes: Runtime[] = []; + +export class Runtime { + language: string; + version: SemVer; + aliases: string[]; + pkgdir: string; + runtime?: any; + timeouts: { run: number; compile: number }; + memory_limits: { run: number; compile: number }; + max_process_count: number; + max_open_files: number; + max_file_size: number; + output_max_size: number; + _compiled?: boolean; + _env_vars?: Record; + constructor(o: { + language: string; + version: SemVer; + aliases: string[]; + pkgdir: string; + runtime?: any; + timeouts: { run: number; compile: number }; + memory_limits: { run: number; compile: number }; + max_process_count: number; + max_open_files: number; + max_file_size: number; + output_max_size: number; }) { - this.language = language; - this.version = version; - this.aliases = aliases || []; - this.pkgdir = pkgdir; - this.runtime = runtime; - this.timeouts = timeouts; - this.memory_limits = memory_limits; - this.max_process_count = max_process_count; - this.max_open_files = max_open_files; - this.max_file_size = max_file_size; - this.output_max_size = output_max_size; + this.language = o.language; + this.version = o.version; + this.aliases = o.aliases || []; + this.pkgdir = o.pkgdir; + this.runtime = o.runtime; + this.timeouts = o.timeouts; + this.memory_limits = o.memory_limits; + this.max_process_count = o.max_process_count; + this.max_open_files = o.max_open_files; + this.max_file_size = o.max_file_size; + this.output_max_size = o.output_max_size; } static compute_single_limit( - language_name, - limit_name, - language_limit_overrides - ) { + language_name: string, + limit_name: Limit, + language_limit_overrides: Limits + ): number { return ( (config.limit_overrides[language_name] && config.limit_overrides[language_name][limit_name]) || @@ -48,7 +64,10 @@ class Runtime { ); } - static compute_all_limits(language_name, language_limit_overrides) { + static compute_all_limits( + language_name: string, + language_limit_overrides: Limits + ) { return { timeouts: { compile: this.compute_single_limit( @@ -97,25 +116,25 @@ class Runtime { }; } - static load_package(package_dir) { + static load_package(package_dir: string) { let info = JSON.parse( - fss.read_file_sync(path.join(package_dir, 'pkg-info.json')) - ); + readFileSync(join(package_dir, 'pkg-info.json'), 'utf8') + ) as PackageInfo; let { language, - version, + version: _version, build_platform, aliases, provides, limit_overrides, } = info; - version = semver.parse(version); + const version = parse(_version); - if (build_platform !== globals.platform) { + if (build_platform !== platform) { logger.warn( `Package ${language}-${version} was built for platform ${build_platform}, ` + - `but our platform is ${globals.platform}` + `but our platform is ${platform}` ); } @@ -153,7 +172,7 @@ class Runtime { get compiled() { if (this._compiled === undefined) { - this._compiled = fss.exists_sync(path.join(this.pkgdir, 'compile')); + this._compiled = existsSync(join(this.pkgdir, 'compile')); } return this._compiled; @@ -161,8 +180,8 @@ class Runtime { get env_vars() { if (!this._env_vars) { - const env_file = path.join(this.pkgdir, '.env'); - const env_content = fss.read_file_sync(env_file).toString(); + const env_file = join(this.pkgdir, '.env'); + const env_content = readFileSync(env_file).toString(); this._env_vars = {}; @@ -188,31 +207,32 @@ class Runtime { } } -module.exports = runtimes; -module.exports.Runtime = Runtime; -module.exports.get_runtimes_matching_language_version = function (lang, ver) { +export function get_runtimes_matching_language_version( + lang: string, + ver: string | import('semver/classes/range.js') +) { return runtimes.filter( rt => (rt.language == lang || rt.aliases.includes(lang)) && - semver.satisfies(rt.version, ver) + satisfies(rt.version, ver) ); -}; -module.exports.get_latest_runtime_matching_language_version = function ( - lang, - ver +} +export function get_latest_runtime_matching_language_version( + lang: string, + ver: string ) { - return module.exports - .get_runtimes_matching_language_version(lang, ver) - .sort((a, b) => semver.rcompare(a.version, b.version))[0]; -}; + return get_runtimes_matching_language_version(lang, ver).sort((a, b) => + rcompare(a.version, b.version) + )[0]; +} -module.exports.get_runtime_by_name_and_version = function (runtime, ver) { +export function get_runtime_by_name_and_version(runtime: string, ver: string) { return runtimes.find( rt => (rt.runtime == runtime || (rt.runtime === undefined && rt.language == runtime)) && - semver.satisfies(rt.version, ver) + satisfies(rt.version, ver) ); -}; +} -module.exports.load_package = Runtime.load_package; +export const load_package = Runtime.load_package; diff --git a/api/src/types.ts b/api/src/types.ts new file mode 100644 index 0000000..68eb36a --- /dev/null +++ b/api/src/types.ts @@ -0,0 +1,63 @@ +export interface Metadata { + language: string; + version: string; + aliases?: string[]; + dependencies?: Record; + provides: { + language: string; + aliases: string[]; + limit_overrides: Limits; + }[]; + limit_overrides?: Limits; +} + +export type Limit = + | 'compile_timeout' + | 'compile_memory_limit' + | 'max_process_count' + | 'max_open_files' + | 'max_file_size' + | 'output_max_size' + | 'run_memory_limit' + | 'run_timeout'; + +export type Limits = Record; + +export type LanguageMetadata = { + language: string; + version: string; +}; + +export type PackageInfo = Metadata & { build_platform: string }; + +export type File = { + content: string; + name?: string; + encoding?: 'base64' | 'hex' | 'utf8'; +}; +export type RequestBody = { + language: string; + version: string; + files: Array; + stdin?: string; + args?: Array; +} & Partial; + +export interface ResponseBody { + language: string; + version: string; + run: { + stdout: string; + stderr: string; + output: string; + code: number; + signal?: NodeJS.Signals; + }; +} + +export type ObjectType< + TObject extends Record>, + Key extends string +> = { + [K in keyof TObject]: TObject[K][Key]; +}; diff --git a/api/tsconfig.json b/api/tsconfig.json new file mode 100644 index 0000000..ca4d1bd --- /dev/null +++ b/api/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true, + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "nodenext", + "allowSyntheticDefaultImports": true, + "outDir": "./dist", + "rootDir": "src", + // "declaration": true + }, + "include": ["src"], + "exclude": ["dist", "node_modules"] +} diff --git a/cli/commands/ppman_commands/install.js b/cli/commands/ppman_commands/install.js index a47665d..a4254b6 100644 --- a/cli/commands/ppman_commands/install.js +++ b/cli/commands/ppman_commands/install.js @@ -27,7 +27,7 @@ const msg_format = { exports.handler = async ({ axios, packages }) => { const requests = packages.map(package => split_package(package)); - for (request of requests) { + for (const request of requests) { try { const install = await axios.post(`/api/v2/packages`, request); diff --git a/packages/deno/1.16.2/run b/packages/deno/1.16.2/run index 288919f..530181f 100644 --- a/packages/deno/1.16.2/run +++ b/packages/deno/1.16.2/run @@ -1,3 +1,3 @@ #!/bin/bash -DENO_DIR=$PWD deno run $@ +DENO_DIR=$PWD NO_COLOR=true deno run $@ diff --git a/packages/deno/1.7.5/run b/packages/deno/1.7.5/run index d1b196f..fbbe106 100644 --- a/packages/deno/1.7.5/run +++ b/packages/deno/1.7.5/run @@ -1,2 +1,2 @@ #!/bin/bash -DENO_DIR=$PWD deno run "$@" \ No newline at end of file +DENO_DIR=$PWD NO_COLOR=true deno run "$@" \ No newline at end of file diff --git a/piston b/piston index fd83727..b67f44d 100755 --- a/piston +++ b/piston @@ -78,7 +78,7 @@ case $1 in clean-pkgs) git clean -fqXd packages ;; clean-repo) git clean -fqXd repo ;; - list-pkgs) find packages -depth 2 | awk -F/ '$2 && $3{ print $2 "-" $3 }' | column ;; + list-pkgs) find packages -maxdepth 2 | awk -F/ '$2 && $3{ print $2 "-" $3 }' | column ;; build-pkg) PKGSLUG="$2-$3"