hobots 6.0.0 → 6.1.1
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 +1 -0
- package/dist/index.cjs +80 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -291,6 +291,8 @@ interface RunItemHandle<T = unknown> {
|
|
|
291
291
|
readonly reported: boolean;
|
|
292
292
|
/** Desfecho registrado até agora (undefined = nenhum). */
|
|
293
293
|
readonly status: RunItemStatus | undefined;
|
|
294
|
+
/** Motivo do desfecho (`failed`/`occurrence`) — vai na linha `[item] FINISH` do log. */
|
|
295
|
+
readonly message: string | undefined;
|
|
294
296
|
/** Tentativa em curso (1-based) — o handler pode ler para logar. */
|
|
295
297
|
readonly attempt: number;
|
|
296
298
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -291,6 +291,8 @@ interface RunItemHandle<T = unknown> {
|
|
|
291
291
|
readonly reported: boolean;
|
|
292
292
|
/** Desfecho registrado até agora (undefined = nenhum). */
|
|
293
293
|
readonly status: RunItemStatus | undefined;
|
|
294
|
+
/** Motivo do desfecho (`failed`/`occurrence`) — vai na linha `[item] FINISH` do log. */
|
|
295
|
+
readonly message: string | undefined;
|
|
294
296
|
/** Tentativa em curso (1-based) — o handler pode ler para logar. */
|
|
295
297
|
readonly attempt: number;
|
|
296
298
|
/**
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/utils.ts
|
|
6
6
|
var SDK_NAME = "hobots";
|
|
7
|
-
var SDK_VERSION = true ? "6.
|
|
7
|
+
var SDK_VERSION = true ? "6.1.1" : "0.0.0-dev";
|
|
8
8
|
function isNode() {
|
|
9
9
|
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
10
10
|
}
|
|
@@ -1479,6 +1479,10 @@ function stepId() {
|
|
|
1479
1479
|
function stepLabel(op, description) {
|
|
1480
1480
|
return [op, description].filter(Boolean).join(" \u2014 ") || "(sem nome)";
|
|
1481
1481
|
}
|
|
1482
|
+
var ITEM_OP = "item";
|
|
1483
|
+
function lifecycleLabel(kind, op, description) {
|
|
1484
|
+
return stepLabel(kind === "item" && op === ITEM_OP ? void 0 : op, description);
|
|
1485
|
+
}
|
|
1482
1486
|
function errorText(error) {
|
|
1483
1487
|
if (error instanceof Error) return error.message || error.name;
|
|
1484
1488
|
return safeString(error);
|
|
@@ -1511,21 +1515,25 @@ function colorForStatus(status) {
|
|
|
1511
1515
|
}
|
|
1512
1516
|
}
|
|
1513
1517
|
var Step = class {
|
|
1514
|
-
constructor(transaction, parentStepId, op, description) {
|
|
1518
|
+
constructor(transaction, parentStepId, op, description, kind = "step") {
|
|
1515
1519
|
this.transaction = transaction;
|
|
1516
1520
|
this.parentStepId = parentStepId;
|
|
1517
1521
|
this.op = op;
|
|
1518
1522
|
this.description = description;
|
|
1523
|
+
this.kind = kind;
|
|
1519
1524
|
}
|
|
1520
1525
|
transaction;
|
|
1521
1526
|
parentStepId;
|
|
1522
1527
|
op;
|
|
1523
1528
|
description;
|
|
1529
|
+
kind;
|
|
1524
1530
|
stepId = stepId();
|
|
1525
1531
|
startTimestamp = nowISO();
|
|
1526
1532
|
status = "ok";
|
|
1527
1533
|
endTimestamp;
|
|
1528
1534
|
_data;
|
|
1535
|
+
// desfecho que a linha de FINISH reporta no lugar do status da etapa (item do `each`)
|
|
1536
|
+
outcome;
|
|
1529
1537
|
// ── API do bot ────────────────────────────────────────────────────────────
|
|
1530
1538
|
warning(message, options) {
|
|
1531
1539
|
if (this.status !== "error") this._setStatus("warning", message);
|
|
@@ -1564,6 +1572,13 @@ var Step = class {
|
|
|
1564
1572
|
this._close();
|
|
1565
1573
|
return this;
|
|
1566
1574
|
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Faz a linha de FINISH reportar `status`/`reason` em vez do status da etapa — o
|
|
1577
|
+
* `items.each` usa para o log do item seguir o desfecho dele (sucesso/falha/ocorrência).
|
|
1578
|
+
*/
|
|
1579
|
+
_setOutcome(status, reason) {
|
|
1580
|
+
this.outcome = { status, reason };
|
|
1581
|
+
}
|
|
1567
1582
|
_setData(key, value) {
|
|
1568
1583
|
this._data = { ...this._data, [key]: value };
|
|
1569
1584
|
}
|
|
@@ -1595,14 +1610,15 @@ var Step = class {
|
|
|
1595
1610
|
_close() {
|
|
1596
1611
|
if (this.endTimestamp) return;
|
|
1597
1612
|
this.endTimestamp = nowISO();
|
|
1613
|
+
const { status, reason } = this.outcome ?? { status: this.status, reason: this.reason() };
|
|
1598
1614
|
this.transaction.emit(
|
|
1599
|
-
|
|
1615
|
+
this.kind,
|
|
1600
1616
|
"finish",
|
|
1601
|
-
|
|
1617
|
+
lifecycleLabel(this.kind, this.op, this.description),
|
|
1602
1618
|
this.startTimestamp,
|
|
1603
1619
|
this.endTimestamp,
|
|
1604
|
-
|
|
1605
|
-
|
|
1620
|
+
status,
|
|
1621
|
+
reason
|
|
1606
1622
|
);
|
|
1607
1623
|
}
|
|
1608
1624
|
toJSON() {
|
|
@@ -1657,7 +1673,7 @@ var Transaction = class {
|
|
|
1657
1673
|
emit(kind, phase, label, startTs, endTs, status, reason) {
|
|
1658
1674
|
const durationMs = startTs && endTs ? new Date(endTs).getTime() - new Date(startTs).getTime() : void 0;
|
|
1659
1675
|
const suffix = (durationMs != null ? ` (${durationMs}ms)` : "") + (reason ? `: ${reason}` : "");
|
|
1660
|
-
const localFinish = this.echo && kind
|
|
1676
|
+
const localFinish = this.echo && kind !== "transaction" && phase === "finish";
|
|
1661
1677
|
if (this.client?.debug || localFinish) {
|
|
1662
1678
|
const tag = colorize(`[hobots:${kind}] ${phase.toUpperCase()}`, phase === "finish" ? colorForStatus(status ?? "ok") : "cyan");
|
|
1663
1679
|
console.log(`${tag} ${label}${suffix}`);
|
|
@@ -1704,13 +1720,16 @@ var Transaction = class {
|
|
|
1704
1720
|
if (!step) return fn();
|
|
1705
1721
|
return runWithStepScope({ transaction: this, step }, fn);
|
|
1706
1722
|
}
|
|
1707
|
-
/**
|
|
1708
|
-
|
|
1723
|
+
/**
|
|
1724
|
+
* Abre uma etapa sob a corrente (ou direta da transaction). Interno: o bot usa `step()`; o
|
|
1725
|
+
* `items.each` abre com `kind: 'item'` (linhas `[item] START/FINISH`).
|
|
1726
|
+
*/
|
|
1727
|
+
start(op, description, kind = "step") {
|
|
1709
1728
|
this.stepGuard?.();
|
|
1710
1729
|
const parent = this.currentStep();
|
|
1711
|
-
const step = new Step(this, parent ? parent.stepId : this.stepId, op, description);
|
|
1730
|
+
const step = new Step(this, parent ? parent.stepId : this.stepId, op, description, kind);
|
|
1712
1731
|
this.steps.push(step);
|
|
1713
|
-
this.emit(
|
|
1732
|
+
this.emit(kind, "start", lifecycleLabel(kind, op, description));
|
|
1714
1733
|
return step;
|
|
1715
1734
|
}
|
|
1716
1735
|
/**
|
|
@@ -1874,6 +1893,7 @@ var ItemHandle = class {
|
|
|
1874
1893
|
id;
|
|
1875
1894
|
reported = false;
|
|
1876
1895
|
status;
|
|
1896
|
+
message;
|
|
1877
1897
|
attempt = 1;
|
|
1878
1898
|
accumulated = {};
|
|
1879
1899
|
data(payload) {
|
|
@@ -1895,6 +1915,7 @@ var ItemHandle = class {
|
|
|
1895
1915
|
this.attempt = attempt;
|
|
1896
1916
|
this.reported = false;
|
|
1897
1917
|
this.status = void 0;
|
|
1918
|
+
this.message = void 0;
|
|
1898
1919
|
this.accumulated = {};
|
|
1899
1920
|
if (this.step && (this.step.status === "error" || this.step.status === "warning")) {
|
|
1900
1921
|
this.step._setStatus("ok");
|
|
@@ -1904,6 +1925,7 @@ var ItemHandle = class {
|
|
|
1904
1925
|
record(status, message, payload, image3) {
|
|
1905
1926
|
this.reported = true;
|
|
1906
1927
|
this.status = status;
|
|
1928
|
+
this.message = message;
|
|
1907
1929
|
const merged = { ...this.basePayload ?? {}, ...this.accumulated, ...payload ?? {} };
|
|
1908
1930
|
this.sink.report(status, message, Object.keys(merged).length > 0 ? merged : void 0, this.id, image3);
|
|
1909
1931
|
}
|
|
@@ -1955,6 +1977,10 @@ function knownLength(list) {
|
|
|
1955
1977
|
const length = list?.length;
|
|
1956
1978
|
return typeof length === "number" && Number.isInteger(length) && length >= 1 ? length : void 0;
|
|
1957
1979
|
}
|
|
1980
|
+
var ITEM_LOG_STATUS = { succeeded: "ok", occurrence: "warning", failed: "error" };
|
|
1981
|
+
function setItemOutcome(step, status, message) {
|
|
1982
|
+
step._setOutcome(ITEM_LOG_STATUS[status], status === "succeeded" ? void 0 : message);
|
|
1983
|
+
}
|
|
1958
1984
|
function skippedMessage(count) {
|
|
1959
1985
|
if (count === 1) return "1 item pulado: j\xE1 conclu\xEDdo neste trabalho numa execu\xE7\xE3o anterior";
|
|
1960
1986
|
return `${count} itens pulados: j\xE1 conclu\xEDdos neste trabalho numa execu\xE7\xE3o anterior`;
|
|
@@ -1964,18 +1990,29 @@ async function eachItem(list, handler, options, sink) {
|
|
|
1964
1990
|
const requested = options.retries ?? DEFAULT_EACH_RETRIES;
|
|
1965
1991
|
const totalRetries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_EACH_RETRIES;
|
|
1966
1992
|
const explicitId = options.id !== void 0;
|
|
1967
|
-
const length = options.progress === false ? void 0 : knownLength(list);
|
|
1968
|
-
if (length !== void 0) sink.declareTotal(length);
|
|
1969
1993
|
const done = options.skipDone === false ? void 0 : await sink.doneItemIds();
|
|
1970
|
-
|
|
1971
|
-
|
|
1994
|
+
const isDone = (id) => id !== void 0 && done !== void 0 && done.has(id);
|
|
1995
|
+
const length = knownLength(list);
|
|
1996
|
+
let entries;
|
|
1997
|
+
if (length !== void 0 && done !== void 0 && done.size > 0) {
|
|
1998
|
+
const pending = [];
|
|
1999
|
+
let position = 0;
|
|
2000
|
+
for await (const element of list) {
|
|
2001
|
+
const id = resolveId(options.id, element, position, explicitId);
|
|
2002
|
+
if (isDone(id)) result.skipped += 1;
|
|
2003
|
+
else pending.push({ element, index: position, id });
|
|
2004
|
+
position += 1;
|
|
2005
|
+
}
|
|
2006
|
+
if (options.progress !== false && pending.length > 0) sink.declareTotal(pending.length);
|
|
2007
|
+
entries = pending;
|
|
2008
|
+
} else {
|
|
2009
|
+
if (options.progress !== false && length !== void 0) sink.declareTotal(length);
|
|
2010
|
+
entries = lazyEntries(list, options.id, explicitId);
|
|
2011
|
+
}
|
|
2012
|
+
for await (const { element, index, id } of entries) {
|
|
1972
2013
|
sink.checkCanceled();
|
|
1973
|
-
|
|
1974
|
-
if (done?.size && id !== void 0 && done.has(id)) {
|
|
1975
|
-
result.total += 1;
|
|
2014
|
+
if (isDone(id)) {
|
|
1976
2015
|
result.skipped += 1;
|
|
1977
|
-
if (options.progress !== false) sink.advance();
|
|
1978
|
-
index += 1;
|
|
1979
2016
|
continue;
|
|
1980
2017
|
}
|
|
1981
2018
|
const description = options.description?.(element, index) ?? id ?? `#${index + 1}`;
|
|
@@ -2025,20 +2062,35 @@ async function eachItem(list, handler, options, sink) {
|
|
|
2025
2062
|
} else {
|
|
2026
2063
|
const message = thrownMessage(error);
|
|
2027
2064
|
if (!handle.reported) handle.failed(message);
|
|
2028
|
-
step
|
|
2029
|
-
|
|
2065
|
+
if (step) {
|
|
2066
|
+
setItemOutcome(step, handle.status ?? "failed", handle.message);
|
|
2067
|
+
step._failed(error);
|
|
2068
|
+
} else {
|
|
2069
|
+
sink.logError(`item ${description} falhou: ${message}`);
|
|
2070
|
+
}
|
|
2030
2071
|
}
|
|
2031
2072
|
}
|
|
2032
|
-
|
|
2073
|
+
const final = handle.status ?? "succeeded";
|
|
2074
|
+
if (step) {
|
|
2075
|
+
setItemOutcome(step, final, handle.message);
|
|
2076
|
+
step._close();
|
|
2077
|
+
}
|
|
2033
2078
|
if (options.progress !== false) sink.advance();
|
|
2034
2079
|
result.total += 1;
|
|
2035
|
-
result[
|
|
2036
|
-
index += 1;
|
|
2080
|
+
result[final] += 1;
|
|
2037
2081
|
if (options.flush !== false) await sink.flush();
|
|
2038
2082
|
}
|
|
2083
|
+
result.total += result.skipped;
|
|
2039
2084
|
if (result.skipped > 0) sink.logInfo(skippedMessage(result.skipped));
|
|
2040
2085
|
return result;
|
|
2041
2086
|
}
|
|
2087
|
+
async function* lazyEntries(list, spec, explicit) {
|
|
2088
|
+
let index = 0;
|
|
2089
|
+
for await (const element of list) {
|
|
2090
|
+
yield { element, index, id: resolveId(spec, element, index, explicit) };
|
|
2091
|
+
index += 1;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2042
2094
|
function noteAttempts(step, attempts) {
|
|
2043
2095
|
if (attempts > 1) step._setData("attempts", attempts);
|
|
2044
2096
|
}
|
|
@@ -2424,7 +2476,7 @@ var RunReporter = class {
|
|
|
2424
2476
|
tx.setStepGuard(checkCanceled);
|
|
2425
2477
|
const eachSink = {
|
|
2426
2478
|
report: (status, message, payload, id, image3) => this.addItem(status, message, payload, id, image3),
|
|
2427
|
-
startStep: (op, description) => tx.start(op, description),
|
|
2479
|
+
startStep: (op, description) => tx.start(op, description, "item"),
|
|
2428
2480
|
stepScope: (step, fn) => tx.scope(step, fn),
|
|
2429
2481
|
declareTotal: (total) => {
|
|
2430
2482
|
if (this.progressTotal == null) this.setProgress(this.progressCurrent, total);
|
|
@@ -2434,7 +2486,9 @@ var RunReporter = class {
|
|
|
2434
2486
|
isAborted: () => this.abortController.signal.aborted,
|
|
2435
2487
|
logInfo: (message) => this.log("info", message),
|
|
2436
2488
|
logWarning: (message) => this.log("warning", message),
|
|
2489
|
+
/* v8 ignore start -- a run sempre tem `tx`: o item tem etapa e o erro sai na linha `[item] FINISH` (o each só chama logError sem etapa) */
|
|
2437
2490
|
logError: (message) => this.log("error", message),
|
|
2491
|
+
/* v8 ignore stop */
|
|
2438
2492
|
sleep: (ms) => cancelableSleep(ms, this.abortController.signal),
|
|
2439
2493
|
doneItemIds: () => this.listDoneItemIds(),
|
|
2440
2494
|
flush: () => this.flush()
|