vite-plugin-vanjs 0.1.16 → 0.1.17

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/router/types.d.ts CHANGED
@@ -4,7 +4,6 @@ import type {
4
4
  Element as VElement,
5
5
  TagFunc as IsoTagFunc,
6
6
  } from "mini-van-plate/van-plate";
7
- // import van from "vanjs-core";
8
7
  import type {
9
8
  ChildDom,
10
9
  Primitive,
@@ -13,10 +12,8 @@ import type {
13
12
  PropValueOrDerived,
14
13
  State,
15
14
  } from "vanjs-core";
16
- import { LayoutFile } from "../plugin/types.d.ts";
15
+ import type { LayoutFile } from "../plugin/types.d.ts";
17
16
 
18
- // type VanElement = VElement | Exclude<Primitive, boolean | undefined>;
19
- // type DOMElement = globalThis.Element;
20
17
  type PrimitiveChild = Primitive | State<Primitive | undefined | null>;
21
18
 
22
19
  type DOMElement<T extends keyof HTMLElementTagNameMap = "div"> =
@@ -36,9 +33,7 @@ export type VanNode =
36
33
  | null
37
34
  | undefined;
38
35
 
39
- type ComponentProps1<T> =
40
- & Props
41
- & PropsWithKnownKeys<T>;
36
+ type ComponentProps1<T> = Props & PropsWithKnownKeys<T>;
42
37
 
43
38
  type ComponentProps<K extends keyof HTMLElementTagNameMap> =
44
39
  & Props
@@ -56,22 +51,6 @@ export type VanComponent<
56
51
  };
57
52
 
58
53
  // router.mjs
59
- /**
60
- * A virtual component that renders the current route
61
- * in your VanJS application. It must be used in your main component.
62
- *
63
- * @example
64
- * import { Router } from '@vanjs/router';
65
- *
66
- * export const App = () => {
67
- * return Router(); // or <Router /> for JSX
68
- * }
69
- */
70
- // export const Router: JSX.Component<HTMLElement> & VanComponent<HTMLElement>;
71
- // export function Router(props?: ComponentProps<HTMLElement>): HTMLElement;
72
- // export function Router(
73
- // props?: JSX.IntrinsicElements["main"] & { children: null },
74
- // ): HTMLElement;
75
54
  export const Router:
76
55
  & VanComponent<"main">
77
56
  & JSX.Component<"main">;
@@ -80,58 +59,50 @@ export const FileSystemRouter:
80
59
  & JSX.Component<"main">;
81
60
 
82
61
  // a.mjs
83
- /**
84
- * A virtual component that creates an anchor element
85
- * that navigates to the specified href when clicked.
86
- *
87
- * @example
88
- * import { A } from '@vanjs/router';
89
- * import van from 'vanjs-core';
90
- *
91
- * export const Navigation = () => {
92
- * const { nav } = van.tags
93
- * return nav(
94
- * A({ href="/" }, "Home"), // or <A href="/">Home</A> with JSX
95
- * A({ href="/about" }, "About"), // or <A href="/about">About</A> with JSX
96
- * // ...other children
97
- * );
98
- * }
99
- */
100
62
  export const A:
101
63
  & VanComponent<"a">
102
64
  & JSX.Component<"a">;
103
65
 
104
66
  // helpers.mjs
105
- /**
106
- * Navigates to the specified href in the client and sets the router state.
107
- * Keep in mind that the router handles the search params and hash.
108
- *
109
- * @param href the URL to navigate to
110
- * @param options when true, will replace the current history entry
111
- */
112
67
  export const navigate: (
113
68
  href: string,
114
69
  options?: { replace?: boolean },
115
70
  ) => void;
116
71
 
117
- /**
118
- * A client only helper function that reloads the current page.
119
- */
120
72
  export const reload: () => void;
121
73
 
122
- /**
123
- * A helper function that redirects the user to the specified href.
124
- * When called in the server, it will return a function that will redirect the user
125
- * to the specified href when called.
126
- * @param {string | undefined} href the URL to redirect to
127
- */
128
74
  export const redirect: (href?: string) => void | (() => void);
129
75
 
76
+ export const getValue: (v: unknown) => string;
77
+
78
+ export const isCurrentPage: (pageName: string) => boolean;
79
+
80
+ export const isCurrentLocation: (pageName: string) => boolean;
81
+
82
+ export const isLazyComponent: (component: unknown) => boolean;
83
+
84
+ export const executeLifecycle: (
85
+ route: RouteEntry | {
86
+ preload?: (params?: Record<string, string>) => unknown;
87
+ load?: (params?: Record<string, string>) => unknown;
88
+ } | null,
89
+ params: Record<string, string> | undefined,
90
+ ) => Promise<boolean>;
91
+
92
+ export const useRouteData: <T>() => T | undefined;
93
+
94
+ export const matchRoute: (path: string) => RouteEntry | null;
95
+
96
+ // extractParams.mjs
97
+ export const extractParams: (
98
+ pattern: string,
99
+ path: string,
100
+ ) => Record<string, string> | null;
101
+
130
102
  // routes.mjs
131
103
  export type RouteEntry = {
132
104
  path: string;
133
105
  component: () => Promise<ComponentModule>;
134
- // component: () => Promise<DynamicModule>;
135
106
  params?: Record<string, string>;
136
107
  preload?: (
137
108
  params?: Record<string, string>,
@@ -143,24 +114,16 @@ export type RouteEntry = {
143
114
 
144
115
  export type ImportFn = () => LazyComponent;
145
116
 
146
- /**
147
- * Registers a lazy component.
148
- * @param importFn
149
- */
150
117
  export const lazy: (importFn: ImportFn) => () => Promise<ComponentModule>;
151
118
 
152
119
  export type RouteProps = {
153
120
  path: string;
154
121
  params?: Record<string, string>;
155
122
  component:
156
- // | (() => HTMLElementTagNameMap[unknown] | HTMLElementTagNameMap[unknown][])
157
- // | VanNode
158
123
  | (() => DOMElement)
159
124
  | VanComponent
160
125
  | ComponentFn
161
- | (() => Promise<DynamicModule>);
162
- // | ComponentModule["component"];
163
- // component: ComponentFn | (() => Promise<ComponentModule>);
126
+ | (() => Promise<ComponentModule>);
164
127
  preload?: (
165
128
  params?: Record<string, string>,
166
129
  ) => boolean | void | Promise<boolean | void>;
@@ -177,19 +140,6 @@ export type RouteConfig = {
177
140
 
178
141
  export const routes: RouteEntry[];
179
142
 
180
- /**
181
- * Registers a new route in the router state.
182
- * @param route the route to register
183
- *
184
- * @example
185
- * import { Route, lazy } from '@vanjs/router';
186
- * import Home from './pages/Home';
187
- * import NotFound from './pages/NotFound';
188
- *
189
- * Route({ path: '/', component: Home });
190
- * Route({ path: '/about', component: lazy(() => import("./pages/About.ts")) });
191
- * Route({ path: '*', component: NotFound });
192
- */
193
143
  export const Route: (route: RouteProps) => void;
194
144
 
195
145
  // state.mjs
@@ -197,39 +147,33 @@ export type RouterState = {
197
147
  pathname: string;
198
148
  searchParams: URLSearchParams;
199
149
  params: Record<string, string>;
150
+ status: "idle" | "pending" | "success" | "error";
200
151
  };
201
- /**
202
- * A reactive object that holds the current router state.
203
- * This state is maintained by both server and client.
204
- */
152
+
205
153
  export const routerState: {
206
154
  pathname: RouterState["pathname"];
207
155
  searchParams: RouterState["searchParams"];
208
156
  params?: RouterState["params"];
157
+ status: RouterState["status"];
209
158
  };
210
159
 
211
- /**
212
- * Sets the router state to the specified href.
213
- * @param href the URL to navigate to
214
- * @param search the search string
215
- * @param params the route params object
216
- */
217
160
  export const setRouterState: (
218
161
  href: string,
219
162
  search?: string,
220
163
  params?: Record<string, string>,
221
164
  ) => void;
222
165
 
223
- export type UnwrapResult = {
224
- children: VanNode[];
225
- };
166
+ export const microStore: <T extends Record<string, unknown>>(init: T) => T;
226
167
 
227
- /**
228
- * Merge the children of an Element or an array of elements with an optional array of children
229
- * into the childen prperty of a simple object.
230
- * @param source
231
- * @param children
232
- */
168
+ // routeCache.mjs
169
+ export const cacheRoute: (key: ImportFn, value: ComponentModule) => void;
170
+
171
+ export const getCachedRoute: (key: ImportFn) => ComponentModule | undefined;
172
+
173
+ export const fixRouteUrl: (url: string) => string;
174
+
175
+ // unwrap.mjs
176
+ export type UnwrapResult = { children: VanNode[] };
233
177
 
234
178
  export const unwrap: (
235
179
  source:
@@ -257,42 +201,29 @@ export type ComponentModule = {
257
201
  route?: Pick<RouteEntry, "load" | "preload">;
258
202
  };
259
203
 
260
- export type DynamicModule = {
261
- Page: ComponentFn;
204
+ export type LazyComponent = Promise<{
262
205
  default?: ComponentFn;
206
+ Page?: ComponentFn;
263
207
  route?: Pick<RouteEntry, "load" | "preload">;
264
- };
265
-
266
- export type LazyComponent = Promise<DynamicModule>;
267
-
268
- /**
269
- * Fixes the URL of a route.
270
- * @param url
271
- */
272
- export const fixRouteUrl: (url: string) => string;
208
+ }>;
273
209
 
274
- /**
275
- * Cache a route.
276
- * @param key the cache route key
277
- * @param value the cache route
278
- */
279
- export const cache: (key: ImportFn, value: ComponentModule) => void;
280
-
281
- /**
282
- * Return a route cache.
283
- * @param key the cache route key
284
- */
285
- export const getCached: (key: typeof importFn) => ComponentModule | undefined;
286
-
287
- /**
288
- * Execute lifecycle methods preload and / or load
289
- */
290
- export const executeLifecycle: (
291
- { route }: ComponentModule,
292
- params: Record<string, string> | undefined,
293
- ) => Promise<boolean>;
210
+ // dataCache.mjs
211
+ export type CacheEntry<T = unknown> = {
212
+ data: T;
213
+ error: Error | null;
214
+ timestamp: number;
215
+ };
294
216
 
295
- /**
296
- * Find a registered route that matches the given path
297
- */
298
- export const matchRoute: (path: string) => RouteEntry | null;
217
+ export const dataCache: {
218
+ get<T>(pathname: string, key: string): CacheEntry<T> | undefined;
219
+ set<T>(pathname: string, key: string, entry: Partial<CacheEntry<T>>): void;
220
+ has(pathname: string, key?: string): boolean;
221
+ getRoute(pathname: string): Record<string, CacheEntry> | undefined;
222
+ del(pathname: string, key?: string): boolean;
223
+ clear(): void;
224
+ touch(pathname: string): void;
225
+ toJSON(): Record<string, Record<string, CacheEntry>>;
226
+ hydrateFromJSON(json: Record<string, Record<string, CacheEntry>>): void;
227
+ size(): number;
228
+ setMaxRoutes(n: number): void;
229
+ };
@@ -47,4 +47,26 @@ declare module "@vanjs/server" {
47
47
  * @returns HTML string
48
48
  */
49
49
  export const renderToString: (source: Source) => Promise<string>;
50
+
51
+ /**
52
+ * A function that generates a <script> for initial hydration data.
53
+ * Serializes the full path-keyed data cache into window.__DATA_CACHE
54
+ * @returns HTML string
55
+ */
56
+ export const getDataPreload: () => string;
57
+ }
58
+
59
+ interface Window {
60
+ __DATA_CACHE?: Record<
61
+ string,
62
+ Record<
63
+ string,
64
+ {
65
+ data: unknown;
66
+ status: string;
67
+ timestamp: number;
68
+ error: { message: string } | null;
69
+ }
70
+ >
71
+ >;
50
72
  }
package/server/index.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  import { basename } from "node:path";
2
+ // import { routerState } from "../router/index.mjs";
3
+ import * as dataCache from "../router/dataCache.mjs";
2
4
  export * from "../plugin/helpers.mjs";
3
5
 
4
6
  /**
@@ -8,6 +10,7 @@ export const renderToString = async (inputSource) => {
8
10
  const source = typeof inputSource === "function"
9
11
  ? inputSource()
10
12
  : inputSource;
13
+
11
14
  if (typeof source === "number") {
12
15
  return String(source);
13
16
  }
@@ -31,8 +34,8 @@ export const renderToString = async (inputSource) => {
31
34
  }
32
35
  return elements.join("");
33
36
  }
34
- // return String(source)
35
37
 
38
+ // return String(source)
36
39
  // no source provided
37
40
  // @ts-ignore - this is server side code
38
41
  console.warn("Render error! Source not recognized: " + source);
@@ -49,17 +52,17 @@ function renderPreloadLink(file) {
49
52
  } else if (file.endsWith(".css")) {
50
53
  return `<link rel="preload" href="${file}" as="style" crossorigin>`;
51
54
  } else if (file.endsWith(".woff")) {
52
- return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`;
55
+ return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`;
53
56
  } else if (file.endsWith(".woff2")) {
54
- return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`;
57
+ return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`;
55
58
  } else if (file.endsWith(".gif")) {
56
- return ` <link rel="preload" href="${file}" as="image" type="image/gif">`;
59
+ return `<link rel="preload" href="${file}" as="image" type="image/gif">`;
57
60
  } else if (file.endsWith(".jpg") || file.endsWith(".jpeg")) {
58
- return ` <link rel="preload" href="${file}" as="image" type="image/jpeg">`;
61
+ return `<link rel="preload" href="${file}" as="image" type="image/jpeg">`;
59
62
  } else if (file.endsWith(".png")) {
60
- return ` <link rel="preload" href="${file}" as="image" type="image/png">`;
63
+ return `<link rel="preload" href="${file}" as="image" type="image/png">`;
61
64
  } else if (file.endsWith(".webp")) {
62
- return ` <link rel="preload" href="${file}" as="image" type="image/webp">`;
65
+ return `<link rel="preload" href="${file}" as="image" type="image/webp">`;
63
66
  } else {
64
67
  // @ts-ignore - this is server side code
65
68
  console.warn("Render error! File format not recognized: " + file);
@@ -90,13 +93,11 @@ export function renderPreloadLinks(modules, manifest) {
90
93
  // Second pass: generate preload links
91
94
  modules.forEach((id) => {
92
95
  const files = manifest[id];
93
-
94
96
  // istanbul ignore else
95
97
  if (files?.length) {
96
98
  files.forEach((file) => {
97
99
  // Skip if we've seen this file or if it's an asset from an ignored path
98
100
  if (seen.has(file) || ignoredAssets.has(file)) return;
99
-
100
101
  seen.add(file);
101
102
  const filename = basename(file);
102
103
 
@@ -111,7 +112,6 @@ export function renderPreloadLinks(modules, manifest) {
111
112
  }
112
113
  }
113
114
  }
114
-
115
115
  links += renderPreloadLink(file);
116
116
  });
117
117
  }
@@ -119,3 +119,19 @@ export function renderPreloadLinks(modules, manifest) {
119
119
 
120
120
  return links;
121
121
  }
122
+
123
+ /**
124
+ * Serialize route data for client hydration.
125
+ * Uses the new __DATA_CACHE format with path-keyed cache entries.
126
+ * @returns {string}
127
+ */
128
+ export const getDataPreload = () => {
129
+ const cacheJSON = dataCache.toJSON();
130
+ const cacheEntries = Object.keys(cacheJSON);
131
+
132
+ if (cacheEntries.length > 0) {
133
+ const json = JSON.stringify(cacheJSON);
134
+ return `<script id="data-cache">window.__DATA_CACHE=${json}</script>`;
135
+ }
136
+ return "";
137
+ };
package/tsconfig.json CHANGED
@@ -27,8 +27,6 @@
27
27
  "jsxImportSource": "@vanjs/jsx"
28
28
  },
29
29
  "include": [
30
- "./tests/*.ts",
31
- "./tests/*.tsx",
32
30
  "./plugin/*.ts",
33
31
  "./jsx/*.ts",
34
32
  "./setup/*.ts",
@@ -36,7 +34,6 @@
36
34
  "./meta/*.ts",
37
35
  "./server/*.ts",
38
36
  "./client/*.ts",
39
- "./tests/vite-env.d.ts"
40
37
  ],
41
38
  "exclude": ["node_modules", "experiments", "coverage"],
42
39
  }