budibase/packages/cli/dist/plugins/index.js

200 lines
9.3 KiB
JavaScript

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Command_1 = require("../structures/Command");
const constants_1 = require("../constants");
const skeleton_1 = require("./skeleton");
const questions = __importStar(require("../questions"));
const fs_1 = __importDefault(require("fs"));
const types_1 = require("@budibase/types");
const backend_core_1 = require("@budibase/backend-core");
const exec_1 = require("../exec");
const path_1 = require("path");
const utils_1 = require("../utils");
const events_1 = require("../events");
const constants_2 = require("../constants");
const init_1 = require("../hosting/init");
const start_1 = require("../hosting/start");
const fp = require("find-free-port");
function checkInPlugin() {
if (!fs_1.default.existsSync("package.json")) {
throw new Error("Please run in a plugin directory - must contain package.json");
}
if (!fs_1.default.existsSync("schema.json")) {
throw new Error("Please run in a plugin directory - must contain schema.json");
}
}
function askAboutTopLevel(name) {
return __awaiter(this, void 0, void 0, function* () {
const files = fs_1.default.readdirSync(process.cwd());
// we are in an empty git repo, don't ask
if (files.find(file => file === ".git")) {
return false;
}
else {
console.log((0, utils_1.info)(`By default the plugin will be created in the directory "${name}"`));
console.log((0, utils_1.info)("if you are already in an empty directory, such as a new Git repo, you can disable this functionality."));
return questions.confirmation("Create top level directory?");
}
});
}
function init(opts) {
return __awaiter(this, void 0, void 0, function* () {
const type = opts["init"] || opts;
if (!type || !types_1.PLUGIN_TYPE_ARR.includes(type)) {
console.log((0, utils_1.error)("Please provide a type to init, either 'component' or 'datasource'."));
return;
}
console.log((0, utils_1.info)("Lets get some details about your new plugin:"));
const name = yield questions.string("Name", `budibase-${type}`);
if (fs_1.default.existsSync(name)) {
console.log((0, utils_1.error)("Directory by plugin name already exists, pick a new name."));
return;
}
const description = yield questions.string("Description", `An amazing Budibase ${type}!`);
const version = yield questions.string("Version", "1.0.0");
const topLevel = yield askAboutTopLevel(name);
// get the skeleton
console.log((0, utils_1.info)("Retrieving project..."));
yield (0, skeleton_1.getSkeleton)(type, name);
yield (0, skeleton_1.fleshOutSkeleton)(type, name, description, version);
console.log((0, utils_1.info)("Installing dependencies..."));
yield (0, exec_1.runPkgCommand)("install", (0, path_1.join)(process.cwd(), name));
// if no parent directory desired move to cwd
if (!topLevel) {
(0, utils_1.moveDirectory)(name, process.cwd());
console.log((0, utils_1.info)(`Plugin created in current directory.`));
}
else {
console.log((0, utils_1.info)(`Plugin created in directory "${name}"`));
}
(0, events_1.captureEvent)(constants_1.AnalyticsEvent.PluginInit, {
type,
name,
description,
version,
});
});
}
function verify() {
return __awaiter(this, void 0, void 0, function* () {
// will throw errors if not acceptable
checkInPlugin();
console.log((0, utils_1.info)("Verifying plugin..."));
const schema = fs_1.default.readFileSync("schema.json", "utf8");
const pkg = fs_1.default.readFileSync("package.json", "utf8");
let name, version;
try {
const schemaJson = JSON.parse(schema);
const pkgJson = JSON.parse(pkg);
if (!pkgJson.name || !pkgJson.version || !pkgJson.description) {
throw new Error("package.json is missing one of 'name', 'version' or 'description'.");
}
name = pkgJson.name;
version = pkgJson.version;
backend_core_1.plugins.validate(schemaJson);
return { name, version };
}
catch (err) {
if (err && err.message && err.message.includes("not valid JSON")) {
console.log((0, utils_1.error)(`schema.json is not valid JSON: ${err.message}`));
}
else {
console.log((0, utils_1.error)(`Invalid schema/package.json: ${err.message}`));
}
}
});
}
function build() {
return __awaiter(this, void 0, void 0, function* () {
const verified = yield verify();
if (!(verified === null || verified === void 0 ? void 0 : verified.name)) {
return;
}
console.log((0, utils_1.success)("Verified!"));
console.log((0, utils_1.info)("Building plugin..."));
yield (0, exec_1.runPkgCommand)("build");
const output = (0, path_1.join)("dist", `${verified.name}-${verified.version}.tar.gz`);
console.log((0, utils_1.success)(`Build complete - output in: ${output}`));
});
}
function watch() {
return __awaiter(this, void 0, void 0, function* () {
const verified = yield verify();
if (!(verified === null || verified === void 0 ? void 0 : verified.name)) {
return;
}
const output = (0, path_1.join)("dist", `${verified.name}-${verified.version}.tar.gz`);
console.log((0, utils_1.info)(`Watching - build in: ${output}`));
try {
yield (0, exec_1.runPkgCommand)("watch");
}
catch (err) {
// always errors when user escapes
console.log((0, utils_1.success)("Watch exited."));
}
});
}
function dev() {
return __awaiter(this, void 0, void 0, function* () {
const pluginDir = yield questions.string("Directory to watch", "./");
const [port] = yield fp(10000);
const password = "admin";
yield (0, init_1.init)({
init: constants_1.InitType.QUICK,
single: true,
watchPluginDir: pluginDir,
genUser: password,
port,
silent: true,
});
yield (0, start_1.start)();
console.log((0, utils_1.success)(`Configuration has been written to docker-compose.yaml`));
console.log((0, utils_1.success)("Development environment started successfully - connect at: ") +
(0, utils_1.info)(`http://localhost:${port}`));
console.log((0, utils_1.success)("Use the following credentials to login:"));
console.log((0, utils_1.success)("Email: ") + (0, utils_1.info)(constants_2.GENERATED_USER_EMAIL));
console.log((0, utils_1.success)("Password: ") + (0, utils_1.info)(password));
});
}
exports.default = new Command_1.Command(`${constants_1.CommandWord.PLUGIN}`)
.addHelp("Custom plugins for Budibase, init, build and verify your components and datasources with this tool.")
.addSubOption("--init [type]", "Init a new plugin project, with a type of either component or datasource.", init)
.addSubOption("--build", "Build your plugin, this will verify and produce a final tarball for your project.", build)
.addSubOption("--watch", "Automatically build any changes to your plugin.", watch)
.addSubOption("--dev", "Run a development environment which automatically watches the current directory.", dev);