@applift/core 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{artifact-B2RCmWw9.mjs → artifact-DFD8C7bE.mjs} +96 -1
- package/dist/{frameworks-DJIt293o.d.mts → frameworks-B_GxUuWQ.d.mts} +55 -1
- package/dist/index.d.mts +33 -2
- package/dist/index.mjs +52 -17
- package/dist/plugins/index.d.mts +19 -10
- package/dist/plugins/index.mjs +96 -42
- package/package.json +1 -1
|
@@ -966,6 +966,101 @@ function writeProjectVersions(cwd, framework, writes) {
|
|
|
966
966
|
};
|
|
967
967
|
}
|
|
968
968
|
//#endregion
|
|
969
|
+
//#region src/version/beta-version.ts
|
|
970
|
+
const PLATFORM_VERSION_CAPS = {
|
|
971
|
+
ios: {
|
|
972
|
+
maxSegments: 3,
|
|
973
|
+
prerelease: "reject",
|
|
974
|
+
note: "TestFlight / App Store 要求 1–3 段非负整数"
|
|
975
|
+
},
|
|
976
|
+
android: {
|
|
977
|
+
maxSegments: 4,
|
|
978
|
+
prerelease: "allow",
|
|
979
|
+
note: "Gradle 不校验,商店要求数字点分"
|
|
980
|
+
},
|
|
981
|
+
harmony: {
|
|
982
|
+
maxSegments: 4,
|
|
983
|
+
prerelease: "warn",
|
|
984
|
+
note: "官方文档要求仅由数字和点构成(构建期 schema 实测放行)"
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
const DEFAULT_BETA_VERSION_CONFIG = {
|
|
988
|
+
mode: "offset",
|
|
989
|
+
segment: "patch",
|
|
990
|
+
delta: 1e3
|
|
991
|
+
};
|
|
992
|
+
/** 平台能力查表:只认自有键,避免 platform="constructor" 拿到原型上的函数 */
|
|
993
|
+
function capsOf(platform) {
|
|
994
|
+
return Object.hasOwn(PLATFORM_VERSION_CAPS, platform) ? PLATFORM_VERSION_CAPS[platform] : void 0;
|
|
995
|
+
}
|
|
996
|
+
/** 拆 versionName:数字段数 + prerelease(4.0.0-beta.1 → 3 段 + "beta.1") */
|
|
997
|
+
function shapeOf(name) {
|
|
998
|
+
const m = /^(\d+(?:\.\d+)*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(name.trim());
|
|
999
|
+
if (!m) return null;
|
|
1000
|
+
return {
|
|
1001
|
+
segments: m[1].split(".").length,
|
|
1002
|
+
...m[2] ? { prerelease: m[2] } : {}
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
/** 完整检查(段数 + prerelease 政策);返回问题描述,null = 可用 */
|
|
1006
|
+
function checkVersionNameShape(name, platform) {
|
|
1007
|
+
const caps = capsOf(platform);
|
|
1008
|
+
const shape = shapeOf(name);
|
|
1009
|
+
if (!shape) return `versionName「${name}」不是「数字段 + 可选 prerelease」形态`;
|
|
1010
|
+
if (!caps) return null;
|
|
1011
|
+
if (shape.segments > caps.maxSegments) return `${platform} 的 versionName 最多 ${caps.maxSegments} 段数字(${caps.note}):${name}`;
|
|
1012
|
+
if (shape.prerelease && caps.prerelease === "reject") return `${platform} 的 versionName 不支持 prerelease 后缀(${caps.note}):${name}`;
|
|
1013
|
+
return null;
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* 派生测试版本名。
|
|
1017
|
+
* 硬约束(段数超限 / iOS prerelease)直接抛错;harmony 的 prerelease 只告警(见 assertBetaVersionSupported)。
|
|
1018
|
+
*/
|
|
1019
|
+
function betaVersionName(ctx) {
|
|
1020
|
+
const name = deriveName(ctx, ctx.config ?? DEFAULT_BETA_VERSION_CONFIG);
|
|
1021
|
+
const caps = capsOf(ctx.platform);
|
|
1022
|
+
const shape = shapeOf(name);
|
|
1023
|
+
if (!shape) throw new Error(`派生出的 versionName「${name}」不是合法版本号形态`);
|
|
1024
|
+
if (caps) {
|
|
1025
|
+
if (shape.segments > caps.maxSegments) throw new Error(`${ctx.platform} 的 versionName 最多 ${caps.maxSegments} 段数字(${caps.note}):${name}——改用 version.beta.mode=offset(segment=patch)或 app-id`);
|
|
1026
|
+
if (shape.prerelease && caps.prerelease === "reject") throw new Error(`${ctx.platform} 的 versionName 不支持 prerelease 后缀(${caps.note}):${name}——改用 version.beta.mode=offset(segment=patch)或 app-id`);
|
|
1027
|
+
}
|
|
1028
|
+
return name;
|
|
1029
|
+
}
|
|
1030
|
+
function deriveName(ctx, config) {
|
|
1031
|
+
if (config.mode === "app-id") return ctx.base;
|
|
1032
|
+
if (config.mode === "suffix") {
|
|
1033
|
+
const template = config.template ?? "{base}-beta";
|
|
1034
|
+
if (template.includes("{n}")) throw new Error(`version.beta.template 不支持 {n}(需要递增序号请用 mode=offset):${template}`);
|
|
1035
|
+
return template.replace(/\{base\}/g, ctx.base);
|
|
1036
|
+
}
|
|
1037
|
+
const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(ctx.base);
|
|
1038
|
+
if (!m) throw new Error(`工程 versionName「${ctx.base}」不是 X.Y.Z:version.beta.mode=offset 需要三段数字作为基线`);
|
|
1039
|
+
const major = Number(m[1]);
|
|
1040
|
+
const minor = Number(m[2]);
|
|
1041
|
+
const patch = Number(m[3]);
|
|
1042
|
+
const delta = config.delta ?? 1e3;
|
|
1043
|
+
if (!Number.isInteger(delta) || delta <= 0) throw new Error(`version.beta.delta 必须是正整数(收到 ${String(delta)})——否则测试包与正式版无法区分`);
|
|
1044
|
+
return (config.segment ?? "patch") === "major" ? `${major + delta}.${minor}.${patch}` : `${major}.${minor}.${patch + delta}`;
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* 平台支持性校验:返回告警(不阻断);官方硬拒的组合抛错。
|
|
1048
|
+
* 供发布前调用——配置错在发版前暴露,不留到上传被拒。
|
|
1049
|
+
*/
|
|
1050
|
+
function assertBetaVersionSupported(ctx) {
|
|
1051
|
+
const config = ctx.config ?? DEFAULT_BETA_VERSION_CONFIG;
|
|
1052
|
+
const warnings = [];
|
|
1053
|
+
if (config.mode === "app-id") return warnings;
|
|
1054
|
+
const caps = capsOf(ctx.platform);
|
|
1055
|
+
if (!caps) return warnings;
|
|
1056
|
+
if (config.mode === "suffix" && caps.prerelease !== "allow") {
|
|
1057
|
+
const msg = `${ctx.platform} 的 versionName ${caps.note}:version.beta.mode=suffix 在该平台不可用`;
|
|
1058
|
+
if (caps.prerelease === "reject") throw new Error(`${msg}——改用 mode=offset(segment=patch)或 app-id`);
|
|
1059
|
+
warnings.push(`${msg}(构建期放行,建议改用 offset)`);
|
|
1060
|
+
}
|
|
1061
|
+
return warnings;
|
|
1062
|
+
}
|
|
1063
|
+
//#endregion
|
|
969
1064
|
//#region src/version/artifact.ts
|
|
970
1065
|
/**
|
|
971
1066
|
* 产物版本读取(只读不写——版本号变更属开发提交,发版工具只负责读版本防回退)。
|
|
@@ -1042,4 +1137,4 @@ function fromAapt(artifactPath) {
|
|
|
1042
1137
|
}
|
|
1043
1138
|
}
|
|
1044
1139
|
//#endregion
|
|
1045
|
-
export {
|
|
1140
|
+
export { resolveFramework as A, tagReleaseVersion as B, suggestFramework as C, detectBundleIds as D, deps as E, git as F, isGitRepo as I, latestSemverTag as L, collectReleaseDiff as M, routeDelivery as N, findArtifacts as O, commitsSince as P, looseSemver as R, rnFramework as S, tauriFramework as T, nativeHarmonyAdapter as _, betaVersionName as a, nativeIosFramework as b, writeProjectVersions as c, electronFramework as d, flutterAdapter as f, nativeAndroidFramework as g, nativeAndroidAdapter as h, assertBetaVersionSupported as i, subdirs as j, readJson as k, redactText as l, knownFrameworkAdapters as m, DEFAULT_BETA_VERSION_CONFIG as n, checkVersionNameShape as o, flutterFramework as p, PLATFORM_VERSION_CAPS as r, readProjectVersions as s, readArtifactVersion as t, electronAdapter as u, nativeHarmonyFramework as v, tauriAdapter as w, rnAdapter as x, nativeIosAdapter as y, statusShort as z };
|
|
@@ -195,11 +195,48 @@ declare const VersionCodeConfigSchema: z.ZodUnion<readonly [z.ZodLiteral<"increm
|
|
|
195
195
|
platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
196
196
|
}, z.core.$strip>]>;
|
|
197
197
|
type VersionCodeConfig = z.infer<typeof VersionCodeConfigSchema>;
|
|
198
|
+
/**
|
|
199
|
+
* 测试版本名策略:测试包与正式包的 versionName 必须不同(pushy 只认 packageVersion 字符串)。
|
|
200
|
+
* - offset:段偏移,默认 patch+1000(4.0.0 → 4.0.1000)——三段纯数字,iOS/Android/鸿蒙全通
|
|
201
|
+
* - suffix:semver prerelease(4.0.0-beta)——iOS TestFlight/App Store 硬拒,仅侧载可用
|
|
202
|
+
* - app-id:版本名不变,隔离交给两个 pushy 应用记录
|
|
203
|
+
*/
|
|
204
|
+
declare const BetaVersionConfigSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
205
|
+
mode: z.ZodLiteral<"offset">;
|
|
206
|
+
segment: z.ZodDefault<z.ZodEnum<{
|
|
207
|
+
major: "major";
|
|
208
|
+
patch: "patch";
|
|
209
|
+
}>>;
|
|
210
|
+
delta: z.ZodDefault<z.ZodNumber>;
|
|
211
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
212
|
+
mode: z.ZodLiteral<"suffix">;
|
|
213
|
+
template: z.ZodDefault<z.ZodString>;
|
|
214
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
215
|
+
mode: z.ZodLiteral<"app-id">;
|
|
216
|
+
}, z.core.$strip>]>;
|
|
217
|
+
/**
|
|
218
|
+
* 配置侧类型:用 z.input(字段带 .default 即为可选)。
|
|
219
|
+
* 用户写 `{ mode: 'offset' }` 也应合法——默认值由 schema 在 parse 时补齐。
|
|
220
|
+
*/
|
|
221
|
+
type BetaVersionConfig = z.input<typeof BetaVersionConfigSchema>;
|
|
198
222
|
declare const VersionConfigSchema: z.ZodObject<{
|
|
199
223
|
versionCode: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"increment">, z.ZodObject<{
|
|
200
224
|
formula: z.ZodString;
|
|
201
225
|
platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
202
226
|
}, z.core.$strip>]>>;
|
|
227
|
+
beta: z.ZodDefault<z.ZodUnion<readonly [z.ZodObject<{
|
|
228
|
+
mode: z.ZodLiteral<"offset">;
|
|
229
|
+
segment: z.ZodDefault<z.ZodEnum<{
|
|
230
|
+
major: "major";
|
|
231
|
+
patch: "patch";
|
|
232
|
+
}>>;
|
|
233
|
+
delta: z.ZodDefault<z.ZodNumber>;
|
|
234
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
235
|
+
mode: z.ZodLiteral<"suffix">;
|
|
236
|
+
template: z.ZodDefault<z.ZodString>;
|
|
237
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
238
|
+
mode: z.ZodLiteral<"app-id">;
|
|
239
|
+
}, z.core.$strip>]>>;
|
|
203
240
|
}, z.core.$strip>;
|
|
204
241
|
type VersionConfig = z.infer<typeof VersionConfigSchema>;
|
|
205
242
|
declare const ProjectConfigSchema: z.ZodObject<{
|
|
@@ -231,6 +268,19 @@ declare const ProjectConfigSchema: z.ZodObject<{
|
|
|
231
268
|
formula: z.ZodString;
|
|
232
269
|
platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
233
270
|
}, z.core.$strip>]>>;
|
|
271
|
+
beta: z.ZodDefault<z.ZodUnion<readonly [z.ZodObject<{
|
|
272
|
+
mode: z.ZodLiteral<"offset">;
|
|
273
|
+
segment: z.ZodDefault<z.ZodEnum<{
|
|
274
|
+
major: "major";
|
|
275
|
+
patch: "patch";
|
|
276
|
+
}>>;
|
|
277
|
+
delta: z.ZodDefault<z.ZodNumber>;
|
|
278
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
279
|
+
mode: z.ZodLiteral<"suffix">;
|
|
280
|
+
template: z.ZodDefault<z.ZodString>;
|
|
281
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
282
|
+
mode: z.ZodLiteral<"app-id">;
|
|
283
|
+
}, z.core.$strip>]>>;
|
|
234
284
|
}, z.core.$strip>>;
|
|
235
285
|
beta: z.ZodOptional<z.ZodObject<{
|
|
236
286
|
pgyer: z.ZodOptional<z.ZodObject<{
|
|
@@ -426,6 +476,10 @@ interface AppliftPlugin {
|
|
|
426
476
|
ref?: string;
|
|
427
477
|
error?: string;
|
|
428
478
|
artifactPath?: string;
|
|
479
|
+
/** 本次发布的平台(pipeline 由渠道计划解析后透传;基线上传类插件据此选对应用记录) */
|
|
480
|
+
platform?: string;
|
|
481
|
+
/** 发布阶段:beta=内测(测试包基线进 beta 应用记录)/ prod=正式。缺省由插件自行推断 */
|
|
482
|
+
target?: "beta" | "prod";
|
|
429
483
|
}, ctx: HookContext): Promise<void> | void;
|
|
430
484
|
"submit:before"?(plans: ReleasePlanEntry[], ctx: HookContext): Promise<ReleasePlanEntry[] | false | void> | ReleasePlanEntry[] | false | void;
|
|
431
485
|
"submit:after"?(summary: PipelineSummary, ctx: HookContext): Promise<void> | void;
|
|
@@ -479,4 +533,4 @@ declare const knownFrameworkAdapters: FrameworkAdapter[];
|
|
|
479
533
|
declare function suggestFramework(cwd: string): FrameworkAdapter | null;
|
|
480
534
|
declare function tauriFramework(): AppliftPlugin;
|
|
481
535
|
//#endregion
|
|
482
|
-
export {
|
|
536
|
+
export { ProjectConfigSchema as $, routeDelivery as A, appendEntry as B, resolvePlugins as C, readJson as Ct, PublishContext as D, FrameworkContext as E, runSubmit as F, BetaVersionConfigSchema as G, BetaConfig as H, HISTORY_PATH as I, CredentialsProfile as J, CredentialsFile as K, HistoryEntry as L, PipelineSummary as M, PipelineSummaryEntry as N, UpdateProvider as O, runStage as P, ProjectConfig as Q, HistoryEvent as R, defineConfig as S, findArtifacts as St, DeliveryRoute as T, subdirs as Tt, BetaConfigSchema as U, readEntries as V, BetaVersionConfig as W, GlobalConfig as X, CredentialsProfileSchema as Y, GlobalConfigSchema as Z, AppliftPlugin as _, BundleIds as _t, knownFrameworkAdapters as a, VersionCodeConfigSchema as at, PluginHookName as b, deps as bt, nativeHarmonyAdapter as c, Channel as ct, nativeIosFramework as d, ChannelEvent as dt, StoreConfig as et, rnAdapter as f, ChannelRegistry as ft, tauriFramework as g, SubmitResult as gt, tauriAdapter as h, StageResult as ht, flutterFramework as i, VersionCodeConfig as it, PipelineInput as j, collectReleaseDiff as k, nativeHarmonyFramework as l, ChannelCapabilities as lt, suggestFramework as m, ReviewStatus as mt, electronFramework as n, Stores as nt, nativeAndroidAdapter as o, VersionConfig as ot, rnFramework as p, ReleasePlanEntry as pt, CredentialsFileSchema as q, flutterAdapter as r, StoresSchema as rt, nativeAndroidFramework as s, VersionConfigSchema as st, electronAdapter as t, StoreConfigSchema as tt, nativeIosAdapter as u, ChannelContext as ut, AppliftUserConfig as v, FrameworkAdapter as vt, DeliveryJudgement as w, resolveFramework as wt, PluginHost as x, detectBundleIds as xt, HookContext as y, Platform as yt, HistoryQuery as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
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_GxUuWQ.mjs";
|
|
2
2
|
//#region src/registry.d.ts
|
|
3
3
|
export declare class DefaultChannelRegistry implements ChannelRegistry {
|
|
4
4
|
private readonly channels;
|
|
@@ -625,6 +625,37 @@ export declare function evalVersionCodeFormula(formula: string, v: {
|
|
|
625
625
|
*/
|
|
626
626
|
export declare function nextVersionCode(current: number | undefined, formulaValue: number | undefined): number;
|
|
627
627
|
//#endregion
|
|
628
|
+
//#region src/version/beta-version.d.ts
|
|
629
|
+
export type PrereleasePolicy = "allow" | "warn" | "reject";
|
|
630
|
+
export interface PlatformVersionCaps {
|
|
631
|
+
/** versionName 允许的最大数字段数 */
|
|
632
|
+
maxSegments: number;
|
|
633
|
+
/** prerelease 后缀(-beta.1)的官方态度 */
|
|
634
|
+
prerelease: PrereleasePolicy;
|
|
635
|
+
/** 官方口径说明(进报错/告警文案) */
|
|
636
|
+
note: string;
|
|
637
|
+
}
|
|
638
|
+
export declare const PLATFORM_VERSION_CAPS: Record<string, PlatformVersionCaps>;
|
|
639
|
+
export declare const DEFAULT_BETA_VERSION_CONFIG: BetaVersionConfig;
|
|
640
|
+
export interface BetaVersionContext {
|
|
641
|
+
/** 工程 versionName(正式号,如 4.0.0) */
|
|
642
|
+
base: string;
|
|
643
|
+
config?: BetaVersionConfig;
|
|
644
|
+
platform: string;
|
|
645
|
+
}
|
|
646
|
+
/** 完整检查(段数 + prerelease 政策);返回问题描述,null = 可用 */
|
|
647
|
+
export declare function checkVersionNameShape(name: string, platform: string): string | null;
|
|
648
|
+
/**
|
|
649
|
+
* 派生测试版本名。
|
|
650
|
+
* 硬约束(段数超限 / iOS prerelease)直接抛错;harmony 的 prerelease 只告警(见 assertBetaVersionSupported)。
|
|
651
|
+
*/
|
|
652
|
+
export declare function betaVersionName(ctx: BetaVersionContext): string;
|
|
653
|
+
/**
|
|
654
|
+
* 平台支持性校验:返回告警(不阻断);官方硬拒的组合抛错。
|
|
655
|
+
* 供发布前调用——配置错在发版前暴露,不留到上传被拒。
|
|
656
|
+
*/
|
|
657
|
+
export declare function assertBetaVersionSupported(ctx: BetaVersionContext): string[];
|
|
658
|
+
//#endregion
|
|
628
659
|
//#region src/version/changelog.d.ts
|
|
629
660
|
export interface ChangelogEntry {
|
|
630
661
|
type: string;
|
|
@@ -687,4 +718,4 @@ export interface ArtifactVersion {
|
|
|
687
718
|
}
|
|
688
719
|
export declare function readArtifactVersion(artifactPath: string): ArtifactVersion | undefined;
|
|
689
720
|
//#endregion
|
|
690
|
-
export { AppliftPlugin, AppliftUserConfig, BetaConfig, BetaConfigSchema, BundleIds, Channel, ChannelCapabilities, ChannelContext, ChannelEvent, ChannelRegistry, CredentialsFile, CredentialsFileSchema, CredentialsProfile, CredentialsProfileSchema, DeliveryJudgement, DeliveryRoute, FrameworkAdapter, FrameworkContext, GlobalConfig, GlobalConfigSchema, HISTORY_PATH, HistoryEntry, HistoryEvent, HistoryQuery, HookContext, PipelineInput, PipelineSummary, PipelineSummaryEntry, Platform, PluginHookName, PluginHost, ProjectConfig, ProjectConfigSchema, PublishContext, ReleasePlanEntry, ReviewStatus, StageResult, StoreConfig, StoreConfigSchema, Stores, StoresSchema, SubmitResult, UpdateProvider, VersionCodeConfig, VersionCodeConfigSchema, VersionConfig, VersionConfigSchema, appendEntry, collectReleaseDiff, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, findArtifacts, flutterAdapter, flutterFramework, knownFrameworkAdapters, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, readEntries, readJson, resolveFramework, resolvePlugins, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, subdirs, suggestFramework, tauriAdapter, tauriFramework };
|
|
721
|
+
export { AppliftPlugin, AppliftUserConfig, BetaConfig, BetaConfigSchema, BetaVersionConfig, BetaVersionConfigSchema, BundleIds, Channel, ChannelCapabilities, ChannelContext, ChannelEvent, ChannelRegistry, CredentialsFile, CredentialsFileSchema, CredentialsProfile, CredentialsProfileSchema, DeliveryJudgement, DeliveryRoute, FrameworkAdapter, FrameworkContext, GlobalConfig, GlobalConfigSchema, HISTORY_PATH, HistoryEntry, HistoryEvent, HistoryQuery, HookContext, PipelineInput, PipelineSummary, PipelineSummaryEntry, Platform, PluginHookName, PluginHost, ProjectConfig, ProjectConfigSchema, PublishContext, ReleasePlanEntry, ReviewStatus, StageResult, StoreConfig, StoreConfigSchema, Stores, StoresSchema, SubmitResult, UpdateProvider, VersionCodeConfig, VersionCodeConfigSchema, VersionConfig, VersionConfigSchema, appendEntry, collectReleaseDiff, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, findArtifacts, flutterAdapter, flutterFramework, knownFrameworkAdapters, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, readEntries, readJson, resolveFramework, resolvePlugins, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, subdirs, suggestFramework, tauriAdapter, tauriFramework };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as resolveFramework, B as tagReleaseVersion, C as suggestFramework, D as detectBundleIds, E as deps, F as git, I as isGitRepo, L as latestSemverTag, M as collectReleaseDiff, N as routeDelivery, O as findArtifacts, P as commitsSince, R as looseSemver, S as rnFramework, T as tauriFramework, _ as nativeHarmonyAdapter, a as betaVersionName, b as nativeIosFramework, c as writeProjectVersions, d as electronFramework, f as flutterAdapter, g as nativeAndroidFramework, h as nativeAndroidAdapter, i as assertBetaVersionSupported, j as subdirs, k as readJson, l as redactText, m as knownFrameworkAdapters, n as DEFAULT_BETA_VERSION_CONFIG, o as checkVersionNameShape, p as flutterFramework, r as PLATFORM_VERSION_CAPS, s as readProjectVersions, t as readArtifactVersion, u as electronAdapter, v as nativeHarmonyFramework, w as tauriAdapter, x as rnAdapter, y as nativeIosAdapter, z as statusShort } from "./artifact-DFD8C7bE.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -101,7 +101,33 @@ const VersionCodeConfigSchema = z.union([z.literal("increment"), z.object({
|
|
|
101
101
|
/** 仅限平台(缺省全部);实际写入 = max(公式值, 现值+1) */
|
|
102
102
|
platforms: z.array(z.string()).optional()
|
|
103
103
|
})]);
|
|
104
|
-
|
|
104
|
+
/**
|
|
105
|
+
* 测试版本名策略:测试包与正式包的 versionName 必须不同(pushy 只认 packageVersion 字符串)。
|
|
106
|
+
* - offset:段偏移,默认 patch+1000(4.0.0 → 4.0.1000)——三段纯数字,iOS/Android/鸿蒙全通
|
|
107
|
+
* - suffix:semver prerelease(4.0.0-beta)——iOS TestFlight/App Store 硬拒,仅侧载可用
|
|
108
|
+
* - app-id:版本名不变,隔离交给两个 pushy 应用记录
|
|
109
|
+
*/
|
|
110
|
+
const BetaVersionConfigSchema = z.union([
|
|
111
|
+
z.object({
|
|
112
|
+
mode: z.literal("offset"),
|
|
113
|
+
segment: z.enum(["patch", "major"]).default("patch"),
|
|
114
|
+
delta: z.number().int().positive().default(1e3)
|
|
115
|
+
}),
|
|
116
|
+
z.object({
|
|
117
|
+
mode: z.literal("suffix"),
|
|
118
|
+
/** 模板:只支持 {base} 占位(不支持 {n}:序号类模板需要持久化状态) */
|
|
119
|
+
template: z.string().default("{base}-beta")
|
|
120
|
+
}),
|
|
121
|
+
z.object({ mode: z.literal("app-id") })
|
|
122
|
+
]);
|
|
123
|
+
const VersionConfigSchema = z.object({
|
|
124
|
+
versionCode: VersionCodeConfigSchema.default("increment"),
|
|
125
|
+
beta: BetaVersionConfigSchema.default({
|
|
126
|
+
mode: "offset",
|
|
127
|
+
segment: "patch",
|
|
128
|
+
delta: 1e3
|
|
129
|
+
})
|
|
130
|
+
});
|
|
105
131
|
const ProjectConfigSchema = z.object({
|
|
106
132
|
/** 项目显示名 */
|
|
107
133
|
name: z.string().optional(),
|
|
@@ -3834,6 +3860,7 @@ async function runStage(input) {
|
|
|
3834
3860
|
ok: false,
|
|
3835
3861
|
error: "该渠道不支持只传包(上传与提审一体)"
|
|
3836
3862
|
};
|
|
3863
|
+
const plan = await safePlan(channel, effectiveCtx);
|
|
3837
3864
|
if (plugins) await plugins.broadcast("stage:after", {
|
|
3838
3865
|
channel: channel.id,
|
|
3839
3866
|
cwd: input.cwd,
|
|
@@ -3843,9 +3870,10 @@ async function runStage(input) {
|
|
|
3843
3870
|
ok: r.ok,
|
|
3844
3871
|
ref: r.ref,
|
|
3845
3872
|
error: r.error,
|
|
3846
|
-
artifactPath: effectiveCtx.artifactPath
|
|
3873
|
+
artifactPath: effectiveCtx.artifactPath,
|
|
3874
|
+
platform: plan.platform,
|
|
3875
|
+
target: "prod"
|
|
3847
3876
|
});
|
|
3848
|
-
const plan = await safePlan(channel, effectiveCtx);
|
|
3849
3877
|
summary.push({
|
|
3850
3878
|
channel: channel.id,
|
|
3851
3879
|
label: channel.label,
|
|
@@ -3958,16 +3986,21 @@ async function runSubmit(input, options) {
|
|
|
3958
3986
|
ref: stageResult.ref,
|
|
3959
3987
|
artifactVersion: plans.find((p) => p.channel === channel.id)?.artifactVersion || void 0
|
|
3960
3988
|
});
|
|
3961
|
-
if (plugins)
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3989
|
+
if (plugins) {
|
|
3990
|
+
const stagedPlan = planFor(plans, basePlans, channel.id, ctx.artifactPath);
|
|
3991
|
+
await plugins.broadcast("stage:after", {
|
|
3992
|
+
channel: channel.id,
|
|
3993
|
+
cwd: input.cwd,
|
|
3994
|
+
credentials: effectiveCtx.credentials
|
|
3995
|
+
}, {
|
|
3996
|
+
channel: channel.id,
|
|
3997
|
+
ok: true,
|
|
3998
|
+
ref: stageResult.ref,
|
|
3999
|
+
artifactPath: effectiveCtx.artifactPath,
|
|
4000
|
+
platform: stagedPlan.platform,
|
|
4001
|
+
target: "prod"
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
3971
4004
|
}
|
|
3972
4005
|
const r = await channel.submit(effectiveCtx, stagedRef);
|
|
3973
4006
|
summary.push({
|
|
@@ -4016,11 +4049,13 @@ async function safePlan(channel, ctx) {
|
|
|
4016
4049
|
return fallbackPlan(channel.id, ctx.artifactPath);
|
|
4017
4050
|
}
|
|
4018
4051
|
}
|
|
4019
|
-
/** 按产物扩展名推断平台(兜底条目用):.ipa→ios,.hap→harmony,.apk/.aab 及其余→android
|
|
4052
|
+
/** 按产物扩展名推断平台(兜底条目用):.ipa→ios,.hap/.app→harmony,.apk/.aab 及其余→android。
|
|
4053
|
+
* `.app` 在 applift 的分发口径里只会是鸿蒙整包(iOS 上架/内测统一用 .ipa)——
|
|
4054
|
+
* 历史实现把它归到 android,会让 stage:after 把鸿蒙基线传到 android 应用记录。 */
|
|
4020
4055
|
function platformOfArtifact(artifactPath) {
|
|
4021
4056
|
const ext = path.extname(artifactPath).toLowerCase();
|
|
4022
4057
|
if (ext === ".ipa") return "ios";
|
|
4023
|
-
if (ext === ".hap") return "harmony";
|
|
4058
|
+
if (ext === ".hap" || ext === ".app") return "harmony";
|
|
4024
4059
|
return "android";
|
|
4025
4060
|
}
|
|
4026
4061
|
/** plan 失败/被插件删除时的兜底条目(保 summary.plan 非可选契约;平台按产物推断不再硬编码 android) */
|
|
@@ -4603,4 +4638,4 @@ function applyBump(cwd, plan, framework, opts) {
|
|
|
4603
4638
|
}
|
|
4604
4639
|
}
|
|
4605
4640
|
//#endregion
|
|
4606
|
-
export { APPLIFT_HOME, AgcHarmonyChannel, AscChannel, BetaConfigSchema, CREDENTIALS_PATH, CredentialsFileSchema, CredentialsProfileSchema, DefaultChannelRegistry, GLOBAL_CONFIG_PATH, GlobalConfigSchema, GooglePlayChannel, HISTORY_PATH, HonorChannel, HuaweiAndroidChannel, OppoChannel, PROJECTS_MAP_PATH, PgyerChannel, PluginHost, ProjectConfigSchema, StoreConfigSchema, StoresSchema, VersionCodeConfigSchema, VersionConfigSchema, VivoChannel, WAIT_BEFORE_SUBMIT_MS, XiaomiChannel, YybChannel, appendEntry, applyBump, assertListingFiles, collectReleaseDiff, commitsSince, decideNextVersion, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, evalVersionCodeFormula, findArtifacts, findUp, flutterAdapter, flutterFramework, formPost, getAgcToken, getHarmonyAppId, git, hmacSign, humanizeError, inferBumpLevel, isGitRepo, knownFrameworkAdapters, latestSemverTag, loadCredentials, loadCredentialsLayered, loadGlobalConfig, loadListingFile, loadProjectConfig, loadProjectProfileMap, looseSemver, md5File, md5String, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, nextVersionCode, planBump, projectCredentialsPath, readArtifactVersion, readEntries, readJson, readProjectVersions, redactText, registry, renderChangelogSection, resolveFramework, resolveListing, resolvePlugins, resolveProfile, resolveProfileFor, resolveProfileSource, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, saveCredentials, saveProjectProfileMap, setProjectProfile, sha256File, sortedQueryString, statusShort, storeVersionName, subdirs, suggestFramework, tagReleaseVersion, tauriAdapter, tauriFramework, toChangelogEntries, tsMillis, tsSeconds, upsertChangelog, writeProjectVersions };
|
|
4641
|
+
export { APPLIFT_HOME, AgcHarmonyChannel, AscChannel, BetaConfigSchema, BetaVersionConfigSchema, CREDENTIALS_PATH, CredentialsFileSchema, CredentialsProfileSchema, DEFAULT_BETA_VERSION_CONFIG, DefaultChannelRegistry, GLOBAL_CONFIG_PATH, GlobalConfigSchema, GooglePlayChannel, HISTORY_PATH, HonorChannel, HuaweiAndroidChannel, OppoChannel, PLATFORM_VERSION_CAPS, PROJECTS_MAP_PATH, PgyerChannel, PluginHost, ProjectConfigSchema, StoreConfigSchema, StoresSchema, VersionCodeConfigSchema, VersionConfigSchema, VivoChannel, WAIT_BEFORE_SUBMIT_MS, XiaomiChannel, YybChannel, appendEntry, applyBump, assertBetaVersionSupported, assertListingFiles, betaVersionName, checkVersionNameShape, collectReleaseDiff, commitsSince, decideNextVersion, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, evalVersionCodeFormula, findArtifacts, findUp, flutterAdapter, flutterFramework, formPost, getAgcToken, getHarmonyAppId, git, hmacSign, humanizeError, inferBumpLevel, isGitRepo, knownFrameworkAdapters, latestSemverTag, loadCredentials, loadCredentialsLayered, loadGlobalConfig, loadListingFile, loadProjectConfig, loadProjectProfileMap, looseSemver, md5File, md5String, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, nextVersionCode, planBump, projectCredentialsPath, readArtifactVersion, readEntries, readJson, readProjectVersions, redactText, registry, renderChangelogSection, resolveFramework, resolveListing, resolvePlugins, resolveProfile, resolveProfileFor, resolveProfileSource, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, saveCredentials, saveProjectProfileMap, setProjectProfile, sha256File, sortedQueryString, statusShort, storeVersionName, subdirs, suggestFramework, tagReleaseVersion, tauriAdapter, tauriFramework, toChangelogEntries, tsMillis, tsSeconds, upsertChangelog, writeProjectVersions };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as FrameworkContext, O as UpdateProvider, _ 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-
|
|
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_GxUuWQ.mjs";
|
|
2
2
|
//#region src/plugins/dingtalk-notify.d.ts
|
|
3
3
|
interface DingtalkNotifyOptions {
|
|
4
4
|
webhook: string;
|
|
@@ -80,11 +80,19 @@ export declare function readDepVersions(cwd: string): Record<string, string>;
|
|
|
80
80
|
export declare function createPushyApi(opts: PushyApiOptions): PushyCli;
|
|
81
81
|
//#endregion
|
|
82
82
|
//#region src/plugins/rn-update.d.ts
|
|
83
|
+
/**
|
|
84
|
+
* 平台 appId 配置:单 appId(隔离靠版本名)或双 appId(内测/正式各一个 pushy 应用记录)。
|
|
85
|
+
* 双 appId 时 promoteToProd 无法 rebind(跨 appId 的 versionId 不通用),退化为同一 ppk 重发。
|
|
86
|
+
*/
|
|
87
|
+
type AppIdConfig = number | {
|
|
88
|
+
prod: number;
|
|
89
|
+
beta: number;
|
|
90
|
+
};
|
|
83
91
|
interface RnUpdateOptions {
|
|
84
92
|
/** 各平台的 app 记录号(如 harmony: 34166);未声明的平台不启用热更 */
|
|
85
|
-
harmony?:
|
|
86
|
-
android?:
|
|
87
|
-
ios?:
|
|
93
|
+
harmony?: AppIdConfig;
|
|
94
|
+
android?: AppIdConfig;
|
|
95
|
+
ios?: AppIdConfig;
|
|
88
96
|
/** 补丁目录(patch-package 约定默认 patches/,项目可覆盖) */
|
|
89
97
|
patchDir?: string;
|
|
90
98
|
/** 正式发布默认灰度比例(缺省 100 全量——promote 语义是"验证后发正式",灰度是显式选择;
|
|
@@ -101,12 +109,13 @@ interface RnUpdateOptions {
|
|
|
101
109
|
* 五形态完备性:新原生实体必现于 原生目录/依赖(原生包)/补丁/构建配置/JS——前四判原生,纯 JS 判热更,其余灰区。
|
|
102
110
|
*/
|
|
103
111
|
export declare function judgeDelivery(diff: string[], ctx: FrameworkContext, opts: RnUpdateOptions): DeliveryJudgement;
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
/** provider 构造(cli 注入点见 resolvePushyClient
|
|
107
|
-
export declare function makeRnUpdateProvider(opts: RnUpdateOptions, cli?: PushyCli): UpdateProvider;
|
|
112
|
+
/** beta 配置读取(插件在 config:resolved 钩子里捕获;缺省走内置默认) */
|
|
113
|
+
type BetaConfigGetter = () => BetaVersionConfig;
|
|
114
|
+
/** provider 构造(cli 注入点见 resolvePushyClient;betaConfig 由插件钩子注入) */
|
|
115
|
+
export declare function makeRnUpdateProvider(opts: RnUpdateOptions, cli?: PushyCli, getBetaConfig?: BetaConfigGetter): UpdateProvider;
|
|
108
116
|
/** rnUpdate 插件工厂:注册完整 provider(判定 + beta 发布 + promote)+ 原生发版自动基线。
|
|
109
|
-
* cli 注入点:测试 mock / 特殊 transport;缺省 OpenAPI 客户端(token 来自 ctx.credentials)。
|
|
117
|
+
* cli 注入点:测试 mock / 特殊 transport;缺省 OpenAPI 客户端(token 来自 ctx.credentials)。
|
|
118
|
+
* beta 策略由项目配置决定,在 config:resolved 钩子里捕获(不重复声明在插件参数里)。 */
|
|
110
119
|
export declare function rnUpdate(opts?: RnUpdateOptions, cli?: PushyCli): AppliftPlugin;
|
|
111
120
|
//#endregion
|
|
112
|
-
export { type DingtalkNotifyOptions, type FetchImpl, type HttpUploadImpl, type PushyApiOptions, type PushyCli, type RnUpdateOptions, electronAdapter, electronFramework, flutterAdapter, flutterFramework, knownFrameworkAdapters, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, rnAdapter, rnFramework, suggestFramework, tauriAdapter, tauriFramework };
|
|
121
|
+
export { type AppIdConfig, type BetaConfigGetter, type DingtalkNotifyOptions, type FetchImpl, type HttpUploadImpl, type PushyApiOptions, type PushyCli, type RnUpdateOptions, electronAdapter, electronFramework, flutterAdapter, flutterFramework, knownFrameworkAdapters, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, rnAdapter, rnFramework, suggestFramework, tauriAdapter, tauriFramework };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as suggestFramework, M as collectReleaseDiff, O as findArtifacts, S as rnFramework, T as tauriFramework, _ as nativeHarmonyAdapter, a as betaVersionName, b as nativeIosFramework, d as electronFramework, f as flutterAdapter, g as nativeAndroidFramework, h as nativeAndroidAdapter, i as assertBetaVersionSupported, l as redactText, m as knownFrameworkAdapters, n as DEFAULT_BETA_VERSION_CONFIG, p as flutterFramework, s as readProjectVersions, t as readArtifactVersion, u as electronAdapter, v as nativeHarmonyFramework, w as tauriAdapter, x as rnAdapter, y as nativeIosAdapter } from "../artifact-DFD8C7bE.mjs";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createHmac } from "node:crypto";
|
|
@@ -491,21 +491,24 @@ function judgeDelivery(diff, ctx, opts) {
|
|
|
491
491
|
evidence
|
|
492
492
|
};
|
|
493
493
|
}
|
|
494
|
-
/** pushy 官方测试包约定:与正式同源码、仅版本号偏移(major+1000,如 1.6.0→1001.6.0) */
|
|
495
|
-
const BETA_VERSION_OFFSET = 1e3;
|
|
496
494
|
/** 正式 promote 的内置默认灰度比例(100 = 全量)。promote 语义是"测试通道已验证、发正式",
|
|
497
495
|
* 全量是常态、灰度是显式选择(--rollout 或 rnUpdate({ defaultRollout })),不藏在配置后面 */
|
|
498
496
|
const DEFAULT_ROLLOUT = 100;
|
|
499
|
-
/**
|
|
500
|
-
function
|
|
501
|
-
const
|
|
502
|
-
if (
|
|
503
|
-
|
|
497
|
+
/** 平台 appId(beta 语境优先取双 appId 里的 beta 记录) */
|
|
498
|
+
function platformAppId(opts, platform, channel) {
|
|
499
|
+
const cfg = opts[platform];
|
|
500
|
+
if (typeof cfg === "number") return cfg;
|
|
501
|
+
if (cfg && typeof cfg === "object") {
|
|
502
|
+
const ids = cfg;
|
|
503
|
+
if (channel === "beta" && typeof ids.beta === "number") return ids.beta;
|
|
504
|
+
if (typeof ids.prod === "number") return ids.prod;
|
|
505
|
+
}
|
|
506
|
+
throw new Error(`平台 ${platform} 未配置热更 app 记录:rnUpdate({ ${platform}: <appId> }) 或 rnUpdate({ ${platform}: { prod, beta } })(在 applift.config.ts 的插件参数里声明)`);
|
|
504
507
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
return
|
|
508
|
+
/** 是否配置了独立的内测 appId(app-id 模式下 promote 无法 rebind) */
|
|
509
|
+
function hasDualAppId(opts, platform) {
|
|
510
|
+
const cfg = opts[platform];
|
|
511
|
+
return !!cfg && typeof cfg === "object" && typeof cfg.beta === "number" && cfg.beta !== cfg.prod;
|
|
509
512
|
}
|
|
510
513
|
/** 当前 versionName(readProjectVersions 按 framework 定位工程文件) */
|
|
511
514
|
function currentVersionName(ctx) {
|
|
@@ -513,9 +516,13 @@ function currentVersionName(ctx) {
|
|
|
513
516
|
if (!v?.versionName) throw new Error(`未读到平台 ${ctx.platform} 的 versionName(readProjectVersions 无该平台版本文件)`);
|
|
514
517
|
return v.versionName;
|
|
515
518
|
}
|
|
519
|
+
/** 正则转义:基线名可能来自 suffix 模板(`+` 等元字符),只转义点号会生成错误正则 */
|
|
520
|
+
function escapeRegExp(s) {
|
|
521
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
522
|
+
}
|
|
516
523
|
/** 服务端取号:该 versionName 下已有热更名 {ver}-patch.N 的最大 N → next = N+1(首版 N=0 → 1) */
|
|
517
524
|
function nextPatchNumber(names, versionName) {
|
|
518
|
-
const re = new RegExp(`^${versionName
|
|
525
|
+
const re = new RegExp(`^${escapeRegExp(versionName)}-patch\\.(\\d+)$`);
|
|
519
526
|
let max = 0;
|
|
520
527
|
for (const { name } of names) {
|
|
521
528
|
const m = name.match(re);
|
|
@@ -570,21 +577,27 @@ async function assertPpkFresh(cwd, ppk) {
|
|
|
570
577
|
} catch {}
|
|
571
578
|
if (newest > 0 && fs.statSync(ppk).mtimeMs < newest) throw new Error(`ppk(${path.basename(ppk)})早于最新代码改动(${newestFile})——疑似忘重新 bundle,请重新产出 ppk 后再发;确认无误可 --artifact 显式指定跳过此护栏`);
|
|
572
579
|
}
|
|
573
|
-
/** 发布新热更的公共骨架:客户端/appId
|
|
574
|
-
async function preparePublish(opts, cli, ctx) {
|
|
580
|
+
/** 发布新热更的公共骨架:客户端/appId/版本名/ppk 探测 + 服务端取号(publishToBeta/publishToProd 共用) */
|
|
581
|
+
async function preparePublish(opts, cli, ctx, channel, getBetaConfig) {
|
|
575
582
|
const client = resolvePushyClient(opts, cli, ctx.credentials);
|
|
576
|
-
const appId = platformAppId(opts, ctx.platform);
|
|
577
|
-
const
|
|
583
|
+
const appId = platformAppId(opts, ctx.platform, channel);
|
|
584
|
+
const base = currentVersionName(ctx);
|
|
585
|
+
const packageVersion = channel === "beta" ? betaVersionName({
|
|
586
|
+
base,
|
|
587
|
+
config: getBetaConfig(),
|
|
588
|
+
platform: ctx.platform
|
|
589
|
+
}) : base;
|
|
578
590
|
return {
|
|
579
591
|
client,
|
|
580
592
|
appId,
|
|
581
|
-
|
|
593
|
+
base,
|
|
594
|
+
packageVersion,
|
|
582
595
|
ppk: await resolvePpk(opts, ctx),
|
|
583
|
-
name: `${
|
|
596
|
+
name: `${packageVersion}-patch.${nextPatchNumber(await client.versions(appId), packageVersion)}`
|
|
584
597
|
};
|
|
585
598
|
}
|
|
586
|
-
/** provider 构造(cli 注入点见 resolvePushyClient
|
|
587
|
-
function makeRnUpdateProvider(opts, cli) {
|
|
599
|
+
/** provider 构造(cli 注入点见 resolvePushyClient;betaConfig 由插件钩子注入) */
|
|
600
|
+
function makeRnUpdateProvider(opts, cli, getBetaConfig = () => DEFAULT_BETA_VERSION_CONFIG) {
|
|
588
601
|
return {
|
|
589
602
|
id: "rn-update",
|
|
590
603
|
frameworks: ["rn"],
|
|
@@ -592,10 +605,17 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
592
605
|
"harmony",
|
|
593
606
|
"android",
|
|
594
607
|
"ios"
|
|
595
|
-
].filter((k) =>
|
|
608
|
+
].filter((k) => opts[k] !== void 0),
|
|
596
609
|
judge: (diff, ctx) => judgeDelivery(diff, ctx, opts),
|
|
597
610
|
async publishToBeta(ctx) {
|
|
598
|
-
|
|
611
|
+
platformAppId(opts, ctx.platform, "beta");
|
|
612
|
+
if (getBetaConfig().mode === "app-id" && !hasDualAppId(opts, ctx.platform)) throw new Error(`app-id 模式必须为 ${ctx.platform} 配置两个推送应用记录:rnUpdate({ ${ctx.platform}: { prod, beta } })——当前只有单 appId,测试热更会绑到正式线(packageVersion 也与正式相同)`);
|
|
613
|
+
for (const w of assertBetaVersionSupported({
|
|
614
|
+
base: currentVersionName(ctx),
|
|
615
|
+
config: getBetaConfig(),
|
|
616
|
+
platform: ctx.platform
|
|
617
|
+
})) process.stderr.write(`⚠ ${w}\n`);
|
|
618
|
+
const { client, appId, packageVersion, ppk, name } = await preparePublish(opts, cli, ctx, "beta", getBetaConfig);
|
|
599
619
|
return {
|
|
600
620
|
versionName: name,
|
|
601
621
|
versionId: (await client.publish({
|
|
@@ -604,13 +624,13 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
604
624
|
platform: ctx.platform,
|
|
605
625
|
name,
|
|
606
626
|
description: ctx.note,
|
|
607
|
-
packageVersion
|
|
627
|
+
packageVersion,
|
|
608
628
|
deps: readDepVersions(ctx.cwd)
|
|
609
629
|
})).versionId
|
|
610
630
|
};
|
|
611
631
|
},
|
|
612
632
|
async publishToProd(ctx) {
|
|
613
|
-
const { client, appId,
|
|
633
|
+
const { client, appId, packageVersion, ppk, name } = await preparePublish(opts, cli, ctx, "prod", getBetaConfig);
|
|
614
634
|
const rollout = ctx.rollout ?? opts.defaultRollout ?? DEFAULT_ROLLOUT;
|
|
615
635
|
return {
|
|
616
636
|
versionName: name,
|
|
@@ -620,7 +640,7 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
620
640
|
platform: ctx.platform,
|
|
621
641
|
name,
|
|
622
642
|
description: ctx.note,
|
|
623
|
-
packageVersion
|
|
643
|
+
packageVersion,
|
|
624
644
|
rollout,
|
|
625
645
|
deps: readDepVersions(ctx.cwd)
|
|
626
646
|
})).versionId,
|
|
@@ -628,11 +648,21 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
628
648
|
};
|
|
629
649
|
},
|
|
630
650
|
async promoteToProd(ctx) {
|
|
651
|
+
const config = getBetaConfig();
|
|
652
|
+
if (config.mode === "app-id" || hasDualAppId(opts, ctx.platform)) {
|
|
653
|
+
process.stderr.write(`⚠ ${ctx.platform} 无法 promote:跨 appId 的 versionId 不通用(app-id/双 appId 模式)——转为 publishToProd,同一 ppk 直接发正式应用记录\n`);
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
631
656
|
const client = resolvePushyClient(opts, cli, ctx.credentials);
|
|
632
|
-
const appId = platformAppId(opts, ctx.platform);
|
|
633
|
-
const
|
|
657
|
+
const appId = platformAppId(opts, ctx.platform, "prod");
|
|
658
|
+
const base = currentVersionName(ctx);
|
|
659
|
+
const betaName = betaVersionName({
|
|
660
|
+
base,
|
|
661
|
+
config,
|
|
662
|
+
platform: ctx.platform
|
|
663
|
+
});
|
|
634
664
|
const latest = (await client.versions(appId)).map((v) => {
|
|
635
|
-
const m = v.name.match(new RegExp(`^${
|
|
665
|
+
const m = v.name.match(new RegExp(`^${escapeRegExp(betaName)}-patch\\.(\\d+)$`));
|
|
636
666
|
return m ? {
|
|
637
667
|
...v,
|
|
638
668
|
n: Number(m[1])
|
|
@@ -640,12 +670,16 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
640
670
|
}).filter((x) => x !== null).sort((a, b) => b.n - a.n)[0];
|
|
641
671
|
if (!latest) return null;
|
|
642
672
|
const rollout = ctx.rollout ?? opts.defaultRollout ?? DEFAULT_ROLLOUT;
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
673
|
+
try {
|
|
674
|
+
await client.rebind({
|
|
675
|
+
appId,
|
|
676
|
+
versionId: latest.id,
|
|
677
|
+
packageVersion: base,
|
|
678
|
+
rollout
|
|
679
|
+
});
|
|
680
|
+
} catch (e) {
|
|
681
|
+
throw new Error(`${e.message}\n提示:promote 需要正式版本 ${base} 的原生基线已上传。先执行 applift release ${ctx.platform} --delivery native(只 stage、不含 --submit)生成基线,再重试 promote。`);
|
|
682
|
+
}
|
|
649
683
|
return {
|
|
650
684
|
versionName: latest.name,
|
|
651
685
|
...rollout !== void 0 ? { rollout } : {}
|
|
@@ -653,31 +687,51 @@ function makeRnUpdateProvider(opts, cli) {
|
|
|
653
687
|
}
|
|
654
688
|
};
|
|
655
689
|
}
|
|
656
|
-
/**
|
|
690
|
+
/** 这条基线属于测试线还是正式线:测试包 versionName 由策略派生,与工程版本名不同。
|
|
691
|
+
* 读不到工程版本时按 prod 处理(保守:宁可少传一条测试基线,也不把测试包灌进正式 app)。 */
|
|
692
|
+
function baselineChannel(versionName, platform, cwd) {
|
|
693
|
+
try {
|
|
694
|
+
const base = readProjectVersions(cwd, null).find((v) => v.platform === platform)?.versionName;
|
|
695
|
+
return base && base !== versionName ? "beta" : "prod";
|
|
696
|
+
} catch {
|
|
697
|
+
return "prod";
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
/** 渠道 → 平台兜底映射(新链路优先用 stage:after 透传的 platform;此表仅兼容旧载荷) */
|
|
657
701
|
const CHANNEL_PLATFORM = { agc: "harmony" };
|
|
658
702
|
/** rnUpdate 插件工厂:注册完整 provider(判定 + beta 发布 + promote)+ 原生发版自动基线。
|
|
659
|
-
* cli 注入点:测试 mock / 特殊 transport;缺省 OpenAPI 客户端(token 来自 ctx.credentials)。
|
|
703
|
+
* cli 注入点:测试 mock / 特殊 transport;缺省 OpenAPI 客户端(token 来自 ctx.credentials)。
|
|
704
|
+
* beta 策略由项目配置决定,在 config:resolved 钩子里捕获(不重复声明在插件参数里)。 */
|
|
660
705
|
function rnUpdate(opts = {}, cli) {
|
|
661
|
-
|
|
706
|
+
let betaConfig = DEFAULT_BETA_VERSION_CONFIG;
|
|
707
|
+
const provider = makeRnUpdateProvider(opts, cli, () => betaConfig);
|
|
708
|
+
const uploadedBaselines = /* @__PURE__ */ new Set();
|
|
662
709
|
return {
|
|
663
710
|
name: "rn-update",
|
|
711
|
+
"config:resolved"(config) {
|
|
712
|
+
betaConfig = config.version?.beta ?? DEFAULT_BETA_VERSION_CONFIG;
|
|
713
|
+
},
|
|
664
714
|
"update:register"(providers) {
|
|
665
715
|
providers.push(provider);
|
|
666
716
|
},
|
|
667
717
|
async "stage:after"(result, hookCtx) {
|
|
668
|
-
const platform = CHANNEL_PLATFORM[result.channel];
|
|
718
|
+
const platform = result.platform ?? CHANNEL_PLATFORM[result.channel];
|
|
669
719
|
if (!result.ok || !platform || !result.artifactPath) return;
|
|
670
|
-
|
|
671
|
-
if (typeof appId !== "number") return;
|
|
720
|
+
if (opts[platform] === void 0) return;
|
|
672
721
|
try {
|
|
673
722
|
const versionName = readArtifactVersion(result.artifactPath)?.versionName;
|
|
674
723
|
if (!versionName) throw new Error(`未能从产物读出 versionName:${result.artifactPath}(readArtifactVersion 不支持该格式?)`);
|
|
724
|
+
const appId = platformAppId(opts, platform, result.target ?? baselineChannel(versionName, platform, hookCtx.cwd));
|
|
725
|
+
const key = `${platform}:${versionName}`;
|
|
726
|
+
if (uploadedBaselines.has(key)) return;
|
|
727
|
+
uploadedBaselines.add(key);
|
|
675
728
|
await resolvePushyClient(opts, cli, hookCtx.credentials).uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd));
|
|
676
729
|
} catch (e) {
|
|
730
|
+
uploadedBaselines.delete(`${platform}:${readArtifactVersion(result.artifactPath)?.versionName ?? ""}`);
|
|
677
731
|
process.stderr.write(`⚠ pushy 基线上传失败(请人工补传):${e.message}\n`);
|
|
678
732
|
}
|
|
679
733
|
}
|
|
680
734
|
};
|
|
681
735
|
}
|
|
682
736
|
//#endregion
|
|
683
|
-
export { PUSHY_DEFAULT_BASE_URL, PUSHY_TOKEN_KEY,
|
|
737
|
+
export { PUSHY_DEFAULT_BASE_URL, PUSHY_TOKEN_KEY, createPushyApi, dingtalkNotify, electronAdapter, electronFramework, flutterAdapter, flutterFramework, judgeDelivery, knownFrameworkAdapters, makeRnUpdateProvider, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, nodeHttpUpload, readDepVersions, rnAdapter, rnFramework, rnUpdate, suggestFramework, tauriAdapter, tauriFramework };
|