taskmonkey-cli 0.11.1 → 0.11.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskmonkey-cli",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "TaskMonkey CLI — Remote dev tools for tenant config editing and tool testing",
5
5
  "bin": {
6
6
  "tm": "./bin/tm.js",
@@ -108,12 +108,13 @@ export async function watch(options = {}) {
108
108
  * kill the watcher.
109
109
  */
110
110
  async function runLogStreamForever(initialConfig) {
111
- const abort = new AbortController();
111
+ // Outer abort: tied to the watcher's lifetime, set by SIGINT.
112
+ const outerAbort = new AbortController();
112
113
  let config = initialConfig;
113
114
  let firstConnect = true;
114
115
 
115
116
  (async () => {
116
- while (!abort.signal.aborted) {
117
+ while (!outerAbort.signal.aborted) {
117
118
  try {
118
119
  // Refresh token before each (re)connect — cheap and prevents
119
120
  // silent auth drops on long-running sessions.
@@ -124,11 +125,18 @@ async function runLogStreamForever(initialConfig) {
124
125
  continue;
125
126
  }
126
127
 
128
+ // Per-connection abort: a fresh AbortController for every fetch so we
129
+ // never accumulate listeners on the long-lived outer signal. Linked to
130
+ // the outer one so SIGINT still tears the in-flight stream down.
131
+ const innerAbort = new AbortController();
132
+ const onOuterAbort = () => innerAbort.abort();
133
+ outerAbort.signal.addEventListener('abort', onOuterAbort, { once: true });
134
+
127
135
  try {
128
136
  await streamLogs({
129
137
  config,
130
138
  lines: firstConnect ? 20 : 0,
131
- signal: abort.signal,
139
+ signal: innerAbort.signal,
132
140
  onLine: (line, type) => {
133
141
  const prefix = chalk.gray(' │ ');
134
142
  switch (type) {
@@ -146,19 +154,22 @@ async function runLogStreamForever(initialConfig) {
146
154
  },
147
155
  });
148
156
  } catch (err) {
149
- if (abort.signal.aborted) return;
157
+ if (outerAbort.signal.aborted) return;
150
158
  // Server timeouts after 5 min are expected; don't spam.
151
159
  if (!/HTTP 5|fetch failed|terminated|ECONN/i.test(err.message)) {
152
160
  console.error(chalk.yellow(` [logs] ${err.message}`));
153
161
  }
162
+ } finally {
163
+ outerAbort.signal.removeEventListener('abort', onOuterAbort);
154
164
  }
155
165
 
156
- if (abort.signal.aborted) return;
166
+ if (outerAbort.signal.aborted) return;
167
+ // Backoff: 1 s after a normal stream end, longer if we're flapping.
157
168
  await sleep(1000);
158
169
  }
159
170
  })();
160
171
 
161
- return abort;
172
+ return outerAbort;
162
173
  }
163
174
 
164
175
  function sleep(ms) {