@toa.io/extensions.exposition 1.0.0-alpha.292 → 1.0.0-alpha.294
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/BVDJTrf4.js +3 -0
- package/ui/dist/_app/immutable/chunks/{aLpTDmOc.js → CEe-wL8u.js} +1 -1
- package/ui/dist/_app/immutable/chunks/CV9soJ0B.js +6 -0
- package/ui/dist/_app/immutable/chunks/Im4_dtgC.js +1 -0
- package/ui/dist/_app/immutable/chunks/UkDaEvqJ.js +86 -0
- package/ui/dist/_app/immutable/entry/app.BnWlwGtD.js +2 -0
- package/ui/dist/_app/immutable/entry/start.Cm--Gj58.js +1 -0
- package/ui/dist/_app/immutable/nodes/0.z7Qg-vYh.js +1 -0
- package/ui/dist/_app/immutable/nodes/1.DtKiO-Oq.js +1 -0
- package/ui/dist/_app/immutable/nodes/2.B8zoEhQx.js +8 -0
- package/ui/dist/_app/immutable/nodes/3.eHKOcSZr.js +1 -0
- package/ui/dist/_app/immutable/nodes/4.CXvilufZ.js +1 -0
- package/ui/dist/_app/immutable/nodes/5.CTa_nmvd.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/Directive.test.ts
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { describe, it, beforeEach, mock } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { generate } from 'randomstring'
|
|
5
|
-
import { DirectivesFactory } from './Directive.js'
|
|
6
|
-
import type { syntax, DirectiveFamily } from './RTD/index.js'
|
|
7
|
-
import type { Remotes } from './Remotes.js'
|
|
8
|
-
import type { Host } from './Factory.js'
|
|
9
|
-
import type { Context } from './HTTP/index.js'
|
|
10
|
-
|
|
11
|
-
const sequence: string[] = []
|
|
12
|
-
|
|
13
|
-
const families: Array<DirectiveFamily> = [
|
|
14
|
-
{
|
|
15
|
-
name: 'foo',
|
|
16
|
-
mandatory: true,
|
|
17
|
-
create: mock.fn((_0: any, _1: any, _2: any) => generate() as any),
|
|
18
|
-
arrange: mock.fn(),
|
|
19
|
-
precall: mock.fn(() => {
|
|
20
|
-
sequence.push('foo')
|
|
21
|
-
return null
|
|
22
|
-
}),
|
|
23
|
-
settle: mock.fn(),
|
|
24
|
-
dispose: mock.fn()
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: 'qux',
|
|
28
|
-
mandatory: true,
|
|
29
|
-
create: mock.fn((_0: any, _1: any, _2: any) => generate() as any),
|
|
30
|
-
arrange: mock.fn(),
|
|
31
|
-
precall: mock.fn(() => {
|
|
32
|
-
sequence.push('qux')
|
|
33
|
-
return null
|
|
34
|
-
}),
|
|
35
|
-
settle: mock.fn(),
|
|
36
|
-
dispose: mock.fn()
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: 'bar',
|
|
40
|
-
mandatory: false,
|
|
41
|
-
create: mock.fn((_0: string, _1: any, _2: any) => generate() as any),
|
|
42
|
-
arrange: mock.fn(),
|
|
43
|
-
precall: mock.fn(() => {
|
|
44
|
-
sequence.push('bar')
|
|
45
|
-
return null
|
|
46
|
-
}),
|
|
47
|
-
settle: mock.fn(),
|
|
48
|
-
dispose: mock.fn()
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
|
|
52
|
-
let factory: DirectivesFactory
|
|
53
|
-
|
|
54
|
-
beforeEach(() => {
|
|
55
|
-
resetCalls()
|
|
56
|
-
sequence.length = 0
|
|
57
|
-
|
|
58
|
-
for (const family of families) {
|
|
59
|
-
assert.ok(family.precall !== undefined)
|
|
60
|
-
|
|
61
|
-
family.precall.mock.mockImplementation(() => {
|
|
62
|
-
sequence.push(family.name)
|
|
63
|
-
return null
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
factory = new DirectivesFactory(
|
|
68
|
-
families,
|
|
69
|
-
{} as unknown as Remotes,
|
|
70
|
-
{} as unknown as Host,
|
|
71
|
-
{ authorities: {} }
|
|
72
|
-
)
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('should create directive', async () => {
|
|
76
|
-
const declarations: syntax.Directive[] = [
|
|
77
|
-
{
|
|
78
|
-
family: 'foo',
|
|
79
|
-
name: generate(),
|
|
80
|
-
value: generate()
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
family: 'bar',
|
|
84
|
-
name: generate(),
|
|
85
|
-
value: generate()
|
|
86
|
-
}
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
factory.create(declarations)
|
|
90
|
-
|
|
91
|
-
for (const declaration of declarations) {
|
|
92
|
-
const family = families.find(({ name }) => name === declaration.family)!
|
|
93
|
-
|
|
94
|
-
assert.strictEqual(family.create.mock.calls[0].arguments[0], declaration.name)
|
|
95
|
-
assert.strictEqual(family.create.mock.calls[0].arguments[1], declaration.value)
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('should pass the route to the families', async () => {
|
|
100
|
-
const route = '/' + generate()
|
|
101
|
-
|
|
102
|
-
factory.create([{ family: 'foo', name: generate(), value: generate() }], route)
|
|
103
|
-
|
|
104
|
-
assert.strictEqual(families[0].create.mock.calls[0].arguments[3], route)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('should throw error if directive family is not found', async () => {
|
|
108
|
-
const declaration: syntax.Directive = {
|
|
109
|
-
family: generate(),
|
|
110
|
-
name: generate(),
|
|
111
|
-
value: generate()
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
assert.throws(
|
|
115
|
-
() => factory.create([declaration]),
|
|
116
|
-
(error: Error) =>
|
|
117
|
-
error.message.includes(`Directive family '${declaration.family}' is not found`)
|
|
118
|
-
)
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('should apply directive', async () => {
|
|
122
|
-
const declaration: syntax.Directive = {
|
|
123
|
-
family: 'foo',
|
|
124
|
-
name: generate(),
|
|
125
|
-
value: generate()
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const directives = factory.create([declaration])
|
|
129
|
-
const request = generate() as unknown as Context
|
|
130
|
-
const directive = families[0].create.mock.calls[0].result
|
|
131
|
-
|
|
132
|
-
await directives.precall(request, [])
|
|
133
|
-
|
|
134
|
-
assert.ok(families[0].precall !== undefined)
|
|
135
|
-
|
|
136
|
-
assert.deepStrictEqual(families[0].precall.mock.calls[0].arguments[0], [directive])
|
|
137
|
-
assert.deepStrictEqual(families[0].precall.mock.calls[0].arguments[1], request)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('should apply mandatory families', async () => {
|
|
141
|
-
const directives = factory.create([])
|
|
142
|
-
const request = generate() as unknown as Context
|
|
143
|
-
|
|
144
|
-
await directives.precall(request, [])
|
|
145
|
-
|
|
146
|
-
assert.ok(families[0].precall.mock.callCount() > 0)
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
describe('order', () => {
|
|
150
|
-
// the order the families actually ran, as each precall recorded it
|
|
151
|
-
function order(): string[] {
|
|
152
|
-
return sequence
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
it('should run mandatory families in their own order, whatever a manifest says', async () => {
|
|
156
|
-
// `qux` declared first, but `foo` is registered first and both are mandatory
|
|
157
|
-
const directives = factory.create([
|
|
158
|
-
{ family: 'qux', name: generate(), value: generate() },
|
|
159
|
-
{ family: 'foo', name: generate(), value: generate() }
|
|
160
|
-
])
|
|
161
|
-
|
|
162
|
-
await directives.precall(generate() as unknown as Context, [])
|
|
163
|
-
|
|
164
|
-
assert.deepStrictEqual(order(), ['foo', 'qux'])
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
it('should run a mandatory family before a declared one it is not declared with', async () => {
|
|
168
|
-
// only `qux` is declared: `foo` still has to run first, not merely first of
|
|
169
|
-
// whatever had no declarations
|
|
170
|
-
const directives = factory.create([
|
|
171
|
-
{ family: 'qux', name: generate(), value: generate() }
|
|
172
|
-
])
|
|
173
|
-
|
|
174
|
-
await directives.precall(generate() as unknown as Context, [])
|
|
175
|
-
|
|
176
|
-
assert.deepStrictEqual(order(), ['foo', 'qux'])
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
it('should run mandatory families before the rest', async () => {
|
|
180
|
-
const directives = factory.create([
|
|
181
|
-
{ family: 'bar', name: generate(), value: generate() },
|
|
182
|
-
{ family: 'qux', name: generate(), value: generate() }
|
|
183
|
-
])
|
|
184
|
-
|
|
185
|
-
await directives.precall(generate() as unknown as Context, [])
|
|
186
|
-
|
|
187
|
-
assert.deepStrictEqual(order(), ['foo', 'qux', 'bar'])
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
function resetCalls(target = [families], seen = new Set()) {
|
|
192
|
-
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
193
|
-
|
|
194
|
-
seen.add(target)
|
|
195
|
-
|
|
196
|
-
for (const value of Object.values(target))
|
|
197
|
-
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
198
|
-
else resetCalls(value, seen)
|
|
199
|
-
}
|
package/source/Directive.ts
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { console, type SpanOptions } from 'openspan'
|
|
2
|
-
import type { Context, OutgoingMessage, Options } from './HTTP/index.js'
|
|
3
|
-
import type { Remotes } from './Remotes.js'
|
|
4
|
-
import type { Host } from './Factory.js'
|
|
5
|
-
import type { Output } from './io.js'
|
|
6
|
-
import type { Introspection } from './Introspection.js'
|
|
7
|
-
import type * as RTD from './RTD/index.js'
|
|
8
|
-
|
|
9
|
-
export class Directives implements RTD.Directives {
|
|
10
|
-
private readonly sets: RTD.DirectiveSet[]
|
|
11
|
-
|
|
12
|
-
/** the span of a stage depends only on the set, so it is built once per route */
|
|
13
|
-
private readonly spans: Spans[]
|
|
14
|
-
|
|
15
|
-
public constructor(sets: RTD.DirectiveSet[]) {
|
|
16
|
-
this.sets = sets
|
|
17
|
-
this.spans = sets.map((set) => ({
|
|
18
|
-
precall: options(set, 'precall'),
|
|
19
|
-
settle: options(set, 'settle'),
|
|
20
|
-
explain: options(set, 'explain')
|
|
21
|
-
}))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public declared<T>(family: string): T[] | undefined {
|
|
25
|
-
return this.sets.find((set) => set.family.name === family)?.directives as
|
|
26
|
-
| T[]
|
|
27
|
-
| undefined
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async precall(context: Context, parameters: RTD.Parameter[]): Promise<Output> {
|
|
31
|
-
let output = null
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < this.sets.length; i++) {
|
|
34
|
-
const set = this.sets[i]
|
|
35
|
-
|
|
36
|
-
if (set.family.precall === undefined) continue
|
|
37
|
-
|
|
38
|
-
const out = await console.span(
|
|
39
|
-
this.spans[i].precall,
|
|
40
|
-
async () => await set.family.precall!(set.directives, context, parameters)
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
if (out === null) continue
|
|
44
|
-
|
|
45
|
-
if (output !== null) throw new Error('Multiple precall directives responded')
|
|
46
|
-
else output = out
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return output
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* What the method says about itself, as its directives leave it. Each family is given
|
|
54
|
-
* what the one before it returned, and the first to refuse ends it: a method this caller
|
|
55
|
-
* cannot reach is not described at all.
|
|
56
|
-
*/
|
|
57
|
-
public async explain(
|
|
58
|
-
context: Context,
|
|
59
|
-
introspection: Introspection
|
|
60
|
-
): Promise<Introspection | null> {
|
|
61
|
-
let described: Introspection = introspection
|
|
62
|
-
|
|
63
|
-
for (let i = 0; i < this.sets.length; i++) {
|
|
64
|
-
const set = this.sets[i]
|
|
65
|
-
|
|
66
|
-
if (set.family.explain === undefined) continue
|
|
67
|
-
|
|
68
|
-
const next = await console.span(
|
|
69
|
-
this.spans[i].explain,
|
|
70
|
-
async () => await set.family.explain!(set.directives, context, described)
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
if (next === null) return null
|
|
74
|
-
|
|
75
|
-
described = next
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return described
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public async settle(context: Context, response: OutgoingMessage): Promise<void> {
|
|
82
|
-
for (let i = 0; i < this.sets.length; i++) {
|
|
83
|
-
const set = this.sets[i]
|
|
84
|
-
|
|
85
|
-
if (set.family.settle !== undefined)
|
|
86
|
-
await console.span(
|
|
87
|
-
this.spans[i].settle,
|
|
88
|
-
async () => await set.family.settle!(set.directives, context, response)
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public dispose(): void {
|
|
94
|
-
for (const set of this.sets) set.family.dispose?.(set.directives)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export class DirectivesFactory implements RTD.DirectiveFactory {
|
|
99
|
-
private readonly remotes: Remotes
|
|
100
|
-
private readonly families: Record<string, RTD.DirectiveFamily> = {}
|
|
101
|
-
private readonly mandatory: string[] = []
|
|
102
|
-
private readonly instances: Directives[] = []
|
|
103
|
-
|
|
104
|
-
/** The request-scoped stages, in registration order, with the spans they run in. */
|
|
105
|
-
private readonly stages: Stage[] = []
|
|
106
|
-
|
|
107
|
-
// eslint-disable-next-line max-params
|
|
108
|
-
public constructor(
|
|
109
|
-
families: RTD.DirectiveFamily[],
|
|
110
|
-
remotes: Remotes,
|
|
111
|
-
host: Host,
|
|
112
|
-
options: Options
|
|
113
|
-
) {
|
|
114
|
-
for (const family of families) {
|
|
115
|
-
family.mount?.(host, options)
|
|
116
|
-
this.families[family.name] = family
|
|
117
|
-
|
|
118
|
-
if (family.mandatory) this.mandatory.push(family.name)
|
|
119
|
-
|
|
120
|
-
this.stages.push({
|
|
121
|
-
family,
|
|
122
|
-
preflight: { name: `${family.name} preflight` },
|
|
123
|
-
depart: { name: `${family.name} depart` }
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
this.remotes = remotes
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Request-scoped, before anything is routed, so no directives are passed: a family
|
|
132
|
-
* answers here only for what it does on its own behalf.
|
|
133
|
-
*/
|
|
134
|
-
public async preflight(context: Context): Promise<void> {
|
|
135
|
-
for (const stage of this.stages)
|
|
136
|
-
if (stage.family.preflight !== undefined)
|
|
137
|
-
await console.span(stage.preflight, async () => {
|
|
138
|
-
await stage.family.preflight!(context)
|
|
139
|
-
})
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/** Request-scoped, on the message going back. */
|
|
143
|
-
public async depart(context: Context, response: OutgoingMessage): Promise<void> {
|
|
144
|
-
for (const stage of this.stages)
|
|
145
|
-
if (stage.family.depart !== undefined)
|
|
146
|
-
await console.span(stage.depart, async () => {
|
|
147
|
-
await stage.family.depart!(context, response)
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
public create(declarations: RTD.syntax.Directive[], route: string = ''): Directives {
|
|
152
|
-
const groups: Record<string, any> = {}
|
|
153
|
-
const mandatory = new Set(this.mandatory)
|
|
154
|
-
|
|
155
|
-
const names: Record<string, string[]> = {}
|
|
156
|
-
|
|
157
|
-
for (const declaration of declarations) {
|
|
158
|
-
const family = this.families[declaration.family]
|
|
159
|
-
|
|
160
|
-
if (family === undefined)
|
|
161
|
-
throw new Error(`Directive family '${declaration.family}' is not found`)
|
|
162
|
-
|
|
163
|
-
const directive = family.create(
|
|
164
|
-
declaration.name,
|
|
165
|
-
declaration.value,
|
|
166
|
-
this.remotes,
|
|
167
|
-
route
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
groups[family.name] ??= []
|
|
171
|
-
groups[family.name].push(directive)
|
|
172
|
-
names[family.name] ??= []
|
|
173
|
-
names[family.name].push(`${declaration.family}:${declaration.name}`)
|
|
174
|
-
mandatory.delete(family.name)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const sets: RTD.DirectiveSet[] = []
|
|
178
|
-
|
|
179
|
-
for (const family of mandatory)
|
|
180
|
-
sets.push({
|
|
181
|
-
family: this.families[family],
|
|
182
|
-
directives: [],
|
|
183
|
-
names: []
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
for (const [family, directives] of Object.entries(groups))
|
|
187
|
-
sets.push({
|
|
188
|
-
family: this.families[family],
|
|
189
|
-
directives,
|
|
190
|
-
names: names[family]
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
// Mandatory families run in the order they are registered in, not in the order a
|
|
194
|
-
// manifest happens to mention them: `auth` must resolve the identity before `io`
|
|
195
|
-
// can key a quota on it, and a request it denies should not reach `io` at all.
|
|
196
|
-
// The rest keep the order they were declared in, the sort being stable.
|
|
197
|
-
sets.sort((a, b) => this.rank(a.family.name) - this.rank(b.family.name))
|
|
198
|
-
|
|
199
|
-
// whatever order a family needs among its own directives is fixed here, not per request
|
|
200
|
-
for (const set of sets) set.family.arrange?.(set.directives)
|
|
201
|
-
|
|
202
|
-
const directives = new Directives(sets)
|
|
203
|
-
|
|
204
|
-
this.instances.push(directives)
|
|
205
|
-
|
|
206
|
-
return directives
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
public inheritable(directive: RTD.syntax.Directive): boolean {
|
|
210
|
-
return this.families[directive.family]?.inherited !== false
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
public dispose(): void {
|
|
214
|
-
for (const directives of this.instances) directives.dispose()
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/** Mandatory families first, in their own order; everything else keeps its own. */
|
|
218
|
-
private rank(family: string): number {
|
|
219
|
-
const index = this.mandatory.indexOf(family)
|
|
220
|
-
|
|
221
|
-
return index === -1 ? this.mandatory.length : index
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function options(
|
|
226
|
-
set: RTD.DirectiveSet,
|
|
227
|
-
stage: 'precall' | 'settle' | 'explain'
|
|
228
|
-
): SpanOptions {
|
|
229
|
-
const options: SpanOptions = { name: `${set.family.name} ${stage}` }
|
|
230
|
-
|
|
231
|
-
if (set.names !== undefined && set.names.length > 0)
|
|
232
|
-
options.attributes = { directives: Array.from(new Set(set.names)).join(' ') }
|
|
233
|
-
|
|
234
|
-
return options
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
interface Spans {
|
|
238
|
-
precall: SpanOptions
|
|
239
|
-
settle: SpanOptions
|
|
240
|
-
explain: SpanOptions
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
interface Stage {
|
|
244
|
-
family: RTD.DirectiveFamily
|
|
245
|
-
preflight: SpanOptions
|
|
246
|
-
depart: SpanOptions
|
|
247
|
-
}
|
|
248
|
-
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import * as http from '../HTTP/index.js'
|
|
2
|
-
import { BRANCH_TTL } from '@toa.io/definitions/extensions.exposition'
|
|
3
|
-
import { describe } from './tree.js'
|
|
4
|
-
import type { Tree } from '../RTD/index.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* What an application serves, for every route at once. Each entry is what `OPTIONS` on that
|
|
8
|
-
* path answers, so a key taken from here is a request that can be made.
|
|
9
|
-
*/
|
|
10
|
-
export class Explorer {
|
|
11
|
-
private readonly tree: Tree
|
|
12
|
-
|
|
13
|
-
public constructor(tree: Tree) {
|
|
14
|
-
this.tree = tree
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public async process(context: http.Context): Promise<http.OutgoingMessage> {
|
|
18
|
-
if (context.request.method !== 'OPTIONS')
|
|
19
|
-
throw new http.MethodNotAllowed(new Headers({ allow: ALLOW }))
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
body: await describe(this.tree, context),
|
|
23
|
-
headers: new Headers({
|
|
24
|
-
allow: ALLOW,
|
|
25
|
-
// it stands until a branch expires, and it is filtered by who asked
|
|
26
|
-
'cache-control': `private, max-age=${BRANCH_TTL / 1000}`,
|
|
27
|
-
vary: 'authorization'
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** The verbs of this path, which are not the verbs of the tree it answers with. */
|
|
34
|
-
const ALLOW = 'GET, HEAD, OPTIONS'
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { Readable } from 'node:stream'
|
|
4
|
-
import * as path from 'node:path'
|
|
5
|
-
import * as fs from 'node:fs'
|
|
6
|
-
import * as os from 'node:os'
|
|
7
|
-
|
|
8
|
-
import { Site } from './Site.js'
|
|
9
|
-
import * as http from '../HTTP/index.js'
|
|
10
|
-
import type { Input, Output } from '../io.js'
|
|
11
|
-
|
|
12
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'discovery-'))
|
|
13
|
-
|
|
14
|
-
fs.mkdirSync(path.join(root, '_app', 'immutable'), { recursive: true })
|
|
15
|
-
fs.writeFileSync(path.join(root, 'index.html'), 'the page\n')
|
|
16
|
-
fs.writeFileSync(path.join(root, 'favicon.ico'), 'icon')
|
|
17
|
-
fs.writeFileSync(path.join(root, '_app', 'immutable', 'asset.js'), 'export {}\n')
|
|
18
|
-
|
|
19
|
-
const empty = fs.mkdtempSync(path.join(os.tmpdir(), 'discovery-empty-'))
|
|
20
|
-
|
|
21
|
-
const site = new Site(root)
|
|
22
|
-
|
|
23
|
-
const input = (url: string, method = 'GET'): Input =>
|
|
24
|
-
({
|
|
25
|
-
request: { method, headers: {} },
|
|
26
|
-
url: new URL(url, 'http://nex.toa.io')
|
|
27
|
-
}) as unknown as Input
|
|
28
|
-
|
|
29
|
-
const header = (output: Output, name: string): string | null =>
|
|
30
|
-
output?.headers?.get(name) ?? null
|
|
31
|
-
|
|
32
|
-
describe('discovery site', () => {
|
|
33
|
-
it('should leave a path outside its prefix alone', () => {
|
|
34
|
-
assert.equal(site.intercept(input('/')), null)
|
|
35
|
-
assert.equal(site.intercept(input('/pots/')), null)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should not claim a path that merely starts like its own', () => {
|
|
39
|
-
assert.equal(site.intercept(input('/.discoveryable/')), null)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should send the bare path to the directory it is', () => {
|
|
43
|
-
const output = site.intercept(input('/.discovery'))
|
|
44
|
-
|
|
45
|
-
assert.equal(output?.status, 302)
|
|
46
|
-
assert.equal(header(output, 'location'), '/.discovery/')
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('should keep the query when it redirects', () => {
|
|
50
|
-
const output = site.intercept(input('/.discovery?at=/pots'))
|
|
51
|
-
|
|
52
|
-
assert.equal(header(output, 'location'), '/.discovery/?at=/pots')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should serve the page', () => {
|
|
56
|
-
const output = site.intercept(input('/.discovery/'))
|
|
57
|
-
|
|
58
|
-
assert.equal(output?.status, 200)
|
|
59
|
-
assert.equal(header(output, 'content-type'), 'text/html; charset=utf-8')
|
|
60
|
-
assert.equal(header(output, 'cache-control'), 'no-cache')
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('should always carry a content-type and a stream', () => {
|
|
64
|
-
// a stream without one is framed as `multipart/*`, and the page arrives as an envelope
|
|
65
|
-
for (const url of ['/.discovery/', '/.discovery/_app/immutable/asset.js']) {
|
|
66
|
-
const output = site.intercept(input(url))
|
|
67
|
-
|
|
68
|
-
assert.ok(output?.headers?.has('content-type'), url)
|
|
69
|
-
assert.ok(output?.body instanceof Readable, url)
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('should hold a hashed asset forever and an icon for a day', () => {
|
|
74
|
-
assert.equal(
|
|
75
|
-
header(site.intercept(input('/.discovery/_app/immutable/asset.js')), 'cache-control'),
|
|
76
|
-
'public, max-age=31536000, immutable'
|
|
77
|
-
)
|
|
78
|
-
assert.equal(
|
|
79
|
-
header(site.intercept(input('/.discovery/favicon.ico')), 'cache-control'),
|
|
80
|
-
'public, max-age=86400'
|
|
81
|
-
)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should fall back to the page for anything that could be a route', () => {
|
|
85
|
-
const output = site.intercept(input('/.discovery/pots/:id'))
|
|
86
|
-
|
|
87
|
-
assert.equal(header(output, 'content-type'), 'text/html; charset=utf-8')
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it('should refuse an asset that is not there', () => {
|
|
91
|
-
// a missing asset is missing, however much a route can look like one
|
|
92
|
-
assert.throws(
|
|
93
|
-
() => site.intercept(input('/.discovery/_app/immutable/gone.js')),
|
|
94
|
-
http.NotFound
|
|
95
|
-
)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('should refuse a path that climbs out of the root', () => {
|
|
99
|
-
/*
|
|
100
|
-
* An encoded separator is what reaches here: `..` and `%2e%2e` are dot segments and the
|
|
101
|
-
* URL parser has already collapsed them, but `%2f` keeps a segment whole through it and
|
|
102
|
-
* decodes to one afterwards.
|
|
103
|
-
*/
|
|
104
|
-
for (const url of [
|
|
105
|
-
'/.discovery/%2f%2e%2e%2f%2e%2e%2fpackage.json',
|
|
106
|
-
'/.discovery/a%2f..%2f..%2fpackage.json',
|
|
107
|
-
'/.discovery/%2e%2e%2fpackage.json'
|
|
108
|
-
])
|
|
109
|
-
assert.throws(() => site.intercept(input(url)), http.NotFound, url)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('should never see a dot segment, which the URL parser collapses first', () => {
|
|
113
|
-
// `/.discovery/%2e%2e/x` is `/x`, which is not this prefix and not ours to answer
|
|
114
|
-
assert.equal(site.intercept(input('/.discovery/%2e%2e/%2e%2e/package.json')), null)
|
|
115
|
-
assert.equal(site.intercept(input('/.discovery/../../package.json')), null)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('should report the length a GET would have returned, and open no stream', () => {
|
|
119
|
-
const output = site.intercept(input('/.discovery/', 'HEAD'))
|
|
120
|
-
|
|
121
|
-
assert.equal(output?.status, 200)
|
|
122
|
-
assert.equal(header(output, 'content-length'), '9')
|
|
123
|
-
assert.equal(output?.body, undefined)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
it('should leave OPTIONS on the prefix to the tree', () => {
|
|
127
|
-
// it needs the identity, which is resolved after this stage
|
|
128
|
-
assert.equal(site.intercept(input('/.discovery', 'OPTIONS')), null)
|
|
129
|
-
assert.equal(site.intercept(input('/.discovery/', 'OPTIONS')), null)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('should refuse every other method', () => {
|
|
133
|
-
assert.throws(() => site.intercept(input('/.discovery/', 'POST')), http.MethodNotAllowed)
|
|
134
|
-
assert.throws(
|
|
135
|
-
() => site.intercept(input('/.discovery/favicon.ico', 'OPTIONS')),
|
|
136
|
-
http.MethodNotAllowed
|
|
137
|
-
)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('should say so where the page is not built', () => {
|
|
141
|
-
const output = new Site(empty).intercept(input('/.discovery/'))
|
|
142
|
-
|
|
143
|
-
assert.equal(output?.status, 503)
|
|
144
|
-
assert.equal(header(output, 'content-type'), 'text/plain; charset=utf-8')
|
|
145
|
-
assert.ok(output?.body instanceof Readable)
|
|
146
|
-
})
|
|
147
|
-
})
|