@highstate/library 0.15.0 → 0.16.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.
Files changed (44) hide show
  1. package/dist/highstate.library.msgpack +0 -0
  2. package/dist/index.js +1721 -953
  3. package/dist/index.js.map +1 -1
  4. package/package.json +3 -3
  5. package/src/abbreviations.ts +1 -0
  6. package/src/common/access-point.ts +2 -2
  7. package/src/common/files.ts +10 -0
  8. package/src/common/server.ts +15 -57
  9. package/src/databases/etcd.ts +97 -0
  10. package/src/databases/index.ts +1 -0
  11. package/src/databases/mariadb.ts +48 -2
  12. package/src/databases/mongodb.ts +48 -2
  13. package/src/databases/postgresql.ts +51 -2
  14. package/src/databases/redis.ts +48 -2
  15. package/src/databases/s3.ts +65 -6
  16. package/src/databases/shared.ts +12 -6
  17. package/src/dns.ts +59 -49
  18. package/src/k8s/apps/etcd.ts +46 -0
  19. package/src/k8s/apps/index.ts +2 -0
  20. package/src/k8s/apps/mariadb.ts +0 -5
  21. package/src/k8s/apps/minio.ts +0 -5
  22. package/src/k8s/apps/mongodb.ts +0 -5
  23. package/src/k8s/apps/postgresql.ts +0 -5
  24. package/src/k8s/apps/shared.ts +10 -1
  25. package/src/k8s/apps/traefik.ts +16 -1
  26. package/src/k8s/apps/valkey.ts +0 -5
  27. package/src/k8s/apps/wg-feed-server.ts +34 -0
  28. package/src/k8s/reduced-access.ts +23 -53
  29. package/src/k8s/resources.ts +78 -35
  30. package/src/k8s/service.ts +21 -10
  31. package/src/k8s/shared.ts +60 -90
  32. package/src/k8s/workload.ts +87 -26
  33. package/src/network/address-space.ts +94 -0
  34. package/src/network/address.ts +33 -0
  35. package/src/network/dynamic-endpoint.ts +39 -0
  36. package/src/network/endpoint-schema.ts +116 -0
  37. package/src/network/endpoint.ts +347 -0
  38. package/src/network/index.ts +6 -0
  39. package/src/network/subnet.ts +31 -0
  40. package/src/ssh.ts +66 -10
  41. package/src/third-party/cloudflare.ts +1 -0
  42. package/src/utils.ts +41 -11
  43. package/src/wireguard.ts +340 -150
  44. package/src/network.ts +0 -391
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { registerKnownAbbreviations, z, camelCaseToHumanReadable, defineEntity, defineUnit, $addArgumentDescription, $addInputDescription, fileContentSchema as fileContentSchema$1, fileMetaSchema, unitArtifactSchema, $secrets, $inputs, $outputs, $args, text } from '@highstate/contract';
2
- import { mapValues, pick, omit } from 'remeda';
1
+ import { registerKnownAbbreviations, z, defineEntity, camelCaseToHumanReadable, genericNameSchema, $args, $addArgumentDescription, defineUnit, $addInputDescription, fileContentSchema as fileContentSchema$1, fileMetaSchema, unitArtifactSchema, $secrets, $inputs, $outputs, text } from '@highstate/contract';
2
+ import { mapValues, pick } from 'remeda';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __export = (target, all) => {
@@ -35,7 +35,8 @@ registerKnownAbbreviations([
35
35
  "CSI",
36
36
  "MariaDB",
37
37
  "PostgreSQL",
38
- "MongoDB"
38
+ "MongoDB",
39
+ "etcd"
39
40
  ]);
40
41
 
41
42
  // src/common/index.ts
@@ -54,7 +55,6 @@ __export(common_exports, {
54
55
  gatewayEntity: () => gatewayEntity,
55
56
  remoteFile: () => remoteFile,
56
57
  script: () => script,
57
- serverDns: () => serverDns,
58
58
  serverEntity: () => serverEntity,
59
59
  serverOutputs: () => serverOutputs,
60
60
  serverPatch: () => serverPatch,
@@ -66,100 +66,283 @@ __export(common_exports, {
66
66
  // src/dns.ts
67
67
  var dns_exports = {};
68
68
  __export(dns_exports, {
69
- createArgs: () => createArgs,
70
- inputs: () => inputs,
69
+ inputs: () => inputs2,
71
70
  providerEntity: () => providerEntity,
72
71
  recordSet: () => recordSet
73
72
  });
74
- var implementationReferenceSchema = z.object({
75
- /**
76
- * The name of the package which contains the implementation.
77
- */
78
- package: z.string().meta({ title: camelCaseToHumanReadable("package"), description: `The name of the package which contains the implementation.` }),
79
- /**
80
- * The implementation specific data.
81
- */
82
- data: z.record(z.string(), z.unknown()).meta({ title: camelCaseToHumanReadable("data"), description: `The implementation specific data.` })
83
- });
84
73
 
85
- // src/network.ts
74
+ // src/network/index.ts
86
75
  var network_exports = {};
87
76
  __export(network_exports, {
77
+ addressEntity: () => addressEntity,
78
+ addressSpace: () => addressSpace,
79
+ addressSpaceEntity: () => addressSpaceEntity,
80
+ addressTypeSchema: () => addressTypeSchema,
81
+ dynamicL3EndpointEntity: () => dynamicL3EndpointEntity,
82
+ dynamicL4EndpointEntity: () => dynamicL4EndpointEntity,
83
+ dynamicL7EndpointEntity: () => dynamicL7EndpointEntity,
84
+ endpointArgs: () => endpointArgs,
88
85
  endpointFilter: () => endpointFilter,
89
- endpointFilterSchema: () => endpointFilterSchema,
90
- endpointVisibilitySchema: () => endpointVisibilitySchema,
91
86
  ipv46Schema: () => ipv46Schema,
92
87
  ipv4PrefixSchema: () => ipv4PrefixSchema,
93
- l34EndpointSchema: () => l34EndpointSchema,
94
88
  l3Endpoint: () => l3Endpoint,
95
89
  l3EndpointEntity: () => l3EndpointEntity,
90
+ l3EndpointSchema: () => l3EndpointSchema,
96
91
  l4Endpoint: () => l4Endpoint,
97
92
  l4EndpointEntity: () => l4EndpointEntity,
93
+ l4EndpointSchema: () => l4EndpointSchema,
98
94
  l4PortInfoSchema: () => l4PortInfoSchema,
99
95
  l4ProtocolSchema: () => l4ProtocolSchema,
100
96
  l7AppInfoSchema: () => l7AppInfoSchema,
101
97
  l7Endpoint: () => l7Endpoint,
102
98
  l7EndpointEntity: () => l7EndpointEntity,
103
- portSchema: () => portSchema
104
- });
105
- var endpointVisibilitySchema = z.enum([
106
- "public",
107
- // reachable from the public internet
108
- "external",
109
- // reachable from outside the system boundary, but not public
110
- "internal"
111
- // reachable only from within the system or cluster
99
+ l7EndpointSchema: () => l7EndpointSchema,
100
+ networkArgs: () => networkArgs,
101
+ optionalNetworkArgs: () => optionalNetworkArgs,
102
+ portSchema: () => portSchema,
103
+ subnetEntity: () => subnetEntity
104
+ });
105
+ var addressTypeSchema = z.enum(["ipv4", "ipv6"]);
106
+ var subnetEntity = defineEntity({
107
+ type: "network.subnet.v1",
108
+ schema: z.object({
109
+ /**
110
+ * The type of the subnet.
111
+ */
112
+ type: addressTypeSchema.meta({ title: camelCaseToHumanReadable("type"), description: `The type of the subnet.` }),
113
+ /**
114
+ * The canonical base IP address of the subnet.
115
+ */
116
+ baseAddress: z.string().meta({ title: camelCaseToHumanReadable("baseAddress"), description: `The canonical base IP address of the subnet.` }),
117
+ /**
118
+ * The prefix length of the subnet.
119
+ */
120
+ prefixLength: z.number().int().nonnegative().meta({ title: camelCaseToHumanReadable("prefixLength"), description: `The prefix length of the subnet.` })
121
+ }),
122
+ meta: {
123
+ color: "#3F51B5"
124
+ }
125
+ });
126
+
127
+ // src/network/address.ts
128
+ var addressEntity = defineEntity({
129
+ type: "network.address.v1",
130
+ includes: {
131
+ /**
132
+ * The subnet to which the address belongs.
133
+ */
134
+ subnet: subnetEntity
135
+ },
136
+ schema: z.object({
137
+ /**
138
+ * The type of the address.
139
+ */
140
+ type: addressTypeSchema.meta({ title: camelCaseToHumanReadable("type"), description: `The type of the address.` }),
141
+ /**
142
+ * The address in canonical string representation.
143
+ *
144
+ * IPv6 addresses must be in shortest possible notation as per RFC 5952.
145
+ *
146
+ * For example:
147
+ * - IPv4: `192.168.1.1`
148
+ * - IPv6: `2001:db8:85a3::8a2e:370:7334`
149
+ */
150
+ value: z.string().meta({ title: camelCaseToHumanReadable("value"), description: `The address in canonical string representation.
151
+
152
+ IPv6 addresses must be in shortest possible notation as per RFC 5952.
153
+
154
+ For example:
155
+ - IPv4: \`192.168.1.1\`
156
+ - IPv6: \`2001:db8:85a3::8a2e:370:7334\`` })
157
+ })
158
+ });
159
+ function prefixWith(string, prefix) {
160
+ return prefix ? `${prefix}${string.charAt(0).toUpperCase()}${string.slice(1)}` : string;
161
+ }
162
+ function prefixKeysWith(prefix, obj) {
163
+ return Object.fromEntries(
164
+ Object.entries(obj).map(([key, value]) => [prefixWith(key, prefix), value])
165
+ );
166
+ }
167
+ var booleanPatchSchema = z.enum(["keep", "true", "false"]).default("keep");
168
+ function toPatchArgs(args) {
169
+ return mapValues(args, (arg) => {
170
+ if (arg.schema instanceof z.ZodBoolean || arg.schema instanceof z.ZodDefault && arg.schema.unwrap() instanceof z.ZodBoolean || arg.schema instanceof z.ZodOptional && arg.schema.unwrap() instanceof z.ZodBoolean) {
171
+ return { ...arg, schema: booleanPatchSchema };
172
+ }
173
+ return arg;
174
+ });
175
+ }
176
+ var metadataKeySchema = z.templateLiteral([
177
+ genericNameSchema,
178
+ z.literal("."),
179
+ genericNameSchema
112
180
  ]);
113
- var endpointFilterSchema = endpointVisibilitySchema.array();
114
- var l3EndpointEntity = defineEntity({
115
- type: "network.l3-endpoint.v1",
116
- schema: z.intersection(
181
+ var metadataSchema = z.record(metadataKeySchema, z.unknown());
182
+ var implementationReferenceSchema = z.object({
183
+ /**
184
+ * The name of the package which contains the implementation.
185
+ */
186
+ package: z.string().meta({ title: camelCaseToHumanReadable("package"), description: `The name of the package which contains the implementation.` }),
187
+ /**
188
+ * The implementation specific data.
189
+ */
190
+ data: z.record(z.string(), z.unknown()).meta({ title: camelCaseToHumanReadable("data"), description: `The implementation specific data.` })
191
+ });
192
+ function createEndpointSchema(level, shape) {
193
+ return z.intersection(
117
194
  z.object({
118
195
  /**
119
- * The generic visibility of an endpoint.
120
- *
121
- * - `public`: reachable from the public internet;
122
- * - `external`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
123
- * - `internal`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
196
+ * The level of the endpoint in the network stack.
124
197
  */
125
- visibility: endpointVisibilitySchema.meta({ title: camelCaseToHumanReadable("visibility"), description: `The generic visibility of an endpoint.
126
-
127
- - \`public\`: reachable from the public internet;
128
- - \`external\`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
129
- - \`internal\`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).` }),
198
+ level: z.literal(level).default(level).meta({ title: camelCaseToHumanReadable("level"), description: `The level of the endpoint in the network stack.` }),
130
199
  /**
131
200
  * The extra metadata for the endpoint.
132
201
  *
133
202
  * In most cases, this is provided by the endpoint origin (e.g., a Kubernetes service).
134
203
  */
135
- metadata: z.record(z.string(), z.unknown()).optional().meta({ title: camelCaseToHumanReadable("metadata"), description: `The extra metadata for the endpoint.
136
-
137
- In most cases, this is provided by the endpoint origin (e.g., a Kubernetes service).` })
204
+ metadata: z.intersection(
205
+ metadataSchema,
206
+ z.object({
207
+ /**
208
+ * The scope of the endpoint as per IANA definitions.
209
+ *
210
+ * - `private`: The endpoint is intended for use within a private network.
211
+ * - `global`: The endpoint is intended for public access over the internet.
212
+ *
213
+ * If not specified, the scope is considered unknown.
214
+ */
215
+ "iana.scope": z.enum(["private", "global"]).optional()
216
+ })
217
+ ).meta({ title: camelCaseToHumanReadable("metadata"), description: `The extra metadata for the endpoint.
218
+
219
+ In most cases, this is provided by the endpoint origin (e.g., a Kubernetes service).` }),
220
+ ...shape
138
221
  }),
139
222
  z.union([
140
223
  z.object({
141
224
  type: z.literal("hostname"),
142
225
  /**
143
- * The hostname of the endpoint in the format of a domain name.
226
+ * The hostname of the endpoint in the format of a domain name as per RFC 1035.
144
227
  */
145
- hostname: z.string().meta({ title: camelCaseToHumanReadable("hostname"), description: `The hostname of the endpoint in the format of a domain name.` })
228
+ hostname: z.string().meta({ title: camelCaseToHumanReadable("hostname"), description: `The hostname of the endpoint in the format of a domain name as per RFC 1035.` }),
229
+ address: z.undefined().optional()
146
230
  }),
147
231
  z.object({
148
- type: z.literal("ipv4"),
232
+ type: z.enum(["ipv4", "ipv6"]),
233
+ /**
234
+ * The address entity representing the IP address of the endpoint.
235
+ */
236
+ address: addressEntity.schema.meta({ title: camelCaseToHumanReadable("address"), description: `The address entity representing the IP address of the endpoint.` }),
237
+ hostname: z.undefined().optional()
238
+ })
239
+ ])
240
+ );
241
+ }
242
+ var l4ProtocolSchema = z.enum(["tcp", "udp"]);
243
+ var portSchema = z.number().int().min(1).max(65535);
244
+ var l4PortInfoSchema = z.object({
245
+ port: portSchema,
246
+ protocol: l4ProtocolSchema
247
+ });
248
+ var l7AppInfoSchema = z.object({
249
+ /**
250
+ * The name of the application protocol used by the endpoint.
251
+ */
252
+ appProtocol: z.string().meta({ title: camelCaseToHumanReadable("appProtocol"), description: `The name of the application protocol used by the endpoint.` }),
253
+ /**
254
+ * The resource path of the application endpoint, including query parameters.
255
+ * Must not start with a slash (`/`).
256
+ *
257
+ * Example: `api/v1/resource?query=value`, `database?param=value`, `user/repo.git`.
258
+ */
259
+ path: z.string().optional().meta({ title: camelCaseToHumanReadable("path"), description: `The resource path of the application endpoint, including query parameters.
260
+ Must not start with a slash (\`/\`).
261
+
262
+ Example: \`api/v1/resource?query=value\`, \`database?param=value\`, \`user/repo.git\`.` })
263
+ });
264
+ var onlyl3EndpointSchema = createEndpointSchema(3, {
265
+ port: z.undefined().optional(),
266
+ protocol: z.undefined().optional(),
267
+ appProtocol: z.undefined().optional(),
268
+ path: z.undefined().optional()
269
+ });
270
+ var onlyl4EndpointSchema = createEndpointSchema(4, {
271
+ ...l4PortInfoSchema.shape,
272
+ appProtocol: z.undefined().optional(),
273
+ path: z.undefined().optional()
274
+ });
275
+ var onlyl7EndpointSchema = createEndpointSchema(7, {
276
+ ...l4PortInfoSchema.shape,
277
+ ...l7AppInfoSchema.shape
278
+ });
279
+ var l3EndpointSchema = z.union([
280
+ onlyl3EndpointSchema,
281
+ onlyl4EndpointSchema,
282
+ onlyl7EndpointSchema
283
+ ]);
284
+ var l4EndpointSchema = z.union([onlyl4EndpointSchema, onlyl7EndpointSchema]);
285
+ var l7EndpointSchema = onlyl7EndpointSchema;
286
+
287
+ // src/network/dynamic-endpoint.ts
288
+ function defineDynamicEndpointEntity(level, endpointSchema) {
289
+ return defineEntity({
290
+ type: `network.dynamic-l${level}-endpoint.v1`,
291
+ schema: z.union([
292
+ z.object({
293
+ type: z.literal("static"),
149
294
  /**
150
- * The IPv4 address of the endpoint.
295
+ * The static endpoint.
151
296
  */
152
- address: z.string().meta({ title: camelCaseToHumanReadable("address"), description: `The IPv4 address of the endpoint.` })
297
+ endpoint: endpointSchema.meta({ title: camelCaseToHumanReadable("endpoint"), description: `The static endpoint.` })
153
298
  }),
154
299
  z.object({
155
- type: z.literal("ipv6"),
300
+ type: z.literal("dynamic"),
156
301
  /**
157
- * The IPv6 address of the endpoint.
302
+ * The implementation reference to resolve the dynamic endpoint.
158
303
  */
159
- address: z.string().meta({ title: camelCaseToHumanReadable("address"), description: `The IPv6 address of the endpoint.` })
304
+ implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The implementation reference to resolve the dynamic endpoint.` })
160
305
  })
161
306
  ])
162
- ),
307
+ });
308
+ }
309
+ var dynamicL3EndpointEntity = defineDynamicEndpointEntity(3, l3EndpointSchema);
310
+ var dynamicL4EndpointEntity = defineDynamicEndpointEntity(4, l3EndpointSchema);
311
+ var dynamicL7EndpointEntity = defineDynamicEndpointEntity(7, l3EndpointSchema);
312
+
313
+ // src/network/endpoint.ts
314
+ var l3EndpointEntity = defineEntity({
315
+ type: "network.l3-endpoint.v1",
316
+ includes: {
317
+ /**
318
+ * The subnet containing the endpoint.
319
+ *
320
+ * If type is "hostname", will be omitted.
321
+ */
322
+ subnet: {
323
+ entity: subnetEntity,
324
+ required: false
325
+ },
326
+ /**
327
+ * The address of the endpoint.
328
+ *
329
+ * If type is "hostname", will be omitted.
330
+ */
331
+ address: {
332
+ entity: addressEntity,
333
+ required: false
334
+ },
335
+ /**
336
+ * The dynamic endpoint which statically resolves to this endpoint.
337
+ *
338
+ * Allows to use any static endpoint as a dynamic without extra units.
339
+ */
340
+ dynamic: {
341
+ entity: dynamicL3EndpointEntity,
342
+ required: false
343
+ }
344
+ },
345
+ schema: l3EndpointSchema,
163
346
  meta: {
164
347
  description: `The L3 endpoint for some service.
165
348
 
@@ -167,17 +350,20 @@ var l3EndpointEntity = defineEntity({
167
350
  color: "#4CAF50"
168
351
  }
169
352
  });
170
- var l4ProtocolSchema = z.enum(["tcp", "udp"]);
171
- var portSchema = z.number().int().min(1).max(65535);
172
353
  var ipv4PrefixSchema = z.number().int().min(0).max(32);
173
354
  var ipv46Schema = z.union([z.ipv4(), z.ipv6()]);
174
- var l4PortInfoSchema = z.object({
175
- port: portSchema,
176
- protocol: l4ProtocolSchema
177
- });
178
355
  var l4EndpointEntity = defineEntity({
179
356
  type: "network.l4-endpoint.v1",
180
- schema: z.intersection(l3EndpointEntity.schema, l4PortInfoSchema),
357
+ extends: { l3EndpointEntity },
358
+ includes: {
359
+ /**
360
+ * The dynamic endpoint which statically resolves to this endpoint.
361
+ *
362
+ * Allows to use any static endpoint as a dynamic without extra units.
363
+ */
364
+ dynamic: dynamicL4EndpointEntity
365
+ },
366
+ schema: l4EndpointSchema,
181
367
  meta: {
182
368
  description: `The L4 endpoint for some service.
183
369
 
@@ -185,25 +371,18 @@ var l4EndpointEntity = defineEntity({
185
371
  color: "#2196F3"
186
372
  }
187
373
  });
188
- var l7AppInfoSchema = z.object({
189
- /**
190
- * The name of the application protocol used by the endpoint.
191
- */
192
- appProtocol: z.string().meta({ title: camelCaseToHumanReadable("appProtocol"), description: `The name of the application protocol used by the endpoint.` }),
193
- /**
194
- * The resource path of the application endpoint, including query parameters.
195
- * Must not start with a slash (`/`).
196
- *
197
- * Example: `api/v1/resource?query=value`, `database?param=value`, `user/repo.git`.
198
- */
199
- resource: z.string().optional().meta({ title: camelCaseToHumanReadable("resource"), description: `The resource path of the application endpoint, including query parameters.
200
- Must not start with a slash (\`/\`).
201
-
202
- Example: \`api/v1/resource?query=value\`, \`database?param=value\`, \`user/repo.git\`.` })
203
- });
204
374
  var l7EndpointEntity = defineEntity({
205
375
  type: "network.l7-endpoint.v1",
206
- schema: z.intersection(l4EndpointEntity.schema, l7AppInfoSchema),
376
+ extends: { l4EndpointEntity },
377
+ includes: {
378
+ /**
379
+ * The dynamic endpoint which statically resolves to this endpoint.
380
+ *
381
+ * Allows to use any static endpoint as a dynamic without extra units.
382
+ */
383
+ dynamic: dynamicL7EndpointEntity
384
+ },
385
+ schema: l7EndpointSchema,
207
386
  meta: {
208
387
  description: `The L7 endpoint for some service.
209
388
 
@@ -211,6 +390,16 @@ var l7EndpointEntity = defineEntity({
211
390
  color: "#FF9800"
212
391
  }
213
392
  });
393
+ var endpointArgs = $args({
394
+ /**
395
+ * The custom metadata entries of the endpoint.
396
+ *
397
+ * Can be used to filter them (for example, by environment, region, etc.).
398
+ */
399
+ metadata: $addArgumentDescription(metadataSchema, `The custom metadata entries of the endpoint.
400
+
401
+ Can be used to filter them (for example, by environment, region, etc.).`)
402
+ });
214
403
  var l3Endpoint = defineUnit({
215
404
  type: "network.l3-endpoint.v1",
216
405
  args: {
@@ -222,24 +411,7 @@ var l3Endpoint = defineUnit({
222
411
  endpoint: $addArgumentDescription(z.string(), `The string representation of the endpoint.
223
412
 
224
413
  May be a domain name or an IP address.`),
225
- /**
226
- * The visibility of the endpoint.
227
- *
228
- * The visibility levels are:
229
- * - `public`: reachable from the public internet;
230
- * - `external`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
231
- * - `internal`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
232
- *
233
- * If not specified, defaults to `public`.
234
- */
235
- visibility: $addArgumentDescription(endpointVisibilitySchema.default("public"), `The visibility of the endpoint.
236
-
237
- The visibility levels are:
238
- - \`public\`: reachable from the public internet;
239
- - \`external\`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
240
- - \`internal\`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
241
-
242
- If not specified, defaults to \`public\`.`)
414
+ ...endpointArgs
243
415
  },
244
416
  outputs: {
245
417
  endpoint: l3EndpointEntity
@@ -280,24 +452,7 @@ var l4Endpoint = defineUnit({
280
452
  - \`endpoint:port\` (TCP by default)
281
453
  - \`tcp://endpoint:port\`
282
454
  - \`udp://endpoint:port\``),
283
- /**
284
- * The visibility of the endpoint.
285
- *
286
- * The visibility levels are:
287
- * - `public`: reachable from the public internet;
288
- * - `external`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
289
- * - `internal`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
290
- *
291
- * If not specified, defaults to `public`.
292
- */
293
- visibility: $addArgumentDescription(endpointVisibilitySchema.default("public"), `The visibility of the endpoint.
294
-
295
- The visibility levels are:
296
- - \`public\`: reachable from the public internet;
297
- - \`external\`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
298
- - \`internal\`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
299
-
300
- If not specified, defaults to \`public\`.`)
455
+ ...endpointArgs
301
456
  },
302
457
  outputs: {
303
458
  endpoint: l4EndpointEntity
@@ -321,37 +476,20 @@ var l7Endpoint = defineUnit({
321
476
  /**
322
477
  * The string representation of the endpoint.
323
478
  *
324
- * The possible formats are:
325
- *
326
- * - `https://endpoint:port/resource`
327
- * - `ftp://endpoint:port/resource`
328
- * - `someotherprotocol://endpoint:port/resource`
479
+ * The format is `[protocol://]endpoint[:port][/path]`.
329
480
  */
330
481
  endpoint: $addArgumentDescription(z.string(), `The string representation of the endpoint.
331
482
 
332
- The possible formats are:
333
-
334
- - \`https://endpoint:port/resource\`
335
- - \`ftp://endpoint:port/resource\`
336
- - \`someotherprotocol://endpoint:port/resource\``),
483
+ The format is \`[protocol://]endpoint[:port][/path]\`.`),
337
484
  /**
338
- * The visibility of the endpoint.
339
- *
340
- * The visibility levels are:
341
- * - `public`: reachable from the public internet;
342
- * - `external`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
343
- * - `internal`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
485
+ * The L4 protocol of the endpoint.
344
486
  *
345
- * If not specified, defaults to `public`.
487
+ * If not specified, it will be inferred from the endpoint string if possible or default to `tcp`.
346
488
  */
347
- visibility: $addArgumentDescription(endpointVisibilitySchema.default("public"), `The visibility of the endpoint.
489
+ protocol: $addArgumentDescription(z.enum(["infer", "tcp", "udp"]).default("infer"), `The L4 protocol of the endpoint.
348
490
 
349
- The visibility levels are:
350
- - \`public\`: reachable from the public internet;
351
- - \`external\`: reachable from outside the system boundary (e.g., LAN, VPC), but not public;
352
- - \`internal\`: reachable only from within the application or infrastructure boundary (e.g., within a cluster).
353
-
354
- If not specified, defaults to \`public\`.`)
491
+ If not specified, it will be inferred from the endpoint string if possible or default to \`tcp\`.`),
492
+ ...endpointArgs
355
493
  },
356
494
  outputs: {
357
495
  endpoint: l7EndpointEntity
@@ -369,41 +507,39 @@ var l7Endpoint = defineUnit({
369
507
  path: "units/network/l7-endpoint"
370
508
  }
371
509
  });
372
- var endpointFilter = defineUnit({
373
- type: "network.endpoint-filter.v1",
374
- args: {
375
- /**
376
- * The endpoint filter to filter the endpoints before creating the DNS records.
377
- *
378
- * Possible values:
379
- *
380
- * - `public`: only endpoints exposed to the public internet;
381
- * - `external`: reachable from outside the system but not public (e.g., LAN, VPC);
382
- * - `internal`: reachable only from within the system boundary (e.g., inside a cluster).
383
- *
384
- * You can select one or more values.
385
- *
386
- * If no value is provided, the endpoints will be filtered by the most accessible type:
387
- *
388
- * - if any public endpoints exist, all public endpoints are selected;
389
- * - otherwise, if any external endpoints exist, all external endpoints are selected;
390
- * - if neither exist, all internal endpoints are selected.
391
- */
392
- endpointFilter: $addArgumentDescription(endpointFilterSchema.default([]), `The endpoint filter to filter the endpoints before creating the DNS records.
393
-
394
- Possible values:
395
-
396
- - \`public\`: only endpoints exposed to the public internet;
397
- - \`external\`: reachable from outside the system but not public (e.g., LAN, VPC);
398
- - \`internal\`: reachable only from within the system boundary (e.g., inside a cluster).
510
+ var networkArgs = $args({
511
+ /**
512
+ * The filter expression to select endpoints by their properties and metadata.
513
+ *
514
+ * The following properties are available for filtering:
515
+ *
516
+ * - `type`: The type of the endpoint (`ipv4`, `ipv6`, `hostname`).
517
+ * - `level`: The level of the endpoint in the network stack (`3`, `4`, `7`). Numeric, can be used in expressions like `level >= 4`.
518
+ * - `protocol`: The L4 protocol of the endpoint (`tcp`, `udp`). Only available for L4 and L7 endpoints.
519
+ * - `port`: The port of the endpoint. Only available for L4 and L7 endpoints.
520
+ * - `appProtocol`: The application protocol of the endpoint (e.g., `http`, `https`, `dns`). Only available for L7 endpoints.
521
+ * - `metadata.{key}`: Any custom metadata field added to the endpoint. Nested fields (e.g., `metadata.k8s.service.clusterId`) are supported.
522
+ *
523
+ * See [filter-expression](https://github.com/tronghieu/filter-expression?tab=readme-ov-file#language) for more details on the expression syntax.
524
+ */
525
+ endpointFilter: $addArgumentDescription(z.string().meta({ language: "javascript" }), `The filter expression to select endpoints by their properties and metadata.
399
526
 
400
- You can select one or more values.
527
+ The following properties are available for filtering:
401
528
 
402
- If no value is provided, the endpoints will be filtered by the most accessible type:
529
+ - \`type\`: The type of the endpoint (\`ipv4\`, \`ipv6\`, \`hostname\`).
530
+ - \`level\`: The level of the endpoint in the network stack (\`3\`, \`4\`, \`7\`). Numeric, can be used in expressions like \`level >= 4\`.
531
+ - \`protocol\`: The L4 protocol of the endpoint (\`tcp\`, \`udp\`). Only available for L4 and L7 endpoints.
532
+ - \`port\`: The port of the endpoint. Only available for L4 and L7 endpoints.
533
+ - \`appProtocol\`: The application protocol of the endpoint (e.g., \`http\`, \`https\`, \`dns\`). Only available for L7 endpoints.
534
+ - \`metadata.{key}\`: Any custom metadata field added to the endpoint. Nested fields (e.g., \`metadata.k8s.service.clusterId\`) are supported.
403
535
 
404
- - if any public endpoints exist, all public endpoints are selected;
405
- - otherwise, if any external endpoints exist, all external endpoints are selected;
406
- - if neither exist, all internal endpoints are selected.`)
536
+ See [filter-expression](https://github.com/tronghieu/filter-expression?tab=readme-ov-file#language) for more details on the expression syntax.`)
537
+ });
538
+ var optionalNetworkArgs = mapValues(networkArgs, (x) => ({ schema: x.schema.optional() }));
539
+ var endpointFilter = defineUnit({
540
+ type: "network.endpoint-filter.v1",
541
+ args: {
542
+ ...pick(networkArgs, ["endpointFilter"])
407
543
  },
408
544
  inputs: {
409
545
  l3Endpoints: {
@@ -415,6 +551,11 @@ var endpointFilter = defineUnit({
415
551
  entity: l4EndpointEntity,
416
552
  multiple: true,
417
553
  required: false
554
+ },
555
+ l7Endpoints: {
556
+ entity: l7EndpointEntity,
557
+ multiple: true,
558
+ required: false
418
559
  }
419
560
  },
420
561
  outputs: {
@@ -425,6 +566,10 @@ var endpointFilter = defineUnit({
425
566
  l4Endpoints: {
426
567
  entity: l4EndpointEntity,
427
568
  multiple: true
569
+ },
570
+ l7Endpoints: {
571
+ entity: l7EndpointEntity,
572
+ multiple: true
428
573
  }
429
574
  },
430
575
  meta: {
@@ -440,286 +585,103 @@ var endpointFilter = defineUnit({
440
585
  path: "units/network/endpoint-filter"
441
586
  }
442
587
  });
443
- var l34EndpointSchema = z.union([
444
- z.intersection(
445
- l3EndpointEntity.schema,
446
- z.object({
447
- port: z.undefined().optional(),
448
- protocol: z.undefined().optional()
449
- })
450
- ),
451
- l4EndpointEntity.schema
452
- ]);
453
- function prefixWith(string, prefix) {
454
- return prefix ? `${prefix}${string.charAt(0).toUpperCase()}${string.slice(1)}` : string;
455
- }
456
- function prefixKeysWith(prefix, obj) {
457
- return Object.fromEntries(
458
- Object.entries(obj).map(([key, value]) => [prefixWith(key, prefix), value])
459
- );
460
- }
461
- var arrayPatchModeSchema = z.enum(["prepend", "replace"]);
462
- var booleanPatchSchema = z.enum(["keep", "true", "false"]);
463
588
 
464
- // src/dns.ts
465
- var providerEntity = defineEntity({
466
- type: "dns.provider.v1",
467
- schema: z.object({
468
- /**
469
- * The ID of the DNS provider unique within the system.
470
- */
471
- id: z.string().meta({ title: camelCaseToHumanReadable("id"), description: `The ID of the DNS provider unique within the system.` }),
589
+ // src/network/address-space.ts
590
+ var addressSpaceEntity = defineEntity({
591
+ type: "network.address-space.v1",
592
+ includes: {
472
593
  /**
473
- * The domain apex for which the DNS records will be created.
474
- *
475
- * If the provider manages multiple domains, the separate provider entity should be created for each domain.
476
- */
477
- domain: z.string().meta({ title: camelCaseToHumanReadable("domain"), description: `The domain apex for which the DNS records will be created.
478
-
479
- If the provider manages multiple domains, the separate provider entity should be created for each domain.` }),
480
- /**
481
- * The reference to the implementation of the DNS provider.
594
+ * The minimal set of subnets that fully cover the address space.
482
595
  */
483
- implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the DNS provider.` })
484
- }),
596
+ subnets: {
597
+ entity: subnetEntity,
598
+ multiple: true
599
+ }
600
+ },
601
+ schema: z.unknown(),
485
602
  meta: {
486
- color: "#FF5722"
603
+ description: `The entity representing a network address space.`,
604
+ color: "#3F51B5"
487
605
  }
488
606
  });
489
- var recordSet = defineUnit({
490
- type: "dns.record-set.v1",
607
+ var addressSpace = defineUnit({
608
+ type: "network.address-space.v1",
491
609
  args: {
492
- ...createArgs(),
493
- /**
494
- * The values of the DNS record.
495
- */
496
- values: $addArgumentDescription(z.string().array().default([]), `The values of the DNS record.`),
497
610
  /**
498
- * The TTL of the DNS record.
499
- */
500
- ttl: $addArgumentDescription(z.number().optional(), `The TTL of the DNS record.`),
501
- /**
502
- * The priority of the DNS record.
611
+ * The list of addresses to include in the address space.
612
+ *
613
+ * The supported formats are:
614
+ * - Single IP address (e.g., `192.168.1.1`);
615
+ * - CIDR notation (e.g., `192.168.1.1/24`);
616
+ * - Dash notation (e.g., `192.168.1.1-192.168.1.254`).
617
+ *
618
+ * The addresses can be a mix of IPv4 and IPv6.
503
619
  */
504
- priority: $addArgumentDescription(z.number().optional(), `The priority of the DNS record.`),
620
+ included: $addArgumentDescription(z.string().array().default([]), `The list of addresses to include in the address space.
621
+
622
+ The supported formats are:
623
+ - Single IP address (e.g., \`192.168.1.1\`);
624
+ - CIDR notation (e.g., \`192.168.1.1/24\`);
625
+ - Dash notation (e.g., \`192.168.1.1-192.168.1.254\`).
626
+
627
+ The addresses can be a mix of IPv4 and IPv6.`),
505
628
  /**
506
- * Whether the DNS record is proxied.
629
+ * The list of addresses to exclude from the `addresses` list.
507
630
  *
508
- * Available only for public IPs and some DNS providers like Cloudflare.
631
+ * The supported formats are the same as in `addresses`.
509
632
  */
510
- proxied: $addArgumentDescription(z.boolean().default(false), `Whether the DNS record is proxied.
633
+ excluded: $addArgumentDescription(z.string().array().default([]), `The list of addresses to exclude from the \`addresses\` list.
511
634
 
512
- Available only for public IPs and some DNS providers like Cloudflare.`)
635
+ The supported formats are the same as in \`addresses\`.`)
513
636
  },
514
637
  inputs: {
515
638
  /**
516
- * The DNS providers to use to create the DNS records.
517
- *
518
- * For each provider, a separate DNS record will be created.
639
+ * The endpoints to include in the address space.
519
640
  */
520
- dnsProviders: $addInputDescription({
521
- entity: providerEntity,
522
- multiple: true
523
- }, `The DNS providers to use to create the DNS records.
524
-
525
- For each provider, a separate DNS record will be created.`),
526
- /**
527
- * The L3 endpoints to use as values of the DNS records.
528
- */
529
- l3Endpoints: $addInputDescription({
641
+ included: $addInputDescription({
530
642
  entity: l3EndpointEntity,
531
- required: false,
532
- multiple: true
533
- }, `The L3 endpoints to use as values of the DNS records.`),
643
+ multiple: true,
644
+ required: false
645
+ }, `The endpoints to include in the address space.`),
534
646
  /**
535
- * The L4 endpoints to use as values of the DNS records.
647
+ * The endpoints to exclude from the `included` list.
536
648
  */
537
- l4Endpoints: $addInputDescription({
538
- entity: l4EndpointEntity,
539
- required: false,
540
- multiple: true
541
- }, `The L4 endpoints to use as values of the DNS records.`)
649
+ excluded: $addInputDescription({
650
+ entity: l3EndpointEntity,
651
+ multiple: true,
652
+ required: false
653
+ }, `The endpoints to exclude from the \`included\` list.`)
542
654
  },
543
655
  outputs: {
544
- l3Endpoints: {
545
- entity: l3EndpointEntity,
546
- multiple: true
547
- },
548
- l4Endpoints: {
549
- entity: l4EndpointEntity,
550
- multiple: true
551
- }
656
+ /**
657
+ * The address space entity representing the created address space.
658
+ */
659
+ addressSpace: $addInputDescription(addressSpaceEntity, `The address space entity representing the created address space.`)
552
660
  },
553
661
  meta: {
554
- title: "DNS Record Set",
555
- description: "A set of DNS records to be created.",
556
- icon: "mdi:server",
557
- defaultNamePrefix: "record",
662
+ description: `Defines an address space from a list of addresses/subnets/ranges.`,
663
+ title: "Address Space",
664
+ icon: "mdi:network",
558
665
  category: "Network"
559
666
  },
560
667
  source: {
561
668
  package: "@highstate/common",
562
- path: "units/dns/record-set"
669
+ path: "units/network/address-space"
563
670
  }
564
671
  });
565
- function createArgs(prefix) {
566
- return prefixKeysWith(prefix, {
567
- /**
568
- * The FQDN to register the existing endpoints with.
569
- *
570
- * Will be inserted at the beginning of the resulting endpoint list.
571
- *
572
- * Will throw an error if no matching provider is found.
573
- */
574
- fqdn: z.string().optional(),
575
- /**
576
- * The endpoint filter to filter the endpoints before creating the DNS records.
577
- *
578
- * Possible values:
579
- *
580
- * - `public`: only endpoints exposed to the public internet;
581
- * - `external`: reachable from outside the system but not public (e.g., LAN, VPC);
582
- * - `internal`: reachable only from within the system boundary (e.g., inside a cluster).
583
- *
584
- * You can select one or more values.
585
- *
586
- * If no value is provided, the endpoints will be filtered by the most accessible type:
587
- *
588
- * - if any public endpoints exist, all public endpoints are selected;
589
- * - otherwise, if any external endpoints exist, all external endpoints are selected;
590
- * - if neither exist, all internal endpoints are selected.
591
- */
592
- endpointFilter: endpointFilterSchema.default([]),
593
- /**
594
- * The mode to use for patching the existing endpoints.
595
- *
596
- * - `prepend`: Prepend the FQDN to the existing endpoints. It will make them prioritized.
597
- * - `replace`: Replace the existing endpoints with the FQDN. It will ensure that the only the FQDN is used.
598
- *
599
- * The default is `prepend`.
600
- */
601
- patchMode: arrayPatchModeSchema.default("prepend")
602
- });
603
- }
604
- var inputs = {
605
- /**
606
- * The DNS providers to use to create the DNS records.
607
- *
608
- * If multiple providers match the domain, all of them will be used and multiple DNS records will be created.
609
- */
610
- dnsProviders: {
611
- entity: providerEntity,
612
- multiple: true
613
- }
614
- };
615
-
616
- // src/common/access-point.ts
617
- var gatewayEntity = defineEntity({
618
- type: "common.gateway.v1",
619
- schema: z.object({
620
- /**
621
- * The reference to the implementation of the gateway.
622
- */
623
- implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the gateway.` }),
624
- /**
625
- * The public L3 endpoints of the gateway.
626
- *
627
- * If not provided, should be automatically detected by the implementation.
628
- */
629
- endpoints: l3EndpointEntity.schema.array().default([]).meta({ title: camelCaseToHumanReadable("endpoints"), description: `The public L3 endpoints of the gateway.
630
672
 
631
- If not provided, should be automatically detected by the implementation.` })
632
- }),
633
- meta: {
634
- color: "#F57F17"
635
- }
636
- });
637
- var tlsIssuerEntity = defineEntity({
638
- type: "common.tls-issuer.v1",
639
- schema: z.object({
640
- /**
641
- * The domain apex for which the TLS issuer will manage certificates.
642
- */
643
- domain: z.string().meta({ title: camelCaseToHumanReadable("domain"), description: `The domain apex for which the TLS issuer will manage certificates.` }),
644
- /**
645
- * The reference to the implementation of the TLS issuer.
646
- */
647
- implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the TLS issuer.` })
648
- }),
649
- meta: {
650
- color: "#F57F17"
651
- }
652
- });
653
- var accessPointEntity = defineEntity({
654
- type: "common.access-point.v1",
655
- schema: z.object({
656
- /**
657
- * The gateway of the access point.
658
- */
659
- gateway: gatewayEntity.schema.meta({ title: camelCaseToHumanReadable("gateway"), description: `The gateway of the access point.` }),
660
- /**
661
- * The TLS issuers used to manage TLS certificates for the access point.
662
- */
663
- tlsIssuers: tlsIssuerEntity.schema.array().meta({ title: camelCaseToHumanReadable("tlsIssuers"), description: `The TLS issuers used to manage TLS certificates for the access point.` }),
664
- /**
665
- * The DNS providers used to manage the DNS records for the access point.
666
- */
667
- dnsProviders: providerEntity.schema.array().meta({ title: camelCaseToHumanReadable("dnsProviders"), description: `The DNS providers used to manage the DNS records for the access point.` }),
668
- /**
669
- * Whether the DNS records created for the access point should be proxied.
670
- */
671
- proxied: z.boolean().default(false).meta({ title: camelCaseToHumanReadable("proxied"), description: `Whether the DNS records created for the access point should be proxied.` })
672
- }),
673
- meta: {
674
- color: "#F57F17"
675
- }
676
- });
677
- var accessPoint = defineUnit({
678
- type: "common.access-point.v1",
679
- args: {
680
- /**
681
- * Whether the DNS records created for the access point should be proxied.
682
- *
683
- * This option is specific to certain DNS providers that support proxying, such as Cloudflare.
684
- * When enabled, the DNS records will be proxied through the provider's network, providing additional security and performance benefits.
685
- *
686
- * Defaults to `false`.
687
- */
688
- proxied: $addArgumentDescription(z.boolean().default(false), `Whether the DNS records created for the access point should be proxied.
689
-
690
- This option is specific to certain DNS providers that support proxying, such as Cloudflare.
691
- When enabled, the DNS records will be proxied through the provider's network, providing additional security and performance benefits.
692
-
693
- Defaults to \`false\`.`)
694
- },
695
- inputs: {
696
- gateway: gatewayEntity,
697
- tlsIssuers: {
698
- entity: tlsIssuerEntity,
699
- required: false,
700
- multiple: true
701
- },
702
- dnsProviders: {
703
- entity: providerEntity,
704
- required: false,
705
- multiple: true
706
- }
707
- },
708
- outputs: {
709
- accessPoint: accessPointEntity
710
- },
711
- meta: {
712
- description: `The access point unit which can be used to connect to services.
713
-
714
- It can be used to expose services and applications running in Kubernetes clusters or other environments.`,
715
- title: "Access Point",
716
- icon: "mdi:access-point",
717
- category: "Kubernetes"
718
- },
719
- source: {
720
- package: "@highstate/common",
721
- path: "units/access-point"
722
- }
673
+ // src/ssh.ts
674
+ var ssh_exports = {};
675
+ __export(ssh_exports, {
676
+ argsSchema: () => argsSchema,
677
+ connectionSchema: () => connectionSchema,
678
+ inputs: () => inputs,
679
+ keyPair: () => keyPair,
680
+ keyPairEntity: () => keyPairEntity,
681
+ keyTypeSchema: () => keyTypeSchema,
682
+ publicKey: () => publicKey,
683
+ publicKeyEntity: () => publicKeyEntity,
684
+ secrets: () => secrets
723
685
  });
724
686
  var checksumAlgorithmSchema = z.enum(["md5", "sha1", "sha256", "sha384", "sha512"]);
725
687
  var checksumSchema = z.object({
@@ -791,8 +753,22 @@ var remoteFile = defineUnit({
791
753
  args: {
792
754
  /**
793
755
  * The URL of the remote file.
756
+ *
757
+ * Either this or the 'endpoint' input must be provided.
794
758
  */
795
- url: $addArgumentDescription(z.string().optional(), `The URL of the remote file.`)
759
+ url: $addArgumentDescription(z.string().optional(), `The URL of the remote file.
760
+
761
+ Either this or the 'endpoint' input must be provided.`),
762
+ /**
763
+ * The name of the file.
764
+ *
765
+ * If not provided, the name will be derived from the URL or endpoint path.
766
+ * If not possible, the name of the unit will be used.
767
+ */
768
+ fileName: $addArgumentDescription(z.string().optional(), `The name of the file.
769
+
770
+ If not provided, the name will be derived from the URL or endpoint path.
771
+ If not possible, the name of the unit will be used.`)
796
772
  },
797
773
  inputs: {
798
774
  /**
@@ -819,19 +795,9 @@ var remoteFile = defineUnit({
819
795
  });
820
796
 
821
797
  // src/ssh.ts
822
- var ssh_exports = {};
823
- __export(ssh_exports, {
824
- argsSchema: () => argsSchema,
825
- connectionSchema: () => connectionSchema,
826
- inputs: () => inputs2,
827
- keyPair: () => keyPair,
828
- keyPairEntity: () => keyPairEntity,
829
- keyTypeSchema: () => keyTypeSchema,
830
- secrets: () => secrets
831
- });
832
798
  var keyTypeSchema = z.enum(["ed25519"]);
833
- var keyPairEntity = defineEntity({
834
- type: "ssh.key-pair.v1",
799
+ var publicKeyEntity = defineEntity({
800
+ type: "ssh.public-key.v1",
835
801
  schema: z.object({
836
802
  /**
837
803
  * The type of the SSH key.
@@ -841,14 +807,23 @@ var keyPairEntity = defineEntity({
841
807
  type: keyTypeSchema.meta({ title: camelCaseToHumanReadable("type"), description: `The type of the SSH key.
842
808
 
843
809
  For now, only \`ed25519\` is supported.` }),
844
- /**
845
- * The fingerprint of the SSH key.
846
- */
847
- fingerprint: z.string().meta({ title: camelCaseToHumanReadable("fingerprint"), description: `The fingerprint of the SSH key.` }),
848
810
  /**
849
811
  * The public key in OpenSSH format.
850
812
  */
851
813
  publicKey: z.string().meta({ title: camelCaseToHumanReadable("publicKey"), description: `The public key in OpenSSH format.` }),
814
+ /**
815
+ * The fingerprint of the SSH key.
816
+ */
817
+ fingerprint: z.string().meta({ title: camelCaseToHumanReadable("fingerprint"), description: `The fingerprint of the SSH key.` })
818
+ }),
819
+ meta: {
820
+ color: "#2b5797"
821
+ }
822
+ });
823
+ var keyPairEntity = defineEntity({
824
+ type: "ssh.key-pair.v1",
825
+ extends: { publicKeyEntity },
826
+ schema: z.object({
852
827
  /**
853
828
  * The private key in PEM format.
854
829
  */
@@ -913,14 +888,51 @@ var secrets = $secrets({
913
888
  */
914
889
  sshPassword: $addArgumentDescription(z.string().optional(), `The SSH password to use for authentication.`)
915
890
  });
916
- var inputs2 = $inputs({
891
+ var inputs = $inputs({
917
892
  /**
918
- * The SSH key pair to use for authentication.
893
+ * The SSH key pair to use for authentication by Highstate.
919
894
  */
920
895
  sshKeyPair: $addInputDescription({
921
896
  entity: keyPairEntity,
922
897
  required: false
923
- }, `The SSH key pair to use for authentication.`)
898
+ }, `The SSH key pair to use for authentication by Highstate.`),
899
+ /**
900
+ * The extra SSH public keys to add to the server's `authorized_keys` file.
901
+ *
902
+ * Will not (and cannot) be used for authentication by Highstate.
903
+ */
904
+ sshPublicKeys: $addInputDescription({
905
+ entity: publicKeyEntity,
906
+ required: false,
907
+ multiple: true
908
+ }, `The extra SSH public keys to add to the server's \`authorized_keys\` file.
909
+
910
+ Will not (and cannot) be used for authentication by Highstate.`)
911
+ });
912
+ var publicKey = defineUnit({
913
+ type: "ssh.public-key.v1",
914
+ args: {
915
+ /**
916
+ * The public key in OpenSSH format.
917
+ */
918
+ publicKey: $addArgumentDescription(z.string().meta({ multiline: true }), `The public key in OpenSSH format.`)
919
+ },
920
+ outputs: {
921
+ publicKey: publicKeyEntity
922
+ },
923
+ meta: {
924
+ description: `Provides existing SSH public key.`,
925
+ title: "SSH Public Key",
926
+ category: "ssh",
927
+ icon: "charm:key",
928
+ iconColor: "#ffffff",
929
+ secondaryIcon: "mdi:lock-open",
930
+ secondaryIconColor: "#ffffff"
931
+ },
932
+ source: {
933
+ package: "@highstate/common",
934
+ path: "units/ssh/public-key"
935
+ }
924
936
  });
925
937
  var keyPair = defineUnit({
926
938
  type: "ssh.key-pair.v1",
@@ -956,9 +968,14 @@ var keyPair = defineUnit({
956
968
  // src/common/server.ts
957
969
  var serverEntity = defineEntity({
958
970
  type: "common.server.v1",
971
+ includes: {
972
+ endpoints: {
973
+ entity: l3EndpointEntity,
974
+ multiple: true
975
+ }
976
+ },
959
977
  schema: z.object({
960
978
  hostname: z.string(),
961
- endpoints: l3EndpointEntity.schema.array(),
962
979
  ssh: connectionSchema.optional()
963
980
  }),
964
981
  meta: {
@@ -974,14 +991,7 @@ var serverOutputs = $outputs({
974
991
  /**
975
992
  * The server entity representing the server.
976
993
  */
977
- server: $addInputDescription(serverEntity, `The server entity representing the server.`),
978
- /**
979
- * The L3 endpoints of the server.
980
- */
981
- endpoints: $addInputDescription({
982
- entity: l3EndpointEntity,
983
- multiple: true
984
- }, `The L3 endpoints of the server.`)
994
+ server: $addInputDescription(serverEntity, `The server entity representing the server.`)
985
995
  });
986
996
  var vmSshArgs = argsSchema.omit({ user: true }).prefault({});
987
997
  var vmSecrets = $secrets({
@@ -1022,11 +1032,12 @@ var existingServer = defineUnit({
1022
1032
  ...secrets
1023
1033
  },
1024
1034
  inputs: {
1025
- endpoint: {
1035
+ endpoints: {
1026
1036
  entity: l3EndpointEntity,
1027
- required: false
1037
+ required: false,
1038
+ multiple: true
1028
1039
  },
1029
- ...inputs2
1040
+ ...inputs
1030
1041
  },
1031
1042
  outputs: serverOutputs,
1032
1043
  meta: {
@@ -1045,129 +1056,443 @@ var serverPatch = defineUnit({
1045
1056
  type: "common.server-patch.v1",
1046
1057
  args: {
1047
1058
  /**
1048
- * The endpoints of the server.
1059
+ * The new hostname of the server.
1049
1060
  *
1050
- * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1061
+ * If not specified, the existing hostname will be kept.
1062
+ */
1063
+ hostname: $addArgumentDescription(z.string().optional(), `The new hostname of the server.
1064
+
1065
+ If not specified, the existing hostname will be kept.`),
1066
+ /**
1067
+ * The endpoints to set on the server.
1051
1068
  *
1052
- * The same server may also be represented by multiple entries (e.g. a node with private and public IP).
1069
+ * If not specified, the existing endpoints will be kept.
1070
+ */
1071
+ endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints to set on the server.
1072
+
1073
+ If not specified, the existing endpoints will be kept.`)
1074
+ },
1075
+ inputs: {
1076
+ server: serverEntity,
1077
+ endpoints: {
1078
+ entity: l3EndpointEntity,
1079
+ required: false,
1080
+ multiple: true
1081
+ }
1082
+ },
1083
+ outputs: {
1084
+ ...serverOutputs
1085
+ },
1086
+ meta: {
1087
+ description: `Patches some properties of the server and outputs the updated server.`,
1088
+ title: "Server Patch",
1089
+ icon: "mdi:server",
1090
+ secondaryIcon: "fluent:patch-20-filled",
1091
+ category: "Infrastructure"
1092
+ },
1093
+ source: {
1094
+ package: "@highstate/common",
1095
+ path: "units/server-patch"
1096
+ }
1097
+ });
1098
+ var script = defineUnit({
1099
+ type: "common.script.v1",
1100
+ args: {
1101
+ script: z.string().meta({ language: "shell" }),
1102
+ updateScript: z.string().optional().meta({ language: "shell" }),
1103
+ deleteScript: z.string().optional().meta({ language: "shell" })
1104
+ },
1105
+ inputs: {
1106
+ server: serverEntity
1107
+ },
1108
+ outputs: {
1109
+ server: serverEntity
1110
+ },
1111
+ meta: {
1112
+ description: `Runs a shell script on the server.`,
1113
+ title: "Shell Script",
1114
+ icon: "mdi:bash",
1115
+ category: "Infrastructure"
1116
+ },
1117
+ source: {
1118
+ package: "@highstate/common",
1119
+ path: "units/script"
1120
+ }
1121
+ });
1122
+
1123
+ // src/dns.ts
1124
+ var providerEntity = defineEntity({
1125
+ type: "dns.provider.v1",
1126
+ schema: z.object({
1127
+ /**
1128
+ * The ID of the DNS provider unique within the system.
1129
+ */
1130
+ id: z.string().meta({ title: camelCaseToHumanReadable("id"), description: `The ID of the DNS provider unique within the system.` }),
1131
+ /**
1132
+ * The zones managed by the DNS provider.
1133
+ */
1134
+ zones: z.string().array().meta({ title: camelCaseToHumanReadable("zones"), description: `The zones managed by the DNS provider.` }),
1135
+ /**
1136
+ * The reference to the implementation of the DNS provider.
1137
+ */
1138
+ implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the DNS provider.` })
1139
+ }),
1140
+ meta: {
1141
+ color: "#FF5722"
1142
+ }
1143
+ });
1144
+ var recordSet = defineUnit({
1145
+ type: "dns.record-set.v1",
1146
+ args: {
1147
+ /**
1148
+ * The FQDN of the DNS to create.
1149
+ *
1150
+ * If not provided, the name of the unit will be used.
1151
+ */
1152
+ recordName: $addArgumentDescription(z.string().optional(), `The FQDN of the DNS to create.
1153
+
1154
+ If not provided, the name of the unit will be used.`),
1155
+ /**
1156
+ * The values of the DNS record.
1157
+ *
1158
+ * Will be parsed as endpoints and merged with provided L3/L4/L7 endpoint inputs.
1159
+ */
1160
+ values: $addArgumentDescription(z.string().array().default([]), `The values of the DNS record.
1161
+
1162
+ Will be parsed as endpoints and merged with provided L3/L4/L7 endpoint inputs.`),
1163
+ ...mapValues(
1164
+ //
1165
+ pick(networkArgs, ["endpointFilter"]),
1166
+ (arg) => ({ ...arg, schema: arg.schema.default(`type != "hostname"`) })
1167
+ ),
1168
+ /**
1169
+ * The TTL of the DNS record.
1170
+ */
1171
+ ttl: $addArgumentDescription(z.number().optional(), `The TTL of the DNS record.`),
1172
+ /**
1173
+ * The priority of the DNS record.
1174
+ */
1175
+ priority: $addArgumentDescription(z.number().optional(), `The priority of the DNS record.`),
1176
+ /**
1177
+ * Whether the DNS record is proxied.
1178
+ *
1179
+ * Available only for public IPs and some DNS providers like Cloudflare.
1180
+ */
1181
+ proxied: $addArgumentDescription(z.boolean().default(false), `Whether the DNS record is proxied.
1182
+
1183
+ Available only for public IPs and some DNS providers like Cloudflare.`),
1184
+ /**
1185
+ * Wait for the DNS record creation/update to be visible at local DNS before continuing.
1186
+ */
1187
+ waitLocal: $addArgumentDescription(z.boolean().default(true), `Wait for the DNS record creation/update to be visible at local DNS before continuing.`)
1188
+ },
1189
+ inputs: {
1190
+ /**
1191
+ * The DNS providers to use to create the DNS records.
1192
+ *
1193
+ * For each provider, a separate DNS record will be created.
1194
+ */
1195
+ dnsProviders: $addInputDescription({
1196
+ entity: providerEntity,
1197
+ multiple: true
1198
+ }, `The DNS providers to use to create the DNS records.
1199
+
1200
+ For each provider, a separate DNS record will be created.`),
1201
+ /**
1202
+ * The servers to wait for the DNS records to be visible at before continuing.
1203
+ */
1204
+ waitServers: $addInputDescription({
1205
+ entity: serverEntity,
1206
+ required: false,
1207
+ multiple: true
1208
+ }, `The servers to wait for the DNS records to be visible at before continuing.`),
1209
+ /**
1210
+ * The L3 endpoints to use as values of the DNS records.
1211
+ */
1212
+ l3Endpoints: $addInputDescription({
1213
+ entity: l3EndpointEntity,
1214
+ required: false,
1215
+ multiple: true
1216
+ }, `The L3 endpoints to use as values of the DNS records.`),
1217
+ /**
1218
+ * The L4 endpoints to use as values of the DNS records.
1053
1219
  */
1054
- endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the server.
1220
+ l4Endpoints: $addInputDescription({
1221
+ entity: l4EndpointEntity,
1222
+ required: false,
1223
+ multiple: true
1224
+ }, `The L4 endpoints to use as values of the DNS records.`),
1225
+ /**
1226
+ * The L7 endpoints to use as values of the DNS records.
1227
+ */
1228
+ l7Endpoints: $addInputDescription({
1229
+ entity: l4EndpointEntity,
1230
+ required: false,
1231
+ multiple: true
1232
+ }, `The L7 endpoints to use as values of the DNS records.`)
1233
+ },
1234
+ outputs: {
1235
+ /**
1236
+ * The filtered L3 endpoints with all IPs replaced with FQDNs.
1237
+ * The duplicates are removed and metadata is merged.
1238
+ */
1239
+ l3Endpoints: $addInputDescription({
1240
+ entity: l3EndpointEntity,
1241
+ multiple: true
1242
+ }, `The filtered L3 endpoints with all IPs replaced with FQDNs.
1243
+ The duplicates are removed and metadata is merged.`),
1244
+ /**
1245
+ * The filtered L4 endpoints with all IPs replaced with FQDNs.
1246
+ * The duplicates are removed and metadata is merged.
1247
+ */
1248
+ l4Endpoints: $addInputDescription({
1249
+ entity: l4EndpointEntity,
1250
+ multiple: true
1251
+ }, `The filtered L4 endpoints with all IPs replaced with FQDNs.
1252
+ The duplicates are removed and metadata is merged.`),
1253
+ /**
1254
+ * The filtered L7 endpoints with all IPs replaced with FQDNs.
1255
+ * The duplicates are removed and metadata is merged.
1256
+ */
1257
+ l7Endpoints: $addInputDescription({
1258
+ entity: l4EndpointEntity,
1259
+ multiple: true
1260
+ }, `The filtered L7 endpoints with all IPs replaced with FQDNs.
1261
+ The duplicates are removed and metadata is merged.`)
1262
+ },
1263
+ meta: {
1264
+ title: "DNS Record Set",
1265
+ description: "A set of DNS records to be created.",
1266
+ icon: "mdi:server",
1267
+ defaultNamePrefix: "record",
1268
+ category: "Network"
1269
+ },
1270
+ source: {
1271
+ package: "@highstate/common",
1272
+ path: "units/dns/record-set"
1273
+ }
1274
+ });
1275
+ var inputs2 = {
1276
+ /**
1277
+ * The DNS providers to use to create the DNS records.
1278
+ *
1279
+ * If multiple providers match the domain, all of them will be used and multiple DNS records will be created.
1280
+ */
1281
+ dnsProviders: {
1282
+ entity: providerEntity,
1283
+ multiple: true
1284
+ }
1285
+ };
1055
1286
 
1056
- The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1287
+ // src/common/access-point.ts
1288
+ var gatewayEntity = defineEntity({
1289
+ type: "common.gateway.v1",
1290
+ schema: z.object({
1291
+ /**
1292
+ * The reference to the implementation of the gateway.
1293
+ */
1294
+ implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the gateway.` }),
1295
+ /**
1296
+ * The public L3 endpoints of the gateway.
1297
+ *
1298
+ * If not provided, should be automatically detected by the implementation.
1299
+ */
1300
+ endpoints: l3EndpointEntity.schema.array().default([]).meta({ title: camelCaseToHumanReadable("endpoints"), description: `The public L3 endpoints of the gateway.
1057
1301
 
1058
- The same server may also be represented by multiple entries (e.g. a node with private and public IP).`),
1302
+ If not provided, should be automatically detected by the implementation.` })
1303
+ }),
1304
+ meta: {
1305
+ color: "#F57F17"
1306
+ }
1307
+ });
1308
+ var tlsIssuerEntity = defineEntity({
1309
+ type: "common.tls-issuer.v1",
1310
+ schema: z.object({
1311
+ /**
1312
+ * The zones for which the TLS issuer will manage certificates.
1313
+ */
1314
+ zones: z.string().array().meta({ title: camelCaseToHumanReadable("zones"), description: `The zones for which the TLS issuer will manage certificates.` }),
1315
+ /**
1316
+ * The reference to the implementation of the TLS issuer.
1317
+ */
1318
+ implRef: implementationReferenceSchema.meta({ title: camelCaseToHumanReadable("implRef"), description: `The reference to the implementation of the TLS issuer.` })
1319
+ }),
1320
+ meta: {
1321
+ color: "#F57F17"
1322
+ }
1323
+ });
1324
+ var accessPointEntity = defineEntity({
1325
+ type: "common.access-point.v1",
1326
+ schema: z.object({
1327
+ /**
1328
+ * The gateway of the access point.
1329
+ */
1330
+ gateway: gatewayEntity.schema.meta({ title: camelCaseToHumanReadable("gateway"), description: `The gateway of the access point.` }),
1331
+ /**
1332
+ * The TLS issuers used to manage TLS certificates for the access point.
1333
+ */
1334
+ tlsIssuers: tlsIssuerEntity.schema.array().meta({ title: camelCaseToHumanReadable("tlsIssuers"), description: `The TLS issuers used to manage TLS certificates for the access point.` }),
1335
+ /**
1336
+ * The DNS providers used to manage the DNS records for the access point.
1337
+ */
1338
+ dnsProviders: providerEntity.schema.array().meta({ title: camelCaseToHumanReadable("dnsProviders"), description: `The DNS providers used to manage the DNS records for the access point.` }),
1339
+ /**
1340
+ * Whether the DNS records created for the access point should be proxied.
1341
+ */
1342
+ proxied: z.boolean().default(false).meta({ title: camelCaseToHumanReadable("proxied"), description: `Whether the DNS records created for the access point should be proxied.` })
1343
+ }),
1344
+ meta: {
1345
+ color: "#F57F17"
1346
+ }
1347
+ });
1348
+ var accessPoint = defineUnit({
1349
+ type: "common.access-point.v1",
1350
+ args: {
1059
1351
  /**
1060
- * The mode to use for patching the endpoints.
1352
+ * Whether the DNS records created for the access point should be proxied.
1353
+ *
1354
+ * This option is specific to certain DNS providers that support proxying, such as Cloudflare.
1355
+ * When enabled, the DNS records will be proxied through the provider's network, providing additional security and performance benefits.
1061
1356
  *
1062
- * - `prepend`: prepend the new endpoints to the existing ones (default);
1063
- * - `replace`: replace the existing endpoints with the new ones.
1357
+ * Defaults to `false`.
1064
1358
  */
1065
- endpointsPatchMode: $addArgumentDescription(arrayPatchModeSchema.default("prepend"), `The mode to use for patching the endpoints.
1359
+ proxied: $addArgumentDescription(z.boolean().default(false), `Whether the DNS records created for the access point should be proxied.
1360
+
1361
+ This option is specific to certain DNS providers that support proxying, such as Cloudflare.
1362
+ When enabled, the DNS records will be proxied through the provider's network, providing additional security and performance benefits.
1066
1363
 
1067
- - \`prepend\`: prepend the new endpoints to the existing ones (default);
1068
- - \`replace\`: replace the existing endpoints with the new ones.`)
1364
+ Defaults to \`false\`.`)
1069
1365
  },
1070
1366
  inputs: {
1071
- server: serverEntity,
1072
- endpoints: {
1073
- entity: l3EndpointEntity,
1367
+ gateway: gatewayEntity,
1368
+ tlsIssuers: {
1369
+ entity: tlsIssuerEntity,
1074
1370
  required: false,
1075
1371
  multiple: true
1076
- }
1077
- },
1078
- outputs: {
1079
- ...serverOutputs
1080
- },
1081
- meta: {
1082
- description: `Patches some properties of the server and outputs the updated server.`,
1083
- title: "Server Patch",
1084
- icon: "mdi:server",
1085
- secondaryIcon: "fluent:patch-20-filled",
1086
- category: "Infrastructure"
1087
- },
1088
- source: {
1089
- package: "@highstate/common",
1090
- path: "units/server-patch"
1091
- }
1092
- });
1093
- var serverDns = defineUnit({
1094
- type: "common.server-dns.v1",
1095
- args: createArgs(),
1096
- inputs: {
1097
- server: serverEntity,
1098
- ...inputs
1099
- },
1100
- outputs: {
1101
- server: serverEntity,
1102
- endpoints: {
1103
- entity: l3EndpointEntity,
1372
+ },
1373
+ dnsProviders: {
1374
+ entity: providerEntity,
1375
+ required: false,
1104
1376
  multiple: true
1105
1377
  }
1106
1378
  },
1107
- meta: {
1108
- description: `Creates a DNS record for the server and updates the endpoints.
1109
-
1110
- The DNS record will be created with the provided FQDN and the endpoints will be updated with the DNS record.`,
1111
- title: "Server DNS",
1112
- icon: "mdi:server",
1113
- secondaryIcon: "mdi:dns",
1114
- category: "Infrastructure"
1115
- },
1116
- source: {
1117
- package: "@highstate/common",
1118
- path: "units/server-dns"
1119
- }
1120
- });
1121
- var script = defineUnit({
1122
- type: "common.script.v1",
1123
- args: {
1124
- script: z.string().meta({ language: "shell" }),
1125
- updateScript: z.string().optional().meta({ language: "shell" }),
1126
- deleteScript: z.string().optional().meta({ language: "shell" })
1127
- },
1128
- inputs: {
1129
- server: serverEntity
1130
- },
1131
1379
  outputs: {
1132
- server: serverEntity
1380
+ accessPoint: accessPointEntity
1133
1381
  },
1134
1382
  meta: {
1135
- description: `Runs a shell script on the server.`,
1136
- title: "Shell Script",
1137
- icon: "mdi:bash",
1138
- category: "Infrastructure"
1383
+ description: `The access point unit which can be used to connect to services.
1384
+
1385
+ It can be used to expose services and applications running in Kubernetes clusters or other environments.`,
1386
+ title: "Access Point",
1387
+ icon: "mdi:access-point",
1388
+ category: "Kubernetes"
1139
1389
  },
1140
1390
  source: {
1141
1391
  package: "@highstate/common",
1142
- path: "units/script"
1392
+ path: "units/access-point"
1143
1393
  }
1144
1394
  });
1145
1395
 
1146
1396
  // src/databases/index.ts
1147
1397
  var databases_exports = {};
1148
1398
  __export(databases_exports, {
1399
+ etcdEntity: () => etcdEntity,
1400
+ etcdPatch: () => etcdPatch,
1401
+ existingEtcd: () => existingEtcd,
1149
1402
  existingMariadb: () => existingMariadb,
1150
1403
  existingMongodb: () => existingMongodb,
1151
1404
  existingPostgresql: () => existingPostgresql,
1152
1405
  existingRedis: () => existingRedis,
1153
1406
  existingS3: () => existingS3,
1154
1407
  mariadbEntity: () => mariadbEntity,
1408
+ mariadbPatch: () => mariadbPatch,
1155
1409
  mongodbEntity: () => mongodbEntity,
1410
+ mongodbPatch: () => mongodbPatch,
1411
+ optionalSharedArgs: () => optionalSharedArgs,
1156
1412
  postgresqlEntity: () => postgresqlEntity,
1413
+ postgresqlPatch: () => postgresqlPatch,
1157
1414
  redisEntity: () => redisEntity,
1415
+ redisPatch: () => redisPatch,
1158
1416
  s3BucketPolicySchema: () => s3BucketPolicySchema,
1159
1417
  s3BucketSchema: () => s3BucketSchema,
1160
1418
  s3Entity: () => s3Entity,
1419
+ s3Patch: () => s3Patch,
1161
1420
  sharedArgs: () => sharedArgs,
1162
1421
  sharedInputs: () => sharedInputs,
1163
1422
  sharedSchema: () => sharedSchema,
1164
1423
  sharedSecrets: () => sharedSecrets
1165
1424
  });
1425
+ var etcdArgs = {
1426
+ endpoints: {
1427
+ schema: z.string().array().default([])
1428
+ }
1429
+ };
1430
+ var etcdEntity = defineEntity({
1431
+ type: "databases.etcd.v1",
1432
+ includes: {
1433
+ endpoints: {
1434
+ entity: l4EndpointEntity,
1435
+ multiple: true
1436
+ }
1437
+ },
1438
+ schema: z.unknown(),
1439
+ meta: {
1440
+ description: `Represents the etcd database instance.`,
1441
+ color: "#0064bf"
1442
+ }
1443
+ });
1444
+ var existingEtcd = defineUnit({
1445
+ type: "databases.etcd.existing.v1",
1446
+ args: etcdArgs,
1447
+ inputs: {
1448
+ endpoints: {
1449
+ entity: l4EndpointEntity,
1450
+ multiple: true,
1451
+ required: false
1452
+ }
1453
+ },
1454
+ outputs: {
1455
+ etcd: etcdEntity
1456
+ },
1457
+ source: {
1458
+ package: "@highstate/common",
1459
+ path: "units/databases/existing-etcd"
1460
+ },
1461
+ meta: {
1462
+ description: `The existing etcd database instance.`,
1463
+ title: "Existing etcd Database",
1464
+ icon: "simple-icons:etcd",
1465
+ secondaryIcon: "mdi:database",
1466
+ category: "Databases"
1467
+ }
1468
+ });
1469
+ var etcdPatch = defineUnit({
1470
+ type: "databases.etcd-patch.v1",
1471
+ args: toPatchArgs(etcdArgs),
1472
+ inputs: {
1473
+ etcd: etcdEntity,
1474
+ endpoints: {
1475
+ entity: l4EndpointEntity,
1476
+ multiple: true,
1477
+ required: false
1478
+ }
1479
+ },
1480
+ outputs: {
1481
+ etcd: etcdEntity
1482
+ },
1483
+ source: {
1484
+ package: "@highstate/common",
1485
+ path: "units/databases/etcd-patch"
1486
+ },
1487
+ meta: {
1488
+ description: `Patches some properties of the etcd database and outputs the updated database.`,
1489
+ title: "etcd Patch",
1490
+ icon: "simple-icons:etcd",
1491
+ secondaryIcon: "fluent:patch-20-filled",
1492
+ category: "Databases"
1493
+ }
1494
+ });
1166
1495
  var sharedSchema = z.object({
1167
- /**
1168
- * The endpoints to connect to the database.
1169
- */
1170
- endpoints: l4EndpointEntity.schema.array().meta({ title: camelCaseToHumanReadable("endpoints"), description: `The endpoints to connect to the database.` }),
1171
1496
  /**
1172
1497
  * The username to connect to the database with.
1173
1498
  */
@@ -1199,6 +1524,10 @@ var sharedArgs = $args({
1199
1524
  */
1200
1525
  database: $addArgumentDescription(z.string().optional(), `The name of the database to connect to.`)
1201
1526
  });
1527
+ var optionalSharedArgs = mapValues(sharedArgs, (arg) => ({
1528
+ ...arg,
1529
+ schema: arg.schema.optional()
1530
+ }));
1202
1531
  var sharedSecrets = $secrets({
1203
1532
  /**
1204
1533
  * The password to connect to the database with.
@@ -1219,6 +1548,12 @@ var sharedInputs = $inputs({
1219
1548
  // src/databases/mariadb.ts
1220
1549
  var mariadbEntity = defineEntity({
1221
1550
  type: "databases.mariadb.v1",
1551
+ includes: {
1552
+ endpoints: {
1553
+ entity: l4EndpointEntity,
1554
+ multiple: true
1555
+ }
1556
+ },
1222
1557
  schema: sharedSchema,
1223
1558
  meta: {
1224
1559
  description: `Represents the MariaDB database or virtual database behind it.`,
@@ -1245,8 +1580,42 @@ var existingMariadb = defineUnit({
1245
1580
  category: "Databases"
1246
1581
  }
1247
1582
  });
1583
+ var mariadbPatch = defineUnit({
1584
+ type: "databases.mariadb-patch.v1",
1585
+ args: {
1586
+ ...toPatchArgs(optionalSharedArgs),
1587
+ endpoints: {
1588
+ ...sharedArgs.endpoints,
1589
+ schema: z.string().array().default([])
1590
+ }
1591
+ },
1592
+ inputs: {
1593
+ mariadb: mariadbEntity,
1594
+ ...sharedInputs
1595
+ },
1596
+ outputs: {
1597
+ mariadb: mariadbEntity
1598
+ },
1599
+ source: {
1600
+ package: "@highstate/common",
1601
+ path: "units/databases/mariadb-patch"
1602
+ },
1603
+ meta: {
1604
+ description: `Patches some properties of the MariaDB database and outputs the updated database.`,
1605
+ title: "MariaDB Patch",
1606
+ icon: "simple-icons:mariadb",
1607
+ secondaryIcon: "fluent:patch-20-filled",
1608
+ category: "Databases"
1609
+ }
1610
+ });
1248
1611
  var mongodbEntity = defineEntity({
1249
1612
  type: "databases.mongodb.v1",
1613
+ includes: {
1614
+ endpoints: {
1615
+ entity: l4EndpointEntity,
1616
+ multiple: true
1617
+ }
1618
+ },
1250
1619
  schema: sharedSchema,
1251
1620
  meta: {
1252
1621
  description: `Represents the MongoDB database or virtual database behind it.`,
@@ -1273,8 +1642,42 @@ var existingMongodb = defineUnit({
1273
1642
  category: "Databases"
1274
1643
  }
1275
1644
  });
1645
+ var mongodbPatch = defineUnit({
1646
+ type: "databases.mongodb-patch.v1",
1647
+ args: {
1648
+ ...toPatchArgs(optionalSharedArgs),
1649
+ endpoints: {
1650
+ ...sharedArgs.endpoints,
1651
+ schema: z.string().array().default([])
1652
+ }
1653
+ },
1654
+ inputs: {
1655
+ mongodb: mongodbEntity,
1656
+ ...sharedInputs
1657
+ },
1658
+ outputs: {
1659
+ mongodb: mongodbEntity
1660
+ },
1661
+ source: {
1662
+ package: "@highstate/common",
1663
+ path: "units/databases/mongodb-patch"
1664
+ },
1665
+ meta: {
1666
+ description: `Patches some properties of the MongoDB database and outputs the updated database.`,
1667
+ title: "MongoDB Patch",
1668
+ icon: "simple-icons:mongodb",
1669
+ secondaryIcon: "fluent:patch-20-filled",
1670
+ category: "Databases"
1671
+ }
1672
+ });
1276
1673
  var postgresqlEntity = defineEntity({
1277
1674
  type: "databases.postgresql.v1",
1675
+ includes: {
1676
+ endpoints: {
1677
+ entity: l4EndpointEntity,
1678
+ multiple: true
1679
+ }
1680
+ },
1278
1681
  schema: sharedSchema,
1279
1682
  meta: {
1280
1683
  description: `Represents the PostgreSQL database or virtual database behind it.`,
@@ -1301,13 +1704,53 @@ var existingPostgresql = defineUnit({
1301
1704
  category: "Databases"
1302
1705
  }
1303
1706
  });
1707
+ var postgresqlPatch = defineUnit({
1708
+ type: "databases.postgresql-patch.v1",
1709
+ args: {
1710
+ ...toPatchArgs(optionalSharedArgs),
1711
+ /**
1712
+ * The endpoints to connect to the database in form of `host:port`.
1713
+ *
1714
+ * If at least one endpoint is provided (either via args or inputs), the existing endpoints
1715
+ * will be replaced completely.
1716
+ */
1717
+ endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints to connect to the database in form of \`host:port\`.
1718
+
1719
+ If at least one endpoint is provided (either via args or inputs), the existing endpoints
1720
+ will be replaced completely.`)
1721
+ },
1722
+ inputs: {
1723
+ postgresql: postgresqlEntity,
1724
+ ...sharedInputs
1725
+ },
1726
+ outputs: {
1727
+ postgresql: postgresqlEntity
1728
+ },
1729
+ source: {
1730
+ package: "@highstate/common",
1731
+ path: "units/databases/postgresql-patch"
1732
+ },
1733
+ meta: {
1734
+ description: `Patches some properties of the PostgreSQL database and outputs the updated database.`,
1735
+ title: "PostgreSQL Patch",
1736
+ icon: "simple-icons:postgresql",
1737
+ secondaryIcon: "fluent:patch-20-filled",
1738
+ category: "Databases"
1739
+ }
1740
+ });
1304
1741
  var redisEntity = defineEntity({
1305
1742
  type: "databases.redis.v1",
1306
- schema: sharedSchema.pick({ endpoints: true }).extend({
1743
+ includes: {
1744
+ endpoints: {
1745
+ entity: l4EndpointEntity,
1746
+ multiple: true
1747
+ }
1748
+ },
1749
+ schema: z.object({
1307
1750
  /**
1308
1751
  * The number of the database to use.
1309
1752
  */
1310
- database: z.number().default(0)
1753
+ database: z.number().default(0).meta({ title: camelCaseToHumanReadable("database"), description: `The number of the database to use.` })
1311
1754
  }),
1312
1755
  meta: {
1313
1756
  description: `Represents the Redis database or virtual database behind it.`,
@@ -1333,6 +1776,34 @@ var existingRedis = defineUnit({
1333
1776
  category: "Databases"
1334
1777
  }
1335
1778
  });
1779
+ var redisPatch = defineUnit({
1780
+ type: "databases.redis-patch.v1",
1781
+ args: {
1782
+ ...toPatchArgs(optionalSharedArgs),
1783
+ endpoints: {
1784
+ ...sharedArgs.endpoints,
1785
+ schema: z.string().array().default([])
1786
+ }
1787
+ },
1788
+ inputs: {
1789
+ redis: redisEntity,
1790
+ ...sharedInputs
1791
+ },
1792
+ outputs: {
1793
+ redis: redisEntity
1794
+ },
1795
+ source: {
1796
+ package: "@highstate/common",
1797
+ path: "units/databases/redis-patch"
1798
+ },
1799
+ meta: {
1800
+ description: `Patches some properties of the Redis database and outputs the updated database.`,
1801
+ title: "Redis Patch",
1802
+ icon: "simple-icons:redis",
1803
+ secondaryIcon: "fluent:patch-20-filled",
1804
+ category: "Databases"
1805
+ }
1806
+ });
1336
1807
  var s3BucketPolicySchema = z.enum(["none", "download", "upload", "public"]);
1337
1808
  var s3BucketSchema = z.object({
1338
1809
  /**
@@ -1362,6 +1833,10 @@ var s3Args = $args({
1362
1833
  */
1363
1834
  buckets: $addArgumentDescription(s3BucketSchema.array().default([]), `The buckets that must exist on the instance.`)
1364
1835
  });
1836
+ var optionalS3Args = mapValues(s3Args, (arg) => ({
1837
+ ...arg,
1838
+ schema: arg.schema.optional()
1839
+ }));
1365
1840
  var s3Secrets = $secrets({
1366
1841
  /**
1367
1842
  * The secret key used to authenticate against the S3-compatible API.
@@ -1380,11 +1855,13 @@ var s3Inputs = $inputs({
1380
1855
  });
1381
1856
  var s3Entity = defineEntity({
1382
1857
  type: "databases.s3.v1",
1858
+ includes: {
1859
+ endpoints: {
1860
+ entity: l4EndpointEntity,
1861
+ multiple: true
1862
+ }
1863
+ },
1383
1864
  schema: z.object({
1384
- /**
1385
- * The endpoints that expose the S3-compatible API.
1386
- */
1387
- endpoints: l4EndpointEntity.schema.array().meta({ title: camelCaseToHumanReadable("endpoints"), description: `The endpoints that expose the S3-compatible API.` }),
1388
1865
  /**
1389
1866
  * The region associated with the object storage instance.
1390
1867
  */
@@ -1427,6 +1904,34 @@ var existingS3 = defineUnit({
1427
1904
  category: "Databases"
1428
1905
  }
1429
1906
  });
1907
+ var s3Patch = defineUnit({
1908
+ type: "databases.s3-patch.v1",
1909
+ args: {
1910
+ ...toPatchArgs(optionalS3Args),
1911
+ endpoints: {
1912
+ ...s3Args.endpoints,
1913
+ schema: z.string().array().default([])
1914
+ }
1915
+ },
1916
+ inputs: {
1917
+ s3: s3Entity,
1918
+ ...s3Inputs
1919
+ },
1920
+ outputs: {
1921
+ s3: s3Entity
1922
+ },
1923
+ source: {
1924
+ package: "@highstate/common",
1925
+ path: "units/databases/s3-patch"
1926
+ },
1927
+ meta: {
1928
+ description: `Patches some properties of the S3-compatible object storage and outputs the updated storage.`,
1929
+ title: "S3 Patch",
1930
+ icon: "simple-icons:amazons3",
1931
+ secondaryIcon: "fluent:patch-20-filled",
1932
+ category: "Databases"
1933
+ }
1934
+ });
1430
1935
 
1431
1936
  // src/distributions/index.ts
1432
1937
  var distributions_exports = {};
@@ -1528,32 +2033,55 @@ __export(k3s_exports, {
1528
2033
  internalComponents: () => internalComponents,
1529
2034
  packagedComponents: () => packagedComponents
1530
2035
  });
1531
- var metadataSchema = z.object({
2036
+ var metadataSchema2 = z.object({
1532
2037
  name: z.string(),
1533
2038
  labels: z.record(z.string(), z.string()).optional(),
1534
2039
  annotations: z.record(z.string(), z.string()).optional(),
1535
- uid: z.string()
2040
+ uid: z.string(),
2041
+ namespace: z.string().optional()
1536
2042
  });
1537
- var scopedMetadataSchema = z.object({
1538
- ...metadataSchema.shape,
2043
+ var namespacedMetadataSchema = z.object({
2044
+ ...metadataSchema2.shape,
1539
2045
  namespace: z.string()
1540
2046
  });
1541
- var resourceSchema = z.object({
1542
- clusterId: z.string(),
1543
- clusterName: z.string(),
1544
- type: z.string(),
1545
- metadata: metadataSchema
2047
+ var resourceEntity = defineEntity({
2048
+ type: "k8s.resource.v1",
2049
+ schema: z.intersection(
2050
+ z.object({
2051
+ clusterId: z.string(),
2052
+ clusterName: z.string(),
2053
+ apiVersion: z.string(),
2054
+ kind: z.string()
2055
+ }),
2056
+ z.union([
2057
+ z.object({
2058
+ isNamespaced: z.literal(false),
2059
+ metadata: metadataSchema2
2060
+ }),
2061
+ z.object({
2062
+ isNamespaced: z.literal(true),
2063
+ metadata: namespacedMetadataSchema
2064
+ })
2065
+ ])
2066
+ ),
2067
+ meta: {
2068
+ description: `The entity which represents a Kubernetes resource.`
2069
+ }
1546
2070
  });
1547
- var scopedResourceSchema = z.object({
1548
- ...resourceSchema.shape,
1549
- metadata: scopedMetadataSchema
2071
+ var namespacedResourceEntity = defineEntity({
2072
+ type: "k8s.namespaced-resource.v1",
2073
+ extends: { resourceEntity },
2074
+ schema: z.object({
2075
+ isNamespaced: z.literal(true)
2076
+ }),
2077
+ meta: {
2078
+ description: `The entity which represents a Kubernetes resource scoped to a namespace.`
2079
+ }
1550
2080
  });
1551
2081
  var namespaceEntity = defineEntity({
1552
2082
  type: "k8s.namespace.v1",
1553
- schema: z.object({
1554
- ...resourceSchema.shape,
1555
- type: z.literal("namespace")
1556
- }),
2083
+ extends: { resourceEntity },
2084
+ schema: z.unknown(),
1557
2085
  meta: {
1558
2086
  description: `The entity which represents a Kubernetes namespace managed by Highstate.`,
1559
2087
  color: "#9E9E9E"
@@ -1561,10 +2089,8 @@ var namespaceEntity = defineEntity({
1561
2089
  });
1562
2090
  var persistentVolumeClaimEntity = defineEntity({
1563
2091
  type: "k8s.persistent-volume-claim.v1",
1564
- schema: z.object({
1565
- ...scopedResourceSchema.shape,
1566
- type: z.literal("persistent-volume-claim")
1567
- }),
2092
+ extends: { namespacedResourceEntity },
2093
+ schema: z.unknown(),
1568
2094
  meta: {
1569
2095
  description: `The entity which represents a Kubernetes persistent volume claim managed by Highstate.`,
1570
2096
  color: "#FFC107"
@@ -1572,10 +2098,8 @@ var persistentVolumeClaimEntity = defineEntity({
1572
2098
  });
1573
2099
  var gatewayEntity2 = defineEntity({
1574
2100
  type: "k8s.gateway.v1",
1575
- schema: z.object({
1576
- ...scopedResourceSchema.shape,
1577
- type: z.literal("gateway")
1578
- }),
2101
+ extends: { namespacedResourceEntity },
2102
+ schema: z.unknown(),
1579
2103
  meta: {
1580
2104
  description: `The entity which represents a Gateway resource from the Gateway API.`,
1581
2105
  color: "#4CAF50"
@@ -1583,10 +2107,27 @@ var gatewayEntity2 = defineEntity({
1583
2107
  });
1584
2108
  var certificateEntity = defineEntity({
1585
2109
  type: "k8s.certificate.v1",
1586
- schema: z.object({
1587
- ...scopedResourceSchema.shape,
1588
- type: z.literal("certificate")
1589
- })
2110
+ extends: { namespacedResourceEntity },
2111
+ schema: z.unknown(),
2112
+ meta: {
2113
+ color: "#3F51B5"
2114
+ }
2115
+ });
2116
+ var configMapEntity = defineEntity({
2117
+ type: "k8s.config-map.v1",
2118
+ extends: { namespacedResourceEntity },
2119
+ schema: z.unknown(),
2120
+ meta: {
2121
+ color: "#FF9800"
2122
+ }
2123
+ });
2124
+ var secretEntity = defineEntity({
2125
+ type: "k8s.secret.v1",
2126
+ extends: { namespacedResourceEntity },
2127
+ schema: z.unknown(),
2128
+ meta: {
2129
+ color: "#9C27B0"
2130
+ }
1590
2131
  });
1591
2132
 
1592
2133
  // src/k8s/shared.ts
@@ -1594,7 +2135,7 @@ var fallbackKubeApiAccessSchema = z.object({
1594
2135
  serverIp: z.string(),
1595
2136
  serverPort: z.number()
1596
2137
  });
1597
- var tunDevicePolicySchema = z.union([
2138
+ var tunDevicePolicySchema = z.discriminatedUnion("type", [
1598
2139
  z.object({
1599
2140
  type: z.literal("host")
1600
2141
  }),
@@ -1622,7 +2163,7 @@ var clusterQuirksSchema = z.object({
1622
2163
  *
1623
2164
  * For some runtimes, like Talos's one, the /dev/net/tun device is not available in the host, so the plugin policy should be used.
1624
2165
  */
1625
- tunDevicePolicy: tunDevicePolicySchema.optional().meta({ title: camelCaseToHumanReadable("tunDevicePolicy"), description: `Specifies the policy for using the tun device inside containers.
2166
+ tunDevicePolicy: tunDevicePolicySchema.prefault({ type: "host" }).meta({ title: camelCaseToHumanReadable("tunDevicePolicy"), description: `Specifies the policy for using the tun device inside containers.
1626
2167
 
1627
2168
  If not provided, the default policy is \`host\` which assumes just mounting /dev/net/tun from the host.
1628
2169
 
@@ -1632,7 +2173,7 @@ var clusterQuirksSchema = z.object({
1632
2173
  *
1633
2174
  * If not provided, the default service type is `NodePort` since `LoadBalancer` may not be available.
1634
2175
  */
1635
- externalServiceType: externalServiceTypeSchema.optional().meta({ title: camelCaseToHumanReadable("externalServiceType"), description: `The service type to use for external services.
2176
+ externalServiceType: externalServiceTypeSchema.default("NodePort").meta({ title: camelCaseToHumanReadable("externalServiceType"), description: `The service type to use for external services.
1636
2177
 
1637
2178
  If not provided, the default service type is \`NodePort\` since \`LoadBalancer\` may not be available.` })
1638
2179
  });
@@ -1661,14 +2202,6 @@ var clusterInfoProperties = {
1661
2202
  * If not provided, the native Kubernetes NetworkPolicy implementation will be used.
1662
2203
  */
1663
2204
  networkPolicyImplRef: implementationReferenceSchema.optional(),
1664
- /**
1665
- * The endpoints of the cluster nodes.
1666
- *
1667
- * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1668
- *
1669
- * The same node may also be represented by multiple entries (e.g. a node with private and public IP).
1670
- */
1671
- endpoints: l3EndpointEntity.schema.array(),
1672
2205
  /**
1673
2206
  * The endpoints of the API server.
1674
2207
  *
@@ -1680,7 +2213,7 @@ var clusterInfoProperties = {
1680
2213
  /**
1681
2214
  * The external IPs of the cluster nodes allowed to be used for external access.
1682
2215
  */
1683
- externalIps: z.string().array(),
2216
+ externalIps: addressEntity.schema.array(),
1684
2217
  /**
1685
2218
  * The extra quirks of the cluster to improve compatibility.
1686
2219
  */
@@ -1688,10 +2221,23 @@ var clusterInfoProperties = {
1688
2221
  /**
1689
2222
  * The extra metadata to attach to the cluster.
1690
2223
  */
1691
- metadata: z.record(z.string(), z.unknown()).optional()
2224
+ metadata: metadataSchema.optional()
1692
2225
  };
1693
2226
  var clusterEntity = defineEntity({
1694
2227
  type: "k8s.cluster.v1",
2228
+ includes: {
2229
+ /**
2230
+ * The endpoints of the cluster nodes.
2231
+ *
2232
+ * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
2233
+ *
2234
+ * The same node may also be represented by multiple entries (e.g. a node with private and public IP).
2235
+ */
2236
+ endpoints: {
2237
+ entity: l3EndpointEntity,
2238
+ multiple: true
2239
+ }
2240
+ },
1695
2241
  schema: z.object({
1696
2242
  ...clusterInfoProperties,
1697
2243
  kubeconfig: z.string()
@@ -1727,43 +2273,63 @@ var clusterInputs = {
1727
2273
  }
1728
2274
  };
1729
2275
  var clusterOutputs = {
1730
- k8sCluster: clusterEntity,
1731
- apiEndpoints: {
1732
- entity: l4EndpointEntity,
1733
- multiple: true
1734
- },
1735
- endpoints: {
1736
- entity: l3EndpointEntity,
1737
- multiple: true
1738
- }
2276
+ k8sCluster: clusterEntity
1739
2277
  };
1740
2278
  var existingCluster = defineUnit({
1741
2279
  type: "k8s.existing-cluster.v1",
1742
2280
  args: {
1743
2281
  /**
1744
- * The list of external IPs of the cluster nodes allowed to be used for external access.
1745
- *
1746
- * If not provided, will be automatically detected by querying the cluster nodes.
2282
+ * Whether to auto-detect external IPs of the cluster nodes and merge them with the provided external IPs.
1747
2283
  */
1748
- externalIps: $addArgumentDescription(z.string().array().optional(), `The list of external IPs of the cluster nodes allowed to be used for external access.
1749
-
1750
- If not provided, will be automatically detected by querying the cluster nodes.`),
2284
+ autoDetectExternalIps: $addArgumentDescription(z.boolean().default(true), `Whether to auto-detect external IPs of the cluster nodes and merge them with the provided external IPs.`),
1751
2285
  /**
1752
2286
  * The policy for using internal IPs of the nodes as external IPs.
1753
2287
  *
1754
2288
  * - `always`: always use internal IPs as external IPs;
1755
2289
  * - `public`: use internal IPs as external IPs only if they are (theoretically) routable from the public internet **(default)**;
1756
2290
  * - `never`: never use internal IPs as external IPs.
2291
+ *
2292
+ * Have no effect if `autoDetectExternalIps` is `false`.
1757
2293
  */
1758
2294
  internalIpsPolicy: $addArgumentDescription(internalIpsPolicySchema.default("public"), `The policy for using internal IPs of the nodes as external IPs.
1759
2295
 
1760
2296
  - \`always\`: always use internal IPs as external IPs;
1761
2297
  - \`public\`: use internal IPs as external IPs only if they are (theoretically) routable from the public internet **(default)**;
1762
- - \`never\`: never use internal IPs as external IPs.`),
2298
+ - \`never\`: never use internal IPs as external IPs.
2299
+
2300
+ Have no effect if \`autoDetectExternalIps\` is \`false\`.`),
2301
+ /**
2302
+ * The list of external IPs of the cluster nodes allowed to be used for external access.
2303
+ */
2304
+ externalIps: $addArgumentDescription(z.string().array().default([]), `The list of external IPs of the cluster nodes allowed to be used for external access.`),
2305
+ /**
2306
+ * Whether to use all external IPs (auto-detected and provided) as endpoints of the cluster.
2307
+ *
2308
+ * Set to `false` if you want to manage endpoints manually.
2309
+ */
2310
+ useExternalIpsAsEndpoints: $addArgumentDescription(z.boolean().default(true), `Whether to use all external IPs (auto-detected and provided) as endpoints of the cluster.
2311
+
2312
+ Set to \`false\` if you want to manage endpoints manually.`),
2313
+ /**
2314
+ * The list of endpoints of the cluster nodes.
2315
+ */
2316
+ endpoints: $addArgumentDescription(z.string().array().default([]), `The list of endpoints of the cluster nodes.`),
2317
+ /**
2318
+ * Whether to add endpoints from `kubeconfig` to the list of API endpoints.
2319
+ *
2320
+ * Set to `false` if you want to manage API endpoints manually.
2321
+ */
2322
+ useKubeconfigApiEndpoint: $addArgumentDescription(z.boolean().default(true), `Whether to add endpoints from \`kubeconfig\` to the list of API endpoints.
2323
+
2324
+ Set to \`false\` if you want to manage API endpoints manually.`),
2325
+ /**
2326
+ * The list of endpoints of the API server.
2327
+ */
2328
+ apiEndpoints: $addArgumentDescription(z.string().array().default([]), `The list of endpoints of the API server.`),
1763
2329
  /**
1764
2330
  * The extra quirks of the cluster to improve compatibility.
1765
2331
  */
1766
- quirks: $addArgumentDescription(clusterQuirksSchema.optional(), `The extra quirks of the cluster to improve compatibility.`)
2332
+ quirks: $addArgumentDescription(clusterQuirksSchema.optional().meta({ complex: true }), `The extra quirks of the cluster to improve compatibility.`)
1767
2333
  },
1768
2334
  secrets: {
1769
2335
  /**
@@ -1791,49 +2357,13 @@ var clusterPatch = defineUnit({
1791
2357
  type: "k8s.cluster-patch.v1",
1792
2358
  args: {
1793
2359
  /**
1794
- * The endpoints of the API server.
1795
- *
1796
- * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1797
- *
1798
- * The same node may also be represented by multiple entries (e.g. a node with private and public IP).
1799
- */
1800
- apiEndpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the API server.
1801
-
1802
- The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1803
-
1804
- The same node may also be represented by multiple entries (e.g. a node with private and public IP).`),
1805
- /**
1806
- * The mode to use for patching the API endpoints.
1807
- *
1808
- * - `prepend`: prepend the new endpoints to the existing ones (default);
1809
- * - `replace`: replace the existing endpoints with the new ones.
1810
- */
1811
- apiEndpointsPatchMode: $addArgumentDescription(arrayPatchModeSchema.default("prepend"), `The mode to use for patching the API endpoints.
1812
-
1813
- - \`prepend\`: prepend the new endpoints to the existing ones (default);
1814
- - \`replace\`: replace the existing endpoints with the new ones.`),
1815
- /**
1816
- * The endpoints of the cluster nodes.
1817
- *
1818
- * The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1819
- *
1820
- * The same node may also be represented by multiple entries (e.g. a node with private and public IP).
2360
+ * The endpoints to set on the cluster.
1821
2361
  */
1822
- endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the cluster nodes.
1823
-
1824
- The entry may represent real node endpoint or virtual endpoint (like a load balancer).
1825
-
1826
- The same node may also be represented by multiple entries (e.g. a node with private and public IP).`),
2362
+ endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints to set on the cluster.`),
1827
2363
  /**
1828
- * The mode to use for patching the endpoints.
1829
- *
1830
- * - `prepend`: prepend the new endpoints to the existing ones (default);
1831
- * - `replace`: replace the existing endpoints with the new ones.
2364
+ * The API endpoints to set on the cluster.
1832
2365
  */
1833
- endpointsPatchMode: $addArgumentDescription(arrayPatchModeSchema.default("prepend"), `The mode to use for patching the endpoints.
1834
-
1835
- - \`prepend\`: prepend the new endpoints to the existing ones (default);
1836
- - \`replace\`: replace the existing endpoints with the new ones.`)
2366
+ apiEndpoints: $addArgumentDescription(z.string().array().default([]), `The API endpoints to set on the cluster.`)
1837
2367
  },
1838
2368
  inputs: {
1839
2369
  k8sCluster: clusterEntity,
@@ -1861,29 +2391,6 @@ var clusterPatch = defineUnit({
1861
2391
  path: "units/cluster-patch"
1862
2392
  }
1863
2393
  });
1864
- var clusterDns = defineUnit({
1865
- type: "k8s.cluster-dns.v1",
1866
- args: {
1867
- ...createArgs(),
1868
- ...createArgs("api")
1869
- },
1870
- inputs: {
1871
- k8sCluster: clusterEntity,
1872
- ...inputs
1873
- },
1874
- outputs: clusterOutputs,
1875
- meta: {
1876
- description: `Creates a set of DNS records for the cluster and updates the endpoints.`,
1877
- title: "Cluster DNS",
1878
- icon: "devicon:kubernetes",
1879
- secondaryIcon: "mdi:dns",
1880
- category: "Kubernetes"
1881
- },
1882
- source: {
1883
- package: "@highstate/k8s",
1884
- path: "units/cluster-dns"
1885
- }
1886
- });
1887
2394
  var monitorWorkerResourceGroupSchema = z.object({
1888
2395
  type: z.enum(["deployment", "statefulset", "pod", "service"]),
1889
2396
  namespace: z.string(),
@@ -1897,7 +2404,7 @@ var monitorWorkerParamsSchema = z.object({
1897
2404
  /**
1898
2405
  * The resources to monitor in the cluster.
1899
2406
  */
1900
- resources: scopedResourceSchema.array().meta({ title: camelCaseToHumanReadable("resources"), description: `The resources to monitor in the cluster.` })
2407
+ resources: namespacedResourceEntity.schema.array().meta({ title: camelCaseToHumanReadable("resources"), description: `The resources to monitor in the cluster.` })
1901
2408
  });
1902
2409
 
1903
2410
  // src/k3s.ts
@@ -1986,21 +2493,23 @@ var cluster = defineUnit({
1986
2493
  // src/k8s/index.ts
1987
2494
  var k8s_exports = {};
1988
2495
  __export(k8s_exports, {
2496
+ accessVerbSchema: () => accessVerbSchema,
2497
+ acessRuleSchema: () => acessRuleSchema,
1989
2498
  apps: () => apps_exports,
1990
2499
  certManager: () => certManager,
1991
2500
  certificateEntity: () => certificateEntity,
1992
2501
  cilium: () => cilium,
1993
2502
  ciliumClusterMetadata: () => ciliumClusterMetadata,
1994
- clusterDns: () => clusterDns,
1995
2503
  clusterEntity: () => clusterEntity,
1996
2504
  clusterInfoProperties: () => clusterInfoProperties,
1997
2505
  clusterInputs: () => clusterInputs,
1998
2506
  clusterOutputs: () => clusterOutputs,
1999
2507
  clusterPatch: () => clusterPatch,
2000
2508
  clusterQuirksSchema: () => clusterQuirksSchema,
2509
+ configMapEntity: () => configMapEntity,
2510
+ cronJobEntity: () => cronJobEntity,
2001
2511
  deploymentEntity: () => deploymentEntity,
2002
2512
  dns01TlsIssuer: () => dns01TlsIssuer,
2003
- endpointServiceMetadataSchema: () => endpointServiceMetadataSchema,
2004
2513
  existingCluster: () => existingCluster,
2005
2514
  exposableWorkloadEntity: () => exposableWorkloadEntity,
2006
2515
  externalServiceTypeSchema: () => externalServiceTypeSchema,
@@ -2011,25 +2520,29 @@ __export(k8s_exports, {
2011
2520
  gatewayEntity: () => gatewayEntity2,
2012
2521
  gatewayImplRefSchema: () => gatewayImplRefSchema,
2013
2522
  internalIpsPolicySchema: () => internalIpsPolicySchema,
2014
- metadataSchema: () => metadataSchema,
2523
+ jobEntity: () => jobEntity,
2524
+ metadataSchema: () => metadataSchema2,
2015
2525
  monitorWorkerParamsSchema: () => monitorWorkerParamsSchema,
2016
2526
  monitorWorkerResourceGroupSchema: () => monitorWorkerResourceGroupSchema,
2017
2527
  namespaceEntity: () => namespaceEntity,
2528
+ namespacedMetadataSchema: () => namespacedMetadataSchema,
2529
+ namespacedResourceEntity: () => namespacedResourceEntity,
2018
2530
  networkInterfaceEntity: () => networkInterfaceEntity,
2019
2531
  obfuscators: () => obfuscators_exports,
2020
2532
  persistentVolumeClaimEntity: () => persistentVolumeClaimEntity,
2021
2533
  reducedAccessCluster: () => reducedAccessCluster,
2022
- resourceSchema: () => resourceSchema,
2534
+ resourceEntity: () => resourceEntity,
2023
2535
  scheduleOnMastersPolicyArgs: () => scheduleOnMastersPolicyArgs,
2024
2536
  scheduleOnMastersPolicySchema: () => scheduleOnMastersPolicySchema,
2025
- scopedMetadataSchema: () => scopedMetadataSchema,
2026
- scopedResourceSchema: () => scopedResourceSchema,
2537
+ secretEntity: () => secretEntity,
2538
+ serviceEndpointMetadataSchema: () => serviceEndpointMetadataSchema,
2027
2539
  serviceEndpointSchema: () => serviceEndpointSchema,
2028
2540
  serviceEntity: () => serviceEntity,
2029
2541
  serviceTypeSchema: () => serviceTypeSchema,
2030
2542
  statefulSetEntity: () => statefulSetEntity,
2031
2543
  tlsIssuerDataSchema: () => tlsIssuerDataSchema,
2032
- tunDevicePolicySchema: () => tunDevicePolicySchema
2544
+ tunDevicePolicySchema: () => tunDevicePolicySchema,
2545
+ workloadEntity: () => workloadEntity
2033
2546
  });
2034
2547
 
2035
2548
  // src/k8s/apps/index.ts
@@ -2040,6 +2553,7 @@ __export(apps_exports, {
2040
2553
  codeServer: () => codeServer,
2041
2554
  databaseConfigKeySchema: () => databaseConfigKeySchema,
2042
2555
  environmentVariableSchema: () => environmentVariableSchema,
2556
+ etcd: () => etcd,
2043
2557
  grocy: () => grocy,
2044
2558
  hubble: () => hubble,
2045
2559
  kubernetesDashboard: () => kubernetesDashboard,
@@ -2050,7 +2564,7 @@ __export(apps_exports, {
2050
2564
  mongodb: () => mongodb,
2051
2565
  mongodbDatabase: () => mongodbDatabase,
2052
2566
  node: () => node,
2053
- optionalSharedArgs: () => optionalSharedArgs,
2567
+ optionalSharedArgs: () => optionalSharedArgs2,
2054
2568
  optionalSharedInputs: () => optionalSharedInputs,
2055
2569
  postgresql: () => postgresql,
2056
2570
  postgresqlDatabase: () => postgresqlDatabase,
@@ -2063,9 +2577,10 @@ __export(apps_exports, {
2063
2577
  traefik: () => traefik,
2064
2578
  valkey: () => valkey,
2065
2579
  vaultwarden: () => vaultwarden,
2580
+ wgFeedServer: () => wgFeedServer,
2066
2581
  workload: () => workload
2067
2582
  });
2068
- var endpointServiceMetadataSchema = z.object({
2583
+ var serviceEndpointMetadataSchema = z.object({
2069
2584
  "k8s.service": z.object({
2070
2585
  /**
2071
2586
  * The ID of the cluster where the service is located.
@@ -2083,6 +2598,10 @@ var endpointServiceMetadataSchema = z.object({
2083
2598
  * The namespace of the service.
2084
2599
  */
2085
2600
  namespace: z.string().meta({ title: camelCaseToHumanReadable("namespace"), description: `The namespace of the service.` }),
2601
+ /**
2602
+ * Whether this endpoint is only accessible within the cluster.
2603
+ */
2604
+ isInternal: z.boolean().meta({ title: camelCaseToHumanReadable("isInternal"), description: `Whether this endpoint is only accessible within the cluster.` }),
2086
2605
  /**
2087
2606
  * The selector of the service.
2088
2607
  */
@@ -2096,16 +2615,19 @@ var endpointServiceMetadataSchema = z.object({
2096
2615
  var serviceEndpointSchema = z.intersection(
2097
2616
  l4EndpointEntity.schema,
2098
2617
  z.object({
2099
- metadata: endpointServiceMetadataSchema
2618
+ metadata: serviceEndpointMetadataSchema
2100
2619
  })
2101
2620
  );
2102
2621
  var serviceEntity = defineEntity({
2103
2622
  type: "k8s.service.v1",
2104
- schema: z.object({
2105
- ...scopedResourceSchema.shape,
2106
- type: z.literal("service"),
2107
- endpoints: serviceEndpointSchema.array()
2108
- }),
2623
+ extends: { namespacedResourceEntity },
2624
+ includes: {
2625
+ endpoints: {
2626
+ entity: l4EndpointEntity,
2627
+ multiple: true
2628
+ }
2629
+ },
2630
+ schema: z.unknown(),
2109
2631
  meta: {
2110
2632
  color: "#2196F3"
2111
2633
  }
@@ -2113,13 +2635,58 @@ var serviceEntity = defineEntity({
2113
2635
  var serviceTypeSchema = z.enum(["NodePort", "LoadBalancer", "ClusterIP"]);
2114
2636
 
2115
2637
  // src/k8s/workload.ts
2638
+ var workloadEntity = defineEntity({
2639
+ type: "k8s.workload.v1",
2640
+ extends: { namespacedResourceEntity },
2641
+ schema: z.unknown(),
2642
+ meta: {
2643
+ description: `The entity which represents a Kubernetes workload.`,
2644
+ color: "#9C27B0"
2645
+ }
2646
+ });
2647
+ var jobEntity = defineEntity({
2648
+ type: "k8s.job.v1",
2649
+ extends: { workloadEntity },
2650
+ schema: z.unknown(),
2651
+ meta: {
2652
+ description: `The entity which represents a Kubernetes job managed by Highstate.`,
2653
+ color: "#FF5722"
2654
+ }
2655
+ });
2656
+ var cronJobEntity = defineEntity({
2657
+ type: "k8s.cron-job.v1",
2658
+ extends: { workloadEntity },
2659
+ schema: z.unknown(),
2660
+ meta: {
2661
+ description: `The entity which represents a Kubernetes cron job managed by Highstate.`,
2662
+ color: "#FF9800"
2663
+ }
2664
+ });
2665
+ var exposableWorkloadEntity = defineEntity({
2666
+ type: "k8s.exposable-workload.v1",
2667
+ extends: { workloadEntity },
2668
+ includes: {
2669
+ service: {
2670
+ entity: serviceEntity,
2671
+ required: false
2672
+ },
2673
+ endpoints: {
2674
+ entity: l4EndpointEntity,
2675
+ multiple: true
2676
+ }
2677
+ },
2678
+ schema: z.unknown(),
2679
+ meta: {
2680
+ description: `The entity which represents a Kubernetes workload (optionally) exposed via a service.
2681
+
2682
+ Includes both the workload and its associated service.`,
2683
+ color: "#4CAF50"
2684
+ }
2685
+ });
2116
2686
  var deploymentEntity = defineEntity({
2117
2687
  type: "k8s.deployment.v1",
2118
- schema: z.object({
2119
- ...scopedResourceSchema.shape,
2120
- type: z.literal("deployment"),
2121
- service: serviceEntity.schema.optional()
2122
- }),
2688
+ extends: { exposableWorkloadEntity },
2689
+ schema: z.unknown(),
2123
2690
  meta: {
2124
2691
  description: `The entity which represents a Kubernetes deployment managed by Highstate.
2125
2692
 
@@ -2129,11 +2696,11 @@ var deploymentEntity = defineEntity({
2129
2696
  });
2130
2697
  var statefulSetEntity = defineEntity({
2131
2698
  type: "k8s.stateful-set.v1",
2132
- schema: z.object({
2133
- ...scopedResourceSchema.shape,
2134
- type: z.literal("stateful-set"),
2135
- service: serviceEntity.schema
2136
- }),
2699
+ extends: { exposableWorkloadEntity },
2700
+ includes: {
2701
+ service: serviceEntity
2702
+ },
2703
+ schema: z.unknown(),
2137
2704
  meta: {
2138
2705
  description: `The entity which represents a Kubernetes stateful set managed by Highstate.
2139
2706
 
@@ -2141,21 +2708,11 @@ var statefulSetEntity = defineEntity({
2141
2708
  color: "#FFC107"
2142
2709
  }
2143
2710
  });
2144
- var exposableWorkloadEntity = defineEntity({
2145
- type: "k8s.exposable-workload.v1",
2146
- schema: z.union([deploymentEntity.schema, statefulSetEntity.schema]),
2147
- meta: {
2148
- description: `The entity which represents a Kubernetes workload exposed via a service.
2149
-
2150
- It can be either a deployment or a stateful set.`,
2151
- color: "#4CAF50"
2152
- }
2153
- });
2154
2711
  var networkInterfaceEntity = defineEntity({
2155
2712
  type: "k8s.network-interface.v1",
2156
2713
  schema: z.object({
2157
2714
  name: z.string(),
2158
- workload: exposableWorkloadEntity.schema
2715
+ workload: workloadEntity.schema
2159
2716
  }),
2160
2717
  meta: {
2161
2718
  description: `The network interface in a network namespace of the pod which can accept and transmit network traffic.`,
@@ -2272,7 +2829,7 @@ var sharedArgs2 = $args({
2272
2829
  */
2273
2830
  replicas: $addArgumentDescription(z.number().default(1), `The number of replicas for the application.`)
2274
2831
  });
2275
- var optionalSharedArgs = mapValues(sharedArgs2, (arg) => ({
2832
+ var optionalSharedArgs2 = mapValues(sharedArgs2, (arg) => ({
2276
2833
  ...arg,
2277
2834
  schema: arg.schema.optional()
2278
2835
  }));
@@ -2360,6 +2917,9 @@ var sharedInputs2 = $inputs({
2360
2917
  },
2361
2918
  redis: {
2362
2919
  entity: redisEntity
2920
+ },
2921
+ etcd: {
2922
+ entity: etcdEntity
2363
2923
  }
2364
2924
  });
2365
2925
  var optionalSharedInputs = mapValues(sharedInputs2, (input) => ({
@@ -2401,6 +2961,32 @@ var codeServer = defineUnit({
2401
2961
  },
2402
2962
  source: source("code-server")
2403
2963
  });
2964
+ var etcd = defineUnit({
2965
+ type: "k8s.apps.etcd.v1",
2966
+ args: {
2967
+ ...appName("etcd"),
2968
+ ...pick(sharedArgs2, ["external"])
2969
+ },
2970
+ secrets: {
2971
+ ...pick(sharedSecrets2, ["backupKey"])
2972
+ },
2973
+ inputs: {
2974
+ ...pick(sharedInputs2, ["k8sCluster"]),
2975
+ ...pick(optionalSharedInputs, ["resticRepo"])
2976
+ },
2977
+ outputs: {
2978
+ etcd: etcdEntity
2979
+ },
2980
+ meta: {
2981
+ description: `The etcd instance deployed on Kubernetes.`,
2982
+ title: "etcd",
2983
+ icon: "simple-icons:etcd",
2984
+ iconColor: "#0069ab",
2985
+ secondaryIcon: "mdi:database",
2986
+ category: "Databases"
2987
+ },
2988
+ source: source("etcd/app")
2989
+ });
2404
2990
  var grocy = defineUnit({
2405
2991
  type: "k8s.apps.grocy.v1",
2406
2992
  args: {
@@ -2477,11 +3063,7 @@ var mariadb = defineUnit({
2477
3063
  },
2478
3064
  outputs: {
2479
3065
  mariadb: mariadbEntity,
2480
- service: serviceEntity,
2481
- endpoints: {
2482
- entity: l4EndpointEntity,
2483
- multiple: true
2484
- }
3066
+ service: serviceEntity
2485
3067
  },
2486
3068
  meta: {
2487
3069
  description: `The MariaDB database deployed on Kubernetes.`,
@@ -2584,11 +3166,7 @@ var minio = defineUnit({
2584
3166
  },
2585
3167
  outputs: {
2586
3168
  s3: s3Entity,
2587
- service: serviceEntity,
2588
- endpoints: {
2589
- entity: l4EndpointEntity,
2590
- multiple: true
2591
- }
3169
+ service: serviceEntity
2592
3170
  },
2593
3171
  meta: {
2594
3172
  description: `The MinIO object storage deployed on Kubernetes.`,
@@ -2614,11 +3192,7 @@ var mongodb = defineUnit({
2614
3192
  },
2615
3193
  outputs: {
2616
3194
  mongodb: mongodbEntity,
2617
- service: serviceEntity,
2618
- endpoints: {
2619
- entity: l4EndpointEntity,
2620
- multiple: true
2621
- }
3195
+ service: serviceEntity
2622
3196
  },
2623
3197
  meta: {
2624
3198
  description: `The MongoDB instance deployed on Kubernetes.`,
@@ -2666,11 +3240,7 @@ var postgresql = defineUnit({
2666
3240
  },
2667
3241
  outputs: {
2668
3242
  postgresql: postgresqlEntity,
2669
- service: serviceEntity,
2670
- endpoints: {
2671
- entity: l4EndpointEntity,
2672
- multiple: true
2673
- }
3243
+ service: serviceEntity
2674
3244
  },
2675
3245
  meta: {
2676
3246
  description: `The PostgreSQL instance deployed on Kubernetes.`,
@@ -2812,7 +3382,7 @@ var traefik = defineUnit({
2812
3382
  type: "k8s.apps.traefik.v1",
2813
3383
  args: {
2814
3384
  ...appName("traefik"),
2815
- ...pick(sharedArgs2, ["external", "replicas", "endpoints"]),
3385
+ ...pick(sharedArgs2, ["external", "replicas"]),
2816
3386
  /**
2817
3387
  * The name of the class to configure for ingress and gateway resources.
2818
3388
  *
@@ -2820,7 +3390,19 @@ var traefik = defineUnit({
2820
3390
  */
2821
3391
  className: $addArgumentDescription(z.string().default("traefik"), `The name of the class to configure for ingress and gateway resources.
2822
3392
 
2823
- Defaults to "traefik".`)
3393
+ Defaults to "traefik".`),
3394
+ /**
3395
+ * Whether to create and enable reconciliation for Traefik CRDs.
3396
+ */
3397
+ enableTraefikCrds: $addArgumentDescription(z.boolean().default(true), `Whether to create and enable reconciliation for Traefik CRDs.`),
3398
+ /**
3399
+ * Whether to enable reconciliation for Ingress resources and create ingress class.
3400
+ */
3401
+ enableIngressApi: $addArgumentDescription(z.boolean().default(true), `Whether to enable reconciliation for Ingress resources and create ingress class.`),
3402
+ /**
3403
+ * Whether to enable reconciliation for Gateway API resources and create gateway class.
3404
+ */
3405
+ enableGatewayApi: $addArgumentDescription(z.boolean().default(false), `Whether to enable reconciliation for Gateway API resources and create gateway class.`)
2824
3406
  },
2825
3407
  inputs: {
2826
3408
  ...pick(sharedInputs2, ["k8sCluster"])
@@ -2856,11 +3438,7 @@ var valkey = defineUnit({
2856
3438
  },
2857
3439
  outputs: {
2858
3440
  redis: databases_exports.redisEntity,
2859
- service: serviceEntity,
2860
- endpoints: {
2861
- entity: l4EndpointEntity,
2862
- multiple: true
2863
- }
3441
+ service: serviceEntity
2864
3442
  },
2865
3443
  meta: {
2866
3444
  description: `The Valkey instance deployed on Kubernetes.`,
@@ -2891,6 +3469,28 @@ var vaultwarden = defineUnit({
2891
3469
  },
2892
3470
  source: source("vaultwarden")
2893
3471
  });
3472
+ var wgFeedServer = defineUnit({
3473
+ type: "k8s.apps.wg-feed-server.v1",
3474
+ args: {
3475
+ ...appName("wg-feed-server"),
3476
+ ...pick(sharedArgs2, ["fqdn"])
3477
+ },
3478
+ inputs: {
3479
+ ...pick(sharedInputs2, ["k8sCluster", "accessPoint", "etcd"])
3480
+ },
3481
+ outputs: {
3482
+ endpoint: l4EndpointEntity
3483
+ },
3484
+ meta: {
3485
+ description: `The WG Feed Server deployed on Kubernetes.`,
3486
+ title: "WG Feed Server",
3487
+ icon: "simple-icons:wireguard",
3488
+ iconColor: "#88171a",
3489
+ secondaryIcon: "mdi:broadcast",
3490
+ category: "Wireguard"
3491
+ },
3492
+ source: source("wg-feed-server")
3493
+ });
2894
3494
  var databaseConfigKeySchema = z.enum([
2895
3495
  "url",
2896
3496
  "host",
@@ -3504,7 +4104,7 @@ var obfuscator = defineUnit({
3504
4104
  path: "phantun/obfuscator"
3505
4105
  }
3506
4106
  });
3507
- var k8sVerbsSchema = z.enum([
4107
+ var accessVerbSchema = z.enum([
3508
4108
  "get",
3509
4109
  "list",
3510
4110
  "watch",
@@ -3514,80 +4114,56 @@ var k8sVerbsSchema = z.enum([
3514
4114
  "delete",
3515
4115
  "deletecollection"
3516
4116
  ]);
4117
+ var acessRuleSchema = z.object({
4118
+ apiGroups: z.string().array(),
4119
+ resources: z.string().array(),
4120
+ verbs: accessVerbSchema.array(),
4121
+ resourceNames: z.string().array().default([])
4122
+ });
3517
4123
  var reducedAccessCluster = defineUnit({
3518
- type: "k8s.reduced-access-cluster.v0",
4124
+ type: "k8s.reduced-access-cluster.v1",
3519
4125
  args: {
3520
4126
  /**
3521
- * The verbs to allow on the specified resources.
4127
+ * The name of the ServiceAccount to create.
3522
4128
  *
3523
- * Defaults to read-only access (get, list, watch).
4129
+ * If not provided, will be the same as the unit name.
3524
4130
  */
3525
- verbs: $addArgumentDescription(k8sVerbsSchema.array().default(["get", "list", "watch"]), `The verbs to allow on the specified resources.
4131
+ serviceAccountName: $addArgumentDescription(z.string().optional(), `The name of the ServiceAccount to create.
3526
4132
 
3527
- Defaults to read-only access (get, list, watch).`),
4133
+ If not provided, will be the same as the unit name.`),
3528
4134
  /**
3529
- * The name of the ServiceAccount to create.
4135
+ * The rules defining the access permissions for the ServiceAccount.
3530
4136
  *
3531
- * If not provided, will be the same as the unit name.
4137
+ * If rule's `apiGroups` and `resources` exactly match resources from the `resources` input,
4138
+ * their names will be added to the rule's `resourceNames` list.
3532
4139
  */
3533
- serviceAccountName: $addArgumentDescription(z.string().optional(), `The name of the ServiceAccount to create.
4140
+ rules: $addArgumentDescription(acessRuleSchema.array().default([]), `The rules defining the access permissions for the ServiceAccount.
3534
4141
 
3535
- If not provided, will be the same as the unit name.`)
4142
+ If rule's \`apiGroups\` and \`resources\` exactly match resources from the \`resources\` input,
4143
+ their names will be added to the rule's \`resourceNames\` list.`)
3536
4144
  },
3537
4145
  inputs: {
3538
4146
  k8sCluster: clusterEntity,
3539
4147
  /**
3540
4148
  * The namespace where the ServiceAccount will be created.
3541
4149
  */
3542
- namespace: $addInputDescription(namespaceEntity, `The namespace where the ServiceAccount will be created.`),
3543
- /**
3544
- * The deployments to grant access to.
3545
- */
3546
- deployments: $addInputDescription({
3547
- entity: deploymentEntity,
3548
- multiple: true,
3549
- required: false
3550
- }, `The deployments to grant access to.`),
3551
- /**
3552
- * The stateful sets to grant access to.
3553
- */
3554
- statefulSets: $addInputDescription({
3555
- entity: statefulSetEntity,
3556
- multiple: true,
3557
- required: false
3558
- }, `The stateful sets to grant access to.`),
3559
- /**
3560
- * The services to grant access to.
3561
- */
3562
- services: $addInputDescription({
3563
- entity: serviceEntity,
3564
- multiple: true,
3565
- required: false
3566
- }, `The services to grant access to.`),
3567
- /**
3568
- * The persistent volume claims to grant access to.
3569
- */
3570
- persistentVolumeClaims: $addInputDescription({
3571
- entity: persistentVolumeClaimEntity,
3572
- multiple: true,
3573
- required: false
3574
- }, `The persistent volume claims to grant access to.`),
4150
+ namespace: $addInputDescription(namespaceEntity, `The namespace where the ServiceAccount will be created.`),
3575
4151
  /**
3576
- * The secrets to grant access to.
4152
+ * The extra namespaces to bind to the ClusterRole and allow ServiceAccount to access them with specified rules.
3577
4153
  */
3578
- secrets: $addInputDescription({
3579
- entity: certificateEntity,
4154
+ extraNamespaces: $addInputDescription({
4155
+ entity: namespaceEntity,
3580
4156
  multiple: true,
3581
4157
  required: false
3582
- }, `The secrets to grant access to.`),
4158
+ }, `The extra namespaces to bind to the ClusterRole and allow ServiceAccount to access them with specified rules.`),
3583
4159
  /**
3584
- * The config maps to grant access to.
4160
+ * The resources to which access will be granted.
3585
4161
  */
3586
- configMaps: $addInputDescription({
3587
- entity: certificateEntity,
4162
+ resources: $addInputDescription({
4163
+ entity: resourceEntity,
3588
4164
  multiple: true,
3589
4165
  required: false
3590
- }, `The config maps to grant access to.`)
4166
+ }, `The resources to which access will be granted.`)
3591
4167
  },
3592
4168
  outputs: {
3593
4169
  k8sCluster: clusterEntity
@@ -3850,7 +4426,7 @@ var connection = defineUnit({
3850
4426
  ...secrets
3851
4427
  },
3852
4428
  inputs: {
3853
- ...inputs2
4429
+ ...inputs
3854
4430
  },
3855
4431
  outputs: {
3856
4432
  /**
@@ -4126,7 +4702,7 @@ var virtualMachine = defineUnit({
4126
4702
  }, `The cloud-init vendor data to use for the virtual machine.
4127
4703
 
4128
4704
  You can provide a cloud-config from the distribution component.`),
4129
- ...inputs2
4705
+ ...inputs
4130
4706
  },
4131
4707
  outputs: serverOutputs,
4132
4708
  meta: {
@@ -4357,6 +4933,7 @@ var connection2 = defineUnit({
4357
4933
  description: `The Cloudflare connection for a single zone.`,
4358
4934
  title: "Cloudflare Connection",
4359
4935
  icon: "simple-icons:cloudflare",
4936
+ iconColor: "#F38020",
4360
4937
  category: "Cloudflare"
4361
4938
  },
4362
4939
  source: {
@@ -4377,6 +4954,10 @@ __export(wireguard_exports, {
4377
4954
  backendSchema: () => backendSchema,
4378
4955
  config: () => config,
4379
4956
  configBundle: () => configBundle,
4957
+ configEntity: () => configEntity,
4958
+ feed: () => feed,
4959
+ feedDisplayInfoSchema: () => feedDisplayInfoSchema,
4960
+ feedMetadataSchema: () => feedMetadataSchema,
4380
4961
  identity: () => identity,
4381
4962
  identityEntity: () => identityEntity,
4382
4963
  network: () => network,
@@ -4389,23 +4970,25 @@ __export(wireguard_exports, {
4389
4970
  peerPatch: () => peerPatch
4390
4971
  });
4391
4972
  var backendSchema = z.enum(["wireguard", "amneziawg"]);
4392
- var networkArgs = {
4973
+ var networkArgs2 = {
4393
4974
  /**
4394
4975
  * The backend to use for the WireGuard network.
4395
4976
  *
4396
4977
  * Possible values are:
4397
4978
  * - `wireguard` - the default backend;
4398
- * - `amneziawg` - the censorship-resistant fork of WireGuard.
4979
+ * - `amneziawg` - the censorship-resistant fork of WireGuard (NOT SUPPORTED YET).
4399
4980
  */
4400
4981
  backend: backendSchema.default("wireguard"),
4401
4982
  /**
4402
4983
  * Whether to enable IPv4 support in the network.
4984
+ * Affects addresses inside network, not the endpoints of peers.
4403
4985
  *
4404
4986
  * By default, IPv4 support is enabled.
4405
4987
  */
4406
4988
  ipv4: z.boolean().default(true),
4407
4989
  /**
4408
4990
  * Whether to enable IPv6 support in the network.
4991
+ * Affects addresses inside network, not the endpoints of peers.
4409
4992
  *
4410
4993
  * By default, IPv6 support is disabled.
4411
4994
  */
@@ -4413,7 +4996,7 @@ var networkArgs = {
4413
4996
  };
4414
4997
  var networkEntity = defineEntity({
4415
4998
  type: "wireguard.network.v1",
4416
- schema: z.object(networkArgs),
4999
+ schema: z.object(networkArgs2),
4417
5000
  meta: {
4418
5001
  description: `The entity representing the WireGuard network configuration.
4419
5002
 
@@ -4423,14 +5006,44 @@ var networkEntity = defineEntity({
4423
5006
  var nodeExposePolicySchema = z.enum(["always", "when-has-endpoint", "never"]);
4424
5007
  var peerEntity = defineEntity({
4425
5008
  type: "wireguard.peer.v1",
5009
+ includes: {
5010
+ /**
5011
+ * The endpoints where the WireGuard peer can be reached.
5012
+ */
5013
+ endpoints: {
5014
+ entity: l4EndpointEntity,
5015
+ multiple: true
5016
+ }
5017
+ },
4426
5018
  schema: z.object({
4427
- name: z.string(),
4428
- network: networkEntity.schema.optional(),
4429
- publicKey: z.string(),
4430
- address: z.string().optional(),
4431
- allowedIps: z.string().array(),
4432
- endpoints: l4EndpointEntity.schema.array(),
4433
- allowedEndpoints: z.union([l3EndpointEntity.schema, l4EndpointEntity.schema]).array(),
5019
+ /**
5020
+ * The name of the WireGuard peer.
5021
+ */
5022
+ name: genericNameSchema.meta({ title: camelCaseToHumanReadable("name"), description: `The name of the WireGuard peer.` }),
5023
+ /**
5024
+ * The network to which the WireGuard peer belongs.
5025
+ *
5026
+ * Holds shared configuration for all identities, peers, and nodes.
5027
+ */
5028
+ network: networkEntity.schema.optional().meta({ title: camelCaseToHumanReadable("network"), description: `The network to which the WireGuard peer belongs.
5029
+
5030
+ Holds shared configuration for all identities, peers, and nodes.` }),
5031
+ /**
5032
+ * The addresses of the WireGuard interface.
5033
+ */
5034
+ addresses: addressEntity.schema.array().meta({ title: camelCaseToHumanReadable("addresses"), description: `The addresses of the WireGuard interface.` }),
5035
+ /**
5036
+ * The allowed subnets of the WireGuard peer.
5037
+ *
5038
+ * Will be used to configure the `AllowedIPs` of the peer.
5039
+ */
5040
+ allowedSubnets: subnetEntity.schema.array().meta({ title: camelCaseToHumanReadable("allowedSubnets"), description: `The allowed subnets of the WireGuard peer.
5041
+
5042
+ Will be used to configure the \`AllowedIPs\` of the peer.` }),
5043
+ /**
5044
+ * The public key of the WireGuard peer.
5045
+ */
5046
+ publicKey: z.string().meta({ title: camelCaseToHumanReadable("publicKey"), description: `The public key of the WireGuard peer.` }),
4434
5047
  /**
4435
5048
  * The pre-shared key of the WireGuard peer.
4436
5049
  *
@@ -4446,14 +5059,27 @@ var peerEntity = defineEntity({
4446
5059
  /**
4447
5060
  * The pre-shared key part of the WireGuard peer.
4448
5061
  *
4449
- * If both peers have `presharedKeyPart` set, their `presharedKey` will be calculated as XOR of the two parts.
5062
+ * If both peers have `presharedKeyPart` set, their `presharedKey` will be calculated as sha256 of the two parts.
4450
5063
  */
4451
5064
  presharedKeyPart: z.string().optional().meta({ title: camelCaseToHumanReadable("presharedKeyPart"), description: `The pre-shared key part of the WireGuard peer.
4452
5065
 
4453
- If both peers have \`presharedKeyPart\` set, their \`presharedKey\` will be calculated as XOR of the two parts.` }),
4454
- excludedIps: z.string().array(),
4455
- dns: z.string().array(),
4456
- listenPort: z.number().optional(),
5066
+ If both peers have \`presharedKeyPart\` set, their \`presharedKey\` will be calculated as sha256 of the two parts.` }),
5067
+ /**
5068
+ * The list of DNS servers to setup for the interface connected to the WireGuard peer.
5069
+ */
5070
+ dns: addressEntity.schema.array().meta({ title: camelCaseToHumanReadable("dns"), description: `The list of DNS servers to setup for the interface connected to the WireGuard peer.` }),
5071
+ /**
5072
+ * The port where the WireGuard peer is listening.
5073
+ *
5074
+ * Will be used:
5075
+ * 1. For implementations if the listen port is not set elsewhere.
5076
+ * 2. To map L3 endpoints to L4 endpoints with this port.
5077
+ */
5078
+ listenPort: z.number().default(51820).meta({ title: camelCaseToHumanReadable("listenPort"), description: `The port where the WireGuard peer is listening.
5079
+
5080
+ Will be used:
5081
+ 1. For implementations if the listen port is not set elsewhere.
5082
+ 2. To map L3 endpoints to L4 endpoints with this port.` }),
4457
5083
  /**
4458
5084
  * The keepalive interval in seconds that will be used by all nodes connecting to this peer.
4459
5085
  *
@@ -4461,7 +5087,19 @@ var peerEntity = defineEntity({
4461
5087
  */
4462
5088
  persistentKeepalive: z.number().int().nonnegative().default(0).meta({ title: camelCaseToHumanReadable("persistentKeepalive"), description: `The keepalive interval in seconds that will be used by all nodes connecting to this peer.
4463
5089
 
4464
- If set to 0, keepalive is disabled.` })
5090
+ If set to 0, keepalive is disabled.` }),
5091
+ /**
5092
+ * The peers which are relayed through this peer.
5093
+ *
5094
+ * All their allowed IPs will be added to this peer's allowed IPs
5095
+ * and will be used to setup routing for all other peers except the relayed ones.
5096
+ */
5097
+ get relayedPeers() {
5098
+ return peerEntity.schema.array().optional().meta({ title: camelCaseToHumanReadable("relayedPeers"), description: `The peers which are relayed through this peer.
5099
+
5100
+ All their allowed IPs will be added to this peer's allowed IPs
5101
+ and will be used to setup routing for all other peers except the relayed ones.` });
5102
+ }
4465
5103
  }),
4466
5104
  meta: {
4467
5105
  color: "#673AB7"
@@ -4469,17 +5107,76 @@ var peerEntity = defineEntity({
4469
5107
  });
4470
5108
  var identityEntity = defineEntity({
4471
5109
  type: "wireguard.identity.v1",
5110
+ includes: {
5111
+ /**
5112
+ * The WireGuard peer representing this identity.
5113
+ */
5114
+ peer: peerEntity
5115
+ },
4472
5116
  schema: z.object({
4473
- peer: peerEntity.schema,
4474
- privateKey: z.string()
5117
+ /**
5118
+ * The private key of the WireGuard identity.
5119
+ */
5120
+ privateKey: z.string().meta({ title: camelCaseToHumanReadable("privateKey"), description: `The private key of the WireGuard identity.` })
4475
5121
  }),
4476
5122
  meta: {
4477
5123
  color: "#F44336"
4478
5124
  }
4479
5125
  });
5126
+ var feedDisplayInfoSchema = z.object({
5127
+ /**
5128
+ * The display title of the tunnel.
5129
+ */
5130
+ title: z.string().meta({ title: camelCaseToHumanReadable("title"), description: `The display title of the tunnel.` }),
5131
+ /**
5132
+ * The display description of the tunnel.
5133
+ */
5134
+ description: z.string().optional().meta({ title: camelCaseToHumanReadable("description"), description: `The display description of the tunnel.` }),
5135
+ /**
5136
+ * The display icon URL of the tunnel.
5137
+ *
5138
+ * Must only be `data:` URL with SVG image.
5139
+ */
5140
+ iconUrl: z.url().optional().meta({ title: camelCaseToHumanReadable("iconUrl"), description: `The display icon URL of the tunnel.
5141
+
5142
+ Must only be \`data:\` URL with SVG image.` })
5143
+ });
5144
+ var feedMetadataSchema = z.object({
5145
+ /**
5146
+ * The ID of the tunnel in the feed.
5147
+ */
5148
+ id: z.string().meta({ title: camelCaseToHumanReadable("id"), description: `The ID of the tunnel in the feed.` }),
5149
+ /**
5150
+ * The suggested name of the interface for the tunnel.
5151
+ */
5152
+ name: genericNameSchema.meta({ title: camelCaseToHumanReadable("name"), description: `The suggested name of the interface for the tunnel.` }),
5153
+ /**
5154
+ * The display information of the tunnel.
5155
+ */
5156
+ displayInfo: feedDisplayInfoSchema.meta({ title: camelCaseToHumanReadable("displayInfo"), description: `The display information of the tunnel.` })
5157
+ });
5158
+ var configEntity = defineEntity({
5159
+ type: "wireguard.config.v1",
5160
+ includes: {
5161
+ /**
5162
+ * The file containing the wg-quick configuration.
5163
+ */
5164
+ file: fileEntity
5165
+ },
5166
+ schema: z.object({
5167
+ /**
5168
+ * The metadata to include in the wg-feed for this config.
5169
+ *
5170
+ * Must be provided for the configs uploaded to wg-feed.
5171
+ */
5172
+ feedMetadata: feedMetadataSchema.optional().meta({ title: camelCaseToHumanReadable("feedMetadata"), description: `The metadata to include in the wg-feed for this config.
5173
+
5174
+ Must be provided for the configs uploaded to wg-feed.` })
5175
+ })
5176
+ });
4480
5177
  var network = defineUnit({
4481
5178
  type: "wireguard.network.v1",
4482
- args: networkArgs,
5179
+ args: networkArgs2,
4483
5180
  outputs: {
4484
5181
  network: networkEntity
4485
5182
  },
@@ -4495,35 +5192,39 @@ var network = defineUnit({
4495
5192
  path: "network"
4496
5193
  }
4497
5194
  });
4498
- var sharedPeerArgs = {
5195
+ var sharedPeerArgs = $args({
4499
5196
  /**
4500
5197
  * The name of the WireGuard peer.
4501
5198
  *
4502
5199
  * If not provided, the peer will be named after the unit.
4503
5200
  */
4504
- peerName: z.string().optional(),
5201
+ peerName: $addArgumentDescription(z.string().optional(), `The name of the WireGuard peer.
5202
+
5203
+ If not provided, the peer will be named after the unit.`),
4505
5204
  /**
4506
- * The address of the WireGuard interface.
5205
+ * The addresses of the WireGuard interface.
4507
5206
  *
4508
5207
  * The address may be any IPv4 or IPv6 address. CIDR notation is also supported.
4509
5208
  */
4510
- address: z.string().optional(),
5209
+ addresses: $addArgumentDescription(z.string().array().default([]), `The addresses of the WireGuard interface.
5210
+
5211
+ The address may be any IPv4 or IPv6 address. CIDR notation is also supported.`),
4511
5212
  /**
4512
5213
  * The convenience option to set `allowedIps` to `0.0.0.0/0, ::/0`.
4513
5214
  *
4514
5215
  * Will be merged with the `allowedIps` if provided.
4515
5216
  */
4516
- exitNode: z.boolean().default(false),
5217
+ exitNode: $addArgumentDescription(z.boolean().default(false), `The convenience option to set \`allowedIps\` to \`0.0.0.0/0, ::/0\`.
5218
+
5219
+ Will be merged with the \`allowedIps\` if provided.`),
5220
+ /**
5221
+ * The list of IP ranges to include in the allowed IPs of the peer.
5222
+ */
5223
+ allowedSubnets: $addArgumentDescription(z.string().array().default([]), `The list of IP ranges to include in the allowed IPs of the peer.`),
4517
5224
  /**
4518
5225
  * The list of IP ranges to exclude from the tunnel.
4519
- *
4520
- * Implementation notes:
4521
- *
4522
- * - this list will not be used to generate the allowed IPs for the peer;
4523
- * - instead, the node will setup extra direct routes to these IPs via default gateway;
4524
- * - this allows to use `0.0.0.0/0, ::/0` in the `allowedIps` (and corresponding fwmark magic) and still have some IPs excluded from the tunnel.
4525
5226
  */
4526
- excludedIps: z.string().array().default([]),
5227
+ excludedSubnets: $addArgumentDescription(z.string().array().default([]), `The list of IP ranges to exclude from the tunnel.`),
4527
5228
  /**
4528
5229
  * The convenience option to exclude private IPs from the tunnel.
4529
5230
  *
@@ -4540,103 +5241,113 @@ var sharedPeerArgs = {
4540
5241
  *
4541
5242
  * Will be merged with `excludedIps` if provided.
4542
5243
  */
4543
- excludePrivateIps: z.boolean().default(false),
5244
+ excludePrivateSubnets: $addArgumentDescription(z.boolean().default(false), `The convenience option to exclude private IPs from the tunnel.
5245
+
5246
+ For IPv4, the private IPs are:
5247
+
5248
+ - \`10.0.0.0/8\`
5249
+ - \`172.16.0.0/12\`
5250
+ - \`192.168.0.0/16\`
5251
+
5252
+ For IPv6, the private IPs are:
5253
+
5254
+ - \`fc00::/7\`
5255
+ - \`fe80::/10\`
5256
+
5257
+ Will be merged with \`excludedIps\` if provided.`),
4544
5258
  /**
4545
5259
  * The endpoints of the WireGuard peer.
4546
5260
  */
4547
- endpoints: z.string().array().default([]),
5261
+ endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the WireGuard peer.`),
4548
5262
  /**
4549
- * The allowed endpoints of the WireGuard peer.
5263
+ * The DNS servers that should be used by the interface connected to the WireGuard peer.
4550
5264
  *
4551
- * The non `hostname` endpoints will be added to the `allowedIps` of the peer.
5265
+ * If multiple peers define DNS servers, the node will merge them into a single list (but this is discouraged).
4552
5266
  */
4553
- allowedEndpoints: z.string().array().default([]),
5267
+ dns: $addArgumentDescription(z.string().array().default([]), `The DNS servers that should be used by the interface connected to the WireGuard peer.
5268
+
5269
+ If multiple peers define DNS servers, the node will merge them into a single list (but this is discouraged).`),
4554
5270
  /**
4555
- * The DNS servers that should be used by the interface connected to the WireGuard peer.
5271
+ * The convenience option to include the addresses to the allowed IPs.
4556
5272
  *
4557
- * If multiple peers define DNS servers, the node will merge them into a single list (but this is discouraged).
5273
+ * By default, is `true`.
4558
5274
  */
4559
- dns: z.string().array().default([]),
5275
+ includeAddresses: $addArgumentDescription(z.boolean().default(true), `The convenience option to include the addresses to the allowed IPs.
5276
+
5277
+ By default, is \`true\`.`),
4560
5278
  /**
4561
5279
  * The convenience option to include the DNS servers to the allowed IPs.
4562
5280
  *
4563
5281
  * By default, is `true`.
4564
5282
  */
4565
- includeDns: z.boolean().default(true),
5283
+ includeDns: $addArgumentDescription(z.boolean().default(true), `The convenience option to include the DNS servers to the allowed IPs.
5284
+
5285
+ By default, is \`true\`.`),
4566
5286
  /**
4567
5287
  * The port to listen on.
4568
5288
  */
4569
- listenPort: z.number().optional(),
5289
+ listenPort: $addArgumentDescription(z.number().default(51820), `The port to listen on.`),
4570
5290
  /**
4571
5291
  * The keepalive interval in seconds that will be used by all nodes connecting to this peer.
4572
5292
  *
4573
5293
  * If set to 0, keepalive is disabled.
4574
5294
  */
4575
- persistentKeepalive: z.number().int().nonnegative().default(0)
4576
- };
4577
- var sharedPeerInputs = {
5295
+ persistentKeepalive: $addArgumentDescription(z.number().int().nonnegative().default(0), `The keepalive interval in seconds that will be used by all nodes connecting to this peer.
5296
+
5297
+ If set to 0, keepalive is disabled.`)
5298
+ });
5299
+ var sharedPeerInputs = $inputs({
4578
5300
  /**
4579
5301
  * The network to use for the WireGuard identity.
4580
5302
  *
4581
5303
  * If not provided, the identity will use default network configuration.
4582
5304
  */
4583
- network: {
5305
+ network: $addInputDescription({
4584
5306
  entity: networkEntity,
4585
5307
  required: false
4586
- },
5308
+ }, `The network to use for the WireGuard identity.
5309
+
5310
+ If not provided, the identity will use default network configuration.`),
4587
5311
  /**
4588
- * The L3 endpoints of the identity.
5312
+ * The L3/L4 endpoints of the identity.
4589
5313
  *
4590
- * Will produce L4 endpoints for each of the provided L3 endpoints.
5314
+ * All L3 endpoints will be adjusted to L4 endpoints with listen port of the identity.
4591
5315
  */
4592
- l3Endpoints: {
5316
+ endpoints: $addInputDescription({
4593
5317
  entity: l3EndpointEntity,
4594
5318
  multiple: true,
4595
5319
  required: false
4596
- },
5320
+ }, `The L3/L4 endpoints of the identity.
5321
+
5322
+ All L3 endpoints will be adjusted to L4 endpoints with listen port of the identity.`),
4597
5323
  /**
4598
- * The L4 endpoints of the identity.
4599
- *
4600
- * Will take priority over all calculated endpoints if provided.
5324
+ * the endpoints to add to the allowed IPs of the identity.
4601
5325
  */
4602
- l4Endpoints: {
4603
- entity: l4EndpointEntity,
4604
- required: false,
4605
- multiple: true
4606
- },
5326
+ allowedEndpoints: $addInputDescription({
5327
+ entity: l3EndpointEntity,
5328
+ multiple: true,
5329
+ required: false
5330
+ }, `the endpoints to add to the allowed IPs of the identity.`),
4607
5331
  /**
4608
- * The L3 endpoints to add to the allowed IPs of the identity.
4609
- *
4610
- * `hostname` endpoints will be ignored.
4611
- *
4612
- * If the endpoint contains k8s service metadata of the cluster where the identity node is deployed,
4613
- * the corresponding network policy will be created.
5332
+ * The subnets to add to the allowed IPs of the identity.
4614
5333
  */
4615
- allowedL3Endpoints: {
4616
- entity: l3EndpointEntity,
5334
+ allowedSubnets: $addInputDescription({
5335
+ entity: subnetEntity,
4617
5336
  multiple: true,
4618
5337
  required: false
4619
- },
5338
+ }, `The subnets to add to the allowed IPs of the identity.`),
4620
5339
  /**
4621
- * The L4 endpoints to add to the allowed IPs of the identity.
4622
- *
4623
- * If the endpoint contains k8s service metadata of the cluster where the identity node is deployed,
4624
- * the corresponding network policy will be created.
5340
+ * The peers which are relayed through this peer.
4625
5341
  */
4626
- allowedL4Endpoints: {
4627
- entity: l4EndpointEntity,
5342
+ relayedPeers: $addInputDescription({
5343
+ entity: peerEntity,
4628
5344
  multiple: true,
4629
5345
  required: false
4630
- }
4631
- };
4632
- var sharedPeerOutputs = {
4633
- peer: peerEntity,
4634
- endpoints: {
4635
- entity: l4EndpointEntity,
4636
- required: false,
4637
- multiple: true
4638
- }
4639
- };
5346
+ }, `The peers which are relayed through this peer.`)
5347
+ });
5348
+ var sharedPeerOutputs = $outputs({
5349
+ peer: peerEntity
5350
+ });
4640
5351
  var peer = defineUnit({
4641
5352
  type: "wireguard.peer.v1",
4642
5353
  args: {
@@ -4668,53 +5379,12 @@ var peer = defineUnit({
4668
5379
  });
4669
5380
  var peerPatch = defineUnit({
4670
5381
  type: "wireguard.peer-patch.v1",
4671
- args: {
4672
- /**
4673
- * The endpoints of the WireGuard peer.
4674
- */
4675
- endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the WireGuard peer.`),
4676
- /**
4677
- * The mode to use for patching the endpoints.
4678
- *
4679
- * - `prepend`: prepend the new endpoints to the existing ones (default);
4680
- * - `replace`: replace the existing endpoints with the new ones.
4681
- */
4682
- endpointsPatchMode: $addArgumentDescription(arrayPatchModeSchema.default("prepend"), `The mode to use for patching the endpoints.
4683
-
4684
- - \`prepend\`: prepend the new endpoints to the existing ones (default);
4685
- - \`replace\`: replace the existing endpoints with the new ones.`),
4686
- /**
4687
- * The allowed endpoints of the WireGuard peer.
4688
- *
4689
- * The non `hostname` endpoints will be added to the `allowedIps` of the peer.
4690
- */
4691
- allowedEndpoints: $addArgumentDescription(z.string().array().default([]), `The allowed endpoints of the WireGuard peer.
4692
-
4693
- The non \`hostname\` endpoints will be added to the \`allowedIps\` of the peer.`),
4694
- /**
4695
- * The mode to use for patching the allowed endpoints.
4696
- *
4697
- * - `prepend`: prepend the new endpoints to the existing ones (default);
4698
- * - `replace`: replace the existing endpoints with the new ones.
4699
- */
4700
- allowedEndpointsPatchMode: $addArgumentDescription(arrayPatchModeSchema.default("prepend"), `The mode to use for patching the allowed endpoints.
4701
-
4702
- - \`prepend\`: prepend the new endpoints to the existing ones (default);
4703
- - \`replace\`: replace the existing endpoints with the new ones.`),
4704
- ...omit(sharedPeerArgs, ["endpoints", "allowedEndpoints"])
4705
- },
5382
+ args: toPatchArgs(sharedPeerArgs),
4706
5383
  inputs: {
4707
5384
  peer: peerEntity,
4708
5385
  ...sharedPeerInputs
4709
5386
  },
4710
- outputs: {
4711
- peer: peerEntity,
4712
- endpoints: {
4713
- entity: l4EndpointEntity,
4714
- required: false,
4715
- multiple: true
4716
- }
4717
- },
5387
+ outputs: sharedPeerOutputs,
4718
5388
  meta: {
4719
5389
  description: `Patches some properties of the WireGuard peer.`,
4720
5390
  title: "WireGuard Peer Patch",
@@ -4730,29 +5400,7 @@ var peerPatch = defineUnit({
4730
5400
  });
4731
5401
  var identity = defineUnit({
4732
5402
  type: "wireguard.identity.v1",
4733
- args: {
4734
- ...sharedPeerArgs,
4735
- /**
4736
- * The port to listen on.
4737
- *
4738
- * Used by the implementation of the identity and to calculate the endpoint of the peer.
4739
- */
4740
- listenPort: $addArgumentDescription(z.number().optional(), `The port to listen on.
4741
-
4742
- Used by the implementation of the identity and to calculate the endpoint of the peer.`),
4743
- /**
4744
- * The endpoint of the WireGuard peer.
4745
- *
4746
- * If overridden, does not affect node which implements the identity, but is used in the peer configuration of other nodes.
4747
- *
4748
- * Will take priority over all calculated endpoints and `l4Endpoint` input.
4749
- */
4750
- endpoints: $addArgumentDescription(z.string().array().default([]), `The endpoint of the WireGuard peer.
4751
-
4752
- If overridden, does not affect node which implements the identity, but is used in the peer configuration of other nodes.
4753
-
4754
- Will take priority over all calculated endpoints and \`l4Endpoint\` input.`)
4755
- },
5403
+ args: sharedPeerArgs,
4756
5404
  secrets: {
4757
5405
  /**
4758
5406
  * The private key of the WireGuard identity.
@@ -4773,8 +5421,7 @@ var identity = defineUnit({
4773
5421
  },
4774
5422
  inputs: sharedPeerInputs,
4775
5423
  outputs: {
4776
- identity: identityEntity,
4777
- ...sharedPeerOutputs
5424
+ identity: identityEntity
4778
5425
  },
4779
5426
  meta: {
4780
5427
  description: `The WireGuard identity with the public key.`,
@@ -4835,7 +5482,7 @@ var nodeK8s = defineUnit({
4835
5482
  *
4836
5483
  * Useful for peer isolation where you want to prevent cross-peer communication.
4837
5484
  */
4838
- forwardRestrictedIps: $addArgumentDescription(z.string().array().default([]), `List of CIDR blocks that should be blocked from forwarding through this WireGuard node.
5485
+ forwardRestrictedSubnets: $addArgumentDescription(z.string().array().default([]), `List of CIDR blocks that should be blocked from forwarding through this WireGuard node.
4839
5486
 
4840
5487
  This prevents other peers from reaching these destination CIDRs while still allowing
4841
5488
  the peers in those CIDRs to access the internet and other allowed endpoints.
@@ -4846,7 +5493,7 @@ var nodeK8s = defineUnit({
4846
5493
  identity: identityEntity,
4847
5494
  k8sCluster: clusterEntity,
4848
5495
  workload: {
4849
- entity: exposableWorkloadEntity,
5496
+ entity: workloadEntity,
4850
5497
  required: false
4851
5498
  },
4852
5499
  interface: {
@@ -4860,18 +5507,14 @@ var nodeK8s = defineUnit({
4860
5507
  }
4861
5508
  },
4862
5509
  outputs: {
5510
+ workload: {
5511
+ entity: workloadEntity
5512
+ },
4863
5513
  interface: {
4864
- entity: networkInterfaceEntity,
4865
- required: false
5514
+ entity: networkInterfaceEntity
4866
5515
  },
4867
5516
  peer: {
4868
- entity: peerEntity,
4869
- required: false
4870
- },
4871
- endpoints: {
4872
- entity: l4EndpointEntity,
4873
- required: false,
4874
- multiple: true
5517
+ entity: peerEntity
4875
5518
  }
4876
5519
  },
4877
5520
  meta: {
@@ -4898,14 +5541,6 @@ var node2 = defineUnit({
4898
5541
  interfaceName: $addArgumentDescription(z.string().optional(), `The name of the WireGuard interface.
4899
5542
 
4900
5543
  By default, the name is \`wg-\${identity.name}\` (truncated to 15 characters).`),
4901
- /**
4902
- * The name of the default interface for excluded routes.
4903
- *
4904
- * This is used to route excluded IPs through the default interface instead of the WireGuard tunnel.
4905
- */
4906
- defaultInterface: $addArgumentDescription(z.string().default("eth0"), `The name of the default interface for excluded routes.
4907
-
4908
- This is used to route excluded IPs through the default interface instead of the WireGuard tunnel.`),
4909
5544
  /**
4910
5545
  * List of CIDR blocks that should be blocked from forwarding through this WireGuard node.
4911
5546
  *
@@ -4981,17 +5616,48 @@ var node2 = defineUnit({
4981
5616
  path: "node"
4982
5617
  }
4983
5618
  });
5619
+ var sharedArgs3 = $args({
5620
+ /**
5621
+ * The filter to use when selecting endpoints for each peer.
5622
+ *
5623
+ * The first matching endpoint will be used.
5624
+ *
5625
+ * If not provided, all endpoints will be considered.
5626
+ */
5627
+ peerEndpointFilter: $addArgumentDescription(z.string().optional().meta({ language: "javascript" }), `The filter to use when selecting endpoints for each peer.
5628
+
5629
+ The first matching endpoint will be used.
5630
+
5631
+ If not provided, all endpoints will be considered.`)
5632
+ });
4984
5633
  var config = defineUnit({
4985
5634
  type: "wireguard.config.v1",
4986
5635
  args: {
5636
+ ...sharedArgs3,
4987
5637
  /**
4988
- * The name of the "default" interface where non-tunneled traffic should go.
4989
- *
4990
- * If not provided, the config will not respect `excludedIps`.
5638
+ * The metadata to include in the wg-feed for this config.
4991
5639
  */
4992
- defaultInterface: $addArgumentDescription(z.string().optional(), `The name of the "default" interface where non-tunneled traffic should go.
5640
+ feedMetadata: $addArgumentDescription(z.discriminatedUnion("enabled", [
5641
+ z.object({
5642
+ /**
5643
+ * Whether this config is enabled for upload to wg-feed.
5644
+ *
5645
+ * You must fill the metadata fields.
5646
+ */
5647
+ enabled: z.literal("true").meta({ title: camelCaseToHumanReadable("enabled"), description: `Whether this config is enabled for upload to wg-feed.
4993
5648
 
4994
- If not provided, the config will not respect \`excludedIps\`.`)
5649
+ You must fill the metadata fields.` }),
5650
+ ...pick(feedMetadataSchema.shape, ["id", "name"]),
5651
+ // Highstate does not support nested objects in UI
5652
+ ...feedDisplayInfoSchema.shape
5653
+ }),
5654
+ z.object({
5655
+ /**
5656
+ * Whether this config is enabled for upload to wg-feed.
5657
+ */
5658
+ enabled: z.literal("false").meta({ title: camelCaseToHumanReadable("enabled"), description: `Whether this config is enabled for upload to wg-feed.` })
5659
+ })
5660
+ ]).prefault({ enabled: "false" }), `The metadata to include in the wg-feed for this config.`)
4995
5661
  },
4996
5662
  inputs: {
4997
5663
  identity: identityEntity,
@@ -5001,6 +5667,9 @@ var config = defineUnit({
5001
5667
  required: false
5002
5668
  }
5003
5669
  },
5670
+ outputs: {
5671
+ config: configEntity
5672
+ },
5004
5673
  meta: {
5005
5674
  description: `Just the WireGuard configuration for the identity and peers.`,
5006
5675
  title: "WireGuard Config",
@@ -5016,6 +5685,9 @@ var config = defineUnit({
5016
5685
  });
5017
5686
  var configBundle = defineUnit({
5018
5687
  type: "wireguard.config-bundle.v1",
5688
+ args: {
5689
+ ...sharedArgs3
5690
+ },
5019
5691
  inputs: {
5020
5692
  identity: identityEntity,
5021
5693
  peers: {
@@ -5028,6 +5700,12 @@ var configBundle = defineUnit({
5028
5700
  required: false
5029
5701
  }
5030
5702
  },
5703
+ outputs: {
5704
+ configs: {
5705
+ entity: configEntity,
5706
+ multiple: true
5707
+ }
5708
+ },
5031
5709
  meta: {
5032
5710
  description: `The WireGuard configuration bundle for the identity and peers.`,
5033
5711
  title: "WireGuard Config Bundle",
@@ -5041,6 +5719,96 @@ var configBundle = defineUnit({
5041
5719
  path: "config-bundle"
5042
5720
  }
5043
5721
  });
5722
+ var feed = defineUnit({
5723
+ type: "wireguard.feed.v1",
5724
+ args: {
5725
+ /**
5726
+ * The TTL seconds to suggest to wg-feed clients.
5727
+ *
5728
+ * By default, is 900 seconds (15 minutes).
5729
+ */
5730
+ ttlSeconds: $addArgumentDescription(z.number().int().positive().default(900), `The TTL seconds to suggest to wg-feed clients.
5731
+
5732
+ By default, is 900 seconds (15 minutes).`),
5733
+ /**
5734
+ * The endpoints of the wg-feed servers to use for generating the subscription URLs.
5735
+ *
5736
+ * At least one endpoint must be provided either here or via `serverEndpoints` input.
5737
+ *
5738
+ * The resulting subscription URL will be inferred as: `https://{firstEndpoint}/{feedId}#{privateKey}`.
5739
+ */
5740
+ serverEndpoints: $addArgumentDescription(z.string().array().default([]), `The endpoints of the wg-feed servers to use for generating the subscription URLs.
5741
+
5742
+ At least one endpoint must be provided either here or via \`serverEndpoints\` input.
5743
+
5744
+ The resulting subscription URL will be inferred as: \`https://{firstEndpoint}/{feedId}#{privateKey}\`.`),
5745
+ /**
5746
+ * The AGE public key (x25519 recipient) to encrypt the configs with.
5747
+ *
5748
+ * Note: If you provide this, you must provide the corresponding private key to the clients.
5749
+ * Resulting subscription URL will not contain the private key.
5750
+ */
5751
+ publicKey: $addArgumentDescription(z.string().optional(), `The AGE public key (x25519 recipient) to encrypt the configs with.
5752
+
5753
+ Note: If you provide this, you must provide the corresponding private key to the clients.
5754
+ Resulting subscription URL will not contain the private key.`),
5755
+ /**
5756
+ * The display information of the feed.
5757
+ */
5758
+ displayInfo: $addArgumentDescription(feedDisplayInfoSchema, `The display information of the feed.`)
5759
+ },
5760
+ secrets: {
5761
+ /**
5762
+ * The cuidv2 of the feed.
5763
+ * Will be used as path of the feed in etcd/subscription URL.
5764
+ *
5765
+ * In most cases, you don't want to provide this and let it be generated automatically.
5766
+ *
5767
+ * The `id` field of the feed document will be inferred from this value as `uuidv5(feedId, "2b5e358c-3510-48fb-b1cf-a8aee788925a")`.
5768
+ */
5769
+ feedId: $addArgumentDescription(z.string().optional(), `The cuidv2 of the feed.
5770
+ Will be used as path of the feed in etcd/subscription URL.
5771
+
5772
+ In most cases, you don't want to provide this and let it be generated automatically.
5773
+
5774
+ The \`id\` field of the feed document will be inferred from this value as \`uuidv5(feedId, "2b5e358c-3510-48fb-b1cf-a8aee788925a")\`.`),
5775
+ /**
5776
+ * The AGE private key (x25519 identity) to embed in the subscription URL.
5777
+ *
5778
+ * If not provided and `publicKey` is not provided, a new key pair will be generated.
5779
+ */
5780
+ privateKey: $addArgumentDescription(z.string().optional(), `The AGE private key (x25519 identity) to embed in the subscription URL.
5781
+
5782
+ If not provided and \`publicKey\` is not provided, a new key pair will be generated.`)
5783
+ },
5784
+ inputs: {
5785
+ etcd: etcdEntity,
5786
+ serverEndpoints: {
5787
+ entity: l4EndpointEntity,
5788
+ required: false,
5789
+ multiple: true
5790
+ },
5791
+ configs: {
5792
+ entity: configEntity,
5793
+ multiple: true
5794
+ }
5795
+ },
5796
+ outputs: {
5797
+ endpoint: l7EndpointEntity
5798
+ },
5799
+ source: {
5800
+ package: "@highstate/wireguard",
5801
+ path: "feed"
5802
+ },
5803
+ meta: {
5804
+ description: `Uploads WireGuard configs to the etcd to be consumed by wg-feed clients.`,
5805
+ title: "WireGuard Feed",
5806
+ icon: "simple-icons:wireguard",
5807
+ iconColor: "#88171a",
5808
+ secondaryIcon: "mdi:rss",
5809
+ category: "VPN"
5810
+ }
5811
+ });
5044
5812
 
5045
5813
  // src/third-party/mullvad.ts
5046
5814
  var peer2 = defineUnit({
@@ -5168,7 +5936,7 @@ var virtualMachine2 = defineUnit({
5168
5936
  },
5169
5937
  inputs: {
5170
5938
  connection: connectionEntity,
5171
- ...inputs2
5939
+ ...inputs
5172
5940
  },
5173
5941
  secrets: vmSecrets,
5174
5942
  outputs: {
@@ -5280,7 +6048,7 @@ var connection4 = defineUnit({
5280
6048
  See [Creating an authorized key](https://yandex.cloud/en/docs/iam/operations/authentication/manage-authorized-keys#create-authorized-key) for details.`)
5281
6049
  },
5282
6050
  inputs: {
5283
- ...inputs2
6051
+ ...inputs
5284
6052
  },
5285
6053
  outputs: {
5286
6054
  /**
@@ -5517,7 +6285,7 @@ var virtualMachine3 = defineUnit({
5517
6285
  inputs: {
5518
6286
  connection: connectionEntity2,
5519
6287
  image: imageEntity2,
5520
- ...inputs2
6288
+ ...inputs
5521
6289
  },
5522
6290
  outputs: serverOutputs,
5523
6291
  meta: {
@@ -5534,6 +6302,6 @@ var virtualMachine3 = defineUnit({
5534
6302
  }
5535
6303
  });
5536
6304
 
5537
- export { arrayPatchModeSchema, booleanPatchSchema, cloudflare_exports as cloudflare, common_exports as common, databases_exports as databases, distributions_exports as distributions, dns_exports as dns, git_exports as git, implementationReferenceSchema, k3s_exports as k3s, k8s_exports as k8s, mullvad_exports as mullvad, network_exports as network, nixos_exports as nixos, prefixKeysWith, proxmox_exports as proxmox, restic_exports as restic, sops_exports as sops, ssh_exports as ssh, talos_exports as talos, timeweb_exports as timeweb, wireguard_exports as wireguard, yandex_exports as yandex };
6305
+ export { booleanPatchSchema, cloudflare_exports as cloudflare, common_exports as common, databases_exports as databases, distributions_exports as distributions, dns_exports as dns, git_exports as git, implementationReferenceSchema, k3s_exports as k3s, k8s_exports as k8s, metadataKeySchema, metadataSchema, mullvad_exports as mullvad, network_exports as network, nixos_exports as nixos, prefixKeysWith, proxmox_exports as proxmox, restic_exports as restic, sops_exports as sops, ssh_exports as ssh, talos_exports as talos, timeweb_exports as timeweb, toPatchArgs, wireguard_exports as wireguard, yandex_exports as yandex };
5538
6306
  //# sourceMappingURL=index.js.map
5539
6307
  //# sourceMappingURL=index.js.map