Skip to content
Merged
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
25 changes: 0 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
"neverthrow": "^8.2.0",
"open": "^8.4.0",
"prettier": "^2.8.8",
"simple-git": "^3.27.0",
"striptags": "^3.2.0",
"tmp-promise": "^3.0.3",
"treeify": "^1.1.0",
Expand Down
1 change: 0 additions & 1 deletion src/config/env.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export const baseURL = "https://api.apimatic.io";
export const staticPortalRepoUrl = "https://github.com/apimatic/static-portal-workflow.git";
export const metadataFileContent = {
ImportSettings: {
AutoGenerateTestCases: false,
Expand Down
47 changes: 32 additions & 15 deletions src/controllers/portal/quickstart.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { simpleGit } from "simple-git";
import axios from "axios";
import * as path from "path";
import filetype from "file-type";
Expand All @@ -18,18 +17,20 @@ import {
} from "../../utils/utils.js";
import { getValidationSummary } from "../api/validate.js";
import { AuthorizationError, GetValidationParams } from "../../types/api/validate.js";
import { metadataFileContent, staticPortalRepoUrl } from "../../config/env.js";
import { metadataFileContent } from "../../config/env.js";
import { PortalQuickstartPrompts } from "../../prompts/portal/quickstart.js";
import { AuthenticationError } from "../../types/utils.js";
import { ZipService } from "../../infrastructure/zip-service.js";
import { FilePath } from "../../types/file/filePath.js";
import { DirectoryPath } from "../../types/file/directoryPath.js";
import { FileName } from "../../types/file/fileName.js";
import { withDirPath } from "../../infrastructure/tmp-extensions.js";
import { FileService } from "../../infrastructure/file-service.js";

export class PortalQuickstartController {
private readonly zipService = new ZipService();
private readonly specUrl =
"https://github.com/apimatic/static-portal-workflow/blob/master/spec/openapi.json";
private readonly fileService = new FileService();
private readonly specUrl = "https://github.com/apimatic/static-portal-workflow/blob/master/spec/openapi.json";

async isUserAuthenticated(configDir: string): Promise<boolean> {
const storedAuth = await getAuthInfo(configDir);
Expand Down Expand Up @@ -114,10 +115,13 @@ export class PortalQuickstartController {
}
} else {
specPath = path.normalize(specPath);
const fileType = await filetype.fromFile(specPath);
const fileType = await filetype.fromFile(specPath);

if (fileType?.ext === "zip") {
await this.zipService.unArchive(new FilePath(new DirectoryPath(path.dirname(specPath)), new FileName(path.basename(specPath))), new DirectoryPath(tempSpecDir));
await this.zipService.unArchive(
new FilePath(new DirectoryPath(path.dirname(specPath)), new FileName(path.basename(specPath))),
new DirectoryPath(tempSpecDir)
);
} else {
const destinationPath = path.join(tempSpecDir, path.basename(specPath));
await fsExtra.copy(specPath, destinationPath);
Expand Down Expand Up @@ -208,27 +212,41 @@ export class PortalQuickstartController {
}
}

private async downloadRepositoryFromGitHub(targetFolder: string): Promise<void> {
return await withDirPath(async (tempDirectory) => {
const zipUrl = `https://github.com/apimatic/static-portal-workflow/archive/refs/heads/master.zip`;
const response = await fetch(zipUrl);
const repositoryFolderName = "static-portal-workflow-master";

if (!response.ok) {
throw new Error(`Unable to setup your portal, please try again later.`);
}
const arrayBuffer = await response.arrayBuffer();
const tempZipPath = new FilePath(tempDirectory, new FileName("static-repo.zip"));
await this.fileService.writeBuffer(tempZipPath, Buffer.from(arrayBuffer));

await this.zipService.unArchive(tempZipPath, tempDirectory);

const extractedFolderPath = new DirectoryPath(tempDirectory.toString(), repositoryFolderName);
await this.fileService.copyDirectoryContents(extractedFolderPath, new DirectoryPath(targetFolder));
});
}

async setupBuildDirectory(
prompts: PortalQuickstartPrompts,
targetFolder: string,
specFile: SpecFile,
validationSummary: ApiValidationSummary,
languages: string[]
): Promise<void> {
const git = simpleGit({
timeout: {
block: 60 * 1000 // 1 minute timeout.
}
});

fsExtra.emptyDirSync(targetFolder);

try {
await git.clone(staticPortalRepoUrl, targetFolder);
await this.downloadRepositoryFromGitHub(targetFolder);
} catch (error) {
prompts.displayBuildDirectoryGenerationErrorMessage();
if (error instanceof Error) {
if (error.message.includes("timed out")) {
if (error.message.includes("timed out") || error.message.includes("timeout")) {
throw new Error(
getMessageInRedColor(
"The operation timed out while setting up the build directory. Please check your internet connection and try again."
Expand All @@ -246,7 +264,6 @@ export class PortalQuickstartController {
}
}

await clearDirectory(path.join(targetFolder, ".git"));
await clearDirectory(path.join(targetFolder, ".github"));

if (specFile.localPath && validationSummary.success) {
Expand Down
20 changes: 20 additions & 0 deletions src/infrastructure/file-service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from "fs";
import fsExtra from "fs-extra";
import * as path from "path";
import { FilePath } from "../types/file/filePath.js";
import { DirectoryPath } from "../types/file/directoryPath.js";
import { pipeline } from "stream";
Expand Down Expand Up @@ -38,6 +39,21 @@ export class FileService {
await fsExtra.emptyDir(dir.toString()); // removes everything inside, keeps the dir
}

public async copyDirectory(source: DirectoryPath, destination: DirectoryPath) {
await fsExtra.copy(source.toString(), destination.toString());
}

public async copyDirectoryContents(source: DirectoryPath, destination: DirectoryPath) {
const entries = await fsExtra.readdir(source.toString());
await Promise.all(
entries.map(async (entry) => {
const srcEntry = path.join(source.toString(), entry);
const destEntry = path.join(destination.toString(), entry);
await fsExtra.copy(srcEntry, destEntry);
})
);
}

public async deleteFile(filePath: FilePath): Promise<void> {
const exists = await this.fileExists(filePath);
if (exists) {
Expand All @@ -62,6 +78,10 @@ export class FileService {
await fsExtra.writeFile(filePath.toString(), contents, 'utf-8');
}

public async writeBuffer(filePath: FilePath, buffer: Buffer) {
await fsExtra.writeFile(filePath.toString(), buffer);
}

public async copy(source: FilePath, destination: FilePath) {
await fsExtra.copyFile(source.toString(), destination.toString());
}
Expand Down