@applift/core 0.1.2 → 0.1.3

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/dist/index.d.mts CHANGED
@@ -311,10 +311,17 @@ export declare class AgcHarmonyChannel implements Channel {
311
311
  stage(ctx: ChannelContext): Promise<StageResult>;
312
312
  /** submit = v1 releaseHarmonyApp 完整链路:上传+绑定+文案 → 等编译轮询 → 提审(带重试) */
313
313
  submit(ctx: ChannelContext): Promise<SubmitResult>;
314
+ /** 轮询软件包云端编译:successStatus 0=成功 2=拒绝(终态,多为签名/证书/bundleName 不匹配)其他=编译中 */
315
+ private awaitCompile;
314
316
  status(): Promise<ReviewStatus>;
315
317
  /** v1 releaseHarmonyApp step 1-4:.app 校验 → 上传地址 → PUT 整包 → v3 绑定(releaseType=1)→ 文案(不阻断) */
316
318
  private uploadFormal;
317
- /** v1 uploadToAgc(releaseType=6 测试发布):上传 → 绑定(不阻断)→ 文案(不阻断),不提审 */
319
+ /**
320
+ * 测试发布(releaseType=6,2026-10 起走 Testing API——旧 app-package-info 直绑链路已被华为下线,
321
+ * 其 releaseType 枚举仅剩 1=全网 / 7=企业非公开):
322
+ * 上传 .hap → 新建测试版本(testType=3 邀请测试)→ 添加测试软件包 → 等云端编译 → 更新测试版本绑定;
323
+ * 不自动提交审核,测试群组/邀请码由控制台人工完成。
324
+ */
318
325
  private uploadBeta;
319
326
  /** v1 更新文案段(releaseHarmonyApp step 4 / uploadToAgc 尾段):查默认语言 → 写 newFeatures,失败仅警告不阻断 */
320
327
  private updateReleaseNotes;
package/dist/index.mjs CHANGED
@@ -447,7 +447,7 @@ var PgyerChannel = class {
447
447
  phase: "wait",
448
448
  message: "等待蒲公英处理"
449
449
  });
450
- const deadline = Date.now() + 3e5;
450
+ const deadline = Date.now() + 9e5;
451
451
  while (Date.now() < deadline) {
452
452
  await sleep(3e3);
453
453
  const info = await pgyerPost(HOSTS[0], "/apiv2/app/buildInfo", {
@@ -472,7 +472,7 @@ var PgyerChannel = class {
472
472
  }
473
473
  return {
474
474
  ok: false,
475
- error: "蒲公英 5 分钟内未完成处理"
475
+ error: "蒲公英 15 分钟内未完成处理(大包云端处理慢属正常,可到 pgyer.com 控制台确认实际状态)"
476
476
  };
477
477
  }
478
478
  async submit() {
@@ -2072,9 +2072,13 @@ var YybChannel = class {
2072
2072
  * 5. GET /api/publish/v3/package/compile/status 轮询编译(0=成功 2=拒绝终态 其他=编译中)
2073
2073
  * 6. POST /api/publish/v3/app-submit 提审(ret 204144719/204144727 = 编译中可重试)
2074
2074
  *
2075
- * 内测测试发布(ctx.target.releaseType === '6',Upload Management API):
2076
- * upload-url/for-obs 带 releaseType=6,传 .hap 即可,后续在 AGC 控制台「测试」中指定测试设备(不做自动提审)。
2077
- * 官方文档: https://developer.huawei.com/consumer/cn/doc/app/agc-help-upload-api-guide-0000002271160549
2075
+ * 测试发布(ctx.target.releaseType === '6',2026-10 起走 Testing API;旧 releaseType=6 直绑 app-package-info 链路已下线,枚举仅剩 1/7):
2076
+ * 0. GET /api/publish/v2/upload-url/for-obs?releaseType=6 .hap 上传地址 → PUT OBS
2077
+ * 1. POST /api/publish/v2/test/app/version 新建测试版本(testType 3=邀请测试)→ versionId
2078
+ * 2. POST /api/publish/v2/test/version/pkg 添加测试软件包(distributeMode=1)→ pkgId
2079
+ * 3. GET /api/publish/v3/package/compile/status 轮询云端编译
2080
+ * 4. PUT /api/publish/v2/test/app/version {versionId, pkgId} 绑定;提交审核/测试群组由控制台人工完成。
2081
+ * 官方文档: https://developer.huawei.com/consumer/cn/doc/doccenter-connect-api/agc-help-test-api-guide-0000002236015562
2078
2082
  */
2079
2083
  const BASE = "https://connect-api.cloud.huawei.com/api";
2080
2084
  const COMPILE_TIMEOUT_MS = 9e5;
@@ -2100,11 +2104,16 @@ async function agcJson(url, init, context) {
2100
2104
  * appId 缺省时由渠道内部调用,也可独立复用。
2101
2105
  */
2102
2106
  async function getHarmonyAppId(opts) {
2103
- const qs = new URLSearchParams({ packageTypes: "7" });
2107
+ const qs = new URLSearchParams({
2108
+ packageTypes: "7",
2109
+ packageName: opts.bundleName
2110
+ });
2104
2111
  const json = await agcJson(`${BASE}/publish/v2/appid-list?${qs}`, { headers: {
2105
2112
  client_id: opts.clientId,
2106
2113
  Authorization: `Bearer ${opts.token}`
2107
2114
  } }, "查询应用列表");
2115
+ const fresh = json.appids?.[0]?.value;
2116
+ if (fresh) return fresh;
2108
2117
  const list = json.appIds ?? json.appIdList ?? [];
2109
2118
  const hit = (Array.isArray(list) ? list : []).find((e) => String(e.bundleName ?? e.BundleName ?? "").toLowerCase() === opts.bundleName.toLowerCase());
2110
2119
  if (!hit) throw new Error(`AGC 未找到 bundleName=${opts.bundleName} 的鸿蒙应用(packageTypes=7)`);
@@ -2172,7 +2181,7 @@ var AgcHarmonyChannel = class {
2172
2181
  artifactVersion: "",
2173
2182
  action: "stage-only",
2174
2183
  afterApproval: "none(beta)",
2175
- notes: "releaseType=6 测试发布:仅上传+绑定,到 AGC 控制台「测试」指定测试设备,不提审"
2184
+ notes: "Testing API 邀请测试:上传→新建测试版本→绑定软件包;提交审核与测试群组到控制台完成,不自动提审"
2176
2185
  };
2177
2186
  return {
2178
2187
  channel: this.id,
@@ -2203,7 +2212,7 @@ var AgcHarmonyChannel = class {
2203
2212
  async submit(ctx) {
2204
2213
  if (ctx.target.releaseType === "6") return {
2205
2214
  ok: false,
2206
- error: "AGC 测试发布(releaseType=6)不做自动提审,请到 AGC 控制台「测试」中指定测试设备"
2215
+ error: "AGC 测试发布(releaseType=6)不做自动提审,请到 AGC 控制台「测试」提交测试版本并指定测试群组"
2207
2216
  };
2208
2217
  const { clientId, token, headers } = await this.authHeaders(ctx);
2209
2218
  const appId = await this.resolveAppId(ctx, clientId, token);
@@ -2213,36 +2222,7 @@ var AgcHarmonyChannel = class {
2213
2222
  message: "token 获取成功"
2214
2223
  });
2215
2224
  const { packageId } = await this.uploadFormal(ctx, appId, headers);
2216
- if (packageId) {
2217
- ctx.emit({
2218
- type: "phase",
2219
- phase: "wait",
2220
- message: `等待 AGC 云端编译(packageId: ${packageId})`
2221
- });
2222
- const deadline = Date.now() + COMPILE_TIMEOUT_MS;
2223
- for (;;) {
2224
- const stQs = new URLSearchParams({
2225
- appId,
2226
- pkgIds: packageId
2227
- });
2228
- const st = await agcJson(`${BASE}/publish/v3/package/compile/status?${stQs}`, { headers }, "查询编译状态");
2229
- const s = (st.pkgStateList?.find((p) => p.pkgId === packageId) ?? st.pkgStateList?.[0])?.successStatus;
2230
- if (s === 0) {
2231
- ctx.emit({
2232
- type: "progress",
2233
- detail: "软件包编译完成"
2234
- });
2235
- break;
2236
- }
2237
- if (s === 2) throw new Error(`AGC 编译拒绝(packageId ${packageId}):签名/证书/bundleName 不匹配,到 AGC 控制台核对`);
2238
- if (Date.now() > deadline) throw new Error(`AGC 编译超时(${COMPILE_TIMEOUT_MS / 6e4} 分钟,packageId ${packageId})`);
2239
- ctx.emit({
2240
- type: "progress",
2241
- detail: `编译中(successStatus=${s}),${COMPILE_POLL_MS / 1e3}s 后重查…`
2242
- });
2243
- await sleep(COMPILE_POLL_MS);
2244
- }
2245
- }
2225
+ if (packageId) await this.awaitCompile(ctx, appId, packageId, headers);
2246
2226
  ctx.emit({
2247
2227
  type: "phase",
2248
2228
  phase: "submit"
@@ -2279,6 +2259,37 @@ var AgcHarmonyChannel = class {
2279
2259
  return { ok: true };
2280
2260
  }
2281
2261
  }
2262
+ /** 轮询软件包云端编译:successStatus 0=成功 2=拒绝(终态,多为签名/证书/bundleName 不匹配)其他=编译中 */
2263
+ async awaitCompile(ctx, appId, pkgId, headers) {
2264
+ ctx.emit({
2265
+ type: "phase",
2266
+ phase: "wait",
2267
+ message: `等待 AGC 云端编译(pkgId: ${pkgId})`
2268
+ });
2269
+ const deadline = Date.now() + COMPILE_TIMEOUT_MS;
2270
+ for (;;) {
2271
+ const stQs = new URLSearchParams({
2272
+ appId,
2273
+ pkgIds: pkgId
2274
+ });
2275
+ const st = await agcJson(`${BASE}/publish/v3/package/compile/status?${stQs}`, { headers }, "查询编译状态");
2276
+ const s = (st.pkgStateList?.find((p) => p.pkgId === pkgId) ?? st.pkgStateList?.[0])?.successStatus;
2277
+ if (s === 0) {
2278
+ ctx.emit({
2279
+ type: "progress",
2280
+ detail: "软件包编译完成"
2281
+ });
2282
+ return;
2283
+ }
2284
+ if (s === 2) throw new Error(`AGC 编译拒绝(pkgId ${pkgId}):签名/证书/bundleName 不匹配,到 AGC 控制台核对`);
2285
+ if (Date.now() > deadline) throw new Error(`AGC 编译超时(${COMPILE_TIMEOUT_MS / 6e4} 分钟,pkgId ${pkgId})`);
2286
+ ctx.emit({
2287
+ type: "progress",
2288
+ detail: `编译中(successStatus=${s}),${COMPILE_POLL_MS / 1e3}s 后重查…`
2289
+ });
2290
+ await sleep(COMPILE_POLL_MS);
2291
+ }
2292
+ }
2282
2293
  async status() {
2283
2294
  return {
2284
2295
  state: "unknown",
@@ -2355,15 +2366,21 @@ var AgcHarmonyChannel = class {
2355
2366
  packageId
2356
2367
  };
2357
2368
  }
2358
- /** v1 uploadToAgc(releaseType=6 测试发布):上传 → 绑定(不阻断)→ 文案(不阻断),不提审 */
2369
+ /**
2370
+ * 测试发布(releaseType=6,2026-10 起走 Testing API——旧 app-package-info 直绑链路已被华为下线,
2371
+ * 其 releaseType 枚举仅剩 1=全网 / 7=企业非公开):
2372
+ * 上传 .hap → 新建测试版本(testType=3 邀请测试)→ 添加测试软件包 → 等云端编译 → 更新测试版本绑定;
2373
+ * 不自动提交审核,测试群组/邀请码由控制台人工完成。
2374
+ */
2359
2375
  async uploadBeta(ctx, appId, headers) {
2360
2376
  const fileName = path.basename(ctx.artifactPath);
2361
2377
  const contentLength = fs.statSync(ctx.artifactPath).size;
2362
2378
  const sha256 = sha256File(ctx.artifactPath);
2379
+ if (path.extname(ctx.artifactPath).toLowerCase() !== ".app") throw new Error("AGC 测试发布需要 .app 整包(DevEco「构建 App」产物,发布签名);Testing API 不再接受 .hap(实测 204144641)");
2363
2380
  ctx.emit({
2364
2381
  type: "phase",
2365
2382
  phase: "upload",
2366
- message: `AGC 上传 ${fileName}(${formatSize(contentLength)},releaseType=6 测试发布)`
2383
+ message: `AGC 上传 ${fileName}(${formatSize(contentLength)},测试发布)`
2367
2384
  });
2368
2385
  const qs = new URLSearchParams({
2369
2386
  appId,
@@ -2376,6 +2393,7 @@ var AgcHarmonyChannel = class {
2376
2393
  const urlInfo = urlJson.urlInfo ?? urlJson;
2377
2394
  const objectId = urlInfo.objectId ?? "";
2378
2395
  if (!urlInfo.url) throw new Error(`AGC 返回的上传地址为空: ${JSON.stringify(urlJson).slice(0, 300)}`);
2396
+ if (!objectId) throw new Error("AGC 上传响应缺 objectId(Testing API 添加软件包必需)");
2379
2397
  ctx.emit({
2380
2398
  type: "progress",
2381
2399
  detail: "上传地址获取成功(5 分钟内有效)"
@@ -2399,46 +2417,59 @@ var AgcHarmonyChannel = class {
2399
2417
  type: "progress",
2400
2418
  detail: "文件上传完成"
2401
2419
  });
2402
- if (objectId) try {
2403
- const bindQs = new URLSearchParams({
2404
- appId,
2405
- releaseType: "6"
2406
- });
2407
- await agcJson(`${BASE}/publish/v3/app-package-info?${bindQs}`, {
2408
- method: "PUT",
2409
- headers: {
2410
- ...headers,
2411
- "Content-Type": "application/json"
2412
- },
2413
- body: JSON.stringify({
2420
+ const versionId = (await agcJson(`${BASE}/publish/v2/test/app/version?appId=${encodeURIComponent(appId)}`, {
2421
+ method: "POST",
2422
+ headers: {
2423
+ ...headers,
2424
+ "Content-Type": "application/json"
2425
+ },
2426
+ body: JSON.stringify({
2427
+ releaseType: 6,
2428
+ testType: 3,
2429
+ testDesc: (ctx.updateDescription ?? "applift 测试发布").slice(0, 50)
2430
+ })
2431
+ }, "新建测试版本")).versionId ?? "";
2432
+ if (!versionId) throw new Error("AGC 新建测试版本未返回 versionId");
2433
+ ctx.emit({
2434
+ type: "phase",
2435
+ phase: "bind",
2436
+ message: `测试版本已创建(versionId: ${versionId})`
2437
+ });
2438
+ const pkgId = (await agcJson(`${BASE}/publish/v2/test/version/pkg?appId=${encodeURIComponent(appId)}`, {
2439
+ method: "POST",
2440
+ headers: {
2441
+ ...headers,
2442
+ "Content-Type": "application/json"
2443
+ },
2444
+ body: JSON.stringify({
2445
+ distributeMode: 1,
2446
+ file: {
2414
2447
  fileName,
2415
2448
  objectId
2416
- })
2417
- }, "绑定软件包");
2418
- ctx.emit({
2419
- type: "phase",
2420
- phase: "bind",
2421
- message: "软件包已绑定到应用"
2422
- });
2423
- } catch (e) {
2424
- ctx.emit({
2425
- type: "warn",
2426
- message: `软件包绑定未成功(不阻断,必要时到控制台手动关联): ${e.message}`
2427
- });
2428
- }
2429
- const langQs = new URLSearchParams({
2430
- appId,
2431
- releaseType: "6"
2432
- });
2433
- await this.updateReleaseNotes(ctx, appId, headers, langQs);
2449
+ }
2450
+ })
2451
+ }, "添加测试软件包")).pkgVersion?.[0] ?? "";
2452
+ if (!pkgId) throw new Error("AGC 添加测试软件包未返回 pkgVersion");
2453
+ await this.awaitCompile(ctx, appId, pkgId, headers);
2454
+ await agcJson(`${BASE}/publish/v2/test/app/version?appId=${encodeURIComponent(appId)}`, {
2455
+ method: "PUT",
2456
+ headers: {
2457
+ ...headers,
2458
+ "Content-Type": "application/json"
2459
+ },
2460
+ body: JSON.stringify({
2461
+ versionId,
2462
+ pkgId
2463
+ })
2464
+ }, "绑定测试软件包");
2434
2465
  ctx.emit({
2435
2466
  type: "phase",
2436
2467
  phase: "done",
2437
- message: "测试包已上传;后续在 AGC 控制台「我的应用 → 测试」中查看并指定测试设备/人员"
2468
+ message: "测试版本已就绪(未提交审核);到 AGC 控制台「测试」提交并指定测试群组"
2438
2469
  });
2439
2470
  return {
2440
2471
  ok: true,
2441
- ref: objectId
2472
+ ref: versionId
2442
2473
  };
2443
2474
  }
2444
2475
  /** v1 更新文案段(releaseHarmonyApp step 4 / uploadToAgc 尾段):查默认语言 → 写 newFeatures,失败仅警告不阻断 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applift/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/hcg1023/applift.git",