@jmm-devkit/ngx-form-generator 1.5.0 → 1.6.0
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/README.md +1 -0
- package/dist/file-utils.js +7 -0
- package/dist/generator-lib.js +15 -15
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/json-parser.d.ts +9 -0
- package/dist/json-parser.js +20 -0
- package/dist/rules.js +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
## Fixes
|
|
4
4
|
|
|
5
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
|
+
- Added JSON parser for handling big integers.
|
|
6
7
|
|
|
7
8
|
## Improvements
|
|
8
9
|
|
package/dist/file-utils.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
/**
|
|
3
4
|
* Saves the generated file
|
|
4
5
|
* @param content - The content of the file to save.
|
|
5
6
|
* @param fileName - The name of the file to save.
|
|
6
7
|
*/
|
|
7
8
|
export function saveFile(content, fileName) {
|
|
9
|
+
// Ensure the directory exists before writing the file
|
|
10
|
+
const dir = path.dirname(fileName);
|
|
11
|
+
if (!fs.existsSync(dir)) {
|
|
12
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
// Write the content to the file
|
|
8
15
|
fs.writeFileSync(fileName, content);
|
|
9
16
|
}
|
package/dist/generator-lib.js
CHANGED
|
@@ -9,6 +9,7 @@ import * as prettier from 'prettier';
|
|
|
9
9
|
import camelcase from 'camelcase';
|
|
10
10
|
import { requiredRule, patternRule, minLengthRule, maxLengthRule, emailRule, minimumRule, maximumRule, } from './rules.js';
|
|
11
11
|
import SwaggerParser from '@apidevtools/swagger-parser';
|
|
12
|
+
import { JSON_PARSER } from './json-parser.js';
|
|
12
13
|
const DEFAULT_RULES = [requiredRule, patternRule, minLengthRule, maxLengthRule, emailRule, minimumRule, maximumRule];
|
|
13
14
|
const NEEDED_IMPORTS = `import { FormGroup, FormControl, Validators, FormArray } from '@angular/forms'; \n`;
|
|
14
15
|
let rules = [...DEFAULT_RULES];
|
|
@@ -20,14 +21,13 @@ let MAX_DEPTH = 2;
|
|
|
20
21
|
* @returns A string representing the generated forms.
|
|
21
22
|
*/
|
|
22
23
|
export async function makeForm(spec, maxDepth) {
|
|
23
|
-
var _a;
|
|
24
24
|
let definitions;
|
|
25
|
-
MAX_DEPTH = maxDepth
|
|
25
|
+
MAX_DEPTH = maxDepth ?? MAX_DEPTH;
|
|
26
26
|
if ('definitions' in spec) {
|
|
27
27
|
definitions = spec.definitions;
|
|
28
28
|
}
|
|
29
29
|
else if ('components' in spec) {
|
|
30
|
-
definitions =
|
|
30
|
+
definitions = spec.components?.schemas;
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
throw new Error('Cannot find schemas/definitions');
|
|
@@ -51,7 +51,7 @@ export async function makeForm(spec, maxDepth) {
|
|
|
51
51
|
*/
|
|
52
52
|
function makeDefinition(definitionName, definition) {
|
|
53
53
|
return `export const ${camelcase(definitionName)}Form = () => new FormGroup({
|
|
54
|
-
${makeFieldsBody(
|
|
54
|
+
${makeFieldsBody({ ...definition }, 0)}
|
|
55
55
|
});\n`;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
@@ -73,12 +73,11 @@ function makeFieldsBody(definition, depth) {
|
|
|
73
73
|
* @returns An array of strings representing the form fields.
|
|
74
74
|
*/
|
|
75
75
|
function extractPropertiesFields(definition, depth) {
|
|
76
|
-
var _a;
|
|
77
76
|
if (!('properties' in definition) || !definition.properties)
|
|
78
77
|
return [];
|
|
79
78
|
const fields = [];
|
|
80
79
|
for (const [fieldName, fieldValue] of Object.entries(definition.properties)) {
|
|
81
|
-
const field = makeField(fieldName, fieldValue, !!
|
|
80
|
+
const field = makeField(fieldName, fieldValue, !!definition.required?.includes(fieldName), depth);
|
|
82
81
|
if (field !== '') {
|
|
83
82
|
fields.push(field);
|
|
84
83
|
}
|
|
@@ -92,22 +91,21 @@ function extractPropertiesFields(definition, depth) {
|
|
|
92
91
|
* @returns An array of strings representing the form fields.
|
|
93
92
|
*/
|
|
94
93
|
function extractAllOfFields(definition, depth) {
|
|
95
|
-
var _a, _b, _c, _d, _e;
|
|
96
94
|
if (!('allOf' in definition) || !Array.isArray(definition.allOf))
|
|
97
95
|
return [];
|
|
98
96
|
const fields = [];
|
|
99
|
-
const definitionRequired =
|
|
97
|
+
const definitionRequired = definition.required ?? [];
|
|
100
98
|
for (const subSchema of definition.allOf) {
|
|
101
99
|
if ('$ref' in subSchema) {
|
|
102
100
|
const refName = subSchema.$ref.split('/').pop();
|
|
103
|
-
const refSchema =
|
|
101
|
+
const refSchema = definition.definitions?.[refName] || definition.components?.schemas?.[refName];
|
|
104
102
|
if (refSchema) {
|
|
105
103
|
refSchema.required = [...refSchema.required, ...definitionRequired];
|
|
106
104
|
fields.push(...makeFieldsBody(refSchema, depth));
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
107
|
else if ('type' in subSchema && subSchema.type === 'object') {
|
|
110
|
-
subSchema.required = [...(
|
|
108
|
+
subSchema.required = [...(subSchema.required ?? []), ...definitionRequired];
|
|
111
109
|
fields.push(...makeFieldsBody(subSchema, depth));
|
|
112
110
|
}
|
|
113
111
|
else {
|
|
@@ -149,9 +147,8 @@ function makeField(fieldName, property, isRequired, depth) {
|
|
|
149
147
|
* @returns A string representing the form array field.
|
|
150
148
|
*/
|
|
151
149
|
function makeArrayField(fieldName, property, isRequired, depth) {
|
|
152
|
-
var _a;
|
|
153
150
|
const itemDefinition = property.items;
|
|
154
|
-
const minItems =
|
|
151
|
+
const minItems = property['minItems'] ?? 1;
|
|
155
152
|
const items = [];
|
|
156
153
|
if (itemDefinition['type'] === 'object') {
|
|
157
154
|
for (let i = 0; i <= minItems; i++) {
|
|
@@ -227,8 +224,7 @@ export function resetRules() {
|
|
|
227
224
|
* @returns A string representing the file name or undefined if no title is available.
|
|
228
225
|
*/
|
|
229
226
|
export function makeFileName(swagger) {
|
|
230
|
-
|
|
231
|
-
if ((_a = swagger.info) === null || _a === void 0 ? void 0 : _a.title) {
|
|
227
|
+
if (swagger.info?.title) {
|
|
232
228
|
return `${camelcase(swagger.info.title)}.ts`;
|
|
233
229
|
}
|
|
234
230
|
}
|
|
@@ -238,5 +234,9 @@ export function makeFileName(swagger) {
|
|
|
238
234
|
* @returns A promise that resolves to the dereferenced OpenAPI document.
|
|
239
235
|
*/
|
|
240
236
|
export async function loadSpec(fileOrUrlPath) {
|
|
241
|
-
return SwaggerParser.dereference(fileOrUrlPath
|
|
237
|
+
return SwaggerParser.dereference(fileOrUrlPath, {
|
|
238
|
+
parse: {
|
|
239
|
+
json: JSON_PARSER,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
242
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as JSONBig from 'json-bigint';
|
|
2
|
+
const JSONBigNative = JSONBig.default({ protoAction: 'preserve' });
|
|
3
|
+
/**
|
|
4
|
+
* Parser for JSON files that can handle big integers.
|
|
5
|
+
*/
|
|
6
|
+
export const JSON_PARSER = {
|
|
7
|
+
order: 1,
|
|
8
|
+
canParse: '.json',
|
|
9
|
+
parse: (file) => {
|
|
10
|
+
const fileContent = file.data.toString();
|
|
11
|
+
try {
|
|
12
|
+
return JSONBigNative.parse(fileContent);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
const error = e;
|
|
16
|
+
console.error(`Error parsing JSON file: ${error.message}`);
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
};
|
package/dist/rules.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Copyright (c) 2020 Verizon
|
|
7
7
|
*/
|
|
8
8
|
function hasMetadata(fieldName, property, metadataName) {
|
|
9
|
-
return
|
|
9
|
+
return Object.hasOwn(property, metadataName);
|
|
10
10
|
}
|
|
11
11
|
function abstractRule(fieldName, property, ruleName) {
|
|
12
12
|
return hasMetadata(fieldName, property, ruleName) ? `Validators.${ruleName}(${property[ruleName]})` : '';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jmm-devkit/ngx-form-generator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Generates an Angular ReactiveForm from a Swagger or OpenAPI definition",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generator-lib.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@eslint/js": "^10.0.1",
|
|
30
|
+
"@types/json-bigint": "^1.0.4",
|
|
30
31
|
"eslint": "^10.0.0",
|
|
31
32
|
"ts-node": "^10.9.2",
|
|
32
33
|
"typescript": "^5.9.3",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
37
38
|
"@types/yargs": "^17.0.35",
|
|
38
39
|
"camelcase": "^9.0.0",
|
|
40
|
+
"json-bigint": "^1.0.0",
|
|
39
41
|
"openapi-types": "^12.1.3",
|
|
40
42
|
"prettier": "^3.8.1",
|
|
41
43
|
"yargs": "^18.0.0"
|