@fougere/core 0.6.0-alpha.0 → 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 (493) hide show
  1. package/README.md +1 -1
  2. package/dist/boot/Emissions.d.ts +13 -90
  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 +2 -12
  19. package/dist/boot/auth.d.ts.map +1 -1
  20. package/dist/boot/boot.d.ts +3 -16
  21. package/dist/boot/boot.d.ts.map +1 -1
  22. package/dist/boot/boot.js +3 -10
  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 +61 -127
  26. package/dist/boot/bootstrap.js.map +1 -1
  27. package/dist/boot/card.d.ts +1 -17
  28. package/dist/boot/card.d.ts.map +1 -1
  29. package/dist/boot/card.js +3 -32
  30. package/dist/boot/card.js.map +1 -1
  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 +20 -54
  34. package/dist/boot/frame.js.map +1 -1
  35. package/dist/boot/hosted.d.ts +2 -24
  36. package/dist/boot/hosted.d.ts.map +1 -1
  37. package/dist/boot/hosted.js +10 -15
  38. package/dist/boot/hosted.js.map +1 -1
  39. package/dist/boot/ownership.d.ts +3 -36
  40. package/dist/boot/ownership.d.ts.map +1 -1
  41. package/dist/boot/ownership.js +5 -40
  42. package/dist/boot/ownership.js.map +1 -1
  43. package/dist/boot/ports.d.ts +1 -14
  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 +4 -21
  52. package/dist/boot/runner.d.ts.map +1 -1
  53. package/dist/boot/runner.js +4 -17
  54. package/dist/boot/runner.js.map +1 -1
  55. package/dist/boot/seed.d.ts +4 -31
  56. package/dist/boot/seed.d.ts.map +1 -1
  57. package/dist/boot/seed.js +6 -37
  58. package/dist/boot/seed.js.map +1 -1
  59. package/dist/boot/statement-drift.d.ts +2 -21
  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 +4 -8
  64. package/dist/boot/together.d.ts.map +1 -1
  65. package/dist/boot/together.js +15 -50
  66. package/dist/boot/together.js.map +1 -1
  67. package/dist/boot/types.d.ts +28 -173
  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 +6 -36
  100. package/dist/declare.d.ts.map +1 -1
  101. package/dist/declare.js +4 -29
  102. package/dist/declare.js.map +1 -1
  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 +3 -28
  108. package/dist/descriptor/Fronds.d.ts.map +1 -1
  109. package/dist/descriptor/Fronds.js +6 -31
  110. package/dist/descriptor/Fronds.js.map +1 -1
  111. package/dist/descriptor/frond.d.ts +14 -63
  112. package/dist/descriptor/frond.d.ts.map +1 -1
  113. package/dist/dispatch/ArgumentResolver.d.ts +1 -1
  114. package/dist/dispatch/ArgumentResolver.d.ts.map +1 -1
  115. package/dist/dispatch/ArgumentResolver.js +5 -5
  116. package/dist/dispatch/ArgumentResolver.js.map +1 -1
  117. package/dist/dispatch/DispatchEvent.d.ts +2 -2
  118. package/dist/dispatch/DispatchEvent.d.ts.map +1 -1
  119. package/dist/dispatch/DispatchLifecycle.d.ts +1 -7
  120. package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -1
  121. package/dist/dispatch/DispatchLifecycle.js +1 -7
  122. package/dist/dispatch/DispatchLifecycle.js.map +1 -1
  123. package/dist/dispatch/DispatchPort.d.ts +1 -1
  124. package/dist/dispatch/DispatchPort.d.ts.map +1 -1
  125. package/dist/dispatch/Dispatcher.d.ts +1 -1
  126. package/dist/dispatch/Dispatcher.d.ts.map +1 -1
  127. package/dist/dispatch/Dispatcher.js +2 -2
  128. package/dist/dispatch/Dispatcher.js.map +1 -1
  129. package/dist/{boot → dispatch}/HandlerFacade.d.ts +25 -38
  130. package/dist/dispatch/HandlerFacade.d.ts.map +1 -0
  131. package/dist/{boot → dispatch}/HandlerFacade.js +65 -74
  132. package/dist/dispatch/HandlerFacade.js.map +1 -0
  133. package/dist/dispatch/LocalRoutePolicy.d.ts +1 -1
  134. package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -1
  135. package/dist/dispatch/LocalRoutePolicy.js +4 -4
  136. package/dist/dispatch/LocalRoutePolicy.js.map +1 -1
  137. package/dist/dispatch/OperationRoute.d.ts +2 -2
  138. package/dist/dispatch/OperationRoute.d.ts.map +1 -1
  139. package/dist/dispatch/OutputView.d.ts +3 -2
  140. package/dist/dispatch/OutputView.d.ts.map +1 -1
  141. package/dist/dispatch/OutputView.js +19 -1
  142. package/dist/dispatch/OutputView.js.map +1 -1
  143. package/dist/dispatch/Route.d.ts +2 -2
  144. package/dist/dispatch/Route.d.ts.map +1 -1
  145. package/dist/dispatch/RoutePolicy.d.ts +1 -1
  146. package/dist/dispatch/RoutePolicy.d.ts.map +1 -1
  147. package/dist/dispatch/RouteRegistry.d.ts +1 -1
  148. package/dist/dispatch/RouteRegistry.d.ts.map +1 -1
  149. package/dist/dispatch/RouteRegistry.js +2 -2
  150. package/dist/dispatch/RouteRegistry.js.map +1 -1
  151. package/dist/dispatch/RouteResolver.d.ts +2 -4
  152. package/dist/dispatch/RouteResolver.d.ts.map +1 -1
  153. package/dist/dispatch/StorageGuard.d.ts +8 -7
  154. package/dist/dispatch/StorageGuard.d.ts.map +1 -1
  155. package/dist/dispatch/StorageGuard.js +61 -18
  156. package/dist/dispatch/StorageGuard.js.map +1 -1
  157. package/dist/dispatch/presenterArguments.d.ts +7 -0
  158. package/dist/dispatch/presenterArguments.d.ts.map +1 -0
  159. package/dist/dispatch/presenterArguments.js +12 -0
  160. package/dist/dispatch/presenterArguments.js.map +1 -0
  161. package/dist/dispatch/remoteRoutes.d.ts +7 -0
  162. package/dist/dispatch/remoteRoutes.d.ts.map +1 -0
  163. package/dist/dispatch/{RemoteRouteResolver.js → remoteRoutes.js} +6 -10
  164. package/dist/dispatch/remoteRoutes.js.map +1 -0
  165. package/dist/dispatch/routeNotFound.d.ts +9 -0
  166. package/dist/dispatch/routeNotFound.d.ts.map +1 -0
  167. package/dist/dispatch/routeNotFound.js +21 -0
  168. package/dist/dispatch/routeNotFound.js.map +1 -0
  169. package/dist/dispatch/validateInput.d.ts +5 -0
  170. package/dist/dispatch/validateInput.d.ts.map +1 -0
  171. package/dist/dispatch/validateInput.js +20 -0
  172. package/dist/dispatch/validateInput.js.map +1 -0
  173. package/dist/effective-operation.d.ts +1 -24
  174. package/dist/effective-operation.d.ts.map +1 -1
  175. package/dist/effective-operation.js +21 -50
  176. package/dist/effective-operation.js.map +1 -1
  177. package/dist/emit.d.ts +4 -42
  178. package/dist/emit.d.ts.map +1 -1
  179. package/dist/emit.js +3 -39
  180. package/dist/emit.js.map +1 -1
  181. package/dist/entry/facade.d.ts +8 -0
  182. package/dist/entry/facade.d.ts.map +1 -0
  183. package/dist/entry/facade.js +28 -0
  184. package/dist/entry/facade.js.map +1 -0
  185. package/dist/entry/transport.d.ts +5 -0
  186. package/dist/entry/transport.d.ts.map +1 -0
  187. package/dist/entry/transport.js +11 -0
  188. package/dist/entry/transport.js.map +1 -0
  189. package/dist/frond-config.d.ts +7 -70
  190. package/dist/frond-config.d.ts.map +1 -1
  191. package/dist/frond-config.js +1 -9
  192. package/dist/frond-config.js.map +1 -1
  193. package/dist/identity-keys.d.ts +2 -5
  194. package/dist/identity-keys.d.ts.map +1 -1
  195. package/dist/identity-keys.js +3 -16
  196. package/dist/identity-keys.js.map +1 -1
  197. package/dist/identity.d.ts +4 -30
  198. package/dist/identity.d.ts.map +1 -1
  199. package/dist/identity.js +11 -73
  200. package/dist/identity.js.map +1 -1
  201. package/dist/imports.d.ts +1 -7
  202. package/dist/imports.d.ts.map +1 -1
  203. package/dist/imports.js +1 -7
  204. package/dist/imports.js.map +1 -1
  205. package/dist/index.d.ts +17 -24
  206. package/dist/index.d.ts.map +1 -1
  207. package/dist/index.js +10 -18
  208. package/dist/index.js.map +1 -1
  209. package/dist/loader.d.ts +1 -8
  210. package/dist/loader.d.ts.map +1 -1
  211. package/dist/loader.js +1 -8
  212. package/dist/loader.js.map +1 -1
  213. package/dist/node.d.ts +2 -11
  214. package/dist/node.d.ts.map +1 -1
  215. package/dist/node.js +2 -11
  216. package/dist/node.js.map +1 -1
  217. package/dist/prefab/collector.d.ts +1 -22
  218. package/dist/prefab/collector.d.ts.map +1 -1
  219. package/dist/prefab/collector.js +1 -22
  220. package/dist/prefab/collector.js.map +1 -1
  221. package/dist/prefab/crud.d.ts +16 -32
  222. package/dist/prefab/crud.d.ts.map +1 -1
  223. package/dist/prefab/crud.js +31 -58
  224. package/dist/prefab/crud.js.map +1 -1
  225. package/dist/prefab/mirror.d.ts +2 -24
  226. package/dist/prefab/mirror.d.ts.map +1 -1
  227. package/dist/prefab/mirror.js +2 -20
  228. package/dist/prefab/mirror.js.map +1 -1
  229. package/dist/prefab/prefab.d.ts +1 -7
  230. package/dist/prefab/prefab.d.ts.map +1 -1
  231. package/dist/prefab/prefab.js +1 -7
  232. package/dist/prefab/prefab.js.map +1 -1
  233. package/dist/prefab/presenter.d.ts +2 -36
  234. package/dist/prefab/presenter.d.ts.map +1 -1
  235. package/dist/prefab/presenter.js +2 -36
  236. package/dist/prefab/presenter.js.map +1 -1
  237. package/dist/prefab/repository.d.ts +5 -73
  238. package/dist/prefab/repository.d.ts.map +1 -1
  239. package/dist/prefab/repository.js +3 -16
  240. package/dist/prefab/repository.js.map +1 -1
  241. package/dist/scan/adapters.d.ts +3 -0
  242. package/dist/scan/adapters.d.ts.map +1 -0
  243. package/dist/scan/adapters.js +25 -0
  244. package/dist/scan/adapters.js.map +1 -0
  245. package/dist/scan/bundling.d.ts +1 -12
  246. package/dist/scan/bundling.d.ts.map +1 -1
  247. package/dist/scan/bundling.js +1 -12
  248. package/dist/scan/bundling.js.map +1 -1
  249. package/dist/scan/conventions.d.ts +6 -40
  250. package/dist/scan/conventions.d.ts.map +1 -1
  251. package/dist/scan/conventions.js +5 -34
  252. package/dist/scan/conventions.js.map +1 -1
  253. package/dist/scan/emit.d.ts +1 -5
  254. package/dist/scan/emit.d.ts.map +1 -1
  255. package/dist/scan/emit.js +4 -38
  256. package/dist/scan/emit.js.map +1 -1
  257. package/dist/scan/handler-parser.d.ts +4 -26
  258. package/dist/scan/handler-parser.d.ts.map +1 -1
  259. package/dist/scan/handler-parser.js +26 -83
  260. package/dist/scan/handler-parser.js.map +1 -1
  261. package/dist/scan/result.d.ts +3 -16
  262. package/dist/scan/result.d.ts.map +1 -1
  263. package/dist/scan/scanner.d.ts +2 -27
  264. package/dist/scan/scanner.d.ts.map +1 -1
  265. package/dist/scan/scanner.js +28 -127
  266. package/dist/scan/scanner.js.map +1 -1
  267. package/dist/scan/statement.d.ts.map +1 -1
  268. package/dist/scan/statement.js +4 -30
  269. package/dist/scan/statement.js.map +1 -1
  270. package/dist/source.d.ts +41 -0
  271. package/dist/source.d.ts.map +1 -0
  272. package/dist/source.js +10 -0
  273. package/dist/source.js.map +1 -0
  274. package/dist/storage.d.ts +13 -210
  275. package/dist/storage.d.ts.map +1 -1
  276. package/dist/storage.js +4 -68
  277. package/dist/storage.js.map +1 -1
  278. package/dist/store.d.ts +18 -0
  279. package/dist/store.d.ts.map +1 -0
  280. package/dist/store.js +146 -0
  281. package/dist/store.js.map +1 -0
  282. package/dist/verify.d.ts +5 -38
  283. package/dist/verify.d.ts.map +1 -1
  284. package/dist/verify.js +17 -37
  285. package/dist/verify.js.map +1 -1
  286. package/dist/wire/CallLog.d.ts +32 -0
  287. package/dist/wire/CallLog.d.ts.map +1 -0
  288. package/dist/{contract → wire}/CallLog.js.map +1 -1
  289. package/dist/wire/Invocation.d.ts +32 -0
  290. package/dist/wire/Invocation.d.ts.map +1 -0
  291. package/dist/wire/Invocation.js +66 -0
  292. package/dist/wire/Invocation.js.map +1 -0
  293. package/dist/{contract → wire}/RouteAddress.d.ts +5 -0
  294. package/dist/wire/RouteAddress.d.ts.map +1 -0
  295. package/dist/{contract → wire}/RouteAddress.js +7 -0
  296. package/dist/wire/RouteAddress.js.map +1 -0
  297. package/dist/wire/binding.d.ts +5 -21
  298. package/dist/wire/binding.d.ts.map +1 -1
  299. package/dist/wire/binding.js +5 -10
  300. package/dist/wire/binding.js.map +1 -1
  301. package/dist/wire/call.d.ts +24 -133
  302. package/dist/wire/call.d.ts.map +1 -1
  303. package/dist/wire/call.js +15 -41
  304. package/dist/wire/call.js.map +1 -1
  305. package/dist/wire/drift.d.ts +3 -28
  306. package/dist/wire/drift.d.ts.map +1 -1
  307. package/dist/wire/drift.js +4 -23
  308. package/dist/wire/drift.js.map +1 -1
  309. package/dist/wire/errors.d.ts +4 -24
  310. package/dist/wire/errors.d.ts.map +1 -1
  311. package/dist/wire/errors.js +4 -24
  312. package/dist/wire/errors.js.map +1 -1
  313. package/dist/wire/http-error.d.ts +2 -13
  314. package/dist/wire/http-error.d.ts.map +1 -1
  315. package/dist/wire/http-error.js +5 -19
  316. package/dist/wire/http-error.js.map +1 -1
  317. package/dist/wire/loggerMiddleware.d.ts +2 -8
  318. package/dist/wire/loggerMiddleware.d.ts.map +1 -1
  319. package/dist/wire/loggerMiddleware.js +1 -7
  320. package/dist/wire/loggerMiddleware.js.map +1 -1
  321. package/dist/wire/middleware.d.ts +3 -7
  322. package/dist/wire/middleware.d.ts.map +1 -1
  323. package/dist/wire/middleware.js +1 -5
  324. package/dist/wire/middleware.js.map +1 -1
  325. package/dist/wire/operation.d.ts +7 -43
  326. package/dist/wire/operation.d.ts.map +1 -1
  327. package/dist/wire/operation.js +4 -15
  328. package/dist/wire/operation.js.map +1 -1
  329. package/dist/wire/signature.d.ts +4 -25
  330. package/dist/wire/signature.d.ts.map +1 -1
  331. package/package.json +3 -3
  332. package/src/boot/Emissions.ts +21 -118
  333. package/src/boot/ambient-port.ts +3 -24
  334. package/src/boot/ambient.als.ts +7 -12
  335. package/src/boot/ambient.queue.ts +2 -5
  336. package/src/boot/apply.ts +3 -15
  337. package/src/boot/auth.ts +2 -12
  338. package/src/boot/boot.ts +5 -20
  339. package/src/boot/bootstrap.ts +69 -136
  340. package/src/boot/card.ts +4 -33
  341. package/src/boot/frame.ts +28 -62
  342. package/src/boot/hosted.ts +12 -34
  343. package/src/boot/ownership.ts +5 -39
  344. package/src/boot/ports.ts +1 -14
  345. package/src/boot/remote.ts +11 -58
  346. package/src/boot/runner.ts +5 -22
  347. package/src/boot/seed.ts +6 -37
  348. package/src/boot/statement-drift.ts +5 -24
  349. package/src/boot/together.ts +18 -51
  350. package/src/boot/types.ts +28 -173
  351. package/src/{builtins → builtin}/config.ts +1 -7
  352. package/src/{builtins → builtin}/logger.ts +6 -39
  353. package/src/config-loader.ts +12 -71
  354. package/src/contract.ts +15 -39
  355. package/src/crypto/encoding.ts +2 -15
  356. package/src/crypto/node.ts +1 -7
  357. package/src/crypto/port.ts +2 -18
  358. package/src/crypto/webcrypto.ts +1 -12
  359. package/src/declare.ts +8 -39
  360. package/src/define.ts +2 -3
  361. package/src/descriptor/Fronds.ts +6 -31
  362. package/src/descriptor/frond.ts +14 -63
  363. package/src/dispatch/ArgumentResolver.ts +6 -6
  364. package/src/dispatch/DispatchEvent.ts +2 -2
  365. package/src/dispatch/DispatchLifecycle.ts +1 -7
  366. package/src/dispatch/DispatchPort.ts +1 -1
  367. package/src/dispatch/Dispatcher.ts +3 -3
  368. package/src/dispatch/HandlerFacade.ts +231 -0
  369. package/src/dispatch/LocalRoutePolicy.ts +4 -4
  370. package/src/dispatch/OperationRoute.ts +2 -2
  371. package/src/dispatch/OutputView.ts +24 -2
  372. package/src/dispatch/Route.ts +2 -2
  373. package/src/dispatch/RoutePolicy.ts +1 -1
  374. package/src/dispatch/RouteRegistry.ts +2 -2
  375. package/src/dispatch/RouteResolver.ts +2 -4
  376. package/src/dispatch/StorageGuard.ts +70 -18
  377. package/src/dispatch/presenterArguments.ts +25 -0
  378. package/src/dispatch/{RemoteRouteResolver.ts → remoteRoutes.ts} +7 -9
  379. package/src/dispatch/routeNotFound.ts +33 -0
  380. package/src/dispatch/validateInput.ts +28 -0
  381. package/src/effective-operation.ts +21 -50
  382. package/src/emit.ts +5 -63
  383. package/src/entry/facade.ts +44 -0
  384. package/src/entry/transport.ts +16 -0
  385. package/src/frond-config.ts +7 -70
  386. package/src/identity-keys.ts +3 -16
  387. package/src/identity.ts +12 -80
  388. package/src/imports.ts +2 -31
  389. package/src/index.ts +17 -24
  390. package/src/loader.ts +2 -16
  391. package/src/node.ts +2 -11
  392. package/src/prefab/collector.ts +1 -22
  393. package/src/prefab/crud.ts +37 -76
  394. package/src/prefab/mirror.ts +4 -44
  395. package/src/prefab/prefab.ts +2 -21
  396. package/src/prefab/presenter.ts +2 -36
  397. package/src/prefab/repository.ts +7 -83
  398. package/src/scan/adapters.ts +32 -0
  399. package/src/scan/bundling.ts +1 -12
  400. package/src/scan/conventions.ts +6 -40
  401. package/src/scan/emit.ts +4 -38
  402. package/src/scan/handler-parser.ts +27 -96
  403. package/src/scan/result.ts +3 -16
  404. package/src/scan/scanner.ts +27 -126
  405. package/src/scan/statement.ts +4 -30
  406. package/src/source.ts +44 -0
  407. package/src/storage.ts +14 -234
  408. package/src/store.ts +152 -0
  409. package/src/verify.ts +16 -57
  410. package/src/wire/CallLog.ts +30 -0
  411. package/src/{contract → wire}/Invocation.ts +24 -17
  412. package/src/{contract → wire}/RouteAddress.ts +7 -0
  413. package/src/wire/binding.ts +9 -25
  414. package/src/wire/call.ts +30 -133
  415. package/src/wire/drift.ts +5 -30
  416. package/src/wire/errors.ts +4 -24
  417. package/src/wire/http-error.ts +5 -19
  418. package/src/wire/loggerMiddleware.ts +2 -8
  419. package/src/wire/middleware.ts +3 -7
  420. package/src/wire/operation.ts +8 -48
  421. package/src/wire/signature.ts +4 -25
  422. package/dist/boot/HandlerFacade.d.ts.map +0 -1
  423. package/dist/boot/HandlerFacade.js.map +0 -1
  424. package/dist/builtins/config.d.ts +0 -13
  425. package/dist/builtins/config.d.ts.map +0 -1
  426. package/dist/builtins/config.js +0 -21
  427. package/dist/builtins/config.js.map +0 -1
  428. package/dist/builtins/logger.d.ts.map +0 -1
  429. package/dist/builtins/logger.js.map +0 -1
  430. package/dist/contract/Call.d.ts +0 -10
  431. package/dist/contract/Call.d.ts.map +0 -1
  432. package/dist/contract/Call.js +0 -15
  433. package/dist/contract/Call.js.map +0 -1
  434. package/dist/contract/CallLog.d.ts +0 -57
  435. package/dist/contract/CallLog.d.ts.map +0 -1
  436. package/dist/contract/Invocation.d.ts +0 -27
  437. package/dist/contract/Invocation.d.ts.map +0 -1
  438. package/dist/contract/Invocation.js +0 -59
  439. package/dist/contract/Invocation.js.map +0 -1
  440. package/dist/contract/RouteAddress.d.ts.map +0 -1
  441. package/dist/contract/RouteAddress.js.map +0 -1
  442. package/dist/dispatch/InputValidator.d.ts +0 -7
  443. package/dist/dispatch/InputValidator.d.ts.map +0 -1
  444. package/dist/dispatch/InputValidator.js +0 -22
  445. package/dist/dispatch/InputValidator.js.map +0 -1
  446. package/dist/dispatch/OperationExecutor.d.ts +0 -25
  447. package/dist/dispatch/OperationExecutor.d.ts.map +0 -1
  448. package/dist/dispatch/OperationExecutor.js +0 -32
  449. package/dist/dispatch/OperationExecutor.js.map +0 -1
  450. package/dist/dispatch/OutputProjector.d.ts +0 -12
  451. package/dist/dispatch/OutputProjector.d.ts.map +0 -1
  452. package/dist/dispatch/OutputProjector.js +0 -30
  453. package/dist/dispatch/OutputProjector.js.map +0 -1
  454. package/dist/dispatch/PresenterArgumentResolver.d.ts +0 -12
  455. package/dist/dispatch/PresenterArgumentResolver.d.ts.map +0 -1
  456. package/dist/dispatch/PresenterArgumentResolver.js +0 -20
  457. package/dist/dispatch/PresenterArgumentResolver.js.map +0 -1
  458. package/dist/dispatch/RemoteRouteResolver.d.ts +0 -13
  459. package/dist/dispatch/RemoteRouteResolver.d.ts.map +0 -1
  460. package/dist/dispatch/RemoteRouteResolver.js.map +0 -1
  461. package/dist/dispatch/RouteNotFoundError.d.ts +0 -10
  462. package/dist/dispatch/RouteNotFoundError.d.ts.map +0 -1
  463. package/dist/dispatch/RouteNotFoundError.js +0 -24
  464. package/dist/dispatch/RouteNotFoundError.js.map +0 -1
  465. package/dist/entry/DynamicFacade.d.ts +0 -10
  466. package/dist/entry/DynamicFacade.d.ts.map +0 -1
  467. package/dist/entry/DynamicFacade.js +0 -27
  468. package/dist/entry/DynamicFacade.js.map +0 -1
  469. package/dist/entry/FacadeEntry.d.ts +0 -11
  470. package/dist/entry/FacadeEntry.d.ts.map +0 -1
  471. package/dist/entry/FacadeEntry.js +0 -26
  472. package/dist/entry/FacadeEntry.js.map +0 -1
  473. package/dist/entry/TransportEntry.d.ts +0 -13
  474. package/dist/entry/TransportEntry.d.ts.map +0 -1
  475. package/dist/entry/TransportEntry.js +0 -24
  476. package/dist/entry/TransportEntry.js.map +0 -1
  477. package/dist/rows.d.ts +0 -40
  478. package/dist/rows.d.ts.map +0 -1
  479. package/dist/rows.js +0 -146
  480. package/dist/rows.js.map +0 -1
  481. package/src/boot/HandlerFacade.ts +0 -242
  482. package/src/contract/Call.ts +0 -18
  483. package/src/contract/CallLog.ts +0 -55
  484. package/src/dispatch/InputValidator.ts +0 -28
  485. package/src/dispatch/OperationExecutor.ts +0 -60
  486. package/src/dispatch/OutputProjector.ts +0 -32
  487. package/src/dispatch/PresenterArgumentResolver.ts +0 -25
  488. package/src/dispatch/RouteNotFoundError.ts +0 -29
  489. package/src/entry/DynamicFacade.ts +0 -28
  490. package/src/entry/FacadeEntry.ts +0 -32
  491. package/src/entry/TransportEntry.ts +0 -30
  492. package/src/rows.ts +0 -155
  493. /package/dist/{contract → wire}/CallLog.js +0 -0
@@ -1,19 +1,7 @@
1
- /**
2
- * The names the scan READS instead of deriving them.
3
- *
4
- * Everything else a frond states, it states by its shape; these seven directories and the
5
- * import prefix are the one place where a name is the declaration. They were spelled as
6
- * literals in five packages, so a project could not move any of them and `frondsDir` was
7
- * a declared key with no reader.
8
- */
1
+ /** The names the scan READS instead of deriving them. */
9
2
 
10
3
  export interface Conventions {
11
- /**
12
- * The scope a frond's package name carries — `@fronds/blog`.
13
- *
14
- * A real package name, not only an alias: the CLI writes it as `name` in a scaffolded
15
- * frond and as a `workspace:*` dependency in the app that consumes it.
16
- */
4
+ /** The scope a frond's package name carries — `@fronds/blog`. */
17
5
  scope: string;
18
6
  /** The directory holding fronds, below the project root. */
19
7
  fronds: string;
@@ -31,12 +19,7 @@ export interface Conventions {
31
19
  };
32
20
  }
33
21
 
34
- /**
35
- * What a project means when it declares nothing — the convention itself.
36
- *
37
- * `@fronds` and not `@frond`: the npm org for the singular belongs to someone else, and a
38
- * scope is a name that must be ownable.
39
- */
22
+ /** What a project means when it declares nothing — the convention itself. */
40
23
  export const DEFAULT_CONVENTIONS: Conventions = {
41
24
  scope: '@fronds',
42
25
  fronds: 'fronds',
@@ -59,13 +42,7 @@ export type ConventionsInput = {
59
42
  dirs?: Partial<Conventions['dirs']>;
60
43
  };
61
44
 
62
- /**
63
- * The convention, with a project's exceptions folded in.
64
- *
65
- * Merged one level into `dirs` so renaming one directory does not require restating the
66
- * other six — the same reading `sources:` and `ports:` get, where only the exception is
67
- * declared.
68
- */
45
+ /** The convention, with a project's exceptions folded in. */
69
46
  export function resolveConventions(input?: ConventionsInput): Conventions {
70
47
  return {
71
48
  scope: input?.scope ?? DEFAULT_CONVENTIONS.scope,
@@ -79,23 +56,12 @@ export function frondPackage(name: string, conventions: Conventions): string {
79
56
  return `${conventions.scope}/${name}`;
80
57
  }
81
58
 
82
- /**
83
- * Directories whose classes register as providers — two spellings, one behaviour.
84
- *
85
- * A project may point both roles at one directory; the scan must then read it once, or
86
- * every provider would be registered twice.
87
- */
59
+ /** Directories whose classes register as providers — two spellings, one behaviour. */
88
60
  export function providerDirsOf(conventions: Conventions): string[] {
89
61
  return [...new Set([conventions.dirs.services, conventions.dirs.repositories])];
90
62
  }
91
63
 
92
- /**
93
- * The frond vocabulary — every directory the scan reads.
94
- *
95
- * What a reader needs to bound a frond: the Nuxt module watches these for the root frond
96
- * (watching the root itself would match every write), and a flat app's tsconfig lists
97
- * them instead of `["."]`, which would swallow `app/` and `nuxt.config.ts`.
98
- */
64
+ /** The frond vocabulary — every directory the scan reads. */
99
65
  export function frondDirsOf(conventions: Conventions): string[] {
100
66
  const { entities, handlers, presenters, collectors, seeds, versions } = conventions.dirs;
101
67
  return [...new Set([
package/src/scan/emit.ts CHANGED
@@ -1,19 +1,4 @@
1
- /**
2
- * The scan, written down as a module — what `createApp` is handed where there is no disk.
3
- *
4
- * It RE-RESOLVES NOTHING. By the time this runs the scan has already decided what every
5
- * slot holds, and `resolveSchema` put the entity's own class in `contract.output` — the
6
- * very object `EntityEntry.entityClass` holds. So the emitter keeps a table from object
7
- * to import alias and writes the alias. Identity is preserved because it is the same
8
- * object that becomes the same import, which is what three call sites depend on
9
- * (`adapter/graphql`'s `view === entity.entityClass` and its WeakMap, and `bootstrap`'s
10
- * `outputSchema !== entity.entityClass`). An emitter that re-resolved instead would build
11
- * a second class for `Post` and those three would silently take the other branch.
12
- *
13
- * Measured on three real projects: every live reference is either a class the descriptor
14
- * already names by `filePath`, a named export of the file that declared the signature, or
15
- * `Partial<X>` — the one derivation `resolveSchema` fabricates.
16
- */
1
+ /** The scan, written down as a module — what `createApp` is handed where there is no disk. */
17
2
  import { dirname, relative } from 'node:path';
18
3
  import { ANONYMOUS_SCHEMA_NAME, Card, type SchemaView } from '@fougere/schema';
19
4
  import type { FrondDescriptor, EntityEntry, HandlerEntry, PresenterEntry, CollectorEntry, ProviderEntry, SeedEntry } from '../descriptor/frond.js';
@@ -32,14 +17,7 @@ type Live = object;
32
17
  /** Is a TypeScript compiler going to read this module? Its name is the only thing that says. */
33
18
  const isTypeScript = (outFile: string): boolean => /\.tsx?$/.test(outFile);
34
19
 
35
- /**
36
- * A source file becomes a specifier its reader can follow — and the two readers differ.
37
- *
38
- * A `.ts` destination is compiled by tsc under Node16 resolution, which spells a
39
- * TypeScript source with `.js`. A `.mjs` destination is read by a bundler, which resolves
40
- * the path AS IT IS ON DISK — measured, Nitro's rollup refused `Post.seed.js` because no
41
- * such file exists. One rule, read off the destination, exactly like the type annotation.
42
- */
20
+ /** A source file becomes a specifier its reader can follow — and the two readers differ. */
43
21
  function specifierOf(filePath: string, outFile: string): string {
44
22
  const path = relative(dirname(outFile), filePath);
45
23
  const rel = isTypeScript(outFile) ? path.replace(/\.tsx?$/, '.js') : path;
@@ -81,15 +59,7 @@ class Imports {
81
59
  render(): string { return this.lines.join('\n'); }
82
60
  }
83
61
 
84
- /**
85
- * What a schema slot becomes in the generated module.
86
- *
87
- * Three answers, and the third is the only rule: a class already imported is its alias; a
88
- * named export of the file that declared the signature is imported by its own name — it
89
- * IS exported there, because that is where `resolveSchema` found it; and an anonymous
90
- * schema is `Partial<X>`, the one derivation `resolveSchema` builds, so it is written as
91
- * the derivation rather than as a value.
92
- */
62
+ /** What a schema slot becomes in the generated module. */
93
63
  function schemaRef(schema: SchemaView | undefined, declaredIn: string, imports: Imports): string | undefined {
94
64
  if (!schema) return undefined;
95
65
  const known = imports.aliasOf(schema as Live);
@@ -178,11 +148,7 @@ function frondOf(f: FrondDescriptor, imports: Imports): string {
178
148
  ].filter(Boolean).join('\n');
179
149
  }
180
150
 
181
- /**
182
- * Write a scan down. The result is a TypeScript module whose only imports are the classes
183
- * the scan found — static, so a bundler traces them — and whose only value is the
184
- * descriptor `createApp` asks for.
185
- */
151
+ /** Write a scan down. */
186
152
  export function emitScan(result: ScanResult, options: EmitOptions): string {
187
153
  const imports = new Imports(options.outFile);
188
154
  const core = options.core ?? '@fougere/core';
@@ -1,9 +1,4 @@
1
- /**
2
- * Handler signature parser — extracts method signatures from handler source files.
3
- *
4
- * The AST says what the author declared; TypeScript's checker says what those types mean.
5
- * TypeScript is lazy-loaded to avoid bundling the compiler in production builds.
6
- */
1
+ /** Handler signature parser — extracts method signatures from handler source files. */
7
2
  import type { TypeRef, Param, Signature } from '../wire/signature.js';
8
3
  import type ts from '@typescript/typescript6';
9
4
  import { readFileSync, existsSync, statSync } from 'node:fs';
@@ -26,26 +21,11 @@ interface TypeProject {
26
21
  program: ts.Program;
27
22
  }
28
23
 
29
- /**
30
- * One checked program per project/configuration during a scan.
31
- *
32
- * A checker is a project reader, not a file parser: creating one per handler would reopen
33
- * the standard library and every imported declaration for each method. `scanProject`
34
- * resets this map at the start of a run, so an edited source can never meet a program from
35
- * the previous run.
36
- */
24
+ /** One checked program per project/configuration during a scan. */
37
25
  const typeProjects = new Map<string, TypeProject>();
38
26
  const compilerProjects = new Map<string, { key: string; roots: string[]; options: ts.CompilerOptions }>();
39
27
 
40
- /**
41
- * What survives a run: the parsed declarations, and the program built over them.
42
- *
43
- * Rebuilding a program re-reads `lib.d.ts` and every imported `.d.ts`, and that is FIXED
44
- * work — measured, a second scan in one process cost the same at 16 frond files as at 406.
45
- * The mtime is the guard, so a run still cannot see a stale type: a file that moved is
46
- * re-read and TypeScript invalidates it and everything depending on it, which is a
47
- * narrower rule than discarding the program and not a weaker one.
48
- */
28
+ /** What survives a run. */
49
29
  const sourceFiles = new Map<string, { mtime: number; file: ts.SourceFile }>();
50
30
  const retained = new Map<string, { host: ts.CompilerHost; program: ts.Program }>();
51
31
 
@@ -61,8 +41,8 @@ export function forgetParsedSources(): void {
61
41
  }
62
42
 
63
43
  function keptHost(key: string, options: ts.CompilerOptions): ts.CompilerHost {
64
- const held = retained.get(key);
65
- if (held) return held.host;
44
+ const cached = retained.get(key);
45
+ if (cached) return cached.host;
66
46
  const typescript = getTS();
67
47
  const base = typescript.createCompilerHost(options);
68
48
  const host: ts.CompilerHost = {
@@ -138,13 +118,7 @@ function compilerProjectOf(filePath: string, projectRoot?: string): { key: strin
138
118
  return configured;
139
119
  }
140
120
 
141
- /**
142
- * Declare every file a run will read, so one program covers it.
143
- *
144
- * `checkedSourceOf` rebuilds whenever it meets a root it has not seen, and a frond lives
145
- * outside its project's tsconfig `include`, so every declaration was a new root: 44 files
146
- * cost 7.3 s that way against 0.34 s for one program.
147
- */
121
+ /** Declare every file a run will read, so one program covers it. */
148
122
  export async function seedTypeProgram(filePaths: readonly string[], projectRoot?: string): Promise<void> {
149
123
  const typescript = await loadTS();
150
124
  const grouped = new Map<string, { options: ts.CompilerOptions; paths: string[] }>();
@@ -152,9 +126,9 @@ export async function seedTypeProgram(filePaths: readonly string[], projectRoot?
152
126
  for (const filePath of filePaths) {
153
127
  const absolute = resolvePath(filePath);
154
128
  const configured = compilerProjectOf(absolute, projectRoot);
155
- const held = grouped.get(configured.key) ?? { options: configured.options, paths: [] };
156
- held.paths.push(absolute);
157
- grouped.set(configured.key, held);
129
+ const group = grouped.get(configured.key) ?? { options: configured.options, paths: [] };
130
+ group.paths.push(absolute);
131
+ grouped.set(configured.key, group);
158
132
  }
159
133
 
160
134
  for (const [key, { options, paths }] of grouped) {
@@ -168,25 +142,25 @@ function checkedSourceOf(filePath: string, projectRoot?: string): { source: ts.S
168
142
  const typescript = getTS();
169
143
  const absolute = resolvePath(filePath);
170
144
  const configured = compilerProjectOf(absolute, projectRoot);
171
- let held = typeProjects.get(configured.key);
145
+ let project = typeProjects.get(configured.key);
172
146
 
173
- if (!held) {
147
+ if (!project) {
174
148
  // `path.resolve` is variadic, so handing it directly to `map` also passed the
175
149
  // index and the whole roots array as path segments. A fixture without a warm scan
176
150
  // cache exposed that first-run-only failure.
177
151
  const roots = new Set(configured.roots.map((root) => resolvePath(root)));
178
152
  roots.add(absolute);
179
153
  const program = builtProgram(configured.key, [...roots], configured.options);
180
- held = { roots, options: configured.options, program };
181
- typeProjects.set(configured.key, held);
182
- } else if (!held.roots.has(absolute)) {
183
- held.roots.add(absolute);
184
- held.program = builtProgram(configured.key, [...held.roots], held.options);
154
+ project = { roots, options: configured.options, program };
155
+ typeProjects.set(configured.key, project);
156
+ } else if (!project.roots.has(absolute)) {
157
+ project.roots.add(absolute);
158
+ project.program = builtProgram(configured.key, [...project.roots], project.options);
185
159
  }
186
160
 
187
- const source = held.program.getSourceFile(absolute);
161
+ const source = project.program.getSourceFile(absolute);
188
162
  if (!source) throw new Error(`TypeScript did not include '${absolute}' in its program.`);
189
- return { source, checker: held.program.getTypeChecker() };
163
+ return { source, checker: project.program.getTypeChecker() };
190
164
  }
191
165
 
192
166
  /** A file, opened. Five places read and parsed one, each spelling the same two calls. */
@@ -428,20 +402,7 @@ function resolveSpecifier(specifier: string, fromFile: string, projectRoot: stri
428
402
 
429
403
  // ── Mixin / heritage parsing ─────────────────
430
404
 
431
- /**
432
- * The class a returned expression carries, however it is wrapped.
433
- *
434
- * A mixin does not always hand its class back bare. `Crud` returns
435
- * `asCrudConstructor(class CrudHandler { … })` — one assertion helper standing between
436
- * `return` and the class — and a parser accepting only a bare `return class` found
437
- * nothing there, silently: the five inherited CRUD ops stopped being derived, and a warm
438
- * scan cache kept answering the old parse for weeks (`scan-cache.ts` keys on source, not
439
- * on parser version).
440
- *
441
- * So unwrap rather than match one shape: descend through call arguments, `as` and
442
- * `satisfies` assertions, and parentheses. What is looked for is a class; where the
443
- * author put it is their business.
444
- */
405
+ /** The class a returned expression carries, however it is wrapped. */
445
406
  function classInExpression(expr: ts.Node, depth = 0): ts.ClassExpression | undefined {
446
407
  const ts = getTS();
447
408
  if (depth > 8) return undefined;
@@ -502,7 +463,7 @@ function extractClassMethods(
502
463
  // `private`/`protected` is a statement about the surface, and the AST carries it —
503
464
  // it was read past. Every helper a handler names by intent (`mustOwn`, `readMany`,
504
465
  // `refuse`) became a callable op: measured on the bench, `list.readMany` executed
505
- // and `list.mayPublish` judged its argument. A door is what the author declares
466
+ // and `list.mayPublish` validated its argument. A door is what the author declares
506
467
  // public, and TypeScript already has the word for it. `#name` is private too, but
507
468
  // it is not an identifier, so it never reached here in the first place.
508
469
  if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)) continue;
@@ -521,14 +482,7 @@ function extractClassMethods(
521
482
  return results;
522
483
  }
523
484
 
524
- /**
525
- * The first sentence of a member's doc comment, or nothing.
526
- *
527
- * One sentence on purpose: what a caller needs to choose an operation is a claim,
528
- * not an essay, and the rest of the comment addresses whoever edits the method.
529
- * Reads the leading trivia rather than `ts.getJSDocTags` — the comment is what the
530
- * author wrote, tags are a schema they never agreed to.
531
- */
485
+ /** The first sentence of a member's doc comment, or nothing. */
532
486
  function docSentenceOf(member: ts.Node, source: ts.SourceFile): string | undefined {
533
487
  const ts = getTS();
534
488
  const ranges = ts.getLeadingCommentRanges(source.text, member.pos) ?? [];
@@ -551,11 +505,7 @@ function docSentenceOf(member: ts.Node, source: ts.SourceFile): string | undefin
551
505
  * Parse inherited methods from a class's heritage clause.
552
506
  * Handles both `extends Crud(Entity)` (mixin) and `extends BaseClass` patterns.
553
507
  */
554
- /**
555
- * Where a name used here is declared. The checker follows the import, the re-export chain
556
- * and an installed package's types — the three cases three hand-rolled functions treated
557
- * separately.
558
- */
508
+ /** Where a name used here is declared. */
559
509
  function declarationFileOf(node: ts.Node, checker: ts.TypeChecker): string | undefined {
560
510
  const typescript = getTS();
561
511
  let symbol = checker.getSymbolAtLocation(node);
@@ -564,13 +514,7 @@ function declarationFileOf(node: ts.Node, checker: ts.TypeChecker): string | und
564
514
  return symbol.declarations?.[0]?.getSourceFile().fileName;
565
515
  }
566
516
 
567
- /**
568
- * The methods a base class contributes, read from the INSTANTIATED type.
569
- *
570
- * `extends Crud(Post)` gives `create(input: Partial<Post>)` directly: the checker has
571
- * already substituted the mixin's type parameter. The three functions this replaces
572
- * detected the generic names and mapped them to the mixin's arguments by position.
573
- */
517
+ /** The methods a base class contributes, read from the INSTANTIATED type. */
574
518
  function inheritedFromBase(
575
519
  base: ts.ExpressionWithTypeArguments,
576
520
  checker: ts.TypeChecker,
@@ -617,10 +561,8 @@ function parseInheritedMethods(
617
561
  checker: ts.TypeChecker,
618
562
  skip: Set<string>,
619
563
  /**
620
- * Base classes this pass could not open — an INSTALLED one, typically, whose
621
- * source is not in the workspace. Reported rather than treated as "no inherited
622
- * method": the two used to be the same answer, so an op inherited from a
623
- * published base class was absent from the façade without a word.
564
+ * Base classes this pass could not open — an INSTALLED one, typically, whose source is not in
565
+ * the workspace.
624
566
  */
625
567
  unresolved: string[],
626
568
  ): Signature[] {
@@ -685,14 +627,7 @@ function findDefaultClass(source: ts.SourceFile): ts.ClassDeclaration | undefine
685
627
  return undefined;
686
628
  }
687
629
 
688
- /**
689
- * What a handler file yielded — its methods, AND what the pass could not open.
690
- *
691
- * The second half is why this is a pair rather than an array: an unresolvable base
692
- * class used to give the same answer as a base class with no method, so an op
693
- * inherited from an installed package was missing from the façade in silence. The
694
- * pair travels through the scan cache, which is why {@link PARSER_VERSION} moved.
695
- */
630
+ /** What a handler file yielded — its methods, AND what the pass could not open. */
696
631
  export interface HandlerParse {
697
632
  methods: Signature[];
698
633
  /** Base classes whose source this pass could not open. Empty is a claim. */
@@ -708,11 +643,7 @@ export async function parseAllHandlerMethods(filePath: string, projectRoot?: str
708
643
  return parseClassMethods(filePath, CONSTRUCTOR_ONLY, projectRoot);
709
644
  }
710
645
 
711
- /**
712
- * Parse a presenter source file and extract all method signatures.
713
- *
714
- * Returns all methods (no CRUD filtering) — each method is a computed field.
715
- */
646
+ /** Parse a presenter source file and extract all method signatures. */
716
647
  export async function parsePresenterMethods(filePath: string, projectRoot?: string): Promise<Signature[]> {
717
648
  await loadTS();
718
649
  // No `projectRoot`, so no heritage pass and nothing to report: a presenter's
@@ -1,24 +1,11 @@
1
1
  import type { Fronds } from '../descriptor/Fronds.js';
2
2
 
3
3
  /** Result of scanning a project directory. */
4
- /**
5
- * Something the scan could NOT do — recorded instead of swallowed.
6
- *
7
- * The scan answers with what it found. Until now it answered the same way whether
8
- * a directory held nothing or could not be read, and whether a handler declared no
9
- * operation or failed to parse: `catch → empty`. So every downstream reader — the
10
- * façade, the identity card, anything asking "what does this app serve?" — could
11
- * not tell **"there is nothing"** from **"I could not look"**.
12
- *
13
- * That distinction is what makes a rule about an ABSENCE sound. Without it, a check
14
- * derived from the scan reports "nothing wrong" precisely when it read nothing.
15
- */
4
+ /** Something the scan could NOT do — recorded instead of swallowed. */
16
5
  export interface ScanDiagnostic {
17
6
  /**
18
- * `blocking` — the app now serves less than its source declares, and no caller
19
- * can know it: a handler that failed to parse contributes zero operations.
20
- * `warning` — something may be missing and the scan cannot decide, e.g. a base
21
- * class it is not allowed to resolve. Statable in `frond.config.ts`.
7
+ * `blocking` — the app now serves less than its source declares, and no caller can know it: a
8
+ * handler that failed to parse contributes zero operations.
22
9
  */
23
10
  severity: 'blocking' | 'warning';
24
11
  /** Stable rule name — `handler-parse-failed`, `directory-unreadable`. */
@@ -31,13 +31,7 @@ import {
31
31
 
32
32
  // FS
33
33
 
34
- /**
35
- * What this scan run could not do. Reset by {@link scanProject}, which owns a run.
36
- *
37
- * Module-scoped like the loader and the cache root above: the scanner already has a
38
- * notion of "the current run". Three sites record — measured — so a per-run object
39
- * would carry twenty methods to spare one line of reset.
40
- */
34
+ /** What this scan run could not do. */
41
35
  let diagnostics: ScanDiagnostic[] = [];
42
36
 
43
37
  function record(d: ScanDiagnostic): void {
@@ -45,10 +39,8 @@ function record(d: ScanDiagnostic): void {
45
39
  }
46
40
 
47
41
  /**
48
- * An absent convention directory is the ordinary case — a frond without
49
- * `presenters/` is not a defect. Anything else (permissions, an I/O error, a path
50
- * that is not a directory) means the scan did not look, and answering `[]` says
51
- * it did. One `catch` used to conflate the two.
42
+ * An absent convention directory is the ordinary case — a frond without `presenters/` is not a
43
+ * defect.
52
44
  */
53
45
  async function readEntries(path: string): Promise<Dirent[]> {
54
46
  try {
@@ -115,13 +107,7 @@ function findWorkspaceRoot(from: string): string {
115
107
  return resolvePath(from); // fallback: use project root itself
116
108
  }
117
109
 
118
- /**
119
- * Strip the 'Handler' suffix → the name the handler answers to. 'PostHandler' → 'post'.
120
- *
121
- * Nothing here checks that an entity carries the result, and nothing should: a handler
122
- * about no stored row is ordinary. The old name of this function — `toEntityName` — is
123
- * what let "one façade per entity" be repeated until it read as a rule.
124
- */
110
+ /** Strip the 'Handler' suffix → the name the handler answers to. */
125
111
  function toAddress(className: string): string {
126
112
  const base = className.endsWith('Handler') ? className.slice(0, -7) : className;
127
113
  return lowerFirst(base);
@@ -130,18 +116,8 @@ function toAddress(className: string): string {
130
116
  // Scan
131
117
 
132
118
  /**
133
- * The container key a constructor parameter asks for — derived from its TYPE, not from
134
- * how the type was spelled.
135
- *
136
- * `deps` used to be `p.type.name`, so the key WAS the alias's name: `type ListStorage =
137
- * Storage<List>` resolved only because someone had spelled it exactly like the
138
- * registration key (`ListStorage`), while `type ListRepo = Storage<List>` — the same type —
139
- * typechecked and died at boot on `'ListRepo' is not registered`. And `Storage<List>`
140
- * written out in full asked for `'Storage'`, which nothing registers.
141
- *
142
- * `Storage<X>` names X's storage, so that is the key. The generic argument was already
143
- * parsed (`TypeRef.generics`) and thrown away. Anything else keeps its own name: a
144
- * plain service IS designated by its class name.
119
+ * The container key a constructor parameter asks for — derived from its TYPE, not from how the
120
+ * type was spelled.
145
121
  */
146
122
  function depKeyOf(type: TypeRef): string {
147
123
  // `Facade<PostHandler>` — the second port, read exactly like the first. The type names
@@ -166,32 +142,25 @@ function depKeyOf(type: TypeRef): string {
166
142
  // `RepositoryOf<Post>` — what an author writes when no repository file exists. The dual
167
143
  // of the line below: one names the port, the other the holder, and both resolve to a key
168
144
  // rather than to a class the author would have to invent.
169
- const held = type.name === 'RepositoryOf' ? type.generics?.[0]?.name : undefined;
170
- if (held) return repositoryKeyOf(held);
145
+ const subject = type.name === 'RepositoryOf' ? type.generics?.[0]?.name : undefined;
146
+ if (subject) return repositoryKeyOf(subject);
171
147
 
172
- const target = type.name === 'Storage' ? type.generics?.[0]?.name : undefined;
148
+ // The GENERIC names the subject, so a prefix does not change the key — `MeiliStorage<Card>`
149
+ // is `Card`'s storage. A class named `FileStorage` is untouched: it carries no generic.
150
+ const target = type.name.endsWith('Storage') && type.generics?.length === 1
151
+ ? type.generics[0]?.name
152
+ : undefined;
173
153
  if (!target) return type.name;
174
154
 
175
155
  return storageKeyOf(target);
176
156
  }
177
157
 
178
- /**
179
- * `'[Account, Ledger]'` → `['Account', 'Ledger']`.
180
- *
181
- * The tuple was chosen over the variadic form the parser reads more cleanly, because the
182
- * variadic one costs arities-with-defaults and a `never` filter on the TypeScript side
183
- * while the tuple maps to `[Storage<Account>, Storage<Ledger>]` in one line. The
184
- * parser does not get to decide alone; this split is what that choice costs.
185
- */
158
+ /** `'[Account, Ledger]'` → `['Account', 'Ledger']`. */
186
159
  function tupleMembers(raw: string): string[] {
187
160
  return raw.replace(/^\[|\]$/g, '').split(',').map((member) => member.trim()).filter(Boolean);
188
161
  }
189
162
 
190
- /**
191
- * These readings are semantic: an unchanged file can mean something different after an
192
- * imported alias changes. The parser's TypeScript Program is the cache for one scan; a
193
- * cache keyed only by this file's bytes would be unsound.
194
- */
163
+ /** These readings are semantic. */
195
164
  const ctorParamsOf = (filePath: string) =>
196
165
  parseConstructorParams(filePath);
197
166
 
@@ -272,12 +241,7 @@ function resolveSchema(type: TypeRef, moduleExports: Record<string, unknown>): S
272
241
  return undefined;
273
242
  }
274
243
 
275
- /**
276
- * Parse ALL method signatures for unified binding.
277
- *
278
- * Resolves schemas for all params (not just the first) and stores
279
- * full signatures for the binding algorithm.
280
- */
244
+ /** Parse ALL method signatures for unified binding. */
281
245
  async function inferOperations(
282
246
  filePath: string,
283
247
  handlerName: string,
@@ -308,15 +272,8 @@ async function inferOperations(
308
272
  }
309
273
 
310
274
  /**
311
- * A base class the parse could not open — an installed package, typically, whose
312
- * source is not in the workspace. Its operations are missing from this façade, and
313
- * the scan cannot tell whether there were any.
314
- *
315
- * A warning, not a refusal: an installed base class with no operation is perfectly
316
- * ordinary, and the boot has no way to decide between the two. So it names the
317
- * clause and stops there. Stating the contract in `frond.config.ts` is the answer
318
- * — the third producer, which creates an op neither other producer found — and it
319
- * silences this by making the op exist.
275
+ * A base class the parse could not open — an installed package, typically, whose source is not
276
+ * in the workspace.
320
277
  */
321
278
  for (const base of parsed.unresolvedHeritage) {
322
279
  record({
@@ -342,10 +299,10 @@ async function inferOperations(
342
299
  // caller supplies through the body are candidates: a schema-typed collector, fact or
343
300
  // context parameter is not input merely because it names an entity. The old loop
344
301
  // ignored provenance and assigned the first schema it met, so swapping two parameters
345
- // silently changed the contract the façade used to judge the request body.
302
+ // silently changed the contract the façade used to validate the request body.
346
303
  const binding = computeBindingPlan(method.params, collectorTypeNames);
347
304
  const candidates = method.params.flatMap((param, index) => {
348
- if (binding[index]?.source.kind !== 'body') return [];
305
+ if (binding[index]?.source.kind !== 'input') return [];
349
306
  const schema = resolveSchema(param.type, moduleExports);
350
307
  return schema ? [{ param, schema }] : [];
351
308
  });
@@ -522,13 +479,7 @@ async function scanFrond(frondPath: string, name: string, source: FrondDescripto
522
479
  entities: entitiesDir, handlers: handlersDir,
523
480
  presenters: presentersDir, collectors: collectorsDir, seeds: seedsDir,
524
481
  } = conventions.dirs;
525
- /**
526
- * A convention directory, read by whoever knows the shape it holds.
527
- *
528
- * The same three lines were written six times — list, read in parallel, drop what the
529
- * reader refused — which is what made `handlers/` quietly special: it grew a second
530
- * pass for its surfaces and nothing else could.
531
- */
482
+ /** A convention directory, read by whoever knows the shape it holds. */
532
483
  const collect = async <T extends object>(
533
484
  dir: string,
534
485
  read: (filePath: string) => Promise<T | null>,
@@ -615,15 +566,7 @@ async function scanFrond(frondPath: string, name: string, source: FrondDescripto
615
566
  };
616
567
  }
617
568
 
618
- /**
619
- * The frond's name — the directory, unless its `package.json` renames it. One rule for a
620
- * frond under `fronds/` and for the root frond alike, so the root needs no second spelling.
621
- *
622
- * Carrying the convention is what makes a frond; the key never marked anything and
623
- * nothing read it. It earns its keep as the one thing the directory cannot say: that
624
- * `fronds/blog-v2/` serves the frond still called `blog` — so a rename on disk does not
625
- * rename the entity keys, the `@fronds/*` import or a `remotes:` entry.
626
- */
569
+ /** The frond's name — the directory, unless its `package.json` renames it. */
627
570
  async function frondNameOf(frondPath: string, dirName: string): Promise<string> {
628
571
  try {
629
572
  const pkg = JSON.parse(await readFile(join(frondPath, 'package.json'), 'utf8')) as {
@@ -637,15 +580,8 @@ async function frondNameOf(frondPath: string, dirName: string): Promise<string>
637
580
  }
638
581
 
639
582
  /**
640
- * A frond is a directory carrying the convention, and the project root is one such
641
- * directory — so a single-domain app writes `entities/` next to `app/` and never names
642
- * anything. `fronds/` is not the definition, it is where the OTHERS live: the root frond
643
- * stays put when a second domain appears, which is what makes flattening free instead of
644
- * a deferred move.
645
- *
646
- * `entities/` is the test, not "any convention directory". `services/` and `repositories/`
647
- * are ordinary top-level names in projects that never heard of Fougere, and a domain
648
- * without a single entity is not a domain.
583
+ * A frond is a directory carrying the convention, and the project root is one such directory — so
584
+ * a single-domain app writes `entities/` next to `app/` and never names anything.
649
585
  */
650
586
  async function rootFrondOf(root: string, workspaceRoot: string, conventions: Conventions): Promise<FrondDescriptor | null> {
651
587
  if ((await files(join(root, conventions.dirs.entities))).length === 0) return null;
@@ -653,21 +589,7 @@ async function rootFrondOf(root: string, workspaceRoot: string, conventions: Con
653
589
  return scanFrond(root, name, { path: root, package: frondPackage(name, conventions) }, conventions, workspaceRoot);
654
590
  }
655
591
 
656
- /**
657
- * `@fronds/<name>` → the directory it names, for every frond of a project.
658
- *
659
- * The framework states this convention — `FrondSource.package` has always spelled it, and
660
- * `fougere sync` writes it into a consumer's tsconfig — and until now its own reader could
661
- * not resolve it. The Nuxt module registered a Vite alias, so a `.vue` page could import
662
- * `@fronds/blog/entities/Post`, while the SCAN loaded sources through a bare jiti: a frond
663
- * naming its neighbour got `Cannot find module '@fronds/user/entities/User.js'`. So the one
664
- * form that survives a split was the one form that did not run.
665
- *
666
- * Hand it to the module loader — `createJiti(url, { alias: await frondAliases(root) })` —
667
- * and the named form resolves everywhere the framework reads. A directory listing and a
668
- * `package.json` read, no parsing: it is deliberately callable BEFORE the loader exists,
669
- * which is what makes the chicken-and-egg go away.
670
- */
592
+ /** `@fronds/<name>` → the directory it names, for every frond of a project. */
671
593
  export async function frondAliases(root: string, conventions: Conventions = DEFAULT_CONVENTIONS): Promise<Record<string, string>> {
672
594
  const frondsDir = join(root, conventions.fronds);
673
595
  const aliases: Record<string, string> = {};
@@ -681,17 +603,7 @@ export async function frondAliases(root: string, conventions: Conventions = DEFA
681
603
  aliases[frondPackage(await frondNameOf(path, dir), conventions)] = resolvePath(path);
682
604
  }
683
605
 
684
- /**
685
- * A SYNCED frond answers to the same name.
686
- *
687
- * `fougere sync` writes `.fougere/remotes/<name>/` and registers it in `remotes.json`,
688
- * which the Nuxt module already reads to alias `@fronds/<name>`. Doing it here too is
689
- * what makes the convention mean ONE thing: a consumer writes `@fronds/blog/entities/Post`
690
- * and never learns whether that frond is on this disk or was fetched from a card.
691
- *
692
- * A local frond wins a name collision — its source is the truth, a synced copy is a
693
- * mirror of somebody else's.
694
- */
606
+ /** A SYNCED frond answers to the same name. */
695
607
  try {
696
608
  const registry = JSON.parse(
697
609
  await readFile(join(root, '.fougere', 'remotes.json'), 'utf8'),
@@ -757,18 +669,7 @@ export async function scanProject(
757
669
  return { fronds, diagnostics };
758
670
  }
759
671
 
760
- /**
761
- * What changes when a frond's domain changes — the paths a dev loop watches.
762
- *
763
- * It lives beside the scan rather than beside the conventions it reads, because it turns
764
- * names into DISK paths: `join` is `node:path`, and `conventions.ts` is reached from
765
- * `index` through `frond()`, which an edge bundle imports. Measured — esbuild refused the
766
- * Worker with `Could not resolve "node:path"`.
767
- *
768
- * The root frond IS the scan root, so watching its path would match every write in the
769
- * project: `.nuxt/`, `node_modules/`, the build output. Its convention directories are
770
- * the frond, and they are what a scan re-reads.
771
- */
672
+ /** What changes when a frond's domain changes — the paths a dev loop watches. */
772
673
  export function watchPathsOf(
773
674
  frond: { source: { path: string } },
774
675
  scanRoot: string,