import assert from 'node:assert/strict' import { createHash } from 'node:crypto' import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import path from 'node:path' import test from 'node:test' import { strToU8, zipSync } from 'fflate' import { readReleasePackageIdentity } from './release-package.mjs' function createPackage(root, overrides = {}, bundle = 'bundle') { const bundleBytes = strToU8(bundle) const manifest = { schemaVersion: 1, moduleId: 'app', platform: 'android', version: '1.0.1', appVersion: '8.0.0', buildId: 'build-20260726', bundleFile: 'app.android.bundle', bundleSha256: createHash('sha256').update(bundleBytes).digest('hex'), bundleFormat: 'hermes-bytecode', builtAgainstNativeBaselineId: 'native-1', appVersionRange: '>=8.0.0 <9.0.0', commonVersionRange: '>=1.0.0 <2.0.0', minNativeApiLevel: 2, ...overrides, } const file = path.join(root, 'app.android.xuqm.zip') writeFileSync( file, zipSync({ 'rn-manifest.json': strToU8(JSON.stringify(manifest)), 'app.android.bundle': bundleBytes, }), ) return file } const expected = { moduleId: 'app', platform: 'android', moduleVersion: '1.0.1', appVersion: '8.0.0', } test('release identity is read from and verified against the packaged Bundle', () => { const root = mkdtempSync(path.join(tmpdir(), 'xuqm-release-package-')) try { const identity = readReleasePackageIdentity(createPackage(root), expected) assert.equal(identity.buildId, 'build-20260726') assert.equal(identity.bundleFormat, 'hermes-bytecode') assert.equal(identity.nativeBaselineId, 'native-1') assert.equal(identity.appVersionRange, '>=8.0.0 <9.0.0') assert.equal(identity.commonVersionRange, '>=1.0.0 <2.0.0') assert.equal(identity.minNativeApiLevel, 2) } finally { rmSync(root, { recursive: true, force: true }) } }) test('publishing rejects development identity and mismatched packaged Bundle hash', () => { const root = mkdtempSync(path.join(tmpdir(), 'xuqm-release-package-invalid-')) try { assert.throws( () => readReleasePackageIdentity(createPackage(root, { buildId: 'development' }), expected), /without a release buildId/, ) assert.throws( () => readReleasePackageIdentity(createPackage(root, { bundleSha256: 'a'.repeat(64) }), expected), /does not match bundle content/, ) } finally { rmSync(root, { recursive: true, force: true }) } })