rn-update-cli 1.0.0
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/LICENSE +21 -0
- package/README.md +167 -0
- package/README.zh-CN.md +167 -0
- package/cli.json +525 -0
- package/lib/api.d.ts +56 -0
- package/lib/api.js +671 -0
- package/lib/app.d.ts +107 -0
- package/lib/app.js +329 -0
- package/lib/auto-update.d.ts +35 -0
- package/lib/auto-update.js +507 -0
- package/lib/bin.d.ts +2 -0
- package/lib/bin.js +133 -0
- package/lib/bundle-pack.d.ts +6 -0
- package/lib/bundle-pack.js +91 -0
- package/lib/bundle-runner.d.ts +168 -0
- package/lib/bundle-runner.js +1305 -0
- package/lib/bundle.d.ts +45 -0
- package/lib/bundle.js +226 -0
- package/lib/cache.d.ts +10 -0
- package/lib/cache.js +25 -0
- package/lib/commands.d.ts +11 -0
- package/lib/commands.js +72 -0
- package/lib/diff.d.ts +18 -0
- package/lib/diff.js +690 -0
- package/lib/exports.d.ts +11 -0
- package/lib/exports.js +20 -0
- package/lib/install.d.ts +9 -0
- package/lib/install.js +51 -0
- package/lib/locales/en.d.ts +187 -0
- package/lib/locales/en.js +194 -0
- package/lib/locales/zh.d.ts +187 -0
- package/lib/locales/zh.js +194 -0
- package/lib/native-package.d.ts +21 -0
- package/lib/native-package.js +298 -0
- package/lib/package.d.ts +68 -0
- package/lib/package.js +487 -0
- package/lib/provider.d.ts +24 -0
- package/lib/provider.js +244 -0
- package/lib/standalone-publish.d.ts +17 -0
- package/lib/standalone-publish.js +433 -0
- package/lib/symbolicate.d.ts +35 -0
- package/lib/symbolicate.js +130 -0
- package/lib/types.d.ts +152 -0
- package/lib/types.js +2 -0
- package/lib/user.d.ts +8 -0
- package/lib/user.js +50 -0
- package/lib/utils/add-gitignore.d.ts +6 -0
- package/lib/utils/add-gitignore.js +44 -0
- package/lib/utils/app-info-parser/aab.d.ts +27 -0
- package/lib/utils/app-info-parser/aab.js +256 -0
- package/lib/utils/app-info-parser/apk.d.ts +19 -0
- package/lib/utils/app-info-parser/apk.js +95 -0
- package/lib/utils/app-info-parser/app.d.ts +9 -0
- package/lib/utils/app-info-parser/app.js +15 -0
- package/lib/utils/app-info-parser/index.d.ts +21 -0
- package/lib/utils/app-info-parser/index.js +51 -0
- package/lib/utils/app-info-parser/ipa.d.ts +19 -0
- package/lib/utils/app-info-parser/ipa.js +101 -0
- package/lib/utils/app-info-parser/resource-finder.d.ts +49 -0
- package/lib/utils/app-info-parser/resource-finder.js +429 -0
- package/lib/utils/app-info-parser/utils.d.ts +36 -0
- package/lib/utils/app-info-parser/utils.js +140 -0
- package/lib/utils/app-info-parser/xml-parser/binary.d.ts +61 -0
- package/lib/utils/app-info-parser/xml-parser/binary.js +577 -0
- package/lib/utils/app-info-parser/xml-parser/manifest.d.ts +15 -0
- package/lib/utils/app-info-parser/xml-parser/manifest.js +207 -0
- package/lib/utils/app-info-parser/zip.d.ts +29 -0
- package/lib/utils/app-info-parser/zip.js +97 -0
- package/lib/utils/check-lockfile.d.ts +6 -0
- package/lib/utils/check-lockfile.js +93 -0
- package/lib/utils/check-plugin.d.ts +12 -0
- package/lib/utils/check-plugin.js +36 -0
- package/lib/utils/command-result.d.ts +8 -0
- package/lib/utils/command-result.js +27 -0
- package/lib/utils/constants.d.ts +10 -0
- package/lib/utils/constants.js +39 -0
- package/lib/utils/dep-versions.d.ts +20 -0
- package/lib/utils/dep-versions.js +129 -0
- package/lib/utils/git.d.ts +14 -0
- package/lib/utils/git.js +64 -0
- package/lib/utils/hbcTransform.d.ts +111 -0
- package/lib/utils/hbcTransform.js +561 -0
- package/lib/utils/hermes-base.d.ts +227 -0
- package/lib/utils/hermes-base.js +1287 -0
- package/lib/utils/hermes-literals.d.ts +64 -0
- package/lib/utils/hermes-literals.js +260 -0
- package/lib/utils/http-helper.d.ts +10 -0
- package/lib/utils/http-helper.js +150 -0
- package/lib/utils/i18n.d.ts +22 -0
- package/lib/utils/i18n.js +46 -0
- package/lib/utils/index.d.ts +67 -0
- package/lib/utils/index.js +545 -0
- package/lib/utils/latest-version/index.d.ts +154 -0
- package/lib/utils/latest-version/index.js +331 -0
- package/lib/utils/options.d.ts +10 -0
- package/lib/utils/options.js +68 -0
- package/lib/utils/plugin-config.d.ts +14 -0
- package/lib/utils/plugin-config.js +66 -0
- package/lib/utils/runtime.d.ts +54 -0
- package/lib/utils/runtime.js +263 -0
- package/lib/utils/slim-sourcemap.d.ts +28 -0
- package/lib/utils/slim-sourcemap.js +106 -0
- package/lib/utils/zip-entries.d.ts +10 -0
- package/lib/utils/zip-entries.js +211 -0
- package/lib/utils/zip-options.d.ts +17 -0
- package/lib/utils/zip-options.js +190 -0
- package/lib/utils/zip-range.d.ts +148 -0
- package/lib/utils/zip-range.js +581 -0
- package/lib/utils/zip-raw-writer.d.ts +52 -0
- package/lib/utils/zip-raw-writer.js +209 -0
- package/lib/version-operations.d.ts +21 -0
- package/lib/version-operations.js +320 -0
- package/lib/versions.d.ts +66 -0
- package/lib/versions.js +402 -0
- package/package.json +113 -0
- package/proto/Configuration.proto +183 -0
- package/proto/Resources.proto +569 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: 依赖 Node/Bun 子进程、HTTP agent、代理环境变量与包管理器运行时布局
|
|
3
|
+
* [OUTPUT]: 对外提供代理感知请求、网络延迟探测、包管理器/JavaScript runtime 选择及进程启动函数
|
|
4
|
+
* [POS]: CLI 跨运行时基础设施,统一网络和子进程行为,供 API、bundle 与安装命令复用
|
|
5
|
+
*/
|
|
6
|
+
import { type ChildProcessWithoutNullStreams, type SpawnOptionsWithoutStdio, type SpawnSyncOptions } from 'child_process';
|
|
7
|
+
import type { Agent as HttpAgent } from 'http';
|
|
8
|
+
export type RuntimeRequestInit = {
|
|
9
|
+
method?: string;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
body?: any;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
};
|
|
14
|
+
export type RuntimeResponse = {
|
|
15
|
+
status: number;
|
|
16
|
+
statusText: string;
|
|
17
|
+
text: () => Promise<string>;
|
|
18
|
+
};
|
|
19
|
+
export type PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn';
|
|
20
|
+
export type JavaScriptRuntime = 'bun' | 'node';
|
|
21
|
+
export declare const isBunRuntime: boolean;
|
|
22
|
+
export declare function runtimeFetch(url: string, options?: RuntimeRequestInit): Promise<RuntimeResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* The proxy url for `targetUrl` from the environment, or undefined for a
|
|
25
|
+
* direct connection (no proxy configured, NO_PROXY exempts the host, or the
|
|
26
|
+
* proxy is not an http(s) url).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveProxy(targetUrl: string, env?: NodeJS.ProcessEnv): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* fetch with the WHATWG Response, through the environment's proxy when one
|
|
31
|
+
* applies to `url`. The proxy path goes through undici's own fetch (Node's
|
|
32
|
+
* built-in one cannot take a dispatcher), loaded only then.
|
|
33
|
+
*/
|
|
34
|
+
export declare function webFetch(url: string, init?: RequestInit): Promise<Response>;
|
|
35
|
+
/**
|
|
36
|
+
* An http.Agent routing `targetUrl` through its proxy, for the core
|
|
37
|
+
* http/https APIs and node-fetch (the streaming uploads); undefined when the
|
|
38
|
+
* connection is direct. Always a CONNECT tunnel (also for http targets, like
|
|
39
|
+
* undici's ProxyAgent above): the absolute-form alternative rewrites the
|
|
40
|
+
* request head after it was buffered, which garbles a streaming body.
|
|
41
|
+
*/
|
|
42
|
+
export declare function proxyAgentFor(targetUrl: string): HttpAgent | undefined;
|
|
43
|
+
export declare function measureTcpLatency(input: string, { attempts, timeout, }?: {
|
|
44
|
+
attempts?: number;
|
|
45
|
+
timeout?: number;
|
|
46
|
+
}): Promise<number>;
|
|
47
|
+
export declare function detectPackageManager(cwd?: string, env?: NodeJS.ProcessEnv): PackageManager;
|
|
48
|
+
export declare function getInstallCommand(installArgs: string[], cwd?: string): {
|
|
49
|
+
command: string;
|
|
50
|
+
args: string[];
|
|
51
|
+
};
|
|
52
|
+
export declare function getJavaScriptRuntime(env?: NodeJS.ProcessEnv): JavaScriptRuntime;
|
|
53
|
+
export declare function spawnJavaScript(args: string[], options?: SpawnOptionsWithoutStdio, env?: NodeJS.ProcessEnv): ChildProcessWithoutNullStreams;
|
|
54
|
+
export declare function spawnJavaScriptSync(args: string[], options?: SpawnSyncOptions, env?: NodeJS.ProcessEnv): import("node:child_process").SpawnSyncReturns<string | NonSharedBuffer>;
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* [INPUT]: 依赖 Node/Bun 子进程、HTTP agent、代理环境变量与包管理器运行时布局
|
|
4
|
+
* [OUTPUT]: 对外提供代理感知请求、网络延迟探测、包管理器/JavaScript runtime 选择及进程启动函数
|
|
5
|
+
* [POS]: CLI 跨运行时基础设施,统一网络和子进程行为,供 API、bundle 与安装命令复用
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.isBunRuntime = void 0;
|
|
12
|
+
exports.runtimeFetch = runtimeFetch;
|
|
13
|
+
exports.resolveProxy = resolveProxy;
|
|
14
|
+
exports.webFetch = webFetch;
|
|
15
|
+
exports.proxyAgentFor = proxyAgentFor;
|
|
16
|
+
exports.measureTcpLatency = measureTcpLatency;
|
|
17
|
+
exports.detectPackageManager = detectPackageManager;
|
|
18
|
+
exports.getInstallCommand = getInstallCommand;
|
|
19
|
+
exports.getJavaScriptRuntime = getJavaScriptRuntime;
|
|
20
|
+
exports.spawnJavaScript = spawnJavaScript;
|
|
21
|
+
exports.spawnJavaScriptSync = spawnJavaScriptSync;
|
|
22
|
+
const child_process_1 = require("child_process");
|
|
23
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
|
+
const net_1 = require("net");
|
|
25
|
+
const path_1 = __importDefault(require("path"));
|
|
26
|
+
exports.isBunRuntime = typeof process.versions.bun ===
|
|
27
|
+
'string';
|
|
28
|
+
function runtimeFetch(url, options) {
|
|
29
|
+
return webFetch(url, options);
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// proxies
|
|
33
|
+
//
|
|
34
|
+
// Node's built-in fetch ignores HTTP(S)_PROXY, so behind a corporate proxy or
|
|
35
|
+
// a VPN every request of the CLI used to fail with a connection error. Every
|
|
36
|
+
// network path (API, uploads, source map / Hermes base downloads, the registry
|
|
37
|
+
// version check) resolves its proxy here, with the conventions curl, npm and
|
|
38
|
+
// undici share: HTTPS_PROXY for https targets (falling back to HTTP_PROXY),
|
|
39
|
+
// HTTP_PROXY for http targets, NO_PROXY to exempt hosts.
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
function firstEnv(env, ...names) {
|
|
42
|
+
for (const name of names) {
|
|
43
|
+
const value = env[name]?.trim();
|
|
44
|
+
if (value)
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* NO_PROXY: comma/space separated hosts; `*` exempts everything; a leading
|
|
51
|
+
* `.` (or `*.`) matches sub-domains, a plain host matches itself and its
|
|
52
|
+
* sub-domains, `host:port` only that port.
|
|
53
|
+
*/
|
|
54
|
+
function matchesNoProxy(target, noProxy) {
|
|
55
|
+
if (!noProxy)
|
|
56
|
+
return false;
|
|
57
|
+
const host = target.hostname.toLowerCase();
|
|
58
|
+
const port = target.port || (target.protocol === 'https:' ? '443' : '80');
|
|
59
|
+
for (const raw of noProxy.split(/[\s,]+/)) {
|
|
60
|
+
let entry = raw.trim().toLowerCase();
|
|
61
|
+
if (!entry)
|
|
62
|
+
continue;
|
|
63
|
+
if (entry === '*')
|
|
64
|
+
return true;
|
|
65
|
+
let entryPort;
|
|
66
|
+
const withPort = /^([^:]+):(\d+)$/.exec(entry);
|
|
67
|
+
if (withPort) {
|
|
68
|
+
entry = withPort[1];
|
|
69
|
+
entryPort = withPort[2];
|
|
70
|
+
}
|
|
71
|
+
if (entryPort && entryPort !== port)
|
|
72
|
+
continue;
|
|
73
|
+
if (entry.startsWith('*.'))
|
|
74
|
+
entry = entry.slice(1);
|
|
75
|
+
if (entry.startsWith('.'))
|
|
76
|
+
entry = entry.slice(1);
|
|
77
|
+
if (host === entry || host.endsWith(`.${entry}`))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The proxy url for `targetUrl` from the environment, or undefined for a
|
|
84
|
+
* direct connection (no proxy configured, NO_PROXY exempts the host, or the
|
|
85
|
+
* proxy is not an http(s) url).
|
|
86
|
+
*/
|
|
87
|
+
function resolveProxy(targetUrl, env = process.env) {
|
|
88
|
+
let target;
|
|
89
|
+
try {
|
|
90
|
+
target = new URL(targetUrl);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
if (target.protocol !== 'http:' && target.protocol !== 'https:') {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const proxy = target.protocol === 'https:'
|
|
99
|
+
? firstEnv(env, 'HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy')
|
|
100
|
+
: firstEnv(env, 'HTTP_PROXY', 'http_proxy');
|
|
101
|
+
if (!proxy || matchesNoProxy(target, firstEnv(env, 'NO_PROXY', 'no_proxy'))) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const parsed = new URL(proxy);
|
|
106
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
return proxy;
|
|
114
|
+
}
|
|
115
|
+
const proxyDispatchers = new Map();
|
|
116
|
+
/**
|
|
117
|
+
* fetch with the WHATWG Response, through the environment's proxy when one
|
|
118
|
+
* applies to `url`. The proxy path goes through undici's own fetch (Node's
|
|
119
|
+
* built-in one cannot take a dispatcher), loaded only then.
|
|
120
|
+
*/
|
|
121
|
+
function webFetch(url, init = {}) {
|
|
122
|
+
const proxy = resolveProxy(url);
|
|
123
|
+
if (proxy) {
|
|
124
|
+
const undici = require('undici');
|
|
125
|
+
let dispatcher = proxyDispatchers.get(proxy);
|
|
126
|
+
if (!dispatcher) {
|
|
127
|
+
dispatcher = new undici.ProxyAgent(proxy);
|
|
128
|
+
proxyDispatchers.set(proxy, dispatcher);
|
|
129
|
+
}
|
|
130
|
+
return undici.fetch(url, {
|
|
131
|
+
...init,
|
|
132
|
+
dispatcher,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (typeof globalThis.fetch === 'function') {
|
|
136
|
+
return globalThis.fetch(url, init);
|
|
137
|
+
}
|
|
138
|
+
// Node < 18 only. Loaded on demand so the built-in fetch path never pays
|
|
139
|
+
// for node-fetch (nor for the punycode deprecation warning it triggers on
|
|
140
|
+
// Node ≥ 21).
|
|
141
|
+
const mod = require('node-fetch');
|
|
142
|
+
const nodeFetch = (mod.default ?? mod);
|
|
143
|
+
return nodeFetch(url, init);
|
|
144
|
+
}
|
|
145
|
+
const proxyAgents = new Map();
|
|
146
|
+
/**
|
|
147
|
+
* An http.Agent routing `targetUrl` through its proxy, for the core
|
|
148
|
+
* http/https APIs and node-fetch (the streaming uploads); undefined when the
|
|
149
|
+
* connection is direct. Always a CONNECT tunnel (also for http targets, like
|
|
150
|
+
* undici's ProxyAgent above): the absolute-form alternative rewrites the
|
|
151
|
+
* request head after it was buffered, which garbles a streaming body.
|
|
152
|
+
*/
|
|
153
|
+
function proxyAgentFor(targetUrl) {
|
|
154
|
+
const proxy = resolveProxy(targetUrl);
|
|
155
|
+
if (!proxy)
|
|
156
|
+
return undefined;
|
|
157
|
+
let agent = proxyAgents.get(proxy);
|
|
158
|
+
if (!agent) {
|
|
159
|
+
const { HttpsProxyAgent } = require('https-proxy-agent');
|
|
160
|
+
agent = new HttpsProxyAgent(proxy);
|
|
161
|
+
proxyAgents.set(proxy, agent);
|
|
162
|
+
}
|
|
163
|
+
return agent;
|
|
164
|
+
}
|
|
165
|
+
function resolveTcpTarget(input) {
|
|
166
|
+
try {
|
|
167
|
+
const parsed = new URL(input);
|
|
168
|
+
const port = parsed.port || (parsed.protocol === 'http:' ? '80' : '443');
|
|
169
|
+
return {
|
|
170
|
+
host: parsed.hostname,
|
|
171
|
+
port: Number(port),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
const [host, port] = input.split(':');
|
|
176
|
+
return {
|
|
177
|
+
host,
|
|
178
|
+
port: port ? Number(port) : 443,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function measureTcpConnectOnce(host, port, timeout) {
|
|
183
|
+
return new Promise((resolve) => {
|
|
184
|
+
const startedAt = Date.now();
|
|
185
|
+
const socket = (0, net_1.createConnection)({ host, port });
|
|
186
|
+
const finish = (latency) => {
|
|
187
|
+
socket.removeAllListeners();
|
|
188
|
+
socket.destroy();
|
|
189
|
+
resolve(latency);
|
|
190
|
+
};
|
|
191
|
+
socket.setTimeout(timeout);
|
|
192
|
+
socket.once('connect', () => {
|
|
193
|
+
finish(Date.now() - startedAt);
|
|
194
|
+
});
|
|
195
|
+
socket.once('timeout', () => {
|
|
196
|
+
finish(Number.POSITIVE_INFINITY);
|
|
197
|
+
});
|
|
198
|
+
socket.once('error', () => {
|
|
199
|
+
finish(Number.POSITIVE_INFINITY);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async function measureTcpLatency(input, { attempts = 4, timeout = 1000, } = {}) {
|
|
204
|
+
const { host, port } = resolveTcpTarget(input);
|
|
205
|
+
const promises = Array.from({ length: attempts }, () => measureTcpConnectOnce(host, port, timeout));
|
|
206
|
+
const results = await Promise.all(promises);
|
|
207
|
+
const latencies = results.filter(Number.isFinite);
|
|
208
|
+
if (latencies.length === 0) {
|
|
209
|
+
return Number.POSITIVE_INFINITY;
|
|
210
|
+
}
|
|
211
|
+
return (latencies.reduce((sum, latency) => sum + latency, 0) / latencies.length);
|
|
212
|
+
}
|
|
213
|
+
function detectPackageManager(cwd = process.cwd(), env = process.env) {
|
|
214
|
+
const lockFiles = [
|
|
215
|
+
['bun.lock', 'bun'],
|
|
216
|
+
['bun.lockb', 'bun'],
|
|
217
|
+
['pnpm-lock.yaml', 'pnpm'],
|
|
218
|
+
['yarn.lock', 'yarn'],
|
|
219
|
+
['package-lock.json', 'npm'],
|
|
220
|
+
];
|
|
221
|
+
for (const [lockFile, manager] of lockFiles) {
|
|
222
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, lockFile))) {
|
|
223
|
+
return manager;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const userAgent = env.npm_config_user_agent ?? '';
|
|
227
|
+
if (userAgent.startsWith('bun/')) {
|
|
228
|
+
return 'bun';
|
|
229
|
+
}
|
|
230
|
+
if (userAgent.startsWith('pnpm/')) {
|
|
231
|
+
return 'pnpm';
|
|
232
|
+
}
|
|
233
|
+
if (userAgent.startsWith('yarn/')) {
|
|
234
|
+
return 'yarn';
|
|
235
|
+
}
|
|
236
|
+
if (userAgent.startsWith('npm/')) {
|
|
237
|
+
return 'npm';
|
|
238
|
+
}
|
|
239
|
+
return exports.isBunRuntime ? 'bun' : 'npm';
|
|
240
|
+
}
|
|
241
|
+
function getInstallCommand(installArgs, cwd = process.cwd()) {
|
|
242
|
+
const packageManager = detectPackageManager(cwd);
|
|
243
|
+
if (packageManager === 'npm') {
|
|
244
|
+
return { command: 'npm', args: ['install', ...installArgs] };
|
|
245
|
+
}
|
|
246
|
+
return { command: packageManager, args: ['add', ...installArgs] };
|
|
247
|
+
}
|
|
248
|
+
function getJavaScriptRuntime(env = process.env) {
|
|
249
|
+
const configured = env.RNU_JS_RUNTIME?.toLowerCase();
|
|
250
|
+
if (configured === 'bun') {
|
|
251
|
+
return 'bun';
|
|
252
|
+
}
|
|
253
|
+
if (configured === 'auto') {
|
|
254
|
+
return exports.isBunRuntime ? 'bun' : 'node';
|
|
255
|
+
}
|
|
256
|
+
return 'node';
|
|
257
|
+
}
|
|
258
|
+
function spawnJavaScript(args, options, env = process.env) {
|
|
259
|
+
return (0, child_process_1.spawn)(getJavaScriptRuntime(env), args, options ?? {});
|
|
260
|
+
}
|
|
261
|
+
function spawnJavaScriptSync(args, options, env = process.env) {
|
|
262
|
+
return (0, child_process_1.spawnSync)(getJavaScriptRuntime(env), args, options ?? {});
|
|
263
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shrink a source map before archiving it with a version, without losing the
|
|
3
|
+
* ability to locate any frame:
|
|
4
|
+
*
|
|
5
|
+
* - absolute source paths under the project root become relative (build
|
|
6
|
+
* machine paths do not belong in an uploaded artifact);
|
|
7
|
+
* - `sourcesContent` of node_modules sources is dropped. Mappings and the
|
|
8
|
+
* source paths stay, so frames inside dependencies still symbolicate to
|
|
9
|
+
* `node_modules/...:line:column` — only the inline code snippet for those
|
|
10
|
+
* frames is lost, and dependency sources are recoverable from the lockfile
|
|
11
|
+
* anyway. On an RN app this is the bulk of the map's bytes.
|
|
12
|
+
*
|
|
13
|
+
* Returns null when the content is not a usable plain source map (invalid
|
|
14
|
+
* JSON, or an indexed map with `sections`); the caller then uploads the
|
|
15
|
+
* original file untouched.
|
|
16
|
+
*/
|
|
17
|
+
export declare function slimSourceMap(content: string, projectRoot: string): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Build the bytes actually archived with a version: the slimmed map (when it
|
|
20
|
+
* is a plain map we understand), gzipped. Source maps are JSON and compress
|
|
21
|
+
* about 5x, which is the difference between a multi-megabyte upload on every
|
|
22
|
+
* publish and a small one. Readers detect the gzip magic bytes rather than
|
|
23
|
+
* trusting a file name, so plain maps archived by older CLI versions keep
|
|
24
|
+
* working unchanged.
|
|
25
|
+
*/
|
|
26
|
+
export declare function packSourceMap(content: string, projectRoot: string): Buffer;
|
|
27
|
+
/** Decode an archived source map: gzip when the magic bytes say so. */
|
|
28
|
+
export declare function unpackSourceMap(data: Buffer): string;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.slimSourceMap = slimSourceMap;
|
|
7
|
+
exports.packSourceMap = packSourceMap;
|
|
8
|
+
exports.unpackSourceMap = unpackSourceMap;
|
|
9
|
+
/**
|
|
10
|
+
* [INPUT]: 依赖 Node path/zlib 与 source map JSON,接收构建机项目根和待归档 map
|
|
11
|
+
* [OUTPUT]: 对外提供 source map 瘦身、gzip 归档与兼容解包函数
|
|
12
|
+
* [POS]: CLI source map 归档边界,清除机器绝对路径与依赖源码内容但保留符号定位
|
|
13
|
+
*/
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
16
|
+
/**
|
|
17
|
+
* Shrink a source map before archiving it with a version, without losing the
|
|
18
|
+
* ability to locate any frame:
|
|
19
|
+
*
|
|
20
|
+
* - absolute source paths under the project root become relative (build
|
|
21
|
+
* machine paths do not belong in an uploaded artifact);
|
|
22
|
+
* - `sourcesContent` of node_modules sources is dropped. Mappings and the
|
|
23
|
+
* source paths stay, so frames inside dependencies still symbolicate to
|
|
24
|
+
* `node_modules/...:line:column` — only the inline code snippet for those
|
|
25
|
+
* frames is lost, and dependency sources are recoverable from the lockfile
|
|
26
|
+
* anyway. On an RN app this is the bulk of the map's bytes.
|
|
27
|
+
*
|
|
28
|
+
* Returns null when the content is not a usable plain source map (invalid
|
|
29
|
+
* JSON, or an indexed map with `sections`); the caller then uploads the
|
|
30
|
+
* original file untouched.
|
|
31
|
+
*/
|
|
32
|
+
function slimSourceMap(content, projectRoot) {
|
|
33
|
+
let map;
|
|
34
|
+
try {
|
|
35
|
+
map = JSON.parse(content);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (!map || typeof map !== 'object' || Array.isArray(map)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (map.sections !== undefined) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(map.sources)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const rootPrefix = resolveProjectRoot(projectRoot);
|
|
50
|
+
const sources = map.sources.map((source) => typeof source === 'string' ? relativizeSource(source, rootPrefix) : source);
|
|
51
|
+
map.sources = sources;
|
|
52
|
+
if (Array.isArray(map.sourcesContent)) {
|
|
53
|
+
map.sourcesContent = map.sourcesContent.map((item, index) => {
|
|
54
|
+
const source = sources[index];
|
|
55
|
+
if (typeof source === 'string' && isDependencySource(source)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return item;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return JSON.stringify(map);
|
|
62
|
+
}
|
|
63
|
+
function normalizeSlashes(value) {
|
|
64
|
+
return value.replace(/\\/g, '/');
|
|
65
|
+
}
|
|
66
|
+
function resolveProjectRoot(value) {
|
|
67
|
+
const normalized = normalizeSlashes(value);
|
|
68
|
+
// Source-map fixtures and CI metadata may use POSIX roots even when the
|
|
69
|
+
// CLI itself runs on Windows. Do not reinterpret `/work/app` as a drive
|
|
70
|
+
// rooted path; real Windows paths still use the host resolver below.
|
|
71
|
+
return normalized.startsWith('/')
|
|
72
|
+
? normalizeSlashes(path_1.default.posix.resolve(normalized))
|
|
73
|
+
: normalizeSlashes(path_1.default.resolve(value));
|
|
74
|
+
}
|
|
75
|
+
function relativizeSource(source, rootPrefix) {
|
|
76
|
+
const normalized = normalizeSlashes(source);
|
|
77
|
+
if (normalized === rootPrefix) {
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
if (normalized.startsWith(`${rootPrefix}/`)) {
|
|
81
|
+
return normalized.slice(rootPrefix.length + 1);
|
|
82
|
+
}
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
function isDependencySource(source) {
|
|
86
|
+
return (source.startsWith('node_modules/') || source.includes('/node_modules/'));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build the bytes actually archived with a version: the slimmed map (when it
|
|
90
|
+
* is a plain map we understand), gzipped. Source maps are JSON and compress
|
|
91
|
+
* about 5x, which is the difference between a multi-megabyte upload on every
|
|
92
|
+
* publish and a small one. Readers detect the gzip magic bytes rather than
|
|
93
|
+
* trusting a file name, so plain maps archived by older CLI versions keep
|
|
94
|
+
* working unchanged.
|
|
95
|
+
*/
|
|
96
|
+
function packSourceMap(content, projectRoot) {
|
|
97
|
+
const slimmed = slimSourceMap(content, projectRoot);
|
|
98
|
+
return zlib_1.default.gzipSync(Buffer.from(slimmed ?? content, 'utf8'));
|
|
99
|
+
}
|
|
100
|
+
/** Decode an archived source map: gzip when the magic bytes say so. */
|
|
101
|
+
function unpackSourceMap(data) {
|
|
102
|
+
if (data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b) {
|
|
103
|
+
return zlib_1.default.gunzipSync(data).toString('utf8');
|
|
104
|
+
}
|
|
105
|
+
return data.toString('utf8');
|
|
106
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: 依赖 fs-extra、临时目录、路径、流式管道与 ZIP 条目元数据
|
|
3
|
+
* [OUTPUT]: 对外提供 ZIP 条目读取、写入、前缀读取和枚举能力
|
|
4
|
+
* [POS]: CLI 归档基础设施,统一本地/嵌套 ZIP 的资源访问和临时目录生命周期
|
|
5
|
+
*/
|
|
6
|
+
import { type Entry, type ZipFile as YauzlZipFile } from 'yauzl';
|
|
7
|
+
export declare function readEntry(entry: Entry, zipFile: YauzlZipFile): Promise<Buffer>;
|
|
8
|
+
export declare function writeEntry(entry: Entry, zipFile: YauzlZipFile, outputPath: string): Promise<void>;
|
|
9
|
+
export declare function readEntryPrefix(entry: Entry, zipFile: YauzlZipFile, maxBytes: number): Promise<Buffer>;
|
|
10
|
+
export declare function enumZipEntries(zipFn: string, callback: (entry: Entry, zipFile: YauzlZipFile, nestedPath?: string) => Promise<any> | undefined, nestedPath?: string): Promise<unknown>;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* [INPUT]: 依赖 fs-extra、临时目录、路径、流式管道与 ZIP 条目元数据
|
|
4
|
+
* [OUTPUT]: 对外提供 ZIP 条目读取、写入、前缀读取和枚举能力
|
|
5
|
+
* [POS]: CLI 归档基础设施,统一本地/嵌套 ZIP 的资源访问和临时目录生命周期
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.readEntry = readEntry;
|
|
45
|
+
exports.writeEntry = writeEntry;
|
|
46
|
+
exports.readEntryPrefix = readEntryPrefix;
|
|
47
|
+
exports.enumZipEntries = enumZipEntries;
|
|
48
|
+
const fs = __importStar(require("fs-extra"));
|
|
49
|
+
const os_1 = __importDefault(require("os"));
|
|
50
|
+
const path_1 = __importDefault(require("path"));
|
|
51
|
+
const promises_1 = require("stream/promises");
|
|
52
|
+
const yauzl_1 = require("yauzl");
|
|
53
|
+
function readEntry(entry, zipFile) {
|
|
54
|
+
const buffers = [];
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
zipFile.openReadStream(entry, (err, stream) => {
|
|
57
|
+
if (err) {
|
|
58
|
+
return reject(err);
|
|
59
|
+
}
|
|
60
|
+
if (!stream) {
|
|
61
|
+
return reject(new Error(`Unable to read zip entry: ${entry.fileName}`));
|
|
62
|
+
}
|
|
63
|
+
stream.on('data', (chunk) => {
|
|
64
|
+
buffers.push(chunk);
|
|
65
|
+
});
|
|
66
|
+
stream.on('end', () => {
|
|
67
|
+
// a single chunk (a cached Range read) is handed back as-is, not copied
|
|
68
|
+
resolve(buffers.length === 1 ? buffers[0] : Buffer.concat(buffers));
|
|
69
|
+
});
|
|
70
|
+
stream.on('error', (err) => {
|
|
71
|
+
reject(err);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function writeEntry(entry, zipFile, outputPath) {
|
|
77
|
+
fs.ensureDirSync(path_1.default.dirname(outputPath));
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
zipFile.openReadStream(entry, (err, stream) => {
|
|
80
|
+
if (err) {
|
|
81
|
+
reject(err);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (!stream) {
|
|
85
|
+
reject(new Error(`Unable to read zip entry: ${entry.fileName}`));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
(0, promises_1.pipeline)(stream, fs.createWriteStream(outputPath)).then(resolve, reject);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function readEntryPrefix(entry, zipFile, maxBytes) {
|
|
93
|
+
if (maxBytes <= 0) {
|
|
94
|
+
return Promise.resolve(Buffer.alloc(0));
|
|
95
|
+
}
|
|
96
|
+
const buffers = [];
|
|
97
|
+
let length = 0;
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
zipFile.openReadStream(entry, (err, stream) => {
|
|
100
|
+
if (err) {
|
|
101
|
+
return reject(err);
|
|
102
|
+
}
|
|
103
|
+
if (!stream) {
|
|
104
|
+
return reject(new Error(`Unable to read zip entry: ${entry.fileName}`));
|
|
105
|
+
}
|
|
106
|
+
let settled = false;
|
|
107
|
+
let expectedDestroyError;
|
|
108
|
+
const cleanup = () => {
|
|
109
|
+
stream.off('data', onData);
|
|
110
|
+
stream.off('end', onEnd);
|
|
111
|
+
stream.off('error', onError);
|
|
112
|
+
};
|
|
113
|
+
const finish = (destroyStream = false) => {
|
|
114
|
+
if (settled) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
settled = true;
|
|
118
|
+
stream.off('data', onData);
|
|
119
|
+
stream.off('end', onEnd);
|
|
120
|
+
if (!destroyStream) {
|
|
121
|
+
stream.off('error', onError);
|
|
122
|
+
}
|
|
123
|
+
resolve(Buffer.concat(buffers, length));
|
|
124
|
+
if (destroyStream) {
|
|
125
|
+
expectedDestroyError = new Error('zip entry prefix read complete');
|
|
126
|
+
stream.destroy(expectedDestroyError);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const onData = (chunk) => {
|
|
130
|
+
const remaining = maxBytes - length;
|
|
131
|
+
if (remaining <= 0) {
|
|
132
|
+
finish(true);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const slice = chunk.length > remaining ? chunk.subarray(0, remaining) : chunk;
|
|
136
|
+
buffers.push(slice);
|
|
137
|
+
length += slice.length;
|
|
138
|
+
if (length >= maxBytes) {
|
|
139
|
+
finish(true);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const onEnd = () => finish();
|
|
143
|
+
const onError = (error) => {
|
|
144
|
+
if (settled && error === expectedDestroyError) {
|
|
145
|
+
cleanup();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (settled) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
settled = true;
|
|
152
|
+
cleanup();
|
|
153
|
+
reject(error);
|
|
154
|
+
};
|
|
155
|
+
stream.on('data', onData);
|
|
156
|
+
stream.once('end', onEnd);
|
|
157
|
+
stream.once('error', onError);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async function enumZipEntries(zipFn, callback, nestedPath = '') {
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
(0, yauzl_1.open)(zipFn, { lazyEntries: true }, async (err, zipfile) => {
|
|
164
|
+
if (err) {
|
|
165
|
+
return reject(err);
|
|
166
|
+
}
|
|
167
|
+
zipfile.on('end', resolve);
|
|
168
|
+
zipfile.on('error', reject);
|
|
169
|
+
zipfile.on('entry', async (entry) => {
|
|
170
|
+
const fullPath = nestedPath + entry.fileName;
|
|
171
|
+
try {
|
|
172
|
+
if (!entry.fileName.endsWith('/') &&
|
|
173
|
+
entry.fileName.toLowerCase().endsWith('.hap')) {
|
|
174
|
+
const tempDir = await fs.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'nested_zip_'));
|
|
175
|
+
const tempZipPath = path_1.default.join(tempDir, 'temp.zip');
|
|
176
|
+
try {
|
|
177
|
+
await new Promise((res, rej) => {
|
|
178
|
+
zipfile.openReadStream(entry, async (err, readStream) => {
|
|
179
|
+
if (err)
|
|
180
|
+
return rej(err);
|
|
181
|
+
const writeStream = fs.createWriteStream(tempZipPath);
|
|
182
|
+
readStream.on('error', rej);
|
|
183
|
+
readStream.pipe(writeStream);
|
|
184
|
+
writeStream.on('finish', () => res(void 0));
|
|
185
|
+
writeStream.on('error', rej);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
await enumZipEntries(tempZipPath, callback, `${fullPath}/`);
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
await fs.remove(tempDir);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const result = callback(entry, zipfile, fullPath);
|
|
195
|
+
if (result && typeof result.then === 'function') {
|
|
196
|
+
await result;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
// the rejection carries the error; logging it here too would make
|
|
201
|
+
// callers report it twice
|
|
202
|
+
zipfile.close();
|
|
203
|
+
reject(error);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
zipfile.readEntry();
|
|
207
|
+
});
|
|
208
|
+
zipfile.readEntry();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|