XuqmGroup-Server/update-service/src/main/java/com/xuqm/update/entity/RnBundleEntity.java

199 行
8.1 KiB
Java

package com.xuqm.update.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
/**
* 一个经过平台签名的 RN 插件发布物。
*
* <p>身份字段全部来自 ZIP 内的 rn-manifest.json,发布、灰度和下线只能改变发布状态,
* 不能修改这些不可变字段。历史旧记录缺少 archiveSha256/signature,永远不会进入候选集。</p>
*/
@Entity
@Table(name = "update_rn_bundle")
public class RnBundleEntity {
public enum Platform { ANDROID, IOS }
public enum ModuleType { COMMON, APP, BUZ }
public enum PublishStatus { DRAFT, PUBLISHED, DEPRECATED }
public enum GrayMode { PERCENT, MEMBERS }
@Id
private String id;
@Column(nullable = false, length = 64)
private String appKey;
@Column(nullable = false, length = 256)
private String packageName;
@Column(nullable = false, length = 64)
private String moduleId;
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 16)
private ModuleType moduleType;
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 16)
private Platform platform;
@Column(nullable = false, length = 64)
private String version;
@Column(nullable = false, length = 128)
private String appVersionRange;
@Column(nullable = false, length = 128)
private String builtAgainstNativeBaselineId;
@Column(nullable = false, length = 128)
private String buildId;
@Column(nullable = false, length = 32)
private String bundleFormat;
@Column(length = 128)
private String commonVersionRange;
@Column(nullable = false)
private Integer minNativeApiLevel;
/** ZIP 内真实 JS/Hermes Bundle 的 SHA-256。 */
@Column(nullable = false, length = 64)
private String bundleSha256;
/** 客户端实际下载并校验的整个 .xuqm.zip 的 SHA-256。 */
@Column(nullable = false, length = 64)
private String archiveSha256;
@Column(nullable = false, length = 512)
private String bundleUrl;
/** Ed25519 签名覆盖的规范 JSON,必须与上面的身份字段逐项一致。 */
@Column(nullable = false, columnDefinition = "TEXT")
private String signedManifest;
@Column(nullable = false, length = 64)
private String signingKeyId;
@Column(nullable = false, length = 256)
private String signature;
@Column(length = 512)
private String note;
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 16)
private PublishStatus publishStatus;
@Column(length = 16)
private String publishMode = "MANUAL";
private LocalDateTime scheduledPublishAt;
@Column(nullable = false)
private boolean grayEnabled;
@Column(nullable = false)
private int grayPercent;
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 24)
private GrayMode grayMode = GrayMode.PERCENT;
@Column(columnDefinition = "TEXT")
private String grayMemberIds;
@Column(columnDefinition = "TEXT")
private String grayGroupNames;
@Column(columnDefinition = "TEXT")
private String extraMemberIds;
@Column(nullable = false)
private LocalDateTime createdAt;
public boolean hasTerminalIdentity() {
return hasText(packageName) && moduleType != null && hasText(appVersionRange)
&& hasText(builtAgainstNativeBaselineId) && hasText(buildId) && hasText(bundleFormat)
&& minNativeApiLevel != null && minNativeApiLevel > 0 && isSha256(bundleSha256)
&& isSha256(archiveSha256) && hasText(signedManifest) && hasText(signingKeyId)
&& hasText(signature);
}
private static boolean hasText(String value) {
return value != null && !value.isBlank();
}
private static boolean isSha256(String value) {
return value != null && value.matches("(?i)[a-f0-9]{64}");
}
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getAppKey() { return appKey; }
public void setAppKey(String appKey) { this.appKey = appKey; }
public String getPackageName() { return packageName; }
public void setPackageName(String packageName) { this.packageName = packageName; }
public String getModuleId() { return moduleId; }
public void setModuleId(String moduleId) { this.moduleId = moduleId; }
public ModuleType getModuleType() { return moduleType; }
public void setModuleType(ModuleType moduleType) { this.moduleType = moduleType; }
public Platform getPlatform() { return platform; }
public void setPlatform(Platform platform) { this.platform = platform; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getAppVersionRange() { return appVersionRange; }
public void setAppVersionRange(String value) { this.appVersionRange = value; }
public String getBuiltAgainstNativeBaselineId() { return builtAgainstNativeBaselineId; }
public void setBuiltAgainstNativeBaselineId(String value) { this.builtAgainstNativeBaselineId = value; }
public String getBuildId() { return buildId; }
public void setBuildId(String buildId) { this.buildId = buildId; }
public String getBundleFormat() { return bundleFormat; }
public void setBundleFormat(String bundleFormat) { this.bundleFormat = bundleFormat; }
public String getCommonVersionRange() { return commonVersionRange; }
public void setCommonVersionRange(String value) { this.commonVersionRange = value; }
public Integer getMinNativeApiLevel() { return minNativeApiLevel; }
public void setMinNativeApiLevel(Integer value) { this.minNativeApiLevel = value; }
public String getBundleSha256() { return bundleSha256; }
public void setBundleSha256(String value) { this.bundleSha256 = value; }
public String getArchiveSha256() { return archiveSha256; }
public void setArchiveSha256(String value) { this.archiveSha256 = value; }
public String getBundleUrl() { return bundleUrl; }
public void setBundleUrl(String bundleUrl) { this.bundleUrl = bundleUrl; }
public String getSignedManifest() { return signedManifest; }
public void setSignedManifest(String value) { this.signedManifest = value; }
public String getSigningKeyId() { return signingKeyId; }
public void setSigningKeyId(String value) { this.signingKeyId = value; }
public String getSignature() { return signature; }
public void setSignature(String value) { this.signature = value; }
public String getNote() { return note; }
public void setNote(String note) { this.note = note; }
public PublishStatus getPublishStatus() { return publishStatus; }
public void setPublishStatus(PublishStatus value) { this.publishStatus = value; }
public String getPublishMode() { return publishMode; }
public void setPublishMode(String value) { this.publishMode = value; }
public LocalDateTime getScheduledPublishAt() { return scheduledPublishAt; }
public void setScheduledPublishAt(LocalDateTime value) { this.scheduledPublishAt = value; }
public boolean isGrayEnabled() { return grayEnabled; }
public void setGrayEnabled(boolean value) { this.grayEnabled = value; }
public int getGrayPercent() { return grayPercent; }
public void setGrayPercent(int value) { this.grayPercent = value; }
public GrayMode getGrayMode() { return grayMode; }
public void setGrayMode(GrayMode value) { this.grayMode = value; }
public String getGrayMemberIds() { return grayMemberIds; }
public void setGrayMemberIds(String value) { this.grayMemberIds = value; }
public String getGrayGroupNames() { return grayGroupNames; }
public void setGrayGroupNames(String value) { this.grayGroupNames = value; }
public String getExtraMemberIds() { return extraMemberIds; }
public void setExtraMemberIds(String value) { this.extraMemberIds = value; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime value) { this.createdAt = value; }
}