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