fix(recipes): build deploy against .env_prod; harden image save
Recipe image upload failed in prod with ENOENT writing the full image. Root cause: the deploy built against the dev .env, whose relative IMAGE_DIR="./imgs/" resolves under the service's dist/ working dir instead of the real served image directory — and `$env/static/private` is inlined at build time, so dev values shipped to prod. - deploy.sh: source .env_prod (overridable via PROD_ENV) into the env before `pnpm build`, so prod values win over .env for the whole build lifecycle; abort if it's missing rather than ship a dev-env build. - .gitignore: ignore .env_* so .env_prod (prod secrets) isn't committed (the existing .env.* dot pattern didn't match the underscore form). - imageProcessing: mkdir -p the full/thumb dirs before writing. The WebP passthrough writes the full image with fs.writeFile, which (unlike sharp's toFile) does not create parent dirs. - recipeFormHelpers: add serializableFormValues() and use it in the add/ edit actions' fail() returns. Returning raw formData (now containing the recipe_image File) crashed the action response with a non-POJO devalue error, masking the real failure with an opaque 500.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import path from 'path';
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { writeFile, mkdir } from 'fs/promises';
|
||||
import sharp from 'sharp';
|
||||
import { generateImageHashFromBuffer, getHashedFilename } from '$utils/imageHash';
|
||||
import { validateImageFile } from '$utils/imageValidation';
|
||||
@@ -138,8 +138,15 @@ export async function processAndSaveRecipeImage(
|
||||
// the size the user saw in the editor — re-encoding through sharp would silently
|
||||
// re-compress and discard their quality/size choice.
|
||||
// Fallback (non-webp upload, e.g. editor bypassed): re-encode to WebP q90 as before.
|
||||
const fullHashedPath = path.join(imageDir, 'rezepte', 'full', hashedFilename);
|
||||
const fullUnhashedPath = path.join(imageDir, 'rezepte', 'full', unhashedFilename);
|
||||
const fullDir = path.join(imageDir, 'rezepte', 'full');
|
||||
const thumbDir = path.join(imageDir, 'rezepte', 'thumb');
|
||||
// fs.writeFile (unlike sharp's toFile) does not create parent dirs, so ensure
|
||||
// both target directories exist before writing.
|
||||
await mkdir(fullDir, { recursive: true });
|
||||
await mkdir(thumbDir, { recursive: true });
|
||||
|
||||
const fullHashedPath = path.join(fullDir, hashedFilename);
|
||||
const fullUnhashedPath = path.join(fullDir, unhashedFilename);
|
||||
|
||||
let fullBuffer: Buffer;
|
||||
if (file.type === 'image/webp') {
|
||||
@@ -165,8 +172,8 @@ export async function processAndSaveRecipeImage(
|
||||
.toBuffer();
|
||||
console.log('[ImageProcessing] Thumbnail buffer created, size:', thumbBuffer.length, 'bytes');
|
||||
|
||||
const thumbHashedPath = path.join(imageDir, 'rezepte', 'thumb', hashedFilename);
|
||||
const thumbUnhashedPath = path.join(imageDir, 'rezepte', 'thumb', unhashedFilename);
|
||||
const thumbHashedPath = path.join(thumbDir, hashedFilename);
|
||||
const thumbUnhashedPath = path.join(thumbDir, unhashedFilename);
|
||||
console.log('[ImageProcessing] Saving thumbnail to:', { thumbHashedPath, thumbUnhashedPath });
|
||||
|
||||
await sharp(thumbBuffer).toFile(thumbHashedPath);
|
||||
|
||||
Reference in New Issue
Block a user