getaimeter 0.7.2 → 0.7.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/service.js +29 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getaimeter",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Track AI coding costs across Claude, Cursor, Codex, and Gemini. Optimization recommendations that cut costs by 30%.",
5
5
  "bin": {
6
6
  "aimeter": "cli.js"
package/service.js CHANGED
@@ -98,37 +98,44 @@ WshShell.Run """${nodePath}"" ""${script}"" watch", 0, False
98
98
  * These are proper Windows shortcuts with icon and description.
99
99
  */
100
100
  function createWindowsShortcuts(nodePath, script) {
101
- const iconPath = path.join(__dirname, 'icon.ico').replace(/\\/g, '\\\\');
101
+ const { execSync } = require('child_process');
102
+ const iconPath = path.join(__dirname, 'icon.ico');
103
+
102
104
  const locations = [
103
- { name: 'Desktop', dir: path.join(os.homedir(), 'Desktop') },
104
- { name: 'Start Menu', dir: path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs') },
105
+ path.join(os.homedir(), 'Desktop', 'AIMeter.lnk'),
106
+ path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'AIMeter.lnk'),
105
107
  ];
106
108
 
107
- for (const loc of locations) {
108
- const lnkPath = path.join(loc.dir, 'AIMeter.lnk');
109
- // PowerShell script to create a .lnk shortcut
110
- const ps = `
111
- $ws = New-Object -ComObject WScript.Shell
112
- $s = $ws.CreateShortcut('${lnkPath.replace(/'/g, "''")}')
113
- $s.TargetPath = '${nodePath.replace(/\\\\/g, '\\').replace(/'/g, "''")}'
114
- $s.Arguments = '"${script.replace(/\\\\/g, '\\').replace(/'/g, "''")}" start'
115
- $s.WorkingDirectory = '${os.homedir().replace(/'/g, "''")}'
116
- $s.Description = 'AIMeter - AI coding cost optimizer'
117
- $s.WindowStyle = 7
118
- $iconFile = '${iconPath.replace(/\\\\/g, '\\').replace(/'/g, "''")}'
119
- if (Test-Path $iconFile) { $s.IconLocation = $iconFile }
120
- $s.Save()
121
- `.trim();
109
+ // Write a temporary PS1 file to avoid all escaping issues
110
+ const ps1Path = path.join(os.tmpdir(), 'aimeter-shortcut.ps1');
111
+
112
+ for (const lnkPath of locations) {
113
+ // Use single quotes in PS1 with doubled single-quote escaping
114
+ const ps1Content = [
115
+ '$ws = New-Object -ComObject WScript.Shell',
116
+ `$s = $ws.CreateShortcut('${lnkPath.replace(/'/g, "''")}')`,
117
+ `$s.TargetPath = '${nodePath.replace(/\\\\/g, '\\').replace(/'/g, "''")}'`,
118
+ `$s.Arguments = [char]34 + '${script.replace(/\\\\/g, '\\').replace(/'/g, "''")}' + [char]34 + ' start'`,
119
+ `$s.WorkingDirectory = '${os.homedir().replace(/'/g, "''")}'`,
120
+ `$s.Description = 'AIMeter - AI coding cost optimizer'`,
121
+ `$s.WindowStyle = 7`,
122
+ `$icon = '${iconPath.replace(/'/g, "''")}'`,
123
+ `if (Test-Path $icon) { $s.IconLocation = $icon }`,
124
+ `$s.Save()`,
125
+ ].join('\n');
122
126
 
123
127
  try {
124
- require('child_process').execSync(
125
- `powershell -NoProfile -ExecutionPolicy Bypass -Command "${ps.replace(/"/g, '\\"')}"`,
126
- { stdio: 'ignore', timeout: 10000 }
127
- );
128
+ fs.writeFileSync(ps1Path, ps1Content, 'utf8');
129
+ execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${ps1Path}"`, {
130
+ stdio: 'ignore',
131
+ timeout: 10000,
132
+ });
128
133
  } catch {
129
134
  // Non-critical — shortcuts are convenience, not required
130
135
  }
131
136
  }
137
+
138
+ try { fs.unlinkSync(ps1Path); } catch {}
132
139
  }
133
140
 
134
141
  function uninstallWindows() {