Skip to content

Commit 9fde665

Browse files
committed
[OpenAPI] Add @ext_doc_id for endpoint externalDocs
1 parent 82461cc commit 9fde665

File tree

14 files changed

+67
-4
lines changed

14 files changed

+67
-4
lines changed

compiler-rs/clients_schema/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ pub trait Documented {
5555
fn description(&self) -> Option<&str>;
5656
}
5757

58+
pub trait ExternalDocument {
59+
fn ext_doc_id(&self) -> Option<&str>;
60+
fn ext_doc_url(&self) -> Option<&str>;
61+
}
62+
5863
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
5964
pub struct TypeName {
6065
// Order is important for Ord implementation
@@ -818,6 +823,12 @@ pub struct Endpoint {
818823
#[serde(skip_serializing_if = "Option::is_none")]
819824
pub doc_tag: Option<String>,
820825

826+
#[serde(skip_serializing_if = "Option::is_none")]
827+
pub ext_doc_id: Option<String>,
828+
829+
#[serde(skip_serializing_if = "Option::is_none")]
830+
pub ext_doc_url: Option<String>,
831+
821832
/// If missing, there is not yet a request definition for this endpoint.
822833
#[serde(skip_serializing_if = "Option::is_none")]
823834
pub request: Option<TypeName>,
@@ -854,6 +865,16 @@ impl Documented for Endpoint {
854865
}
855866
}
856867

868+
impl ExternalDocument for Endpoint {
869+
fn ext_doc_url(&self) -> Option<&str> {
870+
self.ext_doc_url.as_deref()
871+
}
872+
873+
fn ext_doc_id(&self) -> Option<&str> {
874+
self.ext_doc_id.as_deref()
875+
}
876+
}
877+
857878
#[derive(Debug, Clone, Serialize, Deserialize)]
858879
#[serde(rename_all = "camelCase")]
859880
pub struct Privileges {

compiler-rs/clients_schema_to_openapi/src/paths.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ pub fn add_endpoint(
203203
},
204204
summary: sum_desc.summary,
205205
description: sum_desc.description,
206-
// external_docs: tac.convert_external_docs(endpoint),
207-
external_docs: None, // Need values that differ from client purposes
206+
external_docs: tac.convert_endpoint_external_docs(endpoint),
207+
// external_docs: None, // Need values that differ from client purposes
208208
operation_id: None, // set in clone_operation below with operation_counter
209209
parameters,
210210
request_body: request_body.clone(),

compiler-rs/clients_schema_to_openapi/src/schemas.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ impl<'a> TypesAndComponents<'a> {
226226
})
227227
}
228228

229+
pub fn convert_endpoint_external_docs(&self, obj: &impl clients_schema::ExternalDocument) -> Option<ExternalDocumentation> {
230+
// FIXME: does the model contain resolved doc_id?
231+
obj.ext_doc_url().map(|url| {
232+
let branch: &str = self
233+
.model
234+
.info
235+
.as_ref()
236+
.and_then(|i| i.version.as_deref())
237+
.unwrap_or("current");
238+
ExternalDocumentation {
239+
description: None,
240+
url: url.trim().replace("{branch}", branch),
241+
extensions: Default::default(),
242+
}
243+
})
244+
}
245+
229246
fn for_body(&mut self, body: &Body) -> anyhow::Result<Option<ReferenceOr<Schema>>> {
230247
let result = match body {
231248
Body::NoBody(_) => None,
1.68 KB
Binary file not shown.

compiler/src/model/build-model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export function compileEndpoints (): Record<string, model.Endpoint> {
6868
description: spec.documentation.description,
6969
docUrl: spec.documentation.url,
7070
docTag: spec.docTag,
71+
extDocUrl: spec.externalDocs?.url,
7172
// Setting these values by default should be removed
7273
// when we no longer use rest-api-spec stubs as the
7374
// source of truth for stability/visibility.

compiler/src/model/json-spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ export interface JsonSpec {
6262
required?: boolean
6363
}
6464
docTag?: string
65+
externalDocs?: {
66+
url: string
67+
description?: string
68+
}
6569
}
6670

6771
export default function buildJsonSpec (): Map<string, JsonSpec> {

compiler/src/model/metamodel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ export class Endpoint {
406406
description: string
407407
docUrl: string
408408
docId?: string
409+
extDocId?: string
410+
extDocUrl?: string
409411
deprecation?: Deprecation
410412
availability: Availabilities
411413
docTag?: string

compiler/src/model/utils.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ export function hoistRequestAnnotations (
625625
request: model.Request, jsDocs: JSDoc[], mappings: Record<string, model.Endpoint>, response: model.TypeName | null
626626
): void {
627627
const knownRequestAnnotations = [
628-
'rest_spec_name', 'behavior', 'class_serializer', 'index_privileges', 'cluster_privileges', 'doc_id', 'availability', 'doc_tag'
628+
'rest_spec_name', 'behavior', 'class_serializer', 'index_privileges', 'cluster_privileges', 'doc_id', 'availability', 'doc_tag', `ext_doc_id`
629629
]
630630
// in most of the cases the jsDocs comes in a single block,
631631
// but it can happen that the user defines multiple single line jsDoc.
@@ -685,6 +685,12 @@ export function hoistRequestAnnotations (
685685
const docUrl = docIds.find(entry => entry[0] === value.trim())
686686
assert(jsDocs, docUrl != null, `The @doc_id '${value.trim()}' is not present in _doc_ids/table.csv`)
687687
endpoint.docUrl = docUrl[1].replace(/\r/g, '')
688+
} else if (tag === 'ext_doc_id') {
689+
assert(jsDocs, value.trim() !== '', `Request ${request.name.name}'s @ext_doc_id cannot be empty`)
690+
endpoint.extDocId = value.trim()
691+
const docUrl = docIds.find(entry => entry[0] === value.trim())
692+
assert(jsDocs, docUrl != null, `The @ext_doc_id '${value.trim()}' is not present in _doc_ids/table.csv`)
693+
endpoint.extDocUrl = docUrl[1].replace(/\r/g, '')
688694
} else if (tag === 'availability') {
689695
// The @availability jsTag is different than most because it allows
690696
// multiple values within the same docstring, hence needing to parse

output/openapi/elasticsearch-openapi.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

output/openapi/elasticsearch-serverless-openapi.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)