@jmm-devkit/ngx-form-generator 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +118 -0
- package/dist/generator-cli.js +47 -0
- package/dist/generator-lib.d.ts +15 -0
- package/dist/generator-lib.js +132 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/dist/rules.d.ts +26 -0
- package/dist/rules.js +52 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Verizon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Changes and Improvements over the Original
|
|
2
|
+
|
|
3
|
+
## Fixes
|
|
4
|
+
|
|
5
|
+
- Fixed the handling of the `properties` property when generating fields from the OpenAPI definition. Now, if `properties` is `undefined`, an empty array is returned, allowing the rest of the code to execute correctly.
|
|
6
|
+
|
|
7
|
+
## Improvements
|
|
8
|
+
|
|
9
|
+
- The form constant is now an arrow function. This allows the form to be reused without persisting its state between uses, as previously, being an object, the form state was retained.
|
|
10
|
+
|
|
11
|
+
# Angular Form Generator
|
|
12
|
+
|
|
13
|
+
Generates an Angular ReactiveForm from a Swagger or OpenAPI definition.
|
|
14
|
+
|
|
15
|
+
Validation rules should have a single source of truth. These rules should be exposed to consumers to apply them. By doing this we can be sure that the same rules for UI validation are enforced at the API layer.
|
|
16
|
+
|
|
17
|
+
[](http://commitizen.github.io/cz-cli/)
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# install locally in project
|
|
23
|
+
npm install @jmm-devkit/ngx-form-generator --save-dev
|
|
24
|
+
|
|
25
|
+
# install globally
|
|
26
|
+
npm install @jmm-devkit/ngx-form-generator -g
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## CLI Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
ngx-form-generator -f swagger.json -o projects/forms/src/lib/
|
|
33
|
+
|
|
34
|
+
# when installed locally in project run with npx
|
|
35
|
+
npx ngx-form-generator -f swagger.yaml -o projects/forms/src/lib/
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
| Option | Alias | Comment | Required |
|
|
39
|
+
| ------------ | ---------------- | ------------------------------------------------ | -------- |
|
|
40
|
+
| --version | | Show version number | |
|
|
41
|
+
| --input-spec | -i, --swaggerUrl | Location of the OpenAPI spec as URL or file path | ✓ |
|
|
42
|
+
| --output | -o, --outDir | Where to write the generated files | |
|
|
43
|
+
| --file-name | -f, --outFile | Generated file name | |
|
|
44
|
+
| --help | -h | Show help | |
|
|
45
|
+
|
|
46
|
+
### Example CLI Usage
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ngx-form-generator -i https://petstore.swagger.io/v2/swagger.json -o petstore-forms
|
|
50
|
+
ngx-form-generator -i https://petstore.swagger.io/v2/swagger.yaml -o petstore-forms
|
|
51
|
+
npx ngx-form-generator -i swagger.json -o project/form/src/lib
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Library Usage
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { loadSpec, makeForm, saveFile } from '@verizonconnect/ngx-form-generator';
|
|
58
|
+
|
|
59
|
+
async function main() {
|
|
60
|
+
const spec = await loadSpec('swagger.json');
|
|
61
|
+
const form = makeForm(spec);
|
|
62
|
+
await saveFile(form, 'projects/forms/src/lib/index.ts');
|
|
63
|
+
}
|
|
64
|
+
await main();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Examples Generated Form
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
|
71
|
+
|
|
72
|
+
export const addressModelForm = () => new FormGroup({
|
|
73
|
+
firstName: new FormControl(null, [
|
|
74
|
+
Validators.required,
|
|
75
|
+
Validators.pattern(/^[a-zA-Z\'\s]+$/),
|
|
76
|
+
Validators.minLength(1),
|
|
77
|
+
Validators.maxLength(100)
|
|
78
|
+
]),
|
|
79
|
+
lastName: new FormControl(null, [
|
|
80
|
+
Validators.required,
|
|
81
|
+
Validators.pattern(/^[a-zA-Z\'\s]+$/),
|
|
82
|
+
Validators.minLength(1),
|
|
83
|
+
Validators.maxLength(100)
|
|
84
|
+
]),
|
|
85
|
+
address: new FormControl(null, [
|
|
86
|
+
Validators.required,
|
|
87
|
+
Validators.pattern(/^[\w\'\s]+$/),
|
|
88
|
+
Validators.minLength(1),
|
|
89
|
+
Validators.maxLength(100)
|
|
90
|
+
]),
|
|
91
|
+
address2: new FormControl(null, [
|
|
92
|
+
Validators.pattern(/^[\w\'\s]+$/),
|
|
93
|
+
Validators.minLength(1),
|
|
94
|
+
Validators.maxLength(100)
|
|
95
|
+
]),
|
|
96
|
+
city: new FormControl(null, [
|
|
97
|
+
Validators.required,
|
|
98
|
+
Validators.pattern(/^[\w\'\s]+$/),
|
|
99
|
+
Validators.minLength(1),
|
|
100
|
+
Validators.maxLength(100)
|
|
101
|
+
]),
|
|
102
|
+
postalCode: new FormControl(null, [
|
|
103
|
+
Validators.required,
|
|
104
|
+
Validators.pattern(/^[\w\s]+$/),
|
|
105
|
+
Validators.minLength(4),
|
|
106
|
+
Validators.maxLength(8)
|
|
107
|
+
]),
|
|
108
|
+
emailAddress: new FormControl(null, [
|
|
109
|
+
Validators.required,
|
|
110
|
+
Validators.pattern(/^[\w\@\!\#\%\&\'\*\+\-\/\=\?\`\{\|\}\~\.]+$/),
|
|
111
|
+
Validators.email
|
|
112
|
+
])
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Licensed under the MIT License, (“the License”); you may not use this
|
|
6
|
+
* file except in compliance with the License.
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2020 Verizon
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const generator_lib_1 = require("./generator-lib");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
const yargs = require('yargs');
|
|
14
|
+
async function main() {
|
|
15
|
+
const argv = yargs
|
|
16
|
+
.option('input-spec', {
|
|
17
|
+
alias: ['i', 'swaggerUrl'],
|
|
18
|
+
description: 'Location of the OpenAPI spec as a URL or file path',
|
|
19
|
+
type: 'string',
|
|
20
|
+
require: true
|
|
21
|
+
})
|
|
22
|
+
.option('output', {
|
|
23
|
+
alias: ['o', 'outDir'],
|
|
24
|
+
description: 'Where to write the generated files',
|
|
25
|
+
type: 'string'
|
|
26
|
+
})
|
|
27
|
+
.option('file-name', {
|
|
28
|
+
alias: ['f', 'outFile'],
|
|
29
|
+
description: 'Generated file name',
|
|
30
|
+
type: 'string'
|
|
31
|
+
})
|
|
32
|
+
.help()
|
|
33
|
+
.wrap(null)
|
|
34
|
+
.usage('Generates Angular ReactiveForms from an OpenAPI v2 or v3 spec.\n\n Usage: $0 -i <spec> -o <path>')
|
|
35
|
+
.example('ngx-form-generator -i https://petstore.swagger.io/v2/swagger.json -o petstore-forms')
|
|
36
|
+
.example('ngx-form-generator -i https://petstore.swagger.io/v2/swagger.yaml -o petstore-forms')
|
|
37
|
+
.example('npx ngx-form-generator -i swagger.json -o project/form/src/lib')
|
|
38
|
+
.alias('help', 'h').argv;
|
|
39
|
+
const spec = await (0, generator_lib_1.loadSpec)(argv['input-spec']);
|
|
40
|
+
const file = (0, generator_lib_1.makeForm)(spec);
|
|
41
|
+
let fileName = argv['file-name'] || (0, generator_lib_1.makeFileName)(spec) || 'forms.ts';
|
|
42
|
+
if (argv.output) {
|
|
43
|
+
fileName = (0, path_1.join)(argv.output, fileName);
|
|
44
|
+
}
|
|
45
|
+
await (0, generator_lib_1.saveFile)(file, fileName);
|
|
46
|
+
}
|
|
47
|
+
main();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Licensed under the MIT License, (“the License”); you may not use this
|
|
4
|
+
* file except in compliance with the License.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2020 Verizon
|
|
7
|
+
*/
|
|
8
|
+
import { Rule } from './rules';
|
|
9
|
+
import { OpenAPI } from 'openapi-types';
|
|
10
|
+
export declare function addRule(rule: Rule): void;
|
|
11
|
+
export declare function resetRules(): void;
|
|
12
|
+
export declare function makeFileName(swagger: OpenAPI.Document): string | undefined;
|
|
13
|
+
export declare function makeForm(spec: OpenAPI.Document): string;
|
|
14
|
+
export declare function saveFile(file: string, fileName: string): Promise<void>;
|
|
15
|
+
export declare function loadSpec(fileOrUrlPath: string): Promise<OpenAPI.Document>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Licensed under the MIT License, (“the License”); you may not use this
|
|
5
|
+
* file except in compliance with the License.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2020 Verizon
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.loadSpec = exports.saveFile = exports.makeForm = exports.makeFileName = exports.resetRules = exports.addRule = void 0;
|
|
14
|
+
const ts_morph_1 = require("ts-morph");
|
|
15
|
+
const prettier_1 = __importDefault(require("prettier"));
|
|
16
|
+
const camelcase_1 = __importDefault(require("camelcase"));
|
|
17
|
+
const rules_1 = require("./rules");
|
|
18
|
+
const swagger_parser_1 = __importDefault(require("@apidevtools/swagger-parser"));
|
|
19
|
+
const DEFAULT_RULES = [rules_1.requiredRule, rules_1.patternRule, rules_1.minLengthRule, rules_1.maxLengthRule, rules_1.emailRule, rules_1.minimumRule, rules_1.maximumRule];
|
|
20
|
+
let rules = [...DEFAULT_RULES];
|
|
21
|
+
function addRule(rule) {
|
|
22
|
+
rules.push(rule);
|
|
23
|
+
}
|
|
24
|
+
exports.addRule = addRule;
|
|
25
|
+
function resetRules() {
|
|
26
|
+
rules = [...DEFAULT_RULES];
|
|
27
|
+
}
|
|
28
|
+
exports.resetRules = resetRules;
|
|
29
|
+
function makeFileName(swagger) {
|
|
30
|
+
if (swagger.info && swagger.info.title) {
|
|
31
|
+
return `${(0, camelcase_1.default)(swagger.info.title)}.ts`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.makeFileName = makeFileName;
|
|
35
|
+
function makeFieldRules(fieldName, definition) {
|
|
36
|
+
return rules
|
|
37
|
+
.map(rule => rule(fieldName, definition))
|
|
38
|
+
.filter(item => item != '')
|
|
39
|
+
.join();
|
|
40
|
+
}
|
|
41
|
+
function makeField(fieldName, definition) {
|
|
42
|
+
if (definition.properties[fieldName]['type'] === 'array') {
|
|
43
|
+
const itemDefinition = definition.properties[fieldName]['items'];
|
|
44
|
+
const minItems = +definition.properties[fieldName]['minItems'] || 1;
|
|
45
|
+
const items = [];
|
|
46
|
+
if (itemDefinition['type'] === 'object') {
|
|
47
|
+
for (let i = 0; i <= minItems; i++) {
|
|
48
|
+
items.push(`new FormGroup({${makeFieldsBody(itemDefinition)}})`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const _dummyProps = {
|
|
53
|
+
properties: {
|
|
54
|
+
dummy: itemDefinition
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const value = 'default' in _dummyProps.properties.dummy ? `'${_dummyProps.properties.dummy.default}'` : null;
|
|
58
|
+
for (let i = 1; i <= minItems; i++) {
|
|
59
|
+
items.push(`new FormControl(${value}, [${makeFieldRules('dummy', _dummyProps)}])`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return `"${fieldName}": new FormArray([${items.join(',')}])`;
|
|
63
|
+
}
|
|
64
|
+
else if (definition.properties[fieldName]['type'] === 'object') {
|
|
65
|
+
const constructFormGroup = makeFieldsBody(definition.properties[fieldName]);
|
|
66
|
+
return `"${fieldName}": new FormGroup({${constructFormGroup}})`;
|
|
67
|
+
}
|
|
68
|
+
const value = 'default' in definition.properties[fieldName] ? `'${definition.properties[fieldName].default}'` : null;
|
|
69
|
+
return `"${fieldName}": new FormControl(${value}, [${makeFieldRules(fieldName, definition)}])`;
|
|
70
|
+
}
|
|
71
|
+
function makeFieldsBody(definition) {
|
|
72
|
+
if ('allOf' in definition) {
|
|
73
|
+
const definitionKeys = Object.keys(definition.allOf);
|
|
74
|
+
const allOfFieldsBody = definitionKeys
|
|
75
|
+
.map(key => makeFieldsBody(definition.allOf[key]))
|
|
76
|
+
.reduce((acc, val) => acc.concat(val), []);
|
|
77
|
+
return allOfFieldsBody;
|
|
78
|
+
}
|
|
79
|
+
if (!definition.properties)
|
|
80
|
+
return [];
|
|
81
|
+
const fields = Object.keys(definition.properties);
|
|
82
|
+
const fieldsBody = fields.map(fieldName => makeField(fieldName, definition)).filter(item => item !== '');
|
|
83
|
+
return fieldsBody;
|
|
84
|
+
}
|
|
85
|
+
function makeDefinition(definitionName, definition) {
|
|
86
|
+
const fieldsBody = makeFieldsBody(definition);
|
|
87
|
+
return `
|
|
88
|
+
export const ${(0, camelcase_1.default)(definitionName)}Form = () => new FormGroup({
|
|
89
|
+
${fieldsBody}
|
|
90
|
+
});
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
function makeHeader(body) {
|
|
94
|
+
return `import { FormGroup, FormControl, Validators, FormArray } from '@angular/forms';
|
|
95
|
+
|
|
96
|
+
${body}`;
|
|
97
|
+
}
|
|
98
|
+
function makeForm(spec) {
|
|
99
|
+
var _a;
|
|
100
|
+
let definitions;
|
|
101
|
+
if ('definitions' in spec) {
|
|
102
|
+
definitions = spec.definitions;
|
|
103
|
+
}
|
|
104
|
+
else if ('components' in spec) {
|
|
105
|
+
definitions = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.schemas;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw new Error('Cannot find schemas/definitions');
|
|
109
|
+
}
|
|
110
|
+
if (!definitions) {
|
|
111
|
+
throw new Error('Cannot find schemas/definitions');
|
|
112
|
+
}
|
|
113
|
+
const definitionKeys = Object.keys(definitions);
|
|
114
|
+
const forms = definitionKeys
|
|
115
|
+
.map(key => makeDefinition(key, definitions[key]))
|
|
116
|
+
.filter(item => item != '')
|
|
117
|
+
.join('');
|
|
118
|
+
const file = makeHeader(forms);
|
|
119
|
+
return prettier_1.default.format(file, { parser: 'typescript', singleQuote: true });
|
|
120
|
+
}
|
|
121
|
+
exports.makeForm = makeForm;
|
|
122
|
+
async function saveFile(file, fileName) {
|
|
123
|
+
const project = new ts_morph_1.Project();
|
|
124
|
+
project.createSourceFile(fileName, file, { overwrite: true });
|
|
125
|
+
return project.save();
|
|
126
|
+
}
|
|
127
|
+
exports.saveFile = saveFile;
|
|
128
|
+
async function loadSpec(fileOrUrlPath) {
|
|
129
|
+
const parser = new swagger_parser_1.default();
|
|
130
|
+
return parser.dereference(fileOrUrlPath);
|
|
131
|
+
}
|
|
132
|
+
exports.loadSpec = loadSpec;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./generator-lib"), exports);
|
|
18
|
+
__exportStar(require("./rules"), exports);
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Licensed under the MIT License, (“the License”); you may not use this
|
|
4
|
+
* file except in compliance with the License.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2020 Verizon
|
|
7
|
+
*/
|
|
8
|
+
import { OpenAPIV2 } from 'openapi-types';
|
|
9
|
+
export declare type Property = {
|
|
10
|
+
format?: string;
|
|
11
|
+
pattern?: string;
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
minLength?: number;
|
|
14
|
+
minimum?: number;
|
|
15
|
+
maximum?: number;
|
|
16
|
+
};
|
|
17
|
+
export declare type Properties = Record<string, Property>;
|
|
18
|
+
export declare type Rule = (fieldName: string, properties: Definition) => string;
|
|
19
|
+
export declare type Definition = OpenAPIV2.DefinitionsObject;
|
|
20
|
+
export declare function requiredRule(fieldName: string, definition: Definition): string;
|
|
21
|
+
export declare function patternRule(fieldName: string, definition: Definition): string;
|
|
22
|
+
export declare function minLengthRule(fieldName: string, definition: Definition): string;
|
|
23
|
+
export declare function maxLengthRule(fieldName: string, definition: Definition): string;
|
|
24
|
+
export declare function emailRule(fieldName: string, definition: Definition): string;
|
|
25
|
+
export declare function minimumRule(fieldName: string, definition: Definition): string;
|
|
26
|
+
export declare function maximumRule(fieldName: string, definition: Definition): string;
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Licensed under the MIT License, (“the License”); you may not use this
|
|
5
|
+
* file except in compliance with the License.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2020 Verizon
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.maximumRule = exports.minimumRule = exports.emailRule = exports.maxLengthRule = exports.minLengthRule = exports.patternRule = exports.requiredRule = void 0;
|
|
11
|
+
function hasMetadata(fieldName, definition, metadataName) {
|
|
12
|
+
return definition.properties[fieldName].hasOwnProperty(metadataName);
|
|
13
|
+
}
|
|
14
|
+
function abstractRule(fieldName, definition, ruleName) {
|
|
15
|
+
return hasMetadata(fieldName, definition, ruleName)
|
|
16
|
+
? `Validators.${ruleName}(${definition.properties[fieldName][ruleName]})`
|
|
17
|
+
: '';
|
|
18
|
+
}
|
|
19
|
+
function requiredRule(fieldName, definition) {
|
|
20
|
+
return definition.required && definition.required.includes(fieldName) ? `Validators.required` : '';
|
|
21
|
+
}
|
|
22
|
+
exports.requiredRule = requiredRule;
|
|
23
|
+
function patternRule(fieldName, definition) {
|
|
24
|
+
return hasMetadata(fieldName, definition, 'pattern')
|
|
25
|
+
? `Validators.pattern(/${definition.properties[fieldName]['pattern']}/)`
|
|
26
|
+
: '';
|
|
27
|
+
}
|
|
28
|
+
exports.patternRule = patternRule;
|
|
29
|
+
function minLengthRule(fieldName, definition) {
|
|
30
|
+
return abstractRule(fieldName, definition, 'minLength');
|
|
31
|
+
}
|
|
32
|
+
exports.minLengthRule = minLengthRule;
|
|
33
|
+
function maxLengthRule(fieldName, definition) {
|
|
34
|
+
return abstractRule(fieldName, definition, 'maxLength');
|
|
35
|
+
}
|
|
36
|
+
exports.maxLengthRule = maxLengthRule;
|
|
37
|
+
function emailRule(fieldName, definition) {
|
|
38
|
+
return definition.properties[fieldName].format === 'email' ? `Validators.email` : '';
|
|
39
|
+
}
|
|
40
|
+
exports.emailRule = emailRule;
|
|
41
|
+
function minimumRule(fieldName, definition) {
|
|
42
|
+
return hasMetadata(fieldName, definition, 'minimum')
|
|
43
|
+
? `Validators.min(${definition.properties[fieldName]['minimum']})`
|
|
44
|
+
: '';
|
|
45
|
+
}
|
|
46
|
+
exports.minimumRule = minimumRule;
|
|
47
|
+
function maximumRule(fieldName, definition) {
|
|
48
|
+
return hasMetadata(fieldName, definition, 'maximum')
|
|
49
|
+
? `Validators.max(${definition.properties[fieldName]['maximum']})`
|
|
50
|
+
: '';
|
|
51
|
+
}
|
|
52
|
+
exports.maximumRule = maximumRule;
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jmm-devkit/ngx-form-generator",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "Generates an Angular ReactiveForm from a Swagger or OpenAPI definition",
|
|
5
|
+
"main": "dist/generator-lib.js",
|
|
6
|
+
"repository": "github:jmm-devkit/ngx-form-generator",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ngx-form-generator": "dist/generator-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "npm run build && jasmine dist/*.spec.js",
|
|
12
|
+
"build": "tsc --project .\\",
|
|
13
|
+
"lint": "eslint . --ext .ts",
|
|
14
|
+
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md"
|
|
15
|
+
},
|
|
16
|
+
"author": "Martin McWhorter <martin@mcwhorter.org> (https://github.com/martinmcwhorter)",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"angular",
|
|
20
|
+
"validation",
|
|
21
|
+
"form",
|
|
22
|
+
"reactive-forms",
|
|
23
|
+
"swagger",
|
|
24
|
+
"openapi",
|
|
25
|
+
"typescript"
|
|
26
|
+
],
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@commitlint/cli": "^17.1.2",
|
|
29
|
+
"@commitlint/config-conventional": "^17.0.3",
|
|
30
|
+
"@types/camelcase": "^4.1.0",
|
|
31
|
+
"@types/jasmine": "^4.3.0",
|
|
32
|
+
"@types/node-fetch": "^2.5.5",
|
|
33
|
+
"@types/prettier": "^1.19.1",
|
|
34
|
+
"@types/yaml": "^1.2.0",
|
|
35
|
+
"@types/yargs": "^17.0.13",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
37
|
+
"@typescript-eslint/parser": "^5.0.0",
|
|
38
|
+
"commitiquette": "^1.2.1",
|
|
39
|
+
"commitizen": "^4.2.4",
|
|
40
|
+
"eslint": "^8.0.1",
|
|
41
|
+
"eslint-config-prettier": "^6.10.1",
|
|
42
|
+
"husky": "^7.0.4",
|
|
43
|
+
"jasmine": "^4.4.0",
|
|
44
|
+
"lint-staged": "^13.0.3",
|
|
45
|
+
"openapi-types": "^7.0.1",
|
|
46
|
+
"typescript": "^4.8.4"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@apidevtools/swagger-parser": "^10.0.2",
|
|
50
|
+
"camelcase": "^5.0.0",
|
|
51
|
+
"prettier": "^1.19.1",
|
|
52
|
+
"ts-morph": "^16.0.0",
|
|
53
|
+
"yaml": "^2.1.3",
|
|
54
|
+
"yargs": "^17.6.0"
|
|
55
|
+
},
|
|
56
|
+
"husky": {
|
|
57
|
+
"hooks": {
|
|
58
|
+
"pre-commit": "lint-staged",
|
|
59
|
+
"prepare-commit-msg": "exec < /dev/tty && git cz --hook || true",
|
|
60
|
+
"commit-msg": "commitLint -E HUSKY_GIT_PARAMS"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"lint-staged": {
|
|
64
|
+
"*.{js,css,json,md}": [
|
|
65
|
+
"prettier --write",
|
|
66
|
+
"git add"
|
|
67
|
+
],
|
|
68
|
+
"*.ts": [
|
|
69
|
+
"eslint --fix",
|
|
70
|
+
"prettier --write",
|
|
71
|
+
"git add"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"config": {
|
|
75
|
+
"commitizen": {
|
|
76
|
+
"path": "commitiquette"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|