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,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* [INPUT]: 依赖源 ZIP 中央目录、可读流、CRC/尺寸元数据与文件系统
|
|
4
|
+
* [OUTPUT]: 对外提供 RawZipEntry、fitsRawZip、crc32Update 与 RawZipWriter
|
|
5
|
+
* [POS]: CLI 归档快速重打包底座,原样复制已压缩条目,避免资源二次压缩
|
|
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.RawZipWriter = void 0;
|
|
12
|
+
exports.fitsRawZip = fitsRawZip;
|
|
13
|
+
exports.crc32Update = crc32Update;
|
|
14
|
+
// A minimal zip writer that copies entries *as stored* — their compressed
|
|
15
|
+
// bytes, CRC, sizes and timestamps straight from the source archive's central
|
|
16
|
+
// directory — so repacking a subset of an apk / ipa / hap costs disk I/O, not
|
|
17
|
+
// a second deflate of every asset (yazl can only add uncompressed data and
|
|
18
|
+
// re-deflates it). Plain zip only: no zip64, no data descriptors, no extra
|
|
19
|
+
// fields; callers must check `fitsRawZip` before choosing this writer.
|
|
20
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
21
|
+
const LOCAL_HEADER_SIGNATURE = 0x04034b50;
|
|
22
|
+
const CENTRAL_HEADER_SIGNATURE = 0x02014b50;
|
|
23
|
+
const EOCD_SIGNATURE = 0x06054b50;
|
|
24
|
+
const VERSION_NEEDED_DEFAULT = 20;
|
|
25
|
+
/** "made by" for entries this writer creates itself: unix, spec 2.0 */
|
|
26
|
+
const VERSION_MADE_BY_UNIX = (3 << 8) | 20;
|
|
27
|
+
const FLAG_UTF8_NAMES = 0x800;
|
|
28
|
+
const FLAG_DATA_DESCRIPTOR = 0x8;
|
|
29
|
+
/** general-purpose bits carried over from a copied entry: encryption, deflate strength */
|
|
30
|
+
const FLAG_KEEP_MASK = 0x0007;
|
|
31
|
+
const MAX_UINT32 = 0xffffffff;
|
|
32
|
+
const MAX_UINT16 = 0xffff;
|
|
33
|
+
/** external attributes of a plain `-rw-r--r--` file */
|
|
34
|
+
const UNIX_REGULAR_FILE_ATTRIBUTES = 0o100644 << 16;
|
|
35
|
+
/**
|
|
36
|
+
* Whether an archive of `sourceSize` bytes with `entryCount` entries can be
|
|
37
|
+
* (partially) copied without zip64 structures: an output that only keeps a
|
|
38
|
+
* subset of the entries is never larger than its source.
|
|
39
|
+
*/
|
|
40
|
+
function fitsRawZip(sourceSize, entryCount) {
|
|
41
|
+
return sourceSize < MAX_UINT32 && entryCount < MAX_UINT16;
|
|
42
|
+
}
|
|
43
|
+
let crcTable;
|
|
44
|
+
function getCrcTable() {
|
|
45
|
+
if (!crcTable) {
|
|
46
|
+
crcTable = new Int32Array(256);
|
|
47
|
+
for (let n = 0; n < 256; n++) {
|
|
48
|
+
let c = n;
|
|
49
|
+
for (let k = 0; k < 8; k++)
|
|
50
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
51
|
+
crcTable[n] = c;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return crcTable;
|
|
55
|
+
}
|
|
56
|
+
/** CRC-32 (IEEE) continued from `seed` (the running value, not inverted) */
|
|
57
|
+
function crc32Update(seed, chunk) {
|
|
58
|
+
const table = getCrcTable();
|
|
59
|
+
let crc = ~seed;
|
|
60
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
61
|
+
crc = table[(crc ^ chunk[i]) & 0xff] ^ (crc >>> 8);
|
|
62
|
+
}
|
|
63
|
+
return ~crc >>> 0;
|
|
64
|
+
}
|
|
65
|
+
class RawZipWriter {
|
|
66
|
+
output;
|
|
67
|
+
out;
|
|
68
|
+
central = [];
|
|
69
|
+
offset = 0;
|
|
70
|
+
count = 0;
|
|
71
|
+
failure = null;
|
|
72
|
+
closed;
|
|
73
|
+
constructor(output) {
|
|
74
|
+
this.output = output;
|
|
75
|
+
this.out = fs_extra_1.default.createWriteStream(output);
|
|
76
|
+
this.closed = new Promise((resolve, reject) => {
|
|
77
|
+
this.out.once('close', resolve);
|
|
78
|
+
this.out.once('error', (error) => {
|
|
79
|
+
this.failure = error;
|
|
80
|
+
reject(error);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
// surfaced by the next write / end(), never as an unhandled rejection
|
|
84
|
+
this.closed.catch(() => { });
|
|
85
|
+
}
|
|
86
|
+
/** Copy one entry with its file data exactly as stored in the source. */
|
|
87
|
+
async addRawEntry(meta, data) {
|
|
88
|
+
if (meta.compressedSize > MAX_UINT32 ||
|
|
89
|
+
meta.uncompressedSize > MAX_UINT32 ||
|
|
90
|
+
this.offset > MAX_UINT32 ||
|
|
91
|
+
this.count >= MAX_UINT16) {
|
|
92
|
+
throw new Error(`zip64 required for ${meta.fileName}`);
|
|
93
|
+
}
|
|
94
|
+
const name = Buffer.from(meta.fileName, 'utf8');
|
|
95
|
+
if (name.length > MAX_UINT16) {
|
|
96
|
+
throw new Error(`file name too long: ${meta.fileName}`);
|
|
97
|
+
}
|
|
98
|
+
const flags = ((meta.generalPurposeBitFlag ?? 0) &
|
|
99
|
+
FLAG_KEEP_MASK &
|
|
100
|
+
~FLAG_DATA_DESCRIPTOR) |
|
|
101
|
+
FLAG_UTF8_NAMES;
|
|
102
|
+
const versionNeeded = Math.max(VERSION_NEEDED_DEFAULT, meta.versionNeededToExtract ?? 0);
|
|
103
|
+
const localOffset = this.offset;
|
|
104
|
+
const local = Buffer.alloc(30 + name.length);
|
|
105
|
+
local.writeUInt32LE(LOCAL_HEADER_SIGNATURE, 0);
|
|
106
|
+
local.writeUInt16LE(versionNeeded, 4);
|
|
107
|
+
local.writeUInt16LE(flags, 6);
|
|
108
|
+
local.writeUInt16LE(meta.compressionMethod, 8);
|
|
109
|
+
local.writeUInt16LE(meta.lastModFileTime, 10);
|
|
110
|
+
local.writeUInt16LE(meta.lastModFileDate, 12);
|
|
111
|
+
local.writeUInt32LE(meta.crc32 >>> 0, 14);
|
|
112
|
+
local.writeUInt32LE(meta.compressedSize, 18);
|
|
113
|
+
local.writeUInt32LE(meta.uncompressedSize, 22);
|
|
114
|
+
local.writeUInt16LE(name.length, 26);
|
|
115
|
+
local.writeUInt16LE(0, 28);
|
|
116
|
+
name.copy(local, 30);
|
|
117
|
+
await this.write(local);
|
|
118
|
+
let copied = 0;
|
|
119
|
+
for await (const chunk of data) {
|
|
120
|
+
copied += chunk.length;
|
|
121
|
+
await this.write(chunk);
|
|
122
|
+
}
|
|
123
|
+
if (copied !== meta.compressedSize) {
|
|
124
|
+
throw new Error(`${meta.fileName}: read ${copied} bytes, expected ${meta.compressedSize}`);
|
|
125
|
+
}
|
|
126
|
+
const header = Buffer.alloc(46 + name.length);
|
|
127
|
+
header.writeUInt32LE(CENTRAL_HEADER_SIGNATURE, 0);
|
|
128
|
+
header.writeUInt16LE(meta.versionMadeBy ?? VERSION_MADE_BY_UNIX, 4);
|
|
129
|
+
header.writeUInt16LE(versionNeeded, 6);
|
|
130
|
+
header.writeUInt16LE(flags, 8);
|
|
131
|
+
header.writeUInt16LE(meta.compressionMethod, 10);
|
|
132
|
+
header.writeUInt16LE(meta.lastModFileTime, 12);
|
|
133
|
+
header.writeUInt16LE(meta.lastModFileDate, 14);
|
|
134
|
+
header.writeUInt32LE(meta.crc32 >>> 0, 16);
|
|
135
|
+
header.writeUInt32LE(meta.compressedSize, 20);
|
|
136
|
+
header.writeUInt32LE(meta.uncompressedSize, 24);
|
|
137
|
+
header.writeUInt16LE(name.length, 28);
|
|
138
|
+
header.writeUInt16LE(0, 30); // extra
|
|
139
|
+
header.writeUInt16LE(0, 32); // comment
|
|
140
|
+
header.writeUInt16LE(0, 34); // disk number start
|
|
141
|
+
header.writeUInt16LE(meta.internalFileAttributes ?? 0, 36);
|
|
142
|
+
header.writeUInt32LE((meta.externalFileAttributes ?? UNIX_REGULAR_FILE_ATTRIBUTES) >>> 0, 38);
|
|
143
|
+
header.writeUInt32LE(localOffset, 42);
|
|
144
|
+
name.copy(header, 46);
|
|
145
|
+
this.central.push(header);
|
|
146
|
+
this.count += 1;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Add a local file uncompressed (its CRC is computed in a first pass).
|
|
150
|
+
* `like` lends its timestamp and attributes, e.g. the archive entry this
|
|
151
|
+
* file replaces.
|
|
152
|
+
*/
|
|
153
|
+
async addStoredFile(filePath, fileName, like) {
|
|
154
|
+
let crc = 0;
|
|
155
|
+
let size = 0;
|
|
156
|
+
for await (const chunk of fs_extra_1.default.createReadStream(filePath)) {
|
|
157
|
+
crc = crc32Update(crc, chunk);
|
|
158
|
+
size += chunk.length;
|
|
159
|
+
}
|
|
160
|
+
await this.addRawEntry({
|
|
161
|
+
fileName,
|
|
162
|
+
compressionMethod: 0,
|
|
163
|
+
crc32: crc,
|
|
164
|
+
compressedSize: size,
|
|
165
|
+
uncompressedSize: size,
|
|
166
|
+
lastModFileTime: like?.lastModFileTime ?? 0,
|
|
167
|
+
lastModFileDate: like?.lastModFileDate ?? 0x21, // 1980-01-01
|
|
168
|
+
externalFileAttributes: like?.externalFileAttributes,
|
|
169
|
+
versionMadeBy: like?.versionMadeBy,
|
|
170
|
+
}, fs_extra_1.default.createReadStream(filePath));
|
|
171
|
+
}
|
|
172
|
+
/** Write the central directory and close the file. */
|
|
173
|
+
async end() {
|
|
174
|
+
const cdOffset = this.offset;
|
|
175
|
+
for (const header of this.central)
|
|
176
|
+
await this.write(header);
|
|
177
|
+
const cdSize = this.offset - cdOffset;
|
|
178
|
+
if (cdOffset > MAX_UINT32 || cdSize > MAX_UINT32) {
|
|
179
|
+
throw new Error('zip64 required for the central directory');
|
|
180
|
+
}
|
|
181
|
+
const eocd = Buffer.alloc(22);
|
|
182
|
+
eocd.writeUInt32LE(EOCD_SIGNATURE, 0);
|
|
183
|
+
eocd.writeUInt16LE(0, 4);
|
|
184
|
+
eocd.writeUInt16LE(0, 6);
|
|
185
|
+
eocd.writeUInt16LE(this.count, 8);
|
|
186
|
+
eocd.writeUInt16LE(this.count, 10);
|
|
187
|
+
eocd.writeUInt32LE(cdSize, 12);
|
|
188
|
+
eocd.writeUInt32LE(cdOffset, 16);
|
|
189
|
+
eocd.writeUInt16LE(0, 20);
|
|
190
|
+
await this.write(eocd);
|
|
191
|
+
this.out.end();
|
|
192
|
+
await this.closed;
|
|
193
|
+
}
|
|
194
|
+
/** Stop writing and remove the partial output. */
|
|
195
|
+
async abort() {
|
|
196
|
+
this.out.destroy();
|
|
197
|
+
await this.closed.catch(() => { });
|
|
198
|
+
await fs_extra_1.default.remove(this.output).catch(() => { });
|
|
199
|
+
}
|
|
200
|
+
write(chunk) {
|
|
201
|
+
if (this.failure)
|
|
202
|
+
return Promise.reject(this.failure);
|
|
203
|
+
this.offset += chunk.length;
|
|
204
|
+
return new Promise((resolve, reject) => {
|
|
205
|
+
this.out.write(chunk, (error) => (error ? reject(error) : resolve()));
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.RawZipWriter = RawZipWriter;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Package, Version } from './types';
|
|
2
|
+
type Deps = Record<string, string>;
|
|
3
|
+
export declare function normalizeDeps(input: unknown): Deps | undefined;
|
|
4
|
+
export declare function toNumericIds(ids: string[]): number[];
|
|
5
|
+
export declare function printDepsChangesForPublish({ appId, versionId, pkgs, providedVersionDeps, }: {
|
|
6
|
+
appId: string;
|
|
7
|
+
versionId?: string;
|
|
8
|
+
pkgs: Package[];
|
|
9
|
+
providedVersionDeps?: Deps;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function fetchVersions(appId: string, offset?: number, limit?: number): Promise<Version[]>;
|
|
12
|
+
export declare function listVersions(appId: string, interactive?: boolean): Promise<Version[]>;
|
|
13
|
+
export declare function chooseVersion(appId: string): Promise<Version>;
|
|
14
|
+
export declare const bindVersionToPackages: ({ appId, versionId, pkgs, rollout, dryRun, }: {
|
|
15
|
+
appId: string;
|
|
16
|
+
versionId: string | null;
|
|
17
|
+
pkgs: Package[];
|
|
18
|
+
rollout?: number;
|
|
19
|
+
dryRun?: boolean;
|
|
20
|
+
}) => Promise<void>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,320 @@
|
|
|
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.bindVersionToPackages = void 0;
|
|
7
|
+
exports.normalizeDeps = normalizeDeps;
|
|
8
|
+
exports.toNumericIds = toNumericIds;
|
|
9
|
+
exports.printDepsChangesForPublish = printDepsChangesForPublish;
|
|
10
|
+
exports.fetchVersions = fetchVersions;
|
|
11
|
+
exports.listVersions = listVersions;
|
|
12
|
+
exports.chooseVersion = chooseVersion;
|
|
13
|
+
/**
|
|
14
|
+
* [INPUT]: 依赖旧版版本查询/绑定 API、渠道版本模型和终端交互工具
|
|
15
|
+
* [OUTPUT]: 对外提供版本查询、依赖变更提示、原生包绑定及版本选择操作
|
|
16
|
+
* [POS]: CLI 兼容发布操作层;独立服务的 UpdatePackage/Deployment 编排位于 standalone-publish.ts
|
|
17
|
+
*/
|
|
18
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
19
|
+
const api_1 = require("./api");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
const i18n_1 = require("./utils/i18n");
|
|
22
|
+
function normalizeDeps(input) {
|
|
23
|
+
if (!input) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
let raw = input;
|
|
27
|
+
if (typeof input === 'string') {
|
|
28
|
+
try {
|
|
29
|
+
raw = JSON.parse(input);
|
|
30
|
+
}
|
|
31
|
+
catch (_e) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const deps = {};
|
|
39
|
+
for (const [name, version] of Object.entries(raw)) {
|
|
40
|
+
if (typeof version === 'string' && version) {
|
|
41
|
+
deps[name] = version;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return Object.keys(deps).length > 0 ? deps : undefined;
|
|
45
|
+
}
|
|
46
|
+
function getDepsChanges(oldDeps, newDeps) {
|
|
47
|
+
if (!oldDeps || !newDeps) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const rows = [];
|
|
51
|
+
const keys = Object.keys({ ...oldDeps, ...newDeps }).sort((a, b) => a.localeCompare(b));
|
|
52
|
+
for (const key of keys) {
|
|
53
|
+
const oldVersion = oldDeps[key];
|
|
54
|
+
const newVersion = newDeps[key];
|
|
55
|
+
if (oldVersion === undefined && newVersion !== undefined) {
|
|
56
|
+
rows.push({
|
|
57
|
+
dependency: key,
|
|
58
|
+
oldVersion: '-',
|
|
59
|
+
newVersion,
|
|
60
|
+
type: 'added',
|
|
61
|
+
});
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (oldVersion !== undefined && newVersion === undefined) {
|
|
65
|
+
rows.push({
|
|
66
|
+
dependency: key,
|
|
67
|
+
oldVersion,
|
|
68
|
+
newVersion: '-',
|
|
69
|
+
type: 'removed',
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (oldVersion !== undefined &&
|
|
74
|
+
newVersion !== undefined &&
|
|
75
|
+
oldVersion !== newVersion) {
|
|
76
|
+
rows.push({
|
|
77
|
+
dependency: key,
|
|
78
|
+
oldVersion,
|
|
79
|
+
newVersion,
|
|
80
|
+
type: 'changed',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return rows;
|
|
85
|
+
}
|
|
86
|
+
function toNumericIds(ids) {
|
|
87
|
+
return ids.map((id) => {
|
|
88
|
+
const numericId = Number(id);
|
|
89
|
+
if (!Number.isInteger(numericId) || numericId <= 0) {
|
|
90
|
+
throw new Error((0, i18n_1.t)('invalidId', { id }));
|
|
91
|
+
}
|
|
92
|
+
return numericId;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function getDepsChangeSummary(changes) {
|
|
96
|
+
return changes.reduce((acc, item) => {
|
|
97
|
+
if (item.type === 'added') {
|
|
98
|
+
acc.added += 1;
|
|
99
|
+
}
|
|
100
|
+
else if (item.type === 'removed') {
|
|
101
|
+
acc.removed += 1;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
acc.changed += 1;
|
|
105
|
+
}
|
|
106
|
+
return acc;
|
|
107
|
+
}, { added: 0, removed: 0, changed: 0 });
|
|
108
|
+
}
|
|
109
|
+
function renderVersionChange(change) {
|
|
110
|
+
const arrow = chalk_1.default.gray(` ${(0, i18n_1.t)('depsChangeArrow')} `);
|
|
111
|
+
if (change.type === 'added') {
|
|
112
|
+
return `${chalk_1.default.red((0, i18n_1.t)('depsChangeAddedLabel'))} | ${chalk_1.default.gray(change.oldVersion)}${arrow}${chalk_1.default.red(change.newVersion)}`;
|
|
113
|
+
}
|
|
114
|
+
if (change.type === 'removed') {
|
|
115
|
+
return `${chalk_1.default.green((0, i18n_1.t)('depsChangeRemovedLabel'))} | ${chalk_1.default.green(change.oldVersion)}${arrow}${chalk_1.default.gray(change.newVersion)}`;
|
|
116
|
+
}
|
|
117
|
+
return `${chalk_1.default.yellow((0, i18n_1.t)('depsChangeChangedLabel'))} | ${chalk_1.default.yellow(change.oldVersion)}${arrow}${chalk_1.default.yellow(change.newVersion)}`;
|
|
118
|
+
}
|
|
119
|
+
function printDepsChangesForPackage({ pkg, versionDeps, }) {
|
|
120
|
+
const pkgDeps = normalizeDeps(pkg.deps);
|
|
121
|
+
if (!pkgDeps) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const changes = getDepsChanges(pkgDeps, versionDeps);
|
|
125
|
+
if (changes.length === 0) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
const summary = getDepsChangeSummary(changes);
|
|
129
|
+
const summaryText = (0, i18n_1.t)('depsChangeSummary', {
|
|
130
|
+
added: chalk_1.default.red(String(summary.added)),
|
|
131
|
+
removed: chalk_1.default.green(String(summary.removed)),
|
|
132
|
+
changed: chalk_1.default.yellow(String(summary.changed)),
|
|
133
|
+
});
|
|
134
|
+
const header = [
|
|
135
|
+
{ value: (0, i18n_1.t)('depsChangeDependencyHeader') },
|
|
136
|
+
{ value: (0, i18n_1.t)('depsChangeVersionHeader') },
|
|
137
|
+
];
|
|
138
|
+
const rows = changes.map((change) => [
|
|
139
|
+
change.dependency,
|
|
140
|
+
renderVersionChange(change),
|
|
141
|
+
]);
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log(chalk_1.default.bgYellow.black.bold(` ${(0, i18n_1.t)('depsChangeWarningTitle')} `));
|
|
144
|
+
console.log(chalk_1.default.yellow((0, i18n_1.t)('depsChangeTargetPackage', {
|
|
145
|
+
packageName: pkg.name,
|
|
146
|
+
packageId: pkg.id,
|
|
147
|
+
})));
|
|
148
|
+
console.log(summaryText);
|
|
149
|
+
// tty-table is ~25 ms to load; only pay for it when a table is rendered
|
|
150
|
+
const Table = (0, utils_1.loadTtyTable)();
|
|
151
|
+
console.log(Table(header, rows).render());
|
|
152
|
+
console.log(chalk_1.default.yellow((0, i18n_1.t)('depsChangeRiskWarning')));
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
async function findVersionDeps(appId, versionId) {
|
|
156
|
+
const targetId = String(versionId);
|
|
157
|
+
const limit = 100;
|
|
158
|
+
let offset = 0;
|
|
159
|
+
while (true) {
|
|
160
|
+
const { data, count } = await (0, api_1.get)(`/app/${appId}/version/list?offset=${offset}&limit=${limit}`);
|
|
161
|
+
const versions = Array.isArray(data) ? data : [];
|
|
162
|
+
const version = versions.find((item) => String(item.id) === targetId);
|
|
163
|
+
if (version) {
|
|
164
|
+
return normalizeDeps(version.deps);
|
|
165
|
+
}
|
|
166
|
+
offset += versions.length;
|
|
167
|
+
if (versions.length === 0 || offset >= Number(count || 0)) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
async function printDepsChangesForPublish({ appId, versionId, pkgs, providedVersionDeps, }) {
|
|
174
|
+
if (!versionId || pkgs.length !== 1) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
let versionDeps = normalizeDeps(providedVersionDeps);
|
|
178
|
+
if (!versionDeps) {
|
|
179
|
+
try {
|
|
180
|
+
versionDeps = await findVersionDeps(appId, versionId);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
console.warn(chalk_1.default.yellow((0, i18n_1.t)('depsChangeFetchFailed', {
|
|
184
|
+
error: error?.message || String(error),
|
|
185
|
+
})));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (!versionDeps) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
let hasChanges = false;
|
|
193
|
+
for (const pkg of pkgs) {
|
|
194
|
+
const printed = printDepsChangesForPackage({ pkg, versionDeps });
|
|
195
|
+
hasChanges = hasChanges || printed;
|
|
196
|
+
}
|
|
197
|
+
if (hasChanges) {
|
|
198
|
+
console.log(chalk_1.default.yellow((0, i18n_1.t)('depsChangeNonBlockingHint')));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const versionPageLimit = 10;
|
|
202
|
+
async function fetchVersions(appId, offset = 0, limit = versionPageLimit) {
|
|
203
|
+
const { data } = await (0, api_1.get)(`/app/${appId}/version/list?offset=${offset}&limit=${limit}`);
|
|
204
|
+
return Array.isArray(data) ? data : [];
|
|
205
|
+
}
|
|
206
|
+
async function showVersion(appId, offset) {
|
|
207
|
+
const data = await fetchVersions(appId, offset, versionPageLimit);
|
|
208
|
+
console.log((0, i18n_1.t)('offset', { offset }));
|
|
209
|
+
for (const version of data) {
|
|
210
|
+
const pkgCount = version.packages?.length || 0;
|
|
211
|
+
let packageInfo = '';
|
|
212
|
+
if (pkgCount === 0) {
|
|
213
|
+
packageInfo = 'no package';
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
packageInfo = (version.packages ?? [])
|
|
217
|
+
.slice(0, 3)
|
|
218
|
+
.map((pkg) => pkg.name)
|
|
219
|
+
.join(', ');
|
|
220
|
+
if (pkgCount > 3) {
|
|
221
|
+
packageInfo += `...and ${pkgCount - 3} more`;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
packageInfo = `[${packageInfo}]`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
console.log(`${version.id}) ${version.hash.slice(0, 8)} ${version.name} ${packageInfo}`);
|
|
228
|
+
}
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
async function listVersions(appId, interactive = true) {
|
|
232
|
+
let offset = 0;
|
|
233
|
+
while (true) {
|
|
234
|
+
const data = await showVersion(appId, offset);
|
|
235
|
+
if (!interactive) {
|
|
236
|
+
return data;
|
|
237
|
+
}
|
|
238
|
+
const cmd = await (0, utils_1.question)('page Up/page Down/Begin/Quit(U/D/B/Q)');
|
|
239
|
+
switch (cmd.toLowerCase()) {
|
|
240
|
+
case 'u':
|
|
241
|
+
offset = Math.max(0, offset - 10);
|
|
242
|
+
break;
|
|
243
|
+
case 'd':
|
|
244
|
+
offset += 10;
|
|
245
|
+
break;
|
|
246
|
+
case 'b':
|
|
247
|
+
offset = 0;
|
|
248
|
+
break;
|
|
249
|
+
case 'q':
|
|
250
|
+
return data;
|
|
251
|
+
case '':
|
|
252
|
+
return data;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async function chooseVersion(appId) {
|
|
257
|
+
let offset = 0;
|
|
258
|
+
while (true) {
|
|
259
|
+
const data = await showVersion(appId, offset);
|
|
260
|
+
if ((0, utils_1.isNonInteractive)()) {
|
|
261
|
+
throw new Error((0, i18n_1.t)('versionIdRequired'));
|
|
262
|
+
}
|
|
263
|
+
const cmd = await (0, utils_1.question)('Enter versionId or page Up/page Down/Begin(U/D/B)');
|
|
264
|
+
switch (cmd.toUpperCase()) {
|
|
265
|
+
case 'U':
|
|
266
|
+
offset = Math.max(0, offset - 10);
|
|
267
|
+
break;
|
|
268
|
+
case 'D':
|
|
269
|
+
offset += 10;
|
|
270
|
+
break;
|
|
271
|
+
case 'B':
|
|
272
|
+
offset = 0;
|
|
273
|
+
break;
|
|
274
|
+
default: {
|
|
275
|
+
const versionId = Number.parseInt(cmd, 10);
|
|
276
|
+
const v = data.find((version) => String(version.id) === String(versionId));
|
|
277
|
+
if (v) {
|
|
278
|
+
return v;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const bindVersionToPackages = async ({ appId, versionId, pkgs, rollout, dryRun, }) => {
|
|
285
|
+
if (dryRun) {
|
|
286
|
+
console.log(chalk_1.default.yellow((0, i18n_1.t)('dryRun')));
|
|
287
|
+
}
|
|
288
|
+
if (rollout !== undefined) {
|
|
289
|
+
console.log(`${(0, i18n_1.t)('rolloutConfigSet', {
|
|
290
|
+
version: versionId,
|
|
291
|
+
versions: pkgs.map((pkg) => pkg.name).join(', '),
|
|
292
|
+
rollout: rollout,
|
|
293
|
+
})}`);
|
|
294
|
+
}
|
|
295
|
+
if (!dryRun) {
|
|
296
|
+
if (pkgs.length === 1) {
|
|
297
|
+
await (0, api_1.post)(`/app/${appId}/binding`, {
|
|
298
|
+
versionId,
|
|
299
|
+
rollout,
|
|
300
|
+
packageId: pkgs[0].id,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
await (0, api_1.post)(`/app/${appId}/binding`, {
|
|
305
|
+
versionId,
|
|
306
|
+
rollout,
|
|
307
|
+
packageIds: toNumericIds(pkgs.map((pkg) => String(pkg.id))),
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
for (const pkg of pkgs) {
|
|
312
|
+
console.log(`${(0, i18n_1.t)('versionBind', {
|
|
313
|
+
version: versionId,
|
|
314
|
+
nativeVersion: pkg.name,
|
|
315
|
+
id: pkg.id,
|
|
316
|
+
})}`);
|
|
317
|
+
}
|
|
318
|
+
console.log((0, i18n_1.t)('operationComplete', { count: pkgs.length }));
|
|
319
|
+
};
|
|
320
|
+
exports.bindVersionToPackages = bindVersionToPackages;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Platform } from './types';
|
|
2
|
+
import { type HermesBaseMeta } from './utils/hermes-base';
|
|
3
|
+
export interface VersionCommandOptions {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
config?: string;
|
|
6
|
+
appKey?: string;
|
|
7
|
+
appId?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
metaInfo?: string;
|
|
11
|
+
diffFromHash?: string;
|
|
12
|
+
platform?: Platform;
|
|
13
|
+
versionId?: string;
|
|
14
|
+
versionIds?: string;
|
|
15
|
+
packageId?: string;
|
|
16
|
+
packageVersion?: string;
|
|
17
|
+
channel?: string;
|
|
18
|
+
targets?: string;
|
|
19
|
+
deploymentIds?: string;
|
|
20
|
+
releaseIds?: string;
|
|
21
|
+
releaseId?: string;
|
|
22
|
+
deploymentId?: string;
|
|
23
|
+
nativeVersionId?: string;
|
|
24
|
+
minPackageVersion?: string;
|
|
25
|
+
maxPackageVersion?: string;
|
|
26
|
+
packageVersionRange?: string;
|
|
27
|
+
rollout?: number | string;
|
|
28
|
+
dryRun?: boolean;
|
|
29
|
+
sourcemap?: string;
|
|
30
|
+
versionDeps?: Record<string, string>;
|
|
31
|
+
warnDepsChanges?: boolean;
|
|
32
|
+
/** internal: chain metadata from the bundle step (not a CLI flag) */
|
|
33
|
+
hermesBase?: HermesBaseMeta;
|
|
34
|
+
'no-interactive'?: boolean | string;
|
|
35
|
+
}
|
|
36
|
+
export { bindVersionToPackages, fetchVersions, normalizeDeps, } from './version-operations';
|
|
37
|
+
/**
|
|
38
|
+
* Content identity of the ppk's bundle for the server (bundleHash, HBC version)
|
|
39
|
+
* plus the base used to compile it, and a copy of the bundle in the local
|
|
40
|
+
* cache so it can serve as a future base without a download.
|
|
41
|
+
*/
|
|
42
|
+
declare function describePpkBundle(ppkPath: string, base?: HermesBaseMeta): Promise<Record<string, unknown>>;
|
|
43
|
+
/** Exported for tests: the version/create fields derived from a ppk + base. */
|
|
44
|
+
export declare const describePpkBundleForTests: typeof describePpkBundle;
|
|
45
|
+
export declare const versionCommands: {
|
|
46
|
+
registerPdiff: ({ args, options }: {
|
|
47
|
+
args: string[];
|
|
48
|
+
options: VersionCommandOptions;
|
|
49
|
+
}) => Promise<string>;
|
|
50
|
+
publish: ({ args, options, }: {
|
|
51
|
+
args: string[];
|
|
52
|
+
options: VersionCommandOptions;
|
|
53
|
+
}) => Promise<string>;
|
|
54
|
+
versions: ({ options }: {
|
|
55
|
+
options: VersionCommandOptions;
|
|
56
|
+
}) => Promise<void>;
|
|
57
|
+
update: ({ options }: {
|
|
58
|
+
options: VersionCommandOptions;
|
|
59
|
+
}) => Promise<void>;
|
|
60
|
+
updateVersionInfo: ({ options, }: {
|
|
61
|
+
options: VersionCommandOptions;
|
|
62
|
+
}) => Promise<void>;
|
|
63
|
+
deleteVersion: ({ options }: {
|
|
64
|
+
options: VersionCommandOptions;
|
|
65
|
+
}) => Promise<void>;
|
|
66
|
+
};
|