finite: conduite task

This commit is contained in:
2026-05-01 12:42:37 +07:00
parent 04c7310749
commit d287badbee
14 changed files with 2417 additions and 630 deletions
+54
View File
@@ -18,6 +18,20 @@ module.exports = {
"assets/themes/**/*",
"public/**/*"
],
// Component-editor snapshots are written by the editor itself; reloading
// on them would race against the in-flight save and could overwrite tuned
// state with whatever loaded after the reload.
watchOptions: {
// Component-editor: never auto-reload. The editor holds in-memory tuning
// state and Save races; let the user reload manually when they want.
// Snapshots: written by the editor, reloading races against in-flight save.
ignored: [
"**/components/**/*.editor.html",
"**/components/**/*.editor.mjs",
"**/*.snapshot.json",
],
ignoreInitial: true,
},
port: 3300,
open: false,
notify: false,
@@ -34,6 +48,46 @@ module.exports = {
next();
}
},
{
route: "/api/save-component-snapshot",
handle: function (req, res, next) {
if (req.method !== 'POST') return next();
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', () => {
try {
const payload = JSON.parse(body);
const { theme, componentName, ...data } = payload;
if (!theme || !componentName) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Missing theme or componentName' }));
return;
}
// Reject path traversal
if (theme.includes('..') || theme.includes('/') ||
componentName.includes('..') || componentName.includes('/')) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid theme or componentName' }));
return;
}
const compDir = path.join(__dirname, 'assets', 'themes', theme, 'components', componentName);
if (!fs.existsSync(compDir)) {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Component directory not found: ' + compDir }));
return;
}
const snapshotPath = path.join(compDir, componentName + '.snapshot.json');
fs.writeFileSync(snapshotPath, JSON.stringify(data, null, 2));
console.log(`[snapshot] saved ${theme}/${componentName} → ${snapshotPath}`);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true, path: snapshotPath }));
} catch (e) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: e.message }));
}
});
}
},
{
route: "/api/save-edits",
handle: function (req, res, next) {