@grafana/openapi-to-k6 0.2.5 → 0.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/.github/workflows/tests.yaml +1 -0
- package/README.md +10 -4
- package/dist/cli.js +27 -12
- package/dist/constants.js +7 -3
- package/dist/errors.js +10 -0
- package/dist/generator/index.js +50 -3
- package/dist/generator/k6Client.js +5 -55
- package/dist/generator/k6ScriptBuilder.js +256 -0
- package/dist/helper.js +32 -0
- package/examples/basic_schema/single/k6-script.sample.ts +3 -2
- package/examples/basic_schema/single/simpleAPI.ts +1 -1
- package/examples/basic_schema/split/k6-script.sample.ts +3 -2
- package/examples/basic_schema/split/simpleAPI.schemas.ts +1 -1
- package/examples/basic_schema/split/simpleAPI.ts +1 -1
- package/examples/basic_schema/tags/default.ts +1 -1
- package/examples/basic_schema/tags/k6-script.sample.ts +4 -3
- package/examples/basic_schema/tags/simpleAPI.schemas.ts +1 -1
- package/examples/form_data_schema/schema.json +6 -3
- package/examples/form_data_schema/single/formDataAPI.ts +1 -1
- package/examples/form_data_schema/single/k6-script.sample.ts +10 -2
- package/examples/form_data_schema/split/formDataAPI.schemas.ts +1 -1
- package/examples/form_data_schema/split/formDataAPI.ts +1 -1
- package/examples/form_data_schema/split/k6-script.sample.ts +10 -2
- package/examples/form_data_schema/tags/default.ts +1 -1
- package/examples/form_data_schema/tags/formDataAPI.schemas.ts +1 -1
- package/examples/form_data_schema/tags/k6-script.sample.ts +11 -3
- package/examples/form_url_encoded_data_schema/schema.json +6 -3
- package/examples/form_url_encoded_data_schema/single/formURLEncodedAPI.ts +1 -1
- package/examples/form_url_encoded_data_schema/single/k6-script.sample.ts +11 -2
- package/examples/form_url_encoded_data_schema/split/formURLEncodedAPI.schemas.ts +1 -1
- package/examples/form_url_encoded_data_schema/split/formURLEncodedAPI.ts +1 -1
- package/examples/form_url_encoded_data_schema/split/k6-script.sample.ts +11 -2
- package/examples/form_url_encoded_data_schema/tags/default.ts +1 -1
- package/examples/form_url_encoded_data_schema/tags/formURLEncodedAPI.schemas.ts +1 -1
- package/examples/form_url_encoded_data_schema/tags/k6-script.sample.ts +12 -3
- package/examples/form_url_encoded_data_with_query_params_schema/schema.json +8 -4
- package/examples/form_url_encoded_data_with_query_params_schema/single/formURLEncodedAPIWithQueryParameters.ts +1 -1
- package/examples/form_url_encoded_data_with_query_params_schema/single/k6-script.sample.ts +19 -6
- package/examples/form_url_encoded_data_with_query_params_schema/split/formURLEncodedAPIWithQueryParameters.schemas.ts +1 -1
- package/examples/form_url_encoded_data_with_query_params_schema/split/formURLEncodedAPIWithQueryParameters.ts +1 -1
- package/examples/form_url_encoded_data_with_query_params_schema/split/k6-script.sample.ts +19 -6
- package/examples/form_url_encoded_data_with_query_params_schema/tags/default.ts +1 -1
- package/examples/form_url_encoded_data_with_query_params_schema/tags/formURLEncodedAPIWithQueryParameters.schemas.ts +1 -1
- package/examples/form_url_encoded_data_with_query_params_schema/tags/k6-script.sample.ts +14 -3
- package/examples/get_request_with_path_parameters_schema/schema.json +2 -1
- package/examples/get_request_with_path_parameters_schema/single/k6-script.sample.ts +6 -2
- package/examples/get_request_with_path_parameters_schema/single/simpleAPI.ts +1 -1
- package/examples/get_request_with_path_parameters_schema/split/k6-script.sample.ts +6 -2
- package/examples/get_request_with_path_parameters_schema/split/simpleAPI.schemas.ts +1 -1
- package/examples/get_request_with_path_parameters_schema/split/simpleAPI.ts +1 -1
- package/examples/get_request_with_path_parameters_schema/tags/default.ts +1 -1
- package/examples/get_request_with_path_parameters_schema/tags/k6-script.sample.ts +7 -3
- package/examples/get_request_with_path_parameters_schema/tags/simpleAPI.schemas.ts +1 -1
- package/examples/headers_schema/schema.json +2 -1
- package/examples/headers_schema/single/headerDemoAPI.ts +1 -1
- package/examples/headers_schema/single/k6-script.sample.ts +15 -4
- package/examples/headers_schema/split/headerDemoAPI.schemas.ts +1 -1
- package/examples/headers_schema/split/headerDemoAPI.ts +1 -1
- package/examples/headers_schema/split/k6-script.sample.ts +15 -4
- package/examples/headers_schema/tags/default.ts +1 -1
- package/examples/headers_schema/tags/headerDemoAPI.schemas.ts +1 -1
- package/examples/headers_schema/tags/k6-script.sample.ts +16 -5
- package/examples/no_title_schema/single/k6-script.sample.ts +3 -2
- package/examples/no_title_schema/single/k6Client.ts +1 -1
- package/examples/no_title_schema/split/k6-script.sample.ts +3 -2
- package/examples/no_title_schema/split/k6Client.schemas.ts +1 -1
- package/examples/no_title_schema/split/k6Client.ts +1 -1
- package/examples/no_title_schema/tags/default.ts +1 -1
- package/examples/no_title_schema/tags/k6-script.sample.ts +4 -3
- package/examples/no_title_schema/tags/k6Client.schemas.ts +1 -1
- package/examples/post_request_with_query_params/schema.json +14 -7
- package/examples/post_request_with_query_params/single/exampleAPI.ts +1 -1
- package/examples/post_request_with_query_params/single/k6-script.sample.ts +11 -2
- package/examples/post_request_with_query_params/split/exampleAPI.schemas.ts +1 -1
- package/examples/post_request_with_query_params/split/exampleAPI.ts +1 -1
- package/examples/post_request_with_query_params/split/k6-script.sample.ts +11 -2
- package/examples/post_request_with_query_params/tags/default.ts +1 -1
- package/examples/post_request_with_query_params/tags/exampleAPI.schemas.ts +1 -1
- package/examples/post_request_with_query_params/tags/k6-script.sample.ts +12 -3
- package/examples/query_params_schema/schema.json +20 -10
- package/examples/query_params_schema/single/exampleAPI.ts +1 -1
- package/examples/query_params_schema/single/k6-script.sample.ts +8 -2
- package/examples/query_params_schema/split/exampleAPI.schemas.ts +1 -1
- package/examples/query_params_schema/split/exampleAPI.ts +1 -1
- package/examples/query_params_schema/split/k6-script.sample.ts +8 -2
- package/examples/query_params_schema/tags/default.ts +1 -1
- package/examples/query_params_schema/tags/exampleAPI.schemas.ts +1 -1
- package/examples/query_params_schema/tags/k6-script.sample.ts +9 -3
- package/examples/simple_post_request_schema/schema.json +30 -15
- package/examples/simple_post_request_schema/single/exampleAPI.ts +1 -1
- package/examples/simple_post_request_schema/single/k6-script.sample.ts +16 -2
- package/examples/simple_post_request_schema/split/exampleAPI.schemas.ts +1 -1
- package/examples/simple_post_request_schema/split/exampleAPI.ts +1 -1
- package/examples/simple_post_request_schema/split/k6-script.sample.ts +16 -2
- package/examples/simple_post_request_schema/tags/default.ts +1 -1
- package/examples/simple_post_request_schema/tags/exampleAPI.schemas.ts +1 -1
- package/examples/simple_post_request_schema/tags/k6-script.sample.ts +17 -3
- package/package.json +3 -1
- package/src/cli.ts +32 -14
- package/src/constants.ts +7 -3
- package/src/errors.ts +6 -0
- package/src/generator/index.ts +67 -2
- package/src/generator/k6Client.ts +3 -72
- package/src/generator/k6ScriptBuilder.ts +328 -0
- package/src/helper.ts +40 -0
- package/src/type.d.ts +1 -0
- package/tests/e2e/schema.json +136 -18
- package/tests/e2e/single-tag-filter/k6Script.ts +50 -0
- package/tests/e2e/tags/k6Script.ts +3 -3
- package/tests/functional-tests/helper.ts +16 -0
- package/tests/functional-tests/{generator.test.ts → test-generator/generator.test.ts} +12 -21
- package/tests/functional-tests/test-sample-k6-scripts/fixtures/schema_using_ref_models.json +394 -0
- package/tests/functional-tests/test-sample-k6-scripts/fixtures/schema_with_examples.json +416 -0
- package/tests/functional-tests/test-sample-k6-scripts/fixtures/schema_with_no_variables.json +32 -0
- package/tests/functional-tests/test-sample-k6-scripts/sampleK6Scripts.test.ts +248 -0
- package/tests/functional-tests/test-tags-filtering/fixtures/tags_filtering.json +141 -0
- package/tests/functional-tests/test-tags-filtering/tagsFiltering.test.ts +166 -0
- package/tests/helper.test.ts +59 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/basic_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/form_data_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/form_url_encoded_data_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/form_url_encoded_data_with_query_params_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/get_request_with_path_parameters_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/headers_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/no_title_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/post_request_with_query_params.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/query_params_schema.json +0 -0
- /package/tests/functional-tests/{fixtures/schemas → test-generator/fixtures}/simple_post_request_schema.json +0 -0
|
@@ -33,6 +33,7 @@ jobs:
|
|
|
33
33
|
npm run dev -- ./tests/e2e/schema.json ./tests/e2e/single/sdk.ts --disable-analytics --mode single
|
|
34
34
|
npm run dev -- ./tests/e2e/schema.json ./tests/e2e/split/sdk.ts --disable-analytics --mode split
|
|
35
35
|
npm run dev -- ./tests/e2e/schema.json ./tests/e2e/tags/sdk.ts --disable-analytics --mode tags
|
|
36
|
+
npm run dev -- ./tests/e2e/schema.json ./tests/e2e/single-tag-filter/sdk.ts --disable-analytics --mode single --only-tags ItemsHeader
|
|
36
37
|
- name: Start Mockoon CLI
|
|
37
38
|
uses: mockoon/cli-action@v2
|
|
38
39
|
with:
|
package/README.md
CHANGED
|
@@ -60,10 +60,12 @@ Following are some of the configuration options supported by the tool.
|
|
|
60
60
|
3. `tags`: This modes splits your OpenAPI schema based on the tags and generates a separate client for each tag. If a route has no tag set, it will be available in `default.ts` file.
|
|
61
61
|
|
|
62
62
|
To check how the output looks for each mode, check out the [examples](./examples) directory.
|
|
63
|
-
2. `--
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
2. `--only-tags`: Filter the generated client to only include routes with specific tags from your OpenAPI schema. Multiple tags can be specified to include routes matching any of those tags. Routes without tags will be excluded. This is useful for generating focused clients that only contain the endpoints you need.
|
|
64
|
+
e.g. `openapi-to-k6 <path-to-openapi-schema> <output path> --only-tags ItemsHeader` will generate a client with only the routes that have the `ItemsHeader` tag. Multiple tags can be specified by using multiple `--only-tags` flags or by separating them with spaces.
|
|
65
|
+
3. `--disable-analytics`: Disable anonymous usage analytics reporting which helping making the tool better. You can also set an environment variable `DISABLE_ANALYTICS=true` to disable the analytics.
|
|
66
|
+
4. `--include-sample-script`: Generate a sample k6 script. The generated sample script uses the examples defined in the OpenAPI schema requests to make the script usable out of the box. If the examples are not defined, it will use Faker to generate random data.
|
|
67
|
+
5. `--verbose` or `-v` : Enable verbose logging to see more detailed logging output.
|
|
68
|
+
6. `--help` or `-h` : Show help message.
|
|
67
69
|
|
|
68
70
|
## Developing locally
|
|
69
71
|
|
|
@@ -130,4 +132,8 @@ k6 run --compatibility-mode=experimental_enhanced ./K6Script.ts
|
|
|
130
132
|
2. Install the compiled package locally by using `npm install .` or `npm install -g .`.
|
|
131
133
|
3. Use the CLI `k6-sdkgen <path-to-openapi-schema> <output path>`
|
|
132
134
|
|
|
135
|
+
## Releasing
|
|
136
|
+
|
|
137
|
+
To release a new version of the tool, create a new release on GitHub with the new version number as tag (e.g. `0.1.0` ) and the release notes. After the release is created, the GitHub actions will automatically package the tool and publish it to npm.
|
|
138
|
+
|
|
133
139
|
Special mention for the the open-source library [Orval](https://orval.dev/) which is used for the generation of the TypeScript client.
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
17
17
|
const commander_1 = require("commander");
|
|
18
18
|
const analytics_1 = require("./analytics");
|
|
19
19
|
const constants_1 = require("./constants");
|
|
20
|
+
const errors_1 = require("./errors");
|
|
20
21
|
const generator_1 = __importDefault(require("./generator"));
|
|
21
22
|
const helper_1 = require("./helper");
|
|
22
23
|
const logger_1 = require("./logger");
|
|
@@ -35,23 +36,30 @@ function validateMode(value) {
|
|
|
35
36
|
return value;
|
|
36
37
|
}
|
|
37
38
|
function generateSDK(_a) {
|
|
38
|
-
return __awaiter(this, arguments, void 0, function* ({ openApiPath, outputDir, shouldGenerateSampleK6Script, analyticsData, mode, }) {
|
|
39
|
-
logger_1.logger.logMessage('Generating TypeScript client for k6...\n'
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
return __awaiter(this, arguments, void 0, function* ({ openApiPath, outputDir, shouldGenerateSampleK6Script, analyticsData, mode, tags, }) {
|
|
40
|
+
logger_1.logger.logMessage('Generating TypeScript client for k6...\n' +
|
|
41
|
+
'OpenAPI schema: ' +
|
|
42
|
+
chalk_1.default.cyan(openApiPath) +
|
|
43
|
+
'\n' +
|
|
44
|
+
'Output: ' +
|
|
45
|
+
chalk_1.default.cyan(outputDir) +
|
|
46
|
+
'\n' +
|
|
47
|
+
((tags === null || tags === void 0 ? void 0 : tags.length)
|
|
48
|
+
? 'Filtering by tag(s): ' + chalk_1.default.cyan(tags.join(', '))
|
|
49
|
+
: '') +
|
|
50
|
+
'\n');
|
|
42
51
|
yield (0, generator_1.default)({
|
|
43
52
|
openApiPath,
|
|
44
53
|
outputDir,
|
|
45
54
|
shouldGenerateSampleK6Script,
|
|
46
55
|
analyticsData,
|
|
47
56
|
mode,
|
|
57
|
+
tags,
|
|
48
58
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
logger_1.logger.logMessage(`TypeScript client generated successfully.`, chalk_1.default.green);
|
|
54
|
-
}
|
|
59
|
+
const message = shouldGenerateSampleK6Script
|
|
60
|
+
? 'TypeScript client and sample k6 script generated successfully.'
|
|
61
|
+
: 'TypeScript client generated successfully.';
|
|
62
|
+
logger_1.logger.logMessage(message, chalk_1.default.green);
|
|
55
63
|
});
|
|
56
64
|
}
|
|
57
65
|
program
|
|
@@ -61,6 +69,7 @@ program
|
|
|
61
69
|
.argument('<openApiPath>', 'Path or URL for the OpenAPI schema file')
|
|
62
70
|
.argument('<outputDir>', 'Directory where the SDK should be generated')
|
|
63
71
|
.option('-m, --mode <string>', `mode to use for generating the client. Valid values - ${Object.values(constants_1.Mode).join(', ')}`, validateMode, constants_1.Mode.SINGLE)
|
|
72
|
+
.option('--only-tags <filters...>', 'list of tags to filter on. Generated client will only include operations with these tags')
|
|
64
73
|
.option('-v, --verbose', 'enable verbose mode to show debug logs')
|
|
65
74
|
.option('--include-sample-script', 'generate a sample k6 script')
|
|
66
75
|
.option('--disable-analytics', 'disable anonymous usage data collection')
|
|
@@ -89,11 +98,17 @@ program
|
|
|
89
98
|
shouldGenerateSampleK6Script: !!options.includeSampleScript,
|
|
90
99
|
analyticsData,
|
|
91
100
|
mode: options.mode,
|
|
101
|
+
tags: options.onlyTags,
|
|
92
102
|
});
|
|
93
103
|
}
|
|
94
104
|
catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
if (error instanceof errors_1.NoFilesGeneratedError) {
|
|
106
|
+
logger_1.logger.logMessage(error.message, chalk_1.default.yellow);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
logger_1.logger.error('Failed to generate SDK:');
|
|
110
|
+
console.error(error);
|
|
111
|
+
}
|
|
97
112
|
}
|
|
98
113
|
if (!shouldDisableAnalytics && analyticsData) {
|
|
99
114
|
logger_1.logger.debug('Reporting following usage analytics data:');
|
package/dist/constants.js
CHANGED
|
@@ -4,17 +4,21 @@ exports.Mode = exports.K6_SCRIPT_TEMPLATE = exports.SAMPLE_K6_SCRIPT_FILE_NAME =
|
|
|
4
4
|
exports.DEFAULT_SCHEMA_TITLE = 'K6Client';
|
|
5
5
|
exports.SAMPLE_K6_SCRIPT_FILE_NAME = 'k6-script.sample.ts';
|
|
6
6
|
exports.K6_SCRIPT_TEMPLATE = `
|
|
7
|
-
|
|
7
|
+
{{{importStatements}}}
|
|
8
8
|
|
|
9
9
|
const baseUrl = '<BASE_URL>';
|
|
10
|
-
|
|
10
|
+
{{{clientInitializationStatement}}}
|
|
11
|
+
|
|
11
12
|
|
|
12
13
|
export default function () {
|
|
14
|
+
{{{this.variableDefinition}}}
|
|
15
|
+
|
|
13
16
|
{{#each clientFunctionsList}}
|
|
14
17
|
/**
|
|
15
18
|
* {{this.summary}}
|
|
16
19
|
*/
|
|
17
|
-
|
|
20
|
+
{{{this.exampleValues}}}
|
|
21
|
+
const {{this.operationName}}ResponseData = {{clientObjectName}}.{{this.operationName}}({{this.requiredParametersString}});
|
|
18
22
|
|
|
19
23
|
{{/each}}
|
|
20
24
|
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoFilesGeneratedError = void 0;
|
|
4
|
+
class NoFilesGeneratedError extends Error {
|
|
5
|
+
constructor(message = 'No files were generated') {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'NoFilesGeneratedError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.NoFilesGeneratedError = NoFilesGeneratedError;
|
package/dist/generator/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
16
16
|
const orval_1 = __importDefault(require("orval"));
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const constants_1 = require("../constants");
|
|
19
|
+
const errors_1 = require("../errors");
|
|
19
20
|
const helper_1 = require("../helper");
|
|
20
21
|
const logger_1 = require("../logger");
|
|
21
22
|
const k6Client_1 = require("./k6Client");
|
|
@@ -31,7 +32,28 @@ const generatedFileHeaderGenerator = (info) => {
|
|
|
31
32
|
];
|
|
32
33
|
};
|
|
33
34
|
const afterAllFilesWriteHandler = (filePaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const removeSingleFile = (filePath) => {
|
|
36
|
+
try {
|
|
37
|
+
fs_1.default.unlinkSync(filePath);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
// This is non-critical, so we just log it
|
|
41
|
+
logger_1.logger.debug(`afterAllFilesWriteHandler ~ Error deleting file ${filePath}: ${error}`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const emptyFileList = [];
|
|
34
45
|
for (const filePath of filePaths) {
|
|
46
|
+
// There is a bug in the orval library which generates empty files when tags filter is applied
|
|
47
|
+
// and no matching endpoints are found and used mode is split or single.
|
|
48
|
+
// It generates the file with only the header comment.
|
|
49
|
+
// Hence, we manually remove those empty files.
|
|
50
|
+
// Issue link - https://github.com/orval-labs/orval/issues/1691
|
|
51
|
+
if ((0, helper_1.hasOnlyComments)(fs_1.default.readFileSync(filePath, 'utf-8'))) {
|
|
52
|
+
emptyFileList.push(filePath);
|
|
53
|
+
// Delete the file
|
|
54
|
+
removeSingleFile(filePath);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
35
57
|
yield (0, helper_1.formatFileWithPrettier)(filePath);
|
|
36
58
|
const fileName = path_1.default.basename(filePath);
|
|
37
59
|
if (fileName === '.ts') {
|
|
@@ -43,16 +65,32 @@ const afterAllFilesWriteHandler = (filePaths) => __awaiter(void 0, void 0, void
|
|
|
43
65
|
fs_1.default.renameSync(filePath, newPath);
|
|
44
66
|
}
|
|
45
67
|
}
|
|
68
|
+
if (emptyFileList.length > 0) {
|
|
69
|
+
logger_1.logger.debug(`afterAllFilesWriteHandler ~ The following files were empty and removed: ${emptyFileList.join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
// Return the list of generated file paths excluding the empty files
|
|
72
|
+
const filteredFilePaths = filePaths.filter((filePath) => !emptyFileList.includes(filePath));
|
|
73
|
+
// Check if all the filtered file path end with `.schemas.ts`
|
|
74
|
+
if (filteredFilePaths.every((filePath) => filePath.endsWith('.schemas.ts'))) {
|
|
75
|
+
// If yes we should remove them as only schemas files is not needed
|
|
76
|
+
filteredFilePaths.map(removeSingleFile);
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
return filteredFilePaths;
|
|
46
80
|
});
|
|
47
|
-
exports.default = (_a) => __awaiter(void 0, [_a], void 0, function* ({ openApiPath, outputDir, shouldGenerateSampleK6Script, analyticsData, mode, }) {
|
|
81
|
+
exports.default = (_a) => __awaiter(void 0, [_a], void 0, function* ({ openApiPath, outputDir, shouldGenerateSampleK6Script, analyticsData, mode, tags, }) {
|
|
48
82
|
/**
|
|
49
83
|
* Note!
|
|
50
84
|
* 1. override.requestOptions is not supported for the custom K6 client
|
|
51
85
|
* 2. override.mutator is not supported for the custom K6 client
|
|
52
86
|
*/
|
|
87
|
+
const generatedFilePaths = [];
|
|
53
88
|
yield outputOverrider.redirectOutputToNullStream(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
89
|
yield (0, orval_1.default)({
|
|
55
|
-
input:
|
|
90
|
+
input: {
|
|
91
|
+
target: openApiPath,
|
|
92
|
+
filters: { tags: tags && tags.length > 0 ? tags : undefined },
|
|
93
|
+
},
|
|
56
94
|
output: {
|
|
57
95
|
target: outputDir,
|
|
58
96
|
mode: mode,
|
|
@@ -63,8 +101,17 @@ exports.default = (_a) => __awaiter(void 0, [_a], void 0, function* ({ openApiPa
|
|
|
63
101
|
headers: true,
|
|
64
102
|
},
|
|
65
103
|
hooks: {
|
|
66
|
-
afterAllFilesWrite:
|
|
104
|
+
afterAllFilesWrite: (filePaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
105
|
+
const filteredFilePaths = yield afterAllFilesWriteHandler(filePaths);
|
|
106
|
+
generatedFilePaths.push(...filteredFilePaths);
|
|
107
|
+
}),
|
|
67
108
|
},
|
|
68
109
|
});
|
|
69
110
|
}));
|
|
111
|
+
if (generatedFilePaths.length === 0) {
|
|
112
|
+
const tagsMessage = (tags === null || tags === void 0 ? void 0 : tags.length) && tags.length > 0
|
|
113
|
+
? ` Applied tag filter(s): ${tags.join(', ')}`
|
|
114
|
+
: '';
|
|
115
|
+
throw new errors_1.NoFilesGeneratedError(`No files were generated.${tagsMessage}`);
|
|
116
|
+
}
|
|
70
117
|
});
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTitle = void 0;
|
|
15
4
|
exports.getK6ClientBuilder = getK6ClientBuilder;
|
|
16
5
|
const core_1 = require("@orval/core");
|
|
17
|
-
const handlebars_1 = __importDefault(require("handlebars"));
|
|
18
|
-
const path_1 = __importDefault(require("path"));
|
|
19
6
|
const constants_1 = require("../constants");
|
|
20
|
-
const
|
|
21
|
-
const logger_1 = require("../logger");
|
|
7
|
+
const k6ScriptBuilder_1 = require("./k6ScriptBuilder");
|
|
22
8
|
/**
|
|
23
9
|
* In case the supplied schema does not have a title set, it will set the default title to ensure
|
|
24
10
|
* proper client generation
|
|
@@ -209,6 +195,7 @@ const generateTitle = (title) => {
|
|
|
209
195
|
const sanTitle = (0, core_1.sanitize)(title || constants_1.DEFAULT_SCHEMA_TITLE);
|
|
210
196
|
return `${(0, core_1.pascal)(sanTitle)}Client`;
|
|
211
197
|
};
|
|
198
|
+
exports.generateTitle = generateTitle;
|
|
212
199
|
const generateK6Header = ({ title }) => {
|
|
213
200
|
return `
|
|
214
201
|
/**
|
|
@@ -237,43 +224,6 @@ const generateFooter = () => {
|
|
|
237
224
|
`;
|
|
238
225
|
return footer;
|
|
239
226
|
};
|
|
240
|
-
const k6ScriptBuilder = (verbOptions, output, context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
241
|
-
var _a;
|
|
242
|
-
const schemaTitle = ((_a = context.specs[context.specKey]) === null || _a === void 0 ? void 0 : _a.info.title) || constants_1.DEFAULT_SCHEMA_TITLE;
|
|
243
|
-
const { path: pathOfGeneratedClient, filename, extension, } = yield (0, helper_1.getGeneratedClientPath)(output.target, schemaTitle);
|
|
244
|
-
const directoryPath = (0, helper_1.getDirectoryForPath)(pathOfGeneratedClient);
|
|
245
|
-
const generateScriptPath = path_1.default.join(directoryPath, constants_1.SAMPLE_K6_SCRIPT_FILE_NAME);
|
|
246
|
-
logger_1.logger.debug(`k6ScriptBuilder ~ Generating sample K6 Script\n${JSON.stringify({
|
|
247
|
-
pathOfGeneratedClient,
|
|
248
|
-
filename,
|
|
249
|
-
extension,
|
|
250
|
-
schemaTitle,
|
|
251
|
-
directoryPath,
|
|
252
|
-
generateScriptPath,
|
|
253
|
-
}, null, 2)}`);
|
|
254
|
-
const clientFunctionsList = [];
|
|
255
|
-
for (const verbOption of Object.values(verbOptions)) {
|
|
256
|
-
const { operationName, summary, props } = verbOption;
|
|
257
|
-
const requiredProps = props.filter((prop) => prop.required);
|
|
258
|
-
clientFunctionsList.push({
|
|
259
|
-
operationName,
|
|
260
|
-
summary,
|
|
261
|
-
requiredParametersString: (0, core_1.toObjectString)(requiredProps, 'name'),
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
const scriptContentData = {
|
|
265
|
-
clientFunctionName: generateTitle(schemaTitle),
|
|
266
|
-
clientPath: `./${filename}${extension}`,
|
|
267
|
-
clientFunctionsList,
|
|
268
|
-
};
|
|
269
|
-
const template = handlebars_1.default.compile(constants_1.K6_SCRIPT_TEMPLATE);
|
|
270
|
-
return [
|
|
271
|
-
{
|
|
272
|
-
path: generateScriptPath,
|
|
273
|
-
content: template(scriptContentData),
|
|
274
|
-
},
|
|
275
|
-
];
|
|
276
|
-
});
|
|
277
227
|
function getK6Client(analyticsData) {
|
|
278
228
|
return function (verbOptions, options) {
|
|
279
229
|
_setDefaultSchemaTitle(options.context);
|
|
@@ -294,7 +244,7 @@ function getK6ClientBuilder(shouldGenerateSampleK6Script, analyticsData) {
|
|
|
294
244
|
header: generateK6Header,
|
|
295
245
|
dependencies: getK6Dependencies,
|
|
296
246
|
footer: generateFooter,
|
|
297
|
-
title: generateTitle,
|
|
298
|
-
extraFiles: shouldGenerateSampleK6Script ? k6ScriptBuilder : undefined,
|
|
247
|
+
title: exports.generateTitle,
|
|
248
|
+
extraFiles: shouldGenerateSampleK6Script ? k6ScriptBuilder_1.k6ScriptBuilder : undefined,
|
|
299
249
|
};
|
|
300
250
|
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.k6ScriptBuilder = void 0;
|
|
16
|
+
const faker_1 = require("@faker-js/faker");
|
|
17
|
+
const core_1 = require("@orval/core");
|
|
18
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
19
|
+
const path_1 = __importDefault(require("path"));
|
|
20
|
+
const constants_1 = require("../constants");
|
|
21
|
+
const helper_1 = require("../helper");
|
|
22
|
+
const logger_1 = require("../logger");
|
|
23
|
+
const k6Client_1 = require("./k6Client");
|
|
24
|
+
function getExampleValueForSchema(schema, context) {
|
|
25
|
+
// Handle $ref
|
|
26
|
+
if ('$ref' in schema) {
|
|
27
|
+
const { schema: resolvedSchema } = (0, core_1.resolveRef)(schema, context);
|
|
28
|
+
return getExampleValueForSchema(resolvedSchema, context);
|
|
29
|
+
}
|
|
30
|
+
if ('example' in schema) {
|
|
31
|
+
return `'${schema.example}'`;
|
|
32
|
+
}
|
|
33
|
+
let schemaType = schema.type;
|
|
34
|
+
if (Array.isArray(schemaType)) {
|
|
35
|
+
schemaType = schemaType[0];
|
|
36
|
+
}
|
|
37
|
+
if (!schemaType) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const enumValues = schema.enum;
|
|
41
|
+
switch (schemaType) {
|
|
42
|
+
case 'string':
|
|
43
|
+
return enumValues ? `'${enumValues[0]}'` : `'${faker_1.faker.word.sample()}'`;
|
|
44
|
+
case 'number':
|
|
45
|
+
return enumValues ? enumValues[0] : faker_1.faker.number.int();
|
|
46
|
+
case 'integer':
|
|
47
|
+
return enumValues ? enumValues[0] : faker_1.faker.number.int();
|
|
48
|
+
case 'boolean':
|
|
49
|
+
return enumValues ? enumValues[0] : faker_1.faker.datatype.boolean();
|
|
50
|
+
case 'array':
|
|
51
|
+
return '[]';
|
|
52
|
+
case 'object': {
|
|
53
|
+
let objectString = '{\n';
|
|
54
|
+
for (const property in schema.properties) {
|
|
55
|
+
if (schema.properties[property]) {
|
|
56
|
+
const propertyValue = getExampleValueForSchema(schema.properties[property], context);
|
|
57
|
+
objectString += `${property}: ${propertyValue},\n`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
objectString += '\n}';
|
|
61
|
+
return objectString;
|
|
62
|
+
}
|
|
63
|
+
default:
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function getExampleValues(requiredProps, originalOperation, context) {
|
|
68
|
+
var _a;
|
|
69
|
+
let exampleValues = '';
|
|
70
|
+
for (const prop of requiredProps) {
|
|
71
|
+
const propType = prop.type;
|
|
72
|
+
switch (propType) {
|
|
73
|
+
case core_1.GetterPropType.QUERY_PARAM: {
|
|
74
|
+
let exampleValue = '{\n';
|
|
75
|
+
for (const param of originalOperation.parameters || []) {
|
|
76
|
+
let resolvedParam;
|
|
77
|
+
if ('$ref' in param) {
|
|
78
|
+
const { schema: resolvedSchema } = (0, core_1.resolveRef)(param, context);
|
|
79
|
+
resolvedParam = resolvedSchema;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
resolvedParam = param;
|
|
83
|
+
}
|
|
84
|
+
// Only add required query parameters to the example values
|
|
85
|
+
if (resolvedParam.required && resolvedParam.in === 'query') {
|
|
86
|
+
if ('schema' in resolvedParam && resolvedParam.schema) {
|
|
87
|
+
exampleValue += `'${resolvedParam.name}': ${getExampleValueForSchema(resolvedParam.schema, context)},\n`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exampleValue += '\n}';
|
|
92
|
+
exampleValues += `params = ${exampleValue};\n`;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case core_1.GetterPropType.HEADER: {
|
|
96
|
+
let exampleValue = '{\n';
|
|
97
|
+
for (const param of originalOperation.parameters || []) {
|
|
98
|
+
let resolvedParam;
|
|
99
|
+
if ('$ref' in param) {
|
|
100
|
+
const { schema: resolvedSchema } = (0, core_1.resolveRef)(param, context);
|
|
101
|
+
resolvedParam = resolvedSchema;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
resolvedParam = param;
|
|
105
|
+
}
|
|
106
|
+
// Only add required query parameters to the example values
|
|
107
|
+
if (resolvedParam.required && resolvedParam.in === 'header') {
|
|
108
|
+
if ('schema' in resolvedParam && resolvedParam.schema) {
|
|
109
|
+
exampleValue += `'${resolvedParam.name}': ${getExampleValueForSchema(resolvedParam.schema, context)},\n`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exampleValue += '\n}';
|
|
114
|
+
exampleValues += `headers = ${exampleValue};\n`;
|
|
115
|
+
break;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case core_1.GetterPropType.PARAM: {
|
|
119
|
+
let example, paramSchema;
|
|
120
|
+
for (const parameter of originalOperation.parameters || []) {
|
|
121
|
+
if ('name' in parameter) {
|
|
122
|
+
paramSchema = parameter.schema;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
else if ('$ref' in parameter) {
|
|
126
|
+
const { schema: resolvedSchema } = (0, core_1.resolveRef)(parameter, context);
|
|
127
|
+
paramSchema = resolvedSchema.schema;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (paramSchema) {
|
|
132
|
+
example = getExampleValueForSchema(paramSchema, context);
|
|
133
|
+
}
|
|
134
|
+
if (example) {
|
|
135
|
+
exampleValues += `${prop.name} = ${example};\n`;
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case core_1.GetterPropType.BODY: {
|
|
140
|
+
// Generate example value from body schema
|
|
141
|
+
const requestBody = originalOperation.requestBody;
|
|
142
|
+
let requestBodyExample;
|
|
143
|
+
if (!requestBody) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
let resolvedSchema;
|
|
147
|
+
if ('$ref' in requestBody) {
|
|
148
|
+
const { schema } = (0, core_1.resolveRef)(requestBody, context);
|
|
149
|
+
resolvedSchema = schema;
|
|
150
|
+
}
|
|
151
|
+
else if ('content' in requestBody) {
|
|
152
|
+
resolvedSchema = requestBody;
|
|
153
|
+
}
|
|
154
|
+
if (resolvedSchema && 'content' in resolvedSchema) {
|
|
155
|
+
// Get the first available content type
|
|
156
|
+
const contentType = Object.keys(resolvedSchema.content)[0];
|
|
157
|
+
if (contentType) {
|
|
158
|
+
const requestBodySchema = (_a = resolvedSchema.content[contentType]) === null || _a === void 0 ? void 0 : _a.schema;
|
|
159
|
+
if (requestBodySchema) {
|
|
160
|
+
requestBodyExample = getExampleValueForSchema(requestBodySchema, context);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (requestBodyExample) {
|
|
165
|
+
exampleValues += `${prop.name} = ${requestBodyExample};\n`;
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return exampleValues;
|
|
172
|
+
}
|
|
173
|
+
function getClientClassName(identifier) {
|
|
174
|
+
return (0, k6Client_1.generateTitle)((0, core_1.pascal)(identifier));
|
|
175
|
+
}
|
|
176
|
+
function getClientObjectName(identifier) {
|
|
177
|
+
return (0, core_1.camel)((0, k6Client_1.generateTitle)((0, core_1.pascal)(identifier)));
|
|
178
|
+
}
|
|
179
|
+
const k6ScriptBuilder = (verbOptions, output, context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
180
|
+
var _a;
|
|
181
|
+
const schemaTitle = ((_a = context.specs[context.specKey]) === null || _a === void 0 ? void 0 : _a.info.title) || constants_1.DEFAULT_SCHEMA_TITLE;
|
|
182
|
+
const { path: pathOfGeneratedClient, filename, extension, } = yield (0, helper_1.getGeneratedClientPath)(output.target, schemaTitle);
|
|
183
|
+
const directoryPath = (0, helper_1.getDirectoryForPath)(pathOfGeneratedClient);
|
|
184
|
+
const generateScriptPath = path_1.default.join(directoryPath, constants_1.SAMPLE_K6_SCRIPT_FILE_NAME);
|
|
185
|
+
logger_1.logger.debug(`k6ScriptBuilder ~ Generating sample K6 Script\n${JSON.stringify({
|
|
186
|
+
pathOfGeneratedClient,
|
|
187
|
+
filename,
|
|
188
|
+
extension,
|
|
189
|
+
schemaTitle,
|
|
190
|
+
directoryPath,
|
|
191
|
+
generateScriptPath,
|
|
192
|
+
}, null, 2)}`);
|
|
193
|
+
const clientFunctionsList = [];
|
|
194
|
+
const uniqueVariables = new Set(); // Track unique variable names
|
|
195
|
+
const allUniqueTags = new Set();
|
|
196
|
+
for (const verbOption of Object.values(verbOptions)) {
|
|
197
|
+
if (verbOption.tags && verbOption.tags.length > 0) {
|
|
198
|
+
verbOption.tags.forEach((tag) => allUniqueTags.add(tag));
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
allUniqueTags.add('default');
|
|
202
|
+
}
|
|
203
|
+
let clientObjectName;
|
|
204
|
+
if (output.mode === 'tags') {
|
|
205
|
+
clientObjectName = getClientObjectName(verbOption.tags[0] || 'default');
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
clientObjectName = getClientObjectName(schemaTitle);
|
|
209
|
+
}
|
|
210
|
+
const { operationName, summary, props, originalOperation } = verbOption;
|
|
211
|
+
const requiredProps = props.filter((prop) => prop.required);
|
|
212
|
+
// Create example values object
|
|
213
|
+
const exampleValues = getExampleValues(requiredProps, originalOperation, context);
|
|
214
|
+
for (const prop of requiredProps) {
|
|
215
|
+
uniqueVariables.add(prop.name);
|
|
216
|
+
}
|
|
217
|
+
clientFunctionsList.push({
|
|
218
|
+
operationName,
|
|
219
|
+
summary,
|
|
220
|
+
exampleValues,
|
|
221
|
+
requiredParametersString: (0, core_1.toObjectString)(requiredProps, 'name'),
|
|
222
|
+
clientObjectName,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
let importStatements = '';
|
|
226
|
+
let clientInitializationStatement = '';
|
|
227
|
+
if (output.mode === 'tags') {
|
|
228
|
+
for (const tag of allUniqueTags) {
|
|
229
|
+
const { extension } = yield (0, helper_1.getGeneratedClientPath)(output.target, schemaTitle);
|
|
230
|
+
const clientName = getClientClassName(tag);
|
|
231
|
+
importStatements += `import { ${clientName} } from './${(0, core_1.kebab)(tag)}${extension}';\n`;
|
|
232
|
+
clientInitializationStatement += `const ${getClientObjectName(tag)} = new ${clientName}({ baseUrl });\n`;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const clientName = getClientClassName(schemaTitle);
|
|
237
|
+
importStatements = `import { ${clientName} } from './${filename}${extension}';\n`;
|
|
238
|
+
clientInitializationStatement = `const ${getClientObjectName(schemaTitle)} = new ${clientName}({ baseUrl });\n`;
|
|
239
|
+
}
|
|
240
|
+
const scriptContentData = {
|
|
241
|
+
clientFunctionsList,
|
|
242
|
+
variableDefinition: uniqueVariables.size > 0
|
|
243
|
+
? `let ${Array.from(uniqueVariables).join(', ')};`
|
|
244
|
+
: '',
|
|
245
|
+
importStatements,
|
|
246
|
+
clientInitializationStatement,
|
|
247
|
+
};
|
|
248
|
+
const template = handlebars_1.default.compile(constants_1.K6_SCRIPT_TEMPLATE);
|
|
249
|
+
return [
|
|
250
|
+
{
|
|
251
|
+
path: generateScriptPath,
|
|
252
|
+
content: template(scriptContentData),
|
|
253
|
+
},
|
|
254
|
+
];
|
|
255
|
+
});
|
|
256
|
+
exports.k6ScriptBuilder = k6ScriptBuilder;
|
package/dist/helper.js
CHANGED
|
@@ -17,8 +17,10 @@ exports.formatFileWithPrettier = formatFileWithPrettier;
|
|
|
17
17
|
exports.getGeneratedClientPath = getGeneratedClientPath;
|
|
18
18
|
exports.djb2Hash = djb2Hash;
|
|
19
19
|
exports.getDirectoryForPath = getDirectoryForPath;
|
|
20
|
+
exports.hasOnlyComments = hasOnlyComments;
|
|
20
21
|
const core_1 = require("@orval/core");
|
|
21
22
|
const fs_1 = __importDefault(require("fs"));
|
|
23
|
+
const typescript_1 = require("typescript");
|
|
22
24
|
const path_1 = __importDefault(require("path"));
|
|
23
25
|
const prettier_1 = require("prettier");
|
|
24
26
|
const package_json_1 = __importDefault(require("../package.json"));
|
|
@@ -156,3 +158,33 @@ function getDirectoryForPath(pathString) {
|
|
|
156
158
|
// If the path has an extension, it is a file
|
|
157
159
|
return path_1.default.dirname(pathString);
|
|
158
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Checks if a file contains only comments and whitespace, with no actual code.
|
|
163
|
+
*
|
|
164
|
+
* This function uses TypeScript's parser to accurately detect and remove all types
|
|
165
|
+
* of comments (single-line, multi-line, JSDoc) and whitespace from the input text.
|
|
166
|
+
* If nothing remains after removing comments and whitespace, then the file is
|
|
167
|
+
* considered to contain only comments.
|
|
168
|
+
*
|
|
169
|
+
* @param fileContent - The string content of the file to check
|
|
170
|
+
* @returns True if the file contains only comments and whitespace, false if it contains any actual code
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* // Returns true
|
|
174
|
+
* hasOnlyComments('// Just a comment');
|
|
175
|
+
*
|
|
176
|
+
* // Returns false
|
|
177
|
+
* hasOnlyComments('// A comment\nconst x = 1;');
|
|
178
|
+
*/
|
|
179
|
+
function hasOnlyComments(fileContent) {
|
|
180
|
+
// Create a source file
|
|
181
|
+
const sourceFile = (0, typescript_1.createSourceFile)('temp.ts', fileContent, typescript_1.ScriptTarget.Latest, true);
|
|
182
|
+
// Remove all comments and whitespace
|
|
183
|
+
const textWithoutComments = sourceFile
|
|
184
|
+
.getFullText()
|
|
185
|
+
.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '') // Remove comments
|
|
186
|
+
.replace(/\s+/g, ''); // Remove whitespace
|
|
187
|
+
// If there's any content left after removing comments and whitespace,
|
|
188
|
+
// then there's actual code
|
|
189
|
+
return textWithoutComments.length === 0;
|
|
190
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { SimpleAPIClient } from './simpleAPI.ts'
|
|
2
2
|
|
|
3
3
|
const baseUrl = '<BASE_URL>'
|
|
4
|
-
const
|
|
4
|
+
const simpleAPIClient = new SimpleAPIClient({ baseUrl })
|
|
5
5
|
|
|
6
6
|
export default function () {
|
|
7
7
|
/**
|
|
8
8
|
* Retrieve example data
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const getExampleResponseData = simpleAPIClient.getExample()
|
|
11
12
|
}
|