You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

90 lines
1.9 KiB
JavaScript

import * as pty from 'node-pty'
import { getContainerPath, runCommand } from './utils.js'
import fs from 'fs/promises'
import { randomUUID } from 'crypto'
const stat = path =>
new Promise(resolve =>
fs
.access(path)
.then(() => resolve(true))
.catch(() => resolve(false))
)
const containerIds = new Set()
await cleanContainers()
async function storeContainers() {
await fs.writeFile('containers-db.local.json', JSON.stringify([...containerIds]))
}
async function cleanContainers() {
if (!(await stat('containers-db.local.json'))) {
storeContainers()
}
const raw = JSON.parse(await fs.readFile('containers-db.local.json', 'utf8'))
await Promise.all(raw.map(id => destroyContainer(id)))
}
async function createContainer(tag) {
const id = randomUUID()
await fs.mkdir(getContainerPath('phc', id), { recursive: true })
await runCommand('docker', [
'run',
'-d',
'--name',
id,
'--volume',
`${getContainerPath('phc', id)}:/project`,
tag,
'sleep',
'infinity',
])
containerIds.add(id)
await storeContainers()
return id
}
export async function createContainerPty(
tag,
options = {
onExit,
onData,
shellCommand: ['/bin/sh'],
}
) {
const shellCommand = options.shellCommand ?? ['/bin/sh']
const { onData, onExit } = options
const id = await createContainer(tag)
const container = pty.spawn('docker', ['exec', '-it', id, ...shellCommand])
container.onExit(async e => {
onExit?.(e)
await destroyContainer(id)
})
container.onData(data => {
onData?.(data)
})
return { id, pty: container }
}
async function destroyContainer(id) {
await runCommand('docker', ['rm', '-f', id])
containerIds.delete(id)
await storeContainers()
}