functionalscript 0.45.0 → 0.46.1

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 (296) 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 +10 -0
  4. package/fjs/asn.1/proof.f.mjs +16 -0
  5. package/fjs/basen/base128/module.f.mjs +22 -5
  6. package/fjs/bnf/data/module.f.d.mts +32 -6
  7. package/fjs/bnf/data/module.f.mjs +112 -7
  8. package/fjs/bnf/data/proof.f.d.mts +2 -0
  9. package/fjs/bnf/data/proof.f.mjs +74 -3
  10. package/fjs/bnf/data/types.d.ts +20 -2
  11. package/fjs/bnf/descent/module.f.d.mts +28 -14
  12. package/fjs/bnf/descent/module.f.mjs +122 -77
  13. package/fjs/bnf/descent/proof.f.d.mts +2 -0
  14. package/fjs/bnf/descent/proof.f.mjs +117 -31
  15. package/fjs/bnf/descent/types.d.ts +12 -14
  16. package/fjs/bnf/ll1/module.f.d.mts +64 -22
  17. package/fjs/bnf/ll1/module.f.mjs +214 -154
  18. package/fjs/bnf/ll1/proof.f.d.mts +15 -2
  19. package/fjs/bnf/ll1/proof.f.mjs +323 -149
  20. package/fjs/bnf/ll1/types.d.ts +16 -24
  21. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  22. package/fjs/bnf/matcher/module.f.mjs +81 -0
  23. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  24. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  25. package/fjs/bnf/matcher/types.d.ts +54 -0
  26. package/fjs/bnf/testlib.f.d.mts +31 -0
  27. package/fjs/bnf/testlib.f.mjs +80 -0
  28. package/fjs/cas/cli/module.f.d.mts +1 -1
  29. package/fjs/cas/cli/module.f.mjs +14 -20
  30. package/fjs/cas/cli/proof.f.d.mts +1 -3
  31. package/fjs/cas/cli/proof.f.mjs +44 -33
  32. package/fjs/cas/evo/module.f.d.mts +64 -18
  33. package/fjs/cas/evo/module.f.mjs +148 -70
  34. package/fjs/cas/evo/proof.f.d.mts +10 -1
  35. package/fjs/cas/evo/proof.f.mjs +305 -223
  36. package/fjs/cas/evo/types.d.ts +45 -9
  37. package/fjs/cas/module.f.d.mts +18 -32
  38. package/fjs/cas/module.f.mjs +129 -128
  39. package/fjs/cas/proof.f.d.mts +11 -8
  40. package/fjs/cas/proof.f.mjs +259 -147
  41. package/fjs/cas/types.d.ts +24 -10
  42. package/fjs/ci/config/module.f.d.mts +2 -2
  43. package/fjs/ci/config/module.f.mjs +2 -2
  44. package/fjs/ci/module.f.d.mts +5 -5
  45. package/fjs/ci/module.f.mjs +8 -7
  46. package/fjs/ci/nix/module.f.d.mts +7 -5
  47. package/fjs/ci/nix/module.f.mjs +13 -12
  48. package/fjs/ci/nix/proof.f.mjs +2 -2
  49. package/fjs/ci/proof.f.mjs +9 -5
  50. package/fjs/cli/module.f.d.mts +4 -6
  51. package/fjs/cli/module.f.mjs +4 -8
  52. package/fjs/cli/proof.f.mjs +17 -16
  53. package/fjs/cli/types.d.ts +2 -3
  54. package/fjs/common/monoid/types.d.ts +1 -1
  55. package/fjs/crypto/hmac/module.f.mjs +2 -2
  56. package/fjs/crypto/sha2/module.f.mjs +3 -1
  57. package/fjs/crypto/sha2/proof.f.d.mts +1 -0
  58. package/fjs/crypto/sha2/proof.f.mjs +24 -0
  59. package/fjs/crypto/sha2/types.d.ts +11 -0
  60. package/fjs/crypto/sign/module.f.mjs +2 -2
  61. package/fjs/dev/module.f.d.mts +13 -4
  62. package/fjs/dev/module.f.mjs +56 -27
  63. package/fjs/dev/update/module.f.d.mts +9 -4
  64. package/fjs/dev/update/module.f.mjs +14 -10
  65. package/fjs/dev/update/proof.f.d.mts +1 -3
  66. package/fjs/dev/update/proof.f.mjs +10 -5
  67. package/fjs/djs/module.f.d.mts +13 -5
  68. package/fjs/djs/module.f.mjs +31 -16
  69. package/fjs/djs/parser/module.f.d.mts +13 -3
  70. package/fjs/djs/parser/module.f.mjs +117 -16
  71. package/fjs/djs/parser/proof.f.d.mts +5 -1
  72. package/fjs/djs/parser/proof.f.mjs +274 -12
  73. package/fjs/djs/parser/types.d.ts +7 -1
  74. package/fjs/djs/proof.f.d.mts +18 -2
  75. package/fjs/djs/proof.f.mjs +187 -12
  76. package/fjs/djs/serializer/module.f.d.mts +25 -8
  77. package/fjs/djs/serializer/module.f.mjs +61 -15
  78. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  79. package/fjs/djs/serializer/proof.f.mjs +23 -1
  80. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  81. package/fjs/djs/tokenizer/module.f.mjs +99 -60
  82. package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
  83. package/fjs/djs/tokenizer/proof.f.mjs +74 -67
  84. package/fjs/djs/transpiler/module.f.d.mts +12 -7
  85. package/fjs/djs/transpiler/module.f.mjs +82 -56
  86. package/fjs/djs/transpiler/types.d.ts +7 -3
  87. package/fjs/djs/types.d.ts +7 -1
  88. package/fjs/effects/list/module.f.d.mts +14 -11
  89. package/fjs/effects/list/module.f.mjs +13 -11
  90. package/fjs/effects/list/types.d.ts +27 -7
  91. package/fjs/effects/memory/module.f.d.mts +2 -1
  92. package/fjs/effects/memory/module.f.mjs +3 -4
  93. package/fjs/effects/memory/proof.f.mjs +13 -7
  94. package/fjs/effects/memory/types.d.ts +4 -3
  95. package/fjs/effects/mock/module.f.d.mts +20 -4
  96. package/fjs/effects/mock/module.f.mjs +37 -5
  97. package/fjs/effects/mock/types.d.ts +10 -1
  98. package/fjs/effects/module.d.mts +4 -2
  99. package/fjs/effects/module.f.d.mts +466 -280
  100. package/fjs/effects/module.f.mjs +537 -299
  101. package/fjs/effects/module.mjs +2 -1
  102. package/fjs/effects/node/memory/module.d.mts +4 -2
  103. package/fjs/effects/node/memory/module.mjs +6 -3
  104. package/fjs/effects/node/memory/proof.mjs +10 -4
  105. package/fjs/effects/node/module.d.mts +4 -3
  106. package/fjs/effects/node/module.f.d.mts +168 -33
  107. package/fjs/effects/node/module.f.mjs +256 -52
  108. package/fjs/effects/node/module.mjs +57 -34
  109. package/fjs/effects/node/proof.f.d.mts +28 -2
  110. package/fjs/effects/node/proof.f.mjs +161 -42
  111. package/fjs/effects/node/types.d.ts +106 -18
  112. package/fjs/effects/node/virtual/module.f.d.mts +18 -4
  113. package/fjs/effects/node/virtual/module.f.mjs +110 -68
  114. package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
  115. package/fjs/effects/node/virtual/proof.f.mjs +190 -9
  116. package/fjs/effects/proof.f.d.mts +69 -37
  117. package/fjs/effects/proof.f.mjs +410 -130
  118. package/fjs/effects/types.d.ts +161 -33
  119. package/fjs/emergent_testing/module.f.d.mts +19 -12
  120. package/fjs/emergent_testing/module.f.mjs +93 -33
  121. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  122. package/fjs/emergent_testing/proof.f.mjs +166 -32
  123. package/fjs/emergent_testing/types.d.ts +22 -4
  124. package/fjs/fsm/module.f.d.mts +14 -4
  125. package/fjs/fsm/module.f.mjs +54 -37
  126. package/fjs/fsm/proof.f.d.mts +2 -0
  127. package/fjs/fsm/proof.f.mjs +83 -114
  128. package/fjs/js/keywords/module.f.d.mts +52 -0
  129. package/fjs/js/keywords/module.f.mjs +72 -0
  130. package/fjs/js/keywords/proof.f.d.mts +3 -0
  131. package/fjs/js/keywords/proof.f.mjs +13 -0
  132. package/fjs/js/tokenizer/module.f.d.mts +26 -6
  133. package/fjs/js/tokenizer/module.f.mjs +145 -159
  134. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  135. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  136. package/fjs/js/tokenizer/types.d.ts +33 -24
  137. package/fjs/mcp/cas/module.f.d.mts +1 -6
  138. package/fjs/mcp/cas/module.f.mjs +55 -51
  139. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  140. package/fjs/mcp/cas/proof.f.mjs +174 -0
  141. package/fjs/mcp/evo/module.f.d.mts +19 -10
  142. package/fjs/mcp/evo/module.f.mjs +48 -27
  143. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  144. package/fjs/mcp/evo/proof.f.mjs +115 -31
  145. package/fjs/mcp/module.f.d.mts +4 -4
  146. package/fjs/mcp/module.f.mjs +6 -6
  147. package/fjs/mcp/proof.f.d.mts +5 -3
  148. package/fjs/mcp/proof.f.mjs +112 -46
  149. package/fjs/media/html/module.f.mjs +1 -1
  150. package/fjs/media/json/extended/module.f.d.mts +82 -0
  151. package/fjs/media/json/extended/module.f.mjs +153 -0
  152. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  153. package/fjs/media/json/extended/proof.f.mjs +127 -0
  154. package/fjs/media/json/extended/types.d.ts +23 -0
  155. package/fjs/media/json/module.f.d.mts +8 -2
  156. package/fjs/media/json/module.f.mjs +43 -41
  157. package/fjs/media/json/number/module.f.d.mts +59 -0
  158. package/fjs/media/json/number/module.f.mjs +136 -0
  159. package/fjs/media/json/number/proof.f.d.mts +24 -0
  160. package/fjs/media/json/number/proof.f.mjs +86 -0
  161. package/fjs/media/json/number/types.d.ts +28 -0
  162. package/fjs/media/json/parser/module.f.d.mts +25 -13
  163. package/fjs/media/json/parser/module.f.mjs +114 -70
  164. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  165. package/fjs/media/json/parser/proof.f.mjs +31 -1
  166. package/fjs/media/json/parser/types.d.ts +33 -14
  167. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  168. package/fjs/media/json/rtti/module.f.mjs +1 -1
  169. package/fjs/media/json/rtti/proof.f.mjs +9 -9
  170. package/fjs/media/json/schema/module.f.mjs +3 -13
  171. package/fjs/media/json/schema/proof.f.d.mts +0 -1
  172. package/fjs/media/json/schema/proof.f.mjs +1 -2
  173. package/fjs/media/json/serializer/module.f.d.mts +32 -1
  174. package/fjs/media/json/serializer/module.f.mjs +64 -2
  175. package/fjs/media/json/tokenizer/module.f.mjs +7 -3
  176. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  177. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  178. package/fjs/media/json/types.d.ts +36 -10
  179. package/fjs/media/lock/module.f.d.mts +100 -0
  180. package/fjs/media/lock/module.f.mjs +125 -0
  181. package/fjs/media/lock/proof.f.d.mts +33 -0
  182. package/fjs/media/lock/proof.f.mjs +196 -0
  183. package/fjs/media/lock/types.d.ts +15 -0
  184. package/fjs/media/module.f.d.mts +6 -5
  185. package/fjs/media/module.f.mjs +8 -7
  186. package/fjs/media/note/module.f.d.mts +121 -0
  187. package/fjs/media/note/module.f.mjs +131 -0
  188. package/fjs/media/note/proof.f.d.mts +29 -0
  189. package/fjs/media/note/proof.f.mjs +150 -0
  190. package/fjs/media/note/types.d.ts +10 -0
  191. package/fjs/media/proof.f.d.mts +4 -1
  192. package/fjs/media/proof.f.mjs +40 -21
  193. package/fjs/media/revision/module.f.d.mts +78 -7
  194. package/fjs/media/revision/module.f.mjs +119 -12
  195. package/fjs/media/revision/proof.f.d.mts +10 -0
  196. package/fjs/media/revision/proof.f.mjs +88 -0
  197. package/fjs/media/revision/types.d.ts +34 -5
  198. package/fjs/media/type/module.f.d.mts +33 -15
  199. package/fjs/media/type/module.f.mjs +35 -29
  200. package/fjs/media/type/proof.f.d.mts +2 -1
  201. package/fjs/media/type/proof.f.mjs +30 -10
  202. package/fjs/module.f.mjs +29 -8
  203. package/fjs/nanvm/proof.f.mjs +3 -3
  204. package/fjs/nanvm/rust/module.f.mjs +1 -1
  205. package/fjs/nanvm/update/module.f.d.mts +4 -4
  206. package/fjs/nanvm/update/module.f.mjs +8 -9
  207. package/fjs/nanvm/update/proof.f.mjs +4 -3
  208. package/fjs/proof.f.d.mts +3 -3
  209. package/fjs/proof.f.mjs +36 -10
  210. package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
  211. package/fjs/protocol/json_rpc/module.f.mjs +3 -3
  212. package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
  213. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  214. package/fjs/protocol/mcp/module.f.mjs +74 -58
  215. package/fjs/protocol/mcp/proof.f.d.mts +13 -4
  216. package/fjs/protocol/mcp/proof.f.mjs +193 -61
  217. package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
  218. package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
  219. package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
  220. package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
  221. package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
  222. package/fjs/protocol/mcp/types.d.ts +17 -6
  223. package/fjs/sul/id/module.f.d.mts +0 -1
  224. package/fjs/sul/id/module.f.mjs +2 -3
  225. package/fjs/sul/level/hash/module.f.mjs +2 -1
  226. package/fjs/sul/level/hash/proof.f.mjs +2 -2
  227. package/fjs/sul/module.f.mjs +18 -13
  228. package/fjs/text/code_point/module.f.d.mts +8 -0
  229. package/fjs/text/code_point/module.f.mjs +8 -1
  230. package/fjs/text/code_point/proof.f.d.mts +1 -0
  231. package/fjs/text/code_point/proof.f.mjs +11 -0
  232. package/fjs/text/sgr/module.f.d.mts +4 -6
  233. package/fjs/text/sgr/module.f.mjs +6 -7
  234. package/fjs/text/utf16/module.f.mjs +7 -2
  235. package/fjs/text/utf16/proof.f.mjs +3 -3
  236. package/fjs/text/utf8/module.f.mjs +4 -2
  237. package/fjs/types/array/module.f.mjs +14 -2
  238. package/fjs/types/bit_vec/module.f.d.mts +0 -2
  239. package/fjs/types/bit_vec/module.f.mjs +46 -32
  240. package/fjs/types/bit_vec/proof.f.mjs +2 -2
  241. package/fjs/types/btree/remove/module.f.mjs +1 -1
  242. package/fjs/types/btree/set/module.f.mjs +9 -11
  243. package/fjs/types/btree/set/proof.f.mjs +12 -0
  244. package/fjs/types/byte_set/module.f.d.mts +11 -4
  245. package/fjs/types/byte_set/module.f.mjs +14 -6
  246. package/fjs/types/byte_set/proof.f.mjs +7 -7
  247. package/fjs/types/function/compare/module.f.mjs +10 -3
  248. package/fjs/types/list/module.f.d.mts +1 -1
  249. package/fjs/types/list/module.f.mjs +1 -1
  250. package/fjs/types/nullable/module.f.d.mts +18 -4
  251. package/fjs/types/nullable/module.f.mjs +21 -4
  252. package/fjs/types/nullable/proof.f.d.mts +4 -0
  253. package/fjs/types/nullable/proof.f.mjs +15 -0
  254. package/fjs/types/object/module.f.d.mts +12 -2
  255. package/fjs/types/object/module.f.mjs +11 -1
  256. package/fjs/types/patricia_trie/module.f.mjs +26 -11
  257. package/fjs/types/result/module.f.d.mts +3 -3
  258. package/fjs/types/result/module.f.mjs +3 -3
  259. package/fjs/types/rtti/common/module.f.d.mts +25 -28
  260. package/fjs/types/rtti/common/module.f.mjs +36 -32
  261. package/fjs/types/rtti/common/proof.f.mjs +5 -5
  262. package/fjs/types/rtti/data/module.f.d.mts +14 -0
  263. package/fjs/types/rtti/data/module.f.mjs +25 -2
  264. package/fjs/types/rtti/data/proof.f.d.mts +1 -0
  265. package/fjs/types/rtti/data/proof.f.mjs +25 -2
  266. package/fjs/types/rtti/parse/module.f.d.mts +24 -14
  267. package/fjs/types/rtti/parse/module.f.mjs +37 -28
  268. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  269. package/fjs/types/rtti/parse/proof.f.mjs +33 -14
  270. package/fjs/types/rtti/proof.f.mjs +3 -1
  271. package/fjs/types/rtti/ts/module.f.mjs +13 -17
  272. package/fjs/types/rtti/ts/types.d.ts +14 -1
  273. package/fjs/types/rtti/validate/module.f.d.mts +81 -19
  274. package/fjs/types/rtti/validate/module.f.mjs +107 -61
  275. package/fjs/types/rtti/validate/proof.f.d.mts +13 -10
  276. package/fjs/types/rtti/validate/proof.f.mjs +186 -197
  277. package/fjs/types/sorted_set/module.f.d.mts +18 -0
  278. package/fjs/types/sorted_set/module.f.mjs +22 -0
  279. package/fjs/types/sorted_set/proof.f.d.mts +1 -0
  280. package/fjs/types/sorted_set/proof.f.mjs +16 -1
  281. package/fjs/types/uint8array/module.f.d.mts +1 -1
  282. package/fjs/types/uint8array/module.f.mjs +1 -1
  283. package/fjs/website/module.f.d.mts +3 -3
  284. package/fjs/website/module.f.mjs +4 -7
  285. package/fjs/website/proof.f.mjs +2 -1
  286. package/package.json +2 -2
  287. package/fjs/dev/package_json/module.f.d.mts +0 -39
  288. package/fjs/dev/package_json/module.f.mjs +0 -40
  289. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  290. package/fjs/dev/package_json/proof.f.mjs +0 -32
  291. package/fjs/effects/eff/module.f.d.mts +0 -20
  292. package/fjs/effects/eff/module.f.mjs +0 -70
  293. package/fjs/effects/eff/proof.f.d.mts +0 -15
  294. package/fjs/effects/eff/proof.f.mjs +0 -69
  295. package/fjs/effects/eff/types.d.ts +0 -71
  296. package/fjs/types/rtti/validate/types.d.ts +0 -6
@@ -2,6 +2,7 @@
2
2
  * @import { NodeProgramOptions } from '../../effects/node/types.ts'
3
3
  */
4
4
 
5
+ import { exitCode } from '../../effects/node/module.f.mjs'
5
6
  import { commands } from './module.f.mjs'
6
7
  import { computeSync, sha256 } from '../../crypto/sha2/module.f.mjs'
7
8
  import { maxLength, vec, vec8 } from '../../types/bit_vec/module.f.mjs'
@@ -20,8 +21,8 @@ export const proof = {
20
21
  mainAdd: () => {
21
22
  const content = vec8(0x2An)
22
23
  const state = { ...emptyState, root: { myfile: [content] } }
23
- const [finalState, exitCode] = virtual(state)(main(makeOptions(['add', 'myfile'])))
24
- assertEq(exitCode, 0, ['expected exit 0', exitCode])
24
+ const [finalState, code] = virtual(state)(main(makeOptions(['add', 'myfile'])))
25
+ assertEq(exitCode(code), 0, ['expected exit 0', code])
25
26
  assert(finalState.stdout.length !== 0, 'expected hash in stdout')
26
27
  },
27
28
  mainAddGetBig: () => {
@@ -29,8 +30,8 @@ export const proof = {
29
30
  const content = [chunk, chunk]
30
31
  const state = { ...emptyState, root: { myfile: content } }
31
32
  //
32
- const [finalState, exitCode] = virtual(state)(main(makeOptions(['add', 'myfile'])))
33
- assertEq(exitCode, 0)
33
+ const [finalState, code] = virtual(state)(main(makeOptions(['add', 'myfile'])))
34
+ assertEq(exitCode(code), 0)
34
35
  const stdout = finalState.stdout
35
36
  assert(stdout.length !== 0)
36
37
  //
@@ -40,32 +41,33 @@ export const proof = {
40
41
  //
41
42
  const [finalState2, exitCode2] = virtual(finalState)(main(makeOptions(['get', hs, 'myfile2'])))
42
43
  // console.log(finalState2.stderr)
43
- assertEq(exitCode2, 0, 'e2')
44
+ assertEq(exitCode(exitCode2), 0, 'e2')
44
45
  const { myfile2 } = finalState2.root
45
46
  assert(myfile2 instanceof Array)
46
47
  const h2 = computeSync(sha256)(myfile2)
47
48
  assertEq(h, h2, 'h')
48
49
  },
49
50
  mainAddWrongArgs: () => {
50
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['add'])))
51
- assertEq(exitCode, 1)
51
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['add'])))
52
+ assertEq(exitCode(code), 1)
52
53
  assert(finalState.stderr.length !== 0)
53
54
  },
54
55
  mainAddMissingFile: () => {
55
- // The source path doesn't exist, so `streamFile`'s first read comes back as an
56
- // error item; `write` fails closed with that error and the handler exits 1
57
- // without ever calling `log` — covers the `hashResult[0] === 'error'` branch.
58
- const [, exitCode] = virtual(emptyState)(main(makeOptions(['add', 'missing'])))
59
- assertEq(exitCode, 1)
56
+ // The source path doesn't exist, so `streamFile`'s first read comes back as a
57
+ // stream failure; `write` fails closed with that error and the handler exits 1
58
+ // without ever calling `log` — covers `exitStep`'s error branch.
59
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['add', 'missing'])))
60
+ assertEq(exitCode(code), 1)
61
+ assertEq(finalState.stderr, 'no such file or directory\n', finalState.stderr)
60
62
  },
61
63
  mainGetFound: () => {
62
64
  const content = vec8(0x2An)
63
65
  const state = { ...emptyState, root: { myfile: [content] } }
64
66
  const [state1, exitCode1] = virtual(state)(main(makeOptions(['add', 'myfile'])))
65
- assertEq(exitCode1, 0, ['expected add exit 0', exitCode1])
67
+ assertEq(exitCode(exitCode1), 0, ['expected add exit 0', exitCode1])
66
68
  const hashStr = state1.stdout.trim()
67
69
  const [, exitCode2] = virtual(state1)(main(makeOptions(['get', hashStr, 'output'])))
68
- assertEq(exitCode2, 0, ['expected get exit 0', exitCode2])
70
+ assertEq(exitCode(exitCode2), 0, ['expected get exit 0', exitCode2])
69
71
  },
70
72
  mainGetNotFound: () => {
71
73
  // valid cBase32 hash that has not been stored
@@ -74,47 +76,56 @@ export const proof = {
74
76
  const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])))
75
77
  const hashStr = state1.stdout.trim()
76
78
  // use an empty store so the hash is not found
77
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', hashStr, 'output'])))
78
- assertEq(exitCode, 1, ['expected exit 1', exitCode])
79
- assert(finalState.stderr.length !== 0, 'expected error in stderr')
79
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['get', hashStr, 'output'])))
80
+ assertEq(exitCode(code), 1, ['expected exit 1', code])
81
+ // The *message*, not just a non-empty line: the failure reaches the user
82
+ // as the host's own words. Asserting only that something was written is
83
+ // what let a stringified error tuple (`ioError,[object Object]`) pass.
84
+ assertEq(finalState.stderr, 'no such file or directory\n', finalState.stderr)
80
85
  },
81
86
  mainGetWrongArgs: () => {
82
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get'])))
83
- assertEq(exitCode, 1, ['expected exit 1', exitCode])
87
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['get'])))
88
+ assertEq(exitCode(code), 1, ['expected exit 1', code])
84
89
  assert(finalState.stderr.length !== 0, 'expected error in stderr')
85
90
  },
86
91
  mainGetInvalidHash: () => {
87
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', 'not-a-valid-hash', 'output'])))
88
- assertEq(exitCode, 1, ['expected exit 1', exitCode])
92
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['get', 'not-a-valid-hash', 'output'])))
93
+ assertEq(exitCode(code), 1, ['expected exit 1', code])
89
94
  assert(finalState.stderr.length !== 0, 'expected error in stderr')
90
95
  },
91
96
  mainList: () => {
92
97
  const content = vec8(0x2An)
93
98
  const state = { ...emptyState, root: { myfile: [content] } }
94
99
  const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])))
95
- const [, exitCode] = virtual(state1)(main(makeOptions(['list'])))
96
- assertEq(exitCode, 0, ['expected exit 0', exitCode])
100
+ const [, code] = virtual(state1)(main(makeOptions(['list'])))
101
+ assertEq(exitCode(code), 0, ['expected exit 0', code])
97
102
  },
98
103
  mainListEmptyStore: () => {
99
104
  // A fresh directory has no `.cas` yet; listing must succeed (empty),
100
105
  // not crash unwrapping a readdir ENOENT.
101
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['list'])))
102
- assertEq(exitCode, 0, ['expected exit 0', exitCode])
106
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['list'])))
107
+ assertEq(exitCode(code), 0, ['expected exit 0', code])
103
108
  assertEq(finalState.stdout, '', ['expected empty stdout', finalState.stdout])
104
109
  },
105
110
  mainNoCmd: () => {
106
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions([])))
107
- assertEq(exitCode, 1, ['expected exit 1', exitCode])
111
+ const [finalState, code] = virtual(emptyState)(main(makeOptions([])))
112
+ assertEq(exitCode(code), 1, ['expected exit 1', code])
108
113
  assert(finalState.stderr.length !== 0, 'expected error in stderr')
109
114
  },
110
115
  mainUnknownCmd: () => {
111
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['bogus'])))
112
- assertEq(exitCode, 1, ['expected exit 1', exitCode])
116
+ const [finalState, code] = virtual(emptyState)(main(makeOptions(['bogus'])))
117
+ assertEq(exitCode(code), 1, ['expected exit 1', code])
113
118
  assert(finalState.stderr.length !== 0, 'expected error in stderr')
114
119
  },
115
- throw: {
116
- // `.cas` exists but is a file, not a directory: a real storage error
117
- // that must surface, not be masked as an empty list.
118
- mainListCorruptStore: () => virtual({ ...emptyState, root: { '.cas': [vec8(0x2An)] } })(main(makeOptions(['list']))),
120
+ // `.cas` exists but is a file, not a directory: a real storage error that
121
+ // must surface, not be masked as an empty list. It is no longer a panic
122
+ // either `list` answers with the error and the CLI reports it on stderr
123
+ // and exits 1, which is why this is an ordinary proof rather than a
124
+ // `throw` one.
125
+ mainListCorruptStore: () => {
126
+ const [state, code] = virtual({ ...emptyState, root: { '.cas': [vec8(0x2An)] } })(main(makeOptions(['list'])))
127
+ assertEq(exitCode(code), 1)
128
+ assert(state.stderr !== '', ['expected the storage error reported on stderr', state.stderr])
129
+ assertEq(state.stdout, '')
119
130
  },
120
131
  }
@@ -42,24 +42,49 @@
42
42
  *
43
43
  * @module
44
44
  *
45
- * @import { Effect, Operation } from '../../effects/types.ts'
45
+ * @import { Operation } from '../../effects/types.ts'
46
+ * @import { Effect, NotImplemented } from '../../effects/types.ts'
47
+ * @import { EvoChannel, EvoError } from './types.ts'
46
48
  * @import { Key, MemOp } from '../../effects/memory/types.ts'
47
49
  * @import { Cas } from '../types.ts'
48
- * @import { Ok, Result } from '../../types/result/types.ts'
50
+ * @import { Result } from '../../types/result/types.ts'
49
51
  * @import { Vec } from '../../types/bit_vec/types.ts'
50
- * @import { IoResult } from '../../effects/node/types.ts'
52
+ * @import { Ok } from '../../types/result/types.ts'
51
53
  * @import { List } from '../../effects/list/types.ts'
52
- * @import { LockMap, Revision } from '../../media/revision/types.ts'
54
+ * @import { IoChannel, IoResult } from '../../effects/node/types.ts'
55
+ * @import { LockField, LockMap, Revision } from '../../media/revision/types.ts'
53
56
  * @import { Hash, Subject, RevisionData, SubjectState, Cache, Evo } from './types.ts'
54
57
  */
55
- import type { Effect, Operation } from '../../effects/types.ts';
58
+ import type { Operation } from '../../effects/types.ts';
59
+ import type { Effect, NotImplemented } from '../../effects/types.ts';
60
+ import type { EvoChannel, EvoError } from './types.ts';
56
61
  import type { Key, MemOp } from '../../effects/memory/types.ts';
57
62
  import type { Cas } from '../types.ts';
58
- import type { Result } from '../../types/result/types.ts';
59
63
  import type { Vec } from '../../types/bit_vec/types.ts';
64
+ import type { IoChannel } from '../../effects/node/types.ts';
60
65
  import type { Revision } from '../../media/revision/types.ts';
61
66
  import type { Hash, RevisionData, Cache, Evo } from './types.ts';
67
+ /**
68
+ * A rejected revision, tagged so it renders alongside `notImplemented` and
69
+ * `ioError` rather than needing a `typeof` test to be told from them.
70
+ *
71
+ * @type {(message: string) => EvoError}
72
+ */
73
+ export declare const evoError: (message: string) => EvoError;
74
+ /**
75
+ * Renders an {@link EvoChannel} failure as a message.
76
+ *
77
+ * The two cases are told apart by tag and nothing else — which is the whole
78
+ * reason {@link EvoError} is a tuple. A rejected revision already carries a
79
+ * message written for a caller; a runner that could not dispatch is described
80
+ * by `errorSummary`, the same renderer the node channel uses, so there is one
81
+ * phrasing of "operation not implemented" rather than two.
82
+ *
83
+ * @type {(e: EvoChannel) => string}
84
+ */
85
+ export declare const evoSummary: (e: EvoChannel) => string;
62
86
  /** A cache with no known subjects yet — the starting point for {@link buildCache}. */
87
+ /** @type {Cache} */
63
88
  export declare const emptyCache: Cache;
64
89
  /**
65
90
  * Decodes already-read bytes as a `vnd.fjs.revision`. Returns `null` for
@@ -77,26 +102,37 @@ export declare const decodeRevisionVec: (value: Vec) => Revision | null;
77
102
  *
78
103
  * @template {Operation} O
79
104
  * @param {Cas<O>} cas
80
- * @returns {(hash: Vec) => Effect<O, Revision | null>}
105
+ * The `never` is a decision, not an observation: reading the store *can* fail,
106
+ * and this maps that failure to `null` alongside "the bytes are not a
107
+ * revision". A scan wants exactly that — one unreadable blob must not fail the
108
+ * whole cache build — but the two are genuinely different answers, and this
109
+ * one loses the difference on purpose. Saying `never` puts that where a reader
110
+ * can disagree with it.
111
+ *
112
+ * @returns {(hash: Vec) => Effect<O, Revision | null, never>}
81
113
  */
82
- export declare const decodeRevisionBlob: <O extends Operation>(cas: Cas<O>) => (hash: Vec) => Effect<O, Revision | null>;
114
+ export declare const decodeRevisionBlob: <O extends Operation>(cas: Cas<O>) => (hash: Vec) => Effect<O, Revision | null, never>;
83
115
  /**
84
116
  * Scans every hash in `cas` and builds a fresh {@link Cache} from the
85
117
  * `vnd.fjs.revision` blobs found among them. Non-revision blobs are ignored.
86
118
  *
119
+ * A store that cannot be listed is a failure of the scan, not an empty cache:
120
+ * the fold never starts, and the caller is told. Blobs that fail to *read*
121
+ * remain "not a revision" and are skipped — see {@link decodeRevisionBlob}.
122
+ *
87
123
  * @template {Operation} O
88
124
  * @param {Cas<O>} cas
89
- * @returns {Effect<O, Cache>}
125
+ * @returns {Effect<O, Cache, IoChannel>}
90
126
  */
91
- export declare const buildCache: <O extends Operation>(cas: Cas<O>) => Effect<O, Cache>;
127
+ export declare const buildCache: <O extends Operation>(cas: Cas<O>) => Effect<O, Cache, IoChannel>;
92
128
  /**
93
129
  * Scans `cas` once and allocates a memory slot holding the resulting {@link Cache}.
94
130
  *
95
131
  * @template {Operation} O
96
132
  * @param {Cas<O>} cas
97
- * @returns {Effect<O | MemOp, Key<Cache>>}
133
+ * @returns {Effect<O | MemOp, Key<Cache>, IoChannel>}
98
134
  */
99
- export declare const initEvo: <O extends Operation>(cas: Cas<O>) => Effect<O | MemOp, Key<Cache>>;
135
+ export declare const initEvo: <O extends Operation>(cas: Cas<O>) => Effect<O | MemOp, Key<Cache>, IoChannel>;
100
136
  /**
101
137
  * Folds `value` — bytes already written to a `Cas` at `hash` by some other
102
138
  * caller — into the cache at `cacheKey` if it decodes as a `vnd.fjs.revision`
@@ -105,9 +141,9 @@ export declare const initEvo: <O extends Operation>(cas: Cas<O>) => Effect<O | M
105
141
  * call can store a revision blob without going through {@link addRevision},
106
142
  * and this is what keeps the cache honest about it without rescanning the
107
143
  * whole store.
108
- * @type {(cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void>}
144
+ * @type {(cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void, NotImplemented>}
109
145
  */
110
- export declare const syncRevision: (cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void>;
146
+ export declare const syncRevision: (cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void, NotImplemented>;
111
147
  /**
112
148
  * Adds a new revision to `cas` and folds it into the cache at `cacheKey`.
113
149
  *
@@ -126,9 +162,19 @@ export declare const syncRevision: (cacheKey: Key<Cache>) => (hash: Vec) => (val
126
162
  *
127
163
  * @template {Operation} O
128
164
  * @param {Cas<O>} cas
129
- * @returns {(cacheKey: Key<Cache>) => (input: RevisionData) => Effect<O | MemOp, Result<Hash, string>>}
165
+ * A rejected revision and an unreachable cache slot share one channel — see
166
+ * {@link Evo.add} — so every branch below answers `pureError`, and the
167
+ * successful path never re-tests what an earlier step already decided.
168
+ *
169
+ * The `Cas` write is the one place a host failure is *translated* rather than
170
+ * propagated: {@link catchStep} turns any `IoChannel` error into one
171
+ * {@link EvoError}, because a caller of this API has the same recourse to a
172
+ * full disk as to a malformed parent, and the store's own error vocabulary is
173
+ * not part of this contract.
174
+ *
175
+ * @returns {(cacheKey: Key<Cache>) => (input: RevisionData) => Effect<O | MemOp, Hash, EvoChannel>}
130
176
  */
131
- export declare const addRevision: <O extends Operation>(cas: Cas<O>) => (cacheKey: Key<Cache>) => (input: RevisionData) => Effect<O | MemOp, Result<Hash, string>>;
177
+ export declare const addRevision: <O extends Operation>(cas: Cas<O>) => (cacheKey: Key<Cache>) => (input: RevisionData) => Effect<O | MemOp, Hash, EvoChannel>;
132
178
  /**
133
179
  * Reads the revision at `hash`: decoded, validated, and canonicalized
134
180
  * ({@link toRevisionData}). The typed counterpart of a raw `cas.read` — the
@@ -144,9 +190,9 @@ export declare const addRevision: <O extends Operation>(cas: Cas<O>) => (cacheKe
144
190
  *
145
191
  * @template {Operation} O
146
192
  * @param {Cas<O>} cas
147
- * @returns {(hash: Hash) => Effect<O, Result<RevisionData, string>>}
193
+ * @returns {(hash: Hash) => Effect<O, RevisionData, EvoError>}
148
194
  */
149
- export declare const readRevision: <O extends Operation>(cas: Cas<O>) => (hash: Hash) => Effect<O, Result<RevisionData, string>>;
195
+ export declare const readRevision: <O extends Operation>(cas: Cas<O>) => (hash: Hash) => Effect<O, RevisionData, EvoError>;
150
196
  /**
151
197
  * Builds the {@link Evo} API over `cas`, backed by the cache at `cacheKey` (see {@link initEvo}).
152
198
  *