vxrn 2.13.8 → 2.13.9
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/cli.mjs +3 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/cli.native.js +5 -2
- package/dist/cli.native.js.map +1 -1
- package/dist/config/getBaseViteConfigOnly.mjs +3 -3
- package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
- package/dist/config/getBaseViteConfigOnly.native.js +3 -3
- package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
- package/dist/config/getOptionsFilled.mjs +24 -2
- package/dist/config/getOptionsFilled.mjs.map +1 -1
- package/dist/config/getOptionsFilled.native.js +25 -2
- package/dist/config/getOptionsFilled.native.js.map +1 -1
- package/dist/config/getServerOptionsFilled.mjs +119 -1
- package/dist/config/getServerOptionsFilled.mjs.map +1 -1
- package/dist/config/getServerOptionsFilled.native.js +137 -1
- package/dist/config/getServerOptionsFilled.native.js.map +1 -1
- package/dist/exports/build.mjs +5 -5
- package/dist/exports/build.mjs.map +1 -1
- package/dist/exports/build.native.js +5 -5
- package/dist/exports/build.native.js.map +1 -1
- package/dist/exports/dev.mjs +4 -6
- package/dist/exports/dev.mjs.map +1 -1
- package/dist/exports/dev.native.js +6 -6
- package/dist/exports/dev.native.js.map +1 -1
- package/dist/exports/prebuild.mjs +4 -4
- package/dist/exports/prebuild.mjs.map +1 -1
- package/dist/exports/prebuild.native.js +4 -4
- package/dist/exports/prebuild.native.js.map +1 -1
- package/dist/exports/prebuildWithoutExpo.mjs +95 -88
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +95 -88
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.mjs +3 -3
- package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.native.js +3 -3
- package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.mjs +4 -4
- package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.native.js +4 -4
- package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.mjs +18 -5
- package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.native.js +18 -5
- package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
- package/dist/user-interface/index.mjs +1 -1
- package/dist/user-interface/index.mjs.map +1 -1
- package/dist/user-interface/index.native.js +1 -1
- package/dist/user-interface/index.native.js.map +1 -1
- package/dist/utils/env-editor.mjs +198 -0
- package/dist/utils/env-editor.mjs.map +1 -0
- package/dist/utils/env-editor.native.js +266 -0
- package/dist/utils/env-editor.native.js.map +1 -0
- package/dist/utils/fs.mjs +48 -0
- package/dist/utils/fs.mjs.map +1 -0
- package/dist/utils/fs.native.js +48 -0
- package/dist/utils/fs.native.js.map +1 -0
- package/dist/utils/getVitePath.mjs +2 -2
- package/dist/utils/getVitePath.mjs.map +1 -1
- package/dist/utils/getVitePath.native.js +2 -2
- package/dist/utils/getVitePath.native.js.map +1 -1
- package/dist/utils/patches.mjs +38 -29
- package/dist/utils/patches.mjs.map +1 -1
- package/dist/utils/patches.native.js +38 -29
- package/dist/utils/patches.native.js.map +1 -1
- package/dist/utils/scanDepsToOptimize.mjs +12 -11
- package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
- package/dist/utils/scanDepsToOptimize.native.js +12 -11
- package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
- package/dist/utils/state.mjs +5 -5
- package/dist/utils/state.mjs.map +1 -1
- package/dist/utils/state.native.js +5 -5
- package/dist/utils/state.native.js.map +1 -1
- package/dist/utils/utils.mjs +4 -3
- package/dist/utils/utils.mjs.map +1 -1
- package/dist/utils/utils.native.js +4 -3
- package/dist/utils/utils.native.js.map +1 -1
- package/package.json +12 -18
- package/src/cli.ts +5 -4
- package/src/config/getBaseViteConfigOnly.ts +3 -3
- package/src/config/getOptionsFilled.ts +35 -2
- package/src/config/getServerOptionsFilled.test.ts +37 -0
- package/src/config/getServerOptionsFilled.ts +57 -1
- package/src/exports/build.ts +5 -5
- package/src/exports/clean.test.ts +1 -1
- package/src/exports/dev.ts +5 -6
- package/src/exports/prebuild.ts +4 -4
- package/src/exports/prebuildWithoutExpo.ts +102 -89
- package/src/plugins/autoDepOptimizePlugin.ts +3 -3
- package/src/plugins/reactNativeDevAssetPlugin.ts +4 -4
- package/src/rn-commands/bundle/buildBundle.ts +15 -5
- package/src/user-interface/index.ts +1 -1
- package/src/utils/env-editor.LICENSE +9 -0
- package/src/utils/env-editor.ts +214 -0
- package/src/utils/fs.ts +59 -0
- package/src/utils/getVitePath.ts +2 -2
- package/src/utils/patches.test.ts +36 -36
- package/src/utils/patches.ts +39 -27
- package/src/utils/scanDepsToOptimize.test.ts +2 -2
- package/src/utils/scanDepsToOptimize.ts +6 -5
- package/src/utils/state.ts +5 -7
- package/src/utils/utils.ts +5 -5
- package/types/config/getOptionsFilled.d.ts +9 -2
- package/types/config/getOptionsFilled.d.ts.map +1 -1
- package/types/config/getServerOptionsFilled.d.ts.map +1 -1
- package/types/exports/build.d.ts +1 -1
- package/types/exports/dev.d.ts.map +1 -1
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
- package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
- package/types/user-interface/index.d.ts.map +1 -1
- package/types/utils/env-editor.d.ts +9 -0
- package/types/utils/env-editor.d.ts.map +1 -0
- package/types/utils/fs.d.ts +9 -0
- package/types/utils/fs.d.ts.map +1 -0
- package/types/utils/patches.d.ts.map +1 -1
- package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
- package/types/utils/state.d.ts.map +1 -1
- package/types/utils/utils.d.ts +2 -2
- package/types/utils/utils.d.ts.map +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { readFile } from 'node:fs/promises'
|
|
2
4
|
import { createRequire } from 'node:module'
|
|
3
5
|
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
import { readPackageJSON } from 'pkg-types'
|
|
6
|
+
import { basename, dirname, join, resolve } from 'node:path'
|
|
6
7
|
import type { Mode, VXRNOptions } from '../types'
|
|
7
8
|
import { getServerOptionsFilled } from './getServerOptionsFilled'
|
|
8
9
|
import { readState } from '../utils/state'
|
|
@@ -38,6 +39,14 @@ const require = createRequire(import.meta.url)
|
|
|
38
39
|
* * Over time, we can progressively eliminate dependencies on
|
|
39
40
|
* `VXRNOptionsFilled` across the codebase.
|
|
40
41
|
*/
|
|
42
|
+
export type PackageJSON = {
|
|
43
|
+
name?: string
|
|
44
|
+
version?: string
|
|
45
|
+
dependencies?: Record<string, string>
|
|
46
|
+
devDependencies?: Record<string, string>
|
|
47
|
+
[key: string]: any
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
export type VXRNOptionsFilled = Awaited<ReturnType<typeof fillOptions>>
|
|
42
51
|
|
|
43
52
|
let optionsFilled: VXRNOptionsFilled | null = null
|
|
@@ -115,6 +124,30 @@ export function getOptionsFilled() {
|
|
|
115
124
|
return optionsFilled
|
|
116
125
|
}
|
|
117
126
|
|
|
127
|
+
async function readPackageJSON(cwd = process.cwd()): Promise<PackageJSON> {
|
|
128
|
+
// nearest package.json walking up, stopping above the shallowest
|
|
129
|
+
// node_modules segment, matching the pkg-types lookup this replaces
|
|
130
|
+
let stopDir: string | null = null
|
|
131
|
+
for (let dir = resolve(cwd); ; ) {
|
|
132
|
+
if (basename(dir) === 'node_modules') stopDir = dir
|
|
133
|
+
const parent = dirname(dir)
|
|
134
|
+
if (parent === dir) break
|
|
135
|
+
dir = parent
|
|
136
|
+
}
|
|
137
|
+
let dir = resolve(cwd)
|
|
138
|
+
for (;;) {
|
|
139
|
+
const candidate = join(dir, 'package.json')
|
|
140
|
+
if (existsSync(candidate)) {
|
|
141
|
+
return JSON.parse(await readFile(candidate, 'utf8'))
|
|
142
|
+
}
|
|
143
|
+
if (stopDir && resolve(dir) === stopDir) break
|
|
144
|
+
const parent = dirname(dir)
|
|
145
|
+
if (parent === dir) break
|
|
146
|
+
dir = parent
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`Cannot find matching package.json in ${cwd} or parent directories`)
|
|
149
|
+
}
|
|
150
|
+
|
|
118
151
|
function hashString(str: string): string {
|
|
119
152
|
const hash = createHash('sha256') // Create a hash object with the desired algorithm (e.g., 'sha256')
|
|
120
153
|
hash.update(str) // Update the hash content with the input string
|
|
@@ -1,6 +1,22 @@
|
|
|
1
|
+
import { createServer } from 'node:net'
|
|
1
2
|
import { describe, expect, test } from 'vitest'
|
|
2
3
|
import { getServerOptionsFilled } from './getServerOptionsFilled'
|
|
3
4
|
|
|
5
|
+
async function occupyPort(): Promise<{ port: number; close: () => Promise<void> }> {
|
|
6
|
+
const server = createServer()
|
|
7
|
+
await new Promise<void>((resolve) => {
|
|
8
|
+
server.listen({ port: 0, host: '0.0.0.0' }, () => resolve())
|
|
9
|
+
})
|
|
10
|
+
const port = (server.address() as { port: number }).port
|
|
11
|
+
return {
|
|
12
|
+
port,
|
|
13
|
+
close: () =>
|
|
14
|
+
new Promise<void>((resolve, reject) => {
|
|
15
|
+
server.close((err) => (err ? reject(err) : resolve()))
|
|
16
|
+
}),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
4
20
|
describe('getServerOptionsFilled', () => {
|
|
5
21
|
test('uses the configured TLS protocol in the public server URL', async () => {
|
|
6
22
|
const server = await getServerOptionsFilled(
|
|
@@ -21,4 +37,25 @@ describe('getServerOptionsFilled', () => {
|
|
|
21
37
|
key: 'private-key',
|
|
22
38
|
})
|
|
23
39
|
})
|
|
40
|
+
|
|
41
|
+
test('resolves an explicitly requested free port', async () => {
|
|
42
|
+
const occupied = await occupyPort()
|
|
43
|
+
const port = occupied.port
|
|
44
|
+
await occupied.close()
|
|
45
|
+
|
|
46
|
+
const server = await getServerOptionsFilled({ port }, 'dev')
|
|
47
|
+
|
|
48
|
+
expect(server.port).toBe(port)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('rejects an explicitly requested port that is already in use', async () => {
|
|
52
|
+
const occupied = await occupyPort()
|
|
53
|
+
try {
|
|
54
|
+
await expect(getServerOptionsFilled({ port: occupied.port }, 'dev')).rejects.toThrow(
|
|
55
|
+
`Port ${occupied.port} is already in use`
|
|
56
|
+
)
|
|
57
|
+
} finally {
|
|
58
|
+
await occupied.close()
|
|
59
|
+
}
|
|
60
|
+
})
|
|
24
61
|
})
|
|
@@ -1,6 +1,62 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createServer } from 'node:net'
|
|
2
2
|
import type { Mode, VXRNOptions, VXRNServeOptionsFilled } from '../types'
|
|
3
3
|
|
|
4
|
+
// ports browsers refuse to connect to, so binding one would serve nothing.
|
|
5
|
+
// same list get-port-please filters; vxrn's default ranges never hit it.
|
|
6
|
+
const UNSAFE_PORTS = new Set([
|
|
7
|
+
1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79, 87,
|
|
8
|
+
95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137, 139,
|
|
9
|
+
143, 161, 179, 389, 427, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540, 548,
|
|
10
|
+
554, 556, 563, 587, 601, 636, 989, 990, 993, 995, 1719, 1720, 1723, 2049, 3659,
|
|
11
|
+
4045, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668, 6669, 6697, 10080,
|
|
12
|
+
])
|
|
13
|
+
|
|
14
|
+
const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(?<!-)$/
|
|
15
|
+
|
|
16
|
+
function tryPort(port: number, host: string | undefined): Promise<number | false> {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
const server = createServer()
|
|
19
|
+
server.unref()
|
|
20
|
+
server.on('error', () => {
|
|
21
|
+
resolve(false)
|
|
22
|
+
})
|
|
23
|
+
server.listen({ port, host }, () => {
|
|
24
|
+
const bound = (server.address() as { port: number }).port
|
|
25
|
+
server.close(() => {
|
|
26
|
+
resolve(!UNSAFE_PORTS.has(bound) && bound)
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function getPort({
|
|
33
|
+
port,
|
|
34
|
+
portRange,
|
|
35
|
+
host,
|
|
36
|
+
}: {
|
|
37
|
+
port: number
|
|
38
|
+
portRange: [number, number]
|
|
39
|
+
host: string | undefined
|
|
40
|
+
}): Promise<number> {
|
|
41
|
+
if (host && !HOSTNAME_RE.test(host)) {
|
|
42
|
+
host = '127.0.0.1'
|
|
43
|
+
}
|
|
44
|
+
const ports = [port]
|
|
45
|
+
for (let p = portRange[0]; p <= portRange[1]; p++) {
|
|
46
|
+
ports.push(p)
|
|
47
|
+
}
|
|
48
|
+
for (const p of ports) {
|
|
49
|
+
if (!p || UNSAFE_PORTS.has(p)) continue
|
|
50
|
+
const found = await tryPort(p, host)
|
|
51
|
+
if (found) return found
|
|
52
|
+
}
|
|
53
|
+
const random = await tryPort(0, host)
|
|
54
|
+
if (random) return random
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Unable to find an available port ${host ? `on host ${JSON.stringify(host)}` : 'on any host'} (tried ${portRange.join('-')})`
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
4
60
|
export async function getServerOptionsFilled(
|
|
5
61
|
serverOptions: VXRNOptions['server'],
|
|
6
62
|
mode: Mode
|
package/src/exports/build.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { rm } from 'node:fs/promises'
|
|
1
|
+
import { readFile, rm, writeFile } from 'node:fs/promises'
|
|
3
2
|
import { sep } from 'node:path'
|
|
3
|
+
import { readJSON } from '../utils/fs'
|
|
4
4
|
import type { OutputAsset, OutputChunk, RolldownOutput } from 'rolldown'
|
|
5
5
|
import {
|
|
6
6
|
loadConfigFromFile,
|
|
@@ -355,11 +355,11 @@ export const build = async (optionsIn: VXRNOptions, buildArgs: BuildArgs = {}) =
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
if (serverOptions !== false) {
|
|
358
|
-
clientManifest = await
|
|
358
|
+
clientManifest = await readJSON(`${outDir}/client/.vite/manifest.json`)
|
|
359
359
|
|
|
360
360
|
// temp fix - react native web is importing non-existent react 19 apis
|
|
361
|
-
const old = await
|
|
362
|
-
await
|
|
361
|
+
const old = await readFile(serverEntry, 'utf-8')
|
|
362
|
+
await writeFile(
|
|
363
363
|
serverEntry,
|
|
364
364
|
old
|
|
365
365
|
.replace(
|
|
@@ -107,7 +107,7 @@ async function tryConnect(port: number): Promise<Socket | undefined> {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
// outermost node_modules above the test, so a bundled worker's bare
|
|
110
|
-
// imports (vite,
|
|
110
|
+
// imports (vite, picocolors, ...) resolve the way the workspace lays out
|
|
111
111
|
function outermostNodeModules(from: string): string {
|
|
112
112
|
let dir = from
|
|
113
113
|
let found: string | undefined
|
package/src/exports/dev.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process'
|
|
2
|
-
import
|
|
2
|
+
import { mkdir } from 'node:fs/promises'
|
|
3
3
|
import colors from 'picocolors'
|
|
4
4
|
import { debounce } from 'perfect-debounce'
|
|
5
5
|
import { normalizePath, type PluginOption, type ViteDevServer } from 'vite'
|
|
6
6
|
import type { VXRNOptions } from '../types'
|
|
7
7
|
|
|
8
|
-
const {
|
|
8
|
+
const ensureDir = (dir: string) => mkdir(dir, { recursive: true })
|
|
9
9
|
|
|
10
10
|
function readParentPid(pid: number): number | undefined {
|
|
11
11
|
try {
|
|
@@ -31,19 +31,18 @@ function processExists(pid: number): boolean {
|
|
|
31
31
|
|
|
32
32
|
// Exit if we become orphaned (parent dies). `bun run` stays between One and
|
|
33
33
|
// its launcher, so monitor the launcher's PID too instead of only Bun's PID.
|
|
34
|
+
// PID 1 is a live container or machine init, not a dead parent.
|
|
34
35
|
function setupOrphanDetection() {
|
|
35
36
|
if (process.platform === 'win32') return
|
|
36
37
|
|
|
37
38
|
const initialPpid = process.ppid
|
|
38
39
|
const launcherPid = readParentPid(initialPpid)
|
|
39
|
-
|
|
40
|
-
process.exit(0)
|
|
41
|
-
}
|
|
40
|
+
const watchedLauncher = launcherPid !== undefined && launcherPid > 1 ? launcherPid : undefined
|
|
42
41
|
|
|
43
42
|
const interval = setInterval(() => {
|
|
44
43
|
if (
|
|
45
44
|
process.ppid !== initialPpid ||
|
|
46
|
-
(
|
|
45
|
+
(watchedLauncher !== undefined && !processExists(watchedLauncher))
|
|
47
46
|
) {
|
|
48
47
|
process.exit(0)
|
|
49
48
|
}
|
package/src/exports/prebuild.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { detectPackageManager, type PackageManagerName } from '@vxrn/utils'
|
|
2
|
-
import
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import { fillOptions } from '../config/getOptionsFilled'
|
|
5
5
|
import { applyBuiltInPatches } from '../utils/patches'
|
|
@@ -38,7 +38,7 @@ export const prebuild = async ({
|
|
|
38
38
|
|
|
39
39
|
try {
|
|
40
40
|
const packageJsonPath = path.join(root, 'package.json')
|
|
41
|
-
const packageJsonContents = await
|
|
41
|
+
const packageJsonContents = await readFile(packageJsonPath, 'utf8')
|
|
42
42
|
const { devDependencies } = JSON.parse(packageJsonContents)
|
|
43
43
|
if (!devDependencies?.['@react-native-community/template']) {
|
|
44
44
|
const installCommand: `${PackageManagerName} ${'add' | 'install'} ${'-D'} ${'@react-native-community/template'}` =
|
|
@@ -126,9 +126,9 @@ export async function replaceInUTF8File(
|
|
|
126
126
|
findThis: string,
|
|
127
127
|
replaceWith: string
|
|
128
128
|
) {
|
|
129
|
-
const fileContent = await
|
|
129
|
+
const fileContent = await readFile(filePath, 'utf8')
|
|
130
130
|
const replacedFileContent = fileContent.replace(findThis, replaceWith)
|
|
131
131
|
if (replacedFileContent !== fileContent) {
|
|
132
|
-
await
|
|
132
|
+
await writeFile(filePath, replacedFileContent, 'utf8')
|
|
133
133
|
}
|
|
134
134
|
}
|