@tsplc/agent 0.2.7 → 0.2.9

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/cli.js CHANGED
@@ -23,7 +23,8 @@ import {
23
23
  loginCommandSchema,
24
24
  openControllerLogin,
25
25
  resolveConfig,
26
- updateController
26
+ startWarmController,
27
+ updateWarmController
27
28
  } from "@tsplc/build";
28
29
  import { z as z3 } from "zod";
29
30
 
@@ -262,6 +263,7 @@ var network = "tsplc-agent";
262
263
  var codesysNetwork = "tsplc-agent-codesys";
263
264
  var gateway = { host: "tsplc-agent-gateway", port: 1217 };
264
265
  var loginContainer = "tsplc-agent-login";
266
+ var deployContainer = "tsplc-agent-deploy";
265
267
  var credentialNames = {
266
268
  usernameEnv: "TSPLC_DEVICE_USERNAME",
267
269
  passwordEnv: "TSPLC_DEVICE_PASSWORD"
@@ -366,6 +368,16 @@ var createAgent = async (options) => {
366
368
  throw new AgentError("Nothing has been deployed yet: tsplc deploy", 409);
367
369
  return loadRelease(paths.releases, release.id);
368
370
  };
371
+ const warming = (async () => {
372
+ const target = await readJson(paths.target, targetSchema);
373
+ if (!deployed || !target)
374
+ return;
375
+ await ensureGateway();
376
+ const release = await loadRelease(paths.releases, deployed.id);
377
+ await startWarmController(controllerConfig(release, target), deployContainer);
378
+ })().catch((error) => {
379
+ options.log(`Starting CODESYS failed: ${error instanceof Error ? error.message : String(error)}`);
380
+ });
369
381
  const operation = (name, run) => {
370
382
  if (busy)
371
383
  throw new AgentError(`The agent is busy with ${busy}`, 409);
@@ -421,10 +433,14 @@ var createAgent = async (options) => {
421
433
  await server.replace(join2(paths.releases, serverPath));
422
434
  }
423
435
  const kind = settings.download ? "download" : "online-change";
424
- emit({ kind: "progress", message: `Starting the ${kind}; CODESYS takes minutes to start` });
436
+ emit({ kind: "progress", message: `Starting the ${kind}` });
425
437
  await ensureGateway();
438
+ await warming;
426
439
  const stopFollowing = followProgress(paths.controller, emit);
427
- const receipt = await withCredentials(settings.credentials, () => updateController(config, kind, { initializeUser: settings.initializeUser })).catch(async (failure) => {
440
+ const receipt = await updateWarmController(config, deployContainer, kind, {
441
+ initializeUser: settings.initializeUser,
442
+ credentials: settings.credentials
443
+ }).catch(async (failure) => {
428
444
  if (serverPath) {
429
445
  emit({ kind: "progress", message: "Restoring the previous server" });
430
446
  await (previous?.server ? server.replace(join2(paths.releases, previous.server)) : server.stop());
@@ -578,5 +594,5 @@ if (command === "setup") {
578
594
  } else
579
595
  throw new Error(`Unknown command ${command}.`);
580
596
 
581
- //# debugId=6AE382186C37533864756E2164756E21
597
+ //# debugId=94194CB487C8652E64756E2164756E21
582
598
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -3,13 +3,13 @@
3
3
  "sources": ["../src/cli.ts", "../src/agent.ts", "../src/discovery.ts", "../src/protocol.ts", "../src/releases.ts", "../src/server-process.ts"],
4
4
  "sourcesContent": [
5
5
  "#!/usr/bin/env bun\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { configureDocker, configureGateway } from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { createAgent } from \"./agent.ts\";\n\nconst usage = `tsplc-agent setup|serve [--listen host:port] [--state directory] [--server-health url]\n\nsetup Builds the CODESYS builder and gateway images. Run it once, and after updating tsPLC.\nserve Serves deployments and logins. --listen is required: use the machine's Tailscale\n address, such as 100.101.102.103:4850. TSPLC_AGENT_TOKEN must hold a shared secret of\n at least 32 characters, such as one from \\`openssl rand -hex 32\\`.`;\n\nconst { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\" },\n listen: { type: \"string\" },\n state: { type: \"string\" },\n \"server-health\": { type: \"string\" },\n },\n});\nconst command = positionals[0];\nif (!command || values.help) {\n console.log(usage);\n process.exit(0);\n}\nif (positionals.length > 1) throw new Error(\"Specify one command.\");\nif (command === \"setup\") {\n await configureDocker();\n await configureGateway();\n} else if (command === \"serve\") {\n const [, hostname, port] = /^(.+):(\\d+)$/.exec(values.listen ?? \"\") ?? [];\n if (!hostname || !port) throw new Error(\"--listen host:port is required.\");\n const token = z\n .string({ error: \"Set TSPLC_AGENT_TOKEN\" })\n .min(32, \"TSPLC_AGENT_TOKEN must be at least 32 characters\")\n .parse(process.env[\"TSPLC_AGENT_TOKEN\"]);\n const agent = await createAgent({\n state: values.state ?? join(homedir(), \".tsplc-agent\"),\n token,\n serverHealthUrl: values[\"server-health\"],\n log: (message) => console.log(`${new Date().toISOString()} ${message}`),\n });\n const server = Bun.serve({\n hostname,\n port: Number(port),\n fetch: agent.fetch,\n // Deployments stream for minutes and upload a server executable.\n idleTimeout: 0,\n maxRequestBodySize: 2 ** 30,\n });\n console.log(`tsPLC agent listening on ${server.url}`);\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const)\n process.on(signal, () => {\n void agent.stop().then(() => process.exit(0));\n });\n} else throw new Error(`Unknown command ${command}.`);\n",
6
- "import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
6
+ "import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n startWarmController,\n updateWarmController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** Keeps CODESYS running between deployments, so each skips starting it. */\nconst deployContainer = \"tsplc-agent-deploy\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** CODESYS starts for the deployed release in the background, so the first deployment finds it running. */\n const warming = (async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!deployed || !target) return;\n await ensureGateway();\n const release = await loadRelease(paths.releases, deployed.id);\n await startWarmController(controllerConfig(release, target), deployContainer);\n })().catch((error: unknown) => {\n options.log(\n `Starting CODESYS failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}` });\n await ensureGateway();\n await warming;\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await updateWarmController(config, deployContainer, kind, {\n initializeUser: settings.initializeUser,\n credentials: settings.credentials,\n })\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
7
7
  "import { Resolver } from \"node:dns/promises\";\nimport { createConnection } from \"node:net\";\nimport { networkInterfaces as osInterfaces } from \"node:os\";\nimport type { DiscoveredController, NetworkInterface } from \"./protocol\";\n\n/** CODESYS runtimes accept engineering connections on their TCP block driver port. */\nexport const runtimePort = 11740;\n/** A /22 is 1022 hosts: a sweep at 128 probes a time takes a few seconds. */\nconst largestPrefix = 22;\nconst probeTimeoutMs = 500;\nconst probesAtOnce = 128;\n\n/** The machine's IPv4 networks, which `discoverControllers` scans one at a time. */\nexport const networkInterfaces = (): NetworkInterface[] =>\n Object.entries(osInterfaces()).flatMap(([name, addresses]) =>\n (addresses ?? [])\n .filter((address) => address.family === \"IPv4\" && !address.internal)\n .map((address) => ({\n name,\n address: address.address,\n prefixLength: address.netmask\n .split(\".\")\n .reduce((bits, octet) => bits + Number(octet).toString(2).replaceAll(\"0\", \"\").length, 0),\n })),\n );\n\nconst toNumber = (address: string) =>\n address.split(\".\").reduce((value, octet) => value * 256 + Number(octet), 0);\nconst toAddress = (value: number) =>\n [24, 16, 8, 0].map((shift) => Math.floor(value / 2 ** shift) % 256).join(\".\");\n\n/** Every host address on the interface's subnet, except the interface's own. */\nexport const subnetHosts = ({ address, prefixLength }: NetworkInterface) => {\n if (prefixLength < largestPrefix)\n throw new Error(\n `The /${prefixLength} network is too large to scan; the limit is /${largestPrefix}.`,\n );\n const size = 2 ** (32 - prefixLength);\n const network = toNumber(address) - (toNumber(address) % size);\n // /31 and /32 networks have no network or broadcast address to skip.\n const hosts =\n size <= 2\n ? Array.from({ length: size }, (_, index) => network + index)\n : Array.from({ length: size - 2 }, (_, index) => network + index + 1);\n return hosts.map(toAddress).filter((host) => host !== address);\n};\n\nconst accepts = (host: string, port: number) =>\n new Promise<boolean>((resolve) => {\n const socket = createConnection({ host, port });\n // A silent host leaves the connection pending for the OS's own timeout, which is minutes.\n const timer = setTimeout(() => finish(false), probeTimeoutMs);\n const finish = (open: boolean) => {\n clearTimeout(timer);\n socket.destroy();\n resolve(open);\n };\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n });\n\nconst resolver = new Resolver({ timeout: 1000, tries: 1 });\nconst hostname = (address: string) =>\n resolver.reverse(address).then(\n (names) => names[0] ?? null,\n // Plant networks rarely have reverse DNS; the address alone identifies the controller.\n () => null,\n );\n\n/** Finds the hosts on `network` that accept CODESYS runtime connections. */\nexport const discoverControllers = async (\n network: NetworkInterface,\n port = runtimePort,\n): Promise<DiscoveredController[]> => {\n const hosts = subnetHosts(network);\n const found: DiscoveredController[] = [];\n for (let start = 0; start < hosts.length; start += probesAtOnce) {\n const batch = hosts.slice(start, start + probesAtOnce);\n const open = await Promise.all(batch.map((host) => accepts(host, port)));\n for (const [index, host] of batch.entries())\n if (open[index]) found.push({ address: host, port, hostname: await hostname(host) });\n }\n return found;\n};\n",
8
8
  "import { z } from \"zod\";\n\n/** The controller the agent deploys to, as its runtime's TCP block driver address. */\nexport const targetSchema = z.strictObject({\n host: z.string().nonempty(),\n port: z.number().int().min(1).max(65535),\n});\nexport type Target = z.infer<typeof targetSchema>;\n\nexport const networkInterfaceSchema = z.strictObject({\n name: z.string(),\n address: z.ipv4(),\n prefixLength: z.number().int().min(0).max(32),\n});\nexport type NetworkInterface = z.infer<typeof networkInterfaceSchema>;\n\n/** A host on the scanned subnet that accepts connections on the CODESYS runtime port. */\nexport const controllerSchema = z.strictObject({\n address: z.ipv4(),\n port: z.number().int(),\n hostname: z.string().nullable(),\n});\nexport type DiscoveredController = z.infer<typeof controllerSchema>;\n\n/** The controller's user; the agent passes it to CODESYS for one operation and never stores it. */\nexport const credentialsSchema = z.strictObject({\n username: z.string().nonempty(),\n password: z.string().nonempty(),\n});\nexport type Credentials = z.infer<typeof credentialsSchema>;\n\n/** A published leaf of the deployed program, as CODESYS expressions name it. */\nexport const variableSchema = z.strictObject({ path: z.string(), type: z.string() });\nexport type Variable = z.infer<typeof variableSchema>;\n\n/**\n * What `tsplc deploy` uploads beside its files. `config` is the build config with paths\n * relative to the release: `st/`, `template.project` and `libraries/`.\n */\nexport const releaseManifestSchema = z.strictObject({\n config: z.record(z.string(), z.unknown()),\n variables: z.array(variableSchema),\n /** The server executable's path in the release, when the project builds one. */\n server: z.string().nonempty().optional(),\n});\nexport type ReleaseManifest = z.infer<typeof releaseManifestSchema>;\n\nexport const deployOptionsSchema = z.strictObject({\n credentials: credentialsSchema,\n /** A full download stops the application; without it only an online change is applied. */\n download: z.boolean(),\n initializeUser: z.boolean(),\n});\nexport type DeployOptions = z.infer<typeof deployOptionsSchema>;\n\n/** Long operations stream one of these per line. */\nexport const eventSchema = z.discriminatedUnion(\"kind\", [\n z.strictObject({ kind: z.literal(\"progress\"), message: z.string() }),\n z.strictObject({ kind: z.literal(\"done\"), result: z.unknown() }),\n z.strictObject({\n kind: z.literal(\"error\"),\n message: z.string(),\n /** The controller has no application from this agent yet, so only a full download can deploy. */\n downloadRequired: z.boolean(),\n }),\n]);\nexport type AgentEvent = z.infer<typeof eventSchema>;\n\nexport const releaseSchema = z.strictObject({\n id: z.string(),\n deployedAt: z.iso.datetime(),\n operation: z.enum([\"download\", \"online-change\"]),\n controllerIds: z.strictObject({ codeId: z.string(), dataId: z.string() }),\n /** The running server executable, relative to the releases directory. */\n server: z.string().optional(),\n});\nexport type Release = z.infer<typeof releaseSchema>;\n\nexport const statusSchema = z.strictObject({\n target: targetSchema.nullable(),\n release: releaseSchema.nullable(),\n server: z.strictObject({ executable: z.string(), running: z.boolean() }).nullable(),\n /** The open login's application state and forced expressions. */\n login: z.strictObject({ state: z.string(), forced: z.array(z.string()) }).nullable(),\n});\nexport type AgentStatus = z.infer<typeof statusSchema>;\n",
9
9
  "import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { z } from \"zod\";\nimport { type ReleaseManifest, releaseManifestSchema } from \"./protocol\";\n\n/** Uploaded files are named `files/<path in the release>`. */\nconst filePrefix = \"files/\";\n\nconst releasePath = (name: string) => {\n const path = posix.normalize(name.slice(filePrefix.length));\n if (posix.isAbsolute(path) || path.startsWith(\"..\") || path.includes(\"\\\\\"))\n throw new Error(`Invalid release file name: ${name}`);\n return path;\n};\n\n/** An uploaded release, from `tsplc deploy`'s form. */\nexport const readUpload = async (form: FormData) => {\n const manifest = releaseManifestSchema.parse(JSON.parse(z.string().parse(form.get(\"manifest\"))));\n const files = await Promise.all(\n [...form.entries()]\n .filter(([name]) => name.startsWith(filePrefix))\n .map(async ([name, value]) => ({\n path: releasePath(name),\n content: new Uint8Array(await z.instanceof(File).parse(value).arrayBuffer()),\n })),\n );\n if (manifest.server && !files.some((file) => file.path === manifest.server))\n throw new Error(`The release names a server ${manifest.server} it doesn't contain`);\n return { manifest, files };\n};\n\n/**\n * Stores a release under `releases/<id>`, where the id hashes its contents, so the same\n * upload twice is one release. Each release is complete before it appears.\n */\nexport const saveRelease = async (\n releases: string,\n { manifest, files }: Awaited<ReturnType<typeof readUpload>>,\n) => {\n const hash = createHash(\"sha256\").update(JSON.stringify(manifest));\n for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path)))\n hash.update(file.path).update(createHash(\"sha256\").update(file.content).digest(\"hex\"));\n const id = hash.digest(\"hex\").slice(0, 16);\n const directory = join(releases, id);\n if (!existsSync(directory)) {\n await mkdir(releases, { recursive: true });\n const staging = await mkdtemp(join(releases, \".upload-\"));\n try {\n for (const file of files) {\n await mkdir(dirname(join(staging, file.path)), { recursive: true });\n // Uploads lose their mode; the server must stay executable outside Windows.\n await writeFile(join(staging, file.path), file.content, {\n mode: file.path === manifest.server ? 0o755 : 0o644,\n });\n }\n await writeFile(join(staging, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n await rename(staging, directory);\n } catch (cause) {\n await rm(staging, { recursive: true, force: true });\n throw cause;\n }\n }\n return { id, directory, manifest };\n};\n\nexport const loadRelease = async (\n releases: string,\n id: string,\n): Promise<{ id: string; directory: string; manifest: ReleaseManifest }> => {\n const directory = join(releases, id);\n const manifest = releaseManifestSchema.parse(\n JSON.parse(await readFile(join(directory, \"manifest.json\"), \"utf8\")),\n );\n return { id, directory, manifest };\n};\n",
10
10
  "import type { Subprocess } from \"bun\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst healthyWithinMs = 60_000;\n/** Without a health URL, a server that stays up this long counts as started. */\nconst settleMs = 5000;\nconst restartDelayMs = 2000;\n\n/**\n * Runs the deployed server executable, restarting it whenever it exits, and swaps it for\n * another release's. The server reads its own environment and secrets, as it would anywhere.\n */\nexport const createServerSupervisor = (options: {\n /** The server's `/health` route, which answers once it is listening. */\n healthUrl?: string;\n log: (message: string) => void;\n}) => {\n let current: { executable: string; process: Subprocess } | undefined;\n\n const spawn = (executable: string): Subprocess => {\n const child = Bun.spawn([executable], {\n cwd: dirname(executable),\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n onExit: (_, code) => {\n // `stop` and `replace` clear or change `current` before killing a server.\n if (current?.process !== child) return;\n options.log(`Server exited (${code}); restarting it in ${restartDelayMs / 1000} s`);\n void delay(restartDelayMs).then(() => {\n if (current?.process === child) current = { executable, process: spawn(executable) };\n });\n },\n });\n return child;\n };\n\n const start = (executable: string) => {\n current = { executable, process: spawn(executable) };\n return current.process;\n };\n\n const stop = async () => {\n const running = current;\n current = undefined;\n if (!running) return;\n running.process.kill();\n await running.process.exited;\n };\n\n const healthy = async (child: Subprocess) => {\n if (!options.healthUrl) {\n await delay(settleMs);\n return child.exitCode === null;\n }\n const deadline = Date.now() + healthyWithinMs;\n while (Date.now() < deadline && child.exitCode === null) {\n if (\n await fetch(options.healthUrl).then(\n (response) => response.ok,\n () => false,\n )\n )\n return true;\n await delay(1000);\n }\n return false;\n };\n\n return {\n start,\n stop,\n /** Replaces the running server; if the new one doesn't come up, the previous one runs again. */\n replace: async (executable: string) => {\n const previous = current?.executable;\n await stop();\n let failure: unknown;\n const started = await (async () => healthy(start(executable)))().catch((error: unknown) => {\n failure = error;\n return false;\n });\n if (started) return;\n await stop();\n if (previous) start(previous);\n const reason =\n failure instanceof Error\n ? failure.message\n : `it did not start${options.healthUrl ? ` answering ${options.healthUrl}` : \"\"}`;\n throw new Error(\n `The new server failed: ${reason}. ${previous ? \"The previous one is running again.\" : \"\"}`.trim(),\n { cause: failure },\n );\n },\n status: () =>\n current && { executable: current.executable, running: current.process.exitCode === null },\n };\n};\n"
11
11
  ],
12
- "mappings": "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",
13
- "debugId": "6AE382186C37533864756E2164756E21",
12
+ "mappings": "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",
13
+ "debugId": "94194CB487C8652E64756E2164756E21",
14
14
  "names": []
15
15
  }
package/dist/index.js CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  loginCommandSchema,
14
14
  openControllerLogin,
15
15
  resolveConfig,
16
- updateController
16
+ startWarmController,
17
+ updateWarmController
17
18
  } from "@tsplc/build";
18
19
  import { z as z3 } from "zod";
19
20
 
@@ -252,6 +253,7 @@ var network = "tsplc-agent";
252
253
  var codesysNetwork = "tsplc-agent-codesys";
253
254
  var gateway = { host: "tsplc-agent-gateway", port: 1217 };
254
255
  var loginContainer = "tsplc-agent-login";
256
+ var deployContainer = "tsplc-agent-deploy";
255
257
  var credentialNames = {
256
258
  usernameEnv: "TSPLC_DEVICE_USERNAME",
257
259
  passwordEnv: "TSPLC_DEVICE_PASSWORD"
@@ -356,6 +358,16 @@ var createAgent = async (options) => {
356
358
  throw new AgentError("Nothing has been deployed yet: tsplc deploy", 409);
357
359
  return loadRelease(paths.releases, release.id);
358
360
  };
361
+ const warming = (async () => {
362
+ const target = await readJson(paths.target, targetSchema);
363
+ if (!deployed || !target)
364
+ return;
365
+ await ensureGateway();
366
+ const release = await loadRelease(paths.releases, deployed.id);
367
+ await startWarmController(controllerConfig(release, target), deployContainer);
368
+ })().catch((error) => {
369
+ options.log(`Starting CODESYS failed: ${error instanceof Error ? error.message : String(error)}`);
370
+ });
359
371
  const operation = (name, run) => {
360
372
  if (busy)
361
373
  throw new AgentError(`The agent is busy with ${busy}`, 409);
@@ -411,10 +423,14 @@ var createAgent = async (options) => {
411
423
  await server.replace(join2(paths.releases, serverPath));
412
424
  }
413
425
  const kind = settings.download ? "download" : "online-change";
414
- emit({ kind: "progress", message: `Starting the ${kind}; CODESYS takes minutes to start` });
426
+ emit({ kind: "progress", message: `Starting the ${kind}` });
415
427
  await ensureGateway();
428
+ await warming;
416
429
  const stopFollowing = followProgress(paths.controller, emit);
417
- const receipt = await withCredentials(settings.credentials, () => updateController(config, kind, { initializeUser: settings.initializeUser })).catch(async (failure) => {
430
+ const receipt = await updateWarmController(config, deployContainer, kind, {
431
+ initializeUser: settings.initializeUser,
432
+ credentials: settings.credentials
433
+ }).catch(async (failure) => {
418
434
  if (serverPath) {
419
435
  emit({ kind: "progress", message: "Restoring the previous server" });
420
436
  await (previous?.server ? server.replace(join2(paths.releases, previous.server)) : server.stop());
@@ -529,5 +545,5 @@ export {
529
545
  variableSchema
530
546
  };
531
547
 
532
- //# debugId=3E53D86CAC15F1B264756E2164756E21
548
+ //# debugId=B85D90377F39CD9264756E2164756E21
533
549
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,13 +2,13 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/agent.ts", "../src/discovery.ts", "../src/protocol.ts", "../src/releases.ts", "../src/server-process.ts"],
4
4
  "sourcesContent": [
5
- "import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
5
+ "import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n startWarmController,\n updateWarmController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** Keeps CODESYS running between deployments, so each skips starting it. */\nconst deployContainer = \"tsplc-agent-deploy\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** CODESYS starts for the deployed release in the background, so the first deployment finds it running. */\n const warming = (async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!deployed || !target) return;\n await ensureGateway();\n const release = await loadRelease(paths.releases, deployed.id);\n await startWarmController(controllerConfig(release, target), deployContainer);\n })().catch((error: unknown) => {\n options.log(\n `Starting CODESYS failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}` });\n await ensureGateway();\n await warming;\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await updateWarmController(config, deployContainer, kind, {\n initializeUser: settings.initializeUser,\n credentials: settings.credentials,\n })\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
6
6
  "import { Resolver } from \"node:dns/promises\";\nimport { createConnection } from \"node:net\";\nimport { networkInterfaces as osInterfaces } from \"node:os\";\nimport type { DiscoveredController, NetworkInterface } from \"./protocol\";\n\n/** CODESYS runtimes accept engineering connections on their TCP block driver port. */\nexport const runtimePort = 11740;\n/** A /22 is 1022 hosts: a sweep at 128 probes a time takes a few seconds. */\nconst largestPrefix = 22;\nconst probeTimeoutMs = 500;\nconst probesAtOnce = 128;\n\n/** The machine's IPv4 networks, which `discoverControllers` scans one at a time. */\nexport const networkInterfaces = (): NetworkInterface[] =>\n Object.entries(osInterfaces()).flatMap(([name, addresses]) =>\n (addresses ?? [])\n .filter((address) => address.family === \"IPv4\" && !address.internal)\n .map((address) => ({\n name,\n address: address.address,\n prefixLength: address.netmask\n .split(\".\")\n .reduce((bits, octet) => bits + Number(octet).toString(2).replaceAll(\"0\", \"\").length, 0),\n })),\n );\n\nconst toNumber = (address: string) =>\n address.split(\".\").reduce((value, octet) => value * 256 + Number(octet), 0);\nconst toAddress = (value: number) =>\n [24, 16, 8, 0].map((shift) => Math.floor(value / 2 ** shift) % 256).join(\".\");\n\n/** Every host address on the interface's subnet, except the interface's own. */\nexport const subnetHosts = ({ address, prefixLength }: NetworkInterface) => {\n if (prefixLength < largestPrefix)\n throw new Error(\n `The /${prefixLength} network is too large to scan; the limit is /${largestPrefix}.`,\n );\n const size = 2 ** (32 - prefixLength);\n const network = toNumber(address) - (toNumber(address) % size);\n // /31 and /32 networks have no network or broadcast address to skip.\n const hosts =\n size <= 2\n ? Array.from({ length: size }, (_, index) => network + index)\n : Array.from({ length: size - 2 }, (_, index) => network + index + 1);\n return hosts.map(toAddress).filter((host) => host !== address);\n};\n\nconst accepts = (host: string, port: number) =>\n new Promise<boolean>((resolve) => {\n const socket = createConnection({ host, port });\n // A silent host leaves the connection pending for the OS's own timeout, which is minutes.\n const timer = setTimeout(() => finish(false), probeTimeoutMs);\n const finish = (open: boolean) => {\n clearTimeout(timer);\n socket.destroy();\n resolve(open);\n };\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n });\n\nconst resolver = new Resolver({ timeout: 1000, tries: 1 });\nconst hostname = (address: string) =>\n resolver.reverse(address).then(\n (names) => names[0] ?? null,\n // Plant networks rarely have reverse DNS; the address alone identifies the controller.\n () => null,\n );\n\n/** Finds the hosts on `network` that accept CODESYS runtime connections. */\nexport const discoverControllers = async (\n network: NetworkInterface,\n port = runtimePort,\n): Promise<DiscoveredController[]> => {\n const hosts = subnetHosts(network);\n const found: DiscoveredController[] = [];\n for (let start = 0; start < hosts.length; start += probesAtOnce) {\n const batch = hosts.slice(start, start + probesAtOnce);\n const open = await Promise.all(batch.map((host) => accepts(host, port)));\n for (const [index, host] of batch.entries())\n if (open[index]) found.push({ address: host, port, hostname: await hostname(host) });\n }\n return found;\n};\n",
7
7
  "import { z } from \"zod\";\n\n/** The controller the agent deploys to, as its runtime's TCP block driver address. */\nexport const targetSchema = z.strictObject({\n host: z.string().nonempty(),\n port: z.number().int().min(1).max(65535),\n});\nexport type Target = z.infer<typeof targetSchema>;\n\nexport const networkInterfaceSchema = z.strictObject({\n name: z.string(),\n address: z.ipv4(),\n prefixLength: z.number().int().min(0).max(32),\n});\nexport type NetworkInterface = z.infer<typeof networkInterfaceSchema>;\n\n/** A host on the scanned subnet that accepts connections on the CODESYS runtime port. */\nexport const controllerSchema = z.strictObject({\n address: z.ipv4(),\n port: z.number().int(),\n hostname: z.string().nullable(),\n});\nexport type DiscoveredController = z.infer<typeof controllerSchema>;\n\n/** The controller's user; the agent passes it to CODESYS for one operation and never stores it. */\nexport const credentialsSchema = z.strictObject({\n username: z.string().nonempty(),\n password: z.string().nonempty(),\n});\nexport type Credentials = z.infer<typeof credentialsSchema>;\n\n/** A published leaf of the deployed program, as CODESYS expressions name it. */\nexport const variableSchema = z.strictObject({ path: z.string(), type: z.string() });\nexport type Variable = z.infer<typeof variableSchema>;\n\n/**\n * What `tsplc deploy` uploads beside its files. `config` is the build config with paths\n * relative to the release: `st/`, `template.project` and `libraries/`.\n */\nexport const releaseManifestSchema = z.strictObject({\n config: z.record(z.string(), z.unknown()),\n variables: z.array(variableSchema),\n /** The server executable's path in the release, when the project builds one. */\n server: z.string().nonempty().optional(),\n});\nexport type ReleaseManifest = z.infer<typeof releaseManifestSchema>;\n\nexport const deployOptionsSchema = z.strictObject({\n credentials: credentialsSchema,\n /** A full download stops the application; without it only an online change is applied. */\n download: z.boolean(),\n initializeUser: z.boolean(),\n});\nexport type DeployOptions = z.infer<typeof deployOptionsSchema>;\n\n/** Long operations stream one of these per line. */\nexport const eventSchema = z.discriminatedUnion(\"kind\", [\n z.strictObject({ kind: z.literal(\"progress\"), message: z.string() }),\n z.strictObject({ kind: z.literal(\"done\"), result: z.unknown() }),\n z.strictObject({\n kind: z.literal(\"error\"),\n message: z.string(),\n /** The controller has no application from this agent yet, so only a full download can deploy. */\n downloadRequired: z.boolean(),\n }),\n]);\nexport type AgentEvent = z.infer<typeof eventSchema>;\n\nexport const releaseSchema = z.strictObject({\n id: z.string(),\n deployedAt: z.iso.datetime(),\n operation: z.enum([\"download\", \"online-change\"]),\n controllerIds: z.strictObject({ codeId: z.string(), dataId: z.string() }),\n /** The running server executable, relative to the releases directory. */\n server: z.string().optional(),\n});\nexport type Release = z.infer<typeof releaseSchema>;\n\nexport const statusSchema = z.strictObject({\n target: targetSchema.nullable(),\n release: releaseSchema.nullable(),\n server: z.strictObject({ executable: z.string(), running: z.boolean() }).nullable(),\n /** The open login's application state and forced expressions. */\n login: z.strictObject({ state: z.string(), forced: z.array(z.string()) }).nullable(),\n});\nexport type AgentStatus = z.infer<typeof statusSchema>;\n",
8
8
  "import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { z } from \"zod\";\nimport { type ReleaseManifest, releaseManifestSchema } from \"./protocol\";\n\n/** Uploaded files are named `files/<path in the release>`. */\nconst filePrefix = \"files/\";\n\nconst releasePath = (name: string) => {\n const path = posix.normalize(name.slice(filePrefix.length));\n if (posix.isAbsolute(path) || path.startsWith(\"..\") || path.includes(\"\\\\\"))\n throw new Error(`Invalid release file name: ${name}`);\n return path;\n};\n\n/** An uploaded release, from `tsplc deploy`'s form. */\nexport const readUpload = async (form: FormData) => {\n const manifest = releaseManifestSchema.parse(JSON.parse(z.string().parse(form.get(\"manifest\"))));\n const files = await Promise.all(\n [...form.entries()]\n .filter(([name]) => name.startsWith(filePrefix))\n .map(async ([name, value]) => ({\n path: releasePath(name),\n content: new Uint8Array(await z.instanceof(File).parse(value).arrayBuffer()),\n })),\n );\n if (manifest.server && !files.some((file) => file.path === manifest.server))\n throw new Error(`The release names a server ${manifest.server} it doesn't contain`);\n return { manifest, files };\n};\n\n/**\n * Stores a release under `releases/<id>`, where the id hashes its contents, so the same\n * upload twice is one release. Each release is complete before it appears.\n */\nexport const saveRelease = async (\n releases: string,\n { manifest, files }: Awaited<ReturnType<typeof readUpload>>,\n) => {\n const hash = createHash(\"sha256\").update(JSON.stringify(manifest));\n for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path)))\n hash.update(file.path).update(createHash(\"sha256\").update(file.content).digest(\"hex\"));\n const id = hash.digest(\"hex\").slice(0, 16);\n const directory = join(releases, id);\n if (!existsSync(directory)) {\n await mkdir(releases, { recursive: true });\n const staging = await mkdtemp(join(releases, \".upload-\"));\n try {\n for (const file of files) {\n await mkdir(dirname(join(staging, file.path)), { recursive: true });\n // Uploads lose their mode; the server must stay executable outside Windows.\n await writeFile(join(staging, file.path), file.content, {\n mode: file.path === manifest.server ? 0o755 : 0o644,\n });\n }\n await writeFile(join(staging, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n await rename(staging, directory);\n } catch (cause) {\n await rm(staging, { recursive: true, force: true });\n throw cause;\n }\n }\n return { id, directory, manifest };\n};\n\nexport const loadRelease = async (\n releases: string,\n id: string,\n): Promise<{ id: string; directory: string; manifest: ReleaseManifest }> => {\n const directory = join(releases, id);\n const manifest = releaseManifestSchema.parse(\n JSON.parse(await readFile(join(directory, \"manifest.json\"), \"utf8\")),\n );\n return { id, directory, manifest };\n};\n",
9
9
  "import type { Subprocess } from \"bun\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst healthyWithinMs = 60_000;\n/** Without a health URL, a server that stays up this long counts as started. */\nconst settleMs = 5000;\nconst restartDelayMs = 2000;\n\n/**\n * Runs the deployed server executable, restarting it whenever it exits, and swaps it for\n * another release's. The server reads its own environment and secrets, as it would anywhere.\n */\nexport const createServerSupervisor = (options: {\n /** The server's `/health` route, which answers once it is listening. */\n healthUrl?: string;\n log: (message: string) => void;\n}) => {\n let current: { executable: string; process: Subprocess } | undefined;\n\n const spawn = (executable: string): Subprocess => {\n const child = Bun.spawn([executable], {\n cwd: dirname(executable),\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n onExit: (_, code) => {\n // `stop` and `replace` clear or change `current` before killing a server.\n if (current?.process !== child) return;\n options.log(`Server exited (${code}); restarting it in ${restartDelayMs / 1000} s`);\n void delay(restartDelayMs).then(() => {\n if (current?.process === child) current = { executable, process: spawn(executable) };\n });\n },\n });\n return child;\n };\n\n const start = (executable: string) => {\n current = { executable, process: spawn(executable) };\n return current.process;\n };\n\n const stop = async () => {\n const running = current;\n current = undefined;\n if (!running) return;\n running.process.kill();\n await running.process.exited;\n };\n\n const healthy = async (child: Subprocess) => {\n if (!options.healthUrl) {\n await delay(settleMs);\n return child.exitCode === null;\n }\n const deadline = Date.now() + healthyWithinMs;\n while (Date.now() < deadline && child.exitCode === null) {\n if (\n await fetch(options.healthUrl).then(\n (response) => response.ok,\n () => false,\n )\n )\n return true;\n await delay(1000);\n }\n return false;\n };\n\n return {\n start,\n stop,\n /** Replaces the running server; if the new one doesn't come up, the previous one runs again. */\n replace: async (executable: string) => {\n const previous = current?.executable;\n await stop();\n let failure: unknown;\n const started = await (async () => healthy(start(executable)))().catch((error: unknown) => {\n failure = error;\n return false;\n });\n if (started) return;\n await stop();\n if (previous) start(previous);\n const reason =\n failure instanceof Error\n ? failure.message\n : `it did not start${options.healthUrl ? ` answering ${options.healthUrl}` : \"\"}`;\n throw new Error(\n `The new server failed: ${reason}. ${previous ? \"The previous one is running again.\" : \"\"}`.trim(),\n { cause: failure },\n );\n },\n status: () =>\n current && { executable: current.executable, running: current.process.exitCode === null },\n };\n};\n"
10
10
  ],
11
- "mappings": "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",
12
- "debugId": "3E53D86CAC15F1B264756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "B85D90377F39CD9264756E2164756E21",
13
13
  "names": []
14
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsplc/agent",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "The tsPLC plant agent: deploys a program and its server to a controller on the plant network, and holds an engineering login for reads, writes and forces.",
@@ -37,8 +37,8 @@
37
37
  "bun": ">=1.4.3"
38
38
  },
39
39
  "dependencies": {
40
- "@tsplc/build": "0.2.6",
41
- "@tsplc/config": "0.2.6",
40
+ "@tsplc/build": "0.2.9",
41
+ "@tsplc/config": "0.2.9",
42
42
  "zod": "4.3.6"
43
43
  },
44
44
  "bin": {
package/src/agent.ts CHANGED
@@ -12,7 +12,8 @@ import {
12
12
  loginCommandSchema,
13
13
  openControllerLogin,
14
14
  resolveConfig,
15
- updateController,
15
+ startWarmController,
16
+ updateWarmController,
16
17
  } from "@tsplc/build";
17
18
  import { z } from "zod";
18
19
  import { discoverControllers, networkInterfaces } from "./discovery";
@@ -42,6 +43,8 @@ const network = "tsplc-agent";
42
43
  const codesysNetwork = "tsplc-agent-codesys";
43
44
  const gateway = { host: "tsplc-agent-gateway", port: 1217 };
44
45
  const loginContainer = "tsplc-agent-login";
46
+ /** Keeps CODESYS running between deployments, so each skips starting it. */
47
+ const deployContainer = "tsplc-agent-deploy";
45
48
  /** CODESYS reads the controller user from these for one operation; the agent never stores it. */
46
49
  const credentialNames = {
47
50
  usernameEnv: "TSPLC_DEVICE_USERNAME",
@@ -190,6 +193,19 @@ export const createAgent = async (options: AgentOptions) => {
190
193
  return loadRelease(paths.releases, release.id);
191
194
  };
192
195
 
196
+ /** CODESYS starts for the deployed release in the background, so the first deployment finds it running. */
197
+ const warming = (async () => {
198
+ const target = await readJson(paths.target, targetSchema);
199
+ if (!deployed || !target) return;
200
+ await ensureGateway();
201
+ const release = await loadRelease(paths.releases, deployed.id);
202
+ await startWarmController(controllerConfig(release, target), deployContainer);
203
+ })().catch((error: unknown) => {
204
+ options.log(
205
+ `Starting CODESYS failed: ${error instanceof Error ? error.message : String(error)}`,
206
+ );
207
+ });
208
+
193
209
  /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */
194
210
  const operation = (
195
211
  name: string,
@@ -260,12 +276,14 @@ export const createAgent = async (options: AgentOptions) => {
260
276
  await server.replace(join(paths.releases, serverPath));
261
277
  }
262
278
  const kind = settings.download ? "download" : "online-change";
263
- emit({ kind: "progress", message: `Starting the ${kind}; CODESYS takes minutes to start` });
279
+ emit({ kind: "progress", message: `Starting the ${kind}` });
264
280
  await ensureGateway();
281
+ await warming;
265
282
  const stopFollowing = followProgress(paths.controller, emit);
266
- const receipt = await withCredentials(settings.credentials, () =>
267
- updateController(config, kind, { initializeUser: settings.initializeUser }),
268
- )
283
+ const receipt = await updateWarmController(config, deployContainer, kind, {
284
+ initializeUser: settings.initializeUser,
285
+ credentials: settings.credentials,
286
+ })
269
287
  .catch(async (failure: unknown) => {
270
288
  if (serverPath) {
271
289
  emit({ kind: "progress", message: "Restoring the previous server" });