better-cf 0.2.1 → 0.2.2

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/README.md CHANGED
@@ -121,7 +121,7 @@ expect(result.acked).toHaveLength(1);
121
121
  | Local dev orchestration | Team-managed scripts | One `better-cf dev` loop |
122
122
  | Queue test harness | Custom mocks/harnesses | `testQueue` helper |
123
123
 
124
- Detailed comparison: `/apps/docs/src/content/docs/comparison/cloudflare-vs-better-cf.mdx`
124
+ Detailed comparison is being migrated to the separate docs repository.
125
125
 
126
126
  ## Limitations
127
127
 
@@ -142,7 +142,5 @@ Use native Cloudflare APIs directly where the SDK intentionally does not abstrac
142
142
 
143
143
  ## Docs
144
144
 
145
- - Site source: `apps/docs`
146
- - Getting started page: `apps/docs/src/content/docs/getting-started.md`
147
- - File structure guide: `apps/docs/src/content/docs/guides/file-structure.md`
148
- - Cookbook page: `apps/docs/src/content/docs/examples/cookbook.md`
145
+ Docs are being migrated to a separate Next.js application repository.
146
+ During migration, legacy docs source may still exist under `apps/docs`, but it is no longer part of package CI/CD.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { createSDK } from './queue/index.js';
2
- export { a as QueueConfig, b as QueueHandle, k as SendOptions, W as WorkerConfig } from './types-BAZ_wtox.js';
2
+ export { a as BetterCfSDK, D as DefineQueue, e as DefineWorker, i as QueueConfig, l as QueueHandle, n as SendOptions, W as WorkerConfig, p as WorkerEntrypoint } from './types-D44i92Zf.js';
3
3
  import 'zod';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/queue/utils.ts","../src/queue/consumer.ts","../src/queue/internal.ts","../src/queue/types.ts","../src/queue/define-queue.ts","../src/queue/define-worker.ts","../src/queue/create-sdk.ts"],"names":[],"mappings":";AAEO,SAAS,qBAAqB,KAAA,EAAyB;AAC5D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AACxC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAAA,IACrD;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,gBAAgB,CAAA;AAC1C,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAAA,EACrD;AAEA,EAAA,MAAM,cAAc,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAChD,EAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AAEpB,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,OAAO,WAAA,GAAc,EAAA;AAAA,EACvB;AAEA,EAAA,OAAO,WAAA,GAAc,IAAA;AACvB;AAEO,SAAS,gBAAA,CAAiB,OAAqB,KAAA,EAA8C;AAClG,EAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,EAAO;AACpB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,KAAA,EAAO,KAAA,IAAS,KAAA,EAAO,KAAA;AAAA,IAC9B,WAAA,EAAa,KAAA,EAAO,WAAA,IAAe,KAAA,EAAO;AAAA,GAC5C;AACF;AAEO,SAAS,wBAAwB,OAAA,EAGtC;AACA,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,SAA8E,EAAC;AAErF,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,YAAA,GAAe,oBAAA,CAAqB,OAAA,CAAQ,KAAK,CAAA;AAAA,EAC1D;AAEA,EAAA,IAAI,OAAA,CAAQ,gBAAgB,MAAA,EAAW;AACrC,IAAA,MAAA,CAAO,cAAc,OAAA,CAAQ,WAAA;AAAA,EAC/B;AAEA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,cAAc,KAAA,EAAkD;AAC9E,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;;;ACpDA,eAAsB,sBAAA,CACpB,UAAA,EACA,KAAA,EACA,GAAA,EACA,YAAA,EACe;AACf,EAAA,IAAI,UAAA,CAAW,SAAS,QAAA,EAAU;AAChC,IAAA,IAAI,UAAA,CAAW,SAAS,MAAA,EAAQ;AAC9B,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,CAAA,mBAAA,EAAsB,MAAM,KAAK,CAAA,0EAAA;AAAA,OACnC;AACA,MAAA,KAAA,CAAM,MAAA,EAAO;AACb,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,aAAA,CAAc,UAAA,CAAW,MAAA,EAAQ,KAAA,EAAO,KAAoB,YAAY,CAAA;AAC9E,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,aAAa,UAAA,CAAW,IAAA,EAAM,WAAW,MAAA,EAAQ,KAAA,EAAO,KAAoB,YAAY,CAAA;AAChG;AAEA,eAAe,aAAA,CACb,MAAA,EACA,KAAA,EACA,GAAA,EACA,YAAA,EACe;AACf,EAAA,IAAI,cAAA,IAAkB,MAAA,IAAU,MAAA,CAAO,YAAA,EAAc;AACnD,IAAA,IAAI,iBAAA,GAAoB,KAAA;AACxB,IAAA,MAAM,QAAA,GAA4B;AAAA,MAChC,GAAA;AAAA,MACA,YAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,UAAA,sBAAgB,IAAA,EAAK;AAAA,QACrB,qBAAA,EAAuB,KAAA,CAAM,QAAA,CAAS,CAAC,CAAA,EAAG,SAAA;AAAA,QAC1C,QAAQ,MAAM;AACZ,UAAA,iBAAA,GAAoB,IAAA;AACpB,UAAA,KAAA,CAAM,MAAA,EAAO;AAAA,QACf,CAAA;AAAA,QACA,QAAA,EAAU,CAAC,OAAA,KAAwC;AACjD,UAAA,iBAAA,GAAoB,IAAA;AACpB,UAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AAAA,QACxB;AAAA;AACF,KACF;AAEA,IAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MACjD,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,WAAW,GAAA,CAAI,SAAA;AAAA,MACf,UAAU,GAAA,CAAI;AAAA,KAChB,CAAE,CAAA;AAEF,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,YAAA,CAAa,QAAA,EAAU,aAAsB,CAAA;AAC1D,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,QAAA,KAAA,CAAM,MAAA,EAAO;AAAA,MACf;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,kBAAA,CAAmB,MAAA,CAAO,SAAA,EAA2C,QAAA,EAAU,MAAM,KAAK,CAAA;AAChG,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,QAAA,MAAM,YAAA,GACJ,MAAA,CAAO,UAAA,KAAe,MAAA,GAClB,EAAE,cAAc,oBAAA,CAAqB,MAAA,CAAO,UAAU,CAAA,EAAE,GACxD,MAAA;AACN,QAAA,KAAA,CAAM,SAAS,YAAY,CAAA;AAAA,MAC7B;AAAA,IACF;AACA,IAAA;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,OAAA,IAAW,MAAM,QAAA,EAAU;AACpC,IAAA,MAAM,QAAA,GAA4B;AAAA,MAChC,GAAA;AAAA,MACA,YAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,OAAO,KAAA,CAAM;AAAA;AACf,KACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,SAAA,CAAU,QAAQ,IAAI,CAAA;AACpD,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iCAAA,EAAoC,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,MAC5E;AAEA,MAAA,MAAM,MAAA,CAAO,OAAA,CAAQ,QAAA,EAAU,MAAA,CAAO,IAAa,CAAA;AACnD,MAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,IACd,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,kBAAA;AAAA,QACJ,MAAA,CAAO,SAAA;AAAA,QACP,QAAA;AAAA,QACA,OAAA,CAAQ,IAAA;AAAA,QACR;AAAA,OACF;AACA,MAAA,MAAM,YAAA,GACJ,MAAA,CAAO,UAAA,KAAe,MAAA,GAClB,EAAE,cAAc,oBAAA,CAAqB,MAAA,CAAO,UAAU,CAAA,EAAE,GACxD,MAAA;AACN,MAAA,OAAA,CAAQ,MAAM,YAAY,CAAA;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,eAAe,YAAA,CACb,IAAA,EACA,MAAA,EACA,KAAA,EACA,KACA,YAAA,EACe;AACf,EAAA,KAAA,MAAW,OAAA,IAAW,MAAM,QAAA,EAAU;AACpC,IAAA,MAAM,WAAW,OAAA,CAAQ,IAAA;AACzB,IAAA,MAAM,UAAU,QAAA,EAAU,IAAA;AAE1B,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,IAAA,CAAK,OAAO,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,KAAA,CAAM,KAAK,KAAK,MAAA,CAAO,OAAO,CAAC,CAAA,CAAE,CAAA;AACzF,MAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,OAAO,CAAA;AACxB,IAAA,MAAM,QAAA,GAA4B;AAAA,MAChC,GAAA;AAAA,MACA,YAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,OAAO,KAAA,CAAM;AAAA;AACf,KACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,OAAA,CAAQ,SAAA,CAAU,SAAS,IAAI,CAAA;AAClD,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,QAAA,MAAM,IAAI,MAAM,CAAA,gCAAA,EAAmC,OAAO,KAAK,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,MACvF;AACA,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,QAAA,EAAU,MAAA,CAAO,IAAI,CAAA;AACvC,MAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,IACd,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,kBAAA;AAAA,QACJ,GAAA,CAAI,SAAA;AAAA,QACJ,QAAA;AAAA,QACA,QAAA,CAAS,IAAA;AAAA,QACT;AAAA,OACF;AACA,MAAA,MAAM,YAAA,GACJ,MAAA,CAAO,UAAA,KAAe,MAAA,GAClB,EAAE,cAAc,oBAAA,CAAqB,MAAA,CAAO,UAAU,CAAA,EAAE,GACxD,MAAA;AACN,MAAA,OAAA,CAAQ,MAAM,YAAY,CAAA;AAAA,IAC5B;AAAA,EACF;AACF;AAIA,eAAe,kBAAA,CACb,OAAA,EACA,OAAA,EACA,OAAA,EACA,QAAA,EACe;AACf,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,oBAAoB,KAAA,GAAQ,QAAA,GAAW,IAAI,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAC,CAAA;AAC/E,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,CAAQ,OAAA,EAAS,OAAA,EAAS,KAAK,CAAA;AAAA,EACvC,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;AC5LO,IAAM,eAAA,mBAAkB,MAAA,CAAO,GAAA,CAAI,2BAA2B,CAAA;;;ACqM9D,IAAM,uBAAA,uBAA8B,GAAA,CAAI;AAAA,EAC7C,OAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;;;AC1LM,SAAS,kBAAA,GAAwB;AAStC,EAAA,SAAS,YACP,MAAA,EAC8F;AAC9F,IAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAE3C,IAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,IAAA,MAAM,QAAA,GAAW,OAAO,GAAA,EAAiB,IAAA,EAAe,OAAA,KAAyC;AAC/F,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAW,GAAA,CAAI,GAAA,CAAgC,WAAW,CAAA;AAMhE,MAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,CAAQ,SAAS,UAAA,EAAY;AAClD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,WAAW,CAAA,kBAAA,CAAoB,CAAA;AAAA,MAClE;AAEA,MAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAM,uBAAA,CAAwB,OAAO,CAAC,CAAA;AAAA,IAC3D,CAAA;AAEA,IAAA,MAAM,aAAA,GAAgB,OACpB,GAAA,EACA,QAAA,KACkB;AAClB,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAW,GAAA,CAAI,GAAA,CAAgC,WAAW,CAAA;AAMhE,MAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,CAAQ,cAAc,UAAA,EAAY;AACvD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,WAAW,CAAA,kBAAA,CAAoB,CAAA;AAAA,MAClE;AAEA,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,QACtC,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,GAAG,uBAAA,CAAwB,IAAA,CAAK,OAAO;AAAA,OACzC,CAAE,CAAA;AACF,MAAA,MAAM,OAAA,CAAQ,UAAU,OAAO,CAAA;AAAA,IACjC,CAAA;AAEA,IAAA,MAAM,UAAA,GAA+C;AAAA,MACnD,MAAM,IAAA,CAAK,GAAA,EAAiB,IAAA,EAAe,OAAA,EAAsC;AAC/E,QAAA,IAAI,UAAA,CAAW,SAAS,QAAA,EAAU;AAChC,UAAA,MAAM,QAAA,CAAS,GAAA,EAAK,IAAA,EAAM,OAAO,CAAA;AACjC,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,SAAS,GAAA,EAAK,EAAE,MAAM,WAAA,EAAa,IAAA,IAAQ,OAAO,CAAA;AAAA,MAC1D,CAAA;AAAA,MAEA,MAAM,SAAA,CACJ,GAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,QAAA,IAAI,UAAA,CAAW,SAAS,QAAA,EAAU;AAChC,UAAA,MAAM,aAAA;AAAA,YACJ,GAAA;AAAA,YACA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,cACzB,MAAM,OAAA,CAAQ,IAAA;AAAA,cACd,OAAA,EAAS,gBAAA,CAAiB,OAAA,EAAS,OAAO;AAAA,aAC5C,CAAE;AAAA,WACJ;AACA,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,aAAA;AAAA,UACJ,GAAA;AAAA,UACA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,YACzB,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,QAAQ,IAAA,EAAK;AAAA,YAC9C,OAAA,EAAS,gBAAA,CAAiB,OAAA,EAAS,OAAO;AAAA,WAC5C,CAAE;AAAA,SACJ;AAAA,MACF;AAAA,KACF;AAEA,IAAA,IAAI,UAAA,CAAW,SAAS,OAAA,EAAS;AAC/B,MAAA,KAAA,MAAW,OAAA,IAAW,MAAA,CAAO,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA,EAAG;AAClD,QAAA,UAAA,CAAW,OAAO,CAAA,GAAI;AAAA,UACpB,MAAM,IAAA,CAAK,GAAA,EAAiB,IAAA,EAAe,OAAA,EAAuB;AAChE,YAAA,MAAM,SAAS,GAAA,EAAK,EAAE,MAAM,OAAA,EAAS,IAAA,IAAQ,OAAO,CAAA;AAAA,UACtD,CAAA;AAAA,UACA,MAAM,SAAA,CACJ,GAAA,EACA,QAAA,EACA,OAAA,EACA;AACA,YAAA,MAAM,aAAA;AAAA,cACJ,GAAA;AAAA,cACA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,gBACzB,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,QAAQ,IAAA,EAAK;AAAA,gBAC1C,OAAA,EAAS,gBAAA,CAAiB,OAAA,EAAS,OAAO;AAAA,eAC5C,CAAE;AAAA,aACJ;AAAA,UACF;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,cAAA,CAAe,YAAY,eAAA,EAAiB;AAAA,MACjD,UAAA,EAAY,KAAA;AAAA,MACZ,YAAA,EAAc,KAAA;AAAA,MACd,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO;AAAA,QACL,WAAW,IAAA,EAAc;AACvB,UAAA,WAAA,GAAc,IAAA;AAAA,QAChB,CAAA;AAAA,QACA,UAAA,GAAa;AACX,UAAA,OAAO,WAAA;AAAA,QACT,CAAA;AAAA,QACA,aAAA,GAAgB;AACd,UAAA,OAAO,UAAA;AAAA,QACT,CAAA;AAAA,QACA,OAAA,CAAQ,KAAA,EAA8B,GAAA,EAAQ,YAAA,EAAgC;AAC5E,UAAA,OAAO,sBAAA,CAAuB,UAAA,EAAY,KAAA,EAAO,GAAA,EAAK,YAAY,CAAA;AAAA,QACpE;AAAA;AACF,KACD,CAAA;AAED,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,OAAO,WAAA;AACT;AAUA,SAAS,kBACP,MAAA,EACoB;AACpB,EAAA,IAAI,aAAA,CAAc,MAAM,CAAA,EAAG;AACzB,IAAA,IAAI,WAAA,CAAY,MAAM,CAAA,EAAG;AACvB,MAAA,IAAI,SAAA,IAAa,MAAA,IAAU,cAAA,IAAkB,MAAA,EAAQ;AACnD,QAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,MACnG;AACA,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,UAAA,CAAW,MAAM,CAAA,IAAK,eAAA,CAAgB,MAAM,CAAA,EAAG;AACjD,MAAA,MAAM,IAAI,MAAM,2DAA2D,CAAA;AAAA,IAC7E;AAEA,IAAA,IAAI,CAAC,UAAA,CAAW,MAAM,KAAK,CAAC,eAAA,CAAgB,MAAM,CAAA,EAAG;AACnD,MAAA,MAAM,IAAI,MAAM,kFAAkF,CAAA;AAAA,IACpG;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,MAAA;AAAA,MACN;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,eAAe,MAAA,CAAO,aAAA;AAAA,IACtB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC1B,OAAO,MAAA,CAAO;AAAA,GAChB;AAEA,EAAA,MAAM,OAAmD,EAAC;AAC1D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,IAAI,uBAAA,CAAwB,GAAA,CAAI,GAAG,CAAA,EAAG;AACpC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG;AACtB,MAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AAAA,IACd;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AAClC,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,cACP,MAAA,EACwC;AACxC,EAAA,OAAO,SAAA,IAAa,MAAA;AACtB;AAEA,SAAS,YAAe,MAAA,EAA+C;AACrE,EAAA,OAAO,UAAA,IAAc,UAAU,OAAA,CAAQ,MAAA,CAAO,YAAY,MAAA,CAAO,QAAA,CAAS,SAAS,WAAW,CAAA;AAChG;AAEA,SAAS,WAAc,MAAA,EAA+C;AACpE,EAAA,OAAO,SAAA,IAAa,MAAA,IAAU,OAAO,MAAA,CAAO,OAAA,KAAY,UAAA;AAC1D;AAEA,SAAS,gBAAmB,MAAA,EAA+C;AACzE,EAAA,OAAO,cAAA,IAAkB,MAAA,IAAU,OAAO,MAAA,CAAO,YAAA,KAAiB,UAAA;AACpE;AAEA,SAAS,YAAe,KAAA,EAAqD;AAC3E,EAAA,IAAI,CAAC,aAAA,CAAc,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,SAAA,IAAa,SAAS,SAAA,IAAa,KAAA;AAC5C;;;ACnQO,SAAS,mBAAA,GAAyB;AACvC,EAAA,OAAO,SAAS,aAAa,MAAA,EAAyB;AACpD,IAAA,OAAO;AAAA,MACL,MAAM,KAAA,CAAM,OAAA,EAAkB,GAAA,EAAQ,YAAA,EAAmD;AACvF,QAAA,OAAO,MAAA,CAAO,MAAM,OAAA,EAAS;AAAA,UAC3B,GAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH,CAAA;AAAA,MACA,GAAI,OAAO,SAAA,GACP;AAAA,QACE,MAAM,SAAA,CAAU,KAAA,EAAuB,GAAA,EAAQ,YAAA,EAA+C;AAC5F,UAAA,MAAM,MAAA,CAAO,YAAY,KAAA,EAAO;AAAA,YAC9B,GAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,QACH;AAAA,UAEF;AAAC,KACP;AAAA,EACF,CAAA;AACF;;;ACnBO,SAAS,SAAA,GAAiE;AAC/E,EAAA,OAAO;AAAA,IACL,aAAa,kBAAA,EAAsB;AAAA,IACnC,cAAc,mBAAA;AAAuB,GACvC;AACF","file":"index.js","sourcesContent":["import type { Duration, SendOptions } from './types.js';\n\nexport function parseDurationSeconds(value: Duration): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration number: ${value}`);\n }\n return value;\n }\n\n const match = value.match(/^(\\d+)(s|m|h)$/);\n if (!match) {\n throw new Error(`Invalid duration string: ${value}`);\n }\n\n const numberValue = Number.parseInt(match[1], 10);\n const unit = match[2];\n\n if (unit === 's') {\n return numberValue;\n }\n\n if (unit === 'm') {\n return numberValue * 60;\n }\n\n return numberValue * 3600;\n}\n\nexport function mergeSendOptions(entry?: SendOptions, batch?: SendOptions): SendOptions | undefined {\n if (!entry && !batch) {\n return undefined;\n }\n\n return {\n delay: entry?.delay ?? batch?.delay,\n contentType: entry?.contentType ?? batch?.contentType\n };\n}\n\nexport function toCloudflareSendOptions(options: SendOptions | undefined): {\n delaySeconds?: number;\n contentType?: SendOptions['contentType'];\n} {\n if (!options) {\n return {};\n }\n\n const result: { delaySeconds?: number; contentType?: SendOptions['contentType'] } = {};\n\n if (options.delay !== undefined) {\n result.delaySeconds = parseDurationSeconds(options.delay);\n }\n\n if (options.contentType !== undefined) {\n result.contentType = options.contentType;\n }\n\n return result;\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { parseDurationSeconds } from './utils.js';\nimport type {\n AnyJobConfig,\n AnyPushQueueConfig,\n BatchContext,\n Duration,\n QueueContext,\n QueueDefinition,\n QueueEnv\n} from './types.js';\n\nexport async function consumeQueueDefinition<E>(\n definition: QueueDefinition<E>,\n batch: MessageBatch<unknown>,\n env: E,\n executionCtx: ExecutionContext\n): Promise<void> {\n if (definition.kind === 'single') {\n if (definition.mode === 'pull') {\n console.warn(\n `[better-cf] Queue \"${batch.queue}\" configured as http_pull. Worker queue handler is disabled; acking batch.`\n );\n batch.ackAll();\n return;\n }\n\n await consumeSingle(definition.config, batch, env as QueueEnv<E>, executionCtx);\n return;\n }\n\n await consumeMulti(definition.jobs, definition.shared, batch, env as QueueEnv<E>, executionCtx);\n}\n\nasync function consumeSingle<E>(\n config: AnyPushQueueConfig<E>,\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n if ('processBatch' in config && config.processBatch) {\n let ackOrRetryHandled = false;\n const batchCtx: BatchContext<E> = {\n env,\n executionCtx,\n batch: {\n queue: batch.queue,\n receivedAt: new Date(),\n firstMessageTimestamp: batch.messages[0]?.timestamp,\n ackAll: () => {\n ackOrRetryHandled = true;\n batch.ackAll();\n },\n retryAll: (options?: { delaySeconds?: number }) => {\n ackOrRetryHandled = true;\n batch.retryAll(options);\n }\n }\n };\n\n const typedMessages = batch.messages.map((msg) => ({\n data: msg.body,\n id: msg.id,\n timestamp: msg.timestamp,\n attempts: msg.attempts\n }));\n\n try {\n await config.processBatch(batchCtx, typedMessages as never);\n if (!ackOrRetryHandled) {\n batch.ackAll();\n }\n } catch (error) {\n await callFailureHandler(config.onFailure as HandlerLike<BatchContext<E>>, batchCtx, null, error);\n if (!ackOrRetryHandled) {\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n batch.retryAll(retryOptions);\n }\n }\n return;\n }\n\n for (const message of batch.messages) {\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = config.message.safeParse(message.body);\n if (!parsed.success) {\n throw new Error(`Queue message validation failed: ${parsed.error.message}`);\n }\n\n await config.process(queueCtx, parsed.data as never);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n config.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n message.body,\n error\n );\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\nasync function consumeMulti<E>(\n jobs: Record<string, AnyJobConfig<E>>,\n shared: { retryDelay?: Duration },\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n for (const message of batch.messages) {\n const envelope = message.body as { _job?: string; data?: unknown };\n const jobName = envelope?._job;\n\n if (!jobName || !jobs[jobName]) {\n console.error(`[better-cf] Unknown job type for queue ${batch.queue}: ${String(jobName)}`);\n message.ack();\n continue;\n }\n\n const job = jobs[jobName];\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = job.message.safeParse(envelope.data);\n if (!parsed.success) {\n throw new Error(`Queue job validation failed for ${jobName}: ${parsed.error.message}`);\n }\n await job.process(queueCtx, parsed.data);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n job.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n envelope.data,\n error\n );\n const retryOptions =\n shared.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(shared.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\ntype HandlerLike<TContext> = ((ctx: TContext, message: unknown, error: Error) => Promise<void>) | undefined;\n\nasync function callFailureHandler<TContext>(\n handler: HandlerLike<TContext>,\n context: TContext,\n message: unknown,\n rawError: unknown\n): Promise<void> {\n if (!handler) {\n return;\n }\n\n const error = rawError instanceof Error ? rawError : new Error(String(rawError));\n try {\n await handler(context, message, error);\n } catch {\n // Do not fail consume flow because failure hook failed.\n }\n}\n","import type { QueueDefinition } from './types.js';\n\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import type { z } from 'zod';\n\nexport interface BetterCfGeneratedBindings {}\n\nexport interface BetterCfAutoEnv extends BetterCfGeneratedBindings {\n [binding: string]: unknown;\n}\n\nexport type QueueEnv<E> = E & BetterCfGeneratedBindings;\n\nexport type Duration = number | `${number}s` | `${number}m` | `${number}h`;\n\nexport type ContentType = 'json' | 'text' | 'bytes' | 'v8';\n\nexport interface SendOptions {\n delay?: Duration;\n contentType?: ContentType;\n}\n\nexport type SendBatchOptions = SendOptions;\n\nexport interface SendBatchEntry<T> {\n data: T;\n delay?: Duration;\n contentType?: ContentType;\n}\n\nexport interface QueueContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n message: {\n id: string;\n timestamp: Date;\n attempts: number;\n queue: string;\n };\n}\n\nexport interface BatchContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n batch: {\n queue: string;\n receivedAt: Date;\n firstMessageTimestamp?: Date;\n ackAll: () => void;\n retryAll: (options?: { delaySeconds?: number }) => void;\n };\n}\n\nexport interface WorkerContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n}\n\nexport interface ConsumerBatchEntry<T> {\n data: T;\n id: string;\n timestamp: Date;\n attempts: number;\n}\n\nexport interface QueueCommonConfig {\n retry?: number;\n retryDelay?: Duration;\n deadLetter?: string;\n deliveryDelay?: Duration;\n visibilityTimeout?: Duration;\n batch?: {\n maxSize?: number;\n timeout?: Duration;\n maxConcurrency?: number;\n };\n}\n\nexport interface PullConsumerConfig {\n type: 'http_pull';\n visibilityTimeout?: Duration;\n}\n\nexport type QueueProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>\n) => Promise<void>;\n\nexport type QueueBatchProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: BatchContext<E>,\n messages: ConsumerBatchEntry<z.infer<TSchema>>[]\n) => Promise<void>;\n\nexport type QueueFailureHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E> | BatchContext<E>,\n message: z.infer<TSchema> | null,\n error: Error\n) => Promise<void>;\n\nexport type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process: QueueProcessHandler<E, TSchema>;\n processBatch?: never;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\nexport type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process?: never;\n processBatch: QueueBatchProcessHandler<E, TSchema>;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\nexport type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<\n QueueCommonConfig,\n 'visibilityTimeout' | 'batch'\n> & {\n message: TSchema;\n consumer: PullConsumerConfig;\n batch?: never;\n visibilityTimeout?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n};\n\nexport type QueueConfig<E, TSchema extends z.ZodTypeAny> =\n | QueueProcessConfig<E, TSchema>\n | QueueBatchConfig<E, TSchema>\n | QueuePullConfig<E, TSchema>;\n\nexport interface JobConfig<E, TSchema extends z.ZodTypeAny> {\n message: TSchema;\n process: (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;\n onFailure?: (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>,\n error: Error\n ) => Promise<void>;\n}\n\nexport type AnyJobConfig<E> = JobConfig<E, z.ZodTypeAny>;\n\nexport type ExtractJobMap<E, TConfig extends Record<string, unknown>> = {\n [K in keyof TConfig as TConfig[K] extends AnyJobConfig<E> ? K : never]: TConfig[K] extends AnyJobConfig<E>\n ? TConfig[K]\n : never;\n};\n\nexport type MultiJobQueueConfig<E, TConfig extends Record<string, unknown>> = QueueCommonConfig & {\n consumer?: never;\n} & TConfig;\n\nexport interface QueueHandle<E, TMessage> {\n send(ctx: { env: QueueEnv<E> }, data: TMessage, options?: SendOptions): Promise<void>;\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<TMessage>[],\n options?: SendBatchOptions\n ): Promise<void>;\n}\n\nexport type MultiJobQueueHandle<\n E,\n TJobs extends Record<string, AnyJobConfig<E>>\n> = {\n [K in keyof TJobs]: {\n send(\n ctx: { env: QueueEnv<E> },\n data: z.infer<TJobs[K]['message']>,\n options?: SendOptions\n ): Promise<void>;\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<z.infer<TJobs[K]['message']>>[],\n options?: SendBatchOptions\n ): Promise<void>;\n };\n};\n\nexport interface WorkerConfig<E> {\n fetch: (request: Request, ctx: WorkerContext<E>) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, ctx: WorkerContext<E>) => Promise<void>;\n}\n\nexport type AnyQueueConfig<E> = QueueConfig<E, z.ZodTypeAny>;\nexport type AnyPushQueueConfig<E> = QueueProcessConfig<E, z.ZodTypeAny> | QueueBatchConfig<E, z.ZodTypeAny>;\nexport type AnyPullQueueConfig<E> = QueuePullConfig<E, z.ZodTypeAny>;\n\nexport type AnyMultiJobQueueConfig<E> = MultiJobQueueConfig<E, Record<string, unknown>>;\n\nexport type QueueDefinition<E> =\n | { kind: 'single'; mode: 'push'; config: AnyPushQueueConfig<E> }\n | { kind: 'single'; mode: 'pull'; config: AnyPullQueueConfig<E> }\n | {\n kind: 'multi';\n jobs: Record<string, AnyJobConfig<E>>;\n shared: QueueCommonConfig;\n };\n\nexport const RESERVED_MULTI_JOB_KEYS = new Set([\n 'retry',\n 'retryDelay',\n 'deadLetter',\n 'deliveryDelay',\n 'visibilityTimeout',\n 'batch',\n 'consumer'\n]);\n","import { consumeQueueDefinition } from './consumer.js';\nimport { getQueueInternals, kQueueInternals } from './internal.js';\nimport {\n RESERVED_MULTI_JOB_KEYS,\n type AnyMultiJobQueueConfig,\n type AnyPullQueueConfig,\n type AnyPushQueueConfig,\n type ExtractJobMap,\n type JobConfig,\n type MultiJobQueueConfig,\n type MultiJobQueueHandle,\n type QueueConfig,\n type QueueDefinition,\n type QueueHandle,\n type SendBatchEntry,\n type SendBatchOptions,\n type SendOptions\n} from './types.js';\nimport { isPlainObject, mergeSendOptions, toCloudflareSendOptions } from './utils.js';\nimport type { z } from 'zod';\n\nexport function defineQueueFactory<E>() {\n function defineQueue<TSchema extends z.ZodTypeAny>(\n config: QueueConfig<E, TSchema>\n ): QueueHandle<E, z.infer<TSchema>>;\n\n function defineQueue<const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n\n function defineQueue(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n ): QueueHandle<E, unknown> | MultiJobQueueHandle<E, Record<string, JobConfig<E, z.ZodTypeAny>>> {\n const definition = toQueueDefinition(config);\n\n let bindingName: string | null = null;\n\n const sendBase = async (ctx: { env: E }, body: unknown, options?: SendOptions): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n send: (value: unknown, opts?: { delaySeconds?: number; contentType?: SendOptions['contentType'] }) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.send !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n await binding.send(body, toCloudflareSendOptions(options));\n };\n\n const sendBatchBase = async (\n ctx: { env: E },\n messages: Array<{ body: unknown; options?: SendOptions }>\n ): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n sendBatch: (entries: Array<{ body: unknown; delaySeconds?: number; contentType?: SendOptions['contentType'] }>) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.sendBatch !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n const payload = messages.map((item) => ({\n body: item.body,\n ...toCloudflareSendOptions(item.options)\n }));\n await binding.sendBatch(payload);\n };\n\n const baseHandle: Record<string | symbol, unknown> = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions): Promise<void> {\n if (definition.kind === 'single') {\n await sendBase(ctx, data, options);\n return;\n }\n\n await sendBase(ctx, { _job: '__default', data }, options);\n },\n\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ): Promise<void> {\n if (definition.kind === 'single') {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: message.data,\n options: mergeSendOptions(message, options)\n }))\n );\n return;\n }\n\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: '__default', data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n\n if (definition.kind === 'multi') {\n for (const jobName of Object.keys(definition.jobs)) {\n baseHandle[jobName] = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions) {\n await sendBase(ctx, { _job: jobName, data }, options);\n },\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ) {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: jobName, data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n }\n }\n\n Object.defineProperty(baseHandle, kQueueInternals, {\n enumerable: false,\n configurable: false,\n writable: false,\n value: {\n setBinding(name: string) {\n bindingName = name;\n },\n getBinding() {\n return bindingName;\n },\n getDefinition() {\n return definition;\n },\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext) {\n return consumeQueueDefinition(definition, batch, env, executionCtx);\n }\n }\n });\n\n return baseHandle as unknown as QueueHandle<E, unknown>;\n }\n\n return defineQueue;\n}\n\nexport function setQueueBinding<E>(handle: unknown, binding: string): void {\n getQueueInternals<E>(handle).setBinding(binding);\n}\n\nexport function readQueueDefinition<E>(handle: unknown): QueueDefinition<E> {\n return getQueueInternals<E>(handle).getDefinition();\n}\n\nfunction toQueueDefinition<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): QueueDefinition<E> {\n if (isSingleQueue(config)) {\n if (isPullQueue(config)) {\n if ('process' in config || 'processBatch' in config) {\n throw new Error('Queue config with consumer.type=\"http_pull\" cannot define process/processBatch.');\n }\n return {\n kind: 'single',\n mode: 'pull',\n config: config as AnyPullQueueConfig<E>\n };\n }\n\n if (hasProcess(config) && hasProcessBatch(config)) {\n throw new Error('Queue config cannot define both process and processBatch.');\n }\n\n if (!hasProcess(config) && !hasProcessBatch(config)) {\n throw new Error('Queue config must define one of process or processBatch in worker consumer mode.');\n }\n\n return {\n kind: 'single',\n mode: 'push',\n config: config as AnyPushQueueConfig<E>\n };\n }\n\n const shared = {\n retry: config.retry,\n retryDelay: config.retryDelay,\n deadLetter: config.deadLetter,\n deliveryDelay: config.deliveryDelay,\n visibilityTimeout: config.visibilityTimeout,\n batch: config.batch\n };\n\n const jobs: Record<string, JobConfig<E, z.ZodTypeAny>> = {};\n for (const [key, value] of Object.entries(config)) {\n if (RESERVED_MULTI_JOB_KEYS.has(key)) {\n continue;\n }\n if (isJobConfig(value)) {\n jobs[key] = value;\n }\n }\n\n if (Object.keys(jobs).length === 0) {\n throw new Error('Multi-job queue config must define at least one job.');\n }\n\n return {\n kind: 'multi',\n jobs,\n shared\n };\n}\n\nfunction isSingleQueue<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): config is QueueConfig<E, z.ZodTypeAny> {\n return 'message' in config;\n}\n\nfunction isPullQueue<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'consumer' in config && Boolean(config.consumer && config.consumer.type === 'http_pull');\n}\n\nfunction hasProcess<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'process' in config && typeof config.process === 'function';\n}\n\nfunction hasProcessBatch<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'processBatch' in config && typeof config.processBatch === 'function';\n}\n\nfunction isJobConfig<E>(value: unknown): value is JobConfig<E, z.ZodTypeAny> {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return 'message' in value && 'process' in value;\n}\n","import type { QueueEnv, WorkerConfig } from './types.js';\n\nexport function defineWorkerFactory<E>() {\n return function defineWorker(config: WorkerConfig<E>) {\n return {\n async fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response> {\n return config.fetch(request, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n },\n ...(config.scheduled\n ? {\n async scheduled(event: ScheduledEvent, env: E, executionCtx: ExecutionContext): Promise<void> {\n await config.scheduled?.(event, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n }\n }\n : {})\n };\n };\n}\n","import { defineQueueFactory } from './define-queue.js';\nimport { defineWorkerFactory } from './define-worker.js';\nimport type { BetterCfAutoEnv } from './types.js';\n\nexport function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>() {\n return {\n defineQueue: defineQueueFactory<E>(),\n defineWorker: defineWorkerFactory<E>()\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/queue/utils.ts","../src/queue/consumer.ts","../src/queue/internal.ts","../src/queue/types.ts","../src/queue/define-queue.ts","../src/queue/define-worker.ts","../src/queue/create-sdk.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Duration, SendOptions } from './types.js';\n\nexport function parseDurationSeconds(value: Duration): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration number: ${value}`);\n }\n return value;\n }\n\n const match = value.match(/^(\\d+)(s|m|h)$/);\n if (!match) {\n throw new Error(`Invalid duration string: ${value}`);\n }\n\n const numberValue = Number.parseInt(match[1], 10);\n const unit = match[2];\n\n if (unit === 's') {\n return numberValue;\n }\n\n if (unit === 'm') {\n return numberValue * 60;\n }\n\n return numberValue * 3600;\n}\n\nexport function mergeSendOptions(entry?: SendOptions, batch?: SendOptions): SendOptions | undefined {\n if (!entry && !batch) {\n return undefined;\n }\n\n return {\n delay: entry?.delay ?? batch?.delay,\n contentType: entry?.contentType ?? batch?.contentType\n };\n}\n\nexport function toCloudflareSendOptions(options: SendOptions | undefined): {\n delaySeconds?: number;\n contentType?: SendOptions['contentType'];\n} {\n if (!options) {\n return {};\n }\n\n const result: { delaySeconds?: number; contentType?: SendOptions['contentType'] } = {};\n\n if (options.delay !== undefined) {\n result.delaySeconds = parseDurationSeconds(options.delay);\n }\n\n if (options.contentType !== undefined) {\n result.contentType = options.contentType;\n }\n\n return result;\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { parseDurationSeconds } from './utils.js';\nimport type {\n AnyJobConfig,\n AnyPushQueueConfig,\n BatchContext,\n Duration,\n QueueContext,\n QueueDefinition,\n QueueEnv\n} from './types.js';\n\nexport async function consumeQueueDefinition<E>(\n definition: QueueDefinition<E>,\n batch: MessageBatch<unknown>,\n env: E,\n executionCtx: ExecutionContext\n): Promise<void> {\n if (definition.kind === 'single') {\n if (definition.mode === 'pull') {\n console.warn(\n `[better-cf] Queue \"${batch.queue}\" configured as http_pull. Worker queue handler is disabled; acking batch.`\n );\n batch.ackAll();\n return;\n }\n\n await consumeSingle(definition.config, batch, env as QueueEnv<E>, executionCtx);\n return;\n }\n\n await consumeMulti(definition.jobs, definition.shared, batch, env as QueueEnv<E>, executionCtx);\n}\n\nasync function consumeSingle<E>(\n config: AnyPushQueueConfig<E>,\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n if ('processBatch' in config && config.processBatch) {\n let ackOrRetryHandled = false;\n const batchCtx: BatchContext<E> = {\n env,\n executionCtx,\n batch: {\n queue: batch.queue,\n receivedAt: new Date(),\n firstMessageTimestamp: batch.messages[0]?.timestamp,\n ackAll: () => {\n ackOrRetryHandled = true;\n batch.ackAll();\n },\n retryAll: (options?: { delaySeconds?: number }) => {\n ackOrRetryHandled = true;\n batch.retryAll(options);\n }\n }\n };\n\n const typedMessages = batch.messages.map((msg) => ({\n data: msg.body,\n id: msg.id,\n timestamp: msg.timestamp,\n attempts: msg.attempts\n }));\n\n try {\n await config.processBatch(batchCtx, typedMessages as never);\n if (!ackOrRetryHandled) {\n batch.ackAll();\n }\n } catch (error) {\n await callFailureHandler(config.onFailure as HandlerLike<BatchContext<E>>, batchCtx, null, error);\n if (!ackOrRetryHandled) {\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n batch.retryAll(retryOptions);\n }\n }\n return;\n }\n\n for (const message of batch.messages) {\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = config.message.safeParse(message.body);\n if (!parsed.success) {\n throw new Error(`Queue message validation failed: ${parsed.error.message}`);\n }\n\n await config.process(queueCtx, parsed.data as never);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n config.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n message.body,\n error\n );\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\nasync function consumeMulti<E>(\n jobs: Record<string, AnyJobConfig<E>>,\n shared: { retryDelay?: Duration },\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n for (const message of batch.messages) {\n const envelope = message.body as { _job?: string; data?: unknown };\n const jobName = envelope?._job;\n\n if (!jobName || !jobs[jobName]) {\n console.error(`[better-cf] Unknown job type for queue ${batch.queue}: ${String(jobName)}`);\n message.ack();\n continue;\n }\n\n const job = jobs[jobName];\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = job.message.safeParse(envelope.data);\n if (!parsed.success) {\n throw new Error(`Queue job validation failed for ${jobName}: ${parsed.error.message}`);\n }\n await job.process(queueCtx, parsed.data);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n job.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n envelope.data,\n error\n );\n const retryOptions =\n shared.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(shared.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\ntype HandlerLike<TContext> = ((ctx: TContext, message: unknown, error: Error) => Promise<void>) | undefined;\n\nasync function callFailureHandler<TContext>(\n handler: HandlerLike<TContext>,\n context: TContext,\n message: unknown,\n rawError: unknown\n): Promise<void> {\n if (!handler) {\n return;\n }\n\n const error = rawError instanceof Error ? rawError : new Error(String(rawError));\n try {\n await handler(context, message, error);\n } catch {\n // Do not fail consume flow because failure hook failed.\n }\n}\n","import type { QueueDefinition } from './types.js';\n\n/**\n * Symbol used to store non-enumerable queue internals on queue handles.\n */\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\n/**\n * Internal queue API used by runtime/testing/CLI internals.\n */\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\n/**\n * Reads internal queue metadata from a queue handle.\n */\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\n/**\n * Input module shape accepted when resolving worker handlers.\n */\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\n/**\n * Normalized handler pair resolved from a worker module export.\n */\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Resolves `fetch`/`scheduled` handlers from various worker export styles.\n */\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import type { z } from 'zod';\n\n/**\n * Marker interface that generated env bindings extend.\n */\nexport interface BetterCfGeneratedBindings {}\n\n/**\n * Default env type used when `createSDK()` is called without a generic.\n */\nexport interface BetterCfAutoEnv extends BetterCfGeneratedBindings {\n [binding: string]: unknown;\n}\n\n/**\n * Runtime env shape available inside queue and worker handlers.\n */\nexport type QueueEnv<E> = E & BetterCfGeneratedBindings;\n\n/**\n * Duration in seconds/minutes/hours shorthand or raw seconds.\n */\nexport type Duration = number | `${number}s` | `${number}m` | `${number}h`;\n\n/**\n * Cloudflare Queue message content type.\n */\nexport type ContentType = 'json' | 'text' | 'bytes' | 'v8';\n\n/**\n * Per-message send options.\n */\nexport interface SendOptions {\n /** Delay before message becomes visible to consumers. */\n delay?: Duration;\n /** Explicit content type for Cloudflare queue delivery. */\n contentType?: ContentType;\n}\n\n/**\n * Shared send options for `sendBatch`.\n */\nexport type SendBatchOptions = SendOptions;\n\n/**\n * Per-message input for `sendBatch`.\n */\nexport interface SendBatchEntry<T> {\n data: T;\n delay?: Duration;\n contentType?: ContentType;\n}\n\n/**\n * Context passed to per-message queue consumers.\n */\nexport interface QueueContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n message: {\n id: string;\n timestamp: Date;\n attempts: number;\n queue: string;\n };\n}\n\n/**\n * Context passed to batch queue consumers.\n */\nexport interface BatchContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n batch: {\n queue: string;\n receivedAt: Date;\n firstMessageTimestamp?: Date;\n ackAll: () => void;\n retryAll: (options?: { delaySeconds?: number }) => void;\n };\n}\n\n/**\n * Context passed to worker handlers.\n */\nexport interface WorkerContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n}\n\n/**\n * Message shape received by batch consumers.\n */\nexport interface ConsumerBatchEntry<T> {\n data: T;\n id: string;\n timestamp: Date;\n attempts: number;\n}\n\n/**\n * Queue settings shared across worker-consumer and pull-consumer modes.\n */\nexport interface QueueCommonConfig {\n /** Number of retry attempts before dead-lettering. */\n retry?: number;\n /** Delay between retries. */\n retryDelay?: Duration;\n /** Dead-letter queue name. */\n deadLetter?: string;\n /** Delivery delay applied to newly sent messages. */\n deliveryDelay?: Duration;\n /** Message visibility timeout (worker consumer mode only). */\n visibilityTimeout?: Duration;\n /** Batch processing tuning (worker consumer mode only). */\n batch?: {\n maxSize?: number;\n timeout?: Duration;\n maxConcurrency?: number;\n };\n}\n\n/**\n * Pull consumer mode configuration.\n */\nexport interface PullConsumerConfig {\n /** Pull mode marker. */\n type: 'http_pull';\n /** Pull visibility timeout in seconds. */\n visibilityTimeout?: Duration;\n}\n\n/**\n * Per-message queue handler.\n */\nexport type QueueProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>\n) => Promise<void>;\n\n/**\n * Batch queue handler.\n */\nexport type QueueBatchProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: BatchContext<E>,\n messages: ConsumerBatchEntry<z.infer<TSchema>>[]\n) => Promise<void>;\n\n/**\n * Optional failure handler for queue processing.\n */\nexport type QueueFailureHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E> | BatchContext<E>,\n message: z.infer<TSchema> | null,\n error: Error\n) => Promise<void>;\n\n/**\n * Worker-consumer queue with per-message processing.\n */\nexport type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process: QueueProcessHandler<E, TSchema>;\n processBatch?: never;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\n/**\n * Worker-consumer queue with batch processing.\n */\nexport type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process?: never;\n processBatch: QueueBatchProcessHandler<E, TSchema>;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\n/**\n * HTTP pull consumer queue (producer-only declaration).\n */\nexport type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<\n QueueCommonConfig,\n 'visibilityTimeout' | 'batch'\n> & {\n message: TSchema;\n consumer: PullConsumerConfig;\n batch?: never;\n visibilityTimeout?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n};\n\n/**\n * Single-queue config union for worker and pull consumer modes.\n */\nexport type QueueConfig<E, TSchema extends z.ZodTypeAny> =\n | QueueProcessConfig<E, TSchema>\n | QueueBatchConfig<E, TSchema>\n | QueuePullConfig<E, TSchema>;\n\n/**\n * Per-job declaration inside a multi-job queue.\n */\nexport interface JobConfig<E, TSchema extends z.ZodTypeAny> {\n message: TSchema;\n process: (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;\n onFailure?: (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>,\n error: Error\n ) => Promise<void>;\n}\n\n/**\n * Internal helper alias for any job config.\n */\nexport type AnyJobConfig<E> = JobConfig<E, z.ZodTypeAny>;\n\n/**\n * Extracts only job keys from a multi-job config object.\n */\nexport type ExtractJobMap<E, TConfig extends Record<string, unknown>> = {\n [K in keyof TConfig as TConfig[K] extends AnyJobConfig<E> ? K : never]: TConfig[K] extends AnyJobConfig<E>\n ? TConfig[K]\n : never;\n};\n\n/**\n * Multi-job queue declaration object.\n */\nexport type MultiJobQueueConfig<E, TConfig extends Record<string, unknown>> = QueueCommonConfig & {\n consumer?: never;\n message?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n} & TConfig;\n\n/**\n * Producer handle for a single queue declaration.\n */\nexport interface QueueHandle<E, TMessage> {\n /** Sends one message to the queue. */\n send(ctx: { env: QueueEnv<E> }, data: TMessage, options?: SendOptions): Promise<void>;\n /** Sends multiple messages in one request. */\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<TMessage>[],\n options?: SendBatchOptions\n ): Promise<void>;\n}\n\n/**\n * Producer handles keyed by job name for a multi-job queue.\n */\nexport type MultiJobQueueHandle<\n E,\n TJobs extends Record<string, AnyJobConfig<E>>\n> = {\n [K in keyof TJobs]: {\n /** Sends one message to a named job. */\n send(\n ctx: { env: QueueEnv<E> },\n data: z.infer<TJobs[K]['message']>,\n options?: SendOptions\n ): Promise<void>;\n /** Sends many messages to a named job. */\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<z.infer<TJobs[K]['message']>>[],\n options?: SendBatchOptions\n ): Promise<void>;\n };\n};\n\n/**\n * Worker handlers used to define module exports.\n */\nexport interface WorkerConfig<E> {\n /** Main fetch handler. */\n fetch: (request: Request, ctx: WorkerContext<E>) => Promise<Response>;\n /** Optional scheduled handler. */\n scheduled?: (event: ScheduledEvent, ctx: WorkerContext<E>) => Promise<void>;\n}\n\n/**\n * Worker module shape returned by `defineWorker`.\n */\nexport interface WorkerEntrypoint<E> {\n fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: E, executionCtx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Defines a worker module with typed queue-aware context.\n */\nexport type DefineWorker<E> = (config: WorkerConfig<E>) => WorkerEntrypoint<E>;\n\n/**\n * Defines queue contracts and returns typed producer handles.\n */\nexport interface DefineQueue<E> {\n /**\n * Declare a single queue (worker consumer or http pull consumer).\n *\n * @example\n * defineQueue({\n * message: z.object({ id: z.string() }),\n * process: async (ctx, message) => {}\n * })\n */\n <TSchema extends z.ZodTypeAny>(config: QueueConfig<E, TSchema>): QueueHandle<E, z.infer<TSchema>>;\n\n /**\n * Declare a multi-job queue where each top-level key is a job definition.\n *\n * @example\n * defineQueue({\n * email: { message: z.object({ to: z.string() }), process: async () => {} },\n * audit: { message: z.object({ id: z.string() }), process: async () => {} }\n * })\n */\n <const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n}\n\n/**\n * SDK helpers returned by `createSDK`.\n */\nexport interface BetterCfSDK<E> {\n /** Queue declaration helper with schema-inferred producer types. */\n defineQueue: DefineQueue<E>;\n /** Worker declaration helper that maps to Cloudflare module handlers. */\n defineWorker: DefineWorker<E>;\n}\n\n/**\n * Internal helper alias for any queue config mode.\n */\nexport type AnyQueueConfig<E> = QueueConfig<E, z.ZodTypeAny>;\n/**\n * Internal helper alias for worker-consumer queue modes.\n */\nexport type AnyPushQueueConfig<E> = QueueProcessConfig<E, z.ZodTypeAny> | QueueBatchConfig<E, z.ZodTypeAny>;\n/**\n * Internal helper alias for pull-consumer queue mode.\n */\nexport type AnyPullQueueConfig<E> = QueuePullConfig<E, z.ZodTypeAny>;\n\n/**\n * Internal helper alias for any multi-job queue config.\n */\nexport type AnyMultiJobQueueConfig<E> = MultiJobQueueConfig<E, Record<string, unknown>>;\n\n/**\n * Normalized queue definition used by runtime internals.\n */\nexport type QueueDefinition<E> =\n | { kind: 'single'; mode: 'push'; config: AnyPushQueueConfig<E> }\n | { kind: 'single'; mode: 'pull'; config: AnyPullQueueConfig<E> }\n | {\n kind: 'multi';\n jobs: Record<string, AnyJobConfig<E>>;\n shared: QueueCommonConfig;\n };\n\n/**\n * Reserved top-level keys treated as shared config in multi-job mode.\n */\nexport const RESERVED_MULTI_JOB_KEYS = new Set([\n 'retry',\n 'retryDelay',\n 'deadLetter',\n 'deliveryDelay',\n 'visibilityTimeout',\n 'batch',\n 'consumer'\n]);\n","import { consumeQueueDefinition } from './consumer.js';\nimport { getQueueInternals, kQueueInternals } from './internal.js';\nimport {\n RESERVED_MULTI_JOB_KEYS,\n type AnyMultiJobQueueConfig,\n type AnyPullQueueConfig,\n type AnyPushQueueConfig,\n type ExtractJobMap,\n type DefineQueue,\n type JobConfig,\n type MultiJobQueueConfig,\n type MultiJobQueueHandle,\n type QueueConfig,\n type QueueDefinition,\n type QueueHandle,\n type SendBatchEntry,\n type SendBatchOptions,\n type SendOptions\n} from './types.js';\nimport { isPlainObject, mergeSendOptions, toCloudflareSendOptions } from './utils.js';\nimport type { z } from 'zod';\n\n/**\n * Creates a typed `defineQueue` helper bound to the SDK env generic.\n */\nexport function defineQueueFactory<E>(): DefineQueue<E> {\n /**\n * Declare a single queue contract.\n */\n function defineQueue<TSchema extends z.ZodTypeAny>(\n config: QueueConfig<E, TSchema>\n ): QueueHandle<E, z.infer<TSchema>>;\n\n /**\n * Declare a multi-job queue contract.\n */\n function defineQueue<const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n\n function defineQueue(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n ): QueueHandle<E, unknown> | MultiJobQueueHandle<E, Record<string, JobConfig<E, z.ZodTypeAny>>> {\n const definition = toQueueDefinition(config);\n\n let bindingName: string | null = null;\n\n const sendBase = async (ctx: { env: E }, body: unknown, options?: SendOptions): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n send: (value: unknown, opts?: { delaySeconds?: number; contentType?: SendOptions['contentType'] }) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.send !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n await binding.send(body, toCloudflareSendOptions(options));\n };\n\n const sendBatchBase = async (\n ctx: { env: E },\n messages: Array<{ body: unknown; options?: SendOptions }>\n ): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n sendBatch: (entries: Array<{ body: unknown; delaySeconds?: number; contentType?: SendOptions['contentType'] }>) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.sendBatch !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n const payload = messages.map((item) => ({\n body: item.body,\n ...toCloudflareSendOptions(item.options)\n }));\n await binding.sendBatch(payload);\n };\n\n const baseHandle: Record<string | symbol, unknown> = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions): Promise<void> {\n if (definition.kind === 'single') {\n await sendBase(ctx, data, options);\n return;\n }\n\n await sendBase(ctx, { _job: '__default', data }, options);\n },\n\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ): Promise<void> {\n if (definition.kind === 'single') {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: message.data,\n options: mergeSendOptions(message, options)\n }))\n );\n return;\n }\n\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: '__default', data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n\n if (definition.kind === 'multi') {\n for (const jobName of Object.keys(definition.jobs)) {\n baseHandle[jobName] = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions) {\n await sendBase(ctx, { _job: jobName, data }, options);\n },\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ) {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: jobName, data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n }\n }\n\n Object.defineProperty(baseHandle, kQueueInternals, {\n enumerable: false,\n configurable: false,\n writable: false,\n value: {\n setBinding(name: string) {\n bindingName = name;\n },\n getBinding() {\n return bindingName;\n },\n getDefinition() {\n return definition;\n },\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext) {\n return consumeQueueDefinition(definition, batch, env, executionCtx);\n }\n }\n });\n\n return baseHandle as unknown as QueueHandle<E, unknown>;\n }\n\n return defineQueue;\n}\n\n/**\n * Attaches the generated Cloudflare binding name to a queue handle.\n */\nexport function setQueueBinding<E>(handle: unknown, binding: string): void {\n getQueueInternals<E>(handle).setBinding(binding);\n}\n\n/**\n * Reads normalized queue metadata from a queue handle.\n */\nexport function readQueueDefinition<E>(handle: unknown): QueueDefinition<E> {\n return getQueueInternals<E>(handle).getDefinition();\n}\n\nfunction toQueueDefinition<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): QueueDefinition<E> {\n if (isSingleQueue(config)) {\n if (isPullQueue(config)) {\n if ('process' in config || 'processBatch' in config) {\n throw new Error('Queue config with consumer.type=\"http_pull\" cannot define process/processBatch.');\n }\n return {\n kind: 'single',\n mode: 'pull',\n config: config as AnyPullQueueConfig<E>\n };\n }\n\n if (hasProcess(config) && hasProcessBatch(config)) {\n throw new Error('Queue config cannot define both process and processBatch.');\n }\n\n if (!hasProcess(config) && !hasProcessBatch(config)) {\n throw new Error('Queue config must define one of process or processBatch in worker consumer mode.');\n }\n\n return {\n kind: 'single',\n mode: 'push',\n config: config as AnyPushQueueConfig<E>\n };\n }\n\n const shared = {\n retry: config.retry,\n retryDelay: config.retryDelay,\n deadLetter: config.deadLetter,\n deliveryDelay: config.deliveryDelay,\n visibilityTimeout: config.visibilityTimeout,\n batch: config.batch\n };\n\n const jobs: Record<string, JobConfig<E, z.ZodTypeAny>> = {};\n for (const [key, value] of Object.entries(config)) {\n if (RESERVED_MULTI_JOB_KEYS.has(key)) {\n continue;\n }\n if (isJobConfig(value)) {\n jobs[key] = value;\n }\n }\n\n if (Object.keys(jobs).length === 0) {\n throw new Error('Multi-job queue config must define at least one job.');\n }\n\n return {\n kind: 'multi',\n jobs,\n shared\n };\n}\n\nfunction isSingleQueue<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): config is QueueConfig<E, z.ZodTypeAny> {\n return 'message' in config;\n}\n\nfunction isPullQueue<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'consumer' in config && Boolean(config.consumer && config.consumer.type === 'http_pull');\n}\n\nfunction hasProcess<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'process' in config && typeof config.process === 'function';\n}\n\nfunction hasProcessBatch<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'processBatch' in config && typeof config.processBatch === 'function';\n}\n\nfunction isJobConfig<E>(value: unknown): value is JobConfig<E, z.ZodTypeAny> {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return 'message' in value && 'process' in value;\n}\n","import type { DefineWorker, QueueEnv, WorkerConfig, WorkerEntrypoint } from './types.js';\n\n/**\n * Creates a typed `defineWorker` helper bound to the SDK env generic.\n */\nexport function defineWorkerFactory<E>(): DefineWorker<E> {\n return function defineWorker(config: WorkerConfig<E>): WorkerEntrypoint<E> {\n return {\n async fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response> {\n return config.fetch(request, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n },\n ...(config.scheduled\n ? {\n async scheduled(event: ScheduledEvent, env: E, executionCtx: ExecutionContext): Promise<void> {\n await config.scheduled?.(event, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n }\n }\n : {})\n };\n };\n}\n","import { defineQueueFactory } from './define-queue.js';\nimport { defineWorkerFactory } from './define-worker.js';\nimport type { BetterCfAutoEnv, BetterCfSDK } from './types.js';\n\n/**\n * Creates typed queue + worker helpers for your Cloudflare Worker app.\n *\n * @example\n * const { defineQueue, defineWorker } = createSDK<Env>();\n */\nexport function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>(): BetterCfSDK<E> {\n return {\n defineQueue: defineQueueFactory<E>(),\n defineWorker: defineWorkerFactory<E>()\n };\n}\n"]}
@@ -1,16 +1,13 @@
1
- import { B as BetterCfAutoEnv, a as QueueConfig, b as QueueHandle, M as MultiJobQueueConfig, c as MultiJobQueueHandle, E as ExtractJobMap, W as WorkerConfig } from '../types-BAZ_wtox.js';
2
- export { d as BatchContext, e as BetterCfGeneratedBindings, C as ConsumerBatchEntry, f as ContentType, D as Duration, J as JobConfig, P as PullConsumerConfig, g as QueueCommonConfig, h as QueueContext, i as QueueEnv, S as SendBatchEntry, j as SendBatchOptions, k as SendOptions, l as WorkerContext } from '../types-BAZ_wtox.js';
3
- import * as zod from 'zod';
1
+ import { B as BetterCfAutoEnv, a as BetterCfSDK } from '../types-D44i92Zf.js';
2
+ export { b as BatchContext, c as BetterCfGeneratedBindings, C as ConsumerBatchEntry, d as ContentType, D as DefineQueue, e as DefineWorker, f as Duration, J as JobConfig, M as MultiJobQueueConfig, g as MultiJobQueueHandle, P as PullConsumerConfig, h as QueueCommonConfig, i as QueueConfig, j as QueueContext, k as QueueEnv, l as QueueHandle, S as SendBatchEntry, m as SendBatchOptions, n as SendOptions, W as WorkerConfig, o as WorkerContext, p as WorkerEntrypoint } from '../types-D44i92Zf.js';
3
+ import 'zod';
4
4
 
5
- declare function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>(): {
6
- defineQueue: {
7
- <TSchema extends zod.ZodTypeAny>(config: QueueConfig<E, TSchema>): QueueHandle<E, zod.TypeOf<TSchema>>;
8
- <const TConfig extends Record<string, unknown>>(config: MultiJobQueueConfig<E, TConfig>): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;
9
- };
10
- defineWorker: (config: WorkerConfig<E>) => {
11
- scheduled?: ((event: ScheduledEvent, env: E, executionCtx: ExecutionContext) => Promise<void>) | undefined;
12
- fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response>;
13
- };
14
- };
5
+ /**
6
+ * Creates typed queue + worker helpers for your Cloudflare Worker app.
7
+ *
8
+ * @example
9
+ * const { defineQueue, defineWorker } = createSDK<Env>();
10
+ */
11
+ declare function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>(): BetterCfSDK<E>;
15
12
 
16
- export { BetterCfAutoEnv, MultiJobQueueConfig, MultiJobQueueHandle, QueueConfig, QueueHandle, WorkerConfig, createSDK };
13
+ export { BetterCfAutoEnv, BetterCfSDK, createSDK };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queue/utils.ts","../../src/queue/consumer.ts","../../src/queue/internal.ts","../../src/queue/types.ts","../../src/queue/define-queue.ts","../../src/queue/define-worker.ts","../../src/queue/create-sdk.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Duration, SendOptions } from './types.js';\n\nexport function parseDurationSeconds(value: Duration): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration number: ${value}`);\n }\n return value;\n }\n\n const match = value.match(/^(\\d+)(s|m|h)$/);\n if (!match) {\n throw new Error(`Invalid duration string: ${value}`);\n }\n\n const numberValue = Number.parseInt(match[1], 10);\n const unit = match[2];\n\n if (unit === 's') {\n return numberValue;\n }\n\n if (unit === 'm') {\n return numberValue * 60;\n }\n\n return numberValue * 3600;\n}\n\nexport function mergeSendOptions(entry?: SendOptions, batch?: SendOptions): SendOptions | undefined {\n if (!entry && !batch) {\n return undefined;\n }\n\n return {\n delay: entry?.delay ?? batch?.delay,\n contentType: entry?.contentType ?? batch?.contentType\n };\n}\n\nexport function toCloudflareSendOptions(options: SendOptions | undefined): {\n delaySeconds?: number;\n contentType?: SendOptions['contentType'];\n} {\n if (!options) {\n return {};\n }\n\n const result: { delaySeconds?: number; contentType?: SendOptions['contentType'] } = {};\n\n if (options.delay !== undefined) {\n result.delaySeconds = parseDurationSeconds(options.delay);\n }\n\n if (options.contentType !== undefined) {\n result.contentType = options.contentType;\n }\n\n return result;\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { parseDurationSeconds } from './utils.js';\nimport type {\n AnyJobConfig,\n AnyPushQueueConfig,\n BatchContext,\n Duration,\n QueueContext,\n QueueDefinition,\n QueueEnv\n} from './types.js';\n\nexport async function consumeQueueDefinition<E>(\n definition: QueueDefinition<E>,\n batch: MessageBatch<unknown>,\n env: E,\n executionCtx: ExecutionContext\n): Promise<void> {\n if (definition.kind === 'single') {\n if (definition.mode === 'pull') {\n console.warn(\n `[better-cf] Queue \"${batch.queue}\" configured as http_pull. Worker queue handler is disabled; acking batch.`\n );\n batch.ackAll();\n return;\n }\n\n await consumeSingle(definition.config, batch, env as QueueEnv<E>, executionCtx);\n return;\n }\n\n await consumeMulti(definition.jobs, definition.shared, batch, env as QueueEnv<E>, executionCtx);\n}\n\nasync function consumeSingle<E>(\n config: AnyPushQueueConfig<E>,\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n if ('processBatch' in config && config.processBatch) {\n let ackOrRetryHandled = false;\n const batchCtx: BatchContext<E> = {\n env,\n executionCtx,\n batch: {\n queue: batch.queue,\n receivedAt: new Date(),\n firstMessageTimestamp: batch.messages[0]?.timestamp,\n ackAll: () => {\n ackOrRetryHandled = true;\n batch.ackAll();\n },\n retryAll: (options?: { delaySeconds?: number }) => {\n ackOrRetryHandled = true;\n batch.retryAll(options);\n }\n }\n };\n\n const typedMessages = batch.messages.map((msg) => ({\n data: msg.body,\n id: msg.id,\n timestamp: msg.timestamp,\n attempts: msg.attempts\n }));\n\n try {\n await config.processBatch(batchCtx, typedMessages as never);\n if (!ackOrRetryHandled) {\n batch.ackAll();\n }\n } catch (error) {\n await callFailureHandler(config.onFailure as HandlerLike<BatchContext<E>>, batchCtx, null, error);\n if (!ackOrRetryHandled) {\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n batch.retryAll(retryOptions);\n }\n }\n return;\n }\n\n for (const message of batch.messages) {\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = config.message.safeParse(message.body);\n if (!parsed.success) {\n throw new Error(`Queue message validation failed: ${parsed.error.message}`);\n }\n\n await config.process(queueCtx, parsed.data as never);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n config.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n message.body,\n error\n );\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\nasync function consumeMulti<E>(\n jobs: Record<string, AnyJobConfig<E>>,\n shared: { retryDelay?: Duration },\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n for (const message of batch.messages) {\n const envelope = message.body as { _job?: string; data?: unknown };\n const jobName = envelope?._job;\n\n if (!jobName || !jobs[jobName]) {\n console.error(`[better-cf] Unknown job type for queue ${batch.queue}: ${String(jobName)}`);\n message.ack();\n continue;\n }\n\n const job = jobs[jobName];\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = job.message.safeParse(envelope.data);\n if (!parsed.success) {\n throw new Error(`Queue job validation failed for ${jobName}: ${parsed.error.message}`);\n }\n await job.process(queueCtx, parsed.data);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n job.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n envelope.data,\n error\n );\n const retryOptions =\n shared.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(shared.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\ntype HandlerLike<TContext> = ((ctx: TContext, message: unknown, error: Error) => Promise<void>) | undefined;\n\nasync function callFailureHandler<TContext>(\n handler: HandlerLike<TContext>,\n context: TContext,\n message: unknown,\n rawError: unknown\n): Promise<void> {\n if (!handler) {\n return;\n }\n\n const error = rawError instanceof Error ? rawError : new Error(String(rawError));\n try {\n await handler(context, message, error);\n } catch {\n // Do not fail consume flow because failure hook failed.\n }\n}\n","import type { QueueDefinition } from './types.js';\n\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import type { z } from 'zod';\n\nexport interface BetterCfGeneratedBindings {}\n\nexport interface BetterCfAutoEnv extends BetterCfGeneratedBindings {\n [binding: string]: unknown;\n}\n\nexport type QueueEnv<E> = E & BetterCfGeneratedBindings;\n\nexport type Duration = number | `${number}s` | `${number}m` | `${number}h`;\n\nexport type ContentType = 'json' | 'text' | 'bytes' | 'v8';\n\nexport interface SendOptions {\n delay?: Duration;\n contentType?: ContentType;\n}\n\nexport type SendBatchOptions = SendOptions;\n\nexport interface SendBatchEntry<T> {\n data: T;\n delay?: Duration;\n contentType?: ContentType;\n}\n\nexport interface QueueContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n message: {\n id: string;\n timestamp: Date;\n attempts: number;\n queue: string;\n };\n}\n\nexport interface BatchContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n batch: {\n queue: string;\n receivedAt: Date;\n firstMessageTimestamp?: Date;\n ackAll: () => void;\n retryAll: (options?: { delaySeconds?: number }) => void;\n };\n}\n\nexport interface WorkerContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n}\n\nexport interface ConsumerBatchEntry<T> {\n data: T;\n id: string;\n timestamp: Date;\n attempts: number;\n}\n\nexport interface QueueCommonConfig {\n retry?: number;\n retryDelay?: Duration;\n deadLetter?: string;\n deliveryDelay?: Duration;\n visibilityTimeout?: Duration;\n batch?: {\n maxSize?: number;\n timeout?: Duration;\n maxConcurrency?: number;\n };\n}\n\nexport interface PullConsumerConfig {\n type: 'http_pull';\n visibilityTimeout?: Duration;\n}\n\nexport type QueueProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>\n) => Promise<void>;\n\nexport type QueueBatchProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: BatchContext<E>,\n messages: ConsumerBatchEntry<z.infer<TSchema>>[]\n) => Promise<void>;\n\nexport type QueueFailureHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E> | BatchContext<E>,\n message: z.infer<TSchema> | null,\n error: Error\n) => Promise<void>;\n\nexport type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process: QueueProcessHandler<E, TSchema>;\n processBatch?: never;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\nexport type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process?: never;\n processBatch: QueueBatchProcessHandler<E, TSchema>;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\nexport type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<\n QueueCommonConfig,\n 'visibilityTimeout' | 'batch'\n> & {\n message: TSchema;\n consumer: PullConsumerConfig;\n batch?: never;\n visibilityTimeout?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n};\n\nexport type QueueConfig<E, TSchema extends z.ZodTypeAny> =\n | QueueProcessConfig<E, TSchema>\n | QueueBatchConfig<E, TSchema>\n | QueuePullConfig<E, TSchema>;\n\nexport interface JobConfig<E, TSchema extends z.ZodTypeAny> {\n message: TSchema;\n process: (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;\n onFailure?: (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>,\n error: Error\n ) => Promise<void>;\n}\n\nexport type AnyJobConfig<E> = JobConfig<E, z.ZodTypeAny>;\n\nexport type ExtractJobMap<E, TConfig extends Record<string, unknown>> = {\n [K in keyof TConfig as TConfig[K] extends AnyJobConfig<E> ? K : never]: TConfig[K] extends AnyJobConfig<E>\n ? TConfig[K]\n : never;\n};\n\nexport type MultiJobQueueConfig<E, TConfig extends Record<string, unknown>> = QueueCommonConfig & {\n consumer?: never;\n} & TConfig;\n\nexport interface QueueHandle<E, TMessage> {\n send(ctx: { env: QueueEnv<E> }, data: TMessage, options?: SendOptions): Promise<void>;\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<TMessage>[],\n options?: SendBatchOptions\n ): Promise<void>;\n}\n\nexport type MultiJobQueueHandle<\n E,\n TJobs extends Record<string, AnyJobConfig<E>>\n> = {\n [K in keyof TJobs]: {\n send(\n ctx: { env: QueueEnv<E> },\n data: z.infer<TJobs[K]['message']>,\n options?: SendOptions\n ): Promise<void>;\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<z.infer<TJobs[K]['message']>>[],\n options?: SendBatchOptions\n ): Promise<void>;\n };\n};\n\nexport interface WorkerConfig<E> {\n fetch: (request: Request, ctx: WorkerContext<E>) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, ctx: WorkerContext<E>) => Promise<void>;\n}\n\nexport type AnyQueueConfig<E> = QueueConfig<E, z.ZodTypeAny>;\nexport type AnyPushQueueConfig<E> = QueueProcessConfig<E, z.ZodTypeAny> | QueueBatchConfig<E, z.ZodTypeAny>;\nexport type AnyPullQueueConfig<E> = QueuePullConfig<E, z.ZodTypeAny>;\n\nexport type AnyMultiJobQueueConfig<E> = MultiJobQueueConfig<E, Record<string, unknown>>;\n\nexport type QueueDefinition<E> =\n | { kind: 'single'; mode: 'push'; config: AnyPushQueueConfig<E> }\n | { kind: 'single'; mode: 'pull'; config: AnyPullQueueConfig<E> }\n | {\n kind: 'multi';\n jobs: Record<string, AnyJobConfig<E>>;\n shared: QueueCommonConfig;\n };\n\nexport const RESERVED_MULTI_JOB_KEYS = new Set([\n 'retry',\n 'retryDelay',\n 'deadLetter',\n 'deliveryDelay',\n 'visibilityTimeout',\n 'batch',\n 'consumer'\n]);\n","import { consumeQueueDefinition } from './consumer.js';\nimport { getQueueInternals, kQueueInternals } from './internal.js';\nimport {\n RESERVED_MULTI_JOB_KEYS,\n type AnyMultiJobQueueConfig,\n type AnyPullQueueConfig,\n type AnyPushQueueConfig,\n type ExtractJobMap,\n type JobConfig,\n type MultiJobQueueConfig,\n type MultiJobQueueHandle,\n type QueueConfig,\n type QueueDefinition,\n type QueueHandle,\n type SendBatchEntry,\n type SendBatchOptions,\n type SendOptions\n} from './types.js';\nimport { isPlainObject, mergeSendOptions, toCloudflareSendOptions } from './utils.js';\nimport type { z } from 'zod';\n\nexport function defineQueueFactory<E>() {\n function defineQueue<TSchema extends z.ZodTypeAny>(\n config: QueueConfig<E, TSchema>\n ): QueueHandle<E, z.infer<TSchema>>;\n\n function defineQueue<const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n\n function defineQueue(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n ): QueueHandle<E, unknown> | MultiJobQueueHandle<E, Record<string, JobConfig<E, z.ZodTypeAny>>> {\n const definition = toQueueDefinition(config);\n\n let bindingName: string | null = null;\n\n const sendBase = async (ctx: { env: E }, body: unknown, options?: SendOptions): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n send: (value: unknown, opts?: { delaySeconds?: number; contentType?: SendOptions['contentType'] }) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.send !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n await binding.send(body, toCloudflareSendOptions(options));\n };\n\n const sendBatchBase = async (\n ctx: { env: E },\n messages: Array<{ body: unknown; options?: SendOptions }>\n ): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n sendBatch: (entries: Array<{ body: unknown; delaySeconds?: number; contentType?: SendOptions['contentType'] }>) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.sendBatch !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n const payload = messages.map((item) => ({\n body: item.body,\n ...toCloudflareSendOptions(item.options)\n }));\n await binding.sendBatch(payload);\n };\n\n const baseHandle: Record<string | symbol, unknown> = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions): Promise<void> {\n if (definition.kind === 'single') {\n await sendBase(ctx, data, options);\n return;\n }\n\n await sendBase(ctx, { _job: '__default', data }, options);\n },\n\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ): Promise<void> {\n if (definition.kind === 'single') {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: message.data,\n options: mergeSendOptions(message, options)\n }))\n );\n return;\n }\n\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: '__default', data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n\n if (definition.kind === 'multi') {\n for (const jobName of Object.keys(definition.jobs)) {\n baseHandle[jobName] = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions) {\n await sendBase(ctx, { _job: jobName, data }, options);\n },\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ) {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: jobName, data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n }\n }\n\n Object.defineProperty(baseHandle, kQueueInternals, {\n enumerable: false,\n configurable: false,\n writable: false,\n value: {\n setBinding(name: string) {\n bindingName = name;\n },\n getBinding() {\n return bindingName;\n },\n getDefinition() {\n return definition;\n },\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext) {\n return consumeQueueDefinition(definition, batch, env, executionCtx);\n }\n }\n });\n\n return baseHandle as unknown as QueueHandle<E, unknown>;\n }\n\n return defineQueue;\n}\n\nexport function setQueueBinding<E>(handle: unknown, binding: string): void {\n getQueueInternals<E>(handle).setBinding(binding);\n}\n\nexport function readQueueDefinition<E>(handle: unknown): QueueDefinition<E> {\n return getQueueInternals<E>(handle).getDefinition();\n}\n\nfunction toQueueDefinition<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): QueueDefinition<E> {\n if (isSingleQueue(config)) {\n if (isPullQueue(config)) {\n if ('process' in config || 'processBatch' in config) {\n throw new Error('Queue config with consumer.type=\"http_pull\" cannot define process/processBatch.');\n }\n return {\n kind: 'single',\n mode: 'pull',\n config: config as AnyPullQueueConfig<E>\n };\n }\n\n if (hasProcess(config) && hasProcessBatch(config)) {\n throw new Error('Queue config cannot define both process and processBatch.');\n }\n\n if (!hasProcess(config) && !hasProcessBatch(config)) {\n throw new Error('Queue config must define one of process or processBatch in worker consumer mode.');\n }\n\n return {\n kind: 'single',\n mode: 'push',\n config: config as AnyPushQueueConfig<E>\n };\n }\n\n const shared = {\n retry: config.retry,\n retryDelay: config.retryDelay,\n deadLetter: config.deadLetter,\n deliveryDelay: config.deliveryDelay,\n visibilityTimeout: config.visibilityTimeout,\n batch: config.batch\n };\n\n const jobs: Record<string, JobConfig<E, z.ZodTypeAny>> = {};\n for (const [key, value] of Object.entries(config)) {\n if (RESERVED_MULTI_JOB_KEYS.has(key)) {\n continue;\n }\n if (isJobConfig(value)) {\n jobs[key] = value;\n }\n }\n\n if (Object.keys(jobs).length === 0) {\n throw new Error('Multi-job queue config must define at least one job.');\n }\n\n return {\n kind: 'multi',\n jobs,\n shared\n };\n}\n\nfunction isSingleQueue<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): config is QueueConfig<E, z.ZodTypeAny> {\n return 'message' in config;\n}\n\nfunction isPullQueue<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'consumer' in config && Boolean(config.consumer && config.consumer.type === 'http_pull');\n}\n\nfunction hasProcess<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'process' in config && typeof config.process === 'function';\n}\n\nfunction hasProcessBatch<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'processBatch' in config && typeof config.processBatch === 'function';\n}\n\nfunction isJobConfig<E>(value: unknown): value is JobConfig<E, z.ZodTypeAny> {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return 'message' in value && 'process' in value;\n}\n","import type { QueueEnv, WorkerConfig } from './types.js';\n\nexport function defineWorkerFactory<E>() {\n return function defineWorker(config: WorkerConfig<E>) {\n return {\n async fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response> {\n return config.fetch(request, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n },\n ...(config.scheduled\n ? {\n async scheduled(event: ScheduledEvent, env: E, executionCtx: ExecutionContext): Promise<void> {\n await config.scheduled?.(event, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n }\n }\n : {})\n };\n };\n}\n","import { defineQueueFactory } from './define-queue.js';\nimport { defineWorkerFactory } from './define-worker.js';\nimport type { BetterCfAutoEnv } from './types.js';\n\nexport function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>() {\n return {\n defineQueue: defineQueueFactory<E>(),\n defineWorker: defineWorkerFactory<E>()\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/queue/utils.ts","../../src/queue/consumer.ts","../../src/queue/internal.ts","../../src/queue/types.ts","../../src/queue/define-queue.ts","../../src/queue/define-worker.ts","../../src/queue/create-sdk.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Duration, SendOptions } from './types.js';\n\nexport function parseDurationSeconds(value: Duration): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration number: ${value}`);\n }\n return value;\n }\n\n const match = value.match(/^(\\d+)(s|m|h)$/);\n if (!match) {\n throw new Error(`Invalid duration string: ${value}`);\n }\n\n const numberValue = Number.parseInt(match[1], 10);\n const unit = match[2];\n\n if (unit === 's') {\n return numberValue;\n }\n\n if (unit === 'm') {\n return numberValue * 60;\n }\n\n return numberValue * 3600;\n}\n\nexport function mergeSendOptions(entry?: SendOptions, batch?: SendOptions): SendOptions | undefined {\n if (!entry && !batch) {\n return undefined;\n }\n\n return {\n delay: entry?.delay ?? batch?.delay,\n contentType: entry?.contentType ?? batch?.contentType\n };\n}\n\nexport function toCloudflareSendOptions(options: SendOptions | undefined): {\n delaySeconds?: number;\n contentType?: SendOptions['contentType'];\n} {\n if (!options) {\n return {};\n }\n\n const result: { delaySeconds?: number; contentType?: SendOptions['contentType'] } = {};\n\n if (options.delay !== undefined) {\n result.delaySeconds = parseDurationSeconds(options.delay);\n }\n\n if (options.contentType !== undefined) {\n result.contentType = options.contentType;\n }\n\n return result;\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { parseDurationSeconds } from './utils.js';\nimport type {\n AnyJobConfig,\n AnyPushQueueConfig,\n BatchContext,\n Duration,\n QueueContext,\n QueueDefinition,\n QueueEnv\n} from './types.js';\n\nexport async function consumeQueueDefinition<E>(\n definition: QueueDefinition<E>,\n batch: MessageBatch<unknown>,\n env: E,\n executionCtx: ExecutionContext\n): Promise<void> {\n if (definition.kind === 'single') {\n if (definition.mode === 'pull') {\n console.warn(\n `[better-cf] Queue \"${batch.queue}\" configured as http_pull. Worker queue handler is disabled; acking batch.`\n );\n batch.ackAll();\n return;\n }\n\n await consumeSingle(definition.config, batch, env as QueueEnv<E>, executionCtx);\n return;\n }\n\n await consumeMulti(definition.jobs, definition.shared, batch, env as QueueEnv<E>, executionCtx);\n}\n\nasync function consumeSingle<E>(\n config: AnyPushQueueConfig<E>,\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n if ('processBatch' in config && config.processBatch) {\n let ackOrRetryHandled = false;\n const batchCtx: BatchContext<E> = {\n env,\n executionCtx,\n batch: {\n queue: batch.queue,\n receivedAt: new Date(),\n firstMessageTimestamp: batch.messages[0]?.timestamp,\n ackAll: () => {\n ackOrRetryHandled = true;\n batch.ackAll();\n },\n retryAll: (options?: { delaySeconds?: number }) => {\n ackOrRetryHandled = true;\n batch.retryAll(options);\n }\n }\n };\n\n const typedMessages = batch.messages.map((msg) => ({\n data: msg.body,\n id: msg.id,\n timestamp: msg.timestamp,\n attempts: msg.attempts\n }));\n\n try {\n await config.processBatch(batchCtx, typedMessages as never);\n if (!ackOrRetryHandled) {\n batch.ackAll();\n }\n } catch (error) {\n await callFailureHandler(config.onFailure as HandlerLike<BatchContext<E>>, batchCtx, null, error);\n if (!ackOrRetryHandled) {\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n batch.retryAll(retryOptions);\n }\n }\n return;\n }\n\n for (const message of batch.messages) {\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = config.message.safeParse(message.body);\n if (!parsed.success) {\n throw new Error(`Queue message validation failed: ${parsed.error.message}`);\n }\n\n await config.process(queueCtx, parsed.data as never);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n config.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n message.body,\n error\n );\n const retryOptions =\n config.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(config.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\nasync function consumeMulti<E>(\n jobs: Record<string, AnyJobConfig<E>>,\n shared: { retryDelay?: Duration },\n batch: MessageBatch<unknown>,\n env: QueueEnv<E>,\n executionCtx: ExecutionContext\n): Promise<void> {\n for (const message of batch.messages) {\n const envelope = message.body as { _job?: string; data?: unknown };\n const jobName = envelope?._job;\n\n if (!jobName || !jobs[jobName]) {\n console.error(`[better-cf] Unknown job type for queue ${batch.queue}: ${String(jobName)}`);\n message.ack();\n continue;\n }\n\n const job = jobs[jobName];\n const queueCtx: QueueContext<E> = {\n env,\n executionCtx,\n message: {\n id: message.id,\n timestamp: message.timestamp,\n attempts: message.attempts,\n queue: batch.queue\n }\n };\n\n try {\n const parsed = job.message.safeParse(envelope.data);\n if (!parsed.success) {\n throw new Error(`Queue job validation failed for ${jobName}: ${parsed.error.message}`);\n }\n await job.process(queueCtx, parsed.data);\n message.ack();\n } catch (error) {\n await callFailureHandler(\n job.onFailure as HandlerLike<QueueContext<E>>,\n queueCtx,\n envelope.data,\n error\n );\n const retryOptions =\n shared.retryDelay !== undefined\n ? { delaySeconds: parseDurationSeconds(shared.retryDelay) }\n : undefined;\n message.retry(retryOptions);\n }\n }\n}\n\ntype HandlerLike<TContext> = ((ctx: TContext, message: unknown, error: Error) => Promise<void>) | undefined;\n\nasync function callFailureHandler<TContext>(\n handler: HandlerLike<TContext>,\n context: TContext,\n message: unknown,\n rawError: unknown\n): Promise<void> {\n if (!handler) {\n return;\n }\n\n const error = rawError instanceof Error ? rawError : new Error(String(rawError));\n try {\n await handler(context, message, error);\n } catch {\n // Do not fail consume flow because failure hook failed.\n }\n}\n","import type { QueueDefinition } from './types.js';\n\n/**\n * Symbol used to store non-enumerable queue internals on queue handles.\n */\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\n/**\n * Internal queue API used by runtime/testing/CLI internals.\n */\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\n/**\n * Reads internal queue metadata from a queue handle.\n */\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\n/**\n * Input module shape accepted when resolving worker handlers.\n */\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\n/**\n * Normalized handler pair resolved from a worker module export.\n */\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Resolves `fetch`/`scheduled` handlers from various worker export styles.\n */\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import type { z } from 'zod';\n\n/**\n * Marker interface that generated env bindings extend.\n */\nexport interface BetterCfGeneratedBindings {}\n\n/**\n * Default env type used when `createSDK()` is called without a generic.\n */\nexport interface BetterCfAutoEnv extends BetterCfGeneratedBindings {\n [binding: string]: unknown;\n}\n\n/**\n * Runtime env shape available inside queue and worker handlers.\n */\nexport type QueueEnv<E> = E & BetterCfGeneratedBindings;\n\n/**\n * Duration in seconds/minutes/hours shorthand or raw seconds.\n */\nexport type Duration = number | `${number}s` | `${number}m` | `${number}h`;\n\n/**\n * Cloudflare Queue message content type.\n */\nexport type ContentType = 'json' | 'text' | 'bytes' | 'v8';\n\n/**\n * Per-message send options.\n */\nexport interface SendOptions {\n /** Delay before message becomes visible to consumers. */\n delay?: Duration;\n /** Explicit content type for Cloudflare queue delivery. */\n contentType?: ContentType;\n}\n\n/**\n * Shared send options for `sendBatch`.\n */\nexport type SendBatchOptions = SendOptions;\n\n/**\n * Per-message input for `sendBatch`.\n */\nexport interface SendBatchEntry<T> {\n data: T;\n delay?: Duration;\n contentType?: ContentType;\n}\n\n/**\n * Context passed to per-message queue consumers.\n */\nexport interface QueueContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n message: {\n id: string;\n timestamp: Date;\n attempts: number;\n queue: string;\n };\n}\n\n/**\n * Context passed to batch queue consumers.\n */\nexport interface BatchContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n batch: {\n queue: string;\n receivedAt: Date;\n firstMessageTimestamp?: Date;\n ackAll: () => void;\n retryAll: (options?: { delaySeconds?: number }) => void;\n };\n}\n\n/**\n * Context passed to worker handlers.\n */\nexport interface WorkerContext<E> {\n env: QueueEnv<E>;\n executionCtx: ExecutionContext;\n}\n\n/**\n * Message shape received by batch consumers.\n */\nexport interface ConsumerBatchEntry<T> {\n data: T;\n id: string;\n timestamp: Date;\n attempts: number;\n}\n\n/**\n * Queue settings shared across worker-consumer and pull-consumer modes.\n */\nexport interface QueueCommonConfig {\n /** Number of retry attempts before dead-lettering. */\n retry?: number;\n /** Delay between retries. */\n retryDelay?: Duration;\n /** Dead-letter queue name. */\n deadLetter?: string;\n /** Delivery delay applied to newly sent messages. */\n deliveryDelay?: Duration;\n /** Message visibility timeout (worker consumer mode only). */\n visibilityTimeout?: Duration;\n /** Batch processing tuning (worker consumer mode only). */\n batch?: {\n maxSize?: number;\n timeout?: Duration;\n maxConcurrency?: number;\n };\n}\n\n/**\n * Pull consumer mode configuration.\n */\nexport interface PullConsumerConfig {\n /** Pull mode marker. */\n type: 'http_pull';\n /** Pull visibility timeout in seconds. */\n visibilityTimeout?: Duration;\n}\n\n/**\n * Per-message queue handler.\n */\nexport type QueueProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>\n) => Promise<void>;\n\n/**\n * Batch queue handler.\n */\nexport type QueueBatchProcessHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: BatchContext<E>,\n messages: ConsumerBatchEntry<z.infer<TSchema>>[]\n) => Promise<void>;\n\n/**\n * Optional failure handler for queue processing.\n */\nexport type QueueFailureHandler<E, TSchema extends z.ZodTypeAny> = (\n ctx: QueueContext<E> | BatchContext<E>,\n message: z.infer<TSchema> | null,\n error: Error\n) => Promise<void>;\n\n/**\n * Worker-consumer queue with per-message processing.\n */\nexport type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process: QueueProcessHandler<E, TSchema>;\n processBatch?: never;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\n/**\n * Worker-consumer queue with batch processing.\n */\nexport type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {\n message: TSchema;\n consumer?: { type?: 'worker' };\n process?: never;\n processBatch: QueueBatchProcessHandler<E, TSchema>;\n onFailure?: QueueFailureHandler<E, TSchema>;\n};\n\n/**\n * HTTP pull consumer queue (producer-only declaration).\n */\nexport type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<\n QueueCommonConfig,\n 'visibilityTimeout' | 'batch'\n> & {\n message: TSchema;\n consumer: PullConsumerConfig;\n batch?: never;\n visibilityTimeout?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n};\n\n/**\n * Single-queue config union for worker and pull consumer modes.\n */\nexport type QueueConfig<E, TSchema extends z.ZodTypeAny> =\n | QueueProcessConfig<E, TSchema>\n | QueueBatchConfig<E, TSchema>\n | QueuePullConfig<E, TSchema>;\n\n/**\n * Per-job declaration inside a multi-job queue.\n */\nexport interface JobConfig<E, TSchema extends z.ZodTypeAny> {\n message: TSchema;\n process: (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;\n onFailure?: (\n ctx: QueueContext<E>,\n message: z.infer<TSchema>,\n error: Error\n ) => Promise<void>;\n}\n\n/**\n * Internal helper alias for any job config.\n */\nexport type AnyJobConfig<E> = JobConfig<E, z.ZodTypeAny>;\n\n/**\n * Extracts only job keys from a multi-job config object.\n */\nexport type ExtractJobMap<E, TConfig extends Record<string, unknown>> = {\n [K in keyof TConfig as TConfig[K] extends AnyJobConfig<E> ? K : never]: TConfig[K] extends AnyJobConfig<E>\n ? TConfig[K]\n : never;\n};\n\n/**\n * Multi-job queue declaration object.\n */\nexport type MultiJobQueueConfig<E, TConfig extends Record<string, unknown>> = QueueCommonConfig & {\n consumer?: never;\n message?: never;\n process?: never;\n processBatch?: never;\n onFailure?: never;\n} & TConfig;\n\n/**\n * Producer handle for a single queue declaration.\n */\nexport interface QueueHandle<E, TMessage> {\n /** Sends one message to the queue. */\n send(ctx: { env: QueueEnv<E> }, data: TMessage, options?: SendOptions): Promise<void>;\n /** Sends multiple messages in one request. */\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<TMessage>[],\n options?: SendBatchOptions\n ): Promise<void>;\n}\n\n/**\n * Producer handles keyed by job name for a multi-job queue.\n */\nexport type MultiJobQueueHandle<\n E,\n TJobs extends Record<string, AnyJobConfig<E>>\n> = {\n [K in keyof TJobs]: {\n /** Sends one message to a named job. */\n send(\n ctx: { env: QueueEnv<E> },\n data: z.infer<TJobs[K]['message']>,\n options?: SendOptions\n ): Promise<void>;\n /** Sends many messages to a named job. */\n sendBatch(\n ctx: { env: QueueEnv<E> },\n messages: SendBatchEntry<z.infer<TJobs[K]['message']>>[],\n options?: SendBatchOptions\n ): Promise<void>;\n };\n};\n\n/**\n * Worker handlers used to define module exports.\n */\nexport interface WorkerConfig<E> {\n /** Main fetch handler. */\n fetch: (request: Request, ctx: WorkerContext<E>) => Promise<Response>;\n /** Optional scheduled handler. */\n scheduled?: (event: ScheduledEvent, ctx: WorkerContext<E>) => Promise<void>;\n}\n\n/**\n * Worker module shape returned by `defineWorker`.\n */\nexport interface WorkerEntrypoint<E> {\n fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: E, executionCtx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Defines a worker module with typed queue-aware context.\n */\nexport type DefineWorker<E> = (config: WorkerConfig<E>) => WorkerEntrypoint<E>;\n\n/**\n * Defines queue contracts and returns typed producer handles.\n */\nexport interface DefineQueue<E> {\n /**\n * Declare a single queue (worker consumer or http pull consumer).\n *\n * @example\n * defineQueue({\n * message: z.object({ id: z.string() }),\n * process: async (ctx, message) => {}\n * })\n */\n <TSchema extends z.ZodTypeAny>(config: QueueConfig<E, TSchema>): QueueHandle<E, z.infer<TSchema>>;\n\n /**\n * Declare a multi-job queue where each top-level key is a job definition.\n *\n * @example\n * defineQueue({\n * email: { message: z.object({ to: z.string() }), process: async () => {} },\n * audit: { message: z.object({ id: z.string() }), process: async () => {} }\n * })\n */\n <const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n}\n\n/**\n * SDK helpers returned by `createSDK`.\n */\nexport interface BetterCfSDK<E> {\n /** Queue declaration helper with schema-inferred producer types. */\n defineQueue: DefineQueue<E>;\n /** Worker declaration helper that maps to Cloudflare module handlers. */\n defineWorker: DefineWorker<E>;\n}\n\n/**\n * Internal helper alias for any queue config mode.\n */\nexport type AnyQueueConfig<E> = QueueConfig<E, z.ZodTypeAny>;\n/**\n * Internal helper alias for worker-consumer queue modes.\n */\nexport type AnyPushQueueConfig<E> = QueueProcessConfig<E, z.ZodTypeAny> | QueueBatchConfig<E, z.ZodTypeAny>;\n/**\n * Internal helper alias for pull-consumer queue mode.\n */\nexport type AnyPullQueueConfig<E> = QueuePullConfig<E, z.ZodTypeAny>;\n\n/**\n * Internal helper alias for any multi-job queue config.\n */\nexport type AnyMultiJobQueueConfig<E> = MultiJobQueueConfig<E, Record<string, unknown>>;\n\n/**\n * Normalized queue definition used by runtime internals.\n */\nexport type QueueDefinition<E> =\n | { kind: 'single'; mode: 'push'; config: AnyPushQueueConfig<E> }\n | { kind: 'single'; mode: 'pull'; config: AnyPullQueueConfig<E> }\n | {\n kind: 'multi';\n jobs: Record<string, AnyJobConfig<E>>;\n shared: QueueCommonConfig;\n };\n\n/**\n * Reserved top-level keys treated as shared config in multi-job mode.\n */\nexport const RESERVED_MULTI_JOB_KEYS = new Set([\n 'retry',\n 'retryDelay',\n 'deadLetter',\n 'deliveryDelay',\n 'visibilityTimeout',\n 'batch',\n 'consumer'\n]);\n","import { consumeQueueDefinition } from './consumer.js';\nimport { getQueueInternals, kQueueInternals } from './internal.js';\nimport {\n RESERVED_MULTI_JOB_KEYS,\n type AnyMultiJobQueueConfig,\n type AnyPullQueueConfig,\n type AnyPushQueueConfig,\n type ExtractJobMap,\n type DefineQueue,\n type JobConfig,\n type MultiJobQueueConfig,\n type MultiJobQueueHandle,\n type QueueConfig,\n type QueueDefinition,\n type QueueHandle,\n type SendBatchEntry,\n type SendBatchOptions,\n type SendOptions\n} from './types.js';\nimport { isPlainObject, mergeSendOptions, toCloudflareSendOptions } from './utils.js';\nimport type { z } from 'zod';\n\n/**\n * Creates a typed `defineQueue` helper bound to the SDK env generic.\n */\nexport function defineQueueFactory<E>(): DefineQueue<E> {\n /**\n * Declare a single queue contract.\n */\n function defineQueue<TSchema extends z.ZodTypeAny>(\n config: QueueConfig<E, TSchema>\n ): QueueHandle<E, z.infer<TSchema>>;\n\n /**\n * Declare a multi-job queue contract.\n */\n function defineQueue<const TConfig extends Record<string, unknown>>(\n config: MultiJobQueueConfig<E, TConfig>\n ): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;\n\n function defineQueue(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n ): QueueHandle<E, unknown> | MultiJobQueueHandle<E, Record<string, JobConfig<E, z.ZodTypeAny>>> {\n const definition = toQueueDefinition(config);\n\n let bindingName: string | null = null;\n\n const sendBase = async (ctx: { env: E }, body: unknown, options?: SendOptions): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n send: (value: unknown, opts?: { delaySeconds?: number; contentType?: SendOptions['contentType'] }) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.send !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n await binding.send(body, toCloudflareSendOptions(options));\n };\n\n const sendBatchBase = async (\n ctx: { env: E },\n messages: Array<{ body: unknown; options?: SendOptions }>\n ): Promise<void> => {\n if (!bindingName) {\n throw new Error(\n 'Queue binding not initialized. Run through better-cf dev/generate/deploy generated entry.'\n );\n }\n\n const binding = (ctx.env as Record<string, unknown>)[bindingName] as\n | {\n sendBatch: (entries: Array<{ body: unknown; delaySeconds?: number; contentType?: SendOptions['contentType'] }>) => Promise<void>;\n }\n | undefined;\n\n if (!binding || typeof binding.sendBatch !== 'function') {\n throw new Error(`Queue binding ${bindingName} not found in env.`);\n }\n\n const payload = messages.map((item) => ({\n body: item.body,\n ...toCloudflareSendOptions(item.options)\n }));\n await binding.sendBatch(payload);\n };\n\n const baseHandle: Record<string | symbol, unknown> = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions): Promise<void> {\n if (definition.kind === 'single') {\n await sendBase(ctx, data, options);\n return;\n }\n\n await sendBase(ctx, { _job: '__default', data }, options);\n },\n\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ): Promise<void> {\n if (definition.kind === 'single') {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: message.data,\n options: mergeSendOptions(message, options)\n }))\n );\n return;\n }\n\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: '__default', data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n\n if (definition.kind === 'multi') {\n for (const jobName of Object.keys(definition.jobs)) {\n baseHandle[jobName] = {\n async send(ctx: { env: E }, data: unknown, options?: SendOptions) {\n await sendBase(ctx, { _job: jobName, data }, options);\n },\n async sendBatch(\n ctx: { env: E },\n messages: SendBatchEntry<unknown>[],\n options?: SendBatchOptions\n ) {\n await sendBatchBase(\n ctx,\n messages.map((message) => ({\n body: { _job: jobName, data: message.data },\n options: mergeSendOptions(message, options)\n }))\n );\n }\n };\n }\n }\n\n Object.defineProperty(baseHandle, kQueueInternals, {\n enumerable: false,\n configurable: false,\n writable: false,\n value: {\n setBinding(name: string) {\n bindingName = name;\n },\n getBinding() {\n return bindingName;\n },\n getDefinition() {\n return definition;\n },\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext) {\n return consumeQueueDefinition(definition, batch, env, executionCtx);\n }\n }\n });\n\n return baseHandle as unknown as QueueHandle<E, unknown>;\n }\n\n return defineQueue;\n}\n\n/**\n * Attaches the generated Cloudflare binding name to a queue handle.\n */\nexport function setQueueBinding<E>(handle: unknown, binding: string): void {\n getQueueInternals<E>(handle).setBinding(binding);\n}\n\n/**\n * Reads normalized queue metadata from a queue handle.\n */\nexport function readQueueDefinition<E>(handle: unknown): QueueDefinition<E> {\n return getQueueInternals<E>(handle).getDefinition();\n}\n\nfunction toQueueDefinition<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): QueueDefinition<E> {\n if (isSingleQueue(config)) {\n if (isPullQueue(config)) {\n if ('process' in config || 'processBatch' in config) {\n throw new Error('Queue config with consumer.type=\"http_pull\" cannot define process/processBatch.');\n }\n return {\n kind: 'single',\n mode: 'pull',\n config: config as AnyPullQueueConfig<E>\n };\n }\n\n if (hasProcess(config) && hasProcessBatch(config)) {\n throw new Error('Queue config cannot define both process and processBatch.');\n }\n\n if (!hasProcess(config) && !hasProcessBatch(config)) {\n throw new Error('Queue config must define one of process or processBatch in worker consumer mode.');\n }\n\n return {\n kind: 'single',\n mode: 'push',\n config: config as AnyPushQueueConfig<E>\n };\n }\n\n const shared = {\n retry: config.retry,\n retryDelay: config.retryDelay,\n deadLetter: config.deadLetter,\n deliveryDelay: config.deliveryDelay,\n visibilityTimeout: config.visibilityTimeout,\n batch: config.batch\n };\n\n const jobs: Record<string, JobConfig<E, z.ZodTypeAny>> = {};\n for (const [key, value] of Object.entries(config)) {\n if (RESERVED_MULTI_JOB_KEYS.has(key)) {\n continue;\n }\n if (isJobConfig(value)) {\n jobs[key] = value;\n }\n }\n\n if (Object.keys(jobs).length === 0) {\n throw new Error('Multi-job queue config must define at least one job.');\n }\n\n return {\n kind: 'multi',\n jobs,\n shared\n };\n}\n\nfunction isSingleQueue<E>(\n config: QueueConfig<E, z.ZodTypeAny> | AnyMultiJobQueueConfig<E>\n): config is QueueConfig<E, z.ZodTypeAny> {\n return 'message' in config;\n}\n\nfunction isPullQueue<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'consumer' in config && Boolean(config.consumer && config.consumer.type === 'http_pull');\n}\n\nfunction hasProcess<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'process' in config && typeof config.process === 'function';\n}\n\nfunction hasProcessBatch<E>(config: QueueConfig<E, z.ZodTypeAny>): boolean {\n return 'processBatch' in config && typeof config.processBatch === 'function';\n}\n\nfunction isJobConfig<E>(value: unknown): value is JobConfig<E, z.ZodTypeAny> {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return 'message' in value && 'process' in value;\n}\n","import type { DefineWorker, QueueEnv, WorkerConfig, WorkerEntrypoint } from './types.js';\n\n/**\n * Creates a typed `defineWorker` helper bound to the SDK env generic.\n */\nexport function defineWorkerFactory<E>(): DefineWorker<E> {\n return function defineWorker(config: WorkerConfig<E>): WorkerEntrypoint<E> {\n return {\n async fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response> {\n return config.fetch(request, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n },\n ...(config.scheduled\n ? {\n async scheduled(event: ScheduledEvent, env: E, executionCtx: ExecutionContext): Promise<void> {\n await config.scheduled?.(event, {\n env: env as QueueEnv<E>,\n executionCtx\n });\n }\n }\n : {})\n };\n };\n}\n","import { defineQueueFactory } from './define-queue.js';\nimport { defineWorkerFactory } from './define-worker.js';\nimport type { BetterCfAutoEnv, BetterCfSDK } from './types.js';\n\n/**\n * Creates typed queue + worker helpers for your Cloudflare Worker app.\n *\n * @example\n * const { defineQueue, defineWorker } = createSDK<Env>();\n */\nexport function createSDK<E extends Record<string, unknown> = BetterCfAutoEnv>(): BetterCfSDK<E> {\n return {\n defineQueue: defineQueueFactory<E>(),\n defineWorker: defineWorkerFactory<E>()\n };\n}\n"]}
@@ -1,7 +1,13 @@
1
- import { Q as QueueDefinition } from '../types-BAZ_wtox.js';
1
+ import { Q as QueueDefinition } from '../types-D44i92Zf.js';
2
2
  import 'zod';
3
3
 
4
+ /**
5
+ * Symbol used to store non-enumerable queue internals on queue handles.
6
+ */
4
7
  declare const kQueueInternals: unique symbol;
8
+ /**
9
+ * Internal queue API used by runtime/testing/CLI internals.
10
+ */
5
11
  interface QueueInternalApi<E> {
6
12
  setBinding(name: string): void;
7
13
  getBinding(): string | null;
@@ -11,16 +17,28 @@ interface QueueInternalApi<E> {
11
17
  type QueueWithInternals<E> = {
12
18
  [kQueueInternals]: QueueInternalApi<E>;
13
19
  };
20
+ /**
21
+ * Reads internal queue metadata from a queue handle.
22
+ */
14
23
  declare function getQueueInternals<E>(value: unknown): QueueInternalApi<E>;
24
+ /**
25
+ * Input module shape accepted when resolving worker handlers.
26
+ */
15
27
  interface WorkerModuleLike {
16
28
  default?: unknown;
17
29
  fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;
18
30
  scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;
19
31
  }
32
+ /**
33
+ * Normalized handler pair resolved from a worker module export.
34
+ */
20
35
  interface ResolvedWorkerHandlers {
21
36
  fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;
22
37
  scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;
23
38
  }
39
+ /**
40
+ * Resolves `fetch`/`scheduled` handlers from various worker export styles.
41
+ */
24
42
  declare function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers;
25
43
 
26
44
  export { type QueueInternalApi, type QueueWithInternals, type ResolvedWorkerHandlers, type WorkerModuleLike, getQueueInternals, kQueueInternals, resolveWorkerHandlers };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queue/internal.ts"],"names":[],"mappings":";AAEO,IAAM,eAAA,mBAAkB,MAAA,CAAO,GAAA,CAAI,2BAA2B;AAa9D,SAAS,kBAAqB,KAAA,EAAqC;AACxE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,SAAA,GAAa,MAAgC,eAAe,CAAA;AAClE,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,OAAO,SAAA;AACT;AAiBO,SAAS,sBAAsB,UAAA,EAAsD;AAC1F,EAAA,MAAM,IAAA,GAAO,WAAW,OAAA,IAAW,UAAA;AAEnC,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB,WAAW,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,WAAW,IAAA,EAAM;AAC9D,IAAA,MAAM,aAAc,IAAA,CAA6B,KAAA;AACjD,IAAA,IAAI,OAAO,eAAe,UAAA,EAAY;AACpC,MAAA,YAAA,GAAe,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,YAAA,IAAgB,OAAO,UAAA,CAAW,UAAU,UAAA,EAAY;AAC3D,IAAA,YAAA,GAAe,UAAA,CAAW,KAAA;AAAA,EAC5B;AAEA,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,eAAe,IAAA,EAAM;AAC3D,IAAA,MAAM,iBAAkB,IAAA,CAAiC,SAAA;AACzD,IAAA,IAAI,OAAO,mBAAmB,UAAA,EAAY;AACxC,MAAA,gBAAA,GAAmB,cAAA,CAAe,KAAK,IAAI,CAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,gBAAA,IAAoB,OAAO,UAAA,CAAW,cAAc,UAAA,EAAY;AACnE,IAAA,gBAAA,GAAmB,UAAA,CAAW,SAAA;AAAA,EAChC;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,YAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AACF","file":"internal.js","sourcesContent":["import type { QueueDefinition } from './types.js';\n\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/queue/internal.ts"],"names":[],"mappings":";AAKO,IAAM,eAAA,mBAAkB,MAAA,CAAO,GAAA,CAAI,2BAA2B;AAmB9D,SAAS,kBAAqB,KAAA,EAAqC;AACxE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,SAAA,GAAa,MAAgC,eAAe,CAAA;AAClE,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,OAAO,SAAA;AACT;AA0BO,SAAS,sBAAsB,UAAA,EAAsD;AAC1F,EAAA,MAAM,IAAA,GAAO,WAAW,OAAA,IAAW,UAAA;AAEnC,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB,WAAW,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,WAAW,IAAA,EAAM;AAC9D,IAAA,MAAM,aAAc,IAAA,CAA6B,KAAA;AACjD,IAAA,IAAI,OAAO,eAAe,UAAA,EAAY;AACpC,MAAA,YAAA,GAAe,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,YAAA,IAAgB,OAAO,UAAA,CAAW,UAAU,UAAA,EAAY;AAC3D,IAAA,YAAA,GAAe,UAAA,CAAW,KAAA;AAAA,EAC5B;AAEA,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,eAAe,IAAA,EAAM;AAC3D,IAAA,MAAM,iBAAkB,IAAA,CAAiC,SAAA;AACzD,IAAA,IAAI,OAAO,mBAAmB,UAAA,EAAY;AACxC,MAAA,gBAAA,GAAmB,cAAA,CAAe,KAAK,IAAI,CAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,gBAAA,IAAoB,OAAO,UAAA,CAAW,cAAc,UAAA,EAAY;AACnE,IAAA,gBAAA,GAAmB,UAAA,CAAW,SAAA;AAAA,EAChC;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,YAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AACF","file":"internal.js","sourcesContent":["import type { QueueDefinition } from './types.js';\n\n/**\n * Symbol used to store non-enumerable queue internals on queue handles.\n */\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\n/**\n * Internal queue API used by runtime/testing/CLI internals.\n */\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\n/**\n * Reads internal queue metadata from a queue handle.\n */\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\n/**\n * Input module shape accepted when resolving worker handlers.\n */\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\n/**\n * Normalized handler pair resolved from a worker module export.\n */\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Resolves `fetch`/`scheduled` handlers from various worker export styles.\n */\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n"]}
@@ -1,13 +1,35 @@
1
- interface TestQueueOptions<E, TMessage> {
1
+ /**
2
+ * Options for queue consumer tests.
3
+ */
4
+ interface TestQueueBaseOptions<E> {
2
5
  env: E;
3
- message?: TMessage;
4
- messages?: TMessage[];
6
+ /** Overrides message attempts metadata. */
5
7
  attempts?: number;
6
8
  }
9
+ /**
10
+ * Options for queue consumer tests.
11
+ */
12
+ type TestQueueOptions<E, TMessage> = (TestQueueBaseOptions<E> & {
13
+ /** Test one message. */
14
+ message: TMessage;
15
+ messages?: never;
16
+ }) | (TestQueueBaseOptions<E> & {
17
+ /** Test many messages in one batch. */
18
+ messages: TMessage[];
19
+ message?: never;
20
+ });
21
+ /**
22
+ * Test execution result for queue consumers.
23
+ */
7
24
  interface TestQueueResult<TMessage> {
25
+ /** Messages acked by the consumer. */
8
26
  acked: TMessage[];
27
+ /** Messages retried by the consumer. */
9
28
  retried: TMessage[];
10
29
  }
30
+ /**
31
+ * Runs a queue declaration's consumer logic in-memory for tests.
32
+ */
11
33
  declare function testQueue<E, TMessage>(handle: unknown, options: TestQueueOptions<E, TMessage>): Promise<TestQueueResult<TMessage>>;
12
34
 
13
35
  export { type TestQueueOptions, type TestQueueResult, testQueue };
@@ -14,6 +14,9 @@ function getQueueInternals(value) {
14
14
  // src/testing/index.ts
15
15
  async function testQueue(handle, options) {
16
16
  const internals = getQueueInternals(handle);
17
+ if ("message" in options && "messages" in options) {
18
+ throw new Error("testQueue accepts either message or messages, not both.");
19
+ }
17
20
  const allMessages = options.messages ?? (options.message !== void 0 ? [options.message] : []);
18
21
  if (allMessages.length === 0) {
19
22
  throw new Error("testQueue requires message or messages.");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queue/internal.ts","../../src/testing/index.ts"],"names":[],"mappings":";AAEO,IAAM,eAAA,mBAAkB,MAAA,CAAO,GAAA,CAAI,2BAA2B,CAAA;AAa9D,SAAS,kBAAqB,KAAA,EAAqC;AACxE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,SAAA,GAAa,MAAgC,eAAe,CAAA;AAClE,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,OAAO,SAAA;AACT;;;ACZA,eAAsB,SAAA,CACpB,QACA,OAAA,EACoC;AACpC,EAAA,MAAM,SAAA,GAAY,kBAAqB,MAAM,CAAA;AAE7C,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,QAAA,KAAa,OAAA,CAAQ,OAAA,KAAY,SAAY,CAAC,OAAA,CAAQ,OAAO,CAAA,GAAI,EAAC,CAAA;AAC9F,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,MAAM,MAAA,GAAoC;AAAA,IACxC,OAAO,EAAC;AAAA,IACR,SAAS;AAAC,GACZ;AAEA,EAAA,MAAM,KAAA,GAA+B;AAAA,IACnC,KAAA,EAAO,YAAA;AAAA,IACP,QAAA,EAAU,WAAA,CAAY,GAAA,CAAI,CAAC,MAAM,KAAA,MAAW;AAAA,MAC1C,EAAA,EAAI,OAAO,KAAK,CAAA,CAAA;AAAA,MAChB,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,IAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAA,IAAY,CAAA;AAAA,MAC9B,KAAK,MAAM;AACT,QAAA,MAAA,CAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,MACxB,CAAA;AAAA,MACA,OAAO,MAAM;AACX,QAAA,MAAA,CAAO,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,MAC1B;AAAA,KACF,CAAE,CAAA;AAAA,IACF,QAAQ,MAAM;AACZ,MAAA,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,GAAG,WAAW,CAAA;AAAA,IAClC,CAAA;AAAA,IACA,UAAU,MAAM;AACd,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,WAAW,CAAA;AAAA,IACpC;AAAA,GACF;AAEA,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,SAAA,GAAY;AACV,MAAA;AAAA,IACF,CAAA;AAAA,IACA,sBAAA,GAAyB;AACvB,MAAA;AAAA,IACF,CAAA;AAAA,IACA,OAAO;AAAC,GACV;AAEA,EAAA,MAAM,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,KAAK,YAAY,CAAA;AAExD,EAAA,OAAO,MAAA;AACT","file":"index.js","sourcesContent":["import type { QueueDefinition } from './types.js';\n\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import { getQueueInternals } from '../queue/internal.js';\n\nexport interface TestQueueOptions<E, TMessage> {\n env: E;\n message?: TMessage;\n messages?: TMessage[];\n attempts?: number;\n}\n\nexport interface TestQueueResult<TMessage> {\n acked: TMessage[];\n retried: TMessage[];\n}\n\nexport async function testQueue<E, TMessage>(\n handle: unknown,\n options: TestQueueOptions<E, TMessage>\n): Promise<TestQueueResult<TMessage>> {\n const internals = getQueueInternals<E>(handle);\n\n const allMessages = options.messages ?? (options.message !== undefined ? [options.message] : []);\n if (allMessages.length === 0) {\n throw new Error('testQueue requires message or messages.');\n }\n\n const result: TestQueueResult<TMessage> = {\n acked: [],\n retried: []\n };\n\n const batch: MessageBatch<unknown> = {\n queue: 'test-queue',\n messages: allMessages.map((body, index) => ({\n id: `msg-${index}`,\n timestamp: new Date(),\n body,\n attempts: options.attempts ?? 1,\n ack: () => {\n result.acked.push(body);\n },\n retry: () => {\n result.retried.push(body);\n }\n })),\n ackAll: () => {\n result.acked.push(...allMessages);\n },\n retryAll: () => {\n result.retried.push(...allMessages);\n }\n };\n\n const executionCtx = {\n waitUntil() {\n return;\n },\n passThroughOnException() {\n return;\n },\n props: {}\n } as unknown as ExecutionContext;\n\n await internals.consume(batch, options.env, executionCtx);\n\n return result;\n}\n"]}
1
+ {"version":3,"sources":["../../src/queue/internal.ts","../../src/testing/index.ts"],"names":[],"mappings":";AAKO,IAAM,eAAA,mBAAkB,MAAA,CAAO,GAAA,CAAI,2BAA2B,CAAA;AAmB9D,SAAS,kBAAqB,KAAA,EAAqC;AACxE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,SAAA,GAAa,MAAgC,eAAe,CAAA;AAClE,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,OAAO,SAAA;AACT;;;ACIA,eAAsB,SAAA,CACpB,QACA,OAAA,EACoC;AACpC,EAAA,MAAM,SAAA,GAAY,kBAAqB,MAAM,CAAA;AAE7C,EAAA,IAAI,SAAA,IAAa,OAAA,IAAW,UAAA,IAAc,OAAA,EAAS;AACjD,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC3E;AAEA,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,QAAA,KAAa,OAAA,CAAQ,OAAA,KAAY,SAAY,CAAC,OAAA,CAAQ,OAAO,CAAA,GAAI,EAAC,CAAA;AAC9F,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,MAAM,MAAA,GAAoC;AAAA,IACxC,OAAO,EAAC;AAAA,IACR,SAAS;AAAC,GACZ;AAEA,EAAA,MAAM,KAAA,GAA+B;AAAA,IACnC,KAAA,EAAO,YAAA;AAAA,IACP,QAAA,EAAU,WAAA,CAAY,GAAA,CAAI,CAAC,MAAM,KAAA,MAAW;AAAA,MAC1C,EAAA,EAAI,OAAO,KAAK,CAAA,CAAA;AAAA,MAChB,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,IAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAA,IAAY,CAAA;AAAA,MAC9B,KAAK,MAAM;AACT,QAAA,MAAA,CAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,MACxB,CAAA;AAAA,MACA,OAAO,MAAM;AACX,QAAA,MAAA,CAAO,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,MAC1B;AAAA,KACF,CAAE,CAAA;AAAA,IACF,QAAQ,MAAM;AACZ,MAAA,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,GAAG,WAAW,CAAA;AAAA,IAClC,CAAA;AAAA,IACA,UAAU,MAAM;AACd,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,WAAW,CAAA;AAAA,IACpC;AAAA,GACF;AAEA,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,SAAA,GAAY;AACV,MAAA;AAAA,IACF,CAAA;AAAA,IACA,sBAAA,GAAyB;AACvB,MAAA;AAAA,IACF,CAAA;AAAA,IACA,OAAO;AAAC,GACV;AAEA,EAAA,MAAM,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,KAAK,YAAY,CAAA;AAExD,EAAA,OAAO,MAAA;AACT","file":"index.js","sourcesContent":["import type { QueueDefinition } from './types.js';\n\n/**\n * Symbol used to store non-enumerable queue internals on queue handles.\n */\nexport const kQueueInternals = Symbol.for('better-cf.queue.internals');\n\n/**\n * Internal queue API used by runtime/testing/CLI internals.\n */\nexport interface QueueInternalApi<E> {\n setBinding(name: string): void;\n getBinding(): string | null;\n getDefinition(): QueueDefinition<E>;\n consume(batch: MessageBatch<unknown>, env: E, executionCtx: ExecutionContext): Promise<void>;\n}\n\nexport type QueueWithInternals<E> = {\n [kQueueInternals]: QueueInternalApi<E>;\n};\n\n/**\n * Reads internal queue metadata from a queue handle.\n */\nexport function getQueueInternals<E>(value: unknown): QueueInternalApi<E> {\n if (!value || typeof value !== 'object') {\n throw new Error('Queue handle is not an object.');\n }\n\n const internals = (value as QueueWithInternals<E>)[kQueueInternals];\n if (!internals) {\n throw new Error('Object is not a better-cf queue handle.');\n }\n\n return internals;\n}\n\n/**\n * Input module shape accepted when resolving worker handlers.\n */\nexport interface WorkerModuleLike {\n default?: unknown;\n fetch?: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (\n event: ScheduledEvent,\n env: unknown,\n ctx: ExecutionContext\n ) => Promise<void>;\n}\n\n/**\n * Normalized handler pair resolved from a worker module export.\n */\nexport interface ResolvedWorkerHandlers {\n fetch: (request: Request, env: unknown, ctx: ExecutionContext) => Promise<Response>;\n scheduled?: (event: ScheduledEvent, env: unknown, ctx: ExecutionContext) => Promise<void>;\n}\n\n/**\n * Resolves `fetch`/`scheduled` handlers from various worker export styles.\n */\nexport function resolveWorkerHandlers(moduleLike: WorkerModuleLike): ResolvedWorkerHandlers {\n const root = moduleLike.default ?? moduleLike;\n\n let fetchHandler: ResolvedWorkerHandlers['fetch'] | undefined;\n if (typeof root === 'function') {\n fetchHandler = root as ResolvedWorkerHandlers['fetch'];\n } else if (root && typeof root === 'object' && 'fetch' in root) {\n const maybeFetch = (root as { fetch?: unknown }).fetch;\n if (typeof maybeFetch === 'function') {\n fetchHandler = maybeFetch.bind(root) as ResolvedWorkerHandlers['fetch'];\n }\n }\n\n if (!fetchHandler && typeof moduleLike.fetch === 'function') {\n fetchHandler = moduleLike.fetch;\n }\n\n if (!fetchHandler) {\n throw new Error(\n 'Could not resolve worker fetch handler. Export default app/object/function or named fetch.'\n );\n }\n\n let scheduledHandler: ResolvedWorkerHandlers['scheduled'] | undefined;\n if (root && typeof root === 'object' && 'scheduled' in root) {\n const maybeScheduled = (root as { scheduled?: unknown }).scheduled;\n if (typeof maybeScheduled === 'function') {\n scheduledHandler = maybeScheduled.bind(root) as ResolvedWorkerHandlers['scheduled'];\n }\n }\n\n if (!scheduledHandler && typeof moduleLike.scheduled === 'function') {\n scheduledHandler = moduleLike.scheduled;\n }\n\n return {\n fetch: fetchHandler,\n scheduled: scheduledHandler\n };\n}\n","import { getQueueInternals } from '../queue/internal.js';\n\n/**\n * Options for queue consumer tests.\n */\ninterface TestQueueBaseOptions<E> {\n env: E;\n /** Overrides message attempts metadata. */\n attempts?: number;\n}\n\n/**\n * Options for queue consumer tests.\n */\nexport type TestQueueOptions<E, TMessage> =\n | (TestQueueBaseOptions<E> & {\n /** Test one message. */\n message: TMessage;\n messages?: never;\n })\n | (TestQueueBaseOptions<E> & {\n /** Test many messages in one batch. */\n messages: TMessage[];\n message?: never;\n });\n\n/**\n * Test execution result for queue consumers.\n */\nexport interface TestQueueResult<TMessage> {\n /** Messages acked by the consumer. */\n acked: TMessage[];\n /** Messages retried by the consumer. */\n retried: TMessage[];\n}\n\n/**\n * Runs a queue declaration's consumer logic in-memory for tests.\n */\nexport async function testQueue<E, TMessage>(\n handle: unknown,\n options: TestQueueOptions<E, TMessage>\n): Promise<TestQueueResult<TMessage>> {\n const internals = getQueueInternals<E>(handle);\n\n if ('message' in options && 'messages' in options) {\n throw new Error('testQueue accepts either message or messages, not both.');\n }\n\n const allMessages = options.messages ?? (options.message !== undefined ? [options.message] : []);\n if (allMessages.length === 0) {\n throw new Error('testQueue requires message or messages.');\n }\n\n const result: TestQueueResult<TMessage> = {\n acked: [],\n retried: []\n };\n\n const batch: MessageBatch<unknown> = {\n queue: 'test-queue',\n messages: allMessages.map((body, index) => ({\n id: `msg-${index}`,\n timestamp: new Date(),\n body,\n attempts: options.attempts ?? 1,\n ack: () => {\n result.acked.push(body);\n },\n retry: () => {\n result.retried.push(body);\n }\n })),\n ackAll: () => {\n result.acked.push(...allMessages);\n },\n retryAll: () => {\n result.retried.push(...allMessages);\n }\n };\n\n const executionCtx = {\n waitUntil() {\n return;\n },\n passThroughOnException() {\n return;\n },\n props: {}\n } as unknown as ExecutionContext;\n\n await internals.consume(batch, options.env, executionCtx);\n\n return result;\n}\n"]}
@@ -1,23 +1,52 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /**
4
+ * Marker interface that generated env bindings extend.
5
+ */
3
6
  interface BetterCfGeneratedBindings {
4
7
  }
8
+ /**
9
+ * Default env type used when `createSDK()` is called without a generic.
10
+ */
5
11
  interface BetterCfAutoEnv extends BetterCfGeneratedBindings {
6
12
  [binding: string]: unknown;
7
13
  }
14
+ /**
15
+ * Runtime env shape available inside queue and worker handlers.
16
+ */
8
17
  type QueueEnv<E> = E & BetterCfGeneratedBindings;
18
+ /**
19
+ * Duration in seconds/minutes/hours shorthand or raw seconds.
20
+ */
9
21
  type Duration = number | `${number}s` | `${number}m` | `${number}h`;
22
+ /**
23
+ * Cloudflare Queue message content type.
24
+ */
10
25
  type ContentType = 'json' | 'text' | 'bytes' | 'v8';
26
+ /**
27
+ * Per-message send options.
28
+ */
11
29
  interface SendOptions {
30
+ /** Delay before message becomes visible to consumers. */
12
31
  delay?: Duration;
32
+ /** Explicit content type for Cloudflare queue delivery. */
13
33
  contentType?: ContentType;
14
34
  }
35
+ /**
36
+ * Shared send options for `sendBatch`.
37
+ */
15
38
  type SendBatchOptions = SendOptions;
39
+ /**
40
+ * Per-message input for `sendBatch`.
41
+ */
16
42
  interface SendBatchEntry<T> {
17
43
  data: T;
18
44
  delay?: Duration;
19
45
  contentType?: ContentType;
20
46
  }
47
+ /**
48
+ * Context passed to per-message queue consumers.
49
+ */
21
50
  interface QueueContext<E> {
22
51
  env: QueueEnv<E>;
23
52
  executionCtx: ExecutionContext;
@@ -28,6 +57,9 @@ interface QueueContext<E> {
28
57
  queue: string;
29
58
  };
30
59
  }
60
+ /**
61
+ * Context passed to batch queue consumers.
62
+ */
31
63
  interface BatchContext<E> {
32
64
  env: QueueEnv<E>;
33
65
  executionCtx: ExecutionContext;
@@ -41,35 +73,67 @@ interface BatchContext<E> {
41
73
  }) => void;
42
74
  };
43
75
  }
76
+ /**
77
+ * Context passed to worker handlers.
78
+ */
44
79
  interface WorkerContext<E> {
45
80
  env: QueueEnv<E>;
46
81
  executionCtx: ExecutionContext;
47
82
  }
83
+ /**
84
+ * Message shape received by batch consumers.
85
+ */
48
86
  interface ConsumerBatchEntry<T> {
49
87
  data: T;
50
88
  id: string;
51
89
  timestamp: Date;
52
90
  attempts: number;
53
91
  }
92
+ /**
93
+ * Queue settings shared across worker-consumer and pull-consumer modes.
94
+ */
54
95
  interface QueueCommonConfig {
96
+ /** Number of retry attempts before dead-lettering. */
55
97
  retry?: number;
98
+ /** Delay between retries. */
56
99
  retryDelay?: Duration;
100
+ /** Dead-letter queue name. */
57
101
  deadLetter?: string;
102
+ /** Delivery delay applied to newly sent messages. */
58
103
  deliveryDelay?: Duration;
104
+ /** Message visibility timeout (worker consumer mode only). */
59
105
  visibilityTimeout?: Duration;
106
+ /** Batch processing tuning (worker consumer mode only). */
60
107
  batch?: {
61
108
  maxSize?: number;
62
109
  timeout?: Duration;
63
110
  maxConcurrency?: number;
64
111
  };
65
112
  }
113
+ /**
114
+ * Pull consumer mode configuration.
115
+ */
66
116
  interface PullConsumerConfig {
117
+ /** Pull mode marker. */
67
118
  type: 'http_pull';
119
+ /** Pull visibility timeout in seconds. */
68
120
  visibilityTimeout?: Duration;
69
121
  }
122
+ /**
123
+ * Per-message queue handler.
124
+ */
70
125
  type QueueProcessHandler<E, TSchema extends z.ZodTypeAny> = (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;
126
+ /**
127
+ * Batch queue handler.
128
+ */
71
129
  type QueueBatchProcessHandler<E, TSchema extends z.ZodTypeAny> = (ctx: BatchContext<E>, messages: ConsumerBatchEntry<z.infer<TSchema>>[]) => Promise<void>;
130
+ /**
131
+ * Optional failure handler for queue processing.
132
+ */
72
133
  type QueueFailureHandler<E, TSchema extends z.ZodTypeAny> = (ctx: QueueContext<E> | BatchContext<E>, message: z.infer<TSchema> | null, error: Error) => Promise<void>;
134
+ /**
135
+ * Worker-consumer queue with per-message processing.
136
+ */
73
137
  type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {
74
138
  message: TSchema;
75
139
  consumer?: {
@@ -79,6 +143,9 @@ type QueueProcessConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {
79
143
  processBatch?: never;
80
144
  onFailure?: QueueFailureHandler<E, TSchema>;
81
145
  };
146
+ /**
147
+ * Worker-consumer queue with batch processing.
148
+ */
82
149
  type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {
83
150
  message: TSchema;
84
151
  consumer?: {
@@ -88,6 +155,9 @@ type QueueBatchConfig<E, TSchema extends z.ZodTypeAny> = QueueCommonConfig & {
88
155
  processBatch: QueueBatchProcessHandler<E, TSchema>;
89
156
  onFailure?: QueueFailureHandler<E, TSchema>;
90
157
  };
158
+ /**
159
+ * HTTP pull consumer queue (producer-only declaration).
160
+ */
91
161
  type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<QueueCommonConfig, 'visibilityTimeout' | 'batch'> & {
92
162
  message: TSchema;
93
163
  consumer: PullConsumerConfig;
@@ -97,43 +167,131 @@ type QueuePullConfig<E, TSchema extends z.ZodTypeAny> = Omit<QueueCommonConfig,
97
167
  processBatch?: never;
98
168
  onFailure?: never;
99
169
  };
170
+ /**
171
+ * Single-queue config union for worker and pull consumer modes.
172
+ */
100
173
  type QueueConfig<E, TSchema extends z.ZodTypeAny> = QueueProcessConfig<E, TSchema> | QueueBatchConfig<E, TSchema> | QueuePullConfig<E, TSchema>;
174
+ /**
175
+ * Per-job declaration inside a multi-job queue.
176
+ */
101
177
  interface JobConfig<E, TSchema extends z.ZodTypeAny> {
102
178
  message: TSchema;
103
179
  process: (ctx: QueueContext<E>, message: z.infer<TSchema>) => Promise<void>;
104
180
  onFailure?: (ctx: QueueContext<E>, message: z.infer<TSchema>, error: Error) => Promise<void>;
105
181
  }
182
+ /**
183
+ * Internal helper alias for any job config.
184
+ */
106
185
  type AnyJobConfig<E> = JobConfig<E, z.ZodTypeAny>;
186
+ /**
187
+ * Extracts only job keys from a multi-job config object.
188
+ */
107
189
  type ExtractJobMap<E, TConfig extends Record<string, unknown>> = {
108
190
  [K in keyof TConfig as TConfig[K] extends AnyJobConfig<E> ? K : never]: TConfig[K] extends AnyJobConfig<E> ? TConfig[K] : never;
109
191
  };
192
+ /**
193
+ * Multi-job queue declaration object.
194
+ */
110
195
  type MultiJobQueueConfig<E, TConfig extends Record<string, unknown>> = QueueCommonConfig & {
111
196
  consumer?: never;
197
+ message?: never;
198
+ process?: never;
199
+ processBatch?: never;
200
+ onFailure?: never;
112
201
  } & TConfig;
202
+ /**
203
+ * Producer handle for a single queue declaration.
204
+ */
113
205
  interface QueueHandle<E, TMessage> {
206
+ /** Sends one message to the queue. */
114
207
  send(ctx: {
115
208
  env: QueueEnv<E>;
116
209
  }, data: TMessage, options?: SendOptions): Promise<void>;
210
+ /** Sends multiple messages in one request. */
117
211
  sendBatch(ctx: {
118
212
  env: QueueEnv<E>;
119
213
  }, messages: SendBatchEntry<TMessage>[], options?: SendBatchOptions): Promise<void>;
120
214
  }
215
+ /**
216
+ * Producer handles keyed by job name for a multi-job queue.
217
+ */
121
218
  type MultiJobQueueHandle<E, TJobs extends Record<string, AnyJobConfig<E>>> = {
122
219
  [K in keyof TJobs]: {
220
+ /** Sends one message to a named job. */
123
221
  send(ctx: {
124
222
  env: QueueEnv<E>;
125
223
  }, data: z.infer<TJobs[K]['message']>, options?: SendOptions): Promise<void>;
224
+ /** Sends many messages to a named job. */
126
225
  sendBatch(ctx: {
127
226
  env: QueueEnv<E>;
128
227
  }, messages: SendBatchEntry<z.infer<TJobs[K]['message']>>[], options?: SendBatchOptions): Promise<void>;
129
228
  };
130
229
  };
230
+ /**
231
+ * Worker handlers used to define module exports.
232
+ */
131
233
  interface WorkerConfig<E> {
234
+ /** Main fetch handler. */
132
235
  fetch: (request: Request, ctx: WorkerContext<E>) => Promise<Response>;
236
+ /** Optional scheduled handler. */
133
237
  scheduled?: (event: ScheduledEvent, ctx: WorkerContext<E>) => Promise<void>;
134
238
  }
239
+ /**
240
+ * Worker module shape returned by `defineWorker`.
241
+ */
242
+ interface WorkerEntrypoint<E> {
243
+ fetch(request: Request, env: E, executionCtx: ExecutionContext): Promise<Response>;
244
+ scheduled?: (event: ScheduledEvent, env: E, executionCtx: ExecutionContext) => Promise<void>;
245
+ }
246
+ /**
247
+ * Defines a worker module with typed queue-aware context.
248
+ */
249
+ type DefineWorker<E> = (config: WorkerConfig<E>) => WorkerEntrypoint<E>;
250
+ /**
251
+ * Defines queue contracts and returns typed producer handles.
252
+ */
253
+ interface DefineQueue<E> {
254
+ /**
255
+ * Declare a single queue (worker consumer or http pull consumer).
256
+ *
257
+ * @example
258
+ * defineQueue({
259
+ * message: z.object({ id: z.string() }),
260
+ * process: async (ctx, message) => {}
261
+ * })
262
+ */
263
+ <TSchema extends z.ZodTypeAny>(config: QueueConfig<E, TSchema>): QueueHandle<E, z.infer<TSchema>>;
264
+ /**
265
+ * Declare a multi-job queue where each top-level key is a job definition.
266
+ *
267
+ * @example
268
+ * defineQueue({
269
+ * email: { message: z.object({ to: z.string() }), process: async () => {} },
270
+ * audit: { message: z.object({ id: z.string() }), process: async () => {} }
271
+ * })
272
+ */
273
+ <const TConfig extends Record<string, unknown>>(config: MultiJobQueueConfig<E, TConfig>): MultiJobQueueHandle<E, ExtractJobMap<E, TConfig>>;
274
+ }
275
+ /**
276
+ * SDK helpers returned by `createSDK`.
277
+ */
278
+ interface BetterCfSDK<E> {
279
+ /** Queue declaration helper with schema-inferred producer types. */
280
+ defineQueue: DefineQueue<E>;
281
+ /** Worker declaration helper that maps to Cloudflare module handlers. */
282
+ defineWorker: DefineWorker<E>;
283
+ }
284
+ /**
285
+ * Internal helper alias for worker-consumer queue modes.
286
+ */
135
287
  type AnyPushQueueConfig<E> = QueueProcessConfig<E, z.ZodTypeAny> | QueueBatchConfig<E, z.ZodTypeAny>;
288
+ /**
289
+ * Internal helper alias for pull-consumer queue mode.
290
+ */
136
291
  type AnyPullQueueConfig<E> = QueuePullConfig<E, z.ZodTypeAny>;
292
+ /**
293
+ * Normalized queue definition used by runtime internals.
294
+ */
137
295
  type QueueDefinition<E> = {
138
296
  kind: 'single';
139
297
  mode: 'push';
@@ -148,4 +306,4 @@ type QueueDefinition<E> = {
148
306
  shared: QueueCommonConfig;
149
307
  };
150
308
 
151
- export type { BetterCfAutoEnv as B, ConsumerBatchEntry as C, Duration as D, ExtractJobMap as E, JobConfig as J, MultiJobQueueConfig as M, PullConsumerConfig as P, QueueDefinition as Q, SendBatchEntry as S, WorkerConfig as W, QueueConfig as a, QueueHandle as b, MultiJobQueueHandle as c, BatchContext as d, BetterCfGeneratedBindings as e, ContentType as f, QueueCommonConfig as g, QueueContext as h, QueueEnv as i, SendBatchOptions as j, SendOptions as k, WorkerContext as l };
309
+ export type { BetterCfAutoEnv as B, ConsumerBatchEntry as C, DefineQueue as D, JobConfig as J, MultiJobQueueConfig as M, PullConsumerConfig as P, QueueDefinition as Q, SendBatchEntry as S, WorkerConfig as W, BetterCfSDK as a, BatchContext as b, BetterCfGeneratedBindings as c, ContentType as d, DefineWorker as e, Duration as f, MultiJobQueueHandle as g, QueueCommonConfig as h, QueueConfig as i, QueueContext as j, QueueEnv as k, QueueHandle as l, SendBatchOptions as m, SendOptions as n, WorkerContext as o, WorkerEntrypoint as p };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-cf",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Type-safe Cloudflare Queue SDK and CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -54,9 +54,10 @@
54
54
  "test:watch": "BETTER_CF_SKIP_WRANGLER_TYPES=1 vitest",
55
55
  "test:types": "tsc -p tests/types/tsconfig.json --noEmit",
56
56
  "test:e2e": "BETTER_CF_SKIP_WRANGLER_TYPES=1 vitest run tests/e2e",
57
- "check:docs": "node scripts/check-docs.mjs",
58
57
  "security:deps": "npm audit --omit=dev",
59
- "check": "npm run lint && npm run test && npm run test:types && npm run check:docs"
58
+ "check": "npm run lint && npm run test && npm run test:types",
59
+ "release:version": "changeset version",
60
+ "release:publish": "npm run build && npm publish --access public --tag ${NPM_TAG:-latest}"
60
61
  },
61
62
  "dependencies": {
62
63
  "@iarna/toml": "^2.2.5",
@@ -84,6 +85,7 @@
84
85
  "tsup": "^8.4.0",
85
86
  "typescript": "^5.8.2",
86
87
  "vitest": "^3.0.8",
87
- "zod": "^3.24.2"
88
+ "zod": "^3.24.2",
89
+ "@changesets/cli": "^2.29.7"
88
90
  }
89
91
  }