feat(scripts): add s3 script for S3-compatible object storage
Co-authored-by: Nasyarobby Putra <nasyarobby@gmail.com>
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
"migrate": "node -e \"import('./db.js').then((m) => m.migrate().then(() => process.exit(0)))\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.1111.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.1111.0",
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/cors": "^11.1.0",
|
||||
"@fastify/jwt": "^9.1.0",
|
||||
|
||||
@@ -15,6 +15,8 @@ import { getVariablePlain } from "./variables-store.js";
|
||||
const hostRequire = createRequire(import.meta.url);
|
||||
|
||||
const ALLOWED_MODULES = new Set([
|
||||
"@aws-sdk/client-s3",
|
||||
"@aws-sdk/s3-request-presigner",
|
||||
"axios",
|
||||
"jsonata",
|
||||
"mustache",
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
import {
|
||||
CopyObjectCommand,
|
||||
DeleteObjectCommand,
|
||||
GetObjectCommand,
|
||||
HeadObjectCommand,
|
||||
ListObjectsV2Command,
|
||||
PutObjectCommand,
|
||||
S3Client,
|
||||
} from "@aws-sdk/client-s3";
|
||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
||||
|
||||
const ACTIONS = new Set(["list", "read", "write", "delete", "stat", "presign", "copy"]);
|
||||
|
||||
function passContext(ctx) {
|
||||
if (ctx?.context != null && typeof ctx.context === "object" && !Array.isArray(ctx.context)) {
|
||||
return { ...ctx.context };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function mergeData(data) {
|
||||
if (data != null && typeof data === "object" && !Array.isArray(data)) {
|
||||
return { ...data };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function resolveAction(ctx) {
|
||||
const raw = ctx.config?.action ?? ctx.data?.action ?? "list";
|
||||
if (typeof raw !== "string" || raw.length === 0) {
|
||||
throw new Error("s3: action must be a non-empty string");
|
||||
}
|
||||
const action = raw.toLowerCase();
|
||||
if (!ACTIONS.has(action)) {
|
||||
throw new Error(`s3: unsupported action "${raw}"`);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
function resolveBucket(ctx) {
|
||||
const bucket = ctx.config?.bucket ?? ctx.data?.bucket;
|
||||
if (typeof bucket !== "string" || bucket.length === 0) {
|
||||
throw new Error("s3: bucket is required (ctx.config.bucket or ctx.data.bucket)");
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
function resolveKey(ctx, { required = false } = {}) {
|
||||
const key = ctx.config?.key ?? ctx.data?.key;
|
||||
if (key == null || key === "") {
|
||||
if (required) throw new Error("s3: key is required for this action");
|
||||
return undefined;
|
||||
}
|
||||
if (typeof key !== "string") {
|
||||
throw new Error("s3: key must be a string");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
async function resolveSecretValue(secretName, label) {
|
||||
if (typeof secretName !== "string" || secretName.length === 0) {
|
||||
throw new Error(`s3: ${label} is required`);
|
||||
}
|
||||
return $secrets.reveal(await $secrets.get(secretName));
|
||||
}
|
||||
|
||||
async function resolveCredentials(ctx) {
|
||||
const accessKeyIdSecret = ctx.config?.accessKeyIdSecret;
|
||||
const secretAccessKeySecret = ctx.config?.secretAccessKeySecret;
|
||||
|
||||
if (
|
||||
typeof accessKeyIdSecret === "string" &&
|
||||
accessKeyIdSecret.length > 0 &&
|
||||
typeof secretAccessKeySecret === "string" &&
|
||||
secretAccessKeySecret.length > 0
|
||||
) {
|
||||
return {
|
||||
accessKeyId: await resolveSecretValue(accessKeyIdSecret, "accessKeyIdSecret"),
|
||||
secretAccessKey: await resolveSecretValue(secretAccessKeySecret, "secretAccessKeySecret"),
|
||||
};
|
||||
}
|
||||
|
||||
const accessKeyId = ctx.config?.accessKeyId ?? ctx.data?.accessKeyId;
|
||||
const secretAccessKey = ctx.config?.secretAccessKey ?? ctx.data?.secretAccessKey;
|
||||
if (typeof accessKeyId === "string" && typeof secretAccessKey === "string") {
|
||||
return { accessKeyId, secretAccessKey };
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"s3: credentials are required (accessKeyIdSecret + secretAccessKeySecret, or accessKeyId + secretAccessKey)",
|
||||
);
|
||||
}
|
||||
|
||||
function createS3Client(ctx, credentials) {
|
||||
const endpoint = ctx.config?.endpoint ?? ctx.data?.endpoint;
|
||||
const region =
|
||||
typeof ctx.config?.region === "string" && ctx.config.region.length > 0
|
||||
? ctx.config.region
|
||||
: typeof ctx.data?.region === "string" && ctx.data.region.length > 0
|
||||
? ctx.data.region
|
||||
: "us-east-1";
|
||||
|
||||
/** @type {import("@aws-sdk/client-s3").S3ClientConfig} */
|
||||
const options = {
|
||||
region,
|
||||
credentials,
|
||||
};
|
||||
|
||||
if (typeof endpoint === "string" && endpoint.length > 0) {
|
||||
options.endpoint = endpoint;
|
||||
}
|
||||
if (ctx.config?.forcePathStyle === true || ctx.data?.forcePathStyle === true) {
|
||||
options.forcePathStyle = true;
|
||||
}
|
||||
|
||||
return new S3Client(options);
|
||||
}
|
||||
|
||||
function toIsoDate(value) {
|
||||
if (value == null) return null;
|
||||
const date = value instanceof Date ? value : new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return null;
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
function normalizeListedObject(item) {
|
||||
return {
|
||||
key: item.Key ?? null,
|
||||
size: typeof item.Size === "number" ? item.Size : null,
|
||||
modified: toIsoDate(item.LastModified),
|
||||
etag: item.ETag ?? null,
|
||||
storageClass: item.StorageClass ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
async function readObjectBody(body) {
|
||||
if (body == null) return Buffer.alloc(0);
|
||||
if (typeof body.transformToByteArray === "function") {
|
||||
return Buffer.from(await body.transformToByteArray());
|
||||
}
|
||||
/** @type {Buffer[]} */
|
||||
const chunks = [];
|
||||
for await (const chunk of body) {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
}
|
||||
return Buffer.concat(chunks);
|
||||
}
|
||||
|
||||
function resolveWriteBody(ctx) {
|
||||
if (ctx.config != null && typeof ctx.config === "object" && "body" in ctx.config) {
|
||||
return ctx.config.body;
|
||||
}
|
||||
if (ctx.data?.file != null) {
|
||||
const file = ctx.data.file;
|
||||
if (Buffer.isBuffer(file) || file instanceof Uint8Array) {
|
||||
return Buffer.from(file);
|
||||
}
|
||||
}
|
||||
if (ctx.data?.body != null) {
|
||||
const body = ctx.data.body;
|
||||
if (Buffer.isBuffer(body) || body instanceof Uint8Array) {
|
||||
return Buffer.from(body);
|
||||
}
|
||||
if (typeof body === "string") {
|
||||
return Buffer.from(body, "utf8");
|
||||
}
|
||||
return Buffer.from(JSON.stringify(body), "utf8");
|
||||
}
|
||||
throw new Error("s3: write requires ctx.config.body, ctx.data.body, or ctx.data.file");
|
||||
}
|
||||
|
||||
async function s3(ctx) {
|
||||
const action = resolveAction(ctx);
|
||||
const bucket = resolveBucket(ctx);
|
||||
const credentials = await resolveCredentials(ctx);
|
||||
const client = createS3Client(ctx, credentials);
|
||||
|
||||
log.info({ action, bucket }, "s3: starting action");
|
||||
|
||||
/** @type {Record<string, unknown>} */
|
||||
let result = { action, bucket };
|
||||
|
||||
switch (action) {
|
||||
case "list": {
|
||||
const prefix = ctx.config?.prefix ?? ctx.data?.prefix ?? "";
|
||||
const delimiter = ctx.config?.delimiter ?? ctx.data?.delimiter;
|
||||
const maxKeys = Number(ctx.config?.maxKeys ?? ctx.data?.maxKeys ?? 1000);
|
||||
const response = await client.send(
|
||||
new ListObjectsV2Command({
|
||||
Bucket: bucket,
|
||||
Prefix: typeof prefix === "string" ? prefix : "",
|
||||
Delimiter: typeof delimiter === "string" && delimiter.length > 0 ? delimiter : undefined,
|
||||
MaxKeys: Number.isFinite(maxKeys) && maxKeys > 0 ? maxKeys : 1000,
|
||||
}),
|
||||
);
|
||||
const objects = (response.Contents ?? []).map(normalizeListedObject);
|
||||
const prefixes = (response.CommonPrefixes ?? [])
|
||||
.map((entry) => entry.Prefix)
|
||||
.filter((value) => typeof value === "string");
|
||||
result = {
|
||||
...result,
|
||||
prefix: typeof prefix === "string" ? prefix : "",
|
||||
objects,
|
||||
prefixes,
|
||||
count: objects.length,
|
||||
isTruncated: response.IsTruncated === true,
|
||||
nextContinuationToken: response.NextContinuationToken ?? null,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "read": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
const outputVar =
|
||||
typeof ctx.config?.outputVar === "string" && ctx.config.outputVar.length > 0
|
||||
? ctx.config.outputVar
|
||||
: "file";
|
||||
const response = await client.send(
|
||||
new GetObjectCommand({
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
}),
|
||||
);
|
||||
const file = await readObjectBody(response.Body);
|
||||
const contentType = response.ContentType ?? "application/octet-stream";
|
||||
const encoding = ctx.config?.encoding ?? ctx.data?.encoding;
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
[outputVar]: file,
|
||||
contentType,
|
||||
contentLength: file.length,
|
||||
etag: response.ETag ?? null,
|
||||
lastModified: toIsoDate(response.LastModified),
|
||||
};
|
||||
if (encoding === "utf8" || encoding === "text") {
|
||||
result.text = file.toString("utf8");
|
||||
} else if (encoding === "base64") {
|
||||
result.base64 = file.toString("base64");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "write": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
const body = resolveWriteBody(ctx);
|
||||
const contentType =
|
||||
ctx.config?.contentType ??
|
||||
ctx.data?.contentType ??
|
||||
(typeof ctx.data?.body === "string" ? "text/plain; charset=utf-8" : "application/octet-stream");
|
||||
const response = await client.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
Body: body,
|
||||
ContentType: typeof contentType === "string" ? contentType : undefined,
|
||||
}),
|
||||
);
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
etag: response.ETag ?? null,
|
||||
contentLength: body.length,
|
||||
written: true,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "delete": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
await client.send(
|
||||
new DeleteObjectCommand({
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
}),
|
||||
);
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
deleted: true,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "stat": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
const response = await client.send(
|
||||
new HeadObjectCommand({
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
}),
|
||||
);
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
contentType: response.ContentType ?? null,
|
||||
contentLength: typeof response.ContentLength === "number" ? response.ContentLength : null,
|
||||
etag: response.ETag ?? null,
|
||||
lastModified: toIsoDate(response.LastModified),
|
||||
metadata: response.Metadata ?? {},
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "presign": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
const method = String(ctx.config?.presignMethod ?? ctx.data?.presignMethod ?? "get").toLowerCase();
|
||||
const expiresIn = Number(ctx.config?.expiresIn ?? ctx.data?.expiresIn ?? 3600);
|
||||
const command =
|
||||
method === "put"
|
||||
? new PutObjectCommand({ Bucket: bucket, Key: key })
|
||||
: new GetObjectCommand({ Bucket: bucket, Key: key });
|
||||
const url = await getSignedUrl(client, command, {
|
||||
expiresIn: Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 3600,
|
||||
});
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
method,
|
||||
expiresIn: Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 3600,
|
||||
url,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "copy": {
|
||||
const key = resolveKey(ctx, { required: true });
|
||||
const sourceKey = ctx.config?.sourceKey ?? ctx.data?.sourceKey;
|
||||
const sourceBucket = ctx.config?.sourceBucket ?? ctx.data?.sourceBucket ?? bucket;
|
||||
if (typeof sourceKey !== "string" || sourceKey.length === 0) {
|
||||
throw new Error("s3: copy requires sourceKey (ctx.config.sourceKey or ctx.data.sourceKey)");
|
||||
}
|
||||
const response = await client.send(
|
||||
new CopyObjectCommand({
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
CopySource: `${sourceBucket}/${sourceKey}`,
|
||||
}),
|
||||
);
|
||||
result = {
|
||||
...result,
|
||||
key,
|
||||
sourceBucket,
|
||||
sourceKey,
|
||||
etag: response.CopyObjectResult?.ETag ?? null,
|
||||
copied: true,
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(`s3: unsupported action "${action}"`);
|
||||
}
|
||||
|
||||
log.info({ action, bucket, key: result.key ?? null }, "s3: action complete");
|
||||
return {
|
||||
output: { ...mergeData(ctx.data), ...result },
|
||||
context: { ...passContext(ctx), ...result },
|
||||
};
|
||||
}
|
||||
|
||||
s3.meta = {
|
||||
description: "Access S3-compatible object storage (AWS S3, MinIO, Cloudflare R2, etc.)",
|
||||
previewConfigKey: "action",
|
||||
tags: ["S3", "storage"],
|
||||
config: {
|
||||
action: {
|
||||
type: "string",
|
||||
default: "list",
|
||||
enum: ["list", "read", "write", "delete", "stat", "presign", "copy"],
|
||||
description: "Operation to perform",
|
||||
},
|
||||
endpoint: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Custom S3 endpoint URL (required for MinIO and most non-AWS providers)",
|
||||
},
|
||||
region: {
|
||||
type: "string",
|
||||
default: "us-east-1",
|
||||
description: "AWS region (still required by many S3-compatible APIs)",
|
||||
},
|
||||
bucket: {
|
||||
type: "string",
|
||||
required: true,
|
||||
description: "Bucket name",
|
||||
},
|
||||
key: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Object key (required for read, write, delete, stat, presign, copy)",
|
||||
},
|
||||
prefix: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "List only keys under this prefix",
|
||||
},
|
||||
delimiter: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "List folder delimiter, usually /",
|
||||
},
|
||||
maxKeys: {
|
||||
type: "number",
|
||||
default: 1000,
|
||||
description: "Maximum objects returned by list",
|
||||
},
|
||||
forcePathStyle: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Use path-style URLs (often required for MinIO)",
|
||||
},
|
||||
accessKeyIdSecret: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Named secret for the access key id",
|
||||
},
|
||||
secretAccessKeySecret: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Named secret for the secret access key",
|
||||
},
|
||||
accessKeyId: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Plain access key id (prefer secrets in production)",
|
||||
},
|
||||
secretAccessKey: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Plain secret access key (prefer secrets in production)",
|
||||
},
|
||||
contentType: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Content-Type for write",
|
||||
},
|
||||
body: {
|
||||
type: "any",
|
||||
required: false,
|
||||
description: "Body for write when not passed via data",
|
||||
},
|
||||
outputVar: {
|
||||
type: "string",
|
||||
default: "file",
|
||||
description: "Output key for read action bytes",
|
||||
},
|
||||
encoding: {
|
||||
type: "string",
|
||||
required: false,
|
||||
enum: ["utf8", "text", "base64"],
|
||||
description: "Optional read decoding helper (adds text or base64 field)",
|
||||
},
|
||||
expiresIn: {
|
||||
type: "number",
|
||||
default: 3600,
|
||||
description: "Presigned URL lifetime in seconds",
|
||||
},
|
||||
presignMethod: {
|
||||
type: "string",
|
||||
default: "get",
|
||||
enum: ["get", "put"],
|
||||
description: "Presign a download (get) or upload (put) URL",
|
||||
},
|
||||
sourceBucket: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Source bucket for copy (defaults to bucket)",
|
||||
},
|
||||
sourceKey: {
|
||||
type: "string",
|
||||
required: false,
|
||||
description: "Source key for copy",
|
||||
},
|
||||
},
|
||||
input: {
|
||||
action: { type: "string", required: false },
|
||||
bucket: { type: "string", required: false },
|
||||
key: { type: "string", required: false },
|
||||
prefix: { type: "string", required: false },
|
||||
body: { type: "any", required: false, description: "Write payload" },
|
||||
file: { type: "buffer", required: false, description: "Binary write payload" },
|
||||
sourceKey: { type: "string", required: false },
|
||||
sourceBucket: { type: "string", required: false },
|
||||
},
|
||||
output: {
|
||||
action: { type: "string" },
|
||||
bucket: { type: "string" },
|
||||
objects: { type: "array", required: false, description: "list results" },
|
||||
file: { type: "buffer", required: false, description: "read bytes (or outputVar)" },
|
||||
url: { type: "string", required: false, description: "presigned URL" },
|
||||
written: { type: "boolean", required: false },
|
||||
deleted: { type: "boolean", required: false },
|
||||
copied: { type: "boolean", required: false },
|
||||
},
|
||||
context: {
|
||||
action: { type: "string" },
|
||||
bucket: { type: "string" },
|
||||
},
|
||||
example: {
|
||||
data: {},
|
||||
config: {
|
||||
action: "list",
|
||||
endpoint: "https://minio.example.com",
|
||||
region: "us-east-1",
|
||||
bucket: "backups",
|
||||
prefix: "daily/",
|
||||
forcePathStyle: true,
|
||||
accessKeyIdSecret: "minio_access_key",
|
||||
secretAccessKeySecret: "minio_secret_key",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default s3;
|
||||
Generated
+318
@@ -14,6 +14,12 @@ importers:
|
||||
|
||||
packages/server:
|
||||
dependencies:
|
||||
'@aws-sdk/client-s3':
|
||||
specifier: ^3.1111.0
|
||||
version: 3.1111.0
|
||||
'@aws-sdk/s3-request-presigner':
|
||||
specifier: ^3.1111.0
|
||||
version: 3.1111.0
|
||||
'@fastify/cookie':
|
||||
specifier: ^11.0.2
|
||||
version: 11.1.2
|
||||
@@ -132,6 +138,82 @@ packages:
|
||||
'@antfu/install-pkg@1.1.0':
|
||||
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
|
||||
|
||||
'@aws-sdk/checksums@3.1000.28':
|
||||
resolution: {integrity: sha512-VCpnmyHQ1IH49ni3LXnQj7DPr7rmcJmzYeiCkYdCcfgNtkvOj38cdcL9lapBWoItZWFACJPFJlymqC7/gem3Gw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/client-s3@3.1111.0':
|
||||
resolution: {integrity: sha512-VnLT6aSTN8tWl/NsXUysXNZor7wQBp9CRwufo7kt8cwGXvHLZ0S/cV1K9WFcREGboVYSo3NGQ3ZvU7LRidh2aQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/core@3.977.8':
|
||||
resolution: {integrity: sha512-7+Kcrkvrk9lM/m7jRhHpT4jCdvzGHsuaSRbF8TdzzkY1mRzp/Ogwf9c7H29k4gGhey0BBWhCWr16+t0J61gwmg==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-env@3.972.69':
|
||||
resolution: {integrity: sha512-AreCFzcB4kH2HF9031Ot0jSJr3KXvRg6e8uDeub20JEVdZU3Bv0sTq1plc7VsT3KiqutlzH7l0j50UcCWHUioA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-http@3.972.71':
|
||||
resolution: {integrity: sha512-A8ObcqVmDMnk4F9NozZ7JwmUu9Q4xyBJkmyq1C5U+wNM9ht9J7+EuuyabsLWXZnOoTqFaJuYBYTKf5CTipkEjA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-ini@3.973.14':
|
||||
resolution: {integrity: sha512-7c+Wti2LsERNWMfm7ySz3/6RPopFW3Nmn7s63Xpcq6R/tRuY5hpvkHA2xVgi5ukJbvok9l0IDtVEvqTtg+X7dw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-login@3.972.76':
|
||||
resolution: {integrity: sha512-LVixwOnEJfrrfKHeZjBA8pIMTZjNDq8ak8VpcoWUuCJDrSnBNU8POJksULMgvN089P0MXtQYH2Zs627/MK1K0g==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-node@3.972.80':
|
||||
resolution: {integrity: sha512-bE2qh8ww4iClO1jHsBXdOE8FUgzDbdxbyorNjSCoPSkQd51k3jODItuPZfuwcLHZqDXsH+bI4AMHhqtuyR7mSg==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-process@3.972.69':
|
||||
resolution: {integrity: sha512-9kpTNdZTrcqXTfhxM7fgl9Z68ek3Fu5oe3Yf+A/pJGibEqpgZxz2tSY7SinmyCIU2PJ+ygY4FPoBBnLpocMtrQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-sso@3.973.13':
|
||||
resolution: {integrity: sha512-Oc81qauMPzUoTnAS2YKpNwY6sY/LUyQTEeaf6yP197WMxkEBQfcKLR1MFpD7+pNTubXnfkH6gwpji+Gc7iyD2Q==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/credential-provider-web-identity@3.972.75':
|
||||
resolution: {integrity: sha512-YPN6uoGDgjjjeVFZrcOeCJqmB6zpXoeeNgIjqe+DexJaWqdjVfCCe+VAZwli9Z2h8KhFW8oxkO39emQ1tyz/Mw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/middleware-sdk-s3@3.972.74':
|
||||
resolution: {integrity: sha512-2lzoV2z2QO5KJZYGOCnIZ1WVQgzMECvwuzr1xb034a++8QW4U4eGrmC2u4yg1xvNv4TLL/Uv5DLyuAiw0b9z7Q==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/nested-clients@3.997.43':
|
||||
resolution: {integrity: sha512-bit+VpqWNyi3wHxFoTsTliNXimCSL2r2OeDTm7ZrG+YsTZ2D7ofDJ6r/t9PVBn80i6/v0X2h9Tgw6QP2MAKfPw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/s3-request-presigner@3.1111.0':
|
||||
resolution: {integrity: sha512-ACp/VtDTw6AjFW5Q3M59uAMrBbAHeQS0UBIOIgUROO98Z3uhpiy37k9RmvxbXYVugmTcdNTy4DPVQtLG8sDy6g==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/signature-v4-multi-region@3.996.45':
|
||||
resolution: {integrity: sha512-bBuyztukzXq6plzFGHAWiQt0QXo+HL8b8lX5cFTzkez/74PtS1c0qPFCIVuHkyoT+miH2qOjAcm1/yoro2ESPA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/token-providers@3.1111.0':
|
||||
resolution: {integrity: sha512-JfljgoVtl+s3Qy21n9a7Z48uCQaOXcN74KJ3TEQfPoB293GrXFSt6HSQJF1sTZ8c/5QedEvd3NjJQMO4u9qa5A==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/types@3.974.4':
|
||||
resolution: {integrity: sha512-dSFDNG00MEz0/xl5gxL62giLd1iYyJsTxZ1I1DOj6lC+bbgLB4TRsYClJg3b62dhXT1uATzsTNXPnC+33EJV3A==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/xml-builder@3.972.39':
|
||||
resolution: {integrity: sha512-FTti8DS5MMWXNUWiRwXAJeYS+0GHHiMy0+7XOhcwk63ILHmfS2UFy2z/HNpZCSOJJ3P3dnWY6hfYNW3DF0nXUA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws/lambda-invoke-store@0.3.0':
|
||||
resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@babel/code-frame@7.29.7':
|
||||
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -618,6 +700,30 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@smithy/core@3.33.2':
|
||||
resolution: {integrity: sha512-CUGXpnPkVdjUCbix+83sWLW9VFgQOm44MDOx/ihITJMAnOZKvL8YYIc7DR9pP/tZ8CIRvMiON/TucvygqbHO3w==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/credential-provider-imds@4.5.2':
|
||||
resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/fetch-http-handler@5.7.2':
|
||||
resolution: {integrity: sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/node-http-handler@4.11.2':
|
||||
resolution: {integrity: sha512-avwAh9HM3h2lcfjvP3zYIZGf+XVgLQ91wOJ2qoFbNpW1UZeZb33aGlhTZvtkANHfcGhJroRY64525OjfgOg30g==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/signature-v4@5.7.2':
|
||||
resolution: {integrity: sha512-P7Ki6px6OOrxVtx8K7nLmyx4SlXUW/uTKDdMG44UHefmPGSRMBKe2v+TM59WdLcpUIrBrnuCsIqiM2MbsZjmhw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/types@4.17.2':
|
||||
resolution: {integrity: sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@tailwindcss/node@4.3.3':
|
||||
resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
|
||||
|
||||
@@ -903,6 +1009,9 @@ packages:
|
||||
boolbase@1.0.0:
|
||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||
|
||||
bowser@2.14.1:
|
||||
resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
|
||||
|
||||
brace-expansion@5.0.9:
|
||||
resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
|
||||
engines: {node: 20 || >=22}
|
||||
@@ -2038,6 +2147,180 @@ snapshots:
|
||||
package-manager-detector: 1.8.0
|
||||
tinyexec: 1.3.0
|
||||
|
||||
'@aws-sdk/checksums@3.1000.28':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/client-s3@3.1111.0':
|
||||
dependencies:
|
||||
'@aws-sdk/checksums': 3.1000.28
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/credential-provider-node': 3.972.80
|
||||
'@aws-sdk/middleware-sdk-s3': 3.972.74
|
||||
'@aws-sdk/signature-v4-multi-region': 3.996.45
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/fetch-http-handler': 5.7.2
|
||||
'@smithy/node-http-handler': 4.11.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/core@3.977.8':
|
||||
dependencies:
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@aws-sdk/xml-builder': 3.972.39
|
||||
'@aws/lambda-invoke-store': 0.3.0
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/signature-v4': 5.7.2
|
||||
'@smithy/types': 4.17.2
|
||||
bowser: 2.14.1
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-env@3.972.69':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-http@3.972.71':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/fetch-http-handler': 5.7.2
|
||||
'@smithy/node-http-handler': 4.11.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-ini@3.973.14':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/credential-provider-env': 3.972.69
|
||||
'@aws-sdk/credential-provider-http': 3.972.71
|
||||
'@aws-sdk/credential-provider-login': 3.972.76
|
||||
'@aws-sdk/credential-provider-process': 3.972.69
|
||||
'@aws-sdk/credential-provider-sso': 3.973.13
|
||||
'@aws-sdk/credential-provider-web-identity': 3.972.75
|
||||
'@aws-sdk/nested-clients': 3.997.43
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/credential-provider-imds': 4.5.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-login@3.972.76':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/nested-clients': 3.997.43
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-node@3.972.80':
|
||||
dependencies:
|
||||
'@aws-sdk/credential-provider-env': 3.972.69
|
||||
'@aws-sdk/credential-provider-http': 3.972.71
|
||||
'@aws-sdk/credential-provider-ini': 3.973.14
|
||||
'@aws-sdk/credential-provider-process': 3.972.69
|
||||
'@aws-sdk/credential-provider-sso': 3.973.13
|
||||
'@aws-sdk/credential-provider-web-identity': 3.972.75
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/credential-provider-imds': 4.5.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-process@3.972.69':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-sso@3.973.13':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/nested-clients': 3.997.43
|
||||
'@aws-sdk/token-providers': 3.1111.0
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/credential-provider-web-identity@3.972.75':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/nested-clients': 3.997.43
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/middleware-sdk-s3@3.972.74':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/signature-v4-multi-region': 3.996.45
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/nested-clients@3.997.43':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/signature-v4-multi-region': 3.996.45
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/fetch-http-handler': 5.7.2
|
||||
'@smithy/node-http-handler': 4.11.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/s3-request-presigner@3.1111.0':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/signature-v4-multi-region': 3.996.45
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/signature-v4-multi-region@3.996.45':
|
||||
dependencies:
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/signature-v4': 5.7.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/token-providers@3.1111.0':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.8
|
||||
'@aws-sdk/nested-clients': 3.997.43
|
||||
'@aws-sdk/types': 3.974.4
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/types@3.974.4':
|
||||
dependencies:
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/xml-builder@3.972.39':
|
||||
dependencies:
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws/lambda-invoke-store@0.3.0': {}
|
||||
|
||||
'@babel/code-frame@7.29.7':
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.29.7
|
||||
@@ -2447,6 +2730,39 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.62.4':
|
||||
optional: true
|
||||
|
||||
'@smithy/core@3.33.2':
|
||||
dependencies:
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/credential-provider-imds@4.5.2':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/fetch-http-handler@5.7.2':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/node-http-handler@4.11.2':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/signature-v4@5.7.2':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.2
|
||||
'@smithy/types': 4.17.2
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/types@4.17.2':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@tailwindcss/node@4.3.3':
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
@@ -2749,6 +3065,8 @@ snapshots:
|
||||
|
||||
boolbase@1.0.0: {}
|
||||
|
||||
bowser@2.14.1: {}
|
||||
|
||||
brace-expansion@5.0.9:
|
||||
dependencies:
|
||||
balanced-match: 4.0.4
|
||||
|
||||
Reference in New Issue
Block a user