Files
strukto-ai--mirage/typescript/scripts/gen-presigned-url.ts
T
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

113 lines
3.6 KiB
TypeScript

/**
* Generate a presigned URL (GET + PUT) for the AWS S3 bucket configured in
* .env.development, and write them back to the same file under
* AWS_PRESIGNED_GET_URL / AWS_PRESIGNED_PUT_URL.
*
* Run: pnpm tsx scripts/gen-presigned-url.ts
*/
import { readFileSync, writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
const ENV_FILE = resolve(process.cwd(), '../.env.development')
// AWS SigV4 maximum for long-lived access keys is 7 days (604800s). For
// role/STS creds, the cap is the session's remaining lifetime.
const MAX_TTL_SEC = 604800
const TTL_SEC = (() => {
const arg = process.argv[2]
const envVal = process.env.PRESIGNED_TTL_SEC
const raw = arg ?? envVal ?? String(MAX_TTL_SEC)
const parsed = Number.parseInt(raw, 10)
if (Number.isNaN(parsed) || parsed <= 0) {
throw new Error(`Invalid TTL: ${raw}`)
}
if (parsed > MAX_TTL_SEC) {
throw new Error(`TTL ${parsed}s exceeds AWS max ${MAX_TTL_SEC}s (7 days)`)
}
return parsed
})()
const TEST_KEY = `presigned-demo/${Date.now()}.txt`
function parseEnv(raw: string): Map<string, string> {
const out = new Map<string, string>()
for (const line of raw.split('\n')) {
const m = line.match(/^([A-Z0-9_]+)=(.*)$/)
if (m !== null) {
out.set(m[1] as string, m[2] as string)
}
}
return out
}
function writeEnvUpdates(raw: string, updates: Record<string, string>): string {
const keys = new Set(Object.keys(updates))
const lines = raw.split('\n')
const seen = new Set<string>()
const next = lines.map((line) => {
const m = line.match(/^([A-Z0-9_]+)=(.*)$/)
if (m === null) return line
const key = m[1] as string
if (!keys.has(key)) return line
seen.add(key)
return `${key}=${updates[key]}`
})
for (const key of keys) {
if (!seen.has(key)) next.push(`${key}=${updates[key]}`)
}
return next.join('\n')
}
async function main(): Promise<void> {
const raw = readFileSync(ENV_FILE, 'utf8')
const env = parseEnv(raw)
const bucket = env.get('AWS_S3_BUCKET') ?? ''
const region = env.get('AWS_DEFAULT_REGION') ?? 'us-east-1'
const accessKeyId = env.get('AWS_ACCESS_KEY_ID') ?? ''
const secretAccessKey = env.get('AWS_SECRET_ACCESS_KEY') ?? ''
if (bucket === '' || accessKeyId === '' || secretAccessKey === '') {
throw new Error(
'Missing AWS_S3_BUCKET / AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY in .env.development',
)
}
const client = new S3Client({
region,
credentials: { accessKeyId, secretAccessKey },
})
const putUrl = await getSignedUrl(
client,
new PutObjectCommand({
Bucket: bucket,
Key: TEST_KEY,
ContentType: 'text/plain',
}),
{ expiresIn: TTL_SEC },
)
const getUrl = await getSignedUrl(
client,
new GetObjectCommand({ Bucket: bucket, Key: TEST_KEY }),
{ expiresIn: TTL_SEC },
)
const expiresAt = new Date(Date.now() + TTL_SEC * 1000).toISOString()
const updated = writeEnvUpdates(raw, {
AWS_PRESIGNED_KEY: TEST_KEY,
AWS_PRESIGNED_GET_URL: getUrl,
AWS_PRESIGNED_PUT_URL: putUrl,
AWS_PRESIGNED_EXPIRES_AT: expiresAt,
})
writeFileSync(ENV_FILE, updated, 'utf8')
client.destroy()
console.log(`bucket: ${bucket}`)
console.log(`region: ${region}`)
console.log(`key: ${TEST_KEY}`)
console.log(`expires: ${expiresAt} (${TTL_SEC}s)`)
console.log(`put: ${putUrl.slice(0, 80)}...`)
console.log(`get: ${getUrl.slice(0, 80)}...`)
console.log(`wrote: ${ENV_FILE}`)
}
main().catch((err) => {
console.error(err)
process.exit(1)
})