@dudousxd/nestjs-durable-dashboard 0.43.2 → 0.44.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.
@@ -140,6 +140,12 @@ var DashboardService = class {
140
140
  runFacets(query) {
141
141
  return this.gateway.runFacets(query);
142
142
  }
143
+ /** The distinct values of one filter axis over the same predicates — what fills the console's
144
+ * tenant/tag/attribute pickers, so an operator picks a value that exists instead of typing one
145
+ * blind. `[]` when the store cannot enumerate them; the pickers then fall back to free text. */
146
+ runValueFacets(axis, query, opts) {
147
+ return this.gateway.runValueFacets(axis, query, opts);
148
+ }
143
149
  /** This deployment's durable role (control plane vs tenant) + tenant name — for the dashboard header
144
150
  * badge. Routes through the gateway, which knows its own topology (store-backed = operator, proxy =
145
151
  * tenant). Works on both topologies (no store/engine needed). */
@@ -248,10 +254,95 @@ DashboardService = _ts_decorate([
248
254
  ], DashboardService);
249
255
 
250
256
  // src/server/durable-api.controller.ts
251
- var import_common2 = require("@nestjs/common");
257
+ var import_nestjs_filter2 = require("@dudousxd/nestjs-filter");
258
+ var import_common4 = require("@nestjs/common");
259
+
260
+ // src/server/durable-run.ts
261
+ var DurableRun = class {
262
+ static {
263
+ __name(this, "DurableRun");
264
+ }
265
+ workflow;
266
+ status;
267
+ /** `null` for a run no package claims — see `WorkflowRun.origin`. */
268
+ origin;
269
+ /** Tenant / worker-pool partition. */
270
+ namespace;
271
+ /**
272
+ * ONE of the run's tags. Singular deliberately: a run carries a SET of tags, so a predicate here
273
+ * asks about membership (`tag in [etl, nightly]` = runs carrying either), never equality with the
274
+ * whole set.
275
+ */
276
+ tag;
277
+ /** Typed search attributes, addressed per key as `attr.<key>` — a JSON sub-path, not a column. */
278
+ attr;
279
+ };
280
+ var ATTRIBUTE_FIELD = "attr";
281
+ var DURABLE_RUN_FIELDS = [
282
+ {
283
+ name: "workflow",
284
+ columnName: "workflow",
285
+ type: "string"
286
+ },
287
+ {
288
+ name: "status",
289
+ columnName: "status",
290
+ type: "string"
291
+ },
292
+ {
293
+ name: "origin",
294
+ columnName: "origin",
295
+ type: "string"
296
+ },
297
+ {
298
+ name: "namespace",
299
+ columnName: "namespace",
300
+ type: "string"
301
+ },
302
+ {
303
+ name: "tag",
304
+ columnName: "tags",
305
+ type: "string"
306
+ },
307
+ {
308
+ name: ATTRIBUTE_FIELD,
309
+ columnName: "search_attributes",
310
+ type: "json"
311
+ }
312
+ ];
313
+ function runValueAxisFor(field) {
314
+ if (field === ATTRIBUTE_FIELD) return {
315
+ field: "attributeKey"
316
+ };
317
+ if (field.startsWith(`${ATTRIBUTE_FIELD}.`)) {
318
+ const key = field.slice(ATTRIBUTE_FIELD.length + 1);
319
+ return key ? {
320
+ field: "attributeValue",
321
+ key
322
+ } : null;
323
+ }
324
+ if (field === "workflow" || field === "status" || field === "origin" || field === "namespace" || field === "tag") {
325
+ return {
326
+ field
327
+ };
328
+ }
329
+ return null;
330
+ }
331
+ __name(runValueAxisFor, "runValueAxisFor");
332
+
333
+ // src/server/run-list-row.ts
334
+ function toRunListRow(run) {
335
+ const { input: _input, output: _output, error: _error, ...row } = run;
336
+ return row;
337
+ }
338
+ __name(toRunListRow, "toRunListRow");
339
+
340
+ // src/server/run.filter.ts
341
+ var import_nestjs_filter = require("@dudousxd/nestjs-filter");
342
+ var import_common3 = require("@nestjs/common");
252
343
 
253
344
  // src/server/attr-filter.ts
254
- var ATTR_OPS = /* @__PURE__ */ new Set([
345
+ var SCALAR_OPS = /* @__PURE__ */ new Set([
255
346
  "eq",
256
347
  "ne",
257
348
  "gt",
@@ -259,6 +350,7 @@ var ATTR_OPS = /* @__PURE__ */ new Set([
259
350
  "lt",
260
351
  "lte"
261
352
  ]);
353
+ var IN_SEPARATOR = "|";
262
354
  function coerce(v) {
263
355
  if (v === "true") return true;
264
356
  if (v === "false") return false;
@@ -274,25 +366,60 @@ function parseAttrFilters(attr) {
274
366
  const filters = [];
275
367
  for (const entry of raw) {
276
368
  const [key, op, ...rest] = entry.split(":");
277
- if (!key || !ATTR_OPS.has(op) || rest.length === 0) continue;
369
+ if (!key || rest.length === 0) continue;
370
+ const operand = rest.join(":");
371
+ if (op === "in") {
372
+ const values = operand.split(IN_SEPARATOR).filter(Boolean).map(coerce);
373
+ if (values.length) filters.push({
374
+ key,
375
+ op: "in",
376
+ values
377
+ });
378
+ continue;
379
+ }
380
+ if (!SCALAR_OPS.has(op)) continue;
278
381
  filters.push({
279
382
  key,
280
383
  op,
281
- value: coerce(rest.join(":"))
384
+ value: coerce(operand)
282
385
  });
283
386
  }
284
387
  return filters.length ? filters : void 0;
285
388
  }
286
389
  __name(parseAttrFilters, "parseAttrFilters");
287
390
 
288
- // src/server/run-list-row.ts
289
- function toRunListRow(run) {
290
- const { input: _input, output: _output, error: _error, ...row } = run;
291
- return row;
292
- }
293
- __name(toRunListRow, "toRunListRow");
391
+ // src/server/run-query.adapter.ts
392
+ var import_nestjs_durable_core2 = require("@dudousxd/nestjs-durable-core");
393
+ var import_common2 = require("@nestjs/common");
294
394
 
295
- // src/server/durable-api.controller.ts
395
+ // src/server/run-query-draft.ts
396
+ var RunQueryDraft2 = class {
397
+ static {
398
+ __name(this, "RunQueryDraft");
399
+ }
400
+ query = {};
401
+ /** Narrow by one or more predicates. Later calls overwrite the same field — the runner applies one
402
+ * clause per field, so the last one wins, exactly as a repeated `where` on a builder would. */
403
+ narrow(patch) {
404
+ Object.assign(this.query, patch);
405
+ }
406
+ /** Add one search-attribute predicate. These ACCUMULATE (unlike {@link narrow}) because
407
+ * `RunQuery.attributes` is an ANDed list — two predicates on different keys are both meant. */
408
+ attribute(filter) {
409
+ this.query.attributes = [
410
+ ...this.query.attributes ?? [],
411
+ filter
412
+ ];
413
+ }
414
+ /** The predicates minus the page window and the axes a facet count reports on — what
415
+ * `runFacets`/`runValueFacets` are taken over. */
416
+ facetQuery() {
417
+ const { status, statuses, origin, origins, limit, offset, ...facetQuery } = this.query;
418
+ return facetQuery;
419
+ }
420
+ };
421
+
422
+ // src/server/run-query.adapter.ts
296
423
  function _ts_decorate2(decorators, target, key, desc) {
297
424
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
298
425
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -304,73 +431,527 @@ function _ts_metadata2(k, v) {
304
431
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
305
432
  }
306
433
  __name(_ts_metadata2, "_ts_metadata");
434
+ var RUN_QUERY_ADAPTER = Symbol("DURABLE_RUN_QUERY_ADAPTER");
435
+ var FIXED_ORDER = {
436
+ field: "createdAt",
437
+ direction: "desc"
438
+ };
439
+ function coerce2(value) {
440
+ if (typeof value === "number" || typeof value === "boolean") return value;
441
+ const raw = String(value);
442
+ if (raw === "true") return true;
443
+ if (raw === "false") return false;
444
+ if (raw !== "" && !Number.isNaN(Number(raw))) return Number(raw);
445
+ return raw;
446
+ }
447
+ __name(coerce2, "coerce");
448
+ function operands(clause) {
449
+ return Array.isArray(clause.value) ? clause.value : [
450
+ clause.value
451
+ ];
452
+ }
453
+ __name(operands, "operands");
454
+ function unsupported(clause, supported) {
455
+ throw new import_common2.BadRequestException(`The durable run list cannot filter \`${clause.field}\` with \`${clause.operator}\`. Supported here: ${supported}.`);
456
+ }
457
+ __name(unsupported, "unsupported");
458
+ var RunQueryAdapter = class {
459
+ static {
460
+ __name(this, "RunQueryAdapter");
461
+ }
462
+ gateway;
463
+ constructor(gateway) {
464
+ this.gateway = gateway;
465
+ }
466
+ createQueryBuilder(entity) {
467
+ this.assertDurableRun(entity);
468
+ return new RunQueryDraft2();
469
+ }
470
+ getEntityFields(entity) {
471
+ return entity === DurableRun ? DURABLE_RUN_FIELDS : null;
472
+ }
473
+ /** No relations: a run is a flat row here, and the one nested-looking address (`attr.<key>`) is a
474
+ * JSON path. Returning `[]` (not null) tells the runner the answer is "none", not "can't say". */
475
+ getEntityRelations() {
476
+ return [];
477
+ }
478
+ /**
479
+ * Which addresses resolve, and as what. `attr` and `attr.<key>` are JSON paths — that classification
480
+ * is what routes a flat `?attr.tier=pro` through the same translation as a structured
481
+ * `where[attr.tier]`, instead of it being dropped as an unknown key.
482
+ */
483
+ resolveFieldPath(entity, path) {
484
+ if (entity !== DurableRun) return null;
485
+ if (path === ATTRIBUTE_FIELD || path.startsWith(`${ATTRIBUTE_FIELD}.`)) return "json";
486
+ return DURABLE_RUN_FIELDS.some((f) => f.name === path) ? "field" : null;
487
+ }
488
+ applyColumnFilters(qb, filters, entity) {
489
+ if (entity) this.assertDurableRun(entity);
490
+ const draft = this.draft(qb);
491
+ for (const clause of filters) {
492
+ if (clause.AND || clause.OR) {
493
+ throw new import_common2.BadRequestException("The durable run list cannot filter with nested AND/OR groups: its predicates are a flat conjunction.");
494
+ }
495
+ this.applyClause(draft, clause);
496
+ }
497
+ }
498
+ applyClause(draft, clause) {
499
+ const { field, operator } = clause;
500
+ if (field === ATTRIBUTE_FIELD || field.startsWith(`${ATTRIBUTE_FIELD}.`)) {
501
+ this.applyAttributeClause(draft, clause);
502
+ return;
503
+ }
504
+ const anyOf = operator === "in" || operator === "isAnyOf";
505
+ switch (field) {
506
+ case "status":
507
+ if (operator === "equals") {
508
+ draft.narrow({
509
+ status: String(clause.value)
510
+ });
511
+ } else if (anyOf) {
512
+ draft.narrow({
513
+ statuses: operands(clause).map((v) => String(v))
514
+ });
515
+ } else {
516
+ unsupported(clause, "equals, in");
517
+ }
518
+ return;
519
+ case "workflow":
520
+ if (operator === "equals") {
521
+ draft.narrow({
522
+ workflow: String(clause.value)
523
+ });
524
+ } else if (anyOf) {
525
+ draft.narrow({
526
+ workflows: operands(clause).map(String)
527
+ });
528
+ } else {
529
+ unsupported(clause, "equals, in");
530
+ }
531
+ return;
532
+ case "namespace":
533
+ if (operator === "equals") {
534
+ draft.narrow({
535
+ namespace: String(clause.value)
536
+ });
537
+ } else if (anyOf) {
538
+ draft.narrow({
539
+ namespaces: operands(clause).map(String)
540
+ });
541
+ } else {
542
+ unsupported(clause, "equals, in");
543
+ }
544
+ return;
545
+ case "tag":
546
+ if (operator === "equals") {
547
+ draft.narrow({
548
+ tag: String(clause.value)
549
+ });
550
+ } else if (anyOf) {
551
+ draft.narrow({
552
+ tags: operands(clause).map(String)
553
+ });
554
+ } else {
555
+ unsupported(clause, "equals, in");
556
+ }
557
+ return;
558
+ case "origin":
559
+ if (operator === "isNull") {
560
+ draft.narrow({
561
+ origin: null
562
+ });
563
+ } else if (operator === "equals") {
564
+ draft.narrow({
565
+ origin: clause.value === null ? null : String(clause.value)
566
+ });
567
+ } else if (anyOf) {
568
+ draft.narrow({
569
+ origins: operands(clause).map((v) => v === null ? null : String(v))
570
+ });
571
+ } else {
572
+ unsupported(clause, "equals, in, isNull");
573
+ }
574
+ return;
575
+ default:
576
+ unsupported(clause, `one of ${DURABLE_RUN_FIELDS.map((f) => f.name).join(", ")}`);
577
+ }
578
+ }
579
+ /** `attr.<key>` → one {@link AttributeFilter}. The operator set is the store's, so the mapping is
580
+ * 1:1 and anything outside it is rejected rather than approximated. */
581
+ applyAttributeClause(draft, clause) {
582
+ const key = clause.field.slice(ATTRIBUTE_FIELD.length + 1);
583
+ if (!key) {
584
+ throw new import_common2.BadRequestException("Filtering search attributes needs a key: `attr.<key>`, e.g. `attr.tier`.");
585
+ }
586
+ const scalarOps = {
587
+ equals: "eq",
588
+ notEquals: "ne",
589
+ gt: "gt",
590
+ gte: "gte",
591
+ lt: "lt",
592
+ lte: "lte"
593
+ };
594
+ const scalar = scalarOps[clause.operator];
595
+ if (scalar) {
596
+ draft.attribute({
597
+ key,
598
+ op: scalar,
599
+ value: coerce2(clause.value)
600
+ });
601
+ return;
602
+ }
603
+ if (clause.operator === "in" || clause.operator === "isAnyOf") {
604
+ draft.attribute({
605
+ key,
606
+ op: "in",
607
+ values: operands(clause).map(coerce2)
608
+ });
609
+ return;
610
+ }
611
+ unsupported(clause, "equals, notEquals, gt, gte, lt, lte, in");
612
+ }
613
+ applyOffsetPagination(qb, page2, size) {
614
+ this.draft(qb).narrow({
615
+ limit: size,
616
+ offset: (page2 - 1) * size
617
+ });
618
+ }
619
+ /**
620
+ * A run listing has ONE order — newest first — because that is what every store adapter's
621
+ * `listRuns` emits and what the console's paging depends on. A request for any other sort is
622
+ * refused rather than accepted and ignored: silently returning a differently-ordered page is how a
623
+ * paginated list starts duplicating and skipping rows.
624
+ */
625
+ applySort(_qb, sorts) {
626
+ for (const sort of sorts) {
627
+ if (sort.field !== FIXED_ORDER.field || sort.direction !== FIXED_ORDER.direction) {
628
+ throw new import_common2.BadRequestException(`The durable run list is always ordered \`${FIXED_ORDER.field} ${FIXED_ORDER.direction}\` and cannot be sorted by \`${sort.field} ${sort.direction}\`.`);
629
+ }
630
+ }
631
+ }
632
+ getResult(qb) {
633
+ return this.gateway.listRuns(this.draft(qb).query);
634
+ }
635
+ /**
636
+ * A page plus the size of the whole matching set. The total comes from the facet aggregate rather
637
+ * than from a second listing — that is the entire reason durable exposes one, and it keeps the
638
+ * count exact while the page stays bounded.
639
+ */
640
+ async getResultAndCount(qb) {
641
+ const draft = this.draft(qb);
642
+ const [rows, facets] = await Promise.all([
643
+ this.gateway.listRuns(draft.query),
644
+ this.gateway.runFacets(draft.facetQuery())
645
+ ]);
646
+ const { status, statuses, origin, origins } = draft.query;
647
+ const total = facets.filter((cell) => {
648
+ if (status && cell.status !== status) return false;
649
+ if (statuses && !statuses.includes(cell.status)) return false;
650
+ if (origin !== void 0 && cell.origin !== origin) return false;
651
+ if (origins && !origins.includes(cell.origin)) return false;
652
+ return true;
653
+ }).reduce((sum, cell) => sum + cell.count, 0);
654
+ return {
655
+ rows,
656
+ total
657
+ };
658
+ }
659
+ /**
660
+ * The distinct values of one field over the runs the active predicates select — the console's
661
+ * pickers. `limit` is honoured because it has to be: tag and search-attribute cardinality grows
662
+ * with the data, so the unbounded answer is a listing rather than an aggregate.
663
+ */
664
+ async groupByCount(qb, field, entity, opts) {
665
+ this.assertDurableRun(entity);
666
+ if (typeof field !== "string") {
667
+ throw new import_common2.BadRequestException("The durable run list has no computed fields to group by \u2014 group by one of its own fields.");
668
+ }
669
+ if (opts?.bucket !== void 0) {
670
+ throw new import_common2.BadRequestException("The durable run list cannot bucket a group-by-count: none of its filterable fields is numeric.");
671
+ }
672
+ const axis = runValueAxisFor(field);
673
+ if (!axis) {
674
+ throw new import_common2.BadRequestException(`The durable run list cannot enumerate values of \`${field}\`.`);
675
+ }
676
+ const rows = await this.gateway.runValueFacets(axis, this.draft(qb).facetQuery(), {
677
+ limit: opts?.limit ?? import_nestjs_durable_core2.RUN_VALUE_FACET_LIMIT
678
+ });
679
+ return rows.map((row) => ({
680
+ value: row.value,
681
+ count: row.count
682
+ }));
683
+ }
684
+ getPrimaryKey() {
685
+ return "id";
686
+ }
687
+ draft(qb) {
688
+ if (!(qb instanceof RunQueryDraft2)) {
689
+ throw new Error("The durable run adapter was handed a query builder it did not create. A filter using it must declare `@Filterable({ entity: DurableRun, adapter: RUN_QUERY_ADAPTER })`.");
690
+ }
691
+ return qb;
692
+ }
693
+ assertDurableRun(entity) {
694
+ if (entity !== DurableRun) {
695
+ throw new Error(`The durable run adapter only answers for DurableRun, not ${entity?.name ?? String(entity)}.`);
696
+ }
697
+ }
698
+ };
699
+ RunQueryAdapter = _ts_decorate2([
700
+ (0, import_common2.Injectable)(),
701
+ _ts_metadata2("design:type", Function),
702
+ _ts_metadata2("design:paramtypes", [
703
+ typeof import_nestjs_durable_core2.RunGateway === "undefined" ? Object : import_nestjs_durable_core2.RunGateway
704
+ ])
705
+ ], RunQueryAdapter);
706
+
707
+ // src/server/run.filter.ts
708
+ function _ts_decorate3(decorators, target, key, desc) {
709
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
710
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
711
+ 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;
712
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
713
+ }
714
+ __name(_ts_decorate3, "_ts_decorate");
715
+ function _ts_metadata3(k, v) {
716
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
717
+ }
718
+ __name(_ts_metadata3, "_ts_metadata");
719
+ function list(value) {
720
+ return (Array.isArray(value) ? value : [
721
+ value
722
+ ]).filter((v) => v !== void 0 && v !== null && v !== "").map(String);
723
+ }
724
+ __name(list, "list");
725
+ function bound(value) {
726
+ const n = Number(value);
727
+ return value !== void 0 && value !== "" && Number.isInteger(n) && n >= 0 ? n : void 0;
728
+ }
729
+ __name(bound, "bound");
730
+ var RunFilter = class extends import_nestjs_filter.BaseFilter {
731
+ static {
732
+ __name(this, "RunFilter");
733
+ }
734
+ /** One status narrows; several match ANY of them — how a caller asks for a SET (the console's
735
+ * in-flight sibling query, for one). */
736
+ applyStatus(value) {
737
+ const values = list(value);
738
+ if (values.length === 0) return;
739
+ this.$query.narrow(values.length === 1 ? {
740
+ status: values[0]
741
+ } : {
742
+ statuses: values
743
+ });
744
+ }
745
+ applyWorkflow(value) {
746
+ const values = list(value);
747
+ if (values.length === 0) return;
748
+ this.$query.narrow(values.length === 1 ? {
749
+ workflow: values[0]
750
+ } : {
751
+ workflows: values
752
+ });
753
+ }
754
+ /** A blank param (`?namespace=`, from a cleared filter box) is the same as an absent one; passing
755
+ * `''` through would be an exact match on a tenant nobody has, i.e. a silently empty console. */
756
+ applyNamespace(value) {
757
+ const values = list(value);
758
+ if (values.length === 0) return;
759
+ this.$query.narrow(values.length === 1 ? {
760
+ namespace: values[0]
761
+ } : {
762
+ namespaces: values
763
+ });
764
+ }
765
+ applyTag(value) {
766
+ const values = list(value);
767
+ if (values.length === 0) return;
768
+ this.$query.narrow(values.length === 1 ? {
769
+ tag: values[0]
770
+ } : {
771
+ tags: values
772
+ });
773
+ }
774
+ /**
775
+ * Origin has THREE states rather than two — a named package, the unattributed bucket, or no
776
+ * restriction — and the bucket rides on its own `unattributed` param rather than on a reserved
777
+ * `origin` value, because any reserved string is a package name someone can legitimately have and a
778
+ * console that quietly reinterpreted it would show the wrong runs.
779
+ *
780
+ * Both keys resolve through one function, called from either, reading the RAW input each time:
781
+ * the answer depends on both params, and `@FilterFor` dispatch follows the order the client's keys
782
+ * happen to arrive in. Recomputing from the input makes the result the same either way, where
783
+ * accumulating onto the draft would make `?origin=x&unattributed=true` mean different things
784
+ * depending on key order.
785
+ *
786
+ * Sent together they are a UNION, not a contradiction: `origins` carries the absent bucket
787
+ * alongside named packages, which is the "this package plus the runs nothing claims" view that a
788
+ * single `origin` value cannot express at all.
789
+ */
790
+ applyOrigin() {
791
+ this.resolveOrigin();
792
+ }
793
+ applyUnattributed() {
794
+ this.resolveOrigin();
795
+ }
796
+ resolveOrigin() {
797
+ const named = list(this.$input.origin);
798
+ const raw = this.$input.unattributed;
799
+ const wantsUnattributed = raw === "true" || raw === "1" || raw === true;
800
+ const values = [
801
+ ...named,
802
+ ...wantsUnattributed ? [
803
+ null
804
+ ] : []
805
+ ];
806
+ if (values.length === 0) return;
807
+ if (values.length === 1) {
808
+ const only = values[0];
809
+ this.$query.narrow({
810
+ origin: only
811
+ });
812
+ return;
813
+ }
814
+ this.$query.narrow({
815
+ origins: values
816
+ });
817
+ }
818
+ /** Comma/repeat-separated `key:op:value` predicates (e.g. `amount:gte:200`), ANDed. The structured
819
+ * spelling of the same thing is `filter[where][attr.amount][gte]=200`. */
820
+ applyAttributes(value) {
821
+ for (const filter of parseAttrFilters(value) ?? []) {
822
+ this.$query.attribute(filter);
823
+ }
824
+ }
825
+ applyLimit(value) {
826
+ const limit = bound(value);
827
+ if (limit !== void 0) this.$query.narrow({
828
+ limit
829
+ });
830
+ }
831
+ applyOffset(value) {
832
+ const offset = bound(value);
833
+ if (offset !== void 0) this.$query.narrow({
834
+ offset
835
+ });
836
+ }
837
+ };
838
+ _ts_decorate3([
839
+ (0, import_nestjs_filter.FilterFor)("status"),
840
+ _ts_metadata3("design:type", Function),
841
+ _ts_metadata3("design:paramtypes", [
842
+ Object
843
+ ]),
844
+ _ts_metadata3("design:returntype", void 0)
845
+ ], RunFilter.prototype, "applyStatus", null);
846
+ _ts_decorate3([
847
+ (0, import_nestjs_filter.FilterFor)("workflow"),
848
+ _ts_metadata3("design:type", Function),
849
+ _ts_metadata3("design:paramtypes", [
850
+ Object
851
+ ]),
852
+ _ts_metadata3("design:returntype", void 0)
853
+ ], RunFilter.prototype, "applyWorkflow", null);
854
+ _ts_decorate3([
855
+ (0, import_nestjs_filter.FilterFor)("namespace"),
856
+ _ts_metadata3("design:type", Function),
857
+ _ts_metadata3("design:paramtypes", [
858
+ Object
859
+ ]),
860
+ _ts_metadata3("design:returntype", void 0)
861
+ ], RunFilter.prototype, "applyNamespace", null);
862
+ _ts_decorate3([
863
+ (0, import_nestjs_filter.FilterFor)("tag"),
864
+ _ts_metadata3("design:type", Function),
865
+ _ts_metadata3("design:paramtypes", [
866
+ Object
867
+ ]),
868
+ _ts_metadata3("design:returntype", void 0)
869
+ ], RunFilter.prototype, "applyTag", null);
870
+ _ts_decorate3([
871
+ (0, import_nestjs_filter.FilterFor)("origin"),
872
+ _ts_metadata3("design:type", Function),
873
+ _ts_metadata3("design:paramtypes", []),
874
+ _ts_metadata3("design:returntype", void 0)
875
+ ], RunFilter.prototype, "applyOrigin", null);
876
+ _ts_decorate3([
877
+ (0, import_nestjs_filter.FilterFor)("unattributed"),
878
+ _ts_metadata3("design:type", Function),
879
+ _ts_metadata3("design:paramtypes", []),
880
+ _ts_metadata3("design:returntype", void 0)
881
+ ], RunFilter.prototype, "applyUnattributed", null);
882
+ _ts_decorate3([
883
+ (0, import_nestjs_filter.FilterFor)("attr"),
884
+ _ts_metadata3("design:type", Function),
885
+ _ts_metadata3("design:paramtypes", [
886
+ Object
887
+ ]),
888
+ _ts_metadata3("design:returntype", void 0)
889
+ ], RunFilter.prototype, "applyAttributes", null);
890
+ _ts_decorate3([
891
+ (0, import_nestjs_filter.FilterFor)("limit"),
892
+ _ts_metadata3("design:type", Function),
893
+ _ts_metadata3("design:paramtypes", [
894
+ Object
895
+ ]),
896
+ _ts_metadata3("design:returntype", void 0)
897
+ ], RunFilter.prototype, "applyLimit", null);
898
+ _ts_decorate3([
899
+ (0, import_nestjs_filter.FilterFor)("offset"),
900
+ _ts_metadata3("design:type", Function),
901
+ _ts_metadata3("design:paramtypes", [
902
+ Object
903
+ ]),
904
+ _ts_metadata3("design:returntype", void 0)
905
+ ], RunFilter.prototype, "applyOffset", null);
906
+ RunFilter = _ts_decorate3([
907
+ (0, import_common3.Injectable)(),
908
+ (0, import_nestjs_filter.Filterable)({
909
+ entity: DurableRun,
910
+ adapter: RUN_QUERY_ADAPTER,
911
+ autoFields: false
912
+ })
913
+ ], RunFilter);
914
+
915
+ // src/server/durable-api.controller.ts
916
+ function _ts_decorate4(decorators, target, key, desc) {
917
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
918
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
919
+ 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;
920
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
921
+ }
922
+ __name(_ts_decorate4, "_ts_decorate");
923
+ function _ts_metadata4(k, v) {
924
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
925
+ }
926
+ __name(_ts_metadata4, "_ts_metadata");
307
927
  function _ts_param2(paramIndex, decorator) {
308
928
  return function(target, key) {
309
929
  decorator(target, key, paramIndex);
310
930
  };
311
931
  }
312
932
  __name(_ts_param2, "_ts_param");
313
- function pageBounds(limit, offset) {
314
- const bound = /* @__PURE__ */ __name((raw) => {
315
- const n = Number(raw);
316
- return raw !== void 0 && raw !== "" && Number.isInteger(n) && n >= 0 ? n : void 0;
317
- }, "bound");
318
- const l = bound(limit);
319
- const o = bound(offset);
320
- return {
321
- ...l !== void 0 ? {
322
- limit: l
323
- } : {},
324
- ...o !== void 0 ? {
325
- offset: o
326
- } : {}
327
- };
328
- }
329
- __name(pageBounds, "pageBounds");
330
- function statusPredicate(status) {
331
- if (Array.isArray(status)) return status.length ? {
332
- statuses: status
333
- } : {};
334
- return status ? {
335
- status
336
- } : {};
337
- }
338
- __name(statusPredicate, "statusPredicate");
339
- function originPredicate(origin, unattributed) {
340
- if (unattributed === "true" || unattributed === "1") return {
341
- origin: null
342
- };
343
- return origin ? {
344
- origin
345
- } : {};
346
- }
347
- __name(originPredicate, "originPredicate");
348
933
  var DurableApiController = class {
349
934
  static {
350
935
  __name(this, "DurableApiController");
351
936
  }
352
937
  dashboard;
353
- constructor(dashboard) {
938
+ runner;
939
+ constructor(dashboard, runner) {
354
940
  this.dashboard = dashboard;
941
+ this.runner = runner;
355
942
  }
356
943
  /**
357
- * The run list, filtered by whatever the operator asked for. Every predicate is OPTIONAL and an
358
- * omitted one means "don't narrow on this axis" — in particular `namespace`, whose absence keeps
359
- * the historical, deliberate behaviour that read paths are NOT namespace-scoped (core,
360
- * `WorkflowRun.namespace`): the console shows every tenant's runs until an operator chooses one.
361
- * A blank param (`?namespace=`, from a cleared filter box) is the same as an absent one; passing
362
- * `''` through would be an exact match on a tenant nobody has, i.e. a silently empty console.
944
+ * The run list, filtered by whatever the operator asked for.
945
+ *
946
+ * The predicates are parsed, validated and translated by `@dudousxd/nestjs-filter` (see
947
+ * `RunFilter` for the two spellings it accepts, and `RunQueryAdapter` for how they become a
948
+ * `RunQuery`). Every predicate is OPTIONAL and an omitted one means "don't narrow on this axis" —
949
+ * in particular `namespace`, whose absence keeps the historical, deliberate behaviour that read
950
+ * paths are NOT namespace-scoped (core, `WorkflowRun.namespace`): the console shows every tenant's
951
+ * runs until an operator chooses one.
363
952
  */
364
- async runs(status, workflow, tag, attr, namespace, origin, unattributed, limit, offset) {
365
- const runs = await this.dashboard.listRuns({
366
- ...statusPredicate(status),
367
- workflow,
368
- tag,
369
- attributes: parseAttrFilters(attr),
370
- namespace: namespace || void 0,
371
- ...originPredicate(origin, unattributed),
372
- ...pageBounds(limit, offset)
373
- });
953
+ async runs(draft) {
954
+ const runs = await this.dashboard.listRuns(draft.query);
374
955
  return runs.map(toRunListRow);
375
956
  }
376
957
  /**
@@ -378,15 +959,28 @@ var DurableApiController = class {
378
959
  * `GET runs`. This is what lets that listing be PAGED at all: the page bounds what the console
379
960
  * renders, this bounds nothing and keeps its status and origin chips exact.
380
961
  *
381
- * `status`, `origin` and the page bounds are deliberately NOT accepted — they are the axes being
382
- * counted, so narrowing by them would report the answer back to itself.
962
+ * `status`, `origin` and the page bounds are accepted (the route takes the same filter) but
963
+ * deliberately DROPPED before counting — they are the axes being counted, so narrowing by them
964
+ * would report the answer back to itself.
965
+ */
966
+ facets(draft) {
967
+ return this.dashboard.runFacets(draft.facetQuery());
968
+ }
969
+ /**
970
+ * The distinct values one filter field takes across the runs matching every OTHER active
971
+ * predicate, with counts — what the console's tenant/tag/attribute pickers list.
972
+ *
973
+ * `?groupByCount[field]=tag&groupByCount[limit]=20`, with the filters in the structured
974
+ * `filter[where][...]` form (what `filterQuery()` builds). Scoping the values to the active
975
+ * filters is the point: picking a tenant leaves the tag picker offering only that tenant's tags,
976
+ * so a picker never offers a value whose result set is empty.
977
+ *
978
+ * `limit` matters rather than being a nicety — tag and attribute cardinality grows with the data
979
+ * (a `singleton:<key>` tag is minted per key), so the unbounded answer is a listing.
383
980
  */
384
- facets(workflow, tag, attr, namespace) {
385
- return this.dashboard.runFacets({
386
- workflow,
387
- tag,
388
- attributes: parseAttrFilters(attr),
389
- namespace: namespace || void 0
981
+ values(query) {
982
+ return this.runner.groupByCount(DurableRun, query, {
983
+ filterClass: RunFilter
390
984
  });
391
985
  }
392
986
  /** Prometheus-text metrics (runs/steps by outcome, per-workflow counts) for a scrape. */
@@ -403,7 +997,7 @@ var DurableApiController = class {
403
997
  }
404
998
  async run(id) {
405
999
  const detail = await this.dashboard.getRunDetail(id);
406
- if (!detail) throw new import_common2.NotFoundException(`run ${id} not found`);
1000
+ if (!detail) throw new import_common4.NotFoundException(`run ${id} not found`);
407
1001
  return detail;
408
1002
  }
409
1003
  /** Server-Sent Events stream of a run's live lifecycle events — the dashboard tails it instead
@@ -423,18 +1017,9 @@ var DurableApiController = class {
423
1017
  * The filter takes the SAME params as `GET runs` and is parsed identically, so "retry all" acts on
424
1018
  * exactly the set the operator was looking at rather than a wider one.
425
1019
  */
426
- bulk(action, status, tag, workflow, attr, compensate, namespace, origin, unattributed) {
427
- return this.dashboard.bulk(action === "cancel" ? "cancel" : "retry", {
428
- status,
429
- tag,
430
- workflow,
431
- attributes: parseAttrFilters(attr),
432
- namespace: namespace || void 0,
433
- // The unattributed bucket is a scope a console can actually SELECT, so a bulk action launched
434
- // under it must be narrowed to it. Dropping the param would widen a retry/cancel to every
435
- // origin — acting on runs the operator was not looking at.
436
- ...originPredicate(origin, unattributed)
437
- }, {
1020
+ bulk(action, draft, compensate) {
1021
+ const { limit, offset, ...filter } = draft.query;
1022
+ return this.dashboard.bulk(action === "cancel" ? "cancel" : "retry", filter, {
438
1023
  compensate: compensate === "true"
439
1024
  });
440
1025
  }
@@ -442,18 +1027,18 @@ var DurableApiController = class {
442
1027
  const result = await this.dashboard.cancel(id, {
443
1028
  compensate: compensate === "true"
444
1029
  });
445
- if (!result) throw new import_common2.NotFoundException(`run ${id} not found`);
1030
+ if (!result) throw new import_common4.NotFoundException(`run ${id} not found`);
446
1031
  return result;
447
1032
  }
448
1033
  async continue(id) {
449
1034
  const result = await this.dashboard.continue(id);
450
- if (!result) throw new import_common2.NotFoundException(`run ${id} is not paused at a breakpoint`);
1035
+ if (!result) throw new import_common4.NotFoundException(`run ${id} is not paused at a breakpoint`);
451
1036
  return result;
452
1037
  }
453
1038
  /** Re-dispatch a run's stuck `pending` remote steps — recovery for a lost step dispatch. */
454
1039
  async redispatch(id) {
455
1040
  const result = await this.dashboard.redispatch(id);
456
- if (!result) throw new import_common2.NotFoundException(`run ${id} not found`);
1041
+ if (!result) throw new import_common4.NotFoundException(`run ${id} not found`);
457
1042
  return result;
458
1043
  }
459
1044
  /**
@@ -464,7 +1049,7 @@ var DurableApiController = class {
464
1049
  */
465
1050
  async webhook(token, body) {
466
1051
  const result = await this.dashboard.deliverWebhook(token, body);
467
- if (!result) throw new import_common2.NotFoundException(`no run is waiting on webhook ${token}`);
1052
+ if (!result) throw new import_common4.NotFoundException(`no run is waiting on webhook ${token}`);
468
1053
  return result;
469
1054
  }
470
1055
  /** Live query: the latest value a run published for `key` via `ctx.setEvent` (no side effect). */
@@ -476,202 +1061,178 @@ var DurableApiController = class {
476
1061
  return this.dashboard.update(id, name, body);
477
1062
  }
478
1063
  };
479
- _ts_decorate2([
480
- (0, import_common2.Get)("runs"),
481
- _ts_param2(0, (0, import_common2.Query)("status")),
482
- _ts_param2(1, (0, import_common2.Query)("workflow")),
483
- _ts_param2(2, (0, import_common2.Query)("tag")),
484
- _ts_param2(3, (0, import_common2.Query)("attr")),
485
- _ts_param2(4, (0, import_common2.Query)("namespace")),
486
- _ts_param2(5, (0, import_common2.Query)("origin")),
487
- _ts_param2(6, (0, import_common2.Query)("unattributed")),
488
- _ts_param2(7, (0, import_common2.Query)("limit")),
489
- _ts_param2(8, (0, import_common2.Query)("offset")),
490
- _ts_metadata2("design:type", Function),
491
- _ts_metadata2("design:paramtypes", [
492
- Object,
493
- String,
494
- String,
495
- Object,
496
- String,
497
- String,
498
- String,
499
- String,
500
- String
1064
+ _ts_decorate4([
1065
+ (0, import_common4.Get)("runs"),
1066
+ _ts_param2(0, (0, import_nestjs_filter2.ApplyFilter)(RunFilter)),
1067
+ _ts_metadata4("design:type", Function),
1068
+ _ts_metadata4("design:paramtypes", [
1069
+ typeof RunQueryDraft === "undefined" ? Object : RunQueryDraft
501
1070
  ]),
502
- _ts_metadata2("design:returntype", Promise)
1071
+ _ts_metadata4("design:returntype", Promise)
503
1072
  ], DurableApiController.prototype, "runs", null);
504
- _ts_decorate2([
505
- (0, import_common2.Get)("runs/facets"),
506
- _ts_param2(0, (0, import_common2.Query)("workflow")),
507
- _ts_param2(1, (0, import_common2.Query)("tag")),
508
- _ts_param2(2, (0, import_common2.Query)("attr")),
509
- _ts_param2(3, (0, import_common2.Query)("namespace")),
510
- _ts_metadata2("design:type", Function),
511
- _ts_metadata2("design:paramtypes", [
512
- String,
513
- String,
514
- Object,
515
- String
1073
+ _ts_decorate4([
1074
+ (0, import_common4.Get)("runs/facets"),
1075
+ _ts_param2(0, (0, import_nestjs_filter2.ApplyFilter)(RunFilter)),
1076
+ _ts_metadata4("design:type", Function),
1077
+ _ts_metadata4("design:paramtypes", [
1078
+ typeof RunQueryDraft === "undefined" ? Object : RunQueryDraft
516
1079
  ]),
517
- _ts_metadata2("design:returntype", void 0)
1080
+ _ts_metadata4("design:returntype", void 0)
518
1081
  ], DurableApiController.prototype, "facets", null);
519
- _ts_decorate2([
520
- (0, import_common2.Get)("metrics"),
521
- (0, import_common2.Header)("Content-Type", "text/plain; version=0.0.4"),
522
- _ts_metadata2("design:type", Function),
523
- _ts_metadata2("design:paramtypes", []),
524
- _ts_metadata2("design:returntype", void 0)
1082
+ _ts_decorate4([
1083
+ (0, import_common4.Get)("runs/values"),
1084
+ _ts_param2(0, (0, import_common4.Query)()),
1085
+ _ts_metadata4("design:type", Function),
1086
+ _ts_metadata4("design:paramtypes", [
1087
+ typeof Record === "undefined" ? Object : Record
1088
+ ]),
1089
+ _ts_metadata4("design:returntype", void 0)
1090
+ ], DurableApiController.prototype, "values", null);
1091
+ _ts_decorate4([
1092
+ (0, import_common4.Get)("metrics"),
1093
+ (0, import_common4.Header)("Content-Type", "text/plain; version=0.0.4"),
1094
+ _ts_metadata4("design:type", Function),
1095
+ _ts_metadata4("design:paramtypes", []),
1096
+ _ts_metadata4("design:returntype", void 0)
525
1097
  ], DurableApiController.prototype, "metrics", null);
526
- _ts_decorate2([
527
- (0, import_common2.Get)("workers"),
528
- _ts_metadata2("design:type", Function),
529
- _ts_metadata2("design:paramtypes", []),
530
- _ts_metadata2("design:returntype", void 0)
1098
+ _ts_decorate4([
1099
+ (0, import_common4.Get)("workers"),
1100
+ _ts_metadata4("design:type", Function),
1101
+ _ts_metadata4("design:paramtypes", []),
1102
+ _ts_metadata4("design:returntype", void 0)
531
1103
  ], DurableApiController.prototype, "workers", null);
532
- _ts_decorate2([
533
- (0, import_common2.Get)("topology"),
534
- _ts_metadata2("design:type", Function),
535
- _ts_metadata2("design:paramtypes", []),
536
- _ts_metadata2("design:returntype", void 0)
1104
+ _ts_decorate4([
1105
+ (0, import_common4.Get)("topology"),
1106
+ _ts_metadata4("design:type", Function),
1107
+ _ts_metadata4("design:paramtypes", []),
1108
+ _ts_metadata4("design:returntype", void 0)
537
1109
  ], DurableApiController.prototype, "topology", null);
538
- _ts_decorate2([
539
- (0, import_common2.Get)("runs/:id"),
540
- _ts_param2(0, (0, import_common2.Param)("id")),
541
- _ts_metadata2("design:type", Function),
542
- _ts_metadata2("design:paramtypes", [
1110
+ _ts_decorate4([
1111
+ (0, import_common4.Get)("runs/:id"),
1112
+ _ts_param2(0, (0, import_common4.Param)("id")),
1113
+ _ts_metadata4("design:type", Function),
1114
+ _ts_metadata4("design:paramtypes", [
543
1115
  String
544
1116
  ]),
545
- _ts_metadata2("design:returntype", Promise)
1117
+ _ts_metadata4("design:returntype", Promise)
546
1118
  ], DurableApiController.prototype, "run", null);
547
- _ts_decorate2([
548
- (0, import_common2.Sse)("runs/:id/stream"),
549
- _ts_param2(0, (0, import_common2.Param)("id")),
550
- _ts_metadata2("design:type", Function),
551
- _ts_metadata2("design:paramtypes", [
1119
+ _ts_decorate4([
1120
+ (0, import_common4.Sse)("runs/:id/stream"),
1121
+ _ts_param2(0, (0, import_common4.Param)("id")),
1122
+ _ts_metadata4("design:type", Function),
1123
+ _ts_metadata4("design:paramtypes", [
552
1124
  String
553
1125
  ]),
554
- _ts_metadata2("design:returntype", void 0)
1126
+ _ts_metadata4("design:returntype", void 0)
555
1127
  ], DurableApiController.prototype, "stream", null);
556
- _ts_decorate2([
557
- (0, import_common2.Post)("runs/:id/retry"),
558
- _ts_param2(0, (0, import_common2.Param)("id")),
559
- _ts_metadata2("design:type", Function),
560
- _ts_metadata2("design:paramtypes", [
1128
+ _ts_decorate4([
1129
+ (0, import_common4.Post)("runs/:id/retry"),
1130
+ _ts_param2(0, (0, import_common4.Param)("id")),
1131
+ _ts_metadata4("design:type", Function),
1132
+ _ts_metadata4("design:paramtypes", [
561
1133
  String
562
1134
  ]),
563
- _ts_metadata2("design:returntype", void 0)
1135
+ _ts_metadata4("design:returntype", void 0)
564
1136
  ], DurableApiController.prototype, "retry", null);
565
- _ts_decorate2([
566
- (0, import_common2.Post)("runs/:id/retry-with-input"),
567
- _ts_param2(0, (0, import_common2.Param)("id")),
568
- _ts_param2(1, (0, import_common2.Body)()),
569
- _ts_metadata2("design:type", Function),
570
- _ts_metadata2("design:paramtypes", [
1137
+ _ts_decorate4([
1138
+ (0, import_common4.Post)("runs/:id/retry-with-input"),
1139
+ _ts_param2(0, (0, import_common4.Param)("id")),
1140
+ _ts_param2(1, (0, import_common4.Body)()),
1141
+ _ts_metadata4("design:type", Function),
1142
+ _ts_metadata4("design:paramtypes", [
571
1143
  String,
572
1144
  Object
573
1145
  ]),
574
- _ts_metadata2("design:returntype", void 0)
1146
+ _ts_metadata4("design:returntype", void 0)
575
1147
  ], DurableApiController.prototype, "retryWithInput", null);
576
- _ts_decorate2([
577
- (0, import_common2.Post)("bulk/:action"),
578
- _ts_param2(0, (0, import_common2.Param)("action")),
579
- _ts_param2(1, (0, import_common2.Query)("status")),
580
- _ts_param2(2, (0, import_common2.Query)("tag")),
581
- _ts_param2(3, (0, import_common2.Query)("workflow")),
582
- _ts_param2(4, (0, import_common2.Query)("attr")),
583
- _ts_param2(5, (0, import_common2.Query)("compensate")),
584
- _ts_param2(6, (0, import_common2.Query)("namespace")),
585
- _ts_param2(7, (0, import_common2.Query)("origin")),
586
- _ts_param2(8, (0, import_common2.Query)("unattributed")),
587
- _ts_metadata2("design:type", Function),
588
- _ts_metadata2("design:paramtypes", [
589
- String,
590
- typeof RunStatus === "undefined" ? Object : RunStatus,
591
- String,
592
- String,
593
- Object,
594
- String,
595
- String,
1148
+ _ts_decorate4([
1149
+ (0, import_common4.Post)("bulk/:action"),
1150
+ _ts_param2(0, (0, import_common4.Param)("action")),
1151
+ _ts_param2(1, (0, import_nestjs_filter2.ApplyFilter)(RunFilter)),
1152
+ _ts_param2(2, (0, import_common4.Query)("compensate")),
1153
+ _ts_metadata4("design:type", Function),
1154
+ _ts_metadata4("design:paramtypes", [
596
1155
  String,
1156
+ typeof RunQueryDraft === "undefined" ? Object : RunQueryDraft,
597
1157
  String
598
1158
  ]),
599
- _ts_metadata2("design:returntype", void 0)
1159
+ _ts_metadata4("design:returntype", void 0)
600
1160
  ], DurableApiController.prototype, "bulk", null);
601
- _ts_decorate2([
602
- (0, import_common2.Post)("runs/:id/cancel"),
603
- _ts_param2(0, (0, import_common2.Param)("id")),
604
- _ts_param2(1, (0, import_common2.Query)("compensate")),
605
- _ts_metadata2("design:type", Function),
606
- _ts_metadata2("design:paramtypes", [
1161
+ _ts_decorate4([
1162
+ (0, import_common4.Post)("runs/:id/cancel"),
1163
+ _ts_param2(0, (0, import_common4.Param)("id")),
1164
+ _ts_param2(1, (0, import_common4.Query)("compensate")),
1165
+ _ts_metadata4("design:type", Function),
1166
+ _ts_metadata4("design:paramtypes", [
607
1167
  String,
608
1168
  String
609
1169
  ]),
610
- _ts_metadata2("design:returntype", Promise)
1170
+ _ts_metadata4("design:returntype", Promise)
611
1171
  ], DurableApiController.prototype, "cancel", null);
612
- _ts_decorate2([
613
- (0, import_common2.Post)("runs/:id/continue"),
614
- _ts_param2(0, (0, import_common2.Param)("id")),
615
- _ts_metadata2("design:type", Function),
616
- _ts_metadata2("design:paramtypes", [
1172
+ _ts_decorate4([
1173
+ (0, import_common4.Post)("runs/:id/continue"),
1174
+ _ts_param2(0, (0, import_common4.Param)("id")),
1175
+ _ts_metadata4("design:type", Function),
1176
+ _ts_metadata4("design:paramtypes", [
617
1177
  String
618
1178
  ]),
619
- _ts_metadata2("design:returntype", Promise)
1179
+ _ts_metadata4("design:returntype", Promise)
620
1180
  ], DurableApiController.prototype, "continue", null);
621
- _ts_decorate2([
622
- (0, import_common2.Post)("runs/:id/redispatch"),
623
- _ts_param2(0, (0, import_common2.Param)("id")),
624
- _ts_metadata2("design:type", Function),
625
- _ts_metadata2("design:paramtypes", [
1181
+ _ts_decorate4([
1182
+ (0, import_common4.Post)("runs/:id/redispatch"),
1183
+ _ts_param2(0, (0, import_common4.Param)("id")),
1184
+ _ts_metadata4("design:type", Function),
1185
+ _ts_metadata4("design:paramtypes", [
626
1186
  String
627
1187
  ]),
628
- _ts_metadata2("design:returntype", Promise)
1188
+ _ts_metadata4("design:returntype", Promise)
629
1189
  ], DurableApiController.prototype, "redispatch", null);
630
- _ts_decorate2([
631
- (0, import_common2.Post)("webhooks/:token"),
632
- _ts_param2(0, (0, import_common2.Param)("token")),
633
- _ts_param2(1, (0, import_common2.Body)()),
634
- _ts_metadata2("design:type", Function),
635
- _ts_metadata2("design:paramtypes", [
1190
+ _ts_decorate4([
1191
+ (0, import_common4.Post)("webhooks/:token"),
1192
+ _ts_param2(0, (0, import_common4.Param)("token")),
1193
+ _ts_param2(1, (0, import_common4.Body)()),
1194
+ _ts_metadata4("design:type", Function),
1195
+ _ts_metadata4("design:paramtypes", [
636
1196
  String,
637
1197
  Object
638
1198
  ]),
639
- _ts_metadata2("design:returntype", Promise)
1199
+ _ts_metadata4("design:returntype", Promise)
640
1200
  ], DurableApiController.prototype, "webhook", null);
641
- _ts_decorate2([
642
- (0, import_common2.Get)("runs/:id/events/:key"),
643
- _ts_param2(0, (0, import_common2.Param)("id")),
644
- _ts_param2(1, (0, import_common2.Param)("key")),
645
- _ts_metadata2("design:type", Function),
646
- _ts_metadata2("design:paramtypes", [
1201
+ _ts_decorate4([
1202
+ (0, import_common4.Get)("runs/:id/events/:key"),
1203
+ _ts_param2(0, (0, import_common4.Param)("id")),
1204
+ _ts_param2(1, (0, import_common4.Param)("key")),
1205
+ _ts_metadata4("design:type", Function),
1206
+ _ts_metadata4("design:paramtypes", [
647
1207
  String,
648
1208
  String
649
1209
  ]),
650
- _ts_metadata2("design:returntype", void 0)
1210
+ _ts_metadata4("design:returntype", void 0)
651
1211
  ], DurableApiController.prototype, "event", null);
652
- _ts_decorate2([
653
- (0, import_common2.Post)("runs/:id/updates/:name"),
654
- _ts_param2(0, (0, import_common2.Param)("id")),
655
- _ts_param2(1, (0, import_common2.Param)("name")),
656
- _ts_param2(2, (0, import_common2.Body)()),
657
- _ts_metadata2("design:type", Function),
658
- _ts_metadata2("design:paramtypes", [
1212
+ _ts_decorate4([
1213
+ (0, import_common4.Post)("runs/:id/updates/:name"),
1214
+ _ts_param2(0, (0, import_common4.Param)("id")),
1215
+ _ts_param2(1, (0, import_common4.Param)("name")),
1216
+ _ts_param2(2, (0, import_common4.Body)()),
1217
+ _ts_metadata4("design:type", Function),
1218
+ _ts_metadata4("design:paramtypes", [
659
1219
  String,
660
1220
  String,
661
1221
  Object
662
1222
  ]),
663
- _ts_metadata2("design:returntype", void 0)
1223
+ _ts_metadata4("design:returntype", void 0)
664
1224
  ], DurableApiController.prototype, "update", null);
665
- DurableApiController = _ts_decorate2([
666
- (0, import_common2.Controller)(),
667
- _ts_metadata2("design:type", Function),
668
- _ts_metadata2("design:paramtypes", [
669
- typeof DashboardService === "undefined" ? Object : DashboardService
1225
+ DurableApiController = _ts_decorate4([
1226
+ (0, import_common4.Controller)(),
1227
+ _ts_metadata4("design:type", Function),
1228
+ _ts_metadata4("design:paramtypes", [
1229
+ typeof DashboardService === "undefined" ? Object : DashboardService,
1230
+ typeof import_nestjs_filter2.FilterRunner === "undefined" ? Object : import_nestjs_filter2.FilterRunner
670
1231
  ])
671
1232
  ], DurableApiController);
672
1233
 
673
1234
  // src/server/durable-auth.controller.ts
674
- var import_common6 = require("@nestjs/common");
1235
+ var import_common8 = require("@nestjs/common");
675
1236
 
676
1237
  // src/server/auth/dashboard-auth-config.ts
677
1238
  var DASHBOARD_AUTH = Symbol("DASHBOARD_AUTH");
@@ -1223,18 +1784,18 @@ __name(maybeRenewSession, "maybeRenewSession");
1223
1784
  var import_node_fs = require("fs");
1224
1785
  var import_node_path = require("path");
1225
1786
  var import_node_url = require("url");
1226
- var import_common5 = require("@nestjs/common");
1787
+ var import_common7 = require("@nestjs/common");
1227
1788
 
1228
1789
  // src/server/auth/login-redirect.exception.ts
1229
- var import_common3 = require("@nestjs/common");
1230
- function _ts_decorate3(decorators, target, key, desc) {
1790
+ var import_common5 = require("@nestjs/common");
1791
+ function _ts_decorate5(decorators, target, key, desc) {
1231
1792
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1232
1793
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1233
1794
  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;
1234
1795
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1235
1796
  }
1236
- __name(_ts_decorate3, "_ts_decorate");
1237
- var DashboardLoginRedirectException = class extends import_common3.HttpException {
1797
+ __name(_ts_decorate5, "_ts_decorate");
1798
+ var DashboardLoginRedirectException = class extends import_common5.HttpException {
1238
1799
  static {
1239
1800
  __name(this, "DashboardLoginRedirectException");
1240
1801
  }
@@ -1242,7 +1803,7 @@ var DashboardLoginRedirectException = class extends import_common3.HttpException
1242
1803
  constructor(location) {
1243
1804
  super({
1244
1805
  location
1245
- }, import_common3.HttpStatus.FOUND), this.location = location;
1806
+ }, import_common5.HttpStatus.FOUND), this.location = location;
1246
1807
  }
1247
1808
  };
1248
1809
  var DashboardLoginRedirectFilter = class {
@@ -1254,30 +1815,30 @@ var DashboardLoginRedirectFilter = class {
1254
1815
  redirectRaw(response, exception.location);
1255
1816
  }
1256
1817
  };
1257
- DashboardLoginRedirectFilter = _ts_decorate3([
1258
- (0, import_common3.Catch)(DashboardLoginRedirectException)
1818
+ DashboardLoginRedirectFilter = _ts_decorate5([
1819
+ (0, import_common5.Catch)(DashboardLoginRedirectException)
1259
1820
  ], DashboardLoginRedirectFilter);
1260
1821
 
1261
1822
  // src/server/auth/session-required.exception.ts
1262
- var import_common4 = require("@nestjs/common");
1263
- function _ts_decorate4(decorators, target, key, desc) {
1823
+ var import_common6 = require("@nestjs/common");
1824
+ function _ts_decorate6(decorators, target, key, desc) {
1264
1825
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1265
1826
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1266
1827
  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;
1267
1828
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1268
1829
  }
1269
- __name(_ts_decorate4, "_ts_decorate");
1270
- function _ts_metadata3(k, v) {
1830
+ __name(_ts_decorate6, "_ts_decorate");
1831
+ function _ts_metadata5(k, v) {
1271
1832
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1272
1833
  }
1273
- __name(_ts_metadata3, "_ts_metadata");
1834
+ __name(_ts_metadata5, "_ts_metadata");
1274
1835
  function _ts_param3(paramIndex, decorator) {
1275
1836
  return function(target, key) {
1276
1837
  decorator(target, key, paramIndex);
1277
1838
  };
1278
1839
  }
1279
1840
  __name(_ts_param3, "_ts_param");
1280
- var DashboardSessionRequiredException = class extends import_common4.HttpException {
1841
+ var DashboardSessionRequiredException = class extends import_common6.HttpException {
1281
1842
  static {
1282
1843
  __name(this, "DashboardSessionRequiredException");
1283
1844
  }
@@ -1285,7 +1846,7 @@ var DashboardSessionRequiredException = class extends import_common4.HttpExcepti
1285
1846
  constructor(basePath) {
1286
1847
  super({
1287
1848
  basePath
1288
- }, import_common4.HttpStatus.UNAUTHORIZED), this.basePath = basePath;
1849
+ }, import_common6.HttpStatus.UNAUTHORIZED), this.basePath = basePath;
1289
1850
  }
1290
1851
  };
1291
1852
  var DashboardSessionRequiredFilter = class _DashboardSessionRequiredFilter {
@@ -1293,7 +1854,7 @@ var DashboardSessionRequiredFilter = class _DashboardSessionRequiredFilter {
1293
1854
  __name(this, "DashboardSessionRequiredFilter");
1294
1855
  }
1295
1856
  auth;
1296
- logger = new import_common4.Logger(_DashboardSessionRequiredFilter.name);
1857
+ logger = new import_common6.Logger(_DashboardSessionRequiredFilter.name);
1297
1858
  warned = false;
1298
1859
  constructor(auth = null) {
1299
1860
  this.auth = auth;
@@ -1316,7 +1877,7 @@ var DashboardSessionRequiredFilter = class _DashboardSessionRequiredFilter {
1316
1877
  if (responseAlreadyWritten(response)) return;
1317
1878
  }
1318
1879
  }
1319
- writeHtmlRaw(response, renderSessionRequiredPage(exception.basePath), import_common4.HttpStatus.UNAUTHORIZED);
1880
+ writeHtmlRaw(response, renderSessionRequiredPage(exception.basePath), import_common6.HttpStatus.UNAUTHORIZED);
1320
1881
  }
1321
1882
  /** Once per process, not once per request: a broken hook fires on every denied navigation. */
1322
1883
  warnOnce(message) {
@@ -1325,28 +1886,28 @@ var DashboardSessionRequiredFilter = class _DashboardSessionRequiredFilter {
1325
1886
  this.logger.warn(message);
1326
1887
  }
1327
1888
  };
1328
- DashboardSessionRequiredFilter = _ts_decorate4([
1329
- (0, import_common4.Catch)(DashboardSessionRequiredException),
1330
- _ts_param3(0, (0, import_common4.Optional)()),
1331
- _ts_param3(0, (0, import_common4.Inject)(DASHBOARD_AUTH)),
1332
- _ts_metadata3("design:type", Function),
1333
- _ts_metadata3("design:paramtypes", [
1889
+ DashboardSessionRequiredFilter = _ts_decorate6([
1890
+ (0, import_common6.Catch)(DashboardSessionRequiredException),
1891
+ _ts_param3(0, (0, import_common6.Optional)()),
1892
+ _ts_param3(0, (0, import_common6.Inject)(DASHBOARD_AUTH)),
1893
+ _ts_metadata5("design:type", Function),
1894
+ _ts_metadata5("design:paramtypes", [
1334
1895
  Object
1335
1896
  ])
1336
1897
  ], DashboardSessionRequiredFilter);
1337
1898
 
1338
1899
  // src/server/durable-ui.controller.ts
1339
- function _ts_decorate5(decorators, target, key, desc) {
1900
+ function _ts_decorate7(decorators, target, key, desc) {
1340
1901
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1341
1902
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1342
1903
  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;
1343
1904
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1344
1905
  }
1345
- __name(_ts_decorate5, "_ts_decorate");
1346
- function _ts_metadata4(k, v) {
1906
+ __name(_ts_decorate7, "_ts_decorate");
1907
+ function _ts_metadata6(k, v) {
1347
1908
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1348
1909
  }
1349
- __name(_ts_metadata4, "_ts_metadata");
1910
+ __name(_ts_metadata6, "_ts_metadata");
1350
1911
  function _ts_param4(paramIndex, decorator) {
1351
1912
  return function(target, key) {
1352
1913
  decorator(target, key, paramIndex);
@@ -1385,7 +1946,7 @@ var DurableUiController = class {
1385
1946
  index() {
1386
1947
  const indexPath = (0, import_node_path.join)(this.dir, "index.html");
1387
1948
  if (!(0, import_node_fs.existsSync)(indexPath)) {
1388
- throw new import_common5.NotFoundException("Dashboard is not built. Run the package build.");
1949
+ throw new import_common7.NotFoundException("Dashboard is not built. Run the package build.");
1389
1950
  }
1390
1951
  const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
1391
1952
  const inject = `<script>window.__DURABLE_BASE__='${this.basePath}';window.__DURABLE_API__='${this.apiBasePath}';</script>`;
@@ -1393,60 +1954,60 @@ var DurableUiController = class {
1393
1954
  }
1394
1955
  asset(file) {
1395
1956
  const safe = (0, import_node_path.basename)(file);
1396
- if (safe !== file) throw new import_common5.NotFoundException();
1957
+ if (safe !== file) throw new import_common7.NotFoundException();
1397
1958
  const root = (0, import_node_path.resolve)(this.dir, "assets");
1398
1959
  const assetPath = (0, import_node_path.resolve)(root, safe);
1399
1960
  if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
1400
- throw new import_common5.NotFoundException();
1961
+ throw new import_common7.NotFoundException();
1401
1962
  }
1402
1963
  const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
1403
- return new import_common5.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
1964
+ return new import_common7.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
1404
1965
  type
1405
1966
  });
1406
1967
  }
1407
1968
  };
1408
- _ts_decorate5([
1409
- (0, import_common5.Get)(),
1410
- (0, import_common5.Header)("Content-Type", "text/html; charset=utf-8"),
1411
- (0, import_common5.Header)("Cache-Control", "no-store, must-revalidate"),
1412
- _ts_metadata4("design:type", Function),
1413
- _ts_metadata4("design:paramtypes", []),
1414
- _ts_metadata4("design:returntype", String)
1969
+ _ts_decorate7([
1970
+ (0, import_common7.Get)(),
1971
+ (0, import_common7.Header)("Content-Type", "text/html; charset=utf-8"),
1972
+ (0, import_common7.Header)("Cache-Control", "no-store, must-revalidate"),
1973
+ _ts_metadata6("design:type", Function),
1974
+ _ts_metadata6("design:paramtypes", []),
1975
+ _ts_metadata6("design:returntype", String)
1415
1976
  ], DurableUiController.prototype, "index", null);
1416
- _ts_decorate5([
1417
- (0, import_common5.Get)("assets/:file"),
1418
- (0, import_common5.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1419
- _ts_param4(0, (0, import_common5.Param)("file")),
1420
- _ts_metadata4("design:type", Function),
1421
- _ts_metadata4("design:paramtypes", [
1977
+ _ts_decorate7([
1978
+ (0, import_common7.Get)("assets/:file"),
1979
+ (0, import_common7.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1980
+ _ts_param4(0, (0, import_common7.Param)("file")),
1981
+ _ts_metadata6("design:type", Function),
1982
+ _ts_metadata6("design:paramtypes", [
1422
1983
  String
1423
1984
  ]),
1424
- _ts_metadata4("design:returntype", typeof import_common5.StreamableFile === "undefined" ? Object : import_common5.StreamableFile)
1985
+ _ts_metadata6("design:returntype", typeof import_common7.StreamableFile === "undefined" ? Object : import_common7.StreamableFile)
1425
1986
  ], DurableUiController.prototype, "asset", null);
1426
- DurableUiController = _ts_decorate5([
1427
- (0, import_common5.UseFilters)(DashboardLoginRedirectFilter, DashboardSessionRequiredFilter),
1428
- (0, import_common5.Controller)(),
1429
- _ts_param4(0, (0, import_common5.Inject)(DASHBOARD_BASE_PATH)),
1430
- _ts_param4(1, (0, import_common5.Inject)(DASHBOARD_API_PATH)),
1431
- _ts_metadata4("design:type", Function),
1432
- _ts_metadata4("design:paramtypes", [
1987
+ DurableUiController = _ts_decorate7([
1988
+ (0, import_common7.UseFilters)(DashboardLoginRedirectFilter, DashboardSessionRequiredFilter),
1989
+ (0, import_common7.Controller)(),
1990
+ _ts_param4(0, (0, import_common7.Inject)(DASHBOARD_BASE_PATH)),
1991
+ _ts_param4(1, (0, import_common7.Inject)(DASHBOARD_API_PATH)),
1992
+ _ts_metadata6("design:type", Function),
1993
+ _ts_metadata6("design:paramtypes", [
1433
1994
  String,
1434
1995
  String
1435
1996
  ])
1436
1997
  ], DurableUiController);
1437
1998
 
1438
1999
  // src/server/durable-auth.controller.ts
1439
- function _ts_decorate6(decorators, target, key, desc) {
2000
+ function _ts_decorate8(decorators, target, key, desc) {
1440
2001
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1441
2002
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1442
2003
  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;
1443
2004
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1444
2005
  }
1445
- __name(_ts_decorate6, "_ts_decorate");
1446
- function _ts_metadata5(k, v) {
2006
+ __name(_ts_decorate8, "_ts_decorate");
2007
+ function _ts_metadata7(k, v) {
1447
2008
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1448
2009
  }
1449
- __name(_ts_metadata5, "_ts_metadata");
2010
+ __name(_ts_metadata7, "_ts_metadata");
1450
2011
  function _ts_param5(paramIndex, decorator) {
1451
2012
  return function(target, key) {
1452
2013
  decorator(target, key, paramIndex);
@@ -1463,7 +2024,7 @@ var DurableAuthController = class _DurableAuthController {
1463
2024
  }
1464
2025
  auth;
1465
2026
  basePath;
1466
- logger = new import_common6.Logger(_DurableAuthController.name);
2027
+ logger = new import_common8.Logger(_DurableAuthController.name);
1467
2028
  /** Warn once per hook kind so a throwing hook doesn't spam logs on every failed attempt. */
1468
2029
  warnedHooks = /* @__PURE__ */ new Set();
1469
2030
  constructor(auth, basePath) {
@@ -1475,7 +2036,7 @@ var DurableAuthController = class _DurableAuthController {
1475
2036
  // the developer-controlled `basePath`.
1476
2037
  loginPage() {
1477
2038
  const auth = this.requireAuth();
1478
- if (!auth.modes.includes("login")) throw new import_common6.NotFoundException();
2039
+ if (!auth.modes.includes("login")) throw new import_common8.NotFoundException();
1479
2040
  return renderLoginPage(this.basePath);
1480
2041
  }
1481
2042
  // Called by the login page's own fetch (JSON, not a classic form POST — see `login-page.ts` for
@@ -1484,13 +2045,13 @@ var DurableAuthController = class _DurableAuthController {
1484
2045
  // (unknown user, wrong password, throwing hook) — no user-enumeration.
1485
2046
  async login(body, request, response) {
1486
2047
  const auth = this.requireAuth();
1487
- if (!auth.modes.includes("login")) throw new import_common6.NotFoundException();
2048
+ if (!auth.modes.includes("login")) throw new import_common8.NotFoundException();
1488
2049
  if (!isString(body?.username) || !isString(body?.password)) {
1489
- throw new import_common6.BadRequestException("Body must include string `username` and `password`.");
2050
+ throw new import_common8.BadRequestException("Body must include string `username` and `password`.");
1490
2051
  }
1491
2052
  const { username, password } = body;
1492
2053
  const user = await this.runHook("login", () => auth.login?.(username, password) ?? null);
1493
- if (!user) throw new import_common6.UnauthorizedException({
2054
+ if (!user) throw new import_common8.UnauthorizedException({
1494
2055
  message: "Invalid username or password."
1495
2056
  });
1496
2057
  issueSessionCookie(user, {
@@ -1507,9 +2068,9 @@ var DurableAuthController = class _DurableAuthController {
1507
2068
  // guard decides, and no credential ever reaches this library.
1508
2069
  async session(request, response) {
1509
2070
  const auth = this.requireAuth();
1510
- if (!auth.modes.includes("session")) throw new import_common6.NotFoundException();
2071
+ if (!auth.modes.includes("session")) throw new import_common8.NotFoundException();
1511
2072
  const user = await this.runHook("session", () => auth.session?.(request) ?? null);
1512
- if (!user) throw new import_common6.UnauthorizedException();
2073
+ if (!user) throw new import_common8.UnauthorizedException();
1513
2074
  issueSessionCookie(user, {
1514
2075
  auth,
1515
2076
  request,
@@ -1528,7 +2089,7 @@ var DurableAuthController = class _DurableAuthController {
1528
2089
  redirectRaw(response, this.auth?.modes.includes("login") ? `${this.basePath}/login` : this.basePath);
1529
2090
  }
1530
2091
  requireAuth() {
1531
- if (!this.auth) throw new import_common6.NotFoundException();
2092
+ if (!this.auth) throw new import_common8.NotFoundException();
1532
2093
  return this.auth;
1533
2094
  }
1534
2095
  /**
@@ -1548,62 +2109,62 @@ var DurableAuthController = class _DurableAuthController {
1548
2109
  }
1549
2110
  }
1550
2111
  };
1551
- _ts_decorate6([
1552
- (0, import_common6.Get)("login"),
1553
- (0, import_common6.Header)("Content-Type", "text/html; charset=utf-8"),
1554
- (0, import_common6.Header)("Cache-Control", "no-store, must-revalidate"),
1555
- _ts_metadata5("design:type", Function),
1556
- _ts_metadata5("design:paramtypes", []),
1557
- _ts_metadata5("design:returntype", String)
2112
+ _ts_decorate8([
2113
+ (0, import_common8.Get)("login"),
2114
+ (0, import_common8.Header)("Content-Type", "text/html; charset=utf-8"),
2115
+ (0, import_common8.Header)("Cache-Control", "no-store, must-revalidate"),
2116
+ _ts_metadata7("design:type", Function),
2117
+ _ts_metadata7("design:paramtypes", []),
2118
+ _ts_metadata7("design:returntype", String)
1558
2119
  ], DurableAuthController.prototype, "loginPage", null);
1559
- _ts_decorate6([
1560
- (0, import_common6.Post)("login"),
1561
- (0, import_common6.HttpCode)(200),
1562
- _ts_param5(0, (0, import_common6.Body)()),
1563
- _ts_param5(1, (0, import_common6.Req)()),
1564
- _ts_param5(2, (0, import_common6.Res)({
2120
+ _ts_decorate8([
2121
+ (0, import_common8.Post)("login"),
2122
+ (0, import_common8.HttpCode)(200),
2123
+ _ts_param5(0, (0, import_common8.Body)()),
2124
+ _ts_param5(1, (0, import_common8.Req)()),
2125
+ _ts_param5(2, (0, import_common8.Res)({
1565
2126
  passthrough: true
1566
2127
  })),
1567
- _ts_metadata5("design:type", Function),
1568
- _ts_metadata5("design:paramtypes", [
2128
+ _ts_metadata7("design:type", Function),
2129
+ _ts_metadata7("design:paramtypes", [
1569
2130
  typeof LoginBody === "undefined" ? Object : LoginBody,
1570
2131
  Object,
1571
2132
  Object
1572
2133
  ]),
1573
- _ts_metadata5("design:returntype", Promise)
2134
+ _ts_metadata7("design:returntype", Promise)
1574
2135
  ], DurableAuthController.prototype, "login", null);
1575
- _ts_decorate6([
1576
- (0, import_common6.Post)("session"),
1577
- (0, import_common6.HttpCode)(204),
1578
- _ts_param5(0, (0, import_common6.Req)()),
1579
- _ts_param5(1, (0, import_common6.Res)({
2136
+ _ts_decorate8([
2137
+ (0, import_common8.Post)("session"),
2138
+ (0, import_common8.HttpCode)(204),
2139
+ _ts_param5(0, (0, import_common8.Req)()),
2140
+ _ts_param5(1, (0, import_common8.Res)({
1580
2141
  passthrough: true
1581
2142
  })),
1582
- _ts_metadata5("design:type", Function),
1583
- _ts_metadata5("design:paramtypes", [
2143
+ _ts_metadata7("design:type", Function),
2144
+ _ts_metadata7("design:paramtypes", [
1584
2145
  Object,
1585
2146
  Object
1586
2147
  ]),
1587
- _ts_metadata5("design:returntype", Promise)
2148
+ _ts_metadata7("design:returntype", Promise)
1588
2149
  ], DurableAuthController.prototype, "session", null);
1589
- _ts_decorate6([
1590
- (0, import_common6.Get)("logout"),
1591
- _ts_param5(0, (0, import_common6.Req)()),
1592
- _ts_param5(1, (0, import_common6.Res)()),
1593
- _ts_metadata5("design:type", Function),
1594
- _ts_metadata5("design:paramtypes", [
2150
+ _ts_decorate8([
2151
+ (0, import_common8.Get)("logout"),
2152
+ _ts_param5(0, (0, import_common8.Req)()),
2153
+ _ts_param5(1, (0, import_common8.Res)()),
2154
+ _ts_metadata7("design:type", Function),
2155
+ _ts_metadata7("design:paramtypes", [
1595
2156
  Object,
1596
2157
  Object
1597
2158
  ]),
1598
- _ts_metadata5("design:returntype", void 0)
2159
+ _ts_metadata7("design:returntype", void 0)
1599
2160
  ], DurableAuthController.prototype, "logout", null);
1600
- DurableAuthController = _ts_decorate6([
1601
- (0, import_common6.Controller)(),
1602
- _ts_param5(0, (0, import_common6.Optional)()),
1603
- _ts_param5(0, (0, import_common6.Inject)(DASHBOARD_AUTH)),
1604
- _ts_param5(1, (0, import_common6.Inject)(DASHBOARD_BASE_PATH)),
1605
- _ts_metadata5("design:type", Function),
1606
- _ts_metadata5("design:paramtypes", [
2161
+ DurableAuthController = _ts_decorate8([
2162
+ (0, import_common8.Controller)(),
2163
+ _ts_param5(0, (0, import_common8.Optional)()),
2164
+ _ts_param5(0, (0, import_common8.Inject)(DASHBOARD_AUTH)),
2165
+ _ts_param5(1, (0, import_common8.Inject)(DASHBOARD_BASE_PATH)),
2166
+ _ts_metadata7("design:type", Function),
2167
+ _ts_metadata7("design:paramtypes", [
1607
2168
  Object,
1608
2169
  String
1609
2170
  ])
@@ -1611,22 +2172,23 @@ DurableAuthController = _ts_decorate6([
1611
2172
 
1612
2173
  // src/server/durable-dashboard.module.ts
1613
2174
  var import_reflect_metadata = require("reflect-metadata");
1614
- var import_common8 = require("@nestjs/common");
2175
+ var import_nestjs_filter3 = require("@dudousxd/nestjs-filter");
2176
+ var import_common10 = require("@nestjs/common");
1615
2177
  var import_core = require("@nestjs/core");
1616
2178
 
1617
2179
  // src/server/durable-session.guard.ts
1618
- var import_common7 = require("@nestjs/common");
1619
- function _ts_decorate7(decorators, target, key, desc) {
2180
+ var import_common9 = require("@nestjs/common");
2181
+ function _ts_decorate9(decorators, target, key, desc) {
1620
2182
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1621
2183
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1622
2184
  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;
1623
2185
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1624
2186
  }
1625
- __name(_ts_decorate7, "_ts_decorate");
1626
- function _ts_metadata6(k, v) {
2187
+ __name(_ts_decorate9, "_ts_decorate");
2188
+ function _ts_metadata8(k, v) {
1627
2189
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1628
2190
  }
1629
- __name(_ts_metadata6, "_ts_metadata");
2191
+ __name(_ts_metadata8, "_ts_metadata");
1630
2192
  function _ts_param6(paramIndex, decorator) {
1631
2193
  return function(target, key) {
1632
2194
  decorator(target, key, paramIndex);
@@ -1673,12 +2235,12 @@ var DurableUiSessionGuard = class {
1673
2235
  throw new DashboardLoginRedirectException(`${this.basePath}/login?returnTo=${returnTo}`);
1674
2236
  }
1675
2237
  };
1676
- DurableUiSessionGuard = _ts_decorate7([
1677
- (0, import_common7.Injectable)(),
1678
- _ts_param6(0, (0, import_common7.Inject)(DASHBOARD_AUTH)),
1679
- _ts_param6(1, (0, import_common7.Inject)(DASHBOARD_BASE_PATH)),
1680
- _ts_metadata6("design:type", Function),
1681
- _ts_metadata6("design:paramtypes", [
2238
+ DurableUiSessionGuard = _ts_decorate9([
2239
+ (0, import_common9.Injectable)(),
2240
+ _ts_param6(0, (0, import_common9.Inject)(DASHBOARD_AUTH)),
2241
+ _ts_param6(1, (0, import_common9.Inject)(DASHBOARD_BASE_PATH)),
2242
+ _ts_metadata8("design:type", Function),
2243
+ _ts_metadata8("design:paramtypes", [
1682
2244
  Object,
1683
2245
  String
1684
2246
  ])
@@ -1710,30 +2272,30 @@ var DurableApiSessionGuard = class {
1710
2272
  * 401; `DurableUiSessionGuard`'s redirect/session-required exceptions above don't reach it.
1711
2273
  */
1712
2274
  unauthorized(auth) {
1713
- return new import_common7.UnauthorizedException({
2275
+ return new import_common9.UnauthorizedException({
1714
2276
  auth: {
1715
2277
  modes: auth.modes
1716
2278
  }
1717
2279
  });
1718
2280
  }
1719
2281
  };
1720
- DurableApiSessionGuard = _ts_decorate7([
1721
- (0, import_common7.Injectable)(),
1722
- _ts_param6(0, (0, import_common7.Inject)(DASHBOARD_AUTH)),
1723
- _ts_metadata6("design:type", Function),
1724
- _ts_metadata6("design:paramtypes", [
2282
+ DurableApiSessionGuard = _ts_decorate9([
2283
+ (0, import_common9.Injectable)(),
2284
+ _ts_param6(0, (0, import_common9.Inject)(DASHBOARD_AUTH)),
2285
+ _ts_metadata8("design:type", Function),
2286
+ _ts_metadata8("design:paramtypes", [
1725
2287
  Object
1726
2288
  ])
1727
2289
  ], DurableApiSessionGuard);
1728
2290
 
1729
2291
  // src/server/durable-dashboard.module.ts
1730
- function _ts_decorate8(decorators, target, key, desc) {
2292
+ function _ts_decorate10(decorators, target, key, desc) {
1731
2293
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1732
2294
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1733
2295
  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;
1734
2296
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1735
2297
  }
1736
- __name(_ts_decorate8, "_ts_decorate");
2298
+ __name(_ts_decorate10, "_ts_decorate");
1737
2299
  var GUARDS_METADATA = "__guards__";
1738
2300
  function normalize(path) {
1739
2301
  return `/${path.replace(/^\/+|\/+$/g, "")}`;
@@ -1758,13 +2320,31 @@ var DurableApiModule = class _DurableApiModule {
1758
2320
  return {
1759
2321
  module: _DurableApiModule,
1760
2322
  imports: [
1761
- ...options.imports ?? []
2323
+ ...options.imports ?? [],
2324
+ // `validation: 'off'`: the run filter's inputs are validated by its own translation — every
2325
+ // field/operator pair either maps onto a `RunQuery` predicate or is rejected by name — so
2326
+ // there is nothing left for class-validator to check, and requiring it would put a peer
2327
+ // dependency on every consumer of this dashboard for no gain.
2328
+ ...options.filterModule === "host" ? [] : [
2329
+ import_nestjs_filter3.FilterModule.forRoot({
2330
+ validation: "off"
2331
+ })
2332
+ ]
1762
2333
  ],
1763
2334
  controllers: [
1764
2335
  DurableApiController
1765
2336
  ],
1766
2337
  providers: [
1767
2338
  DashboardService,
2339
+ // The adapter is bound to its own token (never to the global `FILTER_ADAPTER`), which is
2340
+ // what lets the console's filter and the host app's own filters run on different backends
2341
+ // in one process — see `RunFilter`'s `@Filterable({ adapter })`.
2342
+ RunQueryAdapter,
2343
+ {
2344
+ provide: RUN_QUERY_ADAPTER,
2345
+ useExisting: RunQueryAdapter
2346
+ },
2347
+ RunFilter,
1768
2348
  options.authProvider,
1769
2349
  DurableApiSessionGuard,
1770
2350
  ...options.guards ?? []
@@ -1775,8 +2355,8 @@ var DurableApiModule = class _DurableApiModule {
1775
2355
  };
1776
2356
  }
1777
2357
  };
1778
- DurableApiModule = _ts_decorate8([
1779
- (0, import_common8.Module)({})
2358
+ DurableApiModule = _ts_decorate10([
2359
+ (0, import_common10.Module)({})
1780
2360
  ], DurableApiModule);
1781
2361
  var DurableDashboardModule = class _DurableDashboardModule {
1782
2362
  static {
@@ -1816,6 +2396,9 @@ var DurableDashboardModule = class _DurableDashboardModule {
1816
2396
  ...options.guards ? {
1817
2397
  guards: options.guards
1818
2398
  } : {},
2399
+ ...options.filterModule ? {
2400
+ filterModule: options.filterModule
2401
+ } : {},
1819
2402
  authProvider,
1820
2403
  authMayBeConfigured
1821
2404
  }),
@@ -1861,8 +2444,8 @@ var DurableDashboardModule = class _DurableDashboardModule {
1861
2444
  };
1862
2445
  }
1863
2446
  };
1864
- DurableDashboardModule = _ts_decorate8([
1865
- (0, import_common8.Module)({})
2447
+ DurableDashboardModule = _ts_decorate10([
2448
+ (0, import_common10.Module)({})
1866
2449
  ], DurableDashboardModule);
1867
2450
  // Annotate the CommonJS export names for ESM import in node:
1868
2451
  0 && (module.exports = {