@fougere/core 0.5.0-alpha.1 → 0.7.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (519) hide show
  1. package/README.md +1 -1
  2. package/dist/boot/Emissions.d.ts +14 -91
  3. package/dist/boot/Emissions.d.ts.map +1 -1
  4. package/dist/boot/Emissions.js +21 -118
  5. package/dist/boot/Emissions.js.map +1 -1
  6. package/dist/boot/ambient-port.d.ts +3 -24
  7. package/dist/boot/ambient-port.d.ts.map +1 -1
  8. package/dist/boot/ambient.als.d.ts.map +1 -1
  9. package/dist/boot/ambient.als.js +7 -12
  10. package/dist/boot/ambient.als.js.map +1 -1
  11. package/dist/boot/ambient.queue.d.ts +2 -5
  12. package/dist/boot/ambient.queue.d.ts.map +1 -1
  13. package/dist/boot/ambient.queue.js.map +1 -1
  14. package/dist/boot/apply.d.ts +1 -13
  15. package/dist/boot/apply.d.ts.map +1 -1
  16. package/dist/boot/apply.js +3 -15
  17. package/dist/boot/apply.js.map +1 -1
  18. package/dist/boot/auth.d.ts +6 -16
  19. package/dist/boot/auth.d.ts.map +1 -1
  20. package/dist/boot/boot.d.ts +5 -18
  21. package/dist/boot/boot.d.ts.map +1 -1
  22. package/dist/boot/boot.js +4 -11
  23. package/dist/boot/boot.js.map +1 -1
  24. package/dist/boot/bootstrap.d.ts.map +1 -1
  25. package/dist/boot/bootstrap.js +106 -163
  26. package/dist/boot/bootstrap.js.map +1 -1
  27. package/dist/boot/card.d.ts +5 -0
  28. package/dist/boot/card.d.ts.map +1 -0
  29. package/dist/boot/card.js +71 -0
  30. package/dist/boot/card.js.map +1 -0
  31. package/dist/boot/frame.d.ts +8 -32
  32. package/dist/boot/frame.d.ts.map +1 -1
  33. package/dist/boot/frame.js +23 -57
  34. package/dist/boot/frame.js.map +1 -1
  35. package/dist/boot/hosted.d.ts +3 -19
  36. package/dist/boot/hosted.d.ts.map +1 -1
  37. package/dist/boot/hosted.js +12 -17
  38. package/dist/boot/hosted.js.map +1 -1
  39. package/dist/boot/ownership.d.ts +5 -36
  40. package/dist/boot/ownership.d.ts.map +1 -1
  41. package/dist/boot/ownership.js +9 -49
  42. package/dist/boot/ownership.js.map +1 -1
  43. package/dist/boot/ports.d.ts +2 -15
  44. package/dist/boot/ports.d.ts.map +1 -1
  45. package/dist/boot/ports.js +1 -14
  46. package/dist/boot/ports.js.map +1 -1
  47. package/dist/boot/remote.d.ts +5 -38
  48. package/dist/boot/remote.d.ts.map +1 -1
  49. package/dist/boot/remote.js +8 -41
  50. package/dist/boot/remote.js.map +1 -1
  51. package/dist/boot/runner.d.ts +11 -0
  52. package/dist/boot/runner.d.ts.map +1 -0
  53. package/dist/boot/runner.js +13 -0
  54. package/dist/boot/runner.js.map +1 -0
  55. package/dist/boot/seed.d.ts +5 -32
  56. package/dist/boot/seed.d.ts.map +1 -1
  57. package/dist/boot/seed.js +10 -41
  58. package/dist/boot/seed.js.map +1 -1
  59. package/dist/boot/statement-drift.d.ts +4 -22
  60. package/dist/boot/statement-drift.d.ts.map +1 -1
  61. package/dist/boot/statement-drift.js +4 -9
  62. package/dist/boot/statement-drift.js.map +1 -1
  63. package/dist/boot/together.d.ts +8 -12
  64. package/dist/boot/together.d.ts.map +1 -1
  65. package/dist/boot/together.js +28 -65
  66. package/dist/boot/together.js.map +1 -1
  67. package/dist/boot/types.d.ts +36 -180
  68. package/dist/boot/types.d.ts.map +1 -1
  69. package/dist/builtin/config.d.ts +7 -0
  70. package/dist/builtin/config.d.ts.map +1 -0
  71. package/dist/builtin/config.js +15 -0
  72. package/dist/builtin/config.js.map +1 -0
  73. package/dist/{builtins → builtin}/logger.d.ts +4 -25
  74. package/dist/builtin/logger.d.ts.map +1 -0
  75. package/dist/{builtins → builtin}/logger.js +5 -32
  76. package/dist/builtin/logger.js.map +1 -0
  77. package/dist/config-loader.d.ts +9 -67
  78. package/dist/config-loader.d.ts.map +1 -1
  79. package/dist/config-loader.js +5 -18
  80. package/dist/config-loader.js.map +1 -1
  81. package/dist/contract.d.ts +13 -31
  82. package/dist/contract.d.ts.map +1 -1
  83. package/dist/contract.js +10 -26
  84. package/dist/contract.js.map +1 -1
  85. package/dist/crypto/encoding.d.ts +2 -15
  86. package/dist/crypto/encoding.d.ts.map +1 -1
  87. package/dist/crypto/encoding.js +2 -15
  88. package/dist/crypto/encoding.js.map +1 -1
  89. package/dist/crypto/node.d.ts.map +1 -1
  90. package/dist/crypto/node.js +1 -7
  91. package/dist/crypto/node.js.map +1 -1
  92. package/dist/crypto/port.d.ts +2 -18
  93. package/dist/crypto/port.d.ts.map +1 -1
  94. package/dist/crypto/port.js +1 -17
  95. package/dist/crypto/port.js.map +1 -1
  96. package/dist/crypto/webcrypto.d.ts.map +1 -1
  97. package/dist/crypto/webcrypto.js +1 -12
  98. package/dist/crypto/webcrypto.js.map +1 -1
  99. package/dist/declare.d.ts +41 -0
  100. package/dist/declare.d.ts.map +1 -0
  101. package/dist/{scan/declare.js → declare.js} +6 -31
  102. package/dist/declare.js.map +1 -0
  103. package/dist/define.d.ts +2 -3
  104. package/dist/define.d.ts.map +1 -1
  105. package/dist/define.js +2 -3
  106. package/dist/define.js.map +1 -1
  107. package/dist/descriptor/Fronds.d.ts +19 -0
  108. package/dist/descriptor/Fronds.d.ts.map +1 -0
  109. package/dist/descriptor/Fronds.js +40 -0
  110. package/dist/descriptor/Fronds.js.map +1 -0
  111. package/dist/descriptor/frond.d.ts +135 -0
  112. package/dist/descriptor/frond.d.ts.map +1 -0
  113. package/dist/{scan → descriptor}/frond.js.map +1 -1
  114. package/dist/dispatch/ArgumentResolver.d.ts +6 -3
  115. package/dist/dispatch/ArgumentResolver.d.ts.map +1 -1
  116. package/dist/dispatch/ArgumentResolver.js +48 -3
  117. package/dist/dispatch/ArgumentResolver.js.map +1 -1
  118. package/dist/dispatch/DispatchEvent.d.ts +2 -2
  119. package/dist/dispatch/DispatchEvent.d.ts.map +1 -1
  120. package/dist/dispatch/DispatchLifecycle.d.ts +1 -7
  121. package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -1
  122. package/dist/dispatch/DispatchLifecycle.js +1 -7
  123. package/dist/dispatch/DispatchLifecycle.js.map +1 -1
  124. package/dist/dispatch/DispatchPort.d.ts +1 -1
  125. package/dist/dispatch/DispatchPort.d.ts.map +1 -1
  126. package/dist/dispatch/Dispatcher.d.ts +1 -1
  127. package/dist/dispatch/Dispatcher.d.ts.map +1 -1
  128. package/dist/dispatch/Dispatcher.js +2 -2
  129. package/dist/dispatch/Dispatcher.js.map +1 -1
  130. package/dist/{boot → dispatch}/HandlerFacade.d.ts +25 -38
  131. package/dist/dispatch/HandlerFacade.d.ts.map +1 -0
  132. package/dist/{boot → dispatch}/HandlerFacade.js +65 -74
  133. package/dist/dispatch/HandlerFacade.js.map +1 -0
  134. package/dist/dispatch/LocalRoutePolicy.d.ts +1 -1
  135. package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -1
  136. package/dist/dispatch/LocalRoutePolicy.js +4 -4
  137. package/dist/dispatch/LocalRoutePolicy.js.map +1 -1
  138. package/dist/dispatch/OperationRoute.d.ts +2 -2
  139. package/dist/dispatch/OperationRoute.d.ts.map +1 -1
  140. package/dist/dispatch/OutputView.d.ts +3 -2
  141. package/dist/dispatch/OutputView.d.ts.map +1 -1
  142. package/dist/dispatch/OutputView.js +19 -1
  143. package/dist/dispatch/OutputView.js.map +1 -1
  144. package/dist/dispatch/Route.d.ts +2 -3
  145. package/dist/dispatch/Route.d.ts.map +1 -1
  146. package/dist/dispatch/RoutePolicy.d.ts +1 -1
  147. package/dist/dispatch/RoutePolicy.d.ts.map +1 -1
  148. package/dist/dispatch/RouteRegistry.d.ts +1 -1
  149. package/dist/dispatch/RouteRegistry.d.ts.map +1 -1
  150. package/dist/dispatch/RouteRegistry.js +2 -2
  151. package/dist/dispatch/RouteRegistry.js.map +1 -1
  152. package/dist/dispatch/RouteResolver.d.ts +2 -4
  153. package/dist/dispatch/RouteResolver.d.ts.map +1 -1
  154. package/dist/dispatch/StorageGuard.d.ts +9 -8
  155. package/dist/dispatch/StorageGuard.d.ts.map +1 -1
  156. package/dist/dispatch/StorageGuard.js +66 -23
  157. package/dist/dispatch/StorageGuard.js.map +1 -1
  158. package/dist/dispatch/presenterArguments.d.ts +7 -0
  159. package/dist/dispatch/presenterArguments.d.ts.map +1 -0
  160. package/dist/dispatch/presenterArguments.js +12 -0
  161. package/dist/dispatch/presenterArguments.js.map +1 -0
  162. package/dist/dispatch/remoteRoutes.d.ts +7 -0
  163. package/dist/dispatch/remoteRoutes.d.ts.map +1 -0
  164. package/dist/dispatch/{RemoteRouteResolver.js → remoteRoutes.js} +6 -10
  165. package/dist/dispatch/remoteRoutes.js.map +1 -0
  166. package/dist/dispatch/routeNotFound.d.ts +9 -0
  167. package/dist/dispatch/routeNotFound.d.ts.map +1 -0
  168. package/dist/dispatch/routeNotFound.js +21 -0
  169. package/dist/dispatch/routeNotFound.js.map +1 -0
  170. package/dist/dispatch/validateInput.d.ts +5 -0
  171. package/dist/dispatch/validateInput.d.ts.map +1 -0
  172. package/dist/dispatch/validateInput.js +20 -0
  173. package/dist/dispatch/validateInput.js.map +1 -0
  174. package/dist/effective-operation.d.ts +6 -3
  175. package/dist/effective-operation.d.ts.map +1 -1
  176. package/dist/effective-operation.js +49 -27
  177. package/dist/effective-operation.js.map +1 -1
  178. package/dist/emit.d.ts +4 -42
  179. package/dist/emit.d.ts.map +1 -1
  180. package/dist/emit.js +3 -39
  181. package/dist/emit.js.map +1 -1
  182. package/dist/entry/facade.d.ts +8 -0
  183. package/dist/entry/facade.d.ts.map +1 -0
  184. package/dist/entry/facade.js +28 -0
  185. package/dist/entry/facade.js.map +1 -0
  186. package/dist/entry/transport.d.ts +5 -0
  187. package/dist/entry/transport.d.ts.map +1 -0
  188. package/dist/entry/transport.js +11 -0
  189. package/dist/entry/transport.js.map +1 -0
  190. package/dist/frond-config.d.ts +8 -71
  191. package/dist/frond-config.d.ts.map +1 -1
  192. package/dist/frond-config.js +1 -9
  193. package/dist/frond-config.js.map +1 -1
  194. package/dist/graph.d.ts +1 -1
  195. package/dist/graph.d.ts.map +1 -1
  196. package/dist/identity-keys.d.ts +2 -5
  197. package/dist/identity-keys.d.ts.map +1 -1
  198. package/dist/identity-keys.js +3 -16
  199. package/dist/identity-keys.js.map +1 -1
  200. package/dist/identity.d.ts +4 -30
  201. package/dist/identity.d.ts.map +1 -1
  202. package/dist/identity.js +11 -73
  203. package/dist/identity.js.map +1 -1
  204. package/dist/imports.d.ts +2 -8
  205. package/dist/imports.d.ts.map +1 -1
  206. package/dist/imports.js +1 -7
  207. package/dist/imports.js.map +1 -1
  208. package/dist/index.d.ts +28 -30
  209. package/dist/index.d.ts.map +1 -1
  210. package/dist/index.js +17 -22
  211. package/dist/index.js.map +1 -1
  212. package/dist/loader.d.ts +1 -8
  213. package/dist/loader.d.ts.map +1 -1
  214. package/dist/loader.js +1 -8
  215. package/dist/loader.js.map +1 -1
  216. package/dist/node.d.ts +2 -11
  217. package/dist/node.d.ts.map +1 -1
  218. package/dist/node.js +2 -11
  219. package/dist/node.js.map +1 -1
  220. package/dist/prefab/collector.d.ts +1 -22
  221. package/dist/prefab/collector.d.ts.map +1 -1
  222. package/dist/prefab/collector.js +1 -22
  223. package/dist/prefab/collector.js.map +1 -1
  224. package/dist/prefab/crud.d.ts +19 -35
  225. package/dist/prefab/crud.d.ts.map +1 -1
  226. package/dist/prefab/crud.js +39 -66
  227. package/dist/prefab/crud.js.map +1 -1
  228. package/dist/prefab/mirror.d.ts +5 -27
  229. package/dist/prefab/mirror.d.ts.map +1 -1
  230. package/dist/prefab/mirror.js +6 -24
  231. package/dist/prefab/mirror.js.map +1 -1
  232. package/dist/prefab/prefab.d.ts +1 -7
  233. package/dist/prefab/prefab.d.ts.map +1 -1
  234. package/dist/prefab/prefab.js +1 -7
  235. package/dist/prefab/prefab.js.map +1 -1
  236. package/dist/prefab/presenter.d.ts +2 -36
  237. package/dist/prefab/presenter.d.ts.map +1 -1
  238. package/dist/prefab/presenter.js +2 -36
  239. package/dist/prefab/presenter.js.map +1 -1
  240. package/dist/prefab/repository.d.ts +12 -80
  241. package/dist/prefab/repository.d.ts.map +1 -1
  242. package/dist/prefab/repository.js +22 -35
  243. package/dist/prefab/repository.js.map +1 -1
  244. package/dist/scan/adapters.d.ts +3 -0
  245. package/dist/scan/adapters.d.ts.map +1 -0
  246. package/dist/scan/adapters.js +25 -0
  247. package/dist/scan/adapters.js.map +1 -0
  248. package/dist/scan/bundling.d.ts +1 -12
  249. package/dist/scan/bundling.d.ts.map +1 -1
  250. package/dist/scan/bundling.js +1 -12
  251. package/dist/scan/bundling.js.map +1 -1
  252. package/dist/scan/conventions.d.ts +6 -40
  253. package/dist/scan/conventions.d.ts.map +1 -1
  254. package/dist/scan/conventions.js +5 -34
  255. package/dist/scan/conventions.js.map +1 -1
  256. package/dist/scan/emit.d.ts +2 -6
  257. package/dist/scan/emit.d.ts.map +1 -1
  258. package/dist/scan/emit.js +5 -39
  259. package/dist/scan/emit.js.map +1 -1
  260. package/dist/scan/handler-parser.d.ts +9 -76
  261. package/dist/scan/handler-parser.d.ts.map +1 -1
  262. package/dist/scan/handler-parser.js +28 -85
  263. package/dist/scan/handler-parser.js.map +1 -1
  264. package/dist/scan/result.d.ts +28 -0
  265. package/dist/scan/result.d.ts.map +1 -0
  266. package/dist/scan/result.js +2 -0
  267. package/dist/scan/result.js.map +1 -0
  268. package/dist/scan/scanner.d.ts +3 -28
  269. package/dist/scan/scanner.d.ts.map +1 -1
  270. package/dist/scan/scanner.js +36 -135
  271. package/dist/scan/scanner.js.map +1 -1
  272. package/dist/scan/statement.d.ts +1 -1
  273. package/dist/scan/statement.d.ts.map +1 -1
  274. package/dist/scan/statement.js +4 -30
  275. package/dist/scan/statement.js.map +1 -1
  276. package/dist/source.d.ts +41 -0
  277. package/dist/source.d.ts.map +1 -0
  278. package/dist/source.js +10 -0
  279. package/dist/source.js.map +1 -0
  280. package/dist/storage.d.ts +92 -0
  281. package/dist/storage.d.ts.map +1 -0
  282. package/dist/storage.js +50 -0
  283. package/dist/storage.js.map +1 -0
  284. package/dist/store.d.ts +18 -0
  285. package/dist/store.d.ts.map +1 -0
  286. package/dist/store.js +146 -0
  287. package/dist/store.js.map +1 -0
  288. package/dist/verify.d.ts +6 -39
  289. package/dist/verify.d.ts.map +1 -1
  290. package/dist/verify.js +19 -39
  291. package/dist/verify.js.map +1 -1
  292. package/dist/wire/CallLog.d.ts +32 -0
  293. package/dist/wire/CallLog.d.ts.map +1 -0
  294. package/dist/{contract → wire}/CallLog.js.map +1 -1
  295. package/dist/wire/Invocation.d.ts +32 -0
  296. package/dist/wire/Invocation.d.ts.map +1 -0
  297. package/dist/wire/Invocation.js +66 -0
  298. package/dist/wire/Invocation.js.map +1 -0
  299. package/dist/wire/RouteAddress.d.ts +24 -0
  300. package/dist/wire/RouteAddress.d.ts.map +1 -0
  301. package/dist/{contract → wire}/RouteAddress.js +7 -0
  302. package/dist/wire/RouteAddress.js.map +1 -0
  303. package/dist/wire/binding.d.ts +36 -0
  304. package/dist/wire/binding.d.ts.map +1 -0
  305. package/dist/{boot → wire}/binding.js +5 -62
  306. package/dist/wire/binding.js.map +1 -0
  307. package/dist/wire/call.d.ts +25 -172
  308. package/dist/wire/call.d.ts.map +1 -1
  309. package/dist/wire/call.js +15 -166
  310. package/dist/wire/call.js.map +1 -1
  311. package/dist/wire/drift.d.ts +3 -28
  312. package/dist/wire/drift.d.ts.map +1 -1
  313. package/dist/wire/drift.js +4 -23
  314. package/dist/wire/drift.js.map +1 -1
  315. package/dist/wire/errors.d.ts +4 -24
  316. package/dist/wire/errors.d.ts.map +1 -1
  317. package/dist/wire/errors.js +4 -24
  318. package/dist/wire/errors.js.map +1 -1
  319. package/dist/wire/http-error.d.ts +2 -13
  320. package/dist/wire/http-error.d.ts.map +1 -1
  321. package/dist/wire/http-error.js +5 -19
  322. package/dist/wire/http-error.js.map +1 -1
  323. package/dist/wire/loggerMiddleware.d.ts +2 -8
  324. package/dist/wire/loggerMiddleware.d.ts.map +1 -1
  325. package/dist/wire/loggerMiddleware.js +1 -7
  326. package/dist/wire/loggerMiddleware.js.map +1 -1
  327. package/dist/wire/middleware.d.ts +3 -7
  328. package/dist/wire/middleware.d.ts.map +1 -1
  329. package/dist/wire/middleware.js +1 -5
  330. package/dist/wire/middleware.js.map +1 -1
  331. package/dist/wire/operation.d.ts +12 -74
  332. package/dist/wire/operation.d.ts.map +1 -1
  333. package/dist/wire/operation.js +4 -66
  334. package/dist/wire/operation.js.map +1 -1
  335. package/dist/wire/signature.d.ts +37 -0
  336. package/dist/wire/signature.d.ts.map +1 -0
  337. package/dist/wire/signature.js +2 -0
  338. package/dist/wire/signature.js.map +1 -0
  339. package/package.json +3 -3
  340. package/src/boot/Emissions.ts +22 -119
  341. package/src/boot/ambient-port.ts +3 -24
  342. package/src/boot/ambient.als.ts +7 -12
  343. package/src/boot/ambient.queue.ts +2 -5
  344. package/src/boot/apply.ts +3 -15
  345. package/src/boot/auth.ts +6 -16
  346. package/src/boot/boot.ts +8 -23
  347. package/src/boot/bootstrap.ts +117 -173
  348. package/src/boot/card.ts +84 -0
  349. package/src/boot/frame.ts +31 -65
  350. package/src/boot/hosted.ts +15 -40
  351. package/src/boot/ownership.ts +14 -49
  352. package/src/boot/ports.ts +2 -15
  353. package/src/boot/remote.ts +11 -58
  354. package/src/boot/runner.ts +17 -0
  355. package/src/boot/seed.ts +11 -42
  356. package/src/boot/statement-drift.ts +10 -28
  357. package/src/boot/together.ts +38 -72
  358. package/src/boot/types.ts +36 -180
  359. package/src/{builtins → builtin}/config.ts +1 -7
  360. package/src/{builtins → builtin}/logger.ts +6 -39
  361. package/src/config-loader.ts +12 -71
  362. package/src/contract.ts +15 -39
  363. package/src/crypto/encoding.ts +2 -15
  364. package/src/crypto/node.ts +1 -7
  365. package/src/crypto/port.ts +2 -18
  366. package/src/crypto/webcrypto.ts +1 -12
  367. package/src/{scan/declare.ts → declare.ts} +11 -42
  368. package/src/define.ts +2 -3
  369. package/src/descriptor/Fronds.ts +47 -0
  370. package/src/descriptor/frond.ts +145 -0
  371. package/src/dispatch/ArgumentResolver.ts +54 -8
  372. package/src/dispatch/DispatchEvent.ts +2 -2
  373. package/src/dispatch/DispatchLifecycle.ts +1 -7
  374. package/src/dispatch/DispatchPort.ts +1 -1
  375. package/src/dispatch/Dispatcher.ts +3 -3
  376. package/src/dispatch/HandlerFacade.ts +231 -0
  377. package/src/dispatch/LocalRoutePolicy.ts +4 -4
  378. package/src/dispatch/OperationRoute.ts +2 -2
  379. package/src/dispatch/OutputView.ts +24 -2
  380. package/src/dispatch/Route.ts +2 -4
  381. package/src/dispatch/RoutePolicy.ts +1 -1
  382. package/src/dispatch/RouteRegistry.ts +2 -2
  383. package/src/dispatch/RouteResolver.ts +2 -4
  384. package/src/dispatch/StorageGuard.ts +75 -23
  385. package/src/dispatch/presenterArguments.ts +25 -0
  386. package/src/dispatch/{RemoteRouteResolver.ts → remoteRoutes.ts} +7 -9
  387. package/src/dispatch/routeNotFound.ts +33 -0
  388. package/src/dispatch/validateInput.ts +28 -0
  389. package/src/effective-operation.ts +60 -37
  390. package/src/emit.ts +5 -63
  391. package/src/entry/facade.ts +44 -0
  392. package/src/entry/transport.ts +16 -0
  393. package/src/frond-config.ts +8 -71
  394. package/src/graph.ts +1 -1
  395. package/src/identity-keys.ts +3 -16
  396. package/src/identity.ts +12 -80
  397. package/src/imports.ts +3 -32
  398. package/src/index.ts +28 -33
  399. package/src/loader.ts +2 -16
  400. package/src/node.ts +2 -11
  401. package/src/prefab/collector.ts +1 -22
  402. package/src/prefab/crud.ts +51 -90
  403. package/src/prefab/mirror.ts +9 -49
  404. package/src/prefab/prefab.ts +2 -21
  405. package/src/prefab/presenter.ts +2 -36
  406. package/src/prefab/repository.ts +32 -108
  407. package/src/scan/adapters.ts +32 -0
  408. package/src/scan/bundling.ts +1 -12
  409. package/src/scan/conventions.ts +6 -40
  410. package/src/scan/emit.ts +7 -43
  411. package/src/scan/handler-parser.ts +41 -163
  412. package/src/scan/result.ts +29 -0
  413. package/src/scan/scanner.ts +40 -138
  414. package/src/scan/statement.ts +6 -31
  415. package/src/source.ts +44 -0
  416. package/src/storage.ts +141 -0
  417. package/src/store.ts +152 -0
  418. package/src/verify.ts +19 -60
  419. package/src/wire/CallLog.ts +30 -0
  420. package/src/{contract → wire}/Invocation.ts +24 -17
  421. package/src/{contract → wire}/RouteAddress.ts +10 -0
  422. package/src/wire/binding.ts +102 -0
  423. package/src/wire/call.ts +30 -261
  424. package/src/wire/drift.ts +5 -30
  425. package/src/wire/errors.ts +4 -24
  426. package/src/wire/http-error.ts +5 -19
  427. package/src/wire/loggerMiddleware.ts +2 -8
  428. package/src/wire/middleware.ts +3 -7
  429. package/src/wire/operation.ts +13 -110
  430. package/src/wire/signature.ts +38 -0
  431. package/dist/boot/HandlerFacade.d.ts.map +0 -1
  432. package/dist/boot/HandlerFacade.js.map +0 -1
  433. package/dist/boot/binding.d.ts +0 -60
  434. package/dist/boot/binding.d.ts.map +0 -1
  435. package/dist/boot/binding.js.map +0 -1
  436. package/dist/builtins/config.d.ts +0 -13
  437. package/dist/builtins/config.d.ts.map +0 -1
  438. package/dist/builtins/config.js +0 -21
  439. package/dist/builtins/config.js.map +0 -1
  440. package/dist/builtins/logger.d.ts.map +0 -1
  441. package/dist/builtins/logger.js.map +0 -1
  442. package/dist/contract/Call.d.ts +0 -10
  443. package/dist/contract/Call.d.ts.map +0 -1
  444. package/dist/contract/Call.js +0 -15
  445. package/dist/contract/Call.js.map +0 -1
  446. package/dist/contract/CallLog.d.ts +0 -57
  447. package/dist/contract/CallLog.d.ts.map +0 -1
  448. package/dist/contract/Invocation.d.ts +0 -27
  449. package/dist/contract/Invocation.d.ts.map +0 -1
  450. package/dist/contract/Invocation.js +0 -59
  451. package/dist/contract/Invocation.js.map +0 -1
  452. package/dist/contract/RouteAddress.d.ts +0 -17
  453. package/dist/contract/RouteAddress.d.ts.map +0 -1
  454. package/dist/contract/RouteAddress.js.map +0 -1
  455. package/dist/dispatch/InputValidator.d.ts +0 -7
  456. package/dist/dispatch/InputValidator.d.ts.map +0 -1
  457. package/dist/dispatch/InputValidator.js +0 -22
  458. package/dist/dispatch/InputValidator.js.map +0 -1
  459. package/dist/dispatch/OperationExecutor.d.ts +0 -25
  460. package/dist/dispatch/OperationExecutor.d.ts.map +0 -1
  461. package/dist/dispatch/OperationExecutor.js +0 -32
  462. package/dist/dispatch/OperationExecutor.js.map +0 -1
  463. package/dist/dispatch/OutputProjector.d.ts +0 -12
  464. package/dist/dispatch/OutputProjector.d.ts.map +0 -1
  465. package/dist/dispatch/OutputProjector.js +0 -30
  466. package/dist/dispatch/OutputProjector.js.map +0 -1
  467. package/dist/dispatch/PresenterArgumentResolver.d.ts +0 -12
  468. package/dist/dispatch/PresenterArgumentResolver.d.ts.map +0 -1
  469. package/dist/dispatch/PresenterArgumentResolver.js +0 -20
  470. package/dist/dispatch/PresenterArgumentResolver.js.map +0 -1
  471. package/dist/dispatch/RemoteRouteResolver.d.ts +0 -13
  472. package/dist/dispatch/RemoteRouteResolver.d.ts.map +0 -1
  473. package/dist/dispatch/RemoteRouteResolver.js.map +0 -1
  474. package/dist/dispatch/RouteNotFoundError.d.ts +0 -10
  475. package/dist/dispatch/RouteNotFoundError.d.ts.map +0 -1
  476. package/dist/dispatch/RouteNotFoundError.js +0 -24
  477. package/dist/dispatch/RouteNotFoundError.js.map +0 -1
  478. package/dist/entry/DynamicFacade.d.ts +0 -10
  479. package/dist/entry/DynamicFacade.d.ts.map +0 -1
  480. package/dist/entry/DynamicFacade.js +0 -27
  481. package/dist/entry/DynamicFacade.js.map +0 -1
  482. package/dist/entry/FacadeEntry.d.ts +0 -11
  483. package/dist/entry/FacadeEntry.d.ts.map +0 -1
  484. package/dist/entry/FacadeEntry.js +0 -26
  485. package/dist/entry/FacadeEntry.js.map +0 -1
  486. package/dist/entry/TransportEntry.d.ts +0 -13
  487. package/dist/entry/TransportEntry.d.ts.map +0 -1
  488. package/dist/entry/TransportEntry.js +0 -24
  489. package/dist/entry/TransportEntry.js.map +0 -1
  490. package/dist/orm.d.ts +0 -207
  491. package/dist/orm.d.ts.map +0 -1
  492. package/dist/orm.js +0 -66
  493. package/dist/orm.js.map +0 -1
  494. package/dist/scan/Fronds.d.ts +0 -45
  495. package/dist/scan/Fronds.d.ts.map +0 -1
  496. package/dist/scan/Fronds.js +0 -66
  497. package/dist/scan/Fronds.js.map +0 -1
  498. package/dist/scan/declare.d.ts +0 -71
  499. package/dist/scan/declare.d.ts.map +0 -1
  500. package/dist/scan/declare.js.map +0 -1
  501. package/dist/scan/frond.d.ts +0 -224
  502. package/dist/scan/frond.d.ts.map +0 -1
  503. package/src/boot/HandlerFacade.ts +0 -242
  504. package/src/boot/binding.ts +0 -182
  505. package/src/contract/Call.ts +0 -18
  506. package/src/contract/CallLog.ts +0 -55
  507. package/src/dispatch/InputValidator.ts +0 -28
  508. package/src/dispatch/OperationExecutor.ts +0 -60
  509. package/src/dispatch/OutputProjector.ts +0 -32
  510. package/src/dispatch/PresenterArgumentResolver.ts +0 -25
  511. package/src/dispatch/RouteNotFoundError.ts +0 -29
  512. package/src/entry/DynamicFacade.ts +0 -28
  513. package/src/entry/FacadeEntry.ts +0 -32
  514. package/src/entry/TransportEntry.ts +0 -30
  515. package/src/orm.ts +0 -252
  516. package/src/scan/Fronds.ts +0 -73
  517. package/src/scan/frond.ts +0 -235
  518. /package/dist/{scan → descriptor}/frond.js +0 -0
  519. /package/dist/{contract → wire}/CallLog.js +0 -0
@@ -1,28 +0,0 @@
1
- type Operation = (...args: any[]) => unknown;
2
-
3
- /** Facade for a remote contract whose operation names are not known before discovery. */
4
- export class DynamicFacade {
5
- readonly operations: Record<string, Operation>;
6
-
7
- constructor(private readonly operation: (name: string) => Operation) {
8
- this.operations = new Proxy({}, {
9
- get: (_target, name) => this.isOperationName(name) ? this.operation(name) : undefined,
10
- has: (_target, name) => this.isOperationName(name),
11
- getOwnPropertyDescriptor: (_target, name) => this.isOperationName(name)
12
- ? {
13
- value: this.operation(name),
14
- writable: false,
15
- enumerable: true,
16
- configurable: true,
17
- }
18
- : undefined,
19
- });
20
- }
21
-
22
- private isOperationName(name: string | symbol): name is string {
23
- return typeof name === 'string'
24
- && name !== 'then'
25
- && name !== 'toJSON'
26
- && !Object.hasOwn(Object.prototype, name);
27
- }
28
- }
@@ -1,32 +0,0 @@
1
- import { Call } from '../contract/Call.js';
2
- import type { InvocationInput } from '../contract/Invocation.js';
3
- import { RouteAddress } from '../contract/RouteAddress.js';
4
- import type { DispatchPort } from '../dispatch/DispatchPort.js';
5
- import { DynamicFacade } from './DynamicFacade.js';
6
-
7
- /** Object-shaped entry that turns facade method calls into canonical dispatches. */
8
- export class FacadeEntry {
9
- readonly operations: Record<string, Function>;
10
-
11
- constructor(
12
- private readonly dispatcher: DispatchPort,
13
- private readonly entity: string,
14
- operationNames?: Iterable<string>,
15
- private readonly surface?: string,
16
- ) {
17
- this.operations = operationNames
18
- ? Object.fromEntries([...operationNames].map((name) => [name, this.operation(name)]))
19
- : new DynamicFacade((name) => this.operation(name)).operations;
20
- }
21
-
22
- private operation(name: string): (invocation?: InvocationInput) => Promise<unknown> {
23
- return (invocation) => this.dispatcher.dispatch(new Call(
24
- new RouteAddress({
25
- entity: this.entity,
26
- operation: name,
27
- ...(this.surface !== undefined ? { surface: this.surface } : {}),
28
- }),
29
- invocation,
30
- ));
31
- }
32
- }
@@ -1,30 +0,0 @@
1
- import { Call } from '../contract/Call.js';
2
- import { RouteAddress } from '../contract/RouteAddress.js';
3
- import type { DispatchPort } from '../dispatch/DispatchPort.js';
4
- import type { FrondCall, Transport } from '../wire/call.js';
5
- import type { InvocationContext } from '../contract/Invocation.js';
6
-
7
- /** Object entry for the historical transport contract. */
8
- export class TransportEntry {
9
- constructor(
10
- private readonly dispatcher: DispatchPort,
11
- private readonly surface?: string,
12
- ) {}
13
-
14
- receive(legacy: FrondCall, invocation: InvocationContext): Promise<unknown> {
15
- return this.dispatcher.dispatch(new Call(
16
- new RouteAddress({
17
- entity: legacy.entity,
18
- operation: legacy.op,
19
- ...(this.surface !== undefined ? { surface: this.surface } : {}),
20
- }),
21
- invocation,
22
- ));
23
- }
24
- }
25
-
26
- /** Adapt the historical transport signature to the canonical dispatch port. */
27
- export function createTransportEntry(dispatcher: DispatchPort, surface?: string): Transport {
28
- const entry = new TransportEntry(dispatcher, surface);
29
- return entry.receive.bind(entry);
30
- }
package/src/orm.ts DELETED
@@ -1,252 +0,0 @@
1
- import { upperFirst, type SchemaView } from '@fougere/schema';
2
-
3
- /** Options for list queries — pagination, sorting, counting. */
4
- export interface ListOptions {
5
- /** Number of records to return. */
6
- limit?: number;
7
-
8
- /** Offset-based: skip N records. */
9
- offset?: number;
10
-
11
- /** Page-based: 1-indexed page number (requires limit). */
12
- page?: number;
13
-
14
- /** Cursor-based: fetch records after this ID. */
15
- after?: string;
16
-
17
- /** Field name to order by. */
18
- orderBy?: string;
19
-
20
- /** Sort direction (default: 'asc'). */
21
- order?: 'asc' | 'desc';
22
-
23
- /** If true, also returns total count (for pagination UIs). */
24
- count?: boolean;
25
-
26
- /**
27
- * Equality criteria, field by field — `{ orderId: '…' }`. Named rather than spread
28
- * across the options so an unknown key stays ignored instead of silently becoming a
29
- * filter. `listBy(criteria)` is the same thing said as an intention.
30
- */
31
- where?: Record<string, unknown>;
32
- }
33
-
34
- /** Result of list() — extends Array so it's backward compatible. */
35
- export interface ListResult<T> extends Array<T> {
36
- /** Total number of matching records (only set when count: true). */
37
- total?: number;
38
- /** Cursor of the last item (for cursor-based pagination). */
39
- endCursor?: string;
40
- /** Whether more records exist after endCursor. */
41
- hasMore?: boolean;
42
- }
43
-
44
- /**
45
- * The keys `list()` answers to. Anything else is a mistake, and saying so is the point:
46
- * the façade refuses an unknown key in a CLIENT's input (`Unknown field`) — this applies the
47
- * same rule to the framework's own arguments. `list({ orderId })` used to be accepted and
48
- * the filter dropped, so a one-to-many relation quietly returned the whole table.
49
- */
50
- const LIST_OPTION_KEYS = [
51
- 'limit', 'offset', 'page', 'after', 'orderBy', 'order', 'count', 'where', 'select',
52
- ] as const;
53
-
54
- /** Refuse an option the port does not answer to, naming it and what was expected. */
55
- export function assertListOptions(options: object | undefined, entity: string): void {
56
- if (!options) return;
57
- const legal = new Set<string>(LIST_OPTION_KEYS);
58
- const strangers = Object.keys(options).filter((key) => !legal.has(key));
59
- if (strangers.length === 0) return;
60
- throw new Error(
61
- `${entity}.list(): unknown option ${strangers.map((s) => `\`${s}\``).join(', ')}. ` +
62
- `Known options are ${LIST_OPTION_KEYS.join(', ')} — to filter, pass \`where: { ${strangers[0]}: … }\`.`,
63
- );
64
- }
65
-
66
- /** Select option — restrict returned fields to those of a SchemaView. */
67
- export interface SelectOption {
68
- select?: SchemaView;
69
- }
70
-
71
- /** Per-entity ORM — scoped CRUD operations on a single entity type. */
72
- export interface EntityOrm<T = Record<string, unknown>> {
73
- list(options?: ListOptions & SelectOption): Promise<ListResult<T>>;
74
- findById(id: string, options?: SelectOption): Promise<T | undefined>;
75
- /**
76
- * Read by criteria — `findBy({ email })` for the one, `findAllBy({ orderId })` for the
77
- * many, which is what a one-to-many relation *is*.
78
- *
79
- * Both existed on the SQL implementation from the start and neither was declared here.
80
- * A port that hides what it offers is a port nobody can use: `auth-better` cast its way
81
- * in (`orm as OrmWithFindBy`), a presenter that needed the lines of an order read the
82
- * whole table instead, and the GraphQL relation resolver passed criteria to `list()`
83
- * — which drops what it does not know.
84
- */
85
- findBy(criteria: Partial<T> | Record<string, unknown>, options?: SelectOption): Promise<T | undefined>;
86
- findAllBy(criteria: Partial<T> | Record<string, unknown>, options?: SelectOption): Promise<T[]>;
87
- /**
88
- * Read a SET of rows by their key, in one go — the gesture every other one was
89
- * being bent into.
90
- *
91
- * `findAllBy` compares with `=`, so a list of ids could not be passed to it; the
92
- * only way to read N rows was `list()` then filter in memory, which is what 14 of
93
- * 14 handlers of a real app measured on 2026-08-14 were doing. It is invisible on
94
- * SQLite and it is the whole table the day the rows are not local.
95
- *
96
- * It answers a MAP, because the caller holds keys and not positions: a page zips
97
- * against it by `get(row.authorId)`, a miss is the absence of a key, and a repeated
98
- * key is one entry. The list form this replaced promised that zip and could not
99
- * keep it — dropping a miss shifts every later position — so each caller rebuilt
100
- * the very index the implementation had just thrown away.
101
- */
102
- findByKeys(ids: readonly string[], options?: SelectOption): Promise<Map<string, T>>;
103
- /**
104
- * Its dual: the rows that point AT each of these keys, grouped by the one they point at.
105
- *
106
- * `findByKeys` answers the side a row designates — one each, at most. This answers the
107
- * side that designates the row — several each, and a key with none is simply absent.
108
- * Together they are both directions of a relation, each in one query.
109
- *
110
- * Written because the page-shaped gesture only covered one of them: a presenter holding
111
- * its page and wanting "the items of these lists" had no vocabulary for it and read the
112
- * whole table instead, measured on a real app. `field` names the foreign key on THIS
113
- * entity, the one carrying the value.
114
- */
115
- findAllByKeys(field: string, keys: readonly string[], options?: SelectOption): Promise<Map<string, T[]>>;
116
- create(input: Partial<T>, options?: SelectOption): Promise<T>;
117
- /**
118
- * Write the row, or make the existing one look like this — one statement.
119
- *
120
- * What an import needs and the port did not have: `create` throws on the second run,
121
- * so re-reading a source meant deleting first. Measured pulling an API twice.
122
- *
123
- * The key and the creation stamps survive an overwrite — a row keeps the moment it
124
- * appeared. An engine with no upsert clause refuses by name rather than emulating
125
- * one with a read in front, which would promise an atomicity it has not got.
126
- */
127
- upsert(input: Partial<T>, options?: SelectOption): Promise<T>;
128
- /**
129
- * A whole page in one statement — what an import writes through.
130
- *
131
- * Row by row, 500 rows were 500 statements (measured); the shape of an import is a
132
- * page, so the write is one too. Answers how many rows were written rather than the
133
- * rows: `create` hands back the complete row because a caller acts on it, and an
134
- * import acts on none of them — re-reading a page for a symmetry nobody uses would
135
- * double the work.
136
- */
137
- upsertAll(inputs: readonly Partial<T>[], options?: SelectOption): Promise<number>;
138
- update(id: string, input: Partial<T>, options?: SelectOption): Promise<T>;
139
- delete(id: string): Promise<boolean>;
140
- /** Returns a scoped ORM that restricts all read results to the fields of the given schema. */
141
- output(schema: SchemaView): EntityOrm<T>;
142
- /**
143
- * What this ORM wraps — the Kysely instance for the SQL one, something else elsewhere.
144
- *
145
- * Every judge sits on the ORM's own methods, so a statement issued here meets none of
146
- * them: a value the entity refuses lands in the table without a word. It is the port's
147
- * own escape hatch rather than a handle on the side, so it keeps the scope the container
148
- * gave you — `productOrm.client` reaches the products, not the whole database.
149
- *
150
- * `unknown` on purpose: the client belongs to the implementation, and narrowing it is
151
- * the caller saying out loud which one they are standing on.
152
- */
153
- readonly client: unknown;
154
- }
155
-
156
- /**
157
- * Factory that creates an EntityOrm for a given entity.
158
- * Called by bootstrap for every scanned entity.
159
- */
160
- export type OrmFactory = (entity: SchemaView, name: string) => EntityOrm;
161
-
162
- /**
163
- * Container key of an entity's storage — 'reading' → 'ReadingOrm'.
164
- *
165
- * The twin of {@link repositoryKeyOf} and of `facadeKeyOf`: the key of a thing
166
- * lives with the thing. This one was spelled by hand in four places in
167
- * `bootstrap.ts` and a fifth in `scanner.ts` — where the SCAN derives what a
168
- * constructor asks for. Two readers of one convention, neither of them naming it,
169
- * so a rename would have moved one and left the other resolving to nothing.
170
- */
171
- export function ormKeyOf(entity: string): string {
172
- return `${upperFirst(entity)}Orm`;
173
- }
174
-
175
- /**
176
- * `Together<[Account, Ledger]>` — writes that stand or fall as one.
177
- *
178
- * `EntityOrm` is the port whose every gesture is ONE statement, and one statement is
179
- * atomic in every engine. This is the port whose unit is a BLOCK: what the callback did
180
- * happens entirely, or not at all. Nothing else separates them — the arity of the unit
181
- * of work is the whole distinction, which is why this lives here and not in a file of
182
- * its own.
183
- *
184
- * ```ts
185
- * constructor(private together: Together<[Account, Ledger]>) {}
186
- *
187
- * await this.together.run(async ([accounts, ledger]) => {
188
- * await accounts.update(from, { balance: b - amount });
189
- * await ledger.create({ from, to, amount });
190
- * });
191
- * ```
192
- *
193
- * **The second list is providers**, rebuilt inside the frame so that what THEY write is
194
- * covered too — a `Mirror` writes its pages through `EntityOrm<T>`, so naming it puts
195
- * them under the same unwind, with no locator and no second injection path:
196
- *
197
- * ```ts
198
- * constructor(private together: Together<[RateCard, Ledger], [RateMirror]>) {}
199
- *
200
- * await this.together.run(async ([rates, ledger], [mirror]) => { await mirror.refresh(); });
201
- * ```
202
- *
203
- * Two lists rather than one, because in a signature an entity and a provider are both
204
- * written as a class name and their instance types do not separate them — the type would
205
- * have to guess, by looking for methods or for a brand, and both answers are worse than
206
- * saying it. They are two different facts anyway: what the unwind covers, and what is
207
- * rebuilt to make that true.
208
- *
209
- * **All or nothing is the promise; isolation is not.** On one engine the members are
210
- * rebuilt over a transaction and the engine gives both. Across engines a transaction
211
- * cannot exist, so the frame keeps the before-image of each write and replays the
212
- * inverse in reverse order — the unwind holds, the isolation does not, and a reader
213
- * between two writes sees the half. The boot says which of the two it built rather
214
- * than letting the author assume the stronger one.
215
- */
216
- export interface Together<E extends readonly unknown[], P extends readonly unknown[] = []> {
217
- run<R>(fn: (entities: { [K in keyof E]: EntityOrm<E[K]> }, providers: P) => Promise<R>): Promise<R>;
218
- }
219
-
220
- /**
221
- * The container key of a frame — `[['Account', 'Ledger'], ['RateMirror']]` →
222
- * 'Account+Ledger|RateMirrorTogether'.
223
- *
224
- * The DECLARED order, not a sorted one. The tuples are what the callback destructures, so
225
- * reordering here would hand `[ledger, accounts]` to a signature that says the opposite —
226
- * the type and the runtime disagreeing about the same line. Two orders of one frame are
227
- * therefore two keys and two registrations; they cost nothing, a frame holding no state
228
- * between runs.
229
- */
230
- export function togetherKeyOf(entities: readonly string[], providers: readonly string[] = []): string {
231
- const named = entities.map(upperFirst).join(SEPARATOR);
232
- return `${named}${providers.length ? KINDS + providers.map(upperFirst).join(SEPARATOR) : ''}${FRAME}`;
233
- }
234
-
235
- const FRAME = 'Together';
236
- const SEPARATOR = '+';
237
- /** Separates the two lists — what the unwind covers, and what is rebuilt to make it true. */
238
- const KINDS = '|';
239
-
240
- /**
241
- * The members behind a frame key, or `undefined` when the key is not one.
242
- *
243
- * The dual of the line above, and here for the reason `factOfEmitKey` is: the boot reads
244
- * the key back out of a handler's `deps` to know which frames to build. A key and the way
245
- * to undo it belong together — the pair that is split is the pair that drifts.
246
- */
247
- export function membersOfTogetherKey(key: string): { entities: string[]; providers: string[] } | undefined {
248
- if (key.length <= FRAME.length || !key.endsWith(FRAME)) return undefined;
249
- const [entities, providers = ''] = key.slice(0, -FRAME.length).split(KINDS);
250
- const split = (list: string) => list.split(SEPARATOR).filter(Boolean);
251
- return { entities: split(entities!), providers: split(providers) };
252
- }
@@ -1,73 +0,0 @@
1
- import type { SchemaView } from '@fougere/schema';
2
- import type { EntityEntry, FrondDescriptor } from './frond.js';
3
-
4
- /**
5
- * What this app hosts — the scan's answer, with the questions everyone was asking it
6
- * by hand.
7
- *
8
- * The list was a bare array, so every reader re-walked it: "which frond owns this
9
- * entity" was spelled four times, "every entity by name" three times as three literal
10
- * copies of the same `Map`, and the two inside the boot even carried comments saying so.
11
- * A concept nobody can question is a concept everyone rebuilds.
12
- *
13
- * It IS an array — the same reason `ListResult` is one: twenty call sites iterate,
14
- * filter and spread it, and none of them is wrong to. `Symbol.species` is `Array` so a
15
- * `.map()` over it answers a plain array rather than something that claims to be a
16
- * hosting table and holds strings.
17
- */
18
- export class Fronds extends Array<FrondDescriptor> {
19
- static override get [Symbol.species](): ArrayConstructor {
20
- return Array;
21
- }
22
-
23
- /** What one scan run found. The only gate in — `Array.of` is taken, and named. */
24
- static scanned(fronds: readonly FrondDescriptor[]): Fronds {
25
- const held = new Fronds();
26
- held.push(...fronds);
27
- return held;
28
- }
29
-
30
- /** The frond that hosts an entity — `undefined` when no loaded frond does. */
31
- owner(entity: string): FrondDescriptor | undefined {
32
- return this.find((frond) => frond.entities.some((e) => e.name === entity));
33
- }
34
-
35
- /** The entity of that name, wherever it was scanned. */
36
- entity(name: string): EntityEntry | undefined {
37
- for (const frond of this) {
38
- const found = frond.entities.find((e) => e.name === name);
39
- if (found) return found;
40
- }
41
- return undefined;
42
- }
43
-
44
- /**
45
- * Every scanned entity class, by name — across all fronds and never per-frond.
46
- *
47
- * A fact is announced in one frond and heard in another, so the subscriber's own
48
- * frond does not hold the shape it must judge; a `reads:` clause names entities
49
- * that belong to neighbours by definition.
50
- */
51
- schemas(): Map<string, SchemaView> {
52
- return new Map(this.flatMap((frond) => frond.entities.map((e) => [e.name, e.entityClass] as const)));
53
- }
54
-
55
- /** Every scanned entity, sorted. What was FOUND, not what answers. */
56
- entityNames(): string[] {
57
- return this.flatMap((frond) => frond.entities.map((e) => e.name)).sort();
58
- }
59
-
60
- /**
61
- * The names a call may address, sorted — what a NOT_FOUND must print.
62
- *
63
- * Not `entityNames()`, which is what the scan found: an entity with no handler is
64
- * scanned and serves nothing, so the refusal read *"Entity 'indexed' is not hosted
65
- * here. Hosted here: indexed."* — naming the very thing it had just refused. A façade
66
- * is keyed on a HANDLER's address, and that is what this lists.
67
- */
68
- servedNames(surface?: string): string[] {
69
- return this.flatMap((frond) => frond.handlers
70
- .filter((handler) => (handler.surface ?? undefined) === surface)
71
- .map((handler) => handler.address)).sort();
72
- }
73
- }
package/src/scan/frond.ts DELETED
@@ -1,235 +0,0 @@
1
- /**
2
- * A frond as the SCAN found it — one interface per convention directory, plus what the
3
- * run could not read.
4
- *
5
- * The declared side is `frond-config.ts`; this is the described one. They meet at
6
- * `FrondDescriptor.operationsOverrides`, where a declaration reaches the façade.
7
- */
8
- import type { SchemaView } from '@fougere/schema';
9
- import type { ParsedParam, OperationContract, OperationsMap } from '../wire/operation.js';
10
- import type { PresenterViews } from '../prefab/presenter.js';
11
- import type { Fronds } from './Fronds.js';
12
-
13
- /**
14
- * A discovered provider — a class under `services/` or `repositories/`, injected by type.
15
- *
16
- * Which of the two directories it came from is deliberately not recorded. The scan used
17
- * to tag it `kind: 'service' | 'repository'`, a field it filled on every provider and
18
- * that **no consumer ever read** — the two directories are two spellings of the same
19
- * thing, and DI resolves by type either way.
20
- */
21
- export interface ProviderEntry {
22
- /**
23
- * The class constructor (default export of the file).
24
- *
25
- * `never[]` and not `unknown[]`: the arguments are the CONTAINER's to supply, so the
26
- * slot must accept any constructor — and with `unknown[]` a real class is refused,
27
- * because assigning it would need `unknown` to be one of its declared parameters.
28
- * Invisible on the scan path, where the value arrives as `unknown` and is cast; the
29
- * module `fougere build` writes states the class by name, and that is where it showed.
30
- */
31
- ctor: new (...args: never[]) => unknown;
32
- /** Constructor dependency type names (from AST scan). */
33
- deps: string[];
34
- /** Absolute file path (for debugging). */
35
- filePath: string;
36
- }
37
-
38
- /** A discovered entity (Entity subclass in entities/ dir). */
39
- export interface EntityEntry {
40
- /** Registration key: class name lowercased first char (e.g. 'product'). */
41
- name: string;
42
- /** The Entity class (has static getFields()). */
43
- entityClass: SchemaView;
44
- /** Absolute file path (for debugging). */
45
- filePath: string;
46
- /** Whether this entity is part of the frond's public contract. */
47
- exposed?: boolean;
48
- }
49
-
50
- /** A discovered handler (controls what a service exposes). */
51
- export interface HandlerEntry {
52
- /** Registration key (e.g. 'postHandler'). */
53
- name: string;
54
- /**
55
- * The name this handler answers to — its class name minus `Handler`, lowercased
56
- * (`PostHandler` → `post`). It is what `facadeKeyOf` builds its key from and what
57
- * travels as `FrondCall.entity` on the wire.
58
- *
59
- * **It is NOT an entity name**, and it was called `entityName` for long enough to
60
- * mislead: `toEntityName` (`scanner.ts`) strips the suffix without checking that any
61
- * entity carries the result, and the boot states the consequence — *pointing at
62
- * nothing is legal*. A health check, a search across several shapes, a pure
63
- * computation: ordinary handlers that own no row. `PresenterEntry`/`CollectorEntry`
64
- * keep `entityName` because those really do target a declared entity.
65
- */
66
- address: string;
67
- /** The handler class. */
68
- ctor: new (...args: never[]) => unknown;
69
- /** All operations with full signatures for binding. */
70
- operations: OperationsMap;
71
- /** Constructor dependency type names (from AST scan). */
72
- deps: string[];
73
- /** Absolute file path (for debugging). */
74
- filePath: string;
75
- /** Whether this handler is part of the frond's public contract. */
76
- exposed?: boolean;
77
- /** Output schema override — when Crud(Entity, Output), restricts ORM output. */
78
- outputOverride?: SchemaView;
79
- /** Surface name — subdirectory in handlers/ (e.g. 'admin', 'public'). */
80
- surface?: string;
81
- }
82
-
83
- /** Return type metadata for a presenter computed field. */
84
- export interface PresenterFieldMeta {
85
- name: string;
86
- /** Inferred return type name: 'string', 'number', 'boolean', or a class name. */
87
- returnType?: string;
88
- /**
89
- * The field emits a LIST per row — `tags(posts: Post[]): string[][]`.
90
- *
91
- * The method answers one value per row, so the outer array level of its return type is
92
- * the page, not the field: what remains after removing it is the field's own arity.
93
- * Nothing measured that remainder, so a computed list and a computed scalar looked
94
- * identical and every projection announced the scalar.
95
- */
96
- list?: boolean;
97
- /** Whether the return is nullable. */
98
- nullable?: boolean;
99
- /**
100
- * The declared parameters AFTER the rows. Kept raw rather than resolved: the scan
101
- * meets presenters before collectors, so the plan is computed at boot where the
102
- * collector names are known — exactly as a handler op's is.
103
- *
104
- * A computed field that declares `user?: User` is then fed by the collector
105
- * that resolves one. A presenter is not a second mechanism.
106
- */
107
- params?: ParsedParam[];
108
- }
109
-
110
- /** A discovered presenter (computed fields for an entity's output). */
111
- export interface PresenterEntry {
112
- /** Entity name this presenter enriches (e.g. 'post' from PostPresenter). */
113
- entityName: string;
114
- /** The presenter class. */
115
- ctor: new (...args: never[]) => unknown;
116
- /** Computed field names (method names on prototype). */
117
- fields: string[];
118
- /** Per-field type metadata (inferred from source via parser). */
119
- fieldMeta: PresenterFieldMeta[];
120
- /**
121
- * The view each computed field emits, when the presenter declares one
122
- * (`Presenter(Order, { items: [OrderItemView] })`). Stated rather than inferred: the
123
- * parser reads a scalar off a return type and nothing more, so an object-valued field
124
- * has no derivable shape without this.
125
- */
126
- views?: PresenterViews;
127
- /** Constructor dependency type names (from AST scan). */
128
- deps: string[];
129
- /** Absolute file path (for debugging). */
130
- filePath: string;
131
- }
132
-
133
- /** A discovered collector (resolves handler input params from invocation context). */
134
- export interface CollectorEntry {
135
- /** Registration key of the TYPE this collector resolves — 'user', 'ability'. */
136
- typeName: string;
137
- /** The collector class. */
138
- ctor: new (...args: never[]) => unknown;
139
- /** Constructor dependency type names (from AST scan). */
140
- deps: string[];
141
- /** Absolute file path (for debugging). */
142
- filePath: string;
143
- }
144
-
145
- /** A discovered seed file (array of records or async factory). */
146
- export interface SeedEntry {
147
- /** Entity name this seed targets (from filename: Author.seed.ts → 'author'). */
148
- entityName: string;
149
- /** Raw default export — array or function. Resolved at runtime. */
150
- data: Record<string, unknown>[] | SeedFactory;
151
- /** Absolute file path (for debugging). */
152
- filePath: string;
153
- }
154
-
155
- /** Seed factory — receives a resolver to access handlers cross-frond. */
156
- export type SeedFactory = (resolve: <T>(name: string) => T) => Promise<Record<string, unknown>[]>;
157
-
158
- /** Where a frond lives on disk. */
159
- export interface FrondSource {
160
- /** Absolute path to the frond directory. */
161
- path: string;
162
- /** The @fronds/{name} package name. Always present. */
163
- package: string;
164
- }
165
-
166
- export interface FrondDescriptor {
167
- name: string;
168
- source: FrondSource;
169
- providers: ProviderEntry[];
170
- entities: EntityEntry[];
171
- handlers: HandlerEntry[];
172
- presenters: PresenterEntry[];
173
- collectors: CollectorEntry[];
174
- seeds: SeedEntry[];
175
- /** Per-surface entity lists from frond.config.ts (e.g. { graphql: ['Post'], rest: ['Post', 'Author'] }). */
176
- surfaces?: Record<string, string[]>;
177
- /** Entities this frond may read across sources — see `FrondConfig.reads`. */
178
- reads?: string[];
179
- /**
180
- * Per-operation overrides from frond.config.ts. Key = operation name.
181
- *
182
- * Two depths, as declared on {@link OperationOverride}: the surface keys travel to the
183
- * transport adapters, the contract keys (`input`/`output`/`binding`) travel to the
184
- * façade — where config is the third producer of an operation's contract, alongside a
185
- * prefab's `__ops` and the scan.
186
- */
187
- operationsOverrides?: Record<string, OperationContract & {
188
- kind?: 'query' | 'command';
189
- /** Class name to resolve from DI (overrides default `{Entity}Handler` lookup). */
190
- handlerName?: string;
191
- /** Method name on the resolved handler (defaults to op name). */
192
- method?: string;
193
- }>;
194
- }
195
-
196
- /** Result of scanning a project directory. */
197
- /**
198
- * Something the scan could NOT do — recorded instead of swallowed.
199
- *
200
- * The scan answers with what it found. Until now it answered the same way whether
201
- * a directory held nothing or could not be read, and whether a handler declared no
202
- * operation or failed to parse: `catch → empty`. So every downstream reader — the
203
- * façade, the identity card, anything asking "what does this app serve?" — could
204
- * not tell **"there is nothing"** from **"I could not look"**.
205
- *
206
- * That distinction is what makes a rule about an ABSENCE sound. Without it, a check
207
- * derived from the scan reports "nothing wrong" precisely when it read nothing.
208
- */
209
- export interface ScanDiagnostic {
210
- /**
211
- * `blocking` — the app now serves less than its source declares, and no caller
212
- * can know it: a handler that failed to parse contributes zero operations.
213
- * `warning` — something may be missing and the scan cannot decide, e.g. a base
214
- * class it is not allowed to resolve. Statable in `frond.config.ts`.
215
- */
216
- severity: 'blocking' | 'warning';
217
- /** Stable rule name — `handler-parse-failed`, `directory-unreadable`. */
218
- code: string;
219
- /** Absolute path of what could not be read. */
220
- filePath: string;
221
- /** The frond it belongs to, when the scan got far enough to know. */
222
- frond?: string;
223
- /** The declaration the diagnostic is about — e.g. `PostHandler.publish`. */
224
- subject?: string;
225
- /** What could not be done, and what it costs. One sentence, for a human. */
226
- message: string;
227
- /** The underlying failure, kept whole. */
228
- cause?: unknown;
229
- }
230
-
231
- export interface ScanResult {
232
- fronds: Fronds;
233
- /** What the scan could not do. Empty is a claim, not a default — see {@link ScanDiagnostic}. */
234
- diagnostics: ScanDiagnostic[];
235
- }
File without changes
File without changes