@fougere/core 0.2.0-alpha.1 → 0.3.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 +2 -1
- package/dist/boot/AppLifecycle.d.ts +18 -0
- package/dist/boot/AppLifecycle.d.ts.map +1 -0
- package/dist/boot/AppLifecycle.js +42 -0
- package/dist/boot/AppLifecycle.js.map +1 -0
- package/dist/boot/Emissions.d.ts +126 -0
- package/dist/boot/Emissions.d.ts.map +1 -0
- package/dist/boot/Emissions.js +233 -0
- package/dist/boot/Emissions.js.map +1 -0
- package/dist/boot/HandlerFacade.d.ts +72 -0
- package/dist/boot/HandlerFacade.d.ts.map +1 -0
- package/dist/boot/HandlerFacade.js +174 -0
- package/dist/boot/HandlerFacade.js.map +1 -0
- package/dist/boot/Lifecycle.d.ts +4 -0
- package/dist/boot/Lifecycle.d.ts.map +1 -0
- package/dist/boot/Lifecycle.js +3 -0
- package/dist/boot/Lifecycle.js.map +1 -0
- package/dist/boot/ambient-port.d.ts +38 -0
- package/dist/boot/ambient-port.d.ts.map +1 -0
- package/dist/boot/ambient-port.js +2 -0
- package/dist/boot/ambient-port.js.map +1 -0
- package/dist/boot/ambient.als.d.ts +3 -0
- package/dist/boot/ambient.als.d.ts.map +1 -0
- package/dist/boot/ambient.als.js +34 -0
- package/dist/boot/ambient.als.js.map +1 -0
- package/dist/boot/ambient.queue.d.ts +10 -0
- package/dist/boot/ambient.queue.d.ts.map +1 -0
- package/dist/boot/ambient.queue.js +60 -0
- package/dist/boot/ambient.queue.js.map +1 -0
- package/dist/boot/apply.d.ts +22 -0
- package/dist/boot/apply.d.ts.map +1 -0
- package/dist/boot/apply.js +48 -0
- package/dist/boot/apply.js.map +1 -0
- package/dist/boot/auth.d.ts +53 -0
- package/dist/boot/auth.d.ts.map +1 -0
- package/dist/boot/auth.js +2 -0
- package/dist/boot/auth.js.map +1 -0
- package/dist/{binding.d.ts → boot/binding.d.ts} +14 -17
- package/dist/boot/binding.d.ts.map +1 -0
- package/dist/{binding.js → boot/binding.js} +19 -10
- package/dist/boot/binding.js.map +1 -0
- package/dist/{boot.d.ts → boot/boot.d.ts} +25 -5
- package/dist/boot/boot.d.ts.map +1 -0
- package/dist/boot/boot.js +70 -0
- package/dist/boot/boot.js.map +1 -0
- package/dist/boot/bootstrap.d.ts.map +1 -0
- package/dist/boot/bootstrap.js +721 -0
- package/dist/boot/bootstrap.js.map +1 -0
- package/dist/boot/egress.d.ts +8 -0
- package/dist/boot/egress.d.ts.map +1 -0
- package/dist/boot/egress.js +11 -0
- package/dist/boot/egress.js.map +1 -0
- package/dist/boot/frame.d.ts +44 -0
- package/dist/boot/frame.d.ts.map +1 -0
- package/dist/boot/frame.js +181 -0
- package/dist/boot/frame.js.map +1 -0
- package/dist/boot/ownership.d.ts +42 -0
- package/dist/boot/ownership.d.ts.map +1 -0
- package/dist/boot/ownership.js +127 -0
- package/dist/boot/ownership.js.map +1 -0
- package/dist/boot/ports.d.ts +17 -0
- package/dist/boot/ports.d.ts.map +1 -0
- package/dist/boot/ports.js +57 -0
- package/dist/boot/ports.js.map +1 -0
- package/dist/{remote.d.ts → boot/remote.d.ts} +13 -5
- package/dist/boot/remote.d.ts.map +1 -0
- package/dist/{remote.js → boot/remote.js} +24 -26
- package/dist/boot/remote.js.map +1 -0
- package/dist/{seed.d.ts → boot/seed.d.ts} +14 -2
- package/dist/boot/seed.d.ts.map +1 -0
- package/dist/{seed.js → boot/seed.js} +25 -4
- package/dist/boot/seed.js.map +1 -0
- package/dist/boot/together.d.ts +26 -0
- package/dist/boot/together.d.ts.map +1 -0
- package/dist/boot/together.js +163 -0
- package/dist/boot/together.js.map +1 -0
- package/dist/boot/types.d.ts +260 -0
- package/dist/boot/types.d.ts.map +1 -0
- package/dist/boot/types.js.map +1 -0
- package/dist/builtins/config.d.ts +9 -0
- package/dist/builtins/config.d.ts.map +1 -1
- package/dist/builtins/config.js +16 -1
- package/dist/builtins/config.js.map +1 -1
- package/dist/builtins/logger.d.ts +37 -4
- package/dist/builtins/logger.d.ts.map +1 -1
- package/dist/builtins/logger.js +66 -7
- package/dist/builtins/logger.js.map +1 -1
- package/dist/config-loader.d.ts +62 -38
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +15 -54
- package/dist/config-loader.js.map +1 -1
- package/dist/contract/Call.d.ts +10 -0
- package/dist/contract/Call.d.ts.map +1 -0
- package/dist/contract/Call.js +15 -0
- package/dist/contract/Call.js.map +1 -0
- package/dist/contract/Invocation.d.ts +27 -0
- package/dist/contract/Invocation.d.ts.map +1 -0
- package/dist/contract/Invocation.js +59 -0
- package/dist/contract/Invocation.js.map +1 -0
- package/dist/contract/RouteAddress.d.ts +17 -0
- package/dist/contract/RouteAddress.d.ts.map +1 -0
- package/dist/contract/RouteAddress.js +38 -0
- package/dist/contract/RouteAddress.js.map +1 -0
- package/dist/contract.d.ts +25 -19
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +25 -10
- package/dist/contract.js.map +1 -1
- package/dist/crypto/encoding.d.ts +25 -0
- package/dist/crypto/encoding.d.ts.map +1 -0
- package/dist/crypto/encoding.js +58 -0
- package/dist/crypto/encoding.js.map +1 -0
- package/dist/crypto/node.d.ts +4 -0
- package/dist/crypto/node.d.ts.map +1 -0
- package/dist/crypto/node.js +25 -0
- package/dist/crypto/node.js.map +1 -0
- package/dist/crypto/port.d.ts +42 -0
- package/dist/crypto/port.d.ts.map +1 -0
- package/dist/crypto/port.js +19 -0
- package/dist/crypto/port.js.map +1 -0
- package/dist/crypto/webcrypto.d.ts +4 -0
- package/dist/crypto/webcrypto.d.ts.map +1 -0
- package/dist/crypto/webcrypto.js +34 -0
- package/dist/crypto/webcrypto.js.map +1 -0
- package/dist/dispatch/ArgumentResolver.d.ts +10 -0
- package/dist/dispatch/ArgumentResolver.d.ts.map +1 -0
- package/dist/dispatch/ArgumentResolver.js +12 -0
- package/dist/dispatch/ArgumentResolver.js.map +1 -0
- package/dist/dispatch/ArrayResult.d.ts +3 -0
- package/dist/dispatch/ArrayResult.d.ts.map +1 -0
- package/dist/dispatch/ArrayResult.js +11 -0
- package/dist/dispatch/ArrayResult.js.map +1 -0
- package/dist/dispatch/DispatchEvent.d.ts +18 -0
- package/dist/dispatch/DispatchEvent.d.ts.map +1 -0
- package/dist/dispatch/DispatchEvent.js +30 -0
- package/dist/dispatch/DispatchEvent.js.map +1 -0
- package/dist/dispatch/DispatchLifecycle.d.ts +9 -0
- package/dist/dispatch/DispatchLifecycle.d.ts.map +1 -0
- package/dist/dispatch/DispatchLifecycle.js +25 -0
- package/dist/dispatch/DispatchLifecycle.js.map +1 -0
- package/dist/dispatch/DispatchPort.d.ts +6 -0
- package/dist/dispatch/DispatchPort.d.ts.map +1 -0
- package/dist/dispatch/DispatchPort.js +2 -0
- package/dist/dispatch/DispatchPort.js.map +1 -0
- package/dist/dispatch/Dispatcher.d.ts +16 -0
- package/dist/dispatch/Dispatcher.d.ts.map +1 -0
- package/dist/dispatch/Dispatcher.js +44 -0
- package/dist/dispatch/Dispatcher.js.map +1 -0
- package/dist/dispatch/InFlight.d.ts +12 -0
- package/dist/dispatch/InFlight.d.ts.map +1 -0
- package/dist/dispatch/InFlight.js +46 -0
- package/dist/dispatch/InFlight.js.map +1 -0
- package/dist/dispatch/InputValidator.d.ts +7 -0
- package/dist/dispatch/InputValidator.d.ts.map +1 -0
- package/dist/dispatch/InputValidator.js +21 -0
- package/dist/dispatch/InputValidator.js.map +1 -0
- package/dist/dispatch/LocalRoutePolicy.d.ts +11 -0
- package/dist/dispatch/LocalRoutePolicy.d.ts.map +1 -0
- package/dist/dispatch/LocalRoutePolicy.js +32 -0
- package/dist/dispatch/LocalRoutePolicy.js.map +1 -0
- package/dist/dispatch/OperationExecutor.d.ts +25 -0
- package/dist/dispatch/OperationExecutor.d.ts.map +1 -0
- package/dist/dispatch/OperationExecutor.js +32 -0
- package/dist/dispatch/OperationExecutor.js.map +1 -0
- package/dist/dispatch/OperationRoute.d.ts +13 -0
- package/dist/dispatch/OperationRoute.d.ts.map +1 -0
- package/dist/dispatch/OperationRoute.js +15 -0
- package/dist/dispatch/OperationRoute.js.map +1 -0
- package/dist/dispatch/OutputProjector.d.ts +12 -0
- package/dist/dispatch/OutputProjector.d.ts.map +1 -0
- package/dist/dispatch/OutputProjector.js +30 -0
- package/dist/dispatch/OutputProjector.js.map +1 -0
- package/dist/dispatch/OutputView.d.ts +8 -0
- package/dist/dispatch/OutputView.d.ts.map +1 -0
- package/dist/dispatch/OutputView.js +10 -0
- package/dist/dispatch/OutputView.js.map +1 -0
- package/dist/dispatch/PresenterArgumentResolver.d.ts +12 -0
- package/dist/dispatch/PresenterArgumentResolver.d.ts.map +1 -0
- package/dist/dispatch/PresenterArgumentResolver.js +20 -0
- package/dist/dispatch/PresenterArgumentResolver.js.map +1 -0
- package/dist/dispatch/PresenterExecutor.d.ts +11 -0
- package/dist/dispatch/PresenterExecutor.d.ts.map +1 -0
- package/dist/dispatch/PresenterExecutor.js +56 -0
- package/dist/dispatch/PresenterExecutor.js.map +1 -0
- package/dist/dispatch/RemoteRouteResolver.d.ts +13 -0
- package/dist/dispatch/RemoteRouteResolver.d.ts.map +1 -0
- package/dist/dispatch/RemoteRouteResolver.js +18 -0
- package/dist/dispatch/RemoteRouteResolver.js.map +1 -0
- package/dist/dispatch/Route.d.ts +10 -0
- package/dist/dispatch/Route.d.ts.map +1 -0
- package/dist/dispatch/Route.js +2 -0
- package/dist/dispatch/Route.js.map +1 -0
- package/dist/dispatch/RouteNotFoundError.d.ts +10 -0
- package/dist/dispatch/RouteNotFoundError.d.ts.map +1 -0
- package/dist/dispatch/RouteNotFoundError.js +24 -0
- package/dist/dispatch/RouteNotFoundError.js.map +1 -0
- package/dist/dispatch/RoutePolicy.d.ts +8 -0
- package/dist/dispatch/RoutePolicy.d.ts.map +1 -0
- package/dist/dispatch/RoutePolicy.js +2 -0
- package/dist/dispatch/RoutePolicy.js.map +1 -0
- package/dist/dispatch/RouteRegistry.d.ts +18 -0
- package/dist/dispatch/RouteRegistry.d.ts.map +1 -0
- package/dist/dispatch/RouteRegistry.js +62 -0
- package/dist/dispatch/RouteRegistry.js.map +1 -0
- package/dist/dispatch/RouteResolver.d.ts +7 -0
- package/dist/dispatch/RouteResolver.d.ts.map +1 -0
- package/dist/dispatch/RouteResolver.js +2 -0
- package/dist/dispatch/RouteResolver.js.map +1 -0
- package/dist/dispatch/StorageGuard.d.ts +15 -0
- package/dist/dispatch/StorageGuard.d.ts.map +1 -0
- package/dist/dispatch/StorageGuard.js +63 -0
- package/dist/dispatch/StorageGuard.js.map +1 -0
- package/dist/effective-operation.d.ts +90 -0
- package/dist/effective-operation.d.ts.map +1 -0
- package/dist/effective-operation.js +450 -0
- package/dist/effective-operation.js.map +1 -0
- package/dist/emit.js +2 -2
- package/dist/emit.js.map +1 -1
- package/dist/entry/DynamicFacade.d.ts +10 -0
- package/dist/entry/DynamicFacade.d.ts.map +1 -0
- package/dist/entry/DynamicFacade.js +27 -0
- package/dist/entry/DynamicFacade.js.map +1 -0
- package/dist/entry/FacadeEntry.d.ts +11 -0
- package/dist/entry/FacadeEntry.d.ts.map +1 -0
- package/dist/entry/FacadeEntry.js +26 -0
- package/dist/entry/FacadeEntry.js.map +1 -0
- package/dist/entry/TransportEntry.d.ts +13 -0
- package/dist/entry/TransportEntry.d.ts.map +1 -0
- package/dist/entry/TransportEntry.js +24 -0
- package/dist/entry/TransportEntry.js.map +1 -0
- package/dist/frond-config.d.ts +38 -8
- package/dist/frond-config.d.ts.map +1 -1
- package/dist/frond-config.js.map +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/graph.d.ts.map +1 -1
- package/dist/graph.js +3 -2
- package/dist/graph.js.map +1 -1
- package/dist/identity-keys.d.ts +14 -0
- package/dist/identity-keys.d.ts.map +1 -0
- package/dist/identity-keys.js +37 -0
- package/dist/identity-keys.js.map +1 -0
- package/dist/identity.d.ts +58 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +182 -0
- package/dist/identity.js.map +1 -0
- package/dist/imports.d.ts +1 -1
- package/dist/imports.d.ts.map +1 -1
- package/dist/imports.js +7 -3
- package/dist/imports.js.map +1 -1
- package/dist/index.d.ts +57 -36
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -31
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +16 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +25 -0
- package/dist/loader.js.map +1 -0
- package/dist/node.d.ts +21 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +24 -0
- package/dist/node.js.map +1 -0
- package/dist/orm.d.ts +123 -12
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +35 -2
- package/dist/orm.js.map +1 -1
- package/dist/prefab/collector.d.ts +29 -0
- package/dist/prefab/collector.d.ts.map +1 -0
- package/dist/prefab/collector.js +34 -0
- package/dist/prefab/collector.js.map +1 -0
- package/dist/{crud.d.ts → prefab/crud.d.ts} +7 -8
- package/dist/prefab/crud.d.ts.map +1 -0
- package/dist/{crud.js → prefab/crud.js} +39 -5
- package/dist/prefab/crud.js.map +1 -0
- package/dist/prefab/mirror.d.ts +52 -0
- package/dist/prefab/mirror.d.ts.map +1 -0
- package/dist/prefab/mirror.js +66 -0
- package/dist/prefab/mirror.js.map +1 -0
- package/dist/prefab/prefab.d.ts +15 -0
- package/dist/prefab/prefab.d.ts.map +1 -0
- package/dist/prefab/prefab.js +19 -0
- package/dist/prefab/prefab.js.map +1 -0
- package/dist/{presenter.d.ts → prefab/presenter.d.ts} +6 -17
- package/dist/prefab/presenter.d.ts.map +1 -0
- package/dist/{presenter.js → prefab/presenter.js} +5 -23
- package/dist/prefab/presenter.js.map +1 -0
- package/dist/prefab/repository.d.ts +104 -0
- package/dist/prefab/repository.d.ts.map +1 -0
- package/dist/prefab/repository.js +62 -0
- package/dist/prefab/repository.js.map +1 -0
- package/dist/scan/Fronds.d.ts +45 -0
- package/dist/scan/Fronds.d.ts.map +1 -0
- package/dist/scan/Fronds.js +66 -0
- package/dist/scan/Fronds.js.map +1 -0
- package/dist/scan/conventions.d.ts +74 -0
- package/dist/scan/conventions.d.ts.map +1 -0
- package/dist/scan/conventions.js +82 -0
- package/dist/scan/conventions.js.map +1 -0
- package/dist/scan/emit.d.ts +14 -0
- package/dist/scan/emit.d.ts.map +1 -0
- package/dist/scan/emit.js +211 -0
- package/dist/scan/emit.js.map +1 -0
- package/dist/scan/frond.d.ts +224 -0
- package/dist/scan/frond.d.ts.map +1 -0
- package/dist/scan/frond.js +2 -0
- package/dist/scan/frond.js.map +1 -0
- package/dist/{handler-parser.d.ts → scan/handler-parser.d.ts} +18 -9
- package/dist/scan/handler-parser.d.ts.map +1 -0
- package/dist/scan/handler-parser.js +625 -0
- package/dist/scan/handler-parser.js.map +1 -0
- package/dist/scan/scan-cache.d.ts +16 -0
- package/dist/scan/scan-cache.d.ts.map +1 -0
- package/dist/{scan-cache.js → scan/scan-cache.js} +27 -20
- package/dist/scan/scan-cache.js.map +1 -0
- package/dist/scan/scanner.d.ts +20 -0
- package/dist/scan/scanner.d.ts.map +1 -0
- package/dist/{scanner.js → scan/scanner.js} +186 -167
- package/dist/scan/scanner.js.map +1 -0
- package/dist/verify.d.ts +16 -3
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +21 -18
- package/dist/verify.js.map +1 -1
- package/dist/{call.d.ts → wire/call.d.ts} +70 -1
- package/dist/wire/call.d.ts.map +1 -0
- package/dist/{call.js → wire/call.js} +48 -75
- package/dist/wire/call.js.map +1 -0
- package/dist/{middleware.d.ts → wire/errors.d.ts} +18 -19
- package/dist/wire/errors.d.ts.map +1 -0
- package/dist/{middleware.js → wire/errors.js} +26 -14
- package/dist/wire/errors.js.map +1 -0
- package/dist/{errors.d.ts → wire/http-error.d.ts} +5 -6
- package/dist/wire/http-error.d.ts.map +1 -0
- package/dist/{errors.js → wire/http-error.js} +7 -6
- package/dist/wire/http-error.js.map +1 -0
- package/dist/wire/invocation.d.ts +4 -0
- package/dist/wire/invocation.d.ts.map +1 -0
- package/dist/wire/invocation.js +3 -0
- package/dist/wire/invocation.js.map +1 -0
- package/dist/{middleware/logger.d.ts → wire/loggerMiddleware.d.ts} +3 -3
- package/dist/wire/loggerMiddleware.d.ts.map +1 -0
- package/dist/{middleware/logger.js → wire/loggerMiddleware.js} +2 -2
- package/dist/wire/loggerMiddleware.js.map +1 -0
- package/dist/wire/middleware.d.ts +29 -0
- package/dist/wire/middleware.d.ts.map +1 -0
- package/dist/wire/middleware.js +20 -0
- package/dist/wire/middleware.js.map +1 -0
- package/dist/{operation.d.ts → wire/operation.d.ts} +42 -13
- package/dist/wire/operation.d.ts.map +1 -0
- package/dist/wire/operation.js +167 -0
- package/dist/wire/operation.js.map +1 -0
- package/package.json +24 -7
- package/dist/binding.d.ts.map +0 -1
- package/dist/binding.js.map +0 -1
- package/dist/boot.d.ts.map +0 -1
- package/dist/boot.js +0 -53
- package/dist/boot.js.map +0 -1
- package/dist/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap.js +0 -848
- package/dist/bootstrap.js.map +0 -1
- package/dist/call.d.ts.map +0 -1
- package/dist/call.js.map +0 -1
- package/dist/collector.d.ts +0 -28
- package/dist/collector.d.ts.map +0 -1
- package/dist/collector.js +0 -32
- package/dist/collector.js.map +0 -1
- package/dist/crud.d.ts.map +0 -1
- package/dist/crud.js.map +0 -1
- package/dist/egress.d.ts +0 -78
- package/dist/egress.d.ts.map +0 -1
- package/dist/egress.js +0 -185
- package/dist/egress.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/handler-parser.d.ts.map +0 -1
- package/dist/handler-parser.js +0 -505
- package/dist/handler-parser.js.map +0 -1
- package/dist/invocation.d.ts +0 -20
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js +0 -15
- package/dist/invocation.js.map +0 -1
- package/dist/middleware/error-handler.d.ts +0 -15
- package/dist/middleware/error-handler.d.ts.map +0 -1
- package/dist/middleware/error-handler.js +0 -29
- package/dist/middleware/error-handler.js.map +0 -1
- package/dist/middleware/logger.d.ts.map +0 -1
- package/dist/middleware/logger.js.map +0 -1
- package/dist/middleware.d.ts.map +0 -1
- package/dist/middleware.js.map +0 -1
- package/dist/operation.d.ts.map +0 -1
- package/dist/operation.js +0 -95
- package/dist/operation.js.map +0 -1
- package/dist/presenter.d.ts.map +0 -1
- package/dist/presenter.js.map +0 -1
- package/dist/remote.d.ts.map +0 -1
- package/dist/remote.js.map +0 -1
- package/dist/repository.d.ts +0 -55
- package/dist/repository.d.ts.map +0 -1
- package/dist/repository.js +0 -26
- package/dist/repository.js.map +0 -1
- package/dist/scan-cache.d.ts +0 -10
- package/dist/scan-cache.d.ts.map +0 -1
- package/dist/scan-cache.js.map +0 -1
- package/dist/scanner.d.ts +0 -34
- package/dist/scanner.d.ts.map +0 -1
- package/dist/scanner.js.map +0 -1
- package/dist/seed.d.ts.map +0 -1
- package/dist/seed.js.map +0 -1
- package/dist/types.d.ts +0 -407
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{bootstrap.d.ts → boot/bootstrap.d.ts} +0 -0
- /package/dist/{types.js → boot/types.js} +0 -0
package/dist/orm.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { classNameOf } from '@fougere/schema';
|
|
1
2
|
/**
|
|
2
3
|
* The keys `list()` answers to. Anything else is a mistake, and saying so is the point:
|
|
3
4
|
* the façade refuses an unknown key in a CLIENT's input (`Unknown field`) — this applies the
|
|
4
5
|
* same rule to the framework's own arguments. `list({ orderId })` used to be accepted and
|
|
5
6
|
* the filter dropped, so a one-to-many relation quietly returned the whole table.
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
+
const LIST_OPTION_KEYS = [
|
|
8
9
|
'limit', 'offset', 'page', 'after', 'orderBy', 'order', 'count', 'where', 'select',
|
|
9
10
|
];
|
|
10
11
|
/** Refuse an option the port does not answer to, naming it and what was expected. */
|
|
@@ -28,6 +29,38 @@ export function assertListOptions(options, entity) {
|
|
|
28
29
|
* so a rename would have moved one and left the other resolving to nothing.
|
|
29
30
|
*/
|
|
30
31
|
export function ormKeyOf(entity) {
|
|
31
|
-
return `${
|
|
32
|
+
return `${classNameOf(entity)}Orm`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The container key of a frame — `[['Account', 'Ledger'], ['RateMirror']]` →
|
|
36
|
+
* 'Account+Ledger|RateMirrorTogether'.
|
|
37
|
+
*
|
|
38
|
+
* The DECLARED order, not a sorted one. The tuples are what the callback destructures, so
|
|
39
|
+
* reordering here would hand `[ledger, accounts]` to a signature that says the opposite —
|
|
40
|
+
* the type and the runtime disagreeing about the same line. Two orders of one frame are
|
|
41
|
+
* therefore two keys and two registrations; they cost nothing, a frame holding no state
|
|
42
|
+
* between runs.
|
|
43
|
+
*/
|
|
44
|
+
export function togetherKeyOf(entities, providers = []) {
|
|
45
|
+
const named = entities.map(classNameOf).join(SEPARATOR);
|
|
46
|
+
return `${named}${providers.length ? KINDS + providers.map(classNameOf).join(SEPARATOR) : ''}${FRAME}`;
|
|
47
|
+
}
|
|
48
|
+
const FRAME = 'Together';
|
|
49
|
+
const SEPARATOR = '+';
|
|
50
|
+
/** Separates the two lists — what the unwind covers, and what is rebuilt to make it true. */
|
|
51
|
+
const KINDS = '|';
|
|
52
|
+
/**
|
|
53
|
+
* The members behind a frame key, or `undefined` when the key is not one.
|
|
54
|
+
*
|
|
55
|
+
* The dual of the line above, and here for the reason `factOfEmitKey` is: the boot reads
|
|
56
|
+
* the key back out of a handler's `deps` to know which frames to build. A key and the way
|
|
57
|
+
* to undo it belong together — the pair that is split is the pair that drifts.
|
|
58
|
+
*/
|
|
59
|
+
export function membersOfTogetherKey(key) {
|
|
60
|
+
if (key.length <= FRAME.length || !key.endsWith(FRAME))
|
|
61
|
+
return undefined;
|
|
62
|
+
const [entities, providers = ''] = key.slice(0, -FRAME.length).split(KINDS);
|
|
63
|
+
const split = (list) => list.split(SEPARATOR).filter(Boolean);
|
|
64
|
+
return { entities: split(entities), providers: split(providers) };
|
|
32
65
|
}
|
|
33
66
|
//# sourceMappingURL=orm.js.map
|
package/dist/orm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orm.js","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"orm.js","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAmB,MAAM,iBAAiB,CAAC;AA2C/D;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG;IACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ;CAC1E,CAAC;AAEX,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,OAA2B,EAAE,MAAc;IAC3E,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,gBAAgB,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACnC,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,2BAA2B,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QACnF,qBAAqB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,iCAAiC,SAAS,CAAC,CAAC,CAAC,UAAU,CACxG,CAAC;AACJ,CAAC;AAkGD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc;IACrC,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;AACrC,CAAC;AA+CD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,QAA2B,EAAE,YAA+B,EAAE;IAC1F,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxD,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;AACzG,CAAC;AAED,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,SAAS,GAAG,GAAG,CAAC;AACtB,6FAA6F;AAC7F,MAAM,KAAK,GAAG,GAAG,CAAC;AAElB;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzE,MAAM,CAAC,QAAQ,EAAE,SAAS,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAS,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collector(Type) — resolves one handler input parameter from the invocation context.
|
|
3
|
+
*
|
|
4
|
+
* The target is a NAME matched against the parameter's type, never a schema: nothing
|
|
5
|
+
* here nor in the scan reads its fields. So `Ability`, built per call from state, sits
|
|
6
|
+
* beside `User`, loaded from a row.
|
|
7
|
+
*
|
|
8
|
+
* The dual of Presenter only in direction. A presenter's subject is a ROW — it adds
|
|
9
|
+
* computed fields to one, so its target must be an entity. A collector's subject is a
|
|
10
|
+
* PARAMETER.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```ts
|
|
14
|
+
* export default class UserCollector extends Collector(User) {
|
|
15
|
+
* constructor(private userOrm: UserOrm) { super(); }
|
|
16
|
+
*
|
|
17
|
+
* async collect(ctx: InvocationContext) {
|
|
18
|
+
* return this.userOrm.findById(ctx.state.userId as string);
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function Collector<T extends abstract new (...args: any[]) => any>(target: T): {
|
|
24
|
+
new (): {};
|
|
25
|
+
readonly __entity: T;
|
|
26
|
+
};
|
|
27
|
+
/** Container key of a collector — 'user' → 'UserCollector', 'ability' → 'AbilityCollector'. */
|
|
28
|
+
export declare function collectorKeyOf(type: string): string;
|
|
29
|
+
//# sourceMappingURL=collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/prefab/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,EAAE,CAAC;;;EAKlF;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collector(Type) — resolves one handler input parameter from the invocation context.
|
|
3
|
+
*
|
|
4
|
+
* The target is a NAME matched against the parameter's type, never a schema: nothing
|
|
5
|
+
* here nor in the scan reads its fields. So `Ability`, built per call from state, sits
|
|
6
|
+
* beside `User`, loaded from a row.
|
|
7
|
+
*
|
|
8
|
+
* The dual of Presenter only in direction. A presenter's subject is a ROW — it adds
|
|
9
|
+
* computed fields to one, so its target must be an entity. A collector's subject is a
|
|
10
|
+
* PARAMETER.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```ts
|
|
14
|
+
* export default class UserCollector extends Collector(User) {
|
|
15
|
+
* constructor(private userOrm: UserOrm) { super(); }
|
|
16
|
+
*
|
|
17
|
+
* async collect(ctx: InvocationContext) {
|
|
18
|
+
* return this.userOrm.findById(ctx.state.userId as string);
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { classNameOf } from '@fougere/schema';
|
|
24
|
+
export function Collector(target) {
|
|
25
|
+
class CollectorBase {
|
|
26
|
+
static __entity = target;
|
|
27
|
+
}
|
|
28
|
+
return CollectorBase;
|
|
29
|
+
}
|
|
30
|
+
/** Container key of a collector — 'user' → 'UserCollector', 'ability' → 'AbilityCollector'. */
|
|
31
|
+
export function collectorKeyOf(type) {
|
|
32
|
+
return `${classNameOf(type)}Collector`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/prefab/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,UAAU,SAAS,CAAiD,MAAS;IACjF,MAAM,aAAa;QACjB,MAAM,CAAU,QAAQ,GAAG,MAAM,CAAC;;IAEpC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;AACzC,CAAC"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { EntityOrm, ListOptions, ListResult } from '
|
|
2
|
-
import type { OperationContract } from '
|
|
3
|
-
|
|
4
|
-
type SchemaCtor = abstract new (...args: any[]) => any;
|
|
1
|
+
import type { EntityOrm, ListOptions, ListResult } from '../orm.js';
|
|
2
|
+
import type { OperationContract } from '../wire/operation.js';
|
|
3
|
+
import type { EntityConstructor } from '@fougere/schema';
|
|
5
4
|
/** The five ops the mixin fabricates. */
|
|
6
5
|
export type CrudOpName = 'list' | 'findById' | 'create' | 'update' | 'delete';
|
|
7
6
|
/** Which view each op speaks — omitted ops speak the entity, the trivial view. */
|
|
8
|
-
export type CrudViews = Partial<Record<CrudOpName,
|
|
7
|
+
export type CrudViews = Partial<Record<CrudOpName, EntityConstructor>>;
|
|
9
8
|
/**
|
|
10
9
|
* The view an op emits, fabricated: the one declared for it, the single view when the
|
|
11
10
|
* whole handler declares one, the entity otherwise. `PostCard` is not a hand-written
|
|
@@ -14,14 +13,14 @@ export type CrudViews = Partial<Record<CrudOpName, SchemaCtor>>;
|
|
|
14
13
|
*/
|
|
15
14
|
type OutOf<V, K extends CrudOpName, T> = [
|
|
16
15
|
V
|
|
17
|
-
] extends [
|
|
16
|
+
] extends [EntityConstructor] ? InstanceType<V & EntityConstructor> : K extends keyof V ? (V[K] extends EntityConstructor ? InstanceType<V[K]> : T) : T;
|
|
18
17
|
/**
|
|
19
18
|
* The five ops, typed from the entity and its views.
|
|
20
19
|
*
|
|
21
20
|
* Two things the mixin declares but does not own. The **output** is the view the
|
|
22
21
|
* handler names (`Crud(Post, { list: PostCard })`) — fabricated, so a redefinition
|
|
23
22
|
* that returns cards stays assignable. The **trailing parameters** are resolved by
|
|
24
|
-
* type from the container (`delete(id, user
|
|
23
|
+
* type from the container (`delete(id, user?: User)` gets its user from a
|
|
25
24
|
* collector): the mixin cannot know them, they belong to the app, so it declares that
|
|
26
25
|
* a tail exists and that it supplies none — which is what `never` says, and what keeps
|
|
27
26
|
* a judged redefinition assignable.
|
|
@@ -56,6 +55,6 @@ export interface CrudConstructor<T, V = {}> {
|
|
|
56
55
|
* scopes the injected ORM via .output(PostPublic) —
|
|
57
56
|
* the whole handler speaks the restricted view.
|
|
58
57
|
*/
|
|
59
|
-
export declare function Crud<E extends
|
|
58
|
+
export declare function Crud<E extends EntityConstructor, V extends CrudViews | EntityConstructor = {}>(entity: E, output?: V): CrudConstructor<InstanceType<E>, V>;
|
|
60
59
|
export {};
|
|
61
60
|
//# sourceMappingURL=crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../src/prefab/crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAc,MAAM,iBAAiB,CAAC;AAyFrE,yCAAyC;AACzC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9E,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,UAAU,EAAE,CAAC,IAInC;IAAC,CAAC;CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG,YAAY,CAAC,CAAC,GAAG,iBAAiB,CAAC,GACnE,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,iBAAiB,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAC7E,CAAC,CAAC;AAEN;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE;IAChC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC1F,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7D;AAED,4FAA4F;AAC5F,MAAM,WAAW,eAAe,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE;IAIxC,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,iBAAiB,EAAE,CAAC,SAAS,SAAS,GAAG,iBAAiB,GAAG,EAAE,EAC5F,MAAM,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,CAAC,GACT,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CA2BrC"}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
/** The id of the row an op acts on — a route segment, or a query fallback. */
|
|
2
2
|
const byId = { name: 'id', source: { kind: 'param', name: 'id' }, optional: false };
|
|
3
3
|
const fromBody = { name: 'input', source: { kind: 'body' }, optional: false };
|
|
4
|
+
/**
|
|
5
|
+
* The same five, written as the scan would have written them.
|
|
6
|
+
*
|
|
7
|
+
* `binding` says WHERE an argument is read from; it never says of what type, and a
|
|
8
|
+
* GraphQL argument needs the type. So a producer that fills only `binding` leaves
|
|
9
|
+
* `adapter/graphql` with nothing to declare — it drops the op (`registerOperations`,
|
|
10
|
+
* `if (!sig) continue`) and four of the five CRUD ops vanish from the schema while
|
|
11
|
+
* the façade and REST still serve them. Measured on an installed app: 16 handlers,
|
|
12
|
+
* 14 with unresolvable heritage, zero `createX` in the schema.
|
|
13
|
+
*/
|
|
14
|
+
const idParam = { name: 'id', type: { raw: 'string', name: 'string' } };
|
|
15
|
+
const inputParam = (entity) => ({ name: 'input', type: { raw: `Partial<${entity}>`, name: entity } });
|
|
16
|
+
const returns = (raw, name, extra) => ({ raw, name, ...extra });
|
|
4
17
|
/**
|
|
5
18
|
* The five ops a Crud handler brings, declared rather than discovered.
|
|
6
19
|
*
|
|
@@ -24,14 +37,35 @@ const fromBody = { name: 'input', source: { kind: 'body' }, optional: false };
|
|
|
24
37
|
* out. `delete` names none — a boolean is not a shape.
|
|
25
38
|
*/
|
|
26
39
|
function crudOps(entity) {
|
|
40
|
+
const name = entity.name ?? 'Entity';
|
|
41
|
+
const input = inputParam(name);
|
|
27
42
|
return {
|
|
28
|
-
list: {
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
list: {
|
|
44
|
+
output: entity, cardinality: 'page',
|
|
45
|
+
binding: [{ name: 'options', source: { kind: 'query' }, optional: true }],
|
|
46
|
+
signature: {
|
|
47
|
+
name: 'list', returnType: returns(`ListResult<${name}>`, 'ListResult'),
|
|
48
|
+
params: [{ name: 'options', type: { raw: 'ListOptions', name: 'ListOptions' }, optional: true }],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
findById: {
|
|
52
|
+
output: entity, cardinality: 'maybe', binding: [byId],
|
|
53
|
+
signature: { name: 'findById', returnType: returns(`${name} | undefined`, name, { nullable: true }), params: [idParam] },
|
|
54
|
+
},
|
|
55
|
+
create: {
|
|
56
|
+
input: entity, output: entity, cardinality: 'one', binding: [fromBody],
|
|
57
|
+
signature: { name: 'create', returnType: returns(name, name), params: [input] },
|
|
58
|
+
},
|
|
31
59
|
// The patch view carries its own mode: an absent field is untouched, an
|
|
32
60
|
// immutable one re-supplied is refused.
|
|
33
|
-
update: {
|
|
34
|
-
|
|
61
|
+
update: {
|
|
62
|
+
input: entity.partial?.(), output: entity, cardinality: 'one', binding: [byId, fromBody],
|
|
63
|
+
signature: { name: 'update', returnType: returns(name, name), params: [idParam, input] },
|
|
64
|
+
},
|
|
65
|
+
delete: {
|
|
66
|
+
cardinality: 'none', binding: [byId],
|
|
67
|
+
signature: { name: 'delete', returnType: returns('boolean', 'boolean'), params: [idParam] },
|
|
68
|
+
},
|
|
35
69
|
};
|
|
36
70
|
}
|
|
37
71
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.js","sourceRoot":"","sources":["../../src/prefab/crud.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type EntityConstructor } from '@fougere/schema';
|
|
2
|
+
import type { EntityOrm } from '../orm.js';
|
|
3
|
+
/**
|
|
4
|
+
* A paginated local copy of a source that cannot be queried directly.
|
|
5
|
+
*
|
|
6
|
+
* The shape must contain an `updated()` field used as a high-water mark. Subclasses
|
|
7
|
+
* implement `pull`; `refresh` validates and upserts each returned page.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* export default class PartnerCatalog extends Mirror(BookCard) {
|
|
11
|
+
* constructor(orm: EntityOrm<BookCard>, private catalog: Facade<CatalogHandler>) {
|
|
12
|
+
* super(orm);
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* async *pull(since?: Date) {
|
|
16
|
+
* for (let page = 0; page !== null;) {
|
|
17
|
+
* const body = await fetch(`${api}?page=${page}&since=${since?.toISOString() ?? ''}`);
|
|
18
|
+
* const { items, next } = await body.json();
|
|
19
|
+
* yield items.map(toCard);
|
|
20
|
+
* page = next;
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/** What one refresh did — enough to log it, and to decide whether to run again. */
|
|
27
|
+
export interface Refreshed {
|
|
28
|
+
/** Rows written, counting a replaced row once. */
|
|
29
|
+
written: number;
|
|
30
|
+
/** The age the pull was asked to start from — absent on the first ever run. */
|
|
31
|
+
since?: Date;
|
|
32
|
+
/** How long the whole pass took, pull included. */
|
|
33
|
+
ms: number;
|
|
34
|
+
}
|
|
35
|
+
export interface MirrorOf<T> {
|
|
36
|
+
/** The copy's own storage — where a page lands, and where its age is read. */
|
|
37
|
+
orm: EntityOrm<T>;
|
|
38
|
+
/** Pages of rows to write. The one thing a mirror's author supplies. */
|
|
39
|
+
pull(since?: Date): AsyncIterable<Partial<T>[]>;
|
|
40
|
+
/** Run one pass: read the high-water mark, pull from there, write each page. */
|
|
41
|
+
refresh(): Promise<Refreshed>;
|
|
42
|
+
/** When the freshest row here was written — `undefined` while the copy is empty. */
|
|
43
|
+
freshness(): Promise<Date | undefined>;
|
|
44
|
+
}
|
|
45
|
+
export interface MirrorConstructor<T> {
|
|
46
|
+
new (orm: EntityOrm<T>): MirrorOf<T>;
|
|
47
|
+
readonly __entity: unknown;
|
|
48
|
+
}
|
|
49
|
+
export declare function Mirror<E extends EntityConstructor>(shape: E): MirrorConstructor<InstanceType<E>>;
|
|
50
|
+
/** The field whose lifecycle stamps every update. */
|
|
51
|
+
export declare function ageFieldOf(shape: unknown): string | undefined;
|
|
52
|
+
//# sourceMappingURL=mirror.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror.d.ts","sourceRoot":"","sources":["../../src/prefab/mirror.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,iBAAiB,EAAsC,MAAM,iBAAiB,CAAC;AACxH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,8EAA8E;IAC9E,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChD,gFAAgF;IAChF,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9B,oFAAoF;IACpF,SAAS,IAAI,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,iBAAiB,EAAE,KAAK,EAAE,CAAC,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAyChG;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO7D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Lifecycle, primaryFieldOf } from '@fougere/schema';
|
|
2
|
+
export function Mirror(shape) {
|
|
3
|
+
// Refuse an undated copy before it can be used as if it held live rows.
|
|
4
|
+
const declared = ageFieldOf(shape);
|
|
5
|
+
if (declared === undefined) {
|
|
6
|
+
throw new Error(`Mirror(${shape.name ?? '?'}): the shape carries no \`updated()\` field — ` +
|
|
7
|
+
`a copy has to be able to say when it was pulled, and \`refresh\` reads its high-water mark from it.`);
|
|
8
|
+
}
|
|
9
|
+
const age = declared;
|
|
10
|
+
class MirrorBase {
|
|
11
|
+
orm;
|
|
12
|
+
static __entity = shape;
|
|
13
|
+
constructor(orm) {
|
|
14
|
+
this.orm = orm;
|
|
15
|
+
}
|
|
16
|
+
/** The freshest persisted stamp; no process-local freshness state is kept. */
|
|
17
|
+
async freshness() {
|
|
18
|
+
const [newest] = await this.orm.list({ orderBy: age, order: 'desc', limit: 1 });
|
|
19
|
+
const value = newest?.[age];
|
|
20
|
+
return value instanceof Date ? value : undefined;
|
|
21
|
+
}
|
|
22
|
+
async refresh() {
|
|
23
|
+
const started = Date.now();
|
|
24
|
+
const since = await this.freshness();
|
|
25
|
+
let written = 0;
|
|
26
|
+
// Preserve the source's page boundaries: one page becomes one upsert.
|
|
27
|
+
for await (const page of this.pull(since)) {
|
|
28
|
+
if (page.length === 0)
|
|
29
|
+
continue;
|
|
30
|
+
written += await this.orm.upsertAll(judgePage(shape, page));
|
|
31
|
+
}
|
|
32
|
+
return { written, since, ms: Date.now() - started };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return MirrorBase;
|
|
36
|
+
}
|
|
37
|
+
/** The field whose lifecycle stamps every update. */
|
|
38
|
+
export function ageFieldOf(shape) {
|
|
39
|
+
const fields = shape.getFields?.();
|
|
40
|
+
if (!fields)
|
|
41
|
+
return undefined;
|
|
42
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
43
|
+
if (Lifecycle.of(field).stampedOnUpdate)
|
|
44
|
+
return name;
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
/** Validate and decode a page, naming a refused row by its declared primary field. */
|
|
49
|
+
function judgePage(shape, page) {
|
|
50
|
+
const judge = shape.validate;
|
|
51
|
+
if (typeof judge !== 'function')
|
|
52
|
+
return page;
|
|
53
|
+
const name = shape.name ?? 'mirror';
|
|
54
|
+
const fields = shape.getFields?.();
|
|
55
|
+
const primary = fields ? primaryFieldOf(fields) : undefined;
|
|
56
|
+
return page.map((row, index) => {
|
|
57
|
+
const verdict = judge.call(shape, row);
|
|
58
|
+
if (verdict.success)
|
|
59
|
+
return verdict.data;
|
|
60
|
+
const key = primary === undefined ? undefined : row[primary];
|
|
61
|
+
const where = key !== undefined ? `row ${primary} ${JSON.stringify(key)}` : `row ${index} of this page`;
|
|
62
|
+
const why = verdict.errors.map((e) => `${e.path}: ${e.message}`).join(', ');
|
|
63
|
+
throw new Error(`${name} mirror refused ${where} — ${why}`);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror.js","sourceRoot":"","sources":["../../src/prefab/mirror.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EntityConstructor } from '@fougere/schema';
|
|
2
|
+
import type { PresenterViews } from './presenter.js';
|
|
3
|
+
/**
|
|
4
|
+
* The shape a prefab was built on, or `undefined` when the class is not one.
|
|
5
|
+
*
|
|
6
|
+
* A plain property read: JavaScript walks a constructor's own prototype chain, so a
|
|
7
|
+
* subclass of a prefab answers what its base recorded. Three of the five accessors this
|
|
8
|
+
* replaces walked that chain by hand, and two did not — one question, two mechanisms.
|
|
9
|
+
*/
|
|
10
|
+
export declare function targetOf(ctor: unknown): EntityConstructor | undefined;
|
|
11
|
+
/** The views a prefab declares, same rule. */
|
|
12
|
+
export declare function viewsOf(ctor: unknown): PresenterViews | undefined;
|
|
13
|
+
/** The handler-wide view a prefab declares, same rule. */
|
|
14
|
+
export declare function outputOf(ctor: unknown): EntityConstructor | undefined;
|
|
15
|
+
//# sourceMappingURL=prefab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefab.d.ts","sourceRoot":"","sources":["../../src/prefab/prefab.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAyBrD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAErE;AAED,8CAA8C;AAC9C,wBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAEjE;AAED,0DAA0D;AAC1D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAErE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape a prefab was built on, or `undefined` when the class is not one.
|
|
3
|
+
*
|
|
4
|
+
* A plain property read: JavaScript walks a constructor's own prototype chain, so a
|
|
5
|
+
* subclass of a prefab answers what its base recorded. Three of the five accessors this
|
|
6
|
+
* replaces walked that chain by hand, and two did not — one question, two mechanisms.
|
|
7
|
+
*/
|
|
8
|
+
export function targetOf(ctor) {
|
|
9
|
+
return ctor?.__entity;
|
|
10
|
+
}
|
|
11
|
+
/** The views a prefab declares, same rule. */
|
|
12
|
+
export function viewsOf(ctor) {
|
|
13
|
+
return ctor?.__views;
|
|
14
|
+
}
|
|
15
|
+
/** The handler-wide view a prefab declares, same rule. */
|
|
16
|
+
export function outputOf(ctor) {
|
|
17
|
+
return ctor?.__output;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=prefab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefab.js","sourceRoot":"","sources":["../../src/prefab/prefab.ts"],"names":[],"mappings":"AA0BA;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAa;IACpC,OAAQ,IAA2B,EAAE,QAAQ,CAAC;AAChD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,OAAO,CAAC,IAAa;IACnC,OAAQ,IAA2B,EAAE,OAAO,CAAC;AAC/C,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,QAAQ,CAAC,IAAa;IACpC,OAAQ,IAA2B,EAAE,QAAQ,CAAC;AAChD,CAAC"}
|
|
@@ -21,19 +21,17 @@
|
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
declare const PRESENTER_TARGET: unique symbol;
|
|
26
|
-
declare const PRESENTER_VIEWS: unique symbol;
|
|
24
|
+
import { type EntityConstructor } from '@fougere/schema';
|
|
27
25
|
/**
|
|
28
26
|
* The view a computed field emits — `OrderItemView` for one, `[OrderItemView]` for many.
|
|
29
27
|
* A view is a schema, so it derives: `Order.pick('id', 'status')`, never a hand-written type.
|
|
30
28
|
*/
|
|
31
|
-
export type PresenterViews = Record<string,
|
|
29
|
+
export type PresenterViews = Record<string, EntityConstructor | [EntityConstructor]>;
|
|
32
30
|
/**
|
|
33
31
|
* `Presenter(Order, { items: [OrderItemView], user: UserCard })` — the second argument names
|
|
34
32
|
* the view each computed field emits, exactly as `Crud(Post, { list: PostCard })` names an
|
|
35
33
|
* op's. What fabricates a field declares its contract, and it declares it **once**: the
|
|
36
|
-
* façade applies the presenter (see `
|
|
34
|
+
* façade applies the presenter (see `PresenterExecutor`), and every surface reads the same statement
|
|
37
35
|
* instead of guessing.
|
|
38
36
|
*
|
|
39
37
|
* Guessing was the cost of not stating it. The scan can read a scalar off a return type and
|
|
@@ -42,22 +40,13 @@ export type PresenterViews = Record<string, EntityClass | [EntityClass]>;
|
|
|
42
40
|
* error on a field REST served whole. Declaring is optional — a scalar field needs nothing,
|
|
43
41
|
* and an undeclared object keeps the old behaviour.
|
|
44
42
|
*/
|
|
45
|
-
export declare function Presenter<E extends
|
|
43
|
+
export declare function Presenter<E extends EntityConstructor>(entity: E, views?: PresenterViews): {
|
|
46
44
|
new (): {};
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
readonly __entity: E;
|
|
46
|
+
readonly __views: PresenterViews | undefined;
|
|
49
47
|
};
|
|
50
|
-
/** Get the entity class a presenter targets. */
|
|
51
|
-
export declare function getPresenterTarget(ctor: Function): EntityClass | undefined;
|
|
52
|
-
/**
|
|
53
|
-
* The views a presenter declares, walked up the prototype chain so a subclass of a
|
|
54
|
-
* presenter keeps what its base stated. Runtime, like `Crud.__ops`: an installed app whose
|
|
55
|
-
* source the scan cannot read still carries its contract.
|
|
56
|
-
*/
|
|
57
|
-
export declare function getPresenterViews(ctor: Function): PresenterViews | undefined;
|
|
58
48
|
/** List computed field names from a presenter class (own methods minus constructor). */
|
|
59
49
|
export declare function getPresenterFields(ctor: Function): string[];
|
|
60
50
|
/** Container key of an entity's presenter — 'post' → 'PostPresenter'. */
|
|
61
51
|
export declare function presenterKeyOf(entity: string): string;
|
|
62
|
-
export {};
|
|
63
52
|
//# sourceMappingURL=presenter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.d.ts","sourceRoot":"","sources":["../../src/prefab/presenter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAErF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,iBAAiB,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,cAAc;;;;EAMvF;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAG3D;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD"}
|
|
@@ -21,13 +21,12 @@
|
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
const PRESENTER_VIEWS = Symbol.for('fougere:presenter_views');
|
|
24
|
+
import { classNameOf } from '@fougere/schema';
|
|
26
25
|
/**
|
|
27
26
|
* `Presenter(Order, { items: [OrderItemView], user: UserCard })` — the second argument names
|
|
28
27
|
* the view each computed field emits, exactly as `Crud(Post, { list: PostCard })` names an
|
|
29
28
|
* op's. What fabricates a field declares its contract, and it declares it **once**: the
|
|
30
|
-
* façade applies the presenter (see `
|
|
29
|
+
* façade applies the presenter (see `PresenterExecutor`), and every surface reads the same statement
|
|
31
30
|
* instead of guessing.
|
|
32
31
|
*
|
|
33
32
|
* Guessing was the cost of not stating it. The scan can read a scalar off a return type and
|
|
@@ -38,28 +37,11 @@ const PRESENTER_VIEWS = Symbol.for('fougere:presenter_views');
|
|
|
38
37
|
*/
|
|
39
38
|
export function Presenter(entity, views) {
|
|
40
39
|
class PresenterBase {
|
|
41
|
-
static
|
|
42
|
-
static
|
|
40
|
+
static __entity = entity;
|
|
41
|
+
static __views = views;
|
|
43
42
|
}
|
|
44
43
|
return PresenterBase;
|
|
45
44
|
}
|
|
46
|
-
/** Get the entity class a presenter targets. */
|
|
47
|
-
export function getPresenterTarget(ctor) {
|
|
48
|
-
return ctor[PRESENTER_TARGET];
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* The views a presenter declares, walked up the prototype chain so a subclass of a
|
|
52
|
-
* presenter keeps what its base stated. Runtime, like `Crud.__ops`: an installed app whose
|
|
53
|
-
* source the scan cannot read still carries its contract.
|
|
54
|
-
*/
|
|
55
|
-
export function getPresenterViews(ctor) {
|
|
56
|
-
for (let cur = ctor; cur; cur = Object.getPrototypeOf(cur)) {
|
|
57
|
-
const views = cur[PRESENTER_VIEWS];
|
|
58
|
-
if (views)
|
|
59
|
-
return views;
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
45
|
/** List computed field names from a presenter class (own methods minus constructor). */
|
|
64
46
|
export function getPresenterFields(ctor) {
|
|
65
47
|
return Object.getOwnPropertyNames(ctor.prototype)
|
|
@@ -67,6 +49,6 @@ export function getPresenterFields(ctor) {
|
|
|
67
49
|
}
|
|
68
50
|
/** Container key of an entity's presenter — 'post' → 'PostPresenter'. */
|
|
69
51
|
export function presenterKeyOf(entity) {
|
|
70
|
-
return `${
|
|
52
|
+
return `${classNameOf(entity)}Presenter`;
|
|
71
53
|
}
|
|
72
54
|
//# sourceMappingURL=presenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.js","sourceRoot":"","sources":["../../src/prefab/presenter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,WAAW,EAA0B,MAAM,iBAAiB,CAAC;AAQtE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAA8B,MAAS,EAAE,KAAsB;IACtF,MAAM,aAAa;QACjB,MAAM,CAAU,QAAQ,GAAG,MAAM,CAAC;QAClC,MAAM,CAAU,OAAO,GAAG,KAAK,CAAC;;IAElC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAC,IAAc;IAC/C,OAAO,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC;SAC9C,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC;AAC5F,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC;AAC3C,CAAC"}
|