@toa.io/extensions.exposition 1.0.0-alpha.6 → 1.0.0-alpha.60
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/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/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 +5 -7
- package/components/octets.storage/operations/store.js +105 -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 +64 -23
- package/documentation/protocol.md +3 -0
- 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 +5 -0
- 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/octets.download.feature +117 -0
- package/features/octets.entries.feature +8 -1
- package/features/octets.feature +58 -64
- 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/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/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 +1 -0
- package/features/timing.feature +27 -1
- package/features/vary.feature +71 -0
- package/package.json +22 -14
- package/readme.md +19 -14
- package/schemas/annotation.cos.yaml +1 -1
- package/schemas/node.cos.yaml +1 -0
- package/schemas/octets/store.cos.yaml +1 -0
- package/schemas/query.cos.yaml +4 -10
- package/source/Annotation.ts +3 -3
- package/source/Composition.ts +2 -2
- package/source/Directive.ts +4 -5
- package/source/Endpoint.ts +48 -12
- package/source/Factory.ts +10 -11
- package/source/Gateway.ts +49 -20
- package/source/HTTP/Context.ts +24 -2
- package/source/HTTP/Server.ts +50 -43
- package/source/HTTP/exceptions.ts +7 -1
- package/source/HTTP/formats/index.ts +3 -3
- package/source/HTTP/messages.test.ts +39 -2
- package/source/HTTP/messages.ts +7 -3
- 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 +32 -22
- 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/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 +2 -2
- package/source/directives/octets/Context.ts +4 -3
- package/source/directives/octets/Delete.ts +4 -2
- package/source/directives/octets/Directive.ts +10 -0
- package/source/directives/octets/Fetch.ts +14 -12
- package/source/directives/octets/List.ts +9 -7
- package/source/directives/octets/Octets.ts +4 -5
- package/source/directives/octets/Store.ts +21 -8
- package/source/directives/octets/Workflow.ts +10 -3
- package/source/directives/octets/schemas.ts +4 -4
- package/source/directives/octets/types.ts +0 -7
- package/source/directives/octets/workflows/Execution.ts +59 -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 +22 -11
- package/source/manifest.ts +10 -11
- package/source/schemas.ts +1 -1
- package/transpiled/Annotation.d.ts +3 -3
- package/transpiled/Composition.js +2 -2
- 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 +28 -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 +15 -2
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +13 -2
- package/transpiled/HTTP/Server.js +37 -35
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/exceptions.d.ts +4 -1
- package/transpiled/HTTP/exceptions.js +7 -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 +9 -3
- 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/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/octets/Context.d.ts +3 -3
- package/transpiled/directives/octets/Context.js +4 -2
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Delete.d.ts +3 -2
- package/transpiled/directives/octets/Delete.js +3 -1
- package/transpiled/directives/octets/Delete.js.map +1 -1
- package/transpiled/directives/octets/Directive.d.ts +8 -0
- package/transpiled/directives/octets/Directive.js +8 -0
- package/transpiled/directives/octets/Directive.js.map +1 -0
- package/transpiled/directives/octets/Fetch.d.ts +6 -5
- package/transpiled/directives/octets/Fetch.js +10 -8
- package/transpiled/directives/octets/Fetch.js.map +1 -1
- package/transpiled/directives/octets/List.d.ts +6 -5
- package/transpiled/directives/octets/List.js +6 -4
- package/transpiled/directives/octets/List.js.map +1 -1
- package/transpiled/directives/octets/Octets.d.ts +2 -1
- package/transpiled/directives/octets/Octets.js +2 -4
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Store.d.ts +6 -3
- package/transpiled/directives/octets/Store.js +12 -6
- package/transpiled/directives/octets/Store.js.map +1 -1
- package/transpiled/directives/octets/Workflow.d.ts +3 -2
- package/transpiled/directives/octets/Workflow.js +9 -2
- package/transpiled/directives/octets/Workflow.js.map +1 -1
- package/transpiled/directives/octets/schemas.d.ts +4 -4
- package/transpiled/directives/octets/schemas.js.map +1 -1
- package/transpiled/directives/octets/types.d.ts +0 -5
- package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
- package/transpiled/directives/octets/workflows/Execution.js +43 -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 +13 -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/source/HTTP/Server.test.ts +0 -126
- package/source/directives/octets/Permute.ts +0 -43
- package/transpiled/directives/octets/Permute.d.ts +0 -10
- package/transpiled/directives/octets/Permute.js +0 -56
- package/transpiled/directives/octets/Permute.js.map +0 -1
- /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
package/source/Gateway.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { type bindings, Connector } from '@toa.io/core'
|
|
2
3
|
import * as http from './HTTP'
|
|
3
4
|
import { rethrow } from './exceptions'
|
|
4
5
|
import type { Interception } from './Interception'
|
|
5
|
-
import type { Method, Parameter, Tree } from './RTD'
|
|
6
|
+
import type { Node, Method, Parameter, Tree, Match } from './RTD'
|
|
6
7
|
import type { Label } from './discovery'
|
|
7
8
|
import type { Branch } from './Branch'
|
|
8
9
|
|
|
@@ -22,34 +23,30 @@ export class Gateway extends Connector {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
public async process (context: http.Context): Promise<http.OutgoingMessage> {
|
|
25
|
-
const interception = await context.timing.capture('
|
|
26
|
+
const interception = await context.timing.capture('intercept',
|
|
26
27
|
this.interceptor.intercept(context))
|
|
27
28
|
|
|
28
29
|
if (interception !== null)
|
|
29
30
|
return interception
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
if (match === null)
|
|
34
|
-
throw new http.NotFound()
|
|
32
|
+
const { node, parameters } = this.match(context)
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
node,
|
|
38
|
-
parameters
|
|
39
|
-
} = match
|
|
34
|
+
if (context.request.method === 'OPTIONS')
|
|
35
|
+
return await this.explain(node, parameters)
|
|
40
36
|
|
|
41
37
|
if (!(context.request.method in node.methods))
|
|
42
38
|
throw new http.MethodNotAllowed()
|
|
43
39
|
|
|
44
40
|
const method = node.methods[context.request.method]
|
|
45
41
|
|
|
46
|
-
const interruption = await context.timing.capture('
|
|
47
|
-
method.directives.preflight(context, parameters))
|
|
42
|
+
const interruption = await context.timing.capture('preflight',
|
|
43
|
+
method.directives.preflight(context, parameters)).catch(rethrow)
|
|
48
44
|
|
|
49
45
|
const response = interruption ??
|
|
50
|
-
await context.timing.capture('
|
|
46
|
+
await context.timing.capture('call', this.call(method, context, parameters))
|
|
51
47
|
|
|
52
|
-
await context.timing.capture('
|
|
48
|
+
await context.timing.capture('settle',
|
|
49
|
+
method.directives.settle(context, response)).catch(rethrow)
|
|
53
50
|
|
|
54
51
|
return response
|
|
55
52
|
}
|
|
@@ -57,17 +54,41 @@ export class Gateway extends Connector {
|
|
|
57
54
|
protected override async open (): Promise<void> {
|
|
58
55
|
await this.discover()
|
|
59
56
|
|
|
60
|
-
console.info('Gateway has started and is awaiting resource branches
|
|
57
|
+
console.info('Gateway has started and is awaiting resource branches')
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
protected override dispose (): void {
|
|
64
|
-
console.info('Gateway is closed
|
|
61
|
+
console.info('Gateway is closed')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private match (context: http.Context): Match {
|
|
65
|
+
const match = this.tree.match(context.url.pathname)
|
|
66
|
+
|
|
67
|
+
if (match === null)
|
|
68
|
+
throw new http.NotFound('Route not found')
|
|
69
|
+
|
|
70
|
+
if (match.node.forward === null)
|
|
71
|
+
return match
|
|
72
|
+
|
|
73
|
+
const destination = match.node.forward.replace(/\/:([^/]+)/g,
|
|
74
|
+
(_, name) => {
|
|
75
|
+
const value = match.parameters.find((parameter) => parameter.name === name)?.value
|
|
76
|
+
|
|
77
|
+
assert.ok(value !== undefined, `Forwarded parameter '${name}' not found`)
|
|
78
|
+
|
|
79
|
+
return `/${value}`
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const forward = this.tree.match(destination)
|
|
83
|
+
|
|
84
|
+
assert.ok(forward !== null, 'Forwarded route not found')
|
|
85
|
+
|
|
86
|
+
return forward
|
|
65
87
|
}
|
|
66
88
|
|
|
67
|
-
private async call (method: Method, context: http.Context, parameters: Parameter[]):
|
|
68
|
-
Promise<http.OutgoingMessage> {
|
|
89
|
+
private async call (method: Method, context: http.Context, parameters: Parameter[]): Promise<http.OutgoingMessage> {
|
|
69
90
|
if (context.url.pathname[context.url.pathname.length - 1] !== '/')
|
|
70
|
-
throw new http.NotFound('Trailing slash is required
|
|
91
|
+
throw new http.NotFound('Trailing slash is required')
|
|
71
92
|
|
|
72
93
|
if (context.encoder === null)
|
|
73
94
|
throw new http.NotAcceptable()
|
|
@@ -80,6 +101,14 @@ export class Gateway extends Connector {
|
|
|
80
101
|
.catch(rethrow) as http.OutgoingMessage
|
|
81
102
|
}
|
|
82
103
|
|
|
104
|
+
private async explain (node: Node, parameters: Parameter[]): Promise<http.OutgoingMessage> {
|
|
105
|
+
const body = await node.explain(parameters)
|
|
106
|
+
const allow = [...Object.keys(node.methods)].join(', ')
|
|
107
|
+
const headers = new Headers({ allow })
|
|
108
|
+
|
|
109
|
+
return { body, headers }
|
|
110
|
+
}
|
|
111
|
+
|
|
83
112
|
private async discover (): Promise<void> {
|
|
84
113
|
await this.broadcast.receive<Branch>('expose', this.merge.bind(this))
|
|
85
114
|
await this.broadcast.transmit<null>('ping', null)
|
|
@@ -90,7 +119,7 @@ export class Gateway extends Connector {
|
|
|
90
119
|
this.tree.merge(branch.node, branch)
|
|
91
120
|
|
|
92
121
|
console.info('Resource branch of ' +
|
|
93
|
-
`'${branch.namespace}.${branch.component}' has been merged
|
|
122
|
+
`'${branch.namespace}.${branch.component}' has been merged`)
|
|
94
123
|
} catch (exception) {
|
|
95
124
|
console.error(exception)
|
|
96
125
|
}
|
package/source/HTTP/Context.ts
CHANGED
|
@@ -6,22 +6,29 @@ import type { OutgoingMessage } from './messages'
|
|
|
6
6
|
import type * as http from 'node:http'
|
|
7
7
|
|
|
8
8
|
export class Context {
|
|
9
|
+
public readonly authority: string
|
|
9
10
|
public readonly request: IncomingMessage
|
|
10
11
|
public readonly url: URL
|
|
11
12
|
public readonly subtype: string | null = null
|
|
12
13
|
public readonly encoder: Format | null = null
|
|
13
14
|
public readonly timing: Timing
|
|
15
|
+
public readonly debug: boolean
|
|
14
16
|
|
|
15
17
|
public readonly pipelines: Pipelines = {
|
|
16
18
|
body: [],
|
|
17
19
|
response: []
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
public constructor (request: IncomingMessage,
|
|
22
|
+
public constructor (authority: string, request: IncomingMessage, properties: Properties) {
|
|
23
|
+
this.authority = authority
|
|
21
24
|
this.request = request
|
|
22
25
|
|
|
23
26
|
this.url = new URL(request.url, `https://${request.headers.host}`)
|
|
24
|
-
this.timing = new Timing(trace)
|
|
27
|
+
this.timing = new Timing(properties.trace)
|
|
28
|
+
this.debug = properties.debug
|
|
29
|
+
|
|
30
|
+
if (this.debug)
|
|
31
|
+
this.log(request)
|
|
25
32
|
|
|
26
33
|
if (this.request.headers.accept !== undefined) {
|
|
27
34
|
const match = SUBTYPE.exec(this.request.headers.accept)
|
|
@@ -52,6 +59,16 @@ export class Context {
|
|
|
52
59
|
? value
|
|
53
60
|
: this.pipelines.body.reduce((value, transform) => transform(value), value)
|
|
54
61
|
}
|
|
62
|
+
|
|
63
|
+
private log (request: IncomingMessage): void {
|
|
64
|
+
const message = `${request.method} ${request.url}`
|
|
65
|
+
const headers = { ...request.headers }
|
|
66
|
+
|
|
67
|
+
if (headers.authorization !== undefined)
|
|
68
|
+
headers.authorization = headers.authorization.slice(0, headers.authorization.indexOf(' '))
|
|
69
|
+
|
|
70
|
+
console.debug(message, headers)
|
|
71
|
+
}
|
|
55
72
|
}
|
|
56
73
|
|
|
57
74
|
export interface IncomingMessage extends http.IncomingMessage {
|
|
@@ -64,4 +81,9 @@ interface Pipelines {
|
|
|
64
81
|
response: Array<(output: OutgoingMessage) => void>
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
interface Properties {
|
|
85
|
+
debug: boolean
|
|
86
|
+
trace: boolean
|
|
87
|
+
}
|
|
88
|
+
|
|
67
89
|
const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/
|
package/source/HTTP/Server.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import * as http from 'node:http'
|
|
4
|
-
import assert from 'node:assert'
|
|
5
4
|
import { once } from 'node:events'
|
|
5
|
+
import { setTimeout } from 'node:timers/promises'
|
|
6
6
|
import { Connector } from '@toa.io/core'
|
|
7
|
-
import { promex } from '@toa.io/generic'
|
|
8
7
|
import { type OutgoingMessage, write } from './messages'
|
|
9
8
|
import { ClientError, Exception } from './exceptions'
|
|
10
9
|
import { Context } from './Context'
|
|
@@ -13,32 +12,22 @@ import type { IncomingMessage } from './Context'
|
|
|
13
12
|
export class Server extends Connector {
|
|
14
13
|
private readonly server: http.Server = http.createServer()
|
|
15
14
|
private readonly properties: Properties
|
|
15
|
+
private readonly authorities: Record<string, string>
|
|
16
16
|
private process?: Processing
|
|
17
|
+
private ready: boolean = false
|
|
18
|
+
private startedAt: number = 0
|
|
17
19
|
|
|
18
20
|
private constructor (properties: Properties) {
|
|
19
21
|
super()
|
|
20
22
|
|
|
21
23
|
this.properties = properties
|
|
24
|
+
this.authorities = Object.fromEntries(Object.entries(properties.authorities).map(([key, value]) => [value, key]))
|
|
22
25
|
|
|
23
26
|
this.server.on('request', (req, res) => this.listener(req, res))
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
public
|
|
27
|
-
|
|
28
|
-
return this.properties.port
|
|
29
|
-
|
|
30
|
-
const address = this.server.address()
|
|
31
|
-
|
|
32
|
-
if (address === null || typeof address === 'string')
|
|
33
|
-
throw new Error('Server is not listening on a port.')
|
|
34
|
-
|
|
35
|
-
return address.port
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public static create (options?: Partial<Properties>): Server {
|
|
39
|
-
const properties = options === undefined
|
|
40
|
-
? DEFAULTS
|
|
41
|
-
: { ...DEFAULTS, ...options }
|
|
29
|
+
public static create (options: Options): Server {
|
|
30
|
+
const properties: Properties = Object.assign({}, DEFAULTS, options)
|
|
42
31
|
|
|
43
32
|
return new Server(properties)
|
|
44
33
|
}
|
|
@@ -48,21 +37,29 @@ export class Server extends Connector {
|
|
|
48
37
|
}
|
|
49
38
|
|
|
50
39
|
protected override async open (): Promise<void> {
|
|
40
|
+
this.startedAt = Date.now()
|
|
51
41
|
this.server.listen(this.properties.port)
|
|
52
42
|
|
|
53
43
|
await once(this.server, 'listening')
|
|
54
44
|
|
|
55
|
-
console.info('HTTP Server is listening
|
|
45
|
+
console.info('HTTP Server is listening')
|
|
46
|
+
|
|
47
|
+
await setTimeout(this.properties.delay)
|
|
48
|
+
|
|
49
|
+
this.ready = true
|
|
50
|
+
|
|
51
|
+
console.info('Ready')
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
protected override async close (): Promise<void> {
|
|
59
55
|
this.server.close()
|
|
56
|
+
this.ready = false
|
|
60
57
|
|
|
61
|
-
console.info('HTTP Server stopped accepting new connections
|
|
58
|
+
console.info('HTTP Server stopped accepting new connections')
|
|
62
59
|
|
|
63
60
|
await once(this.server, 'close')
|
|
64
61
|
|
|
65
|
-
console.info('HTTP Server has been stopped
|
|
62
|
+
console.info('HTTP Server has been stopped')
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
private listener (request: http.IncomingMessage, response: http.ServerResponse): void {
|
|
@@ -72,18 +69,23 @@ export class Server extends Connector {
|
|
|
72
69
|
return
|
|
73
70
|
}
|
|
74
71
|
|
|
75
|
-
if (request.url ===
|
|
76
|
-
|
|
72
|
+
if (request.url === '/.ready') {
|
|
73
|
+
if (this.ready)
|
|
74
|
+
response.writeHead(200, { 'cache-control': 'no-store' }).end()
|
|
75
|
+
else {
|
|
76
|
+
const remaining = (Math.ceil((Date.now() - this.startedAt) / 1000)).toString()
|
|
77
|
+
|
|
78
|
+
response.writeHead(503, { 'retry-after': remaining }).end()
|
|
79
|
+
}
|
|
77
80
|
|
|
78
81
|
return
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const context = new Context(request as IncomingMessage, this.properties.trace)
|
|
84
|
+
const host = request.headers.host!
|
|
85
|
+
const authority = this.authorities[host] ?? host
|
|
86
|
+
const context = new Context(authority, request as IncomingMessage, this.properties)
|
|
85
87
|
|
|
86
|
-
this.process(context)
|
|
88
|
+
this.process!(context)
|
|
87
89
|
.then(this.success(context, response))
|
|
88
90
|
.catch(this.fail(context, response))
|
|
89
91
|
}
|
|
@@ -112,17 +114,15 @@ export class Server extends Connector {
|
|
|
112
114
|
if (!context.request.complete)
|
|
113
115
|
await adam(context.request)
|
|
114
116
|
|
|
115
|
-
response.statusCode = exception instanceof Exception
|
|
116
|
-
? exception.status
|
|
117
|
-
: 500
|
|
117
|
+
response.statusCode = exception instanceof Exception ? exception.status : 500
|
|
118
118
|
|
|
119
119
|
const message: OutgoingMessage = { status: response.statusCode }
|
|
120
|
-
const verbose = exception instanceof ClientError || this.properties.debug
|
|
121
120
|
|
|
122
|
-
if (
|
|
123
|
-
message.body =
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
if (exception instanceof ClientError || this.properties.debug)
|
|
122
|
+
message.body =
|
|
123
|
+
exception instanceof Exception
|
|
124
|
+
? exception.body
|
|
125
|
+
: exception.stack ?? exception.message
|
|
126
126
|
|
|
127
127
|
write(context, response, message)
|
|
128
128
|
}
|
|
@@ -131,28 +131,35 @@ export class Server extends Connector {
|
|
|
131
131
|
|
|
132
132
|
// https://github.com/whatwg/fetch/issues/1254
|
|
133
133
|
async function adam (request: http.IncomingMessage): Promise<void> {
|
|
134
|
-
const completed = promex()
|
|
135
134
|
const devnull = fs.createWriteStream(os.devNull)
|
|
136
135
|
|
|
137
|
-
request
|
|
138
|
-
.on('end', completed.callback)
|
|
139
|
-
.pipe(devnull)
|
|
136
|
+
request.pipe(devnull)
|
|
140
137
|
|
|
141
|
-
|
|
138
|
+
await once(request, 'end')
|
|
142
139
|
}
|
|
143
140
|
|
|
144
|
-
const
|
|
141
|
+
export const PORT = 8000
|
|
142
|
+
export const DELAY = 3 // seconds
|
|
143
|
+
|
|
144
|
+
const DEFAULTS: Omit<Properties, 'authorities'> = {
|
|
145
145
|
methods: new Set<string>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']),
|
|
146
146
|
debug: false,
|
|
147
147
|
trace: false,
|
|
148
|
-
port:
|
|
148
|
+
port: PORT,
|
|
149
|
+
delay: DELAY * 1000
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
interface Properties {
|
|
153
|
+
authorities: Record<string, string>
|
|
152
154
|
methods: Set<string>
|
|
153
155
|
debug: boolean
|
|
154
156
|
trace: boolean
|
|
155
157
|
port: number
|
|
158
|
+
delay: number
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export type Options = { authorities: Properties['authorities'] } & {
|
|
162
|
+
[K in Exclude<keyof Properties, 'authorities'>]?: Properties[K]
|
|
156
163
|
}
|
|
157
164
|
|
|
158
165
|
export type Processing = (input: Context) => Promise<OutgoingMessage>
|
|
@@ -37,11 +37,17 @@ export class NotFound extends ClientError {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export class Conflict extends ClientError {
|
|
40
|
-
public constructor (body
|
|
40
|
+
public constructor (body?: any) {
|
|
41
41
|
super(409, body)
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export class UnprocessableEntity extends ClientError {
|
|
46
|
+
public constructor (body?: any) {
|
|
47
|
+
super(422, body)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
export class MethodNotAllowed extends ClientError {
|
|
46
52
|
public constructor () {
|
|
47
53
|
super(405)
|
|
@@ -5,10 +5,10 @@ import * as msgpack from './msgpack'
|
|
|
5
5
|
import * as text from './text'
|
|
6
6
|
|
|
7
7
|
export const formats: Record<string, Format> = {
|
|
8
|
-
[msgpack.type]: msgpack,
|
|
9
|
-
[yaml.type]: yaml,
|
|
10
8
|
[json.type]: json,
|
|
11
|
-
[
|
|
9
|
+
[yaml.type]: yaml,
|
|
10
|
+
[text.type]: text,
|
|
11
|
+
[msgpack.type]: msgpack
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const types = Object.keys(formats)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { Readable } from 'node:stream'
|
|
1
|
+
import { PassThrough, Readable } from 'node:stream'
|
|
2
|
+
import * as streamConsumers from 'node:stream/consumers'
|
|
3
|
+
import { once } from 'node:events'
|
|
2
4
|
import { generate } from 'randomstring'
|
|
3
5
|
import * as msgpack from 'msgpackr'
|
|
4
|
-
import { read } from './messages'
|
|
6
|
+
import { multipart, read, type OutgoingMessage } from './messages'
|
|
5
7
|
import { BadRequest, UnsupportedMediaType } from './exceptions'
|
|
8
|
+
import { formats } from './formats'
|
|
6
9
|
import { Timing } from './Timing'
|
|
10
|
+
import type * as http from 'node:http'
|
|
7
11
|
import type { Context } from './Context'
|
|
8
12
|
|
|
9
13
|
beforeEach(() => {
|
|
@@ -69,6 +73,39 @@ describe('read', () => {
|
|
|
69
73
|
|
|
70
74
|
await expect(read(request)).rejects.toThrow(BadRequest)
|
|
71
75
|
})
|
|
76
|
+
|
|
77
|
+
it('should output correct mulitpart format', async () => {
|
|
78
|
+
const response = new class extends PassThrough {
|
|
79
|
+
public readonly headers = new Headers()
|
|
80
|
+
|
|
81
|
+
public setHeader (key: string, value: string): this {
|
|
82
|
+
this.headers.set(key, value)
|
|
83
|
+
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
}()
|
|
87
|
+
|
|
88
|
+
const context = { encoder: formats['text/plain'] } as unknown as Context
|
|
89
|
+
const message = { body: Readable.from(['Hello', 'New', 'World']) } as unknown as OutgoingMessage
|
|
90
|
+
|
|
91
|
+
multipart(message, context, response as unknown as http.ServerResponse)
|
|
92
|
+
|
|
93
|
+
await once(message.body, 'end')
|
|
94
|
+
|
|
95
|
+
const result = await streamConsumers.text(response)
|
|
96
|
+
|
|
97
|
+
expect(result).toBe([
|
|
98
|
+
'--cut',
|
|
99
|
+
'',
|
|
100
|
+
'Hello',
|
|
101
|
+
'--cut',
|
|
102
|
+
'',
|
|
103
|
+
'New',
|
|
104
|
+
'--cut',
|
|
105
|
+
'',
|
|
106
|
+
'World',
|
|
107
|
+
'--cut--'].join('\r\n'))
|
|
108
|
+
})
|
|
72
109
|
})
|
|
73
110
|
|
|
74
111
|
export function createContext
|
package/source/HTTP/messages.ts
CHANGED
|
@@ -29,7 +29,7 @@ export async function read (context: Context): Promise<any> {
|
|
|
29
29
|
throw new UnsupportedMediaType()
|
|
30
30
|
|
|
31
31
|
const format = formats[type]
|
|
32
|
-
const buf = await context.timing.capture('
|
|
32
|
+
const buf = await context.timing.capture('buffer', buffer(context.request))
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
35
|
return format.decode(buf)
|
|
@@ -72,7 +72,7 @@ function stream
|
|
|
72
72
|
})
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function multipart
|
|
75
|
+
export function multipart
|
|
76
76
|
(message: OutgoingMessage, context: Context, response: http.ServerResponse): void {
|
|
77
77
|
if (context.encoder === null)
|
|
78
78
|
throw new NotAcceptable()
|
|
@@ -82,7 +82,11 @@ function multipart
|
|
|
82
82
|
response.setHeader('content-type', `${encoder.multipart}; boundary=${BOUNDARY}`)
|
|
83
83
|
|
|
84
84
|
message.body
|
|
85
|
-
.map((part: unknown) => Buffer.concat([
|
|
85
|
+
.map((part: unknown) => Buffer.concat([
|
|
86
|
+
CUT,
|
|
87
|
+
CRLF /* indicates no boundary headers */,
|
|
88
|
+
encoder.encode(part),
|
|
89
|
+
CRLF]))
|
|
86
90
|
.on('end', () => response.end(FINALCUT))
|
|
87
91
|
.pipe(response)
|
|
88
92
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Remote } from '@toa.io/core'
|
|
2
|
+
|
|
3
|
+
export interface Introspection {
|
|
4
|
+
route?: Record<string, Schema>
|
|
5
|
+
query?: Record<string, Schema>
|
|
6
|
+
input?: Schema
|
|
7
|
+
output?: Schema
|
|
8
|
+
errors?: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Schema = Awaited<ReturnType<Remote['explain']>>['input']
|
package/source/Mapping.ts
CHANGED
|
@@ -1,50 +1,92 @@
|
|
|
1
1
|
import { type Parameter } from './RTD'
|
|
2
2
|
import { Query } from './Query'
|
|
3
|
+
import type { Introspection, Schema } from './Introspection'
|
|
4
|
+
import type { QueryString } from './Query'
|
|
3
5
|
import type * as http from './HTTP'
|
|
4
6
|
import type * as syntax from './RTD/syntax'
|
|
5
7
|
import type * as core from '@toa.io/core'
|
|
6
8
|
|
|
7
9
|
export abstract class Mapping {
|
|
8
|
-
|
|
9
|
-
if (query === undefined || query === null)
|
|
10
|
-
return new InputMapping()
|
|
10
|
+
protected readonly query: Query
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
public constructor (query: Query) {
|
|
13
|
+
this.query = query
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public static create (query?: syntax.Query | null): Mapping {
|
|
17
|
+
const q = new Query(query!)
|
|
13
18
|
|
|
14
|
-
return
|
|
19
|
+
return queryable(query)
|
|
20
|
+
? new QueryableMapping(q)
|
|
21
|
+
: new InputMapping(q)
|
|
15
22
|
}
|
|
16
23
|
|
|
17
|
-
public
|
|
24
|
+
public explain (introspection: Introspection): Record<string, Schema> | null {
|
|
25
|
+
return this.query.explain(introspection)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected assign (input: any, qs: QueryString): void {
|
|
29
|
+
if (qs.parameters !== null) {
|
|
30
|
+
if (typeof input !== 'object' || input === null)
|
|
31
|
+
throw new Error('Input must be an object to embed query parameters')
|
|
32
|
+
|
|
33
|
+
Object.assign(input, qs.parameters)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public abstract fit (input: any, query: http.Query, parameters: Parameter[]): core.Request
|
|
18
38
|
}
|
|
19
39
|
|
|
20
40
|
class QueryableMapping extends Mapping {
|
|
21
|
-
|
|
41
|
+
public fit (input: any, query: http.Query, parameters: Parameter[]): core.Request {
|
|
42
|
+
const request: core.Request = {}
|
|
43
|
+
const qs = this.query.fit(query, parameters)
|
|
22
44
|
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
if (input === undefined && qs.parameters !== null)
|
|
46
|
+
input = {}
|
|
25
47
|
|
|
26
|
-
this.
|
|
27
|
-
}
|
|
48
|
+
this.assign(input, qs)
|
|
28
49
|
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
if (input !== undefined)
|
|
51
|
+
request.input = input
|
|
31
52
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
if (qs.query !== null)
|
|
54
|
+
request.query = qs.query
|
|
55
|
+
|
|
56
|
+
return request
|
|
36
57
|
}
|
|
37
58
|
}
|
|
38
59
|
|
|
39
60
|
class InputMapping extends Mapping {
|
|
40
|
-
public fit (input: any,
|
|
41
|
-
|
|
61
|
+
public fit (input: any, query: http.Query, parameters: Parameter[]): core.Request {
|
|
62
|
+
const request: core.Request = {}
|
|
63
|
+
const qs = this.query.fit(query, parameters)
|
|
64
|
+
|
|
65
|
+
if (input === undefined && (parameters.length > 0 || qs.parameters !== null))
|
|
42
66
|
input = {}
|
|
43
67
|
|
|
44
|
-
if (
|
|
68
|
+
if (parameters.length > 0) {
|
|
69
|
+
if (typeof input !== 'object' || input === null)
|
|
70
|
+
throw new Error('Input must be an object to embed route parameters')
|
|
71
|
+
|
|
45
72
|
for (const parameter of parameters)
|
|
46
73
|
input[parameter.name] = parameter.value
|
|
74
|
+
}
|
|
47
75
|
|
|
48
|
-
|
|
76
|
+
this.assign(input, qs)
|
|
77
|
+
|
|
78
|
+
if (input !== undefined)
|
|
79
|
+
request.input = input
|
|
80
|
+
|
|
81
|
+
return request
|
|
49
82
|
}
|
|
50
83
|
}
|
|
84
|
+
|
|
85
|
+
export function queryable (query?: syntax.Query | null): boolean {
|
|
86
|
+
if (query === undefined || query === null)
|
|
87
|
+
return false
|
|
88
|
+
|
|
89
|
+
const keys = Object.keys(query)
|
|
90
|
+
|
|
91
|
+
return !(keys.length === 1 && keys[0] === 'parameters')
|
|
92
|
+
}
|
package/source/Query.test.ts
CHANGED
|
@@ -16,7 +16,7 @@ it('should combine request criteria', async () => {
|
|
|
16
16
|
const instance = new Query(query)
|
|
17
17
|
const result = instance.fit({ criteria: 'qux==4' }, parameters)
|
|
18
18
|
|
|
19
|
-
expect(result.criteria).toStrictEqual('(
|
|
19
|
+
expect(result.query!.criteria).toStrictEqual('(bar==2;baz==3);(foo==1);(qux==4)')
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
it('should set id parameter as query.id', async () => {
|
|
@@ -32,6 +32,6 @@ it('should set id parameter as query.id', async () => {
|
|
|
32
32
|
const instance = new Query(query)
|
|
33
33
|
const result = instance.fit({}, parameters)
|
|
34
34
|
|
|
35
|
-
expect(result.criteria).toBeUndefined()
|
|
36
|
-
expect(result.id).toStrictEqual(id)
|
|
35
|
+
expect(result.query!.criteria).toBeUndefined()
|
|
36
|
+
expect(result.query!.id).toStrictEqual(id)
|
|
37
37
|
})
|