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
package/lib/package.js
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.packageCommands = void 0;
|
|
40
|
+
exports.normalizeUploadBuildTime = normalizeUploadBuildTime;
|
|
41
|
+
exports.listPackage = listPackage;
|
|
42
|
+
exports.choosePackage = choosePackage;
|
|
43
|
+
/**
|
|
44
|
+
* [INPUT]: 依赖原生包解析器、对象上传 API、应用选择与 channel 自动创建/断言
|
|
45
|
+
* [OUTPUT]: 对外提供三端原生包登记/列表/删除/解析命令,上传前执行版本组 JS 一致性与精确身份幂等检查
|
|
46
|
+
* [POS]: CLI 原生构建边界,在上传字节前阻断同版本换 JS,并把合法精简制品、Range 与 buildTime 绑定到 NativeVersion
|
|
47
|
+
*/
|
|
48
|
+
const fs = __importStar(require("fs-extra"));
|
|
49
|
+
const os_1 = __importDefault(require("os"));
|
|
50
|
+
const path_1 = __importDefault(require("path"));
|
|
51
|
+
const api_1 = require("./api");
|
|
52
|
+
const app_1 = require("./app");
|
|
53
|
+
const native_package_1 = require("./native-package");
|
|
54
|
+
const utils_1 = require("./utils");
|
|
55
|
+
const constants_1 = require("./utils/constants");
|
|
56
|
+
const http_helper_1 = require("./utils/http-helper");
|
|
57
|
+
const dep_versions_1 = require("./utils/dep-versions");
|
|
58
|
+
const git_1 = require("./utils/git");
|
|
59
|
+
const hermes_base_1 = require("./utils/hermes-base");
|
|
60
|
+
const i18n_1 = require("./utils/i18n");
|
|
61
|
+
const options_1 = require("./utils/options");
|
|
62
|
+
const zip_range_1 = require("./utils/zip-range");
|
|
63
|
+
// the AAB parser drags in protobufjs; load it only for the aab commands
|
|
64
|
+
function createAabParser(source) {
|
|
65
|
+
const { AabParser } = require('./utils/app-info-parser/aab');
|
|
66
|
+
return new AabParser(source);
|
|
67
|
+
}
|
|
68
|
+
function normalizeUploadBuildTime(value) {
|
|
69
|
+
return String(value);
|
|
70
|
+
}
|
|
71
|
+
function ensureFileByExt(filePath, extension, usageKey) {
|
|
72
|
+
if (!filePath?.endsWith(extension)) {
|
|
73
|
+
throw new Error((0, i18n_1.t)(usageKey));
|
|
74
|
+
}
|
|
75
|
+
return filePath;
|
|
76
|
+
}
|
|
77
|
+
async function assertNativePackageSize(filePath, appId) {
|
|
78
|
+
if (!(0, http_helper_1.isStandaloneService)())
|
|
79
|
+
return;
|
|
80
|
+
// An unauthenticated legacy invocation cannot read account entitlements;
|
|
81
|
+
// let the existing upload endpoint enforce its server-side limit. As soon
|
|
82
|
+
// as a session or API key is present, fail before parsing/slimming bytes.
|
|
83
|
+
if (!(0, api_1.getApiToken)() && !(0, api_1.getSession)())
|
|
84
|
+
return;
|
|
85
|
+
// Harmony .app is a directory containing nested .hap archives. statSync on
|
|
86
|
+
// the directory only returns filesystem metadata, so quota checks must sum
|
|
87
|
+
// every regular file before any parser, slimming, or upload side effect.
|
|
88
|
+
const fileSize = measurePackageBytes(filePath);
|
|
89
|
+
const entitlement = await (0, api_1.getMembershipEntitlement)(appId);
|
|
90
|
+
const maxBytes = Number(entitlement.nativePackageMaxBytes);
|
|
91
|
+
if (!Number.isFinite(maxBytes) || maxBytes <= 0) {
|
|
92
|
+
throw new Error('服务端未返回有效的原生包大小额度,请升级服务端后重试。');
|
|
93
|
+
}
|
|
94
|
+
if (fileSize > maxBytes) {
|
|
95
|
+
throw new Error((0, i18n_1.t)('fileSizeExceeded', {
|
|
96
|
+
fileSize: `${(fileSize / 1048576).toFixed(1)} MB`,
|
|
97
|
+
maxSize: `${(maxBytes / 1048576).toFixed(0)} MB`,
|
|
98
|
+
pricingPageUrl: constants_1.pricingPageUrl,
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function measurePackageBytes(filePath) {
|
|
103
|
+
const stat = fs.lstatSync(filePath);
|
|
104
|
+
if (!stat.isDirectory()) {
|
|
105
|
+
return stat.size;
|
|
106
|
+
}
|
|
107
|
+
return fs
|
|
108
|
+
.readdirSync(filePath)
|
|
109
|
+
.reduce((total, entry) => total + measurePackageBytes(path_1.default.join(filePath, entry)), 0);
|
|
110
|
+
}
|
|
111
|
+
function parseBooleanOption(value) {
|
|
112
|
+
return value === true || value === 'true';
|
|
113
|
+
}
|
|
114
|
+
function parseCsvOption(value) {
|
|
115
|
+
if (typeof value !== 'string') {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const parsed = value
|
|
119
|
+
.split(',')
|
|
120
|
+
.map((item) => item.trim())
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
return parsed.length > 0 ? parsed : null;
|
|
123
|
+
}
|
|
124
|
+
function toNumericIds(ids) {
|
|
125
|
+
return ids.map((id) => {
|
|
126
|
+
const numericId = Number(id);
|
|
127
|
+
if (!Number.isInteger(numericId) || numericId <= 0) {
|
|
128
|
+
throw new Error((0, i18n_1.t)('invalidId', { id }));
|
|
129
|
+
}
|
|
130
|
+
return numericId;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function getVersionBinding(version) {
|
|
134
|
+
if (!version || typeof version !== 'object') {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
const v = version;
|
|
138
|
+
return { id: v.id, name: v.name };
|
|
139
|
+
}
|
|
140
|
+
async function uploadNativePackage(filePath, options, config) {
|
|
141
|
+
const selectedApp = options.appId
|
|
142
|
+
? {
|
|
143
|
+
appId: String(options.appId),
|
|
144
|
+
appKey: typeof options.appKey === 'string' ? options.appKey : undefined,
|
|
145
|
+
}
|
|
146
|
+
: await (0, app_1.getSelectedApp)(config.platform, options.config);
|
|
147
|
+
const { appId, appKey } = selectedApp;
|
|
148
|
+
await assertNativePackageSize(filePath, appId);
|
|
149
|
+
const info = await config.getInfo(filePath);
|
|
150
|
+
const { versionName: extractedVersionName, buildTime, bundleHash, channel: rawChannel = 'default', } = info;
|
|
151
|
+
// 与服务端 resolveChannel 的归一规则同构:渠道 code 一律小写比较。
|
|
152
|
+
const channel = String(rawChannel).trim().toLowerCase();
|
|
153
|
+
const bundleFile = info.bundleFile;
|
|
154
|
+
const { appId: appIdInPkg, appKey: appKeyInPkg } = info;
|
|
155
|
+
// where the expected app came from, for the mismatch messages
|
|
156
|
+
const source = options.appId ? '--appId' : options.config || constants_1.updateJson;
|
|
157
|
+
if (options.channel !== undefined && options.channel !== channel) {
|
|
158
|
+
throw new Error(`渠道断言失败:安装包内为 ${channel},而 --channel 为 ${options.channel}。--channel 不会覆盖包内渠道。`);
|
|
159
|
+
}
|
|
160
|
+
if (appIdInPkg && String(appIdInPkg) !== appId) {
|
|
161
|
+
throw new Error((0, i18n_1.t)(config.appIdMismatchKey, { appIdInPkg, appId, source }));
|
|
162
|
+
}
|
|
163
|
+
if (appKeyInPkg && appKey && appKeyInPkg !== appKey) {
|
|
164
|
+
throw new Error((0, i18n_1.t)(config.appKeyMismatchKey, { appKeyInPkg, appKey, source }));
|
|
165
|
+
}
|
|
166
|
+
const customVersion = typeof options.version === 'string' && options.version
|
|
167
|
+
? options.version
|
|
168
|
+
: undefined;
|
|
169
|
+
const versionName = customVersion ?? extractedVersionName;
|
|
170
|
+
if (customVersion !== undefined) {
|
|
171
|
+
console.log((0, i18n_1.t)('usingCustomVersion', { version: versionName }));
|
|
172
|
+
}
|
|
173
|
+
const normalizedBuildTime = config.normalizeBuildTime
|
|
174
|
+
? config.normalizeBuildTime(buildTime)
|
|
175
|
+
: buildTime;
|
|
176
|
+
const uploadBuildTime = normalizeUploadBuildTime(normalizedBuildTime);
|
|
177
|
+
let standaloneChannelId;
|
|
178
|
+
if ((0, http_helper_1.isStandaloneService)()) {
|
|
179
|
+
if (!bundleHash) {
|
|
180
|
+
throw new Error('独立服务登记原生包体必须包含 bundleHash。');
|
|
181
|
+
}
|
|
182
|
+
const resolvedChannel = await (0, app_1.getOrCreateChannel)(appId, channel);
|
|
183
|
+
if (resolvedChannel.created) {
|
|
184
|
+
console.log((0, i18n_1.t)('channelAutoCreated', { channel }));
|
|
185
|
+
}
|
|
186
|
+
standaloneChannelId = resolvedChannel.channel.id;
|
|
187
|
+
const versionGroup = ((await (0, api_1.getAllPackages)(appId)) ?? []).filter((item) => item.channelId === standaloneChannelId &&
|
|
188
|
+
String(item.versionName ?? item.name) === String(versionName));
|
|
189
|
+
if (versionGroup.some((item) => item.bundleHash !== bundleHash)) {
|
|
190
|
+
throw new Error((0, i18n_1.t)('nativeVersionBundleConflict', { version: versionName }));
|
|
191
|
+
}
|
|
192
|
+
const duplicate = versionGroup.find((item) => item.bundleHash === bundleHash &&
|
|
193
|
+
String(item.buildTime ?? '') === uploadBuildTime);
|
|
194
|
+
if (duplicate) {
|
|
195
|
+
console.log((0, i18n_1.t)('nativeVersionAlreadyRegistered', {
|
|
196
|
+
version: versionName,
|
|
197
|
+
id: duplicate.id,
|
|
198
|
+
}));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const tempRoot = await fs.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'rnu-native-package-upload-'));
|
|
203
|
+
const slimPackagePath = path_1.default.join(tempRoot, `package${config.extension}`);
|
|
204
|
+
try {
|
|
205
|
+
await (0, native_package_1.createSlimNativePackage)(filePath, slimPackagePath, config.platform);
|
|
206
|
+
const uploaded = await (0, api_1.uploadFile)(slimPackagePath, undefined, appId);
|
|
207
|
+
const { hash } = uploaded;
|
|
208
|
+
// where the bundle sits inside the uploaded (slim) archive, so a later
|
|
209
|
+
// `bundle` that falls back to this package as hermes base fetches only
|
|
210
|
+
// the bundle with one HTTP Range request. Harmony .app nests a second
|
|
211
|
+
// zip, so no location is reported for it.
|
|
212
|
+
const bundleLocation = config.extension === '.app'
|
|
213
|
+
? {}
|
|
214
|
+
: (0, zip_range_1.bundleLocationFields)(await (0, zip_range_1.locateZipEntry)(slimPackagePath, (0, hermes_base_1.bundleEntryMatcher)(config.extension.slice(1))).catch(() => null));
|
|
215
|
+
if (bundleFile) {
|
|
216
|
+
// keep the embedded bundle locally so a later `bundle` can use it as
|
|
217
|
+
// hermes base without downloading it back (see hermes-base.ts); getInfo
|
|
218
|
+
// already hashed the bundle, so pass that hash instead of hashing twice
|
|
219
|
+
await (0, hermes_base_1.cachePut)(bundleFile, undefined, bundleHash).catch(() => { });
|
|
220
|
+
}
|
|
221
|
+
let id;
|
|
222
|
+
if ((0, http_helper_1.isStandaloneService)()) {
|
|
223
|
+
const nativeVersion = (0, api_1.unwrapData)(await (0, api_1.post)((0, api_1.servicePath)(`/apps/${encodeURIComponent(appId)}/versions`), {
|
|
224
|
+
channelId: standaloneChannelId,
|
|
225
|
+
packageVersion: String(versionName),
|
|
226
|
+
bundleHash,
|
|
227
|
+
buildTime: uploadBuildTime,
|
|
228
|
+
packageKey: uploaded.key || uploaded.hash,
|
|
229
|
+
downloadUrl: uploaded.url,
|
|
230
|
+
...bundleLocation,
|
|
231
|
+
}));
|
|
232
|
+
id = nativeVersion.id;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
const result = await (0, api_1.post)(`/app/${appId}/package/create`, {
|
|
236
|
+
name: versionName,
|
|
237
|
+
hash,
|
|
238
|
+
buildTime: uploadBuildTime,
|
|
239
|
+
channel,
|
|
240
|
+
// Content identity of the embedded JS bundle; the server matches it
|
|
241
|
+
// against the client-reported bundleHash to decide pdiff applicability.
|
|
242
|
+
// Old servers strip unknown fields, so this is forward-compatible.
|
|
243
|
+
...(bundleHash ? { bundleHash } : {}),
|
|
244
|
+
...bundleLocation,
|
|
245
|
+
deps: (0, dep_versions_1.getDepVersions)(),
|
|
246
|
+
commit: await (0, git_1.getCommitInfo)(),
|
|
247
|
+
});
|
|
248
|
+
id = result.id;
|
|
249
|
+
}
|
|
250
|
+
console.log((0, i18n_1.t)(config.successKey, {
|
|
251
|
+
id,
|
|
252
|
+
version: versionName,
|
|
253
|
+
buildTime: uploadBuildTime,
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
finally {
|
|
257
|
+
await fs.remove(tempRoot);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Print the app's native packages. Pass `packages` when the caller already
|
|
262
|
+
* fetched them (every page of the list), to skip fetching them again.
|
|
263
|
+
*/
|
|
264
|
+
async function listPackage(appId, packages) {
|
|
265
|
+
const allPkgs = packages ?? (await (0, api_1.getAllPackages)(appId)) ?? [];
|
|
266
|
+
const header = [
|
|
267
|
+
{ value: (0, i18n_1.t)('nativePackageId') },
|
|
268
|
+
{ value: (0, i18n_1.t)('nativeVersion') },
|
|
269
|
+
];
|
|
270
|
+
const rows = [];
|
|
271
|
+
for (const pkg of allPkgs) {
|
|
272
|
+
const { version } = pkg;
|
|
273
|
+
let versionInfo = '';
|
|
274
|
+
if (version) {
|
|
275
|
+
const versionObj = getVersionBinding(version);
|
|
276
|
+
versionInfo = (0, i18n_1.t)('boundTo', {
|
|
277
|
+
name: versionObj?.name ?? version,
|
|
278
|
+
id: versionObj?.id ?? version,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
let output = pkg.name;
|
|
282
|
+
if (pkg.status === 'paused') {
|
|
283
|
+
output += (0, i18n_1.t)('pausedStatus');
|
|
284
|
+
}
|
|
285
|
+
if (pkg.status === 'expired') {
|
|
286
|
+
output += (0, i18n_1.t)('expiredStatus');
|
|
287
|
+
}
|
|
288
|
+
output += versionInfo;
|
|
289
|
+
if (pkg.channel)
|
|
290
|
+
output += ` · channel=${pkg.channel}`;
|
|
291
|
+
rows.push([pkg.id, output]);
|
|
292
|
+
}
|
|
293
|
+
// tty-table is ~25 ms to load; only pay for it when a table is rendered
|
|
294
|
+
const Table = (0, utils_1.loadTtyTable)();
|
|
295
|
+
console.log(Table(header, rows).render());
|
|
296
|
+
console.log((0, i18n_1.t)('totalPackages', { count: allPkgs.length }));
|
|
297
|
+
return allPkgs;
|
|
298
|
+
}
|
|
299
|
+
async function choosePackage(appId, packages) {
|
|
300
|
+
// Fail before fetching or rendering the package list when no prompt exists.
|
|
301
|
+
if ((0, utils_1.isNonInteractive)()) {
|
|
302
|
+
throw new Error((0, i18n_1.t)('packageIdRequired'));
|
|
303
|
+
}
|
|
304
|
+
const list = await listPackage(appId, packages);
|
|
305
|
+
const packageMap = new Map(list?.map((v) => [v.id.toString(), v]));
|
|
306
|
+
while (true) {
|
|
307
|
+
const id = await (0, utils_1.question)((0, i18n_1.t)('enterNativePackageId'));
|
|
308
|
+
const app = packageMap.get(id);
|
|
309
|
+
if (app) {
|
|
310
|
+
return app;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.packageCommands = {
|
|
315
|
+
uploadIpa: async ({ args, options, }) => {
|
|
316
|
+
const fn = ensureFileByExt(args[0], '.ipa', 'usageUploadIpa');
|
|
317
|
+
await uploadNativePackage(fn, options, {
|
|
318
|
+
extension: '.ipa',
|
|
319
|
+
platform: 'ios',
|
|
320
|
+
appIdMismatchKey: 'appIdMismatchIpa',
|
|
321
|
+
appKeyMismatchKey: 'appKeyMismatchIpa',
|
|
322
|
+
successKey: 'ipaUploadSuccess',
|
|
323
|
+
getInfo: (filePath) => (0, utils_1.getIpaInfo)(filePath),
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
uploadApk: async ({ args, options, }) => {
|
|
327
|
+
const fn = ensureFileByExt(args[0], '.apk', 'usageUploadApk');
|
|
328
|
+
await uploadNativePackage(fn, options, {
|
|
329
|
+
extension: '.apk',
|
|
330
|
+
platform: 'android',
|
|
331
|
+
appIdMismatchKey: 'appIdMismatchApk',
|
|
332
|
+
appKeyMismatchKey: 'appKeyMismatchApk',
|
|
333
|
+
successKey: 'apkUploadSuccess',
|
|
334
|
+
getInfo: (filePath) => (0, utils_1.getApkInfo)(filePath),
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
uploadAab: async ({ args, options, }) => {
|
|
338
|
+
const source = ensureFileByExt(args[0], '.aab', 'usageUploadAab');
|
|
339
|
+
const selectedApp = options.appId
|
|
340
|
+
? { appId: String(options.appId) }
|
|
341
|
+
: await (0, app_1.getSelectedApp)('android', options.config);
|
|
342
|
+
await assertNativePackageSize(source, selectedApp.appId);
|
|
343
|
+
// private temp dir: unpredictable path, safe against symlink squatting in
|
|
344
|
+
// the shared tmpdir and against concurrent uploads of same-named AABs
|
|
345
|
+
const tempRoot = await fs.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'rnu-aab-upload-'));
|
|
346
|
+
const output = path_1.default.join(tempRoot, 'universal.apk');
|
|
347
|
+
const includeAllSplits = parseBooleanOption(options.includeAllSplits);
|
|
348
|
+
const splits = parseCsvOption(options.splits);
|
|
349
|
+
const parser = createAabParser(source);
|
|
350
|
+
try {
|
|
351
|
+
await parser.extractApk(output, {
|
|
352
|
+
includeAllSplits,
|
|
353
|
+
splits,
|
|
354
|
+
});
|
|
355
|
+
await exports.packageCommands.uploadApk({
|
|
356
|
+
args: [output],
|
|
357
|
+
options,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
finally {
|
|
361
|
+
await fs.remove(tempRoot);
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
uploadApp: async ({ args, options, }) => {
|
|
365
|
+
const fn = ensureFileByExt(args[0], '.app', 'usageUploadApp');
|
|
366
|
+
await uploadNativePackage(fn, options, {
|
|
367
|
+
extension: '.app',
|
|
368
|
+
platform: 'harmony',
|
|
369
|
+
appIdMismatchKey: 'appIdMismatchApp',
|
|
370
|
+
appKeyMismatchKey: 'appKeyMismatchApp',
|
|
371
|
+
successKey: 'appUploadSuccess',
|
|
372
|
+
getInfo: (filePath) => (0, utils_1.getAppInfo)(filePath),
|
|
373
|
+
normalizeBuildTime: (buildTime) => String(buildTime),
|
|
374
|
+
});
|
|
375
|
+
},
|
|
376
|
+
parseApp: async ({ args }) => {
|
|
377
|
+
const fn = args[0];
|
|
378
|
+
if (!fn?.endsWith('.app')) {
|
|
379
|
+
throw new Error((0, i18n_1.t)('usageParseApp'));
|
|
380
|
+
}
|
|
381
|
+
console.log(await (0, utils_1.getAppInfo)(fn));
|
|
382
|
+
},
|
|
383
|
+
parseIpa: async ({ args }) => {
|
|
384
|
+
const fn = args[0];
|
|
385
|
+
if (!fn?.endsWith('.ipa')) {
|
|
386
|
+
throw new Error((0, i18n_1.t)('usageParseIpa'));
|
|
387
|
+
}
|
|
388
|
+
console.log(await (0, utils_1.getIpaInfo)(fn));
|
|
389
|
+
},
|
|
390
|
+
parseApk: async ({ args }) => {
|
|
391
|
+
const fn = args[0];
|
|
392
|
+
if (!fn?.endsWith('.apk')) {
|
|
393
|
+
throw new Error((0, i18n_1.t)('usageParseApk'));
|
|
394
|
+
}
|
|
395
|
+
console.log(await (0, utils_1.getApkInfo)(fn));
|
|
396
|
+
},
|
|
397
|
+
parseAab: async ({ args }) => {
|
|
398
|
+
const fn = args[0];
|
|
399
|
+
if (!fn?.endsWith('.aab')) {
|
|
400
|
+
throw new Error((0, i18n_1.t)('usageParseAab'));
|
|
401
|
+
}
|
|
402
|
+
console.log(await (0, utils_1.getAabInfo)(fn));
|
|
403
|
+
},
|
|
404
|
+
extractApk: async ({ args, options, }) => {
|
|
405
|
+
const source = ensureFileByExt(args[0], '.aab', 'usageExtractApk');
|
|
406
|
+
const output = options.output ||
|
|
407
|
+
path_1.default.join(path_1.default.dirname(source), `${path_1.default.basename(source, path_1.default.extname(source))}.apk`);
|
|
408
|
+
const includeAllSplits = parseBooleanOption(options.includeAllSplits);
|
|
409
|
+
const splits = parseCsvOption(options.splits);
|
|
410
|
+
const parser = createAabParser(source);
|
|
411
|
+
await parser.extractApk(output, {
|
|
412
|
+
includeAllSplits,
|
|
413
|
+
splits,
|
|
414
|
+
});
|
|
415
|
+
console.log((0, i18n_1.t)('apkExtracted', { output }));
|
|
416
|
+
},
|
|
417
|
+
packages: async ({ options, }) => {
|
|
418
|
+
await listPackage(await (0, app_1.resolveAppId)(options));
|
|
419
|
+
},
|
|
420
|
+
deletePackage: async ({ options }) => {
|
|
421
|
+
const appId = await (0, app_1.resolveAppId)(options);
|
|
422
|
+
let packageIds = (0, options_1.getStringListOption)(options, 'packageIds') ??
|
|
423
|
+
(0, options_1.getStringListOption)(options, 'packageId');
|
|
424
|
+
if (!packageIds) {
|
|
425
|
+
const packageVersions = (0, options_1.getStringListOption)(options, 'packageVersion');
|
|
426
|
+
if (!packageVersions) {
|
|
427
|
+
throw new Error((0, i18n_1.t)('usageDeletePackage'));
|
|
428
|
+
}
|
|
429
|
+
const allPkgs = await (0, api_1.getAllPackages)(appId);
|
|
430
|
+
if (!allPkgs) {
|
|
431
|
+
throw new Error((0, i18n_1.t)('noPackagesFound', { appId }));
|
|
432
|
+
}
|
|
433
|
+
const allPkgsMap = new Map(allPkgs.map((pkg) => [pkg.name, pkg]));
|
|
434
|
+
packageIds = packageVersions.map((packageVersion) => {
|
|
435
|
+
const selectedPackage = allPkgsMap.get(packageVersion);
|
|
436
|
+
if (!selectedPackage) {
|
|
437
|
+
throw new Error((0, i18n_1.t)('packageNotFound', { packageVersion }));
|
|
438
|
+
}
|
|
439
|
+
return String(selectedPackage.id);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
// Confirm deletion
|
|
443
|
+
// const confirmDelete = await question(
|
|
444
|
+
// t('confirmDeletePackage', { packageId }),
|
|
445
|
+
// );
|
|
446
|
+
// if (
|
|
447
|
+
// confirmDelete.toLowerCase() !== 'y' &&
|
|
448
|
+
// confirmDelete.toLowerCase() !== 'yes'
|
|
449
|
+
// ) {
|
|
450
|
+
// console.log(t('cancelled'));
|
|
451
|
+
// return;
|
|
452
|
+
// }
|
|
453
|
+
try {
|
|
454
|
+
if ((0, http_helper_1.isStandaloneService)()) {
|
|
455
|
+
for (const packageId of packageIds) {
|
|
456
|
+
await (0, api_1.doDelete)((0, api_1.servicePath)(`/versions/${encodeURIComponent(packageId)}`));
|
|
457
|
+
}
|
|
458
|
+
console.log((0, i18n_1.t)('deletePackagesSuccess', {
|
|
459
|
+
count: packageIds.length,
|
|
460
|
+
packageIds: packageIds.join(', '),
|
|
461
|
+
}));
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (packageIds.length === 1) {
|
|
465
|
+
const [packageId] = packageIds;
|
|
466
|
+
await (0, api_1.doDelete)(`/app/${appId}/package/${packageId}`);
|
|
467
|
+
console.log((0, i18n_1.t)('deletePackageSuccess', { packageId }));
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
await (0, api_1.doDelete)(`/app/${appId}/package`, {
|
|
471
|
+
packageIds: toNumericIds(packageIds),
|
|
472
|
+
});
|
|
473
|
+
console.log((0, i18n_1.t)('deletePackagesSuccess', {
|
|
474
|
+
count: packageIds.length,
|
|
475
|
+
packageIds: packageIds.join(', '),
|
|
476
|
+
}));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
481
|
+
throw new Error((0, i18n_1.t)('deletePackageError', {
|
|
482
|
+
packageId: packageIds.join(', '),
|
|
483
|
+
error: message,
|
|
484
|
+
}));
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { BundleOptions, CLIProvider, CommandResult, Platform, PublishOptions, Session, SymbolicateOptions, UpdateVersionOptions, UploadOptions } from './types';
|
|
2
|
+
export declare class CLIProviderImpl implements CLIProvider {
|
|
3
|
+
private session?;
|
|
4
|
+
private sessionInitPromise?;
|
|
5
|
+
private createContext;
|
|
6
|
+
private ensureInitialized;
|
|
7
|
+
private runMessageCommand;
|
|
8
|
+
private runDataCommand;
|
|
9
|
+
bundle(options: BundleOptions): Promise<CommandResult>;
|
|
10
|
+
publish(options: PublishOptions): Promise<CommandResult>;
|
|
11
|
+
symbolicate(options: SymbolicateOptions): Promise<CommandResult>;
|
|
12
|
+
upload(options: UploadOptions): Promise<CommandResult>;
|
|
13
|
+
getSelectedApp(platform?: Platform, config?: string): Promise<{
|
|
14
|
+
appId: string;
|
|
15
|
+
platform: Platform;
|
|
16
|
+
}>;
|
|
17
|
+
listApps(platform?: Platform): Promise<CommandResult>;
|
|
18
|
+
createApp(name: string, platform: Platform): Promise<CommandResult>;
|
|
19
|
+
listVersions(appId: string): Promise<CommandResult>;
|
|
20
|
+
updateVersion(appId: string, versionId: string, updates: UpdateVersionOptions): Promise<CommandResult>;
|
|
21
|
+
getPlatform(platform?: Platform): Promise<Platform>;
|
|
22
|
+
loadSession(): Promise<Session>;
|
|
23
|
+
listPackages(appId: string): Promise<CommandResult>;
|
|
24
|
+
}
|