gemi 0.114.0 → 0.116.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 +1 -1
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-75wk4jxd.js → chunk-15c2vgaf.js} +2 -2
- package/dist/{chunk-75wk4jxd.js.map → chunk-15c2vgaf.js.map} +1 -1
- package/dist/{chunk-56fgk5rq.js → chunk-1hr4xht1.js} +2 -2
- package/dist/{chunk-56fgk5rq.js.map → chunk-1hr4xht1.js.map} +1 -1
- package/dist/{chunk-8c2fs0n0.js → chunk-1myhm0g3.js} +3 -3
- package/dist/{chunk-8c2fs0n0.js.map → chunk-1myhm0g3.js.map} +1 -1
- package/dist/chunk-1q9kd20m.js +5 -0
- package/dist/{chunk-fakvf9wb.js.map → chunk-1q9kd20m.js.map} +1 -1
- package/dist/{chunk-37qk5dh8.js → chunk-1vzks22y.js} +2 -2
- package/dist/{chunk-37qk5dh8.js.map → chunk-1vzks22y.js.map} +1 -1
- package/dist/{chunk-8h7dh2h2.js → chunk-2tzm58j3.js} +2 -2
- package/dist/{chunk-8h7dh2h2.js.map → chunk-2tzm58j3.js.map} +1 -1
- package/dist/{chunk-x157wrgy.js → chunk-3hrj5rwm.js} +2 -2
- package/dist/{chunk-x157wrgy.js.map → chunk-3hrj5rwm.js.map} +1 -1
- package/dist/{chunk-wysm6qte.js → chunk-4088szy9.js} +2 -2
- package/dist/{chunk-wysm6qte.js.map → chunk-4088szy9.js.map} +1 -1
- package/dist/{chunk-m17ktssc.js → chunk-41da9628.js} +1 -1
- package/dist/chunk-49nyyjfe.js +5 -0
- package/dist/{chunk-jzp0fs6h.js.map → chunk-49nyyjfe.js.map} +3 -3
- package/dist/{chunk-cna105t6.js → chunk-56jky6vf.js} +2 -2
- package/dist/{chunk-cna105t6.js.map → chunk-56jky6vf.js.map} +1 -1
- package/dist/{chunk-h4pazcgg.js → chunk-6cx8ncd4.js} +2 -2
- package/dist/{chunk-h4pazcgg.js.map → chunk-6cx8ncd4.js.map} +1 -1
- package/dist/{chunk-7fwp7vwh.js → chunk-6d8rvr1v.js} +2 -2
- package/dist/{chunk-7fwp7vwh.js.map → chunk-6d8rvr1v.js.map} +1 -1
- package/dist/{chunk-h2r2rdhj.js → chunk-785b41h1.js} +2 -2
- package/dist/{chunk-h2r2rdhj.js.map → chunk-785b41h1.js.map} +1 -1
- package/dist/{chunk-7v8sgqen.js → chunk-79xg42e7.js} +2 -2
- package/dist/{chunk-7v8sgqen.js.map → chunk-79xg42e7.js.map} +1 -1
- package/dist/{chunk-8rt4wx8z.js → chunk-7vb4eey2.js} +2 -2
- package/dist/{chunk-8rt4wx8z.js.map → chunk-7vb4eey2.js.map} +1 -1
- package/dist/{chunk-ap5gek56.js → chunk-8rv62v14.js} +2 -2
- package/dist/{chunk-ap5gek56.js.map → chunk-8rv62v14.js.map} +1 -1
- package/dist/{chunk-1f9sqht5.js → chunk-98m15b9x.js} +2 -2
- package/dist/{chunk-1f9sqht5.js.map → chunk-98m15b9x.js.map} +1 -1
- package/dist/{chunk-d4m4amy4.js → chunk-9n1hx3mq.js} +2 -2
- package/dist/{chunk-d4m4amy4.js.map → chunk-9n1hx3mq.js.map} +1 -1
- package/dist/{chunk-erxv1jz7.js → chunk-aazmrxj9.js} +2 -2
- package/dist/{chunk-erxv1jz7.js.map → chunk-aazmrxj9.js.map} +1 -1
- package/dist/{chunk-pmywkp1w.js → chunk-aeh67ynz.js} +3 -3
- package/dist/{chunk-pmywkp1w.js.map → chunk-aeh67ynz.js.map} +1 -1
- package/dist/{chunk-hz6yzzbz.js → chunk-agyfv3f8.js} +1 -1
- package/dist/{chunk-tp3mzj4v.js → chunk-bra1a1fq.js} +2 -2
- package/dist/{chunk-tp3mzj4v.js.map → chunk-bra1a1fq.js.map} +1 -1
- package/dist/{chunk-583vxa2v.js → chunk-cbqazg9k.js} +2 -2
- package/dist/{chunk-583vxa2v.js.map → chunk-cbqazg9k.js.map} +1 -1
- package/dist/{chunk-m2yfvwrn.js → chunk-d2gfcf85.js} +2 -2
- package/dist/{chunk-m2yfvwrn.js.map → chunk-d2gfcf85.js.map} +1 -1
- package/dist/{chunk-4szjp84e.js → chunk-d9mar37g.js} +2 -2
- package/dist/{chunk-4szjp84e.js.map → chunk-d9mar37g.js.map} +1 -1
- package/dist/{chunk-a5sbgffr.js → chunk-e573yxpq.js} +1 -1
- package/dist/{chunk-gdmsn3f5.js → chunk-eqse2m6n.js} +2 -2
- package/dist/{chunk-gdmsn3f5.js.map → chunk-eqse2m6n.js.map} +1 -1
- package/dist/{chunk-jyrsd1dn.js → chunk-er3wf6ng.js} +2 -2
- package/dist/{chunk-jyrsd1dn.js.map → chunk-er3wf6ng.js.map} +1 -1
- package/dist/{chunk-2rphhsr7.js → chunk-fre6f4nk.js} +2 -2
- package/dist/{chunk-2rphhsr7.js.map → chunk-fre6f4nk.js.map} +1 -1
- package/dist/{chunk-1p0dazvk.js → chunk-fxgxf16k.js} +2 -2
- package/dist/{chunk-1p0dazvk.js.map → chunk-fxgxf16k.js.map} +1 -1
- package/dist/{chunk-ty4aj41k.js → chunk-gts5p6mw.js} +3 -3
- package/dist/{chunk-ty4aj41k.js.map → chunk-gts5p6mw.js.map} +1 -1
- package/dist/{chunk-rrqr1dwq.js → chunk-hdps9n52.js} +2 -2
- package/dist/{chunk-rrqr1dwq.js.map → chunk-hdps9n52.js.map} +1 -1
- package/dist/{chunk-jk97wv0q.js → chunk-jdhdrr2k.js} +2 -2
- package/dist/{chunk-jk97wv0q.js.map → chunk-jdhdrr2k.js.map} +1 -1
- package/dist/chunk-jmg2zsaf.js +5 -0
- package/dist/{chunk-fv9mr1t4.js.map → chunk-jmg2zsaf.js.map} +4 -4
- package/dist/{chunk-w2fpr99k.js → chunk-jmpw6bqz.js} +2 -2
- package/dist/{chunk-w2fpr99k.js.map → chunk-jmpw6bqz.js.map} +1 -1
- package/dist/{chunk-6h9j3f1x.js → chunk-kejwjerj.js} +2 -2
- package/dist/{chunk-6h9j3f1x.js.map → chunk-kejwjerj.js.map} +1 -1
- package/dist/{chunk-mqcy5vja.js → chunk-kqxdsv22.js} +2 -2
- package/dist/{chunk-mqcy5vja.js.map → chunk-kqxdsv22.js.map} +1 -1
- package/dist/{chunk-7rmjr8p7.js → chunk-ktr3k768.js} +2 -2
- package/dist/{chunk-7rmjr8p7.js.map → chunk-ktr3k768.js.map} +1 -1
- package/dist/{chunk-kcx468qv.js → chunk-m54s6jpr.js} +2 -2
- package/dist/{chunk-e6fp6dxx.js.map → chunk-m54s6jpr.js.map} +1 -1
- package/dist/{chunk-nek1gzz2.js → chunk-mazznq15.js} +3 -3
- package/dist/{chunk-nek1gzz2.js.map → chunk-mazznq15.js.map} +1 -1
- package/dist/{chunk-r4namj39.js → chunk-mqfzdfnz.js} +2 -2
- package/dist/{chunk-r4namj39.js.map → chunk-mqfzdfnz.js.map} +1 -1
- package/dist/chunk-ms9k0rx6.js +46 -0
- package/dist/{chunk-v9na3dny.js.map → chunk-ms9k0rx6.js.map} +5 -5
- package/dist/{chunk-hrvzchxd.js → chunk-mschc94q.js} +2 -2
- package/dist/{chunk-hrvzchxd.js.map → chunk-mschc94q.js.map} +1 -1
- package/dist/{chunk-329ggbcw.js → chunk-p91b8zcn.js} +2 -2
- package/dist/{chunk-329ggbcw.js.map → chunk-p91b8zcn.js.map} +1 -1
- package/dist/chunk-pn8v6fj2.js +14 -0
- package/dist/{chunk-0n9vs1ad.js.map → chunk-pn8v6fj2.js.map} +5 -5
- package/dist/{chunk-awp3n119.js → chunk-pyk3gzvc.js} +2 -2
- package/dist/{chunk-awp3n119.js.map → chunk-pyk3gzvc.js.map} +1 -1
- package/dist/{chunk-zns7xcz9.js → chunk-qjhw8nje.js} +1 -1
- package/dist/{chunk-5j76r5q8.js → chunk-qsrcdzan.js} +3 -3
- package/dist/{chunk-5j76r5q8.js.map → chunk-qsrcdzan.js.map} +1 -1
- package/dist/{chunk-xrh6k13s.js → chunk-sr942vb1.js} +2 -2
- package/dist/{chunk-xrh6k13s.js.map → chunk-sr942vb1.js.map} +1 -1
- package/dist/{chunk-yp5979we.js → chunk-t04f3akb.js} +2 -2
- package/dist/{chunk-yp5979we.js.map → chunk-t04f3akb.js.map} +1 -1
- package/dist/{chunk-j3nr4cg0.js → chunk-t4yh4nf9.js} +3 -3
- package/dist/{chunk-j3nr4cg0.js.map → chunk-t4yh4nf9.js.map} +1 -1
- package/dist/{chunk-8k8534kg.js → chunk-tn2bryy2.js} +2 -2
- package/dist/{chunk-8k8534kg.js.map → chunk-tn2bryy2.js.map} +1 -1
- package/dist/{chunk-q95k1ymq.js → chunk-tw5kwbx4.js} +2 -2
- package/dist/{chunk-q95k1ymq.js.map → chunk-tw5kwbx4.js.map} +1 -1
- package/dist/{chunk-kg1nbxvm.js → chunk-tzm3c7n6.js} +4 -4
- package/dist/{chunk-kg1nbxvm.js.map → chunk-tzm3c7n6.js.map} +1 -1
- package/dist/{chunk-zgn0p8qr.js → chunk-v1tfdgy1.js} +2 -2
- package/dist/{chunk-zgn0p8qr.js.map → chunk-v1tfdgy1.js.map} +1 -1
- package/dist/{chunk-e7axa0d5.js → chunk-vbdty91k.js} +3 -3
- package/dist/{chunk-e7axa0d5.js.map → chunk-vbdty91k.js.map} +1 -1
- package/dist/{chunk-e6fp6dxx.js → chunk-vw8849ys.js} +2 -2
- package/dist/{chunk-kcx468qv.js.map → chunk-vw8849ys.js.map} +1 -1
- package/dist/{chunk-y0wx6w80.js → chunk-vxm6yevm.js} +2 -2
- package/dist/{chunk-y0wx6w80.js.map → chunk-vxm6yevm.js.map} +1 -1
- package/dist/{chunk-kqb4s1r0.js → chunk-whtzggn6.js} +2 -2
- package/dist/{chunk-kqb4s1r0.js.map → chunk-whtzggn6.js.map} +1 -1
- package/dist/{chunk-3ma9m432.js → chunk-wyw6p3fg.js} +2 -2
- package/dist/{chunk-3ma9m432.js.map → chunk-wyw6p3fg.js.map} +1 -1
- package/dist/{chunk-gv91vjeb.js → chunk-x7cpth2f.js} +1 -1
- package/dist/{chunk-z32xfe8c.js → chunk-xt9tv99x.js} +2 -2
- package/dist/{chunk-z32xfe8c.js.map → chunk-xt9tv99x.js.map} +1 -1
- package/dist/{chunk-60nyk1w8.js → chunk-yf1njzd5.js} +2 -2
- package/dist/{chunk-60nyk1w8.js.map → chunk-yf1njzd5.js.map} +1 -1
- package/dist/{chunk-jv4g8grc.js → chunk-yhrye9cm.js} +2 -2
- package/dist/{chunk-jv4g8grc.js.map → chunk-yhrye9cm.js.map} +1 -1
- package/dist/{chunk-wwmdqhzy.js → chunk-zyt2w03d.js} +2 -2
- package/dist/{chunk-wwmdqhzy.js.map → chunk-zyt2w03d.js.map} +1 -1
- package/dist/chunks/{ThemeProvider-BgLyzzOL.js → ThemeProvider-BLI4zpLu.js} +8 -3
- package/dist/chunks/ThemeProvider-BLI4zpLu.js.map +1 -0
- package/dist/client/ClientRouter.d.ts +3 -5
- package/dist/client/ClientRouter.d.ts.map +1 -1
- package/dist/client/ClientRouterContext.d.ts.map +1 -1
- package/dist/client/Head.d.ts +1 -1
- package/dist/client/Head.d.ts.map +1 -1
- package/dist/client/ServerDataProvider.d.ts +2 -0
- package/dist/client/ServerDataProvider.d.ts.map +1 -1
- package/dist/client/createRoot.d.ts +2 -4
- package/dist/client/createRoot.d.ts.map +1 -1
- package/dist/client/htmlAttributes.d.ts +18 -0
- package/dist/client/htmlAttributes.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 +79 -6
- package/dist/client/index.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.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/Meta.d.ts +11 -1
- package/dist/facades/Meta.d.ts.map +1 -1
- package/dist/facades/Storage.d.ts +25 -1
- package/dist/facades/Storage.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 +3 -0
- package/dist/http/HttpRequest.d.ts.map +1 -1
- package/dist/http/Metadata.d.ts +23 -0
- package/dist/http/Metadata.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 +3 -0
- package/dist/http/requestContext.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 -0
- 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/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts +12 -1
- package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts +32 -1
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts +22 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/S3Driver.d.ts +14 -1
- package/dist/services/file-storage/drivers/S3Driver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/types.d.ts +26 -0
- package/dist/services/file-storage/drivers/types.d.ts.map +1 -1
- package/dist/services/index.d.ts +3 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +9 -9
- package/dist/services/index.js.map +4 -4
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/services/router/ViewRouteDispatcher.d.ts +3 -1
- package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
- package/dist/services/router/config.d.ts +19 -0
- package/dist/services/router/config.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/testing/index.js +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-0n9vs1ad.js +0 -14
- package/dist/chunk-fakvf9wb.js +0 -5
- package/dist/chunk-fv9mr1t4.js +0 -5
- package/dist/chunk-jzp0fs6h.js +0 -5
- package/dist/chunk-v9na3dny.js +0 -46
- package/dist/chunks/ThemeProvider-BgLyzzOL.js.map +0 -1
- /package/dist/{chunk-m17ktssc.js.map → chunk-41da9628.js.map} +0 -0
- /package/dist/{chunk-hz6yzzbz.js.map → chunk-agyfv3f8.js.map} +0 -0
- /package/dist/{chunk-a5sbgffr.js.map → chunk-e573yxpq.js.map} +0 -0
- /package/dist/{chunk-zns7xcz9.js.map → chunk-qjhw8nje.js.map} +0 -0
- /package/dist/{chunk-gv91vjeb.js.map → chunk-x7cpth2f.js.map} +0 -0
package/dist/app/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Ha as a}from"../chunk-
|
|
2
|
+
import{Ha as a}from"../chunk-tw5kwbx4.js";import"../chunk-d9mar37g.js";import"../chunk-vw8849ys.js";export{a as App};
|
|
3
3
|
|
|
4
4
|
//# debugId=288F3EAB17F12DE464756E2164756E21
|
package/dist/bun/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{da as a}from"../chunk-
|
|
2
|
+
import{da as a}from"../chunk-e573yxpq.js";import"../chunk-gts5p6mw.js";import"../chunk-9n1hx3mq.js";import"../chunk-hdps9n52.js";import"../chunk-vw8849ys.js";export{a as gemiPlugin};
|
|
3
3
|
|
|
4
4
|
//# debugId=255F25075168278464756E2164756E21
|
package/dist/bun/preload.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{da as k}from"../chunk-
|
|
2
|
+
import{da as k}from"../chunk-e573yxpq.js";import"../chunk-gts5p6mw.js";import"../chunk-9n1hx3mq.js";import"../chunk-hdps9n52.js";import{xa as j}from"../chunk-303mprnv.js";import"../chunk-vw8849ys.js";var{plugin:q}=globalThis.Bun;q(k());var y=await j(process.cwd());for(let x of y.bun?.plugins??[])q(x);
|
|
3
3
|
|
|
4
4
|
//# debugId=E7ABFC04ABC989B264756E2164756E21
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
function H(z){if(z===401)return"authentication";if(z===403)return"permission";if(z===404)return"not_found";if(z===416)return"range_not_satisfiable";if(z===429)return"rate_limit";if(z>=500)return"server_error";return"form_error"}var N="GEMI_REQUEST_BREAKER_ERROR";class J extends Error{static legacyStringPayload=!1;kind=N;payload;constructor(z,C={}){super(z);let D=C.status??400;this.payload={api:{status:D,data:{error:L(C.kind??H(D),z??"",D)},...C.headers?{headers:C.headers}:{}},view:{status:D}}}}function L(z,C,D){return{kind:z,message:C,status:D}}function X(z,C,D){return J.legacyStringPayload?C:L(z,C,D)}
|
|
3
|
-
export{H as
|
|
3
|
+
export{H as Pg,N as Qg,J as Rg,L as Sg,X as Tg};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
5
|
+
//# debugId=C7445875786BD2A464756E2164756E21
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"import { refusalKindForStatus, type Refusal, type RefusalKind } from \"./refusal\";\n\nexport const GEMI_REQUEST_BREAKER_ERROR = \"GEMI_REQUEST_BREAKER_ERROR\";\n\nexport type RequestBreakerOptions = {\n /** The answer's status. 400 when absent. */\n status?: number;\n /**\n * What the client's guards classify it as. Absent, it follows from\n * `status`: 401 `authentication`, 403 `permission`, 404 `not_found`, 429\n * `rate_limit`, 5xx `server_error`, any other status `form_error`.\n */\n kind?: Exclude<RefusalKind, \"validation_error\">;\n /** Extra headers for the API answer. */\n headers?: Record<string, string>;\n};\n\nexport class RequestBreakerError extends Error {\n /**\n * Answer the refusals that were bare strings before 0.88 — authentication,\n * authorization, permission, CSRF and a 500 — with that string again,\n * instead of `{ kind, message, status }`.\n *\n * For a shipped native client that reads `body.error` as a string and cannot\n * be rolled forward in the same deploy as the server. Set it once at boot,\n * and remove the line when the clients read `body.error.message`:\n *\n * ```ts\n * RequestBreakerError.legacyStringPayload = true;\n * ```\n *\n * gemi's own web client reads either shape. Refusals that were already\n * objects (404, 429, a policy 403) stay objects.\n */\n static legacyStringPayload = false;\n\n public kind = GEMI_REQUEST_BREAKER_ERROR;\n public payload: {\n api: Record<string, any>;\n view: Record<string, any>;\n /**\n * What a `.json` view navigation answers, when that differs from `api`.\n * Absent, it gets `api` — right for most breakers, but not for one that\n * must be a 401 to an API client and a redirect to the client router.\n */\n viewData?: Record<string, any>;\n };\n\n /**\n * A refusal that answers `{ error: { kind, message, status } }` with\n * `status`, so the client's guards classify it without a payload of your\n * own. A subclass that sets `payload` itself replaces this.\n *\n * ```ts\n * throw new RequestBreakerError(\"This slug is taken\", { status: 409 });\n * // → 409 { error: { kind: \"form_error\", message: \"This slug is taken\", status: 409 } }\n * ```\n */\n constructor(message?: string, options: RequestBreakerOptions = {}) {\n super(message);\n const status = options.status ?? 400;\n this.payload = {\n api: {\n status,\n data: {\n error: refusal(options.kind ?? refusalKindForStatus(status), message ?? \"\", status),\n },\n ...(options.headers ? { headers: options.headers } : {}),\n },\n view: { status },\n };\n }\n}\n\n/** A refusal's `error` field. */\nexport function refusal<K extends Exclude<RefusalKind, \"validation_error\">>(\n kind: K,\n message: string,\n status: number,\n): Refusal<K> {\n return { kind, message, status };\n}\n\n/**\n * A refusal that was a bare string before 0.88: the object, or the string\n * under `RequestBreakerError.legacyStringPayload`.\n *\n * @internal\n */\nexport function stringEraRefusal<K extends Exclude<RefusalKind, \"validation_error\">>(\n kind: K,\n message: string,\n status: number,\n): Refusal<K> | string {\n return RequestBreakerError.legacyStringPayload ? message : refusal(kind, message, status);\n}\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": ";AAqDO,SAAS,CAAoB,CAAC,EAA0D,CAC7F,GAAI,IAAW,IAAK,MAAO,iBAC3B,GAAI,IAAW,IAAK,MAAO,aAC3B,GAAI,IAAW,IAAK,MAAO,YAC3B,GAAI,IAAW,IAAK,MAAO,wBAC3B,GAAI,IAAW,IAAK,MAAO,aAC3B,GAAI,GAAU,IAAK,MAAO,eAC1B,MAAO,aC1DF,IAAM,EAA6B,6BAenC,MAAM,UAA4B,KAAM,OAiBtC,qBAAsB,GAEtB,KAAO,EACP,QAqBP,WAAW,CAAC,EAAkB,EAAiC,CAAC,EAAG,CACjE,MAAM,CAAO,EACb,IAAM,EAAS,EAAQ,QAAU,IACjC,KAAK,QAAU,CACb,IAAK,CACH,SACA,KAAM,CACJ,MAAO,EAAQ,EAAQ,MAAQ,EAAqB,CAAM,EAAG,GAAW,GAAI,CAAM,CACpF,KACI,EAAQ,QAAU,CAAE,QAAS,EAAQ,OAAQ,EAAI,CAAC,CACxD,EACA,KAAM,CAAE,QAAO,CACjB,EAEJ,CAGO,SAAS,CAA2D,CACzE,EACA,EACA,EACY,CACZ,MAAO,CAAE,OAAM,UAAS,QAAO,EAS1B,SAAS,CAAoE,CAClF,EACA,EACA,EACqB,CACrB,OAAO,EAAoB,oBAAsB,EAAU,EAAQ,EAAM,EAAS,CAAM",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "C7445875786BD2A464756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
import{existsSync as $,readdirSync as B}from"fs";import{join as Y,relative as G}from"path";function J(K,Q=[]){let U=[],X=(H)=>{let z=G(K,H).split("\\").join("/");return Q.some((q)=>z===q||z.startsWith(`${q}/`))},V=(H)=>{for(let z of B(H,{withFileTypes:!0}).sort((q,Z)=>q.name<Z.name?-1:q.name>Z.name?1:0)){let q=Y(H,z.name);if(X(q))continue;if(z.isDirectory()){if(z.name.startsWith(".")||z.name==="node_modules")continue;if($(Y(q,"package.json")))continue;V(q);continue}if(!z.name.endsWith(".ts")&&!z.name.endsWith(".tsx"))continue;if(z.name.endsWith(".d.ts"))continue;if(/\.(test|test-d|spec|bench)\.tsx?$/.test(z.name))continue;U.push(q)}};if(!$(K))return U;return V(K),U}class A extends Error{constructor(K,Q){super(K,Q);this.name="DiscoveryError"}}async function W(K,Q,U=[],X){let V=new Set;for(let H of J(K,U)){let z;try{z=await import(H)}catch(q){throw new A(`${H} could not be imported, so the classes in it could not be discovered:
|
|
3
3
|
${q.message}
|
|
4
4
|
List the classes explicitly in the config slice for this directory to skip the walk.`,{cause:q})}for(let q of Object.values(z)){if(typeof q==="function"&&q!==Q&&Object.prototype.isPrototypeOf.call(Q,q)){V.add(q);continue}X?.(q,H)}}return[...V]}function F(){return Y(process.cwd(),process.env.GEMI_PROJECT_DIR??"")}
|
|
5
|
-
export{J as
|
|
5
|
+
export{J as ki,A as li,W as mi,F as ni};
|
|
6
6
|
|
|
7
|
-
//# debugId=
|
|
7
|
+
//# debugId=E9A6106617E15F1E64756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import { existsSync, readdirSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\n\n/**\n * Finding the classes an application declared and never imported — the walk\n * #322 and #323 both end at.\n *\n * ### Why it has to run the files\n *\n * A job that is written and not listed does not fail; it disappears.\n * `QueueManager.run` looks a dispatched name up in the map its config built and\n * drops what is not there, so the dispatch is simply lost. A cron drifts worse:\n * nothing is waiting on a tick, so a job that never fires reports nothing to\n * anyone. What both come down to is that `app/config/queue.ts` naming every\n * `Job` subclass is the *only* thing putting those classes in the module graph —\n * the list and the directory are two spellings of one set, kept in step by hand.\n *\n * The way out of that is to read the directory, and there is no static read that\n * will do: the class does not exist until its module has run. So **every file\n * walked here is imported**, and a file that *does something* when imported does\n * it here — at boot, in production, on every start. `gemi check models` makes\n * the same trade for the same reason and pays it once per CI run; a caller of\n * this pays it once per process.\n *\n * ### What that asks of a caller\n *\n * **Point it at a directory of class declarations, not at `app/`.** The skip\n * rules on `sourceFiles` drop what certainly is not one — tests, benchmarks,\n * `.d.ts`, vendored packages — and nothing else. Widening the guesses is how a\n * discovery pass ends up quietly covering less than the directory holds, which\n * is the same silence in a new place.\n *\n * **Let a broken file stop the boot.** `discoverClasses` rethrows an import\n * failure naming the file rather than dropping it and carrying on, for the same\n * reason: four classes found out of five looks exactly like five out of five.\n *\n * **Leave a way out.** Discovery is what should happen when an app said\n * nothing. An app that lists its classes explicitly must not reach this file at\n * all — that is the escape hatch for a directory holding something this cannot\n * import, and it is the sentence an error from here should point at.\n *\n * ### One more thing worth knowing\n *\n * This imports by absolute path, while the application imports the same files\n * through the `@/app/*` alias. Bun keys its module registry by the *resolved*\n * path, so those two specifiers land on one module: a job already reached from\n * a controller is not evaluated a second time here, and the class object is the\n * same one. `gemi build` leaves that true in production — `packages: \"external\"`\n * keeps the app's own code out of `dist/server/server.mjs` and resolves it from\n * source at runtime, exactly as `gemi dev` does.\n *\n * Nothing here depends on that holding, and deliberately: `QueueManager` and the\n * `Scheduler`'s cross-reload registry are both keyed by name rather than by\n * class identity, so a build that did inline the app's modules would produce a\n * duplicate class object and still register the right job. Worth knowing before\n * writing a registry keyed the other way.\n */\n\n/**\n * The files under `dir` that could declare a class.\n *\n * Everything underneath it, because apps do group classes into folders, minus\n * what cannot be one. Each of these is going to be *imported*, so the exclusions\n * are about what is certainly not source rather than about what is probably not:\n *\n * - **Declaration files.** `.d.ts` has no runtime module behind it.\n * - **Tests, type tests and benchmarks**, by the suffix a runner already\n * recognises.\n * - **Dot-directories and `node_modules`.**\n * - **Any directory holding a `package.json`.** That is a package that happens\n * to live here — a vendored client, a generated SDK — not this app's source,\n * and importing its entry point runs somebody else's module graph. The\n * template has two under `app/models`.\n *\n * `ignore` is the escape hatch for the rest: a path prefix, relative to `dir`,\n * naming a file or a directory of adjacent code that runs something on import.\n * Nothing is ignored by default.\n *\n * The order is the same on every run over the same tree, which matters because\n * the caller is going to import in it: entries are sorted per directory before\n * recursing, and `readdirSync` order is the filesystem's rather than\n * alphabetical — a tree written `A.ts` then `B.ts` reads back `B.ts` first on\n * the machines this was tested on. Sorting per directory rather than sorting the\n * finished list is deliberate: for a tree holding both `a.ts` and `a/b.ts`, this\n * emits `a/b.ts` first, because the directory sorts before the file.\n *\n * A directory that does not exist yields an empty list rather than throwing.\n * \"The app has no jobs yet\" is an ordinary state and not this function's to\n * complain about — but it is indistinguishable from \"the app's source did not\n * ship\", so a caller that boots on the answer owes the reader a word about which\n * one it got.\n */\nexport function sourceFiles(dir: string, ignore: string[] = []): string[] {\n const out: string[] = [];\n\n const ignored = (path: string) => {\n const rel = relative(dir, path).split(\"\\\\\").join(\"/\");\n return ignore.some(\n (pattern) => rel === pattern || rel.startsWith(`${pattern}/`),\n );\n };\n\n const walk = (current: string) => {\n for (const entry of readdirSync(current, { withFileTypes: true }).sort(\n (a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0),\n )) {\n const path = join(current, entry.name);\n if (ignored(path)) continue;\n\n if (entry.isDirectory()) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\")\n continue;\n if (existsSync(join(path, \"package.json\"))) continue;\n walk(path);\n continue;\n }\n\n if (!entry.name.endsWith(\".ts\") && !entry.name.endsWith(\".tsx\")) continue;\n if (entry.name.endsWith(\".d.ts\")) continue;\n if (/\\.(test|test-d|spec|bench)\\.tsx?$/.test(entry.name)) continue;\n\n out.push(path);\n }\n };\n\n if (!existsSync(dir)) return out;\n\n walk(dir);\n return out;\n}\n\n/**\n * A class, as much of one as this file can name. `abstract` so that a base an\n * app never instantiates directly is a legal argument.\n */\ntype ClassLike = abstract new (...args: never[]) => unknown;\n\n/**\n * A file that would not import, reported with the file that would not import.\n *\n * Separate from a bare rethrow because the stack of a failed dynamic import\n * names the module that failed to *resolve*, several frames deep, and says\n * nothing about the walk that asked for it — so the reader learns that some\n * `?raw` specifier is unresolvable without learning that discovery is what\n * imported it, or that listing the classes explicitly is how they get their boot\n * back.\n */\nexport class DiscoveryError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"DiscoveryError\";\n }\n}\n\n/**\n * Every exported class under `dir` whose prototype chain reaches `base`.\n *\n * `base` is a parameter rather than an import so that this file names no\n * service and stays cheap to depend on — `bin/check-models.ts` uses the walker\n * above and is bundled into `dist/bin/gemi.js`, which is not somewhere gemi's\n * service layer should end up. It is also what lets a test hand in a base class\n * of its own instead of standing up a project that can resolve `gemi/services`.\n *\n * `base` itself is never returned. A directory whose files import their base\n * from a sibling — the shape an app reaches for when several jobs share a gate —\n * re-exports it as often as not, and a framework that scheduled the abstract\n * base along with its subclasses would be running a job nobody wrote.\n *\n * A class is returned once no matter how many exports name it. A barrel in the\n * directory re-exporting everything beside it is the ordinary case, and it makes\n * every class reachable twice.\n *\n * The order is the walk's, and within a file the module namespace's, which the\n * language sorts by name. So the answer is the same on every run — worth having\n * where the caller is a scheduler and the alternative is a boot order that\n * depends on the filesystem.\n *\n * `onSkipped` is handed every export that did *not* match, with the file it came\n * from. Discovery's characteristic failure is a thing the author wrote and this\n * walk cannot see, and by the time an export has been discarded here the\n * information about why is gone — the caller is left holding \"four classes\"\n * where the directory holds five. A caller that can recognise its own\n * near-misses, as `discoverCommands` recognises a builder chain that was never\n * finished, uses this to say so by name instead.\n *\n * @throws DiscoveryError if a walked file cannot be imported. Not a skip: a file\n * that will not load is a class the caller was going to be told about and now is\n * not, which is the failure discovery exists to remove.\n */\nexport async function discoverClasses<T extends ClassLike>(\n dir: string,\n base: T,\n ignore: string[] = [],\n onSkipped?: (value: unknown, file: string) => void,\n): Promise<T[]> {\n const found = new Set<T>();\n\n for (const path of sourceFiles(dir, ignore)) {\n let module: Record<string, unknown>;\n\n try {\n module = (await import(path)) as Record<string, unknown>;\n } catch (error) {\n throw new DiscoveryError(\n `${path} could not be imported, so the classes in it could not be ` +\n `discovered:\\n ${(error as Error).message}\\n` +\n `List the classes explicitly in the config slice for this directory ` +\n `to skip the walk.`,\n { cause: error },\n );\n }\n\n for (const value of Object.values(module)) {\n if (\n typeof value === \"function\" &&\n value !== base &&\n Object.prototype.isPrototypeOf.call(base, value)\n ) {\n found.add(value as unknown as T);\n continue;\n }\n\n onSkipped?.(value, path);\n }\n }\n\n return [...found];\n}\n\n/**\n * The directory an app's `app/` sits in, as the running process can know it.\n *\n * `ROOT_DIR` is the obvious answer and is not available: `Server.start` awaits\n * `waitForBoot()` — every provider's `register` and `boot` — and only then\n * imports the http layer that sets it. Anything resolving paths during boot is\n * earlier than the variable it would want.\n *\n * What it can use is the same rule `httpProd` computes `ROOT_DIR` with a moment\n * later, which is why that file now calls this instead of repeating it. `gemi\n * dev` and `gemi start` both spawn the server with no `cwd`, so the process\n * inherits the CLI's, and the CLI takes `process.cwd()` for the project root\n * itself — `bun/preload.ts` reads `gemi.config` from it on the same assumption.\n *\n * `httpDev` computes a bare `process.cwd()`, so it and `httpProd` already\n * disagree whenever `GEMI_PROJECT_DIR` is set. Nothing in this repo sets it and\n * `gemi start` ignores it when locating the built entry point, so the two rules\n * are the same rule for every configuration that runs today; the divergence is\n * older than this function and wants its own fix.\n */\nexport function projectRoot(): string {\n return join(process.cwd(), process.env.GEMI_PROJECT_DIR ?? \"\");\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";AAAA,qBAAS,iBAAY,WACrB,eAAS,cAAM,aA2FR,SAAS,CAAW,CAAC,EAAa,EAAmB,CAAC,EAAa,CACxE,IAAM,EAAgB,CAAC,EAEjB,EAAU,CAAC,IAAiB,CAChC,IAAM,EAAM,EAAS,EAAK,CAAI,EAAE,MAAM,IAAI,EAAE,KAAK,GAAG,EACpD,OAAO,EAAO,KACZ,CAAC,IAAY,IAAQ,GAAW,EAAI,WAAW,GAAG,IAAU,CAC9D,GAGI,EAAO,CAAC,IAAoB,CAChC,QAAW,KAAS,EAAY,EAAS,CAAE,cAAe,EAAK,CAAC,EAAE,KAChE,CAAC,EAAG,IAAO,EAAE,KAAO,EAAE,KAAO,GAAK,EAAE,KAAO,EAAE,KAAO,EAAI,CAC1D,EAAG,CACD,IAAM,EAAO,EAAK,EAAS,EAAM,IAAI,EACrC,GAAI,EAAQ,CAAI,EAAG,SAEnB,GAAI,EAAM,YAAY,EAAG,CACvB,GAAI,EAAM,KAAK,WAAW,GAAG,GAAK,EAAM,OAAS,eAC/C,SACF,GAAI,EAAW,EAAK,EAAM,cAAc,CAAC,EAAG,SAC5C,EAAK,CAAI,EACT,SAGF,GAAI,CAAC,EAAM,KAAK,SAAS,KAAK,GAAK,CAAC,EAAM,KAAK,SAAS,MAAM,EAAG,SACjE,GAAI,EAAM,KAAK,SAAS,OAAO,EAAG,SAClC,GAAI,oCAAoC,KAAK,EAAM,IAAI,EAAG,SAE1D,EAAI,KAAK,CAAI,IAIjB,GAAI,CAAC,EAAW,CAAG,EAAG,OAAO,EAG7B,OADA,EAAK,CAAG,EACD,EAmBF,MAAM,UAAuB,KAAM,CACxC,WAAW,CAAC,EAAiB,EAA+B,CAC1D,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,iBAEhB,CAqCA,eAAsB,CAAoC,CACxD,EACA,EACA,EAAmB,CAAC,EACpB,EACc,CACd,IAAM,EAAQ,IAAI,IAElB,QAAW,KAAQ,EAAY,EAAK,CAAM,EAAG,CAC3C,IAAI,EAEJ,GAAI,CACF,EAAU,MAAa,UACvB,MAAO,EAAO,CACd,MAAM,IAAI,EACR,GAAG;AAAA,MACoB,EAAgB;AAAA,sFAGvC,CAAE,MAAO,CAAM,CACjB,EAGF,QAAW,KAAS,OAAO,OAAO,CAAM,EAAG,CACzC,GACE,OAAO,IAAU,YACjB,IAAU,GACV,OAAO,UAAU,cAAc,KAAK,EAAM,CAAK,EAC/C,CACA,EAAM,IAAI,CAAqB,EAC/B,SAGF,IAAY,EAAO,CAAI,GAI3B,MAAO,CAAC,GAAG,CAAK,EAuBX,SAAS,CAAW,EAAW,CACpC,OAAO,EAAK,QAAQ,IAAI,EAAG,QAAQ,IAAI,kBAAoB,EAAE",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "E9A6106617E15F1E64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Ch as W,sh as X,zh as K}from"./chunk-kejwjerj.js";import{AsyncLocalStorage as S}from"async_hooks";var z=new S;function g(){return z.getStore()?.tx}function U(){return z.getStore()?.connection??K}function O(j,q){let v=z.getStore();if(U()===j)return q();return y(j),z.run({...v,depth:v?.depth??0,connection:j===K?void 0:j},q)}function y(j){let q=z.getStore();if(q?.tx===void 0)return;let v=q.connection??K;if(v===j)return;throw new W(v,j)}function L(j){let q=z.getStore();if(q?.tx===void 0||q.afterCommit===void 0)return!1;return q.afterCommit.push(j),!0}function h(j){if(L(j))return Promise.resolve();let q=(v)=>{console.error("An after-commit callback threw. No transaction was open, so it ran immediately.",v)};try{return Promise.resolve(j()).catch(q)}catch(v){return q(v),Promise.resolve()}}function k(j){let q=z.getStore();if(q?.tx===void 0||q.commitDependsOn===void 0)return!1;return q.commitDependsOn.push(j),!0}class F extends Error{constructor(j){super(`A statement this transaction depended on failed after being issued on it, so the transaction rolled back instead of committing: ${j instanceof Error?j.message:String(j)}`,{cause:j});this.name="TransactionDependencyError"}}async function R(j,q){if(j.length===q)return;let B=(await Promise.allSettled(j.slice(q))).find((G)=>G.status==="rejected");if(B)throw new F(B.reason)}function N(){let j=z.getStore();return j?.tx===void 0?null:j.depth}function T(){return z.getStore()?.system===!0}function x(j){let q=z.getStore();return z.run({...q,depth:q?.depth??0,system:!0},j)}function p(j){return z.getStore()?.trashed?.get(j)}function f(j,q,v){let B=z.getStore(),G=new Map(B?.trashed);return G.set(j,q),z.run({...B,depth:B?.depth??0,trashed:G},v)}function C(){return z.getStore()?.actor}function l(j,q){let v=z.getStore();return z.run({...v,depth:v?.depth??0,system:!1,actor:{user:j??null}},q)}function _(j){if(Bun.env.NODE_ENV!=="development")return null;if(j===!1)return null;if(j===void 0)return X;if(!Number.isFinite(j)||j<=0)return X;return j}function A(j){let q=_(j);if(q===null)return()=>{};let v=Error("transaction opened here"),B=setTimeout(()=>{let G=v.stack?.split(`
|
|
3
3
|
`).slice(1).join(`
|
|
4
4
|
`)??"";console.warn(`[gemi] A database transaction has not settled after ${q}ms. It `+"reserves a pooled connection until it does \u2014 check for network or "+`filesystem I/O inside the callback, and move it outside the transaction if you find any.
|
|
5
5
|
${G}
|
|
6
6
|
(development only; set database.slowTransactionThreshold to change the threshold, or false to switch this off)`)},q);return B.unref?.(),()=>clearTimeout(B)}async function D(j,q){if(j.length===0)return;await z.run({...q,tx:void 0,afterCommit:void 0,commitDependsOn:void 0,depth:q?.depth??0},async()=>{for(let v of j)try{await v()}catch(B){console.error("An after-commit callback threw. The transaction it was waiting on had already committed and stays committed, and the callbacks after it still ran.",B)}})}function u(j,q,v){let B=z.getStore(),G=v?.connection??K;if(y(G),B?.tx){let J=B.afterCommit,Q=J?.length??0,P=B.commitDependsOn,M=P?.length??0;return B.tx.savepoint((V)=>{let H=V;return z.run({...B,tx:H,depth:B.depth+1},async()=>{let I=await q(H);if(P)await R(P,M);return I})}).catch((V)=>{if(J)J.length=Q;if(P)P.length=M;throw V})}let Y=A(v?.slowTransactionThreshold),Z=[],$=[];try{return j.begin((J)=>z.run({...B,tx:J,depth:0,connection:G===K?void 0:G,afterCommit:Z,commitDependsOn:$},async()=>{let Q=await q(J);return await R($,0),Q})).finally(Y).then(async(J)=>{return await D(Z,B),J})}catch(J){throw Y(),J}}
|
|
7
|
-
export{z as
|
|
7
|
+
export{z as $g,g as ah,U as bh,O as ch,y as dh,L as eh,h as fh,k as gh,F as hh,N as ih,T as jh,x as kh,p as lh,f as mh,C as nh,l as oh,u as ph};
|
|
8
8
|
|
|
9
|
-
//# debugId=
|
|
9
|
+
//# debugId=4C5B7052CD785D8164756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import type { SQL, TransactionSQL } from \"bun\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SLOW_TRANSACTION_THRESHOLD } from \"../database/config\";\nimport {\n CrossConnectionTransactionError,\n DEFAULT_CONNECTION,\n} from \"../database/Connection\";\n\n/**\n * The ambient transaction: the ORM's own `AsyncLocalStorage`, holding nothing\n * but the open handle and how deep the nesting is.\n *\n * One store per scope with one owner, which is the pattern the framework\n * already follows — `kernel/context.ts` holds the Application,\n * `http/requestContext.ts` the request and its user. The reasoning for\n * not folding this into the kernel's is written up beside it, and the short\n * version is that a transaction scope has to *nest inside* an Application scope\n * without replacing it, and `foundation/app.ts` must keep reading exactly one\n * shape out of the kernel store or resolving a service becomes a transaction\n * concern.\n *\n * What makes an ALS the right home rather than a field somewhere: two concurrent\n * requests each in their own transaction must never see each other's handle.\n * Anything reachable from the Application — which is one object shared by every\n * in-flight request — fails that by construction, and fails it as silently\n * written data, not as an error. \"two concurrent transactions never see each\n * other's handle\" in `context.test.ts` is the test that would catch it.\n */\nexport interface OrmScope {\n /**\n * Bun's transaction handle. Every ORM statement in scope runs on it, which\n * means they all run on one reserved connection — so nothing here may issue\n * two statements concurrently. `Model.$exec` already runs its nested writes\n * and its relation reads sequentially, for exactly this reason.\n */\n tx?: TransactionSQL;\n /** 0 for the outermost transaction, 1+ for each savepoint inside it. */\n depth: number;\n /**\n * Which named connection this subtree's queries run on, and — when `tx` is\n * set — which connection the open transaction belongs to.\n *\n * Ambient rather than an argument threaded through `$exec`, for the same\n * reason the handle above is: a relation read resolves its target through the\n * registry and calls that class's `$exec`, so an argument would have to be\n * carried by every intermediate that has no interest in it, and the one that\n * forgot would silently read a nested `include` off the *other* pool. There\n * is no error that shape produces; there are just rows from the wrong place.\n *\n * `undefined` means the default connection. Kept as absent-rather-than-\n * `\"default\"` so that entering a scope on the default connection is\n * indistinguishable from not entering one, which is what makes the\n * cross-connection check below cost a comparison of two `undefined`s on every\n * application that never declares a second connection.\n */\n connection?: string;\n /**\n * Whether policies are suspended for this scope. Set only by\n * `Model.asSystem`, and never by anything ambient — the whole point is that\n * unscoped access is a decision visible at the call site, not the accidental\n * result of a missing user.\n */\n system?: boolean;\n /**\n * The user policies should scope to, when there is no request to read one\n * from. Set only by `Model.asUser`.\n *\n * A sentinel wrapper rather than the bare value, so that \"a scope was entered\n * with `null`\" stays distinguishable from \"no scope was entered\" — the two\n * mean different things under deny-by-default.\n */\n actor?: { user: unknown };\n /**\n * Work that must not happen unless this transaction commits — an event whose\n * `static afterCommit` is set, today, and nothing else.\n *\n * **Created by the outermost `withTransaction` and never by a savepoint.** A\n * savepoint's scope is a spread of its parent's (`{ ...current, tx: nested }`),\n * so the array arrives here already shared by reference with the transaction\n * that opened it — which is the behaviour wanted rather than a leak. A\n * dispatch made inside a savepoint that commits, in a transaction that then\n * rolls back, must not run: rolling back the outermost transaction discards\n * the list whole, savepoint entries included, because nothing ever drains it.\n *\n * The inverse — a savepoint that rolls back under a transaction that commits\n * — is the case sharing gets wrong on its own, and `withTransaction`'s\n * savepoint branch is where it is put right.\n *\n * Absent, rather than an empty array, on every scope that is not a\n * transaction: `runAsSystem`, `runAsUser` and `runOnConnection` spread\n * whatever they are given, so \"there is a list here\" and \"there is an open\n * transaction here\" have to stay the same question. `deferUntilCommit`\n * answers `false` when either half is missing and the caller runs the work\n * now, which is what keeps a hand-built scope carrying a `tx` — the shape\n * tests write — from swallowing a dispatch into a list nothing drains.\n */\n afterCommit?: AfterCommitCallback[];\n /**\n * Statements written on `tx` that the commit must wait for and must not\n * outlive — today, a job row the database queue driver wrote on the\n * transaction (#563), and nothing else. See `commitDependsOn`.\n *\n * Created and shared exactly as `afterCommit` is, and truncated with it\n * when a savepoint rolls back.\n */\n commitDependsOn?: Promise<unknown>[];\n /**\n * Models whose soft-delete scope (`static $softDeletes`) is lifted or\n * inverted for this async subtree, by name — set only by\n * `Model.withTrashed(fn)` / `Model.onlyTrashed(fn)`.\n *\n * Keyed by model name rather than class because a nested relation read\n * resolves its target through the registry by name, and the block has to\n * reach those reads too. A fresh map per block, never mutated, so an inner\n * block cannot leak its entry back into the enclosing one.\n */\n trashed?: ReadonlyMap<string, TrashedMode>;\n}\n\n/**\n * How a soft-deleted model's trashed rows are treated: `\"with\"` includes them,\n * `\"only\"` reads nothing else. Absent means the default — they are hidden.\n */\nexport type TrashedMode = \"with\" | \"only\";\n\n/**\n * Work deferred to a transaction's commit.\n *\n * Awaited when it is drained, and its rejection is caught there: a callback is\n * a side effect that the transaction is not waiting on and cannot be told\n * about, so the only thing left to do with a failure is report it.\n *\n * Not exported: a caller passes a lambda and never names this, and an export\n * nothing outside this file uses is what `orm/architecture.test.ts` is pointed\n * at. The declaration emit carries it along regardless, so `OrmScope` stays\n * readable from a `.d.ts`.\n */\ntype AfterCommitCallback = () => void | Promise<void>;\n\n/**\n * One ambient scope for the ORM, not one per feature.\n *\n * Transactions (iteration 5) and system access (iteration 6) are both\n * \"something is true for this async subtree and every query in it\", so they\n * share a store rather than minting a second `AsyncLocalStorage` each. The\n * inventory note in `kernel/context.ts` sets the bar for adding one; two\n * booleans-worth of ORM state does not clear it.\n */\nexport const ormContext = new AsyncLocalStorage<OrmScope>();\n\n/**\n * The open transaction, or `undefined` outside one. This is what `Model.$exec`\n * consults to decide which connection a statement runs on.\n *\n * Exported as the escape hatch for code that genuinely needs the handle — a raw\n * query that must join the surrounding transaction, say. **Do not store what it\n * returns.** Bun's handle stays callable after its `begin` resolves: queries on\n * it then run on the pooled connection, outside any transaction, and succeed.\n * Verified against both dialects, and it is the reason `Model.transaction`'s\n * callback takes no argument.\n */\nexport function currentTransaction(): TransactionSQL | undefined {\n return ormContext.getStore()?.tx;\n}\n\n/**\n * The connection every query in this scope runs on unless it names another.\n *\n * `\"default\"` outside any scope, so callers get a name rather than a\n * `string | undefined` to normalise themselves — the store keeps it absent,\n * which is not the same distinction and is nobody else's business.\n */\nexport function currentConnectionName(): string {\n return ormContext.getStore()?.connection ?? DEFAULT_CONNECTION;\n}\n\n/**\n * Run `fn` with `name` as the ambient connection.\n *\n * Merged into the current scope rather than replacing it, exactly as\n * `runAsSystem` and `runAsUser` are: naming a connection must not drop an open\n * transaction handle or re-enable policies underneath it.\n *\n * Deliberately absent from `orm/index.ts`, so it is not part of what an\n * application can reach — `Model.on(name)` and `DB.connection(name)` are the\n * two doors, and both funnel through here so that a nested relation read,\n * which resolves its own class out of the registry and calls its `$exec`,\n * inherits the connection without anything having to pass it along.\n */\nexport function runOnConnection<T>(\n name: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const current = ormContext.getStore();\n if (currentConnectionName() === name) return fn();\n\n // ENTERING A CONNECTION IS WHERE THE CROSS-CONNECTION CHECK BELONGS, not at\n // each door — and it has to be *here*, before the scope is entered, because\n // entering it is what makes the check impossible afterwards.\n //\n // The scope carries `tx` and `connection` together, so overwriting the name\n // while an open handle stays in place produces a store that says \"a\n // transaction on analytics\" while holding the *default* connection's handle.\n // Every check downstream then agrees with itself and the statement runs on\n // the wrong connection's transaction. `Model.save` found this: it routes to\n // the row's own connection, so it is the one caller that switches connections\n // with a transaction already open.\n assertConnectionUsable(name);\n\n return ormContext.run(\n {\n ...current,\n depth: current?.depth ?? 0,\n connection: name === DEFAULT_CONNECTION ? undefined : name,\n },\n fn,\n );\n}\n\n/**\n * Refuse a statement that names one connection while a transaction is open on\n * another.\n *\n * The check `withTransaction`'s single-connection note asked for, and the\n * reasoning for refusing rather than routing is on\n * `CrossConnectionTransactionError`. Both doors call it — `Model.$exec` for\n * every model operation, `DB` for a raw fragment — because either one alone\n * leaves the other free to straddle the two connections, and a raw `DB.execute`\n * escaping a transaction is the more damaging of the two.\n *\n * Only ever fires on a query that *names* a connection: an unqualified one\n * resolves to the ambient name, which is the transaction's own.\n */\nexport function assertConnectionUsable(name: string): void {\n const store = ormContext.getStore();\n if (store?.tx === undefined) return;\n\n const open = store.connection ?? DEFAULT_CONNECTION;\n if (open === name) return;\n\n throw new CrossConnectionTransactionError(open, name);\n}\n\n/**\n * Hold `callback` until the open transaction commits, and say whether that\n * happened.\n *\n * `false` means there was nothing to wait for — no transaction is open, or the\n * scope was entered by hand rather than by `withTransaction` — and the caller\n * must run the work itself, now. That return value is the whole contract: a\n * caller that ignores it turns \"no transaction here\" into a side effect queued\n * on a list nothing will ever drain, which is a dispatch that silently never\n * happens.\n *\n * `true` means the callback is on the outermost scope's list and will run after\n * `begin` resolves, outside the transaction, whatever the caller does next. It\n * will not run at all if the transaction rolls back, or if a savepoint it was\n * registered inside rolls back — both of which are the point.\n *\n * Nothing here is ordered against anything but the other deferred callbacks:\n * they run in registration order, one at a time, after the commit round-trip.\n */\nexport function deferUntilCommit(callback: AfterCommitCallback): boolean {\n const store = ormContext.getStore();\n if (store?.tx === undefined || store.afterCommit === undefined) return false;\n\n store.afterCommit.push(callback);\n return true;\n}\n\n/**\n * Run `callback` once the open transaction commits, or now when none is open.\n * Never when the transaction rolls back, nor when a savepoint it was\n * registered inside rolls back.\n *\n * The application-facing form of `deferUntilCommit`, exported from `gemi/orm`\n * (#786). The difference is the `false` branch: `deferUntilCommit` hands the\n * \"no transaction\" case back to the caller, who must remember to run the work\n * itself, and this runs it. A caller that wants a side effect only once its\n * writes are durable — waking a long-poll, notifying another process — has\n * nothing left to get wrong.\n *\n * Inside a transaction the callback joins the same list `static afterCommit`\n * events use, so it is drained after `begin` resolves, outside the\n * transaction, in registration order with them.\n *\n * The returned promise resolves once the callback has run (no transaction) or\n * been queued (inside one). It never rejects: a callback that throws is\n * reported on stderr, as a deferred one is at the drain, so a caller that does\n * not await — the usual case — cannot leave an unhandled rejection behind, and\n * the two branches fail the same way. A sync callback outside a transaction\n * runs before this returns.\n */\nexport function afterCommit(\n callback: () => void | Promise<void>,\n): Promise<void> {\n if (deferUntilCommit(callback)) return Promise.resolve();\n\n const report = (error: unknown) => {\n console.error(\n `An after-commit callback threw. No transaction was open, so it ran ` +\n `immediately.`,\n error,\n );\n };\n try {\n return Promise.resolve(callback()).catch(report);\n } catch (error) {\n report(error);\n return Promise.resolve();\n }\n}\n\n/**\n * Make the open transaction's commit depend on `write`, a statement issued on\n * its handle: the transaction does not commit until `write` settles, and\n * rolls back — rejecting with `TransactionDependencyError` — if it rejected.\n *\n * For a write the caller may not await. A queued listener's dispatch never is\n * (`EventManager` pushes it and moves on), and on Postgres a statement that\n * fails aborts the whole transaction: every statement after it is refused and\n * Bun's `COMMIT` quietly becomes a rollback. Without this, the callback's\n * promise resolved, `begin` resolved, and the rows the caller wrote were gone\n * with nothing to say so. MySQL does not abort on a failed statement, and is\n * failed here anyway, so that a joined write means the same thing on both:\n * it commits with the transaction or the transaction does not commit.\n *\n * `false` when there is no transaction to depend on, as for\n * `deferUntilCommit`.\n */\nexport function commitDependsOn(write: Promise<unknown>): boolean {\n const store = ormContext.getStore();\n if (store?.tx === undefined || store.commitDependsOn === undefined) {\n return false;\n }\n store.commitDependsOn.push(write);\n return true;\n}\n\n/**\n * A write the transaction's commit depended on failed, so the transaction —\n * or the savepoint the write was made in — rolled back. `cause` is the write's\n * own error.\n */\nexport class TransactionDependencyError extends Error {\n constructor(cause: unknown) {\n super(\n `A statement this transaction depended on failed after being issued on ` +\n `it, so the transaction rolled back instead of committing: ` +\n `${cause instanceof Error ? cause.message : String(cause)}`,\n { cause },\n );\n this.name = \"TransactionDependencyError\";\n }\n}\n\n/**\n * Wait for the writes registered from `mark` on, and throw if one failed.\n *\n * Called at the end of a transaction's or savepoint's callback, *inside*\n * `begin`/`savepoint`, so a throw is what makes Bun roll back rather than\n * commit — after `begin` has resolved it is too late to do anything but\n * report. Every write is settled before throwing, so none is still running on\n * the handle when the rollback is issued.\n */\nasync function awaitDependencies(\n writes: Promise<unknown>[],\n mark: number,\n): Promise<void> {\n if (writes.length === mark) return;\n const settled = await Promise.allSettled(writes.slice(mark));\n const failed = settled.find(\n (outcome): outcome is PromiseRejectedResult => outcome.status === \"rejected\",\n );\n if (failed) throw new TransactionDependencyError(failed.reason);\n}\n\n/** How deeply nested the current transaction is; `null` outside one. */\nexport function transactionDepth(): number | null {\n const store = ormContext.getStore();\n return store?.tx === undefined ? null : store.depth;\n}\n\n/** Whether policies are suspended for the current async scope. */\nexport function isSystemScope(): boolean {\n return ormContext.getStore()?.system === true;\n}\n\n/**\n * Run `fn` with policies suspended.\n *\n * The escape hatch the deny-by-default rule needs to be usable: a cron tick, a\n * queue worker or a seed script has no user, and under deny-by-default every\n * policied model would refuse it. This makes that intent explicit *at the call\n * site*, which is the property that matters — unscoped access must never be\n * what happens when a user simply fails to turn up.\n *\n * It nests inside a transaction and a transaction nests inside it: the scope is\n * merged rather than replaced, so `asSystem` does not silently drop an open\n * handle.\n */\nexport function runAsSystem<T>(fn: () => Promise<T>): Promise<T> {\n const current = ormContext.getStore();\n return ormContext.run({ ...current, depth: current?.depth ?? 0, system: true }, fn);\n}\n\n/**\n * How `model`'s trashed rows are treated in this async scope, or `undefined`\n * for the default (hidden). See `OrmScope.trashed`.\n */\nexport function trashedMode(model: string): TrashedMode | undefined {\n return ormContext.getStore()?.trashed?.get(model);\n}\n\n/**\n * Run `fn` with `model`'s soft-delete scope lifted (`\"with\"`) or inverted\n * (`\"only\"`). Merged into the current scope like `runAsSystem`, so it keeps an\n * open transaction, the system flag and the actor — and every other policy.\n */\nexport function runWithTrashed<T>(\n model: string,\n mode: TrashedMode,\n fn: () => Promise<T>,\n): Promise<T> {\n const current = ormContext.getStore();\n const trashed = new Map(current?.trashed);\n trashed.set(model, mode);\n return ormContext.run(\n { ...current, depth: current?.depth ?? 0, trashed },\n fn,\n );\n}\n\n/** The explicitly-set actor, or `undefined` when none was. */\nexport function currentActor(): { user: unknown } | undefined {\n return ormContext.getStore()?.actor;\n}\n\n/**\n * Run `fn` with policies scoped to `user`, for code with no request to read one\n * from.\n *\n * The counterpart to `runAsSystem`, and the reason that one is not the only\n * escape hatch. A queue worker processing \"send the invoice for organisation 7\"\n * genuinely acts *as somebody*; giving it `asSystem` would suspend policies\n * entirely and leave it hand-scoping every query — which is precisely the\n * unscoped-by-accident failure the deny-by-default rule exists to prevent. The\n * narrow tool should be the easy one.\n *\n * It is also what makes policies testable without reaching into\n * `RequestContext`'s internals.\n *\n * Takes precedence over the request store, so a job that says who it is acting\n * as is not quietly overridden by an ambient request that happens to enclose it.\n *\n * It also **clears `system`**, which is the more surprising half. Acting as a\n * user is strictly narrower than acting as the system, so naming one inside an\n * `asSystem` block has to narrow back — and the spread would otherwise carry\n * `system: true` forward, leaving `$exec` to skip policies entirely while\n * `currentUser()` cheerfully returned the actor. Silently unscoped, from the\n * realistic shape: a worker enters `asSystem` to read its job queue, then\n * narrows to the job's owner for the work itself. The reverse nesting —\n * `asSystem` inside `asUser` — suspends policies, which is what it should do.\n */\nexport function runAsUser<T>(user: unknown, fn: () => Promise<T>): Promise<T> {\n const current = ormContext.getStore();\n return ormContext.run(\n {\n ...current,\n depth: current?.depth ?? 0,\n system: false,\n actor: { user: user ?? null },\n },\n fn,\n );\n}\n\n/**\n * The warning threshold in milliseconds, or `null` when the warning is off.\n *\n * `configured` is `database.slowTransactionThreshold` — see `DatabaseConfig`.\n * It arrives as a value rather than being read from here so that this file\n * keeps knowing nothing about the container: `withTransaction` is reachable\n * with a bare pool, and its tests use one.\n *\n * Exported for its own tests. The behaviour worth pinning is the fallback —\n * that a malformed threshold lands on the default rather than disabling — and\n * that cannot be observed through `withTransaction`: \"no warning fired\" is what\n * a disabled warning looks like too, so a behavioural test of it passes just as\n * happily when the fallback is gone. Asserting the number directly is the only\n * form of that test that can fail.\n */\nexport function slowTransactionThreshold(\n configured?: number | false,\n): number | null {\n // Read per call, never cached at module scope. `scripts/build.ts` rewrites\n // `process.env.NODE_ENV` to `Bun.env.NODE_ENV` precisely so mode stays a\n // runtime question in the built framework; caching it here would undo that.\n if (process.env.NODE_ENV !== \"development\") return null;\n\n // The one way to switch it off, and it has to be spelled. Everything else\n // falls back, so the warning is never lost to a mistyped value — only to an\n // explicit `false`.\n if (configured === false) return null;\n\n if (configured === undefined) return SLOW_TRANSACTION_THRESHOLD;\n if (!Number.isFinite(configured) || configured <= 0) {\n return SLOW_TRANSACTION_THRESHOLD;\n }\n return configured;\n}\n\n/**\n * Warn, in development only, about a transaction that has been open too long.\n *\n * The risk is structural rather than occasional: an open transaction holds one\n * reserved connection for as long as its callback runs, and nothing about\n * `Model.transaction(async () => { ... })` stops that callback from awaiting a\n * `fetch`, an S3 upload or a slow queue push. Under concurrency that drains the\n * pool, and the symptom — every unrelated query in the process blocking on\n * connection acquisition — names neither the callback nor the I/O in it.\n *\n * A timer rather than measuring elapsed time on the way out, for one reason:\n * the worst case is the transaction that *never* settles (a hung request, a\n * lock wait, a deadlock). After-the-fact measurement is silent for exactly that\n * case; a timer fires while it is still open and still holding the connection.\n *\n * The `Error` is constructed up front and read only if the timer fires — V8\n * formats `.stack` lazily on first access, so an ordinary fast transaction pays\n * for an object allocation and nothing else.\n *\n * The clock starts at the `begin` call, not at the moment a connection is\n * acquired, and stops when `begin` settles rather than when the callback\n * returns — so it spans the pool wait and the commit round-trip as well as the\n * callback. That is deliberate: all three are time this transaction is in\n * flight, and a warning that only covered the callback would stay silent for a\n * transaction stuck waiting on an exhausted pool, which is the exact situation\n * a long transaction elsewhere creates. Hence \"not settled\" rather than \"open\n * for\" — the message must not claim a connection was held for the whole span.\n */\nfunction watchForSlowTransaction(configured?: number | false): () => void {\n const threshold = slowTransactionThreshold(configured);\n if (threshold === null) return () => {};\n\n const site = new Error(\"transaction opened here\");\n\n const timer = setTimeout(() => {\n const stack = site.stack?.split(\"\\n\").slice(1).join(\"\\n\") ?? \"\";\n console.warn(\n `[gemi] A database transaction has not settled after ${threshold}ms. It ` +\n `reserves a pooled connection until it does — check for network or ` +\n `filesystem I/O inside the callback, and move it outside the ` +\n `transaction if you find any.\\n${stack}\\n` +\n `(development only; set database.slowTransactionThreshold to change ` +\n `the threshold, or false to switch this off)`,\n );\n }, threshold);\n\n // Otherwise the warning timer is itself a reason the process stays alive,\n // which would turn a diagnostic into a hang in short-lived commands and\n // scripts.\n timer.unref?.();\n\n return () => clearTimeout(timer);\n}\n\n/**\n * Runs what a committed transaction deferred, outside the transaction it was\n * deferred by.\n *\n * `outside` is the scope that was ambient before `begin` — an `asSystem` block,\n * a named connection, or nothing at all — and re-entering it explicitly is the\n * guarantee rather than a tidy-up. The alternative is relying on where a `.then`\n * happens to have captured its context, and the failure that produces is the\n * one the whole feature is about: a listener that runs \"after commit\" while\n * still holding the closed transaction's handle joins nothing, because Bun's\n * handle stays callable and simply runs on the pool. So the scope is rebuilt\n * with `tx` and the drained list cleared, and a listener that opens its own\n * transaction gets a real one.\n *\n * Errors are caught per callback and the next one still runs, for the reason\n * the event subsystem catches per listener: these are independent side effects\n * whose order came from a filesystem walk. And the transaction is not failed by\n * one — it committed, the database kept the rows, and reporting a rejection to\n * the caller would have it roll back or retry work that is already durable.\n * stderr is all that is left, and it is enough: the caller has no decision to\n * make here.\n *\n * The transaction's own promise does not resolve until this has finished, which\n * is the one thing about `afterCommit` that a caller can feel. Deliberate: the\n * alternative is a floating promise whose rejection nobody sees and whose work\n * a short-lived process — a command, a seed — exits out from under.\n */\nasync function drainAfterCommit(\n callbacks: AfterCommitCallback[],\n outside: OrmScope | undefined,\n): Promise<void> {\n if (callbacks.length === 0) return;\n\n await ormContext.run(\n {\n ...outside,\n tx: undefined,\n afterCommit: undefined,\n commitDependsOn: undefined,\n depth: outside?.depth ?? 0,\n },\n async () => {\n for (const callback of callbacks) {\n try {\n await callback();\n } catch (error) {\n console.error(\n `An after-commit callback threw. The transaction it was waiting ` +\n `on had already committed and stays committed, and the ` +\n `callbacks after it still ran.`,\n error,\n );\n }\n }\n },\n );\n}\n\n/**\n * Run `fn` inside a transaction, entering the ambient scope for its whole async\n * subtree.\n *\n * The single implementation behind both `Model.transaction` and\n * `DB.transaction`, so the two cannot become transaction systems that ignore\n * each other: a `Model.create` inside a `DB.transaction` joins it, and a raw\n * `DB.sql` inside a `Model.transaction` can join it through\n * `currentTransaction()`.\n *\n * Nesting becomes a savepoint. Not a preference — Bun refuses the alternative\n * outright (`cannot call begin inside a transaction use savepoint() instead`),\n * and a savepoint is the semantics worth having anyway: an inner failure rolls\n * back to it and leaves the outer transaction usable, which a caller that\n * catches can rely on. Verified on SQLite and Postgres.\n *\n * Note Bun hands the savepoint callback the *same* handle object as the outer\n * transaction (`sp === tx`), so the depth counter is the only thing that\n * actually changes on the way in. The callback's argument is still what gets\n * stored, so this keeps working if that ever stops being true. The cast is\n * because Bun types a savepoint handle as plain `SQL` — without `savepoint` on\n * it — while the runtime object does carry the method, which is what makes\n * three levels of nesting work.\n *\n * Anything `deferUntilCommit` queued is drained once `begin` resolves, outside\n * the transaction and only on the outermost call — a savepoint has committed\n * nothing durable, so draining there would run work that a later rollback of\n * the enclosing transaction was meant to have prevented. See `drainAfterCommit`\n * for what that costs the caller.\n *\n * In development, an outermost transaction that stays open past\n * `options.slowTransactionThreshold` (2s by default, `false` to disable) warns\n * — see `watchForSlowTransaction`. Nothing here *prevents* a long transaction;\n * the warning exists because the cost of one is paid by unrelated queries\n * elsewhere in the process, which makes it hard to trace back.\n *\n * The threshold is passed in rather than read from `app(DatabaseManager)` here.\n * Every caller already holds the manager — it is where `pool` came from — and\n * taking it as an argument keeps this file free of the container, so a bare\n * `SQL` is still enough to call it. Its tests rely on that.\n *\n * `options.connection` is the name `pool` belongs to, and follows the same rule\n * for the same reason: the pool cannot be asked what it is called. Passing it\n * is what lets a nested `withTransaction` tell \"the same connection, so take a\n * savepoint\" from \"a different one, so refuse\" — omitting it means the default\n * connection, which is what a two-argument call always meant.\n *\n * The return type is asserted rather than inferred for one reason worth\n * knowing: Bun's `begin` unwraps a callback that resolves to an *array of\n * promises*, awaiting each. So `Model.transaction(async () => [a, b])` where\n * `a` and `b` are promises resolves to their values, not to the promises. That\n * is Bun's behaviour and is left alone; it is only surprising if unmentioned.\n */\nexport function withTransaction<T>(\n pool: SQL,\n fn: (tx: TransactionSQL) => Promise<T>,\n options?: { slowTransactionThreshold?: number | false; connection?: string },\n): Promise<T> {\n const current = ormContext.getStore();\n\n // THE SINGLE-CONNECTION ASSUMPTION, WHICH IS NOW CHECKED RATHER THAN PINNED.\n //\n // The savepoint branch below ignores `pool` entirely. That was correct while\n // there was one `DatabaseManager` and one `SQL` — the ambient handle and\n // whatever pool the caller passed were necessarily the same database — and\n // the note that stood here said what would happen when a second connection\n // became configurable (#327): a `DB.transaction` on B inside a\n // `Model.transaction` on A would savepoint on **A** and hand the callback A's\n // handle, so statements landed in the wrong database with no error at all.\n //\n // So the name is compared before the branch is taken, and a mismatch raises.\n // Refusing is the whole answer rather than half of one — there is no way to\n // make one transaction span two pools, and the alternatives are covered on\n // `CrossConnectionTransactionError`.\n //\n // A caller that passes no `connection` is treated as naming the default,\n // which is what `withTransaction(pool, fn)` meant before this argument\n // existed.\n const name = options?.connection ?? DEFAULT_CONNECTION;\n assertConnectionUsable(name);\n\n // `current?.tx` rather than `current`: since iteration 6 a scope can exist\n // with no open transaction — `Model.asSystem` enters one — and a savepoint\n // needs an actual handle, not merely a store.\n if (current?.tx) {\n // WHERE THE SHARED AFTER-COMMIT LIST IS PUT RIGHT.\n //\n // The savepoint's scope is a spread of this one, so it appends to the\n // transaction's list rather than to a list of its own — which is what makes\n // \"the outer transaction rolled back, so nothing runs\" free. The case that\n // is not free is this one: the savepoint rolls back and the transaction\n // goes on to commit. Its entries have to go, or a dispatch made inside a\n // block the database threw away runs anyway, which is the same wrong answer\n // as before with an extra step.\n //\n // A mark on the way in and a truncate on the way out, rather than tagging\n // each entry with its depth and dropping everything at or below the failing\n // one. Depth cannot tell two *siblings* apart: a savepoint that committed\n // and one that rolled back both left entries at the same depth, adjacent in\n // the list, and dropping by depth would discard the committed sibling's\n // work as well. The index is exact because the ORM issues one statement at\n // a time on a transaction handle — see `OrmScope.tx` — so nothing appends\n // between the mark and the failure but this savepoint's own subtree.\n const deferred = current.afterCommit;\n const mark = deferred?.length ?? 0;\n // The same mark for the writes the commit depends on. The savepoint waits\n // for its own before it releases, so one that failed rolls back only the\n // savepoint — which a caller that catches can survive, exactly as it\n // survives a statement that threw inside it — and is then forgotten\n // rather than failing the transaction a second time.\n const dependencies = current.commitDependsOn;\n const dependencyMark = dependencies?.length ?? 0;\n\n return current.tx\n .savepoint((sp) => {\n const nested = sp as TransactionSQL;\n return ormContext.run(\n { ...current, tx: nested, depth: current.depth + 1 },\n async () => {\n const result = await fn(nested);\n if (dependencies) {\n await awaitDependencies(dependencies, dependencyMark);\n }\n return result;\n },\n );\n })\n .catch((error: unknown) => {\n if (deferred) deferred.length = mark;\n if (dependencies) dependencies.length = dependencyMark;\n throw error;\n }) as Promise<T>;\n }\n\n // Only the outermost scope is watched. A savepoint reserves no connection of\n // its own — its lifetime is bounded by the transaction it sits in, which is\n // already being timed — so warning per depth would report one slow block as\n // several warnings and point at the innermost frame rather than the one\n // holding the connection.\n const stopWatching = watchForSlowTransaction(\n options?.slowTransactionThreshold,\n );\n\n // Built out here rather than inside the `begin` callback, because the drain\n // below needs it *after* that callback's scope is gone, and reading it off\n // the store then is exactly what is no longer possible.\n const deferred: AfterCommitCallback[] = [];\n const dependencies: Promise<unknown>[] = [];\n\n // The `try` covers a *synchronous* throw from `begin` — a closed pool, say.\n // `.finally` alone would not: it is only attached once `begin` has returned a\n // promise, so a synchronous throw escapes with the timer still armed and\n // eventually warns about a transaction that never opened. `unref` keeps that\n // from holding the process, which makes it cosmetic rather than a leak, but\n // it is the same gap the `.finally` below exists to close.\n try {\n // Spread rather than replace: a `Model.transaction` inside a\n // `Model.asSystem` must not silently re-enable policies for its subtree.\n //\n // The connection goes into the scope alongside the handle, and the pair is\n // what makes the check at the top of this function possible: \"which\n // connection is this transaction on\" has to be answerable from the store,\n // because the handle itself does not say. It is also what makes an\n // unqualified query inside `DB.connection(\"analytics\").transaction(...)`\n // *join* the transaction instead of being refused by it — the query\n // inherits the name rather than defaulting to the hot path.\n return (\n pool\n .begin((tx) =>\n ormContext.run(\n {\n ...current,\n tx,\n depth: 0,\n connection: name === DEFAULT_CONNECTION ? undefined : name,\n // A fresh list per outermost transaction, assigned rather than\n // left to the spread. `current` holds no list today — the drain\n // clears the field before it runs anything — and assigning is\n // what keeps that from being load-bearing: a transaction opened\n // by a callback during a drain gets its own list either way,\n // rather than appending to the array it is being run out of.\n afterCommit: deferred,\n commitDependsOn: dependencies,\n },\n async () => {\n const result = await fn(tx);\n await awaitDependencies(dependencies, 0);\n return result;\n },\n ),\n )\n // `finally` and not a `then`/`catch` pair: the connection is released on\n // rollback exactly as it is on commit, so a throwing callback must clear\n // the timer too or every failed transaction leaves a warning armed\n // against a connection that has already gone back to the pool.\n //\n // Before the drain, so that a slow after-commit listener is not\n // reported as a transaction that will not settle. The connection went\n // back to the pool at the commit; the warning is about holding it.\n .finally(stopWatching)\n // Only here, on the fulfilled path. A rejected `begin` rolled back, so\n // the scope and everything queued on it are discarded unread — which is\n // the whole of what `afterCommit` promises.\n .then(async (result) => {\n await drainAfterCommit(deferred, current);\n return result;\n }) as Promise<T>\n );\n } catch (error) {\n stopWatching();\n throw error;\n }\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "4C5B7052CD785D8164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
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
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import { ServiceProvider } from \"../support/ServiceProvider\";\nimport { withDefaults } from \"../support/withDefaults\";\nimport { Translator } from \"./Translator\";\nimport { translationConfigDefaults, type TranslationConfig } from \"./config\";\n\nexport class TranslationServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n Translator,\n () =>\n new Translator(\n withDefaults(\n translationConfigDefaults(),\n this.app.config.get<TranslationConfig>(\"translation\", {}),\n ),\n ),\n );\n }\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";sLAKO,AAAM,IAAmC,LAAgB,CAC9D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,EAA0B,EAC1B,KAAK,IAAI,OAAO,IAAuB,cAAe,CAAC,CAAC,CAC1D,CACF,CACJ,EAEJ",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "C32FA7347CB1EE1064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
class A extends Error{constructor(p,q){super(`Target [${p}] is not bound in the container.`+(q.length>0?` Bound tokens: ${q.join(", ")}.`:" No tokens are bound \u2014 was the application booted?"));this.name="BindingResolutionError"}}class C{bindings=new Map;instances=new Map;bind(p,q){this.bindings.set(p.token,{factory:q,shared:!1}),this.instances.delete(p.token)}singleton(p,q){this.bindings.set(p.token,{factory:q,shared:!0}),this.instances.delete(p.token)}instance(p,q){return this.instances.set(p.token,q),q}bound(p){return this.bindings.has(p.token)||this.instances.has(p.token)}resolved(p){return this.instances.has(p.token)}make(p){let q=p.token;if(this.instances.has(q))return this.instances.get(q);let v=this.bindings.get(q);if(!v)throw new A(q,this.keys());let x=v.factory(this);if(v.shared)this.instances.set(q,x);return x}forget(p){this.instances.delete(p.token)}keys(){return[...new Set([...this.bindings.keys(),...this.instances.keys()])]}flush(){this.bindings.clear(),this.instances.clear()}}
|
|
3
|
-
export{A as
|
|
3
|
+
export{A as ci,C as di};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
5
|
+
//# debugId=5274BDBE868C2F3164756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"/**\n * Tokens are the service classes themselves, so `make(MailManager)` is typed\n * `MailManager` without a cast. The container keys its bindings off the class's\n * `static token` string rather than the constructor object: the built binary\n * (`dist/bin/gemi.js`) bundles its own copy of gemi while the app resolves\n * `gemi/*` to source, so the same service is two distinct class objects across\n * that boundary. A string survives it. Laravel binds both `'mail'` and\n * `MailManager::class` for the same reason.\n */\nexport type ServiceToken<T> = (abstract new (...args: any[]) => T) & {\n token: string;\n};\n\nexport type Factory<T> = (app: Container) => T;\n\ninterface Binding {\n factory: Factory<any>;\n shared: boolean;\n}\n\nexport class BindingResolutionError extends Error {\n constructor(token: string, known: string[]) {\n super(\n `Target [${token}] is not bound in the container.` +\n (known.length > 0\n ? ` Bound tokens: ${known.join(\", \")}.`\n : \" No tokens are bound — was the application booted?\"),\n );\n this.name = \"BindingResolutionError\";\n }\n}\n\nexport class Container {\n private bindings = new Map<string, Binding>();\n private instances = new Map<string, any>();\n\n bind<T>(token: ServiceToken<T>, factory: Factory<T>) {\n this.bindings.set(token.token, { factory, shared: false });\n this.instances.delete(token.token);\n }\n\n /**\n * Lazy by design — `factory` is not called until the first `make()`.\n */\n singleton<T>(token: ServiceToken<T>, factory: Factory<T>) {\n this.bindings.set(token.token, { factory, shared: true });\n this.instances.delete(token.token);\n }\n\n instance<T>(token: ServiceToken<T>, object: T): T {\n this.instances.set(token.token, object);\n return object;\n }\n\n bound<T>(token: ServiceToken<T>): boolean {\n return (\n this.bindings.has(token.token) || this.instances.has(token.token)\n );\n }\n\n resolved<T>(token: ServiceToken<T>): boolean {\n return this.instances.has(token.token);\n }\n\n make<T>(token: ServiceToken<T>): T {\n const key = token.token;\n\n if (this.instances.has(key)) {\n return this.instances.get(key) as T;\n }\n\n const binding = this.bindings.get(key);\n if (!binding) {\n throw new BindingResolutionError(key, this.keys());\n }\n\n const object = binding.factory(this) as T;\n if (binding.shared) {\n this.instances.set(key, object);\n }\n return object;\n }\n\n forget<T>(token: ServiceToken<T>) {\n this.instances.delete(token.token);\n }\n\n keys(): string[] {\n return [\n ...new Set([...this.bindings.keys(), ...this.instances.keys()]),\n ];\n }\n\n flush() {\n this.bindings.clear();\n this.instances.clear();\n }\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";AAoBO,MAAM,UAA+B,KAAM,CAChD,WAAW,CAAC,EAAe,EAAiB,CAC1C,MACE,WAAW,qCACR,EAAM,OAAS,EACZ,kBAAkB,EAAM,KAAK,IAAI,KACjC,0DACR,EACA,KAAK,KAAO,yBAEhB,CAEO,MAAM,CAAU,CACb,SAAW,IAAI,IACf,UAAY,IAAI,IAExB,IAAO,CAAC,EAAwB,EAAqB,CACnD,KAAK,SAAS,IAAI,EAAM,MAAO,CAAE,UAAS,OAAQ,EAAM,CAAC,EACzD,KAAK,UAAU,OAAO,EAAM,KAAK,EAMnC,SAAY,CAAC,EAAwB,EAAqB,CACxD,KAAK,SAAS,IAAI,EAAM,MAAO,CAAE,UAAS,OAAQ,EAAK,CAAC,EACxD,KAAK,UAAU,OAAO,EAAM,KAAK,EAGnC,QAAW,CAAC,EAAwB,EAAc,CAEhD,OADA,KAAK,UAAU,IAAI,EAAM,MAAO,CAAM,EAC/B,EAGT,KAAQ,CAAC,EAAiC,CACxC,OACE,KAAK,SAAS,IAAI,EAAM,KAAK,GAAK,KAAK,UAAU,IAAI,EAAM,KAAK,EAIpE,QAAW,CAAC,EAAiC,CAC3C,OAAO,KAAK,UAAU,IAAI,EAAM,KAAK,EAGvC,IAAO,CAAC,EAA2B,CACjC,IAAM,EAAM,EAAM,MAElB,GAAI,KAAK,UAAU,IAAI,CAAG,EACxB,OAAO,KAAK,UAAU,IAAI,CAAG,EAG/B,IAAM,EAAU,KAAK,SAAS,IAAI,CAAG,EACrC,GAAI,CAAC,EACH,MAAM,IAAI,EAAuB,EAAK,KAAK,KAAK,CAAC,EAGnD,IAAM,EAAS,EAAQ,QAAQ,IAAI,EACnC,GAAI,EAAQ,OACV,KAAK,UAAU,IAAI,EAAK,CAAM,EAEhC,OAAO,EAGT,MAAS,CAAC,EAAwB,CAChC,KAAK,UAAU,OAAO,EAAM,KAAK,EAGnC,IAAI,EAAa,CACf,MAAO,CACL,GAAG,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,KAAK,EAAG,GAAG,KAAK,UAAU,KAAK,CAAC,CAAC,CAChE,EAGF,KAAK,EAAG,CACN,KAAK,SAAS,MAAM,EACpB,KAAK,UAAU,MAAM,EAEzB",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "5274BDBE868C2F3164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{X as M}from"./chunk-
|
|
2
|
+
import{X as M}from"./chunk-56jky6vf.js";import{ti as E}from"./chunk-vw8849ys.js";class x{marshaller;serializer;deserializer;serdeContext;defaultContentType;constructor({marshaller:i,serializer:n,deserializer:o,serdeContext:c,defaultContentType:y}){this.marshaller=i,this.serializer=n,this.deserializer=o,this.serdeContext=c,this.defaultContentType=y}async serializeEventStream({eventStream:i,requestSchema:n,initialRequest:o}){let c=this.marshaller,y=n.getEventStreamMember(),p=n.getMemberSchema(y),d=this.serializer,f=this.defaultContentType,h=Symbol("initialRequestMarker"),S={async*[Symbol.asyncIterator](){if(o){let r={":event-type":{type:"string",value:"initial-request"},":message-type":{type:"string",value:"event"},":content-type":{type:"string",value:f}};d.write(n,o);let t=d.flush();yield{[h]:!0,headers:r,body:t}}for await(let r of i)yield r}};return c.serialize(S,(r)=>{if(r[h])return{headers:r.headers,body:r.body};let t=Object.keys(r).find((s)=>{return s!=="__type"})??"",{additionalHeaders:e,body:a,eventType:l,explicitPayloadContentType:m}=this.writeEventBody(t,p,r);return{headers:{":event-type":{type:"string",value:l},":message-type":{type:"string",value:"event"},":content-type":{type:"string",value:m??f},...e},body:a}})}async deserializeEventStream({response:i,responseSchema:n,initialResponseContainer:o}){let c=this.marshaller,y=n.getEventStreamMember(),d=n.getMemberSchema(y).getMemberSchemas(),f=Symbol("initialResponseMarker"),h=c.deserialize(i.body,async(t)=>{let e=Object.keys(t).find((l)=>{return l!=="__type"})??"",a=t[e].body;if(e==="initial-response"){let l=await this.deserializer.read(n,a);return delete l[y],{[f]:!0,...l}}else if(e in d){let l=d[e];if(l.isStructSchema()){let m={},u=!1;for(let[s,g]of l.structIterator()){let{eventHeader:v,eventPayload:w}=g.getMergedTraits();if(u=u||Boolean(v||w),w){if(g.isBlobSchema())m[s]=a;else if(g.isStringSchema())m[s]=(this.serdeContext?.utf8Encoder??z.toUtf8)(a);else if(g.isStructSchema())m[s]=await this.deserializer.read(g,a)}else if(v){let b=t[e].headers[s]?.value;if(b!=null)if(g.isNumericSchema())if(b&&typeof b==="object"&&"bytes"in b)m[s]=BigInt(b.toString());else m[s]=Number(b);else m[s]=b}}if(u)return{[e]:m};if(a.byteLength===0)return{[e]:{}}}return{[e]:await this.deserializer.read(l,a)}}else return{$unknown:t}}),S=h[Symbol.asyncIterator](),r=await S.next();if(r.done)return h;if(r.value?.[f]){if(!n)throw Error("@smithy::core/protocols - initial-response event encountered in event stream but no response schema given.");for(let[t,e]of Object.entries(r.value))o[t]=e}return{async*[Symbol.asyncIterator](){if(!r?.value?.[f])yield r.value;while(!0){let{done:t,value:e}=await S.next();if(t)break;yield e}}}}writeEventBody(i,n,o){let c=this.serializer,y=i,p=null,d,f=(()=>{return n.getSchema()[4].includes(i)})(),h={};if(!f){let[t,e]=o[i];y=t,c.write(15,e)}else{let t=n.getMemberSchema(i);if(t.isStructSchema()){for(let[e,a]of t.structIterator()){let{eventHeader:l,eventPayload:m}=a.getMergedTraits();if(m)p=e;else if(l){let u=o[i][e],s="binary";if(a.isNumericSchema())if(-2147483648<=u&&u<=2147483647)s="integer";else s="long";else if(a.isTimestampSchema())s="timestamp";else if(a.isStringSchema())s="string";else if(a.isBooleanSchema())s="boolean";if(u!=null)h[e]={type:s,value:u},delete o[i][e]}}if(p!==null){let e=t.getMemberSchema(p);if(e.isBlobSchema())d="application/octet-stream";else if(e.isStringSchema())d="text/plain";c.write(e,o[i][p])}else c.write(t,o[i])}else if(t.isUnitSchema())c.write(t,{});else throw Error("@smithy/core/event-streams - non-struct member not supported in event stream union.")}let S=c.flush()??new Uint8Array;return{body:typeof S==="string"?(this.serdeContext?.utf8Decoder??z.fromUtf8)(S):S,eventType:y,explicitPayloadContentType:d,additionalHeaders:h}}}var z,T;var C=E(()=>{z=M();T=x});C();export{T as EventStreamSerde};export default {get EventStreamSerde(){return T}};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=0C7046650647BA6364756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"'use strict';\n\nvar utilUtf8 = require('@smithy/util-utf8');\n\nclass EventStreamSerde {\n marshaller;\n serializer;\n deserializer;\n serdeContext;\n defaultContentType;\n constructor({ marshaller, serializer, deserializer, serdeContext, defaultContentType, }) {\n this.marshaller = marshaller;\n this.serializer = serializer;\n this.deserializer = deserializer;\n this.serdeContext = serdeContext;\n this.defaultContentType = defaultContentType;\n }\n async serializeEventStream({ eventStream, requestSchema, initialRequest, }) {\n const marshaller = this.marshaller;\n const eventStreamMember = requestSchema.getEventStreamMember();\n const unionSchema = requestSchema.getMemberSchema(eventStreamMember);\n const serializer = this.serializer;\n const defaultContentType = this.defaultContentType;\n const initialRequestMarker = Symbol(\"initialRequestMarker\");\n const eventStreamIterable = {\n async *[Symbol.asyncIterator]() {\n if (initialRequest) {\n const headers = {\n \":event-type\": { type: \"string\", value: \"initial-request\" },\n \":message-type\": { type: \"string\", value: \"event\" },\n \":content-type\": { type: \"string\", value: defaultContentType },\n };\n serializer.write(requestSchema, initialRequest);\n const body = serializer.flush();\n yield {\n [initialRequestMarker]: true,\n headers,\n body,\n };\n }\n for await (const page of eventStream) {\n yield page;\n }\n },\n };\n return marshaller.serialize(eventStreamIterable, (event) => {\n if (event[initialRequestMarker]) {\n return {\n headers: event.headers,\n body: event.body,\n };\n }\n const unionMember = Object.keys(event).find((key) => {\n return key !== \"__type\";\n }) ?? \"\";\n const { additionalHeaders, body, eventType, explicitPayloadContentType } = this.writeEventBody(unionMember, unionSchema, event);\n const headers = {\n \":event-type\": { type: \"string\", value: eventType },\n \":message-type\": { type: \"string\", value: \"event\" },\n \":content-type\": { type: \"string\", value: explicitPayloadContentType ?? defaultContentType },\n ...additionalHeaders,\n };\n return {\n headers,\n body,\n };\n });\n }\n async deserializeEventStream({ response, responseSchema, initialResponseContainer, }) {\n const marshaller = this.marshaller;\n const eventStreamMember = responseSchema.getEventStreamMember();\n const unionSchema = responseSchema.getMemberSchema(eventStreamMember);\n const memberSchemas = unionSchema.getMemberSchemas();\n const initialResponseMarker = Symbol(\"initialResponseMarker\");\n const asyncIterable = marshaller.deserialize(response.body, async (event) => {\n const unionMember = Object.keys(event).find((key) => {\n return key !== \"__type\";\n }) ?? \"\";\n const body = event[unionMember].body;\n if (unionMember === \"initial-response\") {\n const dataObject = await this.deserializer.read(responseSchema, body);\n delete dataObject[eventStreamMember];\n return {\n [initialResponseMarker]: true,\n ...dataObject,\n };\n }\n else if (unionMember in memberSchemas) {\n const eventStreamSchema = memberSchemas[unionMember];\n if (eventStreamSchema.isStructSchema()) {\n const out = {};\n let hasBindings = false;\n for (const [name, member] of eventStreamSchema.structIterator()) {\n const { eventHeader, eventPayload } = member.getMergedTraits();\n hasBindings = hasBindings || Boolean(eventHeader || eventPayload);\n if (eventPayload) {\n if (member.isBlobSchema()) {\n out[name] = body;\n }\n else if (member.isStringSchema()) {\n out[name] = (this.serdeContext?.utf8Encoder ?? utilUtf8.toUtf8)(body);\n }\n else if (member.isStructSchema()) {\n out[name] = await this.deserializer.read(member, body);\n }\n }\n else if (eventHeader) {\n const value = event[unionMember].headers[name]?.value;\n if (value != null) {\n if (member.isNumericSchema()) {\n if (value && typeof value === \"object\" && \"bytes\" in value) {\n out[name] = BigInt(value.toString());\n }\n else {\n out[name] = Number(value);\n }\n }\n else {\n out[name] = value;\n }\n }\n }\n }\n if (hasBindings) {\n return {\n [unionMember]: out,\n };\n }\n if (body.byteLength === 0) {\n return {\n [unionMember]: {},\n };\n }\n }\n return {\n [unionMember]: await this.deserializer.read(eventStreamSchema, body),\n };\n }\n else {\n return {\n $unknown: event,\n };\n }\n });\n const asyncIterator = asyncIterable[Symbol.asyncIterator]();\n const firstEvent = await asyncIterator.next();\n if (firstEvent.done) {\n return asyncIterable;\n }\n if (firstEvent.value?.[initialResponseMarker]) {\n if (!responseSchema) {\n throw new Error(\"@smithy::core/protocols - initial-response event encountered in event stream but no response schema given.\");\n }\n for (const [key, value] of Object.entries(firstEvent.value)) {\n initialResponseContainer[key] = value;\n }\n }\n return {\n async *[Symbol.asyncIterator]() {\n if (!firstEvent?.value?.[initialResponseMarker]) {\n yield firstEvent.value;\n }\n while (true) {\n const { done, value } = await asyncIterator.next();\n if (done) {\n break;\n }\n yield value;\n }\n },\n };\n }\n writeEventBody(unionMember, unionSchema, event) {\n const serializer = this.serializer;\n let eventType = unionMember;\n let explicitPayloadMember = null;\n let explicitPayloadContentType;\n const isKnownSchema = (() => {\n const struct = unionSchema.getSchema();\n return struct[4].includes(unionMember);\n })();\n const additionalHeaders = {};\n if (!isKnownSchema) {\n const [type, value] = event[unionMember];\n eventType = type;\n serializer.write(15, value);\n }\n else {\n const eventSchema = unionSchema.getMemberSchema(unionMember);\n if (eventSchema.isStructSchema()) {\n for (const [memberName, memberSchema] of eventSchema.structIterator()) {\n const { eventHeader, eventPayload } = memberSchema.getMergedTraits();\n if (eventPayload) {\n explicitPayloadMember = memberName;\n }\n else if (eventHeader) {\n const value = event[unionMember][memberName];\n let type = \"binary\";\n if (memberSchema.isNumericSchema()) {\n if ((-2) ** 31 <= value && value <= 2 ** 31 - 1) {\n type = \"integer\";\n }\n else {\n type = \"long\";\n }\n }\n else if (memberSchema.isTimestampSchema()) {\n type = \"timestamp\";\n }\n else if (memberSchema.isStringSchema()) {\n type = \"string\";\n }\n else if (memberSchema.isBooleanSchema()) {\n type = \"boolean\";\n }\n if (value != null) {\n additionalHeaders[memberName] = {\n type,\n value,\n };\n delete event[unionMember][memberName];\n }\n }\n }\n if (explicitPayloadMember !== null) {\n const payloadSchema = eventSchema.getMemberSchema(explicitPayloadMember);\n if (payloadSchema.isBlobSchema()) {\n explicitPayloadContentType = \"application/octet-stream\";\n }\n else if (payloadSchema.isStringSchema()) {\n explicitPayloadContentType = \"text/plain\";\n }\n serializer.write(payloadSchema, event[unionMember][explicitPayloadMember]);\n }\n else {\n serializer.write(eventSchema, event[unionMember]);\n }\n }\n else if (eventSchema.isUnitSchema()) {\n serializer.write(eventSchema, {});\n }\n else {\n throw new Error(\"@smithy/core/event-streams - non-struct member not supported in event stream union.\");\n }\n }\n const messageSerialization = serializer.flush() ?? new Uint8Array();\n const body = typeof messageSerialization === \"string\"\n ? (this.serdeContext?.utf8Decoder ?? utilUtf8.fromUtf8)(messageSerialization)\n : messageSerialization;\n return {\n body,\n eventType,\n explicitPayloadContentType,\n additionalHeaders,\n };\n }\n}\n\nexports.EventStreamSerde = EventStreamSerde;\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "0C7046650647BA6364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{_ as F}from"./chunk-
|
|
2
|
+
import{_ as F}from"./chunk-eqse2m6n.js";import{aa as w}from"./chunk-fre6f4nk.js";import{ri as h}from"./chunk-vw8849ys.js";var P=h((p)=>{var t=w(),l=F();function d(e){try{let o=new Set(Array.from(e.match(/([A-Z_]){3,}/g)??[]));return o.delete("CONFIG"),o.delete("CONFIG_PREFIX_SEPARATOR"),o.delete("ENV"),[...o].join(", ")}catch(o){return e}}var u=(e,o)=>async()=>{try{let r=e(process.env,o);if(r===void 0)throw Error();return r}catch(r){throw new t.CredentialsProviderError(r.message||`Not found in ENV: ${d(e.toString())}`,{logger:o?.logger})}},C=(e,{preferredFile:o="config",...r}={})=>async()=>{let n=l.getProfileName(r),{configFile:i,credentialsFile:c}=await l.loadSharedConfigFiles(r),s=c[n]||{},g=i[n]||{},m=o==="config"?{...s,...g}:{...g,...s};try{let f=e(m,o==="config"?i:c);if(f===void 0)throw Error();return f}catch(a){throw new t.CredentialsProviderError(a.message||`Not found in config files w/ profile [${n}]: ${d(e.toString())}`,{logger:r.logger})}},y=(e)=>typeof e==="function",E=(e)=>y(e)?async()=>await e():t.fromStatic(e),N=({environmentVariableSelector:e,configFileSelector:o,default:r},n={})=>{let{signingName:i,logger:c}=n,s={signingName:i,logger:c};return t.memoize(t.chain(u(e,s),C(o,n),E(r)))};p.loadConfig=N});
|
|
3
3
|
export{P as Y};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
5
|
+
//# debugId=A9AE6A37D6EF882964756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"'use strict';\n\nvar propertyProvider = require('@smithy/property-provider');\nvar sharedIniFileLoader = require('@smithy/shared-ini-file-loader');\n\nfunction getSelectorName(functionString) {\n try {\n const constants = new Set(Array.from(functionString.match(/([A-Z_]){3,}/g) ?? []));\n constants.delete(\"CONFIG\");\n constants.delete(\"CONFIG_PREFIX_SEPARATOR\");\n constants.delete(\"ENV\");\n return [...constants].join(\", \");\n }\n catch (e) {\n return functionString;\n }\n}\n\nconst fromEnv = (envVarSelector, options) => async () => {\n try {\n const config = envVarSelector(process.env, options);\n if (config === undefined) {\n throw new Error();\n }\n return config;\n }\n catch (e) {\n throw new propertyProvider.CredentialsProviderError(e.message || `Not found in ENV: ${getSelectorName(envVarSelector.toString())}`, { logger: options?.logger });\n }\n};\n\nconst fromSharedConfigFiles = (configSelector, { preferredFile = \"config\", ...init } = {}) => async () => {\n const profile = sharedIniFileLoader.getProfileName(init);\n const { configFile, credentialsFile } = await sharedIniFileLoader.loadSharedConfigFiles(init);\n const profileFromCredentials = credentialsFile[profile] || {};\n const profileFromConfig = configFile[profile] || {};\n const mergedProfile = preferredFile === \"config\"\n ? { ...profileFromCredentials, ...profileFromConfig }\n : { ...profileFromConfig, ...profileFromCredentials };\n try {\n const cfgFile = preferredFile === \"config\" ? configFile : credentialsFile;\n const configValue = configSelector(mergedProfile, cfgFile);\n if (configValue === undefined) {\n throw new Error();\n }\n return configValue;\n }\n catch (e) {\n throw new propertyProvider.CredentialsProviderError(e.message || `Not found in config files w/ profile [${profile}]: ${getSelectorName(configSelector.toString())}`, { logger: init.logger });\n }\n};\n\nconst isFunction = (func) => typeof func === \"function\";\nconst fromStatic = (defaultValue) => isFunction(defaultValue) ? async () => await defaultValue() : propertyProvider.fromStatic(defaultValue);\n\nconst loadConfig = ({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => {\n const { signingName, logger } = configuration;\n const envOptions = { signingName, logger };\n return propertyProvider.memoize(propertyProvider.chain(fromEnv(environmentVariableSelector, envOptions), fromSharedConfigFiles(configFileSelector, configuration), fromStatic(defaultValue)));\n};\n\nexports.loadConfig = loadConfig;\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";oJAEA,FAAI,AACA,MAEJ,SAAS,CAAe,CAAC,EAAgB,CACrC,GAAI,CACA,IAAM,EAAY,IAAI,IAAI,MAAM,KAAK,EAAe,MAAM,eAAe,GAAK,CAAC,CAAC,CAAC,EAIjF,OAHA,EAAU,OAAO,QAAQ,EACzB,EAAU,OAAO,yBAAyB,EAC1C,EAAU,OAAO,KAAK,EACf,CAAC,GAAG,CAAS,EAAE,KAAK,IAAI,EAEnC,MAAO,EAAG,CACN,OAAO,GAIf,IAAM,EAAU,CAAC,EAAgB,IAAY,SAAY,CACrD,GAAI,CACA,IAAM,EAAS,EAAe,QAAQ,IAAK,CAAO,EAClD,GAAI,IAAW,OACX,MAAU,MAAM,EAEpB,OAAO,EAEX,MAAO,EAAG,CACN,MAAM,IAAI,EAAiB,yBAAyB,EAAE,SAAW,qBAAqB,EAAgB,EAAe,SAAS,CAAC,IAAK,CAAE,OAAQ,GAAS,MAAO,CAAC,IAIjK,EAAwB,CAAC,GAAkB,gBAAgB,YAAa,GAAS,CAAC,IAAM,SAAY,CACtG,IAAM,EAAU,EAAoB,eAAe,CAAI,GAC/C,aAAY,mBAAoB,MAAM,EAAoB,sBAAsB,CAAI,EACtF,EAAyB,EAAgB,IAAY,CAAC,EACtD,EAAoB,EAAW,IAAY,CAAC,EAC5C,EAAgB,IAAkB,SAClC,IAAK,KAA2B,CAAkB,EAClD,IAAK,KAAsB,CAAuB,EACxD,GAAI,CAEA,IAAM,EAAc,EAAe,EADnB,IAAkB,SAAW,EAAa,CACD,EACzD,GAAI,IAAgB,OAChB,MAAU,MAAM,EAEpB,OAAO,EAEX,MAAO,EAAG,CACN,MAAM,IAAI,EAAiB,yBAAyB,EAAE,SAAW,yCAAyC,OAAa,EAAgB,EAAe,SAAS,CAAC,IAAK,CAAE,OAAQ,EAAK,MAAO,CAAC,IAI9L,EAAa,CAAC,IAAS,OAAO,IAAS,WACvC,EAAa,CAAC,IAAiB,EAAW,CAAY,EAAI,SAAY,MAAM,EAAa,EAAI,EAAiB,WAAW,CAAY,EAErI,EAAa,EAAG,8BAA6B,qBAAoB,QAAS,GAAgB,EAAgB,CAAC,IAAM,CACnH,IAAQ,cAAa,UAAW,EAC1B,EAAa,CAAE,cAAa,QAAO,EACzC,OAAO,EAAiB,QAAQ,EAAiB,MAAM,EAAQ,EAA6B,CAAU,EAAG,EAAsB,EAAoB,CAAa,EAAG,EAAW,CAAY,CAAC,CAAC,GAGxL,aAAa",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "A9AE6A37D6EF882964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Kg as M}from"./chunk-pn8v6fj2.js";import{bi as P}from"./chunk-t4yh4nf9.js";class C{spent=new Map;sweepAt=1024;async consume(J,Q){return this.consumeSync(J,Q)}consumeSync(J,Q,Z=Date.now()){if(this.spent.size>=this.sweepAt)this.sweep(Z);let W=this.spent.get(J);if(W!==void 0&&W>Z)return!1;return this.spent.set(J,Q),!0}get size(){return this.spent.size}sweep(J){for(let[Q,Z]of this.spent)if(Z<=J)this.spent.delete(Q);this.sweepAt=Math.max(1024,this.spent.size*2)}}class N{injectedClient;prefix;constructor(J={}){this.injectedClient=J.client,this.prefix=J.prefix??"gemi:ai:nonce"}async consume(J,Q){let Z=Math.max(1,Math.ceil(Q-Date.now()));return await this.client.send("SET",[`${this.prefix}:${J}`,"1","PX",String(Z),"NX"])==="OK"}get client(){if(this.injectedClient)return this.injectedClient;let J=P(),Q=J.bound(M)?J.make(M).client:void 0;if(!Q)throw Error("RedisNonceStore could not reach the Redis client. Register RedisServiceProvider on your application, or pass a client: new RedisNonceStore({ client }).");return Q}}var S=new C;class D extends Error{retryable;constructor(J,Q={}){super(J,Q.cause!==void 0?{cause:Q.cause}:void 0);this.name="ToolError",this.retryable=Q.retryable??!0}}var u={provider_error:"The model provider returned an error.",rate_limited:"The model provider is rate limiting requests. Try again shortly.",context_length_exceeded:"The conversation is too long for the model.",content_filtered:"The model provider's content filter blocked this request.",invalid_tool_input:"The model provider rejected the request.",tool_error:"A tool failed.",unknown:"The run failed unexpectedly."};function V(J,Q){if(Q.source==="tool"){if(Q.cause instanceof D)return J;return{...J,message:`The tool "${Q.toolName}" failed with an unexpected error.`}}let Z=u[J.code];return Z===void 0?J:{...J,message:Z}}function e(J,Q,Z,W){let $;try{$=(J??V)(Q,Z)}catch(X){W(X),$=V(Q,Z)}return{code:$.code,message:$.message,...$.toolCallId!==void 0?{toolCallId:$.toolCallId}:{},retryable:$.retryable}}var L=new WeakMap;function JJ(J,Q){if(J!==Q)L.set(J,Q)}function QJ(J){return L.get(J)??J}import{createHmac as E,hkdfSync as m,randomBytes as k,timingSafeEqual as d}from"crypto";var z="agt2",j="agt1",O=[z,j],G=86400000,p=Date.now()+G;function f(J){return J<=p}var v="gemi.ai.pending-call.v1",I="gemi.ai.nested-run.v1",l="gemi.ai.execution-receipt.v1",t="gemi.ai.signing",b=new Map;function H(J,Q){let Z=K(Q),W=`${J}\x00${Z}`,$=b.get(W);if(!$){if($=Buffer.from(m("sha256",Z,t,J,32)),b.size>64)b.clear();b.set(W,$)}return $}function K(J){let Q=J??process.env.SECRET;if(!Q)throw Error("Signing a pending tool call needs an app secret. Set SECRET in the environment.");return Q}function q(J){if(J===null||typeof J!=="object")return JSON.stringify(J)??"null";if(Array.isArray(J))return`[${J.map(q).join(",")}]`;let Q=J;return`{${Object.keys(Q).filter((W)=>Q[W]!==void 0).sort().map((W)=>`${JSON.stringify(W)}:${q(Q[W])}`).join(",")}}`}function c(J){return J.map((Q)=>`${Q.length}:${Q}`).join("")}function B(J,Q){return E("sha256",J).update(c(Q)).digest()}function x(J,Q){let Z=Buffer.from(J.split(".")[4],"base64url");return Z.length===Q.length&&d(Z,Q)}function U(J){return q(J??null)}function R(J,Q,Z){return[z,J.runId,J.toolCallId,J.name,J.kind,Q,String(Z),q(J.input),q(J.path??[]),U(J.subject)]}function n(J,Q,Z){let W=[j,J.runId,J.toolCallId,J.name,J.kind,Q,String(Z),q(J.input)];if(J.path&&J.path.length>0)W.push(q(J.path));return W}var T=(J)=>Buffer.from(J,"utf8").toString("base64url"),o=(J)=>Buffer.from(J,"base64url").toString("utf8");function qJ(J,Q={}){let Z=H(v,Q.secret),$=(Q.now??Date.now())+(Q.ttlMs??G),X=k(12).toString("base64url"),h=B(Z,R(J,X,$)).toString("base64url");return[z,T(J.runId),X,$.toString(36),h].join(".")}function a(J){return Y(J,O)}function Y(J,Q){let Z=J.split(".");if(Z.length!==5||!Q.includes(Z[0]))return null;let W=Number.parseInt(Z[3],36);if(!Number.isFinite(W))return null;try{return{runId:o(Z[1]),nonce:Z[2],expiresAt:W,version:Z[0]}}catch{return null}}function XJ(J,Q,Z={}){let W=Y(J,O);if(!W)return{ok:!1,reason:"malformed"};if(W.version===j&&!f(W.expiresAt))return{ok:!1,reason:"forged"};let $=W.version===j?B(K(Z.secret),n(Q,W.nonce,W.expiresAt)):B(H(v,Z.secret),R(Q,W.nonce,W.expiresAt));if(!x(J,$))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>W.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:W.runId,nonce:W.nonce,expiresAt:W.expiresAt}}var F="agn2",w="agn1",A=[F,w];function _(J,Q,Z){return[...y(J,Q,Z,F),U(J.subject)]}function y(J,Q,Z,W=w){return[W,J.runId,q(J.path),J.nestedRunId,Q,String(Z),q([...J.open].sort()),q(J.input)]}function BJ(J,Q={}){let Z=H(I,Q.secret),$=(Q.now??Date.now())+(Q.ttlMs??G),X=k(12).toString("base64url"),h=B(Z,_(J,X,$)).toString("base64url");return[F,T(J.runId),X,$.toString(36),h].join(".")}function HJ(J,Q,Z={}){let W=Y(J,A);if(!W)return{ok:!1,reason:"malformed"};if(W.version===w&&!f(W.expiresAt))return{ok:!1,reason:"forged"};let $={...Q,runId:W.runId},X=W.version===w?B(K(Z.secret),y($,W.nonce,W.expiresAt)):B(H(I,Z.secret),_($,W.nonce,W.expiresAt));if(!x(J,X))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>W.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:W.runId,nonce:W.nonce,expiresAt:W.expiresAt}}function bJ(J,Q,Z={}){let W=H(l,Z.secret);return B(W,[J,Q.runId,Q.toolCallId,Q.name,Q.kind,q(Q.input),q(Q.path??[]),U(Q.subject)]).toString("base64url")}function jJ(J,Q){return g(Q,a(J))}function wJ(J,Q){return g(Q,Y(J,A))}async function g(J,Q){if(!Q)return!1;return J.consume(Q.nonce,Q.expiresAt)}
|
|
3
3
|
export{C as Sb,N as Tb,S as Ub,H as Vb,q as Wb,qJ as Xb,a as Yb,XJ as Zb,BJ as _b,HJ as $b,bJ as ac,jJ as bc,wJ as cc,D as dc,V as ec,e as fc,JJ as gc,QJ as hc};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
5
|
+
//# debugId=9F5261FBB47F185564756E2164756E21
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"import { createHmac, hkdfSync, randomBytes, timingSafeEqual } from \"crypto\";\nimport { defaultNonceStore, type NonceStore } from \"./store/Nonces\";\n\n/**\n * Signing for pending tool calls.\n *\n * A pending call travels through the browser and comes back — in stateless mode\n * the whole history does — so the server cannot trust that what it gets back is\n * what it sent. Without a signature the client asserts not just *that* a call\n * was approved but *what* was approved, and nothing would stop it from\n * returning `approve: true` against an input it rewrote on the way. Signing is\n * what makes the round trip safe, and it is why approvals need no server-side\n * storage at all.\n *\n * What is signed, and what deliberately is not:\n *\n * signed — `runId`, `toolCallId`, the tool `name`, the `kind` of pending call\n * and a canonical serialization of the input, plus a nonce, an\n * expiry, and — for a call a sub-agent asked — the `path` of\n * tool-call ids it is nested under.\n * not — the client's answer. `approve: true` / `approve: false` and a\n * question's output are the *point* of asking; a client that flips\n * its own answer has refused, not forged. What the signature buys is\n * that the answer is bound to the call the server actually made,\n * with the input the server actually saw.\n *\n * A verified token is not yet an answer the server may act on: it says the\n * question was asked, not that it is still open. `consumePendingCall` at the\n * bottom of this file spends the nonce, which is what makes an approval\n * single-use — see the note there for what that guarantee is worth.\n *\n * `kind` is in there for a specific attack: an `approval`-kind call is one the\n * *server* runs, so a client that reused its signature on the \"here is the\n * output\" arm of `ClientToolResult` would be fabricating a server tool's result\n * rather than approving it. Binding the kind makes that a forgery instead of a\n * shape the caller has to remember to check.\n *\n * Keys and principals (#447). Neither token kind is MACed with `SECRET`\n * itself: each is keyed with its own HKDF-derived key (`purposeKey` below), so\n * a MAC minted for one purpose — a pending call, a parked-run record, or\n * anything else in the app keyed off `SECRET` (CSRF, sessions) — is never a\n * MAC for another. And each binds the `subject`, the principal the run was\n * started for (`AgentController.runOwner`), so a token minted while user A was\n * asked cannot be answered by user B, even with A's history in hand.\n */\n\n/** Everything the signature commits to. */\nexport type PendingCallClaims = {\n runId: string;\n toolCallId: string;\n name: string;\n kind: \"approval\" | \"question\" | \"client\";\n input: unknown;\n /**\n * The chain of tool-call ids the call is nested under, outermost first.\n * Absent — or empty, which means the same thing — for a top-level call.\n *\n * A sub-agent's question reaches the user through its parent's pending list,\n * so `toolCallId` stops being an address on its own: two sub-runs under two\n * different tools can each hold a call the outer run never made. Binding the\n * path is what stops a token minted for a call nested under tool call X from\n * being replayed as a top-level call, or as one nested under Y.\n */\n path?: string[];\n /**\n * Who the question was asked of: the run's owner (`AgentController.runOwner`,\n * `user:<id>` by default). `null` or absent is nobody in particular — an\n * anonymous run — and the two are the same claim. A token minted for one\n * subject fails verification for any other, `null` included, so an approval\n * cannot be carried from one user's session to another's.\n */\n subject?: string | null;\n};\n\nexport type SignOptions = {\n /** Overrides `process.env.SECRET`. Exists for tests; apps use the app key. */\n secret?: string;\n /**\n * Default 24 hours. An approval waits on a human, and humans go to lunch —\n * a short expiry turns \"I approved it after standup\" into an unexplained\n * failure. Long enough to survive a working day, short enough that a token\n * lifted from a log is not useful next month.\n */\n ttlMs?: number;\n /** Injected clock, so the expiry path is testable without waiting. */\n now?: number;\n};\n\nexport type VerifyOptions = {\n secret?: string;\n now?: number;\n};\n\n/**\n * A discriminated result rather than a boolean, because the two failures are\n * different events: `expired` is a sentence to show the user, `forged` is worth\n * logging and possibly alerting on. Collapsing them loses the only signal that\n * says someone is probing.\n */\nexport type VerifyResult =\n | { ok: true; runId: string; nonce: string; expiresAt: number }\n | { ok: false; reason: \"malformed\" | \"expired\" | \"forged\" };\n\n/**\n * `agt2` is minted; `agt1` is still verified. A v1 token was MACed with the raw\n * `SECRET` and binds no subject — it is accepted so that a question asked\n * before the upgrade can still be answered after it, and it stops mattering on\n * its own when the last one expires (`DEFAULT_TTL_MS` after the deploy). Drop\n * `LEGACY_VERSION` from the accepted set once that window is long past.\n */\nconst VERSION = \"agt2\";\nconst LEGACY_VERSION = \"agt1\";\nconst PENDING_VERSIONS = [VERSION, LEGACY_VERSION];\nconst DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;\n\n/**\n * The latest expiry a legacy token may claim. Every v1 token this process can\n * legitimately see was minted by an earlier deploy with the default TTL, so it\n * expires no later than one TTL after this module loaded. Bounding it here\n * means a v1 token — MACed with the raw `SECRET`, the key this change exists to\n * stop relying on — cannot be forged with a far-future expiry, and that after\n * one TTL of uptime no v1 token verifies at all.\n */\nconst LEGACY_ACCEPTED_UNTIL = Date.now() + DEFAULT_TTL_MS;\n\nfunction legacyExpiryOk(expiresAt: number): boolean {\n return expiresAt <= LEGACY_ACCEPTED_UNTIL;\n}\n\n/**\n * HKDF `info` labels, one per thing a key signs. Changing a label is a key\n * rotation for that purpose alone.\n */\nconst PENDING_CALL_PURPOSE = \"gemi.ai.pending-call.v1\";\nconst NESTED_RUN_PURPOSE = \"gemi.ai.nested-run.v1\";\nconst EXECUTION_RECEIPT_PURPOSE = \"gemi.ai.execution-receipt.v1\";\nconst HKDF_SALT = \"gemi.ai.signing\";\n\nconst derivedKeys = new Map<string, Buffer>();\n\n/**\n * A key for one purpose, derived from the app secret with HKDF-SHA256.\n *\n * `SECRET` is also what CSRF tokens and sessions are keyed with. Using it as\n * the HMAC key here would make every one of those a potential oracle for the\n * others; HKDF with a purpose label gives each its own independent key, so a\n * weakness or leak in one use cannot be turned against another — including\n * the two token kinds in this file against each other.\n *\n * Memoized per (purpose, secret): verification is on the request path and the\n * derivation is pure. The map is bounded by the number of purposes times the\n * secrets a process ever sees, which is one outside of tests.\n */\nexport function purposeKey(purpose: string, override?: string): Buffer {\n const secret = secretKey(override);\n const cacheKey = `${purpose}\\u0000${secret}`;\n let key = derivedKeys.get(cacheKey);\n if (!key) {\n key = Buffer.from(hkdfSync(\"sha256\", secret, HKDF_SALT, purpose, 32));\n if (derivedKeys.size > 64) derivedKeys.clear();\n derivedKeys.set(cacheKey, key);\n }\n return key;\n}\n\nfunction secretKey(override?: string): string {\n const secret = override ?? process.env.SECRET;\n if (!secret) {\n // Refusing is the only safe answer. A fallback constant would make every\n // approval in every deployment forgeable by anyone who read this file, and\n // it would do it silently — the feature would appear to work.\n throw new Error(\n \"Signing a pending tool call needs an app secret. Set SECRET in the environment.\",\n );\n }\n return secret;\n}\n\n/**\n * Serializes a value so that the same value always produces the same string.\n *\n * `JSON.stringify` is not enough: it preserves insertion order, so an input\n * that made a round trip through a client — parsed and re-serialized, with the\n * keys in whatever order the parser produced — would hash differently and a\n * legitimate approval would come back looking forged. Keys are sorted,\n * `undefined` members are dropped (they do not survive JSON anyway), and arrays\n * keep their order because in an array order *is* the value.\n */\nexport function canonicalize(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value) ?? \"null\";\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalize).join(\",\")}]`;\n }\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort();\n return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalize(record[key])}`).join(\",\")}}`;\n}\n\n/**\n * Length-prefixed rather than delimiter-joined. A separator is a place for two\n * different claim sets to hash the same — `runId: \"a\", toolCallId: \"b|c\"` and\n * `runId: \"a|b\", toolCallId: \"c\"` — and while neither field contains the\n * separator today, that is a property of the id generator, not of this code.\n */\nfunction payload(fields: string[]): string {\n return fields.map((field) => `${field.length}:${field}`).join(\"\");\n}\n\nfunction mac(key: string | Buffer, fields: string[]): Buffer {\n return createHmac(\"sha256\", key).update(payload(fields)).digest();\n}\n\nfunction macMatches(signature: string, expected: Buffer): boolean {\n const presented = Buffer.from(signature.split(\".\")[4], \"base64url\");\n // `timingSafeEqual` throws on a length mismatch, and a wrong length is\n // already a public fact about the token — nothing is leaked by checking it\n // first, and everything is leaked by comparing the bytes with `===`.\n return presented.length === expected.length && timingSafeEqual(presented, expected);\n}\n\n/** The principal as a field: absent and `null` are the same claim. */\nfunction subjectField(subject: string | null | undefined): string {\n return canonicalize(subject ?? null);\n}\n\n/**\n * The v2 claim set. Fixed-length: the path is always present (`[]` at the top\n * level) and so is the subject, so there is no optional field to reason about.\n */\nfunction claimFields(claims: PendingCallClaims, nonce: string, expiresAt: number): string[] {\n return [\n VERSION,\n claims.runId,\n claims.toolCallId,\n claims.name,\n claims.kind,\n nonce,\n String(expiresAt),\n canonicalize(claims.input),\n canonicalize(claims.path ?? []),\n subjectField(claims.subject),\n ];\n}\n\n/**\n * The v1 claim set, kept only to verify tokens minted before #447.\n *\n * The path is appended, and only when there is one.\n *\n * Byte-identical output for a call with no path is the whole requirement here:\n * every approval already in flight was minted from the eight fields below, and\n * a ninth field carrying `\"[]\"` or `\"undefined\"` would invalidate all of them\n * on deploy — the user who clicked Approve before the release would be told\n * their answer was forged. So an absent path adds nothing at all, and an empty\n * array is treated as absent because it says the same thing.\n *\n * `payload` is length-prefixed, so appending a field cannot collide with a\n * longer value in the one before it; that is why this can be an append rather\n * than a new version tag.\n */\nfunction legacyClaimFields(claims: PendingCallClaims, nonce: string, expiresAt: number): string[] {\n const fields = [\n LEGACY_VERSION,\n claims.runId,\n claims.toolCallId,\n claims.name,\n claims.kind,\n nonce,\n String(expiresAt),\n canonicalize(claims.input),\n ];\n if (claims.path && claims.path.length > 0) {\n fields.push(canonicalize(claims.path));\n }\n return fields;\n}\n\nconst encode = (value: string) => Buffer.from(value, \"utf8\").toString(\"base64url\");\nconst decode = (value: string) => Buffer.from(value, \"base64url\").toString(\"utf8\");\n\n/** `agt2.<runId>.<nonce>.<expiry>.<mac>`, all base64url or base36. */\nexport function signPendingCall(claims: PendingCallClaims, options: SignOptions = {}): string {\n const key = purposeKey(PENDING_CALL_PURPOSE, options.secret);\n const now = options.now ?? Date.now();\n const expiresAt = now + (options.ttlMs ?? DEFAULT_TTL_MS);\n const nonce = randomBytes(12).toString(\"base64url\");\n const signature = mac(key, claimFields(claims, nonce, expiresAt)).toString(\"base64url\");\n return [VERSION, encode(claims.runId), nonce, expiresAt.toString(36), signature].join(\".\");\n}\n\n/**\n * The metadata a signature carries in the clear.\n *\n * `Agent` needs the issuing `runId` before it can verify anything: the call was\n * signed under the run that made it, and the turn answering it is a *new* run\n * with a new id. Reading it out of the token is safe because the token's own\n * MAC covers it — a client that edits the runId here fails verification, so\n * this is \"which run does this claim to belong to\", not \"which run does the\n * client say it belongs to\".\n */\nexport function readSignature(\n signature: string,\n): { runId: string; nonce: string; expiresAt: number } | null {\n return readToken(signature, PENDING_VERSIONS);\n}\n\n/**\n * The version tag is checked here and nowhere else, which is what keeps the\n * two token kinds apart: a parked-run record presented where a pending call's\n * signature is expected fails as malformed before its MAC is even looked at,\n * and the other way round. Their claim sets are different lengths and would\n * not collide anyway, but a tag makes that a rule rather than an accident of\n * the field count.\n */\nfunction readToken(\n signature: string,\n versions: readonly string[],\n): { runId: string; nonce: string; expiresAt: number; version: string } | null {\n const parts = signature.split(\".\");\n if (parts.length !== 5 || !versions.includes(parts[0])) {\n return null;\n }\n const expiresAt = Number.parseInt(parts[3], 36);\n if (!Number.isFinite(expiresAt)) {\n return null;\n }\n try {\n return { runId: decode(parts[1]), nonce: parts[2], expiresAt, version: parts[0] };\n } catch {\n return null;\n }\n}\n\nexport function verifyPendingCall(\n signature: string,\n claims: PendingCallClaims,\n options: VerifyOptions = {},\n): VerifyResult {\n const parsed = readToken(signature, PENDING_VERSIONS);\n if (!parsed) {\n return { ok: false, reason: \"malformed\" };\n }\n\n if (parsed.version === LEGACY_VERSION && !legacyExpiryOk(parsed.expiresAt)) {\n return { ok: false, reason: \"forged\" };\n }\n const expected =\n parsed.version === LEGACY_VERSION\n ? // Raw secret, no subject: see `LEGACY_VERSION`.\n mac(secretKey(options.secret), legacyClaimFields(claims, parsed.nonce, parsed.expiresAt))\n : mac(\n purposeKey(PENDING_CALL_PURPOSE, options.secret),\n claimFields(claims, parsed.nonce, parsed.expiresAt),\n );\n if (!macMatches(signature, expected)) {\n return { ok: false, reason: \"forged\" };\n }\n\n // Expiry is checked *after* the MAC on purpose: only a genuine token can be\n // \"expired\". Reporting a forgery as expired would tell the UI to say \"your\n // approval timed out\" to someone who was tampering.\n if ((options.now ?? Date.now()) > parsed.expiresAt) {\n return { ok: false, reason: \"expired\" };\n }\n\n return { ok: true, runId: parsed.runId, nonce: parsed.nonce, expiresAt: parsed.expiresAt };\n}\n\n// --- parked sub-runs -----------------------------------------------------\n\n/**\n * What a parked sub-run's record is signed over.\n *\n * `ToolCallPart.nested` is the parent's own record of where a sub-run stopped,\n * and in stateless mode it makes the same trip through the browser a pending\n * call does. The next turn *runs a tool* on the strength of that record — the\n * tool is re-entered because the record says a sub-run under it is waiting on\n * the question being answered — so an unsigned record lets the client choose\n * which tools run, with what input, before any answer is verified. A MAC over\n * what the server actually recorded is what makes the record safe to carry.\n *\n * Only a parked record is signed, because only a parked record executes\n * anything: a finished sub-run is replayed out of its transcript and spends\n * nothing, and a client that forges one has fed its own tool a made-up answer,\n * which a client-carried history already allows everywhere.\n *\n * Deliberately not signed: the transcript. The sub-run resumes from messages\n * the client carried, exactly as the parent does in stateless mode, and the\n * same argument applies — what the signature pins is that the server parked\n * *here*, on *these* calls, with *this* input, and not what was said on the\n * way.\n */\nexport type NestedRunClaims = {\n /** The root run's id, the one every pending call of the tree is minted under. */\n runId: string;\n /**\n * Tool-call ids from the root down to and including the call the record\n * hangs off. A sub-run's id is not an address on its own for the same reason\n * a nested call's is not: two sub-runs under two different tools can carry\n * the same one.\n */\n path: string[];\n /** The sub-run's own id, so a record cannot be moved between sub-runs. */\n nestedRunId: string;\n /** The tool calls the sub-run is waiting on: every call left open in its transcript. */\n open: string[];\n /**\n * The input the tool that parked was running on, as the transcript carries\n * it. Re-entry runs the tool body with the input the history holds, and the\n * history is the client's — so a record that pinned where the sub-run parked\n * but not what its tool was given would let the client keep the run and\n * rewrite the arguments to anything the schema accepts. The same bargain a\n * pending call makes: the input executed is the input signed.\n */\n input: unknown;\n /** The run's owner, as on `PendingCallClaims.subject`: a record parked for\n * one principal does not re-enter a tool for another. */\n subject?: string | null;\n};\n\n/** `agn2` is minted; `agn1` (raw secret, no subject) is still verified. See\n * `LEGACY_VERSION`. */\nconst NESTED_VERSION = \"agn2\";\nconst LEGACY_NESTED_VERSION = \"agn1\";\nconst NESTED_VERSIONS = [NESTED_VERSION, LEGACY_NESTED_VERSION];\n\nfunction nestedFields(claims: NestedRunClaims, nonce: string, expiresAt: number): string[] {\n return [\n ...legacyNestedFields(claims, nonce, expiresAt, NESTED_VERSION),\n subjectField(claims.subject),\n ];\n}\n\nfunction legacyNestedFields(\n claims: NestedRunClaims,\n nonce: string,\n expiresAt: number,\n version = LEGACY_NESTED_VERSION,\n): string[] {\n return [\n version,\n claims.runId,\n canonicalize(claims.path),\n claims.nestedRunId,\n nonce,\n String(expiresAt),\n // A set, so it is sorted: the ids are read back out of a transcript the\n // client re-serialized, and message order is not part of the claim.\n canonicalize([...claims.open].sort()),\n canonicalize(claims.input),\n ];\n}\n\n/**\n * Same shape as a pending call's token, so the same reader serves both — nonce\n * included, and the nonce is spent, by `consumeNestedRun` below. A verified\n * record is permission to run the tool it hangs off, and the tool body runs\n * before the sub-run gets to look at the answer's own nonce; a record that\n * could be presented twice would run the body twice before anything refused\n * the replay. Every park mints a fresh record, so spending one costs a\n * legitimate re-park nothing.\n */\nexport function signNestedRun(claims: NestedRunClaims, options: SignOptions = {}): string {\n const key = purposeKey(NESTED_RUN_PURPOSE, options.secret);\n const now = options.now ?? Date.now();\n const expiresAt = now + (options.ttlMs ?? DEFAULT_TTL_MS);\n const nonce = randomBytes(12).toString(\"base64url\");\n const signature = mac(key, nestedFields(claims, nonce, expiresAt)).toString(\"base64url\");\n return [NESTED_VERSION, encode(claims.runId), nonce, expiresAt.toString(36), signature].join(\".\");\n}\n\n/**\n * The run that verifies a record is never the run that minted it — the turn\n * answering a question is a new run with a new id — so the minting run's id is\n * read out of the token rather than asked of the caller, which has no other\n * source for it. The MAC covers it, so a client that edits the id in the clear\n * fails here rather than being believed.\n */\nexport function verifyNestedRun(\n signature: string,\n claims: Omit<NestedRunClaims, \"runId\">,\n options: VerifyOptions = {},\n): VerifyResult {\n const parsed = readToken(signature, NESTED_VERSIONS);\n if (!parsed) {\n return { ok: false, reason: \"malformed\" };\n }\n\n if (parsed.version === LEGACY_NESTED_VERSION && !legacyExpiryOk(parsed.expiresAt)) {\n return { ok: false, reason: \"forged\" };\n }\n const full = { ...claims, runId: parsed.runId };\n const expected =\n parsed.version === LEGACY_NESTED_VERSION\n ? mac(secretKey(options.secret), legacyNestedFields(full, parsed.nonce, parsed.expiresAt))\n : mac(\n purposeKey(NESTED_RUN_PURPOSE, options.secret),\n nestedFields(full, parsed.nonce, parsed.expiresAt),\n );\n if (!macMatches(signature, expected)) {\n return { ok: false, reason: \"forged\" };\n }\n\n // A parked record outlives its usefulness with the answers it exists to\n // deliver: those expire on the pending call's TTL, and a record older than\n // that can route nothing that would still verify.\n if ((options.now ?? Date.now()) > parsed.expiresAt) {\n return { ok: false, reason: \"expired\" };\n }\n\n return { ok: true, runId: parsed.runId, nonce: parsed.nonce, expiresAt: parsed.expiresAt };\n}\n\n// --- single use ----------------------------------------------------------\n\n/**\n * Spending a nonce.\n *\n * The MAC makes a token unforgeable; it does not make it single-use. Without\n * this a captured signature approves the same call again every time it is\n * presented, because a token that carries its own `runId` is a token that\n * asserts its own binding — which is no binding at all. Verifying tells you the\n * server once asked this exact question; spending the nonce is what says nobody\n * has answered it yet.\n *\n * Where spent nonces live is a `NonceStore` (`store/Nonces.ts`, #445). The\n * default is the process-wide `MemoryNonceStore`, which is exact for one\n * instance; an app with several instances gives the agent a shared store\n * (`RedisNonceStore`, or a table) so a rewound history cannot be replayed once\n * against each of them. The store's `consume` is insert-if-absent, so two\n * instances answering at once cannot both win.\n *\n * The other guard is the app's own message store: once a call has a result\n * next to it, the call is no longer open and the answer has nothing to attach\n * to. This is what stands in for that in stateless mode, where the history the\n * client returns can be rewound to before the result existed.\n */\n\n/**\n * The id an approved call's execution receipt is kept under (#458).\n *\n * Deterministic in the call the signature covers — the issuing run, the tool\n * call id, the tool, its canonical input, the nesting path and the subject —\n * and in nothing else, so every presentation of one approval, on any instance,\n * names the same receipt. Not in the nonce or expiry: those identify one\n * *token*, and a receipt identifies the *execution* it authorizes.\n *\n * An HMAC under its own HKDF-derived key rather than a plain hash, so an id in\n * a shared store is neither a MAC for anything else nor something a client can\n * compute to probe the store for another user's calls.\n */\nexport function executionReceiptId(\n agent: string,\n claims: PendingCallClaims,\n options: { secret?: string } = {},\n): string {\n const key = purposeKey(EXECUTION_RECEIPT_PURPOSE, options.secret);\n return mac(key, [\n agent,\n claims.runId,\n claims.toolCallId,\n claims.name,\n claims.kind,\n canonicalize(claims.input),\n canonicalize(claims.path ?? []),\n subjectField(claims.subject),\n ]).toString(\"base64url\");\n}\n\n/**\n * Spends a signature's nonce in `store`. `false` means it was already spent —\n * the answer is a replay and must not be acted on — or the token is malformed.\n * A store that throws rejects; the caller refuses the answer.\n *\n * Separate from `verifyPendingCall` rather than folded into it, because verify\n * is a pure question a caller may want to ask twice (logging a forgery, say)\n * and this one is a state change that must happen exactly once per answer.\n */\nexport function spendPendingCall(signature: string, store: NonceStore): Promise<boolean> {\n return spendIn(store, readSignature(signature));\n}\n\n/**\n * Spends a parked-run record's nonce, on the same store and the same terms.\n * `false` means the record has already re-entered its tool once — the turn is\n * a replay of a history from before the answer was delivered, and the body\n * must not run again on it.\n */\nexport function spendNestedRun(signature: string, store: NonceStore): Promise<boolean> {\n return spendIn(store, readToken(signature, NESTED_VERSIONS));\n}\n\nasync function spendIn(\n store: NonceStore,\n parsed: { nonce: string; expiresAt: number } | null,\n): Promise<boolean> {\n if (!parsed) return false;\n return store.consume(parsed.nonce, parsed.expiresAt);\n}\n\n/** `spendPendingCall` on the process-wide default store, synchronously.\n * `now` is injectable for tests. */\nexport function consumePendingCall(signature: string, options: VerifyOptions = {}): boolean {\n const parsed = readSignature(signature);\n return parsed\n ? defaultNonceStore.consumeSync(parsed.nonce, parsed.expiresAt, options.now)\n : false;\n}\n\n/** `spendNestedRun` on the process-wide default store, synchronously. */\nexport function consumeNestedRun(signature: string, options: VerifyOptions = {}): boolean {\n const parsed = readToken(signature, NESTED_VERSIONS);\n return parsed\n ? defaultNonceStore.consumeSync(parsed.nonce, parsed.expiresAt, options.now)\n : false;\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "9F5261FBB47F185564756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|