@grafana/openapi-to-k6 0.1.0 → 0.1.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 (51) hide show
  1. package/.eslintignore +5 -0
  2. package/.github/workflows/publish.yaml +3 -1
  3. package/.github/workflows/tests.yaml +20 -4
  4. package/.prettierignore +4 -0
  5. package/README.md +13 -0
  6. package/dist/generator.js +20 -1
  7. package/dist/helper.js +8 -32
  8. package/dist/k6SdkClient.js +13 -7
  9. package/dist/logger.js +3 -0
  10. package/examples/basic_schema/k6-script.sample.ts +11 -0
  11. package/examples/basic_schema/schema.json +32 -0
  12. package/examples/basic_schema/simpleAPI.ts +87 -0
  13. package/examples/form_data_schema/formDataAPI.ts +115 -0
  14. package/examples/form_data_schema/k6-script.sample.ts +11 -0
  15. package/examples/form_data_schema/schema.json +86 -0
  16. package/examples/form_url_encoded_data_schema/formURLEncodedAPI.ts +114 -0
  17. package/examples/form_url_encoded_data_schema/k6-script.sample.ts +11 -0
  18. package/examples/form_url_encoded_data_schema/schema.json +86 -0
  19. package/examples/form_url_encoded_data_with_query_params_schema/formURLEncodedAPIWithQueryParameters.ts +130 -0
  20. package/examples/form_url_encoded_data_with_query_params_schema/k6-script.sample.ts +14 -0
  21. package/examples/form_url_encoded_data_with_query_params_schema/schema.json +107 -0
  22. package/examples/get_request_with_path_parameters_schema/k6-script.sample.ts +11 -0
  23. package/examples/get_request_with_path_parameters_schema/schema.json +57 -0
  24. package/examples/get_request_with_path_parameters_schema/simpleAPI.ts +94 -0
  25. package/examples/headers_schema/headerDemoAPI.ts +196 -0
  26. package/examples/headers_schema/k6-script.sample.ts +25 -0
  27. package/examples/headers_schema/schema.json +148 -0
  28. package/examples/no_title_schema/K6Client.ts +86 -0
  29. package/examples/no_title_schema/k6-script.sample.ts +11 -0
  30. package/examples/no_title_schema/schema.json +31 -0
  31. package/examples/post_request_with_query_params/exampleAPI.ts +124 -0
  32. package/examples/post_request_with_query_params/k6-script.sample.ts +14 -0
  33. package/examples/post_request_with_query_params/schema.json +86 -0
  34. package/examples/query_params_schema/exampleAPI.ts +118 -0
  35. package/examples/query_params_schema/k6-script.sample.ts +11 -0
  36. package/examples/query_params_schema/schema.json +105 -0
  37. package/examples/simple_post_request_schema/exampleAPI.ts +135 -0
  38. package/examples/simple_post_request_schema/k6-script.sample.ts +13 -0
  39. package/examples/simple_post_request_schema/schema.json +122 -0
  40. package/examples/update_examples.sh +21 -0
  41. package/jest.config.js +1 -0
  42. package/package.json +2 -1
  43. package/src/generator.ts +26 -7
  44. package/src/helper.ts +10 -45
  45. package/src/k6SdkClient.ts +22 -14
  46. package/src/logger.ts +4 -0
  47. package/tests/functional-tests/fixtures/schemas/no_title_schema.json +1 -1
  48. package/tests/functional-tests/fixtures/schemas/query_params_schema.json +1 -1
  49. package/tests/functional-tests/generator.test.ts +72 -32
  50. package/tests/helper.test.ts +0 -31
  51. package/tsconfig.json +1 -1
package/.eslintignore ADDED
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ README.md
3
+ package.json
4
+ package-lock.json
5
+ examples/
@@ -24,11 +24,13 @@ jobs:
24
24
  run: |
25
25
  NEW_VERSION=${{ github.event.release.tag_name }}
26
26
  npm version $NEW_VERSION --no-git-tag-version
27
+ - name: Update generated examples
28
+ run: npm run update-examples
27
29
  - name: Commit updated package.json
28
30
  run: |
29
31
  git config --global user.name 'github-actions[bot]'
30
32
  git config --global user.email 'github-actions[bot]@users.noreply.github.com'
31
- git add package.json package-lock.json
33
+ git add package.json package-lock.json examples/
32
34
  git commit -m "Update package.json version to ${{ github.event.release.tag_name }}"
33
35
  git push origin HEAD:main
34
36
  - run: npm run build
@@ -3,10 +3,7 @@ name: Run Tests
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - main
7
- pull_request:
8
- branches:
9
- - main
6
+ - "**"
10
7
 
11
8
  jobs:
12
9
  test:
@@ -41,3 +38,22 @@ jobs:
41
38
  path: './tests/e2e/k6Script.ts'
42
39
  flags: '--compatibility-mode=experimental_enhanced'
43
40
  inspect-flags: '--compatibility-mode=experimental_enhanced'
41
+ run-examples:
42
+ runs-on: ubuntu-latest
43
+ needs: [test, e2e-test]
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ - uses: actions/setup-node@v4
47
+ with:
48
+ node-version: '21.5.0'
49
+ - run: npm ci
50
+ - name: Update examples
51
+ run: npm run update-examples
52
+ - name: Compare generated Clients with existing ones
53
+ id: diff
54
+ run: |
55
+ if [ "$(git diff --ignore-space-at-eol --text examples/ | wc -l)" -gt "0" ]; then
56
+ echo "Detected changes in the examples, run `npm run update-examples` to update all the examples."
57
+ git diff --ignore-space-at-eol --text examples/
58
+ exit 1
59
+ fi
@@ -0,0 +1,4 @@
1
+ examples/
2
+ dist/
3
+ .github/
4
+ .vscode/
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # openapi-to-k6
2
2
 
3
+ <p align="center">⚠️</p>
4
+
5
+ ***This tool is currently in the experimental stage. Expect bugs, incomplete features, and breaking changes as development progresses. Use at your own risk, and please report any issues or feedback to help us improve.***
6
+
7
+ ---
8
+
3
9
  ## Overview
4
10
 
5
11
  The _openapi-to-k6_ repository is a tool designed to ease the process of writing k6 scripts.
@@ -9,6 +15,13 @@ easily call your endpoints and have auto completion in your IDE.
9
15
  This allows developers to easily create performance tests for their APIs based on their existing
10
16
  OpenAPI documentation.
11
17
 
18
+ Along with the client, it also generates a sample k6 script as an example of how to use the client.
19
+
20
+ To get started, install the tool with npm via `npm install openapi-to-k6` and run it to convert your
21
+ OpenAPI specification to a TypeScript client for k6.
22
+
23
+ To take a look at a few examples of how the generated client and sample script looks, check out the [examples](./examples) directory.
24
+
12
25
  Note: Optional usage analytics are gathered to make the tool better. To disable this, use the option
13
26
  `--disable-analytics` or set an environment variable `DISABLE_ANALYTICS=true`.
14
27
 
package/dist/generator.js CHANGED
@@ -12,7 +12,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ const fs_1 = __importDefault(require("fs"));
15
16
  const orval_1 = __importDefault(require("orval"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const constants_1 = require("./constants");
16
19
  const helper_1 = require("./helper");
17
20
  const k6SdkClient_1 = require("./k6SdkClient");
18
21
  const logger_1 = require("./logger");
@@ -27,6 +30,20 @@ const generatedFileHeaderGenerator = (info) => {
27
30
  ...(info.version ? [`OpenAPI spec version: ${info.version}`] : []),
28
31
  ];
29
32
  };
33
+ const afterAllFilesWriteHandler = (filePaths) => __awaiter(void 0, void 0, void 0, function* () {
34
+ for (const filePath of filePaths) {
35
+ yield (0, helper_1.formatFileWithPrettier)(filePath);
36
+ const fileName = path_1.default.basename(filePath);
37
+ if (fileName === '.ts') {
38
+ // Generated SDK had no name because there was no title in the schema
39
+ // Rename it to the default name
40
+ const directoryPath = path_1.default.dirname(filePath);
41
+ const newPath = path_1.default.join(directoryPath, `${constants_1.DEFAULT_SCHEMA_TITLE}.ts`);
42
+ logger_1.logger.debug(`afterAllFilesWriteHandler ~ Renaming ${filePath} to ${newPath}`);
43
+ fs_1.default.renameSync(filePath, newPath);
44
+ }
45
+ }
46
+ });
30
47
  exports.default = (_a) => __awaiter(void 0, [_a], void 0, function* ({ openApiPath, outputDir, shouldGenerateSampleK6Script, analyticsData, }) {
31
48
  const schemaDetails = {
32
49
  title: '',
@@ -48,10 +65,12 @@ exports.default = (_a) => __awaiter(void 0, [_a], void 0, function* ({ openApiPa
48
65
  },
49
66
  headers: true,
50
67
  },
68
+ hooks: {
69
+ afterAllFilesWrite: afterAllFilesWriteHandler,
70
+ },
51
71
  });
52
72
  }));
53
73
  if (!schemaDetails.title) {
54
74
  logger_1.logger.warning('Could not find schema title in the OpenAPI spec. Please provide a `title` in the schema in `info` block to generate proper file names');
55
75
  }
56
- yield (0, helper_1.formatGeneratedFiles)(outputDir, schemaDetails.title, !!shouldGenerateSampleK6Script);
57
76
  });
package/dist/helper.js CHANGED
@@ -14,7 +14,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.OutputOverrider = exports.getPackageDetails = void 0;
16
16
  exports.formatFileWithPrettier = formatFileWithPrettier;
17
- exports.formatGeneratedFiles = formatGeneratedFiles;
18
17
  exports.getGeneratedClientPath = getGeneratedClientPath;
19
18
  exports.isTsNode = isTsNode;
20
19
  exports.djb2Hash = djb2Hash;
@@ -24,7 +23,6 @@ const fs_1 = __importDefault(require("fs"));
24
23
  const path_1 = __importDefault(require("path"));
25
24
  const prettier_1 = require("prettier");
26
25
  const package_json_1 = __importDefault(require("../package.json"));
27
- const constants_1 = require("./constants");
28
26
  const logger_1 = require("./logger");
29
27
  const getPackageDetails = () => {
30
28
  const commandName = Object.keys(package_json_1.default.bin)[0] || 'openapi-to-k6';
@@ -43,6 +41,10 @@ exports.getPackageDetails = getPackageDetails;
43
41
  */
44
42
  function formatFileWithPrettier(filePath) {
45
43
  return __awaiter(this, void 0, void 0, function* () {
44
+ if (!fs_1.default.existsSync(filePath)) {
45
+ logger_1.logger.debug(`formatFileWithPrettier ~ File does not exist: ${filePath}, skipping formatting with prettier.`);
46
+ return;
47
+ }
46
48
  // Read file contents
47
49
  const content = fs_1.default.readFileSync(filePath, 'utf-8');
48
50
  // Format using Prettier
@@ -53,35 +55,6 @@ function formatFileWithPrettier(filePath) {
53
55
  logger_1.logger.debug(`Formatted: ${filePath}`);
54
56
  });
55
57
  }
56
- /**
57
- * Format the generated files using Prettier.
58
- *
59
- * @param outputTarget - Path to the generated files.
60
- * @param schemaTitle - Title of the schema.
61
- */
62
- function formatGeneratedFiles(outputTarget, schemaTitle, isSampleK6ScriptGenerated) {
63
- return __awaiter(this, void 0, void 0, function* () {
64
- // Here we call the original function from @orval/core used by the library to generate the
65
- // file name with same defaults.
66
- const { path: clientPath } = yield getGeneratedClientPath(outputTarget, schemaTitle);
67
- logger_1.logger.debug('Following are the details for formatting generated files:');
68
- logger_1.logger.debug(`Path: ${path_1.default}`);
69
- logger_1.logger.debug(`Schema Title: ${schemaTitle}`);
70
- logger_1.logger.debug(`Output Target: ${outputTarget}`);
71
- yield exports.formatFileWithPrettier(clientPath);
72
- if (isSampleK6ScriptGenerated) {
73
- const k6ScriptPath = path_1.default.join(getDirectoryForPath(clientPath), constants_1.SAMPLE_K6_SCRIPT_FILE_NAME);
74
- logger_1.logger.debug(`Generated sample K6 Script Path: ${k6ScriptPath}`);
75
- if (fs_1.default.existsSync(k6ScriptPath)) {
76
- logger_1.logger.debug('Formatting sample k6 script file');
77
- yield exports.formatFileWithPrettier(k6ScriptPath);
78
- }
79
- else {
80
- logger_1.logger.error('Unable to format sample K6 script file as it does not exist!');
81
- }
82
- }
83
- });
84
- }
85
58
  /**
86
59
  * Get the path for the generated client file.
87
60
  *
@@ -131,7 +104,10 @@ class OutputOverrider {
131
104
  }
132
105
  redirectOutputToNullStream(callback) {
133
106
  return __awaiter(this, void 0, void 0, function* () {
134
- process.stdout.write = process.stderr.write = () => true;
107
+ if (!logger_1.logger.getVerbose()) {
108
+ // Redirect stdout and stderr to null stream only if not running in verbose mode
109
+ process.stdout.write = process.stderr.write = () => true;
110
+ }
135
111
  try {
136
112
  if (callback) {
137
113
  yield callback();
@@ -19,6 +19,7 @@ const handlebars_1 = __importDefault(require("handlebars"));
19
19
  const path_1 = __importDefault(require("path"));
20
20
  const constants_1 = require("./constants");
21
21
  const helper_1 = require("./helper");
22
+ const logger_1 = require("./logger");
22
23
  // A map to store the operationNames for which a return type is to be written at the end to export
23
24
  // and the return type definition
24
25
  const returnTypesToWrite = new Map();
@@ -69,10 +70,12 @@ const getK6Dependencies = () => [
69
70
  exports.getK6Dependencies = getK6Dependencies;
70
71
  function getSchemaTitleFromContext(context) {
71
72
  const specData = Object.values(context.specs);
73
+ let schemaTitle;
72
74
  if (specData[0]) {
73
- return specData[0].info.title;
75
+ schemaTitle = specData[0].info.title;
74
76
  }
75
- return constants_1.DEFAULT_SCHEMA_TITLE;
77
+ schemaTitle !== null && schemaTitle !== void 0 ? schemaTitle : (schemaTitle = constants_1.DEFAULT_SCHEMA_TITLE);
78
+ return schemaTitle;
76
79
  }
77
80
  function _generateResponseTypeName(operationName) {
78
81
  return `${(0, core_1.pascal)(operationName)}Response`;
@@ -249,15 +252,18 @@ const generateFooter = ({ operationNames }) => {
249
252
  };
250
253
  exports.generateFooter = generateFooter;
251
254
  const k6ScriptBuilder = (verbOptions, output, context) => __awaiter(void 0, void 0, void 0, function* () {
252
- console.log(JSON.stringify({
253
- verbOptions,
254
- output,
255
- context,
256
- }, null, 2));
257
255
  const schemaTitle = getSchemaTitleFromContext(context);
258
256
  const { path: pathOfGeneratedClient, filename, extension, } = yield (0, helper_1.getGeneratedClientPath)(output.target, schemaTitle);
259
257
  const directoryPath = (0, helper_1.getDirectoryForPath)(pathOfGeneratedClient);
260
258
  const generateScriptPath = path_1.default.join(directoryPath, constants_1.SAMPLE_K6_SCRIPT_FILE_NAME);
259
+ logger_1.logger.debug(`k6ScriptBuilder ~ Generating sample K6 Script\n${JSON.stringify({
260
+ pathOfGeneratedClient,
261
+ filename,
262
+ extension,
263
+ schemaTitle,
264
+ directoryPath,
265
+ generateScriptPath,
266
+ }, null, 2)}`);
261
267
  const clientFunctionsList = [];
262
268
  for (const verbOption of Object.values(verbOptions)) {
263
269
  const { operationName, summary, props } = verbOption;
package/dist/logger.js CHANGED
@@ -25,6 +25,9 @@ class Logger {
25
25
  setVerbose(verbose) {
26
26
  this.isVerbose = verbose;
27
27
  }
28
+ getVerbose() {
29
+ return this.isVerbose;
30
+ }
28
31
  logWithColor(message, level, color) {
29
32
  const timestamp = new Date().toISOString();
30
33
  console.log(`${color(`[${level}]`)} ${chalk_1.default.gray(`[${timestamp}]`)} ${message}`);
@@ -0,0 +1,11 @@
1
+ import { createSimpleAPI } from './simpleAPI.ts'
2
+
3
+ const baseUrl = '<BASE_URL>'
4
+ const client = createSimpleAPI({ baseUrl })
5
+
6
+ export default function () {
7
+ /**
8
+ * Retrieve example data
9
+ */
10
+ const getExampleResponseData = client.getExample()
11
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "Simple API",
5
+ "version": "1.0.0"
6
+ },
7
+ "paths": {
8
+ "/example": {
9
+ "get": {
10
+ "summary": "Retrieve example data",
11
+ "responses": {
12
+ "200": {
13
+ "description": "Successful response",
14
+ "content": {
15
+ "application/json": {
16
+ "schema": {
17
+ "type": "object",
18
+ "properties": {
19
+ "message": {
20
+ "type": "string",
21
+ "example": "Hello, World!"
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Automatically generated by @grafana/openapi-to-k6: 0.1.1
3
+ * Do not edit manually.
4
+ * Simple API
5
+ * OpenAPI spec version: 1.0.0
6
+ */
7
+ import { URL } from 'https://jslib.k6.io/url/1.0.0/index.js'
8
+ import http from 'k6/http'
9
+ import type { Params, Response, ResponseBody } from 'k6/http'
10
+ export type GetExample200 = {
11
+ message?: string
12
+ }
13
+
14
+ export type CreateSimpleAPIOptions = {
15
+ baseUrl: string
16
+ commonRequestParameters?: Params
17
+ }
18
+
19
+ /**
20
+ * This is the base client to use for interacting with the API.
21
+ */
22
+ export const createSimpleAPI = (clientOptions: CreateSimpleAPIOptions) => {
23
+ const cleanBaseUrl = clientOptions.baseUrl.replace(/\/+$/, '')
24
+ /**
25
+ * @summary Retrieve example data
26
+ */
27
+ const getExample = (requestParameters?: Params): GetExampleResponse => {
28
+ const url = new URL(cleanBaseUrl + `/example`)
29
+ const mergedRequestParameters = _mergeRequestParameters(
30
+ requestParameters || {},
31
+ clientOptions.commonRequestParameters
32
+ )
33
+ const response = http.request(
34
+ 'GET',
35
+ url.toString(),
36
+ undefined,
37
+ mergedRequestParameters
38
+ )
39
+ let data
40
+
41
+ try {
42
+ data = response.json()
43
+ } catch (error) {
44
+ data = response.body
45
+ }
46
+ return {
47
+ response,
48
+ data,
49
+ }
50
+ }
51
+
52
+ return { getExample }
53
+ }
54
+
55
+ export type GetExampleResponse = {
56
+ response: Response
57
+ data: GetExample200 | ResponseBody
58
+ }
59
+
60
+ /**
61
+ * Merges the provided request parameters with default parameters for the client.
62
+ *
63
+ * @param {Params} requestParameters - The parameters provided specifically for the request
64
+ * @param {Params} commonRequestParameters - Common parameters for all requests
65
+ * @returns {Params} - The merged parameters
66
+ */
67
+ const _mergeRequestParameters = (
68
+ requestParameters?: Params,
69
+ commonRequestParameters?: Params
70
+ ): 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
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Automatically generated by @grafana/openapi-to-k6: 0.1.1
3
+ * Do not edit manually.
4
+ * Form Data API
5
+ * OpenAPI spec version: 1.0.0
6
+ */
7
+ import { FormData } from 'https://jslib.k6.io/formdata/0.0.2/index.js'
8
+ import { URL } from 'https://jslib.k6.io/url/1.0.0/index.js'
9
+ import http from 'k6/http'
10
+ import type { Params, Response, ResponseBody } from 'k6/http'
11
+ export type PostUpload400 = {
12
+ error?: string
13
+ success?: boolean
14
+ }
15
+
16
+ export type PostUpload200 = {
17
+ message?: string
18
+ success?: boolean
19
+ }
20
+
21
+ export type PostUploadBody = {
22
+ /** Description of the file */
23
+ description?: string
24
+ /** File to upload */
25
+ file: Blob
26
+ /** User ID associated with the upload */
27
+ userId: string
28
+ }
29
+
30
+ export type CreateFormDataAPIOptions = {
31
+ baseUrl: string
32
+ commonRequestParameters?: Params
33
+ }
34
+
35
+ /**
36
+ * This is the base client to use for interacting with the API.
37
+ */
38
+ export const createFormDataAPI = (clientOptions: CreateFormDataAPIOptions) => {
39
+ const cleanBaseUrl = clientOptions.baseUrl.replace(/\/+$/, '')
40
+ /**
41
+ * This endpoint accepts form data and file uploads.
42
+ * @summary Upload files and data
43
+ */
44
+ const postUpload = (
45
+ postUploadBody: PostUploadBody,
46
+ requestParameters?: Params
47
+ ): PostUploadResponse => {
48
+ const formData = new FormData()
49
+ formData.append('file', postUploadBody.file)
50
+ if (postUploadBody.description !== undefined) {
51
+ formData.append('description', postUploadBody.description)
52
+ }
53
+ formData.append('userId', postUploadBody.userId)
54
+
55
+ const url = new URL(cleanBaseUrl + `/upload`)
56
+ const mergedRequestParameters = _mergeRequestParameters(
57
+ requestParameters || {},
58
+ clientOptions.commonRequestParameters
59
+ )
60
+ const response = http.request('POST', url.toString(), formData.body(), {
61
+ ...mergedRequestParameters,
62
+ headers: {
63
+ 'Content-Type': 'multipart/form-data; boundary=' + formData.boundary,
64
+ ...mergedRequestParameters?.headers,
65
+ },
66
+ })
67
+ let data
68
+
69
+ try {
70
+ data = response.json()
71
+ } catch (error) {
72
+ data = response.body
73
+ }
74
+ return {
75
+ response,
76
+ data,
77
+ }
78
+ }
79
+
80
+ return { postUpload }
81
+ }
82
+
83
+ export type PostUploadResponse = {
84
+ response: Response
85
+ data: PostUpload200 | ResponseBody
86
+ }
87
+
88
+ /**
89
+ * Merges the provided request parameters with default parameters for the client.
90
+ *
91
+ * @param {Params} requestParameters - The parameters provided specifically for the request
92
+ * @param {Params} commonRequestParameters - Common parameters for all requests
93
+ * @returns {Params} - The merged parameters
94
+ */
95
+ const _mergeRequestParameters = (
96
+ requestParameters?: Params,
97
+ commonRequestParameters?: Params
98
+ ): Params => {
99
+ return {
100
+ ...commonRequestParameters, // Default to common parameters
101
+ ...requestParameters, // Override with request-specific parameters
102
+ headers: {
103
+ ...(commonRequestParameters?.headers || {}), // Ensure headers are defined
104
+ ...(requestParameters?.headers || {}),
105
+ },
106
+ cookies: {
107
+ ...(commonRequestParameters?.cookies || {}), // Ensure cookies are defined
108
+ ...(requestParameters?.cookies || {}),
109
+ },
110
+ tags: {
111
+ ...(commonRequestParameters?.tags || {}), // Ensure tags are defined
112
+ ...(requestParameters?.tags || {}),
113
+ },
114
+ }
115
+ }
@@ -0,0 +1,11 @@
1
+ import { createFormDataAPI } from './formDataAPI.ts'
2
+
3
+ const baseUrl = '<BASE_URL>'
4
+ const client = createFormDataAPI({ baseUrl })
5
+
6
+ export default function () {
7
+ /**
8
+ * Upload files and data
9
+ */
10
+ const postUploadResponseData = client.postUpload(postUploadBody)
11
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "Form Data API",
5
+ "version": "1.0.0"
6
+ },
7
+ "paths": {
8
+ "/upload": {
9
+ "post": {
10
+ "summary": "Upload files and data",
11
+ "description": "This endpoint accepts form data and file uploads.",
12
+ "requestBody": {
13
+ "required": true,
14
+ "content": {
15
+ "multipart/form-data": {
16
+ "schema": {
17
+ "type": "object",
18
+ "properties": {
19
+ "file": {
20
+ "type": "string",
21
+ "format": "binary",
22
+ "description": "File to upload"
23
+ },
24
+ "description": {
25
+ "type": "string",
26
+ "description": "Description of the file"
27
+ },
28
+ "userId": {
29
+ "type": "string",
30
+ "description": "User ID associated with the upload"
31
+ }
32
+ },
33
+ "required": [
34
+ "file",
35
+ "userId"
36
+ ]
37
+ }
38
+ }
39
+ }
40
+ },
41
+ "responses": {
42
+ "200": {
43
+ "description": "File uploaded successfully",
44
+ "content": {
45
+ "application/json": {
46
+ "schema": {
47
+ "type": "object",
48
+ "properties": {
49
+ "success": {
50
+ "type": "boolean",
51
+ "example": true
52
+ },
53
+ "message": {
54
+ "type": "string",
55
+ "example": "File uploaded successfully"
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ },
62
+ "400": {
63
+ "description": "Bad Request",
64
+ "content": {
65
+ "application/json": {
66
+ "schema": {
67
+ "type": "object",
68
+ "properties": {
69
+ "success": {
70
+ "type": "boolean",
71
+ "example": false
72
+ },
73
+ "error": {
74
+ "type": "string",
75
+ "example": "Invalid file or data"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }