evikit 2.3.2 → 2.3.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.
Files changed (5) hide show
  1. package/html.js +49 -49
  2. package/index.d.ts +134 -134
  3. package/index.js +243 -243
  4. package/package.json +1 -1
  5. package/server.js +488 -487
package/index.js CHANGED
@@ -1,243 +1,243 @@
1
- import { toStatic } from "hoofd/preact";
2
- import { h } from "preact";
3
- import {
4
- ErrorBoundary,
5
- hydrate as iso,
6
- Router as IsoRouter,
7
- LocationProvider,
8
- prerender,
9
- } from "preact-iso";
10
- import { locationStub } from "preact-iso/prerender";
11
- import { useState } from "preact/hooks";
12
-
13
- import { flatten, primary, references, relations } from "./db.js";
14
- import {
15
- a,
16
- article,
17
- b,
18
- blockquote,
19
- br,
20
- button,
21
- circle,
22
- code,
23
- details,
24
- dialog,
25
- div,
26
- em,
27
- fieldset,
28
- figcaption,
29
- figure,
30
- footer,
31
- form,
32
- h1,
33
- h2,
34
- h3,
35
- h4,
36
- h5,
37
- h6,
38
- header,
39
- hr,
40
- i,
41
- img,
42
- input,
43
- label,
44
- legend,
45
- li,
46
- main,
47
- nav,
48
- ol,
49
- option,
50
- p,
51
- path,
52
- pre,
53
- section,
54
- select,
55
- small,
56
- span,
57
- strong,
58
- summary,
59
- svg,
60
- title,
61
- ul,
62
- } from "./html.js";
63
- import { getI18n, Po, RawI18nProvider, useI18n } from "./i18n.js";
64
- import {
65
- dehydrate,
66
- Hydrate,
67
- QueryClient,
68
- QueryClientProvider,
69
- useQueryClient,
70
- } from "./query.js";
71
- import { queryApi, useApi } from "./use-api.js";
72
- import { useEnhance } from "./use-enhance.js";
73
- import { useStatus } from "./use-status.js";
74
-
75
- /**
76
- * @param {(props: { dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> } ) => import("preact").VNode} App
77
- * @param {string} renderTarget
78
- */
79
- export async function hydrate(App, renderTarget) {
80
- if (typeof window !== "undefined") {
81
- const app = document.querySelector(renderTarget);
82
- if (!app) {
83
- throw new Error(`${renderTarget} not found`);
84
- }
85
- let data;
86
- const prerender = document.querySelector("#preact-prerender-data");
87
- if (prerender) {
88
- data = JSON.parse(prerender.textContent);
89
- prerender.remove();
90
- }
91
-
92
- // If api and hydrate run in the same process, keep value from api.
93
- // Avoid infinite recursion.
94
- if (!Po.value) {
95
- Po.set(
96
- async (lang) =>
97
- await (
98
- await fetch(`${location.origin}/po/${encodeURIComponent(lang)}`)
99
- ).json(),
100
- );
101
- }
102
-
103
- iso(
104
- h(App, {
105
- dehydratedState: data?.dehydratedState,
106
- // `window` matters. We want JSDOM navigator in tests, not Node.js one.
107
- i18n: await getI18n(...window.navigator.languages),
108
- }),
109
- app,
110
- );
111
- }
112
- }
113
-
114
- /** @param {{ children?: import("preact").ComponentChildren, dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }} props */
115
- export function Router({ children, dehydratedState, i18n }) {
116
- const [queryClient] = useState(
117
- () =>
118
- new QueryClient({
119
- defaultOptions: { queries: { staleTime: 60 * 1000 } },
120
- }),
121
- );
122
-
123
- return h(
124
- RawI18nProvider,
125
- { value: /** @type {any} */ (i18n) },
126
- h(
127
- QueryClientProvider,
128
- { client: queryClient },
129
- h(
130
- Hydrate,
131
- { state: dehydratedState },
132
- h(
133
- LocationProvider,
134
- null,
135
- h(ErrorBoundary, null, h(IsoRouter, null, children)),
136
- ),
137
- ),
138
- ),
139
- );
140
- }
141
-
142
- /**
143
- * @param {(props: { dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }) => import("preact").VNode} App
144
- * @param {{ lang?: string, url: string }} data
145
- */
146
- export async function ssr(App, data) {
147
- const origin = process.env["ORIGIN"] || "http://localhost:5173";
148
- const i18n = await getI18n(...(data.lang ? [data.lang] : []));
149
-
150
- const queryClient = new QueryClient({
151
- defaultOptions: { queries: { staleTime: 0 } },
152
- });
153
- await queryClient.prefetchQuery(
154
- queryApi({ lang: i18n.getLocale(), origin, path: data.url }),
155
- );
156
- const dehydratedState = dehydrate(queryClient, {
157
- shouldRedactErrors: (error) => {
158
- const { name } = /** @type {any} */ (error);
159
- return !(Number(name) && name == "404");
160
- },
161
- });
162
-
163
- locationStub(data.url);
164
- const { html, links } = await prerender(h(/** @type {any} */ (App), {}), {
165
- props: { dehydratedState, i18n },
166
- });
167
- const { metas, title } = toStatic();
168
-
169
- return {
170
- data: { ...data, dehydratedState },
171
- head: {
172
- elements: new Set(
173
- metas.map((props) => ({
174
- props: Object.fromEntries(
175
- Object.entries(props).map(([name, content]) => [
176
- name,
177
- String(content),
178
- ]),
179
- ),
180
- type: "meta",
181
- })),
182
- ),
183
- lang: i18n.getLocale(),
184
- title,
185
- },
186
- html,
187
- links,
188
- };
189
- }
190
-
191
- export { flatten, primary, references, relations };
192
-
193
- export { getI18n, useApi, useEnhance, useI18n, useQueryClient, useStatus };
194
-
195
- export {
196
- a,
197
- article,
198
- b,
199
- blockquote,
200
- br,
201
- button,
202
- circle,
203
- code,
204
- details,
205
- dialog,
206
- div,
207
- em,
208
- fieldset,
209
- figcaption,
210
- figure,
211
- footer,
212
- form,
213
- h1,
214
- h2,
215
- h3,
216
- h4,
217
- h5,
218
- h6,
219
- header,
220
- hr,
221
- i,
222
- img,
223
- input,
224
- label,
225
- legend,
226
- li,
227
- main,
228
- nav,
229
- ol,
230
- option,
231
- p,
232
- path,
233
- pre,
234
- section,
235
- select,
236
- small,
237
- span,
238
- strong,
239
- summary,
240
- svg,
241
- title,
242
- ul,
243
- };
1
+ import { toStatic } from "hoofd/preact";
2
+ import { h } from "preact";
3
+ import {
4
+ ErrorBoundary,
5
+ hydrate as iso,
6
+ Router as IsoRouter,
7
+ LocationProvider,
8
+ prerender,
9
+ } from "preact-iso";
10
+ import { locationStub } from "preact-iso/prerender";
11
+ import { useState } from "preact/hooks";
12
+
13
+ import { flatten, primary, references, relations } from "./db.js";
14
+ import {
15
+ a,
16
+ article,
17
+ b,
18
+ blockquote,
19
+ br,
20
+ button,
21
+ circle,
22
+ code,
23
+ details,
24
+ dialog,
25
+ div,
26
+ em,
27
+ fieldset,
28
+ figcaption,
29
+ figure,
30
+ footer,
31
+ form,
32
+ h1,
33
+ h2,
34
+ h3,
35
+ h4,
36
+ h5,
37
+ h6,
38
+ header,
39
+ hr,
40
+ i,
41
+ img,
42
+ input,
43
+ label,
44
+ legend,
45
+ li,
46
+ main,
47
+ nav,
48
+ ol,
49
+ option,
50
+ p,
51
+ path,
52
+ pre,
53
+ section,
54
+ select,
55
+ small,
56
+ span,
57
+ strong,
58
+ summary,
59
+ svg,
60
+ title,
61
+ ul,
62
+ } from "./html.js";
63
+ import { getI18n, Po, RawI18nProvider, useI18n } from "./i18n.js";
64
+ import {
65
+ dehydrate,
66
+ Hydrate,
67
+ QueryClient,
68
+ QueryClientProvider,
69
+ useQueryClient,
70
+ } from "./query.js";
71
+ import { queryApi, useApi } from "./use-api.js";
72
+ import { useEnhance } from "./use-enhance.js";
73
+ import { useStatus } from "./use-status.js";
74
+
75
+ /**
76
+ * @param {(props: { dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> } ) => import("preact").VNode} App
77
+ * @param {string} renderTarget
78
+ */
79
+ export async function hydrate(App, renderTarget) {
80
+ if (typeof window !== "undefined") {
81
+ const app = document.querySelector(renderTarget);
82
+ if (!app) {
83
+ throw new Error(`${renderTarget} not found`);
84
+ }
85
+ let data;
86
+ const prerender = document.querySelector("#preact-prerender-data");
87
+ if (prerender) {
88
+ data = JSON.parse(prerender.textContent);
89
+ prerender.remove();
90
+ }
91
+
92
+ // If api and hydrate run in the same process, keep value from api.
93
+ // Avoid infinite recursion.
94
+ if (!Po.value) {
95
+ Po.set(
96
+ async (lang) =>
97
+ await (
98
+ await fetch(`${location.origin}/po/${encodeURIComponent(lang)}`)
99
+ ).json(),
100
+ );
101
+ }
102
+
103
+ iso(
104
+ h(App, {
105
+ dehydratedState: data?.dehydratedState,
106
+ // `window` matters. We want JSDOM navigator in tests, not Node.js one.
107
+ i18n: await getI18n(...window.navigator.languages),
108
+ }),
109
+ app,
110
+ );
111
+ }
112
+ }
113
+
114
+ /** @param {{ children?: import("preact").ComponentChildren, dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }} props */
115
+ export function Router({ children, dehydratedState, i18n }) {
116
+ const [queryClient] = useState(
117
+ () =>
118
+ new QueryClient({
119
+ defaultOptions: { queries: { staleTime: 60 * 1000 } },
120
+ }),
121
+ );
122
+
123
+ return h(
124
+ RawI18nProvider,
125
+ { value: /** @type {any} */ (i18n) },
126
+ h(
127
+ QueryClientProvider,
128
+ { client: queryClient },
129
+ h(
130
+ Hydrate,
131
+ { state: dehydratedState },
132
+ h(
133
+ LocationProvider,
134
+ null,
135
+ h(ErrorBoundary, null, h(IsoRouter, null, children)),
136
+ ),
137
+ ),
138
+ ),
139
+ );
140
+ }
141
+
142
+ /**
143
+ * @param {(props: { dehydratedState?: ReturnType<import("./query.js").dehydrate> | undefined, i18n: ReturnType<import("./i18n.js").useI18n> }) => import("preact").VNode} App
144
+ * @param {{ lang?: string, url: string }} data
145
+ */
146
+ export async function ssr(App, data) {
147
+ const origin = process.env["ORIGIN"] || "http://localhost:5173";
148
+ const i18n = await getI18n(...(data.lang ? [data.lang] : []));
149
+
150
+ const queryClient = new QueryClient({
151
+ defaultOptions: { queries: { staleTime: 0 } },
152
+ });
153
+ await queryClient.prefetchQuery(
154
+ queryApi({ lang: i18n.getLocale(), origin, path: data.url }),
155
+ );
156
+ const dehydratedState = dehydrate(queryClient, {
157
+ shouldRedactErrors: (error) => {
158
+ const { name } = /** @type {any} */ (error);
159
+ return !(Number(name) && name == "404");
160
+ },
161
+ });
162
+
163
+ locationStub(data.url);
164
+ const { html, links } = await prerender(h(/** @type {any} */ (App), {}), {
165
+ props: { dehydratedState, i18n },
166
+ });
167
+ const { metas, title } = toStatic();
168
+
169
+ return {
170
+ data: { ...data, dehydratedState },
171
+ head: {
172
+ elements: new Set(
173
+ metas.map((props) => ({
174
+ props: Object.fromEntries(
175
+ Object.entries(props).map(([name, content]) => [
176
+ name,
177
+ String(content),
178
+ ]),
179
+ ),
180
+ type: "meta",
181
+ })),
182
+ ),
183
+ lang: i18n.getLocale(),
184
+ title,
185
+ },
186
+ html,
187
+ links,
188
+ };
189
+ }
190
+
191
+ export { flatten, primary, references, relations };
192
+
193
+ export { getI18n, useApi, useEnhance, useI18n, useQueryClient, useStatus };
194
+
195
+ export {
196
+ a,
197
+ article,
198
+ b,
199
+ blockquote,
200
+ br,
201
+ button,
202
+ circle,
203
+ code,
204
+ details,
205
+ dialog,
206
+ div,
207
+ em,
208
+ fieldset,
209
+ figcaption,
210
+ figure,
211
+ footer,
212
+ form,
213
+ h1,
214
+ h2,
215
+ h3,
216
+ h4,
217
+ h5,
218
+ h6,
219
+ header,
220
+ hr,
221
+ i,
222
+ img,
223
+ input,
224
+ label,
225
+ legend,
226
+ li,
227
+ main,
228
+ nav,
229
+ ol,
230
+ option,
231
+ p,
232
+ path,
233
+ pre,
234
+ section,
235
+ select,
236
+ small,
237
+ span,
238
+ strong,
239
+ summary,
240
+ svg,
241
+ title,
242
+ ul,
243
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "evikit",
3
3
  "description": "Preact/SQLite SSR framework for small web apps",
4
- "version": "2.3.2",
4
+ "version": "2.3.3",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./index.js",