MAI CALL - step 3

This commit is contained in:
Pedro Gomes 2026-05-16 15:32:56 +01:00
parent e249a6f0b2
commit 8e57ccc7f0
12 changed files with 910 additions and 2 deletions

View File

@ -19,7 +19,10 @@
"PowerShell($env:npm_config_verify_deps_before_run = \"false\"; corepack pnpm exec prisma migrate status --schema packages/db/prisma/schema.prisma 2>&1 | Select-Object -Last 25)", "PowerShell($env:npm_config_verify_deps_before_run = \"false\"; corepack pnpm exec prisma migrate status --schema packages/db/prisma/schema.prisma 2>&1 | Select-Object -Last 25)",
"Bash(pnpm --filter @repo/db exec prisma migrate dev --name add_maintenance_request)", "Bash(pnpm --filter @repo/db exec prisma migrate dev --name add_maintenance_request)",
"Bash(pnpm --filter @repo/db exec prisma db execute --schema=prisma/schema.prisma --stdin)", "Bash(pnpm --filter @repo/db exec prisma db execute --schema=prisma/schema.prisma --stdin)",
"Bash(docker exec *)" "Bash(docker exec *)",
"Bash(pnpm install *)",
"Bash(docker compose *)",
"Bash(pnpm tsx *)"
] ]
} }
} }

View File

@ -31,3 +31,14 @@ LOG_LEVEL="info"
# Node environment — Next.js sets this automatically; included here for # Node environment — Next.js sets this automatically; included here for
# packages that need it at module load time. # packages that need it at module load time.
NODE_ENV="development" NODE_ENV="development"
# MinIO / S3-compatible object storage. Matches docker-compose.yml defaults.
# S3_FORCE_PATH_STYLE=true is required for MinIO (and other self-hosted S3 impls).
S3_ENDPOINT="http://localhost:9000"
S3_REGION="us-east-1"
S3_BUCKET="fieldops"
S3_ACCESS_KEY="fieldops"
S3_SECRET_KEY="fieldops123"
S3_FORCE_PATH_STYLE="true"
MINIO_ROOT_USER="fieldops"
MINIO_ROOT_PASSWORD="fieldops123"

View File

@ -19,5 +19,41 @@ services:
timeout: 5s timeout: 5s
retries: 10 retries: 10
minio:
image: minio/minio:latest
container_name: fieldops-minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-fieldops}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-fieldops123}
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio-data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 5s
timeout: 5s
retries: 10
minio-init:
image: minio/mc:latest
depends_on:
minio:
condition: service_started
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-fieldops}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-fieldops123}
entrypoint: >
/bin/sh -c "
sleep 3 &&
mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD &&
mc mb -p local/fieldops || true &&
mc anonymous set none local/fieldops
"
volumes: volumes:
postgres-data: postgres-data:
minio-data:

View File

@ -27,9 +27,11 @@
}, },
"devDependencies": { "devDependencies": {
"@repo/config": "workspace:*", "@repo/config": "workspace:*",
"dotenv": "^16.4.7",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9", "prettier-plugin-tailwindcss": "^0.6.9",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"tsx": "^4.19.2",
"turbo": "^2.3.3", "turbo": "^2.3.3",
"typescript": "^5.7.2" "typescript": "^5.7.2"
} }

View File

@ -0,0 +1,24 @@
{
"name": "@repo/storage",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"scripts": {
"typecheck": "tsc --noEmit",
"clean": "rimraf .turbo node_modules"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.787.0",
"@aws-sdk/s3-request-presigner": "^3.787.0"
},
"devDependencies": {
"@repo/config": "workspace:*",
"rimraf": "^6.0.1",
"typescript": "^5.7.2"
}
}

View File

@ -0,0 +1,21 @@
export type { ObjectStorage } from './interface.js';
export { MinioStorage } from './minio.js';
import { MinioStorage } from './minio.js';
export function makeStorage(): MinioStorage {
const endpoint = process.env['S3_ENDPOINT'];
const region = process.env['S3_REGION'] ?? 'us-east-1';
const bucket = process.env['S3_BUCKET'];
const accessKey = process.env['S3_ACCESS_KEY'];
const secretKey = process.env['S3_SECRET_KEY'];
const forcePathStyle = process.env['S3_FORCE_PATH_STYLE'] === 'true';
if (!endpoint || !bucket || !accessKey || !secretKey) {
throw new Error(
'Missing required env vars: S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY',
);
}
return new MinioStorage({ endpoint, region, bucket, accessKey, secretKey, forcePathStyle });
}

View File

@ -0,0 +1,5 @@
export interface ObjectStorage {
signPut(key: string, contentType: string, byteSize: number, ttlSec: number): Promise<{ url: string; expiresAt: Date }>;
signGet(key: string, ttlSec: number): Promise<{ url: string; expiresAt: Date }>;
delete(key: string): Promise<void>;
}

View File

@ -0,0 +1,60 @@
import {
S3Client,
PutObjectCommand,
GetObjectCommand,
DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import type { ObjectStorage } from './interface.js';
interface MinioStorageOptions {
endpoint: string;
region: string;
bucket: string;
accessKey: string;
secretKey: string;
forcePathStyle: boolean;
}
export class MinioStorage implements ObjectStorage {
private readonly client: S3Client;
private readonly bucket: string;
constructor(opts: MinioStorageOptions) {
this.bucket = opts.bucket;
this.client = new S3Client({
endpoint: opts.endpoint,
region: opts.region,
credentials: {
accessKeyId: opts.accessKey,
secretAccessKey: opts.secretKey,
},
forcePathStyle: opts.forcePathStyle,
});
}
async signPut(
key: string,
contentType: string,
_byteSize: number,
ttlSec: number,
): Promise<{ url: string; expiresAt: Date }> {
const cmd = new PutObjectCommand({
Bucket: this.bucket,
Key: key,
ContentType: contentType,
});
const url = await getSignedUrl(this.client, cmd, { expiresIn: ttlSec });
return { url, expiresAt: new Date(Date.now() + ttlSec * 1000) };
}
async signGet(key: string, ttlSec: number): Promise<{ url: string; expiresAt: Date }> {
const cmd = new GetObjectCommand({ Bucket: this.bucket, Key: key });
const url = await getSignedUrl(this.client, cmd, { expiresIn: ttlSec });
return { url, expiresAt: new Date(Date.now() + ttlSec * 1000) };
}
async delete(key: string): Promise<void> {
await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
}
}

View File

@ -0,0 +1,6 @@
{
"extends": "@repo/config/tsconfig/library.json",
"compilerOptions": {
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
}
}

677
pnpm-lock.yaml generated
View File

@ -11,6 +11,9 @@ importers:
'@repo/config': '@repo/config':
specifier: workspace:* specifier: workspace:*
version: link:packages/config version: link:packages/config
dotenv:
specifier: ^16.4.7
version: 16.6.1
prettier: prettier:
specifier: ^3.4.2 specifier: ^3.4.2
version: 3.8.3 version: 3.8.3
@ -20,6 +23,9 @@ importers:
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.1.3 version: 6.1.3
tsx:
specifier: ^4.19.2
version: 4.22.0
turbo: turbo:
specifier: ^2.3.3 specifier: ^2.3.3
version: 2.9.14 version: 2.9.14
@ -259,6 +265,25 @@ importers:
specifier: ^5.7.2 specifier: ^5.7.2
version: 5.9.3 version: 5.9.3
packages/storage:
dependencies:
'@aws-sdk/client-s3':
specifier: ^3.787.0
version: 3.1047.0
'@aws-sdk/s3-request-presigner':
specifier: ^3.787.0
version: 3.1047.0
devDependencies:
'@repo/config':
specifier: workspace:*
version: link:../config
rimraf:
specifier: ^6.0.1
version: 6.1.3
typescript:
specifier: ^5.7.2
version: 5.9.3
packages/ui: packages/ui:
dependencies: dependencies:
class-variance-authority: class-variance-authority:
@ -316,6 +341,165 @@ packages:
nodemailer: nodemailer:
optional: true optional: true
'@aws-crypto/crc32@5.2.0':
resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==}
engines: {node: '>=16.0.0'}
'@aws-crypto/crc32c@5.2.0':
resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==}
'@aws-crypto/sha1-browser@5.2.0':
resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==}
'@aws-crypto/sha256-browser@5.2.0':
resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
'@aws-crypto/sha256-js@5.2.0':
resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==}
engines: {node: '>=16.0.0'}
'@aws-crypto/supports-web-crypto@5.2.0':
resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==}
'@aws-crypto/util@5.2.0':
resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
'@aws-sdk/client-s3@3.1047.0':
resolution: {integrity: sha512-gk8g31eqvgf7eLCpkVjWs9KL7gYgkomt3FT2o9tbIe6goYrBheN2lHxhCsTn1zFYbt7EwrZXTGkQPIQNIN0c5w==}
engines: {node: '>=20.0.0'}
'@aws-sdk/core@3.974.10':
resolution: {integrity: sha512-ZGFFlYynBR78Y/F8b/7y4i4sgW/iGwJSjoM7AZo5Et6vyr4/L0bunN+uzKMsvecCZyqcPp4RRK7Rs17l0kMujg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/crc64-nvme@3.972.8':
resolution: {integrity: sha512-fVfUCL/Xh2zINYMPZvj+iBn6XWouQf0DAnjaWCI9MkmqXzL2Iy5FoQB8O7syFe6gN6AH1ecDDU58T51Ou0kFkA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-env@3.972.36':
resolution: {integrity: sha512-gE+CGuPZD1eqUWGSrM8CXDjlwuPujIuwI+IlorD1wE2RcANKKT4jscB9GY1nTJbjmXzD18sycsYbgCG5m3n4/g==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-http@3.972.38':
resolution: {integrity: sha512-cHZo3bV6zN9joDQ2AYVctfzHTKStxWKwnGu0z7GwCUC+DAtB3qL/+26l+a63RbmFbVvb1JK+0vJKodN3hRMwyw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-ini@3.972.40':
resolution: {integrity: sha512-0NFGS9I3PD2yMveQqqpwpRdyZVStzgk0Yr2rZHh80kV/QNqQCK5lSrksvU3nBcRNSUF5Uk8rL3Xk0EVR+UVAnA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-login@3.972.40':
resolution: {integrity: sha512-IEIl+UQnrEjZP53TSl91e8LBephi4i1Mt9WZrMgN8pOg6xPOLZdkN1GhsEzjkMD1TQy4Fp2dwWA/9ToTQFOlLA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-node@3.972.41':
resolution: {integrity: sha512-h6BlclpsPGkx7Pv7ukr8oKVqN3jvxnH5n9ZIUQa8focr1ZkKd2MYiPJ2Nv9GI97dohJVJBfZAsTp/qoZL5R1pw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-process@3.972.36':
resolution: {integrity: sha512-eDQ6X7clTAOxXegOx4rGT1hyfusGEYdJGCGo0Ym2+CKeMQBjk+SJSxSVev11NJew5xJHJ/c3hryl2awKaxuSEA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-sso@3.972.40':
resolution: {integrity: sha512-jaABbsoOkGlKg5kaHetYmUV6mWM57H89ia0Yksom1XxC847mfjmEVb4p7VijS1sjPbXjUii4cftJuwsl4MXkRg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-web-identity@3.972.40':
resolution: {integrity: sha512-bfIrM8IIzbRtXRQWx/vNEUBLTImLZyX5uKk8uSdeSAZ4Mj3Yi4UnRJLK4FkQLWErbM3McpVLQ1DaM6XO66Ed5g==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-bucket-endpoint@3.972.12':
resolution: {integrity: sha512-MAG0Adg7FFEwuoeLbb5SBnXDW7S2EpNTwHnQ4h3pJqSKVQOhOmugyA1MfMh6AD4SAfx0lko4htZdwkNoLqFj5A==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-expect-continue@3.972.11':
resolution: {integrity: sha512-xpobcctR1AHSrvkiArgTyLffn78Lt9unPMpa/yic9RKn+bOf/5M55UIM6RaPL5xKzI06/GSsTDywTWvzEAbyyw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-flexible-checksums@3.974.18':
resolution: {integrity: sha512-2noO+4ARfC+8vOIyvJvQE6bioVaTRkUcPvUoM/jgwXcweZnZovSZ6OCs/cs+NU2p7yvuwuJT/7LkTzBSj5pU4A==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-host-header@3.972.11':
resolution: {integrity: sha512-CBC6+tVYaOJo7QXgN1zJ4Ba2f3/Cpy4eRViYFimXW/O5Mn8hBmgXXzHu4vy4ubT80YWnp8aCFygr7dTOa14yQg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-location-constraint@3.972.10':
resolution: {integrity: sha512-rI3NZvJcEvjoD0+0PI0iUAwlPw2IlSlhyvgBK/3WkKJQE/YiKFedd9dMN2lVacdNxPNhxL/jzQaKQdrGtQagjQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-logger@3.972.10':
resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-recursion-detection@3.972.12':
resolution: {integrity: sha512-5eltYxKB4MfdQv7/VhWxRbAVQKow5dz9votRFigTYrWJHMQXwLMltlbk7KFWSZh5NDBySfmjT7Jv/DWfYCmDng==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-sdk-s3@3.972.39':
resolution: {integrity: sha512-cimoQxecHHNad+lv2g7QJ24Cxqh1P0EULJSxyX4YD95BUIGeGRPumbdEXpHPxNkJRU99DVmh7u16Y+uhFu31Yw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-ssec@3.972.10':
resolution: {integrity: sha512-Gli9A0u8EVVb+5bFDGS/QbSVg28w/wpEidg1ggVcSj65BDTdGR6punsOcVjqdiu1i42WHWo51MCvARPIIz9juw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/middleware-user-agent@3.972.40':
resolution: {integrity: sha512-QLpD+HNQtL1Mc49/GRa6RmZvi/TEYBWPevC9F3L+j96IoG3xOSRctdQfbkX0lETb3TX9QQXU1oGYDmAB+YJprA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/nested-clients@3.997.8':
resolution: {integrity: sha512-/Vw2M27w+0APfMDzDpvv8auA4WiJ4D22+lC61pMS2M8Wk+4IydeRqh5utbrh+A5gQRxgUYd/xz3tdv8nQlmiHg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/region-config-resolver@3.972.14':
resolution: {integrity: sha512-VuLXVmm7+lKVxqFcOItPkXhjbJ02iUfxkxheRu41SfWf6/xrZup2A2SwHZos/LeQGu3SBHeqTQht80Uo3ienPA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/s3-request-presigner@3.1047.0':
resolution: {integrity: sha512-taPZDq1Xh/o59KELbxalBQHuG4ct518d71kNDfw1SKpM+dGqc3tMUhsE7ma9+wPr8TdGspatP+wAP1A/uI42sA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/signature-v4-multi-region@3.996.26':
resolution: {integrity: sha512-2N62veqdMZBCwQUHsbhtnaovOFjOa5Dn3dAD1nRqFTUXR4QmirT3HZnfus/L1DS08Vm5CkoKmL0iMVt6YbqEag==}
engines: {node: '>=20.0.0'}
'@aws-sdk/token-providers@3.1047.0':
resolution: {integrity: sha512-GwJUeMijpeO2SOGGLRg4q2Nj9foBUBd7hTALYVId+m8fQmA4P2hITp5dmrZFd4AjEkSVmt2eFqmk3TttF7HZeQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/types@3.973.8':
resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==}
engines: {node: '>=20.0.0'}
'@aws-sdk/util-endpoints@3.996.9':
resolution: {integrity: sha512-ibx8Vd73rCTHekNGeXX8cpGWoBKbNAlwKHL3yjSxxttu5QnNDaSAM7/0MFYDjU31/F4lyrPoQcGirT0ew61xcg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/util-locate-window@3.965.5':
resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/util-user-agent-browser@3.972.11':
resolution: {integrity: sha512-kq3RS6XQtHMrLFShbkem6h+8fxazB3jEIsbMC6aaSInOciRGE+eGAqTgJ+obO7Euo/pjM8thVqLiLISEH9X9DA==}
'@aws-sdk/util-user-agent-node@3.973.26':
resolution: {integrity: sha512-9bHR/EERjhrUGyo1qW620ogbGBtCglYB/pEtcm85sVd4/Ah+bwdLI3g1aJf75oNwNwh7+fw+8wOk/OCWHjzVmA==}
engines: {node: '>=20.0.0'}
peerDependencies:
aws-crt: '>=1.0.0'
peerDependenciesMeta:
aws-crt:
optional: true
'@aws-sdk/xml-builder@3.972.24':
resolution: {integrity: sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw==}
engines: {node: '>=20.0.0'}
'@aws/lambda-invoke-store@0.2.4':
resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==}
engines: {node: '>=18.0.0'}
'@emnapi/runtime@1.10.0': '@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
@ -757,6 +941,9 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@nodable/entities@2.1.0':
resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==}
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -810,6 +997,42 @@ packages:
'@prisma/get-platform@6.19.3': '@prisma/get-platform@6.19.3':
resolution: {integrity: sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==} resolution: {integrity: sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==}
'@smithy/core@3.24.3':
resolution: {integrity: sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==}
engines: {node: '>=18.0.0'}
'@smithy/credential-provider-imds@4.3.3':
resolution: {integrity: sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w==}
engines: {node: '>=18.0.0'}
'@smithy/fetch-http-handler@5.4.3':
resolution: {integrity: sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A==}
engines: {node: '>=18.0.0'}
'@smithy/is-array-buffer@2.2.0':
resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==}
engines: {node: '>=14.0.0'}
'@smithy/node-http-handler@4.7.3':
resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==}
engines: {node: '>=18.0.0'}
'@smithy/signature-v4@5.4.3':
resolution: {integrity: sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g==}
engines: {node: '>=18.0.0'}
'@smithy/types@4.14.2':
resolution: {integrity: sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==}
engines: {node: '>=18.0.0'}
'@smithy/util-buffer-from@2.2.0':
resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
engines: {node: '>=14.0.0'}
'@smithy/util-utf8@2.3.0':
resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
engines: {node: '>=14.0.0'}
'@standard-schema/spec@1.1.0': '@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@ -1037,6 +1260,9 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'} engines: {node: '>=8'}
bowser@2.14.1:
resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
brace-expansion@1.1.14: brace-expansion@1.1.14:
resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==}
@ -1314,6 +1540,13 @@ packages:
fast-safe-stringify@2.1.1: fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fast-xml-builder@1.2.0:
resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==}
fast-xml-parser@5.7.3:
resolution: {integrity: sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==}
hasBin: true
fastq@1.20.1: fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
@ -1632,6 +1865,10 @@ packages:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'} engines: {node: '>=8'}
path-expression-matcher@1.5.0:
resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==}
engines: {node: '>=14.0.0'}
path-key@3.1.1: path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1960,6 +2197,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
strnum@2.3.0:
resolution: {integrity: sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==}
styled-jsx@5.1.6: styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@ -2089,6 +2329,10 @@ packages:
wrappy@1.0.2: wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
xml-naming@0.1.0:
resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==}
engines: {node: '>=16.0.0'}
yocto-queue@0.1.0: yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -2110,6 +2354,369 @@ snapshots:
preact: 10.11.3 preact: 10.11.3
preact-render-to-string: 5.2.3(preact@10.11.3) preact-render-to-string: 5.2.3(preact@10.11.3)
'@aws-crypto/crc32@5.2.0':
dependencies:
'@aws-crypto/util': 5.2.0
'@aws-sdk/types': 3.973.8
tslib: 2.8.1
'@aws-crypto/crc32c@5.2.0':
dependencies:
'@aws-crypto/util': 5.2.0
'@aws-sdk/types': 3.973.8
tslib: 2.8.1
'@aws-crypto/sha1-browser@5.2.0':
dependencies:
'@aws-crypto/supports-web-crypto': 5.2.0
'@aws-crypto/util': 5.2.0
'@aws-sdk/types': 3.973.8
'@aws-sdk/util-locate-window': 3.965.5
'@smithy/util-utf8': 2.3.0
tslib: 2.8.1
'@aws-crypto/sha256-browser@5.2.0':
dependencies:
'@aws-crypto/sha256-js': 5.2.0
'@aws-crypto/supports-web-crypto': 5.2.0
'@aws-crypto/util': 5.2.0
'@aws-sdk/types': 3.973.8
'@aws-sdk/util-locate-window': 3.965.5
'@smithy/util-utf8': 2.3.0
tslib: 2.8.1
'@aws-crypto/sha256-js@5.2.0':
dependencies:
'@aws-crypto/util': 5.2.0
'@aws-sdk/types': 3.973.8
tslib: 2.8.1
'@aws-crypto/supports-web-crypto@5.2.0':
dependencies:
tslib: 2.8.1
'@aws-crypto/util@5.2.0':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/util-utf8': 2.3.0
tslib: 2.8.1
'@aws-sdk/client-s3@3.1047.0':
dependencies:
'@aws-crypto/sha1-browser': 5.2.0
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.974.10
'@aws-sdk/credential-provider-node': 3.972.41
'@aws-sdk/middleware-bucket-endpoint': 3.972.12
'@aws-sdk/middleware-expect-continue': 3.972.11
'@aws-sdk/middleware-flexible-checksums': 3.974.18
'@aws-sdk/middleware-host-header': 3.972.11
'@aws-sdk/middleware-location-constraint': 3.972.10
'@aws-sdk/middleware-logger': 3.972.10
'@aws-sdk/middleware-recursion-detection': 3.972.12
'@aws-sdk/middleware-sdk-s3': 3.972.39
'@aws-sdk/middleware-ssec': 3.972.10
'@aws-sdk/middleware-user-agent': 3.972.40
'@aws-sdk/region-config-resolver': 3.972.14
'@aws-sdk/signature-v4-multi-region': 3.996.26
'@aws-sdk/types': 3.973.8
'@aws-sdk/util-endpoints': 3.996.9
'@aws-sdk/util-user-agent-browser': 3.972.11
'@aws-sdk/util-user-agent-node': 3.973.26
'@smithy/core': 3.24.3
'@smithy/fetch-http-handler': 5.4.3
'@smithy/node-http-handler': 4.7.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/core@3.974.10':
dependencies:
'@aws-sdk/types': 3.973.8
'@aws-sdk/xml-builder': 3.972.24
'@smithy/core': 3.24.3
'@smithy/signature-v4': 5.4.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/crc64-nvme@3.972.8':
dependencies:
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/credential-provider-env@3.972.36':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/credential-provider-http@3.972.38':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/fetch-http-handler': 5.4.3
'@smithy/node-http-handler': 4.7.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/credential-provider-ini@3.972.40':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/credential-provider-env': 3.972.36
'@aws-sdk/credential-provider-http': 3.972.38
'@aws-sdk/credential-provider-login': 3.972.40
'@aws-sdk/credential-provider-process': 3.972.36
'@aws-sdk/credential-provider-sso': 3.972.40
'@aws-sdk/credential-provider-web-identity': 3.972.40
'@aws-sdk/nested-clients': 3.997.8
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/credential-provider-imds': 4.3.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-login@3.972.40':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/nested-clients': 3.997.8
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-node@3.972.41':
dependencies:
'@aws-sdk/credential-provider-env': 3.972.36
'@aws-sdk/credential-provider-http': 3.972.38
'@aws-sdk/credential-provider-ini': 3.972.40
'@aws-sdk/credential-provider-process': 3.972.36
'@aws-sdk/credential-provider-sso': 3.972.40
'@aws-sdk/credential-provider-web-identity': 3.972.40
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/credential-provider-imds': 4.3.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-process@3.972.36':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/credential-provider-sso@3.972.40':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/nested-clients': 3.997.8
'@aws-sdk/token-providers': 3.1047.0
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-web-identity@3.972.40':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/nested-clients': 3.997.8
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/middleware-bucket-endpoint@3.972.12':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-expect-continue@3.972.11':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-flexible-checksums@3.974.18':
dependencies:
'@aws-crypto/crc32': 5.2.0
'@aws-crypto/crc32c': 5.2.0
'@aws-crypto/util': 5.2.0
'@aws-sdk/core': 3.974.10
'@aws-sdk/crc64-nvme': 3.972.8
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-host-header@3.972.11':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-location-constraint@3.972.10':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-logger@3.972.10':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-recursion-detection@3.972.12':
dependencies:
'@aws-sdk/types': 3.973.8
'@aws/lambda-invoke-store': 0.2.4
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-sdk-s3@3.972.39':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/signature-v4-multi-region': 3.996.26
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/signature-v4': 5.4.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-ssec@3.972.10':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/middleware-user-agent@3.972.40':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/types': 3.973.8
'@aws-sdk/util-endpoints': 3.996.9
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/nested-clients@3.997.8':
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.974.10
'@aws-sdk/middleware-host-header': 3.972.11
'@aws-sdk/middleware-logger': 3.972.10
'@aws-sdk/middleware-recursion-detection': 3.972.12
'@aws-sdk/middleware-user-agent': 3.972.40
'@aws-sdk/region-config-resolver': 3.972.14
'@aws-sdk/signature-v4-multi-region': 3.996.26
'@aws-sdk/types': 3.973.8
'@aws-sdk/util-endpoints': 3.996.9
'@aws-sdk/util-user-agent-browser': 3.972.11
'@aws-sdk/util-user-agent-node': 3.973.26
'@smithy/core': 3.24.3
'@smithy/fetch-http-handler': 5.4.3
'@smithy/node-http-handler': 4.7.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/region-config-resolver@3.972.14':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/s3-request-presigner@3.1047.0':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/signature-v4-multi-region': 3.996.26
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/signature-v4-multi-region@3.996.26':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/signature-v4': 5.4.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/token-providers@3.1047.0':
dependencies:
'@aws-sdk/core': 3.974.10
'@aws-sdk/nested-clients': 3.997.8
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/types@3.973.8':
dependencies:
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/util-endpoints@3.996.9':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/util-locate-window@3.965.5':
dependencies:
tslib: 2.8.1
'@aws-sdk/util-user-agent-browser@3.972.11':
dependencies:
'@aws-sdk/types': 3.973.8
'@smithy/types': 4.14.2
bowser: 2.14.1
tslib: 2.8.1
'@aws-sdk/util-user-agent-node@3.973.26':
dependencies:
'@aws-sdk/middleware-user-agent': 3.972.40
'@aws-sdk/types': 3.973.8
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/xml-builder@3.972.24':
dependencies:
'@nodable/entities': 2.1.0
'@smithy/types': 4.14.2
fast-xml-parser: 5.7.3
tslib: 2.8.1
'@aws/lambda-invoke-store@0.2.4': {}
'@emnapi/runtime@1.10.0': '@emnapi/runtime@1.10.0':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@ -2396,6 +3003,8 @@ snapshots:
'@next/swc-win32-x64-msvc@15.5.18': '@next/swc-win32-x64-msvc@15.5.18':
optional: true optional: true
'@nodable/entities@2.1.0': {}
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
dependencies: dependencies:
'@nodelib/fs.stat': 2.0.5 '@nodelib/fs.stat': 2.0.5
@ -2451,6 +3060,54 @@ snapshots:
dependencies: dependencies:
'@prisma/debug': 6.19.3 '@prisma/debug': 6.19.3
'@smithy/core@3.24.3':
dependencies:
'@aws-crypto/crc32': 5.2.0
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/credential-provider-imds@4.3.3':
dependencies:
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/fetch-http-handler@5.4.3':
dependencies:
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/is-array-buffer@2.2.0':
dependencies:
tslib: 2.8.1
'@smithy/node-http-handler@4.7.3':
dependencies:
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/signature-v4@5.4.3':
dependencies:
'@smithy/core': 3.24.3
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/types@4.14.2':
dependencies:
tslib: 2.8.1
'@smithy/util-buffer-from@2.2.0':
dependencies:
'@smithy/is-array-buffer': 2.2.0
tslib: 2.8.1
'@smithy/util-utf8@2.3.0':
dependencies:
'@smithy/util-buffer-from': 2.2.0
tslib: 2.8.1
'@standard-schema/spec@1.1.0': {} '@standard-schema/spec@1.1.0': {}
'@swc/helpers@0.5.15': '@swc/helpers@0.5.15':
@ -2674,6 +3331,8 @@ snapshots:
binary-extensions@2.3.0: {} binary-extensions@2.3.0: {}
bowser@2.14.1: {}
brace-expansion@1.1.14: brace-expansion@1.1.14:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
@ -2978,6 +3637,18 @@ snapshots:
fast-safe-stringify@2.1.1: {} fast-safe-stringify@2.1.1: {}
fast-xml-builder@1.2.0:
dependencies:
path-expression-matcher: 1.5.0
xml-naming: 0.1.0
fast-xml-parser@5.7.3:
dependencies:
'@nodable/entities': 2.1.0
fast-xml-builder: 1.2.0
path-expression-matcher: 1.5.0
strnum: 2.3.0
fastq@1.20.1: fastq@1.20.1:
dependencies: dependencies:
reusify: 1.1.0 reusify: 1.1.0
@ -3239,6 +3910,8 @@ snapshots:
path-exists@4.0.0: {} path-exists@4.0.0: {}
path-expression-matcher@1.5.0: {}
path-key@3.1.1: {} path-key@3.1.1: {}
path-parse@1.0.7: {} path-parse@1.0.7: {}
@ -3514,6 +4187,8 @@ snapshots:
strip-json-comments@3.1.1: {} strip-json-comments@3.1.1: {}
strnum@2.3.0: {}
styled-jsx@5.1.6(react@19.2.6): styled-jsx@5.1.6(react@19.2.6):
dependencies: dependencies:
client-only: 0.0.1 client-only: 0.0.1
@ -3658,6 +4333,8 @@ snapshots:
wrappy@1.0.2: {} wrappy@1.0.2: {}
xml-naming@0.1.0: {}
yocto-queue@0.1.0: {} yocto-queue@0.1.0: {}
zod@3.25.76: {} zod@3.25.76: {}

57
scripts/storage-smoke.ts Normal file
View File

@ -0,0 +1,57 @@
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { config as loadEnv } from 'dotenv';
// Load .env from repo root before importing storage (env vars must be set first).
const here = path.dirname(fileURLToPath(import.meta.url));
loadEnv({ path: path.resolve(here, '../.env') });
import { makeStorage } from '../packages/storage/src/index.js';
async function main() {
const storage = makeStorage();
const testKey = `test/smoke-${Date.now()}.jpg`;
const content = 'fake-jpeg-content-for-smoke-test';
console.log('1. Generating presigned PUT URL...');
const { url: putUrl, expiresAt: putExpiry } = await storage.signPut(
testKey,
'image/jpeg',
content.length,
300,
);
console.log(` PUT URL (expires ${putExpiry.toISOString()}): ${putUrl.slice(0, 80)}...`);
console.log('2. Uploading test content via presigned PUT...');
const putRes = await fetch(putUrl, {
method: 'PUT',
body: content,
headers: { 'Content-Type': 'image/jpeg' },
});
if (!putRes.ok) {
throw new Error(`PUT failed: ${putRes.status} ${await putRes.text()}`);
}
console.log(' Upload OK');
console.log('3. Generating presigned GET URL...');
const { url: getUrl, expiresAt: getExpiry } = await storage.signGet(testKey, 60);
console.log(` GET URL (expires ${getExpiry.toISOString()}): ${getUrl.slice(0, 80)}...`);
console.log('4. Downloading and verifying content...');
const getRes = await fetch(getUrl);
if (!getRes.ok) {
throw new Error(`GET failed: ${getRes.status} ${await getRes.text()}`);
}
const downloaded = await getRes.text();
if (downloaded !== content) {
throw new Error(`Content mismatch!\n expected: "${content}"\n got: "${downloaded}"`);
}
console.log(' Download OK — content matches');
console.log('\nSmoke test PASSED');
}
main().catch((err) => {
console.error('Smoke test FAILED:', err);
process.exit(1);
});

View File

@ -7,7 +7,13 @@
"AUTH_SECRET", "AUTH_SECRET",
"AUTH_DEV_AUTOLOGIN", "AUTH_DEV_AUTOLOGIN",
"NEXT_PUBLIC_APP_URL", "NEXT_PUBLIC_APP_URL",
"LOG_LEVEL" "LOG_LEVEL",
"S3_ENDPOINT",
"S3_REGION",
"S3_BUCKET",
"S3_ACCESS_KEY",
"S3_SECRET_KEY",
"S3_FORCE_PATH_STYLE"
], ],
"tasks": { "tasks": {
"build": { "build": {