diff --git a/.gitignore b/.gitignore index 16c75525..f7327b68 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ coverage/ yarn.lock dist/ lib/ +output/ *.tar.gz *.tsbuildinfo diff --git a/__tests__/split/missing-outDir/snapshot.js b/__tests__/split/missing-outDir/snapshot.js index 8f09bcdb..260dc99a 100644 --- a/__tests__/split/missing-outDir/snapshot.js +++ b/__tests__/split/missing-outDir/snapshot.js @@ -10,9 +10,10 @@ Positionals: entrypoint API definition file that you want to split [string] [required] Options: - --version Show version number. [boolean] - --help Show help. [boolean] - --outDir Output directory where files will be saved. [string] [required] + --version Show version number. [boolean] + --help Show help. [boolean] + --outDir Output directory where files will be saved. [string] [required] + --separator File path separator used while splitting. [string] [default: "_"] Missing required argument: outDir diff --git a/__tests__/split/oas3-no-errors/snapshot.js b/__tests__/split/oas3-no-errors/snapshot.js index ec5592c2..e7c2a6d6 100644 --- a/__tests__/split/oas3-no-errors/snapshot.js +++ b/__tests__/split/oas3-no-errors/snapshot.js @@ -109,7 +109,7 @@ paths: /pets: $ref: paths/pets.yaml /pets/{petId}: - $ref: paths/pets@{petId}.yaml + $ref: paths/pets_{petId}.yaml 🪓 Document: ../../../__tests__/split/oas3-no-errors/openapi.yaml is successfully split and all related files are saved to the directory: output diff --git a/docs/commands/split.md b/docs/commands/split.md index e344153e..7b05eb88 100644 --- a/docs/commands/split.md +++ b/docs/commands/split.md @@ -22,6 +22,7 @@ Option | Type | Required | Default | Description --------------------------|:---------:|:------------:|:-----------:|------------ `entrypoint` | `string` | yes | - | Path to the API definition file that you want to split into a multi-file structure `--outDir` | `string` | yes | - | Path to the directory where you want to save split files. If the specified directory doesn't exist, it will be created automatically. +`separator` | `string` | no | `_` | File path separator used while splitting. Will affect file names in the `paths` folder (e.g. `user_create.yaml`) `--help` | `boolean` | no | - | Show help `--version` | `boolean` | no | - | Show version number diff --git a/packages/cli/src/__tests__/utils.test.ts b/packages/cli/src/__tests__/utils.test.ts index 423a7912..ceaa3237 100644 --- a/packages/cli/src/__tests__/utils.test.ts +++ b/packages/cli/src/__tests__/utils.test.ts @@ -1,4 +1,4 @@ -import { isSubdir } from '../utils'; +import { isSubdir, pathToFilename } from '../utils'; jest.mock("os"); @@ -40,3 +40,11 @@ describe('isSubdir', () => { jest.resetModules() }) }); + + +describe('pathToFilename', () => { + it('should use correct path separator', () => { + const processedPath = pathToFilename('/user/createWithList', '_'); + expect(processedPath).toEqual('user_createWithList'); + }); +}); diff --git a/packages/cli/src/commands/split/__tests__/index.test.ts b/packages/cli/src/commands/split/__tests__/index.test.ts index e71bd19e..0ab46e72 100644 --- a/packages/cli/src/commands/split/__tests__/index.test.ts +++ b/packages/cli/src/commands/split/__tests__/index.test.ts @@ -28,6 +28,7 @@ describe('#split', () => { { entrypoint: filePath, outDir: openapiDir, + separator: '_', } ); @@ -41,12 +42,31 @@ describe('#split', () => { ); }); + + it('should use the correct separator', async () => { + const filePath = "./packages/cli/src/commands/split/__tests__/fixtures/spec.json"; + + const utils = require('../../../utils'); + jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath'); + + await handleSplit ( + { + entrypoint: filePath, + outDir: openapiDir, + separator: '_', + } + ); + + expect(utils.pathToFilename).toBeCalledWith(expect.anything(), '_'); + utils.pathToFilename.mockRestore(); + }); + it('should have correct path with paths', () => { const openapi = require("./fixtures/spec.json"); jest.spyOn(openapiCore, 'slash').mockImplementation(() => 'paths/test.yaml'); jest.spyOn(path, 'relative').mockImplementation(() => 'paths/test.yaml'); - iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles); + iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles, '_'); expect(openapiCore.slash).toHaveBeenCalledWith('paths/test.yaml'); expect(path.relative).toHaveBeenCalledWith('test', 'test/paths/test.yaml'); diff --git a/packages/cli/src/commands/split/index.ts b/packages/cli/src/commands/split/index.ts index ee70c45a..d1c392da 100644 --- a/packages/cli/src/commands/split/index.ts +++ b/packages/cli/src/commands/split/index.ts @@ -29,12 +29,13 @@ import { export async function handleSplit (argv: { entrypoint: string; outDir: string + separator: string }) { const startedAt = performance.now(); - const { entrypoint, outDir } = argv; + const { entrypoint, outDir, separator } = argv; validateDefinitionFileName(entrypoint!); const openapi = readYaml(entrypoint!) as Oas3Definition | Oas3_1Definition; - splitDefinition(openapi, outDir); + splitDefinition(openapi, outDir, separator); process.stderr.write( `🪓 Document: ${blue(entrypoint!)} ${green('is successfully split')} and all related files are saved to the directory: ${blue(outDir)} \n`, @@ -42,15 +43,15 @@ export async function handleSplit (argv: { printExecutionTime('split', startedAt, entrypoint!); } -function splitDefinition(openapi: Oas3Definition | Oas3_1Definition, openapiDir: string) { +function splitDefinition(openapi: Oas3Definition | Oas3_1Definition, openapiDir: string, pathSeparator: string) { fs.mkdirSync(openapiDir, { recursive: true }); const componentsFiles: ComponentsFiles = {}; iterateComponents(openapi, openapiDir, componentsFiles); - iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles); + iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles, pathSeparator); const webhooks = (openapi as Oas3_1Definition).webhooks || (openapi as Oas3Definition)['x-webhooks']; // use webhook_ prefix for code samples to prevent potential name-clashes with paths samples - iteratePathItems(webhooks, openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, 'webhook_'); + iteratePathItems(webhooks, openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, pathSeparator, 'webhook_'); replace$Refs(openapi, openapiDir, componentsFiles); writeYaml(openapi, path.join(openapiDir, 'openapi.yaml')); @@ -247,13 +248,14 @@ function iteratePathItems( openapiDir: string, outDir: string, componentsFiles: object, + pathSeparator: string, codeSamplesPathPrefix: string = '', ) { if (!pathItems) return; fs.mkdirSync(outDir, { recursive: true }); for (const pathName of Object.keys(pathItems)) { - const pathFile = `${path.join(outDir, pathToFilename(pathName))}.yaml`; + const pathFile = `${path.join(outDir, pathToFilename(pathName, pathSeparator))}.yaml`; const pathData = pathItems[pathName] as Oas3PathItem; if (isRef(pathData)) continue; @@ -270,7 +272,7 @@ function iteratePathItems( openapiDir, 'code_samples', sample.lang, - codeSamplesPathPrefix + pathToFilename(pathName), + codeSamplesPathPrefix + pathToFilename(pathName, pathSeparator), method + langToExt(sample.lang), ); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 63f3fd5d..10698d72 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -46,6 +46,12 @@ yargs required: true, type: 'string', }, + separator: { + description: 'File path separator used while splitting.', + required: false, + type: 'string', + default: '_', + }, }) .demandOption('entrypoint'), handleSplit, diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index 5f7c1541..9c8761e2 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -66,12 +66,12 @@ export function printExecutionTime(commandName: string, startedAt: number, entry process.stderr.write(gray(`\n${entrypoint}: ${commandName} processed in ${elapsed}\n\n`)); } -export function pathToFilename(path: string) { +export function pathToFilename(path: string, pathSeparator: string) { return path .replace(/~1/g, '/') .replace(/~0/g, '~') .replace(/^\//, '') - .replace(/\//g, '@'); + .replace(/\//g, pathSeparator); } export class CircularJSONNotSupportedError extends Error {