@absolutejs/deploy 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cloudTarget.d.ts +4 -4
- package/dist/cloudflare.d.ts +2 -2
- package/dist/cloudflare.js.map +2 -2
- package/dist/deployer.d.ts +9 -9
- package/dist/digitalocean.d.ts +5 -5
- package/dist/digitalocean.js +8 -2
- package/dist/digitalocean.js.map +5 -5
- package/dist/digitaloceanDns.d.ts +2 -2
- package/dist/digitaloceanDns.js +8 -2
- package/dist/digitaloceanDns.js.map +6 -6
- package/dist/digitaloceanInfrastructure.js +8 -2
- package/dist/digitaloceanInfrastructure.js.map +6 -6
- package/dist/digitaloceanIngress.js +8 -2
- package/dist/digitaloceanIngress.js.map +5 -5
- package/dist/dns.d.ts +1 -1
- package/dist/dns.js.map +2 -2
- package/dist/env.d.ts +1 -1
- package/dist/env.js.map +2 -2
- package/dist/gcp.js +6 -2
- package/dist/gcp.js.map +3 -3
- package/dist/hetzner.d.ts +3 -3
- package/dist/hetzner.js +8 -2
- package/dist/hetzner.js.map +5 -5
- package/dist/hetznerDns.d.ts +2 -2
- package/dist/hetznerDns.js.map +2 -2
- package/dist/hetznerInfrastructure.js +8 -2
- package/dist/hetznerInfrastructure.js.map +7 -7
- package/dist/index.d.ts +10 -10
- package/dist/index.js +64 -16
- package/dist/index.js.map +5 -5
- package/dist/linode.d.ts +3 -3
- package/dist/linode.js +8 -2
- package/dist/linode.js.map +5 -5
- package/dist/linodeInfrastructure.js +13 -3
- package/dist/linodeInfrastructure.js.map +7 -7
- package/dist/managedPreview.d.ts +1 -0
- package/dist/managedPreview.js +3 -2
- package/dist/managedPreview.js.map +3 -3
- package/dist/preview.d.ts +3 -3
- package/dist/preview.js +5 -2
- package/dist/preview.js.map +3 -3
- package/dist/processManagers.d.ts +4 -4
- package/dist/route53.d.ts +2 -2
- package/dist/route53.js.map +2 -2
- package/dist/targets.d.ts +1 -1
- package/dist/tls.d.ts +5 -5
- package/dist/tls.js +5 -2
- package/dist/tls.js.map +3 -3
- package/dist/vultr.d.ts +4 -4
- package/dist/vultr.js +8 -2
- package/dist/vultr.js.map +5 -5
- package/dist/vultrInfrastructure.js +8 -2
- package/dist/vultrInfrastructure.js.map +7 -7
- package/package.json +1 -1
package/dist/linode.js.map
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/targets.ts", "../src/cloudTarget.ts", "../src/linode.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Target interface + bundled adapters (localTarget, sshTarget).\n *\n * A Target is the narrowest abstraction over \"a place I can deploy to\":\n *\n * - `exec(cmd, opts?)` — run a shell command, capture stdout/stderr/exitCode.\n * - `upload(localPath, remotePath, opts?)` — copy a local file or directory\n * to the target. Implementation is free to use whatever is fast (rsync,\n * scp, mv).\n * - `close?()` — optional teardown.\n *\n * Two adapters are bundled:\n *\n * - `localTarget` runs in a temp directory on the local filesystem. Useful\n * for tests and for \"deploy\" workflows that happen on the same host.\n * - `sshTarget` shells out to the system `ssh` and `rsync` binaries. No\n * `ssh2` npm dependency — the controller machine just needs `ssh` and\n * (optionally) `rsync` in PATH, which is universal on Mac/Linux/WSL.\n *\n * Provider-specific targets (Cloudflare Workers HTTP API, Fly Machines API,\n * AWS Fargate) don't fit \"exec + upload\" and ship as siblings later.\n */\n\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type ExecOptions = {\n\t/** Working directory on the target. Default: target's root. */\n\tcwd?: string;\n\t/** Env vars to set for this command (merged onto target.env). */\n\tenv?: Record<string, string>;\n\t/** Hard kill after this many ms. Default 600_000 (10 min). 0 disables. */\n\ttimeoutMs?: number;\n\t/** Pipe stdout/stderr through here as it streams (lines, newline-stripped). */\n\tonLog?: (line: string, stream: 'stdout' | 'stderr') => void;\n\t/** Stdin payload — a string is written verbatim. */\n\tstdin?: string;\n};\n\nexport type ExecResult = {\n\tstdout: string;\n\tstderr: string;\n\texitCode: number;\n};\n\nexport type UploadOptions = {\n\t/** Exclude paths matching these globs from a directory upload. */\n\texclude?: string[];\n\t/** When uploading a directory, delete remote files not present locally. */\n\tdeleteOrphans?: boolean;\n};\n\nexport type Target = {\n\t/** Human-readable description (e.g. \"ssh root@droplet-1.example.com\"). */\n\treadonly description: string;\n\texec: (cmd: string, opts?: ExecOptions) => Promise<ExecResult>;\n\tupload: (localPath: string, remotePath: string, opts?: UploadOptions) => Promise<void>;\n\tclose?: () => Promise<void>;\n};\n\n// -----------------------------------------------------------------------------\n// localTarget\n// -----------------------------------------------------------------------------\n\nexport type LocalTargetOptions = {\n\t/** Root directory the target operates in. Created if missing. */\n\troot: string;\n\t/** Env merged into every exec. */\n\tenv?: Record<string, string>;\n};\n\nconst decodeChunks = async (\n\treader: ReadableStream<Uint8Array> | null,\n\tonLine: ((line: string) => void) | undefined,\n): Promise<string> => {\n\tif (!reader) return '';\n\tconst decoder = new TextDecoder();\n\tlet buffer = '';\n\tlet collected = '';\n\tconst stream = reader.getReader();\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await stream.read();\n\t\t\tif (done) break;\n\t\t\tconst chunk = decoder.decode(value, { stream: true });\n\t\t\tcollected += chunk;\n\t\t\tif (!onLine) continue;\n\t\t\tbuffer += chunk;\n\t\t\tlet newline = buffer.indexOf('\\n');\n\t\t\twhile (newline !== -1) {\n\t\t\t\tconst line = buffer.slice(0, newline).replace(/\\r$/, '');\n\t\t\t\tif (line.length > 0) onLine(line);\n\t\t\t\tbuffer = buffer.slice(newline + 1);\n\t\t\t\tnewline = buffer.indexOf('\\n');\n\t\t\t}\n\t\t}\n\t\tconst tail = decoder.decode();\n\t\tcollected += tail;\n\t\tif (onLine && (buffer + tail).length > 0) onLine((buffer + tail).replace(/\\r$/, ''));\n\t} finally {\n\t\tstream.releaseLock();\n\t}\n\treturn collected;\n};\n\nconst runSpawn = async (\n\targv: string[],\n\toptions: {\n\t\tcwd?: string;\n\t\tenv?: Record<string, string>;\n\t\ttimeoutMs?: number;\n\t\tonLog?: ExecOptions['onLog'];\n\t\tstdin?: string;\n\t},\n): Promise<ExecResult> => {\n\tconst proc = Bun.spawn(argv, {\n\t\tcwd: options.cwd,\n\t\tenv: options.env,\n\t\tstderr: 'pipe',\n\t\tstdin: options.stdin === undefined ? 'ignore' : 'pipe',\n\t\tstdout: 'pipe',\n\t});\n\n\tif (options.stdin !== undefined && proc.stdin) {\n\t\t// Bun.spawn returns a FileSink for piped stdin — `write` + `end`, not a\n\t\t// WritableStream. (We use a permissive cast because @types/bun's\n\t\t// Subprocess.stdin discriminant flips based on the stdin generic.)\n\t\tconst sink = proc.stdin as unknown as {\n\t\t\twrite: (chunk: string | Uint8Array) => number | Promise<number>;\n\t\t\tend: () => void | Promise<void>;\n\t\t};\n\t\tconst wrote = sink.write(options.stdin);\n\t\tif (wrote && typeof (wrote as Promise<number>).then === 'function') {\n\t\t\tawait wrote;\n\t\t}\n\t\tconst ended = sink.end();\n\t\tif (ended && typeof (ended as Promise<void>).then === 'function') {\n\t\t\tawait ended;\n\t\t}\n\t}\n\n\tconst timeout = options.timeoutMs ?? 600_000;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tif (timeout > 0) {\n\t\ttimer = setTimeout(() => {\n\t\t\ttry { proc.kill(); } catch { /* already gone */ }\n\t\t}, timeout);\n\t}\n\n\tconst stdoutPromise = decodeChunks(\n\t\tproc.stdout as unknown as ReadableStream<Uint8Array>,\n\t\toptions.onLog ? (line) => options.onLog!(line, 'stdout') : undefined,\n\t);\n\tconst stderrPromise = decodeChunks(\n\t\tproc.stderr as unknown as ReadableStream<Uint8Array>,\n\t\toptions.onLog ? (line) => options.onLog!(line, 'stderr') : undefined,\n\t);\n\n\tconst [stdout, stderr, exitCode] = await Promise.all([\n\t\tstdoutPromise,\n\t\tstderrPromise,\n\t\tproc.exited,\n\t]);\n\tif (timer) clearTimeout(timer);\n\n\treturn { exitCode: exitCode ?? -1, stderr, stdout };\n};\n\nexport const localTarget = (options: LocalTargetOptions): Target => {\n\tconst baseEnv = { ...options.env };\n\tconst ensureRoot = async () => { await mkdir(options.root, { recursive: true }); };\n\n\treturn {\n\t\tdescription: `local ${options.root}`,\n\t\texec: async (cmd, opts) => {\n\t\t\tawait ensureRoot();\n\t\t\treturn runSpawn(['sh', '-c', cmd], {\n\t\t\t\tcwd: opts?.cwd ?? options.root,\n\t\t\t\tenv: { ...process.env, ...baseEnv, ...(opts?.env ?? {}) } as Record<string, string>,\n\t\t\t\tonLog: opts?.onLog,\n\t\t\t\tstdin: opts?.stdin,\n\t\t\t\ttimeoutMs: opts?.timeoutMs,\n\t\t\t});\n\t\t},\n\t\tupload: async (localPath, remotePath, opts) => {\n\t\t\tawait ensureRoot();\n\t\t\tconst dest = remotePath.startsWith('/') ? remotePath : join(options.root, remotePath);\n\t\t\tconst argv = ['rsync', '-a'];\n\t\t\tif (opts?.deleteOrphans) argv.push('--delete');\n\t\t\tfor (const pattern of opts?.exclude ?? []) argv.push('--exclude', pattern);\n\t\t\t// rsync semantics: a trailing slash on the source copies *contents*; without it the dir itself is nested.\n\t\t\targv.push(localPath, dest);\n\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tthrow new Error(`local upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t}\n\t\t},\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// sshTarget\n// -----------------------------------------------------------------------------\n\nexport type SshTargetOptions = {\n\t/** Hostname or IP of the remote. */\n\thost: string;\n\t/** Login user. Default `root`. */\n\tuser?: string;\n\t/** SSH port. Default 22. */\n\tport?: number;\n\t/** Path to SSH identity file. Default: ssh's own search. */\n\tidentity?: string;\n\t/** Extra flags appended to every `ssh` invocation. */\n\tsshFlags?: string[];\n\t/**\n\t * Use rsync for `upload`. Default true. When false, falls back to `scp`\n\t * which is universal but doesn't support delete / exclude.\n\t */\n\trsync?: boolean;\n\t/**\n\t * Env vars to forward via `ssh -o SendEnv=...`. Most remote sshd configs\n\t * accept only `LANG` and `LC_*` by default; for app env vars use the\n\t * step `env` option instead, which prepends `KEY=value` to the command.\n\t */\n\tforwardEnv?: string[];\n};\n\nconst sshTargetString = (options: SshTargetOptions): string => {\n\tconst user = options.user ?? 'root';\n\treturn `${user}@${options.host}`;\n};\n\nconst sshBaseFlags = (options: SshTargetOptions): string[] => {\n\tconst flags: string[] = [];\n\tif (options.port !== undefined && options.port !== 22) flags.push('-p', String(options.port));\n\tif (options.identity !== undefined) flags.push('-i', options.identity);\n\t// Never get stuck on a host-key prompt; treat unknown hosts as a fatal config issue rather than a UX detour.\n\tflags.push('-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=accept-new');\n\tfor (const flag of options.sshFlags ?? []) flags.push(flag);\n\treturn flags;\n};\n\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, `'\\\\''`)}'`;\n\nconst buildRemoteCmd = (cmd: string, opts: ExecOptions | undefined): string => {\n\tconst env = opts?.env;\n\tconst envPrefix = env\n\t\t? Object.entries(env).map(([k, v]) => `${k}=${shellQuote(v)}`).join(' ') + ' '\n\t\t: '';\n\tif (opts?.cwd) {\n\t\treturn `cd ${shellQuote(opts.cwd)} && ${envPrefix}${cmd}`;\n\t}\n\treturn `${envPrefix}${cmd}`;\n};\n\nexport const sshTarget = (options: SshTargetOptions): Target => {\n\tconst remote = sshTargetString(options);\n\tconst useRsync = options.rsync ?? true;\n\n\treturn {\n\t\tdescription: `ssh ${remote}${options.port && options.port !== 22 ? `:${options.port}` : ''}`,\n\t\texec: async (cmd, opts) => {\n\t\t\tconst argv = ['ssh', ...sshBaseFlags(options)];\n\t\t\tfor (const name of options.forwardEnv ?? []) argv.push('-o', `SendEnv=${name}`);\n\t\t\targv.push(remote, buildRemoteCmd(cmd, opts));\n\t\t\treturn runSpawn(argv, {\n\t\t\t\tonLog: opts?.onLog,\n\t\t\t\tstdin: opts?.stdin,\n\t\t\t\ttimeoutMs: opts?.timeoutMs,\n\t\t\t});\n\t\t},\n\t\tupload: async (localPath, remotePath, opts) => {\n\t\t\tif (useRsync) {\n\t\t\t\tconst sshCmd = ['ssh', ...sshBaseFlags(options)].map((part) => part.includes(' ') ? `'${part}'` : part).join(' ');\n\t\t\t\tconst argv = ['rsync', '-az', '-e', sshCmd];\n\t\t\t\tif (opts?.deleteOrphans) argv.push('--delete');\n\t\t\t\tfor (const pattern of opts?.exclude ?? []) argv.push('--exclude', pattern);\n\t\t\t\targv.push(localPath, `${remote}:${remotePath}`);\n\t\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\t\tif (result.exitCode !== 0) {\n\t\t\t\t\tthrow new Error(`rsync upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// scp fallback — no exclude, no delete. We still need -r to copy directories.\n\t\t\tconst argv = ['scp', '-r', ...sshBaseFlags(options), localPath, `${remote}:${remotePath}`];\n\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tthrow new Error(`scp upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t}\n\t\t},\n\t};\n};\n",
|
|
6
|
-
"/**\n * Shared \"cloud-provider Target\" plumbing used by the\n * provider-specific adapters (`./digitalocean`, `./hetzner`, future\n * `./linode`, `./vultr`, etc.).\n *\n * The provider supplies a small `CloudTargetHooks` bag that knows\n * the provider's:\n *\n * - find-by-name lookup\n * - create call (closure over create params)\n * - fetch-by-id (used to poll for `active`)\n * - destroy-by-id\n * - status + ipv4 + id extraction from the provider's Server shape\n * - readiness predicate (status reached the terminal \"running\" value)\n *\n * `createCloudTarget()` does the universal machinery: provision-or-\n * reuse, poll until ready + IPv4, wait for SSH probe, build\n * `sshTarget` against the IPv4, return the Target wrapped with\n * `{ id, ipv4, destroy() }`.\n *\n * The public adapter (e.g. `digitalOceanTarget`) is a 30-line facade\n * that wires its provider-specific bits and renames `id` → `dropletId`\n * on the way out.\n */\n\nimport type { Target } from
|
|
7
|
-
"/**\n * @absolutejs/deploy/linode — provision-or-reuse Target adapter for\n * Linode (Akamai Cloud) instances. Sibling to digitalOceanTarget +\n * hetznerTarget; same shape, Linode v4 API mappings.\n *\n * Idempotent by label — Linode allows duplicate labels per account\n * but we treat duplicates as drifted state (throw on the second).\n *\n * Narrow LinodeClientLike interface keeps `@linode/api-v4` out as a\n * hard dep. Default client uses `fetch` against `api.linode.com/v4`.\n */\n\nimport type { Target } from './targets';\nimport { createCloudTarget, type CloudTargetHooks } from './cloudTarget';\n\nconst LINODE_API_BASE = 'https://api.linode.com/v4';\n\nexport type LinodeClientLike = {\n\trequest: <T = unknown>(\n\t\tmethod: 'GET' | 'POST' | 'DELETE',\n\t\tpath: string,\n\t\tbody?: unknown\n\t) => Promise<T>;\n};\n\n/** A Linode instance, narrowed to what we inspect. */\nexport type LinodeInstance = {\n\tid: number;\n\tlabel: string;\n\tstatus:\n\t\t| 'running'\n\t\t| 'offline'\n\t\t| 'booting'\n\t\t| 'rebooting'\n\t\t| 'shutting_down'\n\t\t| 'provisioning'\n\t\t| 'deleting'\n\t\t| 'migrating'\n\t\t| 'rebuilding'\n\t\t| 'cloning'\n\t\t| 'restoring'\n\t\t| 'stopped';\n\t/** Linode returns IPv4 as a flat string array; public IPs first. */\n\tipv4: string[];\n\tregion?: string;\n\ttype?: string;\n\ttags?: string[];\n};\n\nexport type LinodeTargetOptions = {\n\t/** Linode Personal Access Token. Required unless `client` is set. */\n\ttoken?: string;\n\t/** Custom client. Overrides token-built default. */\n\tclient?: LinodeClientLike;\n\n\t// ── Instance shape ──────────────────────────────────────────────\n\t/** Instance label. Idempotency key. */\n\tname: string;\n\t/** Region slug — `'us-east'`, `'us-west'`, `'ap-south'`, etc. */\n\tregion: string;\n\t/** Type slug — `'g6-nanode-1'`, `'g6-standard-1'`, etc. */\n\ttype: string;\n\t/** Image slug — e.g. `'linode/ubuntu22.04'`. */\n\timage: string;\n\t/**\n\t * SSH public keys (raw `ssh-rsa AAAA…` / `ssh-ed25519 AAAA…` strings)\n\t * authorized for root login. At least one required for a usable target.\n\t */\n\tsshKeys: ReadonlyArray<string>;\n\t/** Tags applied to the instance. */\n\ttags?: ReadonlyArray<string>;\n\t/** Cloud-init / StackScript user data, base64-encoded by us. */\n\tuserData?: string;\n\t/**\n\t * Root password. Linode requires a password at creation. Defaults to\n\t * a random 32-char string — you should rely on `sshKeys` and never\n\t * type this. Override only if you have a specific reason.\n\t */\n\trootPass?: string;\n\t/** Enable private IP. Default false. */\n\tprivateIp?: boolean;\n\t/** Enable backups. Default false. */\n\tbackupsEnabled?: boolean;\n\n\t// ── SSH wrap ────────────────────────────────────────────────────\n\t/** SSH login user. Default `'root'`. */\n\tuser?: string;\n\t/** SSH identity file. */\n\tidentity?: string;\n\t/** SSH port. Default 22. */\n\tport?: number;\n\n\t// ── Timing ──────────────────────────────────────────────────────\n\tprovisionTimeoutMs?: number;\n\tsshReadinessTimeoutMs?: number;\n\tpollIntervalMs?: number;\n\n\t// ── Observability + injection ───────────────────────────────────\n\tonLog?: (line: string) => void;\n\tprobeSsh?: (host: string, port: number) => Promise<boolean>;\n\tsleep?: (ms: number) => Promise<void>;\n\tnow?: () => number;\n};\n\nexport type LinodeTarget = Target & {\n\treadonly instanceId: number;\n\treadonly ipv4: string;\n\tdestroy: () => Promise<void>;\n};\n\nexport class LinodeError extends Error {\n\treadonly status: number;\n\treadonly body: unknown;\n\tconstructor(message: string, status: number, body: unknown) {\n\t\tsuper(message);\n\t\tthis.name = 'LinodeError';\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport const createLinodeClient = (\n\ttoken: string,\n\toptions: { baseUrl?: string; fetch?: typeof fetch } = {}\n): LinodeClientLike => {\n\tconst base = options.baseUrl ?? LINODE_API_BASE;\n\tconst f = options.fetch ?? fetch;\n\treturn {\n\t\trequest: async <T>(\n\t\t\tmethod: 'GET' | 'POST' | 'DELETE',\n\t\t\tpath: string,\n\t\t\tbody?: unknown\n\t\t): Promise<T> => {\n\t\t\tconst init: RequestInit = {\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${token}`,\n\t\t\t\t\t'content-type': 'application/json'\n\t\t\t\t},\n\t\t\t\tmethod\n\t\t\t};\n\t\t\tif (body !== undefined) init.body = JSON.stringify(body);\n\t\t\tconst response = await f(`${base}${path}`, init);\n\t\t\tif (response.status === 204) return undefined as T;\n\t\t\tconst text = await response.text();\n\t\t\tconst parsed = text.length > 0 ? JSON.parse(text) : undefined;\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new LinodeError(\n\t\t\t\t\t`Linode API ${method} ${path} failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tparsed\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn parsed as T;\n\t\t}\n\t};\n};\n\nconst resolveClient = (\n\toptions: Pick<LinodeTargetOptions, 'client' | 'token'>\n): LinodeClientLike => {\n\tif (options.client !== undefined) return options.client;\n\tif (options.token !== undefined && options.token.length > 0) {\n\t\treturn createLinodeClient(options.token);\n\t}\n\tthrow new Error(\n\t\t'[deploy/linode] either `token` or `client` must be provided'\n\t);\n};\n\nconst publicIpv4 = (instance: LinodeInstance): string | undefined => {\n\t// Linode's first IPv4 entry is the primary public address.\n\tfor (const ip of instance.ipv4) {\n\t\t// Skip private RFC1918 + link-local. Crude but good enough.\n\t\tif (\n\t\t\t!ip.startsWith('10.') &&\n\t\t\t!ip.startsWith('192.168.') &&\n\t\t\t!ip.startsWith('172.') &&\n\t\t\t!ip.startsWith('169.254.')\n\t\t) {\n\t\t\treturn ip;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nconst randomPassword = (length: number): string => {\n\tconst chars =\n\t\t'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';\n\tconst bytes = new Uint8Array(length);\n\tcrypto.getRandomValues(bytes);\n\tlet out = '';\n\tfor (const byte of bytes) out += chars[byte % chars.length];\n\treturn out;\n};\n\n/** Find an instance by label. Throws on ambiguous duplicates. */\nexport const findLinodeInstance = async (\n\tclient: LinodeClientLike,\n\tname: string\n): Promise<LinodeInstance | undefined> => {\n\tconst body = await client.request<{ data: LinodeInstance[] }>(\n\t\t'GET',\n\t\t'/linode/instances?page_size=500'\n\t);\n\tconst matches = body.data.filter((instance) => instance.label === name);\n\tif (matches.length === 0) return undefined;\n\tif (matches.length > 1) {\n\t\tthrow new Error(\n\t\t\t`[deploy/linode] multiple instances labeled \"${name}\" (${matches\n\t\t\t\t.map((instance) => instance.id)\n\t\t\t\t.join(', ')}). Resolve manually before adopting.`\n\t\t);\n\t}\n\treturn matches[0];\n};\n\nexport const listLinodeInstances = async (options: {\n\ttoken?: string;\n\tclient?: LinodeClientLike;\n\ttag?: string;\n}): Promise<LinodeInstance[]> => {\n\tconst client = resolveClient(options);\n\tconst path =\n\t\toptions.tag !== undefined\n\t\t\t? `/linode/instances?tag=${encodeURIComponent(options.tag)}&page_size=500`\n\t\t\t: '/linode/instances?page_size=500';\n\tconst body = await client.request<{ data: LinodeInstance[] }>('GET', path);\n\treturn body.data;\n};\n\nexport const destroyLinodeInstance = async (options: {\n\ttoken?: string;\n\tclient?: LinodeClientLike;\n\tid: number;\n}): Promise<void> => {\n\tconst client = resolveClient(options);\n\ttry {\n\t\tawait client.request('DELETE', `/linode/instances/${options.id}`);\n\t} catch (error) {\n\t\tif (error instanceof LinodeError && error.status === 404) return;\n\t\tthrow error;\n\t}\n};\n\nexport const linodeTarget = async (\n\toptions: LinodeTargetOptions\n): Promise<LinodeTarget> => {\n\tconst client = resolveClient(options);\n\tconst rootPass = options.rootPass ?? randomPassword(32);\n\n\tconst hooks: CloudTargetHooks<LinodeInstance> = {\n\t\tcreate: async () => {\n\t\t\tconst created = await client.request<LinodeInstance>(\n\t\t\t\t'POST',\n\t\t\t\t'/linode/instances',\n\t\t\t\t{\n\t\t\t\t\tauthorized_keys: [...options.sshKeys],\n\t\t\t\t\timage: options.image,\n\t\t\t\t\tlabel: options.name,\n\t\t\t\t\tregion: options.region,\n\t\t\t\t\troot_pass: rootPass,\n\t\t\t\t\ttype: options.type,\n\t\t\t\t\t...(options.tags !== undefined ? { tags: [...options.tags] } : {}),\n\t\t\t\t\t...(options.userData !== undefined\n\t\t\t\t\t\t? { stackscript_data: { user_data: options.userData } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(options.privateIp === true ? { private_ip: true } : {}),\n\t\t\t\t\t...(options.backupsEnabled === true ? { backups_enabled: true } : {})\n\t\t\t\t}\n\t\t\t);\n\t\t\treturn created;\n\t\t},\n\t\tdestroy: (id) => destroyLinodeInstance({ client, id }),\n\t\tfetch: (id) => client.request<LinodeInstance>('GET', `/linode/instances/${id}`),\n\t\tfindByName: (name) => findLinodeInstance(client, name),\n\t\tgetId: (instance) => instance.id,\n\t\tgetIpv4: publicIpv4,\n\t\tgetStatus: (instance) => instance.status,\n\t\tisReady: (instance) => instance.status === 'running'\n\t};\n\n\tconst result = await createCloudTarget(hooks, {\n\t\tdescribeTarget: (sshDescription) =>\n\t\t\t`linode \"${options.name}\" (${sshDescription})`,\n\t\tentityWord: 'instance',\n\t\tlogPrefix: '[linode]',\n\t\tname: options.name,\n\t\tregion: options.region,\n\t\t...(options.user !== undefined ? { user: options.user } : {}),\n\t\t...(options.identity !== undefined ? { identity: options.identity } : {}),\n\t\t...(options.port !== undefined ? { port: options.port } : {}),\n\t\t...(options.provisionTimeoutMs !== undefined\n\t\t\t? { provisionTimeoutMs: options.provisionTimeoutMs }\n\t\t\t: {}),\n\t\t...(options.sshReadinessTimeoutMs !== undefined\n\t\t\t? { sshReadinessTimeoutMs: options.sshReadinessTimeoutMs }\n\t\t\t: {}),\n\t\t...(options.pollIntervalMs !== undefined\n\t\t\t? { pollIntervalMs: options.pollIntervalMs }\n\t\t\t: {}),\n\t\t...(options.onLog !== undefined ? { onLog: options.onLog } : {}),\n\t\t...(options.probeSsh !== undefined ? { probeSsh: options.probeSsh } : {}),\n\t\t...(options.sleep !== undefined ? { sleep: options.sleep } : {}),\n\t\t...(options.now !== undefined ? { now: options.now } : {})\n\t});\n\n\treturn {\n\t\tdescription: result.description,\n\t\tdestroy: result.destroy,\n\t\texec: result.exec,\n\t\tinstanceId: result.id,\n\t\tipv4: result.ipv4,\n\t\tupload: result.upload,\n\t\t...(result.close !== undefined ? { close: result.close } : {})\n\t};\n};\n"
|
|
5
|
+
"/**\n * Target interface + bundled adapters (localTarget, sshTarget).\n *\n * A Target is the narrowest abstraction over \"a place I can deploy to\":\n *\n * - `exec(cmd, opts?)` — run a shell command, capture stdout/stderr/exitCode.\n * - `upload(localPath, remotePath, opts?)` — copy a local file or directory\n * to the target. Implementation is free to use whatever is fast (rsync,\n * scp, mv).\n * - `close?()` — optional teardown.\n *\n * Two adapters are bundled:\n *\n * - `localTarget` runs in a temp directory on the local filesystem. Useful\n * for tests and for \"deploy\" workflows that happen on the same host.\n * - `sshTarget` shells out to the system `ssh` and `rsync` binaries. No\n * `ssh2` npm dependency — the controller machine just needs `ssh` and\n * (optionally) `rsync` in PATH, which is universal on Mac/Linux/WSL.\n *\n * Provider-specific targets (Cloudflare Workers HTTP API, Fly Machines API,\n * AWS Fargate) don't fit \"exec + upload\" and ship as siblings later.\n */\n\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type ExecOptions = {\n /** Working directory on the target. Default: target's root. */\n cwd?: string;\n /** Env vars to set for this command (merged onto target.env). */\n env?: Record<string, string>;\n /** Hard kill after this many ms. Default 600_000 (10 min). 0 disables. */\n timeoutMs?: number;\n /** Pipe stdout/stderr through here as it streams (lines, newline-stripped). */\n onLog?: (line: string, stream: \"stdout\" | \"stderr\") => void;\n /** Stdin payload — a string is written verbatim. */\n stdin?: string;\n};\n\nexport type ExecResult = {\n stdout: string;\n stderr: string;\n exitCode: number;\n};\n\nexport type UploadOptions = {\n /** Exclude paths matching these globs from a directory upload. */\n exclude?: string[];\n /** When uploading a directory, delete remote files not present locally. */\n deleteOrphans?: boolean;\n};\n\nexport type Target = {\n /** Human-readable description (e.g. \"ssh root@droplet-1.example.com\"). */\n readonly description: string;\n exec: (cmd: string, opts?: ExecOptions) => Promise<ExecResult>;\n upload: (\n localPath: string,\n remotePath: string,\n opts?: UploadOptions,\n ) => Promise<void>;\n close?: () => Promise<void>;\n};\n\n// -----------------------------------------------------------------------------\n// localTarget\n// -----------------------------------------------------------------------------\n\nexport type LocalTargetOptions = {\n /** Root directory the target operates in. Created if missing. */\n root: string;\n /** Env merged into every exec. */\n env?: Record<string, string>;\n};\n\nconst decodeChunks = async (\n reader: ReadableStream<Uint8Array> | null,\n onLine: ((line: string) => void) | undefined,\n): Promise<string> => {\n if (!reader) return \"\";\n const decoder = new TextDecoder();\n let buffer = \"\";\n let collected = \"\";\n const stream = reader.getReader();\n try {\n while (true) {\n const { done, value } = await stream.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n collected += chunk;\n if (!onLine) continue;\n buffer += chunk;\n let newline = buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = buffer.slice(0, newline).replace(/\\r$/, \"\");\n if (line.length > 0) onLine(line);\n buffer = buffer.slice(newline + 1);\n newline = buffer.indexOf(\"\\n\");\n }\n }\n const tail = decoder.decode();\n collected += tail;\n if (onLine && (buffer + tail).length > 0)\n onLine((buffer + tail).replace(/\\r$/, \"\"));\n } finally {\n stream.releaseLock();\n }\n return collected;\n};\n\nconst runSpawn = async (\n argv: string[],\n options: {\n cwd?: string;\n env?: Record<string, string>;\n timeoutMs?: number;\n onLog?: ExecOptions[\"onLog\"];\n stdin?: string;\n },\n): Promise<ExecResult> => {\n const proc = Bun.spawn(argv, {\n cwd: options.cwd,\n env: options.env,\n stderr: \"pipe\",\n stdin: options.stdin === undefined ? \"ignore\" : \"pipe\",\n stdout: \"pipe\",\n });\n\n if (options.stdin !== undefined && proc.stdin) {\n // Bun.spawn returns a FileSink for piped stdin — `write` + `end`, not a\n // WritableStream. (We use a permissive cast because @types/bun's\n // Subprocess.stdin discriminant flips based on the stdin generic.)\n const sink = proc.stdin as unknown as {\n write: (chunk: string | Uint8Array) => number | Promise<number>;\n end: () => void | Promise<void>;\n };\n const wrote = sink.write(options.stdin);\n if (wrote && typeof (wrote as Promise<number>).then === \"function\") {\n await wrote;\n }\n const ended = sink.end();\n if (ended && typeof (ended as Promise<void>).then === \"function\") {\n await ended;\n }\n }\n\n const timeout = options.timeoutMs ?? 600_000;\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (timeout > 0) {\n timer = setTimeout(() => {\n try {\n proc.kill();\n } catch {\n /* already gone */\n }\n }, timeout);\n }\n\n const stdoutPromise = decodeChunks(\n proc.stdout as unknown as ReadableStream<Uint8Array>,\n options.onLog ? (line) => options.onLog!(line, \"stdout\") : undefined,\n );\n const stderrPromise = decodeChunks(\n proc.stderr as unknown as ReadableStream<Uint8Array>,\n options.onLog ? (line) => options.onLog!(line, \"stderr\") : undefined,\n );\n\n const [stdout, stderr, exitCode] = await Promise.all([\n stdoutPromise,\n stderrPromise,\n proc.exited,\n ]);\n if (timer) clearTimeout(timer);\n\n return { exitCode: exitCode ?? -1, stderr, stdout };\n};\n\nexport const localTarget = (options: LocalTargetOptions): Target => {\n const baseEnv = { ...options.env };\n const ensureRoot = async () => {\n await mkdir(options.root, { recursive: true });\n };\n\n return {\n description: `local ${options.root}`,\n exec: async (cmd, opts) => {\n await ensureRoot();\n return runSpawn([\"sh\", \"-c\", cmd], {\n cwd: opts?.cwd ?? options.root,\n env: { ...process.env, ...baseEnv, ...(opts?.env ?? {}) } as Record<\n string,\n string\n >,\n onLog: opts?.onLog,\n stdin: opts?.stdin,\n timeoutMs: opts?.timeoutMs,\n });\n },\n upload: async (localPath, remotePath, opts) => {\n await ensureRoot();\n const dest = remotePath.startsWith(\"/\")\n ? remotePath\n : join(options.root, remotePath);\n const argv = [\"rsync\", \"-a\"];\n if (opts?.deleteOrphans) argv.push(\"--delete\");\n for (const pattern of opts?.exclude ?? [])\n argv.push(\"--exclude\", pattern);\n // rsync semantics: a trailing slash on the source copies *contents*; without it the dir itself is nested.\n argv.push(localPath, dest);\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `local upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n },\n };\n};\n\n// -----------------------------------------------------------------------------\n// sshTarget\n// -----------------------------------------------------------------------------\n\nexport type SshTargetOptions = {\n /** Hostname or IP of the remote. */\n host: string;\n /** Login user. Default `root`. */\n user?: string;\n /** SSH port. Default 22. */\n port?: number;\n /** Path to SSH identity file. Default: ssh's own search. */\n identity?: string;\n /** Extra flags appended to every `ssh` invocation. */\n sshFlags?: string[];\n /**\n * Use rsync for `upload`. Default true. When false, falls back to `scp`\n * which is universal but doesn't support delete / exclude.\n */\n rsync?: boolean;\n /**\n * Env vars to forward via `ssh -o SendEnv=...`. Most remote sshd configs\n * accept only `LANG` and `LC_*` by default; for app env vars use the\n * step `env` option instead, which prepends `KEY=value` to the command.\n */\n forwardEnv?: string[];\n};\n\nconst sshTargetString = (options: SshTargetOptions): string => {\n const user = options.user ?? \"root\";\n return `${user}@${options.host}`;\n};\n\nconst sshBaseFlags = (options: SshTargetOptions): string[] => {\n const flags: string[] = [];\n if (options.port !== undefined && options.port !== 22)\n flags.push(\"-p\", String(options.port));\n if (options.identity !== undefined) flags.push(\"-i\", options.identity);\n // Never get stuck on a host-key prompt; treat unknown hosts as a fatal config issue rather than a UX detour.\n flags.push(\"-o\", \"BatchMode=yes\", \"-o\", \"StrictHostKeyChecking=accept-new\");\n for (const flag of options.sshFlags ?? []) flags.push(flag);\n return flags;\n};\n\nconst shellQuote = (value: string): string =>\n `'${value.replace(/'/g, `'\\\\''`)}'`;\n\nconst buildRemoteCmd = (cmd: string, opts: ExecOptions | undefined): string => {\n const env = opts?.env;\n const envPrefix = env\n ? Object.entries(env)\n .map(([k, v]) => `${k}=${shellQuote(v)}`)\n .join(\" \") + \" \"\n : \"\";\n if (opts?.cwd) {\n return `cd ${shellQuote(opts.cwd)} && ${envPrefix}${cmd}`;\n }\n return `${envPrefix}${cmd}`;\n};\n\nexport const sshTarget = (options: SshTargetOptions): Target => {\n const remote = sshTargetString(options);\n const useRsync = options.rsync ?? true;\n\n return {\n description: `ssh ${remote}${options.port && options.port !== 22 ? `:${options.port}` : \"\"}`,\n exec: async (cmd, opts) => {\n const argv = [\"ssh\", ...sshBaseFlags(options)];\n for (const name of options.forwardEnv ?? [])\n argv.push(\"-o\", `SendEnv=${name}`);\n argv.push(remote, buildRemoteCmd(cmd, opts));\n return runSpawn(argv, {\n onLog: opts?.onLog,\n stdin: opts?.stdin,\n timeoutMs: opts?.timeoutMs,\n });\n },\n upload: async (localPath, remotePath, opts) => {\n if (useRsync) {\n const sshCmd = [\"ssh\", ...sshBaseFlags(options)]\n .map((part) => (part.includes(\" \") ? `'${part}'` : part))\n .join(\" \");\n const argv = [\"rsync\", \"-az\", \"-e\", sshCmd];\n if (opts?.deleteOrphans) argv.push(\"--delete\");\n for (const pattern of opts?.exclude ?? [])\n argv.push(\"--exclude\", pattern);\n argv.push(localPath, `${remote}:${remotePath}`);\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `rsync upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n return;\n }\n // scp fallback — no exclude, no delete. We still need -r to copy directories.\n const argv = [\n \"scp\",\n \"-r\",\n ...sshBaseFlags(options),\n localPath,\n `${remote}:${remotePath}`,\n ];\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `scp upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n },\n };\n};\n",
|
|
6
|
+
"/**\n * Shared \"cloud-provider Target\" plumbing used by the\n * provider-specific adapters (`./digitalocean`, `./hetzner`, future\n * `./linode`, `./vultr`, etc.).\n *\n * The provider supplies a small `CloudTargetHooks` bag that knows\n * the provider's:\n *\n * - find-by-name lookup\n * - create call (closure over create params)\n * - fetch-by-id (used to poll for `active`)\n * - destroy-by-id\n * - status + ipv4 + id extraction from the provider's Server shape\n * - readiness predicate (status reached the terminal \"running\" value)\n *\n * `createCloudTarget()` does the universal machinery: provision-or-\n * reuse, poll until ready + IPv4, wait for SSH probe, build\n * `sshTarget` against the IPv4, return the Target wrapped with\n * `{ id, ipv4, destroy() }`.\n *\n * The public adapter (e.g. `digitalOceanTarget`) is a 30-line facade\n * that wires its provider-specific bits and renames `id` → `dropletId`\n * on the way out.\n */\n\nimport type { Target } from \"./targets\";\nimport { sshTarget } from \"./targets\";\n\n/** Provider-specific hooks. Keep these pure of network IO timing — the helper schedules. */\nexport type CloudTargetHooks<Server, Id = number> = {\n /** Find a server by name. Returns undefined if absent. */\n findByName: (name: string) => Promise<Server | undefined>;\n /** Create the server. Closure over provider-specific create params. */\n create: () => Promise<Server>;\n /** Fetch a fresh copy of the server by id. Used to poll. */\n fetch: (id: Id) => Promise<Server>;\n /** Destroy a server by id. 404 should be treated as idempotent success. */\n destroy: (id: Id) => Promise<void>;\n /** True when the server has reached its terminal \"running\" status. */\n isReady: (server: Server) => boolean;\n /** Extract the provider-assigned id (number for DO/Hetzner/Linode, string for Vultr). */\n getId: (server: Server) => Id;\n /** Extract the public IPv4. Returns undefined while one is being assigned. */\n getIpv4: (server: Server) => string | undefined;\n /** Extract the current status as a string (for log lines). */\n getStatus: (server: Server) => string;\n};\n\nexport type CloudTargetOptions = {\n /** Provider's idempotency key (server name). */\n name: string;\n /** Region / location label — used in the \"creating\" log line. */\n region: string;\n\n /** SSH login user. Default `'root'`. */\n user?: string;\n /** SSH identity file. */\n identity?: string;\n /** SSH port. Default 22. */\n port?: number;\n\n /** Default 5 min. */\n provisionTimeoutMs?: number;\n /** Default 2 min. */\n sshReadinessTimeoutMs?: number;\n /** Default 5 s. */\n pollIntervalMs?: number;\n\n /** Called with status updates. */\n onLog?: (line: string) => void;\n /** Override SSH probe — tests skip real TCP IO. */\n probeSsh?: (host: string, port: number) => Promise<boolean>;\n /** Override sleep — tests skip real waits. */\n sleep?: (ms: number) => Promise<void>;\n /** Override clock — tests inject deterministic timestamps. */\n now?: () => number;\n\n /**\n * Short log prefix, e.g. `'[do]'` or `'[hetzner]'`. Threaded through\n * every log line so multi-provider deploys distinguish output.\n */\n logPrefix: string;\n /**\n * Provider's word for the entity in log copy — `'droplet'` for DO,\n * `'server'` for Hetzner. Preserves provider-accurate output.\n */\n entityWord: string;\n /**\n * Build the Target's `description` field. Receives the resolved\n * IPv4 + the wrapped sshTarget description.\n */\n describeTarget: (sshDescription: string) => string;\n};\n\nexport type CloudTargetResult<Id = number> = {\n id: Id;\n ipv4: string;\n description: string;\n exec: Target[\"exec\"];\n upload: Target[\"upload\"];\n close?: Target[\"close\"];\n destroy: () => Promise<void>;\n};\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst defaultProbeSsh = async (\n host: string,\n port: number,\n): Promise<boolean> => {\n const PROBE_TIMEOUT_MS = 2_000;\n return new Promise<boolean>((resolve) => {\n let settled = false;\n const settle = (value: boolean) => {\n if (settled) return;\n settled = true;\n resolve(value);\n };\n const timer = setTimeout(() => settle(false), PROBE_TIMEOUT_MS);\n Bun.connect({\n hostname: host,\n port,\n socket: {\n data: () => {},\n error: () => {\n clearTimeout(timer);\n settle(false);\n },\n open: (socket) => {\n clearTimeout(timer);\n socket.end();\n settle(true);\n },\n },\n }).catch(() => {\n clearTimeout(timer);\n settle(false);\n });\n });\n};\n\n/**\n * The shared provision-or-reuse + wait-for-ready + wait-for-SSH\n * pipeline. Provider-specific adapters wire their `CloudTargetHooks`\n * + their option-shape mapping and return a typed result.\n */\nexport const createCloudTarget = async <Server, Id = number>(\n hooks: CloudTargetHooks<Server, Id>,\n options: CloudTargetOptions,\n): Promise<CloudTargetResult<Id>> => {\n const log = options.onLog ?? (() => {});\n const probeSsh = options.probeSsh ?? defaultProbeSsh;\n const sleep = options.sleep ?? defaultSleep;\n const now = options.now ?? Date.now;\n const pollMs = options.pollIntervalMs ?? 5_000;\n const provisionTimeout = options.provisionTimeoutMs ?? 5 * 60_000;\n const sshTimeout = options.sshReadinessTimeoutMs ?? 2 * 60_000;\n const port = options.port ?? 22;\n const prefix = options.logPrefix;\n const noun = options.entityWord;\n\n const existing = await hooks.findByName(options.name);\n let current: Server;\n if (existing === undefined) {\n log(`${prefix} creating ${noun} \"${options.name}\" in ${options.region}`);\n current = await hooks.create();\n } else {\n log(\n `${prefix} reusing ${noun} \"${options.name}\" (id ${hooks.getId(existing)}, status ${hooks.getStatus(existing)})`,\n );\n current = existing;\n }\n\n // Wait for status=ready AND public IPv4 assigned.\n const provisionStart = now();\n let ipv4 = hooks.getIpv4(current);\n while (!hooks.isReady(current) || ipv4 === undefined) {\n if (now() - provisionStart > provisionTimeout) {\n throw new Error(\n `${prefix} provision timeout after ${provisionTimeout}ms — ${noun} ${hooks.getId(current)} status \"${hooks.getStatus(current)}\", ipv4 ${ipv4 ?? \"(unassigned)\"}`,\n );\n }\n await sleep(pollMs);\n current = await hooks.fetch(hooks.getId(current));\n ipv4 = hooks.getIpv4(current);\n log(\n `${prefix} poll: status=${hooks.getStatus(current)} ipv4=${ipv4 ?? \"(none yet)\"}`,\n );\n }\n log(`${prefix} ${noun} ready at ${ipv4}`);\n\n // Wait for SSH readiness.\n const sshStart = now();\n while (!(await probeSsh(ipv4, port))) {\n if (now() - sshStart > sshTimeout) {\n throw new Error(\n `${prefix} SSH readiness timeout after ${sshTimeout}ms — ${ipv4}:${port} did not accept connections`,\n );\n }\n await sleep(pollMs);\n log(`${prefix} waiting on ssh ${ipv4}:${port}`);\n }\n log(`${prefix} ssh ready at ${ipv4}:${port}`);\n\n const ssh = sshTarget({\n host: ipv4,\n ...(options.user !== undefined ? { user: options.user } : {}),\n ...(options.identity !== undefined ? { identity: options.identity } : {}),\n ...(options.port !== undefined ? { port: options.port } : {}),\n });\n\n const id = hooks.getId(current);\n const resolvedIpv4 = ipv4;\n\n return {\n description: options.describeTarget(ssh.description),\n destroy: () =>\n hooks.destroy(id).then(() => {\n log(`${prefix} destroyed ${noun} ${id}`);\n }),\n exec: ssh.exec,\n id,\n ipv4: resolvedIpv4,\n upload: ssh.upload,\n ...(ssh.close !== undefined ? { close: ssh.close } : {}),\n };\n};\n",
|
|
7
|
+
"/**\n * @absolutejs/deploy/linode — provision-or-reuse Target adapter for\n * Linode (Akamai Cloud) instances. Sibling to digitalOceanTarget +\n * hetznerTarget; same shape, Linode v4 API mappings.\n *\n * Idempotent by label — Linode allows duplicate labels per account\n * but we treat duplicates as drifted state (throw on the second).\n *\n * Narrow LinodeClientLike interface keeps `@linode/api-v4` out as a\n * hard dep. Default client uses `fetch` against `api.linode.com/v4`.\n */\n\nimport type { Target } from \"./targets\";\nimport { createCloudTarget, type CloudTargetHooks } from \"./cloudTarget\";\n\nconst LINODE_API_BASE = \"https://api.linode.com/v4\";\n\nexport type LinodeClientLike = {\n request: <T = unknown>(\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n body?: unknown,\n ) => Promise<T>;\n};\n\n/** A Linode instance, narrowed to what we inspect. */\nexport type LinodeInstance = {\n id: number;\n label: string;\n status:\n | \"running\"\n | \"offline\"\n | \"booting\"\n | \"rebooting\"\n | \"shutting_down\"\n | \"provisioning\"\n | \"deleting\"\n | \"migrating\"\n | \"rebuilding\"\n | \"cloning\"\n | \"restoring\"\n | \"stopped\";\n /** Linode returns IPv4 as a flat string array; public IPs first. */\n ipv4: string[];\n region?: string;\n type?: string;\n tags?: string[];\n};\n\nexport type LinodeTargetOptions = {\n /** Linode Personal Access Token. Required unless `client` is set. */\n token?: string;\n /** Custom client. Overrides token-built default. */\n client?: LinodeClientLike;\n\n // ── Instance shape ──────────────────────────────────────────────\n /** Instance label. Idempotency key. */\n name: string;\n /** Region slug — `'us-east'`, `'us-west'`, `'ap-south'`, etc. */\n region: string;\n /** Type slug — `'g6-nanode-1'`, `'g6-standard-1'`, etc. */\n type: string;\n /** Image slug — e.g. `'linode/ubuntu22.04'`. */\n image: string;\n /**\n * SSH public keys (raw `ssh-rsa AAAA…` / `ssh-ed25519 AAAA…` strings)\n * authorized for root login. At least one required for a usable target.\n */\n sshKeys: ReadonlyArray<string>;\n /** Tags applied to the instance. */\n tags?: ReadonlyArray<string>;\n /** Cloud-init / StackScript user data, base64-encoded by us. */\n userData?: string;\n /**\n * Root password. Linode requires a password at creation. Defaults to\n * a random 32-char string — you should rely on `sshKeys` and never\n * type this. Override only if you have a specific reason.\n */\n rootPass?: string;\n /** Enable private IP. Default false. */\n privateIp?: boolean;\n /** Enable backups. Default false. */\n backupsEnabled?: boolean;\n\n // ── SSH wrap ────────────────────────────────────────────────────\n /** SSH login user. Default `'root'`. */\n user?: string;\n /** SSH identity file. */\n identity?: string;\n /** SSH port. Default 22. */\n port?: number;\n\n // ── Timing ──────────────────────────────────────────────────────\n provisionTimeoutMs?: number;\n sshReadinessTimeoutMs?: number;\n pollIntervalMs?: number;\n\n // ── Observability + injection ───────────────────────────────────\n onLog?: (line: string) => void;\n probeSsh?: (host: string, port: number) => Promise<boolean>;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n};\n\nexport type LinodeTarget = Target & {\n readonly instanceId: number;\n readonly ipv4: string;\n destroy: () => Promise<void>;\n};\n\nexport class LinodeError extends Error {\n readonly status: number;\n readonly body: unknown;\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.name = \"LinodeError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport const createLinodeClient = (\n token: string,\n options: { baseUrl?: string; fetch?: typeof fetch } = {},\n): LinodeClientLike => {\n const base = options.baseUrl ?? LINODE_API_BASE;\n const f = options.fetch ?? fetch;\n return {\n request: async <T>(\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n body?: unknown,\n ): Promise<T> => {\n const init: RequestInit = {\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n method,\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const response = await f(`${base}${path}`, init);\n if (response.status === 204) return undefined as T;\n const text = await response.text();\n const parsed = text.length > 0 ? JSON.parse(text) : undefined;\n if (!response.ok) {\n throw new LinodeError(\n `Linode API ${method} ${path} failed: ${response.status} ${response.statusText}`,\n response.status,\n parsed,\n );\n }\n return parsed as T;\n },\n };\n};\n\nconst resolveClient = (\n options: Pick<LinodeTargetOptions, \"client\" | \"token\">,\n): LinodeClientLike => {\n if (options.client !== undefined) return options.client;\n if (options.token !== undefined && options.token.length > 0) {\n return createLinodeClient(options.token);\n }\n throw new Error(\n \"[deploy/linode] either `token` or `client` must be provided\",\n );\n};\n\nconst publicIpv4 = (instance: LinodeInstance): string | undefined => {\n // Linode's first IPv4 entry is the primary public address.\n for (const ip of instance.ipv4) {\n // Skip private RFC1918 + link-local. Crude but good enough.\n if (\n !ip.startsWith(\"10.\") &&\n !ip.startsWith(\"192.168.\") &&\n !ip.startsWith(\"172.\") &&\n !ip.startsWith(\"169.254.\")\n ) {\n return ip;\n }\n }\n return undefined;\n};\n\nconst randomPassword = (length: number): string => {\n const chars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*\";\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n let out = \"\";\n for (const byte of bytes) out += chars[byte % chars.length];\n return out;\n};\n\n/** Find an instance by label. Throws on ambiguous duplicates. */\nexport const findLinodeInstance = async (\n client: LinodeClientLike,\n name: string,\n): Promise<LinodeInstance | undefined> => {\n const body = await client.request<{ data: LinodeInstance[] }>(\n \"GET\",\n \"/linode/instances?page_size=500\",\n );\n const matches = body.data.filter((instance) => instance.label === name);\n if (matches.length === 0) return undefined;\n if (matches.length > 1) {\n throw new Error(\n `[deploy/linode] multiple instances labeled \"${name}\" (${matches\n .map((instance) => instance.id)\n .join(\", \")}). Resolve manually before adopting.`,\n );\n }\n return matches[0];\n};\n\nexport const listLinodeInstances = async (options: {\n token?: string;\n client?: LinodeClientLike;\n tag?: string;\n}): Promise<LinodeInstance[]> => {\n const client = resolveClient(options);\n const path =\n options.tag !== undefined\n ? `/linode/instances?tag=${encodeURIComponent(options.tag)}&page_size=500`\n : \"/linode/instances?page_size=500\";\n const body = await client.request<{ data: LinodeInstance[] }>(\"GET\", path);\n return body.data;\n};\n\nexport const destroyLinodeInstance = async (options: {\n token?: string;\n client?: LinodeClientLike;\n id: number;\n}): Promise<void> => {\n const client = resolveClient(options);\n try {\n await client.request(\"DELETE\", `/linode/instances/${options.id}`);\n } catch (error) {\n if (error instanceof LinodeError && error.status === 404) return;\n throw error;\n }\n};\n\nexport const linodeTarget = async (\n options: LinodeTargetOptions,\n): Promise<LinodeTarget> => {\n const client = resolveClient(options);\n const rootPass = options.rootPass ?? randomPassword(32);\n\n const hooks: CloudTargetHooks<LinodeInstance> = {\n create: async () => {\n const created = await client.request<LinodeInstance>(\n \"POST\",\n \"/linode/instances\",\n {\n authorized_keys: [...options.sshKeys],\n image: options.image,\n label: options.name,\n region: options.region,\n root_pass: rootPass,\n type: options.type,\n ...(options.tags !== undefined ? { tags: [...options.tags] } : {}),\n ...(options.userData !== undefined\n ? { stackscript_data: { user_data: options.userData } }\n : {}),\n ...(options.privateIp === true ? { private_ip: true } : {}),\n ...(options.backupsEnabled === true ? { backups_enabled: true } : {}),\n },\n );\n return created;\n },\n destroy: (id) => destroyLinodeInstance({ client, id }),\n fetch: (id) =>\n client.request<LinodeInstance>(\"GET\", `/linode/instances/${id}`),\n findByName: (name) => findLinodeInstance(client, name),\n getId: (instance) => instance.id,\n getIpv4: publicIpv4,\n getStatus: (instance) => instance.status,\n isReady: (instance) => instance.status === \"running\",\n };\n\n const result = await createCloudTarget(hooks, {\n describeTarget: (sshDescription) =>\n `linode \"${options.name}\" (${sshDescription})`,\n entityWord: \"instance\",\n logPrefix: \"[linode]\",\n name: options.name,\n region: options.region,\n ...(options.user !== undefined ? { user: options.user } : {}),\n ...(options.identity !== undefined ? { identity: options.identity } : {}),\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.provisionTimeoutMs !== undefined\n ? { provisionTimeoutMs: options.provisionTimeoutMs }\n : {}),\n ...(options.sshReadinessTimeoutMs !== undefined\n ? { sshReadinessTimeoutMs: options.sshReadinessTimeoutMs }\n : {}),\n ...(options.pollIntervalMs !== undefined\n ? { pollIntervalMs: options.pollIntervalMs }\n : {}),\n ...(options.onLog !== undefined ? { onLog: options.onLog } : {}),\n ...(options.probeSsh !== undefined ? { probeSsh: options.probeSsh } : {}),\n ...(options.sleep !== undefined ? { sleep: options.sleep } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n });\n\n return {\n description: result.description,\n destroy: result.destroy,\n exec: result.exec,\n instanceId: result.id,\n ipv4: result.ipv4,\n upload: result.upload,\n ...(result.close !== undefined ? { close: result.close } : {}),\n };\n};\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "B67F18AC4DA3766D64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -199,7 +199,13 @@ var sshTarget = (options) => {
|
|
|
199
199
|
}
|
|
200
200
|
return;
|
|
201
201
|
}
|
|
202
|
-
const argv = [
|
|
202
|
+
const argv = [
|
|
203
|
+
"scp",
|
|
204
|
+
"-r",
|
|
205
|
+
...sshBaseFlags(options),
|
|
206
|
+
localPath,
|
|
207
|
+
`${remote}:${remotePath}`
|
|
208
|
+
];
|
|
203
209
|
const result = await runSpawn(argv, { timeoutMs: 600000 });
|
|
204
210
|
if (result.exitCode !== 0) {
|
|
205
211
|
throw new Error(`scp upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
|
|
@@ -558,7 +564,11 @@ var createLinodeInfrastructureProvider = (options) => {
|
|
|
558
564
|
root_pass: rootPassword(),
|
|
559
565
|
tags: [tag],
|
|
560
566
|
type: region.type,
|
|
561
|
-
...input.userData ?? region.userData ? {
|
|
567
|
+
...input.userData ?? region.userData ? {
|
|
568
|
+
stackscript_data: {
|
|
569
|
+
user_data: input.userData ?? region.userData
|
|
570
|
+
}
|
|
571
|
+
} : {}
|
|
562
572
|
});
|
|
563
573
|
return normalize(instance);
|
|
564
574
|
},
|
|
@@ -569,5 +579,5 @@ export {
|
|
|
569
579
|
createLinodeInfrastructureProvider
|
|
570
580
|
};
|
|
571
581
|
|
|
572
|
-
//# debugId=
|
|
582
|
+
//# debugId=2505939C4EB7F37564756E2164756E21
|
|
573
583
|
//# sourceMappingURL=linodeInfrastructure.js.map
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/targets.ts", "../src/cloudTarget.ts", "../src/linode.ts", "../src/infrastructureAdapter.ts", "../src/linodeInfrastructure.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Target interface + bundled adapters (localTarget, sshTarget).\n *\n * A Target is the narrowest abstraction over \"a place I can deploy to\":\n *\n * - `exec(cmd, opts?)` — run a shell command, capture stdout/stderr/exitCode.\n * - `upload(localPath, remotePath, opts?)` — copy a local file or directory\n * to the target. Implementation is free to use whatever is fast (rsync,\n * scp, mv).\n * - `close?()` — optional teardown.\n *\n * Two adapters are bundled:\n *\n * - `localTarget` runs in a temp directory on the local filesystem. Useful\n * for tests and for \"deploy\" workflows that happen on the same host.\n * - `sshTarget` shells out to the system `ssh` and `rsync` binaries. No\n * `ssh2` npm dependency — the controller machine just needs `ssh` and\n * (optionally) `rsync` in PATH, which is universal on Mac/Linux/WSL.\n *\n * Provider-specific targets (Cloudflare Workers HTTP API, Fly Machines API,\n * AWS Fargate) don't fit \"exec + upload\" and ship as siblings later.\n */\n\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type ExecOptions = {\n\t/** Working directory on the target. Default: target's root. */\n\tcwd?: string;\n\t/** Env vars to set for this command (merged onto target.env). */\n\tenv?: Record<string, string>;\n\t/** Hard kill after this many ms. Default 600_000 (10 min). 0 disables. */\n\ttimeoutMs?: number;\n\t/** Pipe stdout/stderr through here as it streams (lines, newline-stripped). */\n\tonLog?: (line: string, stream: 'stdout' | 'stderr') => void;\n\t/** Stdin payload — a string is written verbatim. */\n\tstdin?: string;\n};\n\nexport type ExecResult = {\n\tstdout: string;\n\tstderr: string;\n\texitCode: number;\n};\n\nexport type UploadOptions = {\n\t/** Exclude paths matching these globs from a directory upload. */\n\texclude?: string[];\n\t/** When uploading a directory, delete remote files not present locally. */\n\tdeleteOrphans?: boolean;\n};\n\nexport type Target = {\n\t/** Human-readable description (e.g. \"ssh root@droplet-1.example.com\"). */\n\treadonly description: string;\n\texec: (cmd: string, opts?: ExecOptions) => Promise<ExecResult>;\n\tupload: (localPath: string, remotePath: string, opts?: UploadOptions) => Promise<void>;\n\tclose?: () => Promise<void>;\n};\n\n// -----------------------------------------------------------------------------\n// localTarget\n// -----------------------------------------------------------------------------\n\nexport type LocalTargetOptions = {\n\t/** Root directory the target operates in. Created if missing. */\n\troot: string;\n\t/** Env merged into every exec. */\n\tenv?: Record<string, string>;\n};\n\nconst decodeChunks = async (\n\treader: ReadableStream<Uint8Array> | null,\n\tonLine: ((line: string) => void) | undefined,\n): Promise<string> => {\n\tif (!reader) return '';\n\tconst decoder = new TextDecoder();\n\tlet buffer = '';\n\tlet collected = '';\n\tconst stream = reader.getReader();\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await stream.read();\n\t\t\tif (done) break;\n\t\t\tconst chunk = decoder.decode(value, { stream: true });\n\t\t\tcollected += chunk;\n\t\t\tif (!onLine) continue;\n\t\t\tbuffer += chunk;\n\t\t\tlet newline = buffer.indexOf('\\n');\n\t\t\twhile (newline !== -1) {\n\t\t\t\tconst line = buffer.slice(0, newline).replace(/\\r$/, '');\n\t\t\t\tif (line.length > 0) onLine(line);\n\t\t\t\tbuffer = buffer.slice(newline + 1);\n\t\t\t\tnewline = buffer.indexOf('\\n');\n\t\t\t}\n\t\t}\n\t\tconst tail = decoder.decode();\n\t\tcollected += tail;\n\t\tif (onLine && (buffer + tail).length > 0) onLine((buffer + tail).replace(/\\r$/, ''));\n\t} finally {\n\t\tstream.releaseLock();\n\t}\n\treturn collected;\n};\n\nconst runSpawn = async (\n\targv: string[],\n\toptions: {\n\t\tcwd?: string;\n\t\tenv?: Record<string, string>;\n\t\ttimeoutMs?: number;\n\t\tonLog?: ExecOptions['onLog'];\n\t\tstdin?: string;\n\t},\n): Promise<ExecResult> => {\n\tconst proc = Bun.spawn(argv, {\n\t\tcwd: options.cwd,\n\t\tenv: options.env,\n\t\tstderr: 'pipe',\n\t\tstdin: options.stdin === undefined ? 'ignore' : 'pipe',\n\t\tstdout: 'pipe',\n\t});\n\n\tif (options.stdin !== undefined && proc.stdin) {\n\t\t// Bun.spawn returns a FileSink for piped stdin — `write` + `end`, not a\n\t\t// WritableStream. (We use a permissive cast because @types/bun's\n\t\t// Subprocess.stdin discriminant flips based on the stdin generic.)\n\t\tconst sink = proc.stdin as unknown as {\n\t\t\twrite: (chunk: string | Uint8Array) => number | Promise<number>;\n\t\t\tend: () => void | Promise<void>;\n\t\t};\n\t\tconst wrote = sink.write(options.stdin);\n\t\tif (wrote && typeof (wrote as Promise<number>).then === 'function') {\n\t\t\tawait wrote;\n\t\t}\n\t\tconst ended = sink.end();\n\t\tif (ended && typeof (ended as Promise<void>).then === 'function') {\n\t\t\tawait ended;\n\t\t}\n\t}\n\n\tconst timeout = options.timeoutMs ?? 600_000;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tif (timeout > 0) {\n\t\ttimer = setTimeout(() => {\n\t\t\ttry { proc.kill(); } catch { /* already gone */ }\n\t\t}, timeout);\n\t}\n\n\tconst stdoutPromise = decodeChunks(\n\t\tproc.stdout as unknown as ReadableStream<Uint8Array>,\n\t\toptions.onLog ? (line) => options.onLog!(line, 'stdout') : undefined,\n\t);\n\tconst stderrPromise = decodeChunks(\n\t\tproc.stderr as unknown as ReadableStream<Uint8Array>,\n\t\toptions.onLog ? (line) => options.onLog!(line, 'stderr') : undefined,\n\t);\n\n\tconst [stdout, stderr, exitCode] = await Promise.all([\n\t\tstdoutPromise,\n\t\tstderrPromise,\n\t\tproc.exited,\n\t]);\n\tif (timer) clearTimeout(timer);\n\n\treturn { exitCode: exitCode ?? -1, stderr, stdout };\n};\n\nexport const localTarget = (options: LocalTargetOptions): Target => {\n\tconst baseEnv = { ...options.env };\n\tconst ensureRoot = async () => { await mkdir(options.root, { recursive: true }); };\n\n\treturn {\n\t\tdescription: `local ${options.root}`,\n\t\texec: async (cmd, opts) => {\n\t\t\tawait ensureRoot();\n\t\t\treturn runSpawn(['sh', '-c', cmd], {\n\t\t\t\tcwd: opts?.cwd ?? options.root,\n\t\t\t\tenv: { ...process.env, ...baseEnv, ...(opts?.env ?? {}) } as Record<string, string>,\n\t\t\t\tonLog: opts?.onLog,\n\t\t\t\tstdin: opts?.stdin,\n\t\t\t\ttimeoutMs: opts?.timeoutMs,\n\t\t\t});\n\t\t},\n\t\tupload: async (localPath, remotePath, opts) => {\n\t\t\tawait ensureRoot();\n\t\t\tconst dest = remotePath.startsWith('/') ? remotePath : join(options.root, remotePath);\n\t\t\tconst argv = ['rsync', '-a'];\n\t\t\tif (opts?.deleteOrphans) argv.push('--delete');\n\t\t\tfor (const pattern of opts?.exclude ?? []) argv.push('--exclude', pattern);\n\t\t\t// rsync semantics: a trailing slash on the source copies *contents*; without it the dir itself is nested.\n\t\t\targv.push(localPath, dest);\n\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tthrow new Error(`local upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t}\n\t\t},\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// sshTarget\n// -----------------------------------------------------------------------------\n\nexport type SshTargetOptions = {\n\t/** Hostname or IP of the remote. */\n\thost: string;\n\t/** Login user. Default `root`. */\n\tuser?: string;\n\t/** SSH port. Default 22. */\n\tport?: number;\n\t/** Path to SSH identity file. Default: ssh's own search. */\n\tidentity?: string;\n\t/** Extra flags appended to every `ssh` invocation. */\n\tsshFlags?: string[];\n\t/**\n\t * Use rsync for `upload`. Default true. When false, falls back to `scp`\n\t * which is universal but doesn't support delete / exclude.\n\t */\n\trsync?: boolean;\n\t/**\n\t * Env vars to forward via `ssh -o SendEnv=...`. Most remote sshd configs\n\t * accept only `LANG` and `LC_*` by default; for app env vars use the\n\t * step `env` option instead, which prepends `KEY=value` to the command.\n\t */\n\tforwardEnv?: string[];\n};\n\nconst sshTargetString = (options: SshTargetOptions): string => {\n\tconst user = options.user ?? 'root';\n\treturn `${user}@${options.host}`;\n};\n\nconst sshBaseFlags = (options: SshTargetOptions): string[] => {\n\tconst flags: string[] = [];\n\tif (options.port !== undefined && options.port !== 22) flags.push('-p', String(options.port));\n\tif (options.identity !== undefined) flags.push('-i', options.identity);\n\t// Never get stuck on a host-key prompt; treat unknown hosts as a fatal config issue rather than a UX detour.\n\tflags.push('-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=accept-new');\n\tfor (const flag of options.sshFlags ?? []) flags.push(flag);\n\treturn flags;\n};\n\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, `'\\\\''`)}'`;\n\nconst buildRemoteCmd = (cmd: string, opts: ExecOptions | undefined): string => {\n\tconst env = opts?.env;\n\tconst envPrefix = env\n\t\t? Object.entries(env).map(([k, v]) => `${k}=${shellQuote(v)}`).join(' ') + ' '\n\t\t: '';\n\tif (opts?.cwd) {\n\t\treturn `cd ${shellQuote(opts.cwd)} && ${envPrefix}${cmd}`;\n\t}\n\treturn `${envPrefix}${cmd}`;\n};\n\nexport const sshTarget = (options: SshTargetOptions): Target => {\n\tconst remote = sshTargetString(options);\n\tconst useRsync = options.rsync ?? true;\n\n\treturn {\n\t\tdescription: `ssh ${remote}${options.port && options.port !== 22 ? `:${options.port}` : ''}`,\n\t\texec: async (cmd, opts) => {\n\t\t\tconst argv = ['ssh', ...sshBaseFlags(options)];\n\t\t\tfor (const name of options.forwardEnv ?? []) argv.push('-o', `SendEnv=${name}`);\n\t\t\targv.push(remote, buildRemoteCmd(cmd, opts));\n\t\t\treturn runSpawn(argv, {\n\t\t\t\tonLog: opts?.onLog,\n\t\t\t\tstdin: opts?.stdin,\n\t\t\t\ttimeoutMs: opts?.timeoutMs,\n\t\t\t});\n\t\t},\n\t\tupload: async (localPath, remotePath, opts) => {\n\t\t\tif (useRsync) {\n\t\t\t\tconst sshCmd = ['ssh', ...sshBaseFlags(options)].map((part) => part.includes(' ') ? `'${part}'` : part).join(' ');\n\t\t\t\tconst argv = ['rsync', '-az', '-e', sshCmd];\n\t\t\t\tif (opts?.deleteOrphans) argv.push('--delete');\n\t\t\t\tfor (const pattern of opts?.exclude ?? []) argv.push('--exclude', pattern);\n\t\t\t\targv.push(localPath, `${remote}:${remotePath}`);\n\t\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\t\tif (result.exitCode !== 0) {\n\t\t\t\t\tthrow new Error(`rsync upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// scp fallback — no exclude, no delete. We still need -r to copy directories.\n\t\t\tconst argv = ['scp', '-r', ...sshBaseFlags(options), localPath, `${remote}:${remotePath}`];\n\t\t\tconst result = await runSpawn(argv, { timeoutMs: 600_000 });\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tthrow new Error(`scp upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n\t\t\t}\n\t\t},\n\t};\n};\n",
|
|
6
|
-
"/**\n * Shared \"cloud-provider Target\" plumbing used by the\n * provider-specific adapters (`./digitalocean`, `./hetzner`, future\n * `./linode`, `./vultr`, etc.).\n *\n * The provider supplies a small `CloudTargetHooks` bag that knows\n * the provider's:\n *\n * - find-by-name lookup\n * - create call (closure over create params)\n * - fetch-by-id (used to poll for `active`)\n * - destroy-by-id\n * - status + ipv4 + id extraction from the provider's Server shape\n * - readiness predicate (status reached the terminal \"running\" value)\n *\n * `createCloudTarget()` does the universal machinery: provision-or-\n * reuse, poll until ready + IPv4, wait for SSH probe, build\n * `sshTarget` against the IPv4, return the Target wrapped with\n * `{ id, ipv4, destroy() }`.\n *\n * The public adapter (e.g. `digitalOceanTarget`) is a 30-line facade\n * that wires its provider-specific bits and renames `id` → `dropletId`\n * on the way out.\n */\n\nimport type { Target } from
|
|
7
|
-
"/**\n * @absolutejs/deploy/linode — provision-or-reuse Target adapter for\n * Linode (Akamai Cloud) instances. Sibling to digitalOceanTarget +\n * hetznerTarget; same shape, Linode v4 API mappings.\n *\n * Idempotent by label — Linode allows duplicate labels per account\n * but we treat duplicates as drifted state (throw on the second).\n *\n * Narrow LinodeClientLike interface keeps `@linode/api-v4` out as a\n * hard dep. Default client uses `fetch` against `api.linode.com/v4`.\n */\n\nimport type { Target } from './targets';\nimport { createCloudTarget, type CloudTargetHooks } from './cloudTarget';\n\nconst LINODE_API_BASE = 'https://api.linode.com/v4';\n\nexport type LinodeClientLike = {\n\trequest: <T = unknown>(\n\t\tmethod: 'GET' | 'POST' | 'DELETE',\n\t\tpath: string,\n\t\tbody?: unknown\n\t) => Promise<T>;\n};\n\n/** A Linode instance, narrowed to what we inspect. */\nexport type LinodeInstance = {\n\tid: number;\n\tlabel: string;\n\tstatus:\n\t\t| 'running'\n\t\t| 'offline'\n\t\t| 'booting'\n\t\t| 'rebooting'\n\t\t| 'shutting_down'\n\t\t| 'provisioning'\n\t\t| 'deleting'\n\t\t| 'migrating'\n\t\t| 'rebuilding'\n\t\t| 'cloning'\n\t\t| 'restoring'\n\t\t| 'stopped';\n\t/** Linode returns IPv4 as a flat string array; public IPs first. */\n\tipv4: string[];\n\tregion?: string;\n\ttype?: string;\n\ttags?: string[];\n};\n\nexport type LinodeTargetOptions = {\n\t/** Linode Personal Access Token. Required unless `client` is set. */\n\ttoken?: string;\n\t/** Custom client. Overrides token-built default. */\n\tclient?: LinodeClientLike;\n\n\t// ── Instance shape ──────────────────────────────────────────────\n\t/** Instance label. Idempotency key. */\n\tname: string;\n\t/** Region slug — `'us-east'`, `'us-west'`, `'ap-south'`, etc. */\n\tregion: string;\n\t/** Type slug — `'g6-nanode-1'`, `'g6-standard-1'`, etc. */\n\ttype: string;\n\t/** Image slug — e.g. `'linode/ubuntu22.04'`. */\n\timage: string;\n\t/**\n\t * SSH public keys (raw `ssh-rsa AAAA…` / `ssh-ed25519 AAAA…` strings)\n\t * authorized for root login. At least one required for a usable target.\n\t */\n\tsshKeys: ReadonlyArray<string>;\n\t/** Tags applied to the instance. */\n\ttags?: ReadonlyArray<string>;\n\t/** Cloud-init / StackScript user data, base64-encoded by us. */\n\tuserData?: string;\n\t/**\n\t * Root password. Linode requires a password at creation. Defaults to\n\t * a random 32-char string — you should rely on `sshKeys` and never\n\t * type this. Override only if you have a specific reason.\n\t */\n\trootPass?: string;\n\t/** Enable private IP. Default false. */\n\tprivateIp?: boolean;\n\t/** Enable backups. Default false. */\n\tbackupsEnabled?: boolean;\n\n\t// ── SSH wrap ────────────────────────────────────────────────────\n\t/** SSH login user. Default `'root'`. */\n\tuser?: string;\n\t/** SSH identity file. */\n\tidentity?: string;\n\t/** SSH port. Default 22. */\n\tport?: number;\n\n\t// ── Timing ──────────────────────────────────────────────────────\n\tprovisionTimeoutMs?: number;\n\tsshReadinessTimeoutMs?: number;\n\tpollIntervalMs?: number;\n\n\t// ── Observability + injection ───────────────────────────────────\n\tonLog?: (line: string) => void;\n\tprobeSsh?: (host: string, port: number) => Promise<boolean>;\n\tsleep?: (ms: number) => Promise<void>;\n\tnow?: () => number;\n};\n\nexport type LinodeTarget = Target & {\n\treadonly instanceId: number;\n\treadonly ipv4: string;\n\tdestroy: () => Promise<void>;\n};\n\nexport class LinodeError extends Error {\n\treadonly status: number;\n\treadonly body: unknown;\n\tconstructor(message: string, status: number, body: unknown) {\n\t\tsuper(message);\n\t\tthis.name = 'LinodeError';\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport const createLinodeClient = (\n\ttoken: string,\n\toptions: { baseUrl?: string; fetch?: typeof fetch } = {}\n): LinodeClientLike => {\n\tconst base = options.baseUrl ?? LINODE_API_BASE;\n\tconst f = options.fetch ?? fetch;\n\treturn {\n\t\trequest: async <T>(\n\t\t\tmethod: 'GET' | 'POST' | 'DELETE',\n\t\t\tpath: string,\n\t\t\tbody?: unknown\n\t\t): Promise<T> => {\n\t\t\tconst init: RequestInit = {\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${token}`,\n\t\t\t\t\t'content-type': 'application/json'\n\t\t\t\t},\n\t\t\t\tmethod\n\t\t\t};\n\t\t\tif (body !== undefined) init.body = JSON.stringify(body);\n\t\t\tconst response = await f(`${base}${path}`, init);\n\t\t\tif (response.status === 204) return undefined as T;\n\t\t\tconst text = await response.text();\n\t\t\tconst parsed = text.length > 0 ? JSON.parse(text) : undefined;\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new LinodeError(\n\t\t\t\t\t`Linode API ${method} ${path} failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tparsed\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn parsed as T;\n\t\t}\n\t};\n};\n\nconst resolveClient = (\n\toptions: Pick<LinodeTargetOptions, 'client' | 'token'>\n): LinodeClientLike => {\n\tif (options.client !== undefined) return options.client;\n\tif (options.token !== undefined && options.token.length > 0) {\n\t\treturn createLinodeClient(options.token);\n\t}\n\tthrow new Error(\n\t\t'[deploy/linode] either `token` or `client` must be provided'\n\t);\n};\n\nconst publicIpv4 = (instance: LinodeInstance): string | undefined => {\n\t// Linode's first IPv4 entry is the primary public address.\n\tfor (const ip of instance.ipv4) {\n\t\t// Skip private RFC1918 + link-local. Crude but good enough.\n\t\tif (\n\t\t\t!ip.startsWith('10.') &&\n\t\t\t!ip.startsWith('192.168.') &&\n\t\t\t!ip.startsWith('172.') &&\n\t\t\t!ip.startsWith('169.254.')\n\t\t) {\n\t\t\treturn ip;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nconst randomPassword = (length: number): string => {\n\tconst chars =\n\t\t'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';\n\tconst bytes = new Uint8Array(length);\n\tcrypto.getRandomValues(bytes);\n\tlet out = '';\n\tfor (const byte of bytes) out += chars[byte % chars.length];\n\treturn out;\n};\n\n/** Find an instance by label. Throws on ambiguous duplicates. */\nexport const findLinodeInstance = async (\n\tclient: LinodeClientLike,\n\tname: string\n): Promise<LinodeInstance | undefined> => {\n\tconst body = await client.request<{ data: LinodeInstance[] }>(\n\t\t'GET',\n\t\t'/linode/instances?page_size=500'\n\t);\n\tconst matches = body.data.filter((instance) => instance.label === name);\n\tif (matches.length === 0) return undefined;\n\tif (matches.length > 1) {\n\t\tthrow new Error(\n\t\t\t`[deploy/linode] multiple instances labeled \"${name}\" (${matches\n\t\t\t\t.map((instance) => instance.id)\n\t\t\t\t.join(', ')}). Resolve manually before adopting.`\n\t\t);\n\t}\n\treturn matches[0];\n};\n\nexport const listLinodeInstances = async (options: {\n\ttoken?: string;\n\tclient?: LinodeClientLike;\n\ttag?: string;\n}): Promise<LinodeInstance[]> => {\n\tconst client = resolveClient(options);\n\tconst path =\n\t\toptions.tag !== undefined\n\t\t\t? `/linode/instances?tag=${encodeURIComponent(options.tag)}&page_size=500`\n\t\t\t: '/linode/instances?page_size=500';\n\tconst body = await client.request<{ data: LinodeInstance[] }>('GET', path);\n\treturn body.data;\n};\n\nexport const destroyLinodeInstance = async (options: {\n\ttoken?: string;\n\tclient?: LinodeClientLike;\n\tid: number;\n}): Promise<void> => {\n\tconst client = resolveClient(options);\n\ttry {\n\t\tawait client.request('DELETE', `/linode/instances/${options.id}`);\n\t} catch (error) {\n\t\tif (error instanceof LinodeError && error.status === 404) return;\n\t\tthrow error;\n\t}\n};\n\nexport const linodeTarget = async (\n\toptions: LinodeTargetOptions\n): Promise<LinodeTarget> => {\n\tconst client = resolveClient(options);\n\tconst rootPass = options.rootPass ?? randomPassword(32);\n\n\tconst hooks: CloudTargetHooks<LinodeInstance> = {\n\t\tcreate: async () => {\n\t\t\tconst created = await client.request<LinodeInstance>(\n\t\t\t\t'POST',\n\t\t\t\t'/linode/instances',\n\t\t\t\t{\n\t\t\t\t\tauthorized_keys: [...options.sshKeys],\n\t\t\t\t\timage: options.image,\n\t\t\t\t\tlabel: options.name,\n\t\t\t\t\tregion: options.region,\n\t\t\t\t\troot_pass: rootPass,\n\t\t\t\t\ttype: options.type,\n\t\t\t\t\t...(options.tags !== undefined ? { tags: [...options.tags] } : {}),\n\t\t\t\t\t...(options.userData !== undefined\n\t\t\t\t\t\t? { stackscript_data: { user_data: options.userData } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(options.privateIp === true ? { private_ip: true } : {}),\n\t\t\t\t\t...(options.backupsEnabled === true ? { backups_enabled: true } : {})\n\t\t\t\t}\n\t\t\t);\n\t\t\treturn created;\n\t\t},\n\t\tdestroy: (id) => destroyLinodeInstance({ client, id }),\n\t\tfetch: (id) => client.request<LinodeInstance>('GET', `/linode/instances/${id}`),\n\t\tfindByName: (name) => findLinodeInstance(client, name),\n\t\tgetId: (instance) => instance.id,\n\t\tgetIpv4: publicIpv4,\n\t\tgetStatus: (instance) => instance.status,\n\t\tisReady: (instance) => instance.status === 'running'\n\t};\n\n\tconst result = await createCloudTarget(hooks, {\n\t\tdescribeTarget: (sshDescription) =>\n\t\t\t`linode \"${options.name}\" (${sshDescription})`,\n\t\tentityWord: 'instance',\n\t\tlogPrefix: '[linode]',\n\t\tname: options.name,\n\t\tregion: options.region,\n\t\t...(options.user !== undefined ? { user: options.user } : {}),\n\t\t...(options.identity !== undefined ? { identity: options.identity } : {}),\n\t\t...(options.port !== undefined ? { port: options.port } : {}),\n\t\t...(options.provisionTimeoutMs !== undefined\n\t\t\t? { provisionTimeoutMs: options.provisionTimeoutMs }\n\t\t\t: {}),\n\t\t...(options.sshReadinessTimeoutMs !== undefined\n\t\t\t? { sshReadinessTimeoutMs: options.sshReadinessTimeoutMs }\n\t\t\t: {}),\n\t\t...(options.pollIntervalMs !== undefined\n\t\t\t? { pollIntervalMs: options.pollIntervalMs }\n\t\t\t: {}),\n\t\t...(options.onLog !== undefined ? { onLog: options.onLog } : {}),\n\t\t...(options.probeSsh !== undefined ? { probeSsh: options.probeSsh } : {}),\n\t\t...(options.sleep !== undefined ? { sleep: options.sleep } : {}),\n\t\t...(options.now !== undefined ? { now: options.now } : {})\n\t});\n\n\treturn {\n\t\tdescription: result.description,\n\t\tdestroy: result.destroy,\n\t\texec: result.exec,\n\t\tinstanceId: result.id,\n\t\tipv4: result.ipv4,\n\t\tupload: result.upload,\n\t\t...(result.close !== undefined ? { close: result.close } : {})\n\t};\n};\n",
|
|
8
|
-
"import type { InfrastructureNode } from \"./infrastructure\";\n\nexport type InfrastructureAgentOptions = {\n audience?: string;\n port?: number;\n preferPrivateNetwork?: boolean;\n protocol?: \"http\" | \"https\";\n};\n\nexport const infrastructureAgent = (\n options: InfrastructureAgentOptions | undefined,\n addresses: Pick<InfrastructureNode, \"privateIpv4\" | \"publicIpv4\">,\n) => {\n if (!options) return undefined;\n const host = options.preferPrivateNetwork\n ? (addresses.privateIpv4 ?? addresses.publicIpv4)\n : (addresses.publicIpv4 ?? addresses.privateIpv4);\n if (!host) return undefined;\n\n return {\n url: `${options.protocol ?? \"http\"}://${host}:${options.port ?? 8081}/`,\n ...(options.audience ? { audience: options.audience } : {}),\n };\n};\n\nexport const leastPopulatedRegion = <Region extends { region: string }>(\n regions: readonly Region[],\n observed: readonly string[],\n requested?: string,\n) => {\n const eligible = requested\n ? regions.filter((region) => region.region === requested)\n : [...regions];\n if (eligible.length === 0) return undefined;\n const counts = new Map(eligible.map((region) => [region.region, 0]));\n for (const region of observed) {\n if (counts.has(region)) counts.set(region, (counts.get(region) ?? 0) + 1);\n }\n const selected = [...counts].sort(\n (left, right)
|
|
9
|
-
"import {\n createLinodeClient,\n destroyLinodeInstance,\n findLinodeInstance,\n listLinodeInstances,\n type LinodeClientLike,\n type LinodeInstance,\n} from \"./linode\";\nimport type {\n InfrastructureNode,\n InfrastructureNodeState,\n InfrastructureProvider,\n} from \"./infrastructure\";\nimport {\n infrastructureAgent,\n leastPopulatedRegion,\n type InfrastructureAgentOptions,\n} from \"./infrastructureAdapter\";\n\nexport type LinodeFleetRegion = {\n image: string;\n region: string;\n sshKeys: ReadonlyArray<string>;\n type: string;\n userData?: string;\n};\n\nexport type LinodeInfrastructureProviderOptions = {\n agent?: InfrastructureAgentOptions;\n client?: LinodeClientLike;\n regions: readonly LinodeFleetRegion[];\n tag?: string;\n token?: string;\n};\n\nconst isPrivate = (ip: string) =>\n ip.startsWith(\"10.\") ||\n ip.startsWith(\"192.168.\") ||\n ip.startsWith(\"172.\") ||\n ip.startsWith(\"169.254.\");\n\nconst stateFor = (status: LinodeInstance[\"status\"]): InfrastructureNodeState => {\n if (status === \"running\") return \"ready\";\n if (\n [\n \"booting\",\n \"rebooting\",\n \"provisioning\",\n \"migrating\",\n \"rebuilding\",\n \"cloning\",\n \"restoring\",\n ].includes(status)\n )\n return \"pending\";\n\n return \"terminated\";\n};\n\nconst parseNodeId = (id: string) => {\n const match = /^linode:([1-9][0-9]*)$/.exec(id);\n if (!match?.[1])\n throw new Error(\"[deploy/linode] invalid infrastructure node id\");\n\n return Number(match[1]);\n};\n\nconst rootPassword = () => {\n const bytes = crypto.getRandomValues(new Uint8Array(24));\n\n return Buffer.from(bytes).toString(\"base64url\");\n};\n\nexport const createLinodeInfrastructureProvider = (\n options: LinodeInfrastructureProviderOptions,\n): InfrastructureProvider => {\n if (options.regions.length === 0)\n throw new Error(\"[deploy/linode] at least one fleet region is required\");\n const client =\n options.client
|
|
5
|
+
"/**\n * Target interface + bundled adapters (localTarget, sshTarget).\n *\n * A Target is the narrowest abstraction over \"a place I can deploy to\":\n *\n * - `exec(cmd, opts?)` — run a shell command, capture stdout/stderr/exitCode.\n * - `upload(localPath, remotePath, opts?)` — copy a local file or directory\n * to the target. Implementation is free to use whatever is fast (rsync,\n * scp, mv).\n * - `close?()` — optional teardown.\n *\n * Two adapters are bundled:\n *\n * - `localTarget` runs in a temp directory on the local filesystem. Useful\n * for tests and for \"deploy\" workflows that happen on the same host.\n * - `sshTarget` shells out to the system `ssh` and `rsync` binaries. No\n * `ssh2` npm dependency — the controller machine just needs `ssh` and\n * (optionally) `rsync` in PATH, which is universal on Mac/Linux/WSL.\n *\n * Provider-specific targets (Cloudflare Workers HTTP API, Fly Machines API,\n * AWS Fargate) don't fit \"exec + upload\" and ship as siblings later.\n */\n\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type ExecOptions = {\n /** Working directory on the target. Default: target's root. */\n cwd?: string;\n /** Env vars to set for this command (merged onto target.env). */\n env?: Record<string, string>;\n /** Hard kill after this many ms. Default 600_000 (10 min). 0 disables. */\n timeoutMs?: number;\n /** Pipe stdout/stderr through here as it streams (lines, newline-stripped). */\n onLog?: (line: string, stream: \"stdout\" | \"stderr\") => void;\n /** Stdin payload — a string is written verbatim. */\n stdin?: string;\n};\n\nexport type ExecResult = {\n stdout: string;\n stderr: string;\n exitCode: number;\n};\n\nexport type UploadOptions = {\n /** Exclude paths matching these globs from a directory upload. */\n exclude?: string[];\n /** When uploading a directory, delete remote files not present locally. */\n deleteOrphans?: boolean;\n};\n\nexport type Target = {\n /** Human-readable description (e.g. \"ssh root@droplet-1.example.com\"). */\n readonly description: string;\n exec: (cmd: string, opts?: ExecOptions) => Promise<ExecResult>;\n upload: (\n localPath: string,\n remotePath: string,\n opts?: UploadOptions,\n ) => Promise<void>;\n close?: () => Promise<void>;\n};\n\n// -----------------------------------------------------------------------------\n// localTarget\n// -----------------------------------------------------------------------------\n\nexport type LocalTargetOptions = {\n /** Root directory the target operates in. Created if missing. */\n root: string;\n /** Env merged into every exec. */\n env?: Record<string, string>;\n};\n\nconst decodeChunks = async (\n reader: ReadableStream<Uint8Array> | null,\n onLine: ((line: string) => void) | undefined,\n): Promise<string> => {\n if (!reader) return \"\";\n const decoder = new TextDecoder();\n let buffer = \"\";\n let collected = \"\";\n const stream = reader.getReader();\n try {\n while (true) {\n const { done, value } = await stream.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n collected += chunk;\n if (!onLine) continue;\n buffer += chunk;\n let newline = buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = buffer.slice(0, newline).replace(/\\r$/, \"\");\n if (line.length > 0) onLine(line);\n buffer = buffer.slice(newline + 1);\n newline = buffer.indexOf(\"\\n\");\n }\n }\n const tail = decoder.decode();\n collected += tail;\n if (onLine && (buffer + tail).length > 0)\n onLine((buffer + tail).replace(/\\r$/, \"\"));\n } finally {\n stream.releaseLock();\n }\n return collected;\n};\n\nconst runSpawn = async (\n argv: string[],\n options: {\n cwd?: string;\n env?: Record<string, string>;\n timeoutMs?: number;\n onLog?: ExecOptions[\"onLog\"];\n stdin?: string;\n },\n): Promise<ExecResult> => {\n const proc = Bun.spawn(argv, {\n cwd: options.cwd,\n env: options.env,\n stderr: \"pipe\",\n stdin: options.stdin === undefined ? \"ignore\" : \"pipe\",\n stdout: \"pipe\",\n });\n\n if (options.stdin !== undefined && proc.stdin) {\n // Bun.spawn returns a FileSink for piped stdin — `write` + `end`, not a\n // WritableStream. (We use a permissive cast because @types/bun's\n // Subprocess.stdin discriminant flips based on the stdin generic.)\n const sink = proc.stdin as unknown as {\n write: (chunk: string | Uint8Array) => number | Promise<number>;\n end: () => void | Promise<void>;\n };\n const wrote = sink.write(options.stdin);\n if (wrote && typeof (wrote as Promise<number>).then === \"function\") {\n await wrote;\n }\n const ended = sink.end();\n if (ended && typeof (ended as Promise<void>).then === \"function\") {\n await ended;\n }\n }\n\n const timeout = options.timeoutMs ?? 600_000;\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (timeout > 0) {\n timer = setTimeout(() => {\n try {\n proc.kill();\n } catch {\n /* already gone */\n }\n }, timeout);\n }\n\n const stdoutPromise = decodeChunks(\n proc.stdout as unknown as ReadableStream<Uint8Array>,\n options.onLog ? (line) => options.onLog!(line, \"stdout\") : undefined,\n );\n const stderrPromise = decodeChunks(\n proc.stderr as unknown as ReadableStream<Uint8Array>,\n options.onLog ? (line) => options.onLog!(line, \"stderr\") : undefined,\n );\n\n const [stdout, stderr, exitCode] = await Promise.all([\n stdoutPromise,\n stderrPromise,\n proc.exited,\n ]);\n if (timer) clearTimeout(timer);\n\n return { exitCode: exitCode ?? -1, stderr, stdout };\n};\n\nexport const localTarget = (options: LocalTargetOptions): Target => {\n const baseEnv = { ...options.env };\n const ensureRoot = async () => {\n await mkdir(options.root, { recursive: true });\n };\n\n return {\n description: `local ${options.root}`,\n exec: async (cmd, opts) => {\n await ensureRoot();\n return runSpawn([\"sh\", \"-c\", cmd], {\n cwd: opts?.cwd ?? options.root,\n env: { ...process.env, ...baseEnv, ...(opts?.env ?? {}) } as Record<\n string,\n string\n >,\n onLog: opts?.onLog,\n stdin: opts?.stdin,\n timeoutMs: opts?.timeoutMs,\n });\n },\n upload: async (localPath, remotePath, opts) => {\n await ensureRoot();\n const dest = remotePath.startsWith(\"/\")\n ? remotePath\n : join(options.root, remotePath);\n const argv = [\"rsync\", \"-a\"];\n if (opts?.deleteOrphans) argv.push(\"--delete\");\n for (const pattern of opts?.exclude ?? [])\n argv.push(\"--exclude\", pattern);\n // rsync semantics: a trailing slash on the source copies *contents*; without it the dir itself is nested.\n argv.push(localPath, dest);\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `local upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n },\n };\n};\n\n// -----------------------------------------------------------------------------\n// sshTarget\n// -----------------------------------------------------------------------------\n\nexport type SshTargetOptions = {\n /** Hostname or IP of the remote. */\n host: string;\n /** Login user. Default `root`. */\n user?: string;\n /** SSH port. Default 22. */\n port?: number;\n /** Path to SSH identity file. Default: ssh's own search. */\n identity?: string;\n /** Extra flags appended to every `ssh` invocation. */\n sshFlags?: string[];\n /**\n * Use rsync for `upload`. Default true. When false, falls back to `scp`\n * which is universal but doesn't support delete / exclude.\n */\n rsync?: boolean;\n /**\n * Env vars to forward via `ssh -o SendEnv=...`. Most remote sshd configs\n * accept only `LANG` and `LC_*` by default; for app env vars use the\n * step `env` option instead, which prepends `KEY=value` to the command.\n */\n forwardEnv?: string[];\n};\n\nconst sshTargetString = (options: SshTargetOptions): string => {\n const user = options.user ?? \"root\";\n return `${user}@${options.host}`;\n};\n\nconst sshBaseFlags = (options: SshTargetOptions): string[] => {\n const flags: string[] = [];\n if (options.port !== undefined && options.port !== 22)\n flags.push(\"-p\", String(options.port));\n if (options.identity !== undefined) flags.push(\"-i\", options.identity);\n // Never get stuck on a host-key prompt; treat unknown hosts as a fatal config issue rather than a UX detour.\n flags.push(\"-o\", \"BatchMode=yes\", \"-o\", \"StrictHostKeyChecking=accept-new\");\n for (const flag of options.sshFlags ?? []) flags.push(flag);\n return flags;\n};\n\nconst shellQuote = (value: string): string =>\n `'${value.replace(/'/g, `'\\\\''`)}'`;\n\nconst buildRemoteCmd = (cmd: string, opts: ExecOptions | undefined): string => {\n const env = opts?.env;\n const envPrefix = env\n ? Object.entries(env)\n .map(([k, v]) => `${k}=${shellQuote(v)}`)\n .join(\" \") + \" \"\n : \"\";\n if (opts?.cwd) {\n return `cd ${shellQuote(opts.cwd)} && ${envPrefix}${cmd}`;\n }\n return `${envPrefix}${cmd}`;\n};\n\nexport const sshTarget = (options: SshTargetOptions): Target => {\n const remote = sshTargetString(options);\n const useRsync = options.rsync ?? true;\n\n return {\n description: `ssh ${remote}${options.port && options.port !== 22 ? `:${options.port}` : \"\"}`,\n exec: async (cmd, opts) => {\n const argv = [\"ssh\", ...sshBaseFlags(options)];\n for (const name of options.forwardEnv ?? [])\n argv.push(\"-o\", `SendEnv=${name}`);\n argv.push(remote, buildRemoteCmd(cmd, opts));\n return runSpawn(argv, {\n onLog: opts?.onLog,\n stdin: opts?.stdin,\n timeoutMs: opts?.timeoutMs,\n });\n },\n upload: async (localPath, remotePath, opts) => {\n if (useRsync) {\n const sshCmd = [\"ssh\", ...sshBaseFlags(options)]\n .map((part) => (part.includes(\" \") ? `'${part}'` : part))\n .join(\" \");\n const argv = [\"rsync\", \"-az\", \"-e\", sshCmd];\n if (opts?.deleteOrphans) argv.push(\"--delete\");\n for (const pattern of opts?.exclude ?? [])\n argv.push(\"--exclude\", pattern);\n argv.push(localPath, `${remote}:${remotePath}`);\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `rsync upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n return;\n }\n // scp fallback — no exclude, no delete. We still need -r to copy directories.\n const argv = [\n \"scp\",\n \"-r\",\n ...sshBaseFlags(options),\n localPath,\n `${remote}:${remotePath}`,\n ];\n const result = await runSpawn(argv, { timeoutMs: 600_000 });\n if (result.exitCode !== 0) {\n throw new Error(\n `scp upload failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n },\n };\n};\n",
|
|
6
|
+
"/**\n * Shared \"cloud-provider Target\" plumbing used by the\n * provider-specific adapters (`./digitalocean`, `./hetzner`, future\n * `./linode`, `./vultr`, etc.).\n *\n * The provider supplies a small `CloudTargetHooks` bag that knows\n * the provider's:\n *\n * - find-by-name lookup\n * - create call (closure over create params)\n * - fetch-by-id (used to poll for `active`)\n * - destroy-by-id\n * - status + ipv4 + id extraction from the provider's Server shape\n * - readiness predicate (status reached the terminal \"running\" value)\n *\n * `createCloudTarget()` does the universal machinery: provision-or-\n * reuse, poll until ready + IPv4, wait for SSH probe, build\n * `sshTarget` against the IPv4, return the Target wrapped with\n * `{ id, ipv4, destroy() }`.\n *\n * The public adapter (e.g. `digitalOceanTarget`) is a 30-line facade\n * that wires its provider-specific bits and renames `id` → `dropletId`\n * on the way out.\n */\n\nimport type { Target } from \"./targets\";\nimport { sshTarget } from \"./targets\";\n\n/** Provider-specific hooks. Keep these pure of network IO timing — the helper schedules. */\nexport type CloudTargetHooks<Server, Id = number> = {\n /** Find a server by name. Returns undefined if absent. */\n findByName: (name: string) => Promise<Server | undefined>;\n /** Create the server. Closure over provider-specific create params. */\n create: () => Promise<Server>;\n /** Fetch a fresh copy of the server by id. Used to poll. */\n fetch: (id: Id) => Promise<Server>;\n /** Destroy a server by id. 404 should be treated as idempotent success. */\n destroy: (id: Id) => Promise<void>;\n /** True when the server has reached its terminal \"running\" status. */\n isReady: (server: Server) => boolean;\n /** Extract the provider-assigned id (number for DO/Hetzner/Linode, string for Vultr). */\n getId: (server: Server) => Id;\n /** Extract the public IPv4. Returns undefined while one is being assigned. */\n getIpv4: (server: Server) => string | undefined;\n /** Extract the current status as a string (for log lines). */\n getStatus: (server: Server) => string;\n};\n\nexport type CloudTargetOptions = {\n /** Provider's idempotency key (server name). */\n name: string;\n /** Region / location label — used in the \"creating\" log line. */\n region: string;\n\n /** SSH login user. Default `'root'`. */\n user?: string;\n /** SSH identity file. */\n identity?: string;\n /** SSH port. Default 22. */\n port?: number;\n\n /** Default 5 min. */\n provisionTimeoutMs?: number;\n /** Default 2 min. */\n sshReadinessTimeoutMs?: number;\n /** Default 5 s. */\n pollIntervalMs?: number;\n\n /** Called with status updates. */\n onLog?: (line: string) => void;\n /** Override SSH probe — tests skip real TCP IO. */\n probeSsh?: (host: string, port: number) => Promise<boolean>;\n /** Override sleep — tests skip real waits. */\n sleep?: (ms: number) => Promise<void>;\n /** Override clock — tests inject deterministic timestamps. */\n now?: () => number;\n\n /**\n * Short log prefix, e.g. `'[do]'` or `'[hetzner]'`. Threaded through\n * every log line so multi-provider deploys distinguish output.\n */\n logPrefix: string;\n /**\n * Provider's word for the entity in log copy — `'droplet'` for DO,\n * `'server'` for Hetzner. Preserves provider-accurate output.\n */\n entityWord: string;\n /**\n * Build the Target's `description` field. Receives the resolved\n * IPv4 + the wrapped sshTarget description.\n */\n describeTarget: (sshDescription: string) => string;\n};\n\nexport type CloudTargetResult<Id = number> = {\n id: Id;\n ipv4: string;\n description: string;\n exec: Target[\"exec\"];\n upload: Target[\"upload\"];\n close?: Target[\"close\"];\n destroy: () => Promise<void>;\n};\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst defaultProbeSsh = async (\n host: string,\n port: number,\n): Promise<boolean> => {\n const PROBE_TIMEOUT_MS = 2_000;\n return new Promise<boolean>((resolve) => {\n let settled = false;\n const settle = (value: boolean) => {\n if (settled) return;\n settled = true;\n resolve(value);\n };\n const timer = setTimeout(() => settle(false), PROBE_TIMEOUT_MS);\n Bun.connect({\n hostname: host,\n port,\n socket: {\n data: () => {},\n error: () => {\n clearTimeout(timer);\n settle(false);\n },\n open: (socket) => {\n clearTimeout(timer);\n socket.end();\n settle(true);\n },\n },\n }).catch(() => {\n clearTimeout(timer);\n settle(false);\n });\n });\n};\n\n/**\n * The shared provision-or-reuse + wait-for-ready + wait-for-SSH\n * pipeline. Provider-specific adapters wire their `CloudTargetHooks`\n * + their option-shape mapping and return a typed result.\n */\nexport const createCloudTarget = async <Server, Id = number>(\n hooks: CloudTargetHooks<Server, Id>,\n options: CloudTargetOptions,\n): Promise<CloudTargetResult<Id>> => {\n const log = options.onLog ?? (() => {});\n const probeSsh = options.probeSsh ?? defaultProbeSsh;\n const sleep = options.sleep ?? defaultSleep;\n const now = options.now ?? Date.now;\n const pollMs = options.pollIntervalMs ?? 5_000;\n const provisionTimeout = options.provisionTimeoutMs ?? 5 * 60_000;\n const sshTimeout = options.sshReadinessTimeoutMs ?? 2 * 60_000;\n const port = options.port ?? 22;\n const prefix = options.logPrefix;\n const noun = options.entityWord;\n\n const existing = await hooks.findByName(options.name);\n let current: Server;\n if (existing === undefined) {\n log(`${prefix} creating ${noun} \"${options.name}\" in ${options.region}`);\n current = await hooks.create();\n } else {\n log(\n `${prefix} reusing ${noun} \"${options.name}\" (id ${hooks.getId(existing)}, status ${hooks.getStatus(existing)})`,\n );\n current = existing;\n }\n\n // Wait for status=ready AND public IPv4 assigned.\n const provisionStart = now();\n let ipv4 = hooks.getIpv4(current);\n while (!hooks.isReady(current) || ipv4 === undefined) {\n if (now() - provisionStart > provisionTimeout) {\n throw new Error(\n `${prefix} provision timeout after ${provisionTimeout}ms — ${noun} ${hooks.getId(current)} status \"${hooks.getStatus(current)}\", ipv4 ${ipv4 ?? \"(unassigned)\"}`,\n );\n }\n await sleep(pollMs);\n current = await hooks.fetch(hooks.getId(current));\n ipv4 = hooks.getIpv4(current);\n log(\n `${prefix} poll: status=${hooks.getStatus(current)} ipv4=${ipv4 ?? \"(none yet)\"}`,\n );\n }\n log(`${prefix} ${noun} ready at ${ipv4}`);\n\n // Wait for SSH readiness.\n const sshStart = now();\n while (!(await probeSsh(ipv4, port))) {\n if (now() - sshStart > sshTimeout) {\n throw new Error(\n `${prefix} SSH readiness timeout after ${sshTimeout}ms — ${ipv4}:${port} did not accept connections`,\n );\n }\n await sleep(pollMs);\n log(`${prefix} waiting on ssh ${ipv4}:${port}`);\n }\n log(`${prefix} ssh ready at ${ipv4}:${port}`);\n\n const ssh = sshTarget({\n host: ipv4,\n ...(options.user !== undefined ? { user: options.user } : {}),\n ...(options.identity !== undefined ? { identity: options.identity } : {}),\n ...(options.port !== undefined ? { port: options.port } : {}),\n });\n\n const id = hooks.getId(current);\n const resolvedIpv4 = ipv4;\n\n return {\n description: options.describeTarget(ssh.description),\n destroy: () =>\n hooks.destroy(id).then(() => {\n log(`${prefix} destroyed ${noun} ${id}`);\n }),\n exec: ssh.exec,\n id,\n ipv4: resolvedIpv4,\n upload: ssh.upload,\n ...(ssh.close !== undefined ? { close: ssh.close } : {}),\n };\n};\n",
|
|
7
|
+
"/**\n * @absolutejs/deploy/linode — provision-or-reuse Target adapter for\n * Linode (Akamai Cloud) instances. Sibling to digitalOceanTarget +\n * hetznerTarget; same shape, Linode v4 API mappings.\n *\n * Idempotent by label — Linode allows duplicate labels per account\n * but we treat duplicates as drifted state (throw on the second).\n *\n * Narrow LinodeClientLike interface keeps `@linode/api-v4` out as a\n * hard dep. Default client uses `fetch` against `api.linode.com/v4`.\n */\n\nimport type { Target } from \"./targets\";\nimport { createCloudTarget, type CloudTargetHooks } from \"./cloudTarget\";\n\nconst LINODE_API_BASE = \"https://api.linode.com/v4\";\n\nexport type LinodeClientLike = {\n request: <T = unknown>(\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n body?: unknown,\n ) => Promise<T>;\n};\n\n/** A Linode instance, narrowed to what we inspect. */\nexport type LinodeInstance = {\n id: number;\n label: string;\n status:\n | \"running\"\n | \"offline\"\n | \"booting\"\n | \"rebooting\"\n | \"shutting_down\"\n | \"provisioning\"\n | \"deleting\"\n | \"migrating\"\n | \"rebuilding\"\n | \"cloning\"\n | \"restoring\"\n | \"stopped\";\n /** Linode returns IPv4 as a flat string array; public IPs first. */\n ipv4: string[];\n region?: string;\n type?: string;\n tags?: string[];\n};\n\nexport type LinodeTargetOptions = {\n /** Linode Personal Access Token. Required unless `client` is set. */\n token?: string;\n /** Custom client. Overrides token-built default. */\n client?: LinodeClientLike;\n\n // ── Instance shape ──────────────────────────────────────────────\n /** Instance label. Idempotency key. */\n name: string;\n /** Region slug — `'us-east'`, `'us-west'`, `'ap-south'`, etc. */\n region: string;\n /** Type slug — `'g6-nanode-1'`, `'g6-standard-1'`, etc. */\n type: string;\n /** Image slug — e.g. `'linode/ubuntu22.04'`. */\n image: string;\n /**\n * SSH public keys (raw `ssh-rsa AAAA…` / `ssh-ed25519 AAAA…` strings)\n * authorized for root login. At least one required for a usable target.\n */\n sshKeys: ReadonlyArray<string>;\n /** Tags applied to the instance. */\n tags?: ReadonlyArray<string>;\n /** Cloud-init / StackScript user data, base64-encoded by us. */\n userData?: string;\n /**\n * Root password. Linode requires a password at creation. Defaults to\n * a random 32-char string — you should rely on `sshKeys` and never\n * type this. Override only if you have a specific reason.\n */\n rootPass?: string;\n /** Enable private IP. Default false. */\n privateIp?: boolean;\n /** Enable backups. Default false. */\n backupsEnabled?: boolean;\n\n // ── SSH wrap ────────────────────────────────────────────────────\n /** SSH login user. Default `'root'`. */\n user?: string;\n /** SSH identity file. */\n identity?: string;\n /** SSH port. Default 22. */\n port?: number;\n\n // ── Timing ──────────────────────────────────────────────────────\n provisionTimeoutMs?: number;\n sshReadinessTimeoutMs?: number;\n pollIntervalMs?: number;\n\n // ── Observability + injection ───────────────────────────────────\n onLog?: (line: string) => void;\n probeSsh?: (host: string, port: number) => Promise<boolean>;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n};\n\nexport type LinodeTarget = Target & {\n readonly instanceId: number;\n readonly ipv4: string;\n destroy: () => Promise<void>;\n};\n\nexport class LinodeError extends Error {\n readonly status: number;\n readonly body: unknown;\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.name = \"LinodeError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport const createLinodeClient = (\n token: string,\n options: { baseUrl?: string; fetch?: typeof fetch } = {},\n): LinodeClientLike => {\n const base = options.baseUrl ?? LINODE_API_BASE;\n const f = options.fetch ?? fetch;\n return {\n request: async <T>(\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n body?: unknown,\n ): Promise<T> => {\n const init: RequestInit = {\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n method,\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const response = await f(`${base}${path}`, init);\n if (response.status === 204) return undefined as T;\n const text = await response.text();\n const parsed = text.length > 0 ? JSON.parse(text) : undefined;\n if (!response.ok) {\n throw new LinodeError(\n `Linode API ${method} ${path} failed: ${response.status} ${response.statusText}`,\n response.status,\n parsed,\n );\n }\n return parsed as T;\n },\n };\n};\n\nconst resolveClient = (\n options: Pick<LinodeTargetOptions, \"client\" | \"token\">,\n): LinodeClientLike => {\n if (options.client !== undefined) return options.client;\n if (options.token !== undefined && options.token.length > 0) {\n return createLinodeClient(options.token);\n }\n throw new Error(\n \"[deploy/linode] either `token` or `client` must be provided\",\n );\n};\n\nconst publicIpv4 = (instance: LinodeInstance): string | undefined => {\n // Linode's first IPv4 entry is the primary public address.\n for (const ip of instance.ipv4) {\n // Skip private RFC1918 + link-local. Crude but good enough.\n if (\n !ip.startsWith(\"10.\") &&\n !ip.startsWith(\"192.168.\") &&\n !ip.startsWith(\"172.\") &&\n !ip.startsWith(\"169.254.\")\n ) {\n return ip;\n }\n }\n return undefined;\n};\n\nconst randomPassword = (length: number): string => {\n const chars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*\";\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n let out = \"\";\n for (const byte of bytes) out += chars[byte % chars.length];\n return out;\n};\n\n/** Find an instance by label. Throws on ambiguous duplicates. */\nexport const findLinodeInstance = async (\n client: LinodeClientLike,\n name: string,\n): Promise<LinodeInstance | undefined> => {\n const body = await client.request<{ data: LinodeInstance[] }>(\n \"GET\",\n \"/linode/instances?page_size=500\",\n );\n const matches = body.data.filter((instance) => instance.label === name);\n if (matches.length === 0) return undefined;\n if (matches.length > 1) {\n throw new Error(\n `[deploy/linode] multiple instances labeled \"${name}\" (${matches\n .map((instance) => instance.id)\n .join(\", \")}). Resolve manually before adopting.`,\n );\n }\n return matches[0];\n};\n\nexport const listLinodeInstances = async (options: {\n token?: string;\n client?: LinodeClientLike;\n tag?: string;\n}): Promise<LinodeInstance[]> => {\n const client = resolveClient(options);\n const path =\n options.tag !== undefined\n ? `/linode/instances?tag=${encodeURIComponent(options.tag)}&page_size=500`\n : \"/linode/instances?page_size=500\";\n const body = await client.request<{ data: LinodeInstance[] }>(\"GET\", path);\n return body.data;\n};\n\nexport const destroyLinodeInstance = async (options: {\n token?: string;\n client?: LinodeClientLike;\n id: number;\n}): Promise<void> => {\n const client = resolveClient(options);\n try {\n await client.request(\"DELETE\", `/linode/instances/${options.id}`);\n } catch (error) {\n if (error instanceof LinodeError && error.status === 404) return;\n throw error;\n }\n};\n\nexport const linodeTarget = async (\n options: LinodeTargetOptions,\n): Promise<LinodeTarget> => {\n const client = resolveClient(options);\n const rootPass = options.rootPass ?? randomPassword(32);\n\n const hooks: CloudTargetHooks<LinodeInstance> = {\n create: async () => {\n const created = await client.request<LinodeInstance>(\n \"POST\",\n \"/linode/instances\",\n {\n authorized_keys: [...options.sshKeys],\n image: options.image,\n label: options.name,\n region: options.region,\n root_pass: rootPass,\n type: options.type,\n ...(options.tags !== undefined ? { tags: [...options.tags] } : {}),\n ...(options.userData !== undefined\n ? { stackscript_data: { user_data: options.userData } }\n : {}),\n ...(options.privateIp === true ? { private_ip: true } : {}),\n ...(options.backupsEnabled === true ? { backups_enabled: true } : {}),\n },\n );\n return created;\n },\n destroy: (id) => destroyLinodeInstance({ client, id }),\n fetch: (id) =>\n client.request<LinodeInstance>(\"GET\", `/linode/instances/${id}`),\n findByName: (name) => findLinodeInstance(client, name),\n getId: (instance) => instance.id,\n getIpv4: publicIpv4,\n getStatus: (instance) => instance.status,\n isReady: (instance) => instance.status === \"running\",\n };\n\n const result = await createCloudTarget(hooks, {\n describeTarget: (sshDescription) =>\n `linode \"${options.name}\" (${sshDescription})`,\n entityWord: \"instance\",\n logPrefix: \"[linode]\",\n name: options.name,\n region: options.region,\n ...(options.user !== undefined ? { user: options.user } : {}),\n ...(options.identity !== undefined ? { identity: options.identity } : {}),\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.provisionTimeoutMs !== undefined\n ? { provisionTimeoutMs: options.provisionTimeoutMs }\n : {}),\n ...(options.sshReadinessTimeoutMs !== undefined\n ? { sshReadinessTimeoutMs: options.sshReadinessTimeoutMs }\n : {}),\n ...(options.pollIntervalMs !== undefined\n ? { pollIntervalMs: options.pollIntervalMs }\n : {}),\n ...(options.onLog !== undefined ? { onLog: options.onLog } : {}),\n ...(options.probeSsh !== undefined ? { probeSsh: options.probeSsh } : {}),\n ...(options.sleep !== undefined ? { sleep: options.sleep } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n });\n\n return {\n description: result.description,\n destroy: result.destroy,\n exec: result.exec,\n instanceId: result.id,\n ipv4: result.ipv4,\n upload: result.upload,\n ...(result.close !== undefined ? { close: result.close } : {}),\n };\n};\n",
|
|
8
|
+
"import type { InfrastructureNode } from \"./infrastructure\";\n\nexport type InfrastructureAgentOptions = {\n audience?: string;\n port?: number;\n preferPrivateNetwork?: boolean;\n protocol?: \"http\" | \"https\";\n};\n\nexport const infrastructureAgent = (\n options: InfrastructureAgentOptions | undefined,\n addresses: Pick<InfrastructureNode, \"privateIpv4\" | \"publicIpv4\">,\n) => {\n if (!options) return undefined;\n const host = options.preferPrivateNetwork\n ? (addresses.privateIpv4 ?? addresses.publicIpv4)\n : (addresses.publicIpv4 ?? addresses.privateIpv4);\n if (!host) return undefined;\n\n return {\n url: `${options.protocol ?? \"http\"}://${host}:${options.port ?? 8081}/`,\n ...(options.audience ? { audience: options.audience } : {}),\n };\n};\n\nexport const leastPopulatedRegion = <Region extends { region: string }>(\n regions: readonly Region[],\n observed: readonly string[],\n requested?: string,\n) => {\n const eligible = requested\n ? regions.filter((region) => region.region === requested)\n : [...regions];\n if (eligible.length === 0) return undefined;\n const counts = new Map(eligible.map((region) => [region.region, 0]));\n for (const region of observed) {\n if (counts.has(region)) counts.set(region, (counts.get(region) ?? 0) + 1);\n }\n const selected = [...counts].sort(\n (left, right) => left[1] - right[1] || left[0].localeCompare(right[0]),\n )[0]?.[0];\n\n return eligible.find((region) => region.region === selected);\n};\n",
|
|
9
|
+
"import {\n createLinodeClient,\n destroyLinodeInstance,\n findLinodeInstance,\n listLinodeInstances,\n type LinodeClientLike,\n type LinodeInstance,\n} from \"./linode\";\nimport type {\n InfrastructureNode,\n InfrastructureNodeState,\n InfrastructureProvider,\n} from \"./infrastructure\";\nimport {\n infrastructureAgent,\n leastPopulatedRegion,\n type InfrastructureAgentOptions,\n} from \"./infrastructureAdapter\";\n\nexport type LinodeFleetRegion = {\n image: string;\n region: string;\n sshKeys: ReadonlyArray<string>;\n type: string;\n userData?: string;\n};\n\nexport type LinodeInfrastructureProviderOptions = {\n agent?: InfrastructureAgentOptions;\n client?: LinodeClientLike;\n regions: readonly LinodeFleetRegion[];\n tag?: string;\n token?: string;\n};\n\nconst isPrivate = (ip: string) =>\n ip.startsWith(\"10.\") ||\n ip.startsWith(\"192.168.\") ||\n ip.startsWith(\"172.\") ||\n ip.startsWith(\"169.254.\");\n\nconst stateFor = (\n status: LinodeInstance[\"status\"],\n): InfrastructureNodeState => {\n if (status === \"running\") return \"ready\";\n if (\n [\n \"booting\",\n \"rebooting\",\n \"provisioning\",\n \"migrating\",\n \"rebuilding\",\n \"cloning\",\n \"restoring\",\n ].includes(status)\n )\n return \"pending\";\n\n return \"terminated\";\n};\n\nconst parseNodeId = (id: string) => {\n const match = /^linode:([1-9][0-9]*)$/.exec(id);\n if (!match?.[1])\n throw new Error(\"[deploy/linode] invalid infrastructure node id\");\n\n return Number(match[1]);\n};\n\nconst rootPassword = () => {\n const bytes = crypto.getRandomValues(new Uint8Array(24));\n\n return Buffer.from(bytes).toString(\"base64url\");\n};\n\nexport const createLinodeInfrastructureProvider = (\n options: LinodeInfrastructureProviderOptions,\n): InfrastructureProvider => {\n if (options.regions.length === 0)\n throw new Error(\"[deploy/linode] at least one fleet region is required\");\n const client =\n options.client ??\n (options.token ? createLinodeClient(options.token) : undefined);\n if (!client)\n throw new Error(\n \"[deploy/linode] either `token` or `client` must be provided\",\n );\n const tag = options.tag ?? \"absolutejs-paas-node\";\n\n const normalize = (instance: LinodeInstance): InfrastructureNode => {\n const publicIpv4 = instance.ipv4.find((ip) => !isPrivate(ip));\n const privateIpv4 = instance.ipv4.find(isPrivate);\n const agent = infrastructureAgent(options.agent, {\n privateIpv4,\n publicIpv4,\n });\n\n return {\n id: `linode:${instance.id}`,\n label: instance.label,\n provider: \"linode\",\n region: instance.region ?? \"unknown\",\n state: stateFor(instance.status),\n ...(publicIpv4 ? { publicIpv4 } : {}),\n ...(privateIpv4 ? { privateIpv4 } : {}),\n ...(agent ? { agent } : {}),\n };\n };\n const list = () => listLinodeInstances({ client, tag });\n\n return {\n capabilities: {\n cloudInit: true,\n idempotentProvisioning: true,\n privateNetworking: true,\n regionalPlacement: true,\n regions: options.regions.map(({ region }) => region),\n },\n getNode: async (id) => {\n const instance = await client.request<LinodeInstance>(\n \"GET\",\n `/linode/instances/${parseNodeId(id)}`,\n );\n\n return normalize(instance);\n },\n listNodes: async () => (await list()).map(normalize),\n name: \"linode\",\n provisionNode: async (input) => {\n const existing = await findLinodeInstance(client, input.name);\n if (existing) return normalize(existing);\n const instances = await list();\n const region = leastPopulatedRegion(\n options.regions,\n instances.map((instance) => instance.region ?? \"unknown\"),\n input.region,\n );\n if (!region)\n throw new Error(\n `[deploy/linode] region ${input.region ?? \"(any)\"} is not configured`,\n );\n const instance = await client.request<LinodeInstance>(\n \"POST\",\n \"/linode/instances\",\n {\n authorized_keys: [...region.sshKeys],\n image: region.image,\n label: input.name,\n private_ip: true,\n region: region.region,\n root_pass: rootPassword(),\n tags: [tag],\n type: region.type,\n ...((input.userData ?? region.userData)\n ? {\n stackscript_data: {\n user_data: input.userData ?? region.userData,\n },\n }\n : {}),\n },\n );\n\n return normalize(instance);\n },\n terminateNode: async (id) =>\n destroyLinodeInstance({ client, id: parseNodeId(id) }),\n };\n};\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "2505939C4EB7F37564756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/dist/managedPreview.d.ts
CHANGED
package/dist/managedPreview.js
CHANGED
|
@@ -100,7 +100,8 @@ var createManagedPreviewFleet = (options) => {
|
|
|
100
100
|
previewId: input.previewId,
|
|
101
101
|
status: "provisioning",
|
|
102
102
|
updatedAt: now,
|
|
103
|
-
...input.expiresAt === undefined ? existing?.expiresAt === undefined ? {} : { expiresAt: existing.expiresAt } : { expiresAt: input.expiresAt }
|
|
103
|
+
...input.expiresAt === undefined ? existing?.expiresAt === undefined ? {} : { expiresAt: existing.expiresAt } : { expiresAt: input.expiresAt },
|
|
104
|
+
...input.releaseId === undefined ? {} : { releaseId: input.releaseId }
|
|
104
105
|
};
|
|
105
106
|
return publish(record);
|
|
106
107
|
});
|
|
@@ -168,5 +169,5 @@ export {
|
|
|
168
169
|
createManagedPreviewFleet
|
|
169
170
|
};
|
|
170
171
|
|
|
171
|
-
//# debugId=
|
|
172
|
+
//# debugId=6747D9124F0D08D764756E2164756E21
|
|
172
173
|
//# sourceMappingURL=managedPreview.js.map
|