@objectstack/cli 10.0.0 → 10.2.0
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/commands/compile.js +2 -2
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/migrate/apply.d.ts +19 -0
- package/dist/commands/migrate/apply.d.ts.map +1 -0
- package/dist/commands/migrate/apply.js +155 -0
- package/dist/commands/migrate/apply.js.map +1 -0
- package/dist/commands/migrate/index.d.ts +9 -0
- package/dist/commands/migrate/index.d.ts.map +1 -0
- package/dist/commands/migrate/index.js +10 -0
- package/dist/commands/migrate/index.js.map +1 -0
- package/dist/commands/migrate/plan.d.ts +16 -0
- package/dist/commands/migrate/plan.d.ts.map +1 -0
- package/dist/commands/migrate/plan.js +93 -0
- package/dist/commands/migrate/plan.js.map +1 -0
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +6 -0
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +37 -3
- package/dist/commands/validate.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/schema-migrate.d.ts +26 -0
- package/dist/utils/schema-migrate.d.ts.map +1 -0
- package/dist/utils/schema-migrate.integration.test.d.ts +2 -0
- package/dist/utils/schema-migrate.integration.test.d.ts.map +1 -0
- package/dist/utils/schema-migrate.integration.test.js +83 -0
- package/dist/utils/schema-migrate.integration.test.js.map +1 -0
- package/dist/utils/schema-migrate.js +123 -0
- package/dist/utils/schema-migrate.js.map +1 -0
- package/package.json +48 -47
- package/dist/utils/validate-expressions.d.ts +0 -19
- package/dist/utils/validate-expressions.d.ts.map +0 -1
- package/dist/utils/validate-expressions.js +0 -201
- package/dist/utils/validate-expressions.js.map +0 -1
- package/dist/utils/validate-expressions.test.d.ts +0 -2
- package/dist/utils/validate-expressions.test.d.ts.map +0 -1
- package/dist/utils/validate-expressions.test.js +0 -320
- package/dist/utils/validate-expressions.test.js.map +0 -1
- package/dist/utils/validate-widget-bindings.d.ts +0 -74
- package/dist/utils/validate-widget-bindings.d.ts.map +0 -1
- package/dist/utils/validate-widget-bindings.js +0 -304
- package/dist/utils/validate-widget-bindings.js.map +0 -1
- package/dist/utils/validate-widget-bindings.test.d.ts +0 -2
- package/dist/utils/validate-widget-bindings.test.d.ts.map +0 -1
- package/dist/utils/validate-widget-bindings.test.js +0 -285
- package/dist/utils/validate-widget-bindings.test.js.map +0 -1
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { validateStackExpressions } from './validate-expressions.js';
|
|
3
|
-
describe('validateStackExpressions (ADR-0032 build-time)', () => {
|
|
4
|
-
const objects = [
|
|
5
|
-
{ name: 'crm_lead', fields: { rating: { type: 'number' }, status: { type: 'text' } } },
|
|
6
|
-
];
|
|
7
|
-
it('passes a clean stack', () => {
|
|
8
|
-
const issues = validateStackExpressions({
|
|
9
|
-
objects,
|
|
10
|
-
flows: [{
|
|
11
|
-
name: 'lead_flow',
|
|
12
|
-
nodes: [
|
|
13
|
-
{ id: 'start', type: 'start', config: { objectName: 'crm_lead' } },
|
|
14
|
-
{ id: 'check', type: 'decision', config: { condition: 'record.rating >= 4' } },
|
|
15
|
-
],
|
|
16
|
-
edges: [{ id: 'e1', source: 'check', target: 'end', condition: 'record.rating < 4' }],
|
|
17
|
-
}],
|
|
18
|
-
});
|
|
19
|
-
expect(issues).toHaveLength(0);
|
|
20
|
-
});
|
|
21
|
-
it('flags a brace-in-CEL condition with location + corrective message', () => {
|
|
22
|
-
const issues = validateStackExpressions({
|
|
23
|
-
objects,
|
|
24
|
-
flows: [{
|
|
25
|
-
name: 'lead_flow',
|
|
26
|
-
nodes: [
|
|
27
|
-
{ id: 'start', type: 'start', config: { objectName: 'crm_lead' } },
|
|
28
|
-
{ id: 'check', type: 'decision', config: { condition: '{record.rating} >= 4' } },
|
|
29
|
-
],
|
|
30
|
-
edges: [],
|
|
31
|
-
}],
|
|
32
|
-
});
|
|
33
|
-
expect(issues).toHaveLength(1);
|
|
34
|
-
expect(issues[0].where).toContain("flow 'lead_flow'");
|
|
35
|
-
expect(issues[0].where).toContain("node 'check'");
|
|
36
|
-
expect(issues[0].message).toMatch(/map literal|bare reference/);
|
|
37
|
-
expect(issues[0].source).toBe('{record.rating} >= 4');
|
|
38
|
-
});
|
|
39
|
-
it('flags an unknown record field against the resolved schema (did-you-mean)', () => {
|
|
40
|
-
const issues = validateStackExpressions({
|
|
41
|
-
objects,
|
|
42
|
-
flows: [{
|
|
43
|
-
name: 'lead_flow',
|
|
44
|
-
nodes: [
|
|
45
|
-
{ id: 'start', type: 'start', config: { objectName: 'crm_lead' } },
|
|
46
|
-
{ id: 'check', type: 'decision', config: { condition: 'record.raitng >= 4' } },
|
|
47
|
-
],
|
|
48
|
-
edges: [],
|
|
49
|
-
}],
|
|
50
|
-
});
|
|
51
|
-
expect(issues).toHaveLength(1);
|
|
52
|
-
expect(issues[0].message).toMatch(/unknown field `raitng`/);
|
|
53
|
-
expect(issues[0].message).toMatch(/did you mean `rating`/);
|
|
54
|
-
});
|
|
55
|
-
it('validates object validation-rule predicates too', () => {
|
|
56
|
-
const issues = validateStackExpressions({
|
|
57
|
-
objects: [
|
|
58
|
-
{ name: 'crm_lead', fields: { rating: {} }, validations: [{ name: 'r1', expression: '{record.rating} > 0' }] },
|
|
59
|
-
],
|
|
60
|
-
});
|
|
61
|
-
expect(issues).toHaveLength(1);
|
|
62
|
-
expect(issues[0].where).toContain("validation 'r1'");
|
|
63
|
-
});
|
|
64
|
-
// #1870 — a `script` node that names no callable is a silent no-op.
|
|
65
|
-
it('flags a script node that declares neither actionType nor function (#1870)', () => {
|
|
66
|
-
const issues = validateStackExpressions({
|
|
67
|
-
flows: [{
|
|
68
|
-
name: 'helpdesk_flow',
|
|
69
|
-
nodes: [
|
|
70
|
-
{ id: 'start', type: 'start', config: {} },
|
|
71
|
-
{ id: 'triage', type: 'script', config: { actionType: undefined } },
|
|
72
|
-
],
|
|
73
|
-
edges: [],
|
|
74
|
-
}],
|
|
75
|
-
});
|
|
76
|
-
expect(issues).toHaveLength(1);
|
|
77
|
-
expect(issues[0].where).toContain("node 'triage' (script) callable");
|
|
78
|
-
expect(issues[0].message).toMatch(/neither .*actionType.* nor .*function/);
|
|
79
|
-
});
|
|
80
|
-
it('accepts a script node that names a built-in action or a function (#1870)', () => {
|
|
81
|
-
const issues = validateStackExpressions({
|
|
82
|
-
flows: [{
|
|
83
|
-
name: 'helpdesk_flow',
|
|
84
|
-
nodes: [
|
|
85
|
-
{ id: 'start', type: 'start', config: {} },
|
|
86
|
-
{ id: 'mail', type: 'script', config: { actionType: 'email' } },
|
|
87
|
-
{ id: 'triage', type: 'script', config: { function: 'helpdesk.aiTriageStub' } },
|
|
88
|
-
{ id: 'inline', type: 'script', config: { script: 'variables.x = 1;' } },
|
|
89
|
-
],
|
|
90
|
-
edges: [],
|
|
91
|
-
}],
|
|
92
|
-
});
|
|
93
|
-
expect(issues).toHaveLength(0);
|
|
94
|
-
});
|
|
95
|
-
// #1870 DX — `functionName` is an accepted alias for `function`.
|
|
96
|
-
it('accepts a script node that names a callable via the functionName alias', () => {
|
|
97
|
-
const issues = validateStackExpressions({
|
|
98
|
-
flows: [{
|
|
99
|
-
name: 'helpdesk_flow',
|
|
100
|
-
nodes: [
|
|
101
|
-
{ id: 'start', type: 'start', config: {} },
|
|
102
|
-
{ id: 'triage', type: 'script', config: { actionType: 'invoke_function', functionName: 'helpdesk.aiTriageStub' } },
|
|
103
|
-
],
|
|
104
|
-
edges: [],
|
|
105
|
-
}],
|
|
106
|
-
});
|
|
107
|
-
expect(issues).toHaveLength(0);
|
|
108
|
-
});
|
|
109
|
-
it('flags actionType invoke_function with no function/functionName', () => {
|
|
110
|
-
const issues = validateStackExpressions({
|
|
111
|
-
flows: [{
|
|
112
|
-
name: 'helpdesk_flow',
|
|
113
|
-
nodes: [
|
|
114
|
-
{ id: 'start', type: 'start', config: {} },
|
|
115
|
-
{ id: 'triage', type: 'script', config: { actionType: 'invoke_function', inputs: { x: 1 } } },
|
|
116
|
-
],
|
|
117
|
-
edges: [],
|
|
118
|
-
}],
|
|
119
|
-
});
|
|
120
|
-
expect(issues).toHaveLength(1);
|
|
121
|
-
expect(issues[0].message).toMatch(/invoke_function.*no .*function/i);
|
|
122
|
-
});
|
|
123
|
-
// #1928 — bare field references are silently null in `record`-scoped sites
|
|
124
|
-
// (field formulas + validation predicates) but correct in flattened flow
|
|
125
|
-
// conditions. The validator wires the scope per site.
|
|
126
|
-
describe('bare-reference detection by site scope (#1928)', () => {
|
|
127
|
-
it('flags a bare reference in a field formula', () => {
|
|
128
|
-
const issues = validateStackExpressions({
|
|
129
|
-
objects: [{
|
|
130
|
-
name: 'crm_opportunity',
|
|
131
|
-
fields: {
|
|
132
|
-
amount: { type: 'currency' },
|
|
133
|
-
probability: { type: 'percent' },
|
|
134
|
-
expected_revenue: { type: 'formula', name: 'expected_revenue', formula: 'amount * probability / 100' },
|
|
135
|
-
},
|
|
136
|
-
}],
|
|
137
|
-
});
|
|
138
|
-
expect(issues).toHaveLength(1);
|
|
139
|
-
expect(issues[0].where).toContain("field 'expected_revenue' formula");
|
|
140
|
-
expect(issues[0].message).toMatch(/bare reference `(amount|probability)`/);
|
|
141
|
-
});
|
|
142
|
-
it('flags a bare reference in a validation predicate', () => {
|
|
143
|
-
const issues = validateStackExpressions({
|
|
144
|
-
objects: [{
|
|
145
|
-
name: 'crm_lead',
|
|
146
|
-
fields: { lead_score: { type: 'number' } },
|
|
147
|
-
validations: [{ name: 'lead_score_range', expression: 'lead_score != null && lead_score > 100' }],
|
|
148
|
-
}],
|
|
149
|
-
});
|
|
150
|
-
expect(issues).toHaveLength(1);
|
|
151
|
-
expect(issues[0].where).toContain("validation 'lead_score_range'");
|
|
152
|
-
expect(issues[0].message).toMatch(/bare reference `lead_score`/);
|
|
153
|
-
});
|
|
154
|
-
it('accepts the record-qualified forms', () => {
|
|
155
|
-
const issues = validateStackExpressions({
|
|
156
|
-
objects: [{
|
|
157
|
-
name: 'crm_opportunity',
|
|
158
|
-
fields: {
|
|
159
|
-
amount: { type: 'currency' },
|
|
160
|
-
probability: { type: 'percent' },
|
|
161
|
-
expected_revenue: { type: 'formula', name: 'expected_revenue', formula: 'record.amount * record.probability / 100' },
|
|
162
|
-
},
|
|
163
|
-
validations: [{ name: 'amt', expression: 'record.amount != null && record.amount >= 0' }],
|
|
164
|
-
}],
|
|
165
|
-
});
|
|
166
|
-
expect(issues).toHaveLength(0);
|
|
167
|
-
});
|
|
168
|
-
it('does NOT flag bare references in a flow condition (flattened scope)', () => {
|
|
169
|
-
const issues = validateStackExpressions({
|
|
170
|
-
objects: [{ name: 'crm_opportunity', fields: { stage: { type: 'select' }, amount: { type: 'currency' } } }],
|
|
171
|
-
flows: [{
|
|
172
|
-
name: 'high_value_deal',
|
|
173
|
-
nodes: [
|
|
174
|
-
{ id: 'start', type: 'start', config: { objectName: 'crm_opportunity', condition: 'amount > 100000 && previous.amount <= 100000' } },
|
|
175
|
-
],
|
|
176
|
-
edges: [{ id: 'e1', source: 'start', target: 'end', condition: 'stage != "closed_won"' }],
|
|
177
|
-
}],
|
|
178
|
-
});
|
|
179
|
-
expect(issues).toHaveLength(0);
|
|
180
|
-
});
|
|
181
|
-
// #1928 tier 3 — a likely field typo in a flow condition is a non-blocking warning.
|
|
182
|
-
it('warns (severity=warning) on a likely field typo in a flow condition', () => {
|
|
183
|
-
const issues = validateStackExpressions({
|
|
184
|
-
objects: [{ name: 'crm_opportunity', fields: { stage: { type: 'select' }, amount: { type: 'currency' } } }],
|
|
185
|
-
flows: [{
|
|
186
|
-
name: 'opp_won',
|
|
187
|
-
nodes: [
|
|
188
|
-
{ id: 'start', type: 'start', config: { objectName: 'crm_opportunity', condition: 'stagee == "closed_won"' } },
|
|
189
|
-
],
|
|
190
|
-
edges: [],
|
|
191
|
-
}],
|
|
192
|
-
});
|
|
193
|
-
expect(issues).toHaveLength(1);
|
|
194
|
-
expect(issues[0].severity).toBe('warning');
|
|
195
|
-
expect(issues[0].message).toMatch(/did you mean `stage`/);
|
|
196
|
-
});
|
|
197
|
-
it('does not warn when the bare ref is far from any field (likely a flow variable)', () => {
|
|
198
|
-
const issues = validateStackExpressions({
|
|
199
|
-
objects: [{ name: 'crm_opportunity', fields: { stage: { type: 'select' } } }],
|
|
200
|
-
flows: [{
|
|
201
|
-
name: 'renewal',
|
|
202
|
-
nodes: [{ id: 'start', type: 'start', config: { objectName: 'crm_opportunity' } }],
|
|
203
|
-
edges: [{ id: 'e1', source: 'start', target: 'end', condition: 'expiring_deals.length > 0' }],
|
|
204
|
-
}],
|
|
205
|
-
});
|
|
206
|
-
expect(issues).toHaveLength(0);
|
|
207
|
-
});
|
|
208
|
-
it('tags record-scoped bare-ref issues as errors', () => {
|
|
209
|
-
const issues = validateStackExpressions({
|
|
210
|
-
objects: [{
|
|
211
|
-
name: 'crm_lead',
|
|
212
|
-
fields: { lead_score: { type: 'number' } },
|
|
213
|
-
validations: [{ name: 'r', expression: 'lead_score > 100' }],
|
|
214
|
-
}],
|
|
215
|
-
});
|
|
216
|
-
expect(issues).toHaveLength(1);
|
|
217
|
-
expect(issues[0].severity).toBe('error');
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
describe('action visible/disabled predicates (record-scoped) — #2183 class', () => {
|
|
221
|
-
it('flags a bare-field `visible` on a stack action (the trap that hid Mark Done)', () => {
|
|
222
|
-
const issues = validateStackExpressions({
|
|
223
|
-
objects: [{ name: 'showcase_task', fields: { done: { type: 'boolean' }, status: { type: 'select' } } }],
|
|
224
|
-
actions: [{ name: 'mark_done', objectName: 'showcase_task', type: 'script', locations: ['record_header'], visible: '!done' }],
|
|
225
|
-
});
|
|
226
|
-
const v = issues.filter(i => i.where.includes("action 'mark_done' visible"));
|
|
227
|
-
expect(v).toHaveLength(1);
|
|
228
|
-
expect(v[0].severity).toBe('error');
|
|
229
|
-
expect(v[0].message).toMatch(/bare reference `done`/);
|
|
230
|
-
});
|
|
231
|
-
it('accepts the record-qualified form', () => {
|
|
232
|
-
const issues = validateStackExpressions({
|
|
233
|
-
objects: [{ name: 'showcase_task', fields: { done: { type: 'boolean' } } }],
|
|
234
|
-
actions: [{ name: 'mark_done', objectName: 'showcase_task', type: 'script', visible: '!record.done' }],
|
|
235
|
-
});
|
|
236
|
-
expect(issues).toHaveLength(0);
|
|
237
|
-
});
|
|
238
|
-
it('accepts ambient globals (ctx / features / user) used by platform actions', () => {
|
|
239
|
-
const issues = validateStackExpressions({
|
|
240
|
-
objects: [{ name: 'sys_user', fields: { id: { type: 'text' }, email_verified: { type: 'boolean' } } }],
|
|
241
|
-
actions: [{ name: 'verify_email', objectName: 'sys_user', visible: 'record.id == ctx.user.id && record.email_verified == false && features.x != true' }],
|
|
242
|
-
});
|
|
243
|
-
expect(issues).toHaveLength(0);
|
|
244
|
-
});
|
|
245
|
-
it('flags a bare-field `disabled` predicate but ignores a boolean `disabled`', () => {
|
|
246
|
-
const bad = validateStackExpressions({
|
|
247
|
-
objects: [{ name: 'crm_lead', fields: { status: { type: 'select' } } }],
|
|
248
|
-
actions: [{ name: 'park', objectName: 'crm_lead', disabled: 'status == "converted"' }],
|
|
249
|
-
});
|
|
250
|
-
expect(bad.filter(i => i.where.includes("action 'park' disabled"))).toHaveLength(1);
|
|
251
|
-
const ok = validateStackExpressions({
|
|
252
|
-
objects: [{ name: 'crm_lead', fields: { status: { type: 'select' } } }],
|
|
253
|
-
actions: [{ name: 'park', objectName: 'crm_lead', disabled: true }],
|
|
254
|
-
});
|
|
255
|
-
expect(ok).toHaveLength(0);
|
|
256
|
-
});
|
|
257
|
-
it('validates an action attached to an object (record scope = parent object)', () => {
|
|
258
|
-
const issues = validateStackExpressions({
|
|
259
|
-
objects: [{
|
|
260
|
-
name: 'showcase_task',
|
|
261
|
-
fields: { done: { type: 'boolean' } },
|
|
262
|
-
actions: [{ name: 'mark_done', type: 'script', visible: '!done' }],
|
|
263
|
-
}],
|
|
264
|
-
});
|
|
265
|
-
expect(issues.filter(i => i.where.includes("action 'mark_done' visible"))).toHaveLength(1);
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
describe('record-scoped coverage extensions (field rules / sharing / hooks / nested when)', () => {
|
|
269
|
-
it('flags a bare-field `readonlyWhen`/`requiredWhen` on a field', () => {
|
|
270
|
-
const issues = validateStackExpressions({
|
|
271
|
-
objects: [{
|
|
272
|
-
name: 'showcase_task',
|
|
273
|
-
fields: {
|
|
274
|
-
done: { type: 'boolean', readonlyWhen: 'done == true' },
|
|
275
|
-
title: { type: 'text', requiredWhen: 'status == "x"' },
|
|
276
|
-
},
|
|
277
|
-
}],
|
|
278
|
-
});
|
|
279
|
-
expect(issues.some(i => i.where.includes('readonlyWhen') && /bare reference `done`/.test(i.message))).toBe(true);
|
|
280
|
-
expect(issues.some(i => i.where.includes('requiredWhen') && /bare reference `status`/.test(i.message))).toBe(true);
|
|
281
|
-
});
|
|
282
|
-
it('accepts record-qualified field rules and the master-detail `parent` namespace', () => {
|
|
283
|
-
const issues = validateStackExpressions({
|
|
284
|
-
objects: [{
|
|
285
|
-
name: 'inv_line',
|
|
286
|
-
fields: {
|
|
287
|
-
qty: { type: 'number', readonlyWhen: "parent.status == 'paid'" },
|
|
288
|
-
note: { type: 'text', requiredWhen: 'record.qty >= 100' },
|
|
289
|
-
},
|
|
290
|
-
}],
|
|
291
|
-
});
|
|
292
|
-
expect(issues).toHaveLength(0);
|
|
293
|
-
});
|
|
294
|
-
it('flags a bare-field sharing-rule condition', () => {
|
|
295
|
-
const issues = validateStackExpressions({
|
|
296
|
-
objects: [{ name: 'crm_account', fields: { region: { type: 'text' } } }],
|
|
297
|
-
sharingRules: [{ name: 'sales_region', object: 'crm_account', condition: 'region == "EMEA"' }],
|
|
298
|
-
});
|
|
299
|
-
expect(issues.some(i => i.where.includes("sharingRule 'sales_region'") && /bare reference `region`/.test(i.message))).toBe(true);
|
|
300
|
-
});
|
|
301
|
-
it('flags a bare-field hook condition', () => {
|
|
302
|
-
const issues = validateStackExpressions({
|
|
303
|
-
objects: [{ name: 'crm_lead', fields: { status: { type: 'select' } } }],
|
|
304
|
-
hooks: [{ name: 'on_close', object: 'crm_lead', condition: 'status == "closed"' }],
|
|
305
|
-
});
|
|
306
|
-
expect(issues.some(i => i.where.includes("hook 'on_close'") && /bare reference `status`/.test(i.message))).toBe(true);
|
|
307
|
-
});
|
|
308
|
-
it('flags a bare-field nested `when` on a conditional validation rule', () => {
|
|
309
|
-
const issues = validateStackExpressions({
|
|
310
|
-
objects: [{
|
|
311
|
-
name: 'crm_account',
|
|
312
|
-
fields: { tier: { type: 'select' } },
|
|
313
|
-
validations: [{ name: 'cond', type: 'conditional', when: 'tier == "gold"', then: { type: 'required' } }],
|
|
314
|
-
}],
|
|
315
|
-
});
|
|
316
|
-
expect(issues.some(i => i.where.includes('when') && /bare reference `tier`/.test(i.message))).toBe(true);
|
|
317
|
-
});
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
//# sourceMappingURL=validate-expressions.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-expressions.test.js","sourceRoot":"","sources":["../../src/utils/validate-expressions.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build-time dashboard widget binding diagnostics (issues #1719, #1721).
|
|
3
|
-
*
|
|
4
|
-
* Runs at `objectstack validate`/`compile`/`build` AFTER the stack has been
|
|
5
|
-
* schema-parsed, so every widget's `dataset` reference can be linked to its
|
|
6
|
-
* `defineDataset` and each entry in `dimensions`/`values` resolved to a
|
|
7
|
-
* declared dimension/measure. This is the semantic/cross-reference phase —
|
|
8
|
-
* the rules here cannot run during plain Zod parsing of the raw widget
|
|
9
|
-
* literal (the dataset may even live in another package of the stack).
|
|
10
|
-
*
|
|
11
|
-
* Reference-integrity rules (#1721) — severity `error`, the page is broken:
|
|
12
|
-
*
|
|
13
|
-
* - `widget-dataset-unknown` — `dataset` does not resolve to a declared
|
|
14
|
-
* `Dataset`.
|
|
15
|
-
* - `widget-dimension-unknown` — a `dimensions[]` entry is not a dimension
|
|
16
|
-
* name on the bound dataset.
|
|
17
|
-
* - `widget-measure-unknown` — a `values[]` entry is not a measure name on
|
|
18
|
-
* the bound dataset.
|
|
19
|
-
* - `chart-field-unknown` — a `chartConfig` binding names a field the query
|
|
20
|
-
* result will not contain: `xAxis.field` must be one of the widget's
|
|
21
|
-
* dimensions (or a dataset dimension), and each `yAxis[].field` /
|
|
22
|
-
* `series[].name` must be one of the widget's selected measures
|
|
23
|
-
* (`values`). Post-cutover (ADR-0021) the result rows are keyed by
|
|
24
|
-
* measure NAME (e.g. `sum_amount`), not the base column (`amount`) — a
|
|
25
|
-
* stale base-column reference renders the axis but an empty series.
|
|
26
|
-
*
|
|
27
|
-
* Advisory rules — severity `warning`, build stays green:
|
|
28
|
-
*
|
|
29
|
-
* - `chart-config-missing` — a chart-type widget (bar/line/pie/…) has no
|
|
30
|
-
* `chartConfig`, so the renderer cannot tell which measure to plot.
|
|
31
|
-
* - `table-count-only` (#1719) — a `table`/`pivot` widget whose selected
|
|
32
|
-
* measures are ALL `aggregate: 'count'` and which declares no
|
|
33
|
-
* `dimensions` asks the analytics service for a single summary row. That
|
|
34
|
-
* is the shape a `metric` widget wants — for a table it almost always
|
|
35
|
-
* means the author wanted a per-record listing, which is not an
|
|
36
|
-
* analytics dataset at all (model it as an object-bound ListView,
|
|
37
|
-
* ADR-0017). Evaluated on the WIDGET's binding, not the dataset.
|
|
38
|
-
*
|
|
39
|
-
* Warnings can be deliberately suppressed per widget via
|
|
40
|
-
* `suppressWarnings: ['<rule-id>']`; errors cannot — they describe a
|
|
41
|
-
* binding the analytics service cannot satisfy.
|
|
42
|
-
*/
|
|
43
|
-
export declare const WIDGET_DATASET_UNKNOWN = "widget-dataset-unknown";
|
|
44
|
-
export declare const WIDGET_DIMENSION_UNKNOWN = "widget-dimension-unknown";
|
|
45
|
-
export declare const WIDGET_MEASURE_UNKNOWN = "widget-measure-unknown";
|
|
46
|
-
export declare const CHART_FIELD_UNKNOWN = "chart-field-unknown";
|
|
47
|
-
export declare const CHART_CONFIG_MISSING = "chart-config-missing";
|
|
48
|
-
export declare const TABLE_COUNT_ONLY = "table-count-only";
|
|
49
|
-
export type WidgetBindingSeverity = 'error' | 'warning';
|
|
50
|
-
export interface WidgetBindingFinding {
|
|
51
|
-
/** `error` = unresolvable binding (broken page); `warning` = advisory. */
|
|
52
|
-
severity: WidgetBindingSeverity;
|
|
53
|
-
/** Diagnostic rule id (registry entry), e.g. `widget-measure-unknown`. */
|
|
54
|
-
rule: string;
|
|
55
|
-
/** Human-readable location, e.g. `dashboard "x" › widget "y"`. */
|
|
56
|
-
where: string;
|
|
57
|
-
/** Config path, e.g. `dashboards[0].widgets[3]`. */
|
|
58
|
-
path: string;
|
|
59
|
-
/** What is wrong. */
|
|
60
|
-
message: string;
|
|
61
|
-
/** How to fix (or deliberately suppress) it. */
|
|
62
|
-
hint: string;
|
|
63
|
-
}
|
|
64
|
-
type AnyRec = Record<string, unknown>;
|
|
65
|
-
/**
|
|
66
|
-
* Validate every dashboard widget's dataset binding. Returns the list of
|
|
67
|
-
* findings (empty = clean). Caller decides how to surface them: `error`
|
|
68
|
-
* findings describe bindings the analytics service cannot satisfy and
|
|
69
|
-
* should fail validate/build; `warning` findings are advisory and must
|
|
70
|
-
* never fail the build on their own.
|
|
71
|
-
*/
|
|
72
|
-
export declare function validateWidgetBindings(stack: AnyRec): WidgetBindingFinding[];
|
|
73
|
-
export {};
|
|
74
|
-
//# sourceMappingURL=validate-widget-bindings.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-widget-bindings.d.ts","sourceRoot":"","sources":["../../src/utils/validate-widget-bindings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AACnE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,EAAE,qBAAqB,CAAC;IAChC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA6EtC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,EAAE,CA2L5E"}
|