@toa.io/extensions.exposition 1.0.0-alpha.283 → 1.0.0-alpha.285
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/components/exposition.octets/types/index.d.ts +1 -1
- package/components/identity.bans/operations/transit.js +1 -1
- package/components/identity.bans/tsconfig.json +1 -1
- package/components/identity.bans/tsconfig.tsbuildinfo +1 -1
- package/components/identity.bans/types/index.d.ts +1 -1
- package/components/identity.basic/operations/add.js +1 -1
- package/components/identity.basic/operations/authenticate.js +1 -1
- package/components/identity.basic/operations/check.js +1 -1
- package/components/identity.basic/operations/delete.js +1 -1
- package/components/identity.basic/operations/incept.js +18 -2
- 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 +1 -1
- package/components/identity.basic/source/incept.ts +29 -1
- package/components/identity.basic/tsconfig.json +1 -1
- package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/types/index.d.ts +3 -2
- package/components/identity.clients/operations/describe.js +1 -1
- package/components/identity.clients/operations/lib/Context.js +1 -1
- package/components/identity.clients/operations/lib/Entity.js +1 -1
- package/components/identity.clients/operations/lib/canonical.js +1 -1
- package/components/identity.clients/operations/lib/cimd.js +1 -1
- package/components/identity.clients/operations/lib/errors.js +1 -1
- package/components/identity.clients/operations/lib/index.js +1 -1
- package/components/identity.clients/operations/lib/redirect.js +1 -1
- package/components/identity.clients/operations/register.js +1 -1
- package/components/identity.clients/tsconfig.json +1 -1
- package/components/identity.clients/tsconfig.tsbuildinfo +1 -1
- package/components/identity.clients/types/index.d.ts +1 -1
- package/components/identity.credentials/operations/list.js +1 -1
- package/components/identity.credentials/tsconfig.json +4 -2
- package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
- package/components/identity.credentials/types/index.d.ts +1 -1
- package/components/identity.federation/operations/authenticate.js +7 -3
- package/components/identity.federation/operations/create.js +1 -1
- 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 +6 -2
- package/components/identity.federation/operations/lib/Configuration.js +1 -1
- package/components/identity.federation/operations/lib/Ctx.js +1 -1
- package/components/identity.federation/operations/lib/Payload.js +1 -1
- package/components/identity.federation/operations/lib/decode.js +1 -1
- package/components/identity.federation/operations/lib/discovery.js +1 -1
- package/components/identity.federation/operations/lib/errors.js +1 -1
- package/components/identity.federation/operations/lib/exchange.js +1 -1
- package/components/identity.federation/operations/lib/index.js +2 -1
- package/components/identity.federation/operations/lib/jose.js +1 -1
- package/components/identity.federation/operations/lib/principal.js +14 -0
- package/components/identity.federation/operations/lib/resolve.js +1 -1
- package/components/identity.federation/operations/list.js +1 -1
- package/components/identity.federation/operations/types/Scheme.js +1 -1
- package/components/identity.federation/operations/types/configuration.js +1 -1
- package/components/identity.federation/operations/types/context.js +1 -1
- package/components/identity.federation/operations/types/entity.js +1 -1
- package/components/identity.federation/operations/types/index.js +1 -1
- package/components/identity.federation/source/authenticate.ts +8 -2
- package/components/identity.federation/source/incept.ts +7 -1
- package/components/identity.federation/source/lib/index.ts +1 -0
- package/components/identity.federation/source/lib/principal.ts +17 -0
- package/components/identity.federation/source/types/context.ts +3 -0
- package/components/identity.federation/tsconfig.json +4 -2
- package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/types/index.d.ts +1 -1
- package/components/identity.grants/operations/authorize.js +1 -1
- package/components/identity.grants/operations/exchange.js +1 -1
- 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/lib/index.js +1 -1
- package/components/identity.grants/operations/list.js +1 -1
- package/components/identity.grants/operations/revoke.js +1 -1
- package/components/identity.grants/tsconfig.json +1 -1
- package/components/identity.grants/tsconfig.tsbuildinfo +1 -1
- package/components/identity.grants/types/index.d.ts +1 -1
- 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/tsconfig.json +1 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.keys/types/index.d.ts +1 -1
- package/components/identity.otp/operations/authenticate.js +1 -1
- package/components/identity.otp/operations/issue.js +1 -1
- package/components/identity.otp/operations/lib/Context.js +1 -1
- package/components/identity.otp/operations/lib/Entity.js +1 -1
- package/components/identity.otp/operations/lib/index.js +1 -1
- package/components/identity.otp/tsconfig.json +1 -1
- package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/types/index.d.ts +1 -1
- package/components/identity.passkeys/operations/authenticate.js +1 -1
- package/components/identity.passkeys/operations/challenge.js +1 -1
- package/components/identity.passkeys/operations/create.js +1 -1
- package/components/identity.passkeys/operations/delete.js +1 -1
- package/components/identity.passkeys/operations/lib/const.js +1 -1
- package/components/identity.passkeys/operations/list.js +1 -1
- package/components/identity.passkeys/operations/types/Configuration.js +1 -1
- package/components/identity.passkeys/operations/types/Context.js +1 -1
- package/components/identity.passkeys/operations/types/Passkey.js +1 -1
- package/components/identity.passkeys/operations/types/index.js +1 -1
- package/components/identity.passkeys/operations/use.js +1 -1
- package/components/identity.passkeys/tsconfig.json +1 -1
- package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/types/index.d.ts +1 -1
- package/components/identity.roles/operations/grant.js +1 -1
- package/components/identity.roles/operations/lib/Entity.js +1 -1
- package/components/identity.roles/operations/list.js +1 -1
- package/components/identity.roles/operations/principal.js +29 -5
- package/components/identity.roles/source/principal.ts +33 -5
- package/components/identity.roles/tsconfig.json +1 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/types/index.d.ts +1 -1
- package/components/identity.tokens/operations/authenticate.js +1 -1
- package/components/identity.tokens/operations/decrypt.js +1 -1
- package/components/identity.tokens/operations/encrypt.js +1 -1
- package/components/identity.tokens/operations/issue.js +1 -1
- package/components/identity.tokens/operations/lib/form.js +1 -1
- package/components/identity.tokens/operations/lib/index.js +1 -1
- package/components/identity.tokens/operations/lib/jose.js +1 -1
- package/components/identity.tokens/operations/lib/key.js +1 -1
- package/components/identity.tokens/operations/lib/pad.js +1 -1
- package/components/identity.tokens/operations/revoke.js +1 -1
- package/components/identity.tokens/tsconfig.json +1 -1
- package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/types/index.d.ts +1 -1
- package/documentation/access.md +13 -0
- package/documentation/components.md +3 -0
- package/documentation/introspection.md +13 -5
- package/documentation/io.md +6 -0
- package/documentation/map.md +8 -0
- package/documentation/mcp.md +186 -0
- package/documentation/oauth.md +8 -7
- package/documentation/rpc.md +144 -0
- package/documentation/tree.md +3 -0
- package/features/identity.basic.feature +44 -0
- package/features/identity.federation.feature +2 -5
- package/features/introspection.feature +333 -0
- package/features/mcp.feature +691 -0
- package/features/oauth.discovery.feature +10 -11
- package/features/oauth.grants.feature +22 -9
- package/features/octets.cloudinary.feature +1 -0
- package/features/rpc.feature +429 -0
- package/features/steps/Cloudinary.ts +13 -0
- package/features/steps/Components.ts +0 -4
- package/features/steps/Gateway.ts +19 -2
- package/features/steps/Parameters.ts +18 -7
- package/features/steps/Realtime.ts +3 -0
- package/features/steps/components/echo/manifest.toa.yaml +1 -0
- package/features/steps/components/pots/manifest.toa.yaml +2 -0
- package/package.json +3 -3
- package/readme.md +3 -0
- package/schemas/annotation.cos.yaml +33 -0
- package/schemas/call.cos.yaml +18 -0
- package/source/Annotation.ts +31 -0
- package/source/Directive.test.ts +15 -15
- package/source/Directive.ts +77 -9
- package/source/Endpoint.test.ts +67 -0
- package/source/Endpoint.ts +31 -11
- package/source/Factory.ts +5 -1
- package/source/Gateway.ts +73 -11
- package/source/HTTP/Context.ts +7 -0
- package/source/HTTP/Server.ts +7 -1
- package/source/HTTP/exceptions.ts +2 -2
- package/source/HTTP/messages.ts +10 -1
- package/source/Introspection.ts +105 -0
- package/source/MCP/Server.ts +275 -0
- package/source/MCP/discover.ts +52 -0
- package/source/MCP/errors.ts +81 -0
- package/source/MCP/index.ts +1 -0
- package/source/MCP/schema.test.ts +85 -0
- package/source/MCP/schema.ts +87 -0
- package/source/MCP/tools.ts +157 -0
- package/source/MCP/types.ts +84 -0
- package/source/Query.ts +48 -8
- package/source/RPC/Context.ts +78 -0
- package/source/RPC/Dispatcher.ts +130 -0
- package/source/RPC/errors.test.ts +52 -0
- package/source/RPC/errors.ts +83 -0
- package/source/RPC/index.ts +1 -0
- package/source/RPC/names.test.ts +122 -0
- package/source/RPC/names.ts +183 -0
- package/source/RPC/types.ts +34 -0
- package/source/RTD/Directives.ts +52 -2
- package/source/RTD/Endpoint.ts +2 -1
- package/source/RTD/Method.ts +14 -11
- package/source/RTD/Node.ts +38 -7
- package/source/RTD/Route.ts +30 -3
- package/source/RTD/Tree.ts +37 -1
- package/source/RTD/expiration.test.ts +1 -1
- package/source/RTD/walk.test.ts +110 -0
- package/source/const.ts +15 -0
- package/source/deployment.ts +8 -1
- package/source/directives/auth/Anonymous.test.ts +38 -0
- package/source/directives/auth/Anonymous.ts +12 -0
- package/source/directives/auth/Anyone.ts +4 -0
- package/source/directives/auth/Authorization.ts +62 -3
- package/source/directives/auth/Delegate.test.ts +36 -0
- package/source/directives/auth/Delegate.ts +14 -0
- package/source/directives/auth/Echo.ts +5 -0
- package/source/directives/auth/Incept.ts +2 -1
- package/source/directives/auth/Role.ts +13 -0
- package/source/directives/auth/Rule.ts +29 -0
- package/source/directives/auth/Scheme.ts +5 -0
- package/source/directives/auth/types.ts +21 -0
- package/source/directives/cache/Cache.ts +1 -1
- package/source/directives/dev/Development.ts +1 -1
- package/source/directives/flow/Flow.ts +1 -1
- package/source/directives/index.ts +3 -1
- package/source/directives/io/Directive.ts +1 -1
- package/source/directives/io/IO.ts +32 -3
- package/source/directives/io/Input.ts +3 -2
- package/source/directives/io/Output.ts +6 -3
- package/source/directives/io/Status.test.ts +2 -2
- package/source/directives/io/Status.ts +1 -1
- package/source/directives/io/Throttle.ts +1 -1
- package/source/directives/io/lib/throttle/Quotas.ts +2 -2
- package/source/directives/map/Headers.ts +11 -0
- package/source/directives/map/Map.ts +10 -1
- package/source/directives/map/Mapping.ts +23 -0
- package/source/directives/map/Segments.ts +12 -0
- package/source/directives/mcp/MCP.ts +40 -0
- package/source/directives/mcp/Tool.test.ts +90 -0
- package/source/directives/mcp/Tool.ts +47 -0
- package/source/directives/mcp/index.ts +6 -0
- package/source/directives/oauth/Discovery.ts +10 -16
- package/source/directives/octets/Octets.ts +1 -1
- package/source/directives/require/Directive.ts +1 -1
- package/source/directives/require/Headers.ts +1 -1
- package/source/directives/require/Require.ts +2 -2
- package/source/schemas.ts +2 -0
- package/transpiled/Annotation.d.ts +24 -0
- package/transpiled/Directive.d.ts +18 -1
- package/transpiled/Directive.js +50 -6
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +9 -0
- package/transpiled/Endpoint.js +27 -11
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.js +5 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +19 -2
- package/transpiled/Gateway.js +51 -9
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +6 -0
- package/transpiled/HTTP/Context.js +6 -0
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +5 -1
- package/transpiled/HTTP/exceptions.d.ts +1 -1
- package/transpiled/HTTP/exceptions.js +2 -2
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +6 -0
- package/transpiled/HTTP/messages.js +9 -1
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Introspection.d.ts +42 -0
- package/transpiled/Introspection.js +50 -1
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/MCP/Server.d.ts +41 -0
- package/transpiled/MCP/Server.js +180 -0
- package/transpiled/MCP/Server.js.map +1 -0
- package/transpiled/MCP/discover.d.ts +13 -0
- package/transpiled/MCP/discover.js +29 -0
- package/transpiled/MCP/discover.js.map +1 -0
- package/transpiled/MCP/errors.d.ts +24 -0
- package/transpiled/MCP/errors.js +67 -0
- package/transpiled/MCP/errors.js.map +1 -0
- package/transpiled/MCP/index.d.ts +1 -0
- package/transpiled/MCP/index.js +2 -0
- package/transpiled/MCP/index.js.map +1 -0
- package/transpiled/MCP/schema.d.ts +18 -0
- package/transpiled/MCP/schema.js +64 -0
- package/transpiled/MCP/schema.js.map +1 -0
- package/transpiled/MCP/tools.d.ts +31 -0
- package/transpiled/MCP/tools.js +122 -0
- package/transpiled/MCP/tools.js.map +1 -0
- package/transpiled/MCP/types.d.ts +66 -0
- package/transpiled/MCP/types.js +13 -0
- package/transpiled/MCP/types.js.map +1 -0
- package/transpiled/Query.d.ts +7 -0
- package/transpiled/Query.js +38 -7
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RPC/Context.d.ts +11 -0
- package/transpiled/RPC/Context.js +63 -0
- package/transpiled/RPC/Context.js.map +1 -0
- package/transpiled/RPC/Dispatcher.d.ts +19 -0
- package/transpiled/RPC/Dispatcher.js +100 -0
- package/transpiled/RPC/Dispatcher.js.map +1 -0
- package/transpiled/RPC/errors.d.ts +18 -0
- package/transpiled/RPC/errors.js +67 -0
- package/transpiled/RPC/errors.js.map +1 -0
- package/transpiled/RPC/index.d.ts +1 -0
- package/transpiled/RPC/index.js +2 -0
- package/transpiled/RPC/index.js.map +1 -0
- package/transpiled/RPC/names.d.ts +31 -0
- package/transpiled/RPC/names.js +121 -0
- package/transpiled/RPC/names.js.map +1 -0
- package/transpiled/RPC/types.d.ts +27 -0
- package/transpiled/RPC/types.js +8 -0
- package/transpiled/RPC/types.js.map +1 -0
- package/transpiled/RTD/Directives.d.ts +41 -2
- package/transpiled/RTD/Endpoint.d.ts +2 -1
- package/transpiled/RTD/Method.d.ts +8 -3
- package/transpiled/RTD/Method.js +12 -10
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.d.ts +20 -2
- package/transpiled/RTD/Node.js +22 -4
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.d.ts +2 -1
- package/transpiled/RTD/Route.js +27 -2
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/Tree.d.ts +3 -1
- package/transpiled/RTD/Tree.js +26 -0
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/const.d.ts +12 -0
- package/transpiled/const.js +12 -0
- package/transpiled/const.js.map +1 -1
- package/transpiled/deployment.js +4 -0
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Anonymous.d.ts +6 -0
- package/transpiled/directives/auth/Anonymous.js +10 -0
- package/transpiled/directives/auth/Anonymous.js.map +1 -1
- package/transpiled/directives/auth/Anyone.d.ts +1 -0
- package/transpiled/directives/auth/Anyone.js +3 -0
- package/transpiled/directives/auth/Anyone.js.map +1 -1
- package/transpiled/directives/auth/Authorization.d.ts +27 -1
- package/transpiled/directives/auth/Authorization.js +49 -1
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.d.ts +5 -0
- package/transpiled/directives/auth/Delegate.js +10 -0
- package/transpiled/directives/auth/Delegate.js.map +1 -1
- package/transpiled/directives/auth/Echo.d.ts +2 -0
- package/transpiled/directives/auth/Echo.js +4 -0
- package/transpiled/directives/auth/Echo.js.map +1 -1
- package/transpiled/directives/auth/Incept.js +2 -1
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Role.d.ts +2 -0
- package/transpiled/directives/auth/Role.js +9 -0
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/Rule.d.ts +5 -0
- package/transpiled/directives/auth/Rule.js +20 -0
- package/transpiled/directives/auth/Rule.js.map +1 -1
- package/transpiled/directives/auth/Scheme.d.ts +2 -0
- package/transpiled/directives/auth/Scheme.js +4 -0
- package/transpiled/directives/auth/Scheme.js.map +1 -1
- package/transpiled/directives/auth/types.d.ts +16 -0
- package/transpiled/directives/cache/Cache.d.ts +1 -1
- package/transpiled/directives/cache/Cache.js +1 -1
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/dev/Development.d.ts +1 -1
- package/transpiled/directives/dev/Development.js +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/flow/Flow.d.ts +1 -1
- package/transpiled/directives/flow/Flow.js +1 -1
- package/transpiled/directives/flow/Flow.js.map +1 -1
- package/transpiled/directives/index.js +2 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/Directive.d.ts +1 -1
- package/transpiled/directives/io/IO.d.ts +7 -1
- package/transpiled/directives/io/IO.js +23 -3
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/io/Input.d.ts +3 -2
- package/transpiled/directives/io/Input.js +2 -1
- package/transpiled/directives/io/Input.js.map +1 -1
- package/transpiled/directives/io/Output.d.ts +5 -3
- package/transpiled/directives/io/Output.js +4 -2
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/io/Status.d.ts +1 -1
- package/transpiled/directives/io/Status.js +1 -1
- package/transpiled/directives/io/Status.js.map +1 -1
- package/transpiled/directives/io/Throttle.d.ts +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/Quotas.d.ts +1 -1
- package/transpiled/directives/io/lib/throttle/Quotas.js +2 -2
- package/transpiled/directives/io/lib/throttle/Quotas.js.map +1 -1
- package/transpiled/directives/map/Headers.d.ts +2 -0
- package/transpiled/directives/map/Headers.js +8 -0
- package/transpiled/directives/map/Headers.js.map +1 -1
- package/transpiled/directives/map/Map.d.ts +3 -1
- package/transpiled/directives/map/Map.js +7 -1
- package/transpiled/directives/map/Map.js.map +1 -1
- package/transpiled/directives/map/Mapping.d.ts +13 -0
- package/transpiled/directives/map/Mapping.js +20 -0
- package/transpiled/directives/map/Mapping.js.map +1 -1
- package/transpiled/directives/map/Segments.d.ts +3 -0
- package/transpiled/directives/map/Segments.js +9 -0
- package/transpiled/directives/map/Segments.js.map +1 -1
- package/transpiled/directives/mcp/MCP.d.ts +15 -0
- package/transpiled/directives/mcp/MCP.js +29 -0
- package/transpiled/directives/mcp/MCP.js.map +1 -0
- package/transpiled/directives/mcp/Tool.d.ts +18 -0
- package/transpiled/directives/mcp/Tool.js +34 -0
- package/transpiled/directives/mcp/Tool.js.map +1 -0
- package/transpiled/directives/mcp/index.d.ts +4 -0
- package/transpiled/directives/mcp/index.js +4 -0
- package/transpiled/directives/mcp/index.js.map +1 -0
- package/transpiled/directives/oauth/Discovery.js +10 -13
- package/transpiled/directives/oauth/Discovery.js.map +1 -1
- package/transpiled/directives/octets/Octets.d.ts +1 -1
- package/transpiled/directives/octets/Octets.js +1 -1
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/require/Directive.d.ts +1 -1
- package/transpiled/directives/require/Headers.d.ts +1 -1
- package/transpiled/directives/require/Headers.js +1 -1
- package/transpiled/directives/require/Headers.js.map +1 -1
- package/transpiled/directives/require/Require.d.ts +1 -1
- package/transpiled/directives/require/Require.js +2 -2
- package/transpiled/directives/require/Require.js.map +1 -1
- package/transpiled/schemas.d.ts +2 -0
- package/transpiled/schemas.js +1 -0
- package/transpiled/schemas.js.map +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/components/identity.bans/operations/transit.d.ts +0 -14
- package/components/identity.bans/operations/transit.js.map +0 -1
- package/components/identity.basic/operations/add.d.ts +0 -3
- package/components/identity.basic/operations/add.js.map +0 -1
- package/components/identity.basic/operations/authenticate.d.ts +0 -13
- package/components/identity.basic/operations/authenticate.js.map +0 -1
- package/components/identity.basic/operations/check.d.ts +0 -7
- package/components/identity.basic/operations/check.js.map +0 -1
- package/components/identity.basic/operations/delete.d.ts +0 -7
- package/components/identity.basic/operations/delete.js.map +0 -1
- package/components/identity.basic/operations/incept.d.ts +0 -12
- package/components/identity.basic/operations/incept.js.map +0 -1
- package/components/identity.basic/operations/info.d.ts +0 -10
- package/components/identity.basic/operations/info.js.map +0 -1
- package/components/identity.basic/operations/lib/credentials.d.ts +0 -5
- package/components/identity.basic/operations/lib/credentials.js.map +0 -1
- package/components/identity.basic/operations/transit.d.ts +0 -15
- package/components/identity.basic/operations/transit.js.map +0 -1
- package/components/identity.clients/operations/describe.d.ts +0 -27
- package/components/identity.clients/operations/describe.js.map +0 -1
- package/components/identity.clients/operations/lib/Context.d.ts +0 -29
- package/components/identity.clients/operations/lib/Context.js.map +0 -1
- package/components/identity.clients/operations/lib/Entity.d.ts +0 -29
- package/components/identity.clients/operations/lib/Entity.js.map +0 -1
- package/components/identity.clients/operations/lib/canonical.d.ts +0 -11
- package/components/identity.clients/operations/lib/canonical.js.map +0 -1
- package/components/identity.clients/operations/lib/cimd.d.ts +0 -8
- package/components/identity.clients/operations/lib/cimd.js.map +0 -1
- package/components/identity.clients/operations/lib/errors.d.ts +0 -7
- package/components/identity.clients/operations/lib/errors.js.map +0 -1
- package/components/identity.clients/operations/lib/index.d.ts +0 -6
- package/components/identity.clients/operations/lib/index.js.map +0 -1
- package/components/identity.clients/operations/lib/redirect.d.ts +0 -10
- package/components/identity.clients/operations/lib/redirect.js.map +0 -1
- package/components/identity.clients/operations/register.d.ts +0 -37
- package/components/identity.clients/operations/register.js.map +0 -1
- package/components/identity.credentials/operations/list.d.ts +0 -52
- package/components/identity.credentials/operations/list.js.map +0 -1
- package/components/identity.federation/operations/authenticate.d.ts +0 -16
- package/components/identity.federation/operations/authenticate.js.map +0 -1
- package/components/identity.federation/operations/create.d.ts +0 -8
- package/components/identity.federation/operations/create.js.map +0 -1
- package/components/identity.federation/operations/decode.d.ts +0 -3
- package/components/identity.federation/operations/decode.js.map +0 -1
- package/components/identity.federation/operations/delete.d.ts +0 -8
- package/components/identity.federation/operations/delete.js.map +0 -1
- package/components/identity.federation/operations/incept.d.ts +0 -11
- package/components/identity.federation/operations/incept.js.map +0 -1
- package/components/identity.federation/operations/lib/Configuration.d.ts +0 -39
- package/components/identity.federation/operations/lib/Configuration.js.map +0 -1
- package/components/identity.federation/operations/lib/Ctx.d.ts +0 -8
- package/components/identity.federation/operations/lib/Ctx.js.map +0 -1
- package/components/identity.federation/operations/lib/Payload.d.ts +0 -5
- package/components/identity.federation/operations/lib/Payload.js.map +0 -1
- package/components/identity.federation/operations/lib/decode.d.ts +0 -3
- package/components/identity.federation/operations/lib/decode.js.map +0 -1
- package/components/identity.federation/operations/lib/discovery.d.ts +0 -5
- package/components/identity.federation/operations/lib/discovery.js.map +0 -1
- package/components/identity.federation/operations/lib/errors.d.ts +0 -77
- package/components/identity.federation/operations/lib/errors.js.map +0 -1
- package/components/identity.federation/operations/lib/exchange.d.ts +0 -3
- package/components/identity.federation/operations/lib/exchange.js.map +0 -1
- package/components/identity.federation/operations/lib/index.d.ts +0 -4
- package/components/identity.federation/operations/lib/index.js.map +0 -1
- package/components/identity.federation/operations/lib/jose.d.ts +0 -1
- package/components/identity.federation/operations/lib/jose.js.map +0 -1
- package/components/identity.federation/operations/lib/resolve.d.ts +0 -3
- package/components/identity.federation/operations/lib/resolve.js.map +0 -1
- package/components/identity.federation/operations/list.d.ts +0 -7
- package/components/identity.federation/operations/list.js.map +0 -1
- package/components/identity.federation/operations/types/Scheme.d.ts +0 -1
- package/components/identity.federation/operations/types/Scheme.js.map +0 -1
- package/components/identity.federation/operations/types/configuration.d.ts +0 -22
- package/components/identity.federation/operations/types/configuration.js.map +0 -1
- package/components/identity.federation/operations/types/context.d.ts +0 -36
- package/components/identity.federation/operations/types/context.js.map +0 -1
- package/components/identity.federation/operations/types/entity.d.ts +0 -9
- package/components/identity.federation/operations/types/entity.js.map +0 -1
- package/components/identity.federation/operations/types/index.d.ts +0 -4
- package/components/identity.federation/operations/types/index.js.map +0 -1
- package/components/identity.grants/operations/authorize.d.ts +0 -35
- package/components/identity.grants/operations/authorize.js.map +0 -1
- package/components/identity.grants/operations/exchange.d.ts +0 -37
- package/components/identity.grants/operations/exchange.js.map +0 -1
- package/components/identity.grants/operations/lib/code.d.ts +0 -15
- package/components/identity.grants/operations/lib/code.js.map +0 -1
- package/components/identity.grants/operations/lib/identify.d.ts +0 -6
- package/components/identity.grants/operations/lib/identify.js.map +0 -1
- package/components/identity.grants/operations/lib/index.d.ts +0 -3
- package/components/identity.grants/operations/lib/index.js.map +0 -1
- package/components/identity.grants/operations/list.d.ts +0 -13
- package/components/identity.grants/operations/list.js.map +0 -1
- package/components/identity.grants/operations/revoke.d.ts +0 -18
- package/components/identity.grants/operations/revoke.js.map +0 -1
- package/components/identity.keys/operations/create.d.ts +0 -22
- package/components/identity.keys/operations/create.js.map +0 -1
- package/components/identity.keys/operations/disable.d.ts +0 -5
- package/components/identity.keys/operations/disable.js.map +0 -1
- package/components/identity.keys/operations/revoke.d.ts +0 -15
- package/components/identity.keys/operations/revoke.js.map +0 -1
- package/components/identity.otp/operations/authenticate.d.ts +0 -12
- package/components/identity.otp/operations/authenticate.js.map +0 -1
- package/components/identity.otp/operations/issue.d.ts +0 -12
- package/components/identity.otp/operations/issue.js.map +0 -1
- package/components/identity.otp/operations/lib/Context.d.ts +0 -16
- package/components/identity.otp/operations/lib/Context.js.map +0 -1
- package/components/identity.otp/operations/lib/Entity.d.ts +0 -6
- package/components/identity.otp/operations/lib/Entity.js.map +0 -1
- package/components/identity.otp/operations/lib/index.d.ts +0 -1
- package/components/identity.otp/operations/lib/index.js.map +0 -1
- package/components/identity.passkeys/operations/authenticate.d.ts +0 -16
- package/components/identity.passkeys/operations/authenticate.js.map +0 -1
- package/components/identity.passkeys/operations/challenge.d.ts +0 -35
- package/components/identity.passkeys/operations/challenge.js.map +0 -1
- package/components/identity.passkeys/operations/create.d.ts +0 -19
- package/components/identity.passkeys/operations/create.js.map +0 -1
- package/components/identity.passkeys/operations/delete.d.ts +0 -8
- package/components/identity.passkeys/operations/delete.js.map +0 -1
- package/components/identity.passkeys/operations/lib/const.d.ts +0 -1
- package/components/identity.passkeys/operations/lib/const.js.map +0 -1
- package/components/identity.passkeys/operations/list.d.ts +0 -7
- package/components/identity.passkeys/operations/list.js.map +0 -1
- package/components/identity.passkeys/operations/types/Configuration.d.ts +0 -6
- package/components/identity.passkeys/operations/types/Configuration.js.map +0 -1
- package/components/identity.passkeys/operations/types/Context.d.ts +0 -16
- package/components/identity.passkeys/operations/types/Context.js.map +0 -1
- package/components/identity.passkeys/operations/types/Passkey.d.ts +0 -12
- package/components/identity.passkeys/operations/types/Passkey.js.map +0 -1
- package/components/identity.passkeys/operations/types/index.d.ts +0 -2
- package/components/identity.passkeys/operations/types/index.js.map +0 -1
- package/components/identity.passkeys/operations/use.d.ts +0 -16
- package/components/identity.passkeys/operations/use.js.map +0 -1
- package/components/identity.roles/operations/grant.d.ts +0 -10
- package/components/identity.roles/operations/grant.js.map +0 -1
- package/components/identity.roles/operations/lib/Entity.d.ts +0 -5
- package/components/identity.roles/operations/lib/Entity.js.map +0 -1
- package/components/identity.roles/operations/list.d.ts +0 -2
- package/components/identity.roles/operations/list.js.map +0 -1
- package/components/identity.roles/operations/principal.d.ts +0 -13
- package/components/identity.roles/operations/principal.js.map +0 -1
- package/components/identity.tokens/operations/authenticate.d.ts +0 -10
- package/components/identity.tokens/operations/authenticate.js.map +0 -1
- package/components/identity.tokens/operations/decrypt.d.ts +0 -16
- package/components/identity.tokens/operations/decrypt.js.map +0 -1
- package/components/identity.tokens/operations/encrypt.d.ts +0 -9
- package/components/identity.tokens/operations/encrypt.js.map +0 -1
- package/components/identity.tokens/operations/issue.d.ts +0 -25
- package/components/identity.tokens/operations/issue.js.map +0 -1
- package/components/identity.tokens/operations/lib/form.d.ts +0 -8
- package/components/identity.tokens/operations/lib/form.js.map +0 -1
- package/components/identity.tokens/operations/lib/index.d.ts +0 -4
- package/components/identity.tokens/operations/lib/index.js.map +0 -1
- package/components/identity.tokens/operations/lib/jose.d.ts +0 -1
- package/components/identity.tokens/operations/lib/jose.js.map +0 -1
- package/components/identity.tokens/operations/lib/key.d.ts +0 -1
- package/components/identity.tokens/operations/lib/key.js.map +0 -1
- package/components/identity.tokens/operations/lib/pad.d.ts +0 -1
- package/components/identity.tokens/operations/lib/pad.js.map +0 -1
- package/components/identity.tokens/operations/revoke.d.ts +0 -2
- package/components/identity.tokens/operations/revoke.js.map +0 -1
package/source/RTD/Directives.ts
CHANGED
|
@@ -2,18 +2,36 @@ import type { Parameter } from './Match.js'
|
|
|
2
2
|
import type * as syntax from './syntax/index.js'
|
|
3
3
|
import type { Context, OutgoingMessage, Options } from '../HTTP/index.js'
|
|
4
4
|
import type { Output } from '../io.js'
|
|
5
|
+
import type { Introspection } from '../Introspection.js'
|
|
5
6
|
import type { extensions } from '@toa.io/core'
|
|
6
7
|
|
|
7
8
|
type Host = extensions.Host
|
|
8
9
|
|
|
9
10
|
export interface Directives {
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The directives of one family on this method, or nothing where it declares none of it.
|
|
13
|
+
* For a consumer of a declaration rather than of a stage: what a method is published as
|
|
14
|
+
* is stated on the route, and read where the publishing happens.
|
|
15
|
+
*/
|
|
16
|
+
declared: <T>(family: string) => T[] | undefined
|
|
17
|
+
|
|
18
|
+
precall: (context: Context, parameters: Parameter[]) => Promise<Output>
|
|
19
|
+
|
|
20
|
+
/** What this route's directives make of what its method says about itself. */
|
|
21
|
+
explain: (context: Context, introspection: Introspection) => Promise<Introspection | null>
|
|
11
22
|
settle: (context: Context, response: OutgoingMessage) => Promise<void>
|
|
12
23
|
dispose: () => void
|
|
13
24
|
}
|
|
14
25
|
|
|
15
26
|
export interface DirectiveFactory {
|
|
16
27
|
create: (directives: syntax.Directive[], route: string) => Directives
|
|
28
|
+
|
|
29
|
+
/** Runs every family's `preflight`, which is request-scoped and needs no node. */
|
|
30
|
+
preflight: (context: Context) => Promise<void>
|
|
31
|
+
|
|
32
|
+
/** Runs every family's `depart`, the counterpart of `preflight`. */
|
|
33
|
+
depart: (context: Context, response: OutgoingMessage) => Promise<void>
|
|
34
|
+
|
|
17
35
|
dispose: () => void
|
|
18
36
|
}
|
|
19
37
|
|
|
@@ -43,13 +61,45 @@ export interface DirectiveFamily<TDirective = any, TExtension = any> {
|
|
|
43
61
|
*/
|
|
44
62
|
arrange?: (directives: TDirective[]) => void
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Request-scoped, before anything is routed. It takes no directives: no node is known
|
|
66
|
+
* yet, and a request that carries several calls has no single node at all. What a
|
|
67
|
+
* directive declares is call-scoped by definition, so only what a family does on its
|
|
68
|
+
* own behalf — authenticating a credential — belongs here. It answers nothing: a stage
|
|
69
|
+
* that runs before a route is known has no reply to make, and refuses by throwing.
|
|
70
|
+
*/
|
|
71
|
+
preflight?: (request: Context & TExtension) => void | Promise<void>
|
|
72
|
+
|
|
73
|
+
/** Call-scoped, with what the node declares. Runs once per call. */
|
|
74
|
+
precall?: (directives: TDirective[],
|
|
47
75
|
request: Context & TExtension,
|
|
48
76
|
parameters: Parameter[]) => Output | Promise<Output>
|
|
49
77
|
|
|
78
|
+
/**
|
|
79
|
+
* What this family's directives make of what the method says about itself, which is
|
|
80
|
+
* what `OPTIONS` answers and what a tool is described by. `null` refuses: the method
|
|
81
|
+
* is not reachable by this caller, and is not described at all.
|
|
82
|
+
*
|
|
83
|
+
* There is no request here — no route variable has a value and no body has arrived, which
|
|
84
|
+
* is why no parameters are passed — so a directive that can only tell from one hands back
|
|
85
|
+
* what it was given.
|
|
86
|
+
*/
|
|
87
|
+
explain?: (directives: TDirective[],
|
|
88
|
+
request: Context & TExtension,
|
|
89
|
+
introspection: Introspection) => Introspection | null | Promise<Introspection | null>
|
|
90
|
+
|
|
91
|
+
/** Call-scoped, on the message that call produced. */
|
|
50
92
|
settle?: (directives: TDirective[],
|
|
51
93
|
request: Context & TExtension,
|
|
52
94
|
response: OutgoingMessage) => void | Promise<void>
|
|
53
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Request-scoped, on the message going back — the counterpart of `preflight`, and
|
|
98
|
+
* likewise without directives. A reply the whole request carries, such as a re-issued
|
|
99
|
+
* credential, is written here rather than by a call that would not own it.
|
|
100
|
+
*/
|
|
101
|
+
depart?: (request: Context & TExtension,
|
|
102
|
+
response: OutgoingMessage) => void | Promise<void>
|
|
103
|
+
|
|
54
104
|
dispose?: (directives: TDirective[]) => void
|
|
55
105
|
}
|
package/source/RTD/Endpoint.ts
CHANGED
|
@@ -2,11 +2,12 @@ import { type Context } from './Context.js'
|
|
|
2
2
|
import type * as http from '../HTTP/index.js'
|
|
3
3
|
import type * as syntax from './syntax/index.js'
|
|
4
4
|
import type * as RTD from './index.js'
|
|
5
|
+
import type { Introspection } from '../Introspection.js'
|
|
5
6
|
|
|
6
7
|
export interface Endpoint {
|
|
7
8
|
call: (context: http.Context, parameters: RTD.Parameter[]) => Promise<http.OutgoingMessage>
|
|
8
9
|
|
|
9
|
-
explain: (parameters: RTD.Parameter[]) => Promise<
|
|
10
|
+
explain: (parameters: RTD.Parameter[]) => Promise<Introspection>
|
|
10
11
|
|
|
11
12
|
close: () => Promise<void>
|
|
12
13
|
}
|
package/source/RTD/Method.ts
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import type { Parameter } from './Match.js'
|
|
2
2
|
import type { Endpoint } from './Endpoint.js'
|
|
3
3
|
import type { Directives } from './Directives.js'
|
|
4
|
+
import type { Context } from '../HTTP/index.js'
|
|
5
|
+
import { order } from '../Introspection.js'
|
|
6
|
+
import type { Introspection } from '../Introspection.js'
|
|
4
7
|
|
|
5
8
|
export class Method {
|
|
6
9
|
public readonly endpoint: Endpoint | null
|
|
7
10
|
public readonly directives: Directives
|
|
8
|
-
private introspection: unknown | null = null
|
|
9
|
-
private introspecting: Promise<unknown> | null = null
|
|
10
11
|
|
|
11
12
|
public constructor (endpoint: Endpoint | null, directives: Directives) {
|
|
12
13
|
this.endpoint = endpoint
|
|
13
14
|
this.directives = directives
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* What this method says about itself, as its directives leave it, or nothing where they
|
|
19
|
+
* refuse this caller. A method of no endpoint — one a directive answers on its own —
|
|
20
|
+
* states nothing of its own, and its directives still have their say.
|
|
21
|
+
*/
|
|
22
|
+
public async explain (context: Context, parameters: Parameter[]): Promise<Introspection | null> {
|
|
23
|
+
const introspection = this.endpoint === null
|
|
24
|
+
? {}
|
|
25
|
+
: await this.endpoint.explain(parameters)
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
|
|
22
|
-
this.introspecting = this.endpoint?.explain(parameters)!
|
|
27
|
+
const described = await this.directives.explain(context, introspection)
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return this.introspection
|
|
29
|
+
return described === null ? null : order(described)
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
public async close (): Promise<void> {
|
package/source/RTD/Node.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type Route } from './Route.js'
|
|
2
|
-
import { type Methods } from './Method.js'
|
|
2
|
+
import { type Method, type Methods } from './Method.js'
|
|
3
3
|
import { type Match, type Parameter } from './Match.js'
|
|
4
|
+
import type { Segment } from './segment.js'
|
|
5
|
+
import type { Context } from '../HTTP/index.js'
|
|
6
|
+
import type { Introspection } from '../Introspection.js'
|
|
4
7
|
|
|
5
8
|
export class Node {
|
|
6
9
|
public intermediate: boolean
|
|
@@ -52,14 +55,35 @@ export class Node {
|
|
|
52
55
|
this.expiration = expiration
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Every method under this node, with the template it answers at.
|
|
60
|
+
*
|
|
61
|
+
* An intermediate node is skipped: it is never what a path matches, because its `/` route
|
|
62
|
+
* answers at the same place and is reached instead. The trunk is the exception `match`
|
|
63
|
+
* makes for it — `'/'` answers the trunk itself, whatever it holds.
|
|
64
|
+
*/
|
|
65
|
+
public * walk (segments: Segment[], trunk = false): Generator<Mount> {
|
|
66
|
+
if (trunk || !this.intermediate)
|
|
67
|
+
for (const [verb, method] of Object.entries(this.methods))
|
|
68
|
+
yield { segments, verb, method }
|
|
69
|
+
|
|
70
|
+
for (const route of this.routes)
|
|
71
|
+
yield * route.walk(segments)
|
|
72
|
+
}
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
74
|
+
/** Every method of this node that this caller may reach, in the order they were declared. */
|
|
75
|
+
public async explain (context: Context,
|
|
76
|
+
parameters: Parameter[]): Promise<Record<string, Introspection>> {
|
|
77
|
+
const entries = Object.entries(this.methods)
|
|
61
78
|
|
|
62
|
-
await Promise.all(
|
|
79
|
+
const explained = await Promise.all(entries
|
|
80
|
+
.map(async ([, method]) => await method.explain(context, parameters)))
|
|
81
|
+
|
|
82
|
+
const methods: Record<string, Introspection> = {}
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < entries.length; i++)
|
|
85
|
+
if (explained[i] !== null)
|
|
86
|
+
methods[entries[i][0]] = explained[i]!
|
|
63
87
|
|
|
64
88
|
return methods
|
|
65
89
|
}
|
|
@@ -119,6 +143,13 @@ export class Node {
|
|
|
119
143
|
}
|
|
120
144
|
}
|
|
121
145
|
|
|
146
|
+
/** A method, and the route template it is reached by. */
|
|
147
|
+
export interface Mount {
|
|
148
|
+
segments: Segment[]
|
|
149
|
+
verb: string
|
|
150
|
+
method: Method
|
|
151
|
+
}
|
|
152
|
+
|
|
122
153
|
export interface Properties {
|
|
123
154
|
protected: boolean
|
|
124
155
|
forward?: string
|
package/source/RTD/Route.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Segment } from './segment.js'
|
|
2
2
|
import { type Match, type Parameter } from './Match.js'
|
|
3
|
-
import type { Node } from './Node.js'
|
|
3
|
+
import type { Mount, Node } from './Node.js'
|
|
4
4
|
|
|
5
5
|
export class Route {
|
|
6
6
|
public readonly root: boolean
|
|
@@ -32,10 +32,13 @@ export class Route {
|
|
|
32
32
|
return null
|
|
33
33
|
|
|
34
34
|
if (segment.fragment === null && segment.placeholder !== null)
|
|
35
|
-
parameters.push({ name: segment.placeholder, value: fragments[i] })
|
|
35
|
+
parameters.push({ name: segment.placeholder, value: decode(fragments[i]) })
|
|
36
36
|
|
|
37
37
|
if (segment.fragment === null && segment.wildcard === true)
|
|
38
|
-
parameters.push({
|
|
38
|
+
parameters.push({
|
|
39
|
+
name: '**',
|
|
40
|
+
value: fragments.slice(this.segments.length - 1).map(decode).join('/')
|
|
41
|
+
})
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
const exact = this.segments.length === fragments.length
|
|
@@ -46,6 +49,14 @@ export class Route {
|
|
|
46
49
|
return this.matchNested(fragments, parameters)
|
|
47
50
|
}
|
|
48
51
|
|
|
52
|
+
public * walk (prefix: Segment[]): Generator<Mount> {
|
|
53
|
+
// an expired branch is not matched, so nothing under it is reachable to name
|
|
54
|
+
if (Date.now() >= this.node.expiration)
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
yield * this.node.walk(prefix.concat(this.segments))
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
public equals (route: Route): boolean {
|
|
50
61
|
if (route.segments.length !== this.segments.length)
|
|
51
62
|
return false
|
|
@@ -67,3 +78,19 @@ export class Route {
|
|
|
67
78
|
return this.node.match(fragments, parameters)
|
|
68
79
|
}
|
|
69
80
|
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* What the segment says, rather than how it was written: a value is percent-encoded to
|
|
84
|
+
* survive the path, and an operation reads what a caller meant — a `client_id` that is a
|
|
85
|
+
* URL arrives as one. A literal segment is matched as written, which is how it is declared.
|
|
86
|
+
*
|
|
87
|
+
* An escape that decodes to nothing valid is left as it stands; refusing the route over it
|
|
88
|
+
* would answer `404` to a request whose only fault is its spelling.
|
|
89
|
+
*/
|
|
90
|
+
function decode (fragment: string): string {
|
|
91
|
+
try {
|
|
92
|
+
return decodeURIComponent(fragment)
|
|
93
|
+
} catch {
|
|
94
|
+
return fragment
|
|
95
|
+
}
|
|
96
|
+
}
|
package/source/RTD/Tree.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { console } from 'openspan'
|
|
2
|
+
import { refusal, template } from '../RPC/names.js'
|
|
1
3
|
import { branchTTL, createNode } from './factory.js'
|
|
2
4
|
import { fragment } from './segment.js'
|
|
3
|
-
import type { Node } from './Node.js'
|
|
5
|
+
import type { Mount, Node } from './Node.js'
|
|
4
6
|
import type { Match } from './Match.js'
|
|
5
7
|
import type { Context } from './Context.js'
|
|
6
8
|
import type { DirectiveFactory } from './Directives.js'
|
|
@@ -18,6 +20,8 @@ export class Tree {
|
|
|
18
20
|
this.directives = directives
|
|
19
21
|
this.root = node
|
|
20
22
|
this.trunk = this.createNode(node, PROTECTED)
|
|
23
|
+
|
|
24
|
+
unnameable(this.trunk)
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
public match (path: string): Match | null {
|
|
@@ -32,9 +36,16 @@ export class Tree {
|
|
|
32
36
|
return this.trunk.match(fragments)
|
|
33
37
|
}
|
|
34
38
|
|
|
39
|
+
/** Every method in the tree, with the template it answers at. */
|
|
40
|
+
public walk (): Generator<Mount> {
|
|
41
|
+
return this.trunk.walk([], TRUNK)
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
public merge (node: syntax.Node, extension: unknown): Node[] {
|
|
36
45
|
const branch = this.createNode(node, !PROTECTED, extension)
|
|
37
46
|
|
|
47
|
+
unnameable(branch)
|
|
48
|
+
|
|
38
49
|
return this.trunk.merge(branch)
|
|
39
50
|
}
|
|
40
51
|
|
|
@@ -72,6 +83,30 @@ export class Tree {
|
|
|
72
83
|
}
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
/**
|
|
87
|
+
* What is served but cannot be called by name. Said once per route as it is built, because a
|
|
88
|
+
* procedure that is missing is otherwise noticed only by the caller who cannot find it.
|
|
89
|
+
*/
|
|
90
|
+
function unnameable (node: Node): void {
|
|
91
|
+
const said = new Set<string>()
|
|
92
|
+
|
|
93
|
+
for (const { segments } of node.walk([], TRUNK)) {
|
|
94
|
+
const segment = refusal(segments)
|
|
95
|
+
|
|
96
|
+
if (segment === null)
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
const route = template(segments)
|
|
100
|
+
|
|
101
|
+
if (said.has(route))
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
said.add(route)
|
|
105
|
+
|
|
106
|
+
console.warn('Route cannot be addressed as a procedure', { route, segment })
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
75
110
|
/**
|
|
76
111
|
* A branch's routes are relative to wherever it is merged, and the mount point is not
|
|
77
112
|
* known while it is being built — so the component it came from is what keeps two
|
|
@@ -89,3 +124,4 @@ function label (extension: unknown): string {
|
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
const PROTECTED = true
|
|
127
|
+
const TRUNK = true
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { Tree } from './Tree.js'
|
|
5
|
+
import { address, name } from '../RPC/names.js'
|
|
6
|
+
import type { EndpointsFactory } from '../Endpoint.js'
|
|
7
|
+
import type { DirectiveFactory } from './Directives.js'
|
|
8
|
+
import type * as syntax from './syntax/index.js'
|
|
9
|
+
|
|
10
|
+
const endpoints = {} as unknown as EndpointsFactory
|
|
11
|
+
|
|
12
|
+
const directives = {
|
|
13
|
+
create: () => ({
|
|
14
|
+
precall: async () => null,
|
|
15
|
+
settle: async () => undefined,
|
|
16
|
+
dispose: () => undefined
|
|
17
|
+
}),
|
|
18
|
+
dispose: mock.fn()
|
|
19
|
+
} as unknown as DirectiveFactory
|
|
20
|
+
|
|
21
|
+
const node = (path: string, verbs: string[] = [], routes: syntax.Route[] = []): syntax.Route => ({
|
|
22
|
+
path,
|
|
23
|
+
node: {
|
|
24
|
+
routes,
|
|
25
|
+
methods: verbs.map((verb) => ({ verb, directives: [] })),
|
|
26
|
+
directives: []
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const trunk = (routes: syntax.Route[], verbs: string[] = []): syntax.Node => ({
|
|
31
|
+
routes,
|
|
32
|
+
methods: verbs.map((verb) => ({ verb, directives: [] })),
|
|
33
|
+
directives: []
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
/** What a walk names, which is what a caller of `/.rpc` would write. */
|
|
37
|
+
function names (tree: Tree): string[] {
|
|
38
|
+
return [...tree.walk()].map(({ segments, verb }) => name(segments, verb))
|
|
39
|
+
.filter((named): named is string => named !== null)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('walk', () => {
|
|
43
|
+
it('should name the trunk by its verb alone', () => {
|
|
44
|
+
const tree = new Tree(trunk([], ['GET']), endpoints, directives)
|
|
45
|
+
|
|
46
|
+
assert.deepEqual(names(tree), ['GET'])
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should name every method of every route', () => {
|
|
50
|
+
const tree = new Tree(trunk([
|
|
51
|
+
node('/pots', ['GET', 'POST'], [node('/:id', ['GET', 'DELETE'])])
|
|
52
|
+
]), endpoints, directives)
|
|
53
|
+
|
|
54
|
+
assert.deepEqual(names(tree).sort(), [
|
|
55
|
+
'pots.GET', 'pots.POST', 'pots._id.DELETE', 'pots._id.GET'
|
|
56
|
+
])
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should walk a branch that was merged', () => {
|
|
60
|
+
const tree = new Tree(trunk([]), endpoints, directives)
|
|
61
|
+
|
|
62
|
+
tree.merge(trunk([node('/pots', ['GET'])]), { namespace: 'default', component: 'pots' })
|
|
63
|
+
|
|
64
|
+
assert.deepEqual(names(tree), ['pots.GET'])
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should name a tail', () => {
|
|
68
|
+
const tree = new Tree(trunk([node('/files', [], [node('/**', ['GET'])])]),
|
|
69
|
+
endpoints, directives)
|
|
70
|
+
|
|
71
|
+
assert.deepEqual(names(tree), ['files.__.GET'])
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('should skip an intermediate node, whose route answers in its place', () => {
|
|
75
|
+
const tree = new Tree(trunk([
|
|
76
|
+
// `/posts` is intermediate: `/posts/` is answered by its `/` route, not by itself
|
|
77
|
+
node('/posts', ['PATCH'], [node('/', ['PUT'])])
|
|
78
|
+
]), endpoints, directives)
|
|
79
|
+
|
|
80
|
+
assert.deepEqual(names(tree), ['posts.PUT'])
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('should name nothing where a segment cannot be spelled', () => {
|
|
84
|
+
const tree = new Tree(trunk([node('/v1.0', ['GET']), node('/pots', ['GET'])]),
|
|
85
|
+
endpoints, directives)
|
|
86
|
+
|
|
87
|
+
assert.deepEqual(names(tree), ['pots.GET'])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should name what the tree then matches', () => {
|
|
91
|
+
const tree = new Tree(trunk([
|
|
92
|
+
node('/pots', ['GET'], [node('/:id', ['GET']), node('/hot', ['GET'])]),
|
|
93
|
+
node('/files', [], [node('/**', ['GET'])])
|
|
94
|
+
], ['GET']), endpoints, directives)
|
|
95
|
+
|
|
96
|
+
const params = { id: 'a1b2', '**': 'a/b/c' }
|
|
97
|
+
|
|
98
|
+
for (const { segments, verb } of tree.walk()) {
|
|
99
|
+
const named = name(segments, verb)
|
|
100
|
+
|
|
101
|
+
assert.notStrictEqual(named, null, 'every walked method has a name')
|
|
102
|
+
|
|
103
|
+
const { path } = address(named!, params)
|
|
104
|
+
const match = tree.match(path)
|
|
105
|
+
|
|
106
|
+
assert.notStrictEqual(match, null, `'${named!}' resolves to '${path}', which matches`)
|
|
107
|
+
assert.ok(verb in match!.node.methods, `'${named!}' matches a node that answers ${verb}`)
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
})
|
package/source/const.ts
CHANGED
|
@@ -2,3 +2,18 @@ export const BRANCH_TTL = 1_800_000
|
|
|
2
2
|
|
|
3
3
|
/** The replicas of the gateway decide together, whatever context they serve. */
|
|
4
4
|
export const ATOM_GROUP = 'exposition'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Where JSON-RPC is served, for every procedure at once. Pinned rather than configured: a
|
|
8
|
+
* path an application could choose is a path it could collide with a route of its own.
|
|
9
|
+
*/
|
|
10
|
+
export const RPC = '/.rpc'
|
|
11
|
+
|
|
12
|
+
/** Calls one request may carry where the annotation does not say. */
|
|
13
|
+
export const BATCH = 32
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Where the Model Context Protocol is served. Pinned for the reason `/.rpc` is: a path an
|
|
17
|
+
* application could choose is a path it could collide with a route of its own.
|
|
18
|
+
*/
|
|
19
|
+
export const MCP = '/.mcp'
|
package/source/deployment.ts
CHANGED
|
@@ -70,6 +70,12 @@ export function deployment (_: unknown, annotation?: Annotation): Dependency {
|
|
|
70
70
|
if (annotation.oauth !== undefined)
|
|
71
71
|
properties.oauth = annotation.oauth
|
|
72
72
|
|
|
73
|
+
if (annotation.rpc !== undefined)
|
|
74
|
+
properties.rpc = annotation.rpc
|
|
75
|
+
|
|
76
|
+
if (annotation.mcp !== undefined)
|
|
77
|
+
properties.mcp = annotation.mcp
|
|
78
|
+
|
|
73
79
|
service.variables!.push({
|
|
74
80
|
name: 'TOA_EXPOSITION_PROPERTIES',
|
|
75
81
|
value: JSON.stringify(properties)
|
|
@@ -86,4 +92,5 @@ export function deployment (_: unknown, annotation?: Annotation): Dependency {
|
|
|
86
92
|
return { services: [service] }
|
|
87
93
|
}
|
|
88
94
|
|
|
89
|
-
type Properties = Pick<Annotation,
|
|
95
|
+
type Properties = Pick<Annotation,
|
|
96
|
+
'authorities' | 'debug' | 'protocol' | 'bouncer' | 'ip' | 'oauth' | 'rpc' | 'mcp'>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { Anonymous } from './Anonymous.js'
|
|
5
|
+
import type { Context } from './types.js'
|
|
6
|
+
|
|
7
|
+
const context = (headers: Record<string, string>, procedural = false): Context =>
|
|
8
|
+
({ request: { headers }, procedural }) as unknown as Context
|
|
9
|
+
|
|
10
|
+
describe('anonymous', () => {
|
|
11
|
+
it('should admit a request that presents nothing', () => {
|
|
12
|
+
assert.equal(new Anonymous(true).authorize(null, context({})), true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('should refuse a request that presents a credential', () => {
|
|
16
|
+
// it would make the reply uncacheable, which is the whole of the rule
|
|
17
|
+
assert.equal(new Anonymous(true).authorize(null, context({ authorization: 'Token x' })), false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should admit a procedure whatever the request presented', () => {
|
|
21
|
+
// what a procedure answers is a value in an envelope, and the envelope is `no-store`
|
|
22
|
+
const procedural = context({ authorization: 'Token x' }, true)
|
|
23
|
+
|
|
24
|
+
assert.equal(new Anonymous(true).authorize(null, procedural), true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should refuse where it admits nobody', () => {
|
|
28
|
+
assert.equal(new Anonymous(false).authorize(null, context({})), false)
|
|
29
|
+
assert.equal(new Anonymous(false).authorize(null, context({}, true)), false)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should describe a method as it authorizes one', () => {
|
|
33
|
+
const directive = new Anonymous(true)
|
|
34
|
+
|
|
35
|
+
assert.equal(directive.admits(null, context({ authorization: 'Token x' })), false)
|
|
36
|
+
assert.equal(directive.admits(null, context({ authorization: 'Token x' }, true)), true)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -7,9 +7,21 @@ export class Anonymous implements Directive {
|
|
|
7
7
|
this.allow = allow
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* A credential refuses, because it would make the reply uncacheable — which is the whole
|
|
12
|
+
* of the rule, and none of it applies to a procedure: what a procedure answers is a value
|
|
13
|
+
* in an envelope, and the envelope is the one thing that is cached or not.
|
|
14
|
+
*/
|
|
10
15
|
public authorize (_: any, context: Context): boolean {
|
|
16
|
+
if (context.procedural)
|
|
17
|
+
return this.allow
|
|
18
|
+
|
|
11
19
|
return 'authorization' in context.request.headers
|
|
12
20
|
? false
|
|
13
21
|
: this.allow
|
|
14
22
|
}
|
|
23
|
+
|
|
24
|
+
public admits (_: any, context: Context): boolean {
|
|
25
|
+
return this.authorize(_, context)
|
|
26
|
+
}
|
|
15
27
|
}
|
|
@@ -21,6 +21,7 @@ import { ATOM_GROUP } from '../../const.js'
|
|
|
21
21
|
import { Quotas, Sync } from '../io/lib/throttle/index.js'
|
|
22
22
|
import { Keys } from '../io/lib/throttle/Keys.js'
|
|
23
23
|
import type { Output } from '../../io.js'
|
|
24
|
+
import type { Introspection } from '../../Introspection.js'
|
|
24
25
|
import type { Component } from '@toa.io/core'
|
|
25
26
|
import type { Remotes } from '../../Remotes.js'
|
|
26
27
|
import type { Parameter, DirectiveFamily } from '../../RTD/index.js'
|
|
@@ -100,11 +101,18 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
100
101
|
directives.sort((a, b) => (a.priority ?? 1) - (b.priority ?? 1))
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Authentication: who the credential names, if one is presented. A credential belongs to
|
|
106
|
+
* the request, so it is read once however many calls the request carries.
|
|
107
|
+
*/
|
|
108
|
+
public async preflight (context: Context): Promise<void> {
|
|
106
109
|
context.identity = await this.resolve(context)
|
|
110
|
+
}
|
|
107
111
|
|
|
112
|
+
/** Authorization: whether that identity may make this call, which every call asks anew. */
|
|
113
|
+
public async precall (directives: Directive[],
|
|
114
|
+
context: Context,
|
|
115
|
+
parameters: Parameter[]): Promise<Output> {
|
|
108
116
|
for (const directive of directives) {
|
|
109
117
|
const allow = await directive.authorize(context.identity, context, parameters)
|
|
110
118
|
|
|
@@ -121,12 +129,63 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
121
129
|
throw new http.Forbidden()
|
|
122
130
|
}
|
|
123
131
|
|
|
132
|
+
/**
|
|
133
|
+
* The same disjunction as `precall`, over what can be told without a request. A method no
|
|
134
|
+
* directive admits, and none is undecided about, is not this caller's to be told about —
|
|
135
|
+
* `null` takes it out of the answer.
|
|
136
|
+
*
|
|
137
|
+
* A permission is matched against a path, and a description is not a request to one, so
|
|
138
|
+
* `permits` has no say here. The call it describes is still checked, which is where a
|
|
139
|
+
* token's permissions belong.
|
|
140
|
+
*
|
|
141
|
+
* A method that is described is then described by each of them, which is a separate pass:
|
|
142
|
+
* admission is a disjunction and stops at the first that admits, while what the directives
|
|
143
|
+
* fill is not any one of them's to state alone.
|
|
144
|
+
*/
|
|
145
|
+
public async explain (directives: Directive[], context: Context,
|
|
146
|
+
introspection: Introspection): Promise<Introspection | null> {
|
|
147
|
+
let untold = false
|
|
148
|
+
let admitted = false
|
|
149
|
+
|
|
150
|
+
for (const directive of directives) {
|
|
151
|
+
const admits = await directive.admits?.(context.identity, context)
|
|
152
|
+
|
|
153
|
+
if (admits === undefined) {
|
|
154
|
+
untold = true
|
|
155
|
+
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (admits) {
|
|
160
|
+
admitted = true
|
|
161
|
+
|
|
162
|
+
break
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!admitted && !untold)
|
|
167
|
+
return null
|
|
168
|
+
|
|
169
|
+
// whichever of them admitted, a property any of them fills from the identity is filled
|
|
170
|
+
// from the identity: what a caller sent there would be overwritten or forged
|
|
171
|
+
for (const directive of directives)
|
|
172
|
+
introspection = directive.describe?.(introspection) ?? introspection
|
|
173
|
+
|
|
174
|
+
return introspection
|
|
175
|
+
}
|
|
176
|
+
|
|
124
177
|
public async settle (directives: Directive[],
|
|
125
178
|
context: Context,
|
|
126
179
|
response: http.OutgoingMessage): Promise<void> {
|
|
127
180
|
await Promise.all(directives.map(async (directive) =>
|
|
128
181
|
directive.settle?.(context, response)))
|
|
182
|
+
}
|
|
129
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Re-issuing a credential, and refusing a ban, are the request's business: the header
|
|
186
|
+
* carries one token however many calls were made, and a ban refuses all of them.
|
|
187
|
+
*/
|
|
188
|
+
public async depart (context: Context, response: http.OutgoingMessage): Promise<void> {
|
|
130
189
|
const identity = context.identity
|
|
131
190
|
|
|
132
191
|
if (identity === null)
|