gemi 0.109.0 → 0.111.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/Agent.d.ts +11 -0
- package/dist/ai/Agent.d.ts.map +1 -1
- package/dist/ai/AgentController.d.ts +7 -0
- package/dist/ai/AgentController.d.ts.map +1 -1
- package/dist/ai/index.js +11 -11
- package/dist/ai/index.js.map +4 -4
- package/dist/app/index.js +2 -2
- package/dist/app/index.js.map +1 -1
- package/dist/bin/gemi.js +485 -63
- package/dist/bin/gemi.js.map +12 -8
- package/dist/bun/plugin.js +2 -2
- package/dist/bun/plugin.js.map +1 -1
- package/dist/bun/preload.js +2 -2
- package/dist/bun/preload.js.map +1 -1
- package/dist/{chunk-hgz8sx40.js → chunk-09ypnhjv.js} +3 -3
- package/dist/{chunk-hgz8sx40.js.map → chunk-09ypnhjv.js.map} +1 -1
- package/dist/{chunk-qnq110tw.js → chunk-0d9qsmx2.js} +3 -3
- package/dist/{chunk-qnq110tw.js.map → chunk-0d9qsmx2.js.map} +1 -1
- package/dist/{chunk-m9609t1y.js → chunk-0sjh5v1n.js} +1 -1
- package/dist/{chunk-g5a3ptsa.js → chunk-11fsn5mr.js} +3 -3
- package/dist/{chunk-g5a3ptsa.js.map → chunk-11fsn5mr.js.map} +1 -1
- package/dist/chunk-1bkr5wnt.js +58 -0
- package/dist/chunk-1bkr5wnt.js.map +14 -0
- package/dist/{chunk-whe0x70j.js → chunk-1c1d0e60.js} +3 -3
- package/dist/{chunk-whe0x70j.js.map → chunk-1c1d0e60.js.map} +1 -1
- package/dist/{chunk-rgfzqwpg.js → chunk-1kr25rcg.js} +3 -3
- package/dist/{chunk-rgfzqwpg.js.map → chunk-1kr25rcg.js.map} +1 -1
- package/dist/{chunk-vee4j6ft.js → chunk-1pem26zc.js} +3 -3
- package/dist/{chunk-vee4j6ft.js.map → chunk-1pem26zc.js.map} +1 -1
- package/dist/{chunk-nxxx0m1a.js → chunk-1va15sfq.js} +2 -2
- package/dist/{chunk-nxxx0m1a.js.map → chunk-1va15sfq.js.map} +2 -2
- package/dist/{chunk-wvwee7dn.js → chunk-1yx2e0bh.js} +2 -2
- package/dist/{chunk-wvwee7dn.js.map → chunk-1yx2e0bh.js.map} +1 -1
- package/dist/{chunk-9r3znmqq.js → chunk-303mprnv.js} +2 -2
- package/dist/{chunk-9r3znmqq.js.map → chunk-303mprnv.js.map} +1 -1
- package/dist/{chunk-grs8dnkd.js → chunk-30xjcyzh.js} +2 -2
- package/dist/{chunk-grs8dnkd.js.map → chunk-30xjcyzh.js.map} +1 -1
- package/dist/{chunk-h15eae7g.js → chunk-358sdcx9.js} +3 -3
- package/dist/{chunk-h15eae7g.js.map → chunk-358sdcx9.js.map} +1 -1
- package/dist/{chunk-367kyrdx.js → chunk-3cg7y62b.js} +2 -2
- package/dist/{chunk-367kyrdx.js.map → chunk-3cg7y62b.js.map} +1 -1
- package/dist/{chunk-t26n9vzw.js → chunk-3y8q8x11.js} +2 -2
- package/dist/{chunk-t26n9vzw.js.map → chunk-3y8q8x11.js.map} +1 -1
- package/dist/chunk-4mfrgd5m.js +34 -0
- package/dist/chunk-4mfrgd5m.js.map +10 -0
- package/dist/chunk-5cygrbxv.js +4 -0
- package/dist/{chunk-9qw9fa6z.js.map → chunk-5cygrbxv.js.map} +2 -2
- package/dist/{chunk-tvy2fqza.js → chunk-5stgtwqw.js} +2 -2
- package/dist/{chunk-tvy2fqza.js.map → chunk-5stgtwqw.js.map} +1 -1
- package/dist/chunk-6chz1ktz.js +9 -0
- package/dist/chunk-6chz1ktz.js.map +13 -0
- package/dist/{chunk-wqsdjweb.js → chunk-6vr7f5fq.js} +4 -4
- package/dist/{chunk-wqsdjweb.js.map → chunk-6vr7f5fq.js.map} +1 -1
- package/dist/{chunk-g74qwhvf.js → chunk-7tx5y712.js} +2 -2
- package/dist/{chunk-g74qwhvf.js.map → chunk-7tx5y712.js.map} +1 -1
- package/dist/{chunk-g7fr2cy2.js → chunk-8afxrmdc.js} +3 -3
- package/dist/{chunk-g7fr2cy2.js.map → chunk-8afxrmdc.js.map} +1 -1
- package/dist/{chunk-vwkdfngg.js → chunk-8b2tw2yp.js} +1 -1
- package/dist/{chunk-t3qw9syt.js → chunk-9rchedr4.js} +2 -2
- package/dist/{chunk-t3qw9syt.js.map → chunk-9rchedr4.js.map} +1 -1
- package/dist/{chunk-jm4jn28j.js → chunk-9s851qz8.js} +2 -2
- package/dist/{chunk-jm4jn28j.js.map → chunk-9s851qz8.js.map} +1 -1
- package/dist/{chunk-jc4j61xb.js → chunk-a6453d9s.js} +3 -3
- package/dist/{chunk-jc4j61xb.js.map → chunk-a6453d9s.js.map} +1 -1
- package/dist/{chunk-9m18pknp.js → chunk-bn5yn731.js} +2 -2
- package/dist/{chunk-9m18pknp.js.map → chunk-bn5yn731.js.map} +1 -1
- package/dist/{chunk-t85rca2p.js → chunk-c098fzvk.js} +2 -2
- package/dist/{chunk-t85rca2p.js.map → chunk-c098fzvk.js.map} +1 -1
- package/dist/{chunk-mp5krm14.js → chunk-cttmy1jp.js} +4 -4
- package/dist/{chunk-mp5krm14.js.map → chunk-cttmy1jp.js.map} +2 -2
- package/dist/{chunk-eyg88bgv.js → chunk-cy5qp6mz.js} +3 -3
- package/dist/{chunk-eyg88bgv.js.map → chunk-cy5qp6mz.js.map} +1 -1
- package/dist/{chunk-zys7kecf.js → chunk-ddr4qvvt.js} +3 -3
- package/dist/{chunk-zys7kecf.js.map → chunk-ddr4qvvt.js.map} +1 -1
- package/dist/{chunk-r9gzbjc5.js → chunk-et4pv1b1.js} +1 -1
- package/dist/{chunk-a1g0bahx.js → chunk-frerzsxq.js} +2 -2
- package/dist/{chunk-a1g0bahx.js.map → chunk-frerzsxq.js.map} +1 -1
- package/dist/{chunk-qz9aaw5x.js → chunk-gb37722w.js} +3 -3
- package/dist/{chunk-qz9aaw5x.js.map → chunk-gb37722w.js.map} +1 -1
- package/dist/chunk-h3864a8z.js +17 -0
- package/dist/{chunk-s5aa4hty.js.map → chunk-h3864a8z.js.map} +13 -12
- package/dist/{chunk-zhm3qvrc.js → chunk-h4sw6nt3.js} +3 -3
- package/dist/{chunk-zhm3qvrc.js.map → chunk-h4sw6nt3.js.map} +1 -1
- package/dist/{chunk-5d6eaxab.js → chunk-he7z7y9j.js} +2 -2
- package/dist/{chunk-5d6eaxab.js.map → chunk-he7z7y9j.js.map} +1 -1
- package/dist/{chunk-d2tngs73.js → chunk-hf7a51s3.js} +2 -2
- package/dist/{chunk-d2tngs73.js.map → chunk-hf7a51s3.js.map} +1 -1
- package/dist/chunk-hn67spz6.js +5 -0
- package/dist/{chunk-z9x8x3wq.js.map → chunk-hn67spz6.js.map} +1 -1
- package/dist/{chunk-f7jhkg8x.js → chunk-jbrwt3cs.js} +4 -4
- package/dist/{chunk-f7jhkg8x.js.map → chunk-jbrwt3cs.js.map} +1 -1
- package/dist/{chunk-k1ezptt8.js → chunk-k1vw22t2.js} +2 -2
- package/dist/{chunk-k1ezptt8.js.map → chunk-k1vw22t2.js.map} +1 -1
- package/dist/chunk-k1xt2tw7.js +4 -0
- package/dist/{chunk-rjcsdazt.js.map → chunk-k1xt2tw7.js.map} +2 -2
- package/dist/{chunk-7mc5e61r.js → chunk-kf71mjxa.js} +3 -3
- package/dist/{chunk-7mc5e61r.js.map → chunk-kf71mjxa.js.map} +1 -1
- package/dist/{chunk-vna85rdq.js → chunk-m6ystvtk.js} +2 -2
- package/dist/{chunk-vna85rdq.js.map → chunk-m6ystvtk.js.map} +1 -1
- package/dist/{chunk-qyyxzy04.js → chunk-mb7q7s0a.js} +3 -3
- package/dist/{chunk-qyyxzy04.js.map → chunk-mb7q7s0a.js.map} +1 -1
- package/dist/{chunk-sp2v357a.js → chunk-mn5xw79b.js} +3 -3
- package/dist/{chunk-sp2v357a.js.map → chunk-mn5xw79b.js.map} +1 -1
- package/dist/{chunk-q8k7f11z.js → chunk-mwqg079k.js} +2 -2
- package/dist/{chunk-q8k7f11z.js.map → chunk-mwqg079k.js.map} +1 -1
- package/dist/{chunk-ga533cpz.js → chunk-nncz308h.js} +3 -3
- package/dist/{chunk-ga533cpz.js.map → chunk-nncz308h.js.map} +1 -1
- package/dist/{chunk-hf32yq23.js → chunk-nsvktvp4.js} +2 -2
- package/dist/{chunk-hf32yq23.js.map → chunk-nsvktvp4.js.map} +1 -1
- package/dist/{chunk-3x86bhfn.js → chunk-nvv9wej6.js} +3 -3
- package/dist/{chunk-3x86bhfn.js.map → chunk-nvv9wej6.js.map} +1 -1
- package/dist/chunk-p1aqq0ga.js +16 -0
- package/dist/{chunk-d5sbnzng.js.map → chunk-p1aqq0ga.js.map} +5 -9
- package/dist/chunk-p7r2w4qw.js +5 -0
- package/dist/{chunk-ehasw3qm.js.map → chunk-p7r2w4qw.js.map} +2 -2
- package/dist/{chunk-zz7h6tdr.js → chunk-pwmgqq7z.js} +2 -2
- package/dist/{chunk-zz7h6tdr.js.map → chunk-pwmgqq7z.js.map} +1 -1
- package/dist/chunk-pyj7cd9t.js +4 -0
- package/dist/{chunk-gdsby5jh.js.map → chunk-pyj7cd9t.js.map} +2 -2
- package/dist/{chunk-h6g9g8qc.js → chunk-q9s7kwgt.js} +3 -3
- package/dist/{chunk-h6g9g8qc.js.map → chunk-q9s7kwgt.js.map} +1 -1
- package/dist/{chunk-9hbwvcxn.js → chunk-qd2v93y4.js} +2 -2
- package/dist/{chunk-9hbwvcxn.js.map → chunk-qd2v93y4.js.map} +1 -1
- package/dist/{chunk-tr9mxdth.js → chunk-rfcygmf5.js} +3 -3
- package/dist/{chunk-tr9mxdth.js.map → chunk-rfcygmf5.js.map} +1 -1
- package/dist/{chunk-vsnmdtrs.js → chunk-s6jjy4y9.js} +2 -2
- package/dist/{chunk-vsnmdtrs.js.map → chunk-s6jjy4y9.js.map} +1 -1
- package/dist/{chunk-6zekebzt.js → chunk-sq2wkynk.js} +2 -2
- package/dist/{chunk-6zekebzt.js.map → chunk-sq2wkynk.js.map} +1 -1
- package/dist/{chunk-52vsdnny.js → chunk-td8tha3j.js} +3 -3
- package/dist/{chunk-52vsdnny.js.map → chunk-td8tha3j.js.map} +1 -1
- package/dist/chunk-tdsfke9q.js +6 -0
- package/dist/{chunk-fe1pcnw6.js.map → chunk-tdsfke9q.js.map} +5 -4
- package/dist/{chunk-t0bp8nrc.js → chunk-tk5q8hkv.js} +4 -4
- package/dist/{chunk-t0bp8nrc.js.map → chunk-tk5q8hkv.js.map} +2 -2
- package/dist/{chunk-dpy08xw4.js → chunk-tq85n8zh.js} +2 -2
- package/dist/{chunk-dpy08xw4.js.map → chunk-tq85n8zh.js.map} +1 -1
- package/dist/{chunk-wdpdqjr1.js → chunk-twnn7r66.js} +2 -2
- package/dist/{chunk-wdpdqjr1.js.map → chunk-twnn7r66.js.map} +1 -1
- package/dist/chunk-w7jsh3xd.js +5 -0
- package/dist/{chunk-1es50p4k.js.map → chunk-w7jsh3xd.js.map} +2 -2
- package/dist/chunk-wqvvjd5r.js +24 -0
- package/dist/{chunk-w3j53r0a.js.map → chunk-wqvvjd5r.js.map} +4 -4
- package/dist/{chunk-zh1t33nq.js → chunk-wsttx9rg.js} +2 -2
- package/dist/{chunk-zh1t33nq.js.map → chunk-wsttx9rg.js.map} +1 -1
- package/dist/{chunk-7ssjzp87.js → chunk-wvsv1jgg.js} +2 -2
- package/dist/{chunk-7ssjzp87.js.map → chunk-wvsv1jgg.js.map} +1 -1
- package/dist/chunk-x78jrs4y.js +4 -0
- package/dist/{chunk-y66ntxbg.js.map → chunk-x78jrs4y.js.map} +2 -2
- package/dist/chunk-xk930yaw.js +5 -0
- package/dist/{chunk-pa3khk46.js.map → chunk-xk930yaw.js.map} +2 -2
- package/dist/chunk-xkc7ftnq.js +9 -0
- package/dist/chunk-xkc7ftnq.js.map +10 -0
- package/dist/{chunk-564zfdd1.js → chunk-yer1r3t3.js} +2 -2
- package/dist/{chunk-564zfdd1.js.map → chunk-yer1r3t3.js.map} +1 -1
- package/dist/{chunk-c8dhvdrs.js → chunk-yqavgpwd.js} +3 -3
- package/dist/{chunk-c8dhvdrs.js.map → chunk-yqavgpwd.js.map} +1 -1
- package/dist/{chunk-hyfzw1fk.js → chunk-z10cas5r.js} +2 -2
- package/dist/{chunk-hyfzw1fk.js.map → chunk-z10cas5r.js.map} +1 -1
- package/dist/{chunk-jgtean4t.js → chunk-zhs1r1z0.js} +3 -3
- package/dist/{chunk-jgtean4t.js.map → chunk-zhs1r1z0.js.map} +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +106 -52
- package/dist/client/index.js.map +1 -1
- package/dist/client/islands.d.ts +99 -56
- package/dist/client/islands.d.ts.map +1 -1
- package/dist/config/index.d.ts +8 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +2 -2
- 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/Lang.d.ts +7 -1
- package/dist/facades/Lang.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/CorsMiddleware.d.ts +13 -0
- package/dist/http/CorsMiddleware.d.ts.map +1 -1
- package/dist/http/Middleware.d.ts +11 -0
- package/dist/http/Middleware.d.ts.map +1 -1
- package/dist/http/ViewRouter.d.ts +29 -0
- package/dist/http/ViewRouter.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/internal/islandRuntime.d.ts +45 -0
- package/dist/internal/islandRuntime.d.ts.map +1 -0
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/orm/context.d.ts +24 -0
- package/dist/orm/context.d.ts.map +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +3 -3
- package/dist/orm/index.js.map +2 -2
- package/dist/server/devFetch.d.ts.map +1 -1
- package/dist/server/httpDev.d.ts.map +1 -1
- package/dist/server/httpProd.d.ts.map +1 -1
- package/dist/server/idleTimeout.d.ts +24 -0
- package/dist/server/idleTimeout.d.ts.map +1 -0
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/modulePreloads.d.ts +7 -6
- package/dist/server/modulePreloads.d.ts.map +1 -1
- package/dist/services/index.js +2 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/middleware/MiddlewareRegistry.d.ts +13 -2
- package/dist/services/middleware/MiddlewareRegistry.d.ts.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/services/router/DomainRouter.d.ts +10 -0
- package/dist/services/router/DomainRouter.d.ts.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/staticCache.d.ts +23 -0
- package/dist/services/router/staticCache.d.ts.map +1 -0
- package/dist/services/router/staticDocument.d.ts +39 -17
- package/dist/services/router/staticDocument.d.ts.map +1 -1
- package/dist/stats/bundleStats.d.ts +104 -0
- package/dist/stats/bundleStats.d.ts.map +1 -0
- package/dist/stats/route-table.d.ts +2 -0
- package/dist/stats/route-table.d.ts.map +1 -0
- package/dist/stats/route-table.js +4 -0
- package/dist/stats/route-table.js.map +11 -0
- package/dist/stats/routeTable.d.ts +25 -0
- package/dist/stats/routeTable.d.ts.map +1 -0
- package/dist/stats/run.d.ts +43 -0
- package/dist/stats/run.d.ts.map +1 -0
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vite/index.mjs +125 -23
- package/dist/vitest/index.d.ts +18 -0
- package/dist/vitest/index.d.ts.map +1 -1
- package/dist/vitest/index.js +2 -2
- package/dist/vitest/index.js.map +3 -3
- package/package.json +2 -1
- package/dist/chunk-1es50p4k.js +0 -5
- package/dist/chunk-9qw9fa6z.js +0 -4
- package/dist/chunk-d5sbnzng.js +0 -18
- package/dist/chunk-ehasw3qm.js +0 -5
- package/dist/chunk-fe1pcnw6.js +0 -6
- package/dist/chunk-fj6yftm7.js +0 -58
- package/dist/chunk-fj6yftm7.js.map +0 -14
- package/dist/chunk-gdsby5jh.js +0 -4
- package/dist/chunk-ngw4xzrt.js +0 -9
- package/dist/chunk-ngw4xzrt.js.map +0 -10
- package/dist/chunk-pa3khk46.js +0 -5
- package/dist/chunk-rjcsdazt.js +0 -4
- package/dist/chunk-s5aa4hty.js +0 -17
- package/dist/chunk-w3j53r0a.js +0 -24
- package/dist/chunk-y66ntxbg.js +0 -4
- package/dist/chunk-z9x8x3wq.js +0 -5
- /package/dist/{chunk-m9609t1y.js.map → chunk-0sjh5v1n.js.map} +0 -0
- /package/dist/{chunk-vwkdfngg.js.map → chunk-8b2tw2yp.js.map} +0 -0
- /package/dist/{chunk-r9gzbjc5.js.map → chunk-et4pv1b1.js.map} +0 -0
|
@@ -70,7 +70,9 @@ export declare class ViewRouteDispatcher {
|
|
|
70
70
|
* a route inside a gated section cannot be more reachable than the section.
|
|
71
71
|
*/
|
|
72
72
|
private passesFeatureGates;
|
|
73
|
-
onRequestEnd(req: HttpRequest
|
|
73
|
+
onRequestEnd(req: HttpRequest, options?: {
|
|
74
|
+
mintSession?: boolean;
|
|
75
|
+
}): Promise<void>;
|
|
74
76
|
/**
|
|
75
77
|
* Fires the provider's `onStreamComplete` from a stream callback — an
|
|
76
78
|
* observability hook must never break the response body it observes, so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewRouteDispatcher.d.ts","sourceRoot":"","sources":["../../../services/router/ViewRouteDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,KAAK,cAAc,EAAmC,MAAM,2BAA2B,CAAC;AAEjG,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAUzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAyBxD,OAAO,
|
|
1
|
+
{"version":3,"file":"ViewRouteDispatcher.d.ts","sourceRoot":"","sources":["../../../services/router/ViewRouteDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { StaticViewOptions } from "../../http/ViewRouter";
|
|
2
|
+
/**
|
|
3
|
+
* Which of the cookies gemi sets on its own a view request gets.
|
|
4
|
+
*
|
|
5
|
+
* A hydrated view gets all three. A static view (`.static()`) gets none unless
|
|
6
|
+
* it asked: it is one body for every visitor, and a per-visitor `Set-Cookie`
|
|
7
|
+
* is what keeps a CDN from caching it. `i18n-locale` has no opt-in — the url
|
|
8
|
+
* carries a static page's locale.
|
|
9
|
+
*/
|
|
10
|
+
export declare function staticCookiePolicy(staticView: StaticViewOptions | undefined): {
|
|
11
|
+
locale: boolean;
|
|
12
|
+
session: boolean;
|
|
13
|
+
csrf: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Sets a static page's `Cache-Control` from `.static({ cacheControl })`.
|
|
17
|
+
*
|
|
18
|
+
* The handler's own header wins. A response that sets a cookie is never handed
|
|
19
|
+
* to a shared cache, whatever the option says: one visitor's cookie stored with
|
|
20
|
+
* the page would be replayed to everyone who gets that copy.
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyStaticCacheControl(headers: Headers, staticView: StaticViewOptions): void;
|
|
23
|
+
//# sourceMappingURL=staticCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staticCache.d.ts","sourceRoot":"","sources":["../../../services/router/staticCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,SAAS;;;;EAS3E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,QAatF"}
|
|
@@ -1,44 +1,66 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type StaticRenderCollector } from "../../client/islands";
|
|
2
2
|
/**
|
|
3
|
-
* Where an island's
|
|
4
|
-
*
|
|
3
|
+
* Where an island's entry is served from: `src` is imported by the loader,
|
|
4
|
+
* `preload` is every chunk that import pulls in (itself first), React
|
|
5
|
+
* included.
|
|
5
6
|
*/
|
|
6
7
|
export type IslandAsset = {
|
|
7
8
|
src: string;
|
|
8
9
|
preload: string[];
|
|
9
10
|
};
|
|
10
|
-
/** Maps an island module's build key (`app/views/site/
|
|
11
|
+
/** Maps an island module's build key (`app/views/site/Counter.tsx`) to its entry. */
|
|
11
12
|
export type IslandResolver = (moduleKey: string) => IslandAsset | undefined;
|
|
12
13
|
/** The id of the JSON block the loader reads its island table from. */
|
|
13
14
|
export declare const ISLAND_DATA_ID = "gemi-islands";
|
|
14
15
|
/**
|
|
15
16
|
* The island loader, inlined into a static document that uses islands.
|
|
16
17
|
*
|
|
17
|
-
* Kept byte-for-byte constant
|
|
18
|
+
* Kept byte-for-byte constant (the per-page island table travels in a
|
|
18
19
|
* separate `<script type="application/json">`, which a Content Security Policy
|
|
19
|
-
* does not treat as script
|
|
20
|
-
* `script-src 'sha256-…'` with `ISLAND_LOADER_CSP_HASH`.
|
|
21
|
-
*
|
|
20
|
+
* does not treat as script), so a strict policy can allow it by hash:
|
|
21
|
+
* `script-src 'sha256-…'` with `ISLAND_LOADER_CSP_HASH`. Everything it loads
|
|
22
|
+
* is a plain `import()` of a same-origin (or asset-base) file.
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* The table is `{ i: [{ s: entry URL, e: export, l: load }] }` and each
|
|
25
|
+
* marker's `data-island` indexes `i`. Per marker, on its schedule: import the
|
|
26
|
+
* island's entry (the module as `m`, the runtime's `h`), then
|
|
27
|
+
* `h(marker, m[export])`, which calls `hydrateRoot`. A failure is logged and
|
|
28
|
+
* leaves the server-rendered markup in place.
|
|
26
29
|
*/
|
|
27
30
|
export declare const ISLAND_LOADER_SOURCE: string;
|
|
28
31
|
/**
|
|
29
32
|
* `'sha256-…'` for the production island loader, ready to put in a
|
|
30
33
|
* `script-src` directive. The dev loader also installs the React Refresh
|
|
31
|
-
* preamble first, so it does not match; a dev policy
|
|
32
|
-
* as Vite itself does.
|
|
34
|
+
* preamble and Vite's HMR client first, so it does not match; a dev policy
|
|
35
|
+
* needs `'unsafe-inline'` as Vite itself does.
|
|
33
36
|
*/
|
|
34
37
|
export declare const ISLAND_LOADER_CSP_HASH: string;
|
|
35
38
|
/**
|
|
36
|
-
* Adds the island loader to a settled static document
|
|
39
|
+
* Adds the island loader to a settled static document, only when the render
|
|
37
40
|
* recorded an island, so a page without one keeps no script at all.
|
|
38
41
|
*
|
|
39
|
-
* Eager islands get `modulepreload`s in the head for their whole
|
|
40
|
-
* closure; lazy ones are fetched when their
|
|
41
|
-
* them is announced up front.
|
|
42
|
+
* Eager islands get `modulepreload`s in the head for their entry's whole
|
|
43
|
+
* static import closure (React included); lazy ones are fetched when their
|
|
44
|
+
* schedule fires, so nothing about them is announced up front.
|
|
45
|
+
*
|
|
46
|
+
* Without a resolver (a test rendering through `app.fetch`), the markup is
|
|
47
|
+
* the whole result: nothing is injected and nothing is logged.
|
|
42
48
|
*/
|
|
43
49
|
export declare function injectIslands(html: string, collector: StaticRenderCollector, resolveIsland: IslandResolver | undefined, dev: boolean): string;
|
|
50
|
+
/**
|
|
51
|
+
* Moves each island's children into its slot.
|
|
52
|
+
*
|
|
53
|
+
* An island's own render (a root of its own) leaves an empty
|
|
54
|
+
* `<gemi-slot data-slot="i0-">`; the page tree renders the children, with the
|
|
55
|
+
* page's context, right after the marker in `<template data-gemi-slot="i0-">`.
|
|
56
|
+
* Here the template's content replaces the placeholder (as
|
|
57
|
+
* `<gemi-slot style="display:contents">…</gemi-slot>`, what the browser
|
|
58
|
+
* hydrates against) and the template goes away.
|
|
59
|
+
*
|
|
60
|
+
* The last template is spliced first: nothing after it can be inside it, so it
|
|
61
|
+
* holds no other island's children, and an island's children that contain
|
|
62
|
+
* islands are spliced after theirs are. Children the island didn't render are
|
|
63
|
+
* dropped, as a component that ignores `children` drops them anywhere.
|
|
64
|
+
*/
|
|
65
|
+
export declare function spliceIslandSlots(html: string): string;
|
|
44
66
|
//# sourceMappingURL=staticDocument.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staticDocument.d.ts","sourceRoot":"","sources":["../../../services/router/staticDocument.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"staticDocument.d.ts","sourceRoot":"","sources":["../../../services/router/staticDocument.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAG9B;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE7D,qFAAqF;AACrF,MAAM,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;AAE5E,uEAAuE;AACvE,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,QAM8G,CAAC;AAEhJ;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAEb,CAAC;AA0BvB;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,aAAa,EAAE,cAAc,GAAG,SAAS,EACzC,GAAG,EAAE,OAAO,GACX,MAAM,CAiCR;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBtD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { type ViteManifest } from "../server/modulePreloads";
|
|
2
|
+
import type { RouteTableEntry } from "./routeTable";
|
|
3
|
+
/**
|
|
4
|
+
* `gemi stats`: the JavaScript each route loads before it can run, from the
|
|
5
|
+
* client build's manifest.
|
|
6
|
+
*
|
|
7
|
+
* A **hydrated** route loads the client entry and every view in its chain
|
|
8
|
+
* (layouts and page), each with its static imports followed transitively: the
|
|
9
|
+
* same walk the server does for the route's `modulepreload` links. Lazy chunks
|
|
10
|
+
* (`import()`) aren't initial and don't count.
|
|
11
|
+
*
|
|
12
|
+
* A **static** route (`.static()`) loads no client entry and no view code, only
|
|
13
|
+
* the islands its views can render. Each island has a client entry of its own,
|
|
14
|
+
* keyed `<module>?gemi-island` in the manifest, that imports the chunk holding
|
|
15
|
+
* the island's module and the island runtime (React, `react-dom/client`). A
|
|
16
|
+
* route can render an island when the chunk holding its module is reachable
|
|
17
|
+
* from the route's views (and the document layout) through static or lazy
|
|
18
|
+
* imports; the route then counts that island entry with its static imports. A
|
|
19
|
+
* page loads only the islands it shows, so this is its most. Chunks the islands
|
|
20
|
+
* share (the runtime, React) count once per route. The island loader is inline
|
|
21
|
+
* in the HTML and not counted.
|
|
22
|
+
*
|
|
23
|
+
* Sizes are raw, gzip -9 and brotli q11, the encodings `gemi build` writes
|
|
24
|
+
* next to each asset; those files are read when present.
|
|
25
|
+
*/
|
|
26
|
+
export type Size = {
|
|
27
|
+
raw: number;
|
|
28
|
+
gzip: number;
|
|
29
|
+
brotli: number;
|
|
30
|
+
};
|
|
31
|
+
export type SizeUnit = keyof Size;
|
|
32
|
+
export interface RouteStats extends Size {
|
|
33
|
+
/** View paths that render the route, outermost layout first. */
|
|
34
|
+
views: string[];
|
|
35
|
+
/** Set for a `.static()` route. */
|
|
36
|
+
static?: true;
|
|
37
|
+
/** A static route's island entries (manifest keys, `<module>?gemi-island`). */
|
|
38
|
+
islands?: string[];
|
|
39
|
+
/** The JS chunks counted, by name without the content hash. */
|
|
40
|
+
chunks: string[];
|
|
41
|
+
}
|
|
42
|
+
export interface BuildStats {
|
|
43
|
+
/** The JSON shape, bumped when it changes incompatibly. */
|
|
44
|
+
version: 1;
|
|
45
|
+
/**
|
|
46
|
+
* `routes`: keyed by route path (`/p/:slug`; `<group>:/path` for a host group
|
|
47
|
+
* other than the root). `views`: the route table could not be read, so each
|
|
48
|
+
* view is reported as a hydrated page, keyed by view path.
|
|
49
|
+
*/
|
|
50
|
+
by: "routes" | "views";
|
|
51
|
+
routes: Record<string, RouteStats>;
|
|
52
|
+
/** Each island entry (`<module>?gemi-island`) with its static imports. */
|
|
53
|
+
islands: Record<string, Size & {
|
|
54
|
+
chunks: string[];
|
|
55
|
+
}>;
|
|
56
|
+
/** Every JS chunk in the build, by name without the content hash. */
|
|
57
|
+
chunks: Record<string, Size>;
|
|
58
|
+
/** All CSS in the build. */
|
|
59
|
+
css: Size;
|
|
60
|
+
}
|
|
61
|
+
/** `stats` in `gemi.config.ts`. */
|
|
62
|
+
export interface StatsConfig {
|
|
63
|
+
budgets?: StatsBudgets;
|
|
64
|
+
}
|
|
65
|
+
/** Initial-JS budgets in KB (1024 bytes). `gemi stats` fails when a route is over its. */
|
|
66
|
+
export interface StatsBudgets {
|
|
67
|
+
/** Which size the budgets are in. Default `gzip`. */
|
|
68
|
+
unit?: SizeUnit;
|
|
69
|
+
/** Applies to every route without its own budget. Unset: only listed routes are checked. */
|
|
70
|
+
default?: number;
|
|
71
|
+
/** By route path (`/p/:slug`) or by view path (`site/Page`, the route's page view). */
|
|
72
|
+
routes?: Record<string, number>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A chunk by its name without the content hash, so the same chunk compares
|
|
76
|
+
* across builds: `assets/PageBuilder-C4f9a1Xz.js` is `PageBuilder.js`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function chunkName(file: string): string;
|
|
79
|
+
/** The route key in `BuildStats.routes`: the path, prefixed by a non-root host group. */
|
|
80
|
+
export declare function routeKey(entry: Pick<RouteTableEntry, "group" | "path">): string;
|
|
81
|
+
export interface BundleStatsOptions {
|
|
82
|
+
/** The client build, `dist/client`. */
|
|
83
|
+
clientDir: string;
|
|
84
|
+
/** The route table; without it every view is reported as a hydrated page. */
|
|
85
|
+
routes?: RouteTableEntry[] | null;
|
|
86
|
+
/** The manifest, if already read; otherwise `<clientDir>/.vite/manifest.json`. */
|
|
87
|
+
manifest?: ViteManifest;
|
|
88
|
+
}
|
|
89
|
+
export declare function bundleStats(options: BundleStatsOptions): BuildStats;
|
|
90
|
+
/** The budget that applies to a route: its own, its page view's, or the default. */
|
|
91
|
+
export declare function budgetFor(key: string, route: Pick<RouteStats, "views">, budgets: StatsBudgets | undefined): number | undefined;
|
|
92
|
+
/** The routes over their budget, as messages. */
|
|
93
|
+
export declare function overBudget(stats: BuildStats, budgets: StatsBudgets | undefined): string[];
|
|
94
|
+
/** Budget keys that match no route and no route's page view: probably a typo or a removed view. */
|
|
95
|
+
export declare function unusedBudgets(stats: BuildStats, budgets: StatsBudgets | undefined): string[];
|
|
96
|
+
/**
|
|
97
|
+
* The stats as a Markdown table, compared with `base` (another build's JSON,
|
|
98
|
+
* e.g. `main`'s) when given: per-route deltas, then the chunks that came, went
|
|
99
|
+
* or changed. Meant for a PR comment.
|
|
100
|
+
*/
|
|
101
|
+
export declare function markdownReport(stats: BuildStats, base: BuildStats | null, budgets: StatsBudgets | undefined): string;
|
|
102
|
+
/** The stats as a plain-text table for the terminal, largest route first. */
|
|
103
|
+
export declare function textReport(stats: BuildStats, budgets: StatsBudgets | undefined): string;
|
|
104
|
+
//# sourceMappingURL=bundleStats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundleStats.d.ts","sourceRoot":"","sources":["../../stats/bundleStats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-table.d.ts","sourceRoot":"","sources":["../../stats/route-table.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import"../chunk-1yx2e0bh.js";import M from"path";import{writeFileSync as Q}from"fs";var L=new Set(["FILE","REDIRECT"]);function H(j){return j.run(()=>{let x=[];for(let{group:z,view:D}of j.domains().viewGroups())for(let[G,B]of Object.entries(D.flatViewRoutes)){let C=D.routeManifest[G]??B.segments.map((K)=>K.viewPath);if(C.length===0||L.has(C.at(-1)))continue;x.push({path:G,group:z,views:C,...B.static?{static:B.static.layout?{layout:B.static.layout}:{}}:{}})}return x})}var J=process.argv[2];async function U(){if(!J)throw Error("usage: route-table <out.json>");let j=M.resolve(process.cwd(),"app/kernel/Kernel.ts"),x=await import(j);if(typeof x.default!=="function")throw Error(`${j} has no default export (the Kernel subclass).`);let z=new x.default;z.boot();try{Q(J,JSON.stringify(H(z)))}finally{z.destroy()}}U().then(()=>process.exit(0),(j)=>{console.error(j?.stack??String(j)),process.exit(1)});
|
|
3
|
+
|
|
4
|
+
//# debugId=2C354352EBF6475164756E2164756E21
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../stats/route-table.ts", "../stats/routeTable.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * The entry `gemi stats` (and `gemi build --stats`) spawns to read the app's\n * route table: `bun --preload gemi/bun/preload stats/route-table.ts <out>`.\n *\n * `gemi build` deliberately never boots the app (see `bin/createRollupInput`).\n * This doesn't either, in the sense that matters: it imports the Kernel and\n * runs only its synchronous `boot()`, which registers providers and constructs\n * nothing that does I/O. No provider `boot()`, no service, no database, no\n * queue claiming and no scheduler. Importing the app's route files is the one\n * side effect, the same one `gemi app:route-manifest` has.\n *\n * Exposed as `gemi/stats/route-table` and resolved from the application's\n * `node_modules`, like `gemi/console/run`: the routers the app's files extend\n * are the app's copy of gemi, so the code reading them has to be as well.\n *\n * The table is written to the file named by the first argument rather than to\n * stdout, which app code is free to log to while it is imported.\n */\nimport path from \"node:path\";\nimport { writeFileSync } from \"node:fs\";\nimport type { Kernel } from \"../kernel/Kernel\";\nimport { collectRouteTable } from \"./routeTable\";\n\nconst out = process.argv[2];\n\nasync function main() {\n if (!out) throw new Error(\"usage: route-table <out.json>\");\n const kernelPath = path.resolve(process.cwd(), \"app/kernel/Kernel.ts\");\n const module: { default?: new () => Kernel } = await import(kernelPath);\n if (typeof module.default !== \"function\") {\n throw new Error(`${kernelPath} has no default export (the Kernel subclass).`);\n }\n const kernel = new module.default();\n kernel.boot();\n try {\n writeFileSync(out, JSON.stringify(collectRouteTable(kernel)));\n } finally {\n kernel.destroy();\n }\n}\n\n// `.then` rather than a top-level `await`; see `console/run.ts`.\nmain().then(\n () => process.exit(0),\n (error) => {\n console.error((error as Error)?.stack ?? String(error));\n process.exit(1);\n },\n);\n",
|
|
6
|
+
"import type { Kernel } from \"../kernel/Kernel\";\n\n/**\n * One document route, as `gemi stats` needs it: which views render it (layouts\n * first, the page last) and whether it is a `.static()` view.\n */\nexport interface RouteTableEntry {\n /** The route pattern, e.g. `/p/:slug`. */\n path: string;\n /** The host group: `\"\"` for the root, a subdomain, `\"*\"` for the custom fallback. */\n group: string;\n /** View paths (`app/views/<path>.tsx`), outermost layout first. */\n views: string[];\n /** Set for a `.static()` route; `layout` is its document layout, if any. */\n static?: { layout?: string };\n}\n\n/** View paths that name no component: file and redirect routes. */\nconst NOT_A_VIEW = new Set([\"FILE\", \"REDIRECT\"]);\n\n/**\n * Every document route the app declares, from a kernel that has only run its\n * synchronous `boot()`: providers have registered, nothing has booted, so no\n * database, queue, scheduler or listener is touched. Reading the routers only\n * constructs them, which is what `app:route-manifest` has always done.\n */\nexport function collectRouteTable(kernel: Kernel): RouteTableEntry[] {\n return kernel.run(() => {\n const entries: RouteTableEntry[] = [];\n for (const { group, view } of kernel.domains().viewGroups()) {\n for (const [path, route] of Object.entries(view.flatViewRoutes)) {\n const views = view.routeManifest[path] ?? route.segments.map((s) => s.viewPath);\n if (views.length === 0 || NOT_A_VIEW.has(views.at(-1)!)) continue;\n entries.push({\n path,\n group,\n views,\n ...(route.static\n ? { static: route.static.layout ? { layout: route.static.layout } : {} }\n : {}),\n });\n }\n }\n return entries;\n });\n}\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": ";6BAkBA,oBACA,wBAAS,WCDT,IAAM,EAAa,IAAI,IAAI,CAAC,OAAQ,UAAU,CAAC,EAQxC,SAAS,CAAiB,CAAC,EAAmC,CACnE,OAAO,EAAO,IAAI,IAAM,CACtB,IAAM,EAA6B,CAAC,EACpC,QAAa,QAAO,UAAU,EAAO,QAAQ,EAAE,WAAW,EACxD,QAAY,EAAM,KAAU,OAAO,QAAQ,EAAK,cAAc,EAAG,CAC/D,IAAM,EAAQ,EAAK,cAAc,IAAS,EAAM,SAAS,IAAI,CAAC,IAAM,EAAE,QAAQ,EAC9E,GAAI,EAAM,SAAW,GAAK,EAAW,IAAI,EAAM,GAAG,EAAE,CAAE,EAAG,SACzD,EAAQ,KAAK,CACX,OACA,QACA,WACI,EAAM,OACN,CAAE,OAAQ,EAAM,OAAO,OAAS,CAAE,OAAQ,EAAM,OAAO,MAAO,EAAI,CAAC,CAAE,EACrE,CAAC,CACP,CAAC,EAGL,OAAO,EACR,EDrBH,IAAM,EAAM,QAAQ,KAAK,GAEzB,eAAe,CAAI,EAAG,CACpB,GAAI,CAAC,EAAK,MAAU,MAAM,+BAA+B,EACzD,IAAM,EAAa,EAAK,QAAQ,QAAQ,IAAI,EAAG,sBAAsB,EAC/D,EAAyC,MAAa,UAC5D,GAAI,OAAO,EAAO,UAAY,WAC5B,MAAU,MAAM,GAAG,gDAAyD,EAE9E,IAAM,EAAS,IAAI,EAAO,QAC1B,EAAO,KAAK,EACZ,GAAI,CACF,EAAc,EAAK,KAAK,UAAU,EAAkB,CAAM,CAAC,CAAC,SAC5D,CACA,EAAO,QAAQ,GAKnB,EAAK,EAAE,KACL,IAAM,QAAQ,KAAK,CAAC,EACpB,CAAC,IAAU,CACT,QAAQ,MAAO,GAAiB,OAAS,OAAO,CAAK,CAAC,EACtD,QAAQ,KAAK,CAAC,EAElB",
|
|
9
|
+
"debugId": "2C354352EBF6475164756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Kernel } from "../kernel/Kernel";
|
|
2
|
+
/**
|
|
3
|
+
* One document route, as `gemi stats` needs it: which views render it (layouts
|
|
4
|
+
* first, the page last) and whether it is a `.static()` view.
|
|
5
|
+
*/
|
|
6
|
+
export interface RouteTableEntry {
|
|
7
|
+
/** The route pattern, e.g. `/p/:slug`. */
|
|
8
|
+
path: string;
|
|
9
|
+
/** The host group: `""` for the root, a subdomain, `"*"` for the custom fallback. */
|
|
10
|
+
group: string;
|
|
11
|
+
/** View paths (`app/views/<path>.tsx`), outermost layout first. */
|
|
12
|
+
views: string[];
|
|
13
|
+
/** Set for a `.static()` route; `layout` is its document layout, if any. */
|
|
14
|
+
static?: {
|
|
15
|
+
layout?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Every document route the app declares, from a kernel that has only run its
|
|
20
|
+
* synchronous `boot()`: providers have registered, nothing has booted, so no
|
|
21
|
+
* database, queue, scheduler or listener is touched. Reading the routers only
|
|
22
|
+
* constructs them, which is what `app:route-manifest` has always done.
|
|
23
|
+
*/
|
|
24
|
+
export declare function collectRouteTable(kernel: Kernel): RouteTableEntry[];
|
|
25
|
+
//# sourceMappingURL=routeTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeTable.d.ts","sourceRoot":"","sources":["../../stats/routeTable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4EAA4E;IAC5E,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAKD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,CAmBnE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type StatsConfig } from "./bundleStats";
|
|
2
|
+
import type { RouteTableEntry } from "./routeTable";
|
|
3
|
+
export interface RunStatsOptions {
|
|
4
|
+
rootDir: string;
|
|
5
|
+
/** `stats` from `gemi.config.ts`. */
|
|
6
|
+
config?: StatsConfig;
|
|
7
|
+
/** Write the stats as JSON here. */
|
|
8
|
+
json?: string;
|
|
9
|
+
/** Another build's JSON to compare with; a missing file is no comparison. */
|
|
10
|
+
base?: string;
|
|
11
|
+
/** Write the Markdown table here. */
|
|
12
|
+
markdown?: string;
|
|
13
|
+
/** `false` skips the route table and reports per view. */
|
|
14
|
+
routes?: boolean;
|
|
15
|
+
/** `bun --preload` args for the app's own preload (see `bin/gemi.ts`). */
|
|
16
|
+
preloadArgs?: string[];
|
|
17
|
+
log?: (line: string) => void;
|
|
18
|
+
error?: (line: string) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reads the client build in `<rootDir>/dist/client`, prints the initial JS per
|
|
22
|
+
* route, writes the requested files and checks the budgets. Returns the exit
|
|
23
|
+
* code: 1 when a route is over its budget or there is no build to read.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runStats(options: RunStatsOptions): Promise<number>;
|
|
26
|
+
export type RouteTableResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
routes: RouteTableEntry[];
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
message: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The app's route table, read in a child process (`gemi/stats/route-table`)
|
|
35
|
+
* that imports the Kernel and runs only its synchronous `boot()`, with the same
|
|
36
|
+
* preloads as `gemi start`. A child, because the app's code has to load under
|
|
37
|
+
* the app's own gemi with the request transform registered, and because it
|
|
38
|
+
* must not leave anything running in the build process.
|
|
39
|
+
*/
|
|
40
|
+
export declare function loadRouteTable(rootDir: string, preloadArgs: string[], options?: {
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}): Promise<RouteTableResult>;
|
|
43
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../stats/run.ts"],"names":[],"mappings":"AAGA,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA6CxE;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAuC3B"}
|
package/dist/support/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{pc as Y}from"../chunk-qd2v93y4.js";import{ig as M}from"../chunk-bn5yn731.js";import{jh as P,lh as R}from"../chunk-q9s7kwgt.js";import"../chunk-3cg7y62b.js";import{uh as Q,vh as U,wh as V,xh as W}from"../chunk-m6ystvtk.js";import"../chunk-1yx2e0bh.js";class S{static token;async boot(){}static inject(){if(!this.token)throw Error(`Service [${this.name}] does not declare a \`static token\`, so the container has no key to resolve it by.`);try{return R(this)}catch(x){throw Error(`Could not inject [${this.name}]. Services are constructed when the kernel boots, so `+"inject() only works from code that runs after that \u2014 a constructor default or a method "+`body, never module top level. Check that [${this.name}] is listed in \`services\` on your Kernel.`,{cause:x})}}static with(x){let f=new this;for(let[C,g]of Object.entries(x))if(g!==void 0)f[C]=g;return f}}import{readdir as z}from"fs/promises";import{join as B,parse as j}from"path";var H=[".ts",".tsx",".js",".mjs",".jsx"];function J(x={}){let f={};for(let[C,g]of Object.entries(x))f[C]=q(g);return new P(f)}async function L(x,f=new P){let C=[];try{C=await z(x)}catch(D){return f}let g=C.filter((D)=>{let{ext:v,name:F}=j(D);return H.includes(v)&&!F.startsWith(".")}).sort();for(let D of g){let{name:v}=j(D),F=await import(B(x,D));f.set(v,q(F))}return f}function q(x){if(x&&typeof x==="object"&&"default"in x)return x.default;return x}export{M as withDefaults,Q as sourceFiles,W as projectRoot,L as loadConfigFrom,V as discoverClasses,J as createConfigRepository,Y as ServiceProvider,S as Service,P as Repository,U as DiscoveryError};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=447CF5C12AD6A7A564756E2164756E21
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"import { readdir } from \"node:fs/promises\";\nimport { join, parse } from \"node:path\";\n\nimport { Repository } from \"./Repository\";\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".mjs\", \".jsx\"];\n\n// Builds a Repository from an already-imported map of config modules. The map\n// key becomes the top-level config key, so `{ mail: mailModule }` is readable\n// as `config.get(\"mail.driver\")`. Each entry may be either the module namespace\n// (its `default` export is unwrapped) or the config object itself.\nexport function createConfigRepository(\n modules: Record<string, any> = {},\n): Repository {\n const items: Record<string, any> = {};\n\n for (const [key, mod] of Object.entries(modules)) {\n items[key] = unwrap(mod);\n }\n\n return new Repository(items);\n}\n\n// Reads every config module in an app's `app/config` directory into a\n// Repository. The file's basename is the top-level key: `app/config/mail.ts`\n// populates `mail.*`. A missing directory yields an empty Repository so apps\n// that declare no config still boot.\nexport async function loadConfigFrom(\n directory: string,\n repository = new Repository(),\n): Promise<Repository> {\n let entries: string[] = [];\n\n try {\n entries = await readdir(directory);\n } catch (err) {\n return repository;\n }\n\n const files = entries\n .filter((entry) => {\n const { ext, name } = parse(entry);\n return CONFIG_EXTENSIONS.includes(ext) && !name.startsWith(\".\");\n })\n .sort();\n\n for (const file of files) {\n const { name } = parse(file);\n const mod = await import(join(directory, file));\n repository.set(name, unwrap(mod));\n }\n\n return repository;\n}\n\nfunction unwrap(mod: any) {\n if (mod && typeof mod === \"object\" && \"default\" in mod) {\n return mod.default;\n }\n return mod;\n}\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": ";2RAgCO,CAAe,JAAQ,EAOrB,OAMD,AAAI,EAAkB,QAmBrB,OAAS,EAKX,CACH,GAAI,CAAC,KAAK,MACR,MAAU,MACR,YAAY,KAAK,0FACnB,EAGF,GAAI,CACF,OAAO,EAAI,IAAuB,EAClC,MAAO,EAAO,CACd,MAAU,MACR,qBAAqB,KAAK,6DACxB,+FACA,6CAA6C,KAAK,kDAEpD,CAAE,OAAM,CACV,SAoBG,KAAuB,CAAoB,EAA0B,CAC1E,IAAM,EAAW,IAAI,KACrB,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAS,EACjD,GAAI,IAAU,OAAW,EAAS,GAAO,EAE3C,OAAO,EAEX,CChHA,kBAAS,oBACT,eAAS,WAAM,aAIf,IAAM,EAAoB,CAAC,MAAO,OAAQ,MAAO,OAAQ,MAAM,EAMxD,SAAS,CAAsB,CACpC,EAA+B,CAAC,EACpB,CACZ,IAAM,EAA6B,CAAC,EAEpC,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAO,EAC7C,EAAM,GAAO,EAAO,CAAG,EAGzB,OAAO,IAAI,EAAW,CAAK,EAO7B,eAAsB,CAAc,CAClC,EACA,EAAa,IAAI,EACI,CACrB,IAAI,EAAoB,CAAC,EAEzB,GAAI,CACF,EAAU,MAAM,EAAQ,CAAS,EACjC,MAAO,EAAK,CACZ,OAAO,EAGT,IAAM,EAAQ,EACX,OAAO,CAAC,IAAU,CACjB,IAAQ,MAAK,QAAS,EAAM,CAAK,EACjC,OAAO,EAAkB,SAAS,CAAG,GAAK,CAAC,EAAK,WAAW,GAAG,EAC/D,EACA,KAAK,EAER,QAAW,KAAQ,EAAO,CACxB,IAAQ,QAAS,EAAM,CAAI,EACrB,EAAM,MAAa,SAAK,EAAW,CAAI,GAC7C,EAAW,IAAI,EAAM,EAAO,CAAG,CAAC,EAGlC,OAAO,EAGT,SAAS,CAAM,CAAC,EAAU,CACxB,GAAI,GAAO,OAAO,IAAQ,UAAY,YAAa,EACjD,OAAO,EAAI,QAEb,OAAO",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "447CF5C12AD6A7A564756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/vite/index.mjs
CHANGED
|
@@ -1448,12 +1448,74 @@ function documentBase(base) {
|
|
|
1448
1448
|
return base.startsWith("/") || /^[a-z][a-z\d+.-]*:\/\//i.test(base) ? normalizeAssetBase(base) : "/";
|
|
1449
1449
|
}
|
|
1450
1450
|
//#endregion
|
|
1451
|
+
//#region internal/islandRuntime.ts
|
|
1452
|
+
/**
|
|
1453
|
+
* The browser side of islands, shared by the Vite plugin (which builds it), the
|
|
1454
|
+
* servers (which point the loader at it) and the tests.
|
|
1455
|
+
*
|
|
1456
|
+
* No imports: the Vite plugin is built on its own and the servers load it at
|
|
1457
|
+
* boot, so this file stays plain strings.
|
|
1458
|
+
*/
|
|
1459
|
+
/**
|
|
1460
|
+
* The module that hydrates islands: React, `react-dom/client` and the small
|
|
1461
|
+
* `h(marker, Component)` below. A virtual module of gemi's Vite plugin that
|
|
1462
|
+
* every island entry imports, so the islands on a page share one copy of
|
|
1463
|
+
* React, in one chunk.
|
|
1464
|
+
*/
|
|
1465
|
+
var ISLAND_RUNTIME_ID = "virtual:gemi-island-runtime";
|
|
1466
|
+
/** What `resolveId` turns `ISLAND_RUNTIME_ID` into (Vite's virtual-module convention). */
|
|
1467
|
+
var RESOLVED_ISLAND_RUNTIME_ID = `\0${ISLAND_RUNTIME_ID}`;
|
|
1468
|
+
/**
|
|
1469
|
+
* The query that turns a module into its island entry: `Counter.tsx?gemi-island`
|
|
1470
|
+
* is a module of the plugin's that re-exports `Counter.tsx` as `m` next to the
|
|
1471
|
+
* runtime's `h`. It is what a static page imports for an island, and so it
|
|
1472
|
+
* is what the client manifest lists, keyed `app/…/Counter.tsx?gemi-island`,
|
|
1473
|
+
* with React and `react-dom/client` among its imports.
|
|
1474
|
+
*/
|
|
1475
|
+
var ISLAND_ENTRY_QUERY = "?gemi-island";
|
|
1476
|
+
/** The island entry module for `file` (an absolute path or a root-relative URL). */
|
|
1477
|
+
function islandEntrySource(file) {
|
|
1478
|
+
return `import * as m from ${JSON.stringify(file)};
|
|
1479
|
+
export { m };
|
|
1480
|
+
export { h } from ${JSON.stringify(ISLAND_RUNTIME_ID)};
|
|
1481
|
+
`;
|
|
1482
|
+
}
|
|
1483
|
+
/** The runtime module's source, as the plugin serves and builds it. */
|
|
1484
|
+
var ISLAND_RUNTIME_SOURCE = `import { createElement } from "react";
|
|
1485
|
+
import { hydrateRoot } from "react-dom/client";
|
|
1486
|
+
export function h(marker, Component) {
|
|
1487
|
+
if (typeof Component !== "function" && (typeof Component !== "object" || Component === null)) {
|
|
1488
|
+
throw new Error("gemi: island module has no component export for " + marker.outerHTML.slice(0, 80));
|
|
1489
|
+
}
|
|
1490
|
+
const json = marker.getAttribute("data-props");
|
|
1491
|
+
const props = json ? JSON.parse(json) : {};
|
|
1492
|
+
let slot = null;
|
|
1493
|
+
for (const candidate of marker.querySelectorAll("gemi-slot")) {
|
|
1494
|
+
if (candidate.closest("gemi-island") === marker) {
|
|
1495
|
+
slot = candidate;
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
const children = slot
|
|
1500
|
+
? [createElement("gemi-slot", {
|
|
1501
|
+
style: { display: "contents" },
|
|
1502
|
+
suppressHydrationWarning: true,
|
|
1503
|
+
dangerouslySetInnerHTML: { __html: slot.innerHTML },
|
|
1504
|
+
})]
|
|
1505
|
+
: [];
|
|
1506
|
+
return hydrateRoot(marker, createElement(Component, props, ...children), {
|
|
1507
|
+
identifierPrefix: marker.getAttribute("data-uid") || undefined,
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
`;
|
|
1511
|
+
//#endregion
|
|
1451
1512
|
//#region vite/islandPlugin.ts
|
|
1452
1513
|
/**
|
|
1453
|
-
* `() => import("./
|
|
1454
|
-
*
|
|
1514
|
+
* `island(() => import("./Counter")`: the call `island()` is declared with.
|
|
1515
|
+
* The loader must be the first argument, written as an arrow with no
|
|
1516
|
+
* parameters returning one `import()` of a string literal.
|
|
1455
1517
|
*/
|
|
1456
|
-
var
|
|
1518
|
+
var ISLAND_CALL = /\bisland\s*\(\s*(\(\s*\)\s*=>\s*import\(\s*(["'])([^"'\n]+)\2\s*\))/g;
|
|
1457
1519
|
/**
|
|
1458
1520
|
* Symlinks resolved, so the key is the same path the manifest is keyed on
|
|
1459
1521
|
* however the project directory was reached (`/var` vs `/private/var` on
|
|
@@ -1467,47 +1529,87 @@ function realPath(path) {
|
|
|
1467
1529
|
}
|
|
1468
1530
|
}
|
|
1469
1531
|
/**
|
|
1470
|
-
*
|
|
1532
|
+
* Islands: `island(() => import("./Counter"))` in `gemi/client`.
|
|
1471
1533
|
*
|
|
1472
|
-
*
|
|
1473
|
-
*
|
|
1474
|
-
*
|
|
1534
|
+
* Every such call is rewritten, in the client and the server graph alike, so
|
|
1535
|
+
* the loader carries the module's build key (its path from the project root,
|
|
1536
|
+
* the key the client manifest uses) and the module itself, imported
|
|
1537
|
+
* statically:
|
|
1475
1538
|
*
|
|
1476
1539
|
* ```js
|
|
1477
|
-
*
|
|
1540
|
+
* import * as __gemi_island_0 from "./Counter";
|
|
1541
|
+
* island(Object.assign(() => Promise.resolve(__gemi_island_0),
|
|
1542
|
+
* { gemiIsland: "app/views/site/Counter.tsx", gemiModule: __gemi_island_0 }))
|
|
1478
1543
|
* ```
|
|
1479
1544
|
*
|
|
1480
|
-
* The
|
|
1481
|
-
*
|
|
1482
|
-
* is
|
|
1545
|
+
* The static import is what lets a hydrated view render the component in
|
|
1546
|
+
* place, and a static view render it on the server without waiting on a
|
|
1547
|
+
* dynamic import. The key is what a static page's loader is pointed at.
|
|
1548
|
+
*
|
|
1549
|
+
* In the client build, each island module also gets an entry of its own,
|
|
1550
|
+
* `Counter.tsx?gemi-island`: the module (as `m`) and the island runtime's
|
|
1551
|
+
* hydrate function `h` (from `virtual:gemi-island-runtime`, which imports
|
|
1552
|
+
* React and `react-dom/client`). That entry's import closure, React included,
|
|
1553
|
+
* is exactly what a static page loads for the island, and the manifest shows
|
|
1554
|
+
* it under the entry's key. The runtime is one chunk the islands share. In
|
|
1555
|
+
* dev, Vite serves the same modules from source.
|
|
1556
|
+
*
|
|
1557
|
+
* Also usable on its own, e.g. from `gemi/vitest` in an app's
|
|
1558
|
+
* `vitest.config.ts`, so tests render islands with the same keys as the build.
|
|
1483
1559
|
*/
|
|
1484
1560
|
function gemiIslandPlugin() {
|
|
1485
1561
|
let root = process.cwd();
|
|
1562
|
+
let clientBuild = false;
|
|
1563
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
1486
1564
|
return {
|
|
1487
1565
|
name: "gemi-plugin-islands",
|
|
1488
1566
|
enforce: "pre",
|
|
1489
1567
|
configResolved(config) {
|
|
1490
1568
|
root = realPath(config.root);
|
|
1569
|
+
clientBuild = config.command === "build" && !config.build.ssr;
|
|
1570
|
+
},
|
|
1571
|
+
buildStart() {
|
|
1572
|
+
emitted.clear();
|
|
1573
|
+
},
|
|
1574
|
+
resolveId(id) {
|
|
1575
|
+
return id === "virtual:gemi-island-runtime" ? RESOLVED_ISLAND_RUNTIME_ID : null;
|
|
1491
1576
|
},
|
|
1492
|
-
|
|
1493
|
-
if (id
|
|
1577
|
+
load(id) {
|
|
1578
|
+
if (id === RESOLVED_ISLAND_RUNTIME_ID) return ISLAND_RUNTIME_SOURCE;
|
|
1579
|
+
if (id.endsWith("?gemi-island")) return islandEntrySource(id.slice(0, -ISLAND_ENTRY_QUERY.length));
|
|
1580
|
+
return null;
|
|
1581
|
+
},
|
|
1582
|
+
async transform(code, id) {
|
|
1583
|
+
if (id.includes("/node_modules/") || id.startsWith("\0") || id.endsWith("?gemi-island")) return null;
|
|
1494
1584
|
if (!/\.[cm]?[jt]sx?$/.test(id.split("?")[0])) return null;
|
|
1495
|
-
if (!code.includes("
|
|
1496
|
-
const
|
|
1585
|
+
if (!code.includes("island")) return null;
|
|
1586
|
+
const environmentConsumer = this.environment?.config?.consumer;
|
|
1587
|
+
const emitEntries = clientBuild && (environmentConsumer === void 0 || environmentConsumer === "client");
|
|
1497
1588
|
const s = new MagicString(code);
|
|
1498
|
-
|
|
1499
|
-
for (const match of code.matchAll(
|
|
1500
|
-
const [
|
|
1589
|
+
const imports = [];
|
|
1590
|
+
for (const match of code.matchAll(ISLAND_CALL)) {
|
|
1591
|
+
const [, loader, quote, specifier] = match;
|
|
1501
1592
|
const resolved = await this.resolve(specifier, id);
|
|
1502
1593
|
if (!resolved || resolved.external) continue;
|
|
1503
1594
|
const file = realPath(resolved.id.split("?")[0]);
|
|
1504
1595
|
const key = relative(root, file).split(sep).join("/");
|
|
1505
1596
|
if (key.startsWith("..")) continue;
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1597
|
+
const name = `__gemi_island_${imports.length}`;
|
|
1598
|
+
imports.push(`import * as ${name} from ${quote}${specifier}${quote};`);
|
|
1599
|
+
const start = match.index + match[0].length - loader.length;
|
|
1600
|
+
s.overwrite(start, start + loader.length, `Object.assign(() => Promise.resolve(${name}), { gemiIsland: ${JSON.stringify(key)}, gemiModule: ${name} })`);
|
|
1601
|
+
const moduleId = resolved.id.split("?")[0];
|
|
1602
|
+
if (emitEntries && !emitted.has(moduleId)) {
|
|
1603
|
+
emitted.add(moduleId);
|
|
1604
|
+
this.emitFile({
|
|
1605
|
+
type: "chunk",
|
|
1606
|
+
id: `${moduleId}${ISLAND_ENTRY_QUERY}`,
|
|
1607
|
+
preserveSignature: "strict"
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1509
1610
|
}
|
|
1510
|
-
if (
|
|
1611
|
+
if (imports.length === 0) return null;
|
|
1612
|
+
s.prepend(`${imports.join("\n")}\n`);
|
|
1511
1613
|
return {
|
|
1512
1614
|
code: s.toString(),
|
|
1513
1615
|
map: s.generateMap({ hires: true })
|
|
@@ -1533,7 +1635,7 @@ var gemi = async () => {
|
|
|
1533
1635
|
ssrEmitAssets: true,
|
|
1534
1636
|
sourcemap: true,
|
|
1535
1637
|
rollupOptions: {
|
|
1536
|
-
input: Array.from(JSON.parse(process.env.GEMI_INPUT ?? "[]"))
|
|
1638
|
+
input: Array.from(JSON.parse(process.env.GEMI_INPUT ?? "[]")),
|
|
1537
1639
|
preserveEntrySignatures: "strict",
|
|
1538
1640
|
...env.isSsrBuild ? { external: isGemiExternal } : {}
|
|
1539
1641
|
}
|
package/dist/vitest/index.d.ts
CHANGED
|
@@ -24,4 +24,22 @@ import type { Plugin } from "vite";
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export declare function gemiRequestPlugin(): Plugin;
|
|
27
|
+
/**
|
|
28
|
+
* gemi's island transform, for an app's `vitest.config.ts`: with it, a test
|
|
29
|
+
* that renders a static view through `App.fetch` sees each
|
|
30
|
+
* `island(() => import("./Counter"))` with the same module key as the build,
|
|
31
|
+
* and a hydrated view renders the component in place instead of lazily.
|
|
32
|
+
*
|
|
33
|
+
* Without it islands still render (the component is loaded with the
|
|
34
|
+
* `import()`), but their keys are unknown.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* // vitest.config.ts
|
|
38
|
+
* import { defineConfig } from "vitest/config";
|
|
39
|
+
* import { gemiIslandPlugin, gemiRequestPlugin } from "gemi/vitest";
|
|
40
|
+
*
|
|
41
|
+
* export default defineConfig({ plugins: [gemiRequestPlugin(), gemiIslandPlugin()] });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export { gemiIslandPlugin } from "../vite/islandPlugin";
|
|
27
45
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../vitest/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAY1C"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../vitest/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAY1C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|