@wirebench/engine 2.1.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/LICENSE +201 -0
- package/README.md +3 -0
- package/dist/assert/contract.d.ts +3 -0
- package/dist/assert/contract.js +17 -0
- package/dist/assert/index.d.ts +4 -0
- package/dist/assert/index.js +27 -0
- package/dist/assert/match.d.ts +3 -0
- package/dist/assert/match.js +58 -0
- package/dist/assert/model.d.ts +73 -0
- package/dist/assert/model.js +8 -0
- package/dist/assert/schema.d.ts +34 -0
- package/dist/assert/schema.js +46 -0
- package/dist/assert/sla.d.ts +3 -0
- package/dist/assert/sla.js +8 -0
- package/dist/assert/soap-fault.d.ts +3 -0
- package/dist/assert/soap-fault.js +20 -0
- package/dist/assert/status.d.ts +3 -0
- package/dist/assert/status.js +14 -0
- package/dist/errors.d.ts +77 -0
- package/dist/errors.js +121 -0
- package/dist/fs.d.ts +35 -0
- package/dist/fs.js +64 -0
- package/dist/generate.d.ts +12 -0
- package/dist/generate.js +14 -0
- package/dist/grpc/browser.d.ts +11 -0
- package/dist/grpc/browser.js +9 -0
- package/dist/grpc/cache.d.ts +113 -0
- package/dist/grpc/cache.js +244 -0
- package/dist/grpc/call.d.ts +64 -0
- package/dist/grpc/call.js +72 -0
- package/dist/grpc/codec.d.ts +29 -0
- package/dist/grpc/codec.js +416 -0
- package/dist/grpc/command.d.ts +23 -0
- package/dist/grpc/command.js +91 -0
- package/dist/grpc/expand.d.ts +25 -0
- package/dist/grpc/expand.js +52 -0
- package/dist/grpc/framing.d.ts +28 -0
- package/dist/grpc/framing.js +61 -0
- package/dist/grpc/import.d.ts +47 -0
- package/dist/grpc/import.js +88 -0
- package/dist/grpc/model.d.ts +179 -0
- package/dist/grpc/model.js +91 -0
- package/dist/grpc/proto/describe.d.ts +92 -0
- package/dist/grpc/proto/describe.js +205 -0
- package/dist/grpc/proto/load.d.ts +35 -0
- package/dist/grpc/proto/load.js +112 -0
- package/dist/grpc/proto/sample.d.ts +21 -0
- package/dist/grpc/proto/sample.js +79 -0
- package/dist/grpc/proto/well-known.d.ts +42 -0
- package/dist/grpc/proto/well-known.js +143 -0
- package/dist/grpc/reconcile.d.ts +42 -0
- package/dist/grpc/reconcile.js +153 -0
- package/dist/grpc/reflection/client.d.ts +70 -0
- package/dist/grpc/reflection/client.js +197 -0
- package/dist/grpc/reflection/descriptors.d.ts +69 -0
- package/dist/grpc/reflection/descriptors.js +140 -0
- package/dist/grpc/reflection/proto.d.ts +33 -0
- package/dist/grpc/reflection/proto.js +144 -0
- package/dist/grpc/send.d.ts +132 -0
- package/dist/grpc/send.js +435 -0
- package/dist/grpc/shape.d.ts +29 -0
- package/dist/grpc/shape.js +36 -0
- package/dist/grpc/status.d.ts +21 -0
- package/dist/grpc/status.js +62 -0
- package/dist/grpc/target.d.ts +21 -0
- package/dist/grpc/target.js +66 -0
- package/dist/http/auth/apply.d.ts +37 -0
- package/dist/http/auth/apply.js +74 -0
- package/dist/http/auth/basic.d.ts +36 -0
- package/dist/http/auth/basic.js +69 -0
- package/dist/http/auth/md4.d.ts +13 -0
- package/dist/http/auth/md4.js +81 -0
- package/dist/http/auth/ntlm-transport.d.ts +61 -0
- package/dist/http/auth/ntlm-transport.js +97 -0
- package/dist/http/auth/ntlm.d.ts +190 -0
- package/dist/http/auth/ntlm.js +377 -0
- package/dist/http/client.d.ts +73 -0
- package/dist/http/client.js +403 -0
- package/dist/http/curl-flags.d.ts +15 -0
- package/dist/http/curl-flags.js +95 -0
- package/dist/http/curl.d.ts +94 -0
- package/dist/http/curl.js +245 -0
- package/dist/http/decompress.d.ts +7 -0
- package/dist/http/decompress.js +22 -0
- package/dist/http/errors.d.ts +22 -0
- package/dist/http/errors.js +144 -0
- package/dist/http/failed-request.d.ts +27 -0
- package/dist/http/failed-request.js +48 -0
- package/dist/http/headers.d.ts +15 -0
- package/dist/http/headers.js +50 -0
- package/dist/http/heredoc.d.ts +25 -0
- package/dist/http/heredoc.js +74 -0
- package/dist/http/proxy.d.ts +103 -0
- package/dist/http/proxy.js +168 -0
- package/dist/http/raw-capture.d.ts +23 -0
- package/dist/http/raw-capture.js +57 -0
- package/dist/http/timings.d.ts +79 -0
- package/dist/http/timings.js +212 -0
- package/dist/http/tls.d.ts +111 -0
- package/dist/http/tls.js +167 -0
- package/dist/http/types.d.ts +125 -0
- package/dist/http/types.js +6 -0
- package/dist/import-detect.d.ts +26 -0
- package/dist/import-detect.js +169 -0
- package/dist/import.d.ts +20 -0
- package/dist/import.js +163 -0
- package/dist/index.d.ts +272 -0
- package/dist/index.js +157 -0
- package/dist/json/cursor.d.ts +43 -0
- package/dist/json/cursor.js +168 -0
- package/dist/operations.d.ts +12 -0
- package/dist/operations.js +52 -0
- package/dist/project/attachments-cache.d.ts +80 -0
- package/dist/project/attachments-cache.js +186 -0
- package/dist/project/endpoints.d.ts +23 -0
- package/dist/project/endpoints.js +47 -0
- package/dist/project/environments.d.ts +68 -0
- package/dist/project/environments.js +124 -0
- package/dist/project/fs.d.ts +45 -0
- package/dist/project/fs.js +78 -0
- package/dist/project/history.d.ts +171 -0
- package/dist/project/history.js +179 -0
- package/dist/project/keystores.d.ts +24 -0
- package/dist/project/keystores.js +66 -0
- package/dist/project/load.d.ts +44 -0
- package/dist/project/load.js +634 -0
- package/dist/project/migrate.d.ts +27 -0
- package/dist/project/migrate.js +46 -0
- package/dist/project/model.d.ts +401 -0
- package/dist/project/model.js +126 -0
- package/dist/project/paths.d.ts +134 -0
- package/dist/project/paths.js +259 -0
- package/dist/project/preferences.d.ts +318 -0
- package/dist/project/preferences.js +239 -0
- package/dist/project/properties.d.ts +97 -0
- package/dist/project/properties.js +356 -0
- package/dist/project/save.d.ts +65 -0
- package/dist/project/save.js +295 -0
- package/dist/project/schema.d.ts +1329 -0
- package/dist/project/schema.js +737 -0
- package/dist/project/serialize.d.ts +42 -0
- package/dist/project/serialize.js +385 -0
- package/dist/project/wss-configs.d.ts +40 -0
- package/dist/project/wss-configs.js +142 -0
- package/dist/project/yaml.d.ts +17 -0
- package/dist/project/yaml.js +39 -0
- package/dist/redact/index.d.ts +77 -0
- package/dist/redact/index.js +328 -0
- package/dist/redact/literal.d.ts +12 -0
- package/dist/redact/literal.js +68 -0
- package/dist/rest/auth.d.ts +53 -0
- package/dist/rest/auth.js +80 -0
- package/dist/rest/body.d.ts +61 -0
- package/dist/rest/body.js +184 -0
- package/dist/rest/browser.d.ts +12 -0
- package/dist/rest/browser.js +11 -0
- package/dist/rest/cookies.d.ts +41 -0
- package/dist/rest/cookies.js +102 -0
- package/dist/rest/curl.d.ts +75 -0
- package/dist/rest/curl.js +417 -0
- package/dist/rest/expand.d.ts +35 -0
- package/dist/rest/expand.js +104 -0
- package/dist/rest/model.d.ts +247 -0
- package/dist/rest/model.js +118 -0
- package/dist/rest/oauth2.d.ts +118 -0
- package/dist/rest/oauth2.js +212 -0
- package/dist/rest/openapi/cache.d.ts +54 -0
- package/dist/rest/openapi/cache.js +128 -0
- package/dist/rest/openapi/import.d.ts +67 -0
- package/dist/rest/openapi/import.js +91 -0
- package/dist/rest/openapi/map.d.ts +102 -0
- package/dist/rest/openapi/map.js +477 -0
- package/dist/rest/openapi/model.d.ts +203 -0
- package/dist/rest/openapi/model.js +37 -0
- package/dist/rest/openapi/parse.d.ts +44 -0
- package/dist/rest/openapi/parse.js +1530 -0
- package/dist/rest/openapi/refs.d.ts +63 -0
- package/dist/rest/openapi/refs.js +258 -0
- package/dist/rest/openapi/sample.d.ts +68 -0
- package/dist/rest/openapi/sample.js +336 -0
- package/dist/rest/postman/import.d.ts +21 -0
- package/dist/rest/postman/import.js +47 -0
- package/dist/rest/postman/index.d.ts +7 -0
- package/dist/rest/postman/index.js +7 -0
- package/dist/rest/postman/map.d.ts +28 -0
- package/dist/rest/postman/map.js +427 -0
- package/dist/rest/postman/model.d.ts +118 -0
- package/dist/rest/postman/model.js +7 -0
- package/dist/rest/postman/parse.d.ts +29 -0
- package/dist/rest/postman/parse.js +518 -0
- package/dist/rest/response.d.ts +72 -0
- package/dist/rest/response.js +221 -0
- package/dist/rest/send.d.ts +102 -0
- package/dist/rest/send.js +148 -0
- package/dist/rest/url.d.ts +92 -0
- package/dist/rest/url.js +213 -0
- package/dist/run/effective-auth.d.ts +10 -0
- package/dist/run/effective-auth.js +19 -0
- package/dist/run/index.d.ts +8 -0
- package/dist/run/index.js +4 -0
- package/dist/run/prepare.d.ts +43 -0
- package/dist/run/prepare.js +280 -0
- package/dist/run/run.d.ts +53 -0
- package/dist/run/run.js +223 -0
- package/dist/run/secret-needs.d.ts +13 -0
- package/dist/run/secret-needs.js +125 -0
- package/dist/run/select.d.ts +34 -0
- package/dist/run/select.js +76 -0
- package/dist/secrets/env-names.d.ts +27 -0
- package/dist/secrets/env-names.js +40 -0
- package/dist/secrets/resolve.d.ts +58 -0
- package/dist/secrets/resolve.js +136 -0
- package/dist/send-options.d.ts +141 -0
- package/dist/send-options.js +228 -0
- package/dist/send.d.ts +53 -0
- package/dist/send.js +210 -0
- package/dist/soap/body-builder.d.ts +38 -0
- package/dist/soap/body-builder.js +250 -0
- package/dist/soap/build-problems.d.ts +12 -0
- package/dist/soap/build-problems.js +2 -0
- package/dist/soap/charset.d.ts +23 -0
- package/dist/soap/charset.js +47 -0
- package/dist/soap/envelope.d.ts +44 -0
- package/dist/soap/envelope.js +76 -0
- package/dist/soap/fault.d.ts +46 -0
- package/dist/soap/fault.js +129 -0
- package/dist/soap/form-request.d.ts +34 -0
- package/dist/soap/form-request.js +251 -0
- package/dist/soap/legacy-project/definition-fetcher.d.ts +21 -0
- package/dist/soap/legacy-project/definition-fetcher.js +43 -0
- package/dist/soap/legacy-project/format.d.ts +18 -0
- package/dist/soap/legacy-project/format.js +24 -0
- package/dist/soap/legacy-project/import.d.ts +21 -0
- package/dist/soap/legacy-project/import.js +46 -0
- package/dist/soap/legacy-project/index.d.ts +9 -0
- package/dist/soap/legacy-project/index.js +5 -0
- package/dist/soap/legacy-project/map.d.ts +91 -0
- package/dist/soap/legacy-project/map.js +290 -0
- package/dist/soap/legacy-project/model.d.ts +98 -0
- package/dist/soap/legacy-project/model.js +5 -0
- package/dist/soap/legacy-project/parse.d.ts +16 -0
- package/dist/soap/legacy-project/parse.js +325 -0
- package/dist/soap/mime/cid-scan.d.ts +36 -0
- package/dist/soap/mime/cid-scan.js +52 -0
- package/dist/soap/mime/inline-files.d.ts +39 -0
- package/dist/soap/mime/inline-files.js +71 -0
- package/dist/soap/mime/mtom.d.ts +74 -0
- package/dist/soap/mime/mtom.js +134 -0
- package/dist/soap/mime/multipart.d.ts +66 -0
- package/dist/soap/mime/multipart.js +329 -0
- package/dist/soap/mime/send-pipeline.d.ts +61 -0
- package/dist/soap/mime/send-pipeline.js +145 -0
- package/dist/soap/mime/swa.d.ts +45 -0
- package/dist/soap/mime/swa.js +62 -0
- package/dist/soap/mime/types.d.ts +69 -0
- package/dist/soap/mime/types.js +10 -0
- package/dist/soap/namespace-scope.d.ts +32 -0
- package/dist/soap/namespace-scope.js +85 -0
- package/dist/soap/prefixes.d.ts +24 -0
- package/dist/soap/prefixes.js +70 -0
- package/dist/soap/recreate.d.ts +28 -0
- package/dist/soap/recreate.js +168 -0
- package/dist/soap/request-builder.d.ts +63 -0
- package/dist/soap/request-builder.js +161 -0
- package/dist/soap/response-parser.d.ts +29 -0
- package/dist/soap/response-parser.js +71 -0
- package/dist/soap/soap-action.d.ts +31 -0
- package/dist/soap/soap-action.js +28 -0
- package/dist/soap/transforms.d.ts +52 -0
- package/dist/soap/transforms.js +164 -0
- package/dist/types.d.ts +307 -0
- package/dist/types.js +6 -0
- package/dist/validate/index.d.ts +61 -0
- package/dist/validate/index.js +72 -0
- package/dist/validate/schema-file-set.d.ts +51 -0
- package/dist/validate/schema-file-set.js +288 -0
- package/dist/validate/schema-validator.d.ts +53 -0
- package/dist/validate/schema-validator.js +251 -0
- package/dist/validate/soap-structure.d.ts +34 -0
- package/dist/validate/soap-structure.js +255 -0
- package/dist/validate/types.d.ts +47 -0
- package/dist/validate/types.js +8 -0
- package/dist/validate/wsi/assertions/helpers.d.ts +145 -0
- package/dist/validate/wsi/assertions/helpers.js +387 -0
- package/dist/validate/wsi/assertions/index.d.ts +44 -0
- package/dist/validate/wsi/assertions/index.js +77 -0
- package/dist/validate/wsi/assertions/message/helpers.d.ts +63 -0
- package/dist/validate/wsi/assertions/message/helpers.js +168 -0
- package/dist/validate/wsi/assertions/message/index.d.ts +39 -0
- package/dist/validate/wsi/assertions/message/index.js +62 -0
- package/dist/validate/wsi/assertions/message/r1001.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1001.js +38 -0
- package/dist/validate/wsi/assertions/message/r1003.d.ts +14 -0
- package/dist/validate/wsi/assertions/message/r1003.js +45 -0
- package/dist/validate/wsi/assertions/message/r1005.d.ts +12 -0
- package/dist/validate/wsi/assertions/message/r1005.js +37 -0
- package/dist/validate/wsi/assertions/message/r1006.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1006.js +49 -0
- package/dist/validate/wsi/assertions/message/r1007.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1007.js +30 -0
- package/dist/validate/wsi/assertions/message/r1011.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1011.js +33 -0
- package/dist/validate/wsi/assertions/message/r1012.d.ts +13 -0
- package/dist/validate/wsi/assertions/message/r1012.js +37 -0
- package/dist/validate/wsi/assertions/message/r1013.d.ts +9 -0
- package/dist/validate/wsi/assertions/message/r1013.js +42 -0
- package/dist/validate/wsi/assertions/message/r1014.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1014.js +30 -0
- package/dist/validate/wsi/assertions/message/r1015.d.ts +12 -0
- package/dist/validate/wsi/assertions/message/r1015.js +36 -0
- package/dist/validate/wsi/assertions/message/r1017.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1017.js +30 -0
- package/dist/validate/wsi/assertions/message/r1100.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1100.js +39 -0
- package/dist/validate/wsi/assertions/message/r1101.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1101.js +37 -0
- package/dist/validate/wsi/assertions/message/r1102.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1102.js +41 -0
- package/dist/validate/wsi/assertions/message/r1103.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1103.js +28 -0
- package/dist/validate/wsi/assertions/message/r1107.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1107.js +38 -0
- package/dist/validate/wsi/assertions/message/r1109.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1109.js +32 -0
- package/dist/validate/wsi/assertions/message/r1124.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1124.js +31 -0
- package/dist/validate/wsi/assertions/message/r1132.d.ts +9 -0
- package/dist/validate/wsi/assertions/message/r1132.js +23 -0
- package/dist/validate/wsi/assertions/message/r1140.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1140.js +42 -0
- package/dist/validate/wsi/assertions/message/r1141.d.ts +10 -0
- package/dist/validate/wsi/assertions/message/r1141.js +32 -0
- package/dist/validate/wsi/assertions/message/r2113.d.ts +11 -0
- package/dist/validate/wsi/assertions/message/r2113.js +33 -0
- package/dist/validate/wsi/assertions/message/r2211.d.ts +7 -0
- package/dist/validate/wsi/assertions/message/r2211.js +42 -0
- package/dist/validate/wsi/assertions/r2001.d.ts +15 -0
- package/dist/validate/wsi/assertions/r2001.js +47 -0
- package/dist/validate/wsi/assertions/r2002.d.ts +11 -0
- package/dist/validate/wsi/assertions/r2002.js +38 -0
- package/dist/validate/wsi/assertions/r2003.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2003.js +32 -0
- package/dist/validate/wsi/assertions/r2005.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2005.js +40 -0
- package/dist/validate/wsi/assertions/r2101.d.ts +14 -0
- package/dist/validate/wsi/assertions/r2101.js +65 -0
- package/dist/validate/wsi/assertions/r2102.d.ts +10 -0
- package/dist/validate/wsi/assertions/r2102.js +41 -0
- package/dist/validate/wsi/assertions/r2105.d.ts +8 -0
- package/dist/validate/wsi/assertions/r2105.js +39 -0
- package/dist/validate/wsi/assertions/r2110.d.ts +8 -0
- package/dist/validate/wsi/assertions/r2110.js +38 -0
- package/dist/validate/wsi/assertions/r2111.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2111.js +30 -0
- package/dist/validate/wsi/assertions/r2112.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2112.js +35 -0
- package/dist/validate/wsi/assertions/r2201.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2201.js +28 -0
- package/dist/validate/wsi/assertions/r2203.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2203.js +30 -0
- package/dist/validate/wsi/assertions/r2204.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2204.js +29 -0
- package/dist/validate/wsi/assertions/r2205.d.ts +8 -0
- package/dist/validate/wsi/assertions/r2205.js +46 -0
- package/dist/validate/wsi/assertions/r2206.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2206.js +36 -0
- package/dist/validate/wsi/assertions/r2209.d.ts +12 -0
- package/dist/validate/wsi/assertions/r2209.js +37 -0
- package/dist/validate/wsi/assertions/r2210.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2210.js +30 -0
- package/dist/validate/wsi/assertions/r2303.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2303.js +44 -0
- package/dist/validate/wsi/assertions/r2304.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2304.js +32 -0
- package/dist/validate/wsi/assertions/r2401.d.ts +12 -0
- package/dist/validate/wsi/assertions/r2401.js +31 -0
- package/dist/validate/wsi/assertions/r2701.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2701.js +28 -0
- package/dist/validate/wsi/assertions/r2702.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2702.js +26 -0
- package/dist/validate/wsi/assertions/r2705.d.ts +11 -0
- package/dist/validate/wsi/assertions/r2705.js +31 -0
- package/dist/validate/wsi/assertions/r2706.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2706.js +29 -0
- package/dist/validate/wsi/assertions/r2710.d.ts +13 -0
- package/dist/validate/wsi/assertions/r2710.js +37 -0
- package/dist/validate/wsi/assertions/r2716.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2716.js +29 -0
- package/dist/validate/wsi/assertions/r2717.d.ts +9 -0
- package/dist/validate/wsi/assertions/r2717.js +31 -0
- package/dist/validate/wsi/assertions/r2718.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2718.js +41 -0
- package/dist/validate/wsi/assertions/r2720.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2720.js +29 -0
- package/dist/validate/wsi/assertions/r2721.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2721.js +27 -0
- package/dist/validate/wsi/assertions/r2722.d.ts +6 -0
- package/dist/validate/wsi/assertions/r2722.js +29 -0
- package/dist/validate/wsi/assertions/r2801.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2801.js +39 -0
- package/dist/validate/wsi/assertions/r2803.d.ts +7 -0
- package/dist/validate/wsi/assertions/r2803.js +29 -0
- package/dist/validate/wsi/docs.d.ts +29 -0
- package/dist/validate/wsi/docs.js +167 -0
- package/dist/validate/wsi/index.d.ts +16 -0
- package/dist/validate/wsi/index.js +11 -0
- package/dist/validate/wsi/report-html.d.ts +36 -0
- package/dist/validate/wsi/report-html.js +135 -0
- package/dist/validate/wsi/run-message.d.ts +50 -0
- package/dist/validate/wsi/run-message.js +190 -0
- package/dist/validate/wsi/run-wsdl.d.ts +48 -0
- package/dist/validate/wsi/run-wsdl.js +99 -0
- package/dist/validate/wsi/types.d.ts +173 -0
- package/dist/validate/wsi/types.js +17 -0
- package/dist/workspace/commit-message.d.ts +47 -0
- package/dist/workspace/commit-message.js +195 -0
- package/dist/workspace/environments.d.ts +79 -0
- package/dist/workspace/environments.js +115 -0
- package/dist/workspace/index.d.ts +28 -0
- package/dist/workspace/index.js +19 -0
- package/dist/workspace/load.d.ts +45 -0
- package/dist/workspace/load.js +155 -0
- package/dist/workspace/local-state.d.ts +37 -0
- package/dist/workspace/local-state.js +59 -0
- package/dist/workspace/migrate.d.ts +38 -0
- package/dist/workspace/migrate.js +50 -0
- package/dist/workspace/model.d.ts +86 -0
- package/dist/workspace/model.js +54 -0
- package/dist/workspace/paths.d.ts +64 -0
- package/dist/workspace/paths.js +97 -0
- package/dist/workspace/reidentify.d.ts +22 -0
- package/dist/workspace/reidentify.js +122 -0
- package/dist/workspace/save.d.ts +31 -0
- package/dist/workspace/save.js +84 -0
- package/dist/workspace/schema.d.ts +93 -0
- package/dist/workspace/schema.js +115 -0
- package/dist/workspace/serialize.d.ts +24 -0
- package/dist/workspace/serialize.js +60 -0
- package/dist/workspace/share.d.ts +52 -0
- package/dist/workspace/share.js +89 -0
- package/dist/ws/browser.d.ts +13 -0
- package/dist/ws/browser.js +11 -0
- package/dist/ws/call.d.ts +53 -0
- package/dist/ws/call.js +106 -0
- package/dist/ws/command.d.ts +19 -0
- package/dist/ws/command.js +28 -0
- package/dist/ws/expand.d.ts +38 -0
- package/dist/ws/expand.js +76 -0
- package/dist/ws/model.d.ts +191 -0
- package/dist/ws/model.js +83 -0
- package/dist/ws/pretty.d.ts +12 -0
- package/dist/ws/pretty.js +25 -0
- package/dist/ws/session.d.ts +50 -0
- package/dist/ws/session.js +333 -0
- package/dist/ws/shape.d.ts +18 -0
- package/dist/ws/shape.js +28 -0
- package/dist/ws/transcript.d.ts +14 -0
- package/dist/ws/transcript.js +29 -0
- package/dist/ws/url.d.ts +3 -0
- package/dist/ws/url.js +44 -0
- package/dist/wsa/headers.d.ts +78 -0
- package/dist/wsa/headers.js +244 -0
- package/dist/wsa/model.d.ts +66 -0
- package/dist/wsa/model.js +52 -0
- package/dist/wsa/policy-detect.d.ts +81 -0
- package/dist/wsa/policy-detect.js +245 -0
- package/dist/wsdl/cache-naming.d.ts +39 -0
- package/dist/wsdl/cache-naming.js +90 -0
- package/dist/wsdl/cache.d.ts +48 -0
- package/dist/wsdl/cache.js +141 -0
- package/dist/wsdl/docs-generator.d.ts +47 -0
- package/dist/wsdl/docs-generator.js +439 -0
- package/dist/wsdl/dom-utils.d.ts +15 -0
- package/dist/wsdl/dom-utils.js +50 -0
- package/dist/wsdl/export-definition.d.ts +38 -0
- package/dist/wsdl/export-definition.js +100 -0
- package/dist/wsdl/fetch.d.ts +13 -0
- package/dist/wsdl/fetch.js +60 -0
- package/dist/wsdl/merge.d.ts +17 -0
- package/dist/wsdl/merge.js +57 -0
- package/dist/wsdl/model.d.ts +176 -0
- package/dist/wsdl/model.js +17 -0
- package/dist/wsdl/parse-binding.d.ts +6 -0
- package/dist/wsdl/parse-binding.js +150 -0
- package/dist/wsdl/parse-wsdl.d.ts +47 -0
- package/dist/wsdl/parse-wsdl.js +161 -0
- package/dist/wsdl/qname.d.ts +28 -0
- package/dist/wsdl/qname.js +41 -0
- package/dist/wsdl/ref-policy.d.ts +54 -0
- package/dist/wsdl/ref-policy.js +87 -0
- package/dist/wsdl/resolver.d.ts +81 -0
- package/dist/wsdl/resolver.js +276 -0
- package/dist/wsdl/update-definition.d.ts +106 -0
- package/dist/wsdl/update-definition.js +314 -0
- package/dist/wss/apply.d.ts +40 -0
- package/dist/wss/apply.js +212 -0
- package/dist/wss/c14n-prefixes.d.ts +27 -0
- package/dist/wss/c14n-prefixes.js +95 -0
- package/dist/wss/incoming/decrypt.d.ts +35 -0
- package/dist/wss/incoming/decrypt.js +57 -0
- package/dist/wss/incoming/index.d.ts +56 -0
- package/dist/wss/incoming/index.js +189 -0
- package/dist/wss/incoming/verify.d.ts +74 -0
- package/dist/wss/incoming/verify.js +440 -0
- package/dist/wss/key-identifiers.d.ts +76 -0
- package/dist/wss/key-identifiers.js +139 -0
- package/dist/wss/keystore/certificate.d.ts +45 -0
- package/dist/wss/keystore/certificate.js +134 -0
- package/dist/wss/keystore/index.d.ts +50 -0
- package/dist/wss/keystore/index.js +80 -0
- package/dist/wss/keystore/model.d.ts +83 -0
- package/dist/wss/keystore/model.js +27 -0
- package/dist/wss/keystore/pem.d.ts +21 -0
- package/dist/wss/keystore/pem.js +140 -0
- package/dist/wss/keystore/pkcs12.d.ts +21 -0
- package/dist/wss/keystore/pkcs12.js +125 -0
- package/dist/wss/model.d.ts +160 -0
- package/dist/wss/model.js +37 -0
- package/dist/wss/outgoing/encryption.d.ts +76 -0
- package/dist/wss/outgoing/encryption.js +618 -0
- package/dist/wss/outgoing/signature.d.ts +73 -0
- package/dist/wss/outgoing/signature.js +239 -0
- package/dist/wss/outgoing/timestamp.d.ts +29 -0
- package/dist/wss/outgoing/timestamp.js +39 -0
- package/dist/wss/outgoing/username-token.d.ts +36 -0
- package/dist/wss/outgoing/username-token.js +68 -0
- package/dist/wss/security-header.d.ts +31 -0
- package/dist/wss/security-header.js +83 -0
- package/dist/xml/index.d.ts +7 -0
- package/dist/xml/index.js +7 -0
- package/dist/xml/namespaces.d.ts +36 -0
- package/dist/xml/namespaces.js +60 -0
- package/dist/xml/parse.d.ts +79 -0
- package/dist/xml/parse.js +109 -0
- package/dist/xml/positions.d.ts +26 -0
- package/dist/xml/positions.js +71 -0
- package/dist/xml/pretty.d.ts +37 -0
- package/dist/xml/pretty.js +137 -0
- package/dist/xml/serialize.d.ts +6 -0
- package/dist/xml/serialize.js +8 -0
- package/dist/xml/tolerant-tree.d.ts +56 -0
- package/dist/xml/tolerant-tree.js +134 -0
- package/dist/xpath/evaluate-async.d.ts +31 -0
- package/dist/xpath/evaluate-async.js +81 -0
- package/dist/xpath/evaluate.d.ts +98 -0
- package/dist/xpath/evaluate.js +340 -0
- package/dist/xpath/jsonpath.d.ts +40 -0
- package/dist/xpath/jsonpath.js +109 -0
- package/dist/xpath/namespaces.d.ts +29 -0
- package/dist/xpath/namespaces.js +101 -0
- package/dist/xpath/worker.d.ts +7 -0
- package/dist/xpath/worker.js +26 -0
- package/dist/xsd/builtins.d.ts +36 -0
- package/dist/xsd/builtins.js +108 -0
- package/dist/xsd/check-references.d.ts +25 -0
- package/dist/xsd/check-references.js +145 -0
- package/dist/xsd/form-edits.d.ts +57 -0
- package/dist/xsd/form-edits.js +153 -0
- package/dist/xsd/form-model.d.ts +153 -0
- package/dist/xsd/form-model.js +691 -0
- package/dist/xsd/locate.d.ts +42 -0
- package/dist/xsd/locate.js +249 -0
- package/dist/xsd/model.d.ts +249 -0
- package/dist/xsd/model.js +1 -0
- package/dist/xsd/parse-particles.d.ts +48 -0
- package/dist/xsd/parse-particles.js +320 -0
- package/dist/xsd/parse-schema.d.ts +21 -0
- package/dist/xsd/parse-schema.js +143 -0
- package/dist/xsd/resolve-content.d.ts +18 -0
- package/dist/xsd/resolve-content.js +242 -0
- package/dist/xsd/sample-generator.d.ts +51 -0
- package/dist/xsd/sample-generator.js +291 -0
- package/dist/xsd/sample-types.d.ts +21 -0
- package/dist/xsd/sample-types.js +69 -0
- package/dist/xsd/sample-values.d.ts +54 -0
- package/dist/xsd/sample-values.js +267 -0
- package/dist/xsd/schema-set.d.ts +51 -0
- package/dist/xsd/schema-set.js +203 -0
- package/dist/xsd/xml-scan.d.ts +64 -0
- package/dist/xsd/xml-scan.js +286 -0
- package/dist/xsd/xml-writer.d.ts +56 -0
- package/dist/xsd/xml-writer.js +103 -0
- package/package.json +69 -0
|
@@ -0,0 +1,1530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading an OpenAPI or Swagger document into the model this client imports from.
|
|
3
|
+
*
|
|
4
|
+
* Tolerant on purpose. A description in the wild is written by hand, generated by a framework, or
|
|
5
|
+
* both, and a parser that refuses a whole document because one operation is malformed refuses
|
|
6
|
+
* documents users legitimately need. So anything that cannot be understood is *skipped and counted*
|
|
7
|
+
* — the import summary names it — and only two things are fatal: text that is neither JSON nor
|
|
8
|
+
* YAML, and a document that does not declare a supported OpenAPI or Swagger version. Swagger 1.x
|
|
9
|
+
* and 2.0 documents are converted into the intermediate OpenAPI representation.
|
|
10
|
+
*
|
|
11
|
+
* The parser reads a document that is already resolved: `refs.ts` inlines every `$ref` first, so
|
|
12
|
+
* nothing here has to fetch anything.
|
|
13
|
+
*/
|
|
14
|
+
import { parse as parseYamlDocument } from 'yaml';
|
|
15
|
+
import { OpenApiError } from '../../errors.js';
|
|
16
|
+
import { HTTP_METHODS } from './model.js';
|
|
17
|
+
import { trimTrailingSlashes } from '../url.js';
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
function asString(value) {
|
|
22
|
+
return typeof value === 'string' ? value : undefined;
|
|
23
|
+
}
|
|
24
|
+
function asBoolean(value) {
|
|
25
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
26
|
+
}
|
|
27
|
+
function asStringArray(value) {
|
|
28
|
+
if (!Array.isArray(value)) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const strings = value.filter((entry) => typeof entry === 'string');
|
|
32
|
+
// All-or-nothing: a list with a non-string in it is not a list of strings, and silently dropping
|
|
33
|
+
// the odd one out would misreport what the document said.
|
|
34
|
+
return strings.length === value.length ? strings : undefined;
|
|
35
|
+
}
|
|
36
|
+
/** A value carried through as it was written — an `example`, a `default`, an `enum` member. */
|
|
37
|
+
function asJson(value) {
|
|
38
|
+
return value === undefined ? undefined : value;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parses text as JSON when it looks like JSON, and as YAML otherwise.
|
|
42
|
+
*
|
|
43
|
+
* JSON is a subset of YAML, so one parser would do — but a JSON document with a syntax error gets a
|
|
44
|
+
* far better message from `JSON.parse`, and that message is what the user has to act on.
|
|
45
|
+
*
|
|
46
|
+
* @throws OpenApiError `openapi-malformed` when the text parses as neither.
|
|
47
|
+
*/
|
|
48
|
+
export function parseDocumentText(text, where = 'the document') {
|
|
49
|
+
const trimmed = text.replace(/^/, '').trimStart();
|
|
50
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(trimmed);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new OpenApiError('openapi-malformed', `${where} is not valid JSON: ${messageOf(error)}`, { cause: error });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
return parseYamlDocument(trimmed);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw new OpenApiError('openapi-malformed', `${where} is not valid YAML: ${messageOf(error)}`, { cause: error });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function messageOf(error) {
|
|
66
|
+
return error instanceof Error ? error.message : String(error);
|
|
67
|
+
}
|
|
68
|
+
function asVersionString(v) {
|
|
69
|
+
if (typeof v === 'string')
|
|
70
|
+
return v;
|
|
71
|
+
if (typeof v === 'number') {
|
|
72
|
+
return Number.isInteger(v) ? `${v}.0` : String(v);
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
function nullRecord() {
|
|
77
|
+
return Object.create(null);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The version a document declares, as a major-minor this client supports.
|
|
81
|
+
*
|
|
82
|
+
* @throws OpenApiError `openapi-unsupported-version` for an OpenAPI major this client
|
|
83
|
+
* does not read, and `openapi-not-a-document` when there is no version at all.
|
|
84
|
+
*/
|
|
85
|
+
export function versionOf(root) {
|
|
86
|
+
if (!isRecord(root)) {
|
|
87
|
+
throw new OpenApiError('openapi-not-a-document', 'This file does not contain an OpenAPI document');
|
|
88
|
+
}
|
|
89
|
+
// 3.1: Check openapi BEFORE swagger/swaggerVersion
|
|
90
|
+
const declared = asVersionString(root['openapi']);
|
|
91
|
+
if (declared !== undefined) {
|
|
92
|
+
if (declared.startsWith('3.0')) {
|
|
93
|
+
return { version: '3.0', declared };
|
|
94
|
+
}
|
|
95
|
+
if (declared.startsWith('3.1')) {
|
|
96
|
+
return { version: '3.1', declared };
|
|
97
|
+
}
|
|
98
|
+
if (declared.startsWith('3.2')) {
|
|
99
|
+
return { version: '3.2', declared };
|
|
100
|
+
}
|
|
101
|
+
throw new OpenApiError('openapi-unsupported-version', `OpenAPI ${declared} is not supported. Wirebench imports OpenAPI 3.0, 3.1 and 3.2.`, { details: { declared } });
|
|
102
|
+
}
|
|
103
|
+
// 3.2: Accept numeric versions for swagger/swaggerVersion as well
|
|
104
|
+
const swaggerVersion = asVersionString(root['swaggerVersion']) ?? asVersionString(root['swagger']);
|
|
105
|
+
if (swaggerVersion !== undefined) {
|
|
106
|
+
// 3.10: report 1.0/1.1 as exact version, remove redundant === '1.2'
|
|
107
|
+
if (swaggerVersion.startsWith('1.0')) {
|
|
108
|
+
return { version: '1.0', declared: `Swagger ${swaggerVersion}` };
|
|
109
|
+
}
|
|
110
|
+
if (swaggerVersion.startsWith('1.1')) {
|
|
111
|
+
return { version: '1.1', declared: `Swagger ${swaggerVersion}` };
|
|
112
|
+
}
|
|
113
|
+
if (swaggerVersion.startsWith('1.')) {
|
|
114
|
+
return { version: '1.2', declared: `Swagger ${swaggerVersion}` };
|
|
115
|
+
}
|
|
116
|
+
if (swaggerVersion.startsWith('2.')) {
|
|
117
|
+
return { version: '2.0', declared: `Swagger ${swaggerVersion}` };
|
|
118
|
+
}
|
|
119
|
+
// 3.3: Swagger 3.x is labeled as OpenAPI 3.x.y
|
|
120
|
+
if (swaggerVersion.startsWith('3.0')) {
|
|
121
|
+
return { version: '3.0', declared: `OpenAPI ${swaggerVersion}` };
|
|
122
|
+
}
|
|
123
|
+
if (swaggerVersion.startsWith('3.1')) {
|
|
124
|
+
return { version: '3.1', declared: `OpenAPI ${swaggerVersion}` };
|
|
125
|
+
}
|
|
126
|
+
if (swaggerVersion.startsWith('3.2')) {
|
|
127
|
+
return { version: '3.2', declared: `OpenAPI ${swaggerVersion}` };
|
|
128
|
+
}
|
|
129
|
+
throw new OpenApiError('openapi-unsupported-version', `This is a Swagger ${swaggerVersion} document. Wirebench imports Swagger 1.x, 2.0, 3.x and OpenAPI 3.0, 3.1, 3.2.`, { details: { declared: swaggerVersion } });
|
|
130
|
+
}
|
|
131
|
+
throw new OpenApiError('openapi-not-a-document', 'This file has no "openapi" or "swaggerVersion" field, so it is not an OpenAPI or Swagger document');
|
|
132
|
+
}
|
|
133
|
+
/** The keys a document may carry that this client knowingly does not read, with what to call them. */
|
|
134
|
+
const IGNORED_ROOT_KEYS = {
|
|
135
|
+
webhooks: 'webhook',
|
|
136
|
+
callbacks: 'callback',
|
|
137
|
+
links: 'link',
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Reads a resolved OpenAPI document.
|
|
141
|
+
*
|
|
142
|
+
* @param root the parsed document, with every `$ref` already inlined (see `refs.ts`)
|
|
143
|
+
* @throws OpenApiError `openapi-not-a-document` / `openapi-unsupported-version` as {@link versionOf} does
|
|
144
|
+
*/
|
|
145
|
+
export function parseOpenApiDocument(root) {
|
|
146
|
+
const { version, declared } = versionOf(root);
|
|
147
|
+
const document = root;
|
|
148
|
+
if (version === '1.0' || version === '1.1' || version === '1.2') {
|
|
149
|
+
return parseSwagger1Document(document, declared, version);
|
|
150
|
+
}
|
|
151
|
+
if (version === '2.0') {
|
|
152
|
+
return parseSwagger2Document(document, declared);
|
|
153
|
+
}
|
|
154
|
+
const skipped = [];
|
|
155
|
+
const rawSwagger = asVersionString(document['swagger']);
|
|
156
|
+
if (rawSwagger !== undefined &&
|
|
157
|
+
(rawSwagger.startsWith('3.0') || rawSwagger.startsWith('3.1') || rawSwagger.startsWith('3.2'))) {
|
|
158
|
+
skipped.push({ kind: 'info', where: '/swagger', reason: `declared as swagger: ${rawSwagger}` });
|
|
159
|
+
}
|
|
160
|
+
const info = isRecord(document['info']) ? document['info'] : {};
|
|
161
|
+
const title = asString(info['title']) ?? 'Imported API';
|
|
162
|
+
for (const [key, kind] of Object.entries(IGNORED_ROOT_KEYS)) {
|
|
163
|
+
const value = document[key];
|
|
164
|
+
if (isRecord(value)) {
|
|
165
|
+
for (const name of Object.keys(value)) {
|
|
166
|
+
skipped.push({ kind, where: `/${key}/${name}`, reason: `${kind}s are not imported` });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const key of Object.keys(document)) {
|
|
171
|
+
if (key.startsWith('x-')) {
|
|
172
|
+
skipped.push({ kind: 'extension', where: `/${key}`, reason: 'vendor extensions are not imported' });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
version,
|
|
177
|
+
declaredVersion: declared,
|
|
178
|
+
info: {
|
|
179
|
+
title,
|
|
180
|
+
...(asString(info['version']) !== undefined ? { version: asString(info['version']) } : {}),
|
|
181
|
+
...(asString(info['description']) !== undefined ? { description: asString(info['description']) } : {}),
|
|
182
|
+
},
|
|
183
|
+
servers: parseServers(document['servers'], skipped),
|
|
184
|
+
operations: parseOperations(document['paths'], skipped),
|
|
185
|
+
securitySchemes: parseSecuritySchemes(document, skipped),
|
|
186
|
+
...(parseSecurityRequirements(document['security']) !== undefined
|
|
187
|
+
? { security: parseSecurityRequirements(document['security']) }
|
|
188
|
+
: {}),
|
|
189
|
+
tags: parseTags(document['tags']),
|
|
190
|
+
skipped,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function parseServers(value, skipped) {
|
|
194
|
+
if (!Array.isArray(value)) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
const servers = [];
|
|
198
|
+
value.forEach((entry, index) => {
|
|
199
|
+
if (!isRecord(entry)) {
|
|
200
|
+
skipped.push({ kind: 'server', where: `/servers/${String(index)}`, reason: 'not an object' });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const url = asString(entry['url']);
|
|
204
|
+
if (url === undefined) {
|
|
205
|
+
skipped.push({ kind: 'server', where: `/servers/${String(index)}`, reason: 'no url' });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const variables = parseServerVariables(entry['variables']);
|
|
209
|
+
servers.push({
|
|
210
|
+
url,
|
|
211
|
+
...(asString(entry['description']) !== undefined
|
|
212
|
+
? { description: asString(entry['description']) }
|
|
213
|
+
: {}),
|
|
214
|
+
...(variables !== undefined ? { variables } : {}),
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
return servers;
|
|
218
|
+
}
|
|
219
|
+
function parseServerVariables(value) {
|
|
220
|
+
if (!isRecord(value)) {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
const variables = {};
|
|
224
|
+
for (const [name, entry] of Object.entries(value)) {
|
|
225
|
+
if (!isRecord(entry)) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
// A variable with no default has nothing to substitute, so the template survives into the base
|
|
229
|
+
// URL — see `serverUrl`.
|
|
230
|
+
const fallback = asString(entry['default']);
|
|
231
|
+
variables[name] = {
|
|
232
|
+
...(fallback !== undefined ? { default: fallback } : {}),
|
|
233
|
+
...(asStringArray(entry['enum']) !== undefined ? { enum: asStringArray(entry['enum']) } : {}),
|
|
234
|
+
...(asString(entry['description']) !== undefined
|
|
235
|
+
? { description: asString(entry['description']) }
|
|
236
|
+
: {}),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return Object.keys(variables).length === 0 ? undefined : variables;
|
|
240
|
+
}
|
|
241
|
+
const RFC_9110_METHOD_TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
242
|
+
const FIXED_PATH_ITEM_METHODS = new Set(HTTP_METHODS);
|
|
243
|
+
function parseOperations(value, skipped) {
|
|
244
|
+
if (!isRecord(value)) {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
const operations = [];
|
|
248
|
+
for (const [path, item] of Object.entries(value)) {
|
|
249
|
+
if (path.startsWith('x-')) {
|
|
250
|
+
skipped.push({ kind: 'extension', where: `/paths/${path}`, reason: 'vendor extensions are not imported' });
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (!isRecord(item)) {
|
|
254
|
+
skipped.push({ kind: 'path', where: `/paths/${path}`, reason: 'not a path item' });
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const shared = parseParameters(item['parameters'], `${path} (path level)`, skipped);
|
|
258
|
+
for (const [key, operation] of Object.entries(item)) {
|
|
259
|
+
if (!HTTP_METHODS.includes(key.toLowerCase())) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (!isRecord(operation)) {
|
|
263
|
+
skipped.push({ kind: 'operation', where: `${key.toUpperCase()} ${path}`, reason: 'not an object' });
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
operations.push(parseOperation(key.toLowerCase(), path, operation, shared, skipped));
|
|
267
|
+
}
|
|
268
|
+
if (isRecord(item['additionalOperations'])) {
|
|
269
|
+
for (const [key, operation] of Object.entries(item['additionalOperations'])) {
|
|
270
|
+
if (key.startsWith('x-')) {
|
|
271
|
+
skipped.push({ kind: 'extension', where: `${key} ${path}`, reason: 'vendor extensions are not imported' });
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (FIXED_PATH_ITEM_METHODS.has(key.toLowerCase())) {
|
|
275
|
+
skipped.push({ kind: 'operation', where: `${key} ${path}`, reason: 'use the fixed field' });
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (!RFC_9110_METHOD_TOKEN.test(key)) {
|
|
279
|
+
skipped.push({ kind: 'operation', where: `${key} ${path}`, reason: 'invalid HTTP method name' });
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!isRecord(operation)) {
|
|
283
|
+
skipped.push({ kind: 'operation', where: `${key} ${path}`, reason: 'not an object' });
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
operations.push(parseOperation(key, path, operation, shared, skipped));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return operations;
|
|
291
|
+
}
|
|
292
|
+
function parseOperation(method, path, operation, shared, skipped) {
|
|
293
|
+
const where = `${method.toUpperCase()} ${path}`;
|
|
294
|
+
const own = parseParameters(operation['parameters'], where, skipped);
|
|
295
|
+
// "The operation's own wins", keyed by name *and* location — the specification's own identity for
|
|
296
|
+
// a parameter, so a `petId` in the path and a `petId` in the query stay two parameters.
|
|
297
|
+
const merged = new Map();
|
|
298
|
+
for (const parameter of [...shared, ...own]) {
|
|
299
|
+
merged.set(`${parameter.in}:${parameter.name}`, parameter);
|
|
300
|
+
}
|
|
301
|
+
for (const key of Object.keys(operation)) {
|
|
302
|
+
if (key === 'callbacks' || key === 'links') {
|
|
303
|
+
skipped.push({ kind: key.replace(/s$/, ''), where, reason: `${key} are not imported` });
|
|
304
|
+
}
|
|
305
|
+
if (key.startsWith('x-')) {
|
|
306
|
+
skipped.push({ kind: 'extension', where: `${where} ${key}`, reason: 'vendor extensions are not imported' });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const requestBody = parseRequestBody(operation['requestBody'], where, skipped);
|
|
310
|
+
const security = parseSecurityRequirements(operation['security']);
|
|
311
|
+
return {
|
|
312
|
+
method,
|
|
313
|
+
path,
|
|
314
|
+
parameters: [...merged.values()],
|
|
315
|
+
...(asString(operation['operationId']) !== undefined
|
|
316
|
+
? { operationId: asString(operation['operationId']) }
|
|
317
|
+
: {}),
|
|
318
|
+
...(asString(operation['summary']) !== undefined ? { summary: asString(operation['summary']) } : {}),
|
|
319
|
+
...(asString(operation['description']) !== undefined
|
|
320
|
+
? { description: asString(operation['description']) }
|
|
321
|
+
: {}),
|
|
322
|
+
...(asStringArray(operation['tags']) !== undefined ? { tags: asStringArray(operation['tags']) } : {}),
|
|
323
|
+
...(asBoolean(operation['deprecated']) === true ? { deprecated: true } : {}),
|
|
324
|
+
...(requestBody !== undefined ? { requestBody } : {}),
|
|
325
|
+
...(security !== undefined ? { security } : {}),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function parseParameters(value, where, skipped) {
|
|
329
|
+
if (!Array.isArray(value)) {
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
const parameters = [];
|
|
333
|
+
value.forEach((entry, index) => {
|
|
334
|
+
if (!isRecord(entry)) {
|
|
335
|
+
skipped.push({ kind: 'parameter', where: `${where} #${String(index)}`, reason: 'not an object' });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const name = asString(entry['name']);
|
|
339
|
+
const location = asString(entry['in']);
|
|
340
|
+
if (name === undefined || location === undefined) {
|
|
341
|
+
skipped.push({
|
|
342
|
+
kind: 'parameter',
|
|
343
|
+
where: `${where} #${String(index)}`,
|
|
344
|
+
reason: entry['$ref'] !== undefined ? 'its $ref could not be resolved' : 'no name or location',
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (!['path', 'query', 'header', 'cookie'].includes(location)) {
|
|
349
|
+
skipped.push({ kind: 'parameter', where: `${where} ${name}`, reason: `unknown location "${location}"` });
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
parameters.push({
|
|
353
|
+
name,
|
|
354
|
+
in: location,
|
|
355
|
+
...(asBoolean(entry['required']) !== undefined ? { required: asBoolean(entry['required']) } : {}),
|
|
356
|
+
...(asBoolean(entry['deprecated']) === true ? { deprecated: true } : {}),
|
|
357
|
+
...(asString(entry['description']) !== undefined
|
|
358
|
+
? { description: asString(entry['description']) }
|
|
359
|
+
: {}),
|
|
360
|
+
...(isRecord(entry['schema']) ? { schema: parseSchema(entry['schema']) } : {}),
|
|
361
|
+
...(entry['example'] !== undefined ? { example: asJson(entry['example']) } : {}),
|
|
362
|
+
...(parseExamples(entry['examples']) !== undefined
|
|
363
|
+
? { examples: parseExamples(entry['examples']) }
|
|
364
|
+
: {}),
|
|
365
|
+
...(asString(entry['style']) !== undefined ? { style: asString(entry['style']) } : {}),
|
|
366
|
+
...(asBoolean(entry['explode']) !== undefined ? { explode: asBoolean(entry['explode']) } : {}),
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
return parameters;
|
|
370
|
+
}
|
|
371
|
+
function parseExamples(value) {
|
|
372
|
+
if (!isRecord(value)) {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
const examples = nullRecord();
|
|
376
|
+
for (const [name, entry] of Object.entries(value)) {
|
|
377
|
+
if (!isRecord(entry)) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const val = asJson(entry['value'] ?? entry['dataValue'] ?? entry['serializedValue']);
|
|
381
|
+
const dataValue = asJson(entry['dataValue']);
|
|
382
|
+
const serializedValue = asString(entry['serializedValue']);
|
|
383
|
+
examples[name] = {
|
|
384
|
+
...(val !== undefined ? { value: val } : {}),
|
|
385
|
+
...(dataValue !== undefined ? { dataValue } : {}),
|
|
386
|
+
...(serializedValue !== undefined ? { serializedValue } : {}),
|
|
387
|
+
...(asString(entry['summary']) !== undefined ? { summary: asString(entry['summary']) } : {}),
|
|
388
|
+
...(asString(entry['externalValue']) !== undefined
|
|
389
|
+
? { externalValue: asString(entry['externalValue']) }
|
|
390
|
+
: {}),
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return Object.keys(examples).length === 0 ? undefined : examples;
|
|
394
|
+
}
|
|
395
|
+
function parseRequestBody(value, where, skipped) {
|
|
396
|
+
if (!isRecord(value)) {
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
if (!isRecord(value['content'])) {
|
|
400
|
+
skipped.push({
|
|
401
|
+
kind: 'requestBody',
|
|
402
|
+
where,
|
|
403
|
+
reason: value['$ref'] !== undefined ? 'its $ref could not be resolved' : 'no content',
|
|
404
|
+
});
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
const content = nullRecord();
|
|
408
|
+
for (const [mediaType, entry] of Object.entries(value['content'])) {
|
|
409
|
+
if (!isRecord(entry)) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const schema = isRecord(entry['schema'])
|
|
413
|
+
? parseSchema(entry['schema'])
|
|
414
|
+
: isRecord(entry['itemSchema'])
|
|
415
|
+
? parseSchema(entry['itemSchema'])
|
|
416
|
+
: undefined;
|
|
417
|
+
const itemSchema = isRecord(entry['itemSchema']) ? parseSchema(entry['itemSchema']) : undefined;
|
|
418
|
+
content[mediaType] = {
|
|
419
|
+
...(schema !== undefined ? { schema } : {}),
|
|
420
|
+
...(itemSchema !== undefined ? { itemSchema } : {}),
|
|
421
|
+
...(entry['example'] !== undefined ? { example: asJson(entry['example']) } : {}),
|
|
422
|
+
...(parseExamples(entry['examples']) !== undefined
|
|
423
|
+
? { examples: parseExamples(entry['examples']) }
|
|
424
|
+
: {}),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
content,
|
|
429
|
+
...(asBoolean(value['required']) !== undefined ? { required: asBoolean(value['required']) } : {}),
|
|
430
|
+
...(asString(value['description']) !== undefined ? { description: asString(value['description']) } : {}),
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
/** Reads a schema, keeping only what a sample generator needs. Recursive, and structure-only. */
|
|
434
|
+
/**
|
|
435
|
+
* One parsed schema per resolved node, keyed by the node itself.
|
|
436
|
+
*
|
|
437
|
+
* A `$ref`-resolved description is a *graph*: `refs.ts` hands back one object per reference target,
|
|
438
|
+
* shared by every place that referenced it. Rebuilding that graph as a tree — which is what a plain
|
|
439
|
+
* recursive parse does — revisits a shared node once per path to it, so a document whose schemas
|
|
440
|
+
* reference each other costs `breadth ^ depth`. Keyed on identity because that is exactly the
|
|
441
|
+
* question being asked: "have I already parsed *this* node?". A `WeakMap` so a parsed document does
|
|
442
|
+
* not pin the resolved one in memory after the import is over.
|
|
443
|
+
*/
|
|
444
|
+
const parsedSchemas = new WeakMap();
|
|
445
|
+
export function parseSchema(value) {
|
|
446
|
+
const already = parsedSchemas.get(value);
|
|
447
|
+
if (already !== undefined) {
|
|
448
|
+
return already;
|
|
449
|
+
}
|
|
450
|
+
// Placed before the recursion so a self-referencing node — one the resolver left cyclic — resolves
|
|
451
|
+
// to the same object rather than recursing forever. The placeholder is filled in below.
|
|
452
|
+
const schema = parseSchemaFields(value);
|
|
453
|
+
parsedSchemas.set(value, schema);
|
|
454
|
+
return schema;
|
|
455
|
+
}
|
|
456
|
+
/** The body of {@link parseSchema}, without the memo. */
|
|
457
|
+
function parseSchemaFields(value) {
|
|
458
|
+
let properties;
|
|
459
|
+
if (isRecord(value['properties'])) {
|
|
460
|
+
properties = nullRecord();
|
|
461
|
+
for (const [name, entry] of Object.entries(value['properties'])) {
|
|
462
|
+
if (isRecord(entry)) {
|
|
463
|
+
properties[name] = parseSchema(entry);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const branches = (key) => {
|
|
468
|
+
const list = value[key];
|
|
469
|
+
return Array.isArray(list) ? list.filter(isRecord).map(parseSchema) : undefined;
|
|
470
|
+
};
|
|
471
|
+
const type = value['type'];
|
|
472
|
+
const additional = value['additionalProperties'];
|
|
473
|
+
return {
|
|
474
|
+
...(typeof type === 'string' || asStringArray(type) !== undefined
|
|
475
|
+
? { type: type }
|
|
476
|
+
: {}),
|
|
477
|
+
...(asString(value['format']) !== undefined ? { format: asString(value['format']) } : {}),
|
|
478
|
+
...(asString(value['title']) !== undefined ? { title: asString(value['title']) } : {}),
|
|
479
|
+
...(asString(value['description']) !== undefined ? { description: asString(value['description']) } : {}),
|
|
480
|
+
...(value['default'] !== undefined ? { default: asJson(value['default']) } : {}),
|
|
481
|
+
...(value['example'] !== undefined ? { example: asJson(value['example']) } : {}),
|
|
482
|
+
...(Array.isArray(value['examples']) ? { examples: value['examples'] } : {}),
|
|
483
|
+
...(Array.isArray(value['enum']) ? { enum: value['enum'] } : {}),
|
|
484
|
+
...(value['const'] !== undefined ? { const: asJson(value['const']) } : {}),
|
|
485
|
+
...(properties !== undefined ? { properties } : {}),
|
|
486
|
+
...(asStringArray(value['required']) !== undefined
|
|
487
|
+
? { required: asStringArray(value['required']) }
|
|
488
|
+
: {}),
|
|
489
|
+
...(isRecord(value['items']) ? { items: parseSchema(value['items']) } : {}),
|
|
490
|
+
...(typeof additional === 'boolean'
|
|
491
|
+
? { additionalProperties: additional }
|
|
492
|
+
: isRecord(additional)
|
|
493
|
+
? { additionalProperties: parseSchema(additional) }
|
|
494
|
+
: {}),
|
|
495
|
+
...(branches('allOf') !== undefined ? { allOf: branches('allOf') } : {}),
|
|
496
|
+
...(branches('oneOf') !== undefined ? { oneOf: branches('oneOf') } : {}),
|
|
497
|
+
...(branches('anyOf') !== undefined ? { anyOf: branches('anyOf') } : {}),
|
|
498
|
+
...(asBoolean(value['nullable']) !== undefined ? { nullable: asBoolean(value['nullable']) } : {}),
|
|
499
|
+
...(asBoolean(value['deprecated']) === true ? { deprecated: true } : {}),
|
|
500
|
+
...(asBoolean(value['readOnly']) === true ? { readOnly: true } : {}),
|
|
501
|
+
...(asBoolean(value['writeOnly']) === true ? { writeOnly: true } : {}),
|
|
502
|
+
...(isRecord(value['xml']) ? { xml: parseXml(value['xml']) } : {}),
|
|
503
|
+
// A `$ref` that survived resolution could not be resolved; the sample generator says so rather
|
|
504
|
+
// than inventing a value for a schema it never saw.
|
|
505
|
+
...(asString(value['$ref']) !== undefined ? { $ref: asString(value['$ref']) } : {}),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function parseXml(value) {
|
|
509
|
+
return {
|
|
510
|
+
...(asString(value['name']) !== undefined ? { name: asString(value['name']) } : {}),
|
|
511
|
+
...(asString(value['namespace']) !== undefined ? { namespace: asString(value['namespace']) } : {}),
|
|
512
|
+
...(asString(value['prefix']) !== undefined ? { prefix: asString(value['prefix']) } : {}),
|
|
513
|
+
...(asBoolean(value['attribute']) !== undefined ? { attribute: asBoolean(value['attribute']) } : {}),
|
|
514
|
+
...(asBoolean(value['wrapped']) !== undefined ? { wrapped: asBoolean(value['wrapped']) } : {}),
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function parseSecuritySchemes(document, skipped) {
|
|
518
|
+
const components = document['components'];
|
|
519
|
+
const schemes = isRecord(components) ? components['securitySchemes'] : undefined;
|
|
520
|
+
if (!isRecord(schemes)) {
|
|
521
|
+
return [];
|
|
522
|
+
}
|
|
523
|
+
const parsed = [];
|
|
524
|
+
for (const [name, entry] of Object.entries(schemes)) {
|
|
525
|
+
if (!isRecord(entry)) {
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
const type = asString(entry['type']);
|
|
529
|
+
if (type === undefined) {
|
|
530
|
+
skipped.push({ kind: 'securityScheme', where: `/components/securitySchemes/${name}`, reason: 'no type' });
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (!['http', 'apiKey', 'oauth2', 'openIdConnect', 'mutualTLS'].includes(type)) {
|
|
534
|
+
skipped.push({
|
|
535
|
+
kind: 'securityScheme',
|
|
536
|
+
where: `/components/securitySchemes/${name}`,
|
|
537
|
+
reason: `unknown type "${type}"`,
|
|
538
|
+
});
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
parsed.push({
|
|
542
|
+
name,
|
|
543
|
+
type: type,
|
|
544
|
+
...(asString(entry['description']) !== undefined
|
|
545
|
+
? { description: asString(entry['description']) }
|
|
546
|
+
: {}),
|
|
547
|
+
...(asString(entry['scheme']) !== undefined
|
|
548
|
+
? { scheme: asString(entry['scheme']).toLowerCase() }
|
|
549
|
+
: {}),
|
|
550
|
+
...(asString(entry['bearerFormat']) !== undefined
|
|
551
|
+
? { bearerFormat: asString(entry['bearerFormat']) }
|
|
552
|
+
: {}),
|
|
553
|
+
...(asString(entry['in']) !== undefined ? { in: asString(entry['in']) } : {}),
|
|
554
|
+
// `name` on an apiKey scheme is the *parameter's* name, which would collide with the scheme's
|
|
555
|
+
// own key, so the model calls it `keyName`.
|
|
556
|
+
...(asString(entry['name']) !== undefined ? { keyName: asString(entry['name']) } : {}),
|
|
557
|
+
...(parseFlows(entry['flows']) !== undefined
|
|
558
|
+
? { flows: parseFlows(entry['flows']) }
|
|
559
|
+
: {}),
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
return parsed;
|
|
563
|
+
}
|
|
564
|
+
function parseFlows(value) {
|
|
565
|
+
if (!isRecord(value)) {
|
|
566
|
+
return undefined;
|
|
567
|
+
}
|
|
568
|
+
const flows = nullRecord();
|
|
569
|
+
for (const [name, entry] of Object.entries(value)) {
|
|
570
|
+
if (!isRecord(entry)) {
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
let scopes;
|
|
574
|
+
if (isRecord(entry['scopes'])) {
|
|
575
|
+
const scopesRecord = nullRecord();
|
|
576
|
+
for (const [scope, description] of Object.entries(entry['scopes'])) {
|
|
577
|
+
scopesRecord[scope] = asString(description) ?? '';
|
|
578
|
+
}
|
|
579
|
+
scopes = scopesRecord;
|
|
580
|
+
}
|
|
581
|
+
flows[name] = {
|
|
582
|
+
...(asString(entry['authorizationUrl']) !== undefined
|
|
583
|
+
? { authorizationUrl: asString(entry['authorizationUrl']) }
|
|
584
|
+
: {}),
|
|
585
|
+
...(asString(entry['tokenUrl']) !== undefined ? { tokenUrl: asString(entry['tokenUrl']) } : {}),
|
|
586
|
+
...(asString(entry['refreshUrl']) !== undefined ? { refreshUrl: asString(entry['refreshUrl']) } : {}),
|
|
587
|
+
...(scopes !== undefined ? { scopes } : {}),
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return Object.keys(flows).length === 0 ? undefined : flows;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Security requirements, or `undefined` when the document or operation declares none.
|
|
594
|
+
*
|
|
595
|
+
* An empty array is kept as an empty array: `security: []` on an operation means "this one is
|
|
596
|
+
* explicitly unauthenticated", which is different from saying nothing at all.
|
|
597
|
+
*/
|
|
598
|
+
function parseSecurityRequirements(value) {
|
|
599
|
+
if (!Array.isArray(value)) {
|
|
600
|
+
return undefined;
|
|
601
|
+
}
|
|
602
|
+
return value.filter(isRecord).map((entry) => {
|
|
603
|
+
const req = nullRecord();
|
|
604
|
+
for (const [name, scopes] of Object.entries(entry)) {
|
|
605
|
+
req[name] = asStringArray(scopes) ?? [];
|
|
606
|
+
}
|
|
607
|
+
return req;
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
function parseTags(value) {
|
|
611
|
+
if (!Array.isArray(value)) {
|
|
612
|
+
return [];
|
|
613
|
+
}
|
|
614
|
+
const tags = [];
|
|
615
|
+
for (const entry of value) {
|
|
616
|
+
if (!isRecord(entry)) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
const name = asString(entry['name']);
|
|
620
|
+
if (name === undefined) {
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
tags.push({
|
|
624
|
+
name,
|
|
625
|
+
...(asString(entry['description']) !== undefined
|
|
626
|
+
? { description: asString(entry['description']) }
|
|
627
|
+
: {}),
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
return tags;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Reads a resolved Swagger 2.0 document into the internal OpenApiDocument representation.
|
|
634
|
+
*/
|
|
635
|
+
function parseSwagger2Document(document, declared) {
|
|
636
|
+
const skipped = [];
|
|
637
|
+
const info = isRecord(document['info']) ? document['info'] : {};
|
|
638
|
+
const title = asString(info['title']) ?? 'Imported API';
|
|
639
|
+
for (const key of Object.keys(document)) {
|
|
640
|
+
if (key.startsWith('x-')) {
|
|
641
|
+
skipped.push({ kind: 'extension', where: `/${key}`, reason: 'vendor extensions are not imported' });
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (document['produces'] !== undefined) {
|
|
645
|
+
skipped.push({ kind: 'produces', where: '/produces', reason: 'produces are not imported' });
|
|
646
|
+
}
|
|
647
|
+
if (document['responses'] !== undefined) {
|
|
648
|
+
skipped.push({ kind: 'responses', where: '/responses', reason: 'responses are not imported' });
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
version: '2.0',
|
|
652
|
+
declaredVersion: declared,
|
|
653
|
+
info: {
|
|
654
|
+
title,
|
|
655
|
+
...(asString(info['version']) !== undefined ? { version: asString(info['version']) } : {}),
|
|
656
|
+
...(asString(info['description']) !== undefined ? { description: asString(info['description']) } : {}),
|
|
657
|
+
},
|
|
658
|
+
servers: parseSwagger2Servers(document),
|
|
659
|
+
operations: parseSwagger2Operations(document, skipped),
|
|
660
|
+
securitySchemes: parseSwagger2SecuritySchemes(document['securityDefinitions'], skipped),
|
|
661
|
+
...(parseSecurityRequirements(document['security']) !== undefined
|
|
662
|
+
? { security: parseSecurityRequirements(document['security']) }
|
|
663
|
+
: {}),
|
|
664
|
+
tags: parseTags(document['tags']),
|
|
665
|
+
skipped,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function parseSwagger2Servers(document) {
|
|
669
|
+
const host = asString(document['host']);
|
|
670
|
+
let basePath = asString(document['basePath']);
|
|
671
|
+
if (basePath !== undefined && basePath !== '') {
|
|
672
|
+
if (!basePath.startsWith('/')) {
|
|
673
|
+
basePath = `/${basePath}`;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
basePath = '';
|
|
678
|
+
}
|
|
679
|
+
const rawSchemes = asStringArray(document['schemes']);
|
|
680
|
+
const validSchemes = (rawSchemes?.filter((s) => s.toLowerCase() === 'http' || s.toLowerCase() === 'https') ?? []).map((s) => s.toLowerCase());
|
|
681
|
+
if (host !== undefined && host !== '') {
|
|
682
|
+
const schemeMatch = host.match(/^([a-z][a-z0-9+.-]*):\/\/(.*)$/i);
|
|
683
|
+
let effectiveHost = host;
|
|
684
|
+
let schemeFromHost;
|
|
685
|
+
if (schemeMatch) {
|
|
686
|
+
schemeFromHost = schemeMatch[1]?.toLowerCase();
|
|
687
|
+
effectiveHost = schemeMatch[2] ?? '';
|
|
688
|
+
}
|
|
689
|
+
const cleanHost = trimTrailingSlashes(effectiveHost);
|
|
690
|
+
let schemes;
|
|
691
|
+
if (schemeFromHost) {
|
|
692
|
+
schemes = [schemeFromHost, ...validSchemes.filter((s) => s !== schemeFromHost)];
|
|
693
|
+
}
|
|
694
|
+
else if (validSchemes.length > 0) {
|
|
695
|
+
schemes = validSchemes;
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
schemes = ['https'];
|
|
699
|
+
}
|
|
700
|
+
return schemes.map((scheme) => ({
|
|
701
|
+
url: `${scheme}://${cleanHost}${basePath}`,
|
|
702
|
+
}));
|
|
703
|
+
}
|
|
704
|
+
if (basePath !== '' && basePath !== '/') {
|
|
705
|
+
return [{ url: basePath }];
|
|
706
|
+
}
|
|
707
|
+
return [{ url: '/' }];
|
|
708
|
+
}
|
|
709
|
+
function parseSwagger2SecuritySchemes(definitions, skipped) {
|
|
710
|
+
if (!isRecord(definitions)) {
|
|
711
|
+
return [];
|
|
712
|
+
}
|
|
713
|
+
const parsed = [];
|
|
714
|
+
for (const [name, entry] of Object.entries(definitions)) {
|
|
715
|
+
if (!isRecord(entry)) {
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
const type = asString(entry['type']);
|
|
719
|
+
if (type === undefined) {
|
|
720
|
+
skipped.push({ kind: 'securityScheme', where: `/securityDefinitions/${name}`, reason: 'no type' });
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
const description = asString(entry['description']);
|
|
724
|
+
if (type === 'basic') {
|
|
725
|
+
parsed.push({
|
|
726
|
+
name,
|
|
727
|
+
type: 'http',
|
|
728
|
+
scheme: 'basic',
|
|
729
|
+
...(description !== undefined ? { description } : {}),
|
|
730
|
+
});
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (type === 'apiKey') {
|
|
734
|
+
const inLoc = asString(entry['in']);
|
|
735
|
+
const keyName = asString(entry['name']);
|
|
736
|
+
if (inLoc !== 'header' && inLoc !== 'query') {
|
|
737
|
+
skipped.push({
|
|
738
|
+
kind: 'securityScheme',
|
|
739
|
+
where: `/securityDefinitions/${name}`,
|
|
740
|
+
reason: `unsupported apiKey location "${inLoc ?? ''}"`,
|
|
741
|
+
});
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
parsed.push({
|
|
745
|
+
name,
|
|
746
|
+
type: 'apiKey',
|
|
747
|
+
in: inLoc,
|
|
748
|
+
keyName: keyName ?? name,
|
|
749
|
+
...(description !== undefined ? { description } : {}),
|
|
750
|
+
});
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
if (type === 'oauth2') {
|
|
754
|
+
const rawFlow = asString(entry['flow']);
|
|
755
|
+
const authorizationUrl = asString(entry['authorizationUrl']);
|
|
756
|
+
const tokenUrl = asString(entry['tokenUrl']);
|
|
757
|
+
let scopes;
|
|
758
|
+
if (isRecord(entry['scopes'])) {
|
|
759
|
+
const scopesRecord = nullRecord();
|
|
760
|
+
for (const [scope, desc] of Object.entries(entry['scopes'])) {
|
|
761
|
+
scopesRecord[scope] = asString(desc) ?? '';
|
|
762
|
+
}
|
|
763
|
+
scopes = scopesRecord;
|
|
764
|
+
}
|
|
765
|
+
const flowObj = {
|
|
766
|
+
...(authorizationUrl !== undefined ? { authorizationUrl } : {}),
|
|
767
|
+
...(tokenUrl !== undefined ? { tokenUrl } : {}),
|
|
768
|
+
...(scopes !== undefined ? { scopes } : {}),
|
|
769
|
+
};
|
|
770
|
+
let flowName;
|
|
771
|
+
if (rawFlow === 'implicit') {
|
|
772
|
+
flowName = 'implicit';
|
|
773
|
+
}
|
|
774
|
+
else if (rawFlow === 'password') {
|
|
775
|
+
flowName = 'password';
|
|
776
|
+
}
|
|
777
|
+
else if (rawFlow === 'application') {
|
|
778
|
+
flowName = 'clientCredentials';
|
|
779
|
+
}
|
|
780
|
+
else if (rawFlow === 'accessCode') {
|
|
781
|
+
flowName = 'authorizationCode';
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
flowName = rawFlow ?? 'implicit';
|
|
785
|
+
}
|
|
786
|
+
parsed.push({
|
|
787
|
+
name,
|
|
788
|
+
type: 'oauth2',
|
|
789
|
+
flows: { [flowName]: flowObj },
|
|
790
|
+
...(description !== undefined ? { description } : {}),
|
|
791
|
+
});
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
skipped.push({
|
|
795
|
+
kind: 'securityScheme',
|
|
796
|
+
where: `/securityDefinitions/${name}`,
|
|
797
|
+
reason: `unknown type "${type}"`,
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
return parsed;
|
|
801
|
+
}
|
|
802
|
+
function synthesizeSwagger2ParamSchema(param) {
|
|
803
|
+
const type = asString(param['type']);
|
|
804
|
+
const format = asString(param['format']);
|
|
805
|
+
const items = isRecord(param['items']) ? synthesizeSwagger2ParamSchema(param['items']) : undefined;
|
|
806
|
+
const enumVals = Array.isArray(param['enum']) ? param['enum'] : undefined;
|
|
807
|
+
const defaultVal = asJson(param['default']);
|
|
808
|
+
return {
|
|
809
|
+
...(type !== undefined ? { type } : {}),
|
|
810
|
+
...(format !== undefined ? { format } : {}),
|
|
811
|
+
...(items !== undefined ? { items } : {}),
|
|
812
|
+
...(enumVals !== undefined ? { enum: enumVals } : {}),
|
|
813
|
+
...(defaultVal !== undefined ? { default: defaultVal } : {}),
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function swagger2CollectionFormatToStyle(collectionFormat) {
|
|
817
|
+
if (collectionFormat === 'multi') {
|
|
818
|
+
return { style: 'form', explode: true };
|
|
819
|
+
}
|
|
820
|
+
if (collectionFormat === 'ssv') {
|
|
821
|
+
return { style: 'spaceDelimited', explode: false };
|
|
822
|
+
}
|
|
823
|
+
if (collectionFormat === 'pipes') {
|
|
824
|
+
return { style: 'pipeDelimited', explode: false };
|
|
825
|
+
}
|
|
826
|
+
if (collectionFormat === 'csv') {
|
|
827
|
+
return { style: 'form', explode: false };
|
|
828
|
+
}
|
|
829
|
+
return {};
|
|
830
|
+
}
|
|
831
|
+
function parseSwagger2Operations(document, skipped) {
|
|
832
|
+
const paths = document['paths'];
|
|
833
|
+
if (!isRecord(paths)) {
|
|
834
|
+
return [];
|
|
835
|
+
}
|
|
836
|
+
const rootConsumes = asStringArray(document['consumes']);
|
|
837
|
+
const operations = [];
|
|
838
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
839
|
+
if (path.startsWith('x-')) {
|
|
840
|
+
skipped.push({ kind: 'extension', where: `/paths/${path}`, reason: 'vendor extensions are not imported' });
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if (!isRecord(item)) {
|
|
844
|
+
skipped.push({ kind: 'path', where: `/paths/${path}`, reason: 'not a path item' });
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
const sharedRaw = Array.isArray(item['parameters']) ? item['parameters'].filter(isRecord) : [];
|
|
848
|
+
for (const [key, operation] of Object.entries(item)) {
|
|
849
|
+
if (!HTTP_METHODS.includes(key.toLowerCase())) {
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
if (!isRecord(operation)) {
|
|
853
|
+
skipped.push({ kind: 'operation', where: `${key.toUpperCase()} ${path}`, reason: 'not an object' });
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
const where = `${key.toUpperCase()} ${path}`;
|
|
857
|
+
const ownRaw = Array.isArray(operation['parameters']) ? operation['parameters'].filter(isRecord) : [];
|
|
858
|
+
const paramMap = new Map();
|
|
859
|
+
for (const p of sharedRaw) {
|
|
860
|
+
const name = asString(p['name']);
|
|
861
|
+
const location = asString(p['in']);
|
|
862
|
+
if (name !== undefined && location !== undefined) {
|
|
863
|
+
paramMap.set(`${location}:${name}`, p);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
for (const p of ownRaw) {
|
|
867
|
+
const name = asString(p['name']);
|
|
868
|
+
const location = asString(p['in']);
|
|
869
|
+
if (name !== undefined && location !== undefined) {
|
|
870
|
+
paramMap.set(`${location}:${name}`, p);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
const allParams = [...paramMap.values()];
|
|
874
|
+
let bodyParam;
|
|
875
|
+
const formDataParams = [];
|
|
876
|
+
const standardParams = [];
|
|
877
|
+
for (const p of allParams) {
|
|
878
|
+
const name = asString(p['name']);
|
|
879
|
+
const location = asString(p['in']);
|
|
880
|
+
if (name === undefined || location === undefined) {
|
|
881
|
+
skipped.push({
|
|
882
|
+
kind: 'parameter',
|
|
883
|
+
where,
|
|
884
|
+
reason: p['$ref'] !== undefined ? 'its $ref could not be resolved' : 'no name or location',
|
|
885
|
+
});
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
if (location === 'body') {
|
|
889
|
+
bodyParam = p;
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
if (location === 'formData') {
|
|
893
|
+
formDataParams.push(p);
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
if (!['path', 'query', 'header'].includes(location)) {
|
|
897
|
+
skipped.push({ kind: 'parameter', where: `${where} ${name}`, reason: `unknown location "${location}"` });
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
const collectionFormat = asString(p['collectionFormat']);
|
|
901
|
+
if (collectionFormat === 'tsv') {
|
|
902
|
+
skipped.push({
|
|
903
|
+
kind: 'parameter',
|
|
904
|
+
where: `${where} ${name}`,
|
|
905
|
+
reason: 'collectionFormat: tsv is not supported',
|
|
906
|
+
});
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
const formatStyle = swagger2CollectionFormatToStyle(collectionFormat);
|
|
910
|
+
const isPath = location === 'path';
|
|
911
|
+
standardParams.push({
|
|
912
|
+
name,
|
|
913
|
+
in: location,
|
|
914
|
+
...(isPath
|
|
915
|
+
? { required: true }
|
|
916
|
+
: asBoolean(p['required']) !== undefined
|
|
917
|
+
? { required: asBoolean(p['required']) }
|
|
918
|
+
: {}),
|
|
919
|
+
...(asBoolean(p['deprecated']) === true ? { deprecated: true } : {}),
|
|
920
|
+
...(asString(p['description']) !== undefined ? { description: asString(p['description']) } : {}),
|
|
921
|
+
schema: synthesizeSwagger2ParamSchema(p),
|
|
922
|
+
...(p['default'] !== undefined ? { example: asJson(p['default']) } : {}),
|
|
923
|
+
...(formatStyle.style !== undefined ? { style: formatStyle.style } : {}),
|
|
924
|
+
...(formatStyle.explode !== undefined ? { explode: formatStyle.explode } : {}),
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
let requestBody;
|
|
928
|
+
const opConsumes = asStringArray(operation['consumes']);
|
|
929
|
+
const effectiveConsumes = opConsumes ?? rootConsumes ?? ['application/json'];
|
|
930
|
+
const normalizeMediaType = (mt) => mt.split(';')[0]?.trim().toLowerCase() ?? '';
|
|
931
|
+
if (bodyParam !== undefined) {
|
|
932
|
+
if (formDataParams.length > 0) {
|
|
933
|
+
skipped.push({
|
|
934
|
+
kind: 'parameter',
|
|
935
|
+
where,
|
|
936
|
+
reason: 'formData ignored because operation already has a body parameter',
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
const schema = isRecord(bodyParam['schema']) ? parseSchema(bodyParam['schema']) : undefined;
|
|
940
|
+
const content = nullRecord();
|
|
941
|
+
for (const mt of effectiveConsumes) {
|
|
942
|
+
content[mt] = {
|
|
943
|
+
...(schema !== undefined ? { schema } : {}),
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
requestBody = {
|
|
947
|
+
content,
|
|
948
|
+
...(asBoolean(bodyParam['required']) !== undefined
|
|
949
|
+
? { required: asBoolean(bodyParam['required']) }
|
|
950
|
+
: {}),
|
|
951
|
+
...(asString(bodyParam['description']) !== undefined
|
|
952
|
+
? { description: asString(bodyParam['description']) }
|
|
953
|
+
: {}),
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
else if (formDataParams.length > 0) {
|
|
957
|
+
const hasFile = formDataParams.some((p) => asString(p['type']) === 'file');
|
|
958
|
+
const defaultMt = hasFile ? 'multipart/form-data' : 'application/x-www-form-urlencoded';
|
|
959
|
+
const matchedConsumes = effectiveConsumes.filter((mt) => {
|
|
960
|
+
const norm = normalizeMediaType(mt);
|
|
961
|
+
return norm === 'multipart/form-data' || norm === 'application/x-www-form-urlencoded';
|
|
962
|
+
});
|
|
963
|
+
const formMediaTypes = matchedConsumes.length > 0 ? matchedConsumes : [defaultMt];
|
|
964
|
+
const properties = nullRecord();
|
|
965
|
+
const required = [];
|
|
966
|
+
for (const p of formDataParams) {
|
|
967
|
+
const name = asString(p['name']);
|
|
968
|
+
if (!name)
|
|
969
|
+
continue;
|
|
970
|
+
if (asBoolean(p['required']) === true) {
|
|
971
|
+
required.push(name);
|
|
972
|
+
}
|
|
973
|
+
if (asString(p['type']) === 'file') {
|
|
974
|
+
properties[name] = {
|
|
975
|
+
type: 'string',
|
|
976
|
+
format: 'binary',
|
|
977
|
+
...(asString(p['description']) !== undefined
|
|
978
|
+
? { description: asString(p['description']) }
|
|
979
|
+
: {}),
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
properties[name] = synthesizeSwagger2ParamSchema(p);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
const schema = {
|
|
987
|
+
type: 'object',
|
|
988
|
+
properties,
|
|
989
|
+
...(required.length > 0 ? { required } : {}),
|
|
990
|
+
};
|
|
991
|
+
const content = nullRecord();
|
|
992
|
+
for (const mt of formMediaTypes) {
|
|
993
|
+
content[mt] = { schema };
|
|
994
|
+
}
|
|
995
|
+
requestBody = {
|
|
996
|
+
content,
|
|
997
|
+
required: required.length > 0,
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
for (const opKey of Object.keys(operation)) {
|
|
1001
|
+
if (opKey.startsWith('x-')) {
|
|
1002
|
+
if (opKey === 'x-example') {
|
|
1003
|
+
skipped.push({ kind: 'example', where: `${where} x-example`, reason: 'examples are not imported' });
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
skipped.push({
|
|
1007
|
+
kind: 'extension',
|
|
1008
|
+
where: `${where} ${opKey}`,
|
|
1009
|
+
reason: 'vendor extensions are not imported',
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
else if (opKey === 'produces') {
|
|
1014
|
+
skipped.push({ kind: 'produces', where: `${where} produces`, reason: 'produces are not imported' });
|
|
1015
|
+
}
|
|
1016
|
+
else if (opKey === 'responses') {
|
|
1017
|
+
skipped.push({ kind: 'responses', where: `${where} responses`, reason: 'responses are not imported' });
|
|
1018
|
+
}
|
|
1019
|
+
else if (opKey === 'example') {
|
|
1020
|
+
skipped.push({ kind: 'example', where: `${where} example`, reason: 'examples are not imported' });
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
const security = parseSecurityRequirements(operation['security']);
|
|
1024
|
+
operations.push({
|
|
1025
|
+
method: key.toLowerCase(),
|
|
1026
|
+
path,
|
|
1027
|
+
parameters: standardParams,
|
|
1028
|
+
...(asString(operation['operationId']) !== undefined
|
|
1029
|
+
? { operationId: asString(operation['operationId']) }
|
|
1030
|
+
: {}),
|
|
1031
|
+
...(asString(operation['summary']) !== undefined ? { summary: asString(operation['summary']) } : {}),
|
|
1032
|
+
...(asString(operation['description']) !== undefined
|
|
1033
|
+
? { description: asString(operation['description']) }
|
|
1034
|
+
: {}),
|
|
1035
|
+
...(asStringArray(operation['tags']) !== undefined
|
|
1036
|
+
? { tags: asStringArray(operation['tags']) }
|
|
1037
|
+
: {}),
|
|
1038
|
+
...(asBoolean(operation['deprecated']) === true ? { deprecated: true } : {}),
|
|
1039
|
+
...(requestBody !== undefined ? { requestBody } : {}),
|
|
1040
|
+
...(security !== undefined ? { security } : {}),
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
return operations;
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Reads a Swagger 1.0, 1.1, or 1.2 document (API Declaration or Resource Listing) into the internal
|
|
1048
|
+
* OpenApiDocument representation.
|
|
1049
|
+
*/
|
|
1050
|
+
function parseSwagger1Document(document, declared, version = '1.2') {
|
|
1051
|
+
const skipped = [];
|
|
1052
|
+
const info = isRecord(document['info']) ? document['info'] : {};
|
|
1053
|
+
const resourcePath = asString(document['resourcePath']);
|
|
1054
|
+
const title = asString(info['title']) ??
|
|
1055
|
+
(resourcePath !== undefined && resourcePath.length > 1 ? resourcePath.replace(/^\//, '') : 'Imported API');
|
|
1056
|
+
for (const key of Object.keys(document)) {
|
|
1057
|
+
if (key.startsWith('x-')) {
|
|
1058
|
+
skipped.push({ kind: 'extension', where: `/${key}`, reason: 'vendor extensions are not imported' });
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
const modelCtx = {
|
|
1062
|
+
rawModels: isRecord(document['models']) ? document['models'] : {},
|
|
1063
|
+
memo: new Map(),
|
|
1064
|
+
};
|
|
1065
|
+
const servers = parseSwagger1Servers(document);
|
|
1066
|
+
const operations = parseSwagger1Operations(document, modelCtx, skipped);
|
|
1067
|
+
if (operations.length === 0 && Array.isArray(document['apis']) && document['apis'].length > 0) {
|
|
1068
|
+
throw new OpenApiError('openapi-resource-listing-not-inlined', 'Swagger 1.2 Resource Listing contains external API declarations that are not inlined and yielded no operations');
|
|
1069
|
+
}
|
|
1070
|
+
const securitySchemes = parseSwagger1SecuritySchemes(document['authorizations'], skipped);
|
|
1071
|
+
const tags = parseSwagger1Tags(document);
|
|
1072
|
+
return {
|
|
1073
|
+
version,
|
|
1074
|
+
declaredVersion: declared,
|
|
1075
|
+
info: {
|
|
1076
|
+
title,
|
|
1077
|
+
...(asString(document['apiVersion']) !== undefined
|
|
1078
|
+
? { version: asString(document['apiVersion']) }
|
|
1079
|
+
: asString(info['version']) !== undefined
|
|
1080
|
+
? { version: asString(info['version']) }
|
|
1081
|
+
: {}),
|
|
1082
|
+
...(asString(info['description']) !== undefined ? { description: asString(info['description']) } : {}),
|
|
1083
|
+
},
|
|
1084
|
+
servers,
|
|
1085
|
+
operations,
|
|
1086
|
+
securitySchemes,
|
|
1087
|
+
tags,
|
|
1088
|
+
skipped,
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
function parseSwagger1Servers(document) {
|
|
1092
|
+
const basePath = asString(document['basePath']);
|
|
1093
|
+
if (basePath !== undefined && basePath.trim().length > 0) {
|
|
1094
|
+
return [{ url: basePath.trim() }];
|
|
1095
|
+
}
|
|
1096
|
+
return [{ url: '/' }];
|
|
1097
|
+
}
|
|
1098
|
+
function parseSwagger1Tags(document) {
|
|
1099
|
+
const tags = [];
|
|
1100
|
+
const resourcePath = asString(document['resourcePath']);
|
|
1101
|
+
if (resourcePath !== undefined && resourcePath.length > 1) {
|
|
1102
|
+
const tagName = resourcePath.replace(/^\//, '');
|
|
1103
|
+
const info = isRecord(document['info']) ? document['info'] : {};
|
|
1104
|
+
tags.push({
|
|
1105
|
+
name: tagName,
|
|
1106
|
+
...(asString(info['description']) !== undefined ? { description: asString(info['description']) } : {}),
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
return tags;
|
|
1110
|
+
}
|
|
1111
|
+
function normalizeSwagger1Type(rawType) {
|
|
1112
|
+
if (rawType === undefined) {
|
|
1113
|
+
return {};
|
|
1114
|
+
}
|
|
1115
|
+
const lower = rawType.toLowerCase();
|
|
1116
|
+
switch (lower) {
|
|
1117
|
+
case 'string':
|
|
1118
|
+
return { type: 'string' };
|
|
1119
|
+
case 'integer':
|
|
1120
|
+
case 'int':
|
|
1121
|
+
case 'int32':
|
|
1122
|
+
return { type: 'integer', format: 'int32' };
|
|
1123
|
+
case 'long':
|
|
1124
|
+
case 'int64':
|
|
1125
|
+
return { type: 'integer', format: 'int64' };
|
|
1126
|
+
case 'float':
|
|
1127
|
+
return { type: 'number', format: 'float' };
|
|
1128
|
+
case 'double':
|
|
1129
|
+
return { type: 'number', format: 'double' };
|
|
1130
|
+
case 'number':
|
|
1131
|
+
return { type: 'number' };
|
|
1132
|
+
case 'boolean':
|
|
1133
|
+
case 'bool':
|
|
1134
|
+
return { type: 'boolean' };
|
|
1135
|
+
case 'byte':
|
|
1136
|
+
return { type: 'string', format: 'byte' };
|
|
1137
|
+
case 'date':
|
|
1138
|
+
return { type: 'string', format: 'date' };
|
|
1139
|
+
case 'date-time':
|
|
1140
|
+
case 'datetime':
|
|
1141
|
+
return { type: 'string', format: 'date-time' };
|
|
1142
|
+
case 'file':
|
|
1143
|
+
return { type: 'string', format: 'binary' };
|
|
1144
|
+
case 'array':
|
|
1145
|
+
case 'list':
|
|
1146
|
+
case 'set':
|
|
1147
|
+
return { type: 'array' };
|
|
1148
|
+
case 'void':
|
|
1149
|
+
return {};
|
|
1150
|
+
default:
|
|
1151
|
+
// An unknown type name (typically an undeclared model) is not a JSON Schema type.
|
|
1152
|
+
return {};
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
function resolveSwagger1Model(name, ctx, visiting = new Set()) {
|
|
1156
|
+
if (visiting.has(name)) {
|
|
1157
|
+
return { type: 'object', properties: {} };
|
|
1158
|
+
}
|
|
1159
|
+
const cached = ctx.memo.get(name);
|
|
1160
|
+
if (cached !== undefined) {
|
|
1161
|
+
return cached;
|
|
1162
|
+
}
|
|
1163
|
+
if (!Object.hasOwn(ctx.rawModels, name)) {
|
|
1164
|
+
return { type: 'object' };
|
|
1165
|
+
}
|
|
1166
|
+
visiting.add(name);
|
|
1167
|
+
const raw = ctx.rawModels[name];
|
|
1168
|
+
if (!raw) {
|
|
1169
|
+
visiting.delete(name);
|
|
1170
|
+
return { type: 'object' };
|
|
1171
|
+
}
|
|
1172
|
+
const required = asStringArray(raw['required']);
|
|
1173
|
+
const propertiesRaw = isRecord(raw['properties']) ? raw['properties'] : {};
|
|
1174
|
+
const properties = nullRecord();
|
|
1175
|
+
for (const [propName, propVal] of Object.entries(propertiesRaw)) {
|
|
1176
|
+
if (!isRecord(propVal))
|
|
1177
|
+
continue;
|
|
1178
|
+
properties[propName] = convertSwagger1Property(propVal, ctx, new Set(visiting));
|
|
1179
|
+
}
|
|
1180
|
+
const schema = {
|
|
1181
|
+
type: 'object',
|
|
1182
|
+
...(asString(raw['description']) !== undefined ? { description: asString(raw['description']) } : {}),
|
|
1183
|
+
...(required && required.length > 0 ? { required } : {}),
|
|
1184
|
+
properties,
|
|
1185
|
+
};
|
|
1186
|
+
visiting.delete(name);
|
|
1187
|
+
ctx.memo.set(name, schema);
|
|
1188
|
+
return schema;
|
|
1189
|
+
}
|
|
1190
|
+
function convertSwagger1Property(prop, ctx, visiting) {
|
|
1191
|
+
const ref = asString(prop['$ref']);
|
|
1192
|
+
const rawType = asString(prop['type']) ?? asString(prop['dataType']);
|
|
1193
|
+
const format = asString(prop['format']);
|
|
1194
|
+
const description = asString(prop['description']);
|
|
1195
|
+
const enumVals = Array.isArray(prop['enum']) ? prop['enum'] : undefined;
|
|
1196
|
+
const defaultVal = asJson(prop['defaultValue'] ?? prop['default']);
|
|
1197
|
+
const hasRef = ref !== undefined && Object.hasOwn(ctx.rawModels, ref);
|
|
1198
|
+
const hasRawType = rawType !== undefined && Object.hasOwn(ctx.rawModels, rawType);
|
|
1199
|
+
const modelRefName = hasRef ? ref : hasRawType ? rawType : undefined;
|
|
1200
|
+
if (modelRefName !== undefined) {
|
|
1201
|
+
return {
|
|
1202
|
+
...resolveSwagger1Model(modelRefName, ctx, visiting),
|
|
1203
|
+
...(description !== undefined ? { description } : {}),
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
const normalized = normalizeSwagger1Type(rawType);
|
|
1207
|
+
if (normalized.type === 'array') {
|
|
1208
|
+
let itemsSchema;
|
|
1209
|
+
const items = isRecord(prop['items']) ? prop['items'] : undefined;
|
|
1210
|
+
if (items !== undefined) {
|
|
1211
|
+
itemsSchema = convertSwagger1Property(items, ctx, visiting);
|
|
1212
|
+
}
|
|
1213
|
+
else {
|
|
1214
|
+
itemsSchema = { type: 'string' };
|
|
1215
|
+
}
|
|
1216
|
+
return {
|
|
1217
|
+
type: 'array',
|
|
1218
|
+
items: itemsSchema,
|
|
1219
|
+
...(description !== undefined ? { description } : {}),
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
return {
|
|
1223
|
+
type: normalized.type ?? 'string',
|
|
1224
|
+
...(format !== undefined ? { format } : normalized.format !== undefined ? { format: normalized.format } : {}),
|
|
1225
|
+
...(description !== undefined ? { description } : {}),
|
|
1226
|
+
...(enumVals !== undefined && enumVals.length > 0 ? { enum: enumVals } : {}),
|
|
1227
|
+
...(defaultVal !== undefined ? { default: defaultVal } : {}),
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
function synthesizeSwagger1ParamPrimitiveSchema(param) {
|
|
1231
|
+
const rawType = asString(param['type']) ?? asString(param['dataType']);
|
|
1232
|
+
const normalized = normalizeSwagger1Type(rawType);
|
|
1233
|
+
const format = asString(param['format']) ?? normalized.format;
|
|
1234
|
+
const enumVals = Array.isArray(param['enum']) ? param['enum'] : undefined;
|
|
1235
|
+
const defaultVal = asJson(param['defaultValue'] ?? param['default']);
|
|
1236
|
+
return {
|
|
1237
|
+
type: normalized.type ?? 'string',
|
|
1238
|
+
...(format !== undefined ? { format } : {}),
|
|
1239
|
+
...(enumVals !== undefined && enumVals.length > 0 ? { enum: enumVals } : {}),
|
|
1240
|
+
...(defaultVal !== undefined ? { default: defaultVal } : {}),
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
function parseSwagger1Operations(document, modelCtx, skipped) {
|
|
1244
|
+
const rawApis = document['apis'];
|
|
1245
|
+
if (!Array.isArray(rawApis)) {
|
|
1246
|
+
return [];
|
|
1247
|
+
}
|
|
1248
|
+
const rootConsumes = asStringArray(document['consumes']);
|
|
1249
|
+
const resourcePath = asString(document['resourcePath']);
|
|
1250
|
+
const operations = [];
|
|
1251
|
+
for (const apiItem of rawApis) {
|
|
1252
|
+
if (!isRecord(apiItem)) {
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
const path = asString(apiItem['path']);
|
|
1256
|
+
if (path === undefined) {
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
const rawOperations = apiItem['operations'];
|
|
1260
|
+
if (!Array.isArray(rawOperations)) {
|
|
1261
|
+
skipped.push({
|
|
1262
|
+
kind: 'resource',
|
|
1263
|
+
where: path,
|
|
1264
|
+
reason: 'Resource Listing references sub-resource file that is not inlined',
|
|
1265
|
+
});
|
|
1266
|
+
continue;
|
|
1267
|
+
}
|
|
1268
|
+
for (const op of rawOperations) {
|
|
1269
|
+
if (!isRecord(op)) {
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
const rawMethod = asString(op['method']) ?? asString(op['httpMethod']);
|
|
1273
|
+
if (rawMethod === undefined || !HTTP_METHODS.includes(rawMethod.toLowerCase())) {
|
|
1274
|
+
continue;
|
|
1275
|
+
}
|
|
1276
|
+
const method = rawMethod.toLowerCase();
|
|
1277
|
+
const where = `${method.toUpperCase()} ${path}`;
|
|
1278
|
+
const rawParams = Array.isArray(op['parameters']) ? op['parameters'].filter(isRecord) : [];
|
|
1279
|
+
let bodyParam;
|
|
1280
|
+
const formDataParams = [];
|
|
1281
|
+
const standardParams = [];
|
|
1282
|
+
for (const p of rawParams) {
|
|
1283
|
+
const name = asString(p['name']);
|
|
1284
|
+
const paramType = asString(p['paramType']);
|
|
1285
|
+
if (name === undefined || paramType === undefined) {
|
|
1286
|
+
skipped.push({ kind: 'parameter', where, reason: 'parameter without name or paramType' });
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
if (paramType === 'body') {
|
|
1290
|
+
bodyParam = p;
|
|
1291
|
+
continue;
|
|
1292
|
+
}
|
|
1293
|
+
if (paramType === 'form') {
|
|
1294
|
+
formDataParams.push(p);
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
if (!['path', 'query', 'header'].includes(paramType)) {
|
|
1298
|
+
skipped.push({ kind: 'parameter', where: `${where} ${name}`, reason: `unknown location "${paramType}"` });
|
|
1299
|
+
continue;
|
|
1300
|
+
}
|
|
1301
|
+
const allowMultiple = asBoolean(p['allowMultiple']) === true;
|
|
1302
|
+
let schema;
|
|
1303
|
+
if (allowMultiple) {
|
|
1304
|
+
schema = { type: 'array', items: synthesizeSwagger1ParamPrimitiveSchema(p) };
|
|
1305
|
+
}
|
|
1306
|
+
else {
|
|
1307
|
+
schema = synthesizeSwagger1ParamPrimitiveSchema(p);
|
|
1308
|
+
}
|
|
1309
|
+
standardParams.push({
|
|
1310
|
+
name,
|
|
1311
|
+
in: paramType,
|
|
1312
|
+
...(paramType === 'path'
|
|
1313
|
+
? { required: true }
|
|
1314
|
+
: asBoolean(p['required']) !== undefined
|
|
1315
|
+
? { required: asBoolean(p['required']) }
|
|
1316
|
+
: {}),
|
|
1317
|
+
...(asString(p['description']) !== undefined ? { description: asString(p['description']) } : {}),
|
|
1318
|
+
schema,
|
|
1319
|
+
...(p['defaultValue'] !== undefined || p['default'] !== undefined
|
|
1320
|
+
? { example: asJson(p['defaultValue'] ?? p['default']) }
|
|
1321
|
+
: {}),
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
let requestBody;
|
|
1325
|
+
const opConsumes = asStringArray(op['consumes']);
|
|
1326
|
+
const effectiveConsumes = opConsumes ?? rootConsumes ?? ['application/json'];
|
|
1327
|
+
if (bodyParam !== undefined) {
|
|
1328
|
+
const bodyType = asString(bodyParam['type']) ?? asString(bodyParam['dataType']);
|
|
1329
|
+
let bodySchema;
|
|
1330
|
+
if (bodyType !== undefined && Object.hasOwn(modelCtx.rawModels, bodyType)) {
|
|
1331
|
+
bodySchema = resolveSwagger1Model(bodyType, modelCtx);
|
|
1332
|
+
}
|
|
1333
|
+
else if (bodyType !== undefined) {
|
|
1334
|
+
bodySchema = synthesizeSwagger1ParamPrimitiveSchema(bodyParam);
|
|
1335
|
+
}
|
|
1336
|
+
const content = nullRecord();
|
|
1337
|
+
for (const mt of effectiveConsumes) {
|
|
1338
|
+
content[mt] = {
|
|
1339
|
+
...(bodySchema !== undefined ? { schema: bodySchema } : {}),
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
requestBody = {
|
|
1343
|
+
content,
|
|
1344
|
+
...(asBoolean(bodyParam['required']) !== undefined
|
|
1345
|
+
? { required: asBoolean(bodyParam['required']) }
|
|
1346
|
+
: {}),
|
|
1347
|
+
...(asString(bodyParam['description']) !== undefined
|
|
1348
|
+
? { description: asString(bodyParam['description']) }
|
|
1349
|
+
: {}),
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
else if (formDataParams.length > 0) {
|
|
1353
|
+
const properties = nullRecord();
|
|
1354
|
+
const required = [];
|
|
1355
|
+
let hasFile = false;
|
|
1356
|
+
for (const p of formDataParams) {
|
|
1357
|
+
const pName = asString(p['name']) ?? 'field';
|
|
1358
|
+
const pType = asString(p['type']) ?? asString(p['dataType']);
|
|
1359
|
+
if (pType?.toLowerCase() === 'file') {
|
|
1360
|
+
hasFile = true;
|
|
1361
|
+
properties[pName] = { type: 'string', format: 'binary' };
|
|
1362
|
+
}
|
|
1363
|
+
else {
|
|
1364
|
+
properties[pName] = synthesizeSwagger1ParamPrimitiveSchema(p);
|
|
1365
|
+
}
|
|
1366
|
+
if (asBoolean(p['required']) === true) {
|
|
1367
|
+
required.push(pName);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
const contentType = hasFile ? 'multipart/form-data' : 'application/x-www-form-urlencoded';
|
|
1371
|
+
requestBody = {
|
|
1372
|
+
content: {
|
|
1373
|
+
[contentType]: {
|
|
1374
|
+
schema: {
|
|
1375
|
+
type: 'object',
|
|
1376
|
+
properties,
|
|
1377
|
+
...(required.length > 0 ? { required } : {}),
|
|
1378
|
+
},
|
|
1379
|
+
},
|
|
1380
|
+
},
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
// Security requirements
|
|
1384
|
+
const security = [];
|
|
1385
|
+
if (isRecord(op['authorizations'])) {
|
|
1386
|
+
const req = nullRecord();
|
|
1387
|
+
for (const [schemeName, scopesRaw] of Object.entries(op['authorizations'])) {
|
|
1388
|
+
const scopes = [];
|
|
1389
|
+
if (Array.isArray(scopesRaw)) {
|
|
1390
|
+
for (const scopeItem of scopesRaw) {
|
|
1391
|
+
if (isRecord(scopeItem) && typeof scopeItem['scope'] === 'string') {
|
|
1392
|
+
scopes.push(scopeItem['scope']);
|
|
1393
|
+
}
|
|
1394
|
+
else if (typeof scopeItem === 'string') {
|
|
1395
|
+
scopes.push(scopeItem);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
req[schemeName] = scopes;
|
|
1400
|
+
}
|
|
1401
|
+
if (Object.keys(req).length > 0) {
|
|
1402
|
+
security.push(req);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
// Tag derivation
|
|
1406
|
+
let tag;
|
|
1407
|
+
if (resourcePath !== undefined && resourcePath.length > 1) {
|
|
1408
|
+
tag = resourcePath.replace(/^\//, '');
|
|
1409
|
+
}
|
|
1410
|
+
else {
|
|
1411
|
+
const segs = path.split('/').filter((s) => s.length > 0 && !s.startsWith('{'));
|
|
1412
|
+
if (segs.length > 0) {
|
|
1413
|
+
tag = segs[0];
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
const tags = tag !== undefined ? [tag] : undefined;
|
|
1417
|
+
const isDeprecated = op['deprecated'] === true || op['deprecated'] === 'true';
|
|
1418
|
+
operations.push({
|
|
1419
|
+
method,
|
|
1420
|
+
path,
|
|
1421
|
+
parameters: standardParams,
|
|
1422
|
+
...(asString(op['nickname']) !== undefined ? { operationId: asString(op['nickname']) } : {}),
|
|
1423
|
+
...(asString(op['summary']) !== undefined ? { summary: asString(op['summary']) } : {}),
|
|
1424
|
+
...(asString(op['notes']) !== undefined
|
|
1425
|
+
? { description: asString(op['notes']) }
|
|
1426
|
+
: asString(op['description']) !== undefined
|
|
1427
|
+
? { description: asString(op['description']) }
|
|
1428
|
+
: {}),
|
|
1429
|
+
...(tags !== undefined ? { tags } : {}),
|
|
1430
|
+
...(isDeprecated ? { deprecated: true } : {}),
|
|
1431
|
+
...(requestBody !== undefined ? { requestBody } : {}),
|
|
1432
|
+
...(security.length > 0 ? { security } : {}),
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
return operations;
|
|
1437
|
+
}
|
|
1438
|
+
function parseSwagger1SecuritySchemes(authorizations, skipped) {
|
|
1439
|
+
if (!isRecord(authorizations)) {
|
|
1440
|
+
return [];
|
|
1441
|
+
}
|
|
1442
|
+
const parsed = [];
|
|
1443
|
+
for (const [name, entry] of Object.entries(authorizations)) {
|
|
1444
|
+
if (!isRecord(entry))
|
|
1445
|
+
continue;
|
|
1446
|
+
const type = asString(entry['type']);
|
|
1447
|
+
if (type === undefined) {
|
|
1448
|
+
skipped.push({ kind: 'securityScheme', where: `/authorizations/${name}`, reason: 'no type' });
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const description = asString(entry['description']);
|
|
1452
|
+
if (type === 'basicAuth' || type === 'basic') {
|
|
1453
|
+
parsed.push({
|
|
1454
|
+
name,
|
|
1455
|
+
type: 'http',
|
|
1456
|
+
scheme: 'basic',
|
|
1457
|
+
...(description !== undefined ? { description } : {}),
|
|
1458
|
+
});
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
if (type === 'apiKey') {
|
|
1462
|
+
const passAs = asString(entry['passAs']) ?? asString(entry['in']);
|
|
1463
|
+
const keyname = asString(entry['keyname']) ?? asString(entry['name']);
|
|
1464
|
+
if (passAs !== 'header' && passAs !== 'query') {
|
|
1465
|
+
skipped.push({
|
|
1466
|
+
kind: 'securityScheme',
|
|
1467
|
+
where: `/authorizations/${name}`,
|
|
1468
|
+
reason: `unsupported apiKey location "${passAs ?? ''}"`,
|
|
1469
|
+
});
|
|
1470
|
+
continue;
|
|
1471
|
+
}
|
|
1472
|
+
parsed.push({
|
|
1473
|
+
name,
|
|
1474
|
+
type: 'apiKey',
|
|
1475
|
+
in: passAs,
|
|
1476
|
+
keyName: keyname ?? name,
|
|
1477
|
+
...(description !== undefined ? { description } : {}),
|
|
1478
|
+
});
|
|
1479
|
+
continue;
|
|
1480
|
+
}
|
|
1481
|
+
if (type === 'oauth2') {
|
|
1482
|
+
const scopesMap = nullRecord();
|
|
1483
|
+
if (Array.isArray(entry['scopes'])) {
|
|
1484
|
+
for (const s of entry['scopes']) {
|
|
1485
|
+
if (isRecord(s) && typeof s['scope'] === 'string') {
|
|
1486
|
+
scopesMap[s['scope']] = asString(s['description']) ?? '';
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
const grantTypes = isRecord(entry['grantTypes']) ? entry['grantTypes'] : {};
|
|
1491
|
+
const flows = {};
|
|
1492
|
+
if (isRecord(grantTypes['authorization_code'])) {
|
|
1493
|
+
const ac = grantTypes['authorization_code'];
|
|
1494
|
+
const tokenEndpoint = isRecord(ac['tokenEndpoint']) ? asString(ac['tokenEndpoint']['url']) : undefined;
|
|
1495
|
+
const tokenUrl = asString(ac['tokenUrl']) ?? tokenEndpoint;
|
|
1496
|
+
const authEndpoint = isRecord(ac['authorizationEndpoint'])
|
|
1497
|
+
? asString(ac['authorizationEndpoint']['url'])
|
|
1498
|
+
: undefined;
|
|
1499
|
+
const authorizationUrl = asString(ac['authorizationUrl']) ?? authEndpoint;
|
|
1500
|
+
flows['authorizationCode'] = {
|
|
1501
|
+
...(authorizationUrl !== undefined ? { authorizationUrl } : {}),
|
|
1502
|
+
...(tokenUrl !== undefined ? { tokenUrl } : {}),
|
|
1503
|
+
...(Object.keys(scopesMap).length > 0 ? { scopes: scopesMap } : {}),
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
if (isRecord(grantTypes['implicit'])) {
|
|
1507
|
+
const imp = grantTypes['implicit'];
|
|
1508
|
+
const loginEndpoint = isRecord(imp['loginEndpoint']) ? asString(imp['loginEndpoint']['url']) : undefined;
|
|
1509
|
+
const authorizationUrl = asString(imp['authorizationUrl']) ?? loginEndpoint;
|
|
1510
|
+
flows['implicit'] = {
|
|
1511
|
+
...(authorizationUrl !== undefined ? { authorizationUrl } : {}),
|
|
1512
|
+
...(Object.keys(scopesMap).length > 0 ? { scopes: scopesMap } : {}),
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
parsed.push({
|
|
1516
|
+
name,
|
|
1517
|
+
type: 'oauth2',
|
|
1518
|
+
flows,
|
|
1519
|
+
...(description !== undefined ? { description } : {}),
|
|
1520
|
+
});
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
skipped.push({
|
|
1524
|
+
kind: 'securityScheme',
|
|
1525
|
+
where: `/authorizations/${name}`,
|
|
1526
|
+
reason: `unknown type "${type}"`,
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
return parsed;
|
|
1530
|
+
}
|