@toa.io/extensions.exposition 1.0.0-alpha.7 → 1.0.0-alpha.73
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/context.toa.yaml +2 -2
- package/components/identity.bans/manifest.toa.yaml +15 -7
- package/components/identity.bans/operations/transit.d.ts +14 -0
- package/components/identity.bans/operations/transit.js +11 -0
- package/components/identity.bans/operations/transit.js.map +1 -0
- package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.bans/source/transit.ts +21 -0
- package/components/identity.bans/tsconfig.json +9 -0
- package/components/identity.basic/manifest.toa.yaml +21 -10
- package/components/identity.basic/operations/authenticate.d.ts +5 -1
- package/components/identity.basic/operations/authenticate.js +5 -2
- package/components/identity.basic/operations/authenticate.js.map +1 -1
- package/components/identity.basic/operations/incept.d.ts +12 -0
- package/components/identity.basic/operations/incept.js +26 -0
- package/components/identity.basic/operations/incept.js.map +1 -0
- package/components/identity.basic/operations/transit.d.ts +4 -4
- package/components/identity.basic/operations/transit.js +5 -3
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +8 -4
- package/components/identity.basic/source/authenticate.ts +16 -5
- package/components/identity.basic/source/incept.ts +38 -0
- package/components/identity.basic/source/transit.ts +8 -6
- package/components/identity.basic/source/types.ts +8 -4
- package/components/identity.federation/manifest.toa.yaml +32 -16
- package/components/identity.federation/operations/authenticate.d.ts +2 -2
- package/components/identity.federation/operations/authenticate.js +4 -11
- package/components/identity.federation/operations/authenticate.js.map +1 -1
- package/components/identity.federation/operations/incept.d.ts +11 -0
- package/components/identity.federation/operations/{create.js → incept.js} +6 -7
- package/components/identity.federation/operations/incept.js.map +1 -0
- package/components/identity.federation/operations/lib/assertions-as-values.js +2 -1
- package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -1
- package/components/identity.federation/operations/lib/jwt.d.ts +5 -5
- package/components/identity.federation/operations/lib/jwt.js +25 -12
- package/components/identity.federation/operations/lib/jwt.js.map +1 -1
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +14 -0
- package/components/identity.federation/operations/types/configuration.js +3 -0
- package/components/identity.federation/operations/types/configuration.js.map +1 -0
- package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +15 -7
- package/components/identity.federation/operations/types/context.js +3 -0
- package/components/identity.federation/operations/types/context.js.map +1 -0
- package/components/identity.federation/operations/types/entity.d.ts +6 -0
- package/components/identity.federation/operations/types/entity.js +3 -0
- package/components/identity.federation/operations/types/entity.js.map +1 -0
- package/components/identity.federation/operations/types/index.d.ts +3 -0
- package/components/identity.federation/operations/types/index.js +20 -0
- package/components/identity.federation/operations/types/index.js.map +1 -0
- package/components/identity.federation/source/authenticate.ts +6 -19
- package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
- package/components/identity.federation/source/lib/assertions-as-values.ts +4 -2
- package/components/identity.federation/source/lib/jwt.test.ts +123 -4
- package/components/identity.federation/source/lib/jwt.ts +36 -16
- package/components/identity.federation/source/types/configuration.ts +15 -0
- package/components/identity.federation/source/{types.ts → types/context.ts} +17 -6
- package/components/identity.federation/source/types/entity.ts +6 -0
- package/components/identity.federation/source/types/index.ts +3 -0
- package/components/identity.federation/tsconfig.json +5 -4
- package/components/identity.roles/manifest.toa.yaml +18 -7
- package/components/identity.roles/operations/grant.d.ts +10 -0
- package/components/identity.roles/operations/grant.js +21 -0
- package/components/identity.roles/operations/grant.js.map +1 -0
- package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
- package/components/identity.roles/operations/lib/Entity.js +3 -0
- package/components/identity.roles/operations/lib/Entity.js.map +1 -0
- package/components/identity.roles/operations/list.d.ts +1 -4
- package/components/identity.roles/operations/list.js.map +1 -1
- package/components/identity.roles/operations/principal.d.ts +4 -6
- package/components/identity.roles/operations/principal.js +6 -1
- package/components/identity.roles/operations/principal.js.map +1 -1
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/source/grant.ts +32 -0
- package/components/identity.roles/source/lib/Entity.ts +5 -0
- package/components/identity.roles/source/list.ts +2 -4
- package/components/identity.roles/source/principal.ts +10 -8
- package/components/identity.tokens/manifest.toa.yaml +19 -5
- package/components/identity.tokens/operations/authenticate.d.ts +2 -2
- package/components/identity.tokens/operations/authenticate.js +12 -5
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.js +1 -0
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.js +5 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/operations/types.d.ts +8 -2
- package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
- package/components/identity.tokens/source/authenticate.test.ts +11 -4
- package/components/identity.tokens/source/authenticate.ts +14 -6
- package/components/identity.tokens/source/decrypt.test.ts +5 -3
- package/components/identity.tokens/source/decrypt.ts +9 -8
- package/components/identity.tokens/source/encrypt.test.ts +26 -2
- package/components/identity.tokens/source/encrypt.ts +5 -1
- package/components/identity.tokens/source/types.ts +9 -2
- package/components/octets.storage/manifest.toa.yaml +6 -7
- package/components/octets.storage/operations/get.js +2 -2
- package/components/octets.storage/operations/store.js +113 -3
- package/documentation/access.md +75 -38
- package/documentation/authorities.md +49 -0
- package/documentation/cache.md +8 -1
- package/documentation/components.md +47 -22
- package/documentation/flow.md +31 -0
- package/documentation/identity.md +17 -22
- package/documentation/introspection.md +82 -0
- package/documentation/octets.md +81 -23
- package/documentation/protocol.md +13 -3
- package/documentation/query.md +29 -4
- package/documentation/require.md +15 -0
- package/documentation/tree.md +13 -0
- package/documentation/vary.md +14 -14
- package/features/access.feature +78 -46
- package/features/annotation.feature +1 -0
- package/features/auth.claim.feature +170 -0
- package/features/authorities.basic.feature +141 -0
- package/features/authorities.feature +32 -0
- package/features/authorities.federation.feature +100 -0
- package/features/authorities.tokens.feature +117 -0
- package/features/body.feature +3 -0
- package/features/cache.feature +109 -5
- package/features/cors.feature +6 -1
- package/features/debug.feature +34 -0
- package/features/directives.feature +3 -0
- package/features/dynamic.feature +48 -0
- package/features/errors.feature +20 -7
- package/features/etag.feature +31 -0
- package/features/flow.feature +45 -0
- package/features/identity.bans.feature +137 -0
- package/features/identity.basic.feature +125 -23
- package/features/identity.feature +7 -2
- package/features/identity.federation.feature +66 -11
- package/features/identity.roles.feature +250 -7
- package/features/identity.tokens.feature +54 -4
- package/features/introspection.feature +153 -0
- package/features/io.feature +38 -1
- package/features/methods.feature +47 -0
- package/features/octets.download.feature +189 -0
- package/features/octets.entries.feature +8 -1
- package/features/octets.feature +82 -54
- package/features/octets.meta.feature +3 -0
- package/features/octets.workflows.feature +239 -19
- package/features/probes.feature +14 -0
- package/features/{queries.feature → query.feature} +65 -2
- package/features/realtime.feature +34 -0
- package/features/require.feature +67 -0
- package/features/response.feature +38 -3
- package/features/routes.feature +93 -2
- package/features/steps/Database.ts +17 -10
- package/features/steps/Gateway.ts +23 -6
- package/features/steps/IdP.ts +30 -25
- package/features/steps/Parameters.ts +4 -1
- package/features/steps/Realtime.ts +151 -0
- package/features/steps/components/echo/manifest.toa.yaml +14 -1
- package/features/steps/components/echo/operations/identity.js +7 -0
- package/features/steps/components/echo/operations/parameters.js +7 -0
- package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
- package/features/steps/components/echo.beacon/operations/hello.js +5 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +22 -1
- package/features/steps/components/octets.tester/operations/authority.js +7 -0
- package/features/steps/components/octets.tester/operations/baz.js +1 -2
- package/features/steps/components/octets.tester/operations/diversify.js +3 -1
- package/features/steps/components/octets.tester/operations/foo.js +2 -2
- package/features/steps/components/octets.tester/operations/redirect.js +12 -0
- package/features/steps/components/octets.tester/operations/yex.js +16 -0
- package/features/steps/components/octets.tester/operations/yield.js +13 -0
- package/features/steps/components/pots/manifest.toa.yaml +14 -3
- package/features/steps/components/users/manifest.toa.yaml +0 -1
- package/features/steps/components/users.properties/manifest.toa.yaml +1 -1
- package/features/streams.feature +5 -0
- package/features/timing.feature +4 -1
- package/features/vary.feature +71 -0
- package/package.json +23 -14
- package/readme.md +19 -14
- package/schemas/annotation.cos.yaml +1 -1
- package/schemas/method.cos.yaml +1 -1
- package/schemas/node.cos.yaml +2 -0
- package/schemas/octets/store.cos.yaml +25 -3
- package/schemas/query.cos.yaml +4 -10
- package/source/Annotation.ts +3 -3
- package/source/Branch.ts +1 -0
- package/source/Composition.ts +0 -6
- package/source/Context.ts +1 -0
- package/source/Directive.ts +4 -5
- package/source/Endpoint.ts +55 -15
- package/source/Factory.ts +22 -13
- package/source/Gateway.ts +67 -19
- package/source/HTTP/Context.ts +25 -2
- package/source/HTTP/Server.ts +52 -44
- package/source/HTTP/exceptions.ts +13 -1
- package/source/HTTP/formats/index.ts +3 -3
- package/source/HTTP/messages.test.ts +45 -2
- package/source/HTTP/messages.ts +23 -5
- package/source/Introspection.ts +11 -0
- package/source/Mapping.ts +63 -21
- package/source/Query.test.ts +3 -3
- package/source/Query.ts +117 -33
- package/source/RTD/Context.ts +1 -1
- package/source/RTD/Endpoint.ts +3 -0
- package/source/RTD/Method.ts +16 -0
- package/source/RTD/Node.ts +29 -13
- package/source/RTD/Route.ts +5 -4
- package/source/RTD/Tree.ts +2 -2
- package/source/RTD/factory.ts +5 -2
- package/source/RTD/syntax/parse.ts +37 -24
- package/source/RTD/syntax/types.ts +6 -4
- package/source/Remotes.ts +7 -6
- package/source/Tenant.ts +6 -20
- package/source/deployment.ts +33 -23
- package/source/directives/auth/Authorization.ts +37 -14
- package/source/directives/auth/Delegate.ts +42 -0
- package/source/directives/auth/Federation.ts +84 -0
- package/source/directives/auth/Incept.ts +4 -3
- package/source/directives/auth/Role.test.ts +53 -6
- package/source/directives/auth/Role.ts +22 -14
- package/source/directives/auth/split.ts +1 -1
- package/source/directives/auth/types.ts +1 -1
- package/source/directives/cache/Cache.ts +13 -6
- package/source/directives/cache/Control.ts +42 -16
- package/source/directives/cors/CORS.ts +1 -1
- package/source/directives/dev/Development.ts +1 -1
- package/source/directives/flow/Fetch.ts +88 -0
- package/source/directives/flow/Flow.ts +34 -0
- package/source/directives/flow/index.ts +3 -0
- package/source/directives/flow/types.ts +6 -0
- package/source/directives/index.ts +3 -1
- package/source/directives/io/Input.ts +4 -4
- package/source/directives/io/Output.ts +4 -3
- package/source/directives/octets/Context.ts +3 -2
- package/source/directives/octets/Fetch.ts +11 -10
- package/source/directives/octets/List.ts +5 -5
- package/source/directives/octets/Octets.ts +1 -3
- package/source/directives/octets/Store.ts +30 -10
- package/source/directives/octets/bytes.test.ts +30 -0
- package/source/directives/octets/bytes.ts +18 -0
- package/source/directives/octets/schemas.ts +4 -6
- package/source/directives/octets/workflows/Execution.ts +60 -8
- package/source/directives/octets/workflows/Workflow.ts +2 -1
- package/source/directives/require/Directive.ts +5 -0
- package/source/directives/require/Headers.ts +20 -0
- package/source/directives/require/Require.ts +28 -0
- package/source/directives/require/index.ts +3 -0
- package/source/directives/vary/Directive.ts +2 -1
- package/source/directives/vary/Embed.ts +14 -8
- package/source/directives/vary/Vary.ts +6 -4
- package/source/directives/vary/embeddings/Authority.ts +8 -0
- package/source/directives/vary/embeddings/Embedding.ts +2 -1
- package/source/directives/vary/embeddings/Parameter.ts +14 -0
- package/source/directives/vary/embeddings/index.ts +6 -4
- package/source/exceptions.ts +23 -11
- package/source/manifest.ts +10 -11
- package/source/schemas.ts +1 -1
- package/transpiled/Annotation.d.ts +3 -3
- package/transpiled/Branch.d.ts +1 -0
- package/transpiled/Composition.d.ts +0 -1
- package/transpiled/Composition.js +0 -4
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Context.d.ts +1 -0
- package/transpiled/Directive.js +4 -4
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +6 -4
- package/transpiled/Endpoint.js +35 -7
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.d.ts +3 -2
- package/transpiled/Factory.js +18 -10
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +3 -0
- package/transpiled/Gateway.js +51 -12
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +8 -1
- package/transpiled/HTTP/Context.js +16 -2
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +13 -2
- package/transpiled/HTTP/Server.js +39 -36
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/exceptions.d.ts +7 -1
- package/transpiled/HTTP/exceptions.js +13 -1
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/HTTP/formats/index.js +3 -3
- package/transpiled/HTTP/formats/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +1 -0
- package/transpiled/HTTP/messages.js +24 -5
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Introspection.d.ts +9 -0
- package/transpiled/Introspection.js +3 -0
- package/transpiled/Introspection.js.map +1 -0
- package/transpiled/Mapping.d.ts +10 -2
- package/transpiled/Mapping.js +48 -19
- package/transpiled/Mapping.js.map +1 -1
- package/transpiled/Query.d.ts +10 -1
- package/transpiled/Query.js +83 -30
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Context.d.ts +1 -1
- package/transpiled/RTD/Endpoint.d.ts +1 -0
- package/transpiled/RTD/Method.d.ts +4 -0
- package/transpiled/RTD/Method.js +11 -0
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.d.ts +4 -1
- package/transpiled/RTD/Node.js +23 -12
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.d.ts +1 -1
- package/transpiled/RTD/Route.js +0 -1
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/Tree.d.ts +1 -1
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/RTD/factory.js +5 -2
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/RTD/syntax/parse.js +34 -22
- package/transpiled/RTD/syntax/parse.js.map +1 -1
- package/transpiled/RTD/syntax/types.d.ts +5 -3
- package/transpiled/RTD/syntax/types.js +1 -1
- package/transpiled/RTD/syntax/types.js.map +1 -1
- package/transpiled/Remotes.d.ts +4 -4
- package/transpiled/Remotes.js +6 -5
- package/transpiled/Remotes.js.map +1 -1
- package/transpiled/Tenant.d.ts +5 -5
- package/transpiled/Tenant.js +2 -13
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/deployment.d.ts +1 -1
- package/transpiled/deployment.js +28 -20
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +26 -10
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.d.ts +10 -0
- package/transpiled/directives/auth/Delegate.js +34 -0
- package/transpiled/directives/auth/Delegate.js.map +1 -0
- package/transpiled/directives/auth/Federation.d.ts +16 -0
- package/transpiled/directives/auth/Federation.js +57 -0
- package/transpiled/directives/auth/Federation.js.map +1 -0
- package/transpiled/directives/auth/Incept.js +4 -3
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Role.d.ts +4 -1
- package/transpiled/directives/auth/Role.js +20 -14
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/split.js +1 -1
- package/transpiled/directives/auth/split.js.map +1 -1
- package/transpiled/directives/cache/Cache.d.ts +3 -3
- package/transpiled/directives/cache/Cache.js +10 -4
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.d.ts +2 -1
- package/transpiled/directives/cache/Control.js +29 -12
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/cors/CORS.js +1 -1
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/dev/Development.js +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/flow/Fetch.d.ts +13 -0
- package/transpiled/directives/flow/Fetch.js +59 -0
- package/transpiled/directives/flow/Fetch.js.map +1 -0
- package/transpiled/directives/flow/Flow.d.ts +10 -0
- package/transpiled/directives/flow/Flow.js +27 -0
- package/transpiled/directives/flow/Flow.js.map +1 -0
- package/transpiled/directives/flow/index.d.ts +2 -0
- package/transpiled/directives/flow/index.js +6 -0
- package/transpiled/directives/flow/index.js.map +1 -0
- package/transpiled/directives/flow/types.d.ts +5 -0
- package/transpiled/directives/flow/types.js.map +1 -0
- package/transpiled/directives/index.js +3 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/Input.js +2 -2
- package/transpiled/directives/io/Input.js.map +1 -1
- package/transpiled/directives/io/Output.js +2 -2
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/octets/Context.js +4 -24
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Fetch.d.ts +3 -3
- package/transpiled/directives/octets/Fetch.js +8 -8
- package/transpiled/directives/octets/Fetch.js.map +1 -1
- package/transpiled/directives/octets/List.d.ts +3 -3
- package/transpiled/directives/octets/List.js +3 -3
- package/transpiled/directives/octets/List.js.map +1 -1
- package/transpiled/directives/octets/Octets.js +1 -3
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Store.d.ts +6 -1
- package/transpiled/directives/octets/Store.js +17 -7
- package/transpiled/directives/octets/Store.js.map +1 -1
- package/transpiled/directives/octets/bytes.d.ts +1 -0
- package/transpiled/directives/octets/bytes.js +21 -0
- package/transpiled/directives/octets/bytes.js.map +1 -0
- package/transpiled/directives/octets/schemas.d.ts +4 -6
- package/transpiled/directives/octets/schemas.js +1 -3
- package/transpiled/directives/octets/schemas.js.map +1 -1
- package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
- package/transpiled/directives/octets/workflows/Execution.js +44 -9
- package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
- package/transpiled/directives/octets/workflows/Workflow.js +2 -1
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
- package/transpiled/directives/require/Directive.d.ts +4 -0
- package/transpiled/directives/require/Directive.js +3 -0
- package/transpiled/directives/require/Directive.js.map +1 -0
- package/transpiled/directives/require/Headers.d.ts +7 -0
- package/transpiled/directives/require/Headers.js +19 -0
- package/transpiled/directives/require/Headers.js.map +1 -0
- package/transpiled/directives/require/Require.d.ts +9 -0
- package/transpiled/directives/require/Require.js +27 -0
- package/transpiled/directives/require/Require.js.map +1 -0
- package/transpiled/directives/require/index.d.ts +2 -0
- package/transpiled/directives/require/index.js +6 -0
- package/transpiled/directives/require/index.js.map +1 -0
- package/transpiled/directives/vary/Directive.d.ts +2 -1
- package/transpiled/directives/vary/Embed.d.ts +2 -1
- package/transpiled/directives/vary/Embed.js +8 -6
- package/transpiled/directives/vary/Embed.js.map +1 -1
- package/transpiled/directives/vary/Vary.d.ts +2 -2
- package/transpiled/directives/vary/Vary.js +3 -3
- package/transpiled/directives/vary/Vary.js.map +1 -1
- package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
- package/transpiled/directives/vary/embeddings/Authority.js +10 -0
- package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
- package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
- package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
- package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
- package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
- package/transpiled/directives/vary/embeddings/index.js +8 -4
- package/transpiled/directives/vary/embeddings/index.js.map +1 -1
- package/transpiled/exceptions.d.ts +3 -2
- package/transpiled/exceptions.js +14 -7
- package/transpiled/exceptions.js.map +1 -1
- package/transpiled/manifest.js +10 -11
- package/transpiled/manifest.js.map +1 -1
- package/transpiled/schemas.d.ts +1 -1
- package/transpiled/schemas.js +2 -2
- package/transpiled/schemas.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
- package/tsconfig.json +9 -7
- package/components/identity.basic/operations/create.d.ts +0 -10
- package/components/identity.basic/operations/create.js +0 -10
- package/components/identity.basic/operations/create.js.map +0 -1
- package/components/identity.basic/source/create.ts +0 -18
- package/components/identity.federation/operations/create.d.ts +0 -10
- package/components/identity.federation/operations/create.js.map +0 -1
- package/components/identity.federation/operations/schemas.d.ts +0 -59
- package/components/identity.federation/operations/schemas.js +0 -9
- package/components/identity.federation/operations/schemas.js.map +0 -1
- package/components/identity.federation/operations/types.js.map +0 -1
- package/components/identity.federation/source/schemas.ts +0 -61
- package/components/octets.storage/operations/permute.js +0 -7
- package/schemas/octets/context.cos.yaml +0 -1
- package/source/HTTP/Server.test.ts +0 -126
- package/source/directives/octets/Permute.ts +0 -44
- package/transpiled/directives/octets/Permute.d.ts +0 -11
- package/transpiled/directives/octets/Permute.js +0 -58
- package/transpiled/directives/octets/Permute.js.map +0 -1
- /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
package/source/Endpoint.ts
CHANGED
|
@@ -1,34 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Remotes } from './Remotes'
|
|
1
|
+
import { console } from 'openspan'
|
|
3
2
|
import { Mapping } from './Mapping'
|
|
4
|
-
import { type Context } from './Context'
|
|
5
3
|
import * as http from './HTTP'
|
|
4
|
+
import type { Introspection, Schema } from './Introspection'
|
|
5
|
+
import type { Remote } from '@toa.io/core'
|
|
6
|
+
import type { Remotes } from './Remotes'
|
|
7
|
+
import type { Context } from './Context'
|
|
6
8
|
import type * as RTD from './RTD'
|
|
7
9
|
|
|
8
10
|
export class Endpoint implements RTD.Endpoint {
|
|
9
11
|
private readonly endpoint: string
|
|
10
12
|
private readonly mapping: Mapping
|
|
11
|
-
private readonly discovery: Promise<
|
|
12
|
-
private remote:
|
|
13
|
+
private readonly discovery: Promise<Remote>
|
|
14
|
+
private remote: Remote | null = null
|
|
13
15
|
|
|
14
|
-
public constructor (endpoint: string, mapping: Mapping, discovery: Promise<
|
|
16
|
+
public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Remote>) {
|
|
15
17
|
this.endpoint = endpoint
|
|
16
18
|
this.mapping = mapping
|
|
17
19
|
this.discovery = discovery
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
public async call
|
|
21
|
-
(context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
|
|
22
|
+
public async call (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
|
|
22
23
|
const body = await context.body()
|
|
23
24
|
const query = this.query(context)
|
|
24
25
|
const request = this.mapping.fit(body, query, parameters)
|
|
25
26
|
|
|
26
27
|
this.remote ??= await this.discovery
|
|
27
28
|
|
|
29
|
+
if (context.debug)
|
|
30
|
+
console.debug('Calling operation', {
|
|
31
|
+
endpoint: this.remote.locator.id + '.' + this.endpoint,
|
|
32
|
+
request
|
|
33
|
+
})
|
|
34
|
+
|
|
28
35
|
const reply = await this.remote.invoke(this.endpoint, request)
|
|
29
36
|
|
|
30
37
|
if (reply instanceof Error)
|
|
31
|
-
throw new http.
|
|
38
|
+
throw new http.UnprocessableEntity(reply)
|
|
32
39
|
|
|
33
40
|
const message: http.OutgoingMessage = {}
|
|
34
41
|
|
|
@@ -42,10 +49,8 @@ export class Endpoint implements RTD.Endpoint {
|
|
|
42
49
|
message.headers.set('etag', etag)
|
|
43
50
|
|
|
44
51
|
return message
|
|
45
|
-
} else
|
|
52
|
+
} else
|
|
46
53
|
message.headers.set('etag', `"${reply._version.toString()}"`)
|
|
47
|
-
delete reply._version
|
|
48
|
-
}
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
message.body = reply
|
|
@@ -53,6 +58,41 @@ export class Endpoint implements RTD.Endpoint {
|
|
|
53
58
|
return message
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
public async explain (parameters: RTD.Parameter[]): Promise<Introspection> {
|
|
62
|
+
this.remote ??= await this.discovery
|
|
63
|
+
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
65
|
+
const operation = await this.remote.explain(this.endpoint)
|
|
66
|
+
|
|
67
|
+
let route: Record<string, Schema> | null = null
|
|
68
|
+
|
|
69
|
+
if (operation.input?.type === 'object')
|
|
70
|
+
for (const parameter of parameters) {
|
|
71
|
+
const schema = operation.input.properties[parameter.name]
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line max-depth
|
|
74
|
+
if (schema !== undefined) {
|
|
75
|
+
route ??= {}
|
|
76
|
+
route[parameter.name] = schema
|
|
77
|
+
|
|
78
|
+
delete operation.input.properties[parameter.name]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const query = this.mapping.explain(operation)
|
|
83
|
+
const introspection: Introspection = {}
|
|
84
|
+
|
|
85
|
+
if (route !== null)
|
|
86
|
+
introspection.route = route
|
|
87
|
+
|
|
88
|
+
if (query !== null)
|
|
89
|
+
introspection.query = query
|
|
90
|
+
|
|
91
|
+
Object.assign(introspection, operation)
|
|
92
|
+
|
|
93
|
+
return introspection
|
|
94
|
+
}
|
|
95
|
+
|
|
56
96
|
public async close (): Promise<void> {
|
|
57
97
|
this.remote ??= await this.discovery
|
|
58
98
|
|
|
@@ -91,13 +131,13 @@ export class EndpointsFactory implements RTD.EndpointsFactory {
|
|
|
91
131
|
throw new Error('Cannot create Endpoint without mapping.')
|
|
92
132
|
|
|
93
133
|
const mapping = Mapping.create(method.mapping.query)
|
|
94
|
-
const namespace = method.mapping.namespace ?? context.extension
|
|
95
|
-
const component = method.mapping.component ?? context.extension
|
|
134
|
+
const namespace = method.mapping.namespace ?? context.extension.namespace
|
|
135
|
+
const component = method.mapping.component ?? context.extension.component
|
|
96
136
|
|
|
97
137
|
if (namespace === undefined || component === undefined)
|
|
98
138
|
throw new Error('Annotation endpoints must be fully qualified.')
|
|
99
139
|
|
|
100
|
-
const discovery = this.remotes.discover(namespace, component)
|
|
140
|
+
const discovery = this.remotes.discover(namespace, component, context.extension.version)
|
|
101
141
|
|
|
102
142
|
return new Endpoint(method.mapping.endpoint, mapping, discovery)
|
|
103
143
|
}
|
package/source/Factory.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { decode } from '@toa.io/generic'
|
|
1
3
|
import { Tenant } from './Tenant'
|
|
2
4
|
import { Gateway } from './Gateway'
|
|
3
5
|
import { Remotes } from './Remotes'
|
|
4
|
-
import { Tree
|
|
5
|
-
import { Server } from './HTTP'
|
|
6
|
+
import { Tree } from './RTD'
|
|
6
7
|
import { EndpointsFactory } from './Endpoint'
|
|
7
8
|
import { families, interceptors } from './directives'
|
|
8
9
|
import { DirectivesFactory } from './Directive'
|
|
9
10
|
import { Composition } from './Composition'
|
|
10
11
|
import * as root from './root'
|
|
11
12
|
import { Interception } from './Interception'
|
|
13
|
+
import * as http from './HTTP'
|
|
14
|
+
import type { Manifest } from '@toa.io/norm'
|
|
15
|
+
import type { Branch } from './Branch'
|
|
16
|
+
import type { syntax } from './RTD'
|
|
12
17
|
import type { Broadcast } from './Gateway'
|
|
13
18
|
import type { Connector, Locator, extensions } from '@toa.io/core'
|
|
14
19
|
|
|
@@ -19,23 +24,27 @@ export class Factory implements extensions.Factory {
|
|
|
19
24
|
this.boot = boot
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
public tenant (locator: Locator, node: syntax.Node): Connector {
|
|
27
|
+
public tenant (locator: Locator, node: syntax.Node, manifest: Manifest): Connector {
|
|
23
28
|
const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL, locator.id)
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
const branch: Branch = {
|
|
31
|
+
namespace: locator.namespace,
|
|
32
|
+
component: locator.name,
|
|
33
|
+
isolated: locator.namespace === 'identity',
|
|
34
|
+
node,
|
|
35
|
+
version: manifest.version
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return new Tenant(broadcast, branch)
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
public service (): Connector | null {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
|
|
32
|
-
|
|
33
|
-
const server = Server.create({
|
|
34
|
-
methods: syntax.verbs,
|
|
35
|
-
debug,
|
|
36
|
-
trace
|
|
37
|
-
})
|
|
42
|
+
assert.ok(process.env.TOA_EXPOSITION_PROPERTIES,
|
|
43
|
+
'TOA_EXPOSITION_PROPERTIES is undefined')
|
|
38
44
|
|
|
45
|
+
const options = decode<http.Options>(process.env.TOA_EXPOSITION_PROPERTIES)
|
|
46
|
+
const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
|
|
47
|
+
const server = http.Server.create({ ...options })
|
|
39
48
|
const remotes = new Remotes(this.boot)
|
|
40
49
|
const node = root.resolve()
|
|
41
50
|
const methods = new EndpointsFactory(remotes)
|
package/source/Gateway.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { console } from 'openspan'
|
|
1
3
|
import { type bindings, Connector } from '@toa.io/core'
|
|
2
4
|
import * as http from './HTTP'
|
|
3
5
|
import { rethrow } from './exceptions'
|
|
4
6
|
import type { Interception } from './Interception'
|
|
5
|
-
import type { Method, Parameter, Tree } from './RTD'
|
|
7
|
+
import type { Node, Method, Parameter, Tree, Match } from './RTD'
|
|
6
8
|
import type { Label } from './discovery'
|
|
7
9
|
import type { Branch } from './Branch'
|
|
8
10
|
|
|
@@ -10,6 +12,7 @@ export class Gateway extends Connector {
|
|
|
10
12
|
private readonly broadcast: Broadcast
|
|
11
13
|
private readonly tree: Tree
|
|
12
14
|
private readonly interceptor: Interception
|
|
15
|
+
private readonly merged = new Set<string>()
|
|
13
16
|
|
|
14
17
|
public constructor (broadcast: Broadcast, tree: Tree, interception: Interception) {
|
|
15
18
|
super()
|
|
@@ -28,15 +31,10 @@ export class Gateway extends Connector {
|
|
|
28
31
|
if (interception !== null)
|
|
29
32
|
return interception
|
|
30
33
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
if (match === null)
|
|
34
|
-
throw new http.NotFound()
|
|
34
|
+
const { node, parameters } = this.match(context)
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
node,
|
|
38
|
-
parameters
|
|
39
|
-
} = match
|
|
36
|
+
if (context.request.method === 'OPTIONS')
|
|
37
|
+
return await this.explain(node, parameters)
|
|
40
38
|
|
|
41
39
|
if (!(context.request.method in node.methods))
|
|
42
40
|
throw new http.MethodNotAllowed()
|
|
@@ -44,12 +42,13 @@ export class Gateway extends Connector {
|
|
|
44
42
|
const method = node.methods[context.request.method]
|
|
45
43
|
|
|
46
44
|
const interruption = await context.timing.capture('preflight',
|
|
47
|
-
method.directives.preflight(context, parameters))
|
|
45
|
+
method.directives.preflight(context, parameters)).catch(rethrow)
|
|
48
46
|
|
|
49
47
|
const response = interruption ??
|
|
50
48
|
await context.timing.capture('call', this.call(method, context, parameters))
|
|
51
49
|
|
|
52
|
-
await context.timing.capture('settle',
|
|
50
|
+
await context.timing.capture('settle',
|
|
51
|
+
method.directives.settle(context, response)).catch(rethrow)
|
|
53
52
|
|
|
54
53
|
return response
|
|
55
54
|
}
|
|
@@ -57,17 +56,41 @@ export class Gateway extends Connector {
|
|
|
57
56
|
protected override async open (): Promise<void> {
|
|
58
57
|
await this.discover()
|
|
59
58
|
|
|
60
|
-
console.info('Gateway
|
|
59
|
+
console.info('Gateway started')
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
protected override dispose (): void {
|
|
64
|
-
console.info('Gateway is closed
|
|
63
|
+
console.info('Gateway is closed')
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
private
|
|
68
|
-
|
|
66
|
+
private match (context: http.Context): Match {
|
|
67
|
+
const match = this.tree.match(context.url.pathname)
|
|
68
|
+
|
|
69
|
+
if (match === null)
|
|
70
|
+
throw new http.NotFound('Route not found')
|
|
71
|
+
|
|
72
|
+
if (match.node.forward === null)
|
|
73
|
+
return match
|
|
74
|
+
|
|
75
|
+
const destination = match.node.forward.replace(/\/:([^/]+)/g,
|
|
76
|
+
(_, name) => {
|
|
77
|
+
const value = match.parameters.find((parameter) => parameter.name === name)?.value
|
|
78
|
+
|
|
79
|
+
assert.ok(value !== undefined, `Forwarded parameter '${name}' not found`)
|
|
80
|
+
|
|
81
|
+
return `/${value}`
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
const forward = this.tree.match(destination)
|
|
85
|
+
|
|
86
|
+
assert.ok(forward !== null, 'Forwarded route not found')
|
|
87
|
+
|
|
88
|
+
return forward
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private async call (method: Method, context: http.Context, parameters: Parameter[]): Promise<http.OutgoingMessage> {
|
|
69
92
|
if (context.url.pathname[context.url.pathname.length - 1] !== '/')
|
|
70
|
-
throw new http.NotFound('Trailing slash is required
|
|
93
|
+
throw new http.NotFound('Trailing slash is required')
|
|
71
94
|
|
|
72
95
|
if (context.encoder === null)
|
|
73
96
|
throw new http.NotAcceptable()
|
|
@@ -80,19 +103,44 @@ export class Gateway extends Connector {
|
|
|
80
103
|
.catch(rethrow) as http.OutgoingMessage
|
|
81
104
|
}
|
|
82
105
|
|
|
106
|
+
private async explain (node: Node, parameters: Parameter[]): Promise<http.OutgoingMessage> {
|
|
107
|
+
const body = await node.explain(parameters)
|
|
108
|
+
const allow = [...Object.keys(node.methods)].join(', ')
|
|
109
|
+
const headers = new Headers({ allow })
|
|
110
|
+
|
|
111
|
+
return { body, headers }
|
|
112
|
+
}
|
|
113
|
+
|
|
83
114
|
private async discover (): Promise<void> {
|
|
84
115
|
await this.broadcast.receive<Branch>('expose', this.merge.bind(this))
|
|
85
116
|
await this.broadcast.transmit<null>('ping', null)
|
|
86
117
|
}
|
|
87
118
|
|
|
88
119
|
private merge (branch: Branch): void {
|
|
120
|
+
const id = branch.namespace + '.' + branch.component + '@' + branch.version
|
|
121
|
+
|
|
122
|
+
if (this.merged.has(id)) {
|
|
123
|
+
console.debug('Branch already merged, ignoring', {
|
|
124
|
+
namespace: branch.namespace,
|
|
125
|
+
component: branch.component,
|
|
126
|
+
version: branch.version
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.merged.add(id)
|
|
133
|
+
|
|
89
134
|
try {
|
|
90
135
|
this.tree.merge(branch.node, branch)
|
|
91
136
|
|
|
92
|
-
console.info('
|
|
93
|
-
|
|
137
|
+
console.info('Branch merged', {
|
|
138
|
+
namespace: branch.namespace,
|
|
139
|
+
component: branch.component,
|
|
140
|
+
version: branch.version
|
|
141
|
+
})
|
|
94
142
|
} catch (exception) {
|
|
95
|
-
console.error(exception)
|
|
143
|
+
console.error('Branch merge exception', exception as Error)
|
|
96
144
|
}
|
|
97
145
|
}
|
|
98
146
|
}
|
package/source/HTTP/Context.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Negotiator from 'negotiator'
|
|
2
|
+
import { console } from 'openspan'
|
|
2
3
|
import { Timing } from './Timing'
|
|
3
4
|
import { type Format, formats, types } from './formats'
|
|
4
5
|
import { read } from './messages'
|
|
@@ -6,22 +7,29 @@ import type { OutgoingMessage } from './messages'
|
|
|
6
7
|
import type * as http from 'node:http'
|
|
7
8
|
|
|
8
9
|
export class Context {
|
|
10
|
+
public readonly authority: string
|
|
9
11
|
public readonly request: IncomingMessage
|
|
10
12
|
public readonly url: URL
|
|
11
13
|
public readonly subtype: string | null = null
|
|
12
14
|
public readonly encoder: Format | null = null
|
|
13
15
|
public readonly timing: Timing
|
|
16
|
+
public readonly debug: boolean
|
|
14
17
|
|
|
15
18
|
public readonly pipelines: Pipelines = {
|
|
16
19
|
body: [],
|
|
17
20
|
response: []
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
public constructor (request: IncomingMessage,
|
|
23
|
+
public constructor (authority: string, request: IncomingMessage, properties: Properties) {
|
|
24
|
+
this.authority = authority
|
|
21
25
|
this.request = request
|
|
22
26
|
|
|
23
27
|
this.url = new URL(request.url, `https://${request.headers.host}`)
|
|
24
|
-
this.timing = new Timing(trace)
|
|
28
|
+
this.timing = new Timing(properties.trace)
|
|
29
|
+
this.debug = properties.debug
|
|
30
|
+
|
|
31
|
+
if (this.debug)
|
|
32
|
+
this.log(request)
|
|
25
33
|
|
|
26
34
|
if (this.request.headers.accept !== undefined) {
|
|
27
35
|
const match = SUBTYPE.exec(this.request.headers.accept)
|
|
@@ -52,6 +60,16 @@ export class Context {
|
|
|
52
60
|
? value
|
|
53
61
|
: this.pipelines.body.reduce((value, transform) => transform(value), value)
|
|
54
62
|
}
|
|
63
|
+
|
|
64
|
+
private log (request: IncomingMessage): void {
|
|
65
|
+
const headers = { ...request.headers }
|
|
66
|
+
|
|
67
|
+
if (headers.authorization !== undefined)
|
|
68
|
+
// only scheme
|
|
69
|
+
headers.authorization = headers.authorization.slice(0, headers.authorization.indexOf(' '))
|
|
70
|
+
|
|
71
|
+
console.debug('Received request', { method: request.method, url: request.url, headers })
|
|
72
|
+
}
|
|
55
73
|
}
|
|
56
74
|
|
|
57
75
|
export interface IncomingMessage extends http.IncomingMessage {
|
|
@@ -64,4 +82,9 @@ interface Pipelines {
|
|
|
64
82
|
response: Array<(output: OutgoingMessage) => void>
|
|
65
83
|
}
|
|
66
84
|
|
|
85
|
+
interface Properties {
|
|
86
|
+
debug: boolean
|
|
87
|
+
trace: boolean
|
|
88
|
+
}
|
|
89
|
+
|
|
67
90
|
const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/
|
package/source/HTTP/Server.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import * as http from 'node:http'
|
|
4
|
-
import assert from 'node:assert'
|
|
5
4
|
import { once } from 'node:events'
|
|
5
|
+
import { setTimeout } from 'node:timers/promises'
|
|
6
|
+
import { console } from 'openspan'
|
|
6
7
|
import { Connector } from '@toa.io/core'
|
|
7
|
-
import { promex } from '@toa.io/generic'
|
|
8
8
|
import { type OutgoingMessage, write } from './messages'
|
|
9
9
|
import { ClientError, Exception } from './exceptions'
|
|
10
10
|
import { Context } from './Context'
|
|
@@ -13,32 +13,22 @@ import type { IncomingMessage } from './Context'
|
|
|
13
13
|
export class Server extends Connector {
|
|
14
14
|
private readonly server: http.Server = http.createServer()
|
|
15
15
|
private readonly properties: Properties
|
|
16
|
+
private readonly authorities: Record<string, string>
|
|
16
17
|
private process?: Processing
|
|
18
|
+
private ready: boolean = false
|
|
19
|
+
private startedAt: number = 0
|
|
17
20
|
|
|
18
21
|
private constructor (properties: Properties) {
|
|
19
22
|
super()
|
|
20
23
|
|
|
21
24
|
this.properties = properties
|
|
25
|
+
this.authorities = Object.fromEntries(Object.entries(properties.authorities).map(([key, value]) => [value, key]))
|
|
22
26
|
|
|
23
27
|
this.server.on('request', (req, res) => this.listener(req, res))
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
public
|
|
27
|
-
|
|
28
|
-
return this.properties.port
|
|
29
|
-
|
|
30
|
-
const address = this.server.address()
|
|
31
|
-
|
|
32
|
-
if (address === null || typeof address === 'string')
|
|
33
|
-
throw new Error('Server is not listening on a port.')
|
|
34
|
-
|
|
35
|
-
return address.port
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public static create (options?: Partial<Properties>): Server {
|
|
39
|
-
const properties = options === undefined
|
|
40
|
-
? DEFAULTS
|
|
41
|
-
: { ...DEFAULTS, ...options }
|
|
30
|
+
public static create (options: Options): Server {
|
|
31
|
+
const properties: Properties = Object.assign({}, DEFAULTS, options)
|
|
42
32
|
|
|
43
33
|
return new Server(properties)
|
|
44
34
|
}
|
|
@@ -48,21 +38,29 @@ export class Server extends Connector {
|
|
|
48
38
|
}
|
|
49
39
|
|
|
50
40
|
protected override async open (): Promise<void> {
|
|
41
|
+
this.startedAt = Date.now()
|
|
51
42
|
this.server.listen(this.properties.port)
|
|
52
43
|
|
|
53
44
|
await once(this.server, 'listening')
|
|
54
45
|
|
|
55
|
-
console.info('HTTP Server is listening
|
|
46
|
+
console.info('HTTP Server is listening')
|
|
47
|
+
|
|
48
|
+
await setTimeout(this.properties.delay)
|
|
49
|
+
|
|
50
|
+
this.ready = true
|
|
51
|
+
|
|
52
|
+
console.info('Ready')
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
protected override async close (): Promise<void> {
|
|
59
56
|
this.server.close()
|
|
57
|
+
this.ready = false
|
|
60
58
|
|
|
61
|
-
console.info('
|
|
59
|
+
console.info('Stopped accepting new connections')
|
|
62
60
|
|
|
63
61
|
await once(this.server, 'close')
|
|
64
62
|
|
|
65
|
-
console.info('
|
|
63
|
+
console.info('Stopped')
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
private listener (request: http.IncomingMessage, response: http.ServerResponse): void {
|
|
@@ -72,18 +70,23 @@ export class Server extends Connector {
|
|
|
72
70
|
return
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
if (request.url ===
|
|
76
|
-
|
|
73
|
+
if (request.url === '/.ready') {
|
|
74
|
+
if (this.ready)
|
|
75
|
+
response.writeHead(200, { 'cache-control': 'no-store' }).end()
|
|
76
|
+
else {
|
|
77
|
+
const remaining = (Math.ceil((Date.now() - this.startedAt) / 1000)).toString()
|
|
78
|
+
|
|
79
|
+
response.writeHead(503, { 'retry-after': remaining }).end()
|
|
80
|
+
}
|
|
77
81
|
|
|
78
82
|
return
|
|
79
83
|
}
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const context = new Context(request as IncomingMessage, this.properties.trace)
|
|
85
|
+
const host = request.headers.host!
|
|
86
|
+
const authority = this.authorities[host] ?? host
|
|
87
|
+
const context = new Context(authority, request as IncomingMessage, this.properties)
|
|
85
88
|
|
|
86
|
-
this.process(context)
|
|
89
|
+
this.process!(context)
|
|
87
90
|
.then(this.success(context, response))
|
|
88
91
|
.catch(this.fail(context, response))
|
|
89
92
|
}
|
|
@@ -112,17 +115,15 @@ export class Server extends Connector {
|
|
|
112
115
|
if (!context.request.complete)
|
|
113
116
|
await adam(context.request)
|
|
114
117
|
|
|
115
|
-
response.statusCode = exception instanceof Exception
|
|
116
|
-
? exception.status
|
|
117
|
-
: 500
|
|
118
|
+
response.statusCode = exception instanceof Exception ? exception.status : 500
|
|
118
119
|
|
|
119
120
|
const message: OutgoingMessage = { status: response.statusCode }
|
|
120
|
-
const verbose = exception instanceof ClientError || this.properties.debug
|
|
121
121
|
|
|
122
|
-
if (
|
|
123
|
-
message.body =
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
if (exception instanceof ClientError || this.properties.debug)
|
|
123
|
+
message.body =
|
|
124
|
+
exception instanceof Exception
|
|
125
|
+
? exception.body
|
|
126
|
+
: exception.stack ?? exception.message
|
|
126
127
|
|
|
127
128
|
write(context, response, message)
|
|
128
129
|
}
|
|
@@ -131,28 +132,35 @@ export class Server extends Connector {
|
|
|
131
132
|
|
|
132
133
|
// https://github.com/whatwg/fetch/issues/1254
|
|
133
134
|
async function adam (request: http.IncomingMessage): Promise<void> {
|
|
134
|
-
const completed = promex()
|
|
135
135
|
const devnull = fs.createWriteStream(os.devNull)
|
|
136
136
|
|
|
137
|
-
request
|
|
138
|
-
.on('end', completed.callback)
|
|
139
|
-
.pipe(devnull)
|
|
137
|
+
request.pipe(devnull)
|
|
140
138
|
|
|
141
|
-
|
|
139
|
+
await once(request, 'end')
|
|
142
140
|
}
|
|
143
141
|
|
|
144
|
-
const
|
|
145
|
-
|
|
142
|
+
export const PORT = 8000
|
|
143
|
+
export const DELAY = 3 // seconds
|
|
144
|
+
|
|
145
|
+
const DEFAULTS: Omit<Properties, 'authorities'> = {
|
|
146
|
+
methods: new Set<string>(['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'LOCK', 'UNLOCK']),
|
|
146
147
|
debug: false,
|
|
147
148
|
trace: false,
|
|
148
|
-
port:
|
|
149
|
+
port: PORT,
|
|
150
|
+
delay: DELAY * 1000
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
interface Properties {
|
|
154
|
+
authorities: Record<string, string>
|
|
152
155
|
methods: Set<string>
|
|
153
156
|
debug: boolean
|
|
154
157
|
trace: boolean
|
|
155
158
|
port: number
|
|
159
|
+
delay: number
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type Options = { authorities: Properties['authorities'] } & {
|
|
163
|
+
[K in Exclude<keyof Properties, 'authorities'>]?: Properties[K]
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
export type Processing = (input: Context) => Promise<OutgoingMessage>
|
|
@@ -37,11 +37,17 @@ export class NotFound extends ClientError {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export class Conflict extends ClientError {
|
|
40
|
-
public constructor (body
|
|
40
|
+
public constructor (body?: any) {
|
|
41
41
|
super(409, body)
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export class UnprocessableEntity extends ClientError {
|
|
46
|
+
public constructor (body?: any) {
|
|
47
|
+
super(422, body)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
export class MethodNotAllowed extends ClientError {
|
|
46
52
|
public constructor () {
|
|
47
53
|
super(405)
|
|
@@ -65,3 +71,9 @@ export class PreconditionFailed extends ClientError {
|
|
|
65
71
|
super(412)
|
|
66
72
|
}
|
|
67
73
|
}
|
|
74
|
+
|
|
75
|
+
export class RequestEntityTooLarge extends ClientError {
|
|
76
|
+
public constructor (body?: any) {
|
|
77
|
+
super(413, body)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -5,10 +5,10 @@ import * as msgpack from './msgpack'
|
|
|
5
5
|
import * as text from './text'
|
|
6
6
|
|
|
7
7
|
export const formats: Record<string, Format> = {
|
|
8
|
-
[msgpack.type]: msgpack,
|
|
9
|
-
[yaml.type]: yaml,
|
|
10
8
|
[json.type]: json,
|
|
11
|
-
[
|
|
9
|
+
[yaml.type]: yaml,
|
|
10
|
+
[text.type]: text,
|
|
11
|
+
[msgpack.type]: msgpack
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const types = Object.keys(formats)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { Readable } from 'node:stream'
|
|
1
|
+
import { PassThrough, Readable } from 'node:stream'
|
|
2
|
+
import * as streamConsumers from 'node:stream/consumers'
|
|
3
|
+
import { once } from 'node:events'
|
|
2
4
|
import { generate } from 'randomstring'
|
|
3
5
|
import * as msgpack from 'msgpackr'
|
|
4
|
-
import { read } from './messages'
|
|
6
|
+
import { multipart, read, type OutgoingMessage } from './messages'
|
|
5
7
|
import { BadRequest, UnsupportedMediaType } from './exceptions'
|
|
8
|
+
import { formats } from './formats'
|
|
6
9
|
import { Timing } from './Timing'
|
|
10
|
+
import type * as http from 'node:http'
|
|
7
11
|
import type { Context } from './Context'
|
|
8
12
|
|
|
9
13
|
beforeEach(() => {
|
|
@@ -69,6 +73,45 @@ describe('read', () => {
|
|
|
69
73
|
|
|
70
74
|
await expect(read(request)).rejects.toThrow(BadRequest)
|
|
71
75
|
})
|
|
76
|
+
|
|
77
|
+
it('should output correct mulitpart format', async () => {
|
|
78
|
+
const response = new class extends PassThrough {
|
|
79
|
+
public readonly headers = new Headers()
|
|
80
|
+
|
|
81
|
+
public setHeader (key: string, value: string): this {
|
|
82
|
+
this.headers.set(key, value)
|
|
83
|
+
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
}()
|
|
87
|
+
|
|
88
|
+
const context = { encoder: formats['text/plain'] } as unknown as Context
|
|
89
|
+
const message = { body: Readable.from(['Hello', 'New', 'World']) } as unknown as OutgoingMessage
|
|
90
|
+
|
|
91
|
+
multipart(message, context, response as unknown as http.ServerResponse)
|
|
92
|
+
|
|
93
|
+
await once(message.body, 'end')
|
|
94
|
+
|
|
95
|
+
const result = await streamConsumers.text(response)
|
|
96
|
+
|
|
97
|
+
expect(result).toBe([
|
|
98
|
+
'--cut',
|
|
99
|
+
'',
|
|
100
|
+
'ACK',
|
|
101
|
+
'--cut',
|
|
102
|
+
'',
|
|
103
|
+
'Hello',
|
|
104
|
+
'--cut',
|
|
105
|
+
'',
|
|
106
|
+
'New',
|
|
107
|
+
'--cut',
|
|
108
|
+
'',
|
|
109
|
+
'World',
|
|
110
|
+
'--cut',
|
|
111
|
+
'',
|
|
112
|
+
'FIN',
|
|
113
|
+
'--cut--'].join('\r\n'))
|
|
114
|
+
})
|
|
72
115
|
})
|
|
73
116
|
|
|
74
117
|
export function createContext
|