vxrn 0.1.28 → 0.1.30
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/cjs/create.js +643 -0
- package/dist/cjs/create.js.map +6 -0
- package/dist/cjs/create.native.js +1318 -0
- package/dist/cjs/create.native.js.map +6 -0
- package/dist/cjs/exports/dev.js +3 -5
- package/dist/cjs/exports/dev.js.map +1 -1
- package/dist/cjs/exports/dev.native.js +3 -5
- package/dist/cjs/exports/dev.native.js.map +1 -1
- package/dist/cjs/getVitePath.js +50 -0
- package/dist/cjs/getVitePath.js.map +6 -0
- package/dist/cjs/getVitePath.native.js +197 -0
- package/dist/cjs/getVitePath.native.js.map +6 -0
- package/dist/cjs/utils/getOptionsFilled.js +6 -3
- package/dist/cjs/utils/getOptionsFilled.js.map +1 -1
- package/dist/cjs/utils/getOptionsFilled.native.js +16 -5
- package/dist/cjs/utils/getOptionsFilled.native.js.map +2 -2
- package/dist/cjs/vendor/createExpoServer.js +16 -4
- package/dist/cjs/vendor/createExpoServer.js.map +1 -1
- package/dist/cjs/vendor/createExpoServer.native.js +148 -4
- package/dist/cjs/vendor/createExpoServer.native.js.map +2 -2
- package/dist/esm/create.js +655 -0
- package/dist/esm/create.js.map +6 -0
- package/dist/esm/create.mjs +622 -0
- package/dist/esm/create.native.js +1309 -0
- package/dist/esm/create.native.js.map +6 -0
- package/dist/esm/exports/dev.js +3 -5
- package/dist/esm/exports/dev.js.map +1 -1
- package/dist/esm/exports/dev.mjs +3 -5
- package/dist/esm/exports/dev.native.js +3 -5
- package/dist/esm/exports/dev.native.js.map +1 -1
- package/dist/esm/getVitePath.js +28 -0
- package/dist/esm/getVitePath.js.map +6 -0
- package/dist/esm/getVitePath.mjs +21 -0
- package/dist/esm/getVitePath.native.js +170 -0
- package/dist/esm/getVitePath.native.js.map +6 -0
- package/dist/esm/utils/getOptionsFilled.js +6 -2
- package/dist/esm/utils/getOptionsFilled.js.map +1 -1
- package/dist/esm/utils/getOptionsFilled.mjs +8 -3
- package/dist/esm/utils/getOptionsFilled.native.js +16 -4
- package/dist/esm/utils/getOptionsFilled.native.js.map +2 -2
- package/dist/esm/vendor/createExpoServer.js +16 -3
- package/dist/esm/vendor/createExpoServer.js.map +1 -1
- package/dist/esm/vendor/createExpoServer.mjs +16 -3
- package/dist/esm/vendor/createExpoServer.native.js +148 -3
- package/dist/esm/vendor/createExpoServer.native.js.map +2 -2
- package/package.json +8 -8
- package/src/exports/dev.ts +2 -7
- package/src/utils/getOptionsFilled.ts +10 -3
- package/src/vendor/createExpoServer.ts +21 -5
- package/types/vendor/createExpoServer.d.ts +3 -2
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
import wsAdapter from "crossws/adapters/node";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { createApp, createRouter, defineEventHandler, defineWebSocketHandler, eventHandler, getQuery, toNodeListener } from "h3";
|
|
4
|
+
import { createProxyEventHandler } from "h3-proxy";
|
|
5
|
+
import { createServer as nodeCreateServer } from "node:http";
|
|
6
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
7
|
+
import readline from "node:readline";
|
|
8
|
+
import viteInspectPlugin from "vite-plugin-inspect";
|
|
9
|
+
import { WebSocket } from "ws";
|
|
10
|
+
import { readPackageJSON } from "pkg-types";
|
|
11
|
+
import findNodeModules from "find-node-modules";
|
|
12
|
+
import * as babel from "@babel/core";
|
|
13
|
+
import react from "@vitejs/plugin-react-swc";
|
|
14
|
+
import { buildReact, buildReactJSX, buildReactNative } from "@vxrn/react-native-prebuilt";
|
|
15
|
+
import viteReactPlugin, { swcTransform, transformForBuild } from "@vxrn/vite-native-swc";
|
|
16
|
+
import { parse } from "es-module-lexer";
|
|
17
|
+
import FSExtra from "fs-extra";
|
|
18
|
+
import { build, createServer, mergeConfig, resolveConfig, transformWithEsbuild } from "vite";
|
|
19
|
+
import { resolve as importMetaResolve } from "import-meta-resolve";
|
|
20
|
+
import { clientInjectionsPlugin } from "./dev/clientInjectPlugin.mjs";
|
|
21
|
+
import { getVitePath } from "./getVitePath.mjs";
|
|
22
|
+
import { nativePlugin } from "./nativePlugin.mjs";
|
|
23
|
+
import createViteFlow from "@vxrn/vite-flow";
|
|
24
|
+
const resolveFile = path => {
|
|
25
|
+
try {
|
|
26
|
+
return importMetaResolve(path, import.meta.url).replace("file://", "");
|
|
27
|
+
} catch {
|
|
28
|
+
return require.resolve(path);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
nativeExtensions = [".native.tsx", ".native.jsx", ".native.js", ".tsx", ".ts", ".js", ".css", ".json"],
|
|
32
|
+
extensions = [".web.tsx", ".tsx", ".web.ts", ".ts", ".web.jsx", ".jsx", ".web.js", ".js", ".css", ".json"];
|
|
33
|
+
async function readState(cacheDir) {
|
|
34
|
+
const statePath = join(cacheDir, "state.json");
|
|
35
|
+
return (await FSExtra.pathExists(statePath)) ? await FSExtra.readJSON(statePath) : {};
|
|
36
|
+
}
|
|
37
|
+
async function getOptionsFilled(options) {
|
|
38
|
+
const {
|
|
39
|
+
host = "127.0.0.1",
|
|
40
|
+
root = process.cwd(),
|
|
41
|
+
port = 8081
|
|
42
|
+
} = options,
|
|
43
|
+
packageRootDir = join(import.meta.url ?? __filename, "..", "..", "..").replace("file:", ""),
|
|
44
|
+
cacheDir = join(root, "node_modules", ".cache", "vxrn"),
|
|
45
|
+
internalPatchesDir = join(packageRootDir, "patches"),
|
|
46
|
+
userPatchesDir = join(root, "patches"),
|
|
47
|
+
[state, packageJSON] = await Promise.all([
|
|
48
|
+
//
|
|
49
|
+
readState(cacheDir), readPackageJSON()]);
|
|
50
|
+
return {
|
|
51
|
+
...options,
|
|
52
|
+
packageJSON,
|
|
53
|
+
state,
|
|
54
|
+
packageRootDir,
|
|
55
|
+
cacheDir,
|
|
56
|
+
userPatchesDir,
|
|
57
|
+
internalPatchesDir,
|
|
58
|
+
host,
|
|
59
|
+
root,
|
|
60
|
+
port
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const {
|
|
64
|
+
ensureDir,
|
|
65
|
+
pathExists,
|
|
66
|
+
pathExistsSync
|
|
67
|
+
} = FSExtra,
|
|
68
|
+
patches = [{
|
|
69
|
+
module: "react-native-screens",
|
|
70
|
+
patchFile: "react-native-screens+3.22.1.patch"
|
|
71
|
+
}];
|
|
72
|
+
async function checkPatches(options) {
|
|
73
|
+
if (options.state.applyPatches === !1) return;
|
|
74
|
+
const nodeModulesDirs = findNodeModules({
|
|
75
|
+
cwd: options.root
|
|
76
|
+
}).map(relativePath => join(options.root, relativePath)),
|
|
77
|
+
patchesToCopy = /* @__PURE__ */new Set();
|
|
78
|
+
await Promise.all(patches.flatMap(patch => nodeModulesDirs.flatMap(async dir => {
|
|
79
|
+
(await FSExtra.pathExists(join(dir, patch.module))) && patchesToCopy.add(patch);
|
|
80
|
+
})));
|
|
81
|
+
let didCopy = !1;
|
|
82
|
+
for (const patch of [...patchesToCopy]) {
|
|
83
|
+
const dest = join(options.userPatchesDir, patch.patchFile);
|
|
84
|
+
if (!(await pathExists(dest))) {
|
|
85
|
+
didCopy = !0, console.info(`Copying patch ${patch.module}`);
|
|
86
|
+
const src = join(options.internalPatchesDir, patch.patchFile);
|
|
87
|
+
await FSExtra.copy(src, dest);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
didCopy && (console.info(`
|
|
91
|
+
Please restart after applying the patch by running "npx patch-package".
|
|
92
|
+
Ideally add it to your devDependencies and as a postinstall script.
|
|
93
|
+
`), process.exit(0));
|
|
94
|
+
}
|
|
95
|
+
const create = async optionsIn => {
|
|
96
|
+
const options = await getOptionsFilled(optionsIn),
|
|
97
|
+
{
|
|
98
|
+
host,
|
|
99
|
+
port,
|
|
100
|
+
root,
|
|
101
|
+
cacheDir
|
|
102
|
+
} = options;
|
|
103
|
+
bindKeypressInput();
|
|
104
|
+
let entryRoot = "";
|
|
105
|
+
checkPatches(options).catch(err => {
|
|
106
|
+
console.error(`
|
|
107
|
+
\u{1F97A} couldn't patch`, err);
|
|
108
|
+
}), await ensureDir(cacheDir);
|
|
109
|
+
const prebuilds = {
|
|
110
|
+
reactJSX: join(cacheDir, "react-jsx-runtime.js"),
|
|
111
|
+
react: join(cacheDir, "react.js"),
|
|
112
|
+
reactNative: join(cacheDir, "react-native.js")
|
|
113
|
+
};
|
|
114
|
+
(await pathExists(prebuilds.reactNative)) || (console.info("Pre-building react, react-native react/jsx-runtime (one time cost)..."), await Promise.all([buildReactNative({
|
|
115
|
+
entryPoints: [resolveFile("react-native")],
|
|
116
|
+
outfile: prebuilds.reactNative
|
|
117
|
+
}), buildReact({
|
|
118
|
+
entryPoints: [resolveFile("react")],
|
|
119
|
+
outfile: prebuilds.react
|
|
120
|
+
}), buildReactJSX({
|
|
121
|
+
entryPoints: [resolveFile("react/jsx-dev-runtime")],
|
|
122
|
+
outfile: prebuilds.reactJSX
|
|
123
|
+
})]));
|
|
124
|
+
const viteFlow = options.flow ? createViteFlow(options.flow) : null,
|
|
125
|
+
templateFile = resolveFile("vxrn/react-native-template.js"),
|
|
126
|
+
hmrListeners = [],
|
|
127
|
+
hotUpdatedCJSFiles = /* @__PURE__ */new Map(),
|
|
128
|
+
jsxRuntime = {
|
|
129
|
+
// alias: 'virtual:react-jsx',
|
|
130
|
+
alias: prebuilds.reactJSX,
|
|
131
|
+
contents: await readFile(prebuilds.reactJSX, "utf-8")
|
|
132
|
+
},
|
|
133
|
+
virtualModules = {
|
|
134
|
+
"react-native": {
|
|
135
|
+
// alias: 'virtual:react-native',
|
|
136
|
+
alias: prebuilds.reactNative,
|
|
137
|
+
contents: await readFile(prebuilds.reactNative, "utf-8")
|
|
138
|
+
},
|
|
139
|
+
react: {
|
|
140
|
+
// alias: 'virtual:react',
|
|
141
|
+
alias: prebuilds.react,
|
|
142
|
+
contents: await readFile(prebuilds.react, "utf-8")
|
|
143
|
+
},
|
|
144
|
+
"react/jsx-runtime": jsxRuntime,
|
|
145
|
+
"react/jsx-dev-runtime": jsxRuntime
|
|
146
|
+
},
|
|
147
|
+
swapRnPlugin = {
|
|
148
|
+
name: "swap-react-native",
|
|
149
|
+
enforce: "pre",
|
|
150
|
+
resolveId(id, importer = "") {
|
|
151
|
+
if (id.startsWith("react-native/Libraries")) return `virtual:rn-internals:${id}`;
|
|
152
|
+
if (id === "react-native-web") return prebuilds.reactNative;
|
|
153
|
+
for (const targetId in virtualModules) if (id === targetId || id.includes(`node_modules/${targetId}/`)) return virtualModules[targetId].alias;
|
|
154
|
+
if (id[0] === ".") {
|
|
155
|
+
const absolutePath = resolve(dirname(importer), id),
|
|
156
|
+
nativePath = absolutePath.replace(/(.m?js)/, ".native.js");
|
|
157
|
+
if (nativePath === id) return;
|
|
158
|
+
try {
|
|
159
|
+
const directoryPath = absolutePath + "/index.native.js",
|
|
160
|
+
directoryNonNativePath = absolutePath + "/index.js";
|
|
161
|
+
if (pathExistsSync(directoryPath)) return directoryPath;
|
|
162
|
+
if (pathExistsSync(directoryNonNativePath)) return directoryNonNativePath;
|
|
163
|
+
if (pathExistsSync(nativePath)) return nativePath;
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.warn("error probably fine", err);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
load(id) {
|
|
170
|
+
if (id.startsWith("virtual:rn-internals")) return `const val = __cachedModules["${id.replace("virtual:rn-internals:", "")}"]
|
|
171
|
+
export const PressabilityDebugView = val.PressabilityDebugView
|
|
172
|
+
export default val ? val.default || val : val`;
|
|
173
|
+
for (const targetId in virtualModules) {
|
|
174
|
+
const info = virtualModules[targetId];
|
|
175
|
+
if (id === info.alias) return info.contents;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
depsToOptimize = ["react", "react-dom", "@react-native/normalize-color"];
|
|
180
|
+
let serverConfig = {
|
|
181
|
+
root,
|
|
182
|
+
mode: "development",
|
|
183
|
+
clearScreen: !1,
|
|
184
|
+
define: {
|
|
185
|
+
__DEV__: "true",
|
|
186
|
+
"process.env.NODE_ENV": '"development"'
|
|
187
|
+
},
|
|
188
|
+
resolve: {
|
|
189
|
+
// dedupe: ['react', 'react-dom'],
|
|
190
|
+
alias: {
|
|
191
|
+
// ...Object.fromEntries(Object.entries(virtualModules).map(([k, v]) => [k, v.alias])),
|
|
192
|
+
"react-native": resolveFile("react-native-web-lite")
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
optimizeDeps: {
|
|
196
|
+
include: depsToOptimize,
|
|
197
|
+
exclude: Object.values(virtualModules).map(v => v.alias),
|
|
198
|
+
force: !0,
|
|
199
|
+
esbuildOptions: {
|
|
200
|
+
resolveExtensions: extensions
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
build: {
|
|
204
|
+
commonjsOptions: {
|
|
205
|
+
transformMixedEsModules: !0
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
plugins: [
|
|
209
|
+
// this breaks web, but for native maybe we need to manually run in the native handleHotUpdate below
|
|
210
|
+
// swapRnPlugin,
|
|
211
|
+
viteFlow, react(),
|
|
212
|
+
// viteReactPlugin({
|
|
213
|
+
// tsDecorators: true,
|
|
214
|
+
// mode: 'serve',
|
|
215
|
+
// }),
|
|
216
|
+
{
|
|
217
|
+
name: "client-transform",
|
|
218
|
+
async handleHotUpdate({
|
|
219
|
+
read,
|
|
220
|
+
modules,
|
|
221
|
+
file
|
|
222
|
+
}) {
|
|
223
|
+
try {
|
|
224
|
+
if (!isWithin(root, file)) return;
|
|
225
|
+
const [module] = modules;
|
|
226
|
+
if (!module) return;
|
|
227
|
+
const id = module?.url || file.replace(root, ""),
|
|
228
|
+
code = await read();
|
|
229
|
+
if (code.startsWith("'use strict';") || !code) return;
|
|
230
|
+
let source = code;
|
|
231
|
+
source = (await transformForBuild(id, source))?.code || "";
|
|
232
|
+
const importsMap = {},
|
|
233
|
+
[imports] = parse(source);
|
|
234
|
+
let accumulatedSliceOffset = 0;
|
|
235
|
+
for (const specifier of imports) {
|
|
236
|
+
const {
|
|
237
|
+
n: importName,
|
|
238
|
+
s: start
|
|
239
|
+
} = specifier;
|
|
240
|
+
if (importName) {
|
|
241
|
+
const id2 = await getVitePath(entryRoot, file, importName);
|
|
242
|
+
if (!id2) {
|
|
243
|
+
console.warn("???");
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
importsMap[id2] = id2.replace(/^(\.\.\/)+/, "");
|
|
247
|
+
const len = importName.length,
|
|
248
|
+
extraLen = id2.length - len;
|
|
249
|
+
source = source.slice(0, start + accumulatedSliceOffset) + id2 + source.slice(start + accumulatedSliceOffset + len), accumulatedSliceOffset += extraLen;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (source = (await swcTransform(id, source, {
|
|
253
|
+
mode: "serve-cjs"
|
|
254
|
+
}))?.code || "", !source) throw "\u274C no source";
|
|
255
|
+
const hotUpdateSource = `exports = ((exports) => {
|
|
256
|
+
const require = createRequire(${JSON.stringify(importsMap, null, 2)})
|
|
257
|
+
${source.replace("import.meta.hot.accept(() => {})", "").replaceAll(/import.meta.glob\(.*\)/gi, "globalThis['__importMetaGlobbed'] || {}")};
|
|
258
|
+
return exports })({})`;
|
|
259
|
+
process.env.DEBUG && console.info("Sending hot update", hotUpdateSource), hotUpdatedCJSFiles.set(id, hotUpdateSource);
|
|
260
|
+
} catch (err) {
|
|
261
|
+
console.error("Error processing hmr update:", err);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}],
|
|
265
|
+
server: {
|
|
266
|
+
hmr: {
|
|
267
|
+
path: "/__vxrnhmr"
|
|
268
|
+
},
|
|
269
|
+
cors: !0,
|
|
270
|
+
host
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
options.webConfig && (serverConfig = mergeConfig(serverConfig, options.webConfig));
|
|
274
|
+
const resolvedConfig = await resolveConfig(serverConfig, "serve"),
|
|
275
|
+
viteRNClientPlugin = clientInjectionsPlugin(resolvedConfig);
|
|
276
|
+
serverConfig = {
|
|
277
|
+
...serverConfig,
|
|
278
|
+
plugins: [...serverConfig.plugins]
|
|
279
|
+
};
|
|
280
|
+
const viteServer = await createServer(serverConfig);
|
|
281
|
+
viteServer.watcher.addListener("change", async path => {
|
|
282
|
+
const id = path.replace(process.cwd(), "");
|
|
283
|
+
if (!(!id.endsWith("tsx") && !id.endsWith("jsx"))) try {
|
|
284
|
+
viteServer.transformRequest(id);
|
|
285
|
+
} catch (err) {
|
|
286
|
+
console.info("err", err);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
let isBuilding = null;
|
|
290
|
+
await viteServer.listen();
|
|
291
|
+
const vitePort = viteServer.config.server.port;
|
|
292
|
+
console.info("vite running on", vitePort);
|
|
293
|
+
const router = createRouter(),
|
|
294
|
+
app = createApp({
|
|
295
|
+
onError: error => {
|
|
296
|
+
console.error(error);
|
|
297
|
+
},
|
|
298
|
+
onRequest: event => {
|
|
299
|
+
console.info(" \u2192", event.path);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
router.get("/file", defineEventHandler(e => {
|
|
303
|
+
const query = getQuery(e);
|
|
304
|
+
if (typeof query.file == "string") {
|
|
305
|
+
const source = hotUpdatedCJSFiles.get(query.file);
|
|
306
|
+
return new Response(source, {
|
|
307
|
+
headers: {
|
|
308
|
+
"content-type": "text/javascript"
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
})), router.get("/index.bundle", defineEventHandler(async e => new Response(await getBundleCode(), {
|
|
313
|
+
headers: {
|
|
314
|
+
"content-type": "text/javascript"
|
|
315
|
+
}
|
|
316
|
+
}))), router.get("/status", defineEventHandler(() => "packager-status:running")), app.use(router), app.use(defineEventHandler(async ({
|
|
317
|
+
node: {
|
|
318
|
+
req
|
|
319
|
+
}
|
|
320
|
+
}) => {
|
|
321
|
+
if (req.headers["user-agent"]?.match(/Expo|React/) && (req.url === "/" || req.url?.startsWith("/?platform="))) return getIndexJsonResponse({
|
|
322
|
+
port,
|
|
323
|
+
root
|
|
324
|
+
});
|
|
325
|
+
}));
|
|
326
|
+
const {
|
|
327
|
+
handleUpgrade
|
|
328
|
+
} = wsAdapter(app.websocket);
|
|
329
|
+
if (vitePort) {
|
|
330
|
+
const clients = /* @__PURE__ */new Set(),
|
|
331
|
+
socket = new WebSocket(`ws://localhost:${vitePort}/__vxrnhmr`, "vite-hmr");
|
|
332
|
+
console.info("connecting to vite..."), socket.on("open", () => {
|
|
333
|
+
console.info("...connected to vite!");
|
|
334
|
+
}), socket.on("message", msg => {
|
|
335
|
+
const message = msg.toString();
|
|
336
|
+
console.info(clients.size, "message", message);
|
|
337
|
+
for (const listener of [...clients]) listener.send(message);
|
|
338
|
+
}), socket.on("error", err => {
|
|
339
|
+
console.info("err", err);
|
|
340
|
+
}), app.use("/__vxrnhmr", defineWebSocketHandler({
|
|
341
|
+
open(peer) {
|
|
342
|
+
console.debug("[hmr:web] open", peer), clients.add(peer);
|
|
343
|
+
},
|
|
344
|
+
message(peer, message) {
|
|
345
|
+
socket.send(message.rawData);
|
|
346
|
+
},
|
|
347
|
+
close(peer, event) {
|
|
348
|
+
console.info("[hmr:web] close", peer, event), clients.delete(peer);
|
|
349
|
+
},
|
|
350
|
+
error(peer, error) {
|
|
351
|
+
console.error("[hmr:web] error", peer, error);
|
|
352
|
+
}
|
|
353
|
+
}));
|
|
354
|
+
}
|
|
355
|
+
app.use("/__hmr", defineWebSocketHandler({
|
|
356
|
+
open(peer) {
|
|
357
|
+
console.debug("[hmr] open", peer);
|
|
358
|
+
},
|
|
359
|
+
message(peer, message) {
|
|
360
|
+
console.info("[hmr] message", peer, message), message.text().includes("ping") && peer.send("pong");
|
|
361
|
+
},
|
|
362
|
+
close(peer, event) {
|
|
363
|
+
console.info("[hmr] close", peer, event);
|
|
364
|
+
},
|
|
365
|
+
error(peer, error) {
|
|
366
|
+
console.error("[hmr] error", peer, error);
|
|
367
|
+
}
|
|
368
|
+
})), app.use("/__client", defineWebSocketHandler({
|
|
369
|
+
open(peer) {
|
|
370
|
+
console.info("[client] open", peer);
|
|
371
|
+
},
|
|
372
|
+
message(peer, messageRaw) {
|
|
373
|
+
const message = JSON.parse(messageRaw.text());
|
|
374
|
+
switch (message.type) {
|
|
375
|
+
case "client-log":
|
|
376
|
+
{
|
|
377
|
+
console.info(`\u{1FAB5} [${message.level}]`, ...message.data);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
default:
|
|
381
|
+
console.warn("[client] Unknown message type", message);
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
close(peer, event) {
|
|
385
|
+
console.info("[client] close", peer, event);
|
|
386
|
+
},
|
|
387
|
+
error(peer, error) {
|
|
388
|
+
console.error("[client] error", peer, error);
|
|
389
|
+
}
|
|
390
|
+
}));
|
|
391
|
+
const proxyEventHandler = createProxyEventHandler({
|
|
392
|
+
target: `http://127.0.0.1:${vitePort}`,
|
|
393
|
+
enableLogger: !!process.env.DEBUG
|
|
394
|
+
});
|
|
395
|
+
app.use(eventHandler(proxyEventHandler));
|
|
396
|
+
const server = nodeCreateServer(toNodeListener(app));
|
|
397
|
+
return server.on("upgrade", handleUpgrade), {
|
|
398
|
+
nativeServer: server,
|
|
399
|
+
viteServer,
|
|
400
|
+
async start() {
|
|
401
|
+
return server.listen(port), console.info(`Server running on http://localhost:${port}`), {
|
|
402
|
+
closePromise: new Promise(res => viteServer.httpServer?.on("close", res))
|
|
403
|
+
};
|
|
404
|
+
},
|
|
405
|
+
stop: async () => {
|
|
406
|
+
await Promise.all([server.close(), viteServer.close()]);
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
async function getBundleCode() {
|
|
410
|
+
if (process.env.LOAD_TMP_BUNDLE) {
|
|
411
|
+
const tmpBundle = join(process.cwd(), "bundle.tmp.js");
|
|
412
|
+
if (await pathExists(tmpBundle)) return console.info("\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F returning temp bundle \u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F", tmpBundle), await readFile(tmpBundle, "utf-8");
|
|
413
|
+
}
|
|
414
|
+
if (isBuilding) return await isBuilding;
|
|
415
|
+
let done;
|
|
416
|
+
isBuilding = new Promise(res => {
|
|
417
|
+
done = res;
|
|
418
|
+
});
|
|
419
|
+
async function babelReanimated(input, filename) {
|
|
420
|
+
return await new Promise((res, rej) => {
|
|
421
|
+
babel.transform(input, {
|
|
422
|
+
plugins: ["react-native-reanimated/plugin"],
|
|
423
|
+
filename
|
|
424
|
+
}, (err, result) => {
|
|
425
|
+
(!result || err) && rej(err || "no res"), res(result.code);
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
let buildConfig = {
|
|
430
|
+
plugins: [viteFlow, swapRnPlugin, {
|
|
431
|
+
name: "reanimated",
|
|
432
|
+
async transform(code, id) {
|
|
433
|
+
if (code.includes("worklet")) return await babelReanimated(code, id);
|
|
434
|
+
}
|
|
435
|
+
}, viteRNClientPlugin, nativePlugin({
|
|
436
|
+
root,
|
|
437
|
+
port,
|
|
438
|
+
mode: "build"
|
|
439
|
+
}), viteReactPlugin({
|
|
440
|
+
tsDecorators: !0,
|
|
441
|
+
mode: "build"
|
|
442
|
+
}), viteInspectPlugin({
|
|
443
|
+
build: !0,
|
|
444
|
+
outputDir: ".vite-inspect"
|
|
445
|
+
}), {
|
|
446
|
+
name: "treat-js-files-as-jsx",
|
|
447
|
+
async transform(code, id) {
|
|
448
|
+
return id.match(/expo-status-bar/) ? transformWithEsbuild(code, id, {
|
|
449
|
+
loader: "jsx",
|
|
450
|
+
jsx: "automatic"
|
|
451
|
+
}) : null;
|
|
452
|
+
}
|
|
453
|
+
}],
|
|
454
|
+
appType: "custom",
|
|
455
|
+
root,
|
|
456
|
+
clearScreen: !1,
|
|
457
|
+
optimizeDeps: {
|
|
458
|
+
include: depsToOptimize,
|
|
459
|
+
esbuildOptions: {
|
|
460
|
+
jsx: "automatic"
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
build: {
|
|
464
|
+
ssr: !1,
|
|
465
|
+
minify: !1,
|
|
466
|
+
commonjsOptions: {
|
|
467
|
+
transformMixedEsModules: !0
|
|
468
|
+
},
|
|
469
|
+
rollupOptions: {
|
|
470
|
+
treeshake: !1,
|
|
471
|
+
preserveEntrySignatures: "strict",
|
|
472
|
+
output: {
|
|
473
|
+
preserveModules: !0,
|
|
474
|
+
format: "cjs"
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
resolve: {
|
|
479
|
+
extensions: nativeExtensions
|
|
480
|
+
},
|
|
481
|
+
mode: "development",
|
|
482
|
+
define: {
|
|
483
|
+
"process.env.NODE_ENV": '"development"'
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
options.buildConfig && (buildConfig = mergeConfig(buildConfig, options.buildConfig)), await resolveConfig(buildConfig, "build");
|
|
487
|
+
const buildOutput = await build(buildConfig);
|
|
488
|
+
if (!("output" in buildOutput)) throw "\u274C";
|
|
489
|
+
let appCode = buildOutput.output.sort((a, b) => a.isEntry ? 1 : -1).map(outputModule => {
|
|
490
|
+
if (outputModule.type == "chunk") {
|
|
491
|
+
const importsMap = {};
|
|
492
|
+
for (const imp of outputModule.imports) {
|
|
493
|
+
const relativePath = relative(dirname(outputModule.fileName), imp);
|
|
494
|
+
importsMap[relativePath[0] === "." ? relativePath : "./" + relativePath] = imp;
|
|
495
|
+
}
|
|
496
|
+
return outputModule.isEntry && (entryRoot = dirname(outputModule.fileName)), `
|
|
497
|
+
___modules___["${outputModule.fileName}"] = ((exports, module) => {
|
|
498
|
+
const require = createRequire(${JSON.stringify(importsMap, null, 2)})
|
|
499
|
+
|
|
500
|
+
${outputModule.code}
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
${outputModule.isEntry ? `
|
|
504
|
+
// run entry
|
|
505
|
+
const __require = createRequire({})
|
|
506
|
+
__require("react-native")
|
|
507
|
+
__require("${outputModule.fileName}")
|
|
508
|
+
` : ""}
|
|
509
|
+
`;
|
|
510
|
+
}
|
|
511
|
+
}).join(`
|
|
512
|
+
`);
|
|
513
|
+
if (!appCode) throw "\u274C";
|
|
514
|
+
appCode = appCode.replaceAll("undefined.accept(() => {})", "").replaceAll("undefined.accept(function() {});", "").replaceAll("(void 0).accept(() => {})", "").replaceAll("(void 0).accept(function() {});", "");
|
|
515
|
+
const appRootParent = join(root, "..", ".."),
|
|
516
|
+
out = (await readFile(templateFile, "utf-8")).replace("_virtual/virtual_react-native.js", relative(appRootParent, prebuilds.reactNative)).replace("_virtual/virtual_react.js", relative(appRootParent, prebuilds.react)).replaceAll("_virtual/virtual_react-jsx.js", relative(appRootParent, prebuilds.reactJSX)) + appCode;
|
|
517
|
+
return done(out), isBuilding = null, out;
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
function getIndexJsonResponse({
|
|
521
|
+
port,
|
|
522
|
+
root
|
|
523
|
+
}) {
|
|
524
|
+
return {
|
|
525
|
+
name: "myapp",
|
|
526
|
+
slug: "myapp",
|
|
527
|
+
scheme: "myapp",
|
|
528
|
+
version: "1.0.0",
|
|
529
|
+
jsEngine: "jsc",
|
|
530
|
+
orientation: "portrait",
|
|
531
|
+
icon: "./assets/icon.png",
|
|
532
|
+
userInterfaceStyle: "light",
|
|
533
|
+
splash: {
|
|
534
|
+
image: "./assets/splash.png",
|
|
535
|
+
resizeMode: "contain",
|
|
536
|
+
backgroundColor: "#ffffff",
|
|
537
|
+
imageUrl: "http://127.0.0.1:8081/assets/./assets/splash.png"
|
|
538
|
+
},
|
|
539
|
+
updates: {
|
|
540
|
+
fallbackToCacheTimeout: 0
|
|
541
|
+
},
|
|
542
|
+
assetBundlePatterns: ["**/*"],
|
|
543
|
+
ios: {
|
|
544
|
+
supportsTablet: !0,
|
|
545
|
+
bundleIdentifier: "com.natew.myapp"
|
|
546
|
+
},
|
|
547
|
+
android: {
|
|
548
|
+
package: "com.tamagui.myapp",
|
|
549
|
+
adaptiveIcon: {
|
|
550
|
+
foregroundImage: "./assets/adaptive-icon.png",
|
|
551
|
+
backgroundColor: "#FFFFFF",
|
|
552
|
+
foregroundImageUrl: "http://127.0.0.1:8081/assets/./assets/adaptive-icon.png"
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
web: {
|
|
556
|
+
favicon: "./assets/favicon.png"
|
|
557
|
+
},
|
|
558
|
+
extra: {
|
|
559
|
+
eas: {
|
|
560
|
+
projectId: "061b4470-78c7-4d6a-b850-8167fb0a3434"
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
_internal: {
|
|
564
|
+
isDebug: !1,
|
|
565
|
+
projectRoot: root,
|
|
566
|
+
dynamicConfigPath: null,
|
|
567
|
+
staticConfigPath: join(root, "app.json"),
|
|
568
|
+
packageJsonPath: join(root, "package.json")
|
|
569
|
+
},
|
|
570
|
+
sdkVersion: "47.0.0",
|
|
571
|
+
platforms: ["ios", "android", "web"],
|
|
572
|
+
iconUrl: `http://127.0.0.1:${port}/assets/./assets/icon.png`,
|
|
573
|
+
debuggerHost: `127.0.0.1:${port}`,
|
|
574
|
+
logUrl: `http://127.0.0.1:${port}/logs`,
|
|
575
|
+
developer: {
|
|
576
|
+
tool: "expo-cli",
|
|
577
|
+
projectRoot: root
|
|
578
|
+
},
|
|
579
|
+
packagerOpts: {
|
|
580
|
+
dev: !0
|
|
581
|
+
},
|
|
582
|
+
mainModuleName: "index",
|
|
583
|
+
__flipperHack: "React Native packager is running",
|
|
584
|
+
hostUri: `127.0.0.1:${port}`,
|
|
585
|
+
bundleUrl: `http://127.0.0.1:${port}/index.bundle?platform=ios&dev=true&hot=false&lazy=true`,
|
|
586
|
+
id: "@anonymous/myapp-473c4543-3c36-4786-9db1-c66a62ac9b78"
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function bindKeypressInput() {
|
|
590
|
+
if (!process.stdin.setRawMode) {
|
|
591
|
+
console.warn({
|
|
592
|
+
msg: "Interactive mode is not supported in this environment"
|
|
593
|
+
});
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
readline.emitKeypressEvents(process.stdin), process.stdin.setRawMode(!0), process.stdin.on("keypress", (_key, data) => {
|
|
597
|
+
const {
|
|
598
|
+
ctrl,
|
|
599
|
+
name
|
|
600
|
+
} = data;
|
|
601
|
+
if (ctrl === !0) switch (name) {
|
|
602
|
+
case "c":
|
|
603
|
+
process.exit();
|
|
604
|
+
case "z":
|
|
605
|
+
process.emit("SIGTSTP", "SIGTSTP");
|
|
606
|
+
break;
|
|
607
|
+
} else switch (name) {
|
|
608
|
+
case "r":
|
|
609
|
+
break;
|
|
610
|
+
case "d":
|
|
611
|
+
break;
|
|
612
|
+
case "c":
|
|
613
|
+
process.stdout.write("\x1B[2J\x1B[0;0H");
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
function isWithin(outer, inner) {
|
|
619
|
+
const rel = relative(outer, inner);
|
|
620
|
+
return !rel.startsWith("../") && rel !== "..";
|
|
621
|
+
}
|
|
622
|
+
export { bindKeypressInput, create };
|