@toa.io/extensions.exposition 1.0.0-alpha.0 → 1.0.0-alpha.3
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 +12 -0
- package/components/identity.bans/manifest.toa.yaml +1 -1
- package/components/identity.basic/manifest.toa.yaml +2 -2
- package/components/identity.basic/operations/authenticate.d.ts +9 -0
- package/components/identity.basic/operations/authenticate.js +24 -0
- package/components/identity.basic/operations/authenticate.js.map +1 -0
- package/components/identity.basic/operations/create.d.ts +10 -0
- package/components/identity.basic/operations/create.js +10 -0
- package/components/identity.basic/operations/create.js.map +1 -0
- package/components/identity.basic/operations/transit.d.ts +12 -0
- package/components/identity.basic/operations/transit.js +53 -0
- package/components/identity.basic/operations/transit.js.map +1 -0
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.basic/operations/types.d.ts +38 -0
- package/components/identity.basic/operations/types.js +3 -0
- package/components/identity.basic/operations/types.js.map +1 -0
- package/components/identity.basic/source/authenticate.ts +0 -1
- package/components/identity.federation/events/principal.js +22 -0
- package/components/identity.federation/manifest.toa.yaml +100 -0
- package/components/identity.federation/operations/authenticate.d.ts +3 -0
- package/components/identity.federation/operations/authenticate.js +20 -0
- package/components/identity.federation/operations/authenticate.js.map +1 -0
- package/components/identity.federation/operations/create.d.ts +10 -0
- package/components/identity.federation/operations/create.js +15 -0
- package/components/identity.federation/operations/create.js.map +1 -0
- package/components/identity.federation/operations/lib/assertions-as-values.d.ts +4 -0
- package/components/identity.federation/operations/lib/assertions-as-values.js +45 -0
- package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -0
- package/components/identity.federation/operations/lib/jwt.d.ts +20 -0
- package/components/identity.federation/operations/lib/jwt.js +136 -0
- package/components/identity.federation/operations/lib/jwt.js.map +1 -0
- package/components/identity.federation/operations/schemas.d.ts +59 -0
- package/components/identity.federation/operations/schemas.js +9 -0
- package/components/identity.federation/operations/schemas.js.map +1 -0
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.federation/operations/types.d.ts +51 -0
- package/components/identity.federation/operations/types.js +3 -0
- package/components/identity.federation/operations/types.js.map +1 -0
- package/components/identity.federation/source/authenticate.ts +28 -0
- package/components/identity.federation/source/create.ts +26 -0
- package/components/identity.federation/source/lib/assertions-as-values.ts +19 -0
- package/components/identity.federation/source/lib/jwt.test.ts +56 -0
- package/components/identity.federation/source/lib/jwt.ts +171 -0
- package/components/identity.federation/source/schemas.ts +61 -0
- package/components/identity.federation/source/types.ts +56 -0
- package/components/identity.federation/tsconfig.json +9 -0
- package/components/identity.roles/operations/list.d.ts +5 -0
- package/components/identity.roles/operations/list.js +8 -0
- package/components/identity.roles/operations/list.js.map +1 -0
- package/components/identity.roles/operations/principal.d.ts +15 -0
- package/components/identity.roles/operations/principal.js +8 -0
- package/components/identity.roles/operations/principal.js.map +1 -0
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.tokens/manifest.toa.yaml +1 -1
- package/components/identity.tokens/operations/authenticate.d.ts +9 -0
- package/components/identity.tokens/operations/authenticate.js +32 -0
- package/components/identity.tokens/operations/authenticate.js.map +1 -0
- package/components/identity.tokens/operations/decrypt.d.ts +3 -0
- package/components/identity.tokens/operations/decrypt.js +32 -0
- package/components/identity.tokens/operations/decrypt.js.map +1 -0
- package/components/identity.tokens/operations/encrypt.d.ts +8 -0
- package/components/identity.tokens/operations/encrypt.js +22 -0
- package/components/identity.tokens/operations/encrypt.js.map +1 -0
- package/components/identity.tokens/operations/revoke.d.ts +2 -0
- package/components/identity.tokens/operations/revoke.js +8 -0
- package/components/identity.tokens/operations/revoke.js.map +1 -0
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.tokens/operations/types.d.ts +40 -0
- package/components/identity.tokens/operations/types.js +3 -0
- package/components/identity.tokens/operations/types.js.map +1 -0
- package/components/octets.storage/manifest.toa.yaml +1 -0
- package/components/octets.storage/operations/store.js +2 -2
- package/cucumber.js +0 -1
- package/documentation/components.md +32 -2
- package/documentation/identity.md +14 -7
- package/documentation/octets.md +105 -40
- package/documentation/protocol.md +21 -1
- package/documentation/query.md +1 -1
- package/documentation/vary.md +69 -0
- package/features/cors.feature +72 -0
- package/features/identity.feature +19 -3
- package/features/identity.federation.feature +155 -0
- package/features/octets.entries.feature +121 -0
- package/features/octets.feature +2 -28
- package/features/octets.meta.feature +65 -0
- package/features/octets.workflows.feature +176 -4
- package/features/response.feature +65 -0
- package/features/routes.feature +37 -0
- package/features/steps/Captures.ts +6 -0
- package/features/steps/Components.ts +18 -6
- package/features/steps/Gateway.ts +1 -2
- package/features/steps/HTTP.ts +40 -87
- package/features/steps/IdP.ts +149 -0
- package/features/steps/Parameters.ts +8 -2
- package/features/steps/Workspace.ts +5 -7
- package/features/steps/components/echo/operations/error.js +11 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +3 -0
- package/features/steps/components/octets.tester/operations/concat.js +7 -0
- package/features/steps/components/octets.tester/operations/echo.js +7 -0
- package/features/steps/components/users/manifest.toa.yaml +3 -0
- package/features/steps/components/users.properties/manifest.toa.yaml +13 -0
- package/features/steps/tsconfig.json +1 -1
- package/features/vary.feature +150 -0
- package/package.json +17 -18
- package/schemas/octets/delete.cos.yaml +2 -1
- package/schemas/octets/list.cos.yaml +2 -1
- package/schemas/octets/workflow.cos.yaml +12 -0
- package/source/Directive.test.ts +8 -2
- package/source/Directive.ts +19 -16
- package/source/Factory.ts +8 -7
- package/source/Gateway.ts +22 -8
- package/source/HTTP/Server.fixtures.ts +0 -1
- package/source/HTTP/Server.test.ts +61 -134
- package/source/HTTP/Server.ts +91 -47
- package/source/HTTP/formats/msgpack.ts +9 -6
- package/source/HTTP/formats/text.ts +1 -1
- package/source/HTTP/formats/yaml.ts +1 -1
- package/source/HTTP/messages.ts +15 -3
- package/source/Interception.ts +24 -0
- package/source/RTD/Directives.ts +2 -2
- package/source/RTD/Tree.ts +3 -0
- package/source/RTD/syntax/parse.ts +6 -6
- package/source/RTD/syntax/types.ts +1 -1
- package/source/deployment.ts +1 -2
- package/source/directives/auth/{Family.ts → Authorization.ts} +29 -33
- package/source/directives/auth/Incept.ts +1 -1
- package/source/directives/auth/Rule.ts +2 -2
- package/source/directives/auth/index.ts +2 -2
- package/source/directives/auth/schemes.ts +2 -1
- package/source/directives/auth/types.ts +9 -6
- package/source/directives/cache/{Family.ts → Cache.ts} +4 -5
- package/source/directives/cache/index.ts +2 -2
- package/source/directives/cache/types.ts +1 -1
- package/source/directives/cors/CORS.ts +54 -0
- package/source/directives/cors/index.ts +3 -0
- package/source/directives/dev/{Family.ts → Development.ts} +3 -4
- package/source/directives/dev/Stub.ts +4 -4
- package/source/directives/dev/Throw.ts +4 -4
- package/source/directives/dev/index.ts +2 -2
- package/source/directives/dev/types.ts +1 -1
- package/source/directives/index.ts +10 -6
- package/source/directives/octets/Context.ts +1 -1
- package/source/directives/octets/Delete.ts +50 -9
- package/source/directives/octets/Fetch.ts +18 -19
- package/source/directives/octets/List.ts +37 -7
- package/source/directives/octets/{Family.ts → Octets.ts} +10 -7
- package/source/directives/octets/Permute.ts +3 -3
- package/source/directives/octets/Store.ts +57 -99
- package/source/directives/octets/Workflow.ts +41 -0
- package/source/directives/octets/index.ts +2 -2
- package/source/directives/octets/schemas.test.ts +21 -0
- package/source/directives/octets/schemas.ts +13 -6
- package/source/directives/octets/types.ts +4 -3
- package/source/directives/octets/workflows/Execution.ts +76 -0
- package/source/directives/octets/workflows/Workflow.ts +37 -0
- package/source/directives/octets/workflows/index.ts +1 -0
- package/source/directives/vary/Directive.ts +6 -0
- package/source/directives/vary/Embed.ts +62 -0
- package/source/directives/vary/Properties.ts +17 -0
- package/source/directives/vary/Vary.ts +48 -0
- package/source/directives/vary/embeddings/Embedding.ts +6 -0
- package/source/directives/vary/embeddings/Header.ts +30 -0
- package/source/directives/vary/embeddings/Language.ts +31 -0
- package/source/directives/vary/embeddings/index.ts +11 -0
- package/source/directives/vary/index.ts +3 -0
- package/source/io.ts +4 -0
- package/source/manifest.test.ts +6 -14
- package/source/manifest.ts +9 -6
- package/source/schemas.ts +7 -3
- package/transpiled/Annotation.d.ts +7 -0
- package/transpiled/Annotation.js +3 -0
- package/transpiled/Annotation.js.map +1 -0
- package/transpiled/Branch.d.ts +7 -0
- package/transpiled/Branch.js +3 -0
- package/transpiled/Branch.js.map +1 -0
- package/transpiled/Composition.d.ts +14 -0
- package/transpiled/Composition.js +43 -0
- package/transpiled/Composition.js.map +1 -0
- package/transpiled/Context.d.ts +5 -0
- package/transpiled/Context.js +3 -0
- package/transpiled/Context.js.map +1 -0
- package/transpiled/Directive.d.ts +31 -0
- package/transpiled/Directive.js +78 -0
- package/transpiled/Directive.js.map +1 -0
- package/transpiled/Endpoint.d.ts +20 -0
- package/transpiled/Endpoint.js +45 -0
- package/transpiled/Endpoint.js.map +1 -0
- package/transpiled/Factory.d.ts +9 -0
- package/transpiled/Factory.js +67 -0
- package/transpiled/Factory.js.map +1 -0
- package/transpiled/Gateway.d.ts +22 -0
- package/transpiled/Gateway.js +102 -0
- package/transpiled/Gateway.js.map +1 -0
- package/transpiled/HTTP/Server.d.ts +24 -0
- package/transpiled/HTTP/Server.fixtures.d.ts +10 -0
- package/transpiled/HTTP/Server.fixtures.js +31 -0
- package/transpiled/HTTP/Server.fixtures.js.map +1 -0
- package/transpiled/HTTP/Server.js +149 -0
- package/transpiled/HTTP/Server.js.map +1 -0
- package/transpiled/HTTP/exceptions.d.ts +34 -0
- package/transpiled/HTTP/exceptions.js +71 -0
- package/transpiled/HTTP/exceptions.js.map +1 -0
- package/transpiled/HTTP/formats/index.d.ts +10 -0
- package/transpiled/HTTP/formats/index.js +38 -0
- package/transpiled/HTTP/formats/index.js.map +1 -0
- package/transpiled/HTTP/formats/json.d.ts +6 -0
- package/transpiled/HTTP/formats/json.js +17 -0
- package/transpiled/HTTP/formats/json.js.map +1 -0
- package/transpiled/HTTP/formats/msgpack.d.ts +6 -0
- package/transpiled/HTTP/formats/msgpack.js +17 -0
- package/transpiled/HTTP/formats/msgpack.js.map +1 -0
- package/transpiled/HTTP/formats/text.d.ts +8 -0
- package/transpiled/HTTP/formats/text.js +15 -0
- package/transpiled/HTTP/formats/text.js.map +1 -0
- package/transpiled/HTTP/formats/yaml.d.ts +6 -0
- package/transpiled/HTTP/formats/yaml.js +41 -0
- package/transpiled/HTTP/formats/yaml.js.map +1 -0
- package/transpiled/HTTP/index.d.ts +3 -0
- package/transpiled/HTTP/index.js +20 -0
- package/transpiled/HTTP/index.js.map +1 -0
- package/transpiled/HTTP/messages.d.ts +33 -0
- package/transpiled/HTTP/messages.js +75 -0
- package/transpiled/HTTP/messages.js.map +1 -0
- package/transpiled/Interception.d.ts +9 -0
- package/transpiled/Interception.js +19 -0
- package/transpiled/Interception.js.map +1 -0
- package/transpiled/Mapping.d.ts +8 -0
- package/transpiled/Mapping.js +38 -0
- package/transpiled/Mapping.js.map +1 -0
- package/transpiled/Query.d.ts +13 -0
- package/transpiled/Query.js +107 -0
- package/transpiled/Query.js.map +1 -0
- package/transpiled/RTD/Context.d.ts +11 -0
- package/transpiled/RTD/Context.js +3 -0
- package/transpiled/RTD/Context.js.map +1 -0
- package/transpiled/RTD/Directives.d.ts +7 -0
- package/transpiled/RTD/Directives.js +3 -0
- package/transpiled/RTD/Directives.js.map +1 -0
- package/transpiled/RTD/Endpoint.d.ts +9 -0
- package/transpiled/RTD/Endpoint.js +3 -0
- package/transpiled/RTD/Endpoint.js.map +1 -0
- package/transpiled/RTD/Match.d.ts +11 -0
- package/transpiled/RTD/Match.js +3 -0
- package/transpiled/RTD/Match.js.map +1 -0
- package/transpiled/RTD/Method.d.ts +9 -0
- package/transpiled/RTD/Method.js +16 -0
- package/transpiled/RTD/Method.js.map +1 -0
- package/transpiled/RTD/Node.d.ts +21 -0
- package/transpiled/RTD/Node.js +61 -0
- package/transpiled/RTD/Node.js.map +1 -0
- package/transpiled/RTD/Route.d.ts +14 -0
- package/transpiled/RTD/Route.js +49 -0
- package/transpiled/RTD/Route.js.map +1 -0
- package/transpiled/RTD/Tree.d.ts +14 -0
- package/transpiled/RTD/Tree.js +42 -0
- package/transpiled/RTD/Tree.js.map +1 -0
- package/transpiled/RTD/factory.d.ts +6 -0
- package/transpiled/RTD/factory.js +36 -0
- package/transpiled/RTD/factory.js.map +1 -0
- package/transpiled/RTD/index.d.ts +8 -0
- package/transpiled/RTD/index.js +38 -0
- package/transpiled/RTD/index.js.map +1 -0
- package/transpiled/RTD/segment.d.ts +8 -0
- package/transpiled/RTD/segment.js +25 -0
- package/transpiled/RTD/segment.js.map +1 -0
- package/transpiled/RTD/syntax/index.d.ts +2 -0
- package/transpiled/RTD/syntax/index.js +19 -0
- package/transpiled/RTD/syntax/index.js.map +1 -0
- package/transpiled/RTD/syntax/parse.d.ts +4 -0
- package/transpiled/RTD/syntax/parse.js +128 -0
- package/transpiled/RTD/syntax/parse.js.map +1 -0
- package/transpiled/RTD/syntax/types.d.ts +41 -0
- package/transpiled/RTD/syntax/types.js +5 -0
- package/transpiled/RTD/syntax/types.js.map +1 -0
- package/transpiled/Remotes.d.ts +9 -0
- package/transpiled/Remotes.js +25 -0
- package/transpiled/Remotes.js.map +1 -0
- package/transpiled/Tenant.d.ts +13 -0
- package/transpiled/Tenant.js +34 -0
- package/transpiled/Tenant.js.map +1 -0
- package/transpiled/deployment.d.ts +3 -0
- package/transpiled/deployment.js +66 -0
- package/transpiled/deployment.js.map +1 -0
- package/transpiled/directives/auth/Anonymous.d.ts +6 -0
- package/transpiled/directives/auth/Anonymous.js +17 -0
- package/transpiled/directives/auth/Anonymous.js.map +1 -0
- package/transpiled/directives/auth/Authorization.d.ts +20 -0
- package/transpiled/directives/auth/Authorization.js +125 -0
- package/transpiled/directives/auth/Authorization.js.map +1 -0
- package/transpiled/directives/auth/Echo.d.ts +6 -0
- package/transpiled/directives/auth/Echo.js +13 -0
- package/transpiled/directives/auth/Echo.js.map +1 -0
- package/transpiled/directives/auth/Id.d.ts +7 -0
- package/transpiled/directives/auth/Id.js +17 -0
- package/transpiled/directives/auth/Id.js.map +1 -0
- package/transpiled/directives/auth/Incept.d.ts +10 -0
- package/transpiled/directives/auth/Incept.js +58 -0
- package/transpiled/directives/auth/Incept.js.map +1 -0
- package/transpiled/directives/auth/Role.d.ts +11 -0
- package/transpiled/directives/auth/Role.js +44 -0
- package/transpiled/directives/auth/Role.js.map +1 -0
- package/transpiled/directives/auth/Rule.d.ts +9 -0
- package/transpiled/directives/auth/Rule.js +22 -0
- package/transpiled/directives/auth/Rule.js.map +1 -0
- package/transpiled/directives/auth/Scheme.d.ts +7 -0
- package/transpiled/directives/auth/Scheme.js +47 -0
- package/transpiled/directives/auth/Scheme.js.map +1 -0
- package/transpiled/directives/auth/index.d.ts +2 -0
- package/transpiled/directives/auth/index.js +6 -0
- package/transpiled/directives/auth/index.js.map +1 -0
- package/transpiled/directives/auth/schemes.d.ts +3 -0
- package/transpiled/directives/auth/schemes.js +10 -0
- package/transpiled/directives/auth/schemes.js.map +1 -0
- package/transpiled/directives/auth/split.d.ts +2 -0
- package/transpiled/directives/auth/split.js +38 -0
- package/transpiled/directives/auth/split.js.map +1 -0
- package/transpiled/directives/auth/types.d.ts +31 -0
- package/transpiled/directives/auth/types.js +3 -0
- package/transpiled/directives/auth/types.js.map +1 -0
- package/transpiled/directives/cache/Cache.d.ts +11 -0
- package/transpiled/directives/cache/Cache.js +28 -0
- package/transpiled/directives/cache/Cache.js.map +1 -0
- package/transpiled/directives/cache/Control.d.ts +9 -0
- package/transpiled/directives/cache/Control.js +42 -0
- package/transpiled/directives/cache/Control.js.map +1 -0
- package/transpiled/directives/cache/Exact.d.ts +4 -0
- package/transpiled/directives/cache/Exact.js +11 -0
- package/transpiled/directives/cache/Exact.js.map +1 -0
- package/transpiled/directives/cache/index.d.ts +2 -0
- package/transpiled/directives/cache/index.js +6 -0
- package/transpiled/directives/cache/index.js.map +1 -0
- package/transpiled/directives/cache/types.d.ts +7 -0
- package/transpiled/directives/cache/types.js +3 -0
- package/transpiled/directives/cache/types.js.map +1 -0
- package/transpiled/directives/cors/CORS.d.ts +11 -0
- package/transpiled/directives/cors/CORS.js +44 -0
- package/transpiled/directives/cors/CORS.js.map +1 -0
- package/transpiled/directives/cors/index.d.ts +2 -0
- package/transpiled/directives/cors/index.js +6 -0
- package/transpiled/directives/cors/index.js.map +1 -0
- package/transpiled/directives/dev/Development.d.ts +9 -0
- package/transpiled/directives/dev/Development.js +29 -0
- package/transpiled/directives/dev/Development.js.map +1 -0
- package/transpiled/directives/dev/Stub.d.ts +7 -0
- package/transpiled/directives/dev/Stub.js +14 -0
- package/transpiled/directives/dev/Stub.js.map +1 -0
- package/transpiled/directives/dev/Throw.d.ts +7 -0
- package/transpiled/directives/dev/Throw.js +14 -0
- package/transpiled/directives/dev/Throw.js.map +1 -0
- package/transpiled/directives/dev/index.d.ts +2 -0
- package/transpiled/directives/dev/index.js +6 -0
- package/transpiled/directives/dev/index.js.map +1 -0
- package/transpiled/directives/dev/types.d.ts +4 -0
- package/transpiled/directives/dev/types.js +3 -0
- package/transpiled/directives/dev/types.js.map +1 -0
- package/transpiled/directives/index.d.ts +4 -0
- package/transpiled/directives/index.js +12 -0
- package/transpiled/directives/index.js.map +1 -0
- package/transpiled/directives/octets/Context.d.ts +8 -0
- package/transpiled/directives/octets/Context.js +40 -0
- package/transpiled/directives/octets/Context.js.map +1 -0
- package/transpiled/directives/octets/Delete.d.ts +19 -0
- package/transpiled/directives/octets/Delete.js +72 -0
- package/transpiled/directives/octets/Delete.js.map +1 -0
- package/transpiled/directives/octets/Fetch.d.ts +17 -0
- package/transpiled/directives/octets/Fetch.js +76 -0
- package/transpiled/directives/octets/Fetch.js.map +1 -0
- package/transpiled/directives/octets/List.d.ts +15 -0
- package/transpiled/directives/octets/List.js +65 -0
- package/transpiled/directives/octets/List.js.map +1 -0
- package/transpiled/directives/octets/Octets.d.ts +12 -0
- package/transpiled/directives/octets/Octets.js +53 -0
- package/transpiled/directives/octets/Octets.js.map +1 -0
- package/transpiled/directives/octets/Permute.d.ts +10 -0
- package/transpiled/directives/octets/Permute.js +51 -0
- package/transpiled/directives/octets/Permute.js.map +1 -0
- package/transpiled/directives/octets/Store.d.ts +23 -0
- package/transpiled/directives/octets/Store.js +88 -0
- package/transpiled/directives/octets/Store.js.map +1 -0
- package/transpiled/directives/octets/Workflow.d.ts +14 -0
- package/transpiled/directives/octets/Workflow.js +52 -0
- package/transpiled/directives/octets/Workflow.js.map +1 -0
- package/transpiled/directives/octets/index.d.ts +2 -0
- package/transpiled/directives/octets/index.js +6 -0
- package/transpiled/directives/octets/index.js.map +1 -0
- package/transpiled/directives/octets/schemas.d.ts +13 -0
- package/transpiled/directives/octets/schemas.js +18 -0
- package/transpiled/directives/octets/schemas.js.map +1 -0
- package/transpiled/directives/octets/types.d.ts +10 -0
- package/transpiled/directives/octets/types.js +3 -0
- package/transpiled/directives/octets/types.js.map +1 -0
- package/transpiled/directives/octets/workflows/Execution.d.ts +25 -0
- package/transpiled/directives/octets/workflows/Execution.js +54 -0
- package/transpiled/directives/octets/workflows/Execution.js.map +1 -0
- package/transpiled/directives/octets/workflows/Workflow.d.ts +12 -0
- package/transpiled/directives/octets/workflows/Workflow.js +25 -0
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -0
- package/transpiled/directives/octets/workflows/index.d.ts +1 -0
- package/transpiled/directives/octets/workflows/index.js +6 -0
- package/transpiled/directives/octets/workflows/index.js.map +1 -0
- package/transpiled/directives/vary/Directive.d.ts +5 -0
- package/transpiled/directives/vary/Directive.js +3 -0
- package/transpiled/directives/vary/Directive.js.map +1 -0
- package/transpiled/directives/vary/Embed.d.ts +10 -0
- package/transpiled/directives/vary/Embed.js +49 -0
- package/transpiled/directives/vary/Embed.js.map +1 -0
- package/transpiled/directives/vary/Properties.d.ts +9 -0
- package/transpiled/directives/vary/Properties.js +16 -0
- package/transpiled/directives/vary/Properties.js.map +1 -0
- package/transpiled/directives/vary/Vary.d.ts +10 -0
- package/transpiled/directives/vary/Vary.js +36 -0
- package/transpiled/directives/vary/Vary.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Embedding.d.ts +5 -0
- package/transpiled/directives/vary/embeddings/Embedding.js +3 -0
- package/transpiled/directives/vary/embeddings/Embedding.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Header.d.ts +7 -0
- package/transpiled/directives/vary/embeddings/Header.js +26 -0
- package/transpiled/directives/vary/embeddings/Header.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Language.d.ts +7 -0
- package/transpiled/directives/vary/embeddings/Language.js +28 -0
- package/transpiled/directives/vary/embeddings/Language.js.map +1 -0
- package/transpiled/directives/vary/embeddings/index.d.ts +5 -0
- package/transpiled/directives/vary/embeddings/index.js +10 -0
- package/transpiled/directives/vary/embeddings/index.js.map +1 -0
- package/transpiled/directives/vary/index.d.ts +2 -0
- package/transpiled/directives/vary/index.js +6 -0
- package/transpiled/directives/vary/index.js.map +1 -0
- package/transpiled/discovery.d.ts +1 -0
- package/transpiled/discovery.js +3 -0
- package/transpiled/discovery.js.map +1 -0
- package/transpiled/exceptions.d.ts +2 -0
- package/transpiled/exceptions.js +39 -0
- package/transpiled/exceptions.js.map +1 -0
- package/transpiled/index.d.ts +5 -0
- package/transpiled/index.js +12 -0
- package/transpiled/index.js.map +1 -0
- package/transpiled/io.d.ts +3 -0
- package/transpiled/io.js +3 -0
- package/transpiled/io.js.map +1 -0
- package/transpiled/manifest.d.ts +3 -0
- package/transpiled/manifest.js +66 -0
- package/transpiled/manifest.js.map +1 -0
- package/transpiled/root.d.ts +2 -0
- package/transpiled/root.js +39 -0
- package/transpiled/root.js.map +1 -0
- package/transpiled/schemas.d.ts +7 -0
- package/transpiled/schemas.js +14 -0
- package/transpiled/schemas.js.map +1 -0
- package/transpiled/tsconfig.tsbuildinfo +1 -0
|
@@ -2,7 +2,7 @@ Feature: Octets storage workflows
|
|
|
2
2
|
|
|
3
3
|
Scenario: Running a workflow
|
|
4
4
|
Given the `octets.tester` is running
|
|
5
|
-
|
|
5
|
+
And the annotation:
|
|
6
6
|
"""yaml
|
|
7
7
|
/:
|
|
8
8
|
auth:anonymous: true
|
|
@@ -47,8 +47,8 @@ Feature: Octets storage workflows
|
|
|
47
47
|
"""
|
|
48
48
|
When the following request is received:
|
|
49
49
|
"""
|
|
50
|
-
GET /10cf16b458f759e0d617f2f3d83599ff
|
|
51
|
-
accept: application/yaml
|
|
50
|
+
GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
51
|
+
accept: application/vnd.toa.octets.entry+yaml
|
|
52
52
|
"""
|
|
53
53
|
Then the following reply is sent:
|
|
54
54
|
"""
|
|
@@ -74,7 +74,7 @@ Feature: Octets storage workflows
|
|
|
74
74
|
content-length: 473831
|
|
75
75
|
"""
|
|
76
76
|
|
|
77
|
-
Scenario: Getting error when
|
|
77
|
+
Scenario: Getting error when running workflow on `store`
|
|
78
78
|
Given the `octets.tester` is running
|
|
79
79
|
Given the annotation:
|
|
80
80
|
"""yaml
|
|
@@ -112,3 +112,175 @@ Feature: Octets storage workflows
|
|
|
112
112
|
message: Something went wrong
|
|
113
113
|
--cut--
|
|
114
114
|
"""
|
|
115
|
+
|
|
116
|
+
Scenario: Running a workflow on `delete`
|
|
117
|
+
Given the `octets.tester` is running
|
|
118
|
+
And the annotation:
|
|
119
|
+
"""yaml
|
|
120
|
+
/:
|
|
121
|
+
auth:anonymous: true
|
|
122
|
+
octets:context: octets
|
|
123
|
+
POST:
|
|
124
|
+
octets:store: ~
|
|
125
|
+
/*:
|
|
126
|
+
GET:
|
|
127
|
+
octets:fetch: ~
|
|
128
|
+
DELETE:
|
|
129
|
+
octets:delete:
|
|
130
|
+
workflow:
|
|
131
|
+
echo: octets.tester.echo
|
|
132
|
+
"""
|
|
133
|
+
When the stream of `lenna.ascii` is received with the following headers:
|
|
134
|
+
"""
|
|
135
|
+
POST / HTTP/1.1
|
|
136
|
+
content-type: application/octet-stream
|
|
137
|
+
"""
|
|
138
|
+
Then the following reply is sent:
|
|
139
|
+
"""
|
|
140
|
+
201 Created
|
|
141
|
+
"""
|
|
142
|
+
When the following request is received:
|
|
143
|
+
"""
|
|
144
|
+
DELETE /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
145
|
+
accept: application/yaml
|
|
146
|
+
"""
|
|
147
|
+
Then the following reply is sent:
|
|
148
|
+
"""
|
|
149
|
+
202 Accepted
|
|
150
|
+
content-type: multipart/yaml; boundary=cut
|
|
151
|
+
|
|
152
|
+
--cut
|
|
153
|
+
echo: 10cf16b458f759e0d617f2f3d83599ff
|
|
154
|
+
--cut--
|
|
155
|
+
"""
|
|
156
|
+
When the following request is received:
|
|
157
|
+
"""
|
|
158
|
+
GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
159
|
+
"""
|
|
160
|
+
Then the following reply is sent:
|
|
161
|
+
"""
|
|
162
|
+
404 Not Found
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
Scenario: Error in the workflow on `delete`
|
|
166
|
+
Given the `octets.tester` is running
|
|
167
|
+
And the annotation:
|
|
168
|
+
"""yaml
|
|
169
|
+
/:
|
|
170
|
+
auth:anonymous: true
|
|
171
|
+
octets:context: octets
|
|
172
|
+
POST:
|
|
173
|
+
octets:store: ~
|
|
174
|
+
/*:
|
|
175
|
+
GET:
|
|
176
|
+
octets:fetch: ~
|
|
177
|
+
DELETE:
|
|
178
|
+
octets:delete:
|
|
179
|
+
workflow:
|
|
180
|
+
err: octets.tester.err
|
|
181
|
+
"""
|
|
182
|
+
When the stream of `lenna.ascii` is received with the following headers:
|
|
183
|
+
"""
|
|
184
|
+
POST / HTTP/1.1
|
|
185
|
+
content-type: application/octet-stream
|
|
186
|
+
"""
|
|
187
|
+
Then the following reply is sent:
|
|
188
|
+
"""
|
|
189
|
+
201 Created
|
|
190
|
+
"""
|
|
191
|
+
When the following request is received:
|
|
192
|
+
"""
|
|
193
|
+
DELETE /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
194
|
+
accept: application/yaml
|
|
195
|
+
"""
|
|
196
|
+
Then the following reply is sent:
|
|
197
|
+
"""
|
|
198
|
+
202 Accepted
|
|
199
|
+
content-type: multipart/yaml; boundary=cut
|
|
200
|
+
|
|
201
|
+
--cut
|
|
202
|
+
error:
|
|
203
|
+
step: err
|
|
204
|
+
code: ERROR
|
|
205
|
+
message: Something went wrong
|
|
206
|
+
--cut--
|
|
207
|
+
"""
|
|
208
|
+
When the following request is received:
|
|
209
|
+
"""
|
|
210
|
+
GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
211
|
+
"""
|
|
212
|
+
Then the following reply is sent:
|
|
213
|
+
"""
|
|
214
|
+
200 OK
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
Scenario: Passing parameters to the workflow
|
|
218
|
+
Given the `octets.tester` is running
|
|
219
|
+
And the annotation:
|
|
220
|
+
"""yaml
|
|
221
|
+
/:
|
|
222
|
+
/:a/:b:
|
|
223
|
+
auth:anonymous: true
|
|
224
|
+
octets:context: octets
|
|
225
|
+
POST:
|
|
226
|
+
octets:store:
|
|
227
|
+
workflow:
|
|
228
|
+
concat: octets.tester.concat
|
|
229
|
+
"""
|
|
230
|
+
When the stream of `lenna.ascii` is received with the following headers:
|
|
231
|
+
"""
|
|
232
|
+
POST /hello/world/ HTTP/1.1
|
|
233
|
+
accept: application/yaml
|
|
234
|
+
content-type: application/octet-stream
|
|
235
|
+
"""
|
|
236
|
+
Then the following reply is sent:
|
|
237
|
+
"""
|
|
238
|
+
201 Created
|
|
239
|
+
content-type: multipart/yaml; boundary=cut
|
|
240
|
+
|
|
241
|
+
--cut
|
|
242
|
+
id: 10cf16b458f759e0d617f2f3d83599ff
|
|
243
|
+
type: application/octet-stream
|
|
244
|
+
size: 8169
|
|
245
|
+
--cut
|
|
246
|
+
concat: hello world
|
|
247
|
+
--cut--
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
Scenario: Executing a workflow with `octets:workflow`
|
|
251
|
+
Given the `octets.tester` is running
|
|
252
|
+
And the annotation:
|
|
253
|
+
"""yaml
|
|
254
|
+
/:
|
|
255
|
+
auth:anonymous: true
|
|
256
|
+
octets:context: octets
|
|
257
|
+
POST:
|
|
258
|
+
octets:store: ~
|
|
259
|
+
/*:
|
|
260
|
+
DELETE:
|
|
261
|
+
octets:workflow:
|
|
262
|
+
echo: octets.tester.echo
|
|
263
|
+
"""
|
|
264
|
+
When the stream of `lenna.ascii` is received with the following headers:
|
|
265
|
+
"""
|
|
266
|
+
POST / HTTP/1.1
|
|
267
|
+
content-type: application/octet-stream
|
|
268
|
+
"""
|
|
269
|
+
Then the following reply is sent:
|
|
270
|
+
"""
|
|
271
|
+
201 Created
|
|
272
|
+
"""
|
|
273
|
+
When the following request is received:
|
|
274
|
+
"""
|
|
275
|
+
DELETE /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
|
|
276
|
+
accept: application/yaml
|
|
277
|
+
"""
|
|
278
|
+
Then the following reply is sent:
|
|
279
|
+
"""
|
|
280
|
+
202 Accepted
|
|
281
|
+
content-type: multipart/yaml; boundary=cut
|
|
282
|
+
|
|
283
|
+
--cut
|
|
284
|
+
echo: 10cf16b458f759e0d617f2f3d83599ff
|
|
285
|
+
--cut--
|
|
286
|
+
"""
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Feature: Response
|
|
2
|
+
|
|
3
|
+
Scenario: Content negotiation
|
|
4
|
+
Given the annotation:
|
|
5
|
+
"""yaml
|
|
6
|
+
/:
|
|
7
|
+
GET:
|
|
8
|
+
anonymous: true
|
|
9
|
+
dev:stub: hello
|
|
10
|
+
"""
|
|
11
|
+
When the following request is received:
|
|
12
|
+
"""
|
|
13
|
+
GET / HTTP/1.1
|
|
14
|
+
accept: application/json
|
|
15
|
+
"""
|
|
16
|
+
Then the following reply is sent:
|
|
17
|
+
"""
|
|
18
|
+
200 OK
|
|
19
|
+
content-type: application/json
|
|
20
|
+
vary: accept
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
Scenario: Error as YAML
|
|
24
|
+
Given the `echo` is running with the following manifest:
|
|
25
|
+
"""yaml
|
|
26
|
+
exposition:
|
|
27
|
+
/:
|
|
28
|
+
GET: error
|
|
29
|
+
"""
|
|
30
|
+
When the following request is received:
|
|
31
|
+
"""
|
|
32
|
+
GET /echo/ HTTP/1.1
|
|
33
|
+
accept: application/yaml
|
|
34
|
+
"""
|
|
35
|
+
Then the following reply is sent:
|
|
36
|
+
"""
|
|
37
|
+
409 Conflict
|
|
38
|
+
content-type: application/yaml
|
|
39
|
+
|
|
40
|
+
code: CODE
|
|
41
|
+
message: message
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
Scenario: Error as MessagePack
|
|
45
|
+
Given the `echo` is running with the following manifest:
|
|
46
|
+
"""yaml
|
|
47
|
+
exposition:
|
|
48
|
+
/:
|
|
49
|
+
GET: error
|
|
50
|
+
"""
|
|
51
|
+
When the following request is received:
|
|
52
|
+
"""
|
|
53
|
+
GET /echo/ HTTP/1.1
|
|
54
|
+
accept: application/msgpack
|
|
55
|
+
"""
|
|
56
|
+
Then the following reply is sent:
|
|
57
|
+
"""
|
|
58
|
+
409 Conflict
|
|
59
|
+
content-type: application/msgpack
|
|
60
|
+
"""
|
|
61
|
+
And response body contains MessagePack-encoded value:
|
|
62
|
+
"""yaml
|
|
63
|
+
code: CODE
|
|
64
|
+
message: message
|
|
65
|
+
"""
|
package/features/routes.feature
CHANGED
|
@@ -87,3 +87,40 @@ Feature: Routes
|
|
|
87
87
|
|
|
88
88
|
Hello
|
|
89
89
|
"""
|
|
90
|
+
|
|
91
|
+
Scenario: Routes with naming conflicts
|
|
92
|
+
Given the Gateway is running
|
|
93
|
+
And the `users` is running with the following manifest:
|
|
94
|
+
"""yaml
|
|
95
|
+
exposition:
|
|
96
|
+
/:
|
|
97
|
+
POST: create
|
|
98
|
+
"""
|
|
99
|
+
And the `users.properties` is running with the following manifest:
|
|
100
|
+
"""yaml
|
|
101
|
+
exposition:
|
|
102
|
+
/:id:
|
|
103
|
+
GET: observe
|
|
104
|
+
"""
|
|
105
|
+
When the following request is received:
|
|
106
|
+
"""
|
|
107
|
+
GET /users/properties/b5534021e30042259badffbd1831e472/ HTTP/1.1
|
|
108
|
+
accept: application/yaml
|
|
109
|
+
"""
|
|
110
|
+
Then the following reply is sent:
|
|
111
|
+
"""
|
|
112
|
+
200 OK
|
|
113
|
+
|
|
114
|
+
newbie: false
|
|
115
|
+
"""
|
|
116
|
+
When the following request is received:
|
|
117
|
+
"""
|
|
118
|
+
POST /users/ HTTP/1.1
|
|
119
|
+
content-type: application/yaml
|
|
120
|
+
|
|
121
|
+
name: Alice
|
|
122
|
+
"""
|
|
123
|
+
Then the following reply is sent:
|
|
124
|
+
"""
|
|
125
|
+
201 Created
|
|
126
|
+
"""
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as assert from 'node:assert'
|
|
1
2
|
import { after, binding, given } from 'cucumber-tsflow'
|
|
2
3
|
import * as boot from '@toa.io/boot'
|
|
3
4
|
import { timeout } from '@toa.io/generic'
|
|
@@ -8,7 +9,7 @@ import { Workspace } from './Workspace'
|
|
|
8
9
|
@binding([Workspace])
|
|
9
10
|
export class Components {
|
|
10
11
|
private readonly workspace: Workspace
|
|
11
|
-
private
|
|
12
|
+
private compositions: Record<string, Connector> = {}
|
|
12
13
|
|
|
13
14
|
public constructor (workspace: Workspace) {
|
|
14
15
|
this.workspace = workspace
|
|
@@ -26,18 +27,29 @@ export class Components {
|
|
|
26
27
|
await this.runComponent(name, manifest)
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
@after()
|
|
30
30
|
@given('the `{word}` is stopped')
|
|
31
|
-
public async stop (
|
|
32
|
-
|
|
31
|
+
public async stop (name: string): Promise<void> {
|
|
32
|
+
assert.ok(name in this.compositions, `Composition '${name}' is not running`)
|
|
33
|
+
|
|
34
|
+
await this.compositions[name].disconnect()
|
|
35
|
+
delete this.compositions[name]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@after()
|
|
39
|
+
public async shutdown (): Promise<void> {
|
|
40
|
+
const promises = Object.values(this.compositions).map((composition) => composition.disconnect())
|
|
41
|
+
|
|
42
|
+
await Promise.all(promises)
|
|
33
43
|
}
|
|
34
44
|
|
|
35
45
|
private async runComponent (name: string, manifest?: object): Promise<void> {
|
|
46
|
+
assert.ok(!(name in this.compositions), `Composition '${name}' is already running`)
|
|
47
|
+
|
|
36
48
|
const path = await this.workspace.addComponent(name, manifest)
|
|
37
49
|
|
|
38
|
-
this.
|
|
50
|
+
this.compositions[name] = await boot.composition([path])
|
|
39
51
|
|
|
40
|
-
await this.
|
|
52
|
+
await this.compositions[name].connect()
|
|
41
53
|
await timeout(50) // discovery
|
|
42
54
|
}
|
|
43
55
|
}
|
|
@@ -18,8 +18,7 @@ export class Gateway {
|
|
|
18
18
|
const annotation = parse(yaml)
|
|
19
19
|
|
|
20
20
|
if ('/' in annotation) {
|
|
21
|
-
const
|
|
22
|
-
const tree = syntax.parse(node, shortcuts)
|
|
21
|
+
const tree = syntax.parse(annotation['/'], shortcuts)
|
|
23
22
|
|
|
24
23
|
process.env.TOA_EXPOSITION = encode(tree)
|
|
25
24
|
}
|
package/features/steps/HTTP.ts
CHANGED
|
@@ -1,121 +1,74 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as assert from 'node:assert'
|
|
2
|
+
import * as fs from 'node:fs'
|
|
3
|
+
import * as path from 'node:path'
|
|
2
4
|
import { binding, then, when } from 'cucumber-tsflow'
|
|
3
|
-
import * as http from '@toa.io/
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import * as http from '@toa.io/agent'
|
|
6
|
+
import * as msgpack from 'msgpackr'
|
|
7
|
+
import * as YAML from 'js-yaml'
|
|
8
|
+
import { Captures } from './Captures'
|
|
7
9
|
import { Parameters } from './Parameters'
|
|
8
10
|
import { Gateway } from './Gateway'
|
|
11
|
+
import type { Readable } from 'node:stream'
|
|
9
12
|
|
|
10
|
-
@binding([Gateway, Parameters])
|
|
11
|
-
export class HTTP {
|
|
13
|
+
@binding([Gateway, Parameters, Captures])
|
|
14
|
+
export class HTTP extends http.Agent {
|
|
12
15
|
private readonly gateway: Gateway
|
|
13
|
-
private
|
|
14
|
-
private response: string = ''
|
|
15
|
-
private readonly variables: Record<string, string> = {}
|
|
16
|
+
private fetched: Response | null = null
|
|
16
17
|
|
|
17
|
-
public constructor (gateway: Gateway, parameters: Parameters) {
|
|
18
|
+
public constructor (gateway: Gateway, parameters: Parameters, captures: Captures) {
|
|
19
|
+
super(parameters.origin, captures)
|
|
18
20
|
this.gateway = gateway
|
|
19
|
-
this.origin = parameters.origin
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
@when('the following request is received:')
|
|
23
|
-
public async request (input: string): Promise<any> {
|
|
24
|
-
let [headers, body] = trim(input).split('\n\n')
|
|
25
|
-
|
|
26
|
-
if (body !== undefined)
|
|
27
|
-
headers += '\ncontent-length: ' + body?.length
|
|
28
|
-
|
|
29
|
-
const text = headers + '\n\n' + (body ?? '')
|
|
30
|
-
const request = text.replaceAll(SUBSTITUTE, (_, name) => this.variables[name])
|
|
31
|
-
|
|
24
|
+
public override async request (input: string): Promise<any> {
|
|
32
25
|
await this.gateway.start()
|
|
33
|
-
|
|
34
|
-
this.response = await http.request(request, this.origin)
|
|
26
|
+
this.fetched = await super.request(input)
|
|
35
27
|
}
|
|
36
28
|
|
|
37
29
|
@then('the following reply is sent:')
|
|
38
|
-
public responseIncludes (expected: string): void {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
for (const line of lines) {
|
|
42
|
-
const escaped = line.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
43
|
-
|
|
44
|
-
const expression = escaped.replace(CAPTURE,
|
|
45
|
-
(_, name) => `(?<${name}>\\S{1,2048})`)
|
|
30
|
+
public override responseIncludes (expected: string): void {
|
|
31
|
+
super.responseIncludes(expected)
|
|
32
|
+
}
|
|
46
33
|
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
@then('response body contains {word}-encoded value:')
|
|
35
|
+
public async bodyIs (format: string, yaml: string): Promise<void> {
|
|
36
|
+
assert.ok(this.fetched !== null, 'Response is null')
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
expected: line,
|
|
54
|
-
actual: this.response
|
|
55
|
-
})
|
|
38
|
+
const buf = await this.fetched.arrayBuffer()
|
|
39
|
+
const value = encoders[format]?.(buf as Buffer)
|
|
40
|
+
const expected = YAML.load(yaml)
|
|
56
41
|
|
|
57
|
-
|
|
58
|
-
}
|
|
42
|
+
assert.deepEqual(value, expected, 'Values are not equal')
|
|
59
43
|
}
|
|
60
44
|
|
|
61
45
|
@then('the reply does not contain:')
|
|
62
|
-
public responseExcludes (expected: string): void {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
for (const line of lines) {
|
|
66
|
-
line.replace(SUBSTITUTE, (_, name) => this.variables[name])
|
|
67
|
-
|
|
68
|
-
const includes = this.response.includes(line)
|
|
69
|
-
|
|
70
|
-
if (includes)
|
|
71
|
-
throw new AssertionError({
|
|
72
|
-
message: `Response contains '${line}'`,
|
|
73
|
-
expected: line,
|
|
74
|
-
actual: this.response
|
|
75
|
-
})
|
|
76
|
-
}
|
|
46
|
+
public override responseExcludes (expected: string): void {
|
|
47
|
+
super.responseExcludes(expected)
|
|
77
48
|
}
|
|
78
49
|
|
|
79
50
|
@when('the stream of `{word}` is received with the following headers:')
|
|
80
51
|
public async streamRequest (filename: string, head: string): Promise<any> {
|
|
81
|
-
|
|
52
|
+
const stream = open(filename)
|
|
82
53
|
|
|
83
54
|
await this.gateway.start()
|
|
84
|
-
|
|
85
|
-
const { url, method, headers } = http.parse.request(head)
|
|
86
|
-
const href = new URL(url, this.origin).href
|
|
87
|
-
const body = open(filename)
|
|
88
|
-
|
|
89
|
-
headers.connection = 'close' // required for interrupted streams
|
|
90
|
-
|
|
91
|
-
const request = {
|
|
92
|
-
method,
|
|
93
|
-
headers,
|
|
94
|
-
body: body as unknown as ReadableStream,
|
|
95
|
-
duplex: 'half'
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
const response = await fetch(href, request)
|
|
100
|
-
|
|
101
|
-
this.response = await http.parse.response(response)
|
|
102
|
-
} catch (e: any) {
|
|
103
|
-
console.error(e)
|
|
104
|
-
console.error(e.cause)
|
|
105
|
-
|
|
106
|
-
throw e
|
|
107
|
-
}
|
|
55
|
+
await super.stream(head, stream)
|
|
108
56
|
}
|
|
109
57
|
|
|
110
58
|
@then('the stream equals to `{word}` is sent with the following headers:')
|
|
111
59
|
public async responseStreamMatch (filename: string, head: string): Promise<any> {
|
|
112
|
-
const
|
|
113
|
-
const text = buf.toString('utf8')
|
|
114
|
-
const expected = head + '\n\n' + text
|
|
60
|
+
const stream = open(filename)
|
|
115
61
|
|
|
116
|
-
|
|
62
|
+
await super.streamMatch(head, stream)
|
|
117
63
|
}
|
|
118
64
|
}
|
|
119
65
|
|
|
120
|
-
const
|
|
121
|
-
|
|
66
|
+
const FILEDIR = path.resolve(__dirname, '../../../storages/source/test')
|
|
67
|
+
|
|
68
|
+
function open (filename: string): Readable {
|
|
69
|
+
return fs.createReadStream(path.join(FILEDIR, filename))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const encoders: Record<string, (buf: Buffer | Uint8Array) => any> = {
|
|
73
|
+
MessagePack: msgpack.decode
|
|
74
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { once } from 'node:events'
|
|
2
|
+
import * as crypto from 'node:crypto'
|
|
3
|
+
import * as http from 'node:http'
|
|
4
|
+
import * as assert from 'node:assert'
|
|
5
|
+
import * as util from 'node:util'
|
|
6
|
+
import { binding, given, afterAll } from 'cucumber-tsflow'
|
|
7
|
+
import { Captures } from './Captures'
|
|
8
|
+
|
|
9
|
+
import type { AddressInfo } from 'node:net'
|
|
10
|
+
|
|
11
|
+
@binding([Captures])
|
|
12
|
+
export class IdP {
|
|
13
|
+
private static server?: http.Server
|
|
14
|
+
private static privateKey?: crypto.KeyObject
|
|
15
|
+
private static issuer?: string
|
|
16
|
+
|
|
17
|
+
public constructor (private readonly captures: Captures) {}
|
|
18
|
+
|
|
19
|
+
@afterAll()
|
|
20
|
+
public static async stop (): Promise<void> {
|
|
21
|
+
if (this.server instanceof http.Server) {
|
|
22
|
+
this.server.close()
|
|
23
|
+
await once(this.server, 'close')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@given(/local IDP is running/i)
|
|
28
|
+
public async start (): Promise<void> {
|
|
29
|
+
if (IdP.server instanceof http.Server) return
|
|
30
|
+
|
|
31
|
+
// creating the key
|
|
32
|
+
const { publicKey, privateKey } = await util.promisify(crypto.generateKeyPair)('rsa', {
|
|
33
|
+
modulusLength: 2048
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
IdP.privateKey = privateKey
|
|
37
|
+
|
|
38
|
+
const jwk = JSON.stringify({
|
|
39
|
+
keys: [{ use: 'sig', alg: 'RS256', ...publicKey.export({ format: 'jwk' }) }]
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const JWK_URL = '/.well-known/jwks'
|
|
43
|
+
|
|
44
|
+
const server = http.createServer((request, response) => {
|
|
45
|
+
switch (request.url) {
|
|
46
|
+
case JWK_URL:
|
|
47
|
+
response.writeHead(200, {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
'Content-Length': jwk.length,
|
|
50
|
+
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
51
|
+
Pragma: 'no-cache',
|
|
52
|
+
Expires: '0'
|
|
53
|
+
})
|
|
54
|
+
response.end(jwk)
|
|
55
|
+
break
|
|
56
|
+
|
|
57
|
+
case '/.well-known/openid-configuration':
|
|
58
|
+
{
|
|
59
|
+
const openIdConfiguration = JSON.stringify({
|
|
60
|
+
issuer: IdP.issuer,
|
|
61
|
+
jwks_uri: IdP.issuer + JWK_URL,
|
|
62
|
+
response_types_supported: ['id_token'],
|
|
63
|
+
subject_types_supported: ['public'],
|
|
64
|
+
id_token_signing_alg_values_supported: ['RS256'],
|
|
65
|
+
scopes_supported: ['openid']
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
response.writeHead(200, {
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
'Cache-Control': 'public, max-age=3600',
|
|
71
|
+
'Content-Length': openIdConfiguration.length
|
|
72
|
+
})
|
|
73
|
+
response.end(openIdConfiguration)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
default:
|
|
79
|
+
response.writeHead(404, 'Not found')
|
|
80
|
+
response.end()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
server.listen(44444, 'localhost')
|
|
85
|
+
await once(server, 'listening')
|
|
86
|
+
|
|
87
|
+
const address = server.address() as AddressInfo
|
|
88
|
+
|
|
89
|
+
console.log('IdP is listening on %s:%s', address.address, address.port)
|
|
90
|
+
IdP.server = server
|
|
91
|
+
IdP.issuer = `http://localhost:${address.port}`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@given('the IDP token for {word} is issued')
|
|
95
|
+
public async issueToken (user: string): Promise<void> {
|
|
96
|
+
assert.ok(IdP.privateKey, 'IdP private key is not available')
|
|
97
|
+
|
|
98
|
+
const jwt = [
|
|
99
|
+
{
|
|
100
|
+
typ: 'JWT',
|
|
101
|
+
alg: 'RS256'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
iss: IdP.issuer,
|
|
105
|
+
sub: `${user}-mock-id`,
|
|
106
|
+
aud: 'test',
|
|
107
|
+
iat: Math.floor(Date.now() / 1000),
|
|
108
|
+
exp: Math.floor((Date.now() + 1000 * 60 * 5) / 1000)
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
.map((v) => Buffer.from(JSON.stringify(v)).toString('base64url'))
|
|
112
|
+
.join('.')
|
|
113
|
+
|
|
114
|
+
const signature = crypto.createSign('RSA-SHA256').end(jwt).sign(IdP.privateKey, 'base64url')
|
|
115
|
+
|
|
116
|
+
const idToken = `${jwt}.${signature}`
|
|
117
|
+
|
|
118
|
+
this.captures.set(`${user}.id_token`, idToken)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@given('the IDP {word} token for {word} is issued with following secret:')
|
|
122
|
+
public async issueSymmetricToken (alg: string, user: string, secret: string): Promise<void> {
|
|
123
|
+
console.log('Sym token for %s with secret "%s"', user, secret)
|
|
124
|
+
|
|
125
|
+
const jwt = [
|
|
126
|
+
{
|
|
127
|
+
typ: 'JWT',
|
|
128
|
+
alg
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
iss: IdP.issuer,
|
|
132
|
+
sub: `${user}-mock-id`,
|
|
133
|
+
aud: 'test',
|
|
134
|
+
iat: Math.floor(Date.now() / 1000),
|
|
135
|
+
exp: Math.floor((Date.now() + 1000 * 60 * 5) / 1000)
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
.map((v) => Buffer.from(JSON.stringify(v)).toString('base64url'))
|
|
139
|
+
.join('.')
|
|
140
|
+
|
|
141
|
+
const signature = crypto.createHmac(alg.replace(/^HS(\d{3})$/, 'sha$1'), secret)
|
|
142
|
+
.update(jwt)
|
|
143
|
+
.digest('base64url')
|
|
144
|
+
|
|
145
|
+
const idToken = `${jwt}.${signature}`
|
|
146
|
+
|
|
147
|
+
this.captures.set(`${user}.id_token`, idToken)
|
|
148
|
+
}
|
|
149
|
+
}
|