@absolutejs/voice 0.0.22-beta.152 → 0.0.22-beta.153

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/vue/index.js CHANGED
@@ -378,6 +378,12 @@ var VoiceOpsStatus = defineComponent({
378
378
  import { defineComponent as defineComponent2, h as h2 } from "vue";
379
379
 
380
380
  // src/client/deliveryRuntime.ts
381
+ var getDefaultActionPath = (path, action, options) => {
382
+ if (action === "tick") {
383
+ return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
384
+ }
385
+ return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
386
+ };
381
387
  var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
382
388
  const fetchImpl = options.fetch ?? globalThis.fetch;
383
389
  const response = await fetchImpl(path);
@@ -386,11 +392,29 @@ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", opt
386
392
  }
387
393
  return await response.json();
388
394
  };
395
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
396
+ const fetchImpl = options.fetch ?? globalThis.fetch;
397
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
398
+ method: "POST"
399
+ });
400
+ if (!response.ok) {
401
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
402
+ }
403
+ const body = await response.json();
404
+ return {
405
+ action,
406
+ result: body.result,
407
+ summary: body.summary,
408
+ updatedAt: Date.now()
409
+ };
410
+ };
389
411
  var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
390
412
  const listeners = new Set;
391
413
  let closed = false;
392
414
  let timer;
393
415
  let snapshot = {
416
+ actionError: null,
417
+ actionStatus: "idle",
394
418
  error: null,
395
419
  isLoading: false
396
420
  };
@@ -412,6 +436,7 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
412
436
  try {
413
437
  const report = await fetchVoiceDeliveryRuntime(path, options);
414
438
  snapshot = {
439
+ ...snapshot,
415
440
  error: null,
416
441
  isLoading: false,
417
442
  report,
@@ -429,6 +454,37 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
429
454
  throw error;
430
455
  }
431
456
  };
457
+ const runAction = async (action) => {
458
+ if (closed) {
459
+ return snapshot.lastAction;
460
+ }
461
+ snapshot = {
462
+ ...snapshot,
463
+ actionError: null,
464
+ actionStatus: "running"
465
+ };
466
+ emit();
467
+ try {
468
+ const result = await runVoiceDeliveryRuntimeAction(action, path, options);
469
+ snapshot = {
470
+ ...snapshot,
471
+ actionError: null,
472
+ actionStatus: "completed",
473
+ lastAction: result
474
+ };
475
+ emit();
476
+ await refresh();
477
+ return result;
478
+ } catch (error) {
479
+ snapshot = {
480
+ ...snapshot,
481
+ actionError: error instanceof Error ? error.message : String(error),
482
+ actionStatus: "failed"
483
+ };
484
+ emit();
485
+ throw error;
486
+ }
487
+ };
432
488
  const close = () => {
433
489
  closed = true;
434
490
  if (timer) {
@@ -446,7 +502,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
446
502
  close,
447
503
  getServerSnapshot: () => snapshot,
448
504
  getSnapshot: () => snapshot,
505
+ requeueDeadLetters: () => runAction("requeue-dead-letters"),
449
506
  refresh,
507
+ tick: () => runAction("tick"),
450
508
  subscribe: (listener) => {
451
509
  listeners.add(listener);
452
510
  return () => {
@@ -495,6 +553,8 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
495
553
  return {
496
554
  description: options.description ?? DEFAULT_DESCRIPTION2,
497
555
  error: snapshot.error,
556
+ actionError: snapshot.actionError,
557
+ actionStatus: snapshot.actionStatus,
498
558
  isLoading: snapshot.isLoading,
499
559
  isRunning: Boolean(report?.isRunning),
500
560
  label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
@@ -511,6 +571,11 @@ var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
511
571
  <strong>${escapeHtml2(surface.detail)}</strong>
512
572
  <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
513
573
  </li>`).join("");
574
+ const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
575
+ <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
576
+ <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
577
+ </div>`;
578
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.actionError)}</p>` : "";
514
579
  return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml2(model.status)}">
515
580
  <header class="absolute-voice-delivery-runtime__header">
516
581
  <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml2(model.title)}</span>
@@ -518,20 +583,38 @@ var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
518
583
  </header>
519
584
  <p class="absolute-voice-delivery-runtime__description">${escapeHtml2(model.description)}</p>
520
585
  <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
586
+ ${actions}
587
+ ${actionError}
521
588
  ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.error)}</p>` : ""}
522
589
  </section>`;
523
590
  };
524
- var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
591
+ var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
525
592
  var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
526
593
  const store = createVoiceDeliveryRuntimeStore(path, options);
527
594
  const render = () => {
528
595
  element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
529
596
  };
530
597
  const unsubscribe = store.subscribe(render);
598
+ const handleClick = (event) => {
599
+ const target = event.target;
600
+ if (!(target instanceof Element)) {
601
+ return;
602
+ }
603
+ const action = target.closest("[data-absolute-voice-delivery-runtime-action]");
604
+ const actionName = action?.getAttribute("data-absolute-voice-delivery-runtime-action");
605
+ if (actionName === "tick") {
606
+ store.tick().catch(() => {});
607
+ }
608
+ if (actionName === "requeue-dead-letters") {
609
+ store.requeueDeadLetters().catch(() => {});
610
+ }
611
+ };
612
+ element.addEventListener?.("click", handleClick);
531
613
  render();
532
614
  store.refresh().catch(() => {});
533
615
  return {
534
616
  close: () => {
617
+ element.removeEventListener?.("click", handleClick);
535
618
  unsubscribe();
536
619
  store.close();
537
620
  },
@@ -563,12 +646,16 @@ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runt
563
646
  import { onUnmounted as onUnmounted2, ref as ref2, shallowRef as shallowRef2 } from "vue";
564
647
  function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options = {}) {
565
648
  const store = createVoiceDeliveryRuntimeStore(path, options);
649
+ const actionError = ref2(null);
650
+ const actionStatus = ref2("idle");
566
651
  const error = ref2(null);
567
652
  const isLoading = ref2(false);
568
653
  const report = shallowRef2(undefined);
569
654
  const updatedAt = ref2(undefined);
570
655
  const sync = () => {
571
656
  const snapshot = store.getSnapshot();
657
+ actionError.value = snapshot.actionError;
658
+ actionStatus.value = snapshot.actionStatus;
572
659
  error.value = snapshot.error;
573
660
  isLoading.value = snapshot.isLoading;
574
661
  report.value = snapshot.report;
@@ -584,10 +671,14 @@ function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options =
584
671
  store.close();
585
672
  });
586
673
  return {
674
+ actionError,
675
+ actionStatus,
587
676
  error,
588
677
  isLoading,
678
+ requeueDeadLetters: store.requeueDeadLetters,
589
679
  refresh: store.refresh,
590
680
  report,
681
+ tick: store.tick,
591
682
  updatedAt
592
683
  };
593
684
  }
@@ -597,6 +688,10 @@ var VoiceDeliveryRuntime = defineComponent2({
597
688
  name: "VoiceDeliveryRuntime",
598
689
  props: {
599
690
  description: String,
691
+ includeActions: {
692
+ default: true,
693
+ type: Boolean
694
+ },
600
695
  intervalMs: Number,
601
696
  path: {
602
697
  default: "/api/voice-delivery-runtime",
@@ -614,10 +709,13 @@ var VoiceDeliveryRuntime = defineComponent2({
614
709
  return () => {
615
710
  const model = createVoiceDeliveryRuntimeViewModel({
616
711
  error: runtime.error.value,
712
+ actionError: runtime.actionError.value,
713
+ actionStatus: runtime.actionStatus.value,
617
714
  isLoading: runtime.isLoading.value,
618
715
  report: runtime.report.value,
619
716
  updatedAt: runtime.updatedAt.value
620
717
  }, options);
718
+ const hasDeadLetters = model.surfaces.some((surface) => surface.deadLettered > 0);
621
719
  return h2("section", {
622
720
  class: [
623
721
  "absolute-voice-delivery-runtime",
@@ -640,6 +738,23 @@ var VoiceDeliveryRuntime = defineComponent2({
640
738
  h2("strong", surface.detail),
641
739
  h2("small", `${surface.failed} failed / ${surface.deadLettered} dead-lettered`)
642
740
  ]))),
741
+ props.includeActions ? h2("div", { class: "absolute-voice-delivery-runtime__actions" }, [
742
+ h2("button", {
743
+ disabled: model.actionStatus === "running",
744
+ onClick: () => {
745
+ runtime.tick().catch(() => {});
746
+ },
747
+ type: "button"
748
+ }, model.actionStatus === "running" ? "Working..." : "Tick workers"),
749
+ h2("button", {
750
+ disabled: model.actionStatus === "running" || !hasDeadLetters,
751
+ onClick: () => {
752
+ runtime.requeueDeadLetters().catch(() => {});
753
+ },
754
+ type: "button"
755
+ }, "Requeue dead letters")
756
+ ]) : null,
757
+ model.actionError ? h2("p", { class: "absolute-voice-delivery-runtime__error" }, model.actionError) : null,
643
758
  model.error ? h2("p", { class: "absolute-voice-delivery-runtime__error" }, model.error) : null
644
759
  ]);
645
760
  };
@@ -1,9 +1,13 @@
1
1
  import { type VoiceDeliveryRuntimeClientOptions } from '../client/deliveryRuntime';
2
2
  import type { VoiceDeliveryRuntimeReport } from '../deliveryRuntime';
3
3
  export declare function useVoiceDeliveryRuntime(path?: string, options?: VoiceDeliveryRuntimeClientOptions): {
4
+ actionError: import("vue").Ref<string | null, string | null>;
5
+ actionStatus: import("vue").Ref<"completed" | "failed" | "idle" | "running", "completed" | "failed" | "idle" | "running">;
4
6
  error: import("vue").Ref<string | null, string | null>;
5
7
  isLoading: import("vue").Ref<boolean, boolean>;
8
+ requeueDeadLetters: () => Promise<import("../client").VoiceDeliveryRuntimeActionResult | undefined>;
6
9
  refresh: () => Promise<VoiceDeliveryRuntimeReport | undefined>;
7
10
  report: import("vue").ShallowRef<VoiceDeliveryRuntimeReport | undefined, VoiceDeliveryRuntimeReport | undefined>;
11
+ tick: () => Promise<import("../client").VoiceDeliveryRuntimeActionResult | undefined>;
8
12
  updatedAt: import("vue").Ref<number | undefined, number | undefined>;
9
13
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.152",
3
+ "version": "0.0.22-beta.153",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",