bunosh 0.5.8 → 0.5.9
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/README.md +2 -0
- package/package.json +1 -1
- package/src/task.js +70 -34
- package/src/tasks/assert.js +7 -0
package/README.md
CHANGED
|
@@ -448,6 +448,8 @@ export async function checkServices() {
|
|
|
448
448
|
}
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
+
`task.try` fully isolates failures from the exit code. Any `shell`, `fetch`, `task`, or `assert` that fails inside the callback is recorded as a warning (yellow), never as a failed task — so the run still exits with code `0` if the rest succeeded. `task.stopOnFailures()` is also suppressed inside `task.try`: an inner failure will never call `process.exit(1)`. The return value (`true`/`false`) is the only signal you act on.
|
|
452
|
+
|
|
451
453
|
## Documentation
|
|
452
454
|
|
|
453
455
|
- **[Examples](docs/examples.md)** — Real-world examples and workflows
|
package/package.json
CHANGED
package/src/task.js
CHANGED
|
@@ -99,10 +99,21 @@ export function getTaskPrefix(taskId) {
|
|
|
99
99
|
|
|
100
100
|
export function createTaskInfo(name, parentId = null, isSilent = false) {
|
|
101
101
|
const taskInfo = new TaskInfo(name, Date.now(), TaskStatus.RUNNING, parentId, isSilent);
|
|
102
|
+
|
|
103
|
+
let p = parentId;
|
|
104
|
+
while (p) {
|
|
105
|
+
const parent = runningTasks.get(p);
|
|
106
|
+
if (!parent) break;
|
|
107
|
+
if (parent.isTry || parent.isInsideTry) {
|
|
108
|
+
taskInfo.isInsideTry = true;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
p = parent.parentId;
|
|
112
|
+
}
|
|
113
|
+
|
|
102
114
|
runningTasks.set(taskInfo.id, taskInfo);
|
|
103
115
|
tasksExecuted.push(taskInfo);
|
|
104
116
|
|
|
105
|
-
// Also add to global array for exit handler
|
|
106
117
|
if (globalThis._bunoshGlobalTasksExecuted) {
|
|
107
118
|
globalThis._bunoshGlobalTasksExecuted.push(taskInfo);
|
|
108
119
|
}
|
|
@@ -114,10 +125,19 @@ export function finishTaskInfo(taskInfo, success = true, error = null, output =
|
|
|
114
125
|
const endTime = Date.now();
|
|
115
126
|
const duration = endTime - taskInfo.startTime;
|
|
116
127
|
|
|
117
|
-
|
|
128
|
+
let status;
|
|
129
|
+
if (success) {
|
|
130
|
+
status = TaskStatus.SUCCESS;
|
|
131
|
+
} else if (taskInfo.isInsideTry) {
|
|
132
|
+
status = TaskStatus.WARNING;
|
|
133
|
+
} else {
|
|
134
|
+
status = TaskStatus.FAIL;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
taskInfo.status = status;
|
|
118
138
|
taskInfo.duration = duration;
|
|
119
139
|
taskInfo.result = {
|
|
120
|
-
status
|
|
140
|
+
status,
|
|
121
141
|
output: error?.message || output || null
|
|
122
142
|
};
|
|
123
143
|
|
|
@@ -132,6 +152,8 @@ export class TaskInfo {
|
|
|
132
152
|
this.status = status;
|
|
133
153
|
this.parentId = parentId;
|
|
134
154
|
this.isSilent = isSilent;
|
|
155
|
+
this.isTry = false;
|
|
156
|
+
this.isInsideTry = false;
|
|
135
157
|
}
|
|
136
158
|
}
|
|
137
159
|
|
|
@@ -141,55 +163,60 @@ export async function tryTask(name, fn, isSilent = true) {
|
|
|
141
163
|
name = fn.toString().slice(0, 50).replace(/\s+/g, ' ').trim();
|
|
142
164
|
}
|
|
143
165
|
|
|
144
|
-
const taskInfo = createTaskInfo(name, null, isSilent);
|
|
166
|
+
const taskInfo = createTaskInfo(name, getCurrentTaskId() || null, isSilent);
|
|
167
|
+
taskInfo.isTry = true;
|
|
168
|
+
const startIndex = tasksExecuted.length;
|
|
145
169
|
|
|
146
170
|
const shouldPrint = !globalSilenceMode && !isSilent;
|
|
147
171
|
const printer = new Printer('task', taskInfo.id);
|
|
148
172
|
if (shouldPrint) printer.start(name);
|
|
149
173
|
|
|
174
|
+
let result;
|
|
175
|
+
let caughtError = null;
|
|
150
176
|
try {
|
|
151
|
-
|
|
177
|
+
result = await asyncLocalStorage.run(taskInfo.id, async () => {
|
|
152
178
|
return await Promise.resolve(fn());
|
|
153
179
|
});
|
|
180
|
+
} catch (err) {
|
|
181
|
+
caughtError = err;
|
|
182
|
+
}
|
|
154
183
|
|
|
155
|
-
|
|
156
|
-
|
|
184
|
+
const endTime = Date.now();
|
|
185
|
+
const duration = endTime - taskInfo.startTime;
|
|
157
186
|
|
|
158
|
-
|
|
159
|
-
if (result && typeof result === 'object' && result.constructor && result.constructor.name === 'TaskResult') {
|
|
160
|
-
if (result.hasFailed || result.hasWarning) {
|
|
161
|
-
taskInfo.status = TaskStatus.WARNING;
|
|
162
|
-
taskInfo.duration = duration;
|
|
163
|
-
taskInfo.result = { status: TaskStatus.WARNING, output: result.output };
|
|
187
|
+
let failed = caughtError !== null;
|
|
164
188
|
|
|
165
|
-
|
|
166
|
-
|
|
189
|
+
if (!failed && result && typeof result === 'object' && result.constructor && result.constructor.name === 'TaskResult') {
|
|
190
|
+
if (result.hasFailed || result.hasWarning) failed = true;
|
|
191
|
+
}
|
|
167
192
|
|
|
168
|
-
|
|
193
|
+
if (!failed) {
|
|
194
|
+
for (let i = startIndex; i < tasksExecuted.length; i++) {
|
|
195
|
+
const t = tasksExecuted[i];
|
|
196
|
+
if (t === taskInfo) continue;
|
|
197
|
+
const s = t.result?.status;
|
|
198
|
+
if (s === TaskStatus.FAIL || s === TaskStatus.WARNING) {
|
|
199
|
+
failed = true;
|
|
200
|
+
break;
|
|
169
201
|
}
|
|
170
202
|
}
|
|
203
|
+
}
|
|
171
204
|
|
|
172
|
-
|
|
173
|
-
taskInfo.duration = duration;
|
|
174
|
-
taskInfo.result = { status: TaskStatus.SUCCESS, output: result };
|
|
175
|
-
|
|
176
|
-
if (shouldPrint) printer.finish(name);
|
|
177
|
-
runningTasks.delete(taskInfo.id);
|
|
178
|
-
|
|
179
|
-
return true;
|
|
180
|
-
} catch (err) {
|
|
181
|
-
const endTime = Date.now();
|
|
182
|
-
const duration = endTime - taskInfo.startTime;
|
|
183
|
-
|
|
205
|
+
if (failed) {
|
|
184
206
|
taskInfo.status = TaskStatus.WARNING;
|
|
185
207
|
taskInfo.duration = duration;
|
|
186
|
-
taskInfo.result = { status: TaskStatus.WARNING, output:
|
|
187
|
-
|
|
188
|
-
if (shouldPrint) printer.warning(name, err);
|
|
208
|
+
taskInfo.result = { status: TaskStatus.WARNING, output: caughtError?.message || result?.output || null };
|
|
209
|
+
if (shouldPrint) printer.warning(name, caughtError);
|
|
189
210
|
runningTasks.delete(taskInfo.id);
|
|
190
|
-
|
|
191
211
|
return false;
|
|
192
212
|
}
|
|
213
|
+
|
|
214
|
+
taskInfo.status = TaskStatus.SUCCESS;
|
|
215
|
+
taskInfo.duration = duration;
|
|
216
|
+
taskInfo.result = { status: TaskStatus.SUCCESS, output: result };
|
|
217
|
+
if (shouldPrint) printer.finish(name);
|
|
218
|
+
runningTasks.delete(taskInfo.id);
|
|
219
|
+
return true;
|
|
193
220
|
}
|
|
194
221
|
|
|
195
222
|
export async function task(name, fn, isSilent = false) {
|
|
@@ -198,7 +225,7 @@ export async function task(name, fn, isSilent = false) {
|
|
|
198
225
|
name = fn.toString().slice(0, 50).replace(/\s+/g, ' ').trim();
|
|
199
226
|
}
|
|
200
227
|
|
|
201
|
-
const taskInfo = createTaskInfo(name, null, isSilent);
|
|
228
|
+
const taskInfo = createTaskInfo(name, getCurrentTaskId() || null, isSilent);
|
|
202
229
|
|
|
203
230
|
const shouldPrint = !globalSilenceMode && !isSilent;
|
|
204
231
|
const printer = new Printer('task', taskInfo.id);
|
|
@@ -231,6 +258,15 @@ export async function task(name, fn, isSilent = false) {
|
|
|
231
258
|
const endTime = Date.now();
|
|
232
259
|
const duration = endTime - taskInfo.startTime;
|
|
233
260
|
|
|
261
|
+
if (taskInfo.isInsideTry) {
|
|
262
|
+
taskInfo.status = TaskStatus.WARNING;
|
|
263
|
+
taskInfo.duration = duration;
|
|
264
|
+
taskInfo.result = { status: TaskStatus.WARNING, output: err.message };
|
|
265
|
+
printer.warning(name, err);
|
|
266
|
+
runningTasks.delete(taskInfo.id);
|
|
267
|
+
return TaskResult.fail(err.message, { taskType: 'task', error: err });
|
|
268
|
+
}
|
|
269
|
+
|
|
234
270
|
taskInfo.status = TaskStatus.FAIL;
|
|
235
271
|
taskInfo.duration = duration;
|
|
236
272
|
taskInfo.result = { status: TaskStatus.FAIL, output: err.message };
|
|
@@ -247,7 +283,7 @@ export async function task(name, fn, isSilent = false) {
|
|
|
247
283
|
if (stopFailToggle && !isTestEnvironment) {
|
|
248
284
|
process.exit(1);
|
|
249
285
|
}
|
|
250
|
-
|
|
286
|
+
|
|
251
287
|
return TaskResult.fail(err.message, { taskType: 'task', error: err });
|
|
252
288
|
}
|
|
253
289
|
}
|
package/src/tasks/assert.js
CHANGED
|
@@ -16,6 +16,13 @@ export default function assert(condition, message = 'Assertion failed') {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const error = new Error(message);
|
|
19
|
+
|
|
20
|
+
if (taskInfo.isInsideTry) {
|
|
21
|
+
printer.warning(message, error);
|
|
22
|
+
finishTaskInfo(taskInfo, false, error, message);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
printer.error(message, error);
|
|
20
27
|
finishTaskInfo(taskInfo, false, error, message);
|
|
21
28
|
|