Giter VIP home page Giter VIP logo

dtsgenerator's People

Contributors

anttiviljami avatar brian-kavanagh avatar davidbiesack avatar deej-io avatar denizkenan avatar dependabot[bot] avatar dmiorandi avatar eostrom avatar gasi avatar glen-84 avatar gongt avatar greenkeeper[bot] avatar greenkeeperio-bot avatar heapx avatar horiuchi avatar jdthorpe avatar laurelnaiad avatar maapteh avatar mcollina avatar medfreeman avatar nateeag avatar nfroidure avatar philliphoff avatar ricokahler avatar sakari avatar silesky avatar skuligowski avatar vincentlin02 avatar wszydlak avatar zregvart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dtsgenerator's Issues

$ref across multiple files

I've got a couple of files. Each file is a schema, but there are references to schema in another files.
I expect that if all files are on input togheter than generator can resolve cross references, but it seem doesn't work. It doesn't care about files/dependency order.
Is it supported? If not any idea to achieve this?.

These are two example files:

{
     "id" :"ApiBaseObject",
     "$schema": "http://json-schema.org/draft-03/schema",
     "type": "object",
     "description": "ApiBaseObject of a record",
     "properties":   {
        "first" : {"type" : "string"}
      }
}
{
     "id" :"ApiMetadata",
     "$schema": "http://json-schema.org/draft-03/schema",
     "type": "object",
     "description": "Metadata of a record",
     "properties":   {
        "serverOperation" : {
            "type" : "string",
            "enum" : ["I","U","D"],
            "javaEnumNames" : ["INSERT","UPDATE","DELETE"]
        },
        "test" : {"$ref" : "ApiBaseObject" }
      }
}

Single quote option

Hello,

is it possible to generate source files which use single quotes instead of double quotes? This would be nice to have to have the generated code uniform with the written code.

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.

Since we did not receive a CI status on the greenkeeper/initial branch, we assume that you still need to configure it.

If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you don’t want it to run on every branch, you can whitelist branches starting with greenkeeper/.

We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

Error: id not found

Testing against the JSONAPI schema, I received the bug below against version 0.4.0.

To recreate, run this command: curl jsonapi.org/schema | dtsgen

{ '$schema': 'http://json-schema.org/draft-04/schema#',
  title: 'JSON API Schema',
  description: 'This is a schema for responses in the JSON API format. For more, see http://jsonapi.org',
  oneOf: 
   [ { '$ref': '#/definitions/success' },
     { '$ref': '#/definitions/failure' },
     { '$ref': '#/definitions/info' } ],
  definitions: 
   { success: 
      { type: 'object',
        required: [Object],
        properties: [Object],
        additionalProperties: false },
     failure: 
      { type: 'object',
        required: [Object],
        properties: [Object],
        additionalProperties: false },
     info: 
      { type: 'object',
        required: [Object],
        properties: [Object],
        additionalProperties: false },
     meta: 
      { description: 'Non-standard meta-information that can not be represented as an attribute or relationship.',
        type: 'object',
        additionalProperties: true },
     data: 
      { description: 'The document\'s "primary data" is a representation of the resource or collection of resources targeted by a request.',
        oneOf: [Object] },
     resource: 
      { description: '"Resource objects" appear in a JSON API document to represent resources.',
        type: 'object',
        required: [Object],
        properties: [Object],
        additionalProperties: false },
     links: 
      { description: 'A resource object **MAY** contain references to other resource objects ("relationships"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource\'s links object.',
        type: 'object',
        properties: [Object],
        additionalProperties: true },
     link: 
      { description: 'A link **MUST** be represented as either: a string containing the link\'s URL or a link object.',
        oneOf: [Object] },
     attributes: 
      { description: 'Members of the attributes object ("attributes") represent information about the resource object in which it\'s defined.',
        type: 'object',
        patternProperties: [Object],
        additionalProperties: false },
     relationships: 
      { description: 'Members of the relationships object ("relationships") represent references from the resource object in which it\'s defined to other resource objects.',
        type: 'object',
        patternProperties: [Object],
        additionalProperties: false },
     relationshipToOne: 
      { description: 'References to other resource objects in a to-one ("relationship"). Relationships can be specified by including a member in a resource\'s links object.',
        anyOf: [Object] },
     relationshipToMany: 
      { description: 'An array of objects each containing "type" and "id" members for to-many relationships.',
        type: 'array',
        items: [Object],
        uniqueItems: true },
     empty: 
      { description: 'Describes an empty to-one relationship.',
        type: 'null' },
     linkage: 
      { description: 'The "type" and "id" to non-empty members.',
        type: 'object',
        required: [Object],
        properties: [Object],
        additionalProperties: false },
     pagination: { type: 'object', properties: [Object] },
     jsonapi: 
      { description: 'An object describing the server\'s implementation',
        type: 'object',
        properties: [Object],
        additionalProperties: false },
     error: 
      { type: 'object',
        properties: [Object],
        additionalProperties: false } } }
/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/generator.js:11
            throw new Error('id is not found.');
            ^

Error: id is not found.
    at new Generator (/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/generator.js:11:19)
    at Function.Generator.add (/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/generator.js:50:17)
    at /home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/index.js:12:20
    at Array.forEach (native)
    at dtsgenerator (/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/index.js:11:13)
    at processGenerate (/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/cli.js:62:18)
    at Socket.<anonymous> (/home/ianks/.nvm/versions/node/v5.8.0/lib/node_modules/dtsgenerator/src/cli.js:40:9)
    at emitNone (events.js:85:20)
    at Socket.emit (events.js:179:7)
    at endReadableNT (_stream_readable.js:913:12)

v0.9.3 does not contain transpiled JS files

When using the package at version 0.9.3, we get a Error: Cannot find module '../src/cli' error. This is because cli.ts is present, but not cli.js.

Was the package pushed prior to transpilation?

Can we choose whether to use namespace by command option?

I don't need namespaces because:

  1. making this output as auto-generated single file
  2. importing expressly interfaces to use in each component and services of Angular.
  3. typing less

So, I want to get a file composing only export interface by command option.

P.S.
How do we use --header option? I guess that use for comment. But I can't have confidence in that.

TypeError: example.split is not a function

When the schema contains non-string examples, the generator crashes with error:

TypeError: example.split is not a function

example schema:

{
  "modelYear": {
    "type": "string",
    "example": 2013
  }
}

`allOf` pushes "extended" schema properties into "base" schema

Under the right circumstances, using allOf in a "derived" schema to inherit properties of a "base" schema will result in that base schema interface being emitted with the same properties as the derived schema interface.

Those circumstances are:

  • When the extended schema does not have a properties property (e.g. it only inherits properties but does not define its own).
  • When the extended schema ID sorts lower than the base schema IDs.

The issue is due to utils.mergeSchema(), where it uses the base schema properties array if the extended schema does not have its own, meaning that two schemas are now sharing the same array. When properties (of other base schemas) are later merged into that array, those properties are now reflected in that original base schema.

Here is a test that exposes the issue:

    it ('should include allOf schemas', async () => {
        const baseSchema: JsonSchemaOrg.Schema = {
            id: 'http://test/zzz/allOf/base',
            type: 'object',
            properties: {
                id: {
                    type: 'string',
                },
            },
            required: ['id'],
        };
        const extendedSchema: JsonSchemaOrg.Schema = {
            id: 'http://test/zzz/allOf/extended',
            type: 'object',
            allOf: [
                { $ref: '/zzz/allOf/base' },
            ],
            properties: {
                value: {
                    type: 'number',
                },
            },
            required: ['value'],
        };
        const separateSchema: JsonSchemaOrg.Schema = {
            id: 'http://test/separate',
            type: 'object',
            properties: {
                message: {
                    type: 'string',
                },
            },
            required: ['message'],
        };
        const combinedSchema: JsonSchemaOrg.Schema = {
            id: 'http://test/combined',
            type: 'object',
            allOf: [
                { $ref: '/zzz/allOf/base' },
                { $ref: '/zzz/allOf/extended' },
                { $ref: '/separate' },
            ],
        };

        const result = await dtsgenerator([baseSchema, extendedSchema, separateSchema, combinedSchema]);

        const expected = `declare namespace Test {
    export interface Combined {
        id: string;
        value: number;
        message: string;
    }
    export interface Separate {
        message: string;
    }
    namespace Zzz {
        namespace AllOf {
            export interface Base {
                id: string;
            }
            export interface Extended {
                value: number;
                id: string;
            }
        }
    }
}
`;
        assert.equal(result, expected, result);
    });

Here is the result of that test:

      + expected - actual

           namespace Zzz {
               namespace AllOf {
                   export interface Base {
                       id: string;
      -                value: number;
      -                message: string;
                   }
                   export interface Extended {
                       value: number;
                       id: string;
      -                message: string;
                   }
               }
           }
       }

Support for actual enums

Would be great to be able to generate actual enums.

Right now, we get:

interface Foo {
  status: 'ended' | 'active' | 'paused';
}

But would be awesome to get:

enum FooStatus {
  'ended' = 'ended',
  'active' = 'active',
  'paused' = 'paused',
}

interface Foo {
  status: FooStatus;
}

And would be even more awesome, if it was possible to filter it before output, so that it can be (optionally) corrected to:

enum FooStatus {
  'ENDED' = 'ended',
  'ACTIVE' = 'active',
  'PAUSED' = 'paused',
}

Thanks!

Support for property name amendment

It'd be great to be able to filter the property names and rename them too.

Our API returns snake_case property names, but JS/TS world is mostly operating in camelCase.

I'd like to be able to convert these before output.

Thanks.

Can't resolve remote schemas correctly

I tried to run npx dtsgenerator --url https://storage.googleapis.com/cognitedata-api-docs/openapi.0.5.json and it failed with Error: The $ref targets root is not found: https://storage.googleapis.com/cognitedata-api-docs/api-acls-0.8.4s.json#/components/schemas/cogniteCapability.

I also ran Swagger-CLI: npx swagger-cli validate https://storage.googleapis.com/cognitedata-api-docs/openapi.0.5.json which stated that the spec is valid.

Error: id is not found

dtsgen won't work since upgrading to typescript 1.7:

dtsgen --out dist/common/schemas.d.ts common/models/**/*.json

{ name: 'auditLog',
  base: 'PersistedModel',
  strict: false,
  idInjection: true,
  options: { validateUpsert: true },
  uiOptions: { editable: false },
  type: 'object',
  properties:
   { date: { type: 'date', required: true },
     userId: { type: 'number', required: false },
     request: { type: 'object', properties: [Object] } },
  validations: [],
  relations: {},
  acls: [],
  methods: [] }
/usr/local/lib/node_modules/dtsgenerator/node_modules/asyncblock/lib/flow_fiber.js:26
        this._fiber.run(task);
                    ^
Error: id is not found.
    at new Generator (/usr/local/lib/node_modules/dtsgenerator/lib/generator.js:11:19)
    at Function.Generator.add (/usr/local/lib/node_modules/dtsgenerator/lib/generator.js:51:17)
    at /usr/local/lib/node_modules/dtsgenerator/lib/index.js:13:20
    at Array.forEach (native)
    at dtsgenerator (/usr/local/lib/node_modules/dtsgenerator/lib/index.js:12:13)
    at /usr/local/lib/node_modules/dtsgenerator/lib/cli.js:25:22
    at fiberContents (/usr/local/lib/node_modules/dtsgenerator/node_modules/asyncblock/lib/asyncblock.js:112:26)
=== Pre-asyncblock stack ===
Error
    at module.exports (/usr/local/lib/node_modules/dtsgenerator/node_modules/asyncblock/lib/asyncblock.js:34:15)
    at processGenerate (/usr/local/lib/node_modules/dtsgenerator/lib/cli.js:19:5)
    at Object.<anonymous> (/usr/local/lib/node_modules/dtsgenerator/lib/cli.js:16:5)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/usr/local/lib/node_modules/dtsgenerator/bin/dtsgen:3:1)

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml
  • The new Node.js version is in-range for the engines in 1 of your package.json files, so that was left alone

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Question: json-schema to typescript or typescript to json-jschema

Hi,

I'm new to typescript and json-schema and I would like to know which one is the more complete. I want to use the most complete one as base in order to generate the other one. At first glance I would think json-schema is more complete and polyvalent than typescript.

Could someone confirm this?

An idea: it would be great to be able to be bidirectionnal.

Thanks for your response and for your work on this project.

Question: do you mind if we add support to ignore filename extensions in the generated type names?

Question: do you mind if we add support to ignore filename extensions in the generated type names?

We'd like to ignore filename extensions in the generated type names, as the extensions we use for our schema files add noise to the generated types.

Would you be happy with this change if I raised a PR? If so, what strategy would you like me to take? As the references are meant to be URIs (or part thereof) I take it this change may not make sense for all use-cases.

  1. Change existing behaviour (which could break existing code) - major change
  2. Introduce a new strategy for naming based on a command line option (defaulting to existing behaviour) - minor change

Related tests

https://github.com/horiuchi/dtsgenerator/blob/master/test/schemaid_test.ts#L26

For exampe: http://x.y.z/rootschema.json => XYZ.RootschemaJson

test(new SchemaId('http://x.y.z/rootschema.json#', []), 'http://x.y.z/rootschema.json#', true, 'http://x.y.z/rootschema.json#', false, [], ['XYZ', 'RootschemaJson']);

Background

We're using JSON Schema to describe payloads (e.g., request/response/stream bodies) across our messaging oriented middleware. We make use of some tools, like jsonschema2pojo, to generate DTOs in Java. We hope to use this library to do the same for TypeScript.

Our existing DTOs sometimes contain relative references to other schemas, e.g., RatesRequest.dto.yaml may contain a reference "$ref": "CurrencyPair.dto.yaml". We also generate service clients etc. from other yaml files. We use the extension of the file to differentiate the different declarations, e.g., services are described in *.service.yaml files.

Support for maxItems on tuples

I have looked at a few different ways to work with json-schema in TypeScript, and dtsgenerator seems to be the closest to what I am looking for, and produces nicely formatted and structured typescript definitions. The issue I have is with tuples, for example:

{
    "$id": "https://example.com/test.json",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "array",
    "minItems": 2,
    "maxItems": 2,
    "items": [
        {"type": "number"},
        {"type": "string"}
    ]
}

This generates:

declare namespace ExampleCom {
    export type TestJson = [number, string] | [number, string, any];
}

Which is too permissive, what I really want is:

declare namespace ExampleCom {
    export type TestJson = [number, string];
}

Could dtsgenerator be extended to support maxItems for this use case, or is there another way to achieve what I want?

Error when not using --url

Using the --url flag to fetch the JSON, the cli works. Specifying a local file, does not.

$ DEBUG=dtsgen dtsgen res.json --out types.d.ts
  dtsgen parse schema: schemaId=[undefined], url=[undefined]. +0ms
  dtsgen generate d.ts. +4ms
  dtsgen resolve reference: reference schema count=0. +3ms
  dtsgen TypeId list: +1ms
  dtsgen SchemaId list: +0ms
  dtsgen Reference list: +0ms
Error: There is no id in the input schema(s)
    at JsonSchemaParser.createHierarchicalMap (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\src\jsonSchemaParser.js:299:23)
    at JsonSchemaParser._callee$ (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\src\jsonSchemaParser.js:278:44)
    at tryCatch (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\node_modules\regenerator-runtime\runtime.js:64:40)
    at Generator.invoke [as _invoke] (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\node_modules\regenerator-runtime\runtime.js:299:22)
    at Generator.prototype.(anonymous function) [as next] (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\node_modules\regenerator-runtime\runtime.js:116:21)
    at fulfilled (C:\Users\wie\AppData\Roaming\npm\node_modules\dtsgenerator\src\jsonSchemaParser.js:15:32)

Can't install

Hi,
I'm on windows with npm 3.5.3 and node 4.2.5 but I can't install this package I have the following error:

npm ERR! [email protected] install: 'node build.js || nodejs build.js'
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script 'node build.js || nodejs build.js'.

Error: id is not found.

If I run:
dtsgen --out types.d.ts src/Schema.json

I get the message "Error: id is not found.". What does it mean?

$ref not generating correct types?

(dtsgenerator 0.7.1)
Using the id referencing technique you outlined in #10 the following schema produces duplicate/confusing TS definitions. I've tried a variety of different ways to $ref the types but no success. My goal is to spit out a .d.ts that contains 3 interface definitions, one each for Batch, Transaction, and Line respectively. What I get instead is output that blends/duplicates portions of the top level and has self-referencing properties. Do I have something wrong in my format or is this a bug with $ref handling?

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "NetSuite Invoice JSON Schema",
  "description": "This JSON Schema represents the Invoice object payload that will be passed to NetSuite from Acumatica.",
  "id": "/Batch",
  "type": "object",
  "properties": {
    "invProcessedAmt": {
      "title": "Invoice Processed Amount",
      "description": "The total currency amount of Invoices to processed.",
      "type": "number"
    },
    "invProcessedCount": {
      "title": "Invoice Processed Amount",
      "description": "The total quantities Invoices to processed.",
      "type": "number"
    },
    "cmProcessedAmt": {
      "title": "Credit Memo Processed Amount",
      "description": "The total currency amount of Credit Memos to be processed.",
      "type": "number"
    },
    "cmProcessedCount": {
      "title": "Credit Memo Processed Amount",
      "description": "The total currency amount of Credit Memos to be processed.",
      "type": "number"
    },
    "correlationid": {
      "type": "string"
    },
    "data": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "/Transaction#"
      }
    },
    "Documents": {
      "title": "Document List",
      "description": "This is list of remotely stored electronic documents related to Invoices and Credit Memos. ",
      "type": "array",
      "minItems": 1,
      "maxItems": 3,
      "uniqueItems": true,
      "items": [
        {
          "title": "Documents",
          "description": "This is an object that contains properties related to Invoice and Credit Memo documents stored remotely.",
          "type": "object",
          "properties": {
            "fileName": {
              "title": "File Name",
              "description": "This is the name of the Invoice or Credit Memo file.",
              "type": "string"
            },
            "fileId": {
              "title": "File Id",
              "description": "This is the GUID of the file.",
              "type": "string"
            },
            "docType": {
              "title": "Doc Type",
              "description": "This is the electronic document type.",
              "type": "string",
              "enum": [
                "Summary",
                "Detail"
              ]
            }
          },
          "required": [
            "fileName",
            "fileId",
            "docType"
          ]
        }
      ],
      "additionalItems": false
    }
  },
  "required": [
    "invProcessedAmt",
    "invProcessedCount",
    "cmProcessedAmt",
    "cmProcessedCount",
    "correlationId",
    "data"
  ],
  "definitions": {
    "transaction": {
      "id": "/Transaction",
      "type": "object",
      "properties": {
        "trantype": {
          "title": "Transaction Type",
          "description": "This is the Type of Transaction being sent from Acumatica.",
          "type": "string",
          "enum": [
            "Invoice",
            "Credit Memo"
          ]
        },
        "custbody_acumatica_batch_id": {
          "title": "Acumatica Batch Number",
          "description": "This is the Invoice Batch Id assigned by Acumatica.",
          "type": "string"
        },
        "tranid": {
          "title": "Transaction Number",
          "description": "This is the Invoice or Credit Memo Id passed from Acumatica.",
          "type": "string"
        },
        "entitiy": {
          "title": "Customer",
          "description": "This is the Customer related to the Invoice or Credit Memo.",
          "type": "string"
        },
        "trandate": {
          "title": "Date",
          "description": "This is the date of the Invoice.",
          "type": "string"
        },
        "refNum": {
          "title": "Ref No.",
          "description": "This applies to Credit Memos only -- it is a reference to the Invoice to which the Credit Memo is applied to.",
          "type": "string"
        },
        "memo": {
          "title": "Memo",
          "type": "string"
        },
        "items": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "/Line#"
          }
        }
      },
      "required": [
        "trantype",
        "custbody_acumatica_batch_id",
        "tranid",
        "entitiy",
        "trandate",
        "memo",
        "items",
        "Documents"
      ],
      "definitions": {
        "line": {
          "id": "/Line",
          "title": "Invoice or Credit Memo Line Items",
          "description": "This is an object that contains properties related to Invoice and Credit Memo line items.",
          "type": "object",
          "properties": {
            "item": {
              "title": "Product Id",
              "description": "This is the Item Name (not the Id) of each Invoice line",
              "type": "string"
            },
            "quantity": {
              "title": "Units",
              "description": "This is the Quantity of Items on each Invoice line.",
              "type": "integer"
            },
            "rate": {
              "title": "Unit Price",
              "description": "This is the Unit Price of the Item on each Invoice line.",
              "type": "number"
            },
            "amount": {
              "title": "Amount",
              "description": "This is the amount of eachthe Item on each Invoice line.",
              "type": "number"
            },
            "istaxable": {
              "title": "Taxable",
              "description": "This boolean field scpecifies whether taxes will be applied to an Invoice line.",
              "type": "boolean"
            },
            "taxcode": {
              "title": "Tax Code",
              "type": "string"
            },
            "taxrate1": {
              "title": "Tax Rate",
              "description": "This is the tax percentage of each Invoice line.",
              "type": "number"
            }
          },
          "required": [
            "item",
            "quantity",
            "rate",
            "amount",
            "istaxable",
            "taxcode",
            "taxrate1"
          ]
        }

      }

    }
  }
}

Fails for non-string examples

Hello! I think a recent change may have introduced an old bug about non-string examples. The particular code is here:

const split = example.toString().split('\n');
if (split.length === 1) {
this.outputLine(` * example: ${this.protectComment(example)}`);

When we do the split, we use toString to support non-string examples. However, we then pass the non-stringified example value into protectComment, which attempts to call replace on it. This function doesn't exist, so we get this error:

TypeError: str.replace is not a function
    at WriteProcessor.protectComment (...\node_modules\dtsgenerator\src\writeProcessor.js:71:20)
    at WriteProcessor.outputJSDoc (...\node_modules\dtsgenerator\src\writeProcessor.js:88:55)
    at TypeDefinition.generateType (...\node_modules\dtsgenerator\src\typeDefinition.js:113:17)
    at TypeDefinition.doProcess (...\node_modules\dtsgenerator\src\typeDefinition.js:48:14)

Adding a type on spec might help prevent this problem, by declaring example as string | number instead of its current any.

Thank you!

Feature Request: Allow non-optional keys when schema has default.

I use this lib primarily for server-side consumption, so my controllers can have types for request bodies and query params.
dtsgenerator marks interface keys as optional (?) when the schema does not mark them as required, which makes sense from the client-side perspective, but from the server-side, if the attribute has a default value the generated TS interface should not consider the key as optional.

My solution to date is to use a wrapper script that dives into the Definition schemas (Swagger v2) and sets keys as required if they have a default set, before throwing the spec into dtsgenerator.

async function main() {
  const spec = JSON.parse(fs.readFileSync(swaggerPath, { encoding: "utf-8" }));
  for (const schema of Object.values(spec.definitions)) {
    fixDefaults(schema);
  }
  const result = await dtsGenerator({
    contents: [spec],
    namespaceName: "MyAPI",
  });
  fs.writeFileSync(outPath, result, { encoding: "utf-8" });
}

function fixDefaults(schema) {
  if (!schema.properties) {
    return;
  }

  if (!schema.required) {
    schema.required = [];
  }

  for (const [k, subSchema] of Object.entries(schema.properties)) {
    if ("default" in subSchema && !schema.required.includes(k)) {
      schema.required.push(k);
    }

    if (subSchema.type === "object") {
      fixDefaults(subSchema);
    }
  }
}

I thought I would open this as an issue instead of a PR to see if this feature has any buyin.
It would mean adding an optional arg, called something?, and the implementation would need to be smarter than my workaround since determining if an attribute has a default varies from JSON Schema/Swagger/OpenAPI.

A property name cannot contain a "/"

Thanks for this, this is awesome.

I do run into the following issue. The following (swagger/open api) schema crashes dtsgenerator:

{
  "swagger": "2.0",
  "definitions": {
    "Zipcode": {
      "type": "object",
      "properties": {
        "odd/even": {
          "type": "string",
          "enum": [
            "odd",
            "even"
          ]
        }
      }
    }
  }
}

Cmd: dtsgen test.json
Expected result: typescript definitions
Actual result: Error with stacktrace:

$ dtsgen test.json 
TypeError: Cannot read property 'id' of undefined
    at getId (/usr/lib/node_modules/dtsgenerator/dist/core/jsonSchema.js:45:19)
    at Object.getSubSchema (/usr/lib/node_modules/dtsgenerator/dist/core/jsonSchema.js:24:21)
    at DtsGenerator.normalizeContent (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:79:35)
    at DtsGenerator.generateProperties (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:152:39)
    at DtsGenerator.generateTypeModel (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:128:14)
    at DtsGenerator.walkSchema (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:69:29)
    at DtsGenerator.walk (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:43:26)
    at DtsGenerator.walk (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:48:26)
    at DtsGenerator.<anonymous> (/usr/lib/node_modules/dtsgenerator/dist/core/dtsGenerator.js:26:30)
    at step (/usr/lib/node_modules/dtsgenerator/node_modules/tslib/tslib.js:133:27)

strictNullTypes option

Hello.
Is it possible to add strictNullTypes option to generate source files friendly to typescript strictNullCheck option instead of optional properties? This would be really useful for projects which uses this typescript option.

TODO for v1 release

  • support JSON Schema Draft 07 and OpenAPI v3
  • remove unused command line
  • add the document of usage as a library for changing Type name rule.
  • add the document of supporting element of each spec

Add --namespace <namespace> CLI to override default namespaces

When running dtsgen -o types.d.ts < openapi.yaml, the emitted file contains a namespace based on the JSON path to the schemas, namely

declare namespace Definitions { ... }

Unfortunately, when one converts the file from OpenAPI 2.0 to OpenAPI 3.0, the location of the schemas is now in components schemas and the output is

declare namespace Components {
    namespace Schemas {

I'd like the output to be independent of the JSON path where the schemas are found, as these names are really unrelated to the API itself; they are merely artifacts of the OpenAPI specification and layout.

I propose adding a --namespace <namespace> option in the CLI, so one could do

dtsgen -o petstore.d.ts --namespace PetStore << petstore.yaml

to get

declare namespace PetStore { ... }

If you like, I can submit a PR to support this. It also allows one to use --namespace ~none~ so the emitted types are not in a namespace at all.

convert union types to types

Hi,

This is more a suggestion/question than a bug. Enums are converted to union types like so:

status: 'active' | 'ended' | 'preparing';

This works well. However, I recently stumbled upon large enums and a sonar tslint rule that only allows for three union type members:
https://github.com/SonarSource/SonarTS/blob/master/sonarts-core/docs/rules/max-union-size.md

Sonar implies it is a better practice to define types than using union types. So that the example becomes:

type statusType =  'active' | 'ended' | 'preparing';
status: statusType;

I like the general idea, because the enum suddenly becomes reusable.

What do you think?

Support for relative references

dtsgenerator creates some really great definitions. I'm having some issues with the $ref implementation requiring a top-level id.

OpenAPI defines the $ref: using the URL of the current document as the base URI. Setting the $ref value to match a dtsgenerator-only-syntax matching an id: causes trouble using this with any other OpenAPI software.

The base cause is that this is not valid a OpenAPI v3 schema. IE running it through something like swagger-parser will fail validation.

Consider this structure:

src/
- api.yaml
|-- components/
|---- models/
|------ Auth.yaml
|---- responses/
|------ Response.yaml

Assume that:

  1. Api.yaml has a $ref to Response.yaml and Auth.yaml
  2. Response.yaml has a $ref to Auth.yaml.

If I set the id:'s and ref:'s to /Auth.yaml and /Response.yaml, it will work with dtsgenerator.

However, this will fail OpenAPI validation (id: property not valid, and eg. /Auth.yaml not found on disk.) and make this schema unusable with most other Open API packages.

If I set the $ref to the follow the proper spec:

  • in Api.yaml:
    • ./components/responses/Response.yaml,
    • ./components/models/Auth.yaml
  • in Response.yaml:
    • ../models/Auth.yaml

Then it will follow the spec and work with most other packages, but fail with dtsgenerator. There is no way to match the id: property, since Auth.yaml is referenced from two different places.

I'm sure there is a good reason why id is required - but is there no way to use this package using the spec-defined implementation of $ref? Or a workaround? Or am I doing something wrong?

Thanks for the great work!

Definition generated improperly when multiple instances of a resource are inherited

Take the following example spec that contains 2 definitions: resource and createResource. Resource both defines its own _embedded property and inherits _embedded from createResource.
_embedded is the same in both cases except for the description.

swagger: '2.0'
info:
  title: Example
  version: 0.1.0
paths:
  /tasks:
    get:
      summary: Return a collection of tasks
      operationId: getTasks
      responses:
        '200':
          description: OK

definitions:
  resource:
    allOf: 
    - $ref: '#/definitions/createResource' 
    properties:
       _embedded:
        description: >-
          Test Description
        type: object
  createResource:
    properties:
       _embedded:
        description: >-
          Other Description
        type: object

Note the generated output below:

declare namespace Definitions {
  export interface CreateResource {
    /**
     * Other Description
     */
    _embedded?: {};
  }
  export interface Resource {
    /**
     * Other Description  // Expect this to be Test Description
     */
    _embedded?: {};
  }
}

Swagger editor shows the 2 resources with different descriptions, but the generated code has them with the same. This example uses Description to demo the issue, the issue is not limited to the Description field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.