1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-12 03:54:34 +00:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Saad Jutt
940f705f5d chore(release): 0.0.32 2022-03-14 06:26:38 +05:00
Saad Jutt
7a6e6c8bec feat(web): added delete option in Drive 2022-03-14 06:26:12 +05:00
Saad Jutt
67d200d817 chore(release): 0.0.31 2022-03-14 05:36:24 +05:00
Muhammad Saad
a0c27ea8d3 Merge pull request #83 from sasjs/issue-52
fix: added cookie for accessToken
2022-03-14 05:35:59 +05:00
Saad Jutt
3d583ff21d feat(drive): new route delete file api 2022-03-14 05:30:10 +05:00
Saad Jutt
7072e282b1 fix(drive): update file API is same as create file 2022-03-14 05:05:59 +05:00
Saad Jutt
145ac45036 fix(stp): return plain/text header for GET & debug 2022-03-14 04:42:30 +05:00
Saad Jutt
698180ab7e fix: added cookie for accessToken 2022-03-09 05:06:06 +05:00
Muhammad Saad
0f4e38d51d Merge pull request #81 from sasjs/issue-79
fix: show content of get file api
2022-03-07 01:29:40 +05:00
Saad Jutt
e76283daa4 chore: few improvements 2022-03-06 18:46:09 +05:00
Saad Jutt
6ab42ca486 fix: show content of get file api 2022-03-06 18:45:07 +05:00
20 changed files with 650 additions and 397 deletions

View File

@@ -2,6 +2,28 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.0.32](https://github.com/sasjs/server/compare/v0.0.31...v0.0.32) (2022-03-14)
### Features
* **web:** added delete option in Drive ([7a6e6c8](https://github.com/sasjs/server/commit/7a6e6c8becab31410d0a36bcc22e13d5359a6cdf))
### [0.0.31](https://github.com/sasjs/server/compare/v0.0.30...v0.0.31) (2022-03-14)
### Features
* **drive:** new route delete file api ([3d583ff](https://github.com/sasjs/server/commit/3d583ff21d344a71aa861c7e5b1426ebc2d54c22))
### Bug Fixes
* added cookie for accessToken ([698180a](https://github.com/sasjs/server/commit/698180ab7e44d67d46c84352ececca5b6c83b230))
* **drive:** update file API is same as create file ([7072e28](https://github.com/sasjs/server/commit/7072e282b1cd1a296d81512c57130237610c1c1e))
* show content of get file api ([6ab42ca](https://github.com/sasjs/server/commit/6ab42ca4868366874f5f21bd711b7b8b72e36774))
* **stp:** return plain/text header for GET & debug ([145ac45](https://github.com/sasjs/server/commit/145ac450365ed39279248ec9321bbe4918bee9fa))
### [0.0.30](https://github.com/sasjs/server/compare/v0.0.29...v0.0.30) (2022-03-05) ### [0.0.30](https://github.com/sasjs/server/compare/v0.0.29...v0.0.30) (2022-03-05)

428
api/package-lock.json generated
View File

@@ -11,6 +11,7 @@
"@sasjs/core": "4.9.0", "@sasjs/core": "4.9.0",
"@sasjs/utils": "2.34.1", "@sasjs/utils": "2.34.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.17.1", "express": "^4.17.1",
"joi": "^17.4.2", "joi": "^17.4.2",
@@ -27,6 +28,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/bcryptjs": "^2.4.2", "@types/bcryptjs": "^2.4.2",
"@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.12", "@types/cors": "^2.8.12",
"@types/express": "^4.17.12", "@types/express": "^4.17.12",
"@types/jest": "^26.0.24", "@types/jest": "^26.0.24",
@@ -42,7 +44,7 @@
"jest": "^27.0.6", "jest": "^27.0.6",
"mongodb-memory-server": "^8.0.0", "mongodb-memory-server": "^8.0.0",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"pkg": "^5.4.1", "pkg": "5.5.2",
"prettier": "^2.3.1", "prettier": "^2.3.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"supertest": "^6.1.3", "supertest": "^6.1.3",
@@ -111,15 +113,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/core/node_modules/@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core/node_modules/@babel/highlight": { "node_modules/@babel/core/node_modules/@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -347,15 +340,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-optimise-call-expression": { "node_modules/@babel/helper-optimise-call-expression": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz",
@@ -417,10 +401,13 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.14.0", "version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
"dev": true "dev": true,
"engines": {
"node": ">=6.9.0"
}
}, },
"node_modules/@babel/helper-validator-option": { "node_modules/@babel/helper-validator-option": {
"version": "7.14.5", "version": "7.14.5",
@@ -498,9 +485,9 @@
"dev": true "dev": true
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.14.7", "version": "7.16.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.2.tgz",
"integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", "integrity": "sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==",
"dev": true, "dev": true,
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -697,15 +684,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/template/node_modules/@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template/node_modules/@babel/highlight": { "node_modules/@babel/template/node_modules/@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -793,15 +771,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse/node_modules/@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse/node_modules/@babel/highlight": { "node_modules/@babel/traverse/node_modules/@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -881,27 +850,18 @@
"dev": true "dev": true
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.14.5", "version": "7.16.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz",
"integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.14.5", "@babel/helper-validator-identifier": "^7.15.7",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/types/node_modules/@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@bcoe/v8-coverage": { "node_modules/@bcoe/v8-coverage": {
"version": "0.2.3", "version": "0.2.3",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
@@ -1406,9 +1366,9 @@
} }
}, },
"node_modules/@nodelib/fs.walk": { "node_modules/@nodelib/fs.walk": {
"version": "1.2.7", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.scandir": "2.1.5", "@nodelib/fs.scandir": "2.1.5",
@@ -1836,6 +1796,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/cookie-parser": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.2.tgz",
"integrity": "sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==",
"dev": true,
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/cookiejar": { "node_modules/@types/cookiejar": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz",
@@ -3296,6 +3265,26 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
"dependencies": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -4009,20 +3998,19 @@
} }
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.5", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3", "@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.0", "glob-parent": "^5.1.2",
"merge2": "^1.3.0", "merge2": "^1.3.0",
"micromatch": "^4.0.2", "micromatch": "^4.0.4"
"picomatch": "^2.2.1"
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8.6.0"
} }
}, },
"node_modules/fast-json-stable-stringify": { "node_modules/fast-json-stable-stringify": {
@@ -4044,9 +4032,9 @@
"dev": true "dev": true
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.11.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"reusify": "^1.0.4" "reusify": "^1.0.4"
@@ -4479,16 +4467,16 @@
} }
}, },
"node_modules/globby": { "node_modules/globby": {
"version": "11.0.3", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"array-union": "^2.1.0", "array-union": "^2.1.0",
"dir-glob": "^3.0.1", "dir-glob": "^3.0.1",
"fast-glob": "^3.1.1", "fast-glob": "^3.2.9",
"ignore": "^5.1.4", "ignore": "^5.2.0",
"merge2": "^1.3.0", "merge2": "^1.4.1",
"slash": "^3.0.0" "slash": "^3.0.0"
}, },
"engines": { "engines": {
@@ -4771,9 +4759,9 @@
] ]
}, },
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.1.8", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@@ -7576,12 +7564,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true "dev": true
}, },
"node_modules/noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
"dev": true
},
"node_modules/nopt": { "node_modules/nopt": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
@@ -7933,26 +7915,26 @@
} }
}, },
"node_modules/pkg": { "node_modules/pkg": {
"version": "5.4.1", "version": "5.5.2",
"resolved": "https://registry.npmjs.org/pkg/-/pkg-5.4.1.tgz", "resolved": "https://registry.npmjs.org/pkg/-/pkg-5.5.2.tgz",
"integrity": "sha512-iJs3W6MCgeZ4MrH7iZtX6HTqsNzoh2U9rGILL3eOLbQFV43U8WPAzrqRK7cBQGuHx38UXxcGT6G/2yDl/GveRg==", "integrity": "sha512-pD0UB2ud01C6pVv2wpGsTYJrXI/bnvGRYvMLd44wFzA1p+A2jrlTGFPAYa7YEYzmitXhx23PqalaG1eUEnSwcA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/parser": "7.13.13", "@babel/parser": "7.16.2",
"@babel/types": "7.13.12", "@babel/types": "7.16.0",
"chalk": "^4.1.0", "chalk": "^4.1.2",
"escodegen": "^2.0.0", "escodegen": "^2.0.0",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"globby": "^11.0.3", "globby": "^11.0.4",
"into-stream": "^6.0.0", "into-stream": "^6.0.0",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"multistream": "^4.1.0", "multistream": "^4.1.0",
"pkg-fetch": "3.2.4", "pkg-fetch": "3.2.6",
"prebuild-install": "6.0.1", "prebuild-install": "6.1.4",
"progress": "^2.0.3", "progress": "^2.0.3",
"resolve": "^1.20.0", "resolve": "^1.20.0",
"stream-meter": "^1.0.4", "stream-meter": "^1.0.4",
"tslib": "2.1.0" "tslib": "2.3.1"
}, },
"bin": { "bin": {
"pkg": "lib-es5/bin.js" "pkg": "lib-es5/bin.js"
@@ -7979,17 +7961,18 @@
} }
}, },
"node_modules/pkg-fetch": { "node_modules/pkg-fetch": {
"version": "3.2.4", "version": "3.2.6",
"resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.2.4.tgz", "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.2.6.tgz",
"integrity": "sha512-ewUD26GP86/8+Fu93zrb30CpJjKOtT4maSgm4SwTX9Ujy1pfdUdv+1PubsY9tTJES0iBYItAtqbfkf7Wu5LV9w==", "integrity": "sha512-Q8fx6SIT022g0cdSE4Axv/xpfHeltspo2gg1KsWRinLQZOTRRAtOOaEFghA1F3jJ8FVsh8hGrL/Pb6Ea5XHIFw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chalk": "^4.1.0", "chalk": "^4.1.2",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"https-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.6",
"progress": "^2.0.3", "progress": "^2.0.3",
"semver": "^7.3.5", "semver": "^7.3.5",
"tar-fs": "^2.1.1",
"yargs": "^16.2.0" "yargs": "^16.2.0"
}, },
"bin": { "bin": {
@@ -8063,29 +8046,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/pkg/node_modules/@babel/parser": {
"version": "7.13.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/pkg/node_modules/@babel/types": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz",
"integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.12.11",
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
"node_modules/pkg/node_modules/chalk": { "node_modules/pkg/node_modules/chalk": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -8138,16 +8098,10 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/pkg/node_modules/tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
"dev": true
},
"node_modules/prebuild-install": { "node_modules/prebuild-install": {
"version": "6.0.1", "version": "6.1.4",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.1.tgz", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz",
"integrity": "sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==", "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"detect-libc": "^1.0.3", "detect-libc": "^1.0.3",
@@ -8156,15 +8110,13 @@
"minimist": "^1.2.3", "minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3", "mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1", "napi-build-utils": "^1.0.1",
"node-abi": "^2.7.0", "node-abi": "^2.21.0",
"noop-logger": "^0.1.1",
"npmlog": "^4.0.1", "npmlog": "^4.0.1",
"pump": "^3.0.0", "pump": "^3.0.0",
"rc": "^1.2.7", "rc": "^1.2.7",
"simple-get": "^3.0.3", "simple-get": "^3.0.3",
"tar-fs": "^2.0.0", "tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0"
"which-pm-runs": "^1.0.0"
}, },
"bin": { "bin": {
"prebuild-install": "bin.js" "prebuild-install": "bin.js"
@@ -9862,12 +9814,6 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
}, },
"node_modules/which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
"dev": true
},
"node_modules/wide-align": { "node_modules/wide-align": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
@@ -10122,12 +10068,6 @@
"@babel/highlight": "^7.14.5" "@babel/highlight": "^7.14.5"
} }
}, },
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
},
"@babel/highlight": { "@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -10303,14 +10243,6 @@
"@babel/template": "^7.14.5", "@babel/template": "^7.14.5",
"@babel/traverse": "^7.14.5", "@babel/traverse": "^7.14.5",
"@babel/types": "^7.14.5" "@babel/types": "^7.14.5"
},
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
}
} }
}, },
"@babel/helper-optimise-call-expression": { "@babel/helper-optimise-call-expression": {
@@ -10359,9 +10291,9 @@
} }
}, },
"@babel/helper-validator-identifier": { "@babel/helper-validator-identifier": {
"version": "7.14.0", "version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
"dev": true "dev": true
}, },
"@babel/helper-validator-option": { "@babel/helper-validator-option": {
@@ -10430,9 +10362,9 @@
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.14.7", "version": "7.16.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.2.tgz",
"integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", "integrity": "sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==",
"dev": true "dev": true
}, },
"@babel/plugin-syntax-async-generators": { "@babel/plugin-syntax-async-generators": {
@@ -10572,12 +10504,6 @@
"@babel/highlight": "^7.14.5" "@babel/highlight": "^7.14.5"
} }
}, },
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
},
"@babel/highlight": { "@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -10652,12 +10578,6 @@
"@babel/highlight": "^7.14.5" "@babel/highlight": "^7.14.5"
} }
}, },
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
},
"@babel/highlight": { "@babel/highlight": {
"version": "7.14.5", "version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
@@ -10722,21 +10642,13 @@
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.14.5", "version": "7.16.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz",
"integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.14.5", "@babel/helper-validator-identifier": "^7.15.7",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
},
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
}
} }
}, },
"@bcoe/v8-coverage": { "@bcoe/v8-coverage": {
@@ -11129,9 +11041,9 @@
"dev": true "dev": true
}, },
"@nodelib/fs.walk": { "@nodelib/fs.walk": {
"version": "1.2.7", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@nodelib/fs.scandir": "2.1.5", "@nodelib/fs.scandir": "2.1.5",
@@ -11500,6 +11412,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/cookie-parser": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.2.tgz",
"integrity": "sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/cookiejar": { "@types/cookiejar": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz",
@@ -12702,6 +12623,22 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
}, },
"cookie-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
"requires": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"dependencies": {
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
}
}
},
"cookie-signature": { "cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -13261,17 +13198,16 @@
} }
}, },
"fast-glob": { "fast-glob": {
"version": "3.2.5", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
"dev": true, "dev": true,
"requires": { "requires": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3", "@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.0", "glob-parent": "^5.1.2",
"merge2": "^1.3.0", "merge2": "^1.3.0",
"micromatch": "^4.0.2", "micromatch": "^4.0.4"
"picomatch": "^2.2.1"
} }
}, },
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
@@ -13293,9 +13229,9 @@
"dev": true "dev": true
}, },
"fastq": { "fastq": {
"version": "1.11.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
"dev": true, "dev": true,
"requires": { "requires": {
"reusify": "^1.0.4" "reusify": "^1.0.4"
@@ -13628,16 +13564,16 @@
} }
}, },
"globby": { "globby": {
"version": "11.0.3", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true, "dev": true,
"requires": { "requires": {
"array-union": "^2.1.0", "array-union": "^2.1.0",
"dir-glob": "^3.0.1", "dir-glob": "^3.0.1",
"fast-glob": "^3.1.1", "fast-glob": "^3.2.9",
"ignore": "^5.1.4", "ignore": "^5.2.0",
"merge2": "^1.3.0", "merge2": "^1.4.1",
"slash": "^3.0.0" "slash": "^3.0.0"
} }
}, },
@@ -13835,9 +13771,9 @@
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
}, },
"ignore": { "ignore": {
"version": "5.1.8", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"dev": true "dev": true
}, },
"ignore-by-default": { "ignore-by-default": {
@@ -15952,12 +15888,6 @@
} }
} }
}, },
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
"dev": true
},
"nopt": { "nopt": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
@@ -16209,45 +16139,28 @@
} }
}, },
"pkg": { "pkg": {
"version": "5.4.1", "version": "5.5.2",
"resolved": "https://registry.npmjs.org/pkg/-/pkg-5.4.1.tgz", "resolved": "https://registry.npmjs.org/pkg/-/pkg-5.5.2.tgz",
"integrity": "sha512-iJs3W6MCgeZ4MrH7iZtX6HTqsNzoh2U9rGILL3eOLbQFV43U8WPAzrqRK7cBQGuHx38UXxcGT6G/2yDl/GveRg==", "integrity": "sha512-pD0UB2ud01C6pVv2wpGsTYJrXI/bnvGRYvMLd44wFzA1p+A2jrlTGFPAYa7YEYzmitXhx23PqalaG1eUEnSwcA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/parser": "7.13.13", "@babel/parser": "7.16.2",
"@babel/types": "7.13.12", "@babel/types": "7.16.0",
"chalk": "^4.1.0", "chalk": "^4.1.2",
"escodegen": "^2.0.0", "escodegen": "^2.0.0",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"globby": "^11.0.3", "globby": "^11.0.4",
"into-stream": "^6.0.0", "into-stream": "^6.0.0",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"multistream": "^4.1.0", "multistream": "^4.1.0",
"pkg-fetch": "3.2.4", "pkg-fetch": "3.2.6",
"prebuild-install": "6.0.1", "prebuild-install": "6.1.4",
"progress": "^2.0.3", "progress": "^2.0.3",
"resolve": "^1.20.0", "resolve": "^1.20.0",
"stream-meter": "^1.0.4", "stream-meter": "^1.0.4",
"tslib": "2.1.0" "tslib": "2.3.1"
}, },
"dependencies": { "dependencies": {
"@babel/parser": {
"version": "7.13.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==",
"dev": true
},
"@babel/types": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz",
"integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
"chalk": { "chalk": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -16284,12 +16197,6 @@
"requires": { "requires": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
} }
},
"tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
"dev": true
} }
} }
}, },
@@ -16303,17 +16210,18 @@
} }
}, },
"pkg-fetch": { "pkg-fetch": {
"version": "3.2.4", "version": "3.2.6",
"resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.2.4.tgz", "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.2.6.tgz",
"integrity": "sha512-ewUD26GP86/8+Fu93zrb30CpJjKOtT4maSgm4SwTX9Ujy1pfdUdv+1PubsY9tTJES0iBYItAtqbfkf7Wu5LV9w==", "integrity": "sha512-Q8fx6SIT022g0cdSE4Axv/xpfHeltspo2gg1KsWRinLQZOTRRAtOOaEFghA1F3jJ8FVsh8hGrL/Pb6Ea5XHIFw==",
"dev": true, "dev": true,
"requires": { "requires": {
"chalk": "^4.1.0", "chalk": "^4.1.2",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"https-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.6",
"progress": "^2.0.3", "progress": "^2.0.3",
"semver": "^7.3.5", "semver": "^7.3.5",
"tar-fs": "^2.1.1",
"yargs": "^16.2.0" "yargs": "^16.2.0"
}, },
"dependencies": { "dependencies": {
@@ -16366,9 +16274,9 @@
} }
}, },
"prebuild-install": { "prebuild-install": {
"version": "6.0.1", "version": "6.1.4",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.1.tgz", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz",
"integrity": "sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==", "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"detect-libc": "^1.0.3", "detect-libc": "^1.0.3",
@@ -16377,15 +16285,13 @@
"minimist": "^1.2.3", "minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3", "mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1", "napi-build-utils": "^1.0.1",
"node-abi": "^2.7.0", "node-abi": "^2.21.0",
"noop-logger": "^0.1.1",
"npmlog": "^4.0.1", "npmlog": "^4.0.1",
"pump": "^3.0.0", "pump": "^3.0.0",
"rc": "^1.2.7", "rc": "^1.2.7",
"simple-get": "^3.0.3", "simple-get": "^3.0.3",
"tar-fs": "^2.0.0", "tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0"
"which-pm-runs": "^1.0.0"
} }
}, },
"prelude-ls": { "prelude-ls": {
@@ -17646,12 +17552,6 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
}, },
"which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
"dev": true
},
"wide-align": { "wide-align": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",

View File

@@ -48,6 +48,7 @@
"@sasjs/core": "4.9.0", "@sasjs/core": "4.9.0",
"@sasjs/utils": "2.34.1", "@sasjs/utils": "2.34.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.17.1", "express": "^4.17.1",
"joi": "^17.4.2", "joi": "^17.4.2",
@@ -61,6 +62,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/bcryptjs": "^2.4.2", "@types/bcryptjs": "^2.4.2",
"@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.12", "@types/cors": "^2.8.12",
"@types/express": "^4.17.12", "@types/express": "^4.17.12",
"@types/jest": "^26.0.24", "@types/jest": "^26.0.24",
@@ -76,7 +78,7 @@
"jest": "^27.0.6", "jest": "^27.0.6",
"mongodb-memory-server": "^8.0.0", "mongodb-memory-server": "^8.0.0",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"pkg": "^5.4.1", "pkg": "5.5.2",
"prettier": "^2.3.1", "prettier": "^2.3.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"supertest": "^6.1.3", "supertest": "^6.1.3",

View File

@@ -233,21 +233,6 @@ components:
- status - status
type: object type: object
additionalProperties: false additionalProperties: false
FilePayload:
properties:
filePath:
type: string
description: 'Path of the file'
example: /Public/somefolder/some.file
fileContent:
type: string
description: 'Contents of the file'
example: 'Contents of the File'
required:
- filePath
- fileContent
type: object
additionalProperties: false
TreeNode: TreeNode:
properties: properties:
name: name:
@@ -600,6 +585,7 @@ paths:
responses: responses:
'204': '204':
description: 'No content' description: 'No content'
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
summary: 'Get file from SASjs Drive' summary: 'Get file from SASjs Drive'
tags: tags:
- Drive - Drive
@@ -609,11 +595,57 @@ paths:
parameters: parameters:
- -
in: query in: query
name: filePath name: _filePath
required: true required: false
schema: schema:
type: string type: string
example: /Public/somefolder/some.file example: /Public/somefolder/some.file
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
filePath:
type: string
delete:
operationId: DeleteFile
responses:
'200':
description: Ok
content:
application/json:
schema:
properties:
status: {type: string}
required:
- status
type: object
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
summary: 'Delete file from SASjs Drive'
tags:
- Drive
security:
-
bearerAuth: []
parameters:
-
in: query
name: _filePath
required: false
schema:
type: string
example: /Public/somefolder/some.file
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
filePath:
type: string
post: post:
operationId: SaveFile operationId: SaveFile
responses: responses:
@@ -626,7 +658,7 @@ paths:
examples: examples:
'Example 1': 'Example 1':
value: {status: success} value: {status: success}
'400': '403':
description: 'File already exists' description: 'File already exists'
content: content:
application/json: application/json:
@@ -635,7 +667,7 @@ paths:
examples: examples:
'Example 1': 'Example 1':
value: {status: failure, message: 'File request failed.'} value: {status: failure, message: 'File request failed.'}
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provided else API will respond with Bad Request." description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
summary: 'Create a file in SASjs Drive' summary: 'Create a file in SASjs Drive'
tags: tags:
- Drive - Drive
@@ -677,8 +709,8 @@ paths:
examples: examples:
'Example 1': 'Example 1':
value: {status: success} value: {status: success}
'400': '403':
description: 'Unable to get File' description: ""
content: content:
application/json: application/json:
schema: schema:
@@ -686,19 +718,36 @@ paths:
examples: examples:
'Example 1': 'Example 1':
value: {status: failure, message: 'File request failed.'} value: {status: failure, message: 'File request failed.'}
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
summary: 'Modify a file in SASjs Drive' summary: 'Modify a file in SASjs Drive'
tags: tags:
- Drive - Drive
security: security:
- -
bearerAuth: [] bearerAuth: []
parameters: [] parameters:
-
description: 'Location of SAS program'
in: query
name: _filePath
required: false
schema:
type: string
example: /Public/somefolder/some.file.sas
requestBody: requestBody:
required: true required: true
content: content:
application/json: multipart/form-data:
schema: schema:
$ref: '#/components/schemas/FilePayload' type: object
properties:
file:
type: string
format: binary
filePath:
type: string
required:
- file
/SASjsApi/drive/filetree: /SASjsApi/drive/filetree:
get: get:
operationId: GetFileTree operationId: GetFileTree
@@ -1054,7 +1103,7 @@ paths:
anyOf: anyOf:
- {type: string} - {type: string}
- {type: string, format: byte} - {type: string, format: byte}
description: "Trigger a SAS program using it's location in the _program URL parameter.\nEnable debugging using the _debug URL parameter. Setting _debug=131 will\ncause the log to be streamed in the output.\n\nAdditional URL parameters are turned into SAS macro variables.\n\nAny files provided in the request body are placed into the SAS session with\ncorresponding _WEBIN_XXX variables created.\n\nThe response headers can be adjusted using the mfs_httpheader() macro. Any\nfile type can be returned, including binary files such as zip or xls.\n\nThis behaviour differs for POST requests, in which case the reponse is\nalways JSON." description: "Trigger a SAS program using it's location in the _program URL parameter.\nEnable debugging using the _debug URL parameter. Setting _debug=131 will\ncause the log to be streamed in the output.\n\nAdditional URL parameters are turned into SAS macro variables.\n\nAny files provided in the request body are placed into the SAS session with\ncorresponding _WEBIN_XXX variables created.\n\nThe response headers can be adjusted using the mfs_httpheader() macro. Any\nfile type can be returned, including binary files such as zip or xls.\n\nIf _debug is >= 131, response headers will contain Content-Type: 'text/plain'\n\nThis behaviour differs for POST requests, in which case the response is\nalways JSON."
summary: 'Execute Stored Program, return raw _webout content.' summary: 'Execute Stored Program, return raw _webout content.'
tags: tags:
- STP - STP

View File

@@ -9,8 +9,6 @@ export const copySASjsCore = async () => {
await deleteFolder(sasJSCoreMacros) await deleteFolder(sasJSCoreMacros)
await createFolder(sasJSCoreMacros) await createFolder(sasJSCoreMacros)
console.log('Copying SASjs Core Macros...')
const foldersToCopy = ['base', 'ddl', 'fcmp', 'lua', 'server'] const foldersToCopy = ['base', 'ddl', 'fcmp', 'lua', 'server']
await asyncForEach(foldersToCopy, async (coreSubFolder) => { await asyncForEach(foldersToCopy, async (coreSubFolder) => {
@@ -18,8 +16,6 @@ export const copySASjsCore = async () => {
await copy(coreSubFolderPath, sasJSCoreMacros) await copy(coreSubFolderPath, sasJSCoreMacros)
}) })
console.log('Macros available at: ', sasJSCoreMacros)
} }
copySASjsCore() copySASjsCore()

View File

@@ -1,10 +1,16 @@
import path from 'path' import path from 'path'
import express, { ErrorRequestHandler } from 'express' import express, { ErrorRequestHandler } from 'express'
import morgan from 'morgan' import morgan from 'morgan'
import cookieParser from 'cookie-parser'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import cors from 'cors' import cors from 'cors'
import { connectDB, getWebBuildFolderPath, setProcessVariables } from './utils' import {
connectDB,
getWebBuildFolderPath,
sasJSCoreMacros,
setProcessVariables
} from './utils'
dotenv.config() dotenv.config()
@@ -21,8 +27,9 @@ if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') {
app.use(cors({ credentials: true, origin: whiteList })) app.use(cors({ credentials: true, origin: whiteList }))
} }
app.use(express.json({ limit: '50mb' })) app.use(cookieParser())
app.use(morgan('tiny')) app.use(morgan('tiny'))
app.use(express.json({ limit: '50mb' }))
app.use(express.static(path.join(__dirname, '../public'))) app.use(express.static(path.join(__dirname, '../public')))
app.use(express.static(getWebBuildFolderPath())) app.use(express.static(getWebBuildFolderPath()))
@@ -37,6 +44,8 @@ export default setProcessVariables().then(async () => {
const { setupRoutes } = await import('./routes/setupRoutes') const { setupRoutes } = await import('./routes/setupRoutes')
setupRoutes(app) setupRoutes(app)
console.log('sasJSCoreMacros', sasJSCoreMacros)
app.use(onError) app.use(onError)
await connectDB() await connectDB()

View File

@@ -13,9 +13,15 @@ import {
Get, Get,
Patch, Patch,
UploadedFile, UploadedFile,
FormField FormField,
Delete
} from 'tsoa' } from 'tsoa'
import { fileExists, createFile, moveFile, createFolder } from '@sasjs/utils' import {
fileExists,
moveFile,
createFolder,
deleteFile as deleteFileOnSystem
} from '@sasjs/utils'
import { createFileTree, ExecutionController, getTreeExample } from './internal' import { createFileTree, ExecutionController, getTreeExample } from './internal'
import { FileTree, isFileTree, TreeNode } from '../types' import { FileTree, isFileTree, TreeNode } from '../types'
@@ -25,18 +31,6 @@ interface DeployPayload {
appLoc?: string appLoc?: string
fileTree: FileTree fileTree: FileTree
} }
interface FilePayload {
/**
* Path of the file
* @example "/Public/somefolder/some.file"
*/
filePath: string
/**
* Contents of the file
* @example "Contents of the File"
*/
fileContent: string
}
interface DeployResponse { interface DeployResponse {
status: string status: string
@@ -93,22 +87,45 @@ export class DriveController {
} }
/** /**
* It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field.
* But it's required to provide else API will respond with Bad Request.
*
* @summary Get file from SASjs Drive * @summary Get file from SASjs Drive
* @query filePath Location of SAS program * @query _filePath Location of SAS program
* @example filePath "/Public/somefolder/some.file" * @example _filePath "/Public/somefolder/some.file"
*/ */
@Get('/file') @Get('/file')
public async getFile( public async getFile(
@Request() request: express.Request, @Request() request: express.Request,
@Query() filePath: string
@Query() _filePath?: string,
@FormField() filePath?: string
) { ) {
return getFile(request, filePath) return getFile(request, (_filePath ?? filePath)!)
} }
/** /**
* It's optional to either provide `_filePath` in url as query parameter * It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field. * Or provide `filePath` in body as form field.
* But it's required to provided else API will respond with Bad Request. * But it's required to provide else API will respond with Bad Request.
*
* @summary Delete file from SASjs Drive
* @query _filePath Location of SAS program
* @example _filePath "/Public/somefolder/some.file"
*/
@Delete('/file')
public async deleteFile(
@Query() _filePath?: string,
@FormField() filePath?: string
) {
return deleteFile((_filePath ?? filePath)!)
}
/**
* It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field.
* But it's required to provide else API will respond with Bad Request.
* *
* @summary Create a file in SASjs Drive * @summary Create a file in SASjs Drive
* @param _filePath Location of SAS program * @param _filePath Location of SAS program
@@ -118,7 +135,7 @@ export class DriveController {
@Example<UpdateFileResponse>({ @Example<UpdateFileResponse>({
status: 'success' status: 'success'
}) })
@Response<UpdateFileResponse>(400, 'File already exists', { @Response<UpdateFileResponse>(403, 'File already exists', {
status: 'failure', status: 'failure',
message: 'File request failed.' message: 'File request failed.'
}) })
@@ -132,21 +149,29 @@ export class DriveController {
} }
/** /**
* It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field.
* But it's required to provide else API will respond with Bad Request.
*
* @summary Modify a file in SASjs Drive * @summary Modify a file in SASjs Drive
* @param _filePath Location of SAS program
* @example _filePath "/Public/somefolder/some.file.sas"
* *
*/ */
@Example<UpdateFileResponse>({ @Example<UpdateFileResponse>({
status: 'success' status: 'success'
}) })
@Response<UpdateFileResponse>(400, 'Unable to get File', { @Response<UpdateFileResponse>(403, `File doesn't exist`, {
status: 'failure', status: 'failure',
message: 'File request failed.' message: 'File request failed.'
}) })
@Patch('/file') @Patch('/file')
public async updateFile( public async updateFile(
@Body() body: FilePayload @UploadedFile() file: Express.Multer.File,
@Query() _filePath?: string,
@FormField() filePath?: string
): Promise<UpdateFileResponse> { ): Promise<UpdateFileResponse> {
return updateFile(body) return updateFile((_filePath ?? filePath)!, file)
} }
/** /**
@@ -194,7 +219,32 @@ const getFile = async (req: express.Request, filePath: string) => {
throw new Error('File does not exist.') throw new Error('File does not exist.')
} }
req.res?.download(filePathFull) const extension = path.extname(filePathFull).toLowerCase()
if (extension === '.sas') {
req.res?.setHeader('Content-type', 'text/plain')
}
req.res?.sendFile(path.resolve(filePathFull))
}
const deleteFile = async (filePath: string) => {
const driveFilesPath = getTmpFilesFolderPath()
const filePathFull = path
.join(getTmpFilesFolderPath(), filePath)
.replace(new RegExp('/', 'g'), path.sep)
if (!filePathFull.includes(driveFilesPath)) {
throw new Error('Cannot delete file outside drive.')
}
if (!(await fileExists(filePathFull))) {
throw new Error('File does not exist.')
}
await deleteFileOnSystem(filePathFull)
return { status: 'success' }
} }
const saveFile = async ( const saveFile = async (
@@ -222,25 +272,27 @@ const saveFile = async (
return { status: 'success' } return { status: 'success' }
} }
const updateFile = async (body: FilePayload): Promise<GetFileResponse> => { const updateFile = async (
const { filePath, fileContent } = body filePath: string,
try { multerFile: Express.Multer.File
const filePathFull = path ): Promise<GetFileResponse> => {
.join(getTmpFilesFolderPath(), filePath) const driveFilesPath = getTmpFilesFolderPath()
.replace(new RegExp('/', 'g'), path.sep)
await validateFilePath(filePathFull) const filePathFull = path
await createFile(filePathFull, fileContent) .join(driveFilesPath, filePath)
.replace(new RegExp('/', 'g'), path.sep)
return { status: 'success' } if (!filePathFull.includes(driveFilesPath)) {
} catch (err: any) { throw new Error('Cannot modify file outside drive.')
throw {
code: 400,
status: 'failure',
message: 'File request failed.',
error: typeof err === 'object' ? err.toString() : err
}
} }
if (!(await fileExists(filePathFull))) {
throw new Error(`File doesn't exist.`)
}
await moveFile(multerFile.path, filePathFull)
return { status: 'success' }
} }
const validateFilePath = async (filePath: string) => { const validateFilePath = async (filePath: string) => {

View File

@@ -14,6 +14,7 @@ import {
generateFileUploadSasCode, generateFileUploadSasCode,
getTmpFilesFolderPath, getTmpFilesFolderPath,
HTTPHeaders, HTTPHeaders,
isDebugOn,
sasJSCoreMacros sasJSCoreMacros
} from '../../utils' } from '../../utils'
@@ -160,9 +161,6 @@ ${program}`
: await readFile(weboutPath) : await readFile(weboutPath)
: '' : ''
const debugValue =
typeof vars._debug === 'string' ? parseInt(vars._debug) : vars._debug
// it should be deleted by scheduleSessionDestroy // it should be deleted by scheduleSessionDestroy
session.inUse = false session.inUse = false
@@ -170,8 +168,7 @@ ${program}`
return { return {
httpHeaders, httpHeaders,
webout, webout,
log: log: isDebugOn(vars) || session.crashed ? log : undefined
(debugValue && debugValue >= 131) || session.crashed ? log : undefined
} }
} }
@@ -179,7 +176,7 @@ ${program}`
httpHeaders, httpHeaders,
result: fileResponse result: fileResponse
? webout ? webout
: (debugValue && debugValue >= 131) || session.crashed : isDebugOn(vars) || session.crashed
? `<html><body>${webout}<div style="text-align:left"><hr /><h2>SAS Log</h2><pre>${log}</pre></div></body></html>` ? `<html><body>${webout}<div style="text-align:left"><hr /><h2>SAS Log</h2><pre>${log}</pre></div></body></html>`
: webout : webout
} }

View File

@@ -21,6 +21,7 @@ import { PreProgramVars } from '../types'
import { import {
getTmpFilesFolderPath, getTmpFilesFolderPath,
HTTPHeaders, HTTPHeaders,
isDebugOn,
LogLine, LogLine,
makeFilesNamesMap, makeFilesNamesMap,
parseLogToArray parseLogToArray
@@ -62,7 +63,9 @@ export class STPController {
* The response headers can be adjusted using the mfs_httpheader() macro. Any * The response headers can be adjusted using the mfs_httpheader() macro. Any
* file type can be returned, including binary files such as zip or xls. * file type can be returned, including binary files such as zip or xls.
* *
* This behaviour differs for POST requests, in which case the reponse is * If _debug is >= 131, response headers will contain Content-Type: 'text/plain'
*
* This behaviour differs for POST requests, in which case the response is
* always JSON. * always JSON.
* *
* @summary Execute Stored Program, return raw _webout content. * @summary Execute Stored Program, return raw _webout content.
@@ -140,6 +143,13 @@ const executeReturnRaw = async (
query query
)) as ExecuteReturnRaw )) as ExecuteReturnRaw
// Should over-ride response header for
// debug on GET request to see entire log
// rendering on browser.
if (isDebugOn(query)) {
httpHeaders['content-type'] = 'text/plain'
}
req.res?.set(httpHeaders) req.res?.set(httpHeaders)
if (result instanceof Buffer) { if (result instanceof Buffer) {

View File

@@ -43,7 +43,9 @@ const authenticateToken = (
} }
const authHeader = req.headers['authorization'] const authHeader = req.headers['authorization']
const token = authHeader?.split(' ')[1] const token =
authHeader?.split(' ')[1] ??
(tokenType === 'accessToken' ? req.cookies.accessToken : '')
if (!token) return res.sendStatus(401) if (!token) return res.sendStatus(401)
jwt.verify(token, key, async (err: any, data: any) => { jwt.verify(token, key, async (err: any, data: any) => {

View File

@@ -55,8 +55,9 @@ authRouter.post('/token', async (req, res) => {
const controller = new AuthController() const controller = new AuthController()
try { try {
const response = await controller.token(body) const response = await controller.token(body)
const { accessToken } = response
res.send(response) res.cookie('accessToken', accessToken).send(response)
} catch (err: any) { } catch (err: any) {
res.status(403).send(err.toString()) res.status(403).send(err.toString())
} }

View File

@@ -3,12 +3,7 @@ import { deleteFile } from '@sasjs/utils'
import { multerSingle } from '../../middlewares/multer' import { multerSingle } from '../../middlewares/multer'
import { DriveController } from '../../controllers/' import { DriveController } from '../../controllers/'
import { import { fileBodyValidation, fileParamValidation } from '../../utils'
getFileDriveValidation,
updateFileDriveValidation,
uploadFileBodyValidation,
uploadFileParamValidation
} from '../../utils'
const controller = new DriveController() const controller = new DriveController()
@@ -28,11 +23,27 @@ driveRouter.post('/deploy', async (req, res) => {
}) })
driveRouter.get('/file', async (req, res) => { driveRouter.get('/file', async (req, res) => {
const { error, value: query } = getFileDriveValidation(req.query) const { error: errQ, value: query } = fileParamValidation(req.query)
if (error) return res.status(400).send(error.details[0].message) const { error: errB, value: body } = fileBodyValidation(req.body)
if (errQ && errB) return res.status(400).send(errB.details[0].message)
try { try {
await controller.getFile(req, query.filePath) await controller.getFile(req, query._filePath, body.filePath)
} catch (err: any) {
res.status(403).send(err.toString())
}
})
driveRouter.delete('/file', async (req, res) => {
const { error: errQ, value: query } = fileParamValidation(req.query)
const { error: errB, value: body } = fileBodyValidation(req.body)
if (errQ && errB) return res.status(400).send(errB.details[0].message)
try {
const response = await controller.deleteFile(query._filePath, body.filePath)
res.send(response)
} catch (err: any) { } catch (err: any) {
res.status(403).send(err.toString()) res.status(403).send(err.toString())
} }
@@ -42,8 +53,8 @@ driveRouter.post(
'/file', '/file',
(...arg) => multerSingle('file', arg), (...arg) => multerSingle('file', arg),
async (req, res) => { async (req, res) => {
const { error: errQ, value: query } = uploadFileParamValidation(req.query) const { error: errQ, value: query } = fileParamValidation(req.query)
const { error: errB, value: body } = uploadFileBodyValidation(req.body) const { error: errB, value: body } = fileBodyValidation(req.body)
if (errQ && errB) { if (errQ && errB) {
if (req.file) await deleteFile(req.file.path) if (req.file) await deleteFile(req.file.path)
@@ -66,21 +77,33 @@ driveRouter.post(
} }
) )
driveRouter.patch('/file', async (req, res) => { driveRouter.patch(
const { error, value: body } = updateFileDriveValidation(req.body) '/file',
if (error) return res.status(400).send(error.details[0].message) (...arg) => multerSingle('file', arg),
async (req, res) => {
const { error: errQ, value: query } = fileParamValidation(req.query)
const { error: errB, value: body } = fileBodyValidation(req.body)
try { if (errQ && errB) {
const response = await controller.updateFile(body) if (req.file) await deleteFile(req.file.path)
res.send(response) return res.status(400).send(errB.details[0].message)
} catch (err: any) { }
const statusCode = err.code
delete err.code if (!req.file) return res.status(400).send('"file" is not present.')
res.status(statusCode).send(err) try {
const response = await controller.updateFile(
req.file,
query._filePath,
body.filePath
)
res.send(response)
} catch (err: any) {
await deleteFile(req.file.path)
res.status(403).send(err.toString())
}
} }
}) )
driveRouter.get('/fileTree', async (req, res) => { driveRouter.get('/fileTree', async (req, res) => {
try { try {

View File

@@ -321,6 +321,166 @@ describe('files', () => {
expect(res.body).toEqual({}) expect(res.body).toEqual({})
}) })
}) })
describe('update', () => {
it('should update a SAS file on drive having filePath as form field', async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.sas')
const pathToUpload = '/my/path/code.sas'
const pathToCopy = path.join(
fileUtilModules.getTmpFilesFolderPath(),
pathToUpload
)
await copy(fileToAttachPath, pathToCopy)
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', fileToAttachPath)
expect(res.statusCode).toEqual(200)
expect(res.body).toEqual({
status: 'success'
})
})
it('should update a SAS file on drive having _filePath as query param', async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.sas')
const pathToUpload = '/my/path/code.sas'
const pathToCopy = path.join(
fileUtilModules.getTmpFilesFolderPath(),
pathToUpload
)
await copy(fileToAttachPath, pathToCopy)
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', fileToAttachPath)
expect(res.statusCode).toEqual(200)
expect(res.body).toEqual({
status: 'success'
})
})
it('should respond with Unauthorized if access token is not present', async () => {
const res = await request(app)
.patch('/SASjsApi/drive/file')
.field('filePath', '/my/path/code.sas')
.attach('file', path.join(__dirname, 'files', 'sample.sas'))
.expect(401)
expect(res.text).toEqual('Unauthorized')
expect(res.body).toEqual({})
})
it('should respond with Forbidden if file is not present', async () => {
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', `/my/path/code-${generateTimestamp()}.sas`)
.attach('file', path.join(__dirname, 'files', 'sample.sas'))
.expect(403)
expect(res.text).toEqual(`Error: File doesn't exist.`)
expect(res.body).toEqual({})
})
it('should respond with Forbidden if filePath outside Drive', async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.sas')
const pathToUpload = '/../path/code.sas'
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', fileToAttachPath)
.expect(403)
expect(res.text).toEqual('Error: Cannot modify file outside drive.')
expect(res.body).toEqual({})
})
it('should respond with Bad Request if filePath is missing', async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.sas')
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.attach('file', fileToAttachPath)
.expect(400)
expect(res.text).toEqual(`"filePath" is required`)
expect(res.body).toEqual({})
})
it("should respond with Bad Request if filePath doesn't has correct extension", async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.sas')
const pathToUpload = '/my/path/code.oth'
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', fileToAttachPath)
.expect(400)
expect(res.text).toEqual('Valid extensions for filePath: .sas')
expect(res.body).toEqual({})
})
it('should respond with Bad Request if file is missing', async () => {
const pathToUpload = '/my/path/code.sas'
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.expect(400)
expect(res.text).toEqual('"file" is not present.')
expect(res.body).toEqual({})
})
it("should respond with Bad Request if attached file doesn't has correct extension", async () => {
const fileToAttachPath = path.join(__dirname, 'files', 'sample.oth')
const pathToUpload = '/my/path/code.sas'
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', fileToAttachPath)
.expect(400)
expect(res.text).toEqual(
`File extension '.oth' not acceptable. Valid extension(s): .sas`
)
expect(res.body).toEqual({})
})
it('should respond with Bad Request if attached file exceeds file limit', async () => {
const pathToUpload = '/my/path/code.sas'
const attachedFile = Buffer.from('.'.repeat(20 * 1024 * 1024))
const res = await request(app)
.patch('/SASjsApi/drive/file')
.auth(accessToken, { type: 'bearer' })
.field('filePath', pathToUpload)
.attach('file', attachedFile, 'another.sas')
.expect(400)
expect(res.text).toEqual(
'File size is over limit. File limit is: 10 MB'
)
expect(res.body).toEqual({})
})
})
}) })
}) })

View File

@@ -4,6 +4,7 @@ export * from './file'
export * from './generateAccessToken' export * from './generateAccessToken'
export * from './generateAuthCode' export * from './generateAuthCode'
export * from './generateRefreshToken' export * from './generateRefreshToken'
export * from './isDebugOn'
export * from './getCertificates' export * from './getCertificates'
export * from './getDesktopFields' export * from './getDesktopFields'
export * from './parseLogToArray' export * from './parseLogToArray'

View File

@@ -0,0 +1,8 @@
import { ExecutionVars } from '../controllers/internal'
export const isDebugOn = (vars: ExecutionVars) => {
const debugValue =
typeof vars._debug === 'string' ? parseInt(vars._debug) : vars._debug
return !!(debugValue && debugValue >= 131)
}

View File

@@ -66,25 +66,14 @@ export const registerClientValidation = (data: any): Joi.ValidationResult =>
clientSecret: Joi.string().required() clientSecret: Joi.string().required()
}).validate(data) }).validate(data)
export const getFileDriveValidation = (data: any): Joi.ValidationResult => export const fileBodyValidation = (data: any): Joi.ValidationResult =>
Joi.object({
filePath: Joi.string().required()
}).validate(data)
export const updateFileDriveValidation = (data: any): Joi.ValidationResult =>
Joi.object({
filePath: Joi.string().required(),
fileContent: Joi.string().required()
}).validate(data)
export const uploadFileBodyValidation = (data: any): Joi.ValidationResult =>
Joi.object({ Joi.object({
filePath: Joi.string().pattern(/.sas$/).required().messages({ filePath: Joi.string().pattern(/.sas$/).required().messages({
'string.pattern.base': `Valid extensions for filePath: .sas` 'string.pattern.base': `Valid extensions for filePath: .sas`
}) })
}).validate(data) }).validate(data)
export const uploadFileParamValidation = (data: any): Joi.ValidationResult => export const fileParamValidation = (data: any): Joi.ValidationResult =>
Joi.object({ Joi.object({
_filePath: Joi.string().pattern(/.sas$/).required().messages({ _filePath: Joi.string().pattern(/.sas$/).required().messages({
'string.pattern.base': `Valid extensions for filePath: .sas` 'string.pattern.base': `Valid extensions for filePath: .sas`

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "server", "name": "server",
"version": "0.0.30", "version": "0.0.32",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "server", "name": "server",
"version": "0.0.30", "version": "0.0.32",
"devDependencies": { "devDependencies": {
"prettier": "^2.3.1", "prettier": "^2.3.1",
"standard-version": "^9.3.2" "standard-version": "^9.3.2"

View File

@@ -1,6 +1,6 @@
{ {
"name": "server", "name": "server",
"version": "0.0.30", "version": "0.0.32",
"description": "NodeJS wrapper for calling the SAS binary executable", "description": "NodeJS wrapper for calling the SAS binary executable",
"repository": "https://github.com/sasjs/server", "repository": "https://github.com/sasjs/server",
"scripts": { "scripts": {

View File

@@ -23,9 +23,9 @@ const Main = (props: any) => {
if (props.selectedFilePath) { if (props.selectedFilePath) {
setIsLoading(true) setIsLoading(true)
axios axios
.get(`/SASjsApi/drive/file?filePath=${props.selectedFilePath}`) .get(`/SASjsApi/drive/file?_filePath=${props.selectedFilePath}`)
.then((res: any) => { .then((res: any) => {
setFileContent(res.data.fileContent) setFileContent(res.data)
}) })
.catch((err) => { .catch((err) => {
console.log(err) console.log(err)
@@ -36,17 +36,40 @@ const Main = (props: any) => {
} }
}, [props.selectedFilePath]) }, [props.selectedFilePath])
const handleDeleteBtnClick = () => {
setIsLoading(true)
const filePath = props.selectedFilePath
axios
.delete(`/SASjsApi/drive/file?_filePath=${filePath}`)
.then((res) => {
setFileContent('')
window.history.pushState('', '', `${baseUrl}/#/SASjsDrive`)
})
.catch((err) => {
console.log(err)
})
.finally(() => {
setIsLoading(false)
})
}
const handleEditSaveBtnClick = () => { const handleEditSaveBtnClick = () => {
if (!editMode) { if (!editMode) {
setFileContentBeforeEdit(fileContent) setFileContentBeforeEdit(fileContent)
setEditMode(true) setEditMode(true)
} else { } else {
setIsLoading(true) setIsLoading(true)
const formData = new FormData()
const stringBlob = new Blob([fileContent], { type: 'text/plain' })
formData.append('file', stringBlob, 'filename.sas')
formData.append('filePath', props.selectedFilePath)
axios axios
.patch(`/SASjsApi/drive/file`, { .patch(`/SASjsApi/drive/file`, formData)
filePath: props.selectedFilePath,
fileContent: fileContent
})
.then((res) => { .then((res) => {
setEditMode(false) setEditMode(false)
}) })
@@ -108,6 +131,13 @@ const Main = (props: any) => {
direction="row" direction="row"
sx={{ justifyContent: 'center', marginTop: '20px' }} sx={{ justifyContent: 'center', marginTop: '20px' }}
> >
<Button
variant="contained"
onClick={handleDeleteBtnClick}
disabled={isLoading || !props?.selectedFilePath}
>
Delete
</Button>
<Button <Button
variant="contained" variant="contained"
onClick={handleEditSaveBtnClick} onClick={handleEditSaveBtnClick}

View File

@@ -64,14 +64,16 @@ const SideBar = (props: any) => {
}, [setFilePathOnMount]) }, [setFilePathOnMount])
const handleSelect = (node: TreeNode) => { const handleSelect = (node: TreeNode) => {
if (!node.children.length) { if (node.children.length) return
window.history.pushState(
'', if (!node.name.includes('.')) return
'',
`${baseUrl}/#/SASjsDrive?filePath=${node.relativePath}` window.history.pushState(
) '',
setSelectedFilePath(node.relativePath) '',
} `${baseUrl}/#/SASjsDrive?filePath=${node.relativePath}`
)
setSelectedFilePath(node.relativePath)
} }
const renderTree = (nodes: TreeNode) => ( const renderTree = (nodes: TreeNode) => (