bunqueue-dashboard 0.0.32 → 0.0.33

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.
Files changed (105) hide show
  1. package/README.md +44 -15
  2. package/agent/db.ts +537 -64
  3. package/agent/dbQueryWorker.ts +34 -11
  4. package/agent/manager.ts +186 -45
  5. package/agent/server.ts +124 -35
  6. package/dist/.vite/manifest.json +212 -157
  7. package/dist/assets/AddJob-ytpBLTCJ.js +3 -0
  8. package/dist/assets/Alerts-C39RrGbQ.js +1 -0
  9. package/dist/assets/{AreaChart-2gM0YoZT.js → AreaChart-REK4ZsTC.js} +1 -1
  10. package/dist/assets/Benchmark-CM60tHbf.js +1 -0
  11. package/dist/assets/BulkAddJobs-BjL-xcQy.js +5 -0
  12. package/dist/assets/CopilotPanel-BGK1rw-V.js +44 -0
  13. package/dist/assets/Cron-s1e-jgOo.js +1 -0
  14. package/dist/assets/CronManager-BostU7BX.js +1 -0
  15. package/dist/assets/Database-ZluStWMz.js +3 -0
  16. package/dist/assets/Diagnostics-C0N5z5j-.js +1 -0
  17. package/dist/assets/Dlq-CtcLzs-b.js +1 -0
  18. package/dist/assets/DlqControl-B_Z8KKn5.js +1 -0
  19. package/dist/assets/DlqPro-B68en6AG.js +1 -0
  20. package/dist/assets/Flows-CD_bkCBM.js +1 -0
  21. package/dist/assets/JobInspector-DwRtyMz0.js +2 -0
  22. package/dist/assets/Jobs-BUtcBKKk.js +1 -0
  23. package/dist/assets/JobsPro-BK_xd4ji.js +1 -0
  24. package/dist/assets/Logs-CmVODYCI.js +1 -0
  25. package/dist/assets/LogsPro-CJ-Il3LP.js +1 -0
  26. package/dist/assets/McpServer-dMjyJKgT.js +22 -0
  27. package/dist/assets/Metrics-Dsbeplz-.js +1 -0
  28. package/dist/assets/MetricsPro-BqxurxrJ.js +1 -0
  29. package/dist/assets/Overview-DH9C2dsf.js +1 -0
  30. package/dist/assets/{Pagination-B9JDi5MI.js → Pagination-DpxiBnt8.js} +1 -1
  31. package/dist/assets/QueueActions-D_QGBaVm.js +1 -0
  32. package/dist/assets/QueueControl-V0DJ6qk6.js +1 -0
  33. package/dist/assets/QueueDetail-BgKAMJqf.js +1 -0
  34. package/dist/assets/QueueDetailPro-BkHYzGiq.js +1 -0
  35. package/dist/assets/Queues-2_v7DcNi.js +1 -0
  36. package/dist/assets/QueuesOverview-BySSkmB4.js +1 -0
  37. package/dist/assets/S3Backup-CPADzKQE.js +1 -0
  38. package/dist/assets/S3BackupPro-CSrQYIDL.js +2 -0
  39. package/dist/assets/ServerControl-C0tI1VDx.js +3 -0
  40. package/dist/assets/Settings-CSzoM5up.js +1 -0
  41. package/dist/assets/Usage-B4B7tmrc.js +1 -0
  42. package/dist/assets/UsagePro-CCBpgSDy.js +1 -0
  43. package/dist/assets/Webhooks-aJz-GisQ.js +1 -0
  44. package/dist/assets/Workers-Bg8xKjkg.js +1 -0
  45. package/dist/assets/WorkersPro-BOOCrXf8.js +1 -0
  46. package/dist/assets/connectionStore-Cd9-3Fw0.js +1 -0
  47. package/dist/assets/flowMutationSafety-DVD1IMr-.js +1 -0
  48. package/dist/assets/form-DsUq0w8s.js +1 -0
  49. package/dist/assets/index-BWoUj86M.css +1 -0
  50. package/dist/assets/index-Bn2R06qm.js +8 -0
  51. package/dist/assets/{install-BIVfix28.js → install-CUS8Kijb.js} +2 -2
  52. package/dist/assets/jobActions-LQD4KfCc.js +1 -0
  53. package/dist/assets/promisePool-BVfQ9n9Q.js +1 -0
  54. package/dist/assets/{react-vendor-BcouBxpZ.js → react-vendor-Bjui4wS4.js} +1 -1
  55. package/dist/assets/upstreamPaths-nG8N1XAz.js +1 -0
  56. package/dist/assets/useServerActionGuard-CItj3hvh.js +1 -0
  57. package/dist/assets/useThroughputSeries-tb26_lkb.js +1 -0
  58. package/dist/index.html +5 -4
  59. package/package.json +11 -3
  60. package/scripts/embedded.gen.ts +132 -126
  61. package/scripts/serve.ts +259 -67
  62. package/dist/assets/AddJob-Dvpp--yq.js +0 -3
  63. package/dist/assets/Alerts-CR9jgCCs.js +0 -1
  64. package/dist/assets/Benchmark-CkL-Ee-M.js +0 -1
  65. package/dist/assets/BulkAddJobs-wI6cRZnX.js +0 -5
  66. package/dist/assets/CopilotPanel-DPZV9opm.js +0 -44
  67. package/dist/assets/Cron-gWVkYWad.js +0 -1
  68. package/dist/assets/CronManager-BvfW219u.js +0 -1
  69. package/dist/assets/Database-D2T_ZIGA.js +0 -3
  70. package/dist/assets/Diagnostics-C2goqq5h.js +0 -1
  71. package/dist/assets/Dlq-Q4TmmZrK.js +0 -1
  72. package/dist/assets/DlqControl-C5BfE7Gq.js +0 -1
  73. package/dist/assets/DlqPro-ClPNmw-X.js +0 -1
  74. package/dist/assets/Flows-DbhMbvSG.js +0 -1
  75. package/dist/assets/JobInspector-CO_zKjSX.js +0 -2
  76. package/dist/assets/Jobs-D2rDHPM_.js +0 -1
  77. package/dist/assets/JobsPro-Drdgdj3s.js +0 -1
  78. package/dist/assets/Logs-DjwGuRLi.js +0 -1
  79. package/dist/assets/LogsPro-7uTBjPWX.js +0 -1
  80. package/dist/assets/McpServer-DAklQDB5.js +0 -22
  81. package/dist/assets/Metrics-Dup9Zinh.js +0 -1
  82. package/dist/assets/MetricsPro-PP3TymeP.js +0 -1
  83. package/dist/assets/Overview-C7RCDE6r.js +0 -1
  84. package/dist/assets/QueueActions-DJTw0h2g.js +0 -1
  85. package/dist/assets/QueueControl-CxKjUjF-.js +0 -1
  86. package/dist/assets/QueueDetail-bf2n-r2h.js +0 -1
  87. package/dist/assets/QueueDetailPro-C-XLWFBa.js +0 -1
  88. package/dist/assets/Queues-CMQW89J9.js +0 -1
  89. package/dist/assets/QueuesOverview-x7-akDzf.js +0 -1
  90. package/dist/assets/S3Backup-1jAySC9R.js +0 -1
  91. package/dist/assets/S3BackupPro-BG_0OHW7.js +0 -1
  92. package/dist/assets/ServerControl-DohTB--h.js +0 -3
  93. package/dist/assets/Settings-CnS5PjNe.js +0 -1
  94. package/dist/assets/Usage-C3H0hMSA.js +0 -1
  95. package/dist/assets/UsagePro-CdnQkP9o.js +0 -1
  96. package/dist/assets/Webhooks-CAwVmIEZ.js +0 -1
  97. package/dist/assets/Workers-lvujKZwF.js +0 -1
  98. package/dist/assets/WorkersPro-CIJKl7U1.js +0 -1
  99. package/dist/assets/connectionStore-DO6xQY7h.js +0 -1
  100. package/dist/assets/form-DGinTEEb.js +0 -1
  101. package/dist/assets/index-DcVOpnSj.css +0 -1
  102. package/dist/assets/index-r1ZMLIZ9.js +0 -8
  103. package/dist/assets/jobActions-CuOdMglt.js +0 -1
  104. package/dist/assets/promisePool-Daxkc1OB.js +0 -1
  105. package/dist/assets/useThroughputSeries-CVKzWzdv.js +0 -1
@@ -0,0 +1,3 @@
1
+ import{r as e}from"./cn-CMFYpumL.js";import{g as t,l as n,r,t as i}from"./react-vendor-Bjui4wS4.js";import{i as a,o}from"./upstreamPaths-nG8N1XAz.js";import{A as s,C as c,S as l,ct as ee,ft as u,h as d,st as f,w as p}from"./index-Bn2R06qm.js";import{a as m,n as h,o as g,t as _}from"./form-DsUq0w8s.js";import{r as te}from"./useServerActionGuard-CItj3hvh.js";var v=e(t(),1),y=i(),b=e=>e==null?``:String(e),x=365*24*60*60*1e3,S=1440*60*1e3,ne=10*1024*1024,C=10*1024*1024;function w(e,t=1/0){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);if(i<=127?n+=1:i<=2047?n+=2:i>=55296&&i<=56319&&r+1<e.length&&e.charCodeAt(r+1)>=56320&&e.charCodeAt(r+1)<=57343?(n+=4,r+=1):n+=3,n>t)return n}return n}function T(e){return e.length>10485760||w(e,10485760)>10485760?`Job data is too large (maximum 10 MiB UTF-8 / 10,485,760 characters)`:null}function E(e){let t=T(e);if(t)return{ok:!1,kind:`size`,msg:t};let n;try{n=JSON.parse(e)}catch(e){return{ok:!1,kind:`json`,msg:`Invalid JSON: ${e.message}`}}let r=JSON.stringify(n);return r.length>10485760||w(r,10485760)>10485760?{ok:!1,kind:`size`,msg:`Job data is too large after JSON encoding (maximum 10 MiB UTF-8)`}:{ok:!0,data:n}}function re(e){let t=[{key:`priority`,label:`Priority`,min:-1e6,max:1e6,integer:!0},{key:`delay`,label:`Delay`,min:0,max:x,integer:!0},{key:`maxAttempts`,label:`Max attempts`,min:1,max:1e3,integer:!0},{key:`backoff`,label:`Backoff`,min:0,max:S,integer:!0},{key:`timeout`,label:`Timeout`,min:0,max:S,integer:!0},{key:`ttl`,label:`TTL`,min:0,max:x,integer:!0}],n={};for(let r of t){let t=(e[r.key]??``).trim();if(!t)continue;let i=Number(t);if(!Number.isFinite(i))return{ok:!1,msg:`${r.label} must be a number`};if(r.integer&&!Number.isSafeInteger(i))return{ok:!1,msg:`${r.label} must be a whole, safe integer`};if(i<r.min||i>r.max)return{ok:!1,msg:`${r.label} must be between ${r.min} and ${r.max}`};n[r.key]=i}return{ok:!0,options:n}}function D(e){let t=o(e);return!e&&t?`Choose a queue`:t}function ie(e,t){return e==null?t?{ok:!1,msg:`Backoff strategy needs a base delay in Backoff (ms)`}:{ok:!0,backoff:void 0}:{ok:!0,backoff:t?{type:t,delay:e}:e}}function ae(e,t){return{ok:!0,msg:`Accepted ${t} job submission${t===1?``:`s`}; server returned ${e} distinct job ID${e===1?``:`s`} (deduplication may reuse existing jobs)`}}function oe(e){if(typeof e!=`object`||!e||e.ok!==!0||typeof e.id!=`string`||!e.id||e.id.length>1024)throw Error(`Add job returned a malformed success response`);return e.id}function O(e,t){let n=e?.ids;if(typeof e!=`object`||!e||e.ok!==!0||!Array.isArray(n)||n.length!==t||n.some(e=>typeof e!=`string`||e.length===0||e.length>1024))throw Error(`Bulk add returned a malformed success response`);return n}function k(e){if(!e.trim())return{ok:!0,repeat:void 0};try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))return{ok:!1,msg:`Repeat must be a JSON object`};let n=t,r=new Set([`every`,`limit`,`pattern`]),i=Object.keys(n).filter(e=>!r.has(e));if(i.length)return{ok:!1,msg:`Unknown repeat option${i.length===1?``:`s`}: ${i.join(`, `)}`};if(n.pattern!==void 0)return{ok:!1,msg:`repeat.pattern is unsafe in bunqueue v2.8.55; use repeat.every or a Cron schedule`};let a=n.every;return!Number.isSafeInteger(a)||a<=0||a>x?{ok:!1,msg:`Repeat "every" must be a whole number from 1 to ${x} ms`}:n.limit!==void 0&&(!Number.isSafeInteger(n.limit)||n.limit<1)?{ok:!1,msg:`Repeat "limit" must be a whole number of at least 1`}:{ok:!0,repeat:{every:a,...typeof n.limit==`number`?{limit:n.limit}:{}}}}catch(e){return{ok:!1,msg:`Repeat is not valid JSON: ${e.message}`}}}function se(e){let t=typeof e.backoff==`object`?e.backoff:void 0,n=e.backoffConfig??t;return{backoff:b(n?.delay??(typeof e.backoff==`number`?e.backoff:void 0)),backoffType:n?.type??``,tags:e.tags?.join(`, `)??``,groupId:e.groupId??``,ttl:b(e.ttl)}}function A(){let{data:e,error:t,refetch:i}=s(()=>f.queues(),[],{intervalMs:3e4}),o=n().state?.clone,g=o?.options??{},C=se(g),[w,T]=(0,v.useState)(o?.queue??``),[A,ce]=(0,v.useState)(o?.dataText??`{
2
+ "hello": "world"
3
+ }`),[le,ue]=(0,v.useState)(`1`),[de,fe]=(0,v.useState)(b(g.priority)),[M,pe]=(0,v.useState)(``),[N,me]=(0,v.useState)(``),[P,he]=(0,v.useState)(b(g.maxAttempts)),[F,ge]=(0,v.useState)(C.backoff),[I,_e]=(0,v.useState)(b(g.timeout)),[L,ve]=(0,v.useState)(C.ttl),[R,ye]=(0,v.useState)(``),[z,be]=(0,v.useState)(g.removeOnComplete??!1),[B,xe]=(0,v.useState)(g.removeOnFail??!1),[V,Se]=(0,v.useState)(!1),[H,Ce]=(0,v.useState)(!1),[U,we]=(0,v.useState)(C.backoffType),[W,Te]=(0,v.useState)(C.tags),[G,Ee]=(0,v.useState)(C.groupId),[K,De]=(0,v.useState)(``),[q,Oe]=(0,v.useState)(``),[J,ke]=(0,v.useState)(``),[Y,X]=(0,v.useState)(!1),[Z,Q]=(0,v.useState)(null),[Ae,$]=(0,v.useState)(null),je=te(`add-job`);(0,v.useEffect)(()=>{X(!1),Q(null),$(null)},[je.scopeKey]);let Me=async()=>{Q(null),$(null);let e=w.trim(),t=D(e);if(t){Q({ok:!1,msg:t});return}let n=E(A);if(!n.ok){n.kind===`json`?$(n.msg):Q({ok:!1,msg:n.msg});return}let r=n.data,i=re({priority:de,delay:N.trim()?``:M,maxAttempts:P,backoff:F,timeout:I,ttl:L});if(!i.ok){Q({ok:!1,msg:i.msg});return}let o=i.options.delay;if(N.trim()){let e=new Date(N).getTime();if(!Number.isFinite(e)){Q({ok:!1,msg:`Run at is not a valid date/time`});return}if(o=Math.max(0,e-Date.now()),o>x){Q({ok:!1,msg:`Run at must be within the next 365 days`});return}}let s=ie(i.options.backoff,U);if(!s.ok){Q({ok:!1,msg:s.msg});return}let c=s.backoff,l=W.split(`,`).map(e=>e.trim()).filter(Boolean),d=K.split(`,`).map(e=>e.trim()).filter(Boolean),p=R.trim();if(p){let e=a(p);if(e){Q({ok:!1,msg:`Job ID: ${e}`});return}}for(let e of d){let t=a(e);if(t){Q({ok:!1,msg:`Dependency ID "${e}": ${t}`});return}}let m=k(J);if(!m.ok){Q({ok:!1,msg:m.msg});return}let h={data:r,priority:i.options.priority,delay:o,maxAttempts:i.options.maxAttempts,backoff:c,timeout:i.options.timeout,ttl:i.options.ttl,jobId:p||void 0,removeOnComplete:z||void 0,removeOnFail:B||void 0,durable:V||void 0,lifo:H||void 0,tags:l.length?l:void 0,groupId:G.trim()||void 0,dependsOn:d.length?d:void 0,uniqueKey:q.trim()||void 0,repeat:m.repeat},g=Number(le);if(!Number.isSafeInteger(g)||g<1||g>1e4){Q({ok:!1,msg:`Count must be a whole number from 1 to 10000`});return}let _=je.begin();if(_){X(!0);try{if(g===1){let t=oe(await f.addJob(e,h));if(!_.isCurrent())return;Q({ok:!0,msg:`Accepted job ID ${t} (it may be an existing deduplicated job)`}),u.success(`Job submission accepted`,`${e} · ${t}`)}else{let t=Array.from({length:g},()=>h),n=ee(t);if(n){_.isCurrent()&&Q({ok:!1,msg:n});return}let r=O(await f.addJobsBulk(e,t),g);if(!_.isCurrent())return;let i=ae(new Set(r).size,g);Q(i),u.success(i.msg,`in ${e}`)}}catch(e){if(!_.isCurrent())return;Q({ok:!1,msg:e.message}),u.error(`Add job failed`,e.message)}finally{_.finish()&&X(!1)}}};return(0,y.jsxs)(`div`,{children:[(0,y.jsx)(d,{title:`Add Job`,description:`Enqueue a job with full options.`,actions:(0,y.jsx)(r,{to:`/jobs/bulk-add`,className:`rounded-lg border border-line px-3 py-1.5 text-sm text-muted hover:bg-surface-2 hover:text-fg`,children:`Bulk import`})}),o&&(0,y.jsx)(`div`,{className:`mb-4 flex items-center gap-2 rounded-lg border border-accent/30 bg-accent/[0.06] px-4 py-2 text-sm text-accent`,children:`Pre-filled from an existing job. Review the data and options, then enqueue a fresh job.`}),(0,y.jsxs)(`form`,{className:`grid grid-cols-1 gap-6 lg:grid-cols-2`,onSubmit:e=>{e.preventDefault(),Me()},children:[(0,y.jsxs)(l,{children:[(0,y.jsx)(c,{title:`Job`}),(0,y.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,y.jsxs)(_,{label:`Queue`,children:[(0,y.jsx)(h,{list:`queue-options`,"aria-label":`Queue`,name:`target-queue`,autoComplete:`off`,value:w,onChange:e=>T(e.target.value),placeholder:`queue name (existing or new)`}),(0,y.jsx)(`datalist`,{id:`queue-options`,children:(e?.queues??[]).map(e=>(0,y.jsx)(`option`,{value:e.name},e.name))})]}),t&&(0,y.jsxs)(`p`,{role:`status`,className:`-mt-2 text-xs text-warning`,children:[`Existing queue suggestions unavailable — `,t.message,`. You can still enter a queue name manually.`,` `,(0,y.jsx)(`button`,{type:`button`,onClick:()=>void i(),className:`font-medium underline underline-offset-2 hover:text-fg`,children:`Retry`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(_,{label:`Data (JSON)`,children:(0,y.jsx)(`textarea`,{name:`job-data`,value:A,onChange:e=>ce(e.target.value),onBlur:()=>{let e=E(A);$(e.ok?null:e.msg)},maxLength:ne,spellCheck:!1,rows:7,className:`w-full rounded-lg border border-line bg-surface-2 p-3 font-mono text-sm text-fg focus:border-accent/60 focus:outline-none focus:ring-2 focus:ring-accent/30`})}),Ae&&(0,y.jsx)(`p`,{role:`alert`,className:`mt-2 text-xs text-danger`,children:Ae})]})]})]}),(0,y.jsxs)(l,{children:[(0,y.jsx)(c,{title:`Options`}),(0,y.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 md:grid-cols-3`,children:[(0,y.jsx)(_,{label:`Priority`,children:(0,y.jsx)(h,{type:`number`,min:-1e6,max:1e6,step:1,name:`priority`,value:de,onChange:e=>fe(e.target.value),placeholder:`0`})}),(0,y.jsx)(_,{label:`Delay (ms)`,children:(0,y.jsx)(h,{type:`number`,min:0,max:x,step:1,name:`delay`,value:M,onChange:e=>pe(e.target.value),placeholder:`0`,disabled:N.trim()!==``})}),(0,y.jsx)(_,{label:`Run at`,hint:N.trim()?`Overrides Delay — derived from this time (local time).`:`(local time)`,children:(0,y.jsx)(h,{type:`datetime-local`,name:`run-at`,value:N,onChange:e=>me(e.target.value)})}),(0,y.jsx)(_,{label:`Max attempts`,hint:`blank = server default`,children:(0,y.jsx)(h,{type:`number`,min:1,max:1e3,step:1,name:`max-attempts`,value:P,onChange:e=>he(e.target.value),placeholder:`3`})}),(0,y.jsx)(_,{label:`Backoff (ms)`,hint:`blank = server default`,children:(0,y.jsx)(h,{type:`number`,min:0,max:S,step:1,name:`backoff`,value:F,onChange:e=>ge(e.target.value),placeholder:`1000`})}),(0,y.jsx)(_,{label:`Backoff strategy`,hint:`flat delay unless set`,children:(0,y.jsxs)(m,{name:`backoff-strategy`,value:U,onChange:e=>we(e.target.value),children:[(0,y.jsx)(`option`,{value:``,children:`flat`}),(0,y.jsx)(`option`,{value:`fixed`,children:`fixed`}),(0,y.jsx)(`option`,{value:`exponential`,children:`exponential`})]})}),(0,y.jsx)(_,{label:`Timeout (ms)`,children:(0,y.jsx)(h,{type:`number`,min:0,max:S,step:1,name:`timeout`,value:I,onChange:e=>_e(e.target.value),placeholder:`—`})}),(0,y.jsx)(_,{label:`TTL (ms)`,hint:`blank = no expiry`,children:(0,y.jsx)(h,{type:`number`,min:0,max:x,step:1,name:`ttl`,value:L,onChange:e=>ve(e.target.value),placeholder:`—`})}),(0,y.jsx)(_,{label:`Custom job ID`,children:(0,y.jsx)(h,{name:`custom-job-id`,value:R,onChange:e=>ye(e.target.value),placeholder:`idempotency key`})})]}),(0,y.jsxs)(`div`,{className:`mt-4 flex flex-wrap gap-6`,children:[(0,y.jsx)(j,{label:`removeOnComplete`,checked:z,onChange:be}),(0,y.jsx)(j,{label:`removeOnFail`,checked:B,onChange:xe}),(0,y.jsx)(j,{label:`durable`,checked:V,onChange:Se}),(0,y.jsx)(j,{label:`lifo`,checked:H,onChange:Ce})]}),(0,y.jsxs)(`div`,{className:`mt-4 border-t border-line pt-4`,children:[(0,y.jsx)(`div`,{className:`mb-3 text-[11px] uppercase tracking-wider text-faint`,children:`Advanced`}),(0,y.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 md:grid-cols-3`,children:[(0,y.jsx)(_,{label:`Tags`,hint:`comma-separated`,children:(0,y.jsx)(h,{name:`tags`,value:W,onChange:e=>Te(e.target.value),placeholder:`email, urgent`})}),(0,y.jsx)(_,{label:`Group ID`,children:(0,y.jsx)(h,{name:`group-id`,value:G,onChange:e=>Ee(e.target.value),placeholder:`—`})}),(0,y.jsx)(_,{label:`Unique key`,hint:`dedup key`,children:(0,y.jsx)(h,{name:`unique-key`,value:q,onChange:e=>Oe(e.target.value),placeholder:`—`})}),(0,y.jsx)(_,{label:`Depends on`,hint:`parent job ids, comma-separated`,children:(0,y.jsx)(h,{name:`depends-on`,value:K,onChange:e=>De(e.target.value),placeholder:`job-id-1, job-id-2`})}),(0,y.jsx)(`div`,{className:`col-span-2 md:col-span-3`,children:(0,y.jsx)(_,{label:`Repeat policy (JSON)`,hint:`v2.8.55-safe form: e.g. {"every":60000,"limit":10}. Use Cron Manager for cron patterns.`,children:(0,y.jsx)(`textarea`,{name:`repeat-policy`,value:J,onChange:e=>ke(e.target.value),rows:2,spellCheck:!1,placeholder:`{"every": 60000}`,className:`w-full rounded-lg border border-line bg-surface-2 px-3 py-2 font-mono text-xs text-fg placeholder:text-faint focus:border-accent/60 focus:outline-none focus:ring-2 focus:ring-accent/30`})})})]})]})]}),(0,y.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3 lg:col-span-2`,children:[(0,y.jsx)(`div`,{className:`w-28`,children:(0,y.jsx)(_,{label:`Count`,hint:`1–10000`,children:(0,y.jsx)(h,{type:`number`,min:1,max:1e4,step:1,name:`count`,value:le,onChange:e=>ue(e.target.value)})})}),(0,y.jsx)(p,{type:`submit`,variant:`accent`,disabled:Y,children:Y?`Adding…`:`Add job`}),Z&&(0,y.jsx)(`span`,{role:Z.ok?`status`:`alert`,className:Z.ok?`text-sm text-success`:`text-sm text-danger`,children:Z.msg})]})]})]})}function j({label:e,checked:t,onChange:n}){return(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,y.jsx)(g,{checked:t,onChange:n,label:e}),(0,y.jsx)(`span`,{className:`font-mono text-xs text-muted`,children:e})]})}export{A as AddJob,C as MAX_JOB_DATA_BYTES,ne as MAX_JOB_DATA_CHARS,O as acceptedBulkIds,E as parseJobData,k as parseRepeat,D as queueNameError,w as utf8ByteLength};
@@ -0,0 +1 @@
1
+ import{r as e}from"./cn-CMFYpumL.js";import{g as t,t as n}from"./react-vendor-Bjui4wS4.js";import{o as r}from"./connectionStore-Cd9-3Fw0.js";import{N as i,S as a,T as o,Y as s,et as c,h as l,mt as u,nt as d,pt as f,tt as p,u as m,v as h,w as g,x as _}from"./index-Bn2R06qm.js";import{a as v,n as y,o as b,t as x}from"./form-DsUq0w8s.js";var S=e(t(),1),C=n(),w=[`email`,`webhook`,`slack`],T=Object.keys(f),E=[`>=`,`>`,`<=`,`<`],D={error_rate:{unit:`% (0–100)`,placeholder:`e.g. 5`},p99_latency:{unit:`ms`,placeholder:`e.g. 250`},waiting:{unit:`jobs`,placeholder:`e.g. 100`},failed:{unit:`jobs`,placeholder:`e.g. 10`},dlq:{unit:`jobs`,placeholder:`e.g. 1`}},O=/^[a-zA-Z0-9_\-.:]+$/;function k(e){let t=e.name.trim();if(!T.includes(e.metric))return{ok:!1,error:`Invalid metric`,field:`metric`};if(!E.includes(e.operator))return{ok:!1,error:`Invalid operator`,field:`operator`};let n=e.metric===`p99_latency`?``:e.queue.trim();if(!t)return{ok:!1,error:`Rule name is required`,field:`name`};if(t.length>200)return{ok:!1,error:`Rule name must be 200 characters or fewer`,field:`name`};if(!e.threshold.trim())return{ok:!1,error:`Threshold is required`,field:`threshold`};let r=Number(e.threshold);return!Number.isFinite(r)||r<0?{ok:!1,error:`Threshold must be a non-negative number`,field:`threshold`}:e.metric===`error_rate`&&r>100?{ok:!1,error:`Error-rate threshold must be between 0 and 100%`,field:`threshold`}:[`waiting`,`failed`,`dlq`].includes(e.metric)&&!Number.isSafeInteger(r)?{ok:!1,error:`Job-count thresholds must be whole numbers`,field:`threshold`}:n&&(n.length>256||!O.test(n))?{ok:!1,error:`Queue contains unsupported characters or is too long`,field:`queue`}:w.includes(e.channel)?{ok:!0,rule:{name:t,metric:e.metric,operator:e.operator,threshold:r,queue:n,channel:e.channel,enabled:!0}}:{ok:!1,error:`Invalid channel type`,field:`channel`}}function A(){return typeof Notification>`u`?`unsupported`:Notification.permission}function j(){let{rules:e,addRule:t,removeRule:n,toggleRule:v}=u(),y=d(e=>e.breaching),x=d(e=>e.status),w=d(e=>e.error),T=d(e=>e.connectionIdentity),E=r(e=>c(e.baseUrl,e.token)),D=e.some(e=>e.enabled),O=T===E,k=O?y:[],j=O?x:D?`checking`:`idle`,N=O?w:null,[P,F]=(0,S.useState)(!1),[I,L]=(0,S.useState)(A);return(0,C.jsxs)(`div`,{children:[(0,C.jsx)(l,{title:`Alerts`,description:`Threshold rules evaluated live in your browser.`,live:D&&j===`live`,actions:(0,C.jsxs)(C.Fragment,{children:[I===`granted`?(0,C.jsxs)(`span`,{className:`flex items-center gap-1.5 text-sm text-success`,children:[(0,C.jsx)(i,{className:`size-4`}),` Desktop alerts on`]}):I===`unsupported`?(0,C.jsx)(`span`,{className:`text-sm text-faint`,children:`Notifications unsupported`}):I===`denied`?(0,C.jsx)(`span`,{className:`text-sm text-faint`,children:`Desktop alerts blocked — allow notifications in browser settings`}):(0,C.jsx)(g,{size:`sm`,onClick:async()=>{L(await p())},children:`Enable desktop notifications`}),(0,C.jsx)(g,{variant:`accent`,size:`sm`,"aria-expanded":P,"aria-controls":`alert-rule-form`,onClick:()=>F(e=>!e),children:`+ Create Alert Rule`})]})}),D&&j===`checking`&&(0,C.jsx)(`p`,{role:`status`,className:`mb-4 text-sm text-muted`,children:`Checking alert metrics for the connected server…`}),D&&j===`degraded`&&(0,C.jsx)(_,{message:N??`Alert metrics are unavailable; current rule results may be stale.`}),(0,C.jsx)(`div`,{className:`mb-6 rounded-lg border border-amber-500/20 bg-amber-500/5 px-4 py-3 text-sm text-amber-400/90`,children:`Rules are evaluated in this browser while a tab is open (even backgrounded), raising an in-app toast and — if enabled — a desktop notification. bunqueue OSS has no alerting backend, so email/webhook/slack delivery still needs your own monitoring or hosted bunqueue Cloud.`}),(0,C.jsxs)(`section`,{className:`mb-8`,children:[(0,C.jsx)(`h2`,{className:`mb-3 text-lg font-semibold text-fg`,children:`Triggered Alerts`}),k.length===0?(0,C.jsx)(h,{icon:(0,C.jsx)(i,{}),title:`No triggered alerts`,hint:D?j===`live`?`All enabled rules are within their thresholds.`:j===`checking`?`Alert metrics are still being checked.`:`Alert metrics are unavailable; no all-clear result is available.`:`No enabled rules yet. Create one below.`}):(0,C.jsx)(`div`,{className:`overflow-x-auto rounded-xl border border-danger/30 bg-red-500/5`,children:(0,C.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,C.jsx)(`thead`,{children:(0,C.jsxs)(`tr`,{className:`border-b border-line text-left text-[11px] uppercase tracking-wider text-faint`,children:[(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Rule`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Condition`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Queue`}),(0,C.jsx)(`th`,{className:`px-5 py-3 text-right font-medium`,children:`Current`}),(0,C.jsx)(`th`,{className:`px-5 py-3 text-right font-medium`,children:`Since`})]})}),(0,C.jsx)(`tbody`,{children:k.map(e=>(0,C.jsxs)(`tr`,{className:`border-b border-line last:border-0`,children:[(0,C.jsx)(`td`,{className:`px-5 py-3 font-medium text-danger`,children:e.ruleName}),(0,C.jsxs)(`td`,{className:`px-5 py-3 text-muted`,children:[e.metricLabel,` `,e.operator,` `,(0,C.jsx)(`span`,{className:`font-semibold text-fg`,children:e.threshold})]}),(0,C.jsx)(`td`,{className:`px-5 py-3 text-muted`,children:e.queue||`All queues`}),(0,C.jsx)(`td`,{className:`px-5 py-3 text-right tnum font-semibold text-danger`,children:Math.round(e.value*100)/100}),(0,C.jsx)(`td`,{className:`px-5 py-3 text-right text-faint`,children:m(e.at)})]},e.ruleId))})]})})]}),(0,C.jsxs)(`section`,{children:[(0,C.jsx)(`h2`,{className:`mb-3 text-lg font-semibold text-fg`,children:`Alert Rules`}),P&&(0,C.jsx)(`div`,{id:`alert-rule-form`,children:(0,C.jsx)(a,{className:`mb-4`,children:(0,C.jsx)(M,{onAdd:e=>{let n=t(e);return n.ok&&F(!1),n}})})}),e.length===0?(0,C.jsx)(h,{title:`No alert rules`,hint:`Create a rule to be notified when a threshold is crossed.`}):(0,C.jsx)(`div`,{className:`overflow-x-auto rounded-xl border border-line bg-surface`,children:(0,C.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,C.jsx)(`thead`,{children:(0,C.jsxs)(`tr`,{className:`border-b border-line text-left text-[11px] uppercase tracking-wider text-faint`,children:[(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Rule`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Condition`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Queue`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Delivery`}),(0,C.jsx)(`th`,{className:`px-5 py-3 font-medium`,children:`Status`}),(0,C.jsx)(`th`,{className:`w-12 px-5 py-3`})]})}),(0,C.jsx)(`tbody`,{children:e.map(e=>(0,C.jsxs)(`tr`,{className:`border-b border-line last:border-0`,children:[(0,C.jsx)(`td`,{className:`px-5 py-3 font-medium text-fg`,children:e.name}),(0,C.jsxs)(`td`,{className:`px-5 py-3 text-muted`,children:[f[e.metric],` `,e.operator,` `,(0,C.jsx)(`span`,{className:`font-semibold text-accent`,children:e.threshold})]}),(0,C.jsx)(`td`,{className:`px-5 py-3 text-muted`,children:e.queue||`All queues`}),(0,C.jsx)(`td`,{className:`px-5 py-3`,children:(0,C.jsx)(`span`,{className:`rounded-md bg-surface-2 px-2 py-0.5 text-xs text-muted`,children:`Browser`})}),(0,C.jsx)(`td`,{className:`px-5 py-3`,children:(0,C.jsx)(b,{checked:e.enabled,onChange:()=>v(e.id),label:`Enabled`})}),(0,C.jsx)(`td`,{className:`px-5 py-3 text-right`,children:(0,C.jsx)(o,{"aria-label":`Delete rule ${e.name}`,onClick:()=>window.confirm(`Delete alert rule "${e.name}"?`)&&n(e.id),children:(0,C.jsx)(s,{className:`size-3.5`})})})]},e.id))})]})})]})]})}function M({onAdd:e}){let[t,n]=(0,S.useState)(``),[r,i]=(0,S.useState)(`error_rate`),[a,o]=(0,S.useState)(`>=`),[s,c]=(0,S.useState)(``),[l,u]=(0,S.useState)(``),[d,p]=(0,S.useState)(null),m=(0,S.useRef)(!1),h=(0,S.useId)(),_=e=>d?.field===e;return(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-5`,children:[(0,C.jsx)(x,{label:`Name`,children:(0,C.jsx)(y,{name:`alert-rule-name`,autoComplete:`off`,maxLength:200,value:t,"aria-invalid":_(`name`),"aria-describedby":_(`name`)?h:void 0,onChange:e=>{n(e.target.value),p(null)},placeholder:`High error rate`})}),(0,C.jsx)(x,{label:`Metric`,children:(0,C.jsx)(v,{name:`alert-rule-metric`,value:r,"aria-invalid":_(`metric`),"aria-describedby":_(`metric`)?h:void 0,onChange:e=>{i(e.target.value),p(null)},children:T.map(e=>(0,C.jsx)(`option`,{value:e,children:f[e]},e))})}),(0,C.jsx)(x,{label:`Operator`,children:(0,C.jsx)(v,{name:`alert-rule-operator`,value:a,"aria-invalid":_(`operator`),"aria-describedby":_(`operator`)?h:void 0,onChange:e=>{o(e.target.value),p(null)},children:E.map(e=>(0,C.jsx)(`option`,{value:e,children:e},e))})}),(0,C.jsx)(x,{label:`Threshold`,hint:D[r].unit,children:(0,C.jsx)(y,{name:`alert-rule-threshold`,autoComplete:`off`,type:`number`,min:0,max:r===`error_rate`?100:void 0,step:[`waiting`,`failed`,`dlq`].includes(r)?1:`any`,value:s,"aria-invalid":_(`threshold`),"aria-describedby":_(`threshold`)?h:void 0,onChange:e=>{c(e.target.value),p(null)},placeholder:D[r].placeholder})}),(0,C.jsx)(x,{label:`Queue (optional)`,hint:r===`p99_latency`?`global only — latency is not per queue`:void 0,children:(0,C.jsx)(y,{name:`alert-rule-queue`,autoComplete:`off`,spellCheck:!1,maxLength:256,value:l,"aria-invalid":_(`queue`),"aria-describedby":_(`queue`)?h:void 0,onChange:e=>{u(e.target.value),p(null)},disabled:r===`p99_latency`,placeholder:r===`p99_latency`?`Global`:`All queues`,className:`disabled:cursor-not-allowed disabled:opacity-40`})}),(0,C.jsxs)(`div`,{className:`col-span-full`,children:[(0,C.jsx)(g,{variant:`accent`,disabled:!t.trim()||!s.trim(),onClick:()=>{if(m.current)return;let n=k({name:t,metric:r,operator:a,threshold:s,queue:l,channel:`email`});if(!n.ok){p({field:n.field,message:n.error});return}m.current=!0;try{let t=e(n.rule);t.ok||(m.current=!1,p({field:`name`,message:t.error}))}catch(e){m.current=!1,p({field:`name`,message:e.message})}},children:`Save rule`}),d&&(0,C.jsx)(`span`,{id:h,role:`alert`,className:`ml-3 text-xs text-danger`,children:d.message})]})]})}export{j as Alerts};
@@ -1 +1 @@
1
- import{r as e}from"./cn-CMFYpumL.js";import{h as t,t as n}from"./react-vendor-BcouBxpZ.js";var r=e(t(),1),i=n();function a({series:e,height:t=180,xLabels:n,ariaLabel:a=`throughput chart`,formatValue:o}){let s=(0,r.useId)().replace(/:/g,``),c=`${s}-desc`,l=t,u=e=>Number.isFinite(e)?e:0,d=Math.max(1,...e.map(e=>e.points.length)),f=Math.max(1,...e.flatMap(e=>e.points.map(u))),p=e=>d<=1?0:e/(d-1)*600,m=e=>l-10-u(e)/f*(l-20),h=[0,.25,.5,.75,1].map(e=>10+e*(l-20)),g=o??(e=>Number.isInteger(e)?String(e):e.toFixed(1)),_=e.some(e=>e.points.length>0),v=e.find(e=>e.points.length>0),y=v?u(v.points[v.points.length-1]):0;return(0,i.jsxs)(`div`,{className:`w-full`,children:[(0,i.jsxs)(`div`,{className:`relative`,children:[(0,i.jsxs)(`svg`,{viewBox:`0 0 600 ${l}`,preserveAspectRatio:`none`,className:`block w-full`,style:{height:t},role:`img`,"aria-label":a,"aria-describedby":c,children:[(0,i.jsx)(`defs`,{children:e.map((e,t)=>(0,i.jsxs)(`linearGradient`,{id:`${s}-g${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,i.jsx)(`stop`,{offset:`0%`,stopColor:e.color,stopOpacity:`0.28`}),(0,i.jsx)(`stop`,{offset:`100%`,stopColor:e.color,stopOpacity:`0`})]},e.label))}),h.map(e=>(0,i.jsx)(`line`,{x1:`0`,y1:e,x2:600,y2:e,stroke:`var(--line)`,strokeWidth:`1`},e)),e.map((e,t)=>{if(e.points.length===0)return null;let n=e.points.length===1?`M0,${m(e.points[0])} L600,${m(e.points[0])}`:e.points.map((e,t)=>`${t===0?`M`:`L`}${p(t)},${m(e)}`).join(` `),r=e.points.length===1?`${n} L600,${l} L0,${l} Z`:`${n} L${p(e.points.length-1)},${l} L${p(0)},${l} Z`;return(0,i.jsxs)(`g`,{children:[e.area&&(0,i.jsx)(`path`,{d:r,fill:`url(#${s}-g${t})`}),(0,i.jsx)(`path`,{d:n,fill:`none`,stroke:e.color,strokeWidth:`2`,strokeLinejoin:`round`,vectorEffect:`non-scaling-stroke`})]},e.label)})]}),_&&(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(`span`,{className:`pointer-events-none absolute left-1 -translate-y-full font-mono text-[10px] leading-none text-faint`,style:{top:10},children:g(f)}),(0,i.jsx)(`span`,{className:`pointer-events-none absolute left-1 top-1/2 -translate-y-1/2 font-mono text-[10px] leading-none text-faint`,children:g(f/2)})]})]}),n&&(0,i.jsx)(`div`,{className:`mt-1 flex justify-between px-1 font-mono text-[10px] text-faint`,children:n.map(e=>(0,i.jsx)(`span`,{children:e},e))}),(0,i.jsx)(`p`,{id:c,className:`sr-only`,children:_?`latest ${g(y)}, max ${g(f)}`:`no data yet`})]})}export{a as t};
1
+ import{r as e}from"./cn-CMFYpumL.js";import{g as t,t as n}from"./react-vendor-Bjui4wS4.js";var r=e(t(),1),i=n();function a({series:e,height:t=180,xLabels:n,ariaLabel:a=`throughput chart`,formatValue:o}){let s=(0,r.useId)().replace(/:/g,``),c=`${s}-desc`,l=t,u=e=>Number.isFinite(e)?e:0,d=Math.max(1,...e.map(e=>e.points.length)),f=Math.max(1,...e.flatMap(e=>e.points.map(u))),p=e=>d<=1?0:e/(d-1)*600,m=e=>l-10-u(e)/f*(l-20),h=[0,.25,.5,.75,1].map(e=>10+e*(l-20)),g=o??(e=>Number.isInteger(e)?String(e):e.toFixed(1)),_=e.some(e=>e.points.length>0),v=e.find(e=>e.points.length>0),y=v?u(v.points[v.points.length-1]):0;return(0,i.jsxs)(`div`,{className:`w-full`,children:[(0,i.jsxs)(`div`,{className:`relative`,children:[(0,i.jsxs)(`svg`,{viewBox:`0 0 600 ${l}`,preserveAspectRatio:`none`,className:`block w-full`,style:{height:t},role:`img`,"aria-label":a,"aria-describedby":c,children:[(0,i.jsx)(`defs`,{children:e.map((e,t)=>(0,i.jsxs)(`linearGradient`,{id:`${s}-g${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,i.jsx)(`stop`,{offset:`0%`,stopColor:e.color,stopOpacity:`0.28`}),(0,i.jsx)(`stop`,{offset:`100%`,stopColor:e.color,stopOpacity:`0`})]},e.label))}),h.map(e=>(0,i.jsx)(`line`,{x1:`0`,y1:e,x2:600,y2:e,stroke:`var(--line)`,strokeWidth:`1`},e)),e.map((e,t)=>{if(e.points.length===0)return null;let n=e.points.length===1?`M0,${m(e.points[0])} L600,${m(e.points[0])}`:e.points.map((e,t)=>`${t===0?`M`:`L`}${p(t)},${m(e)}`).join(` `),r=e.points.length===1?`${n} L600,${l} L0,${l} Z`:`${n} L${p(e.points.length-1)},${l} L${p(0)},${l} Z`;return(0,i.jsxs)(`g`,{children:[e.area&&(0,i.jsx)(`path`,{d:r,fill:`url(#${s}-g${t})`}),(0,i.jsx)(`path`,{d:n,fill:`none`,stroke:e.color,strokeWidth:`2`,strokeLinejoin:`round`,vectorEffect:`non-scaling-stroke`})]},e.label)})]}),_&&(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(`span`,{className:`pointer-events-none absolute left-1 -translate-y-full font-mono text-[10px] leading-none text-faint`,style:{top:10},children:g(f)}),(0,i.jsx)(`span`,{className:`pointer-events-none absolute left-1 top-1/2 -translate-y-1/2 font-mono text-[10px] leading-none text-faint`,children:g(f/2)})]})]}),n&&(0,i.jsx)(`div`,{className:`mt-1 flex justify-between px-1 font-mono text-[10px] text-faint`,children:n.map(e=>(0,i.jsx)(`span`,{children:e},e))}),(0,i.jsx)(`p`,{id:c,className:`sr-only`,children:_?`latest ${g(y)}, max ${g(f)}`:`no data yet`})]})}export{a as t};
@@ -0,0 +1 @@
1
+ import{r as e,t}from"./cn-CMFYpumL.js";import{g as n,t as r}from"./react-vendor-Bjui4wS4.js";import{o as i}from"./connectionStore-Cd9-3Fw0.js";import{A as a,C as o,O as s,S as c,U as ee,W as l,c as u,h as d,m as f,r as p,s as m,st as h,w as g}from"./index-Bn2R06qm.js";import{i as _,n as v,o as y,t as b}from"./form-DsUq0w8s.js";import{t as x}from"./AreaChart-REK4ZsTC.js";var S=e(n(),1),C={total:1e6,batch:5e3,producers:64,payload:65536,workers:64,workerBatch:1e3,processMs:6e4,durationS:600},w={queue:`benchmark`,mode:`count`,total:5e3,durationS:30,batch:100,producers:4,payload:128,workers:4,workerBatch:100,processMs:5,durable:!1,removeOnComplete:!0},T=`bq-dashboard-benchmark-`;function E(){if(typeof globalThis.crypto?.randomUUID!=`function`)throw Error(`A cryptographically secure browser is required to create a benchmark queue.`);return`${T}${globalThis.crypto.randomUUID()}`}function D(e){return RegExp(`^${T}[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`,`i`).test(e)}var O={Smoke:{mode:`count`,total:200,batch:50,producers:2,workers:1,workerBatch:50,processMs:0},Standard:{mode:`count`,total:5e3,batch:100,producers:4,workers:4,workerBatch:100,processMs:5},Stress:{mode:`count`,total:5e4,batch:500,producers:16,workers:16,workerBatch:200,processMs:0},Soak:{mode:`duration`,durationS:30,batch:100,producers:4,workers:8,workerBatch:100,processMs:10}},k=(e,t,n)=>Number.isFinite(e)?Math.max(t,Math.min(n,Math.floor(e))):t;function te(e){return e?e.length>256?`Queue name is too long (maximum 256 characters).`:/^[a-zA-Z0-9_\-.:]+$/.test(e)?null:`Queue name contains unsupported characters.`:`Queue name is required.`}var A=(e,t)=>e.length?e[Math.min(e.length-1,Math.max(0,Math.ceil(t/100*e.length)-1))]:0,j=(e,t,n,r,i,a,o)=>Array.from({length:t},(t,s)=>({data:{i:e+s,blob:n},durable:r,removeOnComplete:i,...o===void 0?{}:{stallTimeout:o},...a?{jobId:`${a}-${e+s}`,tags:[`bunqueue-dashboard-benchmark`,a]}:{}})),M=e=>new Promise(t=>setTimeout(t,e)),N=async(e,t)=>{let n=performance.now()+e;for(;t()&&performance.now()<n;)await M(Math.min(100,Math.max(0,n-performance.now())))},P=e=>e instanceof Error?e.message:String(e),F=e=>e>=1e6?`${(e/1e6).toFixed(2)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:`${Math.round(e)}`,I=r();function ne({history:e,onClear:t}){if(!e.length)return null;let n=JSON.stringify(e,null,2);return(0,I.jsxs)(c,{padded:!1,className:`mt-6 overflow-hidden`,children:[(0,I.jsxs)(`div`,{className:`flex items-center justify-between border-b border-line px-5 py-3`,children:[(0,I.jsx)(`h3`,{className:`text-base font-semibold text-fg`,children:`Run history`}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(s,{value:n}),(0,I.jsx)(g,{size:`sm`,variant:`ghost`,onClick:()=>{let e=new Blob([n],{type:`application/json`}),t=URL.createObjectURL(e),r=document.createElement(`a`);r.href=t,r.download=`benchmark-history-${Date.now()}.json`,r.click(),URL.revokeObjectURL(t)},children:`Export JSON`}),(0,I.jsx)(g,{size:`sm`,variant:`ghost`,onClick:t,children:`Clear`})]})]}),(0,I.jsx)(`div`,{className:`overflow-x-auto`,children:(0,I.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,I.jsx)(`thead`,{children:(0,I.jsxs)(`tr`,{className:`border-b border-line text-left text-[11px] uppercase tracking-wider text-faint`,children:[(0,I.jsx)(`th`,{className:`px-5 py-2 font-medium`,children:`Mode`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Prod`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Wkr`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Pushed`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Done`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Push/s`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Done/s`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`p95`}),(0,I.jsx)(`th`,{className:`px-5 py-2 text-right font-medium`,children:`Dur`})]})}),(0,I.jsx)(`tbody`,{children:e.map(e=>(0,I.jsxs)(`tr`,{className:`border-b border-line last:border-0 hover:bg-surface-2/40`,children:[(0,I.jsx)(`td`,{className:`px-5 py-2 capitalize text-muted`,children:e.mode}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-muted`,children:e.producers}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-muted`,children:e.workers}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-fg`,children:u(e.pushed)}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-success`,children:u(e.completed)}),(0,I.jsxs)(`td`,{className:`px-5 py-2 text-right tnum text-accent`,children:[F(e.pushPerSec),`/s`]}),(0,I.jsxs)(`td`,{className:`px-5 py-2 text-right tnum text-success`,children:[F(e.donePerSec),`/s`]}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-muted`,children:m(e.p95)}),(0,I.jsx)(`td`,{className:`px-5 py-2 text-right tnum text-muted`,children:m(e.durationMs)})]},e.id))})]})})]})}var L={pushed:0,completed:0,pushFailed:0,ackFailed:0,bytes:0,elapsedMs:0,pushPerSec:0,donePerSec:0,activeWorkers:0,pushSeries:[],doneSeries:[],etaMs:null,error:null},R=()=>({pushed:0,completed:0,pushFailed:0,ackFailed:0,bytes:0,assigned:0,startedAt:0,pushLat:[],activeWorkers:0,error:null,lastAt:0,lastPushed:0,lastDone:0,pushSeries:[],doneSeries:[]}),z=0,B=[`waiting`,`prioritized`,`delayed`,`active`,`paused`,`waiting-children`,`completed`,`failed`];function V(e){return B.reduce((t,n)=>{let r=e[n];if(!Number.isSafeInteger(r)||r<0)throw Error(`Malformed queue count for "${n}".`);return t+r},0)}function H(e,t){if(!e||typeof e!=`object`||e.ok!==!0)throw Error(`${t} returned a malformed success response.`)}function re(){let[e,t]=(0,S.useState)(`idle`),[n,r]=(0,S.useState)(L),[i,a]=(0,S.useState)(null),[o,s]=(0,S.useState)([]),[c,ee]=(0,S.useState)(null),l=(0,S.useRef)(!1),u=(0,S.useRef)(!0),d=(0,S.useRef)(0),f=(0,S.useRef)(!1),p=(0,S.useRef)(!1),m=(0,S.useRef)(null),g=(0,S.useRef)(`idle`);g.current=e;let _=(0,S.useRef)(R());return(0,S.useEffect)(()=>(u.current=!0,()=>{u.current=!1,l.current=!0,d.current++}),[]),(0,S.useEffect)(()=>{if(e!==`running`&&e!==`draining`)return;let t=setInterval(()=>{let e=_.current,t=performance.now(),n=t-e.startedAt,i=(t-e.lastAt)/1e3,a=i>0?Math.max(0,(e.pushed-e.lastPushed)/i):0,o=i>0?Math.max(0,(e.completed-e.lastDone)/i):0;e.lastAt=t,e.lastPushed=e.pushed,e.lastDone=e.completed,e.pushSeries=[...e.pushSeries,a].slice(-60),e.doneSeries=[...e.doneSeries,o].slice(-60);let s=null,c=m.current;if(c&&c.mode===`count`){let t=k(c.total,1,C.total);if(g.current===`draining`){let r=e.doneSeries.slice(-10),i=r.length?r.reduce((e,t)=>e+t,0)/r.length:0;i<=0&&n>0&&(i=e.completed/(n/1e3)),i>0&&(s=Math.max(0,t-e.completed)/i*1e3)}else a>0&&(s=Math.max(0,t-e.pushed)/a*1e3)}else c&&c.mode===`duration`&&(s=Math.max(0,k(c.durationS,1,C.durationS)*1e3-n));r({pushed:e.pushed,completed:e.completed,pushFailed:e.pushFailed,ackFailed:e.ackFailed,bytes:e.bytes,elapsedMs:n,pushPerSec:a,donePerSec:o,activeWorkers:e.activeWorkers,pushSeries:e.pushSeries,doneSeries:e.doneSeries,etaMs:s,error:e.error})},200);return()=>clearInterval(t)},[e]),{phase:e,live:n,summary:i,history:o,runCfg:c,run:async(e,n)=>{if(f.current||!u.current)return;f.current=!0;let i=++d.current,o=n??h.createServerTargetClient(h.captureServerRequestTarget()),c=()=>u.current&&d.current===i,v=()=>c()&&!l.current;l.current=!1;try{a(null);let n=e.queue.trim(),i=te(n);if(i){r({...L,error:i}),g.current=`error`,t(`error`);return}if(![`count`,`duration`].includes(e.mode)){r({...L,error:`Benchmark mode is invalid.`}),g.current=`error`,t(`error`);return}if(typeof e.durable!=`boolean`||typeof e.removeOnComplete!=`boolean`){r({...L,error:`Benchmark job options are invalid.`}),g.current=`error`,t(`error`);return}let u=k(e.total,1,C.total),d=k(e.durationS,1,C.durationS),f=d*1e3,h=k(e.batch,1,C.batch),y=k(e.producers,1,C.producers),b=k(e.payload,0,C.payload),x=k(e.workers,0,C.workers),S=k(e.workerBatch,1,C.workerBatch),w=k(e.processMs,0,C.processMs),T=Object.freeze({...e,queue:n,total:u,durationS:d,batch:h,producers:y,payload:b,workers:x,workerBatch:S,processMs:w});try{H(await o.overview(),`Dashboard preflight`)}catch(e){if(!c())return;r({...L,error:`Server unreachable — start it on the Server page first. (${P(e)})`}),t(`error`);return}if(!v())return;try{let e=await o.counts(n);if(!v())return;if(H(e,`Queue-count preflight`),!e?.counts||typeof e.counts!=`object`||Array.isArray(e.counts))throw Error(`Malformed queue-count response.`);let i=V(e.counts);if(i>0){r({...L,error:`Dedicated benchmark queue "${n}" is not empty (${i} job(s) across all states). Clean it before running so no external work can be consumed or deleted.`}),t(`error`);return}}catch(e){if(!c())return;r({...L,error:`Could not verify that dedicated queue "${n}" is empty. (${P(e)})`}),t(`error`);return}if(!v())return;p.current=!1,m.current=T,ee(T),_.current=R(),_.current.startedAt=performance.now(),_.current.lastAt=performance.now(),r({...L}),g.current=`running`,t(`running`);let E=`x`.repeat(b),D=performance.now()+f,O=`bqbench-${globalThis.crypto.randomUUID()}`,M=new Set,F=new Set,I=async()=>{for(;v();){let e;if(T.mode===`count`){if(_.current.assigned>=u)break;e=Math.min(h,u-_.current.assigned)}else{if(performance.now()>=D)break;e=h}let t=_.current.assigned;_.current.assigned+=e;let r=j(t,e,E,T.durable,T.removeOnComplete,O,Math.max(12e4,w+6e4)),i=performance.now(),a=o.addJobsBulk(n,r).then(t=>{if(!c())return;if(H(t,`Bulk enqueue`),!Array.isArray(t.ids)||t.ids.length!==e||t.ids.some(e=>typeof e!=`string`||e.length===0)||new Set(t.ids).size!==t.ids.length)throw Error(`Bulk enqueue returned invalid job IDs.`);let n=t.ids;for(let e of n)M.add(e);_.current.pushed+=n.length,_.current.bytes+=n.length*b;let r=Math.max(0,e-n.length);r>0&&(_.current.pushFailed+=r,_.current.error??=`Server created ${n.length} of ${e} jobs in a benchmark batch.`)}).catch(t=>{c()&&(_.current.pushFailed+=e,_.current.error??=P(t))});F.add(a);try{await a}finally{F.delete(a)}c()&&_.current.pushLat.push(performance.now()-i)}},ne=async()=>{for(;v()&&!(T.mode===`duration`&&performance.now()>=D||T.mode===`count`&&_.current.completed>=u);){_.current.activeWorkers++;let e=[];try{try{let t=await o.pullBatch(n,S);if(!v())break;if(t?.ok!==!0||!Array.isArray(t?.jobs)||t.jobs.length>S||t.jobs.some(e=>!e||typeof e!=`object`||typeof e.id!=`string`||e.id.length===0)||new Set(t.jobs.map(e=>e.id)).size!==t.jobs.length)throw Error(`Malformed pull-batch response.`);e=t.jobs}catch(e){if(!c())break;_.current.error??=P(e)}if(!v())break;if(e.length>0){if(e.some(e=>!M.has(e.id))&&F.size>0&&await Promise.allSettled([...F]),!v())break;let t=e.filter(e=>M.has(e.id)),n=e.filter(e=>!M.has(e.id));if(n.length>0){if(!v())break;let e=await Promise.allSettled(n.map(async e=>{H(await o.retryJob(e.id),`Restore job ${e.id}`)}));if(!c())break;let t=e.filter(e=>e.status===`rejected`);_.current.error??=t.length>0?`Detected ${n.length} foreign job(s); ${t.length} could not be returned to waiting. Benchmark stopped.`:`Detected ${n.length} foreign job(s); returned them to waiting and stopped without counting them.`,l.current=!0}if(t.length>0&&v()){if(w>0&&await N(w,v),!v())break;try{let e=await o.heartbeatBatch(t.map(e=>e.id));H(e,`Heartbeat benchmark jobs`);let n=e.data;if(!n||typeof n!=`object`||n.ok!==!0||!Number.isSafeInteger(n.count)||n.count!==t.length)throw Error(`Heartbeat confirmed ${String(n?.count)} of ${t.length} benchmark jobs; refusing a lossy batch ACK.`);if(!v()||(H(await o.ackBatch(t.map(e=>e.id)),`Acknowledge benchmark jobs`),!c()))break;_.current.completed+=t.length;for(let e of t)M.delete(e.id)}catch(e){if(!c())break;_.current.ackFailed+=t.length,_.current.error??=P(e)}}}}finally{c()&&_.current.activeWorkers--}if(!v())break;if(e.length===0){if(T.mode===`count`&&p.current){M.size>0&&(_.current.error??=`${M.size} benchmark job(s) could not be drained.`);break}await N(50,v)}}},B=Array.from({length:y},I),re=Array.from({length:x},ne),ie=Promise.all(B).then(()=>{c()&&(p.current=!0,v()&&T.mode===`count`&&x>0&&g.current===`running`&&(g.current=`draining`,t(`draining`)))});if(await Promise.all([ie,...re]),!c())return;let U=_.current,W=performance.now()-U.startedAt,G=W/1e3||1,K=[...U.pushLat].sort((e,t)=>e-t),q={pushed:U.pushed,completed:U.completed,pushFailed:U.pushFailed,ackFailed:U.ackFailed,bytes:U.bytes,durationMs:W,pushPerSec:U.pushed/G,donePerSec:U.completed/G,mbPerSec:U.bytes/G,avg:K.length?K.reduce((e,t)=>e+t,0)/K.length:0,p50:A(K,50),p95:A(K,95),p99:A(K,99),max:K.length?K[K.length-1]:0,error:U.error};a(q),r(e=>({...e,pushed:U.pushed,completed:U.completed,pushFailed:U.pushFailed,ackFailed:U.ackFailed,bytes:U.bytes,elapsedMs:W,pushPerSec:0,donePerSec:0,activeWorkers:0,etaMs:0,error:U.error})),s(e=>[{...q,id:++z,at:Date.now(),mode:T.mode,producers:y,workers:x},...e].slice(0,12)),g.current=l.current?`stopped`:U.error?`error`:`done`,t(g.current)}finally{f.current=!1}},stop:()=>{l.current=!0,(g.current===`running`||g.current===`draining`)&&(g.current=`stopping`,t(`stopping`))},reset:()=>{l.current=!0,d.current++,g.current=`idle`,a(null),r(L),t(`idle`)},clearHistory:()=>s([])}}var ie=[`count`,`duration`],U=[`waiting`,`completed`,`failed`],W=null;function G(){return W??=E(),W}var K=[`total`,`durationS`,`batch`,`producers`,`payload`,`workers`,`workerBatch`,`processMs`],q=e=>({...e,total:String(e.total),durationS:String(e.durationS),batch:String(e.batch),producers:String(e.producers),payload:String(e.payload),workers:String(e.workers),workerBatch:String(e.workerBatch),processMs:String(e.processMs)}),ae=e=>({...e,total:Number(e.total),durationS:Number(e.durationS),batch:Number(e.batch),producers:Number(e.producers),payload:Number(e.payload),workers:Number(e.workers),workerBatch:Number(e.workerBatch),processMs:Number(e.processMs)});function oe(){let[e]=(0,S.useState)(G),[n,r]=(0,S.useState)(()=>q({...w,queue:e})),s=re(),T=i(e=>e.baseUrl),[E,A]=(0,S.useState)(null),j=(0,S.useRef)(null),M=(0,S.useRef)(!0);(0,S.useEffect)(()=>(M.current=!0,()=>{M.current=!1,j.current=null}),[]);let{phase:N,live:P,summary:L,history:R}=s,z=N===`running`||N===`draining`||N===`stopping`,B=(e,t)=>r(n=>({...n,[e]:t})),W=e=>t=>B(e,t.target.value),oe=e=>r(t=>{let n={...t};for(let[t,r]of Object.entries(e))n[t]=K.includes(t)?String(r):r;return n}),[J,le]=(0,S.useState)(e);(0,S.useEffect)(()=>{let e=setTimeout(()=>le(n.queue.trim()||w.queue),400);return()=>clearTimeout(e)},[n.queue]);let ue=E?.target.baseUrl??T,{data:de,error:fe}=a(()=>E?E.client.counts(J):h.counts(J),[J,E],{intervalMs:1e3}),Y=de?.counts??null,[X,pe]=(0,S.useState)(!1),[Z,Q]=(0,S.useState)(null),me=async()=>{let t=n.queue.trim();if(j.current||!t)return;if(!D(t)||t!==e){Q({error:`refusing to clean a queue not owned by this dashboard session`});return}j.current=`clean`;let r=E;if(!r){let e=h.captureServerRequestTarget();r={target:e,client:h.createServerTargetClient(e)}}let i=Y&&J===t?` Currently ${u(Y.waiting??0)} waiting / ${u(Y.completed??0)} completed.`:``;if(!window.confirm(`Clean every cleanable job from the dedicated dashboard benchmark queue "${t}" on ${r.target.baseUrl}? This is queue-wide; the cryptographic queue name is owned by this browser session.${i}`)){j.current=null;return}pe(!0),Q(null);try{let e=null;for(let n of U){if(!M.current)return;try{let e=await r.client.clean(t,{state:n,limit:C.total});if(H(e,`Clean ${n} jobs`),!Number.isSafeInteger(e.count)||e.count<0)throw Error(`Clean ${n} jobs returned an invalid count.`)}catch(t){e=t.message}}if(!M.current)return;let n=await r.client.counts(t).catch(t=>(e=t.message,null));if(!M.current)return;if(n==null)Q({error:e??`server unreachable — could not verify`});else if(n.ok!==!0||!n.counts||typeof n.counts!=`object`||Array.isArray(n.counts))Q({error:`server returned a malformed queue-count response`});else{let t=n.counts,r;try{r=V(t)}catch{Q({error:`server returned malformed queue counts`});return}Q(e||r>0?{error:e??`${u(r)} job(s) still present`}:{remaining:0})}}finally{M.current&&pe(!1),j.current===`clean`&&(j.current=null)}},$=s.runCfg??ae(n),he=k($.total,1,C.total),ge=k($.workers,0,C.workers),_e=$.mode===`count`&&(z||L)?Math.min(100,P.pushed/he*100):0,ve=$.mode===`count`&&(z||L)?Math.min(100,P.completed/he*100):0,ye=$.mode===`duration`?Math.min(100,P.elapsedMs/(k($.durationS,1,C.durationS)*1e3)*100):0,be=N===`running`?$.mode===`duration`?`Running…`:`Producing…`:N===`draining`?`Draining…`:N===`stopping`?`Stopping…`:N===`error`?`Error`:L?`Result`:`Ready`,xe=(N===`running`||N===`draining`)&&P.etaMs!=null?P.etaMs>0?`ETA ${m(P.etaMs)}`:`finishing…`:N===`stopped`?`stopped early`:N===`done`?`complete`:``;return(0,I.jsxs)(`div`,{children:[(0,I.jsx)(d,{title:`Benchmark`,description:`Drive real load against the server — producers bulk-enqueue jobs while simulated workers pull, process and ack them. Throughput is measured client-side; the queue genuinely fills and drains.`,actions:N===`stopping`?(0,I.jsxs)(g,{variant:`warning`,size:`sm`,disabled:!0,children:[(0,I.jsx)(ee,{className:`size-3.5`}),` Stopping…`]}):z?(0,I.jsxs)(g,{variant:`warning`,size:`sm`,onClick:s.stop,children:[(0,I.jsx)(ee,{className:`size-3.5`}),` Stop`]}):(0,I.jsxs)(g,{variant:`success`,size:`sm`,disabled:X,onClick:()=>{if(j.current)return;j.current=`run`;let e=ae(n),t=e.queue.trim(),r=h.captureServerRequestTarget(),i=h.createServerTargetClient(r);if(te(t)){s.run({...e,queue:t},i).finally(()=>{j.current===`run`&&(j.current=null)});return}let a=0;if(!E&&Y&&J===t)try{a=V(Y)}catch{}let o=a>0?` Warning: it already holds ${u(a)} job(s) across all states; the safety preflight will refuse the run until the dedicated queue is empty.`:``;if(!window.confirm(`Enqueue real jobs into "${t}" on ${r.baseUrl}?${o}`)){j.current=null;return}A({target:r,client:i}),s.run(e,i).finally(()=>{j.current===`run`&&(j.current=null)})},children:[(0,I.jsx)(l,{className:`size-3.5`}),` Run benchmark`]})}),P.error&&(0,I.jsx)(`div`,{className:`mb-4 rounded-lg border border-red-500/20 bg-red-500/5 px-4 py-2 text-sm text-danger`,children:P.error}),(0,I.jsxs)(`div`,{className:`mb-4 flex flex-wrap items-center gap-2`,children:[(0,I.jsx)(`span`,{className:`text-xs font-medium uppercase tracking-wider text-faint`,children:`Presets`}),Object.keys(O).map(e=>(0,I.jsx)(`button`,{type:`button`,disabled:z,onClick:()=>oe(O[e]),className:`rounded-md border border-line bg-surface-2 px-2.5 py-1 text-xs text-muted transition-colors hover:border-line-strong hover:text-fg disabled:opacity-40`,children:e},e))]}),(0,I.jsxs)(`div`,{className:`grid grid-cols-1 gap-6 lg:grid-cols-3`,children:[(0,I.jsxs)(c,{className:`lg:col-span-1`,children:[(0,I.jsx)(o,{title:`Configuration`}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsx)(b,{label:`Dedicated queue`,hint:`Cryptographically generated for this browser tab; production queue names cannot be entered here.`,children:(0,I.jsx)(v,{name:`benchmark-queue`,autoComplete:`off`,value:n.queue,readOnly:!0,"aria-readonly":`true`})}),(0,I.jsx)(b,{label:`Mode`,hint:n.mode===`count`?`Push a fixed number of jobs.`:`Run producers + workers for a fixed time.`,children:(0,I.jsx)(_,{options:ie,value:n.mode,onChange:e=>B(`mode`,e),disabled:z})}),n.mode===`count`?(0,I.jsx)(b,{label:`Total jobs`,hint:`max ${u(C.total)}`,children:(0,I.jsx)(v,{name:`benchmark-total`,autoComplete:`off`,type:`number`,min:1,max:C.total,value:n.total,disabled:z,onChange:W(`total`)})}):(0,I.jsx)(b,{label:`Duration (s)`,hint:`max ${C.durationS}s`,children:(0,I.jsx)(v,{name:`benchmark-duration-seconds`,autoComplete:`off`,type:`number`,min:1,max:C.durationS,value:n.durationS,disabled:z,onChange:W(`durationS`)})}),(0,I.jsx)(`div`,{className:`mt-1 text-[11px] font-semibold uppercase tracking-wider text-faint`,children:`Producers`}),(0,I.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,I.jsx)(b,{label:`Producers`,hint:`parallel, max ${C.producers}`,children:(0,I.jsx)(v,{name:`benchmark-producers`,autoComplete:`off`,type:`number`,min:1,max:C.producers,value:n.producers,disabled:z,onChange:W(`producers`)})}),(0,I.jsx)(b,{label:`Push batch`,hint:`jobs/req, max ${C.batch}`,children:(0,I.jsx)(v,{name:`benchmark-push-batch`,autoComplete:`off`,type:`number`,min:1,max:C.batch,value:n.batch,disabled:z,onChange:W(`batch`)})}),(0,I.jsx)(b,{label:`Payload`,hint:`bytes/job, max ${u(C.payload)}`,children:(0,I.jsx)(v,{name:`benchmark-payload-bytes`,autoComplete:`off`,type:`number`,min:0,max:C.payload,value:n.payload,disabled:z,onChange:W(`payload`)})})]}),(0,I.jsx)(`div`,{className:`mt-1 text-[11px] font-semibold uppercase tracking-wider text-faint`,children:`Workers (simulated)`}),(0,I.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,I.jsx)(b,{label:`Workers`,hint:`0 = produce only, max ${C.workers}`,children:(0,I.jsx)(v,{name:`benchmark-workers`,autoComplete:`off`,type:`number`,min:0,max:C.workers,value:n.workers,disabled:z,onChange:W(`workers`)})}),(0,I.jsx)(b,{label:`Pull batch`,hint:`jobs/pull, max ${C.workerBatch}`,children:(0,I.jsx)(v,{name:`benchmark-pull-batch`,autoComplete:`off`,type:`number`,min:1,max:C.workerBatch,value:n.workerBatch,disabled:z,onChange:W(`workerBatch`)})}),(0,I.jsx)(b,{label:`Process (ms)`,hint:`simulated work per pull`,children:(0,I.jsx)(v,{name:`benchmark-process-ms`,autoComplete:`off`,type:`number`,min:0,max:C.processMs,value:n.processMs,disabled:z,onChange:W(`processMs`)})})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(y,{checked:n.durable,onChange:e=>B(`durable`,e),disabled:z,label:`Durable (fsync each job)`}),(0,I.jsx)(`span`,{className:`text-sm text-muted`,children:`Durable (fsync each job)`})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(y,{checked:n.removeOnComplete,onChange:e=>B(`removeOnComplete`,e),disabled:z,label:`Remove on complete`}),(0,I.jsx)(`span`,{className:`text-sm text-muted`,children:`Remove on complete`})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-3 pt-1`,children:[(0,I.jsx)(g,{variant:`ghost`,size:`sm`,disabled:z||X,onClick:me,children:X?`Cleaning…`:`Clean queue`}),Z&&(`error`in Z?(0,I.jsxs)(`span`,{className:`text-xs text-danger`,children:[`Clean unverified — `,Z.error]}):(0,I.jsx)(`span`,{className:t(`text-xs`,Z.remaining>0?`text-warning`:`text-success`),children:Z.remaining>0?`Cleaned — ${u(Z.remaining)} active job(s) remain (requeued after the stall timeout)`:`Cleaned — 0 jobs remain`}))]})]})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-6 lg:col-span-2`,children:[(0,I.jsxs)(c,{children:[(0,I.jsxs)(`div`,{className:`mb-3 flex items-center justify-between`,children:[(0,I.jsx)(`h3`,{className:`text-base font-semibold text-fg`,children:be}),(0,I.jsxs)(`span`,{className:`text-right text-xs text-faint`,children:[(0,I.jsxs)(`span`,{className:`block`,children:[`Benchmark target: `,ue]}),xe&&(0,I.jsx)(`span`,{className:`block`,children:xe})]})]}),(0,I.jsx)(se,{label:$.mode===`duration`?`Elapsed`:`Produced`,pct:$.mode===`duration`?ye:_e,tone:`accent`}),ge>0&&$.mode===`count`&&(0,I.jsx)(se,{label:`Completed`,pct:ve,tone:`emerald`}),(0,I.jsxs)(`div`,{className:`mt-4 grid grid-cols-2 gap-4 md:grid-cols-4`,children:[(0,I.jsx)(f,{label:`Pushed`,value:u(P.pushed),tone:`accent`,compact:!0}),(0,I.jsx)(f,{label:`Completed`,value:u(P.completed),tone:`green`,compact:!0}),(0,I.jsx)(f,{label:`Push/sec`,value:F(P.pushPerSec),compact:!0}),(0,I.jsx)(f,{label:`Done/sec`,value:F(P.donePerSec),tone:`green`,compact:!0}),(0,I.jsx)(f,{label:`Elapsed`,value:m(P.elapsedMs),compact:!0}),(0,I.jsx)(f,{label:`Active workers`,value:`${P.activeWorkers}/${ge}`,tone:`blue`,compact:!0}),(0,I.jsx)(f,{label:`Data`,value:p(L?.bytes??P.bytes),compact:!0}),(0,I.jsx)(f,{label:`Errors`,value:u((L?.pushFailed??P.pushFailed)+(L?.ackFailed??P.ackFailed)),tone:P.pushFailed+P.ackFailed?`red`:`default`,compact:!0})]})]}),(0,I.jsxs)(c,{children:[(0,I.jsx)(o,{title:`Throughput`}),(0,I.jsx)(`p`,{className:`-mt-3 mb-4 text-xs text-faint`,children:`Enqueue (client → server) vs completion (workers) per second`}),(0,I.jsx)(x,{series:[{label:`Push/sec`,color:`#38bdf8`,points:P.pushSeries,area:!0},{label:`Done/sec`,color:`#34d399`,points:P.doneSeries,area:!0}]}),(0,I.jsxs)(`div`,{className:`mt-2 flex items-center gap-4 font-mono text-[11px] text-faint`,children:[(0,I.jsx)(ce,{color:`#38bdf8`,label:`Push/sec`,value:P.pushPerSec}),(0,I.jsx)(ce,{color:`#34d399`,label:`Done/sec`,value:P.donePerSec})]})]})]})]}),L&&(0,I.jsxs)(c,{className:`mt-6`,children:[(0,I.jsx)(o,{title:`Summary`}),(0,I.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 md:grid-cols-4 xl:grid-cols-8`,children:[(0,I.jsx)(f,{label:`Pushed`,value:u(L.pushed),tone:`accent`,compact:!0}),(0,I.jsx)(f,{label:`Completed`,value:u(L.completed),tone:`green`,compact:!0}),(0,I.jsx)(f,{label:`Duration`,value:m(L.durationMs),compact:!0}),(0,I.jsx)(f,{label:`Avg push/s`,value:F(L.pushPerSec),tone:`accent`,compact:!0}),(0,I.jsx)(f,{label:`Avg done/s`,value:F(L.donePerSec),tone:`green`,compact:!0}),(0,I.jsx)(f,{label:`Data rate`,value:`${p(L.mbPerSec)}/s`,compact:!0}),(0,I.jsx)(f,{label:`Push p95`,value:m(L.p95),compact:!0}),(0,I.jsx)(f,{label:`Push p99`,value:m(L.p99),compact:!0})]}),(0,I.jsxs)(`p`,{className:`mt-3 text-xs text-faint`,children:[`Push-batch latency avg `,m(L.avg),` · p50 `,m(L.p50),` · p95`,` `,m(L.p95),` · p99 `,m(L.p99),` · max `,m(L.max),`.`,L.error?` First error: ${L.error}`:``]})]}),(0,I.jsxs)(c,{className:`mt-6`,children:[(0,I.jsx)(o,{title:`Server queue: ${J}`,action:fe?(0,I.jsx)(`span`,{className:`text-xs font-medium text-warning`,children:`stale — server unreachable`}):void 0}),(0,I.jsxs)(`p`,{className:`-mt-3 mb-4 text-xs text-faint`,children:[`Live counts from `,ue,` (poll 1s).`,E?` Pinned to the current or last benchmark run.`:``]}),Y?(0,I.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 md:grid-cols-5`,children:[(0,I.jsx)(f,{label:`Waiting`,value:u(Y.waiting??0),tone:`amber`,compact:!0}),(0,I.jsx)(f,{label:`Active`,value:u(Y.active??0),tone:`blue`,compact:!0}),(0,I.jsx)(f,{label:`Completed`,value:u(Y.completed??0),tone:`green`,compact:!0}),(0,I.jsx)(f,{label:`Failed`,value:u(Y.failed??0),tone:Y.failed?`red`:`default`,compact:!0}),(0,I.jsx)(f,{label:`Delayed`,value:u(Y.delayed??0),compact:!0})]}):(0,I.jsx)(`p`,{className:`text-sm text-faint`,children:`No counts yet — waiting for the server to answer for this queue.`})]}),(0,I.jsx)(ne,{history:R,onClear:s.clearHistory})]})}function se({label:e,pct:n,tone:r}){return(0,I.jsxs)(`div`,{className:`mb-2`,children:[(0,I.jsxs)(`div`,{className:`mb-1 flex items-center justify-between text-[11px] text-faint`,children:[(0,I.jsx)(`span`,{children:e}),(0,I.jsxs)(`span`,{className:`tnum`,children:[n.toFixed(0),`%`]})]}),(0,I.jsx)(`div`,{className:`h-1.5 overflow-hidden rounded-full bg-surface-2`,role:`progressbar`,"aria-label":e,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(n),children:(0,I.jsx)(`div`,{className:t(`h-full rounded-full transition-[width] motion-reduce:transition-none`,r===`accent`?`bg-accent`:`bg-emerald-500`),style:{width:`${n}%`}})})]})}function ce({color:e,label:t,value:n}){return(0,I.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,I.jsx)(`span`,{className:`size-2 rounded-full`,style:{background:e}}),t,` `,(0,I.jsxs)(`span`,{className:`text-fg`,children:[F(n),`/s`]})]})}export{oe as Benchmark};
@@ -0,0 +1,5 @@
1
+ import{r as e}from"./cn-CMFYpumL.js";import{g as t,t as n}from"./react-vendor-Bjui4wS4.js";import{i as r}from"./upstreamPaths-nG8N1XAz.js";import{A as i,C as a,S as o,ct as s,ft as c,h as l,st as u,w as d}from"./index-Bn2R06qm.js";import{i as f,n as p,t as m}from"./form-DsUq0w8s.js";import{r as h}from"./useServerActionGuard-CItj3hvh.js";import{MAX_JOB_DATA_BYTES as g,acceptedBulkIds as _,parseRepeat as v,queueNameError as y,utf8ByteLength as b}from"./AddJob-ytpBLTCJ.js";var x=e(t(),1),S=n(),C=1e4,w=365*24*60*60*1e3,T=1440*60*1e3,E=64*1024*1024,D=64*1024*1024,O=`[
2
+ { "data": { "to": "a@example.com", "template": "welcome" }, "priority": 1 },
3
+ { "data": { "to": "b@example.com", "template": "welcome" } }
4
+ ]`,k=e=>{let t=typeof e==`string`&&e.trim()!==``?Number(e.trim()):e;return typeof t==`number`&&Number.isFinite(t)?t:void 0},A=e=>typeof e==`boolean`?e:void 0,j=e=>typeof e==`string`?e.trim()===``?void 0:e.trim():typeof e==`number`&&Number.isFinite(e)?String(e):void 0,M=e=>{if(!Array.isArray(e))return;let t=e.map(j);return t.every(e=>e!==void 0)?t:void 0},N=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:void 0,P=e=>{let t=k(e);if(t!==void 0)return t;let n=N(e);if(!n||n.type!==`fixed`&&n.type!==`exponential`||Object.keys(n).some(e=>e!==`type`&&e!==`delay`))return;let r=k(n.delay);return r===void 0?void 0:{type:n.type,delay:r}},F=e=>{let t=N(e);if(!t)return;let n=v(JSON.stringify(t));return n.ok?n.repeat:void 0};function I(e){let t=N(e);if(!t)return{ok:!1,msg:`must be an object`};let n=new Set([`ttl`,`extend`,`replace`]),r=Object.keys(t).filter(e=>!n.has(e));if(r.length)return{ok:!1,msg:`has unknown option(s): ${r.join(`, `)}`};if(t.ttl!==void 0&&(!Number.isSafeInteger(t.ttl)||t.ttl<=0||t.ttl>w))return{ok:!1,msg:`ttl must be a whole number from 1 to ${w} ms`};for(let e of[`extend`,`replace`])if(t[e]!==void 0&&typeof t[e]!=`boolean`)return{ok:!1,msg:`${e} must be a boolean`};return t.extend===!0&&t.replace===!0?{ok:!1,msg:`extend and replace are mutually exclusive`}:t.extend===!0&&t.ttl===void 0?{ok:!1,msg:`extend requires ttl`}:{ok:!0,dedup:{...typeof t.ttl==`number`?{ttl:t.ttl}:{},...typeof t.extend==`boolean`?{extend:t.extend}:{},...typeof t.replace==`boolean`?{replace:t.replace}:{}}}}var L=e=>{let t=I(e);return t.ok?t.dedup:void 0};function R(e,t,n){if(n===`spec`&&e&&typeof e==`object`&&!Array.isArray(e)&&`data`in e){let n=e;return{data:n.data,priority:k(n.priority)??t.priority,delay:k(n.delay),maxAttempts:k(n.maxAttempts)??t.maxAttempts,backoff:P(n.backoff)??t.backoff,timeout:k(n.timeout)??t.timeout,jobId:j(n.jobId)??j(n.customId),removeOnComplete:A(n.removeOnComplete),removeOnFail:A(n.removeOnFail),durable:A(n.durable),lifo:A(n.lifo),ttl:k(n.ttl),uniqueKey:j(n.uniqueKey),tags:M(n.tags),groupId:j(n.groupId),dependsOn:M(n.dependsOn),stallTimeout:k(n.stallTimeout),repeat:F(n.repeat),dedup:L(n.dedup),stackTraceLimit:k(n.stackTraceLimit),timestamp:k(n.timestamp)}}return{data:e,...t}}var z=new Set([`data`,`priority`,`delay`,`maxAttempts`,`backoff`,`timeout`,`jobId`,`customId`,`removeOnComplete`,`removeOnFail`,`durable`,`lifo`,`ttl`,`uniqueKey`,`tags`,`groupId`,`dependsOn`,`stallTimeout`,`repeat`,`dedup`,`stackTraceLimit`,`timestamp`]),B=(e,t,n,r,i)=>{if(e===void 0)return null;let a=k(e);return a===void 0?`${t} must be a number`:i&&!Number.isSafeInteger(a)?`${t} must be a whole, safe integer`:a<n||a>r?`${t} must be between ${n} and ${r}`:null};function V(e){let t={priority:e.priority.trim()||void 0,maxAttempts:e.maxAttempts.trim()||void 0,backoff:e.backoff.trim()||void 0,timeout:e.timeout.trim()||void 0},n=[[`priority`,`Default priority`,-1e6,1e6,!0],[`maxAttempts`,`Default max attempts`,1,1e3,!0],[`backoff`,`Default backoff`,0,T,!0],[`timeout`,`Default timeout`,0,T,!0]],r={};for(let[e,i,a,o,s]of n){let n=B(t[e],i,a,o,s);if(n)return{ok:!1,msg:n};let c=k(t[e]);c!==void 0&&(r[e]=c)}return{ok:!0,defaults:r}}function H(e){let t=Object.keys(e).filter(e=>!z.has(e));if(t.length)return`unknown job option(s): ${t.join(`, `)}`;let n=[[`priority`,`priority`,-1e6,1e6,!0],[`delay`,`delay`,0,w,!0],[`maxAttempts`,`maxAttempts`,1,1e3,!0],[`timeout`,`timeout`,0,T,!0],[`ttl`,`ttl`,0,w,!0],[`stallTimeout`,`stallTimeout`,0,T,!0],[`stackTraceLimit`,`stackTraceLimit`,0,1e4,!0],[`timestamp`,`timestamp`,0,2**53-1,!0]];for(let[t,r,i,a,o]of n){let n=B(e[t],r,i,a,o);if(n)return n}if(e.backoff!==void 0){let t=P(e.backoff);if(t===void 0)return`backoff must be a number or {"type":"fixed|exponential","delay":number} with no extra keys`;let n=B(typeof t==`number`?t:t.delay,`backoff delay`,0,T,!0);if(n)return n}if(e.repeat!==void 0){let t=N(e.repeat);if(!t)return`repeat must be an object`;let n=v(JSON.stringify(t));if(!n.ok)return n.msg}if(e.dedup!==void 0){let t=I(e.dedup);if(!t.ok)return`dedup ${t.msg}`;if(j(e.uniqueKey)===void 0)return`dedup requires a non-empty uniqueKey`}for(let t of[`removeOnComplete`,`removeOnFail`,`durable`,`lifo`])if(e[t]!==void 0&&typeof e[t]!=`boolean`)return`${t} must be a boolean`;for(let t of[`jobId`,`customId`,`uniqueKey`]){let n=e[t];if(n===void 0)continue;let i=j(n);if(i===void 0||i.length>1024)return`${t} must be a non-empty string (or finite numeric id) of at most 1024 characters`;if((t===`jobId`||t===`customId`)&&r(i))return`${t}: ${r(i)}`}let i=j(e.jobId),a=j(e.customId);if(i!==void 0&&a!==void 0&&i!==a)return`jobId and customId disagree; provide only one spelling`;if(e.groupId!==void 0){let t=j(e.groupId);if(t===void 0||t.length>256)return`groupId must be a non-empty string of at most 256 characters`}for(let t of[`tags`,`dependsOn`]){if(e[t]===void 0)continue;let n=M(e[t]),i=t===`tags`?256:1024;if(!n||n.some(e=>e.length>i))return`${t} must be an array of non-empty strings of at most ${i} characters`;if(t===`dependsOn`){let e=n?.find(e=>r(e));if(e)return`dependsOn ID "${e}": ${r(e)}`}}return null}function U(e){let t=new Map;for(let n of e)if(n.jobId){if(t.has(n.jobId))return`duplicate jobId/customId "${n.jobId}" makes dependency resolution ambiguous`;t.set(n.jobId,n)}let n=new Set,r=new Set,i=e=>{if(n.has(e))return!0;if(r.has(e))return!1;n.add(e);for(let n of t.get(e)?.dependsOn??[])if(t.has(n)&&i(n))return!0;return n.delete(e),r.add(e),!1};for(let e of t.keys())if(i(e))return`dependency cycle detected in this batch (involving "${e}")`;return null}function W(e,t,n){if(e.length>C)return{ok:!1,msg:`Too many jobs (${e.length}). Limit is ${C}.`};let r=[],i=0;for(let a=0;a<e.length;a++){let o=e[a];if(n===`spec`&&typeof o==`object`&&o&&!Array.isArray(o)&&`data`in o){let e=H(o);if(e)return{ok:!1,msg:`Job ${a+1}: ${e}`}}let s=R(o,t,n),c;try{c=JSON.stringify(s.data)}catch{return{ok:!1,msg:`Job ${a+1}: data must be JSON serializable`}}if(c===void 0)return{ok:!1,msg:`Job ${a+1}: data must be JSON serializable`};if(c.length>10485760)return{ok:!1,msg:`Job ${a+1}: data exceeds the 10 MiB UTF-8 limit`};let l=b(c,g);if(l>10485760)return{ok:!1,msg:`Job ${a+1}: data exceeds the 10 MiB UTF-8 limit`};if(i+=l,i>67108864)return{ok:!1,msg:`Combined job data exceeds the 64 MiB import safety limit`};r.push(s)}let a=U(r);return a?{ok:!1,msg:a}:{ok:!0,bodies:r}}function G(e){return e.length>67108864||b(e,67108864)>67108864?`Import text exceeds the 64 MiB UTF-8 safety limit`:null}function K(e,t=D){return s(e,t)}function q(e,t,n){return{ok:!0,msg:`Accepted ${t} job submission${t===1?``:`s`} in ${n}; server returned ${e} distinct job ID${e===1?``:`s`} (deduplication may reuse existing jobs)`}}function J(e){let t=G(e);if(t)return{items:[],error:t};let n=e.trim();if(!n)return{items:[],error:null};try{let e=JSON.parse(n);return Array.isArray(e)?{items:e,error:null}:{items:[e],error:null}}catch{}let r=[],i=e.split(`
5
+ `);for(let e=0;e<i.length;e++){let t=i[e].trim();if(t)try{r.push(JSON.parse(t))}catch(t){return{items:[],error:`Line ${e+1}: ${t.message}`}}}return{items:r,error:null}}function Y(){let{data:e,error:t,refetch:n}=i(()=>u.queues(),[],{intervalMs:3e4}),[r,s]=(0,x.useState)(``),[g,v]=(0,x.useState)(``),[b,w]=(0,x.useState)(`spec`),[D,k]=(0,x.useState)(``),[A,j]=(0,x.useState)(``),[M,N]=(0,x.useState)(``),[P,F]=(0,x.useState)(``),[I,L]=(0,x.useState)(!1),[R,z]=(0,x.useState)(null),B=(0,x.useRef)(null),H=(0,x.useRef)(0),U=h(`bulk-add-jobs`);(0,x.useEffect)(()=>{L(!1),z(null)},[U.scopeKey]),(0,x.useEffect)(()=>()=>{H.current+=1;let e=B.current;B.current=null;try{e?.abort()}catch{}},[]);let{items:Y,error:X}=(0,x.useMemo)(()=>J(g),[g]),Z=(0,x.useMemo)(()=>{if(X)return{ok:!1,msg:X};if(Y.length>C)return{ok:!1,msg:`Too many jobs (${Y.length}). Limit is ${C}.`};let e=V({priority:D,maxAttempts:A,backoff:M,timeout:P});return e.ok?W(Y,e.defaults,b):e},[M,X,Y,A,b,D,P]);return(0,S.jsxs)(`div`,{children:[(0,S.jsx)(l,{title:`Bulk Add Jobs`,description:`Import many distinct jobs at once from a JSON array, NDJSON, or a file.`}),(0,S.jsxs)(`div`,{className:`grid grid-cols-1 gap-6 lg:grid-cols-3`,children:[(0,S.jsxs)(o,{className:`lg:col-span-2`,children:[(0,S.jsx)(a,{title:`Jobs`,action:(0,S.jsxs)(`label`,{className:`cursor-pointer rounded-lg border border-line px-3 py-1.5 text-xs text-muted hover:bg-surface-2 hover:text-fg`,children:[`Upload file`,(0,S.jsx)(`input`,{type:`file`,name:`jobs-file`,accept:`.json,.ndjson,.txt,application/json`,onChange:e=>{let t=e.currentTarget,n=t.files?.[0];if(!n)return;let r=H.current+1;H.current=r;let i=B.current;B.current=null;try{i?.abort()}catch{}if(t.value=``,!Number.isSafeInteger(n.size)||n.size<0||n.size>67108864){z({ok:!1,msg:`File is too large; maximum is 64 MiB (${n.name})`});return}if(g.trim()!==``&&!window.confirm(`Replace the current input with "${n.name}"?`))return;let a=new FileReader,o=()=>H.current===r&&B.current===a,s=()=>{o()&&(B.current=null)};a.onload=()=>{if(!o())return;if(typeof a.result!=`string`){z({ok:!1,msg:`Could not decode file as text (${n.name})`}),s();return}let e=a.result,t=G(e);t?z({ok:!1,msg:`${t} (${n.name})`}):(v(e),z(null)),s()},a.onerror=()=>{o()&&(z({ok:!1,msg:`Could not read file (${n.name})`}),s())},a.onabort=s,B.current=a,z(null);try{a.readAsText(n)}catch{if(!o())return;z({ok:!1,msg:`Could not read file (${n.name})`}),s()}},className:`hidden`})]})}),(0,S.jsx)(`textarea`,{name:`jobs-json`,value:g,onChange:e=>{H.current+=1;let t=B.current;B.current=null;try{t?.abort()}catch{}v(e.target.value)},maxLength:E,spellCheck:!1,rows:16,placeholder:O,"aria-label":`Jobs JSON`,className:`w-full rounded-lg border border-line bg-surface-2 p-3 font-mono text-xs text-fg placeholder:text-faint focus:border-accent/60 focus:outline-none focus:ring-2 focus:ring-accent/30`}),(0,S.jsxs)(`fieldset`,{className:`mt-3 flex flex-wrap items-center gap-3`,children:[(0,S.jsx)(`legend`,{className:`sr-only`,children:`Import interpretation`}),(0,S.jsx)(`span`,{"aria-hidden":`true`,className:`text-xs font-medium text-faint`,children:`Interpret each item as`}),(0,S.jsx)(f,{options:[`spec`,`raw`],value:b,onChange:w}),(0,S.jsx)(`span`,{className:`text-xs text-faint`,children:b===`spec`?`job spec: an object with a "data" key sets options from its sibling fields.`:`raw data: the whole item becomes the job payload, untouched.`})]}),(0,S.jsx)(`p`,{className:`mt-2 text-xs text-faint`,children:`Accepts a JSON array, a single object, or newline-delimited JSON.`}),(0,S.jsx)(`div`,{className:`mt-2 text-sm`,children:X?(0,S.jsx)(`span`,{role:`alert`,className:`text-danger`,children:X}):Y.length>C?(0,S.jsxs)(`span`,{role:`alert`,className:`text-danger`,children:[`Too many jobs (`,Y.length,`). Limit is `,C,`.`]}):Y.length>0?(0,S.jsxs)(`span`,{className:`text-success`,children:[Y.length,` job(s) parsed ✓`]}):(0,S.jsx)(`span`,{className:`text-faint`,children:`Nothing parsed yet.`})}),!X&&Y.length>0&&!Z.ok&&(0,S.jsxs)(`p`,{role:`alert`,className:`mt-2 text-xs text-danger`,children:[`Import blocked — `,Z.msg,`. Fix the spec or switch to “raw” when the whole object is job data.`]})]}),(0,S.jsxs)(o,{children:[(0,S.jsx)(a,{title:`Target & defaults`}),(0,S.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,S.jsxs)(m,{label:`Queue`,children:[(0,S.jsx)(p,{list:`bulk-queue-options`,"aria-label":`Queue`,name:`bulk-target-queue`,autoComplete:`off`,value:r,onChange:e=>s(e.target.value),placeholder:`queue name (existing or new)`}),(0,S.jsx)(`datalist`,{id:`bulk-queue-options`,children:(e?.queues??[]).map(e=>(0,S.jsx)(`option`,{value:e.name},e.name))})]}),t&&(0,S.jsxs)(`p`,{role:`status`,className:`-mt-2 text-xs text-warning`,children:[`Existing queue suggestions unavailable — `,t.message,`. You can still enter a queue name manually.`,` `,(0,S.jsx)(`button`,{type:`button`,onClick:()=>void n(),className:`font-medium underline underline-offset-2 hover:text-fg`,children:`Retry`})]}),(0,S.jsx)(`p`,{className:`-mt-2 text-xs text-faint`,children:`Defaults below fill any field an item omits.`}),(0,S.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,S.jsx)(m,{label:`Priority`,children:(0,S.jsx)(p,{type:`number`,min:-1e6,max:1e6,step:1,name:`default-priority`,value:D,onChange:e=>k(e.target.value),placeholder:`0`})}),(0,S.jsx)(m,{label:`Max attempts`,children:(0,S.jsx)(p,{type:`number`,min:1,max:1e3,step:1,name:`default-max-attempts`,value:A,onChange:e=>j(e.target.value),placeholder:`3`})}),(0,S.jsx)(m,{label:`Backoff (ms)`,children:(0,S.jsx)(p,{type:`number`,min:0,max:T,step:1,name:`default-backoff`,value:M,onChange:e=>N(e.target.value),placeholder:`1000`})}),(0,S.jsx)(m,{label:`Timeout (ms)`,children:(0,S.jsx)(p,{type:`number`,min:0,max:T,step:1,name:`default-timeout`,value:P,onChange:e=>F(e.target.value),placeholder:`—`})})]}),(0,S.jsx)(`div`,{className:`flex items-center gap-3`,children:(0,S.jsx)(d,{variant:`accent`,disabled:I||Y.length===0||Y.length>C||X!=null||!Z.ok,onClick:async()=>{z(null);let e=r.trim(),t=y(e);if(t){z({ok:!1,msg:t});return}let n=G(g);if(n){z({ok:!1,msg:n});return}if(X){z({ok:!1,msg:X});return}if(Y.length===0){z({ok:!1,msg:`Nothing to enqueue — paste a JSON array or NDJSON.`});return}if(Y.length>C){z({ok:!1,msg:`Too many jobs (${Y.length}). Limit is ${C}.`});return}if(!Z.ok){z({ok:!1,msg:Z.msg});return}let i=Z.bodies,a=K(i);if(a){z({ok:!1,msg:a});return}let o=U.begin();if(o){L(!0);try{let t=_(await u.addJobsBulk(e,i),i.length);if(!o.isCurrent())return;let n=q(new Set(t).size,i.length,e);z(n),c.success(n.msg)}catch(e){if(!o.isCurrent())return;let t=e.message;z({ok:!1,msg:t}),c.error(`Bulk import failed`,t)}finally{o.finish()&&L(!1)}}},children:I?`Importing…`:`Import ${Y.length||``}`})}),R&&(0,S.jsx)(`span`,{role:R.ok?`status`:`alert`,className:R.ok?`text-sm text-success`:`text-sm text-danger`,children:R.msg})]})]})]})]})}export{Y as BulkAddJobs};