idea-manager 0.9.1 → 0.9.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idea-manager",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "AI 기반 브레인스토밍 → 구조화 → 프롬프트 생성 도구. MCP Server 내장.",
5
5
  "keywords": [
6
6
  "brainstorm",
package/src/cli.ts CHANGED
@@ -11,9 +11,54 @@ import { spawn } from 'child_process';
11
11
  import path from 'path';
12
12
  import { fileURLToPath } from 'url';
13
13
 
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = path.dirname(__filename);
16
- const PKG_ROOT = path.resolve(__dirname, '..');
14
+ // Resolve PKG_ROOT robustly across macOS/Windows and tsx/cjs context
15
+ let PKG_ROOT: string;
16
+ try {
17
+ const thisFile = fileURLToPath(import.meta.url);
18
+ PKG_ROOT = path.resolve(path.dirname(thisFile), '..');
19
+ } catch {
20
+ // Fallback for CJS context (tsx/cjs on some Windows setups)
21
+ PKG_ROOT = path.resolve(__dirname, '..');
22
+ }
23
+
24
+ async function openAsApp(url: string) {
25
+ const { exec: execCb } = await import('child_process');
26
+ const platform = process.platform;
27
+
28
+ // Shell commands for --app mode per platform
29
+ const commands: string[] =
30
+ platform === 'darwin'
31
+ ? [
32
+ `open -a "Google Chrome" --args --app=${url}`,
33
+ `open -a "Microsoft Edge" --args --app=${url}`,
34
+ `open -a "Chromium" --args --app=${url}`,
35
+ ]
36
+ : platform === 'win32'
37
+ ? [
38
+ `start "" "chrome" "--app=${url}"`,
39
+ `start "" "msedge" "--app=${url}"`,
40
+ ]
41
+ : [
42
+ `google-chrome --app=${url}`,
43
+ `chromium-browser --app=${url}`,
44
+ `microsoft-edge --app=${url}`,
45
+ ];
46
+
47
+ for (const cmd of commands) {
48
+ try {
49
+ await new Promise<void>((resolve, reject) => {
50
+ execCb(cmd, (err) => { if (err) reject(err); else resolve(); });
51
+ });
52
+ return; // success
53
+ } catch {
54
+ continue; // try next browser
55
+ }
56
+ }
57
+
58
+ // Fallback: open normally
59
+ const open = (await import('open')).default;
60
+ await open(url);
61
+ }
17
62
 
18
63
  const program = new Command();
19
64
 
@@ -87,8 +132,7 @@ program
87
132
 
88
133
  setTimeout(async () => {
89
134
  try {
90
- const open = (await import('open')).default;
91
- await open(`http://localhost:${port}`);
135
+ await openAsApp(`http://localhost:${port}`);
92
136
  } catch { /* ignore */ }
93
137
  }, 3000);
94
138
 
@@ -4,10 +4,12 @@ import path from 'path';
4
4
 
5
5
  function quoteArg(arg: string): string {
6
6
  // Quote args with spaces for shell mode
7
- if (arg.includes(' ') || arg.includes('"')) {
8
- return `"${arg.replace(/"/g, '\\"')}"`;
7
+ if (!arg.includes(' ') && !arg.includes('"')) return arg;
8
+ if (process.platform === 'win32') {
9
+ // cmd.exe uses "" to escape quotes
10
+ return `"${arg.replace(/"/g, '""')}"`;
9
11
  }
10
- return arg;
12
+ return `"${arg.replace(/"/g, '\\"')}"`;
11
13
  }
12
14
 
13
15
  function exec(cmd: string, args: string[], cwd?: string): Promise<string> {
@@ -78,21 +78,31 @@ export async function syncInit() {
78
78
  }
79
79
  }
80
80
 
81
- // Clean sync dir and clone
81
+ // Clone into a temp dir, then move contents to sync dir
82
82
  console.log(`\n Cloning to ${syncDir}...`);
83
+ const tmpCloneDir = syncDir + '-tmp-' + Date.now();
84
+ let cloned = false;
85
+
83
86
  try {
84
- // Remove sync dir contents (keep the dir itself)
85
- const entries = fs.readdirSync(syncDir);
86
- for (const e of entries) {
87
+ await git.gitClone(repoUrl, tmpCloneDir);
88
+ // Move contents from tmp to sync dir
89
+ const entries = fs.readdirSync(tmpCloneDir, { withFileTypes: true });
90
+ // Clean sync dir first
91
+ for (const e of fs.readdirSync(syncDir)) {
87
92
  fs.rmSync(path.join(syncDir, e), { recursive: true, force: true });
88
93
  }
89
-
90
- await git.gitClone(repoUrl, syncDir);
94
+ for (const e of entries) {
95
+ fs.renameSync(path.join(tmpCloneDir, e.name), path.join(syncDir, e.name));
96
+ }
97
+ fs.rmSync(tmpCloneDir, { recursive: true, force: true });
98
+ cloned = true;
91
99
  } catch {
92
- // Clone into existing empty dir — init + add remote instead
100
+ // Clone failed — init locally + add remote
101
+ fs.rmSync(tmpCloneDir, { recursive: true, force: true });
93
102
  try {
94
103
  await git.gitInit(syncDir);
95
104
  await git.gitAddRemote(syncDir, repoUrl);
105
+ cloned = true;
96
106
  } catch (err2) {
97
107
  console.error(` Failed: ${(err2 as Error).message}\n`);
98
108
  process.exit(1);