freestyle-sandboxes 0.0.37 → 0.0.40
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/dist/ai/index.cjs +1 -1
- package/dist/ai/index.d.cts +3 -1
- package/dist/ai/index.d.mts +3 -1
- package/dist/ai/index.mjs +1 -1
- package/dist/expo/index.cjs +319 -0
- package/dist/expo/index.d.cts +6 -0
- package/dist/expo/index.d.mts +6 -0
- package/dist/expo/index.mjs +297 -0
- package/dist/index-D1ulQeJR.mjs +3247 -0
- package/dist/index-H7UNEAjs.cjs +3254 -0
- package/dist/langgraph/index.cjs +1 -1
- package/dist/langgraph/index.mjs +1 -1
- package/dist/mastra/index.cjs +1 -1
- package/dist/mastra/index.mjs +1 -1
- package/dist/utils/index.cjs +4 -2
- package/dist/utils/index.mjs +4 -2
- package/package.json +15 -3
- package/src/ai/index.ts +5 -3
- package/src/expo/_expo_internals.ts +389 -0
- package/src/expo/index.ts +26 -0
- package/src/utils/index.ts +2 -0
package/dist/langgraph/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var index$1 = require('../index.cjs');
|
|
4
4
|
var zod = require('zod');
|
|
5
|
-
var index = require('../index-
|
|
5
|
+
var index = require('../index-H7UNEAjs.cjs');
|
|
6
6
|
require('@hey-api/client-fetch');
|
|
7
7
|
|
|
8
8
|
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
package/dist/langgraph/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FreestyleSandboxes } from '../index.mjs';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { g as getDefaultExportFromCjs, z as zodToJsonSchema, a as executeCodeSchema, e as executeCodeDescription } from '../index-
|
|
3
|
+
import { g as getDefaultExportFromCjs, z as zodToJsonSchema, a as executeCodeSchema, e as executeCodeDescription } from '../index-D1ulQeJR.mjs';
|
|
4
4
|
import '@hey-api/client-fetch';
|
|
5
5
|
|
|
6
6
|
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
package/dist/mastra/index.cjs
CHANGED
package/dist/mastra/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { e as executeCodeDescription, a as executeCodeSchema } from '../index-
|
|
2
|
+
import { e as executeCodeDescription, a as executeCodeSchema } from '../index-D1ulQeJR.mjs';
|
|
3
3
|
import { FreestyleSandboxes } from '../index.mjs';
|
|
4
4
|
import '@hey-api/client-fetch';
|
|
5
5
|
|
package/dist/utils/index.cjs
CHANGED
|
@@ -33,7 +33,8 @@ const prepareDirForDeployment = async (directory) => {
|
|
|
33
33
|
nodir: true,
|
|
34
34
|
ignore: ["**/node_modules/**"],
|
|
35
35
|
absolute: false,
|
|
36
|
-
dot: true
|
|
36
|
+
dot: true,
|
|
37
|
+
posix: true
|
|
37
38
|
});
|
|
38
39
|
for (const relativePath of patterns) {
|
|
39
40
|
try {
|
|
@@ -59,7 +60,8 @@ const prepareDirForDeploymentSync = (directory) => {
|
|
|
59
60
|
nodir: true,
|
|
60
61
|
ignore: ["**/node_modules/**"],
|
|
61
62
|
absolute: false,
|
|
62
|
-
dot: true
|
|
63
|
+
dot: true,
|
|
64
|
+
posix: true
|
|
63
65
|
});
|
|
64
66
|
for (const relativePath of patterns) {
|
|
65
67
|
try {
|
package/dist/utils/index.mjs
CHANGED
|
@@ -10,7 +10,8 @@ const prepareDirForDeployment = async (directory) => {
|
|
|
10
10
|
nodir: true,
|
|
11
11
|
ignore: ["**/node_modules/**"],
|
|
12
12
|
absolute: false,
|
|
13
|
-
dot: true
|
|
13
|
+
dot: true,
|
|
14
|
+
posix: true
|
|
14
15
|
});
|
|
15
16
|
for (const relativePath of patterns) {
|
|
16
17
|
try {
|
|
@@ -36,7 +37,8 @@ const prepareDirForDeploymentSync = (directory) => {
|
|
|
36
37
|
nodir: true,
|
|
37
38
|
ignore: ["**/node_modules/**"],
|
|
38
39
|
absolute: false,
|
|
39
|
-
dot: true
|
|
40
|
+
dot: true,
|
|
41
|
+
posix: true
|
|
40
42
|
});
|
|
41
43
|
for (const relativePath of patterns) {
|
|
42
44
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freestyle-sandboxes",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -46,6 +46,16 @@
|
|
|
46
46
|
"default": "./dist/langgraph/index.mjs"
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
|
+
"./expo": {
|
|
50
|
+
"require": {
|
|
51
|
+
"types": "./dist/expo/index.d.cts",
|
|
52
|
+
"default": "./dist/expo/index.cjs"
|
|
53
|
+
},
|
|
54
|
+
"import": {
|
|
55
|
+
"types": "./dist/expo/index.d.mts",
|
|
56
|
+
"default": "./dist/expo/index.mjs"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
49
59
|
"./utils": {
|
|
50
60
|
"require": {
|
|
51
61
|
"types": "./dist/utils/index.d.cts",
|
|
@@ -67,16 +77,18 @@
|
|
|
67
77
|
"description": "",
|
|
68
78
|
"devDependencies": {
|
|
69
79
|
"@hey-api/openapi-ts": "^0.60.1",
|
|
70
|
-
"pkgroll": "^2.6.0",
|
|
71
80
|
"@langchain/core": "^0.3.38",
|
|
72
81
|
"@langchain/langgraph": "^0.2.44",
|
|
73
82
|
"@mastra/core": "^0.6.0",
|
|
74
83
|
"ai": "^4.0.25",
|
|
75
|
-
"humanlayer": "^0.7.0"
|
|
84
|
+
"humanlayer": "^0.7.0",
|
|
85
|
+
"pkgroll": "^2.6.0"
|
|
76
86
|
},
|
|
77
87
|
"dependencies": {
|
|
78
88
|
"@hey-api/client-fetch": "^0.5.7",
|
|
89
|
+
"expo-router": "^4.0.20",
|
|
79
90
|
"glob": "^11.0.1",
|
|
91
|
+
"hono": "^4.7.5",
|
|
80
92
|
"openai": "^4.77.3",
|
|
81
93
|
"openapi": "^1.0.1",
|
|
82
94
|
"zod": "^3.24.1"
|
package/src/ai/index.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
import { FreestyleSandboxes } from "..";
|
|
7
7
|
import { tool } from "ai";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { P } from "../../dist/types.gen-BuhQ5LpB";
|
|
10
9
|
|
|
11
10
|
export const executeCodeSchema = z.object({
|
|
12
11
|
script: z.string().describe(`
|
|
@@ -52,9 +51,11 @@ export const executeTool = (
|
|
|
52
51
|
config: FreestyleExecuteScriptParamsConfiguration & {
|
|
53
52
|
apiKey: string;
|
|
54
53
|
onResult?: (_v: {
|
|
54
|
+
toolCallId: string;
|
|
55
55
|
input: {
|
|
56
56
|
script: string;
|
|
57
|
-
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
};
|
|
58
59
|
result: FreestyleExecuteScriptResultSuccess | HandleExecuteScriptError;
|
|
59
60
|
}) => void | Promise<void>;
|
|
60
61
|
truncateOutput?: boolean;
|
|
@@ -69,11 +70,12 @@ export const executeTool = (
|
|
|
69
70
|
return tool({
|
|
70
71
|
description: executeCodeDescription(envVars, nodeModules),
|
|
71
72
|
parameters: executeCodeSchema,
|
|
72
|
-
execute: async ({ script, ...otherParams }) => {
|
|
73
|
+
execute: async ({ script, ...otherParams }, { toolCallId }) => {
|
|
73
74
|
try {
|
|
74
75
|
const res = await api.executeScript(script, config);
|
|
75
76
|
if (config.onResult) {
|
|
76
77
|
await config.onResult({
|
|
78
|
+
toolCallId,
|
|
77
79
|
result: res,
|
|
78
80
|
input: {
|
|
79
81
|
script,
|
|
@@ -0,0 +1,389 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
};
|
package/src/utils/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export const prepareDirForDeployment = async (
|
|
|
15
15
|
ignore: ["**/node_modules/**"],
|
|
16
16
|
absolute: false,
|
|
17
17
|
dot: true,
|
|
18
|
+
posix: true,
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
for (const relativePath of patterns) {
|
|
@@ -47,6 +48,7 @@ export const prepareDirForDeploymentSync = (
|
|
|
47
48
|
ignore: ["**/node_modules/**"],
|
|
48
49
|
absolute: false,
|
|
49
50
|
dot: true,
|
|
51
|
+
posix: true,
|
|
50
52
|
});
|
|
51
53
|
|
|
52
54
|
for (const relativePath of patterns) {
|