@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
package/source/MCP/tools.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import * as http from '../HTTP/index.js'
|
|
2
|
-
import { fork } from '../RPC/Context.js'
|
|
3
|
-
import { address, name, split } from '../RPC/names.js'
|
|
4
|
-
import { METHOD_NOT_FOUND, failure, refusal, response } from './errors.js'
|
|
5
|
-
import { annotations, input, output } from './schema.js'
|
|
6
|
-
import { FAMILY, MCP, type Tool as Declaration } from '../directives/mcp/index.js'
|
|
7
|
-
import { describing } from '../Introspection.js'
|
|
8
|
-
import { variables } from '../RTD/segment.js'
|
|
9
|
-
import type { Tree } from '../RTD/index.js'
|
|
10
|
-
import type { Params, Result, Tool } from './types.js'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Every method this caller may reach that is published as a tool, named as the procedure
|
|
14
|
-
* it is.
|
|
15
|
-
*
|
|
16
|
-
* A method is a tool where it says so with `mcp:tool`, and a default denies: a tree holds
|
|
17
|
-
* what an application serves, and most of it is machinery a model has no business reading.
|
|
18
|
-
* What a caller may then do with one is what `auth` says. The tree is walked once and each
|
|
19
|
-
* method describes itself, which is where that is decided and where `io` and `map` say what
|
|
20
|
-
* may be sent.
|
|
21
|
-
*
|
|
22
|
-
* Sorted, because the revision asks for an order a client can cache on.
|
|
23
|
-
*/
|
|
24
|
-
export async function list(tree: Tree, request: http.Context): Promise<Tool[]> {
|
|
25
|
-
const tools: Tool[] = []
|
|
26
|
-
|
|
27
|
-
/*
|
|
28
|
-
* A description, not the request asking. What refuses a credentialed request at an
|
|
29
|
-
* `anonymous` route does not refuse the call a tool makes, and a list that says otherwise
|
|
30
|
-
* disagrees with what `tools/call` then does.
|
|
31
|
-
*/
|
|
32
|
-
const context = describing(request)
|
|
33
|
-
|
|
34
|
-
for (const { segments, verb, method } of tree.walk()) {
|
|
35
|
-
if (!MCP.published(method.directives.declared<Declaration>(FAMILY))) continue
|
|
36
|
-
|
|
37
|
-
const named = name(segments, verb)
|
|
38
|
-
|
|
39
|
-
// a route a name cannot spell is a route nothing addresses, here or at `/.rpc`
|
|
40
|
-
if (named === null) continue
|
|
41
|
-
|
|
42
|
-
const params = variables(segments)
|
|
43
|
-
const introspection = await method.explain(context, params)
|
|
44
|
-
|
|
45
|
-
if (introspection === null) continue
|
|
46
|
-
|
|
47
|
-
const described = introspection.description
|
|
48
|
-
const schema = output(introspection)
|
|
49
|
-
const hints = annotations(verb)
|
|
50
|
-
|
|
51
|
-
// in the order the revision documents one, which is the order it is read in
|
|
52
|
-
const tool: Tool = {
|
|
53
|
-
name: named,
|
|
54
|
-
...(introspection.title === undefined ? {} : { title: introspection.title }),
|
|
55
|
-
...(described === undefined ? {} : { description: described }),
|
|
56
|
-
inputSchema: input(
|
|
57
|
-
introspection,
|
|
58
|
-
params.map((param) => param.name),
|
|
59
|
-
method.endpoint?.selection() ?? null
|
|
60
|
-
),
|
|
61
|
-
...(schema === undefined ? {} : { outputSchema: schema }),
|
|
62
|
-
...(hints === undefined ? {} : { annotations: hints })
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
tools.push(tool)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return tools.sort((one, other) => (one.name < other.name ? -1 : 1))
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* The call the tool is. Its arguments are the procedure's parameters, taken apart the way a
|
|
73
|
-
* request carries them, and what answers is the same `route` an ordinary request goes to.
|
|
74
|
-
*
|
|
75
|
-
* A name that is not a published tool is answered as no tool at all, whether or not a route
|
|
76
|
-
* would have taken it: what an application did not publish is not reachable here by guessing
|
|
77
|
-
* its name. What the caller may then do with one that is published is still `auth`'s to say.
|
|
78
|
-
*/
|
|
79
|
-
export async function call(scope: Scope, named: string, args: Params): Promise<Result> {
|
|
80
|
-
if (!published(scope.tree, named))
|
|
81
|
-
throw new http.NotFound(
|
|
82
|
-
response(
|
|
83
|
-
null,
|
|
84
|
-
failure(METHOD_NOT_FOUND, `'${named}' is not a tool this server publishes`)
|
|
85
|
-
)
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
const { path, verb, variables } = address(named, args)
|
|
89
|
-
const { query, input: body } = split(args, variables)
|
|
90
|
-
const clone = fork(scope.context, path, verb, query, body)
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
const message = await scope.route(clone)
|
|
94
|
-
|
|
95
|
-
// what `io:output` restricts, over this call's reply rather than the envelope
|
|
96
|
-
await http.shape(clone, message)
|
|
97
|
-
|
|
98
|
-
return result(message.body)
|
|
99
|
-
} catch (exception) {
|
|
100
|
-
/*
|
|
101
|
-
* What the route made of this call is a value a model reads and may correct itself by:
|
|
102
|
-
* an operation that refused, an argument `io:input` would not take, a record that is
|
|
103
|
-
* not there, an identity `auth` would not let it act on. A credential is none of those
|
|
104
|
-
* — that is the client's to fix and not the model's, so it is answered as it is — and
|
|
105
|
-
* neither is a fault of this server, which is a protocol error and stays one.
|
|
106
|
-
*/
|
|
107
|
-
if (
|
|
108
|
-
exception instanceof http.ClientError &&
|
|
109
|
-
!(exception instanceof http.Unauthorized)
|
|
110
|
-
)
|
|
111
|
-
return { content: [{ type: 'text', text: refusal(exception) }], isError: true }
|
|
112
|
-
|
|
113
|
-
throw exception
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Everything a call needs that is not the call: the request it is of, and what answers it. */
|
|
118
|
-
export interface Scope {
|
|
119
|
-
context: http.Context
|
|
120
|
-
route: http.Processor
|
|
121
|
-
tree: Tree
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Whether the tree publishes this name as a tool. What `auth` makes of the caller is not
|
|
126
|
-
* asked here — the declaration is the route's and does not vary by who is calling, and the
|
|
127
|
-
* call that follows is authorized as any request to that route is.
|
|
128
|
-
*/
|
|
129
|
-
function published(tree: Tree, named: string): boolean {
|
|
130
|
-
for (const { segments, verb, method } of tree.walk())
|
|
131
|
-
if (name(segments, verb) === named)
|
|
132
|
-
return MCP.published(method.directives.declared<Declaration>(FAMILY))
|
|
133
|
-
|
|
134
|
-
return false
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function result(body: unknown): Result {
|
|
138
|
-
if (body === undefined || body === null) return { content: [] }
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
content: [{ type: 'text', text: JSON.stringify(body) }],
|
|
142
|
-
structuredContent: body
|
|
143
|
-
}
|
|
144
|
-
}
|
package/source/MCP/types.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/** The revision this endpoint serves, where a request carries its own metadata. */
|
|
2
|
-
export const MODERN = '2026-07-28'
|
|
3
|
-
|
|
4
|
-
/** The newest revision reached by an `initialize` handshake, which is what clients still send. */
|
|
5
|
-
export const LEGACY = '2025-11-25'
|
|
6
|
-
|
|
7
|
-
export const VERSIONS = [MODERN, LEGACY]
|
|
8
|
-
|
|
9
|
-
/** The version every JSON-RPC message states, which is not the protocol's. */
|
|
10
|
-
export const JSONRPC = '2.0'
|
|
11
|
-
|
|
12
|
-
/** The prefix the revision reserves for itself in `_meta`. */
|
|
13
|
-
export const RESERVED = 'io.modelcontextprotocol/'
|
|
14
|
-
|
|
15
|
-
export const PROTOCOL_VERSION = RESERVED + 'protocolVersion'
|
|
16
|
-
export const CLIENT_CAPABILITIES = RESERVED + 'clientCapabilities'
|
|
17
|
-
export const SERVER_INFO = RESERVED + 'serverInfo'
|
|
18
|
-
|
|
19
|
-
export type Params = Record<string, unknown>
|
|
20
|
-
|
|
21
|
-
export interface Message {
|
|
22
|
-
jsonrpc: string
|
|
23
|
-
method: string
|
|
24
|
-
params?: Params
|
|
25
|
-
|
|
26
|
-
/** Absent makes this a notification, which is answered by not answering. */
|
|
27
|
-
id?: string | number
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface Failure {
|
|
31
|
-
code: number
|
|
32
|
-
message: string
|
|
33
|
-
data?: unknown
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface Response {
|
|
37
|
-
jsonrpc: string
|
|
38
|
-
id: string | number | null
|
|
39
|
-
result?: unknown
|
|
40
|
-
error?: Failure
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* How long a complete result may be held, and by whom. `private` is a result that is the
|
|
45
|
-
* caller's alone — a list `auth` filtered for their identity is not another caller's list.
|
|
46
|
-
*/
|
|
47
|
-
export interface Cache {
|
|
48
|
-
ttlMs: number
|
|
49
|
-
cacheScope: 'public' | 'private'
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** What a tool answers with: what a model reads, and the reply itself. */
|
|
53
|
-
export interface Result {
|
|
54
|
-
content: Content[]
|
|
55
|
-
structuredContent?: unknown
|
|
56
|
-
|
|
57
|
-
/** The operation refused, which is something a model can read and correct. */
|
|
58
|
-
isError?: boolean
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface Content {
|
|
62
|
-
type: 'text'
|
|
63
|
-
text: string
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface Tool {
|
|
67
|
-
name: string
|
|
68
|
-
|
|
69
|
-
/** what a person is shown where a client lists this tool; a name is an address */
|
|
70
|
-
title?: string
|
|
71
|
-
|
|
72
|
-
/** what the route states this method is */
|
|
73
|
-
description?: string
|
|
74
|
-
inputSchema: object
|
|
75
|
-
outputSchema?: object
|
|
76
|
-
annotations?: Annotations
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** What the verb says about the call, which the revision asks a client to treat as a hint. */
|
|
80
|
-
export interface Annotations {
|
|
81
|
-
readOnlyHint?: boolean
|
|
82
|
-
destructiveHint?: boolean
|
|
83
|
-
idempotentHint?: boolean
|
|
84
|
-
}
|
package/source/Mapping.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { type Parameter } from './RTD/index.js'
|
|
2
|
-
import { Query } from './Query.js'
|
|
3
|
-
import type { Introspection, Schema } from './Introspection.js'
|
|
4
|
-
import type { QueryString } from './Query.js'
|
|
5
|
-
import type * as http from './HTTP/index.js'
|
|
6
|
-
import type * as syntax from './RTD/syntax/index.js'
|
|
7
|
-
import type * as core from '@toa.io/core/types'
|
|
8
|
-
|
|
9
|
-
export abstract class Mapping {
|
|
10
|
-
protected readonly query: Query
|
|
11
|
-
public abstract readonly queryable: boolean
|
|
12
|
-
|
|
13
|
-
public constructor(query: Query) {
|
|
14
|
-
this.query = query
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public static create(query?: syntax.Query | null, paged?: boolean): Mapping {
|
|
18
|
-
const q = new Query(query!, paged)
|
|
19
|
-
|
|
20
|
-
return queryable(query) ? new QueryableMapping(q) : new InputMapping(q)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public explain(introspection: Introspection): Record<string, Schema> | null {
|
|
24
|
-
return this.query.explain(introspection)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** What picks the records a call is about; see `Query.selection`. */
|
|
28
|
-
public selection(): Record<string, Schema> | null {
|
|
29
|
-
return this.query.selection()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
protected assign(input: any, qs: QueryString): void {
|
|
33
|
-
if (qs.parameters !== null) {
|
|
34
|
-
if (typeof input !== 'object' || input === null)
|
|
35
|
-
throw new Error('Input must be an object to embed query parameters')
|
|
36
|
-
|
|
37
|
-
Object.assign(input, qs.parameters)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public abstract fit(
|
|
42
|
-
input: any,
|
|
43
|
-
query: http.Query,
|
|
44
|
-
parameters: Parameter[]
|
|
45
|
-
): core.Request
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
class QueryableMapping extends Mapping {
|
|
49
|
-
public override readonly queryable = true
|
|
50
|
-
|
|
51
|
-
public fit(input: any, query: http.Query, parameters: Parameter[]): core.Request {
|
|
52
|
-
const request: core.Request = {}
|
|
53
|
-
const qs = this.query.fit(query, parameters)
|
|
54
|
-
|
|
55
|
-
if (input === undefined && qs.parameters !== null) input = {}
|
|
56
|
-
|
|
57
|
-
this.assign(input, qs)
|
|
58
|
-
|
|
59
|
-
if (input !== undefined) request.input = input
|
|
60
|
-
|
|
61
|
-
if (qs.query !== null) request.query = qs.query
|
|
62
|
-
|
|
63
|
-
return request
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
class InputMapping extends Mapping {
|
|
68
|
-
public override readonly queryable = false
|
|
69
|
-
|
|
70
|
-
public fit(input: any, query: http.Query, parameters: Parameter[]): core.Request {
|
|
71
|
-
const request: core.Request = {}
|
|
72
|
-
const qs = this.query.fit(query, parameters)
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
input === undefined &&
|
|
76
|
-
(this.query.parameterized || parameters.length > 0 || qs.parameters !== null)
|
|
77
|
-
)
|
|
78
|
-
input = {}
|
|
79
|
-
|
|
80
|
-
if (parameters.length > 0) {
|
|
81
|
-
if (typeof input !== 'object' || input === null)
|
|
82
|
-
throw new Error('Input must be an object to embed parameters')
|
|
83
|
-
|
|
84
|
-
for (const parameter of parameters) input[parameter.name] = parameter.value
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
this.assign(input, qs)
|
|
88
|
-
|
|
89
|
-
if (input !== undefined) request.input = input
|
|
90
|
-
|
|
91
|
-
return request
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function queryable(query?: syntax.Query | null): boolean {
|
|
96
|
-
if (query === undefined || query === null) return false
|
|
97
|
-
|
|
98
|
-
const keys = Object.keys(query)
|
|
99
|
-
|
|
100
|
-
return !(keys.length === 1 && keys[0] === 'parameters')
|
|
101
|
-
}
|
package/source/Query.test.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { Query } from './Query.js'
|
|
5
|
-
import { type Parameter, type syntax } from './RTD/index.js'
|
|
6
|
-
|
|
7
|
-
it('should combine request criteria', async () => {
|
|
8
|
-
const query: syntax.Query = {
|
|
9
|
-
criteria: 'foo==1;',
|
|
10
|
-
omit: { range: [0, 1] },
|
|
11
|
-
limit: { range: [0, 1] }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const parameters: Parameter[] = [
|
|
15
|
-
{ name: 'bar', value: '2' },
|
|
16
|
-
{ name: 'baz', value: '3' }
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
const instance = new Query(query)
|
|
20
|
-
const result = instance.fit({ criteria: 'qux==4' }, parameters)
|
|
21
|
-
|
|
22
|
-
assert.deepStrictEqual(result.query!.criteria, '(bar=="2";baz=="3");(foo==1);(qux==4)')
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('should quote parameter values', async () => {
|
|
26
|
-
const query: syntax.Query = {
|
|
27
|
-
omit: { range: [0, 1] },
|
|
28
|
-
limit: { range: [0, 1] }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const parameters: Parameter[] = [{ name: 'user', value: 'me"),(user=="victim' }]
|
|
32
|
-
|
|
33
|
-
const instance = new Query(query)
|
|
34
|
-
const result = instance.fit({}, parameters)
|
|
35
|
-
|
|
36
|
-
assert.deepStrictEqual(result.query!.criteria, '(user=="me\\"),(user==\\"victim")')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should set id parameter as query.id', async () => {
|
|
40
|
-
const query: syntax.Query = {
|
|
41
|
-
omit: { range: [0, 1] },
|
|
42
|
-
limit: { range: [0, 1] }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const id = '87782631058445da81cb82f78b20c223'
|
|
46
|
-
|
|
47
|
-
const parameters: Parameter[] = [{ name: 'id', value: id }]
|
|
48
|
-
|
|
49
|
-
const instance = new Query(query)
|
|
50
|
-
const result = instance.fit({}, parameters)
|
|
51
|
-
|
|
52
|
-
assert.strictEqual(result.query!.criteria, undefined)
|
|
53
|
-
assert.deepStrictEqual(result.query!.id, id)
|
|
54
|
-
})
|
package/source/Query.ts
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { quote } from '@toa.io/generic'
|
|
3
|
-
import * as http from './HTTP/index.js'
|
|
4
|
-
import { type Parameter } from './RTD/index.js'
|
|
5
|
-
import { schemas } from '@toa.io/definitions/extensions.exposition'
|
|
6
|
-
import { queryable } from './Mapping.js'
|
|
7
|
-
import { take } from './Introspection.js'
|
|
8
|
-
import type { Introspection, Schema } from './Introspection.js'
|
|
9
|
-
import type * as syntax from './RTD/syntax/index.js'
|
|
10
|
-
import type * as core from '@toa.io/core/types'
|
|
11
|
-
|
|
12
|
-
export class Query {
|
|
13
|
-
public readonly parameterized: boolean
|
|
14
|
-
|
|
15
|
-
private readonly query: syntax.Query
|
|
16
|
-
private readonly closed: boolean = false
|
|
17
|
-
private readonly prepend: ',' | ';' = ';'
|
|
18
|
-
private readonly queryable: boolean
|
|
19
|
-
private readonly searchable: boolean
|
|
20
|
-
|
|
21
|
-
/** whether a page is taken of what this answers, and so whether `omit` and `limit` apply */
|
|
22
|
-
private readonly paged: boolean
|
|
23
|
-
|
|
24
|
-
public constructor(query: syntax.Query, paged = true) {
|
|
25
|
-
this.parameterized = query?.parameters !== undefined
|
|
26
|
-
this.queryable = queryable(query)
|
|
27
|
-
this.searchable = query?.search === true
|
|
28
|
-
this.paged = paged
|
|
29
|
-
|
|
30
|
-
if (this.queryable) {
|
|
31
|
-
if (this.paged) {
|
|
32
|
-
query.omit ??= { value: 0, range: [0, 1000] }
|
|
33
|
-
query.limit ??= { value: 10, range: [1, 100] }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (query.criteria !== undefined) {
|
|
37
|
-
// eslint-disable-next-line max-depth
|
|
38
|
-
if (query.criteria.endsWith(';')) query.criteria = query.criteria.slice(0, -1)
|
|
39
|
-
else this.closed = true
|
|
40
|
-
|
|
41
|
-
// eslint-disable-next-line max-depth
|
|
42
|
-
if (query.criteria.startsWith(',') || query.criteria.startsWith(';')) {
|
|
43
|
-
this.prepend = query.criteria[0] as ',' | ';'
|
|
44
|
-
|
|
45
|
-
query.criteria = query.criteria.slice(1)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.query = query
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public fit(query: http.Query, parameters: Parameter[]): QueryString {
|
|
54
|
-
const qs = this.split(query)
|
|
55
|
-
|
|
56
|
-
if (qs.query !== null) {
|
|
57
|
-
const error = schemas.querystring.fit(qs.query)
|
|
58
|
-
|
|
59
|
-
if (error !== null) throw new http.BadRequest('Query ' + error.message)
|
|
60
|
-
|
|
61
|
-
this.fitCriteria(qs.query, parameters)
|
|
62
|
-
|
|
63
|
-
if (this.paged) this.fitRanges(qs.query)
|
|
64
|
-
else this.refuseRanges(qs.query)
|
|
65
|
-
|
|
66
|
-
this.fitSort(qs.query)
|
|
67
|
-
|
|
68
|
-
if (this.query.deleted !== undefined)
|
|
69
|
-
(qs.query as core.Query).deleted = this.query.deleted
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
query: qs.query as core.Query,
|
|
74
|
-
parameters: qs.parameters
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* What the querystring carries: the parameters this method declares, taken out of the
|
|
80
|
-
* input because they are not the body's, and what a queryable method accepts besides.
|
|
81
|
-
*
|
|
82
|
-
* Only what it actually accepts — a criteria the declaration closes is refused, and so is
|
|
83
|
-
* a search where none was asked for.
|
|
84
|
-
*/
|
|
85
|
-
/**
|
|
86
|
-
* The querystring parameters this resource declares, which are properties of its own
|
|
87
|
-
* taken out of the input. What selects records is not among them: that is the same of
|
|
88
|
-
* every queryable resource, and `selection` is where it is stated.
|
|
89
|
-
*/
|
|
90
|
-
public explain(introspection: Introspection): Record<string, Schema> | null {
|
|
91
|
-
let query: Record<string, Schema> | null = null
|
|
92
|
-
|
|
93
|
-
if (this.query?.parameters !== undefined)
|
|
94
|
-
for (const parameter of this.query.parameters) {
|
|
95
|
-
const schema = take(introspection, parameter)
|
|
96
|
-
|
|
97
|
-
// eslint-disable-next-line max-depth
|
|
98
|
-
if (schema === undefined) continue
|
|
99
|
-
|
|
100
|
-
query ??= {}
|
|
101
|
-
query[parameter] = schema
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return query
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* What picks the records a call is about, which is the querystring the gateway reads
|
|
109
|
-
* rather than anything the resource declares — the same for every queryable resource,
|
|
110
|
-
* and so not what one says about itself. A procedure states it, because there it is
|
|
111
|
-
* something the caller sends.
|
|
112
|
-
*/
|
|
113
|
-
public selection(): Record<string, Schema> | null {
|
|
114
|
-
if (!this.queryable) return null
|
|
115
|
-
|
|
116
|
-
const query: Record<string, Schema> = {}
|
|
117
|
-
|
|
118
|
-
if (!this.closed)
|
|
119
|
-
query.criteria = keyword(
|
|
120
|
-
'string',
|
|
121
|
-
'What to match, in RSQL: `state==hot`, `rank=gt=5;name==*tea*`.'
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
query.sort = keyword(
|
|
125
|
-
'string',
|
|
126
|
-
'What to order by: `rank:desc`, or `rank` for ascending.'
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
if (this.paged) {
|
|
130
|
-
query.limit = bounded('How many at once.', this.query.limit!)
|
|
131
|
-
query.omit = bounded('How many to skip.', this.query.omit!)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (this.searchable)
|
|
135
|
-
query.search = keyword('string', 'What to search the text index for.')
|
|
136
|
-
|
|
137
|
-
return query
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private split(query: http.Query): {
|
|
141
|
-
query: http.Query | null
|
|
142
|
-
parameters: Record<string, string> | null
|
|
143
|
-
} {
|
|
144
|
-
let parameters: Record<string, string> | null = null
|
|
145
|
-
|
|
146
|
-
if (this.query?.parameters !== undefined)
|
|
147
|
-
for (const key in query)
|
|
148
|
-
// eslint-disable-next-line max-depth
|
|
149
|
-
if (this.query.parameters.includes(key)) {
|
|
150
|
-
parameters ??= {}
|
|
151
|
-
parameters[key] = query[key] as string
|
|
152
|
-
|
|
153
|
-
delete query[key]
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (!this.queryable) {
|
|
157
|
-
const keys = Object.keys(query)
|
|
158
|
-
|
|
159
|
-
if (keys.length > 0)
|
|
160
|
-
throw new http.BadRequest(`Query parameter '${keys[0]}' is not allowed`)
|
|
161
|
-
|
|
162
|
-
query = null!
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (query?.search !== undefined && !this.searchable)
|
|
166
|
-
throw new http.BadRequest('Query search is not allowed')
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
query,
|
|
170
|
-
parameters
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
private fitCriteria(query: http.Query, parameters: Parameter[]): void {
|
|
175
|
-
const groups: CriteriaGroup[] = []
|
|
176
|
-
const idx = parameters.findIndex((parameter) => parameter.name === 'id')
|
|
177
|
-
|
|
178
|
-
if (idx !== -1) {
|
|
179
|
-
query.id = parameters[idx].value
|
|
180
|
-
|
|
181
|
-
parameters.splice(idx, 1)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (parameters.length > 0) {
|
|
185
|
-
// a segment may carry `,` `;` `(` `)` `=`, which is criteria grammar when unquoted
|
|
186
|
-
const criteria = parameters
|
|
187
|
-
.map(({ name, value }) => `${name}==${quote(value)}`)
|
|
188
|
-
.join(';')
|
|
189
|
-
|
|
190
|
-
groups.push({ criteria, operator: this.prepend })
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (this.query.criteria !== undefined)
|
|
194
|
-
groups.push({ criteria: this.query.criteria, operator: ';' })
|
|
195
|
-
|
|
196
|
-
if (query.criteria !== undefined)
|
|
197
|
-
if (this.closed) throw new http.BadRequest('Query criteria is closed')
|
|
198
|
-
else groups.push({ criteria: query.criteria, operator: WHATEVER })
|
|
199
|
-
|
|
200
|
-
if (groups.length > 0)
|
|
201
|
-
query.criteria = groups.reduce((acc, { criteria, operator }, i) => {
|
|
202
|
-
return i === groups.length - 1
|
|
203
|
-
? `${acc}(${criteria})`
|
|
204
|
-
: `${acc}(${criteria})${operator}`
|
|
205
|
-
}, '')
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** A route that answers one object is not paged, so a request that pages it is a mistake. */
|
|
209
|
-
private refuseRanges(qs: http.Query): void {
|
|
210
|
-
for (const name of ['omit', 'limit'] as const)
|
|
211
|
-
if (qs[name] !== undefined)
|
|
212
|
-
throw new http.BadRequest(`Query ${name} is not allowed`)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private fitRanges(qs: http.Query): void {
|
|
216
|
-
const query = qs as core.Query
|
|
217
|
-
|
|
218
|
-
assert.ok(this.query.limit !== undefined, 'Query limit must be defined')
|
|
219
|
-
assert.ok(this.query.omit !== undefined, 'Query limit range must be defined')
|
|
220
|
-
|
|
221
|
-
if (qs.limit !== undefined)
|
|
222
|
-
query.limit = fit(qs.limit, this.query.limit.range, 'limit')
|
|
223
|
-
else query.limit = this.query.limit.value
|
|
224
|
-
|
|
225
|
-
if (qs.omit !== undefined) query.omit = fit(qs.omit, this.query.omit.range, 'omit')
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private fitSort(qs: http.Query): void {
|
|
229
|
-
const query = qs as core.Query
|
|
230
|
-
|
|
231
|
-
if (qs.sort === undefined && this.query.sort === undefined) return
|
|
232
|
-
|
|
233
|
-
const sort = (this.query.sort ?? '') + (qs.sort ?? '')
|
|
234
|
-
|
|
235
|
-
query.sort = sort.split(';')
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function fit(string: string, range: [number, number], name: string): number {
|
|
240
|
-
const number = parseInt(string)
|
|
241
|
-
|
|
242
|
-
if (number < range[0] || number > range[1])
|
|
243
|
-
throw new http.BadRequest(
|
|
244
|
-
`Query ${name} must be between ${range[0]} and ${range[1]} inclusive`
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
return number
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const WHATEVER = ';'
|
|
251
|
-
|
|
252
|
-
interface CriteriaGroup {
|
|
253
|
-
criteria: string
|
|
254
|
-
operator: ',' | ';'
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function keyword(type: string, description: string): Schema {
|
|
258
|
-
return { type, description } as unknown as Schema
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function bounded(description: string, bounds: syntax.Range): Schema {
|
|
262
|
-
const schema: Record<string, unknown> = {
|
|
263
|
-
type: 'integer',
|
|
264
|
-
description,
|
|
265
|
-
minimum: bounds.range[0],
|
|
266
|
-
maximum: bounds.range[1]
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (bounds.value !== undefined) schema.default = bounds.value
|
|
270
|
-
|
|
271
|
-
return schema as unknown as Schema
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export interface QueryString {
|
|
275
|
-
query: core.Query | null
|
|
276
|
-
parameters: Record<string, string> | null
|
|
277
|
-
}
|