openapi-contrib / openapi-schema-to-json-schema

Due to the OpenAPI v3.0 and JSON Schema discrepancy, you can use this JS library to convert OpenAPI Schema objects to proper JSON Schema.
https://www.npmjs.com/package/@openapi-contrib/openapi-schema-to-json-schema
MIT License
242 stars 20 forks source link

version 4.0 - what happened to toJsonSchema #58

Closed steve-baldwin closed 1 year ago

steve-baldwin commented 1 year ago

Maybe a silly question but from what I can tell, this library is quite different with version 4. The examples in the docs don't seem to work any more:

[~/git/unsullied] yarn ts-node
yarn run v1.22.19
$ /Users/stbaldwin/git/unsullied/node_modules/.bin/ts-node
> var toJsonSchema = require("@openapi-contrib/openapi-schema-to-json-schema");
undefined
>
undefined
> var schema = {
...   type: "string",
...   format: "date-time",
...   nullable: true,
... };
undefined
>
undefined
> var convertedSchema = toJsonSchema(schema);
/Users/stbaldwin/git/unsullied/<repl>.ts:1
var convertedSchema = toJsonSchema(schema);
                      ^

Uncaught TypeError: toJsonSchema is not a function
    at /Users/stbaldwin/git/unsullied/<repl>.ts:1:23
    at Script.runInThisContext (node:vm:129:12)
    at runInContext (/Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:673:19)
    at Object.execCommand (/Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:639:28)
    at /Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:661:47
    at Array.reduce (<anonymous>)
    at appendCompileAndEvalInput (/Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:661:23)
    at evalCodeInternal (/Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:222:12)
    at REPLServer.nodeEval (/Users/stbaldwin/git/unsullied/node_modules/ts-node/src/repl.ts:244:26)
    at bound (node:domain:433:15)
>

Do you have any docs to help users of 3.x upgrade?

jonluca commented 1 year ago

Apologies, didn't update the docs, there's now a named export, and a named default export.

If you change var toJsonSchema = require("@openapi-contrib/openapi-schema-to-json-schema"); to var { openapiSchemaToJsonSchema: toJsonSchema } = require("@openapi-contrib/openapi-schema-to-json-schema"); it should work. I'll update the docs later today

steve-baldwin commented 1 year ago

Thank you for such a quick response. I should have tried a bit harder first 😊 . I've found I can now do this to minimise impact and create a compile time import:

import { openapiSchemaToJsonSchema as toJsonSchema } from '@openapi-contrib/openapi-schema-to-json-schema';

var schema = {
  type: "string",
  format: "date-time",
  nullable: true,
};

var convertedSchema = toJsonSchema(schema);

console.log(convertedSchema);

Steve

steve-baldwin commented 1 year ago

Sorry to be a pain but I think there are still issues. After upgrading to 4.0.0 and fixing my usage as above, I'm getting compilation errors coming out of the library:

[~/git/unsullied] yarn tsc:check
yarn run v1.22.19
$ tsc --noEmit
node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/index.d.ts:3:54 - error TS2307: Cannot find module 'openapi-typescript/src/types' or its corresponding type declarations.

3 import type { ParameterObject, ResponseObject } from "openapi-typescript/src/types";
                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types.d.ts:2:31 - error TS2307: Cannot find module 'openapi-typescript' or its corresponding type declarations.

2 import type { OpenAPI3 } from "openapi-typescript";
                                ~~~~~~~~~~~~~~~~~~~~

node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types.d.ts:3:35 - error TS2307: Cannot find module 'openapi-typescript/src/types' or its corresponding type declarations.

3 import type { SchemaObject } from "openapi-typescript/src/types";
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types.d.ts:4:38 - error TS2307: Cannot find module 'openapi-typescript/src/types' or its corresponding type declarations.

4 import type { ReferenceObject } from "openapi-typescript/src/types";
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Found 4 errors in 2 files.

Is there something else I need to install?

jonluca commented 1 year ago

You're right, the dependency is in devDeps right now. https://github.com/openapi-contrib/openapi-schema-to-json-schema/pull/59 should fix it

Released v4.0.1

steve-baldwin commented 1 year ago

I think there may be a few more dependencies missing. I created a new tiny project:

[~/git/t-openapi] cat package.json
{
  "name": "t-openapi",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@openapi-contrib/openapi-schema-to-json-schema": "^4.0.1",
    "typescript": "^5.0.3"
  }
}

and a simple test typescript file:

[~/git/t-openapi] cat t.ts
import { openapiSchemaToJsonSchema } from '@openapi-contrib/openapi-schema-to-json-schema';

const schema = {
  type: "string",
  format: "date-time",
  nullable: true,
};

const converted = openapiSchemaToJsonSchema(schema, { dateToDateTime: true });

Compiling not only complains about library but also about the argument to openapiSchemaToJsonSchema:

[~/git/t-openapi] yarn tsc --noEmit t.ts
yarn run v1.22.19
$ /Users/stbaldwin/git/t-openapi/node_modules/.bin/tsc --noEmit t.ts
node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/index.d.ts:2:34 - error TS2307: Cannot find module 'json-schema' or its corresponding type declarations.

2 import type { JSONSchema4 } from "json-schema";
                                   ~~~~~~~~~~~~~

node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types.d.ts:5:34 - error TS2307: Cannot find module 'json-schema' or its corresponding type declarations.

5 import type { JSONSchema4 } from "json-schema";
                                   ~~~~~~~~~~~~~

node_modules/openapi-typescript/dist/index.d.ts:1:23 - error TS2688: Cannot find type definition file for 'node'.

1 /// <reference types="node" />
                        ~~~~

node_modules/openapi-typescript/dist/index.d.ts:2:23 - error TS2688: Cannot find type definition file for 'node'.

2 /// <reference types="node" />
                        ~~~~

node_modules/openapi-typescript/dist/index.d.ts:4:26 - error TS2307: Cannot find module 'stream' or its corresponding type declarations.

4 import { Readable } from "stream";
                           ~~~~~~~~

node_modules/openapi-typescript/dist/index.d.ts:5:21 - error TS2307: Cannot find module 'url' or its corresponding type declarations.

5 import { URL } from "url";
                      ~~~~~

node_modules/openapi-typescript/dist/types.d.ts:1:23 - error TS2688: Cannot find type definition file for 'node'.

1 /// <reference types="node" />
                        ~~~~

node_modules/openapi-typescript/dist/types.d.ts:2:26 - error TS2307: Cannot find module 'url' or its corresponding type declarations.

2 import type { URL } from "url";
                           ~~~~~

node_modules/openapi-typescript/src/types.ts:1:26 - error TS2307: Cannot find module 'url' or its corresponding type declarations.

1 import type { URL } from "url";
                           ~~~~~

t.ts:9:45 - error TS2345: Argument of type '{ type: string; format: string; nullable: boolean; }' is not assignable to parameter of type 'OpenAPI3'.
  Property 'openapi' is missing in type '{ type: string; format: string; nullable: boolean; }' but required in type 'OpenAPI3'.

9 const converted = openapiSchemaToJsonSchema(schema, { dateToDateTime: true });
                                              ~~~~~~

  node_modules/openapi-typescript/dist/types.d.ts:11:5
    11     openapi: string;
           ~~~~~~~
    'openapi' is declared here.

Found 10 errors in 6 files.

Errors  Files
     1  node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/index.d.ts:2
     1  node_modules/@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types.d.ts:5
     4  node_modules/openapi-typescript/dist/index.d.ts:1
     2  node_modules/openapi-typescript/dist/types.d.ts:1
     1  node_modules/openapi-typescript/src/types.ts:1
     1  t.ts:9
error Command failed with exit code 2.
jonluca commented 1 year ago

The openapi-typescript library does have some weirdness to it - I think there are some type issues with it in prod, actually.

I opened an issue with them last week https://github.com/drwpow/openapi-typescript/issues/1058

With the example you linked above, it looks like it's missing the node type defs and json-schema, though - I'll add those now. Thanks for the fast followup, let's see if 4.0.2 fixes it.

For your example, you will need to cast schema on line 9 to be a valid openapi type though.

I've been looking into migrating away from openapi-typescript, open to suggestions

steve-baldwin commented 1 year ago

Not sure if this is correct but this is what I ended up with for my small test:

[~/git/t-openapi] cat package.json
{
  "name": "t-openapi",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@openapi-contrib/openapi-schema-to-json-schema": "^4.0.1",
    "openapi-typescript": "^6.2.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.0.3"
  },
  "dependencies": {}
}

It seems I needed to explicitly add openapi-typescript for some reason or it doesn't compile. I had to modify my script to:

import { openapiSchemaToJsonSchema } from "@openapi-contrib/openapi-schema-to-json-schema";

const schema = {
  openapi: "something",
  components: {
    schemas: {
      schemaOne: {
        type: "string",
        format: "date-time",
        nullable: true,
      },
    },
  },
};

const converted = openapiSchemaToJsonSchema(schema, { dateToDateTime: true });
console.log(converted);

It now compiles and runs:

[~/git/t-openapi] yarn tsc --noEmit t.ts
yarn run v1.22.19
$ /Users/stbaldwin/git/t-openapi/node_modules/.bin/tsc --noEmit t.ts
✨  Done in 1.24s.
[~/git/t-openapi] yarn ts-node t.ts
yarn run v1.22.19
$ /Users/stbaldwin/git/t-openapi/node_modules/.bin/ts-node t.ts
{
  openapi: 'something',
  components: { schemas: { schemaOne: [Object] } },
  '$schema': 'http://json-schema.org/draft-04/schema#'
}
✨  Done in 0.53s.

If this is what we need to do, it's going to be a bigger lift to upgrade. I realise that's what often happens with major version upgrades, but it may take us a little while before we can get there.

Maybe I've done something wrong. If so, is there any chance of you upgrading the docs to give an example that compiles and runs?

steve-baldwin commented 1 year ago

Oops, that was an old package.json. I had actually upgraded to 4.0.2 but everything else should be ok (I think).

jonluca commented 1 year ago

So with 4.0 we tried to make it a bit more type safe. 4.0.2 should now include openapi-typescript in its dependencies, so you shouldn't need to add it explicitly.

I think the only changes to migrate from 3.x to 4.x should be:

import { openapiSchemaToJsonSchema } from "@openapi-contrib/openapi-schema-to-json-schema";
import type { OpenAPI3 } from "openapi-typescript";

const schema = {
  components: {
    schemas: {
      schemaOne: {
        type: "string",
        format: "date-time",
        nullable: true,
      },
    },
  },
};

const converted = openapiSchemaToJsonSchema(schema as unknown as OpenAPI3, { dateToDateTime: true });
console.log(converted);

You can see that in the old version it was very loosely typed, as just a pretty generic Record.

https://github.com/openapi-contrib/openapi-schema-to-json-schema/blob/9ba0084695ae3dae5f3e19ac7a173e6703ad9f1c/index.d.ts#L29

steve-baldwin commented 1 year ago

That was really helpful. I've now converted all instances of our code using your library to 4.0.2 and everything is working !!

Thank you so much for your patience and responsiveness.

am-burban commented 1 year ago

@jonluca The problem with the current typing is that it only accepts a complete OpenAPI document. Whereas even in the documentation it says you can pass in a single schema: https://github.com/openapi-contrib/openapi-schema-to-json-schema#converting-openapi-schema

The correct type is probably SchemaObject from openapi-typescript in addition to OpenAPI3.

jonluca commented 1 year ago

That's fair, I'll make it more general again - https://github.com/openapi-contrib/openapi-schema-to-json-schema/pull/61