@toa.io/extensions.exposition 1.0.0-alpha.7 → 1.0.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/context.toa.yaml +2 -2
- package/components/identity.bans/manifest.toa.yaml +15 -7
- package/components/identity.bans/operations/transit.d.ts +14 -0
- package/components/identity.bans/operations/transit.js +11 -0
- package/components/identity.bans/operations/transit.js.map +1 -0
- package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.bans/source/transit.ts +21 -0
- package/components/identity.bans/tsconfig.json +9 -0
- package/components/identity.basic/manifest.toa.yaml +21 -10
- package/components/identity.basic/operations/authenticate.d.ts +5 -1
- package/components/identity.basic/operations/authenticate.js +5 -2
- package/components/identity.basic/operations/authenticate.js.map +1 -1
- package/components/identity.basic/operations/incept.d.ts +12 -0
- package/components/identity.basic/operations/incept.js +26 -0
- package/components/identity.basic/operations/incept.js.map +1 -0
- package/components/identity.basic/operations/transit.d.ts +4 -4
- package/components/identity.basic/operations/transit.js +5 -3
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +8 -4
- package/components/identity.basic/source/authenticate.ts +16 -5
- package/components/identity.basic/source/incept.ts +38 -0
- package/components/identity.basic/source/transit.ts +8 -6
- package/components/identity.basic/source/types.ts +8 -4
- package/components/identity.federation/manifest.toa.yaml +32 -16
- package/components/identity.federation/operations/authenticate.d.ts +2 -2
- package/components/identity.federation/operations/authenticate.js +4 -11
- package/components/identity.federation/operations/authenticate.js.map +1 -1
- package/components/identity.federation/operations/incept.d.ts +11 -0
- package/components/identity.federation/operations/{create.js → incept.js} +6 -7
- package/components/identity.federation/operations/incept.js.map +1 -0
- package/components/identity.federation/operations/lib/assertions-as-values.js +2 -1
- package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -1
- package/components/identity.federation/operations/lib/jwt.d.ts +5 -5
- package/components/identity.federation/operations/lib/jwt.js +25 -12
- package/components/identity.federation/operations/lib/jwt.js.map +1 -1
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +14 -0
- package/components/identity.federation/operations/types/configuration.js +3 -0
- package/components/identity.federation/operations/types/configuration.js.map +1 -0
- package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +15 -7
- package/components/identity.federation/operations/types/context.js +3 -0
- package/components/identity.federation/operations/types/context.js.map +1 -0
- package/components/identity.federation/operations/types/entity.d.ts +6 -0
- package/components/identity.federation/operations/types/entity.js +3 -0
- package/components/identity.federation/operations/types/entity.js.map +1 -0
- package/components/identity.federation/operations/types/index.d.ts +3 -0
- package/components/identity.federation/operations/types/index.js +20 -0
- package/components/identity.federation/operations/types/index.js.map +1 -0
- package/components/identity.federation/source/authenticate.ts +6 -19
- package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
- package/components/identity.federation/source/lib/assertions-as-values.ts +4 -2
- package/components/identity.federation/source/lib/jwt.test.ts +123 -4
- package/components/identity.federation/source/lib/jwt.ts +36 -16
- package/components/identity.federation/source/types/configuration.ts +15 -0
- package/components/identity.federation/source/{types.ts → types/context.ts} +17 -6
- package/components/identity.federation/source/types/entity.ts +6 -0
- package/components/identity.federation/source/types/index.ts +3 -0
- package/components/identity.federation/tsconfig.json +5 -4
- package/components/identity.roles/manifest.toa.yaml +18 -7
- package/components/identity.roles/operations/grant.d.ts +10 -0
- package/components/identity.roles/operations/grant.js +21 -0
- package/components/identity.roles/operations/grant.js.map +1 -0
- package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
- package/components/identity.roles/operations/lib/Entity.js +3 -0
- package/components/identity.roles/operations/lib/Entity.js.map +1 -0
- package/components/identity.roles/operations/list.d.ts +1 -4
- package/components/identity.roles/operations/list.js.map +1 -1
- package/components/identity.roles/operations/principal.d.ts +4 -6
- package/components/identity.roles/operations/principal.js +6 -1
- package/components/identity.roles/operations/principal.js.map +1 -1
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/source/grant.ts +32 -0
- package/components/identity.roles/source/lib/Entity.ts +5 -0
- package/components/identity.roles/source/list.ts +2 -4
- package/components/identity.roles/source/principal.ts +10 -8
- package/components/identity.tokens/manifest.toa.yaml +19 -5
- package/components/identity.tokens/operations/authenticate.d.ts +2 -2
- package/components/identity.tokens/operations/authenticate.js +12 -5
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.js +1 -0
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.js +5 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/operations/types.d.ts +8 -2
- package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
- package/components/identity.tokens/source/authenticate.test.ts +11 -4
- package/components/identity.tokens/source/authenticate.ts +14 -6
- package/components/identity.tokens/source/decrypt.test.ts +5 -3
- package/components/identity.tokens/source/decrypt.ts +9 -8
- package/components/identity.tokens/source/encrypt.test.ts +26 -2
- package/components/identity.tokens/source/encrypt.ts +5 -1
- package/components/identity.tokens/source/types.ts +9 -2
- package/components/octets.storage/manifest.toa.yaml +6 -7
- package/components/octets.storage/operations/get.js +2 -2
- package/components/octets.storage/operations/store.js +113 -3
- package/documentation/access.md +75 -38
- package/documentation/authorities.md +49 -0
- package/documentation/cache.md +8 -1
- package/documentation/components.md +47 -22
- package/documentation/flow.md +31 -0
- package/documentation/identity.md +17 -22
- package/documentation/introspection.md +82 -0
- package/documentation/octets.md +81 -23
- package/documentation/protocol.md +13 -3
- package/documentation/query.md +29 -4
- package/documentation/require.md +15 -0
- package/documentation/tree.md +13 -0
- package/documentation/vary.md +14 -14
- package/features/access.feature +78 -46
- package/features/annotation.feature +1 -0
- package/features/auth.claim.feature +170 -0
- package/features/authorities.basic.feature +141 -0
- package/features/authorities.feature +32 -0
- package/features/authorities.federation.feature +100 -0
- package/features/authorities.tokens.feature +117 -0
- package/features/body.feature +3 -0
- package/features/cache.feature +109 -5
- package/features/cors.feature +6 -1
- package/features/debug.feature +34 -0
- package/features/directives.feature +3 -0
- package/features/dynamic.feature +4 -0
- package/features/errors.feature +20 -7
- package/features/etag.feature +31 -0
- package/features/flow.feature +45 -0
- package/features/identity.bans.feature +137 -0
- package/features/identity.basic.feature +125 -23
- package/features/identity.feature +7 -2
- package/features/identity.federation.feature +66 -11
- package/features/identity.roles.feature +250 -7
- package/features/identity.tokens.feature +54 -4
- package/features/introspection.feature +153 -0
- package/features/io.feature +38 -1
- package/features/methods.feature +47 -0
- package/features/octets.download.feature +189 -0
- package/features/octets.entries.feature +8 -1
- package/features/octets.feature +82 -54
- package/features/octets.meta.feature +3 -0
- package/features/octets.workflows.feature +239 -19
- package/features/probes.feature +14 -0
- package/features/{queries.feature → query.feature} +65 -2
- package/features/realtime.feature +34 -0
- package/features/require.feature +67 -0
- package/features/response.feature +38 -3
- package/features/routes.feature +93 -2
- package/features/steps/Database.ts +17 -10
- package/features/steps/Gateway.ts +23 -6
- package/features/steps/IdP.ts +30 -25
- package/features/steps/Parameters.ts +4 -1
- package/features/steps/Realtime.ts +151 -0
- package/features/steps/components/echo/manifest.toa.yaml +14 -1
- package/features/steps/components/echo/operations/identity.js +7 -0
- package/features/steps/components/echo/operations/parameters.js +7 -0
- package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
- package/features/steps/components/echo.beacon/operations/hello.js +5 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +22 -1
- package/features/steps/components/octets.tester/operations/authority.js +7 -0
- package/features/steps/components/octets.tester/operations/baz.js +1 -2
- package/features/steps/components/octets.tester/operations/diversify.js +3 -1
- package/features/steps/components/octets.tester/operations/foo.js +2 -2
- package/features/steps/components/octets.tester/operations/redirect.js +12 -0
- package/features/steps/components/octets.tester/operations/yex.js +16 -0
- package/features/steps/components/octets.tester/operations/yield.js +13 -0
- package/features/steps/components/pots/manifest.toa.yaml +14 -3
- package/features/steps/components/users/manifest.toa.yaml +0 -1
- package/features/steps/components/users.properties/manifest.toa.yaml +1 -1
- package/features/streams.feature +5 -0
- package/features/timing.feature +4 -1
- package/features/vary.feature +71 -0
- package/package.json +23 -14
- package/readme.md +19 -14
- package/schemas/annotation.cos.yaml +1 -1
- package/schemas/method.cos.yaml +1 -1
- package/schemas/node.cos.yaml +1 -0
- package/schemas/octets/store.cos.yaml +25 -3
- package/schemas/query.cos.yaml +4 -10
- package/source/Annotation.ts +3 -3
- package/source/Composition.ts +0 -6
- package/source/Directive.ts +4 -5
- package/source/Endpoint.ts +52 -12
- package/source/Factory.ts +10 -11
- package/source/Gateway.ts +48 -19
- package/source/HTTP/Context.ts +25 -2
- package/source/HTTP/Server.ts +52 -44
- package/source/HTTP/exceptions.ts +13 -1
- package/source/HTTP/formats/index.ts +3 -3
- package/source/HTTP/messages.test.ts +45 -2
- package/source/HTTP/messages.ts +23 -5
- package/source/Introspection.ts +11 -0
- package/source/Mapping.ts +63 -21
- package/source/Query.test.ts +3 -3
- package/source/Query.ts +117 -33
- package/source/RTD/Endpoint.ts +3 -0
- package/source/RTD/Method.ts +16 -0
- package/source/RTD/Node.ts +29 -13
- package/source/RTD/Route.ts +5 -4
- package/source/RTD/factory.ts +5 -2
- package/source/RTD/syntax/parse.ts +37 -24
- package/source/RTD/syntax/types.ts +6 -4
- package/source/Remotes.ts +2 -9
- package/source/Tenant.ts +0 -8
- package/source/deployment.ts +33 -23
- package/source/directives/auth/Authorization.ts +37 -14
- package/source/directives/auth/Delegate.ts +42 -0
- package/source/directives/auth/Federation.ts +84 -0
- package/source/directives/auth/Incept.ts +4 -3
- package/source/directives/auth/Role.test.ts +53 -6
- package/source/directives/auth/Role.ts +22 -14
- package/source/directives/auth/split.ts +1 -1
- package/source/directives/auth/types.ts +1 -1
- package/source/directives/cache/Cache.ts +13 -6
- package/source/directives/cache/Control.ts +42 -16
- package/source/directives/cors/CORS.ts +1 -1
- package/source/directives/dev/Development.ts +1 -1
- package/source/directives/flow/Fetch.ts +88 -0
- package/source/directives/flow/Flow.ts +34 -0
- package/source/directives/flow/index.ts +3 -0
- package/source/directives/flow/types.ts +6 -0
- package/source/directives/index.ts +3 -1
- package/source/directives/io/Input.ts +4 -4
- package/source/directives/io/Output.ts +4 -3
- package/source/directives/octets/Context.ts +3 -2
- package/source/directives/octets/Fetch.ts +11 -10
- package/source/directives/octets/List.ts +5 -5
- package/source/directives/octets/Octets.ts +1 -3
- package/source/directives/octets/Store.ts +30 -10
- package/source/directives/octets/bytes.test.ts +30 -0
- package/source/directives/octets/bytes.ts +18 -0
- package/source/directives/octets/schemas.ts +4 -6
- package/source/directives/octets/workflows/Execution.ts +60 -8
- package/source/directives/octets/workflows/Workflow.ts +2 -1
- package/source/directives/require/Directive.ts +5 -0
- package/source/directives/require/Headers.ts +20 -0
- package/source/directives/require/Require.ts +28 -0
- package/source/directives/require/index.ts +3 -0
- package/source/directives/vary/Directive.ts +2 -1
- package/source/directives/vary/Embed.ts +14 -8
- package/source/directives/vary/Vary.ts +6 -4
- package/source/directives/vary/embeddings/Authority.ts +8 -0
- package/source/directives/vary/embeddings/Embedding.ts +2 -1
- package/source/directives/vary/embeddings/Parameter.ts +14 -0
- package/source/directives/vary/embeddings/index.ts +6 -4
- package/source/exceptions.ts +23 -11
- package/source/manifest.ts +10 -11
- package/source/schemas.ts +1 -1
- package/transpiled/Annotation.d.ts +3 -3
- package/transpiled/Composition.d.ts +0 -1
- package/transpiled/Composition.js +0 -4
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Directive.js +4 -4
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +6 -4
- package/transpiled/Endpoint.js +32 -4
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/Factory.js +9 -8
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +2 -0
- package/transpiled/Gateway.js +36 -12
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +8 -1
- package/transpiled/HTTP/Context.js +16 -2
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +13 -2
- package/transpiled/HTTP/Server.js +39 -36
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/exceptions.d.ts +7 -1
- package/transpiled/HTTP/exceptions.js +13 -1
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/HTTP/formats/index.js +3 -3
- package/transpiled/HTTP/formats/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +1 -0
- package/transpiled/HTTP/messages.js +24 -5
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Introspection.d.ts +9 -0
- package/transpiled/Introspection.js +3 -0
- package/transpiled/Introspection.js.map +1 -0
- package/transpiled/Mapping.d.ts +10 -2
- package/transpiled/Mapping.js +48 -19
- package/transpiled/Mapping.js.map +1 -1
- package/transpiled/Query.d.ts +10 -1
- package/transpiled/Query.js +83 -30
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Endpoint.d.ts +1 -0
- package/transpiled/RTD/Method.d.ts +4 -0
- package/transpiled/RTD/Method.js +11 -0
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.d.ts +4 -1
- package/transpiled/RTD/Node.js +23 -12
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.d.ts +1 -1
- package/transpiled/RTD/Route.js +0 -1
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/factory.js +5 -2
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/RTD/syntax/parse.js +34 -22
- package/transpiled/RTD/syntax/parse.js.map +1 -1
- package/transpiled/RTD/syntax/types.d.ts +5 -3
- package/transpiled/RTD/syntax/types.js +1 -1
- package/transpiled/RTD/syntax/types.js.map +1 -1
- package/transpiled/Remotes.d.ts +2 -4
- package/transpiled/Remotes.js +0 -5
- package/transpiled/Remotes.js.map +1 -1
- package/transpiled/Tenant.d.ts +0 -1
- package/transpiled/Tenant.js +0 -6
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/deployment.d.ts +1 -1
- package/transpiled/deployment.js +28 -20
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +26 -10
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.d.ts +10 -0
- package/transpiled/directives/auth/Delegate.js +34 -0
- package/transpiled/directives/auth/Delegate.js.map +1 -0
- package/transpiled/directives/auth/Federation.d.ts +16 -0
- package/transpiled/directives/auth/Federation.js +57 -0
- package/transpiled/directives/auth/Federation.js.map +1 -0
- package/transpiled/directives/auth/Incept.js +4 -3
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Role.d.ts +4 -1
- package/transpiled/directives/auth/Role.js +20 -14
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/split.js +1 -1
- package/transpiled/directives/auth/split.js.map +1 -1
- package/transpiled/directives/cache/Cache.d.ts +3 -3
- package/transpiled/directives/cache/Cache.js +10 -4
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.d.ts +2 -1
- package/transpiled/directives/cache/Control.js +29 -12
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/cors/CORS.js +1 -1
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/dev/Development.js +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/flow/Fetch.d.ts +13 -0
- package/transpiled/directives/flow/Fetch.js +59 -0
- package/transpiled/directives/flow/Fetch.js.map +1 -0
- package/transpiled/directives/flow/Flow.d.ts +10 -0
- package/transpiled/directives/flow/Flow.js +27 -0
- package/transpiled/directives/flow/Flow.js.map +1 -0
- package/transpiled/directives/flow/index.d.ts +2 -0
- package/transpiled/directives/flow/index.js +6 -0
- package/transpiled/directives/flow/index.js.map +1 -0
- package/transpiled/directives/flow/types.d.ts +5 -0
- package/transpiled/directives/flow/types.js.map +1 -0
- package/transpiled/directives/index.js +3 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/Input.js +2 -2
- package/transpiled/directives/io/Input.js.map +1 -1
- package/transpiled/directives/io/Output.js +2 -2
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/octets/Context.js +4 -24
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Fetch.d.ts +3 -3
- package/transpiled/directives/octets/Fetch.js +8 -8
- package/transpiled/directives/octets/Fetch.js.map +1 -1
- package/transpiled/directives/octets/List.d.ts +3 -3
- package/transpiled/directives/octets/List.js +3 -3
- package/transpiled/directives/octets/List.js.map +1 -1
- package/transpiled/directives/octets/Octets.js +1 -3
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Store.d.ts +6 -1
- package/transpiled/directives/octets/Store.js +17 -7
- package/transpiled/directives/octets/Store.js.map +1 -1
- package/transpiled/directives/octets/bytes.d.ts +1 -0
- package/transpiled/directives/octets/bytes.js +21 -0
- package/transpiled/directives/octets/bytes.js.map +1 -0
- package/transpiled/directives/octets/schemas.d.ts +4 -6
- package/transpiled/directives/octets/schemas.js +1 -3
- package/transpiled/directives/octets/schemas.js.map +1 -1
- package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
- package/transpiled/directives/octets/workflows/Execution.js +44 -9
- package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
- package/transpiled/directives/octets/workflows/Workflow.js +2 -1
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
- package/transpiled/directives/require/Directive.d.ts +4 -0
- package/transpiled/directives/require/Directive.js +3 -0
- package/transpiled/directives/require/Directive.js.map +1 -0
- package/transpiled/directives/require/Headers.d.ts +7 -0
- package/transpiled/directives/require/Headers.js +19 -0
- package/transpiled/directives/require/Headers.js.map +1 -0
- package/transpiled/directives/require/Require.d.ts +9 -0
- package/transpiled/directives/require/Require.js +27 -0
- package/transpiled/directives/require/Require.js.map +1 -0
- package/transpiled/directives/require/index.d.ts +2 -0
- package/transpiled/directives/require/index.js +6 -0
- package/transpiled/directives/require/index.js.map +1 -0
- package/transpiled/directives/vary/Directive.d.ts +2 -1
- package/transpiled/directives/vary/Embed.d.ts +2 -1
- package/transpiled/directives/vary/Embed.js +8 -6
- package/transpiled/directives/vary/Embed.js.map +1 -1
- package/transpiled/directives/vary/Vary.d.ts +2 -2
- package/transpiled/directives/vary/Vary.js +3 -3
- package/transpiled/directives/vary/Vary.js.map +1 -1
- package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
- package/transpiled/directives/vary/embeddings/Authority.js +10 -0
- package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
- package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
- package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
- package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
- package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
- package/transpiled/directives/vary/embeddings/index.js +8 -4
- package/transpiled/directives/vary/embeddings/index.js.map +1 -1
- package/transpiled/exceptions.d.ts +3 -2
- package/transpiled/exceptions.js +14 -7
- package/transpiled/exceptions.js.map +1 -1
- package/transpiled/manifest.js +10 -11
- package/transpiled/manifest.js.map +1 -1
- package/transpiled/schemas.d.ts +1 -1
- package/transpiled/schemas.js +2 -2
- package/transpiled/schemas.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
- package/tsconfig.json +9 -7
- package/components/identity.basic/operations/create.d.ts +0 -10
- package/components/identity.basic/operations/create.js +0 -10
- package/components/identity.basic/operations/create.js.map +0 -1
- package/components/identity.basic/source/create.ts +0 -18
- package/components/identity.federation/operations/create.d.ts +0 -10
- package/components/identity.federation/operations/create.js.map +0 -1
- package/components/identity.federation/operations/schemas.d.ts +0 -59
- package/components/identity.federation/operations/schemas.js +0 -9
- package/components/identity.federation/operations/schemas.js.map +0 -1
- package/components/identity.federation/operations/types.js.map +0 -1
- package/components/identity.federation/source/schemas.ts +0 -61
- package/components/octets.storage/operations/permute.js +0 -7
- package/schemas/octets/context.cos.yaml +0 -1
- package/source/HTTP/Server.test.ts +0 -126
- package/source/directives/octets/Permute.ts +0 -44
- package/transpiled/directives/octets/Permute.d.ts +0 -11
- package/transpiled/directives/octets/Permute.js +0 -58
- package/transpiled/directives/octets/Permute.js.map +0 -1
- /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
package/source/HTTP/Server.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import * as http from 'node:http'
|
|
4
|
-
import assert from 'node:assert'
|
|
5
4
|
import { once } from 'node:events'
|
|
5
|
+
import { setTimeout } from 'node:timers/promises'
|
|
6
|
+
import { console } from 'openspan'
|
|
6
7
|
import { Connector } from '@toa.io/core'
|
|
7
|
-
import { promex } from '@toa.io/generic'
|
|
8
8
|
import { type OutgoingMessage, write } from './messages'
|
|
9
9
|
import { ClientError, Exception } from './exceptions'
|
|
10
10
|
import { Context } from './Context'
|
|
@@ -13,32 +13,22 @@ import type { IncomingMessage } from './Context'
|
|
|
13
13
|
export class Server extends Connector {
|
|
14
14
|
private readonly server: http.Server = http.createServer()
|
|
15
15
|
private readonly properties: Properties
|
|
16
|
+
private readonly authorities: Record<string, string>
|
|
16
17
|
private process?: Processing
|
|
18
|
+
private ready: boolean = false
|
|
19
|
+
private startedAt: number = 0
|
|
17
20
|
|
|
18
21
|
private constructor (properties: Properties) {
|
|
19
22
|
super()
|
|
20
23
|
|
|
21
24
|
this.properties = properties
|
|
25
|
+
this.authorities = Object.fromEntries(Object.entries(properties.authorities).map(([key, value]) => [value, key]))
|
|
22
26
|
|
|
23
27
|
this.server.on('request', (req, res) => this.listener(req, res))
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
public
|
|
27
|
-
|
|
28
|
-
return this.properties.port
|
|
29
|
-
|
|
30
|
-
const address = this.server.address()
|
|
31
|
-
|
|
32
|
-
if (address === null || typeof address === 'string')
|
|
33
|
-
throw new Error('Server is not listening on a port.')
|
|
34
|
-
|
|
35
|
-
return address.port
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public static create (options?: Partial<Properties>): Server {
|
|
39
|
-
const properties = options === undefined
|
|
40
|
-
? DEFAULTS
|
|
41
|
-
: { ...DEFAULTS, ...options }
|
|
30
|
+
public static create (options: Options): Server {
|
|
31
|
+
const properties: Properties = Object.assign({}, DEFAULTS, options)
|
|
42
32
|
|
|
43
33
|
return new Server(properties)
|
|
44
34
|
}
|
|
@@ -48,21 +38,29 @@ export class Server extends Connector {
|
|
|
48
38
|
}
|
|
49
39
|
|
|
50
40
|
protected override async open (): Promise<void> {
|
|
41
|
+
this.startedAt = Date.now()
|
|
51
42
|
this.server.listen(this.properties.port)
|
|
52
43
|
|
|
53
44
|
await once(this.server, 'listening')
|
|
54
45
|
|
|
55
|
-
console.info('HTTP Server is listening
|
|
46
|
+
console.info('HTTP Server is listening')
|
|
47
|
+
|
|
48
|
+
await setTimeout(this.properties.delay)
|
|
49
|
+
|
|
50
|
+
this.ready = true
|
|
51
|
+
|
|
52
|
+
console.info('Ready')
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
protected override async close (): Promise<void> {
|
|
59
56
|
this.server.close()
|
|
57
|
+
this.ready = false
|
|
60
58
|
|
|
61
|
-
console.info('
|
|
59
|
+
console.info('Stopped accepting new connections')
|
|
62
60
|
|
|
63
61
|
await once(this.server, 'close')
|
|
64
62
|
|
|
65
|
-
console.info('
|
|
63
|
+
console.info('Stopped')
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
private listener (request: http.IncomingMessage, response: http.ServerResponse): void {
|
|
@@ -72,18 +70,23 @@ export class Server extends Connector {
|
|
|
72
70
|
return
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
if (request.url ===
|
|
76
|
-
|
|
73
|
+
if (request.url === '/.ready') {
|
|
74
|
+
if (this.ready)
|
|
75
|
+
response.writeHead(200, { 'cache-control': 'no-store' }).end()
|
|
76
|
+
else {
|
|
77
|
+
const remaining = (Math.ceil((Date.now() - this.startedAt) / 1000)).toString()
|
|
78
|
+
|
|
79
|
+
response.writeHead(503, { 'retry-after': remaining }).end()
|
|
80
|
+
}
|
|
77
81
|
|
|
78
82
|
return
|
|
79
83
|
}
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const context = new Context(request as IncomingMessage, this.properties.trace)
|
|
85
|
+
const host = request.headers.host!
|
|
86
|
+
const authority = this.authorities[host] ?? host
|
|
87
|
+
const context = new Context(authority, request as IncomingMessage, this.properties)
|
|
85
88
|
|
|
86
|
-
this.process(context)
|
|
89
|
+
this.process!(context)
|
|
87
90
|
.then(this.success(context, response))
|
|
88
91
|
.catch(this.fail(context, response))
|
|
89
92
|
}
|
|
@@ -112,17 +115,15 @@ export class Server extends Connector {
|
|
|
112
115
|
if (!context.request.complete)
|
|
113
116
|
await adam(context.request)
|
|
114
117
|
|
|
115
|
-
response.statusCode = exception instanceof Exception
|
|
116
|
-
? exception.status
|
|
117
|
-
: 500
|
|
118
|
+
response.statusCode = exception instanceof Exception ? exception.status : 500
|
|
118
119
|
|
|
119
120
|
const message: OutgoingMessage = { status: response.statusCode }
|
|
120
|
-
const verbose = exception instanceof ClientError || this.properties.debug
|
|
121
121
|
|
|
122
|
-
if (
|
|
123
|
-
message.body =
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
if (exception instanceof ClientError || this.properties.debug)
|
|
123
|
+
message.body =
|
|
124
|
+
exception instanceof Exception
|
|
125
|
+
? exception.body
|
|
126
|
+
: exception.stack ?? exception.message
|
|
126
127
|
|
|
127
128
|
write(context, response, message)
|
|
128
129
|
}
|
|
@@ -131,28 +132,35 @@ export class Server extends Connector {
|
|
|
131
132
|
|
|
132
133
|
// https://github.com/whatwg/fetch/issues/1254
|
|
133
134
|
async function adam (request: http.IncomingMessage): Promise<void> {
|
|
134
|
-
const completed = promex()
|
|
135
135
|
const devnull = fs.createWriteStream(os.devNull)
|
|
136
136
|
|
|
137
|
-
request
|
|
138
|
-
.on('end', completed.callback)
|
|
139
|
-
.pipe(devnull)
|
|
137
|
+
request.pipe(devnull)
|
|
140
138
|
|
|
141
|
-
|
|
139
|
+
await once(request, 'end')
|
|
142
140
|
}
|
|
143
141
|
|
|
144
|
-
const
|
|
145
|
-
|
|
142
|
+
export const PORT = 8000
|
|
143
|
+
export const DELAY = 3 // seconds
|
|
144
|
+
|
|
145
|
+
const DEFAULTS: Omit<Properties, 'authorities'> = {
|
|
146
|
+
methods: new Set<string>(['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'LOCK', 'UNLOCK']),
|
|
146
147
|
debug: false,
|
|
147
148
|
trace: false,
|
|
148
|
-
port:
|
|
149
|
+
port: PORT,
|
|
150
|
+
delay: DELAY * 1000
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
interface Properties {
|
|
154
|
+
authorities: Record<string, string>
|
|
152
155
|
methods: Set<string>
|
|
153
156
|
debug: boolean
|
|
154
157
|
trace: boolean
|
|
155
158
|
port: number
|
|
159
|
+
delay: number
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type Options = { authorities: Properties['authorities'] } & {
|
|
163
|
+
[K in Exclude<keyof Properties, 'authorities'>]?: Properties[K]
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
export type Processing = (input: Context) => Promise<OutgoingMessage>
|
|
@@ -37,11 +37,17 @@ export class NotFound extends ClientError {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export class Conflict extends ClientError {
|
|
40
|
-
public constructor (body
|
|
40
|
+
public constructor (body?: any) {
|
|
41
41
|
super(409, body)
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export class UnprocessableEntity extends ClientError {
|
|
46
|
+
public constructor (body?: any) {
|
|
47
|
+
super(422, body)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
export class MethodNotAllowed extends ClientError {
|
|
46
52
|
public constructor () {
|
|
47
53
|
super(405)
|
|
@@ -65,3 +71,9 @@ export class PreconditionFailed extends ClientError {
|
|
|
65
71
|
super(412)
|
|
66
72
|
}
|
|
67
73
|
}
|
|
74
|
+
|
|
75
|
+
export class RequestEntityTooLarge extends ClientError {
|
|
76
|
+
public constructor (body?: any) {
|
|
77
|
+
super(413, body)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -5,10 +5,10 @@ import * as msgpack from './msgpack'
|
|
|
5
5
|
import * as text from './text'
|
|
6
6
|
|
|
7
7
|
export const formats: Record<string, Format> = {
|
|
8
|
-
[msgpack.type]: msgpack,
|
|
9
|
-
[yaml.type]: yaml,
|
|
10
8
|
[json.type]: json,
|
|
11
|
-
[
|
|
9
|
+
[yaml.type]: yaml,
|
|
10
|
+
[text.type]: text,
|
|
11
|
+
[msgpack.type]: msgpack
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const types = Object.keys(formats)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { Readable } from 'node:stream'
|
|
1
|
+
import { PassThrough, Readable } from 'node:stream'
|
|
2
|
+
import * as streamConsumers from 'node:stream/consumers'
|
|
3
|
+
import { once } from 'node:events'
|
|
2
4
|
import { generate } from 'randomstring'
|
|
3
5
|
import * as msgpack from 'msgpackr'
|
|
4
|
-
import { read } from './messages'
|
|
6
|
+
import { multipart, read, type OutgoingMessage } from './messages'
|
|
5
7
|
import { BadRequest, UnsupportedMediaType } from './exceptions'
|
|
8
|
+
import { formats } from './formats'
|
|
6
9
|
import { Timing } from './Timing'
|
|
10
|
+
import type * as http from 'node:http'
|
|
7
11
|
import type { Context } from './Context'
|
|
8
12
|
|
|
9
13
|
beforeEach(() => {
|
|
@@ -69,6 +73,45 @@ describe('read', () => {
|
|
|
69
73
|
|
|
70
74
|
await expect(read(request)).rejects.toThrow(BadRequest)
|
|
71
75
|
})
|
|
76
|
+
|
|
77
|
+
it('should output correct mulitpart format', async () => {
|
|
78
|
+
const response = new class extends PassThrough {
|
|
79
|
+
public readonly headers = new Headers()
|
|
80
|
+
|
|
81
|
+
public setHeader (key: string, value: string): this {
|
|
82
|
+
this.headers.set(key, value)
|
|
83
|
+
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
}()
|
|
87
|
+
|
|
88
|
+
const context = { encoder: formats['text/plain'] } as unknown as Context
|
|
89
|
+
const message = { body: Readable.from(['Hello', 'New', 'World']) } as unknown as OutgoingMessage
|
|
90
|
+
|
|
91
|
+
multipart(message, context, response as unknown as http.ServerResponse)
|
|
92
|
+
|
|
93
|
+
await once(message.body, 'end')
|
|
94
|
+
|
|
95
|
+
const result = await streamConsumers.text(response)
|
|
96
|
+
|
|
97
|
+
expect(result).toBe([
|
|
98
|
+
'--cut',
|
|
99
|
+
'',
|
|
100
|
+
'ACK',
|
|
101
|
+
'--cut',
|
|
102
|
+
'',
|
|
103
|
+
'Hello',
|
|
104
|
+
'--cut',
|
|
105
|
+
'',
|
|
106
|
+
'New',
|
|
107
|
+
'--cut',
|
|
108
|
+
'',
|
|
109
|
+
'World',
|
|
110
|
+
'--cut',
|
|
111
|
+
'',
|
|
112
|
+
'FIN',
|
|
113
|
+
'--cut--'].join('\r\n'))
|
|
114
|
+
})
|
|
72
115
|
})
|
|
73
116
|
|
|
74
117
|
export function createContext
|
package/source/HTTP/messages.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
2
|
import { buffer } from 'node:stream/consumers'
|
|
3
|
+
import { console } from 'openspan'
|
|
3
4
|
import { formats } from './formats'
|
|
4
5
|
import { BadRequest, NotAcceptable, UnsupportedMediaType } from './exceptions'
|
|
5
6
|
import type { Context } from './Context'
|
|
@@ -66,13 +67,13 @@ function stream
|
|
|
66
67
|
else
|
|
67
68
|
multipart(message, context, response)
|
|
68
69
|
|
|
69
|
-
message.body.on('error', (
|
|
70
|
-
console.error(
|
|
70
|
+
message.body.on('error', (exception: Error) => {
|
|
71
|
+
console.error('Stream error', { path: context.url.pathname, exception })
|
|
71
72
|
response.end()
|
|
72
73
|
})
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
function multipart
|
|
76
|
+
export function multipart
|
|
76
77
|
(message: OutgoingMessage, context: Context, response: http.ServerResponse): void {
|
|
77
78
|
if (context.encoder === null)
|
|
78
79
|
throw new NotAcceptable()
|
|
@@ -81,9 +82,26 @@ function multipart
|
|
|
81
82
|
|
|
82
83
|
response.setHeader('content-type', `${encoder.multipart}; boundary=${BOUNDARY}`)
|
|
83
84
|
|
|
85
|
+
response.write(Buffer.concat([
|
|
86
|
+
CUT,
|
|
87
|
+
CRLF,
|
|
88
|
+
encoder.encode('ACK'),
|
|
89
|
+
CRLF,
|
|
90
|
+
CUT
|
|
91
|
+
]))
|
|
92
|
+
|
|
84
93
|
message.body
|
|
85
|
-
.map((part: unknown) => Buffer.concat([
|
|
86
|
-
|
|
94
|
+
.map((part: unknown) => Buffer.concat([
|
|
95
|
+
CRLF /* indicates no boundary headers */,
|
|
96
|
+
encoder.encode(part),
|
|
97
|
+
CRLF,
|
|
98
|
+
CUT]))
|
|
99
|
+
.on('end', () => response.end(Buffer.concat([
|
|
100
|
+
CRLF,
|
|
101
|
+
encoder.encode('FIN'),
|
|
102
|
+
CRLF,
|
|
103
|
+
FINALCUT
|
|
104
|
+
])))
|
|
87
105
|
.pipe(response)
|
|
88
106
|
}
|
|
89
107
|
|
|
@@ -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
|
})
|
package/source/Query.ts
CHANGED
|
@@ -1,43 +1,111 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import * as http from './HTTP'
|
|
2
3
|
import { type Parameter } from './RTD'
|
|
3
4
|
import * as schemas from './schemas'
|
|
5
|
+
import { queryable } from './Mapping'
|
|
6
|
+
import type { Introspection, Schema } from './Introspection'
|
|
4
7
|
import type * as syntax from './RTD/syntax'
|
|
5
8
|
import type * as core from '@toa.io/core'
|
|
6
9
|
|
|
7
10
|
export class Query {
|
|
8
11
|
private readonly query: syntax.Query
|
|
9
12
|
private readonly closed: boolean = false
|
|
13
|
+
private readonly prepend: ',' | ';' = ';'
|
|
14
|
+
private readonly queryable: boolean
|
|
10
15
|
|
|
11
16
|
public constructor (query: syntax.Query) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
this.queryable = queryable(query)
|
|
18
|
+
|
|
19
|
+
if (this.queryable) {
|
|
20
|
+
query.omit ??= { value: 0, range: [0, 1000] }
|
|
21
|
+
query.limit ??= { value: 10, range: [1, 100] }
|
|
22
|
+
|
|
23
|
+
if (query.criteria !== undefined) {
|
|
24
|
+
// eslint-disable-next-line max-depth
|
|
25
|
+
if (query.criteria.endsWith(';'))
|
|
26
|
+
query.criteria = query.criteria.slice(0, -1)
|
|
27
|
+
else
|
|
28
|
+
this.closed = true
|
|
29
|
+
|
|
30
|
+
// eslint-disable-next-line max-depth
|
|
31
|
+
if (query.criteria.startsWith(',') || query.criteria.startsWith(';')) {
|
|
32
|
+
this.prepend = query.criteria[0] as ',' | ';'
|
|
33
|
+
|
|
34
|
+
query.criteria = query.criteria.slice(1)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
}
|
|
18
38
|
|
|
19
39
|
this.query = query
|
|
20
40
|
}
|
|
21
41
|
|
|
22
|
-
public fit (query: http.Query, parameters: Parameter[]):
|
|
23
|
-
const
|
|
42
|
+
public fit (query: http.Query, parameters: Parameter[]): QueryString {
|
|
43
|
+
const qs = this.split(query)
|
|
44
|
+
|
|
45
|
+
if (qs.query !== null) {
|
|
46
|
+
const error = schemas.querystring.fit(qs.query)
|
|
24
47
|
|
|
25
|
-
|
|
26
|
-
|
|
48
|
+
if (error !== null)
|
|
49
|
+
throw new http.BadRequest('Query ' + error.message)
|
|
27
50
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
this.fitCriteria(qs.query, parameters)
|
|
52
|
+
this.fitRanges(qs.query)
|
|
53
|
+
this.fitSort(qs.query)
|
|
54
|
+
}
|
|
31
55
|
|
|
32
|
-
return
|
|
56
|
+
return {
|
|
57
|
+
query: qs.query as core.Query,
|
|
58
|
+
parameters: qs.parameters
|
|
59
|
+
}
|
|
33
60
|
}
|
|
34
61
|
|
|
35
|
-
|
|
36
|
-
|
|
62
|
+
public explain (introspection: Introspection): Record<string, Schema> | null {
|
|
63
|
+
if (this.query?.parameters === undefined || introspection.input?.type !== 'object')
|
|
64
|
+
return null
|
|
37
65
|
|
|
38
|
-
|
|
39
|
-
|
|
66
|
+
let query: Record<string, Schema> | null = null
|
|
67
|
+
|
|
68
|
+
for (const parameter of this.query.parameters) {
|
|
69
|
+
const schema = introspection.input.properties[parameter]
|
|
70
|
+
|
|
71
|
+
if (schema !== undefined) {
|
|
72
|
+
query ??= {}
|
|
73
|
+
query[parameter] = schema
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
delete introspection.input.properties[parameter]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return query
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private split (query: http.Query): {
|
|
83
|
+
query: http.Query | null
|
|
84
|
+
parameters: Record<string, string> | null
|
|
85
|
+
} {
|
|
86
|
+
let parameters: Record<string, string> | null = null
|
|
87
|
+
|
|
88
|
+
if (this.query?.parameters !== undefined)
|
|
89
|
+
for (const key in query)
|
|
90
|
+
// eslint-disable-next-line max-depth
|
|
91
|
+
if (this.query.parameters.includes(key)) {
|
|
92
|
+
parameters ??= {}
|
|
93
|
+
parameters[key] = query[key] as string
|
|
94
|
+
|
|
95
|
+
delete query[key]
|
|
96
|
+
}
|
|
40
97
|
|
|
98
|
+
if (!this.queryable)
|
|
99
|
+
query = null!
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
query,
|
|
103
|
+
parameters
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private fitCriteria (query: http.Query, parameters: Parameter[]): void {
|
|
108
|
+
const groups: CriteriaGroup[] = []
|
|
41
109
|
const idx = parameters.findIndex((parameter) => parameter.name === 'id')
|
|
42
110
|
|
|
43
111
|
if (idx !== -1) {
|
|
@@ -47,32 +115,36 @@ export class Query {
|
|
|
47
115
|
}
|
|
48
116
|
|
|
49
117
|
if (parameters.length > 0) {
|
|
50
|
-
const
|
|
118
|
+
const criteria = parameters
|
|
51
119
|
.map(({ name, value }) => `${name}==${value}`)
|
|
52
120
|
.join(';')
|
|
53
121
|
|
|
54
|
-
|
|
122
|
+
groups.push({ criteria, operator: this.prepend })
|
|
55
123
|
}
|
|
56
124
|
|
|
125
|
+
if (this.query.criteria !== undefined)
|
|
126
|
+
groups.push({ criteria: this.query.criteria, operator: ';' })
|
|
127
|
+
|
|
57
128
|
if (query.criteria !== undefined)
|
|
58
|
-
if (this.closed)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
break
|
|
70
|
-
}
|
|
129
|
+
if (this.closed)
|
|
130
|
+
throw new http.BadRequest('Query criteria is closed')
|
|
131
|
+
else
|
|
132
|
+
groups.push({ criteria: query.criteria, operator: WHATEVER })
|
|
133
|
+
|
|
134
|
+
if (groups.length > 0)
|
|
135
|
+
query.criteria = groups.reduce((acc, { criteria, operator }, i) => {
|
|
136
|
+
return i === groups.length - 1
|
|
137
|
+
? `${acc}(${criteria})`
|
|
138
|
+
: `${acc}(${criteria})${operator}`
|
|
139
|
+
}, '')
|
|
71
140
|
}
|
|
72
141
|
|
|
73
142
|
private fitRanges (qs: http.Query): void {
|
|
74
143
|
const query = qs as core.Query
|
|
75
144
|
|
|
145
|
+
assert.ok(this.query.limit !== undefined, 'Query limit must be defined')
|
|
146
|
+
assert.ok(this.query.omit !== undefined, 'Query limit range must be defined')
|
|
147
|
+
|
|
76
148
|
if (qs.limit !== undefined)
|
|
77
149
|
query.limit = fit(qs.limit, this.query.limit.range, 'limit')
|
|
78
150
|
else
|
|
@@ -99,7 +171,19 @@ function fit (string: string, range: [number, number], name: string): number {
|
|
|
99
171
|
|
|
100
172
|
if (number < range[0] || number > range[1])
|
|
101
173
|
throw new http.BadRequest(`Query ${name} must be between ` +
|
|
102
|
-
`${range[0]} and ${range[1]} inclusive
|
|
174
|
+
`${range[0]} and ${range[1]} inclusive`)
|
|
103
175
|
|
|
104
176
|
return number
|
|
105
177
|
}
|
|
178
|
+
|
|
179
|
+
const WHATEVER = ';'
|
|
180
|
+
|
|
181
|
+
interface CriteriaGroup {
|
|
182
|
+
criteria: string
|
|
183
|
+
operator: ',' | ';'
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface QueryString {
|
|
187
|
+
query: core.Query | null
|
|
188
|
+
parameters: Record<string, string> | null
|
|
189
|
+
}
|