@toa.io/extensions.exposition 1.0.0-alpha.285 → 1.0.0-alpha.286
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/components/exposition.octets/operations/delete.js +1 -1
- package/components/exposition.octets/operations/get.js +5 -2
- package/components/exposition.octets/operations/head.js +1 -1
- package/components/exposition.octets/operations/put.js +29 -37
- package/components/exposition.octets/types/toa.d.ts +1 -1
- package/components/identity.bans/manifest.toa.yaml +12 -13
- package/components/identity.bans/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.bans/operations/transit.js +1 -1
- package/components/identity.bans/source/transit.ts +1 -1
- package/components/identity.bans/tsconfig.tsbuildinfo +1 -1
- package/components/identity.bans/types/toa.d.ts +5 -5
- package/components/identity.basic/events/principal.js +3 -1
- package/components/identity.basic/manifest.toa.yaml +17 -23
- package/components/identity.basic/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.basic/migrations/0002-indexes.yaml +13 -0
- package/components/identity.basic/operations/add.js +1 -1
- package/components/identity.basic/operations/authenticate.js +2 -2
- package/components/identity.basic/operations/check.js +4 -2
- package/components/identity.basic/operations/delete.js +1 -1
- package/components/identity.basic/operations/incept.js +1 -1
- package/components/identity.basic/operations/info.js +1 -1
- package/components/identity.basic/operations/lib/credentials.js +1 -1
- package/components/identity.basic/operations/transit.js +7 -8
- package/components/identity.basic/source/add.ts +5 -2
- package/components/identity.basic/source/authenticate.ts +11 -13
- package/components/identity.basic/source/check.ts +9 -6
- package/components/identity.basic/source/delete.ts +4 -1
- package/components/identity.basic/source/incept.ts +13 -10
- package/components/identity.basic/source/info.ts +4 -1
- package/components/identity.basic/source/lib/credentials.ts +2 -3
- package/components/identity.basic/source/transit.ts +27 -21
- package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/types/index.d.ts +7 -3
- package/components/identity.basic/types/toa.d.ts +5 -5
- package/components/identity.clients/manifest.toa.yaml +36 -40
- package/components/identity.clients/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.clients/migrations/0002-indexes.yaml +4 -0
- package/components/identity.clients/operations/describe.js +1 -1
- package/components/identity.clients/operations/lib/canonical.js +1 -1
- package/components/identity.clients/operations/lib/cimd.js +3 -2
- package/components/identity.clients/operations/lib/redirect.js +7 -4
- package/components/identity.clients/operations/register.js +2 -2
- package/components/identity.clients/source/describe.ts +6 -8
- package/components/identity.clients/source/lib/Context.ts +6 -3
- package/components/identity.clients/source/lib/Entity.ts +1 -1
- package/components/identity.clients/source/lib/canonical.ts +1 -1
- package/components/identity.clients/source/lib/cimd.test.ts +8 -6
- package/components/identity.clients/source/lib/cimd.ts +24 -19
- package/components/identity.clients/source/lib/redirect.test.ts +8 -2
- package/components/identity.clients/source/lib/redirect.ts +12 -8
- package/components/identity.clients/source/register.ts +18 -18
- package/components/identity.clients/tsconfig.tsbuildinfo +1 -1
- package/components/identity.clients/types/toa.d.ts +5 -5
- package/components/identity.credentials/manifest.toa.yaml +4 -4
- package/components/identity.credentials/operations/list.js +8 -4
- package/components/identity.credentials/source/list.test.ts +39 -20
- package/components/identity.credentials/source/list.ts +12 -8
- package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
- package/components/identity.credentials/types/toa.d.ts +2 -2
- package/components/identity.federation/manifest.toa.yaml +23 -32
- package/components/identity.federation/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.federation/migrations/0002-indexes.yaml +25 -0
- package/components/identity.federation/operations/authenticate.js +4 -2
- package/components/identity.federation/operations/create.js +2 -2
- package/components/identity.federation/operations/decode.js +1 -1
- package/components/identity.federation/operations/delete.js +1 -1
- package/components/identity.federation/operations/incept.js +1 -1
- package/components/identity.federation/operations/lib/decode.js +1 -1
- package/components/identity.federation/operations/lib/discovery.js +2 -2
- package/components/identity.federation/operations/lib/exchange.js +8 -4
- package/components/identity.federation/operations/lib/principal.js +1 -1
- package/components/identity.federation/operations/lib/resolve.js +1 -1
- package/components/identity.federation/operations/list.js +2 -2
- package/components/identity.federation/source/authenticate.ts +19 -17
- package/components/identity.federation/source/create.ts +6 -7
- package/components/identity.federation/source/decode.ts +4 -1
- package/components/identity.federation/source/delete.ts +4 -1
- package/components/identity.federation/source/incept.ts +2 -3
- package/components/identity.federation/source/lib/decode.ts +4 -7
- package/components/identity.federation/source/lib/discovery.test.ts +15 -5
- package/components/identity.federation/source/lib/discovery.ts +10 -9
- package/components/identity.federation/source/lib/exchange.ts +18 -15
- package/components/identity.federation/source/lib/jose.d.ts +1 -1
- package/components/identity.federation/source/lib/principal.ts +5 -3
- package/components/identity.federation/source/lib/resolve.ts +5 -1
- package/components/identity.federation/source/list.test.ts +26 -10
- package/components/identity.federation/source/list.ts +5 -2
- package/components/identity.federation/source/types/context.ts +5 -2
- package/components/identity.federation/source/types/entity.ts +2 -2
- package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/types/toa.d.ts +5 -5
- package/components/identity.grants/manifest.toa.yaml +27 -31
- package/components/identity.grants/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.grants/migrations/0002-indexes.yaml +5 -0
- package/components/identity.grants/operations/authorize.js +1 -1
- package/components/identity.grants/operations/exchange.js +5 -2
- package/components/identity.grants/operations/lib/code.js +1 -1
- package/components/identity.grants/operations/lib/identify.js +1 -1
- package/components/identity.grants/operations/list.js +1 -1
- package/components/identity.grants/operations/revoke.js +3 -2
- package/components/identity.grants/source/authorize.ts +27 -19
- package/components/identity.grants/source/exchange.ts +15 -11
- package/components/identity.grants/source/lib/code.ts +20 -8
- package/components/identity.grants/source/lib/identify.ts +1 -1
- package/components/identity.grants/source/list.ts +2 -2
- package/components/identity.grants/source/revoke.ts +9 -7
- package/components/identity.grants/tsconfig.tsbuildinfo +1 -1
- package/components/identity.grants/types/index.d.ts +3 -3
- package/components/identity.grants/types/toa.d.ts +5 -5
- package/components/identity.keys/manifest.toa.yaml +18 -23
- package/components/identity.keys/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.keys/migrations/0002-indexes.yaml +4 -0
- package/components/identity.keys/operations/create.js +1 -1
- package/components/identity.keys/operations/disable.js +1 -1
- package/components/identity.keys/operations/revoke.js +1 -1
- package/components/identity.keys/source/create.ts +2 -3
- package/components/identity.keys/source/disable.ts +1 -1
- package/components/identity.keys/source/revoke.ts +2 -2
- package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.keys/types/toa.d.ts +5 -5
- package/components/identity.otp/manifest.toa.yaml +16 -24
- package/components/identity.otp/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.otp/migrations/0002-indexes.yaml +5 -0
- package/components/identity.otp/operations/authenticate.js +1 -1
- package/components/identity.otp/operations/issue.js +1 -1
- package/components/identity.otp/source/authenticate.ts +4 -7
- package/components/identity.otp/source/issue.ts +1 -1
- package/components/identity.otp/source/lib/Context.ts +1 -1
- package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/types/toa.d.ts +5 -5
- package/components/identity.passkeys/manifest.toa.yaml +45 -53
- package/components/identity.passkeys/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.passkeys/migrations/0002-indexes.yaml +11 -0
- package/components/identity.passkeys/operations/authenticate.js +1 -1
- package/components/identity.passkeys/operations/challenge.js +6 -3
- package/components/identity.passkeys/operations/create.js +1 -1
- package/components/identity.passkeys/operations/delete.js +1 -1
- package/components/identity.passkeys/operations/list.js +1 -1
- package/components/identity.passkeys/operations/use.js +1 -1
- package/components/identity.passkeys/source/authenticate.ts +3 -4
- package/components/identity.passkeys/source/challenge.ts +29 -25
- package/components/identity.passkeys/source/create.ts +8 -6
- package/components/identity.passkeys/source/delete.ts +4 -1
- package/components/identity.passkeys/source/list.ts +4 -1
- package/components/identity.passkeys/source/types/Context.ts +1 -1
- package/components/identity.passkeys/source/use.ts +12 -10
- package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/types/toa.d.ts +5 -5
- package/components/identity.roles/manifest.toa.yaml +12 -16
- package/components/identity.roles/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.roles/migrations/0002-indexes.yaml +8 -0
- package/components/identity.roles/operations/grant.js +1 -1
- package/components/identity.roles/operations/list.js +1 -1
- package/components/identity.roles/operations/principal.js +2 -2
- package/components/identity.roles/source/grant.ts +7 -6
- package/components/identity.roles/source/list.ts +1 -1
- package/components/identity.roles/source/principal.ts +5 -7
- package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/types/toa.d.ts +5 -5
- package/components/identity.tokens/manifest.toa.yaml +17 -15
- package/components/identity.tokens/migrations/0001-system-properties.yaml +14 -0
- package/components/identity.tokens/operations/authenticate.js +2 -2
- package/components/identity.tokens/operations/decrypt.js +11 -5
- package/components/identity.tokens/operations/encrypt.js +2 -2
- package/components/identity.tokens/operations/issue.js +2 -4
- package/components/identity.tokens/operations/lib/form.js +1 -1
- package/components/identity.tokens/operations/lib/key.js +1 -1
- package/components/identity.tokens/operations/revoke.js +1 -1
- package/components/identity.tokens/source/authenticate.test.ts +22 -16
- package/components/identity.tokens/source/authenticate.ts +7 -10
- package/components/identity.tokens/source/decrypt.test.ts +62 -29
- package/components/identity.tokens/source/decrypt.ts +30 -27
- package/components/identity.tokens/source/encrypt.test.ts +21 -16
- package/components/identity.tokens/source/encrypt.ts +8 -11
- package/components/identity.tokens/source/issue.test.ts +4 -2
- package/components/identity.tokens/source/issue.ts +6 -8
- package/components/identity.tokens/source/lib/form.ts +5 -9
- package/components/identity.tokens/source/lib/jose.d.ts +1 -1
- package/components/identity.tokens/source/lib/key.ts +1 -1
- package/components/identity.tokens/source/lib/paseto.test.ts +17 -6
- package/components/identity.tokens/source/revoke.ts +1 -1
- package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/types/index.d.ts +13 -4
- package/components/identity.tokens/types/toa.d.ts +5 -5
- package/context.toa.yaml +2 -2
- package/cucumber.mjs +3 -0
- package/documentation/access.md +4 -3
- package/documentation/cache.md +17 -3
- package/documentation/components.md +2 -2
- package/documentation/credentials.md +2 -2
- package/documentation/identity.md +7 -9
- package/documentation/map.md +2 -2
- package/documentation/mcp.md +16 -16
- package/documentation/notes/peers.md +1 -1
- package/documentation/notes/throttling.md +1 -1
- package/documentation/octets.md +4 -4
- package/documentation/protocol.md +3 -3
- package/documentation/query.md +14 -8
- package/documentation/rpc.md +31 -21
- package/documentation/tracing.md +3 -3
- package/documentation/tree.md +1 -1
- package/features/auth.assert.feature +2 -2
- package/features/auth.bearer.feature +1 -1
- package/features/auth.claims.feature +5 -5
- package/features/auth.incept.feature +2 -2
- package/features/authorities.federation.feature +1 -1
- package/features/configuration.feature +3 -4
- package/features/credentials.feature +9 -9
- package/features/dev.feature +1 -0
- package/features/dynamic.feature +1 -0
- package/features/errors.feature +21 -0
- package/features/etag.feature +0 -86
- package/features/identity.bans.feature +3 -3
- package/features/identity.basic.feature +9 -9
- package/features/identity.federation.feature +11 -11
- package/features/identity.tokens.custom.feature +5 -5
- package/features/identity.tokens.feature +2 -2
- package/features/interruptions.feature +1 -0
- package/features/introspection.map.feature +4 -4
- package/features/io.throttle.feature +1 -0
- package/features/map.feature +2 -2
- package/features/octets.cloudinary.feature +1 -1
- package/features/octets.download.feature +1 -0
- package/features/require.feature +1 -2
- package/features/steps/Captures.ts +1 -1
- package/features/steps/Cloudinary.ts +1 -2
- package/features/steps/Common.ts +4 -5
- package/features/steps/Components.ts +17 -12
- package/features/steps/Database.ts +42 -23
- package/features/steps/Gateway.ts +55 -72
- package/features/steps/HTTP.ts +12 -15
- package/features/steps/IDP.ts +118 -94
- package/features/steps/Identity.ts +3 -3
- package/features/steps/OTP.ts +3 -3
- package/features/steps/Parameters.ts +20 -10
- package/features/steps/Probe.ts +9 -7
- package/features/steps/Realtime.ts +40 -22
- package/features/steps/Workspace.ts +10 -7
- package/features/steps/components/audit/operations/record.js +1 -1
- package/features/steps/components/echo/operations/affect.js +1 -1
- package/features/steps/components/echo/operations/compute.js +1 -1
- package/features/steps/components/echo/operations/echo.js +1 -1
- package/features/steps/components/echo/operations/error.js +1 -1
- package/features/steps/components/echo/operations/identity.js +1 -1
- package/features/steps/components/echo/operations/parameters.js +1 -1
- package/features/steps/components/echo/operations/ping.js +1 -1
- package/features/steps/components/echo/operations/unwrap.js +1 -1
- package/features/steps/components/greeter/operations/greet.js +1 -1
- package/features/steps/components/notify/operations/send.js +1 -1
- package/features/steps/components/octets.tester/operations/authority.js +1 -1
- package/features/steps/components/octets.tester/operations/bar.js +1 -1
- package/features/steps/components/octets.tester/operations/baz.js +1 -1
- package/features/steps/components/octets.tester/operations/concat.js +1 -1
- package/features/steps/components/octets.tester/operations/echo.js +1 -1
- package/features/steps/components/octets.tester/operations/err.js +1 -1
- package/features/steps/components/octets.tester/operations/foo.js +1 -1
- package/features/steps/components/octets.tester/operations/id.js +1 -1
- package/features/steps/components/octets.tester/operations/identity.js +1 -1
- package/features/steps/components/octets.tester/operations/redirect.js +6 -4
- package/features/steps/components/octets.tester/operations/yex.js +1 -1
- package/features/steps/components/octets.tester/operations/yield.js +1 -1
- package/features/steps/components/orders/manifest.toa.yaml +10 -12
- package/features/steps/components/orders/operations/create.js +4 -2
- package/features/steps/components/pots/manifest.toa.yaml +15 -20
- package/features/steps/components/pots/migrations/0002-indexes.yaml +4 -0
- package/features/steps/components/pricing/operations/quote.js +1 -1
- package/features/steps/components/sequences/manifest.toa.yaml +0 -1
- package/features/steps/components/sequences/operations/numbers.js +1 -1
- package/features/steps/components/sequences/operations/tokens.js +3 -3
- package/features/steps/components/users/manifest.toa.yaml +3 -5
- package/features/steps/components/users/operations/create.js +1 -1
- package/features/steps/components/users.properties/manifest.toa.yaml +5 -6
- package/features/steps/map.ts +2 -2
- package/features/timestamps.feature +1 -1
- package/package.json +7 -7
- package/readme.md +11 -11
- package/schemas/annotation.cos.yaml +1 -3
- package/schemas/method.cos.yaml +2 -0
- package/source/Branch.test.ts +2 -2
- package/source/Branch.ts +3 -5
- package/source/Composition.ts +5 -5
- package/source/Directive.test.ts +38 -20
- package/source/Directive.ts +61 -47
- package/source/Endpoint.test.ts +1 -1
- package/source/Endpoint.ts +27 -92
- package/source/Factory.ts +26 -12
- package/source/Gateway.ts +87 -76
- package/source/HTTP/Context.ts +23 -30
- package/source/HTTP/Probe.ts +7 -9
- package/source/HTTP/Server.ts +88 -69
- package/source/HTTP/Timing.ts +6 -21
- package/source/HTTP/address.test.ts +8 -2
- package/source/HTTP/address.ts +2 -3
- package/source/HTTP/exceptions.ts +20 -18
- package/source/HTTP/formats/form.ts +1 -1
- package/source/HTTP/formats/json.ts +2 -2
- package/source/HTTP/formats/msgpack.ts +3 -4
- package/source/HTTP/formats/text.ts +2 -2
- package/source/HTTP/formats/yaml.test.ts +4 -1
- package/source/HTTP/formats/yaml.ts +14 -11
- package/source/HTTP/messages.test.ts +38 -28
- package/source/HTTP/messages.ts +44 -98
- package/source/Interception.ts +3 -4
- package/source/Introspection.ts +26 -14
- package/source/MCP/Server.ts +114 -54
- package/source/MCP/discover.ts +6 -7
- package/source/MCP/errors.ts +7 -8
- package/source/MCP/schema.test.ts +9 -3
- package/source/MCP/schema.ts +12 -16
- package/source/MCP/tools.ts +33 -28
- package/source/Mapping.ts +25 -27
- package/source/Query.ts +58 -44
- package/source/RPC/Context.ts +8 -11
- package/source/RPC/Dispatcher.ts +46 -26
- package/source/RPC/errors.test.ts +41 -16
- package/source/RPC/errors.ts +9 -10
- package/source/RPC/names.test.ts +35 -16
- package/source/RPC/names.ts +22 -29
- package/source/RTD/Directives.ts +21 -10
- package/source/RTD/Endpoint.ts +4 -1
- package/source/RTD/Method.ts +8 -6
- package/source/RTD/Node.ts +32 -34
- package/source/RTD/Route.ts +18 -21
- package/source/RTD/Tree.ts +18 -18
- package/source/RTD/factory.ts +13 -16
- package/source/RTD/segment.ts +12 -10
- package/source/RTD/syntax/parse.test.ts +12 -6
- package/source/RTD/syntax/parse.ts +30 -26
- package/source/RTD/syntax/types.ts +17 -1
- package/source/RTD/walk.test.ts +59 -22
- package/source/Remotes.test.ts +25 -4
- package/source/Remotes.ts +9 -4
- package/source/Tenant.ts +12 -12
- package/source/deployment.ts +20 -20
- package/source/directives/auth/Anonymous.test.ts +8 -2
- package/source/directives/auth/Anonymous.ts +5 -8
- package/source/directives/auth/Anyone.ts +3 -3
- package/source/directives/auth/Assert.ts +10 -10
- package/source/directives/auth/Authorization.ts +83 -69
- package/source/directives/auth/Delegate.test.ts +2 -2
- package/source/directives/auth/Delegate.ts +8 -10
- package/source/directives/auth/Echo.ts +5 -8
- package/source/directives/auth/Federation.ts +30 -21
- package/source/directives/auth/Id.ts +7 -4
- package/source/directives/auth/Incept.ts +32 -26
- package/source/directives/auth/Input.ts +36 -20
- package/source/directives/auth/Role.test.ts +49 -23
- package/source/directives/auth/Role.ts +29 -22
- package/source/directives/auth/Rule.ts +13 -8
- package/source/directives/auth/Scheme.ts +7 -7
- package/source/directives/auth/create.ts +1 -1
- package/source/directives/auth/schemes.ts +1 -1
- package/source/directives/auth/split.ts +2 -3
- package/source/directives/auth/types.ts +5 -2
- package/source/directives/cache/Cache.ts +44 -9
- package/source/directives/cache/Control.ts +25 -26
- package/source/directives/cache/Exact.ts +1 -1
- package/source/directives/cache/etag.ts +38 -0
- package/source/directives/cors/CORS.ts +9 -7
- package/source/directives/dev/Development.ts +3 -4
- package/source/directives/dev/Faulty.ts +11 -6
- package/source/directives/dev/Sleep.ts +5 -7
- package/source/directives/dev/Stub.ts +2 -2
- package/source/directives/dev/Throw.ts +2 -2
- package/source/directives/flow/Compose.ts +26 -20
- package/source/directives/flow/Fetch.ts +15 -15
- package/source/directives/flow/Flow.ts +9 -8
- package/source/directives/index.ts +11 -2
- package/source/directives/io/IO.ts +29 -20
- package/source/directives/io/Input.ts +9 -12
- package/source/directives/io/Output.ts +20 -23
- package/source/directives/io/Status.test.ts +12 -8
- package/source/directives/io/Status.ts +9 -8
- package/source/directives/io/Throttle.ts +6 -7
- package/source/directives/io/lib/throttle/Configuration.test.ts +32 -23
- package/source/directives/io/lib/throttle/Configuration.ts +14 -9
- package/source/directives/io/lib/throttle/Keys.ts +15 -10
- package/source/directives/io/lib/throttle/Quotas.test.ts +33 -17
- package/source/directives/io/lib/throttle/Quotas.ts +20 -26
- package/source/directives/io/lib/throttle/Sync.test.ts +14 -10
- package/source/directives/io/lib/throttle/Sync.ts +9 -12
- package/source/directives/io/lib/throttle/Warning.ts +3 -4
- package/source/directives/io/lib/throttle/components/IP.ts +4 -5
- package/source/directives/io/lib/throttle/components/Identity.ts +1 -1
- package/source/directives/io/lib/throttle/components/Path.ts +1 -1
- package/source/directives/io/lib/throttle/components/Route.ts +2 -2
- package/source/directives/io/lib/throttle/components/Segment.ts +2 -2
- package/source/directives/io/lib/throttle/conditions/Status.ts +2 -2
- package/source/directives/io/schemas.test.ts +12 -6
- package/source/directives/map/Authority.ts +2 -2
- package/source/directives/map/Buffer.ts +2 -2
- package/source/directives/map/Claims.ts +25 -20
- package/source/directives/map/Headers.ts +17 -13
- package/source/directives/map/Language.ts +8 -5
- package/source/directives/map/Languages.ts +9 -3
- package/source/directives/map/Map.ts +25 -12
- package/source/directives/map/Mapping.ts +9 -6
- package/source/directives/map/Properties.ts +1 -1
- package/source/directives/map/Segments.ts +22 -15
- package/source/directives/mcp/MCP.ts +9 -7
- package/source/directives/mcp/Tool.test.ts +21 -9
- package/source/directives/mcp/Tool.ts +23 -11
- package/source/directives/oauth/Discovery.ts +7 -11
- package/source/directives/oauth/documents.ts +11 -14
- package/source/directives/octets/Context.ts +6 -3
- package/source/directives/octets/Delete.ts +33 -25
- package/source/directives/octets/Directive.ts +5 -1
- package/source/directives/octets/Get.ts +13 -21
- package/source/directives/octets/Octets.ts +20 -15
- package/source/directives/octets/Put.ts +62 -27
- package/source/directives/octets/Workflow.ts +18 -12
- package/source/directives/octets/bytes.ts +1 -1
- package/source/directives/octets/schemas.test.ts +8 -14
- package/source/directives/octets/workflows/Execution.ts +19 -21
- package/source/directives/octets/workflows/Workflow.ts +10 -7
- package/source/directives/require/Headers.ts +3 -4
- package/source/directives/require/Require.ts +3 -4
- package/source/exceptions.ts +19 -12
- package/source/index.ts +1 -1
- package/source/manifest.test.ts +4 -1
- package/source/manifest.ts +19 -13
- package/source/octets.d.ts +1 -1
- package/source/root.ts +3 -2
- package/source/schemas.test.ts +17 -3
- package/transpiled/Branch.js.map +1 -1
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Directive.js +6 -2
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +0 -2
- package/transpiled/Endpoint.js +11 -52
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.d.ts +2 -1
- package/transpiled/Factory.js +1 -0
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +2 -1
- package/transpiled/Gateway.js +24 -15
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +0 -3
- package/transpiled/HTTP/Context.js +7 -9
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Probe.js.map +1 -1
- package/transpiled/HTTP/Server.js +19 -4
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/Timing.d.ts +1 -2
- package/transpiled/HTTP/Timing.js +2 -10
- package/transpiled/HTTP/Timing.js.map +1 -1
- package/transpiled/HTTP/address.js.map +1 -1
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/HTTP/formats/form.js.map +1 -1
- package/transpiled/HTTP/formats/json.js.map +1 -1
- package/transpiled/HTTP/formats/msgpack.js.map +1 -1
- package/transpiled/HTTP/formats/text.js.map +1 -1
- package/transpiled/HTTP/formats/yaml.js +4 -1
- package/transpiled/HTTP/formats/yaml.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +3 -2
- package/transpiled/HTTP/messages.js +1 -43
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Interception.js.map +1 -1
- package/transpiled/Introspection.js +13 -2
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/MCP/Server.js +15 -4
- package/transpiled/MCP/Server.js.map +1 -1
- package/transpiled/MCP/discover.js.map +1 -1
- package/transpiled/MCP/errors.js.map +1 -1
- package/transpiled/MCP/schema.js +1 -1
- package/transpiled/MCP/schema.js.map +1 -1
- package/transpiled/MCP/tools.js +10 -7
- package/transpiled/MCP/tools.js.map +1 -1
- package/transpiled/Mapping.d.ts +2 -2
- package/transpiled/Mapping.js +3 -5
- package/transpiled/Mapping.js.map +1 -1
- package/transpiled/Query.d.ts +6 -2
- package/transpiled/Query.js +23 -8
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RPC/Context.js +0 -7
- package/transpiled/RPC/Context.js.map +1 -1
- package/transpiled/RPC/Dispatcher.js +4 -1
- package/transpiled/RPC/Dispatcher.js.map +1 -1
- package/transpiled/RPC/errors.js.map +1 -1
- package/transpiled/RPC/names.js.map +1 -1
- package/transpiled/RTD/Directives.d.ts +1 -1
- package/transpiled/RTD/Method.js +1 -3
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.js +5 -4
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.js +4 -1
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/Tree.js +1 -1
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/RTD/segment.js.map +1 -1
- package/transpiled/RTD/syntax/parse.js.map +1 -1
- package/transpiled/RTD/syntax/types.d.ts +6 -0
- package/transpiled/RTD/syntax/types.js +10 -1
- package/transpiled/RTD/syntax/types.js.map +1 -1
- package/transpiled/Remotes.js.map +1 -1
- package/transpiled/Tenant.d.ts +1 -1
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/deployment.d.ts +3 -0
- package/transpiled/deployment.js +6 -1
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Anonymous.js +1 -3
- package/transpiled/directives/auth/Anonymous.js.map +1 -1
- package/transpiled/directives/auth/Anyone.js.map +1 -1
- package/transpiled/directives/auth/Assert.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +7 -3
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.js.map +1 -1
- package/transpiled/directives/auth/Echo.js +1 -3
- package/transpiled/directives/auth/Echo.js.map +1 -1
- package/transpiled/directives/auth/Federation.js +3 -7
- package/transpiled/directives/auth/Federation.js.map +1 -1
- package/transpiled/directives/auth/Id.js.map +1 -1
- package/transpiled/directives/auth/Incept.js +1 -1
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Input.js.map +1 -1
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/Rule.js.map +1 -1
- package/transpiled/directives/auth/Scheme.js +1 -2
- package/transpiled/directives/auth/Scheme.js.map +1 -1
- package/transpiled/directives/auth/create.js.map +1 -1
- package/transpiled/directives/auth/schemes.js.map +1 -1
- package/transpiled/directives/auth/split.js.map +1 -1
- package/transpiled/directives/auth/types.d.ts +3 -1
- package/transpiled/directives/cache/Cache.js +28 -2
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.js +1 -1
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/cache/etag.d.ts +10 -0
- package/transpiled/directives/cache/etag.js +30 -0
- package/transpiled/directives/cache/etag.js.map +1 -0
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/dev/Faulty.js.map +1 -1
- package/transpiled/directives/dev/Sleep.js.map +1 -1
- package/transpiled/directives/dev/Stub.js.map +1 -1
- package/transpiled/directives/dev/Throw.js.map +1 -1
- package/transpiled/directives/flow/Compose.js +7 -3
- package/transpiled/directives/flow/Compose.js.map +1 -1
- package/transpiled/directives/flow/Fetch.js.map +1 -1
- package/transpiled/directives/flow/Flow.js.map +1 -1
- package/transpiled/directives/index.js +11 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/IO.d.ts +1 -1
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/io/Input.js +1 -1
- package/transpiled/directives/io/Input.js.map +1 -1
- package/transpiled/directives/io/Output.js +3 -3
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/io/Status.js.map +1 -1
- package/transpiled/directives/io/Throttle.js +1 -1
- package/transpiled/directives/io/Throttle.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/Configuration.js +8 -2
- package/transpiled/directives/io/lib/throttle/Configuration.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/Keys.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/Quotas.js +4 -3
- package/transpiled/directives/io/lib/throttle/Quotas.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/Sync.d.ts +1 -1
- package/transpiled/directives/io/lib/throttle/Sync.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/Warning.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/components/IP.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/components/Identity.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/components/Path.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/components/Route.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/components/Segment.js.map +1 -1
- package/transpiled/directives/io/lib/throttle/conditions/Status.js.map +1 -1
- package/transpiled/directives/map/Authority.js.map +1 -1
- package/transpiled/directives/map/Buffer.js.map +1 -1
- package/transpiled/directives/map/Claims.js.map +1 -1
- package/transpiled/directives/map/Headers.js.map +1 -1
- package/transpiled/directives/map/Language.js.map +1 -1
- package/transpiled/directives/map/Languages.js.map +1 -1
- package/transpiled/directives/map/Map.js.map +1 -1
- package/transpiled/directives/map/Mapping.js.map +1 -1
- package/transpiled/directives/map/Properties.js.map +1 -1
- package/transpiled/directives/map/Segments.js.map +1 -1
- package/transpiled/directives/mcp/MCP.js +1 -1
- package/transpiled/directives/mcp/MCP.js.map +1 -1
- package/transpiled/directives/mcp/Tool.js +3 -1
- package/transpiled/directives/mcp/Tool.js.map +1 -1
- package/transpiled/directives/oauth/Discovery.js.map +1 -1
- package/transpiled/directives/oauth/documents.js.map +1 -1
- package/transpiled/directives/octets/Context.js +1 -1
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Delete.js.map +1 -1
- package/transpiled/directives/octets/Directive.js.map +1 -1
- package/transpiled/directives/octets/Get.js.map +1 -1
- package/transpiled/directives/octets/Octets.js +1 -1
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Put.js.map +1 -1
- package/transpiled/directives/octets/Workflow.js.map +1 -1
- package/transpiled/directives/octets/bytes.js.map +1 -1
- package/transpiled/directives/octets/workflows/Execution.js +1 -2
- package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
- package/transpiled/directives/require/Headers.js.map +1 -1
- package/transpiled/directives/require/Require.js.map +1 -1
- package/transpiled/exceptions.js.map +1 -1
- package/transpiled/index.d.ts +1 -1
- package/transpiled/index.js +1 -1
- package/transpiled/index.js.map +1 -1
- package/transpiled/manifest.js +5 -1
- package/transpiled/manifest.js.map +1 -1
- package/transpiled/root.js.map +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +0 -552
- package/source/redact.test.ts +0 -27
- package/source/redact.ts +0 -21
- package/transpiled/redact.d.ts +0 -5
- package/transpiled/redact.js +0 -17
- package/transpiled/redact.js.map +0 -1
|
@@ -11,30 +11,35 @@ export class Keys {
|
|
|
11
11
|
private readonly components: Component[]
|
|
12
12
|
private readonly conditions?: Condition[]
|
|
13
13
|
|
|
14
|
-
public constructor
|
|
14
|
+
public constructor(components: Component[], conditions?: Condition[]) {
|
|
15
15
|
this.components = components
|
|
16
16
|
this.conditions = conditions
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
public static create
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
public static create(
|
|
20
|
+
componentRules: KeyComponent[],
|
|
21
|
+
conditionRules?: KeyCondition[],
|
|
22
|
+
route: string = ''
|
|
23
|
+
): Keys {
|
|
24
|
+
const components = componentRules.map(
|
|
25
|
+
(rule) => new Components[rule.method](rule.options, route)
|
|
26
|
+
)
|
|
23
27
|
|
|
24
|
-
const conditions = conditionRules?.map(
|
|
28
|
+
const conditions = conditionRules?.map(
|
|
29
|
+
(rule) => new Conditions[rule.method](rule.options)
|
|
30
|
+
)
|
|
25
31
|
|
|
26
32
|
return new this(components, conditions)
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
/** The key of the request, or nothing when a component cannot key it. */
|
|
30
|
-
public get
|
|
36
|
+
public get(context: Context, parameters: Parameter[] = NONE): string | undefined {
|
|
31
37
|
const hash = createHash('sha256')
|
|
32
38
|
|
|
33
39
|
for (const component of this.components) {
|
|
34
40
|
const part = component.get(context, parameters)
|
|
35
41
|
|
|
36
|
-
if (part === undefined)
|
|
37
|
-
return
|
|
42
|
+
if (part === undefined) return
|
|
38
43
|
|
|
39
44
|
hash.update(part)
|
|
40
45
|
}
|
|
@@ -42,7 +47,7 @@ export class Keys {
|
|
|
42
47
|
return hash.digest('hex')
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
public matches
|
|
50
|
+
public matches(input: Context, output: Output): boolean {
|
|
46
51
|
return this.conditions?.some((condition) => !condition.match(input, output)) !== true
|
|
47
52
|
}
|
|
48
53
|
}
|
|
@@ -77,8 +77,7 @@ describe('retry', () => {
|
|
|
77
77
|
quotas = Quotas.create(createConfiguration({ requests: 10, interval: 1000 }))
|
|
78
78
|
context = createContext()
|
|
79
79
|
|
|
80
|
-
for (let i = 0; i < 10; i++)
|
|
81
|
-
quotas.check(context, [])
|
|
80
|
+
for (let i = 0; i < 10; i++) quotas.check(context, [])
|
|
82
81
|
|
|
83
82
|
// an emission here is a tenth of a second, and `Retry-After` counts in whole ones
|
|
84
83
|
assert.strictEqual(quotas.check(context, []), 1)
|
|
@@ -237,14 +236,16 @@ describe('ip', () => {
|
|
|
237
236
|
|
|
238
237
|
const context = createContext({})
|
|
239
238
|
|
|
240
|
-
for (let i = 0; i < 5; i++)
|
|
241
|
-
assert.strictEqual(quotas.check(context, []), 0)
|
|
239
|
+
for (let i = 0; i < 5; i++) assert.strictEqual(quotas.check(context, []), 0)
|
|
242
240
|
})
|
|
243
241
|
})
|
|
244
242
|
|
|
245
243
|
describe('route', () => {
|
|
246
244
|
it('should key on the route, not on the path it came in on', () => {
|
|
247
|
-
quotas = Quotas.create(
|
|
245
|
+
quotas = Quotas.create(
|
|
246
|
+
createConfiguration({ key: [{ method: 'route' }] }),
|
|
247
|
+
'/users/:id'
|
|
248
|
+
)
|
|
248
249
|
|
|
249
250
|
const one = createContext({ url: new URL('http://localhost/users/1/') })
|
|
250
251
|
const two = createContext({ url: new URL('http://localhost/users/2/') })
|
|
@@ -258,8 +259,14 @@ describe('route', () => {
|
|
|
258
259
|
})
|
|
259
260
|
|
|
260
261
|
it('should have separate quotas per route', () => {
|
|
261
|
-
const users = Quotas.create(
|
|
262
|
-
|
|
262
|
+
const users = Quotas.create(
|
|
263
|
+
createConfiguration({ key: [{ method: 'route' }] }),
|
|
264
|
+
'/users/:id'
|
|
265
|
+
)
|
|
266
|
+
const posts = Quotas.create(
|
|
267
|
+
createConfiguration({ key: [{ method: 'route' }] }),
|
|
268
|
+
'/posts/:id'
|
|
269
|
+
)
|
|
263
270
|
|
|
264
271
|
context = createContext({ url: new URL('http://localhost/users/1/') })
|
|
265
272
|
|
|
@@ -323,7 +330,9 @@ describe('identity', () => {
|
|
|
323
330
|
describe('status', () => {
|
|
324
331
|
beforeEach(() => {
|
|
325
332
|
context = createContext()
|
|
326
|
-
configuration = createConfiguration({
|
|
333
|
+
configuration = createConfiguration({
|
|
334
|
+
condition: [{ method: 'status', options: 404 }]
|
|
335
|
+
})
|
|
327
336
|
quotas = Quotas.create(configuration)
|
|
328
337
|
})
|
|
329
338
|
|
|
@@ -356,7 +365,9 @@ describe('status', () => {
|
|
|
356
365
|
it('should charge the key checking saw, which settling cannot recompute', () => {
|
|
357
366
|
const keys = [{ method: 'segment' as const, options: 'id' }]
|
|
358
367
|
|
|
359
|
-
quotas = Quotas.create(
|
|
368
|
+
quotas = Quotas.create(
|
|
369
|
+
createConfiguration({ key: keys, condition: configuration.condition })
|
|
370
|
+
)
|
|
360
371
|
|
|
361
372
|
const one = createContext()
|
|
362
373
|
const two = createContext()
|
|
@@ -373,23 +384,28 @@ describe('status', () => {
|
|
|
373
384
|
})
|
|
374
385
|
})
|
|
375
386
|
|
|
376
|
-
function flush
|
|
387
|
+
function flush(now: number = Date.now(), ...of: Quotas[]): Batch[] {
|
|
377
388
|
const batch: Batch[] = []
|
|
378
389
|
|
|
379
|
-
for (const one of of.length === 0 ? [quotas] : of)
|
|
380
|
-
one.flush(now, batch)
|
|
390
|
+
for (const one of of.length === 0 ? [quotas] : of) one.flush(now, batch)
|
|
381
391
|
|
|
382
392
|
return batch
|
|
383
393
|
}
|
|
384
394
|
|
|
385
|
-
function createConfiguration
|
|
386
|
-
return Object.assign(
|
|
395
|
+
function createConfiguration(properties?: Partial<Configuration>): Configuration {
|
|
396
|
+
return Object.assign(
|
|
397
|
+
{ key: [{ method: 'path' }], requests: 2, interval: 100 },
|
|
398
|
+
properties
|
|
399
|
+
)
|
|
387
400
|
}
|
|
388
401
|
|
|
389
|
-
function createContext
|
|
390
|
-
return Object.assign(
|
|
402
|
+
function createContext(properties?: any): Context {
|
|
403
|
+
return Object.assign(
|
|
404
|
+
{ url: new URL('http://localhost/') },
|
|
405
|
+
properties
|
|
406
|
+
) as unknown as Context
|
|
391
407
|
}
|
|
392
408
|
|
|
393
|
-
async function timeout
|
|
409
|
+
async function timeout(ms: number): Promise<void> {
|
|
394
410
|
await setTimeout(ms * 1.2)
|
|
395
411
|
}
|
|
@@ -42,7 +42,7 @@ export class Quotas {
|
|
|
42
42
|
*/
|
|
43
43
|
private readonly keyed = new WeakMap<Context, string>()
|
|
44
44
|
|
|
45
|
-
public constructor
|
|
45
|
+
public constructor(options: Options) {
|
|
46
46
|
this.keys = options.keys
|
|
47
47
|
this.conditional = options.conditional
|
|
48
48
|
this.emission = options.interval / options.requests
|
|
@@ -50,12 +50,13 @@ export class Quotas {
|
|
|
50
50
|
this.period = period(options.interval)
|
|
51
51
|
|
|
52
52
|
// a key means one budget, so quotas that do not share one must not share a key
|
|
53
|
-
this.prefix =
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
this.prefix =
|
|
54
|
+
options.name === undefined
|
|
55
|
+
? `t:${options.requests}:${options.interval}:`
|
|
56
|
+
: `${options.name}:`
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
public static create
|
|
59
|
+
public static create(configuration: Configuration, route: string = ''): Quotas {
|
|
59
60
|
const { requests, interval, condition } = configuration
|
|
60
61
|
const keys = Keys.create(configuration.key, condition, route)
|
|
61
62
|
|
|
@@ -69,12 +70,11 @@ export class Quotas {
|
|
|
69
70
|
* the same call that admits it; otherwise only the response can tell whether it counts,
|
|
70
71
|
* and {@link use} charges once it can.
|
|
71
72
|
*/
|
|
72
|
-
public check
|
|
73
|
+
public check(context: Context, parameters: Parameter[]): number {
|
|
73
74
|
const key = this.keys.get(context, parameters)
|
|
74
75
|
|
|
75
76
|
// a request that cannot be keyed is not metered
|
|
76
|
-
if (key === undefined)
|
|
77
|
-
return 0
|
|
77
|
+
if (key === undefined) return 0
|
|
78
78
|
|
|
79
79
|
this.keyed.set(context, key)
|
|
80
80
|
|
|
@@ -83,25 +83,21 @@ export class Quotas {
|
|
|
83
83
|
const tat = Math.max(entry?.tat ?? now, now)
|
|
84
84
|
const admit = tat + this.emission - this.capacity
|
|
85
85
|
|
|
86
|
-
if (admit > now)
|
|
87
|
-
return Math.ceil((admit - now) / 1000)
|
|
86
|
+
if (admit > now) return Math.ceil((admit - now) / 1000)
|
|
88
87
|
|
|
89
|
-
if (!this.conditional)
|
|
90
|
-
this.charge(key, entry, tat)
|
|
88
|
+
if (!this.conditional) this.charge(key, entry, tat)
|
|
91
89
|
|
|
92
90
|
return 0
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
/** Charges what the condition accepts, once the response can be matched against it. */
|
|
96
|
-
public use
|
|
97
|
-
if (!this.conditional || !this.keys.matches(input, output))
|
|
98
|
-
return
|
|
94
|
+
public use(input: Context, output: Output): void {
|
|
95
|
+
if (!this.conditional || !this.keys.matches(input, output)) return
|
|
99
96
|
|
|
100
97
|
// precall always runs first, and a request it refuses never reaches settle
|
|
101
98
|
const key = this.keyed.get(input) ?? this.keys.get(input)
|
|
102
99
|
|
|
103
|
-
if (key === undefined)
|
|
104
|
-
return
|
|
100
|
+
if (key === undefined) return
|
|
105
101
|
|
|
106
102
|
const now = Date.now()
|
|
107
103
|
const entry = this.entries.get(key)
|
|
@@ -116,7 +112,7 @@ export class Quotas {
|
|
|
116
112
|
* The debt is not cleared here but in {@link settled}, so a tick that fails to reach
|
|
117
113
|
* Redis leaves it to be reported by the next one instead of losing it.
|
|
118
114
|
*/
|
|
119
|
-
public flush
|
|
115
|
+
public flush(now: number, batch: Batch[]): void {
|
|
120
116
|
for (const [key, entry] of this.entries) {
|
|
121
117
|
const delta = Math.round(entry.debt)
|
|
122
118
|
|
|
@@ -127,18 +123,16 @@ export class Quotas {
|
|
|
127
123
|
}
|
|
128
124
|
|
|
129
125
|
// out of debt and with nothing left to report, a key says no more than an absent one
|
|
130
|
-
if (entry.tat <= now)
|
|
131
|
-
this.entries.delete(key)
|
|
126
|
+
if (entry.tat <= now) this.entries.delete(key)
|
|
132
127
|
}
|
|
133
128
|
}
|
|
134
129
|
|
|
135
130
|
/** Takes the group's debt back, and clears what this process contributed to it. */
|
|
136
|
-
public settled
|
|
131
|
+
public settled(reported: Batch, debt: number, now: number): void {
|
|
137
132
|
const entry = this.entries.get(reported.key)
|
|
138
133
|
|
|
139
134
|
if (entry === undefined) {
|
|
140
|
-
if (debt > 0)
|
|
141
|
-
this.entries.set(reported.key, { tat: now + debt, debt: 0 })
|
|
135
|
+
if (debt > 0) this.entries.set(reported.key, { tat: now + debt, debt: 0 })
|
|
142
136
|
|
|
143
137
|
return
|
|
144
138
|
}
|
|
@@ -149,11 +143,11 @@ export class Quotas {
|
|
|
149
143
|
entry.tat = Math.max(entry.tat, now + debt)
|
|
150
144
|
}
|
|
151
145
|
|
|
152
|
-
public name
|
|
146
|
+
public name(key: string): string {
|
|
153
147
|
return this.prefix + key
|
|
154
148
|
}
|
|
155
149
|
|
|
156
|
-
private charge
|
|
150
|
+
private charge(key: string, entry: Entry | undefined, tat: number): void {
|
|
157
151
|
if (entry === undefined)
|
|
158
152
|
this.entries.set(key, { tat: tat + this.emission, debt: this.emission })
|
|
159
153
|
else {
|
|
@@ -170,7 +164,7 @@ export class Quotas {
|
|
|
170
164
|
* what it alone has spent — so it is worth doing an order of magnitude more often than
|
|
171
165
|
* the interval, within reason on either end.
|
|
172
166
|
*/
|
|
173
|
-
function period
|
|
167
|
+
function period(interval: number): number {
|
|
174
168
|
return Math.min(Math.max(interval / 10, MIN_PERIOD), MAX_PERIOD)
|
|
175
169
|
}
|
|
176
170
|
|
|
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict'
|
|
|
3
3
|
|
|
4
4
|
import { Sync } from './Sync.js'
|
|
5
5
|
import { Quotas } from './Quotas.js'
|
|
6
|
-
import type { atomicity } from '@toa.io/core'
|
|
6
|
+
import type { atomicity } from '@toa.io/core/types'
|
|
7
7
|
import type { Configuration } from './Configuration.js'
|
|
8
8
|
import type { Input as Context } from '../../../../io.js'
|
|
9
9
|
|
|
@@ -105,9 +105,11 @@ it('should clear what it reported', async () => {
|
|
|
105
105
|
})
|
|
106
106
|
|
|
107
107
|
it('should keep what it could not report, and keep serving', async () => {
|
|
108
|
-
sync = new Sync(
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
sync = new Sync(
|
|
109
|
+
createStash(() => {
|
|
110
|
+
throw new Error('Redis is unreachable')
|
|
111
|
+
})
|
|
112
|
+
)
|
|
111
113
|
|
|
112
114
|
const quotas = createQuotas()
|
|
113
115
|
|
|
@@ -122,7 +124,7 @@ it('should keep what it could not report, and keep serving', async () => {
|
|
|
122
124
|
assert.strictEqual(quotas.check(context, []), 0)
|
|
123
125
|
})
|
|
124
126
|
|
|
125
|
-
async function tick
|
|
127
|
+
async function tick(): Promise<void> {
|
|
126
128
|
mock.timers.tick(250)
|
|
127
129
|
|
|
128
130
|
// the reconciliation a tick starts is asynchronous, and node:test advances
|
|
@@ -130,18 +132,20 @@ async function tick (): Promise<void> {
|
|
|
130
132
|
await new Promise((resolve) => process.nextTick(resolve))
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
function createQuotas
|
|
135
|
+
function createQuotas(properties?: Partial<Configuration>): Quotas {
|
|
134
136
|
const configuration = { key: [{ method: 'path' as const }], requests: 2, interval: 100 }
|
|
135
137
|
|
|
136
138
|
return Quotas.create(Object.assign(configuration, properties))
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
function createContext
|
|
140
|
-
return Object.assign(
|
|
141
|
-
|
|
141
|
+
function createContext(properties?: any): Context {
|
|
142
|
+
return Object.assign(
|
|
143
|
+
{ url: new URL('http://localhost/'), identity: { id: 'one' } },
|
|
144
|
+
properties
|
|
145
|
+
) as unknown as Context
|
|
142
146
|
}
|
|
143
147
|
|
|
144
|
-
function createStash
|
|
148
|
+
function createStash(reply?: (deltas: number[]) => number[]): atomicity.Atom {
|
|
145
149
|
const atom = {
|
|
146
150
|
meter: async (keys: string[], deltas: number[]): Promise<number[]> => {
|
|
147
151
|
invocations.push({ keys, deltas })
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { console } from 'openspan'
|
|
2
2
|
import type { Quotas } from './Quotas.js'
|
|
3
|
-
import type { atomicity } from '@toa.io/core'
|
|
3
|
+
import type { atomicity } from '@toa.io/core/types'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Reconciles every quota of the process with the other gateways, on one tick.
|
|
@@ -19,11 +19,11 @@ export class Sync {
|
|
|
19
19
|
/** Ticks do not overlap: a slow round trip delays reconciling, it does not double it. */
|
|
20
20
|
private reconciling = false
|
|
21
21
|
|
|
22
|
-
public constructor
|
|
22
|
+
public constructor(atom: atomicity.Atom) {
|
|
23
23
|
this.atom = atom
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
public register
|
|
26
|
+
public register(quotas: Quotas): void {
|
|
27
27
|
this.quotas.push(quotas)
|
|
28
28
|
|
|
29
29
|
// the shortest interval sets the pace, and reconciling the others more often than
|
|
@@ -35,7 +35,7 @@ export class Sync {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
public dispose
|
|
38
|
+
public dispose(): void {
|
|
39
39
|
if (this.timer !== null) {
|
|
40
40
|
clearInterval(this.timer)
|
|
41
41
|
|
|
@@ -43,7 +43,7 @@ export class Sync {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
private start
|
|
46
|
+
private start(): void {
|
|
47
47
|
this.dispose()
|
|
48
48
|
|
|
49
49
|
this.timer = setInterval(this.tick, this.period)
|
|
@@ -52,17 +52,14 @@ export class Sync {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
private readonly tick = (): void => {
|
|
55
|
-
if (this.reconciling)
|
|
56
|
-
return
|
|
55
|
+
if (this.reconciling) return
|
|
57
56
|
|
|
58
57
|
const now = Date.now()
|
|
59
58
|
const batch: Batch[] = []
|
|
60
59
|
|
|
61
|
-
for (const quotas of this.quotas)
|
|
62
|
-
quotas.flush(now, batch)
|
|
60
|
+
for (const quotas of this.quotas) quotas.flush(now, batch)
|
|
63
61
|
|
|
64
|
-
if (batch.length === 0)
|
|
65
|
-
return
|
|
62
|
+
if (batch.length === 0) return
|
|
66
63
|
|
|
67
64
|
this.reconciling = true
|
|
68
65
|
|
|
@@ -71,7 +68,7 @@ export class Sync {
|
|
|
71
68
|
})
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
private async reconcile
|
|
71
|
+
private async reconcile(batch: Batch[]): Promise<void> {
|
|
75
72
|
try {
|
|
76
73
|
const keys = batch.map((entry) => entry.quotas.name(entry.key))
|
|
77
74
|
const deltas = batch.map((entry) => entry.delta)
|
|
@@ -9,16 +9,15 @@ export class Warning {
|
|
|
9
9
|
private readonly interval: number
|
|
10
10
|
private last = -Infinity
|
|
11
11
|
|
|
12
|
-
public constructor
|
|
12
|
+
public constructor(message: string, interval: number = INTERVAL) {
|
|
13
13
|
this.message = message
|
|
14
14
|
this.interval = interval
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
public emit
|
|
17
|
+
public emit(attributes?: Record<string, unknown>): void {
|
|
18
18
|
const now = Date.now()
|
|
19
19
|
|
|
20
|
-
if (now - this.last < this.interval)
|
|
21
|
-
return
|
|
20
|
+
if (now - this.last < this.interval) return
|
|
22
21
|
|
|
23
22
|
this.last = now
|
|
24
23
|
|
|
@@ -12,20 +12,19 @@ import type { Component } from './Component.js'
|
|
|
12
12
|
export class IP implements Component {
|
|
13
13
|
private readonly warning: Warning
|
|
14
14
|
|
|
15
|
-
public constructor
|
|
15
|
+
public constructor(options: unknown, route: string) {
|
|
16
16
|
const subject = typeof options === 'string' ? options : throttle(route)
|
|
17
17
|
|
|
18
18
|
this.warning = new Warning(`${subject} is not in effect: the request has no ip`)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
public get
|
|
22
|
-
if (context.ip === undefined)
|
|
23
|
-
this.warning.emit()
|
|
21
|
+
public get(context: Context): string | undefined {
|
|
22
|
+
if (context.ip === undefined) this.warning.emit()
|
|
24
23
|
|
|
25
24
|
return context.ip
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
function throttle
|
|
28
|
+
function throttle(route: string): string {
|
|
30
29
|
return route === '' ? 'Throttle' : `Throttle of ${route}`
|
|
31
30
|
}
|
|
@@ -8,7 +8,7 @@ import type { Component } from './Component.js'
|
|
|
8
8
|
* that tells them apart.
|
|
9
9
|
*/
|
|
10
10
|
export class Identity implements Component {
|
|
11
|
-
public get
|
|
11
|
+
public get(context: Input): string {
|
|
12
12
|
return (context as AuthenticatedContext).identity?.id ?? ''
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -2,7 +2,7 @@ import type { Context } from '../../../../../HTTP/index.js'
|
|
|
2
2
|
import type { Component } from './Component.js'
|
|
3
3
|
|
|
4
4
|
export class Path implements Component {
|
|
5
|
-
public get
|
|
5
|
+
public get(context: Context): string {
|
|
6
6
|
return context.url.pathname
|
|
7
7
|
}
|
|
8
8
|
}
|
|
@@ -9,11 +9,11 @@ import type { Component } from './Component.js'
|
|
|
9
9
|
export class Route implements Component {
|
|
10
10
|
private readonly route: string
|
|
11
11
|
|
|
12
|
-
public constructor
|
|
12
|
+
public constructor(_: unknown, route: string) {
|
|
13
13
|
this.route = route
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
public get
|
|
16
|
+
public get(): string {
|
|
17
17
|
return this.route
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -7,13 +7,13 @@ import type { Component } from './Component.js'
|
|
|
7
7
|
export class Segment implements Component {
|
|
8
8
|
private readonly name: string
|
|
9
9
|
|
|
10
|
-
public constructor
|
|
10
|
+
public constructor(name: unknown) {
|
|
11
11
|
assert.ok(typeof name === 'string', 'Throttle segment must be a string')
|
|
12
12
|
|
|
13
13
|
this.name = name
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
public get
|
|
16
|
+
public get(_: Context, parameters: Parameter[]): string {
|
|
17
17
|
return parameters.find(({ name }) => name === this.name)?.value ?? ''
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -5,13 +5,13 @@ import type { Condition } from './Condition.js'
|
|
|
5
5
|
export class Status implements Condition {
|
|
6
6
|
private readonly status: number
|
|
7
7
|
|
|
8
|
-
public constructor
|
|
8
|
+
public constructor(status: unknown) {
|
|
9
9
|
assert.ok(typeof status === 'number', 'Status must be a number')
|
|
10
10
|
|
|
11
11
|
this.status = status
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
public match
|
|
14
|
+
public match(input: Input, output: Output): boolean {
|
|
15
15
|
return output?.status === this.status
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -14,16 +14,22 @@ describe('throttle', () => {
|
|
|
14
14
|
for (const key of ['ip', 'path', 'route', 'identity'])
|
|
15
15
|
assert.doesNotThrow(() => schemas.throttle.validate({ key, ...rest }))
|
|
16
16
|
|
|
17
|
-
assert.doesNotThrow(() =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
assert.doesNotThrow(() =>
|
|
18
|
+
schemas.throttle.validate({ key: { segment: 'id' }, ...rest })
|
|
19
|
+
)
|
|
20
|
+
assert.doesNotThrow(() =>
|
|
21
|
+
schemas.throttle.validate({
|
|
22
|
+
key: ['route', { segment: 'id' }],
|
|
23
|
+
...rest
|
|
24
|
+
})
|
|
25
|
+
)
|
|
22
26
|
})
|
|
23
27
|
|
|
24
28
|
it('should reject an unknown key component', () => {
|
|
25
29
|
assert.throws(() => schemas.throttle.validate({ key: 'header', ...rest }))
|
|
26
|
-
assert.throws(() =>
|
|
30
|
+
assert.throws(() =>
|
|
31
|
+
schemas.throttle.validate({ key: { header: 'x-real-ip' }, ...rest })
|
|
32
|
+
)
|
|
27
33
|
})
|
|
28
34
|
|
|
29
35
|
it('should reject a declaration it no longer honours', () => {
|
|
@@ -3,13 +3,13 @@ import { Mapping } from './Mapping.js'
|
|
|
3
3
|
import type { Input } from '../../io.js'
|
|
4
4
|
|
|
5
5
|
export class Authority extends Mapping<string> {
|
|
6
|
-
public constructor
|
|
6
|
+
public constructor(property: string) {
|
|
7
7
|
assert.ok(typeof property === 'string', '`map:authority` must be a string')
|
|
8
8
|
|
|
9
9
|
super(property)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
public properties
|
|
12
|
+
public properties(context: Input): Record<string, string> {
|
|
13
13
|
return { [this.value]: context.authority }
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -3,13 +3,13 @@ import { Mapping } from './Mapping.js'
|
|
|
3
3
|
import type { Input } from '../../io.js'
|
|
4
4
|
|
|
5
5
|
export class BufferMapping extends Mapping<string> {
|
|
6
|
-
public constructor
|
|
6
|
+
public constructor(property: string) {
|
|
7
7
|
assert.ok(typeof property === 'string', '`map:buffer` must be a string')
|
|
8
8
|
|
|
9
9
|
super(property)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
public override async properties
|
|
12
|
+
public override async properties(context: Input): Promise<Record<string, string>> {
|
|
13
13
|
return { [this.value]: (await context.buffer()).toString('utf8') }
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -8,50 +8,55 @@ export class Claims extends Mapping<Record<string, string>> {
|
|
|
8
8
|
private readonly discovery!: Promise<Component>
|
|
9
9
|
private federation: Component | null = null
|
|
10
10
|
|
|
11
|
-
public constructor
|
|
11
|
+
public constructor(map: Record<string, string>, remotes: Remotes) {
|
|
12
12
|
assert.ok(map.constructor === Object, '`map:claims` must be an object')
|
|
13
13
|
|
|
14
|
-
assert.ok(
|
|
15
|
-
|
|
14
|
+
assert.ok(
|
|
15
|
+
Object.values(map).every((value) => typeof value === 'string'),
|
|
16
|
+
'`map:claims ` must be an object with string values'
|
|
17
|
+
)
|
|
16
18
|
|
|
17
19
|
super(map, remotes)
|
|
18
20
|
|
|
19
21
|
this.discovery = remotes.discover('identity', 'federation')
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
public override async properties
|
|
24
|
+
public override async properties(
|
|
25
|
+
context: Input
|
|
26
|
+
): Promise<Record<string, string> | null> {
|
|
23
27
|
const authentication = context.request.headers.authorization
|
|
24
28
|
|
|
25
|
-
if (authentication === undefined)
|
|
26
|
-
return null
|
|
29
|
+
if (authentication === undefined) return null
|
|
27
30
|
|
|
28
31
|
const claims = await this.claims(authentication)
|
|
29
32
|
|
|
30
|
-
if (claims === null)
|
|
31
|
-
return null
|
|
33
|
+
if (claims === null) return null
|
|
32
34
|
|
|
33
|
-
return Object.entries(this.value).reduce(
|
|
34
|
-
|
|
35
|
+
return Object.entries(this.value).reduce(
|
|
36
|
+
(properties: Record<string, string>, [property, claim]) => {
|
|
37
|
+
const value = claims[claim]
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
properties[property] = value
|
|
39
|
+
if (value !== undefined) properties[property] = value
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
return properties
|
|
42
|
+
},
|
|
43
|
+
{}
|
|
44
|
+
)
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
private async claims
|
|
47
|
+
private async claims(authentication: string): Promise<Record<string, string> | null> {
|
|
44
48
|
const [scheme, credentials] = authentication.split(' ')
|
|
45
49
|
|
|
46
|
-
if (scheme !== 'Bearer' || credentials === undefined)
|
|
47
|
-
return null
|
|
50
|
+
if (scheme !== 'Bearer' || credentials === undefined) return null
|
|
48
51
|
|
|
49
52
|
this.federation ??= await this.discovery
|
|
50
53
|
|
|
51
|
-
const claims = await this.federation.invoke<Record<string, string> | Error>(
|
|
54
|
+
const claims = await this.federation.invoke<Record<string, string> | Error>(
|
|
55
|
+
'decode',
|
|
56
|
+
{ input: credentials }
|
|
57
|
+
)
|
|
52
58
|
|
|
53
|
-
if (claims instanceof Error)
|
|
54
|
-
return null
|
|
59
|
+
if (claims instanceof Error) return null
|
|
55
60
|
|
|
56
61
|
return claims
|
|
57
62
|
}
|