@fgv/ts-extras 5.1.0-5 → 5.1.0-50

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 (488) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +90 -0
  3. package/dist/index.browser.js +6 -2
  4. package/dist/index.browser.js.map +1 -0
  5. package/dist/index.js +2 -1
  6. package/dist/index.js.map +1 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
  8. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  9. package/dist/packlets/ai-assist/{apiClient.js → completionClient.js} +165 -214
  10. package/dist/packlets/ai-assist/completionClient.js.map +1 -0
  11. package/dist/packlets/ai-assist/converters.js +47 -3
  12. package/dist/packlets/ai-assist/converters.js.map +1 -0
  13. package/dist/packlets/ai-assist/embeddingClient.js +345 -0
  14. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  15. package/dist/packlets/ai-assist/endpoint.js +107 -0
  16. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  17. package/dist/packlets/ai-assist/http.js +104 -0
  18. package/dist/packlets/ai-assist/http.js.map +1 -0
  19. package/dist/packlets/ai-assist/imageGenerationClient.js +454 -0
  20. package/dist/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  21. package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
  22. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  23. package/dist/packlets/ai-assist/index.js +12 -4
  24. package/dist/packlets/ai-assist/index.js.map +1 -0
  25. package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
  26. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  27. package/dist/packlets/ai-assist/jsonResponse.js +423 -0
  28. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  29. package/dist/packlets/ai-assist/listModelsClient.js +294 -0
  30. package/dist/packlets/ai-assist/listModelsClient.js.map +1 -0
  31. package/dist/packlets/ai-assist/model.js +301 -9
  32. package/dist/packlets/ai-assist/model.js.map +1 -0
  33. package/dist/packlets/ai-assist/registry.js +376 -12
  34. package/dist/packlets/ai-assist/registry.js.map +1 -0
  35. package/dist/packlets/ai-assist/sseParser.js +123 -0
  36. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +376 -0
  38. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  39. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
  40. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  41. package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
  42. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  43. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +208 -0
  44. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  45. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +175 -0
  46. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  47. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +390 -0
  48. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  49. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +178 -0
  50. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  51. package/dist/packlets/ai-assist/streamingClient.js +140 -0
  52. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  53. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
  54. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  55. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  56. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  57. package/dist/packlets/conversion/converters.js +35 -1
  58. package/dist/packlets/conversion/converters.js.map +1 -0
  59. package/dist/packlets/conversion/index.js.map +1 -0
  60. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  61. package/dist/packlets/crypto-utils/converters.js +42 -4
  62. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  63. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  64. package/dist/packlets/crypto-utils/encryptedFile.js +37 -0
  65. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  66. package/dist/packlets/crypto-utils/hpkeProvider.js +355 -0
  67. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  68. package/dist/packlets/crypto-utils/index.browser.js +13 -2
  69. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  70. package/dist/packlets/crypto-utils/index.js +9 -1
  71. package/dist/packlets/crypto-utils/index.js.map +1 -0
  72. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  73. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  74. package/dist/packlets/crypto-utils/keystore/converters.js +111 -16
  75. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  76. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
  77. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  78. package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
  79. package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  80. package/dist/packlets/crypto-utils/keystore/index.js +3 -0
  81. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  82. package/dist/packlets/crypto-utils/keystore/keyStore.js +872 -119
  83. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  84. package/dist/packlets/crypto-utils/keystore/model.js +35 -4
  85. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  86. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  87. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  88. package/dist/packlets/crypto-utils/model.js +32 -0
  89. package/dist/packlets/crypto-utils/model.js.map +1 -0
  90. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +347 -1
  91. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  92. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js +120 -0
  93. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  94. package/dist/packlets/crypto-utils/spkiHelpers.js +284 -0
  95. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  96. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  97. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  98. package/dist/packlets/csv/csvHelpers.js +14 -0
  99. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  100. package/dist/packlets/csv/index.browser.js +1 -3
  101. package/dist/packlets/csv/index.browser.js.map +1 -0
  102. package/dist/packlets/csv/index.js.map +1 -0
  103. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  104. package/dist/packlets/experimental/formatter.js.map +1 -0
  105. package/dist/packlets/experimental/index.js.map +1 -0
  106. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  107. package/dist/packlets/hash/index.browser.js.map +1 -0
  108. package/dist/packlets/hash/index.js.map +1 -0
  109. package/dist/packlets/hash/index.node.js.map +1 -0
  110. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  111. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  112. package/dist/packlets/mustache/index.js.map +1 -0
  113. package/dist/packlets/mustache/interfaces.js.map +1 -0
  114. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  115. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  116. package/dist/packlets/record-jar/index.browser.js +1 -3
  117. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  118. package/dist/packlets/record-jar/index.js.map +1 -0
  119. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  120. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  121. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  122. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  123. package/dist/packlets/safer-fetch/addressClassification.js +438 -0
  124. package/dist/packlets/safer-fetch/addressClassification.js.map +1 -0
  125. package/dist/packlets/safer-fetch/addressPolicy.js +119 -0
  126. package/dist/packlets/safer-fetch/addressPolicy.js.map +1 -0
  127. package/dist/packlets/safer-fetch/contentType.js +120 -0
  128. package/dist/packlets/safer-fetch/contentType.js.map +1 -0
  129. package/dist/packlets/safer-fetch/deadline.js +254 -0
  130. package/dist/packlets/safer-fetch/deadline.js.map +1 -0
  131. package/dist/packlets/safer-fetch/defaults.js +131 -0
  132. package/dist/packlets/safer-fetch/defaults.js.map +1 -0
  133. package/dist/packlets/safer-fetch/failureReason.js +21 -0
  134. package/dist/packlets/safer-fetch/failureReason.js.map +1 -0
  135. package/dist/packlets/safer-fetch/guards.js +148 -0
  136. package/dist/packlets/safer-fetch/guards.js.map +1 -0
  137. package/dist/packlets/safer-fetch/index.browser.js +58 -0
  138. package/dist/packlets/safer-fetch/index.browser.js.map +1 -0
  139. package/dist/packlets/safer-fetch/index.js +52 -0
  140. package/dist/packlets/safer-fetch/index.js.map +1 -0
  141. package/dist/packlets/safer-fetch/model.js +21 -0
  142. package/dist/packlets/safer-fetch/model.js.map +1 -0
  143. package/dist/packlets/safer-fetch/nodeAddressGuard.js +191 -0
  144. package/dist/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  145. package/dist/packlets/safer-fetch/redirect.js +93 -0
  146. package/dist/packlets/safer-fetch/redirect.js.map +1 -0
  147. package/dist/packlets/safer-fetch/retry.js +188 -0
  148. package/dist/packlets/safer-fetch/retry.js.map +1 -0
  149. package/dist/packlets/safer-fetch/saferFetch.js +755 -0
  150. package/dist/packlets/safer-fetch/saferFetch.js.map +1 -0
  151. package/dist/packlets/safer-fetch/transport.js +50 -0
  152. package/dist/packlets/safer-fetch/transport.js.map +1 -0
  153. package/dist/packlets/yaml/converters.js.map +1 -0
  154. package/dist/packlets/yaml/index.js +1 -0
  155. package/dist/packlets/yaml/index.js.map +1 -0
  156. package/dist/packlets/yaml/serializers.js +48 -0
  157. package/dist/packlets/yaml/serializers.js.map +1 -0
  158. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  159. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  160. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  161. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js +16 -1
  162. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  163. package/dist/ts-extras.d.ts +6648 -553
  164. package/dist/tsdoc-metadata.json +1 -1
  165. package/lib/index.browser.d.ts +5 -2
  166. package/lib/index.browser.d.ts.map +1 -0
  167. package/lib/index.browser.js +11 -3
  168. package/lib/index.browser.js.map +1 -0
  169. package/lib/index.d.ts +2 -1
  170. package/lib/index.d.ts.map +1 -0
  171. package/lib/index.js +3 -1
  172. package/lib/index.js.map +1 -0
  173. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
  174. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  175. package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
  176. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  177. package/lib/packlets/ai-assist/completionClient.d.ts +74 -0
  178. package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -0
  179. package/lib/packlets/ai-assist/{apiClient.js → completionClient.js} +164 -213
  180. package/lib/packlets/ai-assist/completionClient.js.map +1 -0
  181. package/lib/packlets/ai-assist/converters.d.ts +15 -1
  182. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  183. package/lib/packlets/ai-assist/converters.js +47 -3
  184. package/lib/packlets/ai-assist/converters.js.map +1 -0
  185. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  186. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  187. package/lib/packlets/ai-assist/embeddingClient.js +349 -0
  188. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  189. package/lib/packlets/ai-assist/endpoint.d.ts +49 -0
  190. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  191. package/lib/packlets/ai-assist/endpoint.js +113 -0
  192. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  193. package/lib/packlets/ai-assist/http.d.ts +34 -0
  194. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  195. package/lib/packlets/ai-assist/http.js +109 -0
  196. package/lib/packlets/ai-assist/http.js.map +1 -0
  197. package/lib/packlets/ai-assist/imageGenerationClient.d.ts +46 -0
  198. package/lib/packlets/ai-assist/imageGenerationClient.d.ts.map +1 -0
  199. package/lib/packlets/ai-assist/imageGenerationClient.js +458 -0
  200. package/lib/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  201. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
  202. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  203. package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
  204. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  205. package/lib/packlets/ai-assist/index.d.ts +12 -4
  206. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  207. package/lib/packlets/ai-assist/index.js +47 -4
  208. package/lib/packlets/ai-assist/index.js.map +1 -0
  209. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  210. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  211. package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
  212. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  213. package/lib/packlets/ai-assist/jsonResponse.d.ts +194 -0
  214. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  215. package/lib/packlets/ai-assist/jsonResponse.js +429 -0
  216. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  217. package/lib/packlets/ai-assist/listModelsClient.d.ts +46 -0
  218. package/lib/packlets/ai-assist/listModelsClient.d.ts.map +1 -0
  219. package/lib/packlets/ai-assist/listModelsClient.js +298 -0
  220. package/lib/packlets/ai-assist/listModelsClient.js.map +1 -0
  221. package/lib/packlets/ai-assist/model.d.ts +1346 -12
  222. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  223. package/lib/packlets/ai-assist/model.js +309 -10
  224. package/lib/packlets/ai-assist/model.js.map +1 -0
  225. package/lib/packlets/ai-assist/registry.d.ts +76 -1
  226. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  227. package/lib/packlets/ai-assist/registry.js +381 -13
  228. package/lib/packlets/ai-assist/registry.js.map +1 -0
  229. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  230. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  231. package/lib/packlets/ai-assist/sseParser.js +128 -0
  232. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  233. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
  234. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  235. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +379 -0
  236. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  237. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +269 -0
  238. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  239. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
  240. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  241. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +163 -0
  242. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  243. package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
  244. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  245. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
  246. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  247. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +211 -0
  248. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  249. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  250. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  251. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +178 -0
  252. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  253. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
  254. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  255. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +393 -0
  256. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  257. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  258. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  259. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +181 -0
  260. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  261. package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
  262. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  263. package/lib/packlets/ai-assist/streamingClient.js +146 -0
  264. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  265. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
  266. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  267. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
  268. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  269. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  270. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  271. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  272. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  273. package/lib/packlets/conversion/converters.d.ts +8 -1
  274. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  275. package/lib/packlets/conversion/converters.js +36 -2
  276. package/lib/packlets/conversion/converters.js.map +1 -0
  277. package/lib/packlets/conversion/index.d.ts.map +1 -0
  278. package/lib/packlets/conversion/index.js.map +1 -0
  279. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  280. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  281. package/lib/packlets/crypto-utils/converters.d.ts +20 -1
  282. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  283. package/lib/packlets/crypto-utils/converters.js +43 -5
  284. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  285. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  286. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  287. package/lib/packlets/crypto-utils/encryptedFile.d.ts +25 -0
  288. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  289. package/lib/packlets/crypto-utils/encryptedFile.js +38 -0
  290. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  291. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +150 -0
  292. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  293. package/lib/packlets/crypto-utils/hpkeProvider.js +359 -0
  294. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  295. package/lib/packlets/crypto-utils/index.browser.d.ts +5 -1
  296. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  297. package/lib/packlets/crypto-utils/index.browser.js +28 -3
  298. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  299. package/lib/packlets/crypto-utils/index.d.ts +5 -1
  300. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  301. package/lib/packlets/crypto-utils/index.js +24 -1
  302. package/lib/packlets/crypto-utils/index.js.map +1 -0
  303. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  304. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  305. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  306. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  307. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  308. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  309. package/lib/packlets/crypto-utils/keystore/converters.js +109 -14
  310. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  311. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
  312. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
  313. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
  314. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  315. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
  316. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
  317. package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
  318. package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  319. package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
  320. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  321. package/lib/packlets/crypto-utils/keystore/index.js +5 -1
  322. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  323. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +314 -13
  324. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  325. package/lib/packlets/crypto-utils/keystore/keyStore.js +877 -124
  326. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  327. package/lib/packlets/crypto-utils/keystore/model.d.ts +404 -21
  328. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  329. package/lib/packlets/crypto-utils/keystore/model.js +37 -5
  330. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  331. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
  332. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  333. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  334. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  335. package/lib/packlets/crypto-utils/model.d.ts +518 -10
  336. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  337. package/lib/packlets/crypto-utils/model.js +33 -1
  338. package/lib/packlets/crypto-utils/model.js.map +1 -0
  339. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +142 -2
  340. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  341. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +346 -0
  342. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  343. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts +42 -0
  344. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts.map +1 -0
  345. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js +123 -0
  346. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  347. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +151 -0
  348. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  349. package/lib/packlets/crypto-utils/spkiHelpers.js +297 -0
  350. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  351. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  352. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  353. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  354. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  355. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  356. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  357. package/lib/packlets/csv/csvHelpers.js +15 -0
  358. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  359. package/lib/packlets/csv/index.browser.d.ts +0 -1
  360. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  361. package/lib/packlets/csv/index.browser.js +1 -5
  362. package/lib/packlets/csv/index.browser.js.map +1 -0
  363. package/lib/packlets/csv/index.d.ts.map +1 -0
  364. package/lib/packlets/csv/index.js.map +1 -0
  365. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  366. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  367. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  368. package/lib/packlets/experimental/formatter.js.map +1 -0
  369. package/lib/packlets/experimental/index.d.ts.map +1 -0
  370. package/lib/packlets/experimental/index.js.map +1 -0
  371. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  372. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  373. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  374. package/lib/packlets/hash/index.browser.js.map +1 -0
  375. package/lib/packlets/hash/index.d.ts.map +1 -0
  376. package/lib/packlets/hash/index.js.map +1 -0
  377. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  378. package/lib/packlets/hash/index.node.js.map +1 -0
  379. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  380. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  381. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  382. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  383. package/lib/packlets/mustache/index.d.ts +1 -1
  384. package/lib/packlets/mustache/index.d.ts.map +1 -0
  385. package/lib/packlets/mustache/index.js.map +1 -0
  386. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  387. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  388. package/lib/packlets/mustache/interfaces.js.map +1 -0
  389. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  390. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  391. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  392. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  393. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  394. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  395. package/lib/packlets/record-jar/index.browser.js +1 -5
  396. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  397. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  398. package/lib/packlets/record-jar/index.js.map +1 -0
  399. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  400. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  401. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  402. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  403. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  404. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  405. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  406. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  407. package/lib/packlets/safer-fetch/addressClassification.d.ts +144 -0
  408. package/lib/packlets/safer-fetch/addressClassification.d.ts.map +1 -0
  409. package/lib/packlets/safer-fetch/addressClassification.js +441 -0
  410. package/lib/packlets/safer-fetch/addressClassification.js.map +1 -0
  411. package/lib/packlets/safer-fetch/addressPolicy.d.ts +113 -0
  412. package/lib/packlets/safer-fetch/addressPolicy.d.ts.map +1 -0
  413. package/lib/packlets/safer-fetch/addressPolicy.js +123 -0
  414. package/lib/packlets/safer-fetch/addressPolicy.js.map +1 -0
  415. package/lib/packlets/safer-fetch/contentType.d.ts +51 -0
  416. package/lib/packlets/safer-fetch/contentType.d.ts.map +1 -0
  417. package/lib/packlets/safer-fetch/contentType.js +127 -0
  418. package/lib/packlets/safer-fetch/contentType.js.map +1 -0
  419. package/lib/packlets/safer-fetch/deadline.d.ts +138 -0
  420. package/lib/packlets/safer-fetch/deadline.d.ts.map +1 -0
  421. package/lib/packlets/safer-fetch/deadline.js +258 -0
  422. package/lib/packlets/safer-fetch/deadline.js.map +1 -0
  423. package/lib/packlets/safer-fetch/defaults.d.ts +108 -0
  424. package/lib/packlets/safer-fetch/defaults.d.ts.map +1 -0
  425. package/lib/packlets/safer-fetch/defaults.js +134 -0
  426. package/lib/packlets/safer-fetch/defaults.js.map +1 -0
  427. package/lib/packlets/safer-fetch/failureReason.d.ts +148 -0
  428. package/lib/packlets/safer-fetch/failureReason.d.ts.map +1 -0
  429. package/lib/packlets/safer-fetch/failureReason.js +22 -0
  430. package/lib/packlets/safer-fetch/failureReason.js.map +1 -0
  431. package/lib/packlets/safer-fetch/guards.d.ts +62 -0
  432. package/lib/packlets/safer-fetch/guards.d.ts.map +1 -0
  433. package/lib/packlets/safer-fetch/guards.js +153 -0
  434. package/lib/packlets/safer-fetch/guards.js.map +1 -0
  435. package/lib/packlets/safer-fetch/index.browser.d.ts +33 -0
  436. package/lib/packlets/safer-fetch/index.browser.d.ts.map +1 -0
  437. package/lib/packlets/safer-fetch/index.browser.js +82 -0
  438. package/lib/packlets/safer-fetch/index.browser.js.map +1 -0
  439. package/lib/packlets/safer-fetch/index.d.ts +27 -0
  440. package/lib/packlets/safer-fetch/index.d.ts.map +1 -0
  441. package/lib/packlets/safer-fetch/index.js +78 -0
  442. package/lib/packlets/safer-fetch/index.js.map +1 -0
  443. package/lib/packlets/safer-fetch/model.d.ts +373 -0
  444. package/lib/packlets/safer-fetch/model.d.ts.map +1 -0
  445. package/lib/packlets/safer-fetch/model.js +22 -0
  446. package/lib/packlets/safer-fetch/model.js.map +1 -0
  447. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts +129 -0
  448. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts.map +1 -0
  449. package/lib/packlets/safer-fetch/nodeAddressGuard.js +196 -0
  450. package/lib/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  451. package/lib/packlets/safer-fetch/redirect.d.ts +62 -0
  452. package/lib/packlets/safer-fetch/redirect.d.ts.map +1 -0
  453. package/lib/packlets/safer-fetch/redirect.js +98 -0
  454. package/lib/packlets/safer-fetch/redirect.js.map +1 -0
  455. package/lib/packlets/safer-fetch/retry.d.ts +162 -0
  456. package/lib/packlets/safer-fetch/retry.d.ts.map +1 -0
  457. package/lib/packlets/safer-fetch/retry.js +197 -0
  458. package/lib/packlets/safer-fetch/retry.js.map +1 -0
  459. package/lib/packlets/safer-fetch/saferFetch.d.ts +108 -0
  460. package/lib/packlets/safer-fetch/saferFetch.d.ts.map +1 -0
  461. package/lib/packlets/safer-fetch/saferFetch.js +760 -0
  462. package/lib/packlets/safer-fetch/saferFetch.js.map +1 -0
  463. package/lib/packlets/safer-fetch/transport.d.ts +18 -0
  464. package/lib/packlets/safer-fetch/transport.d.ts.map +1 -0
  465. package/lib/packlets/safer-fetch/transport.js +53 -0
  466. package/lib/packlets/safer-fetch/transport.js.map +1 -0
  467. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  468. package/lib/packlets/yaml/converters.js.map +1 -0
  469. package/lib/packlets/yaml/index.d.ts +1 -0
  470. package/lib/packlets/yaml/index.d.ts.map +1 -0
  471. package/lib/packlets/yaml/index.js +1 -0
  472. package/lib/packlets/yaml/index.js.map +1 -0
  473. package/lib/packlets/yaml/serializers.d.ts +45 -0
  474. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  475. package/lib/packlets/yaml/serializers.js +84 -0
  476. package/lib/packlets/yaml/serializers.js.map +1 -0
  477. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  478. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  479. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +84 -8
  480. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  481. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  482. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  483. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts +26 -1
  484. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  485. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js +17 -1
  486. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  487. package/package.json +30 -15
  488. package/lib/packlets/ai-assist/apiClient.d.ts +0 -60
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seedDerivedKeyPair.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/seedDerivedKeyPair.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\nimport { captureAsyncResult, fail, Result } from '@fgv/ts-utils';\nimport { SeedDerivableAlgorithm } from './model';\n\n/**\n * Per-algorithm parameters for the shared seed→keypair derivation. The two\n * supported algorithms differ only in the OID embedded in the PKCS#8 envelope,\n * the WebCrypto algorithm name, the JWK curve name, and the key usages — the\n * envelope structure and 32-byte seed handling are identical.\n */\ninterface ISeedAlgorithmParams {\n /**\n * The RFC 8410 §7 DER prefix for a PKCS#8 `OneAsymmetricKey` wrapping a bare\n * 32-byte seed. Decodes as:\n *\n * ```text\n * 30 2e SEQUENCE (46 bytes)\n * 02 01 00 INTEGER version 0 (v1)\n * 30 05 SEQUENCE AlgorithmIdentifier (5 bytes)\n * 06 03 2b65XX OID 1.3.101.XXX\n * 04 22 OCTET STRING privateKey (34 bytes)\n * 04 20 OCTET STRING CurvePrivateKey (32 bytes)\n * ```\n *\n * The 32-byte seed follows immediately (total 48 bytes). Ed25519 uses OID\n * 1.3.101.112 (`...2b 65 70`); X25519 uses 1.3.101.110 (`...2b 65 6e`) — the\n * two prefixes differ only in that final OID byte.\n */\n readonly pkcs8Prefix: ReadonlyArray<number>;\n /** WebCrypto algorithm name (`importKey`'s `algorithm.name`). */\n readonly webCryptoName: 'Ed25519' | 'X25519';\n /** JWK curve name for the reconstructed public key. */\n readonly jwkCrv: 'Ed25519' | 'X25519';\n /** Usages for the imported private key. */\n readonly privateUsages: ReadonlyArray<KeyUsage>;\n /** Usages for the reconstructed public key (empty for X25519). */\n readonly publicUsages: ReadonlyArray<KeyUsage>;\n}\n\n/**\n * An Ed25519 or X25519 private key *is* its 32-byte seed (RFC 8032 §5.1.5 /\n * RFC 7748 §5), and the public key is a deterministic function of that seed, so\n * wrapping the seed in the PKCS#8 envelope and importing it via WebCrypto\n * recovers the exact keypair on every runtime.\n */\nconst _SEED_ALGORITHMS: Readonly<Record<SeedDerivableAlgorithm, ISeedAlgorithmParams>> = {\n ed25519: {\n pkcs8Prefix: [\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20\n ],\n webCryptoName: 'Ed25519',\n jwkCrv: 'Ed25519',\n privateUsages: ['sign'],\n publicUsages: ['verify']\n },\n x25519: {\n pkcs8Prefix: [\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20\n ],\n webCryptoName: 'X25519',\n jwkCrv: 'X25519',\n privateUsages: ['deriveBits'],\n publicUsages: []\n }\n};\n\n/**\n * Required length, in bytes, of an Ed25519 / X25519 seed (RFC 8032 §5.1.5 /\n * RFC 7748 §5).\n */\nconst _SEED_LENGTH: number = 32;\n\n/**\n * Derives an asymmetric keypair *deterministically* from a fixed secret seed\n * using `globalThis.crypto.subtle`, shared by the Node and browser\n * {@link CryptoUtils.ICryptoProvider} implementations (both speak the same\n * WebCrypto API). See\n * {@link CryptoUtils.ICryptoProvider.importKeyPairFromSeed | importKeyPairFromSeed}\n * for the public contract.\n *\n * For each supported algorithm: wraps the 32-byte seed in the RFC 8410 PKCS#8\n * envelope, then runs a transient-extractable-then-derive dance so the public\n * key is recoverable even when the caller requests a non-extractable private key:\n *\n * 1. Import the PKCS#8 as a *transient* extractable private key.\n * 2. Export it to JWK to read the deterministic public coordinate `x`.\n * 3. Import `{ kty: 'OKP', crv, x }` as the returned public key.\n * 4. For the returned private key: reuse the transient key when `extractable`\n * is `true`; otherwise re-import the same PKCS#8 as a non-extractable key.\n * The transient extractable key is never returned when `extractable` is\n * `false`, so seed material cannot escape through it.\n *\n * The two algorithms differ only in the OID/name/curve/usages (see\n * {@link ISeedAlgorithmParams}); `'x25519'` yields the DH key-agreement keypair\n * (private `'deriveBits'`, public no-usage) that {@link CryptoUtils.HpkeProvider}\n * consumes as its recipient key.\n *\n * The seed bytes are copied into a freshly allocated PKCS#8 buffer, so the\n * `BufferSource` handed to WebCrypto is always backed by a plain `ArrayBuffer`\n * (side-stepping the Node-20 `SharedArrayBuffer`-view rejection) and the\n * caller's `seed` is never mutated.\n *\n * @param algorithm - The seed-derivable algorithm (`'ed25519'` or `'x25519'`).\n * Any other value fails loudly rather than being mis-handled.\n * @param seed - The 32-byte secret seed. Any other length fails loudly, before\n * any WebCrypto call.\n * @param extractable - Whether the returned private key may be exported.\n * @returns `Success` with the derived `CryptoKeyPair`, or `Failure` with error context.\n * @public\n */\nexport async function deriveKeyPairFromSeed(\n algorithm: SeedDerivableAlgorithm,\n seed: Uint8Array,\n extractable: boolean\n): Promise<Result<CryptoKeyPair>> {\n const params = _SEED_ALGORITHMS[algorithm];\n if (params === undefined) {\n return fail(\n `importKeyPairFromSeed: unsupported seed-derivable algorithm '${algorithm}' (supported: 'ed25519', 'x25519')`\n );\n }\n if (seed.length !== _SEED_LENGTH) {\n return fail(\n `importKeyPairFromSeed: ${algorithm} seed must be exactly ${_SEED_LENGTH} bytes, got ${seed.length}`\n );\n }\n\n // Back the PKCS#8 by a fresh, non-shared ArrayBuffer so the BufferSource handed\n // to WebCrypto is a `Uint8Array<ArrayBuffer>` — Node 20+ rejects a shared-buffer\n // view, and TypeScript's `BufferSource` excludes the `SharedArrayBuffer` branch.\n const pkcs8: Uint8Array<ArrayBuffer> = new Uint8Array(\n new ArrayBuffer(params.pkcs8Prefix.length + _SEED_LENGTH)\n );\n pkcs8.set(params.pkcs8Prefix, 0);\n pkcs8.set(seed, params.pkcs8Prefix.length);\n\n const algo = { name: params.webCryptoName };\n const privateUsages = [...params.privateUsages];\n\n return (\n await captureAsyncResult<CryptoKeyPair>(async () => {\n const subtle = globalThis.crypto.subtle;\n // Transient extractable private key — only used to read the deterministic\n // public coordinate; dropped (never returned/logged) when the caller\n // asked for a non-extractable private key.\n const transientPrivateKey = await subtle.importKey('pkcs8', pkcs8, algo, true, privateUsages);\n const jwk = await subtle.exportKey('jwk', transientPrivateKey);\n const publicKey = await subtle.importKey(\n 'jwk',\n { kty: 'OKP', crv: params.jwkCrv, x: jwk.x },\n algo,\n true,\n [...params.publicUsages]\n );\n const privateKey = extractable\n ? transientPrivateKey\n : await subtle.importKey('pkcs8', pkcs8, algo, false, privateUsages);\n return { publicKey, privateKey };\n })\n ).withErrorFormat((e) => `importKeyPairFromSeed: failed to derive ${algorithm} keypair from seed: ${e}`);\n}\n"]}
@@ -0,0 +1,151 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { ICryptoProvider, KeyPairAlgorithm, MultibaseSpkiPublicKey } from './model';
3
+ /**
4
+ * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).
5
+ *
6
+ * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`
7
+ * padding is stripped. This is the bare primitive with no multibase prefix; use
8
+ * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.
9
+ *
10
+ * @param data - The binary data to encode.
11
+ * @returns The base64url-no-pad string.
12
+ * @public
13
+ */
14
+ export declare function base64UrlNoPadEncode(data: Uint8Array): string;
15
+ /**
16
+ * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.
17
+ *
18
+ * This is the bare primitive with no multibase prefix; use
19
+ * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.
20
+ *
21
+ * @param encoded - The base64url-no-pad body to decode.
22
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
23
+ * @public
24
+ */
25
+ export declare function base64UrlNoPadDecode(encoded: string): Result<Uint8Array>;
26
+ /**
27
+ * Encodes a `Uint8Array` as a lowercase hexadecimal string with no `0x` prefix.
28
+ *
29
+ * Each byte becomes exactly two lowercase hex characters (zero-padded), so an
30
+ * `n`-byte input yields a `2n`-character string. An empty input yields the empty
31
+ * string. This is the inverse of {@link CryptoUtils.hexDecode}.
32
+ *
33
+ * @param data - The binary data to encode.
34
+ * @returns The lowercase, unprefixed hex string.
35
+ * @public
36
+ */
37
+ export declare function hexEncode(data: Uint8Array): string;
38
+ /**
39
+ * Decodes a hexadecimal string (no `0x` prefix) back to a `Uint8Array`.
40
+ *
41
+ * Liberal in what it accepts: both lowercase and uppercase hex digits are
42
+ * allowed (whereas {@link CryptoUtils.hexEncode} always emits lowercase). The
43
+ * input must have even length and contain only hex digits (`0-9`, `a-f`, `A-F`);
44
+ * an empty string decodes to an empty `Uint8Array`. Odd length or any non-hex
45
+ * character fails with error context.
46
+ *
47
+ * @param encoded - The hex string to decode.
48
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
49
+ * @public
50
+ */
51
+ export declare function hexDecode(encoded: string): Result<Uint8Array>;
52
+ /**
53
+ * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the
54
+ * multibase `'m'` prefix followed by a non-empty base64url-no-pad body
55
+ * (`A-Z`, `a-z`, `0-9`, `-`, `_`).
56
+ *
57
+ * This is a shape prefilter, not full validation: it does not decode the DER
58
+ * SPKI or verify the key material or algorithm (that happens in
59
+ * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard
60
+ * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this
61
+ * pattern **and** additionally rejects a body whose length is an impossible
62
+ * base64 remainder. Exposed for callers that need the pattern directly (e.g. a
63
+ * JSON-schema `pattern` field); prefer the guard/converter for validation.
64
+ *
65
+ * @public
66
+ */
67
+ export declare const MultibaseSpkiPublicKeyRegExp: RegExp;
68
+ /**
69
+ * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching
70
+ * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a
71
+ * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad
72
+ * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a
73
+ * structural *shape* check, not full validation — it does not decode the DER SPKI
74
+ * or verify the key material/algorithm (a malformed-but-well-shaped string fails
75
+ * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).
76
+ *
77
+ * @param value - The value to test.
78
+ * @returns `true` if `value` is a well-formed multibase SPKI public key string.
79
+ * @public
80
+ */
81
+ export declare function isValidMultibaseSpkiPublicKey(value: unknown): value is MultibaseSpkiPublicKey;
82
+ /**
83
+ * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.
84
+ *
85
+ * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url
86
+ * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,
87
+ * and trailing `=` padding is stripped.
88
+ *
89
+ * @param data - The binary data to encode.
90
+ * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).
91
+ * @public
92
+ */
93
+ export declare function multibaseBase64UrlEncode(data: Uint8Array): string;
94
+ /**
95
+ * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.
96
+ *
97
+ * Validates that the first character is `'m'` (the multibase prefix for
98
+ * RFC 4648 base64url without padding), then decodes the remaining body.
99
+ *
100
+ * @param encoded - A multibase-prefixed base64url string.
101
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
102
+ * @public
103
+ */
104
+ export declare function multibaseBase64UrlDecode(encoded: string): Result<Uint8Array>;
105
+ /**
106
+ * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.
107
+ *
108
+ * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure
109
+ * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is
110
+ * algorithm-agnostic and suitable for storage and transmission.
111
+ *
112
+ * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.
113
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.
114
+ * @returns `Success` with the multibase SPKI string, or `Failure` with error context.
115
+ * @public
116
+ */
117
+ export declare function exportPublicKeyAsMultibaseSpki(key: CryptoKey, provider: ICryptoProvider): Promise<Result<MultibaseSpkiPublicKey>>;
118
+ /**
119
+ * Imports a public key from a multibase base64url-encoded SPKI blob.
120
+ *
121
+ * Decodes the multibase prefix, decodes the base64url body, then uses
122
+ * the provider to import the key with the algorithm parameters from
123
+ * {@link CryptoUtils.keyPairAlgorithmParams}.
124
+ *
125
+ * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),
126
+ * so callers holding an unbranded value read from storage or the wire can import
127
+ * it directly; a malformed value fails with error context rather than throwing.
128
+ *
129
+ * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.
130
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.
131
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.
132
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
133
+ * @public
134
+ */
135
+ export declare function importPublicKeyFromMultibaseSpki(encoded: string, algorithm: KeyPairAlgorithm, provider: ICryptoProvider): Promise<Result<CryptoKey>>;
136
+ /**
137
+ * Strips the fixed DER prefix from an X25519 SubjectPublicKeyInfo blob, returning the raw
138
+ * 32-byte public key.
139
+ *
140
+ * An X25519 SPKI is always exactly 44 bytes: a fixed 12-byte prefix (SEQUENCE / AlgorithmIdentifier
141
+ * with OID 1.3.101.110 / BIT STRING) followed by the 32-byte raw key. Use this to convert a
142
+ * SPKI-held recipient public key into the raw form accepted by {@link HpkeProvider.openBase}'s
143
+ * `recipientPublicKey` parameter.
144
+ *
145
+ * @param spki - The DER-encoded X25519 SubjectPublicKeyInfo bytes.
146
+ * @returns `Success` with the raw 32-byte public key, or `Failure` if `spki` is not a
147
+ * well-formed 44-byte X25519 SPKI blob.
148
+ * @public
149
+ */
150
+ export declare function spkiToRawX25519(spki: Uint8Array): Result<Uint8Array>;
151
+ //# sourceMappingURL=spkiHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spkiHelpers.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/spkiHelpers.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYpF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAe7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAyBxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAMlD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAY7D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAA4B,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAM7F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAe5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,8BAA8B,CAClD,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAQzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAQ5B;AASD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAUpE"}
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.MultibaseSpkiPublicKeyRegExp = void 0;
23
+ exports.base64UrlNoPadEncode = base64UrlNoPadEncode;
24
+ exports.base64UrlNoPadDecode = base64UrlNoPadDecode;
25
+ exports.hexEncode = hexEncode;
26
+ exports.hexDecode = hexDecode;
27
+ exports.isValidMultibaseSpkiPublicKey = isValidMultibaseSpkiPublicKey;
28
+ exports.multibaseBase64UrlEncode = multibaseBase64UrlEncode;
29
+ exports.multibaseBase64UrlDecode = multibaseBase64UrlDecode;
30
+ exports.exportPublicKeyAsMultibaseSpki = exportPublicKeyAsMultibaseSpki;
31
+ exports.importPublicKeyFromMultibaseSpki = importPublicKeyFromMultibaseSpki;
32
+ exports.spkiToRawX25519 = spkiToRawX25519;
33
+ const ts_utils_1 = require("@fgv/ts-utils");
34
+ /**
35
+ * Shared shape check for a base64url (no-padding) body: only base64url alphabet
36
+ * characters (`A-Z`, `a-z`, `0-9`, `-`, `_`) and a length that is never `% 4 === 1`
37
+ * (an impossible base64 remainder). Factored so the decoder and the
38
+ * {@link isValidMultibaseSpkiPublicKey} guard agree on exactly one rule.
39
+ */
40
+ function isBase64UrlNoPadBody(body) {
41
+ return /^[A-Za-z0-9_-]*$/.test(body) && body.length % 4 !== 1;
42
+ }
43
+ /**
44
+ * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).
45
+ *
46
+ * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`
47
+ * padding is stripped. This is the bare primitive with no multibase prefix; use
48
+ * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.
49
+ *
50
+ * @param data - The binary data to encode.
51
+ * @returns The base64url-no-pad string.
52
+ * @public
53
+ */
54
+ function base64UrlNoPadEncode(data) {
55
+ let base64;
56
+ if (typeof Buffer !== 'undefined') {
57
+ base64 = Buffer.from(data).toString('base64');
58
+ /* c8 ignore start - browser-only: btoa path not available in Node tests */
59
+ }
60
+ else {
61
+ let binary = '';
62
+ for (let i = 0; i < data.length; i++) {
63
+ binary += String.fromCharCode(data[i]);
64
+ }
65
+ base64 = btoa(binary);
66
+ }
67
+ /* c8 ignore stop */
68
+ // Convert to base64url: + → -, / → _, strip = padding
69
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
70
+ }
71
+ /**
72
+ * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.
73
+ *
74
+ * This is the bare primitive with no multibase prefix; use
75
+ * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.
76
+ *
77
+ * @param encoded - The base64url-no-pad body to decode.
78
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
79
+ * @public
80
+ */
81
+ function base64UrlNoPadDecode(encoded) {
82
+ if (!isBase64UrlNoPadBody(encoded)) {
83
+ return (0, ts_utils_1.fail)(`base64UrlNoPadDecode: malformed base64url body`);
84
+ }
85
+ // Convert base64url back to standard base64 and restore padding
86
+ const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
87
+ const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);
88
+ try {
89
+ let bytes;
90
+ if (typeof Buffer !== 'undefined') {
91
+ bytes = new Uint8Array(Buffer.from(padded, 'base64'));
92
+ /* c8 ignore start - browser-only: atob path not available in Node tests */
93
+ }
94
+ else {
95
+ const binary = atob(padded);
96
+ bytes = new Uint8Array(binary.length);
97
+ for (let i = 0; i < binary.length; i++) {
98
+ bytes[i] = binary.charCodeAt(i);
99
+ }
100
+ }
101
+ /* c8 ignore stop */
102
+ return (0, ts_utils_1.succeed)(bytes);
103
+ /* c8 ignore next 3 - defensive: shape check above prevents invalid chars from reaching here */
104
+ }
105
+ catch (_a) {
106
+ return (0, ts_utils_1.fail)(`base64UrlNoPadDecode: malformed base64url body`);
107
+ }
108
+ }
109
+ /**
110
+ * Encodes a `Uint8Array` as a lowercase hexadecimal string with no `0x` prefix.
111
+ *
112
+ * Each byte becomes exactly two lowercase hex characters (zero-padded), so an
113
+ * `n`-byte input yields a `2n`-character string. An empty input yields the empty
114
+ * string. This is the inverse of {@link CryptoUtils.hexDecode}.
115
+ *
116
+ * @param data - The binary data to encode.
117
+ * @returns The lowercase, unprefixed hex string.
118
+ * @public
119
+ */
120
+ function hexEncode(data) {
121
+ let hex = '';
122
+ for (let i = 0; i < data.length; i++) {
123
+ hex += data[i].toString(16).padStart(2, '0');
124
+ }
125
+ return hex;
126
+ }
127
+ /**
128
+ * Decodes a hexadecimal string (no `0x` prefix) back to a `Uint8Array`.
129
+ *
130
+ * Liberal in what it accepts: both lowercase and uppercase hex digits are
131
+ * allowed (whereas {@link CryptoUtils.hexEncode} always emits lowercase). The
132
+ * input must have even length and contain only hex digits (`0-9`, `a-f`, `A-F`);
133
+ * an empty string decodes to an empty `Uint8Array`. Odd length or any non-hex
134
+ * character fails with error context.
135
+ *
136
+ * @param encoded - The hex string to decode.
137
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
138
+ * @public
139
+ */
140
+ function hexDecode(encoded) {
141
+ if (encoded.length % 2 !== 0) {
142
+ return (0, ts_utils_1.fail)(`hexDecode: odd-length hex string (length ${encoded.length})`);
143
+ }
144
+ if (!/^[0-9a-fA-F]*$/.test(encoded)) {
145
+ return (0, ts_utils_1.fail)(`hexDecode: string contains non-hex characters`);
146
+ }
147
+ const bytes = new Uint8Array(encoded.length / 2);
148
+ for (let i = 0; i < bytes.length; i++) {
149
+ bytes[i] = parseInt(encoded.slice(i * 2, i * 2 + 2), 16);
150
+ }
151
+ return (0, ts_utils_1.succeed)(bytes);
152
+ }
153
+ /**
154
+ * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the
155
+ * multibase `'m'` prefix followed by a non-empty base64url-no-pad body
156
+ * (`A-Z`, `a-z`, `0-9`, `-`, `_`).
157
+ *
158
+ * This is a shape prefilter, not full validation: it does not decode the DER
159
+ * SPKI or verify the key material or algorithm (that happens in
160
+ * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard
161
+ * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this
162
+ * pattern **and** additionally rejects a body whose length is an impossible
163
+ * base64 remainder. Exposed for callers that need the pattern directly (e.g. a
164
+ * JSON-schema `pattern` field); prefer the guard/converter for validation.
165
+ *
166
+ * @public
167
+ */
168
+ exports.MultibaseSpkiPublicKeyRegExp = /^m[A-Za-z0-9_-]+$/;
169
+ /**
170
+ * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching
171
+ * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a
172
+ * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad
173
+ * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a
174
+ * structural *shape* check, not full validation — it does not decode the DER SPKI
175
+ * or verify the key material/algorithm (a malformed-but-well-shaped string fails
176
+ * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).
177
+ *
178
+ * @param value - The value to test.
179
+ * @returns `true` if `value` is a well-formed multibase SPKI public key string.
180
+ * @public
181
+ */
182
+ function isValidMultibaseSpkiPublicKey(value) {
183
+ return (typeof value === 'string' &&
184
+ exports.MultibaseSpkiPublicKeyRegExp.test(value) &&
185
+ isBase64UrlNoPadBody(value.slice(1)));
186
+ }
187
+ /**
188
+ * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.
189
+ *
190
+ * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url
191
+ * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,
192
+ * and trailing `=` padding is stripped.
193
+ *
194
+ * @param data - The binary data to encode.
195
+ * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).
196
+ * @public
197
+ */
198
+ function multibaseBase64UrlEncode(data) {
199
+ return 'm' + base64UrlNoPadEncode(data);
200
+ }
201
+ /**
202
+ * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.
203
+ *
204
+ * Validates that the first character is `'m'` (the multibase prefix for
205
+ * RFC 4648 base64url without padding), then decodes the remaining body.
206
+ *
207
+ * @param encoded - A multibase-prefixed base64url string.
208
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
209
+ * @public
210
+ */
211
+ function multibaseBase64UrlDecode(encoded) {
212
+ var _a;
213
+ if (!encoded.startsWith('m')) {
214
+ return (0, ts_utils_1.fail)(`multibaseBase64UrlDecode: invalid multibase prefix '${(_a = encoded[0]) !== null && _a !== void 0 ? _a : '(empty)'}' — expected 'm' (base64url)`);
215
+ }
216
+ // Intentionally pin the exact original message (the delegate has a single failure
217
+ // mode) to keep this established public function byte-for-byte behavior-preserving
218
+ // after the extract-and-delegate refactor — do not "fix" this into composing the
219
+ // delegate's message without updating the delegation-equivalence tests.
220
+ return base64UrlNoPadDecode(encoded.slice(1)).withErrorFormat(() => `multibaseBase64UrlDecode: malformed base64url body`);
221
+ }
222
+ /**
223
+ * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.
224
+ *
225
+ * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure
226
+ * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is
227
+ * algorithm-agnostic and suitable for storage and transmission.
228
+ *
229
+ * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.
230
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.
231
+ * @returns `Success` with the multibase SPKI string, or `Failure` with error context.
232
+ * @public
233
+ */
234
+ async function exportPublicKeyAsMultibaseSpki(key, provider) {
235
+ return (await provider.exportPublicKeySpki(key))
236
+ .withErrorFormat((e) => `exportPublicKeyAsMultibaseSpki: ${e}`)
237
+ .onSuccess((buf) =>
238
+ // The output is a freshly-built valid multibase SPKI string (`'m'` prefix +
239
+ // base64url-no-pad body), so brand it at the construction site — no re-validation needed.
240
+ (0, ts_utils_1.succeed)(multibaseBase64UrlEncode(buf)));
241
+ }
242
+ /**
243
+ * Imports a public key from a multibase base64url-encoded SPKI blob.
244
+ *
245
+ * Decodes the multibase prefix, decodes the base64url body, then uses
246
+ * the provider to import the key with the algorithm parameters from
247
+ * {@link CryptoUtils.keyPairAlgorithmParams}.
248
+ *
249
+ * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),
250
+ * so callers holding an unbranded value read from storage or the wire can import
251
+ * it directly; a malformed value fails with error context rather than throwing.
252
+ *
253
+ * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.
254
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.
255
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.
256
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
257
+ * @public
258
+ */
259
+ async function importPublicKeyFromMultibaseSpki(encoded, algorithm, provider) {
260
+ const decodeResult = multibaseBase64UrlDecode(encoded);
261
+ if (decodeResult.isFailure()) {
262
+ return (0, ts_utils_1.fail)(`importPublicKeyFromMultibaseSpki: ${decodeResult.message}`);
263
+ }
264
+ return (await provider.importPublicKeySpki(decodeResult.value, algorithm)).withErrorFormat((e) => `importPublicKeyFromMultibaseSpki: ${e}`);
265
+ }
266
+ // DER prefix for an X25519 SubjectPublicKeyInfo: SEQUENCE { SEQUENCE { OID id-X25519 }, BIT STRING }.
267
+ // SEQUENCE(42) / SEQUENCE(5) / OID 1.3.101.110 (id-X25519) / BIT STRING(33, 0 unused bits).
268
+ const _X25519_SPKI_PREFIX = [
269
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00
270
+ ];
271
+ const _X25519_SPKI_LENGTH = _X25519_SPKI_PREFIX.length + 32;
272
+ /**
273
+ * Strips the fixed DER prefix from an X25519 SubjectPublicKeyInfo blob, returning the raw
274
+ * 32-byte public key.
275
+ *
276
+ * An X25519 SPKI is always exactly 44 bytes: a fixed 12-byte prefix (SEQUENCE / AlgorithmIdentifier
277
+ * with OID 1.3.101.110 / BIT STRING) followed by the 32-byte raw key. Use this to convert a
278
+ * SPKI-held recipient public key into the raw form accepted by {@link HpkeProvider.openBase}'s
279
+ * `recipientPublicKey` parameter.
280
+ *
281
+ * @param spki - The DER-encoded X25519 SubjectPublicKeyInfo bytes.
282
+ * @returns `Success` with the raw 32-byte public key, or `Failure` if `spki` is not a
283
+ * well-formed 44-byte X25519 SPKI blob.
284
+ * @public
285
+ */
286
+ function spkiToRawX25519(spki) {
287
+ if (spki.length !== _X25519_SPKI_LENGTH) {
288
+ return (0, ts_utils_1.fail)(`spkiToRawX25519: expected ${_X25519_SPKI_LENGTH} bytes, got ${spki.length}`);
289
+ }
290
+ for (let i = 0; i < _X25519_SPKI_PREFIX.length; i++) {
291
+ if (spki[i] !== _X25519_SPKI_PREFIX[i]) {
292
+ return (0, ts_utils_1.fail)(`spkiToRawX25519: byte ${i} does not match the expected X25519 SPKI prefix`);
293
+ }
294
+ }
295
+ return (0, ts_utils_1.succeed)(spki.slice(_X25519_SPKI_PREFIX.length));
296
+ }
297
+ //# sourceMappingURL=spkiHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spkiHelpers.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/spkiHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport { ICryptoProvider, KeyPairAlgorithm, MultibaseSpkiPublicKey } from './model';\n\n/**\n * Shared shape check for a base64url (no-padding) body: only base64url alphabet\n * characters (`A-Z`, `a-z`, `0-9`, `-`, `_`) and a length that is never `% 4 === 1`\n * (an impossible base64 remainder). Factored so the decoder and the\n * {@link isValidMultibaseSpkiPublicKey} guard agree on exactly one rule.\n */\nfunction isBase64UrlNoPadBody(body: string): boolean {\n return /^[A-Za-z0-9_-]*$/.test(body) && body.length % 4 !== 1;\n}\n\n/**\n * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).\n *\n * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`\n * padding is stripped. This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.\n *\n * @param data - The binary data to encode.\n * @returns The base64url-no-pad string.\n * @public\n */\nexport function base64UrlNoPadEncode(data: Uint8Array): string {\n let base64: string;\n if (typeof Buffer !== 'undefined') {\n base64 = Buffer.from(data).toString('base64');\n /* c8 ignore start - browser-only: btoa path not available in Node tests */\n } else {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n base64 = btoa(binary);\n }\n /* c8 ignore stop */\n // Convert to base64url: + → -, / → _, strip = padding\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.\n *\n * This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.\n *\n * @param encoded - The base64url-no-pad body to decode.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function base64UrlNoPadDecode(encoded: string): Result<Uint8Array> {\n if (!isBase64UrlNoPadBody(encoded)) {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n // Convert base64url back to standard base64 and restore padding\n const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n try {\n let bytes: Uint8Array;\n if (typeof Buffer !== 'undefined') {\n bytes = new Uint8Array(Buffer.from(padded, 'base64'));\n /* c8 ignore start - browser-only: atob path not available in Node tests */\n } else {\n const binary = atob(padded);\n bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n }\n /* c8 ignore stop */\n return succeed(bytes);\n /* c8 ignore next 3 - defensive: shape check above prevents invalid chars from reaching here */\n } catch {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n}\n\n/**\n * Encodes a `Uint8Array` as a lowercase hexadecimal string with no `0x` prefix.\n *\n * Each byte becomes exactly two lowercase hex characters (zero-padded), so an\n * `n`-byte input yields a `2n`-character string. An empty input yields the empty\n * string. This is the inverse of {@link CryptoUtils.hexDecode}.\n *\n * @param data - The binary data to encode.\n * @returns The lowercase, unprefixed hex string.\n * @public\n */\nexport function hexEncode(data: Uint8Array): string {\n let hex = '';\n for (let i = 0; i < data.length; i++) {\n hex += data[i].toString(16).padStart(2, '0');\n }\n return hex;\n}\n\n/**\n * Decodes a hexadecimal string (no `0x` prefix) back to a `Uint8Array`.\n *\n * Liberal in what it accepts: both lowercase and uppercase hex digits are\n * allowed (whereas {@link CryptoUtils.hexEncode} always emits lowercase). The\n * input must have even length and contain only hex digits (`0-9`, `a-f`, `A-F`);\n * an empty string decodes to an empty `Uint8Array`. Odd length or any non-hex\n * character fails with error context.\n *\n * @param encoded - The hex string to decode.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function hexDecode(encoded: string): Result<Uint8Array> {\n if (encoded.length % 2 !== 0) {\n return fail(`hexDecode: odd-length hex string (length ${encoded.length})`);\n }\n if (!/^[0-9a-fA-F]*$/.test(encoded)) {\n return fail(`hexDecode: string contains non-hex characters`);\n }\n const bytes = new Uint8Array(encoded.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(encoded.slice(i * 2, i * 2 + 2), 16);\n }\n return succeed(bytes);\n}\n\n/**\n * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the\n * multibase `'m'` prefix followed by a non-empty base64url-no-pad body\n * (`A-Z`, `a-z`, `0-9`, `-`, `_`).\n *\n * This is a shape prefilter, not full validation: it does not decode the DER\n * SPKI or verify the key material or algorithm (that happens in\n * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard\n * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this\n * pattern **and** additionally rejects a body whose length is an impossible\n * base64 remainder. Exposed for callers that need the pattern directly (e.g. a\n * JSON-schema `pattern` field); prefer the guard/converter for validation.\n *\n * @public\n */\nexport const MultibaseSpkiPublicKeyRegExp: RegExp = /^m[A-Za-z0-9_-]+$/;\n\n/**\n * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching\n * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a\n * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad\n * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a\n * structural *shape* check, not full validation — it does not decode the DER SPKI\n * or verify the key material/algorithm (a malformed-but-well-shaped string fails\n * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).\n *\n * @param value - The value to test.\n * @returns `true` if `value` is a well-formed multibase SPKI public key string.\n * @public\n */\nexport function isValidMultibaseSpkiPublicKey(value: unknown): value is MultibaseSpkiPublicKey {\n return (\n typeof value === 'string' &&\n MultibaseSpkiPublicKeyRegExp.test(value) &&\n isBase64UrlNoPadBody(value.slice(1))\n );\n}\n\n/**\n * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.\n *\n * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url\n * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,\n * and trailing `=` padding is stripped.\n *\n * @param data - The binary data to encode.\n * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).\n * @public\n */\nexport function multibaseBase64UrlEncode(data: Uint8Array): string {\n return 'm' + base64UrlNoPadEncode(data);\n}\n\n/**\n * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.\n *\n * Validates that the first character is `'m'` (the multibase prefix for\n * RFC 4648 base64url without padding), then decodes the remaining body.\n *\n * @param encoded - A multibase-prefixed base64url string.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function multibaseBase64UrlDecode(encoded: string): Result<Uint8Array> {\n if (!encoded.startsWith('m')) {\n return fail(\n `multibaseBase64UrlDecode: invalid multibase prefix '${\n encoded[0] ?? '(empty)'\n }' — expected 'm' (base64url)`\n );\n }\n // Intentionally pin the exact original message (the delegate has a single failure\n // mode) to keep this established public function byte-for-byte behavior-preserving\n // after the extract-and-delegate refactor — do not \"fix\" this into composing the\n // delegate's message without updating the delegation-equivalence tests.\n return base64UrlNoPadDecode(encoded.slice(1)).withErrorFormat(\n () => `multibaseBase64UrlDecode: malformed base64url body`\n );\n}\n\n/**\n * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.\n *\n * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure\n * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is\n * algorithm-agnostic and suitable for storage and transmission.\n *\n * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.\n * @returns `Success` with the multibase SPKI string, or `Failure` with error context.\n * @public\n */\nexport async function exportPublicKeyAsMultibaseSpki(\n key: CryptoKey,\n provider: ICryptoProvider\n): Promise<Result<MultibaseSpkiPublicKey>> {\n return (await provider.exportPublicKeySpki(key))\n .withErrorFormat((e) => `exportPublicKeyAsMultibaseSpki: ${e}`)\n .onSuccess((buf) =>\n // The output is a freshly-built valid multibase SPKI string (`'m'` prefix +\n // base64url-no-pad body), so brand it at the construction site — no re-validation needed.\n succeed(multibaseBase64UrlEncode(buf) as MultibaseSpkiPublicKey)\n );\n}\n\n/**\n * Imports a public key from a multibase base64url-encoded SPKI blob.\n *\n * Decodes the multibase prefix, decodes the base64url body, then uses\n * the provider to import the key with the algorithm parameters from\n * {@link CryptoUtils.keyPairAlgorithmParams}.\n *\n * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),\n * so callers holding an unbranded value read from storage or the wire can import\n * it directly; a malformed value fails with error context rather than throwing.\n *\n * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.\n * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.\n * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.\n * @public\n */\nexport async function importPublicKeyFromMultibaseSpki(\n encoded: string,\n algorithm: KeyPairAlgorithm,\n provider: ICryptoProvider\n): Promise<Result<CryptoKey>> {\n const decodeResult = multibaseBase64UrlDecode(encoded);\n if (decodeResult.isFailure()) {\n return fail(`importPublicKeyFromMultibaseSpki: ${decodeResult.message}`);\n }\n return (await provider.importPublicKeySpki(decodeResult.value, algorithm)).withErrorFormat(\n (e) => `importPublicKeyFromMultibaseSpki: ${e}`\n );\n}\n\n// DER prefix for an X25519 SubjectPublicKeyInfo: SEQUENCE { SEQUENCE { OID id-X25519 }, BIT STRING }.\n// SEQUENCE(42) / SEQUENCE(5) / OID 1.3.101.110 (id-X25519) / BIT STRING(33, 0 unused bits).\nconst _X25519_SPKI_PREFIX: ReadonlyArray<number> = [\n 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00\n];\nconst _X25519_SPKI_LENGTH: number = _X25519_SPKI_PREFIX.length + 32;\n\n/**\n * Strips the fixed DER prefix from an X25519 SubjectPublicKeyInfo blob, returning the raw\n * 32-byte public key.\n *\n * An X25519 SPKI is always exactly 44 bytes: a fixed 12-byte prefix (SEQUENCE / AlgorithmIdentifier\n * with OID 1.3.101.110 / BIT STRING) followed by the 32-byte raw key. Use this to convert a\n * SPKI-held recipient public key into the raw form accepted by {@link HpkeProvider.openBase}'s\n * `recipientPublicKey` parameter.\n *\n * @param spki - The DER-encoded X25519 SubjectPublicKeyInfo bytes.\n * @returns `Success` with the raw 32-byte public key, or `Failure` if `spki` is not a\n * well-formed 44-byte X25519 SPKI blob.\n * @public\n */\nexport function spkiToRawX25519(spki: Uint8Array): Result<Uint8Array> {\n if (spki.length !== _X25519_SPKI_LENGTH) {\n return fail(`spkiToRawX25519: expected ${_X25519_SPKI_LENGTH} bytes, got ${spki.length}`);\n }\n for (let i = 0; i < _X25519_SPKI_PREFIX.length; i++) {\n if (spki[i] !== _X25519_SPKI_PREFIX[i]) {\n return fail(`spkiToRawX25519: byte ${i} does not match the expected X25519 SPKI prefix`);\n }\n }\n return succeed(spki.slice(_X25519_SPKI_PREFIX.length));\n}\n"]}
@@ -1,5 +1,4 @@
1
1
  import { Result } from '@fgv/ts-utils';
2
- import { FileTree } from '@fgv/ts-json-base';
3
2
  import { CsvOptions } from './csvHelpers';
4
3
  /**
5
4
  * Reads a CSV file from a supplied path.
@@ -9,13 +8,4 @@ import { CsvOptions } from './csvHelpers';
9
8
  * @beta
10
9
  */
11
10
  export declare function readCsvFileSync(srcPath: string, options?: CsvOptions): Result<unknown>;
12
- /**
13
- * Reads a CSV file from a FileTree.
14
- * @param fileTree - The FileTree to read from.
15
- * @param filePath - Path of the file within the tree.
16
- * @param options - optional parameters to control the processing
17
- * @returns The parsed CSV data.
18
- * @beta
19
- */
20
- export declare function readCsvFromTree(fileTree: FileTree.FileTree, filePath: string, options?: CsvOptions): Result<unknown>;
21
11
  //# sourceMappingURL=csvFileHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csvFileHelpers.d.ts","sourceRoot":"","sources":["../../../src/packlets/csv/csvFileHelpers.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AAGtD,OAAO,EAAkB,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAOtF"}
@@ -55,7 +55,6 @@ var __importStar = (this && this.__importStar) || (function () {
55
55
  })();
56
56
  Object.defineProperty(exports, "__esModule", { value: true });
57
57
  exports.readCsvFileSync = readCsvFileSync;
58
- exports.readCsvFromTree = readCsvFromTree;
59
58
  const ts_utils_1 = require("@fgv/ts-utils");
60
59
  const fs = __importStar(require("fs"));
61
60
  const path = __importStar(require("path"));
@@ -75,18 +74,4 @@ function readCsvFileSync(srcPath, options) {
75
74
  return (0, csvHelpers_1.parseCsvString)(body, options);
76
75
  });
77
76
  }
78
- /**
79
- * Reads a CSV file from a FileTree.
80
- * @param fileTree - The FileTree to read from.
81
- * @param filePath - Path of the file within the tree.
82
- * @param options - optional parameters to control the processing
83
- * @returns The parsed CSV data.
84
- * @beta
85
- */
86
- function readCsvFromTree(fileTree, filePath, options) {
87
- return fileTree
88
- .getFile(filePath)
89
- .onSuccess((file) => file.getRawContents())
90
- .onSuccess((contents) => (0, csvHelpers_1.parseCsvString)(contents, options));
91
- }
92
77
  //# sourceMappingURL=csvFileHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csvFileHelpers.js","sourceRoot":"","sources":["../../../src/packlets/csv/csvFileHelpers.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcH,0CAOC;AAnBD,4CAAsD;AACtD,uCAAyB;AACzB,2CAA6B;AAC7B,6CAA0D;AAE1D;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,OAAe,EAAE,OAAoB;IACnE,OAAO,IAAA,wBAAa,EAAC,GAAG,EAAE;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;QACpB,OAAO,IAAA,2BAAc,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Result, captureResult } from '@fgv/ts-utils';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { parseCsvString, CsvOptions } from './csvHelpers';\n\n/**\n * Reads a CSV file from a supplied path.\n * @param srcPath - Source path from which the file is read.\n * @param options - optional parameters to control the processing\n * @returns The contents of the file.\n * @beta\n */\nexport function readCsvFileSync(srcPath: string, options?: CsvOptions): Result<unknown> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n return fs.readFileSync(fullPath, 'utf8').toString();\n }).onSuccess((body) => {\n return parseCsvString(body, options);\n });\n}\n\n"]}
@@ -1,4 +1,5 @@
1
1
  import { Result } from '@fgv/ts-utils';
2
+ import { FileTree } from '@fgv/ts-json-base';
2
3
  /**
3
4
  * Options for {@link Csv.readCsvFileSync | readCsvFileSync}
4
5
  * @beta
@@ -14,4 +15,13 @@ export interface CsvOptions {
14
15
  * @beta
15
16
  */
16
17
  export declare function parseCsvString(body: string, options?: CsvOptions): Result<unknown>;
18
+ /**
19
+ * Reads a CSV file from a FileTree.
20
+ * @param fileTree - The FileTree to read from.
21
+ * @param filePath - Path of the file within the tree.
22
+ * @param options - optional parameters to control the processing
23
+ * @returns The parsed CSV data.
24
+ * @beta
25
+ */
26
+ export declare function readCsvFromTree(fileTree: FileTree.FileTree, filePath: string, options?: CsvOptions): Result<unknown>;
17
27
  //# sourceMappingURL=csvHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csvHelpers.d.ts","sourceRoot":"","sources":["../../../src/packlets/csv/csvHelpers.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAYlF;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,UAAU,GACnB,MAAM,CAAC,OAAO,CAAC,CAKjB"}
@@ -22,6 +22,7 @@
22
22
  */
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.parseCsvString = parseCsvString;
25
+ exports.readCsvFromTree = readCsvFromTree;
25
26
  const ts_utils_1 = require("@fgv/ts-utils");
26
27
  const papaparse_1 = require("papaparse");
27
28
  /**
@@ -37,4 +38,18 @@ function parseCsvString(body, options) {
37
38
  return (0, papaparse_1.parse)(body, Object.assign({ transform: (s) => s.trim(), header: false, dynamicTyping: false, skipEmptyLines: 'greedy' }, options)).data.slice(1);
38
39
  });
39
40
  }
41
+ /**
42
+ * Reads a CSV file from a FileTree.
43
+ * @param fileTree - The FileTree to read from.
44
+ * @param filePath - Path of the file within the tree.
45
+ * @param options - optional parameters to control the processing
46
+ * @returns The parsed CSV data.
47
+ * @beta
48
+ */
49
+ function readCsvFromTree(fileTree, filePath, options) {
50
+ return fileTree
51
+ .getFile(filePath)
52
+ .onSuccess((file) => file.getRawContents())
53
+ .onSuccess((contents) => parseCsvString(contents, options));
54
+ }
40
55
  //# sourceMappingURL=csvHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csvHelpers.js","sourceRoot":"","sources":["../../../src/packlets/csv/csvHelpers.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAsBH,wCAYC;AAUD,0CASC;AAnDD,4CAAsD;AAEtD,yCAAkC;AAWlC;;;;;;GAMG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,OAAoB;IAC/D,OAAO,IAAA,wBAAa,EAAC,GAAG,EAAE;QACxB,OAAO,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;QAExB,OAAO,IAAA,iBAAK,EAAC,IAAI,kBACf,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAClC,MAAM,EAAE,KAAK,EACb,aAAa,EAAE,KAAK,EACpB,cAAc,EAAE,QAAQ,IACrB,OAAO,EACV,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,eAAe,CAC7B,QAA2B,EAC3B,QAAgB,EAChB,OAAoB;IAEpB,OAAO,QAAQ;SACZ,OAAO,CAAC,QAAQ,CAAC;SACjB,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;SAC1C,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAChE,CAAC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Result, captureResult } from '@fgv/ts-utils';\nimport { FileTree } from '@fgv/ts-json-base';\nimport { parse } from 'papaparse';\n\n/**\n * Options for {@link Csv.readCsvFileSync | readCsvFileSync}\n * @beta\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport interface CsvOptions {\n delimiter?: string;\n}\n\n/**\n * Parses CSV data from a string.\n * @param body - The CSV string to parse.\n * @param options - optional parameters to control the processing\n * @returns The parsed CSV data.\n * @beta\n */\nexport function parseCsvString(body: string, options?: CsvOptions): Result<unknown> {\n return captureResult(() => {\n options = options ?? {};\n\n return parse(body, {\n transform: (s: string) => s.trim(),\n header: false,\n dynamicTyping: false,\n skipEmptyLines: 'greedy',\n ...options\n }).data.slice(1);\n });\n}\n\n/**\n * Reads a CSV file from a FileTree.\n * @param fileTree - The FileTree to read from.\n * @param filePath - Path of the file within the tree.\n * @param options - optional parameters to control the processing\n * @returns The parsed CSV data.\n * @beta\n */\nexport function readCsvFromTree(\n fileTree: FileTree.FileTree,\n filePath: string,\n options?: CsvOptions\n): Result<unknown> {\n return fileTree\n .getFile(filePath)\n .onSuccess((file) => file.getRawContents())\n .onSuccess((contents) => parseCsvString(contents, options));\n}\n"]}