diff --git a/packages/core/src/submodules/cbor/parseCborBody.ts b/packages/core/src/submodules/cbor/parseCborBody.ts index 2b99e19f32a..8e30b19e1f4 100644 --- a/packages/core/src/submodules/cbor/parseCborBody.ts +++ b/packages/core/src/submodules/cbor/parseCborBody.ts @@ -70,3 +70,9 @@ export const loadSmithyRpcV2CborErrorCode = (output: HttpResponse, data: any): s return sanitizeErrorCode(data.code); } }; + +export const checkCborResponse = (response: HttpResponse): void => { + if (response.headers["smithy-protocol"] !== "rpc-v2-cbor") { + throw new Error("Malformed RPCv2 CBOR response, status: " + response.statusCode); + } +}; diff --git a/packages/smithy-client/src/serde-json.ts b/packages/smithy-client/src/serde-json.ts index b82ff75ba0e..a979e654d52 100644 --- a/packages/smithy-client/src/serde-json.ts +++ b/packages/smithy-client/src/serde-json.ts @@ -4,6 +4,8 @@ * Maps an object through the default JSON serde behavior. * This means removing nullish fields and un-sparsifying lists. * + * This is also used by Smithy RPCv2 CBOR as the default serde behavior. + * * @param obj - to be checked. * @returns same object with default serde behavior applied. */ diff --git a/private/smithy-rpcv2-cbor/package.json b/private/smithy-rpcv2-cbor/package.json index bfe49860328..9c1cb4e1d23 100644 --- a/private/smithy-rpcv2-cbor/package.json +++ b/private/smithy-rpcv2-cbor/package.json @@ -19,27 +19,27 @@ "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/types": "latest", - "@smithy/config-resolver": "^3.0.2", - "@smithy/core": "^2.2.2", - "@smithy/fetch-http-handler": "^3.0.3", - "@smithy/hash-node": "^3.0.1", - "@smithy/invalid-dependency": "^3.0.1", - "@smithy/middleware-content-length": "^3.0.1", - "@smithy/middleware-retry": "^3.0.5", - "@smithy/middleware-serde": "^3.0.1", - "@smithy/middleware-stack": "^3.0.1", - "@smithy/node-config-provider": "^3.1.1", - "@smithy/node-http-handler": "^3.0.1", - "@smithy/protocol-http": "^4.0.1", - "@smithy/smithy-client": "^3.1.3", - "@smithy/types": "^3.1.0", - "@smithy/url-parser": "^3.0.1", + "@smithy/config-resolver": "^3.0.3", + "@smithy/core": "^2.2.3", + "@smithy/fetch-http-handler": "^3.1.0", + "@smithy/hash-node": "^3.0.2", + "@smithy/invalid-dependency": "^3.0.2", + "@smithy/middleware-content-length": "^3.0.2", + "@smithy/middleware-retry": "^3.0.6", + "@smithy/middleware-serde": "^3.0.2", + "@smithy/middleware-stack": "^3.0.2", + "@smithy/node-config-provider": "^3.1.2", + "@smithy/node-http-handler": "^3.1.0", + "@smithy/protocol-http": "^4.0.2", + "@smithy/smithy-client": "^3.1.4", + "@smithy/types": "^3.2.0", + "@smithy/url-parser": "^3.0.2", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.5", - "@smithy/util-defaults-mode-node": "^3.0.5", - "@smithy/util-retry": "^3.0.1", + "@smithy/util-defaults-mode-browser": "^3.0.6", + "@smithy/util-defaults-mode-node": "^3.0.6", + "@smithy/util-retry": "^3.0.2", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, diff --git a/private/smithy-rpcv2-cbor/src/protocols/Rpcv2cbor.ts b/private/smithy-rpcv2-cbor/src/protocols/Rpcv2cbor.ts index da49c70b727..dc9e88eccd5 100644 --- a/private/smithy-rpcv2-cbor/src/protocols/Rpcv2cbor.ts +++ b/private/smithy-rpcv2-cbor/src/protocols/Rpcv2cbor.ts @@ -54,6 +54,7 @@ import { import { dateToTag as __dateToTag, cbor, + checkCborResponse as cr, loadSmithyRpcV2CborErrorCode, parseCborBody as parseBody, parseCborErrorBody as parseErrorBody, @@ -277,9 +278,11 @@ export const de_EmptyInputOutputCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = _json(data); @@ -297,9 +300,11 @@ export const de_FractionalSecondsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_FractionalSecondsOutput(data, context); @@ -317,9 +322,11 @@ export const de_GreetingWithErrorsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = _json(data); @@ -337,9 +344,11 @@ export const de_NoInputOutputCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + await collectBody(output.body, context); const response: NoInputOutputCommandOutput = { $metadata: deserializeMetadata(output), @@ -354,9 +363,11 @@ export const de_OperationWithDefaultsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_OperationWithDefaultsOutput(data, context); @@ -374,9 +385,11 @@ export const de_OptionalInputOutputCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = _json(data); @@ -394,9 +407,11 @@ export const de_RecursiveShapesCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_RecursiveShapesInputOutput(data, context); @@ -414,9 +429,11 @@ export const de_RpcV2CborDenseMapsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = _json(data); @@ -434,9 +451,11 @@ export const de_RpcV2CborListsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_RpcV2CborListInputOutput(data, context); @@ -454,9 +473,11 @@ export const de_RpcV2CborSparseMapsCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_RpcV2CborSparseMapsInputOutput(data, context); @@ -474,9 +495,11 @@ export const de_SimpleScalarPropertiesCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_SimpleScalarStructure(data, context); @@ -494,9 +517,11 @@ export const de_SparseNullsOperationCommand = async ( output: __HttpResponse, context: __SerdeContext ): Promise => { + cr(output); if (output.statusCode >= 300) { return de_CommandError(output, context); } + const data: any = await parseBody(output.body, context); let contents: any = {}; contents = de_SparseNullsOperationInputOutput(data, context); diff --git a/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts b/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts index d319bf8a7ee..59dcf750599 100644 --- a/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts +++ b/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts @@ -64,7 +64,7 @@ class ResponseDeserializationTestHandler implements HttpHandler { body = ""; } this.body = body; - this.isBase64Body = Buffer.from(String(body), "base64").toString("base64") === body; + this.isBase64Body = String(body).length > 0 && Buffer.from(String(body), "base64").toString("base64") === body; } handle(request: HttpRequest, options?: HttpHandlerOptions): Promise<{ response: HttpResponse }> { @@ -201,13 +201,15 @@ function normalizeByteArrayType(data: any) { if (!data || typeof data !== "object") { return data; } + if (data instanceof Uint8Array) { + return Uint8Array.from(data); + } + if (data instanceof String || data instanceof Boolean || data instanceof Number) { + return data.valueOf(); + } const output = {} as any; for (const key of Object.getOwnPropertyNames(data)) { - if (data[key] instanceof Uint8Array) { - output[key] = Uint8Array.from(data[key]); - } else { - output[key] = normalizeByteArrayType(data[key]); - } + output[key] = normalizeByteArrayType(data[key]); } return output; } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/protocols/cbor/SmithyRpcV2Cbor.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/protocols/cbor/SmithyRpcV2Cbor.java index d966550bfaf..e60209ff71a 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/protocols/cbor/SmithyRpcV2Cbor.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/protocols/cbor/SmithyRpcV2Cbor.java @@ -7,6 +7,8 @@ import java.util.Set; import java.util.TreeSet; +import software.amazon.smithy.codegen.core.Symbol; +import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.codegen.core.SymbolReference; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.OperationShape; @@ -16,6 +18,7 @@ import software.amazon.smithy.model.shapes.StructureShape; import software.amazon.smithy.model.traits.TimestampFormatTrait; import software.amazon.smithy.protocol.traits.Rpcv2CborTrait; +import software.amazon.smithy.typescript.codegen.CodegenUtils; import software.amazon.smithy.typescript.codegen.SmithyCoreSubmodules; import software.amazon.smithy.typescript.codegen.TypeScriptDependency; import software.amazon.smithy.typescript.codegen.TypeScriptSettings; @@ -23,6 +26,7 @@ import software.amazon.smithy.typescript.codegen.integration.EventStreamGenerator; import software.amazon.smithy.typescript.codegen.integration.HttpProtocolGeneratorUtils; import software.amazon.smithy.typescript.codegen.integration.HttpRpcProtocolGenerator; +import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; import software.amazon.smithy.typescript.codegen.knowledge.SerdeElisionIndex; import software.amazon.smithy.typescript.codegen.protocols.SmithyProtocolUtils; import software.amazon.smithy.utils.SmithyInternalApi; @@ -177,6 +181,60 @@ protected void generateDocumentBodyShapeDeserializers(GenerationContext generati ); } + @Override + protected void generateOperationDeserializer(GenerationContext context, OperationShape operation) { + SymbolProvider symbolProvider = context.getSymbolProvider(); + Symbol symbol = symbolProvider.toSymbol(operation); + SymbolReference responseType = getApplicationProtocol().getResponseType(); + TypeScriptWriter writer = context.getWriter(); + + writer.addUseImports(responseType); + String methodName = ProtocolGenerator.getDeserFunctionShortName(symbol); + String methodLongName = ProtocolGenerator.getDeserFunctionName(symbol, getName()); + String errorMethodName = "de_CommandError"; + String serdeContextType = CodegenUtils.getOperationDeserializerContextType(context.getSettings(), writer, + context.getModel(), operation); + Symbol outputType = symbol.expectProperty("outputType", Symbol.class); + + writer.writeDocs(methodLongName); + writer.openBlock(""" + export const $L = async( + output: $T, + context: $L + ): Promise<$T> => {""", "}", + methodName, responseType, serdeContextType, outputType, + () -> { + writer.addSubPathImport( + "checkCborResponse", "cr", + TypeScriptDependency.SMITHY_CORE, + SmithyCoreSubmodules.CBOR + ); + writer.write("cr(output);"); + + writer.write(""" + if (output.statusCode >= 300) { + return $L(output, context); + } + """, + errorMethodName + ); + + readResponseBody(context, operation); + + writer.write(""" + const response: $T = { + $$metadata: deserializeMetadata(output), $L + }; + return response; + """, + outputType, + operation.getOutput().map((o) -> "...contents,").orElse("") + ); + } + ); + writer.write(""); + } + @Override protected String getOperationPath(GenerationContext generationContext, OperationShape operationShape) { // TODO(cbor) what is the prefix? diff --git a/yarn.lock b/yarn.lock index 1dc9b11d645..e5133f2d0aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2250,7 +2250,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/config-resolver@^3.0.2, @smithy/config-resolver@workspace:^, @smithy/config-resolver@workspace:packages/config-resolver": +"@smithy/config-resolver@^3.0.3, @smithy/config-resolver@workspace:^, @smithy/config-resolver@workspace:packages/config-resolver": version: 0.0.0-use.local resolution: "@smithy/config-resolver@workspace:packages/config-resolver" dependencies: @@ -2266,7 +2266,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/core@^2.2.2, @smithy/core@workspace:packages/core": +"@smithy/core@^2.2.3, @smithy/core@workspace:packages/core": version: 0.0.0-use.local resolution: "@smithy/core@workspace:packages/core" dependencies: @@ -2401,7 +2401,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/fetch-http-handler@^3.0.3, @smithy/fetch-http-handler@workspace:^, @smithy/fetch-http-handler@workspace:packages/fetch-http-handler": +"@smithy/fetch-http-handler@^3.1.0, @smithy/fetch-http-handler@workspace:^, @smithy/fetch-http-handler@workspace:packages/fetch-http-handler": version: 0.0.0-use.local resolution: "@smithy/fetch-http-handler@workspace:packages/fetch-http-handler" dependencies: @@ -2434,7 +2434,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/hash-node@^3.0.1, @smithy/hash-node@workspace:packages/hash-node": +"@smithy/hash-node@^3.0.2, @smithy/hash-node@workspace:packages/hash-node": version: 0.0.0-use.local resolution: "@smithy/hash-node@workspace:packages/hash-node" dependencies: @@ -2468,7 +2468,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/invalid-dependency@^3.0.1, @smithy/invalid-dependency@workspace:packages/invalid-dependency": +"@smithy/invalid-dependency@^3.0.2, @smithy/invalid-dependency@workspace:packages/invalid-dependency": version: 0.0.0-use.local resolution: "@smithy/invalid-dependency@workspace:packages/invalid-dependency" dependencies: @@ -2556,7 +2556,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/middleware-content-length@^3.0.1, @smithy/middleware-content-length@workspace:packages/middleware-content-length": +"@smithy/middleware-content-length@^3.0.2, @smithy/middleware-content-length@workspace:packages/middleware-content-length": version: 0.0.0-use.local resolution: "@smithy/middleware-content-length@workspace:packages/middleware-content-length" dependencies: @@ -2589,7 +2589,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/middleware-retry@^3.0.5, @smithy/middleware-retry@workspace:^, @smithy/middleware-retry@workspace:packages/middleware-retry": +"@smithy/middleware-retry@^3.0.6, @smithy/middleware-retry@workspace:^, @smithy/middleware-retry@workspace:packages/middleware-retry": version: 0.0.0-use.local resolution: "@smithy/middleware-retry@workspace:packages/middleware-retry" dependencies: @@ -2611,7 +2611,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/middleware-serde@^3.0.1, @smithy/middleware-serde@workspace:^, @smithy/middleware-serde@workspace:packages/middleware-serde": +"@smithy/middleware-serde@^3.0.2, @smithy/middleware-serde@workspace:^, @smithy/middleware-serde@workspace:packages/middleware-serde": version: 0.0.0-use.local resolution: "@smithy/middleware-serde@workspace:packages/middleware-serde" dependencies: @@ -2625,7 +2625,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/middleware-stack@^3.0.1, @smithy/middleware-stack@workspace:^, @smithy/middleware-stack@workspace:packages/middleware-stack": +"@smithy/middleware-stack@^3.0.2, @smithy/middleware-stack@workspace:^, @smithy/middleware-stack@workspace:packages/middleware-stack": version: 0.0.0-use.local resolution: "@smithy/middleware-stack@workspace:packages/middleware-stack" dependencies: @@ -2638,7 +2638,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/node-config-provider@^3.1.1, @smithy/node-config-provider@workspace:^, @smithy/node-config-provider@workspace:packages/node-config-provider": +"@smithy/node-config-provider@^3.1.2, @smithy/node-config-provider@workspace:^, @smithy/node-config-provider@workspace:packages/node-config-provider": version: 0.0.0-use.local resolution: "@smithy/node-config-provider@workspace:packages/node-config-provider" dependencies: @@ -2654,7 +2654,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/node-http-handler@^3.0.1, @smithy/node-http-handler@workspace:^, @smithy/node-http-handler@workspace:packages/node-http-handler": +"@smithy/node-http-handler@^3.1.0, @smithy/node-http-handler@workspace:^, @smithy/node-http-handler@workspace:packages/node-http-handler": version: 0.0.0-use.local resolution: "@smithy/node-http-handler@workspace:packages/node-http-handler" dependencies: @@ -2684,7 +2684,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/protocol-http@^4.0.1, @smithy/protocol-http@workspace:^, @smithy/protocol-http@workspace:packages/protocol-http": +"@smithy/protocol-http@^4.0.2, @smithy/protocol-http@workspace:^, @smithy/protocol-http@workspace:packages/protocol-http": version: 0.0.0-use.local resolution: "@smithy/protocol-http@workspace:packages/protocol-http" dependencies: @@ -2783,7 +2783,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/smithy-client@^3.1.3, @smithy/smithy-client@workspace:^, @smithy/smithy-client@workspace:packages/smithy-client": +"@smithy/smithy-client@^3.1.4, @smithy/smithy-client@workspace:^, @smithy/smithy-client@workspace:packages/smithy-client": version: 0.0.0-use.local resolution: "@smithy/smithy-client@workspace:packages/smithy-client" dependencies: @@ -2808,27 +2808,27 @@ __metadata: "@aws-crypto/sha256-browser": 5.2.0 "@aws-crypto/sha256-js": 5.2.0 "@aws-sdk/types": latest - "@smithy/config-resolver": ^3.0.2 - "@smithy/core": ^2.2.2 - "@smithy/fetch-http-handler": ^3.0.3 - "@smithy/hash-node": ^3.0.1 - "@smithy/invalid-dependency": ^3.0.1 - "@smithy/middleware-content-length": ^3.0.1 - "@smithy/middleware-retry": ^3.0.5 - "@smithy/middleware-serde": ^3.0.1 - "@smithy/middleware-stack": ^3.0.1 - "@smithy/node-config-provider": ^3.1.1 - "@smithy/node-http-handler": ^3.0.1 - "@smithy/protocol-http": ^4.0.1 - "@smithy/smithy-client": ^3.1.3 - "@smithy/types": ^3.1.0 - "@smithy/url-parser": ^3.0.1 + "@smithy/config-resolver": ^3.0.3 + "@smithy/core": ^2.2.3 + "@smithy/fetch-http-handler": ^3.1.0 + "@smithy/hash-node": ^3.0.2 + "@smithy/invalid-dependency": ^3.0.2 + "@smithy/middleware-content-length": ^3.0.2 + "@smithy/middleware-retry": ^3.0.6 + "@smithy/middleware-serde": ^3.0.2 + "@smithy/middleware-stack": ^3.0.2 + "@smithy/node-config-provider": ^3.1.2 + "@smithy/node-http-handler": ^3.1.0 + "@smithy/protocol-http": ^4.0.2 + "@smithy/smithy-client": ^3.1.4 + "@smithy/types": ^3.2.0 + "@smithy/url-parser": ^3.0.2 "@smithy/util-base64": ^3.0.0 "@smithy/util-body-length-browser": ^3.0.0 "@smithy/util-body-length-node": ^3.0.0 - "@smithy/util-defaults-mode-browser": ^3.0.5 - "@smithy/util-defaults-mode-node": ^3.0.5 - "@smithy/util-retry": ^3.0.1 + "@smithy/util-defaults-mode-browser": ^3.0.6 + "@smithy/util-defaults-mode-node": ^3.0.6 + "@smithy/util-retry": ^3.0.2 "@smithy/util-utf8": ^3.0.0 "@tsconfig/node16": 16.1.3 "@types/node": ^16.18.96 @@ -2840,7 +2840,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/types@^3.1.0, @smithy/types@workspace:^, @smithy/types@workspace:packages/types": +"@smithy/types@^3.1.0, @smithy/types@^3.2.0, @smithy/types@workspace:^, @smithy/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@smithy/types@workspace:packages/types" dependencies: @@ -2852,7 +2852,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/url-parser@^3.0.1, @smithy/url-parser@workspace:^, @smithy/url-parser@workspace:packages/url-parser": +"@smithy/url-parser@^3.0.2, @smithy/url-parser@workspace:^, @smithy/url-parser@workspace:packages/url-parser": version: 0.0.0-use.local resolution: "@smithy/url-parser@workspace:packages/url-parser" dependencies: @@ -2943,7 +2943,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/util-defaults-mode-browser@^3.0.5, @smithy/util-defaults-mode-browser@workspace:packages/util-defaults-mode-browser": +"@smithy/util-defaults-mode-browser@^3.0.6, @smithy/util-defaults-mode-browser@workspace:packages/util-defaults-mode-browser": version: 0.0.0-use.local resolution: "@smithy/util-defaults-mode-browser@workspace:packages/util-defaults-mode-browser" dependencies: @@ -2960,7 +2960,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/util-defaults-mode-node@^3.0.5, @smithy/util-defaults-mode-node@workspace:packages/util-defaults-mode-node": +"@smithy/util-defaults-mode-node@^3.0.6, @smithy/util-defaults-mode-node@workspace:packages/util-defaults-mode-node": version: 0.0.0-use.local resolution: "@smithy/util-defaults-mode-node@workspace:packages/util-defaults-mode-node" dependencies: @@ -3020,7 +3020,7 @@ __metadata: languageName: unknown linkType: soft -"@smithy/util-retry@^3.0.1, @smithy/util-retry@workspace:^, @smithy/util-retry@workspace:packages/util-retry": +"@smithy/util-retry@^3.0.2, @smithy/util-retry@workspace:^, @smithy/util-retry@workspace:packages/util-retry": version: 0.0.0-use.local resolution: "@smithy/util-retry@workspace:packages/util-retry" dependencies: