Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.idea
/.nyc_output
/dist
.tsbuildinfo
/dist/
/lib
/node_modules/
Expand Down
6 changes: 6 additions & 0 deletions scripts/fetch-asyncapi-example.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ const tidyUp = async () => {
};

(async () => {
const exampleJsonPath = path.join(EXAMPLE_DIRECTORY, 'examples.json');
if (fs.existsSync(exampleJsonPath) && !process.env.FORCE_FETCH_EXAMPLES) {
console.log('AsyncAPI spec examples already exists. Skipping download.');
return;
}

await fetchAsyncAPIExamplesFromExternalURL();
await unzipAsyncAPIExamples();
await buildCLIListFromExamples();
Expand Down
20 changes: 15 additions & 5 deletions src/apps/cli/commands/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { cyan } from 'picocolors';
import { proxyFlags } from '@cli/internal/flags/proxy.flags';
import specs from '@asyncapi/specs';
import { convertFlags } from '@cli/internal/flags/convert.flags';
import { ConversionService } from '@services/convert.service';
import type { ConversionService } from '@services/convert.service';
import { applyProxyToPath } from '@utils/proxy';

const latestVersion = Object.keys(specs.schemas).pop() as string;
Expand All @@ -17,7 +17,7 @@ const TARGET_VERSION_FLAG = 'target-version';
export default class Convert extends Command {
static description =
'Convert asyncapi documents older to newer versions or OpenAPI documents to AsyncAPI';
private conversionService = new ConversionService();
private _conversionService?: ConversionService;
static flags = {
...convertFlags(latestVersion),
...proxyFlags(),
Expand All @@ -30,6 +30,15 @@ export default class Convert extends Command {
}),
};

private async getConversionService(): Promise<ConversionService> {
if (!this._conversionService) {
const { ConversionService: cService } = await import('@services/convert.service');
this._conversionService = new cService();
}

return this._conversionService;
}

async run() {
const { args, flags } = await this.parse(Convert);
const filePath = applyProxyToPath(
Expand All @@ -50,7 +59,8 @@ export default class Convert extends Command {
perspective: flags['perspective'] as 'client' | 'server',
};

const result = await this.conversionService.convertDocument(
const cService = await this.getConversionService();
const result = await cService.convertDocument(
this.specFile,
conversionOptions,
);
Expand All @@ -62,11 +72,11 @@ export default class Convert extends Command {
this.metricsMetadata.conversion_result = result;

this.log(
this.conversionService.handleLogging(this.specFile, conversionOptions),
cService.handleLogging(this.specFile, conversionOptions),
);

if (flags['output']) {
await this.conversionService.handleOutput(
await cService.handleOutput(
flags['output'],
result.data.convertedDocument,
);
Expand Down
28 changes: 19 additions & 9 deletions src/apps/cli/commands/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ import {
ValidationOptions,
ValidationResult,
} from '@/interfaces';
import {
ValidationService,
ValidationStatus,
} from '@services/validation.service';
import type { ValidationService, } from '@services/validation.service';
import { applyProxyToPath } from '@utils/proxy';

export default class Validate extends Command {
static description = 'validate asyncapi file';
private validationService = new ValidationService();
private _validationService?: ValidationService;

static flags = {
...validateFlags(),
Expand Down Expand Up @@ -57,7 +54,8 @@ export default class Validate extends Command {
suppressAllWarnings: flags['suppressAllWarnings'],
};

const result = await this.validationService.validateDocument(
const vService = await this.getValidationService();
const result = await vService.validateDocument(
this.specFile,
validateOptions,
);
Expand All @@ -76,11 +74,21 @@ export default class Validate extends Command {
await this.handleDiagnostics(result, flags);
}

const { ValidationStatus } = await import('@services/validation.service');
if (result.data?.status === ValidationStatus.INVALID) {
process.exitCode = 1;
}
}

private async getValidationService(): Promise<ValidationService> {
if (!this._validationService) {
const { ValidationService: vService } = await import('@services/validation.service');
this._validationService = new vService();
}

return this._validationService;
}

private async handleDiagnostics(
result: ServiceResult<ValidationResult>,
flags: any,
Expand All @@ -89,10 +97,12 @@ export default class Validate extends Command {
const writeOutput = flags['save-output'];
const hasIssues =
(result.data?.diagnostics && result.data.diagnostics.length > 0) ?? false;
const { ValidationStatus } = await import('@services/validation.service');
const isFailSeverity = result.data?.status === ValidationStatus.INVALID;
const sourceString = this.specFile?.toSourceString() || '';

const governanceMessage = this.validationService.generateGovernanceMessage(
const vService = await this.getValidationService();
const governanceMessage = vService.generateGovernanceMessage(
sourceString,
hasIssues,
isFailSeverity,
Expand All @@ -104,15 +114,15 @@ export default class Validate extends Command {
this.log(governanceMessage);
}

const diagnosticsOutput = this.validationService.formatDiagnosticsOutput(
const diagnosticsOutput = vService.formatDiagnosticsOutput(
result.data?.diagnostics || [],
diagnosticsFormat,
flags['fail-severity'] ?? 'error',
);

if (writeOutput) {
const { success, error } =
await this.validationService.saveDiagnosticsToFile(
await vService.saveDiagnosticsToFile(
writeOutput,
diagnosticsFormat,
diagnosticsOutput,
Expand Down
66 changes: 38 additions & 28 deletions src/apps/cli/internal/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Sink,
StdOutSink,
} from '@smoya/asyncapi-adoption-metrics';
import { Parser } from '@asyncapi/parser';
import type { Parser } from '@asyncapi/parser';
import { Specification } from '@models/SpecificationFile';
import { join, resolve } from 'path';
import { existsSync } from 'fs-extra';
Expand All @@ -25,10 +25,19 @@ class DiscardSink implements Sink {

export default abstract class extends Command {
recorder = this.recorderFromEnv('asyncapi_adoption');
parser = new Parser();
private _parser?: Parser;
metricsMetadata: MetricMetadata = {};
specFile: Specification | undefined;

async getParser(): Promise<Parser> {
if (!this._parser) {
const { Parser: AsyncAPIParser } = await import('@asyncapi/parser');
this._parser = new AsyncAPIParser();
}

return this._parser;
}

async init(): Promise<void> {
await super.init();
const commandName: string = this.id || '';
Expand Down Expand Up @@ -57,7 +66,8 @@ export default abstract class extends Command {
) {
if (rawDocument !== undefined) {
try {
const { document } = await this.parser.parse(rawDocument);
const parser = await this.getParser();
const { document } = await parser.parse(rawDocument);
if (document !== undefined) {
// @ts-ignore
metadata = MetadataFromDocument(document, metadata);
Expand Down Expand Up @@ -150,32 +160,32 @@ export default abstract class extends Command {
process.env.CI !== 'true'
) {
switch (process.env.NODE_ENV) {
case 'development':
// NODE_ENV set to `development` in bin/run
if (!process.env.TEST) {
// Do not pollute stdout when running tests
sink = new StdOutSink();
}
break;
case 'production':
// NODE_ENV set to `production` in bin/run_bin, which is specified in 'bin' package.json section
sink = new NewRelicSink(
process.env.ASYNCAPI_METRICS_NEWRELIC_KEY ||
'eu01xx73a8521047150dd9414f6aedd2FFFFNRAL',
);

if (analyticsConfigFileContent.infoMessageShown === 'false') {
this.log(
'\nAsyncAPI anonymously tracks command executions to improve the specification and tools, ensuring no sensitive data reaches our servers. It aids in comprehending how AsyncAPI tools are used and adopted, facilitating ongoing improvements to our specifications and tools.\n\nTo disable tracking, please run the following command:\n asyncapi config analytics --disable\n\nOnce disabled, if you want to enable tracking back again then run:\n asyncapi config analytics --enable\n',
);
analyticsConfigFileContent.infoMessageShown = 'true';
await writeFile(
analyticsConfigFile,
JSON.stringify(analyticsConfigFileContent),
{ encoding: 'utf8' },
case 'development':
// NODE_ENV set to `development` in bin/run
if (!process.env.TEST) {
// Do not pollute stdout when running tests
sink = new StdOutSink();
}
break;
case 'production':
// NODE_ENV set to `production` in bin/run_bin, which is specified in 'bin' package.json section
sink = new NewRelicSink(
process.env.ASYNCAPI_METRICS_NEWRELIC_KEY ||
'eu01xx73a8521047150dd9414f6aedd2FFFFNRAL',
);
}
break;

if (analyticsConfigFileContent.infoMessageShown === 'false') {
this.log(
'\nAsyncAPI anonymously tracks command executions to improve the specification and tools, ensuring no sensitive data reaches our servers. It aids in comprehending how AsyncAPI tools are used and adopted, facilitating ongoing improvements to our specifications and tools.\n\nTo disable tracking, please run the following command:\n asyncapi config analytics --disable\n\nOnce disabled, if you want to enable tracking back again then run:\n asyncapi config analytics --enable\n',
);
analyticsConfigFileContent.infoMessageShown = 'true';
await writeFile(
analyticsConfigFile,
JSON.stringify(analyticsConfigFileContent),
{ encoding: 'utf8' },
);
}
break;
}
}

Expand Down
40 changes: 30 additions & 10 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
{
"compilerOptions": {
"outDir": "./lib",
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo",
"baseUrl": "./src",
"target": "es6",
"module": "commonjs",
"lib": [
"esnext",
],
"paths": {
"@/*": ["*"],
"@src/*": ["*"],
"@cli/*": ["apps/cli/*"],
"@api/*": ["apps/api/*"],
"@services/*": ["domains/services/*"],
"@models/*": ["domains/models/*"],
"@utils/*": ["utils/*"],
"@errors/*": ["errors/*"],
"@interfaces/*": ["interfaces/*"],
"@/*": [
"*"
],
"@src/*": [
"*"
],
"@cli/*": [
"apps/cli/*"
],
"@api/*": [
"apps/api/*"
],
"@services/*": [
"domains/services/*"
],
"@models/*": [
"domains/models/*"
],
"@utils/*": [
"utils/*"
],
"@errors/*": [
"errors/*"
],
"@interfaces/*": [
"interfaces/*"
],
},
"declaration": true,
"importHelpers": true,
Expand All @@ -34,4 +54,4 @@
"include": [
"src",
],
}
}
Loading