Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions apps/generator-cli/src/app/app.module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,67 @@ describe('AppModule', () => {
expect(programMock.parse).toHaveBeenNthCalledWith(1, process.argv);
});
});

describe('a custom generator is provided', () => {
beforeEach(async () => {
process.argv = [
'foo',
'baz',
'--custom-generator',
'/path/to/custom.jar',
];
programMock.parse.mockImplementation(() => {
expect(passThroughServiceMock.init).toHaveBeenCalledTimes(1);
});
versionManagerServiceMock.getSelectedVersion.mockReturnValue('1.2.3');
await fixture.onApplicationBootstrap();
});

it('does not search for the latest version', () => {
expect(versionManagerServiceMock.search).toHaveBeenCalledTimes(0);
});

it('does not set the selected version', () => {
expect(
versionManagerServiceMock.setSelectedVersion,
).toHaveBeenCalledTimes(0);
});

it('does not download', () => {
expect(
versionManagerServiceMock.downloadIfNeeded,
).toHaveBeenCalledTimes(0);
});

it('parses the command', () => {
expect(programMock.parse).toHaveBeenNthCalledWith(1, process.argv);
});
});

describe('a custom generator is provided with = syntax', () => {
beforeEach(async () => {
process.argv = [
'foo',
'baz',
'--custom-generator=/path/to/custom.jar',
];
programMock.parse.mockImplementation(() => {
expect(passThroughServiceMock.init).toHaveBeenCalledTimes(1);
});
versionManagerServiceMock.getSelectedVersion.mockReturnValue('1.2.3');
await fixture.onApplicationBootstrap();
});

it('does not download', () => {
expect(
versionManagerServiceMock.downloadIfNeeded,
).toHaveBeenCalledTimes(0);
});

it('parses the command', () => {
expect(programMock.parse).toHaveBeenNthCalledWith(1, process.argv);
});
});
});
});
});
24 changes: 16 additions & 8 deletions apps/generator-cli/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,25 @@ export class AppModule implements OnApplicationBootstrap {
) {}

onApplicationBootstrap = async () => {
let selectedVersion = this.versionManager.getSelectedVersion();
const hasCustomGenerator = process.argv.some(
(arg) =>
arg === '--custom-generator' || arg.startsWith('--custom-generator='),
);

if (!selectedVersion) {
const [{ version }] = await this.versionManager
.search(['latest'])
.toPromise();
await this.versionManager.setSelectedVersion(version);
selectedVersion = version;
if (!hasCustomGenerator) {
let selectedVersion = this.versionManager.getSelectedVersion();

if (!selectedVersion) {
const [{ version }] = await this.versionManager
.search(['latest'])
.toPromise();
await this.versionManager.setSelectedVersion(version);
selectedVersion = version;
}

await this.versionManager.downloadIfNeeded(selectedVersion);
}

await this.versionManager.downloadIfNeeded(selectedVersion);
await this.passThroughService.init();
this.program.parse(process.argv);
};
Expand Down
36 changes: 35 additions & 1 deletion apps/generator-cli/src/app/services/generator.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ describe('GeneratorService', () => {

beforeEach(() => {
executedCommands = [];
fs.existsSync.mockImplementation((p) => !!config[p]);
fs.existsSync.mockImplementation(
(p) => p === '/path/to/4.2.1.jar' || !!config[p],
);
fs.readJSONSync.mockImplementation((p) => config[p]);
glob.sync.mockImplementation((g) => specFiles[g]);
concurrently.mockImplementation((ec, cfg) => {
Expand Down Expand Up @@ -275,6 +277,38 @@ describe('GeneratorService', () => {
expect(returnValue).toEqual(expectedCommands.length > 0);
});
});

describe('custom jar only (standard jar missing)', () => {
let returnValue: boolean;

beforeEach(async () => {
fs.existsSync.mockImplementation((p) => {
if (p === '/path/to/4.2.1.jar') return false;
return !!config[p];
});
configGet.mockImplementation(
(path, defaultValue) => config['bar.json'] || defaultValue,
);
returnValue = await fixture.generate('../some/custom.jar');
});

it('uses only the custom jar', () => {
expect(executedCommands).toEqual([
{
name: '[bar] api/cat.yaml',
command: `java -jar "../some/custom.jar" generate --input-spec="${cwd}/api/cat.yaml" --output="bar/cat" --some-bool`,
},
{
name: '[bar] api/bird.json',
command: `java -jar "../some/custom.jar" generate --input-spec="${cwd}/api/bird.json" --output="bar/bird" --some-bool`,
},
]);
});

it('resolved to true', () => {
expect(returnValue).toEqual(true);
});
});
});
});
});
15 changes: 10 additions & 5 deletions apps/generator-cli/src/app/services/generator.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,16 @@ export class GeneratorService {
}

const cliPath = this.versionManager.filePath();
const subCmd = customGenerator
? `-cp "${[cliPath, customGenerator].join(
this.isWin() ? ';' : ':'
)}" org.openapitools.codegen.OpenAPIGenerator`
: `-jar "${cliPath}"`;
let subCmd: string;
if (customGenerator) {
subCmd = fs.existsSync(cliPath)
? `-cp "${[cliPath, customGenerator].join(
this.isWin() ? ';' : ':'
)}" org.openapitools.codegen.OpenAPIGenerator`
: `-jar "${customGenerator}"`;
} else {
subCmd = `-jar "${cliPath}"`;
}
return ['java', process.env['JAVA_OPTS'], subCmd, 'generate', appendix]
.filter((str): str is string => str != null && typeof str === 'string')
.join(' ');
Expand Down
21 changes: 21 additions & 0 deletions apps/generator-cli/src/app/services/pass-through.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import { VersionManagerService } from './version-manager.service';
import { ConfigService } from './config.service';

jest.mock('child_process');
jest.mock('fs');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const childProcess = jest.mocked(require('child_process'));
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = jest.mocked(require('fs'));

describe('PassThroughService', () => {
let fixture: PassThroughService;
Expand Down Expand Up @@ -56,6 +59,7 @@ describe('PassThroughService', () => {
fixture = moduleRef.get(PassThroughService);

childProcess.spawn.mockReset().mockReturnValue({ on: jest.fn() });
fs.existsSync.mockReset().mockReturnValue(true);
configServiceMock.get.mockClear();
configServiceMock.get.mockReset();
configServiceMock.useDocker = false;
Expand Down Expand Up @@ -232,6 +236,23 @@ describe('PassThroughService', () => {
);
});

it('can delegate with custom jar only when standard jar is missing', async () => {
fs.existsSync.mockReturnValue(false);
await program.parseAsync(
[name, ...argv, '--custom-generator=../some/custom.jar'],
{ from: 'user' }
);

expect(childProcess.spawn).toHaveBeenNthCalledWith(
1,
`java -jar "../some/custom.jar" ${name} ${argv.join(' ')}`,
{
stdio: 'inherit',
shell: true,
}
);
});

if (name === 'generate') {
it('can delegate with custom jar to generate command', async () => {
await program.parseAsync(
Expand Down
33 changes: 27 additions & 6 deletions apps/generator-cli/src/app/services/pass-through.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import chalk from 'chalk';
import { exec, spawn } from 'child_process';
import { Command } from 'commander';
import * as fs from 'fs';
import { COMMANDER_PROGRAM, LOGGER } from '../constants';
import { GeneratorService } from './generator.service';
import { VersionManagerService } from './version-manager.service';
Expand Down Expand Up @@ -139,14 +140,21 @@ export class PassThroughService {
].join(' ');
}

const customGenerator = this.program.opts()?.customGenerator;
const customGenerator =
this.program.opts()?.customGenerator ||
this.getCustomGeneratorFromArgs();
const cliPath = this.versionManager.filePath();

const subCmd = customGenerator
? `-cp "${[cliPath, customGenerator].join(
this.isWin() ? ';' : ':'
)}" org.openapitools.codegen.OpenAPIGenerator`
: `-jar "${cliPath}"`;
let subCmd: string;
if (customGenerator) {
subCmd = fs.existsSync(cliPath)
? `-cp "${[cliPath, customGenerator].join(
this.isWin() ? ';' : ':'
)}" org.openapitools.codegen.OpenAPIGenerator`
: `-jar "${customGenerator}"`;
} else {
subCmd = `-jar "${cliPath}"`;
}

return ['java', process.env['JAVA_OPTS'], subCmd]
.filter((str): str is string => str != null && typeof str === 'string')
Expand All @@ -157,5 +165,18 @@ export class PassThroughService {
console.log(chalk.cyanBright(cmd.helpInformation()));
}

private getCustomGeneratorFromArgs(): string | undefined {
for (let i = 0; i < process.argv.length; i++) {
const arg = process.argv[i];
if (arg === '--custom-generator' && i + 1 < process.argv.length) {
return process.argv[i + 1];
}
if (arg.startsWith('--custom-generator=')) {
return arg.substring('--custom-generator='.length);
}
}
return undefined;
}

private isWin = () => process.platform === 'win32';
}