everything-dev 0.1.4 → 0.2.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/src/ui/head.ts ADDED
@@ -0,0 +1,65 @@
1
+ import type { ClientRuntimeConfig } from "../types";
2
+ import type { HeadScript } from "./types";
3
+
4
+ export interface RemoteScriptsOptions {
5
+ assetsUrl: string;
6
+ runtimeConfig?: ClientRuntimeConfig;
7
+ containerName?: string;
8
+ hydratePath?: string;
9
+ }
10
+
11
+ export function getRemoteEntryScript(assetsUrl: string): HeadScript {
12
+ return {
13
+ src: `${assetsUrl}/remoteEntry.js`,
14
+ };
15
+ }
16
+
17
+ export function getThemeInitScript(): HeadScript {
18
+ return {
19
+ children: `(function(){var t=localStorage.getItem('theme');if(t==='dark'||(!t&&window.matchMedia('(prefers-color-scheme: dark)').matches)){document.documentElement.classList.add('dark');}})();`,
20
+ };
21
+ }
22
+
23
+ export function getHydrateScript(
24
+ runtimeConfig: ClientRuntimeConfig | undefined,
25
+ containerName = "ui",
26
+ hydratePath = "./Hydrate"
27
+ ): HeadScript {
28
+ return {
29
+ children: `
30
+ window.__RUNTIME_CONFIG__=${JSON.stringify(runtimeConfig)};
31
+ function __hydrate(){
32
+ var container = window['${containerName}'];
33
+ if (!container) { console.error('[Hydrate] Container not found'); return; }
34
+ container.init({}).then(function(){
35
+ return container.get('${hydratePath}');
36
+ }).then(function(mod){
37
+ return mod().hydrate();
38
+ }).catch(function(e){
39
+ console.error('[Hydrate] Failed:', e);
40
+ });
41
+ }
42
+ if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',__hydrate);}else{__hydrate();}
43
+ `.trim(),
44
+ };
45
+ }
46
+
47
+ export function getRemoteScripts(options: RemoteScriptsOptions): HeadScript[] {
48
+ const { assetsUrl, runtimeConfig, containerName, hydratePath } = options;
49
+
50
+ return [
51
+ getRemoteEntryScript(assetsUrl),
52
+ getThemeInitScript(),
53
+ getHydrateScript(runtimeConfig, containerName, hydratePath),
54
+ ];
55
+ }
56
+
57
+ export function getBaseStyles(): string {
58
+ return `
59
+ *, *::before, *::after { box-sizing: border-box; }
60
+ html { height: 100%; height: 100dvh; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; color-scheme: light dark; }
61
+ body { min-height: 100%; min-height: 100dvh; margin: 0; background-color: var(--background); color: var(--foreground); -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
62
+ #root { min-height: 100vh; }
63
+ @supports (min-height: 100dvh) { #root { min-height: 100dvh; } }
64
+ `.trim();
65
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./types";
2
+ export * from "./runtime";
3
+ export * from "./head";
4
+ export * from "./files";
5
+ export * from "./router";
@@ -0,0 +1,72 @@
1
+ import type { AnyRouter } from "@tanstack/react-router";
2
+ import type { HeadData, HeadLink, HeadMeta, HeadScript } from "./types";
3
+
4
+ export function getMetaKey(meta: HeadMeta): string {
5
+ if (!meta) return "null";
6
+ if ("title" in meta) return "title";
7
+ if ("charSet" in meta) return "charSet";
8
+ if ("name" in meta) return `name:${(meta as { name: string }).name}`;
9
+ if ("property" in meta) return `property:${(meta as { property: string }).property}`;
10
+ if ("httpEquiv" in meta) return `httpEquiv:${(meta as { httpEquiv: string }).httpEquiv}`;
11
+ return JSON.stringify(meta);
12
+ }
13
+
14
+ export function getLinkKey(link: HeadLink): string {
15
+ const rel = (link as { rel?: string }).rel ?? "";
16
+ const href = (link as { href?: string }).href ?? "";
17
+ return `${rel}:${href}`;
18
+ }
19
+
20
+ export function getScriptKey(script: HeadScript): string {
21
+ if (!script) return "null";
22
+ if ("src" in script && script.src) return `src:${script.src}`;
23
+ if ("children" in script && script.children)
24
+ return `children:${typeof script.children === "string" ? script.children : JSON.stringify(script.children)}`;
25
+ return JSON.stringify(script);
26
+ }
27
+
28
+ export async function collectHeadData(router: AnyRouter): Promise<HeadData> {
29
+ await router.load();
30
+
31
+ const metaMap = new Map<string, HeadMeta>();
32
+ const linkMap = new Map<string, HeadLink>();
33
+ const scriptMap = new Map<string, HeadScript>();
34
+
35
+ for (const match of router.state.matches) {
36
+ const headFn = match.route?.options?.head;
37
+ if (!headFn) continue;
38
+
39
+ try {
40
+ const headResult = await headFn({
41
+ loaderData: match.loaderData,
42
+ matches: router.state.matches,
43
+ match,
44
+ params: match.params,
45
+ } as Parameters<typeof headFn>[0]);
46
+
47
+ if (headResult?.meta) {
48
+ for (const meta of headResult.meta) {
49
+ metaMap.set(getMetaKey(meta), meta);
50
+ }
51
+ }
52
+ if (headResult?.links) {
53
+ for (const link of headResult.links) {
54
+ linkMap.set(getLinkKey(link), link);
55
+ }
56
+ }
57
+ if (headResult?.scripts) {
58
+ for (const script of headResult.scripts) {
59
+ scriptMap.set(getScriptKey(script), script);
60
+ }
61
+ }
62
+ } catch (error) {
63
+ console.warn(`[collectHeadData] head() failed for ${match.routeId}:`, error);
64
+ }
65
+ }
66
+
67
+ return {
68
+ meta: [...metaMap.values()],
69
+ links: [...linkMap.values()],
70
+ scripts: [...scriptMap.values()],
71
+ };
72
+ }
@@ -0,0 +1,35 @@
1
+ import type { ClientRuntimeConfig } from "../types";
2
+
3
+ declare global {
4
+ interface Window {
5
+ __RUNTIME_CONFIG__?: ClientRuntimeConfig;
6
+ }
7
+ }
8
+
9
+ export function getRuntimeConfig(): ClientRuntimeConfig | undefined {
10
+ if (typeof window === "undefined") return undefined;
11
+ return window.__RUNTIME_CONFIG__;
12
+ }
13
+
14
+ export function getAssetsUrl(config?: ClientRuntimeConfig): string {
15
+ const cfg = config ?? getRuntimeConfig();
16
+ return cfg?.assetsUrl ?? "";
17
+ }
18
+
19
+ export function getHostUrl(config?: ClientRuntimeConfig): string {
20
+ const cfg = config ?? getRuntimeConfig();
21
+ if (typeof window === "undefined") return "";
22
+ return cfg?.hostUrl ?? window.location.origin;
23
+ }
24
+
25
+ export function getApiBaseUrl(config?: ClientRuntimeConfig): string {
26
+ const cfg = config ?? getRuntimeConfig();
27
+ const base = cfg?.rpcBase;
28
+ if (typeof window === "undefined") return "/api/rpc";
29
+ return base ? `${window.location.origin}${base}` : `${window.location.origin}/api/rpc`;
30
+ }
31
+
32
+ export function getAccount(config?: ClientRuntimeConfig): string {
33
+ const cfg = config ?? getRuntimeConfig();
34
+ return cfg?.account ?? "every.near";
35
+ }
@@ -0,0 +1,51 @@
1
+ import type { QueryClient } from "@tanstack/react-query";
2
+ import type { AnyRouteMatch, AnyRouter, RouterHistory } from "@tanstack/react-router";
3
+ import type { ClientRuntimeConfig } from "../types";
4
+
5
+ export interface RouterContext {
6
+ queryClient: QueryClient;
7
+ assetsUrl: string;
8
+ runtimeConfig?: ClientRuntimeConfig;
9
+ }
10
+
11
+ export interface CreateRouterOptions {
12
+ history?: RouterHistory;
13
+ context?: Partial<RouterContext>;
14
+ }
15
+
16
+ export type HeadMeta = NonNullable<AnyRouteMatch["meta"]>[number];
17
+ export type HeadLink = NonNullable<AnyRouteMatch["links"]>[number];
18
+ export type HeadScript = NonNullable<AnyRouteMatch["headScripts"]>[number];
19
+
20
+ export interface HeadData {
21
+ meta: HeadMeta[];
22
+ links: HeadLink[];
23
+ scripts: HeadScript[];
24
+ }
25
+
26
+ export interface RenderOptions {
27
+ assetsUrl: string;
28
+ runtimeConfig: ClientRuntimeConfig;
29
+ }
30
+
31
+ export interface RenderResult {
32
+ stream: ReadableStream;
33
+ statusCode: number;
34
+ headers: Headers;
35
+ }
36
+
37
+ export interface RouterModule {
38
+ createRouter: (opts?: CreateRouterOptions) => {
39
+ router: AnyRouter;
40
+ queryClient: QueryClient;
41
+ };
42
+ getRouteHead: (
43
+ pathname: string,
44
+ context?: Partial<RouterContext>
45
+ ) => Promise<HeadData>;
46
+ renderToStream: (
47
+ request: Request,
48
+ options: RenderOptions
49
+ ) => Promise<RenderResult>;
50
+ routeTree: AnyRouter["routeTree"];
51
+ }