@fougere/core 0.6.0-alpha.0 → 0.7.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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 +3 -15
- 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 +3 -10
- package/dist/boot/boot.js.map +1 -1
- package/dist/boot/bootstrap.d.ts.map +1 -1
- package/dist/boot/bootstrap.js +61 -127
- 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 +20 -54
- 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 +28 -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 +13 -31
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +10 -26
- package/dist/contract.js.map +1 -1
- 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 +6 -36
- package/dist/declare.d.ts.map +1 -1
- package/dist/declare.js +4 -29
- 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 +14 -63
- package/dist/descriptor/frond.d.ts.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 +8 -7
- package/dist/dispatch/StorageGuard.d.ts.map +1 -1
- package/dist/dispatch/StorageGuard.js +61 -18
- 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/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 +4 -38
- 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 +28 -127
- package/dist/scan/scanner.js.map +1 -1
- package/dist/scan/statement.d.ts.map +1 -1
- package/dist/scan/statement.js +4 -30
- package/dist/scan/statement.js.map +1 -1
- package/dist/source.d.ts +41 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +10 -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 +146 -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/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 +3 -15
- package/src/boot/auth.ts +2 -12
- package/src/boot/boot.ts +5 -20
- package/src/boot/bootstrap.ts +69 -136
- package/src/boot/card.ts +4 -33
- package/src/boot/frame.ts +28 -62
- 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 +28 -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 +15 -39
- 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 +8 -39
- package/src/define.ts +2 -3
- package/src/descriptor/Fronds.ts +6 -31
- package/src/descriptor/frond.ts +14 -63
- 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 +70 -18
- 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/conventions.ts +6 -40
- package/src/scan/emit.ts +4 -38
- package/src/scan/handler-parser.ts +27 -96
- package/src/scan/result.ts +3 -16
- package/src/scan/scanner.ts +27 -126
- package/src/scan/statement.ts +4 -30
- package/src/source.ts +44 -0
- package/src/storage.ts +14 -234
- package/src/store.ts +152 -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
package/src/boot/frame.ts
CHANGED
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The compensated realization of a frame — what `Together` becomes when its members do
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* A transaction is the engine's own answer and costs nothing to use: the members are
|
|
6
|
-
* rebuilt over it and the engine gives both the unwind and the isolation. Across engines
|
|
7
|
-
* there is no such thing, so the unwind is built here: every write through the port is
|
|
8
|
-
* recorded with the image that preceded it, and a failure replays the inverses in reverse
|
|
9
|
-
* order.
|
|
10
|
-
*
|
|
11
|
-
* **It gives all-or-nothing, never isolation.** Between two writes a reader sees the half,
|
|
12
|
-
* and nothing here can hide it — that is the whole difference between the two realizations
|
|
13
|
-
* and the reason the boot says which one it built.
|
|
14
|
-
*
|
|
15
|
-
* The port is thirteen known gestures, which is what makes the inverse derivable rather
|
|
16
|
-
* than declared: a saga asks its author for an `undo` per step because its steps are
|
|
17
|
-
* arbitrary code. Here they are not.
|
|
2
|
+
* The compensated realization of a frame — what `Together` becomes when its members do not share
|
|
3
|
+
* an engine.
|
|
18
4
|
*/
|
|
19
|
-
import {
|
|
5
|
+
import { FieldSet, Role, type SchemaView } from '@fougere/schema';
|
|
20
6
|
import { dequal } from 'dequal';
|
|
21
|
-
import type { Logger } from '../
|
|
7
|
+
import type { Logger } from '../builtin/logger.js';
|
|
22
8
|
|
|
23
9
|
/** One write that landed, and how to take it back. */
|
|
24
10
|
export interface Undo {
|
|
@@ -28,11 +14,8 @@ export interface Undo {
|
|
|
28
14
|
}
|
|
29
15
|
|
|
30
16
|
/**
|
|
31
|
-
* The subset of the port a frame has to watch: every gesture that writes, plus the reads
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* Not `StorageGuard`'s `Writer`, which is `create` and `update` — all a judge needs. Undoing
|
|
35
|
-
* needs more: the deletes, and the reads that fetch the image to put back.
|
|
17
|
+
* The subset of the port a frame has to watch: every gesture that writes, plus the reads that take
|
|
18
|
+
* one back.
|
|
36
19
|
*/
|
|
37
20
|
interface Undoable {
|
|
38
21
|
create(input: Record<string, unknown>, ...rest: unknown[]): Promise<Record<string, unknown>>;
|
|
@@ -47,25 +30,11 @@ interface Undoable {
|
|
|
47
30
|
const pick = (row: Record<string, unknown>, keys: readonly string[]): Record<string, unknown> =>
|
|
48
31
|
Object.fromEntries(keys.map((key) => [key, row[key]]));
|
|
49
32
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* were not. `SqlStorage` spells `onConflict(pk)` on SQLite and Postgres, so that holds —
|
|
56
|
-
* but MySQL's `onDuplicateKeyUpdate` fires on ANY unique constraint, and a row that
|
|
57
|
-
* conflicts on a unique email while carrying a different key would be restored under a key
|
|
58
|
-
* the write never touched.
|
|
59
|
-
*
|
|
60
|
-
* So the question is asked of the DECLARATION, not of the engine: an entity whose only
|
|
61
|
-
* unique constraint is its key upserts unambiguously everywhere. This file knows no dialect
|
|
62
|
-
* and should not learn one.
|
|
63
|
-
*/
|
|
64
|
-
function mayConflictElsewhere(fields: Fields): boolean {
|
|
65
|
-
const groups = FieldGroup.groupsOf(fields, Unique);
|
|
66
|
-
if (groups.length > 0) return true;
|
|
67
|
-
// A sole `unique()` carries a one-member group, which `groupsOf` filters out.
|
|
68
|
-
return Object.values(fields).some((field) => FieldGroup.on(field, Unique).length > 0);
|
|
33
|
+
/** Whether an upsert's conflict can be something other than the primary key. */
|
|
34
|
+
function mayConflictElsewhere(schema: SchemaView): boolean {
|
|
35
|
+
if ((schema.getUnique() ?? []).length > 0) return true;
|
|
36
|
+
|
|
37
|
+
return Object.values(schema.getFields()).some((field) => Role.of(field).isUnique);
|
|
69
38
|
}
|
|
70
39
|
|
|
71
40
|
/** Refused where it is used, naming the group that makes the inverse ambiguous. */
|
|
@@ -79,17 +48,14 @@ function refuseAmbiguousUpsert(entity: string, gesture: string): never {
|
|
|
79
48
|
}
|
|
80
49
|
|
|
81
50
|
/**
|
|
82
|
-
* The storage a member is handed inside a compensated frame: the same port, writing the same
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* `Object.create` for the same reason `StorageGuard` uses it — the storage keeps every gesture
|
|
86
|
-
* it had, including the ones this knows nothing about.
|
|
51
|
+
* The storage a member is handed inside a compensated frame: the same port, writing the same rows,
|
|
52
|
+
* leaving an inverse behind each time.
|
|
87
53
|
*/
|
|
88
|
-
export function recording<T extends object>(storage: T, entity: string,
|
|
54
|
+
export function recording<T extends object>(storage: T, entity: string, schema: SchemaView, journal: Undo[]): T {
|
|
89
55
|
const base = storage as unknown as Undoable;
|
|
90
56
|
if (typeof base.create !== 'function' || typeof base.update !== 'function') return storage;
|
|
91
57
|
|
|
92
|
-
const key = FieldSet.of(
|
|
58
|
+
const key = FieldSet.of(schema.getFields()).primary;
|
|
93
59
|
if (!key) {
|
|
94
60
|
throw new Error(
|
|
95
61
|
`${entity} declares no primary field, so a write to it cannot be taken back by ` +
|
|
@@ -121,9 +87,16 @@ export function recording<T extends object>(storage: T, entity: string, fields:
|
|
|
121
87
|
run: async () => {
|
|
122
88
|
const current = await base.findById.call(this, id);
|
|
123
89
|
if (!current) throw new Error(`${entity}#${id} is gone`);
|
|
90
|
+
// Reading and restoring are two statements, and there is no transaction here to make
|
|
91
|
+
// them one — a write landing between them is overwritten unseen. So this names what it
|
|
92
|
+
// FOUND, and claims nothing about what it did not: the frame was built because no
|
|
93
|
+
// engine could isolate it, and a check does not put the isolation back.
|
|
124
94
|
const moved = touched.filter((field) => !dequal(current[field], wrote[field]));
|
|
125
95
|
if (moved.length > 0) {
|
|
126
|
-
throw new Error(
|
|
96
|
+
throw new Error(
|
|
97
|
+
`${entity}#${id} no longer holds what this frame wrote (${moved.join(', ')}), so ` +
|
|
98
|
+
`restoring the previous values would drop whatever replaced them`,
|
|
99
|
+
);
|
|
127
100
|
}
|
|
128
101
|
await base.update.call(this, id, pick(before, touched));
|
|
129
102
|
},
|
|
@@ -159,8 +132,8 @@ export function recording<T extends object>(storage: T, entity: string, fields:
|
|
|
159
132
|
};
|
|
160
133
|
|
|
161
134
|
if (typeof base.upsert === 'function') {
|
|
162
|
-
|
|
163
|
-
if (mayConflictElsewhere(
|
|
135
|
+
recorded.upsert = async function (input, ...rest) {
|
|
136
|
+
if (mayConflictElsewhere(schema)) refuseAmbiguousUpsert(entity, 'upsert');
|
|
164
137
|
const undo = await undoUpsert.call(this, [input]);
|
|
165
138
|
const row = await base.upsert!.call(this, input, ...rest);
|
|
166
139
|
journal.push(undo);
|
|
@@ -169,8 +142,8 @@ export function recording<T extends object>(storage: T, entity: string, fields:
|
|
|
169
142
|
}
|
|
170
143
|
|
|
171
144
|
if (typeof base.upsertAll === 'function') {
|
|
172
|
-
|
|
173
|
-
if (mayConflictElsewhere(
|
|
145
|
+
recorded.upsertAll = async function (inputs, ...rest) {
|
|
146
|
+
if (mayConflictElsewhere(schema)) refuseAmbiguousUpsert(entity, 'upsertAll');
|
|
174
147
|
const undo = await undoUpsert.call(this, inputs);
|
|
175
148
|
const written = await base.upsertAll!.call(this, inputs, ...rest);
|
|
176
149
|
journal.push(undo);
|
|
@@ -181,14 +154,7 @@ export function recording<T extends object>(storage: T, entity: string, fields:
|
|
|
181
154
|
return recorded;
|
|
182
155
|
}
|
|
183
156
|
|
|
184
|
-
/**
|
|
185
|
-
* Replay the inverses, most recent first, and report rather than pretend.
|
|
186
|
-
*
|
|
187
|
-
* Every one is attempted even after one fails: stopping at the first would leave writes
|
|
188
|
-
* standing that could have been taken back. What cannot be undone is named — the caller is
|
|
189
|
-
* about to tell a user their transfer failed, and "it failed and here is what is still in
|
|
190
|
-
* the database" is the only honest version of that sentence.
|
|
191
|
-
*/
|
|
157
|
+
/** Replay the inverses, most recent first, and report rather than pretend. */
|
|
192
158
|
export async function unwind(journal: readonly Undo[], cause: unknown, log: Logger): Promise<never> {
|
|
193
159
|
const stuck: string[] = [];
|
|
194
160
|
for (const undo of [...journal].reverse()) {
|
package/src/boot/hosted.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What this app hosts — what it STATED, or what a scan FOUND.
|
|
3
|
-
*
|
|
4
|
-
* The PRESENCE of the key is the decision, the way `remotes:` states a topology: an app
|
|
5
|
-
* that passes `fronds:` is saying "do not scan", and one that passes `scan:` is handing
|
|
6
|
-
* over what a scanner read. There is no mode to configure because there is no third
|
|
7
|
-
* behaviour to name.
|
|
8
|
-
*
|
|
9
|
-
* Both may arrive, and then they MERGE — but only where a scan costs nothing at runtime.
|
|
10
|
-
* Under Nuxt the scan is a build artifact, so an app may state the frond it wants to own
|
|
11
|
-
* and leave the rest to what the build found. Anywhere the scan would run at START, half a
|
|
12
|
-
* statement buys nothing the whole one does: the disk is read either way.
|
|
13
|
-
*
|
|
14
|
-
* Merging is per frond NAME and per member. A stated frond wins outright on the members it
|
|
15
|
-
* names — stating `entities: [Post]` where a scan found `[Post, Author]` yields `[Post]`,
|
|
16
|
-
* because the point of stating is to decide. Empty is what "I named none" looks like, and
|
|
17
|
-
* `frond()` builds every member, so an empty one is filled rather than enforced.
|
|
18
|
-
*/
|
|
1
|
+
/** What this app hosts — what it STATED, or what a scan FOUND. */
|
|
19
2
|
import type { FrondDescriptor } from '../descriptor/frond.js';
|
|
20
3
|
import type { ScanResult } from '../scan/result.js';
|
|
21
4
|
import { Fronds } from '../descriptor/Fronds.js';
|
|
@@ -28,22 +11,22 @@ export interface HostedSources {
|
|
|
28
11
|
scan?: ScanResult | (() => Promise<ScanResult> | ScanResult);
|
|
29
12
|
}
|
|
30
13
|
|
|
31
|
-
/** The members a
|
|
14
|
+
/** The members a frond takes from a scan when it named none of its own. */
|
|
32
15
|
type Fillable = 'providers' | 'entities' | 'handlers' | 'presenters' | 'collectors' | 'seeds';
|
|
33
16
|
|
|
34
|
-
/** A
|
|
35
|
-
function completed(
|
|
36
|
-
if (!found) return
|
|
17
|
+
/** A frond the host passed, completed by what a scan found under the same name. */
|
|
18
|
+
function completed(given: FrondDescriptor, found: FrondDescriptor | undefined): FrondDescriptor {
|
|
19
|
+
if (!found) return given;
|
|
37
20
|
|
|
38
21
|
// Written out rather than looped: a loop over the key union asks TypeScript to prove
|
|
39
|
-
// `found[k]` fits `
|
|
22
|
+
// `found[k]` fits `given[k]` for every k at once, which it cannot — and the cast that
|
|
40
23
|
// silences it would also silence a member added to the descriptor and forgotten here.
|
|
41
24
|
const fill = <K extends Fillable>(member: K): FrondDescriptor[K] =>
|
|
42
|
-
(
|
|
25
|
+
(given[member].length === 0 ? found[member] : given[member]);
|
|
43
26
|
|
|
44
27
|
return {
|
|
45
28
|
...found,
|
|
46
|
-
...
|
|
29
|
+
...given,
|
|
47
30
|
providers: fill('providers'),
|
|
48
31
|
entities: fill('entities'),
|
|
49
32
|
handlers: fill('handlers'),
|
|
@@ -53,12 +36,7 @@ function completed(stated: FrondDescriptor, found: FrondDescriptor | undefined):
|
|
|
53
36
|
};
|
|
54
37
|
}
|
|
55
38
|
|
|
56
|
-
/**
|
|
57
|
-
* What the app hosts, and what the scan — if it ran — could not do.
|
|
58
|
-
*
|
|
59
|
-
* Neither key is EMPTY rather than refused: whether an app with no frond is legitimate
|
|
60
|
-
* depends on what else it declares, and this function is handed none of that.
|
|
61
|
-
*/
|
|
39
|
+
/** What the app hosts, and what the scan — if it ran — could not do. */
|
|
62
40
|
export async function hostedBy(sources: HostedSources): Promise<ScanResult> {
|
|
63
41
|
const scanned = sources.scan
|
|
64
42
|
? await (typeof sources.scan === 'function' ? sources.scan() : sources.scan)
|
|
@@ -67,8 +45,8 @@ export async function hostedBy(sources: HostedSources): Promise<ScanResult> {
|
|
|
67
45
|
if (!sources.fronds) return scanned ?? { fronds: Fronds.hosting([]), diagnostics: [] };
|
|
68
46
|
|
|
69
47
|
const found = scanned?.fronds ?? [];
|
|
70
|
-
const
|
|
71
|
-
const
|
|
48
|
+
const configured = sources.fronds.map((f) => completed(f, found.find((s) => s.name === f.name)));
|
|
49
|
+
const discovered = found.filter((f) => !sources.fronds!.some((s) => s.name === f.name));
|
|
72
50
|
|
|
73
|
-
return { fronds: Fronds.hosting([...
|
|
51
|
+
return { fronds: Fronds.hosting([...configured, ...discovered]), diagnostics: scanned?.diagnostics ?? [] };
|
|
74
52
|
}
|
package/src/boot/ownership.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { lowerFirst } from '@fougere/schema';
|
|
2
2
|
import type { FrondDescriptor, ProviderEntry } from '../descriptor/frond.js';
|
|
3
|
+
import { inheritsCrud } from '../prefab/crud.js';
|
|
3
4
|
import { targetOf } from '../prefab/prefab.js';
|
|
4
5
|
import { ownedBy, repositoryKeyOf } from '../prefab/repository.js';
|
|
5
6
|
import { entityOfStorageKey } from '../storage.js';
|
|
6
7
|
|
|
7
|
-
/**
|
|
8
|
-
* Who owns an entity's storage.
|
|
9
|
-
*
|
|
10
|
-
* `Repository(Commande, Stock)` states it — an aggregate is the only thing that claims
|
|
11
|
-
* entities it is not named after, and the arity is what says so. A repository of ONE owns
|
|
12
|
-
* nothing: a boundary between one thing and nothing is not a boundary, and the judge is
|
|
13
|
-
* already on that entity's rows.
|
|
14
|
-
*/
|
|
8
|
+
/** Who owns an entity's storage. */
|
|
15
9
|
export function ownersOf(providers: readonly ProviderEntry[]): Map<string, string> {
|
|
16
10
|
const owners = new Map<string, string>();
|
|
17
11
|
for (const provider of providers) {
|
|
@@ -46,21 +40,7 @@ function builtOn(ctor: unknown): string[] {
|
|
|
46
40
|
return target?.name ? [lowerFirst(target.name)] : [];
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
/**
|
|
50
|
-
* `Storage<E>` is not a word of the user's vocabulary — `<E>Repository` is the one way in.
|
|
51
|
-
*
|
|
52
|
-
* A door judges and projects; a HOLDER keeps the storage. So the rule is not about which
|
|
53
|
-
* directory a file sits in but about which of the two a class is: a handler, a presenter and
|
|
54
|
-
* a collector may never name the port, and a provider may name only the storage of what its
|
|
55
|
-
* prefab was built on — which is `Repository` and `Mirror`, without either being named here.
|
|
56
|
-
*
|
|
57
|
-
* What it buys beyond one word instead of two: an entity that becomes owned later needs no
|
|
58
|
-
* call site to move, because none of them ever spelled the storage.
|
|
59
|
-
*
|
|
60
|
-
* `known` answers what the key's suffix cannot: `FileStorage` is an ordinary class name.
|
|
61
|
-
*
|
|
62
|
-
* Refused at boot rather than reported by `verify`, which nothing calls at startup.
|
|
63
|
-
*/
|
|
43
|
+
/** `Storage<E>` is not a word of the user's vocabulary — `<E>Repository` is the one way in. */
|
|
64
44
|
export function refuseStorageInUserCode(
|
|
65
45
|
frond: FrondDescriptor,
|
|
66
46
|
owners: Map<string, string>,
|
|
@@ -103,25 +83,11 @@ export function refuseStorageInUserCode(
|
|
|
103
83
|
}
|
|
104
84
|
}
|
|
105
85
|
|
|
106
|
-
/**
|
|
107
|
-
* An owned entity has no automatic CRUD — said at boot, not at the first request.
|
|
108
|
-
*
|
|
109
|
-
* `HandlerFacade.deps()` asks for `<E>Repository` when a handler inherits the five gestures
|
|
110
|
-
* and declares no constructor of its own, and an owned entity has no such key. That alone
|
|
111
|
-
* refuses — but LAZILY, at the first call, on the container's own sentence: measured, the app
|
|
112
|
-
* booted clean and answered every request with `'LedgerRepository' is not registered`. A
|
|
113
|
-
* receiver that starts and then rejects everything is found in production, which is the
|
|
114
|
-
* reason `serve()` checks its address at boot rather than per call.
|
|
115
|
-
*
|
|
116
|
-
* Recognized by FORM, like the façade recognizes it: a prototype carrying `list` and
|
|
117
|
-
* `findById` needs storage of its own, whether `Crud()` put them there or an author did.
|
|
118
|
-
*/
|
|
86
|
+
/** An owned entity has no automatic CRUD — said at boot, not at the first request. */
|
|
119
87
|
export function refuseCrudOnOwned(frond: FrondDescriptor, owners: Map<string, string>): void {
|
|
120
88
|
for (const handler of frond.handlers) {
|
|
121
89
|
const owner = owners.get(handler.address);
|
|
122
|
-
if (!owner || handler.deps.length > 0) continue;
|
|
123
|
-
const proto = (handler.ctor as { prototype?: Record<string, unknown> }).prototype;
|
|
124
|
-
if (typeof proto?.list !== 'function' || typeof proto?.findById !== 'function') continue;
|
|
90
|
+
if (!owner || handler.deps.length > 0 || !inheritsCrud(handler.ctor)) continue;
|
|
125
91
|
|
|
126
92
|
throw new Error(
|
|
127
93
|
`[aggregate] ${handler.ctor.name} takes the five gestures on ${handler.address}, `
|
package/src/boot/ports.ts
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import type { ProviderEntry } from '../descriptor/frond.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* A port is a class something already answers under. Nothing declares one — the
|
|
5
|
-
* prototype chain states it, so `class StripePayment extends Payment` IS the whole
|
|
6
|
-
* registration, and so is `class MyLogger extends Logger` over a builtin.
|
|
7
|
-
*
|
|
8
|
-
* This is the fourth reading of the rule the other three already apply: the type
|
|
9
|
-
* names the SUBJECT (`Storage<E>`, `Emit<F>`, `Facade<H>`) and the container
|
|
10
|
-
* holds the realization. Providers were the one case where the type named the
|
|
11
|
-
* realization instead, so `constructor(private payment: Payment)` resolved to the
|
|
12
|
-
* base class and a handler got an object whose method did not exist.
|
|
13
|
-
*
|
|
14
|
-
* Only the DIRECT base binds. A deeper chain binds each link to its own child, and
|
|
15
|
-
* a case that wants otherwise states it in `ports:` — which wins over all of this.
|
|
16
|
-
*/
|
|
3
|
+
/** A port is a class something already answers under. */
|
|
17
4
|
export function portBindings(
|
|
18
5
|
providers: ProviderEntry[],
|
|
19
6
|
answers: (name: string) => boolean,
|
package/src/boot/remote.ts
CHANGED
|
@@ -1,32 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Remote façade — what resolve() falls back to.
|
|
3
|
-
*
|
|
4
|
-
* When a handler isn't hosted locally and remotes are declared, resolve()
|
|
5
|
-
* returns a façade-shaped stand-in: same call surface as a local facade,
|
|
6
|
-
* every operation executed through a Transport. Routing is lazy — on the
|
|
7
|
-
* first miss, each declared remote is asked what it hosts (rpc.discover)
|
|
8
|
-
* and the answer is cached. A remote that can't be reached stays pending
|
|
9
|
-
* and is retried on the next miss instead of being cached as absent.
|
|
10
|
-
*/
|
|
1
|
+
/** Remote façade — what resolve() falls back to. */
|
|
11
2
|
import type { FrondCall, Transport } from '../wire/call.js';
|
|
12
3
|
import { assertIdentityCard, RPC_ENTITY } from '../wire/call.js';
|
|
13
4
|
import { runMiddlewares, type AppMiddleware, type OperationContext } from '../wire/middleware.js';
|
|
14
|
-
import { EMPTY_INVOCATION, type InvocationContext } from '../
|
|
5
|
+
import { EMPTY_INVOCATION, type InvocationContext } from '../wire/Invocation.js';
|
|
15
6
|
import { FougereError, ErrorCode } from '../wire/errors.js';
|
|
16
7
|
import { Card, type SchemaView, type SchemaDescriptor } from '@fougere/schema';
|
|
17
|
-
import {
|
|
8
|
+
import { dynamicOperations } from '../entry/facade.js';
|
|
18
9
|
|
|
19
10
|
interface Route {
|
|
20
11
|
frond: string;
|
|
21
12
|
transport: Transport;
|
|
22
13
|
/**
|
|
23
|
-
* The entity's schema, rebuilt from the identity card — the same
|
|
24
|
-
* `
|
|
25
|
-
* included. Reconstructed once per entity, at discovery time.
|
|
26
|
-
*
|
|
27
|
-
* **Absent when the door stores nothing.** A handler may carry no entity, so the card
|
|
28
|
-
* publishes it with ops and no shape; there is nothing to rebuild and pretending
|
|
29
|
-
* otherwise would hand callers an empty schema that validates everything.
|
|
14
|
+
* The entity's schema, rebuilt from the identity card — the same `SchemaConstructor` shape
|
|
15
|
+
* `entity({...})` produces, live validation included.
|
|
30
16
|
*/
|
|
31
17
|
schema?: SchemaView;
|
|
32
18
|
}
|
|
@@ -79,27 +65,13 @@ export function createRemoteRouter(
|
|
|
79
65
|
// adding one here would answer a call with a transport to a door that
|
|
80
66
|
// does not exist.
|
|
81
67
|
for (const door of frond.doors) {
|
|
82
|
-
const
|
|
83
|
-
/**
|
|
84
|
-
|
|
85
|
-
*
|
|
86
|
-
* `byEntity` is keyed by the door name alone, so the second claim used to be
|
|
87
|
-
* dropped with `if (!byEntity.has(...))` — no warning, and the winner was
|
|
88
|
-
* whichever remote answered first. The local boot already refuses the same
|
|
89
|
-
* collision (`assertOneOwnerPerKey`) and it refused the OTHER duplicate: in
|
|
90
|
-
* process the last frond loaded won, here the first discovered did. One
|
|
91
|
-
* application, two topologies, two different handlers answering — which is
|
|
92
|
-
* precisely the gradient not holding.
|
|
93
|
-
*
|
|
94
|
-
* Refusing is the honest answer while a call names an entity and not a frond.
|
|
95
|
-
* `FrondCall` already carries an optional `frond`; the day it is required, this
|
|
96
|
-
* becomes a disambiguation instead of a refusal.
|
|
97
|
-
*/
|
|
98
|
-
if (held !== undefined && held !== label) {
|
|
68
|
+
const first = claimedBy.get(door.name);
|
|
69
|
+
/** Two remotes claiming one name is refused, not silently arbitrated. */
|
|
70
|
+
if (first !== undefined && first !== label) {
|
|
99
71
|
throw new FougereError({
|
|
100
72
|
code: ErrorCode.INTERNAL_ERROR,
|
|
101
73
|
message:
|
|
102
|
-
`Two remotes serve '${door.name}': '${
|
|
74
|
+
`Two remotes serve '${door.name}': '${first}' and '${label}'.\n`
|
|
103
75
|
+ ` A call names an entity, not a frond, so nothing could choose between them.\n`
|
|
104
76
|
+ ` - Keep one of the two out of \`remotes:\`, or\n`
|
|
105
77
|
+ ` - expose one of them under a different entity name.`,
|
|
@@ -140,26 +112,7 @@ export function createRemoteRouter(
|
|
|
140
112
|
|
|
141
113
|
type Facade = Record<string, (invocation?: InvocationContext) => Promise<unknown>>;
|
|
142
114
|
|
|
143
|
-
/**
|
|
144
|
-
* Façade-shaped stand-in — the consumer can't tell it from a local facade.
|
|
145
|
-
*
|
|
146
|
-
* Every trap answers the same question, and that is the point: the runner asks
|
|
147
|
-
* `Object.hasOwn(facade, op)` before calling, so a proxy that only trapped `get`
|
|
148
|
-
* reported *no* operations and every split call came back `Unknown operation` —
|
|
149
|
-
* `get` said yes, `hasOwn` said no, and the runner believed `hasOwn`.
|
|
150
|
-
*
|
|
151
|
-
* The stand-in claims every legal op name because it cannot know better: routing is
|
|
152
|
-
* lazy on purpose (the card is fetched at the first miss), and the remote is the
|
|
153
|
-
* authority on its own surface anyway. An op it does not serve comes back as its
|
|
154
|
-
* NOT_FOUND — judged where it is owned, which is the same answer a local façade gives.
|
|
155
|
-
*
|
|
156
|
-
* It runs the app's middlewares, like `HandlerFacade` does, because "the consumer can't
|
|
157
|
-
* tell it from a local facade" was false of the one thing a consumer installs: measured,
|
|
158
|
-
* `runMiddlewares` had a single caller, so a frond that moved lost every middleware on
|
|
159
|
-
* the calling side — no log, no retry, no cache — from a `remotes:` line alone.
|
|
160
|
-
* The invocation the transport sends is the one the chain leaves behind, so a middleware
|
|
161
|
-
* can still put something on the wire.
|
|
162
|
-
*/
|
|
115
|
+
/** Façade-shaped stand-in — the consumer can't tell it from a local facade. */
|
|
163
116
|
export function createRemoteFacade(
|
|
164
117
|
entity: string,
|
|
165
118
|
router: RemoteRouter,
|
|
@@ -175,5 +128,5 @@ export function createRemoteFacade(
|
|
|
175
128
|
transport(call, ctx.invocation ?? invocation));
|
|
176
129
|
};
|
|
177
130
|
|
|
178
|
-
return
|
|
131
|
+
return dynamicOperations(opFn) as Facade;
|
|
179
132
|
}
|
package/src/boot/runner.ts
CHANGED
|
@@ -1,33 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A Transport built from an app — the two ways a call enters this process.
|
|
3
|
-
*
|
|
4
|
-
* `Transport` is `wire/`'s shape; making one needs an App and the transport entry.
|
|
5
|
-
*/
|
|
1
|
+
/** A Transport built from an app — the two ways a call enters this process. */
|
|
6
2
|
import type { App } from './types.js';
|
|
7
3
|
import type { Transport } from '../wire/call.js';
|
|
8
|
-
import { createTransportEntry } from '../entry/
|
|
4
|
+
import { createTransportEntry } from '../entry/transport.js';
|
|
9
5
|
|
|
10
|
-
/**
|
|
11
|
-
* Build the local runner — the reference realization of Transport.
|
|
12
|
-
*
|
|
13
|
-
* Resolves strictly from the app's own container: a call that lands here is
|
|
14
|
-
* judged here. A miss is a typed NOT_FOUND, never a forward to another remote.
|
|
15
|
-
*/
|
|
6
|
+
/** Build the local runner — the reference realization of Transport. */
|
|
16
7
|
export function createLocalRunner(app: App, surface?: string): Transport {
|
|
17
8
|
return createTransportEntry(app.local, surface);
|
|
18
9
|
}
|
|
19
10
|
|
|
20
11
|
/**
|
|
21
|
-
* Build the app runner — same
|
|
22
|
-
*
|
|
23
|
-
* an app's own entry points (browser endpoint, bridges) stand on.
|
|
24
|
-
*
|
|
25
|
-
* `surface` is the audience this runner serves, and it belongs to the DOOR that
|
|
26
|
-
* builds the runner, never to the call: a caller cannot name its own audience
|
|
27
|
-
* any more than it can name its own identity (`state` is stamped server-side
|
|
28
|
-
* for the same reason). Reaching the admin door IS the proof. So `FrondCall`
|
|
29
|
-
* gains nothing and the wire format gains nothing — a remote frond's audience
|
|
30
|
-
* is simply which URL `remotes:` points at.
|
|
12
|
+
* Build the app runner — same verdict, but resolution follows the app's topology: local façades
|
|
13
|
+
* and remote doublures alike.
|
|
31
14
|
*/
|
|
32
15
|
export function createAppRunner(app: App, surface?: string): Transport {
|
|
33
16
|
return createTransportEntry(app, surface);
|
package/src/boot/seed.ts
CHANGED
|
@@ -4,22 +4,7 @@ import type { FrondDescriptor, SeedEntry, SeedFactory } from '../descriptor/fron
|
|
|
4
4
|
import type { App } from './types.js';
|
|
5
5
|
import type { Extension } from './AppLifecycle.js';
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Seeds in dependency order — a `ref()` target is planted before its referrer.
|
|
9
|
-
*
|
|
10
|
-
* The order is a fact about the entity graph, not about the surface running the seeds,
|
|
11
|
-
* so it is stated once here. The Nuxt module read it off a pairwise comparator (which
|
|
12
|
-
* `Array.sort` cannot make transitive: `a` before `b` and `b` before `c` never implies
|
|
13
|
-
* `a` before `c`), and `boot()` had no order at all — the same fact, told twice and
|
|
14
|
-
* wrong both times. A list seeded before its owner failed on the foreign key, and the
|
|
15
|
-
* driver's error named neither the entity nor the file.
|
|
16
|
-
*
|
|
17
|
-
* Kahn, like `orderTables` in `@fougere/adapter-sql` — the same shape one level up: there
|
|
18
|
-
* the nodes are tables and the edges FK columns, here they are seeds and the edges the
|
|
19
|
-
* `one` relations of the entities they target. A cycle cannot be satisfied by ordering,
|
|
20
|
-
* so its remaining seeds keep their scan order and land last: the driver refuses what is
|
|
21
|
-
* genuinely impossible, and everything acyclic around it still gets planted.
|
|
22
|
-
*/
|
|
7
|
+
/** Seeds in dependency order — a `ref()` target is planted before its referrer. */
|
|
23
8
|
export function orderSeeds(fronds: FrondDescriptor[]): SeedEntry[] {
|
|
24
9
|
const refs = new Map<string, Set<string>>();
|
|
25
10
|
for (const frond of fronds) {
|
|
@@ -69,14 +54,7 @@ interface SeedDoor {
|
|
|
69
54
|
write(item: unknown): Promise<unknown>;
|
|
70
55
|
}
|
|
71
56
|
|
|
72
|
-
/**
|
|
73
|
-
* Plant a set of seeds, in the order given. Reports what it did, one line per entity.
|
|
74
|
-
*
|
|
75
|
-
* The one seeding loop. `boot()` had one and the Nuxt module generated a second into its
|
|
76
|
-
* Nitro plugin, which had drifted: no storage fallback, so an entity with no façade was
|
|
77
|
-
* skipped there and planted here. Two answers to "how does a row get in at boot" is one
|
|
78
|
-
* too many, and the second was the one running in the browser.
|
|
79
|
-
*/
|
|
57
|
+
/** Plant a set of seeds, in the order given. */
|
|
80
58
|
export async function runSeeds(
|
|
81
59
|
app: App,
|
|
82
60
|
seeds: SeedEntry[],
|
|
@@ -114,11 +92,7 @@ export async function runSeeds(
|
|
|
114
92
|
}
|
|
115
93
|
}
|
|
116
94
|
|
|
117
|
-
/**
|
|
118
|
-
* A seed is not a client: it writes at boot, from inside. The façade is used when the
|
|
119
|
-
* entity declares one (its judge catches a bad seed early), the storage when it does
|
|
120
|
-
* not — an entity that exposes nothing is still an entity whose reference rows must land.
|
|
121
|
-
*/
|
|
95
|
+
/** A seed is not a client. */
|
|
122
96
|
function doorFor(app: App, entityName: string): SeedDoor | undefined {
|
|
123
97
|
let handler: Record<string, Function> | undefined;
|
|
124
98
|
try { handler = app.resolve<Record<string, Function>>(facadeKeyOf(entityName)); } catch {}
|
|
@@ -126,7 +100,7 @@ function doorFor(app: App, entityName: string): SeedDoor | undefined {
|
|
|
126
100
|
if (typeof handler?.list === 'function' && typeof handler.create === 'function') {
|
|
127
101
|
return {
|
|
128
102
|
list: () => handler!.list() as Promise<unknown[]>,
|
|
129
|
-
write: (item) => handler!.create({ params: {}, query: {},
|
|
103
|
+
write: (item) => handler!.create({ params: {}, query: {}, input: item, state: {} }),
|
|
130
104
|
};
|
|
131
105
|
}
|
|
132
106
|
|
|
@@ -139,13 +113,8 @@ function doorFor(app: App, entityName: string): SeedDoor | undefined {
|
|
|
139
113
|
}
|
|
140
114
|
|
|
141
115
|
/**
|
|
142
|
-
* The framework's own ascent for rows, named — so a host can REPLACE it rather than take
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* That is what Nuxt's Nitro plugin had to do: a bundler needs its seed modules spelled out
|
|
146
|
-
* as static imports, so the plugin claimed everything after the boot and its copy of the
|
|
147
|
-
* loop drifted. It now declares an extension under this same name instead, and the delta
|
|
148
|
-
* is one member of a list.
|
|
116
|
+
* The framework's own ascent for rows, named — so a host can REPLACE it rather than take over the
|
|
117
|
+
* whole post-boot to get its own.
|
|
149
118
|
*/
|
|
150
119
|
export function seeding(report?: (message: string) => void): Extension {
|
|
151
120
|
return {
|
|
@@ -1,36 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Where a STATED contract and the signature it is about have stopped agreeing.
|
|
3
|
-
*
|
|
4
|
-
* `frond.config.ts` states an operation's contract and wins over the scan — that order is
|
|
5
|
-
* deliberate, and it is the only answer for a method inherited from an installed base class
|
|
6
|
-
* the workspace scan cannot see. But winning silently is how a statement made about
|
|
7
|
-
* `publish(id: string)` keeps applying after the parameter was renamed to `postId`: the
|
|
8
|
-
* façade binds what the config said, the method receives `undefined`, and nothing anywhere
|
|
9
|
-
* says the two disagree.
|
|
10
|
-
*
|
|
11
|
-
* So this compares, and only where BOTH exist — a statement about a signature the scan
|
|
12
|
-
* never read is not drift, it is the case config was built for. It is a `warning` and not
|
|
13
|
-
* a refusal: the statement is still the author's word, and a boot that ran yesterday must
|
|
14
|
-
* not stop running because a parameter moved. What it must not do is stay quiet.
|
|
15
|
-
*/
|
|
1
|
+
/** Where a STATED contract and the signature it is about have stopped agreeing. */
|
|
16
2
|
import type { FrondDescriptor, HandlerEntry } from '../descriptor/frond.js';
|
|
17
3
|
import type { ScanDiagnostic } from '../scan/result.js';
|
|
18
4
|
import type { BindingPlan } from '../wire/binding.js';
|
|
19
5
|
import type { Signature } from '../wire/signature.js';
|
|
20
6
|
|
|
21
|
-
/** The parameters a
|
|
22
|
-
function namesDisagreeing(
|
|
7
|
+
/** The parameters a binding plan names, against the ones the method declares. */
|
|
8
|
+
function namesDisagreeing(plan: BindingPlan, signature: Signature): string[] {
|
|
23
9
|
const declared = new Set(signature.params.map((p: { name: string }) => p.name));
|
|
24
10
|
|
|
25
|
-
return
|
|
11
|
+
return plan.map((b) => b.name).filter((name) => !declared.has(name));
|
|
26
12
|
}
|
|
27
13
|
|
|
28
|
-
/**
|
|
29
|
-
* What a frond's stated contracts no longer match.
|
|
30
|
-
*
|
|
31
|
-
* Read by `resolveEffectiveOperations`, so the same answer reaches `fougere check` and a
|
|
32
|
-
* boot — one comparison, two readers, no second opinion to drift on its own.
|
|
33
|
-
*/
|
|
14
|
+
/** What a frond's stated contracts no longer match. */
|
|
34
15
|
export function statementDrift(frond: FrondDescriptor, handler: HandlerEntry): ScanDiagnostic[] {
|
|
35
16
|
const found: ScanDiagnostic[] = [];
|
|
36
17
|
|