Refactor code structure for improved readability and maintainability

This commit is contained in:
Poyraz Avsever
2026-03-11 14:44:20 +03:00
parent bcbfebe5a3
commit c6d1252bb8
13 changed files with 1781 additions and 35 deletions
+2
View File
@@ -19,6 +19,8 @@
# production
/build
/dist
/release
# misc
.DS_Store
+45
View File
@@ -0,0 +1,45 @@
# Portfolio Data Panel (Electron)
Bu uygulama `data/`, `content/` ve `public/` klasorlerini yonetmek icin hazirlanmis Electron dashboard'dur.
## Scripts
```bash
pnpm run clean
pnpm run dev
pnpm run pack
pnpm run dist
pnpm run dist:win
pnpm run dist:portable
```
## Workspace Root Secimi
Panel varsayilan olarak monorepo kokunu kullanir (`../../`).
Farkli klasor ile calistirmak icin:
- Environment variable: `PORTFOLIO_WORKSPACE_ROOT`
- CLI arg: `--workspace-root=<path>`
PowerShell ornegi:
```powershell
$env:PORTFOLIO_WORKSPACE_ROOT = "D:\my-portfolio-repo"
pnpm run dev
```
Portable EXE ornegi:
```powershell
.\dist\portfolio-data-panel-0.1.0-x64-portable.exe --workspace-root="D:\my-portfolio-repo"
```
## Ozellestirme
Form ve tab yapisi:
- `renderer/configs.js`
Publish akisi:
- `main.cjs` icindeki `publishChanges` fonksiyonu.
+98 -9
View File
@@ -6,11 +6,82 @@ const path = require("node:path");
const vm = require("node:vm");
const matter = require("gray-matter");
const WORKSPACE_ROOT = path.resolve(__dirname, "../..");
const DATA_DIR = path.join(WORKSPACE_ROOT, "data");
const PUBLIC_DIR = path.join(WORKSPACE_ROOT, "public");
const BLOG_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "blog");
const PODCAST_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "podcasts");
function getCliArgValue(flag) {
const exact = process.argv.find((arg) => arg.startsWith(`${flag}=`));
if (exact) return exact.slice(flag.length + 1);
const index = process.argv.findIndex((arg) => arg === flag);
if (index >= 0 && process.argv[index + 1]) {
return process.argv[index + 1];
}
return "";
}
function resolveWorkspaceRoot() {
const fromArg = getCliArgValue("--workspace-root");
const fromEnv = process.env.PORTFOLIO_WORKSPACE_ROOT || "";
const selected = fromArg || fromEnv;
if (selected) {
return path.resolve(selected);
}
return path.resolve(__dirname, "../..");
}
let WORKSPACE_ROOT = resolveWorkspaceRoot();
let DATA_DIR = path.join(WORKSPACE_ROOT, "data");
let PUBLIC_DIR = path.join(WORKSPACE_ROOT, "public");
let BLOG_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "blog");
let PODCAST_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "podcasts");
function setWorkspaceRoot(nextRoot) {
WORKSPACE_ROOT = path.resolve(nextRoot);
DATA_DIR = path.join(WORKSPACE_ROOT, "data");
PUBLIC_DIR = path.join(WORKSPACE_ROOT, "public");
BLOG_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "blog");
PODCAST_CONTENT_DIR = path.join(WORKSPACE_ROOT, "content", "podcasts");
}
async function pathExists(target) {
try {
await fs.access(target);
return true;
} catch {
return false;
}
}
async function ensureWorkspaceStructure() {
const checks = [
{ label: "data", target: DATA_DIR },
{ label: "public", target: PUBLIC_DIR },
{ label: "content/blog", target: BLOG_CONTENT_DIR },
{ label: "content/podcasts", target: PODCAST_CONTENT_DIR },
];
const missing = [];
for (const check of checks) {
if (!(await pathExists(check.target))) {
missing.push(check.label);
}
}
if (!missing.length) return;
const details = [
`Workspace root: ${WORKSPACE_ROOT}`,
`Missing: ${missing.join(", ")}`,
"",
"Fix options:",
"1) Run panel from repository root.",
"2) Set PORTFOLIO_WORKSPACE_ROOT environment variable.",
"3) Launch app with --workspace-root=<path>.",
].join("\n");
throw new Error(details);
}
function createWindow() {
const win = new BrowserWindow({
@@ -685,11 +756,29 @@ ipcMain.handle("media:deleteFile", async (_, relativePath) => deleteMediaFile(re
ipcMain.handle("publish:status", async () => getPublishStatus());
ipcMain.handle("publish:run", async (_, message) => publishChanges(message));
app.whenReady().then(() => {
createWindow();
app.whenReady().then(async () => {
try {
setWorkspaceRoot(resolveWorkspaceRoot());
await ensureWorkspaceStructure();
createWindow();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
dialog.showErrorBox("Portfolio Data Panel", message);
app.quit();
return;
}
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
app.on("activate", async () => {
if (BrowserWindow.getAllWindows().length === 0) {
try {
await ensureWorkspaceStructure();
createWindow();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
dialog.showErrorBox("Portfolio Data Panel", message);
app.quit();
}
}
});
});
+47 -2
View File
@@ -2,11 +2,56 @@
"name": "@portfolio/data-panel",
"version": "0.1.0",
"private": true,
"description": "Electron dashboard for managing portfolio data/content and publishing updates.",
"author": "Poyraz Avsever",
"main": "main.cjs",
"scripts": {
"dev": "electron ."
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
"dev": "electron .",
"pack": "electron-builder --dir",
"dist": "pnpm run dist:win && pnpm run dist:portable",
"dist:win": "electron-builder --win nsis --config.artifactName=portfolio-data-panel-${version}-${arch}-setup.${ext}",
"dist:portable": "electron-builder --win portable --config.artifactName=portfolio-data-panel-${version}-${arch}-portable.${ext}"
},
"dependencies": {
"gray-matter": "^4.0.3",
"js-yaml": "^3.14.2",
"kind-of": "^6.0.3",
"section-matter": "^1.0.0",
"strip-bom-string": "^1.0.0"
},
"devDependencies": {
"electron": "^33.2.0"
"electron": "^33.2.0",
"electron-builder": "^24.13.3"
},
"build": {
"appId": "com.poyraz.portfolio.datapanel",
"productName": "Portfolio Data Panel",
"asar": true,
"directories": {
"output": "dist"
},
"files": [
"main.cjs",
"preload.cjs",
"renderer/**/*",
"package.json"
],
"win": {
"signAndEditExecutable": false,
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
]
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"perMachine": false
}
}
}