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

OpenApi docs/specs #11

Open
benblub opened this issue Aug 19, 2022 · 4 comments
Open

OpenApi docs/specs #11

benblub opened this issue Aug 19, 2022 · 4 comments
Labels
enhancement New feature or request

Comments

@benblub
Copy link

benblub commented Aug 19, 2022

The filters are not displayed in the OpenApi docs. I would still find it a useful extension. What do you think?

@metaclass-nl
Copy link
Owner

It would certanily be nice if the options to combine existing filters with and, or and not would be displayed in the OpenApi docs!

I was led to believe that the OpenApi docs only support a flat list of keys that activate the filters and types of the values that can be passed to them. But i must admit, i did not really look into it. So maybe OpenApi supports more and can actually express the combination of the existing filters woth and, or and not in a tree of indefinite depth. If you have an idea about how to do that, please explain!

Or maybe a flat list of a configurable number of layers combined with the specs of each of the existing filters would do? But if there are many filters, wouldn't that lead to a very long list? How to keep that within usable limits?

@yobottehg
Copy link

yobottehg commented Aug 24, 2022

We translate the schema to typescript types using https://www.npmjs.com/package/openapi-typescript. For that purpose a wildcard for any additional "and", "or" and "not" would be sufficient for the beginning. Like that the consuming client knows after the FilterLogic filter possibilities.

Something in this direction : openapi-ts/openapi-typescript@f9229a2#diff-0865c2993ba1a2e26419456a46efc98132e5afdffe4028442d17945ba7c19826R21

For that purpose i think we need to describe the and, or and not as query parameters: https://swagger.io/docs/specification/describing-parameters/

The open api spec in 3.0 at least describes this "additional properties" here:
https://spec.openapis.org/oas/v3.0.3#schema-object

Another solution would be to add "valid" open api exposed filters based on allowed filters on the api resource using FilterLogic.
So we map search filters for title and description like this:

  • "and[or][title]": string
  • "and[or][description]": string
  • "and[not][title]": string
  • "and[not][description]": string
  • "or[title]": string
  • "or[description]": string
  • "or[not][title]": string
  • "or[not][description]": string
  • ...

Would perhaps need to settle on one way how to apply these filters not not allow arbitrary combinations.

@metaclass-nl
Copy link
Owner

Hi,

I do not have the time right now to look into it. Ik hope next week is less busy so that i can take a look.

Thanks for now, Henk.

@metaclass-nl
Copy link
Owner

metaclass-nl commented Sep 10, 2022

Flattening out the combinations of logic and filters, like you do under
"Another solution" would be relatively easy but limiting the logic to those
specified would be harder and goes against the idea of allowing the client
to specify the logic. Something like this is discussed on Filters RFC
and here. But not limiting the logic would necessarily leave most options undocumented. Could still be usefull though because Swagger Ui would understand the part that IS documented.

I do not understand what you mean by a wildcard, a description like
{ [key: string]: unknown }
does not seem valid to me.

Reading swagger.io/docs my best guess would be the following:

parameters: [
	(..),
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			type: "object"
		}
		style: deepObject
		explode: false,
		allowEmptyValue: true
	},
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			type: "object"
		}
		style: deepObject
		explode: false,
		allowEmptyValue: false
	},
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			type: "object"
		}
		style: deepObject
		explode: false,
		allowEmptyValue: false
	},
}

Objects additionalProperties by default is true, but i am not sure type "object" itself would be valid.
Instead one could type and, or and not as "#/components/schemas/LogicalFilters" defined as:

parameters: [
	(..),
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			{ $ref: "#/components/schemas/LogicalFilters" }
		},
		style: deepObject,
		explode: false,
		allowEmptyValue: true
	},
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			{ $ref: "#/components/schemas/LogicalFilters" }
		},
		style: deepObject,
		explode: false,
		allowEmptyValue: false
	},
	{
		name: "and",
		in: "query",
		description: "Combines the nested filter specs through AND"
		required: false,
		schema: {
			{ $ref: "#/components/schemas/LogicalFilters" }
		},
		style: deepObject,
		explode: false,
		allowEmptyValue: false
	},
}
LogicalFilters: {
	type: "object",
	description: "Recursive logical combination with the filter specs as additional properties",
	properties: {
		and: {
			nullable: true,
			description: "Combines the nested filter specs through AND",
			anyOf: [
				{ $ref: "#/components/schemas/LogicalFilters" }
			] 
		},
		or: {
			nullable: true,
			description: "Combines the nested filter specs through OR",
			anyOf: [
				{ $ref: "#/components/schemas/LogicalFilters" }
			] 
		},
		not: {
			nullable: true,
			description: "Negates the nested filter specs",
			anyOf: [
				{ $ref: "#/components/schemas/LogicalFilters" }
			] 
		}	
	}
}

Or one could make the type specific to the entity and its filters. For example the
Employee entity
from MetaClass Tutorial Api Platform only has one filter that reacts to the parameter "search":

Employee.logical-filter: {
	type: "object",
	description: "Recursive logical combination with filter specs"
	properties: {
		and: {
			nullable: true,
			description: "Combines the underlying filter specs through AND",
			anyOf: [
				{ $ref: "#/components/schemas/Employee.logical-filter" } 
			] 
		},
		or: {
			nullable: true,
			description: "Combines the underlying filter specs through OR",
			anyOf: [
				{ $ref: "#/components/schemas/Employee.logical-filter" }
			] 
		},
		not: {
			nullable: true,
			description: "Negates the underlying filter specs",
			anyOf: [
				{ $ref: "#/components/schemas/Employee.logical-filter" }
			] 
		},
		search: {
			nullable: true,
			description: "Selects entities where each search term is found somewhere in at least one of the specified properties",
			type: "string",
		}
	}
}

But i am not sure these are valid docs and even then they do not cover multiple criteria for the same property like this:

/offers/?and[price]=10&and[][description]=shirt&and[][description]=cotton

I would not know how to document this with openapi.

@metaclass-nl metaclass-nl added the enhancement New feature or request label Oct 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants