Add native service supervisor and runtime packaging

This commit is contained in:
reaper
2026-08-22 03:02:24 -05:00
parent 854ae3a2ad
commit 2bd9babab2
13 changed files with 483 additions and 26 deletions
+63
View File
@@ -0,0 +1,63 @@
'use strict'
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/explicit-function-return-type */
const { createHash } = require('crypto')
const { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } = require('fs')
const { dirname, isAbsolute, join, resolve, sep } = require('path')
const { spawnSync } = require('child_process')
function fail(message) {
throw new Error(message)
}
const [, , sourceArg, outputArg] = process.argv
if (!sourceArg || !outputArg)
fail('Usage: node scripts/package-native-runtime.cjs <staging-directory> <output.tar.gz>')
const source = resolve(sourceArg)
const output = resolve(outputArg)
const templatePath = join(source, 'runtime.template.json')
if (!existsSync(templatePath)) fail(`Missing ${templatePath}`)
const template = JSON.parse(readFileSync(templatePath, 'utf8'))
if (
template.schema !== 1 ||
!Array.isArray(template.components) ||
template.components.length === 0
)
fail('Invalid runtime template')
const components = template.components.map((component) => {
if (
!component.executable ||
isAbsolute(component.executable) ||
component.executable.split(/[\\/]/).includes('..')
)
fail(`Unsafe executable for ${component.id}`)
const executable = resolve(source, component.executable)
if (executable !== source && !executable.startsWith(`${source}${sep}`))
fail(`Executable leaves staging directory for ${component.id}`)
if (!existsSync(executable))
fail(`Missing executable for ${component.id}: ${component.executable}`)
const sha256 = createHash('sha256').update(readFileSync(executable)).digest('hex')
return {
id: component.id,
version: component.version,
executable: component.executable.replaceAll('\\', '/'),
sha256
}
})
const manifest = {
schema: 1,
runtimeVersion: template.runtimeVersion,
platform: template.platform,
arch: template.arch,
components
}
writeFileSync(join(source, 'runtime.json'), JSON.stringify(manifest, null, 2) + '\n')
mkdirSync(dirname(output), { recursive: true })
rmSync(output, { force: true })
const archive = spawnSync(
'tar',
['-czf', output, '--exclude=runtime.template.json', '-C', source, '.'],
{ stdio: 'inherit' }
)
if (archive.error) throw archive.error
if (archive.status !== 0) fail(`tar failed with exit code ${archive.status}`)
process.stdout.write(`${output}\n`)