@ninedeploy/sdk 0.18.2 → 0.18.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.
Files changed (54) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/resources/auth.d.ts +20 -1
  4. package/dist/resources/auth.d.ts.map +1 -1
  5. package/dist/resources/auth.js +9 -0
  6. package/dist/resources/auth.js.map +1 -1
  7. package/dist/resources/databases.d.ts +6 -1
  8. package/dist/resources/databases.d.ts.map +1 -1
  9. package/dist/resources/databases.js +4 -0
  10. package/dist/resources/databases.js.map +1 -1
  11. package/dist/resources/deploys.d.ts +49 -1
  12. package/dist/resources/deploys.d.ts.map +1 -1
  13. package/dist/resources/deploys.js +12 -0
  14. package/dist/resources/deploys.js.map +1 -1
  15. package/dist/resources/domains.d.ts +16 -1
  16. package/dist/resources/domains.d.ts.map +1 -1
  17. package/dist/resources/domains.js +9 -0
  18. package/dist/resources/domains.js.map +1 -1
  19. package/dist/resources/servers.d.ts +49 -1
  20. package/dist/resources/servers.d.ts.map +1 -1
  21. package/dist/resources/servers.js +26 -0
  22. package/dist/resources/servers.js.map +1 -1
  23. package/dist/resources/services.d.ts +85 -13
  24. package/dist/resources/services.d.ts.map +1 -1
  25. package/dist/resources/services.js +50 -0
  26. package/dist/resources/services.js.map +1 -1
  27. package/dist/resources/settings.d.ts +47 -2
  28. package/dist/resources/settings.d.ts.map +1 -1
  29. package/dist/resources/settings.js +6 -0
  30. package/dist/resources/settings.js.map +1 -1
  31. package/dist/resources/sources.d.ts +6 -1
  32. package/dist/resources/sources.d.ts.map +1 -1
  33. package/dist/resources/sources.js +5 -0
  34. package/dist/resources/sources.js.map +1 -1
  35. package/dist/resources/system.d.ts +20 -1
  36. package/dist/resources/system.d.ts.map +1 -1
  37. package/dist/resources/system.js +8 -0
  38. package/dist/resources/system.js.map +1 -1
  39. package/dist/resources/traefik.d.ts +9 -0
  40. package/dist/resources/traefik.d.ts.map +1 -1
  41. package/dist/resources/traefik.js +4 -0
  42. package/dist/resources/traefik.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/index.ts +2 -2
  45. package/src/resources/auth.ts +25 -0
  46. package/src/resources/databases.ts +11 -0
  47. package/src/resources/deploys.ts +50 -2
  48. package/src/resources/domains.ts +30 -0
  49. package/src/resources/servers.ts +80 -0
  50. package/src/resources/services.ts +155 -6
  51. package/src/resources/settings.ts +45 -1
  52. package/src/resources/sources.ts +12 -0
  53. package/src/resources/system.ts +24 -0
  54. package/src/resources/traefik.ts +9 -0
@@ -4,6 +4,12 @@
4
4
  import type {
5
5
  Attachment,
6
6
  AutoscaleStatusView,
7
+ SizingReport,
8
+ RestartLimitConfig,
9
+ RestartLimitView,
10
+ PendingChangesView,
11
+ PendingApplyInput,
12
+ PendingApplyResult,
7
13
  ComposePreviewRequestInput,
8
14
  ComposePreviewResponse,
9
15
  CreateProjectInput,
@@ -15,6 +21,7 @@ import type {
15
21
  EnvironmentCreateInput,
16
22
  EnvironmentPatchInput,
17
23
  PrimaryRecoveryEntry,
24
+ ServiceRoutingView,
18
25
  PrimaryRecoveryResult,
19
26
  SwarmRecoveryEntry,
20
27
  SwarmRecoveryResult,
@@ -38,12 +45,34 @@ import type {
38
45
  ServiceFile,
39
46
  ServiceFileEntry,
40
47
  ServiceFilePut,
48
+ ServiceLifecycleResult,
49
+ ServiceLifecycleView,
50
+ ServiceLifecycleRetry,
51
+ ErrorPagesInput,
52
+ InlineDockerfileView,
53
+ ServiceMoveView,
54
+ ServiceCommitStatusView,
55
+ ErrorEventView,
56
+ ErrorIngestView,
57
+ ErrorIssueView,
58
+ ErrorPagesView,
59
+ MaintenanceInput,
60
+ MaintenanceView,
41
61
  } from '@ninedeploy/schemas';
42
62
  import { apiGetUrl } from '../apiPath.js';
43
63
  import type { ApplyManifestResult, ApplyManifestInput, ServiceDetail } from '../types.js';
44
64
  import type { Transport } from '../transport.js';
45
65
 
46
66
  /** 0.16.1: one kept upload of a service's source archive. */
67
+ /** G1.7: the registry push webhook of one service. `url` is set only in the answer that made it. */
68
+ export interface RegistryHookView {
69
+ enabled: boolean;
70
+ mine: boolean;
71
+ url: string | null;
72
+ createdAt: string | null;
73
+ lastPushAt: string | null;
74
+ }
75
+
47
76
  export interface SourceUpload {
48
77
  /** First 40 hex chars of the archive's SHA-256 (the deployment's `commitSha`). */
49
78
  sha: string;
@@ -71,9 +100,11 @@ export interface ServicesApi {
71
100
  */
72
101
  composePreview: (input: ComposePreviewRequestInput) => Promise<ComposePreviewResponse>;
73
102
  remove: (id: number) => Promise<void>;
74
- stop: (id: number) => Promise<{ ok: boolean; status: string }>;
75
- start: (id: number) => Promise<{ ok: boolean; status: string }>;
76
- restart: (id: number) => Promise<{ ok: boolean; status: string }>;
103
+ stop: (id: number) => Promise<ServiceLifecycleResult>;
104
+ start: (id: number) => Promise<ServiceLifecycleResult>;
105
+ restart: (id: number) => Promise<ServiceLifecycleResult>;
106
+ lifecycle: (id: number) => Promise<ServiceLifecycleView>;
107
+ retryLifecycle: (id: number) => Promise<ServiceLifecycleRetry>;
77
108
  /** The last `tail` runtime-log lines (default 300, at most 5000; 0.16.3). */
78
109
  logs: (id: number, opts?: { tail?: number }) => Promise<{ lines: string }>;
79
110
  clone: (id: number, input?: { name?: string; slug?: string }) => Promise<Service>;
@@ -181,11 +212,79 @@ export interface ServicesApi {
181
212
  * scaling event. The configuration itself is `autoscale` on the service
182
213
  * and is set with `update(id, { autoscale })` (`null` turns it off).
183
214
  */
215
+ /** Where the service's traffic goes now: domains through Traefik, host ports through Docker. */
216
+ routing: (id: number) => Promise<ServiceRoutingView>;
184
217
  runtimeRecovery: (id: number) => Promise<PrimaryRecoveryEntry | null>;
185
218
  retryRuntimeRecovery: (id: number) => Promise<PrimaryRecoveryResult>;
186
219
  swarmRecovery: (id: number) => Promise<SwarmRecoveryEntry | null>;
187
220
  retrySwarmRecovery: (id: number) => Promise<SwarmRecoveryResult>;
188
221
  autoscale: (id: number) => Promise<AutoscaleStatusView>;
222
+ /** G5.6: memory and CPU limit suggestions from the metric history (viewer; advisory). */
223
+ sizing: (id: number) => Promise<SizingReport>;
224
+ /** G2.2: maintenance mode (a config turns it on, null off) and custom 502/503/504 pages. */
225
+ maintenance: {
226
+ get: (id: number) => Promise<MaintenanceView>;
227
+ set: (id: number, maintenance: MaintenanceInput['maintenance']) => Promise<MaintenanceView>;
228
+ };
229
+ errorPages: {
230
+ get: (id: number) => Promise<ErrorPagesView>;
231
+ set: (id: number, pages: ErrorPagesInput['pages']) => Promise<ErrorPagesView>;
232
+ };
233
+ /** G1.1: a Dockerfile pasted in the panel (null builds from the repository again). */
234
+ /** G5.4: errors reported by Sentry SDKs, grouped into issues. */
235
+ errors: {
236
+ list: (id: number, status?: 'unresolved' | 'resolved' | 'ignored') => Promise<ErrorIssueView[]>;
237
+ get: (id: number, issueId: number) => Promise<{ issue: ErrorIssueView; events: ErrorEventView[] }>;
238
+ setStatus: (id: number, issueId: number, status: 'unresolved' | 'resolved' | 'ignored') => Promise<ErrorIssueView>;
239
+ /** The DSN: `create` answers it once and replaces any earlier one. */
240
+ ingest: {
241
+ get: (id: number) => Promise<ErrorIngestView>;
242
+ create: (id: number) => Promise<ErrorIngestView>;
243
+ remove: (id: number) => Promise<ErrorIngestView>;
244
+ };
245
+ };
246
+ /** G3.1: move a stopped docker service to another host with its data volume (operators). */
247
+ move: {
248
+ get: (id: number) => Promise<ServiceMoveView>;
249
+ /** `serverId` null = the panel host. Answers at once; follow it with `get`. */
250
+ start: (id: number, serverId: number | null) => Promise<ServiceMoveView>;
251
+ };
252
+ inlineDockerfile: {
253
+ get: (id: number) => Promise<InlineDockerfileView>;
254
+ set: (id: number, content: string | null) => Promise<InlineDockerfileView>;
255
+ };
256
+ /**
257
+ * G1.7 registry push webhook: a secret URL a registry (Docker Hub, GHCR,
258
+ * Harbor, registry:2) calls after a push; the service redeploys when the
259
+ * pushed tag is its image. The URL is returned once, by `enable`.
260
+ */
261
+ /** GitLab, Gitea and Bitbucket commit statuses (ROADMAP 0.16.8 item 8). */
262
+ commitStatus: {
263
+ get: (id: number) => Promise<ServiceCommitStatusView>;
264
+ set: (id: number, enabled: boolean) => Promise<ServiceCommitStatusView>;
265
+ };
266
+ registryHook: {
267
+ get: (id: number) => Promise<RegistryHookView>;
268
+ enable: (id: number) => Promise<RegistryHookView>;
269
+ disable: (id: number) => Promise<RegistryHookView>;
270
+ };
271
+ /** G1.3: stop the service when its containers keep restarting (opt-in; member to set). */
272
+ restartLimit: {
273
+ get: (id: number) => Promise<RestartLimitView>;
274
+ set: (id: number, limit: RestartLimitConfig | null) => Promise<RestartLimitView>;
275
+ };
276
+ /**
277
+ * G5.2 pending changes tray. With staging on, edits collect (`stage`, a
278
+ * PATCH body) instead of applying; `apply` sends them through
279
+ * `update` together, optionally with a deploy.
280
+ */
281
+ pending: {
282
+ get: (id: number) => Promise<PendingChangesView>;
283
+ stage: (id: number, patch: UpdateServiceInput) => Promise<PendingChangesView>;
284
+ setStaging: (id: number, staging: boolean) => Promise<PendingChangesView>;
285
+ discard: (id: number) => Promise<PendingChangesView>;
286
+ apply: (id: number, input?: PendingApplyInput) => Promise<PendingApplyResult>;
287
+ };
189
288
  // ── 0.16.11 scale to zero ──
190
289
  /**
191
290
  * Put a docker service to sleep now (`POST /v1/services/:id/sleep`,
@@ -270,9 +369,11 @@ export function servicesApi(t: Transport): ServicesApi {
270
369
  remove: async (id) => {
271
370
  await request(`/v1/services/${id}`, { method: 'DELETE' });
272
371
  },
273
- stop: (id) => send<{ ok: boolean; status: string }>('POST', `/v1/services/${id}/stop`),
274
- start: (id) => send<{ ok: boolean; status: string }>('POST', `/v1/services/${id}/start`),
275
- restart: (id) => send<{ ok: boolean; status: string }>('POST', `/v1/services/${id}/restart`),
372
+ stop: (id) => send<ServiceLifecycleResult>('POST', `/v1/services/${id}/stop`),
373
+ start: (id) => send<ServiceLifecycleResult>('POST', `/v1/services/${id}/start`),
374
+ restart: (id) => send<ServiceLifecycleResult>('POST', `/v1/services/${id}/restart`),
375
+ lifecycle: id => get<ServiceLifecycleView>(`/v1/services/${id}/lifecycle`),
376
+ retryLifecycle: id => send<ServiceLifecycleRetry>('POST', `/v1/services/${id}/lifecycle/retry`),
276
377
  logs: (id, opts) => get<{ lines: string }>(`/v1/services/${id}/logs${opts?.tail ? `?tail=${opts.tail}` : ''}`),
277
378
  clone: (id, input) => send<Service>('POST', `/v1/services/${id}/clone`, input ?? {}),
278
379
  exportUrl: (id) => `/v1/services/${id}/export`,
@@ -321,11 +422,59 @@ export function servicesApi(t: Transport): ServicesApi {
321
422
  },
322
423
  imageTransfers: (id, query) => get<ImageTransfer[]>(apiGetUrl(`/v1/services/${id}/image-transfers`, { ...query })),
323
424
  swarm: (id) => get<ServiceSwarmStatus>(`/v1/services/${id}/swarm`),
425
+ routing: (id) => get<ServiceRoutingView>(`/v1/services/${id}/routing`),
324
426
  runtimeRecovery: async id => (await get<{ entry: PrimaryRecoveryEntry | null }>(`/v1/services/${id}/runtime-recovery`)).entry,
325
427
  retryRuntimeRecovery: id => request<PrimaryRecoveryResult>(`/v1/services/${id}/runtime-recovery`, { method: 'POST' }, 600_000),
326
428
  swarmRecovery: async id => (await get<{ entry: SwarmRecoveryEntry | null }>(`/v1/services/${id}/swarm/recovery`)).entry,
327
429
  retrySwarmRecovery: id => request<SwarmRecoveryResult>(`/v1/services/${id}/swarm/recovery`, { method: 'POST' }, 600_000),
328
430
  autoscale: (id) => get<AutoscaleStatusView>(`/v1/services/${id}/autoscale`),
431
+ sizing: (id) => get<SizingReport>(`/v1/services/${id}/sizing`),
432
+ maintenance: {
433
+ get: (id) => get<MaintenanceView>(`/v1/services/${id}/maintenance`),
434
+ set: (id, maintenance) => send<MaintenanceView>('PUT', `/v1/services/${id}/maintenance`, { maintenance }),
435
+ },
436
+ errorPages: {
437
+ get: (id) => get<ErrorPagesView>(`/v1/services/${id}/error-pages`),
438
+ set: (id, pages) => send<ErrorPagesView>('PUT', `/v1/services/${id}/error-pages`, { pages }),
439
+ },
440
+ errors: {
441
+ list: (id, status) => get<ErrorIssueView[]>(`/v1/services/${id}/errors${status ? `?status=${status}` : ''}`),
442
+ get: (id, issueId) => get<{ issue: ErrorIssueView; events: ErrorEventView[] }>(`/v1/services/${id}/errors/${issueId}`),
443
+ setStatus: (id, issueId, status) => send<ErrorIssueView>('PATCH', `/v1/services/${id}/errors/${issueId}`, { status }),
444
+ ingest: {
445
+ get: (id) => get<ErrorIngestView>(`/v1/services/${id}/error-ingest`),
446
+ create: (id) => send<ErrorIngestView>('POST', `/v1/services/${id}/error-ingest`),
447
+ remove: (id) => send<ErrorIngestView>('DELETE', `/v1/services/${id}/error-ingest`),
448
+ },
449
+ },
450
+ move: {
451
+ get: (id) => get<ServiceMoveView>(`/v1/services/${id}/move`),
452
+ start: (id, serverId) => send<ServiceMoveView>('POST', `/v1/services/${id}/move`, { serverId }),
453
+ },
454
+ inlineDockerfile: {
455
+ get: (id) => get<InlineDockerfileView>(`/v1/services/${id}/inline-dockerfile`),
456
+ set: (id, content) => send<InlineDockerfileView>('PUT', `/v1/services/${id}/inline-dockerfile`, { content }),
457
+ },
458
+ commitStatus: {
459
+ get: (id) => get<ServiceCommitStatusView>(`/v1/services/${id}/commit-status`),
460
+ set: (id, enabled) => send<ServiceCommitStatusView>('PUT', `/v1/services/${id}/commit-status`, { enabled }),
461
+ },
462
+ registryHook: {
463
+ get: (id) => get<RegistryHookView>(`/v1/services/${id}/registry-hook`),
464
+ enable: (id) => send<RegistryHookView>('POST', `/v1/services/${id}/registry-hook`),
465
+ disable: (id) => request<RegistryHookView>(`/v1/services/${id}/registry-hook`, { method: 'DELETE' }),
466
+ },
467
+ restartLimit: {
468
+ get: (id) => get<RestartLimitView>(`/v1/services/${id}/restart-limit`),
469
+ set: (id, limit) => send<RestartLimitView>('PUT', `/v1/services/${id}/restart-limit`, { limit }),
470
+ },
471
+ pending: {
472
+ get: (id) => get<PendingChangesView>(`/v1/services/${id}/pending`),
473
+ stage: (id, patch) => send<PendingChangesView>('PUT', `/v1/services/${id}/pending`, patch),
474
+ setStaging: (id, staging) => send<PendingChangesView>('PUT', `/v1/services/${id}/pending/staging`, { staging }),
475
+ discard: (id) => send<PendingChangesView>('DELETE', `/v1/services/${id}/pending`),
476
+ apply: (id, input) => send<PendingApplyResult>('POST', `/v1/services/${id}/pending/apply`, input ?? {}),
477
+ },
329
478
  sleep: (id) => send<{ ok: boolean; asleep: boolean }>('POST', `/v1/services/${id}/sleep`),
330
479
  wake: (id) => send<{ ok: boolean; status: string }>('POST', `/v1/services/${id}/wake`),
331
480
  // ── end 0.16 T8 ──
@@ -11,10 +11,36 @@ import type {
11
11
  SecretProviderView,
12
12
  VaultProviderPut,
13
13
  AwsProviderPut,
14
+ GcpProviderPut,
15
+ AzureProviderPut,
16
+ OnePasswordProviderPut,
17
+ ExecProviderPut,
14
18
  } from '@ninedeploy/schemas';
15
19
  import type { VaultAllowlistView, VaultSettings, EmailTemplateName, EmailTemplateEntry, EmailTemplateRender } from '../types.js';
16
20
  import type { Transport } from '../transport.js';
17
21
 
22
+ /** The PUT body of each secret provider kind (G3.2 added gcp, azure, onepassword, exec). */
23
+ export type SecretProviderPutFor<K extends SecretProviderKind> = {
24
+ vault: VaultProviderPut;
25
+ aws: AwsProviderPut;
26
+ gcp: GcpProviderPut;
27
+ azure: AzureProviderPut;
28
+ onepassword: OnePasswordProviderPut;
29
+ exec: ExecProviderPut;
30
+ }[K];
31
+
32
+ /** G3.5: the DNS record providers configured through `settings.dnsProvider`. */
33
+ export type DnsCredentialProviderName = 'route53' | 'ovh' | 'porkbun' | 'hetzner';
34
+ export interface DnsProviderSettings {
35
+ providers: DnsCredentialProviderName[];
36
+ /** The active `dns_records_provider` (may be cloudflare, dnsimple, …). */
37
+ provider: string | null;
38
+ /** Which of these four has credentials saved. */
39
+ configured: DnsCredentialProviderName | null;
40
+ /** The saved non-secret fields (an access key id, an OVH endpoint). */
41
+ fields: Record<string, string>;
42
+ }
43
+
18
44
  export type AutoUrlMode = 'off' | 'domain' | 'sslip';
19
45
  export interface AutoUrlEffective {
20
46
  mode: AutoUrlMode;
@@ -88,6 +114,17 @@ export interface SettingsApi {
88
114
  get: () => Promise<{ configured: boolean; apiUser: string | null; clientIp: string | null; hasKey: boolean }>;
89
115
  set: (input: { apiUser: string; apiKey: string; clientIp: string }) => Promise<{ ok: boolean; apiUser: string }>;
90
116
  };
117
+ /**
118
+ * G3.5: Route 53, OVH, Porkbun and Hetzner DNS record auto-provisioning.
119
+ * Saving credentials makes that provider the active one; `get` never
120
+ * returns a secret.
121
+ */
122
+ dnsProvider: {
123
+ get: () => Promise<DnsProviderSettings>;
124
+ set: (input: { provider: DnsCredentialProviderName; credentials: Record<string, string> }) => Promise<{ ok: boolean; provider: string }>;
125
+ clear: () => Promise<{ ok: boolean }>;
126
+ test: () => Promise<{ ok: boolean; provider?: string; zones?: string[]; zoneCount?: number; error?: string }>;
127
+ };
91
128
  /**
92
129
  * Master-key rotation. `rotate` re-encrypts every stored secret onto the
93
130
  * highest key version in `NINEDEPLOY_MASTER_KEYS`; it does NOT rewrite
@@ -114,7 +151,7 @@ export interface SettingsApi {
114
151
  */
115
152
  secretProviders: {
116
153
  list: () => Promise<SecretProviderView[]>;
117
- set: <K extends SecretProviderKind>(kind: K, input: K extends 'vault' ? VaultProviderPut : AwsProviderPut) => Promise<SecretProviderView>;
154
+ set: <K extends SecretProviderKind>(kind: K, input: SecretProviderPutFor<K>) => Promise<SecretProviderView>;
118
155
  delete: (kind: SecretProviderKind) => Promise<{ ok: boolean; deleted: boolean }>;
119
156
  test: (kind: SecretProviderKind, probe?: SecretProviderTestRequest) => Promise<SecretProviderTestResult>;
120
157
  };
@@ -237,6 +274,13 @@ export function settingsApi(t: Transport): SettingsApi {
237
274
  get: () => get<{ configured: boolean; apiUser: string | null; clientIp: string | null; hasKey: boolean }>('/v1/settings/dns-records/namecheap'),
238
275
  set: (input) => send<{ ok: boolean; apiUser: string }>('PUT', '/v1/settings/dns-records/namecheap', input),
239
276
  },
277
+ dnsProvider: {
278
+ get: () => get<DnsProviderSettings>('/v1/settings/dns-records/provider'),
279
+ set: (input) => send<{ ok: boolean; provider: string }>('PUT', '/v1/settings/dns-records/provider', input),
280
+ clear: () => send<{ ok: boolean }>('DELETE', '/v1/settings/dns-records/provider'),
281
+ test: () =>
282
+ send<{ ok: boolean; provider?: string; zones?: string[]; zoneCount?: number; error?: string }>('POST', '/v1/settings/dns-records/provider/test'),
283
+ },
240
284
  masterKey: {
241
285
  get: () => get<{ activeVersion: number; knownVersions: number[]; rotatable: boolean }>('/v1/settings/master-key'),
242
286
  rotate: () =>
@@ -10,6 +10,8 @@ import type {
10
10
  GithubAppManifestRequest,
11
11
  GithubAppManifestResponse,
12
12
  GithubAppPatch,
13
+ GithubRunnerConfig,
14
+ GithubRunnerStatus,
13
15
  } from '@ninedeploy/schemas';
14
16
  import type { GithubAppInstallationSync, SourceRepo, SourceUpdateInput } from '../types.js';
15
17
  import type { Transport } from '../transport.js';
@@ -88,6 +90,11 @@ export interface SourcesApi {
88
90
  remove: (id: number) => Promise<void>;
89
91
  syncInstallations: (id: number) => Promise<GithubAppInstallationSync>;
90
92
  installations: (id: number) => Promise<GithubAppInstallation[]>;
93
+ /** Self-hosted Actions runners (G4.5): settings, waiting jobs, running runners and what is missing. */
94
+ runners: (id: number) => Promise<GithubRunnerStatus>;
95
+ setRunners: (id: number, config: GithubRunnerConfig) => Promise<GithubRunnerStatus>;
96
+ /** Stop one runner container (and remove its registration on GitHub). */
97
+ stopRunner: (id: number, name: string) => Promise<void>;
91
98
  };
92
99
  }
93
100
 
@@ -126,6 +133,11 @@ export function sourcesApi(t: Transport): SourcesApi {
126
133
  },
127
134
  syncInstallations: (id) => send<GithubAppInstallationSync>('POST', `/v1/github-apps/${id}/installations/sync`),
128
135
  installations: (id) => get<GithubAppInstallation[]>(`/v1/github-apps/${id}/installations`),
136
+ runners: (id) => get<GithubRunnerStatus>(`/v1/github-apps/${id}/runners`),
137
+ setRunners: (id, config) => send<GithubRunnerStatus>('PUT', `/v1/github-apps/${id}/runners`, config),
138
+ stopRunner: async (id, name) => {
139
+ await request(`/v1/github-apps/${id}/runners/${encodeURIComponent(name)}`, { method: 'DELETE' });
140
+ },
129
141
  },
130
142
  };
131
143
  }
@@ -25,11 +25,27 @@ import type {
25
25
  PanelBackupRestore,
26
26
  PanelBackupSettingsPatch,
27
27
  PanelBackupStatus,
28
+ GitopsApplyStep,
29
+ GitopsCheck,
30
+ GitopsConfigInput,
31
+ GitopsView,
28
32
  } from '@ninedeploy/schemas';
29
33
  import type { HealthStatus, ImageInfo, PruneImagesInput, PruneImagesResult } from '../types.js';
30
34
  import type { Transport } from '../transport.js';
31
35
 
32
36
  export interface SystemApi {
37
+ /** G5.3 instance GitOps (operators): the instance as a file in a repository. */
38
+ gitops: {
39
+ get: () => Promise<GitopsView>;
40
+ configure: (input: GitopsConfigInput) => Promise<GitopsView>;
41
+ remove: () => Promise<{ ok: true }>;
42
+ /** Read the file now and report the drift. */
43
+ check: () => Promise<GitopsCheck>;
44
+ /** Create and update what the file names (never deletes). */
45
+ apply: () => Promise<{ steps: GitopsApplyStep[]; check: GitopsCheck }>;
46
+ /** The live instance as the file, to commit. */
47
+ export: () => Promise<{ file: string }>;
48
+ };
33
49
  system: {
34
50
  resources: () => Promise<DockerResources>;
35
51
  pruneImages: () => Promise<{ ok: boolean }>;
@@ -175,6 +191,14 @@ export interface SystemApi {
175
191
  export function systemApi(t: Transport): SystemApi {
176
192
  const { get, send, request } = t;
177
193
  return {
194
+ gitops: {
195
+ get: () => get<GitopsView>('/v1/gitops'),
196
+ configure: (input) => send<GitopsView>('PUT', '/v1/gitops', input),
197
+ remove: () => send<{ ok: true }>('DELETE', '/v1/gitops'),
198
+ check: () => send<GitopsCheck>('POST', '/v1/gitops/check'),
199
+ apply: () => send<{ steps: GitopsApplyStep[]; check: GitopsCheck }>('POST', '/v1/gitops/apply'),
200
+ export: () => get<{ file: string }>('/v1/gitops/export?format=json'),
201
+ },
178
202
  system: {
179
203
  resources: () => get<DockerResources>('/v1/system/resources'),
180
204
  pruneImages: () => send<{ ok: boolean }>('POST', '/v1/system/prune-images'),
@@ -76,6 +76,11 @@ export interface TraefikApi {
76
76
  replace: (id: number, input: CustomCertificateReplace) => Promise<CustomCertificateSaved>;
77
77
  delete: (id: number) => Promise<{ ok: boolean }>;
78
78
  };
79
+ /** G5.7: give node proxies the panel's ACME certificates for the hosts they route (operator; off by default). */
80
+ sharedCertificates: {
81
+ get: () => Promise<{ enabled: boolean }>;
82
+ set: (enabled: boolean) => Promise<{ enabled: boolean }>;
83
+ };
79
84
  };
80
85
  }
81
86
 
@@ -120,6 +125,10 @@ export function traefikApi(t: Transport): TraefikApi {
120
125
  replace: (id, input) => send<CustomCertificateSaved>('PUT', `/v1/traefik/certificates/custom/${id}`, input),
121
126
  delete: (id) => send<{ ok: boolean }>('DELETE', `/v1/traefik/certificates/custom/${id}`),
122
127
  },
128
+ sharedCertificates: {
129
+ get: () => get<{ enabled: boolean }>('/v1/traefik/certificates/shared'),
130
+ set: (enabled) => send<{ enabled: boolean }>('PUT', '/v1/traefik/certificates/shared', { enabled }),
131
+ },
123
132
  },
124
133
  };
125
134
  }