@solidjs/start 0.4.8 → 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,54 +13,94 @@ import {
|
|
|
13
13
|
} from 'seroval-plugins/web';
|
|
14
14
|
import { createIslandReference } from "../server/islands";
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
class SerovalChunkReader {
|
|
17
|
+
constructor(stream) {
|
|
18
|
+
this.reader = stream.getReader();
|
|
19
|
+
this.buffer = '';
|
|
20
|
+
this.done = false;
|
|
19
21
|
}
|
|
20
|
-
const reader = response.body.getReader();
|
|
21
22
|
|
|
22
|
-
async
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
await pop();
|
|
23
|
+
async readChunk() {
|
|
24
|
+
// if there's no chunk, read again
|
|
25
|
+
const chunk = await this.reader.read();
|
|
26
|
+
if (!chunk.done) {
|
|
27
|
+
// repopulate the buffer
|
|
28
|
+
this.buffer += new TextDecoder().decode(chunk.value);
|
|
29
|
+
} else {
|
|
30
|
+
this.done = true;
|
|
33
31
|
}
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (split !== "") {
|
|
46
|
-
const current = deserialize(split);
|
|
47
|
-
if (pending) {
|
|
48
|
-
revived = current;
|
|
49
|
-
pending = false;
|
|
34
|
+
async next() {
|
|
35
|
+
// Check if the buffer is empty
|
|
36
|
+
if (this.buffer === '') {
|
|
37
|
+
// if we are already done...
|
|
38
|
+
if (this.done) {
|
|
39
|
+
return {
|
|
40
|
+
done: true,
|
|
41
|
+
value: undefined,
|
|
42
|
+
};
|
|
50
43
|
}
|
|
44
|
+
// Otherwise, read a new chunk
|
|
45
|
+
await this.readChunk();
|
|
46
|
+
return await this.next();
|
|
51
47
|
}
|
|
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.
|
|
57
|
+
if (this.done) {
|
|
58
|
+
throw new Error('Malformed server function stream.')
|
|
59
|
+
}
|
|
60
|
+
// Otherwise, we read more chunks
|
|
61
|
+
await this.readChunk();
|
|
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
|
+
};
|
|
52
72
|
}
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
async drain() {
|
|
75
|
+
while (true) {
|
|
76
|
+
const result = await this.next();
|
|
77
|
+
if (result.done) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
60
80
|
}
|
|
61
|
-
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function deserializeStream(id, response) {
|
|
85
|
+
if (!response.body) {
|
|
86
|
+
throw new Error("missing body");
|
|
87
|
+
}
|
|
88
|
+
const reader = new SerovalChunkReader(response.body);
|
|
89
|
+
|
|
90
|
+
const result = await reader.next();
|
|
91
|
+
|
|
92
|
+
if (!result.done) {
|
|
93
|
+
reader.drain().then(
|
|
94
|
+
() => {
|
|
95
|
+
delete $R[id];
|
|
96
|
+
},
|
|
97
|
+
() => {
|
|
98
|
+
// no-op
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
62
102
|
|
|
63
|
-
return
|
|
103
|
+
return result.value;
|
|
64
104
|
}
|
|
65
105
|
|
|
66
106
|
let INSTANCE = 0;
|
|
@@ -108,7 +148,7 @@ async function fetchServerFunction(base, id, args) {
|
|
|
108
148
|
let result;
|
|
109
149
|
if (contentType && contentType.startsWith("text/plain")) {
|
|
110
150
|
result = await response.text();
|
|
111
|
-
} else if(contentType && contentType.startsWith("application/json")) {
|
|
151
|
+
} else if (contentType && contentType.startsWith("application/json")) {
|
|
112
152
|
result = await response.json();
|
|
113
153
|
} else {
|
|
114
154
|
result = deserializeStream(instance, response);
|
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": {
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"solid-js": "^1.8.
|
|
47
|
-
"vinxi": "0.1.
|
|
46
|
+
"solid-js": "^1.8.11",
|
|
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
|
}
|