Skip to content

Commit dd916c7

Browse files
committed
feat(placeholders): be able to use environment variables
This commit allows to use environment variables in the openapitools.json configuration file.
1 parent 72265dd commit dd916c7

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

apps/generator-cli/src/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ is automatically used to generate your code. 🎉
175175
| relDir | directory name of file relative to the glob provided | docs |
176176
| relPath | file name and extension of file relative to the glob provided | docs/auth.yaml |
177177
| ext | just file extension | yaml |
178+
| env.<name> | environment variable (use ${env.name} syntax) | |
178179

179180
### Using custom / private maven registry
180181

@@ -196,6 +197,18 @@ If you're using a private maven registry you can configure the `downloadUrl` and
196197

197198
If the `version` property param is set it is not necessary to configure the `queryUrl`.
198199

200+
`queryUrl` and `downloadUrl` can use the following placeholders:
201+
202+
| placeholder | description |
203+
|-------------|----------------------------------------------------|
204+
| groupId | maven groupId where '.' has been replace with / |
205+
| artifactId | maven artifactId where '.' has been replace with / |
206+
| versionName | maven version (only for downloadUrl) |
207+
| group.id | maven groupId |
208+
| artifact.id | maven artifactId |
209+
| env.<name> | environment variable name |
210+
211+
199212
### Use locally built JAR
200213
In order to use a locally built jar of the generator CLI, you can copy the jar from your local build (i.e. if you were to `build` the [OpenAPITools/openapi-generator](https://github.com/OpenAPITools/openapi-generator) repository it would be in `~/openapi-generator/modules/openapi-generator-cli/target/openapi-generator-cli.jar`) into `./node_modules/@openapitools/openapi-generator-cli/versions/` and change the `version` in the `openapitools.json` file to the base name of the jar file.
201214
E.g.:

apps/generator-cli/src/app/services/config.service.spec.ts

+35
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,41 @@ describe('ConfigService', () => {
9090
);
9191
});
9292
});
93+
94+
describe('the config has values having placeholders', () => {
95+
beforeEach(() => {
96+
fs.readJSONSync.mockReturnValue({
97+
$schema: 'foo.json',
98+
spaces: 4,
99+
'generator-cli': {
100+
version: '1.2.3',
101+
repository: {
102+
queryUrl: 'https://${env.__unit_test_username}:${env.__unit_test_password}@server/api',
103+
downloadUrl: 'https://${env.__unit_test_non_matching}@server/api'
104+
}
105+
},
106+
});
107+
process.env['__unit_test_username'] = 'myusername';
108+
process.env['__unit_test_password'] = 'mypassword';
109+
});
110+
111+
afterEach(() => {
112+
delete process.env['__unit_test_username'];
113+
delete process.env['__unit_test_password'];
114+
})
115+
116+
it('verify placeholder replaced with env vars', () => {
117+
const value = fixture.get('generator-cli.repository.queryUrl');
118+
119+
expect(value).toEqual('https://myusername:mypassword@server/api');
120+
});
121+
122+
it('verify placeholders not matching env vars are not replaced', () => {
123+
const value = fixture.get('generator-cli.repository.downloadUrl');
124+
125+
expect(value).toEqual('https://${env.__unit_test_non_matching}@server/api');
126+
});
127+
});
93128
});
94129

95130
describe('has()', () => {

apps/generator-cli/src/app/services/config.service.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,43 @@ export class ConfigService {
6060
private read() {
6161
fs.ensureFileSync(this.configFile)
6262

63-
return merge(
63+
const config = merge(
6464
this.defaultConfig,
6565
fs.readJSONSync(this.configFile, {throws: false, encoding: 'utf8'}),
6666
)
67+
68+
return this.replacePlaceholders(config)
6769
}
6870

6971
private write(config) {
7072
fs.writeJSONSync(this.configFile, config, {encoding: 'utf8', spaces: config.spaces || 2})
7173
}
7274

75+
private replacePlaceholders(config: any): any {
76+
const envVariables = Object.fromEntries(
77+
Object.entries(process.env).map(([key, value]) => [`env.${key}`, value])
78+
);
79+
const placeholders = {
80+
...envVariables
81+
};
82+
const replacePlaceholderInString = (str: string): string => {
83+
return str.replace(/\${(.*?)}/g, (match, p1) => {
84+
const key = p1.trim();
85+
return placeholders[key] !== undefined ? placeholders[key] : match;
86+
});
87+
};
88+
const traverseAndReplace = (obj: any): any => {
89+
if (typeof obj === 'string') {
90+
return replacePlaceholderInString(obj);
91+
} else if (Array.isArray(obj)) {
92+
return obj.map(item => traverseAndReplace(item));
93+
} else if (obj !== null && typeof obj === 'object') {
94+
return Object.fromEntries(
95+
Object.entries(obj).map(([key, value]) => [key, traverseAndReplace(value)])
96+
);
97+
}
98+
return obj; // Return the value as is if it's not a string, array, or object
99+
};
100+
return traverseAndReplace(config);
101+
}
73102
}

0 commit comments

Comments
 (0)