paratix 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -698,7 +698,7 @@ async function loadServerDefinitionFromFile(file, options) {
698
698
  return definition;
699
699
  }
700
700
  var program = new Command();
701
- program.name("paratix").description("Idempotent VPS setup tool in TypeScript").version("0.8.0-93d397c");
701
+ program.name("paratix").description("Idempotent VPS setup tool in TypeScript").version("0.9.0-e478726");
702
702
  program.command("apply <file>").description("Apply a server definition").option(
703
703
  "--dry-run",
704
704
  "Only check, do not apply. Some modules validate prospective config but cannot verify runtime restarts.",
@@ -710,7 +710,7 @@ program.command("apply <file>").description("Apply a server definition").option(
710
710
  DEFAULT_RECONNECT_TIMEOUT_SECONDS
711
711
  ).option("--verbose", "Show full stack traces on error", false).action(async (file, options) => {
712
712
  try {
713
- printCliHeader("0.8.0-93d397c");
713
+ printCliHeader("0.9.0-e478726");
714
714
  const environmentOverrides = applyCliEnvironmentOverrides(
715
715
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Commander options typed as Record<string, unknown>
716
716
  options.env,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { E as Environment, M as Module, a as ModuleMetaEntry, b as MetaEnvironmentValue, c as EnvironmentMetaEntry, d as SshdPortMetaEntry, e as SystemHostMetaEntry, f as SystemRebootMetaEntry, g as ModuleResult, h as ExecResult, i as ModuleStatus, j as SshConnection, O as OrchestrationStep, S as ServerDefinition } from './types-Cl2Muw1x.js';
2
2
  export { k as EnvironmentValue, l as ExecOptions, N as NEEDS_APPLY, m as SshConfig } from './types-Cl2Muw1x.js';
3
- export { a as apt, b as archive, c as command, d as compose, e as cron, f as download, g as file, h as git, i as group, j as hostname, m as mount, n as net, o as op, p as package, q as quadlet, r as releaseUpgrade, k as rsync, s as script, l as service, t as ssh, u as sshd, v as sysctl, w as system, x as systemd, y as ufw, z as user } from './user-BJMqDePy.js';
3
+ export { a as apt, b as archive, c as command, d as compose, e as cron, f as download, g as file, h as git, i as group, j as hostname, m as mount, n as net, o as op, p as package, q as quadlet, r as releaseUpgrade, k as rsync, s as script, l as service, t as ssh, u as sshd, v as sysctl, w as system, x as systemd, y as ufw, z as user } from './user-B9lkXr0X.js';
4
4
 
5
5
  /**
6
6
  * Fail the run if a condition on the current env is not satisfied.
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  systemd,
40
40
  ufw,
41
41
  user
42
- } from "./chunk-FFQ6FR4N.js";
42
+ } from "./chunk-7Y2RBVG4.js";
43
43
  import {
44
44
  CommandError,
45
45
  assertValidModuleMetaEntries,
@@ -1,4 +1,4 @@
1
- export { a as apt, b as archive, c as command, d as compose, e as cron, f as download, g as file, h as git, i as group, j as hostname, m as mount, n as net, o as op, p as package, q as quadlet, r as releaseUpgrade, k as rsync, s as script, l as service, t as ssh, u as sshd, v as sysctl, w as system, x as systemd, y as ufw, z as user } from '../user-BJMqDePy.js';
1
+ export { U as UpgradeOptions, a as apt, b as archive, c as command, d as compose, e as cron, f as download, g as file, h as git, i as group, j as hostname, m as mount, n as net, o as op, p as package, q as quadlet, r as releaseUpgrade, k as rsync, s as script, l as service, t as ssh, u as sshd, v as sysctl, w as system, x as systemd, y as ufw, z as user } from '../user-B9lkXr0X.js';
2
2
  import { M as Module } from '../types-Cl2Muw1x.js';
3
3
 
4
4
  /**
@@ -26,7 +26,7 @@ import {
26
26
  systemd,
27
27
  ufw,
28
28
  user
29
- } from "../chunk-FFQ6FR4N.js";
29
+ } from "../chunk-7Y2RBVG4.js";
30
30
  import "../chunk-NRDLYHJL.js";
31
31
  export {
32
32
  apt,
@@ -1,5 +1,108 @@
1
1
  import { M as Module } from './types-Cl2Muw1x.js';
2
2
 
3
+ /** Per-call overrides for package operations that can take a long time. */
4
+ type UpgradeOptions = {
5
+ /** Override the SSH layer's command timeout (milliseconds). */
6
+ timeout?: number;
7
+ };
8
+ /**
9
+ * Distro-agnostic package management module.
10
+ *
11
+ * Automatically detects the system package manager (apt, dnf, yum, apk)
12
+ * and delegates to the appropriate commands. All methods are idempotent.
13
+ *
14
+ * For Debian/Ubuntu-specific configuration (debconf pre-seeding, GPG keys,
15
+ * apt repositories) use the `apt` module instead.
16
+ *
17
+ * @example
18
+ * // Install packages
19
+ * pkg.installed("git", "curl")
20
+ *
21
+ * @example
22
+ * // Refresh package lists and upgrade all packages on a specific date
23
+ * pkg.update("2024-01-15")
24
+ * pkg.upgrade("2024-01-15")
25
+ */
26
+ declare const pkg: {
27
+ /**
28
+ * Ensure the given packages are not installed.
29
+ *
30
+ * The check phase queries the package database for each package individually;
31
+ * the remove command is only executed when at least one package is present.
32
+ *
33
+ * Pass an `UpgradeOptions` object as the last argument to override the SSH
34
+ * timeout for slow remove operations.
35
+ *
36
+ * @param packagesAndOptions - One or more package names, optionally followed
37
+ * by an `UpgradeOptions` object as the last argument.
38
+ * @returns A Module that removes the packages if any are present.
39
+ *
40
+ * @example
41
+ * pkg.absent("vim", "nano")
42
+ * pkg.absent("vim", "nano", { timeout: 600_000 })
43
+ */
44
+ absent(...packagesAndOptions: Array<string | UpgradeOptions>): Module;
45
+ /**
46
+ * Ensure the given packages are installed.
47
+ *
48
+ * The check phase queries the package database for each package individually;
49
+ * the install command is only executed when at least one package is missing.
50
+ *
51
+ * Pass an `UpgradeOptions` object as the last argument to override the SSH
52
+ * timeout for slow install operations.
53
+ *
54
+ * @param packagesAndOptions - One or more package names, optionally followed
55
+ * by an `UpgradeOptions` object as the last argument.
56
+ * @returns A Module that installs missing packages.
57
+ *
58
+ * @example
59
+ * pkg.installed("git", "curl", "unzip")
60
+ * pkg.installed("texlive-full", { timeout: 900_000 })
61
+ */
62
+ installed(...packagesAndOptions: Array<string | UpgradeOptions>): Module;
63
+ /**
64
+ * Refresh the package manager's package lists once per dated flag.
65
+ *
66
+ * A flag file at `${FLAGS_DIRECTORY}/package-update-<date>` is created after
67
+ * a successful run. On the next run the flag is detected and the module
68
+ * reports `"ok"` without running the update again. Changing `date` to a new
69
+ * value invalidates all previous flags for this operation.
70
+ *
71
+ * @param date - A date string used as the idempotency key (e.g. `"2024-01-15"`).
72
+ * @param options - Optional per-call overrides (e.g. SSH command `timeout`).
73
+ * @returns A Module that refreshes package lists.
74
+ *
75
+ * @example
76
+ * pkg.update("2024-01-15")
77
+ * pkg.update("2024-01-15", { timeout: 600_000 })
78
+ */
79
+ update(date: string, options?: UpgradeOptions): Module;
80
+ /**
81
+ * Upgrade all installed packages once per dated flag.
82
+ *
83
+ * A flag file at `${FLAGS_DIRECTORY}/package-upgrade-<date>` is created after
84
+ * a successful run. On the next run the flag is detected and the module
85
+ * reports `"ok"` without running the upgrade again. Changing `date` to a new
86
+ * value invalidates all previous flags for this operation.
87
+ *
88
+ * On apt systems this runs `dpkg --configure -a`, `apt-get update`, and
89
+ * `apt-get upgrade -y` as three separate commands (each subject to its own
90
+ * SSH `timeout`). For full dependency resolution use `apt.distUpgrade`.
91
+ *
92
+ * @param date - A date string used as the idempotency key (e.g. `"2024-01-15"`).
93
+ * @param options - Optional per-call overrides (e.g. SSH command `timeout`).
94
+ * The same `timeout` is applied to every step of the upgrade pipeline.
95
+ * @returns A Module that upgrades all packages.
96
+ *
97
+ * @example
98
+ * pkg.upgrade("2024-01-15")
99
+ * pkg.upgrade("2024-01-15", { timeout: 900_000 })
100
+ *
101
+ * @see apt.distUpgrade
102
+ */
103
+ upgrade(date: string, options?: UpgradeOptions): Module;
104
+ };
105
+
3
106
  /**
4
107
  * Modules for Debian/Ubuntu-specific apt configuration.
5
108
  *
@@ -35,10 +138,19 @@ declare const apt: {
35
138
  * Run `apt-get update && apt-get dist-upgrade` once per dated flag.
36
139
  * Performs a full distribution upgrade with dependency resolution.
37
140
  *
141
+ * The pipeline is split into three separate SSH commands so that each step
142
+ * gets its own timeout window and produces a precise failure label.
143
+ *
38
144
  * @param date - A date string used as the idempotency key (e.g. `"2024-01-15"`).
145
+ * @param options - Optional per-call overrides (e.g. SSH command `timeout`).
146
+ * The same `timeout` is applied to every step of the dist-upgrade pipeline.
39
147
  * @returns A Module that performs the dist-upgrade.
148
+ *
149
+ * @example
150
+ * apt.distUpgrade("2024-01-15")
151
+ * apt.distUpgrade("2024-01-15", { timeout: 900_000 })
40
152
  */
41
- distUpgrade(date: string): Module;
153
+ distUpgrade(date: string, options?: UpgradeOptions): Module;
42
154
  /**
43
155
  * Import a GPG key into `/etc/apt/keyrings/` for use with signed repositories.
44
156
  * @param name - Key file name (without `.gpg` extension).
@@ -811,88 +923,6 @@ declare const op: {
811
923
  resolve(references: Record<string, string>): Module;
812
924
  };
813
925
 
814
- /**
815
- * Distro-agnostic package management module.
816
- *
817
- * Automatically detects the system package manager (apt, dnf, yum, apk)
818
- * and delegates to the appropriate commands. All methods are idempotent.
819
- *
820
- * For Debian/Ubuntu-specific configuration (debconf pre-seeding, GPG keys,
821
- * apt repositories) use the `apt` module instead.
822
- *
823
- * @example
824
- * // Install packages
825
- * pkg.installed("git", "curl")
826
- *
827
- * @example
828
- * // Refresh package lists and upgrade all packages on a specific date
829
- * pkg.update("2024-01-15")
830
- * pkg.upgrade("2024-01-15")
831
- */
832
- declare const pkg: {
833
- /**
834
- * Ensure the given packages are not installed.
835
- *
836
- * The check phase queries the package database for each package individually;
837
- * the remove command is only executed when at least one package is present.
838
- *
839
- * @param packages - One or more package names to remove.
840
- * @returns A Module that removes the packages if any are present.
841
- *
842
- * @example
843
- * pkg.absent("vim", "nano")
844
- */
845
- absent(...packages: string[]): Module;
846
- /**
847
- * Ensure the given packages are installed.
848
- *
849
- * The check phase queries the package database for each package individually;
850
- * the install command is only executed when at least one package is missing.
851
- *
852
- * @param packages - One or more package names to install.
853
- * @returns A Module that installs missing packages.
854
- *
855
- * @example
856
- * pkg.installed("git", "curl", "unzip")
857
- */
858
- installed(...packages: string[]): Module;
859
- /**
860
- * Refresh the package manager's package lists once per dated flag.
861
- *
862
- * A flag file at `${FLAGS_DIRECTORY}/package-update-<date>` is created after
863
- * a successful run. On the next run the flag is detected and the module
864
- * reports `"ok"` without running the update again. Changing `date` to a new
865
- * value invalidates all previous flags for this operation.
866
- *
867
- * @param date - A date string used as the idempotency key (e.g. `"2024-01-15"`).
868
- * @returns A Module that refreshes package lists.
869
- *
870
- * @example
871
- * pkg.update("2024-01-15")
872
- */
873
- update(date: string): Module;
874
- /**
875
- * Upgrade all installed packages once per dated flag.
876
- *
877
- * A flag file at `${FLAGS_DIRECTORY}/package-upgrade-<date>` is created after
878
- * a successful run. On the next run the flag is detected and the module
879
- * reports `"ok"` without running the upgrade again. Changing `date` to a new
880
- * value invalidates all previous flags for this operation.
881
- *
882
- * On apt systems this runs `apt-get update && apt-get upgrade -y` (not
883
- * `dist-upgrade`); use `apt.distUpgrade` for full dependency resolution.
884
- *
885
- * @param date - A date string used as the idempotency key (e.g. `"2024-01-15"`).
886
- * @returns A Module that upgrades all packages.
887
- *
888
- * @example
889
- * pkg.upgrade("2024-01-15")
890
- *
891
- * @see apt.distUpgrade
892
- */
893
- upgrade(date: string): Module;
894
- };
895
-
896
926
  type QuadletAutoUpdate = "local" | "registry";
897
927
  type QuadletHealthOnFailure = "kill" | "none" | "restart" | "stop";
898
928
  type QuadletPullPolicy = "always" | "missing" | "never" | "newer";
@@ -1440,4 +1470,4 @@ declare const user: {
1440
1470
  present(name: string, options?: UserOptions): Module;
1441
1471
  };
1442
1472
 
1443
- export { apt as a, archive as b, command as c, compose as d, cron as e, download as f, file as g, git as h, group as i, hostname as j, rsync as k, service as l, mount as m, net as n, op as o, pkg as p, quadlet as q, releaseUpgrade as r, script as s, ssh as t, sshd as u, sysctl as v, system as w, systemd as x, ufw as y, user as z };
1473
+ export { type UpgradeOptions as U, apt as a, archive as b, command as c, compose as d, cron as e, download as f, file as g, git as h, group as i, hostname as j, rsync as k, service as l, mount as m, net as n, op as o, pkg as p, quadlet as q, releaseUpgrade as r, script as s, ssh as t, sshd as u, sysctl as v, system as w, systemd as x, ufw as y, user as z };
package/llm-guide.md CHANGED
@@ -133,7 +133,7 @@ export default server({
133
133
  | Method | Signature | Idempotent |
134
134
  | ----------------- | ---------------------------------------------------------------------------------------- | -------------------- |
135
135
  | `apt.debconf` | `(packageName: string, selections: Record<string, string>): Module` | Yes |
136
- | `apt.distUpgrade` | `(date: string): Module` | Yes (versioned flag) |
136
+ | `apt.distUpgrade` | `(date: string, options?: UpgradeOptions): Module` | Yes (versioned flag) |
137
137
  | `apt.key` | `(name: string, url: string, options: { fingerprint: string }): Module` | Yes |
138
138
  | `apt.repository` | `(nameOrPpa: string, source?: string, options?: { signedBy?: false \| string }): Module` | Yes |
139
139
 
@@ -227,12 +227,32 @@ export default server({
227
227
 
228
228
  Import with renaming: `import { package as pkg } from "paratix/modules"`. The word `package` is reserved in JavaScript, so you must alias it.
229
229
 
230
- | Method | Signature | Idempotent |
231
- | ------------------- | --------------------------------- | -------------------- |
232
- | `package.installed` | `(...packages: string[]): Module` | Yes |
233
- | `package.absent` | `(...packages: string[]): Module` | Yes |
234
- | `package.update` | `(date: string): Module` | Yes (versioned flag) |
235
- | `package.upgrade` | `(date: string): Module` | Yes (versioned flag) |
230
+ | Method | Signature | Idempotent |
231
+ | ------------------- | ------------------------------------------------------------------ | -------------------- |
232
+ | `package.installed` | `(...packagesAndOptions: Array<string \| UpgradeOptions>): Module` | Yes |
233
+ | `package.absent` | `(...packagesAndOptions: Array<string \| UpgradeOptions>): Module` | Yes |
234
+ | `package.update` | `(date: string, options?: UpgradeOptions): Module` | Yes (versioned flag) |
235
+ | `package.upgrade` | `(date: string, options?: UpgradeOptions): Module` | Yes (versioned flag) |
236
+
237
+ #### `UpgradeOptions`
238
+
239
+ ```typescript
240
+ type UpgradeOptions = {
241
+ timeout?: number // Override SSH command timeout (ms). Same value applies to every step
242
+ // of multi-step pipelines (apt upgrade, apk upgrade, apt dist-upgrade).
243
+ }
244
+ ```
245
+
246
+ For `package.installed` / `package.absent`, pass the options object as the **last** argument
247
+ after the package names; existing variadic call sites such as `pkg.installed("git", "curl")`
248
+ keep working unchanged. Use a longer `timeout` for slow operations on production servers
249
+ with large update backlogs:
250
+
251
+ ```typescript
252
+ pkg.upgrade("2026-05-01", { timeout: 900_000 })
253
+ pkg.installed("texlive-full", { timeout: 900_000 })
254
+ apt.distUpgrade("2026-05-01", { timeout: 1_200_000 })
255
+ ```
236
256
 
237
257
  ### `quadlet`
238
258
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paratix",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Idempotent VPS setup tool in TypeScript",
5
5
  "type": "module",
6
6
  "files": [