@backtomyfuture/exchange-cli 0.2.4 → 0.2.5

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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { execFileSync } = require('child_process');
3
+ const { spawn } = require('child_process');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
 
@@ -16,32 +16,65 @@ const PLATFORM_PACKAGES = {
16
16
  const platformKey = `${process.platform}-${process.arch}`;
17
17
  const ext = process.platform === 'win32' ? '.exe' : '';
18
18
 
19
+ function renderError(message, code = 'BINARY_NOT_FOUND', exitCode = 1) {
20
+ const isText =
21
+ process.argv.includes('--format=text') ||
22
+ (process.argv.indexOf('--format') !== -1 &&
23
+ process.argv[process.argv.indexOf('--format') + 1] === 'text');
24
+ if (isText) {
25
+ console.error(`Error [${code}]: ${message}`);
26
+ } else {
27
+ console.log(
28
+ JSON.stringify({
29
+ ok: false,
30
+ error: message,
31
+ code: code,
32
+ retryable: false,
33
+ })
34
+ );
35
+ }
36
+ process.exit(exitCode);
37
+ }
38
+
19
39
  function getBinaryPath() {
20
40
  if (process.env.EXCHANGE_CLI_BINARY) {
21
- return process.env.EXCHANGE_CLI_BINARY;
41
+ const customBin = process.env.EXCHANGE_CLI_BINARY;
42
+ if (!fs.existsSync(customBin)) {
43
+ renderError(
44
+ `exchange-cli: binary not found at EXCHANGE_CLI_BINARY: ${customBin}`,
45
+ 'BINARY_NOT_FOUND',
46
+ 1
47
+ );
48
+ }
49
+ return customBin;
22
50
  }
23
51
 
24
52
  const pkg = PLATFORM_PACKAGES[platformKey];
25
53
  if (!pkg) {
26
- console.error(`exchange-cli: unsupported platform ${platformKey}`);
27
- process.exit(1);
54
+ renderError(`exchange-cli: unsupported platform ${platformKey}`, 'PLATFORM_NOT_SUPPORTED', 1);
28
55
  }
29
56
 
30
57
  try {
31
58
  return require.resolve(`${pkg}/bin/exchange-cli${ext}`);
32
59
  } catch {
33
- const modPath = path.join(
34
- path.dirname(require.resolve(`${pkg}/package.json`)),
35
- `bin/exchange-cli${ext}`
36
- );
37
- if (fs.existsSync(modPath)) {
38
- return modPath;
60
+ try {
61
+ const modPath = path.join(
62
+ path.dirname(require.resolve(`${pkg}/package.json`)),
63
+ `bin/exchange-cli${ext}`
64
+ );
65
+ if (fs.existsSync(modPath)) {
66
+ return modPath;
67
+ }
68
+ } catch {
69
+ // Ignore require failure
39
70
  }
40
71
  }
41
72
 
42
- console.error(`exchange-cli: binary not found for ${platformKey}`);
43
- console.error('Try: npm install --force @backtomyfuture/exchange-cli');
44
- process.exit(1);
73
+ renderError(
74
+ `exchange-cli: binary not found for ${platformKey}. Try: npm install --force @backtomyfuture/exchange-cli`,
75
+ 'BINARY_NOT_FOUND',
76
+ 1
77
+ );
45
78
  }
46
79
 
47
80
  try {
@@ -50,13 +83,48 @@ try {
50
83
  const { ensureDarwinArm64RuntimeLayout } = require('./runtime-layout');
51
84
  ensureDarwinArm64RuntimeLayout(binaryPath);
52
85
  }
53
- execFileSync(binaryPath, process.argv.slice(2), {
86
+
87
+ const child = spawn(binaryPath, process.argv.slice(2), {
54
88
  stdio: 'inherit',
55
89
  env: { ...process.env },
56
90
  });
91
+
92
+ child.on('error', (err) => {
93
+ renderError(
94
+ `exchange-cli: failed to spawn binary: ${err.message}`,
95
+ 'BINARY_NOT_FOUND',
96
+ 1
97
+ );
98
+ });
99
+
100
+ const forwardSignal = (signal) => {
101
+ if (child && !child.killed && child.pid) {
102
+ try {
103
+ child.kill(signal);
104
+ } catch {
105
+ // Child already exited
106
+ }
107
+ }
108
+ };
109
+
110
+ process.on('SIGINT', () => forwardSignal('SIGINT'));
111
+ process.on('SIGTERM', () => forwardSignal('SIGTERM'));
112
+ process.on('SIGHUP', () => forwardSignal('SIGHUP'));
113
+
114
+ child.on('exit', (code, signal) => {
115
+ if (signal) {
116
+ process.removeAllListeners('SIGINT');
117
+ process.removeAllListeners('SIGTERM');
118
+ process.removeAllListeners('SIGHUP');
119
+ try {
120
+ process.kill(process.pid, signal);
121
+ } catch {
122
+ process.exit(128 + 15);
123
+ }
124
+ } else {
125
+ process.exit(code ?? 0);
126
+ }
127
+ });
57
128
  } catch (e) {
58
- if (e && e.status != null) {
59
- process.exit(e.status);
60
- }
61
- throw e;
129
+ renderError(`exchange-cli wrapper error: ${e.message || e}`, 'WRAPPER_ERROR', 1);
62
130
  }
@@ -79,6 +79,11 @@ function ensureDarwinArm64RuntimeLayout(binaryPath, logger = null) {
79
79
  return { changed: false };
80
80
  }
81
81
 
82
+ const markerPath = path.join(internalDir, '.runtime_layout_ok');
83
+ if (fs.existsSync(markerPath)) {
84
+ return { changed: false };
85
+ }
86
+
82
87
  const frameworkVersionDir = resolveFrameworkVersionDir(internalDir);
83
88
  if (!frameworkVersionDir) {
84
89
  return { changed: false };
@@ -106,6 +111,13 @@ function ensureDarwinArm64RuntimeLayout(binaryPath, logger = null) {
106
111
  } catch {
107
112
  // Best effort only.
108
113
  }
114
+
115
+ try {
116
+ fs.writeFileSync(markerPath, '');
117
+ } catch {
118
+ // Best effort only.
119
+ }
120
+
109
121
  return { changed };
110
122
  }
111
123
 
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@backtomyfuture/exchange-cli",
3
- "version": "0.2.4",
4
- "description": "On-premises Exchange Server CLI for email, calendar, tasks, and contacts.",
3
+ "version": "0.2.5",
4
+ "description": "Cross-platform CLI for on-premises Microsoft Exchange Server",
5
5
  "bin": {
6
- "exchange-cli": "bin/exchange-cli.js"
6
+ "exchange-cli": "./bin/exchange-cli.js"
7
7
  },
8
8
  "scripts": {
9
- "postinstall": "node install.js"
9
+ "postinstall": "node ./install.js"
10
10
  },
11
11
  "files": [
12
12
  "bin/",
13
13
  "install.js"
14
14
  ],
15
15
  "optionalDependencies": {
16
- "@backtomyfuture/exchange-cli-darwin-arm64": "0.2.4",
17
- "@backtomyfuture/exchange-cli-darwin-x64": "0.2.4",
18
- "@backtomyfuture/exchange-cli-linux-x64": "0.2.4",
19
- "@backtomyfuture/exchange-cli-linux-arm64": "0.2.4",
20
- "@backtomyfuture/exchange-cli-win32-x64": "0.2.4",
21
- "@backtomyfuture/exchange-cli-win32-ia32": "0.2.4"
16
+ "@backtomyfuture/exchange-cli-darwin-arm64": "0.2.5",
17
+ "@backtomyfuture/exchange-cli-darwin-x64": "0.2.5",
18
+ "@backtomyfuture/exchange-cli-linux-x64": "0.2.5",
19
+ "@backtomyfuture/exchange-cli-linux-arm64": "0.2.5",
20
+ "@backtomyfuture/exchange-cli-win32-x64": "0.2.5",
21
+ "@backtomyfuture/exchange-cli-win32-ia32": "0.2.5"
22
22
  },
23
23
  "engines": {
24
24
  "node": ">=14"