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
169 changes: 114 additions & 55 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"connect-livereload": "^0.6.1",
"execa": "^9.6.0",
"express": "^4.17.1",
"extract-zip": "^2.0.1",
"file-type": "^15.0.0",
"form-data": "^4.0.2",
"fs-extra": "^11.3.0",
Expand All @@ -72,7 +73,6 @@
"tmp-promise": "^3.0.3",
"treeify": "^1.1.0",
"tslib": "^2.8.1",
"unzipper": "^0.12.3",
"uuid": "^11.1.0",
"yaml": "^2.8.0"
},
Expand Down
10 changes: 7 additions & 3 deletions src/controllers/portal/quickstart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { SDKClient } from "../../client-utils/sdk-client.js";
import {
createTempDirectory,
isValidUrl,
unzipFile,
getMessageInRedColor,
clearDirectory,
deleteFile
Expand All @@ -22,8 +21,13 @@ import { AuthorizationError, GetValidationParams } from "../../types/api/validat
import { metadataFileContent, staticPortalRepoUrl } 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";

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

Expand Down Expand Up @@ -110,10 +114,10 @@ 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 unzipFile(fs.createReadStream(specPath), 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
29 changes: 22 additions & 7 deletions src/infrastructure/zip-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "fs";
import archiver from "archiver";
import unzipper from "unzipper";
import extract from "extract-zip";
import { DirectoryPath } from "../types/file/directoryPath.js";
import { FilePath } from "../types/file/filePath.js";

Expand All @@ -19,12 +19,27 @@ export class ZipService {
});
}

async unArchive(sourceFile: FilePath, destinationDirectory: DirectoryPath): Promise<void> {
return new Promise((resolve, reject) => {
fs.createReadStream(sourceFile.toString())
.pipe(unzipper.Extract({ path: destinationDirectory.toString() }))
.on("close", () => resolve())
.on("error", (err) => reject(err));
public async unArchive(sourceFile: FilePath, destinationDirectory: DirectoryPath): Promise<void> {
const MAX_FILES = 100_000;
const MAX_SIZE = 1_000_000_000; // 1 GB
let fileCount = 0;
let totalSize = 0;

await extract(sourceFile.toString(), {
dir: destinationDirectory.toString(),
onEntry: function (entry) {
fileCount++;
if (fileCount > MAX_FILES) {
throw new Error("Reached max. file count");
}
// The uncompressedSize comes from the zip headers, so it might not be trustworthy.
// Alternatively, calculate the size from the readStream.
let entrySize = entry.uncompressedSize;
totalSize += entrySize;
if (totalSize > MAX_SIZE) {
throw new Error("Reached max. size");
}
}
});
}
}
14 changes: 0 additions & 14 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import fs from "fs";
import fsExtra from "fs-extra";
import os from "os";
import archiver from "archiver";
import unzipper from "unzipper";
import stripTags from "striptags";
import AdmZip from "adm-zip";
import colors from "picocolors";
Expand All @@ -13,19 +12,6 @@ import { PassThrough } from "stream";
import { loggers, ValidationMessages } from "../types/utils.js";
import { ApiValidationSummary } from "@apimatic/sdk";

export const unzipFile = (stream: NodeJS.ReadableStream, destination: string) => {
return new Promise((resolve, reject) => {
const extractStream = unzipper.Extract({ path: destination });

stream
.pipe(extractStream)
.on("error", (error: Error) => reject(new Error("Error during extraction: " + error.message)));

extractStream.on("close", () => resolve("Extracted"));
extractStream.on("error", (error: Error) => reject(new Error("Error during extraction: " + error.message)));
});
};

export const createTempDirectory = async () => {
return fs.mkdtempSync(path.join(os.tmpdir(), "apimatic-cli-"));
};
Expand Down