mirror of
https://github.com/got-feedBack/feedBack-desktop.git
synced 2026-07-21 20:31:28 +00:00
Snapshot the three public surfaces the audio-engine decomposition must not change (docs/audio-engine-tlc.md Part IV §4): addon export table, audio-bridge IPC channels, preload audio/audioEffects API keys. contract-check.test.js diffs regenerated surfaces against the committed snapshots. result-shapes.json (golden result key/type shapes) is deferred until the engine_units harness can run the addon against a null device. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
87 lines
3.5 KiB
JavaScript
87 lines
3.5 KiB
JavaScript
// Contract-surface extraction for the audio engine TLC refactor (Phase 0.a,
|
|
// docs/audio-engine-tlc.md §4). Each extractor returns a sorted, stable JSON
|
|
// snapshot of one public surface. contract-check.test.js diffs these against
|
|
// the committed snapshots so a decomposition phase cannot silently change the
|
|
// public API. Regenerate deliberately with: node tests/contracts/extract.js
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const repoRoot = path.join(__dirname, '..', '..');
|
|
|
|
// Export table of slopsmith_audio.node. Loads the real binary; returns null
|
|
// when it hasn't been built (contract-check skips with a warning then).
|
|
function extractAddonExports() {
|
|
const addonPath = path.join(repoRoot, 'build', 'Release', 'slopsmith_audio.node');
|
|
if (!fs.existsSync(addonPath)) return null;
|
|
const addon = require(addonPath);
|
|
return Object.keys(addon).sort();
|
|
}
|
|
|
|
// Every ipcMain.handle / ipcMain.on channel registered in audio-bridge.ts.
|
|
function extractIpcChannels() {
|
|
const src = fs.readFileSync(path.join(repoRoot, 'src', 'main', 'audio-bridge.ts'), 'utf8');
|
|
const channels = new Set();
|
|
const re = /ipcMain\.(?:handle|on)\(\s*'([^']+)'/g;
|
|
let m;
|
|
while ((m = re.exec(src)) !== null) channels.add(m[1]);
|
|
return [...channels].sort();
|
|
}
|
|
|
|
// Top-level method keys of the `audio:` and `audioEffects:` object literals in
|
|
// preload.ts — the surface the renderer (and every plugin) programs against.
|
|
// Brace-depth walk: record keys only at depth 1 inside the target literal.
|
|
function extractPreloadKeys(objectName, src) {
|
|
const start = src.indexOf(`${objectName}: {`);
|
|
if (start === -1) throw new Error(`preload.ts: '${objectName}: {' not found`);
|
|
let i = src.indexOf('{', start);
|
|
let depth = 0;
|
|
let parenDepth = 0; // multi-line parameter lists must not yield keys
|
|
const keys = [];
|
|
let lineStart = i;
|
|
for (; i < src.length; i++) {
|
|
const c = src[i];
|
|
if (c === '{') depth++;
|
|
else if (c === '}') {
|
|
depth--;
|
|
if (depth === 0) break;
|
|
} else if (c === '(') parenDepth++;
|
|
else if (c === ')') parenDepth--;
|
|
else if (c === '\n') {
|
|
lineStart = i + 1;
|
|
} else if (depth === 1 && parenDepth === 0) {
|
|
// At a key position: line begins (after whitespace) with `name:`
|
|
if (i === lineStart) {
|
|
const line = src.slice(lineStart, src.indexOf('\n', lineStart));
|
|
const km = line.match(/^\s*([A-Za-z_$][\w$]*)\s*:/);
|
|
if (km) keys.push(km[1]);
|
|
}
|
|
}
|
|
}
|
|
return keys.sort();
|
|
}
|
|
|
|
function extractPreloadApi() {
|
|
const src = fs.readFileSync(path.join(repoRoot, 'src', 'main', 'preload.ts'), 'utf8');
|
|
return {
|
|
audio: extractPreloadKeys('audio', src),
|
|
audioEffects: extractPreloadKeys('audioEffects', src),
|
|
};
|
|
}
|
|
|
|
function writeSnapshot(name, data) {
|
|
fs.writeFileSync(path.join(__dirname, name), JSON.stringify(data, null, 2) + '\n');
|
|
}
|
|
|
|
module.exports = { extractAddonExports, extractIpcChannels, extractPreloadApi };
|
|
|
|
if (require.main === module) {
|
|
const addonExports = extractAddonExports();
|
|
if (addonExports) writeSnapshot('addon-exports.json', addonExports);
|
|
else console.warn('addon not built — skipping addon-exports.json');
|
|
writeSnapshot('ipc-channels.json', extractIpcChannels());
|
|
writeSnapshot('preload-audio-api.json', extractPreloadApi());
|
|
console.log('contract snapshots written to tests/contracts/');
|
|
}
|