@solidjs/start 0.4.10 → 0.4.11

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/index.js CHANGED
@@ -73,6 +73,9 @@ export function defineConfig(baseConfig = {}) {
73
73
  {
74
74
  name: "ssr",
75
75
  mode: "handler",
76
+ link: {
77
+ client: "client"
78
+ },
76
79
  handler: `${start.appRoot}/entry-server${entryExtension}`,
77
80
  middleware: start.middleware,
78
81
  routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
@@ -85,10 +88,10 @@ export function defineConfig(baseConfig = {}) {
85
88
  ...(userConfig.optimizeDeps || {}),
86
89
  include: [
87
90
  ...(userConfig.optimizeDeps?.include || []),
88
- '@solidjs/start > source-map-js',
89
- '@solidjs/start > error-stack-parser',
90
- ],
91
- },
91
+ "@solidjs/start > source-map-js",
92
+ "@solidjs/start > error-stack-parser"
93
+ ]
94
+ }
92
95
  }),
93
96
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
94
97
 
@@ -138,10 +141,10 @@ export function defineConfig(baseConfig = {}) {
138
141
  ...(userConfig.optimizeDeps || {}),
139
142
  include: [
140
143
  ...(userConfig.optimizeDeps?.include || []),
141
- '@solidjs/start > source-map-js',
142
- '@solidjs/start > error-stack-parser',
143
- ],
144
- },
144
+ "@solidjs/start > source-map-js",
145
+ "@solidjs/start > error-stack-parser"
146
+ ]
147
+ }
145
148
  }),
146
149
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
147
150
  serverFunctions.client({
@@ -189,10 +192,10 @@ export function defineConfig(baseConfig = {}) {
189
192
  ...(userConfig.optimizeDeps || {}),
190
193
  include: [
191
194
  ...(userConfig.optimizeDeps?.include || []),
192
- '@solidjs/start > source-map-js',
193
- '@solidjs/start > error-stack-parser',
194
- ],
195
- },
195
+ "@solidjs/start > source-map-js",
196
+ "@solidjs/start > error-stack-parser"
197
+ ]
198
+ }
196
199
  }),
197
200
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
198
201
 
@@ -3,12 +3,14 @@ import { provideRequestEvent } from "solid-js/web/storage";
3
3
  import { cloneEvent } from "../server/middleware";
4
4
 
5
5
  export function createServerReference(fn, id, name) {
6
+ if (typeof fn !== "function") throw new Error("Export from a 'use server' module must be a function");
6
7
  const baseURL = import.meta.env.SERVER_BASE_URL;
7
8
  return new Proxy(fn, {
8
9
  get(target, prop, receiver) {
9
10
  if (prop === "url") {
10
11
  return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
11
12
  }
13
+ if (prop === "GET") return receiver;
12
14
  },
13
15
  apply(target, thisArg, args) {
14
16
  const ogEvt = getRequestEvent();
@@ -16,16 +16,13 @@ import { sharedConfig } from "solid-js";
16
16
  /* @ts-ignore */
17
17
  import { provideRequestEvent } from "solid-js/web/storage";
18
18
  import invariant from "vinxi/lib/invariant";
19
- import {
20
- eventHandler,
21
- setHeader
22
- } from "vinxi/server";
19
+ import { eventHandler, setHeader } from "vinxi/server";
23
20
  import { getFetchEvent } from "../server/middleware";
24
21
 
25
22
  function createChunk(data) {
26
23
  const bytes = data.length;
27
24
  const baseHex = bytes.toString(16);
28
- const totalHex = '00000000'.substring(0, 8 - baseHex.length) + baseHex; // 32-bit
25
+ const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
29
26
  return new TextEncoder().encode(`;0x${totalHex};${data}`);
30
27
  }
31
28
 
@@ -47,7 +44,9 @@ function serializeToStream(id, value) {
47
44
  URLPlugin
48
45
  ],
49
46
  onSerialize(data, initial) {
50
- controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
47
+ controller.enqueue(
48
+ createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data)
49
+ );
51
50
  },
52
51
  onDone() {
53
52
  controller.close();
@@ -61,7 +60,6 @@ function serializeToStream(id, value) {
61
60
  }
62
61
 
63
62
  async function handleServerFunction(h3Event) {
64
- invariant(h3Event.method === "POST", `Invalid method ${h3Event.method}. Expected POST.`);
65
63
  const event = getFetchEvent(h3Event);
66
64
  const request = event.request;
67
65
 
@@ -84,39 +82,71 @@ async function handleServerFunction(h3Event) {
84
82
  let parsed = [];
85
83
 
86
84
  // grab bound arguments from url when no JS
87
- if (!instance) {
85
+ if (!instance || h3Event.method === "GET") {
88
86
  const args = url.searchParams.get("args");
89
87
  if (args) JSON.parse(args).forEach(arg => parsed.push(arg));
90
88
  }
91
- const contentType = request.headers.get("content-type");
92
- if (
93
- contentType.startsWith("multipart/form-data") ||
94
- contentType.startsWith("application/x-www-form-urlencoded")
95
- ) {
96
- parsed.push(await request.formData());
97
- } else {
98
- parsed = fromJSON(await request.json(), {
99
- plugins: [
100
- CustomEventPlugin,
101
- DOMExceptionPlugin,
102
- EventPlugin,
103
- FormDataPlugin,
104
- HeadersPlugin,
105
- ReadableStreamPlugin,
106
- RequestPlugin,
107
- ResponsePlugin,
108
- URLSearchParamsPlugin,
109
- URLPlugin
110
- ]
111
- });
89
+ if (h3Event.method === "POST") {
90
+ const contentType = request.headers.get("content-type");
91
+ if (
92
+ contentType.startsWith("multipart/form-data") ||
93
+ contentType.startsWith("application/x-www-form-urlencoded")
94
+ ) {
95
+ // workaround for https://github.com/unjs/nitro/issues/1721
96
+ // (issue only in edge runtimes)
97
+ parsed.push(await new Request(request, { ...request, body: event.node.req.body }).formData());
98
+ // what should work when #1721 is fixed
99
+ // parsed.push(await request.formData);
100
+ } else {
101
+ // workaround for https://github.com/unjs/nitro/issues/1721
102
+ // (issue only in edge runtimes)
103
+ const tmpReq = new Request(request, { ...request, body: event.node.req.body })
104
+ // what should work when #1721 is fixed
105
+ // just use request.json() here
106
+ parsed = fromJSON(await tmpReq.json(), {
107
+ plugins: [
108
+ CustomEventPlugin,
109
+ DOMExceptionPlugin,
110
+ EventPlugin,
111
+ FormDataPlugin,
112
+ HeadersPlugin,
113
+ ReadableStreamPlugin,
114
+ RequestPlugin,
115
+ ResponsePlugin,
116
+ URLSearchParamsPlugin,
117
+ URLPlugin
118
+ ]
119
+ });
120
+ }
112
121
  }
113
122
  try {
114
- const result = await provideRequestEvent(event, () => {
123
+ let result = await provideRequestEvent(event, () => {
115
124
  /* @ts-ignore */
116
125
  sharedConfig.context = { event };
117
126
  return action(...parsed);
118
127
  });
119
128
 
129
+ // handle responses
130
+ if (result instanceof Response) {
131
+ if (result.status === 302) {
132
+ return new Response(null, {
133
+ status: instance ? 204 : 302,
134
+ headers: {
135
+ Location: result.headers.get("Location")
136
+ }
137
+ });
138
+ }
139
+ // forward headers
140
+ if (result.headers) {
141
+ for (const [key, value] of result.headers.entries()) {
142
+ setHeader(h3Event, key, value);
143
+ }
144
+ }
145
+ if (result.customBody) {
146
+ result = await result.customBody();
147
+ } else if (result.body == undefined) result = undefined;
148
+ }
149
+
120
150
  // handle no JS success case
121
151
  if (!instance) {
122
152
  const isError = result instanceof Error;
@@ -142,13 +172,24 @@ async function handleServerFunction(h3Event) {
142
172
  setHeader(h3Event, "content-type", "text/javascript");
143
173
  return serializeToStream(instance, result);
144
174
  } catch (x) {
145
- if (x instanceof Response && x.status === 302) {
146
- return new Response(null, {
147
- status: instance ? 204 : 302,
148
- headers: {
149
- Location: x.headers.get("Location")
175
+ if (x instanceof Response) {
176
+ if (x.status === 302) {
177
+ return new Response(null, {
178
+ status: instance ? 204 : 302,
179
+ headers: {
180
+ Location: x.headers.get("Location")
181
+ }
182
+ });
183
+ }
184
+ // forward headers
185
+ if (x.headers) {
186
+ for (const [key, value] of x.headers.entries()) {
187
+ setHeader(h3Event, key, value);
150
188
  }
151
- });
189
+ }
190
+ if (x.customBody) {
191
+ x = await x.customBody();
192
+ } else if (x.body == undefined) x = undefined;
152
193
  }
153
194
  return x;
154
195
  }
@@ -9,14 +9,14 @@ import {
9
9
  RequestPlugin,
10
10
  ResponsePlugin,
11
11
  URLPlugin,
12
- URLSearchParamsPlugin,
13
- } from 'seroval-plugins/web';
12
+ URLSearchParamsPlugin
13
+ } from "seroval-plugins/web";
14
14
  import { createIslandReference } from "../server/islands";
15
15
 
16
16
  class SerovalChunkReader {
17
17
  constructor(stream) {
18
18
  this.reader = stream.getReader();
19
- this.buffer = '';
19
+ this.buffer = "";
20
20
  this.done = false;
21
21
  }
22
22
 
@@ -33,12 +33,12 @@ class SerovalChunkReader {
33
33
 
34
34
  async next() {
35
35
  // Check if the buffer is empty
36
- if (this.buffer === '') {
36
+ if (this.buffer === "") {
37
37
  // if we are already done...
38
38
  if (this.done) {
39
39
  return {
40
40
  done: true,
41
- value: undefined,
41
+ value: undefined
42
42
  };
43
43
  }
44
44
  // Otherwise, read a new chunk
@@ -55,7 +55,7 @@ class SerovalChunkReader {
55
55
  // If it's not enough, and the reader is done
56
56
  // then the chunk is invalid.
57
57
  if (this.done) {
58
- throw new Error('Malformed server function stream.')
58
+ throw new Error("Malformed server function stream.");
59
59
  }
60
60
  // Otherwise, we read more chunks
61
61
  await this.readChunk();
@@ -67,7 +67,7 @@ class SerovalChunkReader {
67
67
  // Deserialize the chunk
68
68
  return {
69
69
  done: false,
70
- value: deserialize(partial),
70
+ value: deserialize(partial)
71
71
  };
72
72
  }
73
73
 
@@ -117,31 +117,47 @@ function createRequest(base, id, instance, body, contentType) {
117
117
  });
118
118
  }
119
119
 
120
- async function fetchServerFunction(base, id, args) {
120
+ async function fetchServerFunction(base, id, method, args) {
121
121
  const instance = `server-fn:${INSTANCE++}`;
122
- const response = await (args.length === 1 && args[0] instanceof FormData
122
+ const response = await (method === "GET"
123
+ ? fetch(base + (args.length ? `&args=${JSON.stringify(args)}` : ""), {
124
+ headers: {
125
+ "x-server-instance": instance
126
+ }
127
+ })
128
+ : args.length === 1 && args[0] instanceof FormData
123
129
  ? createRequest(base, id, instance, args[0])
124
- : createRequest(base, id, instance, JSON.stringify(await Promise.resolve(toJSONAsync(args, {
125
- plugins: [
126
- CustomEventPlugin,
127
- DOMExceptionPlugin,
128
- EventPlugin,
129
- FormDataPlugin,
130
- HeadersPlugin,
131
- ReadableStreamPlugin,
132
- RequestPlugin,
133
- ResponsePlugin,
134
- URLSearchParamsPlugin,
135
- URLPlugin,
136
- ],
137
- }))), "application/json"));
130
+ : createRequest(
131
+ base,
132
+ id,
133
+ instance,
134
+ JSON.stringify(
135
+ await Promise.resolve(
136
+ toJSONAsync(args, {
137
+ plugins: [
138
+ CustomEventPlugin,
139
+ DOMExceptionPlugin,
140
+ EventPlugin,
141
+ FormDataPlugin,
142
+ HeadersPlugin,
143
+ ReadableStreamPlugin,
144
+ RequestPlugin,
145
+ ResponsePlugin,
146
+ URLSearchParamsPlugin,
147
+ URLPlugin
148
+ ]
149
+ })
150
+ )
151
+ ),
152
+ "application/json"
153
+ ));
138
154
 
139
155
  if (response.headers.get("Location")) throw response;
140
156
  if (response.headers.get("X-Revalidate")) {
141
157
  /* ts-ignore-next-line */
142
158
  response.customBody = () => {
143
159
  return deserializeStream(instance, response);
144
- }
160
+ };
145
161
  throw response;
146
162
  }
147
163
  const contentType = response.headers.get("Content-Type");
@@ -166,9 +182,12 @@ export function createServerReference(fn, id, name) {
166
182
  if (prop === "url") {
167
183
  return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
168
184
  }
185
+ if (prop === "GET") {
186
+ return (...args) => fetchServerFunction(`${baseURL}/_server/?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`, `${id}#${name}`, "GET", args);
187
+ }
169
188
  },
170
189
  apply(target, thisArg, args) {
171
- return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, args);
190
+ return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, "POST", args);
172
191
  }
173
192
  });
174
193
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/start",
3
- "version": "0.4.10",
3
+ "version": "0.4.11",
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.11",
47
- "vinxi": "^0.1.4"
46
+ "solid-js": "^1.8.12",
47
+ "vinxi": "^0.1.6"
48
48
  },
49
49
  "dependencies": {
50
- "@vinxi/plugin-directives": "^0.1.2",
51
- "@vinxi/server-components": "^0.1.2",
52
- "@vinxi/server-functions": "^0.1.2",
50
+ "@vinxi/plugin-directives": "^0.1.3",
51
+ "@vinxi/server-components": "^0.1.3",
52
+ "@vinxi/server-functions": "^0.1.3",
53
53
  "defu": "^6.1.2",
54
54
  "error-stack-parser": "^2.1.4",
55
55
  "html-to-image": "^1.11.11",
@@ -59,7 +59,7 @@
59
59
  "source-map-js": "^1.0.2",
60
60
  "terracotta": "^1.0.4",
61
61
  "vite-plugin-inspect": "^0.7.33",
62
- "vite-plugin-solid": "^2.8.0"
62
+ "vite-plugin-solid": "^2.9.1"
63
63
  },
64
64
  "scripts": {
65
65
  "typecheck": "tsc --noEmit --checkJs false --skipLibCheck"
@@ -45,7 +45,7 @@ export async function createPageEvent(ctx: FetchEvent) {
45
45
  components: {
46
46
  status: props => {
47
47
  setResponseStatus(ctx, props.code, props.text);
48
- return () => setResponseStatus(ctx, 200);
48
+ return () => !ctx.handled && setResponseStatus(ctx, 200);
49
49
  },
50
50
  header: props => {
51
51
  if (props.append) {
@@ -55,18 +55,13 @@ export async function createPageEvent(ctx: FetchEvent) {
55
55
  }
56
56
 
57
57
  return () => {
58
- const value = getResponseHeader(ctx, props.name);
59
-
60
- // Todo: review this logic still the same in H3
61
- // H3 supports arrays so its possible there is no need to split..
62
- // typeof check here is to guard but ultimately may be unneeded
63
- if (value && typeof value === "string") {
64
- const values = value.split(", ");
65
- const index = values.indexOf(props.value);
66
- index !== -1 && values.splice(index, 1);
67
- if (values.length) setResponseHeader(ctx, props.name, values.join(", "));
68
- else removeResponseHeader(ctx, props.name);
69
- }
58
+ if (ctx.handled) return;
59
+ let values = getResponseHeader(ctx, props.name);
60
+ if (!Array.isArray(values)) values = [values as string];
61
+ const index = values.indexOf(props.value);
62
+ index !== -1 && values.splice(index, 1);
63
+ if (values.length) setResponseHeader(ctx, props.name, values);
64
+ else removeResponseHeader(ctx, props.name);
70
65
  };
71
66
  }
72
67
  },
package/shared/GET.ts ADDED
@@ -0,0 +1,5 @@
1
+ export function GET<T extends (...args: any[]) => any>(fn: T) {
2
+ return (...args: Parameters<T>) => {
3
+ return (fn as any).GET(...args) as ReturnType<T>;
4
+ };
5
+ }
@@ -190,7 +190,7 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem
190
190
  if (current) {
191
191
  htmlToImage.toPng(current, {
192
192
  style: {
193
- transform: 'scale(1)',
193
+ transform: 'scale(0.75)',
194
194
  },
195
195
  }).then((url) => {
196
196
  download(url, 'start-screenshot.png');
@@ -216,59 +216,61 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem
216
216
  <Dialog class="dev-overlay" isOpen>
217
217
  <div>
218
218
  <DialogOverlay class="dev-overlay-background"/>
219
- <DialogPanel ref={setPanel} class="dev-overlay-panel">
220
- <div class="dev-overlay-navbar">
221
- <div class="dev-overlay-navbar-left">
222
- <div class="dev-overlay-version">
223
- <div>
224
- <SolidStartIcon title="Solid Start Version" />
225
- </div>
226
- <span>{info.version as string}</span>
227
- </div>
228
- <Show when={props.errors.length > 1}>
229
- <div class="dev-overlay-pagination">
230
- <button class="dev-overlay-button" onClick={goPrev} type="button">
231
- <ArrowLeftIcon title="Go Previous" />
232
- </button>
233
- <div class="dev-overlay-page-counter">
234
- {`${truncated()} of ${props.errors.length}`}
219
+ <DialogPanel ref={setPanel} class="dev-overlay-panel-container">
220
+ <div class="dev-overlay-panel">
221
+ <div class="dev-overlay-navbar">
222
+ <div class="dev-overlay-navbar-left">
223
+ <div class="dev-overlay-version">
224
+ <div>
225
+ <SolidStartIcon title="Solid Start Version" />
235
226
  </div>
236
- <button class="dev-overlay-button" onClick={goNext} type="button">
237
- <ArrowRightIcon title="Go Next" />
238
- </button>
227
+ <span>{info.version as string}</span>
239
228
  </div>
240
- </Show>
241
- </div>
242
- <div class="dev-overlay-controls">
243
- <button class="dev-overlay-button" onClick={redirectToGithub} type="button">
244
- <GithubIcon title="Create an issue thread on Github" />
245
- </button>
246
- <button class="dev-overlay-button" onClick={redirectToDiscord} type="button">
247
- <DiscordIcon title="Join our Discord Channel" />
248
- </button>
249
- <button class="dev-overlay-button" onClick={downloadScreenshot} type="button">
250
- <CameraIcon title="Capture Error Overlay" />
251
- </button>
252
- <button class="dev-overlay-button" onClick={toggleIsCompiled} type="button">
253
- <Show when={isCompiled()} fallback={(
254
- <ViewOriginalIcon title="View Original Source" />
255
- )}>
256
- <ViewCompiledIcon title="View Compiled Source" />
229
+ <Show when={props.errors.length > 1}>
230
+ <div class="dev-overlay-pagination">
231
+ <button class="dev-overlay-button" onClick={goPrev} type="button">
232
+ <ArrowLeftIcon title="Go Previous" />
233
+ </button>
234
+ <div class="dev-overlay-page-counter">
235
+ {`${truncated()} of ${props.errors.length}`}
236
+ </div>
237
+ <button class="dev-overlay-button" onClick={goNext} type="button">
238
+ <ArrowRightIcon title="Go Next" />
239
+ </button>
240
+ </div>
257
241
  </Show>
258
- </button>
259
- <button class="dev-overlay-button" onClick={props.resetError} type="button">
260
- <RefreshIcon title="Reset Error" />
261
- </button>
242
+ </div>
243
+ <div class="dev-overlay-controls">
244
+ <button class="dev-overlay-button" onClick={redirectToGithub} type="button">
245
+ <GithubIcon title="Create an issue thread on Github" />
246
+ </button>
247
+ <button class="dev-overlay-button" onClick={redirectToDiscord} type="button">
248
+ <DiscordIcon title="Join our Discord Channel" />
249
+ </button>
250
+ <button class="dev-overlay-button" onClick={downloadScreenshot} type="button">
251
+ <CameraIcon title="Capture Error Overlay" />
252
+ </button>
253
+ <button class="dev-overlay-button" onClick={toggleIsCompiled} type="button">
254
+ <Show when={isCompiled()} fallback={(
255
+ <ViewOriginalIcon title="View Original Source" />
256
+ )}>
257
+ <ViewCompiledIcon title="View Compiled Source" />
258
+ </Show>
259
+ </button>
260
+ <button class="dev-overlay-button" onClick={props.resetError} type="button">
261
+ <RefreshIcon title="Reset Error" />
262
+ </button>
263
+ </div>
262
264
  </div>
265
+ <Show when={props.errors[truncated() - 1]} keyed>
266
+ {(current) => (
267
+ <div class="dev-overlay-content">
268
+ <ErrorInfo error={current} />
269
+ <StackFrames error={current} isCompiled={isCompiled()} />
270
+ </div>
271
+ )}
272
+ </Show>
263
273
  </div>
264
- <Show when={props.errors[truncated() - 1]} keyed>
265
- {(current) => (
266
- <div class="dev-overlay-content">
267
- <ErrorInfo error={current} />
268
- <StackFrames error={current} isCompiled={isCompiled()} />
269
- </div>
270
- )}
271
- </Show>
272
274
  </DialogPanel>
273
275
  </div>
274
276
  </Dialog>
@@ -9,6 +9,13 @@ export interface StackFrameSource {
9
9
  column: number;
10
10
  }
11
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
+
12
19
  export function createStackFrame(
13
20
  stackframe: StackFrame,
14
21
  isCompiled: () => boolean,
@@ -24,7 +31,7 @@ export function createStackFrame(
24
31
  if (!source.fileName) {
25
32
  return null;
26
33
  }
27
- const response = await fetch(source.fileName);
34
+ const response = await fetch(getActualFileSource(source.fileName));
28
35
  if (!response.ok) {
29
36
  return null;
30
37
  }
@@ -51,6 +58,7 @@ export function createStackFrame(
51
58
  line: source.line,
52
59
  column: source.column,
53
60
  });
61
+ console.log('sourcemap', result);
54
62
 
55
63
  return {
56
64
  ...result,
@@ -25,12 +25,16 @@
25
25
  width: 75vw;
26
26
  margin-top: 2rem;
27
27
  margin-bottom: 2rem;
28
- z-index: 10;
29
28
  gap: 0.5rem;
30
29
  color: rgb(17 24 39);
31
30
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
32
31
  }
33
32
 
33
+ .dev-overlay-panel-container {
34
+ margin: 2rem;
35
+ z-index: 10;
36
+ }
37
+
34
38
  .dev-overlay-navbar {
35
39
  display: flex;
36
40
  flex-direction: row;
package/shared/index.tsx CHANGED
@@ -1,5 +1,6 @@
1
- export { default as clientOnly } from "./clientOnly";
2
1
  export { FileRoutes } from "./FileRoutes";
2
+ export { GET } from "./GET";
3
3
  export { HttpHeader } from "./HttpHeader";
4
4
  export { HttpStatusCode } from "./HttpStatusCode";
5
+ export { default as clientOnly } from "./clientOnly";
5
6