diff --git a/packages/insomnia-cli/package-lock.json b/packages/insomnia-cli/package-lock.json index 930f337667..73fde0768b 100644 --- a/packages/insomnia-cli/package-lock.json +++ b/packages/insomnia-cli/package-lock.json @@ -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 + } + } } } } diff --git a/packages/insomnia-cli/src/__tests__/__snapshots__/inso-snapshot.test.js.snap b/packages/insomnia-cli/src/__tests__/__snapshots__/inso-snapshot.test.js.snap index e96fc8aa8b..4d79340dab 100644 --- a/packages/insomnia-cli/src/__tests__/__snapshots__/inso-snapshot.test.js.snap +++ b/packages/insomnia-cli/src/__tests__/__snapshots__/inso-snapshot.test.js.snap @@ -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 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 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] Generate configuration from an api spec - help [command] display help for command" + config [options] 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] +"Usage: inso generate config [options] 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 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" `; diff --git a/packages/insomnia-cli/src/__tests__/cli.test.js b/packages/insomnia-cli/src/__tests__/cli.test.js index 185e6b785f..34ef491b34 100644 --- a/packages/insomnia-cli/src/__tests__/cli.test.js +++ b/packages/insomnia-cli/src/__tests__/cli.test.js @@ -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', + }), + ); }); }); diff --git a/packages/insomnia-cli/src/__tests__/util.test.js b/packages/insomnia-cli/src/__tests__/util.test.js new file mode 100644 index 0000000000..41ecbf08d4 --- /dev/null +++ b/packages/insomnia-cli/src/__tests__/util.test.js @@ -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(' ')); + }); +}); diff --git a/packages/insomnia-cli/src/cli.js b/packages/insomnia-cli/src/cli.js index d7fbe24e95..62f3575c09 100755 --- a/packages/insomnia-cli/src/cli.js +++ b/packages/insomnia-cli/src/cli.js @@ -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 ') + .command('config ') .description('Generate configuration from an api spec') .requiredOption( '-t, --type ', `the type of configuration to generate, options are [${conversionTypes}]`, ) .option('-o, --output ', '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, exitOverride?: boolean): void { createCommand(!!exitOverride) .version(getVersion(), '-v, --version') .description('A CLI for Insomnia!') + .option('--workingDir ', 'Working directory') .addCommand(makeGenerateCommand(!!exitOverride)) - .parse(args); + .parseAsync(args) + .catch(err => console.log('An error occurred', err)); } diff --git a/packages/insomnia-cli/src/commands/__tests__/generate.test.js b/packages/insomnia-cli/src/commands/__tests__/generate.test.js index 2fc9728ce4..d22c220928 100644 --- a/packages/insomnia-cli/src/commands/__tests__/generate.test.js +++ b/packages/insomnia-cli/src/commands/__tests__/generate.test.js @@ -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(); }); }); diff --git a/packages/insomnia-cli/src/commands/generate.js b/packages/insomnia-cli/src/commands/generate.js index f5b7f84300..da663cfbb0 100644 --- a/packages/insomnia-cli/src/commands/generate.js +++ b/packages/insomnia-cli/src/commands/generate.js @@ -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, 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 { +export async function generateConfig( + identifier: string, + options: GenerateConfigOptions, +): Promise { 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)); diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Malformed/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Malformed/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml new file mode 100755 index 0000000000..2c4b7f6474 --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Malformed/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml @@ -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 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml new file mode 100755 index 0000000000..b54ee1cd5f --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo-malformed-insomnia/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml @@ -0,0 +1,8 @@ +_id: wrk_012d4860c7da418a85ffea7406e1292a +created: 1589851906270 +description: "" +modified: 1592254074771 +name: Global Security 1.2 +parentId: null +scope: spec +type: Workspace diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo-without-insomnia/blank.js b/packages/insomnia-cli/src/db/__fixtures__/git-repo-without-insomnia/blank.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/ApiSpec/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/ApiSpec/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml new file mode 100755 index 0000000000..2c4b7f6474 --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/ApiSpec/spc_46c5a4a40e83445a9bd9d9758b86c16c.yml @@ -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 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_ca046a738f001eb3090261a537b1b78f86c2094c.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_ca046a738f001eb3090261a537b1b78f86c2094c.yml new file mode 100755 index 0000000000..8eced02ede --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_ca046a738f001eb3090261a537b1b78f86c2094c.yml @@ -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 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_env_ca046a738f001eb3090261a537b1b78f86c2094c_sub.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_env_ca046a738f001eb3090261a537b1b78f86c2094c_sub.yml new file mode 100755 index 0000000000..354252fb22 --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Environment/env_env_ca046a738f001eb3090261a537b1b78f86c2094c_sub.yml @@ -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 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292a21946b60.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292a21946b60.yml new file mode 100755 index 0000000000..b5e8dd00ea --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292a21946b60.yml @@ -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" diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292ab410454b.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292ab410454b.yml new file mode 100755 index 0000000000..f36b742a8a --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Request/req_wrk_012d4860c7da418a85ffea7406e1292ab410454b.yml @@ -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" diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/RequestGroup/fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/RequestGroup/fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249.yml new file mode 100755 index 0000000000..672cb2da92 --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/RequestGroup/fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249.yml @@ -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 diff --git a/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml new file mode 100755 index 0000000000..b54ee1cd5f --- /dev/null +++ b/packages/insomnia-cli/src/db/__fixtures__/git-repo/.insomnia/Workspace/wrk_012d4860c7da418a85ffea7406e1292a.yml @@ -0,0 +1,8 @@ +_id: wrk_012d4860c7da418a85ffea7406e1292a +created: 1589851906270 +description: "" +modified: 1592254074771 +name: Global Security 1.2 +parentId: null +scope: spec +type: Workspace diff --git a/packages/insomnia-cli/src/db/__tests__/mem-db.test.js b/packages/insomnia-cli/src/db/__tests__/mem-db.test.js new file mode 100644 index 0000000000..4e14332318 --- /dev/null +++ b/packages/insomnia-cli/src/db/__tests__/mem-db.test.js @@ -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); + }); + }); +}); diff --git a/packages/insomnia-cli/src/db/mem-db.js b/packages/insomnia-cli/src/db/mem-db.js new file mode 100644 index 0000000000..afdb8f7749 --- /dev/null +++ b/packages/insomnia-cli/src/db/mem-db.js @@ -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, + Environment: Map, + Request: Map, + RequestGroup: Map, + Workspace: Map, +|}; + +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>, +}; + +export const gitDataDirDb = async ({ dir, filterTypes }: Options): Promise => { + 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, fileName: string): Promise => { + // 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; +}; diff --git a/packages/insomnia-cli/src/db/types.js b/packages/insomnia-cli/src/db/types.js new file mode 100644 index 0000000000..325eb0491f --- /dev/null +++ b/packages/insomnia-cli/src/db/types.js @@ -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; diff --git a/packages/insomnia-cli/src/util.js b/packages/insomnia-cli/src/util.js index 2911b712a7..37b63bc012 100644 --- a/packages/insomnia-cli/src/util.js +++ b/packages/insomnia-cli/src/util.js @@ -2,10 +2,13 @@ import commander from 'commander'; import * as packageJson from '../package.json'; +export type GlobalOptions = {| + 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(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; +}