gemi 0.45.0 → 0.46.1
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/app/index.js +1 -1
- package/dist/bin/gemi.js +185 -49
- package/dist/bin/gemi.js.map +10 -7
- package/dist/{chunk-tvp3xgfq.js → chunk-2ahct6kg.js} +2 -2
- package/dist/{chunk-tvp3xgfq.js.map → chunk-2ahct6kg.js.map} +1 -1
- package/dist/{chunk-v0qh5dqv.js → chunk-5hggqap1.js} +15 -15
- package/dist/{chunk-v0qh5dqv.js.map → chunk-5hggqap1.js.map} +3 -3
- package/dist/chunk-d9k245jt.js +79 -0
- package/dist/{chunk-jxpwexpz.js.map → chunk-d9k245jt.js.map} +8 -5
- package/dist/chunk-evkv0xa7.js +4 -0
- package/dist/{chunk-atv6nybp.js.map → chunk-evkv0xa7.js.map} +4 -4
- package/dist/{chunk-63gmzy5r.js → chunk-pr2xbq0m.js} +1 -1
- package/dist/{chunk-ppn0j67g.js → chunk-r64ba1pf.js} +1 -1
- package/dist/{chunk-396qq8ge.js → chunk-z29tg1ey.js} +1 -1
- package/dist/client/ClientRouter.d.ts.map +1 -1
- package/dist/client/Head.d.ts.map +1 -1
- package/dist/client/QueryManagerContext.d.ts +5 -2
- package/dist/client/QueryManagerContext.d.ts.map +1 -1
- package/dist/client/QueryResource.d.ts +23 -1
- package/dist/client/QueryResource.d.ts.map +1 -1
- package/dist/client/helpers/mergeCarriedSegments.d.ts +23 -0
- package/dist/client/helpers/mergeCarriedSegments.d.ts.map +1 -0
- package/dist/client/index.js +168 -27
- package/dist/client/index.js.map +1 -1
- package/dist/client/useQuery.d.ts +2 -0
- package/dist/client/useQuery.d.ts.map +1 -1
- package/dist/facades/index.js +1 -1
- package/dist/http/Metadata.d.ts +6 -0
- package/dist/http/Metadata.d.ts.map +1 -1
- package/dist/http/ViewRouter.d.ts +12 -0
- package/dist/http/ViewRouter.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/kernel/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/router/ViewRouterServiceContainer.d.ts.map +1 -1
- package/dist/services/router/ViewRouterServiceProvider.d.ts +10 -0
- package/dist/services/router/ViewRouterServiceProvider.d.ts.map +1 -1
- package/dist/services/router/createFlatViewRoutes.d.ts +16 -0
- package/dist/services/router/createFlatViewRoutes.d.ts.map +1 -1
- package/dist/services/router/matchViewRoute.d.ts +12 -0
- package/dist/services/router/matchViewRoute.d.ts.map +1 -0
- package/dist/services/router/planPartialRender.d.ts +43 -0
- package/dist/services/router/planPartialRender.d.ts.map +1 -0
- package/dist/utils/partialRender.d.ts +28 -0
- package/dist/utils/partialRender.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-atv6nybp.js +0 -4
- package/dist/chunk-jxpwexpz.js +0 -79
- /package/dist/{chunk-63gmzy5r.js.map → chunk-pr2xbq0m.js.map} +0 -0
- /package/dist/{chunk-ppn0j67g.js.map → chunk-r64ba1pf.js.map} +0 -0
- /package/dist/{chunk-396qq8ge.js.map → chunk-z29tg1ey.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{h as g,i as R}from"./chunk-
|
|
2
|
+
import{h as g,i as R}from"./chunk-2ahct6kg.js";import"./chunk-ppt296ye.js";import{K,M as W}from"./chunk-d9k245jt.js";import"./chunk-evkv0xa7.js";import"./chunk-p5r0t9jh.js";import"./chunk-4z53shav.js";import"./chunk-m0earq80.js";import"./chunk-f18weffa.js";import{join as j}from"path";function V(J){let x=J.toString(),Q=new Bun.CryptoHasher("sha1");return Q.update(x),Q.digest("hex")}if(!globalThis.URLPattern)globalThis.URLPattern=K;import{exists as v}from"fs/promises";var u=process.env.GEMI_PROJECT_DIR??"",T=j(process.cwd(),u),F=j(T,"app"),$=j(T,"dist");async function a(J,x){let Q=await import(`${$}/client/.vite/manifest.json`),O=await import(`${$}/server/.vite/manifest.json`);process.env.ROOT_DIR=T,process.env.APP_DIR=F,process.env.DIST_DIR=$;let A={},C={},I={},S=(b,L)=>`"${b}": () => import("${L}")`,_=[];for(let b of["404",...J.getFlatComponentTree.call(J)]){let L=O[`app/views/${b}.tsx`];if(!L?.file){console.log(`Server file not found for ${b}`),console.log(L);let U=Object.keys(O),Y=`app/views/${b}.tsx`;console.log(`${Y} not found in server manifest`),console.log(U)}let z=await import(`${process.env.DIST_DIR}/server/${L?.file}`);A[b]=z.default,C[b]=z.OpenGraph;let k=Q[`app/views/${b}.tsx`];if(k?.css&&k?.css.length>0)I[b]=k?.css;if(k)_.push(S(b,`/${k?.file}`))}let N=`{${_.join(",")}}`,w=Q["app/client.tsx"]?.css??[],M=(await Promise.all(w.map((b)=>Bun.file(`${$}/client/${b}`).text()))).join(`
|
|
3
3
|
`),D=new K({pathname:"/*.:filetype(png|txt|js|css|jpg|svg|jpeg|avif|webp|ico|ttf|map)"});async function E(b){let{pathname:L}=new URL(b.url),z=L.startsWith("/.well-known"),k=D.test({pathname:L})||z,U=L.startsWith("/api");if(k&&!U){let Y=new URL(b.url),B=b.url.replace(Y.origin,"").split("?")[0],Z=`${$}/client${B.replace("/assets/assets","/assets")}`,H=await v(Z);if(!H&&Y.pathname.includes(".js"))return new Response(`if(caches){caches?.delete("${Z}")}window.location.reload();export {}`,{headers:{"Content-Type":"application/javascript"}});if(!H){if(L===W||L.startsWith(`${W}/`))return new Response("Not found",{status:404});return await y(b,L)}try{let G=Bun.file(Z),X=V(G.lastModified);return new Response(G.stream(),{headers:{"Content-Type":G.type,"Cache-Control":"public, max-age=31536000, must-revalidate","Content-Length":String(G.size),ETag:X}})}catch(G){return J.onException?.(G),new Response("Not found",{status:404})}}return await y(b,L)}async function y(b,L){let z=J.fetch.bind(J);try{let k=await z(b);if(k instanceof Response)return k;else{let U=[];return U.push({content:M}),await k({getStyles:async(B)=>{if(!B)return g([]);for(let Z of B){let H=Q[`app/views/${Z}.tsx`];for(let G of H?.css??[]){let X=Bun.file(`${process.env.DIST_DIR}/client/${G}`);U.push({id:G,content:await X.text()})}}return g(U)},bootstrapModules:[`/${Q["app/client.tsx"].file}`],loaders:N,viewImportMap:A,ogMap:C,cssManifest:I})}}catch(k){if(console.error(k),L.startsWith("/api"))return new Response(JSON.stringify({error:k.message}),{status:500,headers:{"Content-Type":"application/json"}});return J.onException?.(k),new Response(k.stack,{status:500})}}let P=Bun.serve({maxRequestBodySize:10737418240,fetch:async(b,L)=>{if(!b.headers.get("x-forwarded-for")){let z=L.requestIP(b);if(z)b.headers.set("x-forwarded-for",z.address)}return await x(b,E)},idleTimeout:Number(process.env.SERVER_IDLE_TIMEOUT??10),port:process.env.PORT||5173});return R({port:P.port,rootDir:T}),P}export{a as httpProd};
|
|
4
4
|
|
|
5
5
|
//# debugId=B6DC0792DD8A023A64756E2164756E21
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{N as U,O as X,s as L}from"./chunk-
|
|
2
|
+
import{N as U,O as X,s as L}from"./chunk-d9k245jt.js";import{Ob as Y}from"./chunk-xkrthw08.js";import{fc as S,gc as $}from"./chunk-f18weffa.js";var K=$((u,I)=>{var{defineProperty:W,getOwnPropertyDescriptor:J,getOwnPropertyNames:Q}=Object,B=Object.prototype.hasOwnProperty,E=(z,F)=>{for(var G in F)W(z,G,{get:F[G],enumerable:!0})},N=(z,F,G,T)=>{if(F&&typeof F==="object"||typeof F==="function"){for(let H of Q(F))if(!B.call(z,H)&&H!==G)W(z,H,{get:()=>F[H],enumerable:!(T=J(F,H))||T.enumerable})}return z},O=(z)=>N(W({},"__esModule",{value:!0}),z),A={};E(A,{Prisma:()=>D,PrismaClient:()=>k,default:()=>v});I.exports=O(A);var R={enginesVersion:"c2990dca591cba766e3b7ef5d9e8a84796e47ab7"},V="6.19.2",h=V,k=class{constructor(){throw Error('@prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.')}};function q(z){if(typeof z==="function")return z;return(F)=>F.$extends(z)}function y(z){return z}var D={defineExtension:q,getExtensionContext:y,prismaVersion:{client:h,engine:R.enginesVersion}},v={Prisma:D}});var b=$((d,M)=>{M.exports={...K()}});class Z{kernel;onException;constructor(z){this.kernel=new z.kernel,this.kernel.boot.call(this.kernel),this.onException=z.onException??((F)=>{console.error("Unhandled exception in App:",F)})}useViewRouter(){let z=this.kernel.services[U._name];if(!z)throw Error("ViewRouterServiceContainer is not registered \u2014 was the kernel booted?");return z}getComponentTree(){return this.useViewRouter().componentTree}getFlatComponentTree(){return this.useViewRouter().flatComponentTree}getRouteManifest(){return this.useViewRouter().routeManifest}async fetch(z){let F=new URL(z.url);return this.kernel.run.call(this.kernel,async()=>{if(F.pathname.startsWith("/api"))return await X.use().handleApiRequest(z);return await U.use().handleViewRequest(z)})}websocket={message:(z,F)=>{this.kernel.run.bind(this.kernel)(()=>{L.use().run(z.data.headers,()=>{L.use().handleMessage(z,F)})})},open:(z)=>{},close:(z)=>{console.log("closed ws"),z.terminate()}};onPublish(z){this.kernel.run.bind(this.kernel)(()=>{L.use().onPublish(z)})}dispatchJob(z,F){return this.kernel.run.bind(this.kernel)(()=>{return Y.use().dispatchJob(z,F)})}destroy(){this.kernel.destroy()}clone(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)}}var j=S(b(),1),P=j.Prisma.defineExtension({name:"Gemi Policies",query:{async $allOperations({args:z,operation:F,query:G,model:T}){return await G(z)}}});export{Z as o,P as p};
|
|
3
3
|
|
|
4
4
|
//# debugId=52D517464DBD54BE64756E2164756E21
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{g as I,i as f}from"./chunk-
|
|
2
|
+
import{g as I,i as f}from"./chunk-2ahct6kg.js";import{j as b,k as y}from"./chunk-ghes36xj.js";import"./chunk-vv72kw74.js";import"./chunk-ppt296ye.js";import"./chunk-r64ba1pf.js";import"./chunk-d9k245jt.js";import"./chunk-evkv0xa7.js";import"./chunk-p5r0t9jh.js";import"./chunk-xkrthw08.js";import"./chunk-4z53shav.js";import"./chunk-m0earq80.js";import"./chunk-f18weffa.js";import{IncomingMessage as w,ServerResponse as N}from"http";import{Socket as T}from"net";import{join as g}from"path";import{createServer as E}from"vite";function S(H){return H.replace(/\x1b\[[0-9;]*m/g,"").replace(/\[[0-9;]*m/g,"").replace(/\n\s*\n/g,`
|
|
3
3
|
`).split(`
|
|
4
4
|
`).map((J)=>J.trim()).filter((J)=>J.length>0).join(`
|
|
5
5
|
`).trim()}function P(H){return`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../client/ClientRouter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../client/ClientRouter.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAqB,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAkC/E,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;KACrC;CACF;AAuSD,eAAO,MAAM,YAAY,GAAI,OAAO;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;IACxD,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE,4CA2CA,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../client/Head.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAGnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../client/Head.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAGnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,QAqBnC;AAmED,eAAO,MAAM,IAAI,GAAI,wBAGlB;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,4CAuB5C,CAAC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type PropsWithChildren } from "react";
|
|
2
2
|
import { QueryResource } from "./QueryResource";
|
|
3
|
-
export
|
|
3
|
+
export type PrefetchedData = Record<string, Record<string, any>>;
|
|
4
|
+
export interface QueryManagerContextValue {
|
|
4
5
|
getResource: (key: string, initialState?: Record<string, any>) => QueryResource;
|
|
5
|
-
|
|
6
|
+
hydrate: (prefetchedData?: PrefetchedData | null) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const QueryManagerContext: import("react").Context<QueryManagerContextValue>;
|
|
6
9
|
export declare const QueryManagerProvider: ({ children }: PropsWithChildren<{}>) => import("react/jsx-runtime").JSX.Element;
|
|
7
10
|
//# sourceMappingURL=QueryManagerContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryManagerContext.d.ts","sourceRoot":"","sources":["../../client/QueryManagerContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,
|
|
1
|
+
{"version":3,"file":"QueryManagerContext.d.ts","sourceRoot":"","sources":["../../client/QueryManagerContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EAIvB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,CACX,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC/B,aAAa,CAAC;IACnB,OAAO,EAAE,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3D;AAED,eAAO,MAAM,mBAAmB,mDAK9B,CAAC;AAEH,eAAO,MAAM,oBAAoB,GAAI,cAAc,iBAAiB,CAAC,EAAE,CAAC,4CA0CvE,CAAC"}
|
|
@@ -5,13 +5,35 @@ type State = {
|
|
|
5
5
|
error: any;
|
|
6
6
|
version: number;
|
|
7
7
|
};
|
|
8
|
+
export declare const DEFAULT_STALE_TIME = 5000;
|
|
8
9
|
export declare class QueryResource {
|
|
9
10
|
store: Subject<Map<string, State>>;
|
|
10
11
|
staleVariants: Set<string>;
|
|
11
12
|
lastFetchRecord: Map<string, number>;
|
|
12
13
|
key: string;
|
|
13
14
|
constructor(key: string, initialState: Record<string, any>);
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Adopt server-prefetched data into the cache.
|
|
17
|
+
*
|
|
18
|
+
* Called once from the constructor for the SSR payload, and again on every
|
|
19
|
+
* client-side navigation with the `prefetchedData` the server just produced —
|
|
20
|
+
* otherwise the resource cache (which is keyed by path for the lifetime of
|
|
21
|
+
* the app) would keep serving the first payload and revalidate it over `/api`.
|
|
22
|
+
*/
|
|
23
|
+
hydrate(initialState: Record<string, any> | null | undefined): void;
|
|
24
|
+
/**
|
|
25
|
+
* The cached state for a variant, or `undefined` — a plain read that never
|
|
26
|
+
* fetches and never revalidates.
|
|
27
|
+
*
|
|
28
|
+
* `getVariant` is the read that keeps the cache honest, and it starts a
|
|
29
|
+
* request when it has to. That makes it the wrong thing to call while
|
|
30
|
+
* rendering: React throws away a render whose subtree suspends and retries
|
|
31
|
+
* it, so every discarded attempt would leak a request. Renders read with
|
|
32
|
+
* this; effects, which only run for a render that committed, use
|
|
33
|
+
* `getVariant`.
|
|
34
|
+
*/
|
|
35
|
+
peek(variantKey: string): State;
|
|
36
|
+
getVariant(variantKey: string, staleTime?: number): State;
|
|
15
37
|
mutate(variantKey: string, fn?: (data: any) => any): void;
|
|
16
38
|
refetch(variantKey: string): void;
|
|
17
39
|
private resolveVariant;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryResource.d.ts","sourceRoot":"","sources":["../../client/QueryResource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qBAAa,aAAa;IACxB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACnC,aAAa,cAAqB;IAClC,eAAe,sBAA6B;IAC5C,GAAG,EAAE,MAAM,CAAC;gBAEA,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"QueryResource.d.ts","sourceRoot":"","sources":["../../client/QueryResource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,qBAAa,aAAa;IACxB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACnC,aAAa,cAAqB;IAClC,eAAe,sBAA6B;IAC5C,GAAG,EAAE,MAAM,CAAC;gBAEA,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAM1D;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS;IA+B5D;;;;;;;;;;OAUG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM;IAIvB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,GAAE,MAA2B;IA+BrE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAoB;IAuClE,OAAO,CAAC,UAAU,EAAE,MAAM;YAIZ,cAAc;CAgE7B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Breadcrumb } from "../useBreadcrumbs";
|
|
2
|
+
interface RouteSnapshot {
|
|
3
|
+
/** Concrete pathname, without the locale segment. */
|
|
4
|
+
pathname: string;
|
|
5
|
+
/** Route pattern the data was produced for — part of every breadcrumb key. */
|
|
6
|
+
routePath: string;
|
|
7
|
+
data: Record<string, any>;
|
|
8
|
+
breadcrumbs: Record<string, Breadcrumb>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A partially rendered response only carries the segments the server actually
|
|
12
|
+
* ran. Everything is keyed by the *new* pathname, so a carried layout would
|
|
13
|
+
* render with empty props unless the data it already had is copied across.
|
|
14
|
+
*
|
|
15
|
+
* Data the server sent always wins: a carried view is only filled in where the
|
|
16
|
+
* response has nothing for it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeCarriedSegments(previous: RouteSnapshot, next: RouteSnapshot, carriedViews: string[]): {
|
|
19
|
+
data: Record<string, any>;
|
|
20
|
+
breadcrumbs: Record<string, Breadcrumb>;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=mergeCarriedSegments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeCarriedSegments.d.ts","sourceRoot":"","sources":["../../../client/helpers/mergeCarriedSegments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,UAAU,aAAa;IACrB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACzC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,aAAa,EACnB,YAAY,EAAE,MAAM,EAAE;;;EAwCvB"}
|
package/dist/client/index.js
CHANGED
|
@@ -25,6 +25,7 @@ var Subject = class {
|
|
|
25
25
|
};
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region client/QueryResource.ts
|
|
28
|
+
var DEFAULT_STALE_TIME = 5e3;
|
|
28
29
|
var QueryResource = class {
|
|
29
30
|
store;
|
|
30
31
|
staleVariants = /* @__PURE__ */ new Set();
|
|
@@ -32,19 +33,53 @@ var QueryResource = class {
|
|
|
32
33
|
key;
|
|
33
34
|
constructor(key, initialState) {
|
|
34
35
|
this.key = key;
|
|
35
|
-
|
|
36
|
+
this.store = new Subject(/* @__PURE__ */ new Map());
|
|
37
|
+
this.hydrate(initialState);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Adopt server-prefetched data into the cache.
|
|
41
|
+
*
|
|
42
|
+
* Called once from the constructor for the SSR payload, and again on every
|
|
43
|
+
* client-side navigation with the `prefetchedData` the server just produced —
|
|
44
|
+
* otherwise the resource cache (which is keyed by path for the lifetime of
|
|
45
|
+
* the app) would keep serving the first payload and revalidate it over `/api`.
|
|
46
|
+
*/
|
|
47
|
+
hydrate(initialState) {
|
|
48
|
+
const store = this.store.getValue();
|
|
36
49
|
const now = Date.now();
|
|
37
|
-
|
|
50
|
+
let changed = false;
|
|
51
|
+
for (const [variantKey, data] of Object.entries(initialState ?? {})) {
|
|
52
|
+
if (!data) continue;
|
|
53
|
+
const current = store.get(variantKey);
|
|
54
|
+
if (current?.loading) continue;
|
|
55
|
+
if (current && current.data === data) continue;
|
|
38
56
|
store.set(variantKey, {
|
|
39
57
|
loading: false,
|
|
40
58
|
data,
|
|
41
|
-
error: null
|
|
59
|
+
error: null,
|
|
60
|
+
version: now
|
|
42
61
|
});
|
|
62
|
+
this.staleVariants.delete(variantKey);
|
|
43
63
|
this.lastFetchRecord.set(variantKey, now);
|
|
64
|
+
changed = true;
|
|
44
65
|
}
|
|
45
|
-
this.store
|
|
66
|
+
if (changed) this.store.next(store);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The cached state for a variant, or `undefined` — a plain read that never
|
|
70
|
+
* fetches and never revalidates.
|
|
71
|
+
*
|
|
72
|
+
* `getVariant` is the read that keeps the cache honest, and it starts a
|
|
73
|
+
* request when it has to. That makes it the wrong thing to call while
|
|
74
|
+
* rendering: React throws away a render whose subtree suspends and retries
|
|
75
|
+
* it, so every discarded attempt would leak a request. Renders read with
|
|
76
|
+
* this; effects, which only run for a render that committed, use
|
|
77
|
+
* `getVariant`.
|
|
78
|
+
*/
|
|
79
|
+
peek(variantKey) {
|
|
80
|
+
return this.store.getValue().get(variantKey);
|
|
46
81
|
}
|
|
47
|
-
getVariant(variantKey) {
|
|
82
|
+
getVariant(variantKey, staleTime = DEFAULT_STALE_TIME) {
|
|
48
83
|
const store = this.store.getValue();
|
|
49
84
|
if (!store.has(variantKey)) this.resolveVariant(variantKey);
|
|
50
85
|
else {
|
|
@@ -57,7 +92,7 @@ var QueryResource = class {
|
|
|
57
92
|
if (variant.data) {
|
|
58
93
|
const stale = this.staleVariants.has(variantKey);
|
|
59
94
|
const now = Date.now();
|
|
60
|
-
const old = now - (this.lastFetchRecord.get(variantKey) ?? now)
|
|
95
|
+
const old = now - (this.lastFetchRecord.get(variantKey) ?? now) >= staleTime;
|
|
61
96
|
if (stale || old) {
|
|
62
97
|
this.lastFetchRecord.set(variantKey, now);
|
|
63
98
|
this.resolveVariant(variantKey, true);
|
|
@@ -141,16 +176,37 @@ var QueryResource = class {
|
|
|
141
176
|
};
|
|
142
177
|
//#endregion
|
|
143
178
|
//#region client/QueryManagerContext.tsx
|
|
144
|
-
var QueryManagerContext = createContext({
|
|
145
|
-
|
|
146
|
-
|
|
179
|
+
var QueryManagerContext = createContext({
|
|
180
|
+
getResource: (key, initialState = {}) => {
|
|
181
|
+
return new QueryResource(key, initialState);
|
|
182
|
+
},
|
|
183
|
+
hydrate: () => {}
|
|
184
|
+
});
|
|
147
185
|
var QueryManagerProvider = ({ children }) => {
|
|
148
186
|
const resourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
187
|
+
const getResource = useCallback((key, initialState) => {
|
|
188
|
+
let resource = resourcesRef.current.get(key);
|
|
189
|
+
if (!resource) {
|
|
190
|
+
resource = new QueryResource(key, initialState ?? {});
|
|
191
|
+
resourcesRef.current.set(key, resource);
|
|
192
|
+
}
|
|
193
|
+
return resource;
|
|
194
|
+
}, []);
|
|
195
|
+
const hydrate = useCallback((prefetchedData) => {
|
|
196
|
+
if (!prefetchedData) return;
|
|
197
|
+
for (const [key, initialState] of Object.entries(prefetchedData)) {
|
|
198
|
+
if (!initialState || typeof initialState !== "object") continue;
|
|
199
|
+
const resource = resourcesRef.current.get(key);
|
|
200
|
+
if (resource) resource.hydrate(initialState);
|
|
201
|
+
else resourcesRef.current.set(key, new QueryResource(key, initialState));
|
|
202
|
+
}
|
|
203
|
+
}, []);
|
|
204
|
+
const value = useMemo(() => ({
|
|
205
|
+
getResource,
|
|
206
|
+
hydrate
|
|
207
|
+
}), [getResource, hydrate]);
|
|
149
208
|
return /* @__PURE__ */ jsx(QueryManagerContext.Provider, {
|
|
150
|
-
value
|
|
151
|
-
if (!resourcesRef.current.has(key)) resourcesRef.current.set(key, new QueryResource(key, initialState ?? {}));
|
|
152
|
-
return resourcesRef.current.get(key);
|
|
153
|
-
} },
|
|
209
|
+
value,
|
|
154
210
|
children
|
|
155
211
|
});
|
|
156
212
|
};
|
|
@@ -213,6 +269,7 @@ var defaultConfig = {
|
|
|
213
269
|
keepPreviousData: true,
|
|
214
270
|
retryIntervalOnError: 1e4,
|
|
215
271
|
refreshInterval: 999999,
|
|
272
|
+
staleTime: DEFAULT_STALE_TIME,
|
|
216
273
|
debug: false,
|
|
217
274
|
lazy: false
|
|
218
275
|
};
|
|
@@ -264,22 +321,23 @@ function useQuery(url, ...args) {
|
|
|
264
321
|
error: null,
|
|
265
322
|
version: 0
|
|
266
323
|
};
|
|
267
|
-
return resource.
|
|
324
|
+
return resource.peek(variantKey);
|
|
268
325
|
});
|
|
269
326
|
const retry = useCallback((vk) => {
|
|
270
327
|
if (!retryingMap.current.get(vk)) {
|
|
271
328
|
if (configRef.current.debug) console.log("retrying", vk);
|
|
272
329
|
retryingMap.current.set(vk, true);
|
|
273
330
|
retryIntervalRef.current = setTimeout(() => {
|
|
274
|
-
resource.getVariant(vk);
|
|
331
|
+
resource.getVariant(vk, configRef.current.staleTime);
|
|
275
332
|
retryingMap.current.set(vk, false);
|
|
276
333
|
}, configRef.current.retryIntervalOnError);
|
|
277
334
|
}
|
|
278
335
|
}, [resource]);
|
|
279
336
|
useEffect(() => {
|
|
280
337
|
if (paramsKey !== paramsRef.current) {
|
|
281
|
-
|
|
282
|
-
|
|
338
|
+
const nextResource = getResource(normalPath, fallbackData);
|
|
339
|
+
setResource(nextResource);
|
|
340
|
+
if (fetchedRef.current) setState(nextResource.getVariant(variantKey, configRef.current.staleTime));
|
|
283
341
|
paramsRef.current = paramsKey;
|
|
284
342
|
}
|
|
285
343
|
}, [
|
|
@@ -287,11 +345,11 @@ function useQuery(url, ...args) {
|
|
|
287
345
|
normalPath,
|
|
288
346
|
variantKey,
|
|
289
347
|
getResource,
|
|
290
|
-
|
|
348
|
+
fallbackData
|
|
291
349
|
]);
|
|
292
350
|
const handleReload = useCallback(() => {
|
|
293
351
|
if (configRef.current.debug) console.log("Reloading query for", variantKey);
|
|
294
|
-
const data = resource.getVariant(variantKey).data;
|
|
352
|
+
const data = resource.getVariant(variantKey, configRef.current.staleTime).data;
|
|
295
353
|
resource.mutate(variantKey, () => data);
|
|
296
354
|
}, [variantKey, resource]);
|
|
297
355
|
useEffect(() => {
|
|
@@ -337,7 +395,7 @@ function useQuery(url, ...args) {
|
|
|
337
395
|
resource
|
|
338
396
|
]);
|
|
339
397
|
useEffect(() => {
|
|
340
|
-
if (fetchedRef.current) handleStateUpdate(resource.getVariant(variantKey));
|
|
398
|
+
if (fetchedRef.current) handleStateUpdate(resource.getVariant(variantKey, configRef.current.staleTime));
|
|
341
399
|
const unsub = resource.store.subscribe((store) => {
|
|
342
400
|
const variant = store.get(variantKey);
|
|
343
401
|
if (variant) handleStateUpdate(variant);
|
|
@@ -2610,6 +2668,7 @@ var WebSocketContextProvider = (props) => {
|
|
|
2610
2668
|
//#endregion
|
|
2611
2669
|
//#region client/Head.tsx
|
|
2612
2670
|
function updateMeta(meta) {
|
|
2671
|
+
if (!meta) return;
|
|
2613
2672
|
const { title, description } = meta;
|
|
2614
2673
|
if (title) document.title = title;
|
|
2615
2674
|
if (description) {
|
|
@@ -2745,6 +2804,66 @@ function useTheme() {
|
|
|
2745
2804
|
return context;
|
|
2746
2805
|
}
|
|
2747
2806
|
//#endregion
|
|
2807
|
+
//#region utils/partialRender.ts
|
|
2808
|
+
/**
|
|
2809
|
+
* Route the client is currently rendering, sent on `.json` navigations so the
|
|
2810
|
+
* server can skip the handlers of the segments that route already has mounted.
|
|
2811
|
+
* Value is a locale-less pathname plus search, e.g. `/app/A/chat?tab=2`.
|
|
2812
|
+
*/
|
|
2813
|
+
var PARTIAL_RENDER_HEADER = "x-gemi-from";
|
|
2814
|
+
/**
|
|
2815
|
+
* The `x-gemi-from` value for the route the client starts on.
|
|
2816
|
+
*
|
|
2817
|
+
* On the first render the router's `pathname` is still the route *pattern* the
|
|
2818
|
+
* server matched — it only becomes a resolved path once the history listener
|
|
2819
|
+
* has run — so this has to apply the params. Sending `/app/:orgId/chat` names
|
|
2820
|
+
* no route the server can resolve, and the first navigation after every full
|
|
2821
|
+
* page load would skip nothing.
|
|
2822
|
+
*/
|
|
2823
|
+
function initialRenderedRoute(route) {
|
|
2824
|
+
return `${applyParams$1(route.pathname ?? "/", route.params ?? {}) || "/"}${route.search ?? ""}`;
|
|
2825
|
+
}
|
|
2826
|
+
//#endregion
|
|
2827
|
+
//#region client/helpers/mergeCarriedSegments.ts
|
|
2828
|
+
/**
|
|
2829
|
+
* A partially rendered response only carries the segments the server actually
|
|
2830
|
+
* ran. Everything is keyed by the *new* pathname, so a carried layout would
|
|
2831
|
+
* render with empty props unless the data it already had is copied across.
|
|
2832
|
+
*
|
|
2833
|
+
* Data the server sent always wins: a carried view is only filled in where the
|
|
2834
|
+
* response has nothing for it.
|
|
2835
|
+
*/
|
|
2836
|
+
function mergeCarriedSegments(previous, next, carriedViews) {
|
|
2837
|
+
if (carriedViews.length === 0) return {
|
|
2838
|
+
data: next.data,
|
|
2839
|
+
breadcrumbs: next.breadcrumbs
|
|
2840
|
+
};
|
|
2841
|
+
const previousData = previous.data ?? {};
|
|
2842
|
+
const previousViewData = previousData[previous.pathname] ?? previousData[Object.keys(previousData)[0]] ?? {};
|
|
2843
|
+
const previousBreadcrumbs = previous.breadcrumbs ?? {};
|
|
2844
|
+
const carriedViewData = {};
|
|
2845
|
+
const carriedBreadcrumbs = {};
|
|
2846
|
+
for (const viewPath of carriedViews) {
|
|
2847
|
+
if (viewPath in previousViewData) carriedViewData[viewPath] = previousViewData[viewPath];
|
|
2848
|
+
const previousKey = `${viewPath}:${previous.routePath}`;
|
|
2849
|
+
if (previousKey in previousBreadcrumbs) carriedBreadcrumbs[`${viewPath}:${next.routePath}`] = previousBreadcrumbs[previousKey];
|
|
2850
|
+
}
|
|
2851
|
+
const [nextKey = next.pathname] = Object.keys(next.data ?? {});
|
|
2852
|
+
return {
|
|
2853
|
+
data: {
|
|
2854
|
+
...next.data,
|
|
2855
|
+
[nextKey]: {
|
|
2856
|
+
...carriedViewData,
|
|
2857
|
+
...next.data?.[nextKey]
|
|
2858
|
+
}
|
|
2859
|
+
},
|
|
2860
|
+
breadcrumbs: {
|
|
2861
|
+
...carriedBreadcrumbs,
|
|
2862
|
+
...next.breadcrumbs
|
|
2863
|
+
}
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2866
|
+
//#endregion
|
|
2748
2867
|
//#region client/ClientRouter.tsx
|
|
2749
2868
|
function restoreScroll(action = null, _pathname = "no path") {
|
|
2750
2869
|
if (action === null) return;
|
|
@@ -2811,6 +2930,7 @@ var Routes = (props) => {
|
|
|
2811
2930
|
const [isPending, startTransition] = useTransition();
|
|
2812
2931
|
const [isFetching, setIsFetching] = useState(false);
|
|
2813
2932
|
const { routerSubject, fetchRouteCSS } = useContext(ClientRouterContext);
|
|
2933
|
+
const { hydrate } = useContext(QueryManagerContext);
|
|
2814
2934
|
const [transitionPath, setTransitionPath] = useState([null, routerSubject?.getValue().pathname]);
|
|
2815
2935
|
const { breadcrumbs, pageData, i18n, prefetchedData, appId: currentAppId } = useContext(ServerDataContext);
|
|
2816
2936
|
const [routeState, setRouteState] = useState({
|
|
@@ -2830,6 +2950,10 @@ var Routes = (props) => {
|
|
|
2830
2950
|
appId: currentAppId
|
|
2831
2951
|
});
|
|
2832
2952
|
const { replace } = useNavigate();
|
|
2953
|
+
useEffect(() => {
|
|
2954
|
+
hydrate(prefetchedData);
|
|
2955
|
+
}, [hydrate, prefetchedData]);
|
|
2956
|
+
const renderedRouteRef = useRef(initialRenderedRoute(routeState));
|
|
2833
2957
|
useEffect(() => {
|
|
2834
2958
|
return routerSubject?.subscribe(async (routerState) => {
|
|
2835
2959
|
const { pathname, search, state, views } = routerState;
|
|
@@ -2853,6 +2977,7 @@ var Routes = (props) => {
|
|
|
2853
2977
|
}
|
|
2854
2978
|
const localeSegment = routerState.locale ? `/${routerState.locale}` : "";
|
|
2855
2979
|
const url = `${`${localeSegment}${localeSegment.length > 0 && pathname === "/" ? "" : pathname}`}.json${search}`;
|
|
2980
|
+
const from = renderedRouteRef.current;
|
|
2856
2981
|
setIsFetching(true);
|
|
2857
2982
|
let res = {
|
|
2858
2983
|
ok: false,
|
|
@@ -2860,7 +2985,7 @@ var Routes = (props) => {
|
|
|
2860
2985
|
};
|
|
2861
2986
|
try {
|
|
2862
2987
|
res = (await Promise.all([
|
|
2863
|
-
fetch(url),
|
|
2988
|
+
fetch(url, { headers: { [PARTIAL_RENDER_HEADER]: from } }),
|
|
2864
2989
|
fetchRouteCSS(pathname),
|
|
2865
2990
|
...views.map((component) => {
|
|
2866
2991
|
if (!window?.loaders) return Promise.resolve();
|
|
@@ -2871,7 +2996,15 @@ var Routes = (props) => {
|
|
|
2871
2996
|
console.error(e);
|
|
2872
2997
|
}
|
|
2873
2998
|
if (res.ok) {
|
|
2874
|
-
|
|
2999
|
+
let payload = await res.json();
|
|
3000
|
+
const claimed = payload.partial ?? null;
|
|
3001
|
+
if (claimed && claimed.from !== renderedRouteRef.current) try {
|
|
3002
|
+
const full = await fetch(url);
|
|
3003
|
+
if (full.ok) payload = await full.json();
|
|
3004
|
+
} catch (e) {
|
|
3005
|
+
console.error(e);
|
|
3006
|
+
}
|
|
3007
|
+
const { data, i18n, prefetchedData, breadcrumbs, meta, directive = {}, is404 = false, appId } = payload;
|
|
2875
3008
|
updateMeta(meta);
|
|
2876
3009
|
if (directive?.kind === "Redirect") {
|
|
2877
3010
|
if (directive?.path) replace(directive.path, { params: {} });
|
|
@@ -2884,15 +3017,22 @@ var Routes = (props) => {
|
|
|
2884
3017
|
views: ["404"]
|
|
2885
3018
|
}));
|
|
2886
3019
|
});
|
|
3020
|
+
const carriedViews = payload.partial?.carriedViews ?? [];
|
|
3021
|
+
renderedRouteRef.current = `${pathname}${search}`;
|
|
3022
|
+
hydrate(prefetchedData);
|
|
2887
3023
|
startTransition(() => {
|
|
2888
|
-
setRouteState({
|
|
3024
|
+
setRouteState((state) => ({
|
|
2889
3025
|
...routerState,
|
|
2890
3026
|
appId,
|
|
2891
|
-
data,
|
|
2892
3027
|
i18n,
|
|
2893
3028
|
prefetchedData,
|
|
2894
|
-
|
|
2895
|
-
|
|
3029
|
+
...mergeCarriedSegments(state, {
|
|
3030
|
+
pathname,
|
|
3031
|
+
routePath: routerState.routePath,
|
|
3032
|
+
data,
|
|
3033
|
+
breadcrumbs
|
|
3034
|
+
}, carriedViews)
|
|
3035
|
+
}));
|
|
2896
3036
|
});
|
|
2897
3037
|
}
|
|
2898
3038
|
setIsFetching(false);
|
|
@@ -2900,7 +3040,8 @@ var Routes = (props) => {
|
|
|
2900
3040
|
}, [
|
|
2901
3041
|
routerSubject,
|
|
2902
3042
|
fetchRouteCSS,
|
|
2903
|
-
replace
|
|
3043
|
+
replace,
|
|
3044
|
+
hydrate
|
|
2904
3045
|
]);
|
|
2905
3046
|
return /* @__PURE__ */ jsx(RouteTransitionProvider, {
|
|
2906
3047
|
isPending,
|