Spaces:
Sleeping
Sleeping
Preserve Supabase bucket routing for legacy storage paths
Browse files- .env.example +3 -0
- src/config.ts +8 -0
- src/db/storage.ts +18 -10
.env.example
CHANGED
|
@@ -26,6 +26,9 @@ INPUT_BUCKET=relv-turnitin-inputs
|
|
| 26 |
REPORT_BUCKET=relv-turnitin-reports
|
| 27 |
DIAGNOSTICS_BUCKET=relv-turnitin-diagnostics
|
| 28 |
SESSION_BUCKET=relv-turnitin-sessions
|
|
|
|
|
|
|
|
|
|
| 29 |
R2_ACCOUNT_ID=
|
| 30 |
R2_ACCESS_KEY_ID=
|
| 31 |
R2_SECRET_ACCESS_KEY=
|
|
|
|
| 26 |
REPORT_BUCKET=relv-turnitin-reports
|
| 27 |
DIAGNOSTICS_BUCKET=relv-turnitin-diagnostics
|
| 28 |
SESSION_BUCKET=relv-turnitin-sessions
|
| 29 |
+
SUPABASE_INPUT_BUCKET=turnitin-inputs
|
| 30 |
+
SUPABASE_REPORT_BUCKET=turnitin-reports
|
| 31 |
+
SUPABASE_SESSION_BUCKET=turnitin-sessions
|
| 32 |
R2_ACCOUNT_ID=
|
| 33 |
R2_ACCESS_KEY_ID=
|
| 34 |
R2_SECRET_ACCESS_KEY=
|
src/config.ts
CHANGED
|
@@ -28,6 +28,14 @@ export const config = {
|
|
| 28 |
reportBucket: process.env.REPORT_BUCKET || 'turnitin-reports',
|
| 29 |
diagnosticsBucket: process.env.DIAGNOSTICS_BUCKET || 'turnitin-diagnostics',
|
| 30 |
sessionBucket: process.env.SESSION_BUCKET || 'turnitin-sessions',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
r2AccountId: process.env.R2_ACCOUNT_ID || '',
|
| 32 |
r2AccessKeyId: process.env.R2_ACCESS_KEY_ID || '',
|
| 33 |
r2SecretAccessKey: process.env.R2_SECRET_ACCESS_KEY || '',
|
|
|
|
| 28 |
reportBucket: process.env.REPORT_BUCKET || 'turnitin-reports',
|
| 29 |
diagnosticsBucket: process.env.DIAGNOSTICS_BUCKET || 'turnitin-diagnostics',
|
| 30 |
sessionBucket: process.env.SESSION_BUCKET || 'turnitin-sessions',
|
| 31 |
+
// Plain storage paths were created before R2 and must always resolve
|
| 32 |
+
// against the original Supabase bucket names after the R2 switch.
|
| 33 |
+
supabaseInputBucket:
|
| 34 |
+
process.env.SUPABASE_INPUT_BUCKET || 'turnitin-inputs',
|
| 35 |
+
supabaseReportBucket:
|
| 36 |
+
process.env.SUPABASE_REPORT_BUCKET || 'turnitin-reports',
|
| 37 |
+
supabaseSessionBucket:
|
| 38 |
+
process.env.SUPABASE_SESSION_BUCKET || 'turnitin-sessions',
|
| 39 |
r2AccountId: process.env.R2_ACCOUNT_ID || '',
|
| 40 |
r2AccessKeyId: process.env.R2_ACCESS_KEY_ID || '',
|
| 41 |
r2SecretAccessKey: process.env.R2_SECRET_ACCESS_KEY || '',
|
src/db/storage.ts
CHANGED
|
@@ -45,7 +45,7 @@ export async function uploadInputFile(
|
|
| 45 |
}
|
| 46 |
|
| 47 |
const { error } = await supabase.storage
|
| 48 |
-
.from(config.
|
| 49 |
.upload(storagePath, fileBuffer, {
|
| 50 |
contentType: getMimeType(ext),
|
| 51 |
upsert,
|
|
@@ -94,7 +94,7 @@ export async function uploadInputFileFromPath(
|
|
| 94 |
// legacy objects/deployments; R2 is the configured destination for new jobs.
|
| 95 |
const fileBuffer = await fs.promises.readFile(localPath);
|
| 96 |
const { error } = await supabase.storage
|
| 97 |
-
.from(config.
|
| 98 |
.upload(storagePath, fileBuffer, {
|
| 99 |
contentType: getMimeType(ext),
|
| 100 |
upsert,
|
|
@@ -126,7 +126,7 @@ export async function downloadInputFile(storagePath: string, localPath: string):
|
|
| 126 |
}
|
| 127 |
|
| 128 |
const { data, error } = await supabase.storage
|
| 129 |
-
.from(config.
|
| 130 |
.download(storagePath);
|
| 131 |
|
| 132 |
if (error) {
|
|
@@ -150,7 +150,7 @@ export async function deleteInputFile(storagePath: string): Promise<void> {
|
|
| 150 |
}
|
| 151 |
|
| 152 |
const { error } = await supabase.storage
|
| 153 |
-
.from(config.
|
| 154 |
.remove([storagePath]);
|
| 155 |
if (error) {
|
| 156 |
logger.error('Failed to delete staged input file', {
|
|
@@ -196,7 +196,7 @@ export async function uploadReportPdf(
|
|
| 196 |
const fileBuffer = fs.readFileSync(localPdfPath);
|
| 197 |
|
| 198 |
const { error } = await supabase.storage
|
| 199 |
-
.from(config.
|
| 200 |
.upload(storagePath, fileBuffer, {
|
| 201 |
contentType: 'application/pdf',
|
| 202 |
upsert: true,
|
|
@@ -245,7 +245,7 @@ export async function uploadReceiptPdf(
|
|
| 245 |
const fileBuffer = fs.readFileSync(localPdfPath);
|
| 246 |
|
| 247 |
const { error } = await supabase.storage
|
| 248 |
-
.from(config.
|
| 249 |
.upload(storagePath, fileBuffer, {
|
| 250 |
contentType: 'application/pdf',
|
| 251 |
upsert: true,
|
|
@@ -280,7 +280,7 @@ export async function deleteReportPdf(storagePath: string): Promise<void> {
|
|
| 280 |
}
|
| 281 |
|
| 282 |
const { error } = await supabase.storage
|
| 283 |
-
.from(config.
|
| 284 |
.remove([storagePath]);
|
| 285 |
|
| 286 |
if (error) {
|
|
@@ -317,7 +317,7 @@ export async function uploadStorageState(
|
|
| 317 |
}
|
| 318 |
|
| 319 |
const { error } = await supabase.storage
|
| 320 |
-
.from(config.
|
| 321 |
.upload(storagePath, Buffer.from(stateJson, 'utf-8'), {
|
| 322 |
contentType: 'application/json',
|
| 323 |
upsert: true,
|
|
@@ -349,7 +349,7 @@ export async function downloadStorageState(storagePath: string): Promise<string
|
|
| 349 |
}
|
| 350 |
|
| 351 |
const { data, error } = await supabase.storage
|
| 352 |
-
.from(config.
|
| 353 |
.download(storagePath);
|
| 354 |
|
| 355 |
if (error) {
|
|
@@ -390,8 +390,16 @@ export async function createSignedUrl(
|
|
| 390 |
}
|
| 391 |
}
|
| 392 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
const { data, error } = await supabase.storage
|
| 394 |
-
.from(
|
| 395 |
.createSignedUrl(
|
| 396 |
filePath,
|
| 397 |
expiresInSeconds,
|
|
|
|
| 45 |
}
|
| 46 |
|
| 47 |
const { error } = await supabase.storage
|
| 48 |
+
.from(config.supabaseInputBucket)
|
| 49 |
.upload(storagePath, fileBuffer, {
|
| 50 |
contentType: getMimeType(ext),
|
| 51 |
upsert,
|
|
|
|
| 94 |
// legacy objects/deployments; R2 is the configured destination for new jobs.
|
| 95 |
const fileBuffer = await fs.promises.readFile(localPath);
|
| 96 |
const { error } = await supabase.storage
|
| 97 |
+
.from(config.supabaseInputBucket)
|
| 98 |
.upload(storagePath, fileBuffer, {
|
| 99 |
contentType: getMimeType(ext),
|
| 100 |
upsert,
|
|
|
|
| 126 |
}
|
| 127 |
|
| 128 |
const { data, error } = await supabase.storage
|
| 129 |
+
.from(config.supabaseInputBucket)
|
| 130 |
.download(storagePath);
|
| 131 |
|
| 132 |
if (error) {
|
|
|
|
| 150 |
}
|
| 151 |
|
| 152 |
const { error } = await supabase.storage
|
| 153 |
+
.from(config.supabaseInputBucket)
|
| 154 |
.remove([storagePath]);
|
| 155 |
if (error) {
|
| 156 |
logger.error('Failed to delete staged input file', {
|
|
|
|
| 196 |
const fileBuffer = fs.readFileSync(localPdfPath);
|
| 197 |
|
| 198 |
const { error } = await supabase.storage
|
| 199 |
+
.from(config.supabaseReportBucket)
|
| 200 |
.upload(storagePath, fileBuffer, {
|
| 201 |
contentType: 'application/pdf',
|
| 202 |
upsert: true,
|
|
|
|
| 245 |
const fileBuffer = fs.readFileSync(localPdfPath);
|
| 246 |
|
| 247 |
const { error } = await supabase.storage
|
| 248 |
+
.from(config.supabaseReportBucket)
|
| 249 |
.upload(storagePath, fileBuffer, {
|
| 250 |
contentType: 'application/pdf',
|
| 251 |
upsert: true,
|
|
|
|
| 280 |
}
|
| 281 |
|
| 282 |
const { error } = await supabase.storage
|
| 283 |
+
.from(config.supabaseReportBucket)
|
| 284 |
.remove([storagePath]);
|
| 285 |
|
| 286 |
if (error) {
|
|
|
|
| 317 |
}
|
| 318 |
|
| 319 |
const { error } = await supabase.storage
|
| 320 |
+
.from(config.supabaseSessionBucket)
|
| 321 |
.upload(storagePath, Buffer.from(stateJson, 'utf-8'), {
|
| 322 |
contentType: 'application/json',
|
| 323 |
upsert: true,
|
|
|
|
| 349 |
}
|
| 350 |
|
| 351 |
const { data, error } = await supabase.storage
|
| 352 |
+
.from(config.supabaseSessionBucket)
|
| 353 |
.download(storagePath);
|
| 354 |
|
| 355 |
if (error) {
|
|
|
|
| 390 |
}
|
| 391 |
}
|
| 392 |
|
| 393 |
+
const legacyBucket =
|
| 394 |
+
bucket === config.reportBucket
|
| 395 |
+
? config.supabaseReportBucket
|
| 396 |
+
: bucket === config.inputBucket
|
| 397 |
+
? config.supabaseInputBucket
|
| 398 |
+
: bucket === config.sessionBucket
|
| 399 |
+
? config.supabaseSessionBucket
|
| 400 |
+
: bucket;
|
| 401 |
const { data, error } = await supabase.storage
|
| 402 |
+
.from(legacyBucket)
|
| 403 |
.createSignedUrl(
|
| 404 |
filePath,
|
| 405 |
expiresInSeconds,
|