@dudousxd/nestjs-durable-dashboard 0.22.2 → 0.22.3
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/LICENSE +21 -0
- package/dist/client/durable-client.d.ts +3 -3
- package/dist/client/durable-client.d.ts.map +1 -1
- package/dist/client/durable-client.js.map +1 -1
- package/dist/client/group-subprocesses.d.ts +5 -5
- package/dist/client/group-subprocesses.d.ts.map +1 -1
- package/dist/server/index.cjs +695 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +160 -0
- package/dist/server/index.d.ts +160 -5
- package/dist/server/index.js +662 -4
- package/dist/server/index.js.map +1 -1
- package/dist/spa/assets/{index-B0Nn98HA.js → index-D8irnyfw.js} +2 -2
- package/dist/spa/index.html +1 -1
- package/package.json +14 -7
- package/dist/server/attr-filter.d.ts +0 -8
- package/dist/server/attr-filter.d.ts.map +0 -1
- package/dist/server/attr-filter.js +0 -30
- package/dist/server/attr-filter.js.map +0 -1
- package/dist/server/dashboard.service.d.ts +0 -70
- package/dist/server/dashboard.service.d.ts.map +0 -1
- package/dist/server/dashboard.service.js +0 -157
- package/dist/server/dashboard.service.js.map +0 -1
- package/dist/server/durable-api.controller.d.ts +0 -44
- package/dist/server/durable-api.controller.d.ts.map +0 -1
- package/dist/server/durable-api.controller.js +0 -197
- package/dist/server/durable-api.controller.js.map +0 -1
- package/dist/server/durable-dashboard.module.d.ts +0 -26
- package/dist/server/durable-dashboard.module.d.ts.map +0 -1
- package/dist/server/durable-dashboard.module.js +0 -60
- package/dist/server/durable-dashboard.module.js.map +0 -1
- package/dist/server/durable-ui.controller.d.ts +0 -19
- package/dist/server/durable-ui.controller.d.ts.map +0 -1
- package/dist/server/durable-ui.controller.js +0 -99
- package/dist/server/durable-ui.controller.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
const __importMetaUrl = require('url').pathToFileURL(__filename).href;
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/server/index.ts
|
|
23
|
+
var index_exports = {};
|
|
24
|
+
__export(index_exports, {
|
|
25
|
+
DASHBOARD_API_PATH: () => DASHBOARD_API_PATH,
|
|
26
|
+
DASHBOARD_BASE_PATH: () => DASHBOARD_BASE_PATH,
|
|
27
|
+
DashboardService: () => DashboardService,
|
|
28
|
+
DurableApiController: () => DurableApiController,
|
|
29
|
+
DurableApiModule: () => DurableApiModule,
|
|
30
|
+
DurableDashboardModule: () => DurableDashboardModule,
|
|
31
|
+
DurableUiController: () => DurableUiController
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
|
|
35
|
+
// src/server/dashboard.service.ts
|
|
36
|
+
var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
|
|
37
|
+
var import_common = require("@nestjs/common");
|
|
38
|
+
var import_rxjs = require("rxjs");
|
|
39
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
40
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
41
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
42
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
43
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
44
|
+
}
|
|
45
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
46
|
+
function _ts_metadata(k, v) {
|
|
47
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
48
|
+
}
|
|
49
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
50
|
+
function _ts_param(paramIndex, decorator) {
|
|
51
|
+
return function(target, key) {
|
|
52
|
+
decorator(target, key, paramIndex);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
__name(_ts_param, "_ts_param");
|
|
56
|
+
var DashboardService = class {
|
|
57
|
+
static {
|
|
58
|
+
__name(this, "DashboardService");
|
|
59
|
+
}
|
|
60
|
+
store;
|
|
61
|
+
engine;
|
|
62
|
+
/** Prometheus counters accumulated from engine events since boot (per process). */
|
|
63
|
+
metricsCollector;
|
|
64
|
+
constructor(store, engine) {
|
|
65
|
+
this.store = store;
|
|
66
|
+
this.engine = engine;
|
|
67
|
+
this.metricsCollector = (0, import_nestjs_durable_core.collectMetrics)(this.engine);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Prometheus-text metrics for a `/metrics` scrape: the event-counters (runs/steps by outcome,
|
|
71
|
+
* per-workflow counts) plus live **backlog gauges** queried at scrape time — `durable_pending_runs`
|
|
72
|
+
* (the dispatch backlog: the key health signal of the dispatch model) and `durable_dead_runs` (DLQ
|
|
73
|
+
* size). Capped per status so the scrape can't load an unbounded result set.
|
|
74
|
+
*/
|
|
75
|
+
async metrics() {
|
|
76
|
+
const cap = 1e4;
|
|
77
|
+
const [pending, running, dead] = await Promise.all([
|
|
78
|
+
this.store.listRuns({
|
|
79
|
+
status: "pending",
|
|
80
|
+
limit: cap
|
|
81
|
+
}),
|
|
82
|
+
this.store.listRuns({
|
|
83
|
+
status: "running",
|
|
84
|
+
limit: cap
|
|
85
|
+
}),
|
|
86
|
+
this.store.listRuns({
|
|
87
|
+
status: "dead",
|
|
88
|
+
limit: cap
|
|
89
|
+
})
|
|
90
|
+
]);
|
|
91
|
+
const gauges = [
|
|
92
|
+
"# TYPE durable_pending_runs gauge",
|
|
93
|
+
`durable_pending_runs ${pending.length}`,
|
|
94
|
+
"# TYPE durable_running_runs gauge",
|
|
95
|
+
`durable_running_runs ${running.length}`,
|
|
96
|
+
"# TYPE durable_dead_runs gauge",
|
|
97
|
+
`durable_dead_runs ${dead.length}`
|
|
98
|
+
];
|
|
99
|
+
const health = await this.engine.workerHealth();
|
|
100
|
+
if (health.length > 0) {
|
|
101
|
+
gauges.push("# TYPE durable_group_queue_depth gauge");
|
|
102
|
+
for (const h of health) {
|
|
103
|
+
gauges.push(`durable_group_queue_depth{group="${h.group}"} ${h.depth}`);
|
|
104
|
+
}
|
|
105
|
+
gauges.push("# TYPE durable_group_live_workers gauge");
|
|
106
|
+
for (const h of health) {
|
|
107
|
+
gauges.push(`durable_group_live_workers{group="${h.group}"} ${h.liveWorkers.length}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return `${this.metricsCollector.prometheus()}${gauges.join("\n")}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
listRuns(query) {
|
|
114
|
+
return this.store.listRuns(query);
|
|
115
|
+
}
|
|
116
|
+
/** Per-group worker health (queue backlog + live worker heartbeats) for the Workers panel. The
|
|
117
|
+
* alert state a row turns red on is `depth > 0 && liveWorkers.length === 0`. */
|
|
118
|
+
workerHealth() {
|
|
119
|
+
return this.engine.workerHealth();
|
|
120
|
+
}
|
|
121
|
+
async getRunDetail(runId) {
|
|
122
|
+
const run = await this.store.getRun(runId);
|
|
123
|
+
if (!run) return null;
|
|
124
|
+
const [timeline, children] = await Promise.all([
|
|
125
|
+
this.store.listCheckpoints(runId),
|
|
126
|
+
this.engine.getRunChildren(runId)
|
|
127
|
+
]);
|
|
128
|
+
return {
|
|
129
|
+
run,
|
|
130
|
+
timeline,
|
|
131
|
+
children
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** Fix-and-replay a dead/failed run with a corrected input — a fresh linked run. Returns its id. */
|
|
135
|
+
retryWithInput(runId, input) {
|
|
136
|
+
return this.engine.retryWithInput(runId, input);
|
|
137
|
+
}
|
|
138
|
+
/** Re-run a failed/incomplete run; completed steps replay from their checkpoints. */
|
|
139
|
+
retry(runId) {
|
|
140
|
+
return this.engine.requeue(runId);
|
|
141
|
+
}
|
|
142
|
+
cancel(runId, opts) {
|
|
143
|
+
return this.engine.cancel(runId, opts);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Apply `retry` or `cancel` to every run matching a filter (status / tag / workflow) — e.g. "retry
|
|
147
|
+
* every `dead` run tagged `type:mel`". Capped at 500 runs per call; runs that can't be acted on
|
|
148
|
+
* (already terminal) are skipped. Returns how many matched and how many the action applied to.
|
|
149
|
+
*/
|
|
150
|
+
async bulk(action, filter, opts) {
|
|
151
|
+
const runs = await this.store.listRuns({
|
|
152
|
+
...filter,
|
|
153
|
+
limit: 500
|
|
154
|
+
});
|
|
155
|
+
let applied = 0;
|
|
156
|
+
for (const r of runs) {
|
|
157
|
+
try {
|
|
158
|
+
if (action === "retry") await this.engine.requeue(r.id);
|
|
159
|
+
else await this.engine.cancel(r.id, opts);
|
|
160
|
+
applied += 1;
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
matched: runs.length,
|
|
166
|
+
applied
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/** Resume a run paused at a `ctx.breakpoint` (the "continue" button). */
|
|
170
|
+
continue(runId) {
|
|
171
|
+
return this.engine.continue(runId);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Deliver a `ctx.webhook()` callback: turn an inbound POST (token + body) into the signal the
|
|
175
|
+
* waiting run is parked on. Returns the run result, or `null` if no run waits on that token (a
|
|
176
|
+
* stale/duplicate callback) — a safe no-op the controller maps to 404.
|
|
177
|
+
*/
|
|
178
|
+
deliverWebhook(token, body) {
|
|
179
|
+
return this.engine.signal(token, body);
|
|
180
|
+
}
|
|
181
|
+
/** Side-effect-free read of a value a run published via `ctx.setEvent` (a live query). */
|
|
182
|
+
getEvent(runId, key) {
|
|
183
|
+
return this.engine.getEvent(runId, key);
|
|
184
|
+
}
|
|
185
|
+
/** Deliver a validated `ctx.onUpdate` to a run; the validator may reject it (see UpdateResult). */
|
|
186
|
+
update(runId, name, arg) {
|
|
187
|
+
return this.engine.update(runId, name, arg);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Live stream of a run's lifecycle events for SSE. Backed by `engine.subscribe`, which — when the
|
|
191
|
+
* transport has a control plane — receives events from EVERY instance, so a dashboard-only pod
|
|
192
|
+
* tails a run executing on a worker pod. Without a control plane it only sees same-process events.
|
|
193
|
+
*/
|
|
194
|
+
streamRun(runId) {
|
|
195
|
+
return new import_rxjs.Observable((subscriber) => {
|
|
196
|
+
const off = this.engine.subscribe((event) => {
|
|
197
|
+
if (event.runId === runId) subscriber.next({
|
|
198
|
+
data: event
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
return () => off();
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
DashboardService = _ts_decorate([
|
|
206
|
+
(0, import_common.Injectable)(),
|
|
207
|
+
_ts_param(0, (0, import_common.Inject)(import_nestjs_durable_core.STATE_STORE)),
|
|
208
|
+
_ts_metadata("design:type", Function),
|
|
209
|
+
_ts_metadata("design:paramtypes", [
|
|
210
|
+
typeof StateStore === "undefined" ? Object : StateStore,
|
|
211
|
+
typeof import_nestjs_durable_core.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core.WorkflowEngine
|
|
212
|
+
])
|
|
213
|
+
], DashboardService);
|
|
214
|
+
|
|
215
|
+
// src/server/durable-api.controller.ts
|
|
216
|
+
var import_common2 = require("@nestjs/common");
|
|
217
|
+
|
|
218
|
+
// src/server/attr-filter.ts
|
|
219
|
+
var ATTR_OPS = /* @__PURE__ */ new Set([
|
|
220
|
+
"eq",
|
|
221
|
+
"ne",
|
|
222
|
+
"gt",
|
|
223
|
+
"gte",
|
|
224
|
+
"lt",
|
|
225
|
+
"lte"
|
|
226
|
+
]);
|
|
227
|
+
function coerce(v) {
|
|
228
|
+
if (v === "true") return true;
|
|
229
|
+
if (v === "false") return false;
|
|
230
|
+
if (v !== "" && !Number.isNaN(Number(v))) return Number(v);
|
|
231
|
+
return v;
|
|
232
|
+
}
|
|
233
|
+
__name(coerce, "coerce");
|
|
234
|
+
function parseAttrFilters(attr) {
|
|
235
|
+
if (!attr) return void 0;
|
|
236
|
+
const raw = Array.isArray(attr) ? attr : [
|
|
237
|
+
attr
|
|
238
|
+
];
|
|
239
|
+
const filters = [];
|
|
240
|
+
for (const entry of raw) {
|
|
241
|
+
const [key, op, ...rest] = entry.split(":");
|
|
242
|
+
if (!key || !ATTR_OPS.has(op) || rest.length === 0) continue;
|
|
243
|
+
filters.push({
|
|
244
|
+
key,
|
|
245
|
+
op,
|
|
246
|
+
value: coerce(rest.join(":"))
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return filters.length ? filters : void 0;
|
|
250
|
+
}
|
|
251
|
+
__name(parseAttrFilters, "parseAttrFilters");
|
|
252
|
+
|
|
253
|
+
// src/server/durable-api.controller.ts
|
|
254
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
255
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
256
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
257
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
258
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
259
|
+
}
|
|
260
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
261
|
+
function _ts_metadata2(k, v) {
|
|
262
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
263
|
+
}
|
|
264
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
265
|
+
function _ts_param2(paramIndex, decorator) {
|
|
266
|
+
return function(target, key) {
|
|
267
|
+
decorator(target, key, paramIndex);
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
__name(_ts_param2, "_ts_param");
|
|
271
|
+
var DurableApiController = class {
|
|
272
|
+
static {
|
|
273
|
+
__name(this, "DurableApiController");
|
|
274
|
+
}
|
|
275
|
+
dashboard;
|
|
276
|
+
constructor(dashboard) {
|
|
277
|
+
this.dashboard = dashboard;
|
|
278
|
+
}
|
|
279
|
+
runs(status, workflow, tag, attr) {
|
|
280
|
+
return this.dashboard.listRuns({
|
|
281
|
+
status,
|
|
282
|
+
workflow,
|
|
283
|
+
tag,
|
|
284
|
+
attributes: parseAttrFilters(attr)
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/** Prometheus-text metrics (runs/steps by outcome, per-workflow counts) for a scrape. */
|
|
288
|
+
metrics() {
|
|
289
|
+
return this.dashboard.metrics();
|
|
290
|
+
}
|
|
291
|
+
/** Per-group worker health (queue backlog + live worker heartbeats) for the Workers panel. */
|
|
292
|
+
workers() {
|
|
293
|
+
return this.dashboard.workerHealth();
|
|
294
|
+
}
|
|
295
|
+
async run(id) {
|
|
296
|
+
const detail = await this.dashboard.getRunDetail(id);
|
|
297
|
+
if (!detail) throw new import_common2.NotFoundException(`run ${id} not found`);
|
|
298
|
+
return detail;
|
|
299
|
+
}
|
|
300
|
+
/** Server-Sent Events stream of a run's live lifecycle events — the dashboard tails it instead
|
|
301
|
+
* of polling. Cross-pod when the transport has a control plane (see DashboardService.streamRun). */
|
|
302
|
+
stream(id) {
|
|
303
|
+
return this.dashboard.streamRun(id);
|
|
304
|
+
}
|
|
305
|
+
retry(id) {
|
|
306
|
+
return this.dashboard.retry(id);
|
|
307
|
+
}
|
|
308
|
+
/** Fix-and-replay: re-run a dead/failed run with a corrected input (a fresh linked run). */
|
|
309
|
+
retryWithInput(id, body) {
|
|
310
|
+
return this.dashboard.retryWithInput(id, body?.input);
|
|
311
|
+
}
|
|
312
|
+
/** Bulk retry/cancel every run matching a filter (status / tag / workflow). */
|
|
313
|
+
bulk(action, status, tag, workflow, attr, compensate) {
|
|
314
|
+
return this.dashboard.bulk(action === "cancel" ? "cancel" : "retry", {
|
|
315
|
+
status,
|
|
316
|
+
tag,
|
|
317
|
+
workflow,
|
|
318
|
+
attributes: parseAttrFilters(attr)
|
|
319
|
+
}, {
|
|
320
|
+
compensate: compensate === "true"
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
async cancel(id, compensate) {
|
|
324
|
+
const result = await this.dashboard.cancel(id, {
|
|
325
|
+
compensate: compensate === "true"
|
|
326
|
+
});
|
|
327
|
+
if (!result) throw new import_common2.NotFoundException(`run ${id} not found`);
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
async continue(id) {
|
|
331
|
+
const result = await this.dashboard.continue(id);
|
|
332
|
+
if (!result) throw new import_common2.NotFoundException(`run ${id} is not paused at a breakpoint`);
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Public callback endpoint for `ctx.webhook()`: a third party POSTs here (the url handed to it),
|
|
337
|
+
* and the body resumes the waiting run. NOTE: this is reachable by external systems — protect it
|
|
338
|
+
* by treating the token as a secret (it embeds runId:seq) and/or fronting it with signature
|
|
339
|
+
* verification in your own middleware.
|
|
340
|
+
*/
|
|
341
|
+
async webhook(token, body) {
|
|
342
|
+
const result = await this.dashboard.deliverWebhook(token, body);
|
|
343
|
+
if (!result) throw new import_common2.NotFoundException(`no run is waiting on webhook ${token}`);
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
346
|
+
/** Live query: the latest value a run published for `key` via `ctx.setEvent` (no side effect). */
|
|
347
|
+
event(id, key) {
|
|
348
|
+
return this.dashboard.getEvent(id, key);
|
|
349
|
+
}
|
|
350
|
+
/** Deliver a validated `ctx.onUpdate` to a run; the body is the update argument. */
|
|
351
|
+
update(id, name, body) {
|
|
352
|
+
return this.dashboard.update(id, name, body);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
_ts_decorate2([
|
|
356
|
+
(0, import_common2.Get)("runs"),
|
|
357
|
+
_ts_param2(0, (0, import_common2.Query)("status")),
|
|
358
|
+
_ts_param2(1, (0, import_common2.Query)("workflow")),
|
|
359
|
+
_ts_param2(2, (0, import_common2.Query)("tag")),
|
|
360
|
+
_ts_param2(3, (0, import_common2.Query)("attr")),
|
|
361
|
+
_ts_metadata2("design:type", Function),
|
|
362
|
+
_ts_metadata2("design:paramtypes", [
|
|
363
|
+
typeof RunStatus === "undefined" ? Object : RunStatus,
|
|
364
|
+
String,
|
|
365
|
+
String,
|
|
366
|
+
Object
|
|
367
|
+
]),
|
|
368
|
+
_ts_metadata2("design:returntype", void 0)
|
|
369
|
+
], DurableApiController.prototype, "runs", null);
|
|
370
|
+
_ts_decorate2([
|
|
371
|
+
(0, import_common2.Get)("metrics"),
|
|
372
|
+
(0, import_common2.Header)("Content-Type", "text/plain; version=0.0.4"),
|
|
373
|
+
_ts_metadata2("design:type", Function),
|
|
374
|
+
_ts_metadata2("design:paramtypes", []),
|
|
375
|
+
_ts_metadata2("design:returntype", void 0)
|
|
376
|
+
], DurableApiController.prototype, "metrics", null);
|
|
377
|
+
_ts_decorate2([
|
|
378
|
+
(0, import_common2.Get)("workers"),
|
|
379
|
+
_ts_metadata2("design:type", Function),
|
|
380
|
+
_ts_metadata2("design:paramtypes", []),
|
|
381
|
+
_ts_metadata2("design:returntype", void 0)
|
|
382
|
+
], DurableApiController.prototype, "workers", null);
|
|
383
|
+
_ts_decorate2([
|
|
384
|
+
(0, import_common2.Get)("runs/:id"),
|
|
385
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
386
|
+
_ts_metadata2("design:type", Function),
|
|
387
|
+
_ts_metadata2("design:paramtypes", [
|
|
388
|
+
String
|
|
389
|
+
]),
|
|
390
|
+
_ts_metadata2("design:returntype", Promise)
|
|
391
|
+
], DurableApiController.prototype, "run", null);
|
|
392
|
+
_ts_decorate2([
|
|
393
|
+
(0, import_common2.Sse)("runs/:id/stream"),
|
|
394
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
395
|
+
_ts_metadata2("design:type", Function),
|
|
396
|
+
_ts_metadata2("design:paramtypes", [
|
|
397
|
+
String
|
|
398
|
+
]),
|
|
399
|
+
_ts_metadata2("design:returntype", void 0)
|
|
400
|
+
], DurableApiController.prototype, "stream", null);
|
|
401
|
+
_ts_decorate2([
|
|
402
|
+
(0, import_common2.Post)("runs/:id/retry"),
|
|
403
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
404
|
+
_ts_metadata2("design:type", Function),
|
|
405
|
+
_ts_metadata2("design:paramtypes", [
|
|
406
|
+
String
|
|
407
|
+
]),
|
|
408
|
+
_ts_metadata2("design:returntype", void 0)
|
|
409
|
+
], DurableApiController.prototype, "retry", null);
|
|
410
|
+
_ts_decorate2([
|
|
411
|
+
(0, import_common2.Post)("runs/:id/retry-with-input"),
|
|
412
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
413
|
+
_ts_param2(1, (0, import_common2.Body)()),
|
|
414
|
+
_ts_metadata2("design:type", Function),
|
|
415
|
+
_ts_metadata2("design:paramtypes", [
|
|
416
|
+
String,
|
|
417
|
+
Object
|
|
418
|
+
]),
|
|
419
|
+
_ts_metadata2("design:returntype", void 0)
|
|
420
|
+
], DurableApiController.prototype, "retryWithInput", null);
|
|
421
|
+
_ts_decorate2([
|
|
422
|
+
(0, import_common2.Post)("bulk/:action"),
|
|
423
|
+
_ts_param2(0, (0, import_common2.Param)("action")),
|
|
424
|
+
_ts_param2(1, (0, import_common2.Query)("status")),
|
|
425
|
+
_ts_param2(2, (0, import_common2.Query)("tag")),
|
|
426
|
+
_ts_param2(3, (0, import_common2.Query)("workflow")),
|
|
427
|
+
_ts_param2(4, (0, import_common2.Query)("attr")),
|
|
428
|
+
_ts_param2(5, (0, import_common2.Query)("compensate")),
|
|
429
|
+
_ts_metadata2("design:type", Function),
|
|
430
|
+
_ts_metadata2("design:paramtypes", [
|
|
431
|
+
String,
|
|
432
|
+
typeof RunStatus === "undefined" ? Object : RunStatus,
|
|
433
|
+
String,
|
|
434
|
+
String,
|
|
435
|
+
Object,
|
|
436
|
+
String
|
|
437
|
+
]),
|
|
438
|
+
_ts_metadata2("design:returntype", void 0)
|
|
439
|
+
], DurableApiController.prototype, "bulk", null);
|
|
440
|
+
_ts_decorate2([
|
|
441
|
+
(0, import_common2.Post)("runs/:id/cancel"),
|
|
442
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
443
|
+
_ts_param2(1, (0, import_common2.Query)("compensate")),
|
|
444
|
+
_ts_metadata2("design:type", Function),
|
|
445
|
+
_ts_metadata2("design:paramtypes", [
|
|
446
|
+
String,
|
|
447
|
+
String
|
|
448
|
+
]),
|
|
449
|
+
_ts_metadata2("design:returntype", Promise)
|
|
450
|
+
], DurableApiController.prototype, "cancel", null);
|
|
451
|
+
_ts_decorate2([
|
|
452
|
+
(0, import_common2.Post)("runs/:id/continue"),
|
|
453
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
454
|
+
_ts_metadata2("design:type", Function),
|
|
455
|
+
_ts_metadata2("design:paramtypes", [
|
|
456
|
+
String
|
|
457
|
+
]),
|
|
458
|
+
_ts_metadata2("design:returntype", Promise)
|
|
459
|
+
], DurableApiController.prototype, "continue", null);
|
|
460
|
+
_ts_decorate2([
|
|
461
|
+
(0, import_common2.Post)("webhooks/:token"),
|
|
462
|
+
_ts_param2(0, (0, import_common2.Param)("token")),
|
|
463
|
+
_ts_param2(1, (0, import_common2.Body)()),
|
|
464
|
+
_ts_metadata2("design:type", Function),
|
|
465
|
+
_ts_metadata2("design:paramtypes", [
|
|
466
|
+
String,
|
|
467
|
+
Object
|
|
468
|
+
]),
|
|
469
|
+
_ts_metadata2("design:returntype", Promise)
|
|
470
|
+
], DurableApiController.prototype, "webhook", null);
|
|
471
|
+
_ts_decorate2([
|
|
472
|
+
(0, import_common2.Get)("runs/:id/events/:key"),
|
|
473
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
474
|
+
_ts_param2(1, (0, import_common2.Param)("key")),
|
|
475
|
+
_ts_metadata2("design:type", Function),
|
|
476
|
+
_ts_metadata2("design:paramtypes", [
|
|
477
|
+
String,
|
|
478
|
+
String
|
|
479
|
+
]),
|
|
480
|
+
_ts_metadata2("design:returntype", void 0)
|
|
481
|
+
], DurableApiController.prototype, "event", null);
|
|
482
|
+
_ts_decorate2([
|
|
483
|
+
(0, import_common2.Post)("runs/:id/updates/:name"),
|
|
484
|
+
_ts_param2(0, (0, import_common2.Param)("id")),
|
|
485
|
+
_ts_param2(1, (0, import_common2.Param)("name")),
|
|
486
|
+
_ts_param2(2, (0, import_common2.Body)()),
|
|
487
|
+
_ts_metadata2("design:type", Function),
|
|
488
|
+
_ts_metadata2("design:paramtypes", [
|
|
489
|
+
String,
|
|
490
|
+
String,
|
|
491
|
+
Object
|
|
492
|
+
]),
|
|
493
|
+
_ts_metadata2("design:returntype", void 0)
|
|
494
|
+
], DurableApiController.prototype, "update", null);
|
|
495
|
+
DurableApiController = _ts_decorate2([
|
|
496
|
+
(0, import_common2.Controller)(),
|
|
497
|
+
_ts_metadata2("design:type", Function),
|
|
498
|
+
_ts_metadata2("design:paramtypes", [
|
|
499
|
+
typeof DashboardService === "undefined" ? Object : DashboardService
|
|
500
|
+
])
|
|
501
|
+
], DurableApiController);
|
|
502
|
+
|
|
503
|
+
// src/server/durable-dashboard.module.ts
|
|
504
|
+
var import_common4 = require("@nestjs/common");
|
|
505
|
+
var import_core = require("@nestjs/core");
|
|
506
|
+
|
|
507
|
+
// src/server/durable-ui.controller.ts
|
|
508
|
+
var import_node_fs = require("fs");
|
|
509
|
+
var import_node_path = require("path");
|
|
510
|
+
var import_node_url = require("url");
|
|
511
|
+
var import_common3 = require("@nestjs/common");
|
|
512
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
513
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
514
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
515
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
516
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
517
|
+
}
|
|
518
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
519
|
+
function _ts_metadata3(k, v) {
|
|
520
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
521
|
+
}
|
|
522
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
523
|
+
function _ts_param3(paramIndex, decorator) {
|
|
524
|
+
return function(target, key) {
|
|
525
|
+
decorator(target, key, paramIndex);
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
__name(_ts_param3, "_ts_param");
|
|
529
|
+
var DASHBOARD_BASE_PATH = Symbol("DASHBOARD_BASE_PATH");
|
|
530
|
+
var DASHBOARD_API_PATH = Symbol("DASHBOARD_API_PATH");
|
|
531
|
+
var BUILD_BASE = "/durable";
|
|
532
|
+
function spaDir() {
|
|
533
|
+
return (0, import_node_url.fileURLToPath)(new URL("../spa", __importMetaUrl));
|
|
534
|
+
}
|
|
535
|
+
__name(spaDir, "spaDir");
|
|
536
|
+
var CONTENT_TYPES = {
|
|
537
|
+
".js": "text/javascript; charset=utf-8",
|
|
538
|
+
".css": "text/css; charset=utf-8",
|
|
539
|
+
".map": "application/json; charset=utf-8",
|
|
540
|
+
".svg": "image/svg+xml",
|
|
541
|
+
".json": "application/json; charset=utf-8",
|
|
542
|
+
".woff2": "font/woff2",
|
|
543
|
+
".ico": "image/x-icon"
|
|
544
|
+
};
|
|
545
|
+
var DurableUiController = class {
|
|
546
|
+
static {
|
|
547
|
+
__name(this, "DurableUiController");
|
|
548
|
+
}
|
|
549
|
+
basePath;
|
|
550
|
+
apiBasePath;
|
|
551
|
+
dir = spaDir();
|
|
552
|
+
constructor(basePath, apiBasePath) {
|
|
553
|
+
this.basePath = basePath;
|
|
554
|
+
this.apiBasePath = apiBasePath;
|
|
555
|
+
}
|
|
556
|
+
// index.html references hash-named bundles, so it MUST NOT be cached (stale bundle = the
|
|
557
|
+
// classic "stuck loading after a deploy"). The hashed assets below are immutable.
|
|
558
|
+
index() {
|
|
559
|
+
const indexPath = (0, import_node_path.join)(this.dir, "index.html");
|
|
560
|
+
if (!(0, import_node_fs.existsSync)(indexPath)) {
|
|
561
|
+
throw new import_common3.NotFoundException("Dashboard is not built. Run the package build.");
|
|
562
|
+
}
|
|
563
|
+
const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
564
|
+
const inject = `<script>window.__DURABLE_BASE__='${this.basePath}';window.__DURABLE_API__='${this.apiBasePath}';</script>`;
|
|
565
|
+
return html.includes("</head>") ? html.replace("</head>", `${inject}</head>`) : inject + html;
|
|
566
|
+
}
|
|
567
|
+
asset(file) {
|
|
568
|
+
const safe = (0, import_node_path.basename)(file);
|
|
569
|
+
if (safe !== file) throw new import_common3.NotFoundException();
|
|
570
|
+
const root = (0, import_node_path.resolve)(this.dir, "assets");
|
|
571
|
+
const assetPath = (0, import_node_path.resolve)(root, safe);
|
|
572
|
+
if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
|
|
573
|
+
throw new import_common3.NotFoundException();
|
|
574
|
+
}
|
|
575
|
+
const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
|
|
576
|
+
return new import_common3.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
|
|
577
|
+
type
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
_ts_decorate3([
|
|
582
|
+
(0, import_common3.Get)(),
|
|
583
|
+
(0, import_common3.Header)("Content-Type", "text/html; charset=utf-8"),
|
|
584
|
+
(0, import_common3.Header)("Cache-Control", "no-store, must-revalidate"),
|
|
585
|
+
_ts_metadata3("design:type", Function),
|
|
586
|
+
_ts_metadata3("design:paramtypes", []),
|
|
587
|
+
_ts_metadata3("design:returntype", String)
|
|
588
|
+
], DurableUiController.prototype, "index", null);
|
|
589
|
+
_ts_decorate3([
|
|
590
|
+
(0, import_common3.Get)("assets/:file"),
|
|
591
|
+
(0, import_common3.Header)("Cache-Control", "public, max-age=31536000, immutable"),
|
|
592
|
+
_ts_param3(0, (0, import_common3.Param)("file")),
|
|
593
|
+
_ts_metadata3("design:type", Function),
|
|
594
|
+
_ts_metadata3("design:paramtypes", [
|
|
595
|
+
String
|
|
596
|
+
]),
|
|
597
|
+
_ts_metadata3("design:returntype", typeof import_common3.StreamableFile === "undefined" ? Object : import_common3.StreamableFile)
|
|
598
|
+
], DurableUiController.prototype, "asset", null);
|
|
599
|
+
DurableUiController = _ts_decorate3([
|
|
600
|
+
(0, import_common3.Controller)(),
|
|
601
|
+
_ts_param3(0, (0, import_common3.Inject)(DASHBOARD_BASE_PATH)),
|
|
602
|
+
_ts_param3(1, (0, import_common3.Inject)(DASHBOARD_API_PATH)),
|
|
603
|
+
_ts_metadata3("design:type", Function),
|
|
604
|
+
_ts_metadata3("design:paramtypes", [
|
|
605
|
+
String,
|
|
606
|
+
String
|
|
607
|
+
])
|
|
608
|
+
], DurableUiController);
|
|
609
|
+
|
|
610
|
+
// src/server/durable-dashboard.module.ts
|
|
611
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
612
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
613
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
614
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
615
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
616
|
+
}
|
|
617
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
618
|
+
function normalize(path) {
|
|
619
|
+
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
|
620
|
+
}
|
|
621
|
+
__name(normalize, "normalize");
|
|
622
|
+
var DurableApiModule = class {
|
|
623
|
+
static {
|
|
624
|
+
__name(this, "DurableApiModule");
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
DurableApiModule = _ts_decorate4([
|
|
628
|
+
(0, import_common4.Module)({
|
|
629
|
+
controllers: [
|
|
630
|
+
DurableApiController
|
|
631
|
+
],
|
|
632
|
+
providers: [
|
|
633
|
+
DashboardService
|
|
634
|
+
],
|
|
635
|
+
exports: [
|
|
636
|
+
DashboardService
|
|
637
|
+
]
|
|
638
|
+
})
|
|
639
|
+
], DurableApiModule);
|
|
640
|
+
var DurableDashboardModule = class _DurableDashboardModule {
|
|
641
|
+
static {
|
|
642
|
+
__name(this, "DurableDashboardModule");
|
|
643
|
+
}
|
|
644
|
+
static forRoot(options = {}) {
|
|
645
|
+
const basePath = normalize(options.basePath ?? "/durable");
|
|
646
|
+
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
647
|
+
return {
|
|
648
|
+
module: _DurableDashboardModule,
|
|
649
|
+
imports: [
|
|
650
|
+
DurableApiModule,
|
|
651
|
+
import_core.RouterModule.register([
|
|
652
|
+
{
|
|
653
|
+
path: basePath,
|
|
654
|
+
module: _DurableDashboardModule
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
path: apiBasePath,
|
|
658
|
+
module: DurableApiModule
|
|
659
|
+
}
|
|
660
|
+
])
|
|
661
|
+
],
|
|
662
|
+
controllers: [
|
|
663
|
+
DurableUiController
|
|
664
|
+
],
|
|
665
|
+
providers: [
|
|
666
|
+
{
|
|
667
|
+
provide: DASHBOARD_BASE_PATH,
|
|
668
|
+
useValue: basePath
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
provide: DASHBOARD_API_PATH,
|
|
672
|
+
useValue: apiBasePath
|
|
673
|
+
}
|
|
674
|
+
],
|
|
675
|
+
// Re-export the API module so its DashboardService reaches importers (e.g. flip's own controllers).
|
|
676
|
+
exports: [
|
|
677
|
+
DurableApiModule
|
|
678
|
+
]
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
DurableDashboardModule = _ts_decorate4([
|
|
683
|
+
(0, import_common4.Module)({})
|
|
684
|
+
], DurableDashboardModule);
|
|
685
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
686
|
+
0 && (module.exports = {
|
|
687
|
+
DASHBOARD_API_PATH,
|
|
688
|
+
DASHBOARD_BASE_PATH,
|
|
689
|
+
DashboardService,
|
|
690
|
+
DurableApiController,
|
|
691
|
+
DurableApiModule,
|
|
692
|
+
DurableDashboardModule,
|
|
693
|
+
DurableUiController
|
|
694
|
+
});
|
|
695
|
+
//# sourceMappingURL=index.cjs.map
|