@asyncapi/generator 2.1.3 → 2.3.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/CHANGELOG.md +12 -0
- package/lib/filtersRegistry.js +7 -2
- package/lib/generator.js +1 -3
- package/lib/hooksRegistry.js +4 -1
- package/lib/logMessages.js +12 -8
- package/lib/renderer/react.js +30 -16
- package/lib/utils.js +7 -1
- package/package.json +3 -3
- package/test/integration.test.js +32 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @asyncapi/generator
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 44fcc33: ts-node is registered only when it's actually needed
|
|
8
|
+
|
|
9
|
+
## 2.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 81dfd0c: Enable `noOverwriteGlobs` option for templates based on react rendering engine.
|
|
14
|
+
|
|
3
15
|
## 2.1.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/lib/filtersRegistry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const xfs = require('fs.extra');
|
|
4
|
-
const { isAsyncFunction } = require('./utils');
|
|
4
|
+
const { isAsyncFunction, registerTypeScript } = require('./utils');
|
|
5
5
|
const nunjucksFilters = require('@asyncapi/nunjucks-filters');
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -38,7 +38,12 @@ function registerLocalFilters(nunjucks, templateDir, filtersDir) {
|
|
|
38
38
|
|
|
39
39
|
walker.on('file', async (root, stats, next) => {
|
|
40
40
|
try {
|
|
41
|
-
const filePath = path.resolve(
|
|
41
|
+
const filePath = path.resolve(
|
|
42
|
+
templateDir,
|
|
43
|
+
path.resolve(root, stats.name)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
registerTypeScript(filePath);
|
|
42
47
|
// If it's a module constructor, inject dependencies to ensure consistent usage in remote templates in other projects or plain directories.
|
|
43
48
|
delete require.cache[require.resolve(filePath)];
|
|
44
49
|
const mod = require(filePath);
|
package/lib/generator.js
CHANGED
|
@@ -28,7 +28,6 @@ const {
|
|
|
28
28
|
isReactTemplate,
|
|
29
29
|
isJsFile,
|
|
30
30
|
registerSourceMap,
|
|
31
|
-
registerTypeScript,
|
|
32
31
|
getTemplateDetails,
|
|
33
32
|
convertCollectionToObject,
|
|
34
33
|
} = require('./utils');
|
|
@@ -59,7 +58,6 @@ const shouldIgnoreDir = dirPath =>
|
|
|
59
58
|
|| dirPath.startsWith(`.git${path.sep}`);
|
|
60
59
|
|
|
61
60
|
registerSourceMap();
|
|
62
|
-
registerTypeScript();
|
|
63
61
|
|
|
64
62
|
class Generator {
|
|
65
63
|
/**
|
|
@@ -852,7 +850,7 @@ class Generator {
|
|
|
852
850
|
if (renderContent === undefined) {
|
|
853
851
|
return;
|
|
854
852
|
} else if (isReactTemplate(this.templateConfig)) {
|
|
855
|
-
await saveRenderedReactContent(renderContent, outputpath);
|
|
853
|
+
await saveRenderedReactContent(renderContent, outputpath, this.noOverwriteGlobs);
|
|
856
854
|
} else {
|
|
857
855
|
await writeFile(outputpath, renderContent);
|
|
858
856
|
}
|
package/lib/hooksRegistry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const xfs = require('fs.extra');
|
|
3
|
-
const { exists } = require('./utils');
|
|
3
|
+
const { exists, registerTypeScript } = require('./utils');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Registers all template hooks.
|
|
@@ -37,6 +37,9 @@ async function registerLocalHooks(hooks, templateDir, hooksDir) {
|
|
|
37
37
|
walker.on('file', async (root, stats, next) => {
|
|
38
38
|
try {
|
|
39
39
|
const filePath = path.resolve(templateDir, path.resolve(root, stats.name));
|
|
40
|
+
|
|
41
|
+
registerTypeScript(filePath);
|
|
42
|
+
|
|
40
43
|
delete require.cache[require.resolve(filePath)];
|
|
41
44
|
const mod = require(filePath);
|
|
42
45
|
|
package/lib/logMessages.js
CHANGED
|
@@ -6,22 +6,22 @@ const NODE_MODULES_INSTALL ='Remember that your local template must have its own
|
|
|
6
6
|
|
|
7
7
|
const NPM_INSTALL_TRIGGER = 'Installation of template located on disk technically means symlink creation betweed node_modules of the generator and template sources. Your local template must have its own node_modules, "npm install" is not triggered.';
|
|
8
8
|
|
|
9
|
-
function templateVersion(ver) {
|
|
9
|
+
function templateVersion(ver) {
|
|
10
10
|
return `Version of used template is ${ver}.`;
|
|
11
|
-
}
|
|
11
|
+
}
|
|
12
12
|
|
|
13
13
|
function templateSource(localHtmlTemplate) {
|
|
14
14
|
return `Template sources taken from ${localHtmlTemplate}.`;
|
|
15
|
-
}
|
|
15
|
+
}
|
|
16
16
|
|
|
17
17
|
function templateNotFound(templateName) {
|
|
18
18
|
return `${templateName} not found in local dependencies but found it installed as a global package.`;
|
|
19
|
-
}
|
|
19
|
+
}
|
|
20
20
|
|
|
21
21
|
function packageNotAvailable(packageDetails) {
|
|
22
22
|
if (packageDetails && packageDetails.pkgPath) {
|
|
23
23
|
return `Unable to resolve template location at ${packageDetails.pkgPath}. Package is not available locally.`;
|
|
24
|
-
}
|
|
24
|
+
}
|
|
25
25
|
|
|
26
26
|
return `Template is not available locally and expected location is undefined. Known details are: ${JSON.stringify(packageDetails, null, 2)}`;
|
|
27
27
|
}
|
|
@@ -38,6 +38,10 @@ function relativeSourceFileNotGenerated(relativeSourceFile , subject) {
|
|
|
38
38
|
return `${relativeSourceFile} was not generated because ${subject} specified in template configuration in conditionalFiles was not found in provided AsyncAPI specification file.`;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function skipOverwrite(testFilePath) {
|
|
42
|
+
return `Skipping overwrite for: ${testFilePath}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
function conditionalFilesMatched(relativeSourceFile) {
|
|
42
46
|
return `${relativeSourceFile} was not generated because condition specified for this file in template configuration in conditionalFiles matched.`;
|
|
43
47
|
}
|
|
@@ -54,6 +58,6 @@ module.exports = {
|
|
|
54
58
|
installationDebugMessage,
|
|
55
59
|
templateSuccessfullyInstalled,
|
|
56
60
|
relativeSourceFileNotGenerated,
|
|
57
|
-
conditionalFilesMatched
|
|
58
|
-
|
|
59
|
-
};
|
|
61
|
+
conditionalFilesMatched,
|
|
62
|
+
skipOverwrite
|
|
63
|
+
};
|
package/lib/renderer/react.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const AsyncReactSDK = require('@asyncapi/generator-react-sdk');
|
|
3
|
+
const minimatch = require('minimatch');
|
|
4
|
+
const logMessage = require('../logMessages.js');
|
|
5
|
+
const log = require('loglevel');
|
|
3
6
|
const {
|
|
4
7
|
writeFile
|
|
5
8
|
} = require('../utils');
|
|
@@ -8,7 +11,7 @@ const reactExport = module.exports;
|
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Configures React templating system, this handles all the transpilation work.
|
|
11
|
-
*
|
|
14
|
+
*
|
|
12
15
|
* @private
|
|
13
16
|
* @param {string} templateLocation located for thetemplate
|
|
14
17
|
* @param {string} templateContentDir where the template content are located
|
|
@@ -23,9 +26,9 @@ reactExport.configureReact = async (templateLocation, templateContentDir, transp
|
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
28
|
* Renders the template with react and returns the content and meta data for the file.
|
|
26
|
-
*
|
|
29
|
+
*
|
|
27
30
|
* @private
|
|
28
|
-
* @param {AsyncAPIDocument} asyncapiDocument
|
|
31
|
+
* @param {AsyncAPIDocument} asyncapiDocument
|
|
29
32
|
* @param {string} filePath path to the template file
|
|
30
33
|
* @param {Object} extraTemplateData Extra data to pass to the template.
|
|
31
34
|
* @param {string} templateLocation located for thetemplate
|
|
@@ -33,34 +36,34 @@ reactExport.configureReact = async (templateLocation, templateContentDir, transp
|
|
|
33
36
|
* @param {string} transpiledTemplateLocation folder for the transpiled code
|
|
34
37
|
* @param {Object} templateParams provided template parameters
|
|
35
38
|
* @param {boolean} debug flag
|
|
36
|
-
* @param {string} originalAsyncAPI
|
|
39
|
+
* @param {string} originalAsyncAPI
|
|
37
40
|
* @return {Promise<TemplateRenderResult>}
|
|
38
41
|
*/
|
|
39
42
|
reactExport.renderReact = async (asyncapiDocument, filePath, extraTemplateData, templateLocation, templateContentDir, transpiledTemplateLocation, templateParams, debug, originalAsyncAPI) => {
|
|
40
43
|
extraTemplateData = extraTemplateData || {};
|
|
41
44
|
filePath = filePath.replace(templateContentDir, path.resolve(templateLocation, transpiledTemplateLocation));
|
|
42
45
|
return await AsyncReactSDK.renderTemplate(
|
|
43
|
-
filePath,
|
|
46
|
+
filePath,
|
|
44
47
|
{
|
|
45
48
|
asyncapi: asyncapiDocument,
|
|
46
49
|
params: templateParams,
|
|
47
50
|
originalAsyncAPI,
|
|
48
51
|
...extraTemplateData
|
|
49
|
-
},
|
|
52
|
+
},
|
|
50
53
|
debug
|
|
51
54
|
);
|
|
52
55
|
};
|
|
53
56
|
|
|
54
57
|
/**
|
|
55
58
|
* Save the single rendered react content based on the meta data available.
|
|
56
|
-
*
|
|
59
|
+
*
|
|
57
60
|
* @private
|
|
58
61
|
* @param {TemplateRenderResult} renderedContent the react content rendered
|
|
59
62
|
* @param {String} outputPath Path to the file being rendered.
|
|
60
63
|
*/
|
|
61
|
-
const saveContentToFile = async (renderedContent, outputPath) => {
|
|
64
|
+
const saveContentToFile = async (renderedContent, outputPath, noOverwriteGlobs = []) => {
|
|
62
65
|
let filePath = outputPath;
|
|
63
|
-
// Might be the same as in the `fs` package, but is an active choice for our default file permission for any rendered files.
|
|
66
|
+
// Might be the same as in the `fs` package, but is an active choice for our default file permission for any rendered files.
|
|
64
67
|
let permissions = 0o666;
|
|
65
68
|
const content = renderedContent.content;
|
|
66
69
|
|
|
@@ -78,21 +81,32 @@ const saveContentToFile = async (renderedContent, outputPath) => {
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
// get the final file name of the file
|
|
85
|
+
const finalFileName = path.basename(filePath);
|
|
86
|
+
// check whether the filename should be ignored based on user's inputs
|
|
87
|
+
const shouldOverwrite = !noOverwriteGlobs.some(globExp => minimatch(finalFileName, globExp));
|
|
88
|
+
|
|
89
|
+
// Write the file only if it should not be skipped
|
|
90
|
+
if (shouldOverwrite) {
|
|
91
|
+
await writeFile(filePath, content, {
|
|
92
|
+
mode: permissions
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
await log.debug(logMessage.skipOverwrite(filePath));
|
|
96
|
+
}
|
|
84
97
|
};
|
|
85
98
|
|
|
86
99
|
/**
|
|
87
100
|
* Save the rendered react content based on the meta data available.
|
|
88
|
-
*
|
|
101
|
+
*
|
|
89
102
|
* @private
|
|
90
103
|
* @param {TemplateRenderResult[] | TemplateRenderResult} renderedContent the react content rendered
|
|
91
104
|
* @param {String} outputPath Path to the file being rendered.
|
|
105
|
+
* @param noOverwriteGlobs Array of globs to skip overwriting files.
|
|
92
106
|
*/
|
|
93
|
-
reactExport.saveRenderedReactContent = async (renderedContent, outputPath) => {
|
|
107
|
+
reactExport.saveRenderedReactContent = async (renderedContent, outputPath, noOverwriteGlobs = []) => {
|
|
94
108
|
if (Array.isArray(renderedContent)) {
|
|
95
|
-
return Promise.all(renderedContent.map(content => saveContentToFile(content, outputPath)));
|
|
109
|
+
return Promise.all(renderedContent.map(content => saveContentToFile(content, outputPath, noOverwriteGlobs)));
|
|
96
110
|
}
|
|
97
|
-
return saveContentToFile(renderedContent, outputPath);
|
|
111
|
+
return await saveContentToFile(renderedContent, outputPath, noOverwriteGlobs);
|
|
98
112
|
};
|
package/lib/utils.js
CHANGED
|
@@ -149,7 +149,13 @@ utils.registerSourceMap = () => {
|
|
|
149
149
|
*
|
|
150
150
|
* @private
|
|
151
151
|
*/
|
|
152
|
-
utils.registerTypeScript = () => {
|
|
152
|
+
utils.registerTypeScript = (filePath) => {
|
|
153
|
+
const isTypescriptFile = filePath.endsWith('.ts');
|
|
154
|
+
|
|
155
|
+
if (!isTypescriptFile) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
153
159
|
const { REGISTER_INSTANCE, register } = require('ts-node');
|
|
154
160
|
// if the ts-node has already been registered before, do not register it again.
|
|
155
161
|
// Check the env. TS_NODE_ENV if ts-node started via ts-node-dev package
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asyncapi/generator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "The AsyncAPI generator. It can generate documentation, code, anything!",
|
|
5
5
|
"main": "./lib/generator.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"test": "npm run test:unit && npm run test:integration && npm run test:cli",
|
|
16
16
|
"test:unit": "jest --coverage --testPathIgnorePatterns=integration --testPathIgnorePatterns=test-project",
|
|
17
17
|
"test:dev": "npm run test:unit -- --watchAll",
|
|
18
|
-
"test:integration": "npm run test:cleanup && jest --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__'",
|
|
19
|
-
"test:integration:update": "jest --updateSnapshot --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__'",
|
|
18
|
+
"test:integration": "npm run test:cleanup && jest --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__(?!\\/loglevel\\.js$)'",
|
|
19
|
+
"test:integration:update": "jest --updateSnapshot --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__(?!\\/loglevel\\.js$)'",
|
|
20
20
|
"test:cli": "node cli.js ./test/docs/dummy.yml ./test/test-templates/react-template -o test/output --force-write --debug && test -e test/output/test-file.md",
|
|
21
21
|
"test:cleanup": "rimraf \"test/temp\"",
|
|
22
22
|
"docs": "jsdoc2md --partial docs/jsdoc2md-handlebars/custom-sig-name.hbs docs/jsdoc2md-handlebars/main.hbs docs/jsdoc2md-handlebars/docs.hbs docs/jsdoc2md-handlebars/header.hbs docs/jsdoc2md-handlebars/defaultvalue.hbs docs/jsdoc2md-handlebars/link.hbs docs/jsdoc2md-handlebars/params-table.hbs --files lib/generator.js > docs/api.md",
|
package/test/integration.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @jest-environment node
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { readFile } = require('fs').promises;
|
|
5
|
+
const { mkdir, writeFile, readFile } = require('fs').promises;
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const Generator = require('../lib/generator');
|
|
8
8
|
const dummySpecPath = path.resolve(__dirname, './docs/dummy.yml');
|
|
@@ -24,7 +24,7 @@ describe('Integration testing generateFromFile() to make sure the result of the
|
|
|
24
24
|
|
|
25
25
|
it('generated using Nunjucks template', async () => {
|
|
26
26
|
const outputDir = generateFolderName();
|
|
27
|
-
const generator = new Generator(nunjucksTemplate, outputDir, {
|
|
27
|
+
const generator = new Generator(nunjucksTemplate, outputDir, {
|
|
28
28
|
forceWrite: true,
|
|
29
29
|
templateParams: { version: 'v1', mode: 'production' }
|
|
30
30
|
});
|
|
@@ -35,7 +35,7 @@ describe('Integration testing generateFromFile() to make sure the result of the
|
|
|
35
35
|
|
|
36
36
|
it('generate using React template', async () => {
|
|
37
37
|
const outputDir = generateFolderName();
|
|
38
|
-
const generator = new Generator(reactTemplate, outputDir, {
|
|
38
|
+
const generator = new Generator(reactTemplate, outputDir, {
|
|
39
39
|
forceWrite: true ,
|
|
40
40
|
templateParams: { version: 'v1', mode: 'production' }
|
|
41
41
|
});
|
|
@@ -55,4 +55,33 @@ describe('Integration testing generateFromFile() to make sure the result of the
|
|
|
55
55
|
const file = await readFile(path.join(outputDir, testOutputFile), 'utf8');
|
|
56
56
|
expect(file).toMatchSnapshot();
|
|
57
57
|
});
|
|
58
|
+
|
|
59
|
+
it('should ignore specified files with noOverwriteGlobs', async () => {
|
|
60
|
+
const outputDir = generateFolderName();
|
|
61
|
+
// Manually create a file to test if it's not overwritten
|
|
62
|
+
await mkdir(outputDir, { recursive: true });
|
|
63
|
+
// Create a variable to store the file content
|
|
64
|
+
const testContent = '<script>const initialContent = "This should not change";</script>';
|
|
65
|
+
// eslint-disable-next-line sonarjs/no-duplicate-string
|
|
66
|
+
const testFilePath = path.normalize(path.resolve(outputDir, testOutputFile));
|
|
67
|
+
await writeFile(testFilePath, testContent);
|
|
68
|
+
|
|
69
|
+
// Manually create an output first, before generation, with additional custom file to validate if later it is still there, not overwritten
|
|
70
|
+
const generator = new Generator(reactTemplate, outputDir, {
|
|
71
|
+
forceWrite: true,
|
|
72
|
+
noOverwriteGlobs: [`**/${testOutputFile}`],
|
|
73
|
+
debug: true,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await generator.generateFromFile(dummySpecPath);
|
|
77
|
+
|
|
78
|
+
// Read the file to confirm it was not overwritten
|
|
79
|
+
const fileContent = await readFile(testFilePath, 'utf8');
|
|
80
|
+
// Check if the files have been overwritten
|
|
81
|
+
expect(fileContent).toBe(testContent);
|
|
82
|
+
// Check if the log debug message was printed
|
|
83
|
+
/*TODO:
|
|
84
|
+
Include log message test in the future to ensure that the log.debug for skipping overwrite is called
|
|
85
|
+
*/
|
|
86
|
+
});
|
|
58
87
|
});
|