@grafana/plugin-ui 0.15.1 → 0.16.0-dsconfig.a155abe

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 (90) hide show
  1. package/dist/cjs/index.cjs +11687 -2012
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +719 -2
  4. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js +217 -0
  5. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js.map +1 -0
  6. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js +27 -0
  7. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js.map +1 -0
  8. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/FieldInput.js +135 -0
  9. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/FieldInput.js.map +1 -0
  10. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js +80 -0
  11. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js.map +1 -0
  12. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js +54 -0
  13. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js.map +1 -0
  14. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js +155 -0
  15. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js.map +1 -0
  16. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js +75 -0
  17. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js.map +1 -0
  18. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js +262 -0
  19. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js.map +1 -0
  20. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js +354 -0
  21. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js.map +1 -0
  22. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js +138 -0
  23. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js.map +1 -0
  24. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/formInterpreter.js +93 -0
  25. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/formInterpreter.js.map +1 -0
  26. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js +253 -0
  27. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js.map +1 -0
  28. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js +106 -0
  29. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js.map +1 -0
  30. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js +52 -0
  31. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js.map +1 -0
  32. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js +26 -0
  33. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js.map +1 -0
  34. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js +106 -0
  35. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js.map +1 -0
  36. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js +124 -0
  37. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js.map +1 -0
  38. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js +190 -0
  39. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js.map +1 -0
  40. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js +31 -0
  41. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js.map +1 -0
  42. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PrimitiveInputs.js +103 -0
  43. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PrimitiveInputs.js.map +1 -0
  44. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js +59 -0
  45. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js.map +1 -0
  46. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js +80 -0
  47. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js.map +1 -0
  48. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/layoutParts.js +82 -0
  49. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/layoutParts.js.map +1 -0
  50. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js +30 -0
  51. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js.map +1 -0
  52. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js +340 -0
  53. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js.map +1 -0
  54. package/dist/esm/index.d.ts +719 -2
  55. package/dist/esm/index.js +11 -0
  56. package/dist/esm/index.js.map +1 -1
  57. package/dist/esm/node_modules/js-yaml/dist/js-yaml.js +3043 -0
  58. package/dist/esm/node_modules/js-yaml/dist/js-yaml.js.map +1 -0
  59. package/dist/esm/node_modules/react-hook-form/dist/index.esm.js +2766 -0
  60. package/dist/esm/node_modules/react-hook-form/dist/index.esm.js.map +1 -0
  61. package/dist/esm/node_modules/semver/classes/range.js +24 -4
  62. package/dist/esm/node_modules/semver/classes/range.js.map +1 -1
  63. package/dist/esm/node_modules/semver/classes/semver.js +19 -2
  64. package/dist/esm/node_modules/semver/classes/semver.js.map +1 -1
  65. package/dist/esm/node_modules/semver/functions/diff.js +1 -1
  66. package/dist/esm/node_modules/semver/functions/diff.js.map +1 -1
  67. package/dist/esm/node_modules/semver/functions/truncate.js +62 -0
  68. package/dist/esm/node_modules/semver/functions/truncate.js.map +1 -0
  69. package/dist/esm/node_modules/semver/index.js +3 -0
  70. package/dist/esm/node_modules/semver/index.js.map +1 -1
  71. package/dist/esm/node_modules/semver/internal/re.js +3 -3
  72. package/dist/esm/node_modules/semver/internal/re.js.map +1 -1
  73. package/dist/esm/node_modules/semver/ranges/subset.js +3 -3
  74. package/dist/esm/node_modules/semver/ranges/subset.js.map +1 -1
  75. package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
  76. package/dist/esm/schema/utils/constants.js +4 -0
  77. package/dist/esm/schema/utils/constants.js.map +1 -0
  78. package/dist/esm/schema/utils/dsconfig.js +97 -0
  79. package/dist/esm/schema/utils/dsconfig.js.map +1 -0
  80. package/dist/esm/schema/utils/llm.js +54 -0
  81. package/dist/esm/schema/utils/llm.js.map +1 -0
  82. package/dist/esm/schema/utils/packs.js +113 -0
  83. package/dist/esm/schema/utils/packs.js.map +1 -0
  84. package/dist/esm/schema/utils/provisioning.js +434 -0
  85. package/dist/esm/schema/utils/provisioning.js.map +1 -0
  86. package/dist/esm/schema/utils/registry.js +30 -0
  87. package/dist/esm/schema/utils/registry.js.map +1 -0
  88. package/dist/esm/schema/utils/useDatasourceSchema.js +39 -0
  89. package/dist/esm/schema/utils/useDatasourceSchema.js.map +1 -0
  90. package/package.json +12 -9
@@ -0,0 +1,354 @@
1
+ import { getBackendSrv } from '@grafana/runtime';
2
+ import { formKey } from './config.js';
3
+
4
+ const SECURE_FIELD_CONFIGURED = "__CONFIGURED__";
5
+ function resolveSecureKeyTemplate(template, item, index) {
6
+ return template.replace(/\{index1\}/g, String(index + 1)).replace(/\{index\}/g, String(index)).replace(/\{item\.(\w+)\}/g, (_, key) => {
7
+ var _a;
8
+ return String((_a = item[key]) != null ? _a : "");
9
+ });
10
+ }
11
+ function evaluateItemCondition(condition, item) {
12
+ const trimmed = condition.trim();
13
+ if (trimmed === "true") {
14
+ return true;
15
+ }
16
+ const match = trimmed.match(/^item\.(\w+)\s*==\s*(.+)$/);
17
+ if (!match) {
18
+ return false;
19
+ }
20
+ const [, key, rawValue] = match;
21
+ const actualValue = item[key];
22
+ const expected = rawValue.trim();
23
+ if (expected === "true") {
24
+ return actualValue === true;
25
+ }
26
+ if (expected === "false") {
27
+ return actualValue === false;
28
+ }
29
+ const unquoted = expected.replace(/^['"]|['"]$/g, "");
30
+ return String(actualValue) === unquoted;
31
+ }
32
+ function findActiveSecureOverride(itemFields, item, index) {
33
+ for (const field of itemFields) {
34
+ if (!field.overrides) {
35
+ continue;
36
+ }
37
+ for (const override of field.overrides) {
38
+ if (!override.secureKey) {
39
+ continue;
40
+ }
41
+ if (evaluateItemCondition(override.when, item)) {
42
+ return {
43
+ fieldKey: field.key,
44
+ resolvedKey: resolveSecureKeyTemplate(override.secureKey, item, index)
45
+ };
46
+ }
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ function patternToRegex(pattern) {
52
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53
+ return new RegExp("^" + escaped.replace("\\{index\\}", "(\\d+)") + "$");
54
+ }
55
+ function findIndicesForPattern(record, pattern) {
56
+ const re = patternToRegex(pattern);
57
+ const indices = [];
58
+ for (const key of Object.keys(record)) {
59
+ const m = key.match(re);
60
+ if (m) {
61
+ const n = Number(m[1]);
62
+ if (!Number.isNaN(n)) {
63
+ indices.push(n);
64
+ }
65
+ }
66
+ }
67
+ return indices.sort((a, b) => a - b);
68
+ }
69
+ function expandIndexedPair(field, ds) {
70
+ var _a, _b, _c;
71
+ const storage = field.storage;
72
+ if ((storage == null ? undefined : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
73
+ return [];
74
+ }
75
+ const source = storage.key.target === "jsonData" ? (_a = ds.jsonData) != null ? _a : {} : ds;
76
+ const indices = findIndicesForPattern(source, storage.key.pattern);
77
+ const items = [];
78
+ for (const i of indices) {
79
+ const nameKey = storage.key.pattern.replace("{index}", String(i));
80
+ const valueKey = storage.value.pattern.replace("{index}", String(i));
81
+ const nameVal = source[nameKey];
82
+ if (nameVal === undefined || nameVal === null) {
83
+ continue;
84
+ }
85
+ const hasValue = storage.value.target === "secureJsonData" ? !!((_b = ds.secureJsonFields) == null ? undefined : _b[valueKey]) : !!((_c = ds.jsonData) == null ? undefined : _c[valueKey]);
86
+ items.push({
87
+ index: i,
88
+ name: String(nameVal),
89
+ value: hasValue ? SECURE_FIELD_CONFIGURED : ""
90
+ });
91
+ }
92
+ return items;
93
+ }
94
+ function flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields) {
95
+ var _a;
96
+ const storage = field.storage;
97
+ if ((storage == null ? undefined : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
98
+ return;
99
+ }
100
+ const existingIndices = new Set(
101
+ storage.key.target === "jsonData" ? findIndicesForPattern(jsonData, storage.key.pattern) : []
102
+ );
103
+ const usedIndices = /* @__PURE__ */ new Set();
104
+ const startIdx = (_a = storage.startIndex) != null ? _a : 1;
105
+ let nextIndex = existingIndices.size > 0 ? Math.max(...existingIndices) + 1 : startIdx;
106
+ for (const item of items) {
107
+ let idx = item.index;
108
+ if (idx === 0) {
109
+ idx = nextIndex++;
110
+ }
111
+ usedIndices.add(idx);
112
+ const nameKey = storage.key.pattern.replace("{index}", String(idx));
113
+ const valueKey = storage.value.pattern.replace("{index}", String(idx));
114
+ if (storage.key.target === "jsonData") {
115
+ jsonData[nameKey] = item.name;
116
+ }
117
+ if (storage.value.target === "secureJsonData") {
118
+ if (item.value === SECURE_FIELD_CONFIGURED) {
119
+ secureJsonFields[valueKey] = true;
120
+ } else if (item.value) {
121
+ secureJsonData[valueKey] = item.value;
122
+ secureJsonFields[valueKey] = false;
123
+ }
124
+ } else if (storage.value.target === "jsonData") {
125
+ jsonData[valueKey] = item.value;
126
+ }
127
+ }
128
+ for (const idx of existingIndices) {
129
+ if (usedIndices.has(idx)) {
130
+ continue;
131
+ }
132
+ const nameKey = storage.key.pattern.replace("{index}", String(idx));
133
+ const valueKey = storage.value.pattern.replace("{index}", String(idx));
134
+ if (storage.key.target === "jsonData") {
135
+ delete jsonData[nameKey];
136
+ }
137
+ if (storage.value.target === "secureJsonData") {
138
+ delete secureJsonFields[valueKey];
139
+ delete secureJsonData[valueKey];
140
+ } else if (storage.value.target === "jsonData") {
141
+ delete jsonData[valueKey];
142
+ }
143
+ }
144
+ }
145
+ function resolveRawPath(ref, ds) {
146
+ var _a;
147
+ const trimmed = ref.trim();
148
+ if (trimmed.startsWith("jsonData.")) {
149
+ return (_a = ds.jsonData) == null ? undefined : _a[trimmed.slice(9)];
150
+ }
151
+ if (trimmed.startsWith("root.")) {
152
+ return ds[trimmed.slice(5)];
153
+ }
154
+ return undefined;
155
+ }
156
+ async function fetchExistingValues(dsUid, fields) {
157
+ var _a, _b, _c, _d, _e, _f;
158
+ try {
159
+ const ds = await getBackendSrv().get(`/api/datasources/uid/${dsUid}`, void 0, void 0, {
160
+ showErrorAlert: false
161
+ });
162
+ const values = {};
163
+ for (const field of fields) {
164
+ if (((_a = field.storage) == null ? void 0 : _a.type) === "indexedPair") {
165
+ values[field.key] = expandIndexedPair(field, ds);
166
+ continue;
167
+ }
168
+ const fk = formKey(field);
169
+ switch (field.target) {
170
+ case "root":
171
+ if (ds[field.key] !== void 0) {
172
+ values[fk] = ds[field.key];
173
+ }
174
+ break;
175
+ case "jsonData":
176
+ if (field.section) {
177
+ const sectionObj = (_b = ds.jsonData) == null ? void 0 : _b[field.section];
178
+ if ((sectionObj == null ? void 0 : sectionObj[field.key]) !== void 0) {
179
+ values[fk] = sectionObj[field.key];
180
+ }
181
+ } else if (((_c = ds.jsonData) == null ? void 0 : _c[field.key]) !== void 0) {
182
+ values[fk] = ds.jsonData[field.key];
183
+ }
184
+ break;
185
+ case "secureJsonData":
186
+ if ((_d = ds.secureJsonFields) == null ? void 0 : _d[field.key]) {
187
+ values[fk] = SECURE_FIELD_CONFIGURED;
188
+ }
189
+ break;
190
+ }
191
+ if (values[fk] === void 0 && ((_e = field.storage) == null ? void 0 : _e.type) === "computed" && field.storage.read) {
192
+ const fallback = resolveRawPath(field.storage.read, ds);
193
+ if (fallback !== void 0) {
194
+ values[fk] = fallback;
195
+ }
196
+ }
197
+ }
198
+ for (const field of fields) {
199
+ if (field.valueType !== "array" || !((_f = field.item) == null ? void 0 : _f.fields)) {
200
+ continue;
201
+ }
202
+ const itemFields = field.item.fields;
203
+ const hasSecureOverride = itemFields.some((f) => {
204
+ var _a2;
205
+ return (_a2 = f.overrides) == null ? void 0 : _a2.some((o) => o.secureKey);
206
+ });
207
+ if (!hasSecureOverride) {
208
+ continue;
209
+ }
210
+ const fk = formKey(field);
211
+ const arr = values[fk];
212
+ if (!Array.isArray(arr)) {
213
+ continue;
214
+ }
215
+ values[fk] = arr.map((item, idx) => {
216
+ var _a2;
217
+ const match = findActiveSecureOverride(itemFields, item, idx);
218
+ if (match && ((_a2 = ds.secureJsonFields) == null ? void 0 : _a2[match.resolvedKey])) {
219
+ return { ...item, [match.fieldKey]: SECURE_FIELD_CONFIGURED };
220
+ }
221
+ return item;
222
+ });
223
+ }
224
+ return { values, readOnly: !!ds.readOnly };
225
+ } catch (err) {
226
+ const message = err instanceof Error ? err.message : "Failed to load datasource configuration";
227
+ return { values: {}, readOnly: false, error: message };
228
+ }
229
+ }
230
+ function buildDatasourceConfigPayload(data, fields, existing, isFieldVisible) {
231
+ var _a, _b, _c, _d, _e, _f, _g, _h;
232
+ const rootFields = {};
233
+ const jsonData = { ...(_a = existing.jsonData) != null ? _a : {} };
234
+ const secureJsonData = {};
235
+ const secureJsonFields = { ...(_b = existing.secureJsonFields) != null ? _b : {} };
236
+ for (const field of fields) {
237
+ if (((_c = field.storage) == null ? undefined : _c.type) === "indexedPair") {
238
+ const items = Array.isArray(data[field.key]) ? data[field.key] : [];
239
+ flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields);
240
+ continue;
241
+ }
242
+ const isManagedByEffect = (_d = field.tags) == null ? undefined : _d.some((t) => t.startsWith("managed-by:"));
243
+ if (!isManagedByEffect && !isFieldVisible(field)) {
244
+ continue;
245
+ }
246
+ const fk = formKey(field);
247
+ const value = data[fk];
248
+ if (field.target === "secureJsonData") {
249
+ if (value === SECURE_FIELD_CONFIGURED) {
250
+ secureJsonFields[field.key] = true;
251
+ continue;
252
+ }
253
+ if (value && value !== "") {
254
+ secureJsonData[field.key] = String(value);
255
+ secureJsonFields[field.key] = false;
256
+ } else {
257
+ secureJsonFields[field.key] = false;
258
+ }
259
+ continue;
260
+ }
261
+ if (value === undefined || value === "") {
262
+ continue;
263
+ }
264
+ switch (field.target) {
265
+ case "root":
266
+ rootFields[field.key] = value;
267
+ break;
268
+ case "jsonData":
269
+ if (field.section) {
270
+ if (!jsonData[field.section] || typeof jsonData[field.section] !== "object") {
271
+ jsonData[field.section] = {};
272
+ }
273
+ jsonData[field.section][field.key] = value;
274
+ } else {
275
+ jsonData[field.key] = value;
276
+ }
277
+ break;
278
+ }
279
+ }
280
+ for (const field of fields) {
281
+ if (field.valueType !== "array" || !((_e = field.item) == null ? undefined : _e.fields) || field.target !== "jsonData") {
282
+ continue;
283
+ }
284
+ const itemFields = field.item.fields;
285
+ const hasSecureOverride = itemFields.some((f) => {
286
+ var _a2;
287
+ return (_a2 = f.overrides) == null ? undefined : _a2.some((o) => o.secureKey);
288
+ });
289
+ if (!hasSecureOverride) {
290
+ continue;
291
+ }
292
+ const arr = field.section ? (_f = jsonData[field.section]) == null ? undefined : _f[field.key] : jsonData[field.key];
293
+ if (!Array.isArray(arr)) {
294
+ continue;
295
+ }
296
+ const secureKeyOverrides = [];
297
+ for (const f of itemFields) {
298
+ for (const o of (_g = f.overrides) != null ? _g : []) {
299
+ if (o.secureKey) {
300
+ secureKeyOverrides.push({ fieldKey: f.key, override: o });
301
+ }
302
+ }
303
+ }
304
+ const activeSecureKeys = /* @__PURE__ */ new Set();
305
+ for (let i = 0; i < arr.length; i++) {
306
+ const item = arr[i];
307
+ const match = findActiveSecureOverride(itemFields, item, i);
308
+ if (!match) {
309
+ continue;
310
+ }
311
+ const resolvedKey = match.resolvedKey;
312
+ activeSecureKeys.add(resolvedKey);
313
+ const itemValue = item[match.fieldKey];
314
+ if (itemValue === SECURE_FIELD_CONFIGURED) {
315
+ secureJsonFields[resolvedKey] = true;
316
+ } else if (itemValue && itemValue !== "") {
317
+ secureJsonData[resolvedKey] = String(itemValue);
318
+ secureJsonFields[resolvedKey] = false;
319
+ item[match.fieldKey] = "";
320
+ }
321
+ }
322
+ const existingSecureFields = (_h = existing.secureJsonFields) != null ? _h : {};
323
+ for (const existingKey of Object.keys(existingSecureFields)) {
324
+ const couldBeFromThisField = secureKeyOverrides.some((sko) => {
325
+ const staticPrefix = sko.override.secureKey.split("{")[0];
326
+ return staticPrefix && existingKey.startsWith(staticPrefix);
327
+ });
328
+ if (couldBeFromThisField && !activeSecureKeys.has(existingKey)) {
329
+ secureJsonFields[existingKey] = false;
330
+ secureJsonData[existingKey] = "";
331
+ }
332
+ }
333
+ }
334
+ return { rootFields, jsonData, secureJsonData, secureJsonFields };
335
+ }
336
+ async function submitDatasourceConfig(dsUid, data, fields, isFieldVisible) {
337
+ const existing = await getBackendSrv().get(`/api/datasources/uid/${dsUid}`);
338
+ const { rootFields, jsonData, secureJsonData, secureJsonFields } = buildDatasourceConfigPayload(
339
+ data,
340
+ fields,
341
+ existing,
342
+ isFieldVisible
343
+ );
344
+ await getBackendSrv().put(`/api/datasources/uid/${dsUid}`, {
345
+ ...existing,
346
+ ...rootFields,
347
+ jsonData,
348
+ secureJsonData,
349
+ secureJsonFields
350
+ });
351
+ }
352
+
353
+ export { SECURE_FIELD_CONFIGURED, buildDatasourceConfigPayload, expandIndexedPair, fetchExistingValues, findActiveSecureOverride, flattenIndexedPair, resolveSecureKeyTemplate, submitDatasourceConfig };
354
+ //# sourceMappingURL=datasource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datasource.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/datasource.ts"],"sourcesContent":["import { getBackendSrv } from '@grafana/runtime';\nimport { formKey } from './config';\nimport type { ConfigField, FieldOverride } from '../../../schema/schema';\n\nexport type DatasourceResponse = Record<string, unknown> & {\n name: string;\n id: number;\n uid: string;\n access?: 'proxy' | 'direct';\n type?: string;\n typeLogoUrl?: string;\n url?: string;\n withCredentials?: boolean;\n basicAuth?: boolean;\n basicAuthUser?: string;\n user?: string;\n database?: string;\n jsonData?: Record<string, unknown>;\n secureJsonFields?: Record<string, boolean>;\n readOnly?: boolean;\n};\n\nexport type DatasourceConfigPayload = {\n rootFields: Record<string, unknown>;\n jsonData: Record<string, unknown>;\n secureJsonData: Record<string, string>;\n secureJsonFields: Record<string, boolean>;\n};\n\nexport type FormValues = Record<string, unknown>;\n\nexport const SECURE_FIELD_CONFIGURED = '__CONFIGURED__';\n\n// ============================================================\n// secureKey helpers for per-item secure routing\n// ============================================================\n\n/**\n * Resolve a secureKey template string by replacing placeholders.\n *\n * Supported placeholders:\n * - `{index}` — 0-based array position\n * - `{index1}` — 1-based array position\n * - `{item.KEY}` — value of sibling field `KEY` in the same item object\n */\nexport function resolveSecureKeyTemplate(template: string, item: Record<string, unknown>, index: number): string {\n return template\n .replace(/\\{index1\\}/g, String(index + 1))\n .replace(/\\{index\\}/g, String(index))\n .replace(/\\{item\\.(\\w+)\\}/g, (_, key) => String(item[key] ?? ''));\n}\n\n/**\n * Evaluate a simple item-scoped condition like `item.secure == true`.\n * Only supports `item.KEY == VALUE` and the literal `true`.\n * Returns false for expressions it cannot evaluate.\n */\nfunction evaluateItemCondition(condition: string, item: Record<string, unknown>): boolean {\n const trimmed = condition.trim();\n if (trimmed === 'true') {\n return true;\n }\n // Match: item.KEY == VALUE (with optional quotes)\n const match = trimmed.match(/^item\\.(\\w+)\\s*==\\s*(.+)$/);\n if (!match) {\n return false;\n }\n const [, key, rawValue] = match;\n const actualValue = item[key];\n // Parse the expected value\n const expected = rawValue.trim();\n if (expected === 'true') {\n return actualValue === true;\n }\n if (expected === 'false') {\n return actualValue === false;\n }\n // String comparison (strip quotes)\n const unquoted = expected.replace(/^['\"]|['\"]$/g, '');\n return String(actualValue) === unquoted;\n}\n\n/**\n * For a given item object at a given index, find the first active secureKey\n * override across all item fields. Returns the resolved secureJsonData key\n * and the item field key whose value should be routed, or null if none active.\n */\nexport function findActiveSecureOverride(\n itemFields: ConfigField[],\n item: Record<string, unknown>,\n index: number\n): { fieldKey: string; resolvedKey: string } | null {\n for (const field of itemFields) {\n if (!field.overrides) {\n continue;\n }\n for (const override of field.overrides) {\n if (!override.secureKey) {\n continue;\n }\n if (evaluateItemCondition(override.when, item)) {\n return {\n fieldKey: field.key,\n resolvedKey: resolveSecureKeyTemplate(override.secureKey, item, index),\n };\n }\n }\n }\n return null;\n}\n\nexport type FetchExistingResult = {\n values: FormValues;\n readOnly: boolean;\n error?: string;\n};\n\n/** Indexed pair item as stored in form values. Each item tracks its original storage index. */\nexport type IndexedPairItem = {\n /** Original storage index (e.g. 1 for httpHeaderName1). 0 = new item, not yet persisted. */\n index: number;\n name: string;\n value: string;\n};\n\n/**\n * Build a RegExp that matches keys produced by a pattern like \"httpHeaderName{index}\"\n * and captures the numeric index.\n */\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp('^' + escaped.replace('\\\\{index\\\\}', '(\\\\d+)') + '$');\n}\n\n/**\n * Find all numeric indices present in a record for a given pattern.\n * E.g. for pattern \"httpHeaderName{index}\" and keys {httpHeaderName1, httpHeaderName3}\n * returns a sorted array [1, 3].\n */\nfunction findIndicesForPattern(record: Record<string, unknown>, pattern: string): number[] {\n const re = patternToRegex(pattern);\n const indices: number[] = [];\n for (const key of Object.keys(record)) {\n const m = key.match(re);\n if (m) {\n const n = Number(m[1]);\n if (!Number.isNaN(n)) {\n indices.push(n);\n }\n }\n }\n return indices.sort((a, b) => a - b);\n}\n\n/**\n * Expand indexed pair storage (e.g. httpHeaderName1..N / httpHeaderValue1..N)\n * into an array of {index, name, value} items for the form.\n * Each item's `index` tracks its storage position so deletes don't shift others.\n * Scans all keys in the source record to find matching indices — no gap heuristics.\n */\nexport function expandIndexedPair(field: ConfigField, ds: DatasourceResponse): IndexedPairItem[] {\n const storage = field.storage;\n if (storage?.type !== 'indexedPair' || !storage.key || !storage.value) {\n return [];\n }\n const source = storage.key.target === 'jsonData' ? (ds.jsonData ?? {}) : (ds as Record<string, unknown>);\n const indices = findIndicesForPattern(source as Record<string, unknown>, storage.key.pattern);\n const items: IndexedPairItem[] = [];\n for (const i of indices) {\n const nameKey = storage.key.pattern.replace('{index}', String(i));\n const valueKey = storage.value.pattern.replace('{index}', String(i));\n const nameVal = (source as Record<string, unknown>)[nameKey];\n if (nameVal === undefined || nameVal === null) {\n continue;\n }\n const hasValue =\n storage.value.target === 'secureJsonData' ? !!ds.secureJsonFields?.[valueKey] : !!ds.jsonData?.[valueKey];\n items.push({\n index: i,\n name: String(nameVal),\n value: hasValue ? SECURE_FIELD_CONFIGURED : '',\n });\n }\n return items;\n}\n\n/**\n * Flatten an array of indexed pair items back into individual indexed keys\n * for jsonData and secureJsonData.\n */\nexport function flattenIndexedPair(\n field: ConfigField,\n items: IndexedPairItem[],\n jsonData: Record<string, unknown>,\n secureJsonData: Record<string, string>,\n secureJsonFields: Record<string, boolean>\n) {\n const storage = field.storage;\n if (storage?.type !== 'indexedPair' || !storage.key || !storage.value) {\n return;\n }\n // Find all existing storage indices by scanning keys in jsonData.\n const existingIndices = new Set(\n storage.key.target === 'jsonData'\n ? findIndicesForPattern(jsonData as Record<string, unknown>, storage.key.pattern)\n : []\n );\n\n // Track which indices are still in use by the surviving items.\n const usedIndices = new Set<number>();\n const startIdx = storage.startIndex ?? 1;\n let nextIndex = existingIndices.size > 0 ? Math.max(...existingIndices) + 1 : startIdx;\n\n // Write each item at its original index. New items (index === 0) get the next available.\n for (const item of items) {\n let idx = item.index;\n if (idx === 0) {\n idx = nextIndex++;\n }\n usedIndices.add(idx);\n const nameKey = storage.key.pattern.replace('{index}', String(idx));\n const valueKey = storage.value.pattern.replace('{index}', String(idx));\n if (storage.key.target === 'jsonData') {\n jsonData[nameKey] = item.name;\n }\n if (storage.value.target === 'secureJsonData') {\n if (item.value === SECURE_FIELD_CONFIGURED) {\n secureJsonFields[valueKey] = true;\n } else if (item.value) {\n secureJsonData[valueKey] = item.value;\n secureJsonFields[valueKey] = false;\n }\n } else if (storage.value.target === 'jsonData') {\n jsonData[valueKey] = item.value;\n }\n }\n\n // Clear deleted indices: indices that existed before but are no longer in use.\n for (const idx of existingIndices) {\n if (usedIndices.has(idx)) {\n continue;\n }\n const nameKey = storage.key.pattern.replace('{index}', String(idx));\n const valueKey = storage.value.pattern.replace('{index}', String(idx));\n if (storage.key.target === 'jsonData') {\n delete jsonData[nameKey];\n }\n if (storage.value.target === 'secureJsonData') {\n delete secureJsonFields[valueKey];\n delete secureJsonData[valueKey];\n } else if (storage.value.target === 'jsonData') {\n delete jsonData[valueKey];\n }\n }\n}\n\n/**\n * Resolve a dotted storage path against the raw API response.\n * Handles: \"jsonData.server\", \"root.database\", \"secureJsonData.password\"\n */\nfunction resolveRawPath(ref: string, ds: DatasourceResponse): unknown {\n const trimmed = ref.trim();\n if (trimmed.startsWith('jsonData.')) {\n return ds.jsonData?.[trimmed.slice(9)];\n }\n if (trimmed.startsWith('root.')) {\n return (ds as Record<string, unknown>)[trimmed.slice(5)];\n }\n return undefined;\n}\n\nexport async function fetchExistingValues(dsUid: string, fields: ConfigField[]): Promise<FetchExistingResult> {\n try {\n const ds: DatasourceResponse = await getBackendSrv().get(`/api/datasources/uid/${dsUid}`, undefined, undefined, {\n showErrorAlert: false,\n });\n\n const values: FormValues = {};\n for (const field of fields) {\n // Expand indexedPair storage: read httpHeaderName1..N + secureJsonFields httpHeaderValue1..N\n if (field.storage?.type === 'indexedPair') {\n values[field.key] = expandIndexedPair(field, ds);\n continue;\n }\n const fk = formKey(field);\n switch (field.target) {\n case 'root':\n if (ds[field.key] !== undefined) {\n values[fk] = ds[field.key];\n }\n break;\n case 'jsonData':\n // Section-scoped fields are stored nested: jsonData.{section}.{key}\n if (field.section) {\n const sectionObj = ds.jsonData?.[field.section] as Record<string, unknown> | undefined;\n if (sectionObj?.[field.key] !== undefined) {\n values[fk] = sectionObj[field.key];\n }\n } else if (ds.jsonData?.[field.key] !== undefined) {\n values[fk] = ds.jsonData[field.key];\n }\n break;\n case 'secureJsonData':\n if (ds.secureJsonFields?.[field.key]) {\n values[fk] = SECURE_FIELD_CONFIGURED;\n }\n break;\n }\n\n // Fallback: if value is still missing and field has storage.read,\n // resolve the expression against the raw API response.\n if (values[fk] === undefined && field.storage?.type === 'computed' && field.storage.read) {\n const fallback = resolveRawPath(field.storage.read, ds);\n if (fallback !== undefined) {\n values[fk] = fallback;\n }\n }\n }\n\n // Post-process arrays with secureKey overrides: for each item, check\n // whether the item's value is stored in secureJsonFields and mark it.\n for (const field of fields) {\n if (field.valueType !== 'array' || !field.item?.fields) {\n continue;\n }\n const itemFields = field.item.fields;\n const hasSecureOverride = itemFields.some((f) => f.overrides?.some((o) => o.secureKey));\n if (!hasSecureOverride) {\n continue;\n }\n const fk = formKey(field);\n const arr = values[fk];\n if (!Array.isArray(arr)) {\n continue;\n }\n values[fk] = arr.map((item: Record<string, unknown>, idx: number) => {\n const match = findActiveSecureOverride(itemFields, item, idx);\n if (match && ds.secureJsonFields?.[match.resolvedKey]) {\n return { ...item, [match.fieldKey]: SECURE_FIELD_CONFIGURED };\n }\n return item;\n });\n }\n\n return { values, readOnly: !!ds.readOnly };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : 'Failed to load datasource configuration';\n return { values: {}, readOnly: false, error: message };\n }\n}\n\nexport function buildDatasourceConfigPayload(\n data: FormValues,\n fields: ConfigField[],\n existing: DatasourceResponse,\n isFieldVisible: (field: ConfigField) => boolean\n): DatasourceConfigPayload {\n const rootFields: Record<string, unknown> = {};\n const jsonData: Record<string, unknown> = { ...(existing.jsonData ?? {}) };\n const secureJsonData: Record<string, string> = {};\n const secureJsonFields: Record<string, boolean> = { ...(existing.secureJsonFields ?? {}) };\n\n for (const field of fields) {\n // Flatten indexedPair storage back into individual indexed keys\n if (field.storage?.type === 'indexedPair') {\n const items = Array.isArray(data[field.key]) ? (data[field.key] as IndexedPairItem[]) : [];\n flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields);\n continue;\n }\n\n // Always include fields managed by effects (tagged \"managed-by:*\")\n // even when they're hidden from the UI — their values are set by effects.\n const isManagedByEffect = field.tags?.some((t) => t.startsWith('managed-by:'));\n if (!isManagedByEffect && !isFieldVisible(field)) {\n continue;\n }\n const fk = formKey(field);\n const value = data[fk];\n\n if (field.target === 'secureJsonData') {\n if (value === SECURE_FIELD_CONFIGURED) {\n secureJsonFields[field.key] = true;\n continue;\n }\n if (value && value !== '') {\n secureJsonData[field.key] = String(value);\n secureJsonFields[field.key] = false;\n } else {\n secureJsonFields[field.key] = false;\n }\n continue;\n }\n\n if (value === undefined || value === '') {\n continue;\n }\n switch (field.target) {\n case 'root':\n rootFields[field.key] = value;\n break;\n case 'jsonData':\n // Section-scoped fields write to jsonData.{section}.{key}\n if (field.section) {\n if (!jsonData[field.section] || typeof jsonData[field.section] !== 'object') {\n jsonData[field.section] = {};\n }\n (jsonData[field.section] as Record<string, unknown>)[field.key] = value;\n } else {\n jsonData[field.key] = value;\n }\n break;\n }\n }\n\n // Post-process arrays with secureKey overrides: route values to secureJsonData\n // and clean up stale secure keys from previous saves.\n for (const field of fields) {\n if (field.valueType !== 'array' || !field.item?.fields || field.target !== 'jsonData') {\n continue;\n }\n const itemFields = field.item.fields;\n const hasSecureOverride = itemFields.some((f) => f.overrides?.some((o) => o.secureKey));\n if (!hasSecureOverride) {\n continue;\n }\n const arr = (\n field.section ? (jsonData[field.section] as Record<string, unknown>)?.[field.key] : jsonData[field.key]\n ) as Array<Record<string, unknown>> | undefined;\n if (!Array.isArray(arr)) {\n continue;\n }\n\n // Collect all secureKey patterns from this field's item overrides for cleanup\n const secureKeyOverrides: Array<{ fieldKey: string; override: FieldOverride }> = [];\n for (const f of itemFields) {\n for (const o of f.overrides ?? []) {\n if (o.secureKey) {\n secureKeyOverrides.push({ fieldKey: f.key, override: o });\n }\n }\n }\n\n // Track which secure keys are still active so we can remove stale ones\n const activeSecureKeys = new Set<string>();\n\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i];\n const match = findActiveSecureOverride(itemFields, item, i);\n if (!match) {\n continue;\n }\n const resolvedKey = match.resolvedKey;\n activeSecureKeys.add(resolvedKey);\n const itemValue = item[match.fieldKey];\n\n if (itemValue === SECURE_FIELD_CONFIGURED) {\n // Value already stored in secureJsonData, keep it\n secureJsonFields[resolvedKey] = true;\n } else if (itemValue && itemValue !== '') {\n // New or updated secret value — route to secureJsonData\n secureJsonData[resolvedKey] = String(itemValue);\n secureJsonFields[resolvedKey] = false;\n // Clear the value from the inline array\n item[match.fieldKey] = '';\n }\n }\n\n // Remove stale secure keys that were previously set but are no longer in the array\n const existingSecureFields = existing.secureJsonFields ?? {};\n for (const existingKey of Object.keys(existingSecureFields)) {\n // Check if this key could have been produced by any of this field's secureKey templates\n const couldBeFromThisField = secureKeyOverrides.some((sko) => {\n // Simple heuristic: check if the existing key starts with the static prefix\n // of the template (everything before the first placeholder)\n const staticPrefix = sko.override.secureKey!.split('{')[0];\n return staticPrefix && existingKey.startsWith(staticPrefix);\n });\n if (couldBeFromThisField && !activeSecureKeys.has(existingKey)) {\n secureJsonFields[existingKey] = false;\n secureJsonData[existingKey] = '';\n }\n }\n }\n\n return { rootFields, jsonData, secureJsonData, secureJsonFields };\n}\n\nexport async function submitDatasourceConfig(\n dsUid: string,\n data: FormValues,\n fields: ConfigField[],\n isFieldVisible: (field: ConfigField) => boolean\n): Promise<void> {\n const existing: DatasourceResponse = await getBackendSrv().get(`/api/datasources/uid/${dsUid}`);\n const { rootFields, jsonData, secureJsonData, secureJsonFields } = buildDatasourceConfigPayload(\n data,\n fields,\n existing,\n isFieldVisible\n );\n\n await getBackendSrv().put(`/api/datasources/uid/${dsUid}`, {\n ...existing,\n ...rootFields,\n jsonData,\n secureJsonData,\n secureJsonFields,\n });\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ import { parseDependsOn, formKey, evaluateDependsOn, getWatchedValue } from './config.js';
2
+ import { evaluateCelExpression } from './cel.js';
3
+ import { SECURE_FIELD_CONFIGURED } from './datasource.js';
4
+
5
+ function evaluateEffectCondition(when, fieldValue) {
6
+ var _a, _b;
7
+ const m = when.match(/^value\s*(==|!=)\s*(?:'([^']*)'|"([^"]*)"|(.+))$/);
8
+ if (!m) {
9
+ return false;
10
+ }
11
+ const op = m[1];
12
+ let target = (_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : m[4];
13
+ if (target === "true") {
14
+ target = true;
15
+ } else if (target === "false") {
16
+ target = false;
17
+ } else if (typeof target === "string" && /^-?\d+(\.\d+)?$/.test(target)) {
18
+ target = Number(target);
19
+ }
20
+ const eq = String(fieldValue) === String(target);
21
+ return op === "==" ? eq : !eq;
22
+ }
23
+ function isFieldRequired(field, watchedValues, fieldById, celContext) {
24
+ if (field.required) {
25
+ return true;
26
+ }
27
+ if (field.requiredWhen) {
28
+ if (celContext) {
29
+ return evaluateCelExpression(field.requiredWhen, celContext);
30
+ }
31
+ const parsed = parseDependsOn(field.requiredWhen);
32
+ if (parsed) {
33
+ const depField = fieldById.get(parsed.field);
34
+ const depKey = depField ? formKey(depField) : parsed.field;
35
+ return evaluateDependsOn(parsed, getWatchedValue(watchedValues, depKey));
36
+ }
37
+ }
38
+ return false;
39
+ }
40
+ function buildValidationRules(field, required) {
41
+ var _a, _b, _c, _d, _e, _f, _g, _h;
42
+ const rules = {};
43
+ const label = (_a = field.label) != null ? _a : field.key;
44
+ if (required) {
45
+ if (field.target === "secureJsonData") {
46
+ rules.validate = (value) => {
47
+ if (value === SECURE_FIELD_CONFIGURED) {
48
+ return true;
49
+ }
50
+ if (!value || value === "") {
51
+ return `${label} is required`;
52
+ }
53
+ return true;
54
+ };
55
+ } else {
56
+ rules.required = `${label} is required`;
57
+ }
58
+ }
59
+ if (field.valueType === "array" && ((_b = field.item) == null ? undefined : _b.valueType) === "object" && ((_c = field.item.fields) == null ? undefined : _c.length)) {
60
+ const requiredItemFields = field.item.fields.filter((f) => f.required);
61
+ if (requiredItemFields.length > 0) {
62
+ const existingValidate = rules.validate;
63
+ rules.validate = (value) => {
64
+ var _a2;
65
+ if (existingValidate) {
66
+ const r = existingValidate(value);
67
+ if (r !== true) {
68
+ return r;
69
+ }
70
+ }
71
+ if (!Array.isArray(value)) {
72
+ return true;
73
+ }
74
+ const itemErrors = {};
75
+ for (let i = 0; i < value.length; i++) {
76
+ const item = value[i];
77
+ const missing = [];
78
+ for (const rf of requiredItemFields) {
79
+ const v = item[rf.key];
80
+ if (v === undefined || v === null || v === "") {
81
+ missing.push((_a2 = rf.label) != null ? _a2 : rf.key);
82
+ }
83
+ }
84
+ if (missing.length > 0) {
85
+ itemErrors[i] = `${missing.join(", ")} required`;
86
+ }
87
+ }
88
+ if (Object.keys(itemErrors).length === 0) {
89
+ return true;
90
+ }
91
+ return `__ITEM_ERRORS__${JSON.stringify(itemErrors)}`;
92
+ };
93
+ }
94
+ }
95
+ if (field.validations) {
96
+ for (const v of field.validations) {
97
+ switch (v.type) {
98
+ case "pattern":
99
+ rules.pattern = {
100
+ value: new RegExp(v.pattern),
101
+ message: (_d = v.message) != null ? _d : `Invalid ${label}`
102
+ };
103
+ break;
104
+ case "range":
105
+ if (v.min !== undefined) {
106
+ rules.min = { value: v.min, message: (_e = v.message) != null ? _e : `Minimum value is ${v.min}` };
107
+ }
108
+ if (v.max !== undefined) {
109
+ rules.max = { value: v.max, message: (_f = v.message) != null ? _f : `Maximum value is ${v.max}` };
110
+ }
111
+ break;
112
+ case "length":
113
+ if (v.min !== undefined) {
114
+ rules.minLength = { value: v.min, message: (_g = v.message) != null ? _g : `Minimum length is ${v.min}` };
115
+ }
116
+ if (v.max !== undefined) {
117
+ rules.maxLength = { value: v.max, message: (_h = v.message) != null ? _h : `Maximum length is ${v.max}` };
118
+ }
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ return rules;
124
+ }
125
+ const ITEM_ERRORS_PREFIX = "__ITEM_ERRORS__";
126
+ function parseItemErrors(errorMessage) {
127
+ if (!errorMessage || !errorMessage.startsWith(ITEM_ERRORS_PREFIX)) {
128
+ return null;
129
+ }
130
+ try {
131
+ return JSON.parse(errorMessage.slice(ITEM_ERRORS_PREFIX.length));
132
+ } catch (e) {
133
+ return null;
134
+ }
135
+ }
136
+
137
+ export { buildValidationRules, evaluateEffectCondition, isFieldRequired, parseItemErrors };
138
+ //# sourceMappingURL=fieldUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldUtils.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.ts"],"sourcesContent":["import type { ConfigField } from '../../../schema/schema';\nimport { parseDependsOn, evaluateDependsOn, formKey, getWatchedValue } from './config';\nimport { evaluateCelExpression } from './cel';\nimport { SECURE_FIELD_CONFIGURED } from './datasource';\n\n/**\n * Evaluate an effect's `when` condition against a field value.\n * Supports: \"value == 'literal'\", \"value == true\", \"value != 'literal'\"\n * The keyword `value` refers to the current value of the source field.\n */\nexport function evaluateEffectCondition(when: string, fieldValue: unknown): boolean {\n const m = when.match(/^value\\s*(==|!=)\\s*(?:'([^']*)'|\"([^\"]*)\"|(.+))$/);\n if (!m) {\n return false;\n }\n const op = m[1];\n let target: unknown = m[2] ?? m[3] ?? m[4];\n if (target === 'true') {\n target = true;\n } else if (target === 'false') {\n target = false;\n } else if (typeof target === 'string' && /^-?\\d+(\\.\\d+)?$/.test(target)) {\n target = Number(target);\n }\n\n const eq = String(fieldValue) === String(target);\n return op === '==' ? eq : !eq;\n}\n\n/**\n * Evaluate whether a field is currently required, considering both the static\n * `required` flag and the conditional `requiredWhen` expression.\n */\nexport function isFieldRequired(\n field: ConfigField,\n watchedValues: Record<string, unknown>,\n fieldById: Map<string, ConfigField>,\n celContext?: Record<string, unknown>\n): boolean {\n if (field.required) {\n return true;\n }\n if (field.requiredWhen) {\n // Use CEL evaluation if context is available (supports compound expressions)\n if (celContext) {\n return evaluateCelExpression(field.requiredWhen, celContext);\n }\n // Fallback to simple parser for backward compatibility\n const parsed = parseDependsOn(field.requiredWhen);\n if (parsed) {\n const depField = fieldById.get(parsed.field);\n const depKey = depField ? formKey(depField) : parsed.field;\n return evaluateDependsOn(parsed, getWatchedValue(watchedValues, depKey));\n }\n }\n return false;\n}\n\nexport function buildValidationRules(field: ConfigField, required: boolean) {\n const rules: Record<string, unknown> = {};\n const label = field.label ?? field.key;\n\n if (required) {\n if (field.target === 'secureJsonData') {\n rules.validate = (value: unknown) => {\n if (value === SECURE_FIELD_CONFIGURED) {\n return true;\n }\n if (!value || value === '') {\n return `${label} is required`;\n }\n return true;\n };\n } else {\n rules.required = `${label} is required`;\n }\n }\n\n // Validate required item fields inside object arrays.\n // Returns a JSON-encoded map of {itemIndex: \"message\"} so ObjectArrayEditor\n // can render errors inline per item. react-hook-form treats any non-true\n // string as an error message.\n if (field.valueType === 'array' && field.item?.valueType === 'object' && field.item.fields?.length) {\n const requiredItemFields = field.item.fields.filter((f) => f.required);\n if (requiredItemFields.length > 0) {\n const existingValidate = rules.validate as ((v: unknown) => true | string) | undefined;\n rules.validate = (value: unknown) => {\n if (existingValidate) {\n const r = existingValidate(value);\n if (r !== true) {\n return r;\n }\n }\n if (!Array.isArray(value)) {\n return true;\n }\n const itemErrors: Record<number, string> = {};\n for (let i = 0; i < value.length; i++) {\n const item = value[i] as Record<string, unknown>;\n const missing: string[] = [];\n for (const rf of requiredItemFields) {\n const v = item[rf.key];\n if (v === undefined || v === null || v === '') {\n missing.push(rf.label ?? rf.key);\n }\n }\n if (missing.length > 0) {\n itemErrors[i] = `${missing.join(', ')} required`;\n }\n }\n if (Object.keys(itemErrors).length === 0) {\n return true;\n }\n // Encode as JSON so ObjectArrayEditor can parse and show per-item\n return `__ITEM_ERRORS__${JSON.stringify(itemErrors)}`;\n };\n }\n }\n\n if (field.validations) {\n for (const v of field.validations) {\n switch (v.type) {\n case 'pattern':\n rules.pattern = {\n value: new RegExp(v.pattern),\n message: v.message ?? `Invalid ${label}`,\n };\n break;\n case 'range':\n if (v.min !== undefined) {\n rules.min = { value: v.min, message: v.message ?? `Minimum value is ${v.min}` };\n }\n if (v.max !== undefined) {\n rules.max = { value: v.max, message: v.message ?? `Maximum value is ${v.max}` };\n }\n break;\n case 'length':\n if (v.min !== undefined) {\n rules.minLength = { value: v.min, message: v.message ?? `Minimum length is ${v.min}` };\n }\n if (v.max !== undefined) {\n rules.maxLength = { value: v.max, message: v.message ?? `Maximum length is ${v.max}` };\n }\n break;\n }\n }\n }\n\n return rules;\n}\nconst ITEM_ERRORS_PREFIX = '__ITEM_ERRORS__';\n\n/**\n * Parse a per-item error message encoded by buildValidationRules.\n * Returns a map of item index → error message, or null if not an item error.\n */\nexport function parseItemErrors(errorMessage: string | undefined): Record<number, string> | null {\n if (!errorMessage || !errorMessage.startsWith(ITEM_ERRORS_PREFIX)) {\n return null;\n }\n try {\n return JSON.parse(errorMessage.slice(ITEM_ERRORS_PREFIX.length));\n } catch {\n return null;\n }\n}\n"],"names":["_a"],"mappings":"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"}