Skip to content

Commit

Permalink
feat: adding interpreter options ignoreAddtionalProperties and ignore…
Browse files Browse the repository at this point in the history
…AddtionalItems (#1094)

Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
  • Loading branch information
artur-ciocanu and Artur Ciocanu authored Jan 25, 2023
1 parent ae55778 commit 3745f54
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 1 deletion.
11 changes: 11 additions & 0 deletions docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This document contains many of the advanced use-cases that you may stumble upon
- [Change the generated indentation type and size](#change-the-generated-indentation-type-and-size)
- [Change the type mapping](#change-the-type-mapping)
- [Changing the constrain rules](#changing-the-constrain-rules)
- [Customizing the interpreter options](#customizing-the-interpreter-options)

<!-- tocstop -->

Expand Down Expand Up @@ -98,3 +99,13 @@ There can be multiple reasons why you want to change the default constrain rules
Check out this [example out for a live demonstration](../examples/overwrite-default-constraint/) for how to overwrite the default constraints.

Check out this [example out for a live demonstration](../examples/overwrite-naming-formatting/) for how to overwrite the naming formatting for models.

## Customizing the interpreter options

According to JSON schema if `additionalProperties` or `additionalItems` are omitted, their default value is `true`. `Interpreter` class honors this behavior, however for people coming from other code generators like `Open API Genertor` or `JSON Schema 2 POJO` this might come as a surprise.

To avoid adding `additionalProperties: false` or `additionalItems: false` to all your specs just to get the same behavior as other code generators, this can be achieved by configuring interpreter options:
- `ignoreAdditionalProperties` - if set, it ensures that `additionalProperties` is considered to be set to `false`
- `ignoreAdditionalItems` - if set, it ensures that `additionalItems` is considered to be set to `false`

Check out this [example out for a live demonstration](../examples/passing-interpreter-options/) for how to customize the behavior of `additionalProperties`.
17 changes: 17 additions & 0 deletions examples/passing-interpreter-options/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Passing interpreter options

This example shows how to pass interpreter options.

## How to run this example

Run this example using:

```sh
npm i && npm run start
```

If you are on Windows, use the `start:windows` script instead:

```sh
npm i && npm run start:windows
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Should be able to render models with overridden additionalProperties and should log expected output to console 1`] = `
Array [
"class Root {
private _email?: string;
constructor(input: {
email?: string,
}) {
this._email = input.email;
}
get email(): string | undefined { return this._email; }
set email(email: string | undefined) { this._email = email; }
}",
]
`;
15 changes: 15 additions & 0 deletions examples/passing-interpreter-options/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const spy = jest.spyOn(global.console, 'log').mockImplementation(() => {
return;
});
import { generate } from './index';

describe('Should be able to render models with overridden additionalProperties', () => {
afterAll(() => {
jest.restoreAllMocks();
});
test('and should log expected output to console', async () => {
await generate();
expect(spy.mock.calls.length).toEqual(1);
expect(spy.mock.calls[0]).toMatchSnapshot();
});
});
37 changes: 37 additions & 0 deletions examples/passing-interpreter-options/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TypeScriptGenerator } from '../../src';
import { CommonModel } from '../../src';
import {
InterpreterSchemaType,
Interpreter,
InterpreterOptions
} from '../../src/interpreter/Interpreter';
import { isModelObject } from '../../src/interpreter/Utils';

const generator = new TypeScriptGenerator({
processorOptions: {
interpreter: {
ignoreAdditionalProperties: true
}
}
});

const jsonSchemaDraft7 = {
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
properties: {
email: {
type: 'string',
format: 'email'
}
}
};

export async function generate(): Promise<void> {
const models = await generator.generate(jsonSchemaDraft7);
for (const model of models) {
console.log(model.result);
}
}
if (require.main === module) {
generate();
}
10 changes: 10 additions & 0 deletions examples/passing-interpreter-options/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions examples/passing-interpreter-options/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"config" : { "example_name" : "passing-interpreter-options" },
"scripts": {
"install": "cd ../.. && npm i",
"start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts",
"start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts",
"test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts",
"test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts"
}
}
3 changes: 3 additions & 0 deletions src/interpreter/InterpretAdditionalItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export default function interpretAdditionalItems(
interpreter: Interpreter,
interpreterOptions: InterpreterOptions = Interpreter.defaultInterpreterOptions
): void {
if (interpreterOptions.ignoreAdditionalItems === true) {
return;
}
if (typeof schema === 'boolean' || model.type?.includes('array') === false) {
return;
}
Expand Down
3 changes: 3 additions & 0 deletions src/interpreter/InterpretAdditionalProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export default function interpretAdditionalProperties(
interpreter: Interpreter,
interpreterOptions: InterpreterOptions = Interpreter.defaultInterpreterOptions
): void {
if (interpreterOptions.ignoreAdditionalProperties === true) {
return;
}
if (typeof schema === 'boolean' || isModelObject(model) === false) {
return;
}
Expand Down
6 changes: 5 additions & 1 deletion src/interpreter/Interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import interpretOneOfWithProperties from './InterpretOneOfWithProperties';

export type InterpreterOptions = {
allowInheritance?: boolean;
ignoreAdditionalProperties?: boolean;
ignoreAdditionalItems?: boolean;
};
export type InterpreterSchemas =
| Draft6Schema
Expand All @@ -35,7 +37,9 @@ export type InterpreterSchemaType = InterpreterSchemas | boolean;

export class Interpreter {
static defaultInterpreterOptions: InterpreterOptions = {
allowInheritance: false
allowInheritance: false,
ignoreAdditionalProperties: false,
ignoreAdditionalItems: false
};

private anonymCounter = 1;
Expand Down

0 comments on commit 3745f54

Please sign in to comment.