functionalscript 0.44.0 → 0.46.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 (571) hide show
  1. package/README.md +5 -3
  2. package/fjs/asn.1/module.f.mjs +8 -1
  3. package/fjs/asn.1/proof.f.d.mts +15 -0
  4. package/fjs/asn.1/proof.f.mjs +31 -3
  5. package/fjs/asserts/module.f.d.mts +14 -0
  6. package/fjs/asserts/module.f.mjs +20 -0
  7. package/fjs/asserts/proof.f.d.mts +3 -0
  8. package/fjs/asserts/proof.f.mjs +15 -1
  9. package/fjs/basen/base128/module.f.mjs +22 -5
  10. package/fjs/basen/base128/proof.f.d.mts +3 -1
  11. package/fjs/basen/base128/proof.f.mjs +3 -1
  12. package/fjs/basen/base64/module.f.mjs +7 -3
  13. package/fjs/basen/base64/proof.f.d.mts +3 -1
  14. package/fjs/basen/base64/proof.f.mjs +7 -4
  15. package/fjs/basen/cbase32/proof.f.d.mts +3 -1
  16. package/fjs/basen/cbase32/proof.f.mjs +3 -1
  17. package/fjs/bnf/data/module.f.d.mts +32 -6
  18. package/fjs/bnf/data/module.f.mjs +112 -7
  19. package/fjs/bnf/data/proof.f.d.mts +2 -0
  20. package/fjs/bnf/data/proof.f.mjs +74 -4
  21. package/fjs/bnf/data/types.d.ts +20 -2
  22. package/fjs/bnf/descent/module.f.d.mts +34 -5
  23. package/fjs/bnf/descent/module.f.mjs +176 -54
  24. package/fjs/bnf/descent/proof.f.d.mts +3 -0
  25. package/fjs/bnf/descent/proof.f.mjs +189 -27
  26. package/fjs/bnf/descent/types.d.ts +24 -18
  27. package/fjs/bnf/ll1/module.f.d.mts +74 -6
  28. package/fjs/bnf/ll1/module.f.mjs +297 -95
  29. package/fjs/bnf/ll1/proof.f.d.mts +17 -2
  30. package/fjs/bnf/ll1/proof.f.mjs +372 -137
  31. package/fjs/bnf/ll1/types.d.ts +25 -27
  32. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  33. package/fjs/bnf/matcher/module.f.mjs +81 -0
  34. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  35. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  36. package/fjs/bnf/matcher/types.d.ts +54 -0
  37. package/fjs/bnf/module.f.d.mts +15 -6
  38. package/fjs/bnf/module.f.mjs +52 -11
  39. package/fjs/bnf/proof.f.d.mts +2 -0
  40. package/fjs/bnf/proof.f.mjs +79 -3
  41. package/fjs/bnf/testlib.f.d.mts +31 -0
  42. package/fjs/bnf/testlib.f.mjs +80 -0
  43. package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
  44. package/fjs/bnf/token_symbol/module.f.mjs +7 -6
  45. package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
  46. package/fjs/bnf/token_symbol/types.d.ts +2 -2
  47. package/fjs/bnf/types.d.ts +10 -3
  48. package/fjs/cas/cli/module.f.d.mts +1 -1
  49. package/fjs/cas/cli/module.f.mjs +14 -20
  50. package/fjs/cas/cli/proof.f.d.mts +4 -4
  51. package/fjs/cas/cli/proof.f.mjs +47 -34
  52. package/fjs/cas/evo/module.f.d.mts +71 -31
  53. package/fjs/cas/evo/module.f.mjs +223 -138
  54. package/fjs/cas/evo/proof.f.d.mts +10 -1
  55. package/fjs/cas/evo/proof.f.mjs +311 -226
  56. package/fjs/cas/evo/types.d.ts +45 -9
  57. package/fjs/cas/module.f.d.mts +18 -32
  58. package/fjs/cas/module.f.mjs +164 -176
  59. package/fjs/cas/proof.f.d.mts +11 -8
  60. package/fjs/cas/proof.f.mjs +259 -147
  61. package/fjs/cas/types.d.ts +24 -10
  62. package/fjs/ci/common/module.f.d.mts +1 -1
  63. package/fjs/ci/common/module.f.mjs +1 -0
  64. package/fjs/ci/config/module.f.d.mts +3 -3
  65. package/fjs/ci/config/module.f.mjs +3 -3
  66. package/fjs/ci/module.f.d.mts +5 -5
  67. package/fjs/ci/module.f.mjs +8 -7
  68. package/fjs/ci/nix/module.f.d.mts +7 -5
  69. package/fjs/ci/nix/module.f.mjs +13 -12
  70. package/fjs/ci/nix/proof.f.d.mts +2 -0
  71. package/fjs/ci/nix/proof.f.mjs +4 -4
  72. package/fjs/ci/proof.f.d.mts +4 -2
  73. package/fjs/ci/proof.f.mjs +13 -8
  74. package/fjs/cli/module.f.d.mts +4 -6
  75. package/fjs/cli/module.f.mjs +4 -8
  76. package/fjs/cli/proof.f.d.mts +4 -2
  77. package/fjs/cli/proof.f.mjs +21 -18
  78. package/fjs/cli/types.d.ts +2 -3
  79. package/fjs/common/monoid/module.f.d.mts +70 -12
  80. package/fjs/common/monoid/module.f.mjs +177 -14
  81. package/fjs/common/monoid/proof.f.d.mts +12 -1
  82. package/fjs/common/monoid/proof.f.mjs +88 -4
  83. package/fjs/common/monoid/types.d.ts +23 -0
  84. package/fjs/crypto/hmac/module.f.mjs +2 -2
  85. package/fjs/crypto/secp/proof.f.d.mts +3 -1
  86. package/fjs/crypto/secp/proof.f.mjs +3 -1
  87. package/fjs/crypto/sha2/module.f.mjs +3 -1
  88. package/fjs/crypto/sha2/proof.f.d.mts +4 -1
  89. package/fjs/crypto/sha2/proof.f.mjs +27 -1
  90. package/fjs/crypto/sha2/types.d.ts +11 -0
  91. package/fjs/crypto/sign/module.f.mjs +2 -2
  92. package/fjs/crypto/vdf/module.f.d.mts +23 -4
  93. package/fjs/crypto/vdf/module.f.mjs +6 -4
  94. package/fjs/dev/module.f.d.mts +17 -5
  95. package/fjs/dev/module.f.mjs +60 -30
  96. package/fjs/dev/update/module.f.d.mts +11 -3
  97. package/fjs/dev/update/module.f.mjs +16 -11
  98. package/fjs/dev/update/proof.f.d.mts +4 -3
  99. package/fjs/dev/update/proof.f.mjs +11 -7
  100. package/fjs/djs/module.f.d.mts +13 -5
  101. package/fjs/djs/module.f.mjs +31 -16
  102. package/fjs/djs/parser/module.f.d.mts +16 -3
  103. package/fjs/djs/parser/module.f.mjs +135 -16
  104. package/fjs/djs/parser/proof.f.d.mts +8 -1
  105. package/fjs/djs/parser/proof.f.mjs +287 -13
  106. package/fjs/djs/parser/types.d.ts +7 -1
  107. package/fjs/djs/proof.f.d.mts +20 -1
  108. package/fjs/djs/proof.f.mjs +190 -12
  109. package/fjs/djs/serializer/module.f.d.mts +25 -8
  110. package/fjs/djs/serializer/module.f.mjs +66 -19
  111. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  112. package/fjs/djs/serializer/proof.f.mjs +23 -1
  113. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  114. package/fjs/djs/tokenizer/module.f.mjs +120 -73
  115. package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
  116. package/fjs/djs/tokenizer/proof.f.mjs +86 -67
  117. package/fjs/djs/transpiler/module.f.d.mts +13 -19
  118. package/fjs/djs/transpiler/module.f.mjs +79 -72
  119. package/fjs/djs/transpiler/types.d.ts +29 -0
  120. package/fjs/djs/types.d.ts +7 -1
  121. package/fjs/effects/list/module.f.d.mts +23 -12
  122. package/fjs/effects/list/module.f.mjs +16 -12
  123. package/fjs/effects/list/types.d.ts +27 -7
  124. package/fjs/effects/memory/module.f.d.mts +6 -3
  125. package/fjs/effects/memory/module.f.mjs +7 -7
  126. package/fjs/effects/memory/proof.f.d.mts +4 -0
  127. package/fjs/effects/memory/proof.f.mjs +18 -9
  128. package/fjs/effects/memory/types.d.ts +4 -3
  129. package/fjs/effects/mock/module.f.d.mts +28 -4
  130. package/fjs/effects/mock/module.f.mjs +39 -5
  131. package/fjs/effects/mock/types.d.ts +10 -1
  132. package/fjs/effects/module.d.mts +12 -2
  133. package/fjs/effects/module.f.d.mts +469 -281
  134. package/fjs/effects/module.f.mjs +538 -299
  135. package/fjs/effects/module.mjs +11 -2
  136. package/fjs/effects/node/memory/module.d.mts +7 -2
  137. package/fjs/effects/node/memory/module.mjs +9 -5
  138. package/fjs/effects/node/memory/proof.d.mts +2 -0
  139. package/fjs/effects/node/memory/proof.mjs +12 -5
  140. package/fjs/effects/node/module.d.mts +8 -2
  141. package/fjs/effects/node/module.f.d.mts +183 -43
  142. package/fjs/effects/node/module.f.mjs +260 -62
  143. package/fjs/effects/node/module.mjs +61 -50
  144. package/fjs/effects/node/proof.f.d.mts +28 -2
  145. package/fjs/effects/node/proof.f.mjs +161 -42
  146. package/fjs/effects/node/types.d.ts +106 -18
  147. package/fjs/effects/node/virtual/module.f.d.mts +21 -4
  148. package/fjs/effects/node/virtual/module.f.mjs +113 -70
  149. package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
  150. package/fjs/effects/node/virtual/proof.f.mjs +201 -8
  151. package/fjs/effects/proof.f.d.mts +69 -34
  152. package/fjs/effects/proof.f.mjs +413 -130
  153. package/fjs/effects/types.d.ts +161 -33
  154. package/fjs/emergent_testing/all.test.d.mts +8 -0
  155. package/fjs/emergent_testing/all.test.mjs +14 -0
  156. package/fjs/emergent_testing/module.f.d.mts +22 -10
  157. package/fjs/emergent_testing/module.f.mjs +119 -85
  158. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  159. package/fjs/emergent_testing/proof.f.mjs +169 -35
  160. package/fjs/emergent_testing/types.d.ts +22 -4
  161. package/fjs/fsc/bnf.f.d.mts +3 -0
  162. package/fjs/fsc/bnf.f.mjs +4 -1
  163. package/fjs/fsc/json.f.d.mts +3 -0
  164. package/fjs/fsc/json.f.mjs +4 -1
  165. package/fjs/fsc/module.f.d.mts +9 -0
  166. package/fjs/fsc/module.f.mjs +5 -3
  167. package/fjs/fsm/module.f.d.mts +14 -4
  168. package/fjs/fsm/module.f.mjs +54 -37
  169. package/fjs/fsm/proof.f.d.mts +5 -0
  170. package/fjs/fsm/proof.f.mjs +87 -115
  171. package/fjs/js/keywords/module.f.d.mts +52 -0
  172. package/fjs/js/keywords/module.f.mjs +72 -0
  173. package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
  174. package/fjs/js/keywords/proof.f.mjs +13 -0
  175. package/fjs/js/tokenizer/module.f.d.mts +30 -3
  176. package/fjs/js/tokenizer/module.f.mjs +161 -211
  177. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  178. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  179. package/fjs/js/tokenizer/types.d.ts +33 -24
  180. package/fjs/mcp/cas/module.f.d.mts +1 -6
  181. package/fjs/mcp/cas/module.f.mjs +55 -51
  182. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  183. package/fjs/mcp/cas/proof.f.mjs +174 -0
  184. package/fjs/mcp/evo/module.f.d.mts +19 -10
  185. package/fjs/mcp/evo/module.f.mjs +48 -27
  186. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  187. package/fjs/mcp/evo/proof.f.mjs +115 -31
  188. package/fjs/mcp/module.f.d.mts +39 -4
  189. package/fjs/mcp/module.f.mjs +14 -12
  190. package/fjs/mcp/proof.f.d.mts +13 -1
  191. package/fjs/mcp/proof.f.mjs +120 -61
  192. package/fjs/media/html/module.f.d.mts +12 -0
  193. package/fjs/media/html/module.f.mjs +7 -5
  194. package/fjs/media/html/proof.f.d.mts +3 -0
  195. package/fjs/media/html/proof.f.mjs +4 -1
  196. package/fjs/media/json/extended/module.f.d.mts +82 -0
  197. package/fjs/media/json/extended/module.f.mjs +153 -0
  198. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  199. package/fjs/media/json/extended/proof.f.mjs +127 -0
  200. package/fjs/media/json/extended/types.d.ts +23 -0
  201. package/fjs/media/json/module.f.d.mts +8 -2
  202. package/fjs/media/json/module.f.mjs +43 -41
  203. package/fjs/media/json/number/module.f.d.mts +59 -0
  204. package/fjs/media/json/number/module.f.mjs +136 -0
  205. package/fjs/media/json/number/proof.f.d.mts +24 -0
  206. package/fjs/media/json/number/proof.f.mjs +86 -0
  207. package/fjs/media/json/number/types.d.ts +28 -0
  208. package/fjs/media/json/parser/module.f.d.mts +25 -13
  209. package/fjs/media/json/parser/module.f.mjs +133 -72
  210. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  211. package/fjs/media/json/parser/proof.f.mjs +31 -1
  212. package/fjs/media/json/parser/types.d.ts +38 -14
  213. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  214. package/fjs/media/json/rtti/module.f.mjs +1 -1
  215. package/fjs/media/json/rtti/proof.f.d.mts +3 -0
  216. package/fjs/media/json/rtti/proof.f.mjs +12 -12
  217. package/fjs/media/json/schema/module.f.d.mts +61 -27
  218. package/fjs/media/json/schema/module.f.mjs +218 -63
  219. package/fjs/media/json/schema/proof.f.d.mts +41 -1
  220. package/fjs/media/json/schema/proof.f.mjs +220 -9
  221. package/fjs/media/json/serializer/module.f.d.mts +44 -0
  222. package/fjs/media/json/serializer/module.f.mjs +71 -9
  223. package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
  224. package/fjs/media/json/tokenizer/module.f.mjs +31 -8
  225. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  226. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  227. package/fjs/media/json/types.d.ts +36 -10
  228. package/fjs/media/lock/module.f.d.mts +100 -0
  229. package/fjs/media/lock/module.f.mjs +125 -0
  230. package/fjs/media/lock/proof.f.d.mts +33 -0
  231. package/fjs/media/lock/proof.f.mjs +196 -0
  232. package/fjs/media/lock/types.d.ts +15 -0
  233. package/fjs/media/module.f.d.mts +6 -5
  234. package/fjs/media/module.f.mjs +8 -7
  235. package/fjs/media/nix/module.f.d.mts +13 -0
  236. package/fjs/media/nix/module.f.mjs +4 -2
  237. package/fjs/media/nix/proof.f.d.mts +3 -0
  238. package/fjs/media/nix/proof.f.mjs +4 -1
  239. package/fjs/media/note/module.f.d.mts +121 -0
  240. package/fjs/media/note/module.f.mjs +131 -0
  241. package/fjs/media/note/proof.f.d.mts +29 -0
  242. package/fjs/media/note/proof.f.mjs +150 -0
  243. package/fjs/media/note/types.d.ts +10 -0
  244. package/fjs/media/proof.f.d.mts +4 -1
  245. package/fjs/media/proof.f.mjs +40 -21
  246. package/fjs/media/revision/module.f.d.mts +83 -7
  247. package/fjs/media/revision/module.f.mjs +127 -23
  248. package/fjs/media/revision/proof.f.d.mts +14 -0
  249. package/fjs/media/revision/proof.f.mjs +93 -2
  250. package/fjs/media/revision/types.d.ts +34 -5
  251. package/fjs/media/type/module.f.d.mts +53 -18
  252. package/fjs/media/type/module.f.mjs +87 -97
  253. package/fjs/media/type/proof.f.d.mts +17 -0
  254. package/fjs/media/type/proof.f.mjs +73 -13
  255. package/fjs/module.d.mts +5 -0
  256. package/fjs/module.f.d.mts +8 -0
  257. package/fjs/module.f.mjs +33 -10
  258. package/fjs/module.mjs +6 -0
  259. package/fjs/nanvm/proof.f.mjs +3 -3
  260. package/fjs/nanvm/rust/module.f.mjs +1 -1
  261. package/fjs/nanvm/update/module.f.d.mts +4 -4
  262. package/fjs/nanvm/update/module.f.mjs +8 -9
  263. package/fjs/nanvm/update/proof.f.mjs +4 -3
  264. package/fjs/path/module.f.d.mts +8 -0
  265. package/fjs/path/module.f.mjs +4 -2
  266. package/fjs/proof.f.d.mts +7 -3
  267. package/fjs/proof.f.mjs +41 -12
  268. package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
  269. package/fjs/protocol/json_rpc/module.f.mjs +10 -7
  270. package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
  271. package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
  272. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  273. package/fjs/protocol/mcp/module.f.mjs +74 -58
  274. package/fjs/protocol/mcp/proof.f.d.mts +16 -3
  275. package/fjs/protocol/mcp/proof.f.mjs +224 -69
  276. package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
  277. package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
  278. package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
  279. package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
  280. package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
  281. package/fjs/protocol/mcp/types.d.ts +17 -6
  282. package/fjs/sul/id/module.f.d.mts +4 -0
  283. package/fjs/sul/id/module.f.mjs +6 -6
  284. package/fjs/sul/level/hash/module.f.d.mts +4 -1
  285. package/fjs/sul/level/hash/module.f.mjs +6 -4
  286. package/fjs/sul/level/hash/proof.f.d.mts +4 -0
  287. package/fjs/sul/level/hash/proof.f.mjs +7 -4
  288. package/fjs/sul/level/literal/module.f.d.mts +4 -1
  289. package/fjs/sul/level/literal/module.f.mjs +4 -3
  290. package/fjs/sul/level/literal/proof.f.d.mts +3 -0
  291. package/fjs/sul/level/literal/proof.f.mjs +4 -1
  292. package/fjs/sul/module.f.d.mts +5 -3
  293. package/fjs/sul/module.f.mjs +23 -17
  294. package/fjs/sul/proof.f.d.mts +4 -0
  295. package/fjs/sul/proof.f.mjs +5 -2
  296. package/fjs/text/ascii/module.f.d.mts +26 -0
  297. package/fjs/text/ascii/module.f.mjs +49 -1
  298. package/fjs/text/ascii/proof.f.d.mts +10 -0
  299. package/fjs/text/ascii/proof.f.mjs +33 -1
  300. package/fjs/text/code_point/module.f.d.mts +29 -3
  301. package/fjs/text/code_point/module.f.mjs +32 -9
  302. package/fjs/text/code_point/proof.f.d.mts +2 -0
  303. package/fjs/text/code_point/proof.f.mjs +39 -0
  304. package/fjs/text/module.f.d.mts +4 -2
  305. package/fjs/text/module.f.mjs +4 -3
  306. package/fjs/text/proof.f.d.mts +3 -0
  307. package/fjs/text/proof.f.mjs +4 -1
  308. package/fjs/text/sgr/module.f.d.mts +6 -5
  309. package/fjs/text/sgr/module.f.mjs +8 -8
  310. package/fjs/text/sgr/proof.f.d.mts +3 -0
  311. package/fjs/text/sgr/proof.f.mjs +4 -1
  312. package/fjs/text/utf16/module.f.d.mts +5 -1
  313. package/fjs/text/utf16/module.f.mjs +38 -35
  314. package/fjs/text/utf16/proof.f.d.mts +3 -1
  315. package/fjs/text/utf16/proof.f.mjs +19 -2
  316. package/fjs/text/utf8/module.f.d.mts +9 -5
  317. package/fjs/text/utf8/module.f.mjs +20 -20
  318. package/fjs/types/array/module.f.d.mts +2 -1
  319. package/fjs/types/array/module.f.mjs +16 -4
  320. package/fjs/types/bigfloat/module.f.d.mts +21 -1
  321. package/fjs/types/bigfloat/module.f.mjs +33 -7
  322. package/fjs/types/bigfloat/proof.f.d.mts +1 -0
  323. package/fjs/types/bigfloat/proof.f.mjs +46 -0
  324. package/fjs/types/bigint/module.f.d.mts +4 -0
  325. package/fjs/types/bigint/module.f.mjs +4 -3
  326. package/fjs/types/bit_vec/module.f.d.mts +10 -16
  327. package/fjs/types/bit_vec/module.f.mjs +99 -95
  328. package/fjs/types/bit_vec/proof.f.d.mts +6 -0
  329. package/fjs/types/bit_vec/proof.f.mjs +31 -5
  330. package/fjs/types/btree/find/module.f.d.mts +5 -1
  331. package/fjs/types/btree/find/module.f.mjs +5 -5
  332. package/fjs/types/btree/find/proof.f.d.mts +5 -1
  333. package/fjs/types/btree/find/proof.f.mjs +5 -3
  334. package/fjs/types/btree/module.f.d.mts +3 -0
  335. package/fjs/types/btree/module.f.mjs +3 -2
  336. package/fjs/types/btree/proof.f.d.mts +5 -1
  337. package/fjs/types/btree/proof.f.mjs +5 -3
  338. package/fjs/types/btree/remove/module.f.d.mts +11 -0
  339. package/fjs/types/btree/remove/module.f.mjs +10 -10
  340. package/fjs/types/btree/remove/proof.f.d.mts +3 -0
  341. package/fjs/types/btree/remove/proof.f.mjs +4 -1
  342. package/fjs/types/btree/set/module.f.d.mts +9 -0
  343. package/fjs/types/btree/set/module.f.mjs +14 -17
  344. package/fjs/types/btree/set/proof.f.d.mts +3 -0
  345. package/fjs/types/btree/set/proof.f.mjs +16 -1
  346. package/fjs/types/btree/types/module.f.d.mts +2 -1
  347. package/fjs/types/btree/types/module.f.mjs +2 -1
  348. package/fjs/types/byte_set/module.f.d.mts +20 -4
  349. package/fjs/types/byte_set/module.f.mjs +18 -8
  350. package/fjs/types/byte_set/proof.f.d.mts +3 -1
  351. package/fjs/types/byte_set/proof.f.mjs +10 -8
  352. package/fjs/types/function/compare/module.f.d.mts +3 -2
  353. package/fjs/types/function/compare/module.f.mjs +13 -5
  354. package/fjs/types/function/module.f.d.mts +8 -1
  355. package/fjs/types/function/module.f.mjs +8 -1
  356. package/fjs/types/function/operator/module.f.d.mts +2 -1
  357. package/fjs/types/function/operator/module.f.mjs +2 -2
  358. package/fjs/types/list/module.f.d.mts +10 -3
  359. package/fjs/types/list/module.f.mjs +6 -4
  360. package/fjs/types/list/proof.f.d.mts +4 -1
  361. package/fjs/types/list/proof.f.mjs +4 -2
  362. package/fjs/types/nibble_set/module.f.d.mts +2 -1
  363. package/fjs/types/nibble_set/module.f.mjs +2 -2
  364. package/fjs/types/nominal/module.f.d.mts +2 -1
  365. package/fjs/types/nominal/module.f.mjs +2 -1
  366. package/fjs/types/nullable/module.f.d.mts +26 -6
  367. package/fjs/types/nullable/module.f.mjs +25 -6
  368. package/fjs/types/nullable/proof.f.d.mts +4 -0
  369. package/fjs/types/nullable/proof.f.mjs +15 -0
  370. package/fjs/types/number/module.f.d.mts +4 -0
  371. package/fjs/types/number/module.f.mjs +4 -3
  372. package/fjs/types/object/module.f.d.mts +26 -4
  373. package/fjs/types/object/module.f.mjs +26 -7
  374. package/fjs/types/object/proof.f.d.mts +5 -2
  375. package/fjs/types/object/proof.f.mjs +6 -3
  376. package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
  377. package/fjs/types/object/structurally_same/module.f.mjs +59 -0
  378. package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
  379. package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
  380. package/fjs/types/ordered_map/module.f.d.mts +5 -0
  381. package/fjs/types/ordered_map/module.f.mjs +5 -4
  382. package/fjs/types/ordered_map/proof.f.d.mts +3 -0
  383. package/fjs/types/ordered_map/proof.f.mjs +4 -1
  384. package/fjs/types/patricia_trie/module.f.d.mts +2 -1
  385. package/fjs/types/patricia_trie/module.f.mjs +27 -12
  386. package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
  387. package/fjs/types/patricia_trie/proof.f.mjs +4 -1
  388. package/fjs/types/prime_field/module.f.d.mts +3 -1
  389. package/fjs/types/prime_field/module.f.mjs +3 -2
  390. package/fjs/types/range/module.f.d.mts +2 -1
  391. package/fjs/types/range/module.f.mjs +2 -2
  392. package/fjs/types/range_map/module.f.d.mts +6 -0
  393. package/fjs/types/range_map/module.f.mjs +6 -9
  394. package/fjs/types/range_map/proof.f.d.mts +5 -1
  395. package/fjs/types/range_map/proof.f.mjs +5 -3
  396. package/fjs/types/range_set/module.f.d.mts +5 -0
  397. package/fjs/types/range_set/module.f.mjs +1 -0
  398. package/fjs/types/range_set/proof.f.d.mts +3 -0
  399. package/fjs/types/range_set/proof.f.mjs +4 -1
  400. package/fjs/types/result/module.d.mts +8 -0
  401. package/fjs/types/result/module.f.d.mts +37 -7
  402. package/fjs/types/result/module.f.mjs +38 -8
  403. package/fjs/types/result/module.mjs +9 -1
  404. package/fjs/types/result/proof.f.d.mts +5 -0
  405. package/fjs/types/result/proof.f.mjs +22 -2
  406. package/fjs/types/rtti/common/module.f.d.mts +44 -14
  407. package/fjs/types/rtti/common/module.f.mjs +42 -36
  408. package/fjs/types/rtti/common/proof.f.d.mts +4 -0
  409. package/fjs/types/rtti/common/proof.f.mjs +10 -7
  410. package/fjs/types/rtti/data/module.f.d.mts +134 -0
  411. package/fjs/types/rtti/data/module.f.mjs +1053 -0
  412. package/fjs/types/rtti/data/proof.f.d.mts +76 -0
  413. package/fjs/types/rtti/data/proof.f.mjs +589 -0
  414. package/fjs/types/rtti/data/types.d.ts +83 -0
  415. package/fjs/types/rtti/module.f.d.mts +12 -5
  416. package/fjs/types/rtti/module.f.mjs +7 -5
  417. package/fjs/types/rtti/parse/module.f.d.mts +48 -0
  418. package/fjs/types/rtti/parse/module.f.mjs +45 -34
  419. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  420. package/fjs/types/rtti/parse/proof.f.mjs +51 -52
  421. package/fjs/types/rtti/proof.f.d.mts +3 -1
  422. package/fjs/types/rtti/proof.f.mjs +6 -2
  423. package/fjs/types/rtti/ts/module.f.d.mts +68 -9
  424. package/fjs/types/rtti/ts/module.f.mjs +258 -30
  425. package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
  426. package/fjs/types/rtti/ts/proof.f.mjs +152 -4
  427. package/fjs/types/rtti/ts/types.d.ts +25 -1
  428. package/fjs/types/rtti/types.d.ts +40 -0
  429. package/fjs/types/sorted_list/module.f.d.mts +4 -1
  430. package/fjs/types/sorted_list/module.f.mjs +21 -12
  431. package/fjs/types/sorted_list/proof.f.d.mts +3 -1
  432. package/fjs/types/sorted_list/proof.f.mjs +3 -1
  433. package/fjs/types/sorted_set/module.f.d.mts +49 -1
  434. package/fjs/types/sorted_set/module.f.mjs +26 -2
  435. package/fjs/types/sorted_set/proof.f.d.mts +4 -1
  436. package/fjs/types/sorted_set/proof.f.mjs +19 -2
  437. package/fjs/types/string/module.f.d.mts +4 -0
  438. package/fjs/types/string/module.f.mjs +4 -3
  439. package/fjs/types/string_set/module.f.d.mts +3 -1
  440. package/fjs/types/string_set/module.f.mjs +3 -2
  441. package/fjs/types/ts/module.f.d.mts +2 -0
  442. package/fjs/types/ts/module.f.mjs +3 -3
  443. package/fjs/types/ts/proof.f.d.mts +1 -0
  444. package/fjs/types/ts/proof.f.mjs +5 -0
  445. package/fjs/types/ts/types.d.ts +6 -1
  446. package/fjs/types/uint8array/module.f.d.mts +13 -2
  447. package/fjs/types/uint8array/module.f.mjs +20 -15
  448. package/fjs/website/module.f.d.mts +5 -2
  449. package/fjs/website/module.f.mjs +6 -8
  450. package/fjs/website/proof.f.mjs +2 -1
  451. package/package.json +3 -3
  452. package/fjs/asn.1/types.js +0 -6
  453. package/fjs/asserts/types.js +0 -6
  454. package/fjs/basen/types.js +0 -6
  455. package/fjs/bnf/data/types.js +0 -6
  456. package/fjs/bnf/descent/types.js +0 -6
  457. package/fjs/bnf/ll1/types.js +0 -6
  458. package/fjs/bnf/token_symbol/types.js +0 -6
  459. package/fjs/bnf/types.js +0 -6
  460. package/fjs/cas/evo/types.js +0 -7
  461. package/fjs/cas/types.js +0 -6
  462. package/fjs/ci/common/types.js +0 -1
  463. package/fjs/ci/nix/types.js +0 -6
  464. package/fjs/ci/types.js +0 -6
  465. package/fjs/cli/types.js +0 -6
  466. package/fjs/common/monoid/types.js +0 -6
  467. package/fjs/crypto/pow/types.js +0 -6
  468. package/fjs/crypto/secp/types.js +0 -6
  469. package/fjs/crypto/sha2/types.js +0 -6
  470. package/fjs/crypto/sign/types.js +0 -6
  471. package/fjs/crypto/vdf/types.js +0 -6
  472. package/fjs/dev/package_json/module.f.d.mts +0 -32
  473. package/fjs/dev/package_json/module.f.mjs +0 -37
  474. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  475. package/fjs/dev/package_json/proof.f.mjs +0 -32
  476. package/fjs/dev/types.js +0 -6
  477. package/fjs/djs/ast/types.js +0 -8
  478. package/fjs/djs/parser/types.js +0 -7
  479. package/fjs/djs/tokenizer/types.js +0 -7
  480. package/fjs/djs/types.js +0 -7
  481. package/fjs/effects/eff/module.f.d.mts +0 -10
  482. package/fjs/effects/eff/module.f.mjs +0 -68
  483. package/fjs/effects/eff/proof.f.d.mts +0 -12
  484. package/fjs/effects/eff/proof.f.mjs +0 -66
  485. package/fjs/effects/eff/types.d.ts +0 -71
  486. package/fjs/effects/eff/types.js +0 -6
  487. package/fjs/effects/list/types.js +0 -6
  488. package/fjs/effects/memory/types.js +0 -6
  489. package/fjs/effects/mock/types.js +0 -6
  490. package/fjs/effects/node/types.js +0 -6
  491. package/fjs/effects/node/virtual/types.js +0 -7
  492. package/fjs/effects/types.js +0 -6
  493. package/fjs/emergent_testing/all.test.d.ts +0 -1
  494. package/fjs/emergent_testing/all.test.js +0 -5
  495. package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
  496. package/fjs/emergent_testing/scenarios/all.js +0 -1
  497. package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
  498. package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
  499. package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
  500. package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
  501. package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
  502. package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
  503. package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
  504. package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
  505. package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
  506. package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
  507. package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
  508. package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
  509. package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
  510. package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
  511. package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
  512. package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
  513. package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
  514. package/fjs/emergent_testing/types.js +0 -6
  515. package/fjs/js/tokenizer/types.js +0 -6
  516. package/fjs/media/html/types.js +0 -6
  517. package/fjs/media/json/parser/types.js +0 -6
  518. package/fjs/media/json/tokenizer/types.js +0 -6
  519. package/fjs/media/json/types.js +0 -13
  520. package/fjs/media/nix/types.js +0 -6
  521. package/fjs/media/revision/types.js +0 -8
  522. package/fjs/media/type/types.js +0 -6
  523. package/fjs/media/types.js +0 -7
  524. package/fjs/nanvm/types.js +0 -11
  525. package/fjs/protocol/json_rpc/types.js +0 -8
  526. package/fjs/protocol/mcp/types.js +0 -8
  527. package/fjs/sul/id/types.js +0 -6
  528. package/fjs/sul/level/hash/types.js +0 -6
  529. package/fjs/sul/level/literal/types.js +0 -6
  530. package/fjs/sul/types.js +0 -6
  531. package/fjs/text/sgr/types.js +0 -6
  532. package/fjs/text/types.js +0 -6
  533. package/fjs/text/utf16/types.js +0 -6
  534. package/fjs/text/utf8/types.js +0 -6
  535. package/fjs/types/array/types.js +0 -6
  536. package/fjs/types/bigfloat/types.js +0 -6
  537. package/fjs/types/bigint/types.js +0 -6
  538. package/fjs/types/bit_vec/types.js +0 -6
  539. package/fjs/types/btree/find/types.js +0 -6
  540. package/fjs/types/btree/types/types.js +0 -6
  541. package/fjs/types/byte_set/types.js +0 -6
  542. package/fjs/types/function/compare/types.js +0 -6
  543. package/fjs/types/function/operator/types.js +0 -6
  544. package/fjs/types/function/types.js +0 -6
  545. package/fjs/types/list/types.js +0 -6
  546. package/fjs/types/nibble_set/types.js +0 -6
  547. package/fjs/types/nominal/types.js +0 -6
  548. package/fjs/types/nullable/types.js +0 -6
  549. package/fjs/types/object/types.js +0 -8
  550. package/fjs/types/option/types.js +0 -6
  551. package/fjs/types/ordered_map/types.js +0 -6
  552. package/fjs/types/patricia_trie/types.js +0 -6
  553. package/fjs/types/phantom/types.js +0 -11
  554. package/fjs/types/prime_field/types.js +0 -6
  555. package/fjs/types/range/types.js +0 -6
  556. package/fjs/types/range_map/types.js +0 -6
  557. package/fjs/types/result/types.js +0 -6
  558. package/fjs/types/rtti/common/types.js +0 -1
  559. package/fjs/types/rtti/parse/types.js +0 -1
  560. package/fjs/types/rtti/ts/types.js +0 -1
  561. package/fjs/types/rtti/types.js +0 -1
  562. package/fjs/types/rtti/validate/module.f.d.mts +0 -6
  563. package/fjs/types/rtti/validate/module.f.mjs +0 -169
  564. package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
  565. package/fjs/types/rtti/validate/proof.f.mjs +0 -437
  566. package/fjs/types/rtti/validate/types.d.ts +0 -6
  567. package/fjs/types/rtti/validate/types.js +0 -1
  568. package/fjs/types/sorted_list/types.js +0 -6
  569. package/fjs/types/sorted_set/types.js +0 -6
  570. package/fjs/types/string_set/types.js +0 -6
  571. package/fjs/types/ts/types.js +0 -8
@@ -1,5 +1,8 @@
1
- /** @import { Object as JsonObject } from '../json/types.ts' */
2
- /** @import { LockMap } from './types.ts' */
1
+ /**
2
+ * @import { Object as JsonObject } from '../json/types.ts'
3
+ * @import { LockMap } from './types.ts'
4
+ */
5
+
3
6
  import { assert, assertEq } from '../../asserts/module.f.mjs'
4
7
  import { dialect, mediaType, isHash, validate, decodeText, encodeText } from './module.f.mjs'
5
8
 
@@ -13,6 +16,11 @@ const alias = /** @type {const} */ ('I')
13
16
  /** @type {LockMap} */
14
17
  const _lockMapAllowsMissingSubjects = {}
15
18
 
19
+ // A lock map's values are `string | LockMap | undefined` at every depth, so
20
+ // the same value is a legal binding for a direct hash and for a nested scope.
21
+ /** @type {LockMap} */
22
+ const _lockMapNests = { direct: h1, scope: { direct: h2, deeper: { direct: h1 } } }
23
+
16
24
  // A shape-valid revision: every required field present (`snapshot` and
17
25
  // `generation` included), with `extra` overriding or adding fields per test.
18
26
  /** @type {(extra: JsonObject) => JsonObject} */
@@ -152,6 +160,62 @@ export const proof = {
152
160
  assertEq(t, 'ok')
153
161
  },
154
162
 
163
+ // A nested map scopes further bindings under a subject — the
164
+ // incompatible-diamond case from the README, where `B` and `C` each
165
+ // pick their own `D`.
166
+ nestedLockAccepted: () => {
167
+ const r = validate(revisionOf({ lock: { B: { B: h1, D: h1 }, C: { C: h2, D: h2 } } }))
168
+ assert(r[0] === 'ok', ['expected ok', r])
169
+ assert(encodeText(r[1]).includes(`"lock":{"B":{"B":"${h1}","D":"${h1}"},"C":{"C":"${h2}","D":"${h2}"}}`))
170
+ },
171
+
172
+ // Nesting has no depth limit, and a nested map may be sparse — it need
173
+ // not bind the subject it appears under, or anything at all.
174
+ deeplyNestedLockAccepted: () => {
175
+ const [t] = validate(revisionOf({ lock: { B: { C: { D: { E: h1 } } }, empty: {} } }))
176
+ assertEq(t, 'ok')
177
+ },
178
+
179
+ // A direct value must be a string or a map at every depth: a number
180
+ // nested two levels down fails structural (rtti) validation, exactly
181
+ // as it does at the root.
182
+ malformedNestedLockRejected: () => {
183
+ const [t] = validate(revisionOf({ lock: { B: { D: 1 } } }))
184
+ assertEq(t, 'error')
185
+ },
186
+
187
+ // Semantic reference checking recurses too: a non-hash string deep in
188
+ // a nested scope is rejected, and the message names the path to it.
189
+ invalidNestedHashLockRejected: () => {
190
+ const r = validate(revisionOf({ lock: { B: { D: 'https://example.com/x' } } }))
191
+ assert(r[0] === 'error', ['expected error', r])
192
+ assertEq(r[1], 'lock value for B/D is not a valid hash: https://example.com/x')
193
+ },
194
+
195
+ // In place of the map, `lock` may be the hash of a `vnd.fjs.lock`
196
+ // blob holding one — the only position where a string means "where
197
+ // the bindings are" rather than "this dependency's content".
198
+ sharedLockReferenceAccepted: () => {
199
+ const r = validate(revisionOf({ lock: h1 }))
200
+ assert(r[0] === 'ok', ['expected ok', r])
201
+ assertEq(r[1].lock, h1)
202
+ },
203
+
204
+ // A reference is validated as a cbase32 hash and nothing more — the
205
+ // same contract `snapshot` has — so a non-hash one is rejected.
206
+ invalidSharedLockReferenceRejected: () => {
207
+ const r = validate(revisionOf({ lock: 'https://example.com/lock' }))
208
+ assert(r[0] === 'error', ['expected error', r])
209
+ assertEq(r[1], 'lock reference is not a valid hash: https://example.com/lock')
210
+ },
211
+
212
+ // Only the top level is widened: a nested value is still a hash or a
213
+ // map, so nothing about an inline map's meaning changed.
214
+ nestedValueIsStillNotAReference: () => {
215
+ const [t] = validate(revisionOf({ lock: { B: { D: h1 } } }))
216
+ assertEq(t, 'ok')
217
+ },
218
+
155
219
  // Wrong dialect tag: structural validation rejects it outright.
156
220
  wrongDialectRejected: () => {
157
221
  const [t] = validate({ dialect: 'vnd.fjs.other', subject: h1, parents: [], snapshot: h2, generation: 0 })
@@ -210,6 +274,32 @@ export const proof = {
210
274
  `{"dialect":"${dialect}","generation":0,"lock":{"10":"${h1}","2":"${h2}"},"parents":[],"snapshot":"${h2}","subject":"${h1}"}`,
211
275
  )
212
276
  },
277
+ // The one `stringify(sort)` rule already reaches every depth, so a
278
+ // nested lock map needs no serialization special case: its keys sort
279
+ // as strings like every other object's ("10" before "2").
280
+ sortsNestedLockKeys: () => {
281
+ const revision = revisionOf({ lock: { scope: { '2': h2, '10': h1 }, '2': h2, '10': h1 } })
282
+ const decoded = validate(revision)
283
+ assert(decoded[0] === 'ok', ['expected ok', decoded])
284
+ assert(encodeText(decoded[1]).includes(
285
+ `"lock":{"10":"${h1}","2":"${h2}","scope":{"10":"${h1}","2":"${h2}"}}`))
286
+ },
287
+ // Two nested maps differing only in property order converge on one
288
+ // byte sequence, so they address the same CAS blob.
289
+ equivalentNestedLockOrdersConverge: () => {
290
+ const a = validate(revisionOf({ lock: { B: { B: h1, D: h2 }, C: { D: h1 } } }))
291
+ const b = validate(revisionOf({ lock: { C: { D: h1 }, B: { D: h2, B: h1 } } }))
292
+ assert(a[0] === 'ok', ['expected ok', a])
293
+ assert(b[0] === 'ok', ['expected ok', b])
294
+ assertEq(encodeText(a[1]), encodeText(b[1]))
295
+ },
296
+ // A shared-lock reference serializes as the plain string it is — no
297
+ // wrapper, no marker: the two forms are told apart by JSON type.
298
+ serializesSharedLockReferenceAsAString: () => {
299
+ const decoded = validate(revisionOf({ lock: h1 }))
300
+ assert(decoded[0] === 'ok', ['expected ok', decoded])
301
+ assert(encodeText(decoded[1]).includes(`"lock":"${h1}"`))
302
+ },
213
303
  preservesArrayOrder: () => {
214
304
  const decoded = validate(revisionOf({ parents: [h2, h1] }))
215
305
  assert(decoded[0] === 'ok', ['expected ok', decoded])
@@ -226,3 +316,4 @@ export const proof = {
226
316
  }
227
317
 
228
318
  void _lockMapAllowsMissingSubjects
319
+ void _lockMapNests
@@ -1,15 +1,44 @@
1
1
  /**
2
2
  * Type-level API for `fjs/media/revision/module.f.mjs`: `LockMap`,
3
- * `Revision`, and `RevisionError`, derived from the module's own rtti
4
- * schemas.
3
+ * `LockSchema`, `LockField`, `LockFieldSchema`, `Revision`, and
4
+ * `RevisionError`.
5
+ *
6
+ * `LockMap` is written by hand rather than derived, so that the recursion
7
+ * reads directly, and is then pinned against the module's rtti schema with
8
+ * `Assert<Equal<LockMap, Ts<typeof lock>>>` — the same arrangement the JSON
9
+ * data model uses in [`../json/types.ts`](../json/types.ts). `LockSchema` is
10
+ * the schema side of the same recursion: `lock` cannot infer its own type
11
+ * (a `const` may not reference itself in its own initializer), so it carries
12
+ * this named annotation instead.
5
13
  *
6
14
  * @module
7
15
  */
8
16
  import type { Ts } from '../../types/rtti/ts/types.ts';
17
+ import type { String as RttiString } from '../../types/rtti/types.ts';
9
18
  import type { ValidationError } from '../../types/rtti/common/types.ts';
10
- import type { _lock, revisionSchema } from './module.f.mjs';
11
- /** A flat set of subject-to-snapshot bindings supplied to dependency resolvers. */
12
- export type LockMap = Ts<typeof _lock>;
19
+ import type { revisionSchema } from './module.f.mjs';
20
+ /**
21
+ * A set of subject-to-snapshot bindings supplied to dependency resolvers.
22
+ * A direct string value selects immutable content; a nested map scopes
23
+ * further bindings under that subject (see the README).
24
+ *
25
+ * Spelled inline rather than as `StringMap<string | LockMap>`: a type alias
26
+ * may not reference itself through another alias's instantiation (TS2456).
27
+ */
28
+ export type LockMap = {
29
+ readonly [subject in string]?: string | LockMap;
30
+ };
31
+ /** The rtti schema type of `lock` — a record of `string | LockSchema`. */
32
+ export type LockSchema = () => readonly ['record', () => readonly ['or', RttiString, LockSchema]];
33
+ /**
34
+ * A revision's `lock` field: the bindings inline as a {@link LockMap}, or the
35
+ * cbase32 hash of a `vnd.fjs.lock` blob (`fjs/media/lock`) holding one to
36
+ * share. Only the top level admits a hash — a string *inside* a map is a
37
+ * dependency's content, unchanged.
38
+ */
39
+ export type LockField = string | LockMap;
40
+ /** The rtti schema type of `lockField` — a shared-lock reference or a lock map. */
41
+ export type LockFieldSchema = () => readonly ['or', RttiString, LockSchema];
13
42
  /** The TypeScript type derived from `revisionSchema` — the single source of truth. */
14
43
  export type Revision = Ts<typeof revisionSchema>;
15
44
  /** Either a structural validation error or a semantic (hash / generation) error message. */
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * Magic-byte MIME type detection.
3
3
  *
4
- * `detect` is a pure table lookup over the leading bytes of a `Vec`: it returns a
5
- * MIME type string for the container formats whose signatures it knows, or `null`
6
- * for anything else text, unknown binary, or a `Vec` too short to match.
4
+ * One list `signatures` declares every recognized magic-byte pattern, and
5
+ * both detectors read it through the same eliminator (`magicStep`): `detect`
6
+ * folds a whole `Vec` and returns a MIME type string or `null`, while
7
+ * `detectStream` folds a read stream one chunk at a time.
7
8
  *
8
- * Beside it, `detectStream` is the **streaming counterpart**: a byte-accepting
9
- * state machine (length × magic-byte eliminator × UTF-8 validity DFA) that derives
10
- * `{ length, mime_type, type }` by folding a CAS read stream in O(1) space, without
11
- * ever buffering the blob into a single `maxLength`-bounded `Vec`. See the README
12
- * for the factored design.
9
+ * Beside `detect`, `detectStream` is the **streaming counterpart**: a
10
+ * byte-accepting state machine (length × magic-byte eliminator × UTF-8 validity
11
+ * DFA) that derives `{ length, mime_type, type }` by folding a CAS read stream in
12
+ * O(1) space, without ever buffering the blob into a single `maxLength`-bounded
13
+ * `Vec`. See the README for the factored design.
13
14
  *
14
15
  * The CAS store is type-agnostic and keeps raw bytes only, so type is never
15
16
  * stored; it is recovered on read by sniffing the content. Callers decide what
@@ -27,21 +28,54 @@
27
28
  * | `application/zip` | `50 4B 03 04` / `05 06` / `07 08` (`"PK"` entry, empty, or spanned) |
28
29
  *
29
30
  * WebP is the one signature with a gap: the four-byte little-endian file size
30
- * sits between the `RIFF` and `WEBP` markers, so it is matched as a prefix plus
31
- * a second marker at byte offset 8 rather than a single contiguous run.
31
+ * sits between the `RIFF` and `WEBP` markers, so its pattern carries four
32
+ * wildcard bytes rather than being one contiguous run.
32
33
  *
33
34
  * See `./types.ts` for the type-level API.
34
35
  *
35
36
  * @module
37
+ *
38
+ * @import { Vec } from '../../types/bit_vec/types.ts'
39
+ * @import { Nullable } from '../../types/nullable/types.ts'
40
+ * @import { Operation } from '../../effects/types.ts'
41
+ * @import { List } from '../../effects/list/types.ts'
42
+ * @import { IoChannel, IoResult } from '../../effects/node/types.ts'
43
+ * @import { Effect } from '../../effects/types.ts'
44
+ * @import { DetectMeta, DetectState, _MagicState, _Signature, _Utf8Detect } from './types.ts'
36
45
  */
37
46
  import type { Vec } from '../../types/bit_vec/types.ts';
38
47
  import type { Nullable } from '../../types/nullable/types.ts';
39
- import type { Effect, Operation } from '../../effects/types.ts';
48
+ import type { Operation } from '../../effects/types.ts';
40
49
  import type { List } from '../../effects/list/types.ts';
41
- import type { IoResult } from '../../effects/node/types.ts';
50
+ import type { IoChannel } from '../../effects/node/types.ts';
51
+ import type { Effect } from '../../effects/types.ts';
42
52
  import type { DetectMeta, DetectState } from './types.ts';
43
53
  /**
44
- * Detects the MIME type of `bytes` from its leading magic-byte signature.
54
+ * Detects the MIME type of `bytes` from its leading magic-byte signature, as
55
+ * the magic projection of the streaming detector below — one fold, read two
56
+ * ways, rather than a second copy of it.
57
+ *
58
+ * The two agree because `magicStep` returns a non-`scan` state unchanged, so
59
+ * both absorbing states are its fixed points. `detect`'s old loop stopped at
60
+ * the first one; `push` stops only once the *whole* verdict is settled and may
61
+ * keep folding for the UTF-8 factor after the magic state is `dead` — but a
62
+ * `dead` or `matched` magic cannot move again, so the final magic is the same
63
+ * either way. A signature still in `scan` at the end of the `Vec` — a prefix
64
+ * too short to complete any signature — reads as `null`.
65
+ *
66
+ * Cost follows `push`, which stops only once the whole verdict is settled, not
67
+ * once the magic state is. On a signature match or on non-text bytes that is
68
+ * still an early exit; on valid text it now reads the whole `Vec`, because the
69
+ * shared machine is still tracking the UTF-8 factor this function ignores
70
+ * (measured: 100 KB of ASCII, 1.2 ms before, 82 ms after). That is the same
71
+ * work {@link detectVec} already does on the same bytes, and `Vec` is capped at
72
+ * `maxLength`, so the cost is bounded rather than unbounded — but a caller
73
+ * scanning many large text blobs for signatures alone should know it is paying
74
+ * for the UTF-8 fold too.
75
+ *
76
+ * The bytes come from `u8List`, so a `Vec` whose length is not a whole number of
77
+ * bytes has its trailing partial byte zero-padded — the same reading of a ragged
78
+ * `Vec` the streaming detector already uses.
45
79
  *
46
80
  * @returns the MIME type string for a recognized format, or `null` when the
47
81
  * leading bytes match no known signature (including any `Vec` shorter than
@@ -87,11 +121,12 @@ export declare const finish: (s: DetectState) => DetectMeta;
87
121
  export declare const detectVec: (bytes: Vec) => DetectMeta;
88
122
  /**
89
123
  * Folds a CAS read stream through {@link push} and reads {@link finish} at EOF,
90
- * deriving `cas_get` metadata without ever materializing the blob. A read `error`
91
- * item short-circuits into the `IoResult` error.
124
+ * deriving `cas_get` metadata without ever materializing the blob. A stream that
125
+ * fails carries its failure out as this one's, through `step` rather than
126
+ * through a case in the loop.
92
127
  *
93
128
  * @template {Operation} O
94
- * @param {List<O, IoResult<Vec>>} stream
95
- * @returns {Effect<O, IoResult<DetectMeta>>}
129
+ * @param {List<O, Vec, IoChannel>} stream
130
+ * @returns {Effect<O, DetectMeta, IoChannel>}
96
131
  */
97
- export declare const detectStream: <O extends Operation>(stream: List<O, IoResult<Vec>>) => Effect<O, IoResult<DetectMeta>>;
132
+ export declare const detectStream: <O extends Operation>(stream: List<O, Vec, IoChannel>) => Effect<O, DetectMeta, IoChannel>;
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * Magic-byte MIME type detection.
3
3
  *
4
- * `detect` is a pure table lookup over the leading bytes of a `Vec`: it returns a
5
- * MIME type string for the container formats whose signatures it knows, or `null`
6
- * for anything else text, unknown binary, or a `Vec` too short to match.
4
+ * One list `signatures` declares every recognized magic-byte pattern, and
5
+ * both detectors read it through the same eliminator (`magicStep`): `detect`
6
+ * folds a whole `Vec` and returns a MIME type string or `null`, while
7
+ * `detectStream` folds a read stream one chunk at a time.
7
8
  *
8
- * Beside it, `detectStream` is the **streaming counterpart**: a byte-accepting
9
- * state machine (length × magic-byte eliminator × UTF-8 validity DFA) that derives
10
- * `{ length, mime_type, type }` by folding a CAS read stream in O(1) space, without
11
- * ever buffering the blob into a single `maxLength`-bounded `Vec`. See the README
12
- * for the factored design.
9
+ * Beside `detect`, `detectStream` is the **streaming counterpart**: a
10
+ * byte-accepting state machine (length × magic-byte eliminator × UTF-8 validity
11
+ * DFA) that derives `{ length, mime_type, type }` by folding a CAS read stream in
12
+ * O(1) space, without ever buffering the blob into a single `maxLength`-bounded
13
+ * `Vec`. See the README for the factored design.
13
14
  *
14
15
  * The CAS store is type-agnostic and keeps raw bytes only, so type is never
15
16
  * stored; it is recovered on read by sniffing the content. Callers decide what
@@ -27,107 +28,51 @@
27
28
  * | `application/zip` | `50 4B 03 04` / `05 06` / `07 08` (`"PK"` entry, empty, or spanned) |
28
29
  *
29
30
  * WebP is the one signature with a gap: the four-byte little-endian file size
30
- * sits between the `RIFF` and `WEBP` markers, so it is matched as a prefix plus
31
- * a second marker at byte offset 8 rather than a single contiguous run.
31
+ * sits between the `RIFF` and `WEBP` markers, so its pattern carries four
32
+ * wildcard bytes rather than being one contiguous run.
32
33
  *
33
34
  * See `./types.ts` for the type-level API.
34
35
  *
35
36
  * @module
37
+ *
38
+ * @import { Vec } from '../../types/bit_vec/types.ts'
39
+ * @import { Nullable } from '../../types/nullable/types.ts'
40
+ * @import { Operation } from '../../effects/types.ts'
41
+ * @import { List } from '../../effects/list/types.ts'
42
+ * @import { IoChannel, IoResult } from '../../effects/node/types.ts'
43
+ * @import { Effect } from '../../effects/types.ts'
44
+ * @import { DetectMeta, DetectState, _MagicState, _Signature, _Utf8Detect } from './types.ts'
36
45
  */
37
46
 
38
- import { msb, fromSentinel, length, u8List } from '../../types/bit_vec/module.f.mjs'
39
- /** @import { Vec } from '../../types/bit_vec/types.ts' */
47
+ import { msb, length, u8List } from '../../types/bit_vec/module.f.mjs'
40
48
  import { iterable } from '../../types/list/module.f.mjs'
41
- /** @import { Nullable } from '../../types/nullable/types.ts' */
42
- import { pure, step } from '../../effects/module.f.mjs'
43
- /** @import { Effect, Operation } from '../../effects/types.ts' */
44
- /** @import { List } from '../../effects/list/types.ts' */
45
- /** @import { IoResult } from '../../effects/node/types.ts' */
46
- import { ok, error } from '../../types/result/module.f.mjs'
49
+ import { pureOk, step as ioStep } from '../../effects/module.f.mjs'
47
50
  import { isValidCodePoint, isTextCodePoint } from '../../text/code_point/module.f.mjs'
48
51
  import { utf8ByteToCodePointOp } from '../../text/utf8/module.f.mjs'
49
- /** @import { DetectMeta, DetectState, _MagicState, _Signature, _Utf8Detect } from './types.ts' */
50
-
51
- const { startsWith, removeFront } = msb
52
-
53
- // Each signature is written as a hex literal whose leading `1` nibble is a
54
- // sentinel marking the start of the byte run (so leading zero bytes survive)
55
- // and fixing the length — see `bit_vec` `fromSentinel`.
56
- const sig = fromSentinel
57
-
58
- /**
59
- * Contiguous magic-byte signatures, checked in order; the first prefix match
60
- * wins. Ordering is irrelevant here — no signature is a prefix of another.
61
- *
62
- * @type {readonly (readonly [Vec, string])[]}
63
- */
64
- const table = [
65
- [sig(0x1_89_50_4e_47_0d_0a_1a_0an), 'image/png'],
66
- [sig(0x1_ff_d8_ffn), 'image/jpeg'],
67
- // Match the full GIF version headers ("GIF87a" / "GIF89a"), not just "GIF8",
68
- // so opaque bytes that merely start with "GIF8" are not mistyped.
69
- [sig(0x1_47_49_46_38_37_61n), 'image/gif'],
70
- [sig(0x1_47_49_46_38_39_61n), 'image/gif'],
71
- [sig(0x1_25_50_44_46_2dn), 'application/pdf'],
72
- // ZIP has three "PK" local-header variants: a normal entry, an empty
73
- // archive (end-of-central-directory only), and a spanned archive.
74
- [sig(0x1_50_4b_03_04n), 'application/zip'],
75
- [sig(0x1_50_4b_05_06n), 'application/zip'],
76
- [sig(0x1_50_4b_07_08n), 'application/zip'],
77
- ]
78
52
 
79
- // WebP: "RIFF" at offset 0, "WEBP" at offset 8 (the 4 bytes between are the
80
- // file size). 12 bytes = 96 bits is the minimum to carry both markers.
81
- const riff = sig(0x1_52_49_46_46n)
82
- const webp = sig(0x1_57_45_42_50n)
83
-
84
- /** @type {(bytes: Vec) => boolean} */
85
- const isWebp = bytes =>
86
- length(bytes) >= 96n
87
- && startsWith(riff)(bytes)
88
- && startsWith(webp)(removeFront(64n)(bytes))
89
-
90
- /**
91
- * Detects the MIME type of `bytes` from its leading magic-byte signature.
92
- *
93
- * @returns the MIME type string for a recognized format, or `null` when the
94
- * leading bytes match no known signature (including any `Vec` shorter than
95
- * the signature it might otherwise match).
96
- *
97
- * @type {(bytes: Vec) => Nullable<string>}
98
- */
99
- export const detect = bytes => {
100
- if (isWebp(bytes)) { return 'image/webp' }
101
- for (const [s, m] of table) {
102
- if (startsWith(s)(bytes)) { return m }
103
- }
104
- return null
105
- }
106
-
107
- // ── Streaming detector ────────────────────────────────────────────────────────────
53
+ // ── Magic-byte signatures ─────────────────────────────────────────────────────────
108
54
  //
109
- // A byte-accepting state machine that derives the same `{ length, mime_type, type }`
110
- // metadata as the pure `detect` + UTF-8 path, but **without buffering the blob**.
111
- // It is the product of three independent folds over the byte stream — length,
112
- // magic-byte signature elimination, and a UTF-8 validity DFA — read off at
113
- // end-of-stream by `finish`. This lets `cas_get` inspect arbitrarily large blobs
114
- // (where a single `Vec` would overflow `maxLength`) in O(1) space, since the bulk
115
- // of a large blob costs only length counting once the verdict is fixed (see
116
- // `isSettled`: a magic match settles it immediately, a dead magic once utf8 fails).
55
+ // The single declaration of what a signature is: a byte pattern the eliminator can
56
+ // consume one byte at a time, with `null` for a wildcard byte. Both `detect` and
57
+ // the streaming detector below eliminate against this one list, so a signature is
58
+ // added or corrected in exactly one place.
117
59
 
118
- // The streaming counterpart of `table`/`isWebp`: the same signatures expressed as
119
- // byte patterns the eliminator can consume one byte at a time. WebP's gap is the
120
- // only wildcard run.
121
60
  /** @type {readonly _Signature[]} */
122
61
  const signatures = [
123
62
  { pattern: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], mime: 'image/png' },
124
63
  { pattern: [0xff, 0xd8, 0xff], mime: 'image/jpeg' },
64
+ // Match the full GIF version headers ("GIF87a" / "GIF89a"), not just "GIF8",
65
+ // so opaque bytes that merely start with "GIF8" are not mistyped.
125
66
  { pattern: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], mime: 'image/gif' },
126
67
  { pattern: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], mime: 'image/gif' },
127
68
  { pattern: [0x25, 0x50, 0x44, 0x46, 0x2d], mime: 'application/pdf' },
69
+ // ZIP has three "PK" local-header variants: a normal entry, an empty
70
+ // archive (end-of-central-directory only), and a spanned archive.
128
71
  { pattern: [0x50, 0x4b, 0x03, 0x04], mime: 'application/zip' },
129
72
  { pattern: [0x50, 0x4b, 0x05, 0x06], mime: 'application/zip' },
130
73
  { pattern: [0x50, 0x4b, 0x07, 0x08], mime: 'application/zip' },
74
+ // WebP: "RIFF" at offset 0, "WEBP" at offset 8; the four bytes between are
75
+ // the little-endian file size, matched as wildcards.
131
76
  {
132
77
  pattern: [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50],
133
78
  mime: 'image/webp',
@@ -154,6 +99,52 @@ const magicStep = (m, byte) => {
154
99
  /** @type {(m: _MagicState) => Nullable<string>} */
155
100
  const magicMime = m => m.tag === 'matched' ? m.mime : null
156
101
 
102
+ /**
103
+ * Detects the MIME type of `bytes` from its leading magic-byte signature, as
104
+ * the magic projection of the streaming detector below — one fold, read two
105
+ * ways, rather than a second copy of it.
106
+ *
107
+ * The two agree because `magicStep` returns a non-`scan` state unchanged, so
108
+ * both absorbing states are its fixed points. `detect`'s old loop stopped at
109
+ * the first one; `push` stops only once the *whole* verdict is settled and may
110
+ * keep folding for the UTF-8 factor after the magic state is `dead` — but a
111
+ * `dead` or `matched` magic cannot move again, so the final magic is the same
112
+ * either way. A signature still in `scan` at the end of the `Vec` — a prefix
113
+ * too short to complete any signature — reads as `null`.
114
+ *
115
+ * Cost follows `push`, which stops only once the whole verdict is settled, not
116
+ * once the magic state is. On a signature match or on non-text bytes that is
117
+ * still an early exit; on valid text it now reads the whole `Vec`, because the
118
+ * shared machine is still tracking the UTF-8 factor this function ignores
119
+ * (measured: 100 KB of ASCII, 1.2 ms before, 82 ms after). That is the same
120
+ * work {@link detectVec} already does on the same bytes, and `Vec` is capped at
121
+ * `maxLength`, so the cost is bounded rather than unbounded — but a caller
122
+ * scanning many large text blobs for signatures alone should know it is paying
123
+ * for the UTF-8 fold too.
124
+ *
125
+ * The bytes come from `u8List`, so a `Vec` whose length is not a whole number of
126
+ * bytes has its trailing partial byte zero-padded — the same reading of a ragged
127
+ * `Vec` the streaming detector already uses.
128
+ *
129
+ * @returns the MIME type string for a recognized format, or `null` when the
130
+ * leading bytes match no known signature (including any `Vec` shorter than
131
+ * the signature it might otherwise match).
132
+ *
133
+ * @type {(bytes: Vec) => Nullable<string>}
134
+ */
135
+ export const detect = bytes => magicMime(push(detectInit)(bytes).magic)
136
+
137
+ // ── Streaming detector ────────────────────────────────────────────────────────────
138
+ //
139
+ // A byte-accepting state machine that derives the same `{ length, mime_type, type }`
140
+ // metadata as the pure `detect` + UTF-8 path, but **without buffering the blob**.
141
+ // It is the product of three independent folds over the byte stream — length,
142
+ // magic-byte signature elimination, and a UTF-8 validity DFA — read off at
143
+ // end-of-stream by `finish`. This lets `cas_get` inspect arbitrarily large blobs
144
+ // (where a single `Vec` would overflow `maxLength`) in O(1) space, since the bulk
145
+ // of a large blob costs only length counting once the verdict is fixed (see
146
+ // `isSettled`: a magic match settles it immediately, a dead magic once utf8 fails).
147
+
157
148
  /** @type {_Utf8Detect} */
158
149
  const utf8Init = { st: null, valid: true, text: true }
159
150
 
@@ -258,24 +249,23 @@ export const detectVec = bytes => finish(push(detectInit)(bytes))
258
249
 
259
250
  /**
260
251
  * Folds a CAS read stream through {@link push} and reads {@link finish} at EOF,
261
- * deriving `cas_get` metadata without ever materializing the blob. A read `error`
262
- * item short-circuits into the `IoResult` error.
252
+ * deriving `cas_get` metadata without ever materializing the blob. A stream that
253
+ * fails carries its failure out as this one's, through `step` rather than
254
+ * through a case in the loop.
263
255
  *
264
256
  * @template {Operation} O
265
- * @param {List<O, IoResult<Vec>>} stream
266
- * @returns {Effect<O, IoResult<DetectMeta>>}
257
+ * @param {List<O, Vec, IoChannel>} stream
258
+ * @returns {Effect<O, DetectMeta, IoChannel>}
267
259
  */
268
260
  export const detectStream = stream => {
269
- /** @type {(s: DetectState) => (l: List<O, IoResult<Vec>>) => Effect<O, IoResult<DetectMeta>>} */
261
+ /** @type {(s: DetectState) => (l: List<O, Vec, IoChannel>) => Effect<O, DetectMeta, IoChannel>} */
270
262
  const loop = s => l =>
271
- step(
263
+ ioStep(
272
264
  l,
273
265
  node => {
274
- if (node === undefined) { return pure(ok(finish(s))) }
266
+ if (node === undefined) { return pureOk(finish(s)) }
275
267
  const { first, tail } = node
276
- const [t, v] = first
277
- if (t === 'error') { return pure(error(v)) }
278
- return loop(push(s)(v))(tail)
268
+ return loop(push(s)(first))(tail)
279
269
  })
280
270
  return loop(detectInit)(stream)
281
271
  }
@@ -1,3 +1,9 @@
1
+ /**
2
+ * @import { Vec } from '../../types/bit_vec/types.ts'
3
+ * @import { List } from '../../effects/list/types.ts'
4
+ * @import { IoChannel } from '../../effects/node/types.ts'
5
+ * @import { DetectMeta } from './types.ts'
6
+ */
1
7
  export declare const proof: {
2
8
  png: () => void;
3
9
  jpeg: () => void;
@@ -7,11 +13,22 @@ export declare const proof: {
7
13
  pdf: () => void;
8
14
  zip: () => void;
9
15
  emptyZip: () => void;
16
+ spannedZip: () => void;
10
17
  webp: () => void;
11
18
  riffNotWebp: () => void;
19
+ settledMagicIsAFixedPoint: (() => void)[];
12
20
  textIsNull: () => void;
13
21
  shortIsNull: () => void;
14
22
  emptyIsNull: () => void;
23
+ truncated: {
24
+ png: () => void;
25
+ jpeg: () => void;
26
+ gif87a: () => void;
27
+ gif89a: () => void;
28
+ pdf: () => void;
29
+ zip: () => void;
30
+ webp: () => void;
31
+ };
15
32
  stream: {
16
33
  text: () => void;
17
34
  png: () => void;