@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
package/src/boot/apply.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { FougereConfig } from '../config-loader.js';
2
- import { setLogLevel, logLevel, envLevel } from '../builtins/logger.js';
2
+ import { setLogLevel, logLevel, envLevel } from '../builtin/logger.js';
3
3
  import { dequal } from 'dequal';
4
4
 
5
5
  export interface ConfigApplication {
@@ -9,25 +9,13 @@ export interface ConfigApplication {
9
9
  pending: string[];
10
10
  }
11
11
 
12
- /**
13
- * What a (re-)read config changes in a process that is already running.
14
- *
15
- * The rule it realizes, and the only one worth remembering: **a value that is
16
- * CONSULTED can change under a running app; a value that was CONSUMED to build
17
- * something cannot, without rebuilding what it built.** `logLevel` is consulted at
18
- * every emission, so it moves. `db` opened a connection, `ports:` registered a class,
19
- * the entities built façades — those are consumed, and this function reports them
20
- * rather than pretending.
21
- *
22
- * The list of consulted keys is not declared anywhere: a key is consulted when this
23
- * function does something with it, which is the only definition that cannot go stale.
24
- */
12
+ /** What a (re-)read config changes in a process that is already running. */
25
13
  export function applyConfig(next: FougereConfig, inForce?: FougereConfig): ConfigApplication {
26
14
  const applied: string[] = [];
27
15
  const pending: string[] = [];
28
16
 
29
17
  // The CLI speaks through the environment, so it keeps winning over the file — read
30
- // through `envLevel`, which is where the environment is already judged. Casting it
18
+ // through `envLevel`, which is where the environment is already validated. Casting it
31
19
  // here was a second reader that validated nothing: `FOUGERE_LOG_LEVEL=verbose` set
32
20
  // the threshold to `undefined` and every log passed.
33
21
  const wanted = envLevel() ?? next.logLevel ?? 'debug';
package/src/boot/auth.ts CHANGED
@@ -5,13 +5,7 @@
5
5
  import type { SchemaView } from '@fougere/schema';
6
6
  import type { Storage, StorageFactory } from '../storage.js';
7
7
 
8
- /**
9
- * Lazy auth declaration written in fougere.config.ts.
10
- *
11
- * Each @fougere/auth-* package exports a factory (e.g. `betterAuth(opts)`) that
12
- * returns this shape. The `create()` method is called once at boot with the
13
- * resolved db + storageFactory, so the provider can wire its engine through Fougere.
14
- */
8
+ /** Lazy auth declaration written in fougere.config.ts. */
15
9
  export interface AuthConfig {
16
10
  /** Build the runtime — invoked by createApp at boot with the resolved storage handles. */
17
11
  create(ctx: AuthContext): AuthRuntime | Promise<AuthRuntime>;
@@ -40,11 +34,7 @@ export interface AuthContext {
40
34
  export interface AuthRuntime {
41
35
  /** Entities used by the provider, including any defaults it filled in. */
42
36
  entities: Record<string, SchemaView>;
43
- /**
44
- * Per-entity ORMs the provider built for itself. Exposed so app code can
45
- * query auth tables (e.g. list active sessions for a user) without rebuilding
46
- * the same Storage.
47
- */
37
+ /** Per-entity ORMs the provider built for itself. */
48
38
  storages: Record<string, Storage>;
49
39
  /** Web Standard handler that processes /auth/* requests. */
50
40
  handler: (request: Request) => Promise<Response>;
package/src/boot/boot.ts CHANGED
@@ -2,7 +2,7 @@ import { createApp } from './bootstrap.js';
2
2
  import { seeding } from './seed.js';
3
3
  import { scanProject } from '../scan/scanner.js';
4
4
  import { loadConfig, type FougereConfig } from '../config-loader.js';
5
- import { Logger } from '../builtins/logger.js';
5
+ import { Logger } from '../builtin/logger.js';
6
6
  import { applyConfig } from './apply.js';
7
7
  import type { App, CreateAppOptions } from './types.js';
8
8
  import { migrating, type Extension } from './AppLifecycle.js';
@@ -25,11 +25,7 @@ interface BootOptions {
25
25
  remotes?: Record<string, string>;
26
26
  /** Builds the transport to reach `remotes`. Supplied by a layer-2 package. */
27
27
  remoteTransport?: (url: string) => Transport;
28
- /**
29
- * Carries an announced fact out of this process. Forwarded rather than dropped: a
30
- * caller handing one in has no other way to reach the emitter, and this path silently
31
- * kept it to itself.
32
- */
28
+ /** Carries an announced fact out of this process. */
33
29
  onEmit?: CreateAppOptions['onEmit'];
34
30
  /**
35
31
  * storage setup — returns the storage handle (db), an storageFactory, and its two halves.
@@ -38,11 +34,7 @@ interface BootOptions {
38
34
  db?: (config: FougereConfig) => {
39
35
  db?: unknown;
40
36
  storageFactory: CreateAppOptions['storageFactory'];
41
- /**
42
- * Bring the schema up to date — an extension's `up`, because it runs after the
43
- * container. It used to be called `afterBoot`, a word that also meant the host's
44
- * post-boot and was read in four places under two senses.
45
- */
37
+ /** Bring the schema up to date — an extension's `up`, because it runs after the container. */
46
38
  migrate?: (app: App) => Promise<void> | void;
47
39
  /** Closes what the factory opened — `boot()` called it, so `boot()` releases it. */
48
40
  close?: () => Promise<void>;
@@ -54,12 +46,7 @@ interface BootOptions {
54
46
  extensions?: readonly (Extension | undefined)[];
55
47
  }
56
48
 
57
- /**
58
- * Boot a Fougere app from fougere.config.ts.
59
- *
60
- * Handles: config loading, container creation, DB setup, seeding.
61
- * Works for any surface (Nuxt, GraphQL standalone, CLI, tests).
62
- */
49
+ /** Boot a Fougere app from fougere.config.ts. */
63
50
  export async function boot(options: BootOptions): Promise<App> {
64
51
  const bootStart = performance.now();
65
52
  const log = new Logger('boot');
@@ -103,9 +90,7 @@ export async function boot(options: BootOptions): Promise<App> {
103
90
  // it was opened before the container existed, so it closes after the container goes.
104
91
  onDispose: dbSetup?.close,
105
92
  /**
106
- * The whole ascent, in one ordered list — tables, then rows, then whatever the host
107
- * takes on. It was four call sites under the name `afterBoot`, two of which meant
108
- * different things and one of which was generated into a Nitro plugin.
93
+ * The whole ascent, in one ordered list — tables, then rows, then whatever the host takes on.
109
94
  */
110
95
  extensions: [
111
96
  migrating(dbSetup?.migrate),
@@ -5,12 +5,12 @@ import { hostedBy } from './hosted.js';
5
5
  import type { AuthRuntime } from './auth.js';
6
6
  import type { CreateAppOptions, App } from './types.js';
7
7
  import type { AppMiddleware } from '../wire/middleware.js';
8
- import { Logger } from '../builtins/logger.js';
9
- import { Config } from '../builtins/config.js';
8
+ import { Logger } from '../builtin/logger.js';
9
+ import { Config } from '../builtin/config.js';
10
10
  import { createRemoteRouter, createRemoteFacade } from './remote.js';
11
11
  import { registerFrames } from './together.js';
12
12
  import { Emissions } from './Emissions.js';
13
- import { HandlerFacade } from './HandlerFacade.js';
13
+ import { HandlerFacade } from '../dispatch/HandlerFacade.js';
14
14
  import { targetOf } from '../prefab/prefab.js';
15
15
  import { ownersOf, refuseStorageInUserCode, refuseCrudOnOwned } from './ownership.js';
16
16
  import type { OperationContract, OperationsMap } from '../wire/operation.js';
@@ -25,48 +25,28 @@ import { InFlight } from '../dispatch/InFlight.js';
25
25
  import { facadeKeyOf, contractsKeyOf, type RpcAnswer } from '../wire/call.js';
26
26
  import { identityCardOf } from './card.js';
27
27
  import { AppLifecycle } from './AppLifecycle.js';
28
+ import { inheritsCrud, subjectOf } from '../prefab/crud.js';
28
29
  import { repositoryKeyOf } from '../prefab/repository.js';
29
30
  import { storageKeyOf } from '../storage.js';
30
31
  import { presenterKeyOf } from '../prefab/presenter.js';
31
32
  import { collectorKeyOf } from '../prefab/collector.js';
32
- import { RouteAddress } from '../contract/RouteAddress.js';
33
+ import { RouteAddress } from '../wire/RouteAddress.js';
33
34
  import { DispatchLifecycle } from '../dispatch/DispatchLifecycle.js';
34
35
  import { Dispatcher } from '../dispatch/Dispatcher.js';
35
36
  import { LocalRoutePolicy } from '../dispatch/LocalRoutePolicy.js';
36
37
  import { OperationRoute } from '../dispatch/OperationRoute.js';
37
- import { RemoteRouteResolver } from '../dispatch/RemoteRouteResolver.js';
38
+ import { remoteRoutes } from '../dispatch/remoteRoutes.js';
38
39
  import { RouteRegistry } from '../dispatch/RouteRegistry.js';
39
- import { FacadeEntry } from '../entry/FacadeEntry.js';
40
+ import { facadeOperations } from '../entry/facade.js';
40
41
 
41
42
 
42
- /**
43
- * The one wording for "nobody hosts this here", with both ways out. Said twice, and the
44
- * second copy (`schemaFor`) had lost the two remedies — the same dead end, strictly less
45
- * useful, for no reason.
46
- */
43
+ /** The one wording for "nobody hosts this here", with both ways out. */
47
44
  const notLoaded = (entity: string) =>
48
45
  `Frond for '${entity}' is not loaded.\n` +
49
46
  ` - Add '${entity}' to --fronds flag\n` +
50
47
  ` - Or declare a remote: remotes: { ${entity}: 'http://...' }`;
51
48
 
52
- /**
53
- * Two fronds cannot claim one name — said at boot, because nothing else says it.
54
- *
55
- * A door lands on the ROOT container under `facadeKeyOf(address)`, and that key carries
56
- * no frond; a presenter lands there too. `registerValue` is a `Map.set`, so the second
57
- * frond loaded simply replaced the first and every call meant for one went to the other.
58
- * Silent in-process, and worse than silent under a split: `createRemoteRouter` guards its
59
- * index with `if (!byEntity.has(...))`, so THERE the first frond discovered wins. The same
60
- * application answered differently depending on how it was deployed.
61
- *
62
- * Refusing is the honest answer while a key cannot say which frond owns it. It is not the
63
- * last word: qualify the key and this boot can accept both. ORMs and repositories are not
64
- * checked because they are registered in the frond's own scope, where two fronds do not meet.
65
- *
66
- * A frond declared remote registers nothing locally, so it cannot collide here. Two REMOTE
67
- * fronds publishing one entity still shadow each other inside the router — a hole this
68
- * check does not reach.
69
- */
49
+ /** Two fronds cannot claim one name — said at boot, because nothing else says it. */
70
50
  function assertOneOwnerPerKey(
71
51
  fronds: { name: string; handlers: HandlerEntry[]; presenters: PresenterEntry[] }[],
72
52
  remotes: Record<string, string> | undefined,
@@ -74,10 +54,10 @@ function assertOneOwnerPerKey(
74
54
  const owner = new Map<string, string>();
75
55
 
76
56
  const claim = (key: string, frond: string, what: string) => {
77
- const held = owner.get(key);
78
- if (held !== undefined && held !== frond) {
57
+ const first = owner.get(key);
58
+ if (first !== undefined && first !== frond) {
79
59
  throw new Error(
80
- `Two fronds claim the key '${key}': '${held}' and '${frond}'.\n`
60
+ `Two fronds claim the key '${key}': '${first}' and '${frond}'.\n`
81
61
  + ` A ${what} is registered under a key that names no frond, so one would silently replace the other.\n`
82
62
  + ` - Rename one of the two classes, or\n`
83
63
  + ` - keep one of the two fronds out of this process (--fronds), or declare it in remotes:`,
@@ -133,22 +113,11 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
133
113
  log.info(`read ${fronds.length} frond(s) in ${scanMs}ms`
134
114
  + (diagnostics.length ? ` — ${diagnostics.length} thing(s) the scan could not do` : ''));
135
115
 
136
- /**
137
- * Say what could not be read, at the one line everyone already watches.
138
- *
139
- * Not a refusal: an app whose `presenters/` is unreadable still serves its
140
- * entities, and stopping the boot would trade a partial app for none. But it is
141
- * an ERROR, not a debug line — the app now serves less than its source declares,
142
- * and nothing downstream can tell that from a source that declares less.
143
- */
116
+ /** Say what could not be read, at the one line everyone already watches. */
144
117
  for (const d of blocking) log.error(`[${d.code}] ${d.message}`, d.cause);
145
118
  for (const d of diagnostics) if (d.severity === 'warning') log.warn(`[${d.code}] ${d.message}`);
146
119
 
147
- /**
148
- * An ambiguous convention is not a partial scan. Every relevant declaration was read,
149
- * but more than one executable contract can be built from it. Refuse before auth,
150
- * storage, migrations or seeds make the boot observable.
151
- */
120
+ /** An ambiguous convention is not a partial scan. */
152
121
  const invalidOperations = operationModel.resolutionDiagnostics
153
122
  .filter((diagnostic) => diagnostic.severity === 'blocking');
154
123
  if (invalidOperations.length > 0) {
@@ -180,7 +149,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
180
149
  log.info(`auth ready — mounted at ${authRuntime.basePath}`);
181
150
  }
182
151
 
183
- // Remote routing — judged at boot: declaring remotes without a transport is a config error.
152
+ // Remote routing — validated at boot: declaring remotes without a transport is a config error.
184
153
  // A remote declaration wins over local presence: `remotes: { blog: url }` IS
185
154
  // the topology statement — the frond's code may sit in fronds/**, it runs elsewhere.
186
155
  const declaredRemotes = Object.entries(options.remotes ?? {});
@@ -225,7 +194,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
225
194
 
226
195
  assertOneOwnerPerKey(fronds, options.remotes);
227
196
 
228
- // Every entity of every frond, by name — so a fact can be judged where it LANDS, and
197
+ // Every entity of every frond, by name — so a fact can be validated where it LANDS, and
229
198
  // so a `reads:` clause can name a neighbour's.
230
199
  const entityByName = fronds.schemas();
231
200
  // Which frond holds an entity — what turns "a member is remote" into a refusal that
@@ -370,6 +339,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
370
339
  hostedHere: (name) => !(options.remotes && name in options.remotes),
371
340
  storageFactory: options.storageFactory,
372
341
  sourceOf: options.sourceOf,
342
+ transacts: options.transacts,
373
343
  transacted: options.transacted,
374
344
  log: frondLog,
375
345
  },
@@ -406,25 +376,25 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
406
376
  targetScope: Container,
407
377
  facadeKey: string,
408
378
  ) => {
409
- const facade = new HandlerFacade(
410
- {
411
- handler,
412
- handlers: frond.handlers,
413
- entity,
414
- scope: targetScope,
415
- key: facadeKey,
416
- operations: operationModel.forHandler(handler),
417
- },
418
- {
419
- frond: frond.name,
420
- frondScope: scope,
421
- log: frondLog,
422
- collectors: collectorTypeNames,
423
- presenters: presenterMap,
424
- middlewaresFor: getMiddlewares,
425
- emissions,
426
- },
427
- );
379
+ if (inheritsCrud(handler.ctor) && !entity) {
380
+ // An installed Crud subject may be absent from the local scan.
381
+ frondLog.debug(`${handler.ctor.name} extends Crud() and no scanned entity is named `
382
+ + `'${subjectOf(handler.ctor, handler.address)}' — installed entity, or a missing `
383
+ + `one: no storage will be injected`);
384
+ }
385
+
386
+ const facade = new HandlerFacade(handler, targetScope, {
387
+ key: facadeKey,
388
+ frond: frond.name,
389
+ handlers: frond.handlers,
390
+ operations: operationModel.forHandler(handler),
391
+ collectors: collectorTypeNames,
392
+ presenter: presenterMap.get(handler.address),
393
+ presenterScope: scope,
394
+ middlewares: () => getMiddlewares(handler.address),
395
+ });
396
+ // Emissions use the same contracts and execution path as direct calls.
397
+ emissions.note(facade.contracts, facadeKey);
428
398
  // The terms alongside the door, under the same audience — a surface that serves
429
399
  // fewer ops describes fewer ops.
430
400
  container.registerValue(contractsKeyOf(handler.address, handler.surface), facade.contracts);
@@ -451,18 +421,18 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
451
421
  routeRegistry.register(new OperationRoute(
452
422
  'local',
453
423
  address,
454
- (call) => facade.ops[operation](call.invocation),
424
+ (call) => facade.execute(operation, call.invocation),
455
425
  ));
456
426
  }
457
427
  }
458
428
 
459
- const entry = new FacadeEntry(
429
+ const operations = facadeOperations(
460
430
  handler.surface ? localDispatcher : dispatcher,
461
431
  handler.address,
462
432
  routeRegistry.operationNames(handler.address, handler.surface),
463
433
  handler.surface,
464
434
  );
465
- container.registerValue(facadeKey, entry.operations);
435
+ container.registerValue(facadeKey, operations);
466
436
  };
467
437
 
468
438
  // A presenter is about an entity — computed fields sit on a shape — so this walks
@@ -573,17 +543,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
573
543
  // Once every door exists: what is announced here and what is listened to are both known.
574
544
  emissions.register();
575
545
 
576
- /**
577
- * The last resort, held by the container so every resolution path shares it.
578
- *
579
- * It used to live on `app.resolve` alone, which meant the runner found a remote façade
580
- * and dependency injection did not — a handler asking for a neighbour that had moved
581
- * got `is not registered` while the very same call over the wire worked. One door now.
582
- *
583
- * Surface-scoped keys ('admin:productHandler') stay local: a named surface resolves in
584
- * this container only, so fabricating one for a remote frond would answer NOT_FOUND on
585
- * everything (see Known issues).
586
- */
546
+ /** The last resort, held by the container so every resolution path shares it. */
587
547
  container.setFallback?.((name) => {
588
548
  if (!remoteRouter) return undefined;
589
549
  if (!name.endsWith('Handler') || name.includes(':')) return undefined;
@@ -591,19 +551,15 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
591
551
  // `lowerFirst` because a DEPENDENCY names the type as written — `ProductHandler`,
592
552
  // PascalCase — while a card declares `product`, so the raw strip asked the router for
593
553
  // 'Product' and every by-type dependency on a remote handler answered NOT_FOUND.
594
- return new FacadeEntry(
554
+ return facadeOperations(
595
555
  dispatcher,
596
556
  lowerFirst(name.replace(/Handler$/, '')),
597
- ).operations;
557
+ );
598
558
  });
599
559
 
600
560
  /**
601
- * Everything this app holds, let go in reverse of how it was taken: what an extension
602
- * took on last, then the container's own, then whoever handed a resource in.
603
- *
604
- * It does NOT wait for running calls — `drain()` is that, and it is a separate gesture
605
- * because waiting and releasing do not have the same owner: a test releases at once, a
606
- * host turning the ring wants the work finished first.
561
+ * Everything this app holds, let go in reverse of how it was taken: what an extension took on
562
+ * last, then the container's own, then whoever handed a resource in.
607
563
  */
608
564
  const release = async (): Promise<void> => {
609
565
  // Every level is told to close even when one refuses, and the refusals leave together —
@@ -626,13 +582,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
626
582
  }
627
583
  };
628
584
 
629
- /**
630
- * Stop taking calls, and resolve once the ones already running are done.
631
- *
632
- * Refuses on `timeoutMs` rather than resolving anyway: a drain that gives up quietly
633
- * reads exactly like a drain that succeeded, and the caller — who is about to release
634
- * a storage connection under whatever is left — is the one who must decide.
635
- */
585
+ /** Stop taking calls, and resolve once the ones already running are done. */
636
586
  const drain = async (timeoutMs?: number): Promise<void> => {
637
587
  inflight.close();
638
588
  if (timeoutMs === undefined) return inflight.whenIdle();
@@ -687,28 +637,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
687
637
  }
688
638
  };
689
639
 
690
- /**
691
- * THE membership rule, stated once — every projection reads this and nothing
692
- * else. It used to live twice, verbatim, in the REST and GraphQL adapters,
693
- * and two other readers invented their own answer.
694
- *
695
- * Naming an audience closes it. Two ways to name an entity into a surface,
696
- * in precedence order:
697
- * - `surfaces:` in frond.config.ts — when the list exists, it IS the list;
698
- * - a handler under `handlers/<surface>/` — which also restricts the façade.
699
- * `@expose` is a THIRD way and this rule does not read it: the scan sets a
700
- * boolean, read by the two adapters and by `exposedAdapters` — never here.
701
- * What neither of the two names is not served. It used to be the reverse: no
702
- * `public:categoryHandler` meant the FULL CategoryHandler rode the public
703
- * door, create/update/delete included (measured on demos/nuxt-blog).
704
- *
705
- * A named entity with no façade of its own falls back to the default one —
706
- * that is not the old widening, it is the author saying "this one, as it is".
707
- * The leak was exposure with no statement behind it.
708
- *
709
- * A surface key stays local: a doublure serves whatever the remote's own door
710
- * serves, which is the remote's business and not ours to re-audience.
711
- */
640
+ /** THE membership rule, stated once — every projection reads this and nothing else. */
712
641
  const facadeFor = (entity: string, surface?: string): Record<string, Function> | undefined => {
713
642
  if (!surface) return facadeAt(facadeKeyOf(entity), true);
714
643
 
@@ -720,18 +649,18 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
720
649
 
721
650
  const fallback = facadeAt(facadeKeyOf(entity), false);
722
651
  return fallback
723
- ? new FacadeEntry(
652
+ ? facadeOperations(
724
653
  localDispatcher,
725
654
  entity,
726
655
  routeRegistry.operationNames(entity, surface),
727
656
  surface,
728
- ).operations
657
+ )
729
658
  : undefined;
730
659
  };
731
660
 
732
661
  if (remoteRouter) {
733
662
  const remoteFacades = new Map<string, Record<string, Function>>();
734
- routeRegistry.addResolver(new RemoteRouteResolver((entity) => {
663
+ routeRegistry.addResolver(remoteRoutes((entity) => {
735
664
  const known = remoteFacades.get(entity);
736
665
  if (known) return known;
737
666
  const facade = createRemoteFacade(entity, remoteRouter, getMiddlewares);
@@ -753,13 +682,8 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
753
682
  };
754
683
 
755
684
  /**
756
- * The storage an entity is backed by — the dual of `facadeFor`, which serves its
757
- * client-facing door. Both are ways in; an entity that opens none of them still has rows.
758
- *
759
- * It resolves through the owning frond's scope, because that is where entity ORMs live:
760
- * `resolve('UserStorage')` reads the ROOT container and never finds one, so callers outside
761
- * the frond concluded there was no storage. The seed loop did exactly that, and skipped
762
- * every entity with no façade — the one case its own fallback existed for.
685
+ * The storage an entity is backed by — the dual of `facadeFor`, which serves its client-facing
686
+ * door.
763
687
  */
764
688
  const storageFor = (entity: string): unknown | undefined => {
765
689
  const owner = fronds.owner(entity);
@@ -773,14 +697,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
773
697
  }
774
698
  };
775
699
 
776
- /**
777
- * The presenter of an entity, resolved through its owning frond's scope.
778
- *
779
- * Same shape as `storageFor`, and it exists for the same reason: without it an adapter
780
- * has to spell the container key itself. `schema-graphql` did — a hand-written
781
- * `${Name}Presenter` — and a key respelled elsewhere finds nothing and says nothing
782
- * the day the convention moves, which is exactly the failure `verify.ts` refuses.
783
- */
700
+ /** The presenter of an entity, resolved through its owning frond's scope. */
784
701
  const presenterFor = (entity: string): unknown | undefined => {
785
702
  const owner = fronds.owner(entity);
786
703
  if (!owner) return undefined;
@@ -852,7 +769,23 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
852
769
 
853
770
  // The last thing the boot does, and the first thing a release undoes. An extension may
854
771
  // await here — which is what a provider needing to OPEN something could never do.
855
- await appLifecycle.up(app);
772
+ //
773
+ // A refusal here has to release what the boot took, because the caller cannot: it handed
774
+ // `onDispose` over BEFORE this line and never receives the app that would carry it back.
775
+ // Whoever opened a connection to give it to us would otherwise leak it on every failed boot.
776
+ try {
777
+ await appLifecycle.up(app);
778
+ } catch (cause) {
779
+ try {
780
+ await release();
781
+ } catch (refused) {
782
+ throw new AggregateError(
783
+ [cause, ...(refused instanceof AggregateError ? refused.errors : [refused])],
784
+ `The boot failed and could not release everything it had taken: ${(cause as Error)?.message ?? String(cause)}`,
785
+ );
786
+ }
787
+ throw cause;
788
+ }
856
789
 
857
790
  return app;
858
791
  }
package/src/boot/card.ts CHANGED
@@ -1,35 +1,14 @@
1
- /**
2
- * What an app says about ITSELF — the `rpc.discover` answer, built from the app.
3
- *
4
- * The shape is `wire/`'s: it crosses a process boundary. Building one needs an App,
5
- * which is why the function lives here and the shape does not.
6
- */
1
+ /** What an app says about ITSELF — the `rpc.discover` answer, built from the app. */
7
2
  import { Card } from '@fougere/schema';
8
3
  import type { App } from './types.js';
9
4
  import { factsAnnouncedBy } from '../emit.js';
10
- import type { InvocationContext } from '../contract/Invocation.js';
5
+ import type { InvocationContext } from '../wire/Invocation.js';
11
6
  import { facadeKeyOf, contractsKeyOf, type CardOp, type IdentityCard } from '../wire/call.js';
12
7
  import type { OperationContract } from '../wire/operation.js';
13
8
 
14
9
  type AnyFacade = Record<string, (invocation?: InvocationContext) => Promise<unknown>>;
15
10
 
16
- /**
17
- * Serialize what the app hosts, for one audience. Served on `rpc.discover`,
18
- * cached by callers.
19
- *
20
- * Hosting means answering: an entity with no façade declares no operation, so
21
- * it is not among the DOORS — publishing its shape would hand an anonymous caller
22
- * the structure of tables it can never reach (the auth tables, typically), and
23
- * `fougere sync` would rebuild a schema with nothing to call on it.
24
- *
25
- * `facts` is the one thing that shape-without-a-door rule does not cover, and the
26
- * reason is the opposite of a leak: an entity nobody exposed is silent, whereas a
27
- * fact was explicitly declared to leave.
28
- *
29
- * `surface` makes that sentence audience-aware rather than app-wide: a door
30
- * answers with what IT serves. Nothing falls back to the full façade — under a
31
- * named surface, an entity with no façade of its own is simply not there.
32
- */
11
+ /** Serialize what the app hosts, for one audience. */
33
12
  export function identityCardOf(app: App, surface?: string): IdentityCard {
34
13
  const declared = app.fronds.schemas();
35
14
 
@@ -59,15 +38,7 @@ export function identityCardOf(app: App, surface?: string): IdentityCard {
59
38
  ...(entity ? { schema: Card.fromSchema(entity.entityClass, address).descriptor } : {}),
60
39
  }];
61
40
  }),
62
- /**
63
- * What leaves on its own — the same list on every surface, deliberately.
64
- *
65
- * A door has an audience; a fact does not. `Emit<T>` names a subject and *the
66
- * number of readers is not the emitter's business* (`emit.ts`), so narrowing this
67
- * by `surface` would invent an axis the primitive refuses. The consequence is
68
- * stated rather than hidden: a fact's SHAPE is readable by anyone who can read the
69
- * card at all. What must not be published must not be announced.
70
- */
41
+ /** What leaves on its own — the same list on every surface, deliberately. */
71
42
  facts: factsAnnouncedBy(frond.handlers).map((name) => {
72
43
  const entityClass = declared.get(name);
73
44
  return { name, ...(entityClass ? { schema: Card.fromSchema(entityClass, name).descriptor } : {}) };