Skip to content

Commit

Permalink
added new command for asyncapi start preview
Browse files Browse the repository at this point in the history
  • Loading branch information
Lemeri123 committed Jan 19, 2025
1 parent 5635245 commit 950ce9b
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 7 deletions.
30 changes: 23 additions & 7 deletions src/commands/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ export default class Bundle extends Command {

this.metricsMetadata.files = AsyncAPIFiles.length;

const document = await bundle(AsyncAPIFiles,
{
base: flags.base,
baseDir: flags.baseDir,
xOrigin: flags.xOrigin,
}
);
const document = await this.bundleFiles(AsyncAPIFiles, {
base: flags.base,
baseDir: flags.baseDir,
xOrigin: flags.xOrigin,
});

await this.collectMetricsData(document);

Expand Down Expand Up @@ -65,6 +63,13 @@ export default class Bundle extends Command {
}
}

private async bundleFiles(
files: string[],
options: { base?: string; baseDir?: string; xOrigin?: boolean }
): Promise<Document> {
return await bundle(files, options);
}

private async collectMetricsData(document: Document) {
try {
// We collect the metadata from the final output so it contains all the files
Expand All @@ -75,4 +80,15 @@ export default class Bundle extends Command {
}
}
}

/**
* Expose a utility method to bundle and return the bundled document in memory.
* Useful for commands like `start preview`.
*/
public static async bundleInMemory(
files: string[],
options: { base?: string; baseDir?: string; xOrigin?: boolean }
): Promise<Document> {
return await bundle(files, options);
}
}
64 changes: 64 additions & 0 deletions src/commands/start/preview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// test/commands/start/preview.test.ts
import { expect, test } from '@oclif/test';
import { promises as fs } from 'fs';
import path from 'path';
import { bundleInMemory } from '../../../src/commands/bundle';
import { startPreview } from '../../../src/commands/start/preview'; //

const asyncAPISpecPath = './test/fixtures/spec/asyncapi.yaml';
const asyncAPIWithRefsPath = './test/fixtures/spec/asyncapi-with-refs.yaml';

async function setupTestSpecFiles() {
await fs.mkdir(path.dirname(asyncAPISpecPath), { recursive: true });
await fs.writeFile(
asyncAPISpecPath,
'asyncapi: "2.0.0"\ninfo:\n title: Test API\n version: "1.0.0"\n'
);
await fs.writeFile(
asyncAPIWithRefsPath,
'asyncapi: "2.0.0"\ninfo:\n title: Test API with Refs\n version: "1.0.0"\ncomponents:\n schemas:\n example: \n $ref: ./example-schema.yaml\n'
);
}

describe('start preview', () => {
before(async () => {
await setupTestSpecFiles();
});

after(async () => {
await fs.rm('./test/fixtures', { recursive: true, force: true });
});

test
.stdout()
.stderr()
.do(async () => {
const bundledDoc = await bundleInMemory([asyncAPISpecPath], {});
await startPreview(bundledDoc.string(), { readOnly: true });
})
.it('should start preview with a bundled AsyncAPI document', (ctx) => {
expect(ctx.stdout).to.contain('Preview started');
});

test
.stdout()
.stderr()
.do(async () => {
const bundledDoc = await bundleInMemory([asyncAPIWithRefsPath], {});
await startPreview(bundledDoc.string(), { readOnly: true });
})
.it('should handle references correctly during preview', (ctx) => {
expect(ctx.stdout).to.contain('Preview started');
});

test
.stderr()
.do(async () => {
try {
await startPreview('', { readOnly: true });
} catch (error) {
expect(error.message).to.contain('Invalid AsyncAPI document');
}
})
.it('should throw an error for invalid or empty AsyncAPI documents');
});
44 changes: 44 additions & 0 deletions src/commands/start/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Command } from '@oclif/core';
import chokidar from 'chokidar';
import { bundle } from '../bundler';
import { startStudio } from '../studio';
import path from 'path';
import fs from 'fs';

export default class StartPreview extends Command {
static description = 'Start a live preview of your AsyncAPI document with references resolved.';

static args = [
{ name: 'file', required: true, description: 'Path to the AsyncAPI file' },
];

async run() {
const { args } = await this.parse(StartPreview);

const filePath = path.resolve(args.file);
if (!fs.existsSync(filePath)) {
this.error(`File not found: ${filePath}`);
}

const bundleAndPreview = async () => {
try {
this.log('Bundling AsyncAPI file...');
const bundledDocument = await bundle(filePath);
this.log('Starting Studio in preview mode...');
await startStudio(bundledDocument, { readOnly: true });
} catch (error) {
this.error(`Error bundling AsyncAPI file: ${error.message}`);
}
};

await bundleAndPreview();

const watcher = chokidar.watch(filePath, { ignoreInitial: true });
watcher.on('change', async () => {
this.log('File changed. Reloading preview...');
await bundleAndPreview();
});

this.log('Watching for file changes. Press Ctrl+C to stop.');
}
}
9 changes: 9 additions & 0 deletions src/commands/studio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import open from 'open';

export async function startStudio(bundledDocument: string, options: { readOnly: boolean }) {
const studioUrl = `https://studio.asyncapi.com/?readOnly=${options.readOnly}&document=${encodeURIComponent(
bundledDocument
)}`;

await open(studioUrl);
}

0 comments on commit 950ce9b

Please sign in to comment.