@mcp-z/client 2.2.4 → 2.3.0

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 (107) hide show
  1. package/README.md +12 -1
  2. package/dist/cjs/auth/capability-discovery.d.cts +3 -1
  3. package/dist/cjs/auth/capability-discovery.d.ts +3 -1
  4. package/dist/cjs/auth/capability-discovery.js +46 -32
  5. package/dist/cjs/auth/capability-discovery.js.map +1 -1
  6. package/dist/cjs/auth/discovery-fetch.d.cts +2 -0
  7. package/dist/cjs/auth/discovery-fetch.d.ts +2 -0
  8. package/dist/cjs/auth/discovery-fetch.js +85 -31
  9. package/dist/cjs/auth/discovery-fetch.js.map +1 -1
  10. package/dist/cjs/auth/interactive-oauth-flow.d.cts +1 -1
  11. package/dist/cjs/auth/interactive-oauth-flow.d.ts +1 -1
  12. package/dist/cjs/auth/interactive-oauth-flow.js +13 -6
  13. package/dist/cjs/auth/interactive-oauth-flow.js.map +1 -1
  14. package/dist/cjs/auth/oauth-callback-listener.d.cts +1 -1
  15. package/dist/cjs/auth/oauth-callback-listener.d.ts +1 -1
  16. package/dist/cjs/auth/oauth-callback-listener.js +38 -2
  17. package/dist/cjs/auth/oauth-callback-listener.js.map +1 -1
  18. package/dist/cjs/auth/rfc9728-discovery.d.cts +7 -2
  19. package/dist/cjs/auth/rfc9728-discovery.d.ts +7 -2
  20. package/dist/cjs/auth/rfc9728-discovery.js +120 -88
  21. package/dist/cjs/auth/rfc9728-discovery.js.map +1 -1
  22. package/dist/cjs/auth/types.d.cts +4 -0
  23. package/dist/cjs/auth/types.d.ts +4 -0
  24. package/dist/cjs/auth/types.js.map +1 -1
  25. package/dist/cjs/connection/connect-client.d.cts +9 -1
  26. package/dist/cjs/connection/connect-client.d.ts +9 -1
  27. package/dist/cjs/connection/connect-client.js +282 -75
  28. package/dist/cjs/connection/connect-client.js.map +1 -1
  29. package/dist/cjs/connection/existing-process-transport.d.cts +18 -18
  30. package/dist/cjs/connection/existing-process-transport.d.ts +18 -18
  31. package/dist/cjs/connection/existing-process-transport.js +187 -82
  32. package/dist/cjs/connection/existing-process-transport.js.map +1 -1
  33. package/dist/cjs/connection/wait-for-http-ready.d.cts +1 -1
  34. package/dist/cjs/connection/wait-for-http-ready.d.ts +1 -1
  35. package/dist/cjs/connection/wait-for-http-ready.js +30 -5
  36. package/dist/cjs/connection/wait-for-http-ready.js.map +1 -1
  37. package/dist/cjs/dcr/dcr-authenticator.d.cts +1 -1
  38. package/dist/cjs/dcr/dcr-authenticator.d.ts +1 -1
  39. package/dist/cjs/dcr/dcr-authenticator.js +29 -18
  40. package/dist/cjs/dcr/dcr-authenticator.js.map +1 -1
  41. package/dist/cjs/dcr/dynamic-client-registrar.js +2 -1
  42. package/dist/cjs/dcr/dynamic-client-registrar.js.map +1 -1
  43. package/dist/cjs/index.d.cts +1 -1
  44. package/dist/cjs/index.d.ts +1 -1
  45. package/dist/cjs/index.js.map +1 -1
  46. package/dist/cjs/spawn/owned-process-tree.d.cts +12 -0
  47. package/dist/cjs/spawn/owned-process-tree.d.ts +12 -0
  48. package/dist/cjs/spawn/owned-process-tree.js +93 -0
  49. package/dist/cjs/spawn/owned-process-tree.js.map +1 -0
  50. package/dist/cjs/spawn/spawn-server.d.cts +8 -32
  51. package/dist/cjs/spawn/spawn-server.d.ts +8 -32
  52. package/dist/cjs/spawn/spawn-server.js +398 -212
  53. package/dist/cjs/spawn/spawn-server.js.map +1 -1
  54. package/dist/cjs/spawn/spawn-servers.d.cts +18 -8
  55. package/dist/cjs/spawn/spawn-servers.d.ts +18 -8
  56. package/dist/cjs/spawn/spawn-servers.js +342 -113
  57. package/dist/cjs/spawn/spawn-servers.js.map +1 -1
  58. package/dist/cjs/types.d.cts +1 -1
  59. package/dist/cjs/types.d.ts +1 -1
  60. package/dist/cjs/types.js.map +1 -1
  61. package/dist/esm/auth/capability-discovery.d.ts +3 -1
  62. package/dist/esm/auth/capability-discovery.js +21 -11
  63. package/dist/esm/auth/capability-discovery.js.map +1 -1
  64. package/dist/esm/auth/discovery-fetch.d.ts +2 -0
  65. package/dist/esm/auth/discovery-fetch.js +64 -23
  66. package/dist/esm/auth/discovery-fetch.js.map +1 -1
  67. package/dist/esm/auth/interactive-oauth-flow.d.ts +1 -1
  68. package/dist/esm/auth/interactive-oauth-flow.js +13 -6
  69. package/dist/esm/auth/interactive-oauth-flow.js.map +1 -1
  70. package/dist/esm/auth/oauth-callback-listener.d.ts +1 -1
  71. package/dist/esm/auth/oauth-callback-listener.js +32 -2
  72. package/dist/esm/auth/oauth-callback-listener.js.map +1 -1
  73. package/dist/esm/auth/rfc9728-discovery.d.ts +7 -2
  74. package/dist/esm/auth/rfc9728-discovery.js +40 -16
  75. package/dist/esm/auth/rfc9728-discovery.js.map +1 -1
  76. package/dist/esm/auth/types.d.ts +4 -0
  77. package/dist/esm/auth/types.js.map +1 -1
  78. package/dist/esm/connection/connect-client.d.ts +9 -1
  79. package/dist/esm/connection/connect-client.js +97 -35
  80. package/dist/esm/connection/connect-client.js.map +1 -1
  81. package/dist/esm/connection/existing-process-transport.d.ts +18 -18
  82. package/dist/esm/connection/existing-process-transport.js +132 -70
  83. package/dist/esm/connection/existing-process-transport.js.map +1 -1
  84. package/dist/esm/connection/wait-for-http-ready.d.ts +1 -1
  85. package/dist/esm/connection/wait-for-http-ready.js +19 -4
  86. package/dist/esm/connection/wait-for-http-ready.js.map +1 -1
  87. package/dist/esm/dcr/dcr-authenticator.d.ts +1 -1
  88. package/dist/esm/dcr/dcr-authenticator.js +26 -15
  89. package/dist/esm/dcr/dcr-authenticator.js.map +1 -1
  90. package/dist/esm/dcr/dynamic-client-registrar.js +2 -1
  91. package/dist/esm/dcr/dynamic-client-registrar.js.map +1 -1
  92. package/dist/esm/index.d.ts +1 -1
  93. package/dist/esm/index.js.map +1 -1
  94. package/dist/esm/spawn/owned-process-tree.d.ts +12 -0
  95. package/dist/esm/spawn/owned-process-tree.js +39 -0
  96. package/dist/esm/spawn/owned-process-tree.js.map +1 -0
  97. package/dist/esm/spawn/spawn-server.d.ts +8 -32
  98. package/dist/esm/spawn/spawn-server.js +224 -130
  99. package/dist/esm/spawn/spawn-server.js.map +1 -1
  100. package/dist/esm/spawn/spawn-servers.d.ts +18 -8
  101. package/dist/esm/spawn/spawn-servers.js +180 -55
  102. package/dist/esm/spawn/spawn-servers.js.map +1 -1
  103. package/dist/esm/types.d.ts +1 -1
  104. package/dist/esm/types.js.map +1 -1
  105. package/package.json +8 -5
  106. package/schemas/servers.d.ts +24 -0
  107. package/schemas/servers.schema.json +31 -0
@@ -11,10 +11,12 @@ Object.defineProperty(exports, "spawnProcess", {
11
11
  return spawnProcess;
12
12
  }
13
13
  });
14
- var _child_process = require("child_process");
14
+ var _crossspawn = /*#__PURE__*/ _interop_require_default(require("cross-spawn"));
15
+ var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
15
16
  var _process = /*#__PURE__*/ _interop_require_wildcard(require("process"));
16
17
  var _loggerts = require("../utils/logger.js");
17
18
  var _pathutilsts = require("../utils/path-utils.js");
19
+ var _ownedprocesstreets = require("./owned-process-tree.js");
18
20
  function _array_like_to_array(arr, len) {
19
21
  if (len == null || len > arr.length) len = arr.length;
20
22
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -66,6 +68,11 @@ function _instanceof(left, right) {
66
68
  return !!right[Symbol.hasInstance](left);
67
69
  } else return left instanceof right;
68
70
  }
71
+ function _interop_require_default(obj) {
72
+ return obj && obj.__esModule ? obj : {
73
+ default: obj
74
+ };
75
+ }
69
76
  function _getRequireWildcardCache(nodeInterop) {
70
77
  if (typeof WeakMap !== "function") return null;
71
78
  var cacheBabelInterop = new WeakMap();
@@ -248,18 +255,18 @@ function _unsupported_iterable_to_array(o, minLen) {
248
255
  if (n === "Map" || n === "Set") return Array.from(n);
249
256
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
250
257
  }
251
- /**
252
- * Normalize environment variables by merging with process.env and filtering undefined values.
253
- */ function normalizeEnv(env) {
254
- var merged = _object_spread({}, _process.env, env || {});
258
+ var DEFAULT_CLOSE_TIMEOUT_MS = 5000;
259
+ var PROCESS_TERMINATION_TIMEOUT_MS = 5000;
260
+ var PROCESS_POLL_INTERVAL_MS = 25;
261
+ function normalizeEnv(env) {
262
+ var inheritEnv = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
263
+ var merged = _object_spread({}, inheritEnv ? _process.env : {}, env || {});
255
264
  var result = {};
256
265
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
257
266
  try {
258
267
  for(var _iterator = Object.entries(merged)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
259
268
  var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
260
- if (value !== undefined) {
261
- result[key] = value;
262
- }
269
+ if (value !== undefined) result[key] = value;
263
270
  }
264
271
  } catch (err) {
265
272
  _didIteratorError = true;
@@ -277,40 +284,226 @@ function _unsupported_iterable_to_array(o, minLen) {
277
284
  }
278
285
  return result;
279
286
  }
280
- function terminateWindowsProcessTree(pid, force) {
281
- var args = [
282
- '/PID',
283
- String(pid),
284
- '/T'
285
- ];
286
- if (force) args.push('/F');
287
- return new Promise(function(resolve, reject) {
288
- var taskkill = (0, _child_process.spawn)('taskkill.exe', args, {
289
- stdio: 'ignore',
290
- windowsHide: true
291
- });
292
- taskkill.once('error', reject);
293
- taskkill.once('close', function(code) {
294
- if (code === 0) {
295
- resolve();
296
- return;
287
+ function delay(ms) {
288
+ return new Promise(function(resolve) {
289
+ return setTimeout(resolve, ms);
290
+ });
291
+ }
292
+ function waitForCompletion(closeEvent, childClosed, tree, timeoutMs) {
293
+ return _async_to_generator(function() {
294
+ var _tmp, deadline, lastError, processGroupEmpty, closed;
295
+ return _ts_generator(this, function(_state) {
296
+ switch(_state.label){
297
+ case 0:
298
+ if (!!tree) return [
299
+ 3,
300
+ 2
301
+ ];
302
+ _tmp = {};
303
+ return [
304
+ 4,
305
+ waitForChildClose(closeEvent, timeoutMs)
306
+ ];
307
+ case 1:
308
+ return [
309
+ 2,
310
+ (_tmp.closed = _state.sent() !== undefined, _tmp)
311
+ ];
312
+ case 2:
313
+ deadline = Date.now() + timeoutMs;
314
+ _state.label = 3;
315
+ case 3:
316
+ if (!true) return [
317
+ 3,
318
+ 5
319
+ ];
320
+ processGroupEmpty = false;
321
+ try {
322
+ processGroupEmpty = tree.isEmpty();
323
+ lastError = undefined;
324
+ } catch (error) {
325
+ lastError = _instanceof(error, Error) ? error : new Error(String(error));
326
+ }
327
+ closed = childClosed();
328
+ if (closed && processGroupEmpty) return [
329
+ 2,
330
+ {
331
+ closed: closed,
332
+ processGroupEmpty: processGroupEmpty
333
+ }
334
+ ];
335
+ if (Date.now() >= deadline) return [
336
+ 2,
337
+ _object_spread({
338
+ closed: closed,
339
+ processGroupEmpty: processGroupEmpty
340
+ }, lastError && {
341
+ error: lastError
342
+ })
343
+ ];
344
+ return [
345
+ 4,
346
+ delay(Math.min(PROCESS_POLL_INTERVAL_MS, Math.max(1, deadline - Date.now())))
347
+ ];
348
+ case 4:
349
+ _state.sent();
350
+ return [
351
+ 3,
352
+ 3
353
+ ];
354
+ case 5:
355
+ return [
356
+ 2
357
+ ];
297
358
  }
298
- reject(new Error("taskkill.exe failed to stop process tree rooted at PID ".concat(pid, " (exit code ").concat(code !== null && code !== void 0 ? code : 'unknown', ")")));
299
359
  });
360
+ })();
361
+ }
362
+ function isCompletionSuccessful(completion) {
363
+ return completion.closed && completion.processGroupEmpty !== false;
364
+ }
365
+ function terminateChild(child, tree) {
366
+ if (tree) return tree.terminate();
367
+ try {
368
+ return {
369
+ killed: child.kill('SIGKILL')
370
+ };
371
+ } catch (error) {
372
+ return {
373
+ killed: false,
374
+ error: asError(error)
375
+ };
376
+ }
377
+ }
378
+ function waitForChildClose(closeEvent, timeoutMs) {
379
+ var timer;
380
+ return Promise.race([
381
+ closeEvent,
382
+ new Promise(function(resolve) {
383
+ timer = setTimeout(function() {
384
+ return resolve(undefined);
385
+ }, timeoutMs);
386
+ })
387
+ ]).finally(function() {
388
+ if (timer) clearTimeout(timer);
389
+ });
390
+ }
391
+ function requestProcessSignal(child, signal) {
392
+ if (!child.pid) throw new Error('Cannot request cooperative shutdown because the server has no process ID');
393
+ if (_process.platform === 'win32') throw new Error('POSIX process signals are not available on Windows');
394
+ try {
395
+ _process.kill(-child.pid, signal);
396
+ } catch (error) {
397
+ if (!(_instanceof(error, Error) && 'code' in error && error.code === 'ESRCH')) throw error;
398
+ }
399
+ }
400
+ function asError(error) {
401
+ return _instanceof(error, Error) ? error : new Error(String(error));
402
+ }
403
+ function withCause(message, cause) {
404
+ return new Error(message, {
405
+ cause: cause
300
406
  });
301
407
  }
408
+ function runStopCommand(command, cwd, timeoutMs, inheritEnv) {
409
+ return _async_to_generator(function() {
410
+ var stopCwd, env, args, child, spawnError, closed, closeEventValue, closeEvent, result, tree, completion, _completion_error, _termination_error, termination, afterTermination, details, reason, remaining, _closeEventValue_code;
411
+ return _ts_generator(this, function(_state) {
412
+ switch(_state.label){
413
+ case 0:
414
+ stopCwd = command.cwd ? _path.resolve(cwd, command.cwd) : cwd;
415
+ env = normalizeEnv(command.env, inheritEnv);
416
+ args = command.args ? (0, _pathutilsts.resolveArgsPaths)(command.args, stopCwd) : [];
417
+ child = (0, _crossspawn.default)(command.command, args, {
418
+ cwd: stopCwd,
419
+ env: env,
420
+ stdio: 'ignore',
421
+ shell: false,
422
+ detached: _process.platform !== 'win32',
423
+ windowsHide: true
424
+ });
425
+ closed = false;
426
+ closeEvent = new Promise(function(resolve) {
427
+ child.once('error', function(error) {
428
+ spawnError = error;
429
+ });
430
+ child.once('close', function(code, signal) {
431
+ closed = true;
432
+ closeEventValue = {
433
+ code: code,
434
+ signal: signal
435
+ };
436
+ resolve({
437
+ code: code,
438
+ signal: signal
439
+ });
440
+ });
441
+ });
442
+ if (!!child.pid) return [
443
+ 3,
444
+ 2
445
+ ];
446
+ return [
447
+ 4,
448
+ waitForChildClose(closeEvent, timeoutMs)
449
+ ];
450
+ case 1:
451
+ result = _state.sent();
452
+ if (!result) throw new Error("Stop command did not start or close within ".concat(timeoutMs, "ms"));
453
+ if (spawnError) throw withCause("Stop command could not be started: ".concat(spawnError.message), spawnError);
454
+ _state.label = 2;
455
+ case 2:
456
+ tree = child.pid && _process.platform !== 'win32' ? new _ownedprocesstreets.OwnedProcessTree(child.pid) : undefined;
457
+ return [
458
+ 4,
459
+ waitForCompletion(closeEvent, function() {
460
+ return closed;
461
+ }, tree, timeoutMs)
462
+ ];
463
+ case 3:
464
+ completion = _state.sent();
465
+ if (!!isCompletionSuccessful(completion)) return [
466
+ 3,
467
+ 5
468
+ ];
469
+ termination = terminateChild(child, tree);
470
+ return [
471
+ 4,
472
+ waitForCompletion(closeEvent, function() {
473
+ return closed;
474
+ }, tree, PROCESS_TERMINATION_TIMEOUT_MS)
475
+ ];
476
+ case 4:
477
+ afterTermination = _state.sent();
478
+ details = [
479
+ (_completion_error = completion.error) === null || _completion_error === void 0 ? void 0 : _completion_error.message,
480
+ (_termination_error = termination.error) === null || _termination_error === void 0 ? void 0 : _termination_error.message
481
+ ].filter(Boolean).join('; ');
482
+ reason = "Stop command exceeded ".concat(timeoutMs, "ms and required emergency process termination");
483
+ remaining = !isCompletionSuccessful(afterTermination) ? '; stop command or its POSIX process group remained alive' : '';
484
+ throw new Error("".concat(reason).concat(details ? ": ".concat(details) : '').concat(remaining));
485
+ case 5:
486
+ if (spawnError) throw withCause("Stop command could not be started: ".concat(spawnError.message), spawnError);
487
+ if (closeEventValue && (closeEventValue.code !== 0 || closeEventValue.signal !== null)) {
488
+ ;
489
+ throw new Error("Stop command exited with code ".concat((_closeEventValue_code = closeEventValue.code) !== null && _closeEventValue_code !== void 0 ? _closeEventValue_code : 'unknown').concat(closeEventValue.signal ? " (signal ".concat(closeEventValue.signal, ")") : ''));
490
+ }
491
+ return [
492
+ 2
493
+ ];
494
+ }
495
+ });
496
+ })();
497
+ }
302
498
  function spawnProcess(opts) {
303
- var _opts_cwd, _opts_stdio, _opts_shell;
499
+ var _opts_cwd, _opts_stdio, _opts_inheritEnv;
304
500
  var name = opts.name;
305
501
  var command = opts.command;
306
502
  var cwd = (_opts_cwd = opts.cwd) !== null && _opts_cwd !== void 0 ? _opts_cwd : _process.cwd();
307
503
  var stdio = (_opts_stdio = opts.stdio) !== null && _opts_stdio !== void 0 ? _opts_stdio : 'inherit';
308
- var shell = (_opts_shell = opts.shell) !== null && _opts_shell !== void 0 ? _opts_shell : _process.platform === 'win32';
309
- // Resolve paths in args relative to the working directory
310
504
  var args = opts.args ? (0, _pathutilsts.resolveArgsPaths)(opts.args, cwd) : [];
311
- // Merge environment variables
312
- var env = normalizeEnv(opts.env);
313
- // Create resolved config for return value
505
+ var inheritEnv = (_opts_inheritEnv = opts.inheritEnv) !== null && _opts_inheritEnv !== void 0 ? _opts_inheritEnv : true;
506
+ var env = normalizeEnv(opts.env, inheritEnv);
314
507
  var resolvedConfig = {
315
508
  name: name,
316
509
  command: command,
@@ -318,204 +511,197 @@ function spawnProcess(opts) {
318
511
  cwd: cwd,
319
512
  env: env,
320
513
  stdio: stdio,
321
- shell: shell
514
+ shell: false
322
515
  };
323
- // Log spawn operation
324
516
  _loggerts.logger.info("[".concat(name, "] → ").concat(command, " ").concat(args.join(' ')));
325
- // Spawn the process
326
- var spawnOpts = {
517
+ var child = (0, _crossspawn.default)(command, args, {
327
518
  cwd: cwd,
328
519
  env: env,
329
520
  stdio: stdio,
330
- shell: shell
331
- };
332
- var child = (0, _child_process.spawn)(command, args, spawnOpts);
333
- // Pipe stdio if not inherited
334
- if (child.stderr) child.stderr.on('data', function(chunk) {
335
- _process.stderr.write(chunk);
521
+ shell: false,
522
+ detached: _process.platform !== 'win32',
523
+ windowsHide: true
336
524
  });
337
- // Attach lifecycle logging
338
- child.on('exit', function(code, sig) {
339
- return _loggerts.logger.info("[".concat(name, "] exited (code=").concat(code, ", signal=").concat(sig || 'none', ")"));
525
+ if (child.stderr) child.stderr.on('data', function(chunk) {
526
+ return _process.stderr.write(chunk);
340
527
  });
341
- child.on('error', function(err) {
342
- return _loggerts.logger.info("[".concat(name, "] process error: ").concat(err.message));
528
+ var isClosed = false;
529
+ var _closeEventValue;
530
+ var closeEvent = new Promise(function(resolve) {
531
+ child.once('close', function(code, signal) {
532
+ isClosed = true;
533
+ _closeEventValue = {
534
+ code: code,
535
+ signal: signal
536
+ };
537
+ _loggerts.logger.info("[".concat(name, "] closed (code=").concat(code, ", signal=").concat(signal || 'none', ")"));
538
+ resolve({
539
+ code: code,
540
+ signal: signal
541
+ });
542
+ });
543
+ child.once('error', function(error) {
544
+ return _loggerts.logger.info("[".concat(name, "] process error: ").concat(error.message));
545
+ });
343
546
  });
344
- // Create stop function with graceful shutdown
345
- var stop = function stop() {
346
- var signal = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 'SIGINT', _$opts = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
547
+ var tree = child.pid && _process.platform !== 'win32' ? new _ownedprocesstreets.OwnedProcessTree(child.pid) : undefined;
548
+ var closePromise;
549
+ var performClose = function performClose(signal, timeoutMs) {
347
550
  return _async_to_generator(function() {
348
- var _opts_timeoutMs, timeoutMs, closePromise;
551
+ var timedOut, killed, errors, stopSucceeded, error, completion, termination;
349
552
  return _ts_generator(this, function(_state) {
350
- // If already exited, return immediately
351
- if (child.exitCode !== null || child.signalCode !== null) {
352
- return [
353
- 2,
354
- {
355
- timedOut: false,
356
- killed: false
553
+ switch(_state.label){
554
+ case 0:
555
+ if (!!child.pid) return [
556
+ 3,
557
+ 2
558
+ ];
559
+ return [
560
+ 4,
561
+ waitForChildClose(closeEvent, timeoutMs)
562
+ ];
563
+ case 1:
564
+ _state.sent();
565
+ throw new Error("Cannot verify shutdown of server '".concat(name, "' because it has no process ID"));
566
+ case 2:
567
+ timedOut = false;
568
+ killed = false;
569
+ errors = [];
570
+ stopSucceeded = false;
571
+ if (!opts.stop) return [
572
+ 3,
573
+ 7
574
+ ];
575
+ _state.label = 3;
576
+ case 3:
577
+ _state.trys.push([
578
+ 3,
579
+ 5,
580
+ ,
581
+ 6
582
+ ]);
583
+ return [
584
+ 4,
585
+ runStopCommand(opts.stop, cwd, timeoutMs, inheritEnv)
586
+ ];
587
+ case 4:
588
+ _state.sent();
589
+ stopSucceeded = true;
590
+ return [
591
+ 3,
592
+ 6
593
+ ];
594
+ case 5:
595
+ error = _state.sent();
596
+ errors.push(withCause("Server '".concat(name, "' application stop command failed: ").concat(asError(error).message), asError(error)));
597
+ return [
598
+ 3,
599
+ 6
600
+ ];
601
+ case 6:
602
+ return [
603
+ 3,
604
+ 8
605
+ ];
606
+ case 7:
607
+ if (child.stdin && !child.stdin.destroyed && !child.stdin.writableEnded) {
608
+ child.stdin.end();
609
+ } else if (_process.platform !== 'win32') {
610
+ try {
611
+ requestProcessSignal(child, signal);
612
+ } catch (error) {
613
+ errors.push(withCause("Server '".concat(name, "' cooperative signal failed: ").concat(asError(error).message), asError(error)));
614
+ }
357
615
  }
358
- ];
359
- }
360
- timeoutMs = (_opts_timeoutMs = _$opts.timeoutMs) !== null && _opts_timeoutMs !== void 0 ? _opts_timeoutMs : 500;
361
- // Wait for 'close' event (process exit + stdio streams closed)
362
- // This is better than 'exit' because it ensures stdio is fully cleaned up
363
- closePromise = new Promise(function(resolve, reject) {
364
- var isResolved = false;
365
- var wasKilled = false;
366
- var timedOut = false;
367
- var resolveOnce = function resolveOnce(didTimeout) {
368
- if (isResolved) return;
369
- isResolved = true;
370
- clearTimeout(timeout);
371
- resolve({
372
- timedOut: didTimeout,
373
- killed: wasKilled
374
- });
375
- };
376
- var rejectOnce = function rejectOnce(error) {
377
- if (isResolved) return;
378
- isResolved = true;
379
- clearTimeout(timeout);
380
- reject(error);
381
- };
382
- // Set timeout for forceful kill
383
- var timeout = setTimeout(function() {
616
+ _state.label = 8;
617
+ case 8:
618
+ return [
619
+ 4,
620
+ waitForCompletion(closeEvent, function() {
621
+ return isClosed;
622
+ }, tree, timeoutMs)
623
+ ];
624
+ case 9:
625
+ completion = _state.sent();
626
+ if (completion.error) errors.push(withCause("Could not inspect the owned process tree for server '".concat(name, "'"), completion.error));
627
+ if (!!isCompletionSuccessful(completion)) return [
628
+ 3,
629
+ 12
630
+ ];
384
631
  timedOut = true;
385
- var forceKill = function forceKill() {
386
- return _async_to_generator(function() {
387
- var error;
388
- return _ts_generator(this, function(_state) {
389
- switch(_state.label){
390
- case 0:
391
- _state.trys.push([
392
- 0,
393
- 4,
394
- ,
395
- 5
396
- ]);
397
- if (!(_process.platform === 'win32' && child.pid)) return [
398
- 3,
399
- 2
400
- ];
401
- return [
402
- 4,
403
- terminateWindowsProcessTree(child.pid, true)
404
- ];
405
- case 1:
406
- _state.sent();
407
- wasKilled = true;
408
- return [
409
- 3,
410
- 3
411
- ];
412
- case 2:
413
- if (child.exitCode === null && !child.killed) {
414
- wasKilled = child.kill('SIGKILL');
415
- }
416
- _state.label = 3;
417
- case 3:
418
- resolveOnce(true);
419
- return [
420
- 3,
421
- 5
422
- ];
423
- case 4:
424
- error = _state.sent();
425
- rejectOnce(_instanceof(error, Error) ? error : new Error(String(error)));
426
- return [
427
- 3,
428
- 5
429
- ];
430
- case 5:
431
- return [
432
- 2
433
- ];
434
- }
435
- });
436
- })();
437
- };
438
- void forceKill();
439
- }, timeoutMs);
440
- // Listen for 'close' event (not 'exit') to wait for stdio close
441
- child.once('close', function() {
442
- if (!timedOut) resolveOnce(false);
443
- });
444
- // Also listen for 'error' event in case spawn failed
445
- // This prevents promise from hanging forever if process never started
446
- child.once('error', function() {
447
- resolveOnce(false);
448
- });
449
- var requestShutdown = function requestShutdown() {
450
- return _async_to_generator(function() {
451
- var error;
452
- return _ts_generator(this, function(_state) {
453
- switch(_state.label){
454
- case 0:
455
- _state.trys.push([
456
- 0,
457
- 4,
458
- ,
459
- 5
460
- ]);
461
- if (child.exitCode !== null || child.signalCode !== null) {
462
- resolveOnce(false);
463
- return [
464
- 2
465
- ];
466
- }
467
- if (!(_process.platform === 'win32' && child.pid)) return [
468
- 3,
469
- 2
470
- ];
471
- return [
472
- 4,
473
- terminateWindowsProcessTree(child.pid, false)
474
- ];
475
- case 1:
476
- _state.sent();
477
- return [
478
- 3,
479
- 3
480
- ];
481
- case 2:
482
- if (!child.kill(signal)) {
483
- resolveOnce(false);
484
- }
485
- _state.label = 3;
486
- case 3:
487
- return [
488
- 3,
489
- 5
490
- ];
491
- case 4:
492
- error = _state.sent();
493
- rejectOnce(_instanceof(error, Error) ? error : new Error(String(error)));
494
- return [
495
- 3,
496
- 5
497
- ];
498
- case 5:
499
- return [
500
- 2
501
- ];
502
- }
503
- });
504
- })();
505
- };
506
- void requestShutdown();
507
- });
508
- return [
509
- 2,
510
- closePromise
511
- ];
632
+ if (!(!opts.stop && child.stdin && _process.platform !== 'win32')) return [
633
+ 3,
634
+ 11
635
+ ];
636
+ try {
637
+ requestProcessSignal(child, signal);
638
+ } catch (error) {
639
+ errors.push(withCause("Server '".concat(name, "' cooperative signal failed: ").concat(asError(error).message), asError(error)));
640
+ }
641
+ return [
642
+ 4,
643
+ waitForCompletion(closeEvent, function() {
644
+ return isClosed;
645
+ }, tree, timeoutMs)
646
+ ];
647
+ case 10:
648
+ completion = _state.sent();
649
+ if (completion.error) errors.push(withCause("Could not inspect the owned process tree for server '".concat(name, "'"), completion.error));
650
+ return [
651
+ 3,
652
+ 12
653
+ ];
654
+ case 11:
655
+ if (!opts.stop && _process.platform !== 'win32' && !child.stdin) {
656
+ // The first signal was sent before waiting for an inherited-stdio HTTP process.
657
+ }
658
+ _state.label = 12;
659
+ case 12:
660
+ if (!!isCompletionSuccessful(completion)) return [
661
+ 3,
662
+ 14
663
+ ];
664
+ termination = terminateChild(child, tree);
665
+ killed || (killed = termination.killed);
666
+ if (termination.error) errors.push(withCause("Emergency termination failed for server '".concat(name, "'"), termination.error));
667
+ return [
668
+ 4,
669
+ waitForCompletion(closeEvent, function() {
670
+ return isClosed;
671
+ }, tree, PROCESS_TERMINATION_TIMEOUT_MS)
672
+ ];
673
+ case 13:
674
+ completion = _state.sent();
675
+ if (!isCompletionSuccessful(completion)) {
676
+ errors.push(new Error("Server '".concat(name, "' did not close").concat(completion.processGroupEmpty === false ? ' with its POSIX process group' : '', " after emergency termination")));
677
+ }
678
+ _state.label = 14;
679
+ case 14:
680
+ if (opts.stop && !stopSucceeded && errors.length === 0) {
681
+ errors.push(new Error("Server '".concat(name, "' application stop command did not complete successfully")));
682
+ }
683
+ if (errors.length > 0) throw new AggregateError(errors, "Server '".concat(name, "' shutdown completed with ").concat(errors.length, " failure(s)"));
684
+ return [
685
+ 2,
686
+ {
687
+ timedOut: timedOut,
688
+ killed: killed
689
+ }
690
+ ];
691
+ }
512
692
  });
513
693
  })();
514
694
  };
695
+ var close = function close() {
696
+ var signal = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 'SIGINT', closeOptions = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
697
+ var _closeOptions_timeoutMs;
698
+ closePromise !== null && closePromise !== void 0 ? closePromise : closePromise = performClose(signal, (_closeOptions_timeoutMs = closeOptions.timeoutMs) !== null && _closeOptions_timeoutMs !== void 0 ? _closeOptions_timeoutMs : DEFAULT_CLOSE_TIMEOUT_MS);
699
+ return closePromise;
700
+ };
515
701
  return {
516
702
  config: resolvedConfig,
517
703
  process: child,
518
- close: stop
704
+ close: close
519
705
  };
520
706
  }
521
707
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }