obsidian-plugin-config
Version:
Système d'injection pour plugins Obsidian autonomes
306 lines (249 loc) β’ 9.81 kB
text/typescript
#!/usr/bin/env tsx
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
/**
* Generate bin/obsidian-inject.js from template
*/
async function generateBinFile(): Promise<void> {
console.log(`\nπ§ Generating bin/obsidian-inject.js...`);
const binDir = "bin";
const binPath = path.join(binDir, "obsidian-inject.js");
// Ensure bin directory exists
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
console.log(` π Created ${binDir} directory`);
}
// Read package.json for version info
const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
const binContent = `#!/usr/bin/env node
/**
* Obsidian Plugin Config - CLI Entry Point
* Global command: obsidian-inject
* Version: ${packageJson.version}
*/
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join, isAbsolute, resolve } from 'path';
import fs from 'fs';
// 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');
function showHelp() {
console.log(\`
Obsidian Plugin Config - Global CLI
Injection system for autonomous Obsidian plugins
USAGE:
obsidian-inject # Inject in current directory
obsidian-inject <path> # Inject by path
obsidian-inject <path> --sass # Inject with SASS support
obsidian-inject --help, -h # Show this help
EXAMPLES:
cd my-plugin && obsidian-inject
obsidian-inject ../my-other-plugin
obsidian-inject ../my-plugin --sass
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)
β
Yarn protection enforced
β
Automatic dependency installation
π¨ SASS support (with --sass option): esbuild-sass-plugin + SCSS compilation
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
\`);
}
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 (!fs.existsSync(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 sassFlag = args.includes('--sass');
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(\`π¨ SASS: \${sassFlag ? 'Enabled' : 'Disabled'}\`);
console.log(\`π¦ From: \${packageRoot}\\n\`);
try {
// Check if target directory has package.json
const targetPackageJson = join(targetPath, 'package.json');
if (!fs.existsSync(targetPackageJson)) {
console.error(\`β Error: package.json not found in \${targetPath}\`);
console.error(\` Make sure this is a valid Node.js project.\`);
process.exit(1);
}
// Clean NPM artifacts if package-lock.json exists
const packageLockPath = join(targetPath, 'package-lock.json');
if (fs.existsSync(packageLockPath)) {
console.log(\`π§Ή NPM installation detected, cleaning...\`);
try {
// Remove package-lock.json
fs.unlinkSync(packageLockPath);
console.log(\` ποΈ package-lock.json removed\`);
// Remove node_modules if it exists
const nodeModulesPath = join(targetPath, 'node_modules');
if (fs.existsSync(nodeModulesPath)) {
fs.rmSync(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.message);
console.log(\` π‘ Manually remove package-lock.json and node_modules\`);
}
}
// Check if tsx is available locally in target
let tsxCommand = 'npx tsx';
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 sassOption = sassFlag ? ' --sass' : '';
const command = \`npx tsx "\${injectScriptPath}" "\${targetPath}" --yes\${sassOption}\`;
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);
}
}
// Run the CLI
main();
`;
fs.writeFileSync(binPath, binContent, "utf8");
console.log(` β
Generated ${binPath}`);
}
/**
* Complete NPM workflow - Version, Commit, Push, Publish
*/
function buildAndPublishNpm(): void {
console.log(`π Obsidian Plugin Config - Complete NPM Workflow`);
console.log(`Full automation: version β commit β push β exports β bin β publish\n`);
try {
// Step 1: Update version and push to GitHub
console.log(`π Step 1/6: Updating version...`);
execSync('echo 1 | tsx scripts/update-version-config.ts', { stdio: 'inherit' });
// Step 2: Commit and push any remaining changes
console.log(`\nπ€ Step 2/6: Committing and pushing changes...`);
try {
execSync('echo "Prepare NPM package publication" | tsx scripts/acp.ts -b', { stdio: 'inherit' });
} catch {
console.log(` βΉοΈ No additional changes to commit`);
}
// Step 3: Update exports automatically
console.log(`\nπ¦ Step 3/6: Updating exports...`);
execSync('yarn update-exports', { stdio: 'inherit' });
// Step 4: Generate bin file
console.log(`\nπ§ Step 4/6: Generating bin/obsidian-inject.js...`);
generateBinFile();
// Step 5: Verify package is ready
console.log(`\nπ Step 5/6: Verifying package...`);
verifyPackage();
// Step 6: Publish to NPM
console.log(`\nπ€ Step 6/6: Publishing to NPM...`);
execSync('npm publish --registry https://registry.npmjs.org/', { stdio: 'inherit' });
console.log(`\nπ Complete workflow successful!`);
console.log(`\nπ Next steps:`);
console.log(` 1. npm install -g obsidian-plugin-config`);
console.log(` 2. Test injection: cd any-plugin && obsidian-inject`);
} catch (error) {
console.error(`\nβ Workflow failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
}
/**
* Verify package is ready for publication
*/
function verifyPackage(): void {
// Check required scripts
const requiredScripts = [
"scripts/inject-path.ts",
"scripts/inject-prompt.ts",
"scripts/utils.ts",
"scripts/esbuild.config.ts",
"scripts/acp.ts",
"scripts/update-version-config.ts",
"scripts/help.ts"
];
for (const script of requiredScripts) {
if (!fs.existsSync(script)) {
throw new Error(`Missing required script: ${script}`);
}
}
console.log(` β
All required scripts present`);
// Check package.json
const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
const requiredFields = ['name', 'version', 'description', 'bin', 'repository', 'author'];
for (const field of requiredFields) {
if (!packageJson[field]) {
throw new Error(`Missing required package.json field: ${field}`);
}
}
console.log(` β
Package.json valid (v${packageJson.version})`);
// Check bin file exists
if (!fs.existsSync("bin/obsidian-inject.js")) {
throw new Error(`Missing bin file: bin/obsidian-inject.js`);
}
console.log(` β
Bin file ready`);
// Sync versions.json
const versionsPath = "versions.json";
let versions: Record<string, string> = {};
if (fs.existsSync(versionsPath)) {
versions = JSON.parse(fs.readFileSync(versionsPath, "utf8"));
}
if (!versions[packageJson.version]) {
versions[packageJson.version] = "1.8.9";
fs.writeFileSync(versionsPath, JSON.stringify(versions, null, "\t"), "utf8");
console.log(` β
Added version ${packageJson.version} to versions.json`);
} else {
console.log(` β
Version ${packageJson.version} in versions.json`);
}
// Quick build test
execSync('yarn build', { stdio: 'pipe' });
console.log(` β
Build test passed`);
}
// Run the script
buildAndPublishNpm();