@highstate/library 0.9.16 → 0.9.19

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.
Files changed (82) hide show
  1. package/dist/highstate.library.msgpack +0 -0
  2. package/dist/index.js +3548 -2985
  3. package/dist/index.js.map +1 -1
  4. package/package.json +5 -5
  5. package/src/common/access-point.ts +105 -0
  6. package/src/common/files.ts +137 -0
  7. package/src/common/index.ts +3 -0
  8. package/src/common/server.ts +231 -0
  9. package/src/databases/index.ts +4 -0
  10. package/src/databases/mariadb.ts +37 -0
  11. package/src/databases/mongodb.ts +37 -0
  12. package/src/databases/postgresql.ts +37 -0
  13. package/src/databases/shared.ts +61 -0
  14. package/src/distributions/ubuntu.ts +13 -11
  15. package/src/dns.ts +116 -18
  16. package/src/git.ts +14 -10
  17. package/src/impl-ref.ts +26 -0
  18. package/src/index.ts +14 -15
  19. package/src/k3s.ts +14 -12
  20. package/src/k8s/apps/code-server.ts +48 -0
  21. package/src/k8s/apps/gitea.ts +25 -0
  22. package/src/k8s/apps/grocy.ts +39 -0
  23. package/src/k8s/apps/hubble.ts +30 -0
  24. package/src/{apps → k8s/apps}/index.ts +16 -13
  25. package/src/k8s/apps/kubernetes-dashboard.ts +28 -0
  26. package/src/k8s/apps/mariadb.ts +83 -0
  27. package/src/k8s/apps/maybe.ts +39 -0
  28. package/src/k8s/apps/mongodb.ts +84 -0
  29. package/src/k8s/apps/postgresql.ts +86 -0
  30. package/src/k8s/apps/shared.ts +149 -0
  31. package/src/k8s/apps/syncthing.ts +72 -0
  32. package/src/k8s/apps/traefik.ts +40 -0
  33. package/src/k8s/apps/vaultwarden.ts +31 -0
  34. package/src/k8s/apps/workload.ts +214 -0
  35. package/src/k8s/apps/zitadel.ts +26 -0
  36. package/src/k8s/cert-manager.ts +80 -0
  37. package/src/k8s/cilium.ts +64 -0
  38. package/src/k8s/gateway.ts +70 -0
  39. package/src/k8s/index.ts +9 -0
  40. package/src/{obfuscators → k8s/obfuscators}/phantun.ts +14 -10
  41. package/src/{obfuscators → k8s/obfuscators}/shared.ts +17 -11
  42. package/src/k8s/resources.ts +111 -0
  43. package/src/k8s/service.ts +65 -0
  44. package/src/k8s/shared.ts +343 -0
  45. package/src/k8s/workload.ts +77 -0
  46. package/src/network.ts +249 -63
  47. package/src/nixos.ts +38 -77
  48. package/src/proxmox.ts +203 -96
  49. package/src/restic.ts +28 -19
  50. package/src/sops.ts +19 -8
  51. package/src/ssh.ts +122 -24
  52. package/src/talos.ts +21 -19
  53. package/src/third-party/cloudflare.ts +59 -0
  54. package/src/third-party/index.ts +3 -0
  55. package/src/{mullvad.ts → third-party/mullvad.ts} +11 -9
  56. package/src/third-party/timeweb.ts +99 -0
  57. package/src/utils.ts +27 -6
  58. package/src/wireguard.ts +249 -115
  59. package/src/apps/code-server.ts +0 -34
  60. package/src/apps/deployment.ts +0 -60
  61. package/src/apps/dns.ts +0 -107
  62. package/src/apps/gitea.ts +0 -18
  63. package/src/apps/grocy.ts +0 -20
  64. package/src/apps/hubble.ts +0 -20
  65. package/src/apps/kubernetes-dashboard.ts +0 -19
  66. package/src/apps/mariadb.ts +0 -81
  67. package/src/apps/maybe.ts +0 -25
  68. package/src/apps/mongodb.ts +0 -81
  69. package/src/apps/network.ts +0 -55
  70. package/src/apps/postgresql.ts +0 -81
  71. package/src/apps/shared.ts +0 -290
  72. package/src/apps/syncthing.ts +0 -54
  73. package/src/apps/test.ts +0 -19
  74. package/src/apps/traefik.ts +0 -36
  75. package/src/apps/vaultwarden.ts +0 -23
  76. package/src/apps/zitadel.ts +0 -21
  77. package/src/cloudflare.ts +0 -26
  78. package/src/common.ts +0 -200
  79. package/src/files.ts +0 -146
  80. package/src/k8s.ts +0 -638
  81. package/src/timeweb.ts +0 -75
  82. package/src/{obfuscators → k8s/obfuscators}/index.ts +1 -1
package/src/ssh.ts CHANGED
@@ -1,17 +1,37 @@
1
- import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
- import { l4EndpointEntity } from "./network"
3
- import { fileEntity } from "./files"
1
+ import { $inputs, $secrets, defineEntity, defineUnit, z } from "@highstate/contract"
2
+ import { fileEntity } from "./common/files"
3
+ import { l4EndpointEntity, portSchema } from "./network"
4
4
 
5
- export const keyTypeSchema = Type.StringEnum(["ed25519"])
5
+ export const keyTypeSchema = z.enum(["ed25519"])
6
6
 
7
+ /**
8
+ * The entity representing an SSH key pair.
9
+ */
7
10
  export const keyPairEntity = defineEntity({
8
- type: "ssh.key-pair",
11
+ type: "ssh.key-pair.v1",
9
12
 
10
- schema: Type.Object({
13
+ schema: z.object({
14
+ /**
15
+ * The type of the SSH key.
16
+ *
17
+ * For now, only `ed25519` is supported.
18
+ */
11
19
  type: keyTypeSchema,
12
- fingerprint: Type.String(),
13
- publicKey: Type.String(),
14
- privateKey: Type.String(),
20
+
21
+ /**
22
+ * The fingerprint of the SSH key.
23
+ */
24
+ fingerprint: z.string(),
25
+
26
+ /**
27
+ * The public key in OpenSSH format.
28
+ */
29
+ publicKey: z.string(),
30
+
31
+ /**
32
+ * The private key in PEM format.
33
+ */
34
+ privateKey: z.string(),
15
35
  }),
16
36
 
17
37
  meta: {
@@ -19,19 +39,97 @@ export const keyPairEntity = defineEntity({
19
39
  },
20
40
  })
21
41
 
22
- export const credentialsSchema = Type.Object({
23
- endpoints: Type.Array(l4EndpointEntity.schema),
24
- hostKey: Type.String(),
25
- user: Type.String(),
26
- password: Type.Optional(Type.String()),
27
- keyPair: Type.Optional(keyPairEntity.schema),
42
+ /**
43
+ * The schema for the SSH connection configuration.
44
+ *
45
+ * Contains enough information to connect to an SSH server.
46
+ */
47
+ export const connectionSchema = z.object({
48
+ /**
49
+ * The list of L4 endpoints which can be used to connect to the SSH server.
50
+ */
51
+ endpoints: l4EndpointEntity.schema.array(),
52
+
53
+ /**
54
+ * The host key of the SSH server which will be used to verify the server's identity.
55
+ */
56
+ hostKey: z.string(),
57
+
58
+ /**
59
+ * The user to connect as.
60
+ */
61
+ user: z.string(),
62
+
63
+ /**
64
+ * The password to use for authentication.
65
+ */
66
+ password: z.string().optional(),
67
+
68
+ /**
69
+ * The SSH key pair to use for authentication.
70
+ */
71
+ keyPair: keyPairEntity.schema.optional(),
72
+ })
73
+
74
+ export const argsSchema = z.object({
75
+ /**
76
+ * Whether the SSH is enabled on the server.
77
+ *
78
+ * If set to `false`, all SSH-related functionality will be disabled.
79
+ */
80
+ enabled: z.boolean().default(true),
81
+
82
+ /**
83
+ * The alternate host to connect to.
84
+ */
85
+ host: z.string().optional(),
86
+
87
+ /**
88
+ * The SSH port to connect to.
89
+ */
90
+ port: portSchema.default(22),
91
+
92
+ /**
93
+ * The SSH user to connect as.
94
+ */
95
+ user: z.string().default("root"),
96
+ })
97
+
98
+ export const secrets = $secrets({
99
+ /**
100
+ * The SSH private key in PEM format.
101
+ */
102
+ sshPrivateKey: z.string().optional().meta({ multiline: true }),
103
+
104
+ /**
105
+ * The SSH password to use for authentication.
106
+ */
107
+ sshPassword: z.string().optional(),
108
+ })
109
+
110
+ export const inputs = $inputs({
111
+ /**
112
+ * The SSH key pair to use for authentication.
113
+ */
114
+ sshKeyPair: {
115
+ entity: keyPairEntity,
116
+ required: false,
117
+ },
28
118
  })
29
119
 
120
+ /**
121
+ * Holds the ED25519 SSH key pair and generates the private key if not provided.
122
+ */
30
123
  export const keyPair = defineUnit({
31
- type: "ssh.key-pair",
124
+ type: "ssh.key-pair.v1",
32
125
 
33
126
  secrets: {
34
- privateKey: Type.Optional(Type.String()),
127
+ /**
128
+ * The SSH private key in PEM format.
129
+ *
130
+ * If not provided, a new key pair will be generated and stored.
131
+ */
132
+ privateKey: z.string().optional().meta({ multiline: true }),
35
133
  },
36
134
 
37
135
  outputs: {
@@ -40,11 +138,10 @@ export const keyPair = defineUnit({
40
138
  },
41
139
 
42
140
  meta: {
43
- displayName: "SSH Key Pair",
44
- description: "Holds the ED25519 SSH key pair and generates the private key if not provided.",
141
+ title: "SSH Key Pair",
45
142
  category: "ssh",
46
- primaryIcon: "charm:key",
47
- primaryIconColor: "#ffffff",
143
+ icon: "charm:key",
144
+ iconColor: "#ffffff",
48
145
  secondaryIcon: "mdi:lock",
49
146
  secondaryIconColor: "#ffffff",
50
147
  },
@@ -55,6 +152,7 @@ export const keyPair = defineUnit({
55
152
  },
56
153
  })
57
154
 
58
- export type KeyType = Static<typeof keyTypeSchema>
59
- export type Credentials = Static<typeof credentialsSchema>
60
- export type KeyPair = Static<typeof keyPairEntity.schema>
155
+ export type Args = z.infer<typeof argsSchema>
156
+ export type KeyType = z.infer<typeof keyTypeSchema>
157
+ export type KeyPair = z.infer<typeof keyPairEntity.schema>
158
+ export type Connection = z.infer<typeof connectionSchema>
package/src/talos.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { defineEntity, defineUnit, Type } from "@highstate/contract"
2
- import { clusterInputs, clusterOutputs, scheduleOnMastersPolicyArgs } from "./k8s"
1
+ import { defineEntity, defineUnit, z } from "@highstate/contract"
2
+ import { clusterInputs, clusterOutputs, scheduleOnMastersPolicyArgs } from "./k8s/shared"
3
3
 
4
4
  export const clusterEntity = defineEntity({
5
- type: "talos.cluster",
5
+ type: "talos.cluster.v1",
6
6
 
7
- schema: Type.Object({
8
- clientConfiguration: Type.String(),
9
- machineSecrets: Type.String(),
7
+ schema: z.object({
8
+ clientConfiguration: z.string(),
9
+ machineSecrets: z.string(),
10
10
  }),
11
11
 
12
12
  meta: {
@@ -14,11 +14,14 @@ export const clusterEntity = defineEntity({
14
14
  },
15
15
  })
16
16
 
17
- export const cniSchema = Type.StringEnum(["none", "cilium", "flannel"])
18
- export const csiSchema = Type.StringEnum(["none", "local-path-provisioner"])
17
+ export const cniSchema = z.enum(["none", "cilium", "flannel"])
18
+ export const csiSchema = z.enum(["none", "local-path-provisioner"])
19
19
 
20
+ /**
21
+ * The Talos cluster created on top of the server.
22
+ */
20
23
  export const cluster = defineUnit({
21
- type: "talos.cluster",
24
+ type: "talos.cluster.v1",
22
25
 
23
26
  args: {
24
27
  ...scheduleOnMastersPolicyArgs,
@@ -28,7 +31,7 @@ export const cluster = defineUnit({
28
31
  *
29
32
  * By default, the name of the instance is used.
30
33
  */
31
- clusterName: Type.Optional(Type.String()),
34
+ clusterName: z.string().optional(),
32
35
 
33
36
  /**
34
37
  * The CNI plugin to use.
@@ -40,7 +43,7 @@ export const cluster = defineUnit({
40
43
  *
41
44
  * The "cilium" CNI plugin is recommended to cover advanced network policies like FQDNs.
42
45
  */
43
- cni: Type.Default(cniSchema, "cilium"),
46
+ cni: cniSchema.default("cilium"),
44
47
 
45
48
  /**
46
49
  * The CSI plugin to use.
@@ -49,25 +52,25 @@ export const cluster = defineUnit({
49
52
  * - "local-path-provisioner" (default)
50
53
  * - "none" (disable CSI, must be installed manually if needed)
51
54
  */
52
- csi: Type.Default(csiSchema, "local-path-provisioner"),
55
+ csi: csiSchema.default("local-path-provisioner"),
53
56
 
54
57
  /**
55
58
  * The shared configuration patch.
56
59
  * It will be applied to all nodes.
57
60
  */
58
- sharedConfigPatch: Type.Optional(Type.Record(Type.String(), Type.Any())),
61
+ sharedConfigPatch: z.record(z.string(), z.any()).optional(),
59
62
 
60
63
  /**
61
64
  * The master configuration patch.
62
65
  * It will be applied to all master nodes.
63
66
  */
64
- masterConfigPatch: Type.Optional(Type.Record(Type.String(), Type.Any())),
67
+ masterConfigPatch: z.record(z.string(), z.any()).optional(),
65
68
 
66
69
  /**
67
70
  * The worker configuration patch.
68
71
  * It will be applied to all worker nodes.
69
72
  */
70
- workerConfigPatch: Type.Optional(Type.Record(Type.String(), Type.Any())),
73
+ workerConfigPatch: z.record(z.string(), z.any()).optional(),
71
74
 
72
75
  /**
73
76
  * Whether to enable the Tun device plugin.
@@ -76,7 +79,7 @@ export const cluster = defineUnit({
76
79
  *
77
80
  * By default, this option is set to true.
78
81
  */
79
- enableTunDevicePlugin: Type.Default(Type.Boolean(), true),
82
+ enableTunDevicePlugin: z.boolean().default(true),
80
83
  },
81
84
 
82
85
  inputs: clusterInputs,
@@ -87,11 +90,10 @@ export const cluster = defineUnit({
87
90
  },
88
91
 
89
92
  meta: {
90
- displayName: "Talos Cluster",
91
- description: "A Kubernetes cluster managed by Talos.",
93
+ title: "Talos Cluster",
92
94
  category: "Talos",
93
95
  color: "#2d2d2d",
94
- primaryIcon: "simple-icons:talos",
96
+ icon: "simple-icons:talos",
95
97
  secondaryIcon: "devicon:kubernetes",
96
98
  },
97
99
 
@@ -0,0 +1,59 @@
1
+ import { defineUnit, z } from "@highstate/contract"
2
+ import { providerEntity } from "../dns"
3
+
4
+ export const providerDataSchema = z.object({
5
+ /**
6
+ * The zone ID of the Cloudflare zone.
7
+ */
8
+ zoneId: z.string(),
9
+
10
+ /**
11
+ * The API token for the Cloudflare account.
12
+ *
13
+ * The API key must have permissions to manage DNS records for exactly one zone.
14
+ * If multiple zones are specified, the unit will fail.
15
+ *
16
+ * The required permissions are:
17
+ * - `Zone:Read`
18
+ * - `Zone:DNS:Edit`
19
+ */
20
+ apiToken: z.string(),
21
+ })
22
+
23
+ /**
24
+ * The Cloudflare connection for a single zone.
25
+ */
26
+ export const connection = defineUnit({
27
+ type: "cloudflare.connection.v1",
28
+
29
+ secrets: {
30
+ /**
31
+ * The API token for the Cloudflare account.
32
+ *
33
+ * The API key must have permissions to manage DNS records for exactly one zone.
34
+ * If multiple zones are specified, the unit will fail.
35
+ *
36
+ * The required permissions are:
37
+ * - `Zone.Zone:Read`
38
+ * - `Zone.DNS:Edit`
39
+ */
40
+ apiToken: z.string(),
41
+ },
42
+
43
+ outputs: {
44
+ dnsProvider: providerEntity,
45
+ },
46
+
47
+ meta: {
48
+ title: "Cloudflare Connection",
49
+ icon: "simple-icons:cloudflare",
50
+ category: "Cloudflare",
51
+ },
52
+
53
+ source: {
54
+ package: "@highstate/cloudflare",
55
+ path: "connection",
56
+ },
57
+ })
58
+
59
+ export type ProviderData = z.infer<typeof providerDataSchema>
@@ -0,0 +1,3 @@
1
+ export * as cloudflare from "./cloudflare"
2
+ export * as mullvad from "./mullvad"
3
+ export * as timeweb from "./timeweb"
@@ -1,17 +1,20 @@
1
- import { defineUnit, Type } from "@highstate/contract"
2
- import { networkEntity, peerEntity } from "./wireguard"
3
- import { l4EndpointEntity } from "./network"
1
+ import { defineUnit, z } from "@highstate/contract"
2
+ import { l4EndpointEntity } from "../network"
3
+ import { networkEntity, peerEntity } from "../wireguard"
4
4
 
5
+ /**
6
+ * The Mullvad WireGuard peer fetched from the Mullvad API.
7
+ */
5
8
  export const peer = defineUnit({
6
- type: "mullvad.peer",
9
+ type: "mullvad.peer.v1",
7
10
 
8
11
  args: {
9
- hostname: Type.Optional(Type.String()),
12
+ hostname: z.string().optional(),
10
13
 
11
14
  /**
12
15
  * Whether to include Mullvad DNS servers in the peer configuration.
13
16
  */
14
- includeDns: Type.Default(Type.Boolean(), true),
17
+ includeDns: z.boolean().default(true),
15
18
  },
16
19
 
17
20
  inputs: {
@@ -36,9 +39,8 @@ export const peer = defineUnit({
36
39
  },
37
40
 
38
41
  meta: {
39
- displayName: "Mullvad Peer",
40
- description: "The Mullvad WireGuard peer fetched from the Mullvad API.",
41
- primaryIcon: "simple-icons:mullvad",
42
+ title: "Mullvad Peer",
43
+ icon: "simple-icons:mullvad",
42
44
  secondaryIcon: "cib:wireguard",
43
45
  secondaryIconColor: "#88171a",
44
46
  category: "VPN",
@@ -0,0 +1,99 @@
1
+ import { defineEntity, defineUnit, z } from "@highstate/contract"
2
+ import { serverOutputs, vmSecrets, vmSshArgs } from "../common"
3
+ import * as ssh from "../ssh"
4
+
5
+ export const connectionEntity = defineEntity({
6
+ type: "timeweb.connection.v1",
7
+
8
+ schema: z.object({
9
+ name: z.string(),
10
+ apiToken: z.string(),
11
+ }),
12
+ })
13
+
14
+ /**
15
+ * The Timeweb connection for a single account.
16
+ */
17
+ export const connection = defineUnit({
18
+ type: "timeweb.connection.v1",
19
+
20
+ secrets: {
21
+ /**
22
+ * The API token for the Timeweb account.
23
+ *
24
+ * Can be obtained from the Timeweb control panel.
25
+ */
26
+ apiToken: z.string(),
27
+ },
28
+
29
+ outputs: {
30
+ connection: connectionEntity,
31
+ },
32
+
33
+ meta: {
34
+ title: "Timeweb Connection",
35
+ icon: "material-symbols:cloud",
36
+ category: "Timeweb",
37
+ },
38
+
39
+ source: {
40
+ package: "@highstate/timeweb",
41
+ path: "connection",
42
+ },
43
+ })
44
+
45
+ export const virtualMachine = defineUnit({
46
+ type: "timeweb.virtual-machine.v1",
47
+
48
+ args: {
49
+ /**
50
+ * The ID of the preset to use for the virtual machine.
51
+ *
52
+ * Can be obtained from the Timeweb control panel when creating a new virtual machine.
53
+ */
54
+ presetId: z.number().optional(),
55
+
56
+ /**
57
+ * The ID of the operating system to use for the virtual machine.
58
+ *
59
+ * Can be obtained from the Timeweb control panel when creating a new virtual machine.
60
+ */
61
+ osId: z.number().optional(),
62
+
63
+ /**
64
+ * The ID of the connection to use for the virtual machine.
65
+ *
66
+ * Can be obtained from the Timeweb control panel when creating a new virtual machine.
67
+ */
68
+ availabilityZone: z.string(),
69
+
70
+ /**
71
+ * The SSH arguments to use for the virtual machine.
72
+ */
73
+ ssh: vmSshArgs,
74
+ },
75
+
76
+ inputs: {
77
+ connection: connectionEntity,
78
+ ...ssh.inputs,
79
+ },
80
+
81
+ secrets: vmSecrets,
82
+
83
+ outputs: {
84
+ ...serverOutputs,
85
+ },
86
+
87
+ meta: {
88
+ title: "Timeweb Virtual Machine",
89
+ description: "Creates a new Timeweb virtual machine.",
90
+ icon: "material-symbols:cloud",
91
+ secondaryIcon: "codicon:vm",
92
+ category: "Timeweb",
93
+ },
94
+
95
+ source: {
96
+ package: "@highstate/timeweb",
97
+ path: "virtual-machine",
98
+ },
99
+ })
package/src/utils.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Type, type Static } from "@highstate/contract"
1
+ import { z } from "@highstate/contract"
2
2
 
3
3
  type PrefixWith<TString extends string, TPrefix extends string> = TPrefix extends ""
4
4
  ? TString
@@ -17,6 +17,17 @@ type PrefixedKeys<T extends Record<string, unknown>, Prefix extends string> = {
17
17
  [K in keyof T as PrefixWith<Extract<K, string>, Prefix>]: T[K]
18
18
  }
19
19
 
20
+ /**
21
+ * The helper function to prefix the keys of an object with a given prefix.
22
+ *
23
+ * If the prefix is not provided, the keys will not be modified.
24
+ *
25
+ * All keys after prefixing will be capitalized.
26
+ *
27
+ * @param prefix The prefix to use. If not provided, the keys will not be modified.
28
+ * @param obj The object to prefix the keys of.
29
+ * @returns The object with prefixed keys.
30
+ */
20
31
  export function prefixKeysWith<T extends Record<string, unknown>, Prefix extends string>(
21
32
  prefix: Prefix | undefined,
22
33
  obj: T,
@@ -26,12 +37,22 @@ export function prefixKeysWith<T extends Record<string, unknown>, Prefix extends
26
37
  ) as PrefixedKeys<T, Prefix>
27
38
  }
28
39
 
29
- export const arrayPatchModeSchema = Type.StringEnum(["prepend", "replace"])
40
+ export const arrayPatchModeSchema = z.enum(["prepend", "replace"])
41
+ export const booleanPatchSchema = z.enum(["keep", "true", "false"])
42
+
43
+ /**
44
+ * The mode to use when patching some array:
45
+ *
46
+ * - `prepend`: prepend the values of the new array to the existing array;
47
+ * - `replace`: replace the existing array with the new array.
48
+ */
49
+ export type ArrayPatchMode = z.infer<typeof arrayPatchModeSchema>
30
50
 
31
51
  /**
32
- * The mode to use when patching some array.
52
+ * The boolean patch:
33
53
  *
34
- * - `prepend`: Prepend the values of the new array to the existing array.
35
- * - `replace`: Replace the existing array with the new array.
54
+ * - `keep`: keep the existing value;
55
+ * - `true`: set the value to `true`;
56
+ * - `false`: set the value to `false`.
36
57
  */
37
- export type ArrayPatchMode = Static<typeof arrayPatchModeSchema>
58
+ export type BooleanPatch = z.infer<typeof booleanPatchSchema>