@quilted/quilt 0.8.7 → 0.8.9
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/CHANGELOG.md +35 -0
- package/build/esm/server.browser.mjs +1 -5
- package/build/esm/server.mjs +0 -2
- package/build/esnext/server.browser.esnext +1 -6
- package/build/esnext/server.esnext +0 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/server.browser.d.ts +0 -4
- package/build/typescript/server.browser.d.ts.map +1 -1
- package/build/typescript/server.d.ts +0 -2
- package/build/typescript/server.d.ts.map +1 -1
- package/package.json +22 -22
- package/source/server.browser.ts +0 -8
- package/source/server.ts +0 -7
- package/build/esm/server/ServerContext.mjs +0 -20
- package/build/esm/server/request-router.mjs +0 -251
- package/build/esnext/server/ServerContext.esnext +0 -14
- package/build/esnext/server/request-router.esnext +0 -270
- package/build/typescript/server/ServerContext.d.ts +0 -10
- package/build/typescript/server/ServerContext.d.ts.map +0 -1
- package/build/typescript/server/request-router.d.ts +0 -22
- package/build/typescript/server/request-router.d.ts.map +0 -1
- package/source/server/ServerContext.tsx +0 -38
- package/source/server/request-router.tsx +0 -389
|
@@ -5,8 +5,4 @@ export * from '@quilted/assets';
|
|
|
5
5
|
export { parseAcceptLanguageHeader } from '@quilted/preact-localize';
|
|
6
6
|
declare function noopCreateRequestRouterLocalization(): void;
|
|
7
7
|
export { noopCreateRequestRouterLocalization as createRequestRouterLocalization };
|
|
8
|
-
declare function noopRenderToResponse(): void;
|
|
9
|
-
export { noopRenderToResponse as renderToResponse };
|
|
10
|
-
declare function NoopServerContext(): null;
|
|
11
|
-
export { NoopServerContext as ServerContext };
|
|
12
8
|
//# sourceMappingURL=server.browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.browser.d.ts","sourceRoot":"","sources":["../../source/server.browser.ts"],"names":[],"mappings":"AAAA,iBAAS,kBAAkB,SAAK;AAEhC,OAAO,EACL,kBAAkB,IAAI,cAAc,EACpC,kBAAkB,IAAI,mBAAmB,EACzC,kBAAkB,IAAI,oBAAoB,GAC3C,CAAC;AACF,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAEnE,iBAAS,mCAAmC,SAAK;AACjD,OAAO,EAAC,mCAAmC,IAAI,+BAA+B,EAAC,CAAC
|
|
1
|
+
{"version":3,"file":"server.browser.d.ts","sourceRoot":"","sources":["../../source/server.browser.ts"],"names":[],"mappings":"AAAA,iBAAS,kBAAkB,SAAK;AAEhC,OAAO,EACL,kBAAkB,IAAI,cAAc,EACpC,kBAAkB,IAAI,mBAAmB,EACzC,kBAAkB,IAAI,oBAAoB,GAC3C,CAAC;AACF,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAEnE,iBAAS,mCAAmC,SAAK;AACjD,OAAO,EAAC,mCAAmC,IAAI,+BAA+B,EAAC,CAAC"}
|
|
@@ -3,6 +3,4 @@ export * from '@quilted/preact-browser/server';
|
|
|
3
3
|
export * from '@quilted/assets';
|
|
4
4
|
export { parseAcceptLanguageHeader } from '@quilted/preact-localize';
|
|
5
5
|
export { createRequestRouterLocalization } from '@quilted/preact-localize/request-router';
|
|
6
|
-
export { renderToResponse, type RenderToResponseOptions, type RenderHTMLFunction, } from './server/request-router.tsx';
|
|
7
|
-
export { ServerContext } from './server/ServerContext.tsx';
|
|
8
6
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../source/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAC,+BAA+B,EAAC,MAAM,yCAAyC,CAAC
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../source/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAC,+BAA+B,EAAC,MAAM,yCAAyC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quilted/quilt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.9",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/lemonmade/quilt.git",
|
|
@@ -241,33 +241,33 @@
|
|
|
241
241
|
"./build/esm/signals.mjs"
|
|
242
242
|
],
|
|
243
243
|
"dependencies": {
|
|
244
|
-
"@quilted/assets": "^0.1.
|
|
244
|
+
"@quilted/assets": "^0.1.6",
|
|
245
245
|
"@quilted/async": "^0.4.22",
|
|
246
|
-
"@quilted/events": "^2.1.
|
|
246
|
+
"@quilted/events": "^2.1.2",
|
|
247
247
|
"@quilted/graphql": "^3.3.8",
|
|
248
|
-
"@quilted/preact-async": "^0.1.
|
|
249
|
-
"@quilted/preact-browser": "^0.1.
|
|
250
|
-
"@quilted/preact-context": "^0.1.
|
|
251
|
-
"@quilted/preact-graphql": "^0.1.
|
|
252
|
-
"@quilted/preact-localize": "^0.3.
|
|
253
|
-
"@quilted/preact-performance": "^0.1.
|
|
254
|
-
"@quilted/preact-router": "^0.2.
|
|
255
|
-
"@quilted/preact-signals": "^0.1.
|
|
256
|
-
"@quilted/preact-workers": "^0.2.
|
|
257
|
-
"@quilted/preact-testing": "^0.1.
|
|
258
|
-
"@quilted/react": "^
|
|
259
|
-
"@quilted/react-dom": "^
|
|
260
|
-
"@quilted/request-router": "^0.3.
|
|
248
|
+
"@quilted/preact-async": "^0.1.20",
|
|
249
|
+
"@quilted/preact-browser": "^0.1.15",
|
|
250
|
+
"@quilted/preact-context": "^0.1.3",
|
|
251
|
+
"@quilted/preact-graphql": "^0.1.8",
|
|
252
|
+
"@quilted/preact-localize": "^0.3.5",
|
|
253
|
+
"@quilted/preact-performance": "^0.1.1",
|
|
254
|
+
"@quilted/preact-router": "^0.2.12",
|
|
255
|
+
"@quilted/preact-signals": "^0.1.1",
|
|
256
|
+
"@quilted/preact-workers": "^0.2.1",
|
|
257
|
+
"@quilted/preact-testing": "^0.1.8",
|
|
258
|
+
"@quilted/react": "^19.0.0",
|
|
259
|
+
"@quilted/react-dom": "^19.0.0",
|
|
260
|
+
"@quilted/request-router": "^0.3.1",
|
|
261
261
|
"@quilted/signals": "^0.2.0",
|
|
262
262
|
"@quilted/threads": "^3.0.0",
|
|
263
|
-
"preact-render-to-string": "^6.
|
|
263
|
+
"preact-render-to-string": "^6.5.13",
|
|
264
264
|
"jest-matcher-utils": "^29.0.0"
|
|
265
265
|
},
|
|
266
266
|
"peerDependencies": {
|
|
267
267
|
"graphql": "^16.8.0",
|
|
268
|
-
"preact": "^10.
|
|
268
|
+
"preact": "^10.26.0",
|
|
269
269
|
"prettier": "^2.0.0 || ^3.0.0",
|
|
270
|
-
"vitest": "^2.0.0"
|
|
270
|
+
"vitest": "^2.0.0 || ^3.0.0"
|
|
271
271
|
},
|
|
272
272
|
"peerDependenciesMeta": {
|
|
273
273
|
"graphql": {
|
|
@@ -285,9 +285,9 @@
|
|
|
285
285
|
},
|
|
286
286
|
"devDependencies": {
|
|
287
287
|
"expect": "^29.0.0",
|
|
288
|
-
"preact": "^10.
|
|
289
|
-
"prettier": "^3.
|
|
290
|
-
"vitest": "^
|
|
288
|
+
"preact": "^10.26.0",
|
|
289
|
+
"prettier": "^3.5.0",
|
|
290
|
+
"vitest": "^3.0.0"
|
|
291
291
|
},
|
|
292
292
|
"scripts": {
|
|
293
293
|
"build": "rollup --config configuration/rollup.config.js"
|
package/source/server.browser.ts
CHANGED
|
@@ -12,11 +12,3 @@ export {parseAcceptLanguageHeader} from '@quilted/preact-localize';
|
|
|
12
12
|
|
|
13
13
|
function noopCreateRequestRouterLocalization() {}
|
|
14
14
|
export {noopCreateRequestRouterLocalization as createRequestRouterLocalization};
|
|
15
|
-
|
|
16
|
-
function noopRenderToResponse() {}
|
|
17
|
-
export {noopRenderToResponse as renderToResponse};
|
|
18
|
-
|
|
19
|
-
function NoopServerContext() {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
export {NoopServerContext as ServerContext};
|
package/source/server.ts
CHANGED
|
@@ -8,10 +8,3 @@ export * from '@quilted/assets';
|
|
|
8
8
|
|
|
9
9
|
export {parseAcceptLanguageHeader} from '@quilted/preact-localize';
|
|
10
10
|
export {createRequestRouterLocalization} from '@quilted/preact-localize/request-router';
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
renderToResponse,
|
|
14
|
-
type RenderToResponseOptions,
|
|
15
|
-
type RenderHTMLFunction,
|
|
16
|
-
} from './server/request-router.tsx';
|
|
17
|
-
export {ServerContext} from './server/ServerContext.tsx';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { BrowserDetailsContext, BrowserAssetsManifestContext } from '@quilted/preact-browser/server';
|
|
2
|
-
import { jsx } from 'preact/jsx-runtime';
|
|
3
|
-
|
|
4
|
-
function ServerContext({
|
|
5
|
-
browser,
|
|
6
|
-
assets,
|
|
7
|
-
children
|
|
8
|
-
}) {
|
|
9
|
-
const withBrowser = browser ? jsx(BrowserDetailsContext.Provider, {
|
|
10
|
-
value: browser,
|
|
11
|
-
children: children
|
|
12
|
-
}) : children;
|
|
13
|
-
const withAssets = assets ? jsx(BrowserAssetsManifestContext.Provider, {
|
|
14
|
-
value: assets,
|
|
15
|
-
children: withBrowser
|
|
16
|
-
}) : withBrowser;
|
|
17
|
-
return withAssets;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export { ServerContext };
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { isValidElement } from 'preact';
|
|
2
|
-
import { renderToStringAsync, renderToStaticMarkup } from 'preact-render-to-string';
|
|
3
|
-
import { styleAssetPreloadAttributes, scriptAssetPreloadAttributes } from '@quilted/assets';
|
|
4
|
-
import { BrowserResponse, BrowserEffectsAreActiveContext, Title, Link, Meta, Serialization, ScriptAsset, StyleAsset, StyleAssetPreload, ScriptAssetPreload } from '@quilted/preact-browser/server';
|
|
5
|
-
import { EnhancedResponse, HTMLResponse } from '@quilted/request-router';
|
|
6
|
-
import { ServerContext } from './ServerContext.mjs';
|
|
7
|
-
import { jsx, jsxs, Fragment } from 'preact/jsx-runtime';
|
|
8
|
-
|
|
9
|
-
async function renderToResponse(optionsOrElement, definitelyOptions) {
|
|
10
|
-
let element;
|
|
11
|
-
let options;
|
|
12
|
-
if (isValidElement(optionsOrElement)) {
|
|
13
|
-
element = optionsOrElement;
|
|
14
|
-
options = definitelyOptions;
|
|
15
|
-
} else {
|
|
16
|
-
options = optionsOrElement;
|
|
17
|
-
}
|
|
18
|
-
const {
|
|
19
|
-
request,
|
|
20
|
-
assets,
|
|
21
|
-
status: explicitStatus,
|
|
22
|
-
headers: explicitHeaders,
|
|
23
|
-
serializations: explicitSerializations,
|
|
24
|
-
waitUntil = noop,
|
|
25
|
-
stream: shouldStream = false,
|
|
26
|
-
renderHTML = true
|
|
27
|
-
} = options;
|
|
28
|
-
const baseURL = request.URL ?? new URL(request.url);
|
|
29
|
-
const browserResponse = new BrowserResponse({
|
|
30
|
-
request,
|
|
31
|
-
status: explicitStatus,
|
|
32
|
-
headers: new Headers(explicitHeaders),
|
|
33
|
-
serializations: explicitSerializations
|
|
34
|
-
});
|
|
35
|
-
let appStream;
|
|
36
|
-
if (shouldStream === false && element != null) {
|
|
37
|
-
let rendered;
|
|
38
|
-
try {
|
|
39
|
-
rendered = await renderToStringAsync(jsx(ServerContext, {
|
|
40
|
-
assets: assets,
|
|
41
|
-
browser: browserResponse,
|
|
42
|
-
children: element
|
|
43
|
-
}));
|
|
44
|
-
} catch (error) {
|
|
45
|
-
if (error instanceof Response) {
|
|
46
|
-
const mergedHeaders = new Headers(browserResponse.headers);
|
|
47
|
-
|
|
48
|
-
// Copy headers from error response, potentially overwriting existing ones
|
|
49
|
-
for (const [key, value] of error.headers) {
|
|
50
|
-
if (key.toLowerCase() === 'set-cookie') continue;
|
|
51
|
-
mergedHeaders.set(key, value);
|
|
52
|
-
}
|
|
53
|
-
for (const setCookie of error.headers.getSetCookie()) {
|
|
54
|
-
mergedHeaders.append('Set-Cookie', setCookie);
|
|
55
|
-
}
|
|
56
|
-
const mergedResponse = new EnhancedResponse(error.body, {
|
|
57
|
-
status: Math.max(browserResponse.status.value, error.status),
|
|
58
|
-
headers: mergedHeaders
|
|
59
|
-
});
|
|
60
|
-
return mergedResponse;
|
|
61
|
-
}
|
|
62
|
-
throw error;
|
|
63
|
-
}
|
|
64
|
-
const appTransformStream = new TransformStream();
|
|
65
|
-
const appWriter = appTransformStream.writable.getWriter();
|
|
66
|
-
appStream = appTransformStream.readable;
|
|
67
|
-
appWriter.write(rendered);
|
|
68
|
-
appWriter.close();
|
|
69
|
-
}
|
|
70
|
-
if (appStream == null) {
|
|
71
|
-
const appTransformStream = new TransformStream();
|
|
72
|
-
appStream = appTransformStream.readable;
|
|
73
|
-
const renderAppStream = async function renderAppStream() {
|
|
74
|
-
const appWriter = appTransformStream.writable.getWriter();
|
|
75
|
-
if (element != null) {
|
|
76
|
-
// TODO: how could we handle redirects automatically? For now, if people want
|
|
77
|
-
// this, they will explicitly turn on streaming and will have to use some in-app
|
|
78
|
-
// to manually handle redirects (e.g., by rendering a script tag that uses JavaScript
|
|
79
|
-
// to redirect)
|
|
80
|
-
const rendered = await renderToStringAsync(jsx(ServerContext, {
|
|
81
|
-
assets: assets,
|
|
82
|
-
browser: browserResponse,
|
|
83
|
-
children: element
|
|
84
|
-
}));
|
|
85
|
-
appWriter.write(rendered);
|
|
86
|
-
}
|
|
87
|
-
appWriter.close();
|
|
88
|
-
};
|
|
89
|
-
waitUntil(renderAppStream());
|
|
90
|
-
}
|
|
91
|
-
const body = await renderToHTMLBody(appStream);
|
|
92
|
-
return new HTMLResponse(body, {
|
|
93
|
-
status: browserResponse.status.value,
|
|
94
|
-
headers: browserResponse.headers
|
|
95
|
-
});
|
|
96
|
-
async function renderToHTMLBody(content) {
|
|
97
|
-
if (typeof renderHTML === 'function') {
|
|
98
|
-
const body = await renderHTML(content, {
|
|
99
|
-
response: browserResponse
|
|
100
|
-
});
|
|
101
|
-
return body;
|
|
102
|
-
} else if (renderHTML === false || renderHTML === 'fragment') {
|
|
103
|
-
return content;
|
|
104
|
-
}
|
|
105
|
-
const responseStream = new TextEncoderStream();
|
|
106
|
-
const body = responseStream.readable;
|
|
107
|
-
const renderFullHTML = async function renderFullHTML() {
|
|
108
|
-
const writer = responseStream.writable.getWriter();
|
|
109
|
-
writer.write(`<!DOCTYPE html>`);
|
|
110
|
-
const synchronousAssets = assets?.entry({
|
|
111
|
-
request,
|
|
112
|
-
modules: browserResponse.assets.get({
|
|
113
|
-
timing: 'load'
|
|
114
|
-
})
|
|
115
|
-
});
|
|
116
|
-
const preloadAssets = assets?.modules(browserResponse.assets.get({
|
|
117
|
-
timing: 'preload'
|
|
118
|
-
}), {
|
|
119
|
-
request
|
|
120
|
-
});
|
|
121
|
-
if (synchronousAssets) {
|
|
122
|
-
for (const style of synchronousAssets.styles) {
|
|
123
|
-
browserResponse.headers.append('Link', preloadHeader(styleAssetPreloadAttributes(style)));
|
|
124
|
-
}
|
|
125
|
-
for (const script of synchronousAssets.scripts) {
|
|
126
|
-
browserResponse.headers.append('Link', preloadHeader(scriptAssetPreloadAttributes(script)));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const htmlContent = renderToStaticMarkup(jsx(BrowserEffectsAreActiveContext.Provider, {
|
|
130
|
-
value: false,
|
|
131
|
-
children: jsxs("html", {
|
|
132
|
-
...browserResponse.htmlAttributes.value,
|
|
133
|
-
children: [jsxs("head", {
|
|
134
|
-
children: [jsx(Title, {
|
|
135
|
-
children: browserResponse.title.value
|
|
136
|
-
}), browserResponse.links.value.map(link => jsx(Link, {
|
|
137
|
-
...link
|
|
138
|
-
})), browserResponse.metas.value.map(meta => jsx(Meta, {
|
|
139
|
-
...meta
|
|
140
|
-
})), browserResponse.serializations.value.map(({
|
|
141
|
-
name,
|
|
142
|
-
content
|
|
143
|
-
}) => jsx(Serialization, {
|
|
144
|
-
name: name,
|
|
145
|
-
content: content
|
|
146
|
-
})), synchronousAssets?.scripts.map(script => jsx(ScriptAsset, {
|
|
147
|
-
asset: script,
|
|
148
|
-
baseURL: baseURL
|
|
149
|
-
}, script.source)), synchronousAssets?.styles.map(style => jsx(StyleAsset, {
|
|
150
|
-
asset: style,
|
|
151
|
-
baseURL: baseURL
|
|
152
|
-
}, style.source)), preloadAssets?.styles.map(style => jsx(StyleAssetPreload, {
|
|
153
|
-
asset: style,
|
|
154
|
-
baseURL: baseURL
|
|
155
|
-
}, style.source)), preloadAssets?.scripts.map(script => jsx(ScriptAssetPreload, {
|
|
156
|
-
asset: script,
|
|
157
|
-
baseURL: baseURL
|
|
158
|
-
}, script.source))]
|
|
159
|
-
}), jsx("body", {
|
|
160
|
-
...browserResponse.bodyAttributes.value,
|
|
161
|
-
dangerouslySetInnerHTML: {
|
|
162
|
-
__html: '%%CONTENT%%'
|
|
163
|
-
}
|
|
164
|
-
})]
|
|
165
|
-
})
|
|
166
|
-
}));
|
|
167
|
-
const [firstChunk, secondChunk] = htmlContent.split('%%CONTENT%%');
|
|
168
|
-
writer.write(firstChunk);
|
|
169
|
-
if (element != null) writer.write(`<div id="app">`);
|
|
170
|
-
const reader = content.getReader();
|
|
171
|
-
while (true) {
|
|
172
|
-
const {
|
|
173
|
-
done,
|
|
174
|
-
value
|
|
175
|
-
} = await reader.read();
|
|
176
|
-
if (done) {
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
writer.write(value);
|
|
180
|
-
}
|
|
181
|
-
if (element != null) writer.write(`</div>`);
|
|
182
|
-
const newSynchronousAssets = assets?.entry({
|
|
183
|
-
request,
|
|
184
|
-
modules: browserResponse.assets.get({
|
|
185
|
-
timing: 'load'
|
|
186
|
-
})
|
|
187
|
-
});
|
|
188
|
-
const newPreloadAssets = assets?.modules(browserResponse.assets.get({
|
|
189
|
-
timing: 'preload'
|
|
190
|
-
}), {
|
|
191
|
-
request
|
|
192
|
-
});
|
|
193
|
-
if (newSynchronousAssets) {
|
|
194
|
-
const diffedSynchronousAssets = diffBrowserAssetsEntries(newSynchronousAssets, synchronousAssets);
|
|
195
|
-
const diffedPreloadAssets = diffBrowserAssetsEntries(newPreloadAssets, preloadAssets);
|
|
196
|
-
const additionalAssetsContent = renderToStaticMarkup(jsxs(Fragment, {
|
|
197
|
-
children: [diffedSynchronousAssets.scripts.map(script => jsx(ScriptAsset, {
|
|
198
|
-
asset: script,
|
|
199
|
-
baseURL: baseURL
|
|
200
|
-
}, script.source)), diffedSynchronousAssets.styles.map(style => jsx(StyleAsset, {
|
|
201
|
-
asset: style,
|
|
202
|
-
baseURL: baseURL
|
|
203
|
-
}, style.source)), diffedPreloadAssets.styles.map(style => jsx(StyleAssetPreload, {
|
|
204
|
-
asset: style,
|
|
205
|
-
baseURL: baseURL
|
|
206
|
-
}, style.source)), diffedPreloadAssets.scripts.map(script => jsx(ScriptAssetPreload, {
|
|
207
|
-
asset: script,
|
|
208
|
-
baseURL: baseURL
|
|
209
|
-
}, script.source))]
|
|
210
|
-
}));
|
|
211
|
-
writer.write(additionalAssetsContent);
|
|
212
|
-
}
|
|
213
|
-
writer.write(secondChunk);
|
|
214
|
-
writer.close();
|
|
215
|
-
};
|
|
216
|
-
waitUntil(renderFullHTML());
|
|
217
|
-
return body;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
function preloadHeader(attributes) {
|
|
221
|
-
const {
|
|
222
|
-
as,
|
|
223
|
-
rel = 'preload',
|
|
224
|
-
href,
|
|
225
|
-
crossOrigin,
|
|
226
|
-
crossorigin
|
|
227
|
-
} = attributes;
|
|
228
|
-
|
|
229
|
-
// Support both property and attribute versions of the casing
|
|
230
|
-
const finalCrossOrigin = crossOrigin ?? crossorigin;
|
|
231
|
-
let header = `<${href}>; rel="${rel}"; as="${as}"`;
|
|
232
|
-
if (finalCrossOrigin === '' || finalCrossOrigin === true) {
|
|
233
|
-
header += `; crossorigin`;
|
|
234
|
-
} else if (typeof finalCrossOrigin === 'string') {
|
|
235
|
-
header += `; crossorigin="${finalCrossOrigin}"`;
|
|
236
|
-
}
|
|
237
|
-
return header;
|
|
238
|
-
}
|
|
239
|
-
function diffBrowserAssetsEntries(newList, oldList) {
|
|
240
|
-
const oldStyles = new Set(oldList.styles.map(style => style.source));
|
|
241
|
-
const oldScripts = new Set(oldList.scripts.map(script => script.source));
|
|
242
|
-
return {
|
|
243
|
-
styles: newList.styles.filter(style => !oldStyles.has(style.source)),
|
|
244
|
-
scripts: newList.scripts.filter(script => !oldScripts.has(script.source))
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
function noop(..._args) {
|
|
248
|
-
// noop
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export { renderToResponse };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'preact/jsx-runtime';
|
|
2
|
-
import { BrowserDetailsContext, BrowserAssetsManifestContext } from '@quilted/preact-browser/server';
|
|
3
|
-
|
|
4
|
-
function ServerContext({
|
|
5
|
-
browser,
|
|
6
|
-
assets,
|
|
7
|
-
children
|
|
8
|
-
}) {
|
|
9
|
-
const withBrowser = browser ? /* @__PURE__ */ jsx(BrowserDetailsContext.Provider, { value: browser, children }) : children;
|
|
10
|
-
const withAssets = assets ? /* @__PURE__ */ jsx(BrowserAssetsManifestContext.Provider, { value: assets, children: withBrowser }) : withBrowser;
|
|
11
|
-
return withAssets;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export { ServerContext };
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs, Fragment } from 'preact/jsx-runtime';
|
|
2
|
-
import { isValidElement } from 'preact';
|
|
3
|
-
import { renderToStringAsync, renderToStaticMarkup } from 'preact-render-to-string';
|
|
4
|
-
import { styleAssetPreloadAttributes, scriptAssetPreloadAttributes } from '@quilted/assets';
|
|
5
|
-
import { BrowserResponse, BrowserEffectsAreActiveContext, Title, Link, Meta, Serialization, ScriptAsset, StyleAsset, StyleAssetPreload, ScriptAssetPreload } from '@quilted/preact-browser/server';
|
|
6
|
-
import { EnhancedResponse, HTMLResponse } from '@quilted/request-router';
|
|
7
|
-
import { ServerContext } from './ServerContext.esnext';
|
|
8
|
-
|
|
9
|
-
async function renderToResponse(optionsOrElement, definitelyOptions) {
|
|
10
|
-
let element;
|
|
11
|
-
let options;
|
|
12
|
-
if (isValidElement(optionsOrElement)) {
|
|
13
|
-
element = optionsOrElement;
|
|
14
|
-
options = definitelyOptions;
|
|
15
|
-
} else {
|
|
16
|
-
options = optionsOrElement;
|
|
17
|
-
}
|
|
18
|
-
const {
|
|
19
|
-
request,
|
|
20
|
-
assets,
|
|
21
|
-
status: explicitStatus,
|
|
22
|
-
headers: explicitHeaders,
|
|
23
|
-
serializations: explicitSerializations,
|
|
24
|
-
waitUntil = noop,
|
|
25
|
-
stream: shouldStream = false,
|
|
26
|
-
renderHTML = true
|
|
27
|
-
} = options;
|
|
28
|
-
const baseURL = request.URL ?? new URL(request.url);
|
|
29
|
-
const browserResponse = new BrowserResponse({
|
|
30
|
-
request,
|
|
31
|
-
status: explicitStatus,
|
|
32
|
-
headers: new Headers(explicitHeaders),
|
|
33
|
-
serializations: explicitSerializations
|
|
34
|
-
});
|
|
35
|
-
let appStream;
|
|
36
|
-
if (shouldStream === false && element != null) {
|
|
37
|
-
let rendered;
|
|
38
|
-
try {
|
|
39
|
-
rendered = await renderToStringAsync(
|
|
40
|
-
/* @__PURE__ */ jsx(ServerContext, { assets, browser: browserResponse, children: element })
|
|
41
|
-
);
|
|
42
|
-
} catch (error) {
|
|
43
|
-
if (error instanceof Response) {
|
|
44
|
-
const mergedHeaders = new Headers(browserResponse.headers);
|
|
45
|
-
for (const [key, value] of error.headers) {
|
|
46
|
-
if (key.toLowerCase() === "set-cookie") continue;
|
|
47
|
-
mergedHeaders.set(key, value);
|
|
48
|
-
}
|
|
49
|
-
for (const setCookie of error.headers.getSetCookie()) {
|
|
50
|
-
mergedHeaders.append("Set-Cookie", setCookie);
|
|
51
|
-
}
|
|
52
|
-
const mergedResponse = new EnhancedResponse(error.body, {
|
|
53
|
-
status: Math.max(browserResponse.status.value, error.status),
|
|
54
|
-
headers: mergedHeaders
|
|
55
|
-
});
|
|
56
|
-
return mergedResponse;
|
|
57
|
-
}
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
const appTransformStream = new TransformStream();
|
|
61
|
-
const appWriter = appTransformStream.writable.getWriter();
|
|
62
|
-
appStream = appTransformStream.readable;
|
|
63
|
-
appWriter.write(rendered);
|
|
64
|
-
appWriter.close();
|
|
65
|
-
}
|
|
66
|
-
if (appStream == null) {
|
|
67
|
-
const appTransformStream = new TransformStream();
|
|
68
|
-
appStream = appTransformStream.readable;
|
|
69
|
-
const renderAppStream = async function renderAppStream2() {
|
|
70
|
-
const appWriter = appTransformStream.writable.getWriter();
|
|
71
|
-
if (element != null) {
|
|
72
|
-
const rendered = await renderToStringAsync(
|
|
73
|
-
/* @__PURE__ */ jsx(ServerContext, { assets, browser: browserResponse, children: element })
|
|
74
|
-
);
|
|
75
|
-
appWriter.write(rendered);
|
|
76
|
-
}
|
|
77
|
-
appWriter.close();
|
|
78
|
-
};
|
|
79
|
-
waitUntil(renderAppStream());
|
|
80
|
-
}
|
|
81
|
-
const body = await renderToHTMLBody(appStream);
|
|
82
|
-
return new HTMLResponse(body, {
|
|
83
|
-
status: browserResponse.status.value,
|
|
84
|
-
headers: browserResponse.headers
|
|
85
|
-
});
|
|
86
|
-
async function renderToHTMLBody(content) {
|
|
87
|
-
if (typeof renderHTML === "function") {
|
|
88
|
-
const body3 = await renderHTML(content, {
|
|
89
|
-
response: browserResponse
|
|
90
|
-
});
|
|
91
|
-
return body3;
|
|
92
|
-
} else if (renderHTML === false || renderHTML === "fragment") {
|
|
93
|
-
return content;
|
|
94
|
-
}
|
|
95
|
-
const responseStream = new TextEncoderStream();
|
|
96
|
-
const body2 = responseStream.readable;
|
|
97
|
-
const renderFullHTML = async function renderFullHTML2() {
|
|
98
|
-
const writer = responseStream.writable.getWriter();
|
|
99
|
-
writer.write(`<!DOCTYPE html>`);
|
|
100
|
-
const synchronousAssets = assets?.entry({
|
|
101
|
-
request,
|
|
102
|
-
modules: browserResponse.assets.get({ timing: "load" })
|
|
103
|
-
});
|
|
104
|
-
const preloadAssets = assets?.modules(
|
|
105
|
-
browserResponse.assets.get({ timing: "preload" }),
|
|
106
|
-
{
|
|
107
|
-
request
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
if (synchronousAssets) {
|
|
111
|
-
for (const style of synchronousAssets.styles) {
|
|
112
|
-
browserResponse.headers.append(
|
|
113
|
-
"Link",
|
|
114
|
-
preloadHeader(styleAssetPreloadAttributes(style))
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
for (const script of synchronousAssets.scripts) {
|
|
118
|
-
browserResponse.headers.append(
|
|
119
|
-
"Link",
|
|
120
|
-
preloadHeader(scriptAssetPreloadAttributes(script))
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const htmlContent = renderToStaticMarkup(
|
|
125
|
-
/* @__PURE__ */ jsx(BrowserEffectsAreActiveContext.Provider, { value: false, children: /* @__PURE__ */ jsxs("html", { ...browserResponse.htmlAttributes.value, children: [
|
|
126
|
-
/* @__PURE__ */ jsxs("head", { children: [
|
|
127
|
-
/* @__PURE__ */ jsx(Title, { children: browserResponse.title.value }),
|
|
128
|
-
browserResponse.links.value.map((link) => /* @__PURE__ */ jsx(Link, { ...link })),
|
|
129
|
-
browserResponse.metas.value.map((meta) => /* @__PURE__ */ jsx(Meta, { ...meta })),
|
|
130
|
-
browserResponse.serializations.value.map(({ name, content: content2 }) => /* @__PURE__ */ jsx(Serialization, { name, content: content2 })),
|
|
131
|
-
synchronousAssets?.scripts.map((script) => /* @__PURE__ */ jsx(
|
|
132
|
-
ScriptAsset,
|
|
133
|
-
{
|
|
134
|
-
asset: script,
|
|
135
|
-
baseURL
|
|
136
|
-
},
|
|
137
|
-
script.source
|
|
138
|
-
)),
|
|
139
|
-
synchronousAssets?.styles.map((style) => /* @__PURE__ */ jsx(
|
|
140
|
-
StyleAsset,
|
|
141
|
-
{
|
|
142
|
-
asset: style,
|
|
143
|
-
baseURL
|
|
144
|
-
},
|
|
145
|
-
style.source
|
|
146
|
-
)),
|
|
147
|
-
preloadAssets?.styles.map((style) => /* @__PURE__ */ jsx(
|
|
148
|
-
StyleAssetPreload,
|
|
149
|
-
{
|
|
150
|
-
asset: style,
|
|
151
|
-
baseURL
|
|
152
|
-
},
|
|
153
|
-
style.source
|
|
154
|
-
)),
|
|
155
|
-
preloadAssets?.scripts.map((script) => /* @__PURE__ */ jsx(
|
|
156
|
-
ScriptAssetPreload,
|
|
157
|
-
{
|
|
158
|
-
asset: script,
|
|
159
|
-
baseURL
|
|
160
|
-
},
|
|
161
|
-
script.source
|
|
162
|
-
))
|
|
163
|
-
] }),
|
|
164
|
-
/* @__PURE__ */ jsx(
|
|
165
|
-
"body",
|
|
166
|
-
{
|
|
167
|
-
...browserResponse.bodyAttributes.value,
|
|
168
|
-
dangerouslySetInnerHTML: { __html: "%%CONTENT%%" }
|
|
169
|
-
}
|
|
170
|
-
)
|
|
171
|
-
] }) })
|
|
172
|
-
);
|
|
173
|
-
const [firstChunk, secondChunk] = htmlContent.split("%%CONTENT%%");
|
|
174
|
-
writer.write(firstChunk);
|
|
175
|
-
if (element != null) writer.write(`<div id="app">`);
|
|
176
|
-
const reader = content.getReader();
|
|
177
|
-
while (true) {
|
|
178
|
-
const { done, value } = await reader.read();
|
|
179
|
-
if (done) {
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
writer.write(value);
|
|
183
|
-
}
|
|
184
|
-
if (element != null) writer.write(`</div>`);
|
|
185
|
-
const newSynchronousAssets = assets?.entry({
|
|
186
|
-
request,
|
|
187
|
-
modules: browserResponse.assets.get({ timing: "load" })
|
|
188
|
-
});
|
|
189
|
-
const newPreloadAssets = assets?.modules(
|
|
190
|
-
browserResponse.assets.get({ timing: "preload" }),
|
|
191
|
-
{
|
|
192
|
-
request
|
|
193
|
-
}
|
|
194
|
-
);
|
|
195
|
-
if (newSynchronousAssets) {
|
|
196
|
-
const diffedSynchronousAssets = diffBrowserAssetsEntries(
|
|
197
|
-
newSynchronousAssets,
|
|
198
|
-
synchronousAssets
|
|
199
|
-
);
|
|
200
|
-
const diffedPreloadAssets = diffBrowserAssetsEntries(
|
|
201
|
-
newPreloadAssets,
|
|
202
|
-
preloadAssets
|
|
203
|
-
);
|
|
204
|
-
const additionalAssetsContent = renderToStaticMarkup(
|
|
205
|
-
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
206
|
-
diffedSynchronousAssets.scripts.map((script) => /* @__PURE__ */ jsx(
|
|
207
|
-
ScriptAsset,
|
|
208
|
-
{
|
|
209
|
-
asset: script,
|
|
210
|
-
baseURL
|
|
211
|
-
},
|
|
212
|
-
script.source
|
|
213
|
-
)),
|
|
214
|
-
diffedSynchronousAssets.styles.map((style) => /* @__PURE__ */ jsx(StyleAsset, { asset: style, baseURL }, style.source)),
|
|
215
|
-
diffedPreloadAssets.styles.map((style) => /* @__PURE__ */ jsx(
|
|
216
|
-
StyleAssetPreload,
|
|
217
|
-
{
|
|
218
|
-
asset: style,
|
|
219
|
-
baseURL
|
|
220
|
-
},
|
|
221
|
-
style.source
|
|
222
|
-
)),
|
|
223
|
-
diffedPreloadAssets.scripts.map((script) => /* @__PURE__ */ jsx(
|
|
224
|
-
ScriptAssetPreload,
|
|
225
|
-
{
|
|
226
|
-
asset: script,
|
|
227
|
-
baseURL
|
|
228
|
-
},
|
|
229
|
-
script.source
|
|
230
|
-
))
|
|
231
|
-
] })
|
|
232
|
-
);
|
|
233
|
-
writer.write(additionalAssetsContent);
|
|
234
|
-
}
|
|
235
|
-
writer.write(secondChunk);
|
|
236
|
-
writer.close();
|
|
237
|
-
};
|
|
238
|
-
waitUntil(renderFullHTML());
|
|
239
|
-
return body2;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
function preloadHeader(attributes) {
|
|
243
|
-
const {
|
|
244
|
-
as,
|
|
245
|
-
rel = "preload",
|
|
246
|
-
href,
|
|
247
|
-
crossOrigin,
|
|
248
|
-
crossorigin
|
|
249
|
-
} = attributes;
|
|
250
|
-
const finalCrossOrigin = crossOrigin ?? crossorigin;
|
|
251
|
-
let header = `<${href}>; rel="${rel}"; as="${as}"`;
|
|
252
|
-
if (finalCrossOrigin === "" || finalCrossOrigin === true) {
|
|
253
|
-
header += `; crossorigin`;
|
|
254
|
-
} else if (typeof finalCrossOrigin === "string") {
|
|
255
|
-
header += `; crossorigin="${finalCrossOrigin}"`;
|
|
256
|
-
}
|
|
257
|
-
return header;
|
|
258
|
-
}
|
|
259
|
-
function diffBrowserAssetsEntries(newList, oldList) {
|
|
260
|
-
const oldStyles = new Set(oldList.styles.map((style) => style.source));
|
|
261
|
-
const oldScripts = new Set(oldList.scripts.map((script) => script.source));
|
|
262
|
-
return {
|
|
263
|
-
styles: newList.styles.filter((style) => !oldStyles.has(style.source)),
|
|
264
|
-
scripts: newList.scripts.filter((script) => !oldScripts.has(script.source))
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
function noop(..._args) {
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export { renderToResponse };
|