@toa.io/extensions.exposition 1.0.0-alpha.292 → 1.0.0-alpha.293
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/identity.basic/package.json +8 -0
- package/components/identity.federation/package.json +8 -0
- package/components/identity.passkeys/package.json +8 -0
- package/components/identity.tokens/package.json +10 -0
- package/package.json +24 -13
- package/transpiled/Endpoint.js +3 -0
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Introspection.d.ts +6 -0
- package/transpiled/Introspection.js +1 -0
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/MCP/schema.js +2 -2
- package/transpiled/Query.d.ts +2 -12
- package/transpiled/Query.js +2 -12
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Endpoint.d.ts +2 -3
- package/ui/dist/_app/immutable/assets/0.Cu0AnR_8.css +2 -0
- package/ui/dist/_app/immutable/assets/2.BghF56l_.css +1 -0
- package/ui/dist/_app/immutable/assets/ui.C8aD6zzF.css +1 -0
- package/ui/dist/_app/immutable/chunks/B8GvXrmq.js +1 -0
- package/ui/dist/_app/immutable/chunks/BVDJTrf4.js +3 -0
- package/ui/dist/_app/immutable/chunks/D6q28_Ok.js +86 -0
- package/ui/dist/_app/immutable/chunks/{aLpTDmOc.js → DVlaUfVU.js} +1 -1
- package/ui/dist/_app/immutable/chunks/DpB73ZB6.js +6 -0
- package/ui/dist/_app/immutable/entry/app.CTava8yn.js +2 -0
- package/ui/dist/_app/immutable/entry/start.yWN0gSLA.js +1 -0
- package/ui/dist/_app/immutable/nodes/0.HKRDBYrC.js +1 -0
- package/ui/dist/_app/immutable/nodes/1.CLa0ydOi.js +1 -0
- package/ui/dist/_app/immutable/nodes/2.C9Kaym8C.js +8 -0
- package/ui/dist/_app/immutable/nodes/3.C1X4_rXZ.js +1 -0
- package/ui/dist/_app/immutable/nodes/4.DdzDIi9E.js +1 -0
- package/ui/dist/_app/immutable/nodes/5.DpbmCMdw.js +1 -0
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +12 -12
- package/CHANGELOG.md +0 -42
- package/components/identity.bans/tsconfig.tsbuildinfo +0 -1
- package/components/identity.basic/source/lib/credentials.test.ts +0 -18
- package/components/identity.basic/tsconfig.tsbuildinfo +0 -1
- package/components/identity.clients/source/lib/canonical.test.ts +0 -43
- package/components/identity.clients/source/lib/cimd.test.ts +0 -122
- package/components/identity.clients/source/lib/redirect.test.ts +0 -47
- package/components/identity.clients/tsconfig.tsbuildinfo +0 -1
- package/components/identity.credentials/source/list.test.ts +0 -70
- package/components/identity.credentials/tsconfig.tsbuildinfo +0 -1
- package/components/identity.federation/source/lib/discovery.test.ts +0 -60
- package/components/identity.federation/source/list.test.ts +0 -41
- package/components/identity.federation/tsconfig.tsbuildinfo +0 -1
- package/components/identity.grants/tsconfig.tsbuildinfo +0 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +0 -1
- package/components/identity.otp/tsconfig.tsbuildinfo +0 -1
- package/components/identity.passkeys/source/errors.test.ts +0 -34
- package/components/identity.passkeys/source/webauthn.test.ts +0 -26
- package/components/identity.passkeys/tsconfig.tsbuildinfo +0 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +0 -1
- package/components/identity.tokens/source/authenticate.test.ts +0 -112
- package/components/identity.tokens/source/decrypt.test.ts +0 -216
- package/components/identity.tokens/source/encrypt.test.ts +0 -150
- package/components/identity.tokens/source/issue.test.ts +0 -73
- package/components/identity.tokens/source/lib/form.test.ts +0 -25
- package/components/identity.tokens/source/lib/paseto.test.ts +0 -62
- package/components/identity.tokens/tsconfig.tsbuildinfo +0 -1
- package/context.toa.yaml +0 -31
- package/cucumber.mjs +0 -7
- package/documentation/.assets/ia3-dark.jpg +0 -0
- package/documentation/.assets/ia3-light.jpg +0 -0
- package/documentation/.assets/overview-dark.jpg +0 -0
- package/documentation/.assets/overview-light.jpg +0 -0
- package/documentation/.assets/role-scopes-dark.jpg +0 -0
- package/documentation/.assets/role-scopes-light.jpg +0 -0
- package/documentation/.assets/rtd-dark.jpg +0 -0
- package/documentation/.assets/rtd-light.jpg +0 -0
- package/documentation/access.md +0 -350
- package/documentation/authorities.md +0 -51
- package/documentation/cache.md +0 -72
- package/documentation/components.md +0 -472
- package/documentation/consent.md +0 -101
- package/documentation/credentials.md +0 -88
- package/documentation/dev.md +0 -30
- package/documentation/discovery.md +0 -81
- package/documentation/flow.md +0 -44
- package/documentation/help.md +0 -122
- package/documentation/identity.md +0 -304
- package/documentation/introspection.md +0 -123
- package/documentation/io.md +0 -167
- package/documentation/ip.md +0 -24
- package/documentation/map.md +0 -123
- package/documentation/mcp.md +0 -183
- package/documentation/notes/desync.jpg +0 -0
- package/documentation/notes/peers.md +0 -59
- package/documentation/notes/sse.md +0 -71
- package/documentation/notes/throttling.md +0 -122
- package/documentation/oauth.md +0 -180
- package/documentation/octets.md +0 -334
- package/documentation/passkeys.md +0 -11
- package/documentation/protocol.md +0 -120
- package/documentation/query.md +0 -324
- package/documentation/require.md +0 -15
- package/documentation/rpc.md +0 -154
- package/documentation/tracing.md +0 -70
- package/documentation/tree.md +0 -199
- package/features/access.feature +0 -596
- package/features/annotation.feature +0 -32
- package/features/auth.assert.feature +0 -55
- package/features/auth.bearer.feature +0 -120
- package/features/auth.claims.feature +0 -171
- package/features/auth.incept.feature +0 -166
- package/features/auth.input.feature +0 -59
- package/features/authorities.basic.feature +0 -141
- package/features/authorities.feature +0 -71
- package/features/authorities.federation.feature +0 -100
- package/features/authorities.tokens.feature +0 -117
- package/features/body.feature +0 -76
- package/features/cache.feature +0 -368
- package/features/configuration.feature +0 -206
- package/features/cors.feature +0 -127
- package/features/credentials.feature +0 -106
- package/features/debug.feature +0 -34
- package/features/dev.feature +0 -90
- package/features/directives.feature +0 -61
- package/features/discovery.feature +0 -213
- package/features/discovery.ui.feature +0 -213
- package/features/dynamic.feature +0 -192
- package/features/errors.feature +0 -258
- package/features/etag.feature +0 -239
- package/features/flow.feature +0 -148
- package/features/help.feature +0 -512
- package/features/identity.bans.feature +0 -200
- package/features/identity.basic.feature +0 -666
- package/features/identity.feature +0 -240
- package/features/identity.federation.feature +0 -396
- package/features/identity.otp.feature +0 -142
- package/features/identity.roles.feature +0 -568
- package/features/identity.tokens.custom.feature +0 -430
- package/features/identity.tokens.feature +0 -131
- package/features/interruptions.feature +0 -20
- package/features/introspection.feature +0 -565
- package/features/introspection.map.feature +0 -108
- package/features/io.feature +0 -204
- package/features/io.throttle.feature +0 -166
- package/features/map.feature +0 -360
- package/features/mcp.feature +0 -753
- package/features/methods.feature +0 -48
- package/features/oauth.clients.feature +0 -195
- package/features/oauth.discovery.feature +0 -164
- package/features/oauth.grants.feature +0 -301
- package/features/octets.cloudinary.feature +0 -233
- package/features/octets.download.feature +0 -194
- package/features/octets.entries.feature +0 -83
- package/features/octets.feature +0 -306
- package/features/octets.head.feature +0 -40
- package/features/octets.location.feature +0 -83
- package/features/octets.meta.feature +0 -117
- package/features/octets.workflows.feature +0 -565
- package/features/passkeys.feature +0 -66
- package/features/probes.feature +0 -18
- package/features/query.feature +0 -389
- package/features/realtime.feature +0 -34
- package/features/require.feature +0 -66
- package/features/response.feature +0 -103
- package/features/routes.feature +0 -224
- package/features/rpc.feature +0 -429
- package/features/server.feature +0 -21
- package/features/site/_app/immutable/asset.js +0 -1
- package/features/site/favicon.ico +0 -0
- package/features/site/index.html +0 -10
- package/features/steps/.env.example +0 -5
- package/features/steps/Captures.ts +0 -20
- package/features/steps/Cloudinary.ts +0 -12
- package/features/steps/Common.ts +0 -38
- package/features/steps/Components.ts +0 -115
- package/features/steps/Database.ts +0 -106
- package/features/steps/Gateway.ts +0 -239
- package/features/steps/HTTP.ts +0 -96
- package/features/steps/IDP.ts +0 -361
- package/features/steps/Identity.ts +0 -54
- package/features/steps/OTP.ts +0 -42
- package/features/steps/Parameters.ts +0 -162
- package/features/steps/Probe.ts +0 -38
- package/features/steps/Realtime.ts +0 -175
- package/features/steps/Workspace.ts +0 -48
- package/features/steps/components/audit/manifest.toa.yaml +0 -20
- package/features/steps/components/audit/operations/record.js +0 -5
- package/features/steps/components/echo/manifest.toa.yaml +0 -59
- package/features/steps/components/echo/operations/affect.js +0 -3
- package/features/steps/components/echo/operations/compute.js +0 -3
- package/features/steps/components/echo/operations/echo.js +0 -3
- package/features/steps/components/echo/operations/error.js +0 -7
- package/features/steps/components/echo/operations/identity.js +0 -3
- package/features/steps/components/echo/operations/parameters.js +0 -3
- package/features/steps/components/echo/operations/ping.js +0 -3
- package/features/steps/components/echo/operations/unwrap.js +0 -3
- package/features/steps/components/echo.beacon/manifest.toa.yaml +0 -2
- package/features/steps/components/echo.beacon/operations/hello.js +0 -3
- package/features/steps/components/greeter/manifest.toa.yaml +0 -5
- package/features/steps/components/greeter/operations/greet.js +0 -3
- package/features/steps/components/notify/manifest.toa.yaml +0 -20
- package/features/steps/components/notify/operations/send.js +0 -5
- package/features/steps/components/octets.tester/manifest.toa.yaml +0 -73
- package/features/steps/components/octets.tester/operations/authority.js +0 -3
- package/features/steps/components/octets.tester/operations/bar.js +0 -9
- package/features/steps/components/octets.tester/operations/baz.js +0 -9
- package/features/steps/components/octets.tester/operations/concat.js +0 -5
- package/features/steps/components/octets.tester/operations/echo.js +0 -5
- package/features/steps/components/octets.tester/operations/err.js +0 -14
- package/features/steps/components/octets.tester/operations/foo.js +0 -5
- package/features/steps/components/octets.tester/operations/id.js +0 -5
- package/features/steps/components/octets.tester/operations/identity.js +0 -5
- package/features/steps/components/octets.tester/operations/lenna.png +0 -0
- package/features/steps/components/octets.tester/operations/redirect.js +0 -17
- package/features/steps/components/octets.tester/operations/yex.js +0 -14
- package/features/steps/components/octets.tester/operations/yield.js +0 -11
- package/features/steps/components/orders/manifest.toa.yaml +0 -30
- package/features/steps/components/orders/operations/create.js +0 -7
- package/features/steps/components/pots/manifest.toa.yaml +0 -91
- package/features/steps/components/pots/migrations/0002-indexes.yaml +0 -4
- package/features/steps/components/pricing/manifest.toa.yaml +0 -13
- package/features/steps/components/pricing/operations/quote.js +0 -3
- package/features/steps/components/sequences/manifest.toa.yaml +0 -11
- package/features/steps/components/sequences/operations/numbers.js +0 -5
- package/features/steps/components/sequences/operations/tokens.js +0 -14
- package/features/steps/components/users/manifest.toa.yaml +0 -30
- package/features/steps/components/users/operations/create.js +0 -11
- package/features/steps/components/users.properties/manifest.toa.yaml +0 -22
- package/features/steps/map.ts +0 -30
- package/features/steps/tsconfig.json +0 -9
- package/features/streams.feature +0 -35
- package/features/timestamps.feature +0 -41
- package/features/timing.feature +0 -49
- package/features/tracing.feature +0 -123
- package/source/Branch.test.ts +0 -40
- package/source/Branch.ts +0 -44
- package/source/Composition.ts +0 -51
- package/source/Context.ts +0 -11
- package/source/Directive.test.ts +0 -199
- package/source/Directive.ts +0 -248
- package/source/Discovery/Explorer.ts +0 -34
- package/source/Discovery/Site.test.ts +0 -147
- package/source/Discovery/Site.ts +0 -202
- package/source/Discovery/index.ts +0 -3
- package/source/Discovery/tree.test.ts +0 -175
- package/source/Discovery/tree.ts +0 -77
- package/source/Discovery/trunk.ts +0 -33
- package/source/Endpoint.test.ts +0 -67
- package/source/Endpoint.ts +0 -157
- package/source/Factory.ts +0 -42
- package/source/Gateway.ts +0 -390
- package/source/HTTP/Context.ts +0 -143
- package/source/HTTP/Probe.ts +0 -99
- package/source/HTTP/Server.ts +0 -435
- package/source/HTTP/Timing.ts +0 -14
- package/source/HTTP/address.test.ts +0 -28
- package/source/HTTP/address.ts +0 -16
- package/source/HTTP/exceptions.ts +0 -99
- package/source/HTTP/formats/form.ts +0 -21
- package/source/HTTP/formats/index.ts +0 -36
- package/source/HTTP/formats/json.ts +0 -14
- package/source/HTTP/formats/msgpack.ts +0 -14
- package/source/HTTP/formats/text.ts +0 -10
- package/source/HTTP/formats/yaml.test.ts +0 -22
- package/source/HTTP/formats/yaml.ts +0 -40
- package/source/HTTP/index.ts +0 -6
- package/source/HTTP/messages.test.ts +0 -196
- package/source/HTTP/messages.ts +0 -186
- package/source/HTTP/types.ts +0 -39
- package/source/Interception.ts +0 -37
- package/source/Introspection.ts +0 -179
- package/source/MCP/Server.ts +0 -335
- package/source/MCP/discover.ts +0 -51
- package/source/MCP/errors.ts +0 -80
- package/source/MCP/index.ts +0 -1
- package/source/MCP/schema.test.ts +0 -91
- package/source/MCP/schema.ts +0 -94
- package/source/MCP/tools.ts +0 -144
- package/source/MCP/types.ts +0 -84
- package/source/Mapping.ts +0 -101
- package/source/Query.test.ts +0 -54
- package/source/Query.ts +0 -277
- package/source/RPC/Context.ts +0 -75
- package/source/RPC/Dispatcher.ts +0 -150
- package/source/RPC/errors.test.ts +0 -77
- package/source/RPC/errors.ts +0 -82
- package/source/RPC/index.ts +0 -1
- package/source/RPC/names.test.ts +0 -141
- package/source/RPC/names.ts +0 -176
- package/source/RPC/types.ts +0 -34
- package/source/RTD/Context.ts +0 -16
- package/source/RTD/Directives.ts +0 -126
- package/source/RTD/Endpoint.ts +0 -27
- package/source/RTD/Match.ts +0 -11
- package/source/RTD/Method.ts +0 -39
- package/source/RTD/Node.ts +0 -169
- package/source/RTD/Route.ts +0 -93
- package/source/RTD/Tree.ts +0 -137
- package/source/RTD/expiration.test.ts +0 -81
- package/source/RTD/factory.ts +0 -105
- package/source/RTD/index.ts +0 -8
- package/source/RTD/segment.test.ts +0 -35
- package/source/RTD/segment.ts +0 -51
- package/source/RTD/syntax/index.ts +0 -1
- package/source/RTD/walk.test.ts +0 -147
- package/source/Remotes.test.ts +0 -79
- package/source/Remotes.ts +0 -39
- package/source/Tenant.ts +0 -73
- package/source/directives/auth/Anonymous.test.ts +0 -70
- package/source/directives/auth/Anonymous.ts +0 -36
- package/source/directives/auth/Anyone.ts +0 -23
- package/source/directives/auth/Assert.ts +0 -43
- package/source/directives/auth/Authorization.test.ts +0 -24
- package/source/directives/auth/Authorization.ts +0 -388
- package/source/directives/auth/Delegate.test.ts +0 -36
- package/source/directives/auth/Delegate.ts +0 -54
- package/source/directives/auth/Echo.ts +0 -24
- package/source/directives/auth/Federation.ts +0 -104
- package/source/directives/auth/Id.ts +0 -37
- package/source/directives/auth/Incept.ts +0 -117
- package/source/directives/auth/Input.ts +0 -92
- package/source/directives/auth/Role.test.ts +0 -147
- package/source/directives/auth/Role.ts +0 -99
- package/source/directives/auth/Rule.ts +0 -59
- package/source/directives/auth/Scheme.ts +0 -31
- package/source/directives/auth/create.ts +0 -11
- package/source/directives/auth/index.ts +0 -3
- package/source/directives/auth/schemes.test.ts +0 -18
- package/source/directives/auth/schemes.ts +0 -39
- package/source/directives/auth/split.ts +0 -14
- package/source/directives/auth/types.ts +0 -75
- package/source/directives/cache/Cache.ts +0 -92
- package/source/directives/cache/Control.ts +0 -81
- package/source/directives/cache/Exact.ts +0 -7
- package/source/directives/cache/etag.ts +0 -38
- package/source/directives/cache/index.ts +0 -3
- package/source/directives/cache/types.ts +0 -9
- package/source/directives/cors/CORS.test.ts +0 -75
- package/source/directives/cors/CORS.ts +0 -88
- package/source/directives/cors/index.ts +0 -3
- package/source/directives/dev/Development.ts +0 -41
- package/source/directives/dev/Faulty.ts +0 -31
- package/source/directives/dev/Sleep.ts +0 -53
- package/source/directives/dev/Stub.ts +0 -14
- package/source/directives/dev/Throw.ts +0 -14
- package/source/directives/dev/index.ts +0 -3
- package/source/directives/dev/types.ts +0 -5
- package/source/directives/flow/Compose.ts +0 -98
- package/source/directives/flow/Fetch.ts +0 -86
- package/source/directives/flow/Flow.ts +0 -43
- package/source/directives/flow/index.ts +0 -3
- package/source/directives/flow/types.ts +0 -7
- package/source/directives/help/Family.ts +0 -122
- package/source/directives/help/Help.test.ts +0 -227
- package/source/directives/help/Help.ts +0 -47
- package/source/directives/help/Parameters.ts +0 -47
- package/source/directives/help/described.ts +0 -57
- package/source/directives/help/index.ts +0 -45
- package/source/directives/index.ts +0 -33
- package/source/directives/io/Directive.ts +0 -17
- package/source/directives/io/IO.ts +0 -118
- package/source/directives/io/Input.ts +0 -55
- package/source/directives/io/Message.ts +0 -1
- package/source/directives/io/Output.ts +0 -81
- package/source/directives/io/Status.test.ts +0 -88
- package/source/directives/io/Status.ts +0 -47
- package/source/directives/io/Throttle.ts +0 -30
- package/source/directives/io/index.ts +0 -3
- package/source/directives/io/lib/throttle/Configuration.test.ts +0 -72
- package/source/directives/io/lib/throttle/Configuration.ts +0 -68
- package/source/directives/io/lib/throttle/Keys.ts +0 -53
- package/source/directives/io/lib/throttle/Quotas.test.ts +0 -411
- package/source/directives/io/lib/throttle/Quotas.ts +0 -190
- package/source/directives/io/lib/throttle/Sync.test.ts +0 -163
- package/source/directives/io/lib/throttle/Sync.ts +0 -93
- package/source/directives/io/lib/throttle/Warning.test.ts +0 -32
- package/source/directives/io/lib/throttle/Warning.ts +0 -29
- package/source/directives/io/lib/throttle/components/Component.ts +0 -7
- package/source/directives/io/lib/throttle/components/IP.ts +0 -30
- package/source/directives/io/lib/throttle/components/Identity.ts +0 -19
- package/source/directives/io/lib/throttle/components/Path.ts +0 -8
- package/source/directives/io/lib/throttle/components/Route.ts +0 -19
- package/source/directives/io/lib/throttle/components/Segment.ts +0 -19
- package/source/directives/io/lib/throttle/components/index.ts +0 -19
- package/source/directives/io/lib/throttle/conditions/Condition.ts +0 -5
- package/source/directives/io/lib/throttle/conditions/Status.ts +0 -17
- package/source/directives/io/lib/throttle/conditions/index.ts +0 -11
- package/source/directives/io/lib/throttle/index.ts +0 -4
- package/source/directives/io/schemas.test.ts +0 -40
- package/source/directives/io/schemas.ts +0 -16
- package/source/directives/map/Authority.ts +0 -15
- package/source/directives/map/Buffer.ts +0 -15
- package/source/directives/map/Claims.ts +0 -63
- package/source/directives/map/Directive.ts +0 -4
- package/source/directives/map/Headers.ts +0 -60
- package/source/directives/map/Language.ts +0 -45
- package/source/directives/map/Languages.ts +0 -17
- package/source/directives/map/Map.ts +0 -85
- package/source/directives/map/Mapping.ts +0 -45
- package/source/directives/map/Properties.ts +0 -15
- package/source/directives/map/Segments.ts +0 -52
- package/source/directives/map/index.ts +0 -3
- package/source/directives/mcp/MCP.ts +0 -33
- package/source/directives/mcp/Tool.test.ts +0 -56
- package/source/directives/mcp/Tool.ts +0 -32
- package/source/directives/mcp/index.ts +0 -6
- package/source/directives/oauth/Discovery.ts +0 -66
- package/source/directives/oauth/documents.ts +0 -110
- package/source/directives/oauth/index.ts +0 -3
- package/source/directives/octets/Context.ts +0 -23
- package/source/directives/octets/Delete.ts +0 -96
- package/source/directives/octets/Directive.ts +0 -21
- package/source/directives/octets/Get.ts +0 -88
- package/source/directives/octets/Octets.ts +0 -82
- package/source/directives/octets/Put.ts +0 -186
- package/source/directives/octets/Workflow.ts +0 -60
- package/source/directives/octets/bytes.test.ts +0 -33
- package/source/directives/octets/bytes.ts +0 -18
- package/source/directives/octets/index.ts +0 -3
- package/source/directives/octets/schemas.test.ts +0 -20
- package/source/directives/octets/schemas.ts +0 -15
- package/source/directives/octets/types.ts +0 -9
- package/source/directives/octets/workflows/Execution.ts +0 -130
- package/source/directives/octets/workflows/Workflow.ts +0 -51
- package/source/directives/octets/workflows/index.ts +0 -1
- package/source/directives/require/Directive.ts +0 -5
- package/source/directives/require/Headers.ts +0 -19
- package/source/directives/require/Require.ts +0 -27
- package/source/directives/require/index.ts +0 -3
- package/source/discovery.ts +0 -1
- package/source/exceptions.ts +0 -47
- package/source/index.ts +0 -10
- package/source/io.ts +0 -4
- package/source/octets.d.ts +0 -17
- package/source/root.ts +0 -59
- package/source/service.ts +0 -95
- package/source/userland.ts +0 -47
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/ui/dist/_app/immutable/assets/0.Bl7vLmIK.css +0 -2
- package/ui/dist/_app/immutable/assets/2.BC0-Jhqu.css +0 -1
- package/ui/dist/_app/immutable/chunks/BaWe3aOV.js +0 -1
- package/ui/dist/_app/immutable/chunks/DjIYL2zC.js +0 -3
- package/ui/dist/_app/immutable/chunks/GZTfV0ks.js +0 -6
- package/ui/dist/_app/immutable/entry/app.D5v4JoUx.js +0 -2
- package/ui/dist/_app/immutable/entry/start.CWxFoIyZ.js +0 -1
- package/ui/dist/_app/immutable/nodes/0.DIh5T_5-.js +0 -1
- package/ui/dist/_app/immutable/nodes/1.CY-bFzHC.js +0 -1
- package/ui/dist/_app/immutable/nodes/2.6Ubd1ItY.js +0 -14
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { it, beforeEach, afterEach, mock } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { Sync } from './Sync.js'
|
|
5
|
-
import { Quotas } from './Quotas.js'
|
|
6
|
-
import type { atomicity } from '@toa.io/core/types'
|
|
7
|
-
import type { Configuration } from './Configuration.js'
|
|
8
|
-
import type { Input as Context } from '../../../../io.js'
|
|
9
|
-
|
|
10
|
-
let sync: Sync
|
|
11
|
-
let invocations: Input[]
|
|
12
|
-
let context: Context
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
mock.timers.enable()
|
|
16
|
-
|
|
17
|
-
invocations = []
|
|
18
|
-
context = createContext()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
sync.dispose()
|
|
23
|
-
|
|
24
|
-
mock.timers.reset()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('should tick as often as the shortest interval asks', async () => {
|
|
28
|
-
sync = new Sync(createStash())
|
|
29
|
-
|
|
30
|
-
const slow = createQuotas({ interval: 60_000 })
|
|
31
|
-
|
|
32
|
-
// on its own a minute reconciles every two seconds, which is the cap
|
|
33
|
-
sync.register(slow)
|
|
34
|
-
slow.check(context, [])
|
|
35
|
-
|
|
36
|
-
await tick()
|
|
37
|
-
|
|
38
|
-
assert.strictEqual(invocations.length, 0)
|
|
39
|
-
|
|
40
|
-
// a second asks for every 250ms, and the shortest sets the pace for all of them
|
|
41
|
-
sync.register(createQuotas({ interval: 1000 }))
|
|
42
|
-
|
|
43
|
-
await tick()
|
|
44
|
-
|
|
45
|
-
// that a single timer paces every quota was asserted through jest's timer
|
|
46
|
-
// count, which node:test does not expose; the pacing above still covers it
|
|
47
|
-
assert.strictEqual(invocations.length, 1)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('should reconcile every quota in one call', async () => {
|
|
51
|
-
sync = new Sync(createStash())
|
|
52
|
-
|
|
53
|
-
const one = createQuotas()
|
|
54
|
-
const two = createQuotas({ key: [{ method: 'identity' }] })
|
|
55
|
-
|
|
56
|
-
sync.register(one)
|
|
57
|
-
sync.register(two)
|
|
58
|
-
|
|
59
|
-
one.check(context, [])
|
|
60
|
-
two.check(context, [])
|
|
61
|
-
|
|
62
|
-
await tick()
|
|
63
|
-
|
|
64
|
-
assert.strictEqual(invocations.length, 1)
|
|
65
|
-
assert.strictEqual(invocations[0].keys.length, 2)
|
|
66
|
-
assert.deepStrictEqual(invocations[0].deltas, [50, 50])
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('should not call when there is nothing to report', async () => {
|
|
70
|
-
sync = new Sync(createStash())
|
|
71
|
-
|
|
72
|
-
sync.register(createQuotas())
|
|
73
|
-
|
|
74
|
-
await tick()
|
|
75
|
-
|
|
76
|
-
assert.strictEqual(invocations.length, 0)
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('should take the group debt back', async () => {
|
|
80
|
-
sync = new Sync(createStash(() => [1000]))
|
|
81
|
-
|
|
82
|
-
const quotas = createQuotas()
|
|
83
|
-
|
|
84
|
-
sync.register(quotas)
|
|
85
|
-
quotas.check(context, [])
|
|
86
|
-
|
|
87
|
-
await tick()
|
|
88
|
-
|
|
89
|
-
// one request here, but the group is already at capacity
|
|
90
|
-
assert.ok(quotas.check(context, []) > 0)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('should clear what it reported', async () => {
|
|
94
|
-
sync = new Sync(createStash())
|
|
95
|
-
|
|
96
|
-
const quotas = createQuotas()
|
|
97
|
-
|
|
98
|
-
sync.register(quotas)
|
|
99
|
-
quotas.check(context, [])
|
|
100
|
-
|
|
101
|
-
await tick()
|
|
102
|
-
await tick()
|
|
103
|
-
|
|
104
|
-
assert.strictEqual(invocations.length, 1)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('should keep what it could not report, and keep serving', async () => {
|
|
108
|
-
sync = new Sync(
|
|
109
|
-
createStash(() => {
|
|
110
|
-
throw new Error('Redis is unreachable')
|
|
111
|
-
})
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
const quotas = createQuotas()
|
|
115
|
-
|
|
116
|
-
sync.register(quotas)
|
|
117
|
-
quotas.check(context, [])
|
|
118
|
-
|
|
119
|
-
await tick()
|
|
120
|
-
await tick()
|
|
121
|
-
|
|
122
|
-
assert.strictEqual(invocations.length, 2)
|
|
123
|
-
assert.deepStrictEqual(invocations[1].deltas, [50])
|
|
124
|
-
assert.strictEqual(quotas.check(context, []), 0)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
async function tick(): Promise<void> {
|
|
128
|
-
mock.timers.tick(250)
|
|
129
|
-
|
|
130
|
-
// the reconciliation a tick starts is asynchronous, and node:test advances
|
|
131
|
-
// timers synchronously; let it settle before the next one
|
|
132
|
-
await new Promise((resolve) => process.nextTick(resolve))
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function createQuotas(properties?: Partial<Configuration>): Quotas {
|
|
136
|
-
const configuration = { key: [{ method: 'path' as const }], requests: 2, interval: 100 }
|
|
137
|
-
|
|
138
|
-
return Quotas.create(Object.assign(configuration, properties))
|
|
139
|
-
}
|
|
140
|
-
|
|
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
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function createStash(reply?: (deltas: number[]) => number[]): atomicity.Atom {
|
|
149
|
-
const atom = {
|
|
150
|
-
meter: async (keys: string[], deltas: number[]): Promise<number[]> => {
|
|
151
|
-
invocations.push({ keys, deltas })
|
|
152
|
-
|
|
153
|
-
return reply === undefined ? deltas : reply(deltas)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return atom as unknown as atomicity.Atom
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
interface Input {
|
|
161
|
-
keys: string[]
|
|
162
|
-
deltas: number[]
|
|
163
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { console } from 'openspan'
|
|
2
|
-
import type { Quotas } from './Quotas.js'
|
|
3
|
-
import type { atomicity } from '@toa.io/core/types'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Reconciles every quota of the process with the other gateways, on one tick.
|
|
7
|
-
*
|
|
8
|
-
* Nothing here is on the request path. Each tick takes what the quotas have spent since
|
|
9
|
-
* the last one and sends all of it as a single call, so the cost of staying in step is
|
|
10
|
-
* one round trip a tick — not one per key, and not one per directive. What comes back is
|
|
11
|
-
* the debt the whole group has reached, which the quotas then decide on locally.
|
|
12
|
-
*/
|
|
13
|
-
export class Sync {
|
|
14
|
-
private readonly atom: atomicity.Atom
|
|
15
|
-
private readonly quotas: Quotas[] = []
|
|
16
|
-
private timer: NodeJS.Timeout | null = null
|
|
17
|
-
private period = Infinity
|
|
18
|
-
|
|
19
|
-
/** Ticks do not overlap: a slow round trip delays reconciling, it does not double it. */
|
|
20
|
-
private reconciling = false
|
|
21
|
-
|
|
22
|
-
public constructor(atom: atomicity.Atom) {
|
|
23
|
-
this.atom = atom
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public register(quotas: Quotas): void {
|
|
27
|
-
this.quotas.push(quotas)
|
|
28
|
-
|
|
29
|
-
// the shortest interval sets the pace, and reconciling the others more often than
|
|
30
|
-
// they asked for only makes them more accurate — an idle quota contributes nothing
|
|
31
|
-
if (quotas.period < this.period) {
|
|
32
|
-
this.period = quotas.period
|
|
33
|
-
|
|
34
|
-
this.start()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public dispose(): void {
|
|
39
|
-
if (this.timer !== null) {
|
|
40
|
-
clearInterval(this.timer)
|
|
41
|
-
|
|
42
|
-
this.timer = null
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private start(): void {
|
|
47
|
-
this.dispose()
|
|
48
|
-
|
|
49
|
-
this.timer = setInterval(this.tick, this.period)
|
|
50
|
-
|
|
51
|
-
this.timer.unref()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private readonly tick = (): void => {
|
|
55
|
-
if (this.reconciling) return
|
|
56
|
-
|
|
57
|
-
const now = Date.now()
|
|
58
|
-
const batch: Batch[] = []
|
|
59
|
-
|
|
60
|
-
for (const quotas of this.quotas) quotas.flush(now, batch)
|
|
61
|
-
|
|
62
|
-
if (batch.length === 0) return
|
|
63
|
-
|
|
64
|
-
this.reconciling = true
|
|
65
|
-
|
|
66
|
-
void this.reconcile(batch).finally(() => {
|
|
67
|
-
this.reconciling = false
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private async reconcile(batch: Batch[]): Promise<void> {
|
|
72
|
-
try {
|
|
73
|
-
const keys = batch.map((entry) => entry.quotas.name(entry.key))
|
|
74
|
-
const deltas = batch.map((entry) => entry.delta)
|
|
75
|
-
|
|
76
|
-
const debts = await this.atom.meter(keys, deltas)
|
|
77
|
-
const now = Date.now()
|
|
78
|
-
|
|
79
|
-
for (let i = 0; i < batch.length; i++)
|
|
80
|
-
batch[i].quotas.settled(batch[i], debts[i], now)
|
|
81
|
-
} catch (error) {
|
|
82
|
-
// what was not reported stays to be reported by the next tick, and until then
|
|
83
|
-
// this gateway keeps throttling on what it alone has seen, and keeps serving
|
|
84
|
-
console.warn('Throttling could not reconcile with the group', error as Error)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface Batch {
|
|
90
|
-
quotas: Quotas
|
|
91
|
-
key: string
|
|
92
|
-
delta: number
|
|
93
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { it, beforeEach, afterEach, mock } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { console } from 'openspan'
|
|
5
|
-
import { Warning } from './Warning.js'
|
|
6
|
-
|
|
7
|
-
let warn: ReturnType<typeof mock.method>
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
mock.timers.enable({ apis: ['Date'] })
|
|
11
|
-
warn = mock.method(console, 'warn', () => undefined)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
warn.mock.restore()
|
|
16
|
-
mock.timers.reset()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('should write once per interval', () => {
|
|
20
|
-
const warning = new Warning('no ip', 1000)
|
|
21
|
-
|
|
22
|
-
warning.emit()
|
|
23
|
-
warning.emit()
|
|
24
|
-
|
|
25
|
-
assert.equal(warn.mock.callCount(), 1)
|
|
26
|
-
|
|
27
|
-
mock.timers.tick(1000)
|
|
28
|
-
warning.emit()
|
|
29
|
-
|
|
30
|
-
assert.equal(warn.mock.callCount(), 2)
|
|
31
|
-
assert.equal(warn.mock.calls[0].arguments[0], 'no ip')
|
|
32
|
-
})
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { console } from 'openspan'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A warning about a condition that holds for request after request, written once per
|
|
5
|
-
* `interval` rather than once per request.
|
|
6
|
-
*/
|
|
7
|
-
export class Warning {
|
|
8
|
-
private readonly message: string
|
|
9
|
-
private readonly interval: number
|
|
10
|
-
private last = -Infinity
|
|
11
|
-
|
|
12
|
-
public constructor(message: string, interval: number = INTERVAL) {
|
|
13
|
-
this.message = message
|
|
14
|
-
this.interval = interval
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public emit(attributes?: Record<string, unknown>): void {
|
|
18
|
-
const now = Date.now()
|
|
19
|
-
|
|
20
|
-
if (now - this.last < this.interval) return
|
|
21
|
-
|
|
22
|
-
this.last = now
|
|
23
|
-
|
|
24
|
-
console.warn(this.message, attributes)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** 100 seconds */
|
|
29
|
-
const INTERVAL = 100_000
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Parameter } from '../../../../../RTD/index.js'
|
|
2
|
-
import type { Input as Context } from '../../../../../io.js'
|
|
3
|
-
|
|
4
|
-
export interface Component {
|
|
5
|
-
/** what to key on, or nothing when the request cannot be keyed by this component */
|
|
6
|
-
get: (context: Context, parameters: Parameter[]) => string | undefined
|
|
7
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Warning } from '../Warning.js'
|
|
2
|
-
import type { Context } from '../../../../../HTTP/index.js'
|
|
3
|
-
import type { Component } from './Component.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The client address, as the request context resolved it; see `documentation/ip.md`.
|
|
7
|
-
*
|
|
8
|
-
* A request without one cannot be keyed, so it is let through, and whoever keys on the
|
|
9
|
-
* address says so — once in a while rather than on every request, because the cause is
|
|
10
|
-
* the deployment, not the request.
|
|
11
|
-
*/
|
|
12
|
-
export class IP implements Component {
|
|
13
|
-
private readonly warning: Warning
|
|
14
|
-
|
|
15
|
-
public constructor(options: unknown, route: string) {
|
|
16
|
-
const subject = typeof options === 'string' ? options : throttle(route)
|
|
17
|
-
|
|
18
|
-
this.warning = new Warning(`${subject} is not in effect: the request has no ip`)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public get(context: Context): string | undefined {
|
|
22
|
-
if (context.ip === undefined) this.warning.emit()
|
|
23
|
-
|
|
24
|
-
return context.ip
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function throttle(route: string): string {
|
|
29
|
-
return route === '' ? 'Throttle' : `Throttle of ${route}`
|
|
30
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Input } from '../../../../../io.js'
|
|
2
|
-
import type { Component } from './Component.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The authenticated identity, or nothing when the request carries none.
|
|
6
|
-
*
|
|
7
|
-
* Anonymous requests therefore share one quota between them; `ip` is the component
|
|
8
|
-
* that tells them apart.
|
|
9
|
-
*/
|
|
10
|
-
export class Identity implements Component {
|
|
11
|
-
public get(context: Input): string {
|
|
12
|
-
return (context as AuthenticatedContext).identity?.id ?? ''
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// declared here rather than imported from `auth`, the way `cache` does it
|
|
17
|
-
interface AuthenticatedContext extends Input {
|
|
18
|
-
identity?: { id?: string } | null
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Component } from './Component.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The route as declared — `/users/:id` — rather than the path a request came in on.
|
|
5
|
-
*
|
|
6
|
-
* A constant per method, resolved when the tree is built, so every request to one
|
|
7
|
-
* route shares a quota however many concrete paths match it.
|
|
8
|
-
*/
|
|
9
|
-
export class Route implements Component {
|
|
10
|
-
private readonly route: string
|
|
11
|
-
|
|
12
|
-
public constructor(_: unknown, route: string) {
|
|
13
|
-
this.route = route
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public get(): string {
|
|
17
|
-
return this.route
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import type { Parameter } from '../../../../../RTD/index.js'
|
|
3
|
-
import type { Input as Context } from '../../../../../io.js'
|
|
4
|
-
import type { Component } from './Component.js'
|
|
5
|
-
|
|
6
|
-
/** The value a named route segment was bound to, or nothing when the route has none. */
|
|
7
|
-
export class Segment implements Component {
|
|
8
|
-
private readonly name: string
|
|
9
|
-
|
|
10
|
-
public constructor(name: unknown) {
|
|
11
|
-
assert.ok(typeof name === 'string', 'Throttle segment must be a string')
|
|
12
|
-
|
|
13
|
-
this.name = name
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public get(_: Context, parameters: Parameter[]): string {
|
|
17
|
-
return parameters.find(({ name }) => name === this.name)?.value ?? ''
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Path } from './Path.js'
|
|
2
|
-
import { IP } from './IP.js'
|
|
3
|
-
import { Route } from './Route.js'
|
|
4
|
-
import { Identity } from './Identity.js'
|
|
5
|
-
import { Segment } from './Segment.js'
|
|
6
|
-
import type { KeyComponentMethod } from '../Configuration.js'
|
|
7
|
-
import type { Component } from './Component.js'
|
|
8
|
-
|
|
9
|
-
type Constructor<T> = new (options: unknown, route: string) => T
|
|
10
|
-
|
|
11
|
-
export const Components: Record<KeyComponentMethod, Constructor<Component>> = {
|
|
12
|
-
ip: IP,
|
|
13
|
-
path: Path,
|
|
14
|
-
route: Route,
|
|
15
|
-
identity: Identity,
|
|
16
|
-
segment: Segment
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type { Component }
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import type { Input, Output } from '../../../../../io.js'
|
|
3
|
-
import type { Condition } from './Condition.js'
|
|
4
|
-
|
|
5
|
-
export class Status implements Condition {
|
|
6
|
-
private readonly status: number
|
|
7
|
-
|
|
8
|
-
public constructor(status: unknown) {
|
|
9
|
-
assert.ok(typeof status === 'number', 'Status must be a number')
|
|
10
|
-
|
|
11
|
-
this.status = status
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public match(input: Input, output: Output): boolean {
|
|
15
|
-
return output?.status === this.status
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Status } from './Status.js'
|
|
2
|
-
import type { KeyConditionMethod } from '../Configuration.js'
|
|
3
|
-
import type { Condition } from './Condition.js'
|
|
4
|
-
|
|
5
|
-
type Constructor<T> = new (options: unknown) => T
|
|
6
|
-
|
|
7
|
-
export const Conditions: Record<KeyConditionMethod, Constructor<Condition>> = {
|
|
8
|
-
status: Status
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type { Condition }
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import * as schemas from './schemas.js'
|
|
5
|
-
|
|
6
|
-
describe('throttle', () => {
|
|
7
|
-
const rest = { requests: 1, interval: 1 }
|
|
8
|
-
|
|
9
|
-
it('should validate key', () => {
|
|
10
|
-
assert.doesNotThrow(() => schemas.throttle.validate({ key: 'ip', ...rest }))
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('should validate every key component', () => {
|
|
14
|
-
for (const key of ['ip', 'path', 'route', 'identity'])
|
|
15
|
-
assert.doesNotThrow(() => schemas.throttle.validate({ key, ...rest }))
|
|
16
|
-
|
|
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
|
-
)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('should reject an unknown key component', () => {
|
|
29
|
-
assert.throws(() => schemas.throttle.validate({ key: 'header', ...rest }))
|
|
30
|
-
assert.throws(() =>
|
|
31
|
-
schemas.throttle.validate({ key: { header: 'x-real-ip' }, ...rest })
|
|
32
|
-
)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('should reject a declaration it no longer honours', () => {
|
|
36
|
-
// metering earns the budget back rather than locking a key out, so a `cooldown`
|
|
37
|
-
// left behind is not something to ignore quietly
|
|
38
|
-
assert.throws(() => schemas.throttle.validate({ key: 'ip', cooldown: 1, ...rest }))
|
|
39
|
-
})
|
|
40
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path'
|
|
2
|
-
import * as schemas from '@toa.io/schemas'
|
|
3
|
-
import type { Schema } from '@toa.io/schemas'
|
|
4
|
-
import type { Permissions as InputPermissions } from './Input.js'
|
|
5
|
-
import type { Permissions as OutputPermissions } from './Output.js'
|
|
6
|
-
import type { Declaration as ThrottleDeclaration } from './lib/throttle/index.js'
|
|
7
|
-
|
|
8
|
-
import type { Message } from './Message.js'
|
|
9
|
-
|
|
10
|
-
const path = resolve(import.meta.dirname, '../../../schemas/io')
|
|
11
|
-
const namespace = schemas.namespace(path)
|
|
12
|
-
|
|
13
|
-
export const message: Schema<Message | Message[]> = namespace.schema('message')
|
|
14
|
-
export const input: Schema<InputPermissions> = namespace.schema('input')
|
|
15
|
-
export const output: Schema<OutputPermissions> = namespace.schema('output')
|
|
16
|
-
export const throttle: Schema<ThrottleDeclaration> = namespace.schema('throttle')
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Mapping } from './Mapping.js'
|
|
3
|
-
import type { Input } from '../../io.js'
|
|
4
|
-
|
|
5
|
-
export class Authority extends Mapping<string> {
|
|
6
|
-
public constructor(property: string) {
|
|
7
|
-
assert.ok(typeof property === 'string', '`map:authority` must be a string')
|
|
8
|
-
|
|
9
|
-
super(property)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
public properties(context: Input): Record<string, string> {
|
|
13
|
-
return { [this.value]: context.authority }
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Mapping } from './Mapping.js'
|
|
3
|
-
import type { Input } from '../../io.js'
|
|
4
|
-
|
|
5
|
-
export class BufferMapping extends Mapping<string> {
|
|
6
|
-
public constructor(property: string) {
|
|
7
|
-
assert.ok(typeof property === 'string', '`map:buffer` must be a string')
|
|
8
|
-
|
|
9
|
-
super(property)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
public override async properties(context: Input): Promise<Record<string, string>> {
|
|
13
|
-
return { [this.value]: (await context.buffer()).toString('utf8') }
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Mapping } from './Mapping.js'
|
|
3
|
-
import type { Component } from '@toa.io/core'
|
|
4
|
-
import type { Remotes } from '../../Remotes.js'
|
|
5
|
-
import type { Input } from '../../io.js'
|
|
6
|
-
|
|
7
|
-
export class Claims extends Mapping<Record<string, string>> {
|
|
8
|
-
private readonly discovery!: Promise<Component>
|
|
9
|
-
private federation: Component | null = null
|
|
10
|
-
|
|
11
|
-
public constructor(map: Record<string, string>, remotes: Remotes) {
|
|
12
|
-
assert.ok(map.constructor === Object, '`map:claims` must be an object')
|
|
13
|
-
|
|
14
|
-
assert.ok(
|
|
15
|
-
Object.values(map).every((value) => typeof value === 'string'),
|
|
16
|
-
'`map:claims ` must be an object with string values'
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
super(map, remotes)
|
|
20
|
-
|
|
21
|
-
this.discovery = remotes.discover('identity', 'federation')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public override async properties(
|
|
25
|
-
context: Input
|
|
26
|
-
): Promise<Record<string, string> | null> {
|
|
27
|
-
const authentication = context.request.headers.authorization
|
|
28
|
-
|
|
29
|
-
if (authentication === undefined) return null
|
|
30
|
-
|
|
31
|
-
const claims = await this.claims(authentication)
|
|
32
|
-
|
|
33
|
-
if (claims === null) return null
|
|
34
|
-
|
|
35
|
-
return Object.entries(this.value).reduce(
|
|
36
|
-
(properties: Record<string, string>, [property, claim]) => {
|
|
37
|
-
const value = claims[claim]
|
|
38
|
-
|
|
39
|
-
if (value !== undefined) properties[property] = value
|
|
40
|
-
|
|
41
|
-
return properties
|
|
42
|
-
},
|
|
43
|
-
{}
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private async claims(authentication: string): Promise<Record<string, string> | null> {
|
|
48
|
-
const [scheme, credentials] = authentication.split(' ')
|
|
49
|
-
|
|
50
|
-
if (scheme !== 'Bearer' || credentials === undefined) return null
|
|
51
|
-
|
|
52
|
-
this.federation ??= await this.discovery
|
|
53
|
-
|
|
54
|
-
const claims = await this.federation.invoke<Record<string, string> | Error>(
|
|
55
|
-
'decode',
|
|
56
|
-
{ input: credentials }
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
if (claims instanceof Error) return null
|
|
60
|
-
|
|
61
|
-
return claims
|
|
62
|
-
}
|
|
63
|
-
}
|