From b3c077320d92b536e9463fdbbf7c6c3666f5ba97 Mon Sep 17 00:00:00 2001 From: Chaitanya Chandurkar Date: Sun, 21 Feb 2021 18:43:54 -0500 Subject: [PATCH] Release v1.1.9 (#13) * Remove dead code * Fix the maxDepth config bug * Fix the Option[] wrap bug * Updated README with conversion example * 1.1.9 --- README.md | 65 +++++++++++++++++++++++++-- package-lock.json | 4 +- package.json | 2 +- src/converter.ts | 9 +--- src/formatter.ts | 2 +- tests/converter.test.ts | 2 +- tests/strip-schema.test.ts | 24 ++++++++++ tests/test-data/local-ref-schema.json | 3 +- 8 files changed, 93 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 75e98e4..3d4f274 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,69 @@ # json-schema-to-case-class A library to convert complex JSON Schema to [Scala Case Classes](https://docs.scala-lang.org/tour/case-classes.html). Supports both NodeJs and Browser environments. -[Try Online Editor](https://cchandurkar.github.io/case-class-generator/). +
[**Try Online Editor**](https://cchandurkar.github.io/case-class-generator/). -![Build Status](https://github.com/cchandurkar/json-schema-to-case-class/actions/workflows/build-and-deploy.yml/badge.svg?branch=main) + ![Build Status](https://github.com/cchandurkar/json-schema-to-case-class/actions/workflows/build-and-deploy.yml/badge.svg?branch=main) [![npm version](https://badge.fury.io/js/json-schema-to-case-class.svg)](https://badge.fury.io/js/json-schema-to-case-class) [![License](https://img.shields.io/npm/l/json-schema-to-case-class.svg)](LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![PRs Welcome](https://img.shields.io/badge/$-support-green.svg?style=flat-square)](https://github.com/sponsors/cchandurkar) + + + + + + + + + +
+JSON Schema + +Generated Scala Case Classes +
+
+{
+  "title": "Product",
+  "type": "object",
+  "required": [ "productId", "productName", "price" ],
+  "properties": {
+    "productId": { "type": "integer" },
+    "productName": { "type": "string" },
+    "price": { "type": "number" },
+    "tags": {
+      "type": "array",
+      "items": { "type": "string" }
+    },
+    "dimensions": {
+      "type": "object",
+      "properties": {
+        "length": { "type": "number" },
+        "width": { "type": "number" },
+        "height": { "type": "number" }
+      }
+    }
+  }
+}
+
+
+
+case class Product (
+   productId: Integer,
+   productName: String,
+   price: Double,
+   tags: Option[List[String]],
+   dimensions: Option[Dimensions]
+)
+
+
+case class Dimensions (
+   length: Double,
+   width: Double,
+   height: Double
+)
+
+
### Features 1. Resolve local as well as remote schema references. @@ -82,8 +138,9 @@ All contributions, enhancements, and bug-fixes are welcome. Open an issue or cre ##### Short-term Goals 1. Handle `allOf`/ `anyOf`/ `oneOf`. -2. Add support for converting YAML. -3. Update online editor to add more examples to choose from. +2. Support validations on class parameters. Eg. `exclusiveMinimum`, `minItems`, `uniqueItems`. +3. Add support for converting YAML. +4. Update online editor to add more examples to choose from. ##### Building locally 1. Clone the repo
diff --git a/package-lock.json b/package-lock.json index d6bad78..43e6ee8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "json-schema-to-case-class", - "version": "1.1.8", + "version": "1.1.9", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.1.8", + "version": "1.1.9", "license": "MIT", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.7", diff --git a/package.json b/package.json index 2c5527b..9418e79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "json-schema-to-case-class", - "version": "1.1.8", + "version": "1.1.9", "description": "A library that converts JSON Schema to Scala Case Classes", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/converter.ts b/src/converter.ts index e95415b..ff91ee8 100644 --- a/src/converter.ts +++ b/src/converter.ts @@ -5,8 +5,6 @@ import map from 'lodash/map'; import * as allTextCases from 'change-case'; -// import { parse, scope } from 'jsonref'; -// import axios from 'axios'; import $RefParser from '@apidevtools/json-schema-ref-parser/lib/index'; import { Config } from './config'; import { format } from './formatter'; @@ -81,11 +79,6 @@ const stripSchema = async (schema: any, config: IConfigResolved) : Promise => { - - // return await parse(schema, { scope: '', retriever: ( url => axios(url) ) }) - // .then( result => { return { error: null, schema: result } } ) - // .catch( err => { return { error: err, schema: null } } ); - return $RefParser .dereference(schema, { dereference: { circular: 'ignore' } }) .then(result => { return { error: null, schema: result } }) @@ -143,7 +136,7 @@ const stripSchemaObject = (schemaObject: any, currentDepth: number, entityTitle: } else { if (paramObject.type === 'object') { paramType = config.defaultGenericType; - } else { + } else if (paramObject.type === 'array') { paramType += `[${config.defaultGenericType}]`; } } diff --git a/src/formatter.ts b/src/formatter.ts index 156be37..2e4d055 100644 --- a/src/formatter.ts +++ b/src/formatter.ts @@ -80,7 +80,7 @@ const formatParamName = (param: ICaseClassDefParams): string => { * @param config */ const formatParamType = (param: ICaseClassDefParams, config: IConfigResolved): string => { - return (config.optionSetting === 'useOptions' && param.isRequired) || config.optionSetting === 'useOptionsForAll' + return (config.optionSetting === 'useOptions' && !param.isRequired) || config.optionSetting === 'useOptionsForAll' ? `Option[${param.paramType}]` : param.paramType; }; diff --git a/tests/converter.test.ts b/tests/converter.test.ts index 35d3043..6ab41e6 100644 --- a/tests/converter.test.ts +++ b/tests/converter.test.ts @@ -25,7 +25,7 @@ describe('Function convert()', () => { expect(result).to.contain('case class PersonInfo'); expect(result).to.contain('case class BillingAddress'); expect(result).to.contain('case class ShippingAddress'); - expect(result).to.contain('Option['); + expect(result).to.contain('zip: Option[Integer]'); }); diff --git a/tests/strip-schema.test.ts b/tests/strip-schema.test.ts index 23434c0..5593bbe 100644 --- a/tests/strip-schema.test.ts +++ b/tests/strip-schema.test.ts @@ -1,4 +1,5 @@ import get from 'lodash/get'; +import find from 'lodash/find'; import { expect } from 'chai'; import { stripSchema } from '../src' @@ -73,4 +74,27 @@ describe('Function stripSchema()', () => { }); + it('should parse parameter types as expected for maxDepth less than the total depth', async () => { + + const config = { + maxDepth: 1, + optionSetting: 'useOptions', + classNameTextCase: 'pascalCase', + classParamsTextCase: 'snakeCase', + topLevelCaseClassName: 'PersonInfo', + defaultGenericType: 'Any', + parseRefs: true, + generateComments: false + }; + + const result = await stripSchema(nestedSchema, Config.resolve(config)); + + expect(result).to.be.an('object'); + expect(result.entityName).to.eql(nestedSchema.title); + expect(get(find(result.parameters, { paramName: 'product_id' }), 'paramType')).to.eql('Integer'); + expect(get(find(result.parameters, { paramName: 'tags' }), 'paramType')).to.eql('List[Any]'); + expect(get(find(result.parameters, { paramName: 'dimensions' }), 'paramType')).to.eql('Any'); + + }); + }); diff --git a/tests/test-data/local-ref-schema.json b/tests/test-data/local-ref-schema.json index 9f17dbd..13efb8d 100644 --- a/tests/test-data/local-ref-schema.json +++ b/tests/test-data/local-ref-schema.json @@ -6,7 +6,8 @@ "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, - "state": { "type": "string" } + "state": { "type": "string" }, + "zip": { "type": "integer" } }, "required": ["street_address", "city", "state"] }