Files
antigravity-skills-reference/web-app/refresh-skills-plugin.js

119 lines
5.3 KiB
JavaScript

import https from 'https';
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const ROOT_DIR = path.resolve(__dirname, '..');
const REPO_ZIP_URL = 'https://github.com/sickn33/antigravity-awesome-skills/archive/refs/heads/main.zip';
function followRedirects(url, dest) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(dest);
const request = (url) => {
https.get(url, { headers: { 'User-Agent': 'antigravity-skills-app' } }, (res) => {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
request(res.headers.location);
return;
}
if (res.statusCode !== 200) {
reject(new Error(`Download failed with status ${res.statusCode}`));
return;
}
res.pipe(file);
file.on('finish', () => { file.close(); resolve(); });
}).on('error', (err) => { fs.unlink(dest, () => {}); reject(err); });
};
request(url);
});
}
export default function refreshSkillsPlugin() {
return {
name: 'refresh-skills',
configureServer(server) {
server.middlewares.use('/api/refresh-skills', async (req, res) => {
res.setHeader('Content-Type', 'application/json');
const zipPath = path.join(ROOT_DIR, 'update.zip');
const tempDir = path.join(ROOT_DIR, 'update_temp');
try {
// 1. Download the ZIP
console.log('[Sync] Downloading latest skills from GitHub...');
await followRedirects(REPO_ZIP_URL, zipPath);
// 2. Extract with PowerShell (Windows) or unzip (Unix)
console.log('[Sync] Extracting archive...');
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
if (process.platform === 'win32') {
execSync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${tempDir}' -Force"`, { stdio: 'ignore' });
} else {
fs.mkdirSync(tempDir, { recursive: true });
execSync(`unzip -o "${zipPath}" -d "${tempDir}"`, { stdio: 'ignore' });
}
// 3. Copy skills folder + index
const extractedRoot = path.join(tempDir, 'antigravity-awesome-skills-main');
const srcSkills = path.join(extractedRoot, 'skills');
const srcIndex = path.join(extractedRoot, 'skills_index.json');
const destSkills = path.join(ROOT_DIR, 'skills');
const destIndex = path.join(ROOT_DIR, 'skills_index.json');
if (!fs.existsSync(srcSkills)) {
throw new Error('Skills folder not found in downloaded archive.');
}
// Replace skills folder
if (fs.existsSync(destSkills)) fs.rmSync(destSkills, { recursive: true, force: true });
copyFolderSync(srcSkills, destSkills);
// Replace index
if (fs.existsSync(srcIndex)) fs.copyFileSync(srcIndex, destIndex);
// 4. Re-run setup_web.js logic to update web-app/public
const webPublic = path.join(__dirname, 'public');
const webSkills = path.join(webPublic, 'skills');
const webIndex = path.join(webPublic, 'skills.json');
if (fs.existsSync(webSkills)) fs.rmSync(webSkills, { recursive: true, force: true });
copyFolderSync(destSkills, webSkills);
if (fs.existsSync(destIndex)) fs.copyFileSync(destIndex, webIndex);
// Count skills
const skillsData = JSON.parse(fs.readFileSync(webIndex, 'utf-8'));
const count = Array.isArray(skillsData) ? skillsData.length : 0;
console.log(`[Sync] ✅ Successfully synced ${count} skills!`);
res.end(JSON.stringify({ success: true, count }));
} catch (err) {
console.error('[Sync] ❌ Failed:', err.message);
res.statusCode = 500;
res.end(JSON.stringify({ success: false, error: err.message }));
} finally {
// Cleanup
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
}
});
}
};
}
function copyFolderSync(from, to) {
if (!fs.existsSync(to)) fs.mkdirSync(to, { recursive: true });
for (const element of fs.readdirSync(from)) {
const srcPath = path.join(from, element);
const destPath = path.join(to, element);
if (fs.lstatSync(srcPath).isFile()) {
fs.copyFileSync(srcPath, destPath);
} else {
copyFolderSync(srcPath, destPath);
}
}
}