@highstate/library 0.9.8 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/library",
3
- "version": "0.9.8",
3
+ "version": "0.9.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -19,12 +19,12 @@
19
19
  "build": "highstate build --library"
20
20
  },
21
21
  "dependencies": {
22
- "@highstate/contract": "^0.9.8",
22
+ "@highstate/contract": "^0.9.10",
23
23
  "@sinclair/typebox": "^0.34.11",
24
24
  "remeda": "^2.21.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@highstate/cli": "^0.9.8"
27
+ "@highstate/cli": "^0.9.10"
28
28
  },
29
- "gitHead": "036db4d9937ff30edf15f143482c5702e5b7a7fb"
29
+ "gitHead": "aacf8837fdf40f2bb2f83d4c11b35a358e26ec33"
30
30
  }
@@ -1,6 +1,6 @@
1
1
  import { defineUnit, Type } from "@highstate/contract"
2
2
  import { persistentVolumeClaimEntity, statefulSetEntity } from "../k8s"
3
- import { createArgs, createInputs } from "./shared"
3
+ import { createArgs, createInputs, createSecrets } from "./shared"
4
4
 
5
5
  export const codeServer = defineUnit({
6
6
  type: "apps.code-server",
@@ -8,6 +8,7 @@ export const codeServer = defineUnit({
8
8
  args: createArgs("code-server", ["fqdn"]),
9
9
 
10
10
  secrets: {
11
+ ...createSecrets(["backupPassword"]),
11
12
  password: Type.Optional(Type.String()),
12
13
  sudoPassword: Type.Optional(Type.String()),
13
14
  },
package/src/apps/grocy.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { defineUnit } from "@highstate/contract"
2
- import { createArgs, createInputs, createSource } from "./shared"
2
+ import { createArgs, createInputs, createSecrets, createSource } from "./shared"
3
3
 
4
4
  export const grocy = defineUnit({
5
5
  type: "apps.grocy",
6
6
 
7
7
  args: createArgs("grocy", ["fqdn"]),
8
+ secrets: createSecrets(["backupPassword"]),
8
9
  inputs: createInputs(["accessPoint", "resticRepo"]),
9
10
 
10
11
  meta: {
@@ -1,8 +1,10 @@
1
1
  import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
2
  import { serviceEntity } from "../k8s"
3
+ import { l4EndpointEntity } from "../network"
3
4
  import {
4
5
  createArgs,
5
6
  createInputs,
7
+ createSecrets,
6
8
  createSource,
7
9
  databaseSchema,
8
10
  extraInputDefinitions,
@@ -22,16 +24,16 @@ export const mariadb = defineUnit({
22
24
  type: "apps.mariadb",
23
25
 
24
26
  args: createArgs("mariadb", ["external"]),
25
-
26
- secrets: {
27
- rootPassword: Type.Optional(Type.String()),
28
- },
29
-
27
+ secrets: createSecrets(["rootPassword", "backupPassword"]),
30
28
  inputs: createInputs(["resticRepo"]),
31
29
 
32
30
  outputs: {
33
31
  mariadb: mariadbEntity,
34
32
  service: serviceEntity,
33
+ endpoints: {
34
+ entity: l4EndpointEntity,
35
+ multiple: true,
36
+ },
35
37
  },
36
38
 
37
39
  meta: {
package/src/apps/maybe.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { defineUnit, Type } from "@highstate/contract"
2
- import { createArgs, createInputs, createSource } from "./shared"
2
+ import { createArgs, createInputs, createSecrets, createSource } from "./shared"
3
3
 
4
4
  export const maybe = defineUnit({
5
5
  type: "apps.maybe",
@@ -7,6 +7,7 @@ export const maybe = defineUnit({
7
7
  args: createArgs("maybe", ["fqdn"]),
8
8
 
9
9
  secrets: {
10
+ ...createSecrets(["backupPassword"]),
10
11
  postgresqlPassword: Type.Optional(Type.String()),
11
12
  secretKey: Type.Optional(Type.String()),
12
13
  },
@@ -1,8 +1,10 @@
1
1
  import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
2
  import { serviceEntity } from "../k8s"
3
+ import { l4EndpointEntity } from "../network"
3
4
  import {
4
5
  createArgs,
5
6
  createInputs,
7
+ createSecrets,
6
8
  createSource,
7
9
  databaseSchema,
8
10
  extraInputDefinitions,
@@ -22,16 +24,16 @@ export const mongodb = defineUnit({
22
24
  type: "apps.mongodb",
23
25
 
24
26
  args: createArgs("mongodb", ["external"]),
25
-
26
- secrets: {
27
- rootPassword: Type.Optional(Type.String()),
28
- },
29
-
27
+ secrets: createSecrets(["rootPassword", "backupPassword"]),
30
28
  inputs: createInputs(["resticRepo"]),
31
29
 
32
30
  outputs: {
33
31
  mongodb: mongodbEntity,
34
32
  service: serviceEntity,
33
+ endpoints: {
34
+ entity: l4EndpointEntity,
35
+ multiple: true,
36
+ },
35
37
  },
36
38
 
37
39
  meta: {
@@ -1,8 +1,10 @@
1
1
  import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
2
  import { serviceEntity } from "../k8s"
3
+ import { l4EndpointEntity } from "../network"
3
4
  import {
4
5
  createArgs,
5
6
  createInputs,
7
+ createSecrets,
6
8
  createSource,
7
9
  databaseSchema,
8
10
  extraInputDefinitions,
@@ -22,16 +24,16 @@ export const postgresql = defineUnit({
22
24
  type: "apps.postgresql",
23
25
 
24
26
  args: createArgs("postgresql", ["external"]),
25
-
26
- secrets: {
27
- rootPassword: Type.Optional(Type.String()),
28
- },
29
-
27
+ secrets: createSecrets(["rootPassword", "backupPassword"]),
30
28
  inputs: createInputs(["resticRepo", "dnsProviders"]),
31
29
 
32
30
  outputs: {
33
31
  postgresql: postgresqlEntity,
34
32
  service: serviceEntity,
33
+ endpoints: {
34
+ entity: l4EndpointEntity,
35
+ multiple: true,
36
+ },
35
37
  },
36
38
 
37
39
  meta: {
@@ -27,6 +27,17 @@ const extraArgsDefinitions = {
27
27
  },
28
28
  } as const
29
29
 
30
+ const extraSecretsDefinitions = {
31
+ rootPassword: {
32
+ schema: Type.String(),
33
+ required: false,
34
+ },
35
+ backupPassword: {
36
+ schema: Type.String(),
37
+ required: false,
38
+ },
39
+ }
40
+
30
41
  type LazyExtraInputDefinitions = {
31
42
  mariadb: {
32
43
  entity: typeof mariadbEntity
@@ -66,13 +77,23 @@ export const extraInputDefinitions = {
66
77
  } as typeof eagerExtraInputDefinitions & LazyExtraInputDefinitions
67
78
 
68
79
  type ExtraArgsDefinitions = typeof extraArgsDefinitions
80
+ type ExtraSecretsDefinitions = typeof extraSecretsDefinitions
69
81
  type ExtraArgsName = keyof ExtraArgsDefinitions
82
+ type ExtraSecretsName = keyof ExtraSecretsDefinitions
70
83
 
71
84
  type CreateArgsOptions<R extends readonly ExtraArgsName[], O extends readonly ExtraArgsName[]> = {
72
85
  required?: R
73
86
  optional?: O
74
87
  }
75
88
 
89
+ type CreateSecretsOptions<
90
+ R extends readonly ExtraSecretsName[],
91
+ O extends readonly ExtraSecretsName[],
92
+ > = {
93
+ required?: R
94
+ optional?: O
95
+ }
96
+
76
97
  export function createArgs<T extends readonly ExtraArgsName[] = []>(
77
98
  defaultAppName: string,
78
99
  extraArgs?: T,
@@ -134,6 +155,58 @@ export function createArgs<
134
155
  }
135
156
  }
136
157
 
158
+ export function createSecrets<T extends readonly ExtraSecretsName[] = []>(
159
+ extraSecrets?: T,
160
+ ): {
161
+ [K in T[number]]: ExtraSecretsDefinitions[K]
162
+ }
163
+
164
+ export function createSecrets<
165
+ R extends readonly ExtraSecretsName[] = [],
166
+ O extends readonly ExtraSecretsName[] = [],
167
+ >(
168
+ extraSecrets?: CreateSecretsOptions<R, O>,
169
+ ): {
170
+ [K in R[number]]: ExtraSecretsDefinitions[K] & { required: true }
171
+ } & {
172
+ [K in O[number]]: ExtraSecretsDefinitions[K] & { required: false }
173
+ }
174
+
175
+ export function createSecrets<
176
+ R extends readonly ExtraSecretsName[] = [],
177
+ O extends readonly ExtraSecretsName[] = [],
178
+ >(extraSecrets?: readonly ExtraSecretsName[] | CreateSecretsOptions<R, O>) {
179
+ const dynamicSecrets: Partial<Record<ExtraSecretsName, object>> = {}
180
+
181
+ if (Array.isArray(extraSecrets)) {
182
+ for (const name of extraSecrets as readonly ExtraSecretsName[]) {
183
+ dynamicSecrets[name] = extraSecretsDefinitions[name]
184
+ }
185
+ } else {
186
+ const { required, optional } = (extraSecrets as CreateSecretsOptions<R, O>) ?? {}
187
+
188
+ for (const name of required ?? []) {
189
+ dynamicSecrets[name] = {
190
+ ...extraSecretsDefinitions[name],
191
+ required: true,
192
+ }
193
+ }
194
+
195
+ for (const name of optional ?? []) {
196
+ dynamicSecrets[name] = {
197
+ ...extraSecretsDefinitions[name],
198
+ required: false,
199
+ }
200
+ }
201
+ }
202
+
203
+ return dynamicSecrets as {
204
+ [K in R[number]]: ExtraSecretsDefinitions[K] & { required: true }
205
+ } & {
206
+ [K in O[number]]: ExtraSecretsDefinitions[K] & { required: false }
207
+ }
208
+ }
209
+
137
210
  type ExtraInputDefinitions = typeof extraInputDefinitions
138
211
  type ExtraInputName = keyof ExtraInputDefinitions
139
212
 
@@ -1,6 +1,7 @@
1
1
  import { defineUnit, Type } from "@highstate/contract"
2
2
  import { persistentVolumeClaimEntity, serviceEntity } from "../k8s"
3
- import { createArgs, createInputs, createSource } from "./shared"
3
+ import { l4EndpointEntity } from "../network"
4
+ import { createArgs, createInputs, createSecrets, createSource } from "./shared"
4
5
 
5
6
  export const backupModeSchema = Type.StringEnum(["state", "full"])
6
7
 
@@ -8,7 +9,7 @@ export const syncthing = defineUnit({
8
9
  type: "apps.syncthing",
9
10
 
10
11
  args: {
11
- ...createArgs("syncthing", ["fqdn"]),
12
+ ...createArgs("syncthing", ["fqdn", "external"]),
12
13
 
13
14
  /**
14
15
  * The FQDN of the Syncthing instance used to sync with other devices.
@@ -30,11 +31,16 @@ export const syncthing = defineUnit({
30
31
  backupMode: Type.Default(backupModeSchema, "state"),
31
32
  },
32
33
 
33
- inputs: createInputs(["accessPoint", "resticRepo", "dnsProviders", "volume"]),
34
+ secrets: createSecrets(["backupPassword"]),
35
+ inputs: createInputs(["accessPoint", "resticRepo", "volume"]),
34
36
 
35
37
  outputs: {
36
- service: serviceEntity,
37
38
  volume: persistentVolumeClaimEntity,
39
+ service: serviceEntity,
40
+ endpoints: {
41
+ entity: l4EndpointEntity,
42
+ multiple: true,
43
+ },
38
44
  },
39
45
 
40
46
  meta: {
@@ -1,5 +1,6 @@
1
1
  import { defineUnit, Type } from "@highstate/contract"
2
2
  import { gatewayEntity, serviceEntity } from "../k8s"
3
+ import { l4EndpointEntity } from "../network"
3
4
  import { createArgs, createInputs } from "./shared"
4
5
 
5
6
  export const traefikGateway = defineUnit({
@@ -15,6 +16,10 @@ export const traefikGateway = defineUnit({
15
16
  outputs: {
16
17
  gateway: gatewayEntity,
17
18
  service: serviceEntity,
19
+ endpoints: {
20
+ entity: l4EndpointEntity,
21
+ multiple: true,
22
+ },
18
23
  },
19
24
 
20
25
  meta: {
package/src/mullvad.ts CHANGED
@@ -21,6 +21,8 @@ export const peer = defineUnit({
21
21
  * The network to use for the WireGuard peer.
22
22
  *
23
23
  * If not provided, the peer will use default network configuration.
24
+ *
25
+ * @schema
24
26
  */
25
27
  network: {
26
28
  entity: networkEntity,
package/src/restic.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { defineEntity, defineUnit, Type, type Static } from "@highstate/contract"
2
+ import { l3EndpointEntity, l4EndpointEntity } from "./network"
2
3
 
3
4
  export const repoEntity = defineEntity({
4
5
  type: "restic.repo",
5
6
 
6
7
  schema: Type.Object({
7
- password: Type.String(),
8
- remoteEndpoints: Type.Array(Type.String()),
8
+ remoteEndpoints: Type.Array(Type.Union([l3EndpointEntity.schema, l4EndpointEntity.schema])),
9
9
 
10
10
  type: Type.Literal("rclone"),
11
11
  rcloneConfig: Type.String(),
12
12
  remoteName: Type.String(),
13
- basePath: Type.String(),
13
+ pathPattern: Type.String(),
14
14
  }),
15
15
 
16
16
  meta: {
@@ -22,13 +22,39 @@ export const repo = defineUnit({
22
22
  type: "restic.repo",
23
23
 
24
24
  args: {
25
- remoteDomains: Type.Optional(Type.Array(Type.String())),
26
- basePath: Type.Optional(Type.String()),
25
+ remoteEndpoints: Type.Default(Type.Array(Type.String()), []),
26
+
27
+ /**
28
+ * The pattern for the path where backups will be stored for the specific application.
29
+ *
30
+ * Available variables:
31
+ *
32
+ * - `$clusterName`: The name of the Kubernetes cluster where the application is deployed.
33
+ * - `$appName`: The name of the application for which the backups are being created. Corresponds to the `appName` argument of the unit.
34
+ * - `$unitName`: The name of the unit, which deploys the application, provided by the user.
35
+ *
36
+ * By default, the path pattern is `backups/$clusterName/$appName`.
37
+ *
38
+ * @schema
39
+ */
40
+ pathPattern: Type.Default(Type.String(), "backups/$clusterName/$appName"),
27
41
  },
28
42
 
29
43
  secrets: {
30
- password: Type.Optional(Type.String()),
31
- rcloneConfig: Type.String({ multiline: true }),
44
+ rcloneConfig: Type.String({ language: "ini" }),
45
+ },
46
+
47
+ inputs: {
48
+ remoteL3Endpoints: {
49
+ entity: l3EndpointEntity,
50
+ multiple: true,
51
+ required: false,
52
+ },
53
+ remoteL4Endpoints: {
54
+ entity: l4EndpointEntity,
55
+ multiple: true,
56
+ required: false,
57
+ },
32
58
  },
33
59
 
34
60
  outputs: {
@@ -1,5 +0,0 @@
1
- {
2
- "sourceHashes": {
3
- "./dist/index.js": "7e27bae537314a0fd9379cd60166c5042e6c10ba797885ecfabfafbfdf2a92b0"
4
- }
5
- }