@solidjs/start 0.4.9 → 0.4.10
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/config/server-handler.js
CHANGED
|
@@ -22,6 +22,13 @@ import {
|
|
|
22
22
|
} from "vinxi/server";
|
|
23
23
|
import { getFetchEvent } from "../server/middleware";
|
|
24
24
|
|
|
25
|
+
function createChunk(data) {
|
|
26
|
+
const bytes = data.length;
|
|
27
|
+
const baseHex = bytes.toString(16);
|
|
28
|
+
const totalHex = '00000000'.substring(0, 8 - baseHex.length) + baseHex; // 32-bit
|
|
29
|
+
return new TextEncoder().encode(`;0x${totalHex};${data}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
25
32
|
function serializeToStream(id, value) {
|
|
26
33
|
return new ReadableStream({
|
|
27
34
|
start(controller) {
|
|
@@ -40,15 +47,12 @@ function serializeToStream(id, value) {
|
|
|
40
47
|
URLPlugin
|
|
41
48
|
],
|
|
42
49
|
onSerialize(data, initial) {
|
|
43
|
-
|
|
44
|
-
controller.enqueue(new TextEncoder().encode(`${result};\n`));
|
|
50
|
+
controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
|
|
45
51
|
},
|
|
46
52
|
onDone() {
|
|
47
|
-
// controller.enqueue(`delete $R["${id}"];\n`);
|
|
48
53
|
controller.close();
|
|
49
54
|
},
|
|
50
55
|
onError(error) {
|
|
51
|
-
// controller.enqueue(`delete $R["${id}"];\n`);
|
|
52
56
|
controller.error(error);
|
|
53
57
|
}
|
|
54
58
|
});
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from 'seroval-plugins/web';
|
|
14
14
|
import { createIslandReference } from "../server/islands";
|
|
15
15
|
|
|
16
|
-
class
|
|
16
|
+
class SerovalChunkReader {
|
|
17
17
|
constructor(stream) {
|
|
18
18
|
this.reader = stream.getReader();
|
|
19
19
|
this.buffer = '';
|
|
@@ -31,10 +31,10 @@ class ChunkReader {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async
|
|
34
|
+
async next() {
|
|
35
35
|
// Check if the buffer is empty
|
|
36
36
|
if (this.buffer === '') {
|
|
37
|
-
// if we are already
|
|
37
|
+
// if we are already done...
|
|
38
38
|
if (this.done) {
|
|
39
39
|
return {
|
|
40
40
|
done: true,
|
|
@@ -43,38 +43,32 @@ class ChunkReader {
|
|
|
43
43
|
}
|
|
44
44
|
// Otherwise, read a new chunk
|
|
45
45
|
await this.readChunk();
|
|
46
|
+
return await this.next();
|
|
46
47
|
}
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.buffer = rest.join('\n');
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async next() {
|
|
61
|
-
try {
|
|
62
|
-
// Attempt to read a valid seroval chunk
|
|
63
|
-
return await this.nextValue();
|
|
64
|
-
} catch (error) {
|
|
65
|
-
// If it happens that there's an error again
|
|
66
|
-
// and we are done reading the buffer
|
|
67
|
-
// then the whole stream is invalid.
|
|
48
|
+
// Read the "byte header"
|
|
49
|
+
// The byte header tells us how big the expected data is
|
|
50
|
+
// so we know how much data we should wait before we
|
|
51
|
+
// deserialize the data
|
|
52
|
+
const bytes = Number.parseInt(this.buffer.substring(1, 11), 16); // ;0x00000000;
|
|
53
|
+
// Check if the buffer has enough bytes to be parsed
|
|
54
|
+
while (bytes > this.buffer.length - 12) {
|
|
55
|
+
// If it's not enough, and the reader is done
|
|
56
|
+
// then the chunk is invalid.
|
|
68
57
|
if (this.done) {
|
|
69
|
-
throw new Error('Malformed server function stream.')
|
|
58
|
+
throw new Error('Malformed server function stream.')
|
|
70
59
|
}
|
|
71
|
-
//
|
|
72
|
-
// we read a new chunk, and hope there's a valid
|
|
73
|
-
// seroval chunk there
|
|
60
|
+
// Otherwise, we read more chunks
|
|
74
61
|
await this.readChunk();
|
|
75
|
-
// Retry again
|
|
76
|
-
return await this.next();
|
|
77
62
|
}
|
|
63
|
+
// Extract the exact chunk as defined by the byte header
|
|
64
|
+
const partial = this.buffer.substring(12, 12 + bytes);
|
|
65
|
+
// The rest goes to the buffer
|
|
66
|
+
this.buffer = this.buffer.substring(12 + bytes);
|
|
67
|
+
// Deserialize the chunk
|
|
68
|
+
return {
|
|
69
|
+
done: false,
|
|
70
|
+
value: deserialize(partial),
|
|
71
|
+
};
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
async drain() {
|
|
@@ -91,7 +85,7 @@ async function deserializeStream(id, response) {
|
|
|
91
85
|
if (!response.body) {
|
|
92
86
|
throw new Error("missing body");
|
|
93
87
|
}
|
|
94
|
-
const reader = new
|
|
88
|
+
const reader = new SerovalChunkReader(response.body);
|
|
95
89
|
|
|
96
90
|
const result = await reader.next();
|
|
97
91
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/start",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"publishConfig": {
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"solid-js": "^1.8.11",
|
|
47
|
-
"vinxi": "^0.1.
|
|
47
|
+
"vinxi": "^0.1.4"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@vinxi/plugin-directives": "^0.1.
|
|
51
|
-
"@vinxi/server-components": "^0.1.
|
|
52
|
-
"@vinxi/server-functions": "^0.1.
|
|
50
|
+
"@vinxi/plugin-directives": "^0.1.2",
|
|
51
|
+
"@vinxi/server-components": "^0.1.2",
|
|
52
|
+
"@vinxi/server-functions": "^0.1.2",
|
|
53
53
|
"defu": "^6.1.2",
|
|
54
54
|
"error-stack-parser": "^2.1.4",
|
|
55
55
|
"html-to-image": "^1.11.11",
|
package/server/middleware.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineMiddleware,
|
|
3
|
-
EventHandlerRequest,
|
|
4
3
|
getRequestIP,
|
|
5
|
-
getRequestURL,
|
|
6
4
|
H3Event,
|
|
7
5
|
sendWebResponse,
|
|
8
6
|
toWebRequest
|
|
@@ -18,15 +16,11 @@ const eventTraps = {
|
|
|
18
16
|
}
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
export function createFetchEvent(event: H3Event
|
|
22
|
-
event
|
|
23
|
-
(event.web = {
|
|
24
|
-
url: getRequestURL(event),
|
|
25
|
-
request: toWebRequest(event)
|
|
26
|
-
});
|
|
19
|
+
export function createFetchEvent(event: H3Event): FetchEvent {
|
|
20
|
+
const request = toWebRequest(event);
|
|
27
21
|
return new Proxy(
|
|
28
22
|
{
|
|
29
|
-
request:
|
|
23
|
+
request: request,
|
|
30
24
|
clientAddress: getRequestIP(event),
|
|
31
25
|
locals: {},
|
|
32
26
|
// @ts-ignore
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { BuiltinLanguage, Highlighter } from 'shikiji';
|
|
2
|
-
import { getHighlighterCore } from 'shikiji/core';
|
|
3
|
-
import { getWasmInlined } from 'shikiji/wasm';
|
|
2
|
+
import { getHighlighterCore, loadWasm } from 'shikiji/core';
|
|
4
3
|
import { createEffect, createResource, type JSX } from 'solid-js';
|
|
5
4
|
|
|
5
|
+
import url from 'shikiji/onig.wasm?url';
|
|
6
|
+
|
|
6
7
|
import langJS from 'shikiji/langs/javascript.mjs';
|
|
7
8
|
import langJSX from 'shikiji/langs/jsx.mjs';
|
|
8
9
|
import langTSX from 'shikiji/langs/tsx.mjs';
|
|
@@ -13,6 +14,7 @@ let HIGHLIGHTER: Highlighter;
|
|
|
13
14
|
|
|
14
15
|
async function loadHighlighter() {
|
|
15
16
|
if (!HIGHLIGHTER) {
|
|
17
|
+
await loadWasm(await fetch(url))
|
|
16
18
|
HIGHLIGHTER = await getHighlighterCore({
|
|
17
19
|
themes: [
|
|
18
20
|
darkPlus,
|
|
@@ -23,7 +25,6 @@ async function loadHighlighter() {
|
|
|
23
25
|
langTS,
|
|
24
26
|
langTSX,
|
|
25
27
|
],
|
|
26
|
-
loadWasm: getWasmInlined,
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
return HIGHLIGHTER;
|
|
@@ -77,7 +78,7 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
|
|
|
77
78
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
78
79
|
const el = lines[i];
|
|
79
80
|
if ((props.line - minLine() - 1) === i) {
|
|
80
|
-
el.
|
|
81
|
+
el.classList.add('dev-overlay-error-line');
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
}
|
package/shared/lazyRoute.tsx
CHANGED
|
@@ -1,60 +1,54 @@
|
|
|
1
1
|
/// <reference types="vinxi/types/client" />
|
|
2
2
|
import { createComponent, lazy, onCleanup } from "solid-js";
|
|
3
|
-
import { appendStyles, cleanupStyles, updateStyles } from "vinxi/css";
|
|
3
|
+
import { appendStyles, cleanupStyles, updateStyles, preloadStyles } from "vinxi/css";
|
|
4
4
|
|
|
5
5
|
import { renderAsset } from "../server/renderAsset";
|
|
6
6
|
|
|
7
|
-
export default function lazyRoute(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
exported = "default",
|
|
12
|
-
) {
|
|
13
|
-
return lazy(async () => {
|
|
14
|
-
if (import.meta.env.DEV) {
|
|
15
|
-
let manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
7
|
+
export default function lazyRoute(component, clientManifest, serverManifest, exported = "default") {
|
|
8
|
+
return lazy(async () => {
|
|
9
|
+
if (import.meta.env.DEV) {
|
|
10
|
+
let manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
const mod = await manifest.inputs[component.src].import();
|
|
13
|
+
if (!mod[exported]) console.error(`Module ${component.src} does not export ${exported}`);
|
|
14
|
+
const Component = mod[exported];
|
|
15
|
+
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
16
|
+
const styles = assets.filter(asset => asset.tag === "style");
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
if (typeof window !== "undefined" && import.meta.hot) {
|
|
19
|
+
import.meta.hot.on("css-update", data => {
|
|
20
|
+
updateStyles(styles, data);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
const Comp = props => {
|
|
25
|
+
if (typeof window !== "undefined") {
|
|
26
|
+
appendStyles(styles);
|
|
27
|
+
}
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
});
|
|
29
|
+
onCleanup(() => {
|
|
30
|
+
if (typeof window !== "undefined") {
|
|
31
|
+
// remove style tags added by vite when a CSS file is imported
|
|
32
|
+
cleanupStyles(styles);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return [...assets.map(asset => renderAsset(asset)), createComponent(Component, props)];
|
|
36
|
+
};
|
|
37
|
+
return { default: Comp };
|
|
38
|
+
} else {
|
|
39
|
+
const mod = await component.import();
|
|
40
|
+
const Component = mod[exported];
|
|
41
|
+
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
42
|
+
const styles = assets.filter(
|
|
43
|
+
asset => asset.tag === "style" || asset.attrs.rel === "stylesheet"
|
|
44
|
+
);
|
|
45
|
+
if (typeof window !== "undefined") {
|
|
46
|
+
preloadStyles(styles);
|
|
47
|
+
}
|
|
48
|
+
const Comp = props => {
|
|
49
|
+
return [...styles.map(asset => renderAsset(asset)), createComponent(Component, props)];
|
|
50
|
+
};
|
|
51
|
+
return { default: Comp };
|
|
52
|
+
}
|
|
53
|
+
});
|
|
60
54
|
}
|