mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-20 22:27:24 -04:00
Support CLI operations against the .insomnia git data directory (#2294)
This commit is contained in:
112
packages/insomnia-cli/package-lock.json
generated
112
packages/insomnia-cli/package-lock.json
generated
@@ -1879,7 +1879,6 @@
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
@@ -2265,6 +2264,11 @@
|
||||
"unset-value": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"call-me-maybe": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
|
||||
"integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms="
|
||||
},
|
||||
"caller-callsite": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
|
||||
@@ -2757,8 +2761,7 @@
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "4.3.0",
|
||||
@@ -5286,7 +5289,6 @@
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
|
||||
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
@@ -5350,6 +5352,16 @@
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-ref-parser": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-7.1.4.tgz",
|
||||
"integrity": "sha512-AD7bvav0vak1/63w3jH8F7eHId/4E4EPdMAEZhGxtjktteUv9dnNB/cJy6nVnMyoTPBJnLwFK6tiQPSTeleCtQ==",
|
||||
"requires": {
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"ono": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
@@ -5441,6 +5453,16 @@
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
|
||||
},
|
||||
"lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||
},
|
||||
"lodash.sortby": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||
@@ -5794,6 +5816,32 @@
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"ono": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ono/-/ono-6.0.1.tgz",
|
||||
"integrity": "sha512-5rdYW/106kHqLeG22GE2MHKq+FlsxMERZev9DCzQX1zwkxnFwBivSn5i17a5O/rDmOJOdf4Wyt80UZljzx9+DA=="
|
||||
},
|
||||
"openapi-2-kong": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/openapi-2-kong/-/openapi-2-kong-2.2.6.tgz",
|
||||
"integrity": "sha512-GggreyB+ZbkjO9MqDIZOm/M9mrSdVdsSyYYx0uglz1S7EhC0YAN+RNIFJWD1aZ9xkEXmzpjaIT12/KjyHb7Svw==",
|
||||
"requires": {
|
||||
"slugify": "^1.3.6",
|
||||
"swagger-parser": "^8.0.3",
|
||||
"url-join": "^4.0.1",
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"openapi-schemas": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-schemas/-/openapi-schemas-1.0.3.tgz",
|
||||
"integrity": "sha512-KtMWcK2VtOS+nD8RKSIyScJsj8JrmVWcIX7Kjx4xEHijFYuvMTDON8WfeKOgeSb4uNG6UsqLj5Na7nKbSav9RQ=="
|
||||
},
|
||||
"openapi-types": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-1.3.5.tgz",
|
||||
"integrity": "sha512-11oi4zYorsgvg5yBarZplAqbpev5HkuVNPlZaPTknPDzAynq+lnJdXAmruGWP0s+dNYZS7bjM+xrTpJw7184Fg=="
|
||||
},
|
||||
"opencollective-postinstall": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||
@@ -6652,6 +6700,11 @@
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"slugify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.0.tgz",
|
||||
"integrity": "sha512-FtLNsMGBSRB/0JOE2A0fxlqjI6fJsgHGS13iTuVT28kViI4JjUiNqp/vyis0ZXYcMnpR3fzGNkv+6vRlI2GwdQ=="
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
|
||||
@@ -6861,8 +6914,7 @@
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
@@ -7019,6 +7071,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"swagger-methods": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-2.0.2.tgz",
|
||||
"integrity": "sha512-/RNqvBZkH8+3S/FqBPejHxJxZenaYq3MrpeXnzi06aDIS39Mqf5YCUNb/ZBjsvFFt8h9FxfKs8EXPtcYdfLiRg=="
|
||||
},
|
||||
"swagger-parser": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-8.0.4.tgz",
|
||||
"integrity": "sha512-KGRdAaMJogSEB7sPKI31ptKIWX8lydEDAwWgB4pBMU7zys5cd54XNhoPSVlTxG/A3LphjX47EBn9j0dOGyzWbA==",
|
||||
"requires": {
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"json-schema-ref-parser": "^7.1.3",
|
||||
"ono": "^6.0.0",
|
||||
"openapi-schemas": "^1.0.2",
|
||||
"openapi-types": "^1.3.5",
|
||||
"swagger-methods": "^2.0.1",
|
||||
"z-schema": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
@@ -7273,6 +7344,11 @@
|
||||
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
|
||||
"dev": true
|
||||
},
|
||||
"url-join": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
||||
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
@@ -7322,6 +7398,11 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"validator": {
|
||||
"version": "12.2.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
|
||||
"integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
@@ -7534,6 +7615,25 @@
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"z-schema": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.3.tgz",
|
||||
"integrity": "sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==",
|
||||
"requires": {
|
||||
"commander": "^2.7.1",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"validator": "^12.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ exports[`Snapshot for "inso --help" 1`] = `
|
||||
A CLI for Insomnia!
|
||||
|
||||
Options:
|
||||
-v, --version output the version number
|
||||
-h, --help display help for command
|
||||
-v, --version output the version number
|
||||
--workingDir <dir> Working directory
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso -h" 1`] = `
|
||||
@@ -20,12 +21,13 @@ exports[`Snapshot for "inso -h" 1`] = `
|
||||
A CLI for Insomnia!
|
||||
|
||||
Options:
|
||||
-v, --version output the version number
|
||||
-h, --help display help for command
|
||||
-v, --version output the version number
|
||||
--workingDir <dir> Working directory
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso generate -h" 1`] = `
|
||||
@@ -34,15 +36,15 @@ exports[`Snapshot for "inso generate -h" 1`] = `
|
||||
Code generation utilities
|
||||
|
||||
Options:
|
||||
-h, --help display help for command
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
config [options] <filePath> Generate configuration from an api spec
|
||||
help [command] display help for command"
|
||||
config [options] <identifier> Generate configuration from an api spec
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso generate config -h" 1`] = `
|
||||
"Usage: inso generate config [options] <filePath>
|
||||
"Usage: inso generate config [options] <identifier>
|
||||
|
||||
Generate configuration from an api spec
|
||||
|
||||
@@ -59,10 +61,11 @@ exports[`Snapshot for "inso help" 1`] = `
|
||||
A CLI for Insomnia!
|
||||
|
||||
Options:
|
||||
-v, --version output the version number
|
||||
-h, --help display help for command
|
||||
-v, --version output the version number
|
||||
--workingDir <dir> Working directory
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
generate Code generation utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
@@ -36,19 +36,30 @@ describe('cli', () => {
|
||||
|
||||
it('should call generateConfig with undefined output argument', () => {
|
||||
inso('generate config -t declarative file.yaml');
|
||||
expect(generateConfig).toHaveBeenCalledWith({
|
||||
filePath: 'file.yaml',
|
||||
expect(generateConfig).toHaveBeenCalledWith('file.yaml', {
|
||||
type: 'declarative',
|
||||
output: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should call generateConfig with all expected arguments', () => {
|
||||
inso('generate config -t kubernetes -o output.yaml file.yaml');
|
||||
expect(generateConfig).toHaveBeenCalledWith({
|
||||
filePath: 'file.yaml',
|
||||
type: 'kubernetes',
|
||||
output: 'output.yaml',
|
||||
});
|
||||
expect(generateConfig).toHaveBeenCalledWith(
|
||||
'file.yaml',
|
||||
expect.objectContaining({
|
||||
type: 'kubernetes',
|
||||
output: 'output.yaml',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should call generateConfig with global option', () => {
|
||||
inso('generate config -t kubernetes --workingDir testing/dir file.yaml');
|
||||
expect(generateConfig).toHaveBeenCalledWith(
|
||||
'file.yaml',
|
||||
expect.objectContaining({
|
||||
type: 'kubernetes',
|
||||
workingDir: 'testing/dir',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
23
packages/insomnia-cli/src/__tests__/util.test.js
Normal file
23
packages/insomnia-cli/src/__tests__/util.test.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// @flow
|
||||
import commander from 'commander';
|
||||
import { getAllOptions } from '../util';
|
||||
|
||||
describe('getAllOptions()', () => {
|
||||
it('should combine options from all commands into one object', () => {
|
||||
const command = new commander.Command('command');
|
||||
|
||||
command
|
||||
.command('subCommand')
|
||||
.option('-s, --subCmd')
|
||||
.action(cmd => {
|
||||
expect(getAllOptions(cmd)).toEqual({
|
||||
global: true,
|
||||
subCmd: true,
|
||||
});
|
||||
});
|
||||
|
||||
const parent = new commander.Command().option('-g, --global').addCommand(command);
|
||||
|
||||
parent.parse('node test command subCommand --global --subCmd'.split(' '));
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
import { ConversionTypeMap, generateConfig } from './commands/generate';
|
||||
import { getVersion, createCommand } from './util';
|
||||
import { getVersion, createCommand, getAllOptions } from './util';
|
||||
|
||||
function makeGenerateCommand(exitOverride: boolean) {
|
||||
// inso generate
|
||||
@@ -10,14 +10,14 @@ function makeGenerateCommand(exitOverride: boolean) {
|
||||
|
||||
// inso generate config -t kubernetes config.yaml
|
||||
generate
|
||||
.command('config <filePath>')
|
||||
.command('config <identifier>')
|
||||
.description('Generate configuration from an api spec')
|
||||
.requiredOption(
|
||||
'-t, --type <value>',
|
||||
`the type of configuration to generate, options are [${conversionTypes}]`,
|
||||
)
|
||||
.option('-o, --output <path>', 'the output path')
|
||||
.action((filePath, opts) => generateConfig({ filePath, ...opts }));
|
||||
.action((identifier, cmd) => generateConfig(identifier, getAllOptions(cmd)));
|
||||
|
||||
return generate;
|
||||
}
|
||||
@@ -31,6 +31,8 @@ export function go(args?: Array<string>, exitOverride?: boolean): void {
|
||||
createCommand(!!exitOverride)
|
||||
.version(getVersion(), '-v, --version')
|
||||
.description('A CLI for Insomnia!')
|
||||
.option('--workingDir <dir>', 'Working directory')
|
||||
.addCommand(makeGenerateCommand(!!exitOverride))
|
||||
.parse(args);
|
||||
.parseAsync(args)
|
||||
.catch(err => console.log('An error occurred', err));
|
||||
}
|
||||
|
||||
@@ -6,13 +6,6 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
jest.mock('openapi-2-kong');
|
||||
jest.mock('fs');
|
||||
|
||||
const base: GenerateConfigOptions = {
|
||||
filePath: 'file.yaml',
|
||||
type: 'kubernetes',
|
||||
output: undefined,
|
||||
};
|
||||
|
||||
describe('generateConfig()', () => {
|
||||
// make flow happy
|
||||
@@ -20,10 +13,18 @@ describe('generateConfig()', () => {
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const base: GenerateConfigOptions = {
|
||||
type: 'kubernetes',
|
||||
output: undefined,
|
||||
};
|
||||
|
||||
const filePath = 'file.yaml';
|
||||
|
||||
it('should should not generate if type arg is invalid', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
await generateConfig({ ...base, type: 'invalid' });
|
||||
await generateConfig(filePath, { ...base, type: 'invalid' });
|
||||
|
||||
expect(o2k.generate).not.toHaveBeenCalled();
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
@@ -35,20 +36,34 @@ describe('generateConfig()', () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
mock(o2k.generate).mockResolvedValue({ documents: ['a', 'b'] });
|
||||
|
||||
await generateConfig(base);
|
||||
await generateConfig(filePath, base);
|
||||
|
||||
expect(o2k.generate).toHaveBeenCalledWith(base.filePath, ConversionTypeMap[base.type]);
|
||||
expect(o2k.generate).toHaveBeenCalledWith(filePath, ConversionTypeMap[base.type]);
|
||||
expect(consoleSpy).toHaveBeenCalledWith('a\n---\nb\n');
|
||||
});
|
||||
|
||||
it('should load identifier from database', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
mock(o2k.generateFromString).mockResolvedValue({ documents: ['a', 'b'] });
|
||||
|
||||
await generateConfig('spc_46c5a4a40e83445a9bd9d9758b86c16c', {
|
||||
...base,
|
||||
workingDir: 'src/db/__fixtures__/git-repo',
|
||||
});
|
||||
|
||||
expect(o2k.generateFromString).toHaveBeenCalled();
|
||||
expect(consoleSpy).toHaveBeenCalledWith('a\n---\nb\n');
|
||||
});
|
||||
|
||||
it('should write converted documents to file system', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
const writeFileSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
|
||||
mock(o2k.generate).mockResolvedValue({ documents: ['a', 'b'] });
|
||||
|
||||
await generateConfig({ ...base, output: 'output.yaml' });
|
||||
await generateConfig(filePath, { ...base, output: 'output.yaml' });
|
||||
|
||||
expect(o2k.generate).toHaveBeenCalledWith(base.filePath, ConversionTypeMap[base.type]);
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(path.resolve('output.yaml'), 'a\n---\nb\n');
|
||||
expect(o2k.generate).toHaveBeenCalledWith(filePath, ConversionTypeMap[base.type]);
|
||||
expect(writeFileSpy).toHaveBeenCalledWith(path.resolve('output.yaml'), 'a\n---\nb\n');
|
||||
expect(consoleSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
// @flow
|
||||
import o2k from 'openapi-2-kong';
|
||||
import * as o2k from 'openapi-2-kong';
|
||||
import YAML from 'yaml';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import type { GlobalOptions } from '../util';
|
||||
import { gitDataDirDb } from '../db/mem-db';
|
||||
|
||||
export const ConversionTypeMap: { [string]: ConversionResultType } = {
|
||||
kubernetes: 'kong-for-kubernetes',
|
||||
declarative: 'kong-declarative-config',
|
||||
};
|
||||
|
||||
export type GenerateConfigOptions = {|
|
||||
filePath: string,
|
||||
export type GenerateConfigOptions = GlobalOptions<{|
|
||||
type: $Keys<typeof ConversionTypeMap>,
|
||||
output?: string,
|
||||
|};
|
||||
|}>;
|
||||
|
||||
function validateOptions({ type }: GenerateConfigOptions): boolean {
|
||||
if (!ConversionTypeMap[type]) {
|
||||
@@ -25,14 +26,31 @@ function validateOptions({ type }: GenerateConfigOptions): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function generateConfig(options: GenerateConfigOptions): Promise<void> {
|
||||
export async function generateConfig(
|
||||
identifier: string,
|
||||
options: GenerateConfigOptions,
|
||||
): Promise<void> {
|
||||
if (!validateOptions(options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { type, output, filePath } = options;
|
||||
const { type, output, workingDir } = options;
|
||||
|
||||
const result = await o2k.generate(filePath, ConversionTypeMap[type]);
|
||||
const db = await gitDataDirDb({ dir: workingDir, filterTypes: ['ApiSpec'] });
|
||||
|
||||
let result: ConversionResult;
|
||||
|
||||
const specFromDb = db.ApiSpec.get(identifier);
|
||||
try {
|
||||
if (specFromDb?.contents) {
|
||||
result = await o2k.generateFromString(specFromDb.contents, ConversionTypeMap[type]);
|
||||
} else {
|
||||
result = await o2k.generate(identifier, ConversionTypeMap[type]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Config failed to generate', err);
|
||||
return;
|
||||
}
|
||||
|
||||
const yamlDocs = result.documents.map(d => YAML.stringify(d));
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
_id: spc_46c5a4a40e83445a9bd9d9758b86c16c
|
||||
contentType: yaml
|
||||
contents: |
|
||||
openapi: '3.0.2'
|
||||
info:
|
||||
title: Global Security
|
||||
version: '1.2'
|
||||
servers:
|
||||
- url: https://api.server.test/v1
|
||||
tags:
|
||||
- name: Folder
|
||||
|
||||
paths:
|
||||
/global:
|
||||
get:
|
||||
tags:
|
||||
- Folder
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
/override:
|
||||
get:
|
||||
security:
|
||||
- Key-Query: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
created: 1589851906273
|
||||
fileName: Global Security
|
||||
modified: 1592254074772
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: ApiSpec
|
||||
@@ -0,0 +1,8 @@
|
||||
_id: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
created: 1589851906270
|
||||
description: ""
|
||||
modified: 1592254074771
|
||||
name: Global Security 1.2
|
||||
parentId: null
|
||||
scope: spec
|
||||
type: Workspace
|
||||
@@ -0,0 +1,32 @@
|
||||
_id: spc_46c5a4a40e83445a9bd9d9758b86c16c
|
||||
contentType: yaml
|
||||
contents: |
|
||||
openapi: '3.0.2'
|
||||
info:
|
||||
title: Global Security
|
||||
version: '1.2'
|
||||
servers:
|
||||
- url: https://api.server.test/v1
|
||||
tags:
|
||||
- name: Folder
|
||||
|
||||
paths:
|
||||
/global:
|
||||
get:
|
||||
tags:
|
||||
- Folder
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
/override:
|
||||
get:
|
||||
security:
|
||||
- Key-Query: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
created: 1589851906273
|
||||
fileName: Global Security
|
||||
modified: 1592254074772
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: ApiSpec
|
||||
@@ -0,0 +1,14 @@
|
||||
_id: env_ca046a738f001eb3090261a537b1b78f86c2094c
|
||||
color: null
|
||||
created: 1589851906358
|
||||
data:
|
||||
base_url: "{{ scheme }}://{{ host }}{{ base_path }}"
|
||||
dataPropertyOrder:
|
||||
"&":
|
||||
- base_url
|
||||
isPrivate: false
|
||||
metaSortKey: 1589851906358
|
||||
modified: 1592254074769
|
||||
name: Base environment
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: Environment
|
||||
@@ -0,0 +1,14 @@
|
||||
_id: env_env_ca046a738f001eb3090261a537b1b78f86c2094c_sub
|
||||
color: null
|
||||
created: 1592252904087
|
||||
data:
|
||||
base_path: /v1
|
||||
host: api.server.test
|
||||
scheme: https
|
||||
dataPropertyOrder: null
|
||||
isPrivate: false
|
||||
metaSortKey: 1592252904087
|
||||
modified: 1592254074767
|
||||
name: OpenAPI env
|
||||
parentId: env_ca046a738f001eb3090261a537b1b78f86c2094c
|
||||
type: Environment
|
||||
@@ -0,0 +1,21 @@
|
||||
_id: req_wrk_012d4860c7da418a85ffea7406e1292a21946b60
|
||||
authentication: {}
|
||||
body: {}
|
||||
created: 1592254074764
|
||||
description: ""
|
||||
headers: []
|
||||
isPrivate: false
|
||||
metaSortKey: -1592254074764
|
||||
method: GET
|
||||
modified: 1592254074764
|
||||
name: /global
|
||||
parameters: []
|
||||
parentId: fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249
|
||||
settingDisableRenderRequestBody: false
|
||||
settingEncodeUrl: true
|
||||
settingFollowRedirects: global
|
||||
settingRebuildPath: true
|
||||
settingSendCookies: true
|
||||
settingStoreCookies: true
|
||||
type: Request
|
||||
url: "{{ base_url }}/global"
|
||||
@@ -0,0 +1,21 @@
|
||||
_id: req_wrk_012d4860c7da418a85ffea7406e1292ab410454b
|
||||
authentication: {}
|
||||
body: {}
|
||||
created: 1592254074762
|
||||
description: ""
|
||||
headers: []
|
||||
isPrivate: false
|
||||
metaSortKey: -1592254074762
|
||||
method: GET
|
||||
modified: 1592254074762
|
||||
name: /override
|
||||
parameters: []
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
settingDisableRenderRequestBody: false
|
||||
settingEncodeUrl: true
|
||||
settingFollowRedirects: global
|
||||
settingRebuildPath: true
|
||||
settingSendCookies: true
|
||||
settingStoreCookies: true
|
||||
type: Request
|
||||
url: "{{ base_url }}/override"
|
||||
@@ -0,0 +1,10 @@
|
||||
_id: fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249
|
||||
created: 1592254074765
|
||||
description: ""
|
||||
environment: {}
|
||||
environmentPropertyOrder: null
|
||||
metaSortKey: -1592254074765
|
||||
modified: 1592254074765
|
||||
name: Folder
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: RequestGroup
|
||||
@@ -0,0 +1,8 @@
|
||||
_id: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
created: 1589851906270
|
||||
description: ""
|
||||
modified: 1592254074771
|
||||
name: Global Security 1.2
|
||||
parentId: null
|
||||
scope: spec
|
||||
type: Workspace
|
||||
44
packages/insomnia-cli/src/db/__tests__/mem-db.test.js
Normal file
44
packages/insomnia-cli/src/db/__tests__/mem-db.test.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// @flow
|
||||
import path from 'path';
|
||||
import { gitDataDirDb } from '../mem-db';
|
||||
|
||||
describe('mem-db', () => {
|
||||
describe('seedGitDataDir()', () => {
|
||||
const fixturesPath = 'src/db/__fixtures__';
|
||||
|
||||
it('should seed with git-repo directory', async () => {
|
||||
const dir = path.join(fixturesPath, 'git-repo');
|
||||
const db = await gitDataDirDb({ dir });
|
||||
|
||||
expect(db.ApiSpec.size).toBe(1);
|
||||
expect(db.Environment.size).toBe(2);
|
||||
expect(db.Request.size).toBe(2);
|
||||
expect(db.RequestGroup.size).toBe(1);
|
||||
expect(db.Workspace.size).toBe(1);
|
||||
});
|
||||
|
||||
it('should seed with git-repo directory with filter', async () => {
|
||||
const dir = path.join(fixturesPath, 'git-repo');
|
||||
const db = await gitDataDirDb({ dir, filterTypes: ['Environment'] });
|
||||
|
||||
expect(db.ApiSpec.size).toBe(0);
|
||||
expect(db.Environment.size).toBe(2);
|
||||
expect(db.Request.size).toBe(0);
|
||||
expect(db.RequestGroup.size).toBe(0);
|
||||
expect(db.Workspace.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should safely continue if data directory not found', async () => {
|
||||
const dir = path.join(fixturesPath, 'git-repo-without-insomnia');
|
||||
const db = await gitDataDirDb({ dir });
|
||||
expect(db.ApiSpec.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should ignore unexpected type directories', async () => {
|
||||
const dir = path.join(fixturesPath, 'git-repo-malformed-insomnia');
|
||||
const db = await gitDataDirDb({ dir });
|
||||
|
||||
expect(db.Workspace.size).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
65
packages/insomnia-cli/src/db/mem-db.js
Normal file
65
packages/insomnia-cli/src/db/mem-db.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// @flow
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import YAML from 'yaml';
|
||||
import type { ApiSpec } from './types';
|
||||
|
||||
type Database = {|
|
||||
ApiSpec: Map<string, ApiSpec>,
|
||||
Environment: Map<string, Object>,
|
||||
Request: Map<string, Object>,
|
||||
RequestGroup: Map<string, Object>,
|
||||
Workspace: Map<string, Object>,
|
||||
|};
|
||||
|
||||
export const emptyDb = (): Database => ({
|
||||
ApiSpec: new Map(),
|
||||
Environment: new Map(),
|
||||
Request: new Map(),
|
||||
RequestGroup: new Map(),
|
||||
Workspace: new Map(),
|
||||
});
|
||||
|
||||
type Options = {
|
||||
dir?: string,
|
||||
filterTypes?: Array<$Keys<Database>>,
|
||||
};
|
||||
|
||||
export const gitDataDirDb = async ({ dir, filterTypes }: Options): Promise<Database> => {
|
||||
const db = emptyDb();
|
||||
const insomniaDir = path.normalize(path.join(dir || '.', '.insomnia'));
|
||||
|
||||
if (!fs.existsSync(insomniaDir)) {
|
||||
// TODO: control logging with verbose flag
|
||||
// console.log(`Directory not found: ${insomniaDir}`);
|
||||
return db;
|
||||
}
|
||||
|
||||
const readAndInsertDoc = async (type: $Keys<Database>, fileName: string): Promise<void> => {
|
||||
// Get contents of each file in type dir and insert into data
|
||||
const contents = await fs.promises.readFile(fileName);
|
||||
const obj = YAML.parse(contents.toString());
|
||||
|
||||
db[type].set(obj._id, obj);
|
||||
};
|
||||
|
||||
const types = filterTypes?.length ? filterTypes : Object.keys(db);
|
||||
|
||||
await Promise.all(
|
||||
types.map(async type => {
|
||||
// Get all files in type dir
|
||||
const typeDir = path.join(insomniaDir, type);
|
||||
if (!fs.existsSync(typeDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const files = await fs.promises.readdir(typeDir);
|
||||
return Promise.all(
|
||||
// Insert each file from each type
|
||||
files.map(file => readAndInsertDoc(type, path.join(insomniaDir, type, file))),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
return db;
|
||||
};
|
||||
23
packages/insomnia-cli/src/db/types.js
Normal file
23
packages/insomnia-cli/src/db/types.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// @flow
|
||||
|
||||
// These types should come from a shared location (maybe insomnia-importers?)
|
||||
// They represent the models that are read from an Insomnia data source
|
||||
// eg. git data directory, insomnia export format, etc
|
||||
|
||||
export type BaseModel = {
|
||||
_id: string,
|
||||
type: string,
|
||||
parentId: string,
|
||||
modified: number,
|
||||
created: number,
|
||||
};
|
||||
|
||||
type BaseApiSpec = {
|
||||
fileName: string,
|
||||
contentType: 'json' | 'yaml',
|
||||
contents: string,
|
||||
};
|
||||
|
||||
export const SpecName = 'ApiSpec';
|
||||
|
||||
export type ApiSpec = BaseModel & BaseApiSpec;
|
||||
@@ -2,10 +2,13 @@
|
||||
import commander from 'commander';
|
||||
import * as packageJson from '../package.json';
|
||||
|
||||
export type GlobalOptions<T> = {|
|
||||
workingDir?: string,
|
||||
...T,
|
||||
|};
|
||||
|
||||
export function createCommand(exitOverride: boolean, cmd?: string) {
|
||||
const command = new commander.Command(cmd)
|
||||
.storeOptionsAsProperties(false)
|
||||
.passCommandToAction(false);
|
||||
const command = new commander.Command(cmd).storeOptionsAsProperties(false);
|
||||
|
||||
if (exitOverride) {
|
||||
return command.exitOverride();
|
||||
@@ -17,3 +20,16 @@ export function createCommand(exitOverride: boolean, cmd?: string) {
|
||||
export function getVersion() {
|
||||
return packageJson.version;
|
||||
}
|
||||
|
||||
export function getAllOptions<T>(cmd: Object): T {
|
||||
let opts = {};
|
||||
let command = cmd;
|
||||
|
||||
do {
|
||||
// overwrite options with more specific ones
|
||||
opts = { ...command.opts(), ...opts };
|
||||
command = command.parent;
|
||||
} while (command);
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user