@grafana/openapi-to-k6 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/.github/workflows/publish.yaml +2 -2
  2. package/.github/workflows/tests.yaml +14 -6
  3. package/README.md +54 -14
  4. package/dist/analytics.js +2 -1
  5. package/dist/cli.js +20 -6
  6. package/dist/constants.js +8 -2
  7. package/dist/{generator.js → generator/index.js} +7 -13
  8. package/dist/{k6SdkClient.js → generator/k6Client.js} +148 -161
  9. package/examples/basic_schema/single/k6-script.sample.ts +11 -0
  10. package/examples/basic_schema/single/simpleAPI.ts +87 -0
  11. package/examples/basic_schema/split/k6-script.sample.ts +11 -0
  12. package/examples/basic_schema/split/simpleAPI.schemas.ts +9 -0
  13. package/examples/basic_schema/split/simpleAPI.ts +85 -0
  14. package/examples/basic_schema/tags/default.ts +85 -0
  15. package/examples/basic_schema/tags/k6-script.sample.ts +11 -0
  16. package/examples/basic_schema/tags/simpleAPI.schemas.ts +9 -0
  17. package/examples/form_data_schema/single/formDataAPI.ts +115 -0
  18. package/examples/form_data_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  19. package/examples/form_data_schema/split/formDataAPI.schemas.ts +24 -0
  20. package/examples/form_data_schema/split/formDataAPI.ts +98 -0
  21. package/examples/form_data_schema/split/k6-script.sample.ts +11 -0
  22. package/examples/form_data_schema/tags/default.ts +98 -0
  23. package/examples/form_data_schema/tags/formDataAPI.schemas.ts +24 -0
  24. package/examples/form_data_schema/tags/k6-script.sample.ts +11 -0
  25. package/examples/form_url_encoded_data_schema/single/formURLEncodedAPI.ts +112 -0
  26. package/examples/form_url_encoded_data_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  27. package/examples/form_url_encoded_data_schema/split/formURLEncodedAPI.schemas.ts +24 -0
  28. package/examples/form_url_encoded_data_schema/split/formURLEncodedAPI.ts +98 -0
  29. package/examples/form_url_encoded_data_schema/split/k6-script.sample.ts +11 -0
  30. package/examples/form_url_encoded_data_schema/tags/default.ts +98 -0
  31. package/examples/form_url_encoded_data_schema/tags/formURLEncodedAPI.schemas.ts +24 -0
  32. package/examples/form_url_encoded_data_schema/tags/k6-script.sample.ts +11 -0
  33. package/examples/form_url_encoded_data_with_query_params_schema/single/formURLEncodedAPIWithQueryParameters.ts +128 -0
  34. package/examples/form_url_encoded_data_with_query_params_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  35. package/examples/form_url_encoded_data_with_query_params_schema/split/formURLEncodedAPIWithQueryParameters.schemas.ts +35 -0
  36. package/examples/form_url_encoded_data_with_query_params_schema/split/formURLEncodedAPIWithQueryParameters.ts +104 -0
  37. package/examples/form_url_encoded_data_with_query_params_schema/split/k6-script.sample.ts +14 -0
  38. package/examples/form_url_encoded_data_with_query_params_schema/tags/default.ts +104 -0
  39. package/examples/form_url_encoded_data_with_query_params_schema/tags/formURLEncodedAPIWithQueryParameters.schemas.ts +35 -0
  40. package/examples/form_url_encoded_data_with_query_params_schema/tags/k6-script.sample.ts +14 -0
  41. package/examples/get_request_with_path_parameters_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  42. package/examples/get_request_with_path_parameters_schema/single/simpleAPI.ts +94 -0
  43. package/examples/get_request_with_path_parameters_schema/split/k6-script.sample.ts +11 -0
  44. package/examples/get_request_with_path_parameters_schema/split/simpleAPI.schemas.ts +12 -0
  45. package/examples/get_request_with_path_parameters_schema/split/simpleAPI.ts +90 -0
  46. package/examples/get_request_with_path_parameters_schema/tags/default.ts +90 -0
  47. package/examples/get_request_with_path_parameters_schema/tags/k6-script.sample.ts +11 -0
  48. package/examples/get_request_with_path_parameters_schema/tags/simpleAPI.schemas.ts +12 -0
  49. package/examples/headers_schema/single/headerDemoAPI.ts +202 -0
  50. package/examples/headers_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  51. package/examples/headers_schema/split/headerDemoAPI.schemas.ts +32 -0
  52. package/examples/headers_schema/split/headerDemoAPI.ts +184 -0
  53. package/examples/headers_schema/split/k6-script.sample.ts +25 -0
  54. package/examples/headers_schema/tags/default.ts +182 -0
  55. package/examples/headers_schema/tags/headerDemoAPI.schemas.ts +32 -0
  56. package/examples/headers_schema/tags/k6-script.sample.ts +25 -0
  57. package/examples/no_title_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  58. package/examples/no_title_schema/single/k6Client.ts +87 -0
  59. package/examples/{basic_schema → no_title_schema/split}/k6-script.sample.ts +2 -2
  60. package/examples/no_title_schema/split/k6Client.schemas.ts +9 -0
  61. package/examples/no_title_schema/split/k6Client.ts +85 -0
  62. package/examples/no_title_schema/tags/default.ts +85 -0
  63. package/examples/no_title_schema/tags/k6-script.sample.ts +11 -0
  64. package/examples/no_title_schema/tags/k6Client.schemas.ts +9 -0
  65. package/examples/post_request_with_query_params/single/exampleAPI.ts +126 -0
  66. package/examples/post_request_with_query_params/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  67. package/examples/post_request_with_query_params/split/exampleAPI.schemas.ts +33 -0
  68. package/examples/post_request_with_query_params/split/exampleAPI.ts +105 -0
  69. package/examples/post_request_with_query_params/split/k6-script.sample.ts +14 -0
  70. package/examples/post_request_with_query_params/tags/default.ts +105 -0
  71. package/examples/post_request_with_query_params/tags/exampleAPI.schemas.ts +33 -0
  72. package/examples/post_request_with_query_params/tags/k6-script.sample.ts +14 -0
  73. package/examples/query_params_schema/single/exampleAPI.ts +120 -0
  74. package/examples/query_params_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  75. package/examples/query_params_schema/split/exampleAPI.schemas.ts +37 -0
  76. package/examples/query_params_schema/split/exampleAPI.ts +94 -0
  77. package/examples/query_params_schema/split/k6-script.sample.ts +11 -0
  78. package/examples/query_params_schema/tags/default.ts +94 -0
  79. package/examples/query_params_schema/tags/exampleAPI.schemas.ts +37 -0
  80. package/examples/query_params_schema/tags/k6-script.sample.ts +11 -0
  81. package/examples/simple_post_request_schema/{exampleAPI.ts → single/exampleAPI.ts} +49 -49
  82. package/examples/simple_post_request_schema/{k6-script.sample.ts → single/k6-script.sample.ts} +2 -2
  83. package/examples/simple_post_request_schema/split/exampleAPI.schemas.ts +47 -0
  84. package/examples/simple_post_request_schema/split/exampleAPI.ts +99 -0
  85. package/examples/simple_post_request_schema/split/k6-script.sample.ts +13 -0
  86. package/examples/simple_post_request_schema/tags/default.ts +99 -0
  87. package/examples/simple_post_request_schema/tags/exampleAPI.schemas.ts +47 -0
  88. package/examples/simple_post_request_schema/tags/k6-script.sample.ts +13 -0
  89. package/images/openapi-to-k6.png +0 -0
  90. package/package.json +2 -2
  91. package/src/analytics.ts +3 -1
  92. package/src/cli.ts +34 -8
  93. package/src/constants.ts +7 -1
  94. package/src/{generator.ts → generator/index.ts} +8 -21
  95. package/src/{k6SdkClient.ts → generator/k6Client.ts} +174 -222
  96. package/src/type.d.ts +4 -4
  97. package/tests/e2e/schema.json +8 -0
  98. package/tests/e2e/{k6Script.ts → single/k6Script.ts} +7 -2
  99. package/tests/e2e/split/k6Script.ts +82 -0
  100. package/tests/e2e/tags/k6Script.ts +106 -0
  101. package/tests/functional-tests/fixtures/schemas/basic_schema.json +1 -4
  102. package/tests/functional-tests/fixtures/schemas/form_data_schema.json +4 -4
  103. package/tests/functional-tests/fixtures/schemas/form_url_encoded_data_schema.json +3 -3
  104. package/tests/functional-tests/fixtures/schemas/form_url_encoded_data_with_query_params_schema.json +2 -2
  105. package/tests/functional-tests/fixtures/schemas/get_request_with_path_parameters_schema.json +2 -2
  106. package/tests/functional-tests/fixtures/schemas/headers_schema.json +7 -8
  107. package/tests/functional-tests/fixtures/schemas/no_title_schema.json +2 -5
  108. package/tests/functional-tests/fixtures/schemas/post_request_with_query_params.json +3 -4
  109. package/tests/functional-tests/fixtures/schemas/query_params_schema.json +3 -3
  110. package/tests/functional-tests/fixtures/schemas/simple_post_request_schema.json +3 -5
  111. package/tests/functional-tests/generator.test.ts +46 -5
  112. package/examples/basic_schema/simpleAPI.ts +0 -87
  113. package/examples/form_data_schema/formDataAPI.ts +0 -115
  114. package/examples/form_url_encoded_data_schema/formURLEncodedAPI.ts +0 -114
  115. package/examples/form_url_encoded_data_with_query_params_schema/formURLEncodedAPIWithQueryParameters.ts +0 -130
  116. package/examples/get_request_with_path_parameters_schema/simpleAPI.ts +0 -94
  117. package/examples/headers_schema/headerDemoAPI.ts +0 -196
  118. package/examples/no_title_schema/K6Client.ts +0 -86
  119. package/examples/post_request_with_query_params/exampleAPI.ts +0 -124
  120. package/examples/query_params_schema/exampleAPI.ts +0 -118
  121. package/examples/update_examples.sh +0 -21
@@ -2,15 +2,15 @@ import fs from 'fs'
2
2
  import { InfoObject } from 'openapi3-ts/oas30'
3
3
  import orval from 'orval'
4
4
  import path from 'path'
5
- import { DEFAULT_SCHEMA_TITLE } from './constants'
5
+ import { DEFAULT_SCHEMA_TITLE } from '../constants'
6
6
  import {
7
7
  formatFileWithPrettier,
8
8
  getPackageDetails,
9
9
  OutputOverrider,
10
- } from './helper'
11
- import { getK6ClientBuilder } from './k6SdkClient'
12
- import { logger } from './logger'
13
- import { GenerateK6SDKOptions, SchemaDetails } from './type'
10
+ } from '../helper'
11
+ import { logger } from '../logger'
12
+ import { GenerateK6SDKOptions } from '../type'
13
+ import { getK6ClientBuilder } from './k6Client'
14
14
 
15
15
  const outputOverrider = OutputOverrider.getInstance()
16
16
  const packageDetails = getPackageDetails()
@@ -49,11 +49,8 @@ export default async ({
49
49
  outputDir,
50
50
  shouldGenerateSampleK6Script,
51
51
  analyticsData,
52
+ mode,
52
53
  }: GenerateK6SDKOptions) => {
53
- const schemaDetails: SchemaDetails = {
54
- title: '',
55
- }
56
-
57
54
  /**
58
55
  * Note!
59
56
  * 1. override.requestOptions is not supported for the custom K6 client
@@ -64,13 +61,9 @@ export default async ({
64
61
  input: openApiPath,
65
62
  output: {
66
63
  target: outputDir,
67
- mode: 'single',
64
+ mode: mode,
68
65
  client: () =>
69
- getK6ClientBuilder(
70
- schemaDetails,
71
- shouldGenerateSampleK6Script,
72
- analyticsData
73
- ),
66
+ getK6ClientBuilder(shouldGenerateSampleK6Script, analyticsData),
74
67
  override: {
75
68
  header: generatedFileHeaderGenerator,
76
69
  },
@@ -81,10 +74,4 @@ export default async ({
81
74
  },
82
75
  })
83
76
  })
84
-
85
- if (!schemaDetails.title) {
86
- logger.warning(
87
- 'Could not find schema title in the OpenAPI spec. Please provide a `title` in the schema in `info` block to generate proper file names'
88
- )
89
- }
90
77
  }
@@ -8,18 +8,14 @@ import {
8
8
  ContextSpecs,
9
9
  generateFormDataAndUrlEncodedFunction,
10
10
  generateVerbImports,
11
- GeneratorMutator,
12
11
  GeneratorOptions,
13
12
  GeneratorSchema,
14
13
  GeneratorVerbOptions,
15
14
  GetterBody,
16
- GetterQueryParam,
17
15
  GetterResponse,
18
- ParamsSerializerOptions,
19
16
  pascal,
20
17
  sanitize,
21
18
  toObjectString,
22
- Verbs,
23
19
  } from '@orval/core'
24
20
  import Handlebars from 'handlebars'
25
21
  import path from 'path'
@@ -27,16 +23,144 @@ import {
27
23
  DEFAULT_SCHEMA_TITLE,
28
24
  K6_SCRIPT_TEMPLATE,
29
25
  SAMPLE_K6_SCRIPT_FILE_NAME,
30
- } from './constants'
31
- import { getDirectoryForPath, getGeneratedClientPath } from './helper'
32
- import { logger } from './logger'
33
- import { AnalyticsData, SchemaDetails } from './type'
26
+ } from '../constants'
27
+ import { getDirectoryForPath, getGeneratedClientPath } from '../helper'
28
+ import { logger } from '../logger'
29
+ import { AnalyticsData } from '../type'
30
+
31
+ /**
32
+ * In case the supplied schema does not have a title set, it will set the default title to ensure
33
+ * proper client generation
34
+ *
35
+ * @param context - The context object containing the schema details
36
+ */
37
+ function _setDefaultSchemaTitle(context: ContextSpecs) {
38
+ const schemaDetails = context.specs[context.specKey]
39
+ if (schemaDetails && !schemaDetails.info.title) {
40
+ schemaDetails.info.title = DEFAULT_SCHEMA_TITLE
41
+ }
42
+ }
43
+
44
+ function _generateResponseTypeDefinition(response: GetterResponse): string {
45
+ let responseDataType = ''
46
+
47
+ if (
48
+ response.definition.success &&
49
+ !['any', 'unknown'].includes(response.definition.success)
50
+ ) {
51
+ responseDataType += response.definition.success
52
+ } else {
53
+ responseDataType += 'ResponseBody'
54
+ }
55
+
56
+ return `{
57
+ response: Response
58
+ data: ${responseDataType}
59
+ }`
60
+ }
61
+
62
+ function _getRequestParametersMergerFunctionImplementation() {
63
+ return `/**
64
+ * Merges the provided request parameters with default parameters for the client.
65
+ *
66
+ * @param {Params} requestParameters - The parameters provided specifically for the request
67
+ * @param {Params} commonRequestParameters - Common parameters for all requests
68
+ * @returns {Params} - The merged parameters
69
+ */
70
+ private _mergeRequestParameters (requestParameters?: Params, commonRequestParameters?: Params): Params {
71
+ return {
72
+ ...commonRequestParameters, // Default to common parameters
73
+ ...requestParameters, // Override with request-specific parameters
74
+ headers: {
75
+ ...commonRequestParameters?.headers || {}, // Ensure headers are defined
76
+ ...requestParameters?.headers || {},
77
+ },
78
+ cookies: {
79
+ ...commonRequestParameters?.cookies || {}, // Ensure cookies are defined
80
+ ...requestParameters?.cookies || {},
81
+ },
82
+ tags: {
83
+ ...commonRequestParameters?.tags || {}, // Ensure tags are defined
84
+ ...requestParameters?.tags || {},
85
+ },
86
+ };
87
+ };`
88
+ }
89
+
90
+ const _getRequestParamsValue = ({
91
+ response,
92
+ queryParams,
93
+ headers,
94
+ body,
95
+ }: {
96
+ response: GetterResponse
97
+ body: GetterBody
98
+ queryParams?: GeneratorSchema
99
+ headers?: GeneratorSchema
100
+ }) => {
101
+ if (!queryParams && !headers && !response.isBlob && !body.contentType) {
102
+ // No parameters to merge, return the request parameters directly
103
+ return 'mergedRequestParameters'
104
+ }
34
105
 
35
- // A map to store the operationNames for which a return type is to be written at the end to export
36
- // and the return type definition
37
- const returnTypesToWrite: Map<string, string> = new Map()
106
+ let value = '\n ...mergedRequestParameters,'
38
107
 
39
- export const getK6Dependencies: ClientDependenciesBuilder = () => [
108
+ if (response.isBlob) {
109
+ value += `\n responseType: 'binary',`
110
+ }
111
+ // Expand the headers
112
+ if (body.contentType || headers) {
113
+ let headersValue = `\n headers: {`
114
+ if (body.contentType) {
115
+ if (body.formData) {
116
+ headersValue += `\n'Content-Type': '${body.contentType}; boundary=' + formData.boundary,`
117
+ } else {
118
+ headersValue += `\n'Content-Type': '${body.contentType}',`
119
+ }
120
+ }
121
+
122
+ if (headers) {
123
+ headersValue += `\n// In the schema, headers can be of any type like number but k6 accepts only strings as headers, hence converting all headers to string`
124
+ headersValue += `\n...Object.fromEntries(Object.entries(headers || {}).map(([key, value]) => [key, String(value)])),`
125
+ }
126
+
127
+ headersValue += `\n...mergedRequestParameters?.headers},`
128
+ value += headersValue
129
+ }
130
+
131
+ return `{${value}}`
132
+ }
133
+
134
+ const _getK6RequestOptions = (verbOptions: GeneratorVerbOptions) => {
135
+ const { body, headers, queryParams, response, verb } = verbOptions
136
+ let fetchBodyOption = 'undefined'
137
+
138
+ if (body.formData) {
139
+ // Use the FormData.body() method to get the body of the request
140
+ fetchBodyOption = 'formData.body()'
141
+ } else if (body.formUrlEncoded || body.implementation) {
142
+ fetchBodyOption = `JSON.stringify(${body.implementation})`
143
+ }
144
+
145
+ // Generate the params input for the call
146
+
147
+ const requestParametersValue = _getRequestParamsValue({
148
+ response,
149
+ body,
150
+ headers: headers?.schema,
151
+ queryParams: queryParams?.schema,
152
+ })
153
+
154
+ // Sample output
155
+ // 'GET', 'http://test.com/route', <body>, <options>
156
+
157
+ return `"${verb.toUpperCase()}",
158
+ url.toString(),
159
+ ${fetchBodyOption},
160
+ ${requestParametersValue}`
161
+ }
162
+
163
+ const getK6Dependencies: ClientDependenciesBuilder = () => [
40
164
  {
41
165
  exports: [
42
166
  {
@@ -81,59 +205,21 @@ export const getK6Dependencies: ClientDependenciesBuilder = () => [
81
205
  },
82
206
  ]
83
207
 
84
- function getSchemaTitleFromContext(context: ContextSpecs) {
85
- const specData = Object.values(context.specs)
86
-
87
- let schemaTitle
88
-
89
- if (specData[0]) {
90
- schemaTitle = specData[0].info.title
91
- }
92
-
93
- schemaTitle ??= DEFAULT_SCHEMA_TITLE
94
-
95
- return schemaTitle
96
- }
97
-
98
- function _generateResponseTypeName(operationName: string): string {
99
- return `${pascal(operationName)}Response`
100
- }
101
-
102
- function _generateResponseTypeDefinition(
103
- operationName: string,
104
- response: GetterResponse
105
- ): string {
106
- const typeName = _generateResponseTypeName(operationName)
107
- let responseDataType = ''
108
-
109
- if (response.definition.success) {
110
- responseDataType += response.definition.success + ' | '
111
- }
112
- responseDataType += 'ResponseBody'
113
-
114
- return `export type ${typeName} = {
115
- response: Response
116
- data: ${responseDataType}
117
- };`
118
- }
119
-
120
208
  const generateK6Implementation = (
121
- {
122
- headers,
209
+ verbOptions: GeneratorVerbOptions,
210
+ { route }: GeneratorOptions,
211
+ analyticsData?: AnalyticsData
212
+ ) => {
213
+ const {
123
214
  queryParams,
124
215
  operationName,
125
216
  response,
126
217
  body,
127
218
  props,
128
219
  verb,
129
- override,
130
220
  formData,
131
221
  formUrlEncoded,
132
- paramsSerializer,
133
- }: GeneratorVerbOptions,
134
- { route }: GeneratorOptions,
135
- analyticsData?: AnalyticsData
136
- ) => {
222
+ } = verbOptions
137
223
  if (analyticsData) {
138
224
  analyticsData.generatedRequestsCount[verb] += 1
139
225
  }
@@ -146,40 +232,24 @@ const generateK6Implementation = (
146
232
  isFormUrlEncoded: false,
147
233
  })
148
234
 
149
- // Generate response return types
150
- returnTypesToWrite.set(
151
- operationName,
152
- _generateResponseTypeDefinition(operationName, response)
153
- )
154
-
155
- let url = `cleanBaseUrl + \`${route}\``
235
+ let url = `this.cleanBaseUrl + \`${route}\``
156
236
 
157
237
  if (queryParams) {
158
238
  url += '+`?${new URLSearchParams(params).toString()}`'
159
239
  }
160
240
  const urlGeneration = `const url = new URL(${url});`
161
241
 
162
- const options = getK6RequestOptions({
163
- route,
164
- body,
165
- headers,
166
- queryParams,
167
- response,
168
- verb,
169
- requestOptions: override?.requestOptions,
170
- paramsSerializer,
171
- paramsSerializerOptions: override?.paramsSerializerOptions,
172
- })
242
+ const options = _getK6RequestOptions(verbOptions)
173
243
 
174
- return `const ${operationName} = (\n ${toObjectString(props, 'implementation')} requestParameters?: Params): ${_generateResponseTypeName(operationName)} => {${bodyForm}
244
+ return `${operationName}(\n ${toObjectString(props, 'implementation')} requestParameters?: Params): ${_generateResponseTypeDefinition(response)} {\n${bodyForm}
175
245
  ${urlGeneration}
176
- const mergedRequestParameters = _mergeRequestParameters(requestParameters || {}, clientOptions.commonRequestParameters);
246
+ const mergedRequestParameters = this._mergeRequestParameters(requestParameters || {}, this.commonRequestParameters);
177
247
  const response = http.request(${options});
178
248
  let data;
179
249
 
180
250
  try {
181
251
  data = response.json();
182
- } catch (error) {
252
+ } catch {
183
253
  data = response.body;
184
254
  }
185
255
  return {
@@ -190,154 +260,38 @@ const generateK6Implementation = (
190
260
  `
191
261
  }
192
262
 
193
- type OptionsInput = {
194
- route: string
195
- body: GetterBody
196
- headers?: GetterQueryParam
197
- queryParams?: GetterQueryParam
198
- response: GetterResponse
199
- verb: Verbs
200
- requestOptions?: object | boolean
201
- isVue?: boolean
202
- paramsSerializer?: GeneratorMutator
203
- paramsSerializerOptions?: ParamsSerializerOptions
204
- }
205
-
206
- const getParamsInputValue = ({
207
- response,
208
- queryParams,
209
- headers,
210
- body,
211
- }: {
212
- response: GetterResponse
213
- body: GetterBody
214
- queryParams?: GeneratorSchema
215
- headers?: GeneratorSchema
216
- }) => {
217
- if (!queryParams && !headers && !response.isBlob && !body.contentType) {
218
- // No parameters to merge, return the request parameters directly
219
- return 'mergedRequestParameters'
220
- }
221
-
222
- let value = '\n ...mergedRequestParameters,'
223
-
224
- if (response.isBlob) {
225
- value += `\n responseType: 'binary',`
226
- }
227
- // Expand the headers
228
- if (body.contentType || headers) {
229
- let headersValue = `\n headers: {`
230
- if (body.contentType) {
231
- if (body.formData) {
232
- headersValue += `\n'Content-Type': '${body.contentType}; boundary=' + formData.boundary,`
233
- } else {
234
- headersValue += `\n'Content-Type': '${body.contentType}',`
235
- }
236
- }
237
-
238
- if (headers) {
239
- headersValue += `\n...headers,`
240
- }
241
-
242
- headersValue += `\n...mergedRequestParameters?.headers},`
243
- value += headersValue
244
- }
245
-
246
- return `{${value}}`
247
- }
248
-
249
- const getK6RequestOptions = (options: OptionsInput) => {
250
- const { body, headers, queryParams, response, verb } = options
251
-
252
- let fetchBodyOption = 'undefined'
253
-
254
- if (body.formData) {
255
- // Use the FormData.body() method to get the body of the request
256
- fetchBodyOption = 'formData.body()'
257
- } else if (body.formUrlEncoded || body.implementation) {
258
- fetchBodyOption = `JSON.stringify(${body.implementation})`
259
- }
260
-
261
- // Generate the params input for the call
262
-
263
- const paramsValue = getParamsInputValue({
264
- response,
265
- body,
266
- headers: headers?.schema,
267
- queryParams: queryParams?.schema,
268
- })
269
-
270
- // Sample output
271
- // 'GET', 'http://test.com/route', <body>, <options>
272
-
273
- return `"${verb.toUpperCase()}",
274
- url.toString(),
275
- ${fetchBodyOption},
276
- ${paramsValue}`
277
- }
278
-
279
- function _getRequestParametersMergerFunctionImplementation() {
280
- return `/**
281
- * Merges the provided request parameters with default parameters for the client.
282
- *
283
- * @param {Params} requestParameters - The parameters provided specifically for the request
284
- * @param {Params} commonRequestParameters - Common parameters for all requests
285
- * @returns {Params} - The merged parameters
286
- */
287
- const _mergeRequestParameters = (requestParameters?: Params, commonRequestParameters?: Params): Params => {
288
- return {
289
- ...commonRequestParameters, // Default to common parameters
290
- ...requestParameters, // Override with request-specific parameters
291
- headers: {
292
- ...commonRequestParameters?.headers || {}, // Ensure headers are defined
293
- ...requestParameters?.headers || {},
294
- },
295
- cookies: {
296
- ...commonRequestParameters?.cookies || {}, // Ensure cookies are defined
297
- ...requestParameters?.cookies || {},
298
- },
299
- tags: {
300
- ...commonRequestParameters?.tags || {}, // Ensure tags are defined
301
- ...requestParameters?.tags || {},
302
- },
303
- };
304
- };`
305
- }
306
-
307
- export const generateTitle: ClientTitleBuilder = (title) => {
263
+ const generateTitle: ClientTitleBuilder = (title) => {
308
264
  const sanTitle = sanitize(title || DEFAULT_SCHEMA_TITLE)
309
- return `create${pascal(sanTitle)}`
265
+ return `${pascal(sanTitle)}Client`
310
266
  }
311
267
 
312
- export const generateK6Header: ClientHeaderBuilder = ({ title }) => {
313
- const clientOptionsTypeName = `${pascal(title)}Options`
268
+ const generateK6Header: ClientHeaderBuilder = ({ title }) => {
314
269
  return `
315
- export type ${clientOptionsTypeName} = {
270
+ /**
271
+ * This is the base client to use for interacting with the API.
272
+ */
273
+ export class ${title} {
274
+ private cleanBaseUrl: string;
275
+ private commonRequestParameters: Params;
276
+
277
+ constructor (clientOptions: {
316
278
  baseUrl: string,
317
279
  commonRequestParameters?: Params
318
- }
319
-
320
- /**
321
- * This is the base client to use for interacting with the API.
322
- */
323
- export const ${title} = (clientOptions: ${clientOptionsTypeName}) => {\n
324
- const cleanBaseUrl = clientOptions.baseUrl.replace(/\\/+$/, '');\n`
280
+ }) {
281
+ this.cleanBaseUrl = clientOptions.baseUrl.replace(/\\/+$/, '');\n
282
+ }\n
283
+ `
325
284
  }
326
285
 
327
- export const generateFooter: ClientFooterBuilder = ({ operationNames }) => {
328
- let footer = ''
286
+ const generateFooter: ClientFooterBuilder = () => {
287
+ // Add function definition for merging request parameters
288
+ const footer = `
329
289
 
330
- footer += `return {${operationNames.join(',')}}};\n\n`
290
+ ${_getRequestParametersMergerFunctionImplementation()}
331
291
 
332
- operationNames.forEach((operationName) => {
333
- if (returnTypesToWrite.has(operationName)) {
334
- footer += returnTypesToWrite.get(operationName) + '\n'
335
- }
336
- })
337
-
338
- // Add function definition for merging request parameters
339
- footer += `\n\n${_getRequestParametersMergerFunctionImplementation()}\n`
292
+ }
340
293
 
294
+ `
341
295
  return footer
342
296
  }
343
297
 
@@ -346,7 +300,8 @@ const k6ScriptBuilder: ClientExtraFilesBuilder = async (
346
300
  output,
347
301
  context
348
302
  ) => {
349
- const schemaTitle = getSchemaTitleFromContext(context)
303
+ const schemaTitle =
304
+ context.specs[context.specKey]?.info.title || DEFAULT_SCHEMA_TITLE
350
305
  const {
351
306
  path: pathOfGeneratedClient,
352
307
  filename,
@@ -400,21 +355,19 @@ const k6ScriptBuilder: ClientExtraFilesBuilder = async (
400
355
  ]
401
356
  }
402
357
 
403
- function getK6Client(
404
- schemaDetails: SchemaDetails,
405
- analyticsData?: AnalyticsData
406
- ) {
358
+ function getK6Client(analyticsData?: AnalyticsData) {
407
359
  return function (
408
360
  verbOptions: GeneratorVerbOptions,
409
361
  options: GeneratorOptions
410
362
  ) {
363
+ _setDefaultSchemaTitle(options.context)
364
+
411
365
  const imports = generateVerbImports(verbOptions)
412
366
  const implementation = generateK6Implementation(
413
367
  verbOptions,
414
368
  options,
415
369
  analyticsData
416
370
  )
417
- schemaDetails.title = getSchemaTitleFromContext(options.context)
418
371
  const specData = Object.values(options.context.specs)
419
372
  if (specData[0]) {
420
373
  if (analyticsData) {
@@ -427,12 +380,11 @@ function getK6Client(
427
380
  }
428
381
 
429
382
  export function getK6ClientBuilder(
430
- schemaDetails: SchemaDetails,
431
383
  shouldGenerateSampleK6Script?: boolean,
432
384
  analyticsData?: AnalyticsData
433
385
  ): ClientGeneratorsBuilder {
434
386
  return {
435
- client: getK6Client(schemaDetails, analyticsData),
387
+ client: getK6Client(analyticsData),
436
388
  header: generateK6Header,
437
389
  dependencies: getK6Dependencies,
438
390
  footer: generateFooter,
package/src/type.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Mode } from './constants'
2
+
1
3
  export interface PackageDetails {
2
4
  name: string
3
5
  commandName: string
@@ -5,10 +7,6 @@ export interface PackageDetails {
5
7
  version: string
6
8
  }
7
9
 
8
- export interface SchemaDetails {
9
- title: string
10
- }
11
-
12
10
  export interface AnalyticsData {
13
11
  generatedRequestsCount: {
14
12
  post: number
@@ -18,6 +16,7 @@ export interface AnalyticsData {
18
16
  patch: number
19
17
  head: number
20
18
  }
19
+ isSampleK6ScriptGenerated: boolean
21
20
  openApiSpecVersion: string
22
21
  toolVersion: string
23
22
  anonymousUserId: string
@@ -31,4 +30,5 @@ export interface GenerateK6SDKOptions {
31
30
  outputDir: string
32
31
  shouldGenerateSampleK6Script?: boolean
33
32
  analyticsData?: AnalyticsData
33
+ mode: Mode
34
34
  }
@@ -8,6 +8,7 @@
8
8
  "paths": {
9
9
  "/items/{id}": {
10
10
  "get": {
11
+ "tags": ["Items"],
11
12
  "summary": "Get an item by ID",
12
13
  "parameters": [
13
14
  {
@@ -37,6 +38,7 @@
37
38
  }
38
39
  },
39
40
  "post": {
41
+ "tags": ["Items"],
40
42
  "summary": "Create an item by ID",
41
43
  "parameters": [
42
44
  {
@@ -74,6 +76,7 @@
74
76
  }
75
77
  },
76
78
  "put": {
79
+ "tags": ["Items"],
77
80
  "summary": "Update an item by ID",
78
81
  "parameters": [
79
82
  {
@@ -111,6 +114,7 @@
111
114
  }
112
115
  },
113
116
  "patch": {
117
+ "tags": ["Items"],
114
118
  "summary": "Partially update an item by ID",
115
119
  "parameters": [
116
120
  {
@@ -145,6 +149,7 @@
145
149
  }
146
150
  },
147
151
  "delete": {
152
+ "tags": ["Items"],
148
153
  "summary": "Delete an item by ID",
149
154
  "parameters": [
150
155
  {
@@ -164,6 +169,7 @@
164
169
  }
165
170
  },
166
171
  "head": {
172
+ "tags": ["Items"],
167
173
  "summary": "Check if item exists",
168
174
  "parameters": [
169
175
  {
@@ -188,6 +194,7 @@
188
194
  },
189
195
  "/items-form-url-encoded": {
190
196
  "post": {
197
+ "tags": ["ItemsForm", "Items"],
191
198
  "summary": "Create an item using form-urlencoded data",
192
199
  "requestBody": {
193
200
  "required": true,
@@ -217,6 +224,7 @@
217
224
  },
218
225
  "/items-form-data": {
219
226
  "post": {
227
+ "tags": ["ItemsForm", "Items"],
220
228
  "summary": "Create an item using form-data",
221
229
  "requestBody": {
222
230
  "required": true,
@@ -1,10 +1,10 @@
1
1
  /* eslint-disable import/no-unresolved */
2
2
  import { check } from 'k6'
3
- import { createComprehensiveAPI } from './sdk.ts'
3
+ import { ComprehensiveAPIClient } from './sdk.ts'
4
4
  /* eslint-enable import/no-unresolved */
5
5
 
6
6
  const baseUrl = 'http://localhost:3000'
7
- const client = createComprehensiveAPI({ baseUrl })
7
+ const client = new ComprehensiveAPIClient({ baseUrl })
8
8
 
9
9
  export const options = {
10
10
  thresholds: {
@@ -74,4 +74,9 @@ export default function () {
74
74
  'multipart/form-data; boundary=---'
75
75
  ),
76
76
  })
77
+
78
+ const getItemsHeaderResponseData = client.getItemsHeader({
79
+ id: 'test',
80
+ })
81
+ checkResponseStatus(getItemsHeaderResponseData.response, 200)
77
82
  }