capgo and adk autoupdates. card tags
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// Publishes a live update of the Android app's web part:
|
||||
// 1. builds the Capacitor web bundle (its version comes from the build time),
|
||||
// 2. zips it into updates/android/bundle-<version>.zip,
|
||||
// 3. writes updates/android/version.json (version, zip, SHA-256, minimum native build).
|
||||
// The mobile-client dev/preview server serves updates/android at /m/android/, i.e.
|
||||
// https://dev.aggtaa.com/m/android/version.json. Installed apps pick the update up on the next check.
|
||||
//
|
||||
// minNativeBuild is the versionCode of the latest published APK (updates/android/apk.json, see
|
||||
// publish-android-apk.mjs): after an APK release, web updates go only to that APK or newer, older
|
||||
// installations are offered the APK instead. Publish an APK whenever the native part changes
|
||||
// (plugins, AndroidManifest, Java code).
|
||||
import { execSync } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { zipSync } from 'fflate';
|
||||
|
||||
const root = path.resolve(import.meta.dirname, '..');
|
||||
const distDir = path.join(root, 'dist-capacitor');
|
||||
const outDir = path.join(root, 'updates', 'android');
|
||||
const KEEP_BUNDLES = 3;
|
||||
|
||||
execSync('pnpm exec vite build --mode capacitor', { cwd: root, stdio: 'inherit' });
|
||||
|
||||
const { version } = JSON.parse(readFileSync(path.join(distDir, 'cardy-version.json'), 'utf8'));
|
||||
|
||||
function collect(dir, prefix = '') {
|
||||
const files = {};
|
||||
for (const name of readdirSync(dir)) {
|
||||
const full = path.join(dir, name);
|
||||
const rel = prefix ? `${prefix}/${name}` : name;
|
||||
if (statSync(full).isDirectory()) Object.assign(files, collect(full, rel));
|
||||
else files[rel] = readFileSync(full);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
const zip = Buffer.from(zipSync(collect(distDir), { level: 6 }));
|
||||
const checksum = createHash('sha256').update(zip).digest('hex');
|
||||
|
||||
let minNativeBuild = 1;
|
||||
try {
|
||||
minNativeBuild = Number(JSON.parse(readFileSync(path.join(outDir, 'apk.json'), 'utf8')).versionCode) || 1;
|
||||
} catch {
|
||||
// no APK published yet: any installed APK can take the bundle
|
||||
}
|
||||
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
const zipName = `bundle-${version}.zip`;
|
||||
writeFileSync(path.join(outDir, zipName), zip);
|
||||
// version.json last: clients never see a version whose zip is not there yet.
|
||||
writeFileSync(
|
||||
path.join(outDir, 'version.json'),
|
||||
JSON.stringify({ version, url: zipName, checksum, minNativeBuild, publishedAt: new Date().toISOString() }, null, 2),
|
||||
);
|
||||
|
||||
// Keep a few recent bundles (clients may be mid-download of the previous one).
|
||||
const bundles = readdirSync(outDir)
|
||||
.filter((f) => /^bundle-.+\.zip$/.test(f))
|
||||
.sort((a, b) => statSync(path.join(outDir, b)).mtimeMs - statSync(path.join(outDir, a)).mtimeMs);
|
||||
for (const old of bundles.slice(KEEP_BUNDLES)) unlinkSync(path.join(outDir, old));
|
||||
|
||||
console.log(`\nPublished Android update ${version} (${(zip.length / 1024).toFixed(0)} KiB, native build >= ${minNativeBuild})`);
|
||||
console.log(` ${path.join(outDir, zipName)}`);
|
||||
console.log('Served at /m/android/version.json by the mobile-client dev/preview server.');
|
||||
Reference in New Issue
Block a user