@wirebench/engine 2.2.1 → 3.1.0-rc.1
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/README.md +134 -1
- package/dist/account/schema.d.ts +34 -0
- package/dist/account/schema.js +29 -0
- package/dist/assert/callback.d.ts +76 -0
- package/dist/assert/callback.js +320 -0
- package/dist/assert/capture-source.d.ts +50 -0
- package/dist/assert/capture-source.js +89 -0
- package/dist/assert/check.d.ts +8 -0
- package/dist/assert/check.js +18 -0
- package/dist/assert/header.d.ts +5 -0
- package/dist/assert/header.js +48 -0
- package/dist/assert/index.d.ts +2 -2
- package/dist/assert/index.js +12 -0
- package/dist/assert/match.d.ts +6 -0
- package/dist/assert/match.js +13 -4
- package/dist/assert/model.d.ts +110 -3
- package/dist/assert/model.js +16 -1
- package/dist/assert/schema.d.ts +194 -1
- package/dist/assert/schema.js +154 -12
- package/dist/assert/status-names.d.ts +9 -0
- package/dist/assert/status-names.js +27 -0
- package/dist/assert/status.d.ts +4 -1
- package/dist/assert/status.js +27 -3
- package/dist/asyncapi/browser.d.ts +7 -0
- package/dist/asyncapi/browser.js +6 -0
- package/dist/asyncapi/frame-check-worker-host.d.ts +44 -0
- package/dist/asyncapi/frame-check-worker-host.js +175 -0
- package/dist/asyncapi/frame-check-worker.d.ts +12 -0
- package/dist/asyncapi/frame-check-worker.js +25 -0
- package/dist/asyncapi/frame-check.d.ts +25 -0
- package/dist/asyncapi/frame-check.js +78 -0
- package/dist/asyncapi/import.d.ts +25 -0
- package/dist/asyncapi/import.js +34 -0
- package/dist/asyncapi/map.d.ts +40 -0
- package/dist/asyncapi/map.js +230 -0
- package/dist/asyncapi/model.d.ts +84 -0
- package/dist/asyncapi/model.js +7 -0
- package/dist/asyncapi/normalise-2.d.ts +13 -0
- package/dist/asyncapi/normalise-2.js +113 -0
- package/dist/asyncapi/normalise-3.d.ts +14 -0
- package/dist/asyncapi/normalise-3.js +133 -0
- package/dist/asyncapi/parse.d.ts +31 -0
- package/dist/asyncapi/parse.js +85 -0
- package/dist/asyncapi/read.d.ts +35 -0
- package/dist/asyncapi/read.js +186 -0
- package/dist/asyncapi/security.d.ts +14 -0
- package/dist/asyncapi/security.js +55 -0
- package/dist/asyncapi/update.d.ts +53 -0
- package/dist/asyncapi/update.js +220 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +22 -0
- package/dist/grpc/events.d.ts +22 -0
- package/dist/grpc/events.js +1 -0
- package/dist/grpc/expand.d.ts +1 -1
- package/dist/grpc/expand.js +15 -5
- package/dist/grpc/files.d.ts +271 -0
- package/dist/grpc/files.js +62 -0
- package/dist/grpc/model.d.ts +11 -1
- package/dist/grpc/module.d.ts +2 -0
- package/dist/grpc/module.js +13 -0
- package/dist/grpc/run.d.ts +73 -0
- package/dist/grpc/run.js +407 -0
- package/dist/grpc/script-types.d.ts +8 -0
- package/dist/grpc/script-types.js +149 -0
- package/dist/grpc/scripting.d.ts +34 -0
- package/dist/grpc/scripting.js +147 -0
- package/dist/grpc/send-input.d.ts +46 -0
- package/dist/grpc/send-input.js +42 -0
- package/dist/grpc/send.d.ts +2 -2
- package/dist/grpc/status.d.ts +9 -2
- package/dist/grpc/status.js +11 -24
- package/dist/grpc/storage.d.ts +9 -0
- package/dist/grpc/storage.js +167 -0
- package/dist/{rest/auth.d.ts → http/auth/apply-auth.d.ts} +4 -4
- package/dist/{rest/auth.js → http/auth/apply-auth.js} +1 -1
- package/dist/http/auth/apply.d.ts +1 -1
- package/dist/{rest → http/auth}/oauth2.d.ts +2 -2
- package/dist/{rest → http/auth}/oauth2.js +1 -1
- package/dist/http/auth/send-auth.d.ts +57 -0
- package/dist/http/auth/send-auth.js +7 -0
- package/dist/http/client.js +150 -8
- package/dist/http/cookies.d.ts +79 -0
- package/dist/http/cookies.js +81 -0
- package/dist/http/curl.d.ts +4 -14
- package/dist/http/curl.js +4 -154
- package/dist/http/decompress.d.ts +7 -0
- package/dist/http/decompress.js +23 -1
- package/dist/http/document-fetch.d.ts +42 -0
- package/dist/http/document-fetch.js +207 -0
- package/dist/http/entries.d.ts +27 -0
- package/dist/http/entries.js +16 -0
- package/dist/http/escape.d.ts +18 -0
- package/dist/http/escape.js +30 -0
- package/dist/http/fetch-document.d.ts +28 -0
- package/dist/{wsdl/fetch.js → http/fetch-document.js} +8 -16
- package/dist/http/media-type.d.ts +9 -0
- package/dist/http/media-type.js +12 -0
- package/dist/http/transcript-cap.d.ts +26 -0
- package/dist/http/transcript-cap.js +36 -0
- package/dist/http/types.d.ts +59 -0
- package/dist/http/webhook-signature.d.ts +81 -0
- package/dist/http/webhook-signature.js +227 -0
- package/dist/import-detect.d.ts +2 -2
- package/dist/import-detect.js +10 -1
- package/dist/index.d.ts +207 -55
- package/dist/index.js +129 -32
- package/dist/json/cursor.d.ts +2 -0
- package/dist/json/cursor.js +1 -0
- package/dist/json/pointer-range.d.ts +18 -0
- package/dist/json/pointer-range.js +157 -0
- package/dist/json/schema/model.d.ts +59 -0
- package/dist/json/schema/model.js +8 -0
- package/dist/json/schema/parse-text.d.ts +16 -0
- package/dist/json/schema/parse-text.js +37 -0
- package/dist/{rest/openapi → json/schema}/refs.d.ts +2 -2
- package/dist/{rest/openapi → json/schema}/refs.js +3 -3
- package/dist/{rest/openapi → json/schema}/sample.d.ts +4 -0
- package/dist/{rest/openapi → json/schema}/sample.js +2 -2
- package/dist/json/schema/source.d.ts +21 -0
- package/dist/json/schema/source.js +8 -0
- package/dist/json/schema-validate.d.ts +49 -0
- package/dist/json/schema-validate.js +557 -0
- package/dist/{wss/keystore → keystore}/index.js +1 -1
- package/dist/{wss/keystore → keystore}/pem.js +1 -1
- package/dist/{wss/keystore → keystore}/pkcs12.js +1 -1
- package/dist/project/attachments-cache.d.ts +3 -1
- package/dist/{wsdl → project}/cache-naming.js +1 -1
- package/dist/project/endpoints.d.ts +18 -8
- package/dist/project/endpoints.js +21 -6
- package/dist/project/environments.d.ts +7 -5
- package/dist/project/history.d.ts +105 -9
- package/dist/project/history.js +195 -23
- package/dist/project/inherit.d.ts +7 -0
- package/dist/project/inherit.js +9 -0
- package/dist/project/keystores.d.ts +1 -1
- package/dist/project/load-helpers.d.ts +89 -0
- package/dist/project/load-helpers.js +177 -0
- package/dist/project/load.d.ts +30 -4
- package/dist/project/load.js +168 -545
- package/dist/project/managed-files.d.ts +36 -0
- package/dist/project/managed-files.js +97 -0
- package/dist/project/migrate.d.ts +2 -2
- package/dist/project/migrate.js +2 -2
- package/dist/project/model.d.ts +92 -14
- package/dist/project/model.js +50 -4
- package/dist/project/paths.d.ts +10 -1
- package/dist/project/paths.js +10 -1
- package/dist/project/preferences.d.ts +11 -2
- package/dist/project/preferences.js +5 -1
- package/dist/project/properties.d.ts +31 -17
- package/dist/project/properties.js +89 -70
- package/dist/project/request-location.d.ts +20 -0
- package/dist/project/request-location.js +62 -0
- package/dist/project/save.d.ts +12 -2
- package/dist/project/save.js +186 -141
- package/dist/project/schema-parts.d.ts +337 -0
- package/dist/project/schema-parts.js +248 -0
- package/dist/project/schema.d.ts +72 -928
- package/dist/project/schema.js +17 -466
- package/dist/project/sequence-guards.d.ts +43 -0
- package/dist/project/sequence-guards.js +109 -0
- package/dist/project/serialize-helpers.d.ts +60 -0
- package/dist/project/serialize-helpers.js +108 -0
- package/dist/project/serialize.d.ts +7 -8
- package/dist/project/serialize.js +34 -293
- package/dist/protocol/features.d.ts +51 -0
- package/dist/protocol/features.js +64 -0
- package/dist/protocol/index.d.ts +7 -0
- package/dist/protocol/index.js +4 -0
- package/dist/protocol/module.d.ts +247 -0
- package/dist/protocol/module.js +48 -0
- package/dist/protocol/registry.d.ts +42 -0
- package/dist/protocol/registry.js +47 -0
- package/dist/protocols.d.ts +77 -0
- package/dist/protocols.js +40 -0
- package/dist/redact/index.d.ts +12 -1
- package/dist/redact/index.js +55 -7
- package/dist/redact/literal.d.ts +10 -0
- package/dist/redact/literal.js +110 -12
- package/dist/rest/body.d.ts +2 -10
- package/dist/rest/body.js +3 -25
- package/dist/rest/browser.d.ts +4 -0
- package/dist/rest/browser.js +5 -0
- package/dist/rest/contract-check-worker-host.d.ts +36 -0
- package/dist/rest/contract-check-worker-host.js +158 -0
- package/dist/rest/contract-check-worker.d.ts +7 -0
- package/dist/rest/contract-check-worker.js +28 -0
- package/dist/rest/contract-check.d.ts +43 -0
- package/dist/rest/contract-check.js +217 -0
- package/dist/rest/cookie-jar.d.ts +62 -0
- package/dist/rest/cookie-jar.js +262 -0
- package/dist/rest/cookies.d.ts +6 -22
- package/dist/rest/cookies.js +6 -42
- package/dist/rest/curl.js +5 -1
- package/dist/rest/events.d.ts +12 -0
- package/dist/rest/events.js +1 -0
- package/dist/rest/expand.d.ts +6 -1
- package/dist/rest/expand.js +29 -11
- package/dist/rest/files.d.ts +439 -0
- package/dist/rest/files.js +107 -0
- package/dist/rest/json-form.d.ts +97 -0
- package/dist/rest/json-form.js +396 -0
- package/dist/rest/model.d.ts +35 -24
- package/dist/rest/model.js +6 -9
- package/dist/rest/module.d.ts +2 -0
- package/dist/rest/module.js +13 -0
- package/dist/rest/openapi/cache.d.ts +7 -2
- package/dist/rest/openapi/cache.js +2 -2
- package/dist/rest/openapi/import.d.ts +11 -16
- package/dist/rest/openapi/import.js +6 -2
- package/dist/rest/openapi/map.d.ts +38 -1
- package/dist/rest/openapi/map.js +151 -41
- package/dist/rest/openapi/match.d.ts +20 -0
- package/dist/rest/openapi/match.js +117 -0
- package/dist/rest/openapi/model.d.ts +33 -45
- package/dist/rest/openapi/parse.d.ts +3 -12
- package/dist/rest/openapi/parse.js +138 -67
- package/dist/rest/openapi/responses.d.ts +23 -0
- package/dist/rest/openapi/responses.js +59 -0
- package/dist/rest/openapi/runtime-expression.d.ts +69 -0
- package/dist/rest/openapi/runtime-expression.js +213 -0
- package/dist/rest/openapi/update.d.ts +116 -0
- package/dist/rest/openapi/update.js +456 -0
- package/dist/rest/postman/map.d.ts +1 -0
- package/dist/rest/postman/map.js +66 -4
- package/dist/rest/postman/model.d.ts +9 -0
- package/dist/rest/postman/parse.js +33 -10
- package/dist/rest/response.d.ts +2 -23
- package/dist/rest/response.js +3 -75
- package/dist/rest/run.d.ts +56 -0
- package/dist/rest/run.js +395 -0
- package/dist/rest/script-types.d.ts +7 -0
- package/dist/rest/script-types.js +83 -0
- package/dist/rest/scripting.d.ts +38 -0
- package/dist/rest/scripting.js +282 -0
- package/dist/rest/send-input.d.ts +54 -0
- package/dist/rest/send-input.js +73 -0
- package/dist/rest/send.d.ts +77 -4
- package/dist/rest/send.js +128 -7
- package/dist/rest/sse-transcript.d.ts +25 -0
- package/dist/rest/sse-transcript.js +95 -0
- package/dist/rest/sse.d.ts +43 -0
- package/dist/rest/sse.js +195 -0
- package/dist/rest/storage.d.ts +26 -0
- package/dist/rest/storage.js +262 -0
- package/dist/rest/url.d.ts +10 -4
- package/dist/rest/url.js +38 -5
- package/dist/run/baseline-update.d.ts +35 -0
- package/dist/run/baseline-update.js +97 -0
- package/dist/run/baseline.d.ts +42 -0
- package/dist/run/baseline.js +93 -0
- package/dist/run/context.d.ts +86 -0
- package/dist/run/context.js +31 -0
- package/dist/run/current-values.d.ts +32 -0
- package/dist/run/current-values.js +43 -0
- package/dist/run/event-queue.d.ts +14 -0
- package/dist/run/event-queue.js +46 -0
- package/dist/run/exchange.d.ts +62 -0
- package/dist/run/exchange.js +65 -0
- package/dist/run/host.d.ts +89 -0
- package/dist/run/host.js +1 -0
- package/dist/run/index.d.ts +20 -7
- package/dist/run/index.js +12 -4
- package/dist/run/oauth2-token.d.ts +42 -0
- package/dist/run/oauth2-token.js +92 -0
- package/dist/run/open.d.ts +12 -0
- package/dist/run/open.js +16 -0
- package/dist/run/run.d.ts +124 -4
- package/dist/run/run.js +293 -134
- package/dist/run/scope.d.ts +11 -0
- package/dist/run/scope.js +26 -0
- package/dist/run/script-support.d.ts +53 -0
- package/dist/run/script-support.js +68 -0
- package/dist/run/secret-needs.d.ts +11 -4
- package/dist/run/secret-needs.js +48 -96
- package/dist/run/select.d.ts +34 -25
- package/dist/run/select.js +45 -54
- package/dist/run/send-helpers.d.ts +93 -0
- package/dist/run/send-helpers.js +255 -0
- package/dist/run/tree.d.ts +50 -0
- package/dist/run/tree.js +54 -0
- package/dist/script/api/postman.d.ts +10 -0
- package/dist/script/api/postman.js +264 -0
- package/dist/script/api/prelude.d.ts +20 -0
- package/dist/script/api/prelude.js +215 -0
- package/dist/script/apply.d.ts +44 -0
- package/dist/script/apply.js +120 -0
- package/dist/script/check/host.d.ts +41 -0
- package/dist/script/check/host.js +143 -0
- package/dist/script/check/service.d.ts +52 -0
- package/dist/script/check/service.js +195 -0
- package/dist/script/check/worker.d.ts +1 -0
- package/dist/script/check/worker.js +40 -0
- package/dist/script/index.d.ts +16 -0
- package/dist/script/index.js +10 -0
- package/dist/script/lookup.d.ts +10 -0
- package/dist/script/lookup.js +23 -0
- package/dist/script/model.d.ts +82 -0
- package/dist/script/model.js +18 -0
- package/dist/script/props.d.ts +8 -0
- package/dist/script/props.js +28 -0
- package/dist/script/request-scripts.d.ts +83 -0
- package/dist/script/request-scripts.js +160 -0
- package/dist/script/run.d.ts +47 -0
- package/dist/script/run.js +146 -0
- package/dist/script/sandbox/execute.d.ts +26 -0
- package/dist/script/sandbox/execute.js +212 -0
- package/dist/script/sandbox/host-api.d.ts +27 -0
- package/dist/script/sandbox/host-api.js +101 -0
- package/dist/script/sandbox/host.d.ts +18 -0
- package/dist/script/sandbox/host.js +172 -0
- package/dist/script/sandbox/model.d.ts +69 -0
- package/dist/script/sandbox/model.js +24 -0
- package/dist/script/sandbox/worker.d.ts +1 -0
- package/dist/script/sandbox/worker.js +20 -0
- package/dist/script/send.d.ts +27 -0
- package/dist/script/send.js +76 -0
- package/dist/script/strip.d.ts +5 -0
- package/dist/script/strip.js +43 -0
- package/dist/script/types/api.d.ts +38 -0
- package/dist/script/types/api.js +113 -0
- package/dist/script/types/json-schema.d.ts +26 -0
- package/dist/script/types/json-schema.js +206 -0
- package/dist/secrets/env-names.d.ts +9 -1
- package/dist/secrets/env-names.js +17 -1
- package/dist/secrets/resolve.d.ts +44 -4
- package/dist/secrets/resolve.js +58 -1
- package/dist/secrets/scan/apply.d.ts +36 -0
- package/dist/secrets/scan/apply.js +194 -0
- package/dist/secrets/scan/rules.d.ts +32 -0
- package/dist/secrets/scan/rules.js +346 -0
- package/dist/secrets/scan/scan.d.ts +6 -0
- package/dist/secrets/scan/scan.js +57 -0
- package/dist/secrets/scan/walk.d.ts +70 -0
- package/dist/secrets/scan/walk.js +156 -0
- package/dist/secrets/secret-refs.d.ts +8 -0
- package/dist/secrets/secret-refs.js +25 -0
- package/dist/secrets/secret-token.d.ts +17 -0
- package/dist/secrets/secret-token.js +25 -0
- package/dist/sequence/file.d.ts +169 -0
- package/dist/sequence/file.js +237 -0
- package/dist/sequence/index.d.ts +7 -0
- package/dist/sequence/index.js +5 -0
- package/dist/sequence/load.d.ts +32 -0
- package/dist/sequence/load.js +56 -0
- package/dist/sequence/model.d.ts +115 -0
- package/dist/sequence/model.js +53 -0
- package/dist/sequence/run.d.ts +131 -0
- package/dist/sequence/run.js +191 -0
- package/dist/sequence/transfer.d.ts +24 -0
- package/dist/sequence/transfer.js +75 -0
- package/dist/server-api/audit.d.ts +455 -0
- package/dist/server-api/audit.js +186 -0
- package/dist/server-api/ci-tokens.d.ts +50 -0
- package/dist/server-api/ci-tokens.js +35 -0
- package/dist/server-api/hooks.d.ts +337 -0
- package/dist/server-api/hooks.js +152 -0
- package/dist/server-api/identity.d.ts +210 -0
- package/dist/server-api/identity.js +115 -0
- package/dist/server-api/licensing.d.ts +80 -0
- package/dist/server-api/licensing.js +53 -0
- package/dist/server-api/live.d.ts +132 -0
- package/dist/server-api/live.js +102 -0
- package/dist/server-api/meta.d.ts +31 -0
- package/dist/server-api/meta.js +21 -0
- package/dist/server-api/sync.d.ts +179 -0
- package/dist/server-api/sync.js +124 -0
- package/dist/server-api/teams.d.ts +306 -0
- package/dist/server-api/teams.js +113 -0
- package/dist/snapshot/diff.d.ts +30 -0
- package/dist/snapshot/diff.js +75 -0
- package/dist/snapshot/format.d.ts +17 -0
- package/dist/snapshot/format.js +40 -0
- package/dist/snapshot/golden-file.d.ts +45 -0
- package/dist/snapshot/golden-file.js +173 -0
- package/dist/snapshot/ignore.d.ts +14 -0
- package/dist/snapshot/ignore.js +79 -0
- package/dist/snapshot/index.d.ts +9 -0
- package/dist/snapshot/index.js +9 -0
- package/dist/snapshot/json-diff.d.ts +3 -0
- package/dist/snapshot/json-diff.js +93 -0
- package/dist/snapshot/xml-diff.d.ts +10 -0
- package/dist/snapshot/xml-diff.js +194 -0
- package/dist/soap/auth.d.ts +26 -0
- package/dist/soap/auth.js +54 -0
- package/dist/soap/curl.d.ts +20 -0
- package/dist/soap/curl.js +161 -0
- package/dist/soap/expand.d.ts +24 -0
- package/dist/soap/expand.js +95 -0
- package/dist/soap/files.d.ts +384 -0
- package/dist/soap/files.js +114 -0
- package/dist/soap/form-request.d.ts +13 -0
- package/dist/soap/form-request.js +2 -2
- package/dist/soap/generate.d.ts +12 -0
- package/dist/{generate.js → soap/generate.js} +4 -4
- package/dist/{import.d.ts → soap/import.d.ts} +4 -4
- package/dist/{import.js → soap/import.js} +13 -13
- package/dist/soap/json-operation.d.ts +35 -0
- package/dist/soap/json-operation.js +225 -0
- package/dist/soap/legacy-project/env-refs.d.ts +19 -0
- package/dist/soap/legacy-project/env-refs.js +105 -0
- package/dist/soap/legacy-project/map.d.ts +2 -2
- package/dist/soap/legacy-project/map.js +6 -0
- package/dist/soap/mime/multipart.d.ts +2 -2
- package/dist/soap/mime/multipart.js +2 -5
- package/dist/soap/mime/send-pipeline.d.ts +1 -1
- package/dist/soap/mime/send-pipeline.js +1 -1
- package/dist/soap/mime/types.d.ts +1 -3
- package/dist/soap/module.d.ts +2 -0
- package/dist/soap/module.js +13 -0
- package/dist/soap/namespace-scope.js +1 -1
- package/dist/soap/operations.d.ts +12 -0
- package/dist/{operations.js → soap/operations.js} +4 -4
- package/dist/soap/run.d.ts +70 -0
- package/dist/soap/run.js +549 -0
- package/dist/soap/script-types.d.ts +65 -0
- package/dist/soap/script-types.js +379 -0
- package/dist/soap/scripting.d.ts +45 -0
- package/dist/soap/scripting.js +221 -0
- package/dist/soap/send-input.d.ts +61 -0
- package/dist/{send-options.js → soap/send-input.js} +5 -109
- package/dist/{send.d.ts → soap/send.d.ts} +1 -1
- package/dist/{send.js → soap/send.js} +28 -12
- package/dist/soap/storage.d.ts +9 -0
- package/dist/soap/storage.js +237 -0
- package/dist/soap/transforms.d.ts +3 -12
- package/dist/soap/transforms.js +3 -14
- package/dist/{types.d.ts → soap/types.d.ts} +34 -84
- package/dist/sync/git-cli.d.ts +202 -0
- package/dist/sync/git-cli.js +684 -0
- package/dist/sync/three-way-merge.d.ts +41 -0
- package/dist/sync/three-way-merge.js +85 -0
- package/dist/sync/tree-paths.d.ts +34 -0
- package/dist/sync/tree-paths.js +131 -0
- package/dist/team-secrets/envelope.d.ts +10 -0
- package/dist/team-secrets/envelope.js +121 -0
- package/dist/team-secrets/errors.d.ts +26 -0
- package/dist/team-secrets/errors.js +27 -0
- package/dist/team-secrets/index.d.ts +14 -0
- package/dist/team-secrets/index.js +8 -0
- package/dist/team-secrets/keys.d.ts +52 -0
- package/dist/team-secrets/keys.js +158 -0
- package/dist/team-secrets/log.d.ts +48 -0
- package/dist/team-secrets/log.js +175 -0
- package/dist/team-secrets/resolve-conflict.d.ts +7 -0
- package/dist/team-secrets/resolve-conflict.js +14 -0
- package/dist/team-secrets/schema.d.ts +97 -0
- package/dist/team-secrets/schema.js +157 -0
- package/dist/team-secrets/sign.d.ts +24 -0
- package/dist/team-secrets/sign.js +71 -0
- package/dist/team-secrets/vault.d.ts +49 -0
- package/dist/team-secrets/vault.js +148 -0
- package/dist/validate/wsi/run-message.d.ts +2 -2
- package/dist/validate/wsi/run-message.js +1 -1
- package/dist/validate/wsi/run-wsdl.d.ts +2 -2
- package/dist/validate/wsi/run-wsdl.js +1 -1
- package/dist/validate/wsi/types.d.ts +1 -1
- package/dist/webhooks/model.d.ts +138 -0
- package/dist/webhooks/model.js +150 -0
- package/dist/workspace/commit-message.d.ts +1 -1
- package/dist/workspace/commit-message.js +6 -1
- package/dist/workspace/environments.d.ts +11 -4
- package/dist/workspace/environments.js +12 -0
- package/dist/workspace/index.d.ts +3 -3
- package/dist/workspace/index.js +2 -2
- package/dist/workspace/paths.d.ts +5 -2
- package/dist/workspace/paths.js +5 -2
- package/dist/workspace/schema.d.ts +7 -3
- package/dist/workspace/schema.js +24 -3
- package/dist/workspace/share.d.ts +30 -11
- package/dist/workspace/share.js +32 -6
- package/dist/ws/call.d.ts +1 -1
- package/dist/ws/call.js +2 -2
- package/dist/ws/connect.d.ts +60 -0
- package/dist/ws/connect.js +131 -0
- package/dist/ws/events.d.ts +17 -0
- package/dist/ws/events.js +1 -0
- package/dist/ws/expand.d.ts +1 -1
- package/dist/ws/expand.js +1 -1
- package/dist/ws/files.d.ts +284 -0
- package/dist/ws/files.js +71 -0
- package/dist/ws/history-entry.d.ts +44 -0
- package/dist/ws/history-entry.js +93 -0
- package/dist/ws/model.d.ts +44 -3
- package/dist/ws/model.js +3 -0
- package/dist/ws/module.d.ts +2 -0
- package/dist/ws/module.js +11 -0
- package/dist/ws/run.d.ts +63 -0
- package/dist/ws/run.js +470 -0
- package/dist/ws/session.d.ts +18 -0
- package/dist/ws/session.js +52 -25
- package/dist/ws/storage.d.ts +9 -0
- package/dist/ws/storage.js +176 -0
- package/dist/ws/transcript.d.ts +3 -4
- package/dist/ws/transcript.js +26 -17
- package/dist/ws/url.d.ts +1 -1
- package/dist/wsdl/cache.js +1 -1
- package/dist/wsdl/docs-generator.d.ts +3 -3
- package/dist/wsdl/docs-generator.js +1 -1
- package/dist/wsdl/export-definition.js +1 -1
- package/dist/wsdl/qname.d.ts +2 -5
- package/dist/wsdl/resolver.d.ts +4 -11
- package/dist/wsdl/resolver.js +3 -3
- package/dist/wsdl/update-definition.d.ts +5 -5
- package/dist/wsdl/update-definition.js +6 -6
- package/dist/wss/apply.js +1 -1
- package/dist/{project/wss-configs.d.ts → wss/configs.d.ts} +2 -2
- package/dist/{project/wss-configs.js → wss/configs.js} +2 -2
- package/dist/wss/incoming/decrypt.d.ts +1 -1
- package/dist/wss/incoming/index.js +1 -1
- package/dist/wss/incoming/verify.d.ts +1 -1
- package/dist/wss/incoming/verify.js +1 -1
- package/dist/wss/key-identifiers.js +1 -1
- package/dist/wss/model.d.ts +1 -1
- package/dist/wss/outgoing/encryption.d.ts +1 -1
- package/dist/wss/outgoing/signature.d.ts +1 -1
- package/dist/xml/decode.d.ts +15 -0
- package/dist/xml/decode.js +22 -0
- package/dist/xml/entitize.d.ts +17 -0
- package/dist/xml/entitize.js +19 -0
- package/dist/xml/index.d.ts +1 -1
- package/dist/xml/index.js +1 -1
- package/dist/xml/locate.d.ts +39 -0
- package/dist/xml/locate.js +117 -0
- package/dist/xml/qname.d.ts +12 -0
- package/dist/xml/qname.js +8 -0
- package/dist/xpath/evaluate-async.d.ts +19 -0
- package/dist/xpath/evaluate-async.js +31 -11
- package/dist/xpath/evaluate.d.ts +1 -1
- package/dist/xpath/namespaces.js +1 -1
- package/dist/xpath/worker.d.ts +11 -5
- package/dist/xpath/worker.js +24 -7
- package/dist/xsd/form-model.d.ts +19 -2
- package/dist/xsd/form-model.js +14 -2
- package/dist/xsd/json-bridge.d.ts +152 -0
- package/dist/xsd/json-bridge.js +1213 -0
- package/dist/xsd/locate.d.ts +2 -30
- package/dist/xsd/locate.js +1 -109
- package/dist/xsd/xml-scan.d.ts +2 -0
- package/dist/xsd/xml-scan.js +1 -1
- package/dist/xsd/xml-writer.d.ts +2 -0
- package/dist/xsd/xml-writer.js +4 -0
- package/package.json +12 -1
- package/dist/generate.d.ts +0 -12
- package/dist/operations.d.ts +0 -12
- package/dist/run/effective-auth.d.ts +0 -10
- package/dist/run/effective-auth.js +0 -19
- package/dist/run/prepare.d.ts +0 -43
- package/dist/run/prepare.js +0 -280
- package/dist/send-options.d.ts +0 -141
- package/dist/wsdl/fetch.d.ts +0 -13
- /package/dist/{soap → http}/charset.d.ts +0 -0
- /package/dist/{soap → http}/charset.js +0 -0
- /package/dist/{wsdl → http}/ref-policy.d.ts +0 -0
- /package/dist/{wsdl → http}/ref-policy.js +0 -0
- /package/dist/{wss/keystore → keystore}/certificate.d.ts +0 -0
- /package/dist/{wss/keystore → keystore}/certificate.js +0 -0
- /package/dist/{wss/keystore → keystore}/index.d.ts +0 -0
- /package/dist/{wss/keystore → keystore}/model.d.ts +0 -0
- /package/dist/{wss/keystore → keystore}/model.js +0 -0
- /package/dist/{wss/keystore → keystore}/pem.d.ts +0 -0
- /package/dist/{wss/keystore → keystore}/pkcs12.d.ts +0 -0
- /package/dist/{wsdl → project}/cache-naming.d.ts +0 -0
- /package/dist/{types.js → soap/types.js} +0 -0
- /package/dist/{soap → xml}/prefixes.d.ts +0 -0
- /package/dist/{soap → xml}/prefixes.js +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A request's scripts in a send (spec §Results): which ones run, the type check before the send,
|
|
3
|
+
* and the pre-request and post-response runs. The run (`run/run.ts`) and the app's send paths both
|
|
4
|
+
* go through this, so a script behaves the same in a pipeline and on a click.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { WirebenchError } from '../errors.js';
|
|
8
|
+
import { scriptFileName, } from './model.js';
|
|
9
|
+
import { runScript } from './run.js';
|
|
10
|
+
import { scriptDeclarations } from './types/api.js';
|
|
11
|
+
/** The scripts of a request that will run: none when there are none or they are switched off. */
|
|
12
|
+
export function activeScripts(scripts) {
|
|
13
|
+
if (scripts === undefined || !scripts.enabled || (scripts.pre === undefined && scripts.post === undefined)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return scripts;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Refuses a request whose script file is missing or too large: sending it without that script
|
|
20
|
+
* would be sending something other than what the request says.
|
|
21
|
+
*
|
|
22
|
+
* @throws WirebenchError `script-file-missing` | `script-too-large`
|
|
23
|
+
*/
|
|
24
|
+
export function assertScriptsUsable(scripts, path) {
|
|
25
|
+
for (const [phase, source] of [
|
|
26
|
+
['pre', scripts.pre],
|
|
27
|
+
['post', scripts.post],
|
|
28
|
+
]) {
|
|
29
|
+
if (source?.problem !== undefined) {
|
|
30
|
+
const which = phase === 'pre' ? 'pre-request' : 'post-response';
|
|
31
|
+
throw new WirebenchError(source.problem, source.problem === 'script-file-missing'
|
|
32
|
+
? `"${path}": its ${which} script file is missing`
|
|
33
|
+
: `"${path}": its ${which} script is over the size limit`, { details: { path, phase } });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** A script failure as the error a send reports, with the script's file and position in it. */
|
|
38
|
+
export function scriptError(failure, filename) {
|
|
39
|
+
const where = failure.position !== undefined
|
|
40
|
+
? `${filename}:${String(failure.position.line)}:${String(failure.position.column)}`
|
|
41
|
+
: filename;
|
|
42
|
+
return new WirebenchError(failure.code, `${where}: ${failure.message}`, {
|
|
43
|
+
details: { file: filename, ...(failure.position !== undefined ? { ...failure.position } : {}) },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** A type-check failure: every error, as `file:line:column: message`. */
|
|
47
|
+
export function typeCheckError(path, errors) {
|
|
48
|
+
const lines = errors.map(({ file, diagnostic: d }) => `${file}:${String(d.line)}:${String(d.column)}: ${d.message}`);
|
|
49
|
+
return new WirebenchError('script-type-error', `"${path}" has script type errors:\n${lines.join('\n')}`, {
|
|
50
|
+
details: {
|
|
51
|
+
path,
|
|
52
|
+
errors: errors.map(({ file, diagnostic }) => ({
|
|
53
|
+
file,
|
|
54
|
+
line: diagnostic.line,
|
|
55
|
+
column: diagnostic.column,
|
|
56
|
+
message: diagnostic.message,
|
|
57
|
+
})),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Runs requests' scripts, caching each script's type check by its text and its types. */
|
|
62
|
+
export class RequestScripting {
|
|
63
|
+
options;
|
|
64
|
+
checked = new Map();
|
|
65
|
+
constructor(options) {
|
|
66
|
+
this.options = options;
|
|
67
|
+
}
|
|
68
|
+
filename(request, phase) {
|
|
69
|
+
return scriptFileName(request.slug, phase, request.scripts.api);
|
|
70
|
+
}
|
|
71
|
+
diagnostics(request, phase, source) {
|
|
72
|
+
const checker = this.options.checker;
|
|
73
|
+
if (checker === undefined)
|
|
74
|
+
return Promise.resolve([]);
|
|
75
|
+
const declarations = request.scripts.api === 'postman'
|
|
76
|
+
? ''
|
|
77
|
+
: scriptDeclarations(request.protocol, phase, request.scripts.secrets, request.types.generated, this.options.registry);
|
|
78
|
+
const key = createHash('sha256')
|
|
79
|
+
.update(request.scripts.api)
|
|
80
|
+
.update('\0')
|
|
81
|
+
.update(source.text)
|
|
82
|
+
.update('\0')
|
|
83
|
+
.update(declarations)
|
|
84
|
+
.digest('hex');
|
|
85
|
+
let found = this.checked.get(key);
|
|
86
|
+
if (found === undefined) {
|
|
87
|
+
found = checker.check({ source: source.text, declarations, api: request.scripts.api });
|
|
88
|
+
found.catch(() => this.checked.delete(key));
|
|
89
|
+
this.checked.set(key, found);
|
|
90
|
+
}
|
|
91
|
+
return found;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Type-checks a request's scripts (syntax only for a Postman one).
|
|
95
|
+
*
|
|
96
|
+
* @throws WirebenchError `script-type-error` (or `script-syntax-error` for a Postman script)
|
|
97
|
+
*/
|
|
98
|
+
async check(request) {
|
|
99
|
+
assertScriptsUsable(request.scripts, request.path);
|
|
100
|
+
const errors = [];
|
|
101
|
+
for (const phase of ['pre', 'post']) {
|
|
102
|
+
const source = request.scripts[phase];
|
|
103
|
+
if (source === undefined)
|
|
104
|
+
continue;
|
|
105
|
+
const file = this.filename(request, phase);
|
|
106
|
+
for (const diagnostic of await this.diagnostics(request, phase, source)) {
|
|
107
|
+
if (diagnostic.severity === 'error')
|
|
108
|
+
errors.push({ file, diagnostic });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (errors.length > 0) {
|
|
112
|
+
const error = typeCheckError(request.path, errors);
|
|
113
|
+
throw request.scripts.api === 'postman'
|
|
114
|
+
? new WirebenchError('script-syntax-error', error.message, { details: error.details ?? {} })
|
|
115
|
+
: error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
run(request, phase, snapshot, response, values, layer) {
|
|
119
|
+
const source = request.scripts[phase];
|
|
120
|
+
if (source === undefined)
|
|
121
|
+
throw new Error(`No ${phase} script`);
|
|
122
|
+
return runScript({
|
|
123
|
+
sandbox: this.options.sandbox,
|
|
124
|
+
phase,
|
|
125
|
+
api: request.scripts.api,
|
|
126
|
+
source: source.text,
|
|
127
|
+
filename: this.filename(request, phase),
|
|
128
|
+
...(request.scripts.timeoutMs !== undefined ? { timeoutMs: request.scripts.timeoutMs } : {}),
|
|
129
|
+
request: snapshot,
|
|
130
|
+
...(response !== undefined ? { response } : {}),
|
|
131
|
+
vars: values.vars,
|
|
132
|
+
props: values.props,
|
|
133
|
+
secrets: values.secrets,
|
|
134
|
+
requestName: request.name,
|
|
135
|
+
...(layer !== undefined ? { layer } : {}),
|
|
136
|
+
...(this.options.onSecretValue !== undefined ? { onSecretValue: this.options.onSecretValue } : {}),
|
|
137
|
+
...(request.types.binding !== undefined ? { binding: request.types.binding } : {}),
|
|
138
|
+
...(this.options.registry !== undefined ? { registry: this.options.registry } : {}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The pre-request script's outcome. A failure is thrown: the request is not sent.
|
|
143
|
+
*
|
|
144
|
+
* @throws WirebenchError with the script's error code
|
|
145
|
+
*/
|
|
146
|
+
async pre(request, snapshot, values, layer) {
|
|
147
|
+
const outcome = await this.run(request, 'pre', snapshot, undefined, values, layer);
|
|
148
|
+
if (!outcome.ok)
|
|
149
|
+
throw scriptError(outcome.error, this.filename(request, 'pre'));
|
|
150
|
+
return outcome;
|
|
151
|
+
}
|
|
152
|
+
/** The post-response script's outcome; a failure is returned, since the response is kept. */
|
|
153
|
+
post(request, sent, response, values, layer) {
|
|
154
|
+
return this.run(request, 'post', sent, response, values, layer);
|
|
155
|
+
}
|
|
156
|
+
/** The file name errors in a phase's script are reported against. */
|
|
157
|
+
fileOf(request, phase) {
|
|
158
|
+
return this.filename(request, phase);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { RequestSnapshotBase, ResponseSnapshotBase } from '../protocol/module.js';
|
|
2
|
+
import type { ProtocolRegistry } from '../protocol/registry.js';
|
|
3
|
+
import type { ResponseSnapshot } from '../protocols.js';
|
|
4
|
+
import { type ScriptApi, type ScriptOutcome, type ScriptPhase } from './model.js';
|
|
5
|
+
import type { ScriptSandbox } from './sandbox/host.js';
|
|
6
|
+
export interface ScriptRunInput {
|
|
7
|
+
readonly sandbox: ScriptSandbox;
|
|
8
|
+
readonly phase: ScriptPhase;
|
|
9
|
+
readonly api: ScriptApi;
|
|
10
|
+
/** The script as written: TypeScript for the `wirebench` API, JavaScript for `postman`. */
|
|
11
|
+
readonly source: string;
|
|
12
|
+
/** The script's file name, which errors are reported against. */
|
|
13
|
+
readonly filename: string;
|
|
14
|
+
readonly timeoutMs?: number;
|
|
15
|
+
/** For a pre-request script, the request it may change; for a post-response one, what was sent. */
|
|
16
|
+
readonly request: RequestSnapshotBase;
|
|
17
|
+
/**
|
|
18
|
+
* Required for a post-response script. Any module's response snapshot; the built-in union is
|
|
19
|
+
* named only so that a literal of one of its members type-checks.
|
|
20
|
+
*/
|
|
21
|
+
readonly response?: ResponseSnapshot | ResponseSnapshotBase;
|
|
22
|
+
/** The run's values so far (spec §Values). */
|
|
23
|
+
readonly vars: Readonly<Record<string, string>>;
|
|
24
|
+
/** Resolved properties, secrets excluded. */
|
|
25
|
+
readonly props: Readonly<Record<string, string>>;
|
|
26
|
+
/** The values of the secrets `scripts.secrets` lists, and no others. */
|
|
27
|
+
readonly secrets: Readonly<Record<string, string>>;
|
|
28
|
+
/** The request's name, for `pm.info.requestName`. */
|
|
29
|
+
readonly requestName: string;
|
|
30
|
+
/** An extra layer run after the API and before the script (the Postman one, spec §Postman). */
|
|
31
|
+
readonly layer?: string;
|
|
32
|
+
/** Called with each secret value before the script runs, so it is masked wherever it lands. */
|
|
33
|
+
readonly onSecretValue?: (value: string) => void;
|
|
34
|
+
/**
|
|
35
|
+
* What the request's module put on its script types for typed views (`RequestScriptTypes.binding`).
|
|
36
|
+
* For SOAP: the schema and the operation's elements, which give the script a typed `request.body`
|
|
37
|
+
* and `response.body`. Without it the body is only reachable as `envelope`.
|
|
38
|
+
*/
|
|
39
|
+
readonly binding?: unknown;
|
|
40
|
+
/** Where the request's protocol is looked up; the built-in registry when absent. */
|
|
41
|
+
readonly registry?: ProtocolRegistry;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Runs one script. A request whose protocol has no scripting facet in the registry fails with
|
|
45
|
+
* `script-unsupported`, and nothing runs.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runScript(input: ScriptRunInput): Promise<ScriptOutcome>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs one pre-request or post-response script and checks what it hands back (spec §API, §Results).
|
|
3
|
+
*
|
|
4
|
+
* The caller supplies the request (and, after a send, the response) as a snapshot, the run's values,
|
|
5
|
+
* the non-secret properties and only the secrets the request file lists. Each of those secrets is
|
|
6
|
+
* reported to `onSecretValue` before the script runs, so whatever the script does with one — log it,
|
|
7
|
+
* set it as a value, write it into the request — is masked downstream.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { TRANSFER_NAME_PATTERN } from '../sequence/model.js';
|
|
11
|
+
import { applyRequestChanges } from './apply.js';
|
|
12
|
+
import { buildPrelude } from './api/prelude.js';
|
|
13
|
+
import { POSTMAN_LAYER } from './api/postman.js';
|
|
14
|
+
import { scriptingOf } from './lookup.js';
|
|
15
|
+
import { SCRIPT_OUTPUT_LIMITS, } from './model.js';
|
|
16
|
+
import { StripError, stripTypes } from './strip.js';
|
|
17
|
+
/** A rule's error, raised in the sandbox by name (`api/prelude.ts`), mapped to its code. */
|
|
18
|
+
const CODE_BY_ERROR_NAME = {
|
|
19
|
+
ScriptSecretDenied: 'script-secret-denied',
|
|
20
|
+
ScriptValueInvalid: 'script-value-invalid',
|
|
21
|
+
ScriptUnsupported: 'script-unsupported',
|
|
22
|
+
};
|
|
23
|
+
const outputSchema = z.object({
|
|
24
|
+
tests: z
|
|
25
|
+
.array(z.object({ name: z.string(), passed: z.boolean(), message: z.string().optional() }))
|
|
26
|
+
.max(SCRIPT_OUTPUT_LIMITS.tests),
|
|
27
|
+
values: z
|
|
28
|
+
.array(z.object({
|
|
29
|
+
name: z.string().regex(TRANSFER_NAME_PATTERN),
|
|
30
|
+
value: z.string().refine((v) => Buffer.byteLength(v, 'utf8') <= SCRIPT_OUTPUT_LIMITS.valueBytes),
|
|
31
|
+
secret: z.boolean(),
|
|
32
|
+
}))
|
|
33
|
+
.max(SCRIPT_OUTPUT_LIMITS.values),
|
|
34
|
+
request: z.unknown().optional(),
|
|
35
|
+
});
|
|
36
|
+
function failureOf(error) {
|
|
37
|
+
if (error.code === 'script-error') {
|
|
38
|
+
const name = /^(\w+):/.exec(error.message)?.[1];
|
|
39
|
+
const code = name !== undefined ? CODE_BY_ERROR_NAME[name] : undefined;
|
|
40
|
+
if (code !== undefined) {
|
|
41
|
+
return { ...error, code, message: error.message.slice((name ?? '').length + 1).trim() };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return error;
|
|
45
|
+
}
|
|
46
|
+
function readOutput(output) {
|
|
47
|
+
const parsed = outputSchema.safeParse(output);
|
|
48
|
+
return parsed.success ? parsed.data : undefined;
|
|
49
|
+
}
|
|
50
|
+
const cleanTests = (tests) => tests.map((t) => ({ name: t.name, passed: t.passed, ...(t.message !== undefined ? { message: t.message } : {}) }));
|
|
51
|
+
/**
|
|
52
|
+
* Runs one script. A request whose protocol has no scripting facet in the registry fails with
|
|
53
|
+
* `script-unsupported`, and nothing runs.
|
|
54
|
+
*/
|
|
55
|
+
export async function runScript(input) {
|
|
56
|
+
const empty = { tests: [], values: [], log: { lines: [], truncated: false } };
|
|
57
|
+
if (input.phase === 'post' && input.response === undefined) {
|
|
58
|
+
throw new Error('runScript: a post-response script needs the response');
|
|
59
|
+
}
|
|
60
|
+
const scripting = scriptingOf(input.request.protocol, input.registry);
|
|
61
|
+
if (scripting === undefined) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
error: {
|
|
65
|
+
code: 'script-unsupported',
|
|
66
|
+
message: `Requests of the "${input.request.protocol}" protocol cannot have scripts`,
|
|
67
|
+
},
|
|
68
|
+
...empty,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
let code;
|
|
72
|
+
try {
|
|
73
|
+
code = input.api === 'wirebench' ? stripTypes(input.source) : input.source;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return {
|
|
77
|
+
ok: false,
|
|
78
|
+
error: { code: 'script-syntax-error', message: error instanceof StripError ? error.message : String(error) },
|
|
79
|
+
...empty,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
for (const value of Object.values(input.secrets)) {
|
|
83
|
+
input.onSecretValue?.(value);
|
|
84
|
+
}
|
|
85
|
+
// The views read only the binding; a script's generated types are the checker's business.
|
|
86
|
+
const types = {
|
|
87
|
+
generated: '',
|
|
88
|
+
...(input.binding !== undefined ? { binding: input.binding } : {}),
|
|
89
|
+
};
|
|
90
|
+
const request = scripting.views?.request(input.request, types) ?? input.request;
|
|
91
|
+
const response = input.response === undefined ? undefined : (scripting.views?.response(input.response, types) ?? input.response);
|
|
92
|
+
const result = await input.sandbox.run({
|
|
93
|
+
prelude: buildPrelude(scripting, input.phase, input.api, input.layer ?? (input.api === 'postman' ? POSTMAN_LAYER : undefined)),
|
|
94
|
+
code,
|
|
95
|
+
filename: input.filename,
|
|
96
|
+
timeoutMs: input.timeoutMs ?? 0,
|
|
97
|
+
input: {
|
|
98
|
+
phase: input.phase,
|
|
99
|
+
request,
|
|
100
|
+
...(response !== undefined ? { response } : {}),
|
|
101
|
+
vars: input.vars,
|
|
102
|
+
props: input.props,
|
|
103
|
+
secrets: input.secrets,
|
|
104
|
+
info: { requestName: input.requestName },
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const output = readOutput(result.ok ? result.output : result.output);
|
|
108
|
+
const tests = output !== undefined ? cleanTests(output.tests) : [];
|
|
109
|
+
const values = output?.values ?? [];
|
|
110
|
+
if (!result.ok) {
|
|
111
|
+
return { ok: false, error: failureOf(result.error), tests, values, log: result.log };
|
|
112
|
+
}
|
|
113
|
+
if (output === undefined) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
error: { code: 'script-error', message: 'The script handed back something the engine cannot read' },
|
|
117
|
+
...empty,
|
|
118
|
+
log: result.log,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (input.phase === 'pre') {
|
|
122
|
+
const applied = applyRequestChanges(scripting, request, output.request);
|
|
123
|
+
if (!applied.ok) {
|
|
124
|
+
return { ok: false, error: applied.error, tests, values, log: result.log };
|
|
125
|
+
}
|
|
126
|
+
const written = scripting.views?.writeBack(request, applied.request, types) ?? {
|
|
127
|
+
ok: true,
|
|
128
|
+
request: applied.request,
|
|
129
|
+
};
|
|
130
|
+
if (!written.ok) {
|
|
131
|
+
return { ok: false, error: written.error, tests, values, log: result.log };
|
|
132
|
+
}
|
|
133
|
+
if (scripting.views === undefined) {
|
|
134
|
+
return { ok: true, request: written.request, tests, values, log: result.log };
|
|
135
|
+
}
|
|
136
|
+
// A view (SOAP's `request.body`) is written back after the rules ran, so what it wrote has not
|
|
137
|
+
// been checked yet: hold the request that is sent to the rules again, against the one the
|
|
138
|
+
// script was given. Otherwise a script could name any secret through the view.
|
|
139
|
+
const checked = applyRequestChanges(scripting, input.request, written.request);
|
|
140
|
+
if (!checked.ok) {
|
|
141
|
+
return { ok: false, error: checked.error, tests, values, log: result.log };
|
|
142
|
+
}
|
|
143
|
+
return { ok: true, request: checked.request, tests, values, log: result.log };
|
|
144
|
+
}
|
|
145
|
+
return { ok: true, tests, values, log: result.log };
|
|
146
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs one {@link SandboxJob} in a fresh QuickJS runtime (ADR-0016).
|
|
3
|
+
*
|
|
4
|
+
* The runtime gets a memory limit, a stack limit and an interrupt handler with the job's deadline,
|
|
5
|
+
* and a context holding nothing but the ECMAScript library and `__host`, an object of plain
|
|
6
|
+
* functions of strings. The prelude builds the script's API from those, the script runs, and
|
|
7
|
+
* `__finish()` hands back the result as JSON text. Every handle is disposed before this returns, and
|
|
8
|
+
* the runtime with it: nothing a script did survives into the next job.
|
|
9
|
+
*
|
|
10
|
+
* This runs inside the sandbox worker (`worker.ts`). Its stack must be larger than the QuickJS stack
|
|
11
|
+
* limit, or a deep recursion overflows the host's stack before QuickJS's own check trips; the host
|
|
12
|
+
* starts the worker with room to spare.
|
|
13
|
+
*/
|
|
14
|
+
import type { QuickJSWASMModule } from 'quickjs-emscripten-core';
|
|
15
|
+
import { type SandboxError, type SandboxJob, type SandboxResult, type ScriptPosition } from './model.js';
|
|
16
|
+
/** What the worker hands back: the result, and whether the runtime ended in a state worth not reusing the worker after. */
|
|
17
|
+
export interface ExecuteOutcome {
|
|
18
|
+
readonly result: SandboxResult;
|
|
19
|
+
/** True after a timeout, memory exhaustion or a failed dispose: the host replaces the worker. */
|
|
20
|
+
readonly recycle: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** The first `file:line:column` of the script's own file in a QuickJS stack. */
|
|
23
|
+
export declare function positionIn(stack: string, filename: string): ScriptPosition | undefined;
|
|
24
|
+
/** Maps what the script threw to the sandbox's error codes. */
|
|
25
|
+
export declare function toSandboxError(value: unknown, filename: string, interrupted: boolean): SandboxError;
|
|
26
|
+
export declare function executeJob(module: QuickJSWASMModule, job: SandboxJob): ExecuteOutcome;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { base64, base64url, fromBase64, hash, hmac, HostCallError, LogCollector, urlEncode, uuid, xpathStrings, } from './host-api.js';
|
|
2
|
+
import { SCRIPT_LIMITS } from './model.js';
|
|
3
|
+
const PRELUDE_FILE = '<prelude>';
|
|
4
|
+
const FINISH_FILE = '<finish>';
|
|
5
|
+
function escapeRegExp(text) {
|
|
6
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
7
|
+
}
|
|
8
|
+
/** The first `file:line:column` of the script's own file in a QuickJS stack. */
|
|
9
|
+
export function positionIn(stack, filename) {
|
|
10
|
+
const match = new RegExp(`${escapeRegExp(filename)}:(\\d+):(\\d+)`).exec(stack);
|
|
11
|
+
if (match === null) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return { line: Number(match[1]), column: Number(match[2]) };
|
|
15
|
+
}
|
|
16
|
+
function describe(value) {
|
|
17
|
+
if (typeof value === 'object' && value !== null) {
|
|
18
|
+
const error = value;
|
|
19
|
+
const name = typeof error.name === 'string' ? error.name : undefined;
|
|
20
|
+
const message = typeof error.message === 'string' ? error.message : undefined;
|
|
21
|
+
const stack = typeof error.stack === 'string' ? error.stack : '';
|
|
22
|
+
if (message !== undefined) {
|
|
23
|
+
return {
|
|
24
|
+
text: name !== undefined ? `${name}: ${message}` : message,
|
|
25
|
+
...(name !== undefined ? { name } : {}),
|
|
26
|
+
stack,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (typeof value === 'string') {
|
|
31
|
+
return { text: value, stack: '' };
|
|
32
|
+
}
|
|
33
|
+
let text;
|
|
34
|
+
try {
|
|
35
|
+
text = JSON.stringify(value) ?? String(value);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
text = String(value);
|
|
39
|
+
}
|
|
40
|
+
return { text, stack: '' };
|
|
41
|
+
}
|
|
42
|
+
/** Maps what the script threw to the sandbox's error codes. */
|
|
43
|
+
export function toSandboxError(value, filename, interrupted) {
|
|
44
|
+
const { text, name, stack } = describe(value);
|
|
45
|
+
if (interrupted || (name === 'InternalError' && text.endsWith('interrupted'))) {
|
|
46
|
+
return { code: 'script-timeout', message: 'The script ran past its time limit' };
|
|
47
|
+
}
|
|
48
|
+
if (name === 'InternalError' && text.endsWith('out of memory')) {
|
|
49
|
+
return { code: 'script-memory', message: 'The script ran out of memory' };
|
|
50
|
+
}
|
|
51
|
+
const position = positionIn(stack, filename);
|
|
52
|
+
return { code: 'script-error', message: text, ...(position !== undefined ? { position } : {}) };
|
|
53
|
+
}
|
|
54
|
+
/** A host function's argument as a string; anything else is refused with a message the script sees. */
|
|
55
|
+
function stringArg(context, handle, what) {
|
|
56
|
+
const value = handle === undefined ? undefined : context.dump(handle);
|
|
57
|
+
if (typeof value !== 'string') {
|
|
58
|
+
throw new HostCallError(`${what} must be a string`);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function optionalStringArg(context, handle, what) {
|
|
63
|
+
const value = handle === undefined ? undefined : context.dump(handle);
|
|
64
|
+
if (value === undefined) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
if (typeof value !== 'string') {
|
|
68
|
+
throw new HostCallError(`${what} must be a string`);
|
|
69
|
+
}
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
/** Installs `__host`: plain functions of strings, and nothing else of the host. */
|
|
73
|
+
function installHost(context, log, inputJson) {
|
|
74
|
+
const functions = {
|
|
75
|
+
log: (ctx, args) => {
|
|
76
|
+
log.add(stringArg(ctx, args[0], 'a log line'));
|
|
77
|
+
return undefined;
|
|
78
|
+
},
|
|
79
|
+
hash: (ctx, args) => ctx.newString(hash(stringArg(ctx, args[0], 'algorithm'), stringArg(ctx, args[1], 'data'), optionalStringArg(ctx, args[2], 'encoding'))),
|
|
80
|
+
hmac: (ctx, args) => ctx.newString(hmac(stringArg(ctx, args[0], 'algorithm'), stringArg(ctx, args[1], 'key'), stringArg(ctx, args[2], 'data'), optionalStringArg(ctx, args[3], 'encoding'))),
|
|
81
|
+
uuid: (ctx) => ctx.newString(uuid()),
|
|
82
|
+
base64: (ctx, args) => ctx.newString(base64(stringArg(ctx, args[0], 'text'))),
|
|
83
|
+
fromBase64: (ctx, args) => ctx.newString(fromBase64(stringArg(ctx, args[0], 'text'))),
|
|
84
|
+
base64url: (ctx, args) => ctx.newString(base64url(stringArg(ctx, args[0], 'text'))),
|
|
85
|
+
urlEncode: (ctx, args) => ctx.newString(urlEncode(stringArg(ctx, args[0], 'text'))),
|
|
86
|
+
xpath: (ctx, args) => ctx.newString(xpathStrings(stringArg(ctx, args[0], 'xml'), stringArg(ctx, args[1], 'expression'), stringArg(ctx, args[2], 'namespaces'))),
|
|
87
|
+
};
|
|
88
|
+
const host = context.newObject();
|
|
89
|
+
try {
|
|
90
|
+
for (const [name, implementation] of Object.entries(functions)) {
|
|
91
|
+
const fn = context.newFunction(name, (...args) => {
|
|
92
|
+
try {
|
|
93
|
+
return implementation(context, args);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
const message = error instanceof HostCallError ? error.message : 'the host function failed';
|
|
97
|
+
return { error: context.newError(`${name}: ${message}`) };
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
context.setProp(host, name, fn);
|
|
101
|
+
fn.dispose();
|
|
102
|
+
}
|
|
103
|
+
const input = context.newString(inputJson);
|
|
104
|
+
context.setProp(host, 'inputJson', input);
|
|
105
|
+
input.dispose();
|
|
106
|
+
context.setProp(context.global, '__host', host);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
host.dispose();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Evaluates code and returns its value dumped to plain data, or what it threw. */
|
|
113
|
+
function evaluate(context, code, filename) {
|
|
114
|
+
const result = context.evalCode(code, filename, { type: 'global', strict: true, backtraceBarrier: true });
|
|
115
|
+
if ('error' in result && result.error !== undefined) {
|
|
116
|
+
const thrown = context.dump(result.error);
|
|
117
|
+
result.error.dispose();
|
|
118
|
+
return { ok: false, thrown };
|
|
119
|
+
}
|
|
120
|
+
const value = context.dump(result.value);
|
|
121
|
+
result.value.dispose();
|
|
122
|
+
return { ok: true, value };
|
|
123
|
+
}
|
|
124
|
+
/** `__finish()`'s JSON, parsed; refused when it is not text or is past the output cap. */
|
|
125
|
+
function finish(context) {
|
|
126
|
+
const done = evaluate(context, 'JSON.stringify(__finish())', FINISH_FILE);
|
|
127
|
+
if (!done.ok) {
|
|
128
|
+
return { ok: false, error: toSandboxError(done.thrown, FINISH_FILE, false) };
|
|
129
|
+
}
|
|
130
|
+
if (typeof done.value !== 'string') {
|
|
131
|
+
return { ok: true, output: undefined };
|
|
132
|
+
}
|
|
133
|
+
if (Buffer.byteLength(done.value, 'utf8') > SCRIPT_LIMITS.outputBytes) {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
error: { code: 'script-error', message: 'The script handed back more than its output limit allows' },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return { ok: true, output: JSON.parse(done.value) };
|
|
140
|
+
}
|
|
141
|
+
export function executeJob(module, job) {
|
|
142
|
+
const log = new LogCollector();
|
|
143
|
+
const runtime = module.newRuntime();
|
|
144
|
+
let interrupted = false;
|
|
145
|
+
let recycle = false;
|
|
146
|
+
const deadline = Date.now() + job.timeoutMs;
|
|
147
|
+
runtime.setMemoryLimit(SCRIPT_LIMITS.memoryBytes);
|
|
148
|
+
runtime.setMaxStackSize(SCRIPT_LIMITS.stackBytes);
|
|
149
|
+
runtime.setInterruptHandler(() => {
|
|
150
|
+
if (Date.now() > deadline) {
|
|
151
|
+
interrupted = true;
|
|
152
|
+
}
|
|
153
|
+
return interrupted;
|
|
154
|
+
});
|
|
155
|
+
const context = runtime.newContext();
|
|
156
|
+
let result;
|
|
157
|
+
try {
|
|
158
|
+
installHost(context, log, JSON.stringify(job.input ?? null));
|
|
159
|
+
const prelude = evaluate(context, job.prelude, PRELUDE_FILE);
|
|
160
|
+
if (!prelude.ok) {
|
|
161
|
+
const error = toSandboxError(prelude.thrown, PRELUDE_FILE, interrupted);
|
|
162
|
+
result = {
|
|
163
|
+
ok: false,
|
|
164
|
+
error: error.code === 'script-error'
|
|
165
|
+
? { code: 'script-error', message: `The script API failed to start: ${error.message}` }
|
|
166
|
+
: error,
|
|
167
|
+
log: log.result(),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const ran = evaluate(context, job.code, job.filename);
|
|
172
|
+
if (ran.ok) {
|
|
173
|
+
const done = finish(context);
|
|
174
|
+
result = done.ok
|
|
175
|
+
? { ok: true, output: done.output, log: log.result() }
|
|
176
|
+
: { ok: false, error: done.error, log: log.result() };
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const error = toSandboxError(ran.thrown, job.filename, interrupted);
|
|
180
|
+
// A script that threw may still have recorded tests before it did; keep them. A script that
|
|
181
|
+
// ran out of time or memory gets nothing more run on its behalf.
|
|
182
|
+
const done = error.code === 'script-error' ? finish(context) : undefined;
|
|
183
|
+
result = {
|
|
184
|
+
ok: false,
|
|
185
|
+
error,
|
|
186
|
+
log: log.result(),
|
|
187
|
+
...(done?.ok === true ? { output: done.output } : {}),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
// The host itself failed (for instance the WASM heap was exhausted outside the runtime's limit).
|
|
194
|
+
recycle = true;
|
|
195
|
+
result = {
|
|
196
|
+
ok: false,
|
|
197
|
+
error: { code: 'script-error', message: error instanceof Error ? error.message : String(error) },
|
|
198
|
+
log: log.result(),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (!result.ok && result.error.code !== 'script-error') {
|
|
202
|
+
recycle = true;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
context.dispose();
|
|
206
|
+
runtime.dispose();
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
recycle = true;
|
|
210
|
+
}
|
|
211
|
+
return { result, recycle };
|
|
212
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type SandboxLog } from './model.js';
|
|
2
|
+
export declare const HASH_ALGORITHMS: readonly ["md5", "sha1", "sha256", "sha512"];
|
|
3
|
+
export declare const HMAC_ALGORITHMS: readonly ["sha1", "sha256", "sha512"];
|
|
4
|
+
export declare const DIGEST_ENCODINGS: readonly ["hex", "base64"];
|
|
5
|
+
/** Thrown into the script (as its message) when a host function is called with something it refuses. */
|
|
6
|
+
export declare class HostCallError extends Error {
|
|
7
|
+
}
|
|
8
|
+
export declare function hash(algorithm: string, data: string, encoding?: string): string;
|
|
9
|
+
export declare function hmac(algorithm: string, key: string, data: string, encoding?: string): string;
|
|
10
|
+
export declare function uuid(): string;
|
|
11
|
+
export declare function base64(text: string): string;
|
|
12
|
+
export declare function fromBase64(text: string): string;
|
|
13
|
+
export declare function base64url(text: string): string;
|
|
14
|
+
export declare function urlEncode(text: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* The strings an XPath expression selects in `xml`, as JSON text: each node's text, or each value.
|
|
17
|
+
* `namespacesJson` is a JSON object of prefix to URI.
|
|
18
|
+
*/
|
|
19
|
+
export declare function xpathStrings(xml: string, expression: string, namespacesJson: string): string;
|
|
20
|
+
/** Collects `log(...)` lines within the caps; anything past them is dropped and flagged. */
|
|
21
|
+
export declare class LogCollector {
|
|
22
|
+
private readonly lines;
|
|
23
|
+
private bytes;
|
|
24
|
+
private truncated;
|
|
25
|
+
add(line: string): void;
|
|
26
|
+
result(): SandboxLog;
|
|
27
|
+
}
|