@aihu/app 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/client.d.ts +21 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm install @aihu/app
|
|
|
21
21
|
bun add @aihu/app
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
24
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
25
25
|
|
|
26
26
|
<!-- END_AUTOGEN: install -->
|
|
27
27
|
|
|
@@ -32,13 +32,13 @@ bun add @aihu/app
|
|
|
32
32
|
|
|
33
33
|
| | |
|
|
34
34
|
|---|---|
|
|
35
|
-
| **Version** | `0.1.
|
|
35
|
+
| **Version** | `0.1.3` |
|
|
36
36
|
| **Tier** | B — Meta-framework — top-level integration of runtime, router, adapter |
|
|
37
|
-
| **Bundle size** |
|
|
37
|
+
| **Bundle size** | 800 B (gz) — limit 800 B |
|
|
38
38
|
| **Published files** | 3 entries |
|
|
39
39
|
| **License** | MIT |
|
|
40
40
|
|
|
41
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
41
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
42
42
|
|
|
43
43
|
<!-- END_AUTOGEN: stats -->
|
|
44
44
|
|
|
@@ -52,7 +52,7 @@ bun add @aihu/app
|
|
|
52
52
|
| `.` | `./dist/index.js` | `—` |
|
|
53
53
|
| `./client` | `./dist/client.js` | `—` |
|
|
54
54
|
|
|
55
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
55
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
56
56
|
|
|
57
57
|
<!-- END_AUTOGEN: exports -->
|
|
58
58
|
|
|
@@ -69,7 +69,7 @@ bun add @aihu/app
|
|
|
69
69
|
- `@aihu/signals` — `workspace:*`
|
|
70
70
|
- `vite` — `>=5.0.0`
|
|
71
71
|
|
|
72
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
72
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
73
73
|
|
|
74
74
|
<!-- END_AUTOGEN: deps -->
|
|
75
75
|
|
|
@@ -83,7 +83,7 @@ bun add @aihu/app
|
|
|
83
83
|
- [@aihu/adapter-cloudflare](../adapter-cloudflare)
|
|
84
84
|
- [Aihu framework root](../../README.md)
|
|
85
85
|
|
|
86
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
86
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
87
87
|
|
|
88
88
|
<!-- END_AUTOGEN: see-also -->
|
|
89
89
|
|
|
@@ -94,6 +94,6 @@ bun add @aihu/app
|
|
|
94
94
|
|
|
95
95
|
MIT — see [LICENSE](../../LICENSE).
|
|
96
96
|
|
|
97
|
-
<sub><i>Auto-generated against `@aihu/app@0.1.
|
|
97
|
+
<sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
|
|
98
98
|
|
|
99
99
|
<!-- END_AUTOGEN: license -->
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
//#region src/client.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Rendering mode passed from the server config into the client bootstrap.
|
|
4
|
+
* Inlined here to avoid importing @aihu/server into the client bundle.
|
|
5
|
+
* Must stay in sync with RenderingMode in @aihu/server.
|
|
6
|
+
*/
|
|
7
|
+
type AppRenderingMode = 'ssr' | 'spa' | 'hybrid';
|
|
2
8
|
/** Inline runtime configuration accepted by createApp(). All fields optional. */
|
|
3
9
|
interface AppConfig {
|
|
4
10
|
/** Id of the outlet element in index.html. Default: 'outlet' */
|
|
@@ -12,6 +18,20 @@ interface AppConfig {
|
|
|
12
18
|
* createApp({ provide: { supabase, checkAuth } })
|
|
13
19
|
*/
|
|
14
20
|
provide?: Record<string, unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Rendering mode from the server config. Controls whether the client
|
|
23
|
+
* wires the hydration function into the runtime.
|
|
24
|
+
*
|
|
25
|
+
* - 'ssr' | 'hybrid' (default): wires _setHydrate so the client can
|
|
26
|
+
* take over from server-rendered HTML without re-creating DOM.
|
|
27
|
+
* - 'spa': skips _setHydrate — no SSR HTML to hydrate, mount-only.
|
|
28
|
+
*
|
|
29
|
+
* Pass `defineAihuConfig(…).rendering?.mode` from your server config.
|
|
30
|
+
* Default: 'ssr' (hydration wired).
|
|
31
|
+
*/
|
|
32
|
+
rendering?: {
|
|
33
|
+
mode?: AppRenderingMode;
|
|
34
|
+
};
|
|
15
35
|
}
|
|
16
36
|
/**
|
|
17
37
|
* Bootstrap the aihu SPA.
|
|
@@ -28,5 +48,5 @@ interface AppConfig {
|
|
|
28
48
|
*/
|
|
29
49
|
declare function createApp(config?: AppConfig): void;
|
|
30
50
|
//#endregion
|
|
31
|
-
export { AppConfig, createApp };
|
|
51
|
+
export { AppConfig, AppRenderingMode, createApp };
|
|
32
52
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;AAYA;;;;KAAY,gBAAA;AAGZ;AAAA,UAAiB,SAAA;;EAEf,QAAA;EAAA;;;;;;;;EASA,OAAA,GAAU,MAAA;EA4Ba;;;;;;;;;;;EAhBvB,SAAA;IAAc,IAAA,GAAO,gBAAA;EAAA;AAAA;;;;;;;;;;;;;;iBAgBP,SAAA,CAAU,MAAA,GAAS,SAAA"}
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"virtual:aihu-routes";import{mount as
|
|
1
|
+
import e from"virtual:aihu-routes";import{hydrate as t,mount as n}from"@aihu/arbor";import{createRouter as r}from"@aihu/router";import{_setHydrate as i,_setMount as a,_setSignal as o}from"@aihu/runtime";import{signal as s}from"@aihu/signals";function c(c){c?.provide&&Object.assign(globalThis,c.provide),a(n),o(s),c?.rendering?.mode!==`spa`&&i(t);let l=c?.outletId??`outlet`,u=document.getElementById(l);if(!u)throw Error(`@aihu/app: no element with id="${l}" found. Add <div id="${l}"></div> to your index.html`);let d=u,f=r(e);async function p(t){if(!t){let t=e.find(e=>e.pattern===`*`||e.name===`not-found`);if(t){await t.module();let e=t.name;if(e?.includes(`-`)){d.replaceChildren(document.createElement(e));return}}let n=document.createElement(`p`);n.style.cssText=`font-family:system-ui;padding:2rem;color:#888`,n.textContent=`404 — page not found`,d.replaceChildren(n);return}await t.route.module();let n=t.route.name;if(!n?.includes(`-`))return;let r=document.createElement(n);if(t.params)for(let[e,n]of Object.entries(t.params))r.setAttribute(e,String(n));d.replaceChildren(r)}p(f.match(location.pathname)),document.addEventListener(`click`,e=>{let t=e.target.closest(`a`);if(!t)return;let n=t.getAttribute(`href`);!n||n.startsWith(`http`)||n.startsWith(`//`)||n.startsWith(`mailto:`)||(e.preventDefault(),history.pushState({},``,n),p(f.match(location.pathname)))}),window.addEventListener(`popstate`,()=>{p(f.match(location.pathname))})}export{c as createApp};
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import routes from 'virtual:aihu-routes'\nimport { mount } from '@aihu/arbor'\nimport type { MatchResult, RouteDefinition } from '@aihu/router'\nimport { createRouter } from '@aihu/router'\nimport { _setMount, _setSignal } from '@aihu/runtime'\nimport { signal } from '@aihu/signals'\n\n/** Inline runtime configuration accepted by createApp(). All fields optional. */\nexport interface AppConfig {\n /** Id of the outlet element in index.html. Default: 'outlet' */\n outletId?: string\n /**\n * App-level values hoisted into globalThis before any component runs.\n * Use this for singletons (db clients, auth helpers, i18n) that are\n * referenced as bare identifiers inside @state blocks.\n *\n * @example\n * createApp({ provide: { supabase, checkAuth } })\n */\n provide?: Record<string, unknown>\n}\n\n/**\n * Bootstrap the aihu SPA.\n *\n * - Wires the aihu runtime (mount + signal) — idempotent if called multiple times\n * - Creates the router from virtual:aihu-routes\n * - Renders the current route\n * - Installs SPA click interception and popstate listeners\n *\n * @example\n * // src/main.ts\n * import { createApp } from '@aihu/app/client'\n * createApp()\n */\nexport function createApp(config?: AppConfig): void {\n // Hoist provided values into globalThis before any component runs so that\n // @state blocks can reference them as bare identifiers.\n if (config?.provide) {\n Object.assign(globalThis, config.provide)\n }\n\n // Wire runtime — null-guarded in @aihu/runtime, safe to call multiple times\n _setMount(mount)\n _setSignal(signal as Parameters<typeof _setSignal>[0])\n\n const outletId = config?.outletId ?? 'outlet'\n const outletEl = document.getElementById(outletId)\n if (!outletEl) {\n throw new Error(\n `@aihu/app: no element with id=\"${outletId}\" found. Add <div id=\"${outletId}\"></div> to your index.html`,\n )\n }\n const outlet: HTMLElement = outletEl\n\n const router = createRouter(routes)\n\n async function render(match: MatchResult | null): Promise<void> {\n if (!match) {\n // Check for a 404/not-found route by convention before falling back inline\n const notFoundRoute = (routes as RouteDefinition[]).find(\n (r) => r.pattern === '*' || r.name === 'not-found',\n )\n if (notFoundRoute) {\n await notFoundRoute.module()\n const tag = notFoundRoute.name\n if (tag?.includes('-')) {\n outlet.replaceChildren(document.createElement(tag))\n return\n }\n }\n // Inline fallback 404\n const p = document.createElement('p')\n p.style.cssText = 'font-family:system-ui;padding:2rem;color:#888'\n p.textContent = '404 — page not found'\n outlet.replaceChildren(p)\n return\n }\n\n // Import the page module — registers its custom element + auto-wires runtime\n await match.route.module()\n const tag = match.route.name\n if (!tag?.includes('-')) return\n\n const el = document.createElement(tag)\n\n // Flat per-attribute route params (A4 protocol — replaces JSON route attribute)\n if (match.params) {\n for (const [key, val] of Object.entries(match.params)) {\n el.setAttribute(key, String(val))\n }\n }\n\n outlet.replaceChildren(el)\n }\n\n // Initial render\n render(router.match(location.pathname))\n\n // SPA click interception — handles <a> links within the app\n document.addEventListener('click', (e) => {\n const a = (e.target as Element).closest('a') as HTMLAnchorElement | null\n if (!a) return\n const href = a.getAttribute('href')\n if (!href || href.startsWith('http') || href.startsWith('//') || href.startsWith('mailto:'))\n return\n e.preventDefault()\n history.pushState({}, '', href)\n render(router.match(location.pathname))\n })\n\n // Browser back/forward\n window.addEventListener('popstate', () => {\n render(router.match(location.pathname))\n })\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import routes from 'virtual:aihu-routes'\nimport { hydrate, mount } from '@aihu/arbor'\nimport type { MatchResult, RouteDefinition } from '@aihu/router'\nimport { createRouter } from '@aihu/router'\nimport { _setHydrate, _setMount, _setSignal } from '@aihu/runtime'\nimport { signal } from '@aihu/signals'\n\n/**\n * Rendering mode passed from the server config into the client bootstrap.\n * Inlined here to avoid importing @aihu/server into the client bundle.\n * Must stay in sync with RenderingMode in @aihu/server.\n */\nexport type AppRenderingMode = 'ssr' | 'spa' | 'hybrid'\n\n/** Inline runtime configuration accepted by createApp(). All fields optional. */\nexport interface AppConfig {\n /** Id of the outlet element in index.html. Default: 'outlet' */\n outletId?: string\n /**\n * App-level values hoisted into globalThis before any component runs.\n * Use this for singletons (db clients, auth helpers, i18n) that are\n * referenced as bare identifiers inside @state blocks.\n *\n * @example\n * createApp({ provide: { supabase, checkAuth } })\n */\n provide?: Record<string, unknown>\n /**\n * Rendering mode from the server config. Controls whether the client\n * wires the hydration function into the runtime.\n *\n * - 'ssr' | 'hybrid' (default): wires _setHydrate so the client can\n * take over from server-rendered HTML without re-creating DOM.\n * - 'spa': skips _setHydrate — no SSR HTML to hydrate, mount-only.\n *\n * Pass `defineAihuConfig(…).rendering?.mode` from your server config.\n * Default: 'ssr' (hydration wired).\n */\n rendering?: { mode?: AppRenderingMode }\n}\n\n/**\n * Bootstrap the aihu SPA.\n *\n * - Wires the aihu runtime (mount + signal) — idempotent if called multiple times\n * - Creates the router from virtual:aihu-routes\n * - Renders the current route\n * - Installs SPA click interception and popstate listeners\n *\n * @example\n * // src/main.ts\n * import { createApp } from '@aihu/app/client'\n * createApp()\n */\nexport function createApp(config?: AppConfig): void {\n // Hoist provided values into globalThis before any component runs so that\n // @state blocks can reference them as bare identifiers.\n if (config?.provide) {\n Object.assign(globalThis, config.provide)\n }\n\n // Wire runtime — null-guarded in @aihu/runtime, safe to call multiple times\n _setMount(mount)\n _setSignal(signal as Parameters<typeof _setSignal>[0])\n if (config?.rendering?.mode !== 'spa') {\n _setHydrate(hydrate as Parameters<typeof _setHydrate>[0])\n }\n\n const outletId = config?.outletId ?? 'outlet'\n const outletEl = document.getElementById(outletId)\n if (!outletEl) {\n throw new Error(\n `@aihu/app: no element with id=\"${outletId}\" found. Add <div id=\"${outletId}\"></div> to your index.html`,\n )\n }\n const outlet: HTMLElement = outletEl\n\n const router = createRouter(routes)\n\n async function render(match: MatchResult | null): Promise<void> {\n if (!match) {\n // Check for a 404/not-found route by convention before falling back inline\n const notFoundRoute = (routes as RouteDefinition[]).find(\n (r) => r.pattern === '*' || r.name === 'not-found',\n )\n if (notFoundRoute) {\n await notFoundRoute.module()\n const tag = notFoundRoute.name\n if (tag?.includes('-')) {\n outlet.replaceChildren(document.createElement(tag))\n return\n }\n }\n // Inline fallback 404\n const p = document.createElement('p')\n p.style.cssText = 'font-family:system-ui;padding:2rem;color:#888'\n p.textContent = '404 — page not found'\n outlet.replaceChildren(p)\n return\n }\n\n // Import the page module — registers its custom element + auto-wires runtime\n await match.route.module()\n const tag = match.route.name\n if (!tag?.includes('-')) return\n\n const el = document.createElement(tag)\n\n // Flat per-attribute route params (A4 protocol — replaces JSON route attribute)\n if (match.params) {\n for (const [key, val] of Object.entries(match.params)) {\n el.setAttribute(key, String(val))\n }\n }\n\n outlet.replaceChildren(el)\n }\n\n // Initial render\n render(router.match(location.pathname))\n\n // SPA click interception — handles <a> links within the app\n document.addEventListener('click', (e) => {\n const a = (e.target as Element).closest('a') as HTMLAnchorElement | null\n if (!a) return\n const href = a.getAttribute('href')\n if (!href || href.startsWith('http') || href.startsWith('//') || href.startsWith('mailto:'))\n return\n e.preventDefault()\n history.pushState({}, '', href)\n render(router.match(location.pathname))\n })\n\n // Browser back/forward\n window.addEventListener('popstate', () => {\n render(router.match(location.pathname))\n })\n}\n"],"mappings":"kPAsDA,SAAgB,EAAU,EAA0B,CAG9C,GAAQ,SACV,OAAO,OAAO,WAAY,EAAO,QAAQ,CAI3C,EAAU,EAAM,CAChB,EAAW,EAA2C,CAClD,GAAQ,WAAW,OAAS,OAC9B,EAAY,EAA6C,CAG3D,IAAM,EAAW,GAAQ,UAAY,SAC/B,EAAW,SAAS,eAAe,EAAS,CAClD,GAAI,CAAC,EACH,MAAU,MACR,kCAAkC,EAAS,wBAAwB,EAAS,6BAC7E,CAEH,IAAM,EAAsB,EAEtB,EAAS,EAAa,EAAO,CAEnC,eAAe,EAAO,EAA0C,CAC9D,GAAI,CAAC,EAAO,CAEV,IAAM,EAAiB,EAA6B,KACjD,GAAM,EAAE,UAAY,KAAO,EAAE,OAAS,YACxC,CACD,GAAI,EAAe,CACjB,MAAM,EAAc,QAAQ,CAC5B,IAAM,EAAM,EAAc,KAC1B,GAAI,GAAK,SAAS,IAAI,CAAE,CACtB,EAAO,gBAAgB,SAAS,cAAc,EAAI,CAAC,CACnD,QAIJ,IAAM,EAAI,SAAS,cAAc,IAAI,CACrC,EAAE,MAAM,QAAU,gDAClB,EAAE,YAAc,uBAChB,EAAO,gBAAgB,EAAE,CACzB,OAIF,MAAM,EAAM,MAAM,QAAQ,CAC1B,IAAM,EAAM,EAAM,MAAM,KACxB,GAAI,CAAC,GAAK,SAAS,IAAI,CAAE,OAEzB,IAAM,EAAK,SAAS,cAAc,EAAI,CAGtC,GAAI,EAAM,OACR,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAM,OAAO,CACnD,EAAG,aAAa,EAAK,OAAO,EAAI,CAAC,CAIrC,EAAO,gBAAgB,EAAG,CAI5B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,CAGvC,SAAS,iBAAiB,QAAU,GAAM,CACxC,IAAM,EAAK,EAAE,OAAmB,QAAQ,IAAI,CAC5C,GAAI,CAAC,EAAG,OACR,IAAM,EAAO,EAAE,aAAa,OAAO,CAC/B,CAAC,GAAQ,EAAK,WAAW,OAAO,EAAI,EAAK,WAAW,KAAK,EAAI,EAAK,WAAW,UAAU,GAE3F,EAAE,gBAAgB,CAClB,QAAQ,UAAU,EAAE,CAAE,GAAI,EAAK,CAC/B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,GACvC,CAGF,OAAO,iBAAiB,eAAkB,CACxC,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,EACvC"}
|