@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,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers that the client middlewares share.
|
|
3
|
+
*
|
|
4
|
+
* The transports report a failure as an error item, not as a thrown error. The middlewares use
|
|
5
|
+
* the same style: a timeout, an abort or a refused retry is an error item, and `Client` throws
|
|
6
|
+
* it when `throwOnError` is on (deep dive TRN-7: before, the timeout middleware waited for a
|
|
7
|
+
* thrown error that the transports never threw).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ResponseItem } from "../types.js";
|
|
11
|
+
|
|
12
|
+
/** This function makes an error item. */
|
|
13
|
+
export function errorItem<TRes>(id: string, code: string, message: string, retryable: boolean): ResponseItem<TRes> {
|
|
14
|
+
return { id, status: { type: "error", code, message, retryable }, payload: null as TRes, metadata: {} };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** The error item of a request that its caller aborted. A retry does not repeat it. */
|
|
18
|
+
export function abortedItem<TRes>(id: string): ResponseItem<TRes> {
|
|
19
|
+
return errorItem<TRes>(id, "ABORTED", "Request was aborted", false);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const NETWORK_CODES = new Set([
|
|
23
|
+
"ECONNREFUSED",
|
|
24
|
+
"ECONNRESET",
|
|
25
|
+
"ECONNABORTED",
|
|
26
|
+
"EPIPE",
|
|
27
|
+
"ETIMEDOUT",
|
|
28
|
+
"ENETUNREACH",
|
|
29
|
+
"EHOSTUNREACH",
|
|
30
|
+
"ENOTFOUND",
|
|
31
|
+
"EAI_AGAIN",
|
|
32
|
+
"UND_ERR_SOCKET",
|
|
33
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
34
|
+
"NETWORK_ERROR",
|
|
35
|
+
"CONNECTION_REFUSED",
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* This function tells if a thrown error is a network failure: the connection failed or broke.
|
|
40
|
+
* A retry can repair a network failure. A validation error, an open circuit breaker or a rate
|
|
41
|
+
* limit cannot be repaired by a retry (deep dive TRN-8).
|
|
42
|
+
*/
|
|
43
|
+
export function isNetworkError(error: unknown): boolean {
|
|
44
|
+
if (!(error instanceof Error)) return false;
|
|
45
|
+
const code = (error as { code?: unknown }).code;
|
|
46
|
+
if (typeof code === "string" && NETWORK_CODES.has(code)) return true;
|
|
47
|
+
const cause = (error as { cause?: unknown }).cause;
|
|
48
|
+
if (cause !== undefined && cause !== error && isNetworkError(cause)) return true;
|
|
49
|
+
// fetch() rejects with TypeError("fetch failed") when the connection fails
|
|
50
|
+
if (error.name === "TypeError" && /fetch failed|network/i.test(error.message)) return true;
|
|
51
|
+
// The WebSocket transport fails the requests of a connection that closed or never opened
|
|
52
|
+
return /WebSocket (connection closed|disconnected)|Connection timeout/.test(error.message);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The item that stands for a thrown error, so that `shouldRetry` can decide about it. It is
|
|
57
|
+
* retryable only when the error is a network failure.
|
|
58
|
+
*/
|
|
59
|
+
export function thrownItem<TRes>(id: string, error: unknown): ResponseItem<TRes> {
|
|
60
|
+
const code = (error as { code?: unknown } | undefined)?.code;
|
|
61
|
+
return errorItem<TRes>(
|
|
62
|
+
id,
|
|
63
|
+
typeof code === "string" ? code : "THROWN",
|
|
64
|
+
error instanceof Error ? error.message : String(error),
|
|
65
|
+
isNetworkError(error),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* This function waits `ms` milliseconds. It returns false at once when the signal aborts (deep
|
|
71
|
+
* dive TRN-8: before, the backoff of the retry middleware ignored the signal).
|
|
72
|
+
*/
|
|
73
|
+
export function sleep(ms: number, signal?: AbortSignal): Promise<boolean> {
|
|
74
|
+
if (signal?.aborted) return Promise.resolve(false);
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const onAbort = (): void => {
|
|
77
|
+
clearTimeout(timer);
|
|
78
|
+
resolve(false);
|
|
79
|
+
};
|
|
80
|
+
const timer = setTimeout(() => {
|
|
81
|
+
signal?.removeEventListener("abort", onAbort);
|
|
82
|
+
resolve(true);
|
|
83
|
+
}, Math.max(0, ms));
|
|
84
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The value that `nextOrAbort` gives when the signal aborts first. */
|
|
89
|
+
export const ABORTED_FIRST: unique symbol = Symbol("aborted first");
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The next result of an iterator, or `ABORTED_FIRST` when the signal aborts first. A transport
|
|
93
|
+
* that ignores the signal cannot keep the caller waiting past its timeout.
|
|
94
|
+
*/
|
|
95
|
+
export function nextOrAbort<T>(
|
|
96
|
+
iterator: AsyncIterator<T>,
|
|
97
|
+
signal: AbortSignal,
|
|
98
|
+
): Promise<IteratorResult<T> | typeof ABORTED_FIRST> {
|
|
99
|
+
if (signal.aborted) return Promise.resolve(ABORTED_FIRST);
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
const onAbort = (): void => resolve(ABORTED_FIRST);
|
|
102
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
103
|
+
iterator.next().then(
|
|
104
|
+
(result) => {
|
|
105
|
+
signal.removeEventListener("abort", onAbort);
|
|
106
|
+
resolve(result);
|
|
107
|
+
},
|
|
108
|
+
(error: unknown) => {
|
|
109
|
+
signal.removeEventListener("abort", onAbort);
|
|
110
|
+
reject(error);
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A map with a capacity, for the cache middleware.
|
|
3
|
+
*
|
|
4
|
+
* A JavaScript `Map` keeps its keys in the order of insertion. A read moves its key to the end,
|
|
5
|
+
* so the first key is always the least recently used one. A write that goes over the capacity
|
|
6
|
+
* removes the first key. The core has this small map itself, so it does not depend on
|
|
7
|
+
* `@procedures/collections` (roadmap 3.3: before, the cache composed `lruMap` and
|
|
8
|
+
* `hashMap` of that package).
|
|
9
|
+
*/
|
|
10
|
+
export class LruMap<K, V> {
|
|
11
|
+
private readonly entries = new Map<K, V>();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param capacity - The largest number of keys. A positive whole number.
|
|
15
|
+
* @param onEvict - Called for each key that a write removes to keep the capacity.
|
|
16
|
+
*/
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly capacity: number,
|
|
19
|
+
private readonly onEvict?: (key: K, value: V) => void
|
|
20
|
+
) {
|
|
21
|
+
if (!Number.isInteger(capacity) || capacity < 1) {
|
|
22
|
+
throw new RangeError(`The capacity of an LRU map must be a positive whole number, not ${capacity}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** The number of keys. */
|
|
27
|
+
get size(): number {
|
|
28
|
+
return this.entries.size;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** True when the map has the key. This does not count as a use. */
|
|
32
|
+
has(key: K): boolean {
|
|
33
|
+
return this.entries.has(key);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The value of the key, or undefined. A read makes the key the most recently used one. */
|
|
37
|
+
get(key: K): V | undefined {
|
|
38
|
+
if (!this.entries.has(key)) return undefined;
|
|
39
|
+
const value = this.entries.get(key) as V;
|
|
40
|
+
this.entries.delete(key);
|
|
41
|
+
this.entries.set(key, value);
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Set the value of a key, as the most recently used one. Over the capacity, the oldest key goes. */
|
|
46
|
+
set(key: K, value: V): void {
|
|
47
|
+
this.entries.delete(key);
|
|
48
|
+
this.entries.set(key, value);
|
|
49
|
+
while (this.entries.size > this.capacity) {
|
|
50
|
+
const oldest = this.entries.keys().next().value as K;
|
|
51
|
+
const evicted = this.entries.get(oldest) as V;
|
|
52
|
+
this.entries.delete(oldest);
|
|
53
|
+
this.onEvict?.(oldest, evicted);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Delete a key. True when it existed. */
|
|
58
|
+
delete(key: K): boolean {
|
|
59
|
+
return this.entries.delete(key);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Delete every key. */
|
|
63
|
+
clear(): void {
|
|
64
|
+
this.entries.clear();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal Pagination Middleware
|
|
3
|
+
*
|
|
4
|
+
* Protocol-agnostic pagination handling.
|
|
5
|
+
* Works with any transport!
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ClientRunner, ClientContext, TypedClientMiddleware } from "../types.js";
|
|
9
|
+
import type { PaginationContext } from "./contexts.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Pagination middleware options.
|
|
13
|
+
*/
|
|
14
|
+
export interface PaginationOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Default page size
|
|
17
|
+
* @default 50
|
|
18
|
+
*/
|
|
19
|
+
defaultLimit?: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Maximum page size (prevents abuse)
|
|
23
|
+
* @default 1000
|
|
24
|
+
*/
|
|
25
|
+
maxLimit?: number;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Page parameter name in metadata
|
|
29
|
+
* @default "page"
|
|
30
|
+
*/
|
|
31
|
+
pageKey?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Limit parameter name in metadata
|
|
35
|
+
* @default "limit"
|
|
36
|
+
*/
|
|
37
|
+
limitKey?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Offset parameter name in metadata (alternative to page)
|
|
41
|
+
* @default "offset"
|
|
42
|
+
*/
|
|
43
|
+
offsetKey?: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether to use offset-based pagination instead of page-based
|
|
47
|
+
* @default false
|
|
48
|
+
*/
|
|
49
|
+
useOffset?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create pagination middleware.
|
|
54
|
+
*
|
|
55
|
+
* Automatically handles pagination parameters in request metadata:
|
|
56
|
+
* - Applies default limit if not specified
|
|
57
|
+
* - Enforces maximum limit to prevent abuse
|
|
58
|
+
* - Supports both page-based and offset-based pagination
|
|
59
|
+
*
|
|
60
|
+
* @param options - Pagination configuration
|
|
61
|
+
* @returns Middleware function
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* // Page-based pagination
|
|
66
|
+
* client.use(createPaginationMiddleware({
|
|
67
|
+
* defaultLimit: 50,
|
|
68
|
+
* maxLimit: 1000
|
|
69
|
+
* }));
|
|
70
|
+
*
|
|
71
|
+
* await client.call(
|
|
72
|
+
* { service: "users", operation: "list" },
|
|
73
|
+
* {},
|
|
74
|
+
* { page: 2, limit: 100 } // Metadata
|
|
75
|
+
* );
|
|
76
|
+
*
|
|
77
|
+
* // Offset-based pagination
|
|
78
|
+
* client.use(createPaginationMiddleware({
|
|
79
|
+
* useOffset: true,
|
|
80
|
+
* defaultLimit: 50
|
|
81
|
+
* }));
|
|
82
|
+
*
|
|
83
|
+
* await client.call(
|
|
84
|
+
* { service: "users", operation: "list" },
|
|
85
|
+
* {},
|
|
86
|
+
* { offset: 100, limit: 50 } // Metadata
|
|
87
|
+
* );
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export function createPaginationMiddleware(
|
|
91
|
+
options: PaginationOptions = {}
|
|
92
|
+
): TypedClientMiddleware<PaginationContext, {}> {
|
|
93
|
+
const {
|
|
94
|
+
defaultLimit = 50,
|
|
95
|
+
maxLimit = 1000,
|
|
96
|
+
pageKey = "page",
|
|
97
|
+
limitKey = "limit",
|
|
98
|
+
offsetKey = "offset",
|
|
99
|
+
useOffset = false,
|
|
100
|
+
} = options;
|
|
101
|
+
|
|
102
|
+
return <TReq, TRes>(next: ClientRunner<TReq, TRes>): ClientRunner<TReq, TRes> => {
|
|
103
|
+
return async function* (context: ClientContext<TReq>) {
|
|
104
|
+
const { metadata } = context.message;
|
|
105
|
+
|
|
106
|
+
// Extract pagination params
|
|
107
|
+
let page = metadata[pageKey] as number | undefined;
|
|
108
|
+
let limit = metadata[limitKey] as number | undefined;
|
|
109
|
+
let offset = metadata[offsetKey] as number | undefined;
|
|
110
|
+
|
|
111
|
+
// Apply defaults and limits
|
|
112
|
+
if (limit === undefined) {
|
|
113
|
+
limit = defaultLimit;
|
|
114
|
+
} else {
|
|
115
|
+
// Enforce maximum limit
|
|
116
|
+
limit = Math.min(Math.max(1, limit), maxLimit);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (useOffset) {
|
|
120
|
+
// Offset-based pagination
|
|
121
|
+
if (offset === undefined) {
|
|
122
|
+
offset = 0;
|
|
123
|
+
} else {
|
|
124
|
+
offset = Math.max(0, offset);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Update message metadata, with the state as one object (PaginationContext)
|
|
128
|
+
context.message.metadata = {
|
|
129
|
+
...metadata,
|
|
130
|
+
[offsetKey]: offset,
|
|
131
|
+
[limitKey]: limit,
|
|
132
|
+
pagination: { offset, limit },
|
|
133
|
+
};
|
|
134
|
+
} else {
|
|
135
|
+
// Page-based pagination
|
|
136
|
+
if (page === undefined) {
|
|
137
|
+
page = 1;
|
|
138
|
+
} else {
|
|
139
|
+
page = Math.max(1, page);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Update message metadata, with the state as one object (PaginationContext)
|
|
143
|
+
context.message.metadata = {
|
|
144
|
+
...metadata,
|
|
145
|
+
[pageKey]: page,
|
|
146
|
+
[limitKey]: limit,
|
|
147
|
+
pagination: { page, limit },
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Optionally compute offset for backends that need it
|
|
151
|
+
const computedOffset = (page - 1) * limit;
|
|
152
|
+
if (metadata["includeOffset"]) {
|
|
153
|
+
context.message.metadata[offsetKey] = computedOffset;
|
|
154
|
+
context.message.metadata["pagination"] = { page, offset: computedOffset, limit };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Execute request
|
|
159
|
+
yield* next(context);
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Helper to create an async iterator for paginated results.
|
|
166
|
+
*
|
|
167
|
+
* Automatically fetches all pages and yields items as they arrive.
|
|
168
|
+
*
|
|
169
|
+
* @param client - The client instance
|
|
170
|
+
* @param method - Method to call
|
|
171
|
+
* @param payload - Request payload
|
|
172
|
+
* @param options - Pagination options
|
|
173
|
+
* @returns Async iterable of all items across all pages
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* // Fetch all users across all pages
|
|
178
|
+
* for await (const user of paginateAll(client, { service: "users", operation: "list" }, {})) {
|
|
179
|
+
* console.log(user);
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export async function* paginateAll<TReq, TRes extends { items: any[]; hasMore?: boolean; total?: number }>(
|
|
184
|
+
client: { call: (method: any, payload: TReq, metadata?: any) => Promise<TRes> },
|
|
185
|
+
method: any,
|
|
186
|
+
payload: TReq,
|
|
187
|
+
options: { limit?: number; maxPages?: number } = {}
|
|
188
|
+
): AsyncIterable<TRes extends { items: (infer U)[] } ? U : never> {
|
|
189
|
+
const { limit = 50, maxPages = Infinity } = options;
|
|
190
|
+
let page = 1;
|
|
191
|
+
let hasMore = true;
|
|
192
|
+
|
|
193
|
+
while (hasMore && page <= maxPages) {
|
|
194
|
+
const response = await client.call(method, payload, { page, limit });
|
|
195
|
+
|
|
196
|
+
// Yield all items from this page
|
|
197
|
+
for (const item of response.items) {
|
|
198
|
+
yield item;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Check if there are more pages
|
|
202
|
+
if (response.hasMore !== undefined) {
|
|
203
|
+
hasMore = response.hasMore;
|
|
204
|
+
} else if (response.total !== undefined) {
|
|
205
|
+
hasMore = page * limit < response.total;
|
|
206
|
+
} else {
|
|
207
|
+
// If no pagination metadata, check if we got a full page
|
|
208
|
+
hasMore = response.items.length === limit;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
page++;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Middleware
|
|
3
|
+
*
|
|
4
|
+
* Throttles requests using token bucket algorithm.
|
|
5
|
+
* Prevents overwhelming services with too many requests.
|
|
6
|
+
*
|
|
7
|
+
* Works with both client and server!
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ClientMiddleware, ClientRunner, ClientContext, TypedClientMiddleware } from "../types.js";
|
|
11
|
+
import type { RateLimitContext } from "./contexts.js";
|
|
12
|
+
import { abortedItem } from "./items.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Rate limiting options.
|
|
16
|
+
*/
|
|
17
|
+
export interface RateLimitOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Maximum number of requests per time window.
|
|
20
|
+
* @default 100
|
|
21
|
+
*/
|
|
22
|
+
maxRequests?: number;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Time window in milliseconds.
|
|
26
|
+
* @default 60000 (1 minute)
|
|
27
|
+
*/
|
|
28
|
+
window?: number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Behavior when rate limit is exceeded.
|
|
32
|
+
* - "reject": Throw error immediately
|
|
33
|
+
* - "queue": Queue requests and process when capacity available
|
|
34
|
+
* @default "reject"
|
|
35
|
+
*/
|
|
36
|
+
strategy?: "reject" | "queue";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Maximum queue size (only for "queue" strategy).
|
|
40
|
+
* @default 100
|
|
41
|
+
*/
|
|
42
|
+
maxQueueSize?: number;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Custom error message.
|
|
46
|
+
*/
|
|
47
|
+
message?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Callback when rate limit is exceeded.
|
|
51
|
+
*/
|
|
52
|
+
onRateLimitExceeded?: (stats: RateLimitStats) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Rate limit statistics.
|
|
57
|
+
*/
|
|
58
|
+
export interface RateLimitStats {
|
|
59
|
+
tokensAvailable: number;
|
|
60
|
+
maxTokens: number;
|
|
61
|
+
queueSize: number;
|
|
62
|
+
totalRequests: number;
|
|
63
|
+
rejectedRequests: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Rate limit error thrown when limit exceeded.
|
|
68
|
+
*/
|
|
69
|
+
export class RateLimitError extends Error {
|
|
70
|
+
constructor(
|
|
71
|
+
message: string,
|
|
72
|
+
public readonly stats: RateLimitStats
|
|
73
|
+
) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = "RateLimitError";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Queued request for "queue" strategy.
|
|
81
|
+
*/
|
|
82
|
+
interface QueuedRequest {
|
|
83
|
+
resolve: () => void;
|
|
84
|
+
reject: (error: Error) => void;
|
|
85
|
+
timestamp: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Create rate limiting middleware using token bucket algorithm.
|
|
90
|
+
*
|
|
91
|
+
* @param options - Rate limiting configuration
|
|
92
|
+
* @returns Middleware function
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Reject strategy (default)
|
|
97
|
+
* client.use(createRateLimitMiddleware({
|
|
98
|
+
* maxRequests: 100, // 100 requests
|
|
99
|
+
* window: 60000, // per minute
|
|
100
|
+
* strategy: "reject" // Throw error when exceeded
|
|
101
|
+
* }));
|
|
102
|
+
*
|
|
103
|
+
* // Queue strategy
|
|
104
|
+
* client.use(createRateLimitMiddleware({
|
|
105
|
+
* maxRequests: 10,
|
|
106
|
+
* window: 1000,
|
|
107
|
+
* strategy: "queue", // Queue requests when exceeded
|
|
108
|
+
* maxQueueSize: 50
|
|
109
|
+
* }));
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function createRateLimitMiddleware(
|
|
113
|
+
options: RateLimitOptions = {}
|
|
114
|
+
): TypedClientMiddleware<RateLimitContext, {}> {
|
|
115
|
+
const {
|
|
116
|
+
maxRequests = 100,
|
|
117
|
+
window = 60000,
|
|
118
|
+
strategy = "reject",
|
|
119
|
+
maxQueueSize = 100,
|
|
120
|
+
message = "Rate limit exceeded",
|
|
121
|
+
onRateLimitExceeded,
|
|
122
|
+
} = options;
|
|
123
|
+
|
|
124
|
+
// Token bucket state
|
|
125
|
+
let tokens = maxRequests;
|
|
126
|
+
let lastRefill = Date.now();
|
|
127
|
+
let totalRequests = 0;
|
|
128
|
+
let rejectedRequests = 0;
|
|
129
|
+
|
|
130
|
+
// Queue for "queue" strategy
|
|
131
|
+
const queue: QueuedRequest[] = [];
|
|
132
|
+
let drainTimer: ReturnType<typeof setTimeout> | undefined;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Refill tokens based on elapsed time.
|
|
136
|
+
*/
|
|
137
|
+
function refillTokens(): void {
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
const elapsed = now - lastRefill;
|
|
140
|
+
|
|
141
|
+
if (elapsed >= window) {
|
|
142
|
+
// Full refill
|
|
143
|
+
tokens = maxRequests;
|
|
144
|
+
lastRefill = now;
|
|
145
|
+
} else {
|
|
146
|
+
// Partial refill (tokens per millisecond * elapsed time)
|
|
147
|
+
const tokensToAdd = (maxRequests / window) * elapsed;
|
|
148
|
+
tokens = Math.min(maxRequests, tokens + tokensToAdd);
|
|
149
|
+
lastRefill = now;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get current statistics.
|
|
155
|
+
*/
|
|
156
|
+
function getStats(): RateLimitStats {
|
|
157
|
+
return {
|
|
158
|
+
tokensAvailable: Math.floor(tokens),
|
|
159
|
+
maxTokens: maxRequests,
|
|
160
|
+
queueSize: queue.length,
|
|
161
|
+
totalRequests,
|
|
162
|
+
rejectedRequests,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Acquire a token (blocking for queue strategy). Returns false when the signal aborted the
|
|
168
|
+
* wait. A new request waits behind the queued requests, also when a token is free: before,
|
|
169
|
+
* an arrival could take the token of a queued request (deep dive TRN-12).
|
|
170
|
+
*/
|
|
171
|
+
async function acquireToken(signal?: AbortSignal): Promise<boolean> {
|
|
172
|
+
refillTokens();
|
|
173
|
+
|
|
174
|
+
if (queue.length === 0 && tokens >= 1) {
|
|
175
|
+
// Token available
|
|
176
|
+
tokens -= 1;
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// No tokens available
|
|
181
|
+
const stats = getStats();
|
|
182
|
+
|
|
183
|
+
if (strategy === "reject") {
|
|
184
|
+
// Reject immediately
|
|
185
|
+
rejectedRequests++;
|
|
186
|
+
if (onRateLimitExceeded) {
|
|
187
|
+
onRateLimitExceeded(stats);
|
|
188
|
+
}
|
|
189
|
+
throw new RateLimitError(message, stats);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Queue strategy - wait for token
|
|
193
|
+
if (queue.length >= maxQueueSize) {
|
|
194
|
+
rejectedRequests++;
|
|
195
|
+
if (onRateLimitExceeded) {
|
|
196
|
+
onRateLimitExceeded(stats);
|
|
197
|
+
}
|
|
198
|
+
throw new RateLimitError(`${message} (queue full)`, stats);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (signal?.aborted) return false;
|
|
202
|
+
|
|
203
|
+
return new Promise<boolean>((resolve) => {
|
|
204
|
+
const request: QueuedRequest = {
|
|
205
|
+
resolve: () => {
|
|
206
|
+
signal?.removeEventListener("abort", onAbort);
|
|
207
|
+
resolve(true);
|
|
208
|
+
},
|
|
209
|
+
reject: () => resolve(false),
|
|
210
|
+
timestamp: Date.now(),
|
|
211
|
+
};
|
|
212
|
+
// A queued request whose caller aborts leaves the queue (before, it kept its place)
|
|
213
|
+
const onAbort = (): void => {
|
|
214
|
+
const index = queue.indexOf(request);
|
|
215
|
+
if (index >= 0) queue.splice(index, 1);
|
|
216
|
+
resolve(false);
|
|
217
|
+
};
|
|
218
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
219
|
+
queue.push(request);
|
|
220
|
+
scheduleDrain();
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Give tokens to the queued requests, in order, and wait for the next token while the queue
|
|
226
|
+
* is not empty. The timer keeps the process alive while requests wait: before, an unref'd
|
|
227
|
+
* timer let the process exit with queued requests that never ran (deep dive TRN-12).
|
|
228
|
+
*/
|
|
229
|
+
function scheduleDrain(): void {
|
|
230
|
+
if (drainTimer !== undefined) return;
|
|
231
|
+
refillTokens();
|
|
232
|
+
while (queue.length > 0 && tokens >= 1) {
|
|
233
|
+
tokens -= 1;
|
|
234
|
+
queue.shift()!.resolve();
|
|
235
|
+
}
|
|
236
|
+
if (queue.length === 0) return;
|
|
237
|
+
// The time until the next whole token
|
|
238
|
+
const wait = Math.max(1, Math.ceil(((1 - tokens) * window) / maxRequests));
|
|
239
|
+
drainTimer = setTimeout(() => {
|
|
240
|
+
drainTimer = undefined;
|
|
241
|
+
scheduleDrain();
|
|
242
|
+
}, wait);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const middleware = <TReq, TRes>(next: ClientRunner<TReq, TRes>): ClientRunner<TReq, TRes> => {
|
|
246
|
+
return async function* (context: ClientContext<TReq>) {
|
|
247
|
+
totalRequests++;
|
|
248
|
+
|
|
249
|
+
// Acquire token (may throw or wait)
|
|
250
|
+
if (!(await acquireToken(context.message.signal))) {
|
|
251
|
+
yield abortedItem<TRes>(context.message.id);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// The state for the other middlewares (RateLimitContext)
|
|
255
|
+
context.message.metadata["rateLimit"] = {
|
|
256
|
+
tokensAvailable: Math.floor(tokens),
|
|
257
|
+
maxTokens: maxRequests,
|
|
258
|
+
queueSize: queue.length,
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// Execute request
|
|
262
|
+
yield* next(context);
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
return middleware;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Create per-service rate limiter.
|
|
270
|
+
*
|
|
271
|
+
* Applies different rate limits based on service name.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* client.use(createPerServiceRateLimiter({
|
|
276
|
+
* users: { maxRequests: 100, window: 60000 },
|
|
277
|
+
* orders: { maxRequests: 50, window: 60000 },
|
|
278
|
+
* default: { maxRequests: 200, window: 60000 }
|
|
279
|
+
* }));
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
export function createPerServiceRateLimiter(
|
|
283
|
+
limits: Record<string, RateLimitOptions> & { default?: RateLimitOptions }
|
|
284
|
+
): ClientMiddleware {
|
|
285
|
+
// Create rate limiter for each service
|
|
286
|
+
const limiters = new Map<string, ClientMiddleware>();
|
|
287
|
+
|
|
288
|
+
for (const [service, options] of Object.entries(limits)) {
|
|
289
|
+
limiters.set(service, createRateLimitMiddleware(options));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const defaultLimiter = limits.default
|
|
293
|
+
? createRateLimitMiddleware(limits.default)
|
|
294
|
+
: null;
|
|
295
|
+
|
|
296
|
+
return <TReq, TRes>(next: ClientRunner<TReq, TRes>): ClientRunner<TReq, TRes> => {
|
|
297
|
+
return async function* (context: ClientContext<TReq>) {
|
|
298
|
+
// Get service name from context
|
|
299
|
+
const service = context.message.method.service;
|
|
300
|
+
|
|
301
|
+
// Get appropriate limiter
|
|
302
|
+
const limiter = limiters.get(service) ?? defaultLimiter;
|
|
303
|
+
|
|
304
|
+
if (limiter) {
|
|
305
|
+
// Apply service-specific rate limit
|
|
306
|
+
const typedLimiter = limiter as ClientMiddleware<TReq, TRes>;
|
|
307
|
+
const limitedNext = typedLimiter(next);
|
|
308
|
+
yield* limitedNext(context);
|
|
309
|
+
} else {
|
|
310
|
+
// No rate limit for this service
|
|
311
|
+
yield* next(context);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
}
|