deepline 0.3.293 → 0.3.295

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 (138) hide show
  1. package/dist/bundling-sources/sdk/src/compat.ts +35 -7
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +269 -267
  4. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +3 -4
  5. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +14 -1
  6. package/dist/cli/auth-EDTRERZP.mjs +31 -0
  7. package/dist/cli/auth-TDHKB277.js +31 -0
  8. package/dist/cli/billing-ELIDPILY.js +1749 -0
  9. package/dist/cli/billing-EXGXJVAU.mjs +1749 -0
  10. package/dist/cli/chunk-2S5Y3TZP.js +5688 -0
  11. package/dist/cli/chunk-3KC45UVF.js +150 -0
  12. package/dist/cli/chunk-3XX5TEA4.js +15 -0
  13. package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
  14. package/dist/cli/chunk-4NEFYBF7.js +2240 -0
  15. package/dist/cli/chunk-5JLQPVNX.js +3056 -0
  16. package/dist/cli/chunk-5KDKFHZI.js +1269 -0
  17. package/dist/cli/chunk-6A3TJUWC.js +76 -0
  18. package/dist/cli/chunk-6O5YZOVN.mjs +890 -0
  19. package/dist/cli/chunk-7P5AA3SN.js +344 -0
  20. package/dist/cli/chunk-AYHLUHE5.js +52 -0
  21. package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
  22. package/dist/cli/chunk-CFVVCN4A.js +735 -0
  23. package/dist/cli/chunk-COGTRVWW.js +30 -0
  24. package/dist/cli/chunk-D4AZUZO4.js +190 -0
  25. package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
  26. package/dist/cli/chunk-EACVZI6N.mjs +1995 -0
  27. package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
  28. package/dist/cli/chunk-EXMLR72R.mjs +0 -0
  29. package/dist/cli/chunk-F35VOIQL.js +890 -0
  30. package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
  31. package/dist/cli/chunk-GHRQQPW2.mjs +2240 -0
  32. package/dist/cli/chunk-GONRLVV3.js +3440 -0
  33. package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
  34. package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
  35. package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
  36. package/dist/cli/chunk-I5YZLGMG.js +1 -0
  37. package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
  38. package/dist/cli/chunk-J5NA2TTX.js +503 -0
  39. package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
  40. package/dist/cli/chunk-JNNOCMQY.js +47 -0
  41. package/dist/cli/chunk-KRD6H754.mjs +30 -0
  42. package/dist/cli/chunk-LA46MMTL.js +560 -0
  43. package/dist/cli/chunk-LDWT7RJK.mjs +190 -0
  44. package/dist/cli/chunk-M2V26OR5.js +499 -0
  45. package/dist/cli/chunk-MIMASXO4.mjs +389 -0
  46. package/dist/cli/chunk-MROPCKW2.mjs +190 -0
  47. package/dist/cli/chunk-NXDRDJ4K.js +389 -0
  48. package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
  49. package/dist/cli/chunk-OG64RBAC.js +6 -0
  50. package/dist/cli/chunk-OQYEC4GL.mjs +34 -0
  51. package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
  52. package/dist/cli/chunk-SDK3ZA2C.js +103 -0
  53. package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
  54. package/dist/cli/chunk-SVIIIYIQ.js +923 -0
  55. package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
  56. package/dist/cli/chunk-U3PI7HBM.js +34 -0
  57. package/dist/cli/chunk-UFS752TU.mjs +52 -0
  58. package/dist/cli/chunk-UI37DQE7.mjs +499 -0
  59. package/dist/cli/chunk-UNEMDKXN.js +1 -0
  60. package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
  61. package/dist/cli/chunk-WJYPBHTE.js +148 -0
  62. package/dist/cli/chunk-WOHBA5PV.js +354 -0
  63. package/dist/cli/chunk-WQICC2B3.js +190 -0
  64. package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
  65. package/dist/cli/chunk-XL2FO6CW.mjs +5688 -0
  66. package/dist/cli/chunk-XNYIZMNQ.js +28 -0
  67. package/dist/cli/chunk-XRK2TZT5.js +1995 -0
  68. package/dist/cli/chunk-YJYPL5OK.mjs +1269 -0
  69. package/dist/cli/chunk-YWNDYCXR.mjs +735 -0
  70. package/dist/cli/chunk-YWWAF7KZ.mjs +923 -0
  71. package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
  72. package/dist/cli/client-4JVOYVC5.js +20 -0
  73. package/dist/cli/client-EEN2IJN2.mjs +20 -0
  74. package/dist/cli/csv-BOHBEP2I.mjs +585 -0
  75. package/dist/cli/csv-S5NYRUEX.js +585 -0
  76. package/dist/cli/db-CLODWCOB.mjs +486 -0
  77. package/dist/cli/db-F6PKFOOV.js +486 -0
  78. package/dist/cli/executions-5TQAKLJU.js +28 -0
  79. package/dist/cli/executions-MAKW6QOY.mjs +28 -0
  80. package/dist/cli/feedback-GV4QJFEN.js +107 -0
  81. package/dist/cli/feedback-XY24TW7H.mjs +107 -0
  82. package/dist/cli/getting-started.js +18 -76
  83. package/dist/cli/getting-started.mjs +10 -37
  84. package/dist/cli/git-6S2C22T5.js +23 -0
  85. package/dist/cli/git-OZLBD5HH.mjs +23 -0
  86. package/dist/cli/index.js +291 -54294
  87. package/dist/cli/index.mjs +209 -54352
  88. package/dist/cli/legacy-noops-LLCGDPQE.js +157 -0
  89. package/dist/cli/legacy-noops-TYH3TW2D.mjs +157 -0
  90. package/dist/cli/monitors-CABMB4DW.js +3251 -0
  91. package/dist/cli/monitors-TTD55HMK.mjs +3251 -0
  92. package/dist/cli/org-MSF3RG76.js +849 -0
  93. package/dist/cli/org-SFJ77MWY.mjs +849 -0
  94. package/dist/cli/play-NXHJSCKL.mjs +18439 -0
  95. package/dist/cli/play-OKSFNNO4.js +18439 -0
  96. package/dist/cli/providers-QC2ERERL.js +95 -0
  97. package/dist/cli/providers-TIIAZEUA.mjs +95 -0
  98. package/dist/cli/proxy-env-EBANZHPV.js +161 -0
  99. package/dist/cli/proxy-env-M4ZHXHRL.mjs +161 -0
  100. package/dist/cli/quickstart-ICANHLMI.js +69 -0
  101. package/dist/cli/quickstart-KWUOP3FI.mjs +69 -0
  102. package/dist/cli/search-U5H2FDOO.mjs +18 -0
  103. package/dist/cli/search-XQRQOLWS.js +18 -0
  104. package/dist/cli/secrets-3J6YTWFA.mjs +400 -0
  105. package/dist/cli/secrets-YNMNZNOM.js +400 -0
  106. package/dist/cli/sessions-CLEES4L6.mjs +15 -0
  107. package/dist/cli/sessions-J6VR47FG.js +15 -0
  108. package/dist/cli/settings-EEKZMTY4.js +846 -0
  109. package/dist/cli/settings-UVLOQZRH.mjs +846 -0
  110. package/dist/cli/setup-DLMDXPGJ.mjs +1257 -0
  111. package/dist/cli/setup-HC4Q7QM4.js +1257 -0
  112. package/dist/cli/skills-33PHFBSB.mjs +28 -0
  113. package/dist/cli/skills-LFRY3KPX.js +28 -0
  114. package/dist/cli/tools-3COEPKML.mjs +2955 -0
  115. package/dist/cli/tools-QXEVCN45.js +2955 -0
  116. package/dist/cli/update-LSAC4FF5.mjs +28 -0
  117. package/dist/cli/update-NXHSPYXA.js +28 -0
  118. package/dist/cli/workflow-7S44OECF.mjs +1936 -0
  119. package/dist/cli/workflow-QPZWYSZE.js +1936 -0
  120. package/dist/helpers.js +6 -32
  121. package/dist/helpers.mjs +2 -0
  122. package/dist/index.js +1972 -12825
  123. package/dist/index.mjs +1910 -12672
  124. package/dist/install-integrity.json +110 -0
  125. package/dist/monitor-fleet-contract.js +31 -730
  126. package/dist/monitor-fleet-contract.mjs +18 -667
  127. package/dist/monitor-input-contract.js +10 -390
  128. package/dist/monitor-input-contract.mjs +7 -348
  129. package/dist/plays/bundle-play-file.mjs +13 -5178
  130. package/dist/plays/csv-data-input.js +5 -3132
  131. package/dist/plays/csv-data-input.mjs +5 -3105
  132. package/dist/plays/run-request.js +56 -664
  133. package/dist/plays/run-request.mjs +30 -588
  134. package/dist/release.d.mts +1 -1
  135. package/dist/release.d.ts +1 -1
  136. package/dist/release.js +5 -212
  137. package/dist/release.mjs +5 -185
  138. package/package.json +1 -1
@@ -1,670 +1,21 @@
1
- // ../integration-contracts/monitor-input-contract.ts
2
- import Handlebars from "handlebars";
3
- function authoredMonitorFieldPath(path, field) {
4
- const batch = /^monitors\.(\d+)$/.exec(path);
5
- return `${batch ? `monitors[${batch[1]}]` : path}.${field}`;
6
- }
7
- function record(value) {
8
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9
- }
10
- function json(value, path, issues) {
11
- if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
12
- return;
13
- }
14
- if (Array.isArray(value)) {
15
- value.forEach((child, index) => json(child, `${path}.${index}`, issues));
16
- return;
17
- }
18
- const object = record(value);
19
- if (!object) {
20
- issues.push({
21
- severity: "error",
22
- code: "invalid_monitor_json_value",
23
- path,
24
- message: "Monitor values must be JSON values."
25
- });
26
- return;
27
- }
28
- for (const [key, child] of Object.entries(object)) {
29
- json(child, `${path}.${key}`, issues);
30
- }
31
- }
32
- function monitorSpec(value, path, issues) {
33
- const input = record(value);
34
- if (!input) {
35
- issues.push({
36
- severity: "error",
37
- code: "invalid_monitor_spec",
38
- path,
39
- message: "A monitor must be a JSON object."
40
- });
41
- return null;
42
- }
43
- const allowed = /* @__PURE__ */ new Set(["key", "tool", "name", "payload"]);
44
- for (const key2 of Object.keys(input)) {
45
- if (!allowed.has(key2)) {
46
- if (key2 === "controls") {
47
- issues.push({
48
- severity: "error",
49
- code: "CONTROLS_NOT_SUPPORTED",
50
- path: authoredMonitorFieldPath(path, "controls"),
51
- message: "Operational controls are managed by Deepline and cannot be authored in Batch or Fleet JSON.",
52
- suggestion: "Remove controls. Bind downstream automation in a Play with sqlListeners."
53
- });
54
- continue;
55
- }
56
- if (key2 === "play") {
57
- issues.push({
58
- severity: "error",
59
- code: "PLAY_BINDING_NOT_IN_MONITOR_SPEC",
60
- path: authoredMonitorFieldPath(path, "play"),
61
- message: "A monitor does not own Play bindings.",
62
- suggestion: "Declare sqlListeners in the Play, or run: deepline plays bootstrap monitor-triggered --out on-event.play.ts"
63
- });
64
- continue;
65
- }
66
- issues.push({
67
- severity: "error",
68
- code: "unknown_monitor_field",
69
- path: `${path}.${key2}`,
70
- message: `Monitor definitions do not accept '${key2}'.`
71
- });
72
- }
73
- }
74
- const key = typeof input.key === "string" ? input.key.trim() : "";
75
- const tool = typeof input.tool === "string" ? input.tool.trim() : "";
76
- const name = input.name === void 0 ? void 0 : typeof input.name === "string" && input.name.trim() ? input.name.trim() : null;
77
- const payload = record(input.payload);
78
- if (!key) {
79
- issues.push({
80
- severity: "error",
81
- code: "invalid_monitor_key",
82
- path: `${path}.key`,
83
- message: "Monitor key must be a non-empty string."
84
- });
85
- }
86
- if (!tool) {
87
- issues.push({
88
- severity: "error",
89
- code: "invalid_monitor_tool",
90
- path: `${path}.tool`,
91
- message: "Monitor tool must be a non-empty literal string."
92
- });
93
- }
94
- if (name === null) {
95
- issues.push({
96
- severity: "error",
97
- code: "invalid_monitor_name",
98
- path: `${path}.name`,
99
- message: "Monitor name must be a non-empty string when supplied."
100
- });
101
- }
102
- if (!payload) {
103
- issues.push({
104
- severity: "error",
105
- code: "invalid_monitor_payload",
106
- path: `${path}.payload`,
107
- message: "Monitor payload must be an object."
108
- });
109
- } else {
110
- json(payload, `${path}.payload`, issues);
111
- }
112
- if (!key || !tool || !payload || name === null) {
113
- return null;
114
- }
115
- return {
116
- key,
117
- tool,
118
- ...name ? { name } : {},
119
- payload
120
- };
121
- }
122
- function issueOrder(left, right) {
123
- return left.path.localeCompare(right.path) || left.severity.localeCompare(right.severity) || left.code.localeCompare(right.code);
124
- }
125
- function validateHandlebars(value, path, issues) {
126
- if (!value.includes("{{")) return;
127
- try {
128
- Handlebars.parse(value);
129
- } catch (error) {
130
- issues.push({
131
- severity: "error",
132
- code: "invalid_handlebars_template",
133
- path,
134
- message: error instanceof Error ? error.message : "Invalid Handlebars template."
135
- });
136
- return;
137
- }
138
- const expressions = value.match(/{{[\s\S]*?}}/g) ?? [];
139
- if (expressions.some(
140
- (expression) => !/^{{\s*[A-Za-z_][A-Za-z0-9_]*\s*}}$/.test(expression)
141
- )) {
142
- issues.push({
143
- severity: "error",
144
- code: "unsupported_handlebars_expression",
145
- path,
146
- message: "Fleet templates allow only direct source-row fields such as {{domain}}; helpers, blocks, partials, paths, and prototype access are disabled."
147
- });
148
- }
149
- }
150
- function walkTemplates(value, path, issues) {
151
- if (typeof value === "string") return validateHandlebars(value, path, issues);
152
- if (Array.isArray(value)) {
153
- value.forEach(
154
- (item, index) => walkTemplates(item, `${path}.${index}`, issues)
155
- );
156
- return;
157
- }
158
- const input = record(value);
159
- if (!input) return;
160
- for (const [key, child] of Object.entries(input)) {
161
- walkTemplates(child, `${path}.${key}`, issues);
162
- }
163
- }
164
- function lintMonitorSpecTemplate(value, path = "monitor") {
165
- const issues = [];
166
- const normalized = monitorSpec(value, path, issues);
167
- const input = record(value);
168
- if (input && typeof input.tool === "string" && input.tool.includes("{{")) {
169
- issues.push({
170
- severity: "error",
171
- code: "templated_monitor_tool",
172
- path: `${path}.tool`,
173
- message: "Fleet monitor tool must be literal; only key, name, and payload may be templated."
174
- });
175
- }
176
- if (input) {
177
- for (const field of ["key", "name", "payload"]) {
178
- if (input[field] !== void 0)
179
- walkTemplates(input[field], `${path}.${field}`, issues);
180
- }
181
- }
182
- const ordered = issues.sort(issueOrder);
183
- return ordered.some((issue) => issue.severity === "error") ? { issues: ordered } : { normalized, issues: ordered };
184
- }
185
-
186
- // ../integration-contracts/monitor-fleet-contract.ts
187
- var MONITOR_FLEET_MAX_MEMBERS = 1e3;
188
- var MONITOR_FLEET_FRONTIER_MAX_ROWS = 1e4;
189
- var MONITOR_FLEET_AUTHORING_CONTRACT_EDITION = 2;
190
- var SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS = [
191
- 1,
192
- 2
193
- ];
194
- var MONITOR_FLEET_AUTHORING_CONTRACT_CHANGELOG = [
195
- {
196
- edition: 1,
197
- changed: "Initial Fleet JSON contract: bounded sticky table membership, source refresh, and a seven-day removal grace.",
198
- compatibilityOwner: "Monitors Runtime",
199
- newWritesEnd: null,
200
- readerRemoval: null
201
- },
202
- {
203
- edition: 2,
204
- changed: "Canonical table-backed Fleet envelope with one Handlebars MonitorSpec template.",
205
- compatibilityOwner: "Monitors Runtime",
206
- newWritesEnd: null,
207
- readerRemoval: null
208
- }
209
- ];
210
- var MONITOR_FLEET_REMOVAL_GRACE_MS = 7 * 24 * 60 * 6e4;
211
- var MONITOR_FLEET_DOCUMENTATION = {
212
- summary: "A Monitor Fleet keeps one bounded, sticky set of ordinary monitors aligned with Customer DB rows.",
213
- authoredFields: {
214
- id: "Stable lowercase fleet id used by sync, get, and deactivate.",
215
- source: "Customer DB table, unique row key, and optional equality filters that select candidate rows.",
216
- monitor: "One Batch-compatible MonitorSpec. Direct Handlebars source-row fields such as {{domain}} are rendered for each selected row.",
217
- selection: "Deterministic ranking and an active-member limit between 1 and 1,000."
218
- },
219
- fixedPolicy: {
220
- cadence: "60s fair bounded source refresh",
221
- membership: "sticky",
222
- removalGrace: "7d",
223
- onRemoved: "deactivate",
224
- ownership: "A Fleet may adopt a same-tool ordinary monitor with its deterministic member key. The first Fleet claim wins; another Fleet or a different tool receives a conflict.",
225
- billing: "No Fleet fee, permit, or renewal. Dry-run reports ordinary monitor lifecycle charges due now."
226
- },
227
- stickyMembership: "Ranking fills vacancies but never replaces a current member merely because another row ranks higher.",
228
- templating: "Use direct Handlebars fields such as {{domain}} in monitor key, name, or payload. Helpers, blocks, partials, paths, and prototype access are disabled.",
229
- legacyCompatibility: 'Edition 1 member/$fleet files remain readable with a lint warning; new files should use version: 2, kind: "fleet", and monitor.'
230
- };
231
- function record2(value) {
232
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
233
- }
234
- function identifier(value) {
235
- return typeof value === "string" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
236
- }
237
- function exactKeys(input, keys, path, issues) {
238
- if (!input) return;
239
- for (const key of Object.keys(input)) {
240
- if (keys.includes(key)) continue;
241
- issues.push({
242
- path: path ? `${path}.${key}` : key,
243
- code: "unknown_fleet_field",
244
- message: `${path || "Fleet"} does not accept '${key}'.`
245
- });
246
- }
247
- }
248
- function jsonValue(value, path, issues) {
249
- if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
250
- return;
251
- }
252
- if (Array.isArray(value)) {
253
- value.forEach((item, index) => jsonValue(item, `${path}.${index}`, issues));
254
- return;
255
- }
256
- const input = record2(value);
257
- if (!input) {
258
- issues.push({
259
- path,
260
- code: "invalid_fleet_json_value",
261
- message: "Fleet payload values must be JSON values."
262
- });
263
- return;
264
- }
265
- for (const [key, item] of Object.entries(input)) {
266
- jsonValue(item, `${path}.${key}`, issues);
267
- }
268
- }
269
- function fleetColumn(name) {
270
- if (!identifier(name)) throw new Error(`Invalid fleet column '${name}'.`);
271
- return { $fleet: "column", name };
272
- }
273
- function fleetKey(...parts) {
274
- if (parts.length === 0)
275
- throw new Error("A fleet key needs at least one part.");
276
- return { $fleet: "template", parts };
277
- }
278
- function defineMonitorFleet(definition) {
279
- return definition;
280
- }
281
- function validateExpression(value, path, issues) {
282
- const input = record2(value);
283
- if (!input || input.$fleet !== "column" || !identifier(input.name)) {
284
- issues.push({
285
- path,
286
- code: "invalid_fleet_expression",
287
- message: "Fleet expressions must be an exact tagged column reference."
288
- });
289
- return;
290
- }
291
- exactKeys(input, ["$fleet", "name"], path, issues);
292
- }
293
- function walkPayload(value, path, issues) {
294
- if (Array.isArray(value)) {
295
- value.forEach(
296
- (item, index) => walkPayload(item, `${path}.${index}`, issues)
297
- );
298
- return;
299
- }
300
- const input = record2(value);
301
- if (!input) return;
302
- if ("$fleet" in input) {
303
- validateExpression(input, path, issues);
304
- return;
305
- }
306
- for (const [key, item] of Object.entries(input)) {
307
- walkPayload(item, `${path}.${key}`, issues);
308
- }
309
- }
310
- function validateMonitorFleetDefinitionV1(value) {
311
- const issues = [];
312
- const input = record2(value);
313
- if (!input) {
314
- return {
315
- valid: false,
316
- issues: [
317
- {
318
- path: "",
319
- code: "invalid_fleet",
320
- message: "Fleet must be an object."
321
- }
322
- ]
323
- };
324
- }
325
- exactKeys(input, ["id", "source", "member", "selection"], "", issues);
326
- if (typeof input.id !== "string" || !/^[a-z][a-z0-9-]{0,199}$/.test(input.id)) {
327
- issues.push({
328
- path: "id",
329
- code: "invalid_fleet_id",
330
- message: "Fleet id must be lowercase kebab-case."
331
- });
332
- }
333
- const source = record2(input.source);
334
- exactKeys(
335
- source,
336
- ["kind", "schema", "table", "key", "where"],
337
- "source",
338
- issues
339
- );
340
- if (!source || source.kind !== "customer_db_table") {
341
- issues.push({
342
- path: "source.kind",
343
- code: "invalid_fleet_source",
344
- message: "Beta fleets require customer_db_table."
345
- });
346
- }
347
- if (!identifier(source?.schema) || !identifier(source?.table)) {
348
- issues.push({
349
- path: "source",
350
- code: "invalid_fleet_table",
351
- message: "Source schema and table must be SQL identifiers."
352
- });
353
- }
354
- const sourceKey = record2(source?.key);
355
- exactKeys(sourceKey, ["column", "type"], "source.key", issues);
356
- if (!sourceKey || !identifier(sourceKey.column) || !["text", "uuid", "int4", "int8"].includes(String(sourceKey.type))) {
357
- issues.push({
358
- path: "source.key",
359
- code: "invalid_fleet_source_key",
360
- message: "Source key must name a supported typed column."
361
- });
362
- }
363
- if (source?.where !== void 0) {
364
- const where = record2(source.where);
365
- if (!where) {
366
- issues.push({
367
- path: "source.where",
368
- code: "invalid_fleet_where",
369
- message: "source.where must be an object of equality values."
370
- });
371
- } else {
372
- for (const [column, expected] of Object.entries(where)) {
373
- if (!identifier(column)) {
374
- issues.push({
375
- path: `source.where.${column}`,
376
- code: "invalid_fleet_where_column",
377
- message: "source.where keys must be SQL identifiers."
378
- });
379
- }
380
- if (expected !== null && typeof expected !== "string" && typeof expected !== "boolean" && !(typeof expected === "number" && Number.isFinite(expected))) {
381
- issues.push({
382
- path: `source.where.${column}`,
383
- code: "invalid_fleet_where_value",
384
- message: "source.where values must be finite JSON scalars or null."
385
- });
386
- }
387
- }
388
- }
389
- }
390
- const member = record2(input.member);
391
- exactKeys(member, ["tool", "key", "payload"], "member", issues);
392
- const key = record2(member?.key);
393
- if (!member || typeof member.tool !== "string" || !member.tool.trim()) {
394
- issues.push({
395
- path: "member.tool",
396
- code: "invalid_fleet_tool",
397
- message: "Member tool is required."
398
- });
399
- }
400
- if (!key || key.$fleet !== "template" || !Array.isArray(key.parts) || key.parts.length === 0) {
401
- issues.push({
402
- path: "member.key",
403
- code: "invalid_fleet_key",
404
- message: "Member key must be a tagged fleet template."
405
- });
406
- } else {
407
- exactKeys(key, ["$fleet", "parts"], "member.key", issues);
408
- for (const [index, part] of key.parts.entries()) {
409
- if (typeof part !== "string")
410
- validateExpression(part, `member.key.parts.${index}`, issues);
411
- }
412
- if (sourceKey && !key.parts.some(
413
- (part) => record2(part)?.$fleet === "column" && record2(part)?.name === sourceKey.column
414
- )) {
415
- issues.push({
416
- path: "member.key.parts",
417
- code: "fleet_key_missing_source_key",
418
- message: "Member key must include the source key column."
419
- });
420
- }
421
- }
422
- if (!member || !("payload" in member)) {
423
- issues.push({
424
- path: "member.payload",
425
- code: "invalid_fleet_payload",
426
- message: "Member payload is required."
427
- });
428
- } else {
429
- jsonValue(member.payload, "member.payload", issues);
430
- }
431
- walkPayload(member?.payload, "member.payload", issues);
432
- const selection = record2(input.selection);
433
- exactKeys(selection, ["limit", "orderBy", "membership"], "selection", issues);
434
- if (!selection || !Number.isSafeInteger(selection.limit) || Number(selection.limit) < 1 || Number(selection.limit) > MONITOR_FLEET_MAX_MEMBERS) {
435
- issues.push({
436
- path: "selection.limit",
437
- code: "MONITOR_FLEET_LIMIT_EXCEEDED",
438
- message: "selection.limit must be between 1 and 1,000."
439
- });
440
- }
441
- if (selection?.membership !== "sticky") {
442
- issues.push({
443
- path: "selection.membership",
444
- code: "invalid_fleet_membership",
445
- message: `Fleet membership is fixed to ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.membership}. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership}`
446
- });
447
- }
448
- const orderBy = selection?.orderBy;
449
- if (!Array.isArray(orderBy) || orderBy.length === 0) {
450
- issues.push({
451
- path: "selection.orderBy",
452
- code: "invalid_fleet_order",
453
- message: "At least one deterministic order field is required."
454
- });
455
- } else {
456
- const orderColumns = /* @__PURE__ */ new Set();
457
- for (const [index, order] of orderBy.entries()) {
458
- const item = record2(order);
459
- exactKeys(
460
- item,
461
- ["column", "direction"],
462
- `selection.orderBy.${index}`,
463
- issues
464
- );
465
- if (!item || !identifier(item.column) || !["asc", "desc"].includes(String(item.direction))) {
466
- issues.push({
467
- path: `selection.orderBy.${index}`,
468
- code: "invalid_fleet_order",
469
- message: "Order fields need a column and asc/desc direction."
470
- });
471
- } else if (orderColumns.has(item.column)) {
472
- issues.push({
473
- path: `selection.orderBy.${index}.column`,
474
- code: "duplicate_fleet_order_column",
475
- message: "Each selection order column may appear only once."
476
- });
477
- } else {
478
- orderColumns.add(item.column);
479
- }
480
- }
481
- if (sourceKey && record2(orderBy.at(-1))?.column !== sourceKey.column) {
482
- issues.push({
483
- path: "selection.orderBy",
484
- code: "fleet_order_missing_key",
485
- message: "The final order field must be the source key."
486
- });
487
- }
488
- }
489
- for (const removedOption of ["spendLimits", "lifecycle", "reconciliation"]) {
490
- if (removedOption in input) {
491
- issues.push({
492
- path: removedOption,
493
- code: "unsupported_fleet_option",
494
- message: `${removedOption} is fixed by Monitor Fleets and must be omitted. Fleets sync ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved} members after ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} absent from the source.`
495
- });
496
- }
497
- }
498
- return issues.length === 0 ? { valid: true, definition: value, issues } : { valid: false, issues };
499
- }
500
- function v2Issue(issue) {
501
- return { path: issue.path, code: issue.code, message: issue.message };
502
- }
503
- function validateMonitorFleetDefinitionV2(value) {
504
- const issues = [];
505
- const input = record2(value);
506
- if (!input) {
507
- return {
508
- valid: false,
509
- issues: [
510
- {
511
- path: "",
512
- code: "invalid_fleet",
513
- message: "Fleet must be an object."
514
- }
515
- ]
516
- };
517
- }
518
- exactKeys(
519
- input,
520
- ["version", "kind", "id", "source", "monitor", "selection"],
521
- "",
522
- issues
523
- );
524
- if (input.version !== 2) {
525
- issues.push({
526
- path: "version",
527
- code: "unsupported_fleet_version",
528
- message: "Canonical Fleet input version must be 2."
529
- });
530
- }
531
- if (input.kind !== "fleet") {
532
- issues.push({
533
- path: "kind",
534
- code: "invalid_fleet_kind",
535
- message: 'Canonical Fleet input kind must be "fleet".'
536
- });
537
- }
538
- const source = record2(input.source);
539
- const sourceKey = record2(source?.key);
540
- const legacyShape = {
541
- id: input.id,
542
- source: input.source,
543
- member: {
544
- tool: record2(input.monitor)?.tool,
545
- key: {
546
- $fleet: "template",
547
- parts: [
548
- "fleet-",
549
- {
550
- $fleet: "column",
551
- name: typeof sourceKey?.column === "string" ? sourceKey.column : "invalid_source_key"
552
- }
553
- ]
554
- },
555
- payload: record2(input.monitor)?.payload
556
- },
557
- selection: input.selection
558
- };
559
- const legacyCheck = validateMonitorFleetDefinitionV1(legacyShape);
560
- for (const issue of legacyCheck.issues) {
561
- issues.push({
562
- ...issue,
563
- path: issue.path.replace(/^member\./, "monitor.")
564
- });
565
- }
566
- const monitorInput = record2(input.monitor);
567
- const monitorKey = monitorInput?.key;
568
- const monitor = lintMonitorSpecTemplate(input.monitor);
569
- issues.push(...monitor.issues.map(v2Issue));
570
- if (typeof monitorKey === "string" && typeof sourceKey?.column === "string" && !monitorKey.includes(`{{${sourceKey.column}}}`)) {
571
- issues.push({
572
- path: "monitor.key",
573
- code: "fleet_key_missing_source_key",
574
- message: "Monitor key must include the source key as a direct Handlebars expression."
575
- });
576
- }
577
- return issues.length === 0 && monitor.normalized ? {
578
- valid: true,
579
- definition: {
580
- version: 2,
581
- kind: "fleet",
582
- id: String(input.id),
583
- source: input.source,
584
- monitor: monitor.normalized,
585
- selection: input.selection
586
- },
587
- issues
588
- } : { valid: false, issues };
589
- }
590
- function validateMonitorFleetDefinition(value) {
591
- const input = record2(value);
592
- return input?.version === 2 || input?.kind === "fleet" ? validateMonitorFleetDefinitionV2(value) : validateMonitorFleetDefinitionV1(value);
593
- }
594
- function admitMonitorFleetAuthoringContract(value, edition) {
595
- const detectedEdition = edition ?? (record2(value)?.version === 2 || record2(value)?.kind === "fleet" ? 2 : 1);
596
- if (!SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS.includes(
597
- detectedEdition
598
- )) {
599
- return {
600
- valid: false,
601
- issues: [
602
- {
603
- path: "authoring_contract_edition",
604
- code: "unsupported_fleet_authoring_contract_edition",
605
- message: `Monitor Fleet authoring contract edition ${detectedEdition} is not supported.`
606
- }
607
- ]
608
- };
609
- }
610
- const result = detectedEdition === 2 ? validateMonitorFleetDefinitionV2(value) : validateMonitorFleetDefinitionV1(value);
611
- return result.valid && result.definition ? {
612
- valid: true,
613
- contract: {
614
- edition: detectedEdition,
615
- // JSON cloning prevents later caller mutation from changing the
616
- // admitted snapshot.
617
- definition: JSON.parse(
618
- JSON.stringify(result.definition)
619
- )
620
- },
621
- issues: []
622
- } : { valid: false, issues: result.issues };
623
- }
624
- function lintMonitorFleetInput(value) {
625
- const input = record2(value);
626
- const legacy = input?.member !== void 0;
627
- const admitted = admitMonitorFleetAuthoringContract(value);
628
- const issues = admitted.issues.map((issue) => ({
629
- ...issue,
630
- severity: "error"
631
- }));
632
- if (legacy) {
633
- issues.push({
634
- severity: "warning",
635
- code: "deprecated_fleet_member",
636
- path: "member",
637
- message: "Legacy Fleet member syntax remains supported."
638
- });
639
- if (JSON.stringify(input).includes('"$fleet"')) {
640
- issues.push({
641
- severity: "warning",
642
- code: "deprecated_fleet_expression",
643
- path: "member",
644
- message: "Legacy $fleet expressions remain supported; use direct Handlebars fields in monitor instead."
645
- });
646
- }
647
- }
648
- return admitted.valid && admitted.contract ? { normalized: admitted.contract.definition, issues } : { issues };
649
- }
650
- function evaluateMonitorFleetValue(value, row) {
651
- if (Array.isArray(value))
652
- return value.map((item) => evaluateMonitorFleetValue(item, row));
653
- const input = record2(value);
654
- if (!input) return value;
655
- if (input.$fleet === "column") return row[String(input.name)];
656
- if (input.$fleet === "template" && Array.isArray(input.parts)) {
657
- return input.parts.map(
658
- (part) => typeof part === "string" ? part : String(evaluateMonitorFleetValue(part, row) ?? "")
659
- ).join("");
660
- }
661
- return Object.fromEntries(
662
- Object.entries(input).map(([key, item]) => [
663
- key,
664
- evaluateMonitorFleetValue(item, row)
665
- ])
666
- );
667
- }
1
+ import {
2
+ MONITOR_FLEET_AUTHORING_CONTRACT_CHANGELOG,
3
+ MONITOR_FLEET_AUTHORING_CONTRACT_EDITION,
4
+ MONITOR_FLEET_DOCUMENTATION,
5
+ MONITOR_FLEET_FRONTIER_MAX_ROWS,
6
+ MONITOR_FLEET_MAX_MEMBERS,
7
+ MONITOR_FLEET_REMOVAL_GRACE_MS,
8
+ SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS,
9
+ admitMonitorFleetAuthoringContract,
10
+ defineMonitorFleet,
11
+ evaluateMonitorFleetValue,
12
+ fleetColumn,
13
+ fleetKey,
14
+ lintMonitorFleetInput,
15
+ validateMonitorFleetDefinition
16
+ } from "./cli/chunk-HUZXWOSK.mjs";
17
+ import "./cli/chunk-TAC3JIFE.mjs";
18
+ import "./cli/chunk-KRD6H754.mjs";
668
19
  export {
669
20
  MONITOR_FLEET_AUTHORING_CONTRACT_CHANGELOG,
670
21
  MONITOR_FLEET_AUTHORING_CONTRACT_EDITION,