@grafana/openapi-to-k6 0.2.6 → 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/README.md +5 -1
- package/dist/constants.js +7 -3
- package/dist/generator/k6Client.js +5 -55
- package/dist/generator/k6ScriptBuilder.js +256 -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/constants.ts +7 -3
- package/src/generator/k6Client.ts +3 -72
- package/src/generator/k6ScriptBuilder.ts +328 -0
- package/tests/e2e/schema.json +135 -18
- package/tests/functional-tests/helper.ts +16 -0
- package/tests/functional-tests/test-generator/generator.test.ts +154 -0
- 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/tagsFiltering.test.ts +166 -0
- package/tests/functional-tests/generator.test.ts +0 -319
- /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
- /package/tests/functional-tests/{fixtures → test-tags-filtering/fixtures}/tags_filtering.json +0 -0
package/src/constants.ts
CHANGED
|
@@ -2,17 +2,21 @@ export const DEFAULT_SCHEMA_TITLE = 'K6Client'
|
|
|
2
2
|
|
|
3
3
|
export const SAMPLE_K6_SCRIPT_FILE_NAME = 'k6-script.sample.ts'
|
|
4
4
|
export const K6_SCRIPT_TEMPLATE = `
|
|
5
|
-
|
|
5
|
+
{{{importStatements}}}
|
|
6
6
|
|
|
7
7
|
const baseUrl = '<BASE_URL>';
|
|
8
|
-
|
|
8
|
+
{{{clientInitializationStatement}}}
|
|
9
|
+
|
|
9
10
|
|
|
10
11
|
export default function () {
|
|
12
|
+
{{{this.variableDefinition}}}
|
|
13
|
+
|
|
11
14
|
{{#each clientFunctionsList}}
|
|
12
15
|
/**
|
|
13
16
|
* {{this.summary}}
|
|
14
17
|
*/
|
|
15
|
-
|
|
18
|
+
{{{this.exampleValues}}}
|
|
19
|
+
const {{this.operationName}}ResponseData = {{clientObjectName}}.{{this.operationName}}({{this.requiredParametersString}});
|
|
16
20
|
|
|
17
21
|
{{/each}}
|
|
18
22
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClientDependenciesBuilder,
|
|
3
|
-
ClientExtraFilesBuilder,
|
|
4
3
|
ClientFooterBuilder,
|
|
5
4
|
ClientGeneratorsBuilder,
|
|
6
5
|
ClientHeaderBuilder,
|
|
@@ -17,17 +16,9 @@ import {
|
|
|
17
16
|
sanitize,
|
|
18
17
|
toObjectString,
|
|
19
18
|
} from '@orval/core'
|
|
20
|
-
import
|
|
21
|
-
import path from 'path'
|
|
22
|
-
import {
|
|
23
|
-
DEFAULT_SCHEMA_TITLE,
|
|
24
|
-
K6_SCRIPT_TEMPLATE,
|
|
25
|
-
SAMPLE_K6_SCRIPT_FILE_NAME,
|
|
26
|
-
} from '../constants'
|
|
27
|
-
import { getDirectoryForPath, getGeneratedClientPath } from '../helper'
|
|
28
|
-
import { logger } from '../logger'
|
|
19
|
+
import { DEFAULT_SCHEMA_TITLE } from '../constants'
|
|
29
20
|
import { AnalyticsData } from '../type'
|
|
30
|
-
|
|
21
|
+
import { k6ScriptBuilder } from './k6ScriptBuilder'
|
|
31
22
|
/**
|
|
32
23
|
* In case the supplied schema does not have a title set, it will set the default title to ensure
|
|
33
24
|
* proper client generation
|
|
@@ -260,7 +251,7 @@ const generateK6Implementation = (
|
|
|
260
251
|
`
|
|
261
252
|
}
|
|
262
253
|
|
|
263
|
-
const generateTitle: ClientTitleBuilder = (title) => {
|
|
254
|
+
export const generateTitle: ClientTitleBuilder = (title) => {
|
|
264
255
|
const sanTitle = sanitize(title || DEFAULT_SCHEMA_TITLE)
|
|
265
256
|
return `${pascal(sanTitle)}Client`
|
|
266
257
|
}
|
|
@@ -295,66 +286,6 @@ const generateFooter: ClientFooterBuilder = () => {
|
|
|
295
286
|
return footer
|
|
296
287
|
}
|
|
297
288
|
|
|
298
|
-
const k6ScriptBuilder: ClientExtraFilesBuilder = async (
|
|
299
|
-
verbOptions,
|
|
300
|
-
output,
|
|
301
|
-
context
|
|
302
|
-
) => {
|
|
303
|
-
const schemaTitle =
|
|
304
|
-
context.specs[context.specKey]?.info.title || DEFAULT_SCHEMA_TITLE
|
|
305
|
-
const {
|
|
306
|
-
path: pathOfGeneratedClient,
|
|
307
|
-
filename,
|
|
308
|
-
extension,
|
|
309
|
-
} = await getGeneratedClientPath(output.target!, schemaTitle)
|
|
310
|
-
const directoryPath = getDirectoryForPath(pathOfGeneratedClient)
|
|
311
|
-
const generateScriptPath = path.join(
|
|
312
|
-
directoryPath,
|
|
313
|
-
SAMPLE_K6_SCRIPT_FILE_NAME
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
logger.debug(
|
|
317
|
-
`k6ScriptBuilder ~ Generating sample K6 Script\n${JSON.stringify(
|
|
318
|
-
{
|
|
319
|
-
pathOfGeneratedClient,
|
|
320
|
-
filename,
|
|
321
|
-
extension,
|
|
322
|
-
schemaTitle,
|
|
323
|
-
directoryPath,
|
|
324
|
-
generateScriptPath,
|
|
325
|
-
},
|
|
326
|
-
null,
|
|
327
|
-
2
|
|
328
|
-
)}`
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
const clientFunctionsList = []
|
|
332
|
-
|
|
333
|
-
for (const verbOption of Object.values(verbOptions)) {
|
|
334
|
-
const { operationName, summary, props } = verbOption
|
|
335
|
-
const requiredProps = props.filter((prop) => prop.required)
|
|
336
|
-
clientFunctionsList.push({
|
|
337
|
-
operationName,
|
|
338
|
-
summary,
|
|
339
|
-
requiredParametersString: toObjectString(requiredProps, 'name'),
|
|
340
|
-
})
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const scriptContentData = {
|
|
344
|
-
clientFunctionName: generateTitle(schemaTitle),
|
|
345
|
-
clientPath: `./${filename}${extension}`,
|
|
346
|
-
clientFunctionsList,
|
|
347
|
-
}
|
|
348
|
-
const template = Handlebars.compile(K6_SCRIPT_TEMPLATE)
|
|
349
|
-
|
|
350
|
-
return [
|
|
351
|
-
{
|
|
352
|
-
path: generateScriptPath,
|
|
353
|
-
content: template(scriptContentData),
|
|
354
|
-
},
|
|
355
|
-
]
|
|
356
|
-
}
|
|
357
|
-
|
|
358
289
|
function getK6Client(analyticsData?: AnalyticsData) {
|
|
359
290
|
return function (
|
|
360
291
|
verbOptions: GeneratorVerbOptions,
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { faker } from '@faker-js/faker'
|
|
2
|
+
import {
|
|
3
|
+
camel,
|
|
4
|
+
ClientExtraFilesBuilder,
|
|
5
|
+
ClientFileBuilder,
|
|
6
|
+
ContextSpecs,
|
|
7
|
+
GeneratorVerbOptions,
|
|
8
|
+
GetterPropType,
|
|
9
|
+
kebab,
|
|
10
|
+
NormalizedOutputOptions,
|
|
11
|
+
pascal,
|
|
12
|
+
resolveRef,
|
|
13
|
+
toObjectString,
|
|
14
|
+
} from '@orval/core'
|
|
15
|
+
import Handlebars from 'handlebars'
|
|
16
|
+
import {
|
|
17
|
+
OperationObject,
|
|
18
|
+
ParameterObject,
|
|
19
|
+
ReferenceObject,
|
|
20
|
+
RequestBodyObject,
|
|
21
|
+
SchemaObject,
|
|
22
|
+
} from 'openapi3-ts/oas30'
|
|
23
|
+
import path from 'path'
|
|
24
|
+
import {
|
|
25
|
+
DEFAULT_SCHEMA_TITLE,
|
|
26
|
+
K6_SCRIPT_TEMPLATE,
|
|
27
|
+
SAMPLE_K6_SCRIPT_FILE_NAME,
|
|
28
|
+
} from '../constants'
|
|
29
|
+
import { getDirectoryForPath, getGeneratedClientPath } from '../helper'
|
|
30
|
+
import { logger } from '../logger'
|
|
31
|
+
import { generateTitle } from './k6Client'
|
|
32
|
+
|
|
33
|
+
function getExampleValueForSchema(
|
|
34
|
+
schema: SchemaObject | ReferenceObject,
|
|
35
|
+
context: ContextSpecs
|
|
36
|
+
) {
|
|
37
|
+
// Handle $ref
|
|
38
|
+
if ('$ref' in schema) {
|
|
39
|
+
const { schema: resolvedSchema } = resolveRef(schema, context)
|
|
40
|
+
return getExampleValueForSchema(resolvedSchema as SchemaObject, context)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if ('example' in schema) {
|
|
44
|
+
return `'${schema.example}'`
|
|
45
|
+
}
|
|
46
|
+
let schemaType = schema.type
|
|
47
|
+
if (Array.isArray(schemaType)) {
|
|
48
|
+
schemaType = schemaType[0]
|
|
49
|
+
}
|
|
50
|
+
if (!schemaType) {
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
const enumValues = schema.enum
|
|
54
|
+
switch (schemaType) {
|
|
55
|
+
case 'string':
|
|
56
|
+
return enumValues ? `'${enumValues[0]}'` : `'${faker.word.sample()}'`
|
|
57
|
+
case 'number':
|
|
58
|
+
return enumValues ? enumValues[0] : faker.number.int()
|
|
59
|
+
case 'integer':
|
|
60
|
+
return enumValues ? enumValues[0] : faker.number.int()
|
|
61
|
+
case 'boolean':
|
|
62
|
+
return enumValues ? enumValues[0] : faker.datatype.boolean()
|
|
63
|
+
case 'array':
|
|
64
|
+
return '[]'
|
|
65
|
+
case 'object': {
|
|
66
|
+
let objectString = '{\n'
|
|
67
|
+
for (const property in schema.properties) {
|
|
68
|
+
if (schema.properties[property]) {
|
|
69
|
+
const propertyValue = getExampleValueForSchema(
|
|
70
|
+
schema.properties[property],
|
|
71
|
+
context
|
|
72
|
+
)
|
|
73
|
+
objectString += `${property}: ${propertyValue},\n`
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
objectString += '\n}'
|
|
78
|
+
return objectString
|
|
79
|
+
}
|
|
80
|
+
default:
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getExampleValues(
|
|
86
|
+
requiredProps: GeneratorVerbOptions['props'],
|
|
87
|
+
originalOperation: OperationObject,
|
|
88
|
+
context: ContextSpecs
|
|
89
|
+
): string {
|
|
90
|
+
let exampleValues = ''
|
|
91
|
+
for (const prop of requiredProps) {
|
|
92
|
+
const propType = prop.type as GetterPropType
|
|
93
|
+
|
|
94
|
+
switch (propType) {
|
|
95
|
+
case GetterPropType.QUERY_PARAM: {
|
|
96
|
+
let exampleValue = '{\n'
|
|
97
|
+
for (const param of originalOperation.parameters || []) {
|
|
98
|
+
let resolvedParam: ParameterObject | ReferenceObject
|
|
99
|
+
|
|
100
|
+
if ('$ref' in param) {
|
|
101
|
+
const { schema: resolvedSchema } = resolveRef<ParameterObject>(
|
|
102
|
+
param,
|
|
103
|
+
context
|
|
104
|
+
)
|
|
105
|
+
resolvedParam = resolvedSchema
|
|
106
|
+
} else {
|
|
107
|
+
resolvedParam = param
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Only add required query parameters to the example values
|
|
111
|
+
if (resolvedParam.required && resolvedParam.in === 'query') {
|
|
112
|
+
if ('schema' in resolvedParam && resolvedParam.schema) {
|
|
113
|
+
exampleValue += `'${resolvedParam.name}': ${getExampleValueForSchema(resolvedParam.schema, context)},\n`
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exampleValue += '\n}'
|
|
118
|
+
exampleValues += `params = ${exampleValue};\n`
|
|
119
|
+
break
|
|
120
|
+
}
|
|
121
|
+
case GetterPropType.HEADER: {
|
|
122
|
+
let exampleValue = '{\n'
|
|
123
|
+
for (const param of originalOperation.parameters || []) {
|
|
124
|
+
let resolvedParam: ParameterObject | ReferenceObject
|
|
125
|
+
|
|
126
|
+
if ('$ref' in param) {
|
|
127
|
+
const { schema: resolvedSchema } = resolveRef<ParameterObject>(
|
|
128
|
+
param,
|
|
129
|
+
context
|
|
130
|
+
)
|
|
131
|
+
resolvedParam = resolvedSchema
|
|
132
|
+
} else {
|
|
133
|
+
resolvedParam = param
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Only add required query parameters to the example values
|
|
137
|
+
if (resolvedParam.required && resolvedParam.in === 'header') {
|
|
138
|
+
if ('schema' in resolvedParam && resolvedParam.schema) {
|
|
139
|
+
exampleValue += `'${resolvedParam.name}': ${getExampleValueForSchema(resolvedParam.schema, context)},\n`
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exampleValue += '\n}'
|
|
144
|
+
exampleValues += `headers = ${exampleValue};\n`
|
|
145
|
+
break
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
case GetterPropType.PARAM: {
|
|
149
|
+
let example, paramSchema: SchemaObject | ReferenceObject | undefined
|
|
150
|
+
|
|
151
|
+
for (const parameter of originalOperation.parameters || []) {
|
|
152
|
+
if ('name' in parameter) {
|
|
153
|
+
paramSchema = parameter.schema as SchemaObject
|
|
154
|
+
break
|
|
155
|
+
} else if ('$ref' in parameter) {
|
|
156
|
+
const { schema: resolvedSchema } = resolveRef<ParameterObject>(
|
|
157
|
+
parameter,
|
|
158
|
+
context
|
|
159
|
+
)
|
|
160
|
+
paramSchema = resolvedSchema.schema
|
|
161
|
+
break
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (paramSchema) {
|
|
166
|
+
example = getExampleValueForSchema(paramSchema, context)
|
|
167
|
+
}
|
|
168
|
+
if (example) {
|
|
169
|
+
exampleValues += `${prop.name} = ${example};\n`
|
|
170
|
+
}
|
|
171
|
+
break
|
|
172
|
+
}
|
|
173
|
+
case GetterPropType.BODY: {
|
|
174
|
+
// Generate example value from body schema
|
|
175
|
+
const requestBody = originalOperation.requestBody
|
|
176
|
+
let requestBodyExample
|
|
177
|
+
if (!requestBody) {
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
let resolvedSchema
|
|
181
|
+
if ('$ref' in requestBody) {
|
|
182
|
+
const { schema } = resolveRef<RequestBodyObject>(requestBody, context)
|
|
183
|
+
resolvedSchema = schema
|
|
184
|
+
} else if ('content' in requestBody) {
|
|
185
|
+
resolvedSchema = requestBody
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (resolvedSchema && 'content' in resolvedSchema) {
|
|
189
|
+
// Get the first available content type
|
|
190
|
+
const contentType = Object.keys(resolvedSchema.content)[0]
|
|
191
|
+
if (contentType) {
|
|
192
|
+
const requestBodySchema =
|
|
193
|
+
resolvedSchema.content[contentType]?.schema
|
|
194
|
+
if (requestBodySchema) {
|
|
195
|
+
requestBodyExample = getExampleValueForSchema(
|
|
196
|
+
requestBodySchema,
|
|
197
|
+
context
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (requestBodyExample) {
|
|
203
|
+
exampleValues += `${prop.name} = ${requestBodyExample};\n`
|
|
204
|
+
}
|
|
205
|
+
break
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return exampleValues
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getClientClassName(identifier: string) {
|
|
213
|
+
return generateTitle(pascal(identifier))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getClientObjectName(identifier: string) {
|
|
217
|
+
return camel(generateTitle(pascal(identifier)))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export const k6ScriptBuilder: ClientExtraFilesBuilder = async (
|
|
221
|
+
verbOptions: Record<string, GeneratorVerbOptions>,
|
|
222
|
+
output: NormalizedOutputOptions,
|
|
223
|
+
context: ContextSpecs
|
|
224
|
+
): Promise<ClientFileBuilder[]> => {
|
|
225
|
+
const schemaTitle =
|
|
226
|
+
context.specs[context.specKey]?.info.title || DEFAULT_SCHEMA_TITLE
|
|
227
|
+
const {
|
|
228
|
+
path: pathOfGeneratedClient,
|
|
229
|
+
filename,
|
|
230
|
+
extension,
|
|
231
|
+
} = await getGeneratedClientPath(output.target!, schemaTitle)
|
|
232
|
+
const directoryPath = getDirectoryForPath(pathOfGeneratedClient)
|
|
233
|
+
const generateScriptPath = path.join(
|
|
234
|
+
directoryPath,
|
|
235
|
+
SAMPLE_K6_SCRIPT_FILE_NAME
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
logger.debug(
|
|
239
|
+
`k6ScriptBuilder ~ Generating sample K6 Script\n${JSON.stringify(
|
|
240
|
+
{
|
|
241
|
+
pathOfGeneratedClient,
|
|
242
|
+
filename,
|
|
243
|
+
extension,
|
|
244
|
+
schemaTitle,
|
|
245
|
+
directoryPath,
|
|
246
|
+
generateScriptPath,
|
|
247
|
+
},
|
|
248
|
+
null,
|
|
249
|
+
2
|
|
250
|
+
)}`
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
const clientFunctionsList = []
|
|
254
|
+
const uniqueVariables = new Set<string>() // Track unique variable names
|
|
255
|
+
const allUniqueTags = new Set<string>()
|
|
256
|
+
|
|
257
|
+
for (const verbOption of Object.values(verbOptions)) {
|
|
258
|
+
if (verbOption.tags && verbOption.tags.length > 0) {
|
|
259
|
+
verbOption.tags.forEach((tag) => allUniqueTags.add(tag))
|
|
260
|
+
} else {
|
|
261
|
+
allUniqueTags.add('default')
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let clientObjectName
|
|
265
|
+
if (output.mode === 'tags') {
|
|
266
|
+
clientObjectName = getClientObjectName(verbOption.tags[0] || 'default')
|
|
267
|
+
} else {
|
|
268
|
+
clientObjectName = getClientObjectName(schemaTitle)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const { operationName, summary, props, originalOperation } = verbOption
|
|
272
|
+
const requiredProps = props.filter((prop) => prop.required)
|
|
273
|
+
// Create example values object
|
|
274
|
+
const exampleValues = getExampleValues(
|
|
275
|
+
requiredProps,
|
|
276
|
+
originalOperation,
|
|
277
|
+
context
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
for (const prop of requiredProps) {
|
|
281
|
+
uniqueVariables.add(prop.name)
|
|
282
|
+
}
|
|
283
|
+
clientFunctionsList.push({
|
|
284
|
+
operationName,
|
|
285
|
+
summary,
|
|
286
|
+
exampleValues,
|
|
287
|
+
requiredParametersString: toObjectString(requiredProps, 'name'),
|
|
288
|
+
clientObjectName,
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
let importStatements = ''
|
|
293
|
+
let clientInitializationStatement = ''
|
|
294
|
+
|
|
295
|
+
if (output.mode === 'tags') {
|
|
296
|
+
for (const tag of allUniqueTags) {
|
|
297
|
+
const { extension } = await getGeneratedClientPath(
|
|
298
|
+
output.target!,
|
|
299
|
+
schemaTitle
|
|
300
|
+
)
|
|
301
|
+
const clientName = getClientClassName(tag)
|
|
302
|
+
importStatements += `import { ${clientName} } from './${kebab(tag)}${extension}';\n`
|
|
303
|
+
clientInitializationStatement += `const ${getClientObjectName(tag)} = new ${clientName}({ baseUrl });\n`
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
const clientName = getClientClassName(schemaTitle)
|
|
307
|
+
importStatements = `import { ${clientName} } from './${filename}${extension}';\n`
|
|
308
|
+
clientInitializationStatement = `const ${getClientObjectName(schemaTitle)} = new ${clientName}({ baseUrl });\n`
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const scriptContentData = {
|
|
312
|
+
clientFunctionsList,
|
|
313
|
+
variableDefinition:
|
|
314
|
+
uniqueVariables.size > 0
|
|
315
|
+
? `let ${Array.from(uniqueVariables).join(', ')};`
|
|
316
|
+
: '',
|
|
317
|
+
importStatements,
|
|
318
|
+
clientInitializationStatement,
|
|
319
|
+
}
|
|
320
|
+
const template = Handlebars.compile(K6_SCRIPT_TEMPLATE)
|
|
321
|
+
|
|
322
|
+
return [
|
|
323
|
+
{
|
|
324
|
+
path: generateScriptPath,
|
|
325
|
+
content: template(scriptContentData),
|
|
326
|
+
},
|
|
327
|
+
]
|
|
328
|
+
}
|