mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-04-21 21:06:01 +02:00
Standardize error responses with consistent format and human-readable messages (#667)
This commit is contained in:
Generated
+101
-106
@@ -70,7 +70,7 @@
|
||||
"gulp-order": "^1.2.0",
|
||||
"gulp-uglify": "^3.0.2",
|
||||
"knip": "^5.1.0",
|
||||
"mocha": "^10.4.0",
|
||||
"mocha": "^10.8.2",
|
||||
"nodemon": "^3.1.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3",
|
||||
@@ -8222,10 +8222,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -9584,10 +9585,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
@@ -12546,31 +12548,32 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mocha": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz",
|
||||
"integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==",
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
|
||||
"integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-colors": "4.1.1",
|
||||
"browser-stdout": "1.3.1",
|
||||
"chokidar": "3.5.3",
|
||||
"debug": "4.3.4",
|
||||
"diff": "5.0.0",
|
||||
"escape-string-regexp": "4.0.0",
|
||||
"find-up": "5.0.0",
|
||||
"glob": "8.1.0",
|
||||
"he": "1.2.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"minimatch": "5.0.1",
|
||||
"ms": "2.1.3",
|
||||
"serialize-javascript": "6.0.0",
|
||||
"strip-json-comments": "3.1.1",
|
||||
"supports-color": "8.1.1",
|
||||
"workerpool": "6.2.1",
|
||||
"yargs": "16.2.0",
|
||||
"yargs-parser": "20.2.4",
|
||||
"yargs-unparser": "2.0.0"
|
||||
"ansi-colors": "^4.1.3",
|
||||
"browser-stdout": "^1.3.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.5",
|
||||
"diff": "^5.2.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"find-up": "^5.0.0",
|
||||
"glob": "^8.1.0",
|
||||
"he": "^1.2.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"log-symbols": "^4.1.0",
|
||||
"minimatch": "^5.1.6",
|
||||
"ms": "^2.1.3",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"supports-color": "^8.1.1",
|
||||
"workerpool": "^6.5.1",
|
||||
"yargs": "^16.2.0",
|
||||
"yargs-parser": "^20.2.9",
|
||||
"yargs-unparser": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"_mocha": "bin/_mocha",
|
||||
@@ -12601,12 +12604,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -12617,12 +12621,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/debug/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mocha/node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@@ -12655,10 +12653,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/minimatch": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||
"version": "5.1.9",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
@@ -14004,6 +14003,7 @@
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@@ -14451,10 +14451,11 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
@@ -15710,10 +15711,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/workerpool": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
|
||||
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
|
||||
"dev": true
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
|
||||
"integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
@@ -15774,10 +15776,11 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "20.2.4",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -22210,9 +22213,9 @@
|
||||
}
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-escapes": {
|
||||
@@ -23226,9 +23229,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
|
||||
"dev": true
|
||||
},
|
||||
"dom-serializer": {
|
||||
@@ -25398,31 +25401,31 @@
|
||||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz",
|
||||
"integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==",
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
|
||||
"integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "4.1.1",
|
||||
"browser-stdout": "1.3.1",
|
||||
"chokidar": "3.5.3",
|
||||
"debug": "4.3.4",
|
||||
"diff": "5.0.0",
|
||||
"escape-string-regexp": "4.0.0",
|
||||
"find-up": "5.0.0",
|
||||
"glob": "8.1.0",
|
||||
"he": "1.2.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"minimatch": "5.0.1",
|
||||
"ms": "2.1.3",
|
||||
"serialize-javascript": "6.0.0",
|
||||
"strip-json-comments": "3.1.1",
|
||||
"supports-color": "8.1.1",
|
||||
"workerpool": "6.2.1",
|
||||
"yargs": "16.2.0",
|
||||
"yargs-parser": "20.2.4",
|
||||
"yargs-unparser": "2.0.0"
|
||||
"ansi-colors": "^4.1.3",
|
||||
"browser-stdout": "^1.3.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.5",
|
||||
"diff": "^5.2.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"find-up": "^5.0.0",
|
||||
"glob": "^8.1.0",
|
||||
"he": "^1.2.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"log-symbols": "^4.1.0",
|
||||
"minimatch": "^5.1.6",
|
||||
"ms": "^2.1.3",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"supports-color": "^8.1.1",
|
||||
"workerpool": "^6.5.1",
|
||||
"yargs": "^16.2.0",
|
||||
"yargs-parser": "^20.2.9",
|
||||
"yargs-unparser": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
@@ -25446,20 +25449,12 @@
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
}
|
||||
"ms": "^2.1.3"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
@@ -25482,9 +25477,9 @@
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||
"version": "5.1.9",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
@@ -26767,9 +26762,9 @@
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
@@ -27716,9 +27711,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"workerpool": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
|
||||
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
|
||||
"integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
|
||||
"dev": true
|
||||
},
|
||||
"wrap-ansi": {
|
||||
@@ -27764,9 +27759,9 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "20.2.4",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs-unparser": {
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@
|
||||
"gulp-order": "^1.2.0",
|
||||
"gulp-uglify": "^3.0.2",
|
||||
"knip": "^5.1.0",
|
||||
"mocha": "^10.4.0",
|
||||
"mocha": "^10.8.2",
|
||||
"nodemon": "^3.1.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3",
|
||||
|
||||
@@ -3,37 +3,82 @@
|
||||
"unknown_error": "Unknown error, contact the admin.",
|
||||
"unreachable": "Anonymous GitHub is unreachable, contact the admin.",
|
||||
"request_error": "Unable to download the file, check your connection or contact the admin.",
|
||||
"not_found": "The requested resource could not be found.",
|
||||
"not_connected": "You must be logged in to perform this action.",
|
||||
"not_authorized": "You do not have permission to perform this action.",
|
||||
"unable_to_connect_user": "Unable to connect your account. Please try again later.",
|
||||
"user_not_found": "The requested user could not be found.",
|
||||
"repo_access_limited": "Access to repository limited by org.",
|
||||
"repo_not_found": "The repository is not found.",
|
||||
"repo_not_accessible": "Anonymous GitHub is unable to or is forbidden to access the repository.",
|
||||
"repository_expired": "The repository is expired",
|
||||
"repository_expired": "The repository is expired.",
|
||||
"repository_not_ready": "Anonymous GitHub is still processing the repository, it can take several minutes.",
|
||||
"repository_not_accessible": "This repository is currently not accessible.",
|
||||
"repo_is_updating": "Anonymous GitHub is still processing the repository, it can take several minutes.",
|
||||
"repoUrl_not_defined": "The repository url needs to be defined.",
|
||||
"repoId_already_used": "The repository id is already used.",
|
||||
"invalid_repoId": "The format of the repository id is invalid.",
|
||||
"invalid_repo": "The provided repository is not valid.",
|
||||
"repoId_not_defined": "A repository ID must be provided.",
|
||||
"repoUrl_not_defined": "The repository URL needs to be defined.",
|
||||
"repoId_already_used": "The repository ID is already used.",
|
||||
"invalid_repoId": "The format of the repository ID is invalid.",
|
||||
"unsupported_source": "The repository source type is not supported.",
|
||||
"branch_not_specified": "The branch is not specified.",
|
||||
"branch_not_found": "The branch of the repository cannot be found.",
|
||||
"commit_not_specified": "A commit must be specified.",
|
||||
"invalid_commit_format": "The commit hash format is invalid. It must be a hexadecimal string.",
|
||||
"pull_request_not_found": "The requested pull request could not be found.",
|
||||
"pull_request_expired": "This pull request has expired and is no longer available.",
|
||||
"pull_request_not_ready": "This pull request is still being prepared. Please try again shortly.",
|
||||
"pull_request_not_available": "This pull request is currently not available.",
|
||||
"invalid_pullRequestId": "The pull request ID is invalid.",
|
||||
"pullRequestId_already_used": "This pull request ID is already in use. Please choose a different one.",
|
||||
"repository_not_specified": "A repository must be specified for this pull request.",
|
||||
"pullRequestId_not_specified": "A pull request ID must be specified.",
|
||||
"pullRequestId_is_not_a_number": "The source pull request ID must be a number.",
|
||||
"options_not_provided": "Anonymization options are mandatory.",
|
||||
"terms_not_specified": "Anonymization terms must be specified.",
|
||||
"invalid_terms_format": "Terms are in an invalid format.",
|
||||
"unable_to_anonymize": "An error happened during the anonymization process. Please try later or report the issue.",
|
||||
"non_supported_mode": "The selected anonymization mode is invalid, only download and stream are supported.",
|
||||
"invalid_path": "The provided path is invalid or missing.",
|
||||
"path_not_specified": "A file path must be specified.",
|
||||
"path_not_defined": "The file path has not been resolved yet.",
|
||||
"no_file_selected": "Please select a file.",
|
||||
"file_not_found": "The requested file is not found.",
|
||||
"file_not_accessible": "The requested file is not accessible.",
|
||||
"file_not_supported": "The file type is not supported. Anonymous GitHub cannot handle it.",
|
||||
"file_too_big": "The file size exceed the limit of Anonymous GitHub.",
|
||||
"file_too_big": "The file size exceeds the limit of Anonymous GitHub.",
|
||||
"is_folder": "The path points to a folder.",
|
||||
"folder_not_supported": "The path points to a folder. Please select a file.",
|
||||
"unable_to_write_file": "Unable to write file on disk.",
|
||||
"download_not_enabled": "Repository downloads are not enabled on this server.",
|
||||
"unable_to_download": "The repository could not be downloaded. Please try again later.",
|
||||
"s3_config_not_provided": "Object storage has not been configured on this server.",
|
||||
"stats_unsupported": "Statistics are only supported in download mode.",
|
||||
"branches_not_found": "The requested branch is not found.",
|
||||
"readme_not_available": "No readme for the repository is found.",
|
||||
"user_not_found": "The current user is not found in the database",
|
||||
"not_connected": "User is not connected",
|
||||
"readme_not_available": "No README for the repository is found.",
|
||||
"page_not_supported_on_different_branch": "Anonymized GitHub pages are only supported on the same branch.",
|
||||
"page_not_activated": "Anonymized GitHub page is not enabled.",
|
||||
"conf_not_activated": "The conference is not activated."
|
||||
"is_removed": "This resource has been removed and is no longer available.",
|
||||
"conf_name_missing": "A conference name is required.",
|
||||
"conf_id_missing": "A conference ID is required.",
|
||||
"conf_id_used": "This conference ID is already in use. Please choose a different one.",
|
||||
"conf_start_date_missing": "A start date is required for the conference.",
|
||||
"conf_end_date_missing": "An end date is required for the conference.",
|
||||
"conf_start_date_invalid": "The start date must be before the end date.",
|
||||
"conf_end_date_invalid": "The end date must be in the future.",
|
||||
"invalid_plan": "The selected plan is not valid.",
|
||||
"conference_not_found": "The requested conference could not be found.",
|
||||
"conf_not_found": "The requested conference could not be found.",
|
||||
"conf_not_activated": "The conference is not activated.",
|
||||
"billing_missing": "Billing information is required for this plan.",
|
||||
"billing_name_missing": "A billing name is required.",
|
||||
"billing_email_missing": "A billing email is required.",
|
||||
"billing_address_missing": "A billing address is required.",
|
||||
"billing_city_missing": "A billing city is required.",
|
||||
"billing_zip_missing": "A billing ZIP/postal code is required.",
|
||||
"billing_country_missing": "A billing country is required.",
|
||||
"queue_not_found": "The specified queue could not be found.",
|
||||
"job_not_found": "The specified job could not be found in the queue.",
|
||||
"error_retrying_job": "An error occurred while retrying the job."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ export default class PullRequest {
|
||||
this.status == "removing" ||
|
||||
this.status == "removed"
|
||||
) {
|
||||
throw new AnonymousError("pullRequest_expired", {
|
||||
throw new AnonymousError("pull_request_expired", {
|
||||
object: this,
|
||||
httpStatus: 410,
|
||||
});
|
||||
@@ -126,8 +126,9 @@ export default class PullRequest {
|
||||
this.status == "preparing" ||
|
||||
(this.status == "download" && this._model.statusDate > fiveMinuteAgo)
|
||||
) {
|
||||
throw new AnonymousError("pullRequest_not_ready", {
|
||||
throw new AnonymousError("pull_request_not_ready", {
|
||||
object: this,
|
||||
httpStatus: 503,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export default class Repository {
|
||||
) {
|
||||
throw new AnonymousError("repository_not_ready", {
|
||||
object: this,
|
||||
httpStatus: 503,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -356,6 +357,7 @@ export default class Repository {
|
||||
await this.resetSate();
|
||||
throw new AnonymousError("branch_not_found", {
|
||||
object: this,
|
||||
httpStatus: 404,
|
||||
});
|
||||
}
|
||||
this._model.anonymizeDate = new Date();
|
||||
|
||||
@@ -127,7 +127,7 @@ export default class S3Storage extends StorageBase {
|
||||
}
|
||||
} catch {
|
||||
try {
|
||||
res.status(500);
|
||||
res.status(500).json({ error: "file_not_found" });
|
||||
} catch (err) {
|
||||
console.error(`[ERROR] S3 send ${path}`, err);
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ function indexResponse(req: express.Request, res: express.Response) {
|
||||
req.path.startsWith("/favicon") ||
|
||||
req.path.startsWith("/api")
|
||||
) {
|
||||
return res.status(404).send("Not found");
|
||||
return res.status(404).json({ error: "not_found" });
|
||||
}
|
||||
if (
|
||||
req.params.repoId &&
|
||||
|
||||
@@ -59,7 +59,7 @@ router.post("/queue/:name/:repo_id", async (req, res) => {
|
||||
}
|
||||
res.send("ok");
|
||||
} catch {
|
||||
res.status(500).send("error_retrying_job");
|
||||
res.status(500).json({ error: "error_retrying_job" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -102,9 +102,9 @@ export function handleError(
|
||||
req?: express.Request
|
||||
) {
|
||||
printError(error, req);
|
||||
let message = error;
|
||||
let errorCode = error;
|
||||
if (error instanceof Error) {
|
||||
message = error.message;
|
||||
errorCode = error.message;
|
||||
}
|
||||
let status = 500;
|
||||
if (error.httpStatus) {
|
||||
@@ -112,15 +112,16 @@ export function handleError(
|
||||
} else if (error.$metadata?.httpStatusCode) {
|
||||
status = error.$metadata.httpStatusCode;
|
||||
} else if (
|
||||
message &&
|
||||
(message.indexOf("not_found") > -1 || message.indexOf("(Not Found)") > -1)
|
||||
errorCode &&
|
||||
(errorCode.indexOf("not_found") > -1 ||
|
||||
errorCode.indexOf("(Not Found)") > -1)
|
||||
) {
|
||||
status = 404;
|
||||
} else if (message && message.indexOf("not_connected") > -1) {
|
||||
} else if (errorCode && errorCode.indexOf("not_connected") > -1) {
|
||||
status = 401;
|
||||
}
|
||||
if (res && !res.headersSent) {
|
||||
res.status(status).send({ error: message });
|
||||
res.status(status).json({ error: errorCode });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
const { expect } = require("chai");
|
||||
const { readFileSync, readdirSync, statSync } = require("fs");
|
||||
const { join } = require("path");
|
||||
|
||||
const LOCALE_PATH = join(__dirname, "..", "public", "i18n", "locale-en.json");
|
||||
const SRC_DIR = join(__dirname, "..", "src");
|
||||
|
||||
/**
|
||||
* Collect all .ts files under a directory recursively.
|
||||
*/
|
||||
function collectTsFiles(dir) {
|
||||
const files = [];
|
||||
for (const entry of readdirSync(dir)) {
|
||||
const full = join(dir, entry);
|
||||
if (statSync(full).isDirectory()) {
|
||||
files.push(...collectTsFiles(full));
|
||||
} else if (full.endsWith(".ts")) {
|
||||
files.push(full);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error codes from backend source files.
|
||||
*
|
||||
* Matches patterns such as:
|
||||
* 1. new AnonymousError("error_code", ...) -- thrown errors
|
||||
* 2. res.status(NNN).json({ error: "code" }) -- direct responses
|
||||
*
|
||||
* Only string literals that look like error codes (contain at least one
|
||||
* underscore, indicating a snake_case identifier) are extracted.
|
||||
*/
|
||||
function extractBackendErrorCodes(files) {
|
||||
const codes = new Map(); // code -> [{ file, line }]
|
||||
|
||||
const patterns = [
|
||||
// new AnonymousError("code") -- including across ternary expressions
|
||||
// e.g. new AnonymousError("repo_not_found",
|
||||
// new AnonymousError(condition ? msg : "fallback_code",
|
||||
/AnonymousError\([^)]*["']([a-zA-Z][a-zA-Z0-9]*(?:_[a-zA-Z0-9]+)+)["']/,
|
||||
// { error: "code" } -- direct JSON responses
|
||||
/\{\s*error:\s*["']([a-zA-Z][a-zA-Z0-9]*(?:_[a-zA-Z0-9]+)+)["']/,
|
||||
];
|
||||
|
||||
for (const file of files) {
|
||||
const content = readFileSync(file, "utf-8");
|
||||
const lines = content.split("\n");
|
||||
const relPath = file.replace(join(__dirname, "..") + "/", "");
|
||||
|
||||
// Per-line matching for simple cases
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (/^\s*(import |\/\/|\/\*|\* )/.test(line)) continue;
|
||||
|
||||
for (const pattern of patterns) {
|
||||
const match = line.match(pattern);
|
||||
if (match) {
|
||||
const code = match[1];
|
||||
if (!codes.has(code)) {
|
||||
codes.set(code, []);
|
||||
}
|
||||
codes.get(code).push({ file: relPath, line: i + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-line matching for AnonymousError calls that span lines
|
||||
// (e.g. ternary expressions where the string is on the next line)
|
||||
const multiLinePattern =
|
||||
/AnonymousError\([\s\S]*?["']([a-zA-Z][a-zA-Z0-9]*(?:_[a-zA-Z0-9]+)+)["']/g;
|
||||
let m;
|
||||
while ((m = multiLinePattern.exec(content)) !== null) {
|
||||
const code = m[1];
|
||||
const lineNum =
|
||||
content.substring(0, m.index + m[0].length).split("\n").length;
|
||||
if (!codes.has(code)) {
|
||||
codes.set(code, []);
|
||||
}
|
||||
// Avoid duplicate entries from the per-line pass
|
||||
const existing = codes.get(code);
|
||||
if (!existing.some((e) => e.file === relPath && e.line === lineNum)) {
|
||||
existing.push({ file: relPath, line: lineNum });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
describe("Error code coverage", function () {
|
||||
let localeErrors;
|
||||
let backendCodes;
|
||||
|
||||
before(function () {
|
||||
const locale = JSON.parse(readFileSync(LOCALE_PATH, "utf-8"));
|
||||
localeErrors = locale.ERRORS || {};
|
||||
backendCodes = extractBackendErrorCodes(collectTsFiles(SRC_DIR));
|
||||
});
|
||||
|
||||
it("locale file is valid JSON with an ERRORS object", function () {
|
||||
expect(localeErrors).to.be.an("object").that.is.not.empty;
|
||||
});
|
||||
|
||||
it("every backend error code has a frontend translation", function () {
|
||||
const missing = [];
|
||||
for (const [code, locations] of backendCodes) {
|
||||
if (!localeErrors[code]) {
|
||||
const where = locations
|
||||
.map((l) => ` ${l.file}:${l.line}`)
|
||||
.join("\n");
|
||||
missing.push(` "${code}" used in:\n${where}`);
|
||||
}
|
||||
}
|
||||
expect(missing, `Missing translations:\n${missing.join("\n")}`).to.have
|
||||
.length(0);
|
||||
});
|
||||
|
||||
it("every frontend translation corresponds to a backend error code", function () {
|
||||
const unused = [];
|
||||
for (const code of Object.keys(localeErrors)) {
|
||||
if (!backendCodes.has(code)) {
|
||||
unused.push(` "${code}"`);
|
||||
}
|
||||
}
|
||||
// This is a warning, not a hard failure -- some codes may only be used
|
||||
// on the frontend itself (e.g. "unreachable", "request_error").
|
||||
// We report them so developers can clean up stale entries.
|
||||
if (unused.length > 0) {
|
||||
console.log(
|
||||
` ⚠ ${unused.length} locale key(s) not found in backend source (frontend-only or stale):\n${unused.join("\n")}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("locale error messages are non-empty strings", function () {
|
||||
const empty = [];
|
||||
for (const [code, message] of Object.entries(localeErrors)) {
|
||||
if (typeof message !== "string" || message.trim() === "") {
|
||||
empty.push(code);
|
||||
}
|
||||
}
|
||||
expect(empty, `Empty/invalid messages for: ${empty.join(", ")}`).to.have
|
||||
.length(0);
|
||||
});
|
||||
|
||||
it("backend error codes use consistent snake_case format", function () {
|
||||
const invalid = [];
|
||||
// Allow snake_case with optional camelCase segments (e.g. pullRequestId_not_specified)
|
||||
const validPattern = /^[a-zA-Z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$/;
|
||||
for (const code of backendCodes.keys()) {
|
||||
if (!validPattern.test(code)) {
|
||||
invalid.push(code);
|
||||
}
|
||||
}
|
||||
expect(
|
||||
invalid,
|
||||
`Invalid error code format: ${invalid.join(", ")}`
|
||||
).to.have.length(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user