rnxsim 0.1.543 → 0.1.545
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 +8 -2
- package/cli/commands/inspect/wait-selector.ts +12 -2
- package/cli/outbound-endpoints.ts +5 -0
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- 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 +93 -2
- package/dist-lib/capture-contract.mjs +92 -2
- 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 +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +29 -14
- 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 +1 -1
- package/dist-lib/index.cjs +93 -2
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.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 +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- 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 +30 -14
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +30 -15
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +40 -13
- package/src/capture-contract.ts +143 -2
- package/src/index.ts +3 -0
package/dist-lib/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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;
|
|
@@ -49,6 +49,7 @@ __export(src_exports, {
|
|
|
49
49
|
isRnxScreenCapture: () => isRnxScreenCapture,
|
|
50
50
|
jumpToSourceBabelPlugin: () => sootsimJumpToSourceBabelPlugin,
|
|
51
51
|
metroPlugin: () => metro_plugin_default,
|
|
52
|
+
packRnxCaptureRegions: () => packRnxCaptureRegions,
|
|
52
53
|
rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
|
|
53
54
|
rnxPlugin: () => rnxPlugin,
|
|
54
55
|
rnxRasterFrames: () => rnxRasterFrames,
|
|
@@ -3204,6 +3205,95 @@ function rnxCaptureRasterRegions(capture) {
|
|
|
3204
3205
|
return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
|
|
3205
3206
|
});
|
|
3206
3207
|
}
|
|
3208
|
+
function packRnxCaptureRegions(regions, pixelRatio, surface) {
|
|
3209
|
+
const physical = regions.map((region) => {
|
|
3210
|
+
const left = Math.floor(region.frame.x * pixelRatio);
|
|
3211
|
+
const top = Math.floor(region.frame.y * pixelRatio);
|
|
3212
|
+
const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
|
|
3213
|
+
const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
|
|
3214
|
+
if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
|
|
3215
|
+
throw new Error(`capture region ${region.key} is outside the app surface`);
|
|
3216
|
+
}
|
|
3217
|
+
return {
|
|
3218
|
+
key: region.key,
|
|
3219
|
+
nodeId: region.nodeId,
|
|
3220
|
+
frame: {
|
|
3221
|
+
x: left / pixelRatio,
|
|
3222
|
+
y: top / pixelRatio,
|
|
3223
|
+
width: (right - left) / pixelRatio,
|
|
3224
|
+
height: (bottom - top) / pixelRatio
|
|
3225
|
+
},
|
|
3226
|
+
sourceX: left,
|
|
3227
|
+
sourceY: top,
|
|
3228
|
+
pixelWidth: right - left,
|
|
3229
|
+
pixelHeight: bottom - top
|
|
3230
|
+
};
|
|
3231
|
+
});
|
|
3232
|
+
const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
|
|
3233
|
+
const totalArea = physical.reduce(
|
|
3234
|
+
(area, region) => area + region.pixelWidth * region.pixelHeight,
|
|
3235
|
+
0
|
|
3236
|
+
);
|
|
3237
|
+
if (totalArea > 4194304) {
|
|
3238
|
+
throw new Error("capture region pixels exceed the atlas budget");
|
|
3239
|
+
}
|
|
3240
|
+
const candidates = [
|
|
3241
|
+
largestWidth,
|
|
3242
|
+
Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
|
|
3243
|
+
Math.max(largestWidth, surface.pixelWidth),
|
|
3244
|
+
4096
|
|
3245
|
+
];
|
|
3246
|
+
const ordered = [...physical].sort(
|
|
3247
|
+
(left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
|
|
3248
|
+
);
|
|
3249
|
+
let best = null;
|
|
3250
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
3251
|
+
if (candidate > 4096) continue;
|
|
3252
|
+
let x = 0;
|
|
3253
|
+
let y = 0;
|
|
3254
|
+
let rowHeight = 0;
|
|
3255
|
+
let usedWidth = 0;
|
|
3256
|
+
const packed = [];
|
|
3257
|
+
for (const region of ordered) {
|
|
3258
|
+
if (x > 0 && x + region.pixelWidth > candidate) {
|
|
3259
|
+
y += rowHeight;
|
|
3260
|
+
x = 0;
|
|
3261
|
+
rowHeight = 0;
|
|
3262
|
+
}
|
|
3263
|
+
packed.push({ ...region, atlasX: x, atlasY: y });
|
|
3264
|
+
x += region.pixelWidth;
|
|
3265
|
+
rowHeight = Math.max(rowHeight, region.pixelHeight);
|
|
3266
|
+
usedWidth = Math.max(usedWidth, x);
|
|
3267
|
+
}
|
|
3268
|
+
const height2 = y + rowHeight;
|
|
3269
|
+
if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
|
|
3270
|
+
const result = { width: usedWidth, height: height2, regions: packed };
|
|
3271
|
+
if (!best || result.width * result.height < best.width * best.height) best = result;
|
|
3272
|
+
}
|
|
3273
|
+
if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
|
|
3274
|
+
const width = best.width / pixelRatio;
|
|
3275
|
+
const height = best.height / pixelRatio;
|
|
3276
|
+
return {
|
|
3277
|
+
width,
|
|
3278
|
+
height,
|
|
3279
|
+
pixelWidth: best.width,
|
|
3280
|
+
pixelHeight: best.height,
|
|
3281
|
+
regions: best.regions,
|
|
3282
|
+
atlasRegions: best.regions.map((region) => ({
|
|
3283
|
+
key: region.key,
|
|
3284
|
+
nodeId: region.nodeId,
|
|
3285
|
+
frame: region.frame,
|
|
3286
|
+
// a region flush with the far edge is anchored to the logical edge so
|
|
3287
|
+
// its source never runs past the atlas by a rounding hair
|
|
3288
|
+
source: {
|
|
3289
|
+
x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
|
|
3290
|
+
y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
|
|
3291
|
+
width: region.frame.width,
|
|
3292
|
+
height: region.frame.height
|
|
3293
|
+
}
|
|
3294
|
+
}))
|
|
3295
|
+
};
|
|
3296
|
+
}
|
|
3207
3297
|
function captureRecord(value) {
|
|
3208
3298
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3209
3299
|
}
|
|
@@ -3259,7 +3349,7 @@ function isRnxScreenCapture(value) {
|
|
|
3259
3349
|
return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
|
|
3260
3350
|
}
|
|
3261
3351
|
function isRnxCaptureRegionAtlas(value) {
|
|
3262
|
-
if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
|
|
3352
|
+
if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
|
|
3263
3353
|
return false;
|
|
3264
3354
|
}
|
|
3265
3355
|
const scale = value.pixelWidth / value.width;
|
|
@@ -4363,6 +4453,7 @@ function sootsimJumpToSourceBabelPlugin(api, options = {}) {
|
|
|
4363
4453
|
isRnxScreenCapture,
|
|
4364
4454
|
jumpToSourceBabelPlugin,
|
|
4365
4455
|
metroPlugin,
|
|
4456
|
+
packRnxCaptureRegions,
|
|
4366
4457
|
rnxCaptureRasterRegions,
|
|
4367
4458
|
rnxPlugin,
|
|
4368
4459
|
rnxRasterFrames,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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/dist-lib/menu.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/menu.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/metro.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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/dist-lib/profiles.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/render-mode.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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;
|
|
@@ -840,7 +840,7 @@ async function resolveLocalIconPath(hostname, port, rawIcon) {
|
|
|
840
840
|
const res = await httpGet(hostname, port, candidate, "HEAD", ENRICH_TIMEOUT_MS);
|
|
841
841
|
if (res?.statusCode === 200) {
|
|
842
842
|
localIconPathCache.set(port, candidate);
|
|
843
|
-
|
|
843
|
+
invalidatePortCache(port);
|
|
844
844
|
return;
|
|
845
845
|
}
|
|
846
846
|
}
|
|
@@ -973,7 +973,7 @@ async function fetchManifestEnrichment(result, buildIconProxyUrl) {
|
|
|
973
973
|
iconPath: parsed.iconPath,
|
|
974
974
|
bundleId: parsed.bundleId
|
|
975
975
|
});
|
|
976
|
-
|
|
976
|
+
invalidatePortCache(result.port);
|
|
977
977
|
}
|
|
978
978
|
var knownNonPatched = /* @__PURE__ */ new Set();
|
|
979
979
|
var knownNonExpo = /* @__PURE__ */ new Set();
|
|
@@ -1013,16 +1013,19 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
1013
1013
|
const framework = launchUrl.includes(
|
|
1014
1014
|
"/one/metro-entry.bundle"
|
|
1015
1015
|
) ? "one" : "expo";
|
|
1016
|
-
return
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1016
|
+
return enrichWithManifest(
|
|
1017
|
+
applyManifest(
|
|
1018
|
+
{
|
|
1019
|
+
port,
|
|
1020
|
+
framework,
|
|
1021
|
+
bundleUrl: withRuntimeConfig(port, launchUrl, owner.cwd),
|
|
1022
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
|
|
1023
|
+
lastSeen: Date.now(),
|
|
1024
|
+
...owner
|
|
1025
|
+
},
|
|
1026
|
+
manifestRes,
|
|
1027
|
+
buildIconProxyUrl
|
|
1028
|
+
),
|
|
1026
1029
|
buildIconProxyUrl
|
|
1027
1030
|
);
|
|
1028
1031
|
}
|
|
@@ -1101,6 +1104,11 @@ function isSootSimSelfServer(server) {
|
|
|
1101
1104
|
}
|
|
1102
1105
|
var __isSootSimSelfServerForTests = isSootSimSelfServer;
|
|
1103
1106
|
var portCache = /* @__PURE__ */ new Map();
|
|
1107
|
+
var portCacheInvalidatedAt = /* @__PURE__ */ new Map();
|
|
1108
|
+
function invalidatePortCache(port) {
|
|
1109
|
+
portCache.delete(port);
|
|
1110
|
+
portCacheInvalidatedAt.set(port, Date.now());
|
|
1111
|
+
}
|
|
1104
1112
|
var NEGATIVE_CACHE_TTL_MS = 3e4;
|
|
1105
1113
|
var WEAK_RESULT_CACHE_TTL_MS = 1500;
|
|
1106
1114
|
function isWeakCachedResult(result) {
|
|
@@ -1128,6 +1136,7 @@ function __resetScannerCache() {
|
|
|
1128
1136
|
knownOne.clear();
|
|
1129
1137
|
enrichmentCache.clear();
|
|
1130
1138
|
enrichmentInFlight.clear();
|
|
1139
|
+
portCacheInvalidatedAt.clear();
|
|
1131
1140
|
__resetAppSettingsBundleCacheForTests();
|
|
1132
1141
|
}
|
|
1133
1142
|
async function attachAppSettingsBundle(result, projectRoot) {
|
|
@@ -1165,6 +1174,9 @@ async function scanDevServers(opts = {}) {
|
|
|
1165
1174
|
for (const p of [...localIconPathCache.keys()]) {
|
|
1166
1175
|
if (!currentPorts.has(p)) localIconPathCache.delete(p);
|
|
1167
1176
|
}
|
|
1177
|
+
for (const p of [...portCacheInvalidatedAt.keys()]) {
|
|
1178
|
+
if (!currentPorts.has(p)) portCacheInvalidatedAt.delete(p);
|
|
1179
|
+
}
|
|
1168
1180
|
const results = [];
|
|
1169
1181
|
const toProbe = [];
|
|
1170
1182
|
for (const { port, pid } of processes) {
|
|
@@ -1183,12 +1195,16 @@ async function scanDevServers(opts = {}) {
|
|
|
1183
1195
|
toProbe.push({ port, pid });
|
|
1184
1196
|
}
|
|
1185
1197
|
if (toProbe.length > 0) {
|
|
1198
|
+
const scanStartedAt = Date.now();
|
|
1186
1199
|
const probed = await Promise.all(
|
|
1187
1200
|
toProbe.map((p) => probePort(p.port, opts.buildIconProxyUrl, p))
|
|
1188
1201
|
);
|
|
1189
1202
|
probed.forEach((result, i) => {
|
|
1190
1203
|
const { port, pid } = toProbe[i];
|
|
1191
|
-
|
|
1204
|
+
const invalidatedAt = portCacheInvalidatedAt.get(port) ?? 0;
|
|
1205
|
+
if (pid !== 0 && invalidatedAt < scanStartedAt) {
|
|
1206
|
+
portCache.set(port, { pid, result, cachedAt: Date.now() });
|
|
1207
|
+
}
|
|
1192
1208
|
if (result) results.push(result);
|
|
1193
1209
|
});
|
|
1194
1210
|
}
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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;
|
|
@@ -20007,7 +20007,7 @@ async function resolveLocalIconPath(hostname, port, rawIcon) {
|
|
|
20007
20007
|
const res = await httpGet(hostname, port, candidate, "HEAD", ENRICH_TIMEOUT_MS);
|
|
20008
20008
|
if (res?.statusCode === 200) {
|
|
20009
20009
|
localIconPathCache.set(port, candidate);
|
|
20010
|
-
|
|
20010
|
+
invalidatePortCache(port);
|
|
20011
20011
|
return;
|
|
20012
20012
|
}
|
|
20013
20013
|
}
|
|
@@ -20126,7 +20126,7 @@ async function fetchManifestEnrichment(result, buildIconProxyUrl) {
|
|
|
20126
20126
|
iconPath: parsed.iconPath,
|
|
20127
20127
|
bundleId: parsed.bundleId
|
|
20128
20128
|
});
|
|
20129
|
-
|
|
20129
|
+
invalidatePortCache(result.port);
|
|
20130
20130
|
}
|
|
20131
20131
|
async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
20132
20132
|
await loadOptionalDemoApps();
|
|
@@ -20163,16 +20163,19 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
20163
20163
|
const framework = launchUrl2.includes(
|
|
20164
20164
|
"/one/metro-entry.bundle"
|
|
20165
20165
|
) ? "one" : "expo";
|
|
20166
|
-
return
|
|
20167
|
-
|
|
20168
|
-
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20166
|
+
return enrichWithManifest(
|
|
20167
|
+
applyManifest(
|
|
20168
|
+
{
|
|
20169
|
+
port,
|
|
20170
|
+
framework,
|
|
20171
|
+
bundleUrl: withRuntimeConfig(port, launchUrl2, owner.cwd),
|
|
20172
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
|
|
20173
|
+
lastSeen: Date.now(),
|
|
20174
|
+
...owner
|
|
20175
|
+
},
|
|
20176
|
+
manifestRes,
|
|
20177
|
+
buildIconProxyUrl
|
|
20178
|
+
),
|
|
20176
20179
|
buildIconProxyUrl
|
|
20177
20180
|
);
|
|
20178
20181
|
}
|
|
@@ -20249,6 +20252,10 @@ function isSootSimSelfServer(server) {
|
|
|
20249
20252
|
if (bundleId?.startsWith("dev.sootsim.")) return true;
|
|
20250
20253
|
return false;
|
|
20251
20254
|
}
|
|
20255
|
+
function invalidatePortCache(port) {
|
|
20256
|
+
portCache.delete(port);
|
|
20257
|
+
portCacheInvalidatedAt.set(port, Date.now());
|
|
20258
|
+
}
|
|
20252
20259
|
function isWeakCachedResult(result) {
|
|
20253
20260
|
if (!result) return true;
|
|
20254
20261
|
if (result.framework === "metro" || result.framework === "unknown") return true;
|
|
@@ -20301,6 +20308,9 @@ async function scanDevServers(opts = {}) {
|
|
|
20301
20308
|
for (const p of [...localIconPathCache.keys()]) {
|
|
20302
20309
|
if (!currentPorts.has(p)) localIconPathCache.delete(p);
|
|
20303
20310
|
}
|
|
20311
|
+
for (const p of [...portCacheInvalidatedAt.keys()]) {
|
|
20312
|
+
if (!currentPorts.has(p)) portCacheInvalidatedAt.delete(p);
|
|
20313
|
+
}
|
|
20304
20314
|
const results = [];
|
|
20305
20315
|
const toProbe = [];
|
|
20306
20316
|
for (const { port, pid } of processes) {
|
|
@@ -20319,12 +20329,16 @@ async function scanDevServers(opts = {}) {
|
|
|
20319
20329
|
toProbe.push({ port, pid });
|
|
20320
20330
|
}
|
|
20321
20331
|
if (toProbe.length > 0) {
|
|
20332
|
+
const scanStartedAt = Date.now();
|
|
20322
20333
|
const probed = await Promise.all(
|
|
20323
20334
|
toProbe.map((p) => probePort(p.port, opts.buildIconProxyUrl, p))
|
|
20324
20335
|
);
|
|
20325
20336
|
probed.forEach((result, i) => {
|
|
20326
20337
|
const { port, pid } = toProbe[i];
|
|
20327
|
-
|
|
20338
|
+
const invalidatedAt = portCacheInvalidatedAt.get(port) ?? 0;
|
|
20339
|
+
if (pid !== 0 && invalidatedAt < scanStartedAt) {
|
|
20340
|
+
portCache.set(port, { pid, result, cachedAt: Date.now() });
|
|
20341
|
+
}
|
|
20328
20342
|
if (result) results.push(result);
|
|
20329
20343
|
});
|
|
20330
20344
|
}
|
|
@@ -20349,7 +20363,7 @@ async function scanDevServers(opts = {}) {
|
|
|
20349
20363
|
}
|
|
20350
20364
|
return results.filter((r) => !isSootSimSelfServer(r));
|
|
20351
20365
|
}
|
|
20352
|
-
var import_child_process, import_promises2, import_http, import_net, import_node_fs2, import_node_path3, EXEC_EXIT_GRACE_MS, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, BODY_TIMEOUT_MS, FALLBACK_PORTS, SELF_PORT_RANGE_START, SELF_PORT_RANGE_END, DevServerScanUnavailableError, LISTING_TIMEOUT_MS, cwdByPid, localIconPathCache, localIconProbeInFlight, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
20366
|
+
var import_child_process, import_promises2, import_http, import_net, import_node_fs2, import_node_path3, EXEC_EXIT_GRACE_MS, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, BODY_TIMEOUT_MS, FALLBACK_PORTS, SELF_PORT_RANGE_START, SELF_PORT_RANGE_END, DevServerScanUnavailableError, LISTING_TIMEOUT_MS, cwdByPid, localIconPathCache, localIconProbeInFlight, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, portCacheInvalidatedAt, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
20353
20367
|
var init_dev_server_scanner = __esm({
|
|
20354
20368
|
"scripts/dev-server-scanner.ts"() {
|
|
20355
20369
|
"use strict";
|
|
@@ -20399,6 +20413,7 @@ var init_dev_server_scanner = __esm({
|
|
|
20399
20413
|
knownNonExpo = /* @__PURE__ */ new Set();
|
|
20400
20414
|
knownOne = /* @__PURE__ */ new Set();
|
|
20401
20415
|
portCache = /* @__PURE__ */ new Map();
|
|
20416
|
+
portCacheInvalidatedAt = /* @__PURE__ */ new Map();
|
|
20402
20417
|
NEGATIVE_CACHE_TTL_MS = 3e4;
|
|
20403
20418
|
WEAK_RESULT_CACHE_TTL_MS = 1500;
|
|
20404
20419
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/swift.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.545 | (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
|
@@ -629,7 +629,7 @@ async function resolveLocalIconPath(
|
|
|
629
629
|
localIconPathCache.set(port, candidate)
|
|
630
630
|
// the identified result caches as a strong entry and won't re-probe on
|
|
631
631
|
// its own; drop it so the next scan republishes with the working url.
|
|
632
|
-
|
|
632
|
+
invalidatePortCache(port)
|
|
633
633
|
return
|
|
634
634
|
}
|
|
635
635
|
}
|
|
@@ -828,7 +828,7 @@ async function fetchManifestEnrichment(
|
|
|
828
828
|
})
|
|
829
829
|
// the nameless result cached as a strong entry and won't re-probe on its own;
|
|
830
830
|
// drop it so the next scan re-runs probePort and publishes the enriched name.
|
|
831
|
-
|
|
831
|
+
invalidatePortCache(result.port)
|
|
832
832
|
}
|
|
833
833
|
|
|
834
834
|
// ports confirmed to be running a non-sootsim dev server — safe to skip the
|
|
@@ -959,16 +959,22 @@ export async function probePort(
|
|
|
959
959
|
)
|
|
960
960
|
? 'one'
|
|
961
961
|
: 'expo'
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
962
|
+
// enrichWithManifest kicks the local-icon shape probe; without it the
|
|
963
|
+
// optimistic metro icon URL publishes forever and the confirmed shape
|
|
964
|
+
// never lands. every other identified return wraps it too.
|
|
965
|
+
return enrichWithManifest(
|
|
966
|
+
applyManifest(
|
|
967
|
+
{
|
|
968
|
+
port,
|
|
969
|
+
framework,
|
|
970
|
+
bundleUrl: withRuntimeConfig(port, launchUrl, owner.cwd),
|
|
971
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl('ws:', probeHostname, port)}/hot`,
|
|
972
|
+
lastSeen: Date.now(),
|
|
973
|
+
...owner,
|
|
974
|
+
},
|
|
975
|
+
manifestRes,
|
|
976
|
+
buildIconProxyUrl,
|
|
977
|
+
),
|
|
972
978
|
buildIconProxyUrl,
|
|
973
979
|
)
|
|
974
980
|
}
|
|
@@ -1123,6 +1129,17 @@ interface PortCacheEntry {
|
|
|
1123
1129
|
}
|
|
1124
1130
|
const portCache = new Map<number, PortCacheEntry>()
|
|
1125
1131
|
|
|
1132
|
+
// out-of-band completions (the icon-shape probe, manifest enrichment) land
|
|
1133
|
+
// while a scan's own probeAll is still in flight, and the scan's cache write
|
|
1134
|
+
// would resurrect the entry they just dropped. stamp every such invalidation
|
|
1135
|
+
// so a scan only caches ports whose verdicts are newer than its own start.
|
|
1136
|
+
const portCacheInvalidatedAt = new Map<number, number>()
|
|
1137
|
+
|
|
1138
|
+
function invalidatePortCache(port: number): void {
|
|
1139
|
+
portCache.delete(port)
|
|
1140
|
+
portCacheInvalidatedAt.set(port, Date.now())
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1126
1143
|
// negative-cache holds a node/bun port that isn't a bundler (e.g. Contrast's own
|
|
1127
1144
|
// api server, Zero, SQLite sync host, a dev tool). at scan interval 3s and a 1.5s ttl
|
|
1128
1145
|
// we used to re-probe every scan, which hits `/` on the port every 3s — that
|
|
@@ -1166,6 +1183,7 @@ export function __resetScannerCache() {
|
|
|
1166
1183
|
knownOne.clear()
|
|
1167
1184
|
enrichmentCache.clear()
|
|
1168
1185
|
enrichmentInFlight.clear()
|
|
1186
|
+
portCacheInvalidatedAt.clear()
|
|
1169
1187
|
__resetAppSettingsBundleCacheForTests()
|
|
1170
1188
|
}
|
|
1171
1189
|
|
|
@@ -1223,6 +1241,9 @@ export async function scanDevServers(
|
|
|
1223
1241
|
for (const p of [...localIconPathCache.keys()]) {
|
|
1224
1242
|
if (!currentPorts.has(p)) localIconPathCache.delete(p)
|
|
1225
1243
|
}
|
|
1244
|
+
for (const p of [...portCacheInvalidatedAt.keys()]) {
|
|
1245
|
+
if (!currentPorts.has(p)) portCacheInvalidatedAt.delete(p)
|
|
1246
|
+
}
|
|
1226
1247
|
|
|
1227
1248
|
const results: DiscoveredServer[] = []
|
|
1228
1249
|
const toProbe: ListeningProcess[] = []
|
|
@@ -1251,6 +1272,7 @@ export async function scanDevServers(
|
|
|
1251
1272
|
}
|
|
1252
1273
|
|
|
1253
1274
|
if (toProbe.length > 0) {
|
|
1275
|
+
const scanStartedAt = Date.now()
|
|
1254
1276
|
const probed = await Promise.all(
|
|
1255
1277
|
toProbe.map((p) => probePort(p.port, opts.buildIconProxyUrl, p)),
|
|
1256
1278
|
)
|
|
@@ -1258,7 +1280,12 @@ export async function scanDevServers(
|
|
|
1258
1280
|
const { port, pid } = toProbe[i]
|
|
1259
1281
|
// only cache when we have a real pid to key the entry against.
|
|
1260
1282
|
// fallback-list ports (pid 0) always reprobe so we catch state changes.
|
|
1261
|
-
|
|
1283
|
+
// skip ports an out-of-band completion invalidated mid-scan, so the
|
|
1284
|
+
// next scan re-probes instead of re-caching this scan's stale verdict.
|
|
1285
|
+
const invalidatedAt = portCacheInvalidatedAt.get(port) ?? 0
|
|
1286
|
+
if (pid !== 0 && invalidatedAt < scanStartedAt) {
|
|
1287
|
+
portCache.set(port, { pid, result, cachedAt: Date.now() })
|
|
1288
|
+
}
|
|
1262
1289
|
if (result) results.push(result)
|
|
1263
1290
|
})
|
|
1264
1291
|
}
|