freestyle-sandboxes 0.0.97 → 0.1.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.
Files changed (69) hide show
  1. package/README.md +39 -48
  2. package/index.cjs +4381 -0
  3. package/index.d.cts +9404 -0
  4. package/index.d.mts +9404 -0
  5. package/index.mjs +4367 -0
  6. package/package.json +16 -109
  7. package/dist/ai/inde.d.cts +0 -75
  8. package/dist/ai/inde.d.mts +0 -75
  9. package/dist/ai/index.cjs +0 -13
  10. package/dist/ai/index.d.cts +0 -75
  11. package/dist/ai/index.d.mts +0 -75
  12. package/dist/ai/index.mjs +0 -4
  13. package/dist/expo/inde.d.cts +0 -6
  14. package/dist/expo/inde.d.mts +0 -6
  15. package/dist/expo/index.cjs +0 -319
  16. package/dist/expo/index.d.cts +0 -6
  17. package/dist/expo/index.d.mts +0 -6
  18. package/dist/expo/index.mjs +0 -297
  19. package/dist/inde.d.cts +0 -373
  20. package/dist/inde.d.mts +0 -373
  21. package/dist/index-BKAG8L-o.mjs +0 -3061
  22. package/dist/index-DuOpIaWc.cjs +0 -3068
  23. package/dist/index.cjs +0 -1329
  24. package/dist/index.d-9H_wnIbz.d.ts +0 -4223
  25. package/dist/index.d.cts +0 -373
  26. package/dist/index.d.mts +0 -373
  27. package/dist/index.mjs +0 -1327
  28. package/dist/langgraph/inde.d.cts +0 -4180
  29. package/dist/langgraph/inde.d.mts +0 -4180
  30. package/dist/langgraph/index.cjs +0 -17155
  31. package/dist/langgraph/index.d.cts +0 -4180
  32. package/dist/langgraph/index.d.mts +0 -4180
  33. package/dist/langgraph/index.mjs +0 -17153
  34. package/dist/mastra/inde.d.cts +0 -2623
  35. package/dist/mastra/inde.d.mts +0 -2623
  36. package/dist/mastra/index.cjs +0 -55
  37. package/dist/mastra/index.d.cts +0 -2623
  38. package/dist/mastra/index.d.mts +0 -2623
  39. package/dist/mastra/index.mjs +0 -53
  40. package/dist/react/dev-server/index..d.cts +0 -33
  41. package/dist/react/dev-server/index..d.mts +0 -33
  42. package/dist/react/dev-server/index.cjs +0 -148
  43. package/dist/react/dev-server/index.d.cts +0 -33
  44. package/dist/react/dev-server/index.d.mts +0 -33
  45. package/dist/react/dev-server/index.mjs +0 -145
  46. package/dist/types.gen-CJa21P0C.d.ts +0 -1902
  47. package/dist/types.gen-DKjMRuu5.d.ts +0 -1898
  48. package/dist/utils/inde.d.cts +0 -10
  49. package/dist/utils/inde.d.mts +0 -10
  50. package/dist/utils/index.cjs +0 -100
  51. package/dist/utils/index.d.cts +0 -10
  52. package/dist/utils/index.d.mts +0 -10
  53. package/dist/utils/index.mjs +0 -75
  54. package/openapi/index.ts +0 -3
  55. package/openapi/sdk.gen.ts +0 -929
  56. package/openapi/types.gen.ts +0 -2234
  57. package/openapi-ts.config.ts +0 -7
  58. package/openapi.json +0 -1
  59. package/src/ai/index.ts +0 -164
  60. package/src/dev-server.ts +0 -95
  61. package/src/expo/_expo_internals.ts +0 -389
  62. package/src/expo/index.ts +0 -26
  63. package/src/index.ts +0 -1459
  64. package/src/langgraph/index.ts +0 -33
  65. package/src/mastra/index.ts +0 -38
  66. package/src/react/dev-server/index.tsx +0 -195
  67. package/src/react/dev-server/types.ts +0 -5
  68. package/src/utils/index.ts +0 -97
  69. package/tsconfig.json +0 -8
package/src/ai/index.ts DELETED
@@ -1,164 +0,0 @@
1
- import {
2
- FreestyleDeployWebConfiguration,
3
- FreestyleExecuteScriptParamsConfiguration,
4
- FreestyleExecuteScriptResultSuccess,
5
- HandleExecuteScriptError,
6
- } from "../../openapi";
7
- import { FreestyleSandboxes } from "..";
8
- import { tool } from "ai";
9
- import { z } from "zod";
10
-
11
- export const executeCodeSchema = z.object({
12
- script: z.string().describe(`
13
- The JavaScript or TypeScript script to execute, must be in the format of:
14
-
15
- import { someModule } from "someModule";
16
- export default () => {
17
- ... your code here ...
18
- return output;
19
- }
20
-
21
- or for async functions:
22
-
23
- import { someModule } from "someModule";
24
-
25
- export default async () => {
26
- ... your code here ...
27
- return output;
28
- }
29
- `),
30
- });
31
-
32
- export const executeCodeDescription = (envVars: string, nodeModules: string) =>
33
- `Execute a JavaScript or TypeScript script.\n${
34
- envVars.length > 0
35
- ? `You can use the following environment variables: ${envVars}`
36
- : ""
37
- }\n${
38
- nodeModules.length > 0
39
- ? `You can use the following node modules: ${nodeModules}`
40
- : "You cannot use any node modules."
41
- }`;
42
- /**
43
- * Execute a JavaScript or TypeScript script
44
- *
45
- *
46
- * @param config - Configuration for the tool
47
- * @param config.apiKey - The API key to use
48
- * @param {Function} [config.onResult] - Optional callback function to handle the result.
49
- * @param {boolean} [config.truncateOutput=false] - Whether to truncate the result to 1000 characters and truncate individual logs to the first 250 characters; useful to prevent long outputs from filling the context window.
50
- */
51
- export const executeTool = (
52
- config: FreestyleExecuteScriptParamsConfiguration & {
53
- apiKey: string;
54
- onResult?: (_v: {
55
- toolCallId: string;
56
- input: {
57
- script: string;
58
- [key: string]: unknown;
59
- };
60
- result: FreestyleExecuteScriptResultSuccess | HandleExecuteScriptError;
61
- }) => void | Promise<void>;
62
- truncateOutput?: boolean;
63
- }
64
- ) => {
65
- const api = new FreestyleSandboxes({
66
- ...config,
67
- });
68
-
69
- const envVars = Object.keys(config.envVars ?? {}).join(", ");
70
- const nodeModules = Object.keys(config.nodeModules ?? {}).join(", ");
71
- return tool({
72
- description: executeCodeDescription(envVars, nodeModules),
73
- parameters: executeCodeSchema,
74
- execute: async ({ script, ...otherParams }, { toolCallId }) => {
75
- try {
76
- const res = await api.executeScript(script, config);
77
- if (config.onResult) {
78
- await config.onResult({
79
- toolCallId,
80
- result: res,
81
- input: {
82
- script,
83
- ...otherParams,
84
- },
85
- });
86
- }
87
- if (config.truncateOutput) {
88
- if ("output" in res) {
89
- res.result = JSON.stringify(res.result).slice(0, 1000);
90
- res.logs = res.logs.slice(0, 1000);
91
- }
92
- }
93
- return res;
94
- } catch (e) {
95
- console.log("ERROR: ", e.message);
96
- return {
97
- message: e.message,
98
- error: e.error,
99
- };
100
- }
101
- },
102
- });
103
- };
104
-
105
- /**
106
- * Deploy a Web project
107
- * @param config - Configuration for the tool
108
- * @param config.apiKey - The API key to use
109
- */
110
- export const deployWebTool = (
111
- config: FreestyleDeployWebConfiguration & {
112
- apiKey: string;
113
- }
114
- ) => {
115
- const api = new FreestyleSandboxes({
116
- ...config,
117
- });
118
-
119
- const envVars = Object.keys(config.envVars ?? {}).join(", ");
120
- const nodeModules = Object.keys(config.nodeModules ?? {}).join(", ");
121
- return tool({
122
- description: `Deploy a Web project. ${
123
- envVars.length > 0
124
- ? `You can use the following environment variables: ${envVars}`
125
- : ""
126
- }\n${
127
- nodeModules.length > 0
128
- ? `You can use the following node modules: ${nodeModules}`
129
- : "You cannot use any node modules."
130
- }`,
131
- parameters: z.object({
132
- files: z.record(z.string()).describe(`
133
- A record of file names and their contents to deploy. For example:
134
- {
135
- "index.js": "import http from 'node:http';\\nnconsole.log('starting server');\\n\\nconst server = http.createServer(async(req, res) => {\\n res.writeHead(200, { 'Content-Type': 'text/plain' });\\n res.end('Welcome to New York its been waiting for you');\\n});\\n\\nserver.listen(3000, () => {\\n console.log('Server is running at http://localhost:3000');\\n});",
136
- }
137
- `),
138
- }),
139
- execute: async ({ files }) => {
140
- // map from record<string, string> to record<string, {content: string}>
141
- const new_files = Object.keys(files).reduce((acc, key) => {
142
- acc[key] = { content: files[key] };
143
- return acc;
144
- }, {} as Record<string, { content: string }>);
145
- try {
146
- const res = await api.deployWeb(
147
- {
148
- kind: "files",
149
- files: new_files,
150
- },
151
- config
152
- );
153
- return res;
154
- } catch (e) {
155
- console.log("ERROR: ", e.message);
156
- return `Error deploying web project:\n\n${JSON.stringify(
157
- files,
158
- null,
159
- 2
160
- )}\n\nError: ${e.message}`;
161
- }
162
- },
163
- });
164
- };
package/src/dev-server.ts DELETED
@@ -1,95 +0,0 @@
1
- export interface FreestyleDevServer {
2
- /**
3
- * The URL for the dev server's HTTP API.
4
- */
5
- ephemeralUrl: string;
6
-
7
- /**
8
- * The URL to the MCP endpoint for the dev server.
9
- */
10
- mcpEphemeralUrl: string;
11
-
12
- /**
13
- * The URL for the VSCode server running in the dev server.
14
- */
15
- codeServerUrl: string;
16
-
17
- /**
18
- * Whether the dev server was just created.
19
- */
20
- isNew: boolean;
21
-
22
- fs: FreestyleDevServerFilesystem;
23
-
24
- process: FreestyleDevServerProcess;
25
-
26
- devCommandRunning: boolean;
27
- installCommandRunning: boolean;
28
-
29
- /**
30
- * Get the status of the dev server
31
- */
32
- status(): Promise<{
33
- installing: boolean;
34
- devRunning: boolean;
35
- }>;
36
-
37
- /**
38
- * Commit and push changes to the dev server repository
39
- * @param message The commit message
40
- */
41
- commitAndPush(message: string): Promise<void>;
42
-
43
- /**
44
- * Shutdown the dev server
45
- */
46
- shutdown(): Promise<{
47
- success: boolean;
48
- message: string;
49
- }>;
50
- }
51
-
52
- export interface FreestyleDevServerFilesystem {
53
- /**
54
- * List files in the dev server directory
55
- */
56
- ls(path?: string): Promise<Array<string>>;
57
-
58
- /**
59
- * Read a file from the dev server
60
- * @param path The path to the file
61
- * @param encoding The encoding to use (defaults to utf-8)
62
- */
63
- readFile(path: string, encoding?: string): Promise<string>;
64
-
65
- /**
66
- * Write a file to the dev server
67
- * @param path The path to write to
68
- * @param content The content to write
69
- * @param encoding The encoding to use (defaults to utf-8)
70
- */
71
- writeFile(
72
- path: string,
73
- content: string | ArrayBufferLike,
74
- encoding?: string
75
- ): Promise<void>;
76
-
77
- watch(): AsyncGenerator<{ eventType: string; filename: string }>;
78
- }
79
-
80
- export interface FreestyleDevServerProcess {
81
- /**
82
- * Execute a command on the dev server
83
- * @param cmd The command to execute
84
- * @param background Whether to run the command in the background
85
- */
86
- exec(
87
- cmd: string,
88
- background?: boolean
89
- ): Promise<{
90
- id: string;
91
- isNew: boolean;
92
- stdout?: string[];
93
- stderr?: string[];
94
- }>;
95
- }
@@ -1,389 +0,0 @@
1
- import type {
2
- ExpoRoutesManifestV1,
3
- RouteInfo,
4
- } from "expo-router/build/routes-manifest";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
-
8
- import { createRequire } from "module";
9
- const require = createRequire(import.meta.url);
10
- // import { ExpoRouterServerManifestV1FunctionRoute } from "./types";
11
-
12
- const debug = console.log;
13
-
14
- function getProcessedManifest(path: string): ExpoRoutesManifestV1<RegExp> {
15
- // TODO: JSON Schema for validation
16
- const routesManifest = JSON.parse(
17
- fs.readFileSync(path, "utf-8")
18
- ) as ExpoRoutesManifestV1;
19
-
20
- const parsed: ExpoRoutesManifestV1<RegExp> = {
21
- ...routesManifest,
22
- notFoundRoutes: routesManifest.notFoundRoutes.map((value: any) => {
23
- return {
24
- ...value,
25
- namedRegex: new RegExp(value.namedRegex),
26
- };
27
- }),
28
- apiRoutes: routesManifest.apiRoutes.map((value: any) => {
29
- return {
30
- ...value,
31
- namedRegex: new RegExp(value.namedRegex),
32
- };
33
- }),
34
- htmlRoutes: routesManifest.htmlRoutes.map((value: any) => {
35
- return {
36
- ...value,
37
- namedRegex: new RegExp(value.namedRegex),
38
- };
39
- }),
40
- redirects: routesManifest.redirects?.map((value: any) => {
41
- return {
42
- ...value,
43
- namedRegex: new RegExp(value.namedRegex),
44
- };
45
- }),
46
- rewrites: routesManifest.rewrites?.map((value: any) => {
47
- return {
48
- ...value,
49
- namedRegex: new RegExp(value.namedRegex),
50
- };
51
- }),
52
- };
53
-
54
- return parsed;
55
- }
56
-
57
- export function getRoutesManifest(distFolder: string) {
58
- return getProcessedManifest(path.join(distFolder, "_expo/routes.json"));
59
- }
60
-
61
- // TODO: Reuse this for dev as well
62
- export function createRequestHandler(
63
- distFolder: string,
64
- {
65
- getRoutesManifest: getInternalRoutesManifest,
66
- getHtml = async (_request, route) => {
67
- // Serve a static file by exact route name
68
- const filePath = path.join(distFolder, route.page + ".html");
69
- if (fs.existsSync(filePath)) {
70
- return fs.readFileSync(filePath, "utf-8");
71
- }
72
-
73
- // Serve a static file by route name with hoisted index
74
- // See: https://github.com/expo/expo/pull/27935
75
- const hoistedFilePath = route.page.match(/\/index$/)
76
- ? path.join(distFolder, route.page.replace(/\/index$/, "") + ".html")
77
- : null;
78
- if (hoistedFilePath && fs.existsSync(hoistedFilePath)) {
79
- return fs.readFileSync(hoistedFilePath, "utf-8");
80
- }
81
-
82
- return null;
83
- },
84
- getApiRoute = async (route) => {
85
- const filePath = path.join(distFolder, route.file);
86
-
87
- debug(`Handling API route: ${route.page}: ${filePath}`);
88
-
89
- // TODO: What's the standard behavior for malformed projects?
90
- if (!fs.existsSync(filePath)) {
91
- return null;
92
- }
93
-
94
- if (/\.c?js$/.test(filePath)) {
95
- return require(filePath);
96
- }
97
- return import(filePath);
98
- },
99
- logApiRouteExecutionError = (error: Error) => {
100
- console.error(error);
101
- },
102
- handleApiRouteError = async (error: Error) => {
103
- if ("statusCode" in error && typeof error.statusCode === "number") {
104
- return new Response(error.message, {
105
- status: error.statusCode,
106
- headers: {
107
- "Content-Type": "text/plain",
108
- },
109
- });
110
- }
111
- return new Response("Internal server error", {
112
- status: 500,
113
- headers: {
114
- "Content-Type": "text/plain",
115
- },
116
- });
117
- },
118
- }: {
119
- getHtml?: (
120
- request: Request,
121
- route: RouteInfo<RegExp>
122
- ) => Promise<string | Response | null>;
123
- getRoutesManifest?: (
124
- distFolder: string
125
- ) => Promise<ExpoRoutesManifestV1<RegExp> | null>;
126
- getApiRoute?: (route: RouteInfo<RegExp>) => Promise<any>;
127
- logApiRouteExecutionError?: (error: Error) => void;
128
- handleApiRouteError?: (error: Error) => Promise<Response>;
129
- } = {}
130
- ) {
131
- let routesManifest: ExpoRoutesManifestV1<RegExp> | undefined;
132
-
133
- return async function handler(request: Request): Promise<Response> {
134
- if (getInternalRoutesManifest) {
135
- const manifest = await getInternalRoutesManifest(distFolder);
136
- if (manifest) {
137
- routesManifest = manifest;
138
- } else {
139
- // Development error when Expo Router is not setup.
140
- return new Response("No routes manifest found", {
141
- status: 404,
142
- headers: {
143
- "Content-Type": "text/plain",
144
- },
145
- });
146
- }
147
- } else if (!routesManifest) {
148
- routesManifest = getRoutesManifest(distFolder);
149
- }
150
-
151
- const url = new URL(request.url, "http://expo.dev");
152
-
153
- const sanitizedPathname = url.pathname;
154
-
155
- debug("Request", sanitizedPathname);
156
-
157
- if (routesManifest.rewrites) {
158
- for (const route of routesManifest.rewrites) {
159
- if (!route.namedRegex.test(sanitizedPathname)) {
160
- continue;
161
- }
162
-
163
- const url = getRedirectRewriteLocation(request, route);
164
-
165
- if (url) {
166
- request = new Request(
167
- new URL(url, new URL(request.url).origin),
168
- request
169
- );
170
- }
171
- }
172
- }
173
-
174
- if (routesManifest.redirects) {
175
- for (const route of routesManifest.redirects) {
176
- if (!route.namedRegex.test(sanitizedPathname)) {
177
- continue;
178
- }
179
-
180
- const Location = getRedirectRewriteLocation(request, route);
181
-
182
- if (Location) {
183
- debug("Redirecting", Location);
184
-
185
- // Get the params
186
- return new Response(null, {
187
- status: route.permanent ? 308 : 307,
188
- headers: {
189
- Location,
190
- },
191
- });
192
- }
193
- }
194
- }
195
-
196
- if (request.method === "GET" || request.method === "HEAD") {
197
- // First test static routes
198
- for (const route of routesManifest.htmlRoutes) {
199
- if (!route.namedRegex.test(sanitizedPathname)) {
200
- continue;
201
- }
202
-
203
- // // Mutate to add the expoUrl object.
204
- updateRequestWithConfig(request, route);
205
-
206
- // serve a static file
207
- const contents = await getHtml(request, route);
208
-
209
- // TODO: What's the standard behavior for malformed projects?
210
- if (!contents) {
211
- return new Response("Not found", {
212
- status: 404,
213
- headers: {
214
- "Content-Type": "text/plain",
215
- },
216
- });
217
- } else if (contents instanceof Response) {
218
- return contents;
219
- }
220
-
221
- return new Response(contents, {
222
- status: 200,
223
- headers: {
224
- "Content-Type": "text/html",
225
- },
226
- });
227
- }
228
- }
229
-
230
- // Next, test API routes
231
- for (const route of routesManifest.apiRoutes) {
232
- if (!route.namedRegex.test(sanitizedPathname)) {
233
- continue;
234
- }
235
-
236
- const func = await getApiRoute(route);
237
-
238
- if (func instanceof Response) {
239
- return func;
240
- }
241
-
242
- const routeHandler = func?.[request.method];
243
- if (!routeHandler) {
244
- return new Response("Method not allowed", {
245
- status: 405,
246
- headers: {
247
- "Content-Type": "text/plain",
248
- },
249
- });
250
- }
251
-
252
- // Mutate to add the expoUrl object.
253
- const params = updateRequestWithConfig(request, route);
254
-
255
- try {
256
- // TODO: Handle undefined
257
- return (await routeHandler(request, params)) as Response;
258
- } catch (error) {
259
- if (error instanceof Error) {
260
- logApiRouteExecutionError(error);
261
- }
262
-
263
- return handleApiRouteError(error as Error);
264
- }
265
- }
266
-
267
- // Finally, test 404 routes
268
- for (const route of routesManifest.notFoundRoutes) {
269
- if (!route.namedRegex.test(sanitizedPathname)) {
270
- continue;
271
- }
272
-
273
- // // Mutate to add the expoUrl object.
274
- updateRequestWithConfig(request, route);
275
-
276
- // serve a static file
277
- const contents = await getHtml(request, route);
278
-
279
- // TODO: What's the standard behavior for malformed projects?
280
- if (!contents) {
281
- return new Response("Not found", {
282
- status: 404,
283
- headers: {
284
- "Content-Type": "text/plain",
285
- },
286
- });
287
- } else if (contents instanceof Response) {
288
- return contents;
289
- }
290
-
291
- return new Response(contents, {
292
- status: 404,
293
- headers: {
294
- "Content-Type": "text/html",
295
- },
296
- });
297
- }
298
-
299
- // 404
300
- const response = new Response("Not found", {
301
- status: 404,
302
- headers: {
303
- "Content-Type": "text/plain",
304
- },
305
- });
306
- return response;
307
- };
308
- }
309
-
310
- /** Match `[page]` -> `page` */
311
- // Ported from `expo-router/src/matchers.tsx`
312
- function matchDynamicName(name: string): string | undefined {
313
- // Don't match `...` or `[` or `]` inside the brackets
314
- // eslint-disable-next-line no-useless-escape
315
- return name.match(/^\[([^[\](?:\.\.\.)]+?)\]$/)?.[1];
316
- }
317
-
318
- /** Match `[...page]` -> `page` */
319
- // Ported from `expo-router/src/matchers.tsx`
320
- function matchDeepDynamicRouteName(name: string): string | undefined {
321
- return name.match(/^\[\.\.\.([^/]+?)\]$/)?.[1];
322
- }
323
-
324
- function updateRequestWithConfig(
325
- request: Request,
326
- config: ExpoRouterServerManifestV1FunctionRoute
327
- ) {
328
- const params: Record<string, string> = {};
329
- const url = new URL(request.url);
330
- const match = config.namedRegex.exec(url.pathname);
331
- if (match?.groups) {
332
- for (const [key, value] of Object.entries(match.groups)) {
333
- const namedKey = config.routeKeys[key];
334
- params[namedKey] = value;
335
- }
336
- }
337
-
338
- return params;
339
- }
340
-
341
- function getRedirectRewriteLocation(
342
- request: Request,
343
- route: RouteInfo<RegExp>
344
- ) {
345
- if (route.methods) {
346
- if (!route.methods.includes(request.method)) {
347
- return;
348
- }
349
- }
350
-
351
- const params = updateRequestWithConfig(request, route);
352
-
353
- const urlSearchParams = new URL(request.url).searchParams;
354
-
355
- let location = route.page
356
- .split("/")
357
- .map((segment) => {
358
- let match = matchDynamicName(segment);
359
-
360
- if (match) {
361
- const value = params[match];
362
- delete params[match];
363
- // If we are redirecting from a catch-all route, we need to remove the extra segments
364
- return value?.split("/")[0];
365
- }
366
-
367
- match = matchDeepDynamicRouteName(segment);
368
-
369
- if (match) {
370
- const value = params[match];
371
- delete params[match];
372
- return value;
373
- }
374
-
375
- return segment;
376
- })
377
- .join("/");
378
-
379
- if (Object.keys(params).length > 0 || urlSearchParams.size > 0) {
380
- location +=
381
- "?" +
382
- new URLSearchParams({
383
- ...params,
384
- ...Object.fromEntries(urlSearchParams.entries()),
385
- }).toString();
386
- }
387
-
388
- return location;
389
- }
package/src/expo/index.ts DELETED
@@ -1,26 +0,0 @@
1
- import { createRequestHandler } from "./_expo_internals";
2
-
3
- import * as path from "node:path";
4
- import * as process from "node:process";
5
- import { Hono } from "hono";
6
- import { serveStatic } from "hono/deno";
7
-
8
- export const freestyleExpoServer = ({
9
- CLIENT_BUILD_DIR = path.join(process.cwd(), "dist/client"),
10
- SERVER_BUILD_DIR = path.join(process.cwd(), "dist/server"),
11
- } = {}) => {
12
- // // Expo handler
13
- const expoHandler = createRequestHandler(SERVER_BUILD_DIR);
14
-
15
- const app = new Hono();
16
- app.use("*", serveStatic({ root: CLIENT_BUILD_DIR }));
17
-
18
- app.all("*", async (c, next) => {
19
- console.log("Request received:", c.req.url);
20
- const response = await expoHandler(c.req.raw);
21
- return response;
22
- });
23
-
24
- // @ts-expect-error — Deno.serve is not in the types
25
- Deno.serve(app.fetch);
26
- };