Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 8.x] Add @doc_tag to override default tag behaviour #2981

Merged
merged 1 commit into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api-design-guidelines/naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Care should be given to ensure that:
- All member APIs of a given namespace are logically related and form a coherent set.
- Related functionality is not distributed across multiple arbitrary namespaces

NOTE: The endpoint namespaces are used to generate tags in the OpenAPI documents. The tags are ultimately used to group the endpoints in the API documentation. To override the default tag, use `@doc_tag`.

### Use the global namespace sparingly

The top-level global namespace should be treated with particular care. It is traditionally reserved for search and document endpoints only. A case should be made and a broader discussion carried out before new endpoints unrelated to these functions are added to the global namespace.
Expand Down
3 changes: 3 additions & 0 deletions compiler-rs/clients_schema/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,9 @@ pub struct Endpoint {
#[serde(skip_serializing_if = "Option::is_none")]
pub availability: Option<Availabilities>,

#[serde(skip_serializing_if = "Option::is_none")]
pub doc_tag: Option<String>,

/// If missing, there is not yet a request definition for this endpoint.
#[serde(skip_serializing_if = "Option::is_none")]
pub request: Option<TypeName>,
Expand Down
6 changes: 5 additions & 1 deletion compiler-rs/clients_schema_to_openapi/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ pub fn add_endpoint(

// Create the operation, it will be repeated if we have several methods
let operation = openapiv3::Operation {
tags: vec![namespace.to_string()],
tags: if let Some(doc_tag) = &endpoint.doc_tag {
vec![doc_tag.clone()]
} else {
vec![namespace.to_string()]
},
summary: sum_desc.summary,
description: sum_desc.description,
// external_docs: tac.convert_external_docs(endpoint),
Expand Down
2 changes: 1 addition & 1 deletion compiler-rs/clients_schema_to_openapi/src/schemas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const SCHEMA_PLACEHOLDER: ReferenceOr<Schema> = ReferenceOr::Reference {
/// Convert `schema.json` type and value definitions to OpenAPI schemas:
///
/// The `convert_*` functions return a concrete schema and not a reference and do not store them in
/// the OpenAPI `components.schema`. This is the role of `for_type_name` hat creates and stores the
/// the OpenAPI `components.schema`. This is the role of `for_type_name` that creates and stores the
/// schema and returns a reference.
impl<'a> TypesAndComponents<'a> {
/// Convert a value. Returns a schema reference and not a concrete schema, as values can
Expand Down
Binary file modified compiler-rs/compiler-wasm-lib/pkg/compiler_wasm_lib_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions compiler/src/model/build-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function compileEndpoints (): Record<string, model.Endpoint> {
name: api,
description: spec.documentation.description,
docUrl: spec.documentation.url,
docTag: spec.docTag,
// Setting these values by default should be removed
// when we no longer use rest-api-spec stubs as the
// source of truth for stability/visibility.
Expand Down
1 change: 1 addition & 0 deletions compiler/src/model/json-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface JsonSpec {
description: string
required?: boolean
}
docTag?: string
}

export default function buildJsonSpec (): Map<string, JsonSpec> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/model/metamodel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ export class Endpoint {
docId?: string
deprecation?: Deprecation
availability: Availabilities

docTag?: string
/**
* If the request value is `null` it means that there is not yet a
* request type definition for this endpoint.
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/model/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ export function hoistRequestAnnotations (
request: model.Request, jsDocs: JSDoc[], mappings: Record<string, model.Endpoint>, response: model.TypeName | null
): void {
const knownRequestAnnotations = [
'rest_spec_name', 'behavior', 'class_serializer', 'index_privileges', 'cluster_privileges', 'doc_id', 'availability'
'rest_spec_name', 'behavior', 'class_serializer', 'index_privileges', 'cluster_privileges', 'doc_id', 'availability', 'doc_tag'
]
// in most of the cases the jsDocs comes in a single block,
// but it can happen that the user defines multiple single line jsDoc.
Expand Down Expand Up @@ -696,6 +696,9 @@ export function hoistRequestAnnotations (
for (const [availabilityName, availabilityValue] of Object.entries(availabilities)) {
endpoint.availability[availabilityName] = availabilityValue
}
} else if (tag === 'doc_tag') {
assert(jsDocs, value.trim() !== '', `Request ${request.name.name}'s @doc_tag cannot be empty`)
endpoint.docTag = value.trim()
} else {
assert(jsDocs, false, `Unhandled tag: '${tag}' with value: '${value}' on request ${request.name.name}`)
}
Expand Down
18 changes: 18 additions & 0 deletions docs/modeling-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,24 @@ class Request {
foobar,/guide/en/example
```

#### `@doc_tag`

An OpenAPI tag that is used to group similar endpoints in the API documentation.
If it is absent, by default the tag is derived from the first part of the namespace.

```ts
/**
* @rest_spec_name api
* @doc_tag my tag
*/
class Request {
...
}
```

NOTE: In the OpenAPI specification, operations can have multiple tags. However, we currently support only a single tag.


#### `@codegen_name`

A custom name that can be used to display the property. Useful in Enums and
Expand Down
2 changes: 1 addition & 1 deletion output/openapi/elasticsearch-openapi.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion output/openapi/elasticsearch-serverless-openapi.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion output/schema/schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { Duration } from '@_types/Time'
* @availability stack since=7.9.0 stability=stable
* @availability serverless stability=stable visibility=public
* @index_privileges create_index
* @doc_tag data stream
*/
export interface Request extends RequestBase {
path_parts: {
Expand Down
2 changes: 1 addition & 1 deletion typescript-generator/src/metamodel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ export class Endpoint {
docId?: string
deprecation?: Deprecation
availability: Availabilities

docTag?: string
/**
* If the request value is `null` it means that there is not yet a
* request type definition for this endpoint.
Expand Down
Loading