@fougere/core 0.6.0-alpha.0 → 0.8.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/boot/AppLifecycle.d.ts +1 -1
- package/dist/boot/AppLifecycle.d.ts.map +1 -1
- package/dist/boot/AppLifecycle.js +13 -2
- package/dist/boot/AppLifecycle.js.map +1 -1
- package/dist/boot/Emissions.d.ts +13 -90
- package/dist/boot/Emissions.d.ts.map +1 -1
- package/dist/boot/Emissions.js +21 -118
- package/dist/boot/Emissions.js.map +1 -1
- package/dist/boot/ambient-port.d.ts +3 -24
- package/dist/boot/ambient-port.d.ts.map +1 -1
- package/dist/boot/ambient.als.d.ts.map +1 -1
- package/dist/boot/ambient.als.js +7 -12
- package/dist/boot/ambient.als.js.map +1 -1
- package/dist/boot/ambient.queue.d.ts +2 -5
- package/dist/boot/ambient.queue.d.ts.map +1 -1
- package/dist/boot/ambient.queue.js.map +1 -1
- package/dist/boot/apply.d.ts +1 -13
- package/dist/boot/apply.d.ts.map +1 -1
- package/dist/boot/apply.js +9 -16
- package/dist/boot/apply.js.map +1 -1
- package/dist/boot/auth.d.ts +2 -12
- package/dist/boot/auth.d.ts.map +1 -1
- package/dist/boot/boot.d.ts +3 -16
- package/dist/boot/boot.d.ts.map +1 -1
- package/dist/boot/boot.js +4 -11
- package/dist/boot/boot.js.map +1 -1
- package/dist/boot/bootstrap.d.ts.map +1 -1
- package/dist/boot/bootstrap.js +84 -130
- package/dist/boot/bootstrap.js.map +1 -1
- package/dist/boot/card.d.ts +1 -17
- package/dist/boot/card.d.ts.map +1 -1
- package/dist/boot/card.js +3 -32
- package/dist/boot/card.js.map +1 -1
- package/dist/boot/frame.d.ts +8 -32
- package/dist/boot/frame.d.ts.map +1 -1
- package/dist/boot/frame.js +17 -56
- package/dist/boot/frame.js.map +1 -1
- package/dist/boot/hosted.d.ts +2 -24
- package/dist/boot/hosted.d.ts.map +1 -1
- package/dist/boot/hosted.js +10 -15
- package/dist/boot/hosted.js.map +1 -1
- package/dist/boot/ownership.d.ts +3 -36
- package/dist/boot/ownership.d.ts.map +1 -1
- package/dist/boot/ownership.js +5 -40
- package/dist/boot/ownership.js.map +1 -1
- package/dist/boot/ports.d.ts +1 -14
- package/dist/boot/ports.d.ts.map +1 -1
- package/dist/boot/ports.js +1 -14
- package/dist/boot/ports.js.map +1 -1
- package/dist/boot/remote.d.ts +5 -38
- package/dist/boot/remote.d.ts.map +1 -1
- package/dist/boot/remote.js +8 -41
- package/dist/boot/remote.js.map +1 -1
- package/dist/boot/runner.d.ts +4 -21
- package/dist/boot/runner.d.ts.map +1 -1
- package/dist/boot/runner.js +4 -17
- package/dist/boot/runner.js.map +1 -1
- package/dist/boot/seed.d.ts +4 -31
- package/dist/boot/seed.d.ts.map +1 -1
- package/dist/boot/seed.js +6 -37
- package/dist/boot/seed.js.map +1 -1
- package/dist/boot/statement-drift.d.ts +2 -21
- package/dist/boot/statement-drift.d.ts.map +1 -1
- package/dist/boot/statement-drift.js +4 -9
- package/dist/boot/statement-drift.js.map +1 -1
- package/dist/boot/together.d.ts +4 -8
- package/dist/boot/together.d.ts.map +1 -1
- package/dist/boot/together.js +15 -50
- package/dist/boot/together.js.map +1 -1
- package/dist/boot/types.d.ts +31 -173
- package/dist/boot/types.d.ts.map +1 -1
- package/dist/builtin/config.d.ts +7 -0
- package/dist/builtin/config.d.ts.map +1 -0
- package/dist/builtin/config.js +15 -0
- package/dist/builtin/config.js.map +1 -0
- package/dist/{builtins → builtin}/logger.d.ts +4 -25
- package/dist/builtin/logger.d.ts.map +1 -0
- package/dist/{builtins → builtin}/logger.js +5 -32
- package/dist/builtin/logger.js.map +1 -0
- package/dist/config-loader.d.ts +9 -67
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +5 -18
- package/dist/config-loader.js.map +1 -1
- package/dist/contract.d.ts +15 -31
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +13 -26
- package/dist/contract.js.map +1 -1
- package/dist/criterion.d.ts +37 -0
- package/dist/criterion.d.ts.map +1 -0
- package/dist/criterion.js +28 -0
- package/dist/criterion.js.map +1 -0
- package/dist/crypto/encoding.d.ts +2 -15
- package/dist/crypto/encoding.d.ts.map +1 -1
- package/dist/crypto/encoding.js +2 -15
- package/dist/crypto/encoding.js.map +1 -1
- package/dist/crypto/node.d.ts.map +1 -1
- package/dist/crypto/node.js +1 -7
- package/dist/crypto/node.js.map +1 -1
- package/dist/crypto/port.d.ts +2 -18
- package/dist/crypto/port.d.ts.map +1 -1
- package/dist/crypto/port.js +1 -17
- package/dist/crypto/port.js.map +1 -1
- package/dist/crypto/webcrypto.d.ts.map +1 -1
- package/dist/crypto/webcrypto.js +1 -12
- package/dist/crypto/webcrypto.js.map +1 -1
- package/dist/declare.d.ts +19 -37
- package/dist/declare.d.ts.map +1 -1
- package/dist/declare.js +23 -30
- package/dist/declare.js.map +1 -1
- package/dist/define.d.ts +2 -3
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +2 -3
- package/dist/define.js.map +1 -1
- package/dist/descriptor/Fronds.d.ts +3 -28
- package/dist/descriptor/Fronds.d.ts.map +1 -1
- package/dist/descriptor/Fronds.js +6 -31
- package/dist/descriptor/Fronds.js.map +1 -1
- package/dist/descriptor/frond.d.ts +25 -60
- package/dist/descriptor/frond.d.ts.map +1 -1
- package/dist/descriptor/frond.js +5 -1
- package/dist/descriptor/frond.js.map +1 -1
- package/dist/dispatch/ArgumentResolver.d.ts +1 -1
- package/dist/dispatch/ArgumentResolver.d.ts.map +1 -1
- package/dist/dispatch/ArgumentResolver.js +5 -5
- package/dist/dispatch/ArgumentResolver.js.map +1 -1
- package/dist/dispatch/DispatchEvent.d.ts +2 -2
- package/dist/dispatch/DispatchEvent.d.ts.map +1 -1
- package/dist/dispatch/DispatchLifecycle.d.ts +1 -7
- package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -1
- package/dist/dispatch/DispatchLifecycle.js +1 -7
- package/dist/dispatch/DispatchLifecycle.js.map +1 -1
- package/dist/dispatch/DispatchPort.d.ts +1 -1
- package/dist/dispatch/DispatchPort.d.ts.map +1 -1
- package/dist/dispatch/Dispatcher.d.ts +1 -1
- package/dist/dispatch/Dispatcher.d.ts.map +1 -1
- package/dist/dispatch/Dispatcher.js +2 -2
- package/dist/dispatch/Dispatcher.js.map +1 -1
- package/dist/{boot → dispatch}/HandlerFacade.d.ts +25 -38
- package/dist/dispatch/HandlerFacade.d.ts.map +1 -0
- package/dist/{boot → dispatch}/HandlerFacade.js +65 -74
- package/dist/dispatch/HandlerFacade.js.map +1 -0
- package/dist/dispatch/LocalRoutePolicy.d.ts +1 -1
- package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -1
- package/dist/dispatch/LocalRoutePolicy.js +4 -4
- package/dist/dispatch/LocalRoutePolicy.js.map +1 -1
- package/dist/dispatch/OperationRoute.d.ts +2 -2
- package/dist/dispatch/OperationRoute.d.ts.map +1 -1
- package/dist/dispatch/OutputView.d.ts +3 -2
- package/dist/dispatch/OutputView.d.ts.map +1 -1
- package/dist/dispatch/OutputView.js +19 -1
- package/dist/dispatch/OutputView.js.map +1 -1
- package/dist/dispatch/Route.d.ts +2 -2
- package/dist/dispatch/Route.d.ts.map +1 -1
- package/dist/dispatch/RoutePolicy.d.ts +1 -1
- package/dist/dispatch/RoutePolicy.d.ts.map +1 -1
- package/dist/dispatch/RouteRegistry.d.ts +1 -1
- package/dist/dispatch/RouteRegistry.d.ts.map +1 -1
- package/dist/dispatch/RouteRegistry.js +2 -2
- package/dist/dispatch/RouteRegistry.js.map +1 -1
- package/dist/dispatch/RouteResolver.d.ts +2 -4
- package/dist/dispatch/RouteResolver.d.ts.map +1 -1
- package/dist/dispatch/StorageGuard.d.ts +40 -8
- package/dist/dispatch/StorageGuard.d.ts.map +1 -1
- package/dist/dispatch/StorageGuard.js +151 -20
- package/dist/dispatch/StorageGuard.js.map +1 -1
- package/dist/dispatch/presenterArguments.d.ts +7 -0
- package/dist/dispatch/presenterArguments.d.ts.map +1 -0
- package/dist/dispatch/presenterArguments.js +12 -0
- package/dist/dispatch/presenterArguments.js.map +1 -0
- package/dist/dispatch/remoteRoutes.d.ts +7 -0
- package/dist/dispatch/remoteRoutes.d.ts.map +1 -0
- package/dist/dispatch/{RemoteRouteResolver.js → remoteRoutes.js} +6 -10
- package/dist/dispatch/remoteRoutes.js.map +1 -0
- package/dist/dispatch/routeNotFound.d.ts +9 -0
- package/dist/dispatch/routeNotFound.d.ts.map +1 -0
- package/dist/dispatch/routeNotFound.js +21 -0
- package/dist/dispatch/routeNotFound.js.map +1 -0
- package/dist/dispatch/validateInput.d.ts +5 -0
- package/dist/dispatch/validateInput.d.ts.map +1 -0
- package/dist/dispatch/validateInput.js +20 -0
- package/dist/dispatch/validateInput.js.map +1 -0
- package/dist/effective-operation.d.ts +1 -24
- package/dist/effective-operation.d.ts.map +1 -1
- package/dist/effective-operation.js +21 -50
- package/dist/effective-operation.js.map +1 -1
- package/dist/emit.d.ts +4 -42
- package/dist/emit.d.ts.map +1 -1
- package/dist/emit.js +3 -39
- package/dist/emit.js.map +1 -1
- package/dist/entry/facade.d.ts +8 -0
- package/dist/entry/facade.d.ts.map +1 -0
- package/dist/entry/facade.js +28 -0
- package/dist/entry/facade.js.map +1 -0
- package/dist/entry/transport.d.ts +5 -0
- package/dist/entry/transport.d.ts.map +1 -0
- package/dist/entry/transport.js +11 -0
- package/dist/entry/transport.js.map +1 -0
- package/dist/frond-config.d.ts +7 -70
- package/dist/frond-config.d.ts.map +1 -1
- package/dist/frond-config.js +1 -9
- package/dist/frond-config.js.map +1 -1
- package/dist/identity-keys.d.ts +2 -5
- package/dist/identity-keys.d.ts.map +1 -1
- package/dist/identity-keys.js +3 -16
- package/dist/identity-keys.js.map +1 -1
- package/dist/identity.d.ts +4 -30
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +11 -73
- package/dist/identity.js.map +1 -1
- package/dist/imports.d.ts +1 -7
- package/dist/imports.d.ts.map +1 -1
- package/dist/imports.js +1 -7
- package/dist/imports.js.map +1 -1
- package/dist/index.d.ts +17 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -18
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +1 -8
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1 -8
- package/dist/loader.js.map +1 -1
- package/dist/node.d.ts +2 -11
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +2 -11
- package/dist/node.js.map +1 -1
- package/dist/prefab/collector.d.ts +1 -22
- package/dist/prefab/collector.d.ts.map +1 -1
- package/dist/prefab/collector.js +1 -22
- package/dist/prefab/collector.js.map +1 -1
- package/dist/prefab/crud.d.ts +16 -32
- package/dist/prefab/crud.d.ts.map +1 -1
- package/dist/prefab/crud.js +31 -58
- package/dist/prefab/crud.js.map +1 -1
- package/dist/prefab/mirror.d.ts +2 -24
- package/dist/prefab/mirror.d.ts.map +1 -1
- package/dist/prefab/mirror.js +2 -20
- package/dist/prefab/mirror.js.map +1 -1
- package/dist/prefab/prefab.d.ts +1 -7
- package/dist/prefab/prefab.d.ts.map +1 -1
- package/dist/prefab/prefab.js +1 -7
- package/dist/prefab/prefab.js.map +1 -1
- package/dist/prefab/presenter.d.ts +2 -36
- package/dist/prefab/presenter.d.ts.map +1 -1
- package/dist/prefab/presenter.js +2 -36
- package/dist/prefab/presenter.js.map +1 -1
- package/dist/prefab/repository.d.ts +5 -73
- package/dist/prefab/repository.d.ts.map +1 -1
- package/dist/prefab/repository.js +3 -16
- package/dist/prefab/repository.js.map +1 -1
- package/dist/scan/adapters.d.ts +3 -0
- package/dist/scan/adapters.d.ts.map +1 -0
- package/dist/scan/adapters.js +25 -0
- package/dist/scan/adapters.js.map +1 -0
- package/dist/scan/bundling.d.ts +1 -12
- package/dist/scan/bundling.d.ts.map +1 -1
- package/dist/scan/bundling.js +1 -12
- package/dist/scan/bundling.js.map +1 -1
- package/dist/scan/contract.d.ts +27 -0
- package/dist/scan/contract.d.ts.map +1 -0
- package/dist/scan/contract.js +46 -0
- package/dist/scan/contract.js.map +1 -0
- package/dist/scan/conventions.d.ts +6 -40
- package/dist/scan/conventions.d.ts.map +1 -1
- package/dist/scan/conventions.js +5 -34
- package/dist/scan/conventions.js.map +1 -1
- package/dist/scan/emit.d.ts +1 -5
- package/dist/scan/emit.d.ts.map +1 -1
- package/dist/scan/emit.js +10 -78
- package/dist/scan/emit.js.map +1 -1
- package/dist/scan/handler-parser.d.ts +4 -26
- package/dist/scan/handler-parser.d.ts.map +1 -1
- package/dist/scan/handler-parser.js +26 -83
- package/dist/scan/handler-parser.js.map +1 -1
- package/dist/scan/result.d.ts +3 -16
- package/dist/scan/result.d.ts.map +1 -1
- package/dist/scan/scanner.d.ts +2 -27
- package/dist/scan/scanner.d.ts.map +1 -1
- package/dist/scan/scanner.js +45 -133
- package/dist/scan/scanner.js.map +1 -1
- package/dist/scan/statement.d.ts.map +1 -1
- package/dist/scan/statement.js +60 -37
- package/dist/scan/statement.js.map +1 -1
- package/dist/source.d.ts +53 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +18 -0
- package/dist/source.js.map +1 -0
- package/dist/storage.d.ts +13 -210
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +4 -68
- package/dist/storage.js.map +1 -1
- package/dist/store.d.ts +18 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +179 -0
- package/dist/store.js.map +1 -0
- package/dist/verify.d.ts +5 -38
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +17 -37
- package/dist/verify.js.map +1 -1
- package/dist/wire/CallLog.d.ts +32 -0
- package/dist/wire/CallLog.d.ts.map +1 -0
- package/dist/{contract → wire}/CallLog.js.map +1 -1
- package/dist/wire/Invocation.d.ts +32 -0
- package/dist/wire/Invocation.d.ts.map +1 -0
- package/dist/wire/Invocation.js +66 -0
- package/dist/wire/Invocation.js.map +1 -0
- package/dist/{contract → wire}/RouteAddress.d.ts +5 -0
- package/dist/wire/RouteAddress.d.ts.map +1 -0
- package/dist/{contract → wire}/RouteAddress.js +7 -0
- package/dist/wire/RouteAddress.js.map +1 -0
- package/dist/wire/binding.d.ts +5 -21
- package/dist/wire/binding.d.ts.map +1 -1
- package/dist/wire/binding.js +5 -10
- package/dist/wire/binding.js.map +1 -1
- package/dist/wire/call.d.ts +24 -133
- package/dist/wire/call.d.ts.map +1 -1
- package/dist/wire/call.js +15 -41
- package/dist/wire/call.js.map +1 -1
- package/dist/wire/drift.d.ts +3 -28
- package/dist/wire/drift.d.ts.map +1 -1
- package/dist/wire/drift.js +4 -23
- package/dist/wire/drift.js.map +1 -1
- package/dist/wire/errors.d.ts +4 -24
- package/dist/wire/errors.d.ts.map +1 -1
- package/dist/wire/errors.js +4 -24
- package/dist/wire/errors.js.map +1 -1
- package/dist/wire/http-error.d.ts +2 -13
- package/dist/wire/http-error.d.ts.map +1 -1
- package/dist/wire/http-error.js +5 -19
- package/dist/wire/http-error.js.map +1 -1
- package/dist/wire/loggerMiddleware.d.ts +2 -8
- package/dist/wire/loggerMiddleware.d.ts.map +1 -1
- package/dist/wire/loggerMiddleware.js +1 -7
- package/dist/wire/loggerMiddleware.js.map +1 -1
- package/dist/wire/middleware.d.ts +3 -7
- package/dist/wire/middleware.d.ts.map +1 -1
- package/dist/wire/middleware.js +1 -5
- package/dist/wire/middleware.js.map +1 -1
- package/dist/wire/operation.d.ts +7 -43
- package/dist/wire/operation.d.ts.map +1 -1
- package/dist/wire/operation.js +4 -15
- package/dist/wire/operation.js.map +1 -1
- package/dist/wire/signature.d.ts +4 -25
- package/dist/wire/signature.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/boot/AppLifecycle.ts +15 -2
- package/src/boot/Emissions.ts +21 -118
- package/src/boot/ambient-port.ts +3 -24
- package/src/boot/ambient.als.ts +7 -12
- package/src/boot/ambient.queue.ts +2 -5
- package/src/boot/apply.ts +9 -16
- package/src/boot/auth.ts +2 -12
- package/src/boot/boot.ts +6 -21
- package/src/boot/bootstrap.ts +95 -140
- package/src/boot/card.ts +4 -33
- package/src/boot/frame.ts +24 -64
- package/src/boot/hosted.ts +12 -34
- package/src/boot/ownership.ts +5 -39
- package/src/boot/ports.ts +1 -14
- package/src/boot/remote.ts +11 -58
- package/src/boot/runner.ts +5 -22
- package/src/boot/seed.ts +6 -37
- package/src/boot/statement-drift.ts +5 -24
- package/src/boot/together.ts +18 -51
- package/src/boot/types.ts +31 -173
- package/src/{builtins → builtin}/config.ts +1 -7
- package/src/{builtins → builtin}/logger.ts +6 -39
- package/src/config-loader.ts +12 -71
- package/src/contract.ts +19 -39
- package/src/criterion.ts +54 -0
- package/src/crypto/encoding.ts +2 -15
- package/src/crypto/node.ts +1 -7
- package/src/crypto/port.ts +2 -18
- package/src/crypto/webcrypto.ts +1 -12
- package/src/declare.ts +42 -41
- package/src/define.ts +2 -3
- package/src/descriptor/Fronds.ts +6 -31
- package/src/descriptor/frond.ts +26 -60
- package/src/dispatch/ArgumentResolver.ts +6 -6
- package/src/dispatch/DispatchEvent.ts +2 -2
- package/src/dispatch/DispatchLifecycle.ts +1 -7
- package/src/dispatch/DispatchPort.ts +1 -1
- package/src/dispatch/Dispatcher.ts +3 -3
- package/src/dispatch/HandlerFacade.ts +231 -0
- package/src/dispatch/LocalRoutePolicy.ts +4 -4
- package/src/dispatch/OperationRoute.ts +2 -2
- package/src/dispatch/OutputView.ts +24 -2
- package/src/dispatch/Route.ts +2 -2
- package/src/dispatch/RoutePolicy.ts +1 -1
- package/src/dispatch/RouteRegistry.ts +2 -2
- package/src/dispatch/RouteResolver.ts +2 -4
- package/src/dispatch/StorageGuard.ts +175 -19
- package/src/dispatch/presenterArguments.ts +25 -0
- package/src/dispatch/{RemoteRouteResolver.ts → remoteRoutes.ts} +7 -9
- package/src/dispatch/routeNotFound.ts +33 -0
- package/src/dispatch/validateInput.ts +28 -0
- package/src/effective-operation.ts +21 -50
- package/src/emit.ts +5 -63
- package/src/entry/facade.ts +44 -0
- package/src/entry/transport.ts +16 -0
- package/src/frond-config.ts +7 -70
- package/src/identity-keys.ts +3 -16
- package/src/identity.ts +12 -80
- package/src/imports.ts +2 -31
- package/src/index.ts +17 -24
- package/src/loader.ts +2 -16
- package/src/node.ts +2 -11
- package/src/prefab/collector.ts +1 -22
- package/src/prefab/crud.ts +37 -76
- package/src/prefab/mirror.ts +4 -44
- package/src/prefab/prefab.ts +2 -21
- package/src/prefab/presenter.ts +2 -36
- package/src/prefab/repository.ts +7 -83
- package/src/scan/adapters.ts +32 -0
- package/src/scan/bundling.ts +1 -12
- package/src/scan/contract.ts +80 -0
- package/src/scan/conventions.ts +6 -40
- package/src/scan/emit.ts +11 -80
- package/src/scan/handler-parser.ts +27 -96
- package/src/scan/result.ts +3 -16
- package/src/scan/scanner.ts +46 -132
- package/src/scan/statement.ts +73 -41
- package/src/source.ts +63 -0
- package/src/storage.ts +14 -234
- package/src/store.ts +191 -0
- package/src/verify.ts +16 -57
- package/src/wire/CallLog.ts +30 -0
- package/src/{contract → wire}/Invocation.ts +24 -17
- package/src/{contract → wire}/RouteAddress.ts +7 -0
- package/src/wire/binding.ts +9 -25
- package/src/wire/call.ts +30 -133
- package/src/wire/drift.ts +5 -30
- package/src/wire/errors.ts +4 -24
- package/src/wire/http-error.ts +5 -19
- package/src/wire/loggerMiddleware.ts +2 -8
- package/src/wire/middleware.ts +3 -7
- package/src/wire/operation.ts +8 -48
- package/src/wire/signature.ts +4 -25
- package/dist/boot/HandlerFacade.d.ts.map +0 -1
- package/dist/boot/HandlerFacade.js.map +0 -1
- package/dist/builtins/config.d.ts +0 -13
- package/dist/builtins/config.d.ts.map +0 -1
- package/dist/builtins/config.js +0 -21
- package/dist/builtins/config.js.map +0 -1
- package/dist/builtins/logger.d.ts.map +0 -1
- package/dist/builtins/logger.js.map +0 -1
- package/dist/contract/Call.d.ts +0 -10
- package/dist/contract/Call.d.ts.map +0 -1
- package/dist/contract/Call.js +0 -15
- package/dist/contract/Call.js.map +0 -1
- package/dist/contract/CallLog.d.ts +0 -57
- package/dist/contract/CallLog.d.ts.map +0 -1
- package/dist/contract/Invocation.d.ts +0 -27
- package/dist/contract/Invocation.d.ts.map +0 -1
- package/dist/contract/Invocation.js +0 -59
- package/dist/contract/Invocation.js.map +0 -1
- package/dist/contract/RouteAddress.d.ts.map +0 -1
- package/dist/contract/RouteAddress.js.map +0 -1
- package/dist/dispatch/InputValidator.d.ts +0 -7
- package/dist/dispatch/InputValidator.d.ts.map +0 -1
- package/dist/dispatch/InputValidator.js +0 -22
- package/dist/dispatch/InputValidator.js.map +0 -1
- package/dist/dispatch/OperationExecutor.d.ts +0 -25
- package/dist/dispatch/OperationExecutor.d.ts.map +0 -1
- package/dist/dispatch/OperationExecutor.js +0 -32
- package/dist/dispatch/OperationExecutor.js.map +0 -1
- package/dist/dispatch/OutputProjector.d.ts +0 -12
- package/dist/dispatch/OutputProjector.d.ts.map +0 -1
- package/dist/dispatch/OutputProjector.js +0 -30
- package/dist/dispatch/OutputProjector.js.map +0 -1
- package/dist/dispatch/PresenterArgumentResolver.d.ts +0 -12
- package/dist/dispatch/PresenterArgumentResolver.d.ts.map +0 -1
- package/dist/dispatch/PresenterArgumentResolver.js +0 -20
- package/dist/dispatch/PresenterArgumentResolver.js.map +0 -1
- package/dist/dispatch/RemoteRouteResolver.d.ts +0 -13
- package/dist/dispatch/RemoteRouteResolver.d.ts.map +0 -1
- package/dist/dispatch/RemoteRouteResolver.js.map +0 -1
- package/dist/dispatch/RouteNotFoundError.d.ts +0 -10
- package/dist/dispatch/RouteNotFoundError.d.ts.map +0 -1
- package/dist/dispatch/RouteNotFoundError.js +0 -24
- package/dist/dispatch/RouteNotFoundError.js.map +0 -1
- package/dist/entry/DynamicFacade.d.ts +0 -10
- package/dist/entry/DynamicFacade.d.ts.map +0 -1
- package/dist/entry/DynamicFacade.js +0 -27
- package/dist/entry/DynamicFacade.js.map +0 -1
- package/dist/entry/FacadeEntry.d.ts +0 -11
- package/dist/entry/FacadeEntry.d.ts.map +0 -1
- package/dist/entry/FacadeEntry.js +0 -26
- package/dist/entry/FacadeEntry.js.map +0 -1
- package/dist/entry/TransportEntry.d.ts +0 -13
- package/dist/entry/TransportEntry.d.ts.map +0 -1
- package/dist/entry/TransportEntry.js +0 -24
- package/dist/entry/TransportEntry.js.map +0 -1
- package/dist/rows.d.ts +0 -40
- package/dist/rows.d.ts.map +0 -1
- package/dist/rows.js +0 -146
- package/dist/rows.js.map +0 -1
- package/src/boot/HandlerFacade.ts +0 -242
- package/src/contract/Call.ts +0 -18
- package/src/contract/CallLog.ts +0 -55
- package/src/dispatch/InputValidator.ts +0 -28
- package/src/dispatch/OperationExecutor.ts +0 -60
- package/src/dispatch/OutputProjector.ts +0 -32
- package/src/dispatch/PresenterArgumentResolver.ts +0 -25
- package/src/dispatch/RouteNotFoundError.ts +0 -29
- package/src/entry/DynamicFacade.ts +0 -28
- package/src/entry/FacadeEntry.ts +0 -32
- package/src/entry/TransportEntry.ts +0 -30
- package/src/rows.ts +0 -155
- /package/dist/{contract → wire}/CallLog.js +0 -0
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Handler signature parser — extracts method signatures from handler source files.
|
|
3
|
-
*
|
|
4
|
-
* The AST says what the author declared; TypeScript's checker says what those types mean.
|
|
5
|
-
* TypeScript is lazy-loaded to avoid bundling the compiler in production builds.
|
|
6
|
-
*/
|
|
1
|
+
/** Handler signature parser — extracts method signatures from handler source files. */
|
|
7
2
|
import type { TypeRef, Param, Signature } from '../wire/signature.js';
|
|
8
3
|
import type ts from '@typescript/typescript6';
|
|
9
4
|
import { readFileSync, existsSync, statSync } from 'node:fs';
|
|
@@ -26,26 +21,11 @@ interface TypeProject {
|
|
|
26
21
|
program: ts.Program;
|
|
27
22
|
}
|
|
28
23
|
|
|
29
|
-
/**
|
|
30
|
-
* One checked program per project/configuration during a scan.
|
|
31
|
-
*
|
|
32
|
-
* A checker is a project reader, not a file parser: creating one per handler would reopen
|
|
33
|
-
* the standard library and every imported declaration for each method. `scanProject`
|
|
34
|
-
* resets this map at the start of a run, so an edited source can never meet a program from
|
|
35
|
-
* the previous run.
|
|
36
|
-
*/
|
|
24
|
+
/** One checked program per project/configuration during a scan. */
|
|
37
25
|
const typeProjects = new Map<string, TypeProject>();
|
|
38
26
|
const compilerProjects = new Map<string, { key: string; roots: string[]; options: ts.CompilerOptions }>();
|
|
39
27
|
|
|
40
|
-
/**
|
|
41
|
-
* What survives a run: the parsed declarations, and the program built over them.
|
|
42
|
-
*
|
|
43
|
-
* Rebuilding a program re-reads `lib.d.ts` and every imported `.d.ts`, and that is FIXED
|
|
44
|
-
* work — measured, a second scan in one process cost the same at 16 frond files as at 406.
|
|
45
|
-
* The mtime is the guard, so a run still cannot see a stale type: a file that moved is
|
|
46
|
-
* re-read and TypeScript invalidates it and everything depending on it, which is a
|
|
47
|
-
* narrower rule than discarding the program and not a weaker one.
|
|
48
|
-
*/
|
|
28
|
+
/** What survives a run. */
|
|
49
29
|
const sourceFiles = new Map<string, { mtime: number; file: ts.SourceFile }>();
|
|
50
30
|
const retained = new Map<string, { host: ts.CompilerHost; program: ts.Program }>();
|
|
51
31
|
|
|
@@ -61,8 +41,8 @@ export function forgetParsedSources(): void {
|
|
|
61
41
|
}
|
|
62
42
|
|
|
63
43
|
function keptHost(key: string, options: ts.CompilerOptions): ts.CompilerHost {
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
44
|
+
const cached = retained.get(key);
|
|
45
|
+
if (cached) return cached.host;
|
|
66
46
|
const typescript = getTS();
|
|
67
47
|
const base = typescript.createCompilerHost(options);
|
|
68
48
|
const host: ts.CompilerHost = {
|
|
@@ -138,13 +118,7 @@ function compilerProjectOf(filePath: string, projectRoot?: string): { key: strin
|
|
|
138
118
|
return configured;
|
|
139
119
|
}
|
|
140
120
|
|
|
141
|
-
/**
|
|
142
|
-
* Declare every file a run will read, so one program covers it.
|
|
143
|
-
*
|
|
144
|
-
* `checkedSourceOf` rebuilds whenever it meets a root it has not seen, and a frond lives
|
|
145
|
-
* outside its project's tsconfig `include`, so every declaration was a new root: 44 files
|
|
146
|
-
* cost 7.3 s that way against 0.34 s for one program.
|
|
147
|
-
*/
|
|
121
|
+
/** Declare every file a run will read, so one program covers it. */
|
|
148
122
|
export async function seedTypeProgram(filePaths: readonly string[], projectRoot?: string): Promise<void> {
|
|
149
123
|
const typescript = await loadTS();
|
|
150
124
|
const grouped = new Map<string, { options: ts.CompilerOptions; paths: string[] }>();
|
|
@@ -152,9 +126,9 @@ export async function seedTypeProgram(filePaths: readonly string[], projectRoot?
|
|
|
152
126
|
for (const filePath of filePaths) {
|
|
153
127
|
const absolute = resolvePath(filePath);
|
|
154
128
|
const configured = compilerProjectOf(absolute, projectRoot);
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
grouped.set(configured.key,
|
|
129
|
+
const group = grouped.get(configured.key) ?? { options: configured.options, paths: [] };
|
|
130
|
+
group.paths.push(absolute);
|
|
131
|
+
grouped.set(configured.key, group);
|
|
158
132
|
}
|
|
159
133
|
|
|
160
134
|
for (const [key, { options, paths }] of grouped) {
|
|
@@ -168,25 +142,25 @@ function checkedSourceOf(filePath: string, projectRoot?: string): { source: ts.S
|
|
|
168
142
|
const typescript = getTS();
|
|
169
143
|
const absolute = resolvePath(filePath);
|
|
170
144
|
const configured = compilerProjectOf(absolute, projectRoot);
|
|
171
|
-
let
|
|
145
|
+
let project = typeProjects.get(configured.key);
|
|
172
146
|
|
|
173
|
-
if (!
|
|
147
|
+
if (!project) {
|
|
174
148
|
// `path.resolve` is variadic, so handing it directly to `map` also passed the
|
|
175
149
|
// index and the whole roots array as path segments. A fixture without a warm scan
|
|
176
150
|
// cache exposed that first-run-only failure.
|
|
177
151
|
const roots = new Set(configured.roots.map((root) => resolvePath(root)));
|
|
178
152
|
roots.add(absolute);
|
|
179
153
|
const program = builtProgram(configured.key, [...roots], configured.options);
|
|
180
|
-
|
|
181
|
-
typeProjects.set(configured.key,
|
|
182
|
-
} else if (!
|
|
183
|
-
|
|
184
|
-
|
|
154
|
+
project = { roots, options: configured.options, program };
|
|
155
|
+
typeProjects.set(configured.key, project);
|
|
156
|
+
} else if (!project.roots.has(absolute)) {
|
|
157
|
+
project.roots.add(absolute);
|
|
158
|
+
project.program = builtProgram(configured.key, [...project.roots], project.options);
|
|
185
159
|
}
|
|
186
160
|
|
|
187
|
-
const source =
|
|
161
|
+
const source = project.program.getSourceFile(absolute);
|
|
188
162
|
if (!source) throw new Error(`TypeScript did not include '${absolute}' in its program.`);
|
|
189
|
-
return { source, checker:
|
|
163
|
+
return { source, checker: project.program.getTypeChecker() };
|
|
190
164
|
}
|
|
191
165
|
|
|
192
166
|
/** A file, opened. Five places read and parsed one, each spelling the same two calls. */
|
|
@@ -428,20 +402,7 @@ function resolveSpecifier(specifier: string, fromFile: string, projectRoot: stri
|
|
|
428
402
|
|
|
429
403
|
// ── Mixin / heritage parsing ─────────────────
|
|
430
404
|
|
|
431
|
-
/**
|
|
432
|
-
* The class a returned expression carries, however it is wrapped.
|
|
433
|
-
*
|
|
434
|
-
* A mixin does not always hand its class back bare. `Crud` returns
|
|
435
|
-
* `asCrudConstructor(class CrudHandler { … })` — one assertion helper standing between
|
|
436
|
-
* `return` and the class — and a parser accepting only a bare `return class` found
|
|
437
|
-
* nothing there, silently: the five inherited CRUD ops stopped being derived, and a warm
|
|
438
|
-
* scan cache kept answering the old parse for weeks (`scan-cache.ts` keys on source, not
|
|
439
|
-
* on parser version).
|
|
440
|
-
*
|
|
441
|
-
* So unwrap rather than match one shape: descend through call arguments, `as` and
|
|
442
|
-
* `satisfies` assertions, and parentheses. What is looked for is a class; where the
|
|
443
|
-
* author put it is their business.
|
|
444
|
-
*/
|
|
405
|
+
/** The class a returned expression carries, however it is wrapped. */
|
|
445
406
|
function classInExpression(expr: ts.Node, depth = 0): ts.ClassExpression | undefined {
|
|
446
407
|
const ts = getTS();
|
|
447
408
|
if (depth > 8) return undefined;
|
|
@@ -502,7 +463,7 @@ function extractClassMethods(
|
|
|
502
463
|
// `private`/`protected` is a statement about the surface, and the AST carries it —
|
|
503
464
|
// it was read past. Every helper a handler names by intent (`mustOwn`, `readMany`,
|
|
504
465
|
// `refuse`) became a callable op: measured on the bench, `list.readMany` executed
|
|
505
|
-
// and `list.mayPublish`
|
|
466
|
+
// and `list.mayPublish` validated its argument. A door is what the author declares
|
|
506
467
|
// public, and TypeScript already has the word for it. `#name` is private too, but
|
|
507
468
|
// it is not an identifier, so it never reached here in the first place.
|
|
508
469
|
if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)) continue;
|
|
@@ -521,14 +482,7 @@ function extractClassMethods(
|
|
|
521
482
|
return results;
|
|
522
483
|
}
|
|
523
484
|
|
|
524
|
-
/**
|
|
525
|
-
* The first sentence of a member's doc comment, or nothing.
|
|
526
|
-
*
|
|
527
|
-
* One sentence on purpose: what a caller needs to choose an operation is a claim,
|
|
528
|
-
* not an essay, and the rest of the comment addresses whoever edits the method.
|
|
529
|
-
* Reads the leading trivia rather than `ts.getJSDocTags` — the comment is what the
|
|
530
|
-
* author wrote, tags are a schema they never agreed to.
|
|
531
|
-
*/
|
|
485
|
+
/** The first sentence of a member's doc comment, or nothing. */
|
|
532
486
|
function docSentenceOf(member: ts.Node, source: ts.SourceFile): string | undefined {
|
|
533
487
|
const ts = getTS();
|
|
534
488
|
const ranges = ts.getLeadingCommentRanges(source.text, member.pos) ?? [];
|
|
@@ -551,11 +505,7 @@ function docSentenceOf(member: ts.Node, source: ts.SourceFile): string | undefin
|
|
|
551
505
|
* Parse inherited methods from a class's heritage clause.
|
|
552
506
|
* Handles both `extends Crud(Entity)` (mixin) and `extends BaseClass` patterns.
|
|
553
507
|
*/
|
|
554
|
-
/**
|
|
555
|
-
* Where a name used here is declared. The checker follows the import, the re-export chain
|
|
556
|
-
* and an installed package's types — the three cases three hand-rolled functions treated
|
|
557
|
-
* separately.
|
|
558
|
-
*/
|
|
508
|
+
/** Where a name used here is declared. */
|
|
559
509
|
function declarationFileOf(node: ts.Node, checker: ts.TypeChecker): string | undefined {
|
|
560
510
|
const typescript = getTS();
|
|
561
511
|
let symbol = checker.getSymbolAtLocation(node);
|
|
@@ -564,13 +514,7 @@ function declarationFileOf(node: ts.Node, checker: ts.TypeChecker): string | und
|
|
|
564
514
|
return symbol.declarations?.[0]?.getSourceFile().fileName;
|
|
565
515
|
}
|
|
566
516
|
|
|
567
|
-
/**
|
|
568
|
-
* The methods a base class contributes, read from the INSTANTIATED type.
|
|
569
|
-
*
|
|
570
|
-
* `extends Crud(Post)` gives `create(input: Partial<Post>)` directly: the checker has
|
|
571
|
-
* already substituted the mixin's type parameter. The three functions this replaces
|
|
572
|
-
* detected the generic names and mapped them to the mixin's arguments by position.
|
|
573
|
-
*/
|
|
517
|
+
/** The methods a base class contributes, read from the INSTANTIATED type. */
|
|
574
518
|
function inheritedFromBase(
|
|
575
519
|
base: ts.ExpressionWithTypeArguments,
|
|
576
520
|
checker: ts.TypeChecker,
|
|
@@ -617,10 +561,8 @@ function parseInheritedMethods(
|
|
|
617
561
|
checker: ts.TypeChecker,
|
|
618
562
|
skip: Set<string>,
|
|
619
563
|
/**
|
|
620
|
-
* Base classes this pass could not open — an INSTALLED one, typically, whose
|
|
621
|
-
*
|
|
622
|
-
* method": the two used to be the same answer, so an op inherited from a
|
|
623
|
-
* published base class was absent from the façade without a word.
|
|
564
|
+
* Base classes this pass could not open — an INSTALLED one, typically, whose source is not in
|
|
565
|
+
* the workspace.
|
|
624
566
|
*/
|
|
625
567
|
unresolved: string[],
|
|
626
568
|
): Signature[] {
|
|
@@ -685,14 +627,7 @@ function findDefaultClass(source: ts.SourceFile): ts.ClassDeclaration | undefine
|
|
|
685
627
|
return undefined;
|
|
686
628
|
}
|
|
687
629
|
|
|
688
|
-
/**
|
|
689
|
-
* What a handler file yielded — its methods, AND what the pass could not open.
|
|
690
|
-
*
|
|
691
|
-
* The second half is why this is a pair rather than an array: an unresolvable base
|
|
692
|
-
* class used to give the same answer as a base class with no method, so an op
|
|
693
|
-
* inherited from an installed package was missing from the façade in silence. The
|
|
694
|
-
* pair travels through the scan cache, which is why {@link PARSER_VERSION} moved.
|
|
695
|
-
*/
|
|
630
|
+
/** What a handler file yielded — its methods, AND what the pass could not open. */
|
|
696
631
|
export interface HandlerParse {
|
|
697
632
|
methods: Signature[];
|
|
698
633
|
/** Base classes whose source this pass could not open. Empty is a claim. */
|
|
@@ -708,11 +643,7 @@ export async function parseAllHandlerMethods(filePath: string, projectRoot?: str
|
|
|
708
643
|
return parseClassMethods(filePath, CONSTRUCTOR_ONLY, projectRoot);
|
|
709
644
|
}
|
|
710
645
|
|
|
711
|
-
/**
|
|
712
|
-
* Parse a presenter source file and extract all method signatures.
|
|
713
|
-
*
|
|
714
|
-
* Returns all methods (no CRUD filtering) — each method is a computed field.
|
|
715
|
-
*/
|
|
646
|
+
/** Parse a presenter source file and extract all method signatures. */
|
|
716
647
|
export async function parsePresenterMethods(filePath: string, projectRoot?: string): Promise<Signature[]> {
|
|
717
648
|
await loadTS();
|
|
718
649
|
// No `projectRoot`, so no heritage pass and nothing to report: a presenter's
|
package/src/scan/result.ts
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import type { Fronds } from '../descriptor/Fronds.js';
|
|
2
2
|
|
|
3
3
|
/** Result of scanning a project directory. */
|
|
4
|
-
/**
|
|
5
|
-
* Something the scan could NOT do — recorded instead of swallowed.
|
|
6
|
-
*
|
|
7
|
-
* The scan answers with what it found. Until now it answered the same way whether
|
|
8
|
-
* a directory held nothing or could not be read, and whether a handler declared no
|
|
9
|
-
* operation or failed to parse: `catch → empty`. So every downstream reader — the
|
|
10
|
-
* façade, the identity card, anything asking "what does this app serve?" — could
|
|
11
|
-
* not tell **"there is nothing"** from **"I could not look"**.
|
|
12
|
-
*
|
|
13
|
-
* That distinction is what makes a rule about an ABSENCE sound. Without it, a check
|
|
14
|
-
* derived from the scan reports "nothing wrong" precisely when it read nothing.
|
|
15
|
-
*/
|
|
4
|
+
/** Something the scan could NOT do — recorded instead of swallowed. */
|
|
16
5
|
export interface ScanDiagnostic {
|
|
17
6
|
/**
|
|
18
|
-
* `blocking` — the app now serves less than its source declares, and no caller
|
|
19
|
-
*
|
|
20
|
-
* `warning` — something may be missing and the scan cannot decide, e.g. a base
|
|
21
|
-
* class it is not allowed to resolve. Statable in `frond.config.ts`.
|
|
7
|
+
* `blocking` — the app now serves less than its source declares, and no caller can know it: a
|
|
8
|
+
* handler that failed to parse contributes zero operations.
|
|
22
9
|
*/
|
|
23
10
|
severity: 'blocking' | 'warning';
|
|
24
11
|
/** Stable rule name — `handler-parse-failed`, `directory-unreadable`. */
|
package/src/scan/scanner.ts
CHANGED
|
@@ -31,13 +31,7 @@ import {
|
|
|
31
31
|
|
|
32
32
|
// FS
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
* What this scan run could not do. Reset by {@link scanProject}, which owns a run.
|
|
36
|
-
*
|
|
37
|
-
* Module-scoped like the loader and the cache root above: the scanner already has a
|
|
38
|
-
* notion of "the current run". Three sites record — measured — so a per-run object
|
|
39
|
-
* would carry twenty methods to spare one line of reset.
|
|
40
|
-
*/
|
|
34
|
+
/** What this scan run could not do. */
|
|
41
35
|
let diagnostics: ScanDiagnostic[] = [];
|
|
42
36
|
|
|
43
37
|
function record(d: ScanDiagnostic): void {
|
|
@@ -45,10 +39,8 @@ function record(d: ScanDiagnostic): void {
|
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
/**
|
|
48
|
-
* An absent convention directory is the ordinary case — a frond without
|
|
49
|
-
*
|
|
50
|
-
* that is not a directory) means the scan did not look, and answering `[]` says
|
|
51
|
-
* it did. One `catch` used to conflate the two.
|
|
42
|
+
* An absent convention directory is the ordinary case — a frond without `presenters/` is not a
|
|
43
|
+
* defect.
|
|
52
44
|
*/
|
|
53
45
|
async function readEntries(path: string): Promise<Dirent[]> {
|
|
54
46
|
try {
|
|
@@ -94,8 +86,18 @@ async function loadDefault(filePath: string): Promise<unknown> {
|
|
|
94
86
|
|
|
95
87
|
async function loadClass(filePath: string): Promise<ProviderEntry['ctor']> {
|
|
96
88
|
const ctor = await loadDefault(filePath);
|
|
97
|
-
|
|
98
|
-
|
|
89
|
+
// A convention directory holds classes, because a provider is registered under one and
|
|
90
|
+
// asked for by its type. What is NOT a class — a shared contract, a pure function, a
|
|
91
|
+
// table of constants — belongs beside them rather than among them, and saying where
|
|
92
|
+
// costs one line: measured twice on a real project, both times a file that had to move.
|
|
93
|
+
if (typeof ctor !== 'function' || !ctor.prototype) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`${filePath}: default export is not a class. This directory is scanned for providers, `
|
|
96
|
+
+ 'which are registered under a class name — a contract or a pure function has no key '
|
|
97
|
+
+ `to answer under. Move it beside the directory, at the frond's root, where the scan `
|
|
98
|
+
+ 'reads nothing and an import still reaches it.',
|
|
99
|
+
);
|
|
100
|
+
}
|
|
99
101
|
return ctor as ProviderEntry['ctor'];
|
|
100
102
|
}
|
|
101
103
|
|
|
@@ -115,13 +117,7 @@ function findWorkspaceRoot(from: string): string {
|
|
|
115
117
|
return resolvePath(from); // fallback: use project root itself
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
/**
|
|
119
|
-
* Strip the 'Handler' suffix → the name the handler answers to. 'PostHandler' → 'post'.
|
|
120
|
-
*
|
|
121
|
-
* Nothing here checks that an entity carries the result, and nothing should: a handler
|
|
122
|
-
* about no stored row is ordinary. The old name of this function — `toEntityName` — is
|
|
123
|
-
* what let "one façade per entity" be repeated until it read as a rule.
|
|
124
|
-
*/
|
|
120
|
+
/** Strip the 'Handler' suffix → the name the handler answers to. */
|
|
125
121
|
function toAddress(className: string): string {
|
|
126
122
|
const base = className.endsWith('Handler') ? className.slice(0, -7) : className;
|
|
127
123
|
return lowerFirst(base);
|
|
@@ -130,18 +126,8 @@ function toAddress(className: string): string {
|
|
|
130
126
|
// Scan
|
|
131
127
|
|
|
132
128
|
/**
|
|
133
|
-
* The container key a constructor parameter asks for — derived from its TYPE, not from
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* `deps` used to be `p.type.name`, so the key WAS the alias's name: `type ListStorage =
|
|
137
|
-
* Storage<List>` resolved only because someone had spelled it exactly like the
|
|
138
|
-
* registration key (`ListStorage`), while `type ListRepo = Storage<List>` — the same type —
|
|
139
|
-
* typechecked and died at boot on `'ListRepo' is not registered`. And `Storage<List>`
|
|
140
|
-
* written out in full asked for `'Storage'`, which nothing registers.
|
|
141
|
-
*
|
|
142
|
-
* `Storage<X>` names X's storage, so that is the key. The generic argument was already
|
|
143
|
-
* parsed (`TypeRef.generics`) and thrown away. Anything else keeps its own name: a
|
|
144
|
-
* plain service IS designated by its class name.
|
|
129
|
+
* The container key a constructor parameter asks for — derived from its TYPE, not from how the
|
|
130
|
+
* type was spelled.
|
|
145
131
|
*/
|
|
146
132
|
function depKeyOf(type: TypeRef): string {
|
|
147
133
|
// `Facade<PostHandler>` — the second port, read exactly like the first. The type names
|
|
@@ -166,32 +152,25 @@ function depKeyOf(type: TypeRef): string {
|
|
|
166
152
|
// `RepositoryOf<Post>` — what an author writes when no repository file exists. The dual
|
|
167
153
|
// of the line below: one names the port, the other the holder, and both resolve to a key
|
|
168
154
|
// rather than to a class the author would have to invent.
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
155
|
+
const subject = type.name === 'RepositoryOf' ? type.generics?.[0]?.name : undefined;
|
|
156
|
+
if (subject) return repositoryKeyOf(subject);
|
|
171
157
|
|
|
172
|
-
|
|
158
|
+
// The GENERIC names the subject, so a prefix does not change the key — `MeiliStorage<Card>`
|
|
159
|
+
// is `Card`'s storage. A class named `FileStorage` is untouched: it carries no generic.
|
|
160
|
+
const target = type.name.endsWith('Storage') && type.generics?.length === 1
|
|
161
|
+
? type.generics[0]?.name
|
|
162
|
+
: undefined;
|
|
173
163
|
if (!target) return type.name;
|
|
174
164
|
|
|
175
165
|
return storageKeyOf(target);
|
|
176
166
|
}
|
|
177
167
|
|
|
178
|
-
/**
|
|
179
|
-
* `'[Account, Ledger]'` → `['Account', 'Ledger']`.
|
|
180
|
-
*
|
|
181
|
-
* The tuple was chosen over the variadic form the parser reads more cleanly, because the
|
|
182
|
-
* variadic one costs arities-with-defaults and a `never` filter on the TypeScript side
|
|
183
|
-
* while the tuple maps to `[Storage<Account>, Storage<Ledger>]` in one line. The
|
|
184
|
-
* parser does not get to decide alone; this split is what that choice costs.
|
|
185
|
-
*/
|
|
168
|
+
/** `'[Account, Ledger]'` → `['Account', 'Ledger']`. */
|
|
186
169
|
function tupleMembers(raw: string): string[] {
|
|
187
170
|
return raw.replace(/^\[|\]$/g, '').split(',').map((member) => member.trim()).filter(Boolean);
|
|
188
171
|
}
|
|
189
172
|
|
|
190
|
-
/**
|
|
191
|
-
* These readings are semantic: an unchanged file can mean something different after an
|
|
192
|
-
* imported alias changes. The parser's TypeScript Program is the cache for one scan; a
|
|
193
|
-
* cache keyed only by this file's bytes would be unsound.
|
|
194
|
-
*/
|
|
173
|
+
/** These readings are semantic. */
|
|
195
174
|
const ctorParamsOf = (filePath: string) =>
|
|
196
175
|
parseConstructorParams(filePath);
|
|
197
176
|
|
|
@@ -203,6 +182,9 @@ const handlerMethodsOf = (filePath: string, projectRoot?: string) =>
|
|
|
203
182
|
|
|
204
183
|
async function toProvider(filePath: string): Promise<ProviderEntry> {
|
|
205
184
|
const ctor = await loadClass(filePath);
|
|
185
|
+
// Read here, while the class is the one the source declared. What a bundler does to
|
|
186
|
+
// that name later is why it is carried rather than asked for again.
|
|
187
|
+
const name = ctor.name;
|
|
206
188
|
const params = await ctorParamsOf(filePath);
|
|
207
189
|
const deps = params.map((p) => depKeyOf(p.type));
|
|
208
190
|
|
|
@@ -222,10 +204,10 @@ async function toProvider(filePath: string): Promise<ProviderEntry> {
|
|
|
222
204
|
deps.push(storageKeyOf(lowerFirst((target as { name: string }).name)));
|
|
223
205
|
}
|
|
224
206
|
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
return { ctor, deps, filePath };
|
|
207
|
+
// `name` beside `ctor`, and it IS the registration key — what `depKeyOf` returns, since
|
|
208
|
+
// it reads the type as written. It used to be asked of `ctor.name` at boot, which held
|
|
209
|
+
// until a bundler lowered a static field and renamed the declaration doing it.
|
|
210
|
+
return { name, ctor, deps, filePath };
|
|
229
211
|
}
|
|
230
212
|
|
|
231
213
|
async function toEntityEntry(filePath: string): Promise<EntityEntry | null> {
|
|
@@ -272,12 +254,7 @@ function resolveSchema(type: TypeRef, moduleExports: Record<string, unknown>): S
|
|
|
272
254
|
return undefined;
|
|
273
255
|
}
|
|
274
256
|
|
|
275
|
-
/**
|
|
276
|
-
* Parse ALL method signatures for unified binding.
|
|
277
|
-
*
|
|
278
|
-
* Resolves schemas for all params (not just the first) and stores
|
|
279
|
-
* full signatures for the binding algorithm.
|
|
280
|
-
*/
|
|
257
|
+
/** Parse ALL method signatures for unified binding. */
|
|
281
258
|
async function inferOperations(
|
|
282
259
|
filePath: string,
|
|
283
260
|
handlerName: string,
|
|
@@ -308,15 +285,8 @@ async function inferOperations(
|
|
|
308
285
|
}
|
|
309
286
|
|
|
310
287
|
/**
|
|
311
|
-
* A base class the parse could not open — an installed package, typically, whose
|
|
312
|
-
*
|
|
313
|
-
* the scan cannot tell whether there were any.
|
|
314
|
-
*
|
|
315
|
-
* A warning, not a refusal: an installed base class with no operation is perfectly
|
|
316
|
-
* ordinary, and the boot has no way to decide between the two. So it names the
|
|
317
|
-
* clause and stops there. Stating the contract in `frond.config.ts` is the answer
|
|
318
|
-
* — the third producer, which creates an op neither other producer found — and it
|
|
319
|
-
* silences this by making the op exist.
|
|
288
|
+
* A base class the parse could not open — an installed package, typically, whose source is not
|
|
289
|
+
* in the workspace.
|
|
320
290
|
*/
|
|
321
291
|
for (const base of parsed.unresolvedHeritage) {
|
|
322
292
|
record({
|
|
@@ -342,10 +312,10 @@ async function inferOperations(
|
|
|
342
312
|
// caller supplies through the body are candidates: a schema-typed collector, fact or
|
|
343
313
|
// context parameter is not input merely because it names an entity. The old loop
|
|
344
314
|
// ignored provenance and assigned the first schema it met, so swapping two parameters
|
|
345
|
-
// silently changed the contract the façade used to
|
|
315
|
+
// silently changed the contract the façade used to validate the request body.
|
|
346
316
|
const binding = computeBindingPlan(method.params, collectorTypeNames);
|
|
347
317
|
const candidates = method.params.flatMap((param, index) => {
|
|
348
|
-
if (binding[index]?.source.kind !== '
|
|
318
|
+
if (binding[index]?.source.kind !== 'input') return [];
|
|
349
319
|
const schema = resolveSchema(param.type, moduleExports);
|
|
350
320
|
return schema ? [{ param, schema }] : [];
|
|
351
321
|
});
|
|
@@ -522,13 +492,7 @@ async function scanFrond(frondPath: string, name: string, source: FrondDescripto
|
|
|
522
492
|
entities: entitiesDir, handlers: handlersDir,
|
|
523
493
|
presenters: presentersDir, collectors: collectorsDir, seeds: seedsDir,
|
|
524
494
|
} = conventions.dirs;
|
|
525
|
-
/**
|
|
526
|
-
* A convention directory, read by whoever knows the shape it holds.
|
|
527
|
-
*
|
|
528
|
-
* The same three lines were written six times — list, read in parallel, drop what the
|
|
529
|
-
* reader refused — which is what made `handlers/` quietly special: it grew a second
|
|
530
|
-
* pass for its surfaces and nothing else could.
|
|
531
|
-
*/
|
|
495
|
+
/** A convention directory, read by whoever knows the shape it holds. */
|
|
532
496
|
const collect = async <T extends object>(
|
|
533
497
|
dir: string,
|
|
534
498
|
read: (filePath: string) => Promise<T | null>,
|
|
@@ -615,15 +579,7 @@ async function scanFrond(frondPath: string, name: string, source: FrondDescripto
|
|
|
615
579
|
};
|
|
616
580
|
}
|
|
617
581
|
|
|
618
|
-
/**
|
|
619
|
-
* The frond's name — the directory, unless its `package.json` renames it. One rule for a
|
|
620
|
-
* frond under `fronds/` and for the root frond alike, so the root needs no second spelling.
|
|
621
|
-
*
|
|
622
|
-
* Carrying the convention is what makes a frond; the key never marked anything and
|
|
623
|
-
* nothing read it. It earns its keep as the one thing the directory cannot say: that
|
|
624
|
-
* `fronds/blog-v2/` serves the frond still called `blog` — so a rename on disk does not
|
|
625
|
-
* rename the entity keys, the `@fronds/*` import or a `remotes:` entry.
|
|
626
|
-
*/
|
|
582
|
+
/** The frond's name — the directory, unless its `package.json` renames it. */
|
|
627
583
|
async function frondNameOf(frondPath: string, dirName: string): Promise<string> {
|
|
628
584
|
try {
|
|
629
585
|
const pkg = JSON.parse(await readFile(join(frondPath, 'package.json'), 'utf8')) as {
|
|
@@ -637,15 +593,8 @@ async function frondNameOf(frondPath: string, dirName: string): Promise<string>
|
|
|
637
593
|
}
|
|
638
594
|
|
|
639
595
|
/**
|
|
640
|
-
* A frond is a directory carrying the convention, and the project root is one such
|
|
641
|
-
*
|
|
642
|
-
* anything. `fronds/` is not the definition, it is where the OTHERS live: the root frond
|
|
643
|
-
* stays put when a second domain appears, which is what makes flattening free instead of
|
|
644
|
-
* a deferred move.
|
|
645
|
-
*
|
|
646
|
-
* `entities/` is the test, not "any convention directory". `services/` and `repositories/`
|
|
647
|
-
* are ordinary top-level names in projects that never heard of Fougere, and a domain
|
|
648
|
-
* without a single entity is not a domain.
|
|
596
|
+
* A frond is a directory carrying the convention, and the project root is one such directory — so
|
|
597
|
+
* a single-domain app writes `entities/` next to `app/` and never names anything.
|
|
649
598
|
*/
|
|
650
599
|
async function rootFrondOf(root: string, workspaceRoot: string, conventions: Conventions): Promise<FrondDescriptor | null> {
|
|
651
600
|
if ((await files(join(root, conventions.dirs.entities))).length === 0) return null;
|
|
@@ -653,21 +602,7 @@ async function rootFrondOf(root: string, workspaceRoot: string, conventions: Con
|
|
|
653
602
|
return scanFrond(root, name, { path: root, package: frondPackage(name, conventions) }, conventions, workspaceRoot);
|
|
654
603
|
}
|
|
655
604
|
|
|
656
|
-
/**
|
|
657
|
-
* `@fronds/<name>` → the directory it names, for every frond of a project.
|
|
658
|
-
*
|
|
659
|
-
* The framework states this convention — `FrondSource.package` has always spelled it, and
|
|
660
|
-
* `fougere sync` writes it into a consumer's tsconfig — and until now its own reader could
|
|
661
|
-
* not resolve it. The Nuxt module registered a Vite alias, so a `.vue` page could import
|
|
662
|
-
* `@fronds/blog/entities/Post`, while the SCAN loaded sources through a bare jiti: a frond
|
|
663
|
-
* naming its neighbour got `Cannot find module '@fronds/user/entities/User.js'`. So the one
|
|
664
|
-
* form that survives a split was the one form that did not run.
|
|
665
|
-
*
|
|
666
|
-
* Hand it to the module loader — `createJiti(url, { alias: await frondAliases(root) })` —
|
|
667
|
-
* and the named form resolves everywhere the framework reads. A directory listing and a
|
|
668
|
-
* `package.json` read, no parsing: it is deliberately callable BEFORE the loader exists,
|
|
669
|
-
* which is what makes the chicken-and-egg go away.
|
|
670
|
-
*/
|
|
605
|
+
/** `@fronds/<name>` → the directory it names, for every frond of a project. */
|
|
671
606
|
export async function frondAliases(root: string, conventions: Conventions = DEFAULT_CONVENTIONS): Promise<Record<string, string>> {
|
|
672
607
|
const frondsDir = join(root, conventions.fronds);
|
|
673
608
|
const aliases: Record<string, string> = {};
|
|
@@ -681,17 +616,7 @@ export async function frondAliases(root: string, conventions: Conventions = DEFA
|
|
|
681
616
|
aliases[frondPackage(await frondNameOf(path, dir), conventions)] = resolvePath(path);
|
|
682
617
|
}
|
|
683
618
|
|
|
684
|
-
/**
|
|
685
|
-
* A SYNCED frond answers to the same name.
|
|
686
|
-
*
|
|
687
|
-
* `fougere sync` writes `.fougere/remotes/<name>/` and registers it in `remotes.json`,
|
|
688
|
-
* which the Nuxt module already reads to alias `@fronds/<name>`. Doing it here too is
|
|
689
|
-
* what makes the convention mean ONE thing: a consumer writes `@fronds/blog/entities/Post`
|
|
690
|
-
* and never learns whether that frond is on this disk or was fetched from a card.
|
|
691
|
-
*
|
|
692
|
-
* A local frond wins a name collision — its source is the truth, a synced copy is a
|
|
693
|
-
* mirror of somebody else's.
|
|
694
|
-
*/
|
|
619
|
+
/** A SYNCED frond answers to the same name. */
|
|
695
620
|
try {
|
|
696
621
|
const registry = JSON.parse(
|
|
697
622
|
await readFile(join(root, '.fougere', 'remotes.json'), 'utf8'),
|
|
@@ -757,18 +682,7 @@ export async function scanProject(
|
|
|
757
682
|
return { fronds, diagnostics };
|
|
758
683
|
}
|
|
759
684
|
|
|
760
|
-
/**
|
|
761
|
-
* What changes when a frond's domain changes — the paths a dev loop watches.
|
|
762
|
-
*
|
|
763
|
-
* It lives beside the scan rather than beside the conventions it reads, because it turns
|
|
764
|
-
* names into DISK paths: `join` is `node:path`, and `conventions.ts` is reached from
|
|
765
|
-
* `index` through `frond()`, which an edge bundle imports. Measured — esbuild refused the
|
|
766
|
-
* Worker with `Could not resolve "node:path"`.
|
|
767
|
-
*
|
|
768
|
-
* The root frond IS the scan root, so watching its path would match every write in the
|
|
769
|
-
* project: `.nuxt/`, `node_modules/`, the build output. Its convention directories are
|
|
770
|
-
* the frond, and they are what a scan re-reads.
|
|
771
|
-
*/
|
|
685
|
+
/** What changes when a frond's domain changes — the paths a dev loop watches. */
|
|
772
686
|
export function watchPathsOf(
|
|
773
687
|
frond: { source: { path: string } },
|
|
774
688
|
scanRoot: string,
|