@supernovaio/cli
Version:
Supernova.io Command Line Interface
227 lines (225 loc) • 9.66 kB
JavaScript
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a8c4f73e-02e8-52a9-8859-155cc944878f")}catch(e){}}();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Flags } from "@oclif/core";
import { SentryTraced } from "@sentry/nestjs";
import pulsarCoreTypes from "@supernova-studio/pulsar-core";
import axios from "axios";
import * as fs from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";
import "colors";
import { z } from "zod";
import { SentryCommand } from "../types/index.js";
import { exportConfiguration } from "../utils/run-exporter/exporter-utils.js";
import { getWritableVersion } from "../utils/sdk.js";
const require = createRequire(import.meta.url);
const pulsarCoreProvider = require("@supernova-studio/pulsar-core");
const pulsarLanguageProvider = require("@supernova-studio/pulsar-language");
export class RunLocalExporter extends SentryCommand {
static aliases = ["run-local-exporter"];
static description = "Run local exporter package";
static examples = [
`$ @supernovaio/cli run-local-exporter \
--apiKey="[API_KEY]" \
--designSystemId="[DESIGN_SYSTEM_ID]" \
--themeId="[THEME_ID]" \
--brandId="[BRAND_ID]" \
--exporterDir="[./path/to/exporter/dir]" \
--outputDir="[./path/to/output/dir]" \
--allowOverridingOutput
`,
];
static flags = {
allowOverridingOutput: Flags.boolean({
default: false,
description: "When enabled, CLI will override output in the output directory if same files where present. When disabled, encountering the same file with throw an error.",
required: false,
}),
apiKey: Flags.string({ description: "API key to use for accessing Supernova instance", required: true }),
brandId: Flags.string({
description: "Brand to export. Will only be used when exporter has usesBrands: true, but then it is required to be provided",
required: false,
}),
designSystemId: Flags.string({ description: "Design System to export from", required: true }),
exporterDir: Flags.string({ description: "Path to exporter package", required: true }),
outputDir: Flags.string({
description: "Path to output folder. Must be empty, unless `forceClearOutputDir` is set",
required: true,
}),
proxyUrl: Flags.string({
description: "When set, CLI will use provided proxy URL for all requests",
hidden: true,
required: false,
}),
themeId: Flags.string({
description: "Theme to export. Will only be used when exporter has usesThemes: true, and is optional",
required: false,
}),
};
get commandId() {
return RunLocalExporter.id;
}
get configSchema() {
return z.object({});
}
async executeExporter(flags, versionId) {
const logger = new pulsarLanguageProvider.PLLogger();
const pulsarEngine = new pulsarCoreProvider.PCPulsar(pulsarCoreTypes.PCPulsarExporterMode.full, logger);
try {
await pulsarEngine.initiateWithLocalFolderURL(flags.exporterDir, pulsarCoreTypes.PCExporterEnvironment.ci);
const config = exportConfiguration({
apiKey: flags.apiKey,
brandId: flags.brandId,
dsId: flags.designSystemId,
environment: this.env,
exportPath: flags.exporterDir,
logger,
proxyUrl: flags.proxyUrl,
themeId: flags.themeId,
versionId,
});
const result = await pulsarEngine.executeExporter(config, false);
return {
logger,
result,
success: true,
};
}
catch (error) {
return {
logger,
result: error,
success: false,
};
}
}
async run() {
const { flags } = await this.parse(RunLocalExporter);
const { version } = await getWritableVersion(flags);
const result = await this.executeExporter(flags, version.id);
if (flags.log) {
this.logRun(result.logger);
}
if (result.success) {
await this.writeToBuildPath(result.result, flags);
this.log("Export finished successfully".green);
}
else {
this.error(`Export failed: ${result.result.message}`.red, {
code: "ERR_EXPORT_FAILED",
});
}
}
async downloadFileToMemory(fileUrl) {
const response = await axios({
method: "get",
responseType: "arraybuffer",
url: fileUrl,
});
return Buffer.from(response.data);
}
ensureDirectoryExists(filePath, forceLastFragmentIsDirectory = false) {
if (forceLastFragmentIsDirectory && !filePath.endsWith("/")) {
filePath += "/";
}
if (fs.existsSync(filePath)) {
return;
}
fs.mkdirSync(filePath, { recursive: true });
}
logRun(logger) {
for (const log of logger.logs) {
let message = log.message.trim();
if (message.startsWith('"')) {
message = message.slice(1);
}
if (message.endsWith('"')) {
message = message.slice(0, Math.max(0, message.length - 1));
}
console.log(`[user]`.gray + message.white);
}
}
async writeToBuildPath(result, flags) {
if (!fs.existsSync(flags.outputDir)) {
this.ensureDirectoryExists(flags.outputDir);
}
if (!flags.allowOverridingOutput) {
for (const file of result.emittedFiles) {
const destination = path.join(flags.outputDir, file.path);
if (fs.existsSync(destination)) {
throw new Error(`Exporter produced file for destination ${destination} but that file already exists. Enable --allowOverridingOutput option to allow overriding`);
}
}
}
const filesToWrite = [];
const processFile = async (file) => {
const filePath = path.join(flags.outputDir, ...file.path.split("/"));
const fileDirectory = path.dirname(filePath);
this.ensureDirectoryExists(fileDirectory);
switch (file.type) {
case "copy_file": {
const fileContent = fs.readFileSync(file.content);
filesToWrite.push({ content: fileContent, filePath });
break;
}
case "copy_file_remote": {
const fileContent = await this.downloadFileToMemory(file.content);
filesToWrite.push({ content: fileContent, filePath });
break;
}
case "string": {
filesToWrite.push({ content: file.content, filePath });
break;
}
}
};
const chunkSize = 4;
for (let i = 0; i < result.emittedFiles.length; i += chunkSize) {
const chunk = result.emittedFiles.slice(i, i + chunkSize);
await Promise.all(chunk.map(file => processFile(file)));
}
for (const { content, filePath } of filesToWrite) {
fs.writeFileSync(filePath, content);
}
}
}
__decorate([
SentryTraced(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, String]),
__metadata("design:returntype", Promise)
], RunLocalExporter.prototype, "executeExporter", null);
__decorate([
SentryTraced(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], RunLocalExporter.prototype, "run", null);
__decorate([
SentryTraced(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], RunLocalExporter.prototype, "downloadFileToMemory", null);
__decorate([
SentryTraced(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Boolean]),
__metadata("design:returntype", void 0)
], RunLocalExporter.prototype, "ensureDirectoryExists", null);
__decorate([
SentryTraced(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], RunLocalExporter.prototype, "writeToBuildPath", null);
//# sourceMappingURL=run-local-exporter.js.map
//# debugId=a8c4f73e-02e8-52a9-8859-155cc944878f