Skip to content

Commit 0645163

Browse files
authored
Merge pull request #335 from mcaden/features/custom-jar
feat(custom generators): added '--custom-generator' parameter fixes #237
2 parents cd3aa24 + 8cb99ee commit 0645163

File tree

7 files changed

+79
-29
lines changed

7 files changed

+79
-29
lines changed

apps/generator-cli/src/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ is automatically used to generate your code. 🎉
173173
| relPath | file name and extension of file relative to the glob provided | docs/auth.yaml |
174174
| ext | just file extension | yaml |
175175

176+
## Custom Generators
177+
178+
Custom generators can be used by passing the `--custom-generator=/my/custom-generator.jar` argument.
179+
176180
## Further Documentation
177181

178182
Please refer to the [official openapi-generator docs](https://github.com/OpenAPITools/openapi-generator#3---usage) for

apps/generator-cli/src/app/app.module.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {AppModule} from './app.module';
22
import {Test} from '@nestjs/testing';
3-
import {PassTroughService, VersionManagerService} from './services';
3+
import {PassThroughService, VersionManagerService} from './services';
44
import {of} from 'rxjs';
55
import {COMMANDER_PROGRAM} from './constants';
66

@@ -12,7 +12,7 @@ describe('AppModule', () => {
1212
parse: jest.fn(),
1313
}
1414

15-
const passTroughServiceMock = {
15+
const passThroughServiceMock = {
1616
init: jest.fn(),
1717
}
1818

@@ -27,22 +27,22 @@ describe('AppModule', () => {
2727

2828
[
2929
...Object.values(versionManagerServiceMock),
30-
...Object.values(passTroughServiceMock),
30+
...Object.values(passThroughServiceMock),
3131
...Object.values(programMock),
3232
].forEach(spy => spy.mockReset())
3333

3434
const moduleRef = await Test.createTestingModule({
3535
providers: [
3636
{provide: COMMANDER_PROGRAM, useValue: programMock},
3737
{provide: VersionManagerService, useValue: versionManagerServiceMock},
38-
{provide: PassTroughService, useValue: passTroughServiceMock},
38+
{provide: PassThroughService, useValue: passThroughServiceMock},
3939
]
4040
}).compile();
4141

4242
fixture = new AppModule(
4343
moduleRef.get(COMMANDER_PROGRAM),
4444
moduleRef.get(VersionManagerService),
45-
moduleRef.get(PassTroughService),
45+
moduleRef.get(PassThroughService),
4646
)
4747
})
4848

@@ -55,7 +55,7 @@ describe('AppModule', () => {
5555
process.argv = ['foo', 'baz']
5656

5757
programMock.parse.mockImplementation(() => {
58-
expect(passTroughServiceMock.init).toBeCalledTimes(1)
58+
expect(passThroughServiceMock.init).toBeCalledTimes(1)
5959
expect(versionManagerServiceMock.downloadIfNeeded).toBeCalledTimes(1)
6060
})
6161
})

apps/generator-cli/src/app/app.module.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as url from 'url';
55

66
import { COMMANDER_PROGRAM, LOGGER } from './constants';
77
import { VersionManagerController } from './controllers/version-manager.controller';
8-
import { ConfigService, GeneratorService, PassTroughService, UIService, VersionManagerService } from './services';
8+
import { ConfigService, GeneratorService, PassThroughService, UIService, VersionManagerService } from './services';
99

1010
let proxyConfig: AxiosProxyConfig;
1111
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
@@ -31,7 +31,7 @@ if (proxyUrl) {
3131
UIService,
3232
ConfigService,
3333
GeneratorService,
34-
PassTroughService,
34+
PassThroughService,
3535
VersionManagerService,
3636
{
3737
provide: COMMANDER_PROGRAM,
@@ -45,7 +45,7 @@ export class AppModule implements OnApplicationBootstrap {
4545
constructor(
4646
@Inject(COMMANDER_PROGRAM) private readonly program: Command,
4747
private readonly versionManager: VersionManagerService,
48-
private readonly passTroughService: PassTroughService
48+
private readonly passThroughService: PassThroughService
4949
) {
5050
}
5151

@@ -60,7 +60,7 @@ export class AppModule implements OnApplicationBootstrap {
6060
}
6161

6262
await this.versionManager.downloadIfNeeded(selectedVersion);
63-
await this.passTroughService.init();
63+
await this.passThroughService.init();
6464
this.program.parse(process.argv);
6565

6666
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export class PassthroughCommandMock {
2+
name = jest.fn().mockReturnValue(this._name);
3+
options: Record<string, string> = {};
4+
5+
parseOptions = jest.fn().mockImplementation(() => {
6+
const result = this.args.find(a => a.startsWith('--custom-generator'))?.split('=')[1];
7+
this.options.customGenerator = result || undefined;
8+
this.args = this.args.filter(a => !a.startsWith('--custom-generator'));
9+
return this.opts();
10+
});
11+
12+
helpInformation = jest.fn().mockReturnValue('has custom generator');
13+
14+
opts = jest.fn().mockImplementation(() => ({ ...this.options, unknown: this.args}));
15+
16+
constructor(private _name: string, public args: string[]) { }
17+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export * from './ui.service'
22
export * from './config.service'
33
export * from './generator.service'
4-
export * from './pass-trough.service'
4+
export * from './pass-through.service'
55
export * from './version-manager.service'

apps/generator-cli/src/app/services/pass-trough.service.spec.ts renamed to apps/generator-cli/src/app/services/pass-through.service.spec.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import {Test} from '@nestjs/testing';
2-
import {PassTroughService} from './pass-trough.service';
2+
import {PassThroughService} from './pass-through.service';
33
import {mocked} from 'ts-jest/utils';
44
import {COMMANDER_PROGRAM, LOGGER} from '../constants';
55
import {VersionManagerService} from './version-manager.service';
66
import {noop} from 'rxjs';
77
import {CommandMock} from '../mocks/command.mock';
8+
import {PassthroughCommandMock} from '../mocks/passthrough-command.mock';
89
import {GeneratorService} from './generator.service';
910

1011
jest.mock('child_process');
1112
// eslint-disable-next-line @typescript-eslint/no-var-requires
1213
const childProcess = mocked(require('child_process'), true)
1314

14-
describe('PassTroughService', () => {
15+
describe('PassThroughService', () => {
1516

16-
let fixture: PassTroughService;
17+
let fixture: PassThroughService;
1718
let commandMock: CommandMock;
1819

1920
const log = jest.fn()
@@ -26,15 +27,15 @@ describe('PassTroughService', () => {
2627

2728
const moduleRef = await Test.createTestingModule({
2829
providers: [
29-
PassTroughService,
30+
PassThroughService,
3031
{provide: VersionManagerService, useValue: {filePath, getSelectedVersion}},
3132
{provide: GeneratorService, useValue: {generate, enabled: true}},
3233
{provide: COMMANDER_PROGRAM, useValue: commandMock},
3334
{provide: LOGGER, useValue: {log}},
3435
],
3536
}).compile();
3637

37-
fixture = moduleRef.get(PassTroughService);
38+
fixture = moduleRef.get(PassThroughService);
3839
});
3940

4041
describe('API', () => {
@@ -130,9 +131,10 @@ describe('PassTroughService', () => {
130131
['completion', ''],
131132
])('%s', (cmd, desc) => {
132133

133-
const cmdMock = {name: () => cmd, args: ['foo', 'baz']};
134+
let cmdMock: PassthroughCommandMock;
134135

135136
beforeEach(() => {
137+
cmdMock = new PassthroughCommandMock(cmd, ['foo', 'baz']);
136138
const on = jest.fn();
137139
childProcess.spawn.mockReset().mockReturnValue({on})
138140
})
@@ -175,15 +177,34 @@ describe('PassTroughService', () => {
175177
)
176178
})
177179

180+
it('can delegate with custom jar', () => {
181+
delete process.env['JAVA_OPTS'];
182+
const args = [...cmdMock.args];
183+
cmdMock.args.push('--custom-generator=../some/custom.jar');
184+
commandMock.commands[cmd].action(cmdMock)
185+
const cpDelimiter = process.platform === "win32" ? ';' : ':';
186+
expect(childProcess.spawn).toHaveBeenNthCalledWith(
187+
1,
188+
`java -cp "${['/some/path/to/4.2.1.jar', '../some/custom.jar'].join(cpDelimiter)}" org.openapitools.codegen.OpenAPIGenerator`,
189+
[cmd, ...args],
190+
{
191+
stdio: 'inherit',
192+
shell: true
193+
}
194+
)
195+
})
196+
178197
if (cmd === 'help') {
179198
it('prints the help info and does not delegate, if args length = 0', () => {
180199
childProcess.spawn.mockReset()
181200
cmdMock.args = []
182-
const logSpy = jest.spyOn(console, 'log').mockImplementationOnce(noop)
201+
const logSpy = jest.spyOn(console, 'log').mockImplementation(noop)
183202
commandMock.commands[cmd].action(cmdMock)
184203
expect(childProcess.spawn).toBeCalledTimes(0)
185204
expect(commandMock.helpInformation).toBeCalledTimes(1)
186-
expect(logSpy).toHaveBeenNthCalledWith(1, 'some help text')
205+
expect(logSpy).toHaveBeenCalledTimes(2);
206+
expect(logSpy).toHaveBeenNthCalledWith(1, 'some help text');
207+
expect(logSpy).toHaveBeenNthCalledWith(2, 'has custom generator');
187208
})
188209
}
189210

apps/generator-cli/src/app/services/pass-trough.service.ts renamed to apps/generator-cli/src/app/services/pass-through.service.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { exec, spawn } from 'child_process';
88
import { GeneratorService } from './generator.service';
99

1010
@Injectable()
11-
export class PassTroughService {
11+
export class PassThroughService {
1212

1313
constructor(
1414
@Inject(LOGGER) private readonly logger: LOGGER,
@@ -24,13 +24,15 @@ export class PassTroughService {
2424
this.program
2525
.command(command, { hidden: !desc })
2626
.allowUnknownOption()
27+
.option("--custom-generator <generator>", "Custom generator to use alongside 'generate'", "")
2728
.description(desc)
2829
.action(async (cmd: Command) => {
29-
30-
if (cmd.args.length === 0) {
30+
const args = cmd.parseOptions(cmd.args).unknown;
31+
if (args.length === 0) {
3132
switch (cmd.name()) {
3233
case 'help':
3334
console.log(this.program.helpInformation());
35+
console.log(cmd.helpInformation());
3436
return;
3537
case 'generate':
3638
if (this.generatorService.enabled) {
@@ -43,16 +45,17 @@ export class PassTroughService {
4345
}
4446
}
4547

46-
this.passTrough([cmd.name(), ...cmd.args]);
48+
this.passThrough([cmd.name(), ...args], cmd.opts().customGenerator);
4749
});
4850
});
4951

5052
}
5153

52-
public passTrough = (args: string[] = []) => spawn(this.cmd(), args, {
53-
stdio: 'inherit',
54-
shell: true
55-
}).on('exit', process.exit);
54+
public passThrough = (args: string[] = [], customGenerator: string) =>
55+
spawn(this.cmd(customGenerator), args, {
56+
stdio: 'inherit',
57+
shell: true
58+
}).on('exit', process.exit);
5659

5760
private getCommands = async (): Promise<[string, string | undefined][]> => {
5861

@@ -85,8 +88,13 @@ export class PassTroughService {
8588
});
8689
});
8790

88-
private cmd() {
89-
return ['java', process.env['JAVA_OPTS'], `-jar "${this.versionManager.filePath()}"`].filter(isString).join(' ');
91+
private cmd(customJarPath = '') {
92+
const cliPath = this.versionManager.filePath();
93+
const cpDelimiter = process.platform === "win32" ? ';' : ':';
94+
const subCmd = customJarPath
95+
? `-cp "${[cliPath, customJarPath].join(cpDelimiter)}" org.openapitools.codegen.OpenAPIGenerator`
96+
: `-jar "${cliPath}"`;
97+
return ['java', process.env['JAVA_OPTS'], subCmd].filter(isString).join(' ');
9098
}
9199

92100
}

0 commit comments

Comments
 (0)