monapdx_obsidian-skeletal/scripts/deploy-local.mjs
Ashly e1f533342d Add local deploy script, docs, and UI tweaks
Add local deployment workflow and docs: .env.local.example, scripts/deploy-local.mjs, deploy:local npm script, screenshots, and CHANGELOG.md. Update README with deployment, screenshots, usage, and development instructions. Update .gitignore to exclude local env, logs, and build outputs. Polish UI and layout: refactor TemplateBrowserModal structure and update styles.css for responsive modal/pane scrolling. Small metadata changes: manifest/package.json author/description and LICENSE copyright.
2026-07-17 02:18:18 -07:00

99 lines
2.8 KiB
JavaScript

import { spawnSync } from "node:child_process";
import { copyFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
import { dirname, isAbsolute, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const envPath = join(rootDir, ".env.local");
const pluginFiles = ["main.js", "manifest.json", "styles.css"];
function fail(message) {
console.error(`deploy:local failed: ${message}`);
process.exit(1);
}
function loadEnvLocal(path) {
if (!existsSync(path)) {
fail(
`Missing .env.local. Copy .env.local.example to .env.local and set OBSIDIAN_VAULT_PATH to your vault root.`
);
}
const values = {};
const text = readFileSync(path, "utf8");
for (const rawLine of text.split(/\r?\n/)) {
const line = rawLine.trim();
if (!line || line.startsWith("#")) {
continue;
}
const eq = line.indexOf("=");
if (eq <= 0) {
continue;
}
const key = line.slice(0, eq).trim();
let value = line.slice(eq + 1).trim();
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.slice(1, -1);
}
values[key] = value;
}
return values;
}
function resolveVaultPath(raw) {
if (!raw || !raw.trim()) {
fail("OBSIDIAN_VAULT_PATH is empty in .env.local.");
}
const trimmed = raw.trim();
if (trimmed.includes("[") || /PASTE|YOUR VAULT|example/i.test(trimmed)) {
fail(
"OBSIDIAN_VAULT_PATH still looks like a placeholder. Set it to your real vault folder path."
);
}
const vaultPath = isAbsolute(trimmed) ? trimmed : resolve(rootDir, trimmed);
if (!existsSync(vaultPath)) {
fail(`Vault path does not exist: ${vaultPath}`);
}
return vaultPath;
}
function runBuild() {
console.log("Building plugin…");
const result = spawnSync("npm", ["run", "build"], {
cwd: rootDir,
stdio: "inherit",
shell: true,
});
if (result.error) {
fail(result.error.message);
}
if (result.status !== 0) {
fail(`Production build exited with code ${result.status ?? "unknown"}.`);
}
}
function deploy(vaultPath) {
const destDir = join(vaultPath, ".obsidian", "plugins", "skeletal");
mkdirSync(destDir, { recursive: true });
for (const file of pluginFiles) {
const source = join(rootDir, file);
if (!existsSync(source)) {
fail(`Expected build output missing: ${file}`);
}
const dest = join(destDir, file);
copyFileSync(source, dest);
console.log(`Copied ${file}${dest}`);
}
console.log(`Deployed Skeletal to ${destDir}`);
console.log("Reload the plugin in Obsidian (or restart Obsidian) to pick up changes.");
}
const env = loadEnvLocal(envPath);
const vaultPath = resolveVaultPath(env.OBSIDIAN_VAULT_PATH ?? "");
runBuild();
deploy(vaultPath);