@solidjs/start 0.4.10 → 0.5.0

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.
@@ -0,0 +1,64 @@
1
+ /// <reference types="vinxi/types/server" />
2
+ import { createRouter } from "radix3";
3
+ import { sharedConfig } from "solid-js";
4
+ import fileRoutes from "vinxi/routes";
5
+
6
+ // @ts-ignore
7
+ import { provideRequestEvent } from "solid-js/web/storage";
8
+ import { eventHandler } from "vinxi/server";
9
+ import { getFetchEvent } from "../server/fetchEvent";
10
+ import { APIEvent } from "../server/types";
11
+
12
+ export default eventHandler(h3Event => {
13
+ const event = getFetchEvent(h3Event);
14
+ const match = matchAPIRoute(new URL(event.request.url).pathname, event.request.method);
15
+ if (match) {
16
+ return provideRequestEvent(event, async () => {
17
+ const mod = await match.handler.import();
18
+ const fn = mod[event.request.method];
19
+ (event as APIEvent).params = match.params;
20
+ // @ts-ignore
21
+ sharedConfig.context = { event };
22
+ const res = await fn(event);
23
+ if (res === undefined && event.request.method !== "GET") {
24
+ throw new Error(
25
+ `API handler for ${event.request.method} "${event.request.url}" did not return a response.`
26
+ );
27
+ }
28
+ return res;
29
+ });
30
+ }
31
+ });
32
+
33
+ interface Route {
34
+ path: string;
35
+ id: string;
36
+ type: "api" | "page";
37
+ children?: Route[];
38
+ }
39
+
40
+ const router = createRouter({
41
+ routes: (fileRoutes as unknown as Route[]).reduce((memo, route) => {
42
+ if (route.type !== "api") return memo;
43
+ const path = route.path.replace(/\(.*\)\/?/g, "");
44
+ if (memo[path]) {
45
+ throw new Error(
46
+ `Duplicate API routes for "${path}" found at "${memo[path].route.path}" and "${route.path}"`
47
+ );
48
+ }
49
+ memo[path] = { route };
50
+ return memo;
51
+ }, {} as Record<string, { route: Route }>)
52
+ });
53
+
54
+ function matchAPIRoute(path: string, method: string) {
55
+ const match = router.lookup(path);
56
+ if (match) {
57
+ const handler = match.route[`$${method}`];
58
+ if (handler === "skip" || handler === undefined) return;
59
+ return {
60
+ handler,
61
+ params: match.params
62
+ };
63
+ }
64
+ }
@@ -57,19 +57,7 @@ export class SolidStartClientFileRouter extends BaseFileSystemRouter {
57
57
  }
58
58
  }
59
59
  }
60
- const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
61
- function createHTTPHandlers(src, exports) {
62
- const handlers = {};
63
- for (const exp of exports) {
64
- if (HTTP_METHODS.includes(exp.n)) {
65
- handlers[`$${exp.n}`] = {
66
- src: src,
67
- pick: [exp.n]
68
- };
69
- }
70
- }
71
- return handlers;
72
- }
60
+
73
61
  export class SolidStartServerFileRouter extends BaseFileSystemRouter {
74
62
  toPath(src) {
75
63
  const routePath = cleanPath(src, this.config)
@@ -123,7 +111,44 @@ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
123
111
  path,
124
112
  filePath: src
125
113
  };
126
- } else if (exports.find(exp => HTTP_METHODS.includes(exp.n))) {
114
+ }
115
+ }
116
+ }
117
+
118
+ const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
119
+ function createHTTPHandlers(src, exports) {
120
+ const handlers = {};
121
+ for (const exp of exports) {
122
+ if (HTTP_METHODS.includes(exp.n)) {
123
+ handlers[`$${exp.n}`] = {
124
+ src: src,
125
+ pick: [exp.n]
126
+ };
127
+ }
128
+ }
129
+ return handlers;
130
+ }
131
+
132
+ export class SolidStartAPIFileRouter extends BaseFileSystemRouter {
133
+ toPath(src) {
134
+ const routePath = cleanPath(src, this.config)
135
+ // remove the initial slash
136
+ .slice(1)
137
+ .replace(/index$/, "")
138
+ .replace(/\[([^\/]+)\]/g, (_, m) => {
139
+ if (m.length > 2 && m.startsWith("...")) {
140
+ return `**${m.length > 3 ? ":" + m.slice(3) : ""}`;
141
+ }
142
+ return `:${m}`;
143
+ });
144
+
145
+ return routePath?.length > 0 ? `/${routePath}` : "/";
146
+ }
147
+
148
+ toRoute(src) {
149
+ let path = this.toPath(src);
150
+ const [_, exports] = analyzeModule(src);
151
+ if (exports.find(exp => HTTP_METHODS.includes(exp.n))) {
127
152
  return {
128
153
  type: "api",
129
154
  ...createHTTPHandlers(src, exports),
package/config/index.d.ts CHANGED
@@ -9,8 +9,9 @@ type SolidStartInlineConfig = Omit<InlineConfig, "router"> & {
9
9
  * true: streaming mode
10
10
  * false: csr only
11
11
  * async: ssr is in async mode
12
+ * sync: ssr is in sync mode
12
13
  */
13
- ssr?: boolean | "async",
14
+ ssr?: boolean | "async" | "sync",
14
15
  solid?: Options,
15
16
  extensions?: string[],
16
17
  server?: AppOptions['server'],
package/config/index.js CHANGED
@@ -8,7 +8,7 @@ import { createApp, resolve } from "vinxi";
8
8
  import { normalize } from "vinxi/lib/path";
9
9
  import { config } from "vinxi/plugins/config";
10
10
  import solid from "vite-plugin-solid";
11
- import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js";
11
+ import { SolidStartAPIFileRouter, SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js";
12
12
  import { serverComponents } from "./server-components.js";
13
13
 
14
14
  const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
@@ -18,7 +18,7 @@ function solidStartClientFsRouter(config) {
18
18
  new SolidStartClientFileRouter(
19
19
  {
20
20
  dir: resolve.absolute(config.dir, router.root),
21
- extensions: config.extensions ?? ["js", "jsx", "ts", "tsx"]
21
+ extensions: config.extensions ?? DEFAULT_EXTENSIONS
22
22
  },
23
23
  router,
24
24
  app
@@ -30,7 +30,19 @@ function solidStartServerFsRouter(config) {
30
30
  new SolidStartServerFileRouter(
31
31
  {
32
32
  dir: resolve.absolute(config.dir, router.root),
33
- extensions: config.extensions ?? ["js", "jsx", "ts", "tsx"]
33
+ extensions: config.extensions ?? DEFAULT_EXTENSIONS
34
+ },
35
+ router,
36
+ app
37
+ );
38
+ }
39
+
40
+ function solidStartAPIFileRouter(config) {
41
+ return (router, app) =>
42
+ new SolidStartAPIFileRouter(
43
+ {
44
+ dir: resolve.absolute(config.dir, router.root),
45
+ extensions: config.extensions ?? DEFAULT_EXTENSIONS
34
46
  },
35
47
  router,
36
48
  app
@@ -44,7 +56,12 @@ export function defineConfig(baseConfig = {}) {
44
56
  appRoot: "./src",
45
57
  ssr: true,
46
58
  islands: false,
47
- solid: {}
59
+ solid: {},
60
+ server: {
61
+ experimental: {
62
+ asyncContext: true
63
+ }
64
+ }
48
65
  });
49
66
  let server = start.server;
50
67
  if (!start.ssr) {
@@ -65,14 +82,25 @@ export function defineConfig(baseConfig = {}) {
65
82
  routers: [
66
83
  {
67
84
  name: "public",
68
- mode: "static",
85
+ type: "static",
69
86
  dir: "./public",
70
87
  base: "/"
71
88
  },
72
-
89
+ {
90
+ name: "api",
91
+ type: "http",
92
+ target: "server",
93
+ base: "/",
94
+ handler: normalize(fileURLToPath(new URL("./api-handler.ts", import.meta.url))),
95
+ routes: solidStartAPIFileRouter({ dir: `${start.appRoot}/routes` }),
96
+ middleware: start.middleware
97
+ },
73
98
  {
74
99
  name: "ssr",
75
- mode: "handler",
100
+ type: "http",
101
+ link: {
102
+ client: start.islands ? undefined : "client"
103
+ },
76
104
  handler: `${start.appRoot}/entry-server${entryExtension}`,
77
105
  middleware: start.middleware,
78
106
  routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
@@ -85,15 +113,15 @@ export function defineConfig(baseConfig = {}) {
85
113
  ...(userConfig.optimizeDeps || {}),
86
114
  include: [
87
115
  ...(userConfig.optimizeDeps?.include || []),
88
- '@solidjs/start > source-map-js',
89
- '@solidjs/start > error-stack-parser',
90
- ],
91
- },
116
+ "@solidjs/start > source-map-js",
117
+ "@solidjs/start > error-stack-parser"
118
+ ]
119
+ }
92
120
  }),
93
121
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
94
122
 
95
123
  serverTransform({
96
- runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.jsx", import.meta.url)))
124
+ runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url)))
97
125
  }),
98
126
  start.islands ? serverComponents.server() : null,
99
127
  solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
@@ -122,7 +150,7 @@ export function defineConfig(baseConfig = {}) {
122
150
  },
123
151
  {
124
152
  name: "client",
125
- mode: "build",
153
+ type: "client",
126
154
  handler: `${start.appRoot}/entry-client${entryExtension}`,
127
155
  ...(start.islands
128
156
  ? {}
@@ -138,14 +166,14 @@ export function defineConfig(baseConfig = {}) {
138
166
  ...(userConfig.optimizeDeps || {}),
139
167
  include: [
140
168
  ...(userConfig.optimizeDeps?.include || []),
141
- '@solidjs/start > source-map-js',
142
- '@solidjs/start > error-stack-parser',
143
- ],
144
- },
169
+ "@solidjs/start > source-map-js",
170
+ "@solidjs/start > error-stack-parser"
171
+ ]
172
+ }
145
173
  }),
146
174
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
147
175
  serverFunctions.client({
148
- runtime: normalize(fileURLToPath(new URL("./server-runtime.jsx", import.meta.url)))
176
+ runtime: normalize(fileURLToPath(new URL("./server-runtime.ts", import.meta.url)))
149
177
  }),
150
178
  start.islands ? serverComponents.client() : null,
151
179
  solid({ ...start.solid, ssr: start.ssr, extensions: extensions.map(ext => `.${ext}`) }),
@@ -179,8 +207,8 @@ export function defineConfig(baseConfig = {}) {
179
207
  base: "/_build"
180
208
  },
181
209
  serverFunctions.router({
182
- handler: normalize(fileURLToPath(new URL("./server-handler.js", import.meta.url))),
183
- runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.jsx", import.meta.url))),
210
+ handler: normalize(fileURLToPath(new URL("./server-handler.ts", import.meta.url))),
211
+ runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url))),
184
212
  // routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
185
213
  plugins: async () => [
186
214
  config("user", {
@@ -189,10 +217,10 @@ export function defineConfig(baseConfig = {}) {
189
217
  ...(userConfig.optimizeDeps || {}),
190
218
  include: [
191
219
  ...(userConfig.optimizeDeps?.include || []),
192
- '@solidjs/start > source-map-js',
193
- '@solidjs/start > error-stack-parser',
194
- ],
195
- },
220
+ "@solidjs/start > source-map-js",
221
+ "@solidjs/start > error-stack-parser"
222
+ ]
223
+ }
196
224
  }),
197
225
  ...(typeof plugins === "function" ? [...(await plugins())] : plugins),
198
226
 
@@ -1,14 +1,17 @@
1
1
  import { getRequestEvent } from "solid-js/web";
2
+ //@ts-ignore
2
3
  import { provideRequestEvent } from "solid-js/web/storage";
3
- import { cloneEvent } from "../server/middleware";
4
+ import { cloneEvent } from "../server/fetchEvent";
4
5
 
5
6
  export function createServerReference(fn, id, name) {
7
+ if (typeof fn !== "function") throw new Error("Export from a 'use server' module must be a function");
6
8
  const baseURL = import.meta.env.SERVER_BASE_URL;
7
9
  return new Proxy(fn, {
8
10
  get(target, prop, receiver) {
9
11
  if (prop === "url") {
10
12
  return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
11
13
  }
14
+ if (prop === "GET") return receiver;
12
15
  },
13
16
  apply(target, thisArg, args) {
14
17
  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";
23
- import { getFetchEvent } from "../server/middleware";
19
+ import { eventHandler, setHeader } from "vinxi/server";
20
+ import { getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
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,67 @@ 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: h3Event.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: h3Event.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) mergeResponseHeaders(h3Event, result.headers);
141
+ if ((result as any).customBody) {
142
+ result = await (result as any).customBody();
143
+ } else if (result.body == undefined) result = undefined;
144
+ }
145
+
120
146
  // handle no JS success case
121
147
  if (!instance) {
122
148
  const isError = result instanceof Error;
@@ -142,13 +168,20 @@ async function handleServerFunction(h3Event) {
142
168
  setHeader(h3Event, "content-type", "text/javascript");
143
169
  return serializeToStream(instance, result);
144
170
  } 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")
150
- }
151
- });
171
+ if (x instanceof Response) {
172
+ if (x.status === 302) {
173
+ return new Response(null, {
174
+ status: instance ? 204 : 302,
175
+ headers: {
176
+ Location: x.headers.get("Location")
177
+ }
178
+ });
179
+ }
180
+ // forward headers
181
+ if (x.headers) mergeResponseHeaders(h3Event, x.headers);
182
+ if ((x as any).customBody) {
183
+ x = await (x as any).customBody();
184
+ } else if (x.body == undefined) x = undefined;
152
185
  }
153
186
  return x;
154
187
  }
@@ -9,14 +9,17 @@ 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
+ reader: ReadableStreamDefaultReader<Uint8Array>;
18
+ buffer: string;
19
+ done: boolean;
17
20
  constructor(stream) {
18
21
  this.reader = stream.getReader();
19
- this.buffer = '';
22
+ this.buffer = "";
20
23
  this.done = false;
21
24
  }
22
25
 
@@ -33,12 +36,12 @@ class SerovalChunkReader {
33
36
 
34
37
  async next() {
35
38
  // Check if the buffer is empty
36
- if (this.buffer === '') {
39
+ if (this.buffer === "") {
37
40
  // if we are already done...
38
41
  if (this.done) {
39
42
  return {
40
43
  done: true,
41
- value: undefined,
44
+ value: undefined
42
45
  };
43
46
  }
44
47
  // Otherwise, read a new chunk
@@ -55,7 +58,7 @@ class SerovalChunkReader {
55
58
  // If it's not enough, and the reader is done
56
59
  // then the chunk is invalid.
57
60
  if (this.done) {
58
- throw new Error('Malformed server function stream.')
61
+ throw new Error("Malformed server function stream.");
59
62
  }
60
63
  // Otherwise, we read more chunks
61
64
  await this.readChunk();
@@ -67,7 +70,7 @@ class SerovalChunkReader {
67
70
  // Deserialize the chunk
68
71
  return {
69
72
  done: false,
70
- value: deserialize(partial),
73
+ value: deserialize(partial)
71
74
  };
72
75
  }
73
76
 
@@ -92,6 +95,7 @@ async function deserializeStream(id, response) {
92
95
  if (!result.done) {
93
96
  reader.drain().then(
94
97
  () => {
98
+ // @ts-ignore
95
99
  delete $R[id];
96
100
  },
97
101
  () => {
@@ -105,7 +109,7 @@ async function deserializeStream(id, response) {
105
109
 
106
110
  let INSTANCE = 0;
107
111
 
108
- function createRequest(base, id, instance, body, contentType) {
112
+ function createRequest(base: string, id: string, instance: string, body: any, contentType?: string) {
109
113
  return fetch(base, {
110
114
  method: "POST",
111
115
  headers: {
@@ -117,31 +121,47 @@ function createRequest(base, id, instance, body, contentType) {
117
121
  });
118
122
  }
119
123
 
120
- async function fetchServerFunction(base, id, args) {
124
+ async function fetchServerFunction(base, id, method, args) {
121
125
  const instance = `server-fn:${INSTANCE++}`;
122
- const response = await (args.length === 1 && args[0] instanceof FormData
126
+ const response = await (method === "GET"
127
+ ? fetch(base + (args.length ? `&args=${JSON.stringify(args)}` : ""), {
128
+ headers: {
129
+ "x-server-instance": instance
130
+ }
131
+ })
132
+ : args.length === 1 && args[0] instanceof FormData
123
133
  ? 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"));
134
+ : createRequest(
135
+ base,
136
+ id,
137
+ instance,
138
+ JSON.stringify(
139
+ await Promise.resolve(
140
+ toJSONAsync(args, {
141
+ plugins: [
142
+ CustomEventPlugin,
143
+ DOMExceptionPlugin,
144
+ EventPlugin,
145
+ FormDataPlugin,
146
+ HeadersPlugin,
147
+ ReadableStreamPlugin,
148
+ RequestPlugin,
149
+ ResponsePlugin,
150
+ URLSearchParamsPlugin,
151
+ URLPlugin
152
+ ]
153
+ })
154
+ )
155
+ ),
156
+ "application/json"
157
+ ));
138
158
 
139
159
  if (response.headers.get("Location")) throw response;
140
160
  if (response.headers.get("X-Revalidate")) {
141
- /* ts-ignore-next-line */
161
+ /* @ts-ignore-next-line */
142
162
  response.customBody = () => {
143
163
  return deserializeStream(instance, response);
144
- }
164
+ };
145
165
  throw response;
146
166
  }
147
167
  const contentType = response.headers.get("Content-Type");
@@ -166,9 +186,12 @@ export function createServerReference(fn, id, name) {
166
186
  if (prop === "url") {
167
187
  return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
168
188
  }
189
+ if (prop === "GET") {
190
+ return (...args) => fetchServerFunction(`${baseURL}/_server/?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`, `${id}#${name}`, "GET", args);
191
+ }
169
192
  },
170
193
  apply(target, thisArg, args) {
171
- return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, args);
194
+ return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, "POST", args);
172
195
  }
173
196
  });
174
197
  }