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
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+56
View File
@@ -0,0 +1,56 @@
# @smithy/core
[![NPM version](https://img.shields.io/npm/v/@smithy/core/latest.svg)](https://www.npmjs.com/package/@smithy/core)
[![NPM downloads](https://img.shields.io/npm/dm/@smithy/core.svg)](https://www.npmjs.com/package/@smithy/core)
### :warning: Internal API :warning:
> This is an internal package.
> That means this is used as a dependency for other, public packages, but
> should not be taken directly as a dependency in your application's `package.json`.
> If you are updating the version of this package, for example to bring in a
> bug-fix, you should do so by updating your application lockfile with
> e.g. `npm up @scope/package` or equivalent command in another
> package manager, rather than taking a direct dependency.
---
This package provides common or core functionality for generic Smithy clients.
You do not need to explicitly install this package, since it will be installed during code generation if used.
## Development of `@smithy/core` submodules
Core submodules are organized for distribution via the `package.json` `exports` field.
`exports` is supported by default by the latest Node.js, webpack, and esbuild. For react-native, it can be
enabled via instructions found at [reactnative.dev/blog](https://reactnative.dev/blog/2023/06/21/package-exports-support), but we also provide a compatibility redirect.
Think of `@smithy/core` as a mono-package within the monorepo.
It preserves the benefits of modularization, for example to optimize Node.js initialization speed,
while making it easier to have a consistent version of core dependencies, reducing package sprawl when
installing a Smithy runtime client.
### Guide for submodules
- Each `index.ts` file corresponding to the pattern `./src/submodules/<MODULE_NAME>/index.ts` will be
published as a separate `dist-cjs` bundled submodule index using the `Inliner.js` build script.
- create a folder as `./src/submodules/<SUBMODULE>` including an `index.ts` file and a `README.md` file.
- The linter will throw an error on missing submodule metadata in `package.json` and the various `tsconfig.json` files, but it will automatically fix them if possible.
- a submodule is equivalent to a standalone `@smithy/<pkg>` package in that importing it in Node.js will resolve a separate bundle.
- submodules may not relatively import files from other submodules. Instead, directly use the `@scope/pkg/submodule` name as the import.
- The linter will check for this and throw an error.
- To the extent possible, correctly declaring submodule metadata is validated by the linter in `@smithy/core`.
The linter runs during `yarn build` and also as `yarn lint`.
### When should I create an `@smithy/core/submodule` vs. `@smithy/new-package`?
Keep in mind that the core package is installed by all downstream clients.
If the component functionality is upstream of multiple clients, it is
a good candidate for a core submodule. For example, if `middleware-retry` had been written
after the support for submodules was added, it would have been a submodule.
If the component's functionality is downstream of a client (rare), or only expected to be used by a very small
subset of clients, it could be written as a standalone package.
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
export * from "./dist-types/submodules/cbor/index";
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
module.exports = require("./dist-cjs/submodules/cbor/index.js");
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
export * from "./dist-types/submodules/checksum/index";
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
module.exports = require("./dist-cjs/submodules/checksum/index.js");
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
export * from "./dist-types/submodules/client/index";
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
module.exports = require("./dist-cjs/submodules/client/index.js");
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
export * from "./dist-types/submodules/config/index";
+5
View File
@@ -0,0 +1,5 @@
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
module.exports = require("./dist-cjs/submodules/config/index.js");
+344
View File
@@ -0,0 +1,344 @@
'use strict';
var transport = require('@smithy/core/transport');
var protocols = require('@smithy/core/protocols');
var types = require('@smithy/types');
var client = require('@smithy/core/client');
const resolveAuthOptions = (candidateAuthOptions, authSchemePreference) => {
if (!authSchemePreference || authSchemePreference.length === 0) {
return candidateAuthOptions;
}
const preferredAuthOptions = [];
for (const preferredSchemeName of authSchemePreference) {
for (const candidateAuthOption of candidateAuthOptions) {
const candidateAuthSchemeName = candidateAuthOption.schemeId.split("#")[1];
if (candidateAuthSchemeName === preferredSchemeName) {
preferredAuthOptions.push(candidateAuthOption);
}
}
}
for (const candidateAuthOption of candidateAuthOptions) {
if (!preferredAuthOptions.find(({ schemeId }) => schemeId === candidateAuthOption.schemeId)) {
preferredAuthOptions.push(candidateAuthOption);
}
}
return preferredAuthOptions;
};
function convertHttpAuthSchemesToMap(httpAuthSchemes) {
const map = new Map();
for (const scheme of httpAuthSchemes) {
map.set(scheme.schemeId, scheme);
}
return map;
}
const httpAuthSchemeMiddleware = (config, mwOptions) => (next, context) => async (args) => {
const options = config.httpAuthSchemeProvider(await mwOptions.httpAuthSchemeParametersProvider(config, context, args.input));
const authSchemePreference = config.authSchemePreference ? await config.authSchemePreference() : [];
const resolvedOptions = resolveAuthOptions(options, authSchemePreference);
const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes);
const smithyContext = client.getSmithyContext(context);
const failureReasons = [];
for (const option of resolvedOptions) {
const scheme = authSchemes.get(option.schemeId);
if (!scheme) {
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`);
continue;
}
const identityProvider = scheme.identityProvider(await mwOptions.identityProviderConfigProvider(config));
if (!identityProvider) {
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`);
continue;
}
const { identityProperties = {}, signingProperties = {} } = option.propertiesExtractor?.(config, context) || {};
option.identityProperties = Object.assign(option.identityProperties || {}, identityProperties);
option.signingProperties = Object.assign(option.signingProperties || {}, signingProperties);
smithyContext.selectedHttpAuthScheme = {
httpAuthOption: option,
identity: await identityProvider(option.identityProperties),
signer: scheme.signer,
};
break;
}
if (!smithyContext.selectedHttpAuthScheme) {
throw new Error(failureReasons.join("\n"));
}
return next(args);
};
const httpAuthSchemeEndpointRuleSetMiddlewareOptions = {
step: "serialize",
tags: ["HTTP_AUTH_SCHEME"],
name: "httpAuthSchemeMiddleware",
override: true,
relation: "before",
toMiddleware: "endpointV2Middleware",
};
const getHttpAuthSchemeEndpointRuleSetPlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider,
identityProviderConfigProvider,
}), httpAuthSchemeEndpointRuleSetMiddlewareOptions);
},
});
const httpAuthSchemeMiddlewareOptions = {
step: "serialize",
tags: ["HTTP_AUTH_SCHEME"],
name: "httpAuthSchemeMiddleware",
override: true,
relation: "before",
toMiddleware: "serializerMiddleware",
};
const getHttpAuthSchemePlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider,
identityProviderConfigProvider,
}), httpAuthSchemeMiddlewareOptions);
},
});
const defaultErrorHandler = (signingProperties) => (error) => {
throw error;
};
const defaultSuccessHandler = (httpResponse, signingProperties) => { };
const httpSigningMiddleware = (config) => (next, context) => async (args) => {
if (!protocols.HttpRequest.isInstance(args.request)) {
return next(args);
}
const smithyContext = client.getSmithyContext(context);
const scheme = smithyContext.selectedHttpAuthScheme;
if (!scheme) {
throw new Error(`No HttpAuthScheme was selected: unable to sign request`);
}
const { httpAuthOption: { signingProperties = {} }, identity, signer, } = scheme;
const output = await next({
...args,
request: await signer.sign(args.request, identity, signingProperties),
}).catch((signer.errorHandler || defaultErrorHandler)(signingProperties));
(signer.successHandler || defaultSuccessHandler)(output.response, signingProperties);
return output;
};
const httpSigningMiddlewareOptions = {
step: "finalizeRequest",
tags: ["HTTP_SIGNING"],
name: "httpSigningMiddleware",
aliases: ["apiKeyMiddleware", "tokenMiddleware", "awsAuthMiddleware"],
override: true,
relation: "after",
toMiddleware: "retryMiddleware",
};
const getHttpSigningPlugin = (config) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpSigningMiddleware(), httpSigningMiddlewareOptions);
},
});
const normalizeProvider = (input) => {
if (typeof input === "function")
return input;
const promisified = Promise.resolve(input);
return () => promisified;
};
const makePagedClientRequest = async (CommandCtor, client, input, withCommand = (_) => _, ...args) => {
let command = new CommandCtor(input);
command = withCommand(command) ?? command;
return await client.send(command, ...args);
};
function createPaginator(ClientCtor, CommandCtor, inputTokenName, outputTokenName, pageSizeTokenName) {
return async function* paginateOperation(config, input, ...additionalArguments) {
const _input = input;
let token = config.startingToken ?? _input[inputTokenName];
let hasNext = true;
let page;
while (hasNext) {
_input[inputTokenName] = token;
if (pageSizeTokenName) {
_input[pageSizeTokenName] = _input[pageSizeTokenName] ?? config.pageSize;
}
if (config.client instanceof ClientCtor) {
page = await makePagedClientRequest(CommandCtor, config.client, input, config.withCommand, ...additionalArguments);
}
else {
throw new Error(`Invalid client, expected instance of ${ClientCtor.name}`);
}
yield page;
const prevToken = token;
token = get(page, outputTokenName);
hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken));
}
return undefined;
};
}
const get = (fromObject, path) => {
let cursor = fromObject;
const pathComponents = path.split(".");
for (const step of pathComponents) {
if (!cursor || typeof cursor !== "object") {
return undefined;
}
cursor = cursor[step];
}
return cursor;
};
function setFeature(context, feature, value) {
if (!context.__smithy_context) {
context.__smithy_context = {
features: {},
};
}
else if (!context.__smithy_context.features) {
context.__smithy_context.features = {};
}
context.__smithy_context.features[feature] = value;
}
class DefaultIdentityProviderConfig {
authSchemes = new Map();
constructor(config) {
for (const key in config) {
const value = config[key];
if (value !== undefined) {
this.authSchemes.set(key, value);
}
}
}
getIdentityProvider(schemeId) {
return this.authSchemes.get(schemeId);
}
}
class HttpApiKeyAuthSigner {
async sign(httpRequest, identity, signingProperties) {
if (!signingProperties) {
throw new Error("request could not be signed with `apiKey` since the `name` and `in` signer properties are missing");
}
if (!signingProperties.name) {
throw new Error("request could not be signed with `apiKey` since the `name` signer property is missing");
}
if (!signingProperties.in) {
throw new Error("request could not be signed with `apiKey` since the `in` signer property is missing");
}
if (!identity.apiKey) {
throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined");
}
const clonedRequest = protocols.HttpRequest.clone(httpRequest);
if (signingProperties.in === types.HttpApiKeyAuthLocation.QUERY) {
clonedRequest.query[signingProperties.name] = identity.apiKey;
}
else if (signingProperties.in === types.HttpApiKeyAuthLocation.HEADER) {
clonedRequest.headers[signingProperties.name] = signingProperties.scheme
? `${signingProperties.scheme} ${identity.apiKey}`
: identity.apiKey;
}
else {
throw new Error("request can only be signed with `apiKey` locations `query` or `header`, " +
"but found: `" +
signingProperties.in +
"`");
}
return clonedRequest;
}
}
class HttpBearerAuthSigner {
async sign(httpRequest, identity, signingProperties) {
const clonedRequest = protocols.HttpRequest.clone(httpRequest);
if (!identity.token) {
throw new Error("request could not be signed with `token` since the `token` is not defined");
}
clonedRequest.headers["Authorization"] = `Bearer ${identity.token}`;
return clonedRequest;
}
}
class NoAuthSigner {
async sign(httpRequest, identity, signingProperties) {
return httpRequest;
}
}
const createIsIdentityExpiredFunction = (expirationMs) => function isIdentityExpired(identity) {
return doesIdentityRequireRefresh(identity) && identity.expiration.getTime() - Date.now() < expirationMs;
};
const EXPIRATION_MS = 300_000;
const isIdentityExpired = createIsIdentityExpiredFunction(EXPIRATION_MS);
const doesIdentityRequireRefresh = (identity) => identity.expiration !== undefined;
const memoizeIdentityProvider = (provider, isExpired, requiresRefresh) => {
if (provider === undefined) {
return undefined;
}
const normalizedProvider = typeof provider !== "function" ? async () => Promise.resolve(provider) : provider;
let resolved;
let pending;
let hasResult;
let isConstant = false;
const coalesceProvider = async (options) => {
if (!pending) {
pending = normalizedProvider(options);
}
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(options);
}
return resolved;
};
}
return async (options) => {
if (!hasResult || options?.forceRefresh) {
resolved = await coalesceProvider(options);
}
if (isConstant) {
return resolved;
}
if (!requiresRefresh(resolved)) {
isConstant = true;
return resolved;
}
if (isExpired(resolved)) {
await coalesceProvider(options);
return resolved;
}
return resolved;
};
};
exports.getSmithyContext = transport.getSmithyContext;
exports.requestBuilder = protocols.requestBuilder;
exports.DefaultIdentityProviderConfig = DefaultIdentityProviderConfig;
exports.EXPIRATION_MS = EXPIRATION_MS;
exports.HttpApiKeyAuthSigner = HttpApiKeyAuthSigner;
exports.HttpBearerAuthSigner = HttpBearerAuthSigner;
exports.NoAuthSigner = NoAuthSigner;
exports.createIsIdentityExpiredFunction = createIsIdentityExpiredFunction;
exports.createPaginator = createPaginator;
exports.doesIdentityRequireRefresh = doesIdentityRequireRefresh;
exports.getHttpAuthSchemeEndpointRuleSetPlugin = getHttpAuthSchemeEndpointRuleSetPlugin;
exports.getHttpAuthSchemePlugin = getHttpAuthSchemePlugin;
exports.getHttpSigningPlugin = getHttpSigningPlugin;
exports.httpAuthSchemeEndpointRuleSetMiddlewareOptions = httpAuthSchemeEndpointRuleSetMiddlewareOptions;
exports.httpAuthSchemeMiddleware = httpAuthSchemeMiddleware;
exports.httpAuthSchemeMiddlewareOptions = httpAuthSchemeMiddlewareOptions;
exports.httpSigningMiddleware = httpSigningMiddleware;
exports.httpSigningMiddlewareOptions = httpSigningMiddlewareOptions;
exports.isIdentityExpired = isIdentityExpired;
exports.memoizeIdentityProvider = memoizeIdentityProvider;
exports.normalizeProvider = normalizeProvider;
exports.setFeature = setFeature;
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
'use strict';
var serde = require('@smithy/core/serde');
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;
}
}
const blobHasher = async function blobHasher(hashCtor, blob) {
const hash = new hashCtor();
await blobReader(blob, (chunk) => {
hash.update(chunk);
});
return hash.digest();
};
const BLOCK_SIZE = 64;
const DIGEST_LENGTH = 16;
const INIT = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
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 serde.fromUtf8(data);
}
if (ArrayBuffer.isView(data)) {
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT);
}
return new Uint8Array(data);
}
const no = Symbol.for("node-only");
const fileStreamHasher = no;
const readableStreamHasher = no;
exports.Md5 = Md5;
exports.blobHasher = blobHasher;
exports.blobReader = blobReader;
exports.fileStreamHasher = fileStreamHasher;
exports.readableStreamHasher = readableStreamHasher;
+259
View File
@@ -0,0 +1,259 @@
'use strict';
var node_fs = require('node:fs');
var node_stream = require('node:stream');
var serde = require('@smithy/core/serde');
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;
}
}
const blobHasher = async function blobHasher(hashCtor, blob) {
const hash = new hashCtor();
await blobReader(blob, (chunk) => {
hash.update(chunk);
});
return hash.digest();
};
class HashCalculator extends node_stream.Writable {
hash;
constructor(hash, options) {
super(options);
this.hash = hash;
}
_write(chunk, encoding, callback) {
try {
this.hash.update(serde.toUint8Array(chunk));
}
catch (err) {
return callback(err);
}
callback();
}
}
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 = node_fs.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";
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);
});
});
};
const BLOCK_SIZE = 64;
const DIGEST_LENGTH = 16;
const INIT = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
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 serde.fromUtf8(data);
}
if (ArrayBuffer.isView(data)) {
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT);
}
return new Uint8Array(data);
}
exports.Md5 = Md5;
exports.blobHasher = blobHasher;
exports.blobReader = blobReader;
exports.fileStreamHasher = fileStreamHasher;
exports.readableStreamHasher = readableStreamHasher;
+229
View File
@@ -0,0 +1,229 @@
'use strict';
var serde = require('@smithy/core/serde');
async function blobReader$1(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;
}
}
const blobHasher = async function blobHasher(hashCtor, blob) {
const hash = new hashCtor();
await blobReader$1(blob, (chunk) => {
hash.update(chunk);
});
return hash.digest();
};
const BLOCK_SIZE = 64;
const DIGEST_LENGTH = 16;
const INIT = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
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 serde.fromUtf8(data);
}
if (ArrayBuffer.isView(data)) {
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT);
}
return new Uint8Array(data);
}
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 = serde.fromBase64(data);
onChunk(decoded);
totalBytesRead += decoded.byteLength;
read();
};
read();
});
}
const no = Symbol.for("node-only");
const fileStreamHasher = no;
const readableStreamHasher = no;
exports.Md5 = Md5;
exports.blobHasher = blobHasher;
exports.blobReader = blobReader;
exports.fileStreamHasher = fileStreamHasher;
exports.readableStreamHasher = readableStreamHasher;
File diff suppressed because it is too large Load Diff
+375
View File
@@ -0,0 +1,375 @@
'use strict';
var client = require('@smithy/core/client');
var transport = require('@smithy/core/transport');
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);
}
}
class CredentialsProviderError extends ProviderError {
name = "CredentialsProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, CredentialsProviderError.prototype);
}
}
class TokenProviderError extends ProviderError {
name = "TokenProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, TokenProviderError.prototype);
}
}
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;
};
const fromValue = (staticValue) => () => Promise.resolve(staticValue);
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;
};
};
const booleanSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
if (obj[key] === "true")
return true;
if (obj[key] === "false")
return false;
throw new Error(`Cannot load ${type} "${key}". Expected "true" or "false", got ${obj[key]}.`);
};
const numberSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
const numberValue = parseInt(obj[key], 10);
if (Number.isNaN(numberValue)) {
throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`);
}
return numberValue;
};
exports.SelectorType = void 0;
(function (SelectorType) {
SelectorType["ENV"] = "env";
SelectorType["CONFIG"] = "shared config entry";
})(exports.SelectorType || (exports.SelectorType = {}));
const resolveCustomEndpointsConfig = (input) => {
const { tls, endpoint, urlParser, useDualstackEndpoint } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint),
isCustomEndpoint: true,
useDualstackEndpoint: client.normalizeProvider(useDualstackEndpoint ?? false),
});
};
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}`);
};
const resolveEndpointsConfig = (input) => {
const useDualstackEndpoint = client.normalizeProvider(input.useDualstackEndpoint ?? false);
const { endpoint, useFipsEndpoint, urlParser, tls } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: endpoint
? client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint)
: () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }),
isCustomEndpoint: !!endpoint,
useDualstackEndpoint,
});
};
const validRegions = new Set();
const checkRegion = (region, check = transport.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);
}
};
const isFipsRegion = (region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips"));
const getRealRegion = (region) => isFipsRegion(region)
? ["fips-aws-global", "aws-fips"].includes(region)
? "us-east-1"
: region.replace(/fips-(dkr-|prod-)?|-fips/, "")
: region;
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();
},
});
};
const getHostnameFromVariants = (variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find(({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack"))?.hostname;
const getResolvedHostname = (resolvedRegion, { regionHostname, partitionHostname }) => regionHostname
? regionHostname
: partitionHostname
? partitionHostname.replace("{region}", resolvedRegion)
: undefined;
const getResolvedPartition = (region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws";
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);
}
}
};
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,
}),
};
};
const DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"];
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));
};
const no = Symbol.for("node-only");
const getHomeDir = no;
const ENV_PROFILE = no;
const DEFAULT_PROFILE = "default";
const getProfileName = no;
const getSSOTokenFilepath = no;
const getSSOTokenFromFile = no;
const CONFIG_PREFIX_SEPARATOR = no;
const loadSharedConfigFiles = no;
const loadSsoSessionData = no;
const parseKnownFiles = no;
const externalDataInterceptor = no;
const readFile = no;
const loadConfig = no;
const fromStatic = no;
const ENV_USE_DUALSTACK_ENDPOINT = no;
const CONFIG_USE_DUALSTACK_ENDPOINT = no;
const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = no;
const nodeDualstackConfigSelectors = no;
const ENV_USE_FIPS_ENDPOINT = no;
const CONFIG_USE_FIPS_ENDPOINT = no;
const DEFAULT_USE_FIPS_ENDPOINT = false;
const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = no;
const nodeFipsConfigSelectors = no;
const REGION_ENV_NAME = no;
const REGION_INI_NAME = no;
const NODE_REGION_CONFIG_OPTIONS = no;
const NODE_REGION_CONFIG_FILE_OPTIONS = no;
exports.CONFIG_PREFIX_SEPARATOR = CONFIG_PREFIX_SEPARATOR;
exports.CONFIG_USE_DUALSTACK_ENDPOINT = CONFIG_USE_DUALSTACK_ENDPOINT;
exports.CONFIG_USE_FIPS_ENDPOINT = CONFIG_USE_FIPS_ENDPOINT;
exports.CredentialsProviderError = CredentialsProviderError;
exports.DEFAULT_PROFILE = DEFAULT_PROFILE;
exports.DEFAULT_USE_DUALSTACK_ENDPOINT = DEFAULT_USE_DUALSTACK_ENDPOINT;
exports.DEFAULT_USE_FIPS_ENDPOINT = DEFAULT_USE_FIPS_ENDPOINT;
exports.ENV_PROFILE = ENV_PROFILE;
exports.ENV_USE_DUALSTACK_ENDPOINT = ENV_USE_DUALSTACK_ENDPOINT;
exports.ENV_USE_FIPS_ENDPOINT = ENV_USE_FIPS_ENDPOINT;
exports.NODE_REGION_CONFIG_FILE_OPTIONS = NODE_REGION_CONFIG_FILE_OPTIONS;
exports.NODE_REGION_CONFIG_OPTIONS = NODE_REGION_CONFIG_OPTIONS;
exports.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS;
exports.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS;
exports.ProviderError = ProviderError;
exports.REGION_ENV_NAME = REGION_ENV_NAME;
exports.REGION_INI_NAME = REGION_INI_NAME;
exports.TokenProviderError = TokenProviderError;
exports.booleanSelector = booleanSelector;
exports.chain = chain;
exports.externalDataInterceptor = externalDataInterceptor;
exports.fromStatic = fromStatic;
exports.fromValue = fromValue;
exports.getHomeDir = getHomeDir;
exports.getProfileName = getProfileName;
exports.getRegionInfo = getRegionInfo;
exports.getSSOTokenFilepath = getSSOTokenFilepath;
exports.getSSOTokenFromFile = getSSOTokenFromFile;
exports.loadConfig = loadConfig;
exports.loadSharedConfigFiles = loadSharedConfigFiles;
exports.loadSsoSessionData = loadSsoSessionData;
exports.memoize = memoize;
exports.nodeDualstackConfigSelectors = nodeDualstackConfigSelectors;
exports.nodeFipsConfigSelectors = nodeFipsConfigSelectors;
exports.numberSelector = numberSelector;
exports.parseKnownFiles = parseKnownFiles;
exports.readFile = readFile;
exports.resolveCustomEndpointsConfig = resolveCustomEndpointsConfig;
exports.resolveDefaultsModeConfig = resolveDefaultsModeConfig;
exports.resolveEndpointsConfig = resolveEndpointsConfig;
exports.resolveRegionConfig = resolveRegionConfig;
+735
View File
@@ -0,0 +1,735 @@
'use strict';
var node_os = require('node:os');
var node_path = require('node:path');
var node_crypto = require('node:crypto');
var promises = require('node:fs/promises');
var types = require('@smithy/types');
var client = require('@smithy/core/client');
var transport = require('@smithy/core/transport');
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);
}
}
class CredentialsProviderError extends ProviderError {
name = "CredentialsProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, CredentialsProviderError.prototype);
}
}
class TokenProviderError extends ProviderError {
name = "TokenProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, TokenProviderError.prototype);
}
}
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;
};
const fromValue = (staticValue) => () => Promise.resolve(staticValue);
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;
};
};
const booleanSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
if (obj[key] === "true")
return true;
if (obj[key] === "false")
return false;
throw new Error(`Cannot load ${type} "${key}". Expected "true" or "false", got ${obj[key]}.`);
};
const numberSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
const numberValue = parseInt(obj[key], 10);
if (Number.isNaN(numberValue)) {
throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`);
}
return numberValue;
};
exports.SelectorType = void 0;
(function (SelectorType) {
SelectorType["ENV"] = "env";
SelectorType["CONFIG"] = "shared config entry";
})(exports.SelectorType || (exports.SelectorType = {}));
const homeDirCache = {};
const getHomeDirCacheKey = () => {
if (process && process.geteuid) {
return `${process.geteuid()}`;
}
return "DEFAULT";
};
const getHomeDir = () => {
const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${node_path.sep}` } = process.env;
if (HOME)
return HOME;
if (USERPROFILE)
return USERPROFILE;
if (HOMEPATH)
return `${HOMEDRIVE}${HOMEPATH}`;
const homeDirCacheKey = getHomeDirCacheKey();
if (!homeDirCache[homeDirCacheKey])
homeDirCache[homeDirCacheKey] = node_os.homedir();
return homeDirCache[homeDirCacheKey];
};
const ENV_PROFILE = "AWS_PROFILE";
const DEFAULT_PROFILE = "default";
const getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
const getSSOTokenFilepath = (id) => {
const hasher = node_crypto.createHash("sha1");
const cacheName = hasher.update(id).digest("hex");
return node_path.join(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
};
const tokenIntercept = {};
const getSSOTokenFromFile = async (id) => {
if (tokenIntercept[id]) {
return tokenIntercept[id];
}
const ssoTokenFilepath = getSSOTokenFilepath(id);
const ssoTokenText = await promises.readFile(ssoTokenFilepath, "utf8");
return JSON.parse(ssoTokenText);
};
const CONFIG_PREFIX_SEPARATOR = ".";
const getConfigData = (data) => Object.entries(data)
.filter(([key]) => {
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
if (indexOfSeparator === -1) {
return false;
}
return Object.values(types.IniSectionType).includes(key.substring(0, indexOfSeparator));
})
.reduce((acc, [key, value]) => {
const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
const updatedKey = key.substring(0, indexOfSeparator) === types.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key;
acc[updatedKey] = value;
return acc;
}, {
...(data.default && { default: data.default }),
});
const ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
const getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || node_path.join(getHomeDir(), ".aws", "config");
const ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
const getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || node_path.join(getHomeDir(), ".aws", "credentials");
const prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
const profileNameBlockList = ["__proto__", "profile __proto__"];
const parseIni = (iniData) => {
const map = {};
let currentSection;
let currentSubSection;
for (const iniLine of iniData.split(/\r?\n/)) {
const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim();
const isSection = trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]";
if (isSection) {
currentSection = undefined;
currentSubSection = undefined;
const sectionName = trimmedLine.substring(1, trimmedLine.length - 1);
const matches = prefixKeyRegex.exec(sectionName);
if (matches) {
const [, prefix, , name] = matches;
if (Object.values(types.IniSectionType).includes(prefix)) {
currentSection = [prefix, name].join(CONFIG_PREFIX_SEPARATOR);
}
}
else {
currentSection = sectionName;
}
if (profileNameBlockList.includes(sectionName)) {
throw new Error(`Found invalid profile name "${sectionName}"`);
}
}
else if (currentSection) {
const indexOfEqualsSign = trimmedLine.indexOf("=");
if (![0, -1].includes(indexOfEqualsSign)) {
const [name, value] = [
trimmedLine.substring(0, indexOfEqualsSign).trim(),
trimmedLine.substring(indexOfEqualsSign + 1).trim(),
];
if (value === "") {
currentSubSection = name;
}
else {
if (currentSubSection && iniLine.trimStart() === iniLine) {
currentSubSection = undefined;
}
map[currentSection] = map[currentSection] || {};
const key = currentSubSection ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR) : name;
map[currentSection][key] = value;
}
}
}
}
return map;
};
const filePromises = {};
const fileIntercept = {};
const readFile = (path, options) => {
if (fileIntercept[path] !== undefined) {
return fileIntercept[path];
}
if (!filePromises[path] || options?.ignoreCache) {
filePromises[path] = promises.readFile(path, "utf8");
}
return filePromises[path];
};
const swallowError$1 = () => ({});
const loadSharedConfigFiles = async (init = {}) => {
const { filepath = getCredentialsFilepath(), configFilepath = getConfigFilepath() } = init;
const homeDir = getHomeDir();
const relativeHomeDirPrefix = "~/";
let resolvedFilepath = filepath;
if (filepath.startsWith(relativeHomeDirPrefix)) {
resolvedFilepath = node_path.join(homeDir, filepath.slice(2));
}
let resolvedConfigFilepath = configFilepath;
if (configFilepath.startsWith(relativeHomeDirPrefix)) {
resolvedConfigFilepath = node_path.join(homeDir, configFilepath.slice(2));
}
const parsedFiles = await Promise.all([
readFile(resolvedConfigFilepath, {
ignoreCache: init.ignoreCache,
})
.then(parseIni)
.then(getConfigData)
.catch(swallowError$1),
readFile(resolvedFilepath, {
ignoreCache: init.ignoreCache,
})
.then(parseIni)
.catch(swallowError$1),
]);
return {
configFile: parsedFiles[0],
credentialsFile: parsedFiles[1],
};
};
const getSsoSessionData = (data) => Object.entries(data)
.filter(([key]) => key.startsWith(types.IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR))
.reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {});
const swallowError = () => ({});
const loadSsoSessionData = async (init = {}) => readFile(init.configFilepath ?? getConfigFilepath())
.then(parseIni)
.then(getSsoSessionData)
.catch(swallowError);
const mergeConfigFiles = (...files) => {
const merged = {};
for (const file of files) {
for (const [key, values] of Object.entries(file)) {
if (merged[key] !== undefined) {
Object.assign(merged[key], values);
}
else {
merged[key] = values;
}
}
}
return merged;
};
const parseKnownFiles = async (init) => {
const parsedFiles = await loadSharedConfigFiles(init);
return mergeConfigFiles(parsedFiles.configFile, parsedFiles.credentialsFile);
};
const externalDataInterceptor = {
getFileRecord() {
return fileIntercept;
},
interceptFile(path, contents) {
fileIntercept[path] = Promise.resolve(contents);
},
getTokenRecord() {
return tokenIntercept;
},
interceptToken(id, contents) {
tokenIntercept[id] = contents;
},
};
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;
}
}
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 });
}
};
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 });
}
};
const isFunction = (func) => typeof func === "function";
const fromStatic = (defaultValue) => isFunction(defaultValue) ? async () => await defaultValue() : fromValue(defaultValue);
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)));
};
const ENV_USE_DUALSTACK_ENDPOINT = "AWS_USE_DUALSTACK_ENDPOINT";
const CONFIG_USE_DUALSTACK_ENDPOINT = "use_dualstack_endpoint";
const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_DUALSTACK_ENDPOINT, exports.SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_DUALSTACK_ENDPOINT, exports.SelectorType.CONFIG),
default: false,
};
const nodeDualstackConfigSelectors = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_DUALSTACK_ENDPOINT, exports.SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_DUALSTACK_ENDPOINT, exports.SelectorType.CONFIG),
default: undefined,
};
const ENV_USE_FIPS_ENDPOINT = "AWS_USE_FIPS_ENDPOINT";
const CONFIG_USE_FIPS_ENDPOINT = "use_fips_endpoint";
const DEFAULT_USE_FIPS_ENDPOINT = false;
const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_FIPS_ENDPOINT, exports.SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_FIPS_ENDPOINT, exports.SelectorType.CONFIG),
default: false,
};
const nodeFipsConfigSelectors = {
environmentVariableSelector: (env) => booleanSelector(env, ENV_USE_FIPS_ENDPOINT, exports.SelectorType.ENV),
configFileSelector: (profile) => booleanSelector(profile, CONFIG_USE_FIPS_ENDPOINT, exports.SelectorType.CONFIG),
default: undefined,
};
const resolveCustomEndpointsConfig = (input) => {
const { tls, endpoint, urlParser, useDualstackEndpoint } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint),
isCustomEndpoint: true,
useDualstackEndpoint: client.normalizeProvider(useDualstackEndpoint ?? false),
});
};
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}`);
};
const resolveEndpointsConfig = (input) => {
const useDualstackEndpoint = client.normalizeProvider(input.useDualstackEndpoint ?? false);
const { endpoint, useFipsEndpoint, urlParser, tls } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: endpoint
? client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint)
: () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }),
isCustomEndpoint: !!endpoint,
useDualstackEndpoint,
});
};
const REGION_ENV_NAME = "AWS_REGION";
const REGION_INI_NAME = "region";
const NODE_REGION_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => env[REGION_ENV_NAME],
configFileSelector: (profile) => profile[REGION_INI_NAME],
default: () => {
throw new Error("Region is missing");
},
};
const NODE_REGION_CONFIG_FILE_OPTIONS = {
preferredFile: "credentials",
};
const validRegions = new Set();
const checkRegion = (region, check = transport.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);
}
};
const isFipsRegion = (region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips"));
const getRealRegion = (region) => isFipsRegion(region)
? ["fips-aws-global", "aws-fips"].includes(region)
? "us-east-1"
: region.replace(/fips-(dkr-|prod-)?|-fips/, "")
: region;
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();
},
});
};
const getHostnameFromVariants = (variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find(({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack"))?.hostname;
const getResolvedHostname = (resolvedRegion, { regionHostname, partitionHostname }) => regionHostname
? regionHostname
: partitionHostname
? partitionHostname.replace("{region}", resolvedRegion)
: undefined;
const getResolvedPartition = (region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws";
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);
}
}
};
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,
}),
};
};
const AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV";
const AWS_REGION_ENV = "AWS_REGION";
const AWS_DEFAULT_REGION_ENV = "AWS_DEFAULT_REGION";
const ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED";
const DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"];
const IMDS_REGION_PATH = "/latest/meta-data/placement/region";
const AWS_DEFAULTS_MODE_ENV = "AWS_DEFAULTS_MODE";
const AWS_DEFAULTS_MODE_CONFIG = "defaults_mode";
const NODE_DEFAULTS_MODE_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => {
return env[AWS_DEFAULTS_MODE_ENV];
},
configFileSelector: (profile) => {
return profile[AWS_DEFAULTS_MODE_CONFIG];
},
default: "legacy",
};
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();
});
};
exports.CONFIG_PREFIX_SEPARATOR = CONFIG_PREFIX_SEPARATOR;
exports.CONFIG_USE_DUALSTACK_ENDPOINT = CONFIG_USE_DUALSTACK_ENDPOINT;
exports.CONFIG_USE_FIPS_ENDPOINT = CONFIG_USE_FIPS_ENDPOINT;
exports.CredentialsProviderError = CredentialsProviderError;
exports.DEFAULT_PROFILE = DEFAULT_PROFILE;
exports.DEFAULT_USE_DUALSTACK_ENDPOINT = DEFAULT_USE_DUALSTACK_ENDPOINT;
exports.DEFAULT_USE_FIPS_ENDPOINT = DEFAULT_USE_FIPS_ENDPOINT;
exports.ENV_PROFILE = ENV_PROFILE;
exports.ENV_USE_DUALSTACK_ENDPOINT = ENV_USE_DUALSTACK_ENDPOINT;
exports.ENV_USE_FIPS_ENDPOINT = ENV_USE_FIPS_ENDPOINT;
exports.NODE_REGION_CONFIG_FILE_OPTIONS = NODE_REGION_CONFIG_FILE_OPTIONS;
exports.NODE_REGION_CONFIG_OPTIONS = NODE_REGION_CONFIG_OPTIONS;
exports.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS;
exports.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS;
exports.ProviderError = ProviderError;
exports.REGION_ENV_NAME = REGION_ENV_NAME;
exports.REGION_INI_NAME = REGION_INI_NAME;
exports.TokenProviderError = TokenProviderError;
exports.booleanSelector = booleanSelector;
exports.chain = chain;
exports.externalDataInterceptor = externalDataInterceptor;
exports.fromStatic = fromStatic;
exports.fromValue = fromValue;
exports.getHomeDir = getHomeDir;
exports.getProfileName = getProfileName;
exports.getRegionInfo = getRegionInfo;
exports.getSSOTokenFilepath = getSSOTokenFilepath;
exports.getSSOTokenFromFile = getSSOTokenFromFile;
exports.loadConfig = loadConfig;
exports.loadSharedConfigFiles = loadSharedConfigFiles;
exports.loadSsoSessionData = loadSsoSessionData;
exports.memoize = memoize;
exports.nodeDualstackConfigSelectors = nodeDualstackConfigSelectors;
exports.nodeFipsConfigSelectors = nodeFipsConfigSelectors;
exports.numberSelector = numberSelector;
exports.parseKnownFiles = parseKnownFiles;
exports.readFile = readFile;
exports.resolveCustomEndpointsConfig = resolveCustomEndpointsConfig;
exports.resolveDefaultsModeConfig = resolveDefaultsModeConfig;
exports.resolveEndpointsConfig = resolveEndpointsConfig;
exports.resolveRegionConfig = resolveRegionConfig;
+364
View File
@@ -0,0 +1,364 @@
'use strict';
var client = require('@smithy/core/client');
var transport = require('@smithy/core/transport');
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);
}
}
class CredentialsProviderError extends ProviderError {
name = "CredentialsProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, CredentialsProviderError.prototype);
}
}
class TokenProviderError extends ProviderError {
name = "TokenProviderError";
constructor(message, options = true) {
super(message, options);
Object.setPrototypeOf(this, TokenProviderError.prototype);
}
}
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;
};
const fromValue = (staticValue) => () => Promise.resolve(staticValue);
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;
};
};
const booleanSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
if (obj[key] === "true")
return true;
if (obj[key] === "false")
return false;
throw new Error(`Cannot load ${type} "${key}". Expected "true" or "false", got ${obj[key]}.`);
};
const numberSelector = (obj, key, type) => {
if (!(key in obj))
return undefined;
const numberValue = parseInt(obj[key], 10);
if (Number.isNaN(numberValue)) {
throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`);
}
return numberValue;
};
exports.SelectorType = void 0;
(function (SelectorType) {
SelectorType["ENV"] = "env";
SelectorType["CONFIG"] = "shared config entry";
})(exports.SelectorType || (exports.SelectorType = {}));
const resolveCustomEndpointsConfig = (input) => {
const { tls, endpoint, urlParser, useDualstackEndpoint } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint),
isCustomEndpoint: true,
useDualstackEndpoint: client.normalizeProvider(useDualstackEndpoint ?? false),
});
};
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}`);
};
const resolveEndpointsConfig = (input) => {
const useDualstackEndpoint = client.normalizeProvider(input.useDualstackEndpoint ?? false);
const { endpoint, useFipsEndpoint, urlParser, tls } = input;
return Object.assign(input, {
tls: tls ?? true,
endpoint: endpoint
? client.normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint)
: () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }),
isCustomEndpoint: !!endpoint,
useDualstackEndpoint,
});
};
const validRegions = new Set();
const checkRegion = (region, check = transport.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);
}
};
const isFipsRegion = (region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips"));
const getRealRegion = (region) => isFipsRegion(region)
? ["fips-aws-global", "aws-fips"].includes(region)
? "us-east-1"
: region.replace(/fips-(dkr-|prod-)?|-fips/, "")
: region;
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();
},
});
};
const getHostnameFromVariants = (variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find(({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack"))?.hostname;
const getResolvedHostname = (resolvedRegion, { regionHostname, partitionHostname }) => regionHostname
? regionHostname
: partitionHostname
? partitionHostname.replace("{region}", resolvedRegion)
: undefined;
const getResolvedPartition = (region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws";
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);
}
}
};
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,
}),
};
};
const DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"];
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}`);
}
});
const no = Symbol.for("node-only");
const getHomeDir = no;
const ENV_PROFILE = no;
const DEFAULT_PROFILE = "default";
const getProfileName = no;
const getSSOTokenFilepath = no;
const getSSOTokenFromFile = no;
const CONFIG_PREFIX_SEPARATOR = no;
const loadSharedConfigFiles = no;
const loadSsoSessionData = no;
const parseKnownFiles = no;
const externalDataInterceptor = no;
const readFile = no;
const loadConfig = no;
const fromStatic = no;
const ENV_USE_DUALSTACK_ENDPOINT = no;
const CONFIG_USE_DUALSTACK_ENDPOINT = no;
const DEFAULT_USE_DUALSTACK_ENDPOINT = false;
const NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = no;
const nodeDualstackConfigSelectors = no;
const ENV_USE_FIPS_ENDPOINT = no;
const CONFIG_USE_FIPS_ENDPOINT = no;
const DEFAULT_USE_FIPS_ENDPOINT = false;
const NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = no;
const nodeFipsConfigSelectors = no;
const REGION_ENV_NAME = no;
const REGION_INI_NAME = no;
const NODE_REGION_CONFIG_OPTIONS = no;
const NODE_REGION_CONFIG_FILE_OPTIONS = no;
exports.CONFIG_PREFIX_SEPARATOR = CONFIG_PREFIX_SEPARATOR;
exports.CONFIG_USE_DUALSTACK_ENDPOINT = CONFIG_USE_DUALSTACK_ENDPOINT;
exports.CONFIG_USE_FIPS_ENDPOINT = CONFIG_USE_FIPS_ENDPOINT;
exports.CredentialsProviderError = CredentialsProviderError;
exports.DEFAULT_PROFILE = DEFAULT_PROFILE;
exports.DEFAULT_USE_DUALSTACK_ENDPOINT = DEFAULT_USE_DUALSTACK_ENDPOINT;
exports.DEFAULT_USE_FIPS_ENDPOINT = DEFAULT_USE_FIPS_ENDPOINT;
exports.ENV_PROFILE = ENV_PROFILE;
exports.ENV_USE_DUALSTACK_ENDPOINT = ENV_USE_DUALSTACK_ENDPOINT;
exports.ENV_USE_FIPS_ENDPOINT = ENV_USE_FIPS_ENDPOINT;
exports.NODE_REGION_CONFIG_FILE_OPTIONS = NODE_REGION_CONFIG_FILE_OPTIONS;
exports.NODE_REGION_CONFIG_OPTIONS = NODE_REGION_CONFIG_OPTIONS;
exports.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS;
exports.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS;
exports.ProviderError = ProviderError;
exports.REGION_ENV_NAME = REGION_ENV_NAME;
exports.REGION_INI_NAME = REGION_INI_NAME;
exports.TokenProviderError = TokenProviderError;
exports.booleanSelector = booleanSelector;
exports.chain = chain;
exports.externalDataInterceptor = externalDataInterceptor;
exports.fromStatic = fromStatic;
exports.fromValue = fromValue;
exports.getHomeDir = getHomeDir;
exports.getProfileName = getProfileName;
exports.getRegionInfo = getRegionInfo;
exports.getSSOTokenFilepath = getSSOTokenFilepath;
exports.getSSOTokenFromFile = getSSOTokenFromFile;
exports.loadConfig = loadConfig;
exports.loadSharedConfigFiles = loadSharedConfigFiles;
exports.loadSsoSessionData = loadSsoSessionData;
exports.memoize = memoize;
exports.nodeDualstackConfigSelectors = nodeDualstackConfigSelectors;
exports.nodeFipsConfigSelectors = nodeFipsConfigSelectors;
exports.numberSelector = numberSelector;
exports.parseKnownFiles = parseKnownFiles;
exports.readFile = readFile;
exports.resolveCustomEndpointsConfig = resolveCustomEndpointsConfig;
exports.resolveDefaultsModeConfig = resolveDefaultsModeConfig;
exports.resolveEndpointsConfig = resolveEndpointsConfig;
exports.resolveRegionConfig = resolveRegionConfig;
@@ -0,0 +1,829 @@
'use strict';
var transport = require('@smithy/core/transport');
var client = require('@smithy/core/client');
var types = require('@smithy/types');
const getEndpointFromConfig = async (serviceId) => undefined;
const resolveParamsForS3 = async (endpointParams) => {
const bucket = endpointParams?.Bucket || "";
if (typeof endpointParams.Bucket === "string") {
endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?"));
}
if (isArnBucketName(bucket)) {
if (endpointParams.ForcePathStyle === true) {
throw new Error("Path-style addressing cannot be used with ARN buckets");
}
}
else if (!isDnsCompatibleBucketName(bucket) ||
(bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:")) ||
bucket.toLowerCase() !== bucket ||
bucket.length < 3) {
endpointParams.ForcePathStyle = true;
}
if (endpointParams.DisableMultiRegionAccessPoints) {
endpointParams.disableMultiRegionAccessPoints = true;
endpointParams.DisableMRAP = true;
}
return endpointParams;
};
const DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/;
const IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/;
const DOTS_PATTERN = /\.\./;
const isDnsCompatibleBucketName = (bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName);
const isArnBucketName = (bucketName) => {
const [arn, partition, service, , , bucket] = bucketName.split(":");
const isArn = arn === "arn" && bucketName.split(":").length >= 6;
const isValidArn = Boolean(isArn && partition && service && bucket);
if (isArn && !isValidArn) {
throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`);
}
return isValidArn;
};
const createConfigValueProvider = (configKey, canonicalEndpointParamKey, config, isClientContextParam = false) => {
const configProvider = async () => {
let configValue;
if (isClientContextParam) {
const clientContextParams = config.clientContextParams;
const nestedValue = clientContextParams?.[configKey];
configValue = nestedValue ?? config[configKey] ?? config[canonicalEndpointParamKey];
}
else {
configValue = config[configKey] ?? config[canonicalEndpointParamKey];
}
if (typeof configValue === "function") {
return configValue();
}
return configValue;
};
if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.credentialScope ?? credentials?.CredentialScope;
return configValue;
};
}
if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.accountId ?? credentials?.AccountId;
return configValue;
};
}
if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") {
return async () => {
if (config.isCustomEndpoint === false) {
return undefined;
}
const endpoint = await configProvider();
if (endpoint && typeof endpoint === "object") {
if ("url" in endpoint) {
return endpoint.url.href;
}
if ("hostname" in endpoint) {
const { protocol, hostname, port, path } = endpoint;
return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`;
}
}
return endpoint;
};
}
return configProvider;
};
function bindGetEndpointFromInstructions(getEndpointFromConfig) {
return async (commandInput, instructionsSupplier, clientConfig, context) => {
if (!clientConfig.isCustomEndpoint) {
let endpointFromConfig;
if (clientConfig.serviceConfiguredEndpoint) {
endpointFromConfig = await clientConfig.serviceConfiguredEndpoint();
}
else {
endpointFromConfig = await getEndpointFromConfig(clientConfig.serviceId);
}
if (endpointFromConfig) {
clientConfig.endpoint = () => Promise.resolve(transport.toEndpointV1(endpointFromConfig));
clientConfig.isCustomEndpoint = true;
}
}
const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig);
if (typeof clientConfig.endpointProvider !== "function") {
throw new Error("config.endpointProvider is not set.");
}
const endpoint = clientConfig.endpointProvider(endpointParams, context);
if (clientConfig.isCustomEndpoint && clientConfig.endpoint) {
const customEndpoint = await clientConfig.endpoint();
if (customEndpoint?.headers) {
endpoint.headers ??= {};
for (const [name, value] of Object.entries(customEndpoint.headers)) {
endpoint.headers[name] = Array.isArray(value) ? value : [value];
}
}
}
return endpoint;
};
}
const resolveParams = async (commandInput, instructionsSupplier, clientConfig) => {
const endpointParams = {};
const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {};
for (const [name, instruction] of Object.entries(instructions)) {
switch (instruction.type) {
case "staticContextParams":
endpointParams[name] = instruction.value;
break;
case "contextParams":
endpointParams[name] = commandInput[instruction.name];
break;
case "clientContextParams":
case "builtInParams":
endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig, instruction.type !== "builtInParams")();
break;
case "operationContextParams":
endpointParams[name] = instruction.get(commandInput);
break;
default:
throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction));
}
}
if (Object.keys(instructions).length === 0) {
Object.assign(endpointParams, clientConfig);
}
if (String(clientConfig.serviceId).toLowerCase() === "s3") {
await resolveParamsForS3(endpointParams);
}
return endpointParams;
};
function setFeature(context, feature, value) {
if (!context.__smithy_context) {
context.__smithy_context = { features: {} };
}
else if (!context.__smithy_context.features) {
context.__smithy_context.features = {};
}
context.__smithy_context.features[feature] = value;
}
function bindEndpointMiddleware(getEndpointFromConfig) {
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
return ({ config, instructions, }) => {
return (next, context) => async (args) => {
if (config.isCustomEndpoint) {
setFeature(context, "ENDPOINT_OVERRIDE", "N");
}
const endpoint = await getEndpointFromInstructions(args.input, {
getEndpointParameterInstructions() {
return instructions;
},
}, { ...config }, context);
context.endpointV2 = endpoint;
context.authSchemes = endpoint.properties?.authSchemes;
const authScheme = context.authSchemes?.[0];
if (authScheme) {
context["signing_region"] = authScheme.signingRegion;
context["signing_service"] = authScheme.signingName;
const smithyContext = client.getSmithyContext(context);
const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption;
if (httpAuthOption) {
httpAuthOption.signingProperties = Object.assign(httpAuthOption.signingProperties || {}, {
signing_region: authScheme.signingRegion,
signingRegion: authScheme.signingRegion,
signing_service: authScheme.signingName,
signingName: authScheme.signingName,
signingRegionSet: authScheme.signingRegionSet,
}, authScheme.properties);
}
}
return next({
...args,
});
};
};
}
const serializerMiddlewareOption = {
name: "serializerMiddleware"};
const endpointMiddlewareOptions = {
step: "serialize",
tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"],
name: "endpointV2Middleware",
override: true,
relation: "before",
toMiddleware: serializerMiddlewareOption.name,
};
function bindGetEndpointPlugin(getEndpointFromConfig) {
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
return (config, instructions) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(endpointMiddleware({
config,
instructions,
}), endpointMiddlewareOptions);
},
});
}
function bindResolveEndpointConfig(getEndpointFromConfig) {
return (input) => {
const tls = input.tls ?? true;
const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input;
const customEndpointProvider = endpoint != null ? async () => transport.toEndpointV1(await transport.normalizeProvider(endpoint)()) : undefined;
const isCustomEndpoint = !!endpoint;
const resolvedConfig = Object.assign(input, {
endpoint: customEndpointProvider,
tls,
isCustomEndpoint,
useDualstackEndpoint: transport.normalizeProvider(useDualstackEndpoint ?? false),
useFipsEndpoint: transport.normalizeProvider(useFipsEndpoint ?? false),
});
let configuredEndpointPromise = undefined;
resolvedConfig.serviceConfiguredEndpoint = async () => {
if (input.serviceId && !configuredEndpointPromise) {
configuredEndpointPromise = getEndpointFromConfig(input.serviceId);
}
return configuredEndpointPromise;
};
return resolvedConfig;
};
}
class BinaryDecisionDiagram {
nodes;
root;
conditions;
results;
constructor(bdd, root, conditions, results) {
this.nodes = bdd;
this.root = root;
this.conditions = conditions;
this.results = results;
}
static from(bdd, root, conditions, results) {
return new BinaryDecisionDiagram(bdd, root, conditions, results);
}
}
class EndpointCache {
capacity;
data = new Map();
parameters = [];
constructor({ size, params }) {
this.capacity = size ?? 50;
if (params) {
this.parameters = params;
}
}
get(endpointParams, resolver) {
const key = this.hash(endpointParams);
if (key === false) {
return resolver();
}
if (!this.data.has(key)) {
if (this.data.size > this.capacity + 10) {
const keys = this.data.keys();
let i = 0;
while (true) {
const { value, done } = keys.next();
this.data.delete(value);
if (done || ++i > 10) {
break;
}
}
}
this.data.set(key, resolver());
}
return this.data.get(key);
}
size() {
return this.data.size;
}
hash(endpointParams) {
let buffer = "";
const { parameters } = this;
if (parameters.length === 0) {
return false;
}
for (const param of parameters) {
const val = String(endpointParams[param] ?? "");
if (val.includes("|;")) {
return false;
}
buffer += val + "|;";
}
return buffer;
}
}
class EndpointError extends Error {
constructor(message) {
super(message);
this.name = "EndpointError";
}
}
const debugId = "endpoints";
function toDebugString(input) {
if (typeof input !== "object" || input == null) {
return input;
}
if ("ref" in input) {
return `$${toDebugString(input.ref)}`;
}
if ("fn" in input) {
return `${input.fn}(${(input.argv || []).map(toDebugString).join(", ")})`;
}
return JSON.stringify(input, null, 2);
}
const customEndpointFunctions = {};
const booleanEquals = (value1, value2) => value1 === value2;
function coalesce(...args) {
for (const arg of args) {
if (arg != null) {
return arg;
}
}
return undefined;
}
const getAttrPathList = (path) => {
const parts = path.split(".");
const pathList = [];
for (const part of parts) {
const squareBracketIndex = part.indexOf("[");
if (squareBracketIndex !== -1) {
if (part.indexOf("]") !== part.length - 1) {
throw new EndpointError(`Path: '${path}' does not end with ']'`);
}
const arrayIndex = part.slice(squareBracketIndex + 1, -1);
if (Number.isNaN(parseInt(arrayIndex))) {
throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path}'`);
}
if (squareBracketIndex !== 0) {
pathList.push(part.slice(0, squareBracketIndex));
}
pathList.push(arrayIndex);
}
else {
pathList.push(part);
}
}
return pathList;
};
const getAttr = (value, path) => getAttrPathList(path).reduce((acc, index) => {
if (typeof acc !== "object") {
throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`);
}
else if (Array.isArray(acc)) {
const i = parseInt(index);
return acc[i < 0 ? acc.length + i : i];
}
return acc[index];
}, value);
const isSet = (value) => value != null;
function ite(condition, trueValue, falseValue) {
return condition ? trueValue : falseValue;
}
const not = (value) => !value;
const IP_V4_REGEX = new RegExp(`^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$`);
const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
const DEFAULT_PORTS = {
[types.EndpointURLScheme.HTTP]: 80,
[types.EndpointURLScheme.HTTPS]: 443,
};
const parseURL = (value) => {
const whatwgURL = (() => {
try {
if (value instanceof URL) {
return value;
}
if (typeof value === "object" && "hostname" in value) {
const { hostname, port, protocol = "", path = "", query = {} } = value;
const url = new URL(`${protocol}//${hostname}${port ? `:${port}` : ""}${path}`);
url.search = Object.entries(query)
.map(([k, v]) => `${k}=${v}`)
.join("&");
return url;
}
return new URL(value);
}
catch (error) {
return null;
}
})();
if (!whatwgURL) {
console.error(`Unable to parse ${JSON.stringify(value)} as a whatwg URL.`);
return null;
}
const urlString = whatwgURL.href;
const { host, hostname, pathname, protocol, search } = whatwgURL;
if (search) {
return null;
}
const scheme = protocol.slice(0, -1);
if (!Object.values(types.EndpointURLScheme).includes(scheme)) {
return null;
}
const isIp = isIpAddress(hostname);
const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) ||
(typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`));
const authority = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`;
return {
scheme,
authority,
path: pathname,
normalizedPath: pathname.endsWith("/") ? pathname : `${pathname}/`,
isIp,
};
};
function split(value, delimiter, limit) {
if (limit === 1) {
return [value];
}
if (value === "") {
return [""];
}
const parts = value.split(delimiter);
if (limit === 0) {
return parts;
}
return parts.slice(0, limit - 1).concat(parts.slice(1).join(delimiter));
}
const stringEquals = (value1, value2) => value1 === value2;
const substring = (input, start, stop, reverse) => {
if (input == null || start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
return null;
}
if (!reverse) {
return input.substring(start, stop);
}
return input.substring(input.length - stop, input.length - start);
};
const uriEncode = (value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
const endpointFunctions = {
booleanEquals,
coalesce,
getAttr,
isSet,
isValidHostLabel: transport.isValidHostLabel,
ite,
not,
parseURL,
split,
stringEquals,
substring,
uriEncode,
};
const evaluateTemplate = (template, options) => {
const evaluatedTemplateArr = [];
const { referenceRecord, endpointParams } = options;
let currentIndex = 0;
while (currentIndex < template.length) {
const openingBraceIndex = template.indexOf("{", currentIndex);
if (openingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(currentIndex));
break;
}
evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex));
const closingBraceIndex = template.indexOf("}", openingBraceIndex);
if (closingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(openingBraceIndex));
break;
}
if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") {
evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex));
currentIndex = closingBraceIndex + 2;
}
const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex);
if (parameterName.includes("#")) {
const [refName, attrName] = parameterName.split("#");
evaluatedTemplateArr.push(getAttr((referenceRecord[refName] ?? endpointParams[refName]), attrName));
}
else {
evaluatedTemplateArr.push((referenceRecord[parameterName] ?? endpointParams[parameterName]));
}
currentIndex = closingBraceIndex + 1;
}
return evaluatedTemplateArr.join("");
};
const getReferenceValue = ({ ref }, options) => {
return options.referenceRecord[ref] ?? options.endpointParams[ref];
};
const evaluateExpression = (obj, keyName, options) => {
if (typeof obj === "string") {
return evaluateTemplate(obj, options);
}
else if (obj["fn"]) {
return group$2.callFunction(obj, options);
}
else if (obj["ref"]) {
return getReferenceValue(obj, options);
}
throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
};
const callFunction = ({ fn, argv }, options) => {
const evaluatedArgs = Array(argv.length);
for (let i = 0; i < evaluatedArgs.length; ++i) {
const arg = argv[i];
if (typeof arg === "boolean" || typeof arg === "number") {
evaluatedArgs[i] = arg;
}
else {
evaluatedArgs[i] = group$2.evaluateExpression(arg, "arg", options);
}
}
const namespaceSeparatorIndex = fn.indexOf(".");
if (namespaceSeparatorIndex !== -1) {
const namespaceFunctions = customEndpointFunctions[fn.slice(0, namespaceSeparatorIndex)];
const customFunction = namespaceFunctions?.[fn.slice(namespaceSeparatorIndex + 1)];
if (typeof customFunction === "function") {
return customFunction(...evaluatedArgs);
}
}
const callable = endpointFunctions[fn];
if (typeof callable === "function") {
return callable(...evaluatedArgs);
}
throw new Error(`function ${fn} not loaded in endpointFunctions.`);
};
const group$2 = {
evaluateExpression,
callFunction,
};
const evaluateCondition = (condition, options) => {
const { assign } = condition;
if (assign && assign in options.referenceRecord) {
throw new EndpointError(`'${assign}' is already defined in Reference Record.`);
}
const value = callFunction(condition, options);
options.logger?.debug?.(`${debugId} evaluateCondition: ${toDebugString(condition)} = ${toDebugString(value)}`);
const result = value === "" ? true : !!value;
if (assign != null) {
return { result, toAssign: { name: assign, value } };
}
return { result };
};
const getEndpointHeaders = (headers, options) => Object.entries(headers ?? {}).reduce((acc, [headerKey, headerVal]) => {
acc[headerKey] = headerVal.map((headerValEntry) => {
const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options);
if (typeof processedExpr !== "string") {
throw new EndpointError(`Header '${headerKey}' value '${processedExpr}' is not a string`);
}
return processedExpr;
});
return acc;
}, {});
const getEndpointProperties = (properties, options) => Object.entries(properties).reduce((acc, [propertyKey, propertyVal]) => {
acc[propertyKey] = group$1.getEndpointProperty(propertyVal, options);
return acc;
}, {});
const getEndpointProperty = (property, options) => {
if (Array.isArray(property)) {
return property.map((propertyEntry) => getEndpointProperty(propertyEntry, options));
}
switch (typeof property) {
case "string":
return evaluateTemplate(property, options);
case "object":
if (property === null) {
throw new EndpointError(`Unexpected endpoint property: ${property}`);
}
return group$1.getEndpointProperties(property, options);
case "boolean":
return property;
default:
throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`);
}
};
const group$1 = {
getEndpointProperty,
getEndpointProperties,
};
const getEndpointUrl = (endpointUrl, options) => {
const expression = evaluateExpression(endpointUrl, "Endpoint URL", options);
if (typeof expression === "string") {
try {
return new URL(expression);
}
catch (error) {
console.error(`Failed to construct URL with ${expression}`, error);
throw error;
}
}
throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`);
};
const RESULT = 100_000_000;
const decideEndpoint = (bdd, options) => {
const { nodes, root, results, conditions } = bdd;
let ref = root;
const referenceRecord = {};
const closure = {
referenceRecord,
endpointParams: options.endpointParams,
logger: options.logger,
};
while (ref !== 1 && ref !== -1 && ref < RESULT) {
const node_i = 3 * (Math.abs(ref) - 1);
const [condition_i, highRef, lowRef] = [nodes[node_i], nodes[node_i + 1], nodes[node_i + 2]];
const [fn, argv, assign] = conditions[condition_i];
const evaluation = evaluateCondition({ fn, assign, argv }, closure);
if (evaluation.toAssign) {
const { name, value } = evaluation.toAssign;
referenceRecord[name] = value;
}
ref = ref >= 0 === evaluation.result ? highRef : lowRef;
}
if (ref >= RESULT) {
const result = results[ref - RESULT];
if (result[0] === -1) {
const [, errorExpression] = result;
throw new EndpointError(evaluateExpression(errorExpression, "Error", closure));
}
const [url, properties, headers] = result;
return {
url: getEndpointUrl(url, closure),
properties: getEndpointProperties(properties, closure),
headers: getEndpointHeaders(headers ?? {}, closure),
};
}
throw new EndpointError(`No matching endpoint.`);
};
const evaluateConditions = (conditions = [], options) => {
const conditionsReferenceRecord = {};
const conditionOptions = {
...options,
referenceRecord: { ...options.referenceRecord },
};
let didAssign = false;
for (const condition of conditions) {
const { result, toAssign } = evaluateCondition(condition, conditionOptions);
if (!result) {
return { result };
}
if (toAssign) {
didAssign = true;
conditionsReferenceRecord[toAssign.name] = toAssign.value;
conditionOptions.referenceRecord[toAssign.name] = toAssign.value;
options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`);
}
}
if (didAssign) {
return { result: true, referenceRecord: conditionsReferenceRecord };
}
return { result: true };
};
const evaluateEndpointRule = (endpointRule, options) => {
const { conditions, endpoint } = endpointRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const endpointRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
const { url, properties, headers } = endpoint;
options.logger?.debug?.(`${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`);
const endpointToReturn = { url: getEndpointUrl(url, endpointRuleOptions) };
if (headers != null) {
endpointToReturn.headers = getEndpointHeaders(headers, endpointRuleOptions);
}
if (properties != null) {
endpointToReturn.properties = getEndpointProperties(properties, endpointRuleOptions);
}
return endpointToReturn;
};
const evaluateErrorRule = (errorRule, options) => {
const { conditions, error } = errorRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const errorRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
throw new EndpointError(evaluateExpression(error, "Error", errorRuleOptions));
};
const evaluateRules = (rules, options) => {
for (const rule of rules) {
if (rule.type === "endpoint") {
const endpointOrUndefined = evaluateEndpointRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else if (rule.type === "error") {
evaluateErrorRule(rule, options);
}
else if (rule.type === "tree") {
const endpointOrUndefined = group.evaluateTreeRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else {
throw new EndpointError(`Unknown endpoint rule: ${rule}`);
}
}
throw new EndpointError(`Rules evaluation failed`);
};
const evaluateTreeRule = (treeRule, options) => {
const { conditions, rules } = treeRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const treeRuleOptions = referenceRecord
? { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }
: options;
return group.evaluateRules(rules, treeRuleOptions);
};
const group = {
evaluateRules,
evaluateTreeRule,
};
const resolveEndpoint = (ruleSetObject, options) => {
const { endpointParams, logger } = options;
const { parameters, rules } = ruleSetObject;
options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
for (const paramKey in parameters) {
const parameter = parameters[paramKey];
const endpointParam = endpointParams[paramKey];
if (endpointParam == null && parameter.default != null) {
endpointParams[paramKey] = parameter.default;
continue;
}
if (parameter.required && endpointParam == null) {
throw new EndpointError(`Missing required parameter: '${paramKey}'`);
}
}
const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} });
options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`);
return endpoint;
};
const resolveEndpointRequiredConfig = (input) => {
const { endpoint } = input;
if (endpoint === undefined) {
input.endpoint = async () => {
throw new Error("@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint.");
};
}
return input;
};
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
const resolveEndpointConfig = bindResolveEndpointConfig(getEndpointFromConfig);
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
const getEndpointPlugin = bindGetEndpointPlugin(getEndpointFromConfig);
exports.isValidHostLabel = transport.isValidHostLabel;
exports.middlewareEndpointToEndpointV1 = transport.toEndpointV1;
exports.toEndpointV1 = transport.toEndpointV1;
exports.BinaryDecisionDiagram = BinaryDecisionDiagram;
exports.EndpointCache = EndpointCache;
exports.EndpointError = EndpointError;
exports.customEndpointFunctions = customEndpointFunctions;
exports.decideEndpoint = decideEndpoint;
exports.endpointMiddleware = endpointMiddleware;
exports.endpointMiddlewareOptions = endpointMiddlewareOptions;
exports.getEndpointFromInstructions = getEndpointFromInstructions;
exports.getEndpointPlugin = getEndpointPlugin;
exports.isIpAddress = isIpAddress;
exports.resolveEndpoint = resolveEndpoint;
exports.resolveEndpointConfig = resolveEndpointConfig;
exports.resolveEndpointRequiredConfig = resolveEndpointRequiredConfig;
exports.resolveParams = resolveParams;
+861
View File
@@ -0,0 +1,861 @@
'use strict';
var config = require('@smithy/core/config');
var transport = require('@smithy/core/transport');
var client = require('@smithy/core/client');
var types = require('@smithy/types');
const ENV_ENDPOINT_URL = "AWS_ENDPOINT_URL";
const CONFIG_ENDPOINT_URL = "endpoint_url";
const getEndpointUrlConfig = (serviceId) => ({
environmentVariableSelector: (env) => {
const serviceSuffixParts = serviceId.split(" ").map((w) => w.toUpperCase());
const serviceEndpointUrl = env[[ENV_ENDPOINT_URL, ...serviceSuffixParts].join("_")];
if (serviceEndpointUrl)
return serviceEndpointUrl;
const endpointUrl = env[ENV_ENDPOINT_URL];
if (endpointUrl)
return endpointUrl;
return undefined;
},
configFileSelector: (profile, config$1) => {
if (config$1 && profile.services) {
const servicesSection = config$1[["services", profile.services].join(config.CONFIG_PREFIX_SEPARATOR)];
if (servicesSection) {
const servicePrefixParts = serviceId.split(" ").map((w) => w.toLowerCase());
const endpointUrl = servicesSection[[servicePrefixParts.join("_"), CONFIG_ENDPOINT_URL].join(config.CONFIG_PREFIX_SEPARATOR)];
if (endpointUrl)
return endpointUrl;
}
}
const endpointUrl = profile[CONFIG_ENDPOINT_URL];
if (endpointUrl)
return endpointUrl;
return undefined;
},
default: undefined,
});
const getEndpointFromConfig = async (serviceId) => config.loadConfig(getEndpointUrlConfig(serviceId ?? ""))();
const resolveParamsForS3 = async (endpointParams) => {
const bucket = endpointParams?.Bucket || "";
if (typeof endpointParams.Bucket === "string") {
endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?"));
}
if (isArnBucketName(bucket)) {
if (endpointParams.ForcePathStyle === true) {
throw new Error("Path-style addressing cannot be used with ARN buckets");
}
}
else if (!isDnsCompatibleBucketName(bucket) ||
(bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:")) ||
bucket.toLowerCase() !== bucket ||
bucket.length < 3) {
endpointParams.ForcePathStyle = true;
}
if (endpointParams.DisableMultiRegionAccessPoints) {
endpointParams.disableMultiRegionAccessPoints = true;
endpointParams.DisableMRAP = true;
}
return endpointParams;
};
const DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/;
const IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/;
const DOTS_PATTERN = /\.\./;
const isDnsCompatibleBucketName = (bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName);
const isArnBucketName = (bucketName) => {
const [arn, partition, service, , , bucket] = bucketName.split(":");
const isArn = arn === "arn" && bucketName.split(":").length >= 6;
const isValidArn = Boolean(isArn && partition && service && bucket);
if (isArn && !isValidArn) {
throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`);
}
return isValidArn;
};
const createConfigValueProvider = (configKey, canonicalEndpointParamKey, config, isClientContextParam = false) => {
const configProvider = async () => {
let configValue;
if (isClientContextParam) {
const clientContextParams = config.clientContextParams;
const nestedValue = clientContextParams?.[configKey];
configValue = nestedValue ?? config[configKey] ?? config[canonicalEndpointParamKey];
}
else {
configValue = config[configKey] ?? config[canonicalEndpointParamKey];
}
if (typeof configValue === "function") {
return configValue();
}
return configValue;
};
if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.credentialScope ?? credentials?.CredentialScope;
return configValue;
};
}
if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.accountId ?? credentials?.AccountId;
return configValue;
};
}
if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") {
return async () => {
if (config.isCustomEndpoint === false) {
return undefined;
}
const endpoint = await configProvider();
if (endpoint && typeof endpoint === "object") {
if ("url" in endpoint) {
return endpoint.url.href;
}
if ("hostname" in endpoint) {
const { protocol, hostname, port, path } = endpoint;
return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`;
}
}
return endpoint;
};
}
return configProvider;
};
function bindGetEndpointFromInstructions(getEndpointFromConfig) {
return async (commandInput, instructionsSupplier, clientConfig, context) => {
if (!clientConfig.isCustomEndpoint) {
let endpointFromConfig;
if (clientConfig.serviceConfiguredEndpoint) {
endpointFromConfig = await clientConfig.serviceConfiguredEndpoint();
}
else {
endpointFromConfig = await getEndpointFromConfig(clientConfig.serviceId);
}
if (endpointFromConfig) {
clientConfig.endpoint = () => Promise.resolve(transport.toEndpointV1(endpointFromConfig));
clientConfig.isCustomEndpoint = true;
}
}
const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig);
if (typeof clientConfig.endpointProvider !== "function") {
throw new Error("config.endpointProvider is not set.");
}
const endpoint = clientConfig.endpointProvider(endpointParams, context);
if (clientConfig.isCustomEndpoint && clientConfig.endpoint) {
const customEndpoint = await clientConfig.endpoint();
if (customEndpoint?.headers) {
endpoint.headers ??= {};
for (const [name, value] of Object.entries(customEndpoint.headers)) {
endpoint.headers[name] = Array.isArray(value) ? value : [value];
}
}
}
return endpoint;
};
}
const resolveParams = async (commandInput, instructionsSupplier, clientConfig) => {
const endpointParams = {};
const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {};
for (const [name, instruction] of Object.entries(instructions)) {
switch (instruction.type) {
case "staticContextParams":
endpointParams[name] = instruction.value;
break;
case "contextParams":
endpointParams[name] = commandInput[instruction.name];
break;
case "clientContextParams":
case "builtInParams":
endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig, instruction.type !== "builtInParams")();
break;
case "operationContextParams":
endpointParams[name] = instruction.get(commandInput);
break;
default:
throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction));
}
}
if (Object.keys(instructions).length === 0) {
Object.assign(endpointParams, clientConfig);
}
if (String(clientConfig.serviceId).toLowerCase() === "s3") {
await resolveParamsForS3(endpointParams);
}
return endpointParams;
};
function setFeature(context, feature, value) {
if (!context.__smithy_context) {
context.__smithy_context = { features: {} };
}
else if (!context.__smithy_context.features) {
context.__smithy_context.features = {};
}
context.__smithy_context.features[feature] = value;
}
function bindEndpointMiddleware(getEndpointFromConfig) {
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
return ({ config, instructions, }) => {
return (next, context) => async (args) => {
if (config.isCustomEndpoint) {
setFeature(context, "ENDPOINT_OVERRIDE", "N");
}
const endpoint = await getEndpointFromInstructions(args.input, {
getEndpointParameterInstructions() {
return instructions;
},
}, { ...config }, context);
context.endpointV2 = endpoint;
context.authSchemes = endpoint.properties?.authSchemes;
const authScheme = context.authSchemes?.[0];
if (authScheme) {
context["signing_region"] = authScheme.signingRegion;
context["signing_service"] = authScheme.signingName;
const smithyContext = client.getSmithyContext(context);
const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption;
if (httpAuthOption) {
httpAuthOption.signingProperties = Object.assign(httpAuthOption.signingProperties || {}, {
signing_region: authScheme.signingRegion,
signingRegion: authScheme.signingRegion,
signing_service: authScheme.signingName,
signingName: authScheme.signingName,
signingRegionSet: authScheme.signingRegionSet,
}, authScheme.properties);
}
}
return next({
...args,
});
};
};
}
const serializerMiddlewareOption = {
name: "serializerMiddleware"};
const endpointMiddlewareOptions = {
step: "serialize",
tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"],
name: "endpointV2Middleware",
override: true,
relation: "before",
toMiddleware: serializerMiddlewareOption.name,
};
function bindGetEndpointPlugin(getEndpointFromConfig) {
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
return (config, instructions) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(endpointMiddleware({
config,
instructions,
}), endpointMiddlewareOptions);
},
});
}
function bindResolveEndpointConfig(getEndpointFromConfig) {
return (input) => {
const tls = input.tls ?? true;
const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input;
const customEndpointProvider = endpoint != null ? async () => transport.toEndpointV1(await transport.normalizeProvider(endpoint)()) : undefined;
const isCustomEndpoint = !!endpoint;
const resolvedConfig = Object.assign(input, {
endpoint: customEndpointProvider,
tls,
isCustomEndpoint,
useDualstackEndpoint: transport.normalizeProvider(useDualstackEndpoint ?? false),
useFipsEndpoint: transport.normalizeProvider(useFipsEndpoint ?? false),
});
let configuredEndpointPromise = undefined;
resolvedConfig.serviceConfiguredEndpoint = async () => {
if (input.serviceId && !configuredEndpointPromise) {
configuredEndpointPromise = getEndpointFromConfig(input.serviceId);
}
return configuredEndpointPromise;
};
return resolvedConfig;
};
}
class BinaryDecisionDiagram {
nodes;
root;
conditions;
results;
constructor(bdd, root, conditions, results) {
this.nodes = bdd;
this.root = root;
this.conditions = conditions;
this.results = results;
}
static from(bdd, root, conditions, results) {
return new BinaryDecisionDiagram(bdd, root, conditions, results);
}
}
class EndpointCache {
capacity;
data = new Map();
parameters = [];
constructor({ size, params }) {
this.capacity = size ?? 50;
if (params) {
this.parameters = params;
}
}
get(endpointParams, resolver) {
const key = this.hash(endpointParams);
if (key === false) {
return resolver();
}
if (!this.data.has(key)) {
if (this.data.size > this.capacity + 10) {
const keys = this.data.keys();
let i = 0;
while (true) {
const { value, done } = keys.next();
this.data.delete(value);
if (done || ++i > 10) {
break;
}
}
}
this.data.set(key, resolver());
}
return this.data.get(key);
}
size() {
return this.data.size;
}
hash(endpointParams) {
let buffer = "";
const { parameters } = this;
if (parameters.length === 0) {
return false;
}
for (const param of parameters) {
const val = String(endpointParams[param] ?? "");
if (val.includes("|;")) {
return false;
}
buffer += val + "|;";
}
return buffer;
}
}
class EndpointError extends Error {
constructor(message) {
super(message);
this.name = "EndpointError";
}
}
const debugId = "endpoints";
function toDebugString(input) {
if (typeof input !== "object" || input == null) {
return input;
}
if ("ref" in input) {
return `$${toDebugString(input.ref)}`;
}
if ("fn" in input) {
return `${input.fn}(${(input.argv || []).map(toDebugString).join(", ")})`;
}
return JSON.stringify(input, null, 2);
}
const customEndpointFunctions = {};
const booleanEquals = (value1, value2) => value1 === value2;
function coalesce(...args) {
for (const arg of args) {
if (arg != null) {
return arg;
}
}
return undefined;
}
const getAttrPathList = (path) => {
const parts = path.split(".");
const pathList = [];
for (const part of parts) {
const squareBracketIndex = part.indexOf("[");
if (squareBracketIndex !== -1) {
if (part.indexOf("]") !== part.length - 1) {
throw new EndpointError(`Path: '${path}' does not end with ']'`);
}
const arrayIndex = part.slice(squareBracketIndex + 1, -1);
if (Number.isNaN(parseInt(arrayIndex))) {
throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path}'`);
}
if (squareBracketIndex !== 0) {
pathList.push(part.slice(0, squareBracketIndex));
}
pathList.push(arrayIndex);
}
else {
pathList.push(part);
}
}
return pathList;
};
const getAttr = (value, path) => getAttrPathList(path).reduce((acc, index) => {
if (typeof acc !== "object") {
throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`);
}
else if (Array.isArray(acc)) {
const i = parseInt(index);
return acc[i < 0 ? acc.length + i : i];
}
return acc[index];
}, value);
const isSet = (value) => value != null;
function ite(condition, trueValue, falseValue) {
return condition ? trueValue : falseValue;
}
const not = (value) => !value;
const IP_V4_REGEX = new RegExp(`^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$`);
const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
const DEFAULT_PORTS = {
[types.EndpointURLScheme.HTTP]: 80,
[types.EndpointURLScheme.HTTPS]: 443,
};
const parseURL = (value) => {
const whatwgURL = (() => {
try {
if (value instanceof URL) {
return value;
}
if (typeof value === "object" && "hostname" in value) {
const { hostname, port, protocol = "", path = "", query = {} } = value;
const url = new URL(`${protocol}//${hostname}${port ? `:${port}` : ""}${path}`);
url.search = Object.entries(query)
.map(([k, v]) => `${k}=${v}`)
.join("&");
return url;
}
return new URL(value);
}
catch (error) {
return null;
}
})();
if (!whatwgURL) {
console.error(`Unable to parse ${JSON.stringify(value)} as a whatwg URL.`);
return null;
}
const urlString = whatwgURL.href;
const { host, hostname, pathname, protocol, search } = whatwgURL;
if (search) {
return null;
}
const scheme = protocol.slice(0, -1);
if (!Object.values(types.EndpointURLScheme).includes(scheme)) {
return null;
}
const isIp = isIpAddress(hostname);
const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) ||
(typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`));
const authority = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`;
return {
scheme,
authority,
path: pathname,
normalizedPath: pathname.endsWith("/") ? pathname : `${pathname}/`,
isIp,
};
};
function split(value, delimiter, limit) {
if (limit === 1) {
return [value];
}
if (value === "") {
return [""];
}
const parts = value.split(delimiter);
if (limit === 0) {
return parts;
}
return parts.slice(0, limit - 1).concat(parts.slice(1).join(delimiter));
}
const stringEquals = (value1, value2) => value1 === value2;
const substring = (input, start, stop, reverse) => {
if (input == null || start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
return null;
}
if (!reverse) {
return input.substring(start, stop);
}
return input.substring(input.length - stop, input.length - start);
};
const uriEncode = (value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
const endpointFunctions = {
booleanEquals,
coalesce,
getAttr,
isSet,
isValidHostLabel: transport.isValidHostLabel,
ite,
not,
parseURL,
split,
stringEquals,
substring,
uriEncode,
};
const evaluateTemplate = (template, options) => {
const evaluatedTemplateArr = [];
const { referenceRecord, endpointParams } = options;
let currentIndex = 0;
while (currentIndex < template.length) {
const openingBraceIndex = template.indexOf("{", currentIndex);
if (openingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(currentIndex));
break;
}
evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex));
const closingBraceIndex = template.indexOf("}", openingBraceIndex);
if (closingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(openingBraceIndex));
break;
}
if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") {
evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex));
currentIndex = closingBraceIndex + 2;
}
const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex);
if (parameterName.includes("#")) {
const [refName, attrName] = parameterName.split("#");
evaluatedTemplateArr.push(getAttr((referenceRecord[refName] ?? endpointParams[refName]), attrName));
}
else {
evaluatedTemplateArr.push((referenceRecord[parameterName] ?? endpointParams[parameterName]));
}
currentIndex = closingBraceIndex + 1;
}
return evaluatedTemplateArr.join("");
};
const getReferenceValue = ({ ref }, options) => {
return options.referenceRecord[ref] ?? options.endpointParams[ref];
};
const evaluateExpression = (obj, keyName, options) => {
if (typeof obj === "string") {
return evaluateTemplate(obj, options);
}
else if (obj["fn"]) {
return group$2.callFunction(obj, options);
}
else if (obj["ref"]) {
return getReferenceValue(obj, options);
}
throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
};
const callFunction = ({ fn, argv }, options) => {
const evaluatedArgs = Array(argv.length);
for (let i = 0; i < evaluatedArgs.length; ++i) {
const arg = argv[i];
if (typeof arg === "boolean" || typeof arg === "number") {
evaluatedArgs[i] = arg;
}
else {
evaluatedArgs[i] = group$2.evaluateExpression(arg, "arg", options);
}
}
const namespaceSeparatorIndex = fn.indexOf(".");
if (namespaceSeparatorIndex !== -1) {
const namespaceFunctions = customEndpointFunctions[fn.slice(0, namespaceSeparatorIndex)];
const customFunction = namespaceFunctions?.[fn.slice(namespaceSeparatorIndex + 1)];
if (typeof customFunction === "function") {
return customFunction(...evaluatedArgs);
}
}
const callable = endpointFunctions[fn];
if (typeof callable === "function") {
return callable(...evaluatedArgs);
}
throw new Error(`function ${fn} not loaded in endpointFunctions.`);
};
const group$2 = {
evaluateExpression,
callFunction,
};
const evaluateCondition = (condition, options) => {
const { assign } = condition;
if (assign && assign in options.referenceRecord) {
throw new EndpointError(`'${assign}' is already defined in Reference Record.`);
}
const value = callFunction(condition, options);
options.logger?.debug?.(`${debugId} evaluateCondition: ${toDebugString(condition)} = ${toDebugString(value)}`);
const result = value === "" ? true : !!value;
if (assign != null) {
return { result, toAssign: { name: assign, value } };
}
return { result };
};
const getEndpointHeaders = (headers, options) => Object.entries(headers ?? {}).reduce((acc, [headerKey, headerVal]) => {
acc[headerKey] = headerVal.map((headerValEntry) => {
const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options);
if (typeof processedExpr !== "string") {
throw new EndpointError(`Header '${headerKey}' value '${processedExpr}' is not a string`);
}
return processedExpr;
});
return acc;
}, {});
const getEndpointProperties = (properties, options) => Object.entries(properties).reduce((acc, [propertyKey, propertyVal]) => {
acc[propertyKey] = group$1.getEndpointProperty(propertyVal, options);
return acc;
}, {});
const getEndpointProperty = (property, options) => {
if (Array.isArray(property)) {
return property.map((propertyEntry) => getEndpointProperty(propertyEntry, options));
}
switch (typeof property) {
case "string":
return evaluateTemplate(property, options);
case "object":
if (property === null) {
throw new EndpointError(`Unexpected endpoint property: ${property}`);
}
return group$1.getEndpointProperties(property, options);
case "boolean":
return property;
default:
throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`);
}
};
const group$1 = {
getEndpointProperty,
getEndpointProperties,
};
const getEndpointUrl = (endpointUrl, options) => {
const expression = evaluateExpression(endpointUrl, "Endpoint URL", options);
if (typeof expression === "string") {
try {
return new URL(expression);
}
catch (error) {
console.error(`Failed to construct URL with ${expression}`, error);
throw error;
}
}
throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`);
};
const RESULT = 100_000_000;
const decideEndpoint = (bdd, options) => {
const { nodes, root, results, conditions } = bdd;
let ref = root;
const referenceRecord = {};
const closure = {
referenceRecord,
endpointParams: options.endpointParams,
logger: options.logger,
};
while (ref !== 1 && ref !== -1 && ref < RESULT) {
const node_i = 3 * (Math.abs(ref) - 1);
const [condition_i, highRef, lowRef] = [nodes[node_i], nodes[node_i + 1], nodes[node_i + 2]];
const [fn, argv, assign] = conditions[condition_i];
const evaluation = evaluateCondition({ fn, assign, argv }, closure);
if (evaluation.toAssign) {
const { name, value } = evaluation.toAssign;
referenceRecord[name] = value;
}
ref = ref >= 0 === evaluation.result ? highRef : lowRef;
}
if (ref >= RESULT) {
const result = results[ref - RESULT];
if (result[0] === -1) {
const [, errorExpression] = result;
throw new EndpointError(evaluateExpression(errorExpression, "Error", closure));
}
const [url, properties, headers] = result;
return {
url: getEndpointUrl(url, closure),
properties: getEndpointProperties(properties, closure),
headers: getEndpointHeaders(headers ?? {}, closure),
};
}
throw new EndpointError(`No matching endpoint.`);
};
const evaluateConditions = (conditions = [], options) => {
const conditionsReferenceRecord = {};
const conditionOptions = {
...options,
referenceRecord: { ...options.referenceRecord },
};
let didAssign = false;
for (const condition of conditions) {
const { result, toAssign } = evaluateCondition(condition, conditionOptions);
if (!result) {
return { result };
}
if (toAssign) {
didAssign = true;
conditionsReferenceRecord[toAssign.name] = toAssign.value;
conditionOptions.referenceRecord[toAssign.name] = toAssign.value;
options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`);
}
}
if (didAssign) {
return { result: true, referenceRecord: conditionsReferenceRecord };
}
return { result: true };
};
const evaluateEndpointRule = (endpointRule, options) => {
const { conditions, endpoint } = endpointRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const endpointRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
const { url, properties, headers } = endpoint;
options.logger?.debug?.(`${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`);
const endpointToReturn = { url: getEndpointUrl(url, endpointRuleOptions) };
if (headers != null) {
endpointToReturn.headers = getEndpointHeaders(headers, endpointRuleOptions);
}
if (properties != null) {
endpointToReturn.properties = getEndpointProperties(properties, endpointRuleOptions);
}
return endpointToReturn;
};
const evaluateErrorRule = (errorRule, options) => {
const { conditions, error } = errorRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const errorRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
throw new EndpointError(evaluateExpression(error, "Error", errorRuleOptions));
};
const evaluateRules = (rules, options) => {
for (const rule of rules) {
if (rule.type === "endpoint") {
const endpointOrUndefined = evaluateEndpointRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else if (rule.type === "error") {
evaluateErrorRule(rule, options);
}
else if (rule.type === "tree") {
const endpointOrUndefined = group.evaluateTreeRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else {
throw new EndpointError(`Unknown endpoint rule: ${rule}`);
}
}
throw new EndpointError(`Rules evaluation failed`);
};
const evaluateTreeRule = (treeRule, options) => {
const { conditions, rules } = treeRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const treeRuleOptions = referenceRecord
? { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }
: options;
return group.evaluateRules(rules, treeRuleOptions);
};
const group = {
evaluateRules,
evaluateTreeRule,
};
const resolveEndpoint = (ruleSetObject, options) => {
const { endpointParams, logger } = options;
const { parameters, rules } = ruleSetObject;
options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
for (const paramKey in parameters) {
const parameter = parameters[paramKey];
const endpointParam = endpointParams[paramKey];
if (endpointParam == null && parameter.default != null) {
endpointParams[paramKey] = parameter.default;
continue;
}
if (parameter.required && endpointParam == null) {
throw new EndpointError(`Missing required parameter: '${paramKey}'`);
}
}
const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} });
options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`);
return endpoint;
};
const resolveEndpointRequiredConfig = (input) => {
const { endpoint } = input;
if (endpoint === undefined) {
input.endpoint = async () => {
throw new Error("@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint.");
};
}
return input;
};
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
const resolveEndpointConfig = bindResolveEndpointConfig(getEndpointFromConfig);
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
const getEndpointPlugin = bindGetEndpointPlugin(getEndpointFromConfig);
exports.isValidHostLabel = transport.isValidHostLabel;
exports.middlewareEndpointToEndpointV1 = transport.toEndpointV1;
exports.toEndpointV1 = transport.toEndpointV1;
exports.BinaryDecisionDiagram = BinaryDecisionDiagram;
exports.EndpointCache = EndpointCache;
exports.EndpointError = EndpointError;
exports.customEndpointFunctions = customEndpointFunctions;
exports.decideEndpoint = decideEndpoint;
exports.endpointMiddleware = endpointMiddleware;
exports.endpointMiddlewareOptions = endpointMiddlewareOptions;
exports.getEndpointFromInstructions = getEndpointFromInstructions;
exports.getEndpointPlugin = getEndpointPlugin;
exports.isIpAddress = isIpAddress;
exports.resolveEndpoint = resolveEndpoint;
exports.resolveEndpointConfig = resolveEndpointConfig;
exports.resolveEndpointRequiredConfig = resolveEndpointRequiredConfig;
exports.resolveParams = resolveParams;
@@ -0,0 +1,866 @@
'use strict';
var crc32 = require('@aws-crypto/crc32');
var serde = require('@smithy/core/serde');
class Int64 {
bytes;
constructor(bytes) {
this.bytes = bytes;
if (bytes.byteLength !== 8) {
throw new Error("Int64 buffers must be exactly 8 bytes");
}
}
static fromNumber(number) {
if (number > 9_223_372_036_854_775_807 || number < -9223372036854776e3) {
throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`);
}
const bytes = new Uint8Array(8);
for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) {
bytes[i] = remaining;
}
if (number < 0) {
negate(bytes);
}
return new Int64(bytes);
}
valueOf() {
const bytes = this.bytes.slice(0);
const negative = bytes[0] & 0b10000000;
if (negative) {
negate(bytes);
}
return parseInt(serde.toHex(bytes), 16) * (negative ? -1 : 1);
}
toString() {
return String(this.valueOf());
}
}
function negate(bytes) {
for (let i = 0; i < 8; i++) {
bytes[i] ^= 0xff;
}
for (let i = 7; i > -1; i--) {
bytes[i]++;
if (bytes[i] !== 0)
break;
}
}
class HeaderMarshaller {
toUtf8;
fromUtf8;
constructor(toUtf8, fromUtf8) {
this.toUtf8 = toUtf8;
this.fromUtf8 = fromUtf8;
}
format(headers) {
const chunks = [];
for (const headerName of Object.keys(headers)) {
const bytes = this.fromUtf8(headerName);
chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName]));
}
const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0));
let position = 0;
for (const chunk of chunks) {
out.set(chunk, position);
position += chunk.byteLength;
}
return out;
}
formatHeaderValue(header) {
switch (header.type) {
case "boolean":
return Uint8Array.from([header.value ? 0 : 1]);
case "byte":
return Uint8Array.from([2, header.value]);
case "short":
const shortView = new DataView(new ArrayBuffer(3));
shortView.setUint8(0, 3);
shortView.setInt16(1, header.value, false);
return new Uint8Array(shortView.buffer);
case "integer":
const intView = new DataView(new ArrayBuffer(5));
intView.setUint8(0, 4);
intView.setInt32(1, header.value, false);
return new Uint8Array(intView.buffer);
case "long":
const longBytes = new Uint8Array(9);
longBytes[0] = 5;
longBytes.set(header.value.bytes, 1);
return longBytes;
case "binary":
const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength));
binView.setUint8(0, 6);
binView.setUint16(1, header.value.byteLength, false);
const binBytes = new Uint8Array(binView.buffer);
binBytes.set(header.value, 3);
return binBytes;
case "string":
const utf8Bytes = this.fromUtf8(header.value);
const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength));
strView.setUint8(0, 7);
strView.setUint16(1, utf8Bytes.byteLength, false);
const strBytes = new Uint8Array(strView.buffer);
strBytes.set(utf8Bytes, 3);
return strBytes;
case "timestamp":
const tsBytes = new Uint8Array(9);
tsBytes[0] = 8;
tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1);
return tsBytes;
case "uuid":
if (!UUID_PATTERN.test(header.value)) {
throw new Error(`Invalid UUID received: ${header.value}`);
}
const uuidBytes = new Uint8Array(17);
uuidBytes[0] = 9;
uuidBytes.set(serde.fromHex(header.value.replace(/\-/g, "")), 1);
return uuidBytes;
}
}
parse(headers) {
const out = {};
let position = 0;
while (position < headers.byteLength) {
const nameLength = headers.getUint8(position++);
const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength));
position += nameLength;
switch (headers.getUint8(position++)) {
case 0:
out[name] = {
type: BOOLEAN_TAG,
value: true,
};
break;
case 1:
out[name] = {
type: BOOLEAN_TAG,
value: false,
};
break;
case 2:
out[name] = {
type: BYTE_TAG,
value: headers.getInt8(position++),
};
break;
case 3:
out[name] = {
type: SHORT_TAG,
value: headers.getInt16(position, false),
};
position += 2;
break;
case 4:
out[name] = {
type: INT_TAG,
value: headers.getInt32(position, false),
};
position += 4;
break;
case 5:
out[name] = {
type: LONG_TAG,
value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)),
};
position += 8;
break;
case 6:
const binaryLength = headers.getUint16(position, false);
position += 2;
out[name] = {
type: BINARY_TAG,
value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength),
};
position += binaryLength;
break;
case 7:
const stringLength = headers.getUint16(position, false);
position += 2;
out[name] = {
type: STRING_TAG,
value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength)),
};
position += stringLength;
break;
case 8:
out[name] = {
type: TIMESTAMP_TAG,
value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf()),
};
position += 8;
break;
case 9:
const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16);
position += 16;
out[name] = {
type: UUID_TAG,
value: `${serde.toHex(uuidBytes.subarray(0, 4))}-${serde.toHex(uuidBytes.subarray(4, 6))}-${serde.toHex(uuidBytes.subarray(6, 8))}-${serde.toHex(uuidBytes.subarray(8, 10))}-${serde.toHex(uuidBytes.subarray(10))}`,
};
break;
default:
throw new Error(`Unrecognized header type tag`);
}
}
return out;
}
}
var HEADER_VALUE_TYPE;
(function (HEADER_VALUE_TYPE) {
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["boolTrue"] = 0] = "boolTrue";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["boolFalse"] = 1] = "boolFalse";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["byte"] = 2] = "byte";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["short"] = 3] = "short";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["integer"] = 4] = "integer";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["long"] = 5] = "long";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["byteArray"] = 6] = "byteArray";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["string"] = 7] = "string";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["timestamp"] = 8] = "timestamp";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["uuid"] = 9] = "uuid";
})(HEADER_VALUE_TYPE || (HEADER_VALUE_TYPE = {}));
const BOOLEAN_TAG = "boolean";
const BYTE_TAG = "byte";
const SHORT_TAG = "short";
const INT_TAG = "integer";
const LONG_TAG = "long";
const BINARY_TAG = "binary";
const STRING_TAG = "string";
const TIMESTAMP_TAG = "timestamp";
const UUID_TAG = "uuid";
const UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
const PRELUDE_MEMBER_LENGTH = 4;
const PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2;
const CHECKSUM_LENGTH = 4;
const MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2;
function splitMessage({ byteLength, byteOffset, buffer }) {
if (byteLength < MINIMUM_MESSAGE_LENGTH) {
throw new Error("Provided message too short to accommodate event stream message overhead");
}
const view = new DataView(buffer, byteOffset, byteLength);
const messageLength = view.getUint32(0, false);
if (byteLength !== messageLength) {
throw new Error("Reported message length does not match received message length");
}
const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false);
const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false);
const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false);
const checksummer = new crc32.Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH));
if (expectedPreludeChecksum !== checksummer.digest()) {
throw new Error(`The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})`);
}
checksummer.update(new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)));
if (expectedMessageChecksum !== checksummer.digest()) {
throw new Error(`The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}`);
}
return {
headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength),
body: new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH)),
};
}
class EventStreamCodec {
headerMarshaller;
messageBuffer;
isEndOfStream;
constructor(toUtf8, fromUtf8) {
this.headerMarshaller = new HeaderMarshaller(toUtf8, fromUtf8);
this.messageBuffer = [];
this.isEndOfStream = false;
}
feed(message) {
this.messageBuffer.push(this.decode(message));
}
endOfStream() {
this.isEndOfStream = true;
}
getMessage() {
const message = this.messageBuffer.pop();
const isEndOfStream = this.isEndOfStream;
return {
getMessage() {
return message;
},
isEndOfStream() {
return isEndOfStream;
},
};
}
getAvailableMessages() {
const messages = this.messageBuffer;
this.messageBuffer = [];
const isEndOfStream = this.isEndOfStream;
return {
getMessages() {
return messages;
},
isEndOfStream() {
return isEndOfStream;
},
};
}
encode({ headers: rawHeaders, body }) {
const headers = this.headerMarshaller.format(rawHeaders);
const length = headers.byteLength + body.byteLength + 16;
const out = new Uint8Array(length);
const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
const checksum = new crc32.Crc32();
view.setUint32(0, length, false);
view.setUint32(4, headers.byteLength, false);
view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false);
out.set(headers, 12);
out.set(body, headers.byteLength + 12);
view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false);
return out;
}
decode(message) {
const { headers, body } = splitMessage(message);
return { headers: this.headerMarshaller.parse(headers), body };
}
formatHeaders(rawHeaders) {
return this.headerMarshaller.format(rawHeaders);
}
}
class MessageDecoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const bytes of this.options.inputStream) {
const decoded = this.options.decoder.decode(bytes);
yield decoded;
}
}
}
class MessageEncoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const msg of this.options.messageStream) {
const encoded = this.options.encoder.encode(msg);
yield encoded;
}
if (this.options.includeEndFrame) {
yield new Uint8Array(0);
}
}
}
class SmithyMessageDecoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const message of this.options.messageStream) {
const deserialized = await this.options.deserializer(message);
if (deserialized === undefined)
continue;
yield deserialized;
}
}
}
class SmithyMessageEncoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const chunk of this.options.inputStream) {
const payloadBuf = this.options.serializer(chunk);
yield payloadBuf;
}
}
}
function getChunkedStream(source) {
let currentMessageTotalLength = 0;
let currentMessagePendingLength = 0;
let currentMessage = null;
let messageLengthBuffer = null;
const allocateMessage = (size) => {
if (typeof size !== "number") {
throw new Error("Attempted to allocate an event message where size was not a number: " + size);
}
currentMessageTotalLength = size;
currentMessagePendingLength = 4;
currentMessage = new Uint8Array(size);
const currentMessageView = new DataView(currentMessage.buffer);
currentMessageView.setUint32(0, size, false);
};
const iterator = async function* () {
const sourceIterator = source[Symbol.asyncIterator]();
while (true) {
const { value, done } = await sourceIterator.next();
if (done) {
if (!currentMessageTotalLength) {
return;
}
else if (currentMessageTotalLength === currentMessagePendingLength) {
yield currentMessage;
}
else {
throw new Error("Truncated event message received.");
}
return;
}
const chunkLength = value.length;
let currentOffset = 0;
while (currentOffset < chunkLength) {
if (!currentMessage) {
const bytesRemaining = chunkLength - currentOffset;
if (!messageLengthBuffer) {
messageLengthBuffer = new Uint8Array(4);
}
const numBytesForTotal = Math.min(4 - currentMessagePendingLength, bytesRemaining);
messageLengthBuffer.set(value.slice(currentOffset, currentOffset + numBytesForTotal), currentMessagePendingLength);
currentMessagePendingLength += numBytesForTotal;
currentOffset += numBytesForTotal;
if (currentMessagePendingLength < 4) {
break;
}
allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false));
messageLengthBuffer = null;
}
const numBytesToWrite = Math.min(currentMessageTotalLength - currentMessagePendingLength, chunkLength - currentOffset);
currentMessage.set(value.slice(currentOffset, currentOffset + numBytesToWrite), currentMessagePendingLength);
currentMessagePendingLength += numBytesToWrite;
currentOffset += numBytesToWrite;
if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) {
yield currentMessage;
currentMessage = null;
currentMessageTotalLength = 0;
currentMessagePendingLength = 0;
}
}
}
};
return {
[Symbol.asyncIterator]: iterator,
};
}
function getUnmarshalledStream(source, options) {
const messageUnmarshaller = getMessageUnmarshaller(options.deserializer, options.toUtf8);
return {
[Symbol.asyncIterator]: async function* () {
for await (const chunk of source) {
const message = options.eventStreamCodec.decode(chunk);
const type = await messageUnmarshaller(message);
if (type === undefined)
continue;
yield type;
}
},
};
}
function getMessageUnmarshaller(deserializer, toUtf8) {
return async function (message) {
const { value: messageType } = message.headers[":message-type"];
if (messageType === "error") {
const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError");
unmodeledError.name = message.headers[":error-code"].value;
throw unmodeledError;
}
else if (messageType === "exception") {
const code = message.headers[":exception-type"].value;
const exception = { [code]: message };
const deserializedException = await deserializer(exception);
if (deserializedException.$unknown) {
const error = new Error(toUtf8(message.body));
error.name = code;
throw error;
}
throw deserializedException[code];
}
else if (messageType === "event") {
const event = {
[message.headers[":event-type"].value]: message,
};
const deserialized = await deserializer(event);
if (deserialized.$unknown)
return;
return deserialized;
}
else {
throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`);
}
};
}
let EventStreamMarshaller$1 = class EventStreamMarshaller {
eventStreamCodec;
utfEncoder;
constructor({ utf8Encoder, utf8Decoder }) {
this.eventStreamCodec = new EventStreamCodec(utf8Encoder, utf8Decoder);
this.utfEncoder = utf8Encoder;
}
deserialize(body, deserializer) {
const inputStream = getChunkedStream(body);
return new SmithyMessageDecoderStream({
messageStream: new MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }),
deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder),
});
}
serialize(inputStream, serializer) {
return new MessageEncoderStream({
messageStream: new SmithyMessageEncoderStream({ inputStream, serializer }),
encoder: this.eventStreamCodec,
includeEndFrame: true,
});
}
};
const eventStreamSerdeProvider$1 = (options) => new EventStreamMarshaller$1(options);
const readableStreamToIterable = (readableStream) => ({
[Symbol.asyncIterator]: async function* () {
const reader = readableStream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done)
return;
yield value;
}
}
finally {
reader.releaseLock();
}
},
});
const iterableToReadableStream = (asyncIterable) => {
const iterator = asyncIterable[Symbol.asyncIterator]();
return new ReadableStream({
async pull(controller) {
const { done, value } = await iterator.next();
if (done) {
return controller.close();
}
controller.enqueue(value);
},
});
};
class EventStreamMarshaller {
universalMarshaller;
constructor({ utf8Encoder, utf8Decoder }) {
this.universalMarshaller = new EventStreamMarshaller$1({
utf8Decoder,
utf8Encoder,
});
}
deserialize(body, deserializer) {
const bodyIterable = isReadableStream(body) ? readableStreamToIterable(body) : body;
return this.universalMarshaller.deserialize(bodyIterable, deserializer);
}
serialize(input, serializer) {
const serializedIterable = this.universalMarshaller.serialize(input, serializer);
return typeof ReadableStream === "function" ? iterableToReadableStream(serializedIterable) : serializedIterable;
}
}
const isReadableStream = (body) => typeof ReadableStream === "function" && body instanceof ReadableStream;
const eventStreamSerdeProvider = (options) => new EventStreamMarshaller(options);
const resolveEventStreamSerdeConfig = (input) => Object.assign(input, {
eventStreamMarshaller: input.eventStreamSerdeProvider(input),
});
class EventStreamSerde {
marshaller;
serializer;
deserializer;
serdeContext;
defaultContentType;
constructor({ marshaller, serializer, deserializer, serdeContext, defaultContentType, }) {
this.marshaller = marshaller;
this.serializer = serializer;
this.deserializer = deserializer;
this.serdeContext = serdeContext;
this.defaultContentType = defaultContentType;
}
async serializeEventStream({ eventStream, requestSchema, initialRequest, }) {
const marshaller = this.marshaller;
const eventStreamMember = requestSchema.getEventStreamMember();
const unionSchema = requestSchema.getMemberSchema(eventStreamMember);
const serializer = this.serializer;
const defaultContentType = this.defaultContentType;
const initialRequestMarker = Symbol("initialRequestMarker");
const eventStreamIterable = {
async *[Symbol.asyncIterator]() {
if (initialRequest) {
const headers = {
":event-type": { type: "string", value: "initial-request" },
":message-type": { type: "string", value: "event" },
":content-type": { type: "string", value: defaultContentType },
};
serializer.write(requestSchema, initialRequest);
const body = serializer.flush();
yield {
[initialRequestMarker]: true,
headers,
body,
};
}
for await (const page of eventStream) {
yield page;
}
},
};
return marshaller.serialize(eventStreamIterable, (event) => {
if (event[initialRequestMarker]) {
return {
headers: event.headers,
body: event.body,
};
}
let unionMember = "";
for (const key in event) {
if (key !== "__type") {
unionMember = key;
break;
}
}
const { additionalHeaders, body, eventType, explicitPayloadContentType } = this.writeEventBody(unionMember, unionSchema, event);
const headers = {
":event-type": { type: "string", value: eventType },
":message-type": { type: "string", value: "event" },
":content-type": { type: "string", value: explicitPayloadContentType ?? defaultContentType },
...additionalHeaders,
};
return {
headers,
body,
};
});
}
async deserializeEventStream({ response, responseSchema, initialResponseContainer, }) {
const marshaller = this.marshaller;
const eventStreamMember = responseSchema.getEventStreamMember();
const unionSchema = responseSchema.getMemberSchema(eventStreamMember);
const memberSchemas = unionSchema.getMemberSchemas();
const initialResponseMarker = Symbol("initialResponseMarker");
const asyncIterable = marshaller.deserialize(response.body, async (event) => {
let unionMember = "";
for (const key in event) {
if (key !== "__type") {
unionMember = key;
break;
}
}
const body = event[unionMember].body;
if (unionMember === "initial-response") {
const dataObject = await this.deserializer.read(responseSchema, body);
delete dataObject[eventStreamMember];
return {
[initialResponseMarker]: true,
...dataObject,
};
}
else if (unionMember in memberSchemas) {
const eventStreamSchema = memberSchemas[unionMember];
if (eventStreamSchema.isStructSchema()) {
const out = {};
let hasBindings = false;
for (const [name, member] of eventStreamSchema.structIterator()) {
const { eventHeader, eventPayload } = member.getMergedTraits();
hasBindings = hasBindings || Boolean(eventHeader || eventPayload);
if (eventPayload) {
if (member.isBlobSchema()) {
out[name] = body;
}
else if (member.isStringSchema()) {
out[name] = (this.serdeContext?.utf8Encoder ?? serde.toUtf8)(body);
}
else if (member.isStructSchema()) {
out[name] = await this.deserializer.read(member, body);
}
}
else if (eventHeader) {
const value = event[unionMember].headers[name]?.value;
if (value != null) {
if (member.isNumericSchema()) {
if (value && typeof value === "object" && "bytes" in value) {
out[name] = BigInt(value.toString());
}
else {
out[name] = Number(value);
}
}
else {
out[name] = value;
}
}
}
}
if (hasBindings) {
return {
[unionMember]: out,
};
}
if (body.byteLength === 0) {
return {
[unionMember]: {},
};
}
}
return {
[unionMember]: await this.deserializer.read(eventStreamSchema, body),
};
}
else {
return {
$unknown: event,
};
}
});
const asyncIterator = asyncIterable[Symbol.asyncIterator]();
const firstEvent = await asyncIterator.next();
if (firstEvent.done) {
return asyncIterable;
}
if (firstEvent.value?.[initialResponseMarker]) {
if (!responseSchema) {
throw new Error("@smithy::core/protocols - initial-response event encountered in event stream but no response schema given.");
}
for (const key in firstEvent.value) {
initialResponseContainer[key] = firstEvent.value[key];
}
}
return {
async *[Symbol.asyncIterator]() {
if (!firstEvent?.value?.[initialResponseMarker]) {
yield firstEvent.value;
}
while (true) {
const { done, value } = await asyncIterator.next();
if (done) {
break;
}
yield value;
}
},
};
}
writeEventBody(unionMember, unionSchema, event) {
const serializer = this.serializer;
let eventType = unionMember;
let explicitPayloadMember = null;
let explicitPayloadContentType;
const isKnownSchema = (() => {
const struct = unionSchema.getSchema();
return struct[4].includes(unionMember);
})();
const additionalHeaders = {};
if (!isKnownSchema) {
const [type, value] = event[unionMember];
eventType = type;
serializer.write(15, value);
}
else {
const eventSchema = unionSchema.getMemberSchema(unionMember);
if (eventSchema.isStructSchema()) {
for (const [memberName, memberSchema] of eventSchema.structIterator()) {
const { eventHeader, eventPayload } = memberSchema.getMergedTraits();
if (eventPayload) {
explicitPayloadMember = memberName;
}
else if (eventHeader) {
const value = event[unionMember][memberName];
let type = "binary";
if (memberSchema.isNumericSchema()) {
if ((-2) ** 31 <= value && value <= 2 ** 31 - 1) {
type = "integer";
}
else {
type = "long";
}
}
else if (memberSchema.isTimestampSchema()) {
type = "timestamp";
}
else if (memberSchema.isStringSchema()) {
type = "string";
}
else if (memberSchema.isBooleanSchema()) {
type = "boolean";
}
if (value != null) {
additionalHeaders[memberName] = {
type,
value,
};
delete event[unionMember][memberName];
}
}
}
if (explicitPayloadMember !== null) {
const payloadSchema = eventSchema.getMemberSchema(explicitPayloadMember);
if (payloadSchema.isBlobSchema()) {
explicitPayloadContentType = "application/octet-stream";
}
else if (payloadSchema.isStringSchema()) {
explicitPayloadContentType = "text/plain";
}
serializer.write(payloadSchema, event[unionMember][explicitPayloadMember]);
}
else {
serializer.write(eventSchema, event[unionMember]);
}
}
else if (eventSchema.isUnitSchema()) {
serializer.write(eventSchema, {});
}
else {
throw new Error("@smithy/core/event-streams - non-struct member not supported in event stream union.");
}
}
const messageSerialization = serializer.flush() ?? new Uint8Array();
const body = typeof messageSerialization === "string"
? (this.serdeContext?.utf8Decoder ?? serde.fromUtf8)(messageSerialization)
: messageSerialization;
return {
body,
eventType,
explicitPayloadContentType,
additionalHeaders,
};
}
}
exports.EventStreamCodec = EventStreamCodec;
exports.EventStreamMarshaller = EventStreamMarshaller;
exports.EventStreamSerde = EventStreamSerde;
exports.HeaderMarshaller = HeaderMarshaller;
exports.Int64 = Int64;
exports.MessageDecoderStream = MessageDecoderStream;
exports.MessageEncoderStream = MessageEncoderStream;
exports.SmithyMessageDecoderStream = SmithyMessageDecoderStream;
exports.SmithyMessageEncoderStream = SmithyMessageEncoderStream;
exports.UniversalEventStreamMarshaller = EventStreamMarshaller$1;
exports.eventStreamSerdeProvider = eventStreamSerdeProvider;
exports.getChunkedStream = getChunkedStream;
exports.getMessageUnmarshaller = getMessageUnmarshaller;
exports.getUnmarshalledStream = getUnmarshalledStream;
exports.iterableToReadableStream = iterableToReadableStream;
exports.readableStreamToIterable = readableStreamToIterable;
exports.resolveEventStreamSerdeConfig = resolveEventStreamSerdeConfig;
exports.universalEventStreamSerdeProvider = eventStreamSerdeProvider$1;
+891
View File
@@ -0,0 +1,891 @@
'use strict';
var crc32 = require('@aws-crypto/crc32');
var serde = require('@smithy/core/serde');
var node_stream = require('node:stream');
class Int64 {
bytes;
constructor(bytes) {
this.bytes = bytes;
if (bytes.byteLength !== 8) {
throw new Error("Int64 buffers must be exactly 8 bytes");
}
}
static fromNumber(number) {
if (number > 9_223_372_036_854_775_807 || number < -9223372036854776e3) {
throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`);
}
const bytes = new Uint8Array(8);
for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) {
bytes[i] = remaining;
}
if (number < 0) {
negate(bytes);
}
return new Int64(bytes);
}
valueOf() {
const bytes = this.bytes.slice(0);
const negative = bytes[0] & 0b10000000;
if (negative) {
negate(bytes);
}
return parseInt(serde.toHex(bytes), 16) * (negative ? -1 : 1);
}
toString() {
return String(this.valueOf());
}
}
function negate(bytes) {
for (let i = 0; i < 8; i++) {
bytes[i] ^= 0xff;
}
for (let i = 7; i > -1; i--) {
bytes[i]++;
if (bytes[i] !== 0)
break;
}
}
class HeaderMarshaller {
toUtf8;
fromUtf8;
constructor(toUtf8, fromUtf8) {
this.toUtf8 = toUtf8;
this.fromUtf8 = fromUtf8;
}
format(headers) {
const chunks = [];
for (const headerName of Object.keys(headers)) {
const bytes = this.fromUtf8(headerName);
chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName]));
}
const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0));
let position = 0;
for (const chunk of chunks) {
out.set(chunk, position);
position += chunk.byteLength;
}
return out;
}
formatHeaderValue(header) {
switch (header.type) {
case "boolean":
return Uint8Array.from([header.value ? 0 : 1]);
case "byte":
return Uint8Array.from([2, header.value]);
case "short":
const shortView = new DataView(new ArrayBuffer(3));
shortView.setUint8(0, 3);
shortView.setInt16(1, header.value, false);
return new Uint8Array(shortView.buffer);
case "integer":
const intView = new DataView(new ArrayBuffer(5));
intView.setUint8(0, 4);
intView.setInt32(1, header.value, false);
return new Uint8Array(intView.buffer);
case "long":
const longBytes = new Uint8Array(9);
longBytes[0] = 5;
longBytes.set(header.value.bytes, 1);
return longBytes;
case "binary":
const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength));
binView.setUint8(0, 6);
binView.setUint16(1, header.value.byteLength, false);
const binBytes = new Uint8Array(binView.buffer);
binBytes.set(header.value, 3);
return binBytes;
case "string":
const utf8Bytes = this.fromUtf8(header.value);
const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength));
strView.setUint8(0, 7);
strView.setUint16(1, utf8Bytes.byteLength, false);
const strBytes = new Uint8Array(strView.buffer);
strBytes.set(utf8Bytes, 3);
return strBytes;
case "timestamp":
const tsBytes = new Uint8Array(9);
tsBytes[0] = 8;
tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1);
return tsBytes;
case "uuid":
if (!UUID_PATTERN.test(header.value)) {
throw new Error(`Invalid UUID received: ${header.value}`);
}
const uuidBytes = new Uint8Array(17);
uuidBytes[0] = 9;
uuidBytes.set(serde.fromHex(header.value.replace(/\-/g, "")), 1);
return uuidBytes;
}
}
parse(headers) {
const out = {};
let position = 0;
while (position < headers.byteLength) {
const nameLength = headers.getUint8(position++);
const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength));
position += nameLength;
switch (headers.getUint8(position++)) {
case 0:
out[name] = {
type: BOOLEAN_TAG,
value: true,
};
break;
case 1:
out[name] = {
type: BOOLEAN_TAG,
value: false,
};
break;
case 2:
out[name] = {
type: BYTE_TAG,
value: headers.getInt8(position++),
};
break;
case 3:
out[name] = {
type: SHORT_TAG,
value: headers.getInt16(position, false),
};
position += 2;
break;
case 4:
out[name] = {
type: INT_TAG,
value: headers.getInt32(position, false),
};
position += 4;
break;
case 5:
out[name] = {
type: LONG_TAG,
value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)),
};
position += 8;
break;
case 6:
const binaryLength = headers.getUint16(position, false);
position += 2;
out[name] = {
type: BINARY_TAG,
value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength),
};
position += binaryLength;
break;
case 7:
const stringLength = headers.getUint16(position, false);
position += 2;
out[name] = {
type: STRING_TAG,
value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength)),
};
position += stringLength;
break;
case 8:
out[name] = {
type: TIMESTAMP_TAG,
value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf()),
};
position += 8;
break;
case 9:
const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16);
position += 16;
out[name] = {
type: UUID_TAG,
value: `${serde.toHex(uuidBytes.subarray(0, 4))}-${serde.toHex(uuidBytes.subarray(4, 6))}-${serde.toHex(uuidBytes.subarray(6, 8))}-${serde.toHex(uuidBytes.subarray(8, 10))}-${serde.toHex(uuidBytes.subarray(10))}`,
};
break;
default:
throw new Error(`Unrecognized header type tag`);
}
}
return out;
}
}
var HEADER_VALUE_TYPE;
(function (HEADER_VALUE_TYPE) {
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["boolTrue"] = 0] = "boolTrue";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["boolFalse"] = 1] = "boolFalse";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["byte"] = 2] = "byte";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["short"] = 3] = "short";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["integer"] = 4] = "integer";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["long"] = 5] = "long";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["byteArray"] = 6] = "byteArray";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["string"] = 7] = "string";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["timestamp"] = 8] = "timestamp";
HEADER_VALUE_TYPE[HEADER_VALUE_TYPE["uuid"] = 9] = "uuid";
})(HEADER_VALUE_TYPE || (HEADER_VALUE_TYPE = {}));
const BOOLEAN_TAG = "boolean";
const BYTE_TAG = "byte";
const SHORT_TAG = "short";
const INT_TAG = "integer";
const LONG_TAG = "long";
const BINARY_TAG = "binary";
const STRING_TAG = "string";
const TIMESTAMP_TAG = "timestamp";
const UUID_TAG = "uuid";
const UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
const PRELUDE_MEMBER_LENGTH = 4;
const PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2;
const CHECKSUM_LENGTH = 4;
const MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2;
function splitMessage({ byteLength, byteOffset, buffer }) {
if (byteLength < MINIMUM_MESSAGE_LENGTH) {
throw new Error("Provided message too short to accommodate event stream message overhead");
}
const view = new DataView(buffer, byteOffset, byteLength);
const messageLength = view.getUint32(0, false);
if (byteLength !== messageLength) {
throw new Error("Reported message length does not match received message length");
}
const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false);
const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false);
const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false);
const checksummer = new crc32.Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH));
if (expectedPreludeChecksum !== checksummer.digest()) {
throw new Error(`The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})`);
}
checksummer.update(new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)));
if (expectedMessageChecksum !== checksummer.digest()) {
throw new Error(`The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}`);
}
return {
headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength),
body: new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH)),
};
}
class EventStreamCodec {
headerMarshaller;
messageBuffer;
isEndOfStream;
constructor(toUtf8, fromUtf8) {
this.headerMarshaller = new HeaderMarshaller(toUtf8, fromUtf8);
this.messageBuffer = [];
this.isEndOfStream = false;
}
feed(message) {
this.messageBuffer.push(this.decode(message));
}
endOfStream() {
this.isEndOfStream = true;
}
getMessage() {
const message = this.messageBuffer.pop();
const isEndOfStream = this.isEndOfStream;
return {
getMessage() {
return message;
},
isEndOfStream() {
return isEndOfStream;
},
};
}
getAvailableMessages() {
const messages = this.messageBuffer;
this.messageBuffer = [];
const isEndOfStream = this.isEndOfStream;
return {
getMessages() {
return messages;
},
isEndOfStream() {
return isEndOfStream;
},
};
}
encode({ headers: rawHeaders, body }) {
const headers = this.headerMarshaller.format(rawHeaders);
const length = headers.byteLength + body.byteLength + 16;
const out = new Uint8Array(length);
const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
const checksum = new crc32.Crc32();
view.setUint32(0, length, false);
view.setUint32(4, headers.byteLength, false);
view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false);
out.set(headers, 12);
out.set(body, headers.byteLength + 12);
view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false);
return out;
}
decode(message) {
const { headers, body } = splitMessage(message);
return { headers: this.headerMarshaller.parse(headers), body };
}
formatHeaders(rawHeaders) {
return this.headerMarshaller.format(rawHeaders);
}
}
class MessageDecoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const bytes of this.options.inputStream) {
const decoded = this.options.decoder.decode(bytes);
yield decoded;
}
}
}
class MessageEncoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const msg of this.options.messageStream) {
const encoded = this.options.encoder.encode(msg);
yield encoded;
}
if (this.options.includeEndFrame) {
yield new Uint8Array(0);
}
}
}
class SmithyMessageDecoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const message of this.options.messageStream) {
const deserialized = await this.options.deserializer(message);
if (deserialized === undefined)
continue;
yield deserialized;
}
}
}
class SmithyMessageEncoderStream {
options;
constructor(options) {
this.options = options;
}
[Symbol.asyncIterator]() {
return this.asyncIterator();
}
async *asyncIterator() {
for await (const chunk of this.options.inputStream) {
const payloadBuf = this.options.serializer(chunk);
yield payloadBuf;
}
}
}
function getChunkedStream(source) {
let currentMessageTotalLength = 0;
let currentMessagePendingLength = 0;
let currentMessage = null;
let messageLengthBuffer = null;
const allocateMessage = (size) => {
if (typeof size !== "number") {
throw new Error("Attempted to allocate an event message where size was not a number: " + size);
}
currentMessageTotalLength = size;
currentMessagePendingLength = 4;
currentMessage = new Uint8Array(size);
const currentMessageView = new DataView(currentMessage.buffer);
currentMessageView.setUint32(0, size, false);
};
const iterator = async function* () {
const sourceIterator = source[Symbol.asyncIterator]();
while (true) {
const { value, done } = await sourceIterator.next();
if (done) {
if (!currentMessageTotalLength) {
return;
}
else if (currentMessageTotalLength === currentMessagePendingLength) {
yield currentMessage;
}
else {
throw new Error("Truncated event message received.");
}
return;
}
const chunkLength = value.length;
let currentOffset = 0;
while (currentOffset < chunkLength) {
if (!currentMessage) {
const bytesRemaining = chunkLength - currentOffset;
if (!messageLengthBuffer) {
messageLengthBuffer = new Uint8Array(4);
}
const numBytesForTotal = Math.min(4 - currentMessagePendingLength, bytesRemaining);
messageLengthBuffer.set(value.slice(currentOffset, currentOffset + numBytesForTotal), currentMessagePendingLength);
currentMessagePendingLength += numBytesForTotal;
currentOffset += numBytesForTotal;
if (currentMessagePendingLength < 4) {
break;
}
allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false));
messageLengthBuffer = null;
}
const numBytesToWrite = Math.min(currentMessageTotalLength - currentMessagePendingLength, chunkLength - currentOffset);
currentMessage.set(value.slice(currentOffset, currentOffset + numBytesToWrite), currentMessagePendingLength);
currentMessagePendingLength += numBytesToWrite;
currentOffset += numBytesToWrite;
if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) {
yield currentMessage;
currentMessage = null;
currentMessageTotalLength = 0;
currentMessagePendingLength = 0;
}
}
}
};
return {
[Symbol.asyncIterator]: iterator,
};
}
function getUnmarshalledStream(source, options) {
const messageUnmarshaller = getMessageUnmarshaller(options.deserializer, options.toUtf8);
return {
[Symbol.asyncIterator]: async function* () {
for await (const chunk of source) {
const message = options.eventStreamCodec.decode(chunk);
const type = await messageUnmarshaller(message);
if (type === undefined)
continue;
yield type;
}
},
};
}
function getMessageUnmarshaller(deserializer, toUtf8) {
return async function (message) {
const { value: messageType } = message.headers[":message-type"];
if (messageType === "error") {
const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError");
unmodeledError.name = message.headers[":error-code"].value;
throw unmodeledError;
}
else if (messageType === "exception") {
const code = message.headers[":exception-type"].value;
const exception = { [code]: message };
const deserializedException = await deserializer(exception);
if (deserializedException.$unknown) {
const error = new Error(toUtf8(message.body));
error.name = code;
throw error;
}
throw deserializedException[code];
}
else if (messageType === "event") {
const event = {
[message.headers[":event-type"].value]: message,
};
const deserialized = await deserializer(event);
if (deserialized.$unknown)
return;
return deserialized;
}
else {
throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`);
}
};
}
let EventStreamMarshaller$1 = class EventStreamMarshaller {
eventStreamCodec;
utfEncoder;
constructor({ utf8Encoder, utf8Decoder }) {
this.eventStreamCodec = new EventStreamCodec(utf8Encoder, utf8Decoder);
this.utfEncoder = utf8Encoder;
}
deserialize(body, deserializer) {
const inputStream = getChunkedStream(body);
return new SmithyMessageDecoderStream({
messageStream: new MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }),
deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder),
});
}
serialize(inputStream, serializer) {
return new MessageEncoderStream({
messageStream: new SmithyMessageEncoderStream({ inputStream, serializer }),
encoder: this.eventStreamCodec,
includeEndFrame: true,
});
}
};
const eventStreamSerdeProvider$1 = (options) => new EventStreamMarshaller$1(options);
class EventStreamMarshaller {
universalMarshaller;
constructor({ utf8Encoder, utf8Decoder }) {
this.universalMarshaller = new EventStreamMarshaller$1({
utf8Decoder,
utf8Encoder,
});
}
deserialize(body, deserializer) {
const bodyIterable = typeof body[Symbol.asyncIterator] === "function" ? body : readableToIterable(body);
return this.universalMarshaller.deserialize(bodyIterable, deserializer);
}
serialize(input, serializer) {
return node_stream.Readable.from(this.universalMarshaller.serialize(input, serializer));
}
}
const eventStreamSerdeProvider = (options) => new EventStreamMarshaller(options);
async function* readableToIterable(readStream) {
let streamEnded = false;
let generationEnded = false;
const records = new Array();
readStream.on("error", (err) => {
if (!streamEnded) {
streamEnded = true;
}
if (err) {
throw err;
}
});
readStream.on("data", (data) => {
records.push(data);
});
readStream.on("end", () => {
streamEnded = true;
});
while (!generationEnded) {
const value = await new Promise((resolve) => setTimeout(() => resolve(records.shift()), 0));
if (value) {
yield value;
}
generationEnded = streamEnded && records.length === 0;
}
}
const readableStreamToIterable = (readableStream) => ({
[Symbol.asyncIterator]: async function* () {
const reader = readableStream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done)
return;
yield value;
}
}
finally {
reader.releaseLock();
}
},
});
const iterableToReadableStream = (asyncIterable) => {
const iterator = asyncIterable[Symbol.asyncIterator]();
return new ReadableStream({
async pull(controller) {
const { done, value } = await iterator.next();
if (done) {
return controller.close();
}
controller.enqueue(value);
},
});
};
const resolveEventStreamSerdeConfig = (input) => Object.assign(input, {
eventStreamMarshaller: input.eventStreamSerdeProvider(input),
});
class EventStreamSerde {
marshaller;
serializer;
deserializer;
serdeContext;
defaultContentType;
constructor({ marshaller, serializer, deserializer, serdeContext, defaultContentType, }) {
this.marshaller = marshaller;
this.serializer = serializer;
this.deserializer = deserializer;
this.serdeContext = serdeContext;
this.defaultContentType = defaultContentType;
}
async serializeEventStream({ eventStream, requestSchema, initialRequest, }) {
const marshaller = this.marshaller;
const eventStreamMember = requestSchema.getEventStreamMember();
const unionSchema = requestSchema.getMemberSchema(eventStreamMember);
const serializer = this.serializer;
const defaultContentType = this.defaultContentType;
const initialRequestMarker = Symbol("initialRequestMarker");
const eventStreamIterable = {
async *[Symbol.asyncIterator]() {
if (initialRequest) {
const headers = {
":event-type": { type: "string", value: "initial-request" },
":message-type": { type: "string", value: "event" },
":content-type": { type: "string", value: defaultContentType },
};
serializer.write(requestSchema, initialRequest);
const body = serializer.flush();
yield {
[initialRequestMarker]: true,
headers,
body,
};
}
for await (const page of eventStream) {
yield page;
}
},
};
return marshaller.serialize(eventStreamIterable, (event) => {
if (event[initialRequestMarker]) {
return {
headers: event.headers,
body: event.body,
};
}
let unionMember = "";
for (const key in event) {
if (key !== "__type") {
unionMember = key;
break;
}
}
const { additionalHeaders, body, eventType, explicitPayloadContentType } = this.writeEventBody(unionMember, unionSchema, event);
const headers = {
":event-type": { type: "string", value: eventType },
":message-type": { type: "string", value: "event" },
":content-type": { type: "string", value: explicitPayloadContentType ?? defaultContentType },
...additionalHeaders,
};
return {
headers,
body,
};
});
}
async deserializeEventStream({ response, responseSchema, initialResponseContainer, }) {
const marshaller = this.marshaller;
const eventStreamMember = responseSchema.getEventStreamMember();
const unionSchema = responseSchema.getMemberSchema(eventStreamMember);
const memberSchemas = unionSchema.getMemberSchemas();
const initialResponseMarker = Symbol("initialResponseMarker");
const asyncIterable = marshaller.deserialize(response.body, async (event) => {
let unionMember = "";
for (const key in event) {
if (key !== "__type") {
unionMember = key;
break;
}
}
const body = event[unionMember].body;
if (unionMember === "initial-response") {
const dataObject = await this.deserializer.read(responseSchema, body);
delete dataObject[eventStreamMember];
return {
[initialResponseMarker]: true,
...dataObject,
};
}
else if (unionMember in memberSchemas) {
const eventStreamSchema = memberSchemas[unionMember];
if (eventStreamSchema.isStructSchema()) {
const out = {};
let hasBindings = false;
for (const [name, member] of eventStreamSchema.structIterator()) {
const { eventHeader, eventPayload } = member.getMergedTraits();
hasBindings = hasBindings || Boolean(eventHeader || eventPayload);
if (eventPayload) {
if (member.isBlobSchema()) {
out[name] = body;
}
else if (member.isStringSchema()) {
out[name] = (this.serdeContext?.utf8Encoder ?? serde.toUtf8)(body);
}
else if (member.isStructSchema()) {
out[name] = await this.deserializer.read(member, body);
}
}
else if (eventHeader) {
const value = event[unionMember].headers[name]?.value;
if (value != null) {
if (member.isNumericSchema()) {
if (value && typeof value === "object" && "bytes" in value) {
out[name] = BigInt(value.toString());
}
else {
out[name] = Number(value);
}
}
else {
out[name] = value;
}
}
}
}
if (hasBindings) {
return {
[unionMember]: out,
};
}
if (body.byteLength === 0) {
return {
[unionMember]: {},
};
}
}
return {
[unionMember]: await this.deserializer.read(eventStreamSchema, body),
};
}
else {
return {
$unknown: event,
};
}
});
const asyncIterator = asyncIterable[Symbol.asyncIterator]();
const firstEvent = await asyncIterator.next();
if (firstEvent.done) {
return asyncIterable;
}
if (firstEvent.value?.[initialResponseMarker]) {
if (!responseSchema) {
throw new Error("@smithy::core/protocols - initial-response event encountered in event stream but no response schema given.");
}
for (const key in firstEvent.value) {
initialResponseContainer[key] = firstEvent.value[key];
}
}
return {
async *[Symbol.asyncIterator]() {
if (!firstEvent?.value?.[initialResponseMarker]) {
yield firstEvent.value;
}
while (true) {
const { done, value } = await asyncIterator.next();
if (done) {
break;
}
yield value;
}
},
};
}
writeEventBody(unionMember, unionSchema, event) {
const serializer = this.serializer;
let eventType = unionMember;
let explicitPayloadMember = null;
let explicitPayloadContentType;
const isKnownSchema = (() => {
const struct = unionSchema.getSchema();
return struct[4].includes(unionMember);
})();
const additionalHeaders = {};
if (!isKnownSchema) {
const [type, value] = event[unionMember];
eventType = type;
serializer.write(15, value);
}
else {
const eventSchema = unionSchema.getMemberSchema(unionMember);
if (eventSchema.isStructSchema()) {
for (const [memberName, memberSchema] of eventSchema.structIterator()) {
const { eventHeader, eventPayload } = memberSchema.getMergedTraits();
if (eventPayload) {
explicitPayloadMember = memberName;
}
else if (eventHeader) {
const value = event[unionMember][memberName];
let type = "binary";
if (memberSchema.isNumericSchema()) {
if ((-2) ** 31 <= value && value <= 2 ** 31 - 1) {
type = "integer";
}
else {
type = "long";
}
}
else if (memberSchema.isTimestampSchema()) {
type = "timestamp";
}
else if (memberSchema.isStringSchema()) {
type = "string";
}
else if (memberSchema.isBooleanSchema()) {
type = "boolean";
}
if (value != null) {
additionalHeaders[memberName] = {
type,
value,
};
delete event[unionMember][memberName];
}
}
}
if (explicitPayloadMember !== null) {
const payloadSchema = eventSchema.getMemberSchema(explicitPayloadMember);
if (payloadSchema.isBlobSchema()) {
explicitPayloadContentType = "application/octet-stream";
}
else if (payloadSchema.isStringSchema()) {
explicitPayloadContentType = "text/plain";
}
serializer.write(payloadSchema, event[unionMember][explicitPayloadMember]);
}
else {
serializer.write(eventSchema, event[unionMember]);
}
}
else if (eventSchema.isUnitSchema()) {
serializer.write(eventSchema, {});
}
else {
throw new Error("@smithy/core/event-streams - non-struct member not supported in event stream union.");
}
}
const messageSerialization = serializer.flush() ?? new Uint8Array();
const body = typeof messageSerialization === "string"
? (this.serdeContext?.utf8Decoder ?? serde.fromUtf8)(messageSerialization)
: messageSerialization;
return {
body,
eventType,
explicitPayloadContentType,
additionalHeaders,
};
}
}
exports.EventStreamCodec = EventStreamCodec;
exports.EventStreamMarshaller = EventStreamMarshaller;
exports.EventStreamSerde = EventStreamSerde;
exports.HeaderMarshaller = HeaderMarshaller;
exports.Int64 = Int64;
exports.MessageDecoderStream = MessageDecoderStream;
exports.MessageEncoderStream = MessageEncoderStream;
exports.SmithyMessageDecoderStream = SmithyMessageDecoderStream;
exports.SmithyMessageEncoderStream = SmithyMessageEncoderStream;
exports.UniversalEventStreamMarshaller = EventStreamMarshaller$1;
exports.eventStreamSerdeProvider = eventStreamSerdeProvider;
exports.getChunkedStream = getChunkedStream;
exports.getMessageUnmarshaller = getMessageUnmarshaller;
exports.getUnmarshalledStream = getUnmarshalledStream;
exports.iterableToReadableStream = iterableToReadableStream;
exports.readableStreamToIterable = readableStreamToIterable;
exports.resolveEventStreamSerdeConfig = resolveEventStreamSerdeConfig;
exports.universalEventStreamSerdeProvider = eventStreamSerdeProvider$1;
File diff suppressed because it is too large Load Diff
+817
View File
@@ -0,0 +1,817 @@
'use strict';
var client = require('@smithy/core/client');
var protocols = require('@smithy/core/protocols');
var serde = require('@smithy/core/serde');
const isStreamingPayload = (request) => request?.body instanceof ReadableStream;
const CLOCK_SKEW_ERROR_CODES = [
"AuthFailure",
"InvalidSignatureException",
"RequestExpired",
"RequestInTheFuture",
"RequestTimeTooSkewed",
"SignatureDoesNotMatch",
];
const THROTTLING_ERROR_CODES = [
"BandwidthLimitExceeded",
"EC2ThrottledException",
"LimitExceededException",
"PriorRequestNotComplete",
"ProvisionedThroughputExceededException",
"RequestLimitExceeded",
"RequestThrottled",
"RequestThrottledException",
"SlowDown",
"ThrottledException",
"Throttling",
"ThrottlingException",
"TooManyRequestsException",
"TransactionInProgressException",
];
const TRANSIENT_ERROR_CODES = ["TimeoutError", "RequestTimeout", "RequestTimeoutException"];
const TRANSIENT_ERROR_STATUS_CODES = [500, 502, 503, 504];
const NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT"];
const NODEJS_NETWORK_ERROR_CODES = ["EHOSTUNREACH", "ENETUNREACH", "ENOTFOUND", "EAI_AGAIN"];
const isRetryableByTrait = (error) => error?.$retryable !== undefined;
const isClockSkewError = (error) => CLOCK_SKEW_ERROR_CODES.includes(error.name);
const isClockSkewCorrectedError = (error) => error.$metadata?.clockSkewCorrected;
const isBrowserNetworkError = (error) => {
const errorMessages = new Set([
"Failed to fetch",
"NetworkError when attempting to fetch resource",
"The Internet connection appears to be offline",
"Load failed",
"Network request failed",
]);
const isValid = error && error instanceof TypeError;
if (!isValid) {
return false;
}
return errorMessages.has(error.message);
};
const isThrottlingError = (error) => error.$metadata?.httpStatusCode === 429 ||
THROTTLING_ERROR_CODES.includes(error.name) ||
error.$retryable?.throttling == true;
const isTransientError = (error, depth = 0) => isRetryableByTrait(error) ||
isClockSkewCorrectedError(error) ||
(error.name === "InvalidSignatureException" && error.message?.includes("Signature expired")) ||
TRANSIENT_ERROR_CODES.includes(error.name) ||
NODEJS_TIMEOUT_ERROR_CODES.includes(error?.code || "") ||
NODEJS_NETWORK_ERROR_CODES.includes(error?.code || "") ||
TRANSIENT_ERROR_STATUS_CODES.includes(error.$metadata?.httpStatusCode || 0) ||
isBrowserNetworkError(error) ||
isNodeJsHttp2TransientError(error) ||
(error.cause !== undefined && depth <= 10 && isTransientError(error.cause, depth + 1));
const isServerError = (error) => {
if (error.$metadata?.httpStatusCode !== undefined) {
const statusCode = error.$metadata.httpStatusCode;
if (500 <= statusCode && statusCode <= 599 && !isTransientError(error)) {
return true;
}
return false;
}
return false;
};
function isNodeJsHttp2TransientError(error) {
return error.code === "ERR_HTTP2_STREAM_ERROR" && error.message.includes("NGHTTP2_REFUSED_STREAM");
}
const DEFAULT_RETRY_DELAY_BASE = 100;
const MAXIMUM_RETRY_DELAY = 20 * 1000;
const THROTTLING_RETRY_DELAY_BASE = 500;
const INITIAL_RETRY_TOKENS = 500;
const RETRY_COST = 5;
const TIMEOUT_RETRY_COST = 10;
const NO_RETRY_INCREMENT = 1;
const INVOCATION_ID_HEADER = "amz-sdk-invocation-id";
const REQUEST_HEADER = "amz-sdk-request";
function parseRetryAfterHeader(response, logger) {
if (!protocols.HttpResponse.isInstance(response)) {
return;
}
for (const header of Object.keys(response.headers)) {
const h = header.toLowerCase();
if (h === "retry-after") {
const retryAfter = response.headers[header];
let retryAfterSeconds = NaN;
if (retryAfter.endsWith("GMT")) {
try {
const date = serde.parseRfc7231DateTime(retryAfter);
retryAfterSeconds = (date.getTime() - Date.now()) / 1000;
}
catch (e) {
logger?.trace?.("Failed to parse retry-after header");
logger?.trace?.(e);
}
}
else if (retryAfter.match(/ GMT, ((\d+)|(\d+\.\d+))$/)) {
retryAfterSeconds = Number(retryAfter.match(/ GMT, ([\d.]+)$/)?.[1]);
}
else if (retryAfter.match(/^((\d+)|(\d+\.\d+))$/)) {
retryAfterSeconds = Number(retryAfter);
}
else if (Date.parse(retryAfter) >= Date.now()) {
retryAfterSeconds = (Date.parse(retryAfter) - Date.now()) / 1000;
}
if (isNaN(retryAfterSeconds)) {
return;
}
return new Date(Date.now() + retryAfterSeconds * 1000);
}
else if (h === "x-amz-retry-after") {
const v = response.headers[header];
const backoffMilliseconds = Number(v);
if (isNaN(backoffMilliseconds)) {
logger?.trace?.(`Failed to parse x-amz-retry-after=${v}`);
return;
}
return new Date(Date.now() + backoffMilliseconds);
}
}
}
function getRetryAfterHint(response, logger) {
return parseRetryAfterHeader(response, logger);
}
const asSdkError = (error) => {
if (error instanceof Error)
return error;
if (error instanceof Object)
return Object.assign(new Error(), error);
if (typeof error === "string")
return new Error(error);
return new Error(`AWS SDK error wrapper for ${error}`);
};
function bindRetryMiddleware(isStreamingPayload) {
return (options) => (next, context) => async (args) => {
let retryStrategy = await options.retryStrategy();
const maxAttempts = await options.maxAttempts();
if (isRetryStrategyV2(retryStrategy)) {
retryStrategy = retryStrategy;
let retryToken = await retryStrategy.acquireInitialRetryToken((context["partition_id"] ?? "") + (context.__retryLongPoll ? ":longpoll" : ""));
let lastError = new Error();
let attempts = 0;
let totalRetryDelay = 0;
const { request } = args;
const isRequest = protocols.HttpRequest.isInstance(request);
if (isRequest) {
request.headers[INVOCATION_ID_HEADER] = serde.v4();
}
while (true) {
try {
if (isRequest) {
request.headers[REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
}
const { response, output } = await next(args);
retryStrategy.recordSuccess(retryToken);
output.$metadata.attempts = attempts + 1;
output.$metadata.totalRetryDelay = totalRetryDelay;
return { response, output };
}
catch (e) {
const retryErrorInfo = getRetryErrorInfo(e, options.logger);
lastError = asSdkError(e);
if (isRequest && isStreamingPayload(request)) {
(context.logger instanceof client.NoOpLogger ? console : context.logger)?.warn("An error was encountered in a non-retryable streaming request.");
throw lastError;
}
try {
retryToken = await retryStrategy.refreshRetryTokenForRetry(retryToken, retryErrorInfo);
}
catch (refreshError) {
if (!lastError.$metadata) {
lastError.$metadata = {};
}
lastError.$metadata.attempts = attempts + 1;
lastError.$metadata.totalRetryDelay = totalRetryDelay;
throw lastError;
}
attempts = retryToken.getRetryCount();
const delay = retryToken.getRetryDelay();
totalRetryDelay += (retryToken?.$retryLog?.acquisitionDelay ?? 0) + delay;
if (delay > 0) {
await cooldown(delay);
}
}
}
}
else {
retryStrategy = retryStrategy;
if (retryStrategy?.mode) {
context.userAgent = [...(context.userAgent || []), ["cfg/retry-mode", retryStrategy.mode]];
}
return retryStrategy.retry(next, args);
}
};
}
const cooldown = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" &&
typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" &&
typeof retryStrategy.recordSuccess !== "undefined";
const getRetryErrorInfo = (error, logger) => {
const errorInfo = {
error,
errorType: getRetryErrorType(error),
};
const retryAfterHint = parseRetryAfterHeader(error.$response, logger);
if (retryAfterHint) {
errorInfo.retryAfterHint = retryAfterHint;
}
return errorInfo;
};
const getRetryErrorType = (error) => {
if (isThrottlingError(error))
return "THROTTLING";
if (isTransientError(error))
return "TRANSIENT";
if (isServerError(error))
return "SERVER_ERROR";
return "CLIENT_ERROR";
};
const retryMiddlewareOptions = {
name: "retryMiddleware",
tags: ["RETRY"],
step: "finalizeRequest",
priority: "high",
override: true,
};
function bindGetRetryPlugin(isStreamingPayload) {
const retryMiddleware = bindRetryMiddleware(isStreamingPayload);
return (options) => ({
applyToStack: (clientStack) => {
clientStack.add(retryMiddleware(options), retryMiddlewareOptions);
},
});
}
class DefaultRateLimiter {
static setTimeoutFn = setTimeout;
beta;
minCapacity;
minFillRate;
scaleConstant;
smooth;
enabled = false;
availableTokens = 0;
lastMaxRate = 0;
measuredTxRate = 0;
requestCount = 0;
fillRate;
lastThrottleTime;
lastTimestamp = 0;
lastTxRateBucket;
maxCapacity;
timeWindow = 0;
constructor(options) {
this.beta = options?.beta ?? 0.7;
this.minCapacity = options?.minCapacity ?? 1;
this.minFillRate = options?.minFillRate ?? 0.5;
this.scaleConstant = options?.scaleConstant ?? 0.4;
this.smooth = options?.smooth ?? 0.8;
this.lastThrottleTime = this.getCurrentTimeInSeconds();
this.lastTxRateBucket = Math.floor(this.getCurrentTimeInSeconds());
this.fillRate = this.minFillRate;
this.maxCapacity = this.minCapacity;
}
async getSendToken() {
return this.acquireTokenBucket(1);
}
updateClientSendingRate(response) {
let calculatedRate;
this.updateMeasuredRate();
const retryErrorInfo = response;
const isThrottling = retryErrorInfo?.errorType === "THROTTLING" || isThrottlingError(retryErrorInfo?.error ?? response);
if (isThrottling) {
const rateToUse = !this.enabled ? this.measuredTxRate : Math.min(this.measuredTxRate, this.fillRate);
this.lastMaxRate = rateToUse;
this.calculateTimeWindow();
this.lastThrottleTime = this.getCurrentTimeInSeconds();
calculatedRate = this.cubicThrottle(rateToUse);
this.enableTokenBucket();
}
else {
this.calculateTimeWindow();
calculatedRate = this.cubicSuccess(this.getCurrentTimeInSeconds());
}
const newRate = Math.min(calculatedRate, 2 * this.measuredTxRate);
this.updateTokenBucketRate(newRate);
}
getCurrentTimeInSeconds() {
return Date.now() / 1000;
}
async acquireTokenBucket(amount) {
if (!this.enabled) {
return;
}
this.refillTokenBucket();
while (amount > this.availableTokens) {
const delay = ((amount - this.availableTokens) / this.fillRate) * 1000;
await new Promise((resolve) => DefaultRateLimiter.setTimeoutFn(resolve, delay));
this.refillTokenBucket();
}
this.availableTokens = this.availableTokens - amount;
}
refillTokenBucket() {
const timestamp = this.getCurrentTimeInSeconds();
if (!this.lastTimestamp) {
this.lastTimestamp = timestamp;
return;
}
const fillAmount = (timestamp - this.lastTimestamp) * this.fillRate;
this.availableTokens = Math.min(this.maxCapacity, this.availableTokens + fillAmount);
this.lastTimestamp = timestamp;
}
calculateTimeWindow() {
this.timeWindow = this.getPrecise(Math.pow((this.lastMaxRate * (1 - this.beta)) / this.scaleConstant, 1 / 3));
}
cubicThrottle(rateToUse) {
return this.getPrecise(rateToUse * this.beta);
}
cubicSuccess(timestamp) {
return this.getPrecise(this.scaleConstant * Math.pow(timestamp - this.lastThrottleTime - this.timeWindow, 3) + this.lastMaxRate);
}
enableTokenBucket() {
this.enabled = true;
}
updateTokenBucketRate(newRate) {
this.refillTokenBucket();
this.fillRate = Math.max(newRate, this.minFillRate);
this.maxCapacity = Math.max(newRate, this.minCapacity);
this.availableTokens = Math.min(this.availableTokens, this.maxCapacity);
}
updateMeasuredRate() {
const t = this.getCurrentTimeInSeconds();
const timeBucket = Math.floor(t * 2) / 2;
this.requestCount++;
if (timeBucket > this.lastTxRateBucket) {
const currentRate = this.requestCount / (timeBucket - this.lastTxRateBucket);
this.measuredTxRate = this.getPrecise(currentRate * this.smooth + this.measuredTxRate * (1 - this.smooth));
this.requestCount = 0;
this.lastTxRateBucket = timeBucket;
}
}
getPrecise(num) {
return parseFloat(num.toFixed(8));
}
}
class Retry {
static v2026 = typeof process !== "undefined" && process.env?.SMITHY_NEW_RETRIES_2026 === "true";
static delay() {
return Retry.v2026 ? 50 : 100;
}
static throttlingDelay() {
return Retry.v2026 ? 1_000 : 500;
}
static cost() {
return Retry.v2026 ? 14 : 5;
}
static throttlingCost() {
return Retry.v2026 ? 5 : 10;
}
static modifiedCostType() {
return Retry.v2026 ? "THROTTLING" : "TRANSIENT";
}
}
class DefaultRetryBackoffStrategy {
x = Retry.delay();
computeNextBackoffDelay(i) {
const b = Math.random();
const r = 2;
const t_i = b * Math.min(this.x * r ** i, MAXIMUM_RETRY_DELAY);
return Math.floor(t_i);
}
setDelayBase(delay) {
this.x = delay;
}
}
class DefaultRetryToken {
delay;
count;
cost;
longPoll;
$retryLog = {
acquisitionDelay: 0,
};
constructor(delay, count, cost, longPoll) {
this.delay = delay;
this.count = count;
this.cost = cost;
this.longPoll = longPoll;
}
getRetryCount() {
return this.count;
}
getRetryDelay() {
return Math.min(MAXIMUM_RETRY_DELAY, this.delay);
}
getRetryCost() {
return this.cost;
}
isLongPoll() {
return this.longPoll;
}
}
exports.RETRY_MODES = void 0;
(function (RETRY_MODES) {
RETRY_MODES["STANDARD"] = "standard";
RETRY_MODES["ADAPTIVE"] = "adaptive";
})(exports.RETRY_MODES || (exports.RETRY_MODES = {}));
const DEFAULT_MAX_ATTEMPTS = 3;
const DEFAULT_RETRY_MODE = exports.RETRY_MODES.STANDARD;
const refusal = {
incompatible: 1,
attempts: 2,
capacity: 3,
};
let StandardRetryStrategy$1 = class StandardRetryStrategy {
mode = exports.RETRY_MODES.STANDARD;
retryBackoffStrategy;
capacity = INITIAL_RETRY_TOKENS;
maxAttemptsProvider;
baseDelay;
constructor(arg1) {
if (typeof arg1 === "number") {
this.maxAttemptsProvider = async () => arg1;
}
else if (typeof arg1 === "function") {
this.maxAttemptsProvider = arg1;
}
else if (arg1 && typeof arg1 === "object") {
this.maxAttemptsProvider = async () => arg1.maxAttempts;
this.baseDelay = arg1.baseDelay;
this.retryBackoffStrategy = arg1.backoff;
}
this.maxAttemptsProvider ??= async () => DEFAULT_MAX_ATTEMPTS;
this.baseDelay ??= Retry.delay();
this.retryBackoffStrategy ??= new DefaultRetryBackoffStrategy();
}
async acquireInitialRetryToken(retryTokenScope) {
return new DefaultRetryToken(Retry.delay(), 0, undefined, Retry.v2026 && retryTokenScope.includes(":longpoll"));
}
async refreshRetryTokenForRetry(token, errorInfo) {
const maxAttempts = await this.getMaxAttempts();
const retryCode = this.retryCode(token, errorInfo, maxAttempts);
const shouldRetry = retryCode === 0;
const isLongPoll = token.isLongPoll?.();
if (shouldRetry || isLongPoll) {
const errorType = errorInfo.errorType;
this.retryBackoffStrategy.setDelayBase(errorType === "THROTTLING" ? Retry.throttlingDelay() : this.baseDelay);
const delayFromErrorType = this.retryBackoffStrategy.computeNextBackoffDelay(token.getRetryCount());
let retryDelay = delayFromErrorType;
if (errorInfo.retryAfterHint instanceof Date) {
retryDelay = Math.max(delayFromErrorType, Math.min(errorInfo.retryAfterHint.getTime() - Date.now(), delayFromErrorType + 5_000));
}
if (!shouldRetry) {
const longPollBackoff = Retry.v2026 && retryCode === refusal.capacity && isLongPoll ? retryDelay : 0;
if (longPollBackoff > 0) {
await new Promise((r) => setTimeout(r, longPollBackoff));
}
}
else {
const capacityCost = this.getCapacityCost(errorType);
this.capacity -= capacityCost;
const nextToken = new DefaultRetryToken(0, token.getRetryCount() + 1, capacityCost, token.isLongPoll?.() ?? false);
await new Promise((r) => setTimeout(r, retryDelay));
nextToken.$retryLog.acquisitionDelay = retryDelay;
return nextToken;
}
}
throw new Error("No retry token available");
}
recordSuccess(token) {
this.capacity = Math.min(INITIAL_RETRY_TOKENS, this.capacity + (token.getRetryCost() ?? NO_RETRY_INCREMENT));
}
getCapacity() {
return this.capacity;
}
async maxAttempts() {
return this.maxAttemptsProvider();
}
async getMaxAttempts() {
try {
return await this.maxAttemptsProvider();
}
catch (error) {
console.warn(`Max attempts provider could not resolve. Using default of ${DEFAULT_MAX_ATTEMPTS}`);
return DEFAULT_MAX_ATTEMPTS;
}
}
retryCode(tokenToRenew, errorInfo, maxAttempts) {
const attempts = tokenToRenew.getRetryCount() + 1;
const retryableStatus = this.isRetryableError(errorInfo.errorType) ? 0 : refusal.incompatible;
const attemptStatus = attempts < maxAttempts ? 0 : refusal.attempts;
const capacityStatus = this.capacity >= this.getCapacityCost(errorInfo.errorType) ? 0 : refusal.capacity;
return retryableStatus || attemptStatus || capacityStatus;
}
getCapacityCost(errorType) {
return errorType === Retry.modifiedCostType() ? Retry.throttlingCost() : Retry.cost();
}
isRetryableError(errorType) {
return errorType === "THROTTLING" || errorType === "TRANSIENT";
}
};
let AdaptiveRetryStrategy$1 = class AdaptiveRetryStrategy {
mode = exports.RETRY_MODES.ADAPTIVE;
rateLimiter;
standardRetryStrategy;
constructor(maxAttemptsProvider, options) {
const { rateLimiter } = options ?? {};
this.rateLimiter = rateLimiter ?? new DefaultRateLimiter();
this.standardRetryStrategy = options
? new StandardRetryStrategy$1({
maxAttempts: typeof maxAttemptsProvider === "number" ? maxAttemptsProvider : 3,
...options,
})
: new StandardRetryStrategy$1(maxAttemptsProvider);
}
async acquireInitialRetryToken(retryTokenScope) {
const token = await this.standardRetryStrategy.acquireInitialRetryToken(retryTokenScope);
await this.rateLimiter.getSendToken();
return token;
}
async refreshRetryTokenForRetry(tokenToRenew, errorInfo) {
this.rateLimiter.updateClientSendingRate(errorInfo);
const token = await this.standardRetryStrategy.refreshRetryTokenForRetry(tokenToRenew, errorInfo);
await this.rateLimiter.getSendToken();
return token;
}
recordSuccess(token) {
this.rateLimiter.updateClientSendingRate({});
this.standardRetryStrategy.recordSuccess(token);
}
async maxAttemptsProvider() {
return this.standardRetryStrategy.maxAttempts();
}
};
class ConfiguredRetryStrategy extends StandardRetryStrategy$1 {
computeNextBackoffDelay;
constructor(maxAttempts, computeNextBackoffDelay = Retry.delay()) {
super(typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts);
if (typeof computeNextBackoffDelay === "number") {
this.computeNextBackoffDelay = () => computeNextBackoffDelay;
}
else {
this.computeNextBackoffDelay = computeNextBackoffDelay;
}
this.retryBackoffStrategy.computeNextBackoffDelay = (completedAttempt) => {
const nextAttempt = completedAttempt + 1;
return this.computeNextBackoffDelay(nextAttempt);
};
}
}
const getDefaultRetryQuota = (initialRetryTokens, options) => {
const MAX_CAPACITY = initialRetryTokens;
const noRetryIncrement = NO_RETRY_INCREMENT;
const retryCost = RETRY_COST;
const timeoutRetryCost = TIMEOUT_RETRY_COST;
let availableCapacity = initialRetryTokens;
const getCapacityAmount = (error) => (error.name === "TimeoutError" ? timeoutRetryCost : retryCost);
const hasRetryTokens = (error) => getCapacityAmount(error) <= availableCapacity;
const retrieveRetryTokens = (error) => {
if (!hasRetryTokens(error)) {
throw new Error("No retry token available");
}
const capacityAmount = getCapacityAmount(error);
availableCapacity -= capacityAmount;
return capacityAmount;
};
const releaseRetryTokens = (capacityReleaseAmount) => {
availableCapacity += capacityReleaseAmount ?? noRetryIncrement;
availableCapacity = Math.min(availableCapacity, MAX_CAPACITY);
};
return Object.freeze({
hasRetryTokens,
retrieveRetryTokens,
releaseRetryTokens,
});
};
const defaultDelayDecider = (delayBase, attempts) => Math.floor(Math.min(MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase));
const defaultRetryDecider = (error) => {
if (!error) {
return false;
}
return isRetryableByTrait(error) || isClockSkewError(error) || isThrottlingError(error) || isTransientError(error);
};
class StandardRetryStrategy {
maxAttemptsProvider;
retryDecider;
delayDecider;
retryQuota;
mode = exports.RETRY_MODES.STANDARD;
constructor(maxAttemptsProvider, options) {
this.maxAttemptsProvider = maxAttemptsProvider;
this.retryDecider = options?.retryDecider ?? defaultRetryDecider;
this.delayDecider = options?.delayDecider ?? defaultDelayDecider;
this.retryQuota = options?.retryQuota ?? getDefaultRetryQuota(INITIAL_RETRY_TOKENS);
}
shouldRetry(error, attempts, maxAttempts) {
return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error);
}
async getMaxAttempts() {
let maxAttempts;
try {
maxAttempts = await this.maxAttemptsProvider();
}
catch (error) {
maxAttempts = DEFAULT_MAX_ATTEMPTS;
}
return maxAttempts;
}
async retry(next, args, options) {
let retryTokenAmount;
let attempts = 0;
let totalDelay = 0;
const maxAttempts = await this.getMaxAttempts();
const { request } = args;
if (protocols.HttpRequest.isInstance(request)) {
request.headers[INVOCATION_ID_HEADER] = serde.v4();
}
while (true) {
try {
if (protocols.HttpRequest.isInstance(request)) {
request.headers[REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
}
if (options?.beforeRequest) {
await options.beforeRequest();
}
const { response, output } = await next(args);
if (options?.afterRequest) {
options.afterRequest(response);
}
this.retryQuota.releaseRetryTokens(retryTokenAmount);
output.$metadata.attempts = attempts + 1;
output.$metadata.totalRetryDelay = totalDelay;
return { response, output };
}
catch (e) {
const err = asSdkError(e);
attempts++;
if (this.shouldRetry(err, attempts, maxAttempts)) {
retryTokenAmount = this.retryQuota.retrieveRetryTokens(err);
const delayFromDecider = this.delayDecider(isThrottlingError(err) ? THROTTLING_RETRY_DELAY_BASE : DEFAULT_RETRY_DELAY_BASE, attempts);
const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
const delay = Math.max(delayFromResponse || 0, delayFromDecider);
totalDelay += delay;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
if (!err.$metadata) {
err.$metadata = {};
}
err.$metadata.attempts = attempts;
err.$metadata.totalRetryDelay = totalDelay;
throw err;
}
}
}
}
const getDelayFromRetryAfterHeader = (response) => {
if (!protocols.HttpResponse.isInstance(response))
return;
const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after");
if (!retryAfterHeaderName)
return;
const retryAfter = response.headers[retryAfterHeaderName];
const retryAfterSeconds = Number(retryAfter);
if (!Number.isNaN(retryAfterSeconds))
return retryAfterSeconds * 1000;
const retryAfterDate = new Date(retryAfter);
return retryAfterDate.getTime() - Date.now();
};
class AdaptiveRetryStrategy extends StandardRetryStrategy {
rateLimiter;
constructor(maxAttemptsProvider, options) {
const { rateLimiter, ...superOptions } = options ?? {};
super(maxAttemptsProvider, superOptions);
this.rateLimiter = rateLimiter ?? new DefaultRateLimiter();
this.mode = exports.RETRY_MODES.ADAPTIVE;
}
async retry(next, args) {
return super.retry(next, args, {
beforeRequest: async () => {
return this.rateLimiter.getSendToken();
},
afterRequest: (response) => {
this.rateLimiter.updateClientSendingRate(response);
},
});
}
}
const resolveRetryConfig = (input, defaults) => {
const { retryStrategy, retryMode } = input;
const { defaultMaxAttempts = DEFAULT_MAX_ATTEMPTS, defaultBaseDelay = Retry.delay() } = defaults ?? {};
const maxAttemptsProvider = client.normalizeProvider(input.maxAttempts ?? defaultMaxAttempts);
let controller = retryStrategy
? Promise.resolve(retryStrategy)
: undefined;
const getDefault = async () => {
const maxAttempts = await maxAttemptsProvider();
const adaptive = (await client.normalizeProvider(retryMode)()) === exports.RETRY_MODES.ADAPTIVE;
if (adaptive) {
return new AdaptiveRetryStrategy$1(maxAttemptsProvider, {
maxAttempts,
baseDelay: defaultBaseDelay,
});
}
return new StandardRetryStrategy$1({
maxAttempts,
baseDelay: defaultBaseDelay,
});
};
return Object.assign(input, {
maxAttempts: maxAttemptsProvider,
retryStrategy: () => (controller ??= getDefault()),
});
};
const omitRetryHeadersMiddleware = () => (next) => async (args) => {
const { request } = args;
if (protocols.HttpRequest.isInstance(request)) {
delete request.headers[INVOCATION_ID_HEADER];
delete request.headers[REQUEST_HEADER];
}
return next(args);
};
const omitRetryHeadersMiddlewareOptions = {
name: "omitRetryHeadersMiddleware",
tags: ["RETRY", "HEADERS", "OMIT_RETRY_HEADERS"],
relation: "before",
toMiddleware: "awsAuthMiddleware",
override: true,
};
const getOmitRetryHeadersPlugin = (options) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(omitRetryHeadersMiddleware(), omitRetryHeadersMiddlewareOptions);
},
});
const no = Symbol.for("node-only");
const ENV_MAX_ATTEMPTS = no;
const CONFIG_MAX_ATTEMPTS = no;
const NODE_MAX_ATTEMPT_CONFIG_OPTIONS = no;
const ENV_RETRY_MODE = no;
const CONFIG_RETRY_MODE = no;
const NODE_RETRY_MODE_CONFIG_OPTIONS = no;
const retryMiddleware = bindRetryMiddleware(isStreamingPayload);
const getRetryPlugin = bindGetRetryPlugin(isStreamingPayload);
exports.AdaptiveRetryStrategy = AdaptiveRetryStrategy$1;
exports.CONFIG_MAX_ATTEMPTS = CONFIG_MAX_ATTEMPTS;
exports.CONFIG_RETRY_MODE = CONFIG_RETRY_MODE;
exports.ConfiguredRetryStrategy = ConfiguredRetryStrategy;
exports.DEFAULT_MAX_ATTEMPTS = DEFAULT_MAX_ATTEMPTS;
exports.DEFAULT_RETRY_DELAY_BASE = DEFAULT_RETRY_DELAY_BASE;
exports.DEFAULT_RETRY_MODE = DEFAULT_RETRY_MODE;
exports.DefaultRateLimiter = DefaultRateLimiter;
exports.DeprecatedAdaptiveRetryStrategy = AdaptiveRetryStrategy;
exports.DeprecatedStandardRetryStrategy = StandardRetryStrategy;
exports.ENV_MAX_ATTEMPTS = ENV_MAX_ATTEMPTS;
exports.ENV_RETRY_MODE = ENV_RETRY_MODE;
exports.INITIAL_RETRY_TOKENS = INITIAL_RETRY_TOKENS;
exports.INVOCATION_ID_HEADER = INVOCATION_ID_HEADER;
exports.MAXIMUM_RETRY_DELAY = MAXIMUM_RETRY_DELAY;
exports.NODE_MAX_ATTEMPT_CONFIG_OPTIONS = NODE_MAX_ATTEMPT_CONFIG_OPTIONS;
exports.NODE_RETRY_MODE_CONFIG_OPTIONS = NODE_RETRY_MODE_CONFIG_OPTIONS;
exports.NO_RETRY_INCREMENT = NO_RETRY_INCREMENT;
exports.REQUEST_HEADER = REQUEST_HEADER;
exports.RETRY_COST = RETRY_COST;
exports.Retry = Retry;
exports.StandardRetryStrategy = StandardRetryStrategy$1;
exports.THROTTLING_RETRY_DELAY_BASE = THROTTLING_RETRY_DELAY_BASE;
exports.TIMEOUT_RETRY_COST = TIMEOUT_RETRY_COST;
exports.defaultDelayDecider = defaultDelayDecider;
exports.defaultRetryDecider = defaultRetryDecider;
exports.getOmitRetryHeadersPlugin = getOmitRetryHeadersPlugin;
exports.getRetryAfterHint = getRetryAfterHint;
exports.getRetryPlugin = getRetryPlugin;
exports.isBrowserNetworkError = isBrowserNetworkError;
exports.isClockSkewCorrectedError = isClockSkewCorrectedError;
exports.isClockSkewError = isClockSkewError;
exports.isNodeJsHttp2TransientError = isNodeJsHttp2TransientError;
exports.isRetryableByTrait = isRetryableByTrait;
exports.isServerError = isServerError;
exports.isThrottlingError = isThrottlingError;
exports.isTransientError = isTransientError;
exports.omitRetryHeadersMiddleware = omitRetryHeadersMiddleware;
exports.omitRetryHeadersMiddlewareOptions = omitRetryHeadersMiddlewareOptions;
exports.resolveRetryConfig = resolveRetryConfig;
exports.retryMiddleware = retryMiddleware;
exports.retryMiddlewareOptions = retryMiddlewareOptions;
+844
View File
@@ -0,0 +1,844 @@
'use strict';
var node_stream = require('node:stream');
var client = require('@smithy/core/client');
var protocols = require('@smithy/core/protocols');
var serde = require('@smithy/core/serde');
const isStreamingPayload = (request) => request?.body instanceof node_stream.Readable ||
(typeof ReadableStream !== "undefined" && request?.body instanceof ReadableStream);
const CLOCK_SKEW_ERROR_CODES = [
"AuthFailure",
"InvalidSignatureException",
"RequestExpired",
"RequestInTheFuture",
"RequestTimeTooSkewed",
"SignatureDoesNotMatch",
];
const THROTTLING_ERROR_CODES = [
"BandwidthLimitExceeded",
"EC2ThrottledException",
"LimitExceededException",
"PriorRequestNotComplete",
"ProvisionedThroughputExceededException",
"RequestLimitExceeded",
"RequestThrottled",
"RequestThrottledException",
"SlowDown",
"ThrottledException",
"Throttling",
"ThrottlingException",
"TooManyRequestsException",
"TransactionInProgressException",
];
const TRANSIENT_ERROR_CODES = ["TimeoutError", "RequestTimeout", "RequestTimeoutException"];
const TRANSIENT_ERROR_STATUS_CODES = [500, 502, 503, 504];
const NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT"];
const NODEJS_NETWORK_ERROR_CODES = ["EHOSTUNREACH", "ENETUNREACH", "ENOTFOUND", "EAI_AGAIN"];
const isRetryableByTrait = (error) => error?.$retryable !== undefined;
const isClockSkewError = (error) => CLOCK_SKEW_ERROR_CODES.includes(error.name);
const isClockSkewCorrectedError = (error) => error.$metadata?.clockSkewCorrected;
const isBrowserNetworkError = (error) => {
const errorMessages = new Set([
"Failed to fetch",
"NetworkError when attempting to fetch resource",
"The Internet connection appears to be offline",
"Load failed",
"Network request failed",
]);
const isValid = error && error instanceof TypeError;
if (!isValid) {
return false;
}
return errorMessages.has(error.message);
};
const isThrottlingError = (error) => error.$metadata?.httpStatusCode === 429 ||
THROTTLING_ERROR_CODES.includes(error.name) ||
error.$retryable?.throttling == true;
const isTransientError = (error, depth = 0) => isRetryableByTrait(error) ||
isClockSkewCorrectedError(error) ||
(error.name === "InvalidSignatureException" && error.message?.includes("Signature expired")) ||
TRANSIENT_ERROR_CODES.includes(error.name) ||
NODEJS_TIMEOUT_ERROR_CODES.includes(error?.code || "") ||
NODEJS_NETWORK_ERROR_CODES.includes(error?.code || "") ||
TRANSIENT_ERROR_STATUS_CODES.includes(error.$metadata?.httpStatusCode || 0) ||
isBrowserNetworkError(error) ||
isNodeJsHttp2TransientError(error) ||
(error.cause !== undefined && depth <= 10 && isTransientError(error.cause, depth + 1));
const isServerError = (error) => {
if (error.$metadata?.httpStatusCode !== undefined) {
const statusCode = error.$metadata.httpStatusCode;
if (500 <= statusCode && statusCode <= 599 && !isTransientError(error)) {
return true;
}
return false;
}
return false;
};
function isNodeJsHttp2TransientError(error) {
return error.code === "ERR_HTTP2_STREAM_ERROR" && error.message.includes("NGHTTP2_REFUSED_STREAM");
}
const DEFAULT_RETRY_DELAY_BASE = 100;
const MAXIMUM_RETRY_DELAY = 20 * 1000;
const THROTTLING_RETRY_DELAY_BASE = 500;
const INITIAL_RETRY_TOKENS = 500;
const RETRY_COST = 5;
const TIMEOUT_RETRY_COST = 10;
const NO_RETRY_INCREMENT = 1;
const INVOCATION_ID_HEADER = "amz-sdk-invocation-id";
const REQUEST_HEADER = "amz-sdk-request";
function parseRetryAfterHeader(response, logger) {
if (!protocols.HttpResponse.isInstance(response)) {
return;
}
for (const header of Object.keys(response.headers)) {
const h = header.toLowerCase();
if (h === "retry-after") {
const retryAfter = response.headers[header];
let retryAfterSeconds = NaN;
if (retryAfter.endsWith("GMT")) {
try {
const date = serde.parseRfc7231DateTime(retryAfter);
retryAfterSeconds = (date.getTime() - Date.now()) / 1000;
}
catch (e) {
logger?.trace?.("Failed to parse retry-after header");
logger?.trace?.(e);
}
}
else if (retryAfter.match(/ GMT, ((\d+)|(\d+\.\d+))$/)) {
retryAfterSeconds = Number(retryAfter.match(/ GMT, ([\d.]+)$/)?.[1]);
}
else if (retryAfter.match(/^((\d+)|(\d+\.\d+))$/)) {
retryAfterSeconds = Number(retryAfter);
}
else if (Date.parse(retryAfter) >= Date.now()) {
retryAfterSeconds = (Date.parse(retryAfter) - Date.now()) / 1000;
}
if (isNaN(retryAfterSeconds)) {
return;
}
return new Date(Date.now() + retryAfterSeconds * 1000);
}
else if (h === "x-amz-retry-after") {
const v = response.headers[header];
const backoffMilliseconds = Number(v);
if (isNaN(backoffMilliseconds)) {
logger?.trace?.(`Failed to parse x-amz-retry-after=${v}`);
return;
}
return new Date(Date.now() + backoffMilliseconds);
}
}
}
function getRetryAfterHint(response, logger) {
return parseRetryAfterHeader(response, logger);
}
const asSdkError = (error) => {
if (error instanceof Error)
return error;
if (error instanceof Object)
return Object.assign(new Error(), error);
if (typeof error === "string")
return new Error(error);
return new Error(`AWS SDK error wrapper for ${error}`);
};
function bindRetryMiddleware(isStreamingPayload) {
return (options) => (next, context) => async (args) => {
let retryStrategy = await options.retryStrategy();
const maxAttempts = await options.maxAttempts();
if (isRetryStrategyV2(retryStrategy)) {
retryStrategy = retryStrategy;
let retryToken = await retryStrategy.acquireInitialRetryToken((context["partition_id"] ?? "") + (context.__retryLongPoll ? ":longpoll" : ""));
let lastError = new Error();
let attempts = 0;
let totalRetryDelay = 0;
const { request } = args;
const isRequest = protocols.HttpRequest.isInstance(request);
if (isRequest) {
request.headers[INVOCATION_ID_HEADER] = serde.v4();
}
while (true) {
try {
if (isRequest) {
request.headers[REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
}
const { response, output } = await next(args);
retryStrategy.recordSuccess(retryToken);
output.$metadata.attempts = attempts + 1;
output.$metadata.totalRetryDelay = totalRetryDelay;
return { response, output };
}
catch (e) {
const retryErrorInfo = getRetryErrorInfo(e, options.logger);
lastError = asSdkError(e);
if (isRequest && isStreamingPayload(request)) {
(context.logger instanceof client.NoOpLogger ? console : context.logger)?.warn("An error was encountered in a non-retryable streaming request.");
throw lastError;
}
try {
retryToken = await retryStrategy.refreshRetryTokenForRetry(retryToken, retryErrorInfo);
}
catch (refreshError) {
if (!lastError.$metadata) {
lastError.$metadata = {};
}
lastError.$metadata.attempts = attempts + 1;
lastError.$metadata.totalRetryDelay = totalRetryDelay;
throw lastError;
}
attempts = retryToken.getRetryCount();
const delay = retryToken.getRetryDelay();
totalRetryDelay += (retryToken?.$retryLog?.acquisitionDelay ?? 0) + delay;
if (delay > 0) {
await cooldown(delay);
}
}
}
}
else {
retryStrategy = retryStrategy;
if (retryStrategy?.mode) {
context.userAgent = [...(context.userAgent || []), ["cfg/retry-mode", retryStrategy.mode]];
}
return retryStrategy.retry(next, args);
}
};
}
const cooldown = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" &&
typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" &&
typeof retryStrategy.recordSuccess !== "undefined";
const getRetryErrorInfo = (error, logger) => {
const errorInfo = {
error,
errorType: getRetryErrorType(error),
};
const retryAfterHint = parseRetryAfterHeader(error.$response, logger);
if (retryAfterHint) {
errorInfo.retryAfterHint = retryAfterHint;
}
return errorInfo;
};
const getRetryErrorType = (error) => {
if (isThrottlingError(error))
return "THROTTLING";
if (isTransientError(error))
return "TRANSIENT";
if (isServerError(error))
return "SERVER_ERROR";
return "CLIENT_ERROR";
};
const retryMiddlewareOptions = {
name: "retryMiddleware",
tags: ["RETRY"],
step: "finalizeRequest",
priority: "high",
override: true,
};
function bindGetRetryPlugin(isStreamingPayload) {
const retryMiddleware = bindRetryMiddleware(isStreamingPayload);
return (options) => ({
applyToStack: (clientStack) => {
clientStack.add(retryMiddleware(options), retryMiddlewareOptions);
},
});
}
class DefaultRateLimiter {
static setTimeoutFn = setTimeout;
beta;
minCapacity;
minFillRate;
scaleConstant;
smooth;
enabled = false;
availableTokens = 0;
lastMaxRate = 0;
measuredTxRate = 0;
requestCount = 0;
fillRate;
lastThrottleTime;
lastTimestamp = 0;
lastTxRateBucket;
maxCapacity;
timeWindow = 0;
constructor(options) {
this.beta = options?.beta ?? 0.7;
this.minCapacity = options?.minCapacity ?? 1;
this.minFillRate = options?.minFillRate ?? 0.5;
this.scaleConstant = options?.scaleConstant ?? 0.4;
this.smooth = options?.smooth ?? 0.8;
this.lastThrottleTime = this.getCurrentTimeInSeconds();
this.lastTxRateBucket = Math.floor(this.getCurrentTimeInSeconds());
this.fillRate = this.minFillRate;
this.maxCapacity = this.minCapacity;
}
async getSendToken() {
return this.acquireTokenBucket(1);
}
updateClientSendingRate(response) {
let calculatedRate;
this.updateMeasuredRate();
const retryErrorInfo = response;
const isThrottling = retryErrorInfo?.errorType === "THROTTLING" || isThrottlingError(retryErrorInfo?.error ?? response);
if (isThrottling) {
const rateToUse = !this.enabled ? this.measuredTxRate : Math.min(this.measuredTxRate, this.fillRate);
this.lastMaxRate = rateToUse;
this.calculateTimeWindow();
this.lastThrottleTime = this.getCurrentTimeInSeconds();
calculatedRate = this.cubicThrottle(rateToUse);
this.enableTokenBucket();
}
else {
this.calculateTimeWindow();
calculatedRate = this.cubicSuccess(this.getCurrentTimeInSeconds());
}
const newRate = Math.min(calculatedRate, 2 * this.measuredTxRate);
this.updateTokenBucketRate(newRate);
}
getCurrentTimeInSeconds() {
return Date.now() / 1000;
}
async acquireTokenBucket(amount) {
if (!this.enabled) {
return;
}
this.refillTokenBucket();
while (amount > this.availableTokens) {
const delay = ((amount - this.availableTokens) / this.fillRate) * 1000;
await new Promise((resolve) => DefaultRateLimiter.setTimeoutFn(resolve, delay));
this.refillTokenBucket();
}
this.availableTokens = this.availableTokens - amount;
}
refillTokenBucket() {
const timestamp = this.getCurrentTimeInSeconds();
if (!this.lastTimestamp) {
this.lastTimestamp = timestamp;
return;
}
const fillAmount = (timestamp - this.lastTimestamp) * this.fillRate;
this.availableTokens = Math.min(this.maxCapacity, this.availableTokens + fillAmount);
this.lastTimestamp = timestamp;
}
calculateTimeWindow() {
this.timeWindow = this.getPrecise(Math.pow((this.lastMaxRate * (1 - this.beta)) / this.scaleConstant, 1 / 3));
}
cubicThrottle(rateToUse) {
return this.getPrecise(rateToUse * this.beta);
}
cubicSuccess(timestamp) {
return this.getPrecise(this.scaleConstant * Math.pow(timestamp - this.lastThrottleTime - this.timeWindow, 3) + this.lastMaxRate);
}
enableTokenBucket() {
this.enabled = true;
}
updateTokenBucketRate(newRate) {
this.refillTokenBucket();
this.fillRate = Math.max(newRate, this.minFillRate);
this.maxCapacity = Math.max(newRate, this.minCapacity);
this.availableTokens = Math.min(this.availableTokens, this.maxCapacity);
}
updateMeasuredRate() {
const t = this.getCurrentTimeInSeconds();
const timeBucket = Math.floor(t * 2) / 2;
this.requestCount++;
if (timeBucket > this.lastTxRateBucket) {
const currentRate = this.requestCount / (timeBucket - this.lastTxRateBucket);
this.measuredTxRate = this.getPrecise(currentRate * this.smooth + this.measuredTxRate * (1 - this.smooth));
this.requestCount = 0;
this.lastTxRateBucket = timeBucket;
}
}
getPrecise(num) {
return parseFloat(num.toFixed(8));
}
}
class Retry {
static v2026 = typeof process !== "undefined" && process.env?.SMITHY_NEW_RETRIES_2026 === "true";
static delay() {
return Retry.v2026 ? 50 : 100;
}
static throttlingDelay() {
return Retry.v2026 ? 1_000 : 500;
}
static cost() {
return Retry.v2026 ? 14 : 5;
}
static throttlingCost() {
return Retry.v2026 ? 5 : 10;
}
static modifiedCostType() {
return Retry.v2026 ? "THROTTLING" : "TRANSIENT";
}
}
class DefaultRetryBackoffStrategy {
x = Retry.delay();
computeNextBackoffDelay(i) {
const b = Math.random();
const r = 2;
const t_i = b * Math.min(this.x * r ** i, MAXIMUM_RETRY_DELAY);
return Math.floor(t_i);
}
setDelayBase(delay) {
this.x = delay;
}
}
class DefaultRetryToken {
delay;
count;
cost;
longPoll;
$retryLog = {
acquisitionDelay: 0,
};
constructor(delay, count, cost, longPoll) {
this.delay = delay;
this.count = count;
this.cost = cost;
this.longPoll = longPoll;
}
getRetryCount() {
return this.count;
}
getRetryDelay() {
return Math.min(MAXIMUM_RETRY_DELAY, this.delay);
}
getRetryCost() {
return this.cost;
}
isLongPoll() {
return this.longPoll;
}
}
exports.RETRY_MODES = void 0;
(function (RETRY_MODES) {
RETRY_MODES["STANDARD"] = "standard";
RETRY_MODES["ADAPTIVE"] = "adaptive";
})(exports.RETRY_MODES || (exports.RETRY_MODES = {}));
const DEFAULT_MAX_ATTEMPTS = 3;
const DEFAULT_RETRY_MODE = exports.RETRY_MODES.STANDARD;
const refusal = {
incompatible: 1,
attempts: 2,
capacity: 3,
};
let StandardRetryStrategy$1 = class StandardRetryStrategy {
mode = exports.RETRY_MODES.STANDARD;
retryBackoffStrategy;
capacity = INITIAL_RETRY_TOKENS;
maxAttemptsProvider;
baseDelay;
constructor(arg1) {
if (typeof arg1 === "number") {
this.maxAttemptsProvider = async () => arg1;
}
else if (typeof arg1 === "function") {
this.maxAttemptsProvider = arg1;
}
else if (arg1 && typeof arg1 === "object") {
this.maxAttemptsProvider = async () => arg1.maxAttempts;
this.baseDelay = arg1.baseDelay;
this.retryBackoffStrategy = arg1.backoff;
}
this.maxAttemptsProvider ??= async () => DEFAULT_MAX_ATTEMPTS;
this.baseDelay ??= Retry.delay();
this.retryBackoffStrategy ??= new DefaultRetryBackoffStrategy();
}
async acquireInitialRetryToken(retryTokenScope) {
return new DefaultRetryToken(Retry.delay(), 0, undefined, Retry.v2026 && retryTokenScope.includes(":longpoll"));
}
async refreshRetryTokenForRetry(token, errorInfo) {
const maxAttempts = await this.getMaxAttempts();
const retryCode = this.retryCode(token, errorInfo, maxAttempts);
const shouldRetry = retryCode === 0;
const isLongPoll = token.isLongPoll?.();
if (shouldRetry || isLongPoll) {
const errorType = errorInfo.errorType;
this.retryBackoffStrategy.setDelayBase(errorType === "THROTTLING" ? Retry.throttlingDelay() : this.baseDelay);
const delayFromErrorType = this.retryBackoffStrategy.computeNextBackoffDelay(token.getRetryCount());
let retryDelay = delayFromErrorType;
if (errorInfo.retryAfterHint instanceof Date) {
retryDelay = Math.max(delayFromErrorType, Math.min(errorInfo.retryAfterHint.getTime() - Date.now(), delayFromErrorType + 5_000));
}
if (!shouldRetry) {
const longPollBackoff = Retry.v2026 && retryCode === refusal.capacity && isLongPoll ? retryDelay : 0;
if (longPollBackoff > 0) {
await new Promise((r) => setTimeout(r, longPollBackoff));
}
}
else {
const capacityCost = this.getCapacityCost(errorType);
this.capacity -= capacityCost;
const nextToken = new DefaultRetryToken(0, token.getRetryCount() + 1, capacityCost, token.isLongPoll?.() ?? false);
await new Promise((r) => setTimeout(r, retryDelay));
nextToken.$retryLog.acquisitionDelay = retryDelay;
return nextToken;
}
}
throw new Error("No retry token available");
}
recordSuccess(token) {
this.capacity = Math.min(INITIAL_RETRY_TOKENS, this.capacity + (token.getRetryCost() ?? NO_RETRY_INCREMENT));
}
getCapacity() {
return this.capacity;
}
async maxAttempts() {
return this.maxAttemptsProvider();
}
async getMaxAttempts() {
try {
return await this.maxAttemptsProvider();
}
catch (error) {
console.warn(`Max attempts provider could not resolve. Using default of ${DEFAULT_MAX_ATTEMPTS}`);
return DEFAULT_MAX_ATTEMPTS;
}
}
retryCode(tokenToRenew, errorInfo, maxAttempts) {
const attempts = tokenToRenew.getRetryCount() + 1;
const retryableStatus = this.isRetryableError(errorInfo.errorType) ? 0 : refusal.incompatible;
const attemptStatus = attempts < maxAttempts ? 0 : refusal.attempts;
const capacityStatus = this.capacity >= this.getCapacityCost(errorInfo.errorType) ? 0 : refusal.capacity;
return retryableStatus || attemptStatus || capacityStatus;
}
getCapacityCost(errorType) {
return errorType === Retry.modifiedCostType() ? Retry.throttlingCost() : Retry.cost();
}
isRetryableError(errorType) {
return errorType === "THROTTLING" || errorType === "TRANSIENT";
}
};
let AdaptiveRetryStrategy$1 = class AdaptiveRetryStrategy {
mode = exports.RETRY_MODES.ADAPTIVE;
rateLimiter;
standardRetryStrategy;
constructor(maxAttemptsProvider, options) {
const { rateLimiter } = options ?? {};
this.rateLimiter = rateLimiter ?? new DefaultRateLimiter();
this.standardRetryStrategy = options
? new StandardRetryStrategy$1({
maxAttempts: typeof maxAttemptsProvider === "number" ? maxAttemptsProvider : 3,
...options,
})
: new StandardRetryStrategy$1(maxAttemptsProvider);
}
async acquireInitialRetryToken(retryTokenScope) {
const token = await this.standardRetryStrategy.acquireInitialRetryToken(retryTokenScope);
await this.rateLimiter.getSendToken();
return token;
}
async refreshRetryTokenForRetry(tokenToRenew, errorInfo) {
this.rateLimiter.updateClientSendingRate(errorInfo);
const token = await this.standardRetryStrategy.refreshRetryTokenForRetry(tokenToRenew, errorInfo);
await this.rateLimiter.getSendToken();
return token;
}
recordSuccess(token) {
this.rateLimiter.updateClientSendingRate({});
this.standardRetryStrategy.recordSuccess(token);
}
async maxAttemptsProvider() {
return this.standardRetryStrategy.maxAttempts();
}
};
class ConfiguredRetryStrategy extends StandardRetryStrategy$1 {
computeNextBackoffDelay;
constructor(maxAttempts, computeNextBackoffDelay = Retry.delay()) {
super(typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts);
if (typeof computeNextBackoffDelay === "number") {
this.computeNextBackoffDelay = () => computeNextBackoffDelay;
}
else {
this.computeNextBackoffDelay = computeNextBackoffDelay;
}
this.retryBackoffStrategy.computeNextBackoffDelay = (completedAttempt) => {
const nextAttempt = completedAttempt + 1;
return this.computeNextBackoffDelay(nextAttempt);
};
}
}
const getDefaultRetryQuota = (initialRetryTokens, options) => {
const MAX_CAPACITY = initialRetryTokens;
const noRetryIncrement = NO_RETRY_INCREMENT;
const retryCost = RETRY_COST;
const timeoutRetryCost = TIMEOUT_RETRY_COST;
let availableCapacity = initialRetryTokens;
const getCapacityAmount = (error) => (error.name === "TimeoutError" ? timeoutRetryCost : retryCost);
const hasRetryTokens = (error) => getCapacityAmount(error) <= availableCapacity;
const retrieveRetryTokens = (error) => {
if (!hasRetryTokens(error)) {
throw new Error("No retry token available");
}
const capacityAmount = getCapacityAmount(error);
availableCapacity -= capacityAmount;
return capacityAmount;
};
const releaseRetryTokens = (capacityReleaseAmount) => {
availableCapacity += capacityReleaseAmount ?? noRetryIncrement;
availableCapacity = Math.min(availableCapacity, MAX_CAPACITY);
};
return Object.freeze({
hasRetryTokens,
retrieveRetryTokens,
releaseRetryTokens,
});
};
const defaultDelayDecider = (delayBase, attempts) => Math.floor(Math.min(MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase));
const defaultRetryDecider = (error) => {
if (!error) {
return false;
}
return isRetryableByTrait(error) || isClockSkewError(error) || isThrottlingError(error) || isTransientError(error);
};
class StandardRetryStrategy {
maxAttemptsProvider;
retryDecider;
delayDecider;
retryQuota;
mode = exports.RETRY_MODES.STANDARD;
constructor(maxAttemptsProvider, options) {
this.maxAttemptsProvider = maxAttemptsProvider;
this.retryDecider = options?.retryDecider ?? defaultRetryDecider;
this.delayDecider = options?.delayDecider ?? defaultDelayDecider;
this.retryQuota = options?.retryQuota ?? getDefaultRetryQuota(INITIAL_RETRY_TOKENS);
}
shouldRetry(error, attempts, maxAttempts) {
return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error);
}
async getMaxAttempts() {
let maxAttempts;
try {
maxAttempts = await this.maxAttemptsProvider();
}
catch (error) {
maxAttempts = DEFAULT_MAX_ATTEMPTS;
}
return maxAttempts;
}
async retry(next, args, options) {
let retryTokenAmount;
let attempts = 0;
let totalDelay = 0;
const maxAttempts = await this.getMaxAttempts();
const { request } = args;
if (protocols.HttpRequest.isInstance(request)) {
request.headers[INVOCATION_ID_HEADER] = serde.v4();
}
while (true) {
try {
if (protocols.HttpRequest.isInstance(request)) {
request.headers[REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
}
if (options?.beforeRequest) {
await options.beforeRequest();
}
const { response, output } = await next(args);
if (options?.afterRequest) {
options.afterRequest(response);
}
this.retryQuota.releaseRetryTokens(retryTokenAmount);
output.$metadata.attempts = attempts + 1;
output.$metadata.totalRetryDelay = totalDelay;
return { response, output };
}
catch (e) {
const err = asSdkError(e);
attempts++;
if (this.shouldRetry(err, attempts, maxAttempts)) {
retryTokenAmount = this.retryQuota.retrieveRetryTokens(err);
const delayFromDecider = this.delayDecider(isThrottlingError(err) ? THROTTLING_RETRY_DELAY_BASE : DEFAULT_RETRY_DELAY_BASE, attempts);
const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
const delay = Math.max(delayFromResponse || 0, delayFromDecider);
totalDelay += delay;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
if (!err.$metadata) {
err.$metadata = {};
}
err.$metadata.attempts = attempts;
err.$metadata.totalRetryDelay = totalDelay;
throw err;
}
}
}
}
const getDelayFromRetryAfterHeader = (response) => {
if (!protocols.HttpResponse.isInstance(response))
return;
const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after");
if (!retryAfterHeaderName)
return;
const retryAfter = response.headers[retryAfterHeaderName];
const retryAfterSeconds = Number(retryAfter);
if (!Number.isNaN(retryAfterSeconds))
return retryAfterSeconds * 1000;
const retryAfterDate = new Date(retryAfter);
return retryAfterDate.getTime() - Date.now();
};
class AdaptiveRetryStrategy extends StandardRetryStrategy {
rateLimiter;
constructor(maxAttemptsProvider, options) {
const { rateLimiter, ...superOptions } = options ?? {};
super(maxAttemptsProvider, superOptions);
this.rateLimiter = rateLimiter ?? new DefaultRateLimiter();
this.mode = exports.RETRY_MODES.ADAPTIVE;
}
async retry(next, args) {
return super.retry(next, args, {
beforeRequest: async () => {
return this.rateLimiter.getSendToken();
},
afterRequest: (response) => {
this.rateLimiter.updateClientSendingRate(response);
},
});
}
}
const ENV_MAX_ATTEMPTS = "AWS_MAX_ATTEMPTS";
const CONFIG_MAX_ATTEMPTS = "max_attempts";
const NODE_MAX_ATTEMPT_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => {
const value = env[ENV_MAX_ATTEMPTS];
if (!value)
return undefined;
const maxAttempt = parseInt(value);
if (Number.isNaN(maxAttempt)) {
throw new Error(`Environment variable ${ENV_MAX_ATTEMPTS} mast be a number, got "${value}"`);
}
return maxAttempt;
},
configFileSelector: (profile) => {
const value = profile[CONFIG_MAX_ATTEMPTS];
if (!value)
return undefined;
const maxAttempt = parseInt(value);
if (Number.isNaN(maxAttempt)) {
throw new Error(`Shared config file entry ${CONFIG_MAX_ATTEMPTS} mast be a number, got "${value}"`);
}
return maxAttempt;
},
default: DEFAULT_MAX_ATTEMPTS,
};
const resolveRetryConfig = (input, defaults) => {
const { retryStrategy, retryMode } = input;
const { defaultMaxAttempts = DEFAULT_MAX_ATTEMPTS, defaultBaseDelay = Retry.delay() } = defaults ?? {};
const maxAttemptsProvider = client.normalizeProvider(input.maxAttempts ?? defaultMaxAttempts);
let controller = retryStrategy
? Promise.resolve(retryStrategy)
: undefined;
const getDefault = async () => {
const maxAttempts = await maxAttemptsProvider();
const adaptive = (await client.normalizeProvider(retryMode)()) === exports.RETRY_MODES.ADAPTIVE;
if (adaptive) {
return new AdaptiveRetryStrategy$1(maxAttemptsProvider, {
maxAttempts,
baseDelay: defaultBaseDelay,
});
}
return new StandardRetryStrategy$1({
maxAttempts,
baseDelay: defaultBaseDelay,
});
};
return Object.assign(input, {
maxAttempts: maxAttemptsProvider,
retryStrategy: () => (controller ??= getDefault()),
});
};
const ENV_RETRY_MODE = "AWS_RETRY_MODE";
const CONFIG_RETRY_MODE = "retry_mode";
const NODE_RETRY_MODE_CONFIG_OPTIONS = {
environmentVariableSelector: (env) => env[ENV_RETRY_MODE],
configFileSelector: (profile) => profile[CONFIG_RETRY_MODE],
default: DEFAULT_RETRY_MODE,
};
const omitRetryHeadersMiddleware = () => (next) => async (args) => {
const { request } = args;
if (protocols.HttpRequest.isInstance(request)) {
delete request.headers[INVOCATION_ID_HEADER];
delete request.headers[REQUEST_HEADER];
}
return next(args);
};
const omitRetryHeadersMiddlewareOptions = {
name: "omitRetryHeadersMiddleware",
tags: ["RETRY", "HEADERS", "OMIT_RETRY_HEADERS"],
relation: "before",
toMiddleware: "awsAuthMiddleware",
override: true,
};
const getOmitRetryHeadersPlugin = (options) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(omitRetryHeadersMiddleware(), omitRetryHeadersMiddlewareOptions);
},
});
const retryMiddleware = bindRetryMiddleware(isStreamingPayload);
const getRetryPlugin = bindGetRetryPlugin(isStreamingPayload);
exports.AdaptiveRetryStrategy = AdaptiveRetryStrategy$1;
exports.CONFIG_MAX_ATTEMPTS = CONFIG_MAX_ATTEMPTS;
exports.CONFIG_RETRY_MODE = CONFIG_RETRY_MODE;
exports.ConfiguredRetryStrategy = ConfiguredRetryStrategy;
exports.DEFAULT_MAX_ATTEMPTS = DEFAULT_MAX_ATTEMPTS;
exports.DEFAULT_RETRY_DELAY_BASE = DEFAULT_RETRY_DELAY_BASE;
exports.DEFAULT_RETRY_MODE = DEFAULT_RETRY_MODE;
exports.DefaultRateLimiter = DefaultRateLimiter;
exports.DeprecatedAdaptiveRetryStrategy = AdaptiveRetryStrategy;
exports.DeprecatedStandardRetryStrategy = StandardRetryStrategy;
exports.ENV_MAX_ATTEMPTS = ENV_MAX_ATTEMPTS;
exports.ENV_RETRY_MODE = ENV_RETRY_MODE;
exports.INITIAL_RETRY_TOKENS = INITIAL_RETRY_TOKENS;
exports.INVOCATION_ID_HEADER = INVOCATION_ID_HEADER;
exports.MAXIMUM_RETRY_DELAY = MAXIMUM_RETRY_DELAY;
exports.NODE_MAX_ATTEMPT_CONFIG_OPTIONS = NODE_MAX_ATTEMPT_CONFIG_OPTIONS;
exports.NODE_RETRY_MODE_CONFIG_OPTIONS = NODE_RETRY_MODE_CONFIG_OPTIONS;
exports.NO_RETRY_INCREMENT = NO_RETRY_INCREMENT;
exports.REQUEST_HEADER = REQUEST_HEADER;
exports.RETRY_COST = RETRY_COST;
exports.Retry = Retry;
exports.StandardRetryStrategy = StandardRetryStrategy$1;
exports.THROTTLING_RETRY_DELAY_BASE = THROTTLING_RETRY_DELAY_BASE;
exports.TIMEOUT_RETRY_COST = TIMEOUT_RETRY_COST;
exports.defaultDelayDecider = defaultDelayDecider;
exports.defaultRetryDecider = defaultRetryDecider;
exports.getOmitRetryHeadersPlugin = getOmitRetryHeadersPlugin;
exports.getRetryAfterHint = getRetryAfterHint;
exports.getRetryPlugin = getRetryPlugin;
exports.isBrowserNetworkError = isBrowserNetworkError;
exports.isClockSkewCorrectedError = isClockSkewCorrectedError;
exports.isClockSkewError = isClockSkewError;
exports.isNodeJsHttp2TransientError = isNodeJsHttp2TransientError;
exports.isRetryableByTrait = isRetryableByTrait;
exports.isServerError = isServerError;
exports.isThrottlingError = isThrottlingError;
exports.isTransientError = isTransientError;
exports.omitRetryHeadersMiddleware = omitRetryHeadersMiddleware;
exports.omitRetryHeadersMiddlewareOptions = omitRetryHeadersMiddlewareOptions;
exports.resolveRetryConfig = resolveRetryConfig;
exports.retryMiddleware = retryMiddleware;
exports.retryMiddlewareOptions = retryMiddlewareOptions;
+713
View File
@@ -0,0 +1,713 @@
'use strict';
var transport = require('@smithy/core/transport');
const deref = (schemaRef) => {
if (typeof schemaRef === "function") {
return schemaRef();
}
return schemaRef;
};
const operation = (namespace, name, traits, input, output) => ({
name,
namespace,
traits,
input,
output,
});
const schemaDeserializationMiddleware = (config) => (next, context) => async (args) => {
const { response } = await next(args);
const { operationSchema } = transport.getSmithyContext(context);
const [, ns, n, t, i, o] = operationSchema ?? [];
try {
const parsed = await config.protocol.deserializeResponse(operation(ns, n, t, i, o), {
...config,
...context,
}, response);
return {
response,
output: parsed,
};
}
catch (error) {
Object.defineProperty(error, "$response", {
value: response,
enumerable: false,
writable: false,
configurable: false,
});
if (!("$metadata" in error)) {
const hint = `Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.`;
try {
error.message += "\n " + hint;
}
catch (e) {
if (!context.logger || context.logger?.constructor?.name === "NoOpLogger") {
console.warn(hint);
}
else {
context.logger?.warn?.(hint);
}
}
if (typeof error.$responseBodyText !== "undefined") {
if (error.$response) {
error.$response.body = error.$responseBodyText;
}
}
try {
if (transport.HttpResponse.isInstance(response)) {
const { headers = {}, statusCode } = response;
const headerEntries = Object.entries(headers);
error.$metadata = {
httpStatusCode: statusCode,
requestId: findHeader(/^x-[\w-]+-request-?id$/, headerEntries),
extendedRequestId: findHeader(/^x-[\w-]+-id-2$/, headerEntries),
cfId: findHeader(/^x-[\w-]+-cf-id$/, headerEntries),
};
}
}
catch (e) {
}
}
throw error;
}
};
const findHeader = (pattern, headers) => {
return (headers.find(([k]) => {
return k.match(pattern);
}) || [void 0, void 0])[1];
};
const schemaSerializationMiddleware = (config) => (next, context) => async (args) => {
const { operationSchema } = transport.getSmithyContext(context);
const [, ns, n, t, i, o] = operationSchema ?? [];
const endpoint = context.endpointV2
? async () => transport.toEndpointV1(context.endpointV2)
: config.endpoint;
const request = await config.protocol.serializeRequest(operation(ns, n, t, i, o), args.input, {
...config,
...context,
endpoint,
});
return next({
...args,
request,
});
};
const deserializerMiddlewareOption = {
name: "deserializerMiddleware",
step: "deserialize",
tags: ["DESERIALIZER"],
override: true,
};
const serializerMiddlewareOption = {
name: "serializerMiddleware",
step: "serialize",
tags: ["SERIALIZER"],
override: true,
};
function getSchemaSerdePlugin(config) {
return {
applyToStack: (commandStack) => {
commandStack.add(schemaSerializationMiddleware(config), serializerMiddlewareOption);
commandStack.add(schemaDeserializationMiddleware(config), deserializerMiddlewareOption);
config.protocol.setSerdeContext(config);
},
};
}
class Schema {
name;
namespace;
traits;
static assign(instance, values) {
const schema = Object.assign(instance, values);
return schema;
}
static [Symbol.hasInstance](lhs) {
const isPrototype = this.prototype.isPrototypeOf(lhs);
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
const list = lhs;
return list.symbol === this.symbol;
}
return isPrototype;
}
getName() {
return this.namespace + "#" + this.name;
}
}
class ListSchema extends Schema {
static symbol = Symbol.for("@smithy/lis");
name;
traits;
valueSchema;
symbol = ListSchema.symbol;
}
const list = (namespace, name, traits, valueSchema) => Schema.assign(new ListSchema(), {
name,
namespace,
traits,
valueSchema,
});
class MapSchema extends Schema {
static symbol = Symbol.for("@smithy/map");
name;
traits;
keySchema;
valueSchema;
symbol = MapSchema.symbol;
}
const map = (namespace, name, traits, keySchema, valueSchema) => Schema.assign(new MapSchema(), {
name,
namespace,
traits,
keySchema,
valueSchema,
});
class OperationSchema extends Schema {
static symbol = Symbol.for("@smithy/ope");
name;
traits;
input;
output;
symbol = OperationSchema.symbol;
}
const op = (namespace, name, traits, input, output) => Schema.assign(new OperationSchema(), {
name,
namespace,
traits,
input,
output,
});
class StructureSchema extends Schema {
static symbol = Symbol.for("@smithy/str");
name;
traits;
memberNames;
memberList;
symbol = StructureSchema.symbol;
}
const struct = (namespace, name, traits, memberNames, memberList) => Schema.assign(new StructureSchema(), {
name,
namespace,
traits,
memberNames,
memberList,
});
class ErrorSchema extends StructureSchema {
static symbol = Symbol.for("@smithy/err");
ctor;
symbol = ErrorSchema.symbol;
}
const error = (namespace, name, traits, memberNames, memberList, ctor) => Schema.assign(new ErrorSchema(), {
name,
namespace,
traits,
memberNames,
memberList,
ctor: null,
});
const traitsCache = [];
function translateTraits(indicator) {
if (typeof indicator === "object") {
return indicator;
}
indicator = indicator | 0;
if (traitsCache[indicator]) {
return traitsCache[indicator];
}
const traits = {};
let i = 0;
for (const trait of [
"httpLabel",
"idempotent",
"idempotencyToken",
"sensitive",
"httpPayload",
"httpResponseCode",
"httpQueryParams",
]) {
if (((indicator >> i++) & 1) === 1) {
traits[trait] = 1;
}
}
return (traitsCache[indicator] = traits);
}
const anno = {
it: Symbol.for("@smithy/nor-struct-it"),
ns: Symbol.for("@smithy/ns"),
};
const simpleSchemaCacheN = [];
const simpleSchemaCacheS = {};
class NormalizedSchema {
ref;
memberName;
static symbol = Symbol.for("@smithy/nor");
symbol = NormalizedSchema.symbol;
name;
schema;
_isMemberSchema;
traits;
memberTraits;
normalizedTraits;
constructor(ref, memberName) {
this.ref = ref;
this.memberName = memberName;
const traitStack = [];
let _ref = ref;
let schema = ref;
this._isMemberSchema = false;
while (isMemberSchema(_ref)) {
traitStack.push(_ref[1]);
_ref = _ref[0];
schema = deref(_ref);
this._isMemberSchema = true;
}
if (traitStack.length > 0) {
this.memberTraits = {};
for (let i = traitStack.length - 1; i >= 0; --i) {
const traitSet = traitStack[i];
Object.assign(this.memberTraits, translateTraits(traitSet));
}
}
else {
this.memberTraits = 0;
}
if (schema instanceof NormalizedSchema) {
const computedMemberTraits = this.memberTraits;
Object.assign(this, schema);
this.memberTraits = Object.assign({}, computedMemberTraits, schema.getMemberTraits(), this.getMemberTraits());
this.normalizedTraits = void 0;
this.memberName = memberName ?? schema.memberName;
return;
}
this.schema = deref(schema);
if (isStaticSchema(this.schema)) {
this.name = `${this.schema[1]}#${this.schema[2]}`;
this.traits = this.schema[3];
}
else {
this.name = this.memberName ?? String(schema);
this.traits = 0;
}
if (this._isMemberSchema && !memberName) {
throw new Error(`@smithy/core/schema - NormalizedSchema member init ${this.getName(true)} missing member name.`);
}
}
static [Symbol.hasInstance](lhs) {
const isPrototype = this.prototype.isPrototypeOf(lhs);
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
const ns = lhs;
return ns.symbol === this.symbol;
}
return isPrototype;
}
static of(ref) {
const keyAble = typeof ref === "function" || (typeof ref === "object" && ref !== null);
if (typeof ref === "number") {
if (simpleSchemaCacheN[ref]) {
return simpleSchemaCacheN[ref];
}
}
else if (typeof ref === "string") {
if (simpleSchemaCacheS[ref]) {
return simpleSchemaCacheS[ref];
}
}
else if (keyAble) {
if (ref[anno.ns]) {
return ref[anno.ns];
}
}
const sc = deref(ref);
if (sc instanceof NormalizedSchema) {
return sc;
}
if (isMemberSchema(sc)) {
const [ns, traits] = sc;
if (ns instanceof NormalizedSchema) {
Object.assign(ns.getMergedTraits(), translateTraits(traits));
return ns;
}
throw new Error(`@smithy/core/schema - may not init unwrapped member schema=${JSON.stringify(ref, null, 2)}.`);
}
const ns = new NormalizedSchema(sc);
if (keyAble) {
return (ref[anno.ns] = ns);
}
if (typeof sc === "string") {
return (simpleSchemaCacheS[sc] = ns);
}
if (typeof sc === "number") {
return (simpleSchemaCacheN[sc] = ns);
}
return ns;
}
getSchema() {
const sc = this.schema;
if (Array.isArray(sc) && sc[0] === 0) {
return sc[4];
}
return sc;
}
getName(withNamespace = false) {
const { name } = this;
const short = !withNamespace && name && name.includes("#");
return short ? name.split("#")[1] : name || undefined;
}
getMemberName() {
return this.memberName;
}
isMemberSchema() {
return this._isMemberSchema;
}
isListSchema() {
const sc = this.getSchema();
return typeof sc === "number"
? sc >= 64 && sc < 128
: sc[0] === 1;
}
isMapSchema() {
const sc = this.getSchema();
return typeof sc === "number"
? sc >= 128 && sc <= 0b1111_1111
: sc[0] === 2;
}
isStructSchema() {
const sc = this.getSchema();
if (typeof sc !== "object") {
return false;
}
const id = sc[0];
return (id === 3 ||
id === -3 ||
id === 4);
}
isUnionSchema() {
const sc = this.getSchema();
if (typeof sc !== "object") {
return false;
}
return sc[0] === 4;
}
isBlobSchema() {
const sc = this.getSchema();
return sc === 21 || sc === 42;
}
isTimestampSchema() {
const sc = this.getSchema();
return (typeof sc === "number" &&
sc >= 4 &&
sc <= 7);
}
isUnitSchema() {
return this.getSchema() === "unit";
}
isDocumentSchema() {
return this.getSchema() === 15;
}
isStringSchema() {
return this.getSchema() === 0;
}
isBooleanSchema() {
return this.getSchema() === 2;
}
isNumericSchema() {
return this.getSchema() === 1;
}
isBigIntegerSchema() {
return this.getSchema() === 17;
}
isBigDecimalSchema() {
return this.getSchema() === 19;
}
isStreaming() {
const { streaming } = this.getMergedTraits();
return !!streaming || this.getSchema() === 42;
}
isIdempotencyToken() {
return !!this.getMergedTraits().idempotencyToken;
}
getMergedTraits() {
return (this.normalizedTraits ??
(this.normalizedTraits = {
...this.getOwnTraits(),
...this.getMemberTraits(),
}));
}
getMemberTraits() {
return translateTraits(this.memberTraits);
}
getOwnTraits() {
return translateTraits(this.traits);
}
getKeySchema() {
const [isDoc, isMap] = [this.isDocumentSchema(), this.isMapSchema()];
if (!isDoc && !isMap) {
throw new Error(`@smithy/core/schema - cannot get key for non-map: ${this.getName(true)}`);
}
const schema = this.getSchema();
const memberSchema = isDoc
? 15
: schema[4] ?? 0;
return member([memberSchema, 0], "key");
}
getValueSchema() {
const sc = this.getSchema();
const [isDoc, isMap, isList] = [this.isDocumentSchema(), this.isMapSchema(), this.isListSchema()];
const memberSchema = typeof sc === "number"
? 0b0011_1111 & sc
: sc && typeof sc === "object" && (isMap || isList)
? sc[3 + sc[0]]
: isDoc
? 15
: void 0;
if (memberSchema != null) {
return member([memberSchema, 0], isMap ? "value" : "member");
}
throw new Error(`@smithy/core/schema - ${this.getName(true)} has no value member.`);
}
getMemberSchema(memberName) {
const struct = this.getSchema();
if (this.isStructSchema() && struct[4].includes(memberName)) {
const i = struct[4].indexOf(memberName);
const memberSchema = struct[5][i];
return member(isMemberSchema(memberSchema) ? memberSchema : [memberSchema, 0], memberName);
}
if (this.isDocumentSchema()) {
return member([15, 0], memberName);
}
throw new Error(`@smithy/core/schema - ${this.getName(true)} has no member=${memberName}.`);
}
getMemberSchemas() {
const buffer = {};
try {
for (const [k, v] of this.structIterator()) {
buffer[k] = v;
}
}
catch (ignored) { }
return buffer;
}
getEventStreamMember() {
if (this.isStructSchema()) {
for (const [memberName, memberSchema] of this.structIterator()) {
if (memberSchema.isStreaming() && memberSchema.isStructSchema()) {
return memberName;
}
}
}
return "";
}
*structIterator() {
if (this.isUnitSchema()) {
return;
}
if (!this.isStructSchema()) {
throw new Error("@smithy/core/schema - cannot iterate non-struct schema.");
}
const struct = this.getSchema();
const z = struct[4].length;
let it = struct[anno.it];
if (it && z === it.length) {
yield* it;
return;
}
it = Array(z);
for (let i = 0; i < z; ++i) {
const k = struct[4][i];
const v = member([struct[5][i], 0], k);
yield (it[i] = [k, v]);
}
struct[anno.it] = it;
}
}
function member(memberSchema, memberName) {
if (memberSchema instanceof NormalizedSchema) {
return Object.assign(memberSchema, {
memberName,
_isMemberSchema: true,
});
}
const internalCtorAccess = NormalizedSchema;
return new internalCtorAccess(memberSchema, memberName);
}
const isMemberSchema = (sc) => Array.isArray(sc) && sc.length === 2;
const isStaticSchema = (sc) => Array.isArray(sc) && sc.length >= 5;
class SimpleSchema extends Schema {
static symbol = Symbol.for("@smithy/sim");
name;
schemaRef;
traits;
symbol = SimpleSchema.symbol;
}
const sim = (namespace, name, schemaRef, traits) => Schema.assign(new SimpleSchema(), {
name,
namespace,
traits,
schemaRef,
});
const simAdapter = (namespace, name, traits, schemaRef) => Schema.assign(new SimpleSchema(), {
name,
namespace,
traits,
schemaRef,
});
const SCHEMA = {
BLOB: 0b0001_0101,
STREAMING_BLOB: 0b0010_1010,
BOOLEAN: 0b0000_0010,
STRING: 0b0000_0000,
NUMERIC: 0b0000_0001,
BIG_INTEGER: 0b0001_0001,
BIG_DECIMAL: 0b0001_0011,
DOCUMENT: 0b0000_1111,
TIMESTAMP_DEFAULT: 0b0000_0100,
TIMESTAMP_DATE_TIME: 0b0000_0101,
TIMESTAMP_HTTP_DATE: 0b0000_0110,
TIMESTAMP_EPOCH_SECONDS: 0b0000_0111,
LIST_MODIFIER: 0b0100_0000,
MAP_MODIFIER: 0b1000_0000,
};
class TypeRegistry {
namespace;
schemas;
exceptions;
static registries = new Map();
constructor(namespace, schemas = new Map(), exceptions = new Map()) {
this.namespace = namespace;
this.schemas = schemas;
this.exceptions = exceptions;
}
static for(namespace) {
if (!TypeRegistry.registries.has(namespace)) {
TypeRegistry.registries.set(namespace, new TypeRegistry(namespace));
}
return TypeRegistry.registries.get(namespace);
}
copyFrom(other) {
const { schemas, exceptions } = this;
for (const [k, v] of other.schemas) {
if (!schemas.has(k)) {
schemas.set(k, v);
}
}
for (const [k, v] of other.exceptions) {
if (!exceptions.has(k)) {
exceptions.set(k, v);
}
}
}
register(shapeId, schema) {
const qualifiedName = this.normalizeShapeId(shapeId);
for (const r of [this, TypeRegistry.for(qualifiedName.split("#")[0])]) {
r.schemas.set(qualifiedName, schema);
}
}
getSchema(shapeId) {
const id = this.normalizeShapeId(shapeId);
if (!this.schemas.has(id)) {
if (!shapeId.includes("#")) {
const suffix = "#" + shapeId;
const candidates = [];
for (const [shapeId, schema] of this.schemas.entries()) {
if (shapeId.endsWith(suffix)) {
candidates.push(schema);
}
}
if (candidates.length === 1) {
return candidates[0];
}
}
throw new Error(`@smithy/core/schema - schema not found for ${id}`);
}
return this.schemas.get(id);
}
registerError(es, ctor) {
const $error = es;
const ns = $error[1];
for (const r of [this, TypeRegistry.for(ns)]) {
r.schemas.set(ns + "#" + $error[2], $error);
r.exceptions.set($error, ctor);
}
}
getErrorCtor(es) {
const $error = es;
if (this.exceptions.has($error)) {
return this.exceptions.get($error);
}
const registry = TypeRegistry.for($error[1]);
return registry.exceptions.get($error);
}
getBaseException() {
for (const exceptionKey of this.exceptions.keys()) {
if (Array.isArray(exceptionKey)) {
const [, ns, name] = exceptionKey;
const id = ns + "#" + name;
if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
return exceptionKey;
}
}
}
return undefined;
}
find(predicate) {
for (const schema of this.schemas.values()) {
if (predicate(schema)) {
return schema;
}
}
return undefined;
}
clear() {
this.schemas.clear();
this.exceptions.clear();
}
normalizeShapeId(shapeId) {
if (shapeId.includes("#")) {
return shapeId;
}
return this.namespace + "#" + shapeId;
}
}
exports.ErrorSchema = ErrorSchema;
exports.ListSchema = ListSchema;
exports.MapSchema = MapSchema;
exports.NormalizedSchema = NormalizedSchema;
exports.OperationSchema = OperationSchema;
exports.SCHEMA = SCHEMA;
exports.Schema = Schema;
exports.SimpleSchema = SimpleSchema;
exports.StructureSchema = StructureSchema;
exports.TypeRegistry = TypeRegistry;
exports.deref = deref;
exports.deserializerMiddlewareOption = deserializerMiddlewareOption;
exports.error = error;
exports.getSchemaSerdePlugin = getSchemaSerdePlugin;
exports.isStaticSchema = isStaticSchema;
exports.list = list;
exports.map = map;
exports.op = op;
exports.operation = operation;
exports.serializerMiddlewareOption = serializerMiddlewareOption;
exports.sim = sim;
exports.simAdapter = simAdapter;
exports.simpleSchemaCacheN = simpleSchemaCacheN;
exports.simpleSchemaCacheS = simpleSchemaCacheS;
exports.struct = struct;
exports.traitsCache = traitsCache;
exports.translateTraits = translateTraits;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+184
View File
@@ -0,0 +1,184 @@
'use strict';
var types = require('@smithy/types');
const getSmithyContext = (context) => context[types.SMITHY_CONTEXT_KEY] || (context[types.SMITHY_CONTEXT_KEY] = {});
class HttpRequest {
method;
protocol;
hostname;
port;
path;
query;
headers;
username;
password;
fragment;
body;
constructor(options) {
this.method = options.method || "GET";
this.hostname = options.hostname || "localhost";
this.port = options.port;
this.query = options.query || {};
this.headers = options.headers || {};
this.body = options.body;
this.protocol = options.protocol
? options.protocol.slice(-1) !== ":"
? `${options.protocol}:`
: options.protocol
: "https:";
this.path = options.path ? (options.path.charAt(0) !== "/" ? `/${options.path}` : options.path) : "/";
this.username = options.username;
this.password = options.password;
this.fragment = options.fragment;
}
static clone(request) {
const cloned = new HttpRequest({
...request,
headers: { ...request.headers },
});
if (cloned.query) {
cloned.query = cloneQuery(cloned.query);
}
return cloned;
}
static isInstance(request) {
if (!request) {
return false;
}
const req = request;
return ("method" in req &&
"protocol" in req &&
"hostname" in req &&
"path" in req &&
typeof req["query"] === "object" &&
typeof req["headers"] === "object");
}
clone() {
return HttpRequest.clone(this);
}
}
function cloneQuery(query) {
return Object.keys(query).reduce((carry, paramName) => {
const param = query[paramName];
return {
...carry,
[paramName]: Array.isArray(param) ? [...param] : param,
};
}, {});
}
class HttpResponse {
statusCode;
reason;
headers;
body;
constructor(options) {
this.statusCode = options.statusCode;
this.reason = options.reason;
this.headers = options.headers || {};
this.body = options.body;
}
static isInstance(response) {
if (!response)
return false;
const resp = response;
return typeof resp.statusCode === "number" && typeof resp.headers === "object";
}
}
const VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`);
const isValidHostLabel = (value, allowSubDomains = false) => {
if (!allowSubDomains) {
return VALID_HOST_LABEL_REGEX.test(value);
}
const labels = value.split(".");
for (const label of labels) {
if (!isValidHostLabel(label)) {
return false;
}
}
return true;
};
function isValidHostname(hostname) {
const hostPattern = /^[a-z0-9][a-z0-9\.\-]*[a-z0-9]$/;
return hostPattern.test(hostname);
}
const normalizeProvider = (input) => {
if (typeof input === "function")
return input;
const promisified = Promise.resolve(input);
return () => promisified;
};
function parseQueryString(querystring) {
const query = {};
querystring = querystring.replace(/^\?/, "");
if (querystring) {
for (const pair of querystring.split("&")) {
let [key, value = null] = pair.split("=");
key = decodeURIComponent(key);
if (value) {
value = decodeURIComponent(value);
}
if (!(key in query)) {
query[key] = value;
}
else if (Array.isArray(query[key])) {
query[key].push(value);
}
else {
query[key] = [query[key], value];
}
}
}
return query;
}
const parseUrl = (url) => {
if (typeof url === "string") {
return parseUrl(new URL(url));
}
const { hostname, pathname, port, protocol, search } = url;
let query;
if (search) {
query = parseQueryString(search);
}
return {
hostname,
port: port ? parseInt(port) : undefined,
protocol,
path: pathname,
query,
};
};
const toEndpointV1 = (endpoint) => {
if (typeof endpoint === "object") {
if ("url" in endpoint) {
const v1Endpoint = parseUrl(endpoint.url);
if (endpoint.headers) {
v1Endpoint.headers = {};
for (const name in endpoint.headers) {
v1Endpoint.headers[name.toLowerCase()] = endpoint.headers[name].join(", ");
}
}
return v1Endpoint;
}
return endpoint;
}
return parseUrl(endpoint);
};
exports.HttpRequest = HttpRequest;
exports.HttpResponse = HttpResponse;
exports.getSmithyContext = getSmithyContext;
exports.isValidHostLabel = isValidHostLabel;
exports.isValidHostname = isValidHostname;
exports.normalizeProvider = normalizeProvider;
exports.parseQueryString = parseQueryString;
exports.parseUrl = parseUrl;
exports.toEndpointV1 = toEndpointV1;
+8
View File
@@ -0,0 +1,8 @@
export { getSmithyContext } from "@smithy/core/transport";
export * from "./legacy-root-exports/middleware-http-auth-scheme";
export * from "./legacy-root-exports/middleware-http-signing";
export * from "./normalizeProvider";
export { createPaginator } from "./legacy-root-exports/pagination/createPaginator";
export { requestBuilder } from "@smithy/core/protocols";
export * from "./setFeature";
export * from "./legacy-root-exports/util-identity-and-auth";
@@ -0,0 +1,17 @@
import { httpAuthSchemeMiddleware } from "./httpAuthSchemeMiddleware";
export const httpAuthSchemeEndpointRuleSetMiddlewareOptions = {
step: "serialize",
tags: ["HTTP_AUTH_SCHEME"],
name: "httpAuthSchemeMiddleware",
override: true,
relation: "before",
toMiddleware: "endpointV2Middleware",
};
export const getHttpAuthSchemeEndpointRuleSetPlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider,
identityProviderConfigProvider,
}), httpAuthSchemeEndpointRuleSetMiddlewareOptions);
},
});
@@ -0,0 +1,17 @@
import { httpAuthSchemeMiddleware } from "./httpAuthSchemeMiddleware";
export const httpAuthSchemeMiddlewareOptions = {
step: "serialize",
tags: ["HTTP_AUTH_SCHEME"],
name: "httpAuthSchemeMiddleware",
override: true,
relation: "before",
toMiddleware: "serializerMiddleware",
};
export const getHttpAuthSchemePlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider,
identityProviderConfigProvider,
}), httpAuthSchemeMiddlewareOptions);
},
});
@@ -0,0 +1,42 @@
import { getSmithyContext } from "@smithy/core/client";
import { resolveAuthOptions } from "./resolveAuthOptions";
function convertHttpAuthSchemesToMap(httpAuthSchemes) {
const map = new Map();
for (const scheme of httpAuthSchemes) {
map.set(scheme.schemeId, scheme);
}
return map;
}
export const httpAuthSchemeMiddleware = (config, mwOptions) => (next, context) => async (args) => {
const options = config.httpAuthSchemeProvider(await mwOptions.httpAuthSchemeParametersProvider(config, context, args.input));
const authSchemePreference = config.authSchemePreference ? await config.authSchemePreference() : [];
const resolvedOptions = resolveAuthOptions(options, authSchemePreference);
const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes);
const smithyContext = getSmithyContext(context);
const failureReasons = [];
for (const option of resolvedOptions) {
const scheme = authSchemes.get(option.schemeId);
if (!scheme) {
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`);
continue;
}
const identityProvider = scheme.identityProvider(await mwOptions.identityProviderConfigProvider(config));
if (!identityProvider) {
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`);
continue;
}
const { identityProperties = {}, signingProperties = {} } = option.propertiesExtractor?.(config, context) || {};
option.identityProperties = Object.assign(option.identityProperties || {}, identityProperties);
option.signingProperties = Object.assign(option.signingProperties || {}, signingProperties);
smithyContext.selectedHttpAuthScheme = {
httpAuthOption: option,
identity: await identityProvider(option.identityProperties),
signer: scheme.signer,
};
break;
}
if (!smithyContext.selectedHttpAuthScheme) {
throw new Error(failureReasons.join("\n"));
}
return next(args);
};
@@ -0,0 +1,3 @@
export * from "./httpAuthSchemeMiddleware";
export * from "./getHttpAuthSchemeEndpointRuleSetPlugin";
export * from "./getHttpAuthSchemePlugin";
@@ -0,0 +1,20 @@
export const resolveAuthOptions = (candidateAuthOptions, authSchemePreference) => {
if (!authSchemePreference || authSchemePreference.length === 0) {
return candidateAuthOptions;
}
const preferredAuthOptions = [];
for (const preferredSchemeName of authSchemePreference) {
for (const candidateAuthOption of candidateAuthOptions) {
const candidateAuthSchemeName = candidateAuthOption.schemeId.split("#")[1];
if (candidateAuthSchemeName === preferredSchemeName) {
preferredAuthOptions.push(candidateAuthOption);
}
}
}
for (const candidateAuthOption of candidateAuthOptions) {
if (!preferredAuthOptions.find(({ schemeId }) => schemeId === candidateAuthOption.schemeId)) {
preferredAuthOptions.push(candidateAuthOption);
}
}
return preferredAuthOptions;
};
@@ -0,0 +1,15 @@
import { httpSigningMiddleware } from "./httpSigningMiddleware";
export const httpSigningMiddlewareOptions = {
step: "finalizeRequest",
tags: ["HTTP_SIGNING"],
name: "httpSigningMiddleware",
aliases: ["apiKeyMiddleware", "tokenMiddleware", "awsAuthMiddleware"],
override: true,
relation: "after",
toMiddleware: "retryMiddleware",
};
export const getHttpSigningPlugin = (config) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpSigningMiddleware(config), httpSigningMiddlewareOptions);
},
});
@@ -0,0 +1,23 @@
import { getSmithyContext } from "@smithy/core/client";
import { HttpRequest } from "@smithy/core/protocols";
const defaultErrorHandler = (signingProperties) => (error) => {
throw error;
};
const defaultSuccessHandler = (httpResponse, signingProperties) => { };
export const httpSigningMiddleware = (config) => (next, context) => async (args) => {
if (!HttpRequest.isInstance(args.request)) {
return next(args);
}
const smithyContext = getSmithyContext(context);
const scheme = smithyContext.selectedHttpAuthScheme;
if (!scheme) {
throw new Error(`No HttpAuthScheme was selected: unable to sign request`);
}
const { httpAuthOption: { signingProperties = {} }, identity, signer, } = scheme;
const output = await next({
...args,
request: await signer.sign(args.request, identity, signingProperties),
}).catch((signer.errorHandler || defaultErrorHandler)(signingProperties));
(signer.successHandler || defaultSuccessHandler)(output.response, signingProperties);
return output;
};
@@ -0,0 +1,2 @@
export * from "./httpSigningMiddleware";
export * from "./getHttpSigningMiddleware";
@@ -0,0 +1,41 @@
const makePagedClientRequest = async (CommandCtor, client, input, withCommand = (_) => _, ...args) => {
let command = new CommandCtor(input);
command = withCommand(command) ?? command;
return await client.send(command, ...args);
};
export function createPaginator(ClientCtor, CommandCtor, inputTokenName, outputTokenName, pageSizeTokenName) {
return async function* paginateOperation(config, input, ...additionalArguments) {
const _input = input;
let token = config.startingToken ?? _input[inputTokenName];
let hasNext = true;
let page;
while (hasNext) {
_input[inputTokenName] = token;
if (pageSizeTokenName) {
_input[pageSizeTokenName] = _input[pageSizeTokenName] ?? config.pageSize;
}
if (config.client instanceof ClientCtor) {
page = await makePagedClientRequest(CommandCtor, config.client, input, config.withCommand, ...additionalArguments);
}
else {
throw new Error(`Invalid client, expected instance of ${ClientCtor.name}`);
}
yield page;
const prevToken = token;
token = get(page, outputTokenName);
hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken));
}
return undefined;
};
}
const get = (fromObject, path) => {
let cursor = fromObject;
const pathComponents = path.split(".");
for (const step of pathComponents) {
if (!cursor || typeof cursor !== "object") {
return undefined;
}
cursor = cursor[step];
}
return cursor;
};
@@ -0,0 +1,14 @@
export class DefaultIdentityProviderConfig {
authSchemes = new Map();
constructor(config) {
for (const key in config) {
const value = config[key];
if (value !== undefined) {
this.authSchemes.set(key, value);
}
}
}
getIdentityProvider(schemeId) {
return this.authSchemes.get(schemeId);
}
}
@@ -0,0 +1,34 @@
import { HttpRequest } from "@smithy/core/protocols";
import { HttpApiKeyAuthLocation, } from "@smithy/types";
export class HttpApiKeyAuthSigner {
async sign(httpRequest, identity, signingProperties) {
if (!signingProperties) {
throw new Error("request could not be signed with `apiKey` since the `name` and `in` signer properties are missing");
}
if (!signingProperties.name) {
throw new Error("request could not be signed with `apiKey` since the `name` signer property is missing");
}
if (!signingProperties.in) {
throw new Error("request could not be signed with `apiKey` since the `in` signer property is missing");
}
if (!identity.apiKey) {
throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined");
}
const clonedRequest = HttpRequest.clone(httpRequest);
if (signingProperties.in === HttpApiKeyAuthLocation.QUERY) {
clonedRequest.query[signingProperties.name] = identity.apiKey;
}
else if (signingProperties.in === HttpApiKeyAuthLocation.HEADER) {
clonedRequest.headers[signingProperties.name] = signingProperties.scheme
? `${signingProperties.scheme} ${identity.apiKey}`
: identity.apiKey;
}
else {
throw new Error("request can only be signed with `apiKey` locations `query` or `header`, " +
"but found: `" +
signingProperties.in +
"`");
}
return clonedRequest;
}
}
@@ -0,0 +1,11 @@
import { HttpRequest } from "@smithy/core/protocols";
export class HttpBearerAuthSigner {
async sign(httpRequest, identity, signingProperties) {
const clonedRequest = HttpRequest.clone(httpRequest);
if (!identity.token) {
throw new Error("request could not be signed with `token` since the `token` is not defined");
}
clonedRequest.headers["Authorization"] = `Bearer ${identity.token}`;
return clonedRequest;
}
}
@@ -0,0 +1,3 @@
export * from "./httpApiKeyAuth";
export * from "./httpBearerAuth";
export * from "./noAuth";
@@ -0,0 +1,5 @@
export class NoAuthSigner {
async sign(httpRequest, identity, signingProperties) {
return httpRequest;
}
}
@@ -0,0 +1,3 @@
export * from "./DefaultIdentityProviderConfig";
export * from "./httpAuthSchemes";
export * from "./memoizeIdentityProvider";
@@ -0,0 +1,55 @@
export const createIsIdentityExpiredFunction = (expirationMs) => function isIdentityExpired(identity) {
return doesIdentityRequireRefresh(identity) && identity.expiration.getTime() - Date.now() < expirationMs;
};
export const EXPIRATION_MS = 300_000;
export const isIdentityExpired = createIsIdentityExpiredFunction(EXPIRATION_MS);
export const doesIdentityRequireRefresh = (identity) => identity.expiration !== undefined;
export const memoizeIdentityProvider = (provider, isExpired, requiresRefresh) => {
if (provider === undefined) {
return undefined;
}
const normalizedProvider = typeof provider !== "function" ? async () => Promise.resolve(provider) : provider;
let resolved;
let pending;
let hasResult;
let isConstant = false;
const coalesceProvider = async (options) => {
if (!pending) {
pending = normalizedProvider(options);
}
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(options);
}
return resolved;
};
}
return async (options) => {
if (!hasResult || options?.forceRefresh) {
resolved = await coalesceProvider(options);
}
if (isConstant) {
return resolved;
}
if (!requiresRefresh(resolved)) {
isConstant = true;
return resolved;
}
if (isExpired(resolved)) {
await coalesceProvider(options);
return resolved;
}
return resolved;
};
};
+6
View File
@@ -0,0 +1,6 @@
export const normalizeProvider = (input) => {
if (typeof input === "function")
return input;
const promisified = Promise.resolve(input);
return () => promisified;
};
+11
View File
@@ -0,0 +1,11 @@
export function setFeature(context, feature, value) {
if (!context.__smithy_context) {
context.__smithy_context = {
features: {},
};
}
else if (!context.__smithy_context.features) {
context.__smithy_context.features = {};
}
context.__smithy_context.features[feature] = value;
}
+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;
};

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