step-node-agent 3.25.4 → 3.26.0

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 (289) hide show
  1. package/AgentConf.yaml +13 -0
  2. package/api/controllers/controller.js +4 -0
  3. package/api/routes/routes.js +1 -0
  4. package/node_modules/aws4/aws4.js +1 -1
  5. package/node_modules/aws4/package.json +2 -2
  6. package/node_modules/body-parser/HISTORY.md +7 -0
  7. package/node_modules/body-parser/README.md +11 -0
  8. package/node_modules/body-parser/lib/types/urlencoded.js +30 -7
  9. package/node_modules/body-parser/package.json +2 -2
  10. package/node_modules/encodeurl/README.md +19 -38
  11. package/node_modules/encodeurl/index.js +1 -1
  12. package/node_modules/encodeurl/package.json +7 -7
  13. package/node_modules/express/History.md +27 -0
  14. package/node_modules/express/Readme.md +100 -6
  15. package/node_modules/express/lib/response.js +11 -10
  16. package/node_modules/express/package.json +11 -11
  17. package/node_modules/finalhandler/HISTORY.md +15 -0
  18. package/node_modules/finalhandler/README.md +2 -2
  19. package/node_modules/finalhandler/index.js +7 -2
  20. package/node_modules/finalhandler/package.json +8 -7
  21. package/node_modules/get-fqdn/LICENSE +21 -0
  22. package/node_modules/get-fqdn/README.md +83 -0
  23. package/node_modules/get-fqdn/index.js +17 -0
  24. package/node_modules/get-fqdn/package.json +73 -0
  25. package/node_modules/is-core-module/CHANGELOG.md +10 -0
  26. package/node_modules/is-core-module/core.json +2 -2
  27. package/node_modules/is-core-module/package.json +4 -4
  28. package/node_modules/is-core-module/test/index.js +17 -1
  29. package/node_modules/merge-descriptors/README.md +4 -3
  30. package/node_modules/merge-descriptors/index.js +3 -3
  31. package/node_modules/merge-descriptors/package.json +14 -7
  32. package/node_modules/path-to-regexp/index.js +57 -40
  33. package/node_modules/path-to-regexp/package.json +2 -2
  34. package/node_modules/qs/.editorconfig +3 -0
  35. package/node_modules/qs/.eslintrc +2 -2
  36. package/node_modules/qs/CHANGELOG.md +59 -5
  37. package/node_modules/qs/README.md +133 -49
  38. package/node_modules/qs/dist/qs.js +56 -2020
  39. package/node_modules/qs/lib/parse.js +46 -13
  40. package/node_modules/qs/lib/stringify.js +53 -28
  41. package/node_modules/qs/lib/utils.js +47 -34
  42. package/node_modules/qs/package.json +26 -12
  43. package/node_modules/qs/test/empty-keys-cases.js +267 -0
  44. package/node_modules/qs/test/parse.js +347 -32
  45. package/node_modules/qs/test/stringify.js +436 -47
  46. package/node_modules/send/HISTORY.md +5 -0
  47. package/node_modules/send/index.js +1 -2
  48. package/node_modules/send/node_modules/encodeurl/LICENSE +22 -0
  49. package/node_modules/send/node_modules/encodeurl/README.md +128 -0
  50. package/node_modules/send/node_modules/encodeurl/index.js +60 -0
  51. package/node_modules/send/node_modules/encodeurl/package.json +40 -0
  52. package/node_modules/send/package.json +1 -1
  53. package/node_modules/serve-static/HISTORY.md +16 -0
  54. package/node_modules/serve-static/index.js +1 -2
  55. package/node_modules/serve-static/package.json +3 -3
  56. package/node_modules/yaml/LICENSE +13 -0
  57. package/node_modules/yaml/README.md +155 -0
  58. package/node_modules/yaml/bin.mjs +11 -0
  59. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  60. package/node_modules/yaml/browser/dist/compose/compose-doc.js +42 -0
  61. package/node_modules/yaml/browser/dist/compose/compose-node.js +92 -0
  62. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +80 -0
  63. package/node_modules/yaml/browser/dist/compose/composer.js +217 -0
  64. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +113 -0
  65. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  66. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +47 -0
  67. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  68. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +203 -0
  69. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +223 -0
  70. package/node_modules/yaml/browser/dist/compose/resolve-props.js +148 -0
  71. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  72. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +27 -0
  73. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  74. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +17 -0
  75. package/node_modules/yaml/browser/dist/doc/Document.js +334 -0
  76. package/node_modules/yaml/browser/dist/doc/anchors.js +72 -0
  77. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  78. package/node_modules/yaml/browser/dist/doc/createNode.js +89 -0
  79. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  80. package/node_modules/yaml/browser/dist/errors.js +57 -0
  81. package/node_modules/yaml/browser/dist/index.js +17 -0
  82. package/node_modules/yaml/browser/dist/log.js +14 -0
  83. package/node_modules/yaml/browser/dist/nodes/Alias.js +101 -0
  84. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  85. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  86. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  87. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  88. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  89. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  90. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +104 -0
  91. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  92. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  93. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  94. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  95. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  96. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  97. package/node_modules/yaml/browser/dist/parse/lexer.js +717 -0
  98. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  99. package/node_modules/yaml/browser/dist/parse/parser.js +954 -0
  100. package/node_modules/yaml/browser/dist/public-api.js +99 -0
  101. package/node_modules/yaml/browser/dist/schema/Schema.js +38 -0
  102. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  103. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  104. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  105. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  106. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  107. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  108. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  109. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  110. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  111. package/node_modules/yaml/browser/dist/schema/tags.js +83 -0
  112. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +66 -0
  113. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  114. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  115. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  116. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  117. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  118. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +37 -0
  119. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  120. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  121. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  122. package/node_modules/yaml/browser/dist/stringify/stringify.js +124 -0
  123. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +143 -0
  124. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  125. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  126. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +24 -0
  127. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  128. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +328 -0
  129. package/node_modules/yaml/browser/dist/util.js +11 -0
  130. package/node_modules/yaml/browser/dist/visit.js +233 -0
  131. package/node_modules/yaml/browser/index.js +5 -0
  132. package/node_modules/yaml/browser/package.json +3 -0
  133. package/node_modules/yaml/dist/cli.d.ts +8 -0
  134. package/node_modules/yaml/dist/cli.mjs +199 -0
  135. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  136. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  137. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  138. package/node_modules/yaml/dist/compose/compose-doc.js +44 -0
  139. package/node_modules/yaml/dist/compose/compose-node.d.ts +28 -0
  140. package/node_modules/yaml/dist/compose/compose-node.js +95 -0
  141. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  142. package/node_modules/yaml/dist/compose/compose-scalar.js +82 -0
  143. package/node_modules/yaml/dist/compose/composer.d.ts +62 -0
  144. package/node_modules/yaml/dist/compose/composer.js +221 -0
  145. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  146. package/node_modules/yaml/dist/compose/resolve-block-map.js +115 -0
  147. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  148. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  149. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  150. package/node_modules/yaml/dist/compose/resolve-block-seq.js +49 -0
  151. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  152. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  153. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  154. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +205 -0
  155. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  156. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +225 -0
  157. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  158. package/node_modules/yaml/dist/compose/resolve-props.js +150 -0
  159. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  160. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  161. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  162. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +29 -0
  163. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  164. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  165. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  166. package/node_modules/yaml/dist/compose/util-map-includes.js +19 -0
  167. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  168. package/node_modules/yaml/dist/doc/Document.js +336 -0
  169. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  170. package/node_modules/yaml/dist/doc/anchors.js +77 -0
  171. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  172. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  173. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  174. package/node_modules/yaml/dist/doc/createNode.js +91 -0
  175. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  176. package/node_modules/yaml/dist/doc/directives.js +178 -0
  177. package/node_modules/yaml/dist/errors.d.ts +21 -0
  178. package/node_modules/yaml/dist/errors.js +62 -0
  179. package/node_modules/yaml/dist/index.d.ts +22 -0
  180. package/node_modules/yaml/dist/index.js +50 -0
  181. package/node_modules/yaml/dist/log.d.ts +3 -0
  182. package/node_modules/yaml/dist/log.js +17 -0
  183. package/node_modules/yaml/dist/nodes/Alias.d.ts +28 -0
  184. package/node_modules/yaml/dist/nodes/Alias.js +103 -0
  185. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  186. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  187. package/node_modules/yaml/dist/nodes/Node.d.ts +47 -0
  188. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  189. package/node_modules/yaml/dist/nodes/Pair.d.ts +21 -0
  190. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  191. package/node_modules/yaml/dist/nodes/Scalar.d.ts +42 -0
  192. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  193. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  194. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  195. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  196. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  197. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  198. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +106 -0
  199. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  200. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  201. package/node_modules/yaml/dist/nodes/toJS.d.ts +27 -0
  202. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  203. package/node_modules/yaml/dist/options.d.ts +338 -0
  204. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  205. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  206. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  207. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  208. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  209. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  210. package/node_modules/yaml/dist/parse/cst.d.ts +108 -0
  211. package/node_modules/yaml/dist/parse/cst.js +112 -0
  212. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  213. package/node_modules/yaml/dist/parse/lexer.js +719 -0
  214. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  215. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  216. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  217. package/node_modules/yaml/dist/parse/parser.js +958 -0
  218. package/node_modules/yaml/dist/public-api.d.ts +43 -0
  219. package/node_modules/yaml/dist/public-api.js +104 -0
  220. package/node_modules/yaml/dist/schema/Schema.d.ts +18 -0
  221. package/node_modules/yaml/dist/schema/Schema.js +40 -0
  222. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  223. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  224. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  225. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  226. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  227. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  228. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  229. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  230. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  231. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  232. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  233. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  234. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  235. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  236. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  237. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  238. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  239. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  240. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  241. package/node_modules/yaml/dist/schema/tags.d.ts +40 -0
  242. package/node_modules/yaml/dist/schema/tags.js +86 -0
  243. package/node_modules/yaml/dist/schema/types.d.ts +90 -0
  244. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  245. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +68 -0
  246. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  247. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  248. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  249. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  250. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  251. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  252. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +28 -0
  253. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  254. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  255. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  256. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  257. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +39 -0
  258. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  259. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  260. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  261. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  262. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  263. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  264. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  265. package/node_modules/yaml/dist/stringify/stringify.js +127 -0
  266. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  267. package/node_modules/yaml/dist/stringify/stringifyCollection.js +145 -0
  268. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  269. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  270. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  271. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  272. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  273. package/node_modules/yaml/dist/stringify/stringifyNumber.js +26 -0
  274. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  275. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  276. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  277. package/node_modules/yaml/dist/stringify/stringifyString.js +330 -0
  278. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  279. package/node_modules/yaml/dist/test-events.js +134 -0
  280. package/node_modules/yaml/dist/util.d.ts +12 -0
  281. package/node_modules/yaml/dist/util.js +28 -0
  282. package/node_modules/yaml/dist/visit.d.ts +102 -0
  283. package/node_modules/yaml/dist/visit.js +236 -0
  284. package/node_modules/yaml/package.json +96 -0
  285. package/node_modules/yaml/util.js +2 -0
  286. package/package.json +7 -3
  287. package/server.js +50 -23
  288. package/node_modules/path-to-regexp/History.md +0 -36
  289. /package/node_modules/{encodeurl → send/node_modules/encodeurl}/HISTORY.md +0 -0
@@ -1,4 +1,58 @@
1
- ## **6.11.0
1
+ ## **6.13.0**
2
+ - [New] `parse`: add `strictDepth` option (#511)
3
+ - [Tests] use `npm audit` instead of `aud`
4
+
5
+ ## **6.12.3**
6
+ - [Fix] `parse`: properly account for `strictNullHandling` when `allowEmptyArrays`
7
+ - [meta] fix changelog indentation
8
+
9
+ ## **6.12.2**
10
+ - [Fix] `parse`: parse encoded square brackets (#506)
11
+ - [readme] add CII best practices badge
12
+
13
+ ## **6.12.1**
14
+ - [Fix] `parse`: Disable `decodeDotInKeys` by default to restore previous behavior (#501)
15
+ - [Performance] `utils`: Optimize performance under large data volumes, reduce memory usage, and speed up processing (#502)
16
+ - [Refactor] `utils`: use `+=`
17
+ - [Tests] increase coverage
18
+
19
+ ## **6.12.0**
20
+
21
+ - [New] `parse`/`stringify`: add `decodeDotInKeys`/`encodeDotKeys` options (#488)
22
+ - [New] `parse`: add `duplicates` option
23
+ - [New] `parse`/`stringify`: add `allowEmptyArrays` option to allow [] in object values (#487)
24
+ - [Refactor] `parse`/`stringify`: move allowDots config logic to its own variable
25
+ - [Refactor] `stringify`: move option-handling code into `normalizeStringifyOptions`
26
+ - [readme] update readme, add logos (#484)
27
+ - [readme] `stringify`: clarify default `arrayFormat` behavior
28
+ - [readme] fix line wrapping
29
+ - [readme] remove dead badges
30
+ - [Deps] update `side-channel`
31
+ - [meta] make the dist build 50% smaller
32
+ - [meta] add `sideEffects` flag
33
+ - [meta] run build in prepack, not prepublish
34
+ - [Tests] `parse`: remove useless tests; add coverage
35
+ - [Tests] `stringify`: increase coverage
36
+ - [Tests] use `mock-property`
37
+ - [Tests] `stringify`: improve coverage
38
+ - [Dev Deps] update `@ljharb/eslint-config `, `aud`, `has-override-mistake`, `has-property-descriptors`, `mock-property`, `npmignore`, `object-inspect`, `tape`
39
+ - [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak`
40
+ - [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6
41
+
42
+ ## **6.11.2**
43
+ - [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473)
44
+ - [Tests] add passing test cases with empty keys (#473)
45
+
46
+ ## **6.11.1**
47
+ - [Fix] `stringify`: encode comma values more consistently (#463)
48
+ - [readme] add usage of `filter` option for injecting custom serialization, i.e. of custom types (#447)
49
+ - [meta] remove extraneous code backticks (#457)
50
+ - [meta] fix changelog markdown
51
+ - [actions] update checkout action
52
+ - [actions] restrict action permissions
53
+ - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape`
54
+
55
+ ## **6.11.0**
2
56
  - [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442)
3
57
  - [readme] fix version badge
4
58
 
@@ -238,7 +292,7 @@
238
292
 
239
293
  ## **6.5.3**
240
294
  - [Fix] `parse`: ignore `__proto__` keys (#428)
241
- - [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
295
+ - [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
242
296
  - [Fix] correctly parse nested arrays
243
297
  - [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
244
298
  - [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
@@ -291,7 +345,7 @@
291
345
  - [Fix] fix for an impossible situation: when the formatter is called with a non-string value
292
346
  - [Fix] use `safer-buffer` instead of `Buffer` constructor
293
347
  - [Fix] `utils.merge`: avoid a crash with a null target and an array source
294
- - [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
348
+ - [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
295
349
  - [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
296
350
  - [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
297
351
  - [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
@@ -320,7 +374,7 @@
320
374
  - [Fix] `parse`: ignore `__proto__` keys (#428)
321
375
  - [Fix] fix for an impossible situation: when the formatter is called with a non-string value
322
376
  - [Fix] `utils.merge`: avoid a crash with a null target and an array source
323
- - [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
377
+ - [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
324
378
  - [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
325
379
  - [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
326
380
  - [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
@@ -407,7 +461,7 @@
407
461
  - [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160)
408
462
  - [Fix] fix compacting of nested sparse arrays (#150)
409
463
 
410
- ## **6.1.2
464
+ ## **6.1.2**
411
465
  - [Fix] follow `allowPrototypes` option during merge (#201, #200)
412
466
  - [Fix] chmod a-x
413
467
  - [Fix] support keys starting with brackets (#202, #200)
@@ -1,11 +1,14 @@
1
+ <p align="center">
2
+ <img alt="qs" src="./logos/banner_default.png" width="800" />
3
+ </p>
4
+
1
5
  # qs <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
2
6
 
3
7
  [![github actions][actions-image]][actions-url]
4
8
  [![coverage][codecov-image]][codecov-url]
5
- [![dependency status][deps-svg]][deps-url]
6
- [![dev dependency status][dev-deps-svg]][dev-deps-url]
7
9
  [![License][license-image]][license-url]
8
10
  [![Downloads][downloads-image]][downloads-url]
11
+ [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/9058/badge)](https://bestpractices.coreinfrastructure.org/projects/9058)
9
12
 
10
13
  [![npm badge][npm-badge-png]][package-url]
11
14
 
@@ -53,7 +56,9 @@ var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
53
56
  assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
54
57
  ```
55
58
 
56
- By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option.
59
+ By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties.
60
+ *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten.
61
+ Always be careful with this option.
57
62
 
58
63
  ```javascript
59
64
  var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
@@ -80,8 +85,8 @@ assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
80
85
  });
81
86
  ```
82
87
 
83
- By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like
84
- `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
88
+ By default, when nesting objects **qs** will only parse up to 5 children deep.
89
+ This means if you attempt to parse a string like `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
85
90
 
86
91
  ```javascript
87
92
  var expected = {
@@ -110,7 +115,18 @@ var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
110
115
  assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
111
116
  ```
112
117
 
113
- The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number.
118
+ You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false):
119
+
120
+ ```javascript
121
+ try {
122
+ qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
123
+ } catch (err) {
124
+ assert(err instanceof RangeError);
125
+ assert.strictEqual(err.message, 'Input depth exceeded depth option of 1 and strictDepth is true');
126
+ }
127
+ ```
128
+
129
+ The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded, allowing you to catch and handle such cases.
114
130
 
115
131
  For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
116
132
 
@@ -147,32 +163,44 @@ var withDots = qs.parse('a.b=c', { allowDots: true });
147
163
  assert.deepEqual(withDots, { a: { b: 'c' } });
148
164
  ```
149
165
 
150
- If you have to deal with legacy browsers or services, there's
151
- also support for decoding percent-encoded octets as iso-8859-1:
166
+ Option `decodeDotInKeys` can be used to decode dots in keys
167
+ Note: it implies `allowDots`, so `parse` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
168
+
169
+ ```javascript
170
+ var withDots = qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { decodeDotInKeys: true });
171
+ assert.deepEqual(withDots, { 'name.obj': { first: 'John', last: 'Doe' }});
172
+ ```
173
+
174
+ Option `allowEmptyArrays` can be used to allowing empty array values in object
175
+ ```javascript
176
+ var withEmptyArrays = qs.parse('foo[]&bar=baz', { allowEmptyArrays: true });
177
+ assert.deepEqual(withEmptyArrays, { foo: [], bar: 'baz' });
178
+ ```
179
+
180
+ Option `duplicates` can be used to change the behavior when duplicate keys are encountered
181
+ ```javascript
182
+ assert.deepEqual(qs.parse('foo=bar&foo=baz'), { foo: ['bar', 'baz'] });
183
+ assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), { foo: ['bar', 'baz'] });
184
+ assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'bar' });
185
+ assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' });
186
+ ```
187
+
188
+ If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1:
152
189
 
153
190
  ```javascript
154
191
  var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' });
155
192
  assert.deepEqual(oldCharset, { a: '§' });
156
193
  ```
157
194
 
158
- Some services add an initial `utf8=✓` value to forms so that old
159
- Internet Explorer versions are more likely to submit the form as
160
- utf-8. Additionally, the server can check the value against wrong
161
- encodings of the checkmark character and detect that a query string
162
- or `application/x-www-form-urlencoded` body was *not* sent as
163
- utf-8, eg. if the form had an `accept-charset` parameter or the
164
- containing page had a different character set.
195
+ Some services add an initial `utf8=✓` value to forms so that old Internet Explorer versions are more likely to submit the form as utf-8.
196
+ Additionally, the server can check the value against wrong encodings of the checkmark character and detect that a query string or `application/x-www-form-urlencoded` body was *not* sent as utf-8, eg. if the form had an `accept-charset` parameter or the containing page had a different character set.
165
197
 
166
198
  **qs** supports this mechanism via the `charsetSentinel` option.
167
- If specified, the `utf8` parameter will be omitted from the
168
- returned object. It will be used to switch to `iso-8859-1`/`utf-8`
169
- mode depending on how the checkmark is encoded.
199
+ If specified, the `utf8` parameter will be omitted from the returned object.
200
+ It will be used to switch to `iso-8859-1`/`utf-8` mode depending on how the checkmark is encoded.
170
201
 
171
- **Important**: When you specify both the `charset` option and the
172
- `charsetSentinel` option, the `charset` will be overridden when
173
- the request contains a `utf8` parameter from which the actual
174
- charset can be deduced. In that sense the `charset` will behave
175
- as the default charset rather than the authoritative charset.
202
+ **Important**: When you specify both the `charset` option and the `charsetSentinel` option, the `charset` will be overridden when the request contains a `utf8` parameter from which the actual charset can be deduced.
203
+ In that sense the `charset` will behave as the default charset rather than the authoritative charset.
176
204
 
177
205
  ```javascript
178
206
  var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', {
@@ -189,8 +217,7 @@ var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', {
189
217
  assert.deepEqual(detectedAsIso8859_1, { a: 'ø' });
190
218
  ```
191
219
 
192
- If you want to decode the `&#...;` syntax to the actual character,
193
- you can specify the `interpretNumericEntities` option as well:
220
+ If you want to decode the `&#...;` syntax to the actual character, you can specify the `interpretNumericEntities` option as well:
194
221
 
195
222
  ```javascript
196
223
  var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
@@ -200,8 +227,7 @@ var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
200
227
  assert.deepEqual(detectedAsIso8859_1, { a: '☺' });
201
228
  ```
202
229
 
203
- It also works when the charset has been detected in `charsetSentinel`
204
- mode.
230
+ It also works when the charset has been detected in `charsetSentinel` mode.
205
231
 
206
232
  ### Parsing Arrays
207
233
 
@@ -219,9 +245,8 @@ var withIndexes = qs.parse('a[1]=c&a[0]=b');
219
245
  assert.deepEqual(withIndexes, { a: ['b', 'c'] });
220
246
  ```
221
247
 
222
- Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number
223
- to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving
224
- their order:
248
+ Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number to create an array.
249
+ When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving their order:
225
250
 
226
251
  ```javascript
227
252
  var noSparse = qs.parse('a[1]=b&a[15]=c');
@@ -245,8 +270,9 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
245
270
  assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
246
271
  ```
247
272
 
248
- **qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will
249
- instead be converted to an object with the index as the key. This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
273
+ **qs** will also limit specifying indices in an array to a maximum index of `20`.
274
+ Any array members with an index of greater than `20` will instead be converted to an object with the index as the key.
275
+ This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
250
276
 
251
277
  ```javascript
252
278
  var withMaxIndex = qs.parse('a[100]=b');
@@ -290,7 +316,8 @@ assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
290
316
 
291
317
  ### Parsing primitive/scalar values (numbers, booleans, null, etc)
292
318
 
293
- By default, all values are parsed as strings. This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
319
+ By default, all values are parsed as strings.
320
+ This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
294
321
 
295
322
  ```javascript
296
323
  var primitiveValues = qs.parse('a=15&b=true&c=null');
@@ -373,16 +400,17 @@ var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset,
373
400
  }})
374
401
  ```
375
402
 
376
- Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage.
403
+ Examples beyond this point will be shown as though the output is not URI encoded for clarity.
404
+ Please note that the return values in these cases *will* be URI encoded during real usage.
377
405
 
378
- When arrays are stringified, by default they are given explicit indices:
406
+ When arrays are stringified, they follow the `arrayFormat` option, which defaults to `indices`:
379
407
 
380
408
  ```javascript
381
409
  qs.stringify({ a: ['b', 'c', 'd'] });
382
410
  // 'a[0]=b&a[1]=c&a[2]=d'
383
411
  ```
384
412
 
385
- You may override this by setting the `indices` option to `false`:
413
+ You may override this by setting the `indices` option to `false`, or to be more explicit, the `arrayFormat` option to `repeat`:
386
414
 
387
415
  ```javascript
388
416
  qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
@@ -418,6 +446,20 @@ qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
418
446
  // 'a.b.c=d&a.b.e=f'
419
447
  ```
420
448
 
449
+ You may encode the dot notation in the keys of object with option `encodeDotInKeys` by setting it to `true`:
450
+ Note: it implies `allowDots`, so `stringify` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
451
+ Caveat: when `encodeValuesOnly` is `true` as well as `encodeDotInKeys`, only dots in keys and nothing else will be encoded.
452
+ ```javascript
453
+ qs.stringify({ "name.obj": { "first": "John", "last": "Doe" } }, { allowDots: true, encodeDotInKeys: true })
454
+ // 'name%252Eobj.first=John&name%252Eobj.last=Doe'
455
+ ```
456
+
457
+ You may allow empty array values by setting the `allowEmptyArrays` option to `true`:
458
+ ```javascript
459
+ qs.stringify({ foo: [], bar: 'baz' }, { allowEmptyArrays: true });
460
+ // 'foo[]&bar=baz'
461
+ ```
462
+
421
463
  Empty strings and null values will omit the value, but the equals sign (=) remains in place:
422
464
 
423
465
  ```javascript
@@ -473,8 +515,8 @@ assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort
473
515
  ```
474
516
 
475
517
  Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
476
- If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
477
- pass an array, it will be used to select properties and array indices for stringification:
518
+ If you pass a function, it will be called for each key to obtain the replacement value.
519
+ Otherwise, if you pass an array, it will be used to select properties and array indices for stringification:
478
520
 
479
521
  ```javascript
480
522
  function filterFunc(prefix, value) {
@@ -498,6 +540,44 @@ qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
498
540
  // 'a[0]=b&a[2]=d'
499
541
  ```
500
542
 
543
+ You could also use `filter` to inject custom serialization for user defined types.
544
+ Consider you're working with some api that expects query strings of the format for ranges:
545
+
546
+ ```
547
+ https://domain.com/endpoint?range=30...70
548
+ ```
549
+
550
+ For which you model as:
551
+
552
+ ```javascript
553
+ class Range {
554
+ constructor(from, to) {
555
+ this.from = from;
556
+ this.to = to;
557
+ }
558
+ }
559
+ ```
560
+
561
+ You could _inject_ a custom serializer to handle values of this type:
562
+
563
+ ```javascript
564
+ qs.stringify(
565
+ {
566
+ range: new Range(30, 70),
567
+ },
568
+ {
569
+ filter: (prefix, value) => {
570
+ if (value instanceof Range) {
571
+ return `${value.from}...${value.to}`;
572
+ }
573
+ // serialize the usual way
574
+ return value;
575
+ },
576
+ }
577
+ );
578
+ // range=30...70
579
+ ```
580
+
501
581
  ### Handling of `null` values
502
582
 
503
583
  By default, `null` values are treated like empty strings:
@@ -507,7 +587,8 @@ var withNull = qs.stringify({ a: null, b: '' });
507
587
  assert.equal(withNull, 'a=&b=');
508
588
  ```
509
589
 
510
- Parsing does not distinguish between parameters with and without equal signs. Both are converted to empty strings.
590
+ Parsing does not distinguish between parameters with and without equal signs.
591
+ Both are converted to empty strings.
511
592
 
512
593
  ```javascript
513
594
  var equalsInsensitive = qs.parse('a&b=');
@@ -536,25 +617,21 @@ var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
536
617
  assert.equal(nullsSkipped, 'a=b');
537
618
  ```
538
619
 
539
- If you're communicating with legacy systems, you can switch to `iso-8859-1`
540
- using the `charset` option:
620
+ If you're communicating with legacy systems, you can switch to `iso-8859-1` using the `charset` option:
541
621
 
542
622
  ```javascript
543
623
  var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' });
544
624
  assert.equal(iso, '%E6=%E6');
545
625
  ```
546
626
 
547
- Characters that don't exist in `iso-8859-1` will be converted to numeric
548
- entities, similar to what browsers do:
627
+ Characters that don't exist in `iso-8859-1` will be converted to numeric entities, similar to what browsers do:
549
628
 
550
629
  ```javascript
551
630
  var numeric = qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' });
552
631
  assert.equal(numeric, 'a=%26%239786%3B');
553
632
  ```
554
633
 
555
- You can use the `charsetSentinel` option to announce the character by
556
- including an `utf8=✓` parameter with the proper encoding if the checkmark,
557
- similar to what Ruby on Rails and others do when submitting forms.
634
+ You can use the `charsetSentinel` option to announce the character by including an `utf8=✓` parameter with the proper encoding if the checkmark, similar to what Ruby on Rails and others do when submitting forms.
558
635
 
559
636
  ```javascript
560
637
  var sentinel = qs.stringify({ a: '☺' }, { charsetSentinel: true });
@@ -566,8 +643,7 @@ assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6');
566
643
 
567
644
  ### Dealing with special character sets
568
645
 
569
- By default the encoding and decoding of characters is done in `utf-8`,
570
- and `iso-8859-1` support is also built in via the `charset` parameter.
646
+ By default the encoding and decoding of characters is done in `utf-8`, and `iso-8859-1` support is also built in via the `charset` parameter.
571
647
 
572
648
  If you wish to encode querystrings to a different character set (i.e.
573
649
  [Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
@@ -606,7 +682,9 @@ Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/se
606
682
 
607
683
  Available as part of the Tidelift Subscription
608
684
 
609
- The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
685
+ The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications.
686
+ Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
687
+ [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
610
688
 
611
689
  [package-url]: https://npmjs.org/package/qs
612
690
  [npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
@@ -623,3 +701,9 @@ The maintainers of qs and thousands of other packages are working with Tidelift
623
701
  [codecov-url]: https://app.codecov.io/gh/ljharb/qs/
624
702
  [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs
625
703
  [actions-url]: https://github.com/ljharb/qs/actions
704
+
705
+ ## Acknowledgements
706
+
707
+ qs logo by [NUMI](https://github.com/numi-hq/open-design):
708
+
709
+ [<img src="https://raw.githubusercontent.com/numi-hq/open-design/main/assets/numi-lockup.png" alt="NUMI Logo" style="width: 200px;"/>](https://numi.tech/?ref=qs)