@quantiya/codevibe-claude-plugin 1.0.37 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/bin/codevibe-claude +17 -3
  3. package/dist/server.js +8 -8
  4. package/hooks/stop.sh +30 -10
  5. package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +1 -139
  6. package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +0 -5
  7. package/node_modules/@quantiya/codevibe-core/dist/auth/auth-telemetry.d.ts +64 -29
  8. package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +0 -4
  9. package/node_modules/@quantiya/codevibe-core/dist/index.js +33 -194
  10. package/node_modules/@quantiya/codevibe-core/dist/keychain/keychain-manager.d.ts +16 -2
  11. package/node_modules/@quantiya/codevibe-core/dist/session/session-rekey.d.ts +40 -0
  12. package/node_modules/@quantiya/codevibe-core/dist/session/session-resume.d.ts +1 -0
  13. package/node_modules/@quantiya/codevibe-core/dist/types/index.d.ts +0 -2
  14. package/node_modules/@quantiya/codevibe-core/dist/types/session.d.ts +0 -16
  15. package/node_modules/@quantiya/codevibe-core/package.json +1 -1
  16. package/node_modules/body-parser/README.md +18 -18
  17. package/node_modules/body-parser/index.js +6 -15
  18. package/node_modules/body-parser/lib/read.js +17 -20
  19. package/node_modules/body-parser/lib/types/json.js +8 -16
  20. package/node_modules/body-parser/lib/types/raw.js +3 -4
  21. package/node_modules/body-parser/lib/types/text.js +3 -4
  22. package/node_modules/body-parser/lib/types/urlencoded.js +8 -8
  23. package/node_modules/body-parser/lib/utils.js +11 -9
  24. package/node_modules/body-parser/package.json +2 -2
  25. package/node_modules/content-disposition/README.md +7 -8
  26. package/node_modules/content-disposition/index.js +118 -40
  27. package/node_modules/content-disposition/package.json +8 -11
  28. package/node_modules/express/Readme.md +39 -29
  29. package/node_modules/express/lib/application.js +1 -1
  30. package/node_modules/express/lib/request.js +5 -6
  31. package/node_modules/express/lib/response.js +14 -0
  32. package/node_modules/express/lib/utils.js +3 -1
  33. package/node_modules/express/package.json +6 -5
  34. package/node_modules/finalhandler/HISTORY.md +6 -0
  35. package/node_modules/finalhandler/README.md +26 -23
  36. package/node_modules/finalhandler/package.json +13 -9
  37. package/node_modules/graphql/execution/execute.d.ts +14 -1
  38. package/node_modules/graphql/execution/execute.js +63 -13
  39. package/node_modules/graphql/execution/execute.mjs +63 -13
  40. package/node_modules/graphql/execution/subscribe.js +1 -0
  41. package/node_modules/graphql/execution/subscribe.mjs +2 -0
  42. package/node_modules/graphql/execution/values.js +4 -4
  43. package/node_modules/graphql/execution/values.mjs +4 -4
  44. package/node_modules/graphql/index.d.ts +1 -0
  45. package/node_modules/graphql/language/ast.d.ts +10 -1
  46. package/node_modules/graphql/language/ast.js +8 -1
  47. package/node_modules/graphql/language/ast.mjs +8 -1
  48. package/node_modules/graphql/language/directiveLocation.d.ts +1 -0
  49. package/node_modules/graphql/language/directiveLocation.js +1 -0
  50. package/node_modules/graphql/language/directiveLocation.mjs +1 -0
  51. package/node_modules/graphql/language/index.d.ts +1 -0
  52. package/node_modules/graphql/language/kinds.d.ts +1 -0
  53. package/node_modules/graphql/language/kinds.js +1 -0
  54. package/node_modules/graphql/language/kinds.mjs +1 -0
  55. package/node_modules/graphql/language/parser.d.ts +14 -0
  56. package/node_modules/graphql/language/parser.js +33 -0
  57. package/node_modules/graphql/language/parser.mjs +33 -0
  58. package/node_modules/graphql/language/predicates.js +3 -1
  59. package/node_modules/graphql/language/predicates.mjs +5 -1
  60. package/node_modules/graphql/language/printer.js +13 -1
  61. package/node_modules/graphql/language/printer.mjs +13 -1
  62. package/node_modules/graphql/package.json +1 -1
  63. package/node_modules/graphql/type/directives.d.ts +9 -1
  64. package/node_modules/graphql/type/directives.js +10 -1
  65. package/node_modules/graphql/type/directives.mjs +10 -1
  66. package/node_modules/graphql/type/introspection.js +24 -1
  67. package/node_modules/graphql/type/introspection.mjs +24 -1
  68. package/node_modules/graphql/utilities/buildASTSchema.js +4 -0
  69. package/node_modules/graphql/utilities/buildASTSchema.mjs +4 -0
  70. package/node_modules/graphql/utilities/buildClientSchema.js +1 -0
  71. package/node_modules/graphql/utilities/buildClientSchema.mjs +1 -0
  72. package/node_modules/graphql/utilities/coerceInputValue.js +2 -2
  73. package/node_modules/graphql/utilities/coerceInputValue.mjs +2 -2
  74. package/node_modules/graphql/utilities/extendSchema.js +58 -3
  75. package/node_modules/graphql/utilities/extendSchema.mjs +58 -3
  76. package/node_modules/graphql/utilities/getIntrospectionQuery.d.ts +16 -0
  77. package/node_modules/graphql/utilities/getIntrospectionQuery.js +31 -38
  78. package/node_modules/graphql/utilities/getIntrospectionQuery.mjs +31 -38
  79. package/node_modules/graphql/utilities/introspectionFromSchema.js +1 -0
  80. package/node_modules/graphql/utilities/introspectionFromSchema.mjs +1 -0
  81. package/node_modules/graphql/utilities/printSchema.js +1 -0
  82. package/node_modules/graphql/utilities/printSchema.mjs +1 -0
  83. package/node_modules/graphql/utilities/valueFromAST.js +12 -2
  84. package/node_modules/graphql/utilities/valueFromAST.mjs +12 -2
  85. package/node_modules/graphql/validation/rules/KnownDirectivesRule.js +4 -0
  86. package/node_modules/graphql/validation/rules/KnownDirectivesRule.mjs +4 -0
  87. package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.js +12 -0
  88. package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.mjs +12 -0
  89. package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.js +5 -11
  90. package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.mjs +5 -11
  91. package/node_modules/graphql/validation/validate.js +12 -0
  92. package/node_modules/graphql/validation/validate.mjs +13 -2
  93. package/node_modules/graphql/version.js +2 -2
  94. package/node_modules/graphql/version.mjs +2 -2
  95. package/node_modules/hasown/CHANGELOG.md +11 -0
  96. package/node_modules/hasown/eslint.config.mjs +6 -0
  97. package/node_modules/hasown/index.d.ts +1 -0
  98. package/node_modules/hasown/package.json +14 -14
  99. package/node_modules/iconv-lite/lib/index.d.ts +114 -26
  100. package/node_modules/iconv-lite/lib/index.js +39 -40
  101. package/node_modules/iconv-lite/package.json +13 -2
  102. package/node_modules/iconv-lite/types/encodings.d.ts +423 -0
  103. package/node_modules/node-abi/abi_registry.json +10 -3
  104. package/node_modules/{semver → node-abi/node_modules/semver}/README.md +19 -4
  105. package/node_modules/{semver → node-abi/node_modules/semver}/bin/semver.js +14 -10
  106. package/node_modules/node-abi/node_modules/semver/functions/truncate.js +48 -0
  107. package/node_modules/{semver → node-abi/node_modules/semver}/index.js +2 -0
  108. package/node_modules/{semver → node-abi/node_modules/semver}/internal/re.js +1 -1
  109. package/node_modules/{semver → node-abi/node_modules/semver}/package.json +3 -3
  110. package/node_modules/{semver → node-abi/node_modules/semver}/range.bnf +5 -4
  111. package/node_modules/node-abi/package.json +1 -1
  112. package/node_modules/path-to-regexp/Readme.md +3 -3
  113. package/node_modules/path-to-regexp/dist/index.d.ts +3 -0
  114. package/node_modules/path-to-regexp/dist/index.js +215 -193
  115. package/node_modules/path-to-regexp/dist/index.js.map +1 -1
  116. package/node_modules/path-to-regexp/package.json +2 -2
  117. package/node_modules/qs/.editorconfig +1 -1
  118. package/node_modules/qs/.github/SECURITY.md +11 -0
  119. package/node_modules/qs/.github/THREAT_MODEL.md +78 -0
  120. package/node_modules/qs/CHANGELOG.md +190 -0
  121. package/node_modules/qs/README.md +29 -4
  122. package/node_modules/qs/dist/qs.js +21 -21
  123. package/node_modules/qs/eslint.config.mjs +56 -0
  124. package/node_modules/qs/lib/parse.js +94 -49
  125. package/node_modules/qs/lib/utils.js +85 -11
  126. package/node_modules/qs/package.json +10 -9
  127. package/node_modules/qs/test/parse.js +391 -13
  128. package/node_modules/qs/test/stringify.js +16 -3
  129. package/node_modules/qs/test/utils.js +173 -3
  130. package/node_modules/send/package.json +11 -8
  131. package/node_modules/serve-static/README.md +23 -23
  132. package/node_modules/serve-static/package.json +6 -3
  133. package/node_modules/side-channel-list/CHANGELOG.md +25 -4
  134. package/node_modules/side-channel-list/index.js +1 -3
  135. package/node_modules/side-channel-list/package.json +8 -8
  136. package/node_modules/side-channel-list/test/index.js +50 -0
  137. package/node_modules/uuid/dist/v35.js +3 -0
  138. package/node_modules/uuid/dist/v6.js +3 -0
  139. package/node_modules/uuid/dist-node/v35.js +3 -0
  140. package/node_modules/uuid/dist-node/v6.js +3 -0
  141. package/node_modules/uuid/package.json +1 -1
  142. package/node_modules/ws/index.js +15 -6
  143. package/node_modules/ws/lib/constants.js +1 -0
  144. package/node_modules/ws/lib/permessage-deflate.js +6 -6
  145. package/node_modules/ws/lib/websocket-server.js +10 -6
  146. package/node_modules/ws/lib/websocket.js +19 -14
  147. package/node_modules/ws/package.json +4 -3
  148. package/node_modules/ws/wrapper.mjs +14 -1
  149. package/package.json +2 -2
  150. package/node_modules/@quantiya/codevibe-core/dist/appsync/__tests__/appsync-client.test.d.ts +0 -1
  151. package/node_modules/@quantiya/codevibe-core/dist/audit-keys/__tests__/audit-keys-parity.test.d.ts +0 -1
  152. package/node_modules/@quantiya/codevibe-core/dist/audit-keys/index.d.ts +0 -41
  153. package/node_modules/@quantiya/codevibe-core/dist/auth/__tests__/auth-telemetry.test.d.ts +0 -1
  154. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-bootstrap.test.d.ts +0 -1
  155. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-failure-recourse.test.d.ts +0 -1
  156. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-save.test.d.ts +0 -1
  157. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-seat-picker.test.d.ts +0 -1
  158. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-telemetry.test.d.ts +0 -1
  159. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-test-agents.test.d.ts +0 -1
  160. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-types.test.d.ts +0 -1
  161. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-wizard.test.d.ts +0 -1
  162. package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/v1-options.test.d.ts +0 -1
  163. package/node_modules/@quantiya/codevibe-core/dist/orchestration/detect-agents.d.ts +0 -56
  164. package/node_modules/@quantiya/codevibe-core/dist/orchestration/index.d.ts +0 -3
  165. package/node_modules/@quantiya/codevibe-core/dist/orchestration/orchestration-cli.d.ts +0 -12
  166. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-bootstrap.d.ts +0 -146
  167. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-failure-recourse.d.ts +0 -23
  168. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-save.d.ts +0 -47
  169. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-seat-picker.d.ts +0 -72
  170. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-telemetry.d.ts +0 -54
  171. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-test-agents.d.ts +0 -108
  172. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-types.d.ts +0 -140
  173. package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-wizard.d.ts +0 -57
  174. package/node_modules/@quantiya/codevibe-core/dist/orchestration/v1-options.d.ts +0 -108
  175. package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/integration.test.d.ts +0 -1
  176. package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/mocks.test.d.ts +0 -1
  177. package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/output-parser.test.d.ts +0 -1
  178. package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/registry.test.d.ts +0 -1
  179. package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/subprocess.test.d.ts +0 -1
  180. package/node_modules/@quantiya/codevibe-core/dist/reviewer/index.d.ts +0 -15
  181. package/node_modules/@quantiya/codevibe-core/dist/reviewer/mocks.d.ts +0 -80
  182. package/node_modules/@quantiya/codevibe-core/dist/reviewer/output-parser.d.ts +0 -95
  183. package/node_modules/@quantiya/codevibe-core/dist/reviewer/provider.d.ts +0 -153
  184. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude-live-smoke.test.d.ts +0 -1
  185. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude.test.d.ts +0 -1
  186. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex-live-smoke.test.d.ts +0 -1
  187. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex.test.d.ts +0 -1
  188. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini-live-smoke.test.d.ts +0 -1
  189. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini.test.d.ts +0 -1
  190. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/claude.d.ts +0 -59
  191. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/codex.d.ts +0 -67
  192. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/common.d.ts +0 -25
  193. package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/gemini.d.ts +0 -108
  194. package/node_modules/@quantiya/codevibe-core/dist/reviewer/registry.d.ts +0 -87
  195. package/node_modules/@quantiya/codevibe-core/dist/reviewer/subprocess.d.ts +0 -117
  196. package/node_modules/@quantiya/codevibe-core/dist/reviewer/types.d.ts +0 -101
  197. package/node_modules/@quantiya/codevibe-core/dist/types/orchestration.d.ts +0 -57
  198. package/node_modules/@quantiya/codevibe-core/dist/types/reviewer.d.ts +0 -67
  199. package/node_modules/content-disposition/HISTORY.md +0 -72
  200. package/node_modules/express/History.md +0 -3858
  201. package/node_modules/hasown/.eslintrc +0 -5
  202. package/node_modules/iconv-lite/Changelog.md +0 -236
  203. package/node_modules/qs/.eslintrc +0 -39
  204. package/node_modules/send/HISTORY.md +0 -580
  205. package/node_modules/serve-static/HISTORY.md +0 -516
  206. /package/node_modules/{semver → node-abi/node_modules/semver}/LICENSE +0 -0
  207. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/comparator.js +0 -0
  208. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/index.js +0 -0
  209. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/range.js +0 -0
  210. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/semver.js +0 -0
  211. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/clean.js +0 -0
  212. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/cmp.js +0 -0
  213. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/coerce.js +0 -0
  214. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-build.js +0 -0
  215. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-loose.js +0 -0
  216. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare.js +0 -0
  217. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/diff.js +0 -0
  218. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/eq.js +0 -0
  219. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gt.js +0 -0
  220. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gte.js +0 -0
  221. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/inc.js +0 -0
  222. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lt.js +0 -0
  223. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lte.js +0 -0
  224. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/major.js +0 -0
  225. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/minor.js +0 -0
  226. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/neq.js +0 -0
  227. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/parse.js +0 -0
  228. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/patch.js +0 -0
  229. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/prerelease.js +0 -0
  230. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rcompare.js +0 -0
  231. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rsort.js +0 -0
  232. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/satisfies.js +0 -0
  233. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/sort.js +0 -0
  234. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/valid.js +0 -0
  235. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/constants.js +0 -0
  236. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/debug.js +0 -0
  237. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/identifiers.js +0 -0
  238. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/lrucache.js +0 -0
  239. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/parse-options.js +0 -0
  240. /package/node_modules/{semver → node-abi/node_modules/semver}/preload.js +0 -0
  241. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/gtr.js +0 -0
  242. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/intersects.js +0 -0
  243. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/ltr.js +0 -0
  244. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/max-satisfying.js +0 -0
  245. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-satisfying.js +0 -0
  246. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-version.js +0 -0
  247. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/outside.js +0 -0
  248. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/simplify.js +0 -0
  249. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/subset.js +0 -0
  250. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/to-comparators.js +0 -0
  251. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/valid.js +0 -0
  252. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/index.js +0 -0
  253. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/license +0 -0
  254. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/package.json +0 -0
  255. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/readme.md +0 -0
@@ -15,11 +15,11 @@ module.exports = contentDisposition
15
15
  module.exports.parse = parse
16
16
 
17
17
  /**
18
- * Module dependencies.
18
+ * TextDecoder instance for UTF-8 decoding when decodeURIComponent fails due to invalid byte sequences.
19
+ * @type {TextDecoder}
19
20
  * @private
20
21
  */
21
-
22
- var basename = require('path').basename
22
+ const utf8Decoder = new TextDecoder('utf-8')
23
23
 
24
24
  /**
25
25
  * RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%")
@@ -28,14 +28,6 @@ var basename = require('path').basename
28
28
 
29
29
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g // eslint-disable-line no-control-regex
30
30
 
31
- /**
32
- * RegExp to match percent encoding escape.
33
- * @private
34
- */
35
-
36
- var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/
37
- var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g
38
-
39
31
  /**
40
32
  * RegExp to match non-latin1 characters.
41
33
  * @private
@@ -199,7 +191,7 @@ function createparams (filename, fallback) {
199
191
  var hasFallback = typeof fallbackName === 'string' && fallbackName !== name
200
192
 
201
193
  // set extended filename parameter
202
- if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
194
+ if (hasFallback || !isQuotedString || hasHexEscape(name)) {
203
195
  params['filename*'] = name
204
196
  }
205
197
 
@@ -262,32 +254,41 @@ function format (obj) {
262
254
  */
263
255
 
264
256
  function decodefield (str) {
265
- var match = EXT_VALUE_REGEXP.exec(str)
257
+ const match = EXT_VALUE_REGEXP.exec(str)
266
258
 
267
259
  if (!match) {
268
260
  throw new TypeError('invalid extended field value')
269
261
  }
270
262
 
271
- var charset = match[1].toLowerCase()
272
- var encoded = match[2]
273
- var value
274
-
275
- // to binary string
276
- var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode)
263
+ const charset = match[1].toLowerCase()
264
+ const encoded = match[2]
277
265
 
278
266
  switch (charset) {
279
267
  case 'iso-8859-1':
280
- value = getlatin1(binary)
281
- break
268
+ {
269
+ const binary = decodeHexEscapes(encoded)
270
+ return getlatin1(binary)
271
+ }
282
272
  case 'utf-8':
283
273
  case 'utf8':
284
- value = Buffer.from(binary, 'binary').toString('utf8')
285
- break
286
- default:
287
- throw new TypeError('unsupported charset in extended field')
274
+ {
275
+ try {
276
+ return decodeURIComponent(encoded)
277
+ } catch {
278
+ // Failed to decode with decodeURIComponent, fallback to lenient decoding which replaces invalid UTF-8 byte sequences with the Unicode replacement character
279
+ // TODO: Consider removing in the next major version to be more strict about invalid percent-encodings
280
+ const binary = decodeHexEscapes(encoded)
281
+
282
+ const bytes = new Uint8Array(binary.length)
283
+ for (let idx = 0; idx < binary.length; idx++) {
284
+ bytes[idx] = binary.charCodeAt(idx)
285
+ }
286
+
287
+ return utf8Decoder.decode(bytes)
288
+ }
289
+ }
288
290
  }
289
-
290
- return value
291
+ throw new TypeError('unsupported charset in extended field')
291
292
  }
292
293
 
293
294
  /**
@@ -383,19 +384,6 @@ function parse (string) {
383
384
  return new ContentDisposition(type, params)
384
385
  }
385
386
 
386
- /**
387
- * Percent decode a single character.
388
- *
389
- * @param {string} str
390
- * @param {string} hex
391
- * @return {string}
392
- * @private
393
- */
394
-
395
- function pdecode (str, hex) {
396
- return String.fromCharCode(parseInt(hex, 16))
397
- }
398
-
399
387
  /**
400
388
  * Percent encode a single character.
401
389
  *
@@ -456,3 +444,93 @@ function ContentDisposition (type, parameters) {
456
444
  this.type = type
457
445
  this.parameters = parameters
458
446
  }
447
+
448
+ /**
449
+ * Return the last portion of a path
450
+ *
451
+ * @param {string} path
452
+ * @returns {string}
453
+ */
454
+ function basename (path) {
455
+ const normalized = path.replaceAll('\\', '/')
456
+
457
+ let end = normalized.length
458
+ while (end > 0 && normalized[end - 1] === '/') {
459
+ end--
460
+ }
461
+
462
+ if (end === 0) {
463
+ return ''
464
+ }
465
+
466
+ let start = end - 1
467
+ while (start >= 0 && normalized[start] !== '/') {
468
+ start--
469
+ }
470
+
471
+ return normalized.slice(start + 1, end)
472
+ }
473
+
474
+ /**
475
+ * Check if a character is a hex digit [0-9A-Fa-f]
476
+ *
477
+ * @param {string} char
478
+ * @return {boolean}
479
+ * @private
480
+ */
481
+ function isHexDigit (char) {
482
+ const code = char.charCodeAt(0)
483
+ return (
484
+ (code >= 48 && code <= 57) || // 0-9
485
+ (code >= 65 && code <= 70) || // A-F
486
+ (code >= 97 && code <= 102) // a-f
487
+ )
488
+ }
489
+
490
+ /**
491
+ * Check if a string contains percent encoding escapes.
492
+ *
493
+ * @param {string} str
494
+ * @return {boolean}
495
+ * @private
496
+ */
497
+ function hasHexEscape (str) {
498
+ const maxIndex = str.length - 3
499
+ let lastIndex = -1
500
+
501
+ while ((lastIndex = str.indexOf('%', lastIndex + 1)) !== -1 && lastIndex <= maxIndex) {
502
+ if (isHexDigit(str[lastIndex + 1]) && isHexDigit(str[lastIndex + 2])) {
503
+ return true
504
+ }
505
+ }
506
+
507
+ return false
508
+ }
509
+
510
+ /**
511
+ * Decode hex escapes in a string (e.g., %20 -> space)
512
+ *
513
+ * @param {string} str
514
+ * @return {string}
515
+ * @private
516
+ */
517
+ function decodeHexEscapes (str) {
518
+ const firstEscape = str.indexOf('%')
519
+ if (firstEscape === -1) return str
520
+
521
+ let result = str.slice(0, firstEscape)
522
+ for (let idx = firstEscape; idx < str.length; idx++) {
523
+ if (
524
+ str[idx] === '%' &&
525
+ idx + 2 < str.length &&
526
+ isHexDigit(str[idx + 1]) &&
527
+ isHexDigit(str[idx + 2])
528
+ ) {
529
+ result += String.fromCharCode(Number.parseInt(str[idx + 1] + str[idx + 2], 16))
530
+ idx += 2
531
+ } else {
532
+ result += str[idx]
533
+ }
534
+ }
535
+ return result
536
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "content-disposition",
3
3
  "description": "Create and parse Content-Disposition header",
4
- "version": "1.0.1",
4
+ "version": "1.1.0",
5
5
  "author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -17,18 +17,15 @@
17
17
  },
18
18
  "devDependencies": {
19
19
  "c8": "^10.1.2",
20
- "eslint": "7.32.0",
21
- "eslint-config-standard": "13.0.1",
22
- "eslint-plugin-import": "2.25.3",
23
- "eslint-plugin-markdown": "2.2.1",
24
- "eslint-plugin-node": "11.1.0",
25
- "eslint-plugin-promise": "5.2.0",
26
- "eslint-plugin-standard": "4.1.0"
20
+ "eslint": "^8.57.1",
21
+ "eslint-config-standard": "^14.1.1",
22
+ "eslint-plugin-import": "^2.32.0",
23
+ "eslint-plugin-markdown": "^3.0.1",
24
+ "eslint-plugin-node": "^11.1.0",
25
+ "eslint-plugin-promise": "^6.6.0",
26
+ "eslint-plugin-standard": "^4.1.0"
27
27
  },
28
28
  "files": [
29
- "LICENSE",
30
- "HISTORY.md",
31
- "README.md",
32
29
  "index.js"
33
30
  ],
34
31
  "engines": {
@@ -2,25 +2,32 @@
2
2
 
3
3
  **Fast, unopinionated, minimalist web framework for [Node.js](https://nodejs.org).**
4
4
 
5
- **This project has a [Code of Conduct][].**
5
+ **This project has a [Code of Conduct].**
6
6
 
7
7
  ## Table of contents
8
8
 
9
- * [Installation](#Installation)
10
- * [Features](#Features)
11
- * [Docs & Community](#docs--community)
12
- * [Quick Start](#Quick-Start)
13
- * [Running Tests](#Running-Tests)
14
- * [Philosophy](#Philosophy)
15
- * [Examples](#Examples)
16
- * [Contributing to Express](#Contributing)
17
- * [TC (Technical Committee)](#tc-technical-committee)
18
- * [Triagers](#triagers)
19
- * [License](#license)
9
+ - [Table of contents](#table-of-contents)
10
+ - [Installation](#installation)
11
+ - [Features](#features)
12
+ - [Docs \& Community](#docs--community)
13
+ - [Quick Start](#quick-start)
14
+ - [Philosophy](#philosophy)
15
+ - [Examples](#examples)
16
+ - [Contributing](#contributing)
17
+ - [Security Issues](#security-issues)
18
+ - [Running Tests](#running-tests)
19
+ - [Current project team members](#current-project-team-members)
20
+ - [TC (Technical Committee)](#tc-technical-committee)
21
+ - [TC emeriti members](#tc-emeriti-members)
22
+ - [Triagers](#triagers)
23
+ - [Emeritus Triagers](#emeritus-triagers)
24
+ - [License](#license)
20
25
 
21
26
 
22
27
  [![NPM Version][npm-version-image]][npm-url]
23
28
  [![NPM Downloads][npm-downloads-image]][npm-downloads-url]
29
+ [![Linux Build][github-actions-ci-image]][github-actions-ci-url]
30
+ [![Test Coverage][coveralls-image]][coveralls-url]
24
31
  [![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
25
32
 
26
33
 
@@ -33,7 +40,9 @@ app.get('/', (req, res) => {
33
40
  res.send('Hello World')
34
41
  })
35
42
 
36
- app.listen(3000)
43
+ app.listen(3000, () => {
44
+ console.log('Server is running on http://localhost:3000')
45
+ })
37
46
  ```
38
47
 
39
48
  ## Installation
@@ -137,18 +146,15 @@ node examples/content-negotiation
137
146
 
138
147
  ## Contributing
139
148
 
140
- [![Linux Build][github-actions-ci-image]][github-actions-ci-url]
141
- [![Test Coverage][coveralls-image]][coveralls-url]
142
-
143
149
  The Express.js project welcomes all constructive contributions. Contributions take many forms,
144
150
  from code for bug fixes and enhancements, to additions and fixes to documentation, additional
145
151
  tests, triaging incoming pull requests and issues, and more!
146
152
 
147
- See the [Contributing Guide](Contributing.md) for more technical details on contributing.
153
+ See the [Contributing Guide] for more technical details on contributing.
148
154
 
149
155
  ### Security Issues
150
156
 
151
- If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
157
+ If you discover a security vulnerability in Express, please see [Security Policies and Procedures](SECURITY.md).
152
158
 
153
159
  ### Running Tests
154
160
 
@@ -164,7 +170,9 @@ Then run `npm test`:
164
170
  npm test
165
171
  ```
166
172
 
167
- ## People
173
+ ## Current project team members
174
+
175
+ For information about the governance of the express.js project, see [GOVERNANCE.md](https://github.com/expressjs/discussions/blob/HEAD/docs/GOVERNANCE.md).
168
176
 
169
177
  The original author of Express is [TJ Holowaychuk](https://github.com/tj)
170
178
 
@@ -200,13 +208,11 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
200
208
  * [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran**
201
209
  * [carpasse](https://github.com/carpasse) - **Carlos Serrano**
202
210
  * [CBID2](https://github.com/CBID2) - **Christine Belzie**
203
- * [dpopp07](https://github.com/dpopp07) - **Dustin Popp**
204
211
  * [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
205
- * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
206
212
  * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him)
207
213
  * [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta**
208
- * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
209
- * [rxmarbles](https://github.com/rxmarbles) **Rick Markins** (He/him)
214
+ * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal**
215
+
210
216
 
211
217
  <details>
212
218
  <summary>Triagers emeriti members</summary>
@@ -245,7 +251,10 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
245
251
  * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him)
246
252
  * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego**
247
253
  * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin**
248
-
254
+ * [dpopp07](https://github.com/dpopp07) - **Dustin Popp**
255
+ * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
256
+ * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
257
+
249
258
  </details>
250
259
 
251
260
 
@@ -253,14 +262,15 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
253
262
 
254
263
  [MIT](LICENSE)
255
264
 
256
- [coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
265
+ [coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/express?branch=master
257
266
  [coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
258
- [github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=CI
267
+ [github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/express/ci.yml?branch=master&label=ci
259
268
  [github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml
260
- [npm-downloads-image]: https://badgen.net/npm/dm/express
269
+ [npm-downloads-image]: https://img.shields.io/npm/dm/express
261
270
  [npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true
262
271
  [npm-url]: https://npmjs.org/package/express
263
- [npm-version-image]: https://badgen.net/npm/v/express
272
+ [npm-version-image]: https://img.shields.io/npm/v/express
264
273
  [ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge
265
274
  [ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express
266
- [Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md
275
+ [Code of Conduct]: https://github.com/expressjs/.github/blob/HEAD/CODE_OF_CONDUCT.md
276
+ [Contributing Guide]: https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md
@@ -597,7 +597,7 @@ app.render = function render(name, options, callback) {
597
597
 
598
598
  app.listen = function listen() {
599
599
  var server = http.createServer(this)
600
- var args = Array.prototype.slice.call(arguments)
600
+ var args = slice.call(arguments)
601
601
  if (typeof args[args.length - 1] === 'function') {
602
602
  var done = args[args.length - 1] = once(args[args.length - 1])
603
603
  server.once('error', done)
@@ -169,9 +169,8 @@ req.acceptsCharsets = function(){
169
169
  * @public
170
170
  */
171
171
 
172
- req.acceptsLanguages = function(){
173
- var accept = accepts(this);
174
- return accept.languages.apply(accept, arguments);
172
+ req.acceptsLanguages = function(...languages) {
173
+ return accepts(this).languages(...languages);
175
174
  };
176
175
 
177
176
  /**
@@ -283,12 +282,12 @@ req.is = function is(types) {
283
282
  */
284
283
 
285
284
  defineGetter(req, 'protocol', function protocol(){
286
- var proto = this.connection.encrypted
285
+ var proto = this.socket.encrypted
287
286
  ? 'https'
288
287
  : 'http';
289
288
  var trust = this.app.get('trust proxy fn');
290
289
 
291
- if (!trust(this.connection.remoteAddress, 0)) {
290
+ if (!trust(this.socket.remoteAddress, 0)) {
292
291
  return proto;
293
292
  }
294
293
 
@@ -407,7 +406,7 @@ defineGetter(req, 'host', function host(){
407
406
  var trust = this.app.get('trust proxy fn');
408
407
  var val = this.get('X-Forwarded-Host');
409
408
 
410
- if (!val || !trust(this.connection.remoteAddress, 0)) {
409
+ if (!val || !trust(this.socket.remoteAddress, 0)) {
411
410
  val = this.get('Host');
412
411
  } else if (val.indexOf(',') !== -1) {
413
412
  // Note: X-Forwarded-Host is normally only ever a
@@ -14,6 +14,7 @@
14
14
 
15
15
  var contentDisposition = require('content-disposition');
16
16
  var createError = require('http-errors')
17
+ var deprecate = require('depd')('express');
17
18
  var encodeUrl = require('encodeurl');
18
19
  var escapeHtml = require('escape-html');
19
20
  var http = require('node:http');
@@ -31,6 +32,7 @@ var send = require('send');
31
32
  var extname = path.extname;
32
33
  var resolve = path.resolve;
33
34
  var vary = require('vary');
35
+ const { Buffer } = require('node:buffer');
34
36
 
35
37
  /**
36
38
  * Response prototype.
@@ -825,6 +827,18 @@ res.redirect = function redirect(url) {
825
827
  address = arguments[1]
826
828
  }
827
829
 
830
+ if (!address) {
831
+ deprecate('Provide a url argument');
832
+ }
833
+
834
+ if (typeof address !== 'string') {
835
+ deprecate('Url must be a string');
836
+ }
837
+
838
+ if (typeof status !== 'number') {
839
+ deprecate('Status must be a number');
840
+ }
841
+
828
842
  // Set location header
829
843
  address = this.location(address).get('Location');
830
844
 
@@ -18,7 +18,9 @@ var etag = require('etag');
18
18
  var mime = require('mime-types')
19
19
  var proxyaddr = require('proxy-addr');
20
20
  var qs = require('qs');
21
- var querystring = require('querystring');
21
+ var querystring = require('node:querystring');
22
+ const { Buffer } = require('node:buffer');
23
+
22
24
 
23
25
  /**
24
26
  * A list of lowercased HTTP methods that are supported by Node.js.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "express",
3
3
  "description": "Fast, unopinionated, minimalist web framework",
4
- "version": "5.1.0",
4
+ "version": "5.2.1",
5
5
  "author": "TJ Holowaychuk <tj@vision-media.ca>",
6
6
  "contributors": [
7
7
  "Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -33,12 +33,13 @@
33
33
  ],
34
34
  "dependencies": {
35
35
  "accepts": "^2.0.0",
36
- "body-parser": "^2.2.0",
36
+ "body-parser": "^2.2.1",
37
37
  "content-disposition": "^1.0.0",
38
38
  "content-type": "^1.0.5",
39
39
  "cookie": "^0.7.1",
40
40
  "cookie-signature": "^1.2.1",
41
41
  "debug": "^4.4.0",
42
+ "depd": "^2.0.0",
42
43
  "encodeurl": "^2.0.0",
43
44
  "escape-html": "^1.0.3",
44
45
  "etag": "^1.8.1",
@@ -64,7 +65,7 @@
64
65
  "after": "0.8.2",
65
66
  "connect-redis": "^8.0.1",
66
67
  "cookie-parser": "1.4.7",
67
- "cookie-session": "2.1.0",
68
+ "cookie-session": "2.1.1",
68
69
  "ejs": "^3.1.10",
69
70
  "eslint": "8.47.0",
70
71
  "express-session": "^1.18.1",
@@ -72,7 +73,7 @@
72
73
  "marked": "^15.0.3",
73
74
  "method-override": "3.0.0",
74
75
  "mocha": "^10.7.3",
75
- "morgan": "1.10.0",
76
+ "morgan": "1.10.1",
76
77
  "nyc": "^17.1.0",
77
78
  "pbkdf2-password": "1.2.1",
78
79
  "supertest": "^6.3.0",
@@ -83,13 +84,13 @@
83
84
  },
84
85
  "files": [
85
86
  "LICENSE",
86
- "History.md",
87
87
  "Readme.md",
88
88
  "index.js",
89
89
  "lib/"
90
90
  ],
91
91
  "scripts": {
92
92
  "lint": "eslint .",
93
+ "lint:fix": "eslint . --fix",
93
94
  "test": "mocha --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
94
95
  "test-ci": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test",
95
96
  "test-cov": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test",
@@ -1,3 +1,9 @@
1
+ v2.1.1. / 2025-12-01
2
+ ==================
3
+
4
+ * update engines field in the package.json to reflect the current compatibility (Node <18). See: 2.0.0
5
+ * Minor changes (package metadata)
6
+
1
7
  v2.1.0 / 2025-03-05
2
8
  ==================
3
9
 
@@ -5,6 +5,7 @@
5
5
  [![Node.js Version][node-image]][node-url]
6
6
  [![Build Status][github-actions-ci-image]][github-actions-ci-url]
7
7
  [![Test Coverage][coveralls-image]][coveralls-url]
8
+ [![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
8
9
 
9
10
  Node.js function to invoke as the final step to respond to HTTP request.
10
11
 
@@ -21,7 +22,7 @@ $ npm install finalhandler
21
22
  ## API
22
23
 
23
24
  ```js
24
- var finalhandler = require('finalhandler')
25
+ const finalhandler = require('finalhandler')
25
26
  ```
26
27
 
27
28
  ### finalhandler(req, res, [options])
@@ -59,11 +60,11 @@ as `onerror(err, req, res)`.
59
60
  ### always 404
60
61
 
61
62
  ```js
62
- var finalhandler = require('finalhandler')
63
- var http = require('http')
63
+ const finalhandler = require('finalhandler')
64
+ const http = require('http')
64
65
 
65
- var server = http.createServer(function (req, res) {
66
- var done = finalhandler(req, res)
66
+ const server = http.createServer((req, res) => {
67
+ const done = finalhandler(req, res)
67
68
  done()
68
69
  })
69
70
 
@@ -73,14 +74,14 @@ server.listen(3000)
73
74
  ### perform simple action
74
75
 
75
76
  ```js
76
- var finalhandler = require('finalhandler')
77
- var fs = require('fs')
78
- var http = require('http')
77
+ const finalhandler = require('finalhandler')
78
+ const fs = require('fs')
79
+ const http = require('http')
79
80
 
80
- var server = http.createServer(function (req, res) {
81
- var done = finalhandler(req, res)
81
+ const server = http.createServer((req, res) => {
82
+ const done = finalhandler(req, res)
82
83
 
83
- fs.readFile('index.html', function (err, buf) {
84
+ fs.readFile('index.html', (err, buf) => {
84
85
  if (err) return done(err)
85
86
  res.setHeader('Content-Type', 'text/html')
86
87
  res.end(buf)
@@ -93,14 +94,14 @@ server.listen(3000)
93
94
  ### use with middleware-style functions
94
95
 
95
96
  ```js
96
- var finalhandler = require('finalhandler')
97
- var http = require('http')
98
- var serveStatic = require('serve-static')
97
+ const finalhandler = require('finalhandler')
98
+ const http = require('http')
99
+ const serveStatic = require('serve-static')
99
100
 
100
- var serve = serveStatic('public')
101
+ const serve = serveStatic('public')
101
102
 
102
- var server = http.createServer(function (req, res) {
103
- var done = finalhandler(req, res)
103
+ const server = http.createServer((req, res) => {
104
+ const done = finalhandler(req, res)
104
105
  serve(req, res, done)
105
106
  })
106
107
 
@@ -110,14 +111,14 @@ server.listen(3000)
110
111
  ### keep log of all errors
111
112
 
112
113
  ```js
113
- var finalhandler = require('finalhandler')
114
- var fs = require('fs')
115
- var http = require('http')
114
+ const finalhandler = require('finalhandler')
115
+ const fs = require('fs')
116
+ const http = require('http')
116
117
 
117
- var server = http.createServer(function (req, res) {
118
- var done = finalhandler(req, res, { onerror: logerror })
118
+ const server = http.createServer((req, res) => {
119
+ const done = finalhandler(req, res, { onerror: logerror })
119
120
 
120
- fs.readFile('index.html', function (err, buf) {
121
+ fs.readFile('index.html', (err, buf) => {
121
122
  if (err) return done(err)
122
123
  res.setHeader('Content-Type', 'text/html')
123
124
  res.end(buf)
@@ -145,3 +146,5 @@ function logerror (err) {
145
146
  [downloads-url]: https://npmjs.org/package/finalhandler
146
147
  [github-actions-ci-image]: https://github.com/pillarjs/finalhandler/actions/workflows/ci.yml/badge.svg
147
148
  [github-actions-ci-url]: https://github.com/pillarjs/finalhandler/actions/workflows/ci.yml
149
+ [ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/pillarjs/finalhandler/badge
150
+ [ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/pillarjs/finalhandler