@ninedeploy/schemas 0.10.6 → 0.16.1
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/LICENSE +21 -21
- package/dist/accessGrants.d.ts +156 -0
- package/dist/accessGrants.d.ts.map +1 -0
- package/dist/accessGrants.js +100 -0
- package/dist/accessGrants.js.map +1 -0
- package/dist/agentCommand.d.ts.map +1 -1
- package/dist/agentCommand.js +11 -1
- package/dist/agentCommand.js.map +1 -1
- package/dist/auth.d.ts +53 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +26 -0
- package/dist/auth.js.map +1 -1
- package/dist/backupPolicy.d.ts +37 -0
- package/dist/backupPolicy.d.ts.map +1 -0
- package/dist/backupPolicy.js +50 -0
- package/dist/backupPolicy.js.map +1 -0
- package/dist/common.d.ts +21 -5
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +35 -6
- package/dist/common.js.map +1 -1
- package/dist/databaseImport.d.ts +145 -0
- package/dist/databaseImport.d.ts.map +1 -0
- package/dist/databaseImport.js +115 -0
- package/dist/databaseImport.js.map +1 -0
- package/dist/doctor.d.ts +16 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +25 -0
- package/dist/doctor.js.map +1 -1
- package/dist/githubApp.d.ts +236 -0
- package/dist/githubApp.d.ts.map +1 -0
- package/dist/githubApp.js +223 -0
- package/dist/githubApp.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/kernel.d.ts +5 -2
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +11 -2
- package/dist/kernel.js.map +1 -1
- package/dist/management.d.ts +46 -2
- package/dist/management.d.ts.map +1 -1
- package/dist/management.js +68 -15
- package/dist/management.js.map +1 -1
- package/dist/multiNode.d.ts +326 -0
- package/dist/multiNode.d.ts.map +1 -0
- package/dist/multiNode.js +296 -0
- package/dist/multiNode.js.map +1 -0
- package/dist/ninedeployManifest.d.ts.map +1 -1
- package/dist/ninedeployManifest.js +6 -3
- package/dist/ninedeployManifest.js.map +1 -1
- package/dist/panelBackup.d.ts +73 -0
- package/dist/panelBackup.d.ts.map +1 -0
- package/dist/panelBackup.js +45 -0
- package/dist/panelBackup.js.map +1 -0
- package/dist/proxyConfig.d.ts +132 -0
- package/dist/proxyConfig.d.ts.map +1 -0
- package/dist/proxyConfig.js +105 -0
- package/dist/proxyConfig.js.map +1 -0
- package/dist/publicAccess.d.ts +64 -0
- package/dist/publicAccess.d.ts.map +1 -0
- package/dist/publicAccess.js +63 -0
- package/dist/publicAccess.js.map +1 -0
- package/dist/secretProviders.d.ts +119 -0
- package/dist/secretProviders.d.ts.map +1 -0
- package/dist/secretProviders.js +130 -0
- package/dist/secretProviders.js.map +1 -0
- package/dist/secretScan.js +1 -1
- package/dist/service.d.ts +235 -17
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +331 -26
- package/dist/service.js.map +1 -1
- package/dist/terminals.d.ts +284 -0
- package/dist/terminals.d.ts.map +1 -0
- package/dist/terminals.js +177 -0
- package/dist/terminals.js.map +1 -0
- package/dist/traffic.d.ts +276 -0
- package/dist/traffic.d.ts.map +1 -0
- package/dist/traffic.js +103 -0
- package/dist/traffic.js.map +1 -0
- package/dist/workspaces.d.ts +19 -1
- package/dist/workspaces.d.ts.map +1 -1
- package/dist/workspaces.js +26 -0
- package/dist/workspaces.js.map +1 -1
- package/package.json +5 -4
- package/src/accessGrants.ts +117 -0
- package/src/agentCommand.ts +67 -0
- package/src/ai.ts +32 -0
- package/src/auth.ts +323 -0
- package/src/backupPolicy.ts +55 -0
- package/src/common.ts +179 -0
- package/src/databaseImport.ts +138 -0
- package/src/doctor.ts +161 -0
- package/src/environments.ts +23 -0
- package/src/githubApp.ts +268 -0
- package/src/index.ts +30 -0
- package/src/insights.ts +78 -0
- package/src/kernel.ts +180 -0
- package/src/labels.ts +86 -0
- package/src/management.ts +620 -0
- package/src/multiNode.ts +356 -0
- package/src/ninedeployManifest.ts +363 -0
- package/src/panelBackup.ts +90 -0
- package/src/project.ts +42 -0
- package/src/proxyConfig.ts +139 -0
- package/src/publicAccess.ts +80 -0
- package/src/runtimeVersions.ts +232 -0
- package/src/secretProviders.ts +159 -0
- package/src/secretScan.ts +169 -0
- package/src/service.ts +1310 -0
- package/src/terminals.ts +212 -0
- package/src/traffic.ts +130 -0
- package/src/workspaces.ts +215 -0
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,WAAW;;;;EAAuC,CAAC;AAChE,eAAO,MAAM,SAAS;;;;;;EAAmE,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/service.js
CHANGED
|
@@ -1,7 +1,206 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { containerPath, dockerVolumeName, envVarName, gitBranch, gitRepoUrl, httpPath, repoBaseDir, repoRelativePath, slug } from './common.js';
|
|
2
|
+
import { containerPath, dockerVolumeName, envVarName, gitBranch, gitRepoUrl, httpPath, providerBaseUrl, repoBaseDir, repoRelativePath, slug } from './common.js';
|
|
3
3
|
export const serviceType = z.enum(['pm2', 'docker', 'compose']);
|
|
4
4
|
export const buildPack = z.enum(['auto', 'nixpacks', 'dockerfile', 'railpack', 'static']);
|
|
5
|
+
/**
|
|
6
|
+
* 0.16.1: names of the service's environment variables a Dockerfile build
|
|
7
|
+
* receives as `--build-arg` (the Dockerfile reads them with `ARG`). Opt-in per
|
|
8
|
+
* name: a build gets none unless listed. Nixpacks and Railpack builds already
|
|
9
|
+
* see the whole environment.
|
|
10
|
+
*/
|
|
11
|
+
export const buildArgNames = z.array(envVarName.max(100)).max(100);
|
|
12
|
+
/**
|
|
13
|
+
* 0.16.1: capabilities a docker service may add. Deliberately short: the ones
|
|
14
|
+
* real workloads ask for (VPNs, packet capture, profilers, realtime audio,
|
|
15
|
+
* mlock). SYS_ADMIN, SYS_MODULE, DAC_READ_SEARCH and the like are left out —
|
|
16
|
+
* each is a known path out of the container.
|
|
17
|
+
*/
|
|
18
|
+
export const runtimeCapability = z.enum(['NET_ADMIN', 'NET_RAW', 'SYS_PTRACE', 'SYS_NICE', 'SYS_RESOURCE', 'IPC_LOCK', 'SYS_TIME']);
|
|
19
|
+
/**
|
|
20
|
+
* 0.16.1 advanced container options for docker services (operator only):
|
|
21
|
+
* structured fields, never free-form `docker run` flags, so nothing outside
|
|
22
|
+
* this list (privileged, host mounts, host network…) can be asked for.
|
|
23
|
+
*/
|
|
24
|
+
export const runtimeOptions = z
|
|
25
|
+
.object({
|
|
26
|
+
/** `--gpus all` or `--gpus <n>` (needs the NVIDIA container toolkit on the host). */
|
|
27
|
+
gpus: z.union([z.literal('all'), z.number().int().min(1).max(16)]).nullable().optional(),
|
|
28
|
+
/** `--shm-size` in MiB; browsers and PyTorch data loaders outgrow Docker's 64. */
|
|
29
|
+
shmSizeMb: z.number().int().min(1).max(65_536).nullable().optional(),
|
|
30
|
+
/** `--init`: reaps zombie processes and forwards signals to the app. */
|
|
31
|
+
init: z.boolean().optional(),
|
|
32
|
+
/** `--ulimit nofile=N:N`. */
|
|
33
|
+
ulimitNofile: z.number().int().min(1024).max(1_048_576).nullable().optional(),
|
|
34
|
+
/** `--cap-add`. */
|
|
35
|
+
capAdd: z.array(runtimeCapability).max(7).optional(),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
/**
|
|
39
|
+
* 0.16.1: the most host ports one service may publish through `portMappings`.
|
|
40
|
+
* Docker starts one userland proxy process per published port and protocol,
|
|
41
|
+
* so a 10 000-port range costs 10 000 processes on the host.
|
|
42
|
+
*/
|
|
43
|
+
export const MAX_MAPPED_PORTS = 1000;
|
|
44
|
+
/** Most port-mapping rules per service. */
|
|
45
|
+
export const MAX_PORT_MAPPINGS = 20;
|
|
46
|
+
const IPV4 = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/;
|
|
47
|
+
/**
|
|
48
|
+
* A literal IPv4 or IPv6 address a port can be bound to (no zone, no CIDR).
|
|
49
|
+
* The unspecified addresses are refused: an empty IP already means "every
|
|
50
|
+
* address", and two spellings of it would dodge the overlap check.
|
|
51
|
+
*/
|
|
52
|
+
export function isBindableIp(ip) {
|
|
53
|
+
if (IPV4.test(ip))
|
|
54
|
+
return ip !== '0.0.0.0';
|
|
55
|
+
if (ip.length > 45)
|
|
56
|
+
return false;
|
|
57
|
+
const halves = ip.split('::');
|
|
58
|
+
if (halves.length > 2)
|
|
59
|
+
return false;
|
|
60
|
+
const groups = halves.flatMap((h) => (h === '' ? [] : h.split(':')));
|
|
61
|
+
let width = groups.length;
|
|
62
|
+
if (groups.length > 0 && IPV4.test(groups[groups.length - 1])) {
|
|
63
|
+
groups.pop();
|
|
64
|
+
width += 1; // an embedded IPv4 fills two groups
|
|
65
|
+
}
|
|
66
|
+
if (!groups.every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g)))
|
|
67
|
+
return false;
|
|
68
|
+
if (halves.length === 2 ? width > 7 : width !== 8)
|
|
69
|
+
return false;
|
|
70
|
+
// `::`, `0::0`, `0:0:0:0:0:0:0:0`: the unspecified address.
|
|
71
|
+
return width !== groups.length || groups.some((g) => Number.parseInt(g, 16) !== 0);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 0.16.1 extra host-port mappings of a docker service: one port or a range,
|
|
75
|
+
* TCP or UDP, on every host address or one dedicated IP
|
|
76
|
+
* (`docker run -p 203.0.113.7:27015-27030:27015-27030/udp`). The container
|
|
77
|
+
* range starts at `containerPort` and is as long as the host range.
|
|
78
|
+
*/
|
|
79
|
+
export const portMapping = z
|
|
80
|
+
.object({
|
|
81
|
+
/** Host address to bind; null or omitted = every address of the host. */
|
|
82
|
+
hostIp: z
|
|
83
|
+
.string()
|
|
84
|
+
.max(45)
|
|
85
|
+
.refine(isBindableIp, 'hostIp must be one IPv4 or IPv6 address of the host (leave it empty for every address)')
|
|
86
|
+
.nullable()
|
|
87
|
+
.optional(),
|
|
88
|
+
hostPort: z.number().int().min(1).max(65535),
|
|
89
|
+
/** Last host port of a range; null or omitted = the single `hostPort`. */
|
|
90
|
+
hostPortEnd: z.number().int().min(1).max(65535).nullable().optional(),
|
|
91
|
+
containerPort: z.number().int().min(1).max(65535),
|
|
92
|
+
protocol: z.enum(['tcp', 'udp']).default('tcp'),
|
|
93
|
+
/**
|
|
94
|
+
* TCP, one port: only these addresses or CIDR ranges may connect. The port
|
|
95
|
+
* is then published by a small Traefik proxy in front of the service
|
|
96
|
+
* instead of Docker's `-p`, which a host firewall cannot restrict.
|
|
97
|
+
*/
|
|
98
|
+
allowFrom: z.array(z.string().trim().min(1).max(64)).min(1).max(100).nullable().optional(),
|
|
99
|
+
})
|
|
100
|
+
.strict();
|
|
101
|
+
/** How many host ports a mapping publishes. */
|
|
102
|
+
export const mappedPortCount = (m) => Math.max(1, (m.hostPortEnd ?? m.hostPort) - m.hostPort + 1);
|
|
103
|
+
/**
|
|
104
|
+
* Whether two mappings would bind the same host socket: same protocol,
|
|
105
|
+
* overlapping ports, and the same IP (or either on every address).
|
|
106
|
+
*/
|
|
107
|
+
export function portMappingsOverlap(a, b) {
|
|
108
|
+
if ((a.protocol ?? 'tcp') !== (b.protocol ?? 'tcp'))
|
|
109
|
+
return false;
|
|
110
|
+
if (a.hostIp && b.hostIp && a.hostIp.toLowerCase() !== b.hostIp.toLowerCase())
|
|
111
|
+
return false;
|
|
112
|
+
return a.hostPort <= (b.hostPortEnd ?? b.hostPort) && b.hostPort <= (a.hostPortEnd ?? a.hostPort);
|
|
113
|
+
}
|
|
114
|
+
/** Why a list of mappings cannot be published, or null. Shared by the server, the panel and the CLI. */
|
|
115
|
+
export function portMappingsProblem(list) {
|
|
116
|
+
let total = 0;
|
|
117
|
+
for (const [i, m] of list.entries()) {
|
|
118
|
+
const end = m.hostPortEnd ?? m.hostPort;
|
|
119
|
+
const label = formatPortMapping(m);
|
|
120
|
+
if (end < m.hostPort)
|
|
121
|
+
return `Mapping ${i + 1} (${label}): the range ends before it starts.`;
|
|
122
|
+
if (m.containerPort + (end - m.hostPort) > 65535)
|
|
123
|
+
return `Mapping ${i + 1} (${label}): the container range runs past 65535.`;
|
|
124
|
+
total += end - m.hostPort + 1;
|
|
125
|
+
if (m.allowFrom?.length && ((m.protocol ?? 'tcp') !== 'tcp' || end !== m.hostPort)) {
|
|
126
|
+
return `Mapping ${i + 1} (${label}): an allow list works on one TCP port (UDP and ranges cannot be filtered by source).`;
|
|
127
|
+
}
|
|
128
|
+
const other = list.slice(0, i).find((o) => portMappingsOverlap(o, m));
|
|
129
|
+
if (other) {
|
|
130
|
+
return `Mapping ${i + 1} (${label}) overlaps ${formatPortMapping(other)}: a host port can be published once per address and protocol.`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (total > MAX_MAPPED_PORTS) {
|
|
134
|
+
return `${total} host ports requested; at most ${MAX_MAPPED_PORTS} per service (Docker runs one proxy process per published port).`;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/** The `docker run -p` operand: `27015-27030:27015-27030/udp`, `203.0.113.7:53:53/udp`, `[2001:db8::7]:53:53/udp`. */
|
|
139
|
+
export function formatPortMapping(m) {
|
|
140
|
+
const span = (m.hostPortEnd ?? m.hostPort) - m.hostPort;
|
|
141
|
+
const range = (start) => (span > 0 ? `${start}-${start + span}` : String(start));
|
|
142
|
+
const ip = m.hostIp ? (m.hostIp.includes(':') ? `[${m.hostIp}]:` : `${m.hostIp}:`) : '';
|
|
143
|
+
return `${ip}${range(m.hostPort)}:${range(m.containerPort)}/${m.protocol ?? 'tcp'}`;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Parse `27015-27030:27015/udp`, `8080:80`, `5432@10.0.0.0/8`, `53/udp`, `10000-10100/udp`
|
|
147
|
+
* (no colon = the same ports inside the container), optionally after an IP:
|
|
148
|
+
* `203.0.113.7:53/udp`, `[2001:db8::7]:8080:80`. A container range must be as
|
|
149
|
+
* long as the host range. Returns the mapping, or why the text is not one.
|
|
150
|
+
*/
|
|
151
|
+
export function parsePortMapping(text) {
|
|
152
|
+
// `…@10.0.0.0/8,203.0.113.4`: the allow list of a TCP port.
|
|
153
|
+
const parts = text.trim().split('@');
|
|
154
|
+
const t = parts[0];
|
|
155
|
+
const allowText = parts[1];
|
|
156
|
+
if (parts.length > 2)
|
|
157
|
+
return `"${text.trim()}" has more than one @.`;
|
|
158
|
+
const allowFrom = allowText === undefined ? null : allowText.split(',').map((e) => e.trim()).filter(Boolean);
|
|
159
|
+
if (allowFrom && allowFrom.length === 0)
|
|
160
|
+
return `"${text.trim()}": list the addresses after @ (10.0.0.0/8,203.0.113.4).`;
|
|
161
|
+
const m = /^(?:(\d{1,3}(?:\.\d{1,3}){3})|\[([0-9A-Fa-f:.]+)\]):(\d{1,5})(?:-(\d{1,5}))?(?::(\d{1,5})(?:-(\d{1,5}))?)?(?:\/(tcp|udp))?$/i.exec(t)
|
|
162
|
+
?? /^()()(\d{1,5})(?:-(\d{1,5}))?(?::(\d{1,5})(?:-(\d{1,5}))?)?(?:\/(tcp|udp))?$/i.exec(t);
|
|
163
|
+
if (!m)
|
|
164
|
+
return `"${t}" is not a port mapping (examples: 8080:80, 27015-27030:27015/udp, 203.0.113.7:53/udp).`;
|
|
165
|
+
const hostIp = m[1] || m[2] || null;
|
|
166
|
+
if (hostIp && !isBindableIp(hostIp))
|
|
167
|
+
return `"${t}": ${hostIp} is not an address a port can be bound to.`;
|
|
168
|
+
const hostPort = Number(m[3]);
|
|
169
|
+
const hostPortEnd = m[4] ? Number(m[4]) : null;
|
|
170
|
+
const containerPort = m[5] ? Number(m[5]) : hostPort;
|
|
171
|
+
const ports = [hostPort, hostPortEnd ?? hostPort, containerPort];
|
|
172
|
+
if (ports.some((p) => p < 1 || p > 65535))
|
|
173
|
+
return `"${t}": ports run from 1 to 65535.`;
|
|
174
|
+
if (hostPortEnd !== null && hostPortEnd < hostPort)
|
|
175
|
+
return `"${t}": the range ends before it starts.`;
|
|
176
|
+
if (m[6] && Number(m[6]) - containerPort !== (hostPortEnd ?? hostPort) - hostPort) {
|
|
177
|
+
return `"${t}": the container range must be as long as the host range.`;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
hostIp,
|
|
181
|
+
hostPort,
|
|
182
|
+
hostPortEnd: hostPortEnd !== null && hostPortEnd !== hostPort ? hostPortEnd : null,
|
|
183
|
+
containerPort,
|
|
184
|
+
protocol: (m[7]?.toLowerCase() ?? 'tcp'),
|
|
185
|
+
...(allowFrom ? { allowFrom } : {}),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/** The PATCH field: rules checked together (ranges, overlaps, the port budget). */
|
|
189
|
+
export const portMappings = z
|
|
190
|
+
.array(portMapping)
|
|
191
|
+
.max(MAX_PORT_MAPPINGS)
|
|
192
|
+
.superRefine((list, ctx) => {
|
|
193
|
+
const problem = portMappingsProblem(list);
|
|
194
|
+
if (problem)
|
|
195
|
+
ctx.addIssue({ code: 'custom', message: problem });
|
|
196
|
+
});
|
|
197
|
+
/**
|
|
198
|
+
* 0.16.1 deploy healthcheck: `http` probes the container port (an HTTP answer
|
|
199
|
+
* below 500, then a TCP connect); `running` only waits for the container to
|
|
200
|
+
* stay up, for services with no HTTP or TCP port to probe (UDP game servers,
|
|
201
|
+
* VoIP, queue workers).
|
|
202
|
+
*/
|
|
203
|
+
export const healthCheckMode = z.enum(['http', 'running']);
|
|
5
204
|
/** Optional project/workspace/label tag IDs for new service creation. */
|
|
6
205
|
const tagIds = z.array(z.number().int().positive()).optional();
|
|
7
206
|
export const createService = z.object({
|
|
@@ -71,6 +270,8 @@ export const createService = z.object({
|
|
|
71
270
|
restartPolicy: z.string().regex(/^(no|always|unless-stopped|on-failure(?::\d{1,3})?)$/).optional(),
|
|
72
271
|
// Seconds between SIGTERM and SIGKILL on stop (docker stop -t).
|
|
73
272
|
stopGraceSeconds: z.number().int().min(0).max(300).optional(),
|
|
273
|
+
/** Env-var names passed to a Dockerfile build as `--build-arg`. */
|
|
274
|
+
buildArgs: buildArgNames.optional(),
|
|
74
275
|
})
|
|
75
276
|
.default({ buildPack: 'auto', baseDir: '/' }),
|
|
76
277
|
}).superRefine((value, ctx) => {
|
|
@@ -101,12 +302,10 @@ export const createService = z.object({
|
|
|
101
302
|
* still applies `.default()` values for absent keys, which would silently
|
|
102
303
|
* rewrite `type` back to 'docker' and `branch` to 'main' on every PATCH. */
|
|
103
304
|
export const updateService = z.object({
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
tagWorkspaceIds: tagIds,
|
|
109
|
-
tagLabelIds: tagIds,
|
|
305
|
+
// r335: no tag fields. Tags change only through `PUT /v1/services/:id/tags`
|
|
306
|
+
// (admin-gated, with the r156 foreign-link rules). The PATCH route used to
|
|
307
|
+
// accept tagProjectIds/tagWorkspaceIds/tagLabelIds here and then silently
|
|
308
|
+
// drop them; it now answers 400 `tags_via_put` when a body carries them.
|
|
110
309
|
name: z.string().min(1).max(100).optional(),
|
|
111
310
|
slug: slug.optional(),
|
|
112
311
|
type: serviceType.optional(),
|
|
@@ -132,8 +331,16 @@ export const updateService = z.object({
|
|
|
132
331
|
/** Horizontal replica count for docker services (Traefik load-balances). */
|
|
133
332
|
replicas: z.number().int().min(1).max(10).optional(),
|
|
134
333
|
healthPath: httpPath.optional(),
|
|
334
|
+
/** Seconds a deploy waits for the healthcheck (10–3600); null restores the 300 s default. */
|
|
335
|
+
healthTimeoutSeconds: z.number().int().min(10).max(3600).nullable().optional(),
|
|
336
|
+
/** 'running' = the deploy only waits for the container to stay up (UDP and other non-HTTP services); 'http' or null = the HTTP/TCP probe. */
|
|
337
|
+
healthCheck: healthCheckMode.nullable().optional(),
|
|
338
|
+
/** Operator only: advanced container options; null clears them all. */
|
|
339
|
+
runtimeOptions: runtimeOptions.nullable().optional(),
|
|
135
340
|
port: z.number().int().min(1).max(65535).optional(),
|
|
136
341
|
publishedPort: z.number().int().min(1).max(65535).nullable().optional(),
|
|
342
|
+
/** Extra host ports, TCP or UDP, single or ranges (docker services on the panel host); null or [] clears them. */
|
|
343
|
+
portMappings: portMappings.nullable().optional(),
|
|
137
344
|
previewDeploymentsEnabled: z.boolean().optional(),
|
|
138
345
|
previewAutoDestroyOnClose: z.boolean().optional(),
|
|
139
346
|
previewDomainPattern: z.string().nullable().optional(),
|
|
@@ -157,6 +364,8 @@ export const updateService = z.object({
|
|
|
157
364
|
preStopCmd: z.string().nullable().optional(),
|
|
158
365
|
restartPolicy: z.string().regex(/^(no|always|unless-stopped|on-failure(?::\d{1,3})?)$/).optional(),
|
|
159
366
|
stopGraceSeconds: z.number().int().min(0).max(300).optional(),
|
|
367
|
+
/** Env-var names passed to a Dockerfile build as `--build-arg`; [] clears. */
|
|
368
|
+
buildArgs: buildArgNames.optional(),
|
|
160
369
|
})
|
|
161
370
|
.optional(),
|
|
162
371
|
});
|
|
@@ -201,9 +410,17 @@ export const service = z.object({
|
|
|
201
410
|
commitSha: z.string().nullable(),
|
|
202
411
|
runtimeId: z.string().nullable(),
|
|
203
412
|
healthPath: z.string(),
|
|
413
|
+
/** Healthcheck deadline in seconds; null = the 300 s default (0.16.1). */
|
|
414
|
+
healthTimeoutSeconds: z.number().int().nullable().optional(),
|
|
415
|
+
/** How a deploy decides the new container is ready (0.16.1). */
|
|
416
|
+
healthCheck: healthCheckMode.optional(),
|
|
417
|
+
/** Advanced container options (0.16.1); null = none. */
|
|
418
|
+
runtimeOptions: runtimeOptions.nullable().optional(),
|
|
204
419
|
autoUrl: z.string().nullable(),
|
|
205
420
|
port: z.number().int().nullable(),
|
|
206
421
|
publishedPort: z.number().int().nullable().optional(),
|
|
422
|
+
/** Extra host-port mappings, TCP or UDP (0.16.1); [] = none. */
|
|
423
|
+
portMappings: z.array(portMapping).optional(),
|
|
207
424
|
cpuShares: z.number().int(),
|
|
208
425
|
cpuLimitMilli: z.number().int(),
|
|
209
426
|
memLimitMb: z.number().int(),
|
|
@@ -234,12 +451,19 @@ export const service = z.object({
|
|
|
234
451
|
preStopCmd: z.string().nullable().optional(),
|
|
235
452
|
restartPolicy: z.string(),
|
|
236
453
|
stopGraceSeconds: z.number().int(),
|
|
454
|
+
/** Env-var names a Dockerfile build receives as `--build-arg` (0.16.1). */
|
|
455
|
+
buildArgs: z.array(z.string()).optional(),
|
|
237
456
|
})
|
|
238
457
|
.nullable(),
|
|
239
458
|
createdAt: z.string().datetime(),
|
|
240
459
|
updatedAt: z.string().datetime(),
|
|
241
460
|
});
|
|
242
461
|
// ── Sources (private repo credentials) ─────────────────────────────────────
|
|
462
|
+
/** r512: a registry host a `registry` credential may be sent to (`ghcr.io`, `registry.local:5000`). */
|
|
463
|
+
export const registryHost = z
|
|
464
|
+
.string()
|
|
465
|
+
.max(255)
|
|
466
|
+
.regex(/^[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?(:\d{1,5})?$/, 'Expected a registry host such as ghcr.io or registry.local:5000');
|
|
243
467
|
export const createSource = z.object({
|
|
244
468
|
name: z.string().min(1).max(100),
|
|
245
469
|
type: z.enum(['github', 'gitlab', 'gitea', 'bitbucket', 'custom', 'registry']),
|
|
@@ -247,7 +471,15 @@ export const createSource = z.object({
|
|
|
247
471
|
deployKey: z.string().optional(),
|
|
248
472
|
// Registry-type sources: username for `docker login` (token = password).
|
|
249
473
|
registryUsername: z.string().max(255).optional(),
|
|
474
|
+
/** r512: registry hosts this credential may be sent to (Docker Hub = docker.io). */
|
|
475
|
+
registryHosts: z.array(registryHost).max(20).optional(),
|
|
250
476
|
defaultBranch: z.string().optional(),
|
|
477
|
+
/**
|
|
478
|
+
* 0.13: self-hosted provider base (Gitea), e.g. `https://git.example.com`.
|
|
479
|
+
* The server refuses `http:` unless private egress is allowed.
|
|
480
|
+
* `github_app` is deliberately NOT in `type`: only installation sync creates those sources.
|
|
481
|
+
*/
|
|
482
|
+
baseUrl: providerBaseUrl.optional(),
|
|
251
483
|
});
|
|
252
484
|
export const source = z.object({
|
|
253
485
|
id: z.number().int(),
|
|
@@ -256,11 +488,29 @@ export const source = z.object({
|
|
|
256
488
|
hasToken: z.boolean(),
|
|
257
489
|
hasDeployKey: z.boolean(),
|
|
258
490
|
registryUsername: z.string().nullable().optional(),
|
|
491
|
+
/** r512: hosts a registry credential is bound to (registry sources only). */
|
|
492
|
+
registryHosts: z.array(z.string()).optional(),
|
|
259
493
|
defaultBranch: z.string().nullable(),
|
|
494
|
+
/** 0.13: self-hosted provider base URL (Gitea); null/absent = not set. */
|
|
495
|
+
baseUrl: z.string().nullable().optional(),
|
|
496
|
+
// ── 0.16 T8 surfaces ── multi-node (0.15.2, additive): this PAT or deploy key
|
|
497
|
+
// may be sent to a node for one clone. Absent on older panels.
|
|
498
|
+
allowOnNodes: z.boolean().optional(),
|
|
499
|
+
// ── end 0.16 T8 ──
|
|
500
|
+
/** 0.15.8: the panel pins this source's git host SSH keys (absent on older panels). */
|
|
501
|
+
pinHostKeys: z.boolean().optional(),
|
|
502
|
+
/** 0.15.8: what the pin holds, as fingerprints only. */
|
|
503
|
+
pinnedHostKeys: z.array(z.object({ host: z.string(), type: z.string(), fingerprint: z.string().nullable() })).optional(),
|
|
260
504
|
createdAt: z.string().datetime(),
|
|
261
505
|
updatedAt: z.string().datetime().optional(),
|
|
262
506
|
});
|
|
263
507
|
export const triggerDeploy = z.object({
|
|
508
|
+
/**
|
|
509
|
+
* @deprecated r334: IGNORED by `POST /v1/services/:id/deploys` — a manual
|
|
510
|
+
* trigger always builds the configured branch head. Pinning a commit here
|
|
511
|
+
* was never wired (the route reads no body). To redeploy an exact commit,
|
|
512
|
+
* use `deploys.promote` (another lane's running SHA) or `deploys.rollback`.
|
|
513
|
+
*/
|
|
264
514
|
commitSha: z.string().optional(),
|
|
265
515
|
});
|
|
266
516
|
export const deployment = z.object({
|
|
@@ -308,7 +558,9 @@ export const queueResponse = z.object({
|
|
|
308
558
|
// ── Domains (Traefik routing) ─────────────────────────────────────────────
|
|
309
559
|
export const createDomain = z.object({
|
|
310
560
|
hostname: z.string().min(3).max(253),
|
|
311
|
-
|
|
561
|
+
// r473: aligned with the manifest's route.path rule — the consumer strips
|
|
562
|
+
// it downstream anyway, but the boundary should not depend on that.
|
|
563
|
+
path: z.string().min(1).max(200).regex(/^\/.*$/).default('/'),
|
|
312
564
|
// Default matches the DB column default and the CLI (`ssl !== false`):
|
|
313
565
|
// HTTPS everywhere unless explicitly disabled.
|
|
314
566
|
ssl: z.boolean().default(true),
|
|
@@ -324,6 +576,41 @@ export const createDomain = z.object({
|
|
|
324
576
|
/** Rate limit: burst peak requests allowed. */
|
|
325
577
|
rateLimitBurst: z.number().int().min(0).max(100000).optional().nullable(),
|
|
326
578
|
});
|
|
579
|
+
/**
|
|
580
|
+
* Why a redirect regex cannot go to Traefik, or null. Traefik compiles it
|
|
581
|
+
* with Go's RE2, which has no lookaround and no backreferences — and a regex
|
|
582
|
+
* Traefik refuses takes the whole dynamic config file down with it, so these
|
|
583
|
+
* are refused when saved. The rest is checked by compiling it here.
|
|
584
|
+
*/
|
|
585
|
+
export function redirectRegexProblem(regex) {
|
|
586
|
+
if (/\(\?<?[=!]/.test(regex))
|
|
587
|
+
return 'lookahead / lookbehind are not supported (Traefik uses Go RE2)';
|
|
588
|
+
if (/\\[1-9]/.test(regex))
|
|
589
|
+
return 'backreferences such as \\1 are not supported (Traefik uses Go RE2)';
|
|
590
|
+
try {
|
|
591
|
+
new RegExp(regex);
|
|
592
|
+
}
|
|
593
|
+
catch (err) {
|
|
594
|
+
// RegExp only ever throws a SyntaxError here.
|
|
595
|
+
return `not a valid regular expression (${err.message})`;
|
|
596
|
+
}
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
/** 0.16.1 one redirect rule of a domain (Dokploy's "Redirects"): Traefik `redirectRegex`. */
|
|
600
|
+
export const redirectRule = z
|
|
601
|
+
.object({
|
|
602
|
+
/** Matched against the full request URL, e.g. `^https://example.com/old/(.*)`. */
|
|
603
|
+
regex: z.string().min(1).max(1000),
|
|
604
|
+
/** The target; `${1}` inserts the first capture group. */
|
|
605
|
+
replacement: z.string().min(1).max(2000).regex(/^[^\r\n]*$/, 'one line'),
|
|
606
|
+
/** 301/308 when true, 302/307 when false. */
|
|
607
|
+
permanent: z.boolean().default(false),
|
|
608
|
+
})
|
|
609
|
+
.superRefine((r, ctx) => {
|
|
610
|
+
const problem = redirectRegexProblem(r.regex);
|
|
611
|
+
if (problem)
|
|
612
|
+
ctx.addIssue({ code: 'custom', path: ['regex'], message: problem });
|
|
613
|
+
});
|
|
327
614
|
/** PATCHable routing extras for an existing domain. */
|
|
328
615
|
export const domainPatch = z.object({
|
|
329
616
|
ssl: z.boolean().optional(),
|
|
@@ -333,6 +620,8 @@ export const domainPatch = z.object({
|
|
|
333
620
|
ipAllowlist: z.string().max(4000).optional().nullable(),
|
|
334
621
|
rateLimitAverage: z.number().int().min(0).max(100000).optional().nullable(),
|
|
335
622
|
rateLimitBurst: z.number().int().min(0).max(100000).optional().nullable(),
|
|
623
|
+
/** 0.16.1: redirect rules, applied in order; null or [] removes them. */
|
|
624
|
+
redirects: z.array(redirectRule).max(10).optional().nullable(),
|
|
336
625
|
});
|
|
337
626
|
export const domain = z.object({
|
|
338
627
|
id: z.number().int(),
|
|
@@ -346,19 +635,17 @@ export const domain = z.object({
|
|
|
346
635
|
ipAllowlist: z.string().nullable().optional(),
|
|
347
636
|
rateLimitAverage: z.number().nullable().optional(),
|
|
348
637
|
rateLimitBurst: z.number().nullable().optional(),
|
|
638
|
+
/** 0.16.1 redirect rules (absent on older panels). */
|
|
639
|
+
redirects: z.array(z.object({ regex: z.string(), replacement: z.string(), permanent: z.boolean() })).optional(),
|
|
349
640
|
status: z.string(),
|
|
350
641
|
createdAt: z.string().datetime(),
|
|
351
642
|
updatedAt: z.string().datetime(),
|
|
352
643
|
});
|
|
353
644
|
// ── Webhooks (auto-deploy) ────────────────────────────────────────────────
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const patterns = raw.split(/[\n,]/).map((pattern) => pattern.trim()).filter(Boolean);
|
|
359
|
-
return patterns.length <= 32 && patterns.every((pattern) => pattern.length <= 256 && (pattern.match(/\*\*/g) ?? []).length <= 4 && (pattern.match(/[?*]/g) ?? []).length <= 16);
|
|
360
|
-
}, 'watchPaths contains an unsafe glob pattern').optional(),
|
|
361
|
-
});
|
|
645
|
+
// Webhook CREATION is validated by `webhookCreate` in management.ts (the
|
|
646
|
+
// route's schema). The former duplicate here (r473: `createWebhook`) was used
|
|
647
|
+
// by no route and had drifted from the live one — removed rather than left
|
|
648
|
+
// as a trap for someone "hardening" the wrong twin.
|
|
362
649
|
export const webhook = z.object({
|
|
363
650
|
id: z.number().int(),
|
|
364
651
|
branch: z.string(),
|
|
@@ -368,12 +655,16 @@ export const webhook = z.object({
|
|
|
368
655
|
url: z.string(),
|
|
369
656
|
createdAt: z.string().datetime(),
|
|
370
657
|
});
|
|
371
|
-
/**
|
|
372
|
-
|
|
658
|
+
/**
|
|
659
|
+
* Returned once at creation time — the secret is never retrievable again.
|
|
660
|
+
* r334: the create route answers id/branch/active/sourceId/url/secret only;
|
|
661
|
+
* `watchPaths` and `createdAt` come from `webhooks.list`.
|
|
662
|
+
*/
|
|
663
|
+
export const createdWebhook = webhook.omit({ watchPaths: true, createdAt: true }).extend({ secret: z.string() });
|
|
373
664
|
// ── Managed databases ─────────────────────────────────────────────────────
|
|
374
665
|
export const createDatabase = z.object({
|
|
375
666
|
name: z.string().min(1).max(100),
|
|
376
|
-
engine: z.enum(['postgres', 'mysql', 'mariadb', 'redis', 'mongo', 'valkey', 'clickhouse', 'meilisearch', 'rabbitmq']),
|
|
667
|
+
engine: z.enum(['postgres', 'mysql', 'mariadb', 'redis', 'mongo', 'valkey', 'clickhouse', 'meilisearch', 'rabbitmq', 'keydb', 'dragonfly']),
|
|
377
668
|
version: z.string().optional(),
|
|
378
669
|
projectId: z.number().int().optional(),
|
|
379
670
|
/** Hub/template provisioning is retryable: resume a matching database owned
|
|
@@ -382,11 +673,12 @@ export const createDatabase = z.object({
|
|
|
382
673
|
existingVolume: z.string().optional(),
|
|
383
674
|
extensions: z.array(z.string()).optional(),
|
|
384
675
|
webGuiEnabled: z.boolean().optional(),
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
676
|
+
/**
|
|
677
|
+
* Multi-node (additive): the node to run the database on. null or absent =
|
|
678
|
+
* the panel host (today). Operator only when non-null; placement is fixed
|
|
679
|
+
* at create time.
|
|
680
|
+
*/
|
|
681
|
+
serverId: z.number().int().positive().nullable().optional(),
|
|
390
682
|
});
|
|
391
683
|
export const managedDatabase = z.object({
|
|
392
684
|
id: z.number().int(),
|
|
@@ -405,6 +697,14 @@ export const managedDatabase = z.object({
|
|
|
405
697
|
webGuiPort: z.number().int().nullable().optional(),
|
|
406
698
|
extensions: z.array(z.string()).optional().default([]),
|
|
407
699
|
attachedServices: z.array(z.object({ id: z.number().int(), name: z.string(), slug: z.string() })).optional().default([]),
|
|
700
|
+
// ── 0.16 T8 surfaces: the node fields the 0.15.3 routes return (additive) ──
|
|
701
|
+
/** The node the database runs on; null = the panel host. Absent before 0.15.3. */
|
|
702
|
+
serverId: z.number().int().nullable().optional(),
|
|
703
|
+
/** That node's name; null for a panel-host database. */
|
|
704
|
+
serverName: z.string().nullable().optional(),
|
|
705
|
+
/** The node's last reachability probe; null for a panel-host database or a node not probed yet. */
|
|
706
|
+
reachable: z.boolean().nullable().optional(),
|
|
707
|
+
// ── end 0.16 T8 ──
|
|
408
708
|
createdAt: z.string().datetime(),
|
|
409
709
|
updatedAt: z.string().datetime(),
|
|
410
710
|
});
|
|
@@ -425,7 +725,9 @@ export const attachment = z.object({
|
|
|
425
725
|
// ── Environment variables ──────────────────────────────────────────────────
|
|
426
726
|
export const upsertEnvVar = z.object({
|
|
427
727
|
key: envVarName.max(100),
|
|
428
|
-
|
|
728
|
+
// r473: same 32 KB cap the Hub deployTemplate path applies — the sink
|
|
729
|
+
// escapes newlines either way, but the twins should not disagree.
|
|
730
|
+
value: z.string().max(32 * 1024),
|
|
429
731
|
isSecret: z.boolean().optional(),
|
|
430
732
|
overwriteExisting: z.boolean().optional(),
|
|
431
733
|
});
|
|
@@ -770,7 +1072,10 @@ export const volumeFileWrite = z.object({
|
|
|
770
1072
|
/** Relative path inside the volume. */
|
|
771
1073
|
path: z.string().min(1).max(1024),
|
|
772
1074
|
/** Base64-encoded file content (schemas validate; argv never sees it). */
|
|
773
|
-
contentBase64: z.string().max(8 * 1024 * 1024)
|
|
1075
|
+
contentBase64: z.string().max(8 * 1024 * 1024).refine((value) => {
|
|
1076
|
+
const compact = value.replace(/\s/g, '');
|
|
1077
|
+
return compact.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(compact);
|
|
1078
|
+
}, { message: 'must be valid base64 content' }),
|
|
774
1079
|
});
|
|
775
1080
|
export const volumePathCreate = z.object({
|
|
776
1081
|
path: z.string().min(1).max(1024),
|