@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,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks a received REST response against the schema its OpenAPI operation declares for it.
|
|
3
|
+
*
|
|
4
|
+
* Pure and synchronous, plain data in and out, so it can run in a worker: a contract's `pattern` is
|
|
5
|
+
* untrusted, and the time budget here only stops the check between steps (reporting `not-checked`,
|
|
6
|
+
* neither a pass nor a failure) — the worker is what bounds a single call that runs away.
|
|
7
|
+
*/
|
|
8
|
+
import { unsupportedKeywordsIn, validateJsonSchema } from '../json/schema-validate.js';
|
|
9
|
+
import { selectResponse } from './openapi/responses.js';
|
|
10
|
+
/** A body bigger than this (UTF-8 bytes) is not parsed or validated: it is reported `skipped`. */
|
|
11
|
+
export const MAX_CHECKED_BODY_BYTES = 1_048_576;
|
|
12
|
+
/** The default time one response's check may take before it gives up as `not-checked`. */
|
|
13
|
+
export const DEFAULT_REST_CHECK_BUDGET_MS = 200;
|
|
14
|
+
export const MAX_CONTRACT_PROBLEMS = 50;
|
|
15
|
+
export const MAX_CONTRACT_MESSAGE_LENGTH = 300;
|
|
16
|
+
/**
|
|
17
|
+
* Schema nodes one check may visit. Generous, since a real response (hundreds of rows of dozens of
|
|
18
|
+
* properties) must be checkable: the worker's deadline is what bounds the time, and this only stops a
|
|
19
|
+
* body the deadline would let through yet is still too big to finish.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_REST_CHECK_NODES = 200_000;
|
|
22
|
+
export const MAX_CONTRACT_PATH_LENGTH = 300;
|
|
23
|
+
/** Value nodes the `writeOnly` pass may visit; it walks the value, so the schema's shape cannot loop it. */
|
|
24
|
+
const MAX_WRITE_ONLY_NODES = MAX_REST_CHECK_NODES;
|
|
25
|
+
function utf8Length(text, limit) {
|
|
26
|
+
if (text.length > limit)
|
|
27
|
+
return text.length;
|
|
28
|
+
if (text.length * 3 <= limit)
|
|
29
|
+
return text.length;
|
|
30
|
+
return new TextEncoder().encode(text).length;
|
|
31
|
+
}
|
|
32
|
+
function capped(problems) {
|
|
33
|
+
return problems.slice(0, MAX_CONTRACT_PROBLEMS).map((p) => ({
|
|
34
|
+
path: p.path.length > MAX_CONTRACT_PATH_LENGTH ? p.path.slice(0, MAX_CONTRACT_PATH_LENGTH) : p.path,
|
|
35
|
+
keyword: p.keyword,
|
|
36
|
+
message: p.message.length > MAX_CONTRACT_MESSAGE_LENGTH ? p.message.slice(0, MAX_CONTRACT_MESSAGE_LENGTH) : p.message,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
function isObject(v) {
|
|
40
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
41
|
+
}
|
|
42
|
+
function escapeSegment(key) {
|
|
43
|
+
return key.replace(/~/g, '~0').replace(/\//g, '~1');
|
|
44
|
+
}
|
|
45
|
+
/** The schema that applies to item `i`: a tuple's own (`prefixItems`, or draft-07 array `items`), then the rest. */
|
|
46
|
+
function itemSchema(sch, i) {
|
|
47
|
+
const items = sch['items'];
|
|
48
|
+
const prefix = Array.isArray(sch['prefixItems']) ? sch['prefixItems'] : Array.isArray(items) ? items : undefined;
|
|
49
|
+
if (prefix !== undefined && i < prefix.length)
|
|
50
|
+
return prefix[i];
|
|
51
|
+
if (Array.isArray(sch['prefixItems']))
|
|
52
|
+
return items;
|
|
53
|
+
return Array.isArray(items) ? sch['additionalItems'] : items;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Every present property whose schema says `writeOnly: true`. `allOf` is always followed; an
|
|
57
|
+
* `anyOf`/`oneOf` branch only when the value matches it, so a write-only property of an alternative
|
|
58
|
+
* the value is not does not count. Composition keywords are followed without moving in the value,
|
|
59
|
+
* so a per-value set of schemas already applied stops a cycle there; everything else descends into
|
|
60
|
+
* the value, which is finite and bounded by the node cap.
|
|
61
|
+
*/
|
|
62
|
+
function writeOnlyProblems(value, schema, max, expired) {
|
|
63
|
+
const problems = [];
|
|
64
|
+
let nodes = 0;
|
|
65
|
+
let capped = false;
|
|
66
|
+
let outOfTime = false;
|
|
67
|
+
let undecided = false;
|
|
68
|
+
const halted = () => {
|
|
69
|
+
if (problems.length >= max || capped || outOfTime)
|
|
70
|
+
return true;
|
|
71
|
+
if (nodes >= MAX_WRITE_ONLY_NODES)
|
|
72
|
+
capped = true;
|
|
73
|
+
else if (expired())
|
|
74
|
+
outOfTime = true;
|
|
75
|
+
return capped || outOfTime;
|
|
76
|
+
};
|
|
77
|
+
const visit = (val, sch, path, applied) => {
|
|
78
|
+
if (!isObject(sch) || applied.has(sch) || halted())
|
|
79
|
+
return;
|
|
80
|
+
applied.add(sch);
|
|
81
|
+
nodes++;
|
|
82
|
+
const allOf = sch['allOf'];
|
|
83
|
+
if (Array.isArray(allOf))
|
|
84
|
+
for (const b of allOf)
|
|
85
|
+
visit(val, b, path, applied);
|
|
86
|
+
for (const keyword of ['anyOf', 'oneOf']) {
|
|
87
|
+
const branches = sch[keyword];
|
|
88
|
+
if (!Array.isArray(branches))
|
|
89
|
+
continue;
|
|
90
|
+
for (const b of branches) {
|
|
91
|
+
if (halted())
|
|
92
|
+
return;
|
|
93
|
+
const trial = validateJsonSchema(val, b, { maxProblems: 1 });
|
|
94
|
+
if (trial.length === 0)
|
|
95
|
+
visit(val, b, path, applied);
|
|
96
|
+
else if (trial[0]?.keyword === 'budget')
|
|
97
|
+
undecided = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (Array.isArray(val)) {
|
|
101
|
+
val.forEach((item, i) => visit(item, itemSchema(sch, i), `${path}/${i}`, new Set()));
|
|
102
|
+
}
|
|
103
|
+
else if (isObject(val)) {
|
|
104
|
+
const properties = isObject(sch['properties']) ? sch['properties'] : {};
|
|
105
|
+
for (const key of Object.keys(val)) {
|
|
106
|
+
const childPath = `${path}/${escapeSegment(key)}`;
|
|
107
|
+
const own = Object.prototype.hasOwnProperty.call(properties, key);
|
|
108
|
+
const propSchema = own ? properties[key] : sch['additionalProperties'];
|
|
109
|
+
if (isObject(propSchema) && propSchema['writeOnly'] === true && problems.length < max) {
|
|
110
|
+
problems.push({
|
|
111
|
+
path: childPath,
|
|
112
|
+
keyword: 'writeOnly',
|
|
113
|
+
message: `"${key}" is write-only and must not be in a response`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
visit(val[key], propSchema, childPath, new Set());
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
visit(value, schema, '', new Set());
|
|
121
|
+
return { problems, capped, expired: outOfTime, undecided };
|
|
122
|
+
}
|
|
123
|
+
export function checkRestResponse(input, options) {
|
|
124
|
+
const skipped = { status: 'skipped', problems: [], notes: [] };
|
|
125
|
+
if (input.language !== 'json' || input.streamed)
|
|
126
|
+
return skipped;
|
|
127
|
+
if (utf8Length(input.bodyText, MAX_CHECKED_BODY_BYTES) > MAX_CHECKED_BODY_BYTES)
|
|
128
|
+
return skipped;
|
|
129
|
+
const { operation, responses } = input;
|
|
130
|
+
if (operation === undefined || responses === undefined)
|
|
131
|
+
return { status: 'no-contract', problems: [], notes: [] };
|
|
132
|
+
// Only a body detected as JSON gets here, so one with no Content-Type is read as `application/json`.
|
|
133
|
+
const contentType = input.contentType?.trim() ? input.contentType : 'application/json';
|
|
134
|
+
const selection = selectResponse(responses, input.status, contentType);
|
|
135
|
+
if (selection.kind === 'unmatched') {
|
|
136
|
+
return {
|
|
137
|
+
status: 'unmatched',
|
|
138
|
+
operation,
|
|
139
|
+
problems: [],
|
|
140
|
+
notes: [`the contract declares no ${input.status} response`],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const { responseKey } = selection;
|
|
144
|
+
if (selection.kind === 'no-body') {
|
|
145
|
+
if (input.bodyText.trim() === '')
|
|
146
|
+
return { status: 'ok', operation, responseKey, problems: [], notes: [] };
|
|
147
|
+
return {
|
|
148
|
+
status: 'violation',
|
|
149
|
+
operation,
|
|
150
|
+
responseKey,
|
|
151
|
+
problems: [{ path: '', keyword: 'body', message: 'the contract declares no body' }],
|
|
152
|
+
notes: [],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (selection.kind === 'no-schema')
|
|
156
|
+
return { status: 'no-schema', operation, responseKey, problems: [], notes: [] };
|
|
157
|
+
const { mediaType, schema } = selection;
|
|
158
|
+
const found = { operation, responseKey, mediaType };
|
|
159
|
+
let value;
|
|
160
|
+
try {
|
|
161
|
+
value = JSON.parse(input.bodyText);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return {
|
|
165
|
+
status: 'violation',
|
|
166
|
+
...found,
|
|
167
|
+
problems: [{ path: '', keyword: 'json', message: 'not valid JSON' }],
|
|
168
|
+
notes: [],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const now = options?.now ?? (() => performance.now());
|
|
172
|
+
const budgetMs = options?.budgetMs ?? DEFAULT_REST_CHECK_BUDGET_MS;
|
|
173
|
+
const start = now();
|
|
174
|
+
const notes = unsupportedKeywordsIn(schema).map((k) => `\`${k}\` is not checked`);
|
|
175
|
+
const notChecked = { status: 'not-checked', ...found, problems: [], notes };
|
|
176
|
+
const expired = () => now() - start > budgetMs;
|
|
177
|
+
let problems;
|
|
178
|
+
let stopped;
|
|
179
|
+
try {
|
|
180
|
+
const checked = validateJsonSchema(value, schema, {
|
|
181
|
+
maxProblems: MAX_CONTRACT_PROBLEMS,
|
|
182
|
+
maxNodes: MAX_REST_CHECK_NODES,
|
|
183
|
+
redactValues: true,
|
|
184
|
+
});
|
|
185
|
+
if (expired())
|
|
186
|
+
return notChecked;
|
|
187
|
+
// A stop on the node or depth cap is not a fault of the body: it only means part went unchecked.
|
|
188
|
+
stopped = checked.find((p) => p.keyword === 'budget')?.message;
|
|
189
|
+
problems = checked.filter((p) => p.keyword !== 'budget');
|
|
190
|
+
if (problems.length < MAX_CONTRACT_PROBLEMS) {
|
|
191
|
+
const pass = writeOnlyProblems(value, schema, MAX_CONTRACT_PROBLEMS - problems.length, expired);
|
|
192
|
+
if (pass.expired)
|
|
193
|
+
return notChecked;
|
|
194
|
+
problems.push(...pass.problems);
|
|
195
|
+
if (pass.capped)
|
|
196
|
+
notes.push(`write-only check stopped after ${MAX_WRITE_ONLY_NODES} nodes`);
|
|
197
|
+
if (pass.undecided) {
|
|
198
|
+
notes.push('write-only check could not tell which anyOf/oneOf branch a value matches, so did not follow it');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
// The validator stops self-referencing schemas itself; this is the last resort should some
|
|
204
|
+
// shape still exhaust the stack.
|
|
205
|
+
if (error instanceof RangeError)
|
|
206
|
+
return notChecked;
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
if (expired())
|
|
210
|
+
return notChecked;
|
|
211
|
+
if (stopped !== undefined) {
|
|
212
|
+
if (problems.length === 0)
|
|
213
|
+
return { ...notChecked, notes: [stopped, ...notes] };
|
|
214
|
+
notes.unshift(`partial check: ${stopped}`);
|
|
215
|
+
}
|
|
216
|
+
return { status: problems.length === 0 ? 'ok' : 'violation', ...found, problems: capped(problems), notes };
|
|
217
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cookie jar (cookie jar and current values spec §1): what REST responses set, kept per
|
|
3
|
+
* workspace in the app and per run on the command line, and sent back by requests whose *Send
|
|
4
|
+
* cookies* setting is on.
|
|
5
|
+
*
|
|
6
|
+
* Storing follows RFC 6265 §5.3, and RFC 6265bis §5.6 for Secure. A cookie's identity is its name,
|
|
7
|
+
* domain and path. A newer cookie replaces an older one but keeps its creation time. A cookie that
|
|
8
|
+
* is already expired deletes the stored one instead. There is no public-suffix list: see
|
|
9
|
+
* `docs/security.md`, "The cookie jar".
|
|
10
|
+
*/
|
|
11
|
+
import type { Cookie, CookieJarHost, CookieKey, CookieVerdict, StoredCookie } from '../http/cookies.js';
|
|
12
|
+
export type { CookieJarHost, CookieKey, CookieRejection, CookieVerdict, StoredCookie } from '../http/cookies.js';
|
|
13
|
+
/** At most this many cookies per domain (spec §1.2). */
|
|
14
|
+
export declare const MAX_COOKIES_PER_DOMAIN = 50;
|
|
15
|
+
/** At most this many cookies in one jar. */
|
|
16
|
+
export declare const MAX_COOKIES = 3000;
|
|
17
|
+
/** A name plus value over this many UTF-8 bytes is not stored. */
|
|
18
|
+
export declare const MAX_COOKIE_BYTES = 4096;
|
|
19
|
+
export declare class CookieJar {
|
|
20
|
+
private readonly cookies;
|
|
21
|
+
constructor(initial?: readonly StoredCookie[]);
|
|
22
|
+
/** Stores what a response to `url` set, at `now`: one verdict per cookie, in order. */
|
|
23
|
+
store(url: string, cookies: readonly Cookie[], now: number): CookieVerdict[];
|
|
24
|
+
/** The cookies a request to `url` carries at `now`, in RFC 6265 §5.4 order. */
|
|
25
|
+
cookiesFor(url: string, now: number): StoredCookie[];
|
|
26
|
+
/** Every unexpired cookie, by domain, then name, then path. */
|
|
27
|
+
list(now: number): StoredCookie[];
|
|
28
|
+
/**
|
|
29
|
+
* Stores `cookie` as given, replacing one of the same identity. The manager's edit: the domain and
|
|
30
|
+
* Secure rules are skipped (it picks its own domain), but the jar's size limits still hold.
|
|
31
|
+
*/
|
|
32
|
+
set(cookie: StoredCookie, now?: number): void;
|
|
33
|
+
remove(key: CookieKey): boolean;
|
|
34
|
+
/** Removes every cookie stored under `domain` (lowercased, leading dot ignored); how many went. */
|
|
35
|
+
removeDomain(domain: string): number;
|
|
36
|
+
clear(): void;
|
|
37
|
+
/** The cookies worth saving: unexpired, with an expiry. */
|
|
38
|
+
persistent(now: number): StoredCookie[];
|
|
39
|
+
private storeOne;
|
|
40
|
+
private dropExpired;
|
|
41
|
+
private enforceLimits;
|
|
42
|
+
private evict;
|
|
43
|
+
}
|
|
44
|
+
/** A {@link CookieJarHost} over `jar`, reading the time from `now`. */
|
|
45
|
+
export declare function jarCookieHost(jar: CookieJar, now?: () => number): CookieJarHost;
|
|
46
|
+
/**
|
|
47
|
+
* The `Cookie` header a request carries: the pairs it sets by hand, then the jar's, in the order
|
|
48
|
+
* given. A jar cookie is left out when a hand-set pair has its name. Unlike `cookieHeader`, two jar
|
|
49
|
+
* cookies of one name on different paths both go, most specific first, as RFC 6265 §5.4 sends them.
|
|
50
|
+
*/
|
|
51
|
+
export declare function mergeCookieHeader(jarCookies: readonly StoredCookie[], handSet: string | undefined): string | undefined;
|
|
52
|
+
/** Options for {@link cookiesToSend}. */
|
|
53
|
+
export interface CookieMatchOptions {
|
|
54
|
+
/** When the cookies were received, for a `Max-Age` that is relative to that moment. */
|
|
55
|
+
readonly setAt?: Date;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The cookies of `cookies` that a request to `url` should carry at `now`, in the order given. Kept
|
|
59
|
+
* for the engine's public API: each cookie is stored, as received from `url`, in a throwaway jar and
|
|
60
|
+
* kept when that jar would send it back to `url`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function cookiesToSend(cookies: readonly Cookie[], url: string, now?: Date, options?: CookieMatchOptions): Cookie[];
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { defaultPath, domainMatches, pathMatches } from './cookies.js';
|
|
2
|
+
/** At most this many cookies per domain (spec §1.2). */
|
|
3
|
+
export const MAX_COOKIES_PER_DOMAIN = 50;
|
|
4
|
+
/** At most this many cookies in one jar. */
|
|
5
|
+
export const MAX_COOKIES = 3000;
|
|
6
|
+
/** A name plus value over this many UTF-8 bytes is not stored. */
|
|
7
|
+
export const MAX_COOKIE_BYTES = 4096;
|
|
8
|
+
const IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
|
|
9
|
+
const encoder = new TextEncoder();
|
|
10
|
+
/** Strip IPv6 brackets from hostname (URL.hostname keeps them). */
|
|
11
|
+
function stripIpv6Brackets(hostname) {
|
|
12
|
+
return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;
|
|
13
|
+
}
|
|
14
|
+
function isIpAddress(host) {
|
|
15
|
+
return IPV4.test(host) || host.includes(':') || host.startsWith('[');
|
|
16
|
+
}
|
|
17
|
+
function idOf(key) {
|
|
18
|
+
return `${key.domain}\n${key.path}\n${key.name}`;
|
|
19
|
+
}
|
|
20
|
+
/** The desktop wire schema's rules: nothing that would break the `Cookie` header a cookie is sent in. */
|
|
21
|
+
const BAD_NAME = /[;=\s\u0000-\u001f\u007f]/;
|
|
22
|
+
const BAD_VALUE = /[;\r\n\0]/;
|
|
23
|
+
function rejected(reason) {
|
|
24
|
+
return { stored: false, reason };
|
|
25
|
+
}
|
|
26
|
+
/** When `cookie` expires, from Max-Age first and then Expires (§5.3 step 3); undefined for a session cookie. */
|
|
27
|
+
function expiresAtOf(cookie, now) {
|
|
28
|
+
if (cookie.maxAge !== undefined) {
|
|
29
|
+
return now + cookie.maxAge * 1000;
|
|
30
|
+
}
|
|
31
|
+
if (cookie.expires === undefined) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const at = Date.parse(cookie.expires);
|
|
35
|
+
return Number.isNaN(at) ? undefined : at;
|
|
36
|
+
}
|
|
37
|
+
/** The domain a cookie from `host` is stored under, or why it is refused (spec §1.3). */
|
|
38
|
+
function scopeOf(cookie, host) {
|
|
39
|
+
const declared = (cookie.domain ?? '').replace(/^\./, '').toLowerCase();
|
|
40
|
+
if (declared === '') {
|
|
41
|
+
return { domain: host, hostOnly: true };
|
|
42
|
+
}
|
|
43
|
+
const restricted = isIpAddress(declared) || !declared.includes('.');
|
|
44
|
+
if (declared === host) {
|
|
45
|
+
// An IP or a single label is honoured only as the host itself, and then only host-only.
|
|
46
|
+
return { domain: host, hostOnly: restricted };
|
|
47
|
+
}
|
|
48
|
+
if (restricted) {
|
|
49
|
+
return 'domain-not-allowed';
|
|
50
|
+
}
|
|
51
|
+
return domainMatches(host, declared) ? { domain: declared, hostOnly: false } : 'domain-mismatch';
|
|
52
|
+
}
|
|
53
|
+
/** RFC 6265 §5.4 step 2: longer paths first, then the earlier created. */
|
|
54
|
+
function sendOrder(a, b) {
|
|
55
|
+
return b.path.length - a.path.length || a.createdAt - b.createdAt;
|
|
56
|
+
}
|
|
57
|
+
/** Which cookie a full jar lets go first: the soonest to expire (a session cookie last), then the oldest. */
|
|
58
|
+
function evictionOrder(a, b) {
|
|
59
|
+
const aExpires = a.expiresAt ?? Number.POSITIVE_INFINITY;
|
|
60
|
+
const bExpires = b.expiresAt ?? Number.POSITIVE_INFINITY;
|
|
61
|
+
if (aExpires !== bExpires) {
|
|
62
|
+
return aExpires < bExpires ? -1 : 1;
|
|
63
|
+
}
|
|
64
|
+
return a.createdAt - b.createdAt;
|
|
65
|
+
}
|
|
66
|
+
function listOrder(a, b) {
|
|
67
|
+
return a.domain.localeCompare(b.domain) || a.name.localeCompare(b.name) || a.path.localeCompare(b.path);
|
|
68
|
+
}
|
|
69
|
+
export class CookieJar {
|
|
70
|
+
cookies = new Map();
|
|
71
|
+
constructor(initial = []) {
|
|
72
|
+
for (const cookie of initial) {
|
|
73
|
+
this.cookies.set(idOf(cookie), cookie);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Stores what a response to `url` set, at `now`: one verdict per cookie, in order. */
|
|
77
|
+
store(url, cookies, now) {
|
|
78
|
+
let target;
|
|
79
|
+
try {
|
|
80
|
+
target = new URL(url);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return cookies.map(() => rejected('malformed'));
|
|
84
|
+
}
|
|
85
|
+
return cookies.map((cookie) => this.storeOne(cookie, target, now));
|
|
86
|
+
}
|
|
87
|
+
/** The cookies a request to `url` carries at `now`, in RFC 6265 §5.4 order. */
|
|
88
|
+
cookiesFor(url, now) {
|
|
89
|
+
this.dropExpired(now);
|
|
90
|
+
let target;
|
|
91
|
+
try {
|
|
92
|
+
target = new URL(url);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
const host = stripIpv6Brackets(target.hostname).toLowerCase();
|
|
98
|
+
const secureContext = target.protocol === 'https:';
|
|
99
|
+
const path = target.pathname === '' ? '/' : target.pathname;
|
|
100
|
+
return [...this.cookies.values()]
|
|
101
|
+
.filter((cookie) => (cookie.hostOnly ? host === cookie.domain : domainMatches(host, cookie.domain)) &&
|
|
102
|
+
pathMatches(path, cookie.path) &&
|
|
103
|
+
(!cookie.secure || secureContext))
|
|
104
|
+
.sort(sendOrder);
|
|
105
|
+
}
|
|
106
|
+
/** Every unexpired cookie, by domain, then name, then path. */
|
|
107
|
+
list(now) {
|
|
108
|
+
this.dropExpired(now);
|
|
109
|
+
return [...this.cookies.values()].sort(listOrder);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Stores `cookie` as given, replacing one of the same identity. The manager's edit: the domain and
|
|
113
|
+
* Secure rules are skipped (it picks its own domain), but the jar's size limits still hold.
|
|
114
|
+
*/
|
|
115
|
+
set(cookie, now = Date.now()) {
|
|
116
|
+
if (cookie.name === '' || BAD_NAME.test(cookie.name)) {
|
|
117
|
+
throw new RangeError('A cookie name is not empty and has no whitespace, control character, semicolon or equals sign.');
|
|
118
|
+
}
|
|
119
|
+
if (BAD_VALUE.test(cookie.value)) {
|
|
120
|
+
throw new RangeError('A cookie value has no semicolon, line break or NUL.');
|
|
121
|
+
}
|
|
122
|
+
this.cookies.set(idOf(cookie), cookie);
|
|
123
|
+
this.enforceLimits(cookie.domain, now);
|
|
124
|
+
}
|
|
125
|
+
remove(key) {
|
|
126
|
+
return this.cookies.delete(idOf(key));
|
|
127
|
+
}
|
|
128
|
+
/** Removes every cookie stored under `domain` (lowercased, leading dot ignored); how many went. */
|
|
129
|
+
removeDomain(domain) {
|
|
130
|
+
const target = domain.replace(/^\./, '').toLowerCase();
|
|
131
|
+
let removed = 0;
|
|
132
|
+
for (const [id, cookie] of this.cookies) {
|
|
133
|
+
if (cookie.domain === target) {
|
|
134
|
+
this.cookies.delete(id);
|
|
135
|
+
removed += 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return removed;
|
|
139
|
+
}
|
|
140
|
+
clear() {
|
|
141
|
+
this.cookies.clear();
|
|
142
|
+
}
|
|
143
|
+
/** The cookies worth saving: unexpired, with an expiry. */
|
|
144
|
+
persistent(now) {
|
|
145
|
+
return this.list(now).filter((cookie) => cookie.expiresAt !== undefined);
|
|
146
|
+
}
|
|
147
|
+
storeOne(cookie, target, now) {
|
|
148
|
+
if (cookie.malformed === true || cookie.name === '' || BAD_NAME.test(cookie.name) || BAD_VALUE.test(cookie.value)) {
|
|
149
|
+
return rejected('malformed');
|
|
150
|
+
}
|
|
151
|
+
if (encoder.encode(cookie.name).length + encoder.encode(cookie.value).length > MAX_COOKIE_BYTES) {
|
|
152
|
+
return rejected('too-large');
|
|
153
|
+
}
|
|
154
|
+
const secureContext = target.protocol === 'https:';
|
|
155
|
+
if (cookie.secure === true && !secureContext) {
|
|
156
|
+
return rejected('secure-over-http');
|
|
157
|
+
}
|
|
158
|
+
const host = stripIpv6Brackets(target.hostname).toLowerCase();
|
|
159
|
+
const scope = scopeOf(cookie, host);
|
|
160
|
+
if (typeof scope === 'string') {
|
|
161
|
+
return rejected(scope);
|
|
162
|
+
}
|
|
163
|
+
const declaredPath = cookie.path;
|
|
164
|
+
const path = declaredPath !== undefined && declaredPath.startsWith('/') ? declaredPath : defaultPath(target.pathname);
|
|
165
|
+
const id = idOf({ name: cookie.name, domain: scope.domain, path });
|
|
166
|
+
const existing = this.cookies.get(id);
|
|
167
|
+
if (existing?.secure === true && !secureContext) {
|
|
168
|
+
return rejected('secure-over-http');
|
|
169
|
+
}
|
|
170
|
+
// RFC 6265bis §5.3 step 13: refuse a non-Secure cookie if the jar holds a Secure cookie shadowing it
|
|
171
|
+
if (!secureContext && cookie.secure !== true) {
|
|
172
|
+
for (const candidate of this.cookies.values()) {
|
|
173
|
+
if (candidate.secure &&
|
|
174
|
+
candidate.name === cookie.name &&
|
|
175
|
+
(domainMatches(candidate.domain, scope.domain) || domainMatches(scope.domain, candidate.domain)) &&
|
|
176
|
+
pathMatches(path, candidate.path)) {
|
|
177
|
+
return rejected('secure-over-http');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const expiresAt = expiresAtOf(cookie, now);
|
|
182
|
+
if (expiresAt !== undefined && expiresAt <= now) {
|
|
183
|
+
this.cookies.delete(id);
|
|
184
|
+
return rejected('deleted');
|
|
185
|
+
}
|
|
186
|
+
this.cookies.set(id, {
|
|
187
|
+
name: cookie.name,
|
|
188
|
+
value: cookie.value,
|
|
189
|
+
domain: scope.domain,
|
|
190
|
+
hostOnly: scope.hostOnly,
|
|
191
|
+
path,
|
|
192
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
193
|
+
secure: cookie.secure === true,
|
|
194
|
+
httpOnly: cookie.httpOnly === true,
|
|
195
|
+
...(cookie.sameSite !== undefined ? { sameSite: cookie.sameSite } : {}),
|
|
196
|
+
createdAt: existing?.createdAt ?? now,
|
|
197
|
+
});
|
|
198
|
+
this.enforceLimits(scope.domain, now);
|
|
199
|
+
return { stored: true };
|
|
200
|
+
}
|
|
201
|
+
dropExpired(now) {
|
|
202
|
+
for (const [id, cookie] of this.cookies) {
|
|
203
|
+
if (cookie.expiresAt !== undefined && cookie.expiresAt <= now) {
|
|
204
|
+
this.cookies.delete(id);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
enforceLimits(domain, now) {
|
|
209
|
+
this.dropExpired(now);
|
|
210
|
+
const inDomain = [...this.cookies.values()].filter((cookie) => cookie.domain === domain);
|
|
211
|
+
this.evict(inDomain, inDomain.length - MAX_COOKIES_PER_DOMAIN);
|
|
212
|
+
this.evict([...this.cookies.values()], this.cookies.size - MAX_COOKIES);
|
|
213
|
+
}
|
|
214
|
+
evict(candidates, count) {
|
|
215
|
+
if (count <= 0) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
for (const cookie of [...candidates].sort(evictionOrder).slice(0, count)) {
|
|
219
|
+
this.cookies.delete(idOf(cookie));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/** A {@link CookieJarHost} over `jar`, reading the time from `now`. */
|
|
224
|
+
export function jarCookieHost(jar, now = () => Date.now()) {
|
|
225
|
+
return {
|
|
226
|
+
cookiesFor: (url) => jar.cookiesFor(url, now()),
|
|
227
|
+
remember: (url, cookies) => jar.store(url, cookies, now()),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The `Cookie` header a request carries: the pairs it sets by hand, then the jar's, in the order
|
|
232
|
+
* given. A jar cookie is left out when a hand-set pair has its name. Unlike `cookieHeader`, two jar
|
|
233
|
+
* cookies of one name on different paths both go, most specific first, as RFC 6265 §5.4 sends them.
|
|
234
|
+
*/
|
|
235
|
+
export function mergeCookieHeader(jarCookies, handSet) {
|
|
236
|
+
const hand = (handSet ?? '')
|
|
237
|
+
.split(';')
|
|
238
|
+
.map((pair) => pair.trim())
|
|
239
|
+
.filter((pair) => pair !== '');
|
|
240
|
+
const handNames = new Set(hand.map((pair) => {
|
|
241
|
+
const equals = pair.indexOf('=');
|
|
242
|
+
return (equals === -1 ? pair : pair.slice(0, equals)).trim();
|
|
243
|
+
}));
|
|
244
|
+
const pairs = [
|
|
245
|
+
...hand,
|
|
246
|
+
...jarCookies.filter((cookie) => !handNames.has(cookie.name)).map((cookie) => `${cookie.name}=${cookie.value}`),
|
|
247
|
+
];
|
|
248
|
+
return pairs.length === 0 ? undefined : pairs.join('; ');
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The cookies of `cookies` that a request to `url` should carry at `now`, in the order given. Kept
|
|
252
|
+
* for the engine's public API: each cookie is stored, as received from `url`, in a throwaway jar and
|
|
253
|
+
* kept when that jar would send it back to `url`.
|
|
254
|
+
*/
|
|
255
|
+
export function cookiesToSend(cookies, url, now = new Date(), options = {}) {
|
|
256
|
+
const storedAt = (options.setAt ?? now).getTime();
|
|
257
|
+
return cookies.filter((cookie) => {
|
|
258
|
+
const jar = new CookieJar();
|
|
259
|
+
jar.store(url, [cookie], storedAt);
|
|
260
|
+
return jar.cookiesFor(url, now.getTime()).length > 0;
|
|
261
|
+
});
|
|
262
|
+
}
|
package/dist/rest/cookies.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* RFC 6265 matching for the cookie jar (`rest/cookie-jar.ts`): domain-match and path-match (§5.1.3,
|
|
3
|
+
* §5.1.4), expiry (§5.3), and the `Cookie` header (§5.4).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* ever reaches disk.
|
|
9
|
-
*
|
|
10
|
-
* Matching follows RFC 6265 §5.1.3 and §5.1.4 (domain-match and path-match) and §5.3 (expiry).
|
|
5
|
+
* Every REST send stores what its responses set in a jar: the open workspace's in the app, the run's
|
|
6
|
+
* on the command line. A request sends the jar's matching cookies only when its *Send cookies*
|
|
7
|
+
* setting is on, which is off by default, so a saved request stays reproducible unless it opts in.
|
|
8
|
+
* The app saves only cookies with an expiry, encrypted; session cookies never reach disk.
|
|
11
9
|
*/
|
|
12
10
|
import type { Cookie } from './response.js';
|
|
13
11
|
/** True when `host` is `domain` or a subdomain of it (RFC 6265 §5.1.3). */
|
|
@@ -18,20 +16,6 @@ export declare function defaultPath(pathname: string): string;
|
|
|
18
16
|
export declare function pathMatches(requestPath: string, cookiePath: string): boolean;
|
|
19
17
|
/** Whether a cookie has expired at `now`, by `Max-Age` first and then `Expires` (§5.3). */
|
|
20
18
|
export declare function isExpired(cookie: Cookie, now: Date, setAt?: Date): boolean;
|
|
21
|
-
/** Options for {@link cookiesToSend}. */
|
|
22
|
-
export interface CookieMatchOptions {
|
|
23
|
-
/** When the cookies were received, for a `Max-Age` that is relative to that moment. */
|
|
24
|
-
readonly setAt?: Date;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* The cookies of `cookies` that a request to `url` should carry at `now`.
|
|
28
|
-
*
|
|
29
|
-
* A cookie with no `Domain` is host-only, so it goes back only to the host that set it — which, for
|
|
30
|
-
* a per-request memory, is the host it was sent from unless the URL changed. `Secure` cookies never
|
|
31
|
-
* travel over plain HTTP, malformed lines are never sent at all, and an expired cookie is dropped
|
|
32
|
-
* rather than sent and rejected.
|
|
33
|
-
*/
|
|
34
|
-
export declare function cookiesToSend(cookies: readonly Cookie[], url: string, now?: Date, options?: CookieMatchOptions): Cookie[];
|
|
35
19
|
/**
|
|
36
20
|
* The `Cookie` header value for `cookies`, or `undefined` when there is nothing to send.
|
|
37
21
|
*
|
package/dist/rest/cookies.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* RFC 6265 matching for the cookie jar (`rest/cookie-jar.ts`): domain-match and path-match (§5.1.3,
|
|
3
|
+
* §5.1.4), expiry (§5.3), and the `Cookie` header (§5.4).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* ever reaches disk.
|
|
9
|
-
*
|
|
10
|
-
* Matching follows RFC 6265 §5.1.3 and §5.1.4 (domain-match and path-match) and §5.3 (expiry).
|
|
5
|
+
* Every REST send stores what its responses set in a jar: the open workspace's in the app, the run's
|
|
6
|
+
* on the command line. A request sends the jar's matching cookies only when its *Send cookies*
|
|
7
|
+
* setting is on, which is off by default, so a saved request stays reproducible unless it opts in.
|
|
8
|
+
* The app saves only cookies with an expiry, encrypted; session cookies never reach disk.
|
|
11
9
|
*/
|
|
12
10
|
/** True when `host` is `domain` or a subdomain of it (RFC 6265 §5.1.3). */
|
|
13
11
|
export function domainMatches(host, domain) {
|
|
@@ -52,40 +50,6 @@ export function isExpired(cookie, now, setAt) {
|
|
|
52
50
|
const expires = new Date(cookie.expires);
|
|
53
51
|
return !Number.isNaN(expires.getTime()) && expires.getTime() <= now.getTime();
|
|
54
52
|
}
|
|
55
|
-
/**
|
|
56
|
-
* The cookies of `cookies` that a request to `url` should carry at `now`.
|
|
57
|
-
*
|
|
58
|
-
* A cookie with no `Domain` is host-only, so it goes back only to the host that set it — which, for
|
|
59
|
-
* a per-request memory, is the host it was sent from unless the URL changed. `Secure` cookies never
|
|
60
|
-
* travel over plain HTTP, malformed lines are never sent at all, and an expired cookie is dropped
|
|
61
|
-
* rather than sent and rejected.
|
|
62
|
-
*/
|
|
63
|
-
export function cookiesToSend(cookies, url, now = new Date(), options = {}) {
|
|
64
|
-
let target;
|
|
65
|
-
try {
|
|
66
|
-
target = new URL(url);
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
return [];
|
|
70
|
-
}
|
|
71
|
-
const secureContext = target.protocol === 'https:';
|
|
72
|
-
const requestPath = target.pathname === '' ? '/' : target.pathname;
|
|
73
|
-
return cookies.filter((cookie) => {
|
|
74
|
-
if (cookie.malformed === true || cookie.name === '') {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
if (cookie.secure === true && !secureContext) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
if (isExpired(cookie, now, options.setAt)) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
if (cookie.domain !== undefined && !domainMatches(target.hostname, cookie.domain)) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
return pathMatches(requestPath, cookie.path ?? defaultPath(requestPath));
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
53
|
/**
|
|
90
54
|
* The `Cookie` header value for `cookies`, or `undefined` when there is nothing to send.
|
|
91
55
|
*
|
package/dist/rest/curl.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { toCurl } from '../http/curl.js';
|
|
15
15
|
import { entry, RAW_LANGUAGE_CONTENT_TYPES } from './model.js';
|
|
16
|
-
import { applyAuth } from '
|
|
16
|
+
import { applyAuth } from '../http/auth/apply-auth.js';
|
|
17
17
|
import { findHeredoc, findHereString } from '../http/heredoc.js';
|
|
18
18
|
import { expandBundles, takesNoValue } from '../http/curl-flags.js';
|
|
19
19
|
import { composeUrl, splitQuery, trimTrailingSlashes } from './url.js';
|
|
@@ -81,6 +81,9 @@ export function restToCurl(input, options = {}) {
|
|
|
81
81
|
for (const [name, value] of Object.entries(applied.headers)) {
|
|
82
82
|
headers.push({ name, value: redact ? CURL_REDACTED : value });
|
|
83
83
|
}
|
|
84
|
+
// A request that asks the server for an event stream must not have curl buffer its output either,
|
|
85
|
+
// or `-N`'s whole point — seeing rows as they arrive — is lost.
|
|
86
|
+
const noBuffer = headers.some((header) => header.name.toLowerCase() === 'accept' && header.value.toLowerCase().includes('text/event-stream'));
|
|
84
87
|
const transport = applied.transportAuth;
|
|
85
88
|
const basic = transport?.type === 'basic'
|
|
86
89
|
? { username: transport.username, password: redact ? CURL_REDACTED : transport.password }
|
|
@@ -96,6 +99,7 @@ export function restToCurl(input, options = {}) {
|
|
|
96
99
|
...(input.settings.followRedirects && input.settings.maxRedirects !== undefined
|
|
97
100
|
? { maxRedirects: input.settings.maxRedirects }
|
|
98
101
|
: {}),
|
|
102
|
+
...(noBuffer ? { noBuffer: true } : {}),
|
|
99
103
|
};
|
|
100
104
|
return toCurl(command, options.shell !== undefined ? { shell: options.shell } : {});
|
|
101
105
|
}
|