@objectstack/cli 10.0.0 → 10.3.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.
Files changed (66) hide show
  1. package/dist/commands/compile.d.ts.map +1 -1
  2. package/dist/commands/compile.js +34 -2
  3. package/dist/commands/compile.js.map +1 -1
  4. package/dist/commands/doctor.js +1 -1
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/lint.js +1 -1
  7. package/dist/commands/lint.js.map +1 -1
  8. package/dist/commands/migrate/apply.d.ts +19 -0
  9. package/dist/commands/migrate/apply.d.ts.map +1 -0
  10. package/dist/commands/migrate/apply.js +155 -0
  11. package/dist/commands/migrate/apply.js.map +1 -0
  12. package/dist/commands/migrate/index.d.ts +9 -0
  13. package/dist/commands/migrate/index.d.ts.map +1 -0
  14. package/dist/commands/migrate/index.js +10 -0
  15. package/dist/commands/migrate/index.js.map +1 -0
  16. package/dist/commands/migrate/plan.d.ts +16 -0
  17. package/dist/commands/migrate/plan.d.ts.map +1 -0
  18. package/dist/commands/migrate/plan.js +93 -0
  19. package/dist/commands/migrate/plan.js.map +1 -0
  20. package/dist/commands/package/publish.js +4 -4
  21. package/dist/commands/serve.d.ts.map +1 -1
  22. package/dist/commands/serve.js +74 -98
  23. package/dist/commands/serve.js.map +1 -1
  24. package/dist/commands/start.d.ts.map +1 -1
  25. package/dist/commands/start.js +10 -0
  26. package/dist/commands/start.js.map +1 -1
  27. package/dist/commands/validate.d.ts.map +1 -1
  28. package/dist/commands/validate.js +70 -3
  29. package/dist/commands/validate.js.map +1 -1
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/utils/schema-migrate.d.ts +26 -0
  35. package/dist/utils/schema-migrate.d.ts.map +1 -0
  36. package/dist/utils/schema-migrate.integration.test.d.ts +2 -0
  37. package/dist/utils/schema-migrate.integration.test.d.ts.map +1 -0
  38. package/dist/utils/schema-migrate.integration.test.js +83 -0
  39. package/dist/utils/schema-migrate.integration.test.js.map +1 -0
  40. package/dist/utils/schema-migrate.js +123 -0
  41. package/dist/utils/schema-migrate.js.map +1 -0
  42. package/package.json +48 -47
  43. package/dist/commands/publish.d.ts +0 -17
  44. package/dist/commands/publish.d.ts.map +0 -1
  45. package/dist/commands/publish.js +0 -135
  46. package/dist/commands/publish.js.map +0 -1
  47. package/dist/commands/rollback.d.ts +0 -13
  48. package/dist/commands/rollback.d.ts.map +0 -1
  49. package/dist/commands/rollback.js +0 -77
  50. package/dist/commands/rollback.js.map +0 -1
  51. package/dist/utils/validate-expressions.d.ts +0 -19
  52. package/dist/utils/validate-expressions.d.ts.map +0 -1
  53. package/dist/utils/validate-expressions.js +0 -201
  54. package/dist/utils/validate-expressions.js.map +0 -1
  55. package/dist/utils/validate-expressions.test.d.ts +0 -2
  56. package/dist/utils/validate-expressions.test.d.ts.map +0 -1
  57. package/dist/utils/validate-expressions.test.js +0 -320
  58. package/dist/utils/validate-expressions.test.js.map +0 -1
  59. package/dist/utils/validate-widget-bindings.d.ts +0 -74
  60. package/dist/utils/validate-widget-bindings.d.ts.map +0 -1
  61. package/dist/utils/validate-widget-bindings.js +0 -304
  62. package/dist/utils/validate-widget-bindings.js.map +0 -1
  63. package/dist/utils/validate-widget-bindings.test.d.ts +0 -2
  64. package/dist/utils/validate-widget-bindings.test.d.ts.map +0 -1
  65. package/dist/utils/validate-widget-bindings.test.js +0 -285
  66. package/dist/utils/validate-widget-bindings.test.js.map +0 -1
@@ -1,201 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
- /**
3
- * Build-time expression validation (ADR-0032 §Decision 1a + 1b).
4
- *
5
- * Runs at `objectstack compile`, where the whole normalized stack is in hand —
6
- * so flow conditions can be checked against the *resolved* object schema
7
- * (field existence) in addition to CEL syntax. Uses the one shared validator
8
- * from `@objectstack/formula`, so the verdict matches `registerFlow` and the
9
- * agent `validate_expression` tool exactly.
10
- *
11
- * Scope (v1): flow predicates (start/decision `config.condition` + edge
12
- * `condition`), object validation-rule / formula predicates, and UI action
13
- * `visible` / `disabled` predicates. Each error is located (flow/object/action
14
- * + node/edge/field) with a corrective message.
15
- */
16
- import { validateExpression } from '@objectstack/formula';
17
- /** Coerce an `objects` collection (array or name-keyed map) to an array. */
18
- function asArray(v) {
19
- if (Array.isArray(v))
20
- return v;
21
- if (v && typeof v === 'object') {
22
- return Object.entries(v).map(([name, def]) => ({ name, ...def }));
23
- }
24
- return [];
25
- }
26
- /** object name → set of its field names, for schema-aware field checks. */
27
- function buildFieldIndex(objects) {
28
- const idx = new Map();
29
- for (const obj of objects) {
30
- const name = typeof obj.name === 'string' ? obj.name : undefined;
31
- if (!name)
32
- continue;
33
- const fields = obj.fields;
34
- let names = [];
35
- if (Array.isArray(fields))
36
- names = fields.map(f => f.name).filter((n) => typeof n === 'string');
37
- else if (fields && typeof fields === 'object')
38
- names = Object.keys(fields);
39
- idx.set(name, names);
40
- }
41
- return idx;
42
- }
43
- /**
44
- * Validate every predicate in the stack. Returns the list of issues (empty =
45
- * clean). Caller decides how to surface / whether to fail the build.
46
- */
47
- export function validateStackExpressions(stack) {
48
- const issues = [];
49
- const objects = asArray(stack.objects);
50
- const fieldIndex = buildFieldIndex(objects);
51
- const check = (where, raw, objectName, scope = 'flattened') => {
52
- if (raw == null)
53
- return;
54
- const fields = objectName ? fieldIndex.get(objectName) : undefined;
55
- const res = validateExpression('predicate', raw, objectName ? { objectName, fields, scope } : { scope });
56
- for (const e of res.errors)
57
- issues.push({ where, message: e.message, source: e.source, severity: 'error' });
58
- for (const w of res.warnings)
59
- issues.push({ where, message: w.message, source: w.source, severity: 'warning' });
60
- };
61
- // ── Flows ──────────────────────────────────────────────────────────
62
- for (const flow of asArray(stack.flows)) {
63
- const flowName = typeof flow.name === 'string' ? flow.name : '(unnamed flow)';
64
- const nodes = Array.isArray(flow.nodes) ? flow.nodes : [];
65
- const edges = Array.isArray(flow.edges) ? flow.edges : [];
66
- // The record-change target object — `record.*` refs resolve against it.
67
- const startNode = nodes.find(n => n.type === 'start');
68
- const startCfg = (startNode?.config ?? {});
69
- const objectName = typeof startCfg.objectName === 'string' ? startCfg.objectName : undefined;
70
- for (const node of nodes) {
71
- const cfg = (node.config ?? {});
72
- check(`flow '${flowName}' · node '${node.id}' (${node.type}) condition`, cfg.condition, objectName);
73
- // #1870 — a `script` node must declare a callable target (`actionType` or
74
- // `function`). A node with neither is a silent no-op that otherwise passes
75
- // build. (Function *existence* isn't checkable here — functions are code,
76
- // not serialized into the artifact — so this is a structural check; the
77
- // runtime verifies the named function is actually registered.)
78
- if (node.type === 'script') {
79
- // `function` is canonical; `functionName` is an accepted alias.
80
- const fn = (typeof cfg.function === 'string' ? cfg.function.trim() : '') ||
81
- (typeof cfg.functionName === 'string' ? cfg.functionName.trim() : '');
82
- const action = typeof cfg.actionType === 'string' ? cfg.actionType.trim() : '';
83
- // Inline `config.script` (a JS body) is also a declared form — the
84
- // built-in runtime doesn't execute it (warned at run time), but the node
85
- // is not the empty no-op this check targets, so don't flag it.
86
- const inline = typeof cfg.script === 'string' ? cfg.script.trim() : '';
87
- if (!fn && !action && !inline) {
88
- issues.push({
89
- where: `flow '${flowName}' · node '${node.id}' (script) callable`,
90
- message: `script node declares neither \`actionType\` nor \`function\` — it would do nothing at runtime. ` +
91
- `Name a built-in action (e.g. \`actionType: 'email'\`) or a registered function ` +
92
- `(\`function: 'my_fn'\`, registered via \`defineStack({ functions })\`).`,
93
- source: JSON.stringify({ id: node.id, type: node.type, config: cfg }),
94
- });
95
- }
96
- else if (action === 'invoke_function' && !fn) {
97
- // `actionType: 'invoke_function'` is a marker that names no callable on
98
- // its own — the function name must be in `function`/`functionName`.
99
- issues.push({
100
- where: `flow '${flowName}' · node '${node.id}' (script) callable`,
101
- message: `script node uses \`actionType: 'invoke_function'\` but no \`function\` (or \`functionName\`) — ` +
102
- `it names no callable. Set \`function: 'my_fn'\` and register it via \`defineStack({ functions })\`.`,
103
- source: JSON.stringify({ id: node.id, type: node.type, config: cfg }),
104
- });
105
- }
106
- }
107
- }
108
- for (const edge of edges) {
109
- check(`flow '${flowName}' · edge '${edge.id}' (${edge.source}→${edge.target}) condition`, edge.condition, objectName);
110
- }
111
- }
112
- // ── Object validation-rule + formula predicates ────────────────────
113
- for (const obj of objects) {
114
- const objectName = typeof obj.name === 'string' ? obj.name : undefined;
115
- const validations = obj.validations ?? obj.validationRules;
116
- for (const rule of asArray(validations)) {
117
- const where = `object '${objectName}' · validation '${rule.name ?? '?'}'`;
118
- // Common predicate keys across rule shapes. Validation predicates are
119
- // `record`-scoped — no field flattening — so bare refs are flagged (#1928).
120
- check(where, rule.expression ?? rule.predicate ?? rule.condition ?? rule.formula, objectName, 'record');
121
- // `conditional` rules carry a nested `when` predicate (record-scoped).
122
- check(`${where} when`, rule.when, objectName, 'record');
123
- }
124
- // Field-level formulas (computed fields) reference the same object.
125
- const fields = obj.fields;
126
- const fieldList = Array.isArray(fields)
127
- ? fields
128
- : (fields && typeof fields === 'object' ? Object.values(fields) : []);
129
- for (const f of fieldList) {
130
- // Field-level conditional rules are server-enforced (rule-validator) and
131
- // record-scoped — a bare ref silently fails the rule (required/readonly
132
- // not enforced = data-integrity hole). #1928 class, same as actions.
133
- if (f && typeof f === 'object') {
134
- const fname = f.name ?? '?';
135
- for (const key of ['requiredWhen', 'readonlyWhen', 'conditionalRequired', 'visibleWhen']) {
136
- check(`object '${objectName}' · field '${fname}' ${key}`, f[key], objectName, 'record');
137
- }
138
- }
139
- if (f && typeof f === 'object' && f.formula) {
140
- // formulas are `value` role (any return type), still CEL. They are
141
- // `record`-scoped — `record.<field>`, never bare — so flag bare refs (#1928).
142
- const res = validateExpression('value', f.formula, objectName ? { objectName, fields: fieldIndex.get(objectName), scope: 'record' } : { scope: 'record' });
143
- const fieldWhere = `object '${objectName}' · field '${f.name ?? '?'}' formula`;
144
- for (const e of res.errors)
145
- issues.push({ where: fieldWhere, message: e.message, source: e.source, severity: 'error' });
146
- for (const w of res.warnings)
147
- issues.push({ where: fieldWhere, message: w.message, source: w.source, severity: 'warning' });
148
- }
149
- }
150
- }
151
- // ── Action `visible` / `disabled` predicates ───────────────────────
152
- // Record-scoped, same as validation rules: a record-header / row action's
153
- // `visible` is evaluated by ActionEngine against `{ record, recordId,
154
- // objectName, user, … }` with fail-closed semantics, so a BARE field ref
155
- // (`done` instead of `record.done`) throws and the action is silently hidden
156
- // on every record (the trap behind the #2183 "Mark Done never hides" hunt).
157
- // Flagging it here turns that into a build error with a corrective message.
158
- // `disabled` may be a boolean (skip) or a predicate (check).
159
- const seenActions = new Set();
160
- const checkAction = (where, action, objectName) => {
161
- const obj = objectName
162
- ?? (typeof action.objectName === 'string' ? action.objectName : undefined)
163
- ?? (typeof action.object === 'string' ? action.object : undefined);
164
- const name = typeof action.name === 'string' ? action.name : '?';
165
- const key = `${obj ?? ''}:${name}`;
166
- if (seenActions.has(key))
167
- return; // de-dup (actions are merged onto objects AND kept top-level)
168
- seenActions.add(key);
169
- check(`${where} · action '${name}' visible`, action.visible, obj, 'record');
170
- if (typeof action.disabled !== 'boolean') {
171
- check(`${where} · action '${name}' disabled`, action.disabled, obj, 'record');
172
- }
173
- };
174
- for (const action of asArray(stack.actions)) {
175
- checkAction('stack', action);
176
- }
177
- for (const obj of objects) {
178
- const objectName = typeof obj.name === 'string' ? obj.name : undefined;
179
- for (const action of asArray(obj.actions)) {
180
- checkAction(`object '${objectName}'`, action, objectName);
181
- }
182
- }
183
- // ── Sharing-rule predicates (security-critical, record-scoped) ─────
184
- // A criteria sharing rule's `condition` decides which rows a principal sees.
185
- // It is evaluated against the record, so a bare ref silently changes access.
186
- for (const rule of asArray(stack.sharingRules)) {
187
- const ruleObj = typeof rule.object === 'string' ? rule.object : undefined;
188
- const where = `sharingRule '${rule.name ?? '?'}'${ruleObj ? ` (${ruleObj})` : ''} condition`;
189
- check(where, rule.condition ?? rule.criteria ?? rule.predicate, ruleObj, 'record');
190
- }
191
- // ── Hook `condition` predicates (record-scoped gate) ───────────────
192
- // A lifecycle hook's `condition` skips the handler when false; it is
193
- // evaluated against the record, so a bare ref silently makes the hook
194
- // run on every record (or never) instead of the intended subset.
195
- for (const hook of asArray(stack.hooks)) {
196
- const hookObj = typeof hook.object === 'string' ? hook.object : undefined; // array targets → no single field set
197
- check(`hook '${hook.name ?? '?'}'${hookObj ? ` (${hookObj})` : ''} condition`, hook.condition, hookObj, 'record');
198
- }
199
- return issues;
200
- }
201
- //# sourceMappingURL=validate-expressions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate-expressions.js","sourceRoot":"","sources":["../../src/utils/validate-expressions.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=validate-expressions.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate-expressions.test.d.ts","sourceRoot":"","sources":["../../src/utils/validate-expressions.test.ts"],"names":[],"mappings":""}
@@ -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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"}