deepline 0.3.294 → 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.
- package/dist/bundling-sources/sdk/src/compat.ts +35 -7
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +14 -1
- package/dist/cli/auth-EDTRERZP.mjs +31 -0
- package/dist/cli/auth-TDHKB277.js +31 -0
- package/dist/cli/billing-ELIDPILY.js +1749 -0
- package/dist/cli/billing-EXGXJVAU.mjs +1749 -0
- package/dist/cli/chunk-2S5Y3TZP.js +5688 -0
- package/dist/cli/chunk-3KC45UVF.js +150 -0
- package/dist/cli/chunk-3XX5TEA4.js +15 -0
- package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
- package/dist/cli/chunk-4NEFYBF7.js +2240 -0
- package/dist/cli/chunk-5JLQPVNX.js +3056 -0
- package/dist/cli/chunk-5KDKFHZI.js +1269 -0
- package/dist/cli/chunk-6A3TJUWC.js +76 -0
- package/dist/cli/chunk-6O5YZOVN.mjs +890 -0
- package/dist/cli/chunk-7P5AA3SN.js +344 -0
- package/dist/cli/chunk-AYHLUHE5.js +52 -0
- package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
- package/dist/cli/chunk-CFVVCN4A.js +735 -0
- package/dist/cli/chunk-COGTRVWW.js +30 -0
- package/dist/cli/chunk-D4AZUZO4.js +190 -0
- package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
- package/dist/cli/chunk-EACVZI6N.mjs +1995 -0
- package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
- package/dist/cli/chunk-EXMLR72R.mjs +0 -0
- package/dist/cli/chunk-F35VOIQL.js +890 -0
- package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
- package/dist/cli/chunk-GHRQQPW2.mjs +2240 -0
- package/dist/cli/chunk-GONRLVV3.js +3440 -0
- package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
- package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
- package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
- package/dist/cli/chunk-I5YZLGMG.js +1 -0
- package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
- package/dist/cli/chunk-J5NA2TTX.js +503 -0
- package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
- package/dist/cli/chunk-JNNOCMQY.js +47 -0
- package/dist/cli/chunk-KRD6H754.mjs +30 -0
- package/dist/cli/chunk-LA46MMTL.js +560 -0
- package/dist/cli/chunk-LDWT7RJK.mjs +190 -0
- package/dist/cli/chunk-M2V26OR5.js +499 -0
- package/dist/cli/chunk-MIMASXO4.mjs +389 -0
- package/dist/cli/chunk-MROPCKW2.mjs +190 -0
- package/dist/cli/chunk-NXDRDJ4K.js +389 -0
- package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
- package/dist/cli/chunk-OG64RBAC.js +6 -0
- package/dist/cli/chunk-OQYEC4GL.mjs +34 -0
- package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
- package/dist/cli/chunk-SDK3ZA2C.js +103 -0
- package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
- package/dist/cli/chunk-SVIIIYIQ.js +923 -0
- package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
- package/dist/cli/chunk-U3PI7HBM.js +34 -0
- package/dist/cli/chunk-UFS752TU.mjs +52 -0
- package/dist/cli/chunk-UI37DQE7.mjs +499 -0
- package/dist/cli/chunk-UNEMDKXN.js +1 -0
- package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
- package/dist/cli/chunk-WJYPBHTE.js +148 -0
- package/dist/cli/chunk-WOHBA5PV.js +354 -0
- package/dist/cli/chunk-WQICC2B3.js +190 -0
- package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
- package/dist/cli/chunk-XL2FO6CW.mjs +5688 -0
- package/dist/cli/chunk-XNYIZMNQ.js +28 -0
- package/dist/cli/chunk-XRK2TZT5.js +1995 -0
- package/dist/cli/chunk-YJYPL5OK.mjs +1269 -0
- package/dist/cli/chunk-YWNDYCXR.mjs +735 -0
- package/dist/cli/chunk-YWWAF7KZ.mjs +923 -0
- package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
- package/dist/cli/client-4JVOYVC5.js +20 -0
- package/dist/cli/client-EEN2IJN2.mjs +20 -0
- package/dist/cli/csv-BOHBEP2I.mjs +585 -0
- package/dist/cli/csv-S5NYRUEX.js +585 -0
- package/dist/cli/db-CLODWCOB.mjs +486 -0
- package/dist/cli/db-F6PKFOOV.js +486 -0
- package/dist/cli/executions-5TQAKLJU.js +28 -0
- package/dist/cli/executions-MAKW6QOY.mjs +28 -0
- package/dist/cli/feedback-GV4QJFEN.js +107 -0
- package/dist/cli/feedback-XY24TW7H.mjs +107 -0
- package/dist/cli/getting-started.js +18 -76
- package/dist/cli/getting-started.mjs +10 -37
- package/dist/cli/git-6S2C22T5.js +23 -0
- package/dist/cli/git-OZLBD5HH.mjs +23 -0
- package/dist/cli/index.js +291 -54294
- package/dist/cli/index.mjs +209 -54352
- package/dist/cli/legacy-noops-LLCGDPQE.js +157 -0
- package/dist/cli/legacy-noops-TYH3TW2D.mjs +157 -0
- package/dist/cli/monitors-CABMB4DW.js +3251 -0
- package/dist/cli/monitors-TTD55HMK.mjs +3251 -0
- package/dist/cli/org-MSF3RG76.js +849 -0
- package/dist/cli/org-SFJ77MWY.mjs +849 -0
- package/dist/cli/play-NXHJSCKL.mjs +18439 -0
- package/dist/cli/play-OKSFNNO4.js +18439 -0
- package/dist/cli/providers-QC2ERERL.js +95 -0
- package/dist/cli/providers-TIIAZEUA.mjs +95 -0
- package/dist/cli/proxy-env-EBANZHPV.js +161 -0
- package/dist/cli/proxy-env-M4ZHXHRL.mjs +161 -0
- package/dist/cli/quickstart-ICANHLMI.js +69 -0
- package/dist/cli/quickstart-KWUOP3FI.mjs +69 -0
- package/dist/cli/search-U5H2FDOO.mjs +18 -0
- package/dist/cli/search-XQRQOLWS.js +18 -0
- package/dist/cli/secrets-3J6YTWFA.mjs +400 -0
- package/dist/cli/secrets-YNMNZNOM.js +400 -0
- package/dist/cli/sessions-CLEES4L6.mjs +15 -0
- package/dist/cli/sessions-J6VR47FG.js +15 -0
- package/dist/cli/settings-EEKZMTY4.js +846 -0
- package/dist/cli/settings-UVLOQZRH.mjs +846 -0
- package/dist/cli/setup-DLMDXPGJ.mjs +1257 -0
- package/dist/cli/setup-HC4Q7QM4.js +1257 -0
- package/dist/cli/skills-33PHFBSB.mjs +28 -0
- package/dist/cli/skills-LFRY3KPX.js +28 -0
- package/dist/cli/tools-3COEPKML.mjs +2955 -0
- package/dist/cli/tools-QXEVCN45.js +2955 -0
- package/dist/cli/update-LSAC4FF5.mjs +28 -0
- package/dist/cli/update-NXHSPYXA.js +28 -0
- package/dist/cli/workflow-7S44OECF.mjs +1936 -0
- package/dist/cli/workflow-QPZWYSZE.js +1936 -0
- package/dist/helpers.js +6 -32
- package/dist/helpers.mjs +2 -0
- package/dist/index.js +1972 -12825
- package/dist/index.mjs +1910 -12672
- package/dist/install-integrity.json +110 -0
- package/dist/monitor-fleet-contract.js +31 -730
- package/dist/monitor-fleet-contract.mjs +18 -667
- package/dist/monitor-input-contract.js +10 -390
- package/dist/monitor-input-contract.mjs +7 -348
- package/dist/plays/bundle-play-file.mjs +13 -5178
- package/dist/plays/csv-data-input.js +5 -3132
- package/dist/plays/csv-data-input.mjs +5 -3105
- package/dist/plays/run-request.js +56 -664
- package/dist/plays/run-request.mjs +30 -588
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +5 -212
- package/dist/release.mjs +5 -185
- package/package.json +1 -1
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lintMonitorSpecTemplate
|
|
3
|
+
} from "./chunk-TAC3JIFE.mjs";
|
|
4
|
+
|
|
5
|
+
// ../integration-contracts/monitor-fleet-contract.ts
|
|
6
|
+
var MONITOR_FLEET_MAX_MEMBERS = 1e3;
|
|
7
|
+
var MONITOR_FLEET_FRONTIER_MAX_ROWS = 1e4;
|
|
8
|
+
var MONITOR_FLEET_AUTHORING_CONTRACT_EDITION = 2;
|
|
9
|
+
var SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS = [
|
|
10
|
+
1,
|
|
11
|
+
2
|
|
12
|
+
];
|
|
13
|
+
var MONITOR_FLEET_AUTHORING_CONTRACT_CHANGELOG = [
|
|
14
|
+
{
|
|
15
|
+
edition: 1,
|
|
16
|
+
changed: "Initial Fleet JSON contract: bounded sticky table membership, source refresh, and a seven-day removal grace.",
|
|
17
|
+
compatibilityOwner: "Monitors Runtime",
|
|
18
|
+
newWritesEnd: null,
|
|
19
|
+
readerRemoval: null
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
edition: 2,
|
|
23
|
+
changed: "Canonical table-backed Fleet envelope with one Handlebars MonitorSpec template.",
|
|
24
|
+
compatibilityOwner: "Monitors Runtime",
|
|
25
|
+
newWritesEnd: null,
|
|
26
|
+
readerRemoval: null
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
var MONITOR_FLEET_REMOVAL_GRACE_MS = 7 * 24 * 60 * 6e4;
|
|
30
|
+
var MONITOR_FLEET_DOCUMENTATION = {
|
|
31
|
+
summary: "A Monitor Fleet keeps one bounded, sticky set of ordinary monitors aligned with Customer DB rows.",
|
|
32
|
+
authoredFields: {
|
|
33
|
+
id: "Stable lowercase fleet id used by sync, get, and deactivate.",
|
|
34
|
+
source: "Customer DB table, unique row key, and optional equality filters that select candidate rows.",
|
|
35
|
+
monitor: "One Batch-compatible MonitorSpec. Direct Handlebars source-row fields such as {{domain}} are rendered for each selected row.",
|
|
36
|
+
selection: "Deterministic ranking and an active-member limit between 1 and 1,000."
|
|
37
|
+
},
|
|
38
|
+
fixedPolicy: {
|
|
39
|
+
cadence: "60s fair bounded source refresh",
|
|
40
|
+
membership: "sticky",
|
|
41
|
+
removalGrace: "7d",
|
|
42
|
+
onRemoved: "deactivate",
|
|
43
|
+
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.",
|
|
44
|
+
billing: "No Fleet fee, permit, or renewal. Dry-run reports ordinary monitor lifecycle charges due now."
|
|
45
|
+
},
|
|
46
|
+
stickyMembership: "Ranking fills vacancies but never replaces a current member merely because another row ranks higher.",
|
|
47
|
+
templating: "Use direct Handlebars fields such as {{domain}} in monitor key, name, or payload. Helpers, blocks, partials, paths, and prototype access are disabled.",
|
|
48
|
+
legacyCompatibility: 'Edition 1 member/$fleet files remain readable with a lint warning; new files should use version: 2, kind: "fleet", and monitor.'
|
|
49
|
+
};
|
|
50
|
+
function record(value) {
|
|
51
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
52
|
+
}
|
|
53
|
+
function identifier(value) {
|
|
54
|
+
return typeof value === "string" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
55
|
+
}
|
|
56
|
+
function exactKeys(input, keys, path, issues) {
|
|
57
|
+
if (!input) return;
|
|
58
|
+
for (const key of Object.keys(input)) {
|
|
59
|
+
if (keys.includes(key)) continue;
|
|
60
|
+
issues.push({
|
|
61
|
+
path: path ? `${path}.${key}` : key,
|
|
62
|
+
code: "unknown_fleet_field",
|
|
63
|
+
message: `${path || "Fleet"} does not accept '${key}'.`
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function jsonValue(value, path, issues) {
|
|
68
|
+
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
value.forEach((item, index) => jsonValue(item, `${path}.${index}`, issues));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const input = record(value);
|
|
76
|
+
if (!input) {
|
|
77
|
+
issues.push({
|
|
78
|
+
path,
|
|
79
|
+
code: "invalid_fleet_json_value",
|
|
80
|
+
message: "Fleet payload values must be JSON values."
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const [key, item] of Object.entries(input)) {
|
|
85
|
+
jsonValue(item, `${path}.${key}`, issues);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function fleetColumn(name) {
|
|
89
|
+
if (!identifier(name)) throw new Error(`Invalid fleet column '${name}'.`);
|
|
90
|
+
return { $fleet: "column", name };
|
|
91
|
+
}
|
|
92
|
+
function fleetKey(...parts) {
|
|
93
|
+
if (parts.length === 0)
|
|
94
|
+
throw new Error("A fleet key needs at least one part.");
|
|
95
|
+
return { $fleet: "template", parts };
|
|
96
|
+
}
|
|
97
|
+
function defineMonitorFleet(definition) {
|
|
98
|
+
return definition;
|
|
99
|
+
}
|
|
100
|
+
function validateExpression(value, path, issues) {
|
|
101
|
+
const input = record(value);
|
|
102
|
+
if (!input || input.$fleet !== "column" || !identifier(input.name)) {
|
|
103
|
+
issues.push({
|
|
104
|
+
path,
|
|
105
|
+
code: "invalid_fleet_expression",
|
|
106
|
+
message: "Fleet expressions must be an exact tagged column reference."
|
|
107
|
+
});
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
exactKeys(input, ["$fleet", "name"], path, issues);
|
|
111
|
+
}
|
|
112
|
+
function walkPayload(value, path, issues) {
|
|
113
|
+
if (Array.isArray(value)) {
|
|
114
|
+
value.forEach(
|
|
115
|
+
(item, index) => walkPayload(item, `${path}.${index}`, issues)
|
|
116
|
+
);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const input = record(value);
|
|
120
|
+
if (!input) return;
|
|
121
|
+
if ("$fleet" in input) {
|
|
122
|
+
validateExpression(input, path, issues);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
for (const [key, item] of Object.entries(input)) {
|
|
126
|
+
walkPayload(item, `${path}.${key}`, issues);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function validateMonitorFleetDefinitionV1(value) {
|
|
130
|
+
const issues = [];
|
|
131
|
+
const input = record(value);
|
|
132
|
+
if (!input) {
|
|
133
|
+
return {
|
|
134
|
+
valid: false,
|
|
135
|
+
issues: [
|
|
136
|
+
{
|
|
137
|
+
path: "",
|
|
138
|
+
code: "invalid_fleet",
|
|
139
|
+
message: "Fleet must be an object."
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
exactKeys(input, ["id", "source", "member", "selection"], "", issues);
|
|
145
|
+
if (typeof input.id !== "string" || !/^[a-z][a-z0-9-]{0,199}$/.test(input.id)) {
|
|
146
|
+
issues.push({
|
|
147
|
+
path: "id",
|
|
148
|
+
code: "invalid_fleet_id",
|
|
149
|
+
message: "Fleet id must be lowercase kebab-case."
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const source = record(input.source);
|
|
153
|
+
exactKeys(
|
|
154
|
+
source,
|
|
155
|
+
["kind", "schema", "table", "key", "where"],
|
|
156
|
+
"source",
|
|
157
|
+
issues
|
|
158
|
+
);
|
|
159
|
+
if (!source || source.kind !== "customer_db_table") {
|
|
160
|
+
issues.push({
|
|
161
|
+
path: "source.kind",
|
|
162
|
+
code: "invalid_fleet_source",
|
|
163
|
+
message: "Beta fleets require customer_db_table."
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (!identifier(source?.schema) || !identifier(source?.table)) {
|
|
167
|
+
issues.push({
|
|
168
|
+
path: "source",
|
|
169
|
+
code: "invalid_fleet_table",
|
|
170
|
+
message: "Source schema and table must be SQL identifiers."
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
const sourceKey = record(source?.key);
|
|
174
|
+
exactKeys(sourceKey, ["column", "type"], "source.key", issues);
|
|
175
|
+
if (!sourceKey || !identifier(sourceKey.column) || !["text", "uuid", "int4", "int8"].includes(String(sourceKey.type))) {
|
|
176
|
+
issues.push({
|
|
177
|
+
path: "source.key",
|
|
178
|
+
code: "invalid_fleet_source_key",
|
|
179
|
+
message: "Source key must name a supported typed column."
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (source?.where !== void 0) {
|
|
183
|
+
const where = record(source.where);
|
|
184
|
+
if (!where) {
|
|
185
|
+
issues.push({
|
|
186
|
+
path: "source.where",
|
|
187
|
+
code: "invalid_fleet_where",
|
|
188
|
+
message: "source.where must be an object of equality values."
|
|
189
|
+
});
|
|
190
|
+
} else {
|
|
191
|
+
for (const [column, expected] of Object.entries(where)) {
|
|
192
|
+
if (!identifier(column)) {
|
|
193
|
+
issues.push({
|
|
194
|
+
path: `source.where.${column}`,
|
|
195
|
+
code: "invalid_fleet_where_column",
|
|
196
|
+
message: "source.where keys must be SQL identifiers."
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (expected !== null && typeof expected !== "string" && typeof expected !== "boolean" && !(typeof expected === "number" && Number.isFinite(expected))) {
|
|
200
|
+
issues.push({
|
|
201
|
+
path: `source.where.${column}`,
|
|
202
|
+
code: "invalid_fleet_where_value",
|
|
203
|
+
message: "source.where values must be finite JSON scalars or null."
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const member = record(input.member);
|
|
210
|
+
exactKeys(member, ["tool", "key", "payload"], "member", issues);
|
|
211
|
+
const key = record(member?.key);
|
|
212
|
+
if (!member || typeof member.tool !== "string" || !member.tool.trim()) {
|
|
213
|
+
issues.push({
|
|
214
|
+
path: "member.tool",
|
|
215
|
+
code: "invalid_fleet_tool",
|
|
216
|
+
message: "Member tool is required."
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (!key || key.$fleet !== "template" || !Array.isArray(key.parts) || key.parts.length === 0) {
|
|
220
|
+
issues.push({
|
|
221
|
+
path: "member.key",
|
|
222
|
+
code: "invalid_fleet_key",
|
|
223
|
+
message: "Member key must be a tagged fleet template."
|
|
224
|
+
});
|
|
225
|
+
} else {
|
|
226
|
+
exactKeys(key, ["$fleet", "parts"], "member.key", issues);
|
|
227
|
+
for (const [index, part] of key.parts.entries()) {
|
|
228
|
+
if (typeof part !== "string")
|
|
229
|
+
validateExpression(part, `member.key.parts.${index}`, issues);
|
|
230
|
+
}
|
|
231
|
+
if (sourceKey && !key.parts.some(
|
|
232
|
+
(part) => record(part)?.$fleet === "column" && record(part)?.name === sourceKey.column
|
|
233
|
+
)) {
|
|
234
|
+
issues.push({
|
|
235
|
+
path: "member.key.parts",
|
|
236
|
+
code: "fleet_key_missing_source_key",
|
|
237
|
+
message: "Member key must include the source key column."
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!member || !("payload" in member)) {
|
|
242
|
+
issues.push({
|
|
243
|
+
path: "member.payload",
|
|
244
|
+
code: "invalid_fleet_payload",
|
|
245
|
+
message: "Member payload is required."
|
|
246
|
+
});
|
|
247
|
+
} else {
|
|
248
|
+
jsonValue(member.payload, "member.payload", issues);
|
|
249
|
+
}
|
|
250
|
+
walkPayload(member?.payload, "member.payload", issues);
|
|
251
|
+
const selection = record(input.selection);
|
|
252
|
+
exactKeys(selection, ["limit", "orderBy", "membership"], "selection", issues);
|
|
253
|
+
if (!selection || !Number.isSafeInteger(selection.limit) || Number(selection.limit) < 1 || Number(selection.limit) > MONITOR_FLEET_MAX_MEMBERS) {
|
|
254
|
+
issues.push({
|
|
255
|
+
path: "selection.limit",
|
|
256
|
+
code: "MONITOR_FLEET_LIMIT_EXCEEDED",
|
|
257
|
+
message: "selection.limit must be between 1 and 1,000."
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (selection?.membership !== "sticky") {
|
|
261
|
+
issues.push({
|
|
262
|
+
path: "selection.membership",
|
|
263
|
+
code: "invalid_fleet_membership",
|
|
264
|
+
message: `Fleet membership is fixed to ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.membership}. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership}`
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
const orderBy = selection?.orderBy;
|
|
268
|
+
if (!Array.isArray(orderBy) || orderBy.length === 0) {
|
|
269
|
+
issues.push({
|
|
270
|
+
path: "selection.orderBy",
|
|
271
|
+
code: "invalid_fleet_order",
|
|
272
|
+
message: "At least one deterministic order field is required."
|
|
273
|
+
});
|
|
274
|
+
} else {
|
|
275
|
+
const orderColumns = /* @__PURE__ */ new Set();
|
|
276
|
+
for (const [index, order] of orderBy.entries()) {
|
|
277
|
+
const item = record(order);
|
|
278
|
+
exactKeys(
|
|
279
|
+
item,
|
|
280
|
+
["column", "direction"],
|
|
281
|
+
`selection.orderBy.${index}`,
|
|
282
|
+
issues
|
|
283
|
+
);
|
|
284
|
+
if (!item || !identifier(item.column) || !["asc", "desc"].includes(String(item.direction))) {
|
|
285
|
+
issues.push({
|
|
286
|
+
path: `selection.orderBy.${index}`,
|
|
287
|
+
code: "invalid_fleet_order",
|
|
288
|
+
message: "Order fields need a column and asc/desc direction."
|
|
289
|
+
});
|
|
290
|
+
} else if (orderColumns.has(item.column)) {
|
|
291
|
+
issues.push({
|
|
292
|
+
path: `selection.orderBy.${index}.column`,
|
|
293
|
+
code: "duplicate_fleet_order_column",
|
|
294
|
+
message: "Each selection order column may appear only once."
|
|
295
|
+
});
|
|
296
|
+
} else {
|
|
297
|
+
orderColumns.add(item.column);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (sourceKey && record(orderBy.at(-1))?.column !== sourceKey.column) {
|
|
301
|
+
issues.push({
|
|
302
|
+
path: "selection.orderBy",
|
|
303
|
+
code: "fleet_order_missing_key",
|
|
304
|
+
message: "The final order field must be the source key."
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
for (const removedOption of ["spendLimits", "lifecycle", "reconciliation"]) {
|
|
309
|
+
if (removedOption in input) {
|
|
310
|
+
issues.push({
|
|
311
|
+
path: removedOption,
|
|
312
|
+
code: "unsupported_fleet_option",
|
|
313
|
+
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.`
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return issues.length === 0 ? { valid: true, definition: value, issues } : { valid: false, issues };
|
|
318
|
+
}
|
|
319
|
+
function v2Issue(issue) {
|
|
320
|
+
return { path: issue.path, code: issue.code, message: issue.message };
|
|
321
|
+
}
|
|
322
|
+
function validateMonitorFleetDefinitionV2(value) {
|
|
323
|
+
const issues = [];
|
|
324
|
+
const input = record(value);
|
|
325
|
+
if (!input) {
|
|
326
|
+
return {
|
|
327
|
+
valid: false,
|
|
328
|
+
issues: [
|
|
329
|
+
{
|
|
330
|
+
path: "",
|
|
331
|
+
code: "invalid_fleet",
|
|
332
|
+
message: "Fleet must be an object."
|
|
333
|
+
}
|
|
334
|
+
]
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
exactKeys(
|
|
338
|
+
input,
|
|
339
|
+
["version", "kind", "id", "source", "monitor", "selection"],
|
|
340
|
+
"",
|
|
341
|
+
issues
|
|
342
|
+
);
|
|
343
|
+
if (input.version !== 2) {
|
|
344
|
+
issues.push({
|
|
345
|
+
path: "version",
|
|
346
|
+
code: "unsupported_fleet_version",
|
|
347
|
+
message: "Canonical Fleet input version must be 2."
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
if (input.kind !== "fleet") {
|
|
351
|
+
issues.push({
|
|
352
|
+
path: "kind",
|
|
353
|
+
code: "invalid_fleet_kind",
|
|
354
|
+
message: 'Canonical Fleet input kind must be "fleet".'
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
const source = record(input.source);
|
|
358
|
+
const sourceKey = record(source?.key);
|
|
359
|
+
const legacyShape = {
|
|
360
|
+
id: input.id,
|
|
361
|
+
source: input.source,
|
|
362
|
+
member: {
|
|
363
|
+
tool: record(input.monitor)?.tool,
|
|
364
|
+
key: {
|
|
365
|
+
$fleet: "template",
|
|
366
|
+
parts: [
|
|
367
|
+
"fleet-",
|
|
368
|
+
{
|
|
369
|
+
$fleet: "column",
|
|
370
|
+
name: typeof sourceKey?.column === "string" ? sourceKey.column : "invalid_source_key"
|
|
371
|
+
}
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
payload: record(input.monitor)?.payload
|
|
375
|
+
},
|
|
376
|
+
selection: input.selection
|
|
377
|
+
};
|
|
378
|
+
const legacyCheck = validateMonitorFleetDefinitionV1(legacyShape);
|
|
379
|
+
for (const issue of legacyCheck.issues) {
|
|
380
|
+
issues.push({
|
|
381
|
+
...issue,
|
|
382
|
+
path: issue.path.replace(/^member\./, "monitor.")
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
const monitorInput = record(input.monitor);
|
|
386
|
+
const monitorKey = monitorInput?.key;
|
|
387
|
+
const monitor = lintMonitorSpecTemplate(input.monitor);
|
|
388
|
+
issues.push(...monitor.issues.map(v2Issue));
|
|
389
|
+
if (typeof monitorKey === "string" && typeof sourceKey?.column === "string" && !monitorKey.includes(`{{${sourceKey.column}}}`)) {
|
|
390
|
+
issues.push({
|
|
391
|
+
path: "monitor.key",
|
|
392
|
+
code: "fleet_key_missing_source_key",
|
|
393
|
+
message: "Monitor key must include the source key as a direct Handlebars expression."
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return issues.length === 0 && monitor.normalized ? {
|
|
397
|
+
valid: true,
|
|
398
|
+
definition: {
|
|
399
|
+
version: 2,
|
|
400
|
+
kind: "fleet",
|
|
401
|
+
id: String(input.id),
|
|
402
|
+
source: input.source,
|
|
403
|
+
monitor: monitor.normalized,
|
|
404
|
+
selection: input.selection
|
|
405
|
+
},
|
|
406
|
+
issues
|
|
407
|
+
} : { valid: false, issues };
|
|
408
|
+
}
|
|
409
|
+
function validateMonitorFleetDefinition(value) {
|
|
410
|
+
const input = record(value);
|
|
411
|
+
return input?.version === 2 || input?.kind === "fleet" ? validateMonitorFleetDefinitionV2(value) : validateMonitorFleetDefinitionV1(value);
|
|
412
|
+
}
|
|
413
|
+
function admitMonitorFleetAuthoringContract(value, edition) {
|
|
414
|
+
const detectedEdition = edition ?? (record(value)?.version === 2 || record(value)?.kind === "fleet" ? 2 : 1);
|
|
415
|
+
if (!SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS.includes(
|
|
416
|
+
detectedEdition
|
|
417
|
+
)) {
|
|
418
|
+
return {
|
|
419
|
+
valid: false,
|
|
420
|
+
issues: [
|
|
421
|
+
{
|
|
422
|
+
path: "authoring_contract_edition",
|
|
423
|
+
code: "unsupported_fleet_authoring_contract_edition",
|
|
424
|
+
message: `Monitor Fleet authoring contract edition ${detectedEdition} is not supported.`
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
const result = detectedEdition === 2 ? validateMonitorFleetDefinitionV2(value) : validateMonitorFleetDefinitionV1(value);
|
|
430
|
+
return result.valid && result.definition ? {
|
|
431
|
+
valid: true,
|
|
432
|
+
contract: {
|
|
433
|
+
edition: detectedEdition,
|
|
434
|
+
// JSON cloning prevents later caller mutation from changing the
|
|
435
|
+
// admitted snapshot.
|
|
436
|
+
definition: JSON.parse(
|
|
437
|
+
JSON.stringify(result.definition)
|
|
438
|
+
)
|
|
439
|
+
},
|
|
440
|
+
issues: []
|
|
441
|
+
} : { valid: false, issues: result.issues };
|
|
442
|
+
}
|
|
443
|
+
function lintMonitorFleetInput(value) {
|
|
444
|
+
const input = record(value);
|
|
445
|
+
const legacy = input?.member !== void 0;
|
|
446
|
+
const admitted = admitMonitorFleetAuthoringContract(value);
|
|
447
|
+
const issues = admitted.issues.map((issue) => ({
|
|
448
|
+
...issue,
|
|
449
|
+
severity: "error"
|
|
450
|
+
}));
|
|
451
|
+
if (legacy) {
|
|
452
|
+
issues.push({
|
|
453
|
+
severity: "warning",
|
|
454
|
+
code: "deprecated_fleet_member",
|
|
455
|
+
path: "member",
|
|
456
|
+
message: "Legacy Fleet member syntax remains supported."
|
|
457
|
+
});
|
|
458
|
+
if (JSON.stringify(input).includes('"$fleet"')) {
|
|
459
|
+
issues.push({
|
|
460
|
+
severity: "warning",
|
|
461
|
+
code: "deprecated_fleet_expression",
|
|
462
|
+
path: "member",
|
|
463
|
+
message: "Legacy $fleet expressions remain supported; use direct Handlebars fields in monitor instead."
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return admitted.valid && admitted.contract ? { normalized: admitted.contract.definition, issues } : { issues };
|
|
468
|
+
}
|
|
469
|
+
function evaluateMonitorFleetValue(value, row) {
|
|
470
|
+
if (Array.isArray(value))
|
|
471
|
+
return value.map((item) => evaluateMonitorFleetValue(item, row));
|
|
472
|
+
const input = record(value);
|
|
473
|
+
if (!input) return value;
|
|
474
|
+
if (input.$fleet === "column") return row[String(input.name)];
|
|
475
|
+
if (input.$fleet === "template" && Array.isArray(input.parts)) {
|
|
476
|
+
return input.parts.map(
|
|
477
|
+
(part) => typeof part === "string" ? part : String(evaluateMonitorFleetValue(part, row) ?? "")
|
|
478
|
+
).join("");
|
|
479
|
+
}
|
|
480
|
+
return Object.fromEntries(
|
|
481
|
+
Object.entries(input).map(([key, item]) => [
|
|
482
|
+
key,
|
|
483
|
+
evaluateMonitorFleetValue(item, row)
|
|
484
|
+
])
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export {
|
|
489
|
+
MONITOR_FLEET_MAX_MEMBERS,
|
|
490
|
+
MONITOR_FLEET_FRONTIER_MAX_ROWS,
|
|
491
|
+
MONITOR_FLEET_AUTHORING_CONTRACT_EDITION,
|
|
492
|
+
SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS,
|
|
493
|
+
MONITOR_FLEET_AUTHORING_CONTRACT_CHANGELOG,
|
|
494
|
+
MONITOR_FLEET_REMOVAL_GRACE_MS,
|
|
495
|
+
MONITOR_FLEET_DOCUMENTATION,
|
|
496
|
+
fleetColumn,
|
|
497
|
+
fleetKey,
|
|
498
|
+
defineMonitorFleet,
|
|
499
|
+
validateMonitorFleetDefinition,
|
|
500
|
+
admitMonitorFleetAuthoringContract,
|
|
501
|
+
lintMonitorFleetInput,
|
|
502
|
+
evaluateMonitorFleetValue
|
|
503
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ../plays/enrich-compat-adapter.ts
|
|
2
|
+
var ENRICH_COMPAT_DEFAULT_PLAY_NAME = "deepline-enrich-v1-compat";
|
|
3
|
+
var ENRICH_COMPAT_DEFAULT_MAP_NAME = "deepline_enrich_rows";
|
|
4
|
+
var ENRICH_COMMAND_DEPRECATION_MESSAGE = "The `deepline enrich` command is deprecated. Deepline Plays gives much better results. Run `deepline plays --help` to get started. If you still need the legacy command, submit feedback explaining why.";
|
|
5
|
+
function buildEnrichCompatibilityPlan(options = {}) {
|
|
6
|
+
return {
|
|
7
|
+
playName: options.playName?.trim() || ENRICH_COMPAT_DEFAULT_PLAY_NAME,
|
|
8
|
+
mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
ENRICH_COMMAND_DEPRECATION_MESSAGE,
|
|
14
|
+
buildEnrichCompatibilityPlan
|
|
15
|
+
};
|