UEA-Prodem

This commit is contained in:
2026-06-10 12:38:42 -03:00
parent 3f33154e16
commit c41625e542
9352 changed files with 1128292 additions and 14752 deletions
+216
View File
@@ -0,0 +1,216 @@
import { SerdeContext } from "@smithy/core/protocols";
import { NormalizedSchema } from "@smithy/core/schema";
import { NumericValue, _parseEpochTimestamp, fromBase64, generateIdempotencyToken } from "@smithy/core/serde";
import { cbor } from "./cbor";
import { dateToTag } from "./parseCborBody";
export class CborCodec extends SerdeContext {
createSerializer() {
const serializer = new CborShapeSerializer();
serializer.setSerdeContext(this.serdeContext);
return serializer;
}
createDeserializer() {
const deserializer = new CborShapeDeserializer();
deserializer.setSerdeContext(this.serdeContext);
return deserializer;
}
}
export class CborShapeSerializer extends SerdeContext {
value;
write(schema, value) {
this.value = this.serialize(schema, value);
}
serialize(schema, source) {
const ns = NormalizedSchema.of(schema);
if (source == null) {
if (ns.isIdempotencyToken()) {
return generateIdempotencyToken();
}
return source;
}
if (ns.isBlobSchema()) {
if (typeof source === "string") {
return (this.serdeContext?.base64Decoder ?? fromBase64)(source);
}
return source;
}
if (ns.isTimestampSchema()) {
if (typeof source === "number" || typeof source === "bigint") {
return dateToTag(new Date((Number(source) / 1000) | 0));
}
return dateToTag(source);
}
if (typeof source === "function" || typeof source === "object") {
const sourceObject = source;
if (ns.isListSchema() && Array.isArray(sourceObject)) {
const sparse = !!ns.getMergedTraits().sparse;
const newArray = [];
let i = 0;
for (const item of sourceObject) {
const value = this.serialize(ns.getValueSchema(), item);
if (value != null || sparse) {
newArray[i++] = value;
}
}
return newArray;
}
if (sourceObject instanceof Date) {
return dateToTag(sourceObject);
}
const newObject = {};
if (ns.isMapSchema()) {
const sparse = !!ns.getMergedTraits().sparse;
for (const key in sourceObject) {
const value = this.serialize(ns.getValueSchema(), sourceObject[key]);
if (value != null || sparse) {
newObject[key] = value;
}
}
}
else if (ns.isStructSchema()) {
for (const [key, memberSchema] of ns.structIterator()) {
const value = this.serialize(memberSchema, sourceObject[key]);
if (value != null) {
newObject[key] = value;
}
}
const isUnion = ns.isUnionSchema();
if (isUnion && Array.isArray(sourceObject.$unknown)) {
const [k, v] = sourceObject.$unknown;
newObject[k] = v;
}
else if (typeof sourceObject.__type === "string") {
for (const k in sourceObject) {
if (!(k in newObject)) {
newObject[k] = this.serialize(15, sourceObject[k]);
}
}
}
}
else if (ns.isDocumentSchema()) {
for (const key in sourceObject) {
newObject[key] = this.serialize(ns.getValueSchema(), sourceObject[key]);
}
}
else if (ns.isBigDecimalSchema()) {
return sourceObject;
}
return newObject;
}
return source;
}
flush() {
const buffer = cbor.serialize(this.value);
this.value = undefined;
return buffer;
}
}
export class CborShapeDeserializer extends SerdeContext {
read(schema, bytes) {
const data = cbor.deserialize(bytes);
return this.readValue(schema, data);
}
readValue(_schema, value) {
const ns = NormalizedSchema.of(_schema);
if (ns.isTimestampSchema()) {
if (typeof value === "number") {
return _parseEpochTimestamp(value);
}
if (typeof value === "object") {
if (value.tag === 1 && "value" in value) {
return _parseEpochTimestamp(value.value);
}
}
}
if (ns.isBlobSchema()) {
if (typeof value === "string") {
return (this.serdeContext?.base64Decoder ?? fromBase64)(value);
}
return value;
}
if (typeof value === "undefined" ||
typeof value === "boolean" ||
typeof value === "number" ||
typeof value === "string" ||
typeof value === "bigint" ||
typeof value === "symbol") {
return value;
}
else if (typeof value === "object") {
if (value === null) {
return null;
}
if ("byteLength" in value) {
return value;
}
if (value instanceof Date) {
return value;
}
if (ns.isDocumentSchema()) {
return value;
}
if (ns.isListSchema()) {
const newArray = [];
const memberSchema = ns.getValueSchema();
for (const item of value) {
const itemValue = this.readValue(memberSchema, item);
newArray.push(itemValue);
}
return newArray;
}
const newObject = {};
if (ns.isMapSchema()) {
const targetSchema = ns.getValueSchema();
for (const key in value) {
const itemValue = this.readValue(targetSchema, value[key]);
newObject[key] = itemValue;
}
}
else if (ns.isStructSchema()) {
const isUnion = ns.isUnionSchema();
let keys;
if (isUnion) {
keys = new Set();
for (const k in value) {
if (k !== "__type") {
keys.add(k);
}
}
}
for (const [key, memberSchema] of ns.structIterator()) {
if (isUnion) {
keys.delete(key);
}
if (value[key] != null) {
newObject[key] = this.readValue(memberSchema, value[key]);
}
}
if (isUnion && keys?.size === 1) {
let newObjectEmpty = true;
for (const _ in newObject) {
newObjectEmpty = false;
break;
}
if (newObjectEmpty) {
const k = keys.values().next().value;
newObject.$unknown = [k, value[k]];
}
}
else if (typeof value.__type === "string") {
for (const k in value) {
if (!(k in newObject)) {
newObject[k] = value[k];
}
}
}
}
else if (value instanceof NumericValue) {
return value;
}
return newObject;
}
else {
return value;
}
}
}
@@ -0,0 +1,99 @@
import { getSmithyContext } from "@smithy/core/client";
import { RpcProtocol } from "@smithy/core/protocols";
import { NormalizedSchema, TypeRegistry, deref } from "@smithy/core/schema";
import { CborCodec } from "./CborCodec";
import { loadSmithyRpcV2CborErrorCode } from "./parseCborBody";
export class SmithyRpcV2CborProtocol extends RpcProtocol {
codec = new CborCodec();
serializer = this.codec.createSerializer();
deserializer = this.codec.createDeserializer();
constructor({ defaultNamespace, errorTypeRegistries, }) {
super({ defaultNamespace, errorTypeRegistries });
}
getShapeId() {
return "smithy.protocols#rpcv2Cbor";
}
getPayloadCodec() {
return this.codec;
}
async serializeRequest(operationSchema, input, context) {
const request = await super.serializeRequest(operationSchema, input, context);
Object.assign(request.headers, {
"content-type": this.getDefaultContentType(),
"smithy-protocol": "rpc-v2-cbor",
accept: this.getDefaultContentType(),
});
if (deref(operationSchema.input) === "unit") {
delete request.body;
delete request.headers["content-type"];
}
else {
if (!request.body) {
this.serializer.write(15, {});
request.body = this.serializer.flush();
}
try {
request.headers["content-length"] = String(request.body.byteLength);
}
catch (e) { }
}
const { service, operation } = getSmithyContext(context);
const path = `/service/${service}/operation/${operation}`;
if (request.path.endsWith("/")) {
request.path += path.slice(1);
}
else {
request.path += path;
}
return request;
}
async deserializeResponse(operationSchema, context, response) {
return super.deserializeResponse(operationSchema, context, response);
}
async handleError(operationSchema, context, response, dataObject, metadata) {
const errorName = loadSmithyRpcV2CborErrorCode(response, dataObject) ?? "Unknown";
const errorMetadata = {
$metadata: metadata,
$fault: response.statusCode <= 500 ? "client" : "server",
};
let namespace = this.options.defaultNamespace;
if (errorName.includes("#")) {
[namespace] = errorName.split("#");
}
const registry = this.compositeErrorRegistry;
const nsRegistry = TypeRegistry.for(namespace);
registry.copyFrom(nsRegistry);
let errorSchema;
try {
errorSchema = registry.getSchema(errorName);
}
catch (e) {
if (dataObject.Message) {
dataObject.message = dataObject.Message;
}
const syntheticRegistry = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace);
registry.copyFrom(syntheticRegistry);
const baseExceptionSchema = registry.getBaseException();
if (baseExceptionSchema) {
const ErrorCtor = registry.getErrorCtor(baseExceptionSchema);
throw Object.assign(new ErrorCtor({ name: errorName }), errorMetadata, dataObject);
}
throw Object.assign(new Error(errorName), errorMetadata, dataObject);
}
const ns = NormalizedSchema.of(errorSchema);
const ErrorCtor = registry.getErrorCtor(errorSchema);
const message = dataObject.message ?? dataObject.Message ?? "Unknown";
const exception = new ErrorCtor({});
const output = {};
for (const [name, member] of ns.structIterator()) {
output[name] = this.deserializer.readValue(member, dataObject[name]);
}
throw Object.assign(exception, errorMetadata, {
$fault: ns.getMergedTraits().error,
message,
}, output);
}
getDefaultContentType() {
return "application/cbor";
}
}
+37
View File
@@ -0,0 +1,37 @@
export function printBytes(bytes) {
return [...bytes].map((n) => {
const pad = (num) => ("0".repeat(8) + num.toString(2)).slice(-8);
const b = pad(n);
const [maj, min] = [b.slice(0, 3), b.slice(3)];
let dmaj = "";
switch (maj) {
case "000":
dmaj = "0 - Uint64";
break;
case "001":
dmaj = "1 - Neg Uint64";
break;
case "010":
dmaj = "2 - unstructured bytestring";
break;
case "011":
dmaj = "3 - utf8 string";
break;
case "100":
dmaj = "4 - list";
break;
case "101":
dmaj = "5 - map";
break;
case "110":
dmaj = "6 - tag";
break;
case "111":
dmaj = "7 - special";
break;
default:
dmaj = String(parseInt(maj, 2));
}
return `${maj}_${min} (${dmaj}, ${parseInt(min, 2)})`;
});
}
+425
View File
@@ -0,0 +1,425 @@
import { nv, toUtf8 } from "@smithy/core/serde";
import { alloc, extendedFloat16, extendedFloat32, extendedFloat64, extendedOneByte, majorList, majorMap, majorNegativeInt64, majorTag, majorUint64, majorUnstructuredByteString, majorUtf8String, minorIndefinite, specialFalse, specialNull, specialTrue, specialUndefined, tag, } from "./cbor-types";
const USE_TEXT_DECODER = typeof TextDecoder !== "undefined";
const USE_BUFFER = typeof Buffer !== "undefined";
let payload = alloc(0);
let dataView = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
const textDecoder = USE_TEXT_DECODER ? new TextDecoder() : null;
let _offset = 0;
export function setPayload(bytes) {
payload = bytes;
dataView = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
}
export function decode(at, to) {
if (at >= to) {
throw new Error("unexpected end of (decode) payload.");
}
const major = (payload[at] & 0b1110_0000) >> 5;
const minor = payload[at] & 0b0001_1111;
switch (major) {
case majorUint64:
case majorNegativeInt64:
case majorTag:
let unsignedInt;
let offset;
if (minor < 24) {
unsignedInt = minor;
offset = 1;
}
else {
switch (minor) {
case extendedOneByte:
case extendedFloat16:
case extendedFloat32:
case extendedFloat64:
const countLength = minorValueToArgumentLength[minor];
const countOffset = (countLength + 1);
offset = countOffset;
if (to - at < countOffset) {
throw new Error(`countLength ${countLength} greater than remaining buf len.`);
}
const countIndex = at + 1;
if (countLength === 1) {
unsignedInt = payload[countIndex];
}
else if (countLength === 2) {
unsignedInt = dataView.getUint16(countIndex);
}
else if (countLength === 4) {
unsignedInt = dataView.getUint32(countIndex);
}
else {
unsignedInt = dataView.getBigUint64(countIndex);
}
break;
default:
throw new Error(`unexpected minor value ${minor}.`);
}
}
if (major === majorUint64) {
_offset = offset;
return castBigInt(unsignedInt);
}
else if (major === majorNegativeInt64) {
let negativeInt;
if (typeof unsignedInt === "bigint") {
negativeInt = BigInt(-1) - unsignedInt;
}
else {
negativeInt = -1 - unsignedInt;
}
_offset = offset;
return castBigInt(negativeInt);
}
else {
if (minor === 2 || minor === 3) {
const length = decodeCount(at + offset, to);
let b = BigInt(0);
const start = at + offset + _offset;
for (let i = start; i < start + length; ++i) {
b = (b << BigInt(8)) | BigInt(payload[i]);
}
_offset = offset + _offset + length;
return minor === 3 ? -b - BigInt(1) : b;
}
else if (minor === 4) {
const decimalFraction = decode(at + offset, to);
const [exponent, mantissa] = decimalFraction;
const normalizer = mantissa < 0 ? -1 : 1;
const mantissaStr = "0".repeat(Math.abs(exponent) + 1) + String(BigInt(normalizer) * BigInt(mantissa));
let numericString;
const sign = mantissa < 0 ? "-" : "";
numericString =
exponent === 0
? mantissaStr
: mantissaStr.slice(0, mantissaStr.length + exponent) + "." + mantissaStr.slice(exponent);
numericString = numericString.replace(/^0+/g, "");
if (numericString === "") {
numericString = "0";
}
if (numericString[0] === ".") {
numericString = "0" + numericString;
}
numericString = sign + numericString;
_offset = offset + _offset;
return nv(numericString);
}
else {
const value = decode(at + offset, to);
const valueOffset = _offset;
_offset = offset + valueOffset;
return tag({ tag: castBigInt(unsignedInt), value });
}
}
case majorUtf8String:
case majorMap:
case majorList:
case majorUnstructuredByteString:
if (minor === minorIndefinite) {
switch (major) {
case majorUtf8String:
return decodeUtf8StringIndefinite(at, to);
case majorMap:
return decodeMapIndefinite(at, to);
case majorList:
return decodeListIndefinite(at, to);
case majorUnstructuredByteString:
return decodeUnstructuredByteStringIndefinite(at, to);
}
}
else {
switch (major) {
case majorUtf8String:
return decodeUtf8String(at, to);
case majorMap:
return decodeMap(at, to);
case majorList:
return decodeList(at, to);
case majorUnstructuredByteString:
return decodeUnstructuredByteString(at, to);
}
}
default:
return decodeSpecial(at, to);
}
}
function bytesToUtf8(bytes, at, to) {
if (USE_BUFFER && bytes.constructor?.name === "Buffer") {
return bytes.toString("utf-8", at, to);
}
if (textDecoder) {
return textDecoder.decode(bytes.subarray(at, to));
}
return toUtf8(bytes.subarray(at, to));
}
function demote(bigInteger) {
const num = Number(bigInteger);
if (num < Number.MIN_SAFE_INTEGER || Number.MAX_SAFE_INTEGER < num) {
console.warn(new Error(`@smithy/core/cbor - truncating BigInt(${bigInteger}) to ${num} with loss of precision.`));
}
return num;
}
const minorValueToArgumentLength = {
[extendedOneByte]: 1,
[extendedFloat16]: 2,
[extendedFloat32]: 4,
[extendedFloat64]: 8,
};
export function bytesToFloat16(a, b) {
const sign = a >> 7;
const exponent = (a & 0b0111_1100) >> 2;
const fraction = ((a & 0b0000_0011) << 8) | b;
const scalar = sign === 0 ? 1 : -1;
let exponentComponent;
let summation;
if (exponent === 0b00000) {
if (fraction === 0b00000_00000) {
return 0;
}
else {
exponentComponent = Math.pow(2, 1 - 15);
summation = 0;
}
}
else if (exponent === 0b11111) {
if (fraction === 0b00000_00000) {
return scalar * Infinity;
}
else {
return NaN;
}
}
else {
exponentComponent = Math.pow(2, exponent - 15);
summation = 1;
}
summation += fraction / 1024;
return scalar * (exponentComponent * summation);
}
function decodeCount(at, to) {
const minor = payload[at] & 0b0001_1111;
if (minor < 24) {
_offset = 1;
return minor;
}
if (minor === extendedOneByte ||
minor === extendedFloat16 ||
minor === extendedFloat32 ||
minor === extendedFloat64) {
const countLength = minorValueToArgumentLength[minor];
_offset = (countLength + 1);
if (to - at < _offset) {
throw new Error(`countLength ${countLength} greater than remaining buf len.`);
}
const countIndex = at + 1;
if (countLength === 1) {
return payload[countIndex];
}
else if (countLength === 2) {
return dataView.getUint16(countIndex);
}
else if (countLength === 4) {
return dataView.getUint32(countIndex);
}
return demote(dataView.getBigUint64(countIndex));
}
throw new Error(`unexpected minor value ${minor}.`);
}
function decodeUtf8String(at, to) {
const length = decodeCount(at, to);
const offset = _offset;
at += offset;
if (to - at < length) {
throw new Error(`string len ${length} greater than remaining buf len.`);
}
const value = bytesToUtf8(payload, at, at + length);
_offset = offset + length;
return value;
}
function decodeUtf8StringIndefinite(at, to) {
at += 1;
const vector = [];
for (const base = at; at < to;) {
if (payload[at] === 0b1111_1111) {
const data = alloc(vector.length);
data.set(vector, 0);
_offset = at - base + 2;
return bytesToUtf8(data, 0, data.length);
}
const major = (payload[at] & 0b1110_0000) >> 5;
const minor = payload[at] & 0b0001_1111;
if (major !== majorUtf8String) {
throw new Error(`unexpected major type ${major} in indefinite string.`);
}
if (minor === minorIndefinite) {
throw new Error("nested indefinite string.");
}
const bytes = decodeUnstructuredByteString(at, to);
const length = _offset;
at += length;
for (let i = 0; i < bytes.length; ++i) {
vector.push(bytes[i]);
}
}
throw new Error("expected break marker.");
}
function decodeUnstructuredByteString(at, to) {
const length = decodeCount(at, to);
const offset = _offset;
at += offset;
if (to - at < length) {
throw new Error(`unstructured byte string len ${length} greater than remaining buf len.`);
}
const value = payload.subarray(at, at + length);
_offset = offset + length;
return value;
}
function decodeUnstructuredByteStringIndefinite(at, to) {
at += 1;
const vector = [];
for (const base = at; at < to;) {
if (payload[at] === 0b1111_1111) {
const data = alloc(vector.length);
data.set(vector, 0);
_offset = at - base + 2;
return data;
}
const major = (payload[at] & 0b1110_0000) >> 5;
const minor = payload[at] & 0b0001_1111;
if (major !== majorUnstructuredByteString) {
throw new Error(`unexpected major type ${major} in indefinite string.`);
}
if (minor === minorIndefinite) {
throw new Error("nested indefinite string.");
}
const bytes = decodeUnstructuredByteString(at, to);
const length = _offset;
at += length;
for (let i = 0; i < bytes.length; ++i) {
vector.push(bytes[i]);
}
}
throw new Error("expected break marker.");
}
function decodeList(at, to) {
const listDataLength = decodeCount(at, to);
const offset = _offset;
at += offset;
const base = at;
const list = Array(listDataLength);
for (let i = 0; i < listDataLength; ++i) {
const item = decode(at, to);
const itemOffset = _offset;
list[i] = item;
at += itemOffset;
}
_offset = offset + (at - base);
return list;
}
function decodeListIndefinite(at, to) {
at += 1;
const list = [];
for (const base = at; at < to;) {
if (payload[at] === 0b1111_1111) {
_offset = at - base + 2;
return list;
}
const item = decode(at, to);
const n = _offset;
at += n;
list.push(item);
}
throw new Error("expected break marker.");
}
function decodeMap(at, to) {
const mapDataLength = decodeCount(at, to);
const offset = _offset;
at += offset;
const base = at;
const map = {};
for (let i = 0; i < mapDataLength; ++i) {
if (at >= to) {
throw new Error("unexpected end of map payload.");
}
const major = (payload[at] & 0b1110_0000) >> 5;
if (major !== majorUtf8String) {
throw new Error(`unexpected major type ${major} for map key at index ${at}.`);
}
const key = decode(at, to);
at += _offset;
const value = decode(at, to);
at += _offset;
map[key] = value;
}
_offset = offset + (at - base);
return map;
}
function decodeMapIndefinite(at, to) {
at += 1;
const base = at;
const map = {};
for (; at < to;) {
if (at >= to) {
throw new Error("unexpected end of map payload.");
}
if (payload[at] === 0b1111_1111) {
_offset = at - base + 2;
return map;
}
const major = (payload[at] & 0b1110_0000) >> 5;
if (major !== majorUtf8String) {
throw new Error(`unexpected major type ${major} for map key.`);
}
const key = decode(at, to);
at += _offset;
const value = decode(at, to);
at += _offset;
map[key] = value;
}
throw new Error("expected break marker.");
}
function decodeSpecial(at, to) {
const minor = payload[at] & 0b0001_1111;
switch (minor) {
case specialTrue:
case specialFalse:
_offset = 1;
return minor === specialTrue;
case specialNull:
_offset = 1;
return null;
case specialUndefined:
_offset = 1;
return null;
case extendedFloat16:
if (to - at < 3) {
throw new Error("incomplete float16 at end of buf.");
}
_offset = 3;
return bytesToFloat16(payload[at + 1], payload[at + 2]);
case extendedFloat32:
if (to - at < 5) {
throw new Error("incomplete float32 at end of buf.");
}
_offset = 5;
return dataView.getFloat32(at + 1);
case extendedFloat64:
if (to - at < 9) {
throw new Error("incomplete float64 at end of buf.");
}
_offset = 9;
return dataView.getFloat64(at + 1);
default:
throw new Error(`unexpected minor value ${minor}.`);
}
}
function castBigInt(bigInt) {
if (typeof bigInt === "number") {
return bigInt;
}
const num = Number(bigInt);
if (Number.MIN_SAFE_INTEGER <= num && num <= Number.MAX_SAFE_INTEGER) {
return num;
}
return bigInt;
}
+220
View File
@@ -0,0 +1,220 @@
import { NumericValue, fromUtf8 } from "@smithy/core/serde";
import { alloc, extendedFloat16, extendedFloat32, extendedFloat64, majorList, majorMap, majorNegativeInt64, majorSpecial, majorTag, majorUint64, majorUnstructuredByteString, majorUtf8String, specialFalse, specialNull, specialTrue, tagSymbol, } from "./cbor-types";
const USE_BUFFER = typeof Buffer !== "undefined";
const initialSize = 2048;
let data = alloc(initialSize);
let dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
let cursor = 0;
function ensureSpace(bytes) {
const remaining = data.byteLength - cursor;
if (remaining < bytes) {
if (cursor < 16_000_000) {
resize(Math.max(data.byteLength * 4, data.byteLength + bytes));
}
else {
resize(data.byteLength + bytes + 16_000_000);
}
}
}
export function toUint8Array() {
const out = alloc(cursor);
out.set(data.subarray(0, cursor), 0);
cursor = 0;
return out;
}
export function resize(size) {
const old = data;
data = alloc(size);
if (old) {
if (old.copy) {
old.copy(data, 0, 0, old.byteLength);
}
else {
data.set(old, 0);
}
}
dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
}
function encodeHeader(major, value) {
if (value < 24) {
data[cursor++] = (major << 5) | value;
}
else if (value < 1 << 8) {
data[cursor++] = (major << 5) | 24;
data[cursor++] = value;
}
else if (value < 1 << 16) {
data[cursor++] = (major << 5) | extendedFloat16;
dataView.setUint16(cursor, value);
cursor += 2;
}
else if (value < 2 ** 32) {
data[cursor++] = (major << 5) | extendedFloat32;
dataView.setUint32(cursor, value);
cursor += 4;
}
else {
data[cursor++] = (major << 5) | extendedFloat64;
dataView.setBigUint64(cursor, typeof value === "bigint" ? value : BigInt(value));
cursor += 8;
}
}
export function encode(_input) {
const encodeStack = [_input];
while (encodeStack.length) {
const input = encodeStack.pop();
ensureSpace(typeof input === "string" ? input.length * 4 : 64);
if (typeof input === "string") {
if (USE_BUFFER) {
encodeHeader(majorUtf8String, Buffer.byteLength(input));
cursor += data.write(input, cursor);
}
else {
const bytes = fromUtf8(input);
encodeHeader(majorUtf8String, bytes.byteLength);
data.set(bytes, cursor);
cursor += bytes.byteLength;
}
continue;
}
else if (typeof input === "number") {
if (Number.isInteger(input)) {
const nonNegative = input >= 0;
const major = nonNegative ? majorUint64 : majorNegativeInt64;
const value = nonNegative ? input : -input - 1;
if (value < 24) {
data[cursor++] = (major << 5) | value;
}
else if (value < 256) {
data[cursor++] = (major << 5) | 24;
data[cursor++] = value;
}
else if (value < 65536) {
data[cursor++] = (major << 5) | extendedFloat16;
data[cursor++] = value >> 8;
data[cursor++] = value;
}
else if (value < 4294967296) {
data[cursor++] = (major << 5) | extendedFloat32;
dataView.setUint32(cursor, value);
cursor += 4;
}
else {
data[cursor++] = (major << 5) | extendedFloat64;
dataView.setBigUint64(cursor, BigInt(value));
cursor += 8;
}
continue;
}
data[cursor++] = (majorSpecial << 5) | extendedFloat64;
dataView.setFloat64(cursor, input);
cursor += 8;
continue;
}
else if (typeof input === "bigint") {
const nonNegative = input >= 0;
const major = nonNegative ? majorUint64 : majorNegativeInt64;
const value = nonNegative ? input : -input - BigInt(1);
const n = Number(value);
if (n < 24) {
data[cursor++] = (major << 5) | n;
}
else if (n < 256) {
data[cursor++] = (major << 5) | 24;
data[cursor++] = n;
}
else if (n < 65536) {
data[cursor++] = (major << 5) | extendedFloat16;
data[cursor++] = n >> 8;
data[cursor++] = n & 0b1111_1111;
}
else if (n < 4294967296) {
data[cursor++] = (major << 5) | extendedFloat32;
dataView.setUint32(cursor, n);
cursor += 4;
}
else if (value < BigInt("18446744073709551616")) {
data[cursor++] = (major << 5) | extendedFloat64;
dataView.setBigUint64(cursor, value);
cursor += 8;
}
else {
const binaryBigInt = value.toString(2);
const bigIntBytes = new Uint8Array(Math.ceil(binaryBigInt.length / 8));
let b = value;
let i = 0;
while (bigIntBytes.byteLength - ++i >= 0) {
bigIntBytes[bigIntBytes.byteLength - i] = Number(b & BigInt(255));
b >>= BigInt(8);
}
ensureSpace(bigIntBytes.byteLength * 2);
data[cursor++] = nonNegative ? 0b110_00010 : 0b110_00011;
if (USE_BUFFER) {
encodeHeader(majorUnstructuredByteString, Buffer.byteLength(bigIntBytes));
}
else {
encodeHeader(majorUnstructuredByteString, bigIntBytes.byteLength);
}
data.set(bigIntBytes, cursor);
cursor += bigIntBytes.byteLength;
}
continue;
}
else if (input === null) {
data[cursor++] = (majorSpecial << 5) | specialNull;
continue;
}
else if (typeof input === "boolean") {
data[cursor++] = (majorSpecial << 5) | (input ? specialTrue : specialFalse);
continue;
}
else if (typeof input === "undefined") {
throw new Error("@smithy/core/cbor: client may not serialize undefined value.");
}
else if (Array.isArray(input)) {
for (let i = input.length - 1; i >= 0; --i) {
encodeStack.push(input[i]);
}
encodeHeader(majorList, input.length);
continue;
}
else if (typeof input.byteLength === "number") {
ensureSpace(input.length * 2);
encodeHeader(majorUnstructuredByteString, input.length);
data.set(input, cursor);
cursor += input.byteLength;
continue;
}
else if (typeof input === "object") {
if (input instanceof NumericValue) {
const decimalIndex = input.string.indexOf(".");
const exponent = decimalIndex === -1 ? 0 : decimalIndex - input.string.length + 1;
const mantissa = BigInt(input.string.replace(".", ""));
data[cursor++] = 0b110_00100;
encodeStack.push(mantissa);
encodeStack.push(exponent);
encodeHeader(majorList, 2);
continue;
}
if (input[tagSymbol]) {
if ("tag" in input && "value" in input) {
encodeStack.push(input.value);
encodeHeader(majorTag, input.tag);
continue;
}
else {
throw new Error("tag encountered with missing fields, need 'tag' and 'value', found: " + JSON.stringify(input));
}
}
const keys = Object.keys(input);
for (let i = keys.length - 1; i >= 0; --i) {
const key = keys[i];
encodeStack.push(input[key]);
encodeStack.push(key);
}
encodeHeader(majorMap, keys.length);
continue;
}
throw new Error(`data type ${input?.constructor?.name ?? typeof input} not compatible for encoding.`);
}
}
+25
View File
@@ -0,0 +1,25 @@
export const majorUint64 = 0;
export const majorNegativeInt64 = 1;
export const majorUnstructuredByteString = 2;
export const majorUtf8String = 3;
export const majorList = 4;
export const majorMap = 5;
export const majorTag = 6;
export const majorSpecial = 7;
export const specialFalse = 20;
export const specialTrue = 21;
export const specialNull = 22;
export const specialUndefined = 23;
export const extendedOneByte = 24;
export const extendedFloat16 = 25;
export const extendedFloat32 = 26;
export const extendedFloat64 = 27;
export const minorIndefinite = 31;
export function alloc(size) {
return typeof Buffer !== "undefined" ? Buffer.alloc(size) : new Uint8Array(size);
}
export const tagSymbol = Symbol("@smithy/core/cbor::tagSymbol");
export function tag(data) {
data[tagSymbol] = true;
return data;
}
+21
View File
@@ -0,0 +1,21 @@
import { decode, setPayload } from "./cbor-decode";
import { encode, resize, toUint8Array } from "./cbor-encode";
export const cbor = {
deserialize(payload) {
setPayload(payload);
return decode(0, payload.length);
},
serialize(input) {
try {
encode(input);
return toUint8Array();
}
catch (e) {
toUint8Array();
throw e;
}
},
resizeEncodingBuffer(size) {
resize(size);
},
};
+5
View File
@@ -0,0 +1,5 @@
export { cbor } from "./cbor";
export { tag, tagSymbol } from "./cbor-types";
export * from "./parseCborBody";
export * from "./SmithyRpcV2CborProtocol";
export * from "./CborCodec";
+97
View File
@@ -0,0 +1,97 @@
import { HttpRequest as __HttpRequest, collectBody } from "@smithy/core/protocols";
import { calculateBodyLength } from "@smithy/core/serde";
import { cbor } from "./cbor";
import { tag } from "./cbor-types";
export const parseCborBody = (streamBody, context) => {
return collectBody(streamBody, context).then(async (bytes) => {
if (bytes.length) {
try {
return cbor.deserialize(bytes);
}
catch (e) {
Object.defineProperty(e, "$responseBodyText", {
value: context.utf8Encoder(bytes),
});
throw e;
}
}
return {};
});
};
export const dateToTag = (date) => {
return tag({
tag: 1,
value: date.getTime() / 1000,
});
};
export const parseCborErrorBody = async (errorBody, context) => {
const value = await parseCborBody(errorBody, context);
value.message = value.message ?? value.Message;
return value;
};
export const loadSmithyRpcV2CborErrorCode = (output, data) => {
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;
};
if (data["__type"] !== undefined) {
return sanitizeErrorCode(data["__type"]);
}
let codeKey;
for (const key in data) {
if (key.toLowerCase() === "code") {
codeKey = key;
break;
}
}
if (codeKey && data[codeKey] !== undefined) {
return sanitizeErrorCode(data[codeKey]);
}
};
export const checkCborResponse = (response) => {
if (String(response.headers["smithy-protocol"]).toLowerCase() !== "rpc-v2-cbor") {
throw new Error("Malformed RPCv2 CBOR response, status: " + response.statusCode);
}
};
export const buildHttpRpcRequest = async (context, headers, path, resolvedHostname, body) => {
const endpoint = await context.endpoint();
const { hostname, protocol = "https", port, path: basePath } = endpoint;
const contents = {
protocol,
hostname,
port,
method: "POST",
path: basePath.endsWith("/") ? basePath.slice(0, -1) + path : basePath + path,
headers: {
...headers,
},
};
if (resolvedHostname !== undefined) {
contents.hostname = resolvedHostname;
}
if (endpoint.headers) {
for (const name in endpoint.headers) {
contents.headers[name] = endpoint.headers[name];
}
}
if (body !== undefined) {
contents.body = body;
try {
contents.headers["content-length"] = String(calculateBodyLength(body));
}
catch (e) { }
}
return new __HttpRequest(contents);
};
@@ -0,0 +1,9 @@
export async function blobReader(blob, onChunk, chunkSize = 1024 * 1024) {
const size = blob.size;
let totalBytesRead = 0;
while (totalBytesRead < size) {
const slice = blob.slice(totalBytesRead, Math.min(size, totalBytesRead + chunkSize));
onChunk(new Uint8Array(await slice.arrayBuffer()));
totalBytesRead += slice.size;
}
}
@@ -0,0 +1,27 @@
import { fromBase64 } from "@smithy/core/serde";
export function blobReader(blob, onChunk, chunkSize = 1024 * 1024) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onerror = reject;
fileReader.onabort = reject;
const size = blob.size;
let totalBytesRead = 0;
const read = () => {
if (totalBytesRead >= size) {
resolve();
return;
}
fileReader.readAsDataURL(blob.slice(totalBytesRead, Math.min(size, totalBytesRead + chunkSize)));
};
fileReader.onload = (event) => {
const result = event.target.result;
const dataOffset = result.indexOf(",") + 1;
const data = result.substring(dataOffset);
const decoded = fromBase64(data);
onChunk(decoded);
totalBytesRead += decoded.byteLength;
read();
};
read();
});
}
@@ -0,0 +1,8 @@
import { blobReader } from "../chunked-blob-reader/chunked-blob-reader";
export const blobHasher = async function blobHasher(hashCtor, blob) {
const hash = new hashCtor();
await blobReader(blob, (chunk) => {
hash.update(chunk);
});
return hash.digest();
};
@@ -0,0 +1,18 @@
import { Writable } from "node:stream";
import { toUint8Array } from "@smithy/core/serde";
export class HashCalculator extends Writable {
hash;
constructor(hash, options) {
super(options);
this.hash = hash;
}
_write(chunk, encoding, callback) {
try {
this.hash.update(toUint8Array(chunk));
}
catch (err) {
return callback(err);
}
callback();
}
}
@@ -0,0 +1,24 @@
import { createReadStream } from "node:fs";
import { HashCalculator } from "./HashCalculator";
export const fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve, reject) => {
if (!isReadStream(fileStream)) {
reject(new Error("Unable to calculate hash for non-file streams."));
return;
}
const fileStreamTee = createReadStream(fileStream.path, {
start: fileStream.start,
end: fileStream.end,
});
const hash = new hashCtor();
const hashCalculator = new HashCalculator(hash);
fileStreamTee.pipe(hashCalculator);
fileStreamTee.on("error", (err) => {
hashCalculator.end();
reject(err);
});
hashCalculator.on("error", reject);
hashCalculator.on("finish", function () {
hash.digest().then(resolve).catch(reject);
});
});
const isReadStream = (stream) => typeof stream.path === "string";
@@ -0,0 +1,19 @@
import { HashCalculator } from "./HashCalculator";
export const readableStreamHasher = (hashCtor, readableStream) => {
if (readableStream.readableFlowing !== null) {
throw new Error("Unable to calculate hash for flowing readable stream");
}
const hash = new hashCtor();
const hashCalculator = new HashCalculator(hash);
readableStream.pipe(hashCalculator);
return new Promise((resolve, reject) => {
readableStream.on("error", (err) => {
hashCalculator.end();
reject(err);
});
hashCalculator.on("error", reject);
hashCalculator.on("finish", () => {
hash.digest().then(resolve).catch(reject);
});
});
};
@@ -0,0 +1,6 @@
const no = Symbol.for("node-only");
export { blobHasher } from "./hash-blob-browser/blobHasher";
export const fileStreamHasher = no;
export const readableStreamHasher = no;
export { Md5 } from "./md5-js/md5";
export { blobReader } from "./chunked-blob-reader/chunked-blob-reader";
+5
View File
@@ -0,0 +1,5 @@
export { blobHasher } from "./hash-blob-browser/blobHasher";
export { fileStreamHasher } from "./hash-stream-node/fileStreamHasher";
export { readableStreamHasher } from "./hash-stream-node/readableStreamHasher";
export { Md5 } from "./md5-js/md5";
export { blobReader } from "./chunked-blob-reader/chunked-blob-reader";
@@ -0,0 +1,6 @@
const no = Symbol.for("node-only");
export { blobHasher } from "./hash-blob-browser/blobHasher";
export const fileStreamHasher = no;
export const readableStreamHasher = no;
export { Md5 } from "./md5-js/md5";
export { blobReader } from "./chunked-blob-reader/chunked-blob-reader.native";
@@ -0,0 +1,3 @@
export const BLOCK_SIZE = 64;
export const DIGEST_LENGTH = 16;
export const INIT = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
+168
View File
@@ -0,0 +1,168 @@
import { fromUtf8 } from "@smithy/core/serde";
import { BLOCK_SIZE, DIGEST_LENGTH, INIT } from "./constants";
export class Md5 {
state;
buffer;
bufferLength;
bytesHashed;
finished;
constructor() {
this.reset();
}
update(sourceData) {
if (isEmptyData(sourceData)) {
return;
}
else if (this.finished) {
throw new Error("Attempted to update an already finished hash.");
}
const data = convertToBuffer(sourceData);
let position = 0;
let { byteLength } = data;
this.bytesHashed += byteLength;
while (byteLength > 0) {
this.buffer.setUint8(this.bufferLength++, data[position++]);
byteLength--;
if (this.bufferLength === BLOCK_SIZE) {
this.hashBuffer();
this.bufferLength = 0;
}
}
}
async digest() {
if (!this.finished) {
const { buffer, bufferLength: undecoratedLength, bytesHashed } = this;
const bitsHashed = bytesHashed * 8;
buffer.setUint8(this.bufferLength++, 0b10000000);
if (undecoratedLength % BLOCK_SIZE >= BLOCK_SIZE - 8) {
for (let i = this.bufferLength; i < BLOCK_SIZE; i++) {
buffer.setUint8(i, 0);
}
this.hashBuffer();
this.bufferLength = 0;
}
for (let i = this.bufferLength; i < BLOCK_SIZE - 8; i++) {
buffer.setUint8(i, 0);
}
buffer.setUint32(BLOCK_SIZE - 8, bitsHashed >>> 0, true);
buffer.setUint32(BLOCK_SIZE - 4, Math.floor(bitsHashed / 0x100000000), true);
this.hashBuffer();
this.finished = true;
}
const out = new DataView(new ArrayBuffer(DIGEST_LENGTH));
for (let i = 0; i < 4; i++) {
out.setUint32(i * 4, this.state[i], true);
}
return new Uint8Array(out.buffer, out.byteOffset, out.byteLength);
}
hashBuffer() {
const { buffer, state } = this;
let a = state[0], b = state[1], c = state[2], d = state[3];
a = ff(a, b, c, d, buffer.getUint32(0, true), 7, 0xd76aa478);
d = ff(d, a, b, c, buffer.getUint32(4, true), 12, 0xe8c7b756);
c = ff(c, d, a, b, buffer.getUint32(8, true), 17, 0x242070db);
b = ff(b, c, d, a, buffer.getUint32(12, true), 22, 0xc1bdceee);
a = ff(a, b, c, d, buffer.getUint32(16, true), 7, 0xf57c0faf);
d = ff(d, a, b, c, buffer.getUint32(20, true), 12, 0x4787c62a);
c = ff(c, d, a, b, buffer.getUint32(24, true), 17, 0xa8304613);
b = ff(b, c, d, a, buffer.getUint32(28, true), 22, 0xfd469501);
a = ff(a, b, c, d, buffer.getUint32(32, true), 7, 0x698098d8);
d = ff(d, a, b, c, buffer.getUint32(36, true), 12, 0x8b44f7af);
c = ff(c, d, a, b, buffer.getUint32(40, true), 17, 0xffff5bb1);
b = ff(b, c, d, a, buffer.getUint32(44, true), 22, 0x895cd7be);
a = ff(a, b, c, d, buffer.getUint32(48, true), 7, 0x6b901122);
d = ff(d, a, b, c, buffer.getUint32(52, true), 12, 0xfd987193);
c = ff(c, d, a, b, buffer.getUint32(56, true), 17, 0xa679438e);
b = ff(b, c, d, a, buffer.getUint32(60, true), 22, 0x49b40821);
a = gg(a, b, c, d, buffer.getUint32(4, true), 5, 0xf61e2562);
d = gg(d, a, b, c, buffer.getUint32(24, true), 9, 0xc040b340);
c = gg(c, d, a, b, buffer.getUint32(44, true), 14, 0x265e5a51);
b = gg(b, c, d, a, buffer.getUint32(0, true), 20, 0xe9b6c7aa);
a = gg(a, b, c, d, buffer.getUint32(20, true), 5, 0xd62f105d);
d = gg(d, a, b, c, buffer.getUint32(40, true), 9, 0x02441453);
c = gg(c, d, a, b, buffer.getUint32(60, true), 14, 0xd8a1e681);
b = gg(b, c, d, a, buffer.getUint32(16, true), 20, 0xe7d3fbc8);
a = gg(a, b, c, d, buffer.getUint32(36, true), 5, 0x21e1cde6);
d = gg(d, a, b, c, buffer.getUint32(56, true), 9, 0xc33707d6);
c = gg(c, d, a, b, buffer.getUint32(12, true), 14, 0xf4d50d87);
b = gg(b, c, d, a, buffer.getUint32(32, true), 20, 0x455a14ed);
a = gg(a, b, c, d, buffer.getUint32(52, true), 5, 0xa9e3e905);
d = gg(d, a, b, c, buffer.getUint32(8, true), 9, 0xfcefa3f8);
c = gg(c, d, a, b, buffer.getUint32(28, true), 14, 0x676f02d9);
b = gg(b, c, d, a, buffer.getUint32(48, true), 20, 0x8d2a4c8a);
a = hh(a, b, c, d, buffer.getUint32(20, true), 4, 0xfffa3942);
d = hh(d, a, b, c, buffer.getUint32(32, true), 11, 0x8771f681);
c = hh(c, d, a, b, buffer.getUint32(44, true), 16, 0x6d9d6122);
b = hh(b, c, d, a, buffer.getUint32(56, true), 23, 0xfde5380c);
a = hh(a, b, c, d, buffer.getUint32(4, true), 4, 0xa4beea44);
d = hh(d, a, b, c, buffer.getUint32(16, true), 11, 0x4bdecfa9);
c = hh(c, d, a, b, buffer.getUint32(28, true), 16, 0xf6bb4b60);
b = hh(b, c, d, a, buffer.getUint32(40, true), 23, 0xbebfbc70);
a = hh(a, b, c, d, buffer.getUint32(52, true), 4, 0x289b7ec6);
d = hh(d, a, b, c, buffer.getUint32(0, true), 11, 0xeaa127fa);
c = hh(c, d, a, b, buffer.getUint32(12, true), 16, 0xd4ef3085);
b = hh(b, c, d, a, buffer.getUint32(24, true), 23, 0x04881d05);
a = hh(a, b, c, d, buffer.getUint32(36, true), 4, 0xd9d4d039);
d = hh(d, a, b, c, buffer.getUint32(48, true), 11, 0xe6db99e5);
c = hh(c, d, a, b, buffer.getUint32(60, true), 16, 0x1fa27cf8);
b = hh(b, c, d, a, buffer.getUint32(8, true), 23, 0xc4ac5665);
a = ii(a, b, c, d, buffer.getUint32(0, true), 6, 0xf4292244);
d = ii(d, a, b, c, buffer.getUint32(28, true), 10, 0x432aff97);
c = ii(c, d, a, b, buffer.getUint32(56, true), 15, 0xab9423a7);
b = ii(b, c, d, a, buffer.getUint32(20, true), 21, 0xfc93a039);
a = ii(a, b, c, d, buffer.getUint32(48, true), 6, 0x655b59c3);
d = ii(d, a, b, c, buffer.getUint32(12, true), 10, 0x8f0ccc92);
c = ii(c, d, a, b, buffer.getUint32(40, true), 15, 0xffeff47d);
b = ii(b, c, d, a, buffer.getUint32(4, true), 21, 0x85845dd1);
a = ii(a, b, c, d, buffer.getUint32(32, true), 6, 0x6fa87e4f);
d = ii(d, a, b, c, buffer.getUint32(60, true), 10, 0xfe2ce6e0);
c = ii(c, d, a, b, buffer.getUint32(24, true), 15, 0xa3014314);
b = ii(b, c, d, a, buffer.getUint32(52, true), 21, 0x4e0811a1);
a = ii(a, b, c, d, buffer.getUint32(16, true), 6, 0xf7537e82);
d = ii(d, a, b, c, buffer.getUint32(44, true), 10, 0xbd3af235);
c = ii(c, d, a, b, buffer.getUint32(8, true), 15, 0x2ad7d2bb);
b = ii(b, c, d, a, buffer.getUint32(36, true), 21, 0xeb86d391);
state[0] = (a + state[0]) & 0xffffffff;
state[1] = (b + state[1]) & 0xffffffff;
state[2] = (c + state[2]) & 0xffffffff;
state[3] = (d + state[3]) & 0xffffffff;
}
reset() {
this.state = Uint32Array.from(INIT);
this.buffer = new DataView(new ArrayBuffer(BLOCK_SIZE));
this.bufferLength = 0;
this.bytesHashed = 0;
this.finished = false;
}
}
function cmn(q, a, b, x, s, t) {
a = (((a + q) & 0xffffffff) + ((x + t) & 0xffffffff)) & 0xffffffff;
return (((a << s) | (a >>> (32 - s))) + b) & 0xffffffff;
}
function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | (~b & d), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & ~d), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | ~d), a, b, x, s, t);
}
function isEmptyData(data) {
if (typeof data === "string") {
return data.length === 0;
}
return data.byteLength === 0;
}
function convertToBuffer(data) {
if (typeof data === "string") {
return fromUtf8(data);
}
if (ArrayBuffer.isView(data)) {
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT);
}
return new Uint8Array(data);
}
+26
View File
@@ -0,0 +1,26 @@
export { constructStack } from "./middleware-stack/MiddlewareStack";
export { getSmithyContext } from "@smithy/core/transport";
export { normalizeProvider } from "@smithy/core/transport";
export { invalidFunction } from "./invalid-dependency/invalidFunction";
export { invalidProvider } from "./invalid-dependency/invalidProvider";
export { createWaiter } from "./util-waiter/createWaiter";
export { waiterServiceDefaults, WaiterState, checkExceptions, } from "./util-waiter/waiter";
export { Client } from "./smithy-client/client";
export { Command } from "./smithy-client/command";
export { SENSITIVE_STRING } from "./smithy-client/constants";
export { createAggregatedClient } from "./smithy-client/create-aggregated-client";
export { throwDefaultError, withBaseException } from "./smithy-client/default-error-handler";
export { loadConfigsForDefaultMode, } from "./smithy-client/defaults-mode";
export { emitWarningIfUnsupportedVersion } from "./smithy-client/emitWarningIfUnsupportedVersion";
export { ServiceException, decorateServiceException, } from "./smithy-client/exceptions";
export { getDefaultExtensionConfiguration, getDefaultClientConfiguration, resolveDefaultRuntimeConfig, } from "./smithy-client/extensions/defaultExtensionConfiguration";
export { AlgorithmId, getChecksumConfiguration, resolveChecksumRuntimeConfig, } from "./smithy-client/extensions/checksum";
export { getRetryConfiguration, resolveRetryRuntimeConfig, } from "./smithy-client/extensions/retry";
export { getArrayIfSingleItem } from "./smithy-client/get-array-if-single-item";
export { getValueFromTextNode } from "./smithy-client/get-value-from-text-node";
export { isSerializableHeaderValue } from "./smithy-client/is-serializable-header-value";
export { NoOpLogger } from "./smithy-client/NoOpLogger";
export { map, convertMap, take, } from "./smithy-client/object-mapping";
export { schemaLogFilter } from "./smithy-client/schemaLogFilter";
export { serializeFloat, serializeDateTime } from "./smithy-client/ser-utils";
export { _json } from "./smithy-client/serde-json";
@@ -0,0 +1,3 @@
export const invalidFunction = (message) => () => {
throw new Error(message);
};
@@ -0,0 +1 @@
export const invalidProvider = (message) => () => Promise.reject(message);
@@ -0,0 +1,281 @@
const getAllAliases = (name, aliases) => {
const _aliases = [];
if (name) {
_aliases.push(name);
}
if (aliases) {
for (const alias of aliases) {
_aliases.push(alias);
}
}
return _aliases;
};
const getMiddlewareNameWithAliases = (name, aliases) => {
return `${name || "anonymous"}${aliases && aliases.length > 0 ? ` (a.k.a. ${aliases.join(",")})` : ""}`;
};
export const constructStack = () => {
let absoluteEntries = [];
let relativeEntries = [];
let identifyOnResolve = false;
const entriesNameSet = new Set();
const sort = (entries) => entries.sort((a, b) => stepWeights[b.step] - stepWeights[a.step] ||
priorityWeights[b.priority || "normal"] - priorityWeights[a.priority || "normal"]);
const removeByName = (toRemove) => {
let isRemoved = false;
const filterCb = (entry) => {
const aliases = getAllAliases(entry.name, entry.aliases);
if (aliases.includes(toRemove)) {
isRemoved = true;
for (const alias of aliases) {
entriesNameSet.delete(alias);
}
return false;
}
return true;
};
absoluteEntries = absoluteEntries.filter(filterCb);
relativeEntries = relativeEntries.filter(filterCb);
return isRemoved;
};
const removeByReference = (toRemove) => {
let isRemoved = false;
const filterCb = (entry) => {
if (entry.middleware === toRemove) {
isRemoved = true;
for (const alias of getAllAliases(entry.name, entry.aliases)) {
entriesNameSet.delete(alias);
}
return false;
}
return true;
};
absoluteEntries = absoluteEntries.filter(filterCb);
relativeEntries = relativeEntries.filter(filterCb);
return isRemoved;
};
const cloneTo = (toStack) => {
absoluteEntries.forEach((entry) => {
toStack.add(entry.middleware, { ...entry });
});
relativeEntries.forEach((entry) => {
toStack.addRelativeTo(entry.middleware, { ...entry });
});
toStack.identifyOnResolve?.(stack.identifyOnResolve());
return toStack;
};
const expandRelativeMiddlewareList = (from) => {
const expandedMiddlewareList = [];
from.before.forEach((entry) => {
if (entry.before.length === 0 && entry.after.length === 0) {
expandedMiddlewareList.push(entry);
}
else {
expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry));
}
});
expandedMiddlewareList.push(from);
from.after.reverse().forEach((entry) => {
if (entry.before.length === 0 && entry.after.length === 0) {
expandedMiddlewareList.push(entry);
}
else {
expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry));
}
});
return expandedMiddlewareList;
};
const getMiddlewareList = (debug = false) => {
const normalizedAbsoluteEntries = [];
const normalizedRelativeEntries = [];
const normalizedEntriesNameMap = {};
absoluteEntries.forEach((entry) => {
const normalizedEntry = {
...entry,
before: [],
after: [],
};
for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) {
normalizedEntriesNameMap[alias] = normalizedEntry;
}
normalizedAbsoluteEntries.push(normalizedEntry);
});
relativeEntries.forEach((entry) => {
const normalizedEntry = {
...entry,
before: [],
after: [],
};
for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) {
normalizedEntriesNameMap[alias] = normalizedEntry;
}
normalizedRelativeEntries.push(normalizedEntry);
});
normalizedRelativeEntries.forEach((entry) => {
if (entry.toMiddleware) {
const toMiddleware = normalizedEntriesNameMap[entry.toMiddleware];
if (toMiddleware === undefined) {
if (debug) {
return;
}
throw new Error(`${entry.toMiddleware} is not found when adding ` +
`${getMiddlewareNameWithAliases(entry.name, entry.aliases)} ` +
`middleware ${entry.relation} ${entry.toMiddleware}`);
}
if (entry.relation === "after") {
toMiddleware.after.push(entry);
}
if (entry.relation === "before") {
toMiddleware.before.push(entry);
}
}
});
const mainChain = sort(normalizedAbsoluteEntries)
.map(expandRelativeMiddlewareList)
.reduce((wholeList, expandedMiddlewareList) => {
wholeList.push(...expandedMiddlewareList);
return wholeList;
}, []);
return mainChain;
};
const stack = {
add: (middleware, options = {}) => {
const { name, override, aliases: _aliases } = options;
const entry = {
step: "initialize",
priority: "normal",
middleware,
...options,
};
const aliases = getAllAliases(name, _aliases);
if (aliases.length > 0) {
if (aliases.some((alias) => entriesNameSet.has(alias))) {
if (!override)
throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`);
for (const alias of aliases) {
const toOverrideIndex = absoluteEntries.findIndex((entry) => entry.name === alias || entry.aliases?.some((a) => a === alias));
if (toOverrideIndex === -1) {
continue;
}
const toOverride = absoluteEntries[toOverrideIndex];
if (toOverride.step !== entry.step || entry.priority !== toOverride.priority) {
throw new Error(`"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware with ` +
`${toOverride.priority} priority in ${toOverride.step} step cannot ` +
`be overridden by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware with ` +
`${entry.priority} priority in ${entry.step} step.`);
}
absoluteEntries.splice(toOverrideIndex, 1);
}
}
for (const alias of aliases) {
entriesNameSet.add(alias);
}
}
absoluteEntries.push(entry);
},
addRelativeTo: (middleware, options) => {
const { name, override, aliases: _aliases } = options;
const entry = {
middleware,
...options,
};
const aliases = getAllAliases(name, _aliases);
if (aliases.length > 0) {
if (aliases.some((alias) => entriesNameSet.has(alias))) {
if (!override)
throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`);
for (const alias of aliases) {
const toOverrideIndex = relativeEntries.findIndex((entry) => entry.name === alias || entry.aliases?.some((a) => a === alias));
if (toOverrideIndex === -1) {
continue;
}
const toOverride = relativeEntries[toOverrideIndex];
if (toOverride.toMiddleware !== entry.toMiddleware || toOverride.relation !== entry.relation) {
throw new Error(`"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware ` +
`${toOverride.relation} "${toOverride.toMiddleware}" middleware cannot be overridden ` +
`by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware ${entry.relation} ` +
`"${entry.toMiddleware}" middleware.`);
}
relativeEntries.splice(toOverrideIndex, 1);
}
}
for (const alias of aliases) {
entriesNameSet.add(alias);
}
}
relativeEntries.push(entry);
},
clone: () => cloneTo(constructStack()),
use: (plugin) => {
plugin.applyToStack(stack);
},
remove: (toRemove) => {
if (typeof toRemove === "string")
return removeByName(toRemove);
else
return removeByReference(toRemove);
},
removeByTag: (toRemove) => {
let isRemoved = false;
const filterCb = (entry) => {
const { tags, name, aliases: _aliases } = entry;
if (tags && tags.includes(toRemove)) {
const aliases = getAllAliases(name, _aliases);
for (const alias of aliases) {
entriesNameSet.delete(alias);
}
isRemoved = true;
return false;
}
return true;
};
absoluteEntries = absoluteEntries.filter(filterCb);
relativeEntries = relativeEntries.filter(filterCb);
return isRemoved;
},
concat: (from) => {
const cloned = cloneTo(constructStack());
cloned.use(from);
cloned.identifyOnResolve(identifyOnResolve || cloned.identifyOnResolve() || (from.identifyOnResolve?.() ?? false));
return cloned;
},
applyToStack: cloneTo,
identify: () => {
return getMiddlewareList(true).map((mw) => {
const step = mw.step ??
mw.relation +
" " +
mw.toMiddleware;
return getMiddlewareNameWithAliases(mw.name, mw.aliases) + " - " + step;
});
},
identifyOnResolve(toggle) {
if (typeof toggle === "boolean")
identifyOnResolve = toggle;
return identifyOnResolve;
},
resolve: (handler, context) => {
for (const middleware of getMiddlewareList()
.map((entry) => entry.middleware)
.reverse()) {
handler = middleware(handler, context);
}
if (identifyOnResolve) {
console.log(stack.identify());
}
return handler;
},
};
return stack;
};
const stepWeights = {
initialize: 5,
serialize: 4,
build: 3,
finalizeRequest: 2,
deserialize: 1,
};
const priorityWeights = {
high: 3,
normal: 2,
low: 1,
};
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,7 @@
export class NoOpLogger {
trace() { }
debug() { }
info() { }
warn() { }
error() { }
}
@@ -0,0 +1,51 @@
import { constructStack } from "../middleware-stack/MiddlewareStack";
export class Client {
config;
middlewareStack = constructStack();
initConfig;
handlers;
constructor(config) {
this.config = config;
const { protocol, protocolSettings } = config;
if (protocolSettings) {
if (typeof protocol === "function") {
config.protocol = new protocol(protocolSettings);
}
}
}
send(command, optionsOrCb, cb) {
const options = typeof optionsOrCb !== "function" ? optionsOrCb : undefined;
const callback = typeof optionsOrCb === "function" ? optionsOrCb : cb;
const useHandlerCache = options === undefined && this.config.cacheMiddleware === true;
let handler;
if (useHandlerCache) {
if (!this.handlers) {
this.handlers = new WeakMap();
}
const handlers = this.handlers;
if (handlers.has(command.constructor)) {
handler = handlers.get(command.constructor);
}
else {
handler = command.resolveMiddleware(this.middlewareStack, this.config, options);
handlers.set(command.constructor, handler);
}
}
else {
delete this.handlers;
handler = command.resolveMiddleware(this.middlewareStack, this.config, options);
}
if (callback) {
handler(command)
.then((result) => callback(null, result.output), (err) => callback(err))
.catch(() => { });
}
else {
return handler(command).then((result) => result.output);
}
}
destroy() {
this.config?.requestHandler?.destroy?.();
delete this.handlers;
}
}
@@ -0,0 +1,131 @@
import { SMITHY_CONTEXT_KEY, } from "@smithy/types";
import { constructStack } from "../middleware-stack/MiddlewareStack";
import { schemaLogFilter } from "./schemaLogFilter";
export class Command {
middlewareStack = constructStack();
schema;
static classBuilder() {
return new ClassBuilder();
}
resolveMiddlewareWithContext(clientStack, configuration, options, { middlewareFn, clientName, commandName, inputFilterSensitiveLog, outputFilterSensitiveLog, smithyContext, additionalContext, CommandCtor, }) {
for (const mw of middlewareFn.bind(this)(CommandCtor, clientStack, configuration, options)) {
this.middlewareStack.use(mw);
}
const stack = clientStack.concat(this.middlewareStack);
const { logger } = configuration;
const handlerExecutionContext = {
logger,
clientName,
commandName,
inputFilterSensitiveLog,
outputFilterSensitiveLog,
[SMITHY_CONTEXT_KEY]: {
commandInstance: this,
...smithyContext,
},
...additionalContext,
};
const { requestHandler } = configuration;
let requestOptions = options ?? {};
if (smithyContext.eventStream) {
requestOptions = {
isEventStream: true,
...requestOptions,
};
}
return stack.resolve((request) => requestHandler.handle(request.request, requestOptions), handlerExecutionContext);
}
}
class ClassBuilder {
_init = () => { };
_ep = {};
_middlewareFn = () => [];
_commandName = "";
_clientName = "";
_additionalContext = {};
_smithyContext = {};
_inputFilterSensitiveLog = undefined;
_outputFilterSensitiveLog = undefined;
_serializer = null;
_deserializer = null;
_operationSchema;
init(cb) {
this._init = cb;
}
ep(endpointParameterInstructions) {
this._ep = endpointParameterInstructions;
return this;
}
m(middlewareSupplier) {
this._middlewareFn = middlewareSupplier;
return this;
}
s(service, operation, smithyContext = {}) {
this._smithyContext = {
service,
operation,
...smithyContext,
};
return this;
}
c(additionalContext = {}) {
this._additionalContext = additionalContext;
return this;
}
n(clientName, commandName) {
this._clientName = clientName;
this._commandName = commandName;
return this;
}
f(inputFilter = (_) => _, outputFilter = (_) => _) {
this._inputFilterSensitiveLog = inputFilter;
this._outputFilterSensitiveLog = outputFilter;
return this;
}
ser(serializer) {
this._serializer = serializer;
return this;
}
de(deserializer) {
this._deserializer = deserializer;
return this;
}
sc(operation) {
this._operationSchema = operation;
this._smithyContext.operationSchema = operation;
return this;
}
build() {
const closure = this;
let CommandRef;
return (CommandRef = class extends Command {
input;
static getEndpointParameterInstructions() {
return closure._ep;
}
constructor(...[input]) {
super();
this.input = input ?? {};
closure._init(this);
this.schema = closure._operationSchema;
}
resolveMiddleware(stack, configuration, options) {
const op = closure._operationSchema;
const input = op?.[4] ?? op?.input;
const output = op?.[5] ?? op?.output;
return this.resolveMiddlewareWithContext(stack, configuration, options, {
CommandCtor: CommandRef,
middlewareFn: closure._middlewareFn,
clientName: closure._clientName,
commandName: closure._commandName,
inputFilterSensitiveLog: closure._inputFilterSensitiveLog ?? (op ? schemaLogFilter.bind(null, input) : (_) => _),
outputFilterSensitiveLog: closure._outputFilterSensitiveLog ?? (op ? schemaLogFilter.bind(null, output) : (_) => _),
smithyContext: closure._smithyContext,
additionalContext: closure._additionalContext,
});
}
serialize = closure._serializer;
deserialize = closure._deserializer;
});
}
}
@@ -0,0 +1 @@
export const SENSITIVE_STRING = "***SensitiveInformation***";
@@ -0,0 +1,47 @@
export const createAggregatedClient = (commands, Client, options) => {
for (const [command, CommandCtor] of Object.entries(commands)) {
const methodImpl = async function (args, optionsOrCb, cb) {
const command = new CommandCtor(args);
if (typeof optionsOrCb === "function") {
this.send(command, optionsOrCb);
}
else if (typeof cb === "function") {
if (typeof optionsOrCb !== "object")
throw new Error(`Expected http options but got ${typeof optionsOrCb}`);
this.send(command, optionsOrCb || {}, cb);
}
else {
return this.send(command, optionsOrCb);
}
};
const methodName = (command[0].toLowerCase() + command.slice(1)).replace(/Command$/, "");
Client.prototype[methodName] = methodImpl;
}
const { paginators = {}, waiters = {} } = options ?? {};
for (const [paginatorName, paginatorFn] of Object.entries(paginators)) {
if (Client.prototype[paginatorName] === void 0) {
Client.prototype[paginatorName] = function (commandInput = {}, paginationConfiguration, ...rest) {
return paginatorFn({
...paginationConfiguration,
client: this,
}, commandInput, ...rest);
};
}
}
for (const [waiterName, waiterFn] of Object.entries(waiters)) {
if (Client.prototype[waiterName] === void 0) {
Client.prototype[waiterName] = async function (commandInput = {}, waiterConfiguration, ...rest) {
let config = waiterConfiguration;
if (typeof waiterConfiguration === "number") {
config = {
maxWaitTime: waiterConfiguration,
};
}
return waiterFn({
...config,
client: this,
}, commandInput, ...rest);
};
}
}
};
@@ -0,0 +1,22 @@
import { decorateServiceException } from "./exceptions";
export const throwDefaultError = ({ output, parsedBody, exceptionCtor, errorCode }) => {
const $metadata = deserializeMetadata(output);
const statusCode = $metadata.httpStatusCode ? $metadata.httpStatusCode + "" : undefined;
const response = new exceptionCtor({
name: parsedBody?.code || parsedBody?.Code || errorCode || statusCode || "UnknownError",
$fault: "client",
$metadata,
});
throw decorateServiceException(response, parsedBody);
};
export const withBaseException = (ExceptionCtor) => {
return ({ output, parsedBody, errorCode }) => {
throwDefaultError({ output, parsedBody, exceptionCtor: ExceptionCtor, errorCode });
};
};
const deserializeMetadata = (output) => ({
httpStatusCode: output.statusCode,
requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"],
extendedRequestId: output.headers["x-amz-id-2"],
cfId: output.headers["x-amz-cf-id"],
});
@@ -0,0 +1,26 @@
export const loadConfigsForDefaultMode = (mode) => {
switch (mode) {
case "standard":
return {
retryMode: "standard",
connectionTimeout: 3100,
};
case "in-region":
return {
retryMode: "standard",
connectionTimeout: 1100,
};
case "cross-region":
return {
retryMode: "standard",
connectionTimeout: 3100,
};
case "mobile":
return {
retryMode: "standard",
connectionTimeout: 30000,
};
default:
return {};
}
};
@@ -0,0 +1,6 @@
let warningEmitted = false;
export const emitWarningIfUnsupportedVersion = (version) => {
if (version && !warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 16) {
warningEmitted = true;
}
};
@@ -0,0 +1,50 @@
export class ServiceException extends Error {
$fault;
$response;
$retryable;
$metadata;
constructor(options) {
super(options.message);
Object.setPrototypeOf(this, Object.getPrototypeOf(this).constructor.prototype);
this.name = options.name;
this.$fault = options.$fault;
this.$metadata = options.$metadata;
}
static isInstance(value) {
if (!value)
return false;
const candidate = value;
return (ServiceException.prototype.isPrototypeOf(candidate) ||
(Boolean(candidate.$fault) &&
Boolean(candidate.$metadata) &&
(candidate.$fault === "client" || candidate.$fault === "server")));
}
static [Symbol.hasInstance](instance) {
if (!instance)
return false;
const candidate = instance;
if (this === ServiceException) {
return ServiceException.isInstance(instance);
}
if (ServiceException.isInstance(instance)) {
if (candidate.name && this.name) {
return this.prototype.isPrototypeOf(instance) || candidate.name === this.name;
}
return this.prototype.isPrototypeOf(instance);
}
return false;
}
}
export const decorateServiceException = (exception, additions = {}) => {
Object.entries(additions)
.filter(([, v]) => v !== undefined)
.forEach(([k, v]) => {
if (exception[k] == undefined || exception[k] === "") {
exception[k] = v;
}
});
const message = exception.message || exception.Message || "UnknownError";
exception.message = message;
delete exception.Message;
return exception;
};
@@ -0,0 +1,49 @@
import { AlgorithmId, } from "@smithy/types";
export { AlgorithmId };
const knownAlgorithms = Object.values(AlgorithmId);
export const getChecksumConfiguration = (runtimeConfig) => {
const checksumAlgorithms = [];
for (const id in AlgorithmId) {
const algorithmId = AlgorithmId[id];
if (runtimeConfig[algorithmId] === undefined) {
continue;
}
checksumAlgorithms.push({
algorithmId: () => algorithmId,
checksumConstructor: () => runtimeConfig[algorithmId],
});
}
for (const [id, ChecksumCtor] of Object.entries(runtimeConfig.checksumAlgorithms ?? {})) {
checksumAlgorithms.push({
algorithmId: () => id,
checksumConstructor: () => ChecksumCtor,
});
}
return {
addChecksumAlgorithm(algo) {
runtimeConfig.checksumAlgorithms = runtimeConfig.checksumAlgorithms ?? {};
const id = algo.algorithmId();
const ctor = algo.checksumConstructor();
if (knownAlgorithms.includes(id)) {
runtimeConfig.checksumAlgorithms[id.toUpperCase()] = ctor;
}
else {
runtimeConfig.checksumAlgorithms[id] = ctor;
}
checksumAlgorithms.push(algo);
},
checksumAlgorithms() {
return checksumAlgorithms;
},
};
};
export const resolveChecksumRuntimeConfig = (clientConfig) => {
const runtimeConfig = {};
clientConfig.checksumAlgorithms().forEach((checksumAlgorithm) => {
const id = checksumAlgorithm.algorithmId();
if (knownAlgorithms.includes(id)) {
runtimeConfig[id] = checksumAlgorithm.checksumConstructor();
}
});
return runtimeConfig;
};
@@ -0,0 +1,9 @@
import { getChecksumConfiguration, resolveChecksumRuntimeConfig, } from "./checksum";
import { getRetryConfiguration, resolveRetryRuntimeConfig } from "./retry";
export const getDefaultExtensionConfiguration = (runtimeConfig) => {
return Object.assign(getChecksumConfiguration(runtimeConfig), getRetryConfiguration(runtimeConfig));
};
export const getDefaultClientConfiguration = getDefaultExtensionConfiguration;
export const resolveDefaultRuntimeConfig = (config) => {
return Object.assign(resolveChecksumRuntimeConfig(config), resolveRetryRuntimeConfig(config));
};
@@ -0,0 +1,15 @@
export const getRetryConfiguration = (runtimeConfig) => {
return {
setRetryStrategy(retryStrategy) {
runtimeConfig.retryStrategy = retryStrategy;
},
retryStrategy() {
return runtimeConfig.retryStrategy;
},
};
};
export const resolveRetryRuntimeConfig = (retryStrategyConfiguration) => {
const runtimeConfig = {};
runtimeConfig.retryStrategy = retryStrategyConfiguration.retryStrategy();
return runtimeConfig;
};
@@ -0,0 +1 @@
export const getArrayIfSingleItem = (mayBeArray) => Array.isArray(mayBeArray) ? mayBeArray : [mayBeArray];
@@ -0,0 +1,12 @@
export const getValueFromTextNode = (obj) => {
const textNodeName = "#text";
for (const key in obj) {
if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== undefined) {
obj[key] = obj[key][textNodeName];
}
else if (typeof obj[key] === "object" && obj[key] !== null) {
obj[key] = getValueFromTextNode(obj[key]);
}
}
return obj;
};
@@ -0,0 +1,3 @@
export const isSerializableHeaderValue = (value) => {
return value != null;
};
@@ -0,0 +1,92 @@
export function map(arg0, arg1, arg2) {
let target;
let filter;
let instructions;
if (typeof arg1 === "undefined" && typeof arg2 === "undefined") {
target = {};
instructions = arg0;
}
else {
target = arg0;
if (typeof arg1 === "function") {
filter = arg1;
instructions = arg2;
return mapWithFilter(target, filter, instructions);
}
else {
instructions = arg1;
}
}
for (const key of Object.keys(instructions)) {
if (!Array.isArray(instructions[key])) {
target[key] = instructions[key];
continue;
}
applyInstruction(target, null, instructions, key);
}
return target;
}
export const convertMap = (target) => {
const output = {};
for (const [k, v] of Object.entries(target || {})) {
output[k] = [, v];
}
return output;
};
export const take = (source, instructions) => {
const out = {};
for (const key in instructions) {
applyInstruction(out, source, instructions, key);
}
return out;
};
const mapWithFilter = (target, filter, instructions) => {
return map(target, Object.entries(instructions).reduce((_instructions, [key, value]) => {
if (Array.isArray(value)) {
_instructions[key] = value;
}
else {
if (typeof value === "function") {
_instructions[key] = [filter, value()];
}
else {
_instructions[key] = [filter, value];
}
}
return _instructions;
}, {}));
};
const applyInstruction = (target, source, instructions, targetKey) => {
if (source !== null) {
let instruction = instructions[targetKey];
if (typeof instruction === "function") {
instruction = [, instruction];
}
const [filter = nonNullish, valueFn = pass, sourceKey = targetKey] = instruction;
if ((typeof filter === "function" && filter(source[sourceKey])) || (typeof filter !== "function" && !!filter)) {
target[targetKey] = valueFn(source[sourceKey]);
}
return;
}
let [filter, value] = instructions[targetKey];
if (typeof value === "function") {
let _value;
const defaultFilterPassed = filter === undefined && (_value = value()) != null;
const customFilterPassed = (typeof filter === "function" && !!filter(void 0)) || (typeof filter !== "function" && !!filter);
if (defaultFilterPassed) {
target[targetKey] = _value;
}
else if (customFilterPassed) {
target[targetKey] = value();
}
}
else {
const defaultFilterPassed = filter === undefined && value != null;
const customFilterPassed = (typeof filter === "function" && !!filter(value)) || (typeof filter !== "function" && !!filter);
if (defaultFilterPassed || customFilterPassed) {
target[targetKey] = value;
}
}
};
const nonNullish = (_) => _ != null;
const pass = (_) => _;
@@ -0,0 +1,34 @@
import { NormalizedSchema } from "@smithy/core/schema";
const SENSITIVE_STRING = "***SensitiveInformation***";
export function schemaLogFilter(schema, data) {
if (data == null) {
return data;
}
const ns = NormalizedSchema.of(schema);
if (ns.getMergedTraits().sensitive) {
return SENSITIVE_STRING;
}
if (ns.isListSchema()) {
const isSensitive = !!ns.getValueSchema().getMergedTraits().sensitive;
if (isSensitive) {
return SENSITIVE_STRING;
}
}
else if (ns.isMapSchema()) {
const isSensitive = !!ns.getKeySchema().getMergedTraits().sensitive || !!ns.getValueSchema().getMergedTraits().sensitive;
if (isSensitive) {
return SENSITIVE_STRING;
}
}
else if (ns.isStructSchema() && typeof data === "object") {
const object = data;
const newObject = {};
for (const [member, memberNs] of ns.structIterator()) {
if (object[member] != null) {
newObject[member] = schemaLogFilter(memberNs, object[member]);
}
}
return newObject;
}
return data;
}
@@ -0,0 +1,14 @@
export const serializeFloat = (value) => {
if (value !== value) {
return "NaN";
}
switch (value) {
case Infinity:
return "Infinity";
case -Infinity:
return "-Infinity";
default:
return value;
}
};
export const serializeDateTime = (date) => date.toISOString().replace(".000Z", "Z");
@@ -0,0 +1,19 @@
export const _json = (obj) => {
if (obj == null) {
return {};
}
if (Array.isArray(obj)) {
return obj.filter((_) => _ != null).map(_json);
}
if (typeof obj === "object") {
const target = {};
for (const key of Object.keys(obj)) {
if (obj[key] == null) {
continue;
}
target[key] = _json(obj[key]);
}
return target;
}
return obj;
};
@@ -0,0 +1,12 @@
export const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return "[Circular]";
}
seen.add(value);
}
return value;
};
};
@@ -0,0 +1,48 @@
import { runPolling } from "./poller";
import { validateWaiterOptions } from "./utils/validate";
import { WaiterState, waiterServiceDefaults } from "./waiter";
const abortTimeout = (abortSignal) => {
let onAbort;
const promise = new Promise((resolve) => {
onAbort = () => resolve({ state: WaiterState.ABORTED });
if (typeof abortSignal.addEventListener === "function") {
abortSignal.addEventListener("abort", onAbort);
}
else {
abortSignal.onabort = onAbort;
}
});
return {
clearListener() {
if (typeof abortSignal.removeEventListener === "function") {
abortSignal.removeEventListener("abort", onAbort);
}
},
aborted: promise,
};
};
export const createWaiter = async (options, input, acceptorChecks) => {
const params = {
...waiterServiceDefaults,
...options,
};
validateWaiterOptions(params);
const exitConditions = [runPolling(params, input, acceptorChecks)];
const finalize = [];
if (options.abortSignal) {
const { aborted, clearListener } = abortTimeout(options.abortSignal);
finalize.push(clearListener);
exitConditions.push(aborted);
}
if (options.abortController?.signal) {
const { aborted, clearListener } = abortTimeout(options.abortController.signal);
finalize.push(clearListener);
exitConditions.push(aborted);
}
return Promise.race(exitConditions).then((result) => {
for (const fn of finalize) {
fn();
}
return result;
});
};
@@ -0,0 +1,87 @@
import { getCircularReplacer } from "./circularReplacer";
import { sleep } from "./utils/sleep";
import { WaiterState } from "./waiter";
export const runPolling = async ({ minDelay, maxDelay, maxWaitTime, abortController, client, abortSignal }, input, acceptorChecks) => {
const observedResponses = {};
const [minDelayMs, maxDelayMs] = [minDelay * 1000, maxDelay * 1000];
let currentAttempt = 0;
const waitUntil = Date.now() + maxWaitTime * 1000;
const warn403Time = Date.now() + 60_000;
let didWarn403 = false;
while (true) {
if (currentAttempt > 0) {
const delayMs = exponentialBackoffWithJitter(minDelayMs, maxDelayMs, currentAttempt, waitUntil);
if (abortController?.signal?.aborted || abortSignal?.aborted) {
const message = "AbortController signal aborted.";
observedResponses[message] |= 0;
observedResponses[message] += 1;
return { state: WaiterState.ABORTED, observedResponses };
}
if (Date.now() + delayMs > waitUntil) {
return { state: WaiterState.TIMEOUT, observedResponses };
}
await sleep(delayMs / 1_000);
}
const { state, reason } = await acceptorChecks(client, input);
if (reason) {
const message = createMessageFromResponse(reason);
observedResponses[message] |= 0;
observedResponses[message] += 1;
}
if (state !== WaiterState.RETRY) {
return { state, reason, final: reason, observedResponses };
}
currentAttempt += 1;
if (!didWarn403 && Date.now() >= warn403Time) {
checkWarn403(observedResponses, client);
didWarn403 = true;
}
}
};
const checkWarn403 = (observedResponses = {}, client) => {
const orderedErrors = Object.keys(observedResponses);
let maxCount = 0;
let count403 = 0;
for (const response of orderedErrors) {
const n = observedResponses[response] | 0;
maxCount = Math.max(n, maxCount);
if (response.startsWith("403:")) {
count403 += n;
}
}
const clientLogger = client?.config?.logger;
const warningLogger = typeof clientLogger?.warn === "function" && !clientLogger.constructor?.name?.includes?.("NoOpLogger")
? clientLogger
: console;
if (count403 >= 3 || orderedErrors[orderedErrors.length - 1]?.startsWith("403:")) {
warningLogger.warn(`@smithy/util-waiter WARN - 403 status code encountered during waiter polling.`);
}
};
const createMessageFromResponse = (reason) => {
const status = reason?.$response?.statusCode ?? reason?.$metadata?.httpStatusCode;
if (reason?.$responseBodyText) {
return `${status ? status + ": " : ""}Deserialization error for body: ${reason.$responseBodyText}`;
}
if (status) {
if (reason?.$response || reason?.message) {
return `${status ?? "Unknown"}: ${reason?.message}`;
}
return `${status}: OK`;
}
return String(reason?.message ?? JSON.stringify(reason, getCircularReplacer()) ?? "Unknown");
};
const exponentialBackoffWithJitter = (minDelayMs, maxDelayMs, attempt, waitUntil) => {
const attemptCountCeiling = Math.log(maxDelayMs / minDelayMs) / Math.log(2) + 1;
if (attempt > attemptCountCeiling) {
return maxDelayMs;
}
const delay = minDelayMs * 2 ** (attempt - 1);
const capped = Math.min(delay, maxDelayMs);
const waitFor = randomInRange(minDelayMs, capped);
if (Date.now() + waitFor > waitUntil) {
const timeRemaining = waitUntil - Date.now();
return Math.max(0, timeRemaining - 500);
}
return waitFor;
};
const randomInRange = (min, max) => min + Math.random() * (max - min);
@@ -0,0 +1,3 @@
export const sleep = (seconds) => {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
};
@@ -0,0 +1,17 @@
export const validateWaiterOptions = (options) => {
if (options.maxWaitTime <= 0) {
throw new Error(`WaiterConfiguration.maxWaitTime must be greater than 0`);
}
else if (options.minDelay <= 0) {
throw new Error(`WaiterConfiguration.minDelay must be greater than 0`);
}
else if (options.maxDelay <= 0) {
throw new Error(`WaiterConfiguration.maxDelay must be greater than 0`);
}
else if (options.maxWaitTime <= options.minDelay) {
throw new Error(`WaiterConfiguration.maxWaitTime [${options.maxWaitTime}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter`);
}
else if (options.maxDelay < options.minDelay) {
throw new Error(`WaiterConfiguration.maxDelay [${options.maxDelay}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter`);
}
};
@@ -0,0 +1,35 @@
import { getCircularReplacer } from "./circularReplacer";
export const waiterServiceDefaults = {
minDelay: 2,
maxDelay: 120,
};
export var WaiterState;
(function (WaiterState) {
WaiterState["ABORTED"] = "ABORTED";
WaiterState["FAILURE"] = "FAILURE";
WaiterState["SUCCESS"] = "SUCCESS";
WaiterState["RETRY"] = "RETRY";
WaiterState["TIMEOUT"] = "TIMEOUT";
})(WaiterState || (WaiterState = {}));
export const checkExceptions = (result) => {
if (result.state === WaiterState.ABORTED) {
const abortError = new Error(`${JSON.stringify({
...result,
reason: "Request was aborted",
}, getCircularReplacer())}`);
abortError.name = "AbortError";
throw abortError;
}
else if (result.state === WaiterState.TIMEOUT) {
const timeoutError = new Error(`${JSON.stringify({
...result,
reason: "Waiter has timed out",
}, getCircularReplacer())}`);
timeoutError.name = "TimeoutError";
throw timeoutError;
}
else if (result.state !== WaiterState.SUCCESS) {
throw new Error(`${JSON.stringify(result, getCircularReplacer())}`);
}
return result;
};
@@ -0,0 +1,15 @@
import { booleanSelector } from "../../util-config-provider/booleanSelector";
import { SelectorType } from "../../util-config-provider/types";
export const ENV_USE_DUALSTACK_ENDPOINT = "AWS_USE_DUALSTACK_ENDPOINT";
export const CONFIG_USE_DUALSTACK_ENDPOINT = "use_dualstack_endpoint";
export const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
export const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_DUALSTACK_ENDPOINT, SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_DUALSTACK_ENDPOINT, SelectorType.CONFIG),
default: false,
};
export const nodeDualstackConfigSelectors = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_DUALSTACK_ENDPOINT, SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_DUALSTACK_ENDPOINT, SelectorType.CONFIG),
default: undefined,
};
@@ -0,0 +1,15 @@
import { booleanSelector } from "../../util-config-provider/booleanSelector";
import { SelectorType } from "../../util-config-provider/types";
export const ENV_USE_FIPS_ENDPOINT = "AWS_USE_FIPS_ENDPOINT";
export const CONFIG_USE_FIPS_ENDPOINT = "use_fips_endpoint";
export const DEFAULT_USE_FIPS_ENDPOINT = false;
export const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_FIPS_ENDPOINT, SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_FIPS_ENDPOINT, SelectorType.CONFIG),
default: false,
};
export const nodeFipsConfigSelectors = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_FIPS_ENDPOINT, SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_FIPS_ENDPOINT, SelectorType.CONFIG),
default: undefined,
};
@@ -0,0 +1,10 @@
import { normalizeProvider } from "@smithy/core/client";
export const resolveCustomEndpointsConfig = (input) => {
const { tls, endpoint, urlParser, useDualstackEndpoint } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint),
isCustomEndpoint: true,
useDualstackEndpoint: normalizeProvider(useDualstackEndpoint ?? false),
});
};
@@ -0,0 +1,14 @@
import { normalizeProvider } from "@smithy/core/client";
import { getEndpointFromRegion } from "./utils/getEndpointFromRegion";
export const resolveEndpointsConfig = (input) => {
const useDualstackEndpoint = normalizeProvider(input.useDualstackEndpoint ?? false);
const { endpoint, useFipsEndpoint, urlParser, tls } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: endpoint
? normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint)
: () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }),
isCustomEndpoint: !!endpoint,
useDualstackEndpoint,
});
};
@@ -0,0 +1,15 @@
export const getEndpointFromRegion = async (input) => {
const { tls = true } = input;
const region = await input.region();
const dnsHostRegex = new RegExp(/^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/);
if (!dnsHostRegex.test(region)) {
throw new Error("Invalid region in client config");
}
const useDualstackEndpoint = await input.useDualstackEndpoint();
const useFipsEndpoint = await input.useFipsEndpoint();
const { hostname } = (await input.regionInfoProvider(region, { useDualstackEndpoint, useFipsEndpoint })) ?? {};
if (!hostname) {
throw new Error("Cannot resolve hostname from client config");
}
return input.urlParser(`${tls ? "https:" : "http:"}//${hostname}`);
};
@@ -0,0 +1,15 @@
import { isValidHostLabel } from "@smithy/core/transport";
const validRegions = new Set();
export const checkRegion = (region, check = isValidHostLabel) => {
if (!validRegions.has(region) && !check(region)) {
if (region === "*") {
console.warn(`@smithy/config-resolver WARN - Please use the caller region instead of "*". See "sigv4a" in https://github.com/aws/aws-sdk-js-v3/blob/main/supplemental-docs/CLIENTS.md.`);
}
else {
throw new Error(`Region not accepted: region="${region}" is not a valid hostname component.`);
}
}
else {
validRegions.add(region);
}
};
@@ -0,0 +1,12 @@
export const REGION_ENV_NAME = "AWS_REGION";
export const REGION_INI_NAME = "region";
export const NODE_REGION_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => env[REGION_ENV_NAME],
configFileSelector: (profile) => profile[REGION_INI_NAME],
default: () => {
throw new Error("Region is missing");
},
};
export const NODE_REGION_CONFIG_FILE_OPTIONS = {
preferredFile: "credentials",
};
@@ -0,0 +1,6 @@
import { isFipsRegion } from "./isFipsRegion";
export const getRealRegion = (region) => isFipsRegion(region)
? ["fips-aws-global", "aws-fips"].includes(region)
? "us-east-1"
: region.replace(/fips-(dkr-|prod-)?|-fips/, "")
: region;
@@ -0,0 +1 @@
export const isFipsRegion = (region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips"));
@@ -0,0 +1,24 @@
import { checkRegion } from "./checkRegion";
import { getRealRegion } from "./getRealRegion";
import { isFipsRegion } from "./isFipsRegion";
export const resolveRegionConfig = (input) => {
const { region, useFipsEndpoint } = input;
if (!region) {
throw new Error("Region is missing");
}
return Object.assign(input, {
region: async () => {
const providedRegion = typeof region === "function" ? await region() : region;
const realRegion = getRealRegion(providedRegion);
checkRegion(realRegion);
return realRegion;
},
useFipsEndpoint: async () => {
const providedRegion = typeof region === "string" ? region : await region();
if (isFipsRegion(providedRegion)) {
return true;
}
return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint();
},
});
};
@@ -0,0 +1 @@
export {};
@@ -0,0 +1 @@
export {};
@@ -0,0 +1 @@
export {};
@@ -0,0 +1 @@
export {};
@@ -0,0 +1 @@
export const getHostnameFromVariants = (variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find(({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack"))?.hostname;
@@ -0,0 +1,29 @@
import { getHostnameFromVariants } from "./getHostnameFromVariants";
import { getResolvedHostname } from "./getResolvedHostname";
import { getResolvedPartition } from "./getResolvedPartition";
import { getResolvedSigningRegion } from "./getResolvedSigningRegion";
export const getRegionInfo = (region, { useFipsEndpoint = false, useDualstackEndpoint = false, signingService, regionHash, partitionHash, }) => {
const partition = getResolvedPartition(region, { partitionHash });
const resolvedRegion = region in regionHash ? region : partitionHash[partition]?.endpoint ?? region;
const hostnameOptions = { useFipsEndpoint, useDualstackEndpoint };
const regionHostname = getHostnameFromVariants(regionHash[resolvedRegion]?.variants, hostnameOptions);
const partitionHostname = getHostnameFromVariants(partitionHash[partition]?.variants, hostnameOptions);
const hostname = getResolvedHostname(resolvedRegion, { regionHostname, partitionHostname });
if (hostname === undefined) {
throw new Error(`Endpoint resolution failed for: ${{ resolvedRegion, useFipsEndpoint, useDualstackEndpoint }}`);
}
const signingRegion = getResolvedSigningRegion(hostname, {
signingRegion: regionHash[resolvedRegion]?.signingRegion,
regionRegex: partitionHash[partition].regionRegex,
useFipsEndpoint,
});
return {
partition,
signingService,
hostname,
...(signingRegion && { signingRegion }),
...(regionHash[resolvedRegion]?.signingService && {
signingService: regionHash[resolvedRegion].signingService,
}),
};
};
@@ -0,0 +1,5 @@
export const getResolvedHostname = (resolvedRegion, { regionHostname, partitionHostname }) => regionHostname
? regionHostname
: partitionHostname
? partitionHostname.replace("{region}", resolvedRegion)
: undefined;
@@ -0,0 +1 @@
export const getResolvedPartition = (region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws";
@@ -0,0 +1,12 @@
export const getResolvedSigningRegion = (hostname, { signingRegion, regionRegex, useFipsEndpoint }) => {
if (signingRegion) {
return signingRegion;
}
else if (useFipsEndpoint) {
const regionRegexJs = regionRegex.replace("\\\\", "\\").replace(/^\^/g, "\\.").replace(/\$$/g, "\\.");
const regionRegexmatchArray = hostname.match(regionRegexJs);
if (regionRegexmatchArray) {
return regionRegexmatchArray[0].slice(1, -1);
}
}
};
@@ -0,0 +1,6 @@
export const AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV";
export const AWS_REGION_ENV = "AWS_REGION";
export const AWS_DEFAULT_REGION_ENV = "AWS_DEFAULT_REGION";
export const ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED";
export const DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"];
export const IMDS_REGION_PATH = "/latest/meta-data/placement/region";
@@ -0,0 +1,11 @@
const AWS_DEFAULTS_MODE_ENV = "AWS_DEFAULTS_MODE";
const AWS_DEFAULTS_MODE_CONFIG = "defaults_mode";
export const NODE_DEFAULTS_MODE_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => {
return env[AWS_DEFAULTS_MODE_ENV];
},
configFileSelector: (profile) => {
return profile[AWS_DEFAULTS_MODE_CONFIG];
},
default: "legacy",
};
@@ -0,0 +1,30 @@
import { memoize } from "../property-provider/memoize";
import { DEFAULTS_MODE_OPTIONS } from "./constants";
export const resolveDefaultsModeConfig = ({ defaultsMode, } = {}) => memoize(async () => {
const mode = typeof defaultsMode === "function" ? await defaultsMode() : defaultsMode;
switch (mode?.toLowerCase()) {
case "auto":
return Promise.resolve(useMobileConfiguration() ? "mobile" : "standard");
case "mobile":
case "in-region":
case "cross-region":
case "standard":
case "legacy":
return Promise.resolve(mode?.toLocaleLowerCase());
case undefined:
return Promise.resolve("legacy");
default:
throw new Error(`Invalid parameter for "defaultsMode", expect ${DEFAULTS_MODE_OPTIONS.join(", ")}, got ${mode}`);
}
});
const useMobileConfiguration = () => {
const navigator = window?.navigator;
if (navigator?.connection) {
const { effectiveType, rtt, downlink } = navigator?.connection;
const slow = (typeof effectiveType === "string" && effectiveType !== "4g") || Number(rtt) > 100 || Number(downlink) < 10;
if (slow) {
return true;
}
}
return (navigator?.userAgentData?.mobile || (typeof navigator?.maxTouchPoints === "number" && navigator?.maxTouchPoints > 1));
};
@@ -0,0 +1,98 @@
import { NODE_REGION_CONFIG_OPTIONS } from "../config-resolver/regionConfig/config";
import { loadConfig } from "../node-config-provider/configLoader";
import { memoize } from "../property-provider/memoize";
import { AWS_DEFAULT_REGION_ENV, AWS_EXECUTION_ENV, AWS_REGION_ENV, DEFAULTS_MODE_OPTIONS, ENV_IMDS_DISABLED, IMDS_REGION_PATH, } from "./constants";
import { NODE_DEFAULTS_MODE_CONFIG_OPTIONS } from "./defaultsModeConfig";
export const resolveDefaultsModeConfig = ({ region = loadConfig(NODE_REGION_CONFIG_OPTIONS), defaultsMode = loadConfig(NODE_DEFAULTS_MODE_CONFIG_OPTIONS), } = {}) => memoize(async () => {
const mode = typeof defaultsMode === "function" ? await defaultsMode() : defaultsMode;
switch (mode?.toLowerCase()) {
case "auto":
return resolveNodeDefaultsModeAuto(region);
case "in-region":
case "cross-region":
case "mobile":
case "standard":
case "legacy":
return Promise.resolve(mode?.toLocaleLowerCase());
case undefined:
return Promise.resolve("legacy");
default:
throw new Error(`Invalid parameter for "defaultsMode", expect ${DEFAULTS_MODE_OPTIONS.join(", ")}, got ${mode}`);
}
});
const resolveNodeDefaultsModeAuto = async (clientRegion) => {
if (clientRegion) {
const resolvedRegion = typeof clientRegion === "function" ? await clientRegion() : clientRegion;
const inferredRegion = await inferPhysicalRegion();
if (!inferredRegion) {
return "standard";
}
if (resolvedRegion === inferredRegion) {
return "in-region";
}
else {
return "cross-region";
}
}
return "standard";
};
const inferPhysicalRegion = async () => {
if (process.env[AWS_EXECUTION_ENV] && (process.env[AWS_REGION_ENV] || process.env[AWS_DEFAULT_REGION_ENV])) {
return process.env[AWS_REGION_ENV] ?? process.env[AWS_DEFAULT_REGION_ENV];
}
if (!process.env[ENV_IMDS_DISABLED]) {
try {
const endpoint = await getImdsEndpoint();
return (await imdsHttpGet({ hostname: endpoint.hostname, path: IMDS_REGION_PATH })).toString();
}
catch (e) {
}
}
};
const getImdsEndpoint = async () => {
const envEndpoint = process.env.AWS_EC2_METADATA_SERVICE_ENDPOINT;
if (envEndpoint) {
const url = new URL(envEndpoint);
return { hostname: url.hostname, path: url.pathname };
}
const envMode = process.env.AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE;
if (envMode === "IPv6") {
return { hostname: "fd00:ec2::254", path: "/" };
}
return { hostname: "169.254.169.254", path: "/" };
};
const imdsHttpGet = async ({ hostname, path }) => {
const { request } = await import("node:http");
return new Promise((resolve, reject) => {
const req = request({
method: "GET",
hostname: hostname.replace(/^\[(.+)]$/, "$1"),
path,
timeout: 1000,
signal: AbortSignal.timeout(1000),
});
req.on("error", (err) => {
reject(err);
req.destroy();
});
req.on("timeout", () => {
reject(new Error("TimeoutError from instance metadata service"));
req.destroy();
});
req.on("response", (res) => {
const { statusCode = 400 } = res;
if (statusCode < 200 || 300 <= statusCode) {
reject(Object.assign(new Error("Error response received from instance metadata service"), { statusCode }));
req.destroy();
return;
}
const chunks = [];
res.on("data", (chunk) => chunks.push(chunk));
res.on("end", () => {
resolve(Buffer.concat(chunks));
req.destroy();
});
});
req.end();
});
};
@@ -0,0 +1,19 @@
import { memoize } from "../property-provider/memoize";
import { DEFAULTS_MODE_OPTIONS } from "./constants";
export const resolveDefaultsModeConfig = ({ defaultsMode, } = {}) => memoize(async () => {
const mode = typeof defaultsMode === "function" ? await defaultsMode() : defaultsMode;
switch (mode?.toLowerCase()) {
case "auto":
return Promise.resolve("mobile");
case "mobile":
case "in-region":
case "cross-region":
case "standard":
case "legacy":
return Promise.resolve(mode?.toLocaleLowerCase());
case undefined:
return Promise.resolve("legacy");
default:
throw new Error(`Invalid parameter for "defaultsMode", expect ${DEFAULTS_MODE_OPTIONS.join(", ")}, got ${mode}`);
}
});
+43
View File
@@ -0,0 +1,43 @@
const no = Symbol.for("node-only");
export { ProviderError } from "./property-provider/ProviderError";
export { CredentialsProviderError } from "./property-provider/CredentialsProviderError";
export { TokenProviderError } from "./property-provider/TokenProviderError";
export { chain } from "./property-provider/chain";
export { fromValue } from "./property-provider/fromValue";
export { memoize } from "./property-provider/memoize";
export { booleanSelector } from "./util-config-provider/booleanSelector";
export { numberSelector } from "./util-config-provider/numberSelector";
export { SelectorType } from "./util-config-provider/types";
export const getHomeDir = no;
export const ENV_PROFILE = no;
export const DEFAULT_PROFILE = "default";
export const getProfileName = no;
export const getSSOTokenFilepath = no;
export const getSSOTokenFromFile = no;
export const CONFIG_PREFIX_SEPARATOR = no;
export const loadSharedConfigFiles = no;
export const loadSsoSessionData = no;
export const parseKnownFiles = no;
export const externalDataInterceptor = no;
export const readFile = no;
export const loadConfig = no;
export const fromStatic = no;
export const ENV_USE_DUALSTACK_ENDPOINT = no;
export const CONFIG_USE_DUALSTACK_ENDPOINT = no;
export const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
export const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = no;
export const nodeDualstackConfigSelectors = no;
export const ENV_USE_FIPS_ENDPOINT = no;
export const CONFIG_USE_FIPS_ENDPOINT = no;
export const DEFAULT_USE_FIPS_ENDPOINT = false;
export const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = no;
export const nodeFipsConfigSelectors = no;
export { resolveCustomEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveCustomEndpointsConfig";
export { resolveEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveEndpointsConfig";
export const REGION_ENV_NAME = no;
export const REGION_INI_NAME = no;
export const NODE_REGION_CONFIG_OPTIONS = no;
export const NODE_REGION_CONFIG_FILE_OPTIONS = no;
export { resolveRegionConfig, } from "./config-resolver/regionConfig/resolveRegionConfig";
export { getRegionInfo } from "./config-resolver/regionInfo/getRegionInfo";
export { resolveDefaultsModeConfig, } from "./defaults-mode/resolveDefaultsModeConfig.browser";
+29
View File
@@ -0,0 +1,29 @@
export { ProviderError } from "./property-provider/ProviderError";
export { CredentialsProviderError } from "./property-provider/CredentialsProviderError";
export { TokenProviderError } from "./property-provider/TokenProviderError";
export { chain } from "./property-provider/chain";
export { fromValue } from "./property-provider/fromValue";
export { memoize } from "./property-provider/memoize";
export { booleanSelector } from "./util-config-provider/booleanSelector";
export { numberSelector } from "./util-config-provider/numberSelector";
export { SelectorType } from "./util-config-provider/types";
export { getHomeDir } from "./shared-ini-file-loader/getHomeDir";
export { ENV_PROFILE, DEFAULT_PROFILE, getProfileName } from "./shared-ini-file-loader/getProfileName";
export { getSSOTokenFilepath } from "./shared-ini-file-loader/getSSOTokenFilepath";
export { getSSOTokenFromFile } from "./shared-ini-file-loader/getSSOTokenFromFile";
export { CONFIG_PREFIX_SEPARATOR } from "./shared-ini-file-loader/constants";
export { loadSharedConfigFiles } from "./shared-ini-file-loader/loadSharedConfigFiles";
export { loadSsoSessionData } from "./shared-ini-file-loader/loadSsoSessionData";
export { parseKnownFiles } from "./shared-ini-file-loader/parseKnownFiles";
export { externalDataInterceptor } from "./shared-ini-file-loader/externalDataInterceptor";
export { readFile } from "./shared-ini-file-loader/readFile";
export { loadConfig } from "./node-config-provider/configLoader";
export { fromStatic } from "./node-config-provider/fromStatic";
export { ENV_USE_DUALSTACK_ENDPOINT, CONFIG_USE_DUALSTACK_ENDPOINT, DEFAULT_USE_DUALSTACK_ENDPOINT, NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, nodeDualstackConfigSelectors, } from "./config-resolver/endpointsConfig/NodeUseDualstackEndpointConfigOptions";
export { ENV_USE_FIPS_ENDPOINT, CONFIG_USE_FIPS_ENDPOINT, DEFAULT_USE_FIPS_ENDPOINT, NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, nodeFipsConfigSelectors, } from "./config-resolver/endpointsConfig/NodeUseFipsEndpointConfigOptions";
export { resolveCustomEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveCustomEndpointsConfig";
export { resolveEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveEndpointsConfig";
export { REGION_ENV_NAME, REGION_INI_NAME, NODE_REGION_CONFIG_OPTIONS, NODE_REGION_CONFIG_FILE_OPTIONS, } from "./config-resolver/regionConfig/config";
export { resolveRegionConfig, } from "./config-resolver/regionConfig/resolveRegionConfig";
export { getRegionInfo } from "./config-resolver/regionInfo/getRegionInfo";
export { resolveDefaultsModeConfig, } from "./defaults-mode/resolveDefaultsModeConfig";
+43
View File
@@ -0,0 +1,43 @@
const no = Symbol.for("node-only");
export { ProviderError } from "./property-provider/ProviderError";
export { CredentialsProviderError } from "./property-provider/CredentialsProviderError";
export { TokenProviderError } from "./property-provider/TokenProviderError";
export { chain } from "./property-provider/chain";
export { fromValue } from "./property-provider/fromValue";
export { memoize } from "./property-provider/memoize";
export { booleanSelector } from "./util-config-provider/booleanSelector";
export { numberSelector } from "./util-config-provider/numberSelector";
export { SelectorType } from "./util-config-provider/types";
export const getHomeDir = no;
export const ENV_PROFILE = no;
export const DEFAULT_PROFILE = "default";
export const getProfileName = no;
export const getSSOTokenFilepath = no;
export const getSSOTokenFromFile = no;
export const CONFIG_PREFIX_SEPARATOR = no;
export const loadSharedConfigFiles = no;
export const loadSsoSessionData = no;
export const parseKnownFiles = no;
export const externalDataInterceptor = no;
export const readFile = no;
export const loadConfig = no;
export const fromStatic = no;
export const ENV_USE_DUALSTACK_ENDPOINT = no;
export const CONFIG_USE_DUALSTACK_ENDPOINT = no;
export const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
export const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = no;
export const nodeDualstackConfigSelectors = no;
export const ENV_USE_FIPS_ENDPOINT = no;
export const CONFIG_USE_FIPS_ENDPOINT = no;
export const DEFAULT_USE_FIPS_ENDPOINT = false;
export const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = no;
export const nodeFipsConfigSelectors = no;
export { resolveCustomEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveCustomEndpointsConfig";
export { resolveEndpointsConfig, } from "./config-resolver/endpointsConfig/resolveEndpointsConfig";
export const REGION_ENV_NAME = no;
export const REGION_INI_NAME = no;
export const NODE_REGION_CONFIG_OPTIONS = no;
export const NODE_REGION_CONFIG_FILE_OPTIONS = no;
export { resolveRegionConfig, } from "./config-resolver/regionConfig/resolveRegionConfig";
export { getRegionInfo } from "./config-resolver/regionInfo/getRegionInfo";
export { resolveDefaultsModeConfig, } from "./defaults-mode/resolveDefaultsModeConfig.native";
@@ -0,0 +1,10 @@
import { chain } from "../property-provider/chain";
import { memoize } from "../property-provider/memoize";
import { fromEnv } from "./fromEnv";
import { fromSharedConfigFiles } from "./fromSharedConfigFiles";
import { fromStatic } from "./fromStatic";
export const loadConfig = ({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => {
const { signingName, logger } = configuration;
const envOptions = { signingName, logger };
return memoize(chain(fromEnv(environmentVariableSelector, envOptions), fromSharedConfigFiles(configFileSelector, configuration), fromStatic(defaultValue)));
};
@@ -0,0 +1,14 @@
import { CredentialsProviderError } from "../property-provider/CredentialsProviderError";
import { getSelectorName } from "./getSelectorName";
export const fromEnv = (envVarSelector, options) => async () => {
try {
const config = envVarSelector(process.env, options);
if (config === undefined) {
throw new Error();
}
return config;
}
catch (e) {
throw new CredentialsProviderError(e.message || `Not found in ENV: ${getSelectorName(envVarSelector.toString())}`, { logger: options?.logger });
}
};
@@ -0,0 +1,24 @@
import { CredentialsProviderError } from "../property-provider/CredentialsProviderError";
import { getProfileName } from "../shared-ini-file-loader/getProfileName";
import { loadSharedConfigFiles } from "../shared-ini-file-loader/loadSharedConfigFiles";
import { getSelectorName } from "./getSelectorName";
export const fromSharedConfigFiles = (configSelector, { preferredFile = "config", ...init } = {}) => async () => {
const profile = getProfileName(init);
const { configFile, credentialsFile } = await loadSharedConfigFiles(init);
const profileFromCredentials = credentialsFile[profile] || {};
const profileFromConfig = configFile[profile] || {};
const mergedProfile = preferredFile === "config"
? { ...profileFromCredentials, ...profileFromConfig }
: { ...profileFromConfig, ...profileFromCredentials };
try {
const cfgFile = preferredFile === "config" ? configFile : credentialsFile;
const configValue = configSelector(mergedProfile, cfgFile);
if (configValue === undefined) {
throw new Error();
}
return configValue;
}
catch (e) {
throw new CredentialsProviderError(e.message || `Not found in config files w/ profile [${profile}]: ${getSelectorName(configSelector.toString())}`, { logger: init.logger });
}
};
@@ -0,0 +1,3 @@
import { fromValue } from "../property-provider/fromValue";
const isFunction = (func) => typeof func === "function";
export const fromStatic = (defaultValue) => isFunction(defaultValue) ? async () => await defaultValue() : fromValue(defaultValue);
@@ -0,0 +1,12 @@
export function getSelectorName(functionString) {
try {
const constants = new Set(Array.from(functionString.match(/([A-Z_]){3,}/g) ?? []));
constants.delete("CONFIG");
constants.delete("CONFIG_PREFIX_SEPARATOR");
constants.delete("ENV");
return [...constants].join(", ");
}
catch (e) {
return functionString;
}
}
@@ -0,0 +1,8 @@
import { ProviderError } from "./ProviderError";
export class CredentialsProviderError extends ProviderError {
name = "CredentialsProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, CredentialsProviderError.prototype);
}
}
@@ -0,0 +1,23 @@
export class ProviderError extends Error {
name = "ProviderError";
tryNextLink;
constructor(message, options = true) {
let logger;
let tryNextLink = true;
if (typeof options === "boolean") {
logger = undefined;
tryNextLink = options;
}
else if (options != null && typeof options === "object") {
logger = options.logger;
tryNextLink = options.tryNextLink ?? true;
}
super(message);
this.tryNextLink = tryNextLink;
Object.setPrototypeOf(this, ProviderError.prototype);
logger?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`);
}
static from(error, options = true) {
return Object.assign(new this(error.message, options), error);
}
}
@@ -0,0 +1,8 @@
import { ProviderError } from "./ProviderError";
export class TokenProviderError extends ProviderError {
name = "TokenProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, TokenProviderError.prototype);
}
}
@@ -0,0 +1,21 @@
import { ProviderError } from "./ProviderError";
export const chain = (...providers) => async () => {
if (providers.length === 0) {
throw new ProviderError("No providers in chain");
}
let lastProviderError;
for (const provider of providers) {
try {
const credentials = await provider();
return credentials;
}
catch (err) {
lastProviderError = err;
if (err?.tryNextLink) {
continue;
}
throw err;
}
}
throw lastProviderError;
};
@@ -0,0 +1 @@
export const fromValue = (staticValue) => () => Promise.resolve(staticValue);
@@ -0,0 +1,45 @@
export const memoize = (provider, isExpired, requiresRefresh) => {
let resolved;
let pending;
let hasResult;
let isConstant = false;
const coalesceProvider = async () => {
if (!pending) {
pending = provider();
}
try {
resolved = await pending;
hasResult = true;
isConstant = false;
}
finally {
pending = undefined;
}
return resolved;
};
if (isExpired === undefined) {
return async (options) => {
if (!hasResult || options?.forceRefresh) {
resolved = await coalesceProvider();
}
return resolved;
};
}
return async (options) => {
if (!hasResult || options?.forceRefresh) {
resolved = await coalesceProvider();
}
if (isConstant) {
return resolved;
}
if (requiresRefresh && !requiresRefresh(resolved)) {
isConstant = true;
return resolved;
}
if (isExpired(resolved)) {
await coalesceProvider();
return resolved;
}
return resolved;
};
};
@@ -0,0 +1 @@
export const CONFIG_PREFIX_SEPARATOR = ".";
@@ -0,0 +1,16 @@
import { tokenIntercept } from "./getSSOTokenFromFile";
import { fileIntercept } from "./readFile";
export const externalDataInterceptor = {
getFileRecord() {
return fileIntercept;
},
interceptFile(path, contents) {
fileIntercept[path] = Promise.resolve(contents);
},
getTokenRecord() {
return tokenIntercept;
},
interceptToken(id, contents) {
tokenIntercept[id] = contents;
},
};
@@ -0,0 +1,18 @@
import { IniSectionType } from "@smithy/types";
import { CONFIG_PREFIX_SEPARATOR } from "./constants";
export const getConfigData = (data) => Object.entries(data)
.filter(([key]) => {
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
if (indexOfSeparator === -1) {
return false;
}
return Object.values(IniSectionType).includes(key.substring(0, indexOfSeparator));
})
.reduce((acc, [key, value]) => {
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
const updatedKey = key.substring(0, indexOfSeparator) === IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key;
acc[updatedKey] = value;
return acc;
}, {
...(data.default && { default: data.default }),
});
@@ -0,0 +1,4 @@
import { join } from "node:path";
import { getHomeDir } from "./getHomeDir";
export const ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
export const getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || join(getHomeDir(), ".aws", "config");
@@ -0,0 +1,4 @@
import { join } from "node:path";
import { getHomeDir } from "./getHomeDir";
export const ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
export const getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || join(getHomeDir(), ".aws", "credentials");
@@ -0,0 +1,22 @@
import { homedir } from "node:os";
import { sep } from "node:path";
const homeDirCache = {};
const getHomeDirCacheKey = () => {
if (process && process.geteuid) {
return `${process.geteuid()}`;
}
return "DEFAULT";
};
export const getHomeDir = () => {
const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${sep}` } = process.env;
if (HOME)
return HOME;
if (USERPROFILE)
return USERPROFILE;
if (HOMEPATH)
return `${HOMEDRIVE}${HOMEPATH}`;
const homeDirCacheKey = getHomeDirCacheKey();
if (!homeDirCache[homeDirCacheKey])
homeDirCache[homeDirCacheKey] = homedir();
return homeDirCache[homeDirCacheKey];
};
@@ -0,0 +1,3 @@
export const ENV_PROFILE = "AWS_PROFILE";
export const DEFAULT_PROFILE = "default";
export const getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
@@ -0,0 +1,8 @@
import { createHash } from "node:crypto";
import { join } from "node:path";
import { getHomeDir } from "./getHomeDir";
export const getSSOTokenFilepath = (id) => {
const hasher = createHash("sha1");
const cacheName = hasher.update(id).digest("hex");
return join(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
};
@@ -0,0 +1,11 @@
import { readFile } from "node:fs/promises";
import { getSSOTokenFilepath } from "./getSSOTokenFilepath";
export const tokenIntercept = {};
export const getSSOTokenFromFile = async (id) => {
if (tokenIntercept[id]) {
return tokenIntercept[id];
}
const ssoTokenFilepath = getSSOTokenFilepath(id);
const ssoTokenText = await readFile(ssoTokenFilepath, "utf8");
return JSON.parse(ssoTokenText);
};
@@ -0,0 +1,5 @@
import { IniSectionType } from "@smithy/types";
import { CONFIG_PREFIX_SEPARATOR } from "./loadSharedConfigFiles";
export const getSsoSessionData = (data) => Object.entries(data)
.filter(([key]) => key.startsWith(IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR))
.reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {});
@@ -0,0 +1,39 @@
import { join } from "node:path";
import { getConfigData } from "./getConfigData";
import { getConfigFilepath } from "./getConfigFilepath";
import { getCredentialsFilepath } from "./getCredentialsFilepath";
import { getHomeDir } from "./getHomeDir";
import { parseIni } from "./parseIni";
import { readFile } from "./readFile";
const swallowError = () => ({});
export { CONFIG_PREFIX_SEPARATOR } from "./constants";
export const loadSharedConfigFiles = async (init = {}) => {
const { filepath = getCredentialsFilepath(), configFilepath = getConfigFilepath() } = init;
const homeDir = getHomeDir();
const relativeHomeDirPrefix = "~/";
let resolvedFilepath = filepath;
if (filepath.startsWith(relativeHomeDirPrefix)) {
resolvedFilepath = join(homeDir, filepath.slice(2));
}
let resolvedConfigFilepath = configFilepath;
if (configFilepath.startsWith(relativeHomeDirPrefix)) {
resolvedConfigFilepath = join(homeDir, configFilepath.slice(2));
}
const parsedFiles = await Promise.all([
readFile(resolvedConfigFilepath, {
ignoreCache: init.ignoreCache,
})
.then(parseIni)
.then(getConfigData)
.catch(swallowError),
readFile(resolvedFilepath, {
ignoreCache: init.ignoreCache,
})
.then(parseIni)
.catch(swallowError),
]);
return {
configFile: parsedFiles[0],
credentialsFile: parsedFiles[1],
};
};
@@ -0,0 +1,9 @@
import { getConfigFilepath } from "./getConfigFilepath";
import { getSsoSessionData } from "./getSsoSessionData";
import { parseIni } from "./parseIni";
import { readFile } from "./readFile";
const swallowError = () => ({});
export const loadSsoSessionData = async (init = {}) => readFile(init.configFilepath ?? getConfigFilepath())
.then(parseIni)
.then(getSsoSessionData)
.catch(swallowError);

Some files were not shown because too many files have changed in this diff Show More