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
@@ -3,12 +3,12 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Access, All, Env, Import, Readdir } from '../effects/node/types.ts'
6
+ * @import { Access, All, Env, Import, IoChannel, Readdir } from '../effects/node/types.ts'
7
7
  * @import { Effect } from '../effects/types.ts'
8
8
  * @import { Dir } from '../effects/node/virtual/types.ts'
9
9
  * @import { Module, ModuleMap, LoadModuleOperations } from './types.ts'
10
10
  */
11
- import type { Env } from '../effects/node/types.ts';
11
+ import type { Env, IoChannel } from '../effects/node/types.ts';
12
12
  import type { Effect } from '../effects/types.ts';
13
13
  import type { ModuleMap, LoadModuleOperations } from './types.ts';
14
14
  /**
@@ -48,12 +48,21 @@ export declare const shouldLoad: (s: string) => boolean;
48
48
  * The result is sorted by path key using `string.cmp` so the order is
49
49
  * deterministic regardless of filesystem traversal order.
50
50
  *
51
- * @type {(env: Env) => Effect<LoadModuleOperations, ModuleMap>}
51
+ * A failure a directory that cannot be listed, a module that will not import
52
+ * — propagates instead of panicking, so the program that asked for the map
53
+ * decides what a partial view of the source tree means for it. Discovery reads
54
+ * the whole tree, and a map missing the file it was asked about is worse than
55
+ * no map at all.
56
+ *
57
+ * @type {(env: Env) => Effect<LoadModuleOperations, ModuleMap, IoChannel>}
52
58
  */
53
- export declare const loadModuleMap: (env: Env) => Effect<LoadModuleOperations, ModuleMap>;
59
+ export declare const loadModuleMap: (env: Env) => Effect<LoadModuleOperations, ModuleMap, IoChannel>;
54
60
  export declare const proof: {
55
61
  isSourceFile: () => void;
56
62
  allFilesFindsFunctionalScript: () => void;
57
63
  allFilesSkipsNodeModules: () => void;
58
64
  loadModuleMapDefaultsToCwdWhenInitCwdUnset: () => void;
65
+ loadModuleMapReportsUnreadableRoot: () => void;
66
+ loadModuleMapReportsUnimportableModule: () => void;
67
+ loadModuleMapStripsInitCwdPrefix: () => void;
59
68
  };
@@ -3,16 +3,16 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Access, All, Env, Import, Readdir } from '../effects/node/types.ts'
6
+ * @import { Access, All, Env, Import, IoChannel, Readdir } from '../effects/node/types.ts'
7
7
  * @import { Effect } from '../effects/types.ts'
8
8
  * @import { Dir } from '../effects/node/virtual/types.ts'
9
9
  * @import { Module, ModuleMap, LoadModuleOperations } from './types.ts'
10
10
  */
11
11
 
12
- import { all, import_, readdir } from '../effects/node/module.f.mjs'
12
+ import { allOk, import_, readdir } from '../effects/node/module.f.mjs'
13
13
  import { cmp as strCmp } from '../types/string/module.f.mjs'
14
14
  import { unwrap } from '../types/result/module.f.mjs'
15
- import { pure, step } from '../effects/module.f.mjs'
15
+ import { mapStep, pureOk, step } from '../effects/module.f.mjs'
16
16
  import { join, relativize, toPosix } from '../path/module.f.mjs'
17
17
  import { assert, assertEq } from '../asserts/module.f.mjs'
18
18
  import { emptyState, virtual } from '../effects/node/virtual/module.f.mjs'
@@ -49,16 +49,16 @@ export const shouldLoad = s =>
49
49
  const isSourceFile = path =>
50
50
  path.endsWith('.js') || path.endsWith('.ts') || path.endsWith('.mts') || path.endsWith('.mjs')
51
51
 
52
- /** @type {(s: string, predicate: (path: string) => boolean) => Effect<Readdir | All, readonly string[]>} */
52
+ /** @type {(s: string, predicate: (path: string) => boolean) => Effect<Readdir | All, readonly string[], IoChannel>} */
53
53
  const allFiles = (s, predicate) => {
54
- /** @type {(p: string) => Effect<Readdir | All, readonly string[]>} */
54
+ /** @type {(p: string) => Effect<Readdir | All, readonly string[], IoChannel>} */
55
55
  const load = p => {
56
- const x0 = step(
56
+ const listed = step(
57
57
  readdir(p, {}),
58
58
  d => {
59
- /** @type {readonly Effect<Readdir | All, readonly string[]>[]} */
59
+ /** @type {readonly Effect<Readdir | All, readonly string[], IoChannel>[]} */
60
60
  let result = []
61
- for (const i of unwrap(d)) {
61
+ for (const i of d) {
62
62
  const { name } = i
63
63
  if (name.startsWith('.')) { continue }
64
64
  const file = join(p, name)
@@ -68,23 +68,19 @@ const allFiles = (s, predicate) => {
68
68
  continue
69
69
  }
70
70
  if (predicate(file)) {
71
- result = [...result, pure([file])]
71
+ result = [...result, pureOk([file])]
72
72
  }
73
73
  }
74
- return all(...result)
74
+ return allOk(...result)
75
75
  })
76
- return step(
77
- x0,
78
- v => pure(v.flat()))
76
+ return mapStep(listed, v => v.flat())
79
77
  }
80
78
  return load(s)
81
79
  }
82
80
 
83
- /** @type {(f: string) => Effect<Access | Import, readonly (readonly [string, Module])[]>} */
81
+ /** @type {(f: string) => Effect<Access | Import, readonly (readonly [string, Module])[], IoChannel>} */
84
82
  const loadFile = f =>
85
- step(
86
- import_(f),
87
- r => pure([/** @type {const} */ ([f, unwrap(r)])]))
83
+ mapStep(import_(f), m => [/** @type {const} */ ([f, m])])
88
84
 
89
85
  const { fromEntries } = Object
90
86
 
@@ -102,7 +98,13 @@ const { fromEntries } = Object
102
98
  * The result is sorted by path key using `string.cmp` so the order is
103
99
  * deterministic regardless of filesystem traversal order.
104
100
  *
105
- * @type {(env: Env) => Effect<LoadModuleOperations, ModuleMap>}
101
+ * A failure a directory that cannot be listed, a module that will not import
102
+ * — propagates instead of panicking, so the program that asked for the map
103
+ * decides what a partial view of the source tree means for it. Discovery reads
104
+ * the whole tree, and a map missing the file it was asked about is worse than
105
+ * no map at all.
106
+ *
107
+ * @type {(env: Env) => Effect<LoadModuleOperations, ModuleMap, IoChannel>}
106
108
  */
107
109
  export const loadModuleMap = env => {
108
110
  const initCwd = env['INIT_CWD']
@@ -112,17 +114,17 @@ export const loadModuleMap = env => {
112
114
  // we should consider optimizing them by ALIQ technique or something similar.
113
115
  // For example, we should be able to write it like `allFiles(s).flatMap(loadFile)`,
114
116
  // then an effect runner can batch all file loading operations together.
115
- const x0 = step(
117
+ const loaded = step(
116
118
  allFiles(s, shouldLoad),
117
- files => all(...files.map(loadFile)))
118
- return step(
119
- x0,
120
- entries => pure(fromEntries(
119
+ files => allOk(...files.map(loadFile)))
120
+ return mapStep(
121
+ loaded,
122
+ entries => fromEntries(
121
123
  entries
122
124
  .flat()
123
125
  .map(([k, v]) => /** @type {const} */ ([relativize(prefix, k), v]))
124
126
  .toSorted(([a], [b]) => strCmp(a)(b))
125
- )))
127
+ ))
126
128
  }
127
129
 
128
130
  export const proof = {
@@ -146,7 +148,7 @@ export const proof = {
146
148
  'd.mjs': [],
147
149
  }
148
150
  const [, result] = virtual({ ...emptyState, root })(allFiles('.', shouldLoad))
149
- assertEq(result.join(','), './a.f.ts,./b.f.mjs,./c.f.mts')
151
+ assertEq(unwrap(result).join(','), './a.f.ts,./b.f.mjs,./c.f.mts')
150
152
  },
151
153
  allFilesSkipsNodeModules: () => {
152
154
  // `node_modules` is skipped without descending into it, even though
@@ -157,7 +159,7 @@ export const proof = {
157
159
  'a.f.ts': [],
158
160
  }
159
161
  const [, result] = virtual({ ...emptyState, root })(allFiles('.', shouldLoad))
160
- assertEq(result.join(','), './a.f.ts')
162
+ assertEq(unwrap(result).join(','), './a.f.ts')
161
163
  },
162
164
  loadModuleMapDefaultsToCwdWhenInitCwdUnset: () => {
163
165
  // With no `INIT_CWD` (e.g. `fjs t` invoked outside `npm run`), `env`
@@ -166,6 +168,33 @@ export const proof = {
166
168
  /** @type {Dir} */
167
169
  const root = { 'a.f.ts': () => ({}) }
168
170
  const [, result] = virtual({ ...emptyState, root })(loadModuleMap({}))
169
- assertEq(Object.keys(result).join(','), './a.f.ts')
171
+ assertEq(Object.keys(unwrap(result)).join(','), './a.f.ts')
172
+ },
173
+ loadModuleMapReportsUnreadableRoot: () => {
174
+ // A directory that cannot be listed is no longer a panic. Discovery
175
+ // hands the failure back, and the program that asked for the map is
176
+ // the one that decides what a source tree it cannot read means — for
177
+ // `fjs t` that is a message on `stderr` and exit `1`.
178
+ const [, result] = virtual({ ...emptyState, root: {} })(loadModuleMap({ INIT_CWD: 'missing' }))
179
+ assert(result[0] === 'error', result)
180
+ },
181
+ loadModuleMapReportsUnimportableModule: () => {
182
+ // The other half of the same breaking change, and the half `readdir`
183
+ // does not cover: discovery lists the file, then the import of it
184
+ // fails. `'a.f.ts': []` is content rather than a module, so the
185
+ // virtual runner's `import` refuses it. Without this, a `loadFile`
186
+ // that turned every import failure into a success would still pass
187
+ // every other proof here.
188
+ const [, result] = virtual({ ...emptyState, root: { 'a.f.ts': [] } })(loadModuleMap({}))
189
+ assert(result[0] === 'error', result)
190
+ },
191
+ loadModuleMapStripsInitCwdPrefix: () => {
192
+ // With `INIT_CWD` set (the normal `npm run` case), discovery starts
193
+ // from that subdirectory and each key is relativized against it, so
194
+ // keys are still `./`-relative to `INIT_CWD` rather than carrying it.
195
+ /** @type {Dir} */
196
+ const root = { 'sub': { 'a.f.ts': () => ({}) } }
197
+ const [, result] = virtual({ ...emptyState, root })(loadModuleMap({ INIT_CWD: 'sub' }))
198
+ assertEq(Object.keys(unwrap(result)).join(','), './a.f.ts')
170
199
  },
171
200
  }
@@ -3,17 +3,22 @@
3
3
  *
4
4
  * @module
5
5
  *
6
+ * @import { IoChannel, Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts'
6
7
  * @import { Effect } from '../../effects/types.ts'
7
- * @import { Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts'
8
8
  */
9
+ import type { IoChannel, Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts';
9
10
  import type { Effect } from '../../effects/types.ts';
10
- import type { Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts';
11
11
  /**
12
12
  * Regenerates VS Code's local MCP configuration from the canonical Copilot configuration.
13
13
  *
14
- * @type {() => Effect<Mkdir | ReadFile | WriteFile, void>}
14
+ * The source text is still needed after the directory has been created, so it
15
+ * is carried forward in a history rather than closed over by a nested
16
+ * continuation — and the history holds the text itself, not the `Result` the
17
+ * read returned.
18
+ *
19
+ * @type {() => Effect<Mkdir | ReadFile | WriteFile, void, IoChannel>}
15
20
  */
16
- export declare const syncMcp: () => Effect<Mkdir | ReadFile | WriteFile, void>;
21
+ export declare const syncMcp: () => Effect<Mkdir | ReadFile | WriteFile, void, IoChannel>;
17
22
  /**
18
23
  * Runs all local development configuration generators.
19
24
  *
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * @module
5
5
  *
6
+ * @import { IoChannel, Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts'
6
7
  * @import { Effect } from '../../effects/types.ts'
7
- * @import { Mkdir, NodeProgram, ReadFile, WriteFile } from '../../effects/node/types.ts'
8
8
  */
9
9
 
10
- import { history, historyStep, mapStep, step } from '../../effects/module.f.mjs'
11
- import { mkdir, readUtf8File, writeUtf8File } from '../../effects/node/module.f.mjs'
12
- import { unwrap } from '../../types/result/module.f.mjs'
10
+
11
+ import { exitStep, mkdir, readUtf8File, writeUtf8File } from '../../effects/node/module.f.mjs'
12
+ import { history, historyStep, step } from '../../effects/module.f.mjs'
13
13
 
14
14
  const source = /** @type {const} */ ('.copilot/mcp.json')
15
15
  const targetDirectory = /** @type {const} */ ('.vscode')
@@ -18,15 +18,19 @@ const target = /** @type {const} */ ('.vscode/mcp.json')
18
18
  /**
19
19
  * Regenerates VS Code's local MCP configuration from the canonical Copilot configuration.
20
20
  *
21
- * @type {() => Effect<Mkdir | ReadFile | WriteFile, void>}
21
+ * The source text is still needed after the directory has been created, so it
22
+ * is carried forward in a history rather than closed over by a nested
23
+ * continuation — and the history holds the text itself, not the `Result` the
24
+ * read returned.
25
+ *
26
+ * @type {() => Effect<Mkdir | ReadFile | WriteFile, void, IoChannel>}
22
27
  */
23
28
  export const syncMcp = () => {
24
- const sourceText = history(mapStep(readUtf8File(source), unwrap))
29
+ const sourceText = history(readUtf8File(source))
25
30
  const targetDirectoryReady = historyStep(
26
31
  sourceText,
27
- () => mapStep(mkdir(targetDirectory, { recursive: true }), unwrap))
28
- const targetWritten = step(targetDirectoryReady, ([, text]) => writeUtf8File(target, text))
29
- return mapStep(targetWritten, unwrap)
32
+ () => mkdir(targetDirectory, { recursive: true }))
33
+ return step(targetDirectoryReady, ([, text]) => writeUtf8File(target, text))
30
34
  }
31
35
 
32
36
  /**
@@ -34,4 +38,4 @@ export const syncMcp = () => {
34
38
  *
35
39
  * @type {NodeProgram}
36
40
  */
37
- export const main = () => mapStep(syncMcp(), () => 0)
41
+ export const main = () => exitStep(syncMcp())
@@ -4,7 +4,5 @@
4
4
  export declare const proof: {
5
5
  syncMcp: () => void;
6
6
  main: () => void;
7
- throw: {
8
- missingSource: () => readonly [import("../../effects/node/virtual/types.ts").State, void];
9
- };
7
+ missingSource: () => void;
10
8
  };
@@ -2,12 +2,13 @@
2
2
  * Proofs for local development configuration generation.
3
3
  */
4
4
 
5
+ import { exitCode } from '../../effects/node/module.f.mjs'
5
6
  import { assert, assertEq } from '../../asserts/module.f.mjs'
6
7
  import { utf8 } from '../../text/module.f.mjs'
7
8
  import { readUtf8File } from '../../effects/node/module.f.mjs'
8
9
  import { defaultNodeProgramOptions, emptyState, virtual } from '../../effects/node/virtual/module.f.mjs'
9
10
  import { main, syncMcp } from './module.f.mjs'
10
- import { step } from '../../effects/module.f.mjs'
11
+ import { step as ioStep } from '../../effects/module.f.mjs'
11
12
 
12
13
  const mcp = /** @type {const} */ ('{"servers":{}}')
13
14
  const initial = /** @type {const} */ ({
@@ -20,16 +21,20 @@ const initial = /** @type {const} */ ({
20
21
  })
21
22
  export const proof = {
22
23
  syncMcp: () => {
23
- const generatedMcp = step(syncMcp(), () => readUtf8File('.vscode/mcp.json'))
24
+ const generatedMcp = ioStep(syncMcp(), () => readUtf8File('.vscode/mcp.json'))
24
25
  const [, [tag, result]] = virtual(initial)(generatedMcp)
25
26
  assert(tag === 'ok', result)
26
27
  assertEq(result, mcp)
27
28
  },
28
29
  main: () => {
29
30
  const [, result] = virtual(initial)(main(defaultNodeProgramOptions))
30
- assertEq(result, 0)
31
+ assertEq(exitCode(result), 0)
31
32
  },
32
- throw: {
33
- missingSource: () => virtual(emptyState)(syncMcp()),
33
+ // A missing source is no longer a panic: it propagates through the chain
34
+ // and the program reports it and exits 1.
35
+ missingSource: () => {
36
+ const [state, code] = virtual(emptyState)(main(defaultNodeProgramOptions))
37
+ assertEq(exitCode(code), 1)
38
+ assertEq(state.stderr, 'no such file or directory\n', state.stderr)
34
39
  },
35
40
  }
@@ -3,15 +3,23 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Effect } from '../effects/types.ts'
7
6
  * @import { WriteFile, ReadFile, Write } from '../effects/node/types.ts'
8
7
  * @import { Result } from '../types/result/types.ts'
9
8
  * @import { Unknown } from './types.ts'
10
9
  * @import { ParseError } from './parser/types.ts'
10
+ * @import { Effect } from '../effects/types.ts'
11
11
  */
12
- import type { Effect } from '../effects/types.ts';
13
12
  import type { WriteFile, ReadFile, Write } from '../effects/node/types.ts';
13
+ import type { Effect } from '../effects/types.ts';
14
14
  export type _CompileOp = ReadFile | WriteFile | Write;
15
- /** @typedef {ReadFile | WriteFile | Write} _CompileOp */
16
- /** @type {(args: readonly string[]) => Effect<_CompileOp, number>} */
17
- export declare const compile: (args: readonly string[]) => Effect<_CompileOp, number>;
15
+ /**
16
+ * Compiles the DJS module `args[0]` into `args[1]`, serializing as a JSON tree
17
+ * when the output name ends with `.json` and as a module otherwise.
18
+ *
19
+ * Returns the process exit code: `0` once the output file is written, `1` on
20
+ * every failure — too few arguments, a missing input file, or a parse error —
21
+ * so a caller can detect a failed compile from the exit status alone.
22
+ *
23
+ * @type {(args: readonly string[]) => Effect<_CompileOp, 0, number>}
24
+ */
25
+ export declare const compile: (args: readonly string[]) => Effect<_CompileOp, 0, number>;
@@ -3,45 +3,60 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Effect } from '../effects/types.ts'
7
6
  * @import { WriteFile, ReadFile, Write } from '../effects/node/types.ts'
8
7
  * @import { Result } from '../types/result/types.ts'
9
8
  * @import { Unknown } from './types.ts'
10
9
  * @import { ParseError } from './parser/types.ts'
10
+ * @import { Effect } from '../effects/types.ts'
11
11
  */
12
12
 
13
13
  import { transpile } from './transpiler/module.f.mjs'
14
14
  import { stringify, stringifyAsTree } from './serializer/module.f.mjs'
15
15
  import { sort } from '../types/object/module.f.mjs'
16
- import { pure, step } from '../effects/module.f.mjs'
17
- import { writeUtf8File, error } from '../effects/node/module.f.mjs'
16
+ import { resultStep } from '../effects/module.f.mjs'
17
+ import { errorExit, exitStep, writeUtf8File } from '../effects/node/module.f.mjs'
18
18
 
19
19
  /** @typedef {ReadFile | WriteFile | Write} _CompileOp */
20
20
 
21
- /** @type {(args: readonly string[]) => Effect<_CompileOp, number>} */
21
+ /**
22
+ * Where an error happened, as much of it as is known: the token's
23
+ * `path:line:column` when the reader tracks positions, and otherwise the name
24
+ * of the file being compiled. A `.json` input is read by `fjs/media/json`,
25
+ * whose errors carry no position, and a missing file or a circular dependency
26
+ * has no token to point at either.
27
+ *
28
+ * @type {(inputFileName: string) => (parseError: ParseError) => string}
29
+ */
30
+ const errorLocation = inputFileName => ({ metadata }) => metadata === null
31
+ ? inputFileName
32
+ : `${metadata.path}:${metadata.line}:${metadata.column}`
33
+
34
+ /**
35
+ * Compiles the DJS module `args[0]` into `args[1]`, serializing as a JSON tree
36
+ * when the output name ends with `.json` and as a module otherwise.
37
+ *
38
+ * Returns the process exit code: `0` once the output file is written, `1` on
39
+ * every failure — too few arguments, a missing input file, or a parse error —
40
+ * so a caller can detect a failed compile from the exit status alone.
41
+ *
42
+ * @type {(args: readonly string[]) => Effect<_CompileOp, 0, number>}
43
+ */
22
44
  export const compile = args => {
23
45
  if (args.length < 2) {
24
- return step(
25
- error('Error: Requires 2 or more arguments'),
26
- () => pure(1))
46
+ return errorExit('Error: Requires 2 or more arguments')
27
47
  }
28
48
  const inputFileName = args[0]
29
49
  const outputFileName = args[1]
30
- return step(
50
+ return resultStep(
31
51
  transpile(inputFileName),
32
- /** @type {(result: Result<Unknown, ParseError>) => Effect<_CompileOp, number>} */
52
+ /** @type {(result: Result<Unknown, ParseError>) => Effect<_CompileOp, 0, number>} */
33
53
  (result) => {
34
54
  if (result[0] === 'error') {
35
- const metadata = result[1].metadata
36
- return step(
37
- error(`${metadata?.path}:${metadata?.line}:${metadata?.column} - error: ${result[1].message}`),
38
- () => pure(0))
55
+ return errorExit(`${errorLocation(inputFileName)(result[1])} - error: ${result[1].message}`)
39
56
  }
40
57
  const content = outputFileName.endsWith('.json')
41
58
  ? stringifyAsTree(sort)(result[1])
42
59
  : stringify(sort)(result[1])
43
- return step(
44
- writeUtf8File(outputFileName, content),
45
- () => pure(0))
60
+ return exitStep(writeUtf8File(outputFileName, content))
46
61
  })
47
62
  }
@@ -10,7 +10,7 @@
10
10
  * @import { OrderedMap } from '../../types/ordered_map/types.ts'
11
11
  * @import { AstArray, AstConst, AstModule, AstModuleRef } from '../ast/types.ts'
12
12
  * @import { TokenMetadata } from '../../js/tokenizer/types.ts'
13
- * @import { ParseError } from './types.ts'
13
+ * @import { ParseError, _ValueToken } from './types.ts'
14
14
  */
15
15
  import type { Result } from '../../types/result/types.ts';
16
16
  import type { List } from '../../types/list/types.ts';
@@ -48,10 +48,11 @@ export type _ExportState = {
48
48
  readonly state: 'export';
49
49
  readonly module: _ModuleState;
50
50
  };
51
+ export type _ValueState = '' | '[' | '[v' | '[,' | '{' | '{[' | '{[k' | '{k' | '{:' | '{v' | '{,';
51
52
  export type _ParseValueState = {
52
53
  readonly state: 'constValue' | 'exportValue';
53
54
  readonly module: _ModuleState;
54
- readonly valueState: '' | '[' | '[v' | '[,' | '{' | '{k' | '{:' | '{v' | '{,';
55
+ readonly valueState: _ValueState;
55
56
  readonly top: _DjsStackElement | null;
56
57
  readonly stack: _DjsStack;
57
58
  };
@@ -63,7 +64,16 @@ export type _ErrorState = {
63
64
  readonly state: 'error';
64
65
  readonly error: ParseError;
65
66
  };
66
- /** @type {(tokenList: List<DjsTokenWithMetadata>) => Result<AstModule, ParseError>} */
67
+ /**
68
+ * Reads the token list as a FunctionalScript module: `import` statements, then
69
+ * `const` statements, then one `export default`.
70
+ *
71
+ * This is the only language the parser reads. A JSON document is data, not a
72
+ * module, and `fjs/media/json` is its reader
73
+ * ([spec: JSON input](../../../spec/README.md#json-input)).
74
+ *
75
+ * @type {(tokenList: List<DjsTokenWithMetadata>) => Result<AstModule, ParseError>}
76
+ */
67
77
  export declare const parseFromTokens: (tokenList: List<DjsTokenWithMetadata>) => Result<AstModule, ParseError>;
68
78
  export declare const proof: {
69
79
  pushKey: {