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

Flesh out options examples in the readme with title, description, etc #98

Closed
wants to merge 1 commit into from

Conversation

rattrayalex
Copy link

#9 (comment)

I had searched for "title", "description", "document", and "nullable" in search of how to add annotations.
Many JSON Schema users use it for OpenAPI, which has the nullable property that isn't in JSON Schema, and may be curious how to use it. They may also wish to know whether extensions like x-mycompany-myattribute work.

sinclairzx81#9 (comment)

I had searched for "title", "description", "document", and "nullable" in search of how to add annotations.  
Many JSON Schema users use it for OpenAPI, which has the `nullable` property that isn't in JSON Schema, and may be curious how to use it. They may also wish to know whether extensions like `x-mycompany-myattribute` work.
@rattrayalex rattrayalex mentioned this pull request Aug 11, 2021
@sinclairzx81
Copy link
Owner

@rattrayalex Hi, sorry for the delay in response on this PR. Thanks for the submission, these are really appreciated.

Yeah, additional information on OpenAPI might be good to add to the readme. I'm kinda wondering if giving OpenAPI its own section in the readme might help with discovery / quick reference. How would you feel about setting up this information between Strict and Validation sections and include a little bit of information on OpenAPI usage?

Out of curiosity, does OpenAPI support nullable through anyOf / union ? TypeBox can represent nullable in a JSON schema centric way using Type.Union([Type.Null(), Type.String()]). I don't follow the OpenAPI specification very closely, so curious about this aspect (and more so if TypeBox should provide better support for this)

Let me know your thoughts
Cheers
S

@rattrayalex
Copy link
Author

rattrayalex commented Aug 14, 2021

Yeah, given that TypeBox already supports a few reasonable nonstandard things (like functions and promises), adding support for openapi's nullable feature would make a lot of sense - otherwise folks would have to fork or awkwardly extend TypeBox to use it with openapi.

Could this work?

const T = Type.String({nullable: true})
Static<typeof T> // string | null
Type.Strict(T) // { type: 'string', nullable: true }

It would not be good to use anyOf/null in the output since openapi doesn't support it (as you may recall).

You may also want a Type.Maybe(x) or something to alias to Type.AnyOf(x, Type.Null) as a convenience for non-openapi users.

@sinclairzx81
Copy link
Owner

@rattrayalex Hi. You raise a good point on the non standard functions provided by TypeBox. These are actually due for an update and have been mulling the idea of expressing these inside JSON schema constraints.

So for example.

const T0 = Type.String()
const T1 = Type.Number()
const R = Type.Boolean()
const F = Type.Function([T0, T1], R)

Is currently expressed as...

const F = {
    type: 'function',
    kind: Symbol(FunctionKind),
    arguments: [T0, T1],
    returns: R
}

...but could be expressed as

const F = {
    type: 'object',
    kind: Symbol(FunctionKind),
    properties: {
        type: {
            const: 'function' 
            type: 'string'
        },
        arguments: {
            type: 'arrays',
            items: [T0, T1],
            minLength: 2,
            maxLength: 2
        },
        returns: R
    }
}

I plan to review some of this the next time I'm able to sit down with TypeBox.

As for Type.String({ nullable: true }) I'm fairly happy with the current design of TypeBox here as it permits unknown schema options (such as nullable) while providing type hints specifically for options in the JSON schema standard.

For Type.Maybe({ ... }), TypeBox can't reasonably implement this as part of the core as it would be moving away from both JSON schema and TypeScript. Note that Maybe is more a functional pattern in TypeScript / JavaScript than a language feature (so wouldn't fit into the extended subset provided by TypeBox which tries to align specifically language constructs), and wouldn't fit into JSON schema either (as Maybe can be reasonably expressed with anyOf as you noted). Also, I am guessing there is a high potential for other disparities between JSON schema and OpenAPI. It's really unfortunate that the OpenAPI specification diverges from JSON schema.

In terms of documentation tho, I would be interested in documenting some of the differences, and potentially working towards providing some mechanism to augment TypeBox to support Open API outside TypeBox itself. But first really need the perspective of a OpenAPI user (I don't use OpenAPI personally, so I'm not really the best person to gauge expectations).

This said, It is actually possible to extend TypeBox types, and you can use it's internal types to new forms of schema that can be statically resolved. See example below (and playground link here)

// ------------------------------------------------------
// Extended Type Builder
// ------------------------------------------------------

import { TypeBuilder, TSchema, TNull, TUnion, Static } from '@sinclair/typebox'

export class OpenAPITypeBuilder extends TypeBuilder {
    
    public Maybe<T extends TSchema>(schema: T): TUnion<[TNull, T]> {
        return { /* add schema for maybe here */ } as unknown as TUnion<[TNull, T]>
    }
}

export const Type = new OpenAPITypeBuilder()

// ------------------------------------------------------
// Implementation
// ------------------------------------------------------

const T = Type.Maybe(Type.String())

type T = Static<typeof T>

Possibly documentation on extending TypeBox in this way could sit well with a Open API section (or perhaps a Extending TypeBox section using OpenAPI as a reference implementation)

Let me know your thoughts! :)
Thanks Again
S

@sinclairzx81
Copy link
Owner

@rattrayalex Hey, just had a quick look around for information on the OpenAPI differences to JSONSchema. Looks like they had been making some moves towards aligning on JSON schema 2019-09 draft. This PR from 2019 OAI/OpenAPI-Specification#1977 seems to suggest things, and I've read a couple of bit of information that nullable may be deprecated in later releases.

OpenAPI do advertise they use an extended subset of JSON schema, so this has somewhat sparked my interest into exactly what that extended subset is. And in particular looking into providing documentation around augmenting the TypeBox TypeBuilder (as above) to support that extended subset.

I may do some additional reading on this over the week.

@sinclairzx81
Copy link
Owner

@rattrayalex Heya. I've gone ahead and added a OpenAPI section to the readme that includes information on dealing with OpenAPI's nullable types which you can read about here https://github.com/sinclairzx81/typebox#openapi

As for the title, description and other known properties, these are already specified on the existing CustomOptions interface here, so users should discover these properties in intellisense when attempting to define them. Note that they only specify known JSON schema options but still permit passing additional unknown options (such as nullable). This is briefly mentioned in the OpenAPI section.

Also, I've held off providing specific documentation for extending TypeBuilder as I have some additional thoughts around this which may implicate TypeBuilder in later releases.

Will close off this PR. But thanks for the submission.
Regards
S

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants