@solidjs/start 1.2.1 → 2.0.0-alpha.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/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/dist/client/StartClient.d.ts +0 -1
- package/dist/client/StartClient.jsx +2 -4
- package/dist/client/index.d.ts +2 -3
- package/dist/client/index.jsx +2 -4
- package/dist/client/mount.d.ts +1 -7
- package/dist/client/mount.js +1 -91
- package/dist/client/spa/index.d.ts +1 -2
- package/dist/client/spa/index.jsx +1 -2
- package/dist/config/constants.d.ts +16 -0
- package/dist/config/constants.js +16 -0
- package/dist/config/dev-server.d.ts +2 -0
- package/dist/config/dev-server.js +108 -0
- package/dist/config/fs-router.d.ts +37 -0
- package/dist/config/fs-router.js +141 -0
- package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
- package/dist/config/fs-routes/fs-watcher.js +49 -0
- package/dist/config/fs-routes/index.d.ts +7 -0
- package/dist/config/fs-routes/index.js +107 -0
- package/dist/config/fs-routes/router.d.ts +37 -0
- package/dist/config/fs-routes/router.js +136 -0
- package/dist/config/fs-routes/tree-shake.d.ts +2 -0
- package/dist/config/fs-routes/tree-shake.js +348 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +214 -0
- package/dist/config/lazy.d.ts +3 -0
- package/dist/config/lazy.js +82 -0
- package/dist/config/manifest.d.ts +3 -0
- package/dist/config/manifest.js +74 -0
- package/dist/config/utils.d.ts +4 -0
- package/dist/config/utils.js +6 -0
- package/dist/config/vite-utils.d.ts +16 -0
- package/dist/config/vite-utils.js +81 -0
- package/dist/http/index.d.ts +81 -0
- package/dist/http/index.js +129 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.jsx +5 -5
- package/dist/middleware/index.d.ts +6 -6
- package/dist/middleware/index.js +39 -0
- package/dist/{router/FileRoutes.js → router.jsx} +7 -8
- package/dist/server/StartServer.d.ts +3 -3
- package/dist/server/StartServer.jsx +9 -63
- package/dist/server/assets/index.d.ts +2 -0
- package/dist/server/assets/index.js +52 -0
- package/dist/server/assets/render.d.ts +19 -0
- package/dist/server/{renderAsset.jsx → assets/render.jsx} +1 -1
- package/dist/server/collect-styles.d.ts +3 -0
- package/dist/server/collect-styles.js +69 -0
- package/dist/server/fetchEvent.d.ts +4 -3
- package/dist/server/fetchEvent.js +12 -74
- package/dist/server/fetchEvent.spec.js +18 -197
- package/dist/server/handler.d.ts +6 -12
- package/dist/server/handler.js +193 -96
- package/dist/server/index.d.ts +9 -6
- package/dist/server/index.jsx +14 -6
- package/dist/server/manifest/client-manifest.d.ts +9 -0
- package/dist/server/manifest/client-manifest.js +6 -0
- package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
- package/dist/server/manifest/dev-client-manifest.js +24 -0
- package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
- package/dist/server/manifest/dev-ssr-manifest.js +23 -0
- package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
- package/dist/server/manifest/prod-client-manifest.js +26 -0
- package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
- package/dist/server/manifest/prod-ssr-manifest.js +85 -0
- package/dist/server/manifest/ssr-manifest.d.ts +4 -0
- package/dist/server/manifest/ssr-manifest.js +6 -0
- package/dist/{router → server}/routes.d.ts +5 -10
- package/dist/{router → server}/routes.js +32 -33
- package/dist/{runtime → server}/server-fns-runtime.d.ts +1 -1
- package/dist/{runtime → server}/server-fns-runtime.js +8 -7
- package/dist/server/server-functions-handler.d.ts +2 -0
- package/dist/{runtime/server-handler.js → server/server-functions-handler.js} +57 -97
- package/dist/server/server-runtime.d.ts +3 -0
- package/dist/{runtime → server}/server-runtime.js +17 -24
- package/dist/server/spa/StartServer.d.ts +1 -1
- package/dist/server/spa/StartServer.jsx +7 -9
- package/dist/server/spa/handler.d.ts +3 -3
- package/dist/server/spa/handler.js +9 -11
- package/dist/server/spa/index.d.ts +4 -3
- package/dist/server/spa/index.jsx +4 -3
- package/dist/server/types.d.ts +7 -9
- package/dist/server/util.d.ts +2 -0
- package/dist/server/util.js +8 -0
- package/dist/shared/ErrorBoundary.jsx +2 -2
- package/dist/shared/HttpHeader.jsx +4 -2
- package/dist/shared/{HttpStatusCode.jsx → HttpStatusCode.js} +3 -1
- package/dist/shared/dev-overlay/CodeView.d.ts +1 -1
- package/dist/shared/dev-overlay/CodeView.jsx +23 -34
- package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +2 -2
- package/dist/shared/dev-overlay/DevOverlayDialog.jsx +73 -64
- package/dist/shared/dev-overlay/createStackFrame.js +3 -3
- package/dist/shared/dev-overlay/get-source-map.d.ts +1 -1
- package/dist/shared/dev-overlay/get-source-map.js +5 -5
- package/dist/shared/dev-overlay/icons.d.ts +10 -10
- package/dist/shared/dev-overlay/icons.jsx +91 -91
- package/dist/shared/dev-overlay/index.jsx +6 -9
- package/dist/shared/lazy.d.ts +3 -0
- package/dist/shared/lazy.js +42 -0
- package/dist/shared/serverFunction.d.ts +1 -1
- package/env.d.ts +2 -19
- package/package.json +44 -65
- package/scripts/build.js +15 -0
- package/scripts/validate-imports.js +316 -0
- package/src/client/StartClient.tsx +34 -0
- package/src/client/index.tsx +2 -0
- package/src/client/mount.ts +1 -0
- package/src/client/spa/index.tsx +9 -0
- package/src/config/constants.ts +19 -0
- package/src/config/dev-server.ts +145 -0
- package/{config/fs-router.js → src/config/fs-router.ts} +49 -29
- package/src/config/fs-routes/fs-watcher.ts +77 -0
- package/src/config/fs-routes/index.ts +136 -0
- package/src/config/fs-routes/router.ts +169 -0
- package/src/config/fs-routes/tree-shake.ts +371 -0
- package/src/config/index.ts +233 -0
- package/src/config/lazy.ts +100 -0
- package/src/config/manifest.ts +84 -0
- package/src/config/utils.ts +5 -0
- package/src/config/vite-utils.ts +109 -0
- package/src/env.d.ts +17 -0
- package/src/http/index.ts +216 -0
- package/src/index.tsx +7 -0
- package/src/internal.d.ts +14 -0
- package/src/middleware/index.ts +72 -0
- package/src/router.tsx +37 -0
- package/src/server/StartServer.tsx +56 -0
- package/src/server/assets/index.ts +70 -0
- package/src/server/assets/render.tsx +46 -0
- package/src/server/collect-styles.ts +87 -0
- package/src/server/fetchEvent.spec.ts +85 -0
- package/src/server/fetchEvent.ts +36 -0
- package/src/server/handler.ts +257 -0
- package/src/server/index.tsx +29 -0
- package/src/server/manifest/client-manifest.ts +8 -0
- package/src/server/manifest/dev-client-manifest.ts +21 -0
- package/src/server/manifest/dev-ssr-manifest.ts +23 -0
- package/src/server/manifest/prod-client-manifest.ts +21 -0
- package/src/server/manifest/prod-ssr-manifest.ts +109 -0
- package/src/server/manifest/ssr-manifest.ts +10 -0
- package/src/server/routes.ts +126 -0
- package/src/server/server-fns-runtime.ts +31 -0
- package/src/server/server-functions-handler.ts +339 -0
- package/src/server/server-runtime.ts +240 -0
- package/src/server/spa/StartServer.tsx +40 -0
- package/src/server/spa/handler.ts +29 -0
- package/src/server/spa/index.tsx +5 -0
- package/src/server/types.ts +82 -0
- package/src/server/util.ts +12 -0
- package/src/shared/ErrorBoundary.tsx +52 -0
- package/src/shared/GET.ts +8 -0
- package/src/shared/HttpHeader.tsx +42 -0
- package/src/shared/HttpStatusCode.ts +27 -0
- package/src/shared/clientOnly.ts +44 -0
- package/src/shared/dev-overlay/CodeView.tsx +92 -0
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +316 -0
- package/src/shared/dev-overlay/createStackFrame.ts +74 -0
- package/src/shared/dev-overlay/download.ts +6 -0
- package/src/shared/dev-overlay/env.d.ts +4 -0
- package/src/shared/dev-overlay/get-source-map.ts +33 -0
- package/src/shared/dev-overlay/icons.tsx +456 -0
- package/src/shared/dev-overlay/index.tsx +63 -0
- package/src/shared/dev-overlay/styles.css +292 -0
- package/src/shared/lazy.ts +52 -0
- package/src/shared/serverFunction.ts +10 -0
- package/src/virtual.d.ts +27 -0
- package/tsconfig.json +23 -0
- package/vitest.config.ts +9 -0
- package/config/index.d.ts +0 -40
- package/config/index.js +0 -304
- package/config/server-components.js +0 -106
- package/dist/client/islands.d.ts +0 -7
- package/dist/client/islands.jsx +0 -10
- package/dist/middleware/index.jsx +0 -35
- package/dist/router/index.d.ts +0 -1
- package/dist/router/index.jsx +0 -2
- package/dist/router/lazyRoute.d.ts +0 -6
- package/dist/router/lazyRoute.js +0 -53
- package/dist/runtime/server-handler.d.ts +0 -2
- package/dist/runtime/server-runtime.d.ts +0 -3
- package/dist/server/islands/index.d.ts +0 -19
- package/dist/server/islands/index.jsx +0 -62
- package/dist/server/islands/utils.d.ts +0 -1
- package/dist/server/islands/utils.jsx +0 -85
- package/dist/server/pageEvent.d.ts +0 -2
- package/dist/server/pageEvent.js +0 -56
- package/dist/server/renderAsset.d.ts +0 -2
- /package/dist/{router/FileRoutes.d.ts → router.d.ts} +0 -0
- /package/dist/shared/{clientOnly.jsx → clientOnly.js} +0 -0
- /package/dist/shared/{serverFunction.jsx → serverFunction.js} +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
import ErrorStackParser from "error-stack-parser";
|
|
3
|
+
import * as htmlToImage from "html-to-image";
|
|
4
|
+
import type { JSX } from "solid-js";
|
|
5
|
+
import { ErrorBoundary, For, Show, Suspense, createMemo, createSignal } from "solid-js";
|
|
6
|
+
import { Portal } from "solid-js/web";
|
|
7
|
+
// @ts-ignore - terracotta module resolution issue with NodeNext
|
|
8
|
+
import { Dialog, DialogOverlay, DialogPanel, Select, SelectOption } from "terracotta";
|
|
9
|
+
import info from "../../../package.json" with { type: "json" };
|
|
10
|
+
import { CodeView } from "./CodeView.tsx";
|
|
11
|
+
import { createStackFrame, type StackFrameSource } from "./createStackFrame.ts";
|
|
12
|
+
import download from "./download.ts";
|
|
13
|
+
import {
|
|
14
|
+
ArrowLeftIcon,
|
|
15
|
+
ArrowRightIcon,
|
|
16
|
+
CameraIcon,
|
|
17
|
+
DiscordIcon,
|
|
18
|
+
GithubIcon,
|
|
19
|
+
RefreshIcon,
|
|
20
|
+
SolidStartIcon,
|
|
21
|
+
ViewCompiledIcon,
|
|
22
|
+
ViewOriginalIcon,
|
|
23
|
+
} from "./icons.tsx";
|
|
24
|
+
import "./styles.css";
|
|
25
|
+
|
|
26
|
+
export function classNames(...classes: (string | boolean | undefined)[]): string {
|
|
27
|
+
return classes.filter(Boolean).join(" ");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ErrorInfoProps {
|
|
31
|
+
error: unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ErrorInfo(props: ErrorInfoProps): JSX.Element {
|
|
35
|
+
const error = createMemo(() => {
|
|
36
|
+
const e = props.error;
|
|
37
|
+
|
|
38
|
+
if (e instanceof Error) {
|
|
39
|
+
return { name: e.name, message: e.message };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (e instanceof ErrorEvent) {
|
|
43
|
+
return { message: e.message };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { message: (e as Error).toString() };
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<span class="dev-overlay-error-info">
|
|
51
|
+
<span class="dev-overlay-error-info-name">{error().name}</span>
|
|
52
|
+
<span class="dev-overlay-error-info-message">{error().message}</span>
|
|
53
|
+
</span>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface StackFramesContentProps {
|
|
58
|
+
error: Error;
|
|
59
|
+
isCompiled: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getFileName(source: string): string {
|
|
63
|
+
try {
|
|
64
|
+
const path = source.startsWith("/") ? new URL(source, "file://") : new URL(source);
|
|
65
|
+
const paths = path.pathname.split("/");
|
|
66
|
+
return paths[paths.length - 1]!;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return getFileName(`/${source}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getFilePath(source: StackFrameSource) {
|
|
73
|
+
const line = source.line ? `:${source.line}` : "";
|
|
74
|
+
const column = source.column ? `:${source.column}` : "";
|
|
75
|
+
return `${getFileName(source.source)}${line}${column}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function CodeFallback(): JSX.Element {
|
|
79
|
+
return (
|
|
80
|
+
<div class="dev-overlay-stack-frames-code-fallback">
|
|
81
|
+
<span>Source not available.</span>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function StackFramesContent(props: StackFramesContentProps) {
|
|
87
|
+
const stackframes = ErrorStackParser.parse(props.error);
|
|
88
|
+
|
|
89
|
+
const [selectedFrame, setSelectedFrame] = createSignal(stackframes[0]!);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div class="dev-overlay-stack-frames-content">
|
|
93
|
+
<div class="dev-overlay-stack-frames-code">
|
|
94
|
+
<ErrorBoundary fallback={null}>
|
|
95
|
+
{(() => {
|
|
96
|
+
const data = createStackFrame(selectedFrame(), () => props.isCompiled);
|
|
97
|
+
return (
|
|
98
|
+
<Suspense fallback={<CodeFallback />}>
|
|
99
|
+
<Show when={data()} keyed fallback={<CodeFallback />}>
|
|
100
|
+
{source => (
|
|
101
|
+
<>
|
|
102
|
+
<span class="dev-overlay-stack-frames-code-source">{source.source}</span>
|
|
103
|
+
<div class="dev-overlay-stack-frames-code-container">
|
|
104
|
+
<CodeView
|
|
105
|
+
fileName={source.source}
|
|
106
|
+
line={source.line}
|
|
107
|
+
content={source.content}
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
</>
|
|
111
|
+
)}
|
|
112
|
+
</Show>
|
|
113
|
+
</Suspense>
|
|
114
|
+
);
|
|
115
|
+
})()}
|
|
116
|
+
</ErrorBoundary>
|
|
117
|
+
</div>
|
|
118
|
+
<Select<ErrorStackParser.StackFrame>
|
|
119
|
+
class="dev-overlay-stack-frames"
|
|
120
|
+
value={selectedFrame()}
|
|
121
|
+
onChange={setSelectedFrame}
|
|
122
|
+
>
|
|
123
|
+
<For each={stackframes}>
|
|
124
|
+
{current => (
|
|
125
|
+
<ErrorBoundary
|
|
126
|
+
fallback={
|
|
127
|
+
<div class="dev-overlay-stack-frame">
|
|
128
|
+
<span class="dev-overlay-stack-frame-function">
|
|
129
|
+
{current.functionName ?? "<anonymous>"}
|
|
130
|
+
</span>
|
|
131
|
+
<span class="dev-overlay-stack-frame-file">
|
|
132
|
+
{getFilePath({
|
|
133
|
+
source: current.getFileName()!,
|
|
134
|
+
content: "",
|
|
135
|
+
line: current.getLineNumber()!,
|
|
136
|
+
column: current.getColumnNumber()!,
|
|
137
|
+
name: current.getFunctionName(),
|
|
138
|
+
})}
|
|
139
|
+
</span>
|
|
140
|
+
</div>
|
|
141
|
+
}
|
|
142
|
+
>
|
|
143
|
+
{(() => {
|
|
144
|
+
const data = createStackFrame(current, () => props.isCompiled);
|
|
145
|
+
return (
|
|
146
|
+
<Suspense>
|
|
147
|
+
<Show when={data()} keyed>
|
|
148
|
+
{source => (
|
|
149
|
+
<SelectOption class="dev-overlay-stack-frame" value={current}>
|
|
150
|
+
<span class="dev-overlay-stack-frame-function">
|
|
151
|
+
{source.name ?? "<anonymous>"}
|
|
152
|
+
</span>
|
|
153
|
+
<span class="dev-overlay-stack-frame-file">{getFilePath(source)}</span>
|
|
154
|
+
</SelectOption>
|
|
155
|
+
)}
|
|
156
|
+
</Show>
|
|
157
|
+
</Suspense>
|
|
158
|
+
);
|
|
159
|
+
})()}
|
|
160
|
+
</ErrorBoundary>
|
|
161
|
+
)}
|
|
162
|
+
</For>
|
|
163
|
+
</Select>
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface StackFramesProps {
|
|
169
|
+
error: unknown;
|
|
170
|
+
isCompiled: boolean;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function StackFrames(props: StackFramesProps) {
|
|
174
|
+
return (
|
|
175
|
+
<Show when={props.error instanceof Error && props.error} keyed>
|
|
176
|
+
{current => <StackFramesContent error={current} isCompiled={props.isCompiled} />}
|
|
177
|
+
</Show>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface DevOverlayDialogProps {
|
|
182
|
+
errors: any[];
|
|
183
|
+
resetError: () => void;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const ISSUE_THREAD = "https://github.com/solidjs/solid-start/issues/new";
|
|
187
|
+
const DISCORD_INVITE = "https://discord.com/invite/solidjs";
|
|
188
|
+
|
|
189
|
+
export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Element {
|
|
190
|
+
const [currentPage, setCurrentPage] = createSignal(1);
|
|
191
|
+
const [isCompiled, setIsCompiled] = createSignal(false);
|
|
192
|
+
const length = createMemo(() => props.errors.length);
|
|
193
|
+
|
|
194
|
+
const truncated = createMemo(() => {
|
|
195
|
+
return Math.min(currentPage(), length());
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
function goPrev() {
|
|
199
|
+
setCurrentPage(c => {
|
|
200
|
+
if (c > 1) {
|
|
201
|
+
return c - 1;
|
|
202
|
+
}
|
|
203
|
+
return length();
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function goNext() {
|
|
208
|
+
setCurrentPage(c => {
|
|
209
|
+
if (c < length()) {
|
|
210
|
+
return c + 1;
|
|
211
|
+
}
|
|
212
|
+
return 1;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function toggleIsCompiled() {
|
|
217
|
+
setIsCompiled(c => !c);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const [panel, setPanel] = createSignal<HTMLElement>();
|
|
221
|
+
|
|
222
|
+
function downloadScreenshot() {
|
|
223
|
+
const current = panel();
|
|
224
|
+
if (current) {
|
|
225
|
+
htmlToImage
|
|
226
|
+
.toPng(current, {
|
|
227
|
+
style: {
|
|
228
|
+
transform: "scale(0.75)",
|
|
229
|
+
},
|
|
230
|
+
})
|
|
231
|
+
.then(url => {
|
|
232
|
+
download(url, "start-screenshot.png");
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function redirectToGithub() {
|
|
238
|
+
const url = new URL(ISSUE_THREAD);
|
|
239
|
+
url.searchParams.append("labels", "bug");
|
|
240
|
+
url.searchParams.append("labels", "needs+triage");
|
|
241
|
+
url.searchParams.append("template", "bug.yml");
|
|
242
|
+
url.searchParams.append("title", `[Bug?]:` + props.errors[truncated() - 1].toString());
|
|
243
|
+
window.open(url, "_blank")!.focus();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function redirectToDiscord() {
|
|
247
|
+
window.open(DISCORD_INVITE, "_blank")!.focus();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<Portal>
|
|
252
|
+
<Dialog class="dev-overlay" isOpen>
|
|
253
|
+
<div>
|
|
254
|
+
<DialogOverlay class="dev-overlay-background" />
|
|
255
|
+
<DialogPanel ref={setPanel} class="dev-overlay-panel-container">
|
|
256
|
+
<div class="dev-overlay-panel">
|
|
257
|
+
<div class="dev-overlay-navbar">
|
|
258
|
+
<div class="dev-overlay-navbar-left">
|
|
259
|
+
<div class="dev-overlay-version">
|
|
260
|
+
<div>
|
|
261
|
+
<SolidStartIcon title="Solid Start Version" />
|
|
262
|
+
</div>
|
|
263
|
+
<span>{info.version as string}</span>
|
|
264
|
+
</div>
|
|
265
|
+
<Show when={props.errors.length > 1}>
|
|
266
|
+
<div class="dev-overlay-pagination">
|
|
267
|
+
<button class="dev-overlay-button" onClick={goPrev} type="button">
|
|
268
|
+
<ArrowLeftIcon title="Go Previous" />
|
|
269
|
+
</button>
|
|
270
|
+
<div class="dev-overlay-page-counter">
|
|
271
|
+
{`${truncated()} of ${props.errors.length}`}
|
|
272
|
+
</div>
|
|
273
|
+
<button class="dev-overlay-button" onClick={goNext} type="button">
|
|
274
|
+
<ArrowRightIcon title="Go Next" />
|
|
275
|
+
</button>
|
|
276
|
+
</div>
|
|
277
|
+
</Show>
|
|
278
|
+
</div>
|
|
279
|
+
<div class="dev-overlay-controls">
|
|
280
|
+
<button class="dev-overlay-button" onClick={redirectToGithub} type="button">
|
|
281
|
+
<GithubIcon title="Create an issue thread on Github" />
|
|
282
|
+
</button>
|
|
283
|
+
<button class="dev-overlay-button" onClick={redirectToDiscord} type="button">
|
|
284
|
+
<DiscordIcon title="Join our Discord Channel" />
|
|
285
|
+
</button>
|
|
286
|
+
<button class="dev-overlay-button" onClick={downloadScreenshot} type="button">
|
|
287
|
+
<CameraIcon title="Capture Error Overlay" />
|
|
288
|
+
</button>
|
|
289
|
+
<button class="dev-overlay-button" onClick={toggleIsCompiled} type="button">
|
|
290
|
+
<Show
|
|
291
|
+
when={isCompiled()}
|
|
292
|
+
fallback={<ViewOriginalIcon title="View Original Source" />}
|
|
293
|
+
>
|
|
294
|
+
<ViewCompiledIcon title="View Compiled Source" />
|
|
295
|
+
</Show>
|
|
296
|
+
</button>
|
|
297
|
+
<button class="dev-overlay-button" onClick={props.resetError} type="button">
|
|
298
|
+
<RefreshIcon title="Reset Error" />
|
|
299
|
+
</button>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
<Show when={props.errors[truncated() - 1]} keyed>
|
|
303
|
+
{current => (
|
|
304
|
+
<div class="dev-overlay-content">
|
|
305
|
+
<ErrorInfo error={current} />
|
|
306
|
+
<StackFrames error={current} isCompiled={isCompiled()} />
|
|
307
|
+
</div>
|
|
308
|
+
)}
|
|
309
|
+
</Show>
|
|
310
|
+
</div>
|
|
311
|
+
</DialogPanel>
|
|
312
|
+
</div>
|
|
313
|
+
</Dialog>
|
|
314
|
+
</Portal>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type Accessor, createMemo, createResource } from "solid-js";
|
|
2
|
+
import getSourceMap from "./get-source-map.ts";
|
|
3
|
+
|
|
4
|
+
export interface StackFrameSource {
|
|
5
|
+
content: string;
|
|
6
|
+
source: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
line: number;
|
|
9
|
+
column: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getActualFileSource(path: string): string {
|
|
13
|
+
if (path.startsWith("file://")) {
|
|
14
|
+
return "/_build/@fs" + path.substring("file://".length);
|
|
15
|
+
}
|
|
16
|
+
return path;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createStackFrame(stackframe: StackFrame, isCompiled: () => boolean) {
|
|
20
|
+
const [data] = createResource(
|
|
21
|
+
() => ({
|
|
22
|
+
fileName: stackframe.fileName,
|
|
23
|
+
line: stackframe.lineNumber,
|
|
24
|
+
column: stackframe.columnNumber,
|
|
25
|
+
functionName: stackframe.functionName,
|
|
26
|
+
}),
|
|
27
|
+
async source => {
|
|
28
|
+
if (!source.fileName) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const response = await fetch(getActualFileSource(source.fileName));
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const content = await response.text();
|
|
36
|
+
const sourceMap = await getSourceMap(source.fileName, content);
|
|
37
|
+
return {
|
|
38
|
+
source,
|
|
39
|
+
content,
|
|
40
|
+
sourceMap,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const info = createMemo(() => {
|
|
46
|
+
const current = data();
|
|
47
|
+
if (!current) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const { source, content, sourceMap } = current;
|
|
51
|
+
|
|
52
|
+
if (!isCompiled() && source.line && source.column && sourceMap) {
|
|
53
|
+
const result = sourceMap.originalPositionFor({
|
|
54
|
+
line: source.line,
|
|
55
|
+
column: source.column,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
...result,
|
|
60
|
+
content: sourceMap.sourceContentFor(result.source),
|
|
61
|
+
} as StackFrameSource;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
source: source.fileName,
|
|
66
|
+
line: source.line,
|
|
67
|
+
column: source.column,
|
|
68
|
+
name: source.functionName,
|
|
69
|
+
content,
|
|
70
|
+
} as StackFrameSource;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return info as Accessor<StackFrameSource>;
|
|
74
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RawSourceMap, SourceMapConsumer } from "source-map-js";
|
|
2
|
+
|
|
3
|
+
const INLINE_SOURCEMAP_REGEX = /^data:application\/json[^,]+base64,/;
|
|
4
|
+
const SOURCEMAP_REGEX =
|
|
5
|
+
/(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^*]+?)[ \t]*(?:\*\/)[ \t]*$)/;
|
|
6
|
+
|
|
7
|
+
export default async function getSourceMap(
|
|
8
|
+
url: string,
|
|
9
|
+
content: string,
|
|
10
|
+
): Promise<SourceMapConsumer | null> {
|
|
11
|
+
const lines = content.split("\n");
|
|
12
|
+
let sourceMapUrl: string | undefined;
|
|
13
|
+
for (let i = lines.length - 1; i >= 0 && !sourceMapUrl; i--) {
|
|
14
|
+
const result = lines[i]!.match(SOURCEMAP_REGEX);
|
|
15
|
+
if (result) {
|
|
16
|
+
sourceMapUrl = result[1];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!sourceMapUrl) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!(INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) || sourceMapUrl.startsWith("/"))) {
|
|
25
|
+
// Resolve path if it's a relative access
|
|
26
|
+
const parsedURL = url.split("/");
|
|
27
|
+
parsedURL[parsedURL.length - 1] = sourceMapUrl;
|
|
28
|
+
sourceMapUrl = parsedURL.join("/");
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(sourceMapUrl);
|
|
31
|
+
const rawSourceMap: RawSourceMap = await response.json();
|
|
32
|
+
return new SourceMapConsumer(rawSourceMap);
|
|
33
|
+
}
|