@objectstack/lint 11.10.0 → 12.1.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/index.cjs +159 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -19
- package/dist/index.d.ts +90 -19
- package/dist/index.js +154 -16
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -69,7 +69,7 @@ interface WidgetBindingFinding {
|
|
|
69
69
|
/** How to fix (or deliberately suppress) it. */
|
|
70
70
|
hint: string;
|
|
71
71
|
}
|
|
72
|
-
type AnyRec$
|
|
72
|
+
type AnyRec$a = Record<string, unknown>;
|
|
73
73
|
/**
|
|
74
74
|
* Validate every dashboard widget's dataset binding. Returns the list of
|
|
75
75
|
* findings (empty = clean). Caller decides how to surface them: `error`
|
|
@@ -77,7 +77,7 @@ type AnyRec$8 = Record<string, unknown>;
|
|
|
77
77
|
* should fail validate/build; `warning` findings are advisory and must
|
|
78
78
|
* never fail the build on their own.
|
|
79
79
|
*/
|
|
80
|
-
declare function validateWidgetBindings(stack: AnyRec$
|
|
80
|
+
declare function validateWidgetBindings(stack: AnyRec$a): WidgetBindingFinding[];
|
|
81
81
|
|
|
82
82
|
interface ExprIssue {
|
|
83
83
|
where: string;
|
|
@@ -90,12 +90,35 @@ interface ExprIssue {
|
|
|
90
90
|
*/
|
|
91
91
|
severity?: 'error' | 'warning';
|
|
92
92
|
}
|
|
93
|
-
type AnyRec$
|
|
93
|
+
type AnyRec$9 = Record<string, unknown>;
|
|
94
94
|
/**
|
|
95
95
|
* Validate every predicate in the stack. Returns the list of issues (empty =
|
|
96
96
|
* clean). Caller decides how to surface / whether to fail the build.
|
|
97
97
|
*/
|
|
98
|
-
declare function validateStackExpressions(stack: AnyRec$
|
|
98
|
+
declare function validateStackExpressions(stack: AnyRec$9): ExprIssue[];
|
|
99
|
+
|
|
100
|
+
type ListViewModeSeverity = 'error' | 'warning';
|
|
101
|
+
interface ListViewModeFinding {
|
|
102
|
+
severity: ListViewModeSeverity;
|
|
103
|
+
rule: string;
|
|
104
|
+
/** Human-readable location, e.g. `object "task" › listViews.my_pending`. */
|
|
105
|
+
where: string;
|
|
106
|
+
/** Config path, e.g. `objects[0].listViews.my_pending.userFilters`. */
|
|
107
|
+
path: string;
|
|
108
|
+
message: string;
|
|
109
|
+
hint: string;
|
|
110
|
+
}
|
|
111
|
+
declare const LIST_VIEW_FILTERS_IN_VIEWS_MODE = "list-view-filters-in-views-mode";
|
|
112
|
+
type AnyRec$8 = Record<string, unknown>;
|
|
113
|
+
/**
|
|
114
|
+
* Flag ADR-0053 "views" mode violations: `userFilters` / `quickFilters` on an
|
|
115
|
+
* object's built-in named views or a `defineView` default `list` / named
|
|
116
|
+
* `listViews`. Returns the list of findings (empty = clean). Caller decides how
|
|
117
|
+
* to surface / whether to fail the build.
|
|
118
|
+
*
|
|
119
|
+
* Feed the PRE-parse stack (normalizeStackInput output) — see file header.
|
|
120
|
+
*/
|
|
121
|
+
declare function validateListViewMode(stack: AnyRec$8): ListViewModeFinding[];
|
|
99
122
|
|
|
100
123
|
type StyleSeverity = 'error' | 'warning';
|
|
101
124
|
interface StyleFinding {
|
|
@@ -113,14 +136,14 @@ declare const STYLE_CLASSNAME_TAILWIND = "style-classname-tailwind";
|
|
|
113
136
|
declare const STYLE_RESPONSIVE_NO_BASE = "style-responsive-no-base";
|
|
114
137
|
declare const STYLE_UNKNOWN_CSS_PROPERTY = "style-unknown-css-property";
|
|
115
138
|
declare const STYLE_UNKNOWN_TOKEN = "style-unknown-token";
|
|
116
|
-
type AnyRec$
|
|
139
|
+
type AnyRec$7 = Record<string, unknown>;
|
|
117
140
|
/**
|
|
118
141
|
* Validate every page's component tree for SDUI styling correctness (ADR-0065).
|
|
119
142
|
* Returns findings (empty = clean). `error` findings describe styles that are
|
|
120
143
|
* silently dropped and should fail validate/build; `warning` findings are
|
|
121
144
|
* advisory (typos, drift, footguns).
|
|
122
145
|
*/
|
|
123
|
-
declare function validateResponsiveStyles(stack: AnyRec$
|
|
146
|
+
declare function validateResponsiveStyles(stack: AnyRec$7): StyleFinding[];
|
|
124
147
|
|
|
125
148
|
type JsxPageSeverity = 'error' | 'warning';
|
|
126
149
|
interface JsxPageFinding {
|
|
@@ -133,8 +156,8 @@ interface JsxPageFinding {
|
|
|
133
156
|
message: string;
|
|
134
157
|
hint: string;
|
|
135
158
|
}
|
|
136
|
-
type AnyRec$
|
|
137
|
-
declare function validateJsxPages(stack: AnyRec$
|
|
159
|
+
type AnyRec$6 = Record<string, unknown>;
|
|
160
|
+
declare function validateJsxPages(stack: AnyRec$6, opts?: {
|
|
138
161
|
manifest?: Manifest;
|
|
139
162
|
}): JsxPageFinding[];
|
|
140
163
|
|
|
@@ -147,8 +170,8 @@ interface ReactPageFinding {
|
|
|
147
170
|
message: string;
|
|
148
171
|
hint: string;
|
|
149
172
|
}
|
|
150
|
-
type AnyRec$
|
|
151
|
-
declare function validateReactPages(stack: AnyRec$
|
|
173
|
+
type AnyRec$5 = Record<string, unknown>;
|
|
174
|
+
declare function validateReactPages(stack: AnyRec$5): ReactPageFinding[];
|
|
152
175
|
|
|
153
176
|
type ReactPropSeverity = 'error' | 'warning';
|
|
154
177
|
interface ReactPropFinding {
|
|
@@ -159,8 +182,8 @@ interface ReactPropFinding {
|
|
|
159
182
|
message: string;
|
|
160
183
|
hint: string;
|
|
161
184
|
}
|
|
162
|
-
type AnyRec$
|
|
163
|
-
declare function validateReactPageProps(stack: AnyRec$
|
|
185
|
+
type AnyRec$4 = Record<string, unknown>;
|
|
186
|
+
declare function validateReactPageProps(stack: AnyRec$4): ReactPropFinding[];
|
|
164
187
|
|
|
165
188
|
type SourceStyleSeverity = 'error' | 'warning';
|
|
166
189
|
interface SourceStyleFinding {
|
|
@@ -172,8 +195,8 @@ interface SourceStyleFinding {
|
|
|
172
195
|
hint: string;
|
|
173
196
|
}
|
|
174
197
|
declare const PAGE_SOURCE_CLASSNAME = "page-source-className-tailwind";
|
|
175
|
-
type AnyRec$
|
|
176
|
-
declare function validatePageSourceStyling(stack: AnyRec$
|
|
198
|
+
type AnyRec$3 = Record<string, unknown>;
|
|
199
|
+
declare function validatePageSourceStyling(stack: AnyRec$3): SourceStyleFinding[];
|
|
177
200
|
|
|
178
201
|
/**
|
|
179
202
|
* Build-time record-title diagnostics (ADR-0079).
|
|
@@ -217,14 +240,14 @@ interface RecordTitleFinding {
|
|
|
217
240
|
/** How to fix it. */
|
|
218
241
|
hint: string;
|
|
219
242
|
}
|
|
220
|
-
type AnyRec$
|
|
243
|
+
type AnyRec$2 = Record<string, unknown>;
|
|
221
244
|
/**
|
|
222
245
|
* Validate every object's record-title declaration. Returns the list of
|
|
223
246
|
* findings (empty = clean). Both rules are advisory (`warning`): the caller
|
|
224
247
|
* must never fail the build on them alone — auto-provision + the `Record #<id>`
|
|
225
248
|
* floor guarantee a resolvable title at runtime.
|
|
226
249
|
*/
|
|
227
|
-
declare function validateRecordTitle(stack: AnyRec$
|
|
250
|
+
declare function validateRecordTitle(stack: AnyRec$2): RecordTitleFinding[];
|
|
228
251
|
|
|
229
252
|
/**
|
|
230
253
|
* Build-time semantic-role diagnostics (ADR-0085).
|
|
@@ -261,12 +284,60 @@ interface SemanticRoleFinding {
|
|
|
261
284
|
/** How to fix it. */
|
|
262
285
|
hint: string;
|
|
263
286
|
}
|
|
264
|
-
type AnyRec = Record<string, unknown>;
|
|
287
|
+
type AnyRec$1 = Record<string, unknown>;
|
|
265
288
|
/**
|
|
266
289
|
* Validate every object's semantic-role pointers. Returns the list of
|
|
267
290
|
* findings (empty = clean). Advisory only — the caller must never fail the
|
|
268
291
|
* build on these alone.
|
|
269
292
|
*/
|
|
270
|
-
declare function validateSemanticRoles(stack: AnyRec): SemanticRoleFinding[];
|
|
293
|
+
declare function validateSemanticRoles(stack: AnyRec$1): SemanticRoleFinding[];
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Build-time form-layout diagnostics (#2578).
|
|
297
|
+
*
|
|
298
|
+
* Authored form views carry field references and column-layout hints that are
|
|
299
|
+
* Zod-valid but can be silently wrong at render time — the "parsed, unmarked,
|
|
300
|
+
* silently inert" shape ADR-0078 prohibits. This lint catches the two that
|
|
301
|
+
* matter for multi-column, AI-authored forms, uniformly for `os build` /
|
|
302
|
+
* `os validate`, MCP authoring and hand authors (ADR-0019).
|
|
303
|
+
*
|
|
304
|
+
* Both rules are warnings, not errors — nothing is fully broken (an unknown
|
|
305
|
+
* field name is skipped; an over-wide colSpan is clamped) — but each is almost
|
|
306
|
+
* certainly an authoring mistake worth surfacing at author time:
|
|
307
|
+
*
|
|
308
|
+
* - `form-field-unknown` — a section references a field that is not on the
|
|
309
|
+
* form's bound object, so the field silently does not render.
|
|
310
|
+
* - `absolute-colspan-discouraged` — a field uses the absolute `colSpan`. Under
|
|
311
|
+
* a per-surface DERIVED column count (mobile 1 / modal 2 / page 3-4) a fixed
|
|
312
|
+
* span only lines up at the one width the author imagined; the renderer
|
|
313
|
+
* clamps it. The robust primitive is the relative `span: 'full'`.
|
|
314
|
+
*
|
|
315
|
+
* Scope: top-level form `views` (a `sections` array). Forms embedded inside
|
|
316
|
+
* page component trees are a follow-up — the walker deliberately stays shallow
|
|
317
|
+
* so it never guesses at an arbitrary component's object binding.
|
|
318
|
+
*/
|
|
319
|
+
declare const FORM_FIELD_UNKNOWN = "form-field-unknown";
|
|
320
|
+
declare const FORM_COLSPAN_ABSOLUTE = "absolute-colspan-discouraged";
|
|
321
|
+
type FormLayoutSeverity = 'error' | 'warning';
|
|
322
|
+
interface FormLayoutFinding {
|
|
323
|
+
/** Always `warning` today — both rules are advisory (see module note). */
|
|
324
|
+
severity: FormLayoutSeverity;
|
|
325
|
+
/** Diagnostic rule id, e.g. `form-field-unknown`. */
|
|
326
|
+
rule: string;
|
|
327
|
+
/** Human-readable location, e.g. `view "contract_form"`. */
|
|
328
|
+
where: string;
|
|
329
|
+
/** Config path, e.g. `views[2].sections[0].fields[3]`. */
|
|
330
|
+
path: string;
|
|
331
|
+
/** What is wrong. */
|
|
332
|
+
message: string;
|
|
333
|
+
/** How to fix it. */
|
|
334
|
+
hint: string;
|
|
335
|
+
}
|
|
336
|
+
type AnyRec = Record<string, unknown>;
|
|
337
|
+
/**
|
|
338
|
+
* Validate authored form-view layout. Returns findings (empty = clean).
|
|
339
|
+
* Advisory only — the caller must never fail the build on these alone.
|
|
340
|
+
*/
|
|
341
|
+
declare function validateFormLayout(stack: AnyRec): FormLayoutFinding[];
|
|
271
342
|
|
|
272
|
-
export { CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, type JsxPageFinding, type JsxPageSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, validateJsxPages, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
|
343
|
+
export { CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
package/dist/index.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ interface WidgetBindingFinding {
|
|
|
69
69
|
/** How to fix (or deliberately suppress) it. */
|
|
70
70
|
hint: string;
|
|
71
71
|
}
|
|
72
|
-
type AnyRec$
|
|
72
|
+
type AnyRec$a = Record<string, unknown>;
|
|
73
73
|
/**
|
|
74
74
|
* Validate every dashboard widget's dataset binding. Returns the list of
|
|
75
75
|
* findings (empty = clean). Caller decides how to surface them: `error`
|
|
@@ -77,7 +77,7 @@ type AnyRec$8 = Record<string, unknown>;
|
|
|
77
77
|
* should fail validate/build; `warning` findings are advisory and must
|
|
78
78
|
* never fail the build on their own.
|
|
79
79
|
*/
|
|
80
|
-
declare function validateWidgetBindings(stack: AnyRec$
|
|
80
|
+
declare function validateWidgetBindings(stack: AnyRec$a): WidgetBindingFinding[];
|
|
81
81
|
|
|
82
82
|
interface ExprIssue {
|
|
83
83
|
where: string;
|
|
@@ -90,12 +90,35 @@ interface ExprIssue {
|
|
|
90
90
|
*/
|
|
91
91
|
severity?: 'error' | 'warning';
|
|
92
92
|
}
|
|
93
|
-
type AnyRec$
|
|
93
|
+
type AnyRec$9 = Record<string, unknown>;
|
|
94
94
|
/**
|
|
95
95
|
* Validate every predicate in the stack. Returns the list of issues (empty =
|
|
96
96
|
* clean). Caller decides how to surface / whether to fail the build.
|
|
97
97
|
*/
|
|
98
|
-
declare function validateStackExpressions(stack: AnyRec$
|
|
98
|
+
declare function validateStackExpressions(stack: AnyRec$9): ExprIssue[];
|
|
99
|
+
|
|
100
|
+
type ListViewModeSeverity = 'error' | 'warning';
|
|
101
|
+
interface ListViewModeFinding {
|
|
102
|
+
severity: ListViewModeSeverity;
|
|
103
|
+
rule: string;
|
|
104
|
+
/** Human-readable location, e.g. `object "task" › listViews.my_pending`. */
|
|
105
|
+
where: string;
|
|
106
|
+
/** Config path, e.g. `objects[0].listViews.my_pending.userFilters`. */
|
|
107
|
+
path: string;
|
|
108
|
+
message: string;
|
|
109
|
+
hint: string;
|
|
110
|
+
}
|
|
111
|
+
declare const LIST_VIEW_FILTERS_IN_VIEWS_MODE = "list-view-filters-in-views-mode";
|
|
112
|
+
type AnyRec$8 = Record<string, unknown>;
|
|
113
|
+
/**
|
|
114
|
+
* Flag ADR-0053 "views" mode violations: `userFilters` / `quickFilters` on an
|
|
115
|
+
* object's built-in named views or a `defineView` default `list` / named
|
|
116
|
+
* `listViews`. Returns the list of findings (empty = clean). Caller decides how
|
|
117
|
+
* to surface / whether to fail the build.
|
|
118
|
+
*
|
|
119
|
+
* Feed the PRE-parse stack (normalizeStackInput output) — see file header.
|
|
120
|
+
*/
|
|
121
|
+
declare function validateListViewMode(stack: AnyRec$8): ListViewModeFinding[];
|
|
99
122
|
|
|
100
123
|
type StyleSeverity = 'error' | 'warning';
|
|
101
124
|
interface StyleFinding {
|
|
@@ -113,14 +136,14 @@ declare const STYLE_CLASSNAME_TAILWIND = "style-classname-tailwind";
|
|
|
113
136
|
declare const STYLE_RESPONSIVE_NO_BASE = "style-responsive-no-base";
|
|
114
137
|
declare const STYLE_UNKNOWN_CSS_PROPERTY = "style-unknown-css-property";
|
|
115
138
|
declare const STYLE_UNKNOWN_TOKEN = "style-unknown-token";
|
|
116
|
-
type AnyRec$
|
|
139
|
+
type AnyRec$7 = Record<string, unknown>;
|
|
117
140
|
/**
|
|
118
141
|
* Validate every page's component tree for SDUI styling correctness (ADR-0065).
|
|
119
142
|
* Returns findings (empty = clean). `error` findings describe styles that are
|
|
120
143
|
* silently dropped and should fail validate/build; `warning` findings are
|
|
121
144
|
* advisory (typos, drift, footguns).
|
|
122
145
|
*/
|
|
123
|
-
declare function validateResponsiveStyles(stack: AnyRec$
|
|
146
|
+
declare function validateResponsiveStyles(stack: AnyRec$7): StyleFinding[];
|
|
124
147
|
|
|
125
148
|
type JsxPageSeverity = 'error' | 'warning';
|
|
126
149
|
interface JsxPageFinding {
|
|
@@ -133,8 +156,8 @@ interface JsxPageFinding {
|
|
|
133
156
|
message: string;
|
|
134
157
|
hint: string;
|
|
135
158
|
}
|
|
136
|
-
type AnyRec$
|
|
137
|
-
declare function validateJsxPages(stack: AnyRec$
|
|
159
|
+
type AnyRec$6 = Record<string, unknown>;
|
|
160
|
+
declare function validateJsxPages(stack: AnyRec$6, opts?: {
|
|
138
161
|
manifest?: Manifest;
|
|
139
162
|
}): JsxPageFinding[];
|
|
140
163
|
|
|
@@ -147,8 +170,8 @@ interface ReactPageFinding {
|
|
|
147
170
|
message: string;
|
|
148
171
|
hint: string;
|
|
149
172
|
}
|
|
150
|
-
type AnyRec$
|
|
151
|
-
declare function validateReactPages(stack: AnyRec$
|
|
173
|
+
type AnyRec$5 = Record<string, unknown>;
|
|
174
|
+
declare function validateReactPages(stack: AnyRec$5): ReactPageFinding[];
|
|
152
175
|
|
|
153
176
|
type ReactPropSeverity = 'error' | 'warning';
|
|
154
177
|
interface ReactPropFinding {
|
|
@@ -159,8 +182,8 @@ interface ReactPropFinding {
|
|
|
159
182
|
message: string;
|
|
160
183
|
hint: string;
|
|
161
184
|
}
|
|
162
|
-
type AnyRec$
|
|
163
|
-
declare function validateReactPageProps(stack: AnyRec$
|
|
185
|
+
type AnyRec$4 = Record<string, unknown>;
|
|
186
|
+
declare function validateReactPageProps(stack: AnyRec$4): ReactPropFinding[];
|
|
164
187
|
|
|
165
188
|
type SourceStyleSeverity = 'error' | 'warning';
|
|
166
189
|
interface SourceStyleFinding {
|
|
@@ -172,8 +195,8 @@ interface SourceStyleFinding {
|
|
|
172
195
|
hint: string;
|
|
173
196
|
}
|
|
174
197
|
declare const PAGE_SOURCE_CLASSNAME = "page-source-className-tailwind";
|
|
175
|
-
type AnyRec$
|
|
176
|
-
declare function validatePageSourceStyling(stack: AnyRec$
|
|
198
|
+
type AnyRec$3 = Record<string, unknown>;
|
|
199
|
+
declare function validatePageSourceStyling(stack: AnyRec$3): SourceStyleFinding[];
|
|
177
200
|
|
|
178
201
|
/**
|
|
179
202
|
* Build-time record-title diagnostics (ADR-0079).
|
|
@@ -217,14 +240,14 @@ interface RecordTitleFinding {
|
|
|
217
240
|
/** How to fix it. */
|
|
218
241
|
hint: string;
|
|
219
242
|
}
|
|
220
|
-
type AnyRec$
|
|
243
|
+
type AnyRec$2 = Record<string, unknown>;
|
|
221
244
|
/**
|
|
222
245
|
* Validate every object's record-title declaration. Returns the list of
|
|
223
246
|
* findings (empty = clean). Both rules are advisory (`warning`): the caller
|
|
224
247
|
* must never fail the build on them alone — auto-provision + the `Record #<id>`
|
|
225
248
|
* floor guarantee a resolvable title at runtime.
|
|
226
249
|
*/
|
|
227
|
-
declare function validateRecordTitle(stack: AnyRec$
|
|
250
|
+
declare function validateRecordTitle(stack: AnyRec$2): RecordTitleFinding[];
|
|
228
251
|
|
|
229
252
|
/**
|
|
230
253
|
* Build-time semantic-role diagnostics (ADR-0085).
|
|
@@ -261,12 +284,60 @@ interface SemanticRoleFinding {
|
|
|
261
284
|
/** How to fix it. */
|
|
262
285
|
hint: string;
|
|
263
286
|
}
|
|
264
|
-
type AnyRec = Record<string, unknown>;
|
|
287
|
+
type AnyRec$1 = Record<string, unknown>;
|
|
265
288
|
/**
|
|
266
289
|
* Validate every object's semantic-role pointers. Returns the list of
|
|
267
290
|
* findings (empty = clean). Advisory only — the caller must never fail the
|
|
268
291
|
* build on these alone.
|
|
269
292
|
*/
|
|
270
|
-
declare function validateSemanticRoles(stack: AnyRec): SemanticRoleFinding[];
|
|
293
|
+
declare function validateSemanticRoles(stack: AnyRec$1): SemanticRoleFinding[];
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Build-time form-layout diagnostics (#2578).
|
|
297
|
+
*
|
|
298
|
+
* Authored form views carry field references and column-layout hints that are
|
|
299
|
+
* Zod-valid but can be silently wrong at render time — the "parsed, unmarked,
|
|
300
|
+
* silently inert" shape ADR-0078 prohibits. This lint catches the two that
|
|
301
|
+
* matter for multi-column, AI-authored forms, uniformly for `os build` /
|
|
302
|
+
* `os validate`, MCP authoring and hand authors (ADR-0019).
|
|
303
|
+
*
|
|
304
|
+
* Both rules are warnings, not errors — nothing is fully broken (an unknown
|
|
305
|
+
* field name is skipped; an over-wide colSpan is clamped) — but each is almost
|
|
306
|
+
* certainly an authoring mistake worth surfacing at author time:
|
|
307
|
+
*
|
|
308
|
+
* - `form-field-unknown` — a section references a field that is not on the
|
|
309
|
+
* form's bound object, so the field silently does not render.
|
|
310
|
+
* - `absolute-colspan-discouraged` — a field uses the absolute `colSpan`. Under
|
|
311
|
+
* a per-surface DERIVED column count (mobile 1 / modal 2 / page 3-4) a fixed
|
|
312
|
+
* span only lines up at the one width the author imagined; the renderer
|
|
313
|
+
* clamps it. The robust primitive is the relative `span: 'full'`.
|
|
314
|
+
*
|
|
315
|
+
* Scope: top-level form `views` (a `sections` array). Forms embedded inside
|
|
316
|
+
* page component trees are a follow-up — the walker deliberately stays shallow
|
|
317
|
+
* so it never guesses at an arbitrary component's object binding.
|
|
318
|
+
*/
|
|
319
|
+
declare const FORM_FIELD_UNKNOWN = "form-field-unknown";
|
|
320
|
+
declare const FORM_COLSPAN_ABSOLUTE = "absolute-colspan-discouraged";
|
|
321
|
+
type FormLayoutSeverity = 'error' | 'warning';
|
|
322
|
+
interface FormLayoutFinding {
|
|
323
|
+
/** Always `warning` today — both rules are advisory (see module note). */
|
|
324
|
+
severity: FormLayoutSeverity;
|
|
325
|
+
/** Diagnostic rule id, e.g. `form-field-unknown`. */
|
|
326
|
+
rule: string;
|
|
327
|
+
/** Human-readable location, e.g. `view "contract_form"`. */
|
|
328
|
+
where: string;
|
|
329
|
+
/** Config path, e.g. `views[2].sections[0].fields[3]`. */
|
|
330
|
+
path: string;
|
|
331
|
+
/** What is wrong. */
|
|
332
|
+
message: string;
|
|
333
|
+
/** How to fix it. */
|
|
334
|
+
hint: string;
|
|
335
|
+
}
|
|
336
|
+
type AnyRec = Record<string, unknown>;
|
|
337
|
+
/**
|
|
338
|
+
* Validate authored form-view layout. Returns findings (empty = clean).
|
|
339
|
+
* Advisory only — the caller must never fail the build on these alone.
|
|
340
|
+
*/
|
|
341
|
+
declare function validateFormLayout(stack: AnyRec): FormLayoutFinding[];
|
|
271
342
|
|
|
272
|
-
export { CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, type JsxPageFinding, type JsxPageSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, validateJsxPages, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
|
343
|
+
export { CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
package/dist/index.js
CHANGED
|
@@ -371,6 +371,60 @@ function validateStackExpressions(stack) {
|
|
|
371
371
|
return issues;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
// src/validate-list-view-mode.ts
|
|
375
|
+
var LIST_VIEW_FILTERS_IN_VIEWS_MODE = "list-view-filters-in-views-mode";
|
|
376
|
+
var FORBIDDEN_FIELDS = ["userFilters", "quickFilters"];
|
|
377
|
+
function asArray3(v) {
|
|
378
|
+
if (Array.isArray(v)) return v;
|
|
379
|
+
if (v && typeof v === "object") {
|
|
380
|
+
return Object.entries(v).map(([name, def]) => ({
|
|
381
|
+
name,
|
|
382
|
+
...def
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
return [];
|
|
386
|
+
}
|
|
387
|
+
function scanView(view, where, path, out) {
|
|
388
|
+
if (!view || typeof view !== "object") return;
|
|
389
|
+
const rec = view;
|
|
390
|
+
for (const field of FORBIDDEN_FIELDS) {
|
|
391
|
+
if (rec[field] == null) continue;
|
|
392
|
+
out.push({
|
|
393
|
+
severity: "error",
|
|
394
|
+
rule: LIST_VIEW_FILTERS_IN_VIEWS_MODE,
|
|
395
|
+
where,
|
|
396
|
+
path: `${path}.${field}`,
|
|
397
|
+
message: `\`${field}\` is a page filters-mode control and is ignored on an object list view ("views" mode) \u2014 the ViewTabBar is the only nav control here.`,
|
|
398
|
+
hint: `Move \`${field}\` to a page list (InterfaceListPage, "filters" mode), or remove it. See ADR-0053.`
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function scanListViews(listViews, wherePrefix, pathPrefix, out) {
|
|
403
|
+
if (!listViews || typeof listViews !== "object") return;
|
|
404
|
+
for (const [name, view] of Object.entries(listViews)) {
|
|
405
|
+
scanView(
|
|
406
|
+
view,
|
|
407
|
+
`${wherePrefix} \u203A listViews.${name}`,
|
|
408
|
+
`${pathPrefix}.listViews.${name}`,
|
|
409
|
+
out
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function validateListViewMode(stack) {
|
|
414
|
+
const out = [];
|
|
415
|
+
asArray3(stack.objects).forEach((obj, i) => {
|
|
416
|
+
const label = typeof obj.name === "string" ? `object "${obj.name}"` : `objects[${i}]`;
|
|
417
|
+
scanListViews(obj.listViews, label, `objects[${i}]`, out);
|
|
418
|
+
});
|
|
419
|
+
asArray3(stack.views).forEach((view, i) => {
|
|
420
|
+
const named = typeof view.objectName === "string" ? view.objectName : typeof view.name === "string" ? view.name : void 0;
|
|
421
|
+
const label = named ? `view "${named}"` : `views[${i}]`;
|
|
422
|
+
scanView(view.list, `${label} \u203A list`, `views[${i}].list`, out);
|
|
423
|
+
scanListViews(view.listViews, label, `views[${i}]`, out);
|
|
424
|
+
});
|
|
425
|
+
return out;
|
|
426
|
+
}
|
|
427
|
+
|
|
374
428
|
// src/validate-responsive-styles.ts
|
|
375
429
|
var STYLE_NODE_MISSING_ID = "style-node-missing-id";
|
|
376
430
|
var STYLE_CLASSNAME_TAILWIND = "style-classname-tailwind";
|
|
@@ -574,7 +628,7 @@ function looksLikeTailwind(className) {
|
|
|
574
628
|
return false;
|
|
575
629
|
});
|
|
576
630
|
}
|
|
577
|
-
function
|
|
631
|
+
function asArray4(v) {
|
|
578
632
|
if (Array.isArray(v)) return v;
|
|
579
633
|
if (v && typeof v === "object") {
|
|
580
634
|
return Object.entries(v).map(([name, def]) => ({ name, ...def }));
|
|
@@ -667,13 +721,13 @@ function checkNode(node, pageName, path, findings) {
|
|
|
667
721
|
}
|
|
668
722
|
function validateResponsiveStyles(stack) {
|
|
669
723
|
const findings = [];
|
|
670
|
-
const pages =
|
|
724
|
+
const pages = asArray4(stack.pages);
|
|
671
725
|
for (let p = 0; p < pages.length; p++) {
|
|
672
726
|
const page = pages[p];
|
|
673
727
|
const pageName = typeof page.name === "string" ? page.name : `pages[${p}]`;
|
|
674
|
-
const regions =
|
|
728
|
+
const regions = asArray4(page.regions);
|
|
675
729
|
for (let r = 0; r < regions.length; r++) {
|
|
676
|
-
const components =
|
|
730
|
+
const components = asArray4(regions[r].components);
|
|
677
731
|
for (let c = 0; c < components.length; c++) {
|
|
678
732
|
checkNode(components[c], pageName, `pages[${p}].regions[${r}].components[${c}]`, findings);
|
|
679
733
|
}
|
|
@@ -684,10 +738,10 @@ function validateResponsiveStyles(stack) {
|
|
|
684
738
|
|
|
685
739
|
// src/validate-jsx-pages.ts
|
|
686
740
|
import { parseJsx, compile } from "@objectstack/sdui-parser";
|
|
687
|
-
var
|
|
741
|
+
var asArray5 = (v) => Array.isArray(v) ? v : [];
|
|
688
742
|
function validateJsxPages(stack, opts = {}) {
|
|
689
743
|
const findings = [];
|
|
690
|
-
const pages =
|
|
744
|
+
const pages = asArray5(stack.pages);
|
|
691
745
|
for (let p = 0; p < pages.length; p++) {
|
|
692
746
|
const page = pages[p];
|
|
693
747
|
if (!page || page.kind !== "html" && page.kind !== "jsx") continue;
|
|
@@ -734,10 +788,10 @@ function loadSucraseTransform() {
|
|
|
734
788
|
}
|
|
735
789
|
return cachedTransform;
|
|
736
790
|
}
|
|
737
|
-
var
|
|
791
|
+
var asArray6 = (v) => Array.isArray(v) ? v : [];
|
|
738
792
|
function validateReactPages(stack) {
|
|
739
793
|
const findings = [];
|
|
740
|
-
const pages =
|
|
794
|
+
const pages = asArray6(stack.pages);
|
|
741
795
|
for (let p = 0; p < pages.length; p++) {
|
|
742
796
|
const page = pages[p];
|
|
743
797
|
if (!page || page.kind !== "react") continue;
|
|
@@ -788,7 +842,7 @@ function loadTypeScript() {
|
|
|
788
842
|
}
|
|
789
843
|
return cachedTs;
|
|
790
844
|
}
|
|
791
|
-
var
|
|
845
|
+
var asArray7 = (v) => Array.isArray(v) ? v : [];
|
|
792
846
|
var BLOCKS = new Map(
|
|
793
847
|
REACT_BLOCKS.map((b) => [
|
|
794
848
|
b.tag,
|
|
@@ -827,7 +881,7 @@ function nearestKnown(prop, known) {
|
|
|
827
881
|
}
|
|
828
882
|
function validateReactPageProps(stack) {
|
|
829
883
|
const findings = [];
|
|
830
|
-
const pages =
|
|
884
|
+
const pages = asArray7(stack.pages);
|
|
831
885
|
for (let p = 0; p < pages.length; p++) {
|
|
832
886
|
const page = pages[p];
|
|
833
887
|
if (!page || page.kind !== "react") continue;
|
|
@@ -895,11 +949,11 @@ function validateReactPageProps(stack) {
|
|
|
895
949
|
|
|
896
950
|
// src/validate-page-source-styling.ts
|
|
897
951
|
var PAGE_SOURCE_CLASSNAME = "page-source-className-tailwind";
|
|
898
|
-
var
|
|
952
|
+
var asArray8 = (v) => Array.isArray(v) ? v : [];
|
|
899
953
|
var CLASSNAME_ATTR = /\bclassName\s*=\s*["'{]/g;
|
|
900
954
|
function validatePageSourceStyling(stack) {
|
|
901
955
|
const findings = [];
|
|
902
|
-
const pages =
|
|
956
|
+
const pages = asArray8(stack.pages);
|
|
903
957
|
for (let p = 0; p < pages.length; p++) {
|
|
904
958
|
const page = pages[p];
|
|
905
959
|
if (!page) continue;
|
|
@@ -928,7 +982,7 @@ function validatePageSourceStyling(stack) {
|
|
|
928
982
|
import { objectTitleCompleteness } from "@objectstack/spec/data";
|
|
929
983
|
var TITLE_FORMAT_RETIRED = "title-format-retired";
|
|
930
984
|
var TITLE_UNRESOLVABLE = "title-unresolvable";
|
|
931
|
-
function
|
|
985
|
+
function asArray9(v) {
|
|
932
986
|
if (Array.isArray(v)) return v;
|
|
933
987
|
if (v && typeof v === "object") {
|
|
934
988
|
return Object.entries(v).map(([name, def]) => ({ name, ...def }));
|
|
@@ -937,7 +991,7 @@ function asArray8(v) {
|
|
|
937
991
|
}
|
|
938
992
|
function validateRecordTitle(stack) {
|
|
939
993
|
const findings = [];
|
|
940
|
-
const objects =
|
|
994
|
+
const objects = asArray9(stack.objects);
|
|
941
995
|
for (let i = 0; i < objects.length; i++) {
|
|
942
996
|
const obj = objects[i];
|
|
943
997
|
const objName = typeof obj.name === "string" ? obj.name : `(object ${i})`;
|
|
@@ -972,7 +1026,7 @@ function validateRecordTitle(stack) {
|
|
|
972
1026
|
var FIELD_GROUP_UNDECLARED = "field-group-undeclared";
|
|
973
1027
|
var FIELD_GROUP_EMPTY = "field-group-empty";
|
|
974
1028
|
var SEMANTIC_ROLE_FIELD_UNKNOWN = "semantic-role-field-unknown";
|
|
975
|
-
function
|
|
1029
|
+
function asArray10(v) {
|
|
976
1030
|
if (Array.isArray(v)) return v;
|
|
977
1031
|
if (v && typeof v === "object") {
|
|
978
1032
|
return Object.entries(v).map(([name, def]) => ({ name, ...def }));
|
|
@@ -981,7 +1035,7 @@ function asArray9(v) {
|
|
|
981
1035
|
}
|
|
982
1036
|
function validateSemanticRoles(stack) {
|
|
983
1037
|
const findings = [];
|
|
984
|
-
const objects =
|
|
1038
|
+
const objects = asArray10(stack.objects);
|
|
985
1039
|
for (let i = 0; i < objects.length; i++) {
|
|
986
1040
|
const obj = objects[i];
|
|
987
1041
|
if (!obj || typeof obj !== "object") continue;
|
|
@@ -1047,11 +1101,93 @@ function validateSemanticRoles(stack) {
|
|
|
1047
1101
|
}
|
|
1048
1102
|
return findings;
|
|
1049
1103
|
}
|
|
1104
|
+
|
|
1105
|
+
// src/validate-form-layout.ts
|
|
1106
|
+
var FORM_FIELD_UNKNOWN = "form-field-unknown";
|
|
1107
|
+
var FORM_COLSPAN_ABSOLUTE = "absolute-colspan-discouraged";
|
|
1108
|
+
function asArray11(v) {
|
|
1109
|
+
if (Array.isArray(v)) return v;
|
|
1110
|
+
if (v && typeof v === "object") {
|
|
1111
|
+
return Object.entries(v).map(([name, def]) => ({ name, ...def }));
|
|
1112
|
+
}
|
|
1113
|
+
return [];
|
|
1114
|
+
}
|
|
1115
|
+
function fieldNameOf(entry) {
|
|
1116
|
+
if (typeof entry === "string") return entry.length > 0 ? entry : null;
|
|
1117
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
1118
|
+
const f = entry.field;
|
|
1119
|
+
return typeof f === "string" && f.length > 0 ? f : null;
|
|
1120
|
+
}
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
function boundObject(view) {
|
|
1124
|
+
const data = view.data;
|
|
1125
|
+
if (data && typeof data === "object" && typeof data.object === "string") {
|
|
1126
|
+
return data.object;
|
|
1127
|
+
}
|
|
1128
|
+
return typeof view.objectName === "string" ? view.objectName : void 0;
|
|
1129
|
+
}
|
|
1130
|
+
function validateFormLayout(stack) {
|
|
1131
|
+
const findings = [];
|
|
1132
|
+
const objectFields = /* @__PURE__ */ new Map();
|
|
1133
|
+
for (const obj of asArray11(stack.objects)) {
|
|
1134
|
+
const name = typeof obj.name === "string" ? obj.name : void 0;
|
|
1135
|
+
if (!name) continue;
|
|
1136
|
+
const fields = obj.fields && typeof obj.fields === "object" && !Array.isArray(obj.fields) ? Object.keys(obj.fields) : [];
|
|
1137
|
+
objectFields.set(name, new Set(fields));
|
|
1138
|
+
}
|
|
1139
|
+
const views = asArray11(stack.views);
|
|
1140
|
+
for (let i = 0; i < views.length; i++) {
|
|
1141
|
+
const view = views[i];
|
|
1142
|
+
if (!view || typeof view !== "object") continue;
|
|
1143
|
+
const sections = Array.isArray(view.sections) ? view.sections : null;
|
|
1144
|
+
if (!sections) continue;
|
|
1145
|
+
const viewName = typeof view.name === "string" ? view.name : `(view ${i})`;
|
|
1146
|
+
const objName = boundObject(view);
|
|
1147
|
+
const known = objName ? objectFields.get(objName) : void 0;
|
|
1148
|
+
const where = `view "${viewName}"`;
|
|
1149
|
+
const base = `views[${i}]`;
|
|
1150
|
+
for (let s = 0; s < sections.length; s++) {
|
|
1151
|
+
const sec = sections[s];
|
|
1152
|
+
const secFields = sec && typeof sec === "object" && Array.isArray(sec.fields) ? sec.fields : [];
|
|
1153
|
+
for (let f = 0; f < secFields.length; f++) {
|
|
1154
|
+
const entry = secFields[f];
|
|
1155
|
+
const fname = fieldNameOf(entry);
|
|
1156
|
+
const fpath = `${base}.sections[${s}].fields[${f}]`;
|
|
1157
|
+
if (fname && known && !known.has(fname)) {
|
|
1158
|
+
findings.push({
|
|
1159
|
+
severity: "warning",
|
|
1160
|
+
rule: FORM_FIELD_UNKNOWN,
|
|
1161
|
+
where,
|
|
1162
|
+
path: fpath,
|
|
1163
|
+
message: `${viewName}: field "${fname}" is not a field on object "${objName}" \u2014 it is silently skipped and never renders on the form`,
|
|
1164
|
+
hint: `Fix the field name, or add "${fname}" to ${objName}. Section field references must match the object's field names exactly.`
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
const colSpan = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.colSpan : void 0;
|
|
1168
|
+
if (colSpan != null) {
|
|
1169
|
+
findings.push({
|
|
1170
|
+
severity: "warning",
|
|
1171
|
+
rule: FORM_COLSPAN_ABSOLUTE,
|
|
1172
|
+
where,
|
|
1173
|
+
path: `${fpath}.colSpan`,
|
|
1174
|
+
message: `${viewName}: field "${fname ?? "?"}" sets absolute colSpan ${String(colSpan)} \u2014 the form's column count is derived per surface (mobile 1 / modal 2 / page 3-4), so a fixed span only aligns at one width`,
|
|
1175
|
+
hint: `Prefer span: 'full' (whole row at any column count), or omit for auto width. The renderer clamps colSpan to the current column count.`
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return findings;
|
|
1182
|
+
}
|
|
1050
1183
|
export {
|
|
1051
1184
|
CHART_CONFIG_MISSING,
|
|
1052
1185
|
CHART_FIELD_UNKNOWN,
|
|
1053
1186
|
FIELD_GROUP_EMPTY,
|
|
1054
1187
|
FIELD_GROUP_UNDECLARED,
|
|
1188
|
+
FORM_COLSPAN_ABSOLUTE,
|
|
1189
|
+
FORM_FIELD_UNKNOWN,
|
|
1190
|
+
LIST_VIEW_FILTERS_IN_VIEWS_MODE,
|
|
1055
1191
|
MEASURE_AGGREGATE_INCOHERENT,
|
|
1056
1192
|
PAGE_SOURCE_CLASSNAME,
|
|
1057
1193
|
SEMANTIC_ROLE_FIELD_UNKNOWN,
|
|
@@ -1066,7 +1202,9 @@ export {
|
|
|
1066
1202
|
WIDGET_DATASET_UNKNOWN,
|
|
1067
1203
|
WIDGET_DIMENSION_UNKNOWN,
|
|
1068
1204
|
WIDGET_MEASURE_UNKNOWN,
|
|
1205
|
+
validateFormLayout,
|
|
1069
1206
|
validateJsxPages,
|
|
1207
|
+
validateListViewMode,
|
|
1070
1208
|
validatePageSourceStyling,
|
|
1071
1209
|
validateReactPageProps,
|
|
1072
1210
|
validateReactPages,
|