obsidian-plugin-config
Version:
Global CLI injection tool for Obsidian plugins
187 lines (153 loc) • 6.14 kB
JavaScript
/**
* Obsidian Plugin Config - CLI Entry Point
* Global command: obsidian-inject
* Version: 1.7.6
*/
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join, isAbsolute, resolve } from 'path';
import { readFile, access, unlink, rm } from 'fs/promises';
// Get the directory of this script
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const packageRoot = dirname(__dirname);
// Path to the injection script
const injectScriptPath = join(packageRoot, 'scripts', 'inject-path.ts');
async function pathExists(p) {
try {
await access(p);
return true;
} catch {
return false;
}
}
function showHelp() {
console.log(`
Obsidian Plugin Config - Global CLI
Injection system for autonomous Obsidian plugins
USAGE:
obsidian-inject # Inject in current directory (with confirmation)
obsidian-inject <path> # Inject by path (with confirmation)
obsidian-inject <path> --no # Inject without confirmation
obsidian-inject --help, -h # Show this help
OPTIONS:
--no, -n # Skip confirmation prompts (auto-confirm all)
--dry-run # Verification only (no changes)
EXAMPLES:
cd my-plugin && obsidian-inject
obsidian-inject ../my-other-plugin
obsidian-inject ../my-plugin --no
obsidian-inject "C:\\Users\\dev\\plugins\\my-plugin"
WHAT IS INJECTED:
✅ Local scripts (esbuild.config.ts, acp.ts, utils.ts, etc.)
✅ Package.json configuration (scripts, dependencies)
✅ Config files (tsconfig, eslint, prettier, vscode, github)
✅ Yarn protection enforced
✅ Automatic dependency installation
ARCHITECTURE:
- Plugin becomes AUTONOMOUS with local scripts
- No external dependencies required after injection
- Updates possible via re-injection
More info: https://github.com/3C0D/obsidian-plugin-config
`);
}
async function main() {
const args = process.argv.slice(2);
// Handle help flags
if (args.includes('--help') || args.includes('-h')) {
showHelp();
process.exit(0);
}
// Check if injection script exists
if (!(await pathExists(injectScriptPath))) {
console.error(`❌ Error: Injection script not found at ${injectScriptPath}`);
console.error(` Make sure obsidian-plugin-config is properly installed.`);
process.exit(1);
}
// Parse arguments
const noConfirm = args.includes('--no') || args.includes('-n');
const dryRun = args.includes('--dry-run');
const pathArg = args.find(arg => !arg.startsWith('-'));
// Determine target path (resolve relative to user's current directory)
const userCwd = process.cwd();
let targetPath = pathArg || userCwd;
// If relative path, resolve from user's current directory
if (pathArg && !isAbsolute(pathArg)) {
targetPath = resolve(userCwd, pathArg);
}
console.log(`🎯 Obsidian Plugin Config - Global Injection`);
console.log(`📁 Target: ${targetPath}`);
console.log(`❓ Confirmation: ${noConfirm ? 'Disabled (auto-confirm)' : 'Enabled'}`);
console.log(`📦 From: ${packageRoot}\n`);
try {
// Check if target directory has package.json
const targetPackageJson = join(targetPath, 'package.json');
if (!(await pathExists(targetPackageJson))) {
console.error(`❌ Error: package.json not found in ${targetPath}`);
console.error(` Make sure this is a valid Node.js project.`);
process.exit(1);
}
// Prevent injecting into obsidian-plugin-config itself
const pkg = JSON.parse(await readFile(targetPackageJson, 'utf8'));
if (pkg.name === 'obsidian-plugin-config') {
console.error(`❌ Cannot inject into obsidian-plugin-config itself.`);
process.exit(1);
}
// Clean NPM artifacts if package-lock.json exists
const packageLockPath = join(targetPath, 'package-lock.json');
if (await pathExists(packageLockPath)) {
console.log(`🧹 NPM installation detected, cleaning...`);
try {
// Remove package-lock.json
await unlink(packageLockPath);
console.log(` 🗑️ package-lock.json removed`);
// Remove node_modules if it exists
const nodeModulesPath = join(targetPath, 'node_modules');
if (await pathExists(nodeModulesPath)) {
await rm(nodeModulesPath, { recursive: true, force: true });
console.log(` 🗑️ node_modules removed (will be reinstalled with Yarn)`);
}
console.log(` ✅ NPM artifacts cleaned to avoid Yarn conflicts`);
} catch (cleanError) {
console.error(` ❌ Cleanup failed:`, cleanError instanceof Error ? cleanError.message : String(cleanError));
console.log(` 💡 Manually remove package-lock.json and node_modules`);
}
}
// Check if tsx is available locally in target
try {
execSync('npx tsx --version', {
cwd: targetPath,
stdio: 'pipe'
});
console.log(`✅ tsx available locally`);
} catch {
console.log(`⚠️ tsx not found, installing...`);
// Install tsx locally in target directory
try {
execSync('yarn add -D tsx', {
cwd: targetPath,
stdio: 'inherit'
});
console.log(`✅ tsx installed successfully`);
} catch (installError) {
console.error(`❌ tsx installation failed:`, installError.message);
console.error(` Try installing tsx manually: cd "${targetPath}" && yarn add -D tsx`);
process.exit(1);
}
}
// Execute the injection script with tsx
const yesOption = noConfirm ? ' --yes' : '';
const dryRunOption = dryRun ? ' --dry-run' : '';
const command = `npx tsx "${injectScriptPath}" "${targetPath}"${yesOption}${dryRunOption}`;
execSync(command, {
stdio: 'inherit',
cwd: targetPath // Use target directory to ensure tsx is available
});
console.log(`\n✅ Injection completed successfully!`);
} catch (error) {
console.error(`\n❌ Injection error:`, error.message);
process.exit(1);
}
}
main().catch(console.error);