feat: private certificates/documents buckets with SeaweedFS support

Add Document CRUD, temp→bucket commit flow, SeaweedFS env aliases, and default temp bucket name to temp.
This commit is contained in:
2026-08-15 02:53:59 +03:30
parent 5c2fad4b44
commit 4603b45208
18 changed files with 585 additions and 112 deletions
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env node
/**
* Ensure Gameno S3 buckets exist on MinIO / SeaweedFS.
*
* Usage:
* node scripts/ensure-s3-buckets.js
*
* Uses the same env resolution as config.js (S3_* or SeaweedFS SERVICE_/AWS_ aliases).
*/
'use strict';
const { S3Client, CreateBucketCommand, HeadBucketCommand } = require('@aws-sdk/client-s3');
const config = require('../config/config');
const buckets = [
config.S3_TEMP_BUCKET,
config.S3_CERTIFICATES_BUCKET,
config.S3_DOCUMENTS_BUCKET
].filter(Boolean);
const uniqueBuckets = [...new Set(buckets)];
const client = new S3Client({
endpoint: config.S3_ENDPOINT,
region: config.S3_REGION,
credentials: {
accessKeyId: config.S3_ACCESS_KEY,
secretAccessKey: config.S3_SECRET_KEY
},
forcePathStyle: config.S3_FORCE_PATH_STYLE
});
const ensureBucket = async (name) => {
try {
await client.send(new HeadBucketCommand({ Bucket: name }));
console.log(`✓ exists: ${name}`);
return;
} catch {
// missing or not head-able — try create
}
try {
await client.send(new CreateBucketCommand({ Bucket: name }));
console.log(`✓ created: ${name}`);
} catch (err) {
const code = err?.name || err?.Code || '';
if (code === 'BucketAlreadyOwnedByYou' || code === 'BucketAlreadyExists') {
console.log(`✓ exists: ${name}`);
return;
}
throw err;
}
};
(async () => {
console.log(`S3 endpoint: ${config.S3_ENDPOINT}`);
console.log(`Ensuring buckets: ${uniqueBuckets.join(', ')}`);
for (const name of uniqueBuckets) {
await ensureBucket(name);
}
console.log('Done.');
})().catch((err) => {
console.error('Failed to ensure buckets:', err.message || err);
process.exit(1);
});