evikit 2.9.2 → 2.10.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/README.md +11 -19
- package/index.d.ts +19 -1
- package/index.js +41 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -180,7 +180,7 @@ export function ErrorPage({ children, error }) {
|
|
|
180
180
|
useTitle(status);
|
|
181
181
|
|
|
182
182
|
return main(
|
|
183
|
-
|
|
183
|
+
{ id: "main" },
|
|
184
184
|
p({ class: "nav" }, a({ href: "/" }, i18n.gettext("Questions"))),
|
|
185
185
|
h1({ class: "title" }, status),
|
|
186
186
|
children,
|
|
@@ -221,9 +221,7 @@ export function api() {
|
|
|
221
221
|
Add a Preact router at `src/app.js` (uncomment the routes one-by-one when we add them later):
|
|
222
222
|
|
|
223
223
|
```js
|
|
224
|
-
import {
|
|
225
|
-
import { h } from "preact";
|
|
226
|
-
import { Route } from "preact-iso";
|
|
224
|
+
import { route, ssr } from "evikit";
|
|
227
225
|
|
|
228
226
|
import { acceptLanguages } from "./lib/index.js";
|
|
229
227
|
import { ErrorPage } from "./routes/error.js";
|
|
@@ -232,21 +230,11 @@ import { ErrorPage } from "./routes/error.js";
|
|
|
232
230
|
|
|
233
231
|
acceptLanguages();
|
|
234
232
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return h(
|
|
241
|
-
Router,
|
|
242
|
-
props,
|
|
243
|
-
// h(Route, { component: HomePage, path: "/" }),
|
|
244
|
-
// h(Route, { component: QuestionIdPage, path: "/question/:id" }),
|
|
245
|
-
h(Route, { component: ErrorPage, default: true }),
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
hydrate(App, "#app");
|
|
233
|
+
export const prerender = ssr(
|
|
234
|
+
{ ErrorPage },
|
|
235
|
+
// route("/", HomePage),
|
|
236
|
+
// route("/question/:id", QuestionIdPage),
|
|
237
|
+
);
|
|
250
238
|
```
|
|
251
239
|
|
|
252
240
|
#### HTML entry point
|
|
@@ -386,6 +374,8 @@ export const HomeGet = {
|
|
|
386
374
|
};
|
|
387
375
|
```
|
|
388
376
|
|
|
377
|
+
> 😉 Note: for live refresh to know when data changes, use columns from `schema` in `outputs`, instead of writing `string()` or `number()` anew.
|
|
378
|
+
|
|
389
379
|
Code the API server endpoint in `src/routes/api/server.js`:
|
|
390
380
|
|
|
391
381
|
```js
|
|
@@ -523,6 +513,8 @@ export function QuestionIdPage() {
|
|
|
523
513
|
}
|
|
524
514
|
|
|
525
515
|
return main(
|
|
516
|
+
{ id: "main" },
|
|
517
|
+
|
|
526
518
|
h1({ class: "title" }, title),
|
|
527
519
|
|
|
528
520
|
// VOTE_FORM: replace with form view from the "Vote for choice" section.
|
package/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface QueryState {
|
|
|
14
14
|
data: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
15
15
|
dataUpdatedAt: number;
|
|
16
16
|
error: null | unknown;
|
|
17
|
+
fromEventSource: boolean;
|
|
17
18
|
isInvalidated: boolean;
|
|
18
19
|
status: "error" | "loading" | "success";
|
|
19
20
|
}
|
|
@@ -61,6 +62,7 @@ export function dehydrate(
|
|
|
61
62
|
|
|
62
63
|
export function getI18n(...langs: string[]): Promise<i18n.Gettext>;
|
|
63
64
|
|
|
65
|
+
/** @deprecated */
|
|
64
66
|
export function hydrate(
|
|
65
67
|
App: (props: {
|
|
66
68
|
dehydratedState?: DehydratedState | undefined;
|
|
@@ -69,6 +71,12 @@ export function hydrate(
|
|
|
69
71
|
renderTarget: string,
|
|
70
72
|
): Promise<void>;
|
|
71
73
|
|
|
74
|
+
export function route(
|
|
75
|
+
path: string,
|
|
76
|
+
component: () => VNode<any> | VNode<never>, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
77
|
+
): { component: typeof component; path: string };
|
|
78
|
+
|
|
79
|
+
/** @deprecated */
|
|
72
80
|
export function Router({
|
|
73
81
|
children,
|
|
74
82
|
dehydratedState,
|
|
@@ -80,8 +88,18 @@ export function Router({
|
|
|
80
88
|
}): VNode<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
81
89
|
|
|
82
90
|
/** @deprecated */
|
|
83
|
-
export function ssr(App: SsrApp): (props: SsrProps) => Promise<SsrResponse>;
|
|
84
91
|
export function ssr(App: SsrApp, props: SsrProps): Promise<SsrResponse>;
|
|
92
|
+
/** @deprecated */
|
|
93
|
+
export function ssr(App: SsrApp): (props: SsrProps) => Promise<SsrResponse>;
|
|
94
|
+
export function ssr(
|
|
95
|
+
props: {
|
|
96
|
+
ErrorPage: (props: {
|
|
97
|
+
children?: import("preact").ComponentChildren;
|
|
98
|
+
error?: unknown;
|
|
99
|
+
}) => VNode<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
100
|
+
},
|
|
101
|
+
...routes: ReturnType<typeof route>[]
|
|
102
|
+
): (props: SsrProps) => Promise<SsrResponse>;
|
|
85
103
|
|
|
86
104
|
export function useI18n(): i18n.Gettext;
|
|
87
105
|
|
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Router as IsoRouter,
|
|
7
7
|
LocationProvider,
|
|
8
8
|
prerender,
|
|
9
|
+
Route,
|
|
9
10
|
} from "preact-iso";
|
|
10
11
|
import { locationStub } from "preact-iso/prerender";
|
|
11
12
|
import { useState } from "preact/hooks";
|
|
@@ -63,6 +64,14 @@ export async function hydrate(App, renderTarget) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
/**
|
|
68
|
+
* @param {string | null} path
|
|
69
|
+
* @param {() => import("preact").VNode} component
|
|
70
|
+
*/
|
|
71
|
+
export function route(path, component) {
|
|
72
|
+
return { component, default: !path, path };
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
/** @param {{ children?: import("preact").ComponentChildren, dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }} props */
|
|
67
76
|
export function Router({ children, dehydratedState, i18n }) {
|
|
68
77
|
const [queryClient] = useState(
|
|
@@ -91,16 +100,41 @@ export function Router({ children, dehydratedState, i18n }) {
|
|
|
91
100
|
);
|
|
92
101
|
}
|
|
93
102
|
|
|
103
|
+
/** @param {(import("./index.d.ts").SsrApp | import("./index.d.ts").SsrProps | { ErrorPage: () => import("preact").VNode } | ReturnType<import("./index.d.ts").route>)[]} args */
|
|
104
|
+
export function ssr(...args) {
|
|
105
|
+
if (typeof args[0] == "function") {
|
|
106
|
+
const App = args[0];
|
|
107
|
+
/** @type {import("./index.d.ts").SsrProps | undefined} */
|
|
108
|
+
const props = /** @type {any} */ (args[1]);
|
|
109
|
+
if (props) {
|
|
110
|
+
return ssrInner(App, props);
|
|
111
|
+
}
|
|
112
|
+
/** @param {import("./index.d.ts").SsrProps} props */
|
|
113
|
+
return (props) => ssrInner(App, props);
|
|
114
|
+
}
|
|
115
|
+
/** @type {() => import("preact").VNode} */
|
|
116
|
+
const ErrorPage = /** @type {any} */ (args[0]).ErrorPage;
|
|
117
|
+
/** @type {ReturnType<import("./index.d.ts").route>[]} */
|
|
118
|
+
const routes = /** @type {any} */ (args.slice(1));
|
|
119
|
+
/** @type {import("./index.d.ts").SsrApp} */
|
|
120
|
+
function App(props) {
|
|
121
|
+
return h(
|
|
122
|
+
Router,
|
|
123
|
+
props,
|
|
124
|
+
...routes.map((route) => h(Route, route)),
|
|
125
|
+
h(Route, { component: ErrorPage, default: true }),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
hydrate(App, "#app");
|
|
129
|
+
/** @param {import("./index.d.ts").SsrProps} props */
|
|
130
|
+
return (props) => ssrInner(App, props);
|
|
131
|
+
}
|
|
132
|
+
|
|
94
133
|
/**
|
|
95
134
|
* @param {(props: { dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }) => import("preact").VNode} App
|
|
96
|
-
* @param {{ cookie?: string | undefined, lang?: string, url: string }}
|
|
135
|
+
* @param {{ cookie?: string | undefined, lang?: string, url: string }} data
|
|
97
136
|
*/
|
|
98
|
-
|
|
99
|
-
if (!data) {
|
|
100
|
-
/** @param {NonNullable<typeof data>} data */
|
|
101
|
-
return (data) => ssr(App, data);
|
|
102
|
-
}
|
|
103
|
-
|
|
137
|
+
async function ssrInner(App, data) {
|
|
104
138
|
const i18n = await getI18n(...(data.lang ? [data.lang] : []));
|
|
105
139
|
|
|
106
140
|
const queryClient = new QueryClient({
|