@objectstack/sdui-parser 17.2.0 → 17.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.
- package/CHANGELOG.md +191 -0
- package/dist/index.d.mts +211 -6
- package/dist/index.d.ts +211 -6
- package/dist/index.js +364 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +357 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,20 @@ interface ParseResult {
|
|
|
39
39
|
type ManifestInputType = 'string' | 'number' | 'boolean' | 'enum' | 'array' | 'object' | 'color' | 'date' | 'code' | 'file' | 'slot';
|
|
40
40
|
interface ManifestInput {
|
|
41
41
|
name: string;
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* The input's coarse type: ONE kind, or an ARRAY of kinds when the key's
|
|
44
|
+
* contract is a union (objectui#3832).
|
|
45
|
+
*
|
|
46
|
+
* A value passes {@link validateTree}'s coarse check when ANY arm accepts it,
|
|
47
|
+
* and is reported when none does — the array widens what is legal, it does
|
|
48
|
+
* not switch the check off.
|
|
49
|
+
*
|
|
50
|
+
* The single-kind form is unchanged and stays the canonical spelling for a
|
|
51
|
+
* one-arm key: `manifestFromConfigs` collapses a one-element array back to
|
|
52
|
+
* the bare string, so a manifest gains arrays only where a union was really
|
|
53
|
+
* declared and every already-published entry serializes byte-identically.
|
|
54
|
+
*/
|
|
55
|
+
type: ManifestInputType | ManifestInputType[];
|
|
43
56
|
required?: boolean;
|
|
44
57
|
/** allowed values for `enum` inputs */
|
|
45
58
|
enum?: Array<string | {
|
|
@@ -94,9 +107,25 @@ interface ValidationResult {
|
|
|
94
107
|
declare function parseJsx(source: string, options?: ParseOptions): ParseResult;
|
|
95
108
|
/**
|
|
96
109
|
* Interpret a braced attribute value `{...}`.
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
110
|
+
*
|
|
111
|
+
* Strict-JSON values are materialized by `JSON.parse`, exactly as they always
|
|
112
|
+
* were. Beyond that, the JS **literal subset** below is materialized too
|
|
113
|
+
* (objectui#6614 Q1-A, maintainer ruling 2026-08-28). Anything left over — a
|
|
114
|
+
* genuine expression — is kept as the deferred marker `{ $expr }`: typed and
|
|
115
|
+
* validated later, drawing `inert-expression`, and NEVER evaluated here.
|
|
116
|
+
*
|
|
117
|
+
* ORDER IS LOAD-BEARING. `JSON.parse` runs FIRST and is untouched, so every
|
|
118
|
+
* input JSON accepts takes byte-identically the path it took before the literal
|
|
119
|
+
* subset existed. The reader below only ever sees strings `JSON.parse` has
|
|
120
|
+
* already thrown on, which makes strict-JSON invariance a property of the
|
|
121
|
+
* structure rather than of a test.
|
|
122
|
+
*
|
|
123
|
+
* LOCKSTEP: this grammar is the port of objectui's `packages/sdui-parser` copy
|
|
124
|
+
* (objectui#6614). The two copies must agree on the accepted grammar AND on
|
|
125
|
+
* diagnostic codes — if they drift, the save gate and the renderer speak
|
|
126
|
+
* different dialects and a page can save clean and render inert
|
|
127
|
+
* (objectstack#12719 states the invariant; #12977 carries this half of it).
|
|
128
|
+
* Change this block only together with the objectui copy.
|
|
100
129
|
*/
|
|
101
130
|
declare function interpretBrace(raw: string): unknown;
|
|
102
131
|
|
|
@@ -111,6 +140,128 @@ declare function interpretBrace(raw: string): unknown;
|
|
|
111
140
|
|
|
112
141
|
declare function validateTree(tree: SchemaElement | null, manifest: Manifest): ValidationResult;
|
|
113
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Unconsumed dashboard-widget `options` keys (objectui#5709), ported into this
|
|
145
|
+
* copy in lockstep (objectstack#12810).
|
|
146
|
+
*
|
|
147
|
+
* `@objectstack/spec`'s `DashboardWidgetOptionsSchema` ends in `.passthrough()`
|
|
148
|
+
* ("declared query keys + open renderer extras"), so ANY key parses, validates
|
|
149
|
+
* and lints cleanly — including one no renderer reads. That is how a showcase
|
|
150
|
+
* dashboard shipped `options: { invert: true }` on a gauge with a comment
|
|
151
|
+
* saying what it was believed to do, and rendered the un-inverted measure with
|
|
152
|
+
* no diagnostic anywhere (objectui#5709). The 2026-08-23 maintainer ruling:
|
|
153
|
+
* open extras stay open — they just stop being SILENT. A key that reaches no
|
|
154
|
+
* renderer draws a WARNING naming the consumed set. Not an error: no gate
|
|
155
|
+
* weakening and no new red gates were ruled.
|
|
156
|
+
*
|
|
157
|
+
* ## LOCKSTEP — what is byte-equal here and what deliberately is not
|
|
158
|
+
*
|
|
159
|
+
* Two copies of this parser exist: objectui's `packages/sdui-parser` and this
|
|
160
|
+
* hoisted `@objectstack/sdui-parser`. The invariant they owe each other is that
|
|
161
|
+
* both agree on the accepted grammar AND on diagnostic codes — if they drift,
|
|
162
|
+
* the save gate and the renderer speak different dialects and a page can save
|
|
163
|
+
* clean and render inert, or the reverse (objectstack#12719, objectstack#12810).
|
|
164
|
+
*
|
|
165
|
+
* Everything from the `import` line below to end of file is a byte-equal port of
|
|
166
|
+
* objectui's `src/dashboard-widget-options.ts` SAVE FOR ONE TOKEN, called out
|
|
167
|
+
* at the site itself: the emitted `code` is spelled as an inline literal here
|
|
168
|
+
* and as the constant there, because this repo runs a vocabulary gate objectui
|
|
169
|
+
* does not. The emitted `code`, `severity`, `message` and the whole census
|
|
170
|
+
* scope are identical, and `__tests__/dashboard-widget-options.test.ts`
|
|
171
|
+
* re-derives that rather than trusting it — including an explicit pin that the
|
|
172
|
+
* literal equals `UNCONSUMED_WIDGET_OPTION`. Change these functions only
|
|
173
|
+
* together with the objectui copy.
|
|
174
|
+
*
|
|
175
|
+
* THIS HEADER is the one deliberate divergence, and it has to be: objectui's
|
|
176
|
+
* header cites the maintenance machinery that derives the census — its
|
|
177
|
+
* `DatasetWidget.tsx` / `DashboardRenderer.tsx` read sites, its
|
|
178
|
+
* `plugin-dashboard.mdx` claim and its two census tests. NONE of those files
|
|
179
|
+
* exists in this repo (measured: no dashboard renderer package here at all), so
|
|
180
|
+
* copying those sentences would ship claims this checkout cannot support and
|
|
181
|
+
* nothing here would ever notice them going false. What follows instead states
|
|
182
|
+
* where each half of the census is derivable, and from what.
|
|
183
|
+
*
|
|
184
|
+
* ## The accepted set, and where each half is authoritative
|
|
185
|
+
*
|
|
186
|
+
* The spec REQUIRES `dataset` on every widget (`DashboardWidgetSchema`, this
|
|
187
|
+
* repo: `packages/spec/src/ui/dashboard.zod.ts`), and both of objectui's
|
|
188
|
+
* dashboard surfaces route a dataset-bound widget to `DatasetWidget`. On that —
|
|
189
|
+
* the only spec-legal — path the renderer-consumed `options` keys are exactly
|
|
190
|
+
* the five the spec DECLARES:
|
|
191
|
+
*
|
|
192
|
+
* dateGranularity, sortBy, sortOrder, limit (query-affecting, framework#3588)
|
|
193
|
+
* stageOrder (funnel/pyramid stage order)
|
|
194
|
+
*
|
|
195
|
+
* plus ONE undeclared key with a real read site:
|
|
196
|
+
*
|
|
197
|
+
* description — the metric-card sub-caption channel. `translateDashboard`
|
|
198
|
+
* OVERLAYS the `widgets.{id}.subCaption` translation onto this key, and that
|
|
199
|
+
* pipeline lives IN THIS REPO: `packages/spec/src/system/i18n-resolver.ts`
|
|
200
|
+
* documents `WidgetLike.options` as "the renderer-extras bag …
|
|
201
|
+
* `translateDashboard` writes exactly one key into it — `description`"
|
|
202
|
+
* (objectstack#5428 item 4, objectstack#7862). Warning on a key the
|
|
203
|
+
* platform's own translation pipeline writes would be a false positive on
|
|
204
|
+
* legal metadata, so it is in the accepted set even though the dataset-bound
|
|
205
|
+
* render path does not currently display it.
|
|
206
|
+
*
|
|
207
|
+
* Notably NOT consumed on the path a widget really renders through:
|
|
208
|
+
* `thresholds` and `format`. Both were widely believed to work; both draw this
|
|
209
|
+
* warning, which is the point. Their closure claims are objectui's to derive —
|
|
210
|
+
* `thresholds` by a repo-wide read-site scan there, `format` by the bounded
|
|
211
|
+
* claim that the dataset-bound path formats from the MEASURE's own metadata —
|
|
212
|
+
* and they are NOT restated here as claims about this repo, which has no
|
|
213
|
+
* renderer to make them about.
|
|
214
|
+
*
|
|
215
|
+
* ## The drift risk that lives on THIS side
|
|
216
|
+
*
|
|
217
|
+
* The spec whose `.passthrough()` this reasons about ships from this repo. So
|
|
218
|
+
* the one way this list can go stale HERE is a new DECLARED key landing in
|
|
219
|
+
* `DashboardWidgetOptionsSchema` without landing in the array below: the key
|
|
220
|
+
* would be spec-legal, renderer-consumed on the objectui side, and warned about
|
|
221
|
+
* here — a false positive on legal metadata. `@objectstack/sdui-parser` takes
|
|
222
|
+
* no dependency on `@objectstack/spec` (it is dependency-free and hoistable by
|
|
223
|
+
* design), so that cross-check is not mechanized in this copy; the census test
|
|
224
|
+
* next door pins the array and names the spec file to re-read when it moves.
|
|
225
|
+
*
|
|
226
|
+
* ## Scope — where the warning deliberately does NOT fire
|
|
227
|
+
*
|
|
228
|
+
* - Widgets WITHOUT `dataset`: the legacy inline forms (`options.data`
|
|
229
|
+
* arrays, `provider: 'object'` bags) consume a much larger, spread-shaped
|
|
230
|
+
* key set, whose true reach is each child component's prop surface. That
|
|
231
|
+
* form is spec-illegal today (`dataset` is required) and its census would be
|
|
232
|
+
* the unmaintainable one; skipping it keeps every warning this module emits
|
|
233
|
+
* a statement about the path the widget actually renders through.
|
|
234
|
+
* - Widgets in the legacy COMPONENT format (`widget.component`): `options`
|
|
235
|
+
* is not part of that contract.
|
|
236
|
+
* - Widgets carrying the spec's own escape hatch
|
|
237
|
+
* `suppressWarnings: ['unconsumed-widget-option']` — the spec models
|
|
238
|
+
* per-widget diagnostic suppression (`DashboardWidgetSchema.suppressWarnings`,
|
|
239
|
+
* "Build diagnostic rule ids suppressed on this widget"), so an author with
|
|
240
|
+
* a genuine out-of-band consumer can say so in metadata.
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
/** The diagnostic `code` — also the id `suppressWarnings` suppresses. */
|
|
244
|
+
declare const UNCONSUMED_WIDGET_OPTION = "unconsumed-widget-option";
|
|
245
|
+
/**
|
|
246
|
+
* Component types that host a dashboard `widgets` array. Both resolve to the
|
|
247
|
+
* surfaces measured by the census above (`DashboardRenderer`,
|
|
248
|
+
* `DashboardGridLayout`), which share one dispatch (`widgetDispatch.ts`).
|
|
249
|
+
*/
|
|
250
|
+
declare const DASHBOARD_WIDGET_HOST_TYPES: ReadonlySet<string>;
|
|
251
|
+
/**
|
|
252
|
+
* The accepted set: every `options` key with a renderer read site on the
|
|
253
|
+
* dataset-bound path, plus the sub-caption convention key. Alphabetical; the
|
|
254
|
+
* warning message prints it verbatim. Derivation and evidence: file header.
|
|
255
|
+
*/
|
|
256
|
+
declare const CONSUMED_WIDGET_OPTION_KEYS: readonly string[];
|
|
257
|
+
/**
|
|
258
|
+
* Diagnostics for `options` keys no renderer consumes, over one dashboard-host
|
|
259
|
+
* node's `widgets` array. Pure and shallow by design: it never descends into
|
|
260
|
+
* `children` (the caller's walk owns that) and answers `[]` for every shape
|
|
261
|
+
* outside its census — see the scope notes in the file header.
|
|
262
|
+
*/
|
|
263
|
+
declare function checkDashboardWidgetOptions(node: SchemaElement): Diagnostic[];
|
|
264
|
+
|
|
114
265
|
/**
|
|
115
266
|
* ObjectUI — codegen the JSX type surface from the registry manifest (ADR-0080 §3)
|
|
116
267
|
*
|
|
@@ -135,6 +286,53 @@ declare function propsName(type: string): string;
|
|
|
135
286
|
*/
|
|
136
287
|
declare function generateBlockList(manifest: Manifest): string;
|
|
137
288
|
|
|
289
|
+
/**
|
|
290
|
+
* ObjectUI — the arms of a manifest input's coarse type (objectui#3832)
|
|
291
|
+
*
|
|
292
|
+
* `ManifestInput.type` carries ONE coarse kind, or an ARRAY of kinds when the
|
|
293
|
+
* key's contract is a union. Every reader of that field needs the same two
|
|
294
|
+
* decisions made the same way — how to see the arms, and which single form to
|
|
295
|
+
* publish — so they live here once instead of at each call site. A reader that
|
|
296
|
+
* forgets is not loud: `switch (input.type)` handed an array falls through to
|
|
297
|
+
* the default branch and reports NOTHING, which looks exactly like a value that
|
|
298
|
+
* validated cleanly.
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
/** The eleven coarse kinds, as a runtime set for guarding untyped input. */
|
|
302
|
+
declare const MANIFEST_INPUT_TYPES: ReadonlySet<string>;
|
|
303
|
+
/**
|
|
304
|
+
* The declared arms of an input's coarse type, always as an array.
|
|
305
|
+
*
|
|
306
|
+
* Exported (not merely internal) so a third-party manifest consumer — a
|
|
307
|
+
* designer panel, a codegen, a validator of its own — reads the arms through
|
|
308
|
+
* the same accessor this package's own gate does, rather than re-deriving the
|
|
309
|
+
* `Array.isArray` branch and getting it subtly wrong on the union form.
|
|
310
|
+
*/
|
|
311
|
+
declare function inputTypeArms(type: ManifestInput['type'] | undefined): ManifestInputType[];
|
|
312
|
+
/**
|
|
313
|
+
* Project a DECLARED type (which may come from an untyped registry config) into
|
|
314
|
+
* the canonical published form: a bare string for one arm, an array for a real
|
|
315
|
+
* union.
|
|
316
|
+
*
|
|
317
|
+
* Two deliberate asymmetries between the single and array forms:
|
|
318
|
+
*
|
|
319
|
+
* - A single unrecognized kind still becomes `'string'`. That coercion predates
|
|
320
|
+
* the union work and is kept exactly: with one arm there is no other
|
|
321
|
+
* information to fall back on, and a manifest whose `type` is off-vocabulary
|
|
322
|
+
* would make every consumer's switch silently inert.
|
|
323
|
+
* - An unrecognized arm INSIDE an array is DROPPED, not coerced. Promoting it
|
|
324
|
+
* to `'string'` would publish an arm the author never declared — a widening
|
|
325
|
+
* invented by the serializer — and the surviving arms already carry the
|
|
326
|
+
* declaration. If dropping empties the array, the single-arm fallback applies
|
|
327
|
+
* so the output is always a valid manifest.
|
|
328
|
+
*
|
|
329
|
+
* Collapsing one arm to the bare string is what keeps this a backward-compatible
|
|
330
|
+
* extension of `sdui.manifest.json`: every input declared today serializes to
|
|
331
|
+
* the byte-identical entry it does now, and arrays appear only where a union was
|
|
332
|
+
* really declared.
|
|
333
|
+
*/
|
|
334
|
+
declare function canonicalizeInputType(type: unknown): ManifestInputType | ManifestInputType[];
|
|
335
|
+
|
|
138
336
|
/**
|
|
139
337
|
* @objectstack/sdui-parser — constrained JSX-source → SDUI SchemaNode tree (ADR-0080)
|
|
140
338
|
*
|
|
@@ -166,7 +364,14 @@ interface RegistryConfigLike {
|
|
|
166
364
|
category?: string;
|
|
167
365
|
inputs?: Array<{
|
|
168
366
|
name: string;
|
|
169
|
-
|
|
367
|
+
/**
|
|
368
|
+
* One coarse kind, or the arms of a union (objectui#3832). Typed loosely
|
|
369
|
+
* (`string`) on purpose — this interface is the STRUCTURAL boundary that
|
|
370
|
+
* keeps this package free of a dependency on the registry, so an
|
|
371
|
+
* off-vocabulary value has to be representable here and is normalized by
|
|
372
|
+
* `canonicalizeInputType` on the way in.
|
|
373
|
+
*/
|
|
374
|
+
type: string | string[];
|
|
170
375
|
required?: boolean;
|
|
171
376
|
enum?: Array<string | {
|
|
172
377
|
value: unknown;
|
|
@@ -181,4 +386,4 @@ declare function manifestFromConfigs(configs: RegistryConfigLike[], opts?: {
|
|
|
181
386
|
publicOnly?: boolean;
|
|
182
387
|
}): Manifest;
|
|
183
388
|
|
|
184
|
-
export { type CodegenOptions, type CompileResult, type Diagnostic, type Manifest, type ManifestComponent, type ManifestInput, type ManifestInputType, type ParseOptions, type ParseResult, type RegistryConfigLike, type SchemaElement, type SchemaNode, type Severity, type ValidationResult, compile, generateBlockList, generateDts, interpretBrace, manifestFromConfigs, parseJsx, propsName, validateTree };
|
|
389
|
+
export { CONSUMED_WIDGET_OPTION_KEYS, type CodegenOptions, type CompileResult, DASHBOARD_WIDGET_HOST_TYPES, type Diagnostic, MANIFEST_INPUT_TYPES, type Manifest, type ManifestComponent, type ManifestInput, type ManifestInputType, type ParseOptions, type ParseResult, type RegistryConfigLike, type SchemaElement, type SchemaNode, type Severity, UNCONSUMED_WIDGET_OPTION, type ValidationResult, canonicalizeInputType, checkDashboardWidgetOptions, compile, generateBlockList, generateDts, inputTypeArms, interpretBrace, manifestFromConfigs, parseJsx, propsName, validateTree };
|