@huoye/app-ship 0.1.0 → 0.1.2
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 +57 -0
- package/README.md +315 -299
- package/dist/cli.js +931 -519
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +927 -515
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +141 -41
- package/dist/index.d.ts +141 -41
- package/dist/index.js +927 -515
- package/dist/index.js.map +1 -1
- package/package.json +37 -9
package/dist/index.js
CHANGED
|
@@ -5,23 +5,517 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
+
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
9
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
10
|
+
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
11
|
+
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
12
|
+
var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
|
|
13
|
+
var styles = {
|
|
14
|
+
modifier: {
|
|
15
|
+
reset: [0, 0],
|
|
16
|
+
// 21 isn't widely supported and 22 does the same thing
|
|
17
|
+
bold: [1, 22],
|
|
18
|
+
dim: [2, 22],
|
|
19
|
+
italic: [3, 23],
|
|
20
|
+
underline: [4, 24],
|
|
21
|
+
overline: [53, 55],
|
|
22
|
+
inverse: [7, 27],
|
|
23
|
+
hidden: [8, 28],
|
|
24
|
+
strikethrough: [9, 29]
|
|
25
|
+
},
|
|
26
|
+
color: {
|
|
27
|
+
black: [30, 39],
|
|
28
|
+
red: [31, 39],
|
|
29
|
+
green: [32, 39],
|
|
30
|
+
yellow: [33, 39],
|
|
31
|
+
blue: [34, 39],
|
|
32
|
+
magenta: [35, 39],
|
|
33
|
+
cyan: [36, 39],
|
|
34
|
+
white: [37, 39],
|
|
35
|
+
// Bright color
|
|
36
|
+
blackBright: [90, 39],
|
|
37
|
+
gray: [90, 39],
|
|
38
|
+
// Alias of `blackBright`
|
|
39
|
+
grey: [90, 39],
|
|
40
|
+
// Alias of `blackBright`
|
|
41
|
+
redBright: [91, 39],
|
|
42
|
+
greenBright: [92, 39],
|
|
43
|
+
yellowBright: [93, 39],
|
|
44
|
+
blueBright: [94, 39],
|
|
45
|
+
magentaBright: [95, 39],
|
|
46
|
+
cyanBright: [96, 39],
|
|
47
|
+
whiteBright: [97, 39]
|
|
48
|
+
},
|
|
49
|
+
bgColor: {
|
|
50
|
+
bgBlack: [40, 49],
|
|
51
|
+
bgRed: [41, 49],
|
|
52
|
+
bgGreen: [42, 49],
|
|
53
|
+
bgYellow: [43, 49],
|
|
54
|
+
bgBlue: [44, 49],
|
|
55
|
+
bgMagenta: [45, 49],
|
|
56
|
+
bgCyan: [46, 49],
|
|
57
|
+
bgWhite: [47, 49],
|
|
58
|
+
// Bright color
|
|
59
|
+
bgBlackBright: [100, 49],
|
|
60
|
+
bgGray: [100, 49],
|
|
61
|
+
// Alias of `bgBlackBright`
|
|
62
|
+
bgGrey: [100, 49],
|
|
63
|
+
// Alias of `bgBlackBright`
|
|
64
|
+
bgRedBright: [101, 49],
|
|
65
|
+
bgGreenBright: [102, 49],
|
|
66
|
+
bgYellowBright: [103, 49],
|
|
67
|
+
bgBlueBright: [104, 49],
|
|
68
|
+
bgMagentaBright: [105, 49],
|
|
69
|
+
bgCyanBright: [106, 49],
|
|
70
|
+
bgWhiteBright: [107, 49]
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
74
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
75
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
76
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
77
|
+
function assembleStyles() {
|
|
78
|
+
const codes = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
80
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
81
|
+
styles[styleName] = {
|
|
82
|
+
open: `\x1B[${style[0]}m`,
|
|
83
|
+
close: `\x1B[${style[1]}m`
|
|
84
|
+
};
|
|
85
|
+
group[styleName] = styles[styleName];
|
|
86
|
+
codes.set(style[0], style[1]);
|
|
87
|
+
}
|
|
88
|
+
Object.defineProperty(styles, groupName, {
|
|
89
|
+
value: group,
|
|
90
|
+
enumerable: false
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
Object.defineProperty(styles, "codes", {
|
|
94
|
+
value: codes,
|
|
95
|
+
enumerable: false
|
|
96
|
+
});
|
|
97
|
+
styles.color.close = "\x1B[39m";
|
|
98
|
+
styles.bgColor.close = "\x1B[49m";
|
|
99
|
+
styles.color.ansi = wrapAnsi16();
|
|
100
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
101
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
102
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
103
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
104
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
105
|
+
Object.defineProperties(styles, {
|
|
106
|
+
rgbToAnsi256: {
|
|
107
|
+
value(red, green, blue) {
|
|
108
|
+
if (red === green && green === blue) {
|
|
109
|
+
if (red < 8) {
|
|
110
|
+
return 16;
|
|
111
|
+
}
|
|
112
|
+
if (red > 248) {
|
|
113
|
+
return 231;
|
|
114
|
+
}
|
|
115
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
116
|
+
}
|
|
117
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
118
|
+
},
|
|
119
|
+
enumerable: false
|
|
120
|
+
},
|
|
121
|
+
hexToRgb: {
|
|
122
|
+
value(hex) {
|
|
123
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
124
|
+
if (!matches) {
|
|
125
|
+
return [0, 0, 0];
|
|
126
|
+
}
|
|
127
|
+
let [colorString] = matches;
|
|
128
|
+
if (colorString.length === 3) {
|
|
129
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
130
|
+
}
|
|
131
|
+
const integer = Number.parseInt(colorString, 16);
|
|
132
|
+
return [
|
|
133
|
+
/* eslint-disable no-bitwise */
|
|
134
|
+
integer >> 16 & 255,
|
|
135
|
+
integer >> 8 & 255,
|
|
136
|
+
integer & 255
|
|
137
|
+
/* eslint-enable no-bitwise */
|
|
138
|
+
];
|
|
139
|
+
},
|
|
140
|
+
enumerable: false
|
|
141
|
+
},
|
|
142
|
+
hexToAnsi256: {
|
|
143
|
+
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
144
|
+
enumerable: false
|
|
145
|
+
},
|
|
146
|
+
ansi256ToAnsi: {
|
|
147
|
+
value(code) {
|
|
148
|
+
if (code < 8) {
|
|
149
|
+
return 30 + code;
|
|
150
|
+
}
|
|
151
|
+
if (code < 16) {
|
|
152
|
+
return 90 + (code - 8);
|
|
153
|
+
}
|
|
154
|
+
let red;
|
|
155
|
+
let green;
|
|
156
|
+
let blue;
|
|
157
|
+
if (code >= 232) {
|
|
158
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
159
|
+
green = red;
|
|
160
|
+
blue = red;
|
|
161
|
+
} else {
|
|
162
|
+
code -= 16;
|
|
163
|
+
const remainder = code % 36;
|
|
164
|
+
red = Math.floor(code / 36) / 5;
|
|
165
|
+
green = Math.floor(remainder / 6) / 5;
|
|
166
|
+
blue = remainder % 6 / 5;
|
|
167
|
+
}
|
|
168
|
+
const value = Math.max(red, green, blue) * 2;
|
|
169
|
+
if (value === 0) {
|
|
170
|
+
return 30;
|
|
171
|
+
}
|
|
172
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
173
|
+
if (value === 2) {
|
|
174
|
+
result += 60;
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
},
|
|
178
|
+
enumerable: false
|
|
179
|
+
},
|
|
180
|
+
rgbToAnsi: {
|
|
181
|
+
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
182
|
+
enumerable: false
|
|
183
|
+
},
|
|
184
|
+
hexToAnsi: {
|
|
185
|
+
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
186
|
+
enumerable: false
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return styles;
|
|
190
|
+
}
|
|
191
|
+
var ansiStyles = assembleStyles();
|
|
192
|
+
var ansi_styles_default = ansiStyles;
|
|
193
|
+
|
|
194
|
+
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
195
|
+
import process2 from "process";
|
|
196
|
+
import os from "os";
|
|
197
|
+
import tty from "tty";
|
|
198
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
199
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
200
|
+
const position = argv.indexOf(prefix + flag);
|
|
201
|
+
const terminatorPosition = argv.indexOf("--");
|
|
202
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
203
|
+
}
|
|
204
|
+
var { env } = process2;
|
|
205
|
+
var flagForceColor;
|
|
206
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
207
|
+
flagForceColor = 0;
|
|
208
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
209
|
+
flagForceColor = 1;
|
|
210
|
+
}
|
|
211
|
+
function envForceColor() {
|
|
212
|
+
if ("FORCE_COLOR" in env) {
|
|
213
|
+
if (env.FORCE_COLOR === "true") {
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
if (env.FORCE_COLOR === "false") {
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function translateLevel(level) {
|
|
223
|
+
if (level === 0) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
level,
|
|
228
|
+
hasBasic: true,
|
|
229
|
+
has256: level >= 2,
|
|
230
|
+
has16m: level >= 3
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
234
|
+
const noFlagForceColor = envForceColor();
|
|
235
|
+
if (noFlagForceColor !== void 0) {
|
|
236
|
+
flagForceColor = noFlagForceColor;
|
|
237
|
+
}
|
|
238
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
239
|
+
if (forceColor === 0) {
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
if (sniffFlags) {
|
|
243
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
244
|
+
return 3;
|
|
245
|
+
}
|
|
246
|
+
if (hasFlag("color=256")) {
|
|
247
|
+
return 2;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
251
|
+
return 1;
|
|
252
|
+
}
|
|
253
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
const min = forceColor || 0;
|
|
257
|
+
if (env.TERM === "dumb") {
|
|
258
|
+
return min;
|
|
259
|
+
}
|
|
260
|
+
if (process2.platform === "win32") {
|
|
261
|
+
const osRelease = os.release().split(".");
|
|
262
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
263
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
264
|
+
}
|
|
265
|
+
return 1;
|
|
266
|
+
}
|
|
267
|
+
if ("CI" in env) {
|
|
268
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
|
|
269
|
+
return 3;
|
|
270
|
+
}
|
|
271
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
272
|
+
return 1;
|
|
273
|
+
}
|
|
274
|
+
return min;
|
|
275
|
+
}
|
|
276
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
277
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
278
|
+
}
|
|
279
|
+
if (env.COLORTERM === "truecolor") {
|
|
280
|
+
return 3;
|
|
281
|
+
}
|
|
282
|
+
if (env.TERM === "xterm-kitty") {
|
|
283
|
+
return 3;
|
|
284
|
+
}
|
|
285
|
+
if (env.TERM === "xterm-ghostty") {
|
|
286
|
+
return 3;
|
|
287
|
+
}
|
|
288
|
+
if (env.TERM === "wezterm") {
|
|
289
|
+
return 3;
|
|
290
|
+
}
|
|
291
|
+
if ("TERM_PROGRAM" in env) {
|
|
292
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
293
|
+
switch (env.TERM_PROGRAM) {
|
|
294
|
+
case "iTerm.app": {
|
|
295
|
+
return version >= 3 ? 3 : 2;
|
|
296
|
+
}
|
|
297
|
+
case "Apple_Terminal": {
|
|
298
|
+
return 2;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
303
|
+
return 2;
|
|
304
|
+
}
|
|
305
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
306
|
+
return 1;
|
|
307
|
+
}
|
|
308
|
+
if ("COLORTERM" in env) {
|
|
309
|
+
return 1;
|
|
310
|
+
}
|
|
311
|
+
return min;
|
|
312
|
+
}
|
|
313
|
+
function createSupportsColor(stream, options = {}) {
|
|
314
|
+
const level = _supportsColor(stream, {
|
|
315
|
+
streamIsTTY: stream && stream.isTTY,
|
|
316
|
+
...options
|
|
317
|
+
});
|
|
318
|
+
return translateLevel(level);
|
|
319
|
+
}
|
|
320
|
+
var supportsColor = {
|
|
321
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
322
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
323
|
+
};
|
|
324
|
+
var supports_color_default = supportsColor;
|
|
325
|
+
|
|
326
|
+
// node_modules/chalk/source/utilities.js
|
|
327
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
328
|
+
let index = string.indexOf(substring);
|
|
329
|
+
if (index === -1) {
|
|
330
|
+
return string;
|
|
331
|
+
}
|
|
332
|
+
const substringLength = substring.length;
|
|
333
|
+
let endIndex = 0;
|
|
334
|
+
let returnValue = "";
|
|
335
|
+
do {
|
|
336
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
337
|
+
endIndex = index + substringLength;
|
|
338
|
+
index = string.indexOf(substring, endIndex);
|
|
339
|
+
} while (index !== -1);
|
|
340
|
+
returnValue += string.slice(endIndex);
|
|
341
|
+
return returnValue;
|
|
342
|
+
}
|
|
343
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
344
|
+
let endIndex = 0;
|
|
345
|
+
let returnValue = "";
|
|
346
|
+
do {
|
|
347
|
+
const gotCR = string[index - 1] === "\r";
|
|
348
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
349
|
+
endIndex = index + 1;
|
|
350
|
+
index = string.indexOf("\n", endIndex);
|
|
351
|
+
} while (index !== -1);
|
|
352
|
+
returnValue += string.slice(endIndex);
|
|
353
|
+
return returnValue;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// node_modules/chalk/source/index.js
|
|
357
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
358
|
+
var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
|
|
359
|
+
var STYLER = /* @__PURE__ */ Symbol("STYLER");
|
|
360
|
+
var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
|
|
361
|
+
var levelMapping = [
|
|
362
|
+
"ansi",
|
|
363
|
+
"ansi",
|
|
364
|
+
"ansi256",
|
|
365
|
+
"ansi16m"
|
|
366
|
+
];
|
|
367
|
+
var styles2 = /* @__PURE__ */ Object.create(null);
|
|
368
|
+
var applyOptions = (object, options = {}) => {
|
|
369
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
370
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
371
|
+
}
|
|
372
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
373
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
374
|
+
};
|
|
375
|
+
var chalkFactory = (options) => {
|
|
376
|
+
const chalk2 = (...strings) => strings.join(" ");
|
|
377
|
+
applyOptions(chalk2, options);
|
|
378
|
+
Object.setPrototypeOf(chalk2, createChalk.prototype);
|
|
379
|
+
return chalk2;
|
|
380
|
+
};
|
|
381
|
+
function createChalk(options) {
|
|
382
|
+
return chalkFactory(options);
|
|
383
|
+
}
|
|
384
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
385
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
386
|
+
styles2[styleName] = {
|
|
387
|
+
get() {
|
|
388
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
389
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
390
|
+
return builder;
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
styles2.visible = {
|
|
395
|
+
get() {
|
|
396
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
397
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
398
|
+
return builder;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
402
|
+
if (model === "rgb") {
|
|
403
|
+
if (level === "ansi16m") {
|
|
404
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
405
|
+
}
|
|
406
|
+
if (level === "ansi256") {
|
|
407
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
408
|
+
}
|
|
409
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
410
|
+
}
|
|
411
|
+
if (model === "hex") {
|
|
412
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
413
|
+
}
|
|
414
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
415
|
+
};
|
|
416
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
417
|
+
for (const model of usedModels) {
|
|
418
|
+
styles2[model] = {
|
|
419
|
+
get() {
|
|
420
|
+
const { level } = this;
|
|
421
|
+
return function(...arguments_) {
|
|
422
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
423
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
428
|
+
styles2[bgModel] = {
|
|
429
|
+
get() {
|
|
430
|
+
const { level } = this;
|
|
431
|
+
return function(...arguments_) {
|
|
432
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
433
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
var proto = Object.defineProperties(() => {
|
|
439
|
+
}, {
|
|
440
|
+
...styles2,
|
|
441
|
+
level: {
|
|
442
|
+
enumerable: true,
|
|
443
|
+
get() {
|
|
444
|
+
return this[GENERATOR].level;
|
|
445
|
+
},
|
|
446
|
+
set(level) {
|
|
447
|
+
this[GENERATOR].level = level;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
var createStyler = (open, close, parent) => {
|
|
452
|
+
let openAll;
|
|
453
|
+
let closeAll;
|
|
454
|
+
if (parent === void 0) {
|
|
455
|
+
openAll = open;
|
|
456
|
+
closeAll = close;
|
|
457
|
+
} else {
|
|
458
|
+
openAll = parent.openAll + open;
|
|
459
|
+
closeAll = close + parent.closeAll;
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
open,
|
|
463
|
+
close,
|
|
464
|
+
openAll,
|
|
465
|
+
closeAll,
|
|
466
|
+
parent
|
|
467
|
+
};
|
|
468
|
+
};
|
|
469
|
+
var createBuilder = (self, _styler, _isEmpty) => {
|
|
470
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
471
|
+
Object.setPrototypeOf(builder, proto);
|
|
472
|
+
builder[GENERATOR] = self;
|
|
473
|
+
builder[STYLER] = _styler;
|
|
474
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
475
|
+
return builder;
|
|
476
|
+
};
|
|
477
|
+
var applyStyle = (self, string) => {
|
|
478
|
+
if (self.level <= 0 || !string) {
|
|
479
|
+
return self[IS_EMPTY] ? "" : string;
|
|
480
|
+
}
|
|
481
|
+
let styler = self[STYLER];
|
|
482
|
+
if (styler === void 0) {
|
|
483
|
+
return string;
|
|
484
|
+
}
|
|
485
|
+
const { openAll, closeAll } = styler;
|
|
486
|
+
if (string.includes("\x1B")) {
|
|
487
|
+
while (styler !== void 0) {
|
|
488
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
489
|
+
styler = styler.parent;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
const lfIndex = string.indexOf("\n");
|
|
493
|
+
if (lfIndex !== -1) {
|
|
494
|
+
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
495
|
+
}
|
|
496
|
+
return openAll + string + closeAll;
|
|
497
|
+
};
|
|
498
|
+
Object.defineProperties(createChalk.prototype, styles2);
|
|
499
|
+
var chalk = createChalk();
|
|
500
|
+
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
501
|
+
var source_default = chalk;
|
|
502
|
+
|
|
8
503
|
// src/utils/logger.ts
|
|
9
|
-
import chalk from "chalk";
|
|
10
504
|
var ConsoleLogger = class {
|
|
11
505
|
info(message) {
|
|
12
|
-
console.log(
|
|
506
|
+
console.log(source_default.blue("\u2139\uFE0F " + message));
|
|
13
507
|
}
|
|
14
508
|
success(message) {
|
|
15
|
-
console.log(
|
|
509
|
+
console.log(source_default.green("\u2705 " + message));
|
|
16
510
|
}
|
|
17
511
|
warn(message) {
|
|
18
|
-
console.log(
|
|
512
|
+
console.log(source_default.yellow("\u26A0\uFE0F " + message));
|
|
19
513
|
}
|
|
20
514
|
error(message) {
|
|
21
|
-
console.log(
|
|
515
|
+
console.log(source_default.red("\u274C " + message));
|
|
22
516
|
}
|
|
23
517
|
title(message) {
|
|
24
|
-
console.log(
|
|
518
|
+
console.log(source_default.bold.cyan("\n" + message + "\n"));
|
|
25
519
|
}
|
|
26
520
|
newLine() {
|
|
27
521
|
console.log("");
|
|
@@ -245,12 +739,7 @@ var RetryStrategy = class {
|
|
|
245
739
|
logger.warn(`${operationName} failed (Attempt ${attempt}): ${errorMessage} [${category}]`);
|
|
246
740
|
if (!this.shouldRetry(error, attempt)) {
|
|
247
741
|
logger.error(`${operationName} failed with non-retryable error: ${errorMessage}`);
|
|
248
|
-
|
|
249
|
-
success: false,
|
|
250
|
-
error,
|
|
251
|
-
totalAttempts: attempt,
|
|
252
|
-
lastError: errorMessage
|
|
253
|
-
};
|
|
742
|
+
throw error;
|
|
254
743
|
}
|
|
255
744
|
if (attempt <= this.config.maxRetries) {
|
|
256
745
|
const delayMs = this.calculateDelay(attempt - 1);
|
|
@@ -261,12 +750,7 @@ var RetryStrategy = class {
|
|
|
261
750
|
}
|
|
262
751
|
}
|
|
263
752
|
}
|
|
264
|
-
|
|
265
|
-
success: false,
|
|
266
|
-
error: lastError || new Error(`${operationName} failed after all retries`),
|
|
267
|
-
totalAttempts: attempt,
|
|
268
|
-
lastError: lastError?.message
|
|
269
|
-
};
|
|
753
|
+
throw lastError || new Error(`${operationName} failed after all retries`);
|
|
270
754
|
}
|
|
271
755
|
};
|
|
272
756
|
var DEFAULT_RETRY_CONFIG = {
|
|
@@ -460,6 +944,7 @@ async function parseHap(filePath) {
|
|
|
460
944
|
}
|
|
461
945
|
|
|
462
946
|
// src/utils/upload-manager.ts
|
|
947
|
+
var GROUPED_ARTIFACT_PLATFORMS = /* @__PURE__ */ new Set(["huawei", "xiaomi", "oppo", "vivo", "tencent"]);
|
|
463
948
|
var UploadManager = class {
|
|
464
949
|
uploaders;
|
|
465
950
|
config;
|
|
@@ -559,30 +1044,64 @@ var UploadManager = class {
|
|
|
559
1044
|
};
|
|
560
1045
|
}
|
|
561
1046
|
const files = Array.isArray(filePaths) ? filePaths : [filePaths];
|
|
562
|
-
|
|
563
|
-
|
|
1047
|
+
const tasks = [];
|
|
1048
|
+
validPlatforms.forEach((platform) => {
|
|
564
1049
|
const uploader = this.uploaders.get(platform);
|
|
565
|
-
const
|
|
566
|
-
if (
|
|
1050
|
+
const matchedFiles = files.filter((f) => uploader.canHandle(f));
|
|
1051
|
+
if (matchedFiles.length === 0) {
|
|
567
1052
|
logger.warn(`[${platform}] No compatible file found in provided files`);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
1053
|
+
} else {
|
|
1054
|
+
if (this.shouldGroupArtifacts(platform)) {
|
|
1055
|
+
const artifactSelection = this.resolveArtifactSelection(platform, matchedFiles, metadata);
|
|
1056
|
+
if (!artifactSelection) {
|
|
1057
|
+
logger.warn(`[${platform}] Failed to build grouped artifact selection`);
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
tasks.push({
|
|
1061
|
+
platform,
|
|
1062
|
+
file: this.getRepresentativeFilePath(artifactSelection),
|
|
1063
|
+
artifactSelection
|
|
1064
|
+
});
|
|
1065
|
+
} else {
|
|
1066
|
+
matchedFiles.forEach((file) => {
|
|
1067
|
+
tasks.push({ platform, file, artifactSelection: file });
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
573
1070
|
}
|
|
574
|
-
|
|
575
|
-
|
|
1071
|
+
});
|
|
1072
|
+
if (tasks.length === 0) {
|
|
1073
|
+
logger.error("No valid platform-file matches found");
|
|
1074
|
+
return {
|
|
1075
|
+
totalUploads: validPlatforms.length,
|
|
1076
|
+
successCount: 0,
|
|
1077
|
+
failureCount: validPlatforms.length,
|
|
1078
|
+
successPlatforms: [],
|
|
1079
|
+
failurePlatforms: validPlatforms,
|
|
1080
|
+
results: [],
|
|
1081
|
+
totalDurationMs: Date.now() - startTime,
|
|
1082
|
+
summary: "No compatible files found for any of the selected platforms"
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
logger.info(`Scheduled ${tasks.length} upload task(s) for ${validPlatforms.length} platform(s)`);
|
|
1086
|
+
const uploadPromises = tasks.map((task) => {
|
|
1087
|
+
logger.info(`[${task.platform}] Matched file: ${path2.basename(task.file)}`);
|
|
1088
|
+
return this.uploadToPlatform(
|
|
1089
|
+
task.platform,
|
|
1090
|
+
task.file,
|
|
1091
|
+
config,
|
|
1092
|
+
metadata,
|
|
1093
|
+
task.artifactSelection
|
|
1094
|
+
);
|
|
576
1095
|
});
|
|
577
1096
|
const results = await Promise.all(uploadPromises);
|
|
578
|
-
const report = this.aggregateResults(results,
|
|
1097
|
+
const report = this.aggregateResults(results, tasks.length, startTime);
|
|
579
1098
|
this.printReport(report);
|
|
580
1099
|
return report;
|
|
581
1100
|
}
|
|
582
1101
|
/**
|
|
583
1102
|
* 上传到单个平台
|
|
584
1103
|
*/
|
|
585
|
-
async uploadToPlatform(platform, filePath, config, metadata) {
|
|
1104
|
+
async uploadToPlatform(platform, filePath, config, metadata, artifactSelection = filePath) {
|
|
586
1105
|
if (this.config.cancellationToken?.isCancelled) {
|
|
587
1106
|
logger.warn(`[${platform.toUpperCase()}] Upload skipped due to cancellation`);
|
|
588
1107
|
return {
|
|
@@ -603,25 +1122,30 @@ var UploadManager = class {
|
|
|
603
1122
|
if (this.config.verbose) {
|
|
604
1123
|
logger.info(`[${platform.toUpperCase()}] Starting upload...`);
|
|
605
1124
|
}
|
|
1125
|
+
const effectiveMetadata = {
|
|
1126
|
+
...metadata,
|
|
1127
|
+
artifactPath: artifactSelection
|
|
1128
|
+
};
|
|
1129
|
+
await this.validateArtifactSelection(platform, artifactSelection, effectiveMetadata);
|
|
606
1130
|
const pkgInfo = await parsePackageInfo(filePath, {
|
|
607
|
-
androidSdkPath:
|
|
1131
|
+
androidSdkPath: effectiveMetadata.globalSettings?.androidSdkPath
|
|
608
1132
|
});
|
|
609
1133
|
if (pkgInfo) {
|
|
610
1134
|
if (pkgInfo.versionName) {
|
|
611
|
-
|
|
1135
|
+
effectiveMetadata.version = pkgInfo.versionName;
|
|
612
1136
|
}
|
|
613
1137
|
if (pkgInfo.versionCode) {
|
|
614
|
-
|
|
1138
|
+
effectiveMetadata.buildNumber = pkgInfo.versionCode;
|
|
615
1139
|
}
|
|
616
1140
|
if (pkgInfo.packageName) {
|
|
617
1141
|
;
|
|
618
|
-
|
|
1142
|
+
effectiveMetadata.packageName = pkgInfo.packageName;
|
|
619
1143
|
}
|
|
620
1144
|
logger.info(
|
|
621
|
-
`[${platform.toUpperCase()}] \u5DF2\u6821\u51C6\u7248\u672C\u4FE1\u606F: v${
|
|
1145
|
+
`[${platform.toUpperCase()}] \u5DF2\u6821\u51C6\u7248\u672C\u4FE1\u606F: v${effectiveMetadata.version}+${effectiveMetadata.buildNumber}`
|
|
622
1146
|
);
|
|
623
1147
|
}
|
|
624
|
-
const result = await uploader.upload(filePath, config,
|
|
1148
|
+
const result = await uploader.upload(filePath, config, effectiveMetadata);
|
|
625
1149
|
return result;
|
|
626
1150
|
} catch (error) {
|
|
627
1151
|
const errorMessage = error.message || String(error);
|
|
@@ -634,6 +1158,85 @@ var UploadManager = class {
|
|
|
634
1158
|
};
|
|
635
1159
|
}
|
|
636
1160
|
}
|
|
1161
|
+
shouldGroupArtifacts(platform) {
|
|
1162
|
+
return GROUPED_ARTIFACT_PLATFORMS.has(platform);
|
|
1163
|
+
}
|
|
1164
|
+
resolveArtifactSelection(platform, matchedFiles, metadata) {
|
|
1165
|
+
const explicitArtifacts = metadata.platformArtifacts?.[platform];
|
|
1166
|
+
if (explicitArtifacts) {
|
|
1167
|
+
if (typeof explicitArtifacts === "string") {
|
|
1168
|
+
return explicitArtifacts;
|
|
1169
|
+
}
|
|
1170
|
+
if (Object.keys(explicitArtifacts).length > 0) {
|
|
1171
|
+
return explicitArtifacts;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (matchedFiles.length === 0) {
|
|
1175
|
+
return null;
|
|
1176
|
+
}
|
|
1177
|
+
if (matchedFiles.length === 1) {
|
|
1178
|
+
return matchedFiles[0];
|
|
1179
|
+
}
|
|
1180
|
+
return this.buildArtifactMapFromFiles(matchedFiles);
|
|
1181
|
+
}
|
|
1182
|
+
buildArtifactMapFromFiles(files) {
|
|
1183
|
+
return files.reduce(
|
|
1184
|
+
(acc, filePath, index) => {
|
|
1185
|
+
acc[this.inferArtifactKey(filePath, index)] = filePath;
|
|
1186
|
+
return acc;
|
|
1187
|
+
},
|
|
1188
|
+
{}
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
inferArtifactKey(filePath, index) {
|
|
1192
|
+
const fileName = path2.basename(filePath).toLowerCase();
|
|
1193
|
+
if (fileName.includes("arm64-v8a")) return "arm64-v8a";
|
|
1194
|
+
if (fileName.includes("armeabi-v7a")) return "armeabi-v7a";
|
|
1195
|
+
if (fileName.includes("x86_64")) return "x86_64";
|
|
1196
|
+
if (fileName.includes("universal")) return "universal";
|
|
1197
|
+
return `artifact_${index + 1}`;
|
|
1198
|
+
}
|
|
1199
|
+
getRepresentativeFilePath(artifactSelection) {
|
|
1200
|
+
if (typeof artifactSelection === "string") {
|
|
1201
|
+
return artifactSelection;
|
|
1202
|
+
}
|
|
1203
|
+
return Object.values(artifactSelection)[0];
|
|
1204
|
+
}
|
|
1205
|
+
async validateArtifactSelection(platform, artifactSelection, metadata) {
|
|
1206
|
+
if (typeof artifactSelection === "string") {
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
const artifactPaths = Object.values(artifactSelection).filter(Boolean);
|
|
1210
|
+
if (artifactPaths.length < 2) {
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
const parsedInfos = await Promise.all(
|
|
1214
|
+
artifactPaths.map(
|
|
1215
|
+
(artifactPath) => parsePackageInfo(artifactPath, {
|
|
1216
|
+
androidSdkPath: metadata.globalSettings?.androidSdkPath
|
|
1217
|
+
})
|
|
1218
|
+
)
|
|
1219
|
+
);
|
|
1220
|
+
const availableInfos = parsedInfos.filter((info) => !!info);
|
|
1221
|
+
if (availableInfos.length < 2) {
|
|
1222
|
+
logger.warn(
|
|
1223
|
+
`[${platform.toUpperCase()}] Unable to fully validate multi-artifact package info; continuing with upload.`
|
|
1224
|
+
);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
const [baseInfo, ...restInfos] = availableInfos;
|
|
1228
|
+
for (const info of restInfos) {
|
|
1229
|
+
if (baseInfo?.packageName && info?.packageName && baseInfo.packageName !== info.packageName) {
|
|
1230
|
+
throw new Error("\u53CC\u5305\u4E0A\u4F20\u5931\u8D25\uFF1A\u6240\u9009\u5B89\u88C5\u5305\u7684 packageName \u4E0D\u4E00\u81F4");
|
|
1231
|
+
}
|
|
1232
|
+
if (baseInfo?.versionName && info?.versionName && baseInfo.versionName !== info.versionName) {
|
|
1233
|
+
throw new Error("\u53CC\u5305\u4E0A\u4F20\u5931\u8D25\uFF1A\u6240\u9009\u5B89\u88C5\u5305\u7684 versionName \u4E0D\u4E00\u81F4");
|
|
1234
|
+
}
|
|
1235
|
+
if (baseInfo?.versionCode && info?.versionCode && baseInfo.versionCode !== info.versionCode) {
|
|
1236
|
+
throw new Error("\u53CC\u5305\u4E0A\u4F20\u5931\u8D25\uFF1A\u6240\u9009\u5B89\u88C5\u5305\u7684 versionCode \u4E0D\u4E00\u81F4");
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
637
1240
|
/**
|
|
638
1241
|
* 聚合上传结果
|
|
639
1242
|
*/
|
|
@@ -1099,27 +1702,39 @@ var HuaweiUploader = class _HuaweiUploader {
|
|
|
1099
1702
|
clientId,
|
|
1100
1703
|
appId
|
|
1101
1704
|
};
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1705
|
+
const artifacts = typeof metadata.artifactPath === "object" ? metadata.artifactPath : { universal: filePath || metadata.artifactPath || "" };
|
|
1706
|
+
logger.info(`[Huawei] \u5904\u7406\u4EA7\u7269\u6570\u91CF: ${Object.keys(artifacts).length}`);
|
|
1707
|
+
const uploadResults = [];
|
|
1708
|
+
const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {
|
|
1709
|
+
if (!p || !fs5.existsSync(p)) return;
|
|
1710
|
+
const currentSuffix = path3.extname(p).substring(1);
|
|
1711
|
+
logger.info(`[Huawei] \u6B63\u5728\u4E0A\u4F20 ${abi} \u5305: ${path3.basename(p)}`);
|
|
1712
|
+
const uploadInfo = await retryStrategy.execute(
|
|
1713
|
+
() => this.getUploadUrl(ctx, currentSuffix),
|
|
1714
|
+
`Huawei get upload URL for ${abi}`
|
|
1715
|
+
);
|
|
1716
|
+
if (!uploadInfo.success || !uploadInfo.data) {
|
|
1717
|
+
throw uploadInfo.error || new Error(`Failed to get upload URL for ${abi}`);
|
|
1718
|
+
}
|
|
1719
|
+
const uploadFileRes = await retryStrategy.execute(
|
|
1720
|
+
() => this.executeUploadRequest(uploadInfo.data.uploadUrl, uploadInfo.data.authCode, p),
|
|
1721
|
+
`Huawei upload file for ${abi}`
|
|
1722
|
+
);
|
|
1723
|
+
if (!uploadFileRes.success || !uploadFileRes.data || uploadFileRes.data.length === 0) {
|
|
1724
|
+
throw uploadFileRes.error || new Error(`File upload failed for ${abi}`);
|
|
1725
|
+
}
|
|
1726
|
+
uploadResults.push({
|
|
1727
|
+
fileName: path3.basename(p),
|
|
1728
|
+
fileDestUrl: uploadFileRes.data[0].fileDestUrl
|
|
1729
|
+
});
|
|
1730
|
+
});
|
|
1731
|
+
await Promise.all(uploadPromises);
|
|
1732
|
+
if (uploadResults.length === 0) {
|
|
1733
|
+
throw new Error("No files were successfully uploaded");
|
|
1118
1734
|
}
|
|
1119
|
-
|
|
1120
|
-
logger.info("Linking file to app...");
|
|
1735
|
+
logger.info(`[Huawei] \u6B63\u5728\u5173\u8054 ${uploadResults.length} \u4E2A\u6587\u4EF6\u5230\u5E94\u7528...`);
|
|
1121
1736
|
const updateInfoResult = await retryStrategy.execute(
|
|
1122
|
-
() => this.updateAppFileInfo(ctx,
|
|
1737
|
+
() => this.updateAppFileInfo(ctx, uploadResults, filePath),
|
|
1123
1738
|
"Huawei update file info"
|
|
1124
1739
|
);
|
|
1125
1740
|
if (!updateInfoResult.success) {
|
|
@@ -1323,14 +1938,17 @@ var HuaweiUploader = class _HuaweiUploader {
|
|
|
1323
1938
|
throw new Error("Upload succeeded but fileDestUrl not found in response");
|
|
1324
1939
|
}
|
|
1325
1940
|
/** 更新应用文件信息 */
|
|
1326
|
-
async updateAppFileInfo(ctx,
|
|
1327
|
-
const
|
|
1328
|
-
const fileType =
|
|
1941
|
+
async updateAppFileInfo(ctx, files, anyFilePath) {
|
|
1942
|
+
const hasAab = files.some((f) => f.fileName.toLowerCase().endsWith(".aab"));
|
|
1943
|
+
const fileType = hasAab ? 7 /* AAB */ : 5 /* APP_PACKAGE */;
|
|
1329
1944
|
const res = await axios2.put(
|
|
1330
1945
|
`${ctx.apiRoot}/app-file-info`,
|
|
1331
1946
|
{
|
|
1332
1947
|
fileType,
|
|
1333
|
-
files:
|
|
1948
|
+
files: files.map((f) => ({
|
|
1949
|
+
fileName: f.fileName,
|
|
1950
|
+
fileDestUrl: f.fileDestUrl
|
|
1951
|
+
}))
|
|
1334
1952
|
},
|
|
1335
1953
|
{
|
|
1336
1954
|
params: { appId: ctx.appId },
|
|
@@ -1500,6 +2118,7 @@ var HuaweiUploader = class _HuaweiUploader {
|
|
|
1500
2118
|
|
|
1501
2119
|
// src/adapters/xiaomi_uploader.ts
|
|
1502
2120
|
import fs6 from "fs-extra";
|
|
2121
|
+
import path4 from "path";
|
|
1503
2122
|
import axios3 from "axios";
|
|
1504
2123
|
import FormData3 from "form-data";
|
|
1505
2124
|
import crypto3 from "crypto";
|
|
@@ -1750,80 +2369,39 @@ ${lines.join("\n")}
|
|
|
1750
2369
|
const xiaomiConfig = config.publish?.xiaomi;
|
|
1751
2370
|
const { userName, privateKey, publicKeyPath } = xiaomiConfig.auth;
|
|
1752
2371
|
const updateDesc = metadata.changelog || xiaomiConfig?.description || "App Update";
|
|
1753
|
-
const
|
|
1754
|
-
if (!fs6.existsSync(filePath)) {
|
|
1755
|
-
return {
|
|
1756
|
-
platform: "xiaomi",
|
|
1757
|
-
success: false,
|
|
1758
|
-
message: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`
|
|
1759
|
-
};
|
|
1760
|
-
}
|
|
2372
|
+
const artifacts = typeof metadata.artifactPath === "object" ? metadata.artifactPath : { universal: filePath || (typeof metadata.artifactPath === "string" ? metadata.artifactPath : "") };
|
|
1761
2373
|
const resolvedPublicKey = await this.resolvePublicKey(publicKeyPath);
|
|
1762
2374
|
if (!resolvedPublicKey) {
|
|
1763
|
-
|
|
1764
|
-
platform: "xiaomi",
|
|
1765
|
-
success: false,
|
|
1766
|
-
message: "\u65E0\u6CD5\u83B7\u53D6 RSA \u516C\u94A5: publicKeyPath \u672A\u63D0\u4F9B\u6216\u6587\u4EF6\u4E0D\u5B58\u5728"
|
|
1767
|
-
};
|
|
1768
|
-
}
|
|
1769
|
-
const packageName = xiaomiConfig.packageName || this.inferPackageName(filePath);
|
|
1770
|
-
if (!packageName) {
|
|
1771
|
-
return {
|
|
1772
|
-
platform: "xiaomi",
|
|
1773
|
-
success: false,
|
|
1774
|
-
message: "\u7F3A\u5C11 packageName \u914D\u7F6E, \u4E14\u65E0\u6CD5\u4ECE\u6587\u4EF6\u540D\u63A8\u65AD\u5E94\u7528\u5305\u540D"
|
|
1775
|
-
};
|
|
1776
|
-
}
|
|
1777
|
-
const appName = xiaomiConfig.appName || this.inferAppName(packageName);
|
|
1778
|
-
if (!appName) {
|
|
1779
|
-
return {
|
|
1780
|
-
platform: "xiaomi",
|
|
1781
|
-
success: false,
|
|
1782
|
-
message: "\u7F3A\u5C11 appName \u914D\u7F6E, \u4E14\u65E0\u6CD5\u4ECE\u5305\u540D\u63A8\u65AD\u5E94\u7528\u540D\u79F0"
|
|
1783
|
-
};
|
|
2375
|
+
throw new Error("\u65E0\u6CD5\u83B7\u53D6 RSA \u516C\u94A5");
|
|
1784
2376
|
}
|
|
1785
|
-
logger.info("\u5F00\u59CB\u4E0A\u4F20\u5230\u5C0F\u7C73\u5E94\u7528\u5546\u5E97...");
|
|
1786
|
-
logger.info(`\u6587\u4EF6: ${filePath}`);
|
|
1787
|
-
logger.info(`\u5305\u540D: ${packageName}`);
|
|
1788
|
-
logger.info(`\u5E94\u7528\u540D: ${appName}`);
|
|
1789
2377
|
const publicKeyObj = this.extractPublicKey(resolvedPublicKey);
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
logger.info("\u6B63\u5728\u67E5\u8BE2\u5E94\u7528\u4FE1\u606F...");
|
|
1795
|
-
const status = await this.queryAppStatus(userName, packageName, privateKey, publicKeyObj);
|
|
1796
|
-
uploadType = status.type;
|
|
1797
|
-
existingAppInfo = status.appInfo;
|
|
1798
|
-
} else {
|
|
1799
|
-
uploadType = configUploadType;
|
|
1800
|
-
}
|
|
1801
|
-
const uploadTypeDesc = uploadType === "update" ? "\u5E94\u7528\u66F4\u65B0 (synchroType=1)" : "\u65B0\u589E\u5E94\u7528 (synchroType=0)";
|
|
1802
|
-
logger.info(`\u4E0A\u4F20\u7C7B\u578B: ${uploadTypeDesc}`);
|
|
1803
|
-
if (uploadType === "new" && xiaomiConfig.uploadType === "new") {
|
|
1804
|
-
const missing = [];
|
|
1805
|
-
if (xiaomiConfig.category == null) missing.push("category (\u5206\u7C7BID)");
|
|
1806
|
-
if (!xiaomiConfig.desc) missing.push("desc (\u5E94\u7528\u4ECB\u7ECD)");
|
|
1807
|
-
if (missing.length > 0) {
|
|
1808
|
-
return {
|
|
1809
|
-
platform: "xiaomi",
|
|
1810
|
-
success: false,
|
|
1811
|
-
message: `\u9996\u6B21\u63D0\u5BA1\u6A21\u5F0F\u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5: ${missing.join(", ")}\u3002\u8BF7\u5728\u540E\u53F0\u8865\u5168\u6216\u5728\u914D\u7F6E\u4E2D\u6DFB\u52A0\u3002`
|
|
1812
|
-
};
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
2378
|
+
const anyPath = Object.values(artifacts)[0];
|
|
2379
|
+
const packageName = xiaomiConfig.packageName || this.inferPackageName(anyPath);
|
|
2380
|
+
if (!packageName) throw new Error("\u7F3A\u5C11 packageName");
|
|
2381
|
+
const appName = xiaomiConfig.appName || this.inferAppName(packageName);
|
|
1815
2382
|
try {
|
|
1816
|
-
|
|
2383
|
+
logger.info(`\u5F00\u59CB\u4E0A\u4F20\u5230\u5C0F\u7C73\u5E94\u7528\u5546\u5E97 (\u5305\u542B ${Object.keys(artifacts).length} \u4E2A\u5305)...`);
|
|
2384
|
+
let uploadType = xiaomiConfig.uploadType || "auto";
|
|
2385
|
+
let finalUploadType;
|
|
2386
|
+
let existingAppInfo = null;
|
|
2387
|
+
if (uploadType === "auto") {
|
|
2388
|
+
const status = await this.queryAppStatus(userName, packageName, privateKey, publicKeyObj);
|
|
2389
|
+
finalUploadType = status.type;
|
|
2390
|
+
existingAppInfo = status.appInfo;
|
|
2391
|
+
} else {
|
|
2392
|
+
finalUploadType = uploadType;
|
|
2393
|
+
}
|
|
2394
|
+
const retryStrategy = createUploadRetryStrategy(config.retry);
|
|
1817
2395
|
const result = await retryStrategy.execute(
|
|
1818
2396
|
() => this.performUpload({
|
|
1819
|
-
|
|
2397
|
+
artifacts,
|
|
1820
2398
|
userName,
|
|
1821
2399
|
privateKey,
|
|
1822
2400
|
publicKey: resolvedPublicKey,
|
|
2401
|
+
uploadType: finalUploadType,
|
|
1823
2402
|
packageName,
|
|
1824
|
-
appName,
|
|
2403
|
+
appName: appName || "",
|
|
1825
2404
|
updateDesc,
|
|
1826
|
-
uploadType,
|
|
1827
2405
|
category: xiaomiConfig.category || existingAppInfo?.category,
|
|
1828
2406
|
keyWords: xiaomiConfig.keyWords || existingAppInfo?.keyWords,
|
|
1829
2407
|
desc: xiaomiConfig.desc || existingAppInfo?.desc,
|
|
@@ -1833,50 +2411,19 @@ ${lines.join("\n")}
|
|
|
1833
2411
|
}),
|
|
1834
2412
|
"Xiaomi push upload"
|
|
1835
2413
|
);
|
|
1836
|
-
if (!result.success) {
|
|
1837
|
-
throw result.error || new Error("Upload failed");
|
|
1838
|
-
}
|
|
1839
|
-
logger.success("\u4E0A\u4F20\u5230\u5C0F\u7C73\u5E94\u7528\u5546\u5E97\u6210\u529F!");
|
|
1840
2414
|
return {
|
|
1841
2415
|
platform: "xiaomi",
|
|
1842
2416
|
success: true,
|
|
1843
|
-
message: "\u4E0A\u4F20\u6210\u529F
|
|
1844
|
-
data: result.data,
|
|
2417
|
+
message: "\u4E0A\u4F20\u6210\u529F",
|
|
1845
2418
|
consoleUrl: "https://dev.mi.com/distribute/app/details"
|
|
1846
2419
|
};
|
|
1847
2420
|
} catch (error) {
|
|
1848
|
-
logger.error(`\u4E0A\u4F20\
|
|
1849
|
-
|
|
1850
|
-
logger.info(`\u9519\u8BEF\u8BE6\u60C5: ${JSON.stringify(error.response.data)}`);
|
|
1851
|
-
}
|
|
1852
|
-
return {
|
|
1853
|
-
platform: "xiaomi",
|
|
1854
|
-
success: false,
|
|
1855
|
-
message: error.message,
|
|
1856
|
-
error
|
|
1857
|
-
};
|
|
2421
|
+
logger.error(`\u5C0F\u7C73\u4E0A\u4F20\u5931\u8D25: ${error.message}`);
|
|
2422
|
+
return { platform: "xiaomi", success: false, message: error.message, error };
|
|
1858
2423
|
}
|
|
1859
2424
|
}
|
|
1860
|
-
/**
|
|
1861
|
-
* 执行实际的上传操作
|
|
1862
|
-
*/
|
|
1863
2425
|
async performUpload(params) {
|
|
1864
|
-
const {
|
|
1865
|
-
filePath,
|
|
1866
|
-
userName,
|
|
1867
|
-
privateKey,
|
|
1868
|
-
publicKey,
|
|
1869
|
-
packageName,
|
|
1870
|
-
appName,
|
|
1871
|
-
updateDesc,
|
|
1872
|
-
uploadType,
|
|
1873
|
-
category,
|
|
1874
|
-
keyWords,
|
|
1875
|
-
desc,
|
|
1876
|
-
brief,
|
|
1877
|
-
privacyUrl,
|
|
1878
|
-
assets
|
|
1879
|
-
} = params;
|
|
2426
|
+
const { artifacts, userName, privateKey, publicKey, packageName, appName, updateDesc, uploadType, category, keyWords, desc, brief, privacyUrl, assets } = params;
|
|
1880
2427
|
const publicKeyObj = this.extractPublicKey(publicKey);
|
|
1881
2428
|
const requestData = this.buildRequestData({
|
|
1882
2429
|
userName,
|
|
@@ -1890,67 +2437,55 @@ ${lines.join("\n")}
|
|
|
1890
2437
|
brief,
|
|
1891
2438
|
privacyUrl
|
|
1892
2439
|
});
|
|
1893
|
-
logger.info("RequestData \u5DF2\u6784\u5EFA");
|
|
1894
|
-
logger.info(`RequestData: ${requestData}`);
|
|
1895
2440
|
const requestDataMD5 = this.calculateStringMD5(requestData);
|
|
1896
|
-
|
|
1897
|
-
|
|
2441
|
+
let mainPath;
|
|
2442
|
+
let secondPath = void 0;
|
|
2443
|
+
const artifactEntries = Object.entries(artifacts);
|
|
2444
|
+
const arm64 = artifactEntries.find(([abi]) => abi === "arm64-v8a");
|
|
2445
|
+
const arm32 = artifactEntries.find(([abi]) => abi === "armeabi-v7a");
|
|
2446
|
+
if (arm64 && arm32) {
|
|
2447
|
+
mainPath = arm64[1];
|
|
2448
|
+
secondPath = arm32[1];
|
|
2449
|
+
logger.info(`[Xiaomi] \u8BC6\u522B\u5230\u591A\u67B6\u6784\u5206\u5305: \u4E3B\u5305(64\u4F4D)=${path4.basename(mainPath)}, \u6B21\u5305(32\u4F4D)=${path4.basename(secondPath)}`);
|
|
2450
|
+
} else {
|
|
2451
|
+
mainPath = artifactEntries[0][1];
|
|
2452
|
+
if (artifactEntries.length > 1) {
|
|
2453
|
+
secondPath = artifactEntries[1][1];
|
|
2454
|
+
logger.info(`[Xiaomi] \u8BC6\u522B\u5230\u591A\u4E2A\u5305\uFF08\u975E\u6807\u51C6\u540D\uFF09\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u987A\u5E8F: \u4E3B\u5305=${path4.basename(mainPath)}, \u6B21\u5305=${path4.basename(secondPath)}`);
|
|
2455
|
+
} else {
|
|
2456
|
+
logger.info(`[Xiaomi] \u4F7F\u7528\u5355\u5305\u6A21\u5F0F: ${path4.basename(mainPath)}`);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
const mainMD5 = await this.calculateFileMD5(mainPath);
|
|
1898
2460
|
const extraSigItems = [];
|
|
1899
|
-
|
|
2461
|
+
if (secondPath) {
|
|
2462
|
+
const secondMD5 = await this.calculateFileMD5(secondPath);
|
|
2463
|
+
extraSigItems.push({ name: "secondApk", hash: secondMD5 });
|
|
2464
|
+
}
|
|
1900
2465
|
if (assets?.icon && fs6.existsSync(assets.icon)) {
|
|
1901
|
-
|
|
1902
|
-
const iconMD5 = await this.calculateFileMD5(iconPath);
|
|
1903
|
-
extraSigItems.push({ name: "icon", hash: iconMD5 });
|
|
1904
|
-
}
|
|
1905
|
-
const screenshotPaths = [];
|
|
1906
|
-
if (assets?.screenshots) {
|
|
1907
|
-
for (let i = 0; i < assets.screenshots.length && i < 4; i++) {
|
|
1908
|
-
const ssPath = assets.screenshots[i];
|
|
1909
|
-
if (fs6.existsSync(ssPath)) {
|
|
1910
|
-
screenshotPaths.push(ssPath);
|
|
1911
|
-
const ssMD5 = await this.calculateFileMD5(ssPath);
|
|
1912
|
-
extraSigItems.push({ name: `screenshot_${i + 1}`, hash: ssMD5 });
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
2466
|
+
extraSigItems.push({ name: "icon", hash: await this.calculateFileMD5(assets.icon) });
|
|
1915
2467
|
}
|
|
1916
|
-
const sig = this.generateUploadSIG(
|
|
1917
|
-
requestDataMD5,
|
|
1918
|
-
apkFileMD5,
|
|
1919
|
-
privateKey,
|
|
1920
|
-
publicKeyObj,
|
|
1921
|
-
extraSigItems.length > 0 ? extraSigItems : void 0
|
|
1922
|
-
);
|
|
1923
|
-
logger.info("SIG \u7B7E\u540D\u5DF2\u751F\u6210");
|
|
2468
|
+
const sig = this.generateUploadSIG(requestDataMD5, mainMD5, privateKey, publicKeyObj, extraSigItems);
|
|
1924
2469
|
const form = new FormData3();
|
|
1925
2470
|
form.append("RequestData", requestData);
|
|
1926
2471
|
form.append("SIG", sig);
|
|
1927
|
-
form.append("apk", fs6.createReadStream(
|
|
1928
|
-
if (
|
|
1929
|
-
form.append("
|
|
1930
|
-
logger.info(`\u9644\u52A0 icon: ${iconPath}`);
|
|
2472
|
+
form.append("apk", fs6.createReadStream(mainPath));
|
|
2473
|
+
if (secondPath) {
|
|
2474
|
+
form.append("secondApk", fs6.createReadStream(secondPath));
|
|
1931
2475
|
}
|
|
1932
|
-
|
|
1933
|
-
form.append(
|
|
1934
|
-
logger.info(`\u9644\u52A0 screenshot_${i + 1}: ${screenshotPaths[i]}`);
|
|
2476
|
+
if (assets?.icon && fs6.existsSync(assets.icon)) {
|
|
2477
|
+
form.append("icon", fs6.createReadStream(assets.icon));
|
|
1935
2478
|
}
|
|
1936
|
-
logger.info(`POST ${_XiaomiUploader.PUSH_API}`);
|
|
1937
2479
|
const response = await axios3.post(_XiaomiUploader.PUSH_API, form, {
|
|
1938
|
-
headers:
|
|
1939
|
-
...form.getHeaders()
|
|
1940
|
-
},
|
|
2480
|
+
headers: form.getHeaders(),
|
|
1941
2481
|
maxContentLength: Infinity,
|
|
1942
2482
|
maxBodyLength: Infinity,
|
|
1943
|
-
timeout:
|
|
1944
|
-
// 60 秒请求超时
|
|
2483
|
+
timeout: 12e4
|
|
1945
2484
|
});
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
if (data?.result !== 0) {
|
|
1949
|
-
const errMsg = data?.message || data?.msg || JSON.stringify(data);
|
|
1950
|
-
throw new Error(`\u5C0F\u7C73 API \u8FD4\u56DE\u9519\u8BEF (result=${data?.result}): ${errMsg}`);
|
|
2485
|
+
if (response.data?.result !== 0) {
|
|
2486
|
+
throw new Error(`\u5C0F\u7C73 API \u9519\u8BEF: ${response.data?.message || JSON.stringify(response.data)}`);
|
|
1951
2487
|
}
|
|
1952
|
-
|
|
1953
|
-
return data;
|
|
2488
|
+
return response.data;
|
|
1954
2489
|
}
|
|
1955
2490
|
/**
|
|
1956
2491
|
* 解析公钥: 优先使用内容字段, 其次从文件路径读取
|
|
@@ -1992,7 +2527,7 @@ ${lines.join("\n")}
|
|
|
1992
2527
|
|
|
1993
2528
|
// src/adapters/apple_store_uploader.ts
|
|
1994
2529
|
import fs7 from "fs-extra";
|
|
1995
|
-
import
|
|
2530
|
+
import path5 from "path";
|
|
1996
2531
|
import { exec as exec2 } from "child_process";
|
|
1997
2532
|
import { promisify as promisify2 } from "util";
|
|
1998
2533
|
import axios4 from "axios";
|
|
@@ -2158,7 +2693,7 @@ var AppleStoreUploader = class {
|
|
|
2158
2693
|
appPassword,
|
|
2159
2694
|
"-showTransferRate"
|
|
2160
2695
|
].join(" ");
|
|
2161
|
-
logger.info(`[Transporter] Uploading: ${
|
|
2696
|
+
logger.info(`[Transporter] Uploading: ${path5.basename(ipaPath)}`);
|
|
2162
2697
|
try {
|
|
2163
2698
|
const { stdout, stderr } = await execAsync(command, {
|
|
2164
2699
|
timeout: 30 * 60 * 1e3,
|
|
@@ -2209,7 +2744,7 @@ Stderr: ${error.stderr || ""}`);
|
|
|
2209
2744
|
});
|
|
2210
2745
|
command = innerArgs.join(" ");
|
|
2211
2746
|
}
|
|
2212
|
-
logger.info(`[altool] Uploading: ${
|
|
2747
|
+
logger.info(`[altool] Uploading: ${path5.basename(ipaPath)}`);
|
|
2213
2748
|
logger.info(`[altool] Command prefix: ${tool.command}`);
|
|
2214
2749
|
try {
|
|
2215
2750
|
const { stdout, stderr } = await execAsync(command, {
|
|
@@ -2793,7 +3328,7 @@ var TestFlightUploader = class _TestFlightUploader {
|
|
|
2793
3328
|
|
|
2794
3329
|
// src/adapters/adhoc_uploader.ts
|
|
2795
3330
|
import fs9 from "fs-extra";
|
|
2796
|
-
import
|
|
3331
|
+
import path6 from "path";
|
|
2797
3332
|
import { execSync } from "child_process";
|
|
2798
3333
|
var AdHocUploader = class {
|
|
2799
3334
|
name = "AdHoc";
|
|
@@ -2926,8 +3461,8 @@ var AdHocUploader = class {
|
|
|
2926
3461
|
* @param changelog 更新日志
|
|
2927
3462
|
*/
|
|
2928
3463
|
async createManifest(ipaPath, version, bundleId, changelog) {
|
|
2929
|
-
const ipaFileName =
|
|
2930
|
-
const appName = bundleId ||
|
|
3464
|
+
const ipaFileName = path6.basename(ipaPath);
|
|
3465
|
+
const appName = bundleId || path6.parse(ipaFileName).name;
|
|
2931
3466
|
const ipaUrl = `itms-services://?action=download-manifest&url=https://your-distribution-server.com/manifests/${ipaFileName}.plist`;
|
|
2932
3467
|
const manifestContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
2933
3468
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -2986,14 +3521,14 @@ var AdHocUploader = class {
|
|
|
2986
3521
|
*/
|
|
2987
3522
|
async setupDistributionDirectory(ipaPath, manifestPath) {
|
|
2988
3523
|
const projectRoot = process.cwd();
|
|
2989
|
-
const distributionDir =
|
|
3524
|
+
const distributionDir = path6.join(projectRoot, "build", "adhoc-distribution");
|
|
2990
3525
|
await fs9.ensureDir(distributionDir);
|
|
2991
|
-
await fs9.ensureDir(
|
|
2992
|
-
await fs9.ensureDir(
|
|
2993
|
-
await fs9.ensureDir(
|
|
2994
|
-
const ipaFileName =
|
|
2995
|
-
await fs9.copy(ipaPath,
|
|
2996
|
-
await fs9.copy(manifestPath,
|
|
3526
|
+
await fs9.ensureDir(path6.join(distributionDir, "apps"));
|
|
3527
|
+
await fs9.ensureDir(path6.join(distributionDir, "manifests"));
|
|
3528
|
+
await fs9.ensureDir(path6.join(distributionDir, "icons"));
|
|
3529
|
+
const ipaFileName = path6.basename(ipaPath);
|
|
3530
|
+
await fs9.copy(ipaPath, path6.join(distributionDir, "apps", ipaFileName));
|
|
3531
|
+
await fs9.copy(manifestPath, path6.join(distributionDir, "manifests", `${ipaFileName}.plist`));
|
|
2997
3532
|
logger.info(`Distribution directory: ${distributionDir}`);
|
|
2998
3533
|
return distributionDir;
|
|
2999
3534
|
}
|
|
@@ -3003,7 +3538,7 @@ var AdHocUploader = class {
|
|
|
3003
3538
|
* @param bundleId Bundle ID
|
|
3004
3539
|
*/
|
|
3005
3540
|
generateInstallUrl(distributionPath, bundleId) {
|
|
3006
|
-
const manifestPath =
|
|
3541
|
+
const manifestPath = path6.join(distributionPath, "manifests", `*.plist`);
|
|
3007
3542
|
return `itms-services://?action=download-manifest&url=file://${manifestPath}`;
|
|
3008
3543
|
}
|
|
3009
3544
|
/**
|
|
@@ -3012,7 +3547,7 @@ var AdHocUploader = class {
|
|
|
3012
3547
|
* @param distributionPath 分发目录
|
|
3013
3548
|
*/
|
|
3014
3549
|
async generateQRCode(url, distributionPath) {
|
|
3015
|
-
const qrCodePath =
|
|
3550
|
+
const qrCodePath = path6.join(distributionPath, "install-qrcode.png");
|
|
3016
3551
|
try {
|
|
3017
3552
|
logger.info(`QR code would be saved to: ${qrCodePath}`);
|
|
3018
3553
|
logger.info(`Install URL: ${url}`);
|
|
@@ -3039,8 +3574,8 @@ var AdHocUploader = class {
|
|
|
3039
3574
|
logger.newLine();
|
|
3040
3575
|
logger.info("\u{1F4E6} Distribution Files:");
|
|
3041
3576
|
logger.info(` Directory: ${distributionPath}`);
|
|
3042
|
-
logger.info(` IPA: ${
|
|
3043
|
-
logger.info(` Manifest: ${
|
|
3577
|
+
logger.info(` IPA: ${path6.join(distributionPath, "apps", "*.ipa")}`);
|
|
3578
|
+
logger.info(` Manifest: ${path6.join(distributionPath, "manifests", "*.plist")}`);
|
|
3044
3579
|
logger.info(` QR Code: ${qrCodePath}`);
|
|
3045
3580
|
logger.newLine();
|
|
3046
3581
|
logger.info("\u{1F517} Installation Link:");
|
|
@@ -3099,7 +3634,7 @@ var AdHocUploader = class {
|
|
|
3099
3634
|
|
|
3100
3635
|
// src/adapters/harmony_uploader.ts
|
|
3101
3636
|
import fs10 from "fs-extra";
|
|
3102
|
-
import
|
|
3637
|
+
import path7 from "path";
|
|
3103
3638
|
import axios6 from "axios";
|
|
3104
3639
|
import FormData5 from "form-data";
|
|
3105
3640
|
var HarmonyUploader = class _HarmonyUploader {
|
|
@@ -3129,7 +3664,7 @@ var HarmonyUploader = class _HarmonyUploader {
|
|
|
3129
3664
|
const clientSecret = harmonyConfig.auth.clientSecret;
|
|
3130
3665
|
const appId = harmonyConfig.appId;
|
|
3131
3666
|
const releaseType = harmonyConfig.releaseType || "draft";
|
|
3132
|
-
const suffix =
|
|
3667
|
+
const suffix = path7.extname(filePath).substring(1);
|
|
3133
3668
|
const retryConfig = config.retry;
|
|
3134
3669
|
logger.info("Starting HarmonyOS AppGallery upload...");
|
|
3135
3670
|
try {
|
|
@@ -3246,7 +3781,7 @@ var HarmonyUploader = class _HarmonyUploader {
|
|
|
3246
3781
|
* @param filePath 文件路径
|
|
3247
3782
|
*/
|
|
3248
3783
|
async updateAppFileInfo(token, appId, authCode, filePath) {
|
|
3249
|
-
const fileName =
|
|
3784
|
+
const fileName = path7.basename(filePath);
|
|
3250
3785
|
const body = {
|
|
3251
3786
|
fileType: 7,
|
|
3252
3787
|
// 鸿蒙包的 fileType(需要根据华为最新文档确认)
|
|
@@ -3269,7 +3804,7 @@ var HarmonyUploader = class _HarmonyUploader {
|
|
|
3269
3804
|
|
|
3270
3805
|
// src/adapters/oppo_uploader.ts
|
|
3271
3806
|
import fs11 from "fs-extra";
|
|
3272
|
-
import
|
|
3807
|
+
import path8 from "path";
|
|
3273
3808
|
import axios7 from "axios";
|
|
3274
3809
|
import FormData6 from "form-data";
|
|
3275
3810
|
import crypto4 from "crypto";
|
|
@@ -3310,7 +3845,7 @@ var OppoUploader = class _OppoUploader {
|
|
|
3310
3845
|
* 尝试从文件名推断包名
|
|
3311
3846
|
*/
|
|
3312
3847
|
inferPackageName(filePath) {
|
|
3313
|
-
const fileName =
|
|
3848
|
+
const fileName = path8.basename(filePath);
|
|
3314
3849
|
const match = fileName.match(/^([\w.]+?)(?:-(?:release|debug|unsigned))?\.apk$/i);
|
|
3315
3850
|
if (match && match[1].includes(".")) {
|
|
3316
3851
|
return match[1];
|
|
@@ -3328,110 +3863,47 @@ var OppoUploader = class _OppoUploader {
|
|
|
3328
3863
|
}
|
|
3329
3864
|
async upload(filePath, config, metadata) {
|
|
3330
3865
|
const oppoConfig = config.publish.oppo;
|
|
3331
|
-
const
|
|
3332
|
-
const clientSecret = oppoConfig.auth.clientSecret;
|
|
3866
|
+
const accessToken = await this.getAccessToken(oppoConfig.auth.clientId, oppoConfig.auth.clientSecret);
|
|
3333
3867
|
const packageName = oppoConfig.packageName || this.inferPackageName(filePath);
|
|
3334
|
-
if (!packageName) {
|
|
3335
|
-
return {
|
|
3336
|
-
platform: "oppo",
|
|
3337
|
-
success: false,
|
|
3338
|
-
message: "\u65E0\u6CD5\u83B7\u53D6\u5305\u540D (packageName)\uFF0C\u8BF7\u5728\u914D\u7F6E\u4E2D\u6307\u5B9A\u6216\u786E\u4FDD\u6587\u4EF6\u540D\u5305\u542B\u5305\u540D",
|
|
3339
|
-
consoleUrl: "https://open.oppomobile.com/new/ecology/app"
|
|
3340
|
-
};
|
|
3341
|
-
}
|
|
3342
|
-
const retryConfig = config.retry;
|
|
3343
3868
|
const consoleUrl = "https://open.oppomobile.com/new/ecology/app";
|
|
3344
|
-
if (!
|
|
3345
|
-
return {
|
|
3346
|
-
platform: "oppo",
|
|
3347
|
-
success: false,
|
|
3348
|
-
message: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`,
|
|
3349
|
-
consoleUrl
|
|
3350
|
-
};
|
|
3869
|
+
if (!packageName) {
|
|
3870
|
+
return { platform: "oppo", success: false, message: "\u65E0\u6CD5\u83B7\u53D6\u5305\u540D", consoleUrl };
|
|
3351
3871
|
}
|
|
3352
|
-
|
|
3353
|
-
logger.info(`\u6587\u4EF6: ${filePath}`);
|
|
3872
|
+
const artifacts = typeof metadata.artifactPath === "object" ? metadata.artifactPath : { universal: filePath || (typeof metadata.artifactPath === "string" ? metadata.artifactPath : "") };
|
|
3354
3873
|
try {
|
|
3355
|
-
const retryStrategy = createUploadRetryStrategy(
|
|
3356
|
-
|
|
3357
|
-
const
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
(
|
|
3368
|
-
|
|
3369
|
-
);
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
throw uploadUrlResult.error || new Error("Failed to get upload URL");
|
|
3384
|
-
}
|
|
3385
|
-
const { uploadUrl, sign: uploadSign } = uploadUrlResult.data;
|
|
3386
|
-
logger.info("\u6B63\u5728\u4E0A\u4F20 APK \u6587\u4EF6...");
|
|
3387
|
-
const uploadFileResult = await retryStrategy.execute(
|
|
3388
|
-
() => this.uploadFile(uploadUrl, uploadSign, filePath),
|
|
3389
|
-
"OPPO file upload"
|
|
3390
|
-
);
|
|
3391
|
-
if (!uploadFileResult.success || !uploadFileResult.data) {
|
|
3392
|
-
throw uploadFileResult.error || new Error("File upload failed");
|
|
3393
|
-
}
|
|
3394
|
-
const rawUrl = uploadFileResult.data.url;
|
|
3395
|
-
const fileUrl = rawUrl.replace(/^http:\/\//i, "https://").replace("storedl1.nearme.com.cn", "storedl.nearme.com.cn");
|
|
3396
|
-
const md5 = uploadFileResult.data.md5;
|
|
3397
|
-
logger.info("\u6B63\u5728\u63D0\u4EA4\u7248\u672C\u4FE1\u606F...");
|
|
3398
|
-
const submitResult = await retryStrategy.execute(
|
|
3399
|
-
() => this.submitVersion({
|
|
3400
|
-
accessToken,
|
|
3401
|
-
clientSecret,
|
|
3402
|
-
packageName,
|
|
3403
|
-
appName: oppoConfig.appName || metadata.appName || onlineAppInfo.app_name || this.inferAppName(packageName),
|
|
3404
|
-
fileUrl,
|
|
3405
|
-
fileMd5: md5,
|
|
3406
|
-
versionName: metadata.version,
|
|
3407
|
-
versionCode: metadata.buildNumber,
|
|
3408
|
-
updateDesc: metadata.changelog || "App Update",
|
|
3409
|
-
onlineType: oppoConfig.onlineType,
|
|
3410
|
-
// 从配置读取
|
|
3411
|
-
onlineAppInfo
|
|
3412
|
-
// 传入线上信息
|
|
3413
|
-
}),
|
|
3414
|
-
"OPPO submit version"
|
|
3415
|
-
);
|
|
3416
|
-
if (!submitResult.success) {
|
|
3417
|
-
throw submitResult.error || new Error("Submit version failed");
|
|
3418
|
-
}
|
|
3874
|
+
const retryStrategy = createUploadRetryStrategy(config.retry);
|
|
3875
|
+
const onlineAppInfo = await this.getAppInfo(accessToken, oppoConfig.auth.clientSecret, packageName) || {};
|
|
3876
|
+
const uploadResults = [];
|
|
3877
|
+
const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {
|
|
3878
|
+
if (!p || !fs11.existsSync(p)) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${p}`);
|
|
3879
|
+
logger.info(`[OPPO] \u6B63\u5728\u5904\u7406 ${abi} \u67B6\u6784\u5305...`);
|
|
3880
|
+
const { uploadUrl, sign } = await this.getUploadUrl(accessToken, oppoConfig.auth.clientSecret);
|
|
3881
|
+
const uploadFileResult = await this.uploadFile(uploadUrl, sign, p);
|
|
3882
|
+
const fileUrl = uploadFileResult.url.replace(/^http:\/\//i, "https://").replace("storedl1.nearme.com.cn", "storedl.nearme.com.cn");
|
|
3883
|
+
let cpu_code = 0;
|
|
3884
|
+
if (abi === "arm64-v8a") cpu_code = 3;
|
|
3885
|
+
else if (abi === "armeabi-v7a") cpu_code = 4;
|
|
3886
|
+
uploadResults.push({ url: fileUrl, md5: uploadFileResult.md5, cpu_code });
|
|
3887
|
+
});
|
|
3888
|
+
await Promise.all(uploadPromises);
|
|
3889
|
+
logger.info(`[OPPO] \u6B63\u5728\u63D0\u4EA4\u6D41\u6C34\u53F7\u7EC4: ${JSON.stringify(uploadResults)}`);
|
|
3890
|
+
await this.submitVersion({
|
|
3891
|
+
accessToken,
|
|
3892
|
+
clientSecret: oppoConfig.auth.clientSecret,
|
|
3893
|
+
packageName,
|
|
3894
|
+
appName: oppoConfig.appName || onlineAppInfo.app_name || metadata.appName || this.inferAppName(packageName),
|
|
3895
|
+
apkUrls: uploadResults,
|
|
3896
|
+
versionName: metadata.version,
|
|
3897
|
+
versionCode: metadata.buildNumber,
|
|
3898
|
+
updateDesc: metadata.changelog || "App Update",
|
|
3899
|
+
onlineType: oppoConfig.onlineType,
|
|
3900
|
+
onlineAppInfo
|
|
3901
|
+
});
|
|
3419
3902
|
logger.success("\u4E0A\u4F20\u5230 OPPO \u5E94\u7528\u5546\u5E97\u6210\u529F!");
|
|
3420
|
-
return {
|
|
3421
|
-
platform: "oppo",
|
|
3422
|
-
success: true,
|
|
3423
|
-
message: "\u4E0A\u4F20\u6210\u529F, \u8BF7\u524D\u5F80\u540E\u53F0\u786E\u8BA4\u5E76\u63D0\u4EA4\u5BA1\u6838",
|
|
3424
|
-
consoleUrl
|
|
3425
|
-
};
|
|
3903
|
+
return { platform: "oppo", success: true, message: "\u4E0A\u4F20\u6210\u529F, \u8BF7\u786E\u8BA4", consoleUrl };
|
|
3426
3904
|
} catch (error) {
|
|
3427
3905
|
logger.error(`\u4E0A\u4F20\u5230 OPPO \u5931\u8D25: ${error.message}`);
|
|
3428
|
-
return {
|
|
3429
|
-
platform: "oppo",
|
|
3430
|
-
success: false,
|
|
3431
|
-
message: this.formatError(error),
|
|
3432
|
-
error,
|
|
3433
|
-
consoleUrl
|
|
3434
|
-
};
|
|
3906
|
+
return { platform: "oppo", success: false, message: error.message, error, consoleUrl };
|
|
3435
3907
|
}
|
|
3436
3908
|
}
|
|
3437
3909
|
/**
|
|
@@ -3552,16 +4024,7 @@ var OppoUploader = class _OppoUploader {
|
|
|
3552
4024
|
const signParams = {
|
|
3553
4025
|
access_token: params.accessToken,
|
|
3554
4026
|
timestamp,
|
|
3555
|
-
|
|
3556
|
-
// cpu_code: 0=通用包, 3=arm64-v8a, 4=armeabi-v7a, 5=x86_64
|
|
3557
|
-
apk_url: JSON.stringify([
|
|
3558
|
-
{
|
|
3559
|
-
url: params.fileUrl,
|
|
3560
|
-
md5: params.fileMd5,
|
|
3561
|
-
cpu_code: 0
|
|
3562
|
-
// 通用包
|
|
3563
|
-
}
|
|
3564
|
-
]),
|
|
4027
|
+
apk_url: JSON.stringify(params.apkUrls),
|
|
3565
4028
|
version_name: params.versionName.split("+")[0],
|
|
3566
4029
|
// 仅保留版本名部分
|
|
3567
4030
|
version_code: vCode,
|
|
@@ -3663,7 +4126,7 @@ var OppoUploader = class _OppoUploader {
|
|
|
3663
4126
|
|
|
3664
4127
|
// src/adapters/vivo_uploader.ts
|
|
3665
4128
|
import fs12 from "fs-extra";
|
|
3666
|
-
import
|
|
4129
|
+
import path9 from "path";
|
|
3667
4130
|
import axios8 from "axios";
|
|
3668
4131
|
import FormData7 from "form-data";
|
|
3669
4132
|
import crypto5 from "crypto";
|
|
@@ -3671,26 +4134,14 @@ var VivoUploader = class _VivoUploader {
|
|
|
3671
4134
|
name = "vivo";
|
|
3672
4135
|
/** vivo 开放 API 基础地址 */
|
|
3673
4136
|
static API_BASE = "https://developer-api.vivo.com.cn/router/rest";
|
|
3674
|
-
/**
|
|
3675
|
-
* vivo API 签名生成
|
|
3676
|
-
* 规则: 所有参数按 ASCII 码排序后拼接为 key=val&... 字符串,
|
|
3677
|
-
* 以 accessSecret 为密钥进行 HMAC-SHA256 加密,结果转为小写 16 进制字符串
|
|
3678
|
-
*/
|
|
3679
4137
|
generateSign(params, accessSecret) {
|
|
3680
4138
|
const sorted = Object.keys(params).sort().filter((key) => params[key] !== void 0 && params[key] !== null).map((key) => `${key}=${params[key]}`).join("&");
|
|
3681
|
-
|
|
3682
|
-
logger.info(`[VIVO DEBUG] \u5F85\u7B7E\u540D\u4E32: ${sorted}
|
|
3683
|
-
-> \u7B7E\u540D\u7ED3\u679C: ${sign}`);
|
|
3684
|
-
return sign;
|
|
4139
|
+
return crypto5.createHmac("sha256", accessSecret).update(sorted).digest("hex");
|
|
3685
4140
|
}
|
|
3686
4141
|
validateConfig(config) {
|
|
3687
4142
|
if (!config?.publish?.vivo?.enable) return false;
|
|
3688
4143
|
const vivo = config.publish.vivo;
|
|
3689
|
-
|
|
3690
|
-
logger.error("vivo config missing: accessKey or accessSecret");
|
|
3691
|
-
return false;
|
|
3692
|
-
}
|
|
3693
|
-
return true;
|
|
4144
|
+
return !!(vivo.auth?.accessKey && vivo.auth?.accessSecret);
|
|
3694
4145
|
}
|
|
3695
4146
|
canHandle(filePath) {
|
|
3696
4147
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
@@ -3700,67 +4151,51 @@ var VivoUploader = class _VivoUploader {
|
|
|
3700
4151
|
const vivoConfig = config.publish.vivo;
|
|
3701
4152
|
const accessKey = vivoConfig.auth.accessKey;
|
|
3702
4153
|
const accessSecret = vivoConfig.auth.accessSecret;
|
|
3703
|
-
const retryConfig = config.retry;
|
|
3704
4154
|
const consoleUrl = "https://dev.vivo.com.cn/manage/app";
|
|
3705
|
-
|
|
3706
|
-
return {
|
|
3707
|
-
platform: "vivo",
|
|
3708
|
-
success: false,
|
|
3709
|
-
message: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`,
|
|
3710
|
-
consoleUrl
|
|
3711
|
-
};
|
|
3712
|
-
}
|
|
3713
|
-
const fileSize = fs12.statSync(filePath).size;
|
|
3714
|
-
logger.info("\u5F00\u59CB\u4E0A\u4F20\u5230 vivo \u5E94\u7528\u5546\u5E97...");
|
|
3715
|
-
logger.info(`\u6587\u4EF6: ${filePath} (${(fileSize / 1024 / 1024).toFixed(2)} MB)`);
|
|
4155
|
+
const artifacts = typeof metadata.artifactPath === "object" ? metadata.artifactPath : { universal: filePath || (typeof metadata.artifactPath === "string" ? metadata.artifactPath : "") };
|
|
3716
4156
|
try {
|
|
3717
|
-
const
|
|
3718
|
-
const
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
4157
|
+
const uploadResults = {};
|
|
4158
|
+
const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {
|
|
4159
|
+
if (!p || !fs12.existsSync(p)) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${p}`);
|
|
4160
|
+
const md5 = await this.calculateFileMD5(p);
|
|
4161
|
+
logger.info(`[vivo] \u6B63\u5728\u5904\u7406 ${abi} \u67B6\u6784\u5305: ${path9.basename(p)}`);
|
|
4162
|
+
const serialnumber = await this.uploadApk(accessKey, accessSecret, p, vivoConfig.packageName || "", md5);
|
|
4163
|
+
const pkgInfo = await parsePackageInfo(p, { androidSdkPath: config.globalSettings?.androidSdkPath });
|
|
4164
|
+
const nativeCodes = pkgInfo?.nativeCode || [];
|
|
4165
|
+
const has64Bit = nativeCodes.includes("arm64-v8a") || nativeCodes.includes("x86_64") || abi === "arm64-v8a";
|
|
4166
|
+
const has32Bit = nativeCodes.includes("armeabi-v7a") || nativeCodes.includes("armeabi") || abi === "armeabi-v7a";
|
|
4167
|
+
uploadResults[abi] = { serialnumber, md5, is64Bit: has64Bit && !has32Bit };
|
|
4168
|
+
});
|
|
4169
|
+
await Promise.all(uploadPromises);
|
|
4170
|
+
const arm64Result = uploadResults["arm64-v8a"] || Object.values(uploadResults).find((r) => r.is64Bit);
|
|
4171
|
+
const arm32Result = uploadResults["armeabi-v7a"] || Object.values(uploadResults).find((r) => !r.is64Bit);
|
|
4172
|
+
const submitData = {
|
|
4173
|
+
packageName: vivoConfig.packageName,
|
|
4174
|
+
versionCode: parseInt(metadata.buildNumber) || 1,
|
|
4175
|
+
updateDesc: metadata.changelog || "App Update"
|
|
4176
|
+
};
|
|
4177
|
+
if (arm64Result) {
|
|
4178
|
+
submitData.serialnumber = arm64Result.serialnumber;
|
|
4179
|
+
submitData.fileMd5 = arm64Result.md5;
|
|
3727
4180
|
}
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
updateDesc: metadata.changelog || "App Update"
|
|
3737
|
-
}),
|
|
3738
|
-
"vivo submit version"
|
|
3739
|
-
);
|
|
3740
|
-
if (!submitResult.success) {
|
|
3741
|
-
throw submitResult.error || new Error("Submit version failed");
|
|
4181
|
+
if (arm32Result) {
|
|
4182
|
+
submitData.apk32 = arm32Result.serialnumber;
|
|
4183
|
+
submitData.md532 = arm32Result.md5;
|
|
4184
|
+
}
|
|
4185
|
+
if (!submitData.serialnumber && !submitData.apk32) {
|
|
4186
|
+
const single = Object.values(uploadResults)[0];
|
|
4187
|
+
submitData.serialnumber = single.serialnumber;
|
|
4188
|
+
submitData.fileMd5 = single.md5;
|
|
3742
4189
|
}
|
|
4190
|
+
logger.info(`[vivo] \u6B63\u5728\u63D0\u4EA4\u5BA1\u6838\u7533\u62A5: ${JSON.stringify(submitData)}`);
|
|
4191
|
+
await this.submitVersion(accessKey, accessSecret, submitData);
|
|
3743
4192
|
logger.success("\u4E0A\u4F20\u5230 vivo \u5E94\u7528\u5546\u5E97\u6210\u529F!");
|
|
3744
|
-
return {
|
|
3745
|
-
platform: "vivo",
|
|
3746
|
-
success: true,
|
|
3747
|
-
message: "\u4E0A\u4F20\u6210\u529F, \u8BF7\u524D\u5F80\u540E\u53F0\u786E\u8BA4\u5E76\u63D0\u4EA4\u5BA1\u6838",
|
|
3748
|
-
consoleUrl
|
|
3749
|
-
};
|
|
4193
|
+
return { platform: "vivo", success: true, message: "\u4E0A\u4F20\u5E76\u63D0\u4EA4\u5BA1\u6838\u6210\u529F", consoleUrl };
|
|
3750
4194
|
} catch (error) {
|
|
3751
4195
|
logger.error(`\u4E0A\u4F20\u5230 vivo \u5931\u8D25: ${error.message}`);
|
|
3752
|
-
return {
|
|
3753
|
-
platform: "vivo",
|
|
3754
|
-
success: false,
|
|
3755
|
-
message: this.formatError(error),
|
|
3756
|
-
error,
|
|
3757
|
-
consoleUrl
|
|
3758
|
-
};
|
|
4196
|
+
return { platform: "vivo", success: false, message: error.message, error, consoleUrl };
|
|
3759
4197
|
}
|
|
3760
4198
|
}
|
|
3761
|
-
/**
|
|
3762
|
-
* 计算文件 MD5
|
|
3763
|
-
*/
|
|
3764
4199
|
calculateFileMD5(filePath) {
|
|
3765
4200
|
return new Promise((resolve, reject) => {
|
|
3766
4201
|
const hash = crypto5.createHash("md5");
|
|
@@ -3770,14 +4205,9 @@ var VivoUploader = class _VivoUploader {
|
|
|
3770
4205
|
stream.on("error", reject);
|
|
3771
4206
|
});
|
|
3772
4207
|
}
|
|
3773
|
-
/**
|
|
3774
|
-
* 上传 APK 文件并获取流水号
|
|
3775
|
-
* 将公共参数与业务参数放入一个 multipart 请求中直接上传至 API_BASE
|
|
3776
|
-
*/
|
|
3777
4208
|
async uploadApk(accessKey, accessSecret, filePath, packageName, fileMd5) {
|
|
3778
4209
|
const timestamp = String(Date.now());
|
|
3779
|
-
const
|
|
3780
|
-
// 公共参数
|
|
4210
|
+
const params = {
|
|
3781
4211
|
access_key: accessKey,
|
|
3782
4212
|
timestamp,
|
|
3783
4213
|
format: "json",
|
|
@@ -3785,41 +4215,19 @@ var VivoUploader = class _VivoUploader {
|
|
|
3785
4215
|
sign_method: "hmac",
|
|
3786
4216
|
target_app_key: "developer",
|
|
3787
4217
|
method: "app.upload.apk.app",
|
|
3788
|
-
// 业务参数
|
|
3789
4218
|
packageName,
|
|
3790
4219
|
fileMd5
|
|
3791
4220
|
};
|
|
3792
|
-
const sign = this.generateSign(
|
|
4221
|
+
const sign = this.generateSign(params, accessSecret);
|
|
3793
4222
|
const form = new FormData7();
|
|
3794
|
-
|
|
3795
|
-
form.append(key, value);
|
|
3796
|
-
}
|
|
4223
|
+
Object.entries(params).forEach(([k, v]) => form.append(k, v));
|
|
3797
4224
|
form.append("sign", sign);
|
|
3798
|
-
form.append("file", fs12.createReadStream(filePath), {
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
logger.info(
|
|
3803
|
-
`[VIVO DEBUG] \u5F00\u59CB\u4E0A\u4F20 APK (API\u8BF7\u6C42) \u53C2\u6570(\u4E0D\u542B\u6587\u4EF6): ${JSON.stringify({ ...paramsForSign, sign })}`
|
|
3804
|
-
);
|
|
3805
|
-
const res = await axios8.post(_VivoUploader.API_BASE, form, {
|
|
3806
|
-
headers: form.getHeaders(),
|
|
3807
|
-
maxContentLength: Infinity,
|
|
3808
|
-
maxBodyLength: Infinity,
|
|
3809
|
-
timeout: 3e5
|
|
3810
|
-
});
|
|
3811
|
-
logger.info(`[VIVO DEBUG] \u4E0A\u4F20\u54CD\u5E94: ${JSON.stringify(res.data)}`);
|
|
3812
|
-
if (res.data.code !== 0) {
|
|
3813
|
-
throw new Error(`\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: ${res.data.msg || JSON.stringify(res.data)}`);
|
|
3814
|
-
}
|
|
3815
|
-
const serialnumber = res.data.data?.serialnumber || res.data.data;
|
|
3816
|
-
logger.info(`APK \u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210\uFF0C\u6D41\u6C34\u53F7: ${serialnumber}`);
|
|
3817
|
-
return serialnumber;
|
|
4225
|
+
form.append("file", fs12.createReadStream(filePath), { filename: path9.basename(filePath) });
|
|
4226
|
+
const res = await axios8.post(_VivoUploader.API_BASE, form, { headers: form.getHeaders(), timeout: 3e5 });
|
|
4227
|
+
if (res.data.code !== 0) throw new Error(`\u4E0A\u4F20\u5305\u5931\u8D25: ${res.data.msg}`);
|
|
4228
|
+
return res.data.data?.serialnumber || res.data.data;
|
|
3818
4229
|
}
|
|
3819
|
-
|
|
3820
|
-
* 提交版本更新信息
|
|
3821
|
-
*/
|
|
3822
|
-
async submitVersion(accessKey, accessSecret, params) {
|
|
4230
|
+
async submitVersion(accessKey, accessSecret, data) {
|
|
3823
4231
|
const timestamp = String(Date.now());
|
|
3824
4232
|
const reqParams = {
|
|
3825
4233
|
access_key: accessKey,
|
|
@@ -3829,51 +4237,32 @@ var VivoUploader = class _VivoUploader {
|
|
|
3829
4237
|
sign_method: "hmac",
|
|
3830
4238
|
target_app_key: "developer",
|
|
3831
4239
|
method: "app.sync.update.app",
|
|
3832
|
-
packageName:
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
apk: params.serialnumber,
|
|
3837
|
-
// 文档中的 apk 字段即为上传接口返回的 serialnumber
|
|
3838
|
-
fileMd5: params.fileMd5,
|
|
3839
|
-
// 文档必填
|
|
4240
|
+
packageName: data.packageName || "",
|
|
4241
|
+
versionCode: String(data.versionCode),
|
|
4242
|
+
apk: data.serialnumber || "",
|
|
4243
|
+
fileMd5: data.fileMd5 || "",
|
|
3840
4244
|
onlineType: "1",
|
|
3841
|
-
// 1:立即上架 2:定时上架 (必填)
|
|
3842
4245
|
compatibleDevice: "1",
|
|
3843
|
-
|
|
3844
|
-
updateDesc: params.updateDesc
|
|
4246
|
+
updateDesc: data.updateDesc
|
|
3845
4247
|
};
|
|
4248
|
+
if (data.apk32) {
|
|
4249
|
+
reqParams.apk32 = data.apk32;
|
|
4250
|
+
if (data.md532) reqParams.md532 = data.md532;
|
|
4251
|
+
}
|
|
3846
4252
|
reqParams.sign = this.generateSign(reqParams, accessSecret);
|
|
3847
4253
|
const formData = new URLSearchParams();
|
|
3848
|
-
|
|
3849
|
-
formData.append(key, value);
|
|
3850
|
-
}
|
|
4254
|
+
Object.entries(reqParams).forEach(([k, v]) => formData.append(k, v));
|
|
3851
4255
|
const res = await axios8.post(_VivoUploader.API_BASE, formData.toString(), {
|
|
3852
|
-
headers: {
|
|
3853
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
3854
|
-
},
|
|
4256
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
3855
4257
|
timeout: 3e4
|
|
3856
4258
|
});
|
|
3857
|
-
if (res.data.code !== 0) {
|
|
3858
|
-
throw new Error(`\u63D0\u4EA4\u7248\u672C\u5931\u8D25: ${res.data.msg || JSON.stringify(res.data)}`);
|
|
3859
|
-
}
|
|
3860
|
-
logger.info("\u7248\u672C\u4FE1\u606F\u5DF2\u63D0\u4EA4");
|
|
3861
|
-
}
|
|
3862
|
-
/**
|
|
3863
|
-
* 格式化错误信息
|
|
3864
|
-
*/
|
|
3865
|
-
formatError(error) {
|
|
3866
|
-
if (error.response?.data) {
|
|
3867
|
-
const data = error.response.data;
|
|
3868
|
-
return data.msg || data.message || error.message;
|
|
3869
|
-
}
|
|
3870
|
-
return error.message;
|
|
4259
|
+
if (res.data.code !== 0) throw new Error(`\u63D0\u4EA4\u5931\u8D25: ${res.data.msg}`);
|
|
3871
4260
|
}
|
|
3872
4261
|
};
|
|
3873
4262
|
|
|
3874
4263
|
// src/adapters/tencent_uploader.ts
|
|
3875
4264
|
import fs13 from "fs-extra";
|
|
3876
|
-
import
|
|
4265
|
+
import path10 from "path";
|
|
3877
4266
|
import axios9 from "axios";
|
|
3878
4267
|
import crypto6 from "crypto";
|
|
3879
4268
|
var TencentUploader = class _TencentUploader {
|
|
@@ -3905,54 +4294,71 @@ var TencentUploader = class _TencentUploader {
|
|
|
3905
4294
|
async upload(filePath, config, metadata) {
|
|
3906
4295
|
const tencentConfig = config.publish.tencent;
|
|
3907
4296
|
const auth = tencentConfig.auth;
|
|
3908
|
-
logger.info(`Tencent \u8FD0\u884C\u65F6\u914D\u7F6E: ${JSON.stringify(tencentConfig)}`);
|
|
3909
4297
|
const consoleUrl = "https://app.open.qq.com";
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
}
|
|
4298
|
+
const pkgName = tencentConfig.packageName || "";
|
|
4299
|
+
const artifacts = typeof metadata.artifactPath === "object" ? metadata.artifactPath : { universal: filePath || (typeof metadata.artifactPath === "string" ? metadata.artifactPath : "") };
|
|
3913
4300
|
try {
|
|
3914
|
-
const
|
|
3915
|
-
const
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
4301
|
+
const uploadResults = {};
|
|
4302
|
+
const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {
|
|
4303
|
+
if (!p || !fs13.existsSync(p)) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${p}`);
|
|
4304
|
+
const stats = fs13.statSync(p);
|
|
4305
|
+
const fileName = path10.basename(p);
|
|
4306
|
+
logger.info(`[Tencent] \u6B63\u5728\u5904\u7406 ${abi} \u67B6\u6784\u5305: ${fileName}`);
|
|
4307
|
+
const uploadInfo = await this.getFileUploadInfo(auth, stats.size, fileName, pkgName);
|
|
4308
|
+
await this.uploadToCos(uploadInfo.pre_sign_url, p, stats.size);
|
|
4309
|
+
const pkgInfo = await parsePackageInfo(p, {
|
|
4310
|
+
androidSdkPath: config.globalSettings?.androidSdkPath
|
|
4311
|
+
});
|
|
4312
|
+
const nativeCodes = pkgInfo?.nativeCode || [];
|
|
4313
|
+
const has64Bit = nativeCodes.includes("arm64-v8a") || nativeCodes.includes("x86_64") || abi === "arm64-v8a";
|
|
4314
|
+
const has32Bit = nativeCodes.includes("armeabi-v7a") || nativeCodes.includes("armeabi") || nativeCodes.includes("x86") || abi === "armeabi-v7a";
|
|
4315
|
+
uploadResults[abi] = {
|
|
4316
|
+
serial_number: uploadInfo.serial_number,
|
|
4317
|
+
is64Bit: has64Bit && !has32Bit,
|
|
4318
|
+
md5: pkgInfo?.md5 || ""
|
|
4319
|
+
};
|
|
4320
|
+
});
|
|
4321
|
+
await Promise.all(uploadPromises);
|
|
4322
|
+
logger.info("[Tencent] \u6B63\u5728\u83B7\u53D6\u7EBF\u4E0A\u5E94\u7528\u8BE6\u60C5...");
|
|
4323
|
+
const anyPkgPath = Object.values(artifacts)[0];
|
|
4324
|
+
const samplePkgInfo = await parsePackageInfo(anyPkgPath, {
|
|
3924
4325
|
androidSdkPath: config.globalSettings?.androidSdkPath
|
|
3925
4326
|
});
|
|
3926
|
-
const nativeCodes = pkgInfo?.nativeCode || [];
|
|
3927
|
-
const has64Bit = nativeCodes.includes("arm64-v8a") || nativeCodes.includes("x86_64");
|
|
3928
|
-
const has32Bit = nativeCodes.includes("armeabi-v7a") || nativeCodes.includes("armeabi") || nativeCodes.includes("x86");
|
|
3929
|
-
const is64Bit = has64Bit && !has32Bit;
|
|
3930
|
-
const md5 = pkgInfo?.md5;
|
|
3931
4327
|
const onlineDetail = await this.queryAppDetail(
|
|
3932
4328
|
auth,
|
|
3933
|
-
|
|
4329
|
+
pkgName || samplePkgInfo?.packageName || ""
|
|
3934
4330
|
);
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
4331
|
+
const submitData = {
|
|
4332
|
+
...onlineDetail,
|
|
4333
|
+
pkg_name: pkgName || samplePkgInfo?.packageName || onlineDetail.pkg_name || "",
|
|
4334
|
+
update_desc: metadata.changelog || "\u7248\u672C\u66F4\u65B0"
|
|
4335
|
+
};
|
|
4336
|
+
const arm64Result = uploadResults["arm64-v8a"] || Object.values(uploadResults).find((r) => r.is64Bit);
|
|
4337
|
+
const arm32Result = uploadResults["armeabi-v7a"] || Object.values(uploadResults).find((r) => !r.is64Bit);
|
|
4338
|
+
if (arm64Result) {
|
|
4339
|
+
submitData.apk64_serial_number = arm64Result.serial_number;
|
|
4340
|
+
submitData.apk64_md5 = arm64Result.md5;
|
|
4341
|
+
}
|
|
4342
|
+
if (arm32Result) {
|
|
4343
|
+
submitData.apk32_serial_number = arm32Result.serial_number;
|
|
4344
|
+
submitData.apk32_md5 = arm32Result.md5;
|
|
4345
|
+
}
|
|
4346
|
+
if (Object.keys(uploadResults).length === 1 && !submitData.apk64_serial_number && !submitData.apk32_serial_number) {
|
|
4347
|
+
const single = Object.values(uploadResults)[0];
|
|
4348
|
+
if (single.is64Bit) {
|
|
4349
|
+
submitData.apk64_serial_number = single.serial_number;
|
|
4350
|
+
submitData.apk64_md5 = single.md5;
|
|
4351
|
+
} else {
|
|
4352
|
+
submitData.apk32_serial_number = single.serial_number;
|
|
4353
|
+
submitData.apk32_md5 = single.md5;
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4356
|
+
logger.info("[Tencent] \u6B63\u5728\u63D0\u4EA4\u5BA1\u6838\u7533\u62A5...");
|
|
4357
|
+
await this.submitModifyAppInfo(auth, submitData, { timeout: tencentConfig.timeout || 6e4 });
|
|
3951
4358
|
logger.success("\u817E\u8BAF\u5E94\u7528\u5B9D\u4E0A\u4F20\u5E76\u63D0\u4EA4\u6210\u529F!");
|
|
3952
4359
|
return { platform: "tencent", success: true, message: "\u4E0A\u4F20\u5E76\u63D0\u4EA4\u5BA1\u6838\u6210\u529F", consoleUrl };
|
|
3953
4360
|
} catch (error) {
|
|
3954
|
-
logger.error(`\u817E\u8BAF\u4E0A\u4F20\u5931\u8D25: ${
|
|
3955
|
-
logger.error(`\u817E\u8BAF\u4E0A\u4F20\u5931\u8D25: ${error.stack}`);
|
|
4361
|
+
logger.error(`\u817E\u8BAF\u4E0A\u4F20\u5931\u8D25: ${error.message}`);
|
|
3956
4362
|
return { platform: "tencent", success: false, message: error.message, error, consoleUrl };
|
|
3957
4363
|
}
|
|
3958
4364
|
}
|
|
@@ -4066,16 +4472,22 @@ var TencentUploader = class _TencentUploader {
|
|
|
4066
4472
|
signParams[key] = String(data[key]);
|
|
4067
4473
|
}
|
|
4068
4474
|
});
|
|
4069
|
-
if (data.
|
|
4070
|
-
signParams.apk64_file_serial_number = String(data.
|
|
4071
|
-
if (data.
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
signParams.
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4475
|
+
if (data.apk64_serial_number) {
|
|
4476
|
+
signParams.apk64_file_serial_number = String(data.apk64_serial_number);
|
|
4477
|
+
if (data.apk64_md5) signParams.apk64_file_md5 = data.apk64_md5;
|
|
4478
|
+
}
|
|
4479
|
+
if (data.apk32_serial_number) {
|
|
4480
|
+
signParams.apk32_file_serial_number = String(data.apk32_serial_number);
|
|
4481
|
+
if (data.apk32_md5) signParams.apk32_file_md5 = data.apk32_md5;
|
|
4482
|
+
}
|
|
4483
|
+
if (!data.apk64_serial_number && !data.apk32_serial_number && data.serial_number) {
|
|
4484
|
+
if (data.is64Bit) {
|
|
4485
|
+
signParams.apk64_file_serial_number = String(data.serial_number || "");
|
|
4486
|
+
if (data.md5) signParams.apk64_file_md5 = data.md5;
|
|
4487
|
+
} else {
|
|
4488
|
+
signParams.apk32_file_serial_number = String(data.serial_number || "");
|
|
4489
|
+
if (data.md5) signParams.apk32_file_md5 = data.md5;
|
|
4490
|
+
}
|
|
4079
4491
|
}
|
|
4080
4492
|
const sign = this.generateSign(signParams, accessSecret);
|
|
4081
4493
|
const formParams = {
|