waybetter-for-x/apps/desktop/scripts/build-areas.ts
2026-10-01 06:01:13 +07:00

55 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
// Writes what native code needs of the feature table (src/areas/table.ts) into
// src-tauri/src/areas.rs: the plugin files that became features (the one-time migration and the
// backup import map them to their flag) and every flag the table defines. One source, so the page,
// the panel and native code cannot disagree; tests/areas.test.ts fails when the file is stale.
//
// node scripts/build-areas.ts write src-tauri/src/areas.rs
// node scripts/build-areas.ts --check exit 1 when it is out of date
import { readFileSync, writeFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { supersededFiles, tableDefaults, validateTable } from '../../../waybetter/packages/runtime/src/featureTable.ts';
import { X_TABLE } from '../src/areas/table.ts';
export const AREAS_RS = fileURLToPath(new URL('../src-tauri/src/areas.rs', import.meta.url));
export function renderAreas(): string {
const problems = validateTable(X_TABLE);
if (problems.length) throw new Error(`src/areas/table.ts: ${problems.join('; ')}`);
const rust = (value: string) => JSON.stringify(value);
const superseded = supersededFiles(X_TABLE).map(row => ` Superseded { file: ${rust(row.file)}, flag: ${rust(row.flag)} },`);
const flags = Object.keys(tableDefaults(X_TABLE)).map(flag => ` ${rust(flag)},`);
return [
'//! Generated from `apps/desktop/src/areas/table.ts` by `scripts/build-areas.ts`. Do not edit:',
'//! change the table and run the script (tests/areas.test.ts compares them).',
'//!',
'//! What native code needs of the feature table: the bundled plugin files that became features of',
'//! an area plugin ([`SUPERSEDED`]: the one-time migration and the backup import turn their',
'//! enabled state into the flag), and every flag the table defines ([`FLAGS`]).',
'',
'use waybetter_host::plugins::migrate::Superseded;',
'',
'/// Old first-party plugin files and the feature flag that replaced each.',
'pub const SUPERSEDED: &[Superseded] = &[',
...superseded,
'];',
'',
'/// Every flag of the table: the features and each area\'s switch (`area.<id>`).',
'pub const FLAGS: &[&str] = &[',
...flags,
'];',
'',
].join('\n');
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
const next = renderAreas();
let current: string | null = null;
try { current = readFileSync(AREAS_RS, 'utf8'); } catch { /* not written yet */ }
if (process.argv.includes('--check')) {
if (current !== next) { console.error('src-tauri/src/areas.rs is out of date: run `node scripts/build-areas.ts`'); process.exit(1); }
} else if (current !== next) {
writeFileSync(AREAS_RS, next);
console.log('wrote src-tauri/src/areas.rs');
}
}