gemi 0.116.0 → 0.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.js +2 -2
- package/dist/ai/index.js.map +1 -1
- package/dist/app/index.js +2 -2
- package/dist/app/index.js.map +1 -1
- package/dist/auth/AuthServiceProvider.d.ts.map +1 -1
- package/dist/auth/config.d.ts +27 -0
- package/dist/auth/config.d.ts.map +1 -1
- package/dist/auth/connections/ConnectionManager.d.ts +133 -0
- package/dist/auth/connections/ConnectionManager.d.ts.map +1 -0
- package/dist/auth/connections/ConnectionStore.d.ts +146 -0
- package/dist/auth/connections/ConnectionStore.d.ts.map +1 -0
- package/dist/auth/connections/ConnectionsController.d.ts +23 -0
- package/dist/auth/connections/ConnectionsController.d.ts.map +1 -0
- package/dist/auth/connections/OAuthConnectionProvider.d.ts +105 -0
- package/dist/auth/connections/OAuthConnectionProvider.d.ts.map +1 -0
- package/dist/auth/connections/errors.d.ts +32 -0
- package/dist/auth/connections/errors.d.ts.map +1 -0
- package/dist/auth/oauth/oauthState.d.ts +15 -2
- package/dist/auth/oauth/oauthState.d.ts.map +1 -1
- package/dist/auth/routes.d.ts +13 -0
- package/dist/auth/routes.d.ts.map +1 -1
- package/dist/bin/orm/emit.d.ts.map +1 -1
- package/dist/bin/orm-generator.js +51 -4
- package/dist/bin/orm-generator.js.map +4 -4
- package/dist/bun/plugin.js +2 -2
- package/dist/bun/plugin.js.map +1 -1
- package/dist/bun/preload.js +2 -2
- package/dist/bun/preload.js.map +1 -1
- package/dist/{chunk-2tzm58j3.js → chunk-01ehxca0.js} +2 -2
- package/dist/{chunk-2tzm58j3.js.map → chunk-01ehxca0.js.map} +1 -1
- package/dist/chunk-0gtyects.js +10 -0
- package/dist/{chunk-yf1njzd5.js.map → chunk-0gtyects.js.map} +6 -5
- package/dist/{chunk-15c2vgaf.js → chunk-1m3hvy3q.js} +2 -2
- package/dist/{chunk-15c2vgaf.js.map → chunk-1m3hvy3q.js.map} +1 -1
- package/dist/{chunk-6cx8ncd4.js → chunk-1z1rj2zq.js} +3 -3
- package/dist/{chunk-6cx8ncd4.js.map → chunk-1z1rj2zq.js.map} +1 -1
- package/dist/{chunk-5stgtwqw.js → chunk-2bja99cq.js} +2 -2
- package/dist/{chunk-5stgtwqw.js.map → chunk-2bja99cq.js.map} +1 -1
- package/dist/{chunk-n672d4g8.js → chunk-30xxc6r7.js} +2 -2
- package/dist/{chunk-n672d4g8.js.map → chunk-30xxc6r7.js.map} +1 -1
- package/dist/{chunk-qjhw8nje.js → chunk-33s2xqv1.js} +1 -1
- package/dist/{chunk-4088szy9.js → chunk-39kyz4k6.js} +3 -3
- package/dist/{chunk-4088szy9.js.map → chunk-39kyz4k6.js.map} +1 -1
- package/dist/chunk-3nf95j9e.js +5 -0
- package/dist/{chunk-1q9kd20m.js.map → chunk-3nf95j9e.js.map} +1 -1
- package/dist/chunk-3zxfd7pn.js +14 -0
- package/dist/{chunk-pn8v6fj2.js.map → chunk-3zxfd7pn.js.map} +11 -6
- package/dist/{chunk-pyk3gzvc.js → chunk-453rmkpm.js} +2 -2
- package/dist/{chunk-pyk3gzvc.js.map → chunk-453rmkpm.js.map} +1 -1
- package/dist/chunk-47h12eme.js +57 -0
- package/dist/{chunk-ms9k0rx6.js.map → chunk-47h12eme.js.map} +15 -11
- package/dist/chunk-490sbcma.js +5 -0
- package/dist/chunk-490sbcma.js.map +12 -0
- package/dist/{chunk-kqxdsv22.js → chunk-4c1kdd8p.js} +2 -2
- package/dist/{chunk-kqxdsv22.js.map → chunk-4c1kdd8p.js.map} +1 -1
- package/dist/{chunk-jdhdrr2k.js → chunk-5cgq9c43.js} +2 -2
- package/dist/{chunk-jdhdrr2k.js.map → chunk-5cgq9c43.js.map} +1 -1
- package/dist/{chunk-9n1hx3mq.js → chunk-5dbpgyrx.js} +3 -3
- package/dist/{chunk-9n1hx3mq.js.map → chunk-5dbpgyrx.js.map} +1 -1
- package/dist/{chunk-eqse2m6n.js → chunk-5ses4tcz.js} +2 -2
- package/dist/{chunk-eqse2m6n.js.map → chunk-5ses4tcz.js.map} +1 -1
- package/dist/{chunk-2z1981d0.js → chunk-675kzd7z.js} +2 -2
- package/dist/{chunk-2z1981d0.js.map → chunk-675kzd7z.js.map} +1 -1
- package/dist/{chunk-p1aqq0ga.js → chunk-6ggmk2eg.js} +3 -3
- package/dist/{chunk-p1aqq0ga.js.map → chunk-6ggmk2eg.js.map} +1 -1
- package/dist/{chunk-mazznq15.js → chunk-76p0rf4d.js} +3 -3
- package/dist/{chunk-mazznq15.js.map → chunk-76p0rf4d.js.map} +1 -1
- package/dist/{chunk-41da9628.js → chunk-8t6dwwz6.js} +1 -1
- package/dist/{chunk-zyt2w03d.js → chunk-8wcpxm41.js} +2 -2
- package/dist/{chunk-zyt2w03d.js.map → chunk-8wcpxm41.js.map} +1 -1
- package/dist/chunk-9pkj7sk6.js +50 -0
- package/dist/chunk-9pkj7sk6.js.map +10 -0
- package/dist/{chunk-jmpw6bqz.js → chunk-a1qt8aky.js} +2 -2
- package/dist/{chunk-jmpw6bqz.js.map → chunk-a1qt8aky.js.map} +1 -1
- package/dist/{chunk-frerzsxq.js → chunk-a22h5cby.js} +2 -2
- package/dist/{chunk-frerzsxq.js.map → chunk-a22h5cby.js.map} +1 -1
- package/dist/{chunk-e573yxpq.js → chunk-aedkrck1.js} +3 -3
- package/dist/{chunk-e573yxpq.js.map → chunk-aedkrck1.js.map} +1 -1
- package/dist/{chunk-vxm6yevm.js → chunk-aqpaw4jq.js} +2 -2
- package/dist/{chunk-vxm6yevm.js.map → chunk-aqpaw4jq.js.map} +1 -1
- package/dist/{chunk-aeh67ynz.js → chunk-bgwtdbfw.js} +3 -3
- package/dist/{chunk-aeh67ynz.js.map → chunk-bgwtdbfw.js.map} +1 -1
- package/dist/{chunk-tw5kwbx4.js → chunk-bz8xssrc.js} +2 -2
- package/dist/{chunk-tw5kwbx4.js.map → chunk-bz8xssrc.js.map} +1 -1
- package/dist/{chunk-tzm3c7n6.js → chunk-cte6ysqd.js} +4 -4
- package/dist/{chunk-tzm3c7n6.js.map → chunk-cte6ysqd.js.map} +1 -1
- package/dist/{chunk-qsrcdzan.js → chunk-cvfg88cx.js} +3 -3
- package/dist/{chunk-qsrcdzan.js.map → chunk-cvfg88cx.js.map} +1 -1
- package/dist/{chunk-1vzks22y.js → chunk-d806cy7p.js} +2 -2
- package/dist/{chunk-1vzks22y.js.map → chunk-d806cy7p.js.map} +1 -1
- package/dist/{chunk-6chz1ktz.js → chunk-de4t48j9.js} +3 -3
- package/dist/{chunk-6chz1ktz.js.map → chunk-de4t48j9.js.map} +1 -1
- package/dist/{chunk-mqfzdfnz.js → chunk-dwpn6fze.js} +2 -2
- package/dist/{chunk-mqfzdfnz.js.map → chunk-dwpn6fze.js.map} +1 -1
- package/dist/{chunk-vbdty91k.js → chunk-ebret82e.js} +3 -3
- package/dist/{chunk-vbdty91k.js.map → chunk-ebret82e.js.map} +1 -1
- package/dist/chunk-eke2frrm.js +9 -0
- package/dist/{chunk-hytt9qyj.js.map → chunk-eke2frrm.js.map} +3 -4
- package/dist/{chunk-yer1r3t3.js → chunk-epvpmakp.js} +2 -2
- package/dist/{chunk-yer1r3t3.js.map → chunk-epvpmakp.js.map} +1 -1
- package/dist/{chunk-fxgxf16k.js → chunk-fsj5k511.js} +2 -2
- package/dist/{chunk-fxgxf16k.js.map → chunk-fsj5k511.js.map} +1 -1
- package/dist/{chunk-t4yh4nf9.js → chunk-g5ppst76.js} +3 -3
- package/dist/{chunk-t4yh4nf9.js.map → chunk-g5ppst76.js.map} +1 -1
- package/dist/{chunk-aazmrxj9.js → chunk-g9hhdcax.js} +2 -2
- package/dist/{chunk-aazmrxj9.js.map → chunk-g9hhdcax.js.map} +1 -1
- package/dist/{chunk-cbqazg9k.js → chunk-gqfqnv3f.js} +2 -2
- package/dist/{chunk-cbqazg9k.js.map → chunk-gqfqnv3f.js.map} +1 -1
- package/dist/chunk-hkf2k2eq.js +5 -0
- package/dist/{chunk-whtzggn6.js.map → chunk-hkf2k2eq.js.map} +3 -4
- package/dist/{chunk-vw8849ys.js → chunk-hm9cjxy2.js} +2 -2
- package/dist/{chunk-m54s6jpr.js.map → chunk-hm9cjxy2.js.map} +1 -1
- package/dist/{chunk-kejwjerj.js → chunk-hr1r3g0d.js} +2 -2
- package/dist/{chunk-kejwjerj.js.map → chunk-hr1r3g0d.js.map} +1 -1
- package/dist/{chunk-3hrj5rwm.js → chunk-hzepfrzy.js} +2 -2
- package/dist/{chunk-3hrj5rwm.js.map → chunk-hzepfrzy.js.map} +1 -1
- package/dist/{chunk-785b41h1.js → chunk-j5858bz7.js} +3 -3
- package/dist/{chunk-785b41h1.js.map → chunk-j5858bz7.js.map} +1 -1
- package/dist/{chunk-d9mar37g.js → chunk-jf6qqzat.js} +2 -2
- package/dist/{chunk-d9mar37g.js.map → chunk-jf6qqzat.js.map} +1 -1
- package/dist/{chunk-1hr4xht1.js → chunk-jg79n382.js} +2 -2
- package/dist/{chunk-1hr4xht1.js.map → chunk-jg79n382.js.map} +1 -1
- package/dist/chunk-k31qfe7a.js +71 -0
- package/dist/chunk-k31qfe7a.js.map +13 -0
- package/dist/{chunk-4mfrgd5m.js → chunk-kk77x2v4.js} +2 -2
- package/dist/{chunk-4mfrgd5m.js.map → chunk-kk77x2v4.js.map} +1 -1
- package/dist/{chunk-1myhm0g3.js → chunk-kkte8nze.js} +3 -3
- package/dist/{chunk-1myhm0g3.js.map → chunk-kkte8nze.js.map} +1 -1
- package/dist/{chunk-hdps9n52.js → chunk-m4kmetpb.js} +3 -3
- package/dist/{chunk-hdps9n52.js.map → chunk-m4kmetpb.js.map} +1 -1
- package/dist/{chunk-gts5p6mw.js → chunk-n4sdm0jn.js} +4 -4
- package/dist/{chunk-gts5p6mw.js.map → chunk-n4sdm0jn.js.map} +1 -1
- package/dist/chunk-nang3847.js +416 -0
- package/dist/chunk-nang3847.js.map +24 -0
- package/dist/{chunk-agyfv3f8.js → chunk-nrezmscd.js} +1 -1
- package/dist/{chunk-xt9tv99x.js → chunk-p83erprx.js} +2 -2
- package/dist/{chunk-xt9tv99x.js.map → chunk-p83erprx.js.map} +1 -1
- package/dist/{chunk-sr942vb1.js → chunk-pkr5dsbk.js} +2 -2
- package/dist/{chunk-sr942vb1.js.map → chunk-pkr5dsbk.js.map} +1 -1
- package/dist/{chunk-yhrye9cm.js → chunk-pqc16rrx.js} +2 -2
- package/dist/{chunk-yhrye9cm.js.map → chunk-pqc16rrx.js.map} +1 -1
- package/dist/{chunk-m54s6jpr.js → chunk-pvz90a49.js} +2 -2
- package/dist/{chunk-vw8849ys.js.map → chunk-pvz90a49.js.map} +1 -1
- package/dist/{chunk-fre6f4nk.js → chunk-q290tgza.js} +2 -2
- package/dist/{chunk-fre6f4nk.js.map → chunk-q290tgza.js.map} +1 -1
- package/dist/{chunk-8rv62v14.js → chunk-qf4bmee9.js} +2 -2
- package/dist/{chunk-8rv62v14.js.map → chunk-qf4bmee9.js.map} +1 -1
- package/dist/chunk-qkxnvpaj.js +5 -0
- package/dist/chunk-qkxnvpaj.js.map +10 -0
- package/dist/chunk-r1favzz4.js +19 -0
- package/dist/{chunk-ktr3k768.js.map → chunk-r1favzz4.js.map} +5 -4
- package/dist/{chunk-303mprnv.js → chunk-r3v2cnrj.js} +2 -2
- package/dist/{chunk-303mprnv.js.map → chunk-r3v2cnrj.js.map} +1 -1
- package/dist/{chunk-x7cpth2f.js → chunk-razjfecn.js} +1 -1
- package/dist/{chunk-t04f3akb.js → chunk-scc0j5k9.js} +2 -2
- package/dist/{chunk-t04f3akb.js.map → chunk-scc0j5k9.js.map} +1 -1
- package/dist/{chunk-56jky6vf.js → chunk-sce5jes2.js} +2 -2
- package/dist/{chunk-56jky6vf.js.map → chunk-sce5jes2.js.map} +1 -1
- package/dist/chunk-sd02ktf2.js +24 -0
- package/dist/{chunk-79xg42e7.js.map → chunk-sd02ktf2.js.map} +2 -2
- package/dist/{chunk-mschc94q.js → chunk-sn04cyw0.js} +2 -2
- package/dist/{chunk-mschc94q.js.map → chunk-sn04cyw0.js.map} +1 -1
- package/dist/{chunk-bra1a1fq.js → chunk-tfdmvxza.js} +2 -2
- package/dist/{chunk-bra1a1fq.js.map → chunk-tfdmvxza.js.map} +1 -1
- package/dist/{chunk-z10cas5r.js → chunk-thz75w6e.js} +2 -2
- package/dist/{chunk-z10cas5r.js.map → chunk-thz75w6e.js.map} +1 -1
- package/dist/{chunk-v1tfdgy1.js → chunk-tzdenj0n.js} +3 -3
- package/dist/{chunk-v1tfdgy1.js.map → chunk-tzdenj0n.js.map} +1 -1
- package/dist/{chunk-98m15b9x.js → chunk-x6v2zex2.js} +2 -2
- package/dist/{chunk-98m15b9x.js.map → chunk-x6v2zex2.js.map} +1 -1
- package/dist/{chunk-d2gfcf85.js → chunk-xfw8zyvn.js} +2 -2
- package/dist/{chunk-d2gfcf85.js.map → chunk-xfw8zyvn.js.map} +1 -1
- package/dist/{chunk-wyw6p3fg.js → chunk-xtzn0qfh.js} +3 -3
- package/dist/{chunk-wyw6p3fg.js.map → chunk-xtzn0qfh.js.map} +1 -1
- package/dist/{chunk-tn2bryy2.js → chunk-xx3zvc3g.js} +2 -2
- package/dist/{chunk-tn2bryy2.js.map → chunk-xx3zvc3g.js.map} +1 -1
- package/dist/{chunk-er3wf6ng.js → chunk-xzn2nmny.js} +2 -2
- package/dist/{chunk-er3wf6ng.js.map → chunk-xzn2nmny.js.map} +1 -1
- package/dist/{chunk-p91b8zcn.js → chunk-xzyy896s.js} +2 -2
- package/dist/{chunk-p91b8zcn.js.map → chunk-xzyy896s.js.map} +1 -1
- package/dist/chunk-y09r0wsw.js +5 -0
- package/dist/chunk-y09r0wsw.js.map +12 -0
- package/dist/{chunk-6d8rvr1v.js → chunk-ygf0z7kk.js} +2 -2
- package/dist/{chunk-6d8rvr1v.js.map → chunk-ygf0z7kk.js.map} +1 -1
- package/dist/chunk-z759yah5.js +5 -0
- package/dist/chunk-z759yah5.js.map +12 -0
- package/dist/client/Head.d.ts.map +1 -1
- package/dist/client/fonts.d.ts +69 -0
- package/dist/client/fonts.d.ts.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +75 -1
- package/dist/client/index.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/builtins.d.ts +13 -0
- package/dist/console/builtins.d.ts.map +1 -0
- package/dist/console/run.js +13 -11
- package/dist/console/run.js.map +6 -5
- package/dist/console/runner.d.ts.map +1 -1
- package/dist/console/usage.d.ts +2 -0
- package/dist/console/usage.d.ts.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/Connections.d.ts +36 -0
- package/dist/facades/Connections.d.ts.map +1 -0
- package/dist/facades/Crypt.d.ts +26 -0
- package/dist/facades/Crypt.d.ts.map +1 -0
- package/dist/facades/Meta.d.ts +7 -1
- package/dist/facades/Meta.d.ts.map +1 -1
- package/dist/facades/Storage.d.ts +29 -0
- package/dist/facades/Storage.d.ts.map +1 -1
- package/dist/facades/index.d.ts +2 -0
- package/dist/facades/index.d.ts.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/HttpRequest.d.ts +1 -0
- package/dist/http/HttpRequest.d.ts.map +1 -1
- package/dist/http/Metadata.d.ts +5 -0
- package/dist/http/Metadata.d.ts.map +1 -1
- package/dist/http/index.d.ts +3 -1
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/http/requestContext.d.ts +1 -0
- package/dist/http/requestContext.d.ts.map +1 -1
- package/dist/http/safeFetch/errors.d.ts +10 -0
- package/dist/http/safeFetch/errors.d.ts.map +1 -1
- package/dist/http/safeFetch/index.d.ts +1 -1
- package/dist/http/safeFetch/index.d.ts.map +1 -1
- package/dist/http/sitemap/Robots.d.ts +95 -0
- package/dist/http/sitemap/Robots.d.ts.map +1 -0
- package/dist/http/sitemap/Sitemap.d.ts +145 -0
- package/dist/http/sitemap/Sitemap.d.ts.map +1 -0
- package/dist/http/sitemap/fetchText.d.ts +16 -0
- package/dist/http/sitemap/fetchText.d.ts.map +1 -0
- package/dist/http/sitemap/index.d.ts +3 -0
- package/dist/http/sitemap/index.d.ts.map +1 -0
- package/dist/http/sitemap/xml.d.ts +21 -0
- package/dist/http/sitemap/xml.d.ts.map +1 -0
- package/dist/i18n/Translator.d.ts.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/resolveLocale.d.ts +18 -0
- package/dist/i18n/resolveLocale.d.ts.map +1 -1
- package/dist/kernel/index.js +3 -3
- package/dist/kernel/index.js.map +3 -3
- package/dist/kernel/providers.d.ts +2 -2
- package/dist/kernel/providers.d.ts.map +1 -1
- package/dist/orm/Model.d.ts.map +1 -1
- package/dist/orm/encryption-rotate.d.ts +44 -0
- package/dist/orm/encryption-rotate.d.ts.map +1 -0
- package/dist/orm/encryption.d.ts +54 -0
- package/dist/orm/encryption.d.ts.map +1 -0
- package/dist/orm/index.d.ts +2 -0
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +3 -3
- package/dist/orm/index.js.map +4 -4
- package/dist/orm/schema.d.ts +25 -1
- package/dist/orm/schema.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/discovery.d.ts +8 -0
- package/dist/services/discovery.d.ts.map +1 -1
- package/dist/services/encryption/Encrypter.d.ts +86 -0
- package/dist/services/encryption/Encrypter.d.ts.map +1 -0
- package/dist/services/encryption/EncryptionServiceProvider.d.ts +13 -0
- package/dist/services/encryption/EncryptionServiceProvider.d.ts.map +1 -0
- package/dist/services/encryption/config.d.ts +36 -0
- package/dist/services/encryption/config.d.ts.map +1 -0
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts +12 -1
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts +8 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/types.d.ts +17 -0
- package/dist/services/file-storage/drivers/types.d.ts.map +1 -1
- package/dist/services/file-storage/putFromUrl.d.ts +56 -0
- package/dist/services/file-storage/putFromUrl.d.ts.map +1 -0
- package/dist/services/file-storage/sniffContentType.d.ts +33 -0
- package/dist/services/file-storage/sniffContentType.d.ts.map +1 -0
- package/dist/services/index.d.ts +26 -5
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +10 -10
- package/dist/services/index.js.map +4 -3
- package/dist/services/queue/DatabaseQueueDriver.d.ts +117 -7
- package/dist/services/queue/DatabaseQueueDriver.d.ts.map +1 -1
- package/dist/services/queue/Job.d.ts +75 -0
- package/dist/services/queue/Job.d.ts.map +1 -1
- package/dist/services/queue/MemoryQueueDriver.d.ts +32 -2
- package/dist/services/queue/MemoryQueueDriver.d.ts.map +1 -1
- package/dist/services/queue/QueueDriver.d.ts +83 -1
- package/dist/services/queue/QueueDriver.d.ts.map +1 -1
- package/dist/services/queue/QueueManager.d.ts +80 -7
- package/dist/services/queue/QueueManager.d.ts.map +1 -1
- package/dist/services/queue/QueueServiceProvider.d.ts.map +1 -1
- package/dist/services/queue/backoff.d.ts +6 -0
- package/dist/services/queue/backoff.d.ts.map +1 -0
- package/dist/services/queue/batch.d.ts +112 -0
- package/dist/services/queue/batch.d.ts.map +1 -0
- package/dist/services/queue/config.d.ts +9 -0
- package/dist/services/queue/config.d.ts.map +1 -1
- package/dist/services/queue/queueDriverContract.d.ts +5 -0
- package/dist/services/queue/queueDriverContract.d.ts.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/services/queue/workflow/DatabaseWorkflowStore.d.ts +89 -0
- package/dist/services/queue/workflow/DatabaseWorkflowStore.d.ts.map +1 -0
- package/dist/services/queue/workflow/MemoryWorkflowStore.d.ts +43 -0
- package/dist/services/queue/workflow/MemoryWorkflowStore.d.ts.map +1 -0
- package/dist/services/queue/workflow/Step.d.ts +202 -0
- package/dist/services/queue/workflow/Step.d.ts.map +1 -0
- package/dist/services/queue/workflow/Workflow.d.ts +124 -0
- package/dist/services/queue/workflow/Workflow.d.ts.map +1 -0
- package/dist/services/queue/workflow/WorkflowRuntime.d.ts +60 -0
- package/dist/services/queue/workflow/WorkflowRuntime.d.ts.map +1 -0
- package/dist/services/queue/workflow/WorkflowStore.d.ts +184 -0
- package/dist/services/queue/workflow/WorkflowStore.d.ts.map +1 -0
- package/dist/services/queue/workflow/duration.d.ts +8 -0
- package/dist/services/queue/workflow/duration.d.ts.map +1 -0
- package/dist/services/queue/workflow/workflowContract.d.ts +30 -0
- package/dist/services/queue/workflow/workflowContract.d.ts.map +1 -0
- package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
- package/dist/stats/route-table.js +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vitest/index.js +2 -2
- package/dist/vitest/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-1q9kd20m.js +0 -5
- package/dist/chunk-49nyyjfe.js +0 -5
- package/dist/chunk-49nyyjfe.js.map +0 -11
- package/dist/chunk-79xg42e7.js +0 -24
- package/dist/chunk-7vb4eey2.js +0 -217
- package/dist/chunk-7vb4eey2.js.map +0 -16
- package/dist/chunk-hytt9qyj.js +0 -54
- package/dist/chunk-jmg2zsaf.js +0 -5
- package/dist/chunk-jmg2zsaf.js.map +0 -12
- package/dist/chunk-ktr3k768.js +0 -19
- package/dist/chunk-ms9k0rx6.js +0 -46
- package/dist/chunk-pn8v6fj2.js +0 -14
- package/dist/chunk-whtzggn6.js +0 -5
- package/dist/chunk-yf1njzd5.js +0 -10
- /package/dist/{chunk-qjhw8nje.js.map → chunk-33s2xqv1.js.map} +0 -0
- /package/dist/{chunk-41da9628.js.map → chunk-8t6dwwz6.js.map} +0 -0
- /package/dist/{chunk-agyfv3f8.js.map → chunk-nrezmscd.js.map} +0 -0
- /package/dist/{chunk-x7cpth2f.js.map → chunk-razjfecn.js.map} +0 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Step } from "./Step";
|
|
2
|
+
import type { StepRunStatus, WorkflowRunStatus } from "./WorkflowStore";
|
|
3
|
+
/** The arguments `start` takes: `run`'s, after `step`. */
|
|
4
|
+
export type WorkflowArgs<T extends Workflow> = Parameters<T["run"]> extends [
|
|
5
|
+
any,
|
|
6
|
+
...infer Rest
|
|
7
|
+
] ? Rest : never;
|
|
8
|
+
/** What `Workflow.find` resolves to. Times are epoch milliseconds. */
|
|
9
|
+
export type WorkflowStatus = {
|
|
10
|
+
id: string;
|
|
11
|
+
/** The workflow class's `static name`. */
|
|
12
|
+
name: string;
|
|
13
|
+
status: WorkflowRunStatus;
|
|
14
|
+
/** The `run` arguments after `step`. */
|
|
15
|
+
args: unknown[];
|
|
16
|
+
/** The key of the step it is on, or `null`. */
|
|
17
|
+
currentStep: string | null;
|
|
18
|
+
/** 0 to 1, as `step.progress` last set it; 1 once completed. */
|
|
19
|
+
progress: number;
|
|
20
|
+
/** What `run` returned, once completed. */
|
|
21
|
+
result: unknown;
|
|
22
|
+
/** Why it failed; for a cancelled one, why `onCancel` failed. */
|
|
23
|
+
error: string | null;
|
|
24
|
+
/** Every step recorded so far, in the order they were first reached. */
|
|
25
|
+
steps: WorkflowStepStatus[];
|
|
26
|
+
createdAt: number;
|
|
27
|
+
updatedAt: number;
|
|
28
|
+
};
|
|
29
|
+
export type WorkflowStepStatus = {
|
|
30
|
+
key: string;
|
|
31
|
+
status: StepRunStatus;
|
|
32
|
+
/** Attempts started; `step.run` only. */
|
|
33
|
+
attempt: number;
|
|
34
|
+
error: string | null;
|
|
35
|
+
/** The batch a `step.batch` dispatched. */
|
|
36
|
+
batchId: string | null;
|
|
37
|
+
/** The batch's progress, 0 to 1, for a `step.batch`. */
|
|
38
|
+
progress?: number;
|
|
39
|
+
/** When a sleep ends, a wait times out, or a retry is due. */
|
|
40
|
+
wakeAt: number | null;
|
|
41
|
+
startedAt: number | null;
|
|
42
|
+
finishedAt: number | null;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A durable workflow (#846): a `run` method made of steps, which survives
|
|
46
|
+
* restarts and deploys, sleeps and waits without holding a process, and can
|
|
47
|
+
* be cancelled.
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* export class ImportSiteWorkflow extends Workflow {
|
|
51
|
+
* static name = "ImportSiteWorkflow";
|
|
52
|
+
*
|
|
53
|
+
* async run(step: Step, importId: string) {
|
|
54
|
+
* const pages = await step.run("discover", () => crawl(importId));
|
|
55
|
+
* const chosen = await step.waitFor<string[]>("pages-chosen", { timeout: "7d" });
|
|
56
|
+
* await step.run("charge", (ctx) => charge(importId, ctx.idempotencyKey), { attempts: 1 });
|
|
57
|
+
* const builds = await step.batch("build", BuildPageJob,
|
|
58
|
+
* chosen.map((id) => [id, importId] as const), { allowFailures: true });
|
|
59
|
+
* await step.sleep("settle", "30s");
|
|
60
|
+
* return step.run("report", () => report(importId, builds.failedJobIds));
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* async onCancel(step: Step, importId: string) {
|
|
64
|
+
* await step.run("refund", () => refundUnbuilt(importId));
|
|
65
|
+
* }
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* ### How it runs
|
|
70
|
+
*
|
|
71
|
+
* Each pass calls `run` from the top, inside an internal queue job (a
|
|
72
|
+
* *tick*), so leases, heartbeats and crash recovery are the queue's. A step
|
|
73
|
+
* whose result is stored returns it without running; the first one without
|
|
74
|
+
* one runs and its result is stored before the code goes on. A step that
|
|
75
|
+
* cannot finish now (a sleep, a wait, a batch, a retry with a delay) ends the
|
|
76
|
+
* pass, and a later tick picks it up. **Code outside the steps runs again on
|
|
77
|
+
* every pass**, so it must be cheap and give the same answer each time: put
|
|
78
|
+
* anything with a side effect, anything slow and anything random or
|
|
79
|
+
* time-dependent inside `step.run`.
|
|
80
|
+
*
|
|
81
|
+
* Step keys are the identity of a step: unique within the workflow, and the
|
|
82
|
+
* same on every pass. Adding or removing a step between deploys is safe; a
|
|
83
|
+
* renamed step runs again.
|
|
84
|
+
*/
|
|
85
|
+
export declare class Workflow {
|
|
86
|
+
static name: string;
|
|
87
|
+
/**
|
|
88
|
+
* The workflow's body. Its return value, as JSON, is the workflow's
|
|
89
|
+
* `result`. A throw that escapes it fails the workflow.
|
|
90
|
+
*/
|
|
91
|
+
run(_step: Step, ..._args: any[]): unknown;
|
|
92
|
+
/**
|
|
93
|
+
* Runs once after `Workflow.cancel`, in place of `run`, with the same
|
|
94
|
+
* arguments: the place to undo what the steps did. Its steps are memoized
|
|
95
|
+
* like `run`'s (use keys of their own), so it may sleep or retry too.
|
|
96
|
+
*/
|
|
97
|
+
onCancel(_step: Step, ..._args: any[]): unknown;
|
|
98
|
+
/**
|
|
99
|
+
* Starts a workflow and resolves to its id. The workflow and its first tick
|
|
100
|
+
* are recorded in one atomic write. Inside an ORM transaction it belongs to
|
|
101
|
+
* the transaction, as a dispatch does: recorded with it, or held until it
|
|
102
|
+
* commits and dropped if it rolls back.
|
|
103
|
+
*/
|
|
104
|
+
static start<T extends Workflow>(this: new () => T, ...args: WorkflowArgs<T>): Promise<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Delivers `payload` to the workflow's `step.waitFor(key)`, and resolves to
|
|
107
|
+
* whether it was taken: `false` for an unknown or ended workflow, and for a
|
|
108
|
+
* key that was already signalled. A signal that arrives before the workflow
|
|
109
|
+
* reaches its `waitFor` is kept until it does.
|
|
110
|
+
*/
|
|
111
|
+
static signal(id: string, key: string, payload?: unknown): Promise<boolean>;
|
|
112
|
+
/** The workflow's status, or `null` for an unknown id. */
|
|
113
|
+
static find(id: string): Promise<WorkflowStatus | null>;
|
|
114
|
+
/**
|
|
115
|
+
* Cancels a workflow that has not ended, and resolves to whether it did.
|
|
116
|
+
* A running `step.batch` is cancelled with it, a running `step.run` is told
|
|
117
|
+
* through `ctx.signal`, and `onCancel` then runs once.
|
|
118
|
+
*/
|
|
119
|
+
static cancel(id: string): Promise<boolean>;
|
|
120
|
+
}
|
|
121
|
+
export type WorkflowClass = (new () => Workflow) & {
|
|
122
|
+
name: string;
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=Workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Workflow.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/Workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAExE,0DAA0D;AAC1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS;IAC1E,GAAG;IACH,GAAG,MAAM,IAAI;CACd,GACG,IAAI,GACJ,KAAK,CAAC;AAEV,sEAAsE;AACtE,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wCAAwC;IACxC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,QAAQ;IACnB,MAAM,CAAC,IAAI,SAAW;IAEtB;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO;IAI1C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO;IAI/C;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAC7B,IAAI,EAAE,UAAU,CAAC,EACjB,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,MAAM,CAAC;IAIlB;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3E,0DAA0D;IAC1D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAIvD;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG5C;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,UAAU,QAAQ,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Job } from "../Job";
|
|
2
|
+
import type { QueueManager } from "../QueueManager";
|
|
3
|
+
import type { WorkflowClass, WorkflowStatus } from "./Workflow";
|
|
4
|
+
import { type WorkflowStore } from "./WorkflowStore";
|
|
5
|
+
/**
|
|
6
|
+
* The queue's half of workflows: the registry of workflow classes, what
|
|
7
|
+
* `Workflow.start`, `signal`, `find` and `cancel` do, and the tick.
|
|
8
|
+
*
|
|
9
|
+
* ### The tick
|
|
10
|
+
*
|
|
11
|
+
* A workflow advances only inside its tick job, which takes the workflow
|
|
12
|
+
* from the store for a lease (the queue's `visibilityTimeout`, renewed while
|
|
13
|
+
* it runs), runs one pass of `run`, and lets go with the outcome written in
|
|
14
|
+
* the same step. Every write of the pass is fenced by that hold, so a tick
|
|
15
|
+
* that lost it (it was too slow and another took over) changes nothing.
|
|
16
|
+
*
|
|
17
|
+
* A tick that finds the workflow held by another is dropped, after marking
|
|
18
|
+
* the workflow so the holder enqueues a fresh tick when it lets go: a signal
|
|
19
|
+
* that lands mid-pass is never lost, and two passes of one workflow never
|
|
20
|
+
* overlap. A tick that failed or died holds the workflow under its job's id,
|
|
21
|
+
* so its own retry takes it straight back.
|
|
22
|
+
*/
|
|
23
|
+
export declare class WorkflowRuntime {
|
|
24
|
+
private readonly queue;
|
|
25
|
+
private registry;
|
|
26
|
+
private storeInstance;
|
|
27
|
+
private tickClass;
|
|
28
|
+
private readonly reportedNames;
|
|
29
|
+
constructor(queue: QueueManager);
|
|
30
|
+
/** The workflow classes this process can run, by `static name`. */
|
|
31
|
+
get workflows(): Readonly<Record<string, WorkflowClass>>;
|
|
32
|
+
/** Replaces the registry. The first class to claim a name wins. */
|
|
33
|
+
use(workflows: readonly WorkflowClass[]): void;
|
|
34
|
+
/** The internal job a workflow's passes run in, one class per manager. */
|
|
35
|
+
get tickJob(): new () => Job;
|
|
36
|
+
get store(): WorkflowStore;
|
|
37
|
+
start(workflow: WorkflowClass, args: unknown[]): Promise<string>;
|
|
38
|
+
signal(id: string, key: string, payload?: unknown): Promise<boolean>;
|
|
39
|
+
cancel(id: string): Promise<boolean>;
|
|
40
|
+
find(id: string): Promise<WorkflowStatus | null>;
|
|
41
|
+
/** One pass of the workflow `id`, run by its tick job. */
|
|
42
|
+
tick(id: string, job: Job): Promise<void>;
|
|
43
|
+
/** The tick's last write: the pass's outcome, and letting go. */
|
|
44
|
+
private finish;
|
|
45
|
+
/**
|
|
46
|
+
* A tick for a workflow this process has no class for. During a
|
|
47
|
+
* blue/green ramp that is usually one only the other release has, so on a
|
|
48
|
+
* shared driver it goes back for another replica until `unknownJobGrace`
|
|
49
|
+
* has passed since the workflow started; then it fails.
|
|
50
|
+
*/
|
|
51
|
+
private unknown;
|
|
52
|
+
/**
|
|
53
|
+
* The tick job ran out of attempts, which only a store that stayed
|
|
54
|
+
* unreachable causes. Fails the workflow if it still can, so it does not
|
|
55
|
+
* sit in `running` with nothing left to advance it.
|
|
56
|
+
*/
|
|
57
|
+
/** @internal */
|
|
58
|
+
tickDeadLettered(id: string, error: Error): void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=WorkflowRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowRuntime.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/WorkflowRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAQpD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAYzB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,eAAe;IAMd,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;gBAEtB,KAAK,EAAE,YAAY;IAEhD,mEAAmE;IACnE,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAEvD;IAED,mEAAmE;IACnE,GAAG,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE;IAoBvC,0EAA0E;IAC1E,IAAI,OAAO,IAAI,UAAU,GAAG,CAG3B;IAED,IAAI,KAAK,IAAI,aAAa,CAYzB;IAED,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoC1D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAuCpE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBpC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAuCtD,0DAA0D;IACpD,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA0G/C,iEAAiE;IACjE,OAAO,CAAC,MAAM;IA4Dd;;;;;OAKG;YACW,OAAO;IAgCrB;;;;OAIG;IACH,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAiB1C"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where workflows are kept (#846), and the one atomic operation everything a
|
|
3
|
+
* workflow does is built from.
|
|
4
|
+
*
|
|
5
|
+
* A store belongs to a queue driver (`QueueDriver.workflowStore`), because a
|
|
6
|
+
* workflow's writes and the jobs they schedule must commit together: a step
|
|
7
|
+
* that sleeps records the sleep and enqueues the tick that wakes it in one
|
|
8
|
+
* step, and `step.batch` records the step and dispatches the batch in one
|
|
9
|
+
* step, so a crash between the two can neither lose the wake-up nor fan out
|
|
10
|
+
* twice. The memory driver does each change synchronously; the database driver
|
|
11
|
+
* does it in a transaction that locks the workflow's row first.
|
|
12
|
+
*
|
|
13
|
+
* A store only keeps records. What a change means (when a step is done, when
|
|
14
|
+
* a workflow sleeps) is decided by the runtime, in the `decide` callback of
|
|
15
|
+
* `update`, while the store holds the workflow exclusively.
|
|
16
|
+
*/
|
|
17
|
+
import type { EnqueueBatch } from "../QueueDriver";
|
|
18
|
+
/** The registered name the internal tick job runs under. */
|
|
19
|
+
export declare const WORKFLOW_TICK_JOB = "gemi.WorkflowTick";
|
|
20
|
+
/**
|
|
21
|
+
* The most a step's output, a signal's payload or a workflow's result may be,
|
|
22
|
+
* as JSON, in bytes. Store an id for anything larger.
|
|
23
|
+
*/
|
|
24
|
+
export declare const WORKFLOW_OUTPUT_LIMIT: number;
|
|
25
|
+
/**
|
|
26
|
+
* Where a workflow stands.
|
|
27
|
+
*
|
|
28
|
+
* - `running`: a tick is running it, or one is queued to.
|
|
29
|
+
* - `sleeping`: waiting for a `step.sleep` or a step's retry backoff.
|
|
30
|
+
* - `waiting`: waiting for a signal (`step.waitFor`) or a batch (`step.batch`).
|
|
31
|
+
* - `cancelling`: `cancel` was accepted, and `onCancel` has not finished yet.
|
|
32
|
+
* - `completed`, `failed`, `cancelled`: final.
|
|
33
|
+
*/
|
|
34
|
+
export type WorkflowRunStatus = "running" | "sleeping" | "waiting" | "completed" | "failed" | "cancelling" | "cancelled";
|
|
35
|
+
/**
|
|
36
|
+
* Where one step stands. `signalled` is a signal that arrived before its
|
|
37
|
+
* `step.waitFor`, kept until the workflow gets there.
|
|
38
|
+
*/
|
|
39
|
+
export type StepRunStatus = "running" | "retrying" | "completed" | "failed" | "sleeping" | "waiting" | "signalled" | "timed_out" | "batching";
|
|
40
|
+
/** A workflow's row. Times are epoch milliseconds. */
|
|
41
|
+
export type WorkflowRecord = {
|
|
42
|
+
id: string;
|
|
43
|
+
/** The workflow class's `static name`. */
|
|
44
|
+
name: string;
|
|
45
|
+
/** The `run` arguments after `step`, as JSON. */
|
|
46
|
+
args: string;
|
|
47
|
+
status: WorkflowRunStatus;
|
|
48
|
+
/** The key of the step it is on, or `null`. */
|
|
49
|
+
currentStep: string | null;
|
|
50
|
+
/** 0 to 1, as `step.progress` last set it; 1 once completed. */
|
|
51
|
+
progress: number;
|
|
52
|
+
/** What `run` returned, as JSON, once completed. `null` for `undefined`. */
|
|
53
|
+
result: string | null;
|
|
54
|
+
error: string | null;
|
|
55
|
+
/** When the next tick that was scheduled for a wake-up is due, or `null`. */
|
|
56
|
+
wakeAt: number | null;
|
|
57
|
+
/** The tick holding the workflow, and until when (on the store's clock). */
|
|
58
|
+
lockedBy: string | null;
|
|
59
|
+
lockedUntil: number | null;
|
|
60
|
+
/** Another tick arrived while one held the workflow; see `update`'s `unlock`. */
|
|
61
|
+
retick: boolean;
|
|
62
|
+
createdAt: number;
|
|
63
|
+
updatedAt: number;
|
|
64
|
+
};
|
|
65
|
+
/** A step's row, unique per workflow and key. */
|
|
66
|
+
export type StepRecord = {
|
|
67
|
+
workflowId: string;
|
|
68
|
+
key: string;
|
|
69
|
+
status: StepRunStatus;
|
|
70
|
+
/** Attempts started, counting from 1. */
|
|
71
|
+
attempt: number;
|
|
72
|
+
/** The step's result or the signal's payload, as JSON. `null` for `undefined`. */
|
|
73
|
+
output: string | null;
|
|
74
|
+
error: string | null;
|
|
75
|
+
/** The batch a `step.batch` dispatched. */
|
|
76
|
+
batchId: string | null;
|
|
77
|
+
/** When a sleep ends, a wait times out, or a retry is due. */
|
|
78
|
+
wakeAt: number | null;
|
|
79
|
+
startedAt: number | null;
|
|
80
|
+
finishedAt: number | null;
|
|
81
|
+
createdAt: number;
|
|
82
|
+
updatedAt: number;
|
|
83
|
+
};
|
|
84
|
+
/** A workflow and its steps, in the order the steps were first recorded. */
|
|
85
|
+
export type WorkflowState = {
|
|
86
|
+
workflow: WorkflowRecord;
|
|
87
|
+
steps: StepRecord[];
|
|
88
|
+
};
|
|
89
|
+
export type AcquireResult = {
|
|
90
|
+
kind: "missing";
|
|
91
|
+
}
|
|
92
|
+
/** Another tick holds it; `retick` is set, so that tick runs it again. */
|
|
93
|
+
| {
|
|
94
|
+
kind: "busy";
|
|
95
|
+
} | ({
|
|
96
|
+
kind: "acquired";
|
|
97
|
+
} & WorkflowState);
|
|
98
|
+
/** What `update`'s `decide` sees, read while the workflow is held. */
|
|
99
|
+
export type WorkflowSnapshot = {
|
|
100
|
+
workflow: WorkflowRecord;
|
|
101
|
+
/** The step `key` names, or `null` when there is none (or no key was given). */
|
|
102
|
+
step: StepRecord | null;
|
|
103
|
+
/** Every step, when `allSteps` was asked for; otherwise empty. */
|
|
104
|
+
steps: StepRecord[];
|
|
105
|
+
/** This process's clock, for the wake-up times the runtime computes. */
|
|
106
|
+
now: number;
|
|
107
|
+
};
|
|
108
|
+
/** What `decide` wants written, all in the same atomic step. */
|
|
109
|
+
export type WorkflowChange<T> = {
|
|
110
|
+
/** What `update` resolves to. */
|
|
111
|
+
result: T;
|
|
112
|
+
workflow?: Partial<Pick<WorkflowRecord, "status" | "currentStep" | "progress" | "result" | "error" | "wakeAt">>;
|
|
113
|
+
/** The step's new row: inserted, or replacing the one under its key. */
|
|
114
|
+
step?: StepRecord;
|
|
115
|
+
/** A batch to dispatch, as `QueueDriver.enqueueBatch` would. */
|
|
116
|
+
batch?: EnqueueBatch;
|
|
117
|
+
/** Batches to cancel, as `QueueDriver.cancelBatch` would. */
|
|
118
|
+
cancelBatches?: string[];
|
|
119
|
+
/** Enqueue a tick for this workflow, claimable after `delayMs`. */
|
|
120
|
+
tick?: {
|
|
121
|
+
delayMs: number;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Release the tick's hold on the workflow. When another tick arrived while
|
|
125
|
+
* it was held (`retick`), a new tick is enqueued in the same step, so a
|
|
126
|
+
* signal that landed mid-tick is never lost.
|
|
127
|
+
*/
|
|
128
|
+
unlock?: boolean;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Whether two holds are attempts of the same tick job. A tick holds the
|
|
132
|
+
* workflow as `<tick job id>:<attempt>`, so a retry of a tick that failed or
|
|
133
|
+
* died takes the workflow straight back instead of waiting out the lease,
|
|
134
|
+
* and the earlier attempt's writes are refused from then on.
|
|
135
|
+
*/
|
|
136
|
+
export declare function sameTick(a: string, b: string): boolean;
|
|
137
|
+
export declare class WorkflowLeaseLostError extends Error {
|
|
138
|
+
constructor(id: string);
|
|
139
|
+
}
|
|
140
|
+
export interface WorkflowStore {
|
|
141
|
+
/**
|
|
142
|
+
* Records a new workflow and enqueues its first tick, in one atomic step.
|
|
143
|
+
* Like `QueueDriver.enqueue`, a store that answers `joinsTransaction`
|
|
144
|
+
* writes on the caller's ORM transaction.
|
|
145
|
+
*/
|
|
146
|
+
create(workflow: {
|
|
147
|
+
id: string;
|
|
148
|
+
name: string;
|
|
149
|
+
args: string;
|
|
150
|
+
}): Promise<void>;
|
|
151
|
+
/** Whether `create` would write on the caller's open ORM transaction. */
|
|
152
|
+
joinsTransaction?(): boolean;
|
|
153
|
+
/** The workflow, and its steps unless `steps: false`, or `null`. */
|
|
154
|
+
find(id: string, options?: {
|
|
155
|
+
steps?: boolean;
|
|
156
|
+
}): Promise<WorkflowState | null>;
|
|
157
|
+
/**
|
|
158
|
+
* Takes the workflow for one tick, for `leaseMs` on the store's clock, and
|
|
159
|
+
* returns its state. A workflow another tick holds under a live lease is
|
|
160
|
+
* `busy`, and is marked to be ticked again when that tick lets go; one held
|
|
161
|
+
* by an earlier attempt of the same tick job (see `sameTick`) is taken over.
|
|
162
|
+
*/
|
|
163
|
+
acquire(id: string, owner: string, leaseMs: number): Promise<AcquireResult>;
|
|
164
|
+
/** Extends the tick's lease, and resolves to whether it still held it. */
|
|
165
|
+
renew(id: string, owner: string, leaseMs: number): Promise<boolean>;
|
|
166
|
+
/**
|
|
167
|
+
* Reads the workflow (and the step `key`, or every step with `allSteps`)
|
|
168
|
+
* while holding it exclusively, calls `decide`, and writes what it returns,
|
|
169
|
+
* all in one atomic step. With `owner`, the write is refused with a
|
|
170
|
+
* `WorkflowLeaseLostError` unless that tick still holds the workflow.
|
|
171
|
+
* Resolves to `undefined` for an unknown workflow.
|
|
172
|
+
*/
|
|
173
|
+
update<T>(id: string, options: {
|
|
174
|
+
owner?: string;
|
|
175
|
+
key?: string;
|
|
176
|
+
allSteps?: boolean;
|
|
177
|
+
}, decide: (snapshot: WorkflowSnapshot) => WorkflowChange<T>): Promise<T | undefined>;
|
|
178
|
+
/**
|
|
179
|
+
* Deletes workflows that ended (completed, failed or cancelled) more than
|
|
180
|
+
* `olderThanMs` ago, with their steps, and resolves to how many.
|
|
181
|
+
*/
|
|
182
|
+
prune?(olderThanMs: number): Promise<number>;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=WorkflowStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowStore.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/WorkflowStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A length of time: milliseconds as a number, or a number and a unit, such as
|
|
3
|
+
* `"500ms"`, `"30s"`, `"5m"`, `"2h"`, `"7d"` or `"1w"`.
|
|
4
|
+
*/
|
|
5
|
+
export type Duration = number | `${number}${"ms" | "s" | "m" | "h" | "d" | "w"}`;
|
|
6
|
+
/** A `Duration` in milliseconds. Throws for anything else, on the caller's stack. */
|
|
7
|
+
export declare function toMilliseconds(duration: Duration): number;
|
|
8
|
+
//# sourceMappingURL=duration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/duration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAWjF,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAezD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { QueueDriver } from "../QueueDriver";
|
|
2
|
+
/**
|
|
3
|
+
* What workflows promise on every driver that keeps them, as a suite a
|
|
4
|
+
* driver's test file runs against itself:
|
|
5
|
+
*
|
|
6
|
+
* workflowContract("MemoryQueueDriver", async () => {
|
|
7
|
+
* const driver = new MemoryQueueDriver();
|
|
8
|
+
* return { driver: () => driver, dispose: async () => {} };
|
|
9
|
+
* });
|
|
10
|
+
*
|
|
11
|
+
* `storage` makes fresh, empty storage for one test. Its `driver()` returns
|
|
12
|
+
* a driver over it, a new one per call where the storage is shared (a
|
|
13
|
+
* database), so that two managers on two drivers are two processes. The
|
|
14
|
+
* workflows run end to end, through `QueueManager`s that claim the ticks.
|
|
15
|
+
*
|
|
16
|
+
* Not a `*.test.ts` file, so vitest never runs it on its own.
|
|
17
|
+
*/
|
|
18
|
+
export declare function workflowContract(name: string, storage: () => Promise<{
|
|
19
|
+
driver(): QueueDriver;
|
|
20
|
+
dispose(): Promise<void>;
|
|
21
|
+
}>, features?: {
|
|
22
|
+
/**
|
|
23
|
+
* Runs the test with two managers ticking the same workflows. Off for
|
|
24
|
+
* SQLite files: two clients in one thread are not two processes there,
|
|
25
|
+
* because SQLite's busy handler sleeps the very thread the lock holder
|
|
26
|
+
* needs to finish its transaction.
|
|
27
|
+
*/
|
|
28
|
+
concurrentWorkers?: boolean;
|
|
29
|
+
}): void;
|
|
30
|
+
//# sourceMappingURL=workflowContract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowContract.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/workflowContract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMlD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,OAAO,CAAC;IAAE,MAAM,IAAI,WAAW,CAAC;IAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,EAC3E,QAAQ,GAAE;IACR;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACC,QAogBhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewRouteDispatcher.d.ts","sourceRoot":"","sources":["../../../services/router/ViewRouteDispatcher.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ViewRouteDispatcher.d.ts","sourceRoot":"","sources":["../../../services/router/ViewRouteDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"../chunk-
|
|
2
|
+
import"../chunk-hm9cjxy2.js";import M from"path";import{writeFileSync as Q}from"fs";var L=new Set(["FILE","REDIRECT"]);function H(j){return j.run(()=>{let x=[];for(let{group:z,view:D}of j.domains().viewGroups())for(let[G,B]of Object.entries(D.flatViewRoutes)){let C=D.routeManifest[G]??B.segments.map((K)=>K.viewPath);if(C.length===0||L.has(C.at(-1)))continue;x.push({path:G,group:z,views:C,...B.static?{static:B.static.layout?{layout:B.static.layout}:{}}:{}})}return x})}var J=process.argv[2];async function U(){if(!J)throw Error("usage: route-table <out.json>");let j=M.resolve(process.cwd(),"app/kernel/Kernel.ts"),x=await import(j);if(typeof x.default!=="function")throw Error(`${j} has no default export (the Kernel subclass).`);let z=new x.default;z.boot();try{Q(J,JSON.stringify(H(z)))}finally{z.destroy()}}U().then(()=>process.exit(0),(j)=>{console.error(j?.stack??String(j)),process.exit(1)});
|
|
3
3
|
|
|
4
4
|
//# debugId=2C354352EBF6475164756E2164756E21
|
package/dist/support/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Yc as Y}from"../chunk-30xxc6r7.js";import{Nh as M}from"../chunk-gqfqnv3f.js";import{Pi as P,Ri as R}from"../chunk-g5ppst76.js";import"../chunk-d806cy7p.js";import{$i as U,_i as Q,aj as V,bj as W}from"../chunk-jg79n382.js";import"../chunk-hm9cjxy2.js";class S{static token;async boot(){}static inject(){if(!this.token)throw Error(`Service [${this.name}] does not declare a \`static token\`, so the container has no key to resolve it by.`);try{return R(this)}catch(x){throw Error(`Could not inject [${this.name}]. Services are constructed when the kernel boots, so `+"inject() only works from code that runs after that \u2014 a constructor default or a method "+`body, never module top level. Check that [${this.name}] is listed in \`services\` on your Kernel.`,{cause:x})}}static with(x){let f=new this;for(let[C,g]of Object.entries(x))if(g!==void 0)f[C]=g;return f}}import{readdir as z}from"fs/promises";import{join as B,parse as j}from"path";var H=[".ts",".tsx",".js",".mjs",".jsx"];function J(x={}){let f={};for(let[C,g]of Object.entries(x))f[C]=q(g);return new P(f)}async function L(x,f=new P){let C=[];try{C=await z(x)}catch(D){return f}let g=C.filter((D)=>{let{ext:v,name:F}=j(D);return H.includes(v)&&!F.startsWith(".")}).sort();for(let D of g){let{name:v}=j(D),F=await import(B(x,D));f.set(v,q(F))}return f}function q(x){if(x&&typeof x==="object"&&"default"in x)return x.default;return x}export{M as withDefaults,Q as sourceFiles,W as projectRoot,L as loadConfigFrom,V as discoverClasses,J as createConfigRepository,Y as ServiceProvider,S as Service,P as Repository,U as DiscoveryError};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=FCAD65B465AB6EA064756E2164756E21
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"import { readdir } from \"node:fs/promises\";\nimport { join, parse } from \"node:path\";\n\nimport { Repository } from \"./Repository\";\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".mjs\", \".jsx\"];\n\n// Builds a Repository from an already-imported map of config modules. The map\n// key becomes the top-level config key, so `{ mail: mailModule }` is readable\n// as `config.get(\"mail.driver\")`. Each entry may be either the module namespace\n// (its `default` export is unwrapped) or the config object itself.\nexport function createConfigRepository(\n modules: Record<string, any> = {},\n): Repository {\n const items: Record<string, any> = {};\n\n for (const [key, mod] of Object.entries(modules)) {\n items[key] = unwrap(mod);\n }\n\n return new Repository(items);\n}\n\n// Reads every config module in an app's `app/config` directory into a\n// Repository. The file's basename is the top-level key: `app/config/mail.ts`\n// populates `mail.*`. A missing directory yields an empty Repository so apps\n// that declare no config still boot.\nexport async function loadConfigFrom(\n directory: string,\n repository = new Repository(),\n): Promise<Repository> {\n let entries: string[] = [];\n\n try {\n entries = await readdir(directory);\n } catch (err) {\n return repository;\n }\n\n const files = entries\n .filter((entry) => {\n const { ext, name } = parse(entry);\n return CONFIG_EXTENSIONS.includes(ext) && !name.startsWith(\".\");\n })\n .sort();\n\n for (const file of files) {\n const { name } = parse(file);\n const mod = await import(join(directory, file));\n repository.set(name, unwrap(mod));\n }\n\n return repository;\n}\n\nfunction unwrap(mod: any) {\n if (mod && typeof mod === \"object\" && \"default\" in mod) {\n return mod.default;\n }\n return mod;\n}\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": ";2RAgCO,CAAe,JAAQ,EAOrB,OAMD,AAAI,EAAkB,QAmBrB,OAAS,EAKX,CACH,GAAI,CAAC,KAAK,MACR,MAAU,MACR,YAAY,KAAK,0FACnB,EAGF,GAAI,CACF,OAAO,EAAI,IAAuB,EAClC,MAAO,EAAO,CACd,MAAU,MACR,qBAAqB,KAAK,6DACxB,+FACA,6CAA6C,KAAK,kDAEpD,CAAE,OAAM,CACV,SAoBG,KAAuB,CAAoB,EAA0B,CAC1E,IAAM,EAAW,IAAI,KACrB,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAS,EACjD,GAAI,IAAU,OAAW,EAAS,GAAO,EAE3C,OAAO,EAEX,CChHA,kBAAS,oBACT,eAAS,WAAM,aAIf,IAAM,EAAoB,CAAC,MAAO,OAAQ,MAAO,OAAQ,MAAM,EAMxD,SAAS,CAAsB,CACpC,EAA+B,CAAC,EACpB,CACZ,IAAM,EAA6B,CAAC,EAEpC,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAO,EAC7C,EAAM,GAAO,EAAO,CAAG,EAGzB,OAAO,IAAI,EAAW,CAAK,EAO7B,eAAsB,CAAc,CAClC,EACA,EAAa,IAAI,EACI,CACrB,IAAI,EAAoB,CAAC,EAEzB,GAAI,CACF,EAAU,MAAM,EAAQ,CAAS,EACjC,MAAO,EAAK,CACZ,OAAO,EAGT,IAAM,EAAQ,EACX,OAAO,CAAC,IAAU,CACjB,IAAQ,MAAK,QAAS,EAAM,CAAK,EACjC,OAAO,EAAkB,SAAS,CAAG,GAAK,CAAC,EAAK,WAAW,GAAG,EAC/D,EACA,KAAK,EAER,QAAW,KAAQ,EAAO,CACxB,IAAQ,QAAS,EAAM,CAAI,EACrB,EAAM,MAAa,SAAK,EAAW,CAAI,GAC7C,EAAW,IAAI,EAAM,EAAO,CAAG,CAAC,EAGlC,OAAO,EAGT,SAAS,CAAM,CAAC,EAAU,CACxB,GAAI,GAAO,OAAO,IAAQ,UAAY,YAAa,EACjD,OAAO,EAAI,QAEb,OAAO",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "FCAD65B465AB6EA064756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/vitest/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{fa as B,ga as D}from"../chunk-n4sdm0jn.js";import"../chunk-5dbpgyrx.js";import"../chunk-m4kmetpb.js";import{Aa as J}from"../chunk-6ggmk2eg.js";import"../chunk-kk77x2v4.js";import"../chunk-hm9cjxy2.js";function N(){return{name:"gemi-custom-request",enforce:"pre",async transform(G,H){let j=H.split("?",1)[0];if(j.includes("/node_modules/")||!B.test(j))return null;return{code:await D(G),map:null}}}}export{N as gemiRequestPlugin,J as gemiIslandPlugin};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=C11E8611E15123D864756E2164756E21
|
package/dist/vitest/index.js.map
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import type { Plugin } from \"vite\";\nimport {\n CUSTOM_REQUEST_FILTER,\n customRequestParser,\n} from \"../bun/customRequestParser\";\n\n/**\n * The request-param rewrite, as a Vite plugin, for running an app's routes\n * under vitest.\n *\n * gemi calls a route handler and a controller method with no arguments, and a\n * handler written `async (req: HttpRequest<…>) => …` only gets its request\n * because the build rewrites it to `async (req = new HttpRequest()) => …`, which\n * reads the current request from the request context. The app's build and dev\n * server get that rewrite from `gemi/bun/plugin`. Vitest loads modules through\n * Vite instead, even under `bun --bun vitest`, so without this plugin a route\n * dispatched with `App.fetch` in a test sees `req === undefined`.\n *\n * Same transform, same files (`/http/controllers/` and `/http/routes/`) as the\n * Bun plugin. `enforce: \"pre\"` so it sees the TypeScript annotations before\n * Vite strips them.\n *\n * ```ts\n * // vitest.config.ts\n * import { defineConfig } from \"vitest/config\";\n * import { gemiRequestPlugin } from \"gemi/vitest\";\n *\n * export default defineConfig({ plugins: [gemiRequestPlugin()] });\n * ```\n */\nexport function gemiRequestPlugin(): Plugin {\n return {\n name: \"gemi-custom-request\",\n enforce: \"pre\",\n async transform(code, id) {\n const path = id.split(\"?\", 1)[0];\n if (path.includes(\"/node_modules/\") || !CUSTOM_REQUEST_FILTER.test(path)) {\n return null;\n }\n return { code: await customRequestParser(code), map: null };\n },\n };\n}\n\n/**\n * gemi's island transform, for an app's `vitest.config.ts`: with it, a test\n * that renders a static view through `App.fetch` sees each\n * `island(() => import(\"./Counter\"))` with the same module key as the build,\n * and a hydrated view renders the component in place instead of lazily.\n *\n * Without it islands still render (the component is loaded with the\n * `import()`), but their keys are unknown.\n *\n * ```ts\n * // vitest.config.ts\n * import { defineConfig } from \"vitest/config\";\n * import { gemiIslandPlugin, gemiRequestPlugin } from \"gemi/vitest\";\n *\n * export default defineConfig({ plugins: [gemiRequestPlugin(), gemiIslandPlugin()] });\n * ```\n */\nexport { gemiIslandPlugin } from \"../vite/islandPlugin\";\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";yOA8BO,IAAS,JAAiB,HAAW,JAC1C,CAAO,CACL,KAAM,sBACN,QAAS,WACH,UAAS,CAAC,EAAM,EAAI,CACxB,IAAM,EAAO,EAAG,MAAM,IAAK,CAAC,EAAE,GAC9B,GAAI,EAAK,SAAS,gBAAgB,GAAK,CAAC,EAAsB,KAAK,CAAI,EACrE,OAAO,KAET,MAAO,CAAE,KAAM,MAAM,EAAoB,CAAI,EAAG,IAAK,IAAK,EAE9D",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "C11E8611E15123D864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/package.json
CHANGED
package/dist/chunk-1q9kd20m.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Kc as o}from"./chunk-v1tfdgy1.js";import{Lc as i}from"./chunk-n672d4g8.js";import{_g as t}from"./chunk-cbqazg9k.js";import{Zh as r}from"./chunk-jmg2zsaf.js";class n extends i{register(){this.app.singleton(r,()=>new r(t(o(),this.app.config.get("translation",{}))))}}
|
|
3
|
-
export{n as eb};
|
|
4
|
-
|
|
5
|
-
//# debugId=C32FA7347CB1EE1064756E2164756E21
|
package/dist/chunk-49nyyjfe.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{AsyncLocalStorage as E}from"async_hooks";class Q{content={title:"Gemi App",description:null,openGraph:null,htmlAttributes:null,canonical:null,alternates:null};touched=!1;render(){return{title:this.content.title,description:this.content.description,openGraph:this.content.openGraph,htmlAttributes:this.content.htmlAttributes,canonical:this.content.canonical,alternates:this.content.alternates}}htmlAttributes(j){this.touched=!0;let B=Object.fromEntries(Object.entries(j).filter(([,z])=>z!==void 0));this.content.htmlAttributes={...this.content.htmlAttributes,...B}}canonical(j){this.touched=!0,this.content.canonical=j}alternates(j){this.touched=!0,this.content.alternates=j}title(j){this.touched=!0,this.content.title=j}description(j){this.touched=!0,this.content.description=j}openGraph({title:j,description:B,type:z,url:G,image:J,imageAlt:U,imageWidth:V,imageHeight:X,twitterImage:Y=J,twitterImageAlt:K=U,twitterImageWidth:N=V,twitterImageHeight:b=X}){this.touched=!0;let Z=J,$=Y;if(J&&!J.startsWith("http"))Z=`${process.env.HOST_NAME}${J}`,$=`${process.env.HOST_NAME}${Y}`;this.content.openGraph=Object.fromEntries(Object.entries({title:j,description:B,type:z,url:G,image:Z,imageAlt:U,imageWidth:V,imageHeight:X,twitterImage:$,twitterImageAlt:K,twitterImageWidth:N,twitterImageHeight:b}).filter(([H,M])=>M!==void 0))}}function F(j,B,z={}){return[`${j}=${B}`,z.maxAge?`Max-Age=${z.maxAge}`:"",z.httpOnly?"HttpOnly":"",z.secure?"Secure":"",z.sameSite?`SameSite=${z.sameSite}`:"SameSite=Strict",z.path?`Path=${z.path}`:"Path=/",z.domain?`Domain=${z.domain}`:"",z.expires?`Expires=${z.expires.toUTCString()}`:"",z.partitioned?"Partitioned":""].filter((G)=>G!=="").join("; ")}var P=new E;class L{req;cookies=new Set;headers=new Headers;serverQueries=null;user=null;csrfHmac=null;locale=null;metadata=new Q;rangeRequest=null;sessionId=null;featureEvaluations=null;featureContext=null;featureBuckets=null;pendingWork=new Set;ended=!1;constructor(j){this.req=j}waitUntil(j){if(this.ended)return;let B=Promise.resolve(j).then(()=>{},()=>{});this.pendingWork.add(B),B.then(()=>this.pendingWork.delete(B))}hasPendingWork(){return this.pendingWork.size>0}async whenIdle(){while(this.pendingWork.size>0)await Promise.all(Array.from(this.pendingWork))}setLocale(j){this.locale=j}renderMeta(){return this.metadata.render()}setCSRFHmac(j){this.csrfHmac=j}setCookie(j,B,z={}){this.cookies.add(F(j,B,z))}deleteCookie(j,B={}){this.cookies.add(F(j,"",{...B,maxAge:-1}))}setHeaders(j,B){this.headers.set(j,B)}setUser(j){this.user=j}setRequest(j){this.req=j}destroy(){this.ended=!0,delete this.cookies,delete this.headers,this.serverQueries=null,this.sessionId=null,this.featureEvaluations=null,this.featureContext=null,this.featureBuckets=null,delete this.user}}var D="session_id";function y(){let j=T.getStore();if(!j)return null;if(j.sessionId)return j.sessionId;let B=j.req?.cookies?.get(D);if(B)j.sessionId=B;return j.sessionId}function A(){let j=T.getStore();if(!j)return null;let B=y();if(B)return B;let z=Bun.randomUUIDv7();return j.sessionId=z,j.setCookie(D,z,{httpOnly:!0,secure:Bun.env.NODE_ENV==="production",sameSite:"Lax",expires:new Date(Date.now()+31536000000)}),z}class T{static getStore(){return P.getStore()}static setRequest(j){P.getStore().req=j}static run(j,B,z){let G=new L(j);if(z)G.user=z.user;return P.run(G,B)}static runWith(j,B){return P.run(j,B)}static exit(j){return P.exit(j)}}
|
|
3
|
-
export{y as Ug,A as Vg,T as Wg};
|
|
4
|
-
|
|
5
|
-
//# debugId=6CD53DADDD8CD4E664756E2164756E21
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../http/requestContext.ts", "../http/Metadata.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { HttpRequest } from \"./HttpRequest\";\nimport { Metadata } from \"./Metadata\";\nimport type { ByteRange } from \"./range\";\n// Type-only: `services/router` imports from `http`, so a runtime import here\n// would be circular.\nimport type { ServerQueryStore } from \"../services/router/ServerQueryStore\";\n\nexport interface CreateCookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\";\n path?: string;\n domain?: string;\n partitioned?: boolean;\n}\n\nexport function createCookie(\n name: string,\n value: string,\n options: CreateCookieOptions = {},\n) {\n return [\n `${name}=${value}`,\n options.maxAge ? `Max-Age=${options.maxAge}` : \"\",\n options.httpOnly ? \"HttpOnly\" : \"\",\n options.secure ? \"Secure\" : \"\",\n options.sameSite ? `SameSite=${options.sameSite}` : \"SameSite=Strict\",\n options.path ? `Path=${options.path}` : \"Path=/\",\n options.domain ? `Domain=${options.domain}` : \"\",\n options.expires ? `Expires=${options.expires.toUTCString()}` : \"\",\n options.partitioned ? \"Partitioned\" : \"\",\n ]\n .filter((i) => i !== \"\")\n .join(\"; \");\n}\n\nconst requestContext = new AsyncLocalStorage<Store>();\n\n/**\n * What a route's request context takes over from the global middleware list's\n * (see `runGlobalMiddleware`): the user, so one the list resolved is not\n * looked up a second time.\n */\nexport interface CarriedContext {\n user: any;\n}\n\nclass Store {\n cookies: Set<string> = new Set();\n headers: Headers = new Headers();\n /**\n * Every server-side query of this request — prefetched or discovered during\n * the streaming render. Assigned by the view router (or lazily by the\n * `Query` facade); `null` for api requests, which must not query themselves.\n */\n serverQueries: ServerQueryStore | null = null;\n user: any = null;\n csrfHmac: string | null = null;\n locale: string | null = null;\n metadata = new Metadata();\n /**\n * The parsed `Range` of the in-flight request, picked up by\n * `FileStorage.read()` so a range reaches the storage backend without every\n * handler having to thread it through by hand.\n *\n * Only populated inside a `this.stream()` route, and cleared once that route\n * returns: a `FileStorage.read()` in an ordinary handler must never start\n * silently returning partial bytes.\n */\n rangeRequest: ByteRange | null = null;\n\n /**\n * This request's `session_id`, once read or minted.\n *\n * The cookie itself cannot answer for it. `setCookie` appends a *serialized*\n * `Set-Cookie` string to `cookies`, so a value written during this request is\n * not readable back out of it, and `req.cookies` still holds only what the\n * browser sent. Anything needing the id in the same request that mints it —\n * feature-flag bucketing, most obviously — has to read it from here.\n */\n sessionId: string | null = null;\n\n /**\n * This request's feature-flag evaluations, computed once.\n *\n * One map per request is what keeps a handler and the SSR payload from\n * disagreeing: a percentage rollout evaluated twice would be consistent\n * anyway — the bucketing is deterministic — but an attribute hook reading a\n * clock, or a `now`-based rule, would not be. Anything the page renders and\n * anything the server branched on have to be the same answer.\n */\n featureEvaluations: Map<string, unknown> | null = null;\n /** The context those evaluations were made against, built at most once. */\n featureContext: unknown = null;\n /** Bucket memo, shared across every flag evaluated for this request. */\n featureBuckets: Map<string, number> | null = null;\n\n /**\n * What `waitUntil` was handed and has not settled yet. Public only because\n * `req.ctx()`'s declared type spells this class out, which a private field\n * cannot be part of; nothing outside the store should touch either.\n */\n pendingWork = new Set<Promise<void>>();\n ended = false;\n\n constructor(public req: HttpRequest) {}\n\n /**\n * Keeps this request open until `work` settles: the api router holds\n * `onRequestEnd` and `destroy()` back until then, so code in `work` still\n * finds `user`, headers and cookies here.\n *\n * For work that outlives the response on purpose. An agent run is the\n * reason it exists: a client that disconnects has not stopped the run, and\n * its next tool call still reads the user who started it. Ignored once the\n * request has ended — there is nothing left to hold open.\n *\n * Only api routes honour this. A view request ends regardless, so work\n * handed to its store — a run started in a view loader — finds no user.\n */\n waitUntil(work: PromiseLike<unknown>) {\n if (this.ended) {\n return;\n }\n const settled = Promise.resolve(work).then(\n () => {},\n () => {},\n );\n this.pendingWork.add(settled);\n void settled.then(() => this.pendingWork.delete(settled));\n }\n\n /** Whether anything handed to `waitUntil` is still running. */\n hasPendingWork() {\n return this.pendingWork.size > 0;\n }\n\n /**\n * Settles once everything handed to `waitUntil` has, including work added\n * while waiting — a run can start another before it ends.\n */\n async whenIdle() {\n while (this.pendingWork.size > 0) {\n await Promise.all(Array.from(this.pendingWork));\n }\n }\n\n setLocale(locale: string) {\n this.locale = locale;\n }\n\n renderMeta() {\n return this.metadata.render();\n }\n\n setCSRFHmac(hmac: string) {\n this.csrfHmac = hmac;\n }\n\n setCookie(name: string, value: string, options: CreateCookieOptions = {}) {\n this.cookies.add(createCookie(name, value, options));\n }\n\n /**\n * A cookie set with a `domain` or `path` is only cleared by a deletion that\n * names the same ones.\n */\n deleteCookie(name: string, options: Pick<CreateCookieOptions, \"domain\" | \"path\"> = {}) {\n this.cookies.add(createCookie(name, \"\", { ...options, maxAge: -1 }));\n }\n\n setHeaders(name: string, value: string) {\n this.headers.set(name, value);\n }\n\n setUser(user: any) {\n this.user = user;\n }\n\n setRequest(req: HttpRequest<any, any>) {\n this.req = req;\n }\n\n destroy() {\n this.ended = true;\n delete this.cookies;\n delete this.headers;\n this.serverQueries = null;\n this.sessionId = null;\n this.featureEvaluations = null;\n this.featureContext = null;\n this.featureBuckets = null;\n delete this.user;\n }\n}\n\nexport const SESSION_ID_COOKIE = \"session_id\";\n\n/**\n * The `session_id` the browser sent, or the one minted earlier in this request.\n * Never mints one, so it is safe on an api request, where a `Set-Cookie` nobody\n * asked for would be a surprise.\n *\n * `null` outside a request, and for an anonymous visitor whose first request is\n * not a view — both meaning \"no stable subject\", which callers must handle\n * rather than paper over with a random value. A per-call random id would give\n * every request its own bucket, which is worse than no bucketing at all: a\n * percentage rollout would reshuffle on every page load.\n *\n * ## It is client-supplied, and unauthenticated\n *\n * Whatever the browser sent, unvalidated. It is a bucketing subject, not a\n * credential — never authenticate or authorize on it. A visitor can pick a value\n * that lands them in any percentage rollout, and signing it would not change\n * that: they can discard the cookie and collect fresh ones until one does. Load\n * bearing enough to state, because `.feature()` route gating is built on top of\n * evaluation — see its documentation for what may safely gate a route.\n */\nexport function sessionId(): string | null {\n const store = RequestContext.getStore();\n if (!store) {\n return null;\n }\n if (store.sessionId) {\n return store.sessionId;\n }\n const sent = store.req?.cookies?.get(SESSION_ID_COOKIE);\n if (sent) {\n store.sessionId = sent;\n }\n return store.sessionId;\n}\n\n/**\n * The same, but mints and sets the cookie when the browser sent none.\n *\n * Call this once per **view** request, early enough that everything downstream —\n * flag evaluation included — sees the same id the browser is about to be given.\n * It used to live inline in `ViewRouteDispatcher.onRequestEnd`, which ran only\n * on the document path and only after the response was decided, so a client-side\n * navigation minted nothing and a first-ever visitor had no id at the point\n * flags were evaluated.\n */\nexport function ensureSessionId(): string | null {\n const store = RequestContext.getStore();\n if (!store) {\n return null;\n }\n const existing = sessionId();\n if (existing) {\n return existing;\n }\n\n const minted = Bun.randomUUIDv7();\n store.sessionId = minted;\n store.setCookie(SESSION_ID_COOKIE, minted, {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n // `Lax`, not `Strict`, and the difference is load-bearing. `Strict`\n // withholds the cookie on cross-site *top-level navigation*, so a visitor\n // arriving from a search result or a shared link would arrive without it,\n // be minted a new id, and overwrite the old one — re-bucketing on every\n // external entry, which is how most anonymous traffic arrives. This is not\n // a credential (`access_token` stays `Strict`); it is an opaque bucketing\n // id, and `Lax` still blocks cross-site POST.\n sameSite: \"Lax\",\n expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365),\n });\n return minted;\n}\n\nexport class RequestContext {\n static getStore() {\n return requestContext.getStore()!;\n }\n\n static setRequest(req: HttpRequest<any, any>) {\n requestContext.getStore().req = req;\n }\n\n /**\n * Opens a fresh request scope. `carried` seeds it with what the global\n * middleware list resolved for the same request; nothing else crosses over.\n */\n static run<T>(\n httpRequest: HttpRequest,\n fn: () => T,\n carried?: CarriedContext | null,\n ): T {\n const store = new Store(httpRequest);\n if (carried) {\n store.user = carried.user;\n }\n return requestContext.run(store, fn);\n }\n\n /**\n * Re-enters an *existing* request scope. Stream lifecycle callbacks fire\n * after the HTTP server has taken over the response body — outside the\n * AsyncLocalStorage scope the request ran in — so the view router captures\n * the live store and re-enters it around user-facing hooks, keeping\n * `req.ctx()` (and everything context-backed) working inside them.\n */\n static runWith<T>(store: Store, fn: () => T): T {\n return requestContext.run(store, fn);\n }\n\n /**\n * Runs `fn` outside any request scope, as the server's own `fetch` handler\n * is. For a request dispatched from inside another one, which must start from\n * where a client's request would, not from its initiator's store.\n */\n static exit<T>(fn: () => T): T {\n return requestContext.exit(fn);\n }\n}\n",
|
|
6
|
-
"export type OpenGraphParams = {\n title: string;\n description?: string;\n type: string;\n url: string;\n image: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n twitterImage?: string;\n twitterImageAlt?: string;\n twitterImageWidth?: number;\n twitterImageHeight?: number;\n};\n/**\n * Attributes for the document's `<html>` element, handed to the root (or a\n * static view's) layout as its `htmlAttributes` prop.\n */\nexport type HtmlAttributes = {\n /** The document's language, e.g. `\"tr\"`. Defaults to the request's locale. */\n lang?: string;\n /** Text direction. Defaults to the one `lang` is written in. */\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n};\n\n/** One `<link rel=\"alternate\" hreflang>`: the same page in another language. */\nexport type AlternateLink = {\n /** A BCP 47 tag, or `\"x-default\"` for the page to use when none matches. */\n hrefLang: string;\n href: string;\n};\n\nexport class Metadata {\n content: any = {\n title: \"Gemi App\",\n description: null,\n openGraph: null,\n htmlAttributes: null,\n canonical: null,\n alternates: null,\n };\n\n /**\n * Whether a handler set anything, as opposed to `content` still being the\n * defaults. A partially rendered response that touched no metadata sends\n * none, so the client keeps what the skipped segments put there.\n */\n touched = false;\n\n render() {\n return {\n title: this.content.title,\n description: this.content.description,\n openGraph: this.content.openGraph,\n htmlAttributes: this.content.htmlAttributes,\n canonical: this.content.canonical,\n alternates: this.content.alternates,\n };\n }\n\n /** Merged into what earlier calls set; `undefined` leaves an attribute alone. */\n htmlAttributes(attributes: HtmlAttributes) {\n this.touched = true;\n const defined = Object.fromEntries(\n Object.entries(attributes).filter(([, value]) => value !== undefined),\n );\n this.content.htmlAttributes = { ...this.content.htmlAttributes, ...defined };\n }\n\n canonical(url: string) {\n this.touched = true;\n this.content.canonical = url;\n }\n\n alternates(links: AlternateLink[]) {\n this.touched = true;\n this.content.alternates = links;\n }\n\n title(title: string) {\n this.touched = true;\n this.content.title = title;\n }\n\n description(description: string) {\n this.touched = true;\n this.content.description = description;\n }\n\n openGraph({\n title,\n description,\n type,\n url,\n image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage = image,\n twitterImageAlt = imageAlt,\n twitterImageWidth = imageWidth,\n twitterImageHeight = imageHeight,\n }: OpenGraphParams) {\n this.touched = true;\n let _image = image;\n let _twitterImage = twitterImage;\n if (image && !image.startsWith(\"http\")) {\n _image = `${process.env.HOST_NAME}${image}`;\n _twitterImage = `${process.env.HOST_NAME}${twitterImage}`;\n }\n this.content.openGraph = Object.fromEntries(\n Object.entries({\n title,\n description,\n type,\n url,\n image: _image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage: _twitterImage,\n twitterImageAlt,\n twitterImageWidth,\n twitterImageHeight,\n }).filter(([_, value]) => value !== undefined),\n );\n }\n}\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": "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",
|
|
9
|
-
"debugId": "6CD53DADDD8CD4E664756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|