fix(backend): enhance sequence discovery from sister website directories and sync in post-receive

This commit is contained in:
Your Name committed 2026-10-17 11:26:29 +07:00
1 parent 0bf544720b
commit ca79692b3e
3 files changed
+71 -10

No files matched your search

+10 -3
View File
@@ -35,7 +35,7 @@ import { crmRoute } from "./routes/crm";
import { brandKnowledgeRoute } from "./routes/brandKnowledge"; import { brandKnowledgeRoute } from "./routes/brandKnowledge";
import { categorySectionsRoute } from "./routes/categorySections"; import { categorySectionsRoute } from "./routes/categorySections";
import { llmPromptsRoute } from "./routes/llmPrompts"; import { llmPromptsRoute } from "./routes/llmPrompts";
import { frameSequencesRoute } from "./routes/frame-sequences"; import { frameSequencesRoute, getCandidateSequenceDirs } from "./routes/frame-sequences";
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3051; const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3051;
const CORS_ORIGIN = process.env.CORS_ORIGIN || "http://localhost:5173"; const CORS_ORIGIN = process.env.CORS_ORIGIN || "http://localhost:5173";
const JWT_SECRET = process.env.JWT_SECRET || "homaroma_secret_2026_brand"; const JWT_SECRET = process.env.JWT_SECRET || "homaroma_secret_2026_brand";
@@ -142,9 +142,16 @@ const app = new Elysia()
} }
return file; return file;
}) })
.get("/frame-sequences/:sequence/:filename", ({ params: { sequence, filename }, set }) => { .get("/frame-sequences/:sequence/:filename", async ({ params: { sequence, filename }, set }) => {
const file = Bun.file(`public/frame-sequences/${sequence}/${filename}`); let file = Bun.file(`public/frame-sequences/${sequence}/${filename}`);
if (file.size === 0) { if (file.size === 0) {
const candidateDirs = await getCandidateSequenceDirs();
for (const d of candidateDirs) {
const altFile = Bun.file(`${d}/${sequence}/${filename}`);
if (altFile.size > 0) {
return altFile;
}
}
set.status = 404; set.status = 404;
return "File not found"; return "File not found";
} }
+57 -7
View File
@@ -19,28 +19,73 @@ export interface FrameSequenceManifest {
const getBaseDir = () => join(process.cwd(), "public", "frame-sequences"); const getBaseDir = () => join(process.cwd(), "public", "frame-sequences");
export const getCandidateSequenceDirs = async (): Promise<string[]> => {
const candidates: string[] = [
getBaseDir(),
join(process.cwd(), "..", "website", "public", "frame-sequences"),
join(process.cwd(), "..", "..", "website", "public", "frame-sequences"),
];
try {
// Check sister projects in deployment layout (e.g. /home/ti/projects/ddc-website/apps/website/public/frame-sequences)
const possibleProjectRoots = [
join(process.cwd(), "..", ".."),
join(process.cwd(), "..", "..", ".."),
];
for (const root of possibleProjectRoots) {
if (existsSync(root)) {
const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
for (const e of entries) {
if (e.isDirectory() && (e.name.includes("website") || e.name.includes("shop"))) {
candidates.push(join(root, e.name, "apps", "website", "public", "frame-sequences"));
candidates.push(join(root, e.name, "public", "frame-sequences"));
}
}
}
}
} catch (err) {
// non-fatal
}
return Array.from(new Set(candidates.filter((d) => existsSync(d))));
};
export const frameSequencesRoute = new Elysia({ prefix: "/frame-sequences" }) export const frameSequencesRoute = new Elysia({ prefix: "/frame-sequences" })
// 1. List all Frame Sequences (Reads manifests from public/frame-sequences/*) // 1. List all Frame Sequences (Reads manifests from public/frame-sequences/* and candidate directories)
.get("/", async () => { .get("/", async () => {
const baseDir = getBaseDir(); const baseDir = getBaseDir();
if (!existsSync(baseDir)) { if (!existsSync(baseDir)) {
await mkdir(baseDir, { recursive: true }); await mkdir(baseDir, { recursive: true }).catch(() => {});
return { sequences: [] };
} }
const entries = await readdir(baseDir, { withFileTypes: true }); const searchDirs = await getCandidateSequenceDirs();
const seenSlugs = new Set<string>();
const sequences: FrameSequenceManifest[] = []; const sequences: FrameSequenceManifest[] = [];
for (const dir of searchDirs) {
try {
const entries = await readdir(dir, { withFileTypes: true });
for (const entry of entries) { for (const entry of entries) {
if (!entry.isDirectory()) continue; if (!entry.isDirectory()) continue;
const folderPath = join(baseDir, entry.name); if (seenSlugs.has(entry.name)) continue;
const folderPath = join(dir, entry.name);
const manifestPath = join(folderPath, "manifest.json"); const manifestPath = join(folderPath, "manifest.json");
if (existsSync(manifestPath)) { if (existsSync(manifestPath)) {
try { try {
const raw = await readFile(manifestPath, "utf8"); const raw = await readFile(manifestPath, "utf8");
const manifest: FrameSequenceManifest = JSON.parse(raw); const manifest: FrameSequenceManifest = JSON.parse(raw);
seenSlugs.add(entry.name);
sequences.push(manifest); sequences.push(manifest);
// Auto-sync manifest to local backend baseDir if not present
const localSeqDir = join(baseDir, entry.name);
if (!existsSync(localSeqDir)) {
await mkdir(localSeqDir, { recursive: true }).catch(() => {});
await writeFile(join(localSeqDir, "manifest.json"), raw, "utf8").catch(() => {});
}
continue; continue;
} catch (e) { } catch (e) {
console.error(`Failed to parse manifest in ${entry.name}`, e); console.error(`Failed to parse manifest in ${entry.name}`, e);
@@ -69,11 +114,16 @@ export const frameSequencesRoute = new Elysia({ prefix: "/frame-sequences" })
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
}; };
await writeFile(manifestPath, JSON.stringify(autoManifest, null, 2), "utf8"); await writeFile(manifestPath, JSON.stringify(autoManifest, null, 2), "utf8").catch(() => {});
seenSlugs.add(entry.name);
sequences.push(autoManifest); sequences.push(autoManifest);
} }
} catch (scanErr) {
console.error(`Error scanning sequence folder ${entry.name}`, scanErr);
}
}
} catch (err) { } catch (err) {
console.error(`Error scanning sequence folder ${entry.name}`, err); // Continue to next candidate dir
} }
} }
+4
View File
@@ -90,6 +90,10 @@ $BUN install
# สร้าง public/ folder สำหรับ static files (upload images) # สร้าง public/ folder สำหรับ static files (upload images)
mkdir -p $TARGET_BACKEND/apps/backend/public mkdir -p $TARGET_BACKEND/apps/backend/public
if [ -d "$TEMP_DIR/apps/backend/public/frame-sequences" ]; then
mkdir -p $TARGET_BACKEND/apps/backend/public/frame-sequences
rsync -av "$TEMP_DIR/apps/backend/public/frame-sequences/" "$TARGET_BACKEND/apps/backend/public/frame-sequences/"
fi
cd $TARGET_BACKEND/apps/backend cd $TARGET_BACKEND/apps/backend