diff --git a/openapi-generator-template/model.mustache b/openapi-generator-template/model.mustache index ab15a350..e02e3b5a 100644 --- a/openapi-generator-template/model.mustache +++ b/openapi-generator-template/model.mustache @@ -129,7 +129,7 @@ impl Default for {{classname}} { {{/vendorExtensions.x-rust-builder}}{{! }}{{#vendorExtensions.x-rust-has-byte-array}}#[serde_as]{{/vendorExtensions.x-rust-has-byte-array}}{{! }}{{#oneOf.isEmpty}}#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] -pub struct {{{classname}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-borrowed-data}} { +pub struct {{{classname}}}{{#vendorExtensions.x-rust-has-lifetime}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-lifetime}} { {{#vars}} {{#description}} /// {{{.}}} @@ -148,15 +148,15 @@ pub struct {{{classname}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#ve ### Enums }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! ### Models - }}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{#vendorExtensions.x-rust-has-borrowed-data}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/vendorExtensions.x-rust-has-borrowed-data}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{! + }}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{#vendorExtensions.x-rust-has-lifetime}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/vendorExtensions.x-rust-has-lifetime}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{! ### ByteArray }}{{^isModel}}{{#isByteArray}}Vec{{/isByteArray}}{{! ### String - }}{{^isByteArray}}{{#isString}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}Cow<'a, str>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}String{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/isString}}{{! + }}{{^isByteArray}}{{#isString}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}Cow<'a, str>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}String{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/isString}}{{! ### Arrays }}{{^isString}}{{#isArray}}Vec<{{#items}}{{! ### Array Models - }}{{#isModel}}{{{dataType}}}{{#vendorExtensions.x-rust-has-borrowed-data}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isModel}}{{! + }}{{#isModel}}{{{dataType}}}{{#vendorExtensions.x-rust-has-lifetime}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/vendorExtensions.x-rust-has-lifetime}}{{/isModel}}{{! ### Array other datatypes }}{{^isModel}}{{{dataType}}}{{/isModel}}{{/items}}>{{/isArray}}{{! ### Primitive datatypes @@ -171,8 +171,8 @@ pub struct {{{classname}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#ve {{/vars}} } -impl{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-borrowed-data}} {{! - }}{{{classname}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-borrowed-data}} { +impl{{#vendorExtensions.x-rust-has-lifetime}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-lifetime}} {{! + }}{{{classname}}}{{#vendorExtensions.x-rust-has-lifetime}}<'a{{#vendorExtensions.x-rust-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-generic-parameter}}>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}{{/vendorExtensions.x-rust-has-lifetime}} { {{#description}} /// {{{.}}} {{/description}} @@ -183,11 +183,11 @@ impl{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#vendorExtensions.x-rust- }}{{^vendorExtensions.x-rust-type}}{{#isNullable}}Option<{{/isNullable}}{{! }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! }}{{^isEnum}}{{#isByteArray}}Vec{{/isByteArray}}{{! - }}{{^isByteArray}}{{#isString}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}Cow<'a, str>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}String{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/isString}}{{! + }}{{^isByteArray}}{{#isString}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}Cow<'a, str>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}String{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/isString}}{{! }}{{^isString}}{{#isArray}}Vec<{{#items}}{{! - }}{{#isModel}}{{{dataType}}}{{#vendorExtensions.x-rust-has-borrowed-data}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isModel}}{{! + }}{{#isModel}}{{{dataType}}}{{#vendorExtensions.x-rust-has-lifetime}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/vendorExtensions.x-rust-has-lifetime}}{{/isModel}}{{! }}{{^isModel}}{{{dataType}}}{{/isModel}}{{/items}}>{{/isArray}}{{! - }}{{^isArray}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-borrowed-data}}{{#model}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}{{^vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/model}}{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isModel}}{{! + }}{{^isArray}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-lifetime}}{{#model}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/model}}{{/vendorExtensions.x-rust-has-lifetime}}{{/isModel}}{{! }}{{/isArray}}{{/isString}}{{/isByteArray}}{{/isEnum}}{{! }}{{#isNullable}}>{{/isNullable}}{{/vendorExtensions.x-rust-type}}{{! ### Comma for next arguement @@ -218,16 +218,16 @@ impl{{#vendorExtensions.x-rust-has-borrowed-data}}<'a{{#vendorExtensions.x-rust- {{/description}} #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] -pub enum {{classname}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}} { +pub enum {{classname}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}} { {{#composedSchemas.oneOf}} {{#description}} /// {{{.}}} {{/description}} - {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{#isArray}}Vec<{{{items.dataType}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}>{{/isArray}}{{^isArray}}{{{dataType}}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'a>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isArray}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), + {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{#isArray}}Vec<{{{items.dataType}}}{{#items.vendorExtensions.x-rust-has-lifetime}}<'a>{{/items.vendorExtensions.x-rust-has-lifetime}}{{^items.vendorExtensions.x-rust-has-lifetime}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{/items.vendorExtensions.x-rust-has-lifetime}}>{{/isArray}}{{^isArray}}{{{dataType}}}{{#vendorExtensions.x-rust-has-lifetime}}<'a>{{/vendorExtensions.x-rust-has-lifetime}}{{/isArray}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), {{/composedSchemas.oneOf}} } -impl Default for {{classname}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'_>{{/vendorExtensions.x-rust-has-borrowed-data}} { +impl Default for {{classname}}{{#vendorExtensions.x-rust-has-lifetime}}<'_>{{/vendorExtensions.x-rust-has-lifetime}} { fn default() -> Self { {{#composedSchemas.oneOf}}{{#-first}}Self::{{{name}}}(Default::default()){{/-first}}{{/composedSchemas.oneOf}} } diff --git a/openapi-generator-template/reqwest/api.mustache b/openapi-generator-template/reqwest/api.mustache index 038480e2..e00ab73c 100644 --- a/openapi-generator-template/reqwest/api.mustache +++ b/openapi-generator-template/reqwest/api.mustache @@ -9,20 +9,11 @@ use serde::{Deserialize, Serialize, de::Error as _}; {{#operations}} {{#operation}} {{#vendorExtensions.x-group-parameters}} -{{#allParams}} -{{#-first}} +{{#hasParams}} /// struct for passing parameters to the method [`{{operationId}}`] #[derive(Clone, Debug)] -pub struct {{{operationIdCamelCase}}}Params<'p{{! - Iterate through ALL parameters in the operation. - Only the requestBody has this extension defined, so it will print "". - The other parameters have nothing, so they will print nothing. - This effectively extract the generic parameter from the requestBody - and places it on the struct definition line. -}}{{#allParams}} -{{#vendorExtensions.x-rust-params-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}} -{{/allParams}}> { -{{/-first}} +pub struct {{{operationIdCamelCase}}}Params{{#vendorExtensions.x-rust-has-lifetime}}<'p{{#allParams}}{{#vendorExtensions.x-rust-params-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}}{{/allParams}}>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}{{#allParams}}{{#-first}}{{#vendorExtensions.x-rust-params-generic-parameter}}<{{/vendorExtensions.x-rust-params-generic-parameter}}{{/-first}}{{/allParams}}{{#allParams}}{{#vendorExtensions.x-rust-params-generic-parameter}}{{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}}{{/allParams}}{{#allParams}}{{#-last}}{{#vendorExtensions.x-rust-params-generic-parameter}}>{{/vendorExtensions.x-rust-params-generic-parameter}}{{/-last}}{{/allParams}}{{/vendorExtensions.x-rust-has-lifetime}} { +{{#allParams}} {{#description}} /// {{{.}}} {{/description}} @@ -37,18 +28,17 @@ pub struct {{{operationIdCamelCase}}}Params<'p{{! }}{{^isUuid}}{{#isString}}{{#isArray}}Vec<{{/isArray}}Cow<'p, str>{{#isArray}}>{{/isArray}}{{/isString}}{{/isUuid}}{{! ### UUIDs }}{{#isUuid}}{{#isArray}}Vec<{{/isArray}}String{{#isArray}}>{{/isArray}}{{/isUuid}}{{! - ### Models and primative types - }}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{#isModel}}<'p>{{/isModel}}{{/isUuid}}{{/isString}}{{! + ### Models and primitive types + }}{{^isString}}{{^isUuid}}{{#isArray}}Vec<{{#items}}{{^isPrimitiveType}}models::{{/isPrimitiveType}}{{{dataType}}}{{^isPrimitiveType}}{{^isEnum}}{{#vendorExtensions.x-rust-has-lifetime}}<'p>{{/vendorExtensions.x-rust-has-lifetime}}{{/isEnum}}{{/isPrimitiveType}}{{/items}}>{{/isArray}}{{^isArray}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{^isContainer}}{{^isPrimitiveType}}{{^isEnum}}{{#vendorExtensions.x-rust-has-lifetime}}<'p>{{/vendorExtensions.x-rust-has-lifetime}}{{/isEnum}}{{/isPrimitiveType}}{{/isContainer}}{{/isArray}}{{/isUuid}}{{/isString}}{{! ### Option End }}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{! ### Comma for next arguement }}, {{/vendorExtensions.x-rust-type}} -{{#-last}} +{{/allParams}} } +{{/hasParams}} -{{/-last}} -{{/allParams}} {{/vendorExtensions.x-group-parameters}} {{/operation}} {{/operations}} @@ -106,16 +96,16 @@ pub enum {{{operationIdCamelCase}}}Error { /// {{{.}}} {{/notes}} {{#vendorExtensions.x-group-parameters}} -pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}(configuration: &configuration::Configuration{{#allParams}}{{#-first}}, {{! +pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}{{#vendorExtensions.x-rust-generic-parameter}}<{{{.}}}>{{/vendorExtensions.x-rust-generic-parameter}}(configuration: &configuration::Configuration{{#hasParams}}, {{! ### Params -}}params: &{{{operationIdCamelCase}}}Params<'_{{#allParams}}{{#vendorExtensions.x-rust-params-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}}{{/allParams}}>{{/-first}}{{/allParams}}{{! +}}params: &{{{operationIdCamelCase}}}Params{{#vendorExtensions.x-rust-has-lifetime}}<'_{{#allParams}}{{#vendorExtensions.x-rust-params-generic-parameter}}, {{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}}{{/allParams}}>{{/vendorExtensions.x-rust-has-lifetime}}{{^vendorExtensions.x-rust-has-lifetime}}{{#allParams}}{{#-first}}{{#vendorExtensions.x-rust-params-generic-parameter}}<{{/vendorExtensions.x-rust-params-generic-parameter}}{{/-first}}{{/allParams}}{{#allParams}}{{#vendorExtensions.x-rust-params-generic-parameter}}{{{.}}}{{/vendorExtensions.x-rust-params-generic-parameter}}{{/allParams}}{{#allParams}}{{#-last}}{{#vendorExtensions.x-rust-params-generic-parameter}}>{{/vendorExtensions.x-rust-params-generic-parameter}}{{/-last}}{{/allParams}}{{/vendorExtensions.x-rust-has-lifetime}}{{/hasParams}}{{! ### Function return type }}) -> Result<{{#vendorExtensions.x-rust-return-type}}{{{.}}}{{/vendorExtensions.x-rust-return-type}}{{^vendorExtensions.x-rust-return-type}}{{! }}{{#isResponseFile}}{{#supportAsync}}reqwest::Response{{/supportAsync}}{{^supportAsync}}reqwest::blocking::Response{{/supportAsync}}{{/isResponseFile}}{{! }}{{^isResponseFile}}{{#supportMultipleResponses}}ResponseContent<{{{operationIdCamelCase}}}Success>{{/supportMultipleResponses}}{{^supportMultipleResponses}}{{! }}{{^returnType}}(){{/returnType}}{{! -}}{{#isArray}}Vec<{{#returnProperty.items}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isModel}}{{/returnProperty.items}}>{{/isArray}}{{! -}}{{^isArray}}{{#returnProperty}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-borrowed-data}}<'static>{{/vendorExtensions.x-rust-has-borrowed-data}}{{/isModel}}{{/returnProperty}}{{! +}}{{#isArray}}Vec<{{#returnProperty.items}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/isModel}}{{/returnProperty.items}}>{{/isArray}}{{! +}}{{^isArray}}{{#returnProperty}}{{{dataType}}}{{#isModel}}{{#vendorExtensions.x-rust-has-lifetime}}<'static>{{/vendorExtensions.x-rust-has-lifetime}}{{/isModel}}{{/returnProperty}}{{! }}{{/isArray}}{{/supportMultipleResponses}}{{/isResponseFile}}{{/vendorExtensions.x-rust-return-type}}, Error<{{{operationIdCamelCase}}}Error>> { {{/vendorExtensions.x-group-parameters}} let uri_str = format!("{}{{{path}}}", configuration.base_path{{#pathParams}}, {{{baseName}}}={{#isString}}crate::apis::urlencode(&{{/isString}}{{{vendorExtensions.x-rust-param-identifier}}}{{^required}}.unwrap(){{/required}}{{#required}}{{#isNullable}}.unwrap(){{/isNullable}}{{/required}}{{#isArray}}.join(",").as_ref(){{/isArray}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}.to_string(){{/isContainer}}{{/isPrimitiveType}}{{/isUuid}}{{/isString}}{{#isString}}){{/isString}}{{/pathParams}}); diff --git a/preprocessed_openapi.yml b/preprocessed_openapi.yml index 229d79c7..671dc61c 100644 --- a/preprocessed_openapi.yml +++ b/preprocessed_openapi.yml @@ -119,6 +119,7 @@ paths: items: $ref: '#/components/schemas/CollectionResponse' x-go-type: '[]*CollectionResponse' + x-rust-has-lifetime: true post: tags: - collections @@ -132,6 +133,8 @@ paths: application/json: schema: $ref: '#/components/schemas/CollectionSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '201': description: Collection successfully created @@ -151,6 +154,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /collections/{collectionName}: get: tags: @@ -178,6 +182,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true patch: tags: - collections @@ -217,6 +222,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - collections @@ -243,6 +249,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /collections/{collectionName}/documents: post: tags: @@ -278,7 +285,6 @@ paths: type: object description: Can be any key-value pair x-go-type: interface{} - x-rust-has-borrowed-data: true responses: '201': description: Document successfully created/indexed @@ -293,6 +299,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true patch: tags: - documents @@ -320,7 +327,6 @@ paths: type: object description: Can be any key-value pair x-go-type: interface{} - x-rust-has-borrowed-data: true x-rust-params-generic-parameter: B x-rust-type: B responses: @@ -350,6 +356,7 @@ paths: schema: $ref: '#/components/schemas/ApiResponse' x-rust-generic-parameter: 'B: Serialize' + x-rust-has-lifetime: true delete: tags: - documents @@ -400,6 +407,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /collections/{collectionName}/documents/search: get: tags: @@ -847,6 +855,7 @@ paths: $ref: '#/components/schemas/ApiResponse' x-rust-generic-parameter: 'D: for<''de> serde::Deserialize<''de> + Serialize' x-rust-return-type: models::SearchResult + x-rust-has-lifetime: true /synonym_sets: get: tags: @@ -890,6 +899,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - synonyms @@ -923,6 +933,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - synonyms @@ -949,6 +960,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /synonym_sets/{synonymSetName}/items: get: tags: @@ -978,6 +990,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /synonym_sets/{synonymSetName}/items/{itemId}: get: tags: @@ -1011,6 +1024,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - synonyms @@ -1037,6 +1051,8 @@ paths: application/json: schema: $ref: '#/components/schemas/SynonymItemUpsertSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Synonym item successfully created/updated @@ -1050,6 +1066,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - synonyms @@ -1082,6 +1099,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /curation_sets: get: tags: @@ -1125,6 +1143,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - curation_sets @@ -1145,6 +1164,8 @@ paths: application/json: schema: $ref: '#/components/schemas/CurationSetCreateSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Curation set successfully created/updated @@ -1158,6 +1179,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - curation_sets @@ -1184,6 +1206,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /curation_sets/{curationSetName}/items: get: tags: @@ -1213,6 +1236,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /curation_sets/{curationSetName}/items/{itemId}: get: tags: @@ -1246,6 +1270,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - curation_sets @@ -1285,6 +1310,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - curation_sets @@ -1317,6 +1343,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /collections/{collectionName}/documents/export: get: tags: @@ -1364,6 +1391,7 @@ paths: schema: $ref: '#/components/schemas/ApiResponse' x-supports-plain-text: true + x-rust-has-lifetime: true /collections/{collectionName}/documents/import: post: tags: @@ -1435,6 +1463,7 @@ paths: $ref: '#/components/schemas/ApiResponse' x-rust-body-is-raw-text: true x-supports-plain-text: true + x-rust-has-lifetime: true /collections/{collectionName}/documents/{documentId}: get: tags: @@ -1469,6 +1498,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true patch: tags: - documents @@ -1502,7 +1532,6 @@ paths: type: object description: Can be any key-value pair x-go-type: interface{} - x-rust-has-borrowed-data: true x-rust-params-generic-parameter: B x-rust-type: B responses: @@ -1520,6 +1549,7 @@ paths: schema: $ref: '#/components/schemas/ApiResponse' x-rust-generic-parameter: 'B: Serialize' + x-rust-has-lifetime: true delete: tags: - documents @@ -1553,6 +1583,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /conversations/models: get: tags: @@ -1582,6 +1613,8 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelCreateSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '201': description: Created Conversation Model @@ -1595,6 +1628,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /conversations/models/{modelId}: get: tags: @@ -1616,6 +1650,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelSchema' + x-rust-has-lifetime: true put: tags: - conversations @@ -1635,6 +1670,8 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelUpdateSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: The conversation model was successfully updated @@ -1642,6 +1679,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelSchema' + x-rust-has-lifetime: true delete: tags: - conversations @@ -1662,6 +1700,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelSchema' + x-rust-has-lifetime: true /keys: get: tags: @@ -1687,6 +1726,8 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiKeySchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '201': description: Created API key @@ -1706,6 +1747,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /keys/{keyId}: get: tags: @@ -1800,6 +1842,8 @@ paths: application/json: schema: $ref: '#/components/schemas/CollectionAliasSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: The collection alias was created/updated @@ -1819,6 +1863,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true get: tags: - collections @@ -1845,6 +1890,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - collections @@ -1870,6 +1916,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /debug: get: tags: @@ -1939,6 +1986,7 @@ paths: application/json: schema: $ref: '#/components/schemas/SuccessStatus' + x-rust-has-lifetime: true /operations/vote: post: tags: @@ -2000,7 +2048,6 @@ paths: properties: log-slow-requests-time-ms: type: integer - x-rust-has-borrowed-data: true responses: '200': description: Toggle Slow Request Log database succeeded. @@ -2393,6 +2440,8 @@ paths: application/json: schema: $ref: '#/components/schemas/MultiSearchSearchesParameter' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Search results @@ -2407,6 +2456,7 @@ paths: schema: $ref: '#/components/schemas/ApiResponse' x-rust-return-type: serde_json::Value + x-rust-has-lifetime: true /analytics/events: post: tags: @@ -2421,6 +2471,8 @@ paths: application/json: schema: $ref: '#/components/schemas/AnalyticsEvent' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Analytics event successfully created @@ -2434,6 +2486,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true get: tags: - analytics @@ -2471,6 +2524,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /analytics/flush: post: tags: @@ -2514,10 +2568,14 @@ paths: schema: oneOf: - $ref: '#/components/schemas/AnalyticsRuleCreate' + x-rust-has-lifetime: true - type: array items: $ref: '#/components/schemas/AnalyticsRuleCreate' - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Analytics rule(s) successfully created @@ -2540,6 +2598,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true get: tags: - analytics @@ -2562,6 +2621,7 @@ paths: type: array items: $ref: '#/components/schemas/AnalyticsRule' + x-rust-has-lifetime: true /analytics/rules/{ruleName}: put: tags: @@ -2583,6 +2643,8 @@ paths: application/json: schema: $ref: '#/components/schemas/AnalyticsRuleUpdate' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Analytics rule successfully upserted @@ -2596,6 +2658,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true get: tags: - analytics @@ -2622,6 +2685,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - analytics @@ -2648,6 +2712,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /metrics.json: get: tags: @@ -2712,6 +2777,8 @@ paths: application/json: schema: $ref: '#/components/schemas/StopwordsSetUpsertSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Stopwords set successfully upserted. @@ -2725,6 +2792,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true get: tags: - stopwords @@ -2752,6 +2820,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - stopwords @@ -2786,6 +2855,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /presets: get: tags: @@ -2828,6 +2898,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - presets @@ -2849,6 +2920,8 @@ paths: application/json: schema: $ref: '#/components/schemas/PresetUpsertSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: Preset successfully upserted. @@ -2862,6 +2935,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - presets @@ -2889,6 +2963,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /stemming/dictionaries: get: tags: @@ -2939,6 +3014,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /stemming/dictionaries/import: post: tags: @@ -2981,6 +3057,7 @@ paths: $ref: '#/components/schemas/ApiResponse' x-rust-body-is-raw-text: true x-supports-plain-text: true + x-rust-has-lifetime: true /nl_search_models: get: tags: @@ -3010,6 +3087,8 @@ paths: application/json: schema: $ref: '#/components/schemas/NLSearchModelCreateSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '201': description: NL search model successfully created @@ -3023,6 +3102,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true /nl_search_models/{modelId}: get: tags: @@ -3050,6 +3130,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true put: tags: - nl_search_models @@ -3070,6 +3151,8 @@ paths: application/json: schema: $ref: '#/components/schemas/NLSearchModelUpdateSchema' + x-rust-has-lifetime: true + x-rust-has-lifetime: true responses: '200': description: NL search model successfully updated @@ -3089,6 +3172,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true delete: tags: - nl_search_models @@ -3115,6 +3199,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + x-rust-has-lifetime: true components: schemas: CollectionSchema: @@ -3182,9 +3267,8 @@ components: type: object description: | Optional details about the collection, e.g., when it was created, who created it etc. - x-rust-has-borrowed-data: true x-rust-builder: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true CollectionUpdateSchema: type: object required: @@ -3215,8 +3299,6 @@ components: type: object description: | Optional details about the collection, e.g., when it was created, who created it etc. - x-rust-has-borrowed-data: true - x-rust-has-borrowed-data: true CollectionResponse: allOf: - $ref: '#/components/schemas/CollectionSchema' @@ -3367,7 +3449,7 @@ components: collection_name: type: string description: Name of the collection you wish to map the alias to - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true CollectionAlias: type: object required: @@ -3711,7 +3793,7 @@ components: expires_at: type: integer format: int64 - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true ApiKey: allOf: - $ref: '#/components/schemas/ApiKeySchema' @@ -4043,7 +4125,7 @@ components: description: | The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. x-rust-builder: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true MultiSearchParameters: type: object description: | @@ -4294,7 +4376,7 @@ components: description: | The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. x-rust-builder: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true MultiSearchSearchesParameter: type: object required: @@ -4308,7 +4390,9 @@ components: type: array items: $ref: '#/components/schemas/MultiSearchCollectionParameters' - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true MultiSearchCollectionParameters: allOf: - $ref: '#/components/schemas/MultiSearchParameters' @@ -4327,7 +4411,7 @@ components: When true, computes both text match and vector distance scores for all matches in hybrid search. Documents found only through keyword search will get a vector distance score, and documents found only through vector search will get a text match score. default: false x-rust-builder: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true FacetCounts: type: object properties: @@ -4399,8 +4483,8 @@ components: type: string analytics_tag: type: string - x-rust-has-borrowed-data: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true AnalyticsEventsResponse: type: object required: @@ -4467,8 +4551,8 @@ components: type: string weight: type: integer - x-rust-has-borrowed-data: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true AnalyticsRuleType: type: string enum: @@ -4503,8 +4587,8 @@ components: type: string weight: type: integer - x-rust-has-borrowed-data: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true AnalyticsRule: allOf: - $ref: '#/components/schemas/AnalyticsRuleCreate' @@ -4581,7 +4665,7 @@ components: type: string locale: type: string - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true StopwordsSetSchema: type: object required: @@ -4625,9 +4709,11 @@ components: value: oneOf: - $ref: '#/components/schemas/SearchParameters' + x-rust-has-lifetime: true - $ref: '#/components/schemas/MultiSearchSearchesParameter' - x-rust-has-borrowed-data: true - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true + x-rust-has-lifetime: true PresetSchema: allOf: - $ref: '#/components/schemas/PresetUpsertSchema' @@ -4661,7 +4747,6 @@ components: - coerce_or_drop - drop - reject - x-rust-has-borrowed-data: true IndexAction: type: string enum: @@ -4669,7 +4754,6 @@ components: - update - upsert - emplace - x-rust-has-borrowed-data: true DropTokensMode: type: string description: | @@ -4678,7 +4762,6 @@ components: - right_to_left - left_to_right - both_sides:3 - x-rust-has-borrowed-data: true ConversationModelCreateSchema: required: - model_name @@ -4701,7 +4784,7 @@ components: history_collection: type: string description: Typesense collection that stores the historical conversations - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true ConversationModelUpdateSchema: type: object properties: @@ -4734,7 +4817,7 @@ components: vllm_url: type: string description: URL of vLLM service - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true ConversationModelSchema: allOf: - $ref: '#/components/schemas/ConversationModelCreateSchema' @@ -4831,6 +4914,7 @@ components: account_id: type: string description: Account ID for Cloudflare-specific models + x-rust-has-lifetime: true NLSearchModelCreateSchema: allOf: - $ref: '#/components/schemas/NLSearchModelBase' @@ -4839,7 +4923,7 @@ components: id: type: string description: Optional ID for the NL search model - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true NLSearchModelSchema: allOf: - $ref: '#/components/schemas/NLSearchModelCreateSchema' @@ -4851,8 +4935,9 @@ components: type: string description: ID of the NL search model NLSearchModelUpdateSchema: - $ref: '#/components/schemas/NLSearchModelCreateSchema' - x-rust-has-borrowed-data: true + allOf: + - $ref: '#/components/schemas/NLSearchModelCreateSchema' + x-rust-has-lifetime: true NLSearchModelDeleteSchema: type: object required: @@ -4882,7 +4967,7 @@ components: description: By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is items: type: string - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true SynonymItemSchema: allOf: - type: object @@ -4903,7 +4988,6 @@ components: description: Array of synonym items items: $ref: '#/components/schemas/SynonymItemSchema' - x-rust-has-borrowed-data: true SynonymSetSchema: allOf: - $ref: '#/components/schemas/SynonymSetCreateSchema' @@ -4969,7 +5053,6 @@ components: type: object description: | Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. - x-rust-has-borrowed-data: true sort_by: type: string description: | @@ -4997,7 +5080,6 @@ components: id: type: string description: ID of the curation item - x-rust-has-borrowed-data: true CurationItemSchema: allOf: - $ref: '#/components/schemas/CurationItemCreateSchema' @@ -5020,7 +5102,7 @@ components: description: type: string description: Optional description for the curation set - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true CurationSetSchema: allOf: - $ref: '#/components/schemas/CurationSetCreateSchema' @@ -5104,7 +5186,6 @@ components: $ref: '#/components/schemas/IndexAction' dirty_values: $ref: '#/components/schemas/DirtyValues' - x-rust-has-borrowed-data: true ExportDocumentsParameters: type: object properties: @@ -5117,14 +5198,14 @@ components: exclude_fields: type: string description: List of fields from the document to exclude in the search result - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true UpdateDocumentsParameters: type: object properties: filter_by: type: string example: 'num_employees:>100 && country: [USA, UK]' - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true DeleteDocumentsParameters: type: object required: @@ -5141,7 +5222,7 @@ components: truncate: type: boolean description: When true, removes all documents from the collection while preserving the collection and its schema. - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true GetCollectionsParameters: type: object properties: @@ -5155,7 +5236,7 @@ components: offset: type: integer description: Identifies the starting point to return collections when paginating. - x-rust-has-borrowed-data: true + x-rust-has-lifetime: true securitySchemes: api_key_header: type: apiKey diff --git a/typesense/src/client/curation_set/items.rs b/typesense/src/client/curation_set/items.rs index decaa352..2bfcdfcb 100644 --- a/typesense/src/client/curation_set/items.rs +++ b/typesense/src/client/curation_set/items.rs @@ -51,7 +51,7 @@ impl<'a> CurationSetItems<'a> { pub async fn upsert( &self, item_id: impl Into>, - schema: models::CurationItemCreateSchema<'_>, + schema: models::CurationItemCreateSchema, ) -> Result> { let params = curation_sets_api::UpsertCurationSetItemParams { diff --git a/typesense_codegen/.openapi-generator/FILES b/typesense_codegen/.openapi-generator/FILES index 3b12b38f..59ee81c0 100644 --- a/typesense_codegen/.openapi-generator/FILES +++ b/typesense_codegen/.openapi-generator/FILES @@ -73,6 +73,7 @@ docs/NlSearchModelBase.md docs/NlSearchModelCreateSchema.md docs/NlSearchModelDeleteSchema.md docs/NlSearchModelSchema.md +docs/NlSearchModelUpdateSchema.md docs/NlSearchModelsApi.md docs/OperationsApi.md docs/PresetDeleteSchema.md @@ -200,6 +201,7 @@ src/models/nl_search_model_base.rs src/models/nl_search_model_create_schema.rs src/models/nl_search_model_delete_schema.rs src/models/nl_search_model_schema.rs +src/models/nl_search_model_update_schema.rs src/models/preset_delete_schema.rs src/models/preset_schema.rs src/models/preset_upsert_schema.rs diff --git a/typesense_codegen/README.md b/typesense_codegen/README.md index dd7acf1f..a245a8d7 100644 --- a/typesense_codegen/README.md +++ b/typesense_codegen/README.md @@ -175,6 +175,7 @@ Class | Method | HTTP request | Description - [NlSearchModelCreateSchema](docs/NlSearchModelCreateSchema.md) - [NlSearchModelDeleteSchema](docs/NlSearchModelDeleteSchema.md) - [NlSearchModelSchema](docs/NlSearchModelSchema.md) + - [NlSearchModelUpdateSchema](docs/NlSearchModelUpdateSchema.md) - [PresetDeleteSchema](docs/PresetDeleteSchema.md) - [PresetSchema](docs/PresetSchema.md) - [PresetUpsertSchema](docs/PresetUpsertSchema.md) diff --git a/typesense_codegen/docs/AnalyticsRuleUpdateParams.md b/typesense_codegen/docs/AnalyticsRuleUpdateParams.md new file mode 100644 index 00000000..f2e45f6c --- /dev/null +++ b/typesense_codegen/docs/AnalyticsRuleUpdateParams.md @@ -0,0 +1,17 @@ +# AnalyticsRuleUpdateParams + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**destination_collection** | Option<**String**> | | [optional] +**limit** | Option<**i32**> | | [optional] +**capture_search_requests** | Option<**bool**> | | [optional] +**meta_fields** | Option<**Vec**> | | [optional] +**expand_query** | Option<**bool**> | | [optional] +**counter_field** | Option<**String**> | | [optional] +**weight** | Option<**i32**> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/typesense_codegen/docs/NlSearchModelUpdateSchema.md b/typesense_codegen/docs/NlSearchModelUpdateSchema.md new file mode 100644 index 00000000..10a8894b --- /dev/null +++ b/typesense_codegen/docs/NlSearchModelUpdateSchema.md @@ -0,0 +1,29 @@ +# NlSearchModelUpdateSchema + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**model_name** | Option<**String**> | Name of the NL model to use | [optional] +**api_key** | Option<**String**> | API key for the NL model service | [optional] +**api_url** | Option<**String**> | Custom API URL for the NL model service | [optional] +**max_bytes** | Option<**i32**> | Maximum number of bytes to process | [optional] +**temperature** | Option<**f64**> | Temperature parameter for the NL model | [optional] +**system_prompt** | Option<**String**> | System prompt for the NL model | [optional] +**top_p** | Option<**f64**> | Top-p parameter for the NL model (Google-specific) | [optional] +**top_k** | Option<**i32**> | Top-k parameter for the NL model (Google-specific) | [optional] +**stop_sequences** | Option<**Vec**> | Stop sequences for the NL model (Google-specific) | [optional] +**api_version** | Option<**String**> | API version for the NL model service | [optional] +**project_id** | Option<**String**> | Project ID for GCP Vertex AI | [optional] +**access_token** | Option<**String**> | Access token for GCP Vertex AI | [optional] +**refresh_token** | Option<**String**> | Refresh token for GCP Vertex AI | [optional] +**client_id** | Option<**String**> | Client ID for GCP Vertex AI | [optional] +**client_secret** | Option<**String**> | Client secret for GCP Vertex AI | [optional] +**region** | Option<**String**> | Region for GCP Vertex AI | [optional] +**max_output_tokens** | Option<**i32**> | Maximum output tokens for GCP Vertex AI | [optional] +**account_id** | Option<**String**> | Account ID for Cloudflare-specific models | [optional] +**id** | Option<**String**> | Optional ID for the NL search model | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/typesense_codegen/docs/NlSearchModelsApi.md b/typesense_codegen/docs/NlSearchModelsApi.md index 07d54480..49e922ee 100644 --- a/typesense_codegen/docs/NlSearchModelsApi.md +++ b/typesense_codegen/docs/NlSearchModelsApi.md @@ -131,7 +131,7 @@ Name | Type | Description | Required | Notes ## update_nl_search_model -> models::NlSearchModelSchema update_nl_search_model(model_id, body) +> models::NlSearchModelSchema update_nl_search_model(model_id, nl_search_model_update_schema) Update a NL search model Update an existing NL search model. @@ -142,7 +142,7 @@ Update an existing NL search model. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- **model_id** | **String** | The ID of the NL search model to update | [required] | -**body** | **models::NlSearchModelCreateSchema** | The NL search model fields to update | [required] | +**nl_search_model_update_schema** | [**NlSearchModelUpdateSchema**](NlSearchModelUpdateSchema.md) | The NL search model fields to update | [required] | ### Return type diff --git a/typesense_codegen/src/apis/curation_sets_api.rs b/typesense_codegen/src/apis/curation_sets_api.rs index 2e67cf71..1f3340c9 100644 --- a/typesense_codegen/src/apis/curation_sets_api.rs +++ b/typesense_codegen/src/apis/curation_sets_api.rs @@ -70,7 +70,7 @@ pub struct UpsertCurationSetItemParams<'p> { /// The id of the curation item to upsert pub item_id: Cow<'p, str>, /// The curation item to be created/updated - pub curation_item_create_schema: models::CurationItemCreateSchema<'p>, + pub curation_item_create_schema: models::CurationItemCreateSchema, } /// struct for typed errors of method [`delete_curation_set`] diff --git a/typesense_codegen/src/apis/nl_search_models_api.rs b/typesense_codegen/src/apis/nl_search_models_api.rs index eef9fa05..317f0412 100644 --- a/typesense_codegen/src/apis/nl_search_models_api.rs +++ b/typesense_codegen/src/apis/nl_search_models_api.rs @@ -41,7 +41,7 @@ pub struct UpdateNlSearchModelParams<'p> { /// The ID of the NL search model to update pub model_id: Cow<'p, str>, /// The NL search model fields to update - pub body: models::NlSearchModelCreateSchema<'p>, + pub nl_search_model_update_schema: models::NlSearchModelUpdateSchema<'p>, } /// struct for typed errors of method [`create_nl_search_model`] @@ -347,7 +347,7 @@ pub async fn update_nl_search_model( }; req_builder = req_builder.header("X-TYPESENSE-API-KEY", value); }; - req_builder = req_builder.json(¶ms.body); + req_builder = req_builder.json(¶ms.nl_search_model_update_schema); let req = req_builder.build()?; let resp = configuration.client.execute(req).await?; diff --git a/typesense_codegen/src/models/curation_item_create_schema.rs b/typesense_codegen/src/models/curation_item_create_schema.rs index 430d10f8..9036e12b 100644 --- a/typesense_codegen/src/models/curation_item_create_schema.rs +++ b/typesense_codegen/src/models/curation_item_create_schema.rs @@ -13,7 +13,7 @@ use ::std::borrow::Cow; use serde::{Deserialize, Serialize}; #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] -pub struct CurationItemCreateSchema<'a> { +pub struct CurationItemCreateSchema { #[serde(rename = "rule")] pub rule: Box, /// List of document `id`s that should be included in the search results with their corresponding `position`s. @@ -24,7 +24,7 @@ pub struct CurationItemCreateSchema<'a> { pub excludes: Option>, /// A filter by clause that is applied to any search query that matches the curation rule. #[serde(rename = "filter_by", skip_serializing_if = "Option::is_none")] - pub filter_by: Option>, + pub filter_by: Option, /// Indicates whether search query tokens that exist in the curation's rule should be removed from the search query. #[serde( rename = "remove_matched_tokens", @@ -36,10 +36,10 @@ pub struct CurationItemCreateSchema<'a> { pub metadata: Option, /// A sort by clause that is applied to any search query that matches the curation rule. #[serde(rename = "sort_by", skip_serializing_if = "Option::is_none")] - pub sort_by: Option>, + pub sort_by: Option, /// Replaces the current search query with this value, when the search query matches the curation rule. #[serde(rename = "replace_query", skip_serializing_if = "Option::is_none")] - pub replace_query: Option>, + pub replace_query: Option, /// When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. #[serde( rename = "filter_curated_hits", @@ -57,10 +57,10 @@ pub struct CurationItemCreateSchema<'a> { pub stop_processing: Option, /// ID of the curation item #[serde(rename = "id", skip_serializing_if = "Option::is_none")] - pub id: Option>, + pub id: Option, } -impl<'a> CurationItemCreateSchema<'a> { +impl CurationItemCreateSchema { pub fn new(rule: models::CurationRule) -> Self { Self { rule: Box::new(rule), diff --git a/typesense_codegen/src/models/curation_set_create_schema.rs b/typesense_codegen/src/models/curation_set_create_schema.rs index c8b336c7..8b4d3f56 100644 --- a/typesense_codegen/src/models/curation_set_create_schema.rs +++ b/typesense_codegen/src/models/curation_set_create_schema.rs @@ -16,14 +16,14 @@ use serde::{Deserialize, Serialize}; pub struct CurationSetCreateSchema<'a> { /// Array of curation items #[serde(rename = "items")] - pub items: Vec>, + pub items: Vec, /// Optional description for the curation set #[serde(rename = "description", skip_serializing_if = "Option::is_none")] pub description: Option>, } impl<'a> CurationSetCreateSchema<'a> { - pub fn new(items: Vec>) -> Self { + pub fn new(items: Vec) -> Self { Self { items, description: None, diff --git a/typesense_codegen/src/models/curation_set_schema.rs b/typesense_codegen/src/models/curation_set_schema.rs index 6f4d2c87..1f7f46bd 100644 --- a/typesense_codegen/src/models/curation_set_schema.rs +++ b/typesense_codegen/src/models/curation_set_schema.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; pub struct CurationSetSchema { /// Array of curation items #[serde(rename = "items")] - pub items: Vec>, + pub items: Vec, /// Optional description for the curation set #[serde(rename = "description", skip_serializing_if = "Option::is_none")] pub description: Option, @@ -25,7 +25,7 @@ pub struct CurationSetSchema { } impl CurationSetSchema { - pub fn new(items: Vec>, name: String) -> Self { + pub fn new(items: Vec, name: String) -> Self { Self { items, description: None, diff --git a/typesense_codegen/src/models/mod.rs b/typesense_codegen/src/models/mod.rs index a02d0e0d..0b29576f 100644 --- a/typesense_codegen/src/models/mod.rs +++ b/typesense_codegen/src/models/mod.rs @@ -130,6 +130,8 @@ pub mod nl_search_model_delete_schema; pub use self::nl_search_model_delete_schema::NlSearchModelDeleteSchema; pub mod nl_search_model_schema; pub use self::nl_search_model_schema::NlSearchModelSchema; +pub mod nl_search_model_update_schema; +pub use self::nl_search_model_update_schema::NlSearchModelUpdateSchema; pub mod preset_delete_schema; pub use self::preset_delete_schema::PresetDeleteSchema; pub mod preset_schema; diff --git a/typesense_codegen/src/models/nl_search_model_base.rs b/typesense_codegen/src/models/nl_search_model_base.rs index a9b4d931..07c0e859 100644 --- a/typesense_codegen/src/models/nl_search_model_base.rs +++ b/typesense_codegen/src/models/nl_search_model_base.rs @@ -13,16 +13,16 @@ use ::std::borrow::Cow; use serde::{Deserialize, Serialize}; #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] -pub struct NlSearchModelBase { +pub struct NlSearchModelBase<'a> { /// Name of the NL model to use #[serde(rename = "model_name", skip_serializing_if = "Option::is_none")] - pub model_name: Option, + pub model_name: Option>, /// API key for the NL model service #[serde(rename = "api_key", skip_serializing_if = "Option::is_none")] - pub api_key: Option, + pub api_key: Option>, /// Custom API URL for the NL model service #[serde(rename = "api_url", skip_serializing_if = "Option::is_none")] - pub api_url: Option, + pub api_url: Option>, /// Maximum number of bytes to process #[serde(rename = "max_bytes", skip_serializing_if = "Option::is_none")] pub max_bytes: Option, @@ -31,7 +31,7 @@ pub struct NlSearchModelBase { pub temperature: Option, /// System prompt for the NL model #[serde(rename = "system_prompt", skip_serializing_if = "Option::is_none")] - pub system_prompt: Option, + pub system_prompt: Option>, /// Top-p parameter for the NL model (Google-specific) #[serde(rename = "top_p", skip_serializing_if = "Option::is_none")] pub top_p: Option, @@ -43,34 +43,34 @@ pub struct NlSearchModelBase { pub stop_sequences: Option>, /// API version for the NL model service #[serde(rename = "api_version", skip_serializing_if = "Option::is_none")] - pub api_version: Option, + pub api_version: Option>, /// Project ID for GCP Vertex AI #[serde(rename = "project_id", skip_serializing_if = "Option::is_none")] - pub project_id: Option, + pub project_id: Option>, /// Access token for GCP Vertex AI #[serde(rename = "access_token", skip_serializing_if = "Option::is_none")] - pub access_token: Option, + pub access_token: Option>, /// Refresh token for GCP Vertex AI #[serde(rename = "refresh_token", skip_serializing_if = "Option::is_none")] - pub refresh_token: Option, + pub refresh_token: Option>, /// Client ID for GCP Vertex AI #[serde(rename = "client_id", skip_serializing_if = "Option::is_none")] - pub client_id: Option, + pub client_id: Option>, /// Client secret for GCP Vertex AI #[serde(rename = "client_secret", skip_serializing_if = "Option::is_none")] - pub client_secret: Option, + pub client_secret: Option>, /// Region for GCP Vertex AI #[serde(rename = "region", skip_serializing_if = "Option::is_none")] - pub region: Option, + pub region: Option>, /// Maximum output tokens for GCP Vertex AI #[serde(rename = "max_output_tokens", skip_serializing_if = "Option::is_none")] pub max_output_tokens: Option, /// Account ID for Cloudflare-specific models #[serde(rename = "account_id", skip_serializing_if = "Option::is_none")] - pub account_id: Option, + pub account_id: Option>, } -impl NlSearchModelBase { +impl<'a> NlSearchModelBase<'a> { pub fn new() -> Self { Self { model_name: None, diff --git a/typesense_codegen/src/models/nl_search_model_update_schema.rs b/typesense_codegen/src/models/nl_search_model_update_schema.rs new file mode 100644 index 00000000..2a1d2dec --- /dev/null +++ b/typesense_codegen/src/models/nl_search_model_update_schema.rs @@ -0,0 +1,100 @@ +/* + * Typesense API + * + * An open source search engine for building delightful search experiences. + * + * The version of the OpenAPI document: 30.0 + * + * Generated by: https://openapi-generator.tech + */ + +use crate::models; +use ::std::borrow::Cow; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct NlSearchModelUpdateSchema<'a> { + /// Name of the NL model to use + #[serde(rename = "model_name", skip_serializing_if = "Option::is_none")] + pub model_name: Option>, + /// API key for the NL model service + #[serde(rename = "api_key", skip_serializing_if = "Option::is_none")] + pub api_key: Option>, + /// Custom API URL for the NL model service + #[serde(rename = "api_url", skip_serializing_if = "Option::is_none")] + pub api_url: Option>, + /// Maximum number of bytes to process + #[serde(rename = "max_bytes", skip_serializing_if = "Option::is_none")] + pub max_bytes: Option, + /// Temperature parameter for the NL model + #[serde(rename = "temperature", skip_serializing_if = "Option::is_none")] + pub temperature: Option, + /// System prompt for the NL model + #[serde(rename = "system_prompt", skip_serializing_if = "Option::is_none")] + pub system_prompt: Option>, + /// Top-p parameter for the NL model (Google-specific) + #[serde(rename = "top_p", skip_serializing_if = "Option::is_none")] + pub top_p: Option, + /// Top-k parameter for the NL model (Google-specific) + #[serde(rename = "top_k", skip_serializing_if = "Option::is_none")] + pub top_k: Option, + /// Stop sequences for the NL model (Google-specific) + #[serde(rename = "stop_sequences", skip_serializing_if = "Option::is_none")] + pub stop_sequences: Option>, + /// API version for the NL model service + #[serde(rename = "api_version", skip_serializing_if = "Option::is_none")] + pub api_version: Option>, + /// Project ID for GCP Vertex AI + #[serde(rename = "project_id", skip_serializing_if = "Option::is_none")] + pub project_id: Option>, + /// Access token for GCP Vertex AI + #[serde(rename = "access_token", skip_serializing_if = "Option::is_none")] + pub access_token: Option>, + /// Refresh token for GCP Vertex AI + #[serde(rename = "refresh_token", skip_serializing_if = "Option::is_none")] + pub refresh_token: Option>, + /// Client ID for GCP Vertex AI + #[serde(rename = "client_id", skip_serializing_if = "Option::is_none")] + pub client_id: Option>, + /// Client secret for GCP Vertex AI + #[serde(rename = "client_secret", skip_serializing_if = "Option::is_none")] + pub client_secret: Option>, + /// Region for GCP Vertex AI + #[serde(rename = "region", skip_serializing_if = "Option::is_none")] + pub region: Option>, + /// Maximum output tokens for GCP Vertex AI + #[serde(rename = "max_output_tokens", skip_serializing_if = "Option::is_none")] + pub max_output_tokens: Option, + /// Account ID for Cloudflare-specific models + #[serde(rename = "account_id", skip_serializing_if = "Option::is_none")] + pub account_id: Option>, + /// Optional ID for the NL search model + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option>, +} + +impl<'a> NlSearchModelUpdateSchema<'a> { + pub fn new() -> Self { + Self { + model_name: None, + api_key: None, + api_url: None, + max_bytes: None, + temperature: None, + system_prompt: None, + top_p: None, + top_k: None, + stop_sequences: None, + api_version: None, + project_id: None, + access_token: None, + refresh_token: None, + client_id: None, + client_secret: None, + region: None, + max_output_tokens: None, + account_id: None, + id: None, + } + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index bb60432c..b25aab4e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -2,6 +2,7 @@ use anyhow::{Context, Result}; use clap::{Parser, ValueEnum}; use std::{env, fs, process::Command}; mod add_vendor_attributes; +mod mark_borrowed_data; mod preprocess_openapi; #[cfg(feature = "typesense")] mod test_clean; diff --git a/xtask/src/mark_borrowed_data.rs b/xtask/src/mark_borrowed_data.rs new file mode 100644 index 00000000..2af22025 --- /dev/null +++ b/xtask/src/mark_borrowed_data.rs @@ -0,0 +1,238 @@ +use indexmap::IndexMap; + +use crate::preprocess_openapi::OpenAPIProperty; + +pub(crate) fn is_forced_borrow_model(name: &str) -> bool { + matches!( + name, + "SearchParameters" + | "MultiSearchParameters" + | "MultiSearchSearchesParameter" + | "MultiSearchCollectionParameters" + ) +} +// Deeply traverse resolving $refs to ensure all nested request models are tracked. +pub(crate) fn collect_request_schemas( + property: &OpenAPIProperty, + schemas: &IndexMap, + collected: &mut std::collections::HashSet, +) { + if let Some(reference) = &property.r#ref { + let name = reference.trim_start_matches("#/components/schemas/"); + if collected.insert(name.to_owned()) + && let Some(schema) = schemas.get(name) + { + collect_request_schemas(schema, schemas, collected); + } + } + + if let Some(properties) = &property.properties { + for nested_property in properties.values() { + collect_request_schemas(nested_property, schemas, collected); + } + } + if let Some(items) = &property.items { + collect_request_schemas(items, schemas, collected); + } + if let Some(one_of) = &property.one_of { + for variant in one_of { + collect_request_schemas(variant, schemas, collected); + } + } + if let Some(any_of) = &property.any_of { + for variant in any_of { + collect_request_schemas(variant, schemas, collected); + } + } + + if let Some(all_of_value) = property.extra.get("allOf") + && let Ok(sequence) = serde_yaml::from_value::>(all_of_value.clone()) + { + for item in sequence { + collect_request_schemas(&item, schemas, collected); + } + } + if let Some(additional_properties_value) = property.extra.get("additionalProperties") + && let Ok(additional_property) = + serde_yaml::from_value::(additional_properties_value.clone()) + { + collect_request_schemas(&additional_property, schemas, collected); + } +} + +// Deeply traverse resolving $refs to ensure all nested response models are tracked. +// IMPORTANT: treat `allOf` as a mixin and do NOT blocklist the mixin schema itself. +pub(crate) fn collect_response_schemas( + property: &OpenAPIProperty, + schemas: &IndexMap, + collected: &mut std::collections::HashSet, + is_mixin: bool, +) { + if let Some(reference) = &property.r#ref { + let name = reference.trim_start_matches("#/components/schemas/"); + + if !is_mixin { + // It's a direct type reference, blocklist it. + if collected.insert(name.to_owned()) + && let Some(schema) = schemas.get(name) + { + collect_response_schemas(schema, schemas, collected, false); + } + } else { + // It's an allOf mixin. Do NOT blocklist the schema itself. + if let Some(schema) = schemas.get(name) { + if let Some(properties) = &schema.properties { + for nested_property in properties.values() { + collect_response_schemas(nested_property, schemas, collected, false); + } + } + if let Some(items) = &schema.items { + collect_response_schemas(items, schemas, collected, false); + } + if let Some(one_of) = &schema.one_of { + for variant in one_of { + collect_response_schemas(variant, schemas, collected, false); + } + } + if let Some(any_of) = &schema.any_of { + for variant in any_of { + collect_response_schemas(variant, schemas, collected, false); + } + } + + if let Some(all_of_value) = schema.extra.get("allOf") + && let Ok(sequence) = + serde_yaml::from_value::>(all_of_value.clone()) + { + for item in sequence { + collect_response_schemas(&item, schemas, collected, true); + } + } + if let Some(additional_properties_value) = schema.extra.get("additionalProperties") + && let Ok(additional_property) = serde_yaml::from_value::( + additional_properties_value.clone(), + ) + { + collect_response_schemas(&additional_property, schemas, collected, false); + } + } + } + } + + if let Some(properties) = &property.properties { + for nested_property in properties.values() { + collect_response_schemas(nested_property, schemas, collected, false); + } + } + if let Some(items) = &property.items { + collect_response_schemas(items, schemas, collected, false); + } + if let Some(one_of) = &property.one_of { + for variant in one_of { + collect_response_schemas(variant, schemas, collected, false); + } + } + if let Some(any_of) = &property.any_of { + for variant in any_of { + collect_response_schemas(variant, schemas, collected, false); + } + } + + // If we hit `allOf` in a response, flag its targets as mixins (is_mixin = true) + if let Some(all_of_value) = property.extra.get("allOf") + && let Ok(sequence) = serde_yaml::from_value::>(all_of_value.clone()) + { + for item in sequence { + collect_response_schemas(&item, schemas, collected, true); + } + } + if let Some(additional_properties_value) = property.extra.get("additionalProperties") + && let Ok(additional_property) = + serde_yaml::from_value::(additional_properties_value.clone()) + { + collect_response_schemas(&additional_property, schemas, collected, false); + } +} + +// Helper function to recursively check if a schema contains an actual string +pub(crate) fn property_contains_string( + property: &OpenAPIProperty, + schemas: &IndexMap, + visited: &mut std::collections::HashSet, + response_schemas: &std::collections::HashSet, +) -> bool { + let is_enum = property.extra.contains_key("enum"); + let is_uuid = property.extra.get("format").and_then(|v| v.as_str()) == Some("uuid"); + + if property.r#type.as_deref() == Some("string") + && !is_enum + && !is_uuid + && property.r#ref.is_none() + { + return true; + } + + if let Some(reference) = &property.r#ref { + let name = reference.trim_start_matches("#/components/schemas/"); + + // Uses the new override helper + if response_schemas.contains(name) && !is_forced_borrow_model(name) { + return false; + } + + if !visited.contains(name) { + visited.insert(name.to_owned()); + if let Some(schema) = schemas.get(name) + && property_contains_string(schema, schemas, visited, response_schemas) + { + return true; + } + } + } + + if let Some(properties) = &property.properties { + for nested_property in properties.values() { + if property_contains_string(nested_property, schemas, visited, response_schemas) { + return true; + } + } + } + if let Some(items) = &property.items + && property_contains_string(items, schemas, visited, response_schemas) + { + return true; + } + if let Some(one_of) = &property.one_of { + for variant in one_of { + if property_contains_string(variant, schemas, visited, response_schemas) { + return true; + } + } + } + if let Some(any_of) = &property.any_of { + for variant in any_of { + if property_contains_string(variant, schemas, visited, response_schemas) { + return true; + } + } + } + + if let Some(all_of_value) = property.extra.get("allOf") + && let Ok(sequence) = serde_yaml::from_value::>(all_of_value.clone()) + { + for item in sequence { + if property_contains_string(&item, schemas, visited, response_schemas) { + return true; + } + } + } + if let Some(additional_properties_value) = property.extra.get("additionalProperties") + && let Ok(additional_property) = + serde_yaml::from_value::(additional_properties_value.clone()) + && property_contains_string(&additional_property, schemas, visited, response_schemas) + { + return true; + } + + false +} diff --git a/xtask/src/preprocess_openapi.rs b/xtask/src/preprocess_openapi.rs index 38be8302..a44d710c 100644 --- a/xtask/src/preprocess_openapi.rs +++ b/xtask/src/preprocess_openapi.rs @@ -1,9 +1,15 @@ -use ::std::{collections::HashSet, fs}; +use ::std::fs; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_yaml::Value; -use crate::add_vendor_attributes::add_vendor_attributes; +use crate::{ + add_vendor_attributes::add_vendor_attributes, + mark_borrowed_data::{ + collect_request_schemas, collect_response_schemas, is_forced_borrow_model, + property_contains_string, + }, +}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -26,6 +32,10 @@ pub(crate) struct OpenAPI { // Everything else not explicitly listed above #[serde(flatten)] pub(crate) extra: IndexMap, + + // Track schemas created by `unwrap_parameters_by_path` which are not used in any OpenAPI path methods + #[serde(skip)] + pub(crate) orphaned_request_schemas: std::collections::HashSet, } pub(crate) type OpenAPIPath = IndexMap; @@ -202,31 +212,48 @@ pub fn preprocess_openapi_file( } impl OpenAPIProperty { - fn collect_properties(&self) -> Vec { - let mut data = Vec::new(); - if let Some(schema) = &self.r#ref { - data.push( - schema - .trim_start_matches("#/components/schemas/") - .to_owned(), - ); + // Helper to determine if a schema is a structure that requires a <'a> or <'p> generic in Rust + fn is_structural(&self) -> bool { + self.r#type.as_deref() == Some("object") + || self.r#ref.is_some() + || self.one_of.is_some() + || self.any_of.is_some() + || self.extra.contains_key("allOf") + // Only flag arrays if their inner items are structural (ignores arrays of primitive strings) + || (self.r#type.as_deref() == Some("array") && self.items.as_deref().is_some_and(|i| i.is_structural())) + } + + fn mark_borrowed_property_recursive( + &mut self, + schemas: &IndexMap, + response_schemas: &std::collections::HashSet, + ) { + let mut visited = std::collections::HashSet::new(); + if property_contains_string(self, schemas, &mut visited, response_schemas) { + // only flag structures that need a Rust <'a> lifetime e.g. objects, arrays,... + if self.is_structural() { + self.extra + .insert("x-rust-has-lifetime".to_owned(), Value::Bool(true)); + } } - if let Some(p) = &self.items { - data.extend(p.collect_properties()); + + if let Some(properties) = &mut self.properties { + for nested_property in properties.values_mut() { + nested_property.mark_borrowed_property_recursive(schemas, response_schemas); + } } - if let Some(v) = &self.any_of { - v.iter().for_each(|p| data.extend(p.collect_properties())); + if let Some(items) = &mut self.items { + items.mark_borrowed_property_recursive(schemas, response_schemas); } - if let Some(v) = &self.one_of { - v.iter().for_each(|p| data.extend(p.collect_properties())); + if let Some(one_of) = &mut self.one_of { + for variant in one_of.iter_mut() { + variant.mark_borrowed_property_recursive(schemas, response_schemas); + } } - data - } - - fn mark_borrowed_property(&mut self) { - if self.r#type.as_deref() == Some("object") || self.one_of.is_some() { - self.extra - .insert("x-rust-has-borrowed-data".to_owned(), Value::Bool(true)); + if let Some(any_of) = &mut self.any_of { + for variant in any_of.iter_mut() { + variant.mark_borrowed_property_recursive(schemas, response_schemas); + } } } } @@ -235,62 +262,183 @@ impl OpenAPI { fn mark_borrowed_data(&mut self) { println!("Marking borrowed data..."); - let mut request_schemas = HashSet::new(); - self.paths.iter_mut().for_each(|(_, pms)| { - pms.iter_mut().for_each(|(_, pm)| { - if let Some(ps) = &mut pm.parameters { - ps.iter_mut().for_each(|p| { - if let Some(s) = &mut p.schema { - s.mark_borrowed_property(); - request_schemas.extend(s.collect_properties()); + let schemas_ref = self.components.schemas.clone(); + let mut request_schemas = std::collections::HashSet::new(); + let mut response_schemas = std::collections::HashSet::new(); + + // This takes the schemas we remembered during the unwrap phase + // and treats them as if they were found in a live API request. + let forced_orphans = self.orphaned_request_schemas.clone(); + for schema_name in &forced_orphans { + request_schemas.insert(schema_name.clone()); + if let Some(schema) = schemas_ref.get(schema_name) { + // Tracing them ensures any sub-models they use also get Cow + collect_request_schemas(schema, &schemas_ref, &mut request_schemas); + } + } + + // Gather all response schemas + self.paths.iter().for_each(|(_path, operations)| { + operations.iter().for_each(|(_method, operation)| { + if let Some(responses) = &operation.responses { + for response in responses.values() { + if let Some(media_types) = &response.content { + for media_type in media_types.values() { + if let Some(schema) = &media_type.schema { + collect_response_schemas( + schema, + &schemas_ref, + &mut response_schemas, + false, + ); + } + } } - }) + } } + }); + }); - if let Some(reqb) = &mut pm.request_body - && let Some(cs) = &mut reqb.content - { - cs.iter_mut().for_each(|(_, c)| { - if let Some(s) = &mut c.schema { - s.mark_borrowed_property(); - request_schemas.extend(s.collect_properties()); + // Process requests + self.paths.iter_mut().for_each(|(_path, operations)| { + operations.iter_mut().for_each(|(_method, operation)| { + let mut operation_has_borrowed_data = false; + + if let Some(parameters) = &mut operation.parameters { + parameters.iter_mut().for_each(|parameter| { + if let Some(schema) = &mut parameter.schema { + collect_request_schemas(schema, &schemas_ref, &mut request_schemas); + + let mut visited = std::collections::HashSet::new(); + if property_contains_string( + schema, + &schemas_ref, + &mut visited, + &response_schemas, + ) { + schema.mark_borrowed_property_recursive( + &schemas_ref, + &response_schemas, + ); + + // only flag the schema and parameter if it is structural (object/arrays) + if schema.is_structural() { + schema.extra.insert( + "x-rust-has-lifetime".to_owned(), + Value::Bool(true), + ); + parameter.extra.insert( + "x-rust-has-lifetime".to_owned(), + Value::Bool(true), + ); + } + operation_has_borrowed_data = true; + } } }) } + + if let Some(request_body) = &mut operation.request_body { + let mut request_body_has_borrowed_data = false; + if let Some(media_types) = &mut request_body.content { + media_types.iter_mut().for_each(|(_mime, media_type)| { + if let Some(schema) = &mut media_type.schema { + collect_request_schemas(schema, &schemas_ref, &mut request_schemas); + + let mut visited = std::collections::HashSet::new(); + if property_contains_string( + schema, + &schemas_ref, + &mut visited, + &response_schemas, + ) { + schema.mark_borrowed_property_recursive( + &schemas_ref, + &response_schemas, + ); + + if schema.is_structural() { + schema.extra.insert( + "x-rust-has-lifetime".to_owned(), + Value::Bool(true), + ); + request_body_has_borrowed_data = true; + } + } + } + }) + } + if request_body_has_borrowed_data { + request_body + .extra + .insert("x-rust-has-lifetime".to_owned(), Value::Bool(true)); + operation_has_borrowed_data = true; + } + } + + if operation_has_borrowed_data { + operation + .extra + .insert("x-rust-has-lifetime".to_owned(), Value::Bool(true)); + } }) }); - let schemas = self + // Filter request schemas to only those that are not also response schemas, unless they are forced borrow models + request_schemas.retain(|schema_name| { + !response_schemas.contains(schema_name) || is_forced_borrow_model(schema_name) + }); + + let schemas_to_check = self .components .schemas - .iter() - .filter(|(n, _)| n.ends_with("Parameters") || request_schemas.contains(n.as_str())) - .map(|(n, _)| n.to_owned()) + .keys() + .filter(|schema_name| { + is_forced_borrow_model(schema_name) + || request_schemas.contains(schema_name.as_str()) + }) + .cloned() .collect::>(); - drop(request_schemas); - for schema_name in schemas { - let Some(schema) = self.components.schemas.get_mut(&schema_name) else { + // Apply the Cow flag + for schema_name in schemas_to_check { + if response_schemas.contains(&schema_name) && !is_forced_borrow_model(&schema_name) { continue; + } + + let contains_string = { + let Some(schema) = self.components.schemas.get(&schema_name) else { + continue; + }; + let mut visited = std::collections::HashSet::new(); + property_contains_string(schema, &schemas_ref, &mut visited, &response_schemas) }; - schema - .extra - .insert("x-rust-has-borrowed-data".to_owned(), Value::Bool(true)); + if !contains_string { + continue; + } - for (_, prop) in schema.properties.iter_mut().flat_map(|v| v.iter_mut()) { - for inner in prop.one_of.iter_mut().flat_map(|v| v.iter_mut()) { - inner.mark_borrowed_property(); - } - for inner in prop.any_of.iter_mut().flat_map(|v| v.iter_mut()) { - inner.mark_borrowed_property(); - } - if let Some(inner) = &mut prop.items { - inner.mark_borrowed_property(); - } + let Some(schema) = self.components.schemas.get_mut(&schema_name) else { + continue; + }; - prop.mark_borrowed_property(); + // prevent OpenAPI generator from dropping flags on pure $ref aliases + // We wrap pure $refs in an `allOf` so the generator keeps the vendor extensions. + if let Some(r) = schema.r#ref.take() { + let all_of_item = OpenAPIProperty { + r#ref: Some(r), + ..Default::default() + }; + schema.extra.insert( + "allOf".to_owned(), + serde_yaml::to_value(vec![all_of_item]).unwrap(), + ); } + + schema + .extra + .insert("x-rust-has-lifetime".to_owned(), Value::Bool(true)); + schema.mark_borrowed_property_recursive(&schemas_ref, &response_schemas); } } @@ -335,6 +483,9 @@ impl OpenAPI { self.components .schemas .insert(component_name.into(), inline_schema); + // Remember that this schema is an orphaned request schema for the next borrow data marking step + self.orphaned_request_schemas + .insert(component_name.to_owned()); } // --- Step 2: Unwrap the parameter object into individual parameters ---