Files
claude-mem/scripts/sync-marketplace.cjs
T
Alex Newman f1162ed4a4 fix: remove sharp dependency that was never needed (#1141)
Sharp was an explicit dependency but nothing in the codebase imports it.
Chroma embeddings use ONNX Runtime via @chroma-core/default-embed, not sharp.
Sharp's native binary has a persistent Bun node_modules layout bug where
@img/sharp-libvips-* isn't placed alongside @img/sharp-darwin-* causing
ERR_DLOPEN_FAILED on every install.

- Remove sharp, @img/sharp-libvips-darwin-arm64, node-gyp from deps
- Remove node-addon-api from devDeps
- Remove @img cache clearing hacks from smart-install.js and sync-marketplace.cjs
- Replace with simple `bun pm cache rm` before install as general cache hygiene

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 19:20:34 -05:00

140 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
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
/**
* Protected sync-marketplace script
*
* Prevents accidental rsync overwrite when installed plugin is on beta branch.
* If on beta, the user should use the UI to update instead.
*/
const { execSync } = require('child_process');
const { existsSync, readFileSync } = require('fs');
const path = require('path');
const os = require('os');
const INSTALLED_PATH = path.join(os.homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack');
const CACHE_BASE_PATH = path.join(os.homedir(), '.claude', 'plugins', 'cache', 'thedotmack', 'claude-mem');
function getCurrentBranch() {
try {
if (!existsSync(path.join(INSTALLED_PATH, '.git'))) {
return null;
}
return execSync('git rev-parse --abbrev-ref HEAD', {
cwd: INSTALLED_PATH,
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe']
}).trim();
} catch {
return null;
}
}
function getGitignoreExcludes(basePath) {
const gitignorePath = path.join(basePath, '.gitignore');
if (!existsSync(gitignorePath)) return '';
const lines = readFileSync(gitignorePath, 'utf-8').split('\n');
return lines
.map(line => line.trim())
.filter(line => line && !line.startsWith('#') && !line.startsWith('!'))
.map(pattern => `--exclude=${JSON.stringify(pattern)}`)
.join(' ');
}
const branch = getCurrentBranch();
const isForce = process.argv.includes('--force');
if (branch && branch !== 'main' && !isForce) {
console.log('');
console.log('\x1b[33m%s\x1b[0m', `WARNING: Installed plugin is on beta branch: ${branch}`);
console.log('\x1b[33m%s\x1b[0m', 'Running rsync would overwrite beta code.');
console.log('');
console.log('Options:');
console.log(' 1. Use UI at http://localhost:37777 to update beta');
console.log(' 2. Switch to stable in UI first, then run sync');
console.log(' 3. Force rsync: npm run sync-marketplace:force');
console.log('');
process.exit(1);
}
// Get version from plugin.json
function getPluginVersion() {
try {
const pluginJsonPath = path.join(__dirname, '..', 'plugin', '.claude-plugin', 'plugin.json');
const pluginJson = JSON.parse(readFileSync(pluginJsonPath, 'utf-8'));
return pluginJson.version;
} catch (error) {
console.error('\x1b[31m%s\x1b[0m', 'Failed to read plugin version:', error.message);
process.exit(1);
}
}
// Normal rsync for main branch or fresh install
console.log('Syncing to marketplace...');
try {
const rootDir = path.join(__dirname, '..');
const gitignoreExcludes = getGitignoreExcludes(rootDir);
execSync(
`rsync -av --delete --exclude=.git --exclude=/.mcp.json --exclude=bun.lock --exclude=package-lock.json ${gitignoreExcludes} ./ ~/.claude/plugins/marketplaces/thedotmack/`,
{ stdio: 'inherit' }
);
// Clear Bun's package cache to prevent stale native module artifacts
try {
execSync('bun pm cache rm', { cwd: INSTALLED_PATH, stdio: 'pipe' });
console.log('Cleared Bun package cache');
} catch {
// Cache may not exist yet on first install
}
console.log('Running bun install in marketplace...');
execSync(
'cd ~/.claude/plugins/marketplaces/thedotmack/ && bun install',
{ stdio: 'inherit' }
);
// Sync to cache folder with version
const version = getPluginVersion();
const CACHE_VERSION_PATH = path.join(CACHE_BASE_PATH, version);
const pluginDir = path.join(rootDir, 'plugin');
const pluginGitignoreExcludes = getGitignoreExcludes(pluginDir);
console.log(`Syncing to cache folder (version ${version})...`);
execSync(
`rsync -av --delete --exclude=.git ${pluginGitignoreExcludes} plugin/ "${CACHE_VERSION_PATH}/"`,
{ stdio: 'inherit' }
);
console.log('\x1b[32m%s\x1b[0m', 'Sync complete!');
// Trigger worker restart after file sync
console.log('\n🔄 Triggering worker restart...');
const http = require('http');
const req = http.request({
hostname: '127.0.0.1',
port: 37777,
path: '/api/admin/restart',
method: 'POST',
timeout: 2000
}, (res) => {
if (res.statusCode === 200) {
console.log('\x1b[32m%s\x1b[0m', '✓ Worker restart triggered');
} else {
console.log('\x1b[33m%s\x1b[0m', ` Worker restart returned status ${res.statusCode}`);
}
});
req.on('error', () => {
console.log('\x1b[33m%s\x1b[0m', ' Worker not running, will start on next hook');
});
req.on('timeout', () => {
req.destroy();
console.log('\x1b[33m%s\x1b[0m', ' Worker restart timed out');
});
req.end();
} catch (error) {
console.error('\x1b[31m%s\x1b[0m', 'Sync failed:', error.message);
process.exit(1);
}