@fougere/core 0.6.0-alpha.0 → 0.8.0-alpha.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 (510) hide show
  1. package/README.md +1 -1
  2. package/dist/boot/AppLifecycle.d.ts +1 -1
  3. package/dist/boot/AppLifecycle.d.ts.map +1 -1
  4. package/dist/boot/AppLifecycle.js +13 -2
  5. package/dist/boot/AppLifecycle.js.map +1 -1
  6. package/dist/boot/Emissions.d.ts +13 -90
  7. package/dist/boot/Emissions.d.ts.map +1 -1
  8. package/dist/boot/Emissions.js +21 -118
  9. package/dist/boot/Emissions.js.map +1 -1
  10. package/dist/boot/ambient-port.d.ts +3 -24
  11. package/dist/boot/ambient-port.d.ts.map +1 -1
  12. package/dist/boot/ambient.als.d.ts.map +1 -1
  13. package/dist/boot/ambient.als.js +7 -12
  14. package/dist/boot/ambient.als.js.map +1 -1
  15. package/dist/boot/ambient.queue.d.ts +2 -5
  16. package/dist/boot/ambient.queue.d.ts.map +1 -1
  17. package/dist/boot/ambient.queue.js.map +1 -1
  18. package/dist/boot/apply.d.ts +1 -13
  19. package/dist/boot/apply.d.ts.map +1 -1
  20. package/dist/boot/apply.js +9 -16
  21. package/dist/boot/apply.js.map +1 -1
  22. package/dist/boot/auth.d.ts +2 -12
  23. package/dist/boot/auth.d.ts.map +1 -1
  24. package/dist/boot/boot.d.ts +3 -16
  25. package/dist/boot/boot.d.ts.map +1 -1
  26. package/dist/boot/boot.js +4 -11
  27. package/dist/boot/boot.js.map +1 -1
  28. package/dist/boot/bootstrap.d.ts.map +1 -1
  29. package/dist/boot/bootstrap.js +84 -130
  30. package/dist/boot/bootstrap.js.map +1 -1
  31. package/dist/boot/card.d.ts +1 -17
  32. package/dist/boot/card.d.ts.map +1 -1
  33. package/dist/boot/card.js +3 -32
  34. package/dist/boot/card.js.map +1 -1
  35. package/dist/boot/frame.d.ts +8 -32
  36. package/dist/boot/frame.d.ts.map +1 -1
  37. package/dist/boot/frame.js +17 -56
  38. package/dist/boot/frame.js.map +1 -1
  39. package/dist/boot/hosted.d.ts +2 -24
  40. package/dist/boot/hosted.d.ts.map +1 -1
  41. package/dist/boot/hosted.js +10 -15
  42. package/dist/boot/hosted.js.map +1 -1
  43. package/dist/boot/ownership.d.ts +3 -36
  44. package/dist/boot/ownership.d.ts.map +1 -1
  45. package/dist/boot/ownership.js +5 -40
  46. package/dist/boot/ownership.js.map +1 -1
  47. package/dist/boot/ports.d.ts +1 -14
  48. package/dist/boot/ports.d.ts.map +1 -1
  49. package/dist/boot/ports.js +1 -14
  50. package/dist/boot/ports.js.map +1 -1
  51. package/dist/boot/remote.d.ts +5 -38
  52. package/dist/boot/remote.d.ts.map +1 -1
  53. package/dist/boot/remote.js +8 -41
  54. package/dist/boot/remote.js.map +1 -1
  55. package/dist/boot/runner.d.ts +4 -21
  56. package/dist/boot/runner.d.ts.map +1 -1
  57. package/dist/boot/runner.js +4 -17
  58. package/dist/boot/runner.js.map +1 -1
  59. package/dist/boot/seed.d.ts +4 -31
  60. package/dist/boot/seed.d.ts.map +1 -1
  61. package/dist/boot/seed.js +6 -37
  62. package/dist/boot/seed.js.map +1 -1
  63. package/dist/boot/statement-drift.d.ts +2 -21
  64. package/dist/boot/statement-drift.d.ts.map +1 -1
  65. package/dist/boot/statement-drift.js +4 -9
  66. package/dist/boot/statement-drift.js.map +1 -1
  67. package/dist/boot/together.d.ts +4 -8
  68. package/dist/boot/together.d.ts.map +1 -1
  69. package/dist/boot/together.js +15 -50
  70. package/dist/boot/together.js.map +1 -1
  71. package/dist/boot/types.d.ts +31 -173
  72. package/dist/boot/types.d.ts.map +1 -1
  73. package/dist/builtin/config.d.ts +7 -0
  74. package/dist/builtin/config.d.ts.map +1 -0
  75. package/dist/builtin/config.js +15 -0
  76. package/dist/builtin/config.js.map +1 -0
  77. package/dist/{builtins → builtin}/logger.d.ts +4 -25
  78. package/dist/builtin/logger.d.ts.map +1 -0
  79. package/dist/{builtins → builtin}/logger.js +5 -32
  80. package/dist/builtin/logger.js.map +1 -0
  81. package/dist/config-loader.d.ts +9 -67
  82. package/dist/config-loader.d.ts.map +1 -1
  83. package/dist/config-loader.js +5 -18
  84. package/dist/config-loader.js.map +1 -1
  85. package/dist/contract.d.ts +15 -31
  86. package/dist/contract.d.ts.map +1 -1
  87. package/dist/contract.js +13 -26
  88. package/dist/contract.js.map +1 -1
  89. package/dist/criterion.d.ts +37 -0
  90. package/dist/criterion.d.ts.map +1 -0
  91. package/dist/criterion.js +28 -0
  92. package/dist/criterion.js.map +1 -0
  93. package/dist/crypto/encoding.d.ts +2 -15
  94. package/dist/crypto/encoding.d.ts.map +1 -1
  95. package/dist/crypto/encoding.js +2 -15
  96. package/dist/crypto/encoding.js.map +1 -1
  97. package/dist/crypto/node.d.ts.map +1 -1
  98. package/dist/crypto/node.js +1 -7
  99. package/dist/crypto/node.js.map +1 -1
  100. package/dist/crypto/port.d.ts +2 -18
  101. package/dist/crypto/port.d.ts.map +1 -1
  102. package/dist/crypto/port.js +1 -17
  103. package/dist/crypto/port.js.map +1 -1
  104. package/dist/crypto/webcrypto.d.ts.map +1 -1
  105. package/dist/crypto/webcrypto.js +1 -12
  106. package/dist/crypto/webcrypto.js.map +1 -1
  107. package/dist/declare.d.ts +19 -37
  108. package/dist/declare.d.ts.map +1 -1
  109. package/dist/declare.js +23 -30
  110. package/dist/declare.js.map +1 -1
  111. package/dist/define.d.ts +2 -3
  112. package/dist/define.d.ts.map +1 -1
  113. package/dist/define.js +2 -3
  114. package/dist/define.js.map +1 -1
  115. package/dist/descriptor/Fronds.d.ts +3 -28
  116. package/dist/descriptor/Fronds.d.ts.map +1 -1
  117. package/dist/descriptor/Fronds.js +6 -31
  118. package/dist/descriptor/Fronds.js.map +1 -1
  119. package/dist/descriptor/frond.d.ts +25 -60
  120. package/dist/descriptor/frond.d.ts.map +1 -1
  121. package/dist/descriptor/frond.js +5 -1
  122. package/dist/descriptor/frond.js.map +1 -1
  123. package/dist/dispatch/ArgumentResolver.d.ts +1 -1
  124. package/dist/dispatch/ArgumentResolver.d.ts.map +1 -1
  125. package/dist/dispatch/ArgumentResolver.js +5 -5
  126. package/dist/dispatch/ArgumentResolver.js.map +1 -1
  127. package/dist/dispatch/DispatchEvent.d.ts +2 -2
  128. package/dist/dispatch/DispatchEvent.d.ts.map +1 -1
  129. package/dist/dispatch/DispatchLifecycle.d.ts +1 -7
  130. package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -1
  131. package/dist/dispatch/DispatchLifecycle.js +1 -7
  132. package/dist/dispatch/DispatchLifecycle.js.map +1 -1
  133. package/dist/dispatch/DispatchPort.d.ts +1 -1
  134. package/dist/dispatch/DispatchPort.d.ts.map +1 -1
  135. package/dist/dispatch/Dispatcher.d.ts +1 -1
  136. package/dist/dispatch/Dispatcher.d.ts.map +1 -1
  137. package/dist/dispatch/Dispatcher.js +2 -2
  138. package/dist/dispatch/Dispatcher.js.map +1 -1
  139. package/dist/{boot → dispatch}/HandlerFacade.d.ts +25 -38
  140. package/dist/dispatch/HandlerFacade.d.ts.map +1 -0
  141. package/dist/{boot → dispatch}/HandlerFacade.js +65 -74
  142. package/dist/dispatch/HandlerFacade.js.map +1 -0
  143. package/dist/dispatch/LocalRoutePolicy.d.ts +1 -1
  144. package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -1
  145. package/dist/dispatch/LocalRoutePolicy.js +4 -4
  146. package/dist/dispatch/LocalRoutePolicy.js.map +1 -1
  147. package/dist/dispatch/OperationRoute.d.ts +2 -2
  148. package/dist/dispatch/OperationRoute.d.ts.map +1 -1
  149. package/dist/dispatch/OutputView.d.ts +3 -2
  150. package/dist/dispatch/OutputView.d.ts.map +1 -1
  151. package/dist/dispatch/OutputView.js +19 -1
  152. package/dist/dispatch/OutputView.js.map +1 -1
  153. package/dist/dispatch/Route.d.ts +2 -2
  154. package/dist/dispatch/Route.d.ts.map +1 -1
  155. package/dist/dispatch/RoutePolicy.d.ts +1 -1
  156. package/dist/dispatch/RoutePolicy.d.ts.map +1 -1
  157. package/dist/dispatch/RouteRegistry.d.ts +1 -1
  158. package/dist/dispatch/RouteRegistry.d.ts.map +1 -1
  159. package/dist/dispatch/RouteRegistry.js +2 -2
  160. package/dist/dispatch/RouteRegistry.js.map +1 -1
  161. package/dist/dispatch/RouteResolver.d.ts +2 -4
  162. package/dist/dispatch/RouteResolver.d.ts.map +1 -1
  163. package/dist/dispatch/StorageGuard.d.ts +40 -8
  164. package/dist/dispatch/StorageGuard.d.ts.map +1 -1
  165. package/dist/dispatch/StorageGuard.js +151 -20
  166. package/dist/dispatch/StorageGuard.js.map +1 -1
  167. package/dist/dispatch/presenterArguments.d.ts +7 -0
  168. package/dist/dispatch/presenterArguments.d.ts.map +1 -0
  169. package/dist/dispatch/presenterArguments.js +12 -0
  170. package/dist/dispatch/presenterArguments.js.map +1 -0
  171. package/dist/dispatch/remoteRoutes.d.ts +7 -0
  172. package/dist/dispatch/remoteRoutes.d.ts.map +1 -0
  173. package/dist/dispatch/{RemoteRouteResolver.js → remoteRoutes.js} +6 -10
  174. package/dist/dispatch/remoteRoutes.js.map +1 -0
  175. package/dist/dispatch/routeNotFound.d.ts +9 -0
  176. package/dist/dispatch/routeNotFound.d.ts.map +1 -0
  177. package/dist/dispatch/routeNotFound.js +21 -0
  178. package/dist/dispatch/routeNotFound.js.map +1 -0
  179. package/dist/dispatch/validateInput.d.ts +5 -0
  180. package/dist/dispatch/validateInput.d.ts.map +1 -0
  181. package/dist/dispatch/validateInput.js +20 -0
  182. package/dist/dispatch/validateInput.js.map +1 -0
  183. package/dist/effective-operation.d.ts +1 -24
  184. package/dist/effective-operation.d.ts.map +1 -1
  185. package/dist/effective-operation.js +21 -50
  186. package/dist/effective-operation.js.map +1 -1
  187. package/dist/emit.d.ts +4 -42
  188. package/dist/emit.d.ts.map +1 -1
  189. package/dist/emit.js +3 -39
  190. package/dist/emit.js.map +1 -1
  191. package/dist/entry/facade.d.ts +8 -0
  192. package/dist/entry/facade.d.ts.map +1 -0
  193. package/dist/entry/facade.js +28 -0
  194. package/dist/entry/facade.js.map +1 -0
  195. package/dist/entry/transport.d.ts +5 -0
  196. package/dist/entry/transport.d.ts.map +1 -0
  197. package/dist/entry/transport.js +11 -0
  198. package/dist/entry/transport.js.map +1 -0
  199. package/dist/frond-config.d.ts +7 -70
  200. package/dist/frond-config.d.ts.map +1 -1
  201. package/dist/frond-config.js +1 -9
  202. package/dist/frond-config.js.map +1 -1
  203. package/dist/identity-keys.d.ts +2 -5
  204. package/dist/identity-keys.d.ts.map +1 -1
  205. package/dist/identity-keys.js +3 -16
  206. package/dist/identity-keys.js.map +1 -1
  207. package/dist/identity.d.ts +4 -30
  208. package/dist/identity.d.ts.map +1 -1
  209. package/dist/identity.js +11 -73
  210. package/dist/identity.js.map +1 -1
  211. package/dist/imports.d.ts +1 -7
  212. package/dist/imports.d.ts.map +1 -1
  213. package/dist/imports.js +1 -7
  214. package/dist/imports.js.map +1 -1
  215. package/dist/index.d.ts +17 -24
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +10 -18
  218. package/dist/index.js.map +1 -1
  219. package/dist/loader.d.ts +1 -8
  220. package/dist/loader.d.ts.map +1 -1
  221. package/dist/loader.js +1 -8
  222. package/dist/loader.js.map +1 -1
  223. package/dist/node.d.ts +2 -11
  224. package/dist/node.d.ts.map +1 -1
  225. package/dist/node.js +2 -11
  226. package/dist/node.js.map +1 -1
  227. package/dist/prefab/collector.d.ts +1 -22
  228. package/dist/prefab/collector.d.ts.map +1 -1
  229. package/dist/prefab/collector.js +1 -22
  230. package/dist/prefab/collector.js.map +1 -1
  231. package/dist/prefab/crud.d.ts +16 -32
  232. package/dist/prefab/crud.d.ts.map +1 -1
  233. package/dist/prefab/crud.js +31 -58
  234. package/dist/prefab/crud.js.map +1 -1
  235. package/dist/prefab/mirror.d.ts +2 -24
  236. package/dist/prefab/mirror.d.ts.map +1 -1
  237. package/dist/prefab/mirror.js +2 -20
  238. package/dist/prefab/mirror.js.map +1 -1
  239. package/dist/prefab/prefab.d.ts +1 -7
  240. package/dist/prefab/prefab.d.ts.map +1 -1
  241. package/dist/prefab/prefab.js +1 -7
  242. package/dist/prefab/prefab.js.map +1 -1
  243. package/dist/prefab/presenter.d.ts +2 -36
  244. package/dist/prefab/presenter.d.ts.map +1 -1
  245. package/dist/prefab/presenter.js +2 -36
  246. package/dist/prefab/presenter.js.map +1 -1
  247. package/dist/prefab/repository.d.ts +5 -73
  248. package/dist/prefab/repository.d.ts.map +1 -1
  249. package/dist/prefab/repository.js +3 -16
  250. package/dist/prefab/repository.js.map +1 -1
  251. package/dist/scan/adapters.d.ts +3 -0
  252. package/dist/scan/adapters.d.ts.map +1 -0
  253. package/dist/scan/adapters.js +25 -0
  254. package/dist/scan/adapters.js.map +1 -0
  255. package/dist/scan/bundling.d.ts +1 -12
  256. package/dist/scan/bundling.d.ts.map +1 -1
  257. package/dist/scan/bundling.js +1 -12
  258. package/dist/scan/bundling.js.map +1 -1
  259. package/dist/scan/contract.d.ts +27 -0
  260. package/dist/scan/contract.d.ts.map +1 -0
  261. package/dist/scan/contract.js +46 -0
  262. package/dist/scan/contract.js.map +1 -0
  263. package/dist/scan/conventions.d.ts +6 -40
  264. package/dist/scan/conventions.d.ts.map +1 -1
  265. package/dist/scan/conventions.js +5 -34
  266. package/dist/scan/conventions.js.map +1 -1
  267. package/dist/scan/emit.d.ts +1 -5
  268. package/dist/scan/emit.d.ts.map +1 -1
  269. package/dist/scan/emit.js +10 -78
  270. package/dist/scan/emit.js.map +1 -1
  271. package/dist/scan/handler-parser.d.ts +4 -26
  272. package/dist/scan/handler-parser.d.ts.map +1 -1
  273. package/dist/scan/handler-parser.js +26 -83
  274. package/dist/scan/handler-parser.js.map +1 -1
  275. package/dist/scan/result.d.ts +3 -16
  276. package/dist/scan/result.d.ts.map +1 -1
  277. package/dist/scan/scanner.d.ts +2 -27
  278. package/dist/scan/scanner.d.ts.map +1 -1
  279. package/dist/scan/scanner.js +45 -133
  280. package/dist/scan/scanner.js.map +1 -1
  281. package/dist/scan/statement.d.ts.map +1 -1
  282. package/dist/scan/statement.js +60 -37
  283. package/dist/scan/statement.js.map +1 -1
  284. package/dist/source.d.ts +53 -0
  285. package/dist/source.d.ts.map +1 -0
  286. package/dist/source.js +18 -0
  287. package/dist/source.js.map +1 -0
  288. package/dist/storage.d.ts +13 -210
  289. package/dist/storage.d.ts.map +1 -1
  290. package/dist/storage.js +4 -68
  291. package/dist/storage.js.map +1 -1
  292. package/dist/store.d.ts +18 -0
  293. package/dist/store.d.ts.map +1 -0
  294. package/dist/store.js +179 -0
  295. package/dist/store.js.map +1 -0
  296. package/dist/verify.d.ts +5 -38
  297. package/dist/verify.d.ts.map +1 -1
  298. package/dist/verify.js +17 -37
  299. package/dist/verify.js.map +1 -1
  300. package/dist/wire/CallLog.d.ts +32 -0
  301. package/dist/wire/CallLog.d.ts.map +1 -0
  302. package/dist/{contract → wire}/CallLog.js.map +1 -1
  303. package/dist/wire/Invocation.d.ts +32 -0
  304. package/dist/wire/Invocation.d.ts.map +1 -0
  305. package/dist/wire/Invocation.js +66 -0
  306. package/dist/wire/Invocation.js.map +1 -0
  307. package/dist/{contract → wire}/RouteAddress.d.ts +5 -0
  308. package/dist/wire/RouteAddress.d.ts.map +1 -0
  309. package/dist/{contract → wire}/RouteAddress.js +7 -0
  310. package/dist/wire/RouteAddress.js.map +1 -0
  311. package/dist/wire/binding.d.ts +5 -21
  312. package/dist/wire/binding.d.ts.map +1 -1
  313. package/dist/wire/binding.js +5 -10
  314. package/dist/wire/binding.js.map +1 -1
  315. package/dist/wire/call.d.ts +24 -133
  316. package/dist/wire/call.d.ts.map +1 -1
  317. package/dist/wire/call.js +15 -41
  318. package/dist/wire/call.js.map +1 -1
  319. package/dist/wire/drift.d.ts +3 -28
  320. package/dist/wire/drift.d.ts.map +1 -1
  321. package/dist/wire/drift.js +4 -23
  322. package/dist/wire/drift.js.map +1 -1
  323. package/dist/wire/errors.d.ts +4 -24
  324. package/dist/wire/errors.d.ts.map +1 -1
  325. package/dist/wire/errors.js +4 -24
  326. package/dist/wire/errors.js.map +1 -1
  327. package/dist/wire/http-error.d.ts +2 -13
  328. package/dist/wire/http-error.d.ts.map +1 -1
  329. package/dist/wire/http-error.js +5 -19
  330. package/dist/wire/http-error.js.map +1 -1
  331. package/dist/wire/loggerMiddleware.d.ts +2 -8
  332. package/dist/wire/loggerMiddleware.d.ts.map +1 -1
  333. package/dist/wire/loggerMiddleware.js +1 -7
  334. package/dist/wire/loggerMiddleware.js.map +1 -1
  335. package/dist/wire/middleware.d.ts +3 -7
  336. package/dist/wire/middleware.d.ts.map +1 -1
  337. package/dist/wire/middleware.js +1 -5
  338. package/dist/wire/middleware.js.map +1 -1
  339. package/dist/wire/operation.d.ts +7 -43
  340. package/dist/wire/operation.d.ts.map +1 -1
  341. package/dist/wire/operation.js +4 -15
  342. package/dist/wire/operation.js.map +1 -1
  343. package/dist/wire/signature.d.ts +4 -25
  344. package/dist/wire/signature.d.ts.map +1 -1
  345. package/package.json +3 -3
  346. package/src/boot/AppLifecycle.ts +15 -2
  347. package/src/boot/Emissions.ts +21 -118
  348. package/src/boot/ambient-port.ts +3 -24
  349. package/src/boot/ambient.als.ts +7 -12
  350. package/src/boot/ambient.queue.ts +2 -5
  351. package/src/boot/apply.ts +9 -16
  352. package/src/boot/auth.ts +2 -12
  353. package/src/boot/boot.ts +6 -21
  354. package/src/boot/bootstrap.ts +95 -140
  355. package/src/boot/card.ts +4 -33
  356. package/src/boot/frame.ts +24 -64
  357. package/src/boot/hosted.ts +12 -34
  358. package/src/boot/ownership.ts +5 -39
  359. package/src/boot/ports.ts +1 -14
  360. package/src/boot/remote.ts +11 -58
  361. package/src/boot/runner.ts +5 -22
  362. package/src/boot/seed.ts +6 -37
  363. package/src/boot/statement-drift.ts +5 -24
  364. package/src/boot/together.ts +18 -51
  365. package/src/boot/types.ts +31 -173
  366. package/src/{builtins → builtin}/config.ts +1 -7
  367. package/src/{builtins → builtin}/logger.ts +6 -39
  368. package/src/config-loader.ts +12 -71
  369. package/src/contract.ts +19 -39
  370. package/src/criterion.ts +54 -0
  371. package/src/crypto/encoding.ts +2 -15
  372. package/src/crypto/node.ts +1 -7
  373. package/src/crypto/port.ts +2 -18
  374. package/src/crypto/webcrypto.ts +1 -12
  375. package/src/declare.ts +42 -41
  376. package/src/define.ts +2 -3
  377. package/src/descriptor/Fronds.ts +6 -31
  378. package/src/descriptor/frond.ts +26 -60
  379. package/src/dispatch/ArgumentResolver.ts +6 -6
  380. package/src/dispatch/DispatchEvent.ts +2 -2
  381. package/src/dispatch/DispatchLifecycle.ts +1 -7
  382. package/src/dispatch/DispatchPort.ts +1 -1
  383. package/src/dispatch/Dispatcher.ts +3 -3
  384. package/src/dispatch/HandlerFacade.ts +231 -0
  385. package/src/dispatch/LocalRoutePolicy.ts +4 -4
  386. package/src/dispatch/OperationRoute.ts +2 -2
  387. package/src/dispatch/OutputView.ts +24 -2
  388. package/src/dispatch/Route.ts +2 -2
  389. package/src/dispatch/RoutePolicy.ts +1 -1
  390. package/src/dispatch/RouteRegistry.ts +2 -2
  391. package/src/dispatch/RouteResolver.ts +2 -4
  392. package/src/dispatch/StorageGuard.ts +175 -19
  393. package/src/dispatch/presenterArguments.ts +25 -0
  394. package/src/dispatch/{RemoteRouteResolver.ts → remoteRoutes.ts} +7 -9
  395. package/src/dispatch/routeNotFound.ts +33 -0
  396. package/src/dispatch/validateInput.ts +28 -0
  397. package/src/effective-operation.ts +21 -50
  398. package/src/emit.ts +5 -63
  399. package/src/entry/facade.ts +44 -0
  400. package/src/entry/transport.ts +16 -0
  401. package/src/frond-config.ts +7 -70
  402. package/src/identity-keys.ts +3 -16
  403. package/src/identity.ts +12 -80
  404. package/src/imports.ts +2 -31
  405. package/src/index.ts +17 -24
  406. package/src/loader.ts +2 -16
  407. package/src/node.ts +2 -11
  408. package/src/prefab/collector.ts +1 -22
  409. package/src/prefab/crud.ts +37 -76
  410. package/src/prefab/mirror.ts +4 -44
  411. package/src/prefab/prefab.ts +2 -21
  412. package/src/prefab/presenter.ts +2 -36
  413. package/src/prefab/repository.ts +7 -83
  414. package/src/scan/adapters.ts +32 -0
  415. package/src/scan/bundling.ts +1 -12
  416. package/src/scan/contract.ts +80 -0
  417. package/src/scan/conventions.ts +6 -40
  418. package/src/scan/emit.ts +11 -80
  419. package/src/scan/handler-parser.ts +27 -96
  420. package/src/scan/result.ts +3 -16
  421. package/src/scan/scanner.ts +46 -132
  422. package/src/scan/statement.ts +73 -41
  423. package/src/source.ts +63 -0
  424. package/src/storage.ts +14 -234
  425. package/src/store.ts +191 -0
  426. package/src/verify.ts +16 -57
  427. package/src/wire/CallLog.ts +30 -0
  428. package/src/{contract → wire}/Invocation.ts +24 -17
  429. package/src/{contract → wire}/RouteAddress.ts +7 -0
  430. package/src/wire/binding.ts +9 -25
  431. package/src/wire/call.ts +30 -133
  432. package/src/wire/drift.ts +5 -30
  433. package/src/wire/errors.ts +4 -24
  434. package/src/wire/http-error.ts +5 -19
  435. package/src/wire/loggerMiddleware.ts +2 -8
  436. package/src/wire/middleware.ts +3 -7
  437. package/src/wire/operation.ts +8 -48
  438. package/src/wire/signature.ts +4 -25
  439. package/dist/boot/HandlerFacade.d.ts.map +0 -1
  440. package/dist/boot/HandlerFacade.js.map +0 -1
  441. package/dist/builtins/config.d.ts +0 -13
  442. package/dist/builtins/config.d.ts.map +0 -1
  443. package/dist/builtins/config.js +0 -21
  444. package/dist/builtins/config.js.map +0 -1
  445. package/dist/builtins/logger.d.ts.map +0 -1
  446. package/dist/builtins/logger.js.map +0 -1
  447. package/dist/contract/Call.d.ts +0 -10
  448. package/dist/contract/Call.d.ts.map +0 -1
  449. package/dist/contract/Call.js +0 -15
  450. package/dist/contract/Call.js.map +0 -1
  451. package/dist/contract/CallLog.d.ts +0 -57
  452. package/dist/contract/CallLog.d.ts.map +0 -1
  453. package/dist/contract/Invocation.d.ts +0 -27
  454. package/dist/contract/Invocation.d.ts.map +0 -1
  455. package/dist/contract/Invocation.js +0 -59
  456. package/dist/contract/Invocation.js.map +0 -1
  457. package/dist/contract/RouteAddress.d.ts.map +0 -1
  458. package/dist/contract/RouteAddress.js.map +0 -1
  459. package/dist/dispatch/InputValidator.d.ts +0 -7
  460. package/dist/dispatch/InputValidator.d.ts.map +0 -1
  461. package/dist/dispatch/InputValidator.js +0 -22
  462. package/dist/dispatch/InputValidator.js.map +0 -1
  463. package/dist/dispatch/OperationExecutor.d.ts +0 -25
  464. package/dist/dispatch/OperationExecutor.d.ts.map +0 -1
  465. package/dist/dispatch/OperationExecutor.js +0 -32
  466. package/dist/dispatch/OperationExecutor.js.map +0 -1
  467. package/dist/dispatch/OutputProjector.d.ts +0 -12
  468. package/dist/dispatch/OutputProjector.d.ts.map +0 -1
  469. package/dist/dispatch/OutputProjector.js +0 -30
  470. package/dist/dispatch/OutputProjector.js.map +0 -1
  471. package/dist/dispatch/PresenterArgumentResolver.d.ts +0 -12
  472. package/dist/dispatch/PresenterArgumentResolver.d.ts.map +0 -1
  473. package/dist/dispatch/PresenterArgumentResolver.js +0 -20
  474. package/dist/dispatch/PresenterArgumentResolver.js.map +0 -1
  475. package/dist/dispatch/RemoteRouteResolver.d.ts +0 -13
  476. package/dist/dispatch/RemoteRouteResolver.d.ts.map +0 -1
  477. package/dist/dispatch/RemoteRouteResolver.js.map +0 -1
  478. package/dist/dispatch/RouteNotFoundError.d.ts +0 -10
  479. package/dist/dispatch/RouteNotFoundError.d.ts.map +0 -1
  480. package/dist/dispatch/RouteNotFoundError.js +0 -24
  481. package/dist/dispatch/RouteNotFoundError.js.map +0 -1
  482. package/dist/entry/DynamicFacade.d.ts +0 -10
  483. package/dist/entry/DynamicFacade.d.ts.map +0 -1
  484. package/dist/entry/DynamicFacade.js +0 -27
  485. package/dist/entry/DynamicFacade.js.map +0 -1
  486. package/dist/entry/FacadeEntry.d.ts +0 -11
  487. package/dist/entry/FacadeEntry.d.ts.map +0 -1
  488. package/dist/entry/FacadeEntry.js +0 -26
  489. package/dist/entry/FacadeEntry.js.map +0 -1
  490. package/dist/entry/TransportEntry.d.ts +0 -13
  491. package/dist/entry/TransportEntry.d.ts.map +0 -1
  492. package/dist/entry/TransportEntry.js +0 -24
  493. package/dist/entry/TransportEntry.js.map +0 -1
  494. package/dist/rows.d.ts +0 -40
  495. package/dist/rows.d.ts.map +0 -1
  496. package/dist/rows.js +0 -146
  497. package/dist/rows.js.map +0 -1
  498. package/src/boot/HandlerFacade.ts +0 -242
  499. package/src/contract/Call.ts +0 -18
  500. package/src/contract/CallLog.ts +0 -55
  501. package/src/dispatch/InputValidator.ts +0 -28
  502. package/src/dispatch/OperationExecutor.ts +0 -60
  503. package/src/dispatch/OutputProjector.ts +0 -32
  504. package/src/dispatch/PresenterArgumentResolver.ts +0 -25
  505. package/src/dispatch/RouteNotFoundError.ts +0 -29
  506. package/src/entry/DynamicFacade.ts +0 -28
  507. package/src/entry/FacadeEntry.ts +0 -32
  508. package/src/entry/TransportEntry.ts +0 -30
  509. package/src/rows.ts +0 -155
  510. /package/dist/{contract → wire}/CallLog.js +0 -0
package/src/store.ts ADDED
@@ -0,0 +1,191 @@
1
+ /** The thirteen gestures of {@link Storage}, derived from four. */
2
+ import { applyCreate, applyUpdate, Lifecycle, Role, type SchemaView } from '@fougere/schema';
3
+ import { comparisonOf, comparisonsIn, type Comparison } from './criterion.js';
4
+ import type { Storage, StorageFactory } from './storage.js';
5
+
6
+ /** One instance, as every realization hands it over. */
7
+ export type Values = Record<string, unknown>;
8
+
9
+ /** Instances addressed by key — what an adapter supplies, and all of it. */
10
+ export interface Store {
11
+ get(key: string): Promise<Values | undefined>;
12
+ has(key: string): Promise<boolean>;
13
+ set(key: string, values: Values): Promise<void>;
14
+ delete(key: string): Promise<boolean>;
15
+ /** Everything it holds. A realization that cannot answer this cheaply says so in its doc. */
16
+ all(): Promise<Values[]>;
17
+ /** Handed on as `Storage.client` — the Map, the directory, whatever it is. */
18
+ readonly client: unknown;
19
+ }
20
+
21
+ export function storageOver(open: (entity: SchemaView, name: string) => Store): StorageFactory {
22
+ return (entity: SchemaView, name: string): Storage => {
23
+ const fields = entity.getFields();
24
+ const store = open(entity, name);
25
+ const pk = Object.entries(fields).find(([, field]) => Role.of(field).isPrimary)?.[0] ?? 'id';
26
+ // `Storage.findById(id: string)` — but a key can hold a number, and a Map keyed on
27
+ // `1` does not answer `'1'`. SQL never had the question; here the divergence was
28
+ // silent and only on this storage.
29
+ const keyOf = (value: unknown) => String(value);
30
+ // Same contract as SQL: a criterion may name a SET, and an empty set matches nothing.
31
+ // A comparison is told from a value by the FIELD, never by the criterion's own shape.
32
+ const matches = (values: Record<string, unknown>, criteria: Record<string, unknown>) =>
33
+ Object.entries(criteria).every(([key, value]) => {
34
+ const comparison = comparisonOf(fields[key], value);
35
+ if (comparison) return compares(values[key], comparison);
36
+
37
+ return Array.isArray(value)
38
+ ? value.some((v) => Object.is(values[key], v))
39
+ : Object.is(values[key], value);
40
+ });
41
+
42
+ // A store holds whole instances and reads them whole, so the scope SQL puts in its
43
+ // SELECT is applied here on the way out. Same set of gestures either way: everything
44
+ // that hands back an instance, which leaves `delete` and `upsertAll` alone.
45
+ const scoped = (selected?: Set<string>): Storage => {
46
+ const pick = (values: Values): Values => (selected
47
+ ? Object.fromEntries(Object.entries(values).filter(([key]) => selected.has(key)))
48
+ : values);
49
+
50
+ return {
51
+ client: store.client,
52
+ async list(options?: any) {
53
+ let items = await store.all();
54
+ if (options?.where) items = items.filter((values) => matches(values, options.where));
55
+ // Held before the page is cut, and after the filter: `total` answers "how many
56
+ // match", which is what a paginator divides. Reading `store.size` at the end
57
+ // answered a different question — everything the store holds, including the ones
58
+ // the filter exists to keep out of this caller's sight.
59
+ const matching = items.length;
60
+ const limit = options?.limit;
61
+ const offset = options?.page && limit ? (options.page - 1) * limit : options?.offset ?? 0;
62
+ if (offset > 0) items = items.slice(offset);
63
+ const hasMore = limit ? items.length > limit : false;
64
+ if (limit) items = items.slice(0, limit);
65
+ // The cursor is read before the scope cuts: a view that drops the key still
66
+ // pages, the way it does over SQL.
67
+ const endCursor = items.length > 0 ? String((items[items.length - 1] as any)[pk] ?? '') : undefined;
68
+ const result = items.map(pick) as any;
69
+ result.hasMore = hasMore;
70
+ result.endCursor = endCursor;
71
+ if (options?.count) result.total = matching;
72
+ return result;
73
+ },
74
+ async findById(id: string) {
75
+ const values = await store.get(keyOf(id));
76
+ return values && pick(values);
77
+ },
78
+ async findBy(criteria: Record<string, unknown>) {
79
+ const values = (await store.all()).find((held) => matches(held, criteria));
80
+ return values && pick(values);
81
+ },
82
+ async findAllBy(criteria: Record<string, unknown>) {
83
+ return (await store.all()).filter((values) => matches(values, criteria)).map(pick);
84
+ },
85
+ // Same contract as SQL: a map keyed by the primary key, a miss being an absent key.
86
+ async findByKeys(ids: readonly string[]) {
87
+ const found = new Map<string, Record<string, unknown>>();
88
+ for (const id of ids) {
89
+ const values = await store.get(keyOf(id));
90
+ if (values) found.set(String(id), pick(values));
91
+ }
92
+ return found;
93
+ },
94
+ // The dual, same contract as SQL: grouped by the value read off the instance.
95
+ async findAllByKeys(field: string, keys: readonly string[]) {
96
+ const grouped = new Map<string, Record<string, unknown>[]>();
97
+ if (keys.length === 0) return grouped;
98
+ const wanted = new Set(keys.map(String));
99
+ for (const values of await store.all()) {
100
+ const key = String(values[field]);
101
+ if (!wanted.has(key)) continue;
102
+ const bucket = grouped.get(key);
103
+ if (bucket) bucket.push(pick(values)); else grouped.set(key, [pick(values)]);
104
+ }
105
+ return grouped;
106
+ },
107
+ // Same contract as SQL: the key and the creation stamps survive an overwrite.
108
+ async upsert(input: Partial<Record<string, unknown>>) {
109
+ const values = applyCreate(fields, applyUpdate(fields, input));
110
+ const id = values[pk] as string | undefined;
111
+ if (id === undefined) throw new Error(`${name}.upsert(): no \`${pk}\` — an upsert needs the key it writes at.`);
112
+ const previous = await store.get(keyOf(id));
113
+ if (previous) {
114
+ for (const [key, field] of Object.entries(fields)) {
115
+ if (key === pk || Lifecycle.of(field).stampedOnce) values[key] = previous[key];
116
+ }
117
+ }
118
+ await store.set(keyOf(id), values);
119
+ return pick(values);
120
+ },
121
+ async upsertAll(inputs: readonly Partial<Record<string, unknown>>[]) {
122
+ for (const input of inputs) await this.upsert(input);
123
+ return inputs.length;
124
+ },
125
+ async create(input: Partial<Record<string, unknown>>) {
126
+ const values = applyCreate(fields, input);
127
+ const id = values[pk] as string | undefined;
128
+ // `primary(text())` declares no generator, so nothing fills the hole and the
129
+ // caller has to. Keying on `undefined` would let the second create overwrite the
130
+ // first, in silence — the old version hid this by inventing an `id` field the
131
+ // entity never declared.
132
+ if (id === undefined) {
133
+ throw new Error(`${name}.create: '${pk}' is the primary key and nothing supplied it — this entity declares no generator for it.`);
134
+ }
135
+ // A create is not an upsert. `Map.set` overwrites, so a second create under the
136
+ // same key answered "created" while destroying the previous instance — SQL answers a
137
+ // constraint violation, and a store that loses data silently is worse than one
138
+ // that fails.
139
+ if (await store.has(keyOf(id))) {
140
+ throw new Error(`${name}.create: '${pk}' ${JSON.stringify(id)} already exists.`);
141
+ }
142
+ await store.set(keyOf(id), values);
143
+ return pick(values);
144
+ },
145
+ async update(id: string, input: Partial<Record<string, unknown>>) {
146
+ const existing = await store.get(keyOf(id));
147
+ if (!existing) throw new Error(`Not found: ${id}`);
148
+ const updated = { ...existing, ...applyUpdate(fields, input), [pk]: existing[pk] };
149
+ await store.set(keyOf(id), updated);
150
+ return pick(updated);
151
+ },
152
+ async delete(id: string) { return await store.delete(keyOf(id)); },
153
+ output(schema: SchemaView) { return scoped(new Set(Object.keys(schema.getFields()))); },
154
+ };
155
+ };
156
+
157
+ return scoped();
158
+ };
159
+ }
160
+
161
+ /**
162
+ * The same comparisons SQL compiles, answered in memory. Every one a criterion names has
163
+ * to hold — the rule two criteria already follow.
164
+ */
165
+ function compares(held: unknown, comparison: Comparison): boolean {
166
+ return comparisonsIn(comparison).every(([name, asked]) => {
167
+ switch (name) {
168
+ case 'gte': return ordered(held, asked, (a, b) => a >= b);
169
+ case 'lte': return ordered(held, asked, (a, b) => a <= b);
170
+ case 'gt': return ordered(held, asked, (a, b) => a > b);
171
+ case 'lt': return ordered(held, asked, (a, b) => a < b);
172
+ case 'ne': return !Object.is(held, asked);
173
+ case 'contains': return String(held ?? '').includes(String(asked));
174
+ case 'notIn': return !(asked as readonly unknown[]).some((one) => Object.is(held, one));
175
+ case 'isNull': return (held === null || held === undefined) === Boolean(asked);
176
+ case 'between': {
177
+ const [low, high] = asked as [unknown, unknown];
178
+
179
+ return ordered(held, low, (a, b) => a >= b) && ordered(held, high, (a, b) => a <= b);
180
+ }
181
+ }
182
+ });
183
+ }
184
+
185
+ /** A row that holds nothing compares to nothing — the answer SQL gives for NULL. */
186
+ const ordered = (held: unknown, asked: unknown, holds: (a: number, b: number) => boolean): boolean =>
187
+ held === null || held === undefined ? false : holds(order(held), order(asked));
188
+
189
+ /** What a Date and a number have in common, and a string keeps for itself. */
190
+ const order = (value: unknown): number =>
191
+ value instanceof Date ? value.getTime() : (value as number);
package/src/verify.ts CHANGED
@@ -5,24 +5,11 @@ import { storageKeyOf } from './storage.js';
5
5
  import { presenterKeyOf } from './prefab/presenter.js';
6
6
  import { collectorKeyOf } from './prefab/collector.js';
7
7
 
8
- /**
9
- * What a rule found in an app.
10
- *
11
- * `message` is the sentence the rule replaces — the prose a human used to have
12
- * to remember. `Known issues` says "Keep collectors in the consuming frond";
13
- * this is that sentence, told about a specific handler, by something that runs.
14
- */
8
+ /** What a rule found in an app. */
15
9
  export interface Violation {
16
10
  /** Rule name, stable — 'cross-frond-dependency'. */
17
11
  rule: string;
18
- /**
19
- * What it costs, decided by the rule that raises it — never by whoever renders it.
20
- *
21
- * The two rules here are not the same animal: a cross-frond dependency resolves
22
- * today and stops resolving the day the other frond answers over the wire, while a
23
- * collector declared elsewhere is already wrong in one process. A reader holding a
24
- * table of rule names would be a second opinion on a fact the rule already has.
25
- */
12
+ /** What it costs, decided by the rule that raises it — never by whoever renders it. */
26
13
  severity: 'blocking' | 'warning';
27
14
  /** The frond the subject lives in. */
28
15
  frond: string;
@@ -30,15 +17,7 @@ export interface Violation {
30
17
  subject: string;
31
18
  /** Where to go and look. */
32
19
  filePath: string;
33
- /**
34
- * What the subject reaches for, and where it actually lives.
35
- *
36
- * `frond` above is the CONSUMER; the target used to exist only inside the
37
- * sentence. A reader that has to parse prose to learn which frond a violation
38
- * points at is a second opinion on a fact the checker already held — so the
39
- * boot can ask "does this violation target a frond named in `remotes:`?" by
40
- * reading a field.
41
- */
20
+ /** What the subject reaches for, and where it actually lives. */
42
21
  dependsOn: { key: string; frond: string; kind: string };
43
22
  /** What breaks, and what the caller gets instead. */
44
23
  message: string;
@@ -48,20 +27,16 @@ export interface Violation {
48
27
  type Registration = { frond: string; kind: string };
49
28
 
50
29
  /**
51
- * The container keys a frond registers in its own scope, keyed as a handler's
52
- * `deps` spell them — DI resolves by type name, so both sides are PascalCase.
53
- *
54
- * Every key comes from the function that states it, never from a derivation
55
- * respelled here: a second reader that spells one differently finds nothing and
56
- * reports nothing wrong, which is the failure mode a checker must not have.
30
+ * The container keys a frond registers in its own scope, keyed as a handler's `deps` spell them —
31
+ * DI resolves by type name, so both sides are PascalCase.
57
32
  */
58
33
  function registrationsOf(frond: FrondDescriptor): Map<string, Registration> {
59
34
  const out = new Map<string, Registration>();
60
35
  const put = (key: string, kind: string) => out.set(key, { frond: frond.name, kind });
61
36
 
62
- for (const p of frond.providers) put(p.ctor.name, 'provider');
63
- for (const p of frond.presenters) put(presenterKeyOf(p.entityName), 'presenter');
64
- for (const c of frond.collectors) put(collectorKeyOf(c.typeName), 'collector');
37
+ for (const provider of frond.providers) put(provider.ctor.name, 'provider');
38
+ for (const presenter of frond.presenters) put(presenterKeyOf(presenter.entityName), 'presenter');
39
+ for (const collector of frond.collectors) put(collectorKeyOf(collector.typeName), 'collector');
65
40
  for (const e of frond.entities) {
66
41
  put(storageKeyOf(e.name), 'storage');
67
42
  put(repositoryKeyOf(e.name), 'repository');
@@ -69,11 +44,7 @@ function registrationsOf(frond: FrondDescriptor): Map<string, Registration> {
69
44
  return out;
70
45
  }
71
46
 
72
- /**
73
- * Everything in a frond that is constructed by DI, so carries `deps`.
74
- * Handlers, presenters and collectors are all built from a constructor whose
75
- * argument types the scan read; each one can therefore reach across.
76
- */
47
+ /** Everything in a frond that is constructed by DI, so carries `deps`. */
77
48
  function injectablesOf(frond: FrondDescriptor) {
78
49
  return [
79
50
  ...frond.handlers.map((h) => ({ name: h.ctor.name, deps: h.deps, filePath: h.filePath })),
@@ -83,20 +54,8 @@ function injectablesOf(frond: FrondDescriptor) {
83
54
  }
84
55
 
85
56
  /**
86
- * Does this app survive being split?
87
- *
88
- * A frond runs in-process or in its own process behind JSON-RPC with identical
89
- * user code — that is the whole claim. What the claim does not say is that
90
- * *every* app survives the move: a dependency that crosses a frond boundary
91
- * resolves today because both scopes live in one container, and resolves to
92
- * nothing the day the other frond answers over the wire.
93
- *
94
- * The question only exists where a module boundary is meant to become a process
95
- * boundary later. Where every inter-module call is already remote there is
96
- * nothing to check, and where no exit is planned there is nothing to check
97
- * either. Here it means something, and until now it had no answer.
98
- *
99
- * Pure over `app.fronds`: no mount, no process, no file. Call it from a test.
57
+ * Does this app survive being split? A frond runs in-process or in its own process behind JSON-RPC
58
+ * with identical user code — that is the whole claim.
100
59
  */
101
60
  export function verify(app: { fronds: readonly FrondDescriptor[] }): Violation[] {
102
61
  const index = new Map<string, Registration>();
@@ -109,7 +68,7 @@ export function verify(app: { fronds: readonly FrondDescriptor[] }): Violation[]
109
68
  // they need their own index and their own rule.
110
69
  const collectorFronds = new Map<string, string>();
111
70
  for (const frond of app.fronds) {
112
- for (const c of frond.collectors) collectorFronds.set(c.typeName, frond.name);
71
+ for (const collector of frond.collectors) collectorFronds.set(collector.typeName, frond.name);
113
72
  }
114
73
 
115
74
  const violations: Violation[] = [];
@@ -144,8 +103,8 @@ export function verify(app: { fronds: readonly FrondDescriptor[] }): Violation[]
144
103
 
145
104
  // Rule 2 — an operation parameter that wanted a collector this frond has not
146
105
  // got. The preliminary binding convention can only see this frond's collector
147
- // set, so it produces body evidence. EffectiveOperation refuses that evidence
148
- // before boot: another frond's collector proves the provenance is not a body.
106
+ // set, so it produces input evidence. EffectiveOperation refuses that evidence
107
+ // before boot: another frond's collector proves the provenance is not an input.
149
108
  const own = new Set(frond.collectors.map((c) => c.typeName));
150
109
  for (const handler of frond.handlers) {
151
110
  for (const [opName, op] of handler.operations) {
@@ -156,7 +115,7 @@ export function verify(app: { fronds: readonly FrondDescriptor[] }): Violation[]
156
115
  const wanted = lowerFirst(param.type.name);
157
116
  if (own.has(wanted)) continue;
158
117
  const elsewhere = collectorFronds.get(wanted);
159
- // No collector anywhere for that type may be an ordinary body parameter.
118
+ // No collector anywhere for that type may be an ordinary input parameter.
160
119
  // Only a collector that exists in the wrong place makes that interpretation
161
120
  // provably false.
162
121
  if (!elsewhere) continue;
@@ -170,7 +129,7 @@ export function verify(app: { fronds: readonly FrondDescriptor[] }): Violation[]
170
129
  message:
171
130
  `'${param.name}' is typed ${param.type.name}, and the collector that produces one ` +
172
131
  `is declared in frond '${elsewhere}'. A binding plan only sees its own frond's ` +
173
- `collectors, so the preliminary body interpretation is invalid. Fougere refuses ` +
132
+ `collectors, so the preliminary input interpretation is invalid. Fougere refuses ` +
174
133
  `the operation before it can receive what the caller sent. ` +
175
134
  `Move the collector into '${frond.name}'.`,
176
135
  });
@@ -0,0 +1,30 @@
1
+ import type { RouteKind } from './RouteAddress.js';
2
+
3
+ /** What crosses the door. */
4
+ export interface CallRecord {
5
+ /** Monotonic, and the whole cursor protocol: a reader asks for what is above its own. */
6
+ seq: number;
7
+ frond?: string;
8
+ entity: string;
9
+ operation: string;
10
+ surface?: string;
11
+ /** Known at `resolved`, so absent on a call that never found a route. */
12
+ route?: RouteKind;
13
+ /** The traceparent the invocation carried, when one did. */
14
+ trace?: string;
15
+ /** The peer that established this call, when one did. */
16
+ caller?: string;
17
+ startedAt: number;
18
+ /** Known at `settled`. */
19
+ ms?: number;
20
+ verdict: 'running' | 'ok' | 'failed';
21
+ refusal?: { code?: string; message: string };
22
+ }
23
+
24
+ /** One page of the ring. */
25
+ export interface CallPage {
26
+ calls: CallRecord[];
27
+ cursor: number;
28
+ inFlight: number;
29
+ dropped: number;
30
+ }
@@ -1,15 +1,16 @@
1
1
  export interface InvocationContext {
2
2
  params: Record<string, unknown>;
3
3
  query: Record<string, unknown>;
4
- body: unknown;
4
+ input: unknown;
5
5
  state: Record<string, unknown>;
6
6
  trace?: string;
7
7
  identity?: string;
8
8
  caller?: string;
9
9
  }
10
10
 
11
- export type InvocationInput = Partial<InvocationContext>;
11
+ export type PartialInvocation = Partial<InvocationContext>;
12
12
 
13
+ /** Freezes plain data deeply, and leaves a class instance alone — a `Date` is not a record. */
13
14
  function canonicalValue(value: unknown): unknown {
14
15
  if (value === null || value === undefined || typeof value !== 'object') return value;
15
16
  if (Array.isArray(value)) return Object.freeze(value.map(canonicalValue));
@@ -19,6 +20,7 @@ function canonicalValue(value: unknown): unknown {
19
20
  return canonicalRecord(value);
20
21
  }
21
22
 
23
+ /** Drops the keys set to `undefined`, so an input and its JSON round-trip agree. */
22
24
  function canonicalRecord(value: unknown): Record<string, unknown> {
23
25
  if (!value || typeof value !== 'object' || Array.isArray(value)) return Object.freeze({});
24
26
 
@@ -33,33 +35,37 @@ function canonicalRecord(value: unknown): Record<string, unknown> {
33
35
  export class Invocation implements InvocationContext {
34
36
  readonly params: Record<string, unknown>;
35
37
  readonly query: Record<string, unknown>;
36
- readonly body: unknown;
38
+ readonly input: unknown;
37
39
  readonly state: Record<string, unknown>;
38
40
  readonly trace?: string;
39
41
  readonly identity?: string;
40
42
  readonly caller?: string;
41
43
 
42
- private constructor(input: InvocationInput) {
43
- this.params = canonicalRecord(input.params);
44
- this.query = canonicalRecord(input.query);
45
- this.body = canonicalValue(input.body);
44
+ /** Gives every entry and every transport the same seven-member value, frozen. */
45
+ private constructor(context: PartialInvocation) {
46
+ this.params = canonicalRecord(context.params);
47
+ this.query = canonicalRecord(context.query);
48
+ this.input = canonicalValue(context.input);
46
49
  // State is host-owned and may still be enriched by existing middlewares. Moving it
47
50
  // to immutable lifecycle context is a separate migration.
48
- this.state = input.state ?? {};
49
- if (input.trace !== undefined) this.trace = input.trace;
50
- if (input.identity !== undefined) this.identity = input.identity;
51
- if (input.caller !== undefined) this.caller = input.caller;
51
+ this.state = context.state ?? {};
52
+ if (context.trace !== undefined) this.trace = context.trace;
53
+ if (context.identity !== undefined) this.identity = context.identity;
54
+ if (context.caller !== undefined) this.caller = context.caller;
52
55
  Object.freeze(this);
53
56
  }
54
57
 
55
- static from(input?: InvocationInput): Invocation {
56
- return input instanceof Invocation ? input : new Invocation(input ?? {});
58
+ /** Takes a raw object or an invocation, so a caller never has to know which it holds. */
59
+ static from(context?: PartialInvocation): Invocation {
60
+ return context instanceof Invocation ? context : new Invocation(context ?? {});
57
61
  }
58
62
 
59
- withBody(body: unknown): Invocation {
60
- return new Invocation({ ...this, body });
63
+ /** Replaces the input — how the façade hands on the value it parsed. */
64
+ withInput(input: unknown): Invocation {
65
+ return new Invocation({ ...this, input });
61
66
  }
62
67
 
68
+ /** Replaces the host-owned state, which a middleware enriches before the handler runs. */
63
69
  withState(state: Record<string, unknown>): Invocation {
64
70
  return new Invocation({ ...this, state });
65
71
  }
@@ -67,6 +73,7 @@ export class Invocation implements InvocationContext {
67
73
 
68
74
  export const EMPTY_INVOCATION = Invocation.from();
69
75
 
70
- export function canonicalInvocation(input?: InvocationInput): Invocation {
71
- return Invocation.from(input);
76
+ /** Names the same gesture as `Invocation.from` for callers that read better this way. */
77
+ export function canonicalInvocation(context?: PartialInvocation): Invocation {
78
+ return Invocation.from(context);
72
79
  }
@@ -7,11 +7,13 @@ export interface RouteAddressInput {
7
7
  surface?: string;
8
8
  }
9
9
 
10
+ /** Refuses an empty segment, so no address can be built that nothing can serve. */
10
11
  function required(value: string, name: string): string {
11
12
  if (value.trim().length === 0) throw new TypeError(`Route ${name} cannot be empty`);
12
13
  return value;
13
14
  }
14
15
 
16
+ /** Applies the same refusal to a segment that may be absent, but not blank. */
15
17
  function optional(value: string | undefined, name: string): string | undefined {
16
18
  return value === undefined ? undefined : required(value, name);
17
19
  }
@@ -22,6 +24,7 @@ export class RouteAddress {
22
24
  readonly operation: string;
23
25
  readonly surface?: string;
24
26
 
27
+ /** Names one callable operation, and freezes it so a registry key cannot drift. */
25
28
  constructor(input: RouteAddressInput) {
26
29
  this.entity = required(input.entity, 'entity');
27
30
  this.operation = required(input.operation, 'operation');
@@ -29,19 +32,23 @@ export class RouteAddress {
29
32
  Object.freeze(this);
30
33
  }
31
34
 
35
+ /** Serializes the three segments so a route can be looked up in a `Map`. */
32
36
  key(): string {
33
37
  return JSON.stringify([this.surface ?? null, this.entity, this.operation]);
34
38
  }
35
39
 
40
+ /** Compares two addresses by their key, so `surface` counts as much as the operation. */
36
41
  equals(other: RouteAddress): boolean {
37
42
  return this.key() === other.key();
38
43
  }
39
44
 
45
+ /** Writes the address the way a log and an error message name it. */
40
46
  toString(): string {
41
47
  const audience = this.surface ? `${this.surface}/` : '';
42
48
  return `${audience}${this.entity}.${this.operation}`;
43
49
  }
44
50
 
51
+ /** Sends the address over the wire without `surface: undefined` riding along. */
45
52
  toJSON(): RouteAddressInput {
46
53
  return {
47
54
  entity: this.entity,
@@ -1,10 +1,6 @@
1
1
  /**
2
- * Where each parameter of an operation gets its value — decided once at boot from the
3
- * parsed signature, replayed per call by `resolveArgs`.
4
- *
5
- * The branches are ORDERED and each states why it sits where it does; the list used to
6
- * be repeated here too, and it had already lost `Fact` — the one whose position is
7
- * load-bearing, since the fall-through would otherwise hand it the caller's body.
2
+ * Where each parameter of an operation gets its value — decided once at boot from the parsed
3
+ * signature, replayed per call by `resolveArgs`.
8
4
  */
9
5
  import type { Param } from './signature.js';
10
6
  import { lowerFirst } from '@fougere/schema';
@@ -13,17 +9,10 @@ import { lowerFirst } from '@fougere/schema';
13
9
 
14
10
  type ParamSource =
15
11
  | { kind: 'collector'; typeName: string }
16
- /**
17
- * `Fact<PostPublished>` — something that happened, not something a caller typed.
18
- *
19
- * It resolves from the body exactly like `body` does, and that is deliberate: an
20
- * emission and a direct call ARE the same call, so a subscriber cannot tell them apart
21
- * and does not need to. The branch exists so the PLAN says what this parameter is —
22
- * that sentence is what makes the subscriber index readable without reparsing types.
23
- */
12
+ /** `Fact<PostPublished>` — something that happened, not something a caller typed. */
24
13
  | { kind: 'fact'; factName: string }
25
14
  | { kind: 'param'; name: string; coerce?: 'number' | 'boolean' }
26
- | { kind: 'body' }
15
+ | { kind: 'input' }
27
16
  | { kind: 'context' }
28
17
  /** The whole query bag, for an op whose argument IS the options (list). */
29
18
  | { kind: 'query' };
@@ -48,12 +37,7 @@ function coercionFor(typeName: string): 'number' | 'boolean' | undefined {
48
37
 
49
38
  // ── Compute ───────────────────────────────────
50
39
 
51
- /**
52
- * Build a BindingPlan from parsed method params.
53
- *
54
- * @param params - Parsed parameter list from AST
55
- * @param collectorTypeNames - Registration keys of the types a Collector answers for
56
- */
40
+ /** Build a BindingPlan from parsed method params. */
57
41
  export function computeBindingPlan(
58
42
  params: Param[],
59
43
  collectorTypeNames: Set<string>,
@@ -62,11 +46,11 @@ export function computeBindingPlan(
62
46
  const typeName = param.type.name;
63
47
  // `lowerFirst`, never `toLowerCase()`: the collector set is keyed the way the
64
48
  // scan spells it, and the two agree on one word only — `AuthorUser` looked up as
65
- // `authoruser` missed `authorUser` and fell through to branch 4, the request body.
49
+ // `authoruser` missed `authorUser` and fell through to branch 4, the request input.
66
50
  const typeKey = lowerFirst(typeName);
67
51
 
68
52
  // 0. Fact — `Fact<X>` names itself, so nothing has to be known in advance. It comes
69
- // FIRST because branch 4 would otherwise hand it the caller's body under the name
53
+ // FIRST because branch 4 would otherwise hand it the caller's input under the name
70
54
  // of something that happened.
71
55
  const factOf = param.type.name === 'Fact' ? param.type.generics?.[0]?.name : undefined;
72
56
  if (factOf) {
@@ -108,10 +92,10 @@ export function computeBindingPlan(
108
92
  };
109
93
  }
110
94
 
111
- // 4. Everything else — body
95
+ // 4. Everything else — input
112
96
  return {
113
97
  name: param.name,
114
- source: { kind: 'body' as const },
98
+ source: { kind: 'input' as const },
115
99
  optional: param.optional ?? false,
116
100
  };
117
101
  });