@applift/core 0.11.0 → 0.12.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.
@@ -184,6 +184,8 @@ declare const BetaConfigSchema: z.ZodObject<{
184
184
  submit: z.ZodDefault<z.ZodBoolean>;
185
185
  group: z.ZodOptional<z.ZodString>;
186
186
  testType: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<3>, z.ZodLiteral<4>]>>;
187
+ privacyPolicy: z.ZodOptional<z.ZodString>;
188
+ appDesc: z.ZodOptional<z.ZodString>;
187
189
  cleanup: z.ZodDefault<z.ZodBoolean>;
188
190
  }, z.core.$strip>>;
189
191
  testflight: z.ZodOptional<z.ZodObject<{
@@ -297,6 +299,8 @@ declare const ProjectConfigSchema: z.ZodObject<{
297
299
  submit: z.ZodDefault<z.ZodBoolean>;
298
300
  group: z.ZodOptional<z.ZodString>;
299
301
  testType: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<3>, z.ZodLiteral<4>]>>;
302
+ privacyPolicy: z.ZodOptional<z.ZodString>;
303
+ appDesc: z.ZodOptional<z.ZodString>;
300
304
  cleanup: z.ZodDefault<z.ZodBoolean>;
301
305
  }, z.core.$strip>>;
302
306
  testflight: z.ZodOptional<z.ZodObject<{
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as ProjectConfigSchema, A as routeDelivery, B as appendEntry, C as resolvePlugins, Ct as readJson, D as PublishContext, E as FrameworkContext, F as runSubmit, G as BetaVersionConfigSchema, H as BetaConfig, I as HISTORY_PATH, J as CredentialsProfile, K as CredentialsFile, L as HistoryEntry, M as PipelineSummary, N as PipelineSummaryEntry, O as UpdateProvider, P as runStage, Q as ProjectConfig, R as HistoryEvent, S as defineConfig, St as findArtifacts, T as DeliveryRoute, Tt as subdirs, U as BetaConfigSchema, V as readEntries, W as BetaVersionConfig, X as GlobalConfig, Y as CredentialsProfileSchema, Z as GlobalConfigSchema, _ as AppliftPlugin, _t as BundleIds, a as knownFrameworkAdapters, at as VersionCodeConfigSchema, b as PluginHookName, bt as deps, c as nativeHarmonyAdapter, ct as Channel, d as nativeIosFramework, dt as ChannelEvent, et as StoreConfig, f as rnAdapter, ft as ChannelRegistry, g as tauriFramework, gt as SubmitResult, h as tauriAdapter, ht as StageResult, i as flutterFramework, it as VersionCodeConfig, j as PipelineInput, k as collectReleaseDiff, l as nativeHarmonyFramework, lt as ChannelCapabilities, m as suggestFramework, mt as ReviewStatus, n as electronFramework, nt as Stores, o as nativeAndroidAdapter, ot as VersionConfig, p as rnFramework, pt as ReleasePlanEntry, q as CredentialsFileSchema, r as flutterAdapter, rt as StoresSchema, s as nativeAndroidFramework, st as VersionConfigSchema, t as electronAdapter, tt as StoreConfigSchema, u as nativeIosAdapter, ut as ChannelContext, v as AppliftUserConfig, vt as FrameworkAdapter, w as DeliveryJudgement, wt as resolveFramework, x as PluginHost, xt as detectBundleIds, y as HookContext, yt as Platform, z as HistoryQuery } from "./frameworks-D0dZKGUL.mjs";
1
+ import { $ as ProjectConfigSchema, A as routeDelivery, B as appendEntry, C as resolvePlugins, Ct as readJson, D as PublishContext, E as FrameworkContext, F as runSubmit, G as BetaVersionConfigSchema, H as BetaConfig, I as HISTORY_PATH, J as CredentialsProfile, K as CredentialsFile, L as HistoryEntry, M as PipelineSummary, N as PipelineSummaryEntry, O as UpdateProvider, P as runStage, Q as ProjectConfig, R as HistoryEvent, S as defineConfig, St as findArtifacts, T as DeliveryRoute, Tt as subdirs, U as BetaConfigSchema, V as readEntries, W as BetaVersionConfig, X as GlobalConfig, Y as CredentialsProfileSchema, Z as GlobalConfigSchema, _ as AppliftPlugin, _t as BundleIds, a as knownFrameworkAdapters, at as VersionCodeConfigSchema, b as PluginHookName, bt as deps, c as nativeHarmonyAdapter, ct as Channel, d as nativeIosFramework, dt as ChannelEvent, et as StoreConfig, f as rnAdapter, ft as ChannelRegistry, g as tauriFramework, gt as SubmitResult, h as tauriAdapter, ht as StageResult, i as flutterFramework, it as VersionCodeConfig, j as PipelineInput, k as collectReleaseDiff, l as nativeHarmonyFramework, lt as ChannelCapabilities, m as suggestFramework, mt as ReviewStatus, n as electronFramework, nt as Stores, o as nativeAndroidAdapter, ot as VersionConfig, p as rnFramework, pt as ReleasePlanEntry, q as CredentialsFileSchema, r as flutterAdapter, rt as StoresSchema, s as nativeAndroidFramework, st as VersionConfigSchema, t as electronAdapter, tt as StoreConfigSchema, u as nativeIosAdapter, ut as ChannelContext, v as AppliftUserConfig, vt as FrameworkAdapter, w as DeliveryJudgement, wt as resolveFramework, x as PluginHost, xt as detectBundleIds, y as HookContext, yt as Platform, z as HistoryQuery } from "./frameworks-B-t5Ywma.mjs";
2
2
  //#region src/registry.d.ts
3
3
  export declare class DefaultChannelRegistry implements ChannelRegistry {
4
4
  private readonly channels;
package/dist/index.mjs CHANGED
@@ -92,6 +92,18 @@ const BetaConfigSchema = z.object({
92
92
  /** 3=邀请测试(默认)4=公开测试 */
93
93
  testType: z.union([z.literal(3), z.literal(4)]).default(3),
94
94
  /**
95
+ * 隐私政策 URL(提审必填:AGC Testing API 校验 extInfo.privacyPolicy,
96
+ * 控制台对应版本创建时的「自定义协议」步骤;缺失提审报 204144692
97
+ * privacyPolicy is necessary——2026-10-25 qy-driver 实测)。透传 target.privacyPolicy。
98
+ */
99
+ privacyPolicy: z.string().optional(),
100
+ /**
101
+ * 测试版本描述(languages[].appDesc):AGC 校验 appDesc/newFeatures/线上 briefInfo
102
+ * 三者不得相同(2026-10-25 实测),appDesc 与 newFeatures(--note)来源必须互异。
103
+ * 未配置时用通用基线文案;透传 target.appDesc。
104
+ */
105
+ appDesc: z.string().optional(),
106
+ /**
95
107
  * 发布前自动清理旧测试版本(stop+delete,默认 true):
96
108
  * AGC 测试版本在审/在架数量有上限(在审超限提交报 204144692、在架邀请测试 3 个),
97
109
  * 旧版本不清理会阻塞新版本提审。清理只移除 AGC 在架记录——已装设备与热更均不受影响,
@@ -2550,7 +2562,7 @@ var AgcHarmonyChannel = class {
2550
2562
  "1003": "client_id/client_secret 无效(AGC → 项目设置 → 常规 → API Client 重新获取)",
2551
2563
  "204144702": "签名/证书不匹配:检查签名证书指纹(SHA256)与 AGC 后台登记是否一致",
2552
2564
  "204144677": "bundleName 与应用不匹配:确认 appId 对应的应用包名",
2553
- "204144692": "提审前置校验失败(按 msg 判断):privacyPolicy → 控制台「更多服务→协议服务」登记隐私政策;count of harmony test in audit → 在审测试版本超限(beta.agc.cleanup 默认已自动清理,仍出现请到控制台核对是否有删不掉的旧测试版本)"
2565
+ "204144692": "提审前置校验失败(按 msg 对症,2026-10-25 实测):privacyPolicy → 配置 beta.agc.privacyPolicy(Testing API extInfo.privacyPolicy,控制台对应版本创建的「自定义协议」);displayArea → 邀请测试必填测试专区(CLI 已默认携带,仍报则到控制台核对版本);count of harmony test in audit → 在审测试版本超限(beta.agc.cleanup 默认已自动清理,仍出现请到控制台核对是否有删不掉的旧测试版本)"
2554
2566
  };
2555
2567
  async authHeaders(ctx) {
2556
2568
  const clientId = required$1(ctx, "AGC_CLIENT_ID");
@@ -2934,6 +2946,10 @@ var AgcHarmonyChannel = class {
2934
2946
  }, "添加测试软件包")).pkgVersion?.[0] ?? "";
2935
2947
  if (!pkgId) throw new Error("AGC 添加测试软件包未返回 pkgVersion");
2936
2948
  await this.awaitCompile(ctx, appId, pkgId, headers);
2949
+ const privacyPolicy = ctx.target.privacyPolicy?.trim();
2950
+ const note = ctx.updateDescription ?? "applift 测试发布";
2951
+ const appDesc = (ctx.target.appDesc?.trim() || "内测验证版本(internal test build),更新内容以新特性说明为准。").slice(0, 100);
2952
+ const newFeatures = note.slice(0, 100);
2937
2953
  await agcJson(`${BASE}/publish/v2/test/app/version?appId=${encodeURIComponent(appId)}`, {
2938
2954
  method: "PUT",
2939
2955
  headers: {
@@ -2942,7 +2958,13 @@ var AgcHarmonyChannel = class {
2942
2958
  },
2943
2959
  body: JSON.stringify({
2944
2960
  versionId,
2945
- pkgId
2961
+ pkgId,
2962
+ ...privacyPolicy ? { extInfo: { privacyPolicy } } : {},
2963
+ languages: [{
2964
+ language: "zh-CN",
2965
+ appDesc,
2966
+ newFeatures
2967
+ }]
2946
2968
  })
2947
2969
  }, "绑定测试软件包");
2948
2970
  if (ctx.target.submitTest === "true") {
@@ -2962,10 +2984,13 @@ var AgcHarmonyChannel = class {
2962
2984
  openTestInfo: {
2963
2985
  startTime: now,
2964
2986
  endTime: now + 2592e6,
2965
- testTaskInfo: { groupInfos: [{
2966
- groupId,
2967
- groupName
2968
- }] }
2987
+ testTaskInfo: {
2988
+ groupInfos: [{
2989
+ groupId,
2990
+ groupName
2991
+ }],
2992
+ displayArea: "1"
2993
+ }
2969
2994
  }
2970
2995
  })
2971
2996
  }, "绑定测试群组");
@@ -3069,9 +3094,11 @@ var AgcHarmonyChannel = class {
3069
3094
  body: JSON.stringify({ versionId: vid })
3070
3095
  }, "停止测试版本");
3071
3096
  } catch (e) {
3097
+ const msg = e.message;
3098
+ const hint = msg.includes("state is 9998") ? "——该版本在审中,AGC 不允许停/删:到控制台撤回该审核或等审毕后下次发版自动清理" : "";
3072
3099
  ctx.emit({
3073
3100
  type: "warn",
3074
- message: `停止测试版本 ${label}失败(继续尝试删除): ${e.message}`
3101
+ message: `停止测试版本 ${label}失败(继续尝试删除): ${msg}${hint}`
3075
3102
  });
3076
3103
  }
3077
3104
  try {
@@ -1,4 +1,4 @@
1
- import { E as FrameworkContext, O as UpdateProvider, W as BetaVersionConfig, _ as AppliftPlugin, a as knownFrameworkAdapters, c as nativeHarmonyAdapter, d as nativeIosFramework, f as rnAdapter, g as tauriFramework, h as tauriAdapter, i as flutterFramework, l as nativeHarmonyFramework, m as suggestFramework, n as electronFramework, o as nativeAndroidAdapter, p as rnFramework, r as flutterAdapter, s as nativeAndroidFramework, t as electronAdapter, u as nativeIosAdapter, w as DeliveryJudgement } from "../frameworks-D0dZKGUL.mjs";
1
+ import { E as FrameworkContext, O as UpdateProvider, W as BetaVersionConfig, _ as AppliftPlugin, a as knownFrameworkAdapters, c as nativeHarmonyAdapter, d as nativeIosFramework, f as rnAdapter, g as tauriFramework, h as tauriAdapter, i as flutterFramework, l as nativeHarmonyFramework, m as suggestFramework, n as electronFramework, o as nativeAndroidAdapter, p as rnFramework, r as flutterAdapter, s as nativeAndroidFramework, t as electronAdapter, u as nativeIosAdapter, w as DeliveryJudgement } from "../frameworks-B-t5Ywma.mjs";
2
2
  //#region src/plugins/dingtalk-notify.d.ts
3
3
  interface DingtalkNotifyOptions {
4
4
  webhook: string;
@@ -44,12 +44,24 @@ interface PushyCli {
44
44
  packageVersion: string;
45
45
  rollout?: number;
46
46
  }): Promise<void>;
47
- /** 版本列表(取号与状态展示用) */
47
+ /** 版本列表(取号与状态展示用)。packageVersion:该热更绑定的原生基线版本名
48
+ * (基线自动替换的安全判据;服务端未回显时字段缺省,调用方按无法确认处理) */
48
49
  versions(appId: number): Promise<Array<{
49
50
  id: number;
50
51
  hash: string;
51
52
  name: string;
53
+ packageVersion?: string;
52
54
  }>>;
55
+ /** 基线包列表(GET /app/:id/package/list;409 自动替换的发现手段) */
56
+ packages(appId: number): Promise<Array<{
57
+ id: number;
58
+ hash: string;
59
+ name: string;
60
+ status: string;
61
+ }>>;
62
+ /** 删除基线包(DELETE /app/:id/package/:packageId,2026-10-25 实测端点存在)。
63
+ * 调用方必须先确认该基线无热更版本绑定(删除被绑定的基线会孤儿化热更)。 */
64
+ deletePackage(appId: number, packageId: number): Promise<void>;
53
65
  }
54
66
  /** credentials.json 中的 pushy token 键名 */
55
67
  export declare const PUSHY_TOKEN_KEY = "PUSHY_API_TOKEN";
@@ -94,7 +94,9 @@ async function query(f, baseUrl, token, api, init) {
94
94
  }
95
95
  if (!res.ok) {
96
96
  const msg = json?.message || res.statusText || `HTTP ${res.status}`;
97
- throw new Error(res.status === 401 ? `pushy API 鉴权失败(token 无效或过期):请更新 credentials.json 的 ${PUSHY_TOKEN_KEY}` : `pushy API ${api} 失败(HTTP ${res.status}):${msg}`);
97
+ const err = /* @__PURE__ */ new Error(res.status === 401 ? `pushy API 鉴权失败(token 无效或过期):请更新 credentials.json 的 ${PUSHY_TOKEN_KEY}` : `pushy API ${api} 失败(HTTP ${res.status}):${msg}`);
98
+ err.status = res.status;
99
+ throw err;
98
100
  }
99
101
  return json ?? {};
100
102
  }
@@ -271,11 +273,31 @@ function createPushyApi(opts) {
271
273
  for (const v of data) out.push({
272
274
  id: v.id,
273
275
  hash: v.hash ?? "",
274
- name: v.name
276
+ name: v.name,
277
+ ...v.packageVersion !== void 0 ? { packageVersion: v.packageVersion } : {}
275
278
  });
276
279
  if (data.length < limit) break;
277
280
  }
278
281
  return out;
282
+ },
283
+ async packages(appId) {
284
+ const out = [];
285
+ const limit = 100;
286
+ for (let offset = 0; offset < 1e4; offset += limit) {
287
+ const { data } = await q(`/app/${appId}/package/list?offset=${offset}&limit=${limit}`);
288
+ if (!data?.length) break;
289
+ for (const p of data) out.push({
290
+ id: p.id,
291
+ hash: p.hash ?? "",
292
+ name: p.name,
293
+ status: p.status ?? ""
294
+ });
295
+ if (data.length < limit) break;
296
+ }
297
+ return out;
298
+ },
299
+ async deletePackage(appId, packageId) {
300
+ await q(`/app/${appId}/package/${packageId}`, { method: "DELETE" });
279
301
  }
280
302
  };
281
303
  }
@@ -725,7 +747,21 @@ function rnUpdate(opts = {}, cli) {
725
747
  const key = `${platform}:${versionName}`;
726
748
  if (uploadedBaselines.has(key)) return;
727
749
  uploadedBaselines.add(key);
728
- await resolvePushyClient(opts, cli, hookCtx.credentials).uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd));
750
+ const pushy = resolvePushyClient(opts, cli, hookCtx.credentials);
751
+ try {
752
+ await pushy.uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd));
753
+ } catch (e) {
754
+ if (e.status !== 409) throw e;
755
+ const sameName = (await pushy.packages(appId)).filter((p) => p.name === versionName);
756
+ if (sameName.length === 0) throw new Error(`基线 409 但未发现同名基线(hash 重复?):${versionName}——请人工核对 pushy 后台`);
757
+ const vers = await pushy.versions(appId);
758
+ const bound = vers.filter((v) => v.packageVersion === versionName || v.packageVersion === void 0 && sameName.some((p) => v.hash === p.hash && v.name === versionName));
759
+ if (vers.length > 0 && bound.length > 0) throw new Error(`基线 ${versionName} 已绑定 ${bound.length} 个热更版本,自动替换会使热更孤儿化——请人工处理(pushy 后台迁移热更或删除后重发)`);
760
+ if (vers.length > 0 && vers.every((v) => v.packageVersion === void 0)) throw new Error(`服务端未回显热更绑定关系,无法确认 ${versionName} 基线可安全替换——请人工核对后删除重传`);
761
+ for (const p of sameName) await pushy.deletePackage(appId, p.id);
762
+ process.stderr.write(`⚠ pushy 基线 ${versionName} 内容已变(同版本名重建),自动删除旧基线 ${sameName.map((p) => `#${p.id}(${p.hash})`).join(",")} 并重传\n`);
763
+ await pushy.uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd));
764
+ }
729
765
  } catch (e) {
730
766
  uploadedBaselines.delete(`${platform}:${readArtifactVersion(result.artifactPath)?.versionName ?? ""}`);
731
767
  process.stderr.write(`⚠ pushy 基线上传失败(请人工补传):${e.message}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applift/core",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/hcg1023/applift.git",