rnxsim 0.1.427 → 0.1.428
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/cli/commands/control.ts +17 -1
- package/cli/commands/flow.ts +5 -9
- package/cli/commands/inspect/core.ts +1 -0
- package/cli/outbound-endpoints.ts +5 -2
- package/cli/self-invocation.ts +24 -0
- package/detox/index.ts +10 -36
- package/dist-lib/agent-daemon-client.cjs +48 -24
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +100 -76
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +2 -25
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +324 -218
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +162 -78
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +43 -24
- package/dist-lib/metro-production-bundle.mjs +43 -24
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +452 -336
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/host/websocket-proxy.ts +197 -92
- package/src/metro-production-bundle.ts +55 -30
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.428 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/package.json
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import { createHash } from 'crypto'
|
|
2
|
+
import { request as requestHttp, type IncomingMessage } from 'http'
|
|
3
|
+
import { request as requestHttps } from 'https'
|
|
3
4
|
import type { Duplex } from 'stream'
|
|
4
5
|
|
|
5
6
|
export const WEBSOCKET_PROXY_PATH = '/__websocket-proxy'
|
|
7
|
+
export const WEBSOCKET_PROXY_HANDSHAKE_TIMEOUT_MS = 10_000
|
|
8
|
+
|
|
9
|
+
const WEBSOCKET_PROTOCOL_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
|
|
10
|
+
const WEBSOCKET_KEY = /^[+/0-9A-Za-z]{22}==$/
|
|
11
|
+
|
|
12
|
+
type UpgradeRejection = {
|
|
13
|
+
status: number
|
|
14
|
+
message: string
|
|
15
|
+
headers?: Record<string, string>
|
|
16
|
+
}
|
|
6
17
|
|
|
7
18
|
const STRIP_UPSTREAM_HEADERS = new Set([
|
|
8
19
|
'host',
|
|
@@ -17,15 +28,74 @@ const STRIP_UPSTREAM_HEADERS = new Set([
|
|
|
17
28
|
'sec-websocket-version',
|
|
18
29
|
])
|
|
19
30
|
|
|
20
|
-
function rejectUpgrade(
|
|
31
|
+
function rejectUpgrade(
|
|
32
|
+
socket: Duplex,
|
|
33
|
+
status: number,
|
|
34
|
+
message: string,
|
|
35
|
+
headers: Record<string, string> = {},
|
|
36
|
+
) {
|
|
21
37
|
try {
|
|
38
|
+
const extraHeaders = Object.entries(headers)
|
|
39
|
+
.map(([name, value]) => `${name}: ${value}\r\n`)
|
|
40
|
+
.join('')
|
|
22
41
|
socket.write(
|
|
23
|
-
`HTTP/1.1 ${status} ${message}\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: ${message.length}\r\n\r\n${message}`,
|
|
42
|
+
`HTTP/1.1 ${status} ${message}\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: ${message.length}\r\n${extraHeaders}\r\n${message}`,
|
|
24
43
|
)
|
|
25
44
|
} catch {}
|
|
26
45
|
socket.destroy()
|
|
27
46
|
}
|
|
28
47
|
|
|
48
|
+
function hasHeaderToken(value: string | undefined, token: string): boolean {
|
|
49
|
+
return (value || '').split(',').some((part) => part.trim().toLowerCase() === token)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function hasValidProtocolOffer(value: string | undefined): boolean {
|
|
53
|
+
if (value === undefined) return true
|
|
54
|
+
if (!WEBSOCKET_PROTOCOL_TOKEN.test(value[0] || '')) return false
|
|
55
|
+
if (!WEBSOCKET_PROTOCOL_TOKEN.test(value[value.length - 1] || '')) return false
|
|
56
|
+
const protocols = new Set<string>()
|
|
57
|
+
for (const part of value.split(',')) {
|
|
58
|
+
const protocol = part.trim()
|
|
59
|
+
if (!WEBSOCKET_PROTOCOL_TOKEN.test(protocol) || protocols.has(protocol)) {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
protocols.add(protocol)
|
|
63
|
+
}
|
|
64
|
+
return true
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function validateUpgradeRequest(req: IncomingMessage): UpgradeRejection | null {
|
|
68
|
+
if (req.method !== 'GET') {
|
|
69
|
+
return { status: 405, message: 'invalid websocket http method' }
|
|
70
|
+
}
|
|
71
|
+
if (
|
|
72
|
+
!hasHeaderToken(req.headers.connection, 'upgrade') ||
|
|
73
|
+
!hasHeaderToken(req.headers.upgrade, 'websocket')
|
|
74
|
+
) {
|
|
75
|
+
return { status: 400, message: 'invalid websocket upgrade headers' }
|
|
76
|
+
}
|
|
77
|
+
const key = req.headers['sec-websocket-key']
|
|
78
|
+
if (
|
|
79
|
+
typeof key !== 'string' ||
|
|
80
|
+
!WEBSOCKET_KEY.test(key) ||
|
|
81
|
+
Buffer.from(key, 'base64').byteLength !== 16 ||
|
|
82
|
+
Buffer.from(key, 'base64').toString('base64') !== key
|
|
83
|
+
) {
|
|
84
|
+
return { status: 400, message: 'invalid websocket key' }
|
|
85
|
+
}
|
|
86
|
+
if (req.headers['sec-websocket-version'] !== '13') {
|
|
87
|
+
return {
|
|
88
|
+
status: 400,
|
|
89
|
+
message: 'invalid websocket version',
|
|
90
|
+
headers: { 'Sec-WebSocket-Version': '13' },
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!hasValidProtocolOffer(req.headers['sec-websocket-protocol'])) {
|
|
94
|
+
return { status: 400, message: 'invalid websocket protocol offer' }
|
|
95
|
+
}
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
29
99
|
function isSameOriginUpgrade(req: IncomingMessage): boolean {
|
|
30
100
|
const origin = req.headers.origin
|
|
31
101
|
const host = req.headers.host
|
|
@@ -58,66 +128,12 @@ function getDefaultWebSocketOrigin(targetUrl: URL): string {
|
|
|
58
128
|
return origin.origin
|
|
59
129
|
}
|
|
60
130
|
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
const value = Array.isArray(header) ? header.join(',') : header || ''
|
|
64
|
-
return value
|
|
65
|
-
.split(',')
|
|
66
|
-
.map((part) => part.trim())
|
|
67
|
-
.filter(Boolean)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function safeClose(ws: WebSocket, code: number, reason: string) {
|
|
71
|
-
if (ws.readyState === WebSocket.CLOSED || ws.readyState === WebSocket.CLOSING) {
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
ws.close(code, reason)
|
|
76
|
-
} catch {
|
|
77
|
-
ws.terminate()
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function connectProxyPair(clientWs: WebSocket, upstream: WebSocket) {
|
|
82
|
-
let closing = false
|
|
83
|
-
|
|
84
|
-
const closeBoth = (
|
|
85
|
-
source: WebSocket,
|
|
86
|
-
target: WebSocket,
|
|
87
|
-
code: number,
|
|
88
|
-
reason: Buffer,
|
|
89
|
-
) => {
|
|
90
|
-
if (closing) return
|
|
91
|
-
closing = true
|
|
92
|
-
safeClose(target, code, reason.toString())
|
|
93
|
-
if (source.readyState === WebSocket.OPEN) {
|
|
94
|
-
safeClose(source, code, reason.toString())
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
clientWs.on('message', (data, isBinary) => {
|
|
99
|
-
if (upstream.readyState === WebSocket.OPEN) {
|
|
100
|
-
upstream.send(data, { binary: isBinary })
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
upstream.on('message', (data, isBinary) => {
|
|
104
|
-
if (clientWs.readyState === WebSocket.OPEN) {
|
|
105
|
-
clientWs.send(data, { binary: isBinary })
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
clientWs.on('close', (code, reason) => closeBoth(clientWs, upstream, code, reason))
|
|
110
|
-
upstream.on('close', (code, reason) => closeBoth(upstream, clientWs, code, reason))
|
|
111
|
-
clientWs.on('error', () => safeClose(upstream, 1011, 'proxy client error'))
|
|
112
|
-
upstream.on('error', () => safeClose(clientWs, 1011, 'upstream websocket error'))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function createUpstreamWebSocket(
|
|
131
|
+
function createUpstreamHeaders(
|
|
132
|
+
req: IncomingMessage,
|
|
116
133
|
targetUrl: URL,
|
|
117
|
-
protocols: string[],
|
|
118
134
|
headers: Record<string, string>,
|
|
119
135
|
forwardOrigin: boolean,
|
|
120
|
-
):
|
|
136
|
+
): Record<string, string> {
|
|
121
137
|
const upstreamHeaders = { ...headers }
|
|
122
138
|
const originKeys = Object.keys(upstreamHeaders).filter(
|
|
123
139
|
(key) => key.toLowerCase() === 'origin',
|
|
@@ -127,11 +143,19 @@ function createUpstreamWebSocket(
|
|
|
127
143
|
} else if (!forwardOrigin) {
|
|
128
144
|
for (const key of originKeys) delete upstreamHeaders[key]
|
|
129
145
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
upstreamHeaders.connection = 'Upgrade'
|
|
147
|
+
upstreamHeaders.upgrade = 'websocket'
|
|
148
|
+
const key = req.headers['sec-websocket-key']
|
|
149
|
+
if (typeof key === 'string') upstreamHeaders['sec-websocket-key'] = key
|
|
150
|
+
const version = req.headers['sec-websocket-version']
|
|
151
|
+
if (typeof version === 'string') upstreamHeaders['sec-websocket-version'] = version
|
|
152
|
+
const protocol = req.headers['sec-websocket-protocol']
|
|
153
|
+
if (typeof protocol === 'string') upstreamHeaders['sec-websocket-protocol'] = protocol
|
|
154
|
+
const extensions = req.headers['sec-websocket-extensions']
|
|
155
|
+
if (typeof extensions === 'string') {
|
|
156
|
+
upstreamHeaders['sec-websocket-extensions'] = extensions
|
|
157
|
+
}
|
|
158
|
+
return upstreamHeaders
|
|
135
159
|
}
|
|
136
160
|
|
|
137
161
|
export function isWebSocketProxyRequestUrl(rawUrl: string | undefined): boolean {
|
|
@@ -154,6 +178,16 @@ export function handleWebSocketProxyUpgrade(
|
|
|
154
178
|
rejectUpgrade(socket, 403, 'forbidden websocket proxy origin')
|
|
155
179
|
return true
|
|
156
180
|
}
|
|
181
|
+
const upgradeRejection = validateUpgradeRequest(req)
|
|
182
|
+
if (upgradeRejection) {
|
|
183
|
+
rejectUpgrade(
|
|
184
|
+
socket,
|
|
185
|
+
upgradeRejection.status,
|
|
186
|
+
upgradeRejection.message,
|
|
187
|
+
upgradeRejection.headers,
|
|
188
|
+
)
|
|
189
|
+
return true
|
|
190
|
+
}
|
|
157
191
|
|
|
158
192
|
let targetUrl: URL
|
|
159
193
|
let headers: Record<string, string>
|
|
@@ -175,36 +209,107 @@ export function handleWebSocketProxyUpgrade(
|
|
|
175
209
|
return true
|
|
176
210
|
}
|
|
177
211
|
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
212
|
+
const upstreamHeaders = createUpstreamHeaders(req, targetUrl, headers, forwardOrigin)
|
|
213
|
+
let settled = false
|
|
214
|
+
const request = targetUrl.protocol === 'wss:' ? requestHttps : requestHttp
|
|
215
|
+
const upstreamRequestUrl = new URL(targetUrl)
|
|
216
|
+
upstreamRequestUrl.protocol = targetUrl.protocol === 'wss:' ? 'https:' : 'http:'
|
|
217
|
+
const upstreamRequest = request(upstreamRequestUrl, {
|
|
218
|
+
method: 'GET',
|
|
219
|
+
headers: upstreamHeaders,
|
|
220
|
+
})
|
|
221
|
+
let destroyUpstreamSocket = () => {}
|
|
222
|
+
upstreamRequest.once('socket', (upstreamSocket) => {
|
|
223
|
+
destroyUpstreamSocket = () => upstreamSocket.destroy()
|
|
224
|
+
})
|
|
225
|
+
const fail = (status: number, message: string) => {
|
|
226
|
+
if (settled) return
|
|
227
|
+
settled = true
|
|
228
|
+
clearTimeout(timer)
|
|
229
|
+
upstreamRequest.destroy()
|
|
230
|
+
destroyUpstreamSocket()
|
|
231
|
+
rejectUpgrade(socket, status, message)
|
|
232
|
+
}
|
|
233
|
+
const timer = setTimeout(() => {
|
|
234
|
+
fail(504, 'upstream websocket handshake timeout')
|
|
235
|
+
}, WEBSOCKET_PROXY_HANDSHAKE_TIMEOUT_MS)
|
|
181
236
|
socket.once('close', () => {
|
|
182
|
-
if (!
|
|
237
|
+
if (!settled) {
|
|
238
|
+
settled = true
|
|
239
|
+
clearTimeout(timer)
|
|
240
|
+
}
|
|
241
|
+
upstreamRequest.destroy()
|
|
242
|
+
destroyUpstreamSocket()
|
|
183
243
|
})
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const selectedProtocol = upstream.protocol
|
|
188
|
-
const proxyServer = new WebSocketServer({
|
|
189
|
-
noServer: true,
|
|
190
|
-
clientTracking: false,
|
|
191
|
-
handleProtocols(requestedProtocols) {
|
|
192
|
-
return selectedProtocol || requestedProtocols.values().next().value || false
|
|
193
|
-
},
|
|
194
|
-
})
|
|
195
|
-
proxyServer.handleUpgrade(req, socket, head, (clientWs) => {
|
|
196
|
-
connectProxyPair(clientWs, upstream)
|
|
197
|
-
})
|
|
244
|
+
upstreamRequest.once('response', (response) => {
|
|
245
|
+
response.resume()
|
|
246
|
+
fail(502, 'upstream websocket rejected upgrade')
|
|
198
247
|
})
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
completed = true
|
|
202
|
-
rejectUpgrade(socket, 502, 'upstream websocket error')
|
|
248
|
+
upstreamRequest.once('error', () => {
|
|
249
|
+
fail(502, 'upstream websocket error')
|
|
203
250
|
})
|
|
204
|
-
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
251
|
+
upstreamRequest.once('upgrade', (response, upstreamSocket, upstreamHead) => {
|
|
252
|
+
if (settled) {
|
|
253
|
+
upstreamSocket.destroy()
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
const accept = response.headers['sec-websocket-accept']
|
|
257
|
+
const upgrade = response.headers.upgrade
|
|
258
|
+
const requestKey = req.headers['sec-websocket-key']
|
|
259
|
+
const expectedAccept =
|
|
260
|
+
typeof requestKey === 'string'
|
|
261
|
+
? createHash('sha1')
|
|
262
|
+
.update(`${requestKey}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
|
|
263
|
+
.digest('base64')
|
|
264
|
+
: ''
|
|
265
|
+
if (
|
|
266
|
+
typeof accept !== 'string' ||
|
|
267
|
+
accept !== expectedAccept ||
|
|
268
|
+
typeof upgrade !== 'string' ||
|
|
269
|
+
upgrade.toLowerCase() !== 'websocket'
|
|
270
|
+
) {
|
|
271
|
+
upstreamSocket.destroy()
|
|
272
|
+
fail(502, 'upstream websocket handshake is invalid')
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
const selectedProtocol = response.headers['sec-websocket-protocol']
|
|
276
|
+
const requestedProtocols = (req.headers['sec-websocket-protocol'] || '')
|
|
277
|
+
.split(',')
|
|
278
|
+
.map((protocol) => protocol.trim())
|
|
279
|
+
if (
|
|
280
|
+
typeof selectedProtocol === 'string' &&
|
|
281
|
+
!requestedProtocols.includes(selectedProtocol)
|
|
282
|
+
) {
|
|
283
|
+
upstreamSocket.destroy()
|
|
284
|
+
fail(502, 'upstream websocket selected an unrequested protocol')
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
settled = true
|
|
288
|
+
clearTimeout(timer)
|
|
289
|
+
const responseHeaders = [
|
|
290
|
+
'HTTP/1.1 101 Switching Protocols',
|
|
291
|
+
'Upgrade: websocket',
|
|
292
|
+
'Connection: Upgrade',
|
|
293
|
+
`Sec-WebSocket-Accept: ${accept}`,
|
|
294
|
+
]
|
|
295
|
+
if (typeof selectedProtocol === 'string') {
|
|
296
|
+
responseHeaders.push(`Sec-WebSocket-Protocol: ${selectedProtocol}`)
|
|
297
|
+
}
|
|
298
|
+
const selectedExtensions = response.headers['sec-websocket-extensions']
|
|
299
|
+
if (typeof selectedExtensions === 'string') {
|
|
300
|
+
responseHeaders.push(`Sec-WebSocket-Extensions: ${selectedExtensions}`)
|
|
301
|
+
}
|
|
302
|
+
// the upstream and browser used the same websocket key and extension offer,
|
|
303
|
+
// so their negotiated byte streams can be relayed without decoding frames.
|
|
304
|
+
socket.write(`${responseHeaders.join('\r\n')}\r\n\r\n`)
|
|
305
|
+
if (head.length > 0) upstreamSocket.write(head)
|
|
306
|
+
if (upstreamHead.length > 0) socket.write(upstreamHead)
|
|
307
|
+
socket.once('close', () => upstreamSocket.destroy())
|
|
308
|
+
socket.once('error', () => upstreamSocket.destroy())
|
|
309
|
+
upstreamSocket.once('error', () => socket.destroy())
|
|
310
|
+
socket.pipe(upstreamSocket)
|
|
311
|
+
upstreamSocket.pipe(socket)
|
|
208
312
|
})
|
|
313
|
+
upstreamRequest.end()
|
|
209
314
|
return true
|
|
210
315
|
}
|
|
@@ -130,11 +130,34 @@ export function readRNXMetroModuleIdentity(
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
const version = Reflect.get(parsed, 'version')
|
|
133
|
-
// stored artifacts from before the versioned footer carry a bare
|
|
134
|
-
// map with no
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
133
|
+
// stored artifacts from before the versioned footer carry a bare
|
|
134
|
+
// `{"<moduleId>":"<path>", ...}` map with no wrapper — the exact shape
|
|
135
|
+
// appendRNXModulePaths wrote before the footer was versioned, and the only
|
|
136
|
+
// writer of that shape used identitySource 'rnx-plugin'. normalize it into
|
|
137
|
+
// the current in-memory identity so callers get the same exact modulePaths
|
|
138
|
+
// map instead of falling back to name-scanning or fingerprint inference.
|
|
139
|
+
// validateRNXMetroModuleIdentity still detects a missing, extra, duplicate,
|
|
140
|
+
// or truncated module ID against the bundle's own __d() defines, so those
|
|
141
|
+
// legacy-map corruptions are caught there, not trusted here — it does not
|
|
142
|
+
// corroborate that a path or factory is itself correct.
|
|
143
|
+
if (version === undefined) {
|
|
144
|
+
const modulePaths: RNXMetroModulePathMap = Object.fromEntries(
|
|
145
|
+
Object.entries(parsed).map(([moduleId, modulePath]) => {
|
|
146
|
+
if (typeof modulePath !== 'string') {
|
|
147
|
+
throw new Error(`Metro module identity has an invalid path for ${moduleId}`)
|
|
148
|
+
}
|
|
149
|
+
return [moduleId, modulePath]
|
|
150
|
+
}),
|
|
151
|
+
)
|
|
152
|
+
return {
|
|
153
|
+
source: withoutMap.slice(0, footerStart),
|
|
154
|
+
version: RNX_METRO_MODULE_IDENTITY_VERSION,
|
|
155
|
+
identitySource: 'rnx-plugin',
|
|
156
|
+
modulePaths,
|
|
157
|
+
logicalSpecifiers: {},
|
|
158
|
+
sourceMappingUrl: detached.sourceMappingUrl,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
138
161
|
const identitySource = Reflect.get(parsed, 'identitySource')
|
|
139
162
|
const parsedModulePaths = Reflect.get(parsed, 'modulePaths')
|
|
140
163
|
const parsedLogicalSpecifiers = Reflect.get(parsed, 'logicalSpecifiers')
|
|
@@ -153,32 +176,34 @@ export function readRNXMetroModuleIdentity(
|
|
|
153
176
|
throw new Error('Metro module identity footer is malformed')
|
|
154
177
|
}
|
|
155
178
|
|
|
156
|
-
const modulePaths: RNXMetroModulePathMap =
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
(
|
|
179
|
+
const modulePaths: RNXMetroModulePathMap = Object.fromEntries(
|
|
180
|
+
Object.entries(parsedModulePaths).map(([moduleId, modulePath]) => {
|
|
181
|
+
if (typeof modulePath !== 'string') {
|
|
182
|
+
throw new Error(`Metro module identity has an invalid path for ${moduleId}`)
|
|
183
|
+
}
|
|
184
|
+
return [moduleId, modulePath]
|
|
185
|
+
}),
|
|
186
|
+
)
|
|
187
|
+
const logicalSpecifiers: RNXMetroLogicalSpecifierMap = Object.fromEntries(
|
|
188
|
+
Object.entries(parsedLogicalSpecifiers).map(([moduleId, specifiers]) => {
|
|
189
|
+
if (
|
|
190
|
+
!Array.isArray(specifiers) ||
|
|
191
|
+
specifiers.length === 0 ||
|
|
192
|
+
!specifiers.every(
|
|
193
|
+
(specifier) => typeof specifier === 'string' && specifier.length > 0,
|
|
194
|
+
)
|
|
195
|
+
) {
|
|
196
|
+
throw new Error(`Metro module identity has invalid specifiers for ${moduleId}`)
|
|
197
|
+
}
|
|
198
|
+
const unique = [...new Set(specifiers)].sort((left, right) =>
|
|
199
|
+
left.localeCompare(right),
|
|
170
200
|
)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (unique.length !== specifiers.length) {
|
|
178
|
-
throw new Error(`Metro module identity repeats a specifier for ${moduleId}`)
|
|
179
|
-
}
|
|
180
|
-
logicalSpecifiers[moduleId] = unique
|
|
181
|
-
}
|
|
201
|
+
if (unique.length !== specifiers.length) {
|
|
202
|
+
throw new Error(`Metro module identity repeats a specifier for ${moduleId}`)
|
|
203
|
+
}
|
|
204
|
+
return [moduleId, unique]
|
|
205
|
+
}),
|
|
206
|
+
)
|
|
182
207
|
return {
|
|
183
208
|
source: withoutMap.slice(0, footerStart),
|
|
184
209
|
version,
|