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