XuqmGroup-RNSDK/packages/update/scripts/native-baseline.mjs

79 行
2.6 KiB
JavaScript

import { createHash } from 'node:crypto'
import { existsSync, readFileSync, readdirSync } from 'node:fs'
import path from 'node:path'
const NATIVE_EXTENSIONS = new Set([
'.c',
'.cc',
'.cmake',
'.cpp',
'.gradle',
'.h',
'.java',
'.kts',
'.kt',
'.properties',
'.toml',
'.xml',
])
const IGNORED_DIRECTORIES = new Set(['.cxx', '.gradle', 'build', 'generated'])
const IGNORED_FILES = new Set(['local.properties'])
function walkNativeFiles(directory, root = directory) {
if (!existsSync(directory)) return []
const files = []
for (const entry of readdirSync(directory, { withFileTypes: true })) {
if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) continue
const absolute = path.join(directory, entry.name)
if (entry.isDirectory()) files.push(...walkNativeFiles(absolute, root))
else if (
!IGNORED_FILES.has(entry.name) &&
(NATIVE_EXTENSIONS.has(path.extname(entry.name)) || entry.name === 'gradlew')
) {
files.push({ absolute, relative: path.relative(root, absolute).split(path.sep).join('/') })
}
}
return files
}
function packageJson(directory) {
const file = path.join(directory, 'package.json')
return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : null
}
function nativeDependencyVersions(root, hostPackage) {
const dependencies = { ...hostPackage.dependencies, ...hostPackage.devDependencies }
const native = []
for (const name of Object.keys(dependencies).sort()) {
const directory = path.join(root, 'node_modules', ...name.split('/'))
const manifest = packageJson(directory)
if (!manifest) continue
const hasNativeCode =
existsSync(path.join(directory, 'android')) ||
existsSync(path.join(directory, 'react-native.config.js')) ||
manifest.codegenConfig !== undefined
if (hasNativeCode || name === 'react-native') {
native.push(`${name}@${manifest.version ?? dependencies[name]}`)
}
}
return native
}
/** Deterministic identity of code and dependencies that can only change through a full APK. */
export function computeNativeBaseline(root = process.cwd()) {
const hostPackage = packageJson(root)
if (!hostPackage) throw new Error('package.json is missing')
const hash = createHash('sha256')
for (const dependency of nativeDependencyVersions(root, hostPackage)) {
hash.update(`dependency\0${dependency}\0`)
}
for (const file of walkNativeFiles(path.join(root, 'android')).sort((a, b) =>
a.relative.localeCompare(b.relative),
)) {
hash.update(`file\0${file.relative}\0`)
hash.update(readFileSync(file.absolute))
hash.update('\0')
}
return `android-sha256:${hash.digest('hex')}`
}