Skip to content

[Docs][Visualizations API] Schema reference pages + OAS required-field fixes#262900

Closed
florent-leborgne wants to merge 13 commits into
mainfrom
viz-api-schema-reference
Closed

[Docs][Visualizations API] Schema reference pages + OAS required-field fixes#262900
florent-leborgne wants to merge 13 commits into
mainfrom
viz-api-schema-reference

Conversation

@florent-leborgne
Copy link
Copy Markdown
Member

@florent-leborgne florent-leborgne commented Apr 13, 2026

Summary

This PR adds field-level schema reference pages for the Visualizations API and fixes incorrectly-required fields in the generated OAS.

What's included

1. Schema reference pages (docs/reference/visualizations-api/)

One page per chart type (12 types), each with:

  • A top-level fields table rendered via {csv-include} from a CSV file
  • Named sub-sections for complex nested types (styling, layers, legend, drilldowns, etc.)
  • 2-column format: parameter name + type + required / description + possible values
  • Object-type fields link to the sub-table section that defines them on the same page
  • NoESQL and ES|QL variants merged into a single table per chart type (with a note on query and data_source differences)

2. CSV generator (oas_docs/scripts/generate_csv_schemas.js)

Reads oas_docs/output/kibana.yaml (post required-field overlay, pre Bump simplification) and emits the CSV tables and .md pages. The CSV files are committed alongside the pages so docs-builder can render them without a build step.

To regenerate after an OAS update:
```bash
PATH="$HOME/.nvm/versions/node/v22.22.0/bin:$PATH" make merge-api-docs
make api-docs-overlay # apply required-field fixes
node oas_docs/scripts/generate_csv_schemas.js # regenerate tables from full schema
```

3. OAS required-field fixes (oas_docs/overlays/visualizations.overlays.yaml)

Fixes 57 schemas where schema.maybe() fields were incorrectly promoted into the required array by the OAS generator. Affected fields include filters, time_range, styling, legend, axis, values, query, and several sub-schema properties across all 12 chart types.

Root cause: schema.maybe() produces x-oas-optional: true on the resolved type schema, but the OAS generator still includes the field in the parent required array. Nothing downstream can tell the field is truly optional without checking x-oas-optional on the resolved type.

Short-term fix (this PR): overlay actions that remove the incorrect required array and replace it with the correct one for each affected schema.

Long-term fix (out of scope): a post-processing step in @kbn/openapi-generator to strip x-oas-optional: true fields from parent required arrays automatically — would eliminate the need for these overlay actions entirely.

The same bug affects the Dashboards API (query, refresh_interval, time_range on kbn-dashboard-data) — that fix is in oas_docs/overlays/dashboards.overlays.yaml and is part of #262396.

Cc @Devon_Thomson @markov00 — see root cause note above, happy to discuss the long-term fix.

4. Bump.sh simplification (oas_docs/overlays/visualizations.overlays.yaml)

The Visualizations API create/update pages in Bump.sh were slow to load because lensApiState is a 24-variant anyOf — one deeply nested schema per chart type. The overlay now removes the anyOf and replaces it with a description containing links to the per-chart-type reference pages added in this PR.

5. Makefile change

Adds visualizations.overlays.yaml as a step in make api-docs-overlay (stateful pipeline only).

Pipeline ordering constraint

The CSV generator must read from the OAS after the required-field overlay has been applied (so required markers are accurate) but before the Bump simplification (which replaces lensApiState with a description, leaving nothing useful to walk). The current manual workflow satisfies this. When the generator is wired into make api-docs automatically, the makefile will need to reflect this ordering:

```makefile
api-docs:
$(MAKE) merge-api-docs
$(MAKE) api-docs-overlay-required # required-field fixes
node scripts/generate_csv_schemas.js # generate reference tables from full schema
$(MAKE) api-docs-overlay-simplify # Bump simplification + other overlays
```

What's NOT yet in this PR

Automated pipeline wiring

generate_csv_schemas.js is not yet wired into make api-docs. The CSV tables and .md pages need to regenerate whenever the OAS changes — this should be a step in the makefile (respecting the ordering constraint above) so the committed CSV files stay in sync automatically.

Dashboards API reference pages

The Dashboards API (/api/dashboards) needs equivalent reference pages for its panel types, grid structure, controls, etc. The vis panel type within the Dashboards API embeds the full Lens visualization config — for "by value", those pages would link directly to the chart type pages added in this PR rather than duplicating them.

Request examples

Each chart type page currently has schema tables but no working request example. These are being added in separate PRs.

Test plan

  • Run PATH="\$HOME/.nvm/versions/node/v22.22.0/bin:\$PATH" make api-docs and confirm output/kibana.yaml has correct required arrays for metricNoESQL, xyChartNoESQL, and kbn-dashboard-data
  • Run node oas_docs/scripts/generate_csv_schemas.js and confirm 27 CSV files written to docs/reference/visualizations-api/_tables/
  • Run docs-builder serve --path docs and navigate to /reference/visualizations-api to verify pages render correctly
  • Confirm filters, styling, time_range, query are not marked required in the metric chart page
  • Confirm the Bump preview for POST /api/visualizations shows a description with links instead of an expandable schema tree

🤖 Generated with Claude Code

florent-leborgne and others added 10 commits April 13, 2026 19:09
…dpoints

Adds cURL and Console code samples (x-codeSamples) and response examples
for all Dashboards API endpoints: POST, GET, PUT, DELETE, and GET _find.

Also fixes description text for ES|QL metric charts that incorrectly
referenced the removed `operation: "value"` field.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Corrects field order in all response examples to match actual API output:
- `data` fields: options → panels → pinned_panels → title
- Panel fields: grid → config → id → type
- Search response: time_range before title

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…se description

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Expand response examples to include all server-returned fields:
sampling, ignore_global_filters, empty_as_null, axis_id, styling,
axis, and legend defaults. Fixes GET response field ordering
(options → title → panels → pinned_panels) which differs from POST.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…points

Adds lang: JSON response examples to x-codeSamples for POST, GET _find,
GET /{id}, and PUT /{id} so they reliably appear in the Bump code panel.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… it in wrong location)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… rendering

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…d fields in OAS

## What this adds

### Schema reference pages (`docs/reference/visualizations-api/`)
- One page per chart type (12 types: metric, XY, gauge, heatmap, datatable, pie,
  mosaic, treemap, waffle, tagcloud, region-map, legacy-metric)
- Each page has a top-level fields table and named sub-sections (styling, layers,
  legend, drilldowns, etc.) rendered from CSV files via `{csv-include}`
- 2-column format: parameter name + type + required / description + possible values
- Object fields link to the sub-table section that defines them on the same page
- NoESQL and ES|QL variants merged into a single table per chart type

### CSV generator (`oas_docs/scripts/generate_csv_schemas.js`)
Reads `oas_docs/output/kibana.yaml` (post-overlay) and emits:
- `docs/reference/visualizations-api/_tables/*.csv` — one file per chart type
  and referenced sub-type (styling, layers, legend, drilldowns, etc.)
- `docs/reference/visualizations-api/*.md` — one page per chart type

To regenerate after an OAS update:
  PATH="$HOME/.nvm/versions/node/v22.22.0/bin:$PATH" make merge-api-docs
  make api-docs-overlay
  node oas_docs/scripts/generate_csv_schemas.js

### Overlay fixes (`oas_docs/overlays/visualizations.overlays.yaml`)
Fixes 57 schemas where `schema.maybe()` fields were incorrectly promoted into
the `required` array by the OAS generator. Affected fields include `filters`,
`time_range`, `styling`, `legend`, `axis`, and `query` across all 12 chart types
and their sub-schemas. The fix uses `remove` + `update` per schema to replace
the required array (bump overlay appends rather than replaces arrays on `update`
alone). Wired into `make api-docs-overlay` via a new step in the makefile.

The same required-field bug affects the Dashboards API — that fix is in
`oas_docs/overlays/dashboards.overlays.yaml` (separate commit).

### Root cause note
`schema.maybe()` in `@kbn/config-schema` produces `x-oas-optional: true` on
the resolved type schema, but the OAS generator still includes the field in the
parent schema's `required` array. Downstream tools (Bump.sh, this generator)
cannot tell the field is optional without checking `x-oas-optional` on the
resolved type. The overlays are the short-term fix; the long-term fix is a
post-processing step in the OAS generator to strip `x-oas-optional` fields
from parent `required` arrays automatically.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@elasticmachine
Copy link
Copy Markdown
Contributor

🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

✅ Vale Linting Results

No issues found on modified lines!


The Vale linter checks documentation changes against the Elastic Docs style guide.

To use Vale locally or report issues, refer to Elastic style guide for Vale.

function metaValues(rawProp) {
const s = resolve(rawProp);

if (s.const !== undefined) return `Value: \`"${s.const}"\``;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium scripts/generate_csv_schemas.js:188

metaValues formats non-string const values with quotes on line 188 (Value: \"${s.const}"`), while line 199 handles strings and non-strings correctly. For const: 42orconst: true, this produces Value: "42"orValue: "true"instead ofValue: 42orValue: true`. Consider using the same type-aware formatting as line 199.

Suggested change
if (s.const !== undefined) return `Value: \`"${s.const}"\``;
if (s.const !== undefined) return typeof s.const === 'string' ? `Value: \`"${s.const}"\`` : `Value: \`${s.const}\``;
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file oas_docs/scripts/generate_csv_schemas.js around line 188:

`metaValues` formats non-string `const` values with quotes on line 188 (`Value: \`"${s.const}"\``), while line 199 handles strings and non-strings correctly. For `const: 42` or `const: true`, this produces `Value: "42"` or `Value: "true"` instead of `Value: 42` or `Value: true`. Consider using the same type-aware formatting as line 199.

Evidence trail:
oas_docs/scripts/generate_csv_schemas.js lines 188 and 199 at REVIEWED_COMMIT. Line 188: `if (s.const !== undefined) return \`Value: \`"${s.const}"\`\`;` - always uses quotes. Line 199: `typeof item.const === 'string' ? \`\`"${item.const}"\`\` : \`\`${item.const}\`\`` - uses type-aware formatting.

Comment on lines +104 to +115
function mergeAllOf(schema) {
if (!schema.allOf) return schema;
const merged = { properties: {}, required: [] };
for (const sub of schema.allOf) {
const r = resolve(sub);
const e = mergeAllOf(r);
Object.assign(merged.properties, e.properties || {});
merged.required.push(...(e.required || []));
if (!merged.description && e.description) merged.description = e.description;
}
return merged;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low scripts/generate_csv_schemas.js:104

mergeAllOf returns a new object with only the merged allOf branches, so any properties defined directly on the schema alongside allOf are silently dropped. Per JSON Schema/OpenAPI semantics, both sets of properties should be present. Consider copying schema.properties into merged.properties before the loop, or merging them after the loop completes.

 function mergeAllOf(schema) {
   if (!schema.allOf) return schema;
-  const merged = { properties: {}, required: [] };
+  const merged = { properties: { ...(schema.properties || {}) }, required: [...(schema.required || [])] };
   for (const sub of schema.allOf) {
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file oas_docs/scripts/generate_csv_schemas.js around lines 104-115:

`mergeAllOf` returns a new object with only the merged `allOf` branches, so any `properties` defined directly on the schema alongside `allOf` are silently dropped. Per JSON Schema/OpenAPI semantics, both sets of properties should be present. Consider copying `schema.properties` into `merged.properties` before the loop, or merging them after the loop completes.

Evidence trail:
oas_docs/scripts/generate_csv_schemas.js lines 104-114 at REVIEWED_COMMIT - the `mergeAllOf` function creates `merged = { properties: {}, required: [] }` and only populates from `schema.allOf` items, never copying `schema.properties` or `schema.required`. JSON Schema semantics: https://json-schema.org/understanding-json-schema/reference/combining shows that `allOf` and other keywords like `properties` at the same level should all apply independently.

Comment on lines +28 to +31
function getArg(name, defaultVal) {
const i = process.argv.indexOf(name);
return i !== -1 ? process.argv[i + 1] : defaultVal;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low scripts/generate_csv_schemas.js:28

getArg returns undefined instead of defaultVal when a flag is passed without a value. If a user runs node script.js --input (missing the path), process.argv[i + 1] is undefined, the condition i !== -1 is true, so undefined is returned instead of the default. This causes fs.readFileSync(undefined, 'utf8') to throw a TypeError rather than using the default path. Consider checking that i + 1 is within bounds and that the next argument is not another flag before returning it.

-  const i = process.argv.indexOf(name);
-  return i !== -1 ? process.argv[i + 1] : defaultVal;
+  const i = process.argv.indexOf(name);
+  if (i === -1) return defaultVal;
+  const val = process.argv[i + 1];
+  if (val === undefined || val.startsWith('--')) return defaultVal;
+  return val;
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file oas_docs/scripts/generate_csv_schemas.js around lines 28-31:

`getArg` returns `undefined` instead of `defaultVal` when a flag is passed without a value. If a user runs `node script.js --input` (missing the path), `process.argv[i + 1]` is `undefined`, the condition `i !== -1` is true, so `undefined` is returned instead of the default. This causes `fs.readFileSync(undefined, 'utf8')` to throw a `TypeError` rather than using the default path. Consider checking that `i + 1` is within bounds and that the next argument is not another flag before returning it.

Evidence trail:
oas_docs/scripts/generate_csv_schemas.js lines 28-34 at REVIEWED_COMMIT: The `getArg` function at line 28-30 shows `return i !== -1 ? process.argv[i + 1] : defaultVal;` which returns `process.argv[i + 1]` (which is `undefined` when out of bounds) whenever the flag is found, regardless of whether there's a following argument. Line 32-33 shows these values are used as file paths: `const inputPath = getArg('--input', path.join(oasDocsDir, 'output/kibana.yaml'));`

florent-leborgne and others added 3 commits April 13, 2026 22:02
…eference pages

Bump.sh struggles to render the create/update endpoints because lensApiState
is a 24-variant anyOf — one deeply nested schema per chart type. Replace the
union with a plain description containing links to the per-chart-type schema
reference pages added in the parent commit.

The full field-level reference is in docs/reference/visualizations-api/; the
Bump API reference now points there rather than trying to render the tree inline.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Remove title from all metric panel configs (metrics use their own label)
- Change metric panel height to h:5 across all examples
- Fix Unique visitors panel to w:12, h:5
- Add missing titles to xy panels in sections+controls example
- Add PUT description note: all panels must be included or they are removed

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@florent-leborgne
Copy link
Copy Markdown
Member Author

This draft is no longer needed, closing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants