tractatus/scripts/update-cache-version.js
TheFlow 2238547344 refactor: Rename "Home AI" → "Village AI" across entire codebase
- 57 files modified, 5 files renamed (home-ai → village-ai)
- HTML pages: all user-facing text, data-i18n attributes, anchor IDs, CSS classes
- i18n JSON: keys (home_ai → village_ai) and values across en/de/fr/mi
- Locale files renamed: home-ai.json → village-ai.json (4 languages)
- Main page renamed: home-ai.html → village-ai.html
- Research downloads: translated terms updated (French "IA domestique",
  Māori "AI ā-whare"/"AI kāinga" → "Village AI" per brand name rule)
- JavaScript: navbar component, blog post scripts
- Markdown: research timeline, steering vectors paper, taonga paper

Aligns with community codebase rename (commit 21ab7bc0).
"Village" is a brand name — stays untranslated in all languages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:09:44 +13:00

222 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Update Cache Version - Unified Cache Busting
*
* CRITICAL: Run this script EVERY TIME JavaScript files are modified!
*
* Updates:
* 1. All HTML files with ?v= cache-busting parameters
* 2. public/service-worker.js CACHE_VERSION constant
* 3. public/version.json with new version and changelog
*
* Format: v={package.version}.{timestamp}
* Example: v=0.1.0.1760201234
*
* This ensures:
* - Browser cache is invalidated
* - Service worker forces refresh
* - Version tracking is updated
*/
const fs = require('fs');
const path = require('path');
const packageJson = require('../package.json');
// Parse semantic version from package.json
const [major, minor, patch] = packageJson.version.split('.').map(Number);
// Generate cache version: package version + timestamp
const timestamp = Date.now();
const CACHE_VERSION = `${packageJson.version}.${timestamp}`;
// Bump patch version for version.json
const NEW_SEMVER = `${major}.${minor}.${patch + 1}`;
const VERSION_FILE = path.join(__dirname, '../public/version.json');
const SERVICE_WORKER_FILE = path.join(__dirname, '../public/service-worker.js');
// HTML files to update (relative to project root)
const HTML_FILES = [
'public/index.html',
'public/docs.html',
'public/faq.html',
'public/researcher.html',
'public/implementer.html',
'public/leader.html',
'public/about.html',
'public/privacy.html',
'public/blog.html',
'public/blog-post.html',
'public/docs-viewer.html',
'public/api-reference.html',
'public/media-inquiry.html',
'public/case-submission.html',
'public/koha.html',
'public/check-version.html',
'public/village-ai.html',
'public/architecture.html',
'public/village-case-study.html',
'public/architectural-alignment.html',
'public/architectural-alignment-community.html',
'public/architectural-alignment-policymakers.html',
'public/korero-counter-arguments.html',
'public/admin/blog-curation.html',
'public/admin/dashboard.html'
];
/**
* Update cache version in a file
* Replaces all instances of ?v=X with ?v={CACHE_VERSION}
*/
function updateCacheVersion(filePath) {
try {
const fullPath = path.join(__dirname, '..', filePath);
if (!fs.existsSync(fullPath)) {
console.warn(`⚠️ File not found: ${filePath}`);
return false;
}
let content = fs.readFileSync(fullPath, 'utf8');
const originalContent = content;
// Pattern: ?v=ANYTHING → ?v={CACHE_VERSION}
// Matches: ?v=1.0.4, ?v=1759833751, ?v=1.0.5.1760123456
content = content.replace(/\?v=[0-9a-zA-Z._-]+/g, `?v=${CACHE_VERSION}`);
// Also catch bare CSS/JS references that are missing ?v= entirely
// Adds ?v= to .css and .js hrefs/srcs that don't have one
content = content.replace(/(href|src)="([^"]+\.(?:css|js))(?!.*\?v=)"/g, `$1="$2?v=${CACHE_VERSION}"`);
// Only write if changed
if (content !== originalContent) {
fs.writeFileSync(fullPath, content, 'utf8');
// Count replacements
const matches = originalContent.match(/\?v=[0-9a-zA-Z._-]+/g) || [];
console.log(`${filePath}: Updated ${matches.length} cache version(s)`);
return true;
} else {
console.log(` ${filePath}: No changes needed`);
return false;
}
} catch (error) {
console.error(`❌ Error updating ${filePath}:`, error.message);
return false;
}
}
/**
* Update service worker CACHE_VERSION
*/
function updateServiceWorker() {
try {
let content = fs.readFileSync(SERVICE_WORKER_FILE, 'utf8');
const original = content;
// Update CACHE_VERSION constant
content = content.replace(
/const CACHE_VERSION = '[^']+';/,
`const CACHE_VERSION = '${NEW_SEMVER}';`
);
if (content !== original) {
fs.writeFileSync(SERVICE_WORKER_FILE, content);
console.log(`✅ service-worker.js: Updated CACHE_VERSION to ${NEW_SEMVER}`);
return true;
}
return false;
} catch (error) {
console.error(`❌ Error updating service-worker.js:`, error.message);
return false;
}
}
/**
* Update version.json
*/
function updateVersionJson() {
try {
const versionData = JSON.parse(fs.readFileSync(VERSION_FILE, 'utf8'));
versionData.version = NEW_SEMVER;
versionData.buildDate = new Date().toISOString();
versionData.forceUpdate = false;
// Preserve existing changelog
if (!versionData.changelog) {
versionData.changelog = ['Cache version update - JavaScript files modified'];
}
fs.writeFileSync(VERSION_FILE, JSON.stringify(versionData, null, 2) + '\n');
console.log(`✅ version.json: Updated to ${NEW_SEMVER}`);
return true;
} catch (error) {
console.error(`❌ Error updating version.json:`, error.message);
return false;
}
}
/**
* Main execution
*/
function main() {
console.log('');
console.log('═'.repeat(70));
console.log(' Tractatus - Cache Version Update (CRITICAL FOR .JS CHANGES)');
console.log('═'.repeat(70));
console.log('');
console.log(`📦 Package version: ${packageJson.version}`);
console.log(`🔄 New semantic version: ${NEW_SEMVER}`);
console.log(`🔄 New cache-bust version: ${CACHE_VERSION}`);
console.log('');
// Step 1: Update service worker
console.log('Step 1: Updating service worker...');
updateServiceWorker();
console.log('');
// Step 2: Update version.json
console.log('Step 2: Updating version.json...');
updateVersionJson();
console.log('');
// Step 3: Update HTML cache parameters
console.log('Step 3: Updating HTML cache parameters...');
let updatedCount = 0;
let totalFiles = 0;
HTML_FILES.forEach(file => {
totalFiles++;
if (updateCacheVersion(file)) {
updatedCount++;
}
});
console.log('');
console.log('═'.repeat(70));
console.log(` Summary: ${updatedCount}/${totalFiles} HTML files updated`);
console.log('═'.repeat(70));
console.log('');
console.log('✅ Cache version update complete!');
console.log('');
console.log('📝 Files modified:');
console.log(' - public/service-worker.js (CACHE_VERSION)');
console.log(' - public/version.json (version + buildDate)');
console.log(` - ${updatedCount} HTML files (?v= parameters)`);
console.log('');
console.log('⚠️ NEXT STEPS:');
console.log(' 1. Review changes: git diff');
console.log(' 2. Commit: git add -A && git commit -m "chore: bump cache version"');
console.log(' 3. Deploy to production');
console.log('');
}
// Run if called directly
if (require.main === module) {
main();
}
module.exports = { updateCacheVersion, CACHE_VERSION };