diff --git a/package.json b/package.json index d47438c1..aa4d2661 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint:fix": "prettier -w \"./**/*.ts\"", "build": "concurrently 'yarn:build:*'", "build:www": "cd packages/pockethost.io && yarn build", + "build:daemon": "cd packages/daemon && yarn build", "dev": "NODE_ENV=development concurrently 'yarn:dev:*'", "dev:proxy": "cd packages/proxy && yarn dev", "dev:www": "cd packages/pockethost.io && yarn dev", @@ -55,4 +56,4 @@ "postinstall-postinstall": "^2.1.0", "replace-in-file": "^7.0.1" } -} +} \ No newline at end of file diff --git a/packages/common/src/schema/Invocation.ts b/packages/common/src/schema/Invocation.ts index 55e24e9b..fc923e6d 100644 --- a/packages/common/src/schema/Invocation.ts +++ b/packages/common/src/schema/Invocation.ts @@ -2,10 +2,11 @@ import { BaseFields, IsoDate, RecordId } from './types' export const INVOCATION_COLLECTION = 'invocations' +export type InvocationPid = string export type InvocationFields = BaseFields & { instanceId: RecordId startedAt: IsoDate endedAt: IsoDate - pid: number + pid: InvocationPid totalSeconds: number } diff --git a/packages/daemon/package.json b/packages/daemon/package.json index e2a3500e..16147ad2 100644 --- a/packages/daemon/package.json +++ b/packages/daemon/package.json @@ -3,7 +3,8 @@ "version": "0.0.1", "license": "MIT", "scripts": { - "build": "echo 'Build complete' `date`", + "build": "yarn build:docker", + "build:docker": "cd src/services/PocketBaseService && docker build -t pockethost/pocketbase .", "dev": "tsx watch src/server.ts", "ddos": "NODE_ENV=development tsx watch src/stresser/index.ts", "start": "tsx src/server.ts", @@ -14,7 +15,9 @@ "@pockethost/common": "0.0.1", "@s-libs/micro-dash": "^15.1.0", "@types/decompress": "^4.2.4", + "@types/dockerode": "^3.3.19", "@types/http-proxy": "^1.17.9", + "@types/memorystream": "^0.3.1", "@types/node": "^18.11.9", "@types/semver": "^7.3.13", "@types/tmp": "^0.2.1", @@ -26,18 +29,21 @@ "date-fns": "^2.29.3", "decompress": "^4.2.1", "decompress-unzip": "^4.0.1", + "dockerode": "^3.3.5", "event-source-polyfill": "^1.0.31", "eventsource": "^2.0.2", "ftp-srv": "^4.6.2", "get-port": "^6.1.2", "http-proxy": "^1.18.1", "knex": "^2.3.0", + "memorystream": "^0.3.1", "node-fetch": "^3.3.0", "pocketbase": "^0.8.0", "semver": "^7.3.8", "sqlite": "^4.1.2", "sqlite3": "^5.1.6", "tmp": "^0.2.1", + "tsx": "^3.11.0", "type-fest": "^3.3.0", "url-pattern": "^1.0.3" } diff --git a/packages/daemon/src/constants.ts b/packages/daemon/src/constants.ts index 29d675fa..13e2a40f 100644 --- a/packages/daemon/src/constants.ts +++ b/packages/daemon/src/constants.ts @@ -77,6 +77,9 @@ export const DENO_PATH = env('DENO_PATH', `deno`) export const DAEMON_PB_SEMVER = env('DAEMON_PB_SEMVER', '') // This will default always to the max version +export const HOST_OS = env('HOST_OS', 'darwin') +export const DOCKER_ARCH = env('DOCKER_ARCH', 'arm64') + console.log({ PUBLIC_APP_PROTOCOL, PUBLIC_APP_DOMAIN, diff --git a/packages/daemon/src/services/InstanceService/InstanceService.ts b/packages/daemon/src/services/InstanceService/InstanceService.ts index 46e48b0b..1230dbdd 100644 --- a/packages/daemon/src/services/InstanceService/InstanceService.ts +++ b/packages/daemon/src/services/InstanceService/InstanceService.ts @@ -28,7 +28,7 @@ import { join } from 'path' import { ClientResponseError } from 'pocketbase' import { AsyncReturnType } from 'type-fest' import { instanceLoggerService } from '../InstanceLoggerService' -import { pocketbaseService } from '../PocketBaseService' +import { pocketbaseService } from '../PocketBaseService/PocketBaseService' import { portManager } from '../PortManager' import { createDenoProcess } from './Deno/DenoProcess' @@ -326,7 +326,7 @@ export const instanceService = mkSingleton( Create the invocation record */ healthyGuard() - const invocation = await createInvocation(instance, pid) + const invocation = await createInvocation(instance, pid()) shutdownManager.add(async () => { await finalizeInvocation(invocation).catch(error) }) diff --git a/packages/daemon/src/services/PocketBaseService.ts b/packages/daemon/src/services/PocketBaseService.ts deleted file mode 100644 index 6d5f07a9..00000000 --- a/packages/daemon/src/services/PocketBaseService.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { DAEMON_PB_DATA_DIR, DAEMON_PB_MIGRATIONS_DIR } from '$constants' -import { mkInternalAddress, mkInternalUrl, tryFetch } from '$util' -import { createCleanupManager, createTimerManager } from '@pockethost/common' -import { - SingletonBaseConfig, - mkSingleton, -} from '@pockethost/common/src/mkSingleton' -import { spawn } from 'child_process' -import { existsSync } from 'fs' -import getPort from 'get-port' -import { gte } from 'semver' -import { AsyncReturnType } from 'type-fest' -import { AsyncContext } from '../util/AsyncContext' -import { updaterService } from './UpdaterService/UpdaterService' - -export type PocketbaseCommand = 'serve' | 'migrate' -export type SpawnConfig = { - command: PocketbaseCommand - slug: string - version?: string - port?: number - isMothership?: boolean - onUnexpectedStop: ( - code: number | null, - stdout: string[], - stderr: string[], - ) => void -} -export type PocketbaseServiceApi = AsyncReturnType< - typeof createPocketbaseService -> - -export type PocketbaseServiceConfig = SingletonBaseConfig & {} - -export type PocketbaseProcess = { - url: string - pid: number | undefined - kill: () => Promise - exited: Promise -} - -function pidIsRunning(pid: number) { - try { - process.kill(pid, 0) - return true - } catch (e) { - return false - } -} - -export const createPocketbaseService = async ( - config: PocketbaseServiceConfig, -) => { - const { logger } = config - const _serviceLogger = logger.create('PocketbaseService') - const { dbg, error, warn, abort } = _serviceLogger - - const { getLatestVersion, getVersion } = await updaterService() - const maxVersion = getLatestVersion() - - const cm = createCleanupManager() - const tm = createTimerManager({}) - - const _spawn = async (cfg: SpawnConfig, context?: AsyncContext) => { - const logger = (context?.logger || _serviceLogger).create('spawn') - const { dbg, warn, error } = logger - const _cfg: Required = { - version: maxVersion, - port: cfg.port || (await getPort()), - isMothership: false, - ...cfg, - } - const { version, command, slug, port, onUnexpectedStop, isMothership } = - _cfg - const _version = version || maxVersion // If _version is blank, we use the max version available - const realVersion = await getVersion(_version) - const bin = realVersion.binPath - if (!existsSync(bin)) { - throw new Error( - `PocketBase binary (${bin}) not found. Contact pockethost.io.`, - ) - } - - const args = [ - command, - `--dir`, - `${DAEMON_PB_DATA_DIR}/${slug}/pb_data`, - `--publicDir`, - `${DAEMON_PB_DATA_DIR}/${slug}/pb_public`, - ] - if (gte(realVersion.version, `0.9.0`)) { - args.push(`--migrationsDir`) - args.push( - isMothership - ? DAEMON_PB_MIGRATIONS_DIR - : `${DAEMON_PB_DATA_DIR}/${slug}/pb_migrations`, - ) - } - if (command === 'serve') { - args.push(`--http`) - args.push(mkInternalAddress(port)) - } - - let isRunning = true - - dbg(`Spawning ${slug}`, { bin, args, cli: [bin, ...args].join(' ') }) - const ls = spawn(bin, args) - cm.add(() => { - ls.kill() - }) - - const stdout: string[] = [] - ls.stdout.on('data', (data: Buffer) => { - dbg(`${slug} stdout: ${data}`) - stdout.push(data.toString()) - if (stdout.length > 100) stdout.pop() - }) - - const stderr: string[] = [] - ls.stderr.on('data', (data: Buffer) => { - warn(`${slug} stderr: ${data}`) - stderr.push(data.toString()) - if (stderr.length > 100) stderr.pop() - }) - - ls.on('close', (code) => { - dbg(`${slug} closed with code ${code}`) - }) - - const exited = new Promise((resolve) => { - ls.on('exit', (code) => { - dbg(`${slug} exited with code ${code}`) - isRunning = false - if (code || stderr.length > 0) { - onUnexpectedStop?.(code, stdout, stderr) - } - resolve(code) - }) - }) - - ls.on('error', (err) => { - dbg(`${slug} had error ${err}`) - }) - - const url = mkInternalUrl(port) - if (command === 'serve') { - await tryFetch(url, { - preflight: async () => isRunning, - logger: _serviceLogger, - }) - } - const api: PocketbaseProcess = { - url, - exited, - pid: ls.pid, - kill: async () => { - const { pid } = ls - if (!pid) { - throw new Error( - `Attempt to kill a PocketBase process that was never running.`, - ) - } - const p = new Promise((resolve, reject) => { - let cid: NodeJS.Timeout - const tid = setTimeout(() => { - clearTimeout(cid) - reject(new Error(`Timeout waiting for pid:${pid} to die`)) - }, 1000) - const _check = () => { - dbg(`Checking to see if pid:${pid} is running`) - if (pidIsRunning(pid)) { - dbg(`pid:${pid} is still running`) - ls.kill() - cid = setTimeout(_check, 50) - } else { - dbg(`pid:${pid} is not running`) - clearTimeout(tid) - - resolve(true) - } - } - _check() - }) - return p - }, - } - return api - } - - const shutdown = () => { - dbg(`Shutting down pocketbaseService`) - tm.shutdown() - cm.shutdown() - } - - return { - spawn: _spawn, - shutdown, - } -} - -export const pocketbaseService = mkSingleton(createPocketbaseService) diff --git a/packages/daemon/src/services/PocketBaseService/Dockerfile b/packages/daemon/src/services/PocketBaseService/Dockerfile new file mode 100644 index 00000000..5ee02217 --- /dev/null +++ b/packages/daemon/src/services/PocketBaseService/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:3 +RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* + +EXPOSE 8090 + +CMD ["ls", "-lah", "/host_bin"] \ No newline at end of file diff --git a/packages/daemon/src/services/PocketBaseService/PocketBaseService.ts b/packages/daemon/src/services/PocketBaseService/PocketBaseService.ts new file mode 100644 index 00000000..3703c4d2 --- /dev/null +++ b/packages/daemon/src/services/PocketBaseService/PocketBaseService.ts @@ -0,0 +1,215 @@ +import { DAEMON_PB_DATA_DIR, DAEMON_PB_MIGRATIONS_DIR } from '$constants' +import { assert, mkInternalUrl, tryFetch } from '$util' +import { + InvocationPid, + createCleanupManager, + createTimerManager, +} from '@pockethost/common' +import { + SingletonBaseConfig, + mkSingleton, +} from '@pockethost/common/src/mkSingleton' +import Docker, { Container, ContainerCreateOptions } from 'dockerode' +import { existsSync } from 'fs' +import getPort from 'get-port' +import MemoryStream from 'memorystream' +import { dirname } from 'path' +import { gte } from 'semver' +import { AsyncReturnType } from 'type-fest' +import { AsyncContext } from '../../util/AsyncContext' +import { updaterService } from '../UpdaterService/UpdaterService' + +export type PocketbaseCommand = 'serve' | 'migrate' +export type SpawnConfig = { + command: PocketbaseCommand + slug: string + version?: string + port?: number + isMothership?: boolean + onUnexpectedStop: ( + code: number | null, + stdout: string[], + stderr: string[], + ) => void +} +export type PocketbaseServiceApi = AsyncReturnType< + typeof createPocketbaseService +> + +export type PocketbaseServiceConfig = SingletonBaseConfig & {} + +export type PocketbaseProcess = { + url: string + pid: () => InvocationPid + kill: () => Promise + exited: Promise +} + +export const createPocketbaseService = async ( + config: PocketbaseServiceConfig, +) => { + const { logger } = config + const _serviceLogger = logger.create('PocketbaseService') + const { dbg, error, warn, abort } = _serviceLogger + + const { getLatestVersion, getVersion } = await updaterService() + const maxVersion = getLatestVersion() + + const cm = createCleanupManager() + const tm = createTimerManager({}) + + const _spawn = async (cfg: SpawnConfig, context?: AsyncContext) => { + const logger = (context?.logger || _serviceLogger).create('spawn') + const { dbg, warn, error } = logger + const _cfg: Required = { + version: maxVersion, + port: cfg.port || (await getPort()), + isMothership: false, + ...cfg, + } + const { version, command, slug, port, onUnexpectedStop, isMothership } = + _cfg + const _version = version || maxVersion // If _version is blank, we use the max version available + const realVersion = await getVersion(_version) + const binPath = realVersion.binPath + if (!existsSync(binPath)) { + throw new Error( + `PocketBase binary (${binPath}) not found. Contact pockethost.io.`, + ) + } + + const bin = `/host_bin/pocketbase` + + const args = [ + bin, + command, + `--dir`, + `/host_data/pb_data`, + `--publicDir`, + `/host_data/pb_public`, + ] + if (gte(realVersion.version, `0.9.0`)) { + args.push(`--migrationsDir`) + args.push(`/host_data/pb_migrations`) + } + if (gte(realVersion.version, `0.17.0`)) { + args.push(`--hooksDir`) + args.push(`/host_data/pb_hooks`) + } + if (command === 'serve') { + args.push(`--http`) + args.push(`0.0.0.0:8090`) + } + + let isRunning = true + + const docker = new Docker() + const stdoutHistory: string[] = [] + const stderrHistory: string[] = [] + const stdout = new MemoryStream() + stdout.on('data', (data: Buffer) => { + dbg(`${slug} stdout: ${data}`) + stdoutHistory.push(data.toString()) + if (stdoutHistory.length > 100) stdoutHistory.pop() + }) + const stderr = new MemoryStream() + stderr.on('data', (data: Buffer) => { + warn(`${slug} stderr: ${data}`) + stderrHistory.push(data.toString()) + if (stderrHistory.length > 100) stderrHistory.pop() + }) + const createOptions: ContainerCreateOptions = { + Image: `pockethost/pocketbase`, + Cmd: args, + HostConfig: { + CpuPercent: 10, + PortBindings: { + '8090/tcp': [{ HostPort: `${port}` }], + }, + Binds: [ + `${dirname(binPath)}:/host_bin`, + `${DAEMON_PB_DATA_DIR}/${slug}:/host_data`, + `${ + isMothership + ? DAEMON_PB_MIGRATIONS_DIR + : `${DAEMON_PB_DATA_DIR}/${slug}/pb_migrations` + }:/host_data/pb_migrations`, + ], + }, + Tty: false, + ExposedPorts: { + [`8090/tcp`]: {}, + }, + } + dbg(`Spawning ${slug}`, { args, createOptions }) + + let container: Container | undefined = undefined + const exited = new Promise(async (resolveExit) => { + container = await new Promise((resolve) => { + docker + .run( + `pockethost/pocketbase`, + [bin, `--help`], + [stdout, stderr], + createOptions, + (err, data) => { + const { StatusCode } = data || {} + dbg(`${slug} closed with code ${StatusCode}`, { err, data }) + isRunning = false + if (StatusCode > 0) { + dbg(`${slug} stopped unexpectedly with code ${err}`, data) + onUnexpectedStop?.(StatusCode, stdoutHistory, stderrHistory) + } + resolveExit(0) + }, + ) + .on('container', (container: Container) => { + dbg(`Got container`, container) + resolve(container) + }) + }) + cm.add(async () => { + dbg(`Stopping ${slug} for cleanup`) + await container?.stop().catch(warn) + }) + }) + + const url = mkInternalUrl(port) + if (command === 'serve') { + await tryFetch(url, { + preflight: async () => isRunning, + logger: _serviceLogger, + }) + } + const api: PocketbaseProcess = { + url, + pid: () => { + assert(container) + return container.id + }, + exited, + kill: async () => { + if (!container) { + throw new Error( + `Attempt to kill a PocketBase process that was never running.`, + ) + } + await container.stop() + }, + } + return api + } + + const shutdown = () => { + dbg(`Shutting down pocketbaseService`) + tm.shutdown() + cm.shutdown() + } + + return { + spawn: _spawn, + shutdown, + } +} + +export const pocketbaseService = mkSingleton(createPocketbaseService) diff --git a/packages/daemon/src/services/UpdaterService/UpdaterService.ts b/packages/daemon/src/services/UpdaterService/UpdaterService.ts index c4793b40..ad1d5879 100644 --- a/packages/daemon/src/services/UpdaterService/UpdaterService.ts +++ b/packages/daemon/src/services/UpdaterService/UpdaterService.ts @@ -7,7 +7,6 @@ import { } from '@pockethost/common' import { keys } from '@s-libs/micro-dash' import { chmodSync, existsSync } from 'fs' -import { type } from 'os' import { join } from 'path' import { maxSatisfying, rsort } from 'semver' @@ -39,7 +38,7 @@ export const updaterService = mkSingleton( const cm = createCleanupManager() const tm = createTimerManager({}) - const osName = type().toLowerCase() + const osName = 'linux' // type().toLowerCase() const cpuArchitecture = process.arch === 'x64' ? 'amd64' : process.arch dbg({ osName, cpuArchitecture }) diff --git a/packages/daemon/src/services/clientService/InvocationMixin.ts b/packages/daemon/src/services/clientService/InvocationMixin.ts index 663c3383..0dbb40a0 100644 --- a/packages/daemon/src/services/clientService/InvocationMixin.ts +++ b/packages/daemon/src/services/clientService/InvocationMixin.ts @@ -1,6 +1,7 @@ import { InstanceFields, InvocationFields, + InvocationPid, pocketNow, safeCatch, } from '@pockethost/common' @@ -19,7 +20,7 @@ export const createInvocationMixin = ( const createInvocation = safeCatch( `createInvocation`, logger, - async (instance: InstanceFields, pid: number) => { + async (instance: InstanceFields, pid: InvocationPid) => { const init: Partial = { startedAt: pocketNow(), pid, diff --git a/packages/daemon/src/services/index.ts b/packages/daemon/src/services/index.ts index d68f55d9..be6bbdf5 100644 --- a/packages/daemon/src/services/index.ts +++ b/packages/daemon/src/services/index.ts @@ -1,6 +1,6 @@ export * from './FtpService/FtpService' export * from './InstanceService/InstanceService' -export * from './PocketBaseService' +export * from './PocketBaseService/PocketBaseService' export * from './ProxyService' export * from './RealtimeLog' export * from './RpcService/RpcService' diff --git a/yarn.lock b/yarn.lock index 80927b29..e7b6b743 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38,6 +38,11 @@ dependencies: regenerator-runtime "^0.14.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@dansvel/vite-plugin-markdown@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@dansvel/vite-plugin-markdown/-/vite-plugin-markdown-2.0.5.tgz#55cff46adb457cb654b84a424aef2e25ca635926" @@ -1096,6 +1101,22 @@ dependencies: "@types/node" "*" +"@types/docker-modem@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/docker-modem/-/docker-modem-3.0.3.tgz#28e1d4971fc88073bbd03c989b40c978af693def" + integrity sha512-i1A2Etnav7uHizZ87vUf4EqwJehY3JOcTfBS0pGBlO+HQ0jg2lUMCaJRg9VQM8ldZkpYdIfsenxcTOCpwxPXEg== + dependencies: + "@types/node" "*" + "@types/ssh2" "*" + +"@types/dockerode@^3.3.19": + version "3.3.19" + resolved "https://registry.yarnpkg.com/@types/dockerode/-/dockerode-3.3.19.tgz#59eb07550a102b397a9504083a6c50d811eed04c" + integrity sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA== + dependencies: + "@types/docker-modem" "*" + "@types/node" "*" + "@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" @@ -1123,10 +1144,17 @@ resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.8.tgz#b316887ab3499d0a8f4c70b7bd8508f92d477955" integrity sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw== -"@types/node@*", "@types/node@^18.11.17", "@types/node@^18.11.9", "@types/node@^18.8.2": - version "18.11.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.17.tgz#5c009e1d9c38f4a2a9d45c0b0c493fe6cdb4bcb5" - integrity sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng== +"@types/memorystream@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@types/memorystream/-/memorystream-0.3.1.tgz#27436590f0b7398e029177c5a2ec5df20577c75a" + integrity sha512-eSkOeBPwr0godOTPV4hQTzXZElnpyHhhCCscrcN6teFLbSPC8Xyb/rxsU2r6tg+eNzIuVX4miav3KhY6NUpgMw== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^18.11.17", "@types/node@^18.11.18", "@types/node@^18.11.9", "@types/node@^18.8.2": + version "18.17.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.5.tgz#c58b12bca8c2a437b38c15270615627e96dd0bc5" + integrity sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA== "@types/parse-json@^4.0.0": version "4.0.0" @@ -1155,6 +1183,13 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/ssh2@*": + version "1.11.13" + resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-1.11.13.tgz#e6224da936abec0541bf26aa826b1cc37ea70d69" + integrity sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ== + dependencies: + "@types/node" "^18.11.18" + "@types/tmp@^0.2.1", "@types/tmp@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.3.tgz#908bfb113419fd6a42273674c00994d40902c165" @@ -1293,6 +1328,13 @@ aria-query@^5.3.0: dependencies: dequal "^2.0.3" +asn1@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -1322,6 +1364,13 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bcrypt-pbkdf@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1335,6 +1384,15 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.5.1: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -1415,7 +1473,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.2.1: +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -1423,6 +1481,11 @@ buffer@^5.2.1: base64-js "^1.3.1" ieee754 "^1.1.13" +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + builtin-modules@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -1526,6 +1589,11 @@ chokidar-cli@^3.0.0: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -1694,6 +1762,14 @@ cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cpu-features@~0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.8.tgz#a2d464b023b8ad09004c8cdca23b33f192f63546" + integrity sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg== + dependencies: + buildcheck "~0.0.6" + nan "^2.17.0" + cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -1829,7 +1905,7 @@ date-fns@^2.29.3, date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1934,6 +2010,25 @@ devalue@^4.3.1: resolved "https://registry.yarnpkg.com/devalue/-/devalue-4.3.2.tgz#cc44e4cf3872ac5a78229fbce3b77e57032727b5" integrity sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg== +docker-modem@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" + integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.11.0" + +dockerode@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" + integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^3.0.0" + tar-fs "~2.0.1" + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -2028,7 +2123,7 @@ encoding@^0.1.12: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -2732,7 +2827,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3178,6 +3273,11 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -3274,6 +3374,11 @@ minizlib@^2.0.0, minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -3341,7 +3446,7 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -nan@^2.14.0: +nan@^2.14.0, nan@^2.17.0: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== @@ -3485,7 +3590,7 @@ object-assign@^4.0.1, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3800,6 +3905,14 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -3838,10 +3951,10 @@ readable-stream@^2.3.0, readable-stream@^2.3.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -4005,7 +4118,7 @@ safe-json-stringify@~1: resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== -"safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -4159,6 +4272,11 @@ spawn-command@0.0.2: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== +split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -4180,6 +4298,17 @@ sqlite@^4.1.2: resolved "https://registry.yarnpkg.com/sqlite/-/sqlite-4.1.2.tgz#35643893dc1cec118c835cbab9ddbd283ffaba7d" integrity sha512-FlBG51gHbux5vPjwnoqFEghNGvnTMTbHyiI09U3qFTQs9AtWuwd4i++6+WCusCXKrVdIDLzfdGekrolr3m4U4A== +ssh2@^1.11.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" + integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.8" + nan "^2.17.0" + ssri@^8.0.0, ssri@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" @@ -4352,6 +4481,16 @@ svgo@^2.4.0: picocolors "^1.0.0" stable "^0.1.8" +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -4365,6 +4504,17 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" +tar-stream@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: version "6.1.12" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.12.tgz#3b742fb05669b55671fb769ab67a7791ea1a62e6" @@ -4466,7 +4616,7 @@ tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tsx@^3.12.8: +tsx@^3.11.0, tsx@^3.12.8: version "3.12.10" resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.12.10.tgz#073b7c8368c61dd6b816523eb203e6c8099c27ec" integrity sha512-2+46h4xvUt1aLDNvk5YBT8Uzw+b7BolGbn7iSMucYqCXZiDc+1IMghLVdw8kKjING32JFOeO+Am9posvjkeclA== @@ -4477,6 +4627,11 @@ tsx@^3.12.8: optionalDependencies: fsevents "~2.3.2" +tweetnacl@^0.14.3: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"