@procedures/client 0.0.0-stage → 0.1.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/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +832 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/adapters/http/client/index.d.ts +11 -0
- package/dist/adapters/http/client/index.d.ts.map +1 -0
- package/dist/adapters/http/client/index.js +18 -0
- package/dist/adapters/http/client/index.js.map +1 -0
- package/dist/adapters/http/client/transport.d.ts +72 -0
- package/dist/adapters/http/client/transport.d.ts.map +1 -0
- package/dist/adapters/http/client/transport.js +282 -0
- package/dist/adapters/http/client/transport.js.map +1 -0
- package/dist/adapters/http/client/types.d.ts +27 -0
- package/dist/adapters/http/client/types.d.ts.map +1 -0
- package/dist/adapters/http/client/types.js +8 -0
- package/dist/adapters/http/client/types.js.map +1 -0
- package/dist/adapters/http/index.d.ts +7 -0
- package/dist/adapters/http/index.d.ts.map +1 -0
- package/dist/adapters/http/index.js +7 -0
- package/dist/adapters/http/index.js.map +1 -0
- package/dist/adapters/http/server/index.d.ts +9 -0
- package/dist/adapters/http/server/index.d.ts.map +1 -0
- package/dist/adapters/http/server/index.js +10 -0
- package/dist/adapters/http/server/index.js.map +1 -0
- package/dist/adapters/http/server/strategies.d.ts +39 -0
- package/dist/adapters/http/server/strategies.d.ts.map +1 -0
- package/dist/adapters/http/server/strategies.js +90 -0
- package/dist/adapters/http/server/strategies.js.map +1 -0
- package/dist/adapters/http/server/transport.d.ts +66 -0
- package/dist/adapters/http/server/transport.d.ts.map +1 -0
- package/dist/adapters/http/server/transport.js +561 -0
- package/dist/adapters/http/server/transport.js.map +1 -0
- package/dist/adapters/http/server/types.d.ts +71 -0
- package/dist/adapters/http/server/types.d.ts.map +1 -0
- package/dist/adapters/http/server/types.js +7 -0
- package/dist/adapters/http/server/types.js.map +1 -0
- package/dist/adapters/http/shared/constants.d.ts +95 -0
- package/dist/adapters/http/shared/constants.d.ts.map +1 -0
- package/dist/adapters/http/shared/constants.js +102 -0
- package/dist/adapters/http/shared/constants.js.map +1 -0
- package/dist/adapters/http/shared/errors.d.ts +78 -0
- package/dist/adapters/http/shared/errors.d.ts.map +1 -0
- package/dist/adapters/http/shared/errors.js +151 -0
- package/dist/adapters/http/shared/errors.js.map +1 -0
- package/dist/adapters/http/shared/headers.d.ts +122 -0
- package/dist/adapters/http/shared/headers.d.ts.map +1 -0
- package/dist/adapters/http/shared/headers.js +216 -0
- package/dist/adapters/http/shared/headers.js.map +1 -0
- package/dist/adapters/http/shared/index.d.ts +12 -0
- package/dist/adapters/http/shared/index.d.ts.map +1 -0
- package/dist/adapters/http/shared/index.js +17 -0
- package/dist/adapters/http/shared/index.js.map +1 -0
- package/dist/adapters/http/shared/status-codes.d.ts +92 -0
- package/dist/adapters/http/shared/status-codes.d.ts.map +1 -0
- package/dist/adapters/http/shared/status-codes.js +189 -0
- package/dist/adapters/http/shared/status-codes.js.map +1 -0
- package/dist/adapters/http/shared/strategies.d.ts +90 -0
- package/dist/adapters/http/shared/strategies.d.ts.map +1 -0
- package/dist/adapters/http/shared/strategies.js +180 -0
- package/dist/adapters/http/shared/strategies.js.map +1 -0
- package/dist/adapters/local/client/index.d.ts +8 -0
- package/dist/adapters/local/client/index.d.ts.map +1 -0
- package/dist/adapters/local/client/index.js +8 -0
- package/dist/adapters/local/client/index.js.map +1 -0
- package/dist/adapters/local/client/transport.d.ts +81 -0
- package/dist/adapters/local/client/transport.d.ts.map +1 -0
- package/dist/adapters/local/client/transport.js +172 -0
- package/dist/adapters/local/client/transport.js.map +1 -0
- package/dist/adapters/local/client/types.d.ts +39 -0
- package/dist/adapters/local/client/types.d.ts.map +1 -0
- package/dist/adapters/local/client/types.js +13 -0
- package/dist/adapters/local/client/types.js.map +1 -0
- package/dist/adapters/metadata.d.ts +10 -0
- package/dist/adapters/metadata.d.ts.map +1 -0
- package/dist/adapters/metadata.js +19 -0
- package/dist/adapters/metadata.js.map +1 -0
- package/dist/adapters/mock/client/builder.d.ts +35 -0
- package/dist/adapters/mock/client/builder.d.ts.map +1 -0
- package/dist/adapters/mock/client/builder.js +58 -0
- package/dist/adapters/mock/client/builder.js.map +1 -0
- package/dist/adapters/mock/client/index.d.ts +9 -0
- package/dist/adapters/mock/client/index.d.ts.map +1 -0
- package/dist/adapters/mock/client/index.js +10 -0
- package/dist/adapters/mock/client/index.js.map +1 -0
- package/dist/adapters/mock/client/transport.d.ts +149 -0
- package/dist/adapters/mock/client/transport.d.ts.map +1 -0
- package/dist/adapters/mock/client/transport.js +289 -0
- package/dist/adapters/mock/client/transport.js.map +1 -0
- package/dist/adapters/mock/client/types.d.ts +86 -0
- package/dist/adapters/mock/client/types.d.ts.map +1 -0
- package/dist/adapters/mock/client/types.js +7 -0
- package/dist/adapters/mock/client/types.js.map +1 -0
- package/dist/adapters/websocket/client/index.d.ts +9 -0
- package/dist/adapters/websocket/client/index.d.ts.map +1 -0
- package/dist/adapters/websocket/client/index.js +9 -0
- package/dist/adapters/websocket/client/index.js.map +1 -0
- package/dist/adapters/websocket/client/transport.d.ts +106 -0
- package/dist/adapters/websocket/client/transport.d.ts.map +1 -0
- package/dist/adapters/websocket/client/transport.js +647 -0
- package/dist/adapters/websocket/client/transport.js.map +1 -0
- package/dist/adapters/websocket/client/types.d.ts +192 -0
- package/dist/adapters/websocket/client/types.d.ts.map +1 -0
- package/dist/adapters/websocket/client/types.js +17 -0
- package/dist/adapters/websocket/client/types.js.map +1 -0
- package/dist/adapters/websocket/index.d.ts +8 -0
- package/dist/adapters/websocket/index.d.ts.map +1 -0
- package/dist/adapters/websocket/index.js +8 -0
- package/dist/adapters/websocket/index.js.map +1 -0
- package/dist/adapters/websocket/server/index.d.ts +8 -0
- package/dist/adapters/websocket/server/index.d.ts.map +1 -0
- package/dist/adapters/websocket/server/index.js +8 -0
- package/dist/adapters/websocket/server/index.js.map +1 -0
- package/dist/adapters/websocket/server/transport.d.ts +112 -0
- package/dist/adapters/websocket/server/transport.d.ts.map +1 -0
- package/dist/adapters/websocket/server/transport.js +619 -0
- package/dist/adapters/websocket/server/transport.js.map +1 -0
- package/dist/adapters/websocket/server/types.d.ts +140 -0
- package/dist/adapters/websocket/server/types.d.ts.map +1 -0
- package/dist/adapters/websocket/server/types.js +7 -0
- package/dist/adapters/websocket/server/types.js.map +1 -0
- package/dist/browser.d.ts +48 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +86 -0
- package/dist/browser.js.map +1 -0
- package/dist/client/batch-executor.d.ts +160 -0
- package/dist/client/batch-executor.d.ts.map +1 -0
- package/dist/client/batch-executor.js +397 -0
- package/dist/client/batch-executor.js.map +1 -0
- package/dist/client/call-types.d.ts +271 -0
- package/dist/client/call-types.d.ts.map +1 -0
- package/dist/client/call-types.js +208 -0
- package/dist/client/call-types.js.map +1 -0
- package/dist/client/client.d.ts +517 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +990 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/consumption.d.ts +191 -0
- package/dist/client/consumption.d.ts.map +1 -0
- package/dist/client/consumption.js +98 -0
- package/dist/client/consumption.js.map +1 -0
- package/dist/client/context.d.ts +116 -0
- package/dist/client/context.d.ts.map +1 -0
- package/dist/client/context.js +111 -0
- package/dist/client/context.js.map +1 -0
- package/dist/client/errors/codes.d.ts +71 -0
- package/dist/client/errors/codes.d.ts.map +1 -0
- package/dist/client/errors/codes.js +81 -0
- package/dist/client/errors/codes.js.map +1 -0
- package/dist/client/errors/factory.d.ts +102 -0
- package/dist/client/errors/factory.d.ts.map +1 -0
- package/dist/client/errors/factory.js +210 -0
- package/dist/client/errors/factory.js.map +1 -0
- package/dist/client/errors/http-errors.d.ts +47 -0
- package/dist/client/errors/http-errors.d.ts.map +1 -0
- package/dist/client/errors/http-errors.js +548 -0
- package/dist/client/errors/http-errors.js.map +1 -0
- package/dist/client/errors/http-status.d.ts +73 -0
- package/dist/client/errors/http-status.d.ts.map +1 -0
- package/dist/client/errors/http-status.js +79 -0
- package/dist/client/errors/http-status.js.map +1 -0
- package/dist/client/errors/index.d.ts +36 -0
- package/dist/client/errors/index.d.ts.map +1 -0
- package/dist/client/errors/index.js +40 -0
- package/dist/client/errors/index.js.map +1 -0
- package/dist/client/errors/registry.d.ts +38 -0
- package/dist/client/errors/registry.d.ts.map +1 -0
- package/dist/client/errors/registry.js +535 -0
- package/dist/client/errors/registry.js.map +1 -0
- package/dist/client/errors/types.d.ts +112 -0
- package/dist/client/errors/types.d.ts.map +1 -0
- package/dist/client/errors/types.js +45 -0
- package/dist/client/errors/types.js.map +1 -0
- package/dist/client/index.d.ts +44 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +36 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/middleware/auth.d.ts +90 -0
- package/dist/client/middleware/auth.d.ts.map +1 -0
- package/dist/client/middleware/auth.js +98 -0
- package/dist/client/middleware/auth.js.map +1 -0
- package/dist/client/middleware/batching.d.ts +102 -0
- package/dist/client/middleware/batching.d.ts.map +1 -0
- package/dist/client/middleware/batching.js +245 -0
- package/dist/client/middleware/batching.js.map +1 -0
- package/dist/client/middleware/cache.d.ts +124 -0
- package/dist/client/middleware/cache.d.ts.map +1 -0
- package/dist/client/middleware/cache.js +208 -0
- package/dist/client/middleware/cache.js.map +1 -0
- package/dist/client/middleware/circuit-breaker.d.ts +113 -0
- package/dist/client/middleware/circuit-breaker.d.ts.map +1 -0
- package/dist/client/middleware/circuit-breaker.js +236 -0
- package/dist/client/middleware/circuit-breaker.js.map +1 -0
- package/dist/client/middleware/contexts.d.ts +199 -0
- package/dist/client/middleware/contexts.d.ts.map +1 -0
- package/dist/client/middleware/contexts.js +74 -0
- package/dist/client/middleware/contexts.js.map +1 -0
- package/dist/client/middleware/items.d.ts +37 -0
- package/dist/client/middleware/items.d.ts.map +1 -0
- package/dist/client/middleware/items.js +100 -0
- package/dist/client/middleware/items.js.map +1 -0
- package/dist/client/middleware/lru.d.ts +32 -0
- package/dist/client/middleware/lru.d.ts.map +1 -0
- package/dist/client/middleware/lru.js +62 -0
- package/dist/client/middleware/lru.js.map +1 -0
- package/dist/client/middleware/pagination.d.ts +114 -0
- package/dist/client/middleware/pagination.d.ts.map +1 -0
- package/dist/client/middleware/pagination.js +148 -0
- package/dist/client/middleware/pagination.js.map +1 -0
- package/dist/client/middleware/rate-limit.d.ts +105 -0
- package/dist/client/middleware/rate-limit.d.ts.map +1 -0
- package/dist/client/middleware/rate-limit.js +222 -0
- package/dist/client/middleware/rate-limit.js.map +1 -0
- package/dist/client/middleware/retry.d.ts +100 -0
- package/dist/client/middleware/retry.d.ts.map +1 -0
- package/dist/client/middleware/retry.js +150 -0
- package/dist/client/middleware/retry.js.map +1 -0
- package/dist/client/middleware/timeout.d.ts +91 -0
- package/dist/client/middleware/timeout.d.ts.map +1 -0
- package/dist/client/middleware/timeout.js +253 -0
- package/dist/client/middleware/timeout.js.map +1 -0
- package/dist/client/middleware/tracing.d.ts +118 -0
- package/dist/client/middleware/tracing.d.ts.map +1 -0
- package/dist/client/middleware/tracing.js +152 -0
- package/dist/client/middleware/tracing.js.map +1 -0
- package/dist/client/route-resolver.d.ts +181 -0
- package/dist/client/route-resolver.d.ts.map +1 -0
- package/dist/client/route-resolver.js +300 -0
- package/dist/client/route-resolver.js.map +1 -0
- package/dist/client/typed-method.d.ts +29 -0
- package/dist/client/typed-method.d.ts.map +1 -0
- package/dist/client/typed-method.js +36 -0
- package/dist/client/typed-method.js.map +1 -0
- package/dist/client/typed.d.ts +102 -0
- package/dist/client/typed.d.ts.map +1 -0
- package/dist/client/typed.js +52 -0
- package/dist/client/typed.js.map +1 -0
- package/dist/client/types.d.ts +296 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +26 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/validation/index.d.ts +34 -0
- package/dist/client/validation/index.d.ts.map +1 -0
- package/dist/client/validation/index.js +36 -0
- package/dist/client/validation/index.js.map +1 -0
- package/dist/client/validation/middleware.d.ts +82 -0
- package/dist/client/validation/middleware.d.ts.map +1 -0
- package/dist/client/validation/middleware.js +138 -0
- package/dist/client/validation/middleware.js.map +1 -0
- package/dist/client/validation/types.d.ts +118 -0
- package/dist/client/validation/types.d.ts.map +1 -0
- package/dist/client/validation/types.js +59 -0
- package/dist/client/validation/types.js.map +1 -0
- package/dist/collections/async/async-queue.d.ts +144 -0
- package/dist/collections/async/async-queue.d.ts.map +1 -0
- package/dist/collections/async/async-queue.js +347 -0
- package/dist/collections/async/async-queue.js.map +1 -0
- package/dist/collections/async/channels.d.ts +188 -0
- package/dist/collections/async/channels.d.ts.map +1 -0
- package/dist/collections/async/channels.js +312 -0
- package/dist/collections/async/channels.js.map +1 -0
- package/dist/collections/behaviors/bounded.d.ts +79 -0
- package/dist/collections/behaviors/bounded.d.ts.map +1 -0
- package/dist/collections/behaviors/bounded.js +384 -0
- package/dist/collections/behaviors/bounded.js.map +1 -0
- package/dist/collections/behaviors/evented.d.ts +154 -0
- package/dist/collections/behaviors/evented.d.ts.map +1 -0
- package/dist/collections/behaviors/evented.js +299 -0
- package/dist/collections/behaviors/evented.js.map +1 -0
- package/dist/collections/behaviors/lru.d.ts +84 -0
- package/dist/collections/behaviors/lru.d.ts.map +1 -0
- package/dist/collections/behaviors/lru.js +330 -0
- package/dist/collections/behaviors/lru.js.map +1 -0
- package/dist/collections/behaviors/readonly.d.ts +73 -0
- package/dist/collections/behaviors/readonly.d.ts.map +1 -0
- package/dist/collections/behaviors/readonly.js +158 -0
- package/dist/collections/behaviors/readonly.js.map +1 -0
- package/dist/collections/behaviors/safe.d.ts +163 -0
- package/dist/collections/behaviors/safe.d.ts.map +1 -0
- package/dist/collections/behaviors/safe.js +172 -0
- package/dist/collections/behaviors/safe.js.map +1 -0
- package/dist/collections/behaviors/synchronized.d.ts +88 -0
- package/dist/collections/behaviors/synchronized.d.ts.map +1 -0
- package/dist/collections/behaviors/synchronized.js +294 -0
- package/dist/collections/behaviors/synchronized.js.map +1 -0
- package/dist/collections/behaviors/ttl.d.ts +118 -0
- package/dist/collections/behaviors/ttl.d.ts.map +1 -0
- package/dist/collections/behaviors/ttl.js +338 -0
- package/dist/collections/behaviors/ttl.js.map +1 -0
- package/dist/collections/core/effects.d.ts +176 -0
- package/dist/collections/core/effects.d.ts.map +1 -0
- package/dist/collections/core/effects.js +180 -0
- package/dist/collections/core/effects.js.map +1 -0
- package/dist/collections/core/events.d.ts +192 -0
- package/dist/collections/core/events.d.ts.map +1 -0
- package/dist/collections/core/events.js +291 -0
- package/dist/collections/core/events.js.map +1 -0
- package/dist/collections/core/middleware.d.ts +231 -0
- package/dist/collections/core/middleware.d.ts.map +1 -0
- package/dist/collections/core/middleware.js +161 -0
- package/dist/collections/core/middleware.js.map +1 -0
- package/dist/collections/core/policies.d.ts +220 -0
- package/dist/collections/core/policies.d.ts.map +1 -0
- package/dist/collections/core/policies.js +48 -0
- package/dist/collections/core/policies.js.map +1 -0
- package/dist/collections/core/traits.d.ts +142 -0
- package/dist/collections/core/traits.d.ts.map +1 -0
- package/dist/collections/core/traits.js +8 -0
- package/dist/collections/core/traits.js.map +1 -0
- package/dist/collections/examples.d.ts +13 -0
- package/dist/collections/examples.d.ts.map +1 -0
- package/dist/collections/examples.js +302 -0
- package/dist/collections/examples.js.map +1 -0
- package/dist/collections/fx/collectors.d.ts +190 -0
- package/dist/collections/fx/collectors.d.ts.map +1 -0
- package/dist/collections/fx/collectors.js +369 -0
- package/dist/collections/fx/collectors.js.map +1 -0
- package/dist/collections/fx/iter.d.ts +166 -0
- package/dist/collections/fx/iter.d.ts.map +1 -0
- package/dist/collections/fx/iter.js +421 -0
- package/dist/collections/fx/iter.js.map +1 -0
- package/dist/collections/impl/array-deque.d.ts +107 -0
- package/dist/collections/impl/array-deque.d.ts.map +1 -0
- package/dist/collections/impl/array-deque.js +381 -0
- package/dist/collections/impl/array-deque.js.map +1 -0
- package/dist/collections/impl/array-list.d.ts +101 -0
- package/dist/collections/impl/array-list.d.ts.map +1 -0
- package/dist/collections/impl/array-list.js +387 -0
- package/dist/collections/impl/array-list.js.map +1 -0
- package/dist/collections/impl/hash-map.d.ts +141 -0
- package/dist/collections/impl/hash-map.d.ts.map +1 -0
- package/dist/collections/impl/hash-map.js +450 -0
- package/dist/collections/impl/hash-map.js.map +1 -0
- package/dist/collections/impl/hash-set.d.ts +125 -0
- package/dist/collections/impl/hash-set.d.ts.map +1 -0
- package/dist/collections/impl/hash-set.js +264 -0
- package/dist/collections/impl/hash-set.js.map +1 -0
- package/dist/collections/impl/linked-hash-map.d.ts +141 -0
- package/dist/collections/impl/linked-hash-map.d.ts.map +1 -0
- package/dist/collections/impl/linked-hash-map.js +472 -0
- package/dist/collections/impl/linked-hash-map.js.map +1 -0
- package/dist/collections/impl/linked-list.d.ts +109 -0
- package/dist/collections/impl/linked-list.d.ts.map +1 -0
- package/dist/collections/impl/linked-list.js +491 -0
- package/dist/collections/impl/linked-list.js.map +1 -0
- package/dist/collections/impl/priority-queue.d.ts +134 -0
- package/dist/collections/impl/priority-queue.d.ts.map +1 -0
- package/dist/collections/impl/priority-queue.js +336 -0
- package/dist/collections/impl/priority-queue.js.map +1 -0
- package/dist/collections/impl/tree-map.d.ts +146 -0
- package/dist/collections/impl/tree-map.d.ts.map +1 -0
- package/dist/collections/impl/tree-map.js +781 -0
- package/dist/collections/impl/tree-map.js.map +1 -0
- package/dist/collections/impl/tree-set.d.ts +112 -0
- package/dist/collections/impl/tree-set.d.ts.map +1 -0
- package/dist/collections/impl/tree-set.js +374 -0
- package/dist/collections/impl/tree-set.js.map +1 -0
- package/dist/collections/index.d.ts +105 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/collections/index.js +135 -0
- package/dist/collections/index.js.map +1 -0
- package/dist/collections/interfaces/collection.d.ts +119 -0
- package/dist/collections/interfaces/collection.d.ts.map +1 -0
- package/dist/collections/interfaces/collection.js +8 -0
- package/dist/collections/interfaces/collection.js.map +1 -0
- package/dist/collections/interfaces/list.d.ts +247 -0
- package/dist/collections/interfaces/list.d.ts.map +1 -0
- package/dist/collections/interfaces/list.js +8 -0
- package/dist/collections/interfaces/list.js.map +1 -0
- package/dist/collections/interfaces/map.d.ts +344 -0
- package/dist/collections/interfaces/map.d.ts.map +1 -0
- package/dist/collections/interfaces/map.js +8 -0
- package/dist/collections/interfaces/map.js.map +1 -0
- package/dist/collections/interfaces/queue.d.ts +304 -0
- package/dist/collections/interfaces/queue.d.ts.map +1 -0
- package/dist/collections/interfaces/queue.js +8 -0
- package/dist/collections/interfaces/queue.js.map +1 -0
- package/dist/collections/interfaces/set.d.ts +137 -0
- package/dist/collections/interfaces/set.d.ts.map +1 -0
- package/dist/collections/interfaces/set.js +8 -0
- package/dist/collections/interfaces/set.js.map +1 -0
- package/dist/collections/storage/api.d.ts +109 -0
- package/dist/collections/storage/api.d.ts.map +1 -0
- package/dist/collections/storage/api.js +182 -0
- package/dist/collections/storage/api.js.map +1 -0
- package/dist/collections/storage/hybrid.d.ts +164 -0
- package/dist/collections/storage/hybrid.d.ts.map +1 -0
- package/dist/collections/storage/hybrid.js +416 -0
- package/dist/collections/storage/hybrid.js.map +1 -0
- package/dist/collections/storage/index.d.ts +16 -0
- package/dist/collections/storage/index.d.ts.map +1 -0
- package/dist/collections/storage/index.js +13 -0
- package/dist/collections/storage/index.js.map +1 -0
- package/dist/collections/storage/interface.d.ts +141 -0
- package/dist/collections/storage/interface.d.ts.map +1 -0
- package/dist/collections/storage/interface.js +23 -0
- package/dist/collections/storage/interface.js.map +1 -0
- package/dist/collections/storage/memory.d.ts +68 -0
- package/dist/collections/storage/memory.d.ts.map +1 -0
- package/dist/collections/storage/memory.js +154 -0
- package/dist/collections/storage/memory.js.map +1 -0
- package/dist/collections/utils/defaults.d.ts +135 -0
- package/dist/collections/utils/defaults.d.ts.map +1 -0
- package/dist/collections/utils/defaults.js +322 -0
- package/dist/collections/utils/defaults.js.map +1 -0
- package/dist/collections/utils/factories.d.ts +144 -0
- package/dist/collections/utils/factories.d.ts.map +1 -0
- package/dist/collections/utils/factories.js +293 -0
- package/dist/collections/utils/factories.js.map +1 -0
- package/dist/collections/utils/helpers.d.ts +137 -0
- package/dist/collections/utils/helpers.d.ts.map +1 -0
- package/dist/collections/utils/helpers.js +221 -0
- package/dist/collections/utils/helpers.js.map +1 -0
- package/dist/collections.d.ts +12 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +10 -0
- package/dist/collections.js.map +1 -0
- package/dist/components/define.d.ts +134 -0
- package/dist/components/define.d.ts.map +1 -0
- package/dist/components/define.js +486 -0
- package/dist/components/define.js.map +1 -0
- package/dist/components/index.d.ts +39 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +38 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/types.d.ts +264 -0
- package/dist/components/types.d.ts.map +1 -0
- package/dist/components/types.js +46 -0
- package/dist/components/types.js.map +1 -0
- package/dist/events/bus.d.ts +193 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +511 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/events/index.d.ts +34 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +36 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +242 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +8 -0
- package/dist/events/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/compose.d.ts +88 -0
- package/dist/middleware/compose.d.ts.map +1 -0
- package/dist/middleware/compose.js +108 -0
- package/dist/middleware/compose.js.map +1 -0
- package/dist/middleware/index.d.ts +12 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +11 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/types.d.ts +112 -0
- package/dist/middleware/types.d.ts.map +1 -0
- package/dist/middleware/types.js +14 -0
- package/dist/middleware/types.js.map +1 -0
- package/dist/procedures/cli/announce.d.ts +67 -0
- package/dist/procedures/cli/announce.d.ts.map +1 -0
- package/dist/procedures/cli/announce.js +392 -0
- package/dist/procedures/cli/announce.js.map +1 -0
- package/dist/procedures/cli/discover.d.ts +66 -0
- package/dist/procedures/cli/discover.d.ts.map +1 -0
- package/dist/procedures/cli/discover.js +310 -0
- package/dist/procedures/cli/discover.js.map +1 -0
- package/dist/procedures/cli/index.d.ts +13 -0
- package/dist/procedures/cli/index.d.ts.map +1 -0
- package/dist/procedures/cli/index.js +201 -0
- package/dist/procedures/cli/index.js.map +1 -0
- package/dist/procedures/cli/init.d.ts +17 -0
- package/dist/procedures/cli/init.d.ts.map +1 -0
- package/dist/procedures/cli/init.js +336 -0
- package/dist/procedures/cli/init.js.map +1 -0
- package/dist/procedures/collection/index.d.ts +10 -0
- package/dist/procedures/collection/index.d.ts.map +1 -0
- package/dist/procedures/collection/index.js +10 -0
- package/dist/procedures/collection/index.js.map +1 -0
- package/dist/procedures/collection/procedures.d.ts +21 -0
- package/dist/procedures/collection/procedures.d.ts.map +1 -0
- package/dist/procedures/collection/procedures.js +198 -0
- package/dist/procedures/collection/procedures.js.map +1 -0
- package/dist/procedures/collection/schemas.d.ts +131 -0
- package/dist/procedures/collection/schemas.d.ts.map +1 -0
- package/dist/procedures/collection/schemas.js +422 -0
- package/dist/procedures/collection/schemas.js.map +1 -0
- package/dist/procedures/collection/storage.d.ts +53 -0
- package/dist/procedures/collection/storage.d.ts.map +1 -0
- package/dist/procedures/collection/storage.js +2 -0
- package/dist/procedures/collection/storage.js.map +1 -0
- package/dist/procedures/core/array.d.ts +276 -0
- package/dist/procedures/core/array.d.ts.map +1 -0
- package/dist/procedures/core/array.js +637 -0
- package/dist/procedures/core/array.js.map +1 -0
- package/dist/procedures/core/comparison.d.ts +85 -0
- package/dist/procedures/core/comparison.d.ts.map +1 -0
- package/dist/procedures/core/comparison.js +156 -0
- package/dist/procedures/core/comparison.js.map +1 -0
- package/dist/procedures/core/index.d.ts +261 -0
- package/dist/procedures/core/index.d.ts.map +1 -0
- package/dist/procedures/core/index.js +585 -0
- package/dist/procedures/core/index.js.map +1 -0
- package/dist/procedures/core/logic.d.ts +144 -0
- package/dist/procedures/core/logic.d.ts.map +1 -0
- package/dist/procedures/core/logic.js +169 -0
- package/dist/procedures/core/logic.js.map +1 -0
- package/dist/procedures/core/math.d.ts +139 -0
- package/dist/procedures/core/math.d.ts.map +1 -0
- package/dist/procedures/core/math.js +273 -0
- package/dist/procedures/core/math.js.map +1 -0
- package/dist/procedures/core/meta.d.ts +111 -0
- package/dist/procedures/core/meta.d.ts.map +1 -0
- package/dist/procedures/core/meta.js +239 -0
- package/dist/procedures/core/meta.js.map +1 -0
- package/dist/procedures/core/object.d.ts +109 -0
- package/dist/procedures/core/object.d.ts.map +1 -0
- package/dist/procedures/core/object.js +270 -0
- package/dist/procedures/core/object.js.map +1 -0
- package/dist/procedures/core/operands.d.ts +51 -0
- package/dist/procedures/core/operands.d.ts.map +1 -0
- package/dist/procedures/core/operands.js +90 -0
- package/dist/procedures/core/operands.js.map +1 -0
- package/dist/procedures/core/outputs.d.ts +28 -0
- package/dist/procedures/core/outputs.d.ts.map +1 -0
- package/dist/procedures/core/outputs.js +42 -0
- package/dist/procedures/core/outputs.js.map +1 -0
- package/dist/procedures/core/results.d.ts +202 -0
- package/dist/procedures/core/results.d.ts.map +1 -0
- package/dist/procedures/core/results.js +106 -0
- package/dist/procedures/core/results.js.map +1 -0
- package/dist/procedures/core/schemas.d.ts +48 -0
- package/dist/procedures/core/schemas.d.ts.map +1 -0
- package/dist/procedures/core/schemas.js +102 -0
- package/dist/procedures/core/schemas.js.map +1 -0
- package/dist/procedures/core/string.d.ts +138 -0
- package/dist/procedures/core/string.d.ts.map +1 -0
- package/dist/procedures/core/string.js +268 -0
- package/dist/procedures/core/string.js.map +1 -0
- package/dist/procedures/core/type.d.ts +101 -0
- package/dist/procedures/core/type.d.ts.map +1 -0
- package/dist/procedures/core/type.js +208 -0
- package/dist/procedures/core/type.js.map +1 -0
- package/dist/procedures/define-procedure.d.ts +187 -0
- package/dist/procedures/define-procedure.d.ts.map +1 -0
- package/dist/procedures/define-procedure.js +356 -0
- package/dist/procedures/define-procedure.js.map +1 -0
- package/dist/procedures/define.d.ts +228 -0
- package/dist/procedures/define.d.ts.map +1 -0
- package/dist/procedures/define.js +300 -0
- package/dist/procedures/define.js.map +1 -0
- package/dist/procedures/discovery.d.ts +57 -0
- package/dist/procedures/discovery.d.ts.map +1 -0
- package/dist/procedures/discovery.js +68 -0
- package/dist/procedures/discovery.js.map +1 -0
- package/dist/procedures/index.d.ts +24 -0
- package/dist/procedures/index.d.ts.map +1 -0
- package/dist/procedures/index.js +69 -0
- package/dist/procedures/index.js.map +1 -0
- package/dist/procedures/interceptors.d.ts +82 -0
- package/dist/procedures/interceptors.d.ts.map +1 -0
- package/dist/procedures/interceptors.js +193 -0
- package/dist/procedures/interceptors.js.map +1 -0
- package/dist/procedures/invoke.d.ts +127 -0
- package/dist/procedures/invoke.d.ts.map +1 -0
- package/dist/procedures/invoke.js +277 -0
- package/dist/procedures/invoke.js.map +1 -0
- package/dist/procedures/module.d.ts +49 -0
- package/dist/procedures/module.d.ts.map +1 -0
- package/dist/procedures/module.js +93 -0
- package/dist/procedures/module.js.map +1 -0
- package/dist/procedures/policy.d.ts +70 -0
- package/dist/procedures/policy.d.ts.map +1 -0
- package/dist/procedures/policy.js +138 -0
- package/dist/procedures/policy.js.map +1 -0
- package/dist/procedures/ref.d.ts +606 -0
- package/dist/procedures/ref.d.ts.map +1 -0
- package/dist/procedures/ref.js +895 -0
- package/dist/procedures/ref.js.map +1 -0
- package/dist/procedures/registry.d.ts +208 -0
- package/dist/procedures/registry.d.ts.map +1 -0
- package/dist/procedures/registry.js +402 -0
- package/dist/procedures/registry.js.map +1 -0
- package/dist/procedures/schema.d.ts +126 -0
- package/dist/procedures/schema.d.ts.map +1 -0
- package/dist/procedures/schema.js +108 -0
- package/dist/procedures/schema.js.map +1 -0
- package/dist/procedures/storage/adapter.d.ts +148 -0
- package/dist/procedures/storage/adapter.d.ts.map +1 -0
- package/dist/procedures/storage/adapter.js +214 -0
- package/dist/procedures/storage/adapter.js.map +1 -0
- package/dist/procedures/storage/api.d.ts +125 -0
- package/dist/procedures/storage/api.d.ts.map +1 -0
- package/dist/procedures/storage/api.js +220 -0
- package/dist/procedures/storage/api.js.map +1 -0
- package/dist/procedures/storage/factory.d.ts +134 -0
- package/dist/procedures/storage/factory.d.ts.map +1 -0
- package/dist/procedures/storage/factory.js +166 -0
- package/dist/procedures/storage/factory.js.map +1 -0
- package/dist/procedures/storage/hybrid.d.ts +193 -0
- package/dist/procedures/storage/hybrid.d.ts.map +1 -0
- package/dist/procedures/storage/hybrid.js +519 -0
- package/dist/procedures/storage/hybrid.js.map +1 -0
- package/dist/procedures/storage/index.d.ts +17 -0
- package/dist/procedures/storage/index.d.ts.map +1 -0
- package/dist/procedures/storage/index.js +17 -0
- package/dist/procedures/storage/index.js.map +1 -0
- package/dist/procedures/storage/procedures.d.ts +39 -0
- package/dist/procedures/storage/procedures.d.ts.map +1 -0
- package/dist/procedures/storage/procedures.js +261 -0
- package/dist/procedures/storage/procedures.js.map +1 -0
- package/dist/procedures/storage/serialization.d.ts +123 -0
- package/dist/procedures/storage/serialization.d.ts.map +1 -0
- package/dist/procedures/storage/serialization.js +216 -0
- package/dist/procedures/storage/serialization.js.map +1 -0
- package/dist/procedures/storage/synced-registry.d.ts +246 -0
- package/dist/procedures/storage/synced-registry.d.ts.map +1 -0
- package/dist/procedures/storage/synced-registry.js +575 -0
- package/dist/procedures/storage/synced-registry.js.map +1 -0
- package/dist/procedures/storage/types.d.ts +130 -0
- package/dist/procedures/storage/types.d.ts.map +1 -0
- package/dist/procedures/storage/types.js +8 -0
- package/dist/procedures/storage/types.js.map +1 -0
- package/dist/procedures/types.d.ts +370 -0
- package/dist/procedures/types.d.ts.map +1 -0
- package/dist/procedures/types.js +23 -0
- package/dist/procedures/types.js.map +1 -0
- package/dist/server/browser-guard.d.ts +69 -0
- package/dist/server/browser-guard.d.ts.map +1 -0
- package/dist/server/browser-guard.js +103 -0
- package/dist/server/browser-guard.js.map +1 -0
- package/dist/server/host-policy.d.ts +59 -0
- package/dist/server/host-policy.d.ts.map +1 -0
- package/dist/server/host-policy.js +82 -0
- package/dist/server/host-policy.js.map +1 -0
- package/dist/server/index.d.ts +46 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +42 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/method.d.ts +24 -0
- package/dist/server/method.d.ts.map +1 -0
- package/dist/server/method.js +29 -0
- package/dist/server/method.js.map +1 -0
- package/dist/server/procedure-server.d.ts +212 -0
- package/dist/server/procedure-server.d.ts.map +1 -0
- package/dist/server/procedure-server.js +323 -0
- package/dist/server/procedure-server.js.map +1 -0
- package/dist/server/server.d.ts +161 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +279 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/types.d.ts +106 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +29 -0
- package/dist/server/types.js.map +1 -0
- package/package.json +115 -3
- package/src/adapters/http/client/index.ts +51 -0
- package/src/adapters/http/client/transport.ts +338 -0
- package/src/adapters/http/client/types.ts +33 -0
- package/src/adapters/http/index.ts +7 -0
- package/src/adapters/http/server/index.ts +14 -0
- package/src/adapters/http/server/strategies.ts +105 -0
- package/src/adapters/http/server/transport.ts +622 -0
- package/src/adapters/http/server/types.ts +81 -0
- package/src/adapters/http/shared/constants.ts +108 -0
- package/src/adapters/http/shared/errors.ts +199 -0
- package/src/adapters/http/shared/headers.ts +291 -0
- package/src/adapters/http/shared/index.ts +21 -0
- package/src/adapters/http/shared/status-codes.ts +212 -0
- package/src/adapters/http/shared/strategies.ts +255 -0
- package/src/adapters/local/client/index.ts +11 -0
- package/src/adapters/local/client/transport.ts +188 -0
- package/src/adapters/local/client/types.ts +50 -0
- package/src/adapters/metadata.ts +17 -0
- package/src/adapters/mock/client/builder.ts +64 -0
- package/src/adapters/mock/client/index.ts +19 -0
- package/src/adapters/mock/client/transport.ts +352 -0
- package/src/adapters/mock/client/types.ts +99 -0
- package/src/adapters/websocket/client/index.ts +18 -0
- package/src/adapters/websocket/client/transport.ts +733 -0
- package/src/adapters/websocket/client/types.ts +235 -0
- package/src/adapters/websocket/index.ts +24 -0
- package/src/adapters/websocket/server/index.ts +18 -0
- package/src/adapters/websocket/server/transport.ts +705 -0
- package/src/adapters/websocket/server/types.ts +169 -0
- package/src/browser.ts +373 -0
- package/src/client/batch-executor.ts +514 -0
- package/src/client/call-types.ts +491 -0
- package/src/client/client.ts +1202 -0
- package/src/client/consumption.ts +288 -0
- package/src/client/context.ts +228 -0
- package/src/client/errors/README.md +279 -0
- package/src/client/errors/codes.ts +88 -0
- package/src/client/errors/factory.ts +263 -0
- package/src/client/errors/http-errors.ts +601 -0
- package/src/client/errors/http-status.ts +82 -0
- package/src/client/errors/index.ts +72 -0
- package/src/client/errors/registry.ts +595 -0
- package/src/client/errors/types.ts +139 -0
- package/src/client/index.ts +124 -0
- package/src/client/middleware/auth.ts +132 -0
- package/src/client/middleware/cache.ts +316 -0
- package/src/client/middleware/circuit-breaker.ts +339 -0
- package/src/client/middleware/contexts.ts +319 -0
- package/src/client/middleware/items.ts +114 -0
- package/src/client/middleware/lru.ts +66 -0
- package/src/client/middleware/pagination.ts +213 -0
- package/src/client/middleware/rate-limit.ts +315 -0
- package/src/client/middleware/retry.ts +236 -0
- package/src/client/middleware/timeout.ts +308 -0
- package/src/client/middleware/tracing.ts +191 -0
- package/src/client/route-resolver.ts +407 -0
- package/src/client/typed-method.ts +65 -0
- package/src/client/typed.ts +140 -0
- package/src/client/types.ts +361 -0
- package/src/client/validation/index.ts +56 -0
- package/src/client/validation/middleware.ts +254 -0
- package/src/client/validation/types.ts +162 -0
- package/src/events/bus.ts +594 -0
- package/src/events/index.ts +67 -0
- package/src/events/types.ts +263 -0
- package/src/index.ts +33 -0
- package/src/middleware/compose.ts +159 -0
- package/src/middleware/index.ts +28 -0
- package/src/middleware/types.ts +166 -0
- package/src/procedures/cli/announce.ts +470 -0
- package/src/procedures/cli/discover.ts +390 -0
- package/src/procedures/cli/index.ts +229 -0
- package/src/procedures/cli/init.ts +370 -0
- package/src/procedures/collection/index.ts +51 -0
- package/src/procedures/collection/procedures.ts +245 -0
- package/src/procedures/collection/schemas.ts +550 -0
- package/src/procedures/collection/storage.ts +53 -0
- package/src/procedures/core/array.ts +1024 -0
- package/src/procedures/core/comparison.ts +263 -0
- package/src/procedures/core/index.ts +895 -0
- package/src/procedures/core/logic.ts +225 -0
- package/src/procedures/core/math.ts +469 -0
- package/src/procedures/core/meta.ts +384 -0
- package/src/procedures/core/object.ts +427 -0
- package/src/procedures/core/operands.ts +119 -0
- package/src/procedures/core/outputs.ts +48 -0
- package/src/procedures/core/results.ts +296 -0
- package/src/procedures/core/schemas.ts +123 -0
- package/src/procedures/core/string.ts +458 -0
- package/src/procedures/core/type.ts +344 -0
- package/src/procedures/define-procedure.ts +531 -0
- package/src/procedures/define.ts +387 -0
- package/src/procedures/discovery.ts +76 -0
- package/src/procedures/index.ts +228 -0
- package/src/procedures/interceptors.ts +272 -0
- package/src/procedures/invoke.ts +413 -0
- package/src/procedures/module.ts +107 -0
- package/src/procedures/policy.ts +171 -0
- package/src/procedures/ref.ts +1305 -0
- package/src/procedures/registry.ts +473 -0
- package/src/procedures/schema.ts +225 -0
- package/src/procedures/types.ts +485 -0
- package/src/server/browser-guard.ts +147 -0
- package/src/server/host-policy.ts +121 -0
- package/src/server/index.ts +70 -0
- package/src/server/method.ts +33 -0
- package/src/server/procedure-server.ts +417 -0
- package/src/server/server.ts +364 -0
- package/src/server/types.ts +147 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interceptors for every host (roadmap 1.2): a timeout, tracing and metrics.
|
|
3
|
+
*
|
|
4
|
+
* An interceptor runs around each invocation of `invokeProcedure()`, also the nested calls. A
|
|
5
|
+
* host takes a list: `ProcedureServer({ interceptors })`, `new Client({ interceptors })` or
|
|
6
|
+
* `invokeProcedure(procedure, input, { interceptors })`. See `invoke.ts` for the types.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { InvocationError, type Interceptor, type Invocation, type ProcedureOutput } from "./invoke.js";
|
|
10
|
+
import { pathToKey, type ProcedurePath } from "./types.js";
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Timeout
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
export interface TimeoutInterceptorOptions {
|
|
17
|
+
/** The time limit in milliseconds. 0 or less: no limit. */
|
|
18
|
+
ms: number;
|
|
19
|
+
/**
|
|
20
|
+
* The invocations to limit. The default is the calls of the host (depth 0): a nested call gets
|
|
21
|
+
* the signal of its parent, so the limit of the parent ends it too.
|
|
22
|
+
*/
|
|
23
|
+
appliesTo?: ((invocation: Invocation) => boolean) | undefined;
|
|
24
|
+
/** This function gets each invocation that the interceptor limits (for tests and logs). */
|
|
25
|
+
onLimit?: ((invocation: Invocation) => void) | undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A signal that aborts when one of the signals aborts. */
|
|
29
|
+
function anySignal(signals: AbortSignal[]): AbortSignal {
|
|
30
|
+
const any = (AbortSignal as { any?: (signals: AbortSignal[]) => AbortSignal }).any;
|
|
31
|
+
if (any) return any(signals);
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
for (const signal of signals) {
|
|
34
|
+
if (signal.aborted) {
|
|
35
|
+
controller.abort(signal.reason);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
|
|
39
|
+
}
|
|
40
|
+
return controller.signal;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function timeoutError(path: ProcedurePath, ms: number): InvocationError {
|
|
44
|
+
return new InvocationError("TIMEOUT", `Procedure timed out after ${ms} ms: ${pathToKey(path)}`, path);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The items of a stream until the deadline. At the deadline, the reader gets the TIMEOUT error
|
|
49
|
+
* and the stream gets `return()`.
|
|
50
|
+
*/
|
|
51
|
+
async function* itemsUntil<T>(
|
|
52
|
+
items: AsyncGenerator<T, void, undefined>,
|
|
53
|
+
deadline: Promise<never>,
|
|
54
|
+
done: () => void,
|
|
55
|
+
): AsyncGenerator<T, void, undefined> {
|
|
56
|
+
let finished = false;
|
|
57
|
+
try {
|
|
58
|
+
for (;;) {
|
|
59
|
+
const step = await Promise.race([items.next(), deadline]);
|
|
60
|
+
if (step.done) {
|
|
61
|
+
finished = true;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
yield step.value;
|
|
65
|
+
}
|
|
66
|
+
} finally {
|
|
67
|
+
done();
|
|
68
|
+
// The generator can wait on an await that the aborted signal ends later: do not wait for it
|
|
69
|
+
if (!finished) void items.return(undefined).catch(() => undefined);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* This interceptor ends an invocation that runs longer than `ms`: the reader gets a TIMEOUT
|
|
75
|
+
* error, and the handler's signal aborts. A handler that ignores its signal can run on, but its
|
|
76
|
+
* result is not used. For a stream, the limit covers the whole stream.
|
|
77
|
+
*/
|
|
78
|
+
export function timeoutInterceptor(options: TimeoutInterceptorOptions): Interceptor {
|
|
79
|
+
const { ms } = options;
|
|
80
|
+
const appliesTo = options.appliesTo ?? ((invocation: Invocation) => invocation.depth === 0);
|
|
81
|
+
return async (invocation, next) => {
|
|
82
|
+
if (!(ms > 0) || !appliesTo(invocation)) return next();
|
|
83
|
+
options.onLimit?.(invocation);
|
|
84
|
+
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
const signal = invocation.signal ? anySignal([invocation.signal, controller.signal]) : controller.signal;
|
|
87
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
88
|
+
const deadline = new Promise<never>((_resolve, reject) => {
|
|
89
|
+
timer = setTimeout(() => {
|
|
90
|
+
const error = timeoutError(invocation.path, ms);
|
|
91
|
+
controller.abort(error);
|
|
92
|
+
reject(error);
|
|
93
|
+
}, ms);
|
|
94
|
+
});
|
|
95
|
+
// A deadline that no one waits for must not be an unhandled rejection
|
|
96
|
+
deadline.catch(() => undefined);
|
|
97
|
+
const stop = (): void => clearTimeout(timer);
|
|
98
|
+
|
|
99
|
+
let output: ProcedureOutput<unknown>;
|
|
100
|
+
try {
|
|
101
|
+
output = await Promise.race([next({ signal }), deadline]);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
stop();
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
if (output.kind === "value") {
|
|
107
|
+
stop();
|
|
108
|
+
return output;
|
|
109
|
+
}
|
|
110
|
+
return { kind: "stream", items: itemsUntil(output.items, deadline, stop) };
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// =============================================================================
|
|
115
|
+
// Tracing
|
|
116
|
+
// =============================================================================
|
|
117
|
+
|
|
118
|
+
/** One invocation as a span of a trace. */
|
|
119
|
+
export interface InvocationSpan {
|
|
120
|
+
readonly id: string;
|
|
121
|
+
/** The span of the invocation whose handler made this call. A call of a host has none. */
|
|
122
|
+
readonly parentId: string | undefined;
|
|
123
|
+
/** The same for every span of one call of a host. */
|
|
124
|
+
readonly traceId: string;
|
|
125
|
+
readonly path: ProcedurePath;
|
|
126
|
+
readonly key: string;
|
|
127
|
+
readonly depth: number;
|
|
128
|
+
/** The start, in milliseconds from `now()`. */
|
|
129
|
+
readonly start: number;
|
|
130
|
+
end: number | undefined;
|
|
131
|
+
durationMs: number | undefined;
|
|
132
|
+
status: "running" | "ok" | "error";
|
|
133
|
+
/** The message of the error. */
|
|
134
|
+
error?: string | undefined;
|
|
135
|
+
/** The code of an invocation error (`TIMEOUT`, `VALIDATION_ERROR` and so on). */
|
|
136
|
+
code?: string | undefined;
|
|
137
|
+
kind?: "value" | "stream" | undefined;
|
|
138
|
+
/** The number of items of a stream. */
|
|
139
|
+
items?: number | undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface TracingInterceptorOptions {
|
|
143
|
+
/** This function gets each span when its invocation ends (a stream: when the stream ends). */
|
|
144
|
+
onSpan: (span: InvocationSpan) => void;
|
|
145
|
+
/** This function gets each span when its invocation starts. */
|
|
146
|
+
onStart?: ((span: InvocationSpan) => void) | undefined;
|
|
147
|
+
/** The clock. The default is `performance.now()`. */
|
|
148
|
+
now?: (() => number) | undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let traceCount = 0;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* This interceptor makes a span for each invocation, with the span of its parent. A host can
|
|
155
|
+
* send the spans to a trace backend, a log or the site's trace view.
|
|
156
|
+
*/
|
|
157
|
+
export function tracingInterceptor(options: TracingInterceptorOptions): Interceptor {
|
|
158
|
+
const now = options.now ?? (() => performance.now());
|
|
159
|
+
const prefix = `t${++traceCount}-${Math.random().toString(36).slice(2, 8)}`;
|
|
160
|
+
let spanCount = 0;
|
|
161
|
+
/** The open spans, by the id of their invocation */
|
|
162
|
+
const open = new Map<number, InvocationSpan>();
|
|
163
|
+
|
|
164
|
+
const finish = (span: InvocationSpan, invocationId: number, error?: unknown): void => {
|
|
165
|
+
span.end = now();
|
|
166
|
+
span.durationMs = span.end - span.start;
|
|
167
|
+
if (error !== undefined) {
|
|
168
|
+
span.status = "error";
|
|
169
|
+
span.error = error instanceof Error ? error.message : String(error);
|
|
170
|
+
const code = (error as { code?: unknown }).code;
|
|
171
|
+
if (typeof code === "string") span.code = code;
|
|
172
|
+
} else {
|
|
173
|
+
span.status = "ok";
|
|
174
|
+
}
|
|
175
|
+
open.delete(invocationId);
|
|
176
|
+
options.onSpan(span);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
return async (invocation, next) => {
|
|
180
|
+
const parent = invocation.parent ? open.get(invocation.parent.id) : undefined;
|
|
181
|
+
const id = `${prefix}-${++spanCount}`;
|
|
182
|
+
const span: InvocationSpan = {
|
|
183
|
+
id,
|
|
184
|
+
parentId: parent?.id,
|
|
185
|
+
traceId: parent?.traceId ?? id,
|
|
186
|
+
path: invocation.path,
|
|
187
|
+
key: pathToKey(invocation.path),
|
|
188
|
+
depth: invocation.depth,
|
|
189
|
+
start: now(),
|
|
190
|
+
end: undefined,
|
|
191
|
+
durationMs: undefined,
|
|
192
|
+
status: "running",
|
|
193
|
+
};
|
|
194
|
+
open.set(invocation.id, span);
|
|
195
|
+
options.onStart?.(span);
|
|
196
|
+
|
|
197
|
+
let output: ProcedureOutput<unknown>;
|
|
198
|
+
try {
|
|
199
|
+
output = await next();
|
|
200
|
+
} catch (error) {
|
|
201
|
+
finish(span, invocation.id, error);
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
if (output.kind === "value") {
|
|
205
|
+
span.kind = "value";
|
|
206
|
+
finish(span, invocation.id);
|
|
207
|
+
return output;
|
|
208
|
+
}
|
|
209
|
+
span.kind = "stream";
|
|
210
|
+
span.items = 0;
|
|
211
|
+
const items = output.items;
|
|
212
|
+
return {
|
|
213
|
+
kind: "stream",
|
|
214
|
+
items: (async function* () {
|
|
215
|
+
let failure: unknown;
|
|
216
|
+
try {
|
|
217
|
+
for await (const item of items) {
|
|
218
|
+
span.items = (span.items ?? 0) + 1;
|
|
219
|
+
yield item;
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
failure = error;
|
|
223
|
+
throw error;
|
|
224
|
+
} finally {
|
|
225
|
+
finish(span, invocation.id, failure);
|
|
226
|
+
}
|
|
227
|
+
})(),
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// =============================================================================
|
|
233
|
+
// Metrics
|
|
234
|
+
// =============================================================================
|
|
235
|
+
|
|
236
|
+
/** The counts of one procedure. */
|
|
237
|
+
export interface ProcedureMetrics {
|
|
238
|
+
calls: number;
|
|
239
|
+
errors: number;
|
|
240
|
+
/** The sum of the durations, in milliseconds. */
|
|
241
|
+
totalMs: number;
|
|
242
|
+
maxMs: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** A metrics interceptor and its counts. */
|
|
246
|
+
export interface MetricsInterceptor {
|
|
247
|
+
interceptor: Interceptor;
|
|
248
|
+
/** A copy of the counts, by procedure key. */
|
|
249
|
+
snapshot(): Record<string, ProcedureMetrics>;
|
|
250
|
+
reset(): void;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** This function makes an interceptor that counts the calls, the errors and the time of each procedure. */
|
|
254
|
+
export function metricsInterceptor(options: { now?: () => number } = {}): MetricsInterceptor {
|
|
255
|
+
const counts = new Map<string, ProcedureMetrics>();
|
|
256
|
+
const record = (key: string, duration: number, failed: boolean): void => {
|
|
257
|
+
const entry = counts.get(key) ?? { calls: 0, errors: 0, totalMs: 0, maxMs: 0 };
|
|
258
|
+
entry.calls++;
|
|
259
|
+
if (failed) entry.errors++;
|
|
260
|
+
entry.totalMs += duration;
|
|
261
|
+
entry.maxMs = Math.max(entry.maxMs, duration);
|
|
262
|
+
counts.set(key, entry);
|
|
263
|
+
};
|
|
264
|
+
return {
|
|
265
|
+
interceptor: tracingInterceptor({
|
|
266
|
+
onSpan: (span) => record(span.key, span.durationMs ?? 0, span.status === "error"),
|
|
267
|
+
...(options.now ? { now: options.now } : {}),
|
|
268
|
+
}),
|
|
269
|
+
snapshot: () => Object.fromEntries([...counts].map(([key, value]) => [key, { ...value }])),
|
|
270
|
+
reset: () => counts.clear(),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure invocation: the one way to run a procedure.
|
|
3
|
+
*
|
|
4
|
+
* `Client.exec()`, `Client.route()`, the local transport and `ProcedureServer` run each
|
|
5
|
+
* procedure through `invokeProcedure()`. The function validates the input, makes the context,
|
|
6
|
+
* runs the handler and validates each output. Thus every host applies the same rules
|
|
7
|
+
* (ARCHITECTURE-PROPOSALS-2026-10 P1).
|
|
8
|
+
*
|
|
9
|
+
* A handler gives one value, or it is a generator that yields values (a stream). The result
|
|
10
|
+
* tells which: `{ kind: "value" }` or `{ kind: "stream" }`. A caller that wants one value uses
|
|
11
|
+
* `outputValue()` (the last item of a stream). A caller that wants each value uses `outputItems()`.
|
|
12
|
+
*
|
|
13
|
+
* Interceptors run around each invocation, the nested calls too (roadmap 1.2): policy, tracing,
|
|
14
|
+
* timeouts and metrics for every host. `interceptors.ts` has a timeout, a tracing and a metrics
|
|
15
|
+
* interceptor.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
AnyProcedure,
|
|
20
|
+
ProcedureClient,
|
|
21
|
+
ProcedureContext,
|
|
22
|
+
ProcedurePath,
|
|
23
|
+
RepositoryProvider,
|
|
24
|
+
} from "./types.js";
|
|
25
|
+
import { pathToKey } from "./types.js";
|
|
26
|
+
import { validateSchema } from "./schema.js";
|
|
27
|
+
import type { ProcedureRegistry } from "./registry.js";
|
|
28
|
+
import { PROCEDURE_REGISTRY } from "./registry.js";
|
|
29
|
+
import { nestedCallRefusal } from "./policy.js";
|
|
30
|
+
import { scopeOf, withScope, type HydrationEvent } from "./ref.js";
|
|
31
|
+
import type { EventBus } from "../events/types.js";
|
|
32
|
+
import { getGlobalEventBus, withEventBusSignal } from "../events/bus.js";
|
|
33
|
+
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Errors
|
|
36
|
+
// =============================================================================
|
|
37
|
+
|
|
38
|
+
/** The reasons for which an invocation fails before or after the handler. */
|
|
39
|
+
export type InvocationErrorCode =
|
|
40
|
+
| "NOT_FOUND"
|
|
41
|
+
| "NO_HANDLER"
|
|
42
|
+
| "NOT_EXPOSED"
|
|
43
|
+
| "NOT_DECLARED"
|
|
44
|
+
| "VALIDATION_ERROR"
|
|
45
|
+
| "OUTPUT_VALIDATION_ERROR"
|
|
46
|
+
| "NO_OUTPUT"
|
|
47
|
+
| "ABORTED"
|
|
48
|
+
| "TIMEOUT";
|
|
49
|
+
|
|
50
|
+
/** An error of the invocation itself. An error that the handler throws passes through unchanged. */
|
|
51
|
+
export class InvocationError extends Error {
|
|
52
|
+
override readonly name = "InvocationError";
|
|
53
|
+
readonly code: InvocationErrorCode;
|
|
54
|
+
readonly path: ProcedurePath;
|
|
55
|
+
readonly retryable: boolean = false;
|
|
56
|
+
|
|
57
|
+
constructor(code: InvocationErrorCode, message: string, path: ProcedurePath) {
|
|
58
|
+
super(message);
|
|
59
|
+
this.code = code;
|
|
60
|
+
this.path = path;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function abortError(path: ProcedurePath): InvocationError {
|
|
65
|
+
return new InvocationError("ABORTED", `Procedure was aborted: ${pathToKey(path)}`, path);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// Types
|
|
70
|
+
// =============================================================================
|
|
71
|
+
|
|
72
|
+
/** The output of an invocation: one value, or a stream of values. */
|
|
73
|
+
export type ProcedureOutput<T = unknown> =
|
|
74
|
+
| { readonly kind: "value"; readonly value: T }
|
|
75
|
+
| { readonly kind: "stream"; readonly items: AsyncGenerator<T, void, undefined> };
|
|
76
|
+
|
|
77
|
+
export interface InvokeOptions {
|
|
78
|
+
/**
|
|
79
|
+
* The hydration observer of the program (see `HydrateOptions.onRef`). It goes to the context
|
|
80
|
+
* (`ctx.onRef`) and to the nested calls, so the hydrations of this program report to it.
|
|
81
|
+
*/
|
|
82
|
+
onRef?: ((event: HydrationEvent) => void) | undefined;
|
|
83
|
+
/** The nested calls of `ctx.client` find their procedures here. The default is `PROCEDURE_REGISTRY`. */
|
|
84
|
+
registry?: ProcedureRegistry | undefined;
|
|
85
|
+
metadata?: Record<string, unknown> | undefined;
|
|
86
|
+
/** When the signal aborts, a stream stops, and its handler gets `return()`. */
|
|
87
|
+
signal?: AbortSignal | undefined;
|
|
88
|
+
repository?: RepositoryProvider | undefined;
|
|
89
|
+
/** The bus of `ctx.bus`. The default is the global bus of `getGlobalEventBus()`. */
|
|
90
|
+
bus?: EventBus | undefined;
|
|
91
|
+
/** The input is valid already (for example, the route resolver validated it). */
|
|
92
|
+
inputValidated?: boolean | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* This client replaces the default `ctx.client`, for example a Client that sends unknown paths
|
|
95
|
+
* to its transport. A function gets the invocation, so its nested calls can name their parent.
|
|
96
|
+
*/
|
|
97
|
+
client?: ProcedureClient | ((invocation: Invocation) => ProcedureClient) | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* The expose rule of a server. A data-driven procedure (control flow, `runs-refs`, a procedure
|
|
100
|
+
* that `procedure.define` made) can call only the paths for which it gives true. A code
|
|
101
|
+
* procedure with `metadata.calls` can call what it declares and the exposed paths. See
|
|
102
|
+
* `policy.ts` (deep dive MCP-3).
|
|
103
|
+
*/
|
|
104
|
+
expose?: ((path: ProcedurePath) => boolean) | undefined;
|
|
105
|
+
/** True: a code procedure without `metadata.calls` can call only the exposed paths. */
|
|
106
|
+
strictCalls?: boolean | undefined;
|
|
107
|
+
/** The interceptors of each invocation, the outermost first. The nested calls get them too. */
|
|
108
|
+
interceptors?: readonly Interceptor[] | undefined;
|
|
109
|
+
/** The invocation whose handler makes this call. The context client sets it for a nested call. */
|
|
110
|
+
parent?: Invocation | undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// Interceptors
|
|
115
|
+
// =============================================================================
|
|
116
|
+
|
|
117
|
+
let invocationCount = 0;
|
|
118
|
+
|
|
119
|
+
/** One invocation, as an interceptor sees it. */
|
|
120
|
+
export interface Invocation {
|
|
121
|
+
/** A number that identifies the invocation in this process. `next()` keeps it. */
|
|
122
|
+
readonly id: number;
|
|
123
|
+
readonly procedure: AnyProcedure;
|
|
124
|
+
readonly path: ProcedurePath;
|
|
125
|
+
/** The input before its validation. */
|
|
126
|
+
readonly input: unknown;
|
|
127
|
+
readonly metadata: Record<string, unknown>;
|
|
128
|
+
readonly signal: AbortSignal | undefined;
|
|
129
|
+
/** The invocation whose handler made this nested call. A call of a host has none. */
|
|
130
|
+
readonly parent: Invocation | undefined;
|
|
131
|
+
/** 0 for a call of a host, 1 for its nested calls, and so on. */
|
|
132
|
+
readonly depth: number;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** The changes that an interceptor gives to the next step: the handler and the nested calls get them. */
|
|
136
|
+
export interface InvocationChanges {
|
|
137
|
+
signal?: AbortSignal | undefined;
|
|
138
|
+
metadata?: Record<string, unknown> | undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The rest of the chain: the next interceptors, then the validation and the handler. */
|
|
142
|
+
export type InvocationNext = (changes?: InvocationChanges) => Promise<ProcedureOutput<unknown>>;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* A function around an invocation. It can examine the invocation, refuse it (throw), change its
|
|
146
|
+
* signal or metadata (`next(changes)`), and examine or wrap the output.
|
|
147
|
+
*/
|
|
148
|
+
export type Interceptor = (invocation: Invocation, next: InvocationNext) => Promise<ProcedureOutput<unknown>>;
|
|
149
|
+
|
|
150
|
+
// =============================================================================
|
|
151
|
+
// Invocation
|
|
152
|
+
// =============================================================================
|
|
153
|
+
|
|
154
|
+
/** True for a value that `for await` can read: a generator, a stream. A string is not one. */
|
|
155
|
+
export function isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {
|
|
156
|
+
return (
|
|
157
|
+
value !== null &&
|
|
158
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
159
|
+
typeof (value as { [Symbol.asyncIterator]?: unknown })[Symbol.asyncIterator] === "function"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** The output (or one stream item), validated by the output schema of the procedure. */
|
|
164
|
+
async function validateOutput(procedure: AnyProcedure, output: unknown): Promise<unknown> {
|
|
165
|
+
const result = await validateSchema(procedure.output, output);
|
|
166
|
+
if (!result.ok) {
|
|
167
|
+
throw new InvocationError(
|
|
168
|
+
"OUTPUT_VALIDATION_ERROR",
|
|
169
|
+
`Output validation failed for ${pathToKey(procedure.path)}: ${result.message}`,
|
|
170
|
+
procedure.path,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
return result.value;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The next item, or an abort error when the signal aborts first. */
|
|
177
|
+
function nextOrAbort<T>(iterator: AsyncIterator<T>, signal: AbortSignal, path: ProcedurePath): Promise<IteratorResult<T>> {
|
|
178
|
+
if (signal.aborted) return Promise.reject(abortError(path));
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const onAbort = (): void => reject(abortError(path));
|
|
181
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
182
|
+
iterator.next().then(
|
|
183
|
+
(result) => {
|
|
184
|
+
signal.removeEventListener("abort", onAbort);
|
|
185
|
+
resolve(result);
|
|
186
|
+
},
|
|
187
|
+
(error: unknown) => {
|
|
188
|
+
signal.removeEventListener("abort", onAbort);
|
|
189
|
+
reject(error);
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The items of a handler's stream, each validated with the output schema. When the reader stops
|
|
197
|
+
* early or an item is not valid, the handler's generator gets `return()`, so its `finally` runs.
|
|
198
|
+
*/
|
|
199
|
+
async function* validatedItems(
|
|
200
|
+
procedure: AnyProcedure,
|
|
201
|
+
source: AsyncIterable<unknown>,
|
|
202
|
+
signal: AbortSignal | undefined,
|
|
203
|
+
): AsyncGenerator<unknown, void, undefined> {
|
|
204
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
205
|
+
let done = false;
|
|
206
|
+
let aborted = false;
|
|
207
|
+
try {
|
|
208
|
+
for (;;) {
|
|
209
|
+
let step: IteratorResult<unknown>;
|
|
210
|
+
try {
|
|
211
|
+
step = signal ? await nextOrAbort(iterator, signal, procedure.path) : await iterator.next();
|
|
212
|
+
} catch (error) {
|
|
213
|
+
// The handler threw (its generator is done), or the signal aborted (it is not)
|
|
214
|
+
if (error instanceof InvocationError && error.code === "ABORTED") aborted = true;
|
|
215
|
+
else done = true;
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
if (step.done) {
|
|
219
|
+
done = true;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
yield await validateOutput(procedure, step.value);
|
|
223
|
+
}
|
|
224
|
+
} finally {
|
|
225
|
+
if (!done) {
|
|
226
|
+
// The generator of an aborted handler can wait on an await: do not wait for it
|
|
227
|
+
const closing = Promise.resolve(iterator.return?.()).catch(() => undefined);
|
|
228
|
+
if (!aborted) await closing;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* This function runs a procedure: it validates the input, makes the context, runs the handler
|
|
235
|
+
* and validates the output. It throws an `InvocationError` for an invocation that cannot run,
|
|
236
|
+
* and the handler's own error when the handler throws. The interceptors of the options run
|
|
237
|
+
* around these steps.
|
|
238
|
+
*/
|
|
239
|
+
export async function invokeProcedure<TOutput = unknown>(
|
|
240
|
+
procedure: AnyProcedure,
|
|
241
|
+
input: unknown,
|
|
242
|
+
options: InvokeOptions = {},
|
|
243
|
+
): Promise<ProcedureOutput<TOutput>> {
|
|
244
|
+
const { path } = procedure;
|
|
245
|
+
if (!procedure.handler) {
|
|
246
|
+
throw new InvocationError("NO_HANDLER", `Procedure has no handler: ${pathToKey(path)}`, path);
|
|
247
|
+
}
|
|
248
|
+
if (options.signal?.aborted) throw abortError(path);
|
|
249
|
+
|
|
250
|
+
const invocation: Invocation = {
|
|
251
|
+
id: ++invocationCount,
|
|
252
|
+
procedure,
|
|
253
|
+
path,
|
|
254
|
+
input,
|
|
255
|
+
metadata: options.metadata ?? {},
|
|
256
|
+
signal: options.signal,
|
|
257
|
+
parent: options.parent,
|
|
258
|
+
depth: options.parent ? options.parent.depth + 1 : 0,
|
|
259
|
+
};
|
|
260
|
+
const interceptors = options.interceptors ?? [];
|
|
261
|
+
if (interceptors.length === 0) return runInvocation<TOutput>(invocation, options);
|
|
262
|
+
|
|
263
|
+
const dispatch = (index: number, current: Invocation, currentOptions: InvokeOptions): Promise<ProcedureOutput<unknown>> => {
|
|
264
|
+
const interceptor = interceptors[index];
|
|
265
|
+
if (!interceptor) return runInvocation(current, currentOptions);
|
|
266
|
+
return interceptor(current, (changes) => {
|
|
267
|
+
if (!changes) return dispatch(index + 1, current, currentOptions);
|
|
268
|
+
const changed: Invocation = {
|
|
269
|
+
...current,
|
|
270
|
+
signal: changes.signal ?? current.signal,
|
|
271
|
+
metadata: changes.metadata ?? current.metadata,
|
|
272
|
+
};
|
|
273
|
+
return dispatch(index + 1, changed, { ...currentOptions, signal: changed.signal, metadata: changed.metadata });
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
return dispatch(0, invocation, options) as Promise<ProcedureOutput<TOutput>>;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** The end of the chain: the validation, the context, the handler and the output. */
|
|
280
|
+
async function runInvocation<TOutput>(invocation: Invocation, options: InvokeOptions): Promise<ProcedureOutput<TOutput>> {
|
|
281
|
+
const { procedure, path, input } = invocation;
|
|
282
|
+
const handler = procedure.handler!;
|
|
283
|
+
if (options.signal?.aborted) throw abortError(path);
|
|
284
|
+
|
|
285
|
+
let data: unknown = input;
|
|
286
|
+
if (!options.inputValidated) {
|
|
287
|
+
// A synchronous schema gives its result at once, so the handler starts before an await
|
|
288
|
+
let parsed = validateSchema(procedure.input, input);
|
|
289
|
+
if (parsed instanceof Promise) parsed = await parsed;
|
|
290
|
+
if (!parsed.ok) {
|
|
291
|
+
throw new InvocationError(
|
|
292
|
+
"VALIDATION_ERROR",
|
|
293
|
+
`Input validation failed for ${pathToKey(path)}: ${parsed.message}`,
|
|
294
|
+
path,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
// A parse makes a new object, without the hidden scope of a raw input (`withScope()`). The
|
|
298
|
+
// scope goes onto the parsed data, so a runner with a Zod schema can read the names of the
|
|
299
|
+
// caller (docs review DOC-10: before, each runner needed its own workaround).
|
|
300
|
+
data = parsed.value === input ? input : withScope(parsed.value, scopeOf(input));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// The handler starts here, before the first await (the site's trace depends on it)
|
|
304
|
+
const result: unknown = await handler(data, createProcedureContext(procedure, options, invocation));
|
|
305
|
+
if (isAsyncIterable(result)) {
|
|
306
|
+
return { kind: "stream", items: validatedItems(procedure, result, options.signal) as AsyncGenerator<TOutput, void, undefined> };
|
|
307
|
+
}
|
|
308
|
+
return { kind: "value", value: (await validateOutput(procedure, result)) as TOutput };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** This function finds the procedure at a path in the registry of the options, then runs it. */
|
|
312
|
+
export async function invokePath<TOutput = unknown>(
|
|
313
|
+
path: ProcedurePath,
|
|
314
|
+
input: unknown,
|
|
315
|
+
options: InvokeOptions = {},
|
|
316
|
+
): Promise<ProcedureOutput<TOutput>> {
|
|
317
|
+
const procedure = (options.registry ?? PROCEDURE_REGISTRY).get(path);
|
|
318
|
+
if (!procedure) {
|
|
319
|
+
throw new InvocationError("NOT_FOUND", `Procedure not found: ${pathToKey(path)}`, path);
|
|
320
|
+
}
|
|
321
|
+
return invokeProcedure<TOutput>(procedure, input, options);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// =============================================================================
|
|
325
|
+
// Consumption
|
|
326
|
+
// =============================================================================
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* One value of an output: the value, or the last item of a stream (the "sponge" mode). An
|
|
330
|
+
* empty stream is an error.
|
|
331
|
+
*/
|
|
332
|
+
export async function outputValue<T>(output: ProcedureOutput<T>, path: ProcedurePath = []): Promise<T> {
|
|
333
|
+
if (output.kind === "value") return output.value;
|
|
334
|
+
let last: { value: T } | undefined;
|
|
335
|
+
for await (const item of output.items) last = { value: item };
|
|
336
|
+
if (!last) {
|
|
337
|
+
throw new InvocationError("NO_OUTPUT", `Procedure gave no output: ${pathToKey(path)}`, path);
|
|
338
|
+
}
|
|
339
|
+
return last.value;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Each value of an output: the items of a stream, or the one value. */
|
|
343
|
+
export async function* outputItems<T>(output: ProcedureOutput<T>): AsyncGenerator<T, void, undefined> {
|
|
344
|
+
if (output.kind === "value") {
|
|
345
|
+
yield output.value;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
yield* output.items;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** The items of an output that `start` gives. Nothing runs until the reader asks for the first item. */
|
|
352
|
+
export async function* streamOutput<T>(start: () => Promise<ProcedureOutput<T>>): AsyncGenerator<T, void, undefined> {
|
|
353
|
+
yield* outputItems(await start());
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// =============================================================================
|
|
357
|
+
// Context
|
|
358
|
+
// =============================================================================
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* The context of a procedure. Its `client` calls other procedures through `invokePath()` with
|
|
362
|
+
* the same options, so the nested calls get the same metadata, signal, rules and interceptors.
|
|
363
|
+
* With an invocation, the nested calls name it as their parent.
|
|
364
|
+
*/
|
|
365
|
+
export function createProcedureContext(
|
|
366
|
+
procedure: AnyProcedure,
|
|
367
|
+
options: InvokeOptions = {},
|
|
368
|
+
invocation?: Invocation,
|
|
369
|
+
): ProcedureContext {
|
|
370
|
+
const nestedOptions: InvokeOptions = invocation ? { ...options, parent: invocation } : options;
|
|
371
|
+
let client: ProcedureClient;
|
|
372
|
+
if (typeof options.client === "function") {
|
|
373
|
+
client = invocation ? options.client(invocation) : registryClient(procedure, nestedOptions);
|
|
374
|
+
} else {
|
|
375
|
+
client = options.client ?? registryClient(procedure, nestedOptions);
|
|
376
|
+
}
|
|
377
|
+
const context: ProcedureContext = {
|
|
378
|
+
metadata: options.metadata ?? {},
|
|
379
|
+
path: procedure.path,
|
|
380
|
+
client,
|
|
381
|
+
registry: options.registry ?? PROCEDURE_REGISTRY,
|
|
382
|
+
};
|
|
383
|
+
if (options.signal) context.signal = options.signal;
|
|
384
|
+
if (options.repository) context.repository = options.repository;
|
|
385
|
+
if (options.onRef) context.onRef = options.onRef;
|
|
386
|
+
// Every context has a bus. With a signal, the waits of the handler on the bus end when the
|
|
387
|
+
// invocation aborts, so a stream handler that waits on ctx.bus.stream() can finish. (Before,
|
|
388
|
+
// no host set ctx.bus: deep dive CORE-15.)
|
|
389
|
+
const bus = options.bus ?? getGlobalEventBus();
|
|
390
|
+
context.bus = options.signal ? withEventBusSignal(bus, options.signal) : bus;
|
|
391
|
+
return context;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** The client of a procedure's context: it runs the nested calls from the registry. */
|
|
395
|
+
function registryClient(caller: AnyProcedure, options: InvokeOptions): ProcedureClient {
|
|
396
|
+
const start = <TOutput>(path: ProcedurePath, input: unknown): Promise<ProcedureOutput<TOutput>> => {
|
|
397
|
+
// The call policy of the host, with the immediate caller (BUGS-2026-07 H18, deep dive MCP-3).
|
|
398
|
+
// It runs before the lookup, so a refused path tells nothing about the procedure.
|
|
399
|
+
const refusal = nestedCallRefusal(caller, path, options);
|
|
400
|
+
if (refusal) {
|
|
401
|
+
return Promise.reject(new InvocationError(refusal.code, refusal.message, path));
|
|
402
|
+
}
|
|
403
|
+
return invokePath<TOutput>(path, input, options);
|
|
404
|
+
};
|
|
405
|
+
return {
|
|
406
|
+
async call<TInput, TOutput>(path: ProcedurePath, input: TInput): Promise<TOutput> {
|
|
407
|
+
return outputValue(await start<TOutput>(path, input), path);
|
|
408
|
+
},
|
|
409
|
+
stream<TInput, TOutput>(path: ProcedurePath, input: TInput): AsyncIterable<TOutput> {
|
|
410
|
+
return streamOutput(() => start<TOutput>(path, input));
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|