docs: final polish and refined protocol automation

This commit is contained in:
MacBook
2026-05-04 04:45:02 +02:00
parent 652f1cef4f
commit c9ec6ce3e0
3 changed files with 40 additions and 16 deletions
+3 -3
View File
@@ -62,6 +62,6 @@ KoalaSync uses a megaphone routing approach to minimize server logic:
## 8. Constant Synchronization & Consistency
To maintain a "Single Source of Truth" across the server and extension without using a bundler:
- **Relay Server & Extension Modules**: `background.js` and `popup.js` import constants directly from `shared/constants.js`.
- **Content Scripts**: To ensure zero-latency execution, `content.js` uses a manual mirror of `EVENTS`.
- **Synchronization**: The `node scripts/build-extension.js` script ensures that the `shared/` folder within the `extension/` directory is kept up-to-date with the root `shared/` source while packaging artifacts.
- **Verification**: Any protocol change requires a manual verification sweep across all three constant locations (Shared, Server, and Content Script Mirror).
- **Content Scripts**: To ensure zero-latency execution, `content.js` uses a synchronized copy of `EVENTS` and constants.
- **Automation**: The `node scripts/build-extension.js` script automatically injects these constants into `content.js` during the build process, eliminating the risk of manual mirror mismatch.
- **Verification**: Any protocol change is automatically propagated across the stack by running the build script.
+5 -1
View File
@@ -506,6 +506,10 @@
});
observer.observe(document.body, { childList: true, subtree: true });
// --- SHARED_HEARTBEAT_INJECT_START ---
const HEARTBEAT_INTERVAL_VAL = 15000;
// --- SHARED_HEARTBEAT_INJECT_END ---
// Heartbeat
let heartbeatErrorCount = 0;
const heartbeatInterval = setInterval(() => {
@@ -532,7 +536,7 @@
}
});
}
}, 15000);
}, HEARTBEAT_INTERVAL_VAL);
// Initial Setup
setupListeners();
+32 -12
View File
@@ -45,12 +45,19 @@ function copyExtensionFiles(targetDir) {
const masterConstantsPath = path.join(rootDir, 'shared', 'constants.js');
const constantsContent = fs.readFileSync(masterConstantsPath, 'utf8');
// Extract the EVENTS object using regex
const eventsMatch = constantsContent.match(/export const EVENTS = ({[\s\S]+?});/);
// Robust Extraction using flexible regex
const eventsMatch = constantsContent.match(/export const EVENTS\s*=\s*({[\s\S]+?});/);
const heartbeatMatch = constantsContent.match(/export const HEARTBEAT_INTERVAL\s*=\s*(\d+);/);
if (!eventsMatch) {
throw new Error('CRITICAL: Could not find EVENTS object in shared/constants.js');
}
if (!heartbeatMatch) {
throw new Error('CRITICAL: Could not find HEARTBEAT_INTERVAL in shared/constants.js');
}
const eventsObject = eventsMatch[1];
const heartbeatVal = heartbeatMatch[1];
const items = fs.readdirSync(extDir);
for (const item of items) {
@@ -65,20 +72,33 @@ function copyExtensionFiles(targetDir) {
if (item === 'content.js') {
// Perform injection
let content = fs.readFileSync(srcPath, 'utf8');
const startMarker = '// --- SHARED_EVENTS_INJECT_START ---';
const endMarker = '// --- SHARED_EVENTS_INJECT_END ---';
const pattern = new RegExp(`${startMarker}[\\s\\S]+?${endMarker}`);
const replacement = `${startMarker}\n // This block is automatically updated by /scripts/build-extension.js\n const EVENTS = ${eventsObject};\n ${endMarker}`;
// 1. Inject Events
const eStart = '// --- SHARED_EVENTS_INJECT_START ---';
const eEnd = '// --- SHARED_EVENTS_INJECT_END ---';
const ePattern = new RegExp(`${eStart}[\\s\\S]+?${eEnd}`);
const eRep = `${eStart}\n // This block is automatically updated by /scripts/build-extension.js\n const EVENTS = ${eventsObject};\n ${eEnd}`;
if (pattern.test(content)) {
content = content.replace(pattern, replacement);
fs.writeFileSync(destPath, content);
console.log('✓ Injected shared events into content.js');
if (ePattern.test(content)) {
content = content.replace(ePattern, eRep);
} else {
console.warn('⚠️ WARNING: Markers not found in content.js, skipping injection.');
fs.copyFileSync(srcPath, destPath);
console.warn('⚠️ WARNING: Event markers not found in content.js');
}
// 2. Inject Heartbeat
const hStart = '// --- SHARED_HEARTBEAT_INJECT_START ---';
const hEnd = '// --- SHARED_HEARTBEAT_INJECT_END ---';
const hPattern = new RegExp(`${hStart}[\\s\\S]+?${hEnd}`);
const hRep = `${hStart}\n const HEARTBEAT_INTERVAL_VAL = ${heartbeatVal};\n ${hEnd}`;
if (hPattern.test(content)) {
content = content.replace(hPattern, hRep);
} else {
console.warn('⚠️ WARNING: Heartbeat markers not found in content.js');
}
fs.writeFileSync(destPath, content);
console.log('✓ Injected shared constants into content.js');
} else {
fs.copyFileSync(srcPath, destPath);
}