@vrdmr/fnx-test 0.4.1 → 0.4.2

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.
@@ -60,14 +60,18 @@ async function isAzuriteRunning() {
60
60
  * Returns the path/command or null.
61
61
  */
62
62
  function findAzurite() {
63
- // 1. Check the fnx tools cache first
64
- const cachedBin = join(AZURITE_INSTALL_DIR, 'node_modules', '.bin', 'azurite');
63
+ // 1. Check the fnx tools cache first (Windows uses .cmd shims)
64
+ const isWin = process.platform === 'win32';
65
+ const cachedBin = join(AZURITE_INSTALL_DIR, 'node_modules', '.bin', isWin ? 'azurite.cmd' : 'azurite');
65
66
  if (existsSync(cachedBin)) return cachedBin;
66
67
 
67
- // 2. Check global PATH
68
+ // 2. Check global PATH (use 'where' on Windows, 'which' on Unix)
68
69
  try {
69
- const which = execSync('which azurite', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
70
- if (which) return which;
70
+ const whichCmd = isWin ? 'where azurite' : 'which azurite';
71
+ const result = execSync(whichCmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
72
+ // 'where' on Windows may return multiple lines; take the first
73
+ const firstLine = result.split(/\r?\n/)[0];
74
+ if (firstLine) return firstLine;
71
75
  } catch { /* not found */ }
72
76
 
73
77
  return null;
@@ -98,7 +102,9 @@ function installAzurite() {
98
102
  return null;
99
103
  }
100
104
 
101
- const installed = join(AZURITE_INSTALL_DIR, 'node_modules', '.bin', 'azurite');
105
+ // Use .cmd on Windows (npm creates .cmd shims for bin entries)
106
+ const binName = process.platform === 'win32' ? 'azurite.cmd' : 'azurite';
107
+ const installed = join(AZURITE_INSTALL_DIR, 'node_modules', '.bin', binName);
102
108
  if (existsSync(installed)) {
103
109
  console.log(info('[fnx] Azurite installed successfully.'));
104
110
  return installed;
@@ -158,9 +164,12 @@ export async function ensureAzurite(mergedValues, opts = {}) {
158
164
  // Ensure data directory exists
159
165
  mkdirSync(join(homedir(), '.fnx', 'azurite-data'), { recursive: true });
160
166
 
161
- azuriteProcess = spawn(azuriteBin, azuriteArgs, {
162
- stdio: 'ignore',
163
- });
167
+ // On Windows, use shell:true so cmd.exe can resolve .cmd shims from PATH-based paths
168
+ const spawnOptions = process.platform === 'win32'
169
+ ? { stdio: 'ignore', shell: true }
170
+ : { stdio: 'ignore' };
171
+
172
+ azuriteProcess = spawn(azuriteBin, azuriteArgs, spawnOptions);
164
173
  weStartedAzurite = true;
165
174
 
166
175
  azuriteProcess.on('error', (err) => {
package/lib/doctor.js CHANGED
@@ -182,14 +182,16 @@ async function checkAzurite() {
182
182
  return { name: 'Azurite', status: 'pass', message: 'Running on default ports (10000–10002)' };
183
183
  }
184
184
 
185
- // Check if azurite binary is available
186
- const cachedBin = join(homedir(), '.fnx', 'tools', 'azurite', 'node_modules', '.bin', 'azurite');
185
+ // Check if azurite binary is available (Windows uses .cmd shims)
186
+ const isWin = process.platform === 'win32';
187
+ const cachedBin = join(homedir(), '.fnx', 'tools', 'azurite', 'node_modules', '.bin', isWin ? 'azurite.cmd' : 'azurite');
187
188
  if (existsSync(cachedBin)) {
188
189
  return { name: 'Azurite', status: 'warn', message: 'Installed but not running — fnx start will auto-launch it', fix: 'Azurite will start automatically when needed' };
189
190
  }
190
191
 
191
192
  try {
192
- execSync('which azurite', { stdio: ['pipe', 'pipe', 'ignore'] });
193
+ const whichCmd = isWin ? 'where azurite' : 'which azurite';
194
+ execSync(whichCmd, { stdio: ['pipe', 'pipe', 'ignore'] });
193
195
  return { name: 'Azurite', status: 'warn', message: 'Installed globally but not running — fnx start will auto-launch it' };
194
196
  } catch { /* not found */ }
195
197
 
package/lib/pack.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { basename, resolve as resolvePath, join } from 'node:path';
2
2
  import { access, constants, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
- import { tmpdir } from 'node:os';
3
+ import { tmpdir, platform } from 'node:os';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { loadFuncIgnore, getFilteredFiles } from './funcignore.js';
6
6
 
@@ -80,20 +80,53 @@ async function ensureExists(pathToCheck) {
80
80
  }
81
81
 
82
82
  async function zipDirectory(sourceDir, outputZip) {
83
- await runCommand('zip', ['-r', '-q', outputZip, '.'], { cwd: sourceDir });
83
+ if (platform() === 'win32') {
84
+ await zipWithPowerShell(sourceDir, outputZip);
85
+ } else {
86
+ await runCommand('zip', ['-r', '-q', outputZip, '.'], { cwd: sourceDir });
87
+ }
84
88
  }
85
89
 
86
90
  async function zipFilteredFiles(sourceDir, outputZip, files) {
87
- // Write file list to a temp file for zip -@ (read names from stdin)
88
- const listFile = join(tmpdir(), `fnx-pack-${Date.now()}.txt`);
89
- try {
90
- await writeFile(listFile, files.join('\n'), 'utf-8');
91
- await runCommand('zip', ['-q', outputZip, '-@'], {
92
- cwd: sourceDir,
93
- stdinFile: listFile,
94
- });
95
- } finally {
96
- await rm(listFile, { force: true });
91
+ if (platform() === 'win32') {
92
+ await zipWithPowerShell(sourceDir, outputZip, files);
93
+ } else {
94
+ // Write file list to a temp file for zip -@ (read names from stdin)
95
+ const listFile = join(tmpdir(), `fnx-pack-${Date.now()}.txt`);
96
+ try {
97
+ await writeFile(listFile, files.join('\n'), 'utf-8');
98
+ await runCommand('zip', ['-q', outputZip, '-@'], {
99
+ cwd: sourceDir,
100
+ stdinFile: listFile,
101
+ });
102
+ } finally {
103
+ await rm(listFile, { force: true });
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Create a zip archive using PowerShell on Windows.
110
+ * If `files` is provided, those paths are converted to absolute paths and included.
111
+ * Otherwise, the entire `sourceDir` is zipped.
112
+ */
113
+ async function zipWithPowerShell(sourceDir, outputZip, files) {
114
+ const absOutput = resolvePath(outputZip);
115
+ if (files) {
116
+ // Write file list to a temp file, then use PowerShell to read + compress
117
+ const listFile = join(tmpdir(), `fnx-pack-${Date.now()}.txt`);
118
+ try {
119
+ // PowerShell needs absolute paths for Compress-Archive
120
+ const absPaths = files.map(f => join(sourceDir, f).replace(/\//g, '\\'));
121
+ await writeFile(listFile, absPaths.join('\n'), 'utf-8');
122
+ const ps = `$files = Get-Content '${listFile.replace(/'/g, "''")}'; Compress-Archive -Path $files -DestinationPath '${absOutput.replace(/'/g, "''")}' -Force`;
123
+ await runCommand('powershell', ['-NoProfile', '-Command', ps], { silent: true });
124
+ } finally {
125
+ await rm(listFile, { force: true });
126
+ }
127
+ } else {
128
+ const ps = `Compress-Archive -Path '${join(sourceDir, '*').replace(/'/g, "''")}' -DestinationPath '${absOutput.replace(/'/g, "''")}' -Force`;
129
+ await runCommand('powershell', ['-NoProfile', '-Command', ps], { silent: true });
97
130
  }
98
131
  }
99
132
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrdmr/fnx-test",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "SKU-aware Azure Functions local emulator",
5
5
  "type": "module",
6
6
  "bin": {