hobots 5.1.0 → 6.0.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.
- package/README.md +3 -1
- package/dist/index.cjs +25 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -7
- package/dist/index.d.ts +27 -7
- package/dist/index.js +25 -6
- package/dist/index.js.map +1 -1
- package/docs/api-reference.md +1 -1
- package/docs/runs.md +6 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,7 +112,7 @@ A opção passada em `register()`/`start()` tem precedência sobre a env — út
|
|
|
112
112
|
| --- | --- |
|
|
113
113
|
| `hobots.log.debug/info/warn/error/success(msg, ...rest)` | Log da execução, enviado incrementalmente ao app (e ecoado no terminal como `[hobots] INFO …`). Aceita vários argumentos como `console.log` — `hobots.log.info('nota', numero, 'ok')` — cada um vira texto, unidos por espaço. Um `hobots.image(...)` como **último** argumento pendura um print na linha. **Nunca lança** — pode ir em `finally`. |
|
|
114
114
|
| `hobots.items.succeeded(payload?, { id, image }?)` · `.failed(msg, payload?, …)` · `.occurrence(msg, payload?, …)` · `.add({...})` | **A entrega do robô**: cada item processado, com status e atributos (viram colunas no app — declare-as com a opção `items: { columns: [...] }` do `register`/`start`). `image` pendura um print no item. Bufferizado, em lotes. |
|
|
115
|
-
| `hobots.items.each(lista, async (
|
|
115
|
+
| `hobots.items.each(lista, async (item, index?) => …, { id: 'campo', payload, retries: 1, retryDelayMs: 5000, skipDone: true }?)` | **Loop com o contrato garantido**: o handler recebe o handle do item (e, se declarar, o índice) — o elemento é `item.value` e a posição, `item.index`; sem `payload`, os campos do elemento (objeto simples) viram as colunas do item (`payload: false` desliga); cada elemento vira etapa + item; exceção no handler = nova tentativa e, esgotada, item `failed` com a mensagem e o loop **segue** até o fim; `throw new Occurrence(msg)` = item `occurrence`, sem repetir; na reexecução do mesmo trabalho pula o que já deu `succeeded`/`occurrence`; progresso automático; `hobots.flush()` ao fim de cada ciclo (`flush: false` desliga). Só cancelamento/timeout interrompem. No handler, `item.data({ nf: 123 })` vai guardando os atributos do item sem decidir o desfecho — entram no `succeeded`/`failed`/`occurrence`, inclusive nos implícitos. |
|
|
116
116
|
| `hobots.progress.total(n)` · `.advance(k = 1)` · `.set(atual, total?)` · `.current` · `.snapshot` | Barra, percentual e tempo restante na execução. Sem `total()` nada é enviado. |
|
|
117
117
|
| `hobots.flush(timeoutMs?)` | **Entrega já** o que a execução fez: as etapas raiz finalizadas viram transactions parciais (waterfall na Central sem esperar a run terminar) e itens, logs e progresso pendentes saem sem esperar o throttle. `step` (raiz) e cada ciclo do `items.each` já chamam sozinhos; à mão, para o resto da rodada de um agente `start()`. Aguarda com teto (15 s) e nunca lança. |
|
|
118
118
|
| `hobots.step(nome, async etapa => …, { retries = 1, retryDelayMs = 5_000, flush = true }?)` | Uma **etapa** no waterfall de performance da execução: roda a função, **tenta de novo** se ela lançar (`retries: 0` desliga — use em etapas não idempotentes) e fecha a etapa. Resolve com o retorno da função. `hobots.step` dentro de outra vira sub-etapa. A etapa raiz faz `flush()` ao terminar (`flush: false` desliga). O handle `etapa` tem `warning(motivo, { image }?)`, `image(png)` e `data(chave, valor)`. |
|
|
@@ -231,6 +231,8 @@ Sem handler próprio de sinal, um `SIGINT`/`SIGTERM` (ou erro fatal) com execuç
|
|
|
231
231
|
|
|
232
232
|
## Changelog resumido
|
|
233
233
|
|
|
234
|
+
- **6.0.0** — **breaking**: o handler de `items.each` recebe o handle do item, `async (item, index) => …` (`index` opcional); o elemento da lista é `item.value` e a posição, `item.index`. Migração: `async (conta, item, i) => …` → `async (item, i) => { const conta = item.value; … }`. `options.id`/`payload`/`description` continuam recebendo `(element, index)`. **Payload padrão:** sem `options.payload`, os campos do elemento (objeto simples, cópia rasa) viram o payload base do item; `options.payload` substitui, `payload: false` desliga. Detalhes no [CHANGELOG](./CHANGELOG.md).
|
|
235
|
+
- **5.2.0** — **`item.data(payload)`** no handle do `items.each`: guarda atributos do item sem registrar desfecho; mescla a cada chamada e entra em qualquer desfecho (inclusive nos implícitos), entre o `options.payload` do `each` e o payload da chamada de desfecho; zera na nova tentativa. Detalhes no [CHANGELOG](./CHANGELOG.md).
|
|
234
236
|
- **5.1.0** — `items.each` com **nova tentativa por item** (`retries: 1`, `retryDelayMs: 5000`; uma etapa só por elemento, `warning` quando a repetição deu certo, `error` + item `failed` quando esgotou), **`Occurrence`** exportada (`throw new Occurrence(msg, payload?, { image }?)` no handler = item `occurrence`, sem repetir), `id` por campo (`'numero'`), chave composta (`['cnpj', 'competencia']`) ou função — padrão: o campo `id` do elemento — e **reexecução sem repetir**: ao executar novamente o trabalho, pula os ids já `succeeded`/`occurrence` (`skipDone: true`; `POST /v1/runs/{id}/items/done`); resultado com `skipped`; `item.id` sempre `string`, `item.attempt`. Detalhes no [CHANGELOG](./CHANGELOG.md).
|
|
235
237
|
- **5.0.0** — **uma API só de etapas** (breaking): `hobots.step(nome, fn, { retries, retryDelayMs }?)` abre a etapa, tenta de novo quando `fn` lança (default 1 tentativa extra) e fecha; `fn` recebe o handle `etapa` (`warning`/`image`/`data`); `hobots.step` dentro de outra (ou do handler do `items.each`) vira sub-etapa. `hobots.transaction`, `ctx.transaction` e os tipos `Transaction`/`Step`/`StepOutcomeOptions` foram removidos; `item.step` é o handle novo. Modo local ecoa `[hobots:step] FINISH …`. Nomes de etapa são recortados em 2048 no cliente. Flush automático ao fim da etapa raiz e de cada ciclo do `items.each` (`flush: false` desliga). Antes/depois no [CHANGELOG](./CHANGELOG.md).
|
|
236
238
|
- **4.6.0** — **modo local** (`HOBOTS_LOCAL_RUN=1`): `register()`/`start()` rodam o handler uma vez sem Central, sem secret e sem rede, com params de `HOBOTS_RUN_PARAMS`; itens viram linhas `[hobots:item]` + `[hobots:summary]` no stdout, exit code 0/1/130; CLI `npx hobots run <entry.js> [--params] [--param] [--file] [--reset-ledger]`; `FileRef` local aceita `path` no modo local; eco `[hobots:progress] c/t` no stdout (paridade com o SDK Python).
|
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
45
45
|
|
|
46
46
|
// src/utils.ts
|
|
47
47
|
var SDK_NAME = "hobots";
|
|
48
|
-
var SDK_VERSION = true ? "
|
|
48
|
+
var SDK_VERSION = true ? "6.0.0" : "0.0.0-dev";
|
|
49
49
|
function isNode() {
|
|
50
50
|
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
51
51
|
}
|
|
@@ -1925,13 +1925,15 @@ function thrownMessage(error) {
|
|
|
1925
1925
|
return safeString(error);
|
|
1926
1926
|
}
|
|
1927
1927
|
var ItemHandle = class {
|
|
1928
|
-
constructor(index, id, step,
|
|
1928
|
+
constructor(value, index, id, step, basePayload2, sink) {
|
|
1929
|
+
this.value = value;
|
|
1929
1930
|
this.index = index;
|
|
1930
1931
|
this.step = step;
|
|
1931
|
-
this.basePayload =
|
|
1932
|
+
this.basePayload = basePayload2;
|
|
1932
1933
|
this.sink = sink;
|
|
1933
1934
|
this.id = id ?? uuid4();
|
|
1934
1935
|
}
|
|
1936
|
+
value;
|
|
1935
1937
|
index;
|
|
1936
1938
|
step;
|
|
1937
1939
|
basePayload;
|
|
@@ -1941,6 +1943,10 @@ var ItemHandle = class {
|
|
|
1941
1943
|
reported = false;
|
|
1942
1944
|
status;
|
|
1943
1945
|
attempt = 1;
|
|
1946
|
+
accumulated = {};
|
|
1947
|
+
data(payload) {
|
|
1948
|
+
Object.assign(this.accumulated, payload);
|
|
1949
|
+
}
|
|
1944
1950
|
succeeded(payload, options) {
|
|
1945
1951
|
this.record("succeeded", void 0, payload, options?.image);
|
|
1946
1952
|
}
|
|
@@ -1957,6 +1963,7 @@ var ItemHandle = class {
|
|
|
1957
1963
|
this.attempt = attempt;
|
|
1958
1964
|
this.reported = false;
|
|
1959
1965
|
this.status = void 0;
|
|
1966
|
+
this.accumulated = {};
|
|
1960
1967
|
if (this.step && (this.step.status === "error" || this.step.status === "warning")) {
|
|
1961
1968
|
this.step._setStatus("ok");
|
|
1962
1969
|
this.step._deleteData("message");
|
|
@@ -1965,10 +1972,22 @@ var ItemHandle = class {
|
|
|
1965
1972
|
record(status, message, payload, image3) {
|
|
1966
1973
|
this.reported = true;
|
|
1967
1974
|
this.status = status;
|
|
1968
|
-
const merged = { ...this.basePayload ?? {}, ...payload ?? {} };
|
|
1975
|
+
const merged = { ...this.basePayload ?? {}, ...this.accumulated, ...payload ?? {} };
|
|
1969
1976
|
this.sink.report(status, message, Object.keys(merged).length > 0 ? merged : void 0, this.id, image3);
|
|
1970
1977
|
}
|
|
1971
1978
|
};
|
|
1979
|
+
function defaultPayload(element) {
|
|
1980
|
+
if (typeof element !== "object" || element === null) return void 0;
|
|
1981
|
+
const proto = Object.getPrototypeOf(element);
|
|
1982
|
+
if (proto !== Object.prototype && proto !== null) return void 0;
|
|
1983
|
+
const copy = { ...element };
|
|
1984
|
+
return Object.keys(copy).length > 0 ? copy : void 0;
|
|
1985
|
+
}
|
|
1986
|
+
function basePayload(spec, element, index) {
|
|
1987
|
+
if (spec === false) return void 0;
|
|
1988
|
+
if (spec === void 0) return defaultPayload(element);
|
|
1989
|
+
return spec(element, index);
|
|
1990
|
+
}
|
|
1972
1991
|
function field(element, name) {
|
|
1973
1992
|
if (typeof element !== "object" || element === null) return { present: false, value: void 0 };
|
|
1974
1993
|
const record = element;
|
|
@@ -2029,7 +2048,7 @@ async function eachItem(list, handler, options, sink) {
|
|
|
2029
2048
|
}
|
|
2030
2049
|
const description = options.description?.(element, index) ?? id ?? `#${index + 1}`;
|
|
2031
2050
|
const step = sink.startStep(options.op ?? "item", description);
|
|
2032
|
-
const handle = new ItemHandle(index, id, step, options.payload
|
|
2051
|
+
const handle = new ItemHandle(element, index, id, step, basePayload(options.payload, element, index), sink);
|
|
2033
2052
|
const current = index;
|
|
2034
2053
|
let attempts = 0;
|
|
2035
2054
|
let lastFailure;
|
|
@@ -2038,7 +2057,7 @@ async function eachItem(list, handler, options, sink) {
|
|
|
2038
2057
|
(attempt) => {
|
|
2039
2058
|
attempts = attempt;
|
|
2040
2059
|
if (attempt > 1) handle._nextAttempt(attempt);
|
|
2041
|
-
return sink.stepScope(step, async () => handler(
|
|
2060
|
+
return sink.stepScope(step, async () => handler(handle, current));
|
|
2042
2061
|
},
|
|
2043
2062
|
{
|
|
2044
2063
|
retries: totalRetries,
|