Skip to content

Commit

Permalink
feat: new CLI architecture (part 1) (#1200)
Browse files Browse the repository at this point in the history
  • Loading branch information
Amzani authored Jun 6, 2024
1 parent 74918ad commit 26853d7
Show file tree
Hide file tree
Showing 55 changed files with 514 additions and 433 deletions.
14 changes: 4 additions & 10 deletions src/commands/bundle.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Flags } from '@oclif/core';
import Command from '../base';
import Command from '../core/base';
import bundle from '@asyncapi/bundler';
import { promises } from 'fs';
import path from 'path';
import { Specification } from '../models/SpecificationFile';
import { Specification } from '../core/models/SpecificationFile';
import { Document } from '@asyncapi/bundler/lib/document';
import { bundleFlags } from '../core/flags/bundle.flags';

const { writeFile } = promises;

Expand All @@ -21,13 +21,7 @@ export default class Bundle extends Command {
'asyncapi bundle ./asyncapi.yaml -o final-asyncapi.yaml --base ../public-api/main.yaml --baseDir ./social-media/comments-service',
];

static flags = {
help: Flags.help({ char: 'h' }),
output: Flags.string({ char: 'o', description: 'The output file name. Omitting this flag the result will be printed in the console.' }),
base: Flags.string({ char: 'b', description: 'Path to the file which will act as a base. This is required when some properties need to be overwritten.' }),
baseDir: Flags.string({ char: 'd', description: 'One relative/absolute path to directory relative to which paths to AsyncAPI Documents that should be bundled will be resolved.' }),
xOrigin: Flags.boolean({ char: 'x', description: 'Pass this switch to generate properties "x-origin" that will contain historical values of dereferenced "$ref"s.' }),
};
static flags = bundleFlags();

async run() {
const { argv, flags } = await this.parse(Bundle);
Expand Down
14 changes: 4 additions & 10 deletions src/commands/config/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { Flags } from '@oclif/core';
import { join, resolve } from 'path';
import Command from '../../base';
import Command from '../../core/base';
import { promises as fPromises } from 'fs';
import { homedir } from 'os';
import { analyticsFlags } from '../../core/flags/config/analytics.flags';

const { readFile, writeFile } = fPromises;

export default class Analytics extends Command {
static readonly description = 'Enable or disable analytics for metrics collection';
static readonly flags = {
help: Flags.help({ char: 'h' }),
disable: Flags.boolean({ char: 'd', description: 'disable analytics', default: false }),
enable: Flags.boolean({ char: 'e', description: 'enable analytics', default: false }),
status: Flags.boolean({ char: 's', description: 'show current status of analytics' }),

};
static readonly flags = analyticsFlags();

async run() {
const { flags } = await this.parse(Analytics);
Expand Down Expand Up @@ -57,5 +51,5 @@ export default class Analytics extends Command {
this.error(`Unable to change your analytics configuration. Please check the following message for further info about the error:\n\n${e}`);
}
}
}
}
}
19 changes: 6 additions & 13 deletions src/commands/config/context/add.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { Flags, Args } from '@oclif/core';
import Command from '../../../base';
import { addContext, setCurrentContext } from '../../../models/Context';
import { Args } from '@oclif/core';
import Command from '../../../core/base';
import { addContext, setCurrentContext } from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { addFlags } from '../../../core/flags/config/context.flags';

export default class ContextAdd extends Command {
static description = 'Add a context to the store';
static flags = {
help: Flags.help({ char: 'h' }),
'set-current': Flags.boolean({
char: 's',
description: 'Set context being added as the current context',
default: false,
required: false,
})
};
static flags = addFlags();

static args = {
'context-name': Args.string({description: 'context name', required: true}),
Expand Down
12 changes: 5 additions & 7 deletions src/commands/config/context/current.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { Flags } from '@oclif/core';
import Command from '../../../base';
import { getCurrentContext, CONTEXT_FILE_PATH } from '../../../models/Context';
import Command from '../../../core/base';
import { getCurrentContext, CONTEXT_FILE_PATH } from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
ContextFileEmptyError,
ContextNotFoundError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextCurrent extends Command {
static description = 'Shows the current context that is being used';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

async run() {
let fileContent;
Expand Down
13 changes: 6 additions & 7 deletions src/commands/config/context/edit.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { Flags, Args } from '@oclif/core';
import Command from '../../../base';
import { editContext, CONTEXT_FILE_PATH } from '../../../models/Context';
import { Args } from '@oclif/core';
import Command from '../../../core/base';
import { editContext, CONTEXT_FILE_PATH } from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
ContextFileEmptyError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextEdit extends Command {
static description = 'Edit a context in the store';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

static args = {
'context-name': Args.string({description: 'context name', required: true}),
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/context/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { loadHelpClass } from '@oclif/core';
import Command from '../../../base';
import Command from '../../../core/base';

export default class Context extends Command {
static description =
Expand Down
11 changes: 5 additions & 6 deletions src/commands/config/context/init.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Flags, Args } from '@oclif/core';
import Command from '../../../base';
import { initContext } from '../../../models/Context';
import { Args } from '@oclif/core';
import Command from '../../../core/base';
import { initContext } from '../../../core/models/Context';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextInit extends Command {
static description = 'Initialize context';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

static contextFilePathMessage = `Specify directory in which context file should be created:
- current directory : asyncapi config context init . (default)
Expand Down
12 changes: 5 additions & 7 deletions src/commands/config/context/list.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { Flags } from '@oclif/core';
import Command from '../../../base';
import Command from '../../../core/base';
import {
loadContextFile,
isContextFileEmpty,
CONTEXT_FILE_PATH,
} from '../../../models/Context';
} from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextList extends Command {
static description = 'List all the stored contexts in the store';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

async run() {
try {
Expand Down
13 changes: 6 additions & 7 deletions src/commands/config/context/remove.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { Flags, Args } from '@oclif/core';
import Command from '../../../base';
import { removeContext, CONTEXT_FILE_PATH } from '../../../models/Context';
import { Args } from '@oclif/core';
import Command from '../../../core/base';
import { removeContext, CONTEXT_FILE_PATH } from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
ContextFileEmptyError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextRemove extends Command {
static description = 'Delete a context from the store';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

static args = {
'context-name': Args.string({description: 'Name of the context to delete', required: true}),
Expand Down
13 changes: 6 additions & 7 deletions src/commands/config/context/use.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { Flags, Args } from '@oclif/core';
import Command from '../../../base';
import { setCurrentContext, CONTEXT_FILE_PATH } from '../../../models/Context';
import { Args } from '@oclif/core';
import Command from '../../../core/base';
import { setCurrentContext, CONTEXT_FILE_PATH } from '../../../core/models/Context';
import {
MissingContextFileError,
ContextFileWrongFormatError,
ContextFileEmptyError,
} from '../../../errors/context-error';
} from '../../../core/errors/context-error';
import { helpFlag } from '../../../core/flags/global.flags';

export default class ContextUse extends Command {
static description = 'Set a context as current';
static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

static args = {
'context-name': Args.string({description: 'name of the saved context', required: true}),
Expand Down
4 changes: 2 additions & 2 deletions src/commands/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Command from '../../base';
import {loadHelpClass} from '@oclif/core';
import Command from '../../core/base';
import { loadHelpClass } from '@oclif/core';

export default class Config extends Command {
static description = 'CLI config settings';
Expand Down
8 changes: 3 additions & 5 deletions src/commands/config/versions.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Flags } from '@oclif/core';
import Command from '../../base';
import Command from '../../core/base';
import { helpFlag } from '../../core/flags/global.flags';

export default class Versions extends Command {
static description = 'Show versions of AsyncAPI tools used';

static flags = {
help: Flags.help({ char: 'h' }),
};
static flags = helpFlag();

async run() {
const dependencies: string[] = [];
Expand Down
19 changes: 8 additions & 11 deletions src/commands/convert.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { promises as fPromises } from 'fs';
import { Flags, Args } from '@oclif/core';
import Command from '../base';
import { ValidationError } from '../errors/validation-error';
import { load } from '../models/SpecificationFile';
import { SpecificationFileNotFound } from '../errors/specification-file';
import { Args } from '@oclif/core';
import Command from '../core/base';
import { ValidationError } from '../core/errors/validation-error';
import { load } from '../core/models/SpecificationFile';
import { SpecificationFileNotFound } from '../core/errors/specification-file';
import { convert } from '@asyncapi/converter';
import type { ConvertVersion } from '@asyncapi/converter';
import { cyan, green } from 'picocolors';

// @ts-ignore
import specs from '@asyncapi/specs';
import { convertFlags } from '../core/flags/convert.flags';

const latestVersion = Object.keys(specs.schemas).pop() as string;

export default class Convert extends Command {
static description = 'Convert asyncapi documents older to newer versions';

static flags = {
help: Flags.help({ char: 'h' }),
output: Flags.string({ char: 'o', description: 'path to the file where the result is saved' }),
'target-version': Flags.string({ char: 't', description: 'asyncapi version to convert to', default: latestVersion })
};
static flags = convertFlags(latestVersion);

static args = {
'spec-file': Args.string({description: 'spec path, url, or context-name', required: false}),
Expand Down Expand Up @@ -71,6 +68,6 @@ export default class Convert extends Command {
} else {
this.error(err as Error);
}
}
}
}
}
50 changes: 11 additions & 39 deletions src/commands/diff.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,30 @@
/* eslint-disable sonarjs/no-duplicate-string */
import { Flags, Args } from '@oclif/core';
import { Args } from '@oclif/core';
import * as diff from '@asyncapi/diff';
import AsyncAPIDiff from '@asyncapi/diff/lib/asyncapidiff';
import { promises as fs } from 'fs';
import chalk from 'chalk';
import { load, Specification } from '../models/SpecificationFile';
import Command from '../base';
import { ValidationError } from '../errors/validation-error';
import { SpecificationFileNotFound } from '../errors/specification-file';
import { load, Specification } from '../core/models/SpecificationFile';
import Command from '../core/base';
import { ValidationError } from '../core/errors/validation-error';
import { SpecificationFileNotFound } from '../core/errors/specification-file';
import {
DiffBreakingChangeError,
DiffOverrideFileError,
DiffOverrideJSONError,
} from '../errors/diff-error';
import { specWatcher } from '../globals';
import { watchFlag } from '../flags';
import { validationFlags, parse, convertToOldAPI } from '../parser';
} from '../core/errors/diff-error';
import { specWatcher } from '../core/globals';
import { parse, convertToOldAPI } from '../core/parser';

import type { SpecWatcherParams } from '../globals';
import type { SpecWatcherParams } from '../core/globals';
import { diffFlags } from '../core/flags/diff.flags';

const { readFile } = fs;

export default class Diff extends Command {
static description = 'Find diff between two asyncapi files';

static flags = {
help: Flags.help({ char: 'h' }),
format: Flags.string({
char: 'f',
description: 'format of the output',
default: 'yaml',
options: ['json', 'yaml', 'yml', 'md'],
}),
type: Flags.string({
char: 't',
description: 'type of the output',
default: 'all',
options: ['breaking', 'non-breaking', 'unclassified', 'all'],
}),
markdownSubtype: Flags.string({
description: 'the format of changes made to AsyncAPI document. It works only when diff is generated using md type. For example, when you specify subtype as json, then diff information in markdown is dumped as json structure.',
default: undefined,
options: ['json', 'yaml', 'yml']
}),
overrides: Flags.string({
char: 'o',
description: 'path to JSON file containing the override properties',
}),
'no-error': Flags.boolean({
description: 'don\'t show error on breaking changes',
}),
watch: watchFlag(),
...validationFlags({ logDiagnostics: false }),
};
static flags = diffFlags();

static args = {
old: Args.string({description: 'old spec path, URL or context-name', required: true}),
Expand Down
Loading

0 comments on commit 26853d7

Please sign in to comment.