shipup 0.2.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +14 -0
  3. package/README.md +112 -0
  4. package/README.zh-CN.md +105 -0
  5. package/SECURITY.md +32 -0
  6. package/creds.example.yaml +62 -0
  7. package/dist/adapters/android/honor/api.js +360 -0
  8. package/dist/adapters/android/honor/api.js.map +1 -0
  9. package/dist/adapters/android/honor/index.js +122 -0
  10. package/dist/adapters/android/honor/index.js.map +1 -0
  11. package/dist/adapters/android/huawei/api.js +389 -0
  12. package/dist/adapters/android/huawei/api.js.map +1 -0
  13. package/dist/adapters/android/huawei/index.js +128 -0
  14. package/dist/adapters/android/huawei/index.js.map +1 -0
  15. package/dist/adapters/android/meizu/api.js +367 -0
  16. package/dist/adapters/android/meizu/api.js.map +1 -0
  17. package/dist/adapters/android/meizu/index.js +129 -0
  18. package/dist/adapters/android/meizu/index.js.map +1 -0
  19. package/dist/adapters/android/oppo/api.js +397 -0
  20. package/dist/adapters/android/oppo/api.js.map +1 -0
  21. package/dist/adapters/android/oppo/index.js +135 -0
  22. package/dist/adapters/android/oppo/index.js.map +1 -0
  23. package/dist/adapters/android/qq/api.js +184 -0
  24. package/dist/adapters/android/qq/api.js.map +1 -0
  25. package/dist/adapters/android/qq/index.js +80 -0
  26. package/dist/adapters/android/qq/index.js.map +1 -0
  27. package/dist/adapters/android/samsung/api.js +355 -0
  28. package/dist/adapters/android/samsung/api.js.map +1 -0
  29. package/dist/adapters/android/samsung/index.js +111 -0
  30. package/dist/adapters/android/samsung/index.js.map +1 -0
  31. package/dist/adapters/android/specs.js +106 -0
  32. package/dist/adapters/android/specs.js.map +1 -0
  33. package/dist/adapters/android/stub.js +27 -0
  34. package/dist/adapters/android/stub.js.map +1 -0
  35. package/dist/adapters/android/vivo/api.js +236 -0
  36. package/dist/adapters/android/vivo/api.js.map +1 -0
  37. package/dist/adapters/android/vivo/index.js +121 -0
  38. package/dist/adapters/android/vivo/index.js.map +1 -0
  39. package/dist/adapters/android/xiaomi/api.js +163 -0
  40. package/dist/adapters/android/xiaomi/api.js.map +1 -0
  41. package/dist/adapters/android/xiaomi/index.js +108 -0
  42. package/dist/adapters/android/xiaomi/index.js.map +1 -0
  43. package/dist/adapters/ios/appstore/asc.js +280 -0
  44. package/dist/adapters/ios/appstore/asc.js.map +1 -0
  45. package/dist/adapters/ios/appstore/index.js +323 -0
  46. package/dist/adapters/ios/appstore/index.js.map +1 -0
  47. package/dist/adapters/registry.js +34 -0
  48. package/dist/adapters/registry.js.map +1 -0
  49. package/dist/adapters/util.js +26 -0
  50. package/dist/adapters/util.js.map +1 -0
  51. package/dist/cli/index.js +479 -0
  52. package/dist/cli/index.js.map +1 -0
  53. package/dist/cli/output.js +65 -0
  54. package/dist/cli/output.js.map +1 -0
  55. package/dist/core/exit.js +20 -0
  56. package/dist/core/exit.js.map +1 -0
  57. package/dist/core/orchestrator.js +24 -0
  58. package/dist/core/orchestrator.js.map +1 -0
  59. package/dist/core/types.js +20 -0
  60. package/dist/core/types.js.map +1 -0
  61. package/dist/creds/load.js +68 -0
  62. package/dist/creds/load.js.map +1 -0
  63. package/dist/creds/schema.js +30 -0
  64. package/dist/creds/schema.js.map +1 -0
  65. package/dist/infra/crypto.js +12 -0
  66. package/dist/infra/crypto.js.map +1 -0
  67. package/dist/infra/http.js +87 -0
  68. package/dist/infra/http.js.map +1 -0
  69. package/dist/pkginfo/apk-icon.js +89 -0
  70. package/dist/pkginfo/apk-icon.js.map +1 -0
  71. package/dist/pkginfo/icon.js +83 -0
  72. package/dist/pkginfo/icon.js.map +1 -0
  73. package/dist/pkginfo/index.js +33 -0
  74. package/dist/pkginfo/index.js.map +1 -0
  75. package/docs/android-markets.md +190 -0
  76. package/docs/credentials.md +72 -0
  77. package/docs/providers.md +60 -0
  78. package/lib/common.mjs +265 -0
  79. package/lib/harmony.mjs +190 -0
  80. package/lib/huawei.mjs +153 -0
  81. package/lib/ios.mjs +477 -0
  82. package/package.json +70 -0
  83. package/shipup.mjs +160 -0
@@ -0,0 +1,367 @@
1
+ // 文档:https://open.flyme.cn/docs?id=333(域名 developer.meizu.com)
2
+ // 能力:更新已上架应用的版本(新版本发布)。要求 64 位安装包。
3
+ //
4
+ // 调用流程:
5
+ // 1) GET /open/api/v1/token 换 accessToken(header: clientId/clientSecret)
6
+ // 2) POST /open/api/v1/app/apk/upload multipart 上传 APK,得 destFileName(packageUrl)
7
+ // 3) GET /open/api/v1/app/list 按包名找 appId / 最新 verId
8
+ // 4) GET /open/api/v1/app/detail 取当前版本全部字段(分类/标签/备案/资质等)
9
+ // 5) POST /open/api/v1/app/image/upload 上传图标
10
+ // 6) POST /open/api/v1/app/publish 复用 detail 字段 + 新包 + 新版本说明,发布新版本
11
+ //
12
+ // 每个业务请求都带签名:参与字段 traceId/clientId/timestamp/uri,
13
+ // 按 "key=value" 升序拼 & 后追加 ":clientSecret",SHA-256 转小写 hex。
14
+ import { randomUUID } from 'node:crypto';
15
+ import { sha256Hex } from '../../../infra/crypto.js';
16
+ import { redactSensitive, UploadError } from '../../../core/types.js';
17
+ import { withRetry } from '../../../infra/http.js';
18
+ const BASE = 'https://developer.meizu.com';
19
+ /**
20
+ * 签名:参与字段 traceId、clientId、timestamp、uri;
21
+ * 按 "key=value" 升序拼 & 后追加 ":clientSecret",SHA-256 转小写 hex。
22
+ */
23
+ export function signMeizu(args) {
24
+ const parts = [
25
+ `clientId=${args.clientId}`,
26
+ `timestamp=${args.timestamp}`,
27
+ `traceId=${args.traceId}`,
28
+ `uri=${args.uri}`,
29
+ ].sort();
30
+ const raw = `${parts.join('&')}:${args.clientSecret}`;
31
+ return sha256Hex(raw);
32
+ }
33
+ /** 组装公共请求头(含签名)。multipart 时不要带 Content-Type,交给 fetch 自动加 boundary。 */
34
+ function commonHeaders(uri, auth) {
35
+ const traceId = randomUUID();
36
+ const timestamp = String(Date.now());
37
+ const sign = signMeizu({
38
+ traceId,
39
+ clientId: auth.clientId,
40
+ timestamp,
41
+ uri,
42
+ clientSecret: auth.clientSecret,
43
+ });
44
+ return {
45
+ traceId,
46
+ clientId: auth.clientId,
47
+ timestamp,
48
+ sign,
49
+ accessToken: auth.accessToken,
50
+ };
51
+ }
52
+ /** 校验响应 code===200,否则抛 UploadError;返回 value。 */
53
+ function checkValue(data, fallbackMsg) {
54
+ if (Number(data?.code ?? -1) !== 200) {
55
+ throw new UploadError(data?.code ?? -1, String(data?.msg ?? fallbackMsg));
56
+ }
57
+ return data?.value;
58
+ }
59
+ /** 获取鉴权 accessToken(header 传 clientId/clientSecret,无签名)。 */
60
+ export async function getToken(args) {
61
+ return withRetry(async () => {
62
+ const res = await fetch(`${BASE}/open/api/v1/token`, {
63
+ method: 'GET',
64
+ headers: { clientId: args.clientId, clientSecret: args.clientSecret },
65
+ signal: AbortSignal.timeout(args.timeoutMs),
66
+ });
67
+ const data = JSON.parse(await res.text());
68
+ const value = checkValue(data, 'token error');
69
+ return String(value.accessToken);
70
+ }, { label: 'meizu token' });
71
+ }
72
+ /** GET 请求(公共头),返回 value。query 不参与签名(签名只用 path)。 */
73
+ async function getValue(uri, query, auth, timeoutMs) {
74
+ const url = new URL(`${BASE}${uri}`);
75
+ for (const [k, v] of Object.entries(query))
76
+ url.searchParams.set(k, v);
77
+ return withRetry(async () => {
78
+ // commonHeaders 放进闭包:每次重试都重算 traceId/timestamp/sign,避免签名过期。
79
+ const res = await fetch(url, {
80
+ method: 'GET',
81
+ headers: commonHeaders(uri, auth),
82
+ signal: AbortSignal.timeout(timeoutMs),
83
+ });
84
+ const data = JSON.parse(await res.text());
85
+ return checkValue(data, `get error: ${uri}`);
86
+ }, { label: `meizu ${uri}` });
87
+ }
88
+ /** multipart 上传单文件,返回 value.destFileName。 */
89
+ async function uploadFile(uri, bytes, filename, contentType, auth, timeoutMs, fallbackMsg) {
90
+ const form = new FormData();
91
+ form.append('file', new Blob([bytes], { type: contentType }), filename);
92
+ const res = await fetch(`${BASE}${uri}`, {
93
+ method: 'POST',
94
+ headers: commonHeaders(uri, auth), // 不含 Content-Type,fetch 自动补 multipart boundary
95
+ body: form,
96
+ signal: AbortSignal.timeout(timeoutMs),
97
+ });
98
+ const data = JSON.parse(await res.text());
99
+ const value = checkValue(data, fallbackMsg);
100
+ return String(value.destFileName);
101
+ }
102
+ /** 上传 APK,返回 destFileName(packageUrl)。 */
103
+ export async function uploadApk(args) {
104
+ return uploadFile('/open/api/v1/app/apk/upload', args.apkBytes, args.apkFilename, 'application/octet-stream', args.auth, args.timeoutMs, 'apk upload error');
105
+ }
106
+ /** 上传图片(图标/截图),返回 destFileName。 */
107
+ export async function uploadImage(args) {
108
+ return uploadFile('/open/api/v1/app/image/upload', args.imageBytes, args.imageFilename, args.contentType, args.auth, args.timeoutMs, 'image upload error');
109
+ }
110
+ /** 按包名查找开发者应用,返回 {id, verId, versionName, status, ...}。 */
111
+ export async function findAppByPackage(args) {
112
+ let start = 0;
113
+ const limit = 10;
114
+ // eslint-disable-next-line no-constant-condition
115
+ while (true) {
116
+ const value = await getValue('/open/api/v1/app/list', { start: String(start), limit: String(limit) }, args.auth, args.timeoutMs);
117
+ const list = Array.isArray(value?.data) ? value.data : [];
118
+ for (const app of list) {
119
+ if (String(app?.pkgName) === args.packageName)
120
+ return app;
121
+ }
122
+ const total = Number(value?.total ?? 0);
123
+ start += limit;
124
+ if (list.length === 0 || start >= total) {
125
+ throw new UploadError(-1, `魅族未找到应用: ${args.packageName}`);
126
+ }
127
+ }
128
+ }
129
+ /** 根据 verId 获取应用详情(全部字段)。 */
130
+ export async function getAppDetail(args) {
131
+ return getValue('/open/api/v1/app/detail', { verId: args.verId }, args.auth, args.timeoutMs);
132
+ }
133
+ /** 获取应用版本列表(用于回退查找可复用的截图)。 */
134
+ export async function getAppVersions(args) {
135
+ const value = await getValue('/open/api/v1/app/versions', { appId: args.appId }, args.auth, args.timeoutMs);
136
+ return Array.isArray(value) ? value : [];
137
+ }
138
+ /** 解析可复用的截图:优先当前 detail;为空则遍历历史版本 detail 取第一份非空。 */
139
+ export async function resolveScreenShots(args) {
140
+ const cur = args.detail?.screenShots;
141
+ if (Array.isArray(cur) && cur.length > 0)
142
+ return cur;
143
+ const versions = await getAppVersions({ auth: args.auth, appId: args.appId, timeoutMs: args.timeoutMs });
144
+ for (const v of versions) {
145
+ const verId = v?.verId != null ? String(v.verId) : '';
146
+ if (!verId)
147
+ continue;
148
+ try {
149
+ const d = await getAppDetail({ auth: args.auth, verId, timeoutMs: args.timeoutMs });
150
+ const ss = d?.screenShots;
151
+ if (Array.isArray(ss) && ss.length > 0) {
152
+ console.error(`[meizu] 复用历史版本 ${verId} 的截图(${ss.length} 张)`);
153
+ return ss;
154
+ }
155
+ }
156
+ catch {
157
+ /* 忽略单个历史版本详情失败,继续找下一个 */
158
+ }
159
+ }
160
+ return [];
161
+ }
162
+ /** 发布新版本:复用 detail 字段,覆盖 packageUrl/verDesc/icon/screenShots。返回新 verId。 */
163
+ export async function publish(args) {
164
+ const uri = '/open/api/v1/app/publish';
165
+ const detail = args.detail ?? {};
166
+ const certificatesRaw = detail.certificates;
167
+ const certificates = Array.isArray(certificatesRaw)
168
+ ? certificatesRaw
169
+ : certificatesRaw != null
170
+ ? String(certificatesRaw).split(',')
171
+ : [];
172
+ // 文案真值守卫:仅当外部传入非空串才覆盖,否则复用线上 detail 回填(与 samsung/qq 的真值判断一致)。
173
+ // 空串 '' 是 falsy → 走 fallback,避免空文案覆盖线上已有值。
174
+ const pick = (override, fallback) => override ? override : fallback ?? null;
175
+ const payload = {
176
+ appName: pick(args.appName, detail.name),
177
+ appDesc: pick(args.description, detail.appDescription),
178
+ verDesc: args.verDesc,
179
+ // 主分类从 detail 回填,取不到再兜底 1,避免硬编码 catid:1 覆盖线上主分类。
180
+ catid: detail.category1Id ?? 1,
181
+ cat2id: detail.category2Id ?? null,
182
+ tagId: detail.tagId ?? null,
183
+ authorName: detail.authorName ?? null,
184
+ packageUrl: args.packageUrl,
185
+ icon: args.icon,
186
+ screenShots: args.screenShots,
187
+ certificates,
188
+ privacyPolicyUrl: args.privacyPolicyUrl ?? detail.privacyPolicyUrl ?? null,
189
+ keyword: detail.keyword ?? null,
190
+ recommendDesc: pick(args.summary, detail.recommendDesc),
191
+ softwareAuthorNum: detail.softwareAuthorNum ?? null,
192
+ devContact: detail.devContact ?? null,
193
+ ageBracket: detail.ageBracket ?? null,
194
+ qualifcation: detail.qualifcation ?? null,
195
+ dwmc: detail.dwmc ?? null,
196
+ zjlx: detail.zjlx ?? null,
197
+ zjhm: detail.zjhm ?? null,
198
+ yyzzjlx: detail.yyzzjlx ?? null,
199
+ yyzmc: detail.yyzmc ?? null,
200
+ yyzzjhm: detail.yyzzjhm ?? null,
201
+ yyzlxrlxfs: detail.yyzlxrlxfs ?? null,
202
+ yylb: detail.yylb ?? null,
203
+ zbzShengId: detail.zbzShengId ?? null,
204
+ };
205
+ // 诊断:publish 全字段必填,若 detail 未回吐某些备案/资质字段会导致 113001 缺少参数。
206
+ // 找出为空的必填字段(仅打印 key,不打印值,避免泄露证件号等敏感信息)。
207
+ const requiredKeys = [
208
+ 'appName', 'appDesc', 'verDesc', 'cat2id', 'tagId', 'authorName',
209
+ 'packageUrl', 'icon', 'screenShots', 'certificates', 'privacyPolicyUrl',
210
+ 'keyword', 'recommendDesc', 'softwareAuthorNum', 'devContact', 'ageBracket',
211
+ 'qualifcation', 'dwmc', 'zjlx', 'zjhm', 'yyzzjlx', 'yyzmc', 'yyzzjhm',
212
+ 'yyzlxrlxfs', 'yylb', 'zbzShengId',
213
+ ];
214
+ const missing = [];
215
+ for (const k of requiredKeys) {
216
+ const v = payload[k];
217
+ if (v === null ||
218
+ v === undefined ||
219
+ (typeof v === 'string' && v.length === 0) ||
220
+ (Array.isArray(v) && v.length === 0)) {
221
+ missing.push(k);
222
+ }
223
+ }
224
+ console.error(`[meizu] detail 返回字段: ${JSON.stringify(Object.keys(detail))}`);
225
+ if (missing.length > 0) {
226
+ console.error(`[meizu] publish 必填但为空的字段(来自 detail 复用): ${missing.join(', ')}`);
227
+ }
228
+ const headers = { ...commonHeaders(uri, args.auth), 'Content-Type': 'application/json' };
229
+ const res = await fetch(`${BASE}${uri}`, {
230
+ method: 'POST',
231
+ headers,
232
+ body: JSON.stringify(payload),
233
+ signal: AbortSignal.timeout(args.timeoutMs),
234
+ });
235
+ const respBody = await res.text();
236
+ console.error(`[meizu] publish resp: ${redactSensitive(respBody).slice(0, 500)}`);
237
+ const data = JSON.parse(respBody);
238
+ if (Number(data?.code ?? -1) !== 200) {
239
+ const code = data?.code ?? -1;
240
+ // 魅族错误响应字段可能是 msg 或 message;都空时带上原始响应,便于定位 113046 这类服务端拒绝。
241
+ const rawMsg = data?.msg ?? data?.message;
242
+ const base = rawMsg != null && String(rawMsg).length > 0
243
+ ? `${rawMsg}(resp: ${respBody})`
244
+ : `publish error(resp: ${respBody})`;
245
+ const hint = missing.length === 0 ? '' : `;疑似缺失字段(detail 未回吐): ${missing.join(', ')}`;
246
+ throw new UploadError(code, `${base}${hint}`);
247
+ }
248
+ return Number(data.value.verId);
249
+ }
250
+ /** 应用状态码 → 文案(见文档附录 3.12.6)。 */
251
+ export function meizuStatusText(status) {
252
+ switch (Number(status)) {
253
+ case 20:
254
+ return '待审核';
255
+ case 30:
256
+ return '审核不通过';
257
+ case 50:
258
+ return '上架';
259
+ case 70:
260
+ return '下架';
261
+ case 100:
262
+ return '审核中';
263
+ default:
264
+ return `status=${status}`;
265
+ }
266
+ }
267
+ /**
268
+ * 完整传报:换 token → 传包 → 传图标 → 取线上详情/截图 → 发布新版本。
269
+ *
270
+ * 魅族 /app/detail 不回吐 icon/screenShots:icon 用 APK 提取图标重新上传,
271
+ * screenShots 复用线上已有(detail 或历史版本)。
272
+ *
273
+ * 幂等:publish 实际成功后服务端会保存版本,但重复提交会被拒为 113046/113040。
274
+ * 因此发布前先比对线上最新版本号,已是本包版本则跳过;publish 报错后再复查,
275
+ * 若版本已出现则判定为成功(避免“其实传上去了却报错”)。
276
+ */
277
+ export async function uploadMeizu(args) {
278
+ console.error('[meizu] get token');
279
+ const accessToken = await getToken({
280
+ clientId: args.clientId,
281
+ clientSecret: args.clientSecret,
282
+ timeoutMs: args.timeoutMs,
283
+ });
284
+ const auth = { clientId: args.clientId, clientSecret: args.clientSecret, accessToken };
285
+ console.error(`[meizu] find app for ${args.packageName}`);
286
+ const app = await findAppByPackage({ auth, packageName: args.packageName, timeoutMs: args.timeoutMs });
287
+ // 幂等预检:线上最新版本已是本包版本 → 视为已提交,跳过
288
+ if (String(app?.versionName) === args.versionName) {
289
+ console.error(`[meizu] 版本 ${args.versionName} 已是最新提交版本(${meizuStatusText(app?.status)}),跳过 publish,视为成功`);
290
+ return;
291
+ }
292
+ console.error('[meizu] upload apk');
293
+ const packageUrl = await uploadApk({
294
+ auth,
295
+ apkBytes: args.apkBytes,
296
+ apkFilename: args.apkFilename,
297
+ timeoutMs: args.uploadTimeoutMs,
298
+ });
299
+ console.error('[meizu] upload icon');
300
+ const iconPath = await uploadImage({
301
+ auth,
302
+ imageBytes: args.iconBytes,
303
+ imageFilename: args.iconFilename,
304
+ contentType: args.iconContentType,
305
+ timeoutMs: args.uploadTimeoutMs,
306
+ });
307
+ const detail = await getAppDetail({ auth, verId: String(app?.verId), timeoutMs: args.timeoutMs });
308
+ // 截图:外部提供则逐张 /image/upload 得 destFileName 覆盖 screenShots;空则复用线上/历史(detail 或历史版本)。
309
+ let screenShots;
310
+ if (args.screenshotImages && args.screenshotImages.length > 0) {
311
+ console.error(`[meizu] upload ${args.screenshotImages.length} screenshot(s)`);
312
+ screenShots = [];
313
+ for (const img of args.screenshotImages) {
314
+ const dest = await uploadImage({
315
+ auth,
316
+ imageBytes: img.bytes,
317
+ imageFilename: img.filename,
318
+ contentType: img.contentType,
319
+ timeoutMs: args.uploadTimeoutMs,
320
+ });
321
+ screenShots.push(dest);
322
+ }
323
+ }
324
+ else {
325
+ screenShots = await resolveScreenShots({
326
+ auth,
327
+ appId: String(app?.id),
328
+ detail,
329
+ timeoutMs: args.timeoutMs,
330
+ });
331
+ if (screenShots.length === 0) {
332
+ throw new UploadError(113001, '魅族缺少应用截图(detail 与历史版本均未返回 screenShots),请先在 Flyme 控制台为该应用配置截图后重试');
333
+ }
334
+ }
335
+ console.error('[meizu] publish new version');
336
+ try {
337
+ const verId = await publish({
338
+ auth,
339
+ detail,
340
+ packageUrl,
341
+ icon: iconPath,
342
+ screenShots,
343
+ verDesc: args.verDesc,
344
+ appName: args.appName,
345
+ summary: args.summary,
346
+ description: args.description,
347
+ privacyPolicyUrl: args.privacyUrl,
348
+ timeoutMs: args.timeoutMs,
349
+ });
350
+ console.error(`[meizu] published, verId=${verId}`);
351
+ }
352
+ catch (e) {
353
+ // publish 报错后复查:服务端可能其实已创建该版本(如 113046/113040)
354
+ try {
355
+ const after = await findAppByPackage({ auth, packageName: args.packageName, timeoutMs: args.timeoutMs });
356
+ if (String(after?.versionName) === args.versionName) {
357
+ console.error(`[meizu] publish 返回错误但版本 ${args.versionName} 已出现(${meizuStatusText(after?.status)}),判定为成功: ${e instanceof Error ? e.message : String(e)}`);
358
+ return;
359
+ }
360
+ }
361
+ catch {
362
+ /* 复查失败则按原始错误抛出 */
363
+ }
364
+ throw e;
365
+ }
366
+ }
367
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/adapters/android/meizu/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ // upload 即「上传 + 发布新版本(提交审核)」,无「只传不提审」模式 → action 恒为 upload+submit。
2
+ import { readFile } from 'node:fs/promises';
3
+ import { basename } from 'node:path';
4
+ import { toFailed } from '../../util.js';
5
+ import { prepareScreenshot } from '../../../pkginfo/icon.js';
6
+ import { resolveIconBytes } from '../../../pkginfo/apk-icon.js';
7
+ import { getChannelSpec, warnIfTooLong } from '../specs.js';
8
+ import { findAppByPackage, getToken, meizuStatusText, uploadMeizu } from './api.js';
9
+ /** 大文件上传超时下限 15min。 */
10
+ const MIN_UPLOAD_TIMEOUT_MS = 900_000;
11
+ /** 魅族应用状态码(/app/list 的 status)→ 归一化状态。 */
12
+ function mapStatus(status) {
13
+ switch (Number(status)) {
14
+ case 20: // 待审核
15
+ return 'submitted';
16
+ case 30: // 审核不通过
17
+ return 'rejected';
18
+ case 50: // 上架
19
+ return 'published';
20
+ case 70: // 下架
21
+ return 'offline';
22
+ case 100: // 审核中
23
+ return 'pending_review';
24
+ default:
25
+ return 'pending_review';
26
+ }
27
+ }
28
+ export class MeizuAdapter {
29
+ channel = 'meizu';
30
+ async upload(ctx) {
31
+ const start = Date.now();
32
+ try {
33
+ const spec = getChannelSpec('meizu');
34
+ // 魅族 publish 必须带图标:优先 --icon,否则用 aapt 从 APK 自动提取(缩放 spec.iconSize²,≤spec.iconMaxBytes)。
35
+ const iconBytes = await resolveIconBytes({
36
+ iconPath: ctx.iconPath,
37
+ apkPath: ctx.pkg,
38
+ size: spec.iconSize,
39
+ maxBytes: spec.iconMaxBytes,
40
+ });
41
+ // 文案:按需覆盖线上回填值,写前做长度告警(不阻断,最终以渠道后台为准)。
42
+ warnIfTooLong('meizu', 'appName', ctx.appName, spec.appNameMax);
43
+ warnIfTooLong('meizu', 'summary', ctx.summary, spec.summaryMax);
44
+ warnIfTooLong('meizu', 'description', ctx.description, spec.descriptionMax);
45
+ // 截图:仅当 --screenshots 非空时编码为 jpg 后逐张上传覆盖;空则复用线上/历史。
46
+ let screenshotImages;
47
+ if (ctx.screenshots && ctx.screenshots.length > 0) {
48
+ screenshotImages = [];
49
+ for (let i = 0; i < ctx.screenshots.length; i++) {
50
+ const p = ctx.screenshots[i];
51
+ const bytes = await prepareScreenshot(p, 'jpg', spec.screenshotMaxBytes);
52
+ screenshotImages.push({
53
+ bytes,
54
+ filename: `screenshot_${i + 1}.jpg`,
55
+ contentType: 'image/jpeg',
56
+ });
57
+ }
58
+ }
59
+ const apkBytes = await readFile(ctx.pkg);
60
+ await uploadMeizu({
61
+ clientId: ctx.creds.access_key,
62
+ clientSecret: ctx.creds.access_secret,
63
+ packageName: ctx.packageName,
64
+ apkBytes,
65
+ apkFilename: basename(ctx.pkg),
66
+ iconBytes,
67
+ iconFilename: 'icon.png',
68
+ iconContentType: 'image/png',
69
+ versionName: ctx.versionName,
70
+ verDesc: ctx.releaseNote ?? '',
71
+ privacyUrl: ctx.privacyUrl,
72
+ appName: ctx.appName,
73
+ summary: ctx.summary,
74
+ description: ctx.description,
75
+ screenshotImages,
76
+ timeoutMs: ctx.timeoutMs,
77
+ uploadTimeoutMs: Math.max(ctx.timeoutMs, MIN_UPLOAD_TIMEOUT_MS),
78
+ });
79
+ return {
80
+ channel: this.channel,
81
+ packageName: ctx.packageName,
82
+ versionName: ctx.versionName,
83
+ versionCode: ctx.versionCode,
84
+ action: 'upload+submit',
85
+ status: 'submitted',
86
+ errorCode: null,
87
+ durationMs: Date.now() - start,
88
+ };
89
+ }
90
+ catch (e) {
91
+ return toFailed(this.channel, e, start, 'upload+submit', ctx);
92
+ }
93
+ }
94
+ async queryStatus(ctx) {
95
+ const start = Date.now();
96
+ try {
97
+ const accessToken = await getToken({
98
+ clientId: ctx.creds.access_key,
99
+ clientSecret: ctx.creds.access_secret,
100
+ timeoutMs: ctx.timeoutMs,
101
+ });
102
+ const auth = {
103
+ clientId: ctx.creds.access_key,
104
+ clientSecret: ctx.creds.access_secret,
105
+ accessToken,
106
+ };
107
+ const app = await findAppByPackage({
108
+ auth,
109
+ packageName: ctx.packageName ?? '',
110
+ timeoutMs: ctx.timeoutMs,
111
+ });
112
+ return {
113
+ channel: this.channel,
114
+ packageName: ctx.packageName,
115
+ versionName: app?.versionName != null ? String(app.versionName) : undefined,
116
+ action: 'status',
117
+ status: mapStatus(app?.status),
118
+ marketVersion: app?.versionName != null ? String(app.versionName) : undefined,
119
+ errorCode: null,
120
+ message: meizuStatusText(app?.status),
121
+ durationMs: Date.now() - start,
122
+ };
123
+ }
124
+ catch (e) {
125
+ return toFailed(this.channel, e, start, 'status');
126
+ }
127
+ }
128
+ }
129
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/android/meizu/index.ts"],"names":[],"mappings":"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"}