@toa.io/extensions.exposition 1.0.0-alpha.7 → 1.0.0-alpha.71
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 +4 -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 +1 -0
- package/schemas/octets/store.cos.yaml +25 -3
- package/schemas/query.cos.yaml +4 -10
- package/source/Annotation.ts +3 -3
- package/source/Composition.ts +0 -6
- package/source/Directive.ts +4 -5
- package/source/Endpoint.ts +52 -12
- package/source/Factory.ts +10 -11
- package/source/Gateway.ts +48 -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/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/factory.ts +5 -2
- package/source/RTD/syntax/parse.ts +37 -24
- package/source/RTD/syntax/types.ts +6 -4
- package/source/Remotes.ts +2 -9
- package/source/Tenant.ts +0 -8
- 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/Composition.d.ts +0 -1
- package/transpiled/Composition.js +0 -4
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Directive.js +4 -4
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +6 -4
- package/transpiled/Endpoint.js +32 -4
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/Factory.js +9 -8
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +2 -0
- package/transpiled/Gateway.js +36 -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/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/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 +2 -4
- package/transpiled/Remotes.js +0 -5
- package/transpiled/Remotes.js.map +1 -1
- package/transpiled/Tenant.d.ts +0 -1
- package/transpiled/Tenant.js +0 -6
- 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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import type { Directive, Identity, Input } from './types'
|
|
3
|
+
import type { Parameter } from '../../RTD'
|
|
4
|
+
|
|
5
|
+
export class Federation implements Directive {
|
|
6
|
+
private readonly matchers: Array<[keyof Claim, Matcher]>
|
|
7
|
+
|
|
8
|
+
public constructor (options: Options) {
|
|
9
|
+
this.matchers = (Object.entries(options) as Array<[keyof Claim, string]>)
|
|
10
|
+
.map(([key, value]) => [key, toMatcher(value)])
|
|
11
|
+
|
|
12
|
+
assert.ok(this.matchers.length > 0, 'auth:claim requires at least one property defined')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public authorize (identity: Identity | null, context: Input, parameters: Parameter[]): boolean {
|
|
16
|
+
if (identity === null || !('claim' in identity))
|
|
17
|
+
return false
|
|
18
|
+
|
|
19
|
+
const claim = (identity as FederatedIdentity).claim
|
|
20
|
+
|
|
21
|
+
for (const [key, match] of this.matchers)
|
|
22
|
+
if (!match(claim[key], context, parameters))
|
|
23
|
+
return false
|
|
24
|
+
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toMatcher (expression: string): Matcher {
|
|
30
|
+
if (expression.startsWith(':')) {
|
|
31
|
+
const key = expression.slice(1) as 'authority'
|
|
32
|
+
|
|
33
|
+
if (key === 'authority')
|
|
34
|
+
return (value, context) => matches(value, context[key])
|
|
35
|
+
|
|
36
|
+
if (key === 'domain')
|
|
37
|
+
return (value, context) => {
|
|
38
|
+
return Array.isArray(value)
|
|
39
|
+
? value.some((iss) => codomain(iss, context))
|
|
40
|
+
: codomain(value, context)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw new Error(`Unknown 'auth:claim' syntax: ${expression}`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (expression.startsWith('/:')) {
|
|
47
|
+
const name = expression.slice(2)
|
|
48
|
+
|
|
49
|
+
return (value, _, parameters) => parameters
|
|
50
|
+
.some((parameter) => parameter.name === name && matches(value, parameter.value))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (value) => matches(value, expression)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function matches (value: string | string[], reference: string): boolean {
|
|
57
|
+
return Array.isArray(value)
|
|
58
|
+
? value.includes(reference)
|
|
59
|
+
: value === reference
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function codomain (iss: string, context: Input): boolean {
|
|
63
|
+
const hostname = new URL(iss).hostname
|
|
64
|
+
const dot = hostname.indexOf('.')
|
|
65
|
+
const basename = dot === -1 ? hostname : hostname.slice(dot)
|
|
66
|
+
|
|
67
|
+
return context.authority.slice(-basename.length) === basename
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type Matcher = (value: string | string[], context: Input, parameters: Parameter[]) => boolean
|
|
71
|
+
|
|
72
|
+
interface Claim {
|
|
73
|
+
iss: string
|
|
74
|
+
sub: string
|
|
75
|
+
aud: string | string[]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface Options extends Partial<Claim> {
|
|
79
|
+
iss: string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface FederatedIdentity extends Identity {
|
|
83
|
+
claim: Claim
|
|
84
|
+
}
|
|
@@ -23,7 +23,7 @@ export class Incept implements Directive {
|
|
|
23
23
|
|
|
24
24
|
if (id === undefined)
|
|
25
25
|
throw new http.Conflict('Identity inception has failed as the response body ' +
|
|
26
|
-
`
|
|
26
|
+
`does not contain the '${this.property}' property.`)
|
|
27
27
|
|
|
28
28
|
const [scheme, credentials] = split(input.request.headers.authorization!)
|
|
29
29
|
const provider = PROVIDERS[scheme]
|
|
@@ -31,15 +31,16 @@ export class Incept implements Directive {
|
|
|
31
31
|
this.schemes[scheme] ??= await this.discovery[provider]
|
|
32
32
|
|
|
33
33
|
const identity = await this.schemes[scheme]
|
|
34
|
-
.invoke<Maybe<Identity>>('
|
|
34
|
+
.invoke<Maybe<Identity>>('incept', {
|
|
35
35
|
input: {
|
|
36
|
+
authority: input.authority,
|
|
36
37
|
id,
|
|
37
38
|
credentials
|
|
38
39
|
}
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
if (identity instanceof Error)
|
|
42
|
-
throw new http.
|
|
43
|
+
throw new http.UnprocessableEntity(identity)
|
|
43
44
|
|
|
44
45
|
input.identity = identity
|
|
45
46
|
input.identity.scheme = scheme
|
|
@@ -2,6 +2,7 @@ import { type Component } from '@toa.io/core'
|
|
|
2
2
|
import { generate } from 'randomstring'
|
|
3
3
|
import { Role } from './Role'
|
|
4
4
|
import { type Identity } from './types'
|
|
5
|
+
import type { Parameter } from '../../RTD'
|
|
5
6
|
|
|
6
7
|
const remote = {
|
|
7
8
|
invoke: jest.fn()
|
|
@@ -16,16 +17,26 @@ beforeEach(() => {
|
|
|
16
17
|
it('should return false if not matched', async () => {
|
|
17
18
|
const roles = ['admin', 'user']
|
|
18
19
|
const directive = new Role(roles, discovery)
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
const identity: Identity = {
|
|
22
|
+
id: generate(),
|
|
23
|
+
scheme: '',
|
|
24
|
+
refresh: false
|
|
25
|
+
}
|
|
20
26
|
|
|
21
27
|
remote.invoke.mockResolvedValueOnce(['guest'])
|
|
22
28
|
|
|
23
|
-
const result = await directive.authorize(identity)
|
|
29
|
+
const result = await directive.authorize(identity, undefined, [])
|
|
24
30
|
|
|
25
31
|
expect(result).toBe(false)
|
|
26
32
|
|
|
27
33
|
expect(remote.invoke)
|
|
28
|
-
.toBeCalledWith('list', {
|
|
34
|
+
.toBeCalledWith('list', {
|
|
35
|
+
query: {
|
|
36
|
+
criteria: `identity==${identity.id}`,
|
|
37
|
+
limit: 1024
|
|
38
|
+
}
|
|
39
|
+
})
|
|
29
40
|
})
|
|
30
41
|
|
|
31
42
|
it('should return true on exact match', async () => {
|
|
@@ -52,11 +63,47 @@ it('should return false on non-scope substring match', async () => {
|
|
|
52
63
|
expect(result).toBe(false)
|
|
53
64
|
})
|
|
54
65
|
|
|
55
|
-
|
|
66
|
+
it('should return true on match with parameters', async () => {
|
|
67
|
+
const result = await match(['app:{org}:reviews'],
|
|
68
|
+
['app:29e54ae1:reviews'], [{
|
|
69
|
+
name: 'org',
|
|
70
|
+
value: '29e54ae1'
|
|
71
|
+
}])
|
|
72
|
+
|
|
73
|
+
expect(result).toBe(true)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('should return true on match with parameters', async () => {
|
|
77
|
+
const result = await match(['app:{org}:reviews'],
|
|
78
|
+
['app:29e54ae1:reviews'], [{
|
|
79
|
+
name: 'org',
|
|
80
|
+
value: '29e54ae1'
|
|
81
|
+
}])
|
|
82
|
+
|
|
83
|
+
expect(result).toBe(true)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('should return false on mismatch with parameters', async () => {
|
|
87
|
+
const result = await match(['app:{org}:reviews'],
|
|
88
|
+
['app:29e54ae1:reviews'], [{
|
|
89
|
+
name: 'org',
|
|
90
|
+
value: '88584c9b'
|
|
91
|
+
}])
|
|
92
|
+
|
|
93
|
+
expect(result).toBe(false)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
async function match
|
|
97
|
+
(expected: string[], actual: string[], parameters: Parameter[] = []): Promise<boolean> {
|
|
56
98
|
const directive = new Role(expected, discovery)
|
|
57
|
-
|
|
99
|
+
|
|
100
|
+
const identity: Identity = {
|
|
101
|
+
id: generate(),
|
|
102
|
+
scheme: '',
|
|
103
|
+
refresh: false
|
|
104
|
+
}
|
|
58
105
|
|
|
59
106
|
remote.invoke.mockResolvedValueOnce(actual)
|
|
60
107
|
|
|
61
|
-
return await directive.authorize(identity)
|
|
108
|
+
return await directive.authorize(identity, undefined, parameters)
|
|
62
109
|
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { type Component, type Query } from '@toa.io/core'
|
|
2
3
|
import { type Directive, type Identity } from './types'
|
|
4
|
+
import type { Parameter } from '../../RTD'
|
|
3
5
|
|
|
4
6
|
export class Role implements Directive {
|
|
5
7
|
public static remote: Component | null = null
|
|
6
8
|
private readonly roles: string[]
|
|
7
9
|
private readonly discovery: Promise<Component>
|
|
10
|
+
private readonly dynamic: boolean
|
|
8
11
|
|
|
9
12
|
public constructor (roles: string | string[], discovery: Promise<Component>) {
|
|
10
13
|
this.roles = typeof roles === 'string' ? [roles] : roles
|
|
11
14
|
this.discovery = discovery
|
|
15
|
+
this.dynamic = this.roles.some((role) => role.includes('{'))
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
public static async set (identity: Identity, discovery: Promise<Component>): Promise<void> {
|
|
@@ -22,37 +26,41 @@ export class Role implements Directive {
|
|
|
22
26
|
identity.roles = await this.remote.invoke('list', { query })
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
public async authorize
|
|
29
|
+
public async authorize
|
|
30
|
+
(identity: Identity | null, _: unknown, parameters: Parameter[]): Promise<boolean> {
|
|
26
31
|
if (identity === null)
|
|
27
32
|
return false
|
|
28
33
|
|
|
29
34
|
await Role.set(identity, this.discovery)
|
|
30
35
|
|
|
31
|
-
if (identity.roles ===
|
|
36
|
+
if (identity.roles!.length === 0) // Role.set()
|
|
37
|
+
|
|
32
38
|
return false
|
|
33
39
|
|
|
34
|
-
return this.match(identity.roles)
|
|
40
|
+
return this.match(identity.roles!, parameters)
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
private match (roles: string[]): boolean {
|
|
43
|
+
private match (roles: string[], parameters: Parameter[]): boolean {
|
|
44
|
+
const required = this.dynamic ? this.substitute(parameters) : this.roles
|
|
45
|
+
|
|
38
46
|
for (const role of roles) {
|
|
39
|
-
const
|
|
47
|
+
const ok = required.some((expected) => expected === role || expected.startsWith(role + ':'))
|
|
40
48
|
|
|
41
|
-
if (
|
|
49
|
+
if (ok)
|
|
42
50
|
return true
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
return false
|
|
46
54
|
}
|
|
47
|
-
}
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
private substitute (parameters: Parameter[]): string[] {
|
|
57
|
+
return this.roles.map((role) => role.replaceAll(/{(\w+)}/g, (_, key) => {
|
|
58
|
+
const value = parameters.find((parameter) => parameter.name === key)?.value
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return false
|
|
60
|
+
assert.ok(value !== undefined,
|
|
61
|
+
`Role '${role}' requires '${key}' route parameter.`)
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
return value
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
58
66
|
}
|
|
@@ -5,7 +5,7 @@ export function split (authorization: string): [Scheme, string] {
|
|
|
5
5
|
const space = authorization.indexOf(' ')
|
|
6
6
|
|
|
7
7
|
if (space === -1)
|
|
8
|
-
throw new http.Unauthorized('Malformed authorization header
|
|
8
|
+
throw new http.Unauthorized('Malformed authorization header')
|
|
9
9
|
|
|
10
10
|
const Scheme = authorization.slice(0, space)
|
|
11
11
|
const scheme = Scheme.toLowerCase() as Scheme
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Control } from './Control'
|
|
2
2
|
import { Exact } from './Exact'
|
|
3
|
-
import type {
|
|
4
|
-
import type { Directive } from './types'
|
|
3
|
+
import type { Output } from '../../io'
|
|
4
|
+
import type { AuthenticatedContext, Directive } from './types'
|
|
5
5
|
import type { DirectiveFamily } from '../../RTD'
|
|
6
6
|
import type * as http from '../../HTTP'
|
|
7
7
|
|
|
8
8
|
export class Cache implements DirectiveFamily<Directive> {
|
|
9
9
|
public readonly name: string = 'cache'
|
|
10
|
-
public readonly mandatory: boolean =
|
|
10
|
+
public readonly mandatory: boolean = true
|
|
11
11
|
|
|
12
12
|
public create (name: string, value: any): Directive {
|
|
13
13
|
const Class = constructors[name]
|
|
14
14
|
|
|
15
15
|
if (Class === undefined)
|
|
16
|
-
throw new Error(`Directive '
|
|
16
|
+
throw new Error(`Directive 'cache:${name}' is not implemented.`)
|
|
17
17
|
|
|
18
18
|
return new Class(value)
|
|
19
19
|
}
|
|
@@ -23,9 +23,16 @@ export class Cache implements DirectiveFamily<Directive> {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async settle
|
|
26
|
-
(directives: Directive[],
|
|
26
|
+
(directives: Directive[], context: AuthenticatedContext, response: http.OutgoingMessage): Promise<void> {
|
|
27
|
+
const directive = directives[0]
|
|
28
|
+
|
|
27
29
|
response.headers ??= new Headers()
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
if (directive === undefined) {
|
|
32
|
+
if (context.identity !== null && !Control.disabled(response.headers))
|
|
33
|
+
response.headers.set('cache-control', 'private')
|
|
34
|
+
} else
|
|
35
|
+
directive.set(context, response.headers)
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -4,56 +4,82 @@ import type { AuthenticatedContext, Directive } from './types'
|
|
|
4
4
|
export class Control implements Directive {
|
|
5
5
|
protected readonly value: string
|
|
6
6
|
private cache: string | null = null
|
|
7
|
+
private vary: boolean = false
|
|
7
8
|
|
|
8
9
|
public constructor (value: string) {
|
|
9
10
|
this.value = value
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
public static disabled (headers: Headers): boolean {
|
|
14
|
+
const value = headers.get('cache-control')
|
|
15
|
+
|
|
16
|
+
if (value === null)
|
|
17
|
+
return false
|
|
18
|
+
|
|
19
|
+
const directives = mask(value)
|
|
20
|
+
|
|
21
|
+
return (directives & NO_STORE) === NO_STORE
|
|
22
|
+
}
|
|
23
|
+
|
|
12
24
|
public set (context: AuthenticatedContext, headers: Headers): void {
|
|
13
25
|
if (!['GET', 'HEAD', 'OPTIONS'].includes(context.request.method))
|
|
14
26
|
return
|
|
15
27
|
|
|
16
28
|
this.cache ??= this.resolve(context)
|
|
17
29
|
|
|
30
|
+
if (Control.disabled(headers))
|
|
31
|
+
return
|
|
32
|
+
|
|
18
33
|
headers.set('cache-control', this.cache)
|
|
34
|
+
|
|
35
|
+
if (this.vary !== null)
|
|
36
|
+
headers.append('vary', 'authorization')
|
|
19
37
|
}
|
|
20
38
|
|
|
21
39
|
protected resolve (request: AuthenticatedContext): string {
|
|
22
40
|
if (request.identity === null)
|
|
23
41
|
return this.value
|
|
24
42
|
|
|
25
|
-
const directives = this.
|
|
43
|
+
const directives = mask(this.value)
|
|
44
|
+
|
|
45
|
+
if ((directives & PRIVATE) === PRIVATE)
|
|
46
|
+
this.vary = true
|
|
26
47
|
|
|
27
48
|
if ((directives & (PUBLIC | NO_CACHE)) === PUBLIC)
|
|
28
49
|
return 'no-cache, ' + this.value
|
|
29
50
|
|
|
30
|
-
if ((directives & (PUBLIC | PRIVATE)) === 0)
|
|
51
|
+
if ((directives & (PUBLIC | PRIVATE)) === 0) {
|
|
52
|
+
this.vary = true
|
|
53
|
+
|
|
31
54
|
return 'private, ' + this.value
|
|
55
|
+
}
|
|
32
56
|
|
|
33
57
|
return this.value
|
|
34
58
|
}
|
|
59
|
+
}
|
|
35
60
|
|
|
36
|
-
|
|
37
|
-
|
|
61
|
+
function mask (value: string): number {
|
|
62
|
+
const directives = value.match(DIRECTIVES_RX)
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
if (directives === null)
|
|
65
|
+
return 0
|
|
41
66
|
|
|
42
|
-
|
|
67
|
+
let mask = 0
|
|
43
68
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
for (const directive of directives)
|
|
70
|
+
mask |= match<number>(directive,
|
|
71
|
+
'private', PRIVATE,
|
|
72
|
+
'public', PUBLIC,
|
|
73
|
+
'no-cache', NO_CACHE,
|
|
74
|
+
'no-store', NO_STORE,
|
|
75
|
+
0)
|
|
50
76
|
|
|
51
|
-
|
|
52
|
-
}
|
|
77
|
+
return mask
|
|
53
78
|
}
|
|
54
79
|
|
|
55
|
-
const DIRECTIVES_RX = /\b(private|public|no-cache)\b/ig
|
|
80
|
+
const DIRECTIVES_RX = /\b(private|public|no-cache|no-store)\b/ig
|
|
56
81
|
|
|
57
82
|
const PUBLIC = 1
|
|
58
83
|
const PRIVATE = 2
|
|
59
84
|
const NO_CACHE = 4
|
|
85
|
+
const NO_STORE = 8
|
|
@@ -14,7 +14,7 @@ export class CORS implements Interceptor {
|
|
|
14
14
|
])
|
|
15
15
|
|
|
16
16
|
private readonly headers = new Headers({
|
|
17
|
-
'access-control-allow-methods': 'GET, POST, PUT, PATCH, DELETE',
|
|
17
|
+
'access-control-allow-methods': 'GET, POST, PUT, PATCH, DELETE, LOCK, UNLOCK',
|
|
18
18
|
'access-control-allow-credentials': 'true',
|
|
19
19
|
'access-control-allow-headers': Array.from(this.requestHeaders).join(', '),
|
|
20
20
|
'access-control-max-age': '3600',
|
|
@@ -12,7 +12,7 @@ export class Development implements DirectiveFamily<Directive> {
|
|
|
12
12
|
const Class = constructors[name]
|
|
13
13
|
|
|
14
14
|
if (Class === undefined)
|
|
15
|
-
throw new Error(`Directive '
|
|
15
|
+
throw new Error(`Directive 'dev:${name}' is not implemented.`)
|
|
16
16
|
|
|
17
17
|
return new Class(value)
|
|
18
18
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Readable } from 'node:stream'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { match } from 'matchacho'
|
|
4
|
+
import { NotFound } from '../../HTTP'
|
|
5
|
+
import type { Directive } from './types'
|
|
6
|
+
import type { ReadableStream } from 'node:stream/web'
|
|
7
|
+
import type { Remotes } from '../../Remotes'
|
|
8
|
+
import type { Maybe } from '@toa.io/types'
|
|
9
|
+
import type { Component } from '@toa.io/core'
|
|
10
|
+
import type { Output } from '../../io'
|
|
11
|
+
import type { Input } from '../octets/types'
|
|
12
|
+
import type { Parameter } from '../../RTD'
|
|
13
|
+
|
|
14
|
+
export class Fetch implements Directive {
|
|
15
|
+
public readonly targeted = true
|
|
16
|
+
|
|
17
|
+
private readonly connecting: Promise<Component>
|
|
18
|
+
private remote: Component | null = null
|
|
19
|
+
private readonly operation: string
|
|
20
|
+
|
|
21
|
+
public constructor (endpoint: string, discovery: Remotes) {
|
|
22
|
+
assert.equal(typeof endpoint, 'string', '`flow:redirect` must be a string')
|
|
23
|
+
|
|
24
|
+
const [operation, name, namespace = 'default'] = endpoint.split('.').reverse()
|
|
25
|
+
|
|
26
|
+
this.operation = operation
|
|
27
|
+
this.connecting = discovery.discover(namespace, name)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async apply (input: Input, parameters: Parameter[]): Promise<Output> {
|
|
31
|
+
if ('if-none-match' in input.request.headers)
|
|
32
|
+
return { status: 304 }
|
|
33
|
+
|
|
34
|
+
this.remote ??= await this.connecting
|
|
35
|
+
|
|
36
|
+
const request = await this.remote.invoke<Maybe<Request | string>>(this.operation, {
|
|
37
|
+
input: {
|
|
38
|
+
authority: input.authority,
|
|
39
|
+
path: input.request.url,
|
|
40
|
+
parameters: Object.fromEntries(parameters.map(({ name, value }) => [name, value]))
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (request instanceof Error)
|
|
45
|
+
throw new NotFound(request)
|
|
46
|
+
|
|
47
|
+
const { url, options } = match<Request>(request,
|
|
48
|
+
String, { url: request },
|
|
49
|
+
(request: Request): Request => ({
|
|
50
|
+
url: request.url,
|
|
51
|
+
options: {
|
|
52
|
+
method: request.options?.method ?? 'GET',
|
|
53
|
+
body: request.options?.body,
|
|
54
|
+
headers: request.options?.headers
|
|
55
|
+
}
|
|
56
|
+
}))
|
|
57
|
+
|
|
58
|
+
const response = await fetch(url, options)
|
|
59
|
+
|
|
60
|
+
if (!response.ok)
|
|
61
|
+
throw new NotFound()
|
|
62
|
+
|
|
63
|
+
const headers = new Headers()
|
|
64
|
+
|
|
65
|
+
for (const header of ['content-type', 'content-length', 'etag']) {
|
|
66
|
+
const value = response.headers.get(header)
|
|
67
|
+
|
|
68
|
+
if (value !== null)
|
|
69
|
+
headers.set(header, value)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
headers,
|
|
74
|
+
body: response.body === null ? null : Readable.fromWeb(response.body as ReadableStream)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface Request {
|
|
80
|
+
url: string
|
|
81
|
+
options?: RequestOptions
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface RequestOptions {
|
|
85
|
+
method?: string
|
|
86
|
+
body?: string
|
|
87
|
+
headers?: Record<string, string>
|
|
88
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Fetch } from './Fetch'
|
|
2
|
+
import type { Directive } from './types'
|
|
3
|
+
import type { Input, Output } from '../../io'
|
|
4
|
+
import type { DirectiveFamily, Parameter } from '../../RTD'
|
|
5
|
+
import type { Remotes } from '../../Remotes'
|
|
6
|
+
|
|
7
|
+
export class Flow implements DirectiveFamily<Directive> {
|
|
8
|
+
public readonly name: string = 'flow'
|
|
9
|
+
public readonly mandatory: boolean = false
|
|
10
|
+
|
|
11
|
+
public create (name: string, value: unknown, remotes: Remotes): Directive {
|
|
12
|
+
const Class = constructors[name]
|
|
13
|
+
|
|
14
|
+
if (Class === undefined)
|
|
15
|
+
throw new Error(`Directive '${this.name}:${name}' is not implemented.`)
|
|
16
|
+
|
|
17
|
+
return new Class(value, remotes)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async preflight (directives: Directive[], input: Input, parameters: Parameter[]): Promise<Output> {
|
|
21
|
+
for (const directive of directives) {
|
|
22
|
+
const output = await directive.apply(input, parameters)
|
|
23
|
+
|
|
24
|
+
if (output !== null)
|
|
25
|
+
return output
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const constructors: Record<string, new (value: any, discovery: Remotes) => Directive> = {
|
|
33
|
+
fetch: Fetch
|
|
34
|
+
}
|
|
@@ -5,8 +5,10 @@ import { dev } from './dev'
|
|
|
5
5
|
import { octets } from './octets'
|
|
6
6
|
import { io } from './io'
|
|
7
7
|
import { vary } from './vary'
|
|
8
|
+
import { req } from './require'
|
|
9
|
+
import { flow } from './flow'
|
|
8
10
|
import type { DirectiveFamily } from '../RTD'
|
|
9
11
|
import type { Interceptor } from '../Interception'
|
|
10
12
|
|
|
11
|
-
export const families: DirectiveFamily[] = [authorization, io, cache, vary, octets, dev]
|
|
13
|
+
export const families: DirectiveFamily[] = [authorization, io, cache, vary, req, flow, octets, dev]
|
|
12
14
|
export const interceptors: Interceptor[] = [cors]
|
|
@@ -12,7 +12,7 @@ export class Input implements Directive {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
public static validate (permissions: unknown): asserts permissions is Permissions {
|
|
15
|
-
schemas.input.validate(permissions, 'Incorrect \'io:input\' format')
|
|
15
|
+
schemas.input.validate<Permissions>(permissions, 'Incorrect \'io:input\' format')
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
public attach (context: Context): void {
|
|
@@ -21,15 +21,15 @@ export class Input implements Directive {
|
|
|
21
21
|
|
|
22
22
|
private check (body: unknown): unknown {
|
|
23
23
|
try {
|
|
24
|
-
schemas.message.validate(body)
|
|
24
|
+
schemas.message.validate<Message | Message[]>(body)
|
|
25
25
|
} catch {
|
|
26
|
-
throw new BadRequest('Invalid request body
|
|
26
|
+
throw new BadRequest('Invalid request body')
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const property = this.violation(body)
|
|
30
30
|
|
|
31
31
|
if (property !== undefined)
|
|
32
|
-
throw new BadRequest(`Unexpected input: ${property}
|
|
32
|
+
throw new BadRequest(`Unexpected input: ${property}`)
|
|
33
33
|
|
|
34
34
|
return body
|
|
35
35
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Stream } from 'node:stream'
|
|
2
|
+
import { console } from 'openspan'
|
|
2
3
|
import * as schemas from './schemas'
|
|
3
4
|
import type { Message } from './Message'
|
|
4
5
|
import type { Directive } from './Directive'
|
|
@@ -40,15 +41,15 @@ export class Output implements Directive {
|
|
|
40
41
|
|
|
41
42
|
if (typeof message.body !== 'object' || this.permissions.length === 0) {
|
|
42
43
|
if (this.omitted)
|
|
43
|
-
console.warn('Permissions for \'io:output\' are not specified properly '
|
|
44
|
-
|
|
44
|
+
console.warn('Permissions for \'io:output\' are not specified properly. Response omitted.',
|
|
45
|
+
{ path: context.url.pathname })
|
|
45
46
|
|
|
46
47
|
delete message.body
|
|
47
48
|
|
|
48
49
|
return
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
schemas.message.validate(message.body,
|
|
52
|
+
schemas.message.validate<Message>(message.body,
|
|
52
53
|
'\'io:output\' expects response to be an object or array of objects')
|
|
53
54
|
|
|
54
55
|
if (Array.isArray(message.body))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from 'node:assert'
|
|
2
2
|
import { Directive } from './Directive'
|
|
3
3
|
import type { Output } from '../../io'
|
|
4
4
|
|
|
@@ -8,7 +8,8 @@ export class Context extends Directive {
|
|
|
8
8
|
|
|
9
9
|
public constructor (value: unknown) {
|
|
10
10
|
super()
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
assert.ok(typeof value === 'string', 'Directive \'octets:context\' must must be a string')
|
|
12
13
|
|
|
13
14
|
this.storage = value
|
|
14
15
|
}
|