@highstate/library 0.9.4 → 0.9.6

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/src/common.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
2
  import { credentialsSchema, keyPairEntity } from "./ssh"
3
+ import { l3EndpointEntity } from "./network"
4
+ import * as dns from "./dns"
5
+ import { arrayPatchModeSchema } from "./utils"
3
6
 
4
7
  export const serverEntity = defineEntity({
5
8
  type: "common.server",
6
9
 
7
10
  schema: Type.Object({
8
- endpoint: Type.String(),
9
11
  hostname: Type.String(),
10
- sshCredentials: Type.Optional(credentialsSchema),
12
+ endpoints: Type.Array(l3EndpointEntity.schema),
13
+ ssh: Type.Optional(credentialsSchema),
11
14
  }),
12
15
 
13
16
  meta: {
@@ -15,40 +18,34 @@ export const serverEntity = defineEntity({
15
18
  },
16
19
  })
17
20
 
18
- export const l3EndpointEntity = defineEntity({
19
- type: "common.l3-endpoint",
20
-
21
- schema: Type.Object({
22
- endpoint: Type.String(),
23
- }),
24
-
25
- meta: {
26
- color: "#1B5E20",
27
- description: "The L3 endpoint for some service. May be a domain name or an IP address.",
21
+ export const serverOutputs = {
22
+ server: serverEntity,
23
+ endpoints: {
24
+ entity: l3EndpointEntity,
25
+ multiple: true,
28
26
  },
29
- })
30
-
31
- export const l4EndpointEntity = defineEntity({
32
- type: "common.l4-endpoint",
33
-
34
- schema: Type.Object({
35
- endpoint: Type.String(),
36
- port: Type.Number(),
37
- }),
38
-
39
- meta: {
40
- color: "#F57F17",
41
- description: "The L4 endpoint for some service. Extends an L3 endpoint with a port.",
42
- },
43
- })
27
+ } as const
44
28
 
45
29
  export const existingServer = defineUnit({
46
30
  type: "common.existing-server",
47
31
 
48
32
  args: {
49
- endpoint: Type.String(),
50
- sshUser: Type.Optional(Type.String({ default: "root" })),
51
- sshPort: Type.Optional(Type.Number({ default: 22 })),
33
+ /**
34
+ * The endpoint of the server.
35
+ *
36
+ * Takes precedence over the `endpoint` input.
37
+ */
38
+ endpoint: Type.Optional(Type.String()),
39
+
40
+ /**
41
+ * The SSH user to use for connecting to the server.
42
+ */
43
+ sshUser: Type.Default(Type.String(), "root"),
44
+
45
+ /**
46
+ * The SSH port to use for connecting to the server.
47
+ */
48
+ sshPort: Type.Default(Type.Number(), 22),
52
49
  },
53
50
 
54
51
  secrets: {
@@ -61,22 +58,112 @@ export const existingServer = defineUnit({
61
58
  entity: keyPairEntity,
62
59
  required: false,
63
60
  },
61
+ endpoint: {
62
+ entity: l3EndpointEntity,
63
+ required: false,
64
+ },
64
65
  },
65
66
 
66
- outputs: {
67
- server: serverEntity,
68
- },
67
+ outputs: serverOutputs,
69
68
 
70
69
  meta: {
71
70
  displayName: "Existing Server",
72
71
  description: "An existing server that can be used in the configuration.",
73
72
  primaryIcon: "mdi:server",
74
73
  defaultNamePrefix: "server",
74
+ category: "Infrastructure",
75
+ },
76
+
77
+ source: {
78
+ package: "@highstate/common",
79
+ path: "units/existing-server",
80
+ },
81
+ })
82
+
83
+ export const serverPatch = defineUnit({
84
+ type: "common.server-patch",
85
+
86
+ args: {
87
+ /**
88
+ * The endpoints of the server.
89
+ *
90
+ * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
91
+ *
92
+ * The same server may also be represented by multiple entries (e.g. a node with private and public IP).
93
+ *
94
+ * @schema
95
+ */
96
+ endpoints: Type.Default(Type.Array(Type.String()), []),
97
+
98
+ /**
99
+ * The mode to use for patching the endpoints.
100
+ *
101
+ * - `prepend`: prepend the new endpoints to the existing ones (default);
102
+ * - `replace`: replace the existing endpoints with the new ones.
103
+ */
104
+ endpointsPatchMode: Type.Default(arrayPatchModeSchema, "prepend"),
105
+ },
106
+
107
+ inputs: {
108
+ server: serverEntity,
109
+ endpoints: {
110
+ entity: l3EndpointEntity,
111
+ required: false,
112
+ multiple: true,
113
+ },
114
+ },
115
+
116
+ outputs: {
117
+ server: serverEntity,
118
+ endpoints: {
119
+ entity: l3EndpointEntity,
120
+ multiple: true,
121
+ },
122
+ },
123
+
124
+ meta: {
125
+ displayName: "Server Patch",
126
+ description: "Patches some properties of the server.",
127
+ primaryIcon: "mdi:server",
128
+ secondaryIcon: "fluent:patch-20-filled",
129
+ category: "Infrastructure",
130
+ },
131
+
132
+ source: {
133
+ package: "@highstate/common",
134
+ path: "units/server-patch",
135
+ },
136
+ })
137
+
138
+ export const serverDns = defineUnit({
139
+ type: "common.server-dns",
140
+
141
+ args: dns.createArgs(),
142
+
143
+ inputs: {
144
+ server: serverEntity,
145
+ ...dns.inputs,
146
+ },
147
+
148
+ outputs: {
149
+ server: serverEntity,
150
+ endpoints: {
151
+ entity: l3EndpointEntity,
152
+ multiple: true,
153
+ },
154
+ },
155
+
156
+ meta: {
157
+ displayName: "Server DNS",
158
+ description: "Creates DNS records for the server and updates endpoints.",
159
+ primaryIcon: "mdi:server",
160
+ secondaryIcon: "mdi:dns",
161
+ category: "Infrastructure",
75
162
  },
76
163
 
77
164
  source: {
78
165
  package: "@highstate/common",
79
- path: "existing-server",
166
+ path: "units/server-dns",
80
167
  },
81
168
  })
82
169
 
@@ -101,11 +188,12 @@ export const script = defineUnit({
101
188
  displayName: "Shell Script",
102
189
  description: "Run a shell script on the server.",
103
190
  primaryIcon: "mdi:bash",
191
+ category: "Infrastructure",
104
192
  },
105
193
 
106
194
  source: {
107
195
  package: "@highstate/common",
108
- path: "script",
196
+ path: "units/script",
109
197
  },
110
198
  })
111
199
 
@@ -115,8 +203,8 @@ export const fileMetaEntity = defineEntity({
115
203
  schema: Type.Object({
116
204
  name: Type.String(),
117
205
  size: Type.Number(),
206
+ mode: Type.Number(),
118
207
  isBinary: Type.Optional(Type.Boolean()),
119
- isExecutable: Type.Optional(Type.Boolean()),
120
208
  }),
121
209
 
122
210
  meta: {
@@ -159,8 +247,6 @@ export const fileEntity = defineEntity({
159
247
  })
160
248
 
161
249
  export type Server = Static<typeof serverEntity.schema>
162
- export type L3Endpoint = Static<typeof l3EndpointEntity.schema>
163
- export type L4Endpoint = Static<typeof l4EndpointEntity.schema>
164
250
 
165
251
  export type File = Static<typeof fileEntity.schema>
166
252
  export type FileMeta = Static<typeof fileMetaEntity.schema>
package/src/dns.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
1
+ import { defineEntity, Type, type Static } from "@highstate/contract"
2
+ import { endpointFilterSchema } from "./network"
3
+ import { arrayPatchModeSchema, prefixKeysWith } from "./utils"
2
4
 
3
5
  export const providerEntity = defineEntity({
4
6
  type: "dns.provider",
@@ -15,31 +17,66 @@ export const providerEntity = defineEntity({
15
17
  },
16
18
  })
17
19
 
18
- export const record = defineUnit({
19
- type: "common.dns-record",
20
+ export function createArgs<TPrefix extends string = "">(prefix?: TPrefix) {
21
+ return prefixKeysWith(prefix, {
22
+ /**
23
+ * The FQDN to register the existing endpoints with.
24
+ *
25
+ * Will be inserted at the beginning of the resulting endpoint list.
26
+ *
27
+ * Will throw an error if no matching provider is found.
28
+ *
29
+ * @schema
30
+ */
31
+ fqdn: Type.Optional(Type.String()),
20
32
 
21
- args: {
22
- name: Type.String(),
23
- type: Type.String(),
24
- value: Type.String(),
25
- ttl: Type.Optional(Type.Number()),
26
- },
27
-
28
- inputs: {
29
- dnsProvider: providerEntity,
30
- },
33
+ /**
34
+ * The endpoint filter to filter the endpoints before creating the DNS records.
35
+ *
36
+ * Possible values:
37
+ *
38
+ * - `public`: Only endpoints exposed to the public internet.
39
+ * - `external`: Reachable from outside the system but not public (e.g., LAN, VPC).
40
+ * - `internal`: Reachable only from within the system boundary (e.g., inside a cluster).
41
+ *
42
+ * You can select one or more values.
43
+ *
44
+ * If no value is provided, the endpoints will be filtered by the most accessible type:
45
+ *
46
+ * - If any public endpoints exist, all public endpoints are selected;
47
+ * - Otherwise, if any external endpoints exist, all external endpoints are selected;
48
+ * - If neither exist, all internal endpoints are selected.
49
+ *
50
+ * @schema
51
+ */
52
+ endpointFilter: Type.Default(endpointFilterSchema, []),
31
53
 
32
- meta: {
33
- displayName: "DNS Record",
34
- description: "A DNS record to create.",
35
- primaryIcon: "mdi:server",
36
- defaultNamePrefix: "record",
37
- },
54
+ /**
55
+ * The mode to use for patching the existing endpoints.
56
+ *
57
+ * - `prepend`: Prepend the FQDN to the existing endpoints. It will make them prioritized.
58
+ * - `replace`: Replace the existing endpoints with the FQDN. It will ensure that the only the FQDN is used.
59
+ *
60
+ * The default is `prepend`.
61
+ *
62
+ * @schema
63
+ */
64
+ patchMode: Type.Default(arrayPatchModeSchema, "prepend"),
65
+ })
66
+ }
38
67
 
39
- source: {
40
- package: "@highstate/common",
41
- path: "dns/record",
68
+ export const inputs = {
69
+ /**
70
+ * The DNS providers to use to create the DNS records.
71
+ *
72
+ * If multiple providers match the domain, all of them will be used and multiple DNS records will be created.
73
+ *
74
+ * @schema
75
+ */
76
+ dnsProviders: {
77
+ entity: providerEntity,
78
+ multiple: true,
42
79
  },
43
- })
80
+ } as const
44
81
 
45
82
  export type Provider = Static<typeof providerEntity.schema>
package/src/index.ts CHANGED
@@ -14,3 +14,5 @@ export * as timeweb from "./timeweb"
14
14
  export * as nixos from "./nixos"
15
15
  export * as sops from "./sops"
16
16
  export * as obfuscators from "./obfuscators"
17
+ export * as network from "./network"
18
+ export * from "./utils"
package/src/k3s.ts CHANGED
@@ -1,29 +1,31 @@
1
- import { defineUnit } from "@highstate/contract"
2
- import { Type } from "@sinclair/typebox"
3
- import { serverEntity } from "./common"
4
- import { clusterEntity, sharedClusterArgs } from "./k8s"
5
- import { providerEntity } from "./dns"
1
+ import { defineUnit, Type } from "@highstate/contract"
2
+ import { clusterInputs, clusterOutputs } from "./k8s"
6
3
 
7
4
  export const cluster = defineUnit({
8
5
  type: "k3s.cluster",
9
6
 
10
7
  args: {
11
- ...sharedClusterArgs,
8
+ /**
9
+ * The K3S configuration to pass to each server or agent in the cluster.
10
+ *
11
+ * See: https://docs.k3s.io/installation/configuration
12
+ *
13
+ * @schema
14
+ */
12
15
  config: Type.Optional(Type.Record(Type.String(), Type.Any())),
13
- },
14
16
 
15
- inputs: {
16
- server: serverEntity,
17
- dnsProviders: {
18
- entity: providerEntity,
19
- required: false,
20
- multiple: true,
21
- },
17
+ /**
18
+ * The configuration of the registries to use for the K3S cluster.
19
+ *
20
+ * See: https://docs.k3s.io/installation/private-registry
21
+ *
22
+ * @schema
23
+ */
24
+ registries: Type.Optional(Type.Record(Type.String(), Type.Any())),
22
25
  },
23
26
 
24
- outputs: {
25
- k8sCluster: clusterEntity,
26
- },
27
+ inputs: clusterInputs,
28
+ outputs: clusterOutputs,
27
29
 
28
30
  meta: {
29
31
  displayName: "K3s Cluster",