fix(android): patch android config identifier and avoid Java reserved words
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
30
.github/scripts/prepare-template.mjs
vendored
30
.github/scripts/prepare-template.mjs
vendored
@@ -18,6 +18,12 @@ if (!jobId || !appName || !appIdentifier) {
|
||||
const zipPath = path.join(root, "builds", jobId, "site.zip");
|
||||
const distDir = path.join(root, "template", "dist");
|
||||
const confPath = path.join(root, "template", "src-tauri", "tauri.conf.json");
|
||||
const androidConfPath = path.join(
|
||||
root,
|
||||
"template",
|
||||
"src-tauri",
|
||||
"tauri.android.conf.json",
|
||||
);
|
||||
|
||||
if (!fs.existsSync(zipPath)) {
|
||||
console.error(`Missing upload: ${zipPath}`);
|
||||
@@ -36,14 +42,22 @@ if (!fs.existsSync(indexPath)) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const conf = JSON.parse(fs.readFileSync(confPath, "utf8"));
|
||||
conf.productName = appName;
|
||||
conf.mainBinaryName = appName.replace(/[^\w.-]+/g, "") || "Web2App";
|
||||
conf.identifier = appIdentifier;
|
||||
conf.version = "1.0.0";
|
||||
conf.app.windows = conf.app.windows ?? [{}];
|
||||
conf.app.windows[0].title = appName;
|
||||
fs.writeFileSync(confPath, `${JSON.stringify(conf, null, 2)}\n`);
|
||||
function patchTauriConfig(filePath) {
|
||||
const conf = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
||||
conf.productName = appName;
|
||||
conf.mainBinaryName = appName.replace(/[^\w.-]+/g, "") || "Web2App";
|
||||
conf.identifier = appIdentifier;
|
||||
conf.version = "1.0.0";
|
||||
if (conf.app?.windows?.[0]) {
|
||||
conf.app.windows[0].title = appName;
|
||||
}
|
||||
fs.writeFileSync(filePath, `${JSON.stringify(conf, null, 2)}\n`);
|
||||
}
|
||||
|
||||
patchTauriConfig(confPath);
|
||||
if (fs.existsSync(androidConfPath)) {
|
||||
patchTauriConfig(androidConfPath);
|
||||
}
|
||||
|
||||
const iconCandidates = ["icon.png", "favicon.png", "logo.png"];
|
||||
for (const candidate of iconCandidates) {
|
||||
|
||||
@@ -16,7 +16,12 @@ import {
|
||||
triggerBuildWorkflow,
|
||||
uploadSiteZip,
|
||||
} from "../services/github.js";
|
||||
import { slugifyIdentifier, validateZipBuffer, ZipValidationError } from "../services/zip.js";
|
||||
import {
|
||||
normalizeAppIdentifier,
|
||||
slugifyIdentifier,
|
||||
validateZipBuffer,
|
||||
ZipValidationError,
|
||||
} from "../services/zip.js";
|
||||
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
@@ -69,9 +74,10 @@ buildsRouter.post("/", upload.single("file"), async (req, res) => {
|
||||
|
||||
const { normalizedBuffer } = validateZipBuffer(req.file.buffer, maxUploadBytes);
|
||||
const jobId = nanoid(10);
|
||||
const appIdentifier =
|
||||
identifierInput ||
|
||||
`com.web2app.${slugifyIdentifier(appName) || jobId.toLowerCase()}`;
|
||||
const slug = slugifyIdentifier(appName) || jobId.toLowerCase();
|
||||
const appIdentifier = normalizeAppIdentifier(
|
||||
identifierInput || `com.web2app.${slug}`,
|
||||
);
|
||||
|
||||
insertBuild({ id: jobId, appName, appIdentifier });
|
||||
|
||||
|
||||
@@ -93,10 +93,91 @@ function addDirectoryToZip(zip: AdmZip, dir: string, prefix: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const JAVA_RESERVED_SEGMENTS = new Set([
|
||||
"abstract",
|
||||
"assert",
|
||||
"boolean",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"default",
|
||||
"do",
|
||||
"double",
|
||||
"else",
|
||||
"enum",
|
||||
"extends",
|
||||
"final",
|
||||
"finally",
|
||||
"float",
|
||||
"for",
|
||||
"goto",
|
||||
"if",
|
||||
"implements",
|
||||
"import",
|
||||
"instanceof",
|
||||
"int",
|
||||
"interface",
|
||||
"long",
|
||||
"native",
|
||||
"new",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"return",
|
||||
"short",
|
||||
"static",
|
||||
"strictfp",
|
||||
"super",
|
||||
"switch",
|
||||
"synchronized",
|
||||
"this",
|
||||
"throw",
|
||||
"throws",
|
||||
"transient",
|
||||
"try",
|
||||
"void",
|
||||
"volatile",
|
||||
"while",
|
||||
]);
|
||||
|
||||
function sanitizeSegment(segment: string): string {
|
||||
let value = segment.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
||||
if (!value) return "app";
|
||||
if (/^\d/.test(value)) value = `app${value}`;
|
||||
if (JAVA_RESERVED_SEGMENTS.has(value)) value = `${value}app`;
|
||||
return value.slice(0, 48);
|
||||
}
|
||||
|
||||
export function slugifyIdentifier(input: string): string {
|
||||
return input
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, ".")
|
||||
.replace(/^\.+|\.+$/g, "")
|
||||
.slice(0, 48);
|
||||
.split(".")
|
||||
.map(sanitizeSegment)
|
||||
.filter(Boolean)
|
||||
.join(".")
|
||||
.slice(0, 120);
|
||||
}
|
||||
|
||||
export function normalizeAppIdentifier(identifier: string): string {
|
||||
const parts = identifier
|
||||
.trim()
|
||||
.split(".")
|
||||
.map(sanitizeSegment)
|
||||
.filter(Boolean);
|
||||
|
||||
if (parts.length < 2) {
|
||||
throw new ZipValidationError(
|
||||
"Bundle ID 至少需要两段,例如 com.example.myapp",
|
||||
);
|
||||
}
|
||||
|
||||
return parts.join(".");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Web2App",
|
||||
"version": "1.0.0",
|
||||
"identifier": "com.web2app.default",
|
||||
"identifier": "com.web2app.app",
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"productName": "Web2App",
|
||||
"mainBinaryName": "Web2App",
|
||||
"version": "1.0.0",
|
||||
"identifier": "com.web2app.default",
|
||||
"identifier": "com.web2app.app",
|
||||
"build": {
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": "",
|
||||
|
||||
Reference in New Issue
Block a user