@statuser/cli 0.0.0-stage → 0.1.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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +448 -2
  3. package/dist/client.js +163 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/commander-i18n.js +52 -0
  6. package/dist/commander-i18n.js.map +1 -0
  7. package/dist/commands/api.js +104 -0
  8. package/dist/commands/api.js.map +1 -0
  9. package/dist/commands/auth.js +104 -0
  10. package/dist/commands/auth.js.map +1 -0
  11. package/dist/commands/catalog.js +72 -0
  12. package/dist/commands/catalog.js.map +1 -0
  13. package/dist/commands/config.js +302 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/heartbeat.js +199 -0
  16. package/dist/commands/heartbeat.js.map +1 -0
  17. package/dist/commands/incidents.js +265 -0
  18. package/dist/commands/incidents.js.map +1 -0
  19. package/dist/commands/maintenance.js +211 -0
  20. package/dist/commands/maintenance.js.map +1 -0
  21. package/dist/commands/reports.js +170 -0
  22. package/dist/commands/reports.js.map +1 -0
  23. package/dist/commands/scenarios.js +361 -0
  24. package/dist/commands/scenarios.js.map +1 -0
  25. package/dist/commands/servers-add.js +152 -0
  26. package/dist/commands/servers-add.js.map +1 -0
  27. package/dist/commands/servers-checks.js +56 -0
  28. package/dist/commands/servers-checks.js.map +1 -0
  29. package/dist/commands/servers.js +424 -0
  30. package/dist/commands/servers.js.map +1 -0
  31. package/dist/config.js +107 -0
  32. package/dist/config.js.map +1 -0
  33. package/dist/confirm.js +34 -0
  34. package/dist/confirm.js.map +1 -0
  35. package/dist/context.js +27 -0
  36. package/dist/context.js.map +1 -0
  37. package/dist/duration.js +20 -0
  38. package/dist/duration.js.map +1 -0
  39. package/dist/errors.js +73 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/files.js +36 -0
  42. package/dist/files.js.map +1 -0
  43. package/dist/generated/openapi.js +6 -0
  44. package/dist/generated/openapi.js.map +1 -0
  45. package/dist/i18n.js +757 -0
  46. package/dist/i18n.js.map +1 -0
  47. package/dist/index.js +58 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/json-error.js +10 -0
  50. package/dist/json-error.js.map +1 -0
  51. package/dist/output.js +43 -0
  52. package/dist/output.js.map +1 -0
  53. package/dist/scenarios/config.js +228 -0
  54. package/dist/scenarios/config.js.map +1 -0
  55. package/dist/scenarios/plan.js +159 -0
  56. package/dist/scenarios/plan.js.map +1 -0
  57. package/dist/servers-config/export.js +72 -0
  58. package/dist/servers-config/export.js.map +1 -0
  59. package/dist/servers-config/fields.js +172 -0
  60. package/dist/servers-config/fields.js.map +1 -0
  61. package/dist/servers-config/forbidden-host.js +75 -0
  62. package/dist/servers-config/forbidden-host.js.map +1 -0
  63. package/dist/servers-config/host-pattern.js +6 -0
  64. package/dist/servers-config/host-pattern.js.map +1 -0
  65. package/dist/servers-config/parse.js +260 -0
  66. package/dist/servers-config/parse.js.map +1 -0
  67. package/dist/servers-config/plan.js +492 -0
  68. package/dist/servers-config/plan.js.map +1 -0
  69. package/dist/servers-update.js +157 -0
  70. package/dist/servers-update.js.map +1 -0
  71. package/dist/status-page.js +15 -0
  72. package/dist/status-page.js.map +1 -0
  73. package/dist/text-length.js +8 -0
  74. package/dist/text-length.js.map +1 -0
  75. package/dist/write-failure.js +37 -0
  76. package/dist/write-failure.js.map +1 -0
  77. package/package.json +70 -4
@@ -0,0 +1,492 @@
1
+ import { CliError, ExitCode } from '../errors.js';
2
+ import { t } from '../i18n.js';
3
+ import { duplicateKey, isDuplicateOf, sameValue } from './fields.js';
4
+ import { isForbiddenHost } from './forbidden-host.js';
5
+ const fail = (message) => {
6
+ throw new CliError(message, ExitCode.Usage);
7
+ };
8
+ /**
9
+ * Pure: compares the `servers` section with the account. Everything the
10
+ * API would reject mid-way — an ambiguous match, a protocol change, a
11
+ * duplicate monitor, a plan limit, a create without its password — is
12
+ * raised here, before any write.
13
+ *
14
+ * `account` must hold ALL servers of the account: duplicates and the
15
+ * servers limit are account-wide.
16
+ */
17
+ export function buildServersPlan(desired, projectId, account, features, plannedScenarioCreates = 0,
18
+ // `servers add` always creates: a server of the same name is not a match
19
+ // there, since only heartbeats are told apart by name.
20
+ options = {}) {
21
+ const inProject = account.filter((s) => s.project_id === projectId && s.protocol !== 'scenario');
22
+ const byId = new Map(account.map((s) => [s.id, s]));
23
+ const claimed = new Set();
24
+ const steps = [];
25
+ checkNames(desired);
26
+ for (const entry of desired) {
27
+ const server = options.createOnly
28
+ ? undefined
29
+ : matchServer(entry, byId, inProject, projectId);
30
+ if (server) {
31
+ if (claimed.has(server.id))
32
+ fail(t.applyClaimedTwice(entry.at, server.id));
33
+ claimed.add(server.id);
34
+ // Changing the protocol wipes what belongs to the old one: HTTP
35
+ // credentials, the LLM key, the heartbeat token.
36
+ if (server.protocol !== entry.protocol) {
37
+ fail(t.applyProtocolChange(entry.at, server.id, server.protocol));
38
+ }
39
+ steps.push(diffServer(entry, server));
40
+ }
41
+ else {
42
+ steps.push(createStep(entry, projectId, features));
43
+ }
44
+ }
45
+ checkHosts(steps);
46
+ checkRequestSize(steps);
47
+ checkAuth(steps, byId);
48
+ checkLlm(steps, byId);
49
+ checkDuplicates(steps, account);
50
+ checkPlan(steps, account, features, plannedScenarioCreates);
51
+ const unmanaged = inProject
52
+ .filter((s) => !claimed.has(s.id))
53
+ .map((s) => ({ id: s.id, name: s.name }));
54
+ return { steps, unmanaged };
55
+ }
56
+ function matchServer(entry, byId, inProject, projectId) {
57
+ if (entry.id !== undefined) {
58
+ const server = byId.get(entry.id);
59
+ // A pinned id that is gone is an error, not a reason to create a copy.
60
+ if (!server || server.protocol === 'scenario') {
61
+ return fail(t.applyIdNotFound(entry.at, entry.id));
62
+ }
63
+ if (server.project_id !== projectId) {
64
+ return fail(t.applyIdOtherProject(entry.at, entry.id, server.project_id));
65
+ }
66
+ return server;
67
+ }
68
+ const byName = inProject.filter((s) => s.name === entry.name);
69
+ if (byName.length > 1)
70
+ fail(t.applyAmbiguousName(entry.at, entry.name ?? ''));
71
+ return byName[0];
72
+ }
73
+ /**
74
+ * Entries without an id are found by name on every run, so such names must
75
+ * be unique in the file. Entries pinned by id may share a name, as two
76
+ * servers of the project may (an own export has them); a name shared with a
77
+ * server the file does not mention makes the name match itself ambiguous,
78
+ * and `matchServer` stops there.
79
+ */
80
+ function checkNames(desired) {
81
+ const fileNames = new Map();
82
+ for (const entry of desired) {
83
+ if (entry.name === null)
84
+ continue;
85
+ const other = fileNames.get(entry.name);
86
+ if (other && (other.id === undefined || entry.id === undefined)) {
87
+ fail(t.applyDuplicateName(entry.at, other.at, entry.name));
88
+ }
89
+ if (!other || entry.id === undefined)
90
+ fileNames.set(entry.name, entry);
91
+ }
92
+ }
93
+ function diffServer(entry, server) {
94
+ const current = server;
95
+ const body = {};
96
+ const fields = [];
97
+ // `name: null` on a pinned entry clears the name, as the API does; an
98
+ // entry without `name` leaves it alone.
99
+ if (entry.nameGiven && entry.name !== server.name) {
100
+ body.name = entry.name;
101
+ fields.push('name');
102
+ }
103
+ for (const [field, value] of Object.entries(entry.fields)) {
104
+ if (!sameValue(field, value, current[field])) {
105
+ // `body: null` would be stored as the string "null"; clear with "".
106
+ body[field] = field === 'body' && value === null ? '' : value;
107
+ fields.push(field);
108
+ }
109
+ }
110
+ // Values never come back from the API, so a set secret is always sent.
111
+ for (const [field, value] of Object.entries(entry.secrets)) {
112
+ body[field] = value;
113
+ fields.push(field);
114
+ }
115
+ if (!fields.length) {
116
+ return { kind: 'unchanged', entry, serverId: server.id };
117
+ }
118
+ return { kind: 'update', entry, serverId: server.id, fields, body };
119
+ }
120
+ function createStep(entry, projectId, features) {
121
+ const f = entry.fields;
122
+ const warnings = [];
123
+ if (entry.protocol !== 'heartbeat' && !f.host) {
124
+ fail(t.applyFieldRequired(entry.at, 'host'));
125
+ }
126
+ if (entry.protocol === 'tcp' && f.port === undefined) {
127
+ fail(t.applyFieldRequired(entry.at, 'port'));
128
+ }
129
+ if (entry.protocol === 'keyword' && !f.keyword) {
130
+ fail(t.applyFieldRequired(entry.at, 'keyword'));
131
+ }
132
+ if (entry.protocol === 'dns' && !f.dns_record_types) {
133
+ fail(t.applyFieldRequired(entry.at, 'dns_record_types'));
134
+ }
135
+ if (entry.protocol === 'llm' && !f.llm_provider) {
136
+ fail(t.applyFieldRequired(entry.at, 'llm_provider'));
137
+ }
138
+ // An empty Basic password is legal; only its absence is not.
139
+ if (f.http_auth_type === 'basic' &&
140
+ entry.secrets.http_auth_password === undefined) {
141
+ fail(t.applyFieldRequired(entry.at, 'http_auth_password'));
142
+ }
143
+ if (f.http_auth_type === 'bearer' && !entry.secrets.http_auth_token) {
144
+ fail(t.applyFieldRequired(entry.at, 'http_auth_token'));
145
+ }
146
+ if (entry.protocol === 'llm' && entry.secrets.llm_api_key && !f.llm_model) {
147
+ fail(t.applyFieldRequired(entry.at, 'llm_model'));
148
+ }
149
+ if (entry.protocol === 'llm' && !entry.secrets.llm_api_key) {
150
+ warnings.push(t.applyLlmAvailability(entry.name ?? entry.at));
151
+ }
152
+ const isHttp = entry.protocol === 'http' || entry.protocol === 'keyword';
153
+ return {
154
+ kind: 'create',
155
+ entry,
156
+ warnings,
157
+ body: {
158
+ // Fields the API requires for every protocol, with the panel defaults.
159
+ is_follow_redirects: isHttp,
160
+ request_timeout: 30,
161
+ check_interval: 300,
162
+ is_ssl_check: false,
163
+ is_domain_check: false,
164
+ // Without locations the API stores its own default (Moscow and
165
+ // St Petersburg) without checking the plan; on Free they are not
166
+ // available, and every later edit of the server would be refused.
167
+ // The panel sends all locations of the plan, and so does this.
168
+ locations: features.available_locations,
169
+ // HEAD has no body, so a keyword check needs GET to see the page.
170
+ ...(isHttp && {
171
+ http_method: entry.protocol === 'keyword' ? 'get' : 'head',
172
+ }),
173
+ ...(entry.protocol === 'keyword' && { keyword_mode: 'present' }),
174
+ ...f,
175
+ ...entry.secrets,
176
+ ...(entry.protocol === 'heartbeat' && { host: 'heartbeat' }),
177
+ ...(f.body === null && { body: '' }),
178
+ project_id: projectId,
179
+ protocol: entry.protocol,
180
+ ...(entry.name !== null && { name: entry.name }),
181
+ },
182
+ };
183
+ }
184
+ /**
185
+ * HTTP credentials as they end up after the write: Basic needs a username,
186
+ * switching the type needs the new secret, and a set `Authorization`
187
+ * header would clash with them (`server_http_auth_header_conflict`).
188
+ */
189
+ /**
190
+ * The backend refuses an internal address only when the host is set or
191
+ * changed, so a server created before the rule keeps working and stays
192
+ * editable; the file may list it unchanged.
193
+ */
194
+ function checkHosts(steps) {
195
+ for (const step of steps) {
196
+ if (step.kind === 'unchanged')
197
+ continue;
198
+ const host = step.body.host;
199
+ if (typeof host === 'string' && isForbiddenHost(host)) {
200
+ fail(`${step.entry.at}.host: ${t.cfgHostInternal}`);
201
+ }
202
+ }
203
+ }
204
+ // The API's JSON body limit (`main.ts`); a larger request is refused
205
+ // before validation, after the writes ahead of it in the plan.
206
+ const MAX_REQUEST_BYTES = 10 * 1024 * 1024;
207
+ function checkRequestSize(steps) {
208
+ for (const step of steps) {
209
+ if (step.kind === 'unchanged')
210
+ continue;
211
+ const bytes = Buffer.byteLength(JSON.stringify(step.body), 'utf8');
212
+ if (bytes > MAX_REQUEST_BYTES) {
213
+ fail(t.applyRequestTooLarge(step.entry.at, MAX_REQUEST_BYTES));
214
+ }
215
+ }
216
+ }
217
+ function checkAuth(steps, byId) {
218
+ for (const step of steps) {
219
+ if (step.kind === 'unchanged')
220
+ continue;
221
+ const current = step.kind === 'update' ? byId.get(step.serverId) : undefined;
222
+ const body = step.body;
223
+ const type = (body.http_auth_type ??
224
+ current?.http_auth_type ??
225
+ 'none');
226
+ // A secret of the other type would be accepted and ignored.
227
+ if (body.http_auth_password !== undefined && type !== 'basic') {
228
+ fail(t.applyAuthSecretMismatch(step.entry.at, 'http_auth_password', type));
229
+ }
230
+ if (body.http_auth_token !== undefined && type !== 'bearer') {
231
+ fail(t.applyAuthSecretMismatch(step.entry.at, 'http_auth_token', type));
232
+ }
233
+ // The login as written in the file, sent or not: an unchanged login
234
+ // next to `none` would be wiped by the API and fail the next run.
235
+ const login = body.http_auth_username ?? step.entry.fields.http_auth_username;
236
+ if (login != null && type !== 'basic') {
237
+ fail(t.applyAuthSecretMismatch(step.entry.at, 'http_auth_username', type));
238
+ }
239
+ if (type === 'none')
240
+ continue;
241
+ const username = body.http_auth_username ?? current?.http_auth_username;
242
+ if (type === 'basic' && !String(username ?? '').trim()) {
243
+ fail(t.applyFieldRequired(step.entry.at, 'http_auth_username'));
244
+ }
245
+ const typeChanged = !current || current.http_auth_type !== type;
246
+ const secret = type === 'basic' ? 'http_auth_password' : 'http_auth_token';
247
+ if (typeChanged && body[secret] === undefined) {
248
+ fail(t.applyFieldRequired(step.entry.at, secret));
249
+ }
250
+ const headers = (body.headers ?? current?.headers ?? []);
251
+ if (headers.some((h) => h.key.trim().toLowerCase() === 'authorization')) {
252
+ fail(t.applyAuthHeaderConflict(step.entry.at));
253
+ }
254
+ }
255
+ }
256
+ /**
257
+ * The LLM configuration as it ends up (`assertLlmConfigUsable`): a key
258
+ * needs a model, and a model without a key is dropped by the backend — the
259
+ * duplicate check would then compare a model that is never stored.
260
+ */
261
+ function checkLlm(steps, byId) {
262
+ for (const step of steps) {
263
+ if (step.kind === 'unchanged' || step.entry.protocol !== 'llm')
264
+ continue;
265
+ const current = step.kind === 'update' ? byId.get(step.serverId) : undefined;
266
+ const body = step.body;
267
+ const hasKey = body.llm_api_key !== undefined
268
+ ? Boolean(body.llm_api_key)
269
+ : current?.llm_check_mode === 'inference';
270
+ const model = body.llm_model ?? current?.llm_model ?? null;
271
+ if (hasKey && !model) {
272
+ fail(t.applyFieldRequired(step.entry.at, 'llm_model'));
273
+ }
274
+ if (!hasKey && body.llm_model !== undefined) {
275
+ fail(`${step.entry.at}.llm_model: ${t.cfgLlmModelWithoutKey}`);
276
+ }
277
+ }
278
+ }
279
+ /**
280
+ * The backend rejects a monitor equal to another one anywhere in the
281
+ * account, and it checks every request against the state at that moment.
282
+ * So the plan is replayed in execution order (updates, then creates): a
283
+ * swap of addresses between two servers collides on its first PATCH and
284
+ * is refused here, before any write.
285
+ */
286
+ function checkDuplicates(steps, account) {
287
+ const states = new Map();
288
+ for (const server of account) {
289
+ if (server.protocol === 'scenario')
290
+ continue;
291
+ states.set(`#${server.id}`, {
292
+ state: server,
293
+ label: server.name ?? server.host,
294
+ });
295
+ }
296
+ const ordered = [
297
+ ...steps.filter((s) => s.kind === 'update'),
298
+ ...steps.filter((s) => s.kind === 'create'),
299
+ ];
300
+ for (const step of ordered) {
301
+ // Creates and existing servers keep separate keys: a label like `#123`
302
+ // must not land on the slot of server 123.
303
+ const slot = step.kind === 'create' ? `create:${step.entry.at}` : `#${step.serverId}`;
304
+ const previous = states.get(slot);
305
+ const state = { ...previous?.state, ...step.body };
306
+ const label = step.entry.name ?? previous?.label ?? step.entry.at;
307
+ const key = duplicateKey(state);
308
+ // The backend checks only a create or a write that changes the identity:
309
+ // a duplicate made before the check existed can still be edited.
310
+ if (previous && duplicateKey(previous.state) === key) {
311
+ states.set(slot, { state, label });
312
+ continue;
313
+ }
314
+ for (const [other, item] of states) {
315
+ if (other !== slot && isDuplicateOf(state, item.state)) {
316
+ fail(t.applyDuplicate(label, item.label));
317
+ }
318
+ }
319
+ states.set(slot, { state, label });
320
+ }
321
+ }
322
+ // Fields whose presence in a PATCH makes the backend re-check the plan
323
+ // (`ServerWriteService.update` → `validateServerFeatures`).
324
+ const FEATURE_TRIGGERS = [
325
+ 'check_interval',
326
+ 'locations',
327
+ 'is_ssl_check',
328
+ 'is_domain_check',
329
+ 'is_blocklist_check',
330
+ 'is_latency_alert_enabled',
331
+ 'latency_trigger_ms',
332
+ 'incident_confirm_delay',
333
+ 'llm_api_key',
334
+ 'success_http_codes',
335
+ ];
336
+ /**
337
+ * What a write needs from the plan, as the backend checks it: on create
338
+ * the new server, on update the server as it will be after the PATCH —
339
+ * so a server kept from a richer plan fails as soon as it is touched.
340
+ */
341
+ function requirements(step, current) {
342
+ if (step.kind === 'unchanged')
343
+ return { features: [] };
344
+ const body = step.body;
345
+ if (step.kind === 'update' &&
346
+ !FEATURE_TRIGGERS.some((field) => field in body)) {
347
+ return { features: [] };
348
+ }
349
+ const merged = {
350
+ ...current,
351
+ ...body,
352
+ };
353
+ const needs = [];
354
+ const byProtocol = {
355
+ keyword: 'keyword_monitoring_enabled',
356
+ dns: 'dns_monitoring_enabled',
357
+ heartbeat: 'heartbeat_monitoring_enabled',
358
+ llm: 'ai_monitoring_enabled',
359
+ };
360
+ const protocolFeature = byProtocol[merged.protocol];
361
+ if (protocolFeature)
362
+ needs.push(protocolFeature);
363
+ const inference = body.llm_api_key !== undefined
364
+ ? Boolean(body.llm_api_key)
365
+ : current?.llm_check_mode === 'inference';
366
+ if (merged.protocol === 'llm' && inference)
367
+ needs.push('ai_inference_enabled');
368
+ if (merged.is_ssl_check === true)
369
+ needs.push('ssl_monitoring_enabled');
370
+ if (merged.is_domain_check === true)
371
+ needs.push('domain_monitoring_enabled');
372
+ // The backend reads only the sent value here: old rows have it on.
373
+ if (body.is_blocklist_check === true) {
374
+ needs.push('blocklist_monitoring_enabled');
375
+ }
376
+ if (merged.is_latency_alert_enabled === true) {
377
+ needs.push('latency_alerts_enabled');
378
+ }
379
+ if (typeof body.incident_confirm_delay === 'number' &&
380
+ body.incident_confirm_delay > 0) {
381
+ needs.push('incident_debounce_enabled');
382
+ }
383
+ const codes = body.success_http_codes?.map((c) => c.trim().toLowerCase());
384
+ if (codes && !(codes.length === 1 && codes[0] === '2xx')) {
385
+ needs.push('custom_success_http_codes_enabled');
386
+ }
387
+ return {
388
+ features: needs,
389
+ interval: merged.check_interval,
390
+ locations: merged.locations,
391
+ };
392
+ }
393
+ function checkPlan(steps, account, features, plannedScenarioCreates) {
394
+ const byId = new Map(account.map((s) => [s.id, s]));
395
+ const creates = steps.filter((s) => s.kind === 'create').length;
396
+ // An account already over the limit after a downgrade may still edit
397
+ // its servers; only new ones are refused.
398
+ if (creates + plannedScenarioCreates > 0 &&
399
+ account.length + creates + plannedScenarioCreates > features.servers_limit) {
400
+ fail(t.applyServersLimit(features.servers_limit, account.length, creates + plannedScenarioCreates));
401
+ }
402
+ for (const step of steps) {
403
+ if (step.kind === 'unchanged')
404
+ continue;
405
+ const current = step.kind === 'update' ? byId.get(step.serverId) : undefined;
406
+ const needed = requirements(step, current);
407
+ for (const feature of needed.features) {
408
+ if (!features[feature]) {
409
+ fail(t.applyFeatureUnavailable(step.entry.at, feature));
410
+ }
411
+ }
412
+ if (needed.interval !== undefined &&
413
+ needed.interval < features.min_check_interval_seconds) {
414
+ fail(t.applyIntervalTooLow(step.entry.at, features.min_check_interval_seconds));
415
+ }
416
+ const unavailable = (needed.locations ?? []).filter((l) => !features.available_locations.includes(l));
417
+ if (unavailable.length) {
418
+ fail(t.applyLocationsUnavailable(step.entry.at, unavailable.join(', ')));
419
+ }
420
+ }
421
+ }
422
+ /**
423
+ * The scenario side of the plan limits: the number of scenarios, their
424
+ * minimal interval and maximal timeout. Checked together with the servers
425
+ * so a full apply never stops on the scenarios after servers were written.
426
+ */
427
+ export function checkScenarioLimits(steps, existingScenarios, features) {
428
+ const creates = steps.filter((s) => s.kind === 'create').length;
429
+ // The backend checks the plan on a create and on any change to the
430
+ // scenario or its interval (`validateScenarioFeatures`); a rename alone
431
+ // passes even on a plan without scenarios.
432
+ const gated = steps.filter((s) => s.kind === 'create' ||
433
+ (s.kind === 'update' && (s.fields ?? []).some((f) => f !== 'name')));
434
+ if (features.scenarios_limit <= 0 && gated.length) {
435
+ fail(t.applyFeatureUnavailable('scenarios', 'scenarios_limit'));
436
+ }
437
+ if (creates && existingScenarios + creates > features.scenarios_limit) {
438
+ fail(t.applyScenariosLimit(features.scenarios_limit, existingScenarios, creates));
439
+ }
440
+ for (const step of gated) {
441
+ const { name, interval, timeout } = step.scenario;
442
+ if (interval < features.scenario_min_check_interval_seconds) {
443
+ fail(t.applyIntervalTooLow(name, features.scenario_min_check_interval_seconds));
444
+ }
445
+ if (timeout > features.scenario_max_timeout_seconds) {
446
+ fail(t.applyScenarioTimeoutTooHigh(name, features.scenario_max_timeout_seconds));
447
+ }
448
+ }
449
+ }
450
+ /**
451
+ * Plan checks for one PATCH of `servers update`, the same the backend runs:
452
+ * features of the server as it will be, the minimal interval, available
453
+ * locations, and for scenarios their own limits. Null when it fits.
454
+ */
455
+ export function patchPlanProblem(server, body, features) {
456
+ if (server.protocol === 'scenario') {
457
+ // The API checks the plan of a scenario only when its schedule or run
458
+ // changes; a rename or a new description passes on any plan.
459
+ if (!['check_interval', 'request_timeout', 'locations'].some((field) => field in body)) {
460
+ return null;
461
+ }
462
+ if (features.scenarios_limit <= 0)
463
+ return 'scenarios_limit';
464
+ const interval = body.check_interval ?? server.check_interval;
465
+ const timeout = body.request_timeout ?? server.request_timeout;
466
+ if (interval < features.scenario_min_check_interval_seconds) {
467
+ return `interval ≥ ${features.scenario_min_check_interval_seconds}`;
468
+ }
469
+ if (timeout > features.scenario_max_timeout_seconds) {
470
+ return `timeout ≤ ${features.scenario_max_timeout_seconds}`;
471
+ }
472
+ return null;
473
+ }
474
+ const step = {
475
+ kind: 'update',
476
+ serverId: server.id,
477
+ body,
478
+ fields: Object.keys(body),
479
+ entry: { at: `#${server.id}` },
480
+ };
481
+ const needed = requirements(step, server);
482
+ const missing = needed.features.find((feature) => !features[feature]);
483
+ if (missing)
484
+ return missing;
485
+ if (needed.interval !== undefined &&
486
+ needed.interval < features.min_check_interval_seconds) {
487
+ return `interval ≥ ${features.min_check_interval_seconds}`;
488
+ }
489
+ const unavailable = (needed.locations ?? []).filter((l) => !features.available_locations.includes(l));
490
+ return unavailable.length ? unavailable.join(', ') : null;
491
+ }
492
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/servers-config/plan.ts"],"names":[],"mappings":"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"}