@fougere/core 0.5.0-alpha.1 → 0.7.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 (519) hide show
  1. package/README.md +1 -1
  2. package/dist/boot/Emissions.d.ts +14 -91
  3. package/dist/boot/Emissions.d.ts.map +1 -1
  4. package/dist/boot/Emissions.js +21 -118
  5. package/dist/boot/Emissions.js.map +1 -1
  6. package/dist/boot/ambient-port.d.ts +3 -24
  7. package/dist/boot/ambient-port.d.ts.map +1 -1
  8. package/dist/boot/ambient.als.d.ts.map +1 -1
  9. package/dist/boot/ambient.als.js +7 -12
  10. package/dist/boot/ambient.als.js.map +1 -1
  11. package/dist/boot/ambient.queue.d.ts +2 -5
  12. package/dist/boot/ambient.queue.d.ts.map +1 -1
  13. package/dist/boot/ambient.queue.js.map +1 -1
  14. package/dist/boot/apply.d.ts +1 -13
  15. package/dist/boot/apply.d.ts.map +1 -1
  16. package/dist/boot/apply.js +3 -15
  17. package/dist/boot/apply.js.map +1 -1
  18. package/dist/boot/auth.d.ts +6 -16
  19. package/dist/boot/auth.d.ts.map +1 -1
  20. package/dist/boot/boot.d.ts +5 -18
  21. package/dist/boot/boot.d.ts.map +1 -1
  22. package/dist/boot/boot.js +4 -11
  23. package/dist/boot/boot.js.map +1 -1
  24. package/dist/boot/bootstrap.d.ts.map +1 -1
  25. package/dist/boot/bootstrap.js +106 -163
  26. package/dist/boot/bootstrap.js.map +1 -1
  27. package/dist/boot/card.d.ts +5 -0
  28. package/dist/boot/card.d.ts.map +1 -0
  29. package/dist/boot/card.js +71 -0
  30. package/dist/boot/card.js.map +1 -0
  31. package/dist/boot/frame.d.ts +8 -32
  32. package/dist/boot/frame.d.ts.map +1 -1
  33. package/dist/boot/frame.js +23 -57
  34. package/dist/boot/frame.js.map +1 -1
  35. package/dist/boot/hosted.d.ts +3 -19
  36. package/dist/boot/hosted.d.ts.map +1 -1
  37. package/dist/boot/hosted.js +12 -17
  38. package/dist/boot/hosted.js.map +1 -1
  39. package/dist/boot/ownership.d.ts +5 -36
  40. package/dist/boot/ownership.d.ts.map +1 -1
  41. package/dist/boot/ownership.js +9 -49
  42. package/dist/boot/ownership.js.map +1 -1
  43. package/dist/boot/ports.d.ts +2 -15
  44. package/dist/boot/ports.d.ts.map +1 -1
  45. package/dist/boot/ports.js +1 -14
  46. package/dist/boot/ports.js.map +1 -1
  47. package/dist/boot/remote.d.ts +5 -38
  48. package/dist/boot/remote.d.ts.map +1 -1
  49. package/dist/boot/remote.js +8 -41
  50. package/dist/boot/remote.js.map +1 -1
  51. package/dist/boot/runner.d.ts +11 -0
  52. package/dist/boot/runner.d.ts.map +1 -0
  53. package/dist/boot/runner.js +13 -0
  54. package/dist/boot/runner.js.map +1 -0
  55. package/dist/boot/seed.d.ts +5 -32
  56. package/dist/boot/seed.d.ts.map +1 -1
  57. package/dist/boot/seed.js +10 -41
  58. package/dist/boot/seed.js.map +1 -1
  59. package/dist/boot/statement-drift.d.ts +4 -22
  60. package/dist/boot/statement-drift.d.ts.map +1 -1
  61. package/dist/boot/statement-drift.js +4 -9
  62. package/dist/boot/statement-drift.js.map +1 -1
  63. package/dist/boot/together.d.ts +8 -12
  64. package/dist/boot/together.d.ts.map +1 -1
  65. package/dist/boot/together.js +28 -65
  66. package/dist/boot/together.js.map +1 -1
  67. package/dist/boot/types.d.ts +36 -180
  68. package/dist/boot/types.d.ts.map +1 -1
  69. package/dist/builtin/config.d.ts +7 -0
  70. package/dist/builtin/config.d.ts.map +1 -0
  71. package/dist/builtin/config.js +15 -0
  72. package/dist/builtin/config.js.map +1 -0
  73. package/dist/{builtins → builtin}/logger.d.ts +4 -25
  74. package/dist/builtin/logger.d.ts.map +1 -0
  75. package/dist/{builtins → builtin}/logger.js +5 -32
  76. package/dist/builtin/logger.js.map +1 -0
  77. package/dist/config-loader.d.ts +9 -67
  78. package/dist/config-loader.d.ts.map +1 -1
  79. package/dist/config-loader.js +5 -18
  80. package/dist/config-loader.js.map +1 -1
  81. package/dist/contract.d.ts +13 -31
  82. package/dist/contract.d.ts.map +1 -1
  83. package/dist/contract.js +10 -26
  84. package/dist/contract.js.map +1 -1
  85. package/dist/crypto/encoding.d.ts +2 -15
  86. package/dist/crypto/encoding.d.ts.map +1 -1
  87. package/dist/crypto/encoding.js +2 -15
  88. package/dist/crypto/encoding.js.map +1 -1
  89. package/dist/crypto/node.d.ts.map +1 -1
  90. package/dist/crypto/node.js +1 -7
  91. package/dist/crypto/node.js.map +1 -1
  92. package/dist/crypto/port.d.ts +2 -18
  93. package/dist/crypto/port.d.ts.map +1 -1
  94. package/dist/crypto/port.js +1 -17
  95. package/dist/crypto/port.js.map +1 -1
  96. package/dist/crypto/webcrypto.d.ts.map +1 -1
  97. package/dist/crypto/webcrypto.js +1 -12
  98. package/dist/crypto/webcrypto.js.map +1 -1
  99. package/dist/declare.d.ts +41 -0
  100. package/dist/declare.d.ts.map +1 -0
  101. package/dist/{scan/declare.js → declare.js} +6 -31
  102. package/dist/declare.js.map +1 -0
  103. package/dist/define.d.ts +2 -3
  104. package/dist/define.d.ts.map +1 -1
  105. package/dist/define.js +2 -3
  106. package/dist/define.js.map +1 -1
  107. package/dist/descriptor/Fronds.d.ts +19 -0
  108. package/dist/descriptor/Fronds.d.ts.map +1 -0
  109. package/dist/descriptor/Fronds.js +40 -0
  110. package/dist/descriptor/Fronds.js.map +1 -0
  111. package/dist/descriptor/frond.d.ts +135 -0
  112. package/dist/descriptor/frond.d.ts.map +1 -0
  113. package/dist/{scan → descriptor}/frond.js.map +1 -1
  114. package/dist/dispatch/ArgumentResolver.d.ts +6 -3
  115. package/dist/dispatch/ArgumentResolver.d.ts.map +1 -1
  116. package/dist/dispatch/ArgumentResolver.js +48 -3
  117. package/dist/dispatch/ArgumentResolver.js.map +1 -1
  118. package/dist/dispatch/DispatchEvent.d.ts +2 -2
  119. package/dist/dispatch/DispatchEvent.d.ts.map +1 -1
  120. package/dist/dispatch/DispatchLifecycle.d.ts +1 -7
  121. package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -1
  122. package/dist/dispatch/DispatchLifecycle.js +1 -7
  123. package/dist/dispatch/DispatchLifecycle.js.map +1 -1
  124. package/dist/dispatch/DispatchPort.d.ts +1 -1
  125. package/dist/dispatch/DispatchPort.d.ts.map +1 -1
  126. package/dist/dispatch/Dispatcher.d.ts +1 -1
  127. package/dist/dispatch/Dispatcher.d.ts.map +1 -1
  128. package/dist/dispatch/Dispatcher.js +2 -2
  129. package/dist/dispatch/Dispatcher.js.map +1 -1
  130. package/dist/{boot → dispatch}/HandlerFacade.d.ts +25 -38
  131. package/dist/dispatch/HandlerFacade.d.ts.map +1 -0
  132. package/dist/{boot → dispatch}/HandlerFacade.js +65 -74
  133. package/dist/dispatch/HandlerFacade.js.map +1 -0
  134. package/dist/dispatch/LocalRoutePolicy.d.ts +1 -1
  135. package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -1
  136. package/dist/dispatch/LocalRoutePolicy.js +4 -4
  137. package/dist/dispatch/LocalRoutePolicy.js.map +1 -1
  138. package/dist/dispatch/OperationRoute.d.ts +2 -2
  139. package/dist/dispatch/OperationRoute.d.ts.map +1 -1
  140. package/dist/dispatch/OutputView.d.ts +3 -2
  141. package/dist/dispatch/OutputView.d.ts.map +1 -1
  142. package/dist/dispatch/OutputView.js +19 -1
  143. package/dist/dispatch/OutputView.js.map +1 -1
  144. package/dist/dispatch/Route.d.ts +2 -3
  145. package/dist/dispatch/Route.d.ts.map +1 -1
  146. package/dist/dispatch/RoutePolicy.d.ts +1 -1
  147. package/dist/dispatch/RoutePolicy.d.ts.map +1 -1
  148. package/dist/dispatch/RouteRegistry.d.ts +1 -1
  149. package/dist/dispatch/RouteRegistry.d.ts.map +1 -1
  150. package/dist/dispatch/RouteRegistry.js +2 -2
  151. package/dist/dispatch/RouteRegistry.js.map +1 -1
  152. package/dist/dispatch/RouteResolver.d.ts +2 -4
  153. package/dist/dispatch/RouteResolver.d.ts.map +1 -1
  154. package/dist/dispatch/StorageGuard.d.ts +9 -8
  155. package/dist/dispatch/StorageGuard.d.ts.map +1 -1
  156. package/dist/dispatch/StorageGuard.js +66 -23
  157. package/dist/dispatch/StorageGuard.js.map +1 -1
  158. package/dist/dispatch/presenterArguments.d.ts +7 -0
  159. package/dist/dispatch/presenterArguments.d.ts.map +1 -0
  160. package/dist/dispatch/presenterArguments.js +12 -0
  161. package/dist/dispatch/presenterArguments.js.map +1 -0
  162. package/dist/dispatch/remoteRoutes.d.ts +7 -0
  163. package/dist/dispatch/remoteRoutes.d.ts.map +1 -0
  164. package/dist/dispatch/{RemoteRouteResolver.js → remoteRoutes.js} +6 -10
  165. package/dist/dispatch/remoteRoutes.js.map +1 -0
  166. package/dist/dispatch/routeNotFound.d.ts +9 -0
  167. package/dist/dispatch/routeNotFound.d.ts.map +1 -0
  168. package/dist/dispatch/routeNotFound.js +21 -0
  169. package/dist/dispatch/routeNotFound.js.map +1 -0
  170. package/dist/dispatch/validateInput.d.ts +5 -0
  171. package/dist/dispatch/validateInput.d.ts.map +1 -0
  172. package/dist/dispatch/validateInput.js +20 -0
  173. package/dist/dispatch/validateInput.js.map +1 -0
  174. package/dist/effective-operation.d.ts +6 -3
  175. package/dist/effective-operation.d.ts.map +1 -1
  176. package/dist/effective-operation.js +49 -27
  177. package/dist/effective-operation.js.map +1 -1
  178. package/dist/emit.d.ts +4 -42
  179. package/dist/emit.d.ts.map +1 -1
  180. package/dist/emit.js +3 -39
  181. package/dist/emit.js.map +1 -1
  182. package/dist/entry/facade.d.ts +8 -0
  183. package/dist/entry/facade.d.ts.map +1 -0
  184. package/dist/entry/facade.js +28 -0
  185. package/dist/entry/facade.js.map +1 -0
  186. package/dist/entry/transport.d.ts +5 -0
  187. package/dist/entry/transport.d.ts.map +1 -0
  188. package/dist/entry/transport.js +11 -0
  189. package/dist/entry/transport.js.map +1 -0
  190. package/dist/frond-config.d.ts +8 -71
  191. package/dist/frond-config.d.ts.map +1 -1
  192. package/dist/frond-config.js +1 -9
  193. package/dist/frond-config.js.map +1 -1
  194. package/dist/graph.d.ts +1 -1
  195. package/dist/graph.d.ts.map +1 -1
  196. package/dist/identity-keys.d.ts +2 -5
  197. package/dist/identity-keys.d.ts.map +1 -1
  198. package/dist/identity-keys.js +3 -16
  199. package/dist/identity-keys.js.map +1 -1
  200. package/dist/identity.d.ts +4 -30
  201. package/dist/identity.d.ts.map +1 -1
  202. package/dist/identity.js +11 -73
  203. package/dist/identity.js.map +1 -1
  204. package/dist/imports.d.ts +2 -8
  205. package/dist/imports.d.ts.map +1 -1
  206. package/dist/imports.js +1 -7
  207. package/dist/imports.js.map +1 -1
  208. package/dist/index.d.ts +28 -30
  209. package/dist/index.d.ts.map +1 -1
  210. package/dist/index.js +17 -22
  211. package/dist/index.js.map +1 -1
  212. package/dist/loader.d.ts +1 -8
  213. package/dist/loader.d.ts.map +1 -1
  214. package/dist/loader.js +1 -8
  215. package/dist/loader.js.map +1 -1
  216. package/dist/node.d.ts +2 -11
  217. package/dist/node.d.ts.map +1 -1
  218. package/dist/node.js +2 -11
  219. package/dist/node.js.map +1 -1
  220. package/dist/prefab/collector.d.ts +1 -22
  221. package/dist/prefab/collector.d.ts.map +1 -1
  222. package/dist/prefab/collector.js +1 -22
  223. package/dist/prefab/collector.js.map +1 -1
  224. package/dist/prefab/crud.d.ts +19 -35
  225. package/dist/prefab/crud.d.ts.map +1 -1
  226. package/dist/prefab/crud.js +39 -66
  227. package/dist/prefab/crud.js.map +1 -1
  228. package/dist/prefab/mirror.d.ts +5 -27
  229. package/dist/prefab/mirror.d.ts.map +1 -1
  230. package/dist/prefab/mirror.js +6 -24
  231. package/dist/prefab/mirror.js.map +1 -1
  232. package/dist/prefab/prefab.d.ts +1 -7
  233. package/dist/prefab/prefab.d.ts.map +1 -1
  234. package/dist/prefab/prefab.js +1 -7
  235. package/dist/prefab/prefab.js.map +1 -1
  236. package/dist/prefab/presenter.d.ts +2 -36
  237. package/dist/prefab/presenter.d.ts.map +1 -1
  238. package/dist/prefab/presenter.js +2 -36
  239. package/dist/prefab/presenter.js.map +1 -1
  240. package/dist/prefab/repository.d.ts +12 -80
  241. package/dist/prefab/repository.d.ts.map +1 -1
  242. package/dist/prefab/repository.js +22 -35
  243. package/dist/prefab/repository.js.map +1 -1
  244. package/dist/scan/adapters.d.ts +3 -0
  245. package/dist/scan/adapters.d.ts.map +1 -0
  246. package/dist/scan/adapters.js +25 -0
  247. package/dist/scan/adapters.js.map +1 -0
  248. package/dist/scan/bundling.d.ts +1 -12
  249. package/dist/scan/bundling.d.ts.map +1 -1
  250. package/dist/scan/bundling.js +1 -12
  251. package/dist/scan/bundling.js.map +1 -1
  252. package/dist/scan/conventions.d.ts +6 -40
  253. package/dist/scan/conventions.d.ts.map +1 -1
  254. package/dist/scan/conventions.js +5 -34
  255. package/dist/scan/conventions.js.map +1 -1
  256. package/dist/scan/emit.d.ts +2 -6
  257. package/dist/scan/emit.d.ts.map +1 -1
  258. package/dist/scan/emit.js +5 -39
  259. package/dist/scan/emit.js.map +1 -1
  260. package/dist/scan/handler-parser.d.ts +9 -76
  261. package/dist/scan/handler-parser.d.ts.map +1 -1
  262. package/dist/scan/handler-parser.js +28 -85
  263. package/dist/scan/handler-parser.js.map +1 -1
  264. package/dist/scan/result.d.ts +28 -0
  265. package/dist/scan/result.d.ts.map +1 -0
  266. package/dist/scan/result.js +2 -0
  267. package/dist/scan/result.js.map +1 -0
  268. package/dist/scan/scanner.d.ts +3 -28
  269. package/dist/scan/scanner.d.ts.map +1 -1
  270. package/dist/scan/scanner.js +36 -135
  271. package/dist/scan/scanner.js.map +1 -1
  272. package/dist/scan/statement.d.ts +1 -1
  273. package/dist/scan/statement.d.ts.map +1 -1
  274. package/dist/scan/statement.js +4 -30
  275. package/dist/scan/statement.js.map +1 -1
  276. package/dist/source.d.ts +41 -0
  277. package/dist/source.d.ts.map +1 -0
  278. package/dist/source.js +10 -0
  279. package/dist/source.js.map +1 -0
  280. package/dist/storage.d.ts +92 -0
  281. package/dist/storage.d.ts.map +1 -0
  282. package/dist/storage.js +50 -0
  283. package/dist/storage.js.map +1 -0
  284. package/dist/store.d.ts +18 -0
  285. package/dist/store.d.ts.map +1 -0
  286. package/dist/store.js +146 -0
  287. package/dist/store.js.map +1 -0
  288. package/dist/verify.d.ts +6 -39
  289. package/dist/verify.d.ts.map +1 -1
  290. package/dist/verify.js +19 -39
  291. package/dist/verify.js.map +1 -1
  292. package/dist/wire/CallLog.d.ts +32 -0
  293. package/dist/wire/CallLog.d.ts.map +1 -0
  294. package/dist/{contract → wire}/CallLog.js.map +1 -1
  295. package/dist/wire/Invocation.d.ts +32 -0
  296. package/dist/wire/Invocation.d.ts.map +1 -0
  297. package/dist/wire/Invocation.js +66 -0
  298. package/dist/wire/Invocation.js.map +1 -0
  299. package/dist/wire/RouteAddress.d.ts +24 -0
  300. package/dist/wire/RouteAddress.d.ts.map +1 -0
  301. package/dist/{contract → wire}/RouteAddress.js +7 -0
  302. package/dist/wire/RouteAddress.js.map +1 -0
  303. package/dist/wire/binding.d.ts +36 -0
  304. package/dist/wire/binding.d.ts.map +1 -0
  305. package/dist/{boot → wire}/binding.js +5 -62
  306. package/dist/wire/binding.js.map +1 -0
  307. package/dist/wire/call.d.ts +25 -172
  308. package/dist/wire/call.d.ts.map +1 -1
  309. package/dist/wire/call.js +15 -166
  310. package/dist/wire/call.js.map +1 -1
  311. package/dist/wire/drift.d.ts +3 -28
  312. package/dist/wire/drift.d.ts.map +1 -1
  313. package/dist/wire/drift.js +4 -23
  314. package/dist/wire/drift.js.map +1 -1
  315. package/dist/wire/errors.d.ts +4 -24
  316. package/dist/wire/errors.d.ts.map +1 -1
  317. package/dist/wire/errors.js +4 -24
  318. package/dist/wire/errors.js.map +1 -1
  319. package/dist/wire/http-error.d.ts +2 -13
  320. package/dist/wire/http-error.d.ts.map +1 -1
  321. package/dist/wire/http-error.js +5 -19
  322. package/dist/wire/http-error.js.map +1 -1
  323. package/dist/wire/loggerMiddleware.d.ts +2 -8
  324. package/dist/wire/loggerMiddleware.d.ts.map +1 -1
  325. package/dist/wire/loggerMiddleware.js +1 -7
  326. package/dist/wire/loggerMiddleware.js.map +1 -1
  327. package/dist/wire/middleware.d.ts +3 -7
  328. package/dist/wire/middleware.d.ts.map +1 -1
  329. package/dist/wire/middleware.js +1 -5
  330. package/dist/wire/middleware.js.map +1 -1
  331. package/dist/wire/operation.d.ts +12 -74
  332. package/dist/wire/operation.d.ts.map +1 -1
  333. package/dist/wire/operation.js +4 -66
  334. package/dist/wire/operation.js.map +1 -1
  335. package/dist/wire/signature.d.ts +37 -0
  336. package/dist/wire/signature.d.ts.map +1 -0
  337. package/dist/wire/signature.js +2 -0
  338. package/dist/wire/signature.js.map +1 -0
  339. package/package.json +3 -3
  340. package/src/boot/Emissions.ts +22 -119
  341. package/src/boot/ambient-port.ts +3 -24
  342. package/src/boot/ambient.als.ts +7 -12
  343. package/src/boot/ambient.queue.ts +2 -5
  344. package/src/boot/apply.ts +3 -15
  345. package/src/boot/auth.ts +6 -16
  346. package/src/boot/boot.ts +8 -23
  347. package/src/boot/bootstrap.ts +117 -173
  348. package/src/boot/card.ts +84 -0
  349. package/src/boot/frame.ts +31 -65
  350. package/src/boot/hosted.ts +15 -40
  351. package/src/boot/ownership.ts +14 -49
  352. package/src/boot/ports.ts +2 -15
  353. package/src/boot/remote.ts +11 -58
  354. package/src/boot/runner.ts +17 -0
  355. package/src/boot/seed.ts +11 -42
  356. package/src/boot/statement-drift.ts +10 -28
  357. package/src/boot/together.ts +38 -72
  358. package/src/boot/types.ts +36 -180
  359. package/src/{builtins → builtin}/config.ts +1 -7
  360. package/src/{builtins → builtin}/logger.ts +6 -39
  361. package/src/config-loader.ts +12 -71
  362. package/src/contract.ts +15 -39
  363. package/src/crypto/encoding.ts +2 -15
  364. package/src/crypto/node.ts +1 -7
  365. package/src/crypto/port.ts +2 -18
  366. package/src/crypto/webcrypto.ts +1 -12
  367. package/src/{scan/declare.ts → declare.ts} +11 -42
  368. package/src/define.ts +2 -3
  369. package/src/descriptor/Fronds.ts +47 -0
  370. package/src/descriptor/frond.ts +145 -0
  371. package/src/dispatch/ArgumentResolver.ts +54 -8
  372. package/src/dispatch/DispatchEvent.ts +2 -2
  373. package/src/dispatch/DispatchLifecycle.ts +1 -7
  374. package/src/dispatch/DispatchPort.ts +1 -1
  375. package/src/dispatch/Dispatcher.ts +3 -3
  376. package/src/dispatch/HandlerFacade.ts +231 -0
  377. package/src/dispatch/LocalRoutePolicy.ts +4 -4
  378. package/src/dispatch/OperationRoute.ts +2 -2
  379. package/src/dispatch/OutputView.ts +24 -2
  380. package/src/dispatch/Route.ts +2 -4
  381. package/src/dispatch/RoutePolicy.ts +1 -1
  382. package/src/dispatch/RouteRegistry.ts +2 -2
  383. package/src/dispatch/RouteResolver.ts +2 -4
  384. package/src/dispatch/StorageGuard.ts +75 -23
  385. package/src/dispatch/presenterArguments.ts +25 -0
  386. package/src/dispatch/{RemoteRouteResolver.ts → remoteRoutes.ts} +7 -9
  387. package/src/dispatch/routeNotFound.ts +33 -0
  388. package/src/dispatch/validateInput.ts +28 -0
  389. package/src/effective-operation.ts +60 -37
  390. package/src/emit.ts +5 -63
  391. package/src/entry/facade.ts +44 -0
  392. package/src/entry/transport.ts +16 -0
  393. package/src/frond-config.ts +8 -71
  394. package/src/graph.ts +1 -1
  395. package/src/identity-keys.ts +3 -16
  396. package/src/identity.ts +12 -80
  397. package/src/imports.ts +3 -32
  398. package/src/index.ts +28 -33
  399. package/src/loader.ts +2 -16
  400. package/src/node.ts +2 -11
  401. package/src/prefab/collector.ts +1 -22
  402. package/src/prefab/crud.ts +51 -90
  403. package/src/prefab/mirror.ts +9 -49
  404. package/src/prefab/prefab.ts +2 -21
  405. package/src/prefab/presenter.ts +2 -36
  406. package/src/prefab/repository.ts +32 -108
  407. package/src/scan/adapters.ts +32 -0
  408. package/src/scan/bundling.ts +1 -12
  409. package/src/scan/conventions.ts +6 -40
  410. package/src/scan/emit.ts +7 -43
  411. package/src/scan/handler-parser.ts +41 -163
  412. package/src/scan/result.ts +29 -0
  413. package/src/scan/scanner.ts +40 -138
  414. package/src/scan/statement.ts +6 -31
  415. package/src/source.ts +44 -0
  416. package/src/storage.ts +141 -0
  417. package/src/store.ts +152 -0
  418. package/src/verify.ts +19 -60
  419. package/src/wire/CallLog.ts +30 -0
  420. package/src/{contract → wire}/Invocation.ts +24 -17
  421. package/src/{contract → wire}/RouteAddress.ts +10 -0
  422. package/src/wire/binding.ts +102 -0
  423. package/src/wire/call.ts +30 -261
  424. package/src/wire/drift.ts +5 -30
  425. package/src/wire/errors.ts +4 -24
  426. package/src/wire/http-error.ts +5 -19
  427. package/src/wire/loggerMiddleware.ts +2 -8
  428. package/src/wire/middleware.ts +3 -7
  429. package/src/wire/operation.ts +13 -110
  430. package/src/wire/signature.ts +38 -0
  431. package/dist/boot/HandlerFacade.d.ts.map +0 -1
  432. package/dist/boot/HandlerFacade.js.map +0 -1
  433. package/dist/boot/binding.d.ts +0 -60
  434. package/dist/boot/binding.d.ts.map +0 -1
  435. package/dist/boot/binding.js.map +0 -1
  436. package/dist/builtins/config.d.ts +0 -13
  437. package/dist/builtins/config.d.ts.map +0 -1
  438. package/dist/builtins/config.js +0 -21
  439. package/dist/builtins/config.js.map +0 -1
  440. package/dist/builtins/logger.d.ts.map +0 -1
  441. package/dist/builtins/logger.js.map +0 -1
  442. package/dist/contract/Call.d.ts +0 -10
  443. package/dist/contract/Call.d.ts.map +0 -1
  444. package/dist/contract/Call.js +0 -15
  445. package/dist/contract/Call.js.map +0 -1
  446. package/dist/contract/CallLog.d.ts +0 -57
  447. package/dist/contract/CallLog.d.ts.map +0 -1
  448. package/dist/contract/Invocation.d.ts +0 -27
  449. package/dist/contract/Invocation.d.ts.map +0 -1
  450. package/dist/contract/Invocation.js +0 -59
  451. package/dist/contract/Invocation.js.map +0 -1
  452. package/dist/contract/RouteAddress.d.ts +0 -17
  453. package/dist/contract/RouteAddress.d.ts.map +0 -1
  454. package/dist/contract/RouteAddress.js.map +0 -1
  455. package/dist/dispatch/InputValidator.d.ts +0 -7
  456. package/dist/dispatch/InputValidator.d.ts.map +0 -1
  457. package/dist/dispatch/InputValidator.js +0 -22
  458. package/dist/dispatch/InputValidator.js.map +0 -1
  459. package/dist/dispatch/OperationExecutor.d.ts +0 -25
  460. package/dist/dispatch/OperationExecutor.d.ts.map +0 -1
  461. package/dist/dispatch/OperationExecutor.js +0 -32
  462. package/dist/dispatch/OperationExecutor.js.map +0 -1
  463. package/dist/dispatch/OutputProjector.d.ts +0 -12
  464. package/dist/dispatch/OutputProjector.d.ts.map +0 -1
  465. package/dist/dispatch/OutputProjector.js +0 -30
  466. package/dist/dispatch/OutputProjector.js.map +0 -1
  467. package/dist/dispatch/PresenterArgumentResolver.d.ts +0 -12
  468. package/dist/dispatch/PresenterArgumentResolver.d.ts.map +0 -1
  469. package/dist/dispatch/PresenterArgumentResolver.js +0 -20
  470. package/dist/dispatch/PresenterArgumentResolver.js.map +0 -1
  471. package/dist/dispatch/RemoteRouteResolver.d.ts +0 -13
  472. package/dist/dispatch/RemoteRouteResolver.d.ts.map +0 -1
  473. package/dist/dispatch/RemoteRouteResolver.js.map +0 -1
  474. package/dist/dispatch/RouteNotFoundError.d.ts +0 -10
  475. package/dist/dispatch/RouteNotFoundError.d.ts.map +0 -1
  476. package/dist/dispatch/RouteNotFoundError.js +0 -24
  477. package/dist/dispatch/RouteNotFoundError.js.map +0 -1
  478. package/dist/entry/DynamicFacade.d.ts +0 -10
  479. package/dist/entry/DynamicFacade.d.ts.map +0 -1
  480. package/dist/entry/DynamicFacade.js +0 -27
  481. package/dist/entry/DynamicFacade.js.map +0 -1
  482. package/dist/entry/FacadeEntry.d.ts +0 -11
  483. package/dist/entry/FacadeEntry.d.ts.map +0 -1
  484. package/dist/entry/FacadeEntry.js +0 -26
  485. package/dist/entry/FacadeEntry.js.map +0 -1
  486. package/dist/entry/TransportEntry.d.ts +0 -13
  487. package/dist/entry/TransportEntry.d.ts.map +0 -1
  488. package/dist/entry/TransportEntry.js +0 -24
  489. package/dist/entry/TransportEntry.js.map +0 -1
  490. package/dist/orm.d.ts +0 -207
  491. package/dist/orm.d.ts.map +0 -1
  492. package/dist/orm.js +0 -66
  493. package/dist/orm.js.map +0 -1
  494. package/dist/scan/Fronds.d.ts +0 -45
  495. package/dist/scan/Fronds.d.ts.map +0 -1
  496. package/dist/scan/Fronds.js +0 -66
  497. package/dist/scan/Fronds.js.map +0 -1
  498. package/dist/scan/declare.d.ts +0 -71
  499. package/dist/scan/declare.d.ts.map +0 -1
  500. package/dist/scan/declare.js.map +0 -1
  501. package/dist/scan/frond.d.ts +0 -224
  502. package/dist/scan/frond.d.ts.map +0 -1
  503. package/src/boot/HandlerFacade.ts +0 -242
  504. package/src/boot/binding.ts +0 -182
  505. package/src/contract/Call.ts +0 -18
  506. package/src/contract/CallLog.ts +0 -55
  507. package/src/dispatch/InputValidator.ts +0 -28
  508. package/src/dispatch/OperationExecutor.ts +0 -60
  509. package/src/dispatch/OutputProjector.ts +0 -32
  510. package/src/dispatch/PresenterArgumentResolver.ts +0 -25
  511. package/src/dispatch/RouteNotFoundError.ts +0 -29
  512. package/src/entry/DynamicFacade.ts +0 -28
  513. package/src/entry/FacadeEntry.ts +0 -32
  514. package/src/entry/TransportEntry.ts +0 -30
  515. package/src/orm.ts +0 -252
  516. package/src/scan/Fronds.ts +0 -73
  517. package/src/scan/frond.ts +0 -235
  518. /package/dist/{scan → descriptor}/frond.js +0 -0
  519. /package/dist/{contract → wire}/CallLog.js +0 -0
@@ -1,21 +1,19 @@
1
- import type { RouteAddress } from '../contract/RouteAddress.js';
2
1
  import { OperationRoute } from './OperationRoute.js';
3
- import type { Route } from './Route.js';
4
2
  import type { RouteResolver } from './RouteResolver.js';
5
3
 
6
4
  type RemoteFacade = Record<string, Function>;
7
5
  export type RemoteFacadeResolver = (entity: string) => RemoteFacade | undefined;
8
6
 
9
- /** Builds a remote route on the first call, after the remote façade can be resolved. */
10
- export class RemoteRouteResolver implements RouteResolver {
11
- constructor(private readonly facades: RemoteFacadeResolver) {}
12
-
13
- resolve(address: RouteAddress): Route | undefined {
7
+ /** Builds a remote route on the first call, once the remote façade can be resolved. */
8
+ export function remoteRoutes(facades: RemoteFacadeResolver): RouteResolver {
9
+ return (address) => {
14
10
  if (address.surface !== undefined) return undefined;
15
11
 
16
- const facade = this.facades(address.entity);
12
+ const facade = facades(address.entity);
17
13
  const operation = facade?.[address.operation];
14
+
18
15
  if (typeof operation !== 'function') return undefined;
16
+
19
17
  return new OperationRoute('remote', address, (call) => operation(call.invocation));
20
- }
18
+ };
21
19
  }
@@ -0,0 +1,33 @@
1
+ import type { Call } from '../wire/call.js';
2
+ import { ErrorCode, FougereError } from '../wire/errors.js';
3
+ import type { Route } from './Route.js';
4
+ import type { RoutePolicy } from './RoutePolicy.js';
5
+
6
+ /** The operations this dispatcher would have served for the entity the call names. */
7
+ export function servedOperations(
8
+ call: Call,
9
+ routes: readonly Route[],
10
+ policy?: RoutePolicy,
11
+ ): readonly string[] {
12
+ return routes
13
+ .filter((route) => !policy || policy.accepts(route))
14
+ .filter((route) => route.address.entity === call.address.entity)
15
+ .filter((route) => route.kind === 'system' || route.address.surface === call.address.surface)
16
+ .map((route) => route.address.operation);
17
+ }
18
+
19
+ /** `Unknown operation 'draft' on 'post'. It serves list, findById.` */
20
+ export function routeNotFound(
21
+ call: Call,
22
+ served: readonly string[],
23
+ ): FougereError {
24
+ const { entity, operation } = call.address;
25
+ const message = entity === 'rpc'
26
+ ? `Unknown rpc operation '${operation}'. `
27
+ + (served.length ? `It serves ${served.join(', ')}.` : 'It serves nothing.')
28
+ : served.length
29
+ ? `Unknown operation '${operation}' on '${entity}'. It serves ${served.join(', ')}.`
30
+ : `No route serves '${call.address}'`;
31
+
32
+ return new FougereError({ code: ErrorCode.NOT_FOUND, message, entity, operation });
33
+ }
@@ -0,0 +1,28 @@
1
+ import { InputValidator, type SchemaView } from '@fougere/schema';
2
+ import type { InvocationContext } from '../wire/Invocation.js';
3
+ import { ErrorCode, FougereError } from '../wire/errors.js';
4
+
5
+ /** Validates and decodes the input declared by one operation contract. */
6
+ export function validateInput(
7
+ schema: SchemaView | undefined,
8
+ invocation: InvocationContext,
9
+ entity: string,
10
+ operation: string,
11
+ ): InvocationContext {
12
+ if (!schema || invocation.input === undefined || invocation.input === null) return invocation;
13
+
14
+ const result = InputValidator.of(schema.getFields(), { patch: schema.getOpts().patch })
15
+ .validate(invocation.input);
16
+
17
+ if (!result.success) {
18
+ throw new FougereError({
19
+ code: ErrorCode.VALIDATION_FAILED,
20
+ message: result.errors.map((error) => `${error.path}: ${error.message}`).join(', '),
21
+ details: result.errors,
22
+ entity,
23
+ operation,
24
+ });
25
+ }
26
+
27
+ return { ...invocation, input: result.data };
28
+ }
@@ -1,27 +1,17 @@
1
- /**
2
- * The operation model after every declaration and convention has been resolved.
3
- *
4
- * The scanner produces evidence. This module turns that evidence into the one table
5
- * boot, check, explain and protocol projections consume. It is deliberately pure: no
6
- * container, filesystem, migration or handler construction is involved.
7
- */
1
+ /** The operation model after every declaration and convention has been resolved. */
8
2
  import { lowerFirst, type SchemaView } from '@fougere/schema';
9
3
  import { statementDrift } from './boot/statement-drift.js';
10
- import type { BindingPlan } from './boot/binding.js';
4
+ import { computeBindingPlan, type BindingPlan } from './wire/binding.js';
11
5
  import { targetOf } from './prefab/prefab.js';
12
- import type {
13
- CollectorEntry,
14
- FrondDescriptor,
15
- HandlerEntry,
16
- ScanDiagnostic,
17
- } from './scan/frond.js';
6
+ import type { CollectorEntry, FrondDescriptor, HandlerEntry } from './descriptor/frond.js';
7
+ import type { ScanDiagnostic } from './scan/result.js';
18
8
  import { verify } from './verify.js';
19
9
  import {
20
10
  inferOperationKind,
21
- resolveContracts,
22
11
  type OperationContract,
23
12
  type OperationKind,
24
- type ParsedType,
13
+ type OperationsMap,
14
+ type TypeRef,
25
15
  knownVerbs,
26
16
  } from './wire/operation.js';
27
17
 
@@ -236,7 +226,7 @@ export function resolveEffectiveOperations(
236
226
  resolutionDiagnostics,
237
227
  )) continue;
238
228
 
239
- // A fact is judged by the entity it names. This used to be patched into the
229
+ // A fact is validated by the entity it names. This used to be patched into the
240
230
  // facade after resolution, leaving check/explain with a different input.
241
231
  let input = contract.input;
242
232
  if (!input) {
@@ -330,9 +320,9 @@ export function resolveEffectiveOperations(
330
320
  function groupedCollectors(collectors: readonly CollectorEntry[]): Map<string, CollectorEntry[]> {
331
321
  const grouped = new Map<string, CollectorEntry[]>();
332
322
  for (const collector of collectors) {
333
- const held = grouped.get(collector.typeName) ?? [];
334
- held.push(collector);
335
- grouped.set(collector.typeName, held);
323
+ const sameName = grouped.get(collector.typeName) ?? [];
324
+ sameName.push(collector);
325
+ grouped.set(collector.typeName, sameName);
336
326
  }
337
327
  return grouped;
338
328
  }
@@ -363,9 +353,9 @@ function normalizeBinding(
363
353
  // Array order is never allowed to become semantic authority.
364
354
  const byName = new Map<string, Binding[]>();
365
355
  for (const binding of contract.binding) {
366
- const held = byName.get(binding.name) ?? [];
367
- held.push(binding);
368
- byName.set(binding.name, held);
356
+ const sameName = byName.get(binding.name) ?? [];
357
+ sameName.push(binding);
358
+ byName.set(binding.name, sameName);
369
359
  }
370
360
  const expected = new Set(params.map((param) => param.name));
371
361
  const invalid = params.filter((param) => (byName.get(param.name)?.length ?? 0) !== 1);
@@ -407,14 +397,14 @@ function validateProvenance(
407
397
  const ambiguousInput = diagnostics.some((diagnostic) =>
408
398
  diagnostic.code === 'input-contract-ambiguous'
409
399
  && diagnostic.subject === `${handler.ctor.name}.${name}`);
410
- const body = parameters.filter((parameter) => parameter.binding.source.kind === 'body');
400
+ const fromInput = parameters.filter((parameter) => parameter.binding.source.kind === 'input');
411
401
  const inferredBody = new Set<EffectiveParameter>();
412
402
 
413
403
  if (!explicitBinding && !ambiguousInput && contract.input) {
414
- if (body.length === 1) {
415
- inferredBody.add(body[0]!);
416
- } else if (body.length > 1) {
417
- const matches = body.filter((parameter) =>
404
+ if (fromInput.length === 1) {
405
+ inferredBody.add(fromInput[0]!);
406
+ } else if (fromInput.length > 1) {
407
+ const matches = fromInput.filter((parameter) =>
418
408
  schemaMatches(contract.input!, contract.signature?.params[parameter.position]?.type));
419
409
  if (matches.length > 1) {
420
410
  diagnostics.push({
@@ -423,7 +413,7 @@ function validateProvenance(
423
413
  filePath: handler.filePath,
424
414
  frond: frond.name,
425
415
  subject: `${handler.ctor.name}.${name}`,
426
- message: `Cannot resolve which parameter of ${handler.ctor.name}.${name} receives the body: `
416
+ message: `Cannot resolve which parameter of ${handler.ctor.name}.${name} receives the input: `
427
417
  + `${matches.map((parameter) => `${parameter.name}: ${parameter.type ?? 'unknown'}`).join('; ')} `
428
418
  + 'all match the resolved input contract. Declare an explicit binding plan.',
429
419
  });
@@ -434,9 +424,9 @@ function validateProvenance(
434
424
  }
435
425
 
436
426
  // A type written with an inline object literal names nothing a collector can register
437
- // under, so the parameter IS the body. Only a NAMED type can be the wrong-frond
427
+ // under, so the parameter IS the input. Only a NAMED type can be the wrong-frond
438
428
  // substitution the refusal below exists for.
439
- for (const parameter of body) {
429
+ for (const parameter of fromInput) {
440
430
  if (structural(contract.signature?.params[parameter.position]?.type)) inferredBody.add(parameter);
441
431
  }
442
432
 
@@ -459,7 +449,7 @@ function validateProvenance(
459
449
  }
460
450
  continue;
461
451
  }
462
- if (source.kind !== 'body' || explicitBinding || ambiguousInput) continue;
452
+ if (source.kind !== 'input' || explicitBinding || ambiguousInput) continue;
463
453
 
464
454
  const typeName = lowerFirst(contract.signature?.params[parameter.position]?.type.name ?? '');
465
455
  const elsewhere = fronds.flatMap((candidate) => candidate === frond
@@ -467,12 +457,12 @@ function validateProvenance(
467
457
  : candidate.collectors.filter((collector) => collector.typeName === typeName));
468
458
  if (elsewhere.length > 0) {
469
459
  // verify() supplies the more complete topology diagnostic; do not also call this
470
- // an unknown body.
460
+ // an unknown input.
471
461
  continue;
472
462
  }
473
463
 
474
- // An inferred body must be backed by exactly one resolved interpretation. With one
475
- // body, the input itself is sufficient evidence; with several, exactly one type may
464
+ // An inferred input must be backed by exactly one resolved interpretation. With one
465
+ // input, the value itself is sufficient evidence; with several, exactly one type may
476
466
  // match. Explicit plans are authoritative because they state every provenance.
477
467
  const recognized = explicitBinding || inferredBody.has(parameter);
478
468
  if (recognized) continue;
@@ -491,11 +481,11 @@ function validateProvenance(
491
481
  return valid;
492
482
  }
493
483
 
494
- function structural(type: ParsedType | undefined): boolean {
484
+ function structural(type: TypeRef | undefined): boolean {
495
485
  return type !== undefined && type.raw.includes('{');
496
486
  }
497
487
 
498
- function schemaMatches(schema: SchemaView, type: ParsedType | undefined): boolean {
488
+ function schemaMatches(schema: SchemaView, type: TypeRef | undefined): boolean {
499
489
  const names = new Set([schema.name, schema.derivation?.sourceName].filter(Boolean));
500
490
  if (type?.name && names.has(type.name)) return true;
501
491
  return type?.generics?.some((generic) => generic.name && names.has(generic.name)) ?? false;
@@ -599,3 +589,36 @@ function uniqueDiagnostics(diagnostics: readonly ScanDiagnostic[]): ScanDiagnost
599
589
  return true;
600
590
  });
601
591
  }
592
+
593
+ /** The contract of every operation a handler serves — the three producers, merged once. */
594
+ export function resolveContracts(
595
+ handler: Pick<HandlerEntry, 'ctor' | 'operations'>,
596
+ overrides: FrondDescriptor['operationsOverrides'],
597
+ collectorTypeNames: Set<string>,
598
+ ): OperationsMap {
599
+ const declared = (handler.ctor as { __ops?: Record<string, OperationContract> }).__ops ?? {};
600
+ const contracts: OperationsMap = new Map(Object.entries(declared));
601
+
602
+ for (const [opName, scanned] of handler.operations) {
603
+ if (scanned.signature?.inherited && opName in declared) continue;
604
+ contracts.set(opName, {
605
+ ...scanned,
606
+ binding: scanned.binding
607
+ ?? (scanned.signature ? computeBindingPlan(scanned.signature.params, collectorTypeNames) : undefined),
608
+ });
609
+ }
610
+
611
+ for (const [opName, override] of Object.entries(overrides ?? {})) {
612
+ const { input, output, binding, description } = override;
613
+ if (input === undefined && output === undefined && binding === undefined && description === undefined) continue;
614
+ contracts.set(opName, {
615
+ ...contracts.get(opName),
616
+ ...(input !== undefined && { input }),
617
+ ...(output !== undefined && { output }),
618
+ ...(binding !== undefined && { binding }),
619
+ ...(description !== undefined && { description }),
620
+ });
621
+ }
622
+
623
+ return contracts;
624
+ }
package/src/emit.ts CHANGED
@@ -1,61 +1,13 @@
1
- /**
2
- * Announcing a fact — the half of the topology `remotes:` never covered.
3
- *
4
- * Every other call in Fougere names **one** recipient: `remotes` names one address per
5
- * frond, `Facade<T>` resolves one door. `Emit<T>` names a **subject** instead, and the
6
- * number of readers is not the emitter's business.
7
- *
8
- * ```ts
9
- * constructor(private published: Emit<PostPublished>) {}
10
- * await this.published({ id, title }); // I say it happened. I do not know who cares.
11
- *
12
- * async reindex(fact: Fact<PostPublished>) {} // any handler, any frond. Nothing to register.
13
- * ```
14
- *
15
- * **It is a resolver, not a channel.** A bus moves messages — it has a queue, an envelope
16
- * format, a delivery semantic. This has none of that: it answers *who*, then hands over to
17
- * the call path that already exists. It is `resolve` returning N things instead of one.
18
- * That is also why temporal decoupling stays out of reach: a resolver holds nothing. The
19
- * day at-least-once is wanted, a real channel goes UNDER this, in the transport — the
20
- * dispatch line becomes a publish and a consumer calls the same door on the far side.
21
- */
1
+ /** Announcing a fact — the half of the topology `remotes:` never covered. */
22
2
  import { lowerFirst } from '@fougere/schema';
23
3
 
24
- /**
25
- * What an emitter injects. Resolved by type, like `EntityOrm<Post>` and `Facade<T>`.
26
- *
27
- * The returned promise settles when the fact has been **dispatched**, never when it has
28
- * been handled: a subscriber's failure is its own. The `EventBus` this replaces did
29
- * `await Promise.all(handlers)` and handed their rejections back, which made a publication
30
- * hostage to its own indexer.
31
- */
4
+ /** What an emitter injects. */
32
5
  export type Emit<T> = (fact: T) => Promise<void>;
33
6
 
34
- /**
35
- * What a subscriber accepts — and what it PROMISES about itself.
36
- *
37
- * Not merely "I subscribe". Push is the strict mode and pull is a special case of it: an
38
- * op written for push is correct when called directly, the reverse is false. So this
39
- * wrapper commits the operation to three things its author must honour, because no type
40
- * can check them:
41
- *
42
- * 1. **replayable** — delivery is at-least-once the day a broker sits underneath;
43
- * 2. **no reader for its return** — nobody receives what it hands back;
44
- * 3. **owner of its failures** — they reach a log, never the emitter.
45
- *
46
- * It is the identity at runtime. The scan reads the written name, which is the whole
47
- * mechanism: `binding.ts` sees `Fact<X>` and binds the parameter as a fact instead of
48
- * letting it fall through to "everything else — body".
49
- */
7
+ /** What a subscriber accepts — and what it PROMISES about itself. */
50
8
  export type Fact<T> = T;
51
9
 
52
- /**
53
- * The container key of an emission — THE one place that spells the format.
54
- *
55
- * Its dual is right below, because the boot reads the fact back out of a handler's `deps`
56
- * to know which emissions to register. A key and the way to undo it belong together: the
57
- * pair that is split is the pair that drifts.
58
- */
10
+ /** The container key of an emission — THE one place that spells the format. */
59
11
  export function emitKeyOf(fact: string): string {
60
12
  return `${lowerFirst(fact)}Emit`;
61
13
  }
@@ -69,17 +21,7 @@ export function factOfEmitKey(key: string): string | undefined {
69
21
  : undefined;
70
22
  }
71
23
 
72
- /**
73
- * What a set of handlers ANNOUNCES — `Emit<T>` read back out of their dependencies.
74
- *
75
- * Two readers, which is exactly why it is a function and not a line: the boot registers one
76
- * emission value per name, and the identity card publishes the same set. Spelled twice they
77
- * would drift the day an emission stops being a constructor dependency.
78
- *
79
- * The dual — what a handler ACCEPTS — is not here, because it is not read the same way: a
80
- * `Fact<T>` parameter is a fact about one operation, and `computeBindingPlan` has already
81
- * written it into the plan (`app.listensTo()`).
82
- */
24
+ /** What a set of handlers ANNOUNCES — `Emit<T>` read back out of their dependencies. */
83
25
  export function factsAnnouncedBy(handlers: readonly { deps: readonly string[] }[]): string[] {
84
26
  return [...new Set(
85
27
  handlers
@@ -0,0 +1,44 @@
1
+ import { Call } from '../wire/call.js';
2
+ import type { PartialInvocation } from '../wire/Invocation.js';
3
+ import { RouteAddress } from '../wire/RouteAddress.js';
4
+ import type { DispatchPort } from '../dispatch/DispatchPort.js';
5
+
6
+ type Operation = (...args: any[]) => unknown;
7
+
8
+ /** Facade for a contract whose operation names are only known at discovery. */
9
+ export function dynamicOperations(operation: (name: string) => Operation): Record<string, Operation> {
10
+ const isOperationName = (name: string | symbol): name is string =>
11
+ typeof name === 'string'
12
+ && name !== 'then'
13
+ && name !== 'toJSON'
14
+ && !Object.hasOwn(Object.prototype, name);
15
+
16
+ return new Proxy({}, {
17
+ get: (_target, name) => (isOperationName(name) ? operation(name) : undefined),
18
+ has: (_target, name) => isOperationName(name),
19
+ getOwnPropertyDescriptor: (_target, name) => (isOperationName(name)
20
+ ? { value: operation(name), writable: false, enumerable: true, configurable: true }
21
+ : undefined),
22
+ });
23
+ }
24
+
25
+ /** Turns facade method calls into canonical dispatches. */
26
+ export function facadeOperations(
27
+ dispatcher: DispatchPort,
28
+ entity: string,
29
+ operationNames?: Iterable<string>,
30
+ surface?: string,
31
+ ): Record<string, Operation> {
32
+ const operation = (name: string): Operation => (invocation) => dispatcher.dispatch(new Call(
33
+ new RouteAddress({
34
+ entity,
35
+ operation: name,
36
+ ...(surface !== undefined ? { surface } : {}),
37
+ }),
38
+ invocation,
39
+ ));
40
+
41
+ return operationNames
42
+ ? Object.fromEntries([...operationNames].map((name) => [name, operation(name)]))
43
+ : dynamicOperations(operation);
44
+ }
@@ -0,0 +1,16 @@
1
+ import { Call } from '../wire/call.js';
2
+ import { RouteAddress } from '../wire/RouteAddress.js';
3
+ import type { DispatchPort } from '../dispatch/DispatchPort.js';
4
+ import type { Transport } from '../wire/call.js';
5
+
6
+ /** Adapts the historical transport signature to the canonical dispatch port. */
7
+ export function createTransportEntry(dispatcher: DispatchPort, surface?: string): Transport {
8
+ return (legacy, invocation) => dispatcher.dispatch(new Call(
9
+ new RouteAddress({
10
+ entity: legacy.entity,
11
+ operation: legacy.op,
12
+ ...(surface !== undefined ? { surface } : {}),
13
+ }),
14
+ invocation,
15
+ ));
16
+ }
@@ -1,49 +1,15 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { existsSync } from 'node:fs';
3
3
  import type { EntityConstructor, SchemaView } from '@fougere/schema';
4
- import type { BindingPlan } from './boot/binding.js';
4
+ import type { BindingPlan } from './wire/binding.js';
5
5
 
6
6
  // ── Types ────────────────────────────────────────
7
7
 
8
- /**
9
- * Per-operation override. Config takes precedence over conventions (isReadOp, facade lookup).
10
- *
11
- * Two families of keys, and they act at different depths:
12
- *
13
- * - **Resolution** (`kind`, `handler`, `method`) — intent and implementation, resolved
14
- * once into core's `EffectiveOperation`; every local or remote door consumes it.
15
- * - **Projection** (`graphql`) — protocol vocabulary, read only by that adapter.
16
- * - **Contract** (`input`, `output`, `binding`) — what the op IS. Read by the façade,
17
- * and this is the third producer of an {@link OperationContract}: a prefab DECLARES its
18
- * ops (`Crud.__ops`), the scan DERIVES them from source, config STATES them outright.
19
- * The façade cannot tell the three apart.
20
- *
21
- * Stating a contract here makes the scan optional rather than load-bearing. Two cases it
22
- * answers that nothing else does:
23
- * - a method inherited from an **installed** base class — the scan resolves nothing there
24
- * (workspace-only heritage) and says nothing, so the op silently misses the façade;
25
- * - an operation inherited from a declaration unavailable to the project's type checker.
26
- *
27
- * Config wins over both other producers — it is the most explicit statement, made by
28
- * whoever assembles the app. Precedence: CLI > frond config > fougere config > scan >
29
- * conventions.
30
- */
8
+ /** Per-operation override. */
31
9
  export interface OperationOverride {
32
- /**
33
- * Force operation kind, over the naming convention (`isReadOp`).
34
- *
35
- * The convention reads the NAME, which is a weak signal — an app naming its reads in
36
- * domain terms (`ofBook`, `roots`, `bySlug`) matches no prefix and every one of them is
37
- * published as a mutation and a POST. This is the only place that fixes it.
38
- */
10
+ /** Force operation kind, over the naming convention (`isReadOp`). */
39
11
  kind?: 'query' | 'command';
40
- /**
41
- * The GraphQL root field this op answers to. Defaults to the method name.
42
- *
43
- * A GraphQL root is flat, so two handlers naming a method `ofBook` claim one field and
44
- * the build is refused, naming both. Nothing is renamed for you: the root vocabulary is
45
- * the app's, and a derived name would move the day a distant frond gained an entity.
46
- */
12
+ /** The GraphQL root field this op answers to. */
47
13
  graphql?: string;
48
14
  /**
49
15
  * Handler class to delegate to (overrides the default `{Entity}Handler` lookup).
@@ -52,22 +18,12 @@ export interface OperationOverride {
52
18
  handler?: EntityConstructor;
53
19
  /** Method name on `handler` (defaults to the operation name). */
54
20
  method?: string;
55
- /**
56
- * CASL ability check (e.g. 'archive Post'). **Declared, not implemented** — no
57
- * reader interprets it today, in any adapter. Kept as the named slot for the
58
- * question rather than silently dropped, but do not rely on it: a config that
59
- * states a policy is not enforced anywhere.
60
- *
61
- * Wiring it means adopting a rules engine, which is precisely what the design
62
- * turns down: an identity-dependent right is judged INSIDE the operation
63
- * (`publish` reads `post.authorId !== user.id`), and a door-dependent one is a
64
- * surface. Neither needs a second vocabulary evaluated by a second engine.
65
- */
21
+ /** CASL ability check (e.g. */
66
22
  policy?: string;
67
23
 
68
24
  // ── The contract itself — see the note above ──
69
25
 
70
- /** What judges the input. The view carries its own mode (`partial()` → patch). */
26
+ /** What validates the input. The view carries its own mode (`partial()` → patch). */
71
27
  input?: SchemaView;
72
28
  /**
73
29
  * Where each argument is read from — states what the scan would otherwise derive
@@ -82,18 +38,7 @@ export interface OperationOverride {
82
38
  export interface FrondConfig {
83
39
  /** Class names exposed as the frond's public contract (all surfaces). */
84
40
  expose?: string[];
85
- /**
86
- * The entities this frond may read ACROSS sources, by name.
87
- *
88
- * It is not a permission checked after the fact: the list IS the environment a
89
- * cross-source query runs in — a source holding none of these is never opened, so
90
- * its tables do not exist in that connection. `facadeFor` excludes an entity with no
91
- * door on purpose ("it would publish the auth tables to anyone who asks"), and a SQL
92
- * door at app scope would hand them over; this is what keeps it shut.
93
- *
94
- * Declaring it is what makes `Sources` injectable here. A frond that declares none
95
- * asks for none, and nothing is attached on its behalf.
96
- */
41
+ /** The entities this frond may read ACROSS sources, by name. */
97
42
  reads?: string[];
98
43
  /** Per-surface entity lists. Overrides default deduction for each named surface. */
99
44
  surfaces?: Record<string, string[]>;
@@ -105,15 +50,7 @@ export interface FrondConfig {
105
50
 
106
51
  // ── Helper ───────────────────────────────────────
107
52
 
108
- /**
109
- * Define a frond configuration (typed identity helper).
110
- *
111
- * ```ts
112
- * // fronds/auth/frond.config.ts
113
- * import { defineFrond } from '@fougere/core'
114
- * export default defineFrond({ expose: ['User', 'AuthHandler'] })
115
- * ```
116
- */
53
+ /** Define a frond configuration (typed identity helper). */
117
54
  export function defineFrond(config: FrondConfig): FrondConfig {
118
55
  return config;
119
56
  }
package/src/graph.ts CHANGED
@@ -3,7 +3,7 @@ import { Role } from '@fougere/schema';
3
3
  * Entity dependency graph — analyzes ref() links between entities
4
4
  * to suggest domain boundaries for splitting fronds.
5
5
  */
6
- import type { FrondDescriptor } from './scan/frond.js';
6
+ import type { FrondDescriptor } from './descriptor/frond.js';
7
7
 
8
8
  export interface EntityNode {
9
9
  name: string;
@@ -1,14 +1,4 @@
1
- /**
2
- * Making keys and issuing grants — the half of identity that runs at a DEPLOYMENT.
3
- *
4
- * It sits on the Node entry because it is the CLI speaking: `fougere keys` generates a
5
- * pair, `fougere grant` binds a name to one, and both happen once, on a machine with a
6
- * filesystem. Neither is reachable from a request path, so nothing here is on any hot
7
- * path and `generateKeyPairSync` — the one gesture WebCrypto could not replace without
8
- * changing what a key IS — never has to leave `node:crypto`.
9
- *
10
- * The verifying half is elsewhere (`identity.ts`) because it runs per call, everywhere.
11
- */
1
+ /** Making keys and issuing grants — the half of identity that runs at a DEPLOYMENT. */
12
2
  import { createPrivateKey, createPublicKey, generateKeyPairSync, sign } from 'node:crypto';
13
3
  import { b64url } from './crypto/encoding.js';
14
4
 
@@ -22,11 +12,8 @@ export function generateKeyPair(): { privateKey: string; publicKey: string } {
22
12
  }
23
13
 
24
14
  /**
25
- * Bind a name to a public key, signed by the root — the whole of what a receiver
26
- * needs to recognize a frond it has never seen.
27
- *
28
- * `ttlDays` bounds the damage of a leaked frond key without a revocation list:
29
- * re-issuing is a deployment, which is the same gesture that leaked it.
15
+ * Bind a name to a public key, signed by the root — the whole of what a receiver needs to
16
+ * recognize a frond it has never seen.
30
17
  */
31
18
  export function issueGrant(
32
19
  rootPrivateKey: string,