UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

1,287 lines (1,251 loc) 88.2 kB
'use strict'; var protocolHttp = require('@smithy/protocol-http'); var core = require('@smithy/core'); var propertyProvider = require('@smithy/property-provider'); var client = require('@aws-sdk/core/client'); var signatureV4 = require('@smithy/signature-v4'); var cbor = require('@smithy/core/cbor'); var schema = require('@smithy/core/schema'); var smithyClient = require('@smithy/smithy-client'); var protocols = require('@smithy/core/protocols'); var serde = require('@smithy/core/serde'); var utilBase64 = require('@smithy/util-base64'); var utilUtf8 = require('@smithy/util-utf8'); var xmlBuilder = require('@aws-sdk/xml-builder'); const state = { warningEmitted: false, }; const emitWarningIfUnsupportedVersion = (version) => { if (version && !state.warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 20) { state.warningEmitted = true; process.emitWarning(`NodeDeprecationWarning: The AWS SDK for JavaScript (v3) will no longer support Node.js ${version} in January 2026. To continue receiving updates to AWS services, bug fixes, and security updates please upgrade to a supported Node.js LTS version. More information can be found at: https://a.co/c895JFp`); } }; function setCredentialFeature(credentials, feature, value) { if (!credentials.$source) { credentials.$source = {}; } credentials.$source[feature] = value; return credentials; } function setFeature(context, feature, value) { if (!context.__aws_sdk_context) { context.__aws_sdk_context = { features: {}, }; } else if (!context.__aws_sdk_context.features) { context.__aws_sdk_context.features = {}; } context.__aws_sdk_context.features[feature] = value; } function setTokenFeature(token, feature, value) { if (!token.$source) { token.$source = {}; } token.$source[feature] = value; return token; } const getDateHeader = (response) => protocolHttp.HttpResponse.isInstance(response) ? response.headers?.date ?? response.headers?.Date : undefined; const getSkewCorrectedDate = (systemClockOffset) => new Date(Date.now() + systemClockOffset); const isClockSkewed = (clockTime, systemClockOffset) => Math.abs(getSkewCorrectedDate(systemClockOffset).getTime() - clockTime) >= 300000; const getUpdatedSystemClockOffset = (clockTime, currentSystemClockOffset) => { const clockTimeInMs = Date.parse(clockTime); if (isClockSkewed(clockTimeInMs, currentSystemClockOffset)) { return clockTimeInMs - Date.now(); } return currentSystemClockOffset; }; const throwSigningPropertyError = (name, property) => { if (!property) { throw new Error(`Property \`${name}\` is not resolved for AWS SDK SigV4Auth`); } return property; }; const validateSigningProperties = async (signingProperties) => { const context = throwSigningPropertyError("context", signingProperties.context); const config = throwSigningPropertyError("config", signingProperties.config); const authScheme = context.endpointV2?.properties?.authSchemes?.[0]; const signerFunction = throwSigningPropertyError("signer", config.signer); const signer = await signerFunction(authScheme); const signingRegion = signingProperties?.signingRegion; const signingRegionSet = signingProperties?.signingRegionSet; const signingName = signingProperties?.signingName; return { config, signer, signingRegion, signingRegionSet, signingName, }; }; class AwsSdkSigV4Signer { async sign(httpRequest, identity, signingProperties) { if (!protocolHttp.HttpRequest.isInstance(httpRequest)) { throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); } const validatedProps = await validateSigningProperties(signingProperties); const { config, signer } = validatedProps; let { signingRegion, signingName } = validatedProps; const handlerExecutionContext = signingProperties.context; if (handlerExecutionContext?.authSchemes?.length ?? 0 > 1) { const [first, second] = handlerExecutionContext.authSchemes; if (first?.name === "sigv4a" && second?.name === "sigv4") { signingRegion = second?.signingRegion ?? signingRegion; signingName = second?.signingName ?? signingName; } } const signedRequest = await signer.sign(httpRequest, { signingDate: getSkewCorrectedDate(config.systemClockOffset), signingRegion: signingRegion, signingService: signingName, }); return signedRequest; } errorHandler(signingProperties) { return (error) => { const serverTime = error.ServerTime ?? getDateHeader(error.$response); if (serverTime) { const config = throwSigningPropertyError("config", signingProperties.config); const initialSystemClockOffset = config.systemClockOffset; config.systemClockOffset = getUpdatedSystemClockOffset(serverTime, config.systemClockOffset); const clockSkewCorrected = config.systemClockOffset !== initialSystemClockOffset; if (clockSkewCorrected && error.$metadata) { error.$metadata.clockSkewCorrected = true; } } throw error; }; } successHandler(httpResponse, signingProperties) { const dateHeader = getDateHeader(httpResponse); if (dateHeader) { const config = throwSigningPropertyError("config", signingProperties.config); config.systemClockOffset = getUpdatedSystemClockOffset(dateHeader, config.systemClockOffset); } } } const AWSSDKSigV4Signer = AwsSdkSigV4Signer; class AwsSdkSigV4ASigner extends AwsSdkSigV4Signer { async sign(httpRequest, identity, signingProperties) { if (!protocolHttp.HttpRequest.isInstance(httpRequest)) { throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); } const { config, signer, signingRegion, signingRegionSet, signingName } = await validateSigningProperties(signingProperties); const configResolvedSigningRegionSet = await config.sigv4aSigningRegionSet?.(); const multiRegionOverride = (configResolvedSigningRegionSet ?? signingRegionSet ?? [signingRegion]).join(","); const signedRequest = await signer.sign(httpRequest, { signingDate: getSkewCorrectedDate(config.systemClockOffset), signingRegion: multiRegionOverride, signingService: signingName, }); return signedRequest; } } const getArrayForCommaSeparatedString = (str) => typeof str === "string" && str.length > 0 ? str.split(",").map((item) => item.trim()) : []; const getBearerTokenEnvKey = (signingName) => `AWS_BEARER_TOKEN_${signingName.replace(/[\s-]/g, "_").toUpperCase()}`; const NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY = "AWS_AUTH_SCHEME_PREFERENCE"; const NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY = "auth_scheme_preference"; const NODE_AUTH_SCHEME_PREFERENCE_OPTIONS = { environmentVariableSelector: (env, options) => { if (options?.signingName) { const bearerTokenKey = getBearerTokenEnvKey(options.signingName); if (bearerTokenKey in env) return ["httpBearerAuth"]; } if (!(NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY in env)) return undefined; return getArrayForCommaSeparatedString(env[NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY]); }, configFileSelector: (profile) => { if (!(NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY in profile)) return undefined; return getArrayForCommaSeparatedString(profile[NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY]); }, default: [], }; const resolveAwsSdkSigV4AConfig = (config) => { config.sigv4aSigningRegionSet = core.normalizeProvider(config.sigv4aSigningRegionSet); return config; }; const NODE_SIGV4A_CONFIG_OPTIONS = { environmentVariableSelector(env) { if (env.AWS_SIGV4A_SIGNING_REGION_SET) { return env.AWS_SIGV4A_SIGNING_REGION_SET.split(",").map((_) => _.trim()); } throw new propertyProvider.ProviderError("AWS_SIGV4A_SIGNING_REGION_SET not set in env.", { tryNextLink: true, }); }, configFileSelector(profile) { if (profile.sigv4a_signing_region_set) { return (profile.sigv4a_signing_region_set ?? "").split(",").map((_) => _.trim()); } throw new propertyProvider.ProviderError("sigv4a_signing_region_set not set in profile.", { tryNextLink: true, }); }, default: undefined, }; const resolveAwsSdkSigV4Config = (config) => { let inputCredentials = config.credentials; let isUserSupplied = !!config.credentials; let resolvedCredentials = undefined; Object.defineProperty(config, "credentials", { set(credentials) { if (credentials && credentials !== inputCredentials && credentials !== resolvedCredentials) { isUserSupplied = true; } inputCredentials = credentials; const memoizedProvider = normalizeCredentialProvider(config, { credentials: inputCredentials, credentialDefaultProvider: config.credentialDefaultProvider, }); const boundProvider = bindCallerConfig(config, memoizedProvider); if (isUserSupplied && !boundProvider.attributed) { const isCredentialObject = typeof inputCredentials === "object" && inputCredentials !== null; resolvedCredentials = async (options) => { const creds = await boundProvider(options); const attributedCreds = creds; if (isCredentialObject && (!attributedCreds.$source || Object.keys(attributedCreds.$source).length === 0)) { return client.setCredentialFeature(attributedCreds, "CREDENTIALS_CODE", "e"); } return attributedCreds; }; resolvedCredentials.memoized = boundProvider.memoized; resolvedCredentials.configBound = boundProvider.configBound; resolvedCredentials.attributed = true; } else { resolvedCredentials = boundProvider; } }, get() { return resolvedCredentials; }, enumerable: true, configurable: true, }); config.credentials = inputCredentials; const { signingEscapePath = true, systemClockOffset = config.systemClockOffset || 0, sha256, } = config; let signer; if (config.signer) { signer = core.normalizeProvider(config.signer); } else if (config.regionInfoProvider) { signer = () => core.normalizeProvider(config.region)() .then(async (region) => [ (await config.regionInfoProvider(region, { useFipsEndpoint: await config.useFipsEndpoint(), useDualstackEndpoint: await config.useDualstackEndpoint(), })) || {}, region, ]) .then(([regionInfo, region]) => { const { signingRegion, signingService } = regionInfo; config.signingRegion = config.signingRegion || signingRegion || region; config.signingName = config.signingName || signingService || config.serviceId; const params = { ...config, credentials: config.credentials, region: config.signingRegion, service: config.signingName, sha256, uriEscapePath: signingEscapePath, }; const SignerCtor = config.signerConstructor || signatureV4.SignatureV4; return new SignerCtor(params); }); } else { signer = async (authScheme) => { authScheme = Object.assign({}, { name: "sigv4", signingName: config.signingName || config.defaultSigningName, signingRegion: await core.normalizeProvider(config.region)(), properties: {}, }, authScheme); const signingRegion = authScheme.signingRegion; const signingService = authScheme.signingName; config.signingRegion = config.signingRegion || signingRegion; config.signingName = config.signingName || signingService || config.serviceId; const params = { ...config, credentials: config.credentials, region: config.signingRegion, service: config.signingName, sha256, uriEscapePath: signingEscapePath, }; const SignerCtor = config.signerConstructor || signatureV4.SignatureV4; return new SignerCtor(params); }; } const resolvedConfig = Object.assign(config, { systemClockOffset, signingEscapePath, signer, }); return resolvedConfig; }; const resolveAWSSDKSigV4Config = resolveAwsSdkSigV4Config; function normalizeCredentialProvider(config, { credentials, credentialDefaultProvider, }) { let credentialsProvider; if (credentials) { if (!credentials?.memoized) { credentialsProvider = core.memoizeIdentityProvider(credentials, core.isIdentityExpired, core.doesIdentityRequireRefresh); } else { credentialsProvider = credentials; } } else { if (credentialDefaultProvider) { credentialsProvider = core.normalizeProvider(credentialDefaultProvider(Object.assign({}, config, { parentClientConfig: config, }))); } else { credentialsProvider = async () => { throw new Error("@aws-sdk/core::resolveAwsSdkSigV4Config - `credentials` not provided and no credentialDefaultProvider was configured."); }; } } credentialsProvider.memoized = true; return credentialsProvider; } function bindCallerConfig(config, credentialsProvider) { if (credentialsProvider.configBound) { return credentialsProvider; } const fn = async (options) => credentialsProvider({ ...options, callerClientConfig: config }); fn.memoized = credentialsProvider.memoized; fn.configBound = true; return fn; } class ProtocolLib { queryCompat; constructor(queryCompat = false) { this.queryCompat = queryCompat; } resolveRestContentType(defaultContentType, inputSchema) { const members = inputSchema.getMemberSchemas(); const httpPayloadMember = Object.values(members).find((m) => { return !!m.getMergedTraits().httpPayload; }); if (httpPayloadMember) { const mediaType = httpPayloadMember.getMergedTraits().mediaType; if (mediaType) { return mediaType; } else if (httpPayloadMember.isStringSchema()) { return "text/plain"; } else if (httpPayloadMember.isBlobSchema()) { return "application/octet-stream"; } else { return defaultContentType; } } else if (!inputSchema.isUnitSchema()) { const hasBody = Object.values(members).find((m) => { const { httpQuery, httpQueryParams, httpHeader, httpLabel, httpPrefixHeaders } = m.getMergedTraits(); const noPrefixHeaders = httpPrefixHeaders === void 0; return !httpQuery && !httpQueryParams && !httpHeader && !httpLabel && noPrefixHeaders; }); if (hasBody) { return defaultContentType; } } } async getErrorSchemaOrThrowBaseException(errorIdentifier, defaultNamespace, response, dataObject, metadata, getErrorSchema) { let namespace = defaultNamespace; let errorName = errorIdentifier; if (errorIdentifier.includes("#")) { [namespace, errorName] = errorIdentifier.split("#"); } const errorMetadata = { $metadata: metadata, $fault: response.statusCode < 500 ? "client" : "server", }; const registry = schema.TypeRegistry.for(namespace); try { const errorSchema = getErrorSchema?.(registry, errorName) ?? registry.getSchema(errorIdentifier); return { errorSchema, errorMetadata }; } catch (e) { dataObject.message = dataObject.message ?? dataObject.Message ?? "UnknownError"; const synthetic = schema.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace); const baseExceptionSchema = synthetic.getBaseException(); if (baseExceptionSchema) { const ErrorCtor = synthetic.getErrorCtor(baseExceptionSchema) ?? Error; throw this.decorateServiceException(Object.assign(new ErrorCtor({ name: errorName }), errorMetadata), dataObject); } throw this.decorateServiceException(Object.assign(new Error(errorName), errorMetadata), dataObject); } } decorateServiceException(exception, additions = {}) { if (this.queryCompat) { const msg = exception.Message ?? additions.Message; const error = smithyClient.decorateServiceException(exception, additions); if (msg) { error.message = msg; } error.Error = { ...error.Error, Type: error.Error?.Type, Code: error.Error?.Code, Message: error.Error?.message ?? error.Error?.Message ?? msg, }; const reqId = error.$metadata.requestId; if (reqId) { error.RequestId = reqId; } return error; } return smithyClient.decorateServiceException(exception, additions); } setQueryCompatError(output, response) { const queryErrorHeader = response.headers?.["x-amzn-query-error"]; if (output !== undefined && queryErrorHeader != null) { const [Code, Type] = queryErrorHeader.split(";"); const entries = Object.entries(output); const Error = { Code, Type, }; Object.assign(output, Error); for (const [k, v] of entries) { Error[k === "message" ? "Message" : k] = v; } delete Error.__type; output.Error = Error; } } queryCompatOutput(queryCompatErrorData, errorData) { if (queryCompatErrorData.Error) { errorData.Error = queryCompatErrorData.Error; } if (queryCompatErrorData.Type) { errorData.Type = queryCompatErrorData.Type; } if (queryCompatErrorData.Code) { errorData.Code = queryCompatErrorData.Code; } } findQueryCompatibleError(registry, errorName) { try { return registry.getSchema(errorName); } catch (e) { return registry.find((schema$1) => schema.NormalizedSchema.of(schema$1).getMergedTraits().awsQueryError?.[0] === errorName); } } } class AwsSmithyRpcV2CborProtocol extends cbor.SmithyRpcV2CborProtocol { awsQueryCompatible; mixin; constructor({ defaultNamespace, awsQueryCompatible, }) { super({ defaultNamespace }); this.awsQueryCompatible = !!awsQueryCompatible; this.mixin = new ProtocolLib(this.awsQueryCompatible); } async serializeRequest(operationSchema, input, context) { const request = await super.serializeRequest(operationSchema, input, context); if (this.awsQueryCompatible) { request.headers["x-amzn-query-mode"] = "true"; } return request; } async handleError(operationSchema, context, response, dataObject, metadata) { if (this.awsQueryCompatible) { this.mixin.setQueryCompatError(dataObject, response); } const errorName = (() => { const compatHeader = response.headers["x-amzn-query-error"]; if (compatHeader && this.awsQueryCompatible) { return compatHeader.split(";")[0]; } return cbor.loadSmithyRpcV2CborErrorCode(response, dataObject) ?? "Unknown"; })(); const { errorSchema, errorMetadata } = await this.mixin.getErrorSchemaOrThrowBaseException(errorName, this.options.defaultNamespace, response, dataObject, metadata, this.awsQueryCompatible ? this.mixin.findQueryCompatibleError : undefined); const ns = schema.NormalizedSchema.of(errorSchema); const message = dataObject.message ?? dataObject.Message ?? "Unknown"; const ErrorCtor = schema.TypeRegistry.for(errorSchema[1]).getErrorCtor(errorSchema) ?? Error; const exception = new ErrorCtor(message); const output = {}; for (const [name, member] of ns.structIterator()) { if (dataObject[name] != null) { output[name] = this.deserializer.readValue(member, dataObject[name]); } } if (this.awsQueryCompatible) { this.mixin.queryCompatOutput(dataObject, output); } throw this.mixin.decorateServiceException(Object.assign(exception, errorMetadata, { $fault: ns.getMergedTraits().error, message, }, output), dataObject); } } const _toStr = (val) => { if (val == null) { return val; } if (typeof val === "number" || typeof val === "bigint") { const warning = new Error(`Received number ${val} where a string was expected.`); warning.name = "Warning"; console.warn(warning); return String(val); } if (typeof val === "boolean") { const warning = new Error(`Received boolean ${val} where a string was expected.`); warning.name = "Warning"; console.warn(warning); return String(val); } return val; }; const _toBool = (val) => { if (val == null) { return val; } if (typeof val === "string") { const lowercase = val.toLowerCase(); if (val !== "" && lowercase !== "false" && lowercase !== "true") { const warning = new Error(`Received string "${val}" where a boolean was expected.`); warning.name = "Warning"; console.warn(warning); } return val !== "" && lowercase !== "false"; } return val; }; const _toNum = (val) => { if (val == null) { return val; } if (typeof val === "string") { const num = Number(val); if (num.toString() !== val) { const warning = new Error(`Received string "${val}" where a number was expected.`); warning.name = "Warning"; console.warn(warning); return val; } return num; } return val; }; class SerdeContextConfig { serdeContext; setSerdeContext(serdeContext) { this.serdeContext = serdeContext; } } class UnionSerde { from; to; keys; constructor(from, to) { this.from = from; this.to = to; this.keys = new Set(Object.keys(this.from).filter((k) => k !== "__type")); } mark(key) { this.keys.delete(key); } hasUnknown() { return this.keys.size === 1 && Object.keys(this.to).length === 0; } writeUnknown() { if (this.hasUnknown()) { const k = this.keys.values().next().value; const v = this.from[k]; this.to.$unknown = [k, v]; } } } function jsonReviver(key, value, context) { if (context?.source) { const numericString = context.source; if (typeof value === "number") { if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER || numericString !== String(value)) { const isFractional = numericString.includes("."); if (isFractional) { return new serde.NumericValue(numericString, "bigDecimal"); } else { return BigInt(numericString); } } } } return value; } const collectBodyString = (streamBody, context) => smithyClient.collectBody(streamBody, context).then((body) => (context?.utf8Encoder ?? utilUtf8.toUtf8)(body)); const parseJsonBody = (streamBody, context) => collectBodyString(streamBody, context).then((encoded) => { if (encoded.length) { try { return JSON.parse(encoded); } catch (e) { if (e?.name === "SyntaxError") { Object.defineProperty(e, "$responseBodyText", { value: encoded, }); } throw e; } } return {}; }); const parseJsonErrorBody = async (errorBody, context) => { const value = await parseJsonBody(errorBody, context); value.message = value.message ?? value.Message; return value; }; const loadRestJsonErrorCode = (output, data) => { const findKey = (object, key) => Object.keys(object).find((k) => k.toLowerCase() === key.toLowerCase()); const sanitizeErrorCode = (rawValue) => { let cleanValue = rawValue; if (typeof cleanValue === "number") { cleanValue = cleanValue.toString(); } if (cleanValue.indexOf(",") >= 0) { cleanValue = cleanValue.split(",")[0]; } if (cleanValue.indexOf(":") >= 0) { cleanValue = cleanValue.split(":")[0]; } if (cleanValue.indexOf("#") >= 0) { cleanValue = cleanValue.split("#")[1]; } return cleanValue; }; const headerKey = findKey(output.headers, "x-amzn-errortype"); if (headerKey !== undefined) { return sanitizeErrorCode(output.headers[headerKey]); } if (data && typeof data === "object") { const codeKey = findKey(data, "code"); if (codeKey && data[codeKey] !== undefined) { return sanitizeErrorCode(data[codeKey]); } if (data["__type"] !== undefined) { return sanitizeErrorCode(data["__type"]); } } }; class JsonShapeDeserializer extends SerdeContextConfig { settings; constructor(settings) { super(); this.settings = settings; } async read(schema, data) { return this._read(schema, typeof data === "string" ? JSON.parse(data, jsonReviver) : await parseJsonBody(data, this.serdeContext)); } readObject(schema, data) { return this._read(schema, data); } _read(schema$1, value) { const isObject = value !== null && typeof value === "object"; const ns = schema.NormalizedSchema.of(schema$1); if (isObject) { if (ns.isStructSchema()) { const record = value; const union = ns.isUnionSchema(); const out = {}; let nameMap = void 0; const { jsonName } = this.settings; if (jsonName) { nameMap = {}; } let unionSerde; if (union) { unionSerde = new UnionSerde(record, out); } for (const [memberName, memberSchema] of ns.structIterator()) { let fromKey = memberName; if (jsonName) { fromKey = memberSchema.getMergedTraits().jsonName ?? fromKey; nameMap[fromKey] = memberName; } if (union) { unionSerde.mark(fromKey); } if (record[fromKey] != null) { out[memberName] = this._read(memberSchema, record[fromKey]); } } if (union) { unionSerde.writeUnknown(); } else if (typeof record.__type === "string") { for (const [k, v] of Object.entries(record)) { const t = jsonName ? nameMap[k] ?? k : k; if (!(t in out)) { out[t] = v; } } } return out; } if (Array.isArray(value) && ns.isListSchema()) { const listMember = ns.getValueSchema(); const out = []; for (const item of value) { out.push(this._read(listMember, item)); } return out; } if (ns.isMapSchema()) { const mapMember = ns.getValueSchema(); const out = {}; for (const [_k, _v] of Object.entries(value)) { out[_k] = this._read(mapMember, _v); } return out; } } if (ns.isBlobSchema() && typeof value === "string") { return utilBase64.fromBase64(value); } const mediaType = ns.getMergedTraits().mediaType; if (ns.isStringSchema() && typeof value === "string" && mediaType) { const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); if (isJson) { return serde.LazyJsonString.from(value); } return value; } if (ns.isTimestampSchema() && value != null) { const format = protocols.determineTimestampFormat(ns, this.settings); switch (format) { case 5: return serde.parseRfc3339DateTimeWithOffset(value); case 6: return serde.parseRfc7231DateTime(value); case 7: return serde.parseEpochTimestamp(value); default: console.warn("Missing timestamp format, parsing value with Date constructor:", value); return new Date(value); } } if (ns.isBigIntegerSchema() && (typeof value === "number" || typeof value === "string")) { return BigInt(value); } if (ns.isBigDecimalSchema() && value != undefined) { if (value instanceof serde.NumericValue) { return value; } const untyped = value; if (untyped.type === "bigDecimal" && "string" in untyped) { return new serde.NumericValue(untyped.string, untyped.type); } return new serde.NumericValue(String(value), "bigDecimal"); } if (ns.isNumericSchema() && typeof value === "string") { switch (value) { case "Infinity": return Infinity; case "-Infinity": return -Infinity; case "NaN": return NaN; } return value; } if (ns.isDocumentSchema()) { if (isObject) { const out = Array.isArray(value) ? [] : {}; for (const [k, v] of Object.entries(value)) { if (v instanceof serde.NumericValue) { out[k] = v; } else { out[k] = this._read(ns, v); } } return out; } else { return structuredClone(value); } } return value; } } const NUMERIC_CONTROL_CHAR = String.fromCharCode(925); class JsonReplacer { values = new Map(); counter = 0; stage = 0; createReplacer() { if (this.stage === 1) { throw new Error("@aws-sdk/core/protocols - JsonReplacer already created."); } if (this.stage === 2) { throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); } this.stage = 1; return (key, value) => { if (value instanceof serde.NumericValue) { const v = `${NUMERIC_CONTROL_CHAR + "nv" + this.counter++}_` + value.string; this.values.set(`"${v}"`, value.string); return v; } if (typeof value === "bigint") { const s = value.toString(); const v = `${NUMERIC_CONTROL_CHAR + "b" + this.counter++}_` + s; this.values.set(`"${v}"`, s); return v; } return value; }; } replaceInJson(json) { if (this.stage === 0) { throw new Error("@aws-sdk/core/protocols - JsonReplacer not created yet."); } if (this.stage === 2) { throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); } this.stage = 2; if (this.counter === 0) { return json; } for (const [key, value] of this.values) { json = json.replace(key, value); } return json; } } class JsonShapeSerializer extends SerdeContextConfig { settings; buffer; useReplacer = false; rootSchema; constructor(settings) { super(); this.settings = settings; } write(schema$1, value) { this.rootSchema = schema.NormalizedSchema.of(schema$1); this.buffer = this._write(this.rootSchema, value); } writeDiscriminatedDocument(schema$1, value) { this.write(schema$1, value); if (typeof this.buffer === "object") { this.buffer.__type = schema.NormalizedSchema.of(schema$1).getName(true); } } flush() { const { rootSchema, useReplacer } = this; this.rootSchema = undefined; this.useReplacer = false; if (rootSchema?.isStructSchema() || rootSchema?.isDocumentSchema()) { if (!useReplacer) { return JSON.stringify(this.buffer); } const replacer = new JsonReplacer(); return replacer.replaceInJson(JSON.stringify(this.buffer, replacer.createReplacer(), 0)); } return this.buffer; } _write(schema$1, value, container) { const isObject = value !== null && typeof value === "object"; const ns = schema.NormalizedSchema.of(schema$1); if (isObject) { if (ns.isStructSchema()) { const record = value; const out = {}; const { jsonName } = this.settings; let nameMap = void 0; if (jsonName) { nameMap = {}; } for (const [memberName, memberSchema] of ns.structIterator()) { const serializableValue = this._write(memberSchema, record[memberName], ns); if (serializableValue !== undefined) { let targetKey = memberName; if (jsonName) { targetKey = memberSchema.getMergedTraits().jsonName ?? memberName; nameMap[memberName] = targetKey; } out[targetKey] = serializableValue; } } if (ns.isUnionSchema() && Object.keys(out).length === 0) { const { $unknown } = record; if (Array.isArray($unknown)) { const [k, v] = $unknown; out[k] = this._write(15, v); } } else if (typeof record.__type === "string") { for (const [k, v] of Object.entries(record)) { const targetKey = jsonName ? nameMap[k] ?? k : k; if (!(targetKey in out)) { out[targetKey] = this._write(15, v); } } } return out; } if (Array.isArray(value) && ns.isListSchema()) { const listMember = ns.getValueSchema(); const out = []; const sparse = !!ns.getMergedTraits().sparse; for (const item of value) { if (sparse || item != null) { out.push(this._write(listMember, item)); } } return out; } if (ns.isMapSchema()) { const mapMember = ns.getValueSchema(); const out = {}; const sparse = !!ns.getMergedTraits().sparse; for (const [_k, _v] of Object.entries(value)) { if (sparse || _v != null) { out[_k] = this._write(mapMember, _v); } } return out; } if (value instanceof Uint8Array && (ns.isBlobSchema() || ns.isDocumentSchema())) { if (ns === this.rootSchema) { return value; } return (this.serdeContext?.base64Encoder ?? utilBase64.toBase64)(value); } if (value instanceof Date && (ns.isTimestampSchema() || ns.isDocumentSchema())) { const format = protocols.determineTimestampFormat(ns, this.settings); switch (format) { case 5: return value.toISOString().replace(".000Z", "Z"); case 6: return serde.dateToUtcString(value); case 7: return value.getTime() / 1000; default: console.warn("Missing timestamp format, using epoch seconds", value); return value.getTime() / 1000; } } if (value instanceof serde.NumericValue) { this.useReplacer = true; } } if (value === null && container?.isStructSchema()) { return void 0; } if (ns.isStringSchema()) { if (typeof value === "undefined" && ns.isIdempotencyToken()) { return serde.generateIdempotencyToken(); } const mediaType = ns.getMergedTraits().mediaType; if (value != null && mediaType) { const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); if (isJson) { return serde.LazyJsonString.from(value); } } return value; } if (typeof value === "number" && ns.isNumericSchema()) { if (Math.abs(value) === Infinity || isNaN(value)) { return String(value); } return value; } if (typeof value === "string" && ns.isBlobSchema()) { if (ns === this.rootSchema) { return value; } return (this.serdeContext?.base64Encoder ?? utilBase64.toBase64)(value); } if (typeof value === "bigint") { this.useReplacer = true; } if (ns.isDocumentSchema()) { if (isObject) { const out = Array.isArray(value) ? [] : {}; for (const [k, v] of Object.entries(value)) { if (v instanceof serde.NumericValue) { this.useReplacer = true; out[k] = v; } else { out[k] = this._write(ns, v); } } return out; } else { return structuredClone(value); } } return value; } } class JsonCodec extends SerdeContextConfig { settings; constructor(settings) { super(); this.settings = settings; } createSerializer() { const serializer = new JsonShapeSerializer(this.settings); serializer.setSerdeContext(this.serdeContext); return serializer; } createDeserializer() { const deserializer = new JsonShapeDeserializer(this.settings); deserializer.setSerdeContext(this.serdeContext); return deserializer; } } class AwsJsonRpcProtocol extends protocols.RpcProtocol { serializer; deserializer; serviceTarget; codec; mixin; awsQueryCompatible; constructor({ defaultNamespace, serviceTarget, awsQueryCompatible, jsonCodec, }) { super({ defaultNamespace, }); this.serviceTarget = serviceTarget; this.codec = jsonCodec ?? new JsonCodec({ timestampFormat: { useTrait: true, default: 7, }, jsonName: false, }); this.serializer = this.codec.createSerializer(); this.deserializer = this.codec.createDeserializer(); this.awsQueryCompatible = !!awsQueryCompatible; this.mixin = new ProtocolLib(this.awsQueryCompatible); } async serializeRequest(operationSchema, input, context) { const request = await super.serializeRequest(operationSchema, input, context); if (!request.path.endsWith("/")) { request.path += "/"; } Object.assign(request.headers, { "content-type": `application/x-amz-json-${this.getJsonRpcVersion()}`, "x-amz-target": `${this.serviceTarget}.${operationSchema.name}`, }); if (this.awsQueryCompatible) { request.headers["x-amzn-query-mode"] = "true"; } if (schema.deref(operationSchema.input) === "unit" || !request.body) { request.body = "{}"; } return request; } getPayloadCodec() { return this.codec; } async handleError(operationSchema, context, response, dataObject, metadata) { if (this.awsQueryCompatible) { this.mixin.setQueryCompatError(dataObject, response); } const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; const { errorSchema, errorMetadata } = await this.mixin.getErrorSchemaOrThrowBaseException(errorIdentifier, this.options.defaultNamespace, response, dataObject, metadata, this.awsQueryCompatible ? this.mixin.findQueryCompatibleError : undefined); const ns = schema.NormalizedSchema.of(errorSchema); const message = dataObject.message ?? dataObject.Message ?? "Unknown"; const ErrorCtor = schema.TypeRegistry.for(errorSchema[1]).getErrorCtor(errorSchema) ?? Error; const exception = new ErrorCtor(message); const output = {}; for (const [name, member] of ns.structIterator()) { if (dataObject[name] != null) { output[name] = this.codec.createDeserializer().readObject(member, dataObject[name]); } } if (this.awsQueryCompatible) { this.mixin.queryCompatOutput(dataObject, output); } throw this.mixin.decorateServiceException(Object.assign(exception, errorMetadata, { $fault: ns.getMergedTraits().error, message, }, output), dataObject); } } class AwsJson1_0Protocol extends AwsJsonRpcProtocol { constructor({ defaultNamespace, serviceTarget, awsQueryCompatible, jsonCodec, }) { super({ defaultNamespace, serviceTarget, awsQueryCompatible, jsonCodec, }); } getShapeId() { return "aws.protocols#awsJson1_0"; } getJsonRpcVersion() { return "1.0"; } getDefaultContentType() { return "application/x-amz-json-1.0"; } } class AwsJson1_1Protocol extends AwsJsonRpcProtocol { constructor({ defaultNamespace, serviceTarget, awsQueryCompatible, jsonCodec, }) { super({ defaultNamespace, serviceTarget, awsQueryCompatible, jsonCodec, }); } getShapeId() { return "aws.protocols#awsJson1_1"; } getJsonRpcVersion() { return "1.1"; } getDefaultContentType() { return "application/x-amz-json-1.1"; } } class AwsRestJsonProtocol extends protocols.HttpBindingProtocol { serializer; deserializer; codec; mixin = new ProtocolLib(); constructor({ defaultNamespace }) { super({ defaultNamespace, }); const settings = { timestampFormat: { useTrait: true, default: 7, }, httpBindings: true, jsonName: true, }; this.codec = new JsonCodec(settings); this.serializer = new protocols.HttpInterceptingShapeSerializer(this.codec.createSerializer(), settings); this.deserializer = new protocols.HttpInterceptingShapeDeserializer(this.codec.createDeserializer(), settings); } getShapeId() { return "aws.protocols#restJson1"; } getPayloadCodec() { return this.codec; } setSerdeContext(serdeContext) { this.codec.setSerdeContext(serdeContext); super.setSerdeContext(serdeContext); } async serializeRequest(operationSchema, input, context) { const request = await super.serializeRequest(operationSchema, input, context); const inputSchema = schema.NormalizedSchema.of(operationSchema.input); if (!request.headers["content-type"]) { const contentType = this.mixin.resolveRestContentType(this.getDefaultContentType(), inputSchema); if (contentType) { request.headers["content-type"] = contentType; } } if (request.body == null && request.headers["content-type"] === this.getDefaultContentType()) { request.body = "{}"; } return request; } async deserializeResponse(operationSchema, context, response) { const output = await super.deserializeResponse(operationSchema, context, response); const outputSchema = schema.NormalizedSchema.of(operationSchema.output); for (const [name, member] of outputSchema.structIterator()) { if (member.getMemberTraits().httpPayload && !(name in output)) { output[name] = null; } } return output; } async handleError(operationSchema, context, response, dataObject, metadata) { const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; const { errorSchema, errorMetadata } = await this.mixin.getErrorSchemaOrThrowBaseException(errorIdentifier, this.options.defaultNamespace, response, dataObject, metadata); const ns = schema.NormalizedSchema.of(errorSchema); const message = dataObject.message ?? dataObject.Message ?? "Unknown"; const ErrorCtor = schema.TypeRegistry.for(errorSchema[1]).getErrorCtor(errorSchema) ?? Error; const exception = new ErrorCtor(message); await this.deserializeHttpMessage(errorSchema, context, response, dataObject); const output = {}; for (const [name, member] of ns.structIterator()) { const target = member.getMergedTraits().jsonName ?? name; output[name] = this.codec.createDeserializer().readObject(member, dataObject[target]); } throw this.mixin.decorateServiceException(Object.assign(exception, errorMetadata, { $fault: ns.getMergedTraits().error, message, }, output), dataObject); } getDefaultContentType() { return "application/json"; } } const awsExpectUnion = (value) => { if (value == null) { return undefined; } if (typeof value === "object" && "__type" in value) { delete value.__type; } return smithyClient.expectUnion(value); }; class XmlShapeDeserializer extends SerdeContextConfig { settings; stringDeserializer; constructor(settings) { super(); this.settings = settings; this.stringDeserializer = new protocols.FromStringShapeDeserializer(settings); } setSerdeContext(serdeContext) { this.serdeContext = serdeContext; this.stringDeserializer.setSerdeContext(serdeContext); } read(schema$1, bytes, key) { const ns = schema.NormalizedSchema.of(schema$1); const memberSchemas = ns.getMemberSchemas(); const isEventPayload = ns.isStructSchema() && ns.isMemberSchema() && !!Object.values(memberSchemas).find((memberNs) => { return !!memberNs.getMemberTraits().eventPayload; }); if (isEventPayload) { const output = {}; const memberName = Object.keys(memberSchemas)[0]; const eventMemberSchema = memberSchemas[memberName]; if (eventMemberSchema.isBlobSchema()) { output[memberName] = bytes; } else { output[memberName] = this.read(memberSchemas[memberName], bytes); } return output; } const xmlString = (this.serdeContext?.utf8Encoder ?? utilUtf8.toUtf8)(bytes); const parsedObject = this.parseXml(xmlString); return this.readSchema(schema$1, key ? parsedObject[key] : parsedObject); } readSchema(_schema, value) { const ns = schema.Norma