@dudousxd/nestjs-durable-dashboard 0.56.0 → 0.58.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/dist/server/index.cjs +1203 -98
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +229 -9
- package/dist/server/index.d.ts +229 -9
- package/dist/server/index.js +1193 -103
- package/dist/server/index.js.map +1 -1
- package/dist/spa/assets/{bench-BXhQP2W7.js → bench--sTow8cG.js} +1 -1
- package/dist/spa/assets/index-BA5RJf7A.css +1 -0
- package/dist/spa/assets/{index-C6Ih-K3x.js → index-DG9crD2T.js} +1 -1
- package/dist/spa/assets/index-L85j6H4X.js +66 -0
- package/dist/spa/assets/{preview-ekPMzj7t.js → preview-b6LbKDyY.js} +1 -1
- package/dist/spa/bench.html +3 -3
- package/dist/spa/index.html +3 -3
- package/dist/spa/preview.html +3 -3
- package/package.json +2 -2
- package/dist/spa/assets/index-D_rIGnea.css +0 -1
- package/dist/spa/assets/index-DwGUovEa.js +0 -66
package/dist/server/index.cjs
CHANGED
|
@@ -32,26 +32,41 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
32
32
|
// src/server/index.ts
|
|
33
33
|
var index_exports = {};
|
|
34
34
|
__export(index_exports, {
|
|
35
|
+
AVIARY_CONSOLES_SLOT: () => AVIARY_CONSOLES_SLOT,
|
|
35
36
|
CONSOLE_AUTHORIZE_DECIDE: () => CONSOLE_AUTHORIZE_DECIDE,
|
|
36
37
|
CONSOLE_AUTHORIZE_MISSING_WARNING: () => CONSOLE_AUTHORIZE_MISSING_WARNING,
|
|
37
38
|
CONSOLE_GATE: () => CONSOLE_GATE,
|
|
38
39
|
CONSOLE_PAGE_METADATA: () => CONSOLE_PAGE_METADATA,
|
|
40
|
+
CONSOLE_PROBE_TIMEOUT_MS: () => CONSOLE_PROBE_TIMEOUT_MS,
|
|
41
|
+
CONSOLE_PUBLIC_METADATA: () => CONSOLE_PUBLIC_METADATA,
|
|
39
42
|
ConsoleAccessDenied: () => ConsoleAccessDenied,
|
|
40
43
|
ConsoleAuthorizeFilter: () => ConsoleAuthorizeFilter,
|
|
41
44
|
ConsoleAuthorizeGuard: () => ConsoleAuthorizeGuard,
|
|
42
45
|
ConsolePage: () => ConsolePage,
|
|
46
|
+
ConsolePublic: () => ConsolePublic,
|
|
43
47
|
DASHBOARD_API_PATH: () => DASHBOARD_API_PATH,
|
|
44
48
|
DASHBOARD_BASE_PATH: () => DASHBOARD_BASE_PATH,
|
|
49
|
+
DEV_TOOLS_SLOT: () => DEV_TOOLS_SLOT,
|
|
50
|
+
DURABLE_CONSOLE_ID: () => DURABLE_CONSOLE_ID,
|
|
51
|
+
DURABLE_DASHBOARD_CONFIG_ID: () => DURABLE_DASHBOARD_CONFIG_ID,
|
|
45
52
|
DashboardService: () => DashboardService,
|
|
46
53
|
DurableApiController: () => DurableApiController,
|
|
47
54
|
DurableApiControllerBase: () => DurableApiControllerBase,
|
|
48
55
|
DurableApiModule: () => DurableApiModule,
|
|
56
|
+
DurableConsoleRegistration: () => DurableConsoleRegistration,
|
|
57
|
+
DurableConsolesController: () => DurableConsolesController,
|
|
49
58
|
DurableDashboardModule: () => DurableDashboardModule,
|
|
59
|
+
DurableDevToolsRegistration: () => DurableDevToolsRegistration,
|
|
50
60
|
DurableUiController: () => DurableUiController,
|
|
51
61
|
DurableUiControllerBase: () => DurableUiControllerBase,
|
|
62
|
+
MAX_RUN_IDS: () => MAX_RUN_IDS,
|
|
52
63
|
UseConsoleAuthorize: () => UseConsoleAuthorize,
|
|
64
|
+
anyAuthorize: () => anyAuthorize,
|
|
53
65
|
authorizeByToken: () => authorizeByToken,
|
|
66
|
+
durableDevTools: () => durableDevTools,
|
|
67
|
+
listVisibleConsoles: () => listVisibleConsoles,
|
|
54
68
|
normalizeConsoleResult: () => normalizeConsoleResult,
|
|
69
|
+
registerAviaryConsole: () => registerAviaryConsole,
|
|
55
70
|
resolveConsoleAuthorize: () => resolveConsoleAuthorize
|
|
56
71
|
});
|
|
57
72
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -91,9 +106,12 @@ var CONSOLE_GATE = Symbol.for("@dudousxd/aviary:console-gate");
|
|
|
91
106
|
var PACKAGE = "@dudousxd/nestjs-durable-dashboard";
|
|
92
107
|
var MODULE = "DurableDashboardModule";
|
|
93
108
|
var CONSOLE_AUTHORIZE_MISSING_WARNING = `[${PACKAGE}] console has no \`authorize\` configured: it is open outside production and denies every request in production. Set \`authorize\` in ${MODULE}.forRoot().`;
|
|
94
|
-
var allow = /* @__PURE__ */ __name(() =>
|
|
109
|
+
var allow = /* @__PURE__ */ __name((caller) => caller !== void 0 && caller !== "" ? {
|
|
110
|
+
allowed: true,
|
|
111
|
+
caller
|
|
112
|
+
} : {
|
|
95
113
|
allowed: true
|
|
96
|
-
}
|
|
114
|
+
}, "allow");
|
|
97
115
|
var forbidden = /* @__PURE__ */ __name(() => ({
|
|
98
116
|
allowed: false,
|
|
99
117
|
reason: "forbidden"
|
|
@@ -133,7 +151,9 @@ function normalizeConsoleResult(result) {
|
|
|
133
151
|
redirectTo: shape.redirectTo
|
|
134
152
|
};
|
|
135
153
|
}
|
|
136
|
-
if (shape.allowed === true)
|
|
154
|
+
if (shape.allowed === true) {
|
|
155
|
+
return allow(typeof shape.caller === "string" ? shape.caller : void 0);
|
|
156
|
+
}
|
|
137
157
|
return shape.reason === "unauthenticated" ? unauthenticated() : forbidden();
|
|
138
158
|
}
|
|
139
159
|
__name(normalizeConsoleResult, "normalizeConsoleResult");
|
|
@@ -216,11 +236,11 @@ function classDecider(moduleRef) {
|
|
|
216
236
|
}
|
|
217
237
|
__name(classDecider, "classDecider");
|
|
218
238
|
async function resolveConsoleAuthorize(authorize, moduleRef, options = {}) {
|
|
219
|
-
const
|
|
239
|
+
const logger3 = options.logger ?? new import_common.Logger(MODULE);
|
|
220
240
|
if (authorize === void 0) {
|
|
221
|
-
if (options.warnIfMissing !== false)
|
|
241
|
+
if (options.warnIfMissing !== false) logger3.warn(CONSOLE_AUTHORIZE_MISSING_WARNING);
|
|
222
242
|
const production = isProduction();
|
|
223
|
-
return async () => production ? forbidden() : allow();
|
|
243
|
+
return async () => production ? forbidden() : allow("dev-open");
|
|
224
244
|
}
|
|
225
245
|
let decide;
|
|
226
246
|
if (typeof authorize === "string") {
|
|
@@ -247,7 +267,7 @@ async function resolveConsoleAuthorize(authorize, moduleRef, options = {}) {
|
|
|
247
267
|
try {
|
|
248
268
|
return await decide(context);
|
|
249
269
|
} catch (error) {
|
|
250
|
-
|
|
270
|
+
logger3.warn(`console \`authorize\` threw, denying the request: ${error instanceof Error ? error.message : String(error)}`);
|
|
251
271
|
return forbidden();
|
|
252
272
|
}
|
|
253
273
|
};
|
|
@@ -260,10 +280,16 @@ function authorizeByToken(options) {
|
|
|
260
280
|
throw new Error("authorizeByToken: `token` is empty; set it (e.g. from an env var).");
|
|
261
281
|
}
|
|
262
282
|
const expected = sha256(token);
|
|
283
|
+
const caller = `token:${expected.toString("hex").slice(0, 12)}`;
|
|
263
284
|
return (context) => {
|
|
264
285
|
const header = context.switchToHttp().getRequest()?.headers?.authorization;
|
|
265
286
|
const match = typeof header === "string" ? /^Bearer\s+(.+)$/i.exec(header.trim()) : null;
|
|
266
|
-
if (match?.[1] && (0, import_node_crypto.timingSafeEqual)(sha256(match[1]), expected))
|
|
287
|
+
if (match?.[1] && (0, import_node_crypto.timingSafeEqual)(sha256(match[1]), expected)) {
|
|
288
|
+
return {
|
|
289
|
+
allowed: true,
|
|
290
|
+
caller
|
|
291
|
+
};
|
|
292
|
+
}
|
|
267
293
|
return {
|
|
268
294
|
allowed: false,
|
|
269
295
|
reason: "unauthenticated"
|
|
@@ -271,6 +297,48 @@ function authorizeByToken(options) {
|
|
|
271
297
|
};
|
|
272
298
|
}
|
|
273
299
|
__name(authorizeByToken, "authorizeByToken");
|
|
300
|
+
function anyAuthorize(...forms) {
|
|
301
|
+
if (forms.length === 0) throw new Error("anyAuthorize: pass at least one authorize form.");
|
|
302
|
+
let AnyConsoleAuthorizer = class AnyConsoleAuthorizer {
|
|
303
|
+
static {
|
|
304
|
+
__name(this, "AnyConsoleAuthorizer");
|
|
305
|
+
}
|
|
306
|
+
moduleRef;
|
|
307
|
+
#decides;
|
|
308
|
+
constructor(moduleRef) {
|
|
309
|
+
this.moduleRef = moduleRef;
|
|
310
|
+
}
|
|
311
|
+
async authorize(context) {
|
|
312
|
+
this.#decides ??= Promise.all(forms.map((form) => resolveConsoleAuthorize(form, this.moduleRef, {
|
|
313
|
+
warnIfMissing: false
|
|
314
|
+
})));
|
|
315
|
+
this.#decides.catch(() => {
|
|
316
|
+
this.#decides = void 0;
|
|
317
|
+
});
|
|
318
|
+
let unauthenticated2;
|
|
319
|
+
for (const decide of await this.#decides) {
|
|
320
|
+
const decision = await decide(context);
|
|
321
|
+
if (decision.allowed) return decision;
|
|
322
|
+
if (decision.reason === "unauthenticated") unauthenticated2 ??= decision;
|
|
323
|
+
}
|
|
324
|
+
if (unauthenticated2 === void 0) return {
|
|
325
|
+
allowed: false,
|
|
326
|
+
reason: "forbidden"
|
|
327
|
+
};
|
|
328
|
+
return "redirectTo" in unauthenticated2 && unauthenticated2.redirectTo !== void 0 ? {
|
|
329
|
+
redirectTo: unauthenticated2.redirectTo
|
|
330
|
+
} : {
|
|
331
|
+
allowed: false,
|
|
332
|
+
reason: "unauthenticated"
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
Reflect.defineMetadata("design:paramtypes", [
|
|
337
|
+
import_core.ModuleRef
|
|
338
|
+
], AnyConsoleAuthorizer);
|
|
339
|
+
return AnyConsoleAuthorizer;
|
|
340
|
+
}
|
|
341
|
+
__name(anyAuthorize, "anyAuthorize");
|
|
274
342
|
var CONSOLE_AUTHORIZE_DECIDE = Symbol(`${PACKAGE}:console-authorize`);
|
|
275
343
|
var CONSOLE_PAGE_METADATA = `${PACKAGE}:console-page`;
|
|
276
344
|
var ConsolePage = /* @__PURE__ */ __name(() => (target) => {
|
|
@@ -282,7 +350,7 @@ var ConsoleAccessDenied = class extends import_common.HttpException {
|
|
|
282
350
|
}
|
|
283
351
|
decision;
|
|
284
352
|
page;
|
|
285
|
-
constructor(decision,
|
|
353
|
+
constructor(decision, page2) {
|
|
286
354
|
const unauthenticated2 = decision.reason === "unauthenticated";
|
|
287
355
|
super(unauthenticated2 ? {
|
|
288
356
|
error: "unauthenticated",
|
|
@@ -291,9 +359,13 @@ var ConsoleAccessDenied = class extends import_common.HttpException {
|
|
|
291
359
|
} : {}
|
|
292
360
|
} : {
|
|
293
361
|
error: "forbidden"
|
|
294
|
-
}, unauthenticated2 ? 401 : 403), this.decision = decision, this.page =
|
|
362
|
+
}, unauthenticated2 ? 401 : 403), this.decision = decision, this.page = page2;
|
|
295
363
|
}
|
|
296
364
|
};
|
|
365
|
+
var CONSOLE_PUBLIC_METADATA = `${PACKAGE}:console-public`;
|
|
366
|
+
var ConsolePublic = /* @__PURE__ */ __name(() => (_target, _key, descriptor) => {
|
|
367
|
+
Reflect.defineMetadata(CONSOLE_PUBLIC_METADATA, true, descriptor.value);
|
|
368
|
+
}, "ConsolePublic");
|
|
297
369
|
var ConsoleAuthorizeGuard = class {
|
|
298
370
|
static {
|
|
299
371
|
__name(this, "ConsoleAuthorizeGuard");
|
|
@@ -303,6 +375,7 @@ var ConsoleAuthorizeGuard = class {
|
|
|
303
375
|
this.decide = decide;
|
|
304
376
|
}
|
|
305
377
|
async canActivate(context) {
|
|
378
|
+
if (Reflect.getMetadata(CONSOLE_PUBLIC_METADATA, context.getHandler()) === true) return true;
|
|
306
379
|
const decision = await this.decide(context);
|
|
307
380
|
if (decision.allowed) return true;
|
|
308
381
|
throw new ConsoleAccessDenied(decision, isPageNavigation(context));
|
|
@@ -338,12 +411,12 @@ var ConsoleAuthorizeFilter = class {
|
|
|
338
411
|
catch(exception, host) {
|
|
339
412
|
const adapter = this.adapterHost.httpAdapter;
|
|
340
413
|
const response = host.switchToHttp().getResponse();
|
|
341
|
-
const { decision, page } = exception;
|
|
342
|
-
if (
|
|
414
|
+
const { decision, page: page2 } = exception;
|
|
415
|
+
if (page2 && decision.redirectTo) {
|
|
343
416
|
adapter.redirect(response, 302, decision.redirectTo);
|
|
344
417
|
return;
|
|
345
418
|
}
|
|
346
|
-
if (
|
|
419
|
+
if (page2) {
|
|
347
420
|
const forbiddenPage = decision.reason === "forbidden";
|
|
348
421
|
adapter.setHeader(response, "Content-Type", "text/html; charset=utf-8");
|
|
349
422
|
adapter.reply(response, forbiddenPage ? DENIED_PAGE : SIGN_IN_PAGE, forbiddenPage ? 403 : 401);
|
|
@@ -415,7 +488,7 @@ var DashboardService = class {
|
|
|
415
488
|
*/
|
|
416
489
|
controlPlane() {
|
|
417
490
|
if (!this.store || !this.engine) {
|
|
418
|
-
throw new
|
|
491
|
+
throw new import_common2.NotImplementedException("This durable dashboard operation requires the control plane (not available on a tenant deployment).");
|
|
419
492
|
}
|
|
420
493
|
return {
|
|
421
494
|
store: this.store,
|
|
@@ -515,31 +588,31 @@ var DashboardService = class {
|
|
|
515
588
|
async workerHealth() {
|
|
516
589
|
return this.gateway.workerHealth();
|
|
517
590
|
}
|
|
518
|
-
getRunDetail(
|
|
519
|
-
return this.gateway.getRunDetail(
|
|
591
|
+
getRunDetail(runId2, options) {
|
|
592
|
+
return this.gateway.getRunDetail(runId2, options);
|
|
520
593
|
}
|
|
521
594
|
/** A page of one fan's members, or null when the run is unknown or the gateway can't page fans. */
|
|
522
|
-
async getFanMembers(
|
|
523
|
-
return await this.gateway.getFanMembers?.(
|
|
595
|
+
async getFanMembers(runId2, group, query) {
|
|
596
|
+
return await this.gateway.getFanMembers?.(runId2, group, query) ?? null;
|
|
524
597
|
}
|
|
525
598
|
/** Fix-and-replay a dead/failed run with a corrected input — a fresh linked run. Returns its id. */
|
|
526
|
-
retryWithInput(
|
|
527
|
-
return this.gateway.retryWithInput(
|
|
599
|
+
retryWithInput(runId2, input) {
|
|
600
|
+
return this.gateway.retryWithInput(runId2, input);
|
|
528
601
|
}
|
|
529
602
|
/** Re-run a failed/incomplete run; completed steps replay from their checkpoints. */
|
|
530
|
-
retry(
|
|
531
|
-
return this.gateway.retry(
|
|
603
|
+
retry(runId2) {
|
|
604
|
+
return this.gateway.retry(runId2);
|
|
532
605
|
}
|
|
533
|
-
cancel(
|
|
534
|
-
return this.gateway.cancel(
|
|
606
|
+
cancel(runId2, opts) {
|
|
607
|
+
return this.gateway.cancel(runId2, opts);
|
|
535
608
|
}
|
|
536
609
|
/**
|
|
537
610
|
* Publish a settled run's lifecycle event again, to its subscribers that have not started (or to
|
|
538
611
|
* `subscriber` alone). Undefined when the gateway cannot republish (a tenant proxy).
|
|
539
612
|
*/
|
|
540
|
-
async republishLifecycle(
|
|
613
|
+
async republishLifecycle(runId2, subscriber) {
|
|
541
614
|
return this.gateway.republishLifecycle?.({
|
|
542
|
-
runId,
|
|
615
|
+
runId: runId2,
|
|
543
616
|
...subscriber !== void 0 ? {
|
|
544
617
|
subscriber
|
|
545
618
|
} : {}
|
|
@@ -607,12 +680,12 @@ var DashboardService = class {
|
|
|
607
680
|
};
|
|
608
681
|
}
|
|
609
682
|
/** Resume a run paused at a `ctx.breakpoint` (the "continue" button). */
|
|
610
|
-
continue(
|
|
611
|
-
return this.gateway.continue(
|
|
683
|
+
continue(runId2) {
|
|
684
|
+
return this.gateway.continue(runId2);
|
|
612
685
|
}
|
|
613
686
|
/** Re-dispatch a run's stuck `pending` remote steps — recovery for a lost step dispatch. */
|
|
614
|
-
redispatch(
|
|
615
|
-
return this.gateway.redispatchPending(
|
|
687
|
+
redispatch(runId2) {
|
|
688
|
+
return this.gateway.redispatchPending(runId2);
|
|
616
689
|
}
|
|
617
690
|
/**
|
|
618
691
|
* Deliver a `ctx.webhook()` callback: turn an inbound POST (token + body) into the signal the
|
|
@@ -641,13 +714,39 @@ var DashboardService = class {
|
|
|
641
714
|
status: fresh?.status ?? run.status
|
|
642
715
|
};
|
|
643
716
|
}
|
|
717
|
+
/**
|
|
718
|
+
* What this deployment can serve: `controlPlane` (signals, run events, updates, metrics) and
|
|
719
|
+
* `schedules` (persisted schedules). Both are false on a store-less tenant.
|
|
720
|
+
*/
|
|
721
|
+
capabilities() {
|
|
722
|
+
const controlPlane = this.store !== void 0 && this.engine !== void 0;
|
|
723
|
+
return {
|
|
724
|
+
controlPlane,
|
|
725
|
+
schedules: controlPlane && this.engine?.schedules?.supported === true
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
/** Whether `runId` names a run the caller may see (tenancy applies). */
|
|
729
|
+
async runExists(runId2) {
|
|
730
|
+
if (this.gateway.getRun) return await this.gateway.getRun(runId2) !== null;
|
|
731
|
+
return await this.gateway.getRunDetail(runId2, {
|
|
732
|
+
summarizeFansOver: 0
|
|
733
|
+
}) !== null;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Deliver `payload` to the run waiting on `token` (`engine.signal`). Null when no run the caller
|
|
737
|
+
* may see waits on it yet: the engine then buffers the payload for the run that waits next.
|
|
738
|
+
* Control-plane-only.
|
|
739
|
+
*/
|
|
740
|
+
signal(token, payload) {
|
|
741
|
+
return this.controlPlane().engine.signal(token, payload);
|
|
742
|
+
}
|
|
644
743
|
/** Side-effect-free read of a value a run published via `ctx.setEvent` (a live query). Control-plane-only. */
|
|
645
|
-
async getEvent(
|
|
646
|
-
return this.controlPlane().engine.getEvent(
|
|
744
|
+
async getEvent(runId2, key) {
|
|
745
|
+
return this.controlPlane().engine.getEvent(runId2, key);
|
|
647
746
|
}
|
|
648
747
|
/** Deliver a validated `ctx.onUpdate` to a run; the validator may reject it (see UpdateResult). Control-plane-only. */
|
|
649
|
-
async update(
|
|
650
|
-
return this.controlPlane().engine.update(
|
|
748
|
+
async update(runId2, name, arg) {
|
|
749
|
+
return this.controlPlane().engine.update(runId2, name, arg);
|
|
651
750
|
}
|
|
652
751
|
/**
|
|
653
752
|
* Live stream of a run's lifecycle events for SSE. Backed by `gateway.subscribe`, which — on the
|
|
@@ -655,9 +754,9 @@ var DashboardService = class {
|
|
|
655
754
|
* executing on a worker pod), and on a tenant round-trips over the transport. Either way the
|
|
656
755
|
* gateway already filters to `runId`; the dashboard just wires the events through.
|
|
657
756
|
*/
|
|
658
|
-
streamRun(
|
|
757
|
+
streamRun(runId2) {
|
|
659
758
|
return new import_rxjs.Observable((subscriber) => {
|
|
660
|
-
const off = this.gateway.subscribe(
|
|
759
|
+
const off = this.gateway.subscribe(runId2, (event) => subscriber.next({
|
|
661
760
|
data: event
|
|
662
761
|
}));
|
|
663
762
|
return () => off();
|
|
@@ -905,7 +1004,7 @@ var RunQueryDraft2 = class {
|
|
|
905
1004
|
/** The predicates minus the page window and the axes a facet count reports on — what
|
|
906
1005
|
* `runFacets`/`runValueFacets` are taken over. */
|
|
907
1006
|
facetQuery() {
|
|
908
|
-
const { status, statuses, origin, origins, limit, offset, ...facetQuery } = this.query;
|
|
1007
|
+
const { status, statuses, origin, origins, limit: limit2, offset, ...facetQuery } = this.query;
|
|
909
1008
|
return facetQuery;
|
|
910
1009
|
}
|
|
911
1010
|
};
|
|
@@ -1110,10 +1209,10 @@ var RunQueryAdapter = class {
|
|
|
1110
1209
|
}
|
|
1111
1210
|
unsupported(clause, "equals, notEquals, gt, gte, lt, lte, in");
|
|
1112
1211
|
}
|
|
1113
|
-
applyOffsetPagination(qb,
|
|
1212
|
+
applyOffsetPagination(qb, page2, size) {
|
|
1114
1213
|
this.draft(qb).narrow({
|
|
1115
1214
|
limit: size,
|
|
1116
|
-
offset: (
|
|
1215
|
+
offset: (page2 - 1) * size
|
|
1117
1216
|
});
|
|
1118
1217
|
}
|
|
1119
1218
|
/**
|
|
@@ -1340,9 +1439,9 @@ var RunFilter = class extends import_nestjs_filter.BaseFilter {
|
|
|
1340
1439
|
}
|
|
1341
1440
|
}
|
|
1342
1441
|
applyLimit(value) {
|
|
1343
|
-
const
|
|
1344
|
-
if (
|
|
1345
|
-
limit
|
|
1442
|
+
const limit2 = bound(value);
|
|
1443
|
+
if (limit2 !== void 0) this.$query.narrow({
|
|
1444
|
+
limit: limit2
|
|
1346
1445
|
});
|
|
1347
1446
|
}
|
|
1348
1447
|
applyOffset(value) {
|
|
@@ -1524,7 +1623,7 @@ var DurableApiControllerBase = class {
|
|
|
1524
1623
|
* The persisted schedules (`engine.schedules`), soonest-due first, optionally narrowed by
|
|
1525
1624
|
* `namespace`/`workflow`/`tag`/`paused`. Empty on a tenant or a store without schedules.
|
|
1526
1625
|
*/
|
|
1527
|
-
schedules(namespace, workflow, tag, paused,
|
|
1626
|
+
schedules(namespace, workflow, tag, paused, limit2) {
|
|
1528
1627
|
return this.dashboard.listSchedules({
|
|
1529
1628
|
...namespace ? {
|
|
1530
1629
|
namespace
|
|
@@ -1538,7 +1637,7 @@ var DurableApiControllerBase = class {
|
|
|
1538
1637
|
...paused === "true" || paused === "false" ? {
|
|
1539
1638
|
paused: paused === "true"
|
|
1540
1639
|
} : {},
|
|
1541
|
-
limit: Math.min(Number(
|
|
1640
|
+
limit: Math.min(Number(limit2) || 200, 1e3)
|
|
1542
1641
|
});
|
|
1543
1642
|
}
|
|
1544
1643
|
pauseSchedule(id) {
|
|
@@ -1588,17 +1687,17 @@ var DurableApiControllerBase = class {
|
|
|
1588
1687
|
return body;
|
|
1589
1688
|
}
|
|
1590
1689
|
/** One page of a summarized fan's members, in seq order. Versioned like {@link run}. */
|
|
1591
|
-
async fanMembers(id, group, offset,
|
|
1592
|
-
const
|
|
1690
|
+
async fanMembers(id, group, offset, limit2, failed, ifNoneMatch, response) {
|
|
1691
|
+
const page2 = await this.dashboard.getFanMembers(id, group, {
|
|
1593
1692
|
offset: offset === void 0 ? void 0 : Number(offset),
|
|
1594
|
-
limit:
|
|
1693
|
+
limit: limit2 === void 0 ? void 0 : Number(limit2),
|
|
1595
1694
|
failedOnly: failed === "true",
|
|
1596
1695
|
...ifNoneMatch && {
|
|
1597
1696
|
ifNoneMatch
|
|
1598
1697
|
}
|
|
1599
1698
|
});
|
|
1600
|
-
if (!
|
|
1601
|
-
const { etag, notModified, ...body } =
|
|
1699
|
+
if (!page2) throw new import_common6.NotFoundException(`fan ${group} of run ${id} not found`);
|
|
1700
|
+
const { etag, notModified, ...body } = page2;
|
|
1602
1701
|
if (etag) {
|
|
1603
1702
|
if (notModified) throw new NotModifiedException(etag);
|
|
1604
1703
|
setEtag(response, etag);
|
|
@@ -1623,7 +1722,7 @@ var DurableApiControllerBase = class {
|
|
|
1623
1722
|
* exactly the set the operator was looking at rather than a wider one.
|
|
1624
1723
|
*/
|
|
1625
1724
|
bulk(action, draft, compensate) {
|
|
1626
|
-
const { limit, offset, ...filter } = draft.query;
|
|
1725
|
+
const { limit: limit2, offset, ...filter } = draft.query;
|
|
1627
1726
|
return this.dashboard.bulk(action === "cancel" ? "cancel" : "retry", filter, {
|
|
1628
1727
|
compensate: compensate === "true"
|
|
1629
1728
|
});
|
|
@@ -1670,9 +1769,9 @@ var DurableApiControllerBase = class {
|
|
|
1670
1769
|
}
|
|
1671
1770
|
/**
|
|
1672
1771
|
* Public callback endpoint for `ctx.webhook()`: a third party POSTs here (the url handed to it),
|
|
1673
|
-
* and the body resumes the waiting run.
|
|
1674
|
-
*
|
|
1675
|
-
* verification in your own middleware.
|
|
1772
|
+
* and the body resumes the waiting run. Not a console route: the console's `authorize` does not
|
|
1773
|
+
* apply, the token is the secret. The app's `decorators` still do. Treat the token as a secret
|
|
1774
|
+
* and/or front it with signature verification in your own middleware.
|
|
1676
1775
|
*/
|
|
1677
1776
|
async webhook(token, body) {
|
|
1678
1777
|
const result = await this.dashboard.deliverWebhook(token, body);
|
|
@@ -1910,6 +2009,7 @@ _ts_decorate6([
|
|
|
1910
2009
|
_ts_metadata5("design:returntype", Promise)
|
|
1911
2010
|
], DurableApiControllerBase.prototype, "redispatch", null);
|
|
1912
2011
|
_ts_decorate6([
|
|
2012
|
+
ConsolePublic(),
|
|
1913
2013
|
(0, import_common6.Post)("webhooks/:token"),
|
|
1914
2014
|
_ts_param3(0, (0, import_common6.Param)("token")),
|
|
1915
2015
|
_ts_param3(1, (0, import_common6.Body)()),
|
|
@@ -1980,9 +2080,196 @@ DurableApiController = _ts_decorate6([
|
|
|
1980
2080
|
// src/server/durable-dashboard.module.ts
|
|
1981
2081
|
var import_reflect_metadata3 = require("reflect-metadata");
|
|
1982
2082
|
var import_nestjs_filter3 = require("@dudousxd/nestjs-filter");
|
|
1983
|
-
var
|
|
2083
|
+
var import_common10 = require("@nestjs/common");
|
|
1984
2084
|
var import_core2 = require("@nestjs/core");
|
|
1985
2085
|
|
|
2086
|
+
// src/server/console-switcher.ts
|
|
2087
|
+
var import_common7 = require("@nestjs/common");
|
|
2088
|
+
|
|
2089
|
+
// src/server/tokens.ts
|
|
2090
|
+
var import_nestjs_durable_core3 = require("@dudousxd/nestjs-durable-core");
|
|
2091
|
+
var DASHBOARD_DEV_TOOLS = Symbol("DASHBOARD_DEV_TOOLS");
|
|
2092
|
+
var DASHBOARD_BASE_PATH = Symbol("DASHBOARD_BASE_PATH");
|
|
2093
|
+
var DASHBOARD_API_PATH = Symbol("DASHBOARD_API_PATH");
|
|
2094
|
+
|
|
2095
|
+
// src/server/console-switcher.ts
|
|
2096
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
2097
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2098
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2099
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
2100
|
+
} else {
|
|
2101
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2102
|
+
if (d = decorators[i]) {
|
|
2103
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2108
|
+
}
|
|
2109
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
2110
|
+
function _ts_metadata6(metadataKey, metadataValue) {
|
|
2111
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2112
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
__name(_ts_metadata6, "_ts_metadata");
|
|
2116
|
+
function _ts_param4(paramIndex, decorator) {
|
|
2117
|
+
return function(target, key) {
|
|
2118
|
+
decorator(target, key, paramIndex);
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
__name(_ts_param4, "_ts_param");
|
|
2122
|
+
var AVIARY_CONSOLES_SLOT = Symbol.for("@dudousxd/aviary:consoles");
|
|
2123
|
+
var ID = /^[a-z][a-z0-9-]*$/;
|
|
2124
|
+
var ICONS = /* @__PURE__ */ new Set([
|
|
2125
|
+
"workflow",
|
|
2126
|
+
"telescope",
|
|
2127
|
+
"media",
|
|
2128
|
+
"payments",
|
|
2129
|
+
"agent",
|
|
2130
|
+
"identity",
|
|
2131
|
+
"generic"
|
|
2132
|
+
]);
|
|
2133
|
+
var CONSOLE_PROBE_TIMEOUT_MS = 300;
|
|
2134
|
+
function isSameOriginPath(path) {
|
|
2135
|
+
return typeof path === "string" && path.startsWith("/") && !path.startsWith("//");
|
|
2136
|
+
}
|
|
2137
|
+
__name(isSameOriginPath, "isSameOriginPath");
|
|
2138
|
+
function readAviaryConsoles() {
|
|
2139
|
+
const value = globalThis[AVIARY_CONSOLES_SLOT];
|
|
2140
|
+
if (value?.version !== 1 || !Array.isArray(value.entries)) return void 0;
|
|
2141
|
+
return value;
|
|
2142
|
+
}
|
|
2143
|
+
__name(readAviaryConsoles, "readAviaryConsoles");
|
|
2144
|
+
function registerAviaryConsole(entry, logger3) {
|
|
2145
|
+
if (!ID.test(entry.id)) throw new Error(`console id ${JSON.stringify(entry.id)} is invalid`);
|
|
2146
|
+
if (!isSameOriginPath(entry.path)) {
|
|
2147
|
+
throw new Error(`console path ${JSON.stringify(entry.path)} must start with a single "/"`);
|
|
2148
|
+
}
|
|
2149
|
+
const holder = globalThis;
|
|
2150
|
+
if (holder[AVIARY_CONSOLES_SLOT] === void 0) {
|
|
2151
|
+
const fresh = {
|
|
2152
|
+
version: 1,
|
|
2153
|
+
entries: []
|
|
2154
|
+
};
|
|
2155
|
+
holder[AVIARY_CONSOLES_SLOT] = fresh;
|
|
2156
|
+
}
|
|
2157
|
+
const registry = readAviaryConsoles();
|
|
2158
|
+
if (registry === void 0) return void 0;
|
|
2159
|
+
if (registry.entries.some((existing) => existing.id === entry.id)) {
|
|
2160
|
+
logger3?.warn(`console id "${entry.id}" is already registered`);
|
|
2161
|
+
return void 0;
|
|
2162
|
+
}
|
|
2163
|
+
registry.entries.push(entry);
|
|
2164
|
+
return () => {
|
|
2165
|
+
const index = registry.entries.indexOf(entry);
|
|
2166
|
+
if (index !== -1) registry.entries.splice(index, 1);
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
__name(registerAviaryConsole, "registerAviaryConsole");
|
|
2170
|
+
function consoleSwitcherConfig(selfId, endpoint) {
|
|
2171
|
+
const registry = readAviaryConsoles();
|
|
2172
|
+
if (!registry?.entries.some((entry) => entry.id === selfId)) return void 0;
|
|
2173
|
+
const others = registry.entries.filter((entry) => entry.id !== selfId).length;
|
|
2174
|
+
return others > 0 ? {
|
|
2175
|
+
endpoint,
|
|
2176
|
+
others
|
|
2177
|
+
} : void 0;
|
|
2178
|
+
}
|
|
2179
|
+
__name(consoleSwitcherConfig, "consoleSwitcherConfig");
|
|
2180
|
+
async function allows(entry, context, ms) {
|
|
2181
|
+
let timer;
|
|
2182
|
+
const timeout = new Promise((resolve2) => {
|
|
2183
|
+
timer = setTimeout(() => resolve2(false), ms);
|
|
2184
|
+
});
|
|
2185
|
+
try {
|
|
2186
|
+
return await Promise.race([
|
|
2187
|
+
Promise.resolve().then(() => entry.authorize(context)).then((decision) => decision?.allowed === true, () => false),
|
|
2188
|
+
timeout
|
|
2189
|
+
]);
|
|
2190
|
+
} finally {
|
|
2191
|
+
clearTimeout(timer);
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
__name(allows, "allows");
|
|
2195
|
+
async function listVisibleConsoles(registry, selfId, context, timeoutMs = CONSOLE_PROBE_TIMEOUT_MS) {
|
|
2196
|
+
const others = (registry?.entries ?? []).filter((entry) => entry.id !== selfId && isSameOriginPath(entry.path)).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
|
|
2197
|
+
const verdicts = await Promise.all(others.map((entry) => allows(entry, context, timeoutMs)));
|
|
2198
|
+
return {
|
|
2199
|
+
version: 1,
|
|
2200
|
+
current: selfId,
|
|
2201
|
+
consoles: others.filter((_, index) => verdicts[index]).map((entry) => ({
|
|
2202
|
+
id: entry.id,
|
|
2203
|
+
title: entry.title,
|
|
2204
|
+
icon: ICONS.has(entry.icon) ? entry.icon : "generic",
|
|
2205
|
+
href: entry.path
|
|
2206
|
+
}))
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
__name(listVisibleConsoles, "listVisibleConsoles");
|
|
2210
|
+
var DURABLE_CONSOLE_ID = "durable";
|
|
2211
|
+
var logger = new import_common7.Logger("DurableDashboardModule");
|
|
2212
|
+
var DurableConsoleRegistration = class {
|
|
2213
|
+
static {
|
|
2214
|
+
__name(this, "DurableConsoleRegistration");
|
|
2215
|
+
}
|
|
2216
|
+
basePath;
|
|
2217
|
+
decide;
|
|
2218
|
+
#unregister;
|
|
2219
|
+
constructor(basePath, decide) {
|
|
2220
|
+
this.basePath = basePath;
|
|
2221
|
+
this.decide = decide;
|
|
2222
|
+
}
|
|
2223
|
+
onModuleInit() {
|
|
2224
|
+
this.#unregister = registerAviaryConsole({
|
|
2225
|
+
id: DURABLE_CONSOLE_ID,
|
|
2226
|
+
title: "Workflows",
|
|
2227
|
+
icon: "workflow",
|
|
2228
|
+
order: 10,
|
|
2229
|
+
path: this.basePath,
|
|
2230
|
+
authorize: /* @__PURE__ */ __name((context) => this.decide(context), "authorize")
|
|
2231
|
+
}, logger);
|
|
2232
|
+
}
|
|
2233
|
+
onModuleDestroy() {
|
|
2234
|
+
this.#unregister?.();
|
|
2235
|
+
this.#unregister = void 0;
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2238
|
+
DurableConsoleRegistration = _ts_decorate7([
|
|
2239
|
+
(0, import_common7.Injectable)(),
|
|
2240
|
+
_ts_param4(0, (0, import_common7.Inject)(DASHBOARD_BASE_PATH)),
|
|
2241
|
+
_ts_param4(1, (0, import_common7.Inject)(CONSOLE_AUTHORIZE_DECIDE)),
|
|
2242
|
+
_ts_metadata6("design:type", Function),
|
|
2243
|
+
_ts_metadata6("design:paramtypes", [
|
|
2244
|
+
String,
|
|
2245
|
+
typeof ConsoleDecide === "undefined" ? Object : ConsoleDecide
|
|
2246
|
+
])
|
|
2247
|
+
], DurableConsoleRegistration);
|
|
2248
|
+
var CurrentExecutionContext = (0, import_common7.createParamDecorator)((_data, context) => ({
|
|
2249
|
+
context
|
|
2250
|
+
}));
|
|
2251
|
+
var DurableConsolesController = class {
|
|
2252
|
+
static {
|
|
2253
|
+
__name(this, "DurableConsolesController");
|
|
2254
|
+
}
|
|
2255
|
+
consoles(current) {
|
|
2256
|
+
return listVisibleConsoles(readAviaryConsoles(), DURABLE_CONSOLE_ID, current.context);
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
_ts_decorate7([
|
|
2260
|
+
(0, import_common7.Get)("consoles"),
|
|
2261
|
+
(0, import_common7.Header)("Cache-Control", "private, no-store"),
|
|
2262
|
+
_ts_param4(0, CurrentExecutionContext()),
|
|
2263
|
+
_ts_metadata6("design:type", Function),
|
|
2264
|
+
_ts_metadata6("design:paramtypes", [
|
|
2265
|
+
typeof CurrentContext === "undefined" ? Object : CurrentContext
|
|
2266
|
+
]),
|
|
2267
|
+
_ts_metadata6("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
2268
|
+
], DurableConsolesController.prototype, "consoles", null);
|
|
2269
|
+
DurableConsolesController = _ts_decorate7([
|
|
2270
|
+
(0, import_common7.Controller)()
|
|
2271
|
+
], DurableConsolesController);
|
|
2272
|
+
|
|
1986
2273
|
// src/server/controller-decorators.ts
|
|
1987
2274
|
var import_reflect_metadata2 = require("reflect-metadata");
|
|
1988
2275
|
var CAN_ANYONE_METADATA = "authorization:can-anyone";
|
|
@@ -2009,12 +2296,785 @@ function controllerFor(base, decorators) {
|
|
|
2009
2296
|
}
|
|
2010
2297
|
__name(controllerFor, "controllerFor");
|
|
2011
2298
|
|
|
2299
|
+
// src/server/dev-tools.ts
|
|
2300
|
+
var import_common8 = require("@nestjs/common");
|
|
2301
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
2302
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2303
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2304
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
2305
|
+
} else {
|
|
2306
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2307
|
+
if (d = decorators[i]) {
|
|
2308
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2313
|
+
}
|
|
2314
|
+
__name(_ts_decorate8, "_ts_decorate");
|
|
2315
|
+
function _ts_metadata7(metadataKey, metadataValue) {
|
|
2316
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2317
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
__name(_ts_metadata7, "_ts_metadata");
|
|
2321
|
+
function _ts_param5(paramIndex, decorator) {
|
|
2322
|
+
return function(target, key) {
|
|
2323
|
+
decorator(target, key, paramIndex);
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
__name(_ts_param5, "_ts_param");
|
|
2327
|
+
var DEV_TOOLS_SLOT = Symbol.for("@dudousxd/aviary:dev-tools");
|
|
2328
|
+
function devToolsSlot() {
|
|
2329
|
+
const holder = globalThis;
|
|
2330
|
+
const existing = holder[DEV_TOOLS_SLOT];
|
|
2331
|
+
if (existing !== void 0) return existing;
|
|
2332
|
+
const libs = [];
|
|
2333
|
+
const slot = {
|
|
2334
|
+
version: 1,
|
|
2335
|
+
libs,
|
|
2336
|
+
register(lib) {
|
|
2337
|
+
if (libs.some((entry) => entry.lib === lib.lib)) {
|
|
2338
|
+
throw new Error(`dev tools: the lib "${lib.lib}" is already registered`);
|
|
2339
|
+
}
|
|
2340
|
+
libs.push(lib);
|
|
2341
|
+
return () => {
|
|
2342
|
+
const index = libs.indexOf(lib);
|
|
2343
|
+
if (index !== -1) libs.splice(index, 1);
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
};
|
|
2347
|
+
holder[DEV_TOOLS_SLOT] = slot;
|
|
2348
|
+
return slot;
|
|
2349
|
+
}
|
|
2350
|
+
__name(devToolsSlot, "devToolsSlot");
|
|
2351
|
+
var DEFAULT_LIMIT = 20;
|
|
2352
|
+
var MAX_LIMIT = 100;
|
|
2353
|
+
var MAX_RUN_IDS = 100;
|
|
2354
|
+
var ERROR_SUMMARY_CHARS = 300;
|
|
2355
|
+
var RUN_STATUSES = [
|
|
2356
|
+
"pending",
|
|
2357
|
+
"running",
|
|
2358
|
+
"suspended",
|
|
2359
|
+
"completed",
|
|
2360
|
+
"failed",
|
|
2361
|
+
"cancelling",
|
|
2362
|
+
"cancelled",
|
|
2363
|
+
"dead",
|
|
2364
|
+
"blocked"
|
|
2365
|
+
];
|
|
2366
|
+
var COUNT_FIELDS = [
|
|
2367
|
+
"status",
|
|
2368
|
+
"workflow",
|
|
2369
|
+
"origin",
|
|
2370
|
+
"namespace",
|
|
2371
|
+
"tag",
|
|
2372
|
+
"attributeKey",
|
|
2373
|
+
"attributeValue"
|
|
2374
|
+
];
|
|
2375
|
+
var limit = {
|
|
2376
|
+
type: "integer",
|
|
2377
|
+
description: `Rows per page (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT}).`,
|
|
2378
|
+
minimum: 1,
|
|
2379
|
+
maximum: MAX_LIMIT
|
|
2380
|
+
};
|
|
2381
|
+
var cursor = {
|
|
2382
|
+
type: "string",
|
|
2383
|
+
description: "Pass the `next` of the previous page."
|
|
2384
|
+
};
|
|
2385
|
+
var runId = {
|
|
2386
|
+
type: "string",
|
|
2387
|
+
description: "Run id."
|
|
2388
|
+
};
|
|
2389
|
+
var runIds = {
|
|
2390
|
+
type: "array",
|
|
2391
|
+
items: {
|
|
2392
|
+
type: "string"
|
|
2393
|
+
},
|
|
2394
|
+
description: `Several run ids (1 to ${MAX_RUN_IDS}), instead of \`id\`.`
|
|
2395
|
+
};
|
|
2396
|
+
var scheduleKey = {
|
|
2397
|
+
type: "string",
|
|
2398
|
+
description: "Schedule id."
|
|
2399
|
+
};
|
|
2400
|
+
var runFilters = {
|
|
2401
|
+
workflow: {
|
|
2402
|
+
type: "string",
|
|
2403
|
+
description: "Workflow name."
|
|
2404
|
+
},
|
|
2405
|
+
tag: {
|
|
2406
|
+
type: "string",
|
|
2407
|
+
description: "A tag the run carries."
|
|
2408
|
+
},
|
|
2409
|
+
namespace: {
|
|
2410
|
+
type: "string",
|
|
2411
|
+
description: "Worker pool (namespace)."
|
|
2412
|
+
},
|
|
2413
|
+
attr: {
|
|
2414
|
+
type: "array",
|
|
2415
|
+
items: {
|
|
2416
|
+
type: "string"
|
|
2417
|
+
},
|
|
2418
|
+
description: "Search-attribute predicates `key:op:value` (ops: eq, ne, gt, gte, lt, lte, in with `|`), ANDed."
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2421
|
+
var str = /* @__PURE__ */ __name((value) => typeof value === "string" && value !== "" ? value : void 0, "str");
|
|
2422
|
+
function limitOf(input) {
|
|
2423
|
+
const value = input.limit;
|
|
2424
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? Math.min(value, MAX_LIMIT) : DEFAULT_LIMIT;
|
|
2425
|
+
}
|
|
2426
|
+
__name(limitOf, "limitOf");
|
|
2427
|
+
function offsetOf(input) {
|
|
2428
|
+
const value = str(input.cursor);
|
|
2429
|
+
if (value === void 0) return 0;
|
|
2430
|
+
if (!/^\d+$/.test(value)) {
|
|
2431
|
+
throw new Error(`"cursor" must be the \`next\` of a previous page, got "${value}"`);
|
|
2432
|
+
}
|
|
2433
|
+
return Number(value);
|
|
2434
|
+
}
|
|
2435
|
+
__name(offsetOf, "offsetOf");
|
|
2436
|
+
function required(input, key) {
|
|
2437
|
+
const value = str(input[key]);
|
|
2438
|
+
if (value === void 0) throw new Error(`"${key}" is required`);
|
|
2439
|
+
return value;
|
|
2440
|
+
}
|
|
2441
|
+
__name(required, "required");
|
|
2442
|
+
function page(rows, offset, size) {
|
|
2443
|
+
return {
|
|
2444
|
+
items: rows.slice(0, size),
|
|
2445
|
+
next: rows.length > size ? String(offset + size) : null
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2448
|
+
__name(page, "page");
|
|
2449
|
+
function runPredicates(input) {
|
|
2450
|
+
const query = {};
|
|
2451
|
+
const workflow = str(input.workflow);
|
|
2452
|
+
if (workflow !== void 0) query.workflow = workflow;
|
|
2453
|
+
const tag = str(input.tag);
|
|
2454
|
+
if (tag !== void 0) query.tag = tag;
|
|
2455
|
+
const namespace = str(input.namespace);
|
|
2456
|
+
if (namespace !== void 0) query.namespace = namespace;
|
|
2457
|
+
const attr = Array.isArray(input.attr) ? input.attr.filter((entry) => typeof entry === "string" && entry !== "") : [];
|
|
2458
|
+
if (attr.length > 0) {
|
|
2459
|
+
const attributes = parseAttrFilters(attr);
|
|
2460
|
+
if (attributes === void 0 || attributes.length !== attr.length) {
|
|
2461
|
+
throw new Error(`"attr" entries must read \`key:op:value\`, got ${JSON.stringify(attr)}`);
|
|
2462
|
+
}
|
|
2463
|
+
query.attributes = attributes;
|
|
2464
|
+
}
|
|
2465
|
+
return query;
|
|
2466
|
+
}
|
|
2467
|
+
__name(runPredicates, "runPredicates");
|
|
2468
|
+
function statusOf(input) {
|
|
2469
|
+
const status = str(input.status);
|
|
2470
|
+
if (status === void 0) return void 0;
|
|
2471
|
+
if (!RUN_STATUSES.includes(status)) {
|
|
2472
|
+
throw new Error(`"status" must be one of ${RUN_STATUSES.join(", ")}, got "${status}"`);
|
|
2473
|
+
}
|
|
2474
|
+
return status;
|
|
2475
|
+
}
|
|
2476
|
+
__name(statusOf, "statusOf");
|
|
2477
|
+
function listRow(run) {
|
|
2478
|
+
const row = {
|
|
2479
|
+
...toRunListRow(run)
|
|
2480
|
+
};
|
|
2481
|
+
const message = run.error?.message;
|
|
2482
|
+
if (typeof message === "string" && message !== "") {
|
|
2483
|
+
const line = message.split("\n", 1)[0] ?? "";
|
|
2484
|
+
row.error = line.length > ERROR_SUMMARY_CHARS ? `${line.slice(0, ERROR_SUMMARY_CHARS)}\u2026` : line;
|
|
2485
|
+
}
|
|
2486
|
+
return row;
|
|
2487
|
+
}
|
|
2488
|
+
__name(listRow, "listRow");
|
|
2489
|
+
async function call(what, run) {
|
|
2490
|
+
try {
|
|
2491
|
+
return await run();
|
|
2492
|
+
} catch (error) {
|
|
2493
|
+
if (error instanceof import_common8.NotFoundException || error instanceof Error && error.name === "ScheduleNotFoundError") {
|
|
2494
|
+
throw new Error(`${what()} not found`);
|
|
2495
|
+
}
|
|
2496
|
+
if (error instanceof import_common8.HttpException) throw new Error(error.message);
|
|
2497
|
+
throw error;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
__name(call, "call");
|
|
2501
|
+
function found(value, what) {
|
|
2502
|
+
if (value === null || value === void 0) throw new Error(`${what} not found`);
|
|
2503
|
+
return value;
|
|
2504
|
+
}
|
|
2505
|
+
__name(found, "found");
|
|
2506
|
+
function idsOf(input) {
|
|
2507
|
+
const one = str(input.id);
|
|
2508
|
+
const many = Array.isArray(input.ids) ? input.ids.filter((id) => typeof id === "string" && id !== "") : void 0;
|
|
2509
|
+
if (one !== void 0 && many !== void 0) throw new Error('pass "id" or "ids", not both');
|
|
2510
|
+
if (one !== void 0) return {
|
|
2511
|
+
ids: [
|
|
2512
|
+
one
|
|
2513
|
+
],
|
|
2514
|
+
many: false
|
|
2515
|
+
};
|
|
2516
|
+
if (many === void 0 || many.length === 0) throw new Error('"id" or "ids" is required');
|
|
2517
|
+
if (many.length > MAX_RUN_IDS) {
|
|
2518
|
+
throw new Error(`"ids" lists ${many.length} runs; at most ${MAX_RUN_IDS} per call`);
|
|
2519
|
+
}
|
|
2520
|
+
return {
|
|
2521
|
+
ids: many,
|
|
2522
|
+
many: true
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
__name(idsOf, "idsOf");
|
|
2526
|
+
async function each(input, act) {
|
|
2527
|
+
const { ids, many } = idsOf(input);
|
|
2528
|
+
if (!many) return act(ids[0]);
|
|
2529
|
+
const applied = [];
|
|
2530
|
+
for (const [index, id] of ids.entries()) {
|
|
2531
|
+
try {
|
|
2532
|
+
applied.push(await act(id));
|
|
2533
|
+
} catch (error) {
|
|
2534
|
+
return {
|
|
2535
|
+
applied,
|
|
2536
|
+
failed: {
|
|
2537
|
+
id,
|
|
2538
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2539
|
+
},
|
|
2540
|
+
skipped: ids.slice(index + 1)
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
return {
|
|
2545
|
+
applied
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
__name(each, "each");
|
|
2549
|
+
function starvedGroups(groups) {
|
|
2550
|
+
return groups.filter((group) => group.depth > 0 && group.liveWorkers.length === 0).sort((a, b) => b.depth - a.depth).map(({ group, depth, kind }) => ({
|
|
2551
|
+
group,
|
|
2552
|
+
depth,
|
|
2553
|
+
...kind ? {
|
|
2554
|
+
kind
|
|
2555
|
+
} : {}
|
|
2556
|
+
}));
|
|
2557
|
+
}
|
|
2558
|
+
__name(starvedGroups, "starvedGroups");
|
|
2559
|
+
function durableDevTools(service) {
|
|
2560
|
+
const controlPlane = /* @__PURE__ */ __name(() => service.capabilities().controlPlane, "controlPlane");
|
|
2561
|
+
const schedules = /* @__PURE__ */ __name(() => service.capabilities().schedules, "schedules");
|
|
2562
|
+
return [
|
|
2563
|
+
{
|
|
2564
|
+
name: "durable_list_runs",
|
|
2565
|
+
kind: "read",
|
|
2566
|
+
description: "Workflow runs, newest first: id, workflow, status, what a suspended run waits on, times, tags and a one-line error summary (no input or output). Filters: status, workflow, tag, namespace, origin, attr. Returns { items, next }; pass next as cursor.",
|
|
2567
|
+
input: {
|
|
2568
|
+
type: "object",
|
|
2569
|
+
properties: {
|
|
2570
|
+
status: {
|
|
2571
|
+
type: "string",
|
|
2572
|
+
enum: RUN_STATUSES,
|
|
2573
|
+
description: "Run status."
|
|
2574
|
+
},
|
|
2575
|
+
...runFilters,
|
|
2576
|
+
origin: {
|
|
2577
|
+
type: "string",
|
|
2578
|
+
description: "The package the run came from."
|
|
2579
|
+
},
|
|
2580
|
+
cursor,
|
|
2581
|
+
limit
|
|
2582
|
+
}
|
|
2583
|
+
},
|
|
2584
|
+
async run(input) {
|
|
2585
|
+
const size = limitOf(input);
|
|
2586
|
+
const offset = offsetOf(input);
|
|
2587
|
+
const status = statusOf(input);
|
|
2588
|
+
const origin = str(input.origin);
|
|
2589
|
+
const query = {
|
|
2590
|
+
...runPredicates(input),
|
|
2591
|
+
...status !== void 0 ? {
|
|
2592
|
+
status
|
|
2593
|
+
} : {},
|
|
2594
|
+
...origin !== void 0 ? {
|
|
2595
|
+
origin
|
|
2596
|
+
} : {},
|
|
2597
|
+
offset,
|
|
2598
|
+
limit: size + 1
|
|
2599
|
+
};
|
|
2600
|
+
const runs = await call(() => "runs", () => service.listRuns(query));
|
|
2601
|
+
return page(runs.map(listRow), offset, size);
|
|
2602
|
+
}
|
|
2603
|
+
},
|
|
2604
|
+
{
|
|
2605
|
+
name: "durable_get_run",
|
|
2606
|
+
kind: "read",
|
|
2607
|
+
description: 'One run: its input, output, error, step timeline, children, fans (summarized over 50 members unless full) and lifecycle links. `field` returns that one field only (e.g. "steps"). An error when no run has that id.',
|
|
2608
|
+
input: {
|
|
2609
|
+
type: "object",
|
|
2610
|
+
properties: {
|
|
2611
|
+
id: runId,
|
|
2612
|
+
full: {
|
|
2613
|
+
type: "boolean",
|
|
2614
|
+
description: "Every fan member inline (default false)."
|
|
2615
|
+
},
|
|
2616
|
+
field: {
|
|
2617
|
+
type: "string",
|
|
2618
|
+
description: "Return only this top-level field."
|
|
2619
|
+
}
|
|
2620
|
+
},
|
|
2621
|
+
required: [
|
|
2622
|
+
"id"
|
|
2623
|
+
]
|
|
2624
|
+
},
|
|
2625
|
+
async run(input) {
|
|
2626
|
+
const id = required(input, "id");
|
|
2627
|
+
const detail = found(await call(() => `run ${id}`, () => service.getRunDetail(id, input.full === true ? void 0 : {
|
|
2628
|
+
summarizeFansOver: 50
|
|
2629
|
+
})), `run ${id}`);
|
|
2630
|
+
const { etag: _etag, notModified: _notModified, ...body } = detail;
|
|
2631
|
+
const field = str(input.field);
|
|
2632
|
+
if (field === void 0) return body;
|
|
2633
|
+
if (!Object.hasOwn(body, field)) {
|
|
2634
|
+
throw new Error(`run ${id} has no field "${field}"; fields: ${Object.keys(body).join(", ")}`);
|
|
2635
|
+
}
|
|
2636
|
+
return {
|
|
2637
|
+
id,
|
|
2638
|
+
[field]: body[field]
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
name: "durable_list_fan_members",
|
|
2644
|
+
kind: "read",
|
|
2645
|
+
description: "One fan's members (the steps or children of a fan-out group), in order. Filters: failed (only failed members). Returns { items, total, next }; pass next as cursor. An error when the run or the fan does not exist.",
|
|
2646
|
+
input: {
|
|
2647
|
+
type: "object",
|
|
2648
|
+
properties: {
|
|
2649
|
+
id: runId,
|
|
2650
|
+
group: {
|
|
2651
|
+
type: "string",
|
|
2652
|
+
description: "The fan group, as the run detail names it."
|
|
2653
|
+
},
|
|
2654
|
+
failed: {
|
|
2655
|
+
type: "boolean",
|
|
2656
|
+
description: "Only failed members."
|
|
2657
|
+
},
|
|
2658
|
+
cursor,
|
|
2659
|
+
limit
|
|
2660
|
+
},
|
|
2661
|
+
required: [
|
|
2662
|
+
"id",
|
|
2663
|
+
"group"
|
|
2664
|
+
]
|
|
2665
|
+
},
|
|
2666
|
+
async run(input) {
|
|
2667
|
+
const id = required(input, "id");
|
|
2668
|
+
const group = required(input, "group");
|
|
2669
|
+
const size = limitOf(input);
|
|
2670
|
+
const offset = offsetOf(input);
|
|
2671
|
+
const fan = found(await call(() => `fan ${group} of run ${id}`, () => service.getFanMembers(id, group, {
|
|
2672
|
+
offset,
|
|
2673
|
+
limit: size,
|
|
2674
|
+
failedOnly: input.failed === true
|
|
2675
|
+
})), `fan ${group} of run ${id}`);
|
|
2676
|
+
const end = offset + fan.items.length;
|
|
2677
|
+
return {
|
|
2678
|
+
items: fan.items,
|
|
2679
|
+
total: fan.total,
|
|
2680
|
+
next: fan.items.length > 0 && end < fan.total ? String(end) : null
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2683
|
+
},
|
|
2684
|
+
{
|
|
2685
|
+
name: "durable_count_runs_by",
|
|
2686
|
+
kind: "read",
|
|
2687
|
+
description: "How many runs have each value of one field (status, workflow, origin, namespace, tag, attributeKey, or attributeValue with key), most frequent first. Filters: workflow, tag, namespace, attr. Returns { items: [{ value, count }], next }; pass next as cursor. Empty when the store cannot count that field.",
|
|
2688
|
+
input: {
|
|
2689
|
+
type: "object",
|
|
2690
|
+
properties: {
|
|
2691
|
+
field: {
|
|
2692
|
+
type: "string",
|
|
2693
|
+
enum: COUNT_FIELDS,
|
|
2694
|
+
description: "The field to count by."
|
|
2695
|
+
},
|
|
2696
|
+
key: {
|
|
2697
|
+
type: "string",
|
|
2698
|
+
description: "The search attribute, for attributeValue."
|
|
2699
|
+
},
|
|
2700
|
+
...runFilters,
|
|
2701
|
+
cursor,
|
|
2702
|
+
limit
|
|
2703
|
+
},
|
|
2704
|
+
required: [
|
|
2705
|
+
"field"
|
|
2706
|
+
]
|
|
2707
|
+
},
|
|
2708
|
+
async run(input) {
|
|
2709
|
+
const field = required(input, "field");
|
|
2710
|
+
if (!COUNT_FIELDS.includes(field)) {
|
|
2711
|
+
throw new Error(`"field" must be one of ${COUNT_FIELDS.join(", ")}, got "${field}"`);
|
|
2712
|
+
}
|
|
2713
|
+
const size = limitOf(input);
|
|
2714
|
+
const offset = offsetOf(input);
|
|
2715
|
+
const predicates = runPredicates(input);
|
|
2716
|
+
if (field === "status" || field === "origin") {
|
|
2717
|
+
const rows2 = await call(() => "runs", () => service.runFacets(predicates));
|
|
2718
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2719
|
+
for (const row of rows2) {
|
|
2720
|
+
const value = field === "status" ? row.status : row.origin;
|
|
2721
|
+
counts.set(value, (counts.get(value) ?? 0) + row.count);
|
|
2722
|
+
}
|
|
2723
|
+
const items = [
|
|
2724
|
+
...counts
|
|
2725
|
+
].map(([value, count]) => ({
|
|
2726
|
+
value,
|
|
2727
|
+
count
|
|
2728
|
+
})).sort((a, b) => b.count - a.count || String(a.value).localeCompare(String(b.value)));
|
|
2729
|
+
return page(items.slice(offset), offset, size);
|
|
2730
|
+
}
|
|
2731
|
+
const axis = field === "attributeValue" ? {
|
|
2732
|
+
field,
|
|
2733
|
+
key: required(input, "key")
|
|
2734
|
+
} : {
|
|
2735
|
+
field
|
|
2736
|
+
};
|
|
2737
|
+
const rows = await call(() => "runs", () => service.runValueFacets(axis, predicates, {
|
|
2738
|
+
offset,
|
|
2739
|
+
limit: size + 1
|
|
2740
|
+
}));
|
|
2741
|
+
return page(rows, offset, size);
|
|
2742
|
+
}
|
|
2743
|
+
},
|
|
2744
|
+
{
|
|
2745
|
+
name: "durable_get_health",
|
|
2746
|
+
kind: "read",
|
|
2747
|
+
description: "The fleet at a glance: run counts by status (pending backlog, dead, blocked: a run no compatible worker can take), queues with backlog and no live worker (starved), live worker count, and this deployment's role (control plane or tenant).",
|
|
2748
|
+
input: {
|
|
2749
|
+
type: "object",
|
|
2750
|
+
properties: {}
|
|
2751
|
+
},
|
|
2752
|
+
async run() {
|
|
2753
|
+
const [facets, groups] = await Promise.all([
|
|
2754
|
+
call(() => "runs", () => service.runFacets({})),
|
|
2755
|
+
call(() => "workers", () => service.workerHealth())
|
|
2756
|
+
]);
|
|
2757
|
+
const runs = {};
|
|
2758
|
+
for (const row of facets) runs[row.status] = (runs[row.status] ?? 0) + row.count;
|
|
2759
|
+
const workers = /* @__PURE__ */ new Set();
|
|
2760
|
+
for (const group of groups) {
|
|
2761
|
+
for (const worker of group.liveWorkers) workers.add(worker.instanceId);
|
|
2762
|
+
}
|
|
2763
|
+
const starved = starvedGroups(groups);
|
|
2764
|
+
return {
|
|
2765
|
+
topology: service.topology(),
|
|
2766
|
+
runs,
|
|
2767
|
+
backlog: runs.pending ?? 0,
|
|
2768
|
+
dead: runs.dead ?? 0,
|
|
2769
|
+
blocked: runs.blocked ?? 0,
|
|
2770
|
+
queues: groups.length,
|
|
2771
|
+
liveWorkers: workers.size,
|
|
2772
|
+
starved,
|
|
2773
|
+
healthy: starved.length === 0 && (runs.blocked ?? 0) === 0
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
},
|
|
2777
|
+
{
|
|
2778
|
+
name: "durable_list_workers",
|
|
2779
|
+
kind: "read",
|
|
2780
|
+
description: "Worker groups (queues): group, kind (workflow or step), queue depth and the live workers with their heartbeats. A group with depth > 0 and no live worker is starved. Returns { items, next: null }.",
|
|
2781
|
+
input: {
|
|
2782
|
+
type: "object",
|
|
2783
|
+
properties: {}
|
|
2784
|
+
},
|
|
2785
|
+
async run() {
|
|
2786
|
+
const groups = await call(() => "workers", () => service.workerHealth());
|
|
2787
|
+
return {
|
|
2788
|
+
items: groups,
|
|
2789
|
+
next: null
|
|
2790
|
+
};
|
|
2791
|
+
}
|
|
2792
|
+
},
|
|
2793
|
+
{
|
|
2794
|
+
name: "durable_list_schedules",
|
|
2795
|
+
kind: "read",
|
|
2796
|
+
description: "Persisted schedules, soonest due first: id, workflow, cadence (cron, every or rrule), paused, nextFireAt, lastFireAt, lastRunId, fires, lastError. Filters: workflow, tag, namespace, paused. Returns { items, next }; pass next as cursor.",
|
|
2797
|
+
input: {
|
|
2798
|
+
type: "object",
|
|
2799
|
+
properties: {
|
|
2800
|
+
workflow: {
|
|
2801
|
+
type: "string",
|
|
2802
|
+
description: "Workflow name."
|
|
2803
|
+
},
|
|
2804
|
+
tag: {
|
|
2805
|
+
type: "string",
|
|
2806
|
+
description: "A tag the schedule carries."
|
|
2807
|
+
},
|
|
2808
|
+
namespace: {
|
|
2809
|
+
type: "string",
|
|
2810
|
+
description: "Worker pool (namespace)."
|
|
2811
|
+
},
|
|
2812
|
+
paused: {
|
|
2813
|
+
type: "boolean",
|
|
2814
|
+
description: "Only paused (true) or active (false)."
|
|
2815
|
+
},
|
|
2816
|
+
cursor,
|
|
2817
|
+
limit
|
|
2818
|
+
}
|
|
2819
|
+
},
|
|
2820
|
+
available: schedules,
|
|
2821
|
+
async run(input) {
|
|
2822
|
+
const size = limitOf(input);
|
|
2823
|
+
const offset = offsetOf(input);
|
|
2824
|
+
const workflow = str(input.workflow);
|
|
2825
|
+
const tag = str(input.tag);
|
|
2826
|
+
const namespace = str(input.namespace);
|
|
2827
|
+
const rows = await call(() => "schedules", () => service.listSchedules({
|
|
2828
|
+
...workflow !== void 0 ? {
|
|
2829
|
+
workflow
|
|
2830
|
+
} : {},
|
|
2831
|
+
...tag !== void 0 ? {
|
|
2832
|
+
tag
|
|
2833
|
+
} : {},
|
|
2834
|
+
...namespace !== void 0 ? {
|
|
2835
|
+
namespace
|
|
2836
|
+
} : {},
|
|
2837
|
+
...typeof input.paused === "boolean" ? {
|
|
2838
|
+
paused: input.paused
|
|
2839
|
+
} : {},
|
|
2840
|
+
offset,
|
|
2841
|
+
limit: size + 1
|
|
2842
|
+
}));
|
|
2843
|
+
return page(rows, offset, size);
|
|
2844
|
+
}
|
|
2845
|
+
},
|
|
2846
|
+
{
|
|
2847
|
+
name: "durable_get_run_event",
|
|
2848
|
+
kind: "read",
|
|
2849
|
+
description: "The latest value a run published for `key` with ctx.setEvent (a live query, no side effect). Returns { id, key, value }; value is null when the run never published that key. An error when no run has that id.",
|
|
2850
|
+
input: {
|
|
2851
|
+
type: "object",
|
|
2852
|
+
properties: {
|
|
2853
|
+
id: runId,
|
|
2854
|
+
key: {
|
|
2855
|
+
type: "string",
|
|
2856
|
+
description: "Event key."
|
|
2857
|
+
}
|
|
2858
|
+
},
|
|
2859
|
+
required: [
|
|
2860
|
+
"id",
|
|
2861
|
+
"key"
|
|
2862
|
+
]
|
|
2863
|
+
},
|
|
2864
|
+
available: controlPlane,
|
|
2865
|
+
async run(input) {
|
|
2866
|
+
const id = required(input, "id");
|
|
2867
|
+
const key = required(input, "key");
|
|
2868
|
+
if (!await call(() => `run ${id}`, () => service.runExists(id))) {
|
|
2869
|
+
throw new Error(`run ${id} not found`);
|
|
2870
|
+
}
|
|
2871
|
+
const value = await call(() => `run ${id}`, () => service.getEvent(id, key));
|
|
2872
|
+
return {
|
|
2873
|
+
id,
|
|
2874
|
+
key,
|
|
2875
|
+
value: value ?? null
|
|
2876
|
+
};
|
|
2877
|
+
}
|
|
2878
|
+
},
|
|
2879
|
+
{
|
|
2880
|
+
name: "durable_retry_run",
|
|
2881
|
+
kind: "action",
|
|
2882
|
+
description: `Re-runs a failed, dead or cancelled run; completed steps replay from their checkpoints. Returns { runId, status }. With ids (at most ${MAX_RUN_IDS}), runs them in order and stops at the first that fails: { applied, failed: { id, error }, skipped }. An error when no run has that id.`,
|
|
2883
|
+
input: {
|
|
2884
|
+
type: "object",
|
|
2885
|
+
properties: {
|
|
2886
|
+
id: runId,
|
|
2887
|
+
ids: runIds
|
|
2888
|
+
}
|
|
2889
|
+
},
|
|
2890
|
+
async run(input) {
|
|
2891
|
+
return each(input, async (id) => found(await call(() => `run ${id}`, () => service.retry(id)), `run ${id}`));
|
|
2892
|
+
}
|
|
2893
|
+
},
|
|
2894
|
+
{
|
|
2895
|
+
name: "durable_cancel_run",
|
|
2896
|
+
kind: "action",
|
|
2897
|
+
destructive: true,
|
|
2898
|
+
description: `Cancels a run that has not finished (with compensate: true, its completed steps' compensations run first). Returns { runId, status }. With ids (at most ${MAX_RUN_IDS}), cancels them in order and stops at the first that fails: { applied, failed: { id, error }, skipped }. An error when no run has that id.`,
|
|
2899
|
+
input: {
|
|
2900
|
+
type: "object",
|
|
2901
|
+
properties: {
|
|
2902
|
+
id: runId,
|
|
2903
|
+
ids: runIds,
|
|
2904
|
+
compensate: {
|
|
2905
|
+
type: "boolean",
|
|
2906
|
+
description: "Run compensations (default false)."
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
},
|
|
2910
|
+
async run(input) {
|
|
2911
|
+
const compensate = input.compensate === true;
|
|
2912
|
+
return each(input, async (id) => found(await call(() => `run ${id}`, () => service.cancel(id, {
|
|
2913
|
+
compensate
|
|
2914
|
+
})), `run ${id}`));
|
|
2915
|
+
}
|
|
2916
|
+
},
|
|
2917
|
+
{
|
|
2918
|
+
name: "durable_continue_run",
|
|
2919
|
+
kind: "action",
|
|
2920
|
+
description: "Resumes a run paused at a ctx.breakpoint. Returns { runId, status }. An error when no run has that id, or when it is not paused at a breakpoint.",
|
|
2921
|
+
input: {
|
|
2922
|
+
type: "object",
|
|
2923
|
+
properties: {
|
|
2924
|
+
id: runId
|
|
2925
|
+
},
|
|
2926
|
+
required: [
|
|
2927
|
+
"id"
|
|
2928
|
+
]
|
|
2929
|
+
},
|
|
2930
|
+
async run(input) {
|
|
2931
|
+
const id = required(input, "id");
|
|
2932
|
+
const what = /* @__PURE__ */ __name(() => `run ${id}`, "what");
|
|
2933
|
+
const result = await call(what, () => service.continue(id));
|
|
2934
|
+
if (result) return result;
|
|
2935
|
+
if (!await call(what, () => service.runExists(id))) throw new Error(`run ${id} not found`);
|
|
2936
|
+
throw new Error(`run ${id} is not paused at a breakpoint`);
|
|
2937
|
+
}
|
|
2938
|
+
},
|
|
2939
|
+
{
|
|
2940
|
+
name: "durable_signal_run",
|
|
2941
|
+
kind: "action",
|
|
2942
|
+
description: "Sends a signal: delivers payload (JSON text; omitted is null) to the run waiting on token (ctx.waitForSignal or a ctx.webhook token). Returns { delivered: true, runId, status }, or { delivered: false } when no run you can see waits on the token yet: the engine then buffers the payload for the next run that waits on it.",
|
|
2943
|
+
input: {
|
|
2944
|
+
type: "object",
|
|
2945
|
+
properties: {
|
|
2946
|
+
token: {
|
|
2947
|
+
type: "string",
|
|
2948
|
+
description: "The signal token the run waits on."
|
|
2949
|
+
},
|
|
2950
|
+
payload: {
|
|
2951
|
+
type: "string",
|
|
2952
|
+
description: "The payload, as JSON text."
|
|
2953
|
+
}
|
|
2954
|
+
},
|
|
2955
|
+
required: [
|
|
2956
|
+
"token"
|
|
2957
|
+
]
|
|
2958
|
+
},
|
|
2959
|
+
available: controlPlane,
|
|
2960
|
+
async run(input) {
|
|
2961
|
+
const token = required(input, "token");
|
|
2962
|
+
let payload = null;
|
|
2963
|
+
if (typeof input.payload === "string" && input.payload.trim() !== "") {
|
|
2964
|
+
try {
|
|
2965
|
+
payload = JSON.parse(input.payload);
|
|
2966
|
+
} catch {
|
|
2967
|
+
throw new Error('"payload" must be JSON text (quote a plain string: "\\"ok\\"")');
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
const result = await call(() => `token ${token}`, () => service.signal(token, payload));
|
|
2971
|
+
return result ? {
|
|
2972
|
+
delivered: true,
|
|
2973
|
+
runId: result.runId,
|
|
2974
|
+
status: result.status
|
|
2975
|
+
} : {
|
|
2976
|
+
delivered: false
|
|
2977
|
+
};
|
|
2978
|
+
}
|
|
2979
|
+
},
|
|
2980
|
+
{
|
|
2981
|
+
name: "durable_trigger_schedule",
|
|
2982
|
+
kind: "action",
|
|
2983
|
+
description: "Starts one run of a schedule now, outside its cadence (it does not count as a fire). Returns { runId, status }. An error when no schedule has that id.",
|
|
2984
|
+
input: {
|
|
2985
|
+
type: "object",
|
|
2986
|
+
properties: {
|
|
2987
|
+
key: scheduleKey
|
|
2988
|
+
},
|
|
2989
|
+
required: [
|
|
2990
|
+
"key"
|
|
2991
|
+
]
|
|
2992
|
+
},
|
|
2993
|
+
available: schedules,
|
|
2994
|
+
async run(input) {
|
|
2995
|
+
const key = required(input, "key");
|
|
2996
|
+
return call(() => `schedule ${key}`, () => service.triggerSchedule(key));
|
|
2997
|
+
}
|
|
2998
|
+
},
|
|
2999
|
+
{
|
|
3000
|
+
name: "durable_pause_schedule",
|
|
3001
|
+
kind: "action",
|
|
3002
|
+
description: "Pauses a schedule (paused: true, the default) or resumes it from its next window (paused: false). Returns the schedule. An error when no schedule has that id.",
|
|
3003
|
+
input: {
|
|
3004
|
+
type: "object",
|
|
3005
|
+
properties: {
|
|
3006
|
+
key: scheduleKey,
|
|
3007
|
+
paused: {
|
|
3008
|
+
type: "boolean",
|
|
3009
|
+
description: "false resumes it (default true)."
|
|
3010
|
+
}
|
|
3011
|
+
},
|
|
3012
|
+
required: [
|
|
3013
|
+
"key"
|
|
3014
|
+
]
|
|
3015
|
+
},
|
|
3016
|
+
available: schedules,
|
|
3017
|
+
async run(input) {
|
|
3018
|
+
const key = required(input, "key");
|
|
3019
|
+
return call(() => `schedule ${key}`, () => input.paused === false ? service.resumeSchedule(key) : service.pauseSchedule(key));
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
];
|
|
3023
|
+
}
|
|
3024
|
+
__name(durableDevTools, "durableDevTools");
|
|
3025
|
+
var logger2 = new import_common8.Logger("DurableDashboardModule");
|
|
3026
|
+
var DurableDevToolsRegistration = class {
|
|
3027
|
+
static {
|
|
3028
|
+
__name(this, "DurableDevToolsRegistration");
|
|
3029
|
+
}
|
|
3030
|
+
enabled;
|
|
3031
|
+
service;
|
|
3032
|
+
decide;
|
|
3033
|
+
#unregister;
|
|
3034
|
+
constructor(enabled, service, decide) {
|
|
3035
|
+
this.enabled = enabled;
|
|
3036
|
+
this.service = service;
|
|
3037
|
+
this.decide = decide;
|
|
3038
|
+
}
|
|
3039
|
+
onModuleInit() {
|
|
3040
|
+
if (!this.enabled) return;
|
|
3041
|
+
const slot = devToolsSlot();
|
|
3042
|
+
if (slot.version !== 1 || typeof slot.register !== "function") return;
|
|
3043
|
+
try {
|
|
3044
|
+
this.#unregister = slot.register({
|
|
3045
|
+
lib: "durable",
|
|
3046
|
+
title: "Durable workflows",
|
|
3047
|
+
authorize: /* @__PURE__ */ __name((context) => this.decide(context), "authorize"),
|
|
3048
|
+
tools: durableDevTools(this.service)
|
|
3049
|
+
});
|
|
3050
|
+
} catch (error) {
|
|
3051
|
+
logger2.warn(`durable dev tools not registered: ${error instanceof Error ? error.message : String(error)}`);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
onModuleDestroy() {
|
|
3055
|
+
this.#unregister?.();
|
|
3056
|
+
this.#unregister = void 0;
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
DurableDevToolsRegistration = _ts_decorate8([
|
|
3060
|
+
(0, import_common8.Injectable)(),
|
|
3061
|
+
_ts_param5(0, (0, import_common8.Inject)(DASHBOARD_DEV_TOOLS)),
|
|
3062
|
+
_ts_param5(1, (0, import_common8.Inject)(DashboardService)),
|
|
3063
|
+
_ts_param5(2, (0, import_common8.Inject)(CONSOLE_AUTHORIZE_DECIDE)),
|
|
3064
|
+
_ts_metadata7("design:type", Function),
|
|
3065
|
+
_ts_metadata7("design:paramtypes", [
|
|
3066
|
+
Boolean,
|
|
3067
|
+
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
3068
|
+
typeof ConsoleDecide === "undefined" ? Object : ConsoleDecide
|
|
3069
|
+
])
|
|
3070
|
+
], DurableDevToolsRegistration);
|
|
3071
|
+
|
|
2012
3072
|
// src/server/durable-ui.controller.ts
|
|
2013
3073
|
var import_node_fs = require("fs");
|
|
2014
3074
|
var import_node_path = require("path");
|
|
2015
3075
|
var import_node_url = require("url");
|
|
2016
|
-
var
|
|
2017
|
-
function
|
|
3076
|
+
var import_common9 = require("@nestjs/common");
|
|
3077
|
+
function _ts_decorate9(decorators, target, key, desc) {
|
|
2018
3078
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2019
3079
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2020
3080
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2027,21 +3087,20 @@ function _ts_decorate7(decorators, target, key, desc) {
|
|
|
2027
3087
|
}
|
|
2028
3088
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2029
3089
|
}
|
|
2030
|
-
__name(
|
|
2031
|
-
function
|
|
3090
|
+
__name(_ts_decorate9, "_ts_decorate");
|
|
3091
|
+
function _ts_metadata8(metadataKey, metadataValue) {
|
|
2032
3092
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2033
3093
|
return Reflect.metadata(metadataKey, metadataValue);
|
|
2034
3094
|
}
|
|
2035
3095
|
}
|
|
2036
|
-
__name(
|
|
2037
|
-
function
|
|
3096
|
+
__name(_ts_metadata8, "_ts_metadata");
|
|
3097
|
+
function _ts_param6(paramIndex, decorator) {
|
|
2038
3098
|
return function(target, key) {
|
|
2039
3099
|
decorator(target, key, paramIndex);
|
|
2040
3100
|
};
|
|
2041
3101
|
}
|
|
2042
|
-
__name(
|
|
2043
|
-
var
|
|
2044
|
-
var DASHBOARD_API_PATH = Symbol("DASHBOARD_API_PATH");
|
|
3102
|
+
__name(_ts_param6, "_ts_param");
|
|
3103
|
+
var DURABLE_DASHBOARD_CONFIG_ID = "durable-dashboard-config";
|
|
2045
3104
|
var BUILD_BASE = "/durable";
|
|
2046
3105
|
function spaDir() {
|
|
2047
3106
|
return (0, import_node_url.fileURLToPath)(new URL("../spa", __importMetaUrl));
|
|
@@ -2072,51 +3131,65 @@ var DurableUiControllerBase = class {
|
|
|
2072
3131
|
index() {
|
|
2073
3132
|
const indexPath = (0, import_node_path.join)(this.dir, "index.html");
|
|
2074
3133
|
if (!(0, import_node_fs.existsSync)(indexPath)) {
|
|
2075
|
-
throw new
|
|
3134
|
+
throw new import_common9.NotFoundException("Dashboard is not built. Run the package build.");
|
|
2076
3135
|
}
|
|
2077
3136
|
const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
2078
|
-
const inject = `<script>window.__DURABLE_BASE__='${this.basePath}';window.__DURABLE_API__='${this.apiBasePath}';</script
|
|
3137
|
+
const inject = `<script>window.__DURABLE_BASE__='${this.basePath}';window.__DURABLE_API__='${this.apiBasePath}';</script>${this.configBlock()}`;
|
|
2079
3138
|
return html.includes("</head>") ? html.replace("</head>", `${inject}</head>`) : inject + html;
|
|
2080
3139
|
}
|
|
3140
|
+
/**
|
|
3141
|
+
* The page's JSON config block (`durable-dashboard-config`, CSP-safe: data, not script). It
|
|
3142
|
+
* carries `switcher` only when another Aviary console is registered.
|
|
3143
|
+
*/
|
|
3144
|
+
configBlock() {
|
|
3145
|
+
const switcher = consoleSwitcherConfig(DURABLE_CONSOLE_ID, `${this.apiBasePath}/consoles`);
|
|
3146
|
+
const json = JSON.stringify({
|
|
3147
|
+
apiBase: this.apiBasePath,
|
|
3148
|
+
...switcher !== void 0 ? {
|
|
3149
|
+
switcher
|
|
3150
|
+
} : {}
|
|
3151
|
+
}).replaceAll("<", "\\u003c");
|
|
3152
|
+
return `<script type="application/json" id="${DURABLE_DASHBOARD_CONFIG_ID}">${json}</script>`;
|
|
3153
|
+
}
|
|
2081
3154
|
asset(file) {
|
|
2082
3155
|
const safe = (0, import_node_path.basename)(file);
|
|
2083
|
-
if (safe !== file) throw new
|
|
3156
|
+
if (safe !== file) throw new import_common9.NotFoundException();
|
|
2084
3157
|
const root = (0, import_node_path.resolve)(this.dir, "assets");
|
|
2085
3158
|
const assetPath = (0, import_node_path.resolve)(root, safe);
|
|
2086
3159
|
if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
|
|
2087
|
-
throw new
|
|
3160
|
+
throw new import_common9.NotFoundException();
|
|
2088
3161
|
}
|
|
2089
3162
|
const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
|
|
2090
|
-
return new
|
|
3163
|
+
return new import_common9.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
|
|
2091
3164
|
type
|
|
2092
3165
|
});
|
|
2093
3166
|
}
|
|
2094
3167
|
};
|
|
2095
|
-
|
|
2096
|
-
(0,
|
|
2097
|
-
(0,
|
|
2098
|
-
(0,
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
3168
|
+
_ts_decorate9([
|
|
3169
|
+
(0, import_common9.Get)(),
|
|
3170
|
+
(0, import_common9.Header)("Content-Type", "text/html; charset=utf-8"),
|
|
3171
|
+
(0, import_common9.Header)("Cache-Control", "no-store, must-revalidate"),
|
|
3172
|
+
_ts_metadata8("design:type", Function),
|
|
3173
|
+
_ts_metadata8("design:paramtypes", []),
|
|
3174
|
+
_ts_metadata8("design:returntype", String)
|
|
2102
3175
|
], DurableUiControllerBase.prototype, "index", null);
|
|
2103
|
-
|
|
2104
|
-
(0,
|
|
2105
|
-
(0,
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
3176
|
+
_ts_decorate9([
|
|
3177
|
+
(0, import_common9.Get)("assets/:file"),
|
|
3178
|
+
(0, import_common9.Header)("Cache-Control", "public, max-age=31536000, immutable"),
|
|
3179
|
+
_ts_param6(0, (0, import_common9.Param)("file")),
|
|
3180
|
+
_ts_metadata8("design:type", Function),
|
|
3181
|
+
_ts_metadata8("design:paramtypes", [
|
|
2109
3182
|
String
|
|
2110
3183
|
]),
|
|
2111
|
-
|
|
3184
|
+
_ts_metadata8("design:returntype", typeof import_common9.StreamableFile === "undefined" ? Object : import_common9.StreamableFile)
|
|
2112
3185
|
], DurableUiControllerBase.prototype, "asset", null);
|
|
2113
|
-
DurableUiControllerBase =
|
|
2114
|
-
(0,
|
|
3186
|
+
DurableUiControllerBase = _ts_decorate9([
|
|
3187
|
+
(0, import_common9.Controller)(),
|
|
2115
3188
|
ConsolePage(),
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
3189
|
+
_ts_param6(0, (0, import_common9.Inject)(DASHBOARD_BASE_PATH)),
|
|
3190
|
+
_ts_param6(1, (0, import_common9.Inject)(DASHBOARD_API_PATH)),
|
|
3191
|
+
_ts_metadata8("design:type", Function),
|
|
3192
|
+
_ts_metadata8("design:paramtypes", [
|
|
2120
3193
|
String,
|
|
2121
3194
|
String
|
|
2122
3195
|
])
|
|
@@ -2126,12 +3199,12 @@ var DurableUiController = class extends DurableUiControllerBase {
|
|
|
2126
3199
|
__name(this, "DurableUiController");
|
|
2127
3200
|
}
|
|
2128
3201
|
};
|
|
2129
|
-
DurableUiController =
|
|
2130
|
-
(0,
|
|
3202
|
+
DurableUiController = _ts_decorate9([
|
|
3203
|
+
(0, import_common9.Controller)()
|
|
2131
3204
|
], DurableUiController);
|
|
2132
3205
|
|
|
2133
3206
|
// src/server/durable-dashboard.module.ts
|
|
2134
|
-
function
|
|
3207
|
+
function _ts_decorate10(decorators, target, key, desc) {
|
|
2135
3208
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2136
3209
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2137
3210
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2144,9 +3217,10 @@ function _ts_decorate8(decorators, target, key, desc) {
|
|
|
2144
3217
|
}
|
|
2145
3218
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2146
3219
|
}
|
|
2147
|
-
__name(
|
|
3220
|
+
__name(_ts_decorate10, "_ts_decorate");
|
|
2148
3221
|
markOpenToAuthorization(DurableApiController);
|
|
2149
3222
|
markOpenToAuthorization(DurableUiController);
|
|
3223
|
+
markOpenToAuthorization(DurableConsolesController);
|
|
2150
3224
|
function assertNothingToDecorate(options) {
|
|
2151
3225
|
if (options.decorators === void 0) return;
|
|
2152
3226
|
throw new Error([
|
|
@@ -2180,10 +3254,16 @@ var DurableApiModule = class _DurableApiModule {
|
|
|
2180
3254
|
...options.imports ?? []
|
|
2181
3255
|
],
|
|
2182
3256
|
controllers: routes ? [
|
|
2183
|
-
consoleController(DurableApiController, options.decorators)
|
|
3257
|
+
consoleController(DurableApiController, options.decorators),
|
|
3258
|
+
consoleController(DurableConsolesController, options.decorators)
|
|
2184
3259
|
] : [],
|
|
2185
3260
|
providers: [
|
|
2186
3261
|
DashboardService,
|
|
3262
|
+
{
|
|
3263
|
+
provide: DASHBOARD_DEV_TOOLS,
|
|
3264
|
+
useValue: options.devTools ?? routes
|
|
3265
|
+
},
|
|
3266
|
+
DurableDevToolsRegistration,
|
|
2187
3267
|
// Resolved at boot: a gate name without nestjs-authz, or a policy without
|
|
2188
3268
|
// @nestjs/authorization, fails here rather than on the first request.
|
|
2189
3269
|
{
|
|
@@ -2241,8 +3321,8 @@ var DurableApiModule = class _DurableApiModule {
|
|
|
2241
3321
|
};
|
|
2242
3322
|
}
|
|
2243
3323
|
};
|
|
2244
|
-
DurableApiModule =
|
|
2245
|
-
(0,
|
|
3324
|
+
DurableApiModule = _ts_decorate10([
|
|
3325
|
+
(0, import_common10.Module)({})
|
|
2246
3326
|
], DurableApiModule);
|
|
2247
3327
|
var DurableDashboardModule = class _DurableDashboardModule {
|
|
2248
3328
|
static {
|
|
@@ -2270,6 +3350,9 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
2270
3350
|
...options.authorize !== void 0 ? {
|
|
2271
3351
|
authorize: options.authorize
|
|
2272
3352
|
} : {},
|
|
3353
|
+
...options.devTools !== void 0 ? {
|
|
3354
|
+
devTools: options.devTools
|
|
3355
|
+
} : {},
|
|
2273
3356
|
routes: false
|
|
2274
3357
|
});
|
|
2275
3358
|
return {
|
|
@@ -2306,6 +3389,9 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
2306
3389
|
} : {},
|
|
2307
3390
|
...options.authorize !== void 0 ? {
|
|
2308
3391
|
authorize: options.authorize
|
|
3392
|
+
} : {},
|
|
3393
|
+
...options.devTools !== void 0 ? {
|
|
3394
|
+
devTools: options.devTools
|
|
2309
3395
|
} : {}
|
|
2310
3396
|
}),
|
|
2311
3397
|
import_core2.RouterModule.register([
|
|
@@ -2322,7 +3408,11 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
2322
3408
|
controllers: [
|
|
2323
3409
|
consoleController(DurableUiController, options.decorators)
|
|
2324
3410
|
],
|
|
2325
|
-
|
|
3411
|
+
// The console switcher lists this console only where it serves its own page.
|
|
3412
|
+
providers: [
|
|
3413
|
+
...pathProviders,
|
|
3414
|
+
DurableConsoleRegistration
|
|
3415
|
+
],
|
|
2326
3416
|
// Re-export the API module so its DashboardService reaches importers (e.g. flip's own controllers).
|
|
2327
3417
|
exports: [
|
|
2328
3418
|
DurableApiModule
|
|
@@ -2330,31 +3420,46 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
2330
3420
|
};
|
|
2331
3421
|
}
|
|
2332
3422
|
};
|
|
2333
|
-
DurableDashboardModule =
|
|
2334
|
-
(0,
|
|
3423
|
+
DurableDashboardModule = _ts_decorate10([
|
|
3424
|
+
(0, import_common10.Module)({})
|
|
2335
3425
|
], DurableDashboardModule);
|
|
2336
3426
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2337
3427
|
0 && (module.exports = {
|
|
3428
|
+
AVIARY_CONSOLES_SLOT,
|
|
2338
3429
|
CONSOLE_AUTHORIZE_DECIDE,
|
|
2339
3430
|
CONSOLE_AUTHORIZE_MISSING_WARNING,
|
|
2340
3431
|
CONSOLE_GATE,
|
|
2341
3432
|
CONSOLE_PAGE_METADATA,
|
|
3433
|
+
CONSOLE_PROBE_TIMEOUT_MS,
|
|
3434
|
+
CONSOLE_PUBLIC_METADATA,
|
|
2342
3435
|
ConsoleAccessDenied,
|
|
2343
3436
|
ConsoleAuthorizeFilter,
|
|
2344
3437
|
ConsoleAuthorizeGuard,
|
|
2345
3438
|
ConsolePage,
|
|
3439
|
+
ConsolePublic,
|
|
2346
3440
|
DASHBOARD_API_PATH,
|
|
2347
3441
|
DASHBOARD_BASE_PATH,
|
|
3442
|
+
DEV_TOOLS_SLOT,
|
|
3443
|
+
DURABLE_CONSOLE_ID,
|
|
3444
|
+
DURABLE_DASHBOARD_CONFIG_ID,
|
|
2348
3445
|
DashboardService,
|
|
2349
3446
|
DurableApiController,
|
|
2350
3447
|
DurableApiControllerBase,
|
|
2351
3448
|
DurableApiModule,
|
|
3449
|
+
DurableConsoleRegistration,
|
|
3450
|
+
DurableConsolesController,
|
|
2352
3451
|
DurableDashboardModule,
|
|
3452
|
+
DurableDevToolsRegistration,
|
|
2353
3453
|
DurableUiController,
|
|
2354
3454
|
DurableUiControllerBase,
|
|
3455
|
+
MAX_RUN_IDS,
|
|
2355
3456
|
UseConsoleAuthorize,
|
|
3457
|
+
anyAuthorize,
|
|
2356
3458
|
authorizeByToken,
|
|
3459
|
+
durableDevTools,
|
|
3460
|
+
listVisibleConsoles,
|
|
2357
3461
|
normalizeConsoleResult,
|
|
3462
|
+
registerAviaryConsole,
|
|
2358
3463
|
resolveConsoleAuthorize
|
|
2359
3464
|
});
|
|
2360
3465
|
//# sourceMappingURL=index.cjs.map
|