@fgiova/aws-signature
Version:
[](https://www.npmjs.com/package/@fgiova/aws-signature)  [ • 4.08 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SignerSingleton = exports.Signer = void 0;
const node_os_1 = require("node:os");
const node_path_1 = __importDefault(require("node:path"));
const typebox_1 = require("@sinclair/typebox");
const env_schema_1 = require("env-schema");
const lru_cache_1 = require("lru-cache");
const piscina_1 = __importDefault(require("piscina"));
/* c8 ignore start */
const isTS = node_path_1.default.resolve(__filename).endsWith(".ts");
const isMjs = node_path_1.default.resolve(__filename).endsWith(".mjs");
const runEnv = {
ext: isTS ? "ts" : isMjs ? "mjs" : "js",
execArgv: isTS ? ["-r", "ts-node/register"] : undefined,
};
/* c8 ignore end */
const keyCache = new lru_cache_1.LRUCache({
max: 50,
ttl: 1000 * 60 * 60 * 24,
});
const ConfigSchema = typebox_1.Type.Object({
AWS_ACCESS_KEY_ID: typebox_1.Type.Optional(typebox_1.Type.String()),
AWS_SECRET_ACCESS_KEY: typebox_1.Type.Optional(typebox_1.Type.String()),
AWS_REGION: typebox_1.Type.String({ default: "" }),
});
class Signer {
constructor(options = {}) {
this.cpuCount = (() => {
try {
return (0, node_os_1.cpus)().length;
}
catch {
/* istanbul ignore next */
return 1;
}
})();
const { minThreads, maxThreads, idleTimeout, maxQueue, concurrentTasksPerWorker, resourceLimits, credentials: credentialsOptions, } = options;
const config = (0, env_schema_1.envSchema)({
schema: ConfigSchema,
});
this.credentials = {
region: config.AWS_REGION,
accessKeyId: config.AWS_ACCESS_KEY_ID || "",
secretAccessKey: config.AWS_SECRET_ACCESS_KEY || "",
...credentialsOptions,
};
if (!this.credentials.accessKeyId || !this.credentials.secretAccessKey) {
throw new Error("AWS credentials are required");
}
this.worker = new piscina_1.default({
filename: node_path_1.default.resolve(__dirname, `./sign_worker.${runEnv.ext}`),
execArgv: runEnv.execArgv,
name: "generateKey",
minThreads: minThreads ?? Math.max(this.cpuCount / 2, 1),
maxThreads: maxThreads ?? this.cpuCount * 1.5,
idleTimeout,
maxQueue,
concurrentTasksPerWorker,
resourceLimits,
});
}
millsToNextDay() {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
return Math.abs(tomorrow.getTime() - Date.now());
}
async request(request, service, region, date = new Date()) {
const requestCredentials = {
...this.credentials,
region: region || this.credentials.region,
};
if (!requestCredentials.region) {
throw new Error("Region is required");
}
const keyId = `${service}-${requestCredentials.region}`;
let key = keyCache.get(keyId);
if (!key) {
key = (await this.worker.run({
credentials: requestCredentials,
service,
date,
}));
keyCache.set(keyId, key, {
ttl: this.millsToNextDay(),
});
}
return (await this.worker.run({ credentials: requestCredentials, request, service, key, date }, { name: "signRequest" }));
}
async destroy() {
return this.worker.destroy();
}
}
exports.Signer = Signer;
class SignerSingleton {
constructor() {
throw new Error("Use SignerSingleton.getSigner()");
}
static getSigner(options) {
if (!SignerSingleton.signer) {
SignerSingleton.signer = new Signer(options);
}
return SignerSingleton.signer;
}
}
exports.SignerSingleton = SignerSingleton;