@epic-web/workshop-utils 6.47.0 → 6.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16,6 +16,7 @@ export type Workshop = {
|
|
|
16
16
|
export type WorkshopsConfig = z.infer<typeof ConfigSchema>;
|
|
17
17
|
export declare function loadConfig(): Promise<WorkshopsConfig>;
|
|
18
18
|
export declare function saveConfig(config: WorkshopsConfig): Promise<void>;
|
|
19
|
+
export declare function deleteConfig(): Promise<void>;
|
|
19
20
|
export declare function getReposDirectory(): Promise<string>;
|
|
20
21
|
export declare function isReposDirectoryConfigured(): Promise<boolean>;
|
|
21
22
|
export declare function getDefaultReposDir(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workshops.server.d.ts","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,YAAY;;;;;;EAEhB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA2B1D,wBAAsB,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC,CAS3D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4CzD;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQ/B;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,iBAAiB,CACtC,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAI/B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CA6HD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE"}
|
|
1
|
+
{"version":3,"file":"workshops.server.d.ts","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,YAAY;;;;;;EAEhB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA2B1D,wBAAsB,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC,CAS3D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAOlD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4CzD;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQ/B;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,iBAAiB,CACtC,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAI/B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CA6HD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE"}
|
|
@@ -61,6 +61,15 @@ export async function saveConfig(config) {
|
|
|
61
61
|
const configPath = resolveConfigPath();
|
|
62
62
|
await atomicWriteJSON(configPath, config);
|
|
63
63
|
}
|
|
64
|
+
export async function deleteConfig() {
|
|
65
|
+
const configPath = resolveConfigPath();
|
|
66
|
+
try {
|
|
67
|
+
await fs.unlink(configPath);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// File doesn't exist, which is fine
|
|
71
|
+
}
|
|
72
|
+
}
|
|
64
73
|
export async function getReposDirectory() {
|
|
65
74
|
const config = await loadConfig();
|
|
66
75
|
return config.reposDirectory || getDefaultReposDirectory();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workshops.server.js","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { z } from 'zod'\nimport { resolvePrimaryDir } from './data-storage.server.js'\n\nconst CONFIG_FILE = 'workshops-config.json'\n\n// Schema for the epicshop property in package.json\nconst EpicshopConfigSchema = z.object({\n\ttitle: z.string(),\n\tsubtitle: z.string().optional(),\n\tproduct: z\n\t\t.object({\n\t\t\thost: z.string().optional(),\n\t\t\tslug: z.string().optional(),\n\t\t\tlogo: z.string().optional(),\n\t\t\tdisplayName: z.string().optional(),\n\t\t\tdisplayNameShort: z.string().optional(),\n\t\t})\n\t\t.optional(),\n})\n\n// Schema for workshop configuration (stored settings only)\nconst ConfigSchema = z.object({\n\treposDirectory: z.string().optional(),\n})\n\nexport type Workshop = {\n\tname: string\n\ttitle: string\n\tsubtitle?: string\n\trepoName: string\n\tpath: string\n}\n\nexport type WorkshopsConfig = z.infer<typeof ConfigSchema>\n\nfunction getDefaultReposDirectory(): string {\n\treturn path.join(os.homedir(), 'epic-workshops')\n}\n\nfunction resolveConfigPath(): string {\n\treturn path.join(resolvePrimaryDir(), CONFIG_FILE)\n}\n\nasync function ensureDir(dir: string) {\n\ttry {\n\t\tawait fs.mkdir(dir, { recursive: true, mode: 0o700 })\n\t} catch {}\n\ttry {\n\t\tawait fs.chmod(dir, 0o700)\n\t} catch {}\n}\n\nasync function atomicWriteJSON(filePath: string, data: unknown) {\n\tconst dir = path.dirname(filePath)\n\tawait ensureDir(dir)\n\tconst tmp = path.join(dir, `.tmp-${randomUUID()}`)\n\tawait fs.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 0o600 })\n\tawait fs.rename(tmp, filePath)\n}\n\nexport async function loadConfig(): Promise<WorkshopsConfig> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tconst txt = await fs.readFile(configPath, 'utf8')\n\t\tconst data = JSON.parse(txt)\n\t\treturn ConfigSchema.parse(data)\n\t} catch {\n\t\treturn {}\n\t}\n}\n\nexport async function saveConfig(config: WorkshopsConfig): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\tawait atomicWriteJSON(configPath, config)\n}\n\nexport async function getReposDirectory(): Promise<string> {\n\tconst config = await loadConfig()\n\treturn config.reposDirectory || getDefaultReposDirectory()\n}\n\nexport async function isReposDirectoryConfigured(): Promise<boolean> {\n\tconst config = await loadConfig()\n\treturn Boolean(config.reposDirectory)\n}\n\nexport function getDefaultReposDir(): string {\n\treturn getDefaultReposDirectory()\n}\n\nexport async function setReposDirectory(directory: string): Promise<void> {\n\tconst config = await loadConfig()\n\tconfig.reposDirectory = path.resolve(directory)\n\tawait saveConfig(config)\n}\n\n/**\n * Scan a directory for workshops (directories with package.json containing \"epicshop\" property)\n */\nexport async function listWorkshops(): Promise<Workshop[]> {\n\tconst reposDir = await getReposDirectory()\n\n\t// Check if directory exists\n\ttry {\n\t\tawait fs.access(reposDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\tconst entries = await fs.readdir(reposDir, { withFileTypes: true })\n\tconst workshops: Workshop[] = []\n\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue\n\n\t\tconst workshopPath = path.join(reposDir, entry.name)\n\t\tconst pkgPath = path.join(workshopPath, 'package.json')\n\n\t\ttry {\n\t\t\tconst pkgContent = await fs.readFile(pkgPath, 'utf8')\n\t\t\tconst pkg = JSON.parse(pkgContent) as {\n\t\t\t\tname?: string\n\t\t\t\tepicshop?: unknown\n\t\t\t}\n\n\t\t\tif (pkg.epicshop) {\n\t\t\t\tconst epicshopConfig = EpicshopConfigSchema.safeParse(pkg.epicshop)\n\t\t\t\tif (epicshopConfig.success) {\n\t\t\t\t\tworkshops.push({\n\t\t\t\t\t\tname: pkg.name || entry.name,\n\t\t\t\t\t\ttitle: epicshopConfig.data.title,\n\t\t\t\t\t\tsubtitle: epicshopConfig.data.subtitle,\n\t\t\t\t\t\trepoName: entry.name,\n\t\t\t\t\t\tpath: workshopPath,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not a valid workshop directory, skip\n\t\t}\n\t}\n\n\treturn workshops\n}\n\nexport async function getWorkshop(\n\tidOrName: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.find(\n\t\t(w) =>\n\t\t\tw.name.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.repoName.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.title.toLowerCase() === idOrName.toLowerCase(),\n\t)\n}\n\nexport async function workshopExists(repoName: string): Promise<boolean> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.some(\n\t\t(w) => w.repoName.toLowerCase() === repoName.toLowerCase(),\n\t)\n}\n\nexport async function getWorkshopByPath(\n\tworkshopPath: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\tconst resolvedPath = path.resolve(workshopPath)\n\treturn workshops.find((w) => path.resolve(w.path) === resolvedPath)\n}\n\n/**\n * Check for unpushed changes in a git repository\n * Returns info about unpushed commits across all branches\n */\nexport async function getUnpushedChanges(repoPath: string): Promise<{\n\thasUnpushed: boolean\n\tbranches: Array<{ name: string; unpushedCount: number }>\n\tuncommittedChanges: boolean\n\tsummary: string[]\n}> {\n\tconst { execSync } = await import('node:child_process')\n\n\tconst result = {\n\t\thasUnpushed: false,\n\t\tbranches: [] as Array<{ name: string; unpushedCount: number }>,\n\t\tuncommittedChanges: false,\n\t\tsummary: [] as string[],\n\t}\n\n\ttry {\n\t\t// Check if it's a git repository\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: repoPath,\n\t\t\tstdio: 'pipe',\n\t\t})\n\t} catch {\n\t\t// Not a git repository\n\t\treturn result\n\t}\n\n\ttry {\n\t\t// Check for uncommitted changes\n\t\tconst status = execSync('git status --porcelain', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tif (status) {\n\t\t\tresult.uncommittedChanges = true\n\t\t\tresult.hasUnpushed = true\n\t\t\tconst lines = status.split('\\n')\n\t\t\tconst modified = lines.filter(\n\t\t\t\t(l) => l.startsWith(' M') || l.startsWith('M '),\n\t\t\t).length\n\t\t\tconst added = lines.filter(\n\t\t\t\t(l) => l.startsWith('A ') || l.startsWith('??'),\n\t\t\t).length\n\t\t\tconst deleted = lines.filter(\n\t\t\t\t(l) => l.startsWith(' D') || l.startsWith('D '),\n\t\t\t).length\n\n\t\t\tconst parts = []\n\t\t\tif (modified > 0) parts.push(`${modified} modified`)\n\t\t\tif (added > 0) parts.push(`${added} untracked/added`)\n\t\t\tif (deleted > 0) parts.push(`${deleted} deleted`)\n\t\t\tif (parts.length > 0) {\n\t\t\t\tresult.summary.push(`Uncommitted changes: ${parts.join(', ')}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get all local branches\n\t\tconst branchOutput = execSync('git branch', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tconst branches = branchOutput\n\t\t\t.split('\\n')\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, '').trim())\n\t\t\t.filter(Boolean)\n\n\t\tfor (const branch of branches) {\n\t\t\ttry {\n\t\t\t\t// Check if branch has an upstream\n\t\t\t\tconst upstream = execSync(\n\t\t\t\t\t`git rev-parse --abbrev-ref ${branch}@{upstream}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\t// Count unpushed commits\n\t\t\t\tconst unpushedOutput = execSync(\n\t\t\t\t\t`git rev-list --count ${upstream}..${branch}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\tconst unpushedCount = parseInt(unpushedOutput, 10)\n\t\t\t\tif (unpushedCount > 0) {\n\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount })\n\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t`Branch \"${branch}\": ${unpushedCount} unpushed commit${unpushedCount > 1 ? 's' : ''}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Branch has no upstream, check if it has any commits not in any remote\n\t\t\t\ttry {\n\t\t\t\t\tconst allRemotes = execSync('git remote', {\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}).trim()\n\n\t\t\t\t\tif (allRemotes) {\n\t\t\t\t\t\t// Branch exists but has no upstream tracking\n\t\t\t\t\t\tconst commitCount = execSync(`git rev-list --count ${branch}`, {\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t}).trim()\n\n\t\t\t\t\t\tconst count = parseInt(commitCount, 10)\n\t\t\t\t\t\tif (count > 0) {\n\t\t\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount: count })\n\t\t\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t\t\t`Branch \"${branch}\": ${count} local commit${count > 1 ? 's' : ''} (no upstream)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors for individual branches\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Error checking git status, assume no unpushed changes\n\t}\n\n\treturn result\n}\n\n/**\n * Delete a workshop directory\n */\nexport async function deleteWorkshop(workshopPath: string): Promise<void> {\n\tawait fs.rm(workshopPath, { recursive: true, force: true })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workshops.server.js","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,MAAM,WAAW,GAAG,uBAAuB,CAAA;AAE3C,mDAAmD;AACnD,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACvC,CAAC;SACD,QAAQ,EAAE;CACZ,CAAC,CAAA;AAEF,2DAA2D;AAC3D,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAYF,SAAS,wBAAwB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAA;AACjD,CAAC;AAED,SAAS,iBAAiB;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,WAAW,CAAC,CAAA;AACnD,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACJ,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACtD,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,CAAC;QACJ,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACX,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAa;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAA;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,UAAU,EAAE,EAAE,CAAC,CAAA;IAClD,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACvE,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC/B,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAA;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5B,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAA;IACV,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAuB;IACvD,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAA;IACtC,MAAM,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IACjC,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAA;IACtC,IAAI,CAAC;QACJ,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACR,oCAAoC;IACrC,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACtC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,OAAO,MAAM,CAAC,cAAc,IAAI,wBAAwB,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB;IACjC,OAAO,wBAAwB,EAAE,CAAA;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACxD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC/C,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IAClC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,EAAE,CAAA;IAE1C,4BAA4B;IAC5B,IAAI,CAAC;QACJ,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAA;IACV,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IACnE,MAAM,SAAS,GAAe,EAAE,CAAA;IAEhC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAQ;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;QAEvD,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAGhC,CAAA;YAED,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;gBACnE,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;oBAC5B,SAAS,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI;wBAC5B,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK;wBAChC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ;wBACtC,QAAQ,EAAE,KAAK,CAAC,IAAI;wBACpB,IAAI,EAAE,YAAY;qBAClB,CAAC,CAAA;gBACH,CAAC;YACF,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,uCAAuC;QACxC,CAAC;IACF,CAAC;IAED,OAAO,SAAS,CAAA;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,QAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAA;IACvC,OAAO,SAAS,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,EAAE,CACL,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE;QAC/C,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE;QACnD,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,CACjD,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACpD,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAA;IACvC,OAAO,SAAS,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,CAC1D,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,YAAoB;IAEpB,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAA;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;IAC/C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,YAAY,CAAC,CAAA;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IAMxD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAEvD,MAAM,MAAM,GAAG;QACd,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,EAAoD;QAC9D,kBAAkB,EAAE,KAAK;QACzB,OAAO,EAAE,EAAc;KACvB,CAAA;IAED,IAAI,CAAC;QACJ,iCAAiC;QACjC,QAAQ,CAAC,yBAAyB,EAAE;YACnC,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,MAAM;SACb,CAAC,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACR,uBAAuB;QACvB,OAAO,MAAM,CAAA;IACd,CAAC;IAED,IAAI,CAAC;QACJ,gCAAgC;QAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,wBAAwB,EAAE;YACjD,GAAG,EAAE,QAAQ;YACb,QAAQ,EAAE,MAAM;SAChB,CAAC,CAAC,IAAI,EAAE,CAAA;QAET,IAAI,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAA;YAChC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;YACzB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAC/C,CAAC,MAAM,CAAA;YACR,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAC/C,CAAC,MAAM,CAAA;YACR,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAC3B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAC/C,CAAC,MAAM,CAAA;YAER,MAAM,KAAK,GAAG,EAAE,CAAA;YAChB,IAAI,QAAQ,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,WAAW,CAAC,CAAA;YACpD,IAAI,KAAK,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,kBAAkB,CAAC,CAAA;YACrD,IAAI,OAAO,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,UAAU,CAAC,CAAA;YACjD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAChE,CAAC;QACF,CAAC;QAED,yBAAyB;QACzB,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,EAAE;YAC3C,GAAG,EAAE,QAAQ;YACb,QAAQ,EAAE,MAAM;SAChB,CAAC,CAAC,IAAI,EAAE,CAAA;QAET,MAAM,QAAQ,GAAG,YAAY;aAC3B,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;aAC3C,MAAM,CAAC,OAAO,CAAC,CAAA;QAEjB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACJ,kCAAkC;gBAClC,MAAM,QAAQ,GAAG,QAAQ,CACxB,8BAA8B,MAAM,aAAa,EACjD;oBACC,GAAG,EAAE,QAAQ;oBACb,QAAQ,EAAE,MAAM;oBAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;iBAC/B,CACD,CAAC,IAAI,EAAE,CAAA;gBAER,yBAAyB;gBACzB,MAAM,cAAc,GAAG,QAAQ,CAC9B,wBAAwB,QAAQ,KAAK,MAAM,EAAE,EAC7C;oBACC,GAAG,EAAE,QAAQ;oBACb,QAAQ,EAAE,MAAM;iBAChB,CACD,CAAC,IAAI,EAAE,CAAA;gBAER,MAAM,aAAa,GAAG,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAA;gBAClD,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;oBACvB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;oBACzB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAA;oBACrD,MAAM,CAAC,OAAO,CAAC,IAAI,CAClB,WAAW,MAAM,MAAM,aAAa,mBAAmB,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrF,CAAA;gBACF,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;gBACR,wEAAwE;gBACxE,IAAI,CAAC;oBACJ,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,EAAE;wBACzC,GAAG,EAAE,QAAQ;wBACb,QAAQ,EAAE,MAAM;qBAChB,CAAC,CAAC,IAAI,EAAE,CAAA;oBAET,IAAI,UAAU,EAAE,CAAC;wBAChB,6CAA6C;wBAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,wBAAwB,MAAM,EAAE,EAAE;4BAC9D,GAAG,EAAE,QAAQ;4BACb,QAAQ,EAAE,MAAM;yBAChB,CAAC,CAAC,IAAI,EAAE,CAAA;wBAET,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;wBACvC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;4BACf,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;4BACzB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAA;4BAC5D,MAAM,CAAC,OAAO,CAAC,IAAI,CAClB,WAAW,MAAM,MAAM,KAAK,gBAAgB,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAChF,CAAA;wBACF,CAAC;oBACF,CAAC;gBACF,CAAC;gBAAC,MAAM,CAAC;oBACR,wCAAwC;gBACzC,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,wDAAwD;IACzD,CAAC;IAED,OAAO,MAAM,CAAA;AACd,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,YAAoB;IACxD,MAAM,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC5D,CAAC","sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { z } from 'zod'\nimport { resolvePrimaryDir } from './data-storage.server.js'\n\nconst CONFIG_FILE = 'workshops-config.json'\n\n// Schema for the epicshop property in package.json\nconst EpicshopConfigSchema = z.object({\n\ttitle: z.string(),\n\tsubtitle: z.string().optional(),\n\tproduct: z\n\t\t.object({\n\t\t\thost: z.string().optional(),\n\t\t\tslug: z.string().optional(),\n\t\t\tlogo: z.string().optional(),\n\t\t\tdisplayName: z.string().optional(),\n\t\t\tdisplayNameShort: z.string().optional(),\n\t\t})\n\t\t.optional(),\n})\n\n// Schema for workshop configuration (stored settings only)\nconst ConfigSchema = z.object({\n\treposDirectory: z.string().optional(),\n})\n\nexport type Workshop = {\n\tname: string\n\ttitle: string\n\tsubtitle?: string\n\trepoName: string\n\tpath: string\n}\n\nexport type WorkshopsConfig = z.infer<typeof ConfigSchema>\n\nfunction getDefaultReposDirectory(): string {\n\treturn path.join(os.homedir(), 'epic-workshops')\n}\n\nfunction resolveConfigPath(): string {\n\treturn path.join(resolvePrimaryDir(), CONFIG_FILE)\n}\n\nasync function ensureDir(dir: string) {\n\ttry {\n\t\tawait fs.mkdir(dir, { recursive: true, mode: 0o700 })\n\t} catch {}\n\ttry {\n\t\tawait fs.chmod(dir, 0o700)\n\t} catch {}\n}\n\nasync function atomicWriteJSON(filePath: string, data: unknown) {\n\tconst dir = path.dirname(filePath)\n\tawait ensureDir(dir)\n\tconst tmp = path.join(dir, `.tmp-${randomUUID()}`)\n\tawait fs.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 0o600 })\n\tawait fs.rename(tmp, filePath)\n}\n\nexport async function loadConfig(): Promise<WorkshopsConfig> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tconst txt = await fs.readFile(configPath, 'utf8')\n\t\tconst data = JSON.parse(txt)\n\t\treturn ConfigSchema.parse(data)\n\t} catch {\n\t\treturn {}\n\t}\n}\n\nexport async function saveConfig(config: WorkshopsConfig): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\tawait atomicWriteJSON(configPath, config)\n}\n\nexport async function deleteConfig(): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tawait fs.unlink(configPath)\n\t} catch {\n\t\t// File doesn't exist, which is fine\n\t}\n}\n\nexport async function getReposDirectory(): Promise<string> {\n\tconst config = await loadConfig()\n\treturn config.reposDirectory || getDefaultReposDirectory()\n}\n\nexport async function isReposDirectoryConfigured(): Promise<boolean> {\n\tconst config = await loadConfig()\n\treturn Boolean(config.reposDirectory)\n}\n\nexport function getDefaultReposDir(): string {\n\treturn getDefaultReposDirectory()\n}\n\nexport async function setReposDirectory(directory: string): Promise<void> {\n\tconst config = await loadConfig()\n\tconfig.reposDirectory = path.resolve(directory)\n\tawait saveConfig(config)\n}\n\n/**\n * Scan a directory for workshops (directories with package.json containing \"epicshop\" property)\n */\nexport async function listWorkshops(): Promise<Workshop[]> {\n\tconst reposDir = await getReposDirectory()\n\n\t// Check if directory exists\n\ttry {\n\t\tawait fs.access(reposDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\tconst entries = await fs.readdir(reposDir, { withFileTypes: true })\n\tconst workshops: Workshop[] = []\n\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue\n\n\t\tconst workshopPath = path.join(reposDir, entry.name)\n\t\tconst pkgPath = path.join(workshopPath, 'package.json')\n\n\t\ttry {\n\t\t\tconst pkgContent = await fs.readFile(pkgPath, 'utf8')\n\t\t\tconst pkg = JSON.parse(pkgContent) as {\n\t\t\t\tname?: string\n\t\t\t\tepicshop?: unknown\n\t\t\t}\n\n\t\t\tif (pkg.epicshop) {\n\t\t\t\tconst epicshopConfig = EpicshopConfigSchema.safeParse(pkg.epicshop)\n\t\t\t\tif (epicshopConfig.success) {\n\t\t\t\t\tworkshops.push({\n\t\t\t\t\t\tname: pkg.name || entry.name,\n\t\t\t\t\t\ttitle: epicshopConfig.data.title,\n\t\t\t\t\t\tsubtitle: epicshopConfig.data.subtitle,\n\t\t\t\t\t\trepoName: entry.name,\n\t\t\t\t\t\tpath: workshopPath,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not a valid workshop directory, skip\n\t\t}\n\t}\n\n\treturn workshops\n}\n\nexport async function getWorkshop(\n\tidOrName: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.find(\n\t\t(w) =>\n\t\t\tw.name.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.repoName.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.title.toLowerCase() === idOrName.toLowerCase(),\n\t)\n}\n\nexport async function workshopExists(repoName: string): Promise<boolean> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.some(\n\t\t(w) => w.repoName.toLowerCase() === repoName.toLowerCase(),\n\t)\n}\n\nexport async function getWorkshopByPath(\n\tworkshopPath: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\tconst resolvedPath = path.resolve(workshopPath)\n\treturn workshops.find((w) => path.resolve(w.path) === resolvedPath)\n}\n\n/**\n * Check for unpushed changes in a git repository\n * Returns info about unpushed commits across all branches\n */\nexport async function getUnpushedChanges(repoPath: string): Promise<{\n\thasUnpushed: boolean\n\tbranches: Array<{ name: string; unpushedCount: number }>\n\tuncommittedChanges: boolean\n\tsummary: string[]\n}> {\n\tconst { execSync } = await import('node:child_process')\n\n\tconst result = {\n\t\thasUnpushed: false,\n\t\tbranches: [] as Array<{ name: string; unpushedCount: number }>,\n\t\tuncommittedChanges: false,\n\t\tsummary: [] as string[],\n\t}\n\n\ttry {\n\t\t// Check if it's a git repository\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: repoPath,\n\t\t\tstdio: 'pipe',\n\t\t})\n\t} catch {\n\t\t// Not a git repository\n\t\treturn result\n\t}\n\n\ttry {\n\t\t// Check for uncommitted changes\n\t\tconst status = execSync('git status --porcelain', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tif (status) {\n\t\t\tresult.uncommittedChanges = true\n\t\t\tresult.hasUnpushed = true\n\t\t\tconst lines = status.split('\\n')\n\t\t\tconst modified = lines.filter(\n\t\t\t\t(l) => l.startsWith(' M') || l.startsWith('M '),\n\t\t\t).length\n\t\t\tconst added = lines.filter(\n\t\t\t\t(l) => l.startsWith('A ') || l.startsWith('??'),\n\t\t\t).length\n\t\t\tconst deleted = lines.filter(\n\t\t\t\t(l) => l.startsWith(' D') || l.startsWith('D '),\n\t\t\t).length\n\n\t\t\tconst parts = []\n\t\t\tif (modified > 0) parts.push(`${modified} modified`)\n\t\t\tif (added > 0) parts.push(`${added} untracked/added`)\n\t\t\tif (deleted > 0) parts.push(`${deleted} deleted`)\n\t\t\tif (parts.length > 0) {\n\t\t\t\tresult.summary.push(`Uncommitted changes: ${parts.join(', ')}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get all local branches\n\t\tconst branchOutput = execSync('git branch', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tconst branches = branchOutput\n\t\t\t.split('\\n')\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, '').trim())\n\t\t\t.filter(Boolean)\n\n\t\tfor (const branch of branches) {\n\t\t\ttry {\n\t\t\t\t// Check if branch has an upstream\n\t\t\t\tconst upstream = execSync(\n\t\t\t\t\t`git rev-parse --abbrev-ref ${branch}@{upstream}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\t// Count unpushed commits\n\t\t\t\tconst unpushedOutput = execSync(\n\t\t\t\t\t`git rev-list --count ${upstream}..${branch}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\tconst unpushedCount = parseInt(unpushedOutput, 10)\n\t\t\t\tif (unpushedCount > 0) {\n\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount })\n\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t`Branch \"${branch}\": ${unpushedCount} unpushed commit${unpushedCount > 1 ? 's' : ''}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Branch has no upstream, check if it has any commits not in any remote\n\t\t\t\ttry {\n\t\t\t\t\tconst allRemotes = execSync('git remote', {\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}).trim()\n\n\t\t\t\t\tif (allRemotes) {\n\t\t\t\t\t\t// Branch exists but has no upstream tracking\n\t\t\t\t\t\tconst commitCount = execSync(`git rev-list --count ${branch}`, {\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t}).trim()\n\n\t\t\t\t\t\tconst count = parseInt(commitCount, 10)\n\t\t\t\t\t\tif (count > 0) {\n\t\t\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount: count })\n\t\t\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t\t\t`Branch \"${branch}\": ${count} local commit${count > 1 ? 's' : ''} (no upstream)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors for individual branches\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Error checking git status, assume no unpushed changes\n\t}\n\n\treturn result\n}\n\n/**\n * Delete a workshop directory\n */\nexport async function deleteWorkshop(workshopPath: string): Promise<void> {\n\tawait fs.rm(workshopPath, { recursive: true, force: true })\n}\n"]}
|