UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

1,307 lines (1,286 loc) 73.1 kB
'use strict'; 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'); 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.NormalizedSchema.of(_schema); if (ns.isUnitSchema()) { return; } const traits = ns.getMergedTraits(); if (ns.isListSchema() && !Array.isArray(value)) { return this.readSchema(ns, [value]); } if (value == null) { return value; } if (typeof value === "object") { const flat = !!traits.xmlFlattened; if (ns.isListSchema()) { const listValue = ns.getValueSchema(); const buffer = []; const sourceKey = listValue.getMergedTraits().xmlName ?? "member"; const source = flat ? value : (value[0] ?? value)[sourceKey]; if (source == null) { return buffer; } const sourceArray = Array.isArray(source) ? source : [source]; for (const v of sourceArray) { buffer.push(this.readSchema(listValue, v)); } return buffer; } const buffer = {}; if (ns.isMapSchema()) { const keyNs = ns.getKeySchema(); const memberNs = ns.getValueSchema(); let entries; if (flat) { entries = Array.isArray(value) ? value : [value]; } else { entries = Array.isArray(value.entry) ? value.entry : [value.entry]; } const keyProperty = keyNs.getMergedTraits().xmlName ?? "key"; const valueProperty = memberNs.getMergedTraits().xmlName ?? "value"; for (const entry of entries) { const key = entry[keyProperty]; const value = entry[valueProperty]; buffer[key] = this.readSchema(memberNs, value); } return buffer; } if (ns.isStructSchema()) { const union = ns.isUnionSchema(); let unionSerde; if (union) { unionSerde = new UnionSerde(value, buffer); } for (const [memberName, memberSchema] of ns.structIterator()) { const memberTraits = memberSchema.getMergedTraits(); const xmlObjectKey = !memberTraits.httpPayload ? memberSchema.getMemberTraits().xmlName ?? memberName : memberTraits.xmlName ?? memberSchema.getName(); if (union) { unionSerde.mark(xmlObjectKey); } if (value[xmlObjectKey] != null) { buffer[memberName] = this.readSchema(memberSchema, value[xmlObjectKey]); } } if (union) { unionSerde.writeUnknown(); } return buffer; } if (ns.isDocumentSchema()) { return value; } throw new Error(`@aws-sdk/core/protocols - xml deserializer unhandled schema type for ${ns.getName(true)}`); } if (ns.isListSchema()) { return []; } if (ns.isMapSchema() || ns.isStructSchema()) { return {}; } return this.stringDeserializer.read(ns, value); } parseXml(xml) { if (xml.length) { let parsedObj; try { parsedObj = xmlBuilder.parseXML(xml); } catch (e) { if (e && typeof e === "object") { Object.defineProperty(e, "$responseBodyText", { value: xml, }); } throw e; } const textNodeName = "#text"; const key = Object.keys(parsedObj)[0]; const parsedObjToReturn = parsedObj[key]; if (parsedObjToReturn[textNodeName]) { parsedObjToReturn[key] = parsedObjToReturn[textNodeName]; delete parsedObjToReturn[textNodeName]; } return smithyClient.getValueFromTextNode(parsedObjToReturn); } return {}; } } class QueryShapeSerializer extends SerdeContextConfig { settings; buffer; constructor(settings) { super(); this.settings = settings; } write(schema$1, value, prefix = "") { if (this.buffer === undefined) { this.buffer = ""; } const ns = schema.NormalizedSchema.of(schema$1); if (prefix && !prefix.endsWith(".")) { prefix += "."; } if (ns.isBlobSchema()) { if (typeof value === "string" || value instanceof Uint8Array) { this.writeKey(prefix); this.writeValue((this.serdeContext?.base64Encoder ?? utilBase64.toBase64)(value)); } } else if (ns.isBooleanSchema() || ns.isNumericSchema() || ns.isStringSchema()) { if (value != null) { this.writeKey(prefix); this.writeValue(String(value)); } else if (ns.isIdempotencyToken()) { this.writeKey(prefix); this.writeValue(serde.generateIdempotencyToken()); } } else if (ns.isBigIntegerSchema()) { if (value != null) { this.writeKey(prefix); this.writeValue(String(value)); } } else if (ns.isBigDecimalSchema()) { if (value != null) { this.writeKey(prefix); this.writeValue(value instanceof serde.NumericValue ? value.string : String(value)); } } else if (ns.isTimestampSchema()) { if (value instanceof Date) { this.writeKey(prefix); const format = protocols.determineTimestampFormat(ns, this.settings); switch (format) { case 5: this.writeValue(value.toISOString().replace(".000Z", "Z")); break; case 6: this.writeValue(smithyClient.dateToUtcString(value)); break; case 7: this.writeValue(String(value.getTime() / 1000)); break; } } } else if (ns.isDocumentSchema()) { if (Array.isArray(value)) { this.write(64 | 15, value, prefix); } else if (value instanceof Date) { this.write(4, value, prefix); } else if (value instanceof Uint8Array) { this.write(21, value, prefix); } else if (value && typeof value === "object") { this.write(128 | 15, value, prefix); } else { this.writeKey(prefix); this.writeValue(String(value)); } } else if (ns.isListSchema()) { if (Array.isArray(value)) { if (value.length === 0) { if (this.settings.serializeEmptyLists) { this.writeKey(prefix); this.writeValue(""); } } else { const member = ns.getValueSchema(); const flat = this.settings.flattenLists || ns.getMergedTraits().xmlFlattened; let i = 1; for (const item of value) { if (item == null) { continue; } const traits = member.getMergedTraits(); const suffix = this.getKey("member", traits.xmlName, traits.ec2QueryName); const key = flat ? `${prefix}${i}` : `${prefix}${suffix}.${i}`; this.write(member, item, key); ++i; } } } } else if (ns.isMapSchema()) { if (value && typeof value === "object") { const keySchema = ns.getKeySchema(); const memberSchema = ns.getValueSchema(); const flat = ns.getMergedTraits().xmlFlattened; let i = 1; for (const [k, v] of Object.entries(value)) { if (v == null) { continue; } const keyTraits = keySchema.getMergedTraits(); const keySuffix = this.getKey("key", keyTraits.xmlName, keyTraits.ec2QueryName); const key = flat ? `${prefix}${i}.${keySuffix}` : `${prefix}entry.${i}.${keySuffix}`; const valTraits = memberSchema.getMergedTraits(); const valueSuffix = this.getKey("value", valTraits.xmlName, valTraits.ec2QueryName); const valueKey = flat ? `${prefix}${i}.${valueSuffix}` : `${prefix}entry.${i}.${valueSuffix}`; this.write(keySchema, k, key); this.write(memberSchema, v, valueKey); ++i; } } } else if (ns.isStructSchema()) { if (value && typeof value === "object") { let didWriteMember = false; for (const [memberName, member] of ns.structIterator()) { if (value[memberName] == null && !member.isIdempotencyToken()) { continue; } const traits = member.getMergedTraits(); const suffix = this.getKey(memberName, traits.xmlName, traits.ec2QueryName, "struct"); const key = `${prefix}${suffix}`; this.write(member, value[memberName], key); didWriteMember = true; } if (!didWriteMember && ns.isUnionSchema()) { const { $unknown } = value; if (Array.isArray($unknown)) { const [k, v] = $unknown; const key = `${prefix}${k}`; this.write(15, v, key); } } } } else if (ns.isUnitSchema()) ; else { throw new Error(`@aws-sdk/core/protocols - QuerySerializer unrecognized schema type ${ns.getName(true)}`); } } flush() { if (this.buffer === undefined) { throw new Error("@aws-sdk/core/protocols - QuerySerializer cannot flush with nothing written to buffer."); } const str = this.buffer; delete this.buffer; return str; } getKey(memberName, xmlName, ec2QueryName, keySource) { const { ec2, capitalizeKeys } = this.settings; if (ec2 && ec2QueryName) { return ec2QueryName; } const key = xmlName ?? memberName; if (capitalizeKeys && keySource === "struct") { return key[0].toUpperCase() + key.slice(1); } return key; } writeKey(key) { if (key.endsWith(".")) { key = key.slice(0, key.length - 1); } this.buffer += `&${protocols.extendedEncodeURIComponent(key)}=`; } writeValue(value) { this.buffer += protocols.extendedEncodeURIComponent(value); } } class AwsQueryProtocol extends protocols.RpcProtocol { options; serializer; deserializer; mixin = new ProtocolLib(); constructor(options) { super({ defaultNamespace: options.defaultNamespace, }); this.options = options; const settings = { timestampFormat: { useTrait: true, default: 5, }, httpBindings: false, xmlNamespace: options.xmlNamespace, serviceNamespace: options.defaultNamespace, serializeEmptyLists: true, }; this.serializer = new QueryShapeSerializer(settings); this.deserializer = new XmlShapeDeserializer(settings); } getShapeId() { return "aws.protocols#awsQuery"; } setSerdeContext(serdeContext) { this.serializer.setSerdeContext(serdeContext); this.deserializer.setSerdeContext(serdeContext); } getPayloadCodec() { throw new Error("AWSQuery protocol has no payload codec."); } 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-www-form-urlencoded`, }); if (schema.deref(operationSchema.input) === "unit" || !request.body) { request.body = ""; } const action = operationSchema.name.split("#")[1] ?? operationSchema.name; request.body = `Action=${action}&Version=${this.options.version}` + request.body; if (request.body.endsWith("&")) { request.body = request.body.slice(-1); } return request; } async deserializeResponse(operationSchema, context, response) { const deserializer = this.deserializer; const ns = schema.NormalizedSchema.of(operationSchema.output); const dataObject = {}; if (response.statusCode >= 300) { const bytes = await protocols.collectBody(response.body, context); if (bytes.byteLength > 0) { Object.assign(dataObject, await deserializer.read(15, bytes)); } await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); } for (const header in response.headers) { const value = response.headers[header]; delete response.headers[header]; response.headers[header.toLowerCase()]